Merge "msm: kgsl: Don't signal the timeline if its refcount is zero"
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
index c3c8212..cc4c3cc 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
@@ -233,8 +233,6 @@
 		    configuration registers for the Performance cluster.
 		    The array must contain exactly three elements.
 
-		    corresponding CPRh device.
-
 - qcom,perfcl-apcs-mem-acc-threshold-voltage
 	Usage:      optional
 	Value type: <u32>
@@ -245,6 +243,27 @@
 		    the MEM ACC threshold voltage specified for the
 		    corresponding CPRh device.
 
+- qcom,l3-memacc-level-vc-binX
+	Usage:      required
+	Value type: <prop-encoded-array>
+	Definition: Array which defines the NOM and TURBO VCs for the L3 clock
+		    on that BIN part.
+		    The array must contain exactly two elements.
+
+- qcom,pwrcl-memacc-level-vc-binX
+	Usage:      required
+	Value type: <prop-encoded-array>
+	Definition: Array which defines the NOM and TURBO VCs for the Power
+		    cluster clock on that BIN part.
+		    The array must contain exactly two elements.
+
+- qcom,perfcl-memacc-level-vc-binX
+	Usage:      required
+	Value type: <prop-encoded-array>
+	Definition: Array which defines the NOM and TURBO VCs for the
+		    Performance cluster clock on that BIN part.
+		    The array must contain exactly two elements.
+
 - qcom,apcs-cbc-addr
 	Usage:      required
 	Value type: <prop-encoded-array>
@@ -483,6 +502,18 @@
 			<  1881600000 0x404c1462 0x00004e4e 0x2 21 >,
 			<  1958400000 0x404c1566 0x00005252 0x3 22 >;
 
+		qcom,l3-memacc-level-vc-bin0 = <7 63>;
+		qcom,l3-memacc-level-vc-bin1 = <7 9>;
+		qcom,l3-memacc-level-vc-bin2 = <7 9>;
+
+		qcom,pwrcl-memacc-level-vc-bin0 = <12 63>;
+		qcom,pwrcl-memacc-level-vc-bin1 = <12 17>;
+		qcom,pwrcl-memacc-level-vc-bin2 = <12 17>;
+
+		qcom,perfcl-memacc-level-vc-bin0 = <12 18>;
+		qcom,perfcl-memacc-level-vc-bin1 = <12 18>;
+		qcom,perfcl-memacc-level-vc-bin2 = <12 18>;
+
 		qcom,up-timer =
 			<1000 1000 1000>;
 		qcom,down-timer =
diff --git a/Documentation/devicetree/bindings/arm/msm/qsee_ipc_irq_bridge.txt b/Documentation/devicetree/bindings/arm/msm/qsee_ipc_irq_bridge.txt
new file mode 100644
index 0000000..442ad52
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qsee_ipc_irq_bridge.txt
@@ -0,0 +1,30 @@
+Qualcomm Technologies, Inc. Secure Execution Environment IPC Interrupt Bridge
+
+[Root level node]
+Required properties:
+-compatible : should be "qcom,qsee-ipc-irq-bridge";
+
+[Second level nodes]
+qcom,qsee-ipc-irq-subsystem
+Required properties:
+-qcom,dev-name: the bridge device name
+-interrupt: IPC interrupt line from remote subsystem to QSEE
+-label : The name of this subsystem.
+
+Required properties if interrupt type is IRQ_TYPE_LEVEL_HIGH[4]:
+-qcom,rx-irq-clr : the register to clear the level triggered rx interrupt
+-qcom,rx-irq-clr-mask : the bitmask to clear the rx interrupt
+
+Example:
+
+	qcom,qsee_ipc_irq_bridge {
+		compatible = "qcom,qsee-ipc-irq-bridge";
+
+		qcom,qsee-ipc-irq-spss {
+			qcom,rx-irq-clr = <0x1d08008 0x4>;
+			qcom,rx-irq-clr-mask = <0x2>;
+			qcom,dev-name = "qsee_ipc_irq_spss";
+			interrupts = <0 349 4>;
+			label = "spss";
+		};
+	};
diff --git a/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt b/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt
index 231b8a3..37c48ad 100644
--- a/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt
@@ -2,7 +2,7 @@
 ------------------------------------------------------------------------
 
 Required properties :
-- compatible : must be "qcom,aop-qmp-clk"
+- compatible : must be "qcom,aop-qmp-clk-v1" or "qcom,aop-qmp-clk-v2".
 - #clock-cells : must contain 1
 - mboxes : list of QMP mailbox phandle and channel identifier tuples.
 - mbox-names: List of identifier strings for each mailbox channel.
@@ -10,7 +10,7 @@
 
 Example :
 	clock_qdss: qcom,aopclk {
-		compatible = "qcom,aop-qmp-clk";
+		compatible = "qcom,aop-qmp-clk-v1";
 		#clock-cells = <1>;
 		mboxes = <&qmp_aop 0>;
 		mbox-names = "qdss_clk";
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt
index f214c58..12676b7 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt
@@ -4,7 +4,9 @@
 Required properties :
 - compatible : shall contain only one of the following:
 		"qcom,gpucc-sdm845",
-		"qcom,gfxcc-sdm845"
+		"qcom,gpucc-sdm845-v2",
+		"qcom,gfxcc-sdm845",
+		"qcom,gfxcc-sdm845-v2"
 
 - reg : shall contain base register offset and size.
 - #clock-cells : shall contain 1.
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
index c8077cb..051b315 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
@@ -20,6 +20,8 @@
   - qcom,ce-hw-key : optional, indicates if the hardware supports use of HW KEY.
   - qcom,support-core-clk-only : optional, indicates if the HW supports single crypto core clk.
   - qcom,bsm-ee : optional, indicate the BAM EE value, changes from target to target. Default value is 1 if not specified.
+  - qcom,smmu-s1-bypass : Boolean flag to bypass SMMU stage 1 translation.
+  - iommus : A list of phandle and IOMMU specifier pairs that describe the IOMMU master interfaces of the device.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
index 3c8a79a..fa27198 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -40,6 +40,9 @@
 	required. For other targets such as fsm, they do not perform
 	bus scaling. It is not required for those targets.
 
+  - qcom,smmu-s1-bypass : Boolean flag to bypass SMMU stage 1 translation.
+  - iommus : A list of phandle and IOMMU specifier pairs that describe the IOMMU master interfaces of the device.
+
 Example:
 
         qcom,qcrypto@fd444000 {
diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
index cbe8378..32c31af 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
@@ -401,6 +401,24 @@
 					String that specifies the ctrl state for reading the panel status.
 					"dsi_lp_mode" = DSI low power mode
 					"dsi_hs_mode" = DSI high speed mode
+- qcom,mdss-dsi-lp1-command:		An optional byte stream to request low
+					power mode on a panel
+- qcom,mdss-dsi-lp1-command-mode:	String that specifies the ctrl state for
+					setting the panel power mode.
+					"dsi_lp_mode" = DSI low power mode
+					"dsi_hs_mode" = DSI high speed mode
+- qcom,mdss-dsi-lp2-command:		An optional byte stream to request ultra
+					low power mode on a panel
+- qcom,mdss-dsi-lp2-command-mode:	String that specifies the ctrl state for
+					setting the panel power mode.
+					"dsi_lp_mode" = DSI low power mode
+					"dsi_hs_mode" = DSI high speed mode
+- qcom,mdss-dsi-nolp-command:		An optional byte stream to disable low
+					power and ultra low power panel modes
+- qcom,mdss-dsi-nolp-command-mode:	String that specifies the ctrl state for
+					setting the panel power mode.
+					"dsi_lp_mode" = DSI low power mode
+					"dsi_hs_mode" = DSI high speed mode
 - qcom,mdss-dsi-panel-status-check-mode:Specifies the panel status check method for ESD recovery.
 					"bta_check" = Uses BTA to check the panel status
 					"reg_read" = Reads panel status register to check the panel status
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
index 790da12..c811c28 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
@@ -25,7 +25,46 @@
 - qcom,aux-en-gpio:			Specifies the aux-channel enable gpio.
 - qcom,aux-sel-gpio:		Specifies the aux-channel select gpio.
 - qcom,usbplug-cc-gpio:		Specifies the usbplug orientation gpio.
-- qcom,aux-cfg-settings:	An array that specifies the DP AUX configuration settings.
+- qcom,aux-cfg0-settings:		Specifies the DP AUX configuration 0 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg1-settings:		Specifies the DP AUX configuration 1 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg2-settings:		Specifies the DP AUX configuration 2 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg3-settings:		Specifies the DP AUX configuration 3 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg4-settings:		Specifies the DP AUX configuration 4 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg5-settings:		Specifies the DP AUX configuration 5 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg6-settings:		Specifies the DP AUX configuration 6 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg7-settings:		Specifies the DP AUX configuration 7 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg8-settings:		Specifies the DP AUX configuration 8 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
+- qcom,aux-cfg9-settings:		Specifies the DP AUX configuration 9 settings. The first
+					entry in this array corresponds to the register offset
+					within DP AUX, while the remaining entries indicate the
+					programmable values.
 - qcom,max-pclk-frequency-khz:	An integer specifying the max. pixel clock in KHz supported by Display Port.
 - qcom,dp-usbpd-detection:	Phandle for the PMI regulator node for USB PHY PD detection.
 - qcom,<type>-supply-entries:		A node that lists the elements of the supply used by the a particular "type" of DSI module. The module "types"
@@ -93,7 +132,16 @@
 
 		qcom,dp-usbpd-detection = <&pmi8998_pdphy>;
 
-		qcom,aux-cfg-settings = [00 13 04 00 0a 26 0a 03 bb 03];
+		qcom,aux-cfg0-settings = [1c 00];
+		qcom,aux-cfg1-settings = [20 13 23 1d];
+		qcom,aux-cfg2-settings = [24 00];
+		qcom,aux-cfg3-settings = [28 00];
+		qcom,aux-cfg4-settings = [2c 0a];
+		qcom,aux-cfg5-settings = [30 26];
+		qcom,aux-cfg6-settings = [34 0a];
+		qcom,aux-cfg7-settings = [38 03];
+		qcom,aux-cfg8-settings = [3c bb];
+		qcom,aux-cfg9-settings = [40 03];
 		qcom,max-pclk-frequency-khz = <593470>;
 		pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
 		pinctrl-0 = <&sde_dp_aux_active &sde_dp_usbplug_cc_active>;
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
index 3ad0986..641cc26 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
@@ -96,3 +96,7 @@
 					If ping pong split enabled, this time should not be higher
 					than two times the dsi link rate time.
 					If the property is not specified, then the default value is 14000 us.
+- qcom,dsi-phy-isolation-enabled:	A boolean property enables the phy isolation from dsi
+					controller. This must be enabled for debugging purpose
+					only with simulator panel. It should not be enabled for
+					normal DSI panels.
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 196f6f7..0f8dc27 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -96,6 +96,12 @@
 		  retention. No cache invalidation operations involving asid
 		  may be used.
 
+- qcom,deferred-regulator-disable-delay : The time delay for deferred regulator
+                  disable in ms. In case of unmap call, regulator is
+                  enabled/disabled. This may introduce additional delay. For
+                  clients who do not detach, it's not possible to keep regulator
+                  vote while smmu is attached. Type is <u32>.
+
 - clocks        : List of clocks to be used during SMMU register access. See
                   Documentation/devicetree/bindings/clock/clock-bindings.txt
                   for information about the format. For each clock specified
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
index 1e6aac5..42e97f7 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
@@ -78,6 +78,8 @@
 - qcom,lcd-psm-ctrl	: A boolean property to specify if PSM needs to be
 			  controlled dynamically when WLED module is enabled
 			  or disabled.
+- qcom,auto-calibration-enable : A boolean property which enables auto-calibration
+				 of the WLED sink configuration.
 
 Optional properties if 'qcom,disp-type-amoled' is mentioned in DT:
 - qcom,loop-comp-res-kohm	: control to select the compensation resistor in kohm. default is 320.
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-eeprom.txt b/Documentation/devicetree/bindings/media/video/msm-cam-eeprom.txt
new file mode 100644
index 0000000..933ad85
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-eeprom.txt
@@ -0,0 +1,438 @@
+* Qualcomm Technologies, Inc. MSM EEPROM
+
+EEPROM is an one time programmed(OTP) device that stores the calibration data
+use for camera sensor. It may either be integrated in the sensor module or in
+the sensor itself. As a result, the power, clock and GPIOs may be the same as
+the camera sensor. The following describes the page block map, power supply,
+clock, GPIO and power on sequence properties of the EEPROM device.
+
+=======================================================
+Required Node Structure if probe happens from userspace
+=======================================================
+The EEPROM device is described in one level of the device node.
+
+======================================
+First Level Node - CAM EEPROM device
+======================================
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,eeprom".
+
+- cell-index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: Register values.
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: Name of the regulator resources for EEPROM HW.
+
+- xxxx-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: Regulator reference corresponding to the names listed in
+		"regulator-names".
+
+- rgltr-cntrl-support
+  Usage: required
+  Value type: <bool>
+  Definition: This property specifies if the regulator control is supported
+		e.g. rgltr-min-voltage.
+
+- rgltr-min-voltage
+  Usage: required
+  Value type: <u32>
+  Definition: should contain minimum voltage level for regulators
+		mentioned in regulator-names property.
+
+- rgltr-max-voltage
+  Usage: required
+  Value type: <u32>
+  Definition: should contain maximum voltage level for regulators
+		mentioned in regulator-names property.
+
+- rgltr-load-current
+  Usage: required
+  Value type: <u32>
+  Definition: should contain the maximum current in microamps required for
+		the regulators mentioned in regulator-names property.
+
+- gpio-no-mux
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio mux type.
+
+- gpios
+  Usage: required
+  Value type: <phandle>
+  Definition: should specify the gpios to be used for the eeprom.
+
+- gpio-reset
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the reset gpio index.
+
+- gpio-standby
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the standby gpio index.
+
+- gpio-req-tbl-num
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio table index.
+
+- gpio-req-tbl-flags
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio functions.
+
+- gpio-req-tbl-label
+  Usage: required
+  Value type: <string>
+  Definition: should specify the gpio labels.
+
+- sensor-position
+  Usage: required
+  Value type: <u32>
+  Definition: should contain the mount angle of the camera sensor.
+
+- cci-master
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c master id to be used for this camera
+		sensor.
+
+- sensor-mode
+  Usage: required
+  Value type: <u32>
+  Definition: should contain sensor mode supported.
+
+- clock-names
+  Usage: required
+  Value type: <string>
+  Definition: List of clock names required for EEPROM HW.
+
+- clocks
+  Usage: required
+  Value type: <phandle>
+  Definition: List of clocks used for EEPROM HW.
+
+- clock-cntl-level
+  Usage: required
+  Value type: <string>
+  Definition: says what all different clock levels eeprom node has.
+
+- clock-rates
+  Usage: required
+  Value type: <u32>
+  Definition: List of clocks rates.
+
+Example:
+
+	eprom0: qcom,eeprom@0 {
+	        cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,eeprom";
+		cam_vdig-supply = <&pm8998_l5>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		regulator-names = "cam_vdig", "cam_vio";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1200000 0>;
+		rgltr-max-voltage = <1200000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
+		gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+			<&msmgpio 37 0>,
+			<&msmgpio 36 0>;
+		gpio-reset = <1>;
+		gpio-standby = <2>;
+		gpio-req-tbl-num = <0 1 2>;
+		gpio-req-tbl-flags = <1 0 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		sensor-position = <0>;
+		sensor-mode = <0>;
+		cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
+=======================================================
+Required Node Structure if probe happens from kernel
+=======================================================
+The EEPROM device is described in one level of the device node.
+
+======================================
+First Level Node - CAM EEPROM device
+======================================
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,eeprom".
+
+- cell-index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: Register values.
+
+- qcom,eeprom-name
+  Usage: required
+  Value type: <string>
+  Definition: Name of the EEPROM HW.
+
+- qcom,slave-addr
+  Usage: required
+  Value type: <u32>
+  Definition: Slave address of the EEPROM HW.
+
+- qcom,num-blocks
+  Usage: required
+  Value type: <u32>
+  Definition: Total block number that eeprom contains.
+
+- qcom,pageX
+  Usage: required
+  Value type: <u32>
+  Definition: List of values specifying page size, start address,
+		address type, data, data type, delay in ms.
+		size 0 stand for non-paged.
+
+- qcom,pollX
+  Usage: required
+  Value type: <u32>
+  Definition: List of values specifying poll size, poll reg address,
+		address type, data, data type, delay in ms.
+		size 0 stand for not used.
+
+- qcom,memX
+  Usage: required
+  Value type: <u32>
+  Definition: List of values specifying memory size, start address,
+		address type, data, data type, delay in ms.
+		size 0 stand for not used.
+
+- qcom,saddrX
+  Usage: required
+  Value type: <u32>
+  Definition: property should specify the slave address for block (%d).
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: Name of the regulator resources for EEPROM HW.
+
+- qcom,cmm-data-support
+  Usage: required
+  Value type: <u32>
+  Definition: Camera MultiModule data capability flag..
+
+- qcom,cmm-data-compressed
+  Usage: required
+  Value type: <u32>
+  Definition: Camera MultiModule data compression flag.
+
+- qcom,cmm-data-offset
+  Usage: required
+  Value type: <u32>
+  Definition: Camera MultiModule data start offset.
+
+- qcom,cmm-data-size
+  Usage: required
+  Value type: <u32>
+  Definition: Camera MultiModule data size.
+
+- qcom,cam-power-seq-type
+  Usage: required
+  Value type: <string>
+  Definition: should specify the power on sequence types.
+
+- qcom,cam-power-seq-val
+  Usage: required
+  Value type: <string>
+  Definition: should specify the power on sequence values.
+
+- qcom,cam-power-seq-cfg-val
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the power on sequence config values.
+
+- qcom,cam-power-seq-delay
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the power on sequence delay time in ms.
+
+- xxxx-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: Regulator reference corresponding to the names listed in
+		"regulator-names".
+
+- rgltr-cntrl-support
+  Usage: required
+  Value type: <bool>
+  Definition: This property specifies if the regulator control is supported
+		e.g. rgltr-min-voltage.
+
+- rgltr-min-voltage
+  Usage: required
+  Value type: <u32>
+  Definition: should contain minimum voltage level for regulators
+		mentioned in regulator-names property.
+
+- rgltr-max-voltage
+  Usage: required
+  Value type: <u32>
+  Definition: should contain maximum voltage level for regulators
+		mentioned in regulator-names property.
+
+- rgltr-load-current
+  Usage: required
+  Value type: <u32>
+  Definition: should contain the maximum current in microamps required for
+		the regulators mentioned in regulator-names property.
+
+- gpio-no-mux
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio mux type.
+
+- gpios
+  Usage: required
+  Value type: <phandle>
+  Definition: should specify the gpios to be used for the eeprom.
+
+- gpio-reset
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the reset gpio index.
+
+- gpio-standby
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the standby gpio index.
+
+- gpio-req-tbl-num
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio table index.
+
+- gpio-req-tbl-flags
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio functions.
+
+- gpio-req-tbl-label
+  Usage: required
+  Value type: <string>
+  Definition: should specify the gpio labels.
+
+- sensor-position
+  Usage: required
+  Value type: <u32>
+  Definition: should contain the mount angle of the camera sensor.
+
+- cci-master
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c master id to be used for this camera
+		sensor.
+
+- sensor-mode
+  Usage: required
+  Value type: <u32>
+  Definition: should contain sensor mode supported.
+
+- clock-cntl-level
+  Usage: required
+  Value type: <string>
+  Definition:  says what all different clock levels eeprom node has.
+
+- clock-names
+  Usage: required
+  Value type: <string>
+  Definition: List of clock names required for EEPROM HW.
+
+- clocks
+  Usage: required
+  Value type: <phandle>
+  Definition: List of clocks used for EEPROM HW.
+
+- clock-rates
+  Usage: required
+  Value type: <u32>
+  Definition: List of clocks rates.
+
+Example:
+
+	eeprom0: qcom,eeprom@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		qcom,eeprom-name = "msm_eeprom";
+		compatible = "qcom,eeprom";
+		qcom,slave-addr = <0x60>;
+		qcom,num-blocks = <2>;
+		qcom,page0 = <1 0x100 2 0x01 1 1>;
+		qcom,poll0 = <0 0x0 2 0 1 1>;
+		qcom,mem0 = <0 0x0 2 0 1 0>;
+		qcom,page1 = <1 0x0200 2 0x8 1 1>;
+		qcom,pageen1 = <1 0x0202 2 0x01 1 10>;
+		qcom,poll1 = <0 0x0 2 0 1 1>;
+		qcom,mem1 = <32 0x3000 2 0 1 0>;
+		qcom,saddr1 = <0x62>;
+		qcom,cmm-data-support;
+		qcom,cmm-data-compressed;
+		qcom,cmm-data-offset = <0>;
+		qcom,cmm-data-size = <0>;
+		qcom,cam-power-seq-type = "sensor_vreg",
+			"sensor_vreg", "sensor_clk",
+			"sensor_gpio", "sensor_gpio";
+		qcom,cam-power-seq-val = "cam_vdig",
+			"cam_vio", "sensor_cam_mclk",
+			"sensor_gpio_reset",
+			"sensor_gpio_standby";
+		qcom,cam-power-seq-cfg-val = <1 1 24000000 1 1>;
+		qcom,cam-power-seq-delay = <1 1 5 5 10>;
+		cam_vdig-supply = <&pm8998_l5>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		regulator-names = "cam_vdig", "cam_vio";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1200000 0>;
+		rgltr-max-voltage = <1200000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+			<&msmgpio 37 0>,
+			<&msmgpio 36 0>;
+		gpio-reset = <1>;
+		gpio-standby = <2>;
+		gpio-req-tbl-num = <0 1 2>;
+		gpio-req-tbl-flags = <1 0 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		sensor-position = <0>;
+		sensor-mode = <0>;
+		cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-cntl-level = "turbo";
+		clock-names = "cam_clk";
+		clock-rates = <24000000>;
+	};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-jpeg.txt b/Documentation/devicetree/bindings/media/video/msm-cam-jpeg.txt
new file mode 100644
index 0000000..a2ed98e
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-jpeg.txt
@@ -0,0 +1,187 @@
+* Qualcomm Technologies, Inc. MSM Camera JPEG
+
+The MSM camera JPEG devices are implemented multiple device nodes.
+The root JPEG device node has properties defined to hint the driver
+about the number of Encoder and DMA nodes available during the
+probe sequence. Each node has multiple properties defined
+for interrupts, clocks and regulators.
+
+=======================
+Required Node Structure
+=======================
+JPEG root interface node takes care of the handling account for number
+of Encoder and DMA devices present on the hardware.
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,cam-jpeg".
+
+- compat-hw-name
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,jpegenc" or "qcom,jpegdma".
+
+- num-jpeg-enc
+  Usage: required
+  Value type: <u32>
+  Definition: Number of supported Encoder HW blocks.
+
+- num-jpeg-dma
+  Usage: required
+  Value type: <u32>
+  Definition: Number of supported DMA HW blocks.
+
+Example:
+	qcom,cam-jpeg {
+		compatible = "qcom,cam-jpeg";
+		compat-hw-name = "qcom,jpegenc",
+			"qcom,jpegdma";
+		num-jpeg-enc = <1>;
+		num-jpeg-dma = <1>;
+		status = "ok";
+	};
+
+
+=======================
+Required Node Structure
+=======================
+Encoder/DMA Nodes provide interface for JPEG driver about
+the device register map, interrupt map, clocks and regulators.
+
+- cell-index
+  Usage: required
+  Value type: <u32>
+  Definition: Node instance number.
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,cam_jpeg_enc".
+
+- reg-names
+  Usage: optional
+  Value type: <string>
+  Definition: Name of the register resources.
+
+- reg
+  Usage: optional
+  Value type: <u32>
+  Definition: Register values.
+
+- reg-cam-base
+  Usage: optional
+  Value type: <u32>
+  Definition: Offset of the register space compared to
+              to Camera base register space.
+
+- interrupt-names
+  Usage: optional
+  Value type: <string>
+  Definition: Name of the interrupt.
+
+- interrupts
+  Usage: optional
+  Value type: <u32>
+  Definition: Interrupt associated with JPEG HW.
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: Name of the regulator resources for JPEG HW.
+
+- camss-vdd-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: Regulator reference corresponding to the names listed
+              in "regulator-names".
+
+- clock-names
+  Usage: required
+  Value type: <string>
+  Definition: List of clock names required for JPEG HW.
+
+- clocks
+  Usage: required
+  Value type: <phandle>
+  Definition: List of clocks used for JPEG HW.
+
+- clock-rates
+  Usage: required
+  Value type: <u32>
+  Definition: List of clocks rates.
+
+- src-clock-name
+  Usage: required
+  Value type: <string>
+  Definition: Source clock name.
+
+- clock-cntl-level
+  Usage: required
+  Value type: <string>
+  Definition: List of strings corresponds clock-rates levels.
+  Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo.
+
+Examples:
+	cam_jpeg_enc: qcom,jpegenc@ac4e000 {
+		cell-index = <0>;
+		compatible = "qcom,cam_jpeg_enc";
+		reg-names = "jpege_hw";
+		reg = <0xac4e000 0x4000>;
+		reg-cam-base = <0x4e000>;
+		interrupt-names = "jpeg";
+		interrupts = <0 474 0>;
+		regulator-names = "camss-vdd";
+		camss-vdd-supply = <&titan_top_gdsc>;
+		clock-names = "camera_ahb",
+			"camera_axi",
+			"soc_ahb_clk",
+			"cpas_ahb_clk",
+			"camnoc_axi_clk",
+			"jpegenc_clk_src",
+			"jpegenc_clk";
+		clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>,
+			<&clock_gcc GCC_CAMERA_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_JPEG_CLK_SRC>,
+			<&clock_camcc CAM_CC_JPEG_CLK>;
+
+		clock-rates = <0 0 0 0 0 600000000 0>;
+		src-clock-name = "jpegenc_clk_src";
+		clock-cntl-level = "nominal";
+		status = "ok";
+	};
+
+	cam_jpeg_dma: qcom,jpegdma@0xac52000{
+		cell-index = <0>;
+		compatible = "qcom,cam_jpeg_dma";
+		reg-names = "jpegdma_hw";
+		reg = <0xac52000 0x4000>;
+		reg-cam-base = <0x52000>;
+		interrupt-names = "jpegdma";
+		interrupts = <0 475 0>;
+		regulator-names = "camss-vdd";
+		camss-vdd-supply = <&titan_top_gdsc>;
+		clock-names = "camera_ahb",
+			"camera_axi",
+			"soc_ahb_clk",
+			"cpas_ahb_clk",
+			"camnoc_axi_clk",
+			"jpegdma_clk_src",
+			"jpegdma_clk";
+		clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>,
+			<&clock_gcc GCC_CAMERA_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_JPEG_CLK_SRC>,
+			<&clock_camcc CAM_CC_JPEG_CLK>;
+
+		clock-rates = <0 0 0 0 0 600000000 0>;
+		src-clock-name = "jpegdma_clk_src";
+		clock-cntl-level = "nominal";
+		status = "ok";
+	};
+
diff --git a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
new file mode 100644
index 0000000..d24314a
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
@@ -0,0 +1,126 @@
+* Qualcomm Technologies, Inc. MSM FLASH
+
+The MSM camera Flash driver provides the definitions for
+enabling and disabling LED Torch/Flash by requesting it to
+PMIC/I2C/GPIO based hardware. It provides the functions for
+the Client to control the Flash hardware.
+
+=======================================================
+Required Node Structure
+=======================================================
+The Flash device is described in one level of the device node.
+
+======================================
+First Level Node - CAM FLASH device
+======================================
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,camera-flash".
+
+- cell-index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: Register values.
+
+- flash-source
+  Usage: required
+  Value type: <phandle>
+  Definition: Should contain array of phandles to Flash source nodes.
+
+- torch-source
+  Usage: required
+  Value type: <phandle>
+  Definition: Should contain array of phandles to torch source nodes.
+
+- switch-source
+  Usage: Optional
+  Value type: <phandle>
+  Definition: Should contain phandle to switch source nodes.
+
+- slave-id
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain i2c slave address, device id address
+		      and expected id read value.
+
+- cci-master
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain i2c master id to be used for this camera
+              flash.
+
+- max-current
+  Usage: optional
+  Value type: <u32>
+  Definition: Max current in mA supported by flash
+
+- max-duration
+  Usage: optional
+  Value type: <u32>
+  Definition: Max duration in ms flash can glow.
+
+- gpios
+  Usage: optional
+  Value type: <u32>
+  Definition: should specify the gpios to be used for the flash.
+
+- gpio-req-tbl-num
+  Usage: optional
+  Value type: <u32>
+  Definition: should specify the gpio table index.
+
+- gpio-req-tbl-flags
+  Usage: optional
+  Value type: <u32>
+  Definition: should specify the gpio functions.
+
+- gpio-req-tbl-label
+  Usage: optional
+  Value type: <u32>
+  Definition: should specify the gpio labels.
+
+- gpio-flash-reset
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by flash's "flash reset" pin.
+
+- gpio-flash-en
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by flash's "flash enable" pin.
+
+- gpio-flash-now
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by flash's "flash now" pin.
+
+Example:
+
+led_flash_rear: qcom,camera-flash@0 {
+		reg = <0x00 0x00>;
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+		torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+		switch-source = <&pmi8998_switch0>;
+        qcom,slave-id = <0x00 0x00 0x0011>;
+		qcom,cci-master = <0>;
+		gpios = <&msmgpio 23 0>,
+			<&msmgpio 24 0>;
+			<&msmgpio 25 0>;
+		qcom,gpio-flash-reset = <0>;
+		qcom,gpio-flash-en = <0>;
+		qcom,gpio-flash-now = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <0 0>;
+		qcom,gpio-req-tbl-label = "FLASH_EN",
+			"FLASH_NOW";
+		qcom,max-current = <1500>;
+		qcom,max-duration = <1200>;
+	};
diff --git a/Documentation/devicetree/bindings/msm_hdcp/msm_hdcp.txt b/Documentation/devicetree/bindings/msm_hdcp/msm_hdcp.txt
new file mode 100644
index 0000000..8d5f55d
--- /dev/null
+++ b/Documentation/devicetree/bindings/msm_hdcp/msm_hdcp.txt
@@ -0,0 +1,14 @@
+MSM HDCP driver
+
+Standalone driver managing HDCP related communications
+between TZ and HLOS for MSM chipset.
+
+Required properties:
+
+compatible = "qcom,msm-hdcp";
+
+Example:
+
+qcom_msmhdcp: qcom,msm_hdcp {
+       compatible = "qcom,msm-hdcp";
+};
diff --git a/Documentation/devicetree/bindings/platform/msm/msm_tspp.txt b/Documentation/devicetree/bindings/platform/msm/msm_tspp.txt
index 072f920..b4ce7cb 100644
--- a/Documentation/devicetree/bindings/platform/msm/msm_tspp.txt
+++ b/Documentation/devicetree/bindings/platform/msm/msm_tspp.txt
@@ -23,6 +23,8 @@
 - qcom, msm_bus,num_paths: The paths for source and destination ports
 - qcom, msm_bus,vectors: Vectors for bus topology.
 - pinctrl-names: Names for the TSIF mode configuration to specify which TSIF interface is active.
+- qcom,smmu-s1-bypass : Boolean flag to bypass SMMU stage 1 translation.
+- iommus : A list of phandle and IOMMU specifier pairs that describe the IOMMU master interfaces of the device.
 
 Example:
 
@@ -75,4 +77,7 @@
                         &tsif0_sync_active
                         &tsif1_signals_active
                         &tsif1_sync_active>;            /* dual-tsif-mode2 */
+
+		qcom,smmu-s1-bypass;
+		iommus = <&apps_smmu 0x20 0x0f>;
         };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
index 0123682..d0d878b 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -385,6 +385,11 @@
 		    property "qcom,slope-limit-temp-threshold" to make dynamic
 		    slope limit adjustment functional.
 
+- qcom,fg-bmd-en-delay-ms
+	Usage:      optional
+	Value type: <u32>
+	Definition: The delay in ms for FG to enable BMD after reading RID.
+
 ==========================================================
 Second Level Nodes - Peripherals managed by FG Gen3 driver
 ==========================================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
index 441d771..05fa6e4 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
@@ -85,21 +85,6 @@
 		maximum charge current in mA for each thermal
 		level.
 
-- qcom,step-soc-thresholds
-  Usage:      optional
-  Value type: Array of <u32>
-  Definition: Array of SOC threshold values, size of 4. This should be a
-		flat array that denotes the percentage ranging from 0 to 100.
-		If the array is not present, step charging is disabled.
-
-- qcom,step-current-deltas
-  Usage:      optional
-  Value type: Array of <s32>
-  Definition: Array of delta values for charging current, size of 5, with
-		FCC as base.  This should be a flat array that denotes the
-		offset of charging current in uA, from -3100000 to 3200000.
-		If the array is not present, step charging is disabled.
-
 - io-channels
   Usage:      optional
   Value type: List of <phandle u32>
@@ -182,6 +167,22 @@
   Definition: Specifies the deglitch interval for OTG detection.
 		If the value is not present, 50 msec is used as default.
 
+- qcom,step-charging-enable
+  Usage:      optional
+  Value type: bool
+  Definition: Boolean flag which when present enables step-charging.
+
+- qcom,wd-bark-time-secs
+  Usage:      optional
+  Value type: <u32>
+  Definition: WD bark-timeout in seconds. The possible values are
+		16, 32, 64, 128. If not defined it defaults to 64.
+
+- qcom,sw-jeita-enable
+  Usage:      optional
+  Value type: bool
+  Definition: Boolean flag which when present enables sw compensation for jeita
+
 =============================================
 Second Level Nodes - SMB2 Charger Peripherals
 =============================================
@@ -217,9 +218,6 @@
 
 	dpdm-supply = <&qusb_phy0>;
 
-	qcom,step-soc-thresholds = <60 70 80 90>;
-	qcom,step-current-deltas = <500000 250000 150000 0 (-150000)>;
-
 	qcom,chgr@1000 {
 		reg = <0x1000 0x100>;
 		interrupts =    <0x2 0x10 0x0 IRQ_TYPE_NONE>,
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index 9b1b9ee..b0db996 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -12,6 +12,7 @@
 
 Optional properties:
 - qcom,fastrpc-glink:	Flag to use glink instead of smd for IPC
+- qcom,rpc-latency-us:	FastRPC QoS latency vote
 
 Optional subnodes:
 - qcom,msm_fastrpc_compute_cb :	Child nodes representing the compute context
@@ -26,6 +27,7 @@
 	qcom,msm_fastrpc {
 		compatible = "qcom,msm-fastrpc-adsp";
 		qcom,fastrpc-glink;
+		qcom,rpc-latency-us = <2343>;
 
 		qcom,msm_fastrpc_compute_cb_1 {
 			compatible = "qcom,msm-fastrpc-compute-cb";
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index c116e42..4d05e50 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -329,7 +329,7 @@
  - qcom,gpio-connect                       Gpio that connects to parent
                                            interrupt controller
 
-* audio-ext-clk
+* audio-ext-clk-up
 
 Required properties:
 
@@ -2579,3 +2579,256 @@
 		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
 					  "SpkrLeft", "SpkrRight";
 	};
+
+* SDM670 ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,sdm670-asoc-snd"
+- qcom,model : The user-visible name of this sound card.
+- qcom,msm-hs-micbias-type : This property is used to recognize the headset
+  micbias type, internal or external.
+- qcom,msm-mbhc-hphl-swh: This property is used to distinguish headset HPHL
+switch type on target typically the switch type will be normally open or
+normally close, value for this property 0 for normally close and 1 for
+normally open.
+-  qcom,msm-mbhc-gnd-swh: This property is used to distinguish headset GND
+switch type on target typically the switch type will be normally open or
+normally close, value for this property 0 for normally close and 1 for
+normally open.
+- qcom,audio-routing : A list of the connections between audio components.
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+
+Optional properties:
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,msm-micbias1-ext-cap : Boolean. Enable micbias1 external
+capacitor mode.
+- qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external
+capacitor mode.
+- qcom,wsa-disable : Boolean. Disables WSA speaker dailinks from sound node.
+- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa.
+- qcom,msm-mclk-freq : This property is used to inform machine driver about
+mclk frequency needs to be configured for internal and external PA.
+- asoc-platform: This is phandle list containing the references to platform device
+		 nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+		       the platform names should match to that of the phandle order
+		       given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+	    that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+		  cpu dai names should match to that of the phandle order given.
+- asoc-codec: This is phandle list containing the references to codec dai device
+	nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+	codec dai names should match to that of the phandle order given
+	in "asoc-codec".
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+- qcom,cdc-pdm-gpios : phandle for pdm gpios.
+- qcom,cdc-comp-gpios : phandle for compander gpios.
+- qcom,cdc-dmic-gpios : phandle for Digital mic clk and data gpios.
+- qcom,cdc-sdw-gpios : phandle for soundwire clk and data gpios.
+- qcom,msm-mbhc-moist-cfg: This property is used to set moisture detection
+		threshold values for different codecs. First parameter is V(voltage)
+		second one is i(current), third one is r (resistance). Depending on the
+		codec set corresponding element in array and set others to 0.
+
+Example:
+	 sound {
+		compatible = "qcom,sdm670-asoc-snd";
+		qcom,model = "sdm670-snd-card";
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-hs-micbias-type = "internal";
+		qcom,msm-micbias1-ext-cap;
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"SPK_RX_BIAS", "MCLK",
+			"INT_LDO_H", "MCLK",
+			"MIC BIAS External", "Handset Mic",
+			"MIC BIAS Internal2", "Headset Mic",
+			"MIC BIAS External", "Secondary Mic",
+			"AMIC1", "MIC BIAS External",
+			"AMIC2", "MIC BIAS Internal2",
+			"AMIC3", "MIC BIAS External";
+		qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>;
+		qcom,cdc-pdm-gpios = <&cdc_pdm_gpios>;
+		qcom,cdc-comp-gpios = <&cdc_comp_gpios>;
+		qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+		qcom,cdc-sdw-gpios = <&cdc_sdw_gpios>;
+		asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&lpa>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe",
+				"msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa";
+		asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>,
+				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+				<&bt_sco_rx>, <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>,
+				<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>,
+				<&incall_music_2_rx>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+				"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+				"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+				"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+				"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+				<&wsa881x_213>, <&wsa881x_214>;
+		qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
+					  "SpkrRight", "SpkrLeft";
+	};
+
+* SDM670 ASoC Slimbus Machine driver
+
+Required properties:
+- compatible : "qcom,sdm670-asoc-snd-tasha" for tasha codec,
+		"qcom,sdm670-asoc-snd-tavil" for tavil codec.
+- qcom,model : The user-visible name of this sound card.
+- qcom,msm-mclk-freq : MCLK frequency value for external codec
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios. Say we have 2^N combinations for N GPIOs,
+this would list all the 2^N combinations.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor. This can be sometimes same as qcom, pinctrl-names i.e with 2^N
+combinations or will have less incase if some combination is not supported.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+- qcom,audio-routing : A list of the connections between audio components.
+- asoc-platform: This is phandle list containing the references to platform device
+		 nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+		       the platform names should match to that of the phandle order
+		       given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+	    that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+		  cpu dai names should match to that of the phandle order given
+		  in "asoc-cpu". The cpu names are in the form of "%s.%d" form,
+		  where the id (%d) field represents the back-end AFE port id that
+		  this CPU dai is associated with.
+- asoc-codec: This is phandle list containing the references to codec dai device
+	      nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+		    codec dai names should match to that of the phandle order given
+		    in "asoc-codec".
+Optional properties:
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- clock-names : clock name defined for external clock.
+- clocks : external clock defined for codec clock.
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+
+Example:
+
+	sound-9335 {
+	compatible = "qcom,sdm670-asoc-snd-tasha";
+	qcom,model = "sdm670-tasha-snd-card";
+
+	qcom,audio-routing =
+		"RX_BIAS", "MCLK",
+		"LDO_H", "MCLK",
+		"AIF4 MAD", "MCLK",
+		"ultrasound amp", "LINEOUT1",
+		"ultrasound amp", "LINEOUT3",
+		"AMIC1", "MIC BIAS1 Internal1",
+		"MIC BIAS1 Internal1", "Handset Mic",
+		"AMIC2", "MIC BIAS2 External",
+		"MIC BIAS2 External", "Headset Mic",
+		"AMIC3", "MIC BIAS2 External",
+		"MIC BIAS2 External", "ANCRight Headset Mic",
+		"AMIC4", "MIC BIAS2 External",
+		"MIC BIAS2 External", "ANCLeft Headset Mic",
+		"DMIC1", "MIC BIAS1 External",
+		"MIC BIAS1 External", "Digital Mic1",
+		"DMIC2", "MIC BIAS1 External",
+		"MIC BIAS1 External", "Digital Mic2",
+		"DMIC3", "MIC BIAS3 External",
+		"MIC BIAS3 External", "Digital Mic3",
+		"DMIC4", "MIC BIAS3 External",
+		"MIC BIAS3 External", "Digital Mic4",
+		"DMIC5", "MIC BIAS4 External",
+		"MIC BIAS4 External", "Digital Mic5",
+		"DMIC6", "MIC BIAS4 External",
+		"MIC BIAS4 External", "Digital Mic6";
+
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-gpios =
+			"slim",
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"slim_act",
+			"us_eu_gpio_act",
+			"slim_us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"slim_act",
+			"us_eu_gpio_act",
+			"slim_us_eu_gpio_act";
+		pinctrl-0 = <&cdc_slim_lines_sus &cross_conn_det_sus>;
+		pinctrl-1 = <&cdc_slim_lines_act &cross_conn_det_sus>;
+		pinctrl-2 = <&cdc_slim_lines_sus &cross_conn_det_act>;
+		pinctrl-3 = <&cdc_slim_lines_act &cross_conn_det_act>;
+		qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>;
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "msm-voip-dsp",
+				"msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless",
+				"msm-pcm-afe", "msm-lsm-client",
+				"msm-pcm-routing", "msm-cpe-lsm",
+				"msm-compr-dsp";
+		asoc-cpu = <&dai_hdmi>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+				<&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
+				<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
+				<&afe_proxy_tx>, <&incall_record_rx>,
+				<&incall_record_tx>, <&incall_music_rx>,
+				<&incall_music_2_rx>, <&sb_5_rx>;
+		asoc-cpu-names = "msm-dai-q6-hdmi.8",
+				"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+				"msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
+				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+				"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+				"msm-dai-q6-dev.16395", "msm-dai-q6-dev.224",
+				"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+				"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+				"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+				"msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+				<&wsa881x_213>, <&wsa881x_214>;
+		qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
+					  "SpkrRight", "SpkrLeft";
+	};
diff --git a/Documentation/devicetree/bindings/sound/wcd_codec.txt b/Documentation/devicetree/bindings/sound/wcd_codec.txt
index 0df9417..c848ab5 100644
--- a/Documentation/devicetree/bindings/sound/wcd_codec.txt
+++ b/Documentation/devicetree/bindings/sound/wcd_codec.txt
@@ -12,7 +12,6 @@
  - qcom,wcd-rst-gpio-node: Phandle reference to the DT node having codec reset gpio
                         configuration. If this property is not defined, it is
                         expected to atleast define "qcom,cdc-reset-gpio" property.
-
  - cdc-vdd-buck-supply: phandle of buck supply's regulator device tree node.
  - qcom,cdc-vdd-buck-voltage: buck supply's voltage level min and max in mV.
  - qcom,cdc-vdd-buck-current: buck supply's max current in mA.
@@ -142,6 +141,11 @@
  - clock-names : clock name defined for external clock.
  - clocks : external clock defined for codec clock.
 
+ - qcom,has-buck-vsel-gpio:  Boolean property to select if WCD_BUCK has VSEL
+			controlled by GPIO.
+ - qcom,buck-vsel-gpio-node: Phandle reference to the DT node having wcd buck
+			VSEL gpio configuration.
+
 Example:
 
 taiko_codec {
diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
index 8bead0d..be50d45 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
@@ -31,12 +31,29 @@
 	Definition: Should specify the cluster affinity this hardware
 			corresponds to.
 
+- isens_vref-supply:
+	Usage: optional
+	Value type: <phandle>
+	Definition: Should specify the phandle of the vref regulator used by
+			the isens hardware. This active only regulator will be
+			enabled by LMH DCVSh.
+
+- isens-vref-settings:
+	Usage: optional
+	Value type: <u32 array>
+	Definition: Should specify the min voltage(uV), max voltage(uV) and
+			max load(uA) for the isens vref regulator. This
+			property is valid only if there is valid entry for
+			isens_vref-supply.
+
 Example:
 
 	lmh_dcvs0: qcom,limits-dcvs@0 {
 		compatible = "qcom,msm-hw-limits";
 		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
 		qcom,affinity = <0>;
+		isens_vref-supply = <&pm8998_l1_ao>;
+		isens-vref-settings = <880000 880000 36000>;
 	};
 
 	CPU0: cpu@0 {
diff --git a/Documentation/devicetree/bindings/thermal/regulator-cdev.txt b/Documentation/devicetree/bindings/thermal/regulator-cdev.txt
new file mode 100644
index 0000000..7c9abe2
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/regulator-cdev.txt
@@ -0,0 +1,38 @@
+Regulator cooling device.
+
+The regulator cooling device, will be used to place a voltage floor
+restriction on a rail.
+
+Properties:
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: shall be "qcom,regulator-cooling-device"
+
+- cdev-supply:
+	Usage: required
+	Value type: <phandle>
+	Definition: phandle to the regulator to which the cooling device will
+			place a floor mitigation.
+
+- regulator-levels:
+	Usage: required
+	Value type: <U32 array>
+	Definition: Array of regulator voltages the cooling device should
+			use to place a floor restriction. The voltages should
+			be specified in descending order.
+
+- #cooling-cells: Must be 2. Please refer to
+			<devicetree/bindings/thermal/thermal.txt> for more
+			details.
+
+Example:
+
+	mv_cdev: mx-cdev-lvl {
+		compatible = "qcom,regulator-cooling-device";
+		cdev-supply = <&regulator-cdev-supply>;
+		regulator-levels = <RPMH_REGULATOR_LEVEL_NOM
+			RPMH_REGULATOR_LEVEL_OFF>;
+		#cooling-cells = <2>;
+	};
diff --git a/Makefile b/Makefile
index 04b3557..5894331 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 38
+SUBLEVEL = 40
 EXTRAVERSION =
 NAME = Roaring Lionus
 
@@ -565,7 +565,7 @@
 
 # Objects we will link into vmlinux / subdirs we need to visit
 init-y		:= init/
-drivers-y	:= drivers/ sound/ firmware/
+drivers-y	:= drivers/ sound/ firmware/ techpack/
 net-y		:= net/
 libs-y		:= lib/
 core-y		:= usr/
@@ -633,6 +633,9 @@
 
 KBUILD_CFLAGS	+= $(call cc-option,-fno-delete-null-pointer-checks,)
 KBUILD_CFLAGS	+= $(call cc-disable-warning,frame-address,)
+KBUILD_CFLAGS	+= $(call cc-disable-warning, format-truncation)
+KBUILD_CFLAGS	+= $(call cc-disable-warning, format-overflow)
+KBUILD_CFLAGS	+= $(call cc-disable-warning, int-in-bool-context)
 
 ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
 KBUILD_CFLAGS	+= $(call cc-option,-ffunction-sections,)
@@ -1152,6 +1155,7 @@
 	  $(error Headers not exportable for the $(SRCARCH) architecture))
 	$(Q)$(MAKE) $(hdr-inst)=include/uapi
 	$(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst)
+	$(Q)$(MAKE) $(hdr-inst)=techpack
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
@@ -1161,6 +1165,7 @@
 headers_check: headers_install
 	$(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
 	$(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
+	$(Q)$(MAKE) $(hdr-inst)=techpack HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Kernel selftest
diff --git a/arch/Kconfig b/arch/Kconfig
index 659bdd0..babac73 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -218,6 +218,12 @@
 config GENERIC_IDLE_POLL_SETUP
        bool
 
+config ARCH_HAS_FORTIFY_SOURCE
+	bool
+	help
+	  An architecture should select this when it can successfully
+	  build and run with CONFIG_FORTIFY_SOURCE.
+
 # Select if arch init_task initializer is different to init/init_task.c
 config ARCH_INIT_TASK
        bool
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index f2a4063..45a0fdc 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -294,6 +294,11 @@
 		};
 	};
 
+	qcom,ipa_fws {
+		compatible = "qcom,pil-tz-generic";
+		qcom,pas-id = <0xf>;
+		qcom,firmware-name = "ipa_fws";
+	};
 };
 
 #include "sdxpoorwills-regulator.dtsi"
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 88bd16c..23d4056 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -189,7 +189,6 @@
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
-CONFIG_HVC_DCC=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index ee4a723..8e349ce 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -178,6 +178,8 @@
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
+extern void __dma_map_area(const void *addr, size_t size, int dir);
+extern void __dma_unmap_area(const void *addr, size_t size, int dir);
 extern void dmac_inv_range(const void *, const void *);
 extern void dmac_clean_range(const void *, const void *);
 extern void dmac_flush_range(const void *, const void *);
diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index b4e74af..74643f5 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -8,6 +8,7 @@
 #include <linux/dma-debug.h>
 #include <linux/kmemcheck.h>
 #include <linux/kref.h>
+#include <linux/dma-mapping-fast.h>
 
 struct dma_iommu_mapping {
 	/* iommu specific data */
@@ -22,6 +23,8 @@
 
 	spinlock_t		lock;
 	struct kref		kref;
+
+	struct dma_fast_smmu_mapping *fast;
 };
 
 #ifdef CONFIG_ARM_DMA_USE_IOMMU
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index d2315ff..f13ae15 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -112,12 +112,8 @@
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE	(TASK_SIZE / 3 * 2)
+/* This is the base location for PIE (ET_DYN with INTERP) loads. */
+#define ELF_ET_DYN_BASE		0x400000UL
 
 /* When the program starts, a1 contains a pointer to a function to be 
    registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index d14f310..f7c75dc 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -157,6 +157,11 @@
 #define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
 #define dmac_inv_range			__glue(_CACHE, _dma_inv_range)
 #define dmac_clean_range		__glue(_CACHE, _dma_clean_range)
+#define dmac_map_area			__glue(_CACHE, _dma_map_area)
+#define dmac_unmap_area			__glue(_CACHE, _dma_unmap_area)
+
+#define __dma_map_area			dmac_map_area
+#define __dma_unmap_area		dmac_unmap_area
 #endif
 
 #endif
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 441063f..cb2c9f4 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -29,6 +29,7 @@
 #include <linux/sizes.h>
 #include <linux/cma.h>
 #include <linux/msm_dma_iommu_mapping.h>
+#include <linux/dma-mapping-fast.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
@@ -50,6 +51,8 @@
 	pgprot_t prot;
 	const void *caller;
 	bool want_vaddr;
+	bool skip_cpu_sync;
+	bool skip_zeroing;
 	int coherent_flag;
 };
 
@@ -113,6 +116,21 @@
 static void __dma_page_dev_to_cpu(struct page *, unsigned long,
 		size_t, enum dma_data_direction);
 
+static void *
+__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
+		const void *caller);
+
+static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn);
+
+static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot);
+
+static void *arm_dma_remap(struct device *dev, void *cpu_addr,
+			dma_addr_t handle, size_t size,
+			unsigned long attrs);
+
+static void arm_dma_unremap(struct device *dev, void *remapped_addr,
+				size_t size);
+
 /**
  * arm_dma_map_page - map a portion of a page for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -194,6 +212,8 @@
 	.sync_single_for_device	= arm_dma_sync_single_for_device,
 	.sync_sg_for_cpu	= arm_dma_sync_sg_for_cpu,
 	.sync_sg_for_device	= arm_dma_sync_sg_for_device,
+	.remap			= arm_dma_remap,
+	.unremap		= arm_dma_unremap,
 };
 EXPORT_SYMBOL(arm_dma_ops);
 
@@ -276,7 +296,8 @@
 	return mask;
 }
 
-static void __dma_clear_buffer(struct page *page, size_t size, int coherent_flag)
+static void __dma_clear_buffer(struct page *page, size_t size,
+					bool skip_zeroing, int coherent_flag)
 {
 	/*
 	 * Ensure that the allocated pages are zeroed, and that any data
@@ -287,7 +308,8 @@
 		phys_addr_t end = base + size;
 		while (size > 0) {
 			void *ptr = kmap_atomic(page);
-			memset(ptr, 0, PAGE_SIZE);
+			if (!skip_zeroing)
+				memset(ptr, 0, PAGE_SIZE);
 			if (coherent_flag != COHERENT)
 				dmac_flush_range(ptr, ptr + PAGE_SIZE);
 			kunmap_atomic(ptr);
@@ -298,7 +320,8 @@
 			outer_flush_range(base, end);
 	} else {
 		void *ptr = page_address(page);
-		memset(ptr, 0, size);
+		if (!skip_zeroing)
+			memset(ptr, 0, size);
 		if (coherent_flag != COHERENT) {
 			dmac_flush_range(ptr, ptr + size);
 			outer_flush_range(__pa(ptr), __pa(ptr) + size);
@@ -327,7 +350,7 @@
 	for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++)
 		__free_page(p);
 
-	__dma_clear_buffer(page, size, coherent_flag);
+	__dma_clear_buffer(page, size, false, coherent_flag);
 
 	return page;
 }
@@ -350,6 +373,7 @@
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
 				     pgprot_t prot, struct page **ret_page,
 				     const void *caller, bool want_vaddr,
+				     bool skip_cpu_sync, bool skip_zeroing,
 				     int coherent_flag);
 
 static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
@@ -369,10 +393,10 @@
 			prot, caller);
 }
 
-static void __dma_free_remap(void *cpu_addr, size_t size)
+static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn)
 {
 	dma_common_free_remap(cpu_addr, size,
-			VM_ARM_DMA_CONSISTENT | VM_USERMAP, false);
+			VM_ARM_DMA_CONSISTENT | VM_USERMAP, no_warn);
 }
 
 #define DEFAULT_DMA_COHERENT_POOL_SIZE	SZ_256K
@@ -421,7 +445,8 @@
 	 */
 	if (dev_get_cma_area(NULL))
 		ptr = __alloc_from_contiguous(NULL, atomic_pool_size, prot,
-				      &page, atomic_pool_init, true, NORMAL);
+				      &page, atomic_pool_init, true, false,
+				      false, NORMAL);
 	else
 		ptr = __alloc_remap_buffer(NULL, atomic_pool_size, gfp, prot,
 					   &page, atomic_pool_init, true);
@@ -520,21 +545,39 @@
 	return 0;
 }
 
-static void __dma_remap(struct page *page, size_t size, pgprot_t prot)
+static int __dma_clear_pte(pte_t *pte, pgtable_t token, unsigned long addr,
+			    void *data)
+{
+	pte_clear(&init_mm, addr, pte);
+	return 0;
+}
+
+static void __dma_remap(struct page *page, size_t size, pgprot_t prot,
+			bool want_vaddr)
 {
 	unsigned long start = (unsigned long) page_address(page);
 	unsigned end = start + size;
+	int (*func)(pte_t *pte, pgtable_t token, unsigned long addr,
+			    void *data);
 
-	apply_to_page_range(&init_mm, start, size, __dma_update_pte, &prot);
+	if (!want_vaddr)
+		func = __dma_clear_pte;
+	else
+		func = __dma_update_pte;
+
+	apply_to_page_range(&init_mm, start, size, func, &prot);
+	mb(); /*Ensure pte's are updated */
 	flush_tlb_kernel_range(start, end);
 }
 
+
+#define NO_KERNEL_MAPPING_DUMMY	0x2222
 static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
 				 pgprot_t prot, struct page **ret_page,
 				 const void *caller, bool want_vaddr)
 {
 	struct page *page;
-	void *ptr = NULL;
+	void *ptr = (void *)NO_KERNEL_MAPPING_DUMMY;
 	/*
 	 * __alloc_remap_buffer is only called when the device is
 	 * non-coherent
@@ -595,6 +638,7 @@
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
 				     pgprot_t prot, struct page **ret_page,
 				     const void *caller, bool want_vaddr,
+				     bool skip_cpu_sync, bool skip_zeroing,
 				     int coherent_flag)
 {
 	unsigned long order = get_order(size);
@@ -606,23 +650,37 @@
 	if (!page)
 		return NULL;
 
-	__dma_clear_buffer(page, size, coherent_flag);
-
-	if (!want_vaddr)
-		goto out;
+	/*
+	 * skip completely if we neither need to zero nor sync.
+	 */
+	if (!(skip_cpu_sync  && skip_zeroing))
+		__dma_clear_buffer(page, size, skip_zeroing, coherent_flag);
 
 	if (PageHighMem(page)) {
-		ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot, caller);
-		if (!ptr) {
-			dma_release_from_contiguous(dev, page, count);
-			return NULL;
+		if (!want_vaddr) {
+			/*
+			 * Something non-NULL needs to be returned here. Give
+			 * back a dummy address that is unmapped to catch
+			 * clients trying to use the address incorrectly
+			 */
+			ptr = (void *)NO_KERNEL_MAPPING_DUMMY;
+
+			/* also flush out the stale highmem mappings */
+			kmap_flush_unused();
+			kmap_atomic_flush_unused();
+		} else {
+			ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot,
+						caller);
+			if (!ptr) {
+				dma_release_from_contiguous(dev, page, count);
+				return NULL;
+			}
 		}
 	} else {
-		__dma_remap(page, size, prot);
+		__dma_remap(page, size, prot, want_vaddr);
 		ptr = page_address(page);
 	}
 
- out:
 	*ret_page = page;
 	return ptr;
 }
@@ -630,12 +688,10 @@
 static void __free_from_contiguous(struct device *dev, struct page *page,
 				   void *cpu_addr, size_t size, bool want_vaddr)
 {
-	if (want_vaddr) {
-		if (PageHighMem(page))
-			__dma_free_remap(cpu_addr, size);
-		else
-			__dma_remap(page, size, PAGE_KERNEL);
-	}
+	if (PageHighMem(page))
+		__dma_free_remap(cpu_addr, size, true);
+	else
+		__dma_remap(page, size, PAGE_KERNEL, true);
 	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
@@ -656,10 +712,11 @@
 #define __get_dma_pgprot(attrs, prot)				__pgprot(0)
 #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv)	NULL
 #define __alloc_from_pool(size, ret_page)			NULL
-#define __alloc_from_contiguous(dev, size, prot, ret, c, wv, coherent_flag)	NULL
+#define __alloc_from_contiguous(dev, size, prot, ret, c, \
+					wv, scs, sz, coherent_flag) NULL
 #define __free_from_pool(cpu_addr, size)			do { } while (0)
 #define __free_from_contiguous(dev, page, cpu_addr, size, wv)	do { } while (0)
-#define __dma_free_remap(cpu_addr, size)			do { } while (0)
+#define __dma_free_remap(cpu_addr, size, w)			do { } while (0)
 
 #endif	/* CONFIG_MMU */
 
@@ -698,7 +755,8 @@
 {
 	return __alloc_from_contiguous(args->dev, args->size, args->prot,
 				       ret_page, args->caller,
-				       args->want_vaddr, args->coherent_flag);
+				       args->want_vaddr, args->skip_cpu_sync,
+				       args->skip_zeroing, args->coherent_flag);
 }
 
 static void cma_allocator_free(struct arm_dma_free_args *args)
@@ -739,7 +797,7 @@
 static void remap_allocator_free(struct arm_dma_free_args *args)
 {
 	if (args->want_vaddr)
-		__dma_free_remap(args->cpu_addr, args->size);
+		__dma_free_remap(args->cpu_addr, args->size, false);
 
 	__dma_free_buffer(args->page, args->size);
 }
@@ -765,6 +823,8 @@
 		.prot = prot,
 		.caller = caller,
 		.want_vaddr = ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0),
+		.skip_cpu_sync = (attrs & DMA_ATTR_SKIP_CPU_SYNC),
+		.skip_zeroing = (attrs & DMA_ATTR_SKIP_ZEROING),
 		.coherent_flag = is_coherent ? COHERENT : NORMAL,
 	};
 
@@ -826,7 +886,7 @@
 		kfree(buf);
 	}
 
-	return args.want_vaddr ? addr : page;
+	return  addr;
 }
 
 /*
@@ -874,6 +934,38 @@
 	return ret;
 }
 
+static void *arm_dma_remap(struct device *dev, void *cpu_addr,
+			dma_addr_t handle, size_t size,
+			unsigned long attrs)
+{
+	void *ptr;
+	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
+	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
+	unsigned long offset = handle & ~PAGE_MASK;
+
+	size = PAGE_ALIGN(size + offset);
+	ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot,
+			__builtin_return_address(0));
+	return ptr ? ptr + offset : ptr;
+}
+
+static void arm_dma_unremap(struct device *dev, void *remapped_addr,
+				size_t size)
+{
+	unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
+	struct vm_struct *area;
+
+	remapped_addr = (void *)((unsigned long)remapped_addr & PAGE_MASK);
+
+	area = find_vm_area(remapped_addr);
+	if (!area || (area->flags & flags) != flags) {
+		WARN(1, "trying to free invalid coherent area: %p\n",
+			remapped_addr);
+		return;
+	}
+
+	vunmap(remapped_addr);
+}
 /*
  * Create userspace mapping for the DMA-coherent memory.
  */
@@ -1298,7 +1390,7 @@
 		if (!page)
 			goto error;
 
-		__dma_clear_buffer(page, size, coherent_flag);
+		__dma_clear_buffer(page, size, false, coherent_flag);
 
 		for (i = 0; i < count; i++)
 			pages[i] = page + i;
@@ -1348,7 +1440,8 @@
 				pages[i + j] = pages[i] + j;
 		}
 
-		__dma_clear_buffer(pages[i], PAGE_SIZE << order, coherent_flag);
+		__dma_clear_buffer(pages[i], PAGE_SIZE << order,
+						false, coherent_flag);
 		i += 1 << order;
 		count -= 1 << order;
 	}
@@ -2287,12 +2380,21 @@
 			    struct dma_iommu_mapping *mapping)
 {
 	int err;
+	int s1_bypass = 0;
+	int is_fast = 0;
+
+	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
+	if (is_fast)
+		return fast_smmu_attach_device(dev, mapping);
 
 	err = __arm_iommu_attach_device(dev, mapping);
 	if (err)
 		return err;
 
-	set_dma_ops(dev, &iommu_ops);
+	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS,
+					&s1_bypass);
+	if (!s1_bypass)
+		set_dma_ops(dev, &iommu_ops);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
@@ -2300,6 +2402,7 @@
 static void __arm_iommu_detach_device(struct device *dev)
 {
 	struct dma_iommu_mapping *mapping;
+	int is_fast;
 
 	mapping = to_dma_iommu_mapping(dev);
 	if (!mapping) {
@@ -2309,6 +2412,9 @@
 
 	if (msm_dma_unmap_all_for_dev(dev))
 		dev_warn(dev, "IOMMU detach with outstanding mappings\n");
+	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
+	if (is_fast)
+		return fast_smmu_detach_device(dev, mapping);
 
 	iommu_detach_device(mapping->domain, dev);
 	kref_put(&mapping->kref, release_iommu_mapping);
@@ -2326,8 +2432,21 @@
  */
 void arm_iommu_detach_device(struct device *dev)
 {
+	struct dma_iommu_mapping *mapping;
+	int s1_bypass = 0;
+
+	mapping = to_dma_iommu_mapping(dev);
+	if (!mapping) {
+		dev_warn(dev, "Not attached\n");
+		return;
+	}
+
 	__arm_iommu_detach_device(dev);
-	set_dma_ops(dev, NULL);
+
+	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS,
+					&s1_bypass);
+	if (!s1_bypass)
+		set_dma_ops(dev, NULL);
 }
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
diff --git a/arch/arm/mm/dma.h b/arch/arm/mm/dma.h
index 70ea6852..29c54f7 100644
--- a/arch/arm/mm/dma.h
+++ b/arch/arm/mm/dma.h
@@ -4,9 +4,6 @@
 #include <asm/glue-cache.h>
 
 #ifndef MULTI_CACHE
-#define dmac_map_area			__glue(_CACHE,_dma_map_area)
-#define dmac_unmap_area 		__glue(_CACHE,_dma_unmap_area)
-
 /*
  * These are private to the dma-mapping API.  Do not use directly.
  * Their sole purpose is to ensure that data held in the cache
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 842c38a..b5f9be7 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -9,6 +9,7 @@
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
 	select ARCH_HAS_ELF_RANDOMIZE
+	select ARCH_HAS_FORTIFY_SOURCE
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select ARCH_HAS_GIGANTIC_PAGE
 	select ARCH_HAS_KCOV
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index dae2f9f..f96fba6 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -116,6 +116,8 @@
 	select PINCTRL
 	select SOC_BUS
 	select PM_OPP
+	select MFD_CORE
+	select SND_SOC_COMPRESS
 	help
 	  This enables support for the ARMv8 based Qualcomm chipsets.
 
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index e9bd587..49a5d8c 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -75,14 +75,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 14
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 11
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 10
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	soc {
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 20288fe..ee7f735 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -12,7 +12,9 @@
 		sdm845-v2-qrd-overlay.dtbo \
 		sdm845-4k-panel-mtp-overlay.dtbo \
 		sdm845-4k-panel-cdp-overlay.dtbo \
-		sdm845-4k-panel-qrd-overlay.dtbo
+		sdm845-4k-panel-qrd-overlay.dtbo \
+		sdm845-interposer-sdm670-cdp-overlay.dtbo \
+		sdm845-interposer-sdm670-mtp-overlay.dtbo
 
 sdm845-cdp-overlay.dtbo-base := sdm845.dtb
 sdm845-mtp-overlay.dtbo-base := sdm845.dtb
@@ -23,6 +25,8 @@
 sdm845-4k-panel-mtp-overlay.dtbo-base := sdm845.dtb
 sdm845-4k-panel-cdp-overlay.dtbo-base := sdm845.dtb
 sdm845-4k-panel-qrd-overlay.dtbo-base := sdm845.dtb
+sdm845-interposer-sdm670-cdp-overlay.dtbo-base := sdm845-interposer-sdm670.dtb
+sdm845-interposer-sdm670-mtp-overlay.dtbo-base := sdm845-interposer-sdm670.dtb
 else
 dtb-$(CONFIG_ARCH_SDM845) += sdm845-sim.dtb \
 	sdm845-rumi.dtb \
@@ -35,7 +39,9 @@
 	sdm845-v2-qrd.dtb \
 	sdm845-4k-panel-mtp.dtb \
 	sdm845-4k-panel-cdp.dtb \
-	sdm845-4k-panel-qrd.dtb
+	sdm845-4k-panel-qrd.dtb \
+	sdm845-interposer-sdm670-mtp.dtb \
+	sdm845-interposer-sdm670-cdp.dtb
 endif
 
 dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi
index 44b817e..0ca1175 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi
@@ -15,22 +15,10 @@
 		qcom,mdss-dsi-panel-name =
 			"nt35597 cmd mode dsi truly panel with DSC";
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1440>;
-		qcom,mdss-dsi-panel-height = <2560>;
-		qcom,mdss-dsi-h-front-porch = <100>;
-		qcom,mdss-dsi-h-back-porch = <32>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <8>;
-		qcom,mdss-dsi-v-front-porch = <10>;
-		qcom,mdss-dsi-v-pulse-width = <2>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-pan-physical-width-dimension = <74>;
+		qcom,mdss-pan-physical-height-dimension = <131>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-color-order = "rgb_swap_rgb";
 		qcom,mdss-dsi-underflow-color = <0xff>;
@@ -40,171 +28,6 @@
 			17000 15500 30000 8000 3000>;
 		qcom,mdss-dsi-panel-peak-brightness = <4200000>;
 		qcom,mdss-dsi-panel-blackness-level = <3230>;
-		qcom,mdss-dsi-on-command = [
-			/* CMD2_P0 */
-			15 01 00 00 00 00 02 ff 20
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 01
-			15 01 00 00 00 00 02 01 55
-			15 01 00 00 00 00 02 02 45
-			15 01 00 00 00 00 02 05 40
-			15 01 00 00 00 00 02 06 19
-			15 01 00 00 00 00 02 07 1e
-			15 01 00 00 00 00 02 0b 73
-			15 01 00 00 00 00 02 0c 73
-			15 01 00 00 00 00 02 0e b0
-			15 01 00 00 00 00 02 0f ae
-			15 01 00 00 00 00 02 11 b8
-			15 01 00 00 00 00 02 13 00
-			15 01 00 00 00 00 02 58 80
-			15 01 00 00 00 00 02 59 01
-			15 01 00 00 00 00 02 5a 00
-			15 01 00 00 00 00 02 5b 01
-			15 01 00 00 00 00 02 5c 80
-			15 01 00 00 00 00 02 5d 81
-			15 01 00 00 00 00 02 5e 00
-			15 01 00 00 00 00 02 5f 01
-			15 01 00 00 00 00 02 72 31
-			15 01 00 00 00 00 02 68 03
-			/* CMD2_P4 */
-			15 01 00 00 00 00 02 ff 24
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 1c
-			15 01 00 00 00 00 02 01 0b
-			15 01 00 00 00 00 02 02 0c
-			15 01 00 00 00 00 02 03 01
-			15 01 00 00 00 00 02 04 0f
-			15 01 00 00 00 00 02 05 10
-			15 01 00 00 00 00 02 06 10
-			15 01 00 00 00 00 02 07 10
-			15 01 00 00 00 00 02 08 89
-			15 01 00 00 00 00 02 09 8a
-			15 01 00 00 00 00 02 0a 13
-			15 01 00 00 00 00 02 0b 13
-			15 01 00 00 00 00 02 0c 15
-			15 01 00 00 00 00 02 0d 15
-			15 01 00 00 00 00 02 0e 17
-			15 01 00 00 00 00 02 0f 17
-			15 01 00 00 00 00 02 10 1c
-			15 01 00 00 00 00 02 11 0b
-			15 01 00 00 00 00 02 12 0c
-			15 01 00 00 00 00 02 13 01
-			15 01 00 00 00 00 02 14 0f
-			15 01 00 00 00 00 02 15 10
-			15 01 00 00 00 00 02 16 10
-			15 01 00 00 00 00 02 17 10
-			15 01 00 00 00 00 02 18 89
-			15 01 00 00 00 00 02 19 8a
-			15 01 00 00 00 00 02 1a 13
-			15 01 00 00 00 00 02 1b 13
-			15 01 00 00 00 00 02 1c 15
-			15 01 00 00 00 00 02 1d 15
-			15 01 00 00 00 00 02 1e 17
-			15 01 00 00 00 00 02 1f 17
-			/* STV */
-			15 01 00 00 00 00 02 20 40
-			15 01 00 00 00 00 02 21 01
-			15 01 00 00 00 00 02 22 00
-			15 01 00 00 00 00 02 23 40
-			15 01 00 00 00 00 02 24 40
-			15 01 00 00 00 00 02 25 6d
-			15 01 00 00 00 00 02 26 40
-			15 01 00 00 00 00 02 27 40
-			/* Vend */
-			15 01 00 00 00 00 02 e0 00
-			15 01 00 00 00 00 02 dc 21
-			15 01 00 00 00 00 02 dd 22
-			15 01 00 00 00 00 02 de 07
-			15 01 00 00 00 00 02 df 07
-			15 01 00 00 00 00 02 e3 6D
-			15 01 00 00 00 00 02 e1 07
-			15 01 00 00 00 00 02 e2 07
-			/* UD */
-			15 01 00 00 00 00 02 29 d8
-			15 01 00 00 00 00 02 2a 2a
-			/* CLK */
-			15 01 00 00 00 00 02 4b 03
-			15 01 00 00 00 00 02 4c 11
-			15 01 00 00 00 00 02 4d 10
-			15 01 00 00 00 00 02 4e 01
-			15 01 00 00 00 00 02 4f 01
-			15 01 00 00 00 00 02 50 10
-			15 01 00 00 00 00 02 51 00
-			15 01 00 00 00 00 02 52 80
-			15 01 00 00 00 00 02 53 00
-			15 01 00 00 00 00 02 56 00
-			15 01 00 00 00 00 02 54 07
-			15 01 00 00 00 00 02 58 07
-			15 01 00 00 00 00 02 55 25
-			/* Reset XDONB */
-			15 01 00 00 00 00 02 5b 43
-			15 01 00 00 00 00 02 5c 00
-			15 01 00 00 00 00 02 5f 73
-			15 01 00 00 00 00 02 60 73
-			15 01 00 00 00 00 02 63 22
-			15 01 00 00 00 00 02 64 00
-			15 01 00 00 00 00 02 67 08
-			15 01 00 00 00 00 02 68 04
-			/* Resolution:1440x2560*/
-			15 01 00 00 00 00 02 72 02
-			/* mux */
-			15 01 00 00 00 00 02 7a 80
-			15 01 00 00 00 00 02 7b 91
-			15 01 00 00 00 00 02 7c D8
-			15 01 00 00 00 00 02 7d 60
-			15 01 00 00 00 00 02 7f 15
-			15 01 00 00 00 00 02 75 15
-			/* ABOFF */
-			15 01 00 00 00 00 02 b3 C0
-			15 01 00 00 00 00 02 b4 00
-			15 01 00 00 00 00 02 b5 00
-			/* Source EQ */
-			15 01 00 00 00 00 02 78 00
-			15 01 00 00 00 00 02 79 00
-			15 01 00 00 00 00 02 80 00
-			15 01 00 00 00 00 02 83 00
-			/* FP BP */
-			15 01 00 00 00 00 02 93 0a
-			15 01 00 00 00 00 02 94 0a
-			/* Inversion Type */
-			15 01 00 00 00 00 02 8a 00
-			15 01 00 00 00 00 02 9b ff
-			/* IMGSWAP =1 @PortSwap=1 */
-			15 01 00 00 00 00 02 9d b0
-			15 01 00 00 00 00 02 9f 63
-			15 01 00 00 00 00 02 98 10
-			/* FRM */
-			15 01 00 00 00 00 02 ec 00
-			/* CMD1 */
-			15 01 00 00 00 00 02 ff 10
-			/* VESA DSC PPS settings(1440x2560 slide 16H) */
-			39 01 00 00 00 00 11 c1 09 20 00 10 02 00 02 68
-					01 bb 00 0a 06 67 04 c5
-			39 01 00 00 00 00 03 c2 10 f0
-			/* C0h = 0x0(2 Port SDC)0x01(1 PortA FBC)
-			 * 0x02(MTK) 0x03(1 PortA VESA)
-			 */
-			15 01 00 00 00 00 02 c0 03
-			/* VBP+VSA=,VFP = 10H */
-			15 01 00 00 00 00 04 3b 03 0a 0a
-			/* FTE on */
-			15 01 00 00 00 00 02 35 00
-			/* EN_BK =1(auto black) */
-			15 01 00 00 00 00 02 e5 01
-			/* CMD mode(10) VDO mode(03) */
-			15 01 00 00 00 00 02 bb 10
-			/* Non Reload MTP */
-			15 01 00 00 00 00 02 fb 01
-			/* SlpOut + DispOn */
-			05 01 00 00 78 00 02 11 00
-			05 01 00 00 78 00 02 29 00
-			];
-		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
-			05 01 00 00 78 00 02 10 00];
-
-		qcom,mdss-dsi-on-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -215,7 +38,6 @@
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
-
 		qcom,mdss-dsi-bl-max-level = <4095>;
 		qcom,adjust-timer-wakeup-ms = <1>;
 		qcom,mdss-dsi-te-pin-select = <1>;
@@ -225,13 +47,201 @@
 		qcom,mdss-dsi-te-check-enable;
 		qcom,mdss-dsi-te-using-te-pin;
 
-		qcom,compression-mode = "dsc";
-		qcom,mdss-dsc-slice-height = <16>;
-		qcom,mdss-dsc-slice-width = <720>;
-		qcom,mdss-dsc-slice-per-pkt = <2>;
-		qcom,mdss-dsc-bit-per-component = <8>;
-		qcom,mdss-dsc-bit-per-pixel = <8>;
-		qcom,mdss-dsc-block-prediction-enable;
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-panel-width = <1440>;
+				qcom,mdss-dsi-panel-height = <2560>;
+				qcom,mdss-dsi-h-front-porch = <100>;
+				qcom,mdss-dsi-h-back-porch = <32>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <8>;
+				qcom,mdss-dsi-v-front-porch = <10>;
+				qcom,mdss-dsi-v-pulse-width = <2>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-panel-jitter = <0x1 0x1>;
+				qcom,mdss-dsi-on-command = [
+					/* CMD2_P0 */
+					15 01 00 00 00 00 02 ff 20
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 01
+					15 01 00 00 00 00 02 01 55
+					15 01 00 00 00 00 02 02 45
+					15 01 00 00 00 00 02 05 40
+					15 01 00 00 00 00 02 06 19
+					15 01 00 00 00 00 02 07 1e
+					15 01 00 00 00 00 02 0b 73
+					15 01 00 00 00 00 02 0c 73
+					15 01 00 00 00 00 02 0e b0
+					15 01 00 00 00 00 02 0f ae
+					15 01 00 00 00 00 02 11 b8
+					15 01 00 00 00 00 02 13 00
+					15 01 00 00 00 00 02 58 80
+					15 01 00 00 00 00 02 59 01
+					15 01 00 00 00 00 02 5a 00
+					15 01 00 00 00 00 02 5b 01
+					15 01 00 00 00 00 02 5c 80
+					15 01 00 00 00 00 02 5d 81
+					15 01 00 00 00 00 02 5e 00
+					15 01 00 00 00 00 02 5f 01
+					15 01 00 00 00 00 02 72 31
+					15 01 00 00 00 00 02 68 03
+					/* CMD2_P4 */
+					15 01 00 00 00 00 02 ff 24
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 1c
+					15 01 00 00 00 00 02 01 0b
+					15 01 00 00 00 00 02 02 0c
+					15 01 00 00 00 00 02 03 01
+					15 01 00 00 00 00 02 04 0f
+					15 01 00 00 00 00 02 05 10
+					15 01 00 00 00 00 02 06 10
+					15 01 00 00 00 00 02 07 10
+					15 01 00 00 00 00 02 08 89
+					15 01 00 00 00 00 02 09 8a
+					15 01 00 00 00 00 02 0a 13
+					15 01 00 00 00 00 02 0b 13
+					15 01 00 00 00 00 02 0c 15
+					15 01 00 00 00 00 02 0d 15
+					15 01 00 00 00 00 02 0e 17
+					15 01 00 00 00 00 02 0f 17
+					15 01 00 00 00 00 02 10 1c
+					15 01 00 00 00 00 02 11 0b
+					15 01 00 00 00 00 02 12 0c
+					15 01 00 00 00 00 02 13 01
+					15 01 00 00 00 00 02 14 0f
+					15 01 00 00 00 00 02 15 10
+					15 01 00 00 00 00 02 16 10
+					15 01 00 00 00 00 02 17 10
+					15 01 00 00 00 00 02 18 89
+					15 01 00 00 00 00 02 19 8a
+					15 01 00 00 00 00 02 1a 13
+					15 01 00 00 00 00 02 1b 13
+					15 01 00 00 00 00 02 1c 15
+					15 01 00 00 00 00 02 1d 15
+					15 01 00 00 00 00 02 1e 17
+					15 01 00 00 00 00 02 1f 17
+					/* STV */
+					15 01 00 00 00 00 02 20 40
+					15 01 00 00 00 00 02 21 01
+					15 01 00 00 00 00 02 22 00
+					15 01 00 00 00 00 02 23 40
+					15 01 00 00 00 00 02 24 40
+					15 01 00 00 00 00 02 25 6d
+					15 01 00 00 00 00 02 26 40
+					15 01 00 00 00 00 02 27 40
+					/* Vend */
+					15 01 00 00 00 00 02 e0 00
+					15 01 00 00 00 00 02 dc 21
+					15 01 00 00 00 00 02 dd 22
+					15 01 00 00 00 00 02 de 07
+					15 01 00 00 00 00 02 df 07
+					15 01 00 00 00 00 02 e3 6D
+					15 01 00 00 00 00 02 e1 07
+					15 01 00 00 00 00 02 e2 07
+					/* UD */
+					15 01 00 00 00 00 02 29 d8
+					15 01 00 00 00 00 02 2a 2a
+					/* CLK */
+					15 01 00 00 00 00 02 4b 03
+					15 01 00 00 00 00 02 4c 11
+					15 01 00 00 00 00 02 4d 10
+					15 01 00 00 00 00 02 4e 01
+					15 01 00 00 00 00 02 4f 01
+					15 01 00 00 00 00 02 50 10
+					15 01 00 00 00 00 02 51 00
+					15 01 00 00 00 00 02 52 80
+					15 01 00 00 00 00 02 53 00
+					15 01 00 00 00 00 02 56 00
+					15 01 00 00 00 00 02 54 07
+					15 01 00 00 00 00 02 58 07
+					15 01 00 00 00 00 02 55 25
+					/* Reset XDONB */
+					15 01 00 00 00 00 02 5b 43
+					15 01 00 00 00 00 02 5c 00
+					15 01 00 00 00 00 02 5f 73
+					15 01 00 00 00 00 02 60 73
+					15 01 00 00 00 00 02 63 22
+					15 01 00 00 00 00 02 64 00
+					15 01 00 00 00 00 02 67 08
+					15 01 00 00 00 00 02 68 04
+					/* Resolution:1440x2560*/
+					15 01 00 00 00 00 02 72 02
+					/* mux */
+					15 01 00 00 00 00 02 7a 80
+					15 01 00 00 00 00 02 7b 91
+					15 01 00 00 00 00 02 7c D8
+					15 01 00 00 00 00 02 7d 60
+					15 01 00 00 00 00 02 7f 15
+					15 01 00 00 00 00 02 75 15
+					/* ABOFF */
+					15 01 00 00 00 00 02 b3 C0
+					15 01 00 00 00 00 02 b4 00
+					15 01 00 00 00 00 02 b5 00
+					/* Source EQ */
+					15 01 00 00 00 00 02 78 00
+					15 01 00 00 00 00 02 79 00
+					15 01 00 00 00 00 02 80 00
+					15 01 00 00 00 00 02 83 00
+					/* FP BP */
+					15 01 00 00 00 00 02 93 0a
+					15 01 00 00 00 00 02 94 0a
+					/* Inversion Type */
+					15 01 00 00 00 00 02 8a 00
+					15 01 00 00 00 00 02 9b ff
+					/* IMGSWAP =1 @PortSwap=1 */
+					15 01 00 00 00 00 02 9d b0
+					15 01 00 00 00 00 02 9f 63
+					15 01 00 00 00 00 02 98 10
+					/* FRM */
+					15 01 00 00 00 00 02 ec 00
+					/* CMD1 */
+					15 01 00 00 00 00 02 ff 10
+					/* VESA DSC PPS settings
+					 *  (1440x2560 slide 16H)
+					 */
+					39 01 00 00 00 00 11 c1 09
+					20 00 10 02 00 02 68 01 bb
+					00 0a 06 67 04 c5
 
+					39 01 00 00 00 00 03 c2 10 f0
+					/* C0h = 0x0(2 Port SDC)
+					 * 0x01(1 PortA FBC)
+					 * 0x02(MTK) 0x03(1 PortA VESA)
+					 */
+					15 01 00 00 00 00 02 c0 03
+					/* VBP+VSA=,VFP = 10H */
+					15 01 00 00 00 00 04 3b 03 0a 0a
+					/* FTE on */
+					15 01 00 00 00 00 02 35 00
+					/* EN_BK =1(auto black) */
+					15 01 00 00 00 00 02 e5 01
+					/* CMD mode(10) VDO mode(03) */
+					15 01 00 00 00 00 02 bb 10
+					/* Non Reload MTP */
+					15 01 00 00 00 00 02 fb 01
+					/* SlpOut + DispOn */
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 78 00 02 29 00
+					];
+				qcom,mdss-dsi-off-command = [05 01 00 00 78 00
+					02 28 00 05 01 00 00 78 00 02 10 00];
+
+				qcom,mdss-dsi-on-command-state = "dsi_hs_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,compression-mode = "dsc";
+				qcom,mdss-dsc-slice-height = <16>;
+				qcom,mdss-dsc-slice-width = <720>;
+				qcom,mdss-dsc-slice-per-pkt = <2>;
+				qcom,mdss-dsc-bit-per-component = <8>;
+				qcom,mdss-dsc-bit-per-pixel = <8>;
+				qcom,mdss-dsc-block-prediction-enable;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi
index 515949e..ac8a956 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi
@@ -15,18 +15,8 @@
 		qcom,mdss-dsi-panel-name =
 			"nt35597 video mode dsi truly panel with DSC";
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1440>;
-		qcom,mdss-dsi-panel-height = <2560>;
-		qcom,mdss-dsi-h-front-porch = <100>;
-		qcom,mdss-dsi-h-back-porch = <32>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <8>;
-		qcom,mdss-dsi-v-front-porch = <10>;
-		qcom,mdss-dsi-v-pulse-width = <2>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
@@ -35,170 +25,6 @@
 			17000 15500 30000 8000 3000>;
 		qcom,mdss-dsi-panel-peak-brightness = <4200000>;
 		qcom,mdss-dsi-panel-blackness-level = <3230>;
-		qcom,mdss-dsi-on-command = [
-			/* CMD2_P0 */
-			15 01 00 00 00 00 02 ff 20
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 01
-			15 01 00 00 00 00 02 01 55
-			15 01 00 00 00 00 02 02 45
-			15 01 00 00 00 00 02 05 40
-			15 01 00 00 00 00 02 06 19
-			15 01 00 00 00 00 02 07 1e
-			15 01 00 00 00 00 02 0b 73
-			15 01 00 00 00 00 02 0c 73
-			15 01 00 00 00 00 02 0e b0
-			15 01 00 00 00 00 02 0f aE
-			15 01 00 00 00 00 02 11 b8
-			15 01 00 00 00 00 02 13 00
-			15 01 00 00 00 00 02 58 80
-			15 01 00 00 00 00 02 59 01
-			15 01 00 00 00 00 02 5a 00
-			15 01 00 00 00 00 02 5b 01
-			15 01 00 00 00 00 02 5c 80
-			15 01 00 00 00 00 02 5d 81
-			15 01 00 00 00 00 02 5e 00
-			15 01 00 00 00 00 02 5f 01
-			15 01 00 00 00 00 02 72 31
-			15 01 00 00 00 00 02 68 03
-			/* CMD2_P4 */
-			15 01 00 00 00 00 02 ff 24
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 1c
-			15 01 00 00 00 00 02 01 0b
-			15 01 00 00 00 00 02 02 0c
-			15 01 00 00 00 00 02 03 01
-			15 01 00 00 00 00 02 04 0f
-			15 01 00 00 00 00 02 05 10
-			15 01 00 00 00 00 02 06 10
-			15 01 00 00 00 00 02 07 10
-			15 01 00 00 00 00 02 08 89
-			15 01 00 00 00 00 02 09 8a
-			15 01 00 00 00 00 02 0a 13
-			15 01 00 00 00 00 02 0b 13
-			15 01 00 00 00 00 02 0c 15
-			15 01 00 00 00 00 02 0d 15
-			15 01 00 00 00 00 02 0e 17
-			15 01 00 00 00 00 02 0f 17
-			15 01 00 00 00 00 02 10 1c
-			15 01 00 00 00 00 02 11 0b
-			15 01 00 00 00 00 02 12 0c
-			15 01 00 00 00 00 02 13 01
-			15 01 00 00 00 00 02 14 0f
-			15 01 00 00 00 00 02 15 10
-			15 01 00 00 00 00 02 16 10
-			15 01 00 00 00 00 02 17 10
-			15 01 00 00 00 00 02 18 89
-			15 01 00 00 00 00 02 19 8a
-			15 01 00 00 00 00 02 1a 13
-			15 01 00 00 00 00 02 1b 13
-			15 01 00 00 00 00 02 1c 15
-			15 01 00 00 00 00 02 1d 15
-			15 01 00 00 00 00 02 1e 17
-			15 01 00 00 00 00 02 1f 17
-			/* STV */
-			15 01 00 00 00 00 02 20 40
-			15 01 00 00 00 00 02 21 01
-			15 01 00 00 00 00 02 22 00
-			15 01 00 00 00 00 02 23 40
-			15 01 00 00 00 00 02 24 40
-			15 01 00 00 00 00 02 25 6d
-			15 01 00 00 00 00 02 26 40
-			15 01 00 00 00 00 02 27 40
-			/* Vend */
-			15 01 00 00 00 00 02 e0 00
-			15 01 00 00 00 00 02 dc 21
-			15 01 00 00 00 00 02 dd 22
-			15 01 00 00 00 00 02 de 07
-			15 01 00 00 00 00 02 df 07
-			15 01 00 00 00 00 02 e3 6d
-			15 01 00 00 00 00 02 e1 07
-			15 01 00 00 00 00 02 e2 07
-			/* UD */
-			15 01 00 00 00 00 02 29 d8
-			15 01 00 00 00 00 02 2a 2a
-			/* CLK */
-			15 01 00 00 00 00 02 4b 03
-			15 01 00 00 00 00 02 4c 11
-			15 01 00 00 00 00 02 4d 10
-			15 01 00 00 00 00 02 4e 01
-			15 01 00 00 00 00 02 4f 01
-			15 01 00 00 00 00 02 50 10
-			15 01 00 00 00 00 02 51 00
-			15 01 00 00 00 00 02 52 80
-			15 01 00 00 00 00 02 53 00
-			15 01 00 00 00 00 02 56 00
-			15 01 00 00 00 00 02 54 07
-			15 01 00 00 00 00 02 58 07
-			15 01 00 00 00 00 02 55 25
-			/* Reset XDONB */
-			15 01 00 00 00 00 02 5b 43
-			15 01 00 00 00 00 02 5c 00
-			15 01 00 00 00 00 02 5f 73
-			15 01 00 00 00 00 02 60 73
-			15 01 00 00 00 00 02 63 22
-			15 01 00 00 00 00 02 64 00
-			15 01 00 00 00 00 02 67 08
-			15 01 00 00 00 00 02 68 04
-			/* Resolution:1440x2560*/
-			15 01 00 00 00 00 02 72 02
-			/* mux */
-			15 01 00 00 00 00 02 7a 80
-			15 01 00 00 00 00 02 7b 91
-			15 01 00 00 00 00 02 7c d8
-			15 01 00 00 00 00 02 7d 60
-			15 01 00 00 00 00 02 7f 15
-			15 01 00 00 00 00 02 75 15
-			/* ABOFF */
-			15 01 00 00 00 00 02 b3 c0
-			15 01 00 00 00 00 02 b4 00
-			15 01 00 00 00 00 02 b5 00
-			/* Source EQ */
-			15 01 00 00 00 00 02 78 00
-			15 01 00 00 00 00 02 79 00
-			15 01 00 00 00 00 02 80 00
-			15 01 00 00 00 00 02 83 00
-			/* FP BP */
-			15 01 00 00 00 00 02 93 0a
-			15 01 00 00 00 00 02 94 0a
-			/* Inversion Type */
-			15 01 00 00 00 00 02 8a 00
-			15 01 00 00 00 00 02 9b ff
-			/* IMGSWAP =1 @PortSwap=1 */
-			15 01 00 00 00 00 02 9d b0
-			15 01 00 00 00 00 02 9f 63
-			15 01 00 00 00 00 02 98 10
-			/* FRM */
-			15 01 00 00 00 00 02 ec 00
-			/* CMD1 */
-			15 01 00 00 00 00 02 ff 10
-			/* VESA DSC PPS settings(1440x2560 slide 16H) */
-			39 01 00 00 00 00 11 c1 09 20 00 10 02 00 02 68 01
-				bb 00 0a 06 67 04 c5
-			39 01 00 00 00 00 03 c2 10 f0
-			/* C0h = 0x00(2 Port SDC); 0x01(1 PortA FBC);
-			 * 0x02(MTK); 0x03(1 PortA VESA)
-			 */
-			15 01 00 00 00 00 02 c0 03
-			/* VBP+VSA=,VFP = 10H */
-			39 01 00 00 00 00 04 3b 03 0a 0a
-			/* FTE on */
-			15 01 00 00 00 00 02 35 00
-			/* EN_BK =1(auto black) */
-			15 01 00 00 00 00 02 e5 01
-			/* CMD mode(10) VDO mode(03) */
-			15 01 00 00 00 00 02 bb 03
-			/* Non Reload MTP */
-			15 01 00 00 00 00 02 fb 01
-			/* SlpOut + DispOn */
-			05 01 00 00 78 00 02 11 00
-			05 01 00 00 78 00 02 29 00
-			];
-		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
-				 05 01 00 00 78 00 02 10 00];
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -212,12 +38,195 @@
 		qcom,mdss-pan-physical-width-dimension = <74>;
 		qcom,mdss-pan-physical-height-dimension = <131>;
 
-		qcom,compression-mode = "dsc";
-		qcom,mdss-dsc-slice-height = <16>;
-		qcom,mdss-dsc-slice-width = <720>;
-		qcom,mdss-dsc-slice-per-pkt = <2>;
-		qcom,mdss-dsc-bit-per-component = <8>;
-		qcom,mdss-dsc-bit-per-pixel = <8>;
-		qcom,mdss-dsc-block-prediction-enable;
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <1440>;
+				qcom,mdss-dsi-panel-height = <2560>;
+				qcom,mdss-dsi-h-front-porch = <100>;
+				qcom,mdss-dsi-h-back-porch = <32>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <8>;
+				qcom,mdss-dsi-v-front-porch = <10>;
+				qcom,mdss-dsi-v-pulse-width = <2>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command = [
+					/* CMD2_P0 */
+					15 01 00 00 00 00 02 ff 20
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 01
+					15 01 00 00 00 00 02 01 55
+					15 01 00 00 00 00 02 02 45
+					15 01 00 00 00 00 02 05 40
+					15 01 00 00 00 00 02 06 19
+					15 01 00 00 00 00 02 07 1e
+					15 01 00 00 00 00 02 0b 73
+					15 01 00 00 00 00 02 0c 73
+					15 01 00 00 00 00 02 0e b0
+					15 01 00 00 00 00 02 0f aE
+					15 01 00 00 00 00 02 11 b8
+					15 01 00 00 00 00 02 13 00
+					15 01 00 00 00 00 02 58 80
+					15 01 00 00 00 00 02 59 01
+					15 01 00 00 00 00 02 5a 00
+					15 01 00 00 00 00 02 5b 01
+					15 01 00 00 00 00 02 5c 80
+					15 01 00 00 00 00 02 5d 81
+					15 01 00 00 00 00 02 5e 00
+					15 01 00 00 00 00 02 5f 01
+					15 01 00 00 00 00 02 72 31
+					15 01 00 00 00 00 02 68 03
+					/* CMD2_P4 */
+					15 01 00 00 00 00 02 ff 24
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 1c
+					15 01 00 00 00 00 02 01 0b
+					15 01 00 00 00 00 02 02 0c
+					15 01 00 00 00 00 02 03 01
+					15 01 00 00 00 00 02 04 0f
+					15 01 00 00 00 00 02 05 10
+					15 01 00 00 00 00 02 06 10
+					15 01 00 00 00 00 02 07 10
+					15 01 00 00 00 00 02 08 89
+					15 01 00 00 00 00 02 09 8a
+					15 01 00 00 00 00 02 0a 13
+					15 01 00 00 00 00 02 0b 13
+					15 01 00 00 00 00 02 0c 15
+					15 01 00 00 00 00 02 0d 15
+					15 01 00 00 00 00 02 0e 17
+					15 01 00 00 00 00 02 0f 17
+					15 01 00 00 00 00 02 10 1c
+					15 01 00 00 00 00 02 11 0b
+					15 01 00 00 00 00 02 12 0c
+					15 01 00 00 00 00 02 13 01
+					15 01 00 00 00 00 02 14 0f
+					15 01 00 00 00 00 02 15 10
+					15 01 00 00 00 00 02 16 10
+					15 01 00 00 00 00 02 17 10
+					15 01 00 00 00 00 02 18 89
+					15 01 00 00 00 00 02 19 8a
+					15 01 00 00 00 00 02 1a 13
+					15 01 00 00 00 00 02 1b 13
+					15 01 00 00 00 00 02 1c 15
+					15 01 00 00 00 00 02 1d 15
+					15 01 00 00 00 00 02 1e 17
+					15 01 00 00 00 00 02 1f 17
+					/* STV */
+					15 01 00 00 00 00 02 20 40
+					15 01 00 00 00 00 02 21 01
+					15 01 00 00 00 00 02 22 00
+					15 01 00 00 00 00 02 23 40
+					15 01 00 00 00 00 02 24 40
+					15 01 00 00 00 00 02 25 6d
+					15 01 00 00 00 00 02 26 40
+					15 01 00 00 00 00 02 27 40
+					/* Vend */
+					15 01 00 00 00 00 02 e0 00
+					15 01 00 00 00 00 02 dc 21
+					15 01 00 00 00 00 02 dd 22
+					15 01 00 00 00 00 02 de 07
+					15 01 00 00 00 00 02 df 07
+					15 01 00 00 00 00 02 e3 6d
+					15 01 00 00 00 00 02 e1 07
+					15 01 00 00 00 00 02 e2 07
+					/* UD */
+					15 01 00 00 00 00 02 29 d8
+					15 01 00 00 00 00 02 2a 2a
+					/* CLK */
+					15 01 00 00 00 00 02 4b 03
+					15 01 00 00 00 00 02 4c 11
+					15 01 00 00 00 00 02 4d 10
+					15 01 00 00 00 00 02 4e 01
+					15 01 00 00 00 00 02 4f 01
+					15 01 00 00 00 00 02 50 10
+					15 01 00 00 00 00 02 51 00
+					15 01 00 00 00 00 02 52 80
+					15 01 00 00 00 00 02 53 00
+					15 01 00 00 00 00 02 56 00
+					15 01 00 00 00 00 02 54 07
+					15 01 00 00 00 00 02 58 07
+					15 01 00 00 00 00 02 55 25
+					/* Reset XDONB */
+					15 01 00 00 00 00 02 5b 43
+					15 01 00 00 00 00 02 5c 00
+					15 01 00 00 00 00 02 5f 73
+					15 01 00 00 00 00 02 60 73
+					15 01 00 00 00 00 02 63 22
+					15 01 00 00 00 00 02 64 00
+					15 01 00 00 00 00 02 67 08
+					15 01 00 00 00 00 02 68 04
+					/* Resolution:1440x2560*/
+					15 01 00 00 00 00 02 72 02
+					/* mux */
+					15 01 00 00 00 00 02 7a 80
+					15 01 00 00 00 00 02 7b 91
+					15 01 00 00 00 00 02 7c d8
+					15 01 00 00 00 00 02 7d 60
+					15 01 00 00 00 00 02 7f 15
+					15 01 00 00 00 00 02 75 15
+					/* ABOFF */
+					15 01 00 00 00 00 02 b3 c0
+					15 01 00 00 00 00 02 b4 00
+					15 01 00 00 00 00 02 b5 00
+					/* Source EQ */
+					15 01 00 00 00 00 02 78 00
+					15 01 00 00 00 00 02 79 00
+					15 01 00 00 00 00 02 80 00
+					15 01 00 00 00 00 02 83 00
+					/* FP BP */
+					15 01 00 00 00 00 02 93 0a
+					15 01 00 00 00 00 02 94 0a
+					/* Inversion Type */
+					15 01 00 00 00 00 02 8a 00
+					15 01 00 00 00 00 02 9b ff
+					/* IMGSWAP =1 @PortSwap=1 */
+					15 01 00 00 00 00 02 9d b0
+					15 01 00 00 00 00 02 9f 63
+					15 01 00 00 00 00 02 98 10
+					/* FRM */
+					15 01 00 00 00 00 02 ec 00
+					/* CMD1 */
+					15 01 00 00 00 00 02 ff 10
+					/* VESA DSC PPS settings
+					 * (1440x2560 slide 16H)
+					 */
+					39 01 00 00 00 00 11 c1 09
+					20 00 10 02 00 02 68 01	bb
+					00 0a 06 67 04 c5
+
+					39 01 00 00 00 00 03 c2 10 f0
+					/* C0h = 0x00(2 Port SDC);
+					 * 0x01(1 PortA FBC);
+					 * 0x02(MTK); 0x03(1 PortA VESA)
+					 */
+					15 01 00 00 00 00 02 c0 03
+					/* VBP+VSA=,VFP = 10H */
+					39 01 00 00 00 00 04 3b 03 0a 0a
+					/* FTE on */
+					15 01 00 00 00 00 02 35 00
+					/* EN_BK =1(auto black) */
+					15 01 00 00 00 00 02 e5 01
+					/* CMD mode(10) VDO mode(03) */
+					15 01 00 00 00 00 02 bb 03
+					/* Non Reload MTP */
+					15 01 00 00 00 00 02 fb 01
+					/* SlpOut + DispOn */
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 78 00 02 29 00
+					];
+				qcom,mdss-dsi-off-command = [05 01 00 00 78 00
+					02 28 00 05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,compression-mode = "dsc";
+				qcom,mdss-dsc-slice-height = <16>;
+				qcom,mdss-dsc-slice-width = <720>;
+				qcom,mdss-dsc-slice-per-pkt = <2>;
+				qcom,mdss-dsc-bit-per-component = <8>;
+				qcom,mdss-dsc-bit-per-pixel = <8>;
+				qcom,mdss-dsc-block-prediction-enable;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi
index 647ea4e..87cabae 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi
@@ -15,27 +15,12 @@
 		qcom,mdss-dsi-panel-name =
 			"Dual nt35597 cmd mode dsi truly panel without DSC";
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <720>;
-		qcom,mdss-dsi-panel-height = <2560>;
-		qcom,mdss-dsi-h-front-porch = <100>;
-		qcom,mdss-dsi-h-back-porch = <32>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <7>;
-		qcom,mdss-dsi-v-front-porch = <8>;
-		qcom,mdss-dsi-v-pulse-width = <1>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-color-order = "rgb_swap_rgb";
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -45,6 +30,8 @@
 		qcom,mdss-dsi-lane-3-state;
 		qcom,adjust-timer-wakeup-ms = <1>;
 		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+		qcom,mdss-pan-physical-width-dimension = <74>;
+		qcom,mdss-pan-physical-height-dimension = <131>;
 		qcom,mdss-dsi-bl-max-level = <4095>;
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
@@ -59,167 +46,181 @@
 			17000 15500 30000 8000 3000>;
 		qcom,mdss-dsi-panel-peak-brightness = <4200000>;
 		qcom,mdss-dsi-panel-blackness-level = <3230>;
-		qcom,mdss-dsi-on-command = [
-			/* CMD2_P0 */
-			15 01 00 00 00 00 02 FF 20
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 01
-			15 01 00 00 00 00 02 01 55
-			15 01 00 00 00 00 02 02 45
-			15 01 00 00 00 00 02 05 40
-			15 01 00 00 00 00 02 06 19
-			15 01 00 00 00 00 02 07 1E
-			15 01 00 00 00 00 02 0B 73
-			15 01 00 00 00 00 02 0C 73
-			15 01 00 00 00 00 02 0E B0
-			15 01 00 00 00 00 02 0F AE
-			15 01 00 00 00 00 02 11 B8
-			15 01 00 00 00 00 02 13 00
-			15 01 00 00 00 00 02 58 80
-			15 01 00 00 00 00 02 59 01
-			15 01 00 00 00 00 02 5A 00
-			15 01 00 00 00 00 02 5B 01
-			15 01 00 00 00 00 02 5C 80
-			15 01 00 00 00 00 02 5D 81
-			15 01 00 00 00 00 02 5E 00
-			15 01 00 00 00 00 02 5F 01
-			15 01 00 00 00 00 02 72 31
-			15 01 00 00 00 00 02 68 03
-			/* CMD2_P4 */
-			15 01 00 00 00 00 02 ff 24
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 1C
-			15 01 00 00 00 00 02 01 0B
-			15 01 00 00 00 00 02 02 0C
-			15 01 00 00 00 00 02 03 01
-			15 01 00 00 00 00 02 04 0F
-			15 01 00 00 00 00 02 05 10
-			15 01 00 00 00 00 02 06 10
-			15 01 00 00 00 00 02 07 10
-			15 01 00 00 00 00 02 08 89
-			15 01 00 00 00 00 02 09 8A
-			15 01 00 00 00 00 02 0A 13
-			15 01 00 00 00 00 02 0B 13
-			15 01 00 00 00 00 02 0C 15
-			15 01 00 00 00 00 02 0D 15
-			15 01 00 00 00 00 02 0E 17
-			15 01 00 00 00 00 02 0F 17
-			15 01 00 00 00 00 02 10 1C
-			15 01 00 00 00 00 02 11 0B
-			15 01 00 00 00 00 02 12 0C
-			15 01 00 00 00 00 02 13 01
-			15 01 00 00 00 00 02 14 0F
-			15 01 00 00 00 00 02 15 10
-			15 01 00 00 00 00 02 16 10
-			15 01 00 00 00 00 02 17 10
-			15 01 00 00 00 00 02 18 89
-			15 01 00 00 00 00 02 19 8A
-			15 01 00 00 00 00 02 1A 13
-			15 01 00 00 00 00 02 1B 13
-			15 01 00 00 00 00 02 1C 15
-			15 01 00 00 00 00 02 1D 15
-			15 01 00 00 00 00 02 1E 17
-			15 01 00 00 00 00 02 1F 17
-			/* STV */
-			15 01 00 00 00 00 02 20 40
-			15 01 00 00 00 00 02 21 01
-			15 01 00 00 00 00 02 22 00
-			15 01 00 00 00 00 02 23 40
-			15 01 00 00 00 00 02 24 40
-			15 01 00 00 00 00 02 25 6D
-			15 01 00 00 00 00 02 26 40
-			15 01 00 00 00 00 02 27 40
-			/* Vend */
-			15 01 00 00 00 00 02 E0 00
-			15 01 00 00 00 00 02 DC 21
-			15 01 00 00 00 00 02 DD 22
-			15 01 00 00 00 00 02 DE 07
-			15 01 00 00 00 00 02 DF 07
-			15 01 00 00 00 00 02 E3 6D
-			15 01 00 00 00 00 02 E1 07
-			15 01 00 00 00 00 02 E2 07
-			/* UD */
-			15 01 00 00 00 00 02 29 D8
-			15 01 00 00 00 00 02 2A 2A
-			/* CLK */
-			15 01 00 00 00 00 02 4B 03
-			15 01 00 00 00 00 02 4C 11
-			15 01 00 00 00 00 02 4D 10
-			15 01 00 00 00 00 02 4E 01
-			15 01 00 00 00 00 02 4F 01
-			15 01 00 00 00 00 02 50 10
-			15 01 00 00 00 00 02 51 00
-			15 01 00 00 00 00 02 52 80
-			15 01 00 00 00 00 02 53 00
-			15 01 00 00 00 00 02 56 00
-			15 01 00 00 00 00 02 54 07
-			15 01 00 00 00 00 02 58 07
-			15 01 00 00 00 00 02 55 25
-			/* Reset XDONB */
-			15 01 00 00 00 00 02 5B 43
-			15 01 00 00 00 00 02 5C 00
-			15 01 00 00 00 00 02 5F 73
-			15 01 00 00 00 00 02 60 73
-			15 01 00 00 00 00 02 63 22
-			15 01 00 00 00 00 02 64 00
-			15 01 00 00 00 00 02 67 08
-			15 01 00 00 00 00 02 68 04
-			/* Resolution:1440x2560*/
-			15 01 00 00 00 00 02 72 02
-			/* mux */
-			15 01 00 00 00 00 02 7A 80
-			15 01 00 00 00 00 02 7B 91
-			15 01 00 00 00 00 02 7C D8
-			15 01 00 00 00 00 02 7D 60
-			15 01 00 00 00 00 02 7F 15
-			15 01 00 00 00 00 02 75 15
-			/* ABOFF */
-			15 01 00 00 00 00 02 B3 C0
-			15 01 00 00 00 00 02 B4 00
-			15 01 00 00 00 00 02 B5 00
-			/* Source EQ */
-			15 01 00 00 00 00 02 78 00
-			15 01 00 00 00 00 02 79 00
-			15 01 00 00 00 00 02 80 00
-			15 01 00 00 00 00 02 83 00
-			/* FP BP */
-			15 01 00 00 00 00 02 93 0A
-			15 01 00 00 00 00 02 94 0A
-			/* Inversion Type */
-			15 01 00 00 00 00 02 8A 00
-			15 01 00 00 00 00 02 9B FF
-			/* IMGSWAP =1 @PortSwap=1 */
-			15 01 00 00 00 00 02 9D B0
-			15 01 00 00 00 00 02 9F 63
-			15 01 00 00 00 00 02 98 10
-			/* FRM */
-			15 01 00 00 00 00 02 EC 00
-			/* CMD1 */
-			15 01 00 00 00 00 02 ff 10
-			/* VBP+VSA=,VFP = 10H */
-			15 01 00 00 00 00 04 3B 03 0A 0A
-			/* FTE on */
-			15 01 00 00 00 00 02 35 00
-			/* EN_BK =1(auto black) */
-			15 01 00 00 00 00 02 E5 01
-			/* CMD mode(10) VDO mode(03) */
-			15 01 00 00 00 00 02 BB 10
-			/* Non Reload MTP */
-			15 01 00 00 00 00 02 FB 01
-			/* SlpOut + DispOn */
-			05 01 00 00 78 00 02 11 00
-			05 01 00 00 78 00 02 29 00
-			];
-		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
-			05 01 00 00 78 00 02 10 00];
 
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-
-		qcom,config-select = <&dsi_dual_nt35597_truly_cmd_config0>;
-
-		dsi_dual_nt35597_truly_cmd_config0: config0 {
-			qcom,split-mode = "dualctl-split";
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-panel-width = <720>;
+				qcom,mdss-dsi-panel-height = <2560>;
+				qcom,mdss-dsi-h-front-porch = <100>;
+				qcom,mdss-dsi-h-back-porch = <32>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <7>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-jitter = <0x1 0x1>;
+				qcom,mdss-dsi-on-command = [
+					/* CMD2_P0 */
+					15 01 00 00 00 00 02 FF 20
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 01
+					15 01 00 00 00 00 02 01 55
+					15 01 00 00 00 00 02 02 45
+					15 01 00 00 00 00 02 05 40
+					15 01 00 00 00 00 02 06 19
+					15 01 00 00 00 00 02 07 1E
+					15 01 00 00 00 00 02 0B 73
+					15 01 00 00 00 00 02 0C 73
+					15 01 00 00 00 00 02 0E B0
+					15 01 00 00 00 00 02 0F AE
+					15 01 00 00 00 00 02 11 B8
+					15 01 00 00 00 00 02 13 00
+					15 01 00 00 00 00 02 58 80
+					15 01 00 00 00 00 02 59 01
+					15 01 00 00 00 00 02 5A 00
+					15 01 00 00 00 00 02 5B 01
+					15 01 00 00 00 00 02 5C 80
+					15 01 00 00 00 00 02 5D 81
+					15 01 00 00 00 00 02 5E 00
+					15 01 00 00 00 00 02 5F 01
+					15 01 00 00 00 00 02 72 31
+					15 01 00 00 00 00 02 68 03
+					/* CMD2_P4 */
+					15 01 00 00 00 00 02 ff 24
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 1C
+					15 01 00 00 00 00 02 01 0B
+					15 01 00 00 00 00 02 02 0C
+					15 01 00 00 00 00 02 03 01
+					15 01 00 00 00 00 02 04 0F
+					15 01 00 00 00 00 02 05 10
+					15 01 00 00 00 00 02 06 10
+					15 01 00 00 00 00 02 07 10
+					15 01 00 00 00 00 02 08 89
+					15 01 00 00 00 00 02 09 8A
+					15 01 00 00 00 00 02 0A 13
+					15 01 00 00 00 00 02 0B 13
+					15 01 00 00 00 00 02 0C 15
+					15 01 00 00 00 00 02 0D 15
+					15 01 00 00 00 00 02 0E 17
+					15 01 00 00 00 00 02 0F 17
+					15 01 00 00 00 00 02 10 1C
+					15 01 00 00 00 00 02 11 0B
+					15 01 00 00 00 00 02 12 0C
+					15 01 00 00 00 00 02 13 01
+					15 01 00 00 00 00 02 14 0F
+					15 01 00 00 00 00 02 15 10
+					15 01 00 00 00 00 02 16 10
+					15 01 00 00 00 00 02 17 10
+					15 01 00 00 00 00 02 18 89
+					15 01 00 00 00 00 02 19 8A
+					15 01 00 00 00 00 02 1A 13
+					15 01 00 00 00 00 02 1B 13
+					15 01 00 00 00 00 02 1C 15
+					15 01 00 00 00 00 02 1D 15
+					15 01 00 00 00 00 02 1E 17
+					15 01 00 00 00 00 02 1F 17
+					/* STV */
+					15 01 00 00 00 00 02 20 40
+					15 01 00 00 00 00 02 21 01
+					15 01 00 00 00 00 02 22 00
+					15 01 00 00 00 00 02 23 40
+					15 01 00 00 00 00 02 24 40
+					15 01 00 00 00 00 02 25 6D
+					15 01 00 00 00 00 02 26 40
+					15 01 00 00 00 00 02 27 40
+					/* Vend */
+					15 01 00 00 00 00 02 E0 00
+					15 01 00 00 00 00 02 DC 21
+					15 01 00 00 00 00 02 DD 22
+					15 01 00 00 00 00 02 DE 07
+					15 01 00 00 00 00 02 DF 07
+					15 01 00 00 00 00 02 E3 6D
+					15 01 00 00 00 00 02 E1 07
+					15 01 00 00 00 00 02 E2 07
+					/* UD */
+					15 01 00 00 00 00 02 29 D8
+					15 01 00 00 00 00 02 2A 2A
+					/* CLK */
+					15 01 00 00 00 00 02 4B 03
+					15 01 00 00 00 00 02 4C 11
+					15 01 00 00 00 00 02 4D 10
+					15 01 00 00 00 00 02 4E 01
+					15 01 00 00 00 00 02 4F 01
+					15 01 00 00 00 00 02 50 10
+					15 01 00 00 00 00 02 51 00
+					15 01 00 00 00 00 02 52 80
+					15 01 00 00 00 00 02 53 00
+					15 01 00 00 00 00 02 56 00
+					15 01 00 00 00 00 02 54 07
+					15 01 00 00 00 00 02 58 07
+					15 01 00 00 00 00 02 55 25
+					/* Reset XDONB */
+					15 01 00 00 00 00 02 5B 43
+					15 01 00 00 00 00 02 5C 00
+					15 01 00 00 00 00 02 5F 73
+					15 01 00 00 00 00 02 60 73
+					15 01 00 00 00 00 02 63 22
+					15 01 00 00 00 00 02 64 00
+					15 01 00 00 00 00 02 67 08
+					15 01 00 00 00 00 02 68 04
+					/* Resolution:1440x2560*/
+					15 01 00 00 00 00 02 72 02
+					/* mux */
+					15 01 00 00 00 00 02 7A 80
+					15 01 00 00 00 00 02 7B 91
+					15 01 00 00 00 00 02 7C D8
+					15 01 00 00 00 00 02 7D 60
+					15 01 00 00 00 00 02 7F 15
+					15 01 00 00 00 00 02 75 15
+					/* ABOFF */
+					15 01 00 00 00 00 02 B3 C0
+					15 01 00 00 00 00 02 B4 00
+					15 01 00 00 00 00 02 B5 00
+					/* Source EQ */
+					15 01 00 00 00 00 02 78 00
+					15 01 00 00 00 00 02 79 00
+					15 01 00 00 00 00 02 80 00
+					15 01 00 00 00 00 02 83 00
+					/* FP BP */
+					15 01 00 00 00 00 02 93 0A
+					15 01 00 00 00 00 02 94 0A
+					/* Inversion Type */
+					15 01 00 00 00 00 02 8A 00
+					15 01 00 00 00 00 02 9B FF
+					/* IMGSWAP =1 @PortSwap=1 */
+					15 01 00 00 00 00 02 9D B0
+					15 01 00 00 00 00 02 9F 63
+					15 01 00 00 00 00 02 98 10
+					/* FRM */
+					15 01 00 00 00 00 02 EC 00
+					/* CMD1 */
+					15 01 00 00 00 00 02 ff 10
+					/* VBP+VSA=,VFP = 10H */
+					15 01 00 00 00 00 04 3B 03 0A 0A
+					/* FTE on */
+					15 01 00 00 00 00 02 35 00
+					/* EN_BK =1(auto black) */
+					15 01 00 00 00 00 02 E5 01
+					/* CMD mode(10) VDO mode(03) */
+					15 01 00 00 00 00 02 BB 10
+					/* Non Reload MTP */
+					15 01 00 00 00 00 02 FB 01
+					/* SlpOut + DispOn */
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 78 00 02 29 00
+					];
+				qcom,mdss-dsi-off-command = [05 01 00 00 78 00
+					02 28 00 05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+			};
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi
index 346a8b4..0d0e7f7 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi
@@ -15,182 +15,13 @@
 		qcom,mdss-dsi-panel-name =
 			"Dual nt35597 video mode dsi truly panel without DSC";
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <720>;
-		qcom,mdss-dsi-panel-height = <2560>;
-		qcom,mdss-dsi-h-front-porch = <100>;
-		qcom,mdss-dsi-h-back-porch = <32>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <7>;
-		qcom,mdss-dsi-v-front-porch = <8>;
-		qcom,mdss-dsi-v-pulse-width = <1>;
-		qcom,mdss-dsi-bpp = <24>;
-		qcom,mdss-dsi-underflow-color = <0x3ff>;
-		qcom,mdss-dsi-border-color = <0>;
 		qcom,mdss-dsi-panel-hdr-enabled;
 		qcom,mdss-dsi-panel-hdr-color-primaries = <14500 15500 32000
 			17000 15500 30000 8000 3000>;
 		qcom,mdss-dsi-panel-peak-brightness = <4200000>;
 		qcom,mdss-dsi-panel-blackness-level = <3230>;
-		qcom,mdss-dsi-on-command = [
-			/* CMD2_P0 */
-			15 01 00 00 00 00 02 FF 20
-			15 01 00 00 00 00 02 FB 01
-			15 01 00 00 00 00 02 00 01
-			15 01 00 00 00 00 02 01 55
-			15 01 00 00 00 00 02 02 45
-			15 01 00 00 00 00 02 05 40
-			15 01 00 00 00 00 02 06 19
-			15 01 00 00 00 00 02 07 1E
-			15 01 00 00 00 00 02 0B 73
-			15 01 00 00 00 00 02 0C 73
-			15 01 00 00 00 00 02 0E B0
-			15 01 00 00 00 00 02 0F AE
-			15 01 00 00 00 00 02 11 B8
-			15 01 00 00 00 00 02 13 00
-			15 01 00 00 00 00 02 58 80
-			15 01 00 00 00 00 02 59 01
-			15 01 00 00 00 00 02 5A 00
-			15 01 00 00 00 00 02 5B 01
-			15 01 00 00 00 00 02 5C 80
-			15 01 00 00 00 00 02 5D 81
-			15 01 00 00 00 00 02 5E 00
-			15 01 00 00 00 00 02 5F 01
-			15 01 00 00 00 00 02 72 31
-			15 01 00 00 00 00 02 68 03
-			/* CMD2_P4 */
-			15 01 00 00 00 00 02 FF 24
-			15 01 00 00 00 00 02 FB 01
-			15 01 00 00 00 00 02 00 1C
-			15 01 00 00 00 00 02 01 0B
-			15 01 00 00 00 00 02 02 0C
-			15 01 00 00 00 00 02 03 01
-			15 01 00 00 00 00 02 04 0F
-			15 01 00 00 00 00 02 05 10
-			15 01 00 00 00 00 02 06 10
-			15 01 00 00 00 00 02 07 10
-			15 01 00 00 00 00 02 08 89
-			15 01 00 00 00 00 02 09 8A
-			15 01 00 00 00 00 02 0A 13
-			15 01 00 00 00 00 02 0B 13
-			15 01 00 00 00 00 02 0C 15
-			15 01 00 00 00 00 02 0D 15
-			15 01 00 00 00 00 02 0E 17
-			15 01 00 00 00 00 02 0F 17
-			15 01 00 00 00 00 02 10 1C
-			15 01 00 00 00 00 02 11 0B
-			15 01 00 00 00 00 02 12 0C
-			15 01 00 00 00 00 02 13 01
-			15 01 00 00 00 00 02 14 0F
-			15 01 00 00 00 00 02 15 10
-			15 01 00 00 00 00 02 16 10
-			15 01 00 00 00 00 02 17 10
-			15 01 00 00 00 00 02 18 89
-			15 01 00 00 00 00 02 19 8A
-			15 01 00 00 00 00 02 1A 13
-			15 01 00 00 00 00 02 1B 13
-			15 01 00 00 00 00 02 1C 15
-			15 01 00 00 00 00 02 1D 15
-			15 01 00 00 00 00 02 1E 17
-			15 01 00 00 00 00 02 1F 17
-			/* STV */
-			15 01 00 00 00 00 02 20 40
-			15 01 00 00 00 00 02 21 01
-			15 01 00 00 00 00 02 22 00
-			15 01 00 00 00 00 02 23 40
-			15 01 00 00 00 00 02 24 40
-			15 01 00 00 00 00 02 25 6D
-			15 01 00 00 00 00 02 26 40
-			15 01 00 00 00 00 02 27 40
-			/* Vend */
-			15 01 00 00 00 00 02 E0 00
-			15 01 00 00 00 00 02 DC 21
-			15 01 00 00 00 00 02 DD 22
-			15 01 00 00 00 00 02 DE 07
-			15 01 00 00 00 00 02 DF 07
-			15 01 00 00 00 00 02 E3 6D
-			15 01 00 00 00 00 02 E1 07
-			15 01 00 00 00 00 02 E2 07
-			/* UD */
-			15 01 00 00 00 00 02 29 D8
-			15 01 00 00 00 00 02 2A 2A
-			/* CLK */
-			15 01 00 00 00 00 02 4B 03
-			15 01 00 00 00 00 02 4C 11
-			15 01 00 00 00 00 02 4D 10
-			15 01 00 00 00 00 02 4E 01
-			15 01 00 00 00 00 02 4F 01
-			15 01 00 00 00 00 02 50 10
-			15 01 00 00 00 00 02 51 00
-			15 01 00 00 00 00 02 52 80
-			15 01 00 00 00 00 02 53 00
-			15 01 00 00 00 00 02 56 00
-			15 01 00 00 00 00 02 54 07
-			15 01 00 00 00 00 02 58 07
-			15 01 00 00 00 00 02 55 25
-			/* Reset XDONB */
-			15 01 00 00 00 00 02 5B 43
-			15 01 00 00 00 00 02 5C 00
-			15 01 00 00 00 00 02 5F 73
-			15 01 00 00 00 00 02 60 73
-			15 01 00 00 00 00 02 63 22
-			15 01 00 00 00 00 02 64 00
-			15 01 00 00 00 00 02 67 08
-			15 01 00 00 00 00 02 68 04
-			/* Resolution:1440x2560*/
-			15 01 00 00 00 00 02 72 02
-			/* mux */
-			15 01 00 00 00 00 02 7A 80
-			15 01 00 00 00 00 02 7B 91
-			15 01 00 00 00 00 02 7C D8
-			15 01 00 00 00 00 02 7D 60
-			15 01 00 00 00 00 02 7F 15
-			15 01 00 00 00 00 02 75 15
-			/* ABOFF */
-			15 01 00 00 00 00 02 B3 C0
-			15 01 00 00 00 00 02 B4 00
-			15 01 00 00 00 00 02 B5 00
-			/* Source EQ */
-			15 01 00 00 00 00 02 78 00
-			15 01 00 00 00 00 02 79 00
-			15 01 00 00 00 00 02 80 00
-			15 01 00 00 00 00 02 83 00
-			/* FP BP */
-			15 01 00 00 00 00 02 93 0A
-			15 01 00 00 00 00 02 94 0A
-			/* Inversion Type */
-			15 01 00 00 00 00 02 8A 00
-			15 01 00 00 00 00 02 9B FF
-			/* IMGSWAP =1 @PortSwap=1 */
-			15 01 00 00 00 00 02 9D B0
-			15 01 00 00 00 00 02 9F 63
-			15 01 00 00 00 00 02 98 10
-			/* FRM */
-			15 01 00 00 00 00 02 EC 00
-			/* CMD1 */
-			15 01 00 00 00 00 02 FF 10
-			/* VBP+VSA=,VFP = 10H */
-			15 01 00 00 00 00 04 3B 03 0A 0A
-			/* FTE on */
-			15 01 00 00 00 00 02 35 00
-			/* EN_BK =1(auto black) */
-			15 01 00 00 00 00 02 E5 01
-			/* CMD mode(10) VDO mode(03) */
-			15 01 00 00 00 00 02 BB 03
-			/* Non Reload MTP */
-			15 01 00 00 00 00 02 FB 01
-			/* SlpOut + DispOn */
-			05 01 00 00 78 00 02 11 00
-			05 01 00 00 78 00 02 29 00
-			];
-		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
-				 05 01 00 00 78 00 02 10 00];
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -202,14 +33,182 @@
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 20>, <1 50>;
+		qcom,mdss-pan-physical-width-dimension = <74>;
+		qcom,mdss-pan-physical-height-dimension = <131>;
 		qcom,mdss-dsi-tx-eot-append;
+		qcom,mdss-dsi-underflow-color = <0x3ff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-bpp = <24>;
 
-		qcom,config-select = <&dsi_dual_nt35597_truly_video_config0>;
-
-		dsi_dual_nt35597_truly_video_config0: config0 {
-			qcom,split-mode = "dualctl-split";
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <720>;
+				qcom,mdss-dsi-panel-height = <2560>;
+				qcom,mdss-dsi-h-front-porch = <100>;
+				qcom,mdss-dsi-h-back-porch = <32>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <7>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command = [
+					/* CMD2_P0 */
+					15 01 00 00 00 00 02 FF 20
+					15 01 00 00 00 00 02 FB 01
+					15 01 00 00 00 00 02 00 01
+					15 01 00 00 00 00 02 01 55
+					15 01 00 00 00 00 02 02 45
+					15 01 00 00 00 00 02 05 40
+					15 01 00 00 00 00 02 06 19
+					15 01 00 00 00 00 02 07 1E
+					15 01 00 00 00 00 02 0B 73
+					15 01 00 00 00 00 02 0C 73
+					15 01 00 00 00 00 02 0E B0
+					15 01 00 00 00 00 02 0F AE
+					15 01 00 00 00 00 02 11 B8
+					15 01 00 00 00 00 02 13 00
+					15 01 00 00 00 00 02 58 80
+					15 01 00 00 00 00 02 59 01
+					15 01 00 00 00 00 02 5A 00
+					15 01 00 00 00 00 02 5B 01
+					15 01 00 00 00 00 02 5C 80
+					15 01 00 00 00 00 02 5D 81
+					15 01 00 00 00 00 02 5E 00
+					15 01 00 00 00 00 02 5F 01
+					15 01 00 00 00 00 02 72 31
+					15 01 00 00 00 00 02 68 03
+					/* CMD2_P4 */
+					15 01 00 00 00 00 02 FF 24
+					15 01 00 00 00 00 02 FB 01
+					15 01 00 00 00 00 02 00 1C
+					15 01 00 00 00 00 02 01 0B
+					15 01 00 00 00 00 02 02 0C
+					15 01 00 00 00 00 02 03 01
+					15 01 00 00 00 00 02 04 0F
+					15 01 00 00 00 00 02 05 10
+					15 01 00 00 00 00 02 06 10
+					15 01 00 00 00 00 02 07 10
+					15 01 00 00 00 00 02 08 89
+					15 01 00 00 00 00 02 09 8A
+					15 01 00 00 00 00 02 0A 13
+					15 01 00 00 00 00 02 0B 13
+					15 01 00 00 00 00 02 0C 15
+					15 01 00 00 00 00 02 0D 15
+					15 01 00 00 00 00 02 0E 17
+					15 01 00 00 00 00 02 0F 17
+					15 01 00 00 00 00 02 10 1C
+					15 01 00 00 00 00 02 11 0B
+					15 01 00 00 00 00 02 12 0C
+					15 01 00 00 00 00 02 13 01
+					15 01 00 00 00 00 02 14 0F
+					15 01 00 00 00 00 02 15 10
+					15 01 00 00 00 00 02 16 10
+					15 01 00 00 00 00 02 17 10
+					15 01 00 00 00 00 02 18 89
+					15 01 00 00 00 00 02 19 8A
+					15 01 00 00 00 00 02 1A 13
+					15 01 00 00 00 00 02 1B 13
+					15 01 00 00 00 00 02 1C 15
+					15 01 00 00 00 00 02 1D 15
+					15 01 00 00 00 00 02 1E 17
+					15 01 00 00 00 00 02 1F 17
+					/* STV */
+					15 01 00 00 00 00 02 20 40
+					15 01 00 00 00 00 02 21 01
+					15 01 00 00 00 00 02 22 00
+					15 01 00 00 00 00 02 23 40
+					15 01 00 00 00 00 02 24 40
+					15 01 00 00 00 00 02 25 6D
+					15 01 00 00 00 00 02 26 40
+					15 01 00 00 00 00 02 27 40
+					/* Vend */
+					15 01 00 00 00 00 02 E0 00
+					15 01 00 00 00 00 02 DC 21
+					15 01 00 00 00 00 02 DD 22
+					15 01 00 00 00 00 02 DE 07
+					15 01 00 00 00 00 02 DF 07
+					15 01 00 00 00 00 02 E3 6D
+					15 01 00 00 00 00 02 E1 07
+					15 01 00 00 00 00 02 E2 07
+					/* UD */
+					15 01 00 00 00 00 02 29 D8
+					15 01 00 00 00 00 02 2A 2A
+					/* CLK */
+					15 01 00 00 00 00 02 4B 03
+					15 01 00 00 00 00 02 4C 11
+					15 01 00 00 00 00 02 4D 10
+					15 01 00 00 00 00 02 4E 01
+					15 01 00 00 00 00 02 4F 01
+					15 01 00 00 00 00 02 50 10
+					15 01 00 00 00 00 02 51 00
+					15 01 00 00 00 00 02 52 80
+					15 01 00 00 00 00 02 53 00
+					15 01 00 00 00 00 02 56 00
+					15 01 00 00 00 00 02 54 07
+					15 01 00 00 00 00 02 58 07
+					15 01 00 00 00 00 02 55 25
+					/* Reset XDONB */
+					15 01 00 00 00 00 02 5B 43
+					15 01 00 00 00 00 02 5C 00
+					15 01 00 00 00 00 02 5F 73
+					15 01 00 00 00 00 02 60 73
+					15 01 00 00 00 00 02 63 22
+					15 01 00 00 00 00 02 64 00
+					15 01 00 00 00 00 02 67 08
+					15 01 00 00 00 00 02 68 04
+					/* Resolution:1440x2560*/
+					15 01 00 00 00 00 02 72 02
+					/* mux */
+					15 01 00 00 00 00 02 7A 80
+					15 01 00 00 00 00 02 7B 91
+					15 01 00 00 00 00 02 7C D8
+					15 01 00 00 00 00 02 7D 60
+					15 01 00 00 00 00 02 7F 15
+					15 01 00 00 00 00 02 75 15
+					/* ABOFF */
+					15 01 00 00 00 00 02 B3 C0
+					15 01 00 00 00 00 02 B4 00
+					15 01 00 00 00 00 02 B5 00
+					/* Source EQ */
+					15 01 00 00 00 00 02 78 00
+					15 01 00 00 00 00 02 79 00
+					15 01 00 00 00 00 02 80 00
+					15 01 00 00 00 00 02 83 00
+					/* FP BP */
+					15 01 00 00 00 00 02 93 0A
+					15 01 00 00 00 00 02 94 0A
+					/* Inversion Type */
+					15 01 00 00 00 00 02 8A 00
+					15 01 00 00 00 00 02 9B FF
+					/* IMGSWAP =1 @PortSwap=1 */
+					15 01 00 00 00 00 02 9D B0
+					15 01 00 00 00 00 02 9F 63
+					15 01 00 00 00 00 02 98 10
+					/* FRM */
+					15 01 00 00 00 00 02 EC 00
+					/* CMD1 */
+					15 01 00 00 00 00 02 FF 10
+					/* VBP+VSA=,VFP = 10H */
+					15 01 00 00 00 00 04 3B 03 0A 0A
+					/* FTE on */
+					15 01 00 00 00 00 02 35 00
+					/* EN_BK =1(auto black) */
+					15 01 00 00 00 00 02 E5 01
+					/* CMD mode(10) VDO mode(03) */
+					15 01 00 00 00 00 02 BB 03
+					/* Non Reload MTP */
+					15 01 00 00 00 00 02 FB 01
+					/* SlpOut + DispOn */
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 78 00 02 29 00
+					];
+				qcom,mdss-dsi-off-command = [05 01 00 00 78 00
+					02 28 00 05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+			};
 		};
-
-
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-1080p-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-1080p-cmd.dtsi
index c2b054a..aebc8b9 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-1080p-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-1080p-cmd.dtsi
@@ -16,48 +16,15 @@
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
 		qcom,mdss-dsi-panel-destination = "display_1";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-panel-clockrate = <850000000>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1080>;
-		qcom,mdss-dsi-panel-height = <1920>;
-		qcom,mdss-dsi-h-front-porch = <0>;
-		qcom,mdss-dsi-h-back-porch = <0>;
-		qcom,mdss-dsi-h-pulse-width = <0>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <0>;
-		qcom,mdss-dsi-v-front-porch = <0>;
-		qcom,mdss-dsi-v-pulse-width = <0>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
 		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
-		qcom,mdss-dsi-on-command = [
-			15 01 00 00 00 00 02 bb 10
-			15 01 00 00 00 00 02 b0 03
-			05 01 00 00 78 00 01 11
-			15 01 00 00 00 00 02 51 ff
-			15 01 00 00 00 00 02 53 24
-			15 01 00 00 00 00 02 ff 23
-			15 01 00 00 00 00 02 08 05
-			15 01 00 00 00 00 02 46 90
-			15 01 00 00 00 00 02 ff 10
-			15 01 00 00 00 00 02 ff f0
-			15 01 00 00 00 00 02 92 01
-			15 01 00 00 00 00 02 ff 10
-			15 01 00 00 00 00 02 35 00 /* enable TE generation */
-			05 01 00 00 28 00 01 29];
-		qcom,mdss-dsi-off-command = [
-			05 01 00 00 10 00 01 28
-			05 01 00 00 40 00 01 10];
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-pan-physical-width-dimension = <64>;
+		qcom,mdss-pan-physical-height-dimension = <117>;
 		qcom,mdss-dsi-traffic-mode = "burst_mode";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -74,5 +41,46 @@
 		qcom,mdss-dsi-te-dcs-command = <1>;
 		qcom,mdss-dsi-te-check-enable;
 		qcom,mdss-dsi-te-using-te-pin;
+
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <1080>;
+				qcom,mdss-dsi-panel-height = <1920>;
+				qcom,mdss-dsi-h-front-porch = <0>;
+				qcom,mdss-dsi-h-back-porch = <0>;
+				qcom,mdss-dsi-h-pulse-width = <0>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <0>;
+				qcom,mdss-dsi-v-front-porch = <0>;
+				qcom,mdss-dsi-v-pulse-width = <0>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command = [
+					15 01 00 00 00 00 02 bb 10
+					15 01 00 00 00 00 02 b0 03
+					05 01 00 00 78 00 01 11
+					15 01 00 00 00 00 02 51 ff
+					15 01 00 00 00 00 02 53 24
+					15 01 00 00 00 00 02 ff 23
+					15 01 00 00 00 00 02 08 05
+					15 01 00 00 00 00 02 46 90
+					15 01 00 00 00 00 02 ff 10
+					15 01 00 00 00 00 02 ff f0
+					15 01 00 00 00 00 02 92 01
+					15 01 00 00 00 00 02 ff 10
+					/* enable TE generation */
+					15 01 00 00 00 00 02 35 00
+					05 01 00 00 28 00 01 29];
+				qcom,mdss-dsi-off-command = [
+					05 01 00 00 10 00 01 28
+					05 01 00 00 40 00 01 10];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-cmd.dtsi
index 6534cdc..ce849c6 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-cmd.dtsi
@@ -14,23 +14,10 @@
 	dsi_sharp_4k_dsc_cmd: qcom,mdss_dsi_sharp_4k_dsc_cmd {
 		qcom,mdss-dsi-panel-name = "Sharp 4k cmd mode dsc dsi panel";
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1080>;
-		qcom,mdss-dsi-panel-height = <3840>;
-		qcom,mdss-dsi-h-front-porch = <30>;
-		qcom,mdss-dsi-h-back-porch = <100>;
-		qcom,mdss-dsi-h-pulse-width = <4>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <7>;
-		qcom,mdss-dsi-v-front-porch = <8>;
-		qcom,mdss-dsi-v-pulse-width = <1>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-border-color = <0>;
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "burst_mode";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -41,6 +28,8 @@
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-reset-sequence = <1 100>, <0 100>, <1 100>;
+		qcom,mdss-pan-physical-width-dimension = <71>;
+		qcom,mdss-pan-physical-height-dimension = <129>;
 		qcom,mdss-dsi-te-pin-select = <1>;
 		qcom,mdss-dsi-wr-mem-start = <0x2c>;
 		qcom,mdss-dsi-wr-mem-continue = <0x3c>;
@@ -49,39 +38,61 @@
 		qcom,mdss-dsi-te-using-te-pin;
 		qcom,dcs-cmd-by-left;
 		qcom,mdss-dsi-tx-eot-append;
-
 		qcom,adjust-timer-wakeup-ms = <1>;
-		qcom,mdss-dsi-on-command = [
-			39 01 00 00 00 00 11 91 09 20 00 20 02 00 03 1c 04 21 00
-			0f 03 19 01 97
-			39 01 00 00 00 00 03 92 10 f0
-			15 01 00 00 00 00 02 90 03
-			15 01 00 00 00 00 02 03 01
-			39 01 00 00 00 00 06 f0 55 aa 52 08 04
-			15 01 00 00 00 00 02 c0 03
-			39 01 00 00 00 00 06 f0 55 aa 52 08 07
-			15 01 00 00 00 00 02 ef 01
-			39 01 00 00 00 00 06 f0 55 aa 52 08 00
-			15 01 00 00 00 00 02 b4 01
-			15 01 00 00 00 00 02 35 00
-			39 01 00 00 00 00 06 f0 55 aa 52 08 01
-			39 01 00 00 00 00 05 ff aa 55 a5 80
-			15 01 00 00 00 00 02 6f 01
-			15 01 00 00 00 00 02 f3 10
-			39 01 00 00 00 00 05 ff aa 55 a5 00
-			05 01 00 00 78 00 01 11 /* sleep out + delay 120ms */
-			05 01 00 00 78 00 01 29 /* display on + delay 120ms */
-			];
 
-		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
-				 05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <1080>;
+				qcom,mdss-dsi-panel-height = <3840>;
+				qcom,mdss-dsi-h-front-porch = <30>;
+				qcom,mdss-dsi-h-back-porch = <100>;
+				qcom,mdss-dsi-h-pulse-width = <4>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <7>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-panel-jitter = <0x8 0xa>;
 
-		qcom,compression-mode = "dsc";
-		qcom,mdss-dsc-slice-height = <32>;
-		qcom,mdss-dsc-slice-width = <1080>;
-		qcom,mdss-dsc-slice-per-pkt = <1>;
-		qcom,mdss-dsc-bit-per-component = <8>;
-		qcom,mdss-dsc-bit-per-pixel = <8>;
-		qcom,mdss-dsc-block-prediction-enable;
+				qcom,mdss-dsi-on-command = [
+					39 01 00 00 00 00 11 91 09 20 00 20 02
+					00 03 1c 04 21 00
+					0f 03 19 01 97
+					39 01 00 00 00 00 03 92 10 f0
+					15 01 00 00 00 00 02 90 03
+					15 01 00 00 00 00 02 03 01
+					39 01 00 00 00 00 06 f0 55 aa 52 08 04
+					15 01 00 00 00 00 02 c0 03
+					39 01 00 00 00 00 06 f0 55 aa 52 08 07
+					15 01 00 00 00 00 02 ef 01
+					39 01 00 00 00 00 06 f0 55 aa 52 08 00
+					15 01 00 00 00 00 02 b4 01
+					15 01 00 00 00 00 02 35 00
+					39 01 00 00 00 00 06 f0 55 aa 52 08 01
+					39 01 00 00 00 00 05 ff aa 55 a5 80
+					15 01 00 00 00 00 02 6f 01
+					15 01 00 00 00 00 02 f3 10
+					39 01 00 00 00 00 05 ff aa 55 a5 00
+					/* sleep out + delay 120ms */
+					05 01 00 00 78 00 01 11
+					/* display on + delay 120ms */
+					05 01 00 00 78 00 01 29
+					];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 78 00 02 28 00
+					 05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+
+				qcom,compression-mode = "dsc";
+				qcom,mdss-dsc-slice-height = <32>;
+				qcom,mdss-dsc-slice-width = <1080>;
+				qcom,mdss-dsc-slice-per-pkt = <1>;
+				qcom,mdss-dsc-bit-per-component = <8>;
+				qcom,mdss-dsc-bit-per-pixel = <8>;
+				qcom,mdss-dsc-block-prediction-enable;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-video.dtsi
index b314e99..d3411c8 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dsc-4k-video.dtsi
@@ -14,23 +14,10 @@
 	dsi_sharp_4k_dsc_video: qcom,mdss_dsi_sharp_4k_dsc_video {
 		qcom,mdss-dsi-panel-name = "Sharp 4k video mode dsc dsi panel";
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1080>;
-		qcom,mdss-dsi-panel-height = <3840>;
-		qcom,mdss-dsi-h-front-porch = <30>;
-		qcom,mdss-dsi-h-back-porch = <100>;
-		qcom,mdss-dsi-h-pulse-width = <4>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <7>;
-		qcom,mdss-dsi-v-front-porch = <8>;
-		qcom,mdss-dsi-v-pulse-width = <1>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-border-color = <0>;
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "burst_mode";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -41,40 +28,64 @@
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-reset-sequence = <1 100>, <0 100>, <1 100>;
+		qcom,mdss-pan-physical-width-dimension = <71>;
+		qcom,mdss-pan-physical-height-dimension = <129>;
 		qcom,mdss-dsi-tx-eot-append;
 
 		qcom,adjust-timer-wakeup-ms = <1>;
-		qcom,mdss-dsi-on-command = [
-			39 01 00 00 00 00 11 91 09 20 00 20 02 00 03 1c 04 21 00
-			0f 03 19 01 97
-			39 01 00 00 00 00 03 92 10 f0
-			15 01 00 00 00 00 02 90 03
-			15 01 00 00 00 00 02 03 01
-			39 01 00 00 00 00 06 f0 55 aa 52 08 04
-			15 01 00 00 00 00 02 c0 03
-			39 01 00 00 00 00 06 f0 55 aa 52 08 07
-			15 01 00 00 00 00 02 ef 01
-			39 01 00 00 00 00 06 f0 55 aa 52 08 00
-			15 01 00 00 00 00 02 b4 10
-			15 01 00 00 00 00 02 35 00
-			39 01 00 00 00 00 06 f0 55 aa 52 08 01
-			39 01 00 00 00 00 05 ff aa 55 a5 80
-			15 01 00 00 00 00 02 6f 01
-			15 01 00 00 00 00 02 f3 10
-			39 01 00 00 00 00 05 ff aa 55 a5 00
-			05 01 00 00 78 00 01 11 /* sleep out + delay 120ms */
-			05 01 00 00 78 00 01 29 /* display on + delay 120ms */
-			];
 
-		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
-				 05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <1080>;
+				qcom,mdss-dsi-panel-height = <3840>;
+				qcom,mdss-dsi-h-front-porch = <30>;
+				qcom,mdss-dsi-h-back-porch = <100>;
+				qcom,mdss-dsi-h-pulse-width = <4>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <7>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
 
-		qcom,compression-mode = "dsc";
-		qcom,mdss-dsc-slice-height = <32>;
-		qcom,mdss-dsc-slice-width = <1080>;
-		qcom,mdss-dsc-slice-per-pkt = <1>;
-		qcom,mdss-dsc-bit-per-component = <8>;
-		qcom,mdss-dsc-bit-per-pixel = <8>;
-		qcom,mdss-dsc-block-prediction-enable;
+				qcom,mdss-dsi-on-command = [
+					39 01 00 00 00 00 11 91 09 20 00 20 02
+					00 03 1c 04 21 00
+					0f 03 19 01 97
+					39 01 00 00 00 00 03 92 10 f0
+					15 01 00 00 00 00 02 90 03
+					15 01 00 00 00 00 02 03 01
+					39 01 00 00 00 00 06 f0 55 aa 52 08 04
+					15 01 00 00 00 00 02 c0 03
+					39 01 00 00 00 00 06 f0 55 aa 52 08 07
+					15 01 00 00 00 00 02 ef 01
+					39 01 00 00 00 00 06 f0 55 aa 52 08 00
+					15 01 00 00 00 00 02 b4 10
+					15 01 00 00 00 00 02 35 00
+					39 01 00 00 00 00 06 f0 55 aa 52 08 01
+					39 01 00 00 00 00 05 ff aa 55 a5 80
+					15 01 00 00 00 00 02 6f 01
+					15 01 00 00 00 00 02 f3 10
+					39 01 00 00 00 00 05 ff aa 55 a5 00
+					/* sleep out + delay 120ms */
+					05 01 00 00 78 00 01 11
+					/* display on + delay 120ms */
+					05 01 00 00 78 00 01 29
+					];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 78 00 02 28 00
+					 05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+
+				qcom,compression-mode = "dsc";
+				qcom,mdss-dsc-slice-height = <32>;
+				qcom,mdss-dsc-slice-width = <1080>;
+				qcom,mdss-dsc-slice-per-pkt = <1>;
+				qcom,mdss-dsc-bit-per-component = <8>;
+				qcom,mdss-dsc-bit-per-pixel = <8>;
+				qcom,mdss-dsc-block-prediction-enable;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dualmipi-1080p-120hz.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dualmipi-1080p-120hz.dtsi
index 2071649..6dc621e 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dualmipi-1080p-120hz.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sharp-dualmipi-1080p-120hz.dtsi
@@ -15,595 +15,12 @@
 		qcom,mdss-dsi-panel-name =
 			"sharp 1080p 120hz dual dsi cmd mode panel";
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
-		qcom,mdss-dsi-panel-framerate = <120>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <540>;
-		qcom,mdss-dsi-panel-height = <1920>;
-		qcom,mdss-dsi-h-front-porch = <28>;
-		qcom,mdss-dsi-h-back-porch = <4>;
-		qcom,mdss-dsi-h-pulse-width = <4>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <12>;
-		qcom,mdss-dsi-v-front-porch = <12>;
-		qcom,mdss-dsi-v-pulse-width = <2>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 10>;
-		qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 ff 10
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 ba 07
-			15 01 00 00 00 00 02 c0 00
-			15 01 00 00 00 00 02 bb 10
-			15 01 00 00 00 00 02 d9 00
-			15 01 00 00 00 00 02 ef 70
-			15 01 00 00 00 00 02 f7 80
-			39 01 00 00 00 00 06 3b 03 0e 0c 08 1c
-			15 01 00 00 00 00 02 e9 0e
-			15 01 00 00 00 00 02 ea 0c
-			15 01 00 00 00 00 02 35 00
-			15 01 00 00 00 00 02 c0 00
-			15 01 00 00 00 00 02 ff 20
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 59 6a
-			15 01 00 00 00 00 02 0b 1b
-			15 01 00 00 00 00 02 61 f7
-			15 01 00 00 00 00 02 62 6c
-			15 01 00 00 00 00 02 00 01
-			15 01 00 00 00 00 02 01 55
-			15 01 00 00 00 00 02 04 c8
-			15 01 00 00 00 00 02 05 1a
-			15 01 00 00 00 00 02 0d 93
-			15 01 00 00 00 00 02 0e 93
-			15 01 00 00 00 00 02 0f 7e
-			15 01 00 00 00 00 02 06 69
-			15 01 00 00 00 00 02 07 bc
-			15 01 00 00 00 00 02 10 03
-			15 01 00 00 00 00 02 11 64
-			15 01 00 00 00 00 02 12 5a
-			15 01 00 00 00 00 02 13 40
-			15 01 00 00 00 00 02 14 40
-			15 01 00 00 00 00 02 15 00
-			15 01 00 00 00 00 02 33 13
-			15 01 00 00 00 00 02 5a 40
-			15 01 00 00 00 00 02 5b 40
-			15 01 00 00 00 00 02 5e 80
-			15 01 00 00 00 00 02 ff 24
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 80
-			15 01 00 00 00 00 02 14 80
-			15 01 00 00 00 00 02 01 80
-			15 01 00 00 00 00 02 15 80
-			15 01 00 00 00 00 02 02 80
-			15 01 00 00 00 00 02 16 80
-			15 01 00 00 00 00 02 03 0a
-			15 01 00 00 00 00 02 17 0c
-			15 01 00 00 00 00 02 04 06
-			15 01 00 00 00 00 02 18 08
-			15 01 00 00 00 00 02 05 80
-			15 01 00 00 00 00 02 19 80
-			15 01 00 00 00 00 02 06 80
-			15 01 00 00 00 00 02 1a 80
-			15 01 00 00 00 00 02 07 80
-			15 01 00 00 00 00 02 1b 80
-			15 01 00 00 00 00 02 08 80
-			15 01 00 00 00 00 02 1c 80
-			15 01 00 00 00 00 02 09 80
-			15 01 00 00 00 00 02 1d 80
-			15 01 00 00 00 00 02 0a 80
-			15 01 00 00 00 00 02 1e 80
-			15 01 00 00 00 00 02 0b 1a
-			15 01 00 00 00 00 02 1f 1b
-			15 01 00 00 00 00 02 0c 16
-			15 01 00 00 00 00 02 20 17
-			15 01 00 00 00 00 02 0d 1c
-			15 01 00 00 00 00 02 21 1d
-			15 01 00 00 00 00 02 0e 18
-			15 01 00 00 00 00 02 22 19
-			15 01 00 00 00 00 02 0f 0e
-			15 01 00 00 00 00 02 23 10
-			15 01 00 00 00 00 02 10 80
-			15 01 00 00 00 00 02 24 80
-			15 01 00 00 00 00 02 11 80
-			15 01 00 00 00 00 02 25 80
-			15 01 00 00 00 00 02 12 80
-			15 01 00 00 00 00 02 26 80
-			15 01 00 00 00 00 02 13 80
-			15 01 00 00 00 00 02 27 80
-			15 01 00 00 00 00 02 74 ff
-			15 01 00 00 00 00 02 75 ff
-			15 01 00 00 00 00 02 8d 00
-			15 01 00 00 00 00 02 8e 00
-			15 01 00 00 00 00 02 8f 9c
-			15 01 00 00 00 00 02 90 0c
-			15 01 00 00 00 00 02 91 0e
-			15 01 00 00 00 00 02 d6 00
-			15 01 00 00 00 00 02 d7 20
-			15 01 00 00 00 00 02 d8 00
-			15 01 00 00 00 00 02 d9 88
-			15 01 00 00 00 00 02 e5 05
-			15 01 00 00 00 00 02 e6 10
-			15 01 00 00 00 00 02 54 06
-			15 01 00 00 00 00 02 55 05
-			15 01 00 00 00 00 02 56 04
-			15 01 00 00 00 00 02 58 03
-			15 01 00 00 00 00 02 59 33
-			15 01 00 00 00 00 02 5a 33
-			15 01 00 00 00 00 02 5b 01
-			15 01 00 00 00 00 02 5c 00
-			15 01 00 00 00 00 02 5d 01
-			15 01 00 00 00 00 02 5e 0a
-			15 01 00 00 00 00 02 5f 0a
-			15 01 00 00 00 00 02 60 0a
-			15 01 00 00 00 00 02 61 0a
-			15 01 00 00 00 00 02 62 10
-			15 01 00 00 00 00 02 63 01
-			15 01 00 00 00 00 02 64 00
-			15 01 00 00 00 00 02 65 00
-			15 01 00 00 00 00 02 ef 00
-			15 01 00 00 00 00 02 f0 00
-			15 01 00 00 00 00 02 6d 20
-			15 01 00 00 00 00 02 66 44
-			15 01 00 00 00 00 02 68 01
-			15 01 00 00 00 00 02 69 00
-			15 01 00 00 00 00 02 67 11
-			15 01 00 00 00 00 02 6a 06
-			15 01 00 00 00 00 02 6b 31
-			15 01 00 00 00 00 02 6c 90
-			15 01 00 00 00 00 02 ab c3
-			15 01 00 00 00 00 02 b1 49
-			15 01 00 00 00 00 02 aa 80
-			15 01 00 00 00 00 02 b0 90
-			15 01 00 00 00 00 02 b2 a4
-			15 01 00 00 00 00 02 b3 00
-			15 01 00 00 00 00 02 b4 23
-			15 01 00 00 00 00 02 b5 00
-			15 01 00 00 00 00 02 b6 00
-			15 01 00 00 00 00 02 b7 00
-			15 01 00 00 00 00 02 b8 00
-			15 01 00 00 00 00 02 b9 00
-			15 01 00 00 00 00 02 ba 00
-			15 01 00 00 00 00 02 bb 00
-			15 01 00 00 00 00 02 bc 00
-			15 01 00 00 00 00 02 bd 00
-			15 01 00 00 00 00 02 be 00
-			15 01 00 00 00 00 02 bf 00
-			15 01 00 00 00 00 02 c0 00
-			15 01 00 00 00 00 02 c7 40
-			15 01 00 00 00 00 02 c9 00
-			15 01 00 00 00 00 02 c1 2a
-			15 01 00 00 00 00 02 c2 2a
-			15 01 00 00 00 00 02 c3 00
-			15 01 00 00 00 00 02 c4 00
-			15 01 00 00 00 00 02 c5 00
-			15 01 00 00 00 00 02 c6 00
-			15 01 00 00 00 00 02 c8 ab
-			15 01 00 00 00 00 02 ca 00
-			15 01 00 00 00 00 02 cb 00
-			15 01 00 00 00 00 02 cc 20
-			15 01 00 00 00 00 02 cd 40
-			15 01 00 00 00 00 02 ce a8
-			15 01 00 00 00 00 02 cf a8
-			15 01 00 00 00 00 02 d0 00
-			15 01 00 00 00 00 02 d1 00
-			15 01 00 00 00 00 02 d2 00
-			15 01 00 00 00 00 02 d3 00
-			15 01 00 00 00 00 02 af 01
-			15 01 00 00 00 00 02 a4 1e
-			15 01 00 00 00 00 02 95 41
-			15 01 00 00 00 00 02 96 03
-			15 01 00 00 00 00 02 98 00
-			15 01 00 00 00 00 02 9a 9a
-			15 01 00 00 00 00 02 9b 03
-			15 01 00 00 00 00 02 9d 80
-			15 01 00 00 00 00 02 ff 26
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 fa d0
-			15 01 00 00 00 00 02 6b 80
-			15 01 00 00 00 00 02 6c 5c
-			15 01 00 00 00 00 02 6d 0c
-			15 01 00 00 00 00 02 6e 0e
-			15 01 00 00 00 00 02 58 01
-			15 01 00 00 00 00 02 59 15
-			15 01 00 00 00 00 02 5a 01
-			15 01 00 00 00 00 02 5b 00
-			15 01 00 00 00 00 02 5c 01
-			15 01 00 00 00 00 02 5d 2b
-			15 01 00 00 00 00 02 74 00
-			15 01 00 00 00 00 02 75 ba
-			15 01 00 00 00 00 02 81 0a
-			15 01 00 00 00 00 02 4e 81
-			15 01 00 00 00 00 02 4f 83
-			15 01 00 00 00 00 02 51 00
-			15 01 00 00 00 00 02 53 4d
-			15 01 00 00 00 00 02 54 03
-			15 01 00 00 00 00 02 ff e0
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 b2 81
-			15 01 00 00 00 00 02 62 28
-			15 01 00 00 00 00 02 a2 09
-			15 01 00 00 00 00 02 b3 01
-			15 01 00 00 00 00 02 ed 00
-			15 01 00 00 00 00 02 ff 10
-			05 01 00 00 78 00 01 11
-			15 01 00 00 00 00 02 ff 20
-			15 01 00 00 00 00 02 75 00
-			15 01 00 00 00 00 02 76 71
-			15 01 00 00 00 00 02 77 00
-			15 01 00 00 00 00 02 78 84
-			15 01 00 00 00 00 02 79 00
-			15 01 00 00 00 00 02 7a a5
-			15 01 00 00 00 00 02 7b 00
-			15 01 00 00 00 00 02 7c bb
-			15 01 00 00 00 00 02 7d 00
-			15 01 00 00 00 00 02 7e ce
-			15 01 00 00 00 00 02 7f 00
-			15 01 00 00 00 00 02 80 e0
-			15 01 00 00 00 00 02 81 00
-			15 01 00 00 00 00 02 82 ef
-			15 01 00 00 00 00 02 83 00
-			15 01 00 00 00 00 02 84 ff
-			15 01 00 00 00 00 02 85 01
-			15 01 00 00 00 00 02 86 0b
-			15 01 00 00 00 00 02 87 01
-			15 01 00 00 00 00 02 88 38
-			15 01 00 00 00 00 02 89 01
-			15 01 00 00 00 00 02 8a 5b
-			15 01 00 00 00 00 02 8b 01
-			15 01 00 00 00 00 02 8c 95
-			15 01 00 00 00 00 02 8d 01
-			15 01 00 00 00 00 02 8e c4
-			15 01 00 00 00 00 02 8f 02
-			15 01 00 00 00 00 02 90 0d
-			15 01 00 00 00 00 02 91 02
-			15 01 00 00 00 00 02 92 4a
-			15 01 00 00 00 00 02 93 02
-			15 01 00 00 00 00 02 94 4c
-			15 01 00 00 00 00 02 95 02
-			15 01 00 00 00 00 02 96 85
-			15 01 00 00 00 00 02 97 02
-			15 01 00 00 00 00 02 98 c3
-			15 01 00 00 00 00 02 99 02
-			15 01 00 00 00 00 02 9a e9
-			15 01 00 00 00 00 02 9b 03
-			15 01 00 00 00 00 02 9c 16
-			15 01 00 00 00 00 02 9d 03
-			15 01 00 00 00 00 02 9e 34
-			15 01 00 00 00 00 02 9f 03
-			15 01 00 00 00 00 02 a0 56
-			15 01 00 00 00 00 02 a2 03
-			15 01 00 00 00 00 02 a3 62
-			15 01 00 00 00 00 02 a4 03
-			15 01 00 00 00 00 02 a5 6c
-			15 01 00 00 00 00 02 a6 03
-			15 01 00 00 00 00 02 a7 74
-			15 01 00 00 00 00 02 a9 03
-			15 01 00 00 00 00 02 aa 80
-			15 01 00 00 00 00 02 ab 03
-			15 01 00 00 00 00 02 ac 89
-			15 01 00 00 00 00 02 ad 03
-			15 01 00 00 00 00 02 ae 8b
-			15 01 00 00 00 00 02 af 03
-			15 01 00 00 00 00 02 b0 8d
-			15 01 00 00 00 00 02 b1 03
-			15 01 00 00 00 00 02 b2 8e
-			15 01 00 00 00 00 02 b3 00
-			15 01 00 00 00 00 02 b4 71
-			15 01 00 00 00 00 02 b5 00
-			15 01 00 00 00 00 02 b6 84
-			15 01 00 00 00 00 02 b7 00
-			15 01 00 00 00 00 02 b8 a5
-			15 01 00 00 00 00 02 b9 00
-			15 01 00 00 00 00 02 ba bb
-			15 01 00 00 00 00 02 bb 00
-			15 01 00 00 00 00 02 bc ce
-			15 01 00 00 00 00 02 bd 00
-			15 01 00 00 00 00 02 be e0
-			15 01 00 00 00 00 02 bf 00
-			15 01 00 00 00 00 02 c0 ef
-			15 01 00 00 00 00 02 c1 00
-			15 01 00 00 00 00 02 c2 ff
-			15 01 00 00 00 00 02 c3 01
-			15 01 00 00 00 00 02 c4 0b
-			15 01 00 00 00 00 02 c5 01
-			15 01 00 00 00 00 02 c6 38
-			15 01 00 00 00 00 02 c7 01
-			15 01 00 00 00 00 02 c8 5b
-			15 01 00 00 00 00 02 c9 01
-			15 01 00 00 00 00 02 ca 95
-			15 01 00 00 00 00 02 cb 01
-			15 01 00 00 00 00 02 cc c4
-			15 01 00 00 00 00 02 cd 02
-			15 01 00 00 00 00 02 ce 0d
-			15 01 00 00 00 00 02 cf 02
-			15 01 00 00 00 00 02 d0 4a
-			15 01 00 00 00 00 02 d1 02
-			15 01 00 00 00 00 02 d2 4c
-			15 01 00 00 00 00 02 d3 02
-			15 01 00 00 00 00 02 d4 85
-			15 01 00 00 00 00 02 d5 02
-			15 01 00 00 00 00 02 d6 c3
-			15 01 00 00 00 00 02 d7 02
-			15 01 00 00 00 00 02 d8 e9
-			15 01 00 00 00 00 02 d9 03
-			15 01 00 00 00 00 02 da 16
-			15 01 00 00 00 00 02 db 03
-			15 01 00 00 00 00 02 dc 34
-			15 01 00 00 00 00 02 dd 03
-			15 01 00 00 00 00 02 de 56
-			15 01 00 00 00 00 02 df 03
-			15 01 00 00 00 00 02 e0 62
-			15 01 00 00 00 00 02 e1 03
-			15 01 00 00 00 00 02 e2 6c
-			15 01 00 00 00 00 02 e3 03
-			15 01 00 00 00 00 02 e4 74
-			15 01 00 00 00 00 02 e5 03
-			15 01 00 00 00 00 02 e6 80
-			15 01 00 00 00 00 02 e7 03
-			15 01 00 00 00 00 02 e8 89
-			15 01 00 00 00 00 02 e9 03
-			15 01 00 00 00 00 02 ea 8b
-			15 01 00 00 00 00 02 eb 03
-			15 01 00 00 00 00 02 ec 8d
-			15 01 00 00 00 00 02 ed 03
-			15 01 00 00 00 00 02 ee 8e
-			15 01 00 00 00 00 02 ef 00
-			15 01 00 00 00 00 02 f0 71
-			15 01 00 00 00 00 02 f1 00
-			15 01 00 00 00 00 02 f2 84
-			15 01 00 00 00 00 02 f3 00
-			15 01 00 00 00 00 02 f4 a5
-			15 01 00 00 00 00 02 f5 00
-			15 01 00 00 00 00 02 f6 bb
-			15 01 00 00 00 00 02 f7 00
-			15 01 00 00 00 00 02 f8 ce
-			15 01 00 00 00 00 02 f9 00
-			15 01 00 00 00 00 02 fa e0
-			15 01 00 00 00 00 02 ff 21
-			15 01 00 00 00 00 02 fb 01
-			15 01 00 00 00 00 02 00 00
-			15 01 00 00 00 00 02 01 ef
-			15 01 00 00 00 00 02 02 00
-			15 01 00 00 00 00 02 03 ff
-			15 01 00 00 00 00 02 04 01
-			15 01 00 00 00 00 02 05 0b
-			15 01 00 00 00 00 02 06 01
-			15 01 00 00 00 00 02 07 38
-			15 01 00 00 00 00 02 08 01
-			15 01 00 00 00 00 02 09 5b
-			15 01 00 00 00 00 02 0a 01
-			15 01 00 00 00 00 02 0b 95
-			15 01 00 00 00 00 02 0c 01
-			15 01 00 00 00 00 02 0d c4
-			15 01 00 00 00 00 02 0e 02
-			15 01 00 00 00 00 02 0f 0d
-			15 01 00 00 00 00 02 10 02
-			15 01 00 00 00 00 02 11 4a
-			15 01 00 00 00 00 02 12 02
-			15 01 00 00 00 00 02 13 4c
-			15 01 00 00 00 00 02 14 02
-			15 01 00 00 00 00 02 15 85
-			15 01 00 00 00 00 02 16 02
-			15 01 00 00 00 00 02 17 c3
-			15 01 00 00 00 00 02 18 02
-			15 01 00 00 00 00 02 19 e9
-			15 01 00 00 00 00 02 1a 03
-			15 01 00 00 00 00 02 1b 16
-			15 01 00 00 00 00 02 1c 03
-			15 01 00 00 00 00 02 1d 34
-			15 01 00 00 00 00 02 1e 03
-			15 01 00 00 00 00 02 1f 56
-			15 01 00 00 00 00 02 20 03
-			15 01 00 00 00 00 02 21 62
-			15 01 00 00 00 00 02 22 03
-			15 01 00 00 00 00 02 23 6c
-			15 01 00 00 00 00 02 24 03
-			15 01 00 00 00 00 02 25 74
-			15 01 00 00 00 00 02 26 03
-			15 01 00 00 00 00 02 27 80
-			15 01 00 00 00 00 02 28 03
-			15 01 00 00 00 00 02 29 89
-			15 01 00 00 00 00 02 2a 03
-			15 01 00 00 00 00 02 2b 8b
-			15 01 00 00 00 00 02 2d 03
-			15 01 00 00 00 00 02 2f 8d
-			15 01 00 00 00 00 02 30 03
-			15 01 00 00 00 00 02 31 8e
-			15 01 00 00 00 00 02 32 00
-			15 01 00 00 00 00 02 33 71
-			15 01 00 00 00 00 02 34 00
-			15 01 00 00 00 00 02 35 84
-			15 01 00 00 00 00 02 36 00
-			15 01 00 00 00 00 02 37 a5
-			15 01 00 00 00 00 02 38 00
-			15 01 00 00 00 00 02 39 bb
-			15 01 00 00 00 00 02 3a 00
-			15 01 00 00 00 00 02 3b ce
-			15 01 00 00 00 00 02 3d 00
-			15 01 00 00 00 00 02 3f e0
-			15 01 00 00 00 00 02 40 00
-			15 01 00 00 00 00 02 41 ef
-			15 01 00 00 00 00 02 42 00
-			15 01 00 00 00 00 02 43 ff
-			15 01 00 00 00 00 02 44 01
-			15 01 00 00 00 00 02 45 0b
-			15 01 00 00 00 00 02 46 01
-			15 01 00 00 00 00 02 47 38
-			15 01 00 00 00 00 02 48 01
-			15 01 00 00 00 00 02 49 5b
-			15 01 00 00 00 00 02 4a 01
-			15 01 00 00 00 00 02 4b 95
-			15 01 00 00 00 00 02 4c 01
-			15 01 00 00 00 00 02 4d c4
-			15 01 00 00 00 00 02 4e 02
-			15 01 00 00 00 00 02 4f 0d
-			15 01 00 00 00 00 02 50 02
-			15 01 00 00 00 00 02 51 4a
-			15 01 00 00 00 00 02 52 02
-			15 01 00 00 00 00 02 53 4c
-			15 01 00 00 00 00 02 54 02
-			15 01 00 00 00 00 02 55 85
-			15 01 00 00 00 00 02 56 02
-			15 01 00 00 00 00 02 58 c3
-			15 01 00 00 00 00 02 59 02
-			15 01 00 00 00 00 02 5a e9
-			15 01 00 00 00 00 02 5b 03
-			15 01 00 00 00 00 02 5c 16
-			15 01 00 00 00 00 02 5d 03
-			15 01 00 00 00 00 02 5e 34
-			15 01 00 00 00 00 02 5f 03
-			15 01 00 00 00 00 02 60 56
-			15 01 00 00 00 00 02 61 03
-			15 01 00 00 00 00 02 62 62
-			15 01 00 00 00 00 02 63 03
-			15 01 00 00 00 00 02 64 6c
-			15 01 00 00 00 00 02 65 03
-			15 01 00 00 00 00 02 66 74
-			15 01 00 00 00 00 02 67 03
-			15 01 00 00 00 00 02 68 80
-			15 01 00 00 00 00 02 69 03
-			15 01 00 00 00 00 02 6a 89
-			15 01 00 00 00 00 02 6b 03
-			15 01 00 00 00 00 02 6c 8b
-			15 01 00 00 00 00 02 6d 03
-			15 01 00 00 00 00 02 6e 8d
-			15 01 00 00 00 00 02 6f 03
-			15 01 00 00 00 00 02 70 8e
-			15 01 00 00 00 00 02 71 00
-			15 01 00 00 00 00 02 72 71
-			15 01 00 00 00 00 02 73 00
-			15 01 00 00 00 00 02 74 84
-			15 01 00 00 00 00 02 75 00
-			15 01 00 00 00 00 02 76 a5
-			15 01 00 00 00 00 02 77 00
-			15 01 00 00 00 00 02 78 bb
-			15 01 00 00 00 00 02 79 00
-			15 01 00 00 00 00 02 7a ce
-			15 01 00 00 00 00 02 7b 00
-			15 01 00 00 00 00 02 7c e0
-			15 01 00 00 00 00 02 7d 00
-			15 01 00 00 00 00 02 7e ef
-			15 01 00 00 00 00 02 7f 00
-			15 01 00 00 00 00 02 80 ff
-			15 01 00 00 00 00 02 81 01
-			15 01 00 00 00 00 02 82 0b
-			15 01 00 00 00 00 02 83 01
-			15 01 00 00 00 00 02 84 38
-			15 01 00 00 00 00 02 85 01
-			15 01 00 00 00 00 02 86 5b
-			15 01 00 00 00 00 02 87 01
-			15 01 00 00 00 00 02 88 95
-			15 01 00 00 00 00 02 89 01
-			15 01 00 00 00 00 02 8a c4
-			15 01 00 00 00 00 02 8b 02
-			15 01 00 00 00 00 02 8c 0d
-			15 01 00 00 00 00 02 8d 02
-			15 01 00 00 00 00 02 8e 4a
-			15 01 00 00 00 00 02 8f 02
-			15 01 00 00 00 00 02 90 4c
-			15 01 00 00 00 00 02 91 02
-			15 01 00 00 00 00 02 92 85
-			15 01 00 00 00 00 02 93 02
-			15 01 00 00 00 00 02 94 c3
-			15 01 00 00 00 00 02 95 02
-			15 01 00 00 00 00 02 96 e9
-			15 01 00 00 00 00 02 97 03
-			15 01 00 00 00 00 02 98 16
-			15 01 00 00 00 00 02 99 03
-			15 01 00 00 00 00 02 9a 34
-			15 01 00 00 00 00 02 9b 03
-			15 01 00 00 00 00 02 9c 56
-			15 01 00 00 00 00 02 9d 03
-			15 01 00 00 00 00 02 9e 62
-			15 01 00 00 00 00 02 9f 03
-			15 01 00 00 00 00 02 a0 6c
-			15 01 00 00 00 00 02 a2 03
-			15 01 00 00 00 00 02 a3 74
-			15 01 00 00 00 00 02 a4 03
-			15 01 00 00 00 00 02 a5 80
-			15 01 00 00 00 00 02 a6 03
-			15 01 00 00 00 00 02 a7 89
-			15 01 00 00 00 00 02 a9 03
-			15 01 00 00 00 00 02 aa 8b
-			15 01 00 00 00 00 02 ab 03
-			15 01 00 00 00 00 02 ac 8d
-			15 01 00 00 00 00 02 ad 03
-			15 01 00 00 00 00 02 ae 8e
-			15 01 00 00 00 00 02 af 00
-			15 01 00 00 00 00 02 b0 71
-			15 01 00 00 00 00 02 b1 00
-			15 01 00 00 00 00 02 b2 84
-			15 01 00 00 00 00 02 b3 00
-			15 01 00 00 00 00 02 b4 a5
-			15 01 00 00 00 00 02 b5 00
-			15 01 00 00 00 00 02 b6 bb
-			15 01 00 00 00 00 02 b7 00
-			15 01 00 00 00 00 02 b8 ce
-			15 01 00 00 00 00 02 b9 00
-			15 01 00 00 00 00 02 ba e0
-			15 01 00 00 00 00 02 bb 00
-			15 01 00 00 00 00 02 bc ef
-			15 01 00 00 00 00 02 bd 00
-			15 01 00 00 00 00 02 be ff
-			15 01 00 00 00 00 02 bf 01
-			15 01 00 00 00 00 02 c0 0b
-			15 01 00 00 00 00 02 c1 01
-			15 01 00 00 00 00 02 c2 38
-			15 01 00 00 00 00 02 c3 01
-			15 01 00 00 00 00 02 c4 5b
-			15 01 00 00 00 00 02 c5 01
-			15 01 00 00 00 00 02 c6 95
-			15 01 00 00 00 00 02 c7 01
-			15 01 00 00 00 00 02 c8 c4
-			15 01 00 00 00 00 02 c9 02
-			15 01 00 00 00 00 02 ca 0d
-			15 01 00 00 00 00 02 cb 02
-			15 01 00 00 00 00 02 cc 4a
-			15 01 00 00 00 00 02 cd 02
-			15 01 00 00 00 00 02 ce 4c
-			15 01 00 00 00 00 02 cf 02
-			15 01 00 00 00 00 02 d0 85
-			15 01 00 00 00 00 02 d1 02
-			15 01 00 00 00 00 02 d2 c3
-			15 01 00 00 00 00 02 d3 02
-			15 01 00 00 00 00 02 d4 e9
-			15 01 00 00 00 00 02 d5 03
-			15 01 00 00 00 00 02 d6 16
-			15 01 00 00 00 00 02 d7 03
-			15 01 00 00 00 00 02 d8 34
-			15 01 00 00 00 00 02 d9 03
-			15 01 00 00 00 00 02 da 56
-			15 01 00 00 00 00 02 db 03
-			15 01 00 00 00 00 02 dc 62
-			15 01 00 00 00 00 02 dd 03
-			15 01 00 00 00 00 02 de 6c
-			15 01 00 00 00 00 02 df 03
-			15 01 00 00 00 00 02 e0 74
-			15 01 00 00 00 00 02 e1 03
-			15 01 00 00 00 00 02 e2 80
-			15 01 00 00 00 00 02 e3 03
-			15 01 00 00 00 00 02 e4 89
-			15 01 00 00 00 00 02 e5 03
-			15 01 00 00 00 00 02 e6 8b
-			15 01 00 00 00 00 02 e7 03
-			15 01 00 00 00 00 02 e8 8d
-			15 01 00 00 00 00 02 e9 03
-			15 01 00 00 00 00 02 ea 8e
-			15 01 00 00 00 00 02 FF 10
-			05 01 00 00 00 00 01 29];
-		qcom,mdss-dsi-off-command = [15 01 00 00 00 00 02 ff 10
-			05 01 00 00 10 00 01 28
-			15 01 00 00 00 00 02 b0 00
-			05 01 00 00 40 00 01 10
-			15 01 00 00 00 00 02 4f 01];
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "burst_mode";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -623,10 +40,594 @@
 		qcom,mdss-dsi-te-check-enable;
 		qcom,mdss-dsi-te-using-te-pin;
 
-		qcom,config-select = <&dsi_dual_sharp_cmd_config0>;
-
-		dsi_dual_sharp_cmd_config0: config0 {
-			qcom,split-mode = "dualctl-split";
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <540>;
+				qcom,mdss-dsi-panel-height = <1920>;
+				qcom,mdss-dsi-h-front-porch = <28>;
+				qcom,mdss-dsi-h-back-porch = <4>;
+				qcom,mdss-dsi-h-pulse-width = <4>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <12>;
+				qcom,mdss-dsi-v-front-porch = <12>;
+				qcom,mdss-dsi-v-pulse-width = <2>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-panel-framerate = <120>;
+				qcom,mdss-dsi-on-command =
+					[15 01 00 00 00 00 02 ff 10
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 ba 07
+					15 01 00 00 00 00 02 c0 00
+					15 01 00 00 00 00 02 bb 10
+					15 01 00 00 00 00 02 d9 00
+					15 01 00 00 00 00 02 ef 70
+					15 01 00 00 00 00 02 f7 80
+					39 01 00 00 00 00 06 3b 03 0e 0c 08 1c
+					15 01 00 00 00 00 02 e9 0e
+					15 01 00 00 00 00 02 ea 0c
+					15 01 00 00 00 00 02 35 00
+					15 01 00 00 00 00 02 c0 00
+					15 01 00 00 00 00 02 ff 20
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 59 6a
+					15 01 00 00 00 00 02 0b 1b
+					15 01 00 00 00 00 02 61 f7
+					15 01 00 00 00 00 02 62 6c
+					15 01 00 00 00 00 02 00 01
+					15 01 00 00 00 00 02 01 55
+					15 01 00 00 00 00 02 04 c8
+					15 01 00 00 00 00 02 05 1a
+					15 01 00 00 00 00 02 0d 93
+					15 01 00 00 00 00 02 0e 93
+					15 01 00 00 00 00 02 0f 7e
+					15 01 00 00 00 00 02 06 69
+					15 01 00 00 00 00 02 07 bc
+					15 01 00 00 00 00 02 10 03
+					15 01 00 00 00 00 02 11 64
+					15 01 00 00 00 00 02 12 5a
+					15 01 00 00 00 00 02 13 40
+					15 01 00 00 00 00 02 14 40
+					15 01 00 00 00 00 02 15 00
+					15 01 00 00 00 00 02 33 13
+					15 01 00 00 00 00 02 5a 40
+					15 01 00 00 00 00 02 5b 40
+					15 01 00 00 00 00 02 5e 80
+					15 01 00 00 00 00 02 ff 24
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 80
+					15 01 00 00 00 00 02 14 80
+					15 01 00 00 00 00 02 01 80
+					15 01 00 00 00 00 02 15 80
+					15 01 00 00 00 00 02 02 80
+					15 01 00 00 00 00 02 16 80
+					15 01 00 00 00 00 02 03 0a
+					15 01 00 00 00 00 02 17 0c
+					15 01 00 00 00 00 02 04 06
+					15 01 00 00 00 00 02 18 08
+					15 01 00 00 00 00 02 05 80
+					15 01 00 00 00 00 02 19 80
+					15 01 00 00 00 00 02 06 80
+					15 01 00 00 00 00 02 1a 80
+					15 01 00 00 00 00 02 07 80
+					15 01 00 00 00 00 02 1b 80
+					15 01 00 00 00 00 02 08 80
+					15 01 00 00 00 00 02 1c 80
+					15 01 00 00 00 00 02 09 80
+					15 01 00 00 00 00 02 1d 80
+					15 01 00 00 00 00 02 0a 80
+					15 01 00 00 00 00 02 1e 80
+					15 01 00 00 00 00 02 0b 1a
+					15 01 00 00 00 00 02 1f 1b
+					15 01 00 00 00 00 02 0c 16
+					15 01 00 00 00 00 02 20 17
+					15 01 00 00 00 00 02 0d 1c
+					15 01 00 00 00 00 02 21 1d
+					15 01 00 00 00 00 02 0e 18
+					15 01 00 00 00 00 02 22 19
+					15 01 00 00 00 00 02 0f 0e
+					15 01 00 00 00 00 02 23 10
+					15 01 00 00 00 00 02 10 80
+					15 01 00 00 00 00 02 24 80
+					15 01 00 00 00 00 02 11 80
+					15 01 00 00 00 00 02 25 80
+					15 01 00 00 00 00 02 12 80
+					15 01 00 00 00 00 02 26 80
+					15 01 00 00 00 00 02 13 80
+					15 01 00 00 00 00 02 27 80
+					15 01 00 00 00 00 02 74 ff
+					15 01 00 00 00 00 02 75 ff
+					15 01 00 00 00 00 02 8d 00
+					15 01 00 00 00 00 02 8e 00
+					15 01 00 00 00 00 02 8f 9c
+					15 01 00 00 00 00 02 90 0c
+					15 01 00 00 00 00 02 91 0e
+					15 01 00 00 00 00 02 d6 00
+					15 01 00 00 00 00 02 d7 20
+					15 01 00 00 00 00 02 d8 00
+					15 01 00 00 00 00 02 d9 88
+					15 01 00 00 00 00 02 e5 05
+					15 01 00 00 00 00 02 e6 10
+					15 01 00 00 00 00 02 54 06
+					15 01 00 00 00 00 02 55 05
+					15 01 00 00 00 00 02 56 04
+					15 01 00 00 00 00 02 58 03
+					15 01 00 00 00 00 02 59 33
+					15 01 00 00 00 00 02 5a 33
+					15 01 00 00 00 00 02 5b 01
+					15 01 00 00 00 00 02 5c 00
+					15 01 00 00 00 00 02 5d 01
+					15 01 00 00 00 00 02 5e 0a
+					15 01 00 00 00 00 02 5f 0a
+					15 01 00 00 00 00 02 60 0a
+					15 01 00 00 00 00 02 61 0a
+					15 01 00 00 00 00 02 62 10
+					15 01 00 00 00 00 02 63 01
+					15 01 00 00 00 00 02 64 00
+					15 01 00 00 00 00 02 65 00
+					15 01 00 00 00 00 02 ef 00
+					15 01 00 00 00 00 02 f0 00
+					15 01 00 00 00 00 02 6d 20
+					15 01 00 00 00 00 02 66 44
+					15 01 00 00 00 00 02 68 01
+					15 01 00 00 00 00 02 69 00
+					15 01 00 00 00 00 02 67 11
+					15 01 00 00 00 00 02 6a 06
+					15 01 00 00 00 00 02 6b 31
+					15 01 00 00 00 00 02 6c 90
+					15 01 00 00 00 00 02 ab c3
+					15 01 00 00 00 00 02 b1 49
+					15 01 00 00 00 00 02 aa 80
+					15 01 00 00 00 00 02 b0 90
+					15 01 00 00 00 00 02 b2 a4
+					15 01 00 00 00 00 02 b3 00
+					15 01 00 00 00 00 02 b4 23
+					15 01 00 00 00 00 02 b5 00
+					15 01 00 00 00 00 02 b6 00
+					15 01 00 00 00 00 02 b7 00
+					15 01 00 00 00 00 02 b8 00
+					15 01 00 00 00 00 02 b9 00
+					15 01 00 00 00 00 02 ba 00
+					15 01 00 00 00 00 02 bb 00
+					15 01 00 00 00 00 02 bc 00
+					15 01 00 00 00 00 02 bd 00
+					15 01 00 00 00 00 02 be 00
+					15 01 00 00 00 00 02 bf 00
+					15 01 00 00 00 00 02 c0 00
+					15 01 00 00 00 00 02 c7 40
+					15 01 00 00 00 00 02 c9 00
+					15 01 00 00 00 00 02 c1 2a
+					15 01 00 00 00 00 02 c2 2a
+					15 01 00 00 00 00 02 c3 00
+					15 01 00 00 00 00 02 c4 00
+					15 01 00 00 00 00 02 c5 00
+					15 01 00 00 00 00 02 c6 00
+					15 01 00 00 00 00 02 c8 ab
+					15 01 00 00 00 00 02 ca 00
+					15 01 00 00 00 00 02 cb 00
+					15 01 00 00 00 00 02 cc 20
+					15 01 00 00 00 00 02 cd 40
+					15 01 00 00 00 00 02 ce a8
+					15 01 00 00 00 00 02 cf a8
+					15 01 00 00 00 00 02 d0 00
+					15 01 00 00 00 00 02 d1 00
+					15 01 00 00 00 00 02 d2 00
+					15 01 00 00 00 00 02 d3 00
+					15 01 00 00 00 00 02 af 01
+					15 01 00 00 00 00 02 a4 1e
+					15 01 00 00 00 00 02 95 41
+					15 01 00 00 00 00 02 96 03
+					15 01 00 00 00 00 02 98 00
+					15 01 00 00 00 00 02 9a 9a
+					15 01 00 00 00 00 02 9b 03
+					15 01 00 00 00 00 02 9d 80
+					15 01 00 00 00 00 02 ff 26
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 fa d0
+					15 01 00 00 00 00 02 6b 80
+					15 01 00 00 00 00 02 6c 5c
+					15 01 00 00 00 00 02 6d 0c
+					15 01 00 00 00 00 02 6e 0e
+					15 01 00 00 00 00 02 58 01
+					15 01 00 00 00 00 02 59 15
+					15 01 00 00 00 00 02 5a 01
+					15 01 00 00 00 00 02 5b 00
+					15 01 00 00 00 00 02 5c 01
+					15 01 00 00 00 00 02 5d 2b
+					15 01 00 00 00 00 02 74 00
+					15 01 00 00 00 00 02 75 ba
+					15 01 00 00 00 00 02 81 0a
+					15 01 00 00 00 00 02 4e 81
+					15 01 00 00 00 00 02 4f 83
+					15 01 00 00 00 00 02 51 00
+					15 01 00 00 00 00 02 53 4d
+					15 01 00 00 00 00 02 54 03
+					15 01 00 00 00 00 02 ff e0
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 b2 81
+					15 01 00 00 00 00 02 62 28
+					15 01 00 00 00 00 02 a2 09
+					15 01 00 00 00 00 02 b3 01
+					15 01 00 00 00 00 02 ed 00
+					15 01 00 00 00 00 02 ff 10
+					05 01 00 00 78 00 01 11
+					15 01 00 00 00 00 02 ff 20
+					15 01 00 00 00 00 02 75 00
+					15 01 00 00 00 00 02 76 71
+					15 01 00 00 00 00 02 77 00
+					15 01 00 00 00 00 02 78 84
+					15 01 00 00 00 00 02 79 00
+					15 01 00 00 00 00 02 7a a5
+					15 01 00 00 00 00 02 7b 00
+					15 01 00 00 00 00 02 7c bb
+					15 01 00 00 00 00 02 7d 00
+					15 01 00 00 00 00 02 7e ce
+					15 01 00 00 00 00 02 7f 00
+					15 01 00 00 00 00 02 80 e0
+					15 01 00 00 00 00 02 81 00
+					15 01 00 00 00 00 02 82 ef
+					15 01 00 00 00 00 02 83 00
+					15 01 00 00 00 00 02 84 ff
+					15 01 00 00 00 00 02 85 01
+					15 01 00 00 00 00 02 86 0b
+					15 01 00 00 00 00 02 87 01
+					15 01 00 00 00 00 02 88 38
+					15 01 00 00 00 00 02 89 01
+					15 01 00 00 00 00 02 8a 5b
+					15 01 00 00 00 00 02 8b 01
+					15 01 00 00 00 00 02 8c 95
+					15 01 00 00 00 00 02 8d 01
+					15 01 00 00 00 00 02 8e c4
+					15 01 00 00 00 00 02 8f 02
+					15 01 00 00 00 00 02 90 0d
+					15 01 00 00 00 00 02 91 02
+					15 01 00 00 00 00 02 92 4a
+					15 01 00 00 00 00 02 93 02
+					15 01 00 00 00 00 02 94 4c
+					15 01 00 00 00 00 02 95 02
+					15 01 00 00 00 00 02 96 85
+					15 01 00 00 00 00 02 97 02
+					15 01 00 00 00 00 02 98 c3
+					15 01 00 00 00 00 02 99 02
+					15 01 00 00 00 00 02 9a e9
+					15 01 00 00 00 00 02 9b 03
+					15 01 00 00 00 00 02 9c 16
+					15 01 00 00 00 00 02 9d 03
+					15 01 00 00 00 00 02 9e 34
+					15 01 00 00 00 00 02 9f 03
+					15 01 00 00 00 00 02 a0 56
+					15 01 00 00 00 00 02 a2 03
+					15 01 00 00 00 00 02 a3 62
+					15 01 00 00 00 00 02 a4 03
+					15 01 00 00 00 00 02 a5 6c
+					15 01 00 00 00 00 02 a6 03
+					15 01 00 00 00 00 02 a7 74
+					15 01 00 00 00 00 02 a9 03
+					15 01 00 00 00 00 02 aa 80
+					15 01 00 00 00 00 02 ab 03
+					15 01 00 00 00 00 02 ac 89
+					15 01 00 00 00 00 02 ad 03
+					15 01 00 00 00 00 02 ae 8b
+					15 01 00 00 00 00 02 af 03
+					15 01 00 00 00 00 02 b0 8d
+					15 01 00 00 00 00 02 b1 03
+					15 01 00 00 00 00 02 b2 8e
+					15 01 00 00 00 00 02 b3 00
+					15 01 00 00 00 00 02 b4 71
+					15 01 00 00 00 00 02 b5 00
+					15 01 00 00 00 00 02 b6 84
+					15 01 00 00 00 00 02 b7 00
+					15 01 00 00 00 00 02 b8 a5
+					15 01 00 00 00 00 02 b9 00
+					15 01 00 00 00 00 02 ba bb
+					15 01 00 00 00 00 02 bb 00
+					15 01 00 00 00 00 02 bc ce
+					15 01 00 00 00 00 02 bd 00
+					15 01 00 00 00 00 02 be e0
+					15 01 00 00 00 00 02 bf 00
+					15 01 00 00 00 00 02 c0 ef
+					15 01 00 00 00 00 02 c1 00
+					15 01 00 00 00 00 02 c2 ff
+					15 01 00 00 00 00 02 c3 01
+					15 01 00 00 00 00 02 c4 0b
+					15 01 00 00 00 00 02 c5 01
+					15 01 00 00 00 00 02 c6 38
+					15 01 00 00 00 00 02 c7 01
+					15 01 00 00 00 00 02 c8 5b
+					15 01 00 00 00 00 02 c9 01
+					15 01 00 00 00 00 02 ca 95
+					15 01 00 00 00 00 02 cb 01
+					15 01 00 00 00 00 02 cc c4
+					15 01 00 00 00 00 02 cd 02
+					15 01 00 00 00 00 02 ce 0d
+					15 01 00 00 00 00 02 cf 02
+					15 01 00 00 00 00 02 d0 4a
+					15 01 00 00 00 00 02 d1 02
+					15 01 00 00 00 00 02 d2 4c
+					15 01 00 00 00 00 02 d3 02
+					15 01 00 00 00 00 02 d4 85
+					15 01 00 00 00 00 02 d5 02
+					15 01 00 00 00 00 02 d6 c3
+					15 01 00 00 00 00 02 d7 02
+					15 01 00 00 00 00 02 d8 e9
+					15 01 00 00 00 00 02 d9 03
+					15 01 00 00 00 00 02 da 16
+					15 01 00 00 00 00 02 db 03
+					15 01 00 00 00 00 02 dc 34
+					15 01 00 00 00 00 02 dd 03
+					15 01 00 00 00 00 02 de 56
+					15 01 00 00 00 00 02 df 03
+					15 01 00 00 00 00 02 e0 62
+					15 01 00 00 00 00 02 e1 03
+					15 01 00 00 00 00 02 e2 6c
+					15 01 00 00 00 00 02 e3 03
+					15 01 00 00 00 00 02 e4 74
+					15 01 00 00 00 00 02 e5 03
+					15 01 00 00 00 00 02 e6 80
+					15 01 00 00 00 00 02 e7 03
+					15 01 00 00 00 00 02 e8 89
+					15 01 00 00 00 00 02 e9 03
+					15 01 00 00 00 00 02 ea 8b
+					15 01 00 00 00 00 02 eb 03
+					15 01 00 00 00 00 02 ec 8d
+					15 01 00 00 00 00 02 ed 03
+					15 01 00 00 00 00 02 ee 8e
+					15 01 00 00 00 00 02 ef 00
+					15 01 00 00 00 00 02 f0 71
+					15 01 00 00 00 00 02 f1 00
+					15 01 00 00 00 00 02 f2 84
+					15 01 00 00 00 00 02 f3 00
+					15 01 00 00 00 00 02 f4 a5
+					15 01 00 00 00 00 02 f5 00
+					15 01 00 00 00 00 02 f6 bb
+					15 01 00 00 00 00 02 f7 00
+					15 01 00 00 00 00 02 f8 ce
+					15 01 00 00 00 00 02 f9 00
+					15 01 00 00 00 00 02 fa e0
+					15 01 00 00 00 00 02 ff 21
+					15 01 00 00 00 00 02 fb 01
+					15 01 00 00 00 00 02 00 00
+					15 01 00 00 00 00 02 01 ef
+					15 01 00 00 00 00 02 02 00
+					15 01 00 00 00 00 02 03 ff
+					15 01 00 00 00 00 02 04 01
+					15 01 00 00 00 00 02 05 0b
+					15 01 00 00 00 00 02 06 01
+					15 01 00 00 00 00 02 07 38
+					15 01 00 00 00 00 02 08 01
+					15 01 00 00 00 00 02 09 5b
+					15 01 00 00 00 00 02 0a 01
+					15 01 00 00 00 00 02 0b 95
+					15 01 00 00 00 00 02 0c 01
+					15 01 00 00 00 00 02 0d c4
+					15 01 00 00 00 00 02 0e 02
+					15 01 00 00 00 00 02 0f 0d
+					15 01 00 00 00 00 02 10 02
+					15 01 00 00 00 00 02 11 4a
+					15 01 00 00 00 00 02 12 02
+					15 01 00 00 00 00 02 13 4c
+					15 01 00 00 00 00 02 14 02
+					15 01 00 00 00 00 02 15 85
+					15 01 00 00 00 00 02 16 02
+					15 01 00 00 00 00 02 17 c3
+					15 01 00 00 00 00 02 18 02
+					15 01 00 00 00 00 02 19 e9
+					15 01 00 00 00 00 02 1a 03
+					15 01 00 00 00 00 02 1b 16
+					15 01 00 00 00 00 02 1c 03
+					15 01 00 00 00 00 02 1d 34
+					15 01 00 00 00 00 02 1e 03
+					15 01 00 00 00 00 02 1f 56
+					15 01 00 00 00 00 02 20 03
+					15 01 00 00 00 00 02 21 62
+					15 01 00 00 00 00 02 22 03
+					15 01 00 00 00 00 02 23 6c
+					15 01 00 00 00 00 02 24 03
+					15 01 00 00 00 00 02 25 74
+					15 01 00 00 00 00 02 26 03
+					15 01 00 00 00 00 02 27 80
+					15 01 00 00 00 00 02 28 03
+					15 01 00 00 00 00 02 29 89
+					15 01 00 00 00 00 02 2a 03
+					15 01 00 00 00 00 02 2b 8b
+					15 01 00 00 00 00 02 2d 03
+					15 01 00 00 00 00 02 2f 8d
+					15 01 00 00 00 00 02 30 03
+					15 01 00 00 00 00 02 31 8e
+					15 01 00 00 00 00 02 32 00
+					15 01 00 00 00 00 02 33 71
+					15 01 00 00 00 00 02 34 00
+					15 01 00 00 00 00 02 35 84
+					15 01 00 00 00 00 02 36 00
+					15 01 00 00 00 00 02 37 a5
+					15 01 00 00 00 00 02 38 00
+					15 01 00 00 00 00 02 39 bb
+					15 01 00 00 00 00 02 3a 00
+					15 01 00 00 00 00 02 3b ce
+					15 01 00 00 00 00 02 3d 00
+					15 01 00 00 00 00 02 3f e0
+					15 01 00 00 00 00 02 40 00
+					15 01 00 00 00 00 02 41 ef
+					15 01 00 00 00 00 02 42 00
+					15 01 00 00 00 00 02 43 ff
+					15 01 00 00 00 00 02 44 01
+					15 01 00 00 00 00 02 45 0b
+					15 01 00 00 00 00 02 46 01
+					15 01 00 00 00 00 02 47 38
+					15 01 00 00 00 00 02 48 01
+					15 01 00 00 00 00 02 49 5b
+					15 01 00 00 00 00 02 4a 01
+					15 01 00 00 00 00 02 4b 95
+					15 01 00 00 00 00 02 4c 01
+					15 01 00 00 00 00 02 4d c4
+					15 01 00 00 00 00 02 4e 02
+					15 01 00 00 00 00 02 4f 0d
+					15 01 00 00 00 00 02 50 02
+					15 01 00 00 00 00 02 51 4a
+					15 01 00 00 00 00 02 52 02
+					15 01 00 00 00 00 02 53 4c
+					15 01 00 00 00 00 02 54 02
+					15 01 00 00 00 00 02 55 85
+					15 01 00 00 00 00 02 56 02
+					15 01 00 00 00 00 02 58 c3
+					15 01 00 00 00 00 02 59 02
+					15 01 00 00 00 00 02 5a e9
+					15 01 00 00 00 00 02 5b 03
+					15 01 00 00 00 00 02 5c 16
+					15 01 00 00 00 00 02 5d 03
+					15 01 00 00 00 00 02 5e 34
+					15 01 00 00 00 00 02 5f 03
+					15 01 00 00 00 00 02 60 56
+					15 01 00 00 00 00 02 61 03
+					15 01 00 00 00 00 02 62 62
+					15 01 00 00 00 00 02 63 03
+					15 01 00 00 00 00 02 64 6c
+					15 01 00 00 00 00 02 65 03
+					15 01 00 00 00 00 02 66 74
+					15 01 00 00 00 00 02 67 03
+					15 01 00 00 00 00 02 68 80
+					15 01 00 00 00 00 02 69 03
+					15 01 00 00 00 00 02 6a 89
+					15 01 00 00 00 00 02 6b 03
+					15 01 00 00 00 00 02 6c 8b
+					15 01 00 00 00 00 02 6d 03
+					15 01 00 00 00 00 02 6e 8d
+					15 01 00 00 00 00 02 6f 03
+					15 01 00 00 00 00 02 70 8e
+					15 01 00 00 00 00 02 71 00
+					15 01 00 00 00 00 02 72 71
+					15 01 00 00 00 00 02 73 00
+					15 01 00 00 00 00 02 74 84
+					15 01 00 00 00 00 02 75 00
+					15 01 00 00 00 00 02 76 a5
+					15 01 00 00 00 00 02 77 00
+					15 01 00 00 00 00 02 78 bb
+					15 01 00 00 00 00 02 79 00
+					15 01 00 00 00 00 02 7a ce
+					15 01 00 00 00 00 02 7b 00
+					15 01 00 00 00 00 02 7c e0
+					15 01 00 00 00 00 02 7d 00
+					15 01 00 00 00 00 02 7e ef
+					15 01 00 00 00 00 02 7f 00
+					15 01 00 00 00 00 02 80 ff
+					15 01 00 00 00 00 02 81 01
+					15 01 00 00 00 00 02 82 0b
+					15 01 00 00 00 00 02 83 01
+					15 01 00 00 00 00 02 84 38
+					15 01 00 00 00 00 02 85 01
+					15 01 00 00 00 00 02 86 5b
+					15 01 00 00 00 00 02 87 01
+					15 01 00 00 00 00 02 88 95
+					15 01 00 00 00 00 02 89 01
+					15 01 00 00 00 00 02 8a c4
+					15 01 00 00 00 00 02 8b 02
+					15 01 00 00 00 00 02 8c 0d
+					15 01 00 00 00 00 02 8d 02
+					15 01 00 00 00 00 02 8e 4a
+					15 01 00 00 00 00 02 8f 02
+					15 01 00 00 00 00 02 90 4c
+					15 01 00 00 00 00 02 91 02
+					15 01 00 00 00 00 02 92 85
+					15 01 00 00 00 00 02 93 02
+					15 01 00 00 00 00 02 94 c3
+					15 01 00 00 00 00 02 95 02
+					15 01 00 00 00 00 02 96 e9
+					15 01 00 00 00 00 02 97 03
+					15 01 00 00 00 00 02 98 16
+					15 01 00 00 00 00 02 99 03
+					15 01 00 00 00 00 02 9a 34
+					15 01 00 00 00 00 02 9b 03
+					15 01 00 00 00 00 02 9c 56
+					15 01 00 00 00 00 02 9d 03
+					15 01 00 00 00 00 02 9e 62
+					15 01 00 00 00 00 02 9f 03
+					15 01 00 00 00 00 02 a0 6c
+					15 01 00 00 00 00 02 a2 03
+					15 01 00 00 00 00 02 a3 74
+					15 01 00 00 00 00 02 a4 03
+					15 01 00 00 00 00 02 a5 80
+					15 01 00 00 00 00 02 a6 03
+					15 01 00 00 00 00 02 a7 89
+					15 01 00 00 00 00 02 a9 03
+					15 01 00 00 00 00 02 aa 8b
+					15 01 00 00 00 00 02 ab 03
+					15 01 00 00 00 00 02 ac 8d
+					15 01 00 00 00 00 02 ad 03
+					15 01 00 00 00 00 02 ae 8e
+					15 01 00 00 00 00 02 af 00
+					15 01 00 00 00 00 02 b0 71
+					15 01 00 00 00 00 02 b1 00
+					15 01 00 00 00 00 02 b2 84
+					15 01 00 00 00 00 02 b3 00
+					15 01 00 00 00 00 02 b4 a5
+					15 01 00 00 00 00 02 b5 00
+					15 01 00 00 00 00 02 b6 bb
+					15 01 00 00 00 00 02 b7 00
+					15 01 00 00 00 00 02 b8 ce
+					15 01 00 00 00 00 02 b9 00
+					15 01 00 00 00 00 02 ba e0
+					15 01 00 00 00 00 02 bb 00
+					15 01 00 00 00 00 02 bc ef
+					15 01 00 00 00 00 02 bd 00
+					15 01 00 00 00 00 02 be ff
+					15 01 00 00 00 00 02 bf 01
+					15 01 00 00 00 00 02 c0 0b
+					15 01 00 00 00 00 02 c1 01
+					15 01 00 00 00 00 02 c2 38
+					15 01 00 00 00 00 02 c3 01
+					15 01 00 00 00 00 02 c4 5b
+					15 01 00 00 00 00 02 c5 01
+					15 01 00 00 00 00 02 c6 95
+					15 01 00 00 00 00 02 c7 01
+					15 01 00 00 00 00 02 c8 c4
+					15 01 00 00 00 00 02 c9 02
+					15 01 00 00 00 00 02 ca 0d
+					15 01 00 00 00 00 02 cb 02
+					15 01 00 00 00 00 02 cc 4a
+					15 01 00 00 00 00 02 cd 02
+					15 01 00 00 00 00 02 ce 4c
+					15 01 00 00 00 00 02 cf 02
+					15 01 00 00 00 00 02 d0 85
+					15 01 00 00 00 00 02 d1 02
+					15 01 00 00 00 00 02 d2 c3
+					15 01 00 00 00 00 02 d3 02
+					15 01 00 00 00 00 02 d4 e9
+					15 01 00 00 00 00 02 d5 03
+					15 01 00 00 00 00 02 d6 16
+					15 01 00 00 00 00 02 d7 03
+					15 01 00 00 00 00 02 d8 34
+					15 01 00 00 00 00 02 d9 03
+					15 01 00 00 00 00 02 da 56
+					15 01 00 00 00 00 02 db 03
+					15 01 00 00 00 00 02 dc 62
+					15 01 00 00 00 00 02 dd 03
+					15 01 00 00 00 00 02 de 6c
+					15 01 00 00 00 00 02 df 03
+					15 01 00 00 00 00 02 e0 74
+					15 01 00 00 00 00 02 e1 03
+					15 01 00 00 00 00 02 e2 80
+					15 01 00 00 00 00 02 e3 03
+					15 01 00 00 00 00 02 e4 89
+					15 01 00 00 00 00 02 e5 03
+					15 01 00 00 00 00 02 e6 8b
+					15 01 00 00 00 00 02 e7 03
+					15 01 00 00 00 00 02 e8 8d
+					15 01 00 00 00 00 02 e9 03
+					15 01 00 00 00 00 02 ea 8e
+					15 01 00 00 00 00 02 FF 10
+					05 01 00 00 00 00 01 29];
+				qcom,mdss-dsi-off-command =
+					[15 01 00 00 00 00 02 ff 10
+					05 01 00 00 10 00 01 28
+					15 01 00 00 00 00 02 b0 00
+					05 01 00 00 40 00 01 10
+					15 01 00 00 00 00 02 4f 01];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+			};
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sim-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sim-cmd.dtsi
index 1f08294..50da1bf 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sim-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sim-cmd.dtsi
@@ -14,27 +14,12 @@
 	dsi_sim_cmd: qcom,mdss_dsi_sim_cmd{
 		qcom,mdss-dsi-panel-name = "Simulator cmd mode dsi panel";
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <640>;
-		qcom,mdss-dsi-panel-height = <480>;
-		qcom,mdss-dsi-h-front-porch = <20>;
-		qcom,mdss-dsi-h-back-porch = <20>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <16>;
-		qcom,mdss-dsi-v-front-porch = <4>;
-		qcom,mdss-dsi-v-pulse-width = <1>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-color-order = "rgb_swap_rgb";
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -42,11 +27,6 @@
 		qcom,mdss-dsi-lane-1-state;
 		qcom,mdss-dsi-lane-2-state;
 		qcom,mdss-dsi-lane-3-state;
-		qcom,mdss-dsi-hor-line-idle = <0 40 256>,
-						<40 120 128>,
-						<120 240 64>;
-		qcom,mdss-dsi-panel-timings = [cd 32 22 00 60 64 26 34 29 03
-									04 00];
 		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
 		qcom,mdss-dsi-t-clk-post = <0x03>;
 		qcom,mdss-dsi-t-clk-pre = <0x27>;
@@ -65,33 +45,60 @@
 			17000 15500 30000 8000 3000>;
 		qcom,mdss-dsi-panel-peak-brightness = <4200000>;
 		qcom,mdss-dsi-panel-blackness-level = <3230>;
-		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 b0 03
-			05 01 00 00 0a 00 01 00
-			/* Soft reset, wait 10ms */
-			15 01 00 00 0a 00 02 3a 77
-			/* Set Pixel format (24 bpp) */
-			39 01 00 00 0a 00 05 2a 00 00 04 ff
-			/* Set Column address */
-			39 01 00 00 0a 00 05 2b 00 00 05 9f
-			/* Set page address */
-			15 01 00 00 0a 00 02 35 00
-			/* Set tear on */
-			39 01 00 00 0a 00 03 44 00 00
-			/* Set tear scan line */
-			15 01 00 00 0a 00 02 51 ff
-			/* write display brightness */
-			15 01 00 00 0a 00 02 53 24
-			 /* write control brightness */
-			15 01 00 00 0a 00 02 55 00
-			/* CABC brightness */
-			05 01 00 00 78 00 01 11
-			/* exit sleep mode, wait 120ms */
-			05 01 00 00 10 00 01 29];
-			/* Set display on, wait 16ms */
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
-					05 01 00 00 78 00 02 10 00];
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
 		qcom,panel-ack-disabled;
+
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <640>;
+				qcom,mdss-dsi-panel-height = <480>;
+				qcom,mdss-dsi-h-front-porch = <20>;
+				qcom,mdss-dsi-h-back-porch = <20>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <16>;
+				qcom,mdss-dsi-v-front-porch = <4>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-hor-line-idle = <0 40 256>,
+								<40 120 128>,
+								<120 240 64>;
+				qcom,mdss-dsi-panel-timings =
+					[cd 32 22 00 60 64 26 34 29 03 04 00];
+				qcom,mdss-dsi-on-command =
+					[29 01 00 00 00 00 02 b0 03
+					05 01 00 00 0a 00 01 00
+					/* Soft reset, wait 10ms */
+					15 01 00 00 0a 00 02 3a 77
+					/* Set Pixel format (24 bpp) */
+					39 01 00 00 0a 00 05 2a 00 00 04 ff
+					/* Set Column address */
+					39 01 00 00 0a 00 05 2b 00 00 05 9f
+					/* Set page address */
+					15 01 00 00 0a 00 02 35 00
+					/* Set tear on */
+					39 01 00 00 0a 00 03 44 00 00
+					/* Set tear scan line */
+					15 01 00 00 0a 00 02 51 ff
+					/* write display brightness */
+					15 01 00 00 0a 00 02 53 24
+					 /* write control brightness */
+					15 01 00 00 0a 00 02 55 00
+					/* CABC brightness */
+					05 01 00 00 78 00 01 11
+					/* exit sleep mode, wait 120ms */
+					05 01 00 00 10 00 01 29];
+					/* Set display on, wait 16ms */
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-cmd.dtsi
index 36f36fb..895cbc5 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-cmd.dtsi
@@ -14,27 +14,12 @@
 	dsi_dual_sim_cmd: qcom,mdss_dsi_dual_sim_cmd {
 		qcom,mdss-dsi-panel-name = "Sim dual cmd mode dsi panel";
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1280>;
-		qcom,mdss-dsi-panel-height = <1440>;
-		qcom,mdss-dsi-h-front-porch = <120>;
-		qcom,mdss-dsi-h-back-porch = <44>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <4>;
-		qcom,mdss-dsi-v-front-porch = <8>;
-		qcom,mdss-dsi-v-pulse-width = <4>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-color-order = "rgb_swap_rgb";
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -57,33 +42,80 @@
 		qcom,mdss-dsi-te-check-enable;
 		qcom,mdss-dsi-te-using-wd;
 		qcom,mdss-dsi-te-using-te-pin;
-		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 b0 03
-			05 01 00 00 0a 00 01 00
-			/* Soft reset, wait 10ms */
-			15 01 00 00 0a 00 02 3a 77
-			/* Set Pixel format (24 bpp) */
-			39 01 00 00 0a 00 05 2a 00 00 04 ff
-			/* Set Column address */
-			39 01 00 00 0a 00 05 2b 00 00 05 9f
-			/* Set page address */
-			15 01 00 00 0a 00 02 35 00
-			/* Set tear on */
-			39 01 00 00 0a 00 03 44 00 00
-			/* Set tear scan line */
-			15 01 00 00 0a 00 02 51 ff
-			/* write display brightness */
-			15 01 00 00 0a 00 02 53 24
-			 /* write control brightness */
-			15 01 00 00 0a 00 02 55 00
-			/* CABC brightness */
-			05 01 00 00 78 00 01 11
-			/* exit sleep mode, wait 120ms */
-			05 01 00 00 10 00 01 29];
-			/* Set display on, wait 16ms */
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
-					05 01 00 00 78 00 02 10 00];
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
 		qcom,panel-ack-disabled;
+
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <540>;
+				qcom,mdss-dsi-panel-height = <1920>;
+				qcom,mdss-dsi-h-front-porch = <28>;
+				qcom,mdss-dsi-h-back-porch = <4>;
+				qcom,mdss-dsi-h-pulse-width = <4>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <12>;
+				qcom,mdss-dsi-v-front-porch = <12>;
+				qcom,mdss-dsi-v-pulse-width = <2>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-panel-framerate = <120>;
+				qcom,mdss-dsi-on-command =
+					[/* exit sleep mode, wait 0ms */
+					05 01 00 00 00 00 01 29];
+					/* Set display on, wait 16ms */
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 00 00 02 28 00
+					05 01 00 00 00 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+			};
+			timing@1{
+				qcom,mdss-dsi-panel-width = <1280>;
+				qcom,mdss-dsi-panel-height = <1440>;
+				qcom,mdss-dsi-h-front-porch = <120>;
+				qcom,mdss-dsi-h-back-porch = <44>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <4>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <4>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command =
+					[/* exit sleep mode, wait 0ms */
+					05 01 00 00 00 00 01 29];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 00 00 02 28 00
+					05 01 00 00 00 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+			};
+			timing@2{
+				qcom,mdss-dsi-panel-width = <1080>;
+				qcom,mdss-dsi-panel-height = <3840>;
+				qcom,mdss-dsi-h-front-porch = <30>;
+				qcom,mdss-dsi-h-back-porch = <100>;
+				qcom,mdss-dsi-h-pulse-width = <4>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <7>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-framerate = <40>;
+				qcom,mdss-dsi-on-command =
+					[/* exit sleep mode, wait 0ms */
+					05 01 00 00 00 00 01 29];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 00 00 02 28 00
+					05 01 00 00 00 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-video.dtsi
index cca28c7..dbfedb9 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sim-dualmipi-video.dtsi
@@ -14,26 +14,11 @@
 	dsi_dual_sim_vid: qcom,mdss_dsi_dual_sim_video {
 		qcom,mdss-dsi-panel-name = "Sim dual video mode dsi panel";
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <1280>;
-		qcom,mdss-dsi-panel-height = <1440>;
-		qcom,mdss-dsi-h-front-porch = <120>;
-		qcom,mdss-dsi-h-back-porch = <44>;
-		qcom,mdss-dsi-h-pulse-width = <16>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <4>;
-		qcom,mdss-dsi-v-front-porch = <8>;
-		qcom,mdss-dsi-v-pulse-width = <4>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -45,11 +30,32 @@
 		qcom,mdss-dsi-bl-max-level = <4095>;
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
-					05 01 00 00 78 00 02 10 00];
-		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
 		qcom,panel-ack-disabled;
+
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <1280>;
+				qcom,mdss-dsi-panel-height = <1440>;
+				qcom,mdss-dsi-h-front-porch = <120>;
+				qcom,mdss-dsi-h-back-porch = <44>;
+				qcom,mdss-dsi-h-pulse-width = <16>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <4>;
+				qcom,mdss-dsi-v-front-porch = <8>;
+				qcom,mdss-dsi-v-pulse-width = <4>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command =
+					[05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sim-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sim-video.dtsi
index 98a1f61..40bedd0 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sim-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sim-video.dtsi
@@ -14,22 +14,8 @@
 	dsi_sim_vid: qcom,mdss_dsi_sim_video {
 		qcom,mdss-dsi-panel-name = "Simulator video mode dsi panel";
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
-		qcom,mdss-dsi-panel-framerate = <60>;
 		qcom,mdss-dsi-virtual-channel-id = <0>;
 		qcom,mdss-dsi-stream = <0>;
-		qcom,mdss-dsi-panel-width = <640>;
-		qcom,mdss-dsi-panel-height = <480>;
-		qcom,mdss-dsi-h-front-porch = <8>;
-		qcom,mdss-dsi-h-back-porch = <8>;
-		qcom,mdss-dsi-h-pulse-width = <8>;
-		qcom,mdss-dsi-h-sync-skew = <0>;
-		qcom,mdss-dsi-v-back-porch = <6>;
-		qcom,mdss-dsi-v-front-porch = <6>;
-		qcom,mdss-dsi-v-pulse-width = <2>;
-		qcom,mdss-dsi-h-left-border = <0>;
-		qcom,mdss-dsi-h-right-border = <0>;
-		qcom,mdss-dsi-v-top-border = <0>;
-		qcom,mdss-dsi-v-bottom-border = <0>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-underflow-color = <0xff>;
 		qcom,mdss-dsi-border-color = <0>;
@@ -38,11 +24,6 @@
 			17000 15500 30000 8000 3000>;
 		qcom,mdss-dsi-panel-peak-brightness = <4200000>;
 		qcom,mdss-dsi-panel-blackness-level = <3230>;
-		qcom,mdss-dsi-on-command = [32 01 00 00 00 00 02 00 00];
-		qcom,mdss-dsi-off-command = [22 01 00 00 00 00 02 00 00];
-		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
-		qcom,mdss-dsi-h-sync-pulse = <0>;
 		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
 		qcom,mdss-dsi-bllp-eof-power-mode;
 		qcom,mdss-dsi-bllp-power-mode;
@@ -50,13 +31,39 @@
 		qcom,mdss-dsi-lane-1-state;
 		qcom,mdss-dsi-lane-2-state;
 		qcom,mdss-dsi-lane-3-state;
-		qcom,mdss-dsi-panel-timings =
-					[00 00 00 00 00 00 00 00 00 00 00 00];
 		qcom,mdss-dsi-t-clk-post = <0x04>;
 		qcom,mdss-dsi-t-clk-pre = <0x1b>;
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-reset-sequence = <1 0>, <0 0>, <1 0>;
 		qcom,panel-ack-disabled;
+
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <640>;
+				qcom,mdss-dsi-panel-height = <480>;
+				qcom,mdss-dsi-h-front-porch = <8>;
+				qcom,mdss-dsi-h-back-porch = <8>;
+				qcom,mdss-dsi-h-pulse-width = <8>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <6>;
+				qcom,mdss-dsi-v-front-porch = <6>;
+				qcom,mdss-dsi-v-pulse-width = <2>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-panel-timings =
+					[00 00 00 00 00 00 00 00 00 00 00 00];
+				qcom,mdss-dsi-on-command =
+					[32 01 00 00 00 00 02 00 00];
+				qcom,mdss-dsi-off-command =
+					[22 01 00 00 00 00 02 00 00];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-gt3746a6-2900mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-gt3746a6-2900mah.dtsi
new file mode 100644
index 0000000..95dd07e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-gt3746a6-2900mah.dtsi
@@ -0,0 +1,81 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+qcom,gt3746a6_2900mah {
+	/* #GT3746A6_2900mAh_averaged_MasterSlave_May11th2017*/
+	qcom,max-voltage-uv = <4350000>;
+	qcom,fg-cc-cv-threshold-mv = <4340>;
+	qcom,fastchg-current-ma = <2900>;
+	qcom,batt-id-kohm = <121>;
+	qcom,battery-beta = <3435>;
+	qcom,battery-type = "GT3746A6_2900mah_averaged_masterslave_may11th2017";
+	qcom,checksum = <0xDF27>;
+	qcom,gui-version = "PMI8998GUI - 2.0.0.57";
+	qcom,fg-profile-data = [
+		 C9 1F 44 05
+		 A5 0A 27 06
+		 F0 1C 07 01
+		 49 F2 91 05
+		 C3 17 42 23
+		 69 45 E8 52
+		 58 00 00 00
+		 0E 00 00 00
+		 00 00 DF A2
+		 12 CD 0C C3
+		 19 00 08 00
+		 89 C2 A5 ED
+		 DF 05 1A 01
+		 C0 05 10 12
+		 03 CA C2 32
+		 32 06 09 20
+		 27 00 14 00
+		 69 20 CD 04
+		 F1 0A E3 05
+		 12 1D 59 01
+		 A3 ED D1 05
+		 95 18 27 23
+		 35 45 6D 53
+		 5F 00 00 00
+		 0E 00 00 00
+		 00 00 0A D5
+		 A6 B5 D0 D2
+		 14 00 00 00
+		 52 F2 A5 ED
+		 57 06 AA F2
+		 29 F4 A5 0B
+		 4D FD FA 1A
+		 AD 33 CC FF
+		 07 10 00 00
+		 27 0B 99 45
+		 14 00 40 00
+		 26 02 0A FA
+		 FF 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+	];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 02fedbe..56e74be 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -34,14 +34,10 @@
 				<GIC_SPI 369 IRQ_TYPE_EDGE_RISING>,
 				<GIC_SPI 370 IRQ_TYPE_EDGE_RISING>,
 				<GIC_SPI 371 IRQ_TYPE_EDGE_RISING>;
-		clock-names = "gcc_ddrss_gpu_axi_clk",
-				"gcc_gpu_memnoc_gfx_clk",
-				"gpu_cc_ahb_clk",
-				"gpu_cc_cx_gmu_clk";
-		clocks = <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>,
-			<&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
-			<&clock_gpucc GPU_CC_AHB_CLK>,
-			<&clock_gpucc GPU_CC_CX_GMU_CLK>;
+		clock-names =	"gcc_gpu_memnoc_gfx_clk",
+				"gpu_cc_ahb_clk";
+		clocks = <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
+			<&clock_gpucc GPU_CC_AHB_CLK>;
 		attach-impl-defs =
 				<0x6000 0x2378>,
 				<0x6060 0x1055>,
diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
index bc0b118..0d2f9e8 100644
--- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -85,7 +85,7 @@
 		compatible = "qcom,msm-pcm-loopback";
 	};
 
-	qcom,msm-dai-mi2s {
+	msm_dai_mi2s: qcom,msm-dai-mi2s {
 		compatible = "qcom,msm-dai-mi2s";
 		dai_mi2s0: qcom,msm-dai-q6-mi2s-prim {
 			compatible = "qcom,msm-dai-q6-mi2s";
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 5d71f2d..5f23b91 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -652,6 +652,27 @@
 		reg = <0x1 SPMI_USID>;
 		#address-cells = <2>;
 		#size-cells = <0>;
+
+		pm660_haptics: qcom,haptics@c000 {
+			compatible = "qcom,qpnp-haptics";
+			reg = <0xc000 0x100>;
+			interrupts = <0x1 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+				     <0x1 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+			interrupt-names = "hap-sc-irq", "hap-play-irq";
+			qcom,pmic-revid = <&pm660_revid>;
+			qcom,pmic-misc = <&pm660_misc>;
+			qcom,misc-clk-trim-error-reg = <0xf3>;
+			qcom,actuator-type = <0>;
+			qcom,play-mode = "direct";
+			qcom,vmax-mv = <3200>;
+			qcom,ilim-ma = <800>;
+			qcom,sc-dbc-cycles = <8>;
+			qcom,wave-play-rate-us = <6667>;
+			qcom,en-brake;
+			qcom,lra-high-z = "opt0";
+			qcom,lra-auto-res-mode = "qwd";
+			qcom,lra-res-cal-period = <4>;
+		};
 	};
 };
 
diff --git a/arch/arm64/boot/dts/qcom/pm660l.dtsi b/arch/arm64/boot/dts/qcom/pm660l.dtsi
index 0f18ba5..075eaef2 100644
--- a/arch/arm64/boot/dts/qcom/pm660l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660l.dtsi
@@ -250,9 +250,8 @@
 				<0xd900 0x100>;
 			reg-names = "qpnp-wled-ctrl-base",
 					"qpnp-wled-sink-base";
-			interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>,
-					<0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
-			interrupt-names = "ovp-irq", "sc-irq";
+			interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "ovp-irq";
 			linux,name = "wled";
 			linux,default-trigger = "bkl-trigger";
 			qcom,fdbk-output = "auto";
@@ -268,9 +267,9 @@
 			qcom,fs-curr-ua = <25000>;
 			qcom,cons-sync-write-delay-us = <1000>;
 			qcom,led-strings-list = [00 01 02];
-			qcom,en-ext-pfet-sc-pro;
 			qcom,loop-auto-gm-en;
 			qcom,pmic-revid = <&pm660l_revid>;
+			qcom,auto-calibration-enable;
 			status = "ok";
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 09405ee..a8b826a 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -12,9 +12,10 @@
 
 #include <dt-bindings/spmi/spmi.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/thermal/thermal.h>
 
 &spmi_bus {
-	qcom,pmi8998@2 {
+	pmi8998_lsid0: qcom,pmi8998@2 {
 		compatible = "qcom,spmi-pmic";
 		reg = <0x2 SPMI_USID>;
 		#address-cells = <2>;
@@ -335,7 +336,7 @@
 		};
 	};
 
-	qcom,pmi8998@3 {
+	pmi8998_lsid1: qcom,pmi8998@3 {
 		compatible ="qcom,spmi-pmic";
 		reg = <0x3 SPMI_USID>;
 		#address-cells = <2>;
@@ -563,6 +564,7 @@
 			qcom,en-ext-pfet-sc-pro;
 			qcom,pmic-revid = <&pmi8998_revid>;
 			qcom,loop-auto-gm-en;
+			qcom,auto-calibration-enable;
 			status = "disabled";
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
new file mode 100644
index 0000000..3bd0350
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm-audio-lpass.dtsi"
+#include "sdm670-wsa881x.dtsi"
+#include "sdm670-wcd.dtsi"
+#include "sdm670-lpi.dtsi"
+#include <dt-bindings/clock/qcom,audio-ext-clk.h>
+
+&msm_audio_ion {
+	iommus = <&apps_smmu 0x1801 0x0>;
+	qcom,smmu-sid-mask = /bits/ 64 <0xf>;
+};
+
+&soc {
+	qcom,avtimer@62cf700c {
+		compatible = "qcom,avtimer";
+		reg = <0x62cf700c 0x4>,
+			<0x62cf7010 0x4>;
+		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+		qcom,clk-div = <192>;
+		qcom,clk-mult = <10>;
+	};
+
+	tavil_snd: sound-tavil {
+		status = "disabled";
+		compatible = "qcom,sdm670-asoc-snd-tavil";
+		qcom,model = "sdm670-tavil-snd-card";
+		qcom,wcn-btfm;
+		qcom,mi2s-audio-intf;
+		qcom,auxpcm-audio-intf;
+		qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
+		qcom,audio-routing =
+			"AIF4 VI", "MCLK",
+			"RX_BIAS", "MCLK",
+			"MADINPUT", "MCLK",
+			"hifi amp", "LINEOUT1",
+			"hifi amp", "LINEOUT2",
+			"AMIC2", "MIC BIAS2",
+			"MIC BIAS2", "Headset Mic",
+			"AMIC3", "MIC BIAS2",
+			"MIC BIAS2", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2",
+			"MIC BIAS2", "ANCLeft Headset Mic",
+			"AMIC5", "MIC BIAS3",
+			"MIC BIAS3", "Handset Mic",
+			"DMIC0", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic0",
+			"DMIC1", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic1",
+			"DMIC2", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic2",
+			"DMIC3", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic3",
+			"DMIC4", "MIC BIAS4",
+			"MIC BIAS4", "Digital Mic4",
+			"DMIC5", "MIC BIAS4",
+			"MIC BIAS4", "Digital Mic5",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,msm-mbhc-hphl-swh = <1>;
+		qcom,msm-mbhc-gnd-swh = <1>;
+		qcom,hph-en0-gpio = <&tavil_hph_en0>;
+		qcom,hph-en1-gpio = <&tavil_hph_en1>;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,usbc-analog-en1_gpio = <&wcd_usbc_analog_en1_gpio>;
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+			<&loopback>, <&compress>, <&hostless>,
+			<&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>,
+			<&pcm_noirq>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+			"msm-pcm-dsp.2", "msm-voip-dsp",
+			"msm-pcm-voice", "msm-pcm-loopback",
+			"msm-compress-dsp", "msm-pcm-hostless",
+			"msm-pcm-afe", "msm-lsm-client",
+			"msm-pcm-routing", "msm-cpe-lsm",
+			"msm-compr-dsp", "msm-pcm-dsp-noirq";
+		asoc-cpu = <&dai_mi2s0>, <&dai_mi2s1>,
+			<&dai_mi2s2>, <&dai_mi2s3>,
+			<&dai_pri_auxpcm>, <&dai_sec_auxpcm>,
+			<&dai_tert_auxpcm>, <&dai_quat_auxpcm>,
+			<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+			<&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+			<&sb_4_rx>, <&sb_4_tx>, <&sb_5_rx>, <&sb_5_tx>,
+			<&sb_6_rx>, <&sb_7_rx>, <&sb_7_tx>,
+			<&sb_8_rx>, <&sb_8_tx>,
+			<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
+			<&afe_proxy_tx>, <&incall_record_rx>,
+			<&incall_record_tx>, <&incall_music_rx>,
+			<&incall_music_2_rx>,
+			<&usb_audio_rx>, <&usb_audio_tx>,
+			<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>,
+			<&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>,
+			<&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>,
+			<&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>;
+		asoc-cpu-names = "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+			"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+			"msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2",
+			"msm-dai-q6-auxpcm.3", "msm-dai-q6-auxpcm.4",
+			"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+			"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+			"msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
+			"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+			"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+			"msm-dai-q6-dev.16394", "msm-dai-q6-dev.16395",
+			"msm-dai-q6-dev.16396",
+			"msm-dai-q6-dev.16398", "msm-dai-q6-dev.16399",
+			"msm-dai-q6-dev.16400", "msm-dai-q6-dev.16401",
+			"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+			"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+			"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+			"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
+			"msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673",
+			"msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865",
+			"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
+			"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
+			"msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>,
+				<&wsa881x_0213>, <&wsa881x_0214>;
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+					"SpkrLeft", "SpkrRight";
+	};
+
+int_codec: sound {
+		status = "okay";
+		compatible = "qcom,sdm670-asoc-snd";
+		qcom,model = "sdm670-snd-card";
+		qcom,wcn-btfm;
+		qcom,mi2s-audio-intf;
+		qcom,auxpcm-audio-intf;
+		qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-mbhc-hphl-swh = <1>;
+		qcom,msm-mbhc-gnd-swh = <1>;
+		qcom,msm-micbias2-ext-cap;
+		qcom,msm-hs-micbias-type = "external";
+		qcom,cdc-pdm-gpios = <&cdc_pdm_gpios>;
+		qcom,cdc-comp-gpios = <&cdc_comp_gpios>;
+		qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+		qcom,audio-routing =
+			"RX_BIAS", "INT_MCLK0",
+			"SPK_RX_BIAS", "INT_MCLK0",
+			"INT_LDO_H", "INT_MCLK0",
+			"MIC BIAS External", "Handset Mic",
+			"MIC BIAS External2", "Headset Mic",
+			"MIC BIAS External", "Secondary Mic",
+			"AMIC1", "MIC BIAS External",
+			"AMIC2", "MIC BIAS External2",
+			"AMIC3", "MIC BIAS External",
+			"DMIC1", "MIC BIAS External",
+			"MIC BIAS External", "Digital Mic1",
+			"DMIC2", "MIC BIAS External",
+			"MIC BIAS External", "Digital Mic2",
+			"DMIC3", "MIC BIAS External",
+			"MIC BIAS External", "Digital Mic3",
+			"DMIC4", "MIC BIAS External",
+			"MIC BIAS External", "Digital Mic4",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT",
+			"PDM_IN_RX1", "PDM_OUT_RX1",
+			"PDM_IN_RX2", "PDM_OUT_RX2",
+			"PDM_IN_RX3", "PDM_OUT_RX3",
+			"ADC1_IN", "ADC1_OUT",
+			"ADC2_IN", "ADC2_OUT",
+			"ADC3_IN", "ADC3_OUT";
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+			<&loopback>, <&compress>, <&hostless>,
+			<&afe>, <&lsm>, <&routing>, <&compr>,
+			<&pcm_noirq>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+			"msm-pcm-dsp.2", "msm-voip-dsp",
+			"msm-pcm-voice", "msm-pcm-loopback",
+			"msm-compress-dsp", "msm-pcm-hostless",
+			"msm-pcm-afe", "msm-lsm-client",
+			"msm-pcm-routing", "msm-compr-dsp",
+			"msm-pcm-dsp-noirq";
+		asoc-cpu = <&dai_mi2s0>, <&dai_mi2s1>,
+			<&dai_mi2s2>, <&dai_mi2s3>,
+			<&dai_int_mi2s0>, <&dai_int_mi2s1>,
+			<&dai_int_mi2s2>, <&dai_int_mi2s3>,
+			<&dai_int_mi2s4>, <&dai_int_mi2s5>,
+			<&dai_pri_auxpcm>, <&dai_sec_auxpcm>,
+			<&dai_tert_auxpcm>, <&dai_quat_auxpcm>,
+			<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
+			<&afe_proxy_tx>, <&incall_record_rx>,
+			<&incall_record_tx>, <&incall_music_rx>,
+			<&incall_music_2_rx>, <&sb_7_rx>, <&sb_7_tx>,
+			<&sb_8_tx>, <&sb_8_rx>,
+			<&usb_audio_rx>, <&usb_audio_tx>,
+			<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>,
+			<&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>,
+			<&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>,
+			<&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>;
+		asoc-cpu-names = "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+			"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+			"msm-dai-q6-mi2s.7", "msm-dai-q6-mi2s.8",
+			"msm-dai-q6-mi2s.9", "msm-dai-q6-mi2s.10",
+			"msm-dai-q6-mi2s.11", "msm-dai-q6-mi2s.12",
+			"msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2",
+			"msm-dai-q6-auxpcm.3", "msm-dai-q6-auxpcm.4",
+			"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+			"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+			"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+			"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
+			"msm-dai-q6-dev.16398", "msm-dai-q6-dev.16399",
+			"msm-dai-q6-dev.16401", "msm-dai-q6-dev.16400",
+			"msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673",
+			"msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865",
+			"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
+			"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
+			"msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913";
+		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+				<&pmic_analog_codec>, <&msm_sdw_codec>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+				"analog-codec", "msm_sdw_codec";
+
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_212_en>,
+				<&wsa881x_213_en>, <&wsa881x_214_en>;
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+					"SpkrLeft", "SpkrRight";
+	};
+
+	cdc_pdm_gpios: cdc_pdm_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_pdm_clk_active &cdc_pdm_sync_active
+			     &cdc_pdm_rx0_active &cdc_pdm_rx1_2_active
+			     &cdc_pdm_2_gpios_active>;
+		pinctrl-1 = <&cdc_pdm_clk_sleep &cdc_pdm_sync_sleep
+			     &cdc_pdm_rx0_sleep &cdc_pdm_rx1_2_sleep
+			     &cdc_pdm_2_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_comp_gpios: cdc_comp_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_rx0_comp_active &cdc_rx1_comp_active>;
+		pinctrl-1 = <&cdc_rx0_comp_sleep &cdc_rx1_comp_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_dmic_gpios: cdc_dmic_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_dmic12_gpios_active
+				&cdc_dmic34_gpios_active>;
+		pinctrl-1 = <&cdc_dmic12_gpios_sleep
+				&cdc_dmic34_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_sdw_gpios: sdw_clk_data_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&sdw_clk_active &sdw_data_active>;
+		pinctrl-1 = <&sdw_clk_sleep &sdw_data_sleep>;
+	};
+
+	wsa_spkr_en1: wsa_spkr_en1_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_1_sd_n_active>;
+		pinctrl-1 = <&spkr_1_sd_n_sleep>;
+	};
+
+	wsa_spkr_en2: wsa_spkr_en2_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_2_sd_n_active>;
+		pinctrl-1 = <&spkr_2_sd_n_sleep>;
+	};
+
+	msm_sdw_codec: msm-sdw-codec@62ec1000 {
+		status = "okay";
+		compatible = "qcom,msm-sdw-codec";
+		reg = <0x62ec1000 0x0>;
+		interrupts = <0 161 0>;
+		interrupt-names = "swr_master_irq";
+		qcom,cdc-sdw-gpios = <&cdc_sdw_gpios>;
+
+		swr_master {
+			compatible = "qcom,swr-wcd";
+			#address-cells = <2>;
+			#size-cells = <0>;
+
+			wsa881x_211_en: wsa881x_en@20170211 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170211>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+			};
+
+			wsa881x_212_en: wsa881x_en@20170212 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170212>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+			};
+
+			wsa881x_213_en: wsa881x_en@21170213 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170213>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+			};
+
+			wsa881x_214_en: wsa881x_en@21170214 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170214>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+			};
+		};
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		status = "disabled";
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&tlmm>;
+		qcom,gpio-connect = <&tlmm 80 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wcd_intr_default>;
+	};
+
+	clock_audio_lnbb: audio_ext_clk_lnbb {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		clock-names = "osr_clk";
+		clocks = <&clock_rpmh RPMH_LN_BB_CLK2>;
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+	};
+
+	wcd_rst_gpio: msm_cdc_pinctrl@64 {
+		status = "disabled";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&lpi_cdc_reset_active>;
+		pinctrl-1 = <&lpi_cdc_reset_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cpe: qcom,msm-cpe-lsm {
+		compatible = "qcom,msm-cpe-lsm";
+	};
+
+	cpe3: qcom,msm-cpe-lsm@3 {
+		compatible = "qcom,msm-cpe-lsm";
+		qcom,msm-cpe-lsm-id = <3>;
+	};
+
+	wdsp_mgr: qcom,wcd-dsp-mgr {
+		compatible = "qcom,wcd-dsp-mgr";
+		qcom,wdsp-components = <&wcd934x_cdc 0>,
+				       <&wcd_spi_0 1>,
+				       <&glink_spi_xprt_wdsp 2>;
+		qcom,img-filename = "cpe_9340";
+	};
+
+	wdsp_glink: qcom,wcd-dsp-glink {
+		compatible = "qcom,wcd-dsp-glink";
+	};
+};
+
+&slim_aud {
+	status = "disabled";
+	dai_slim: msm_dai_slim {
+		status = "disabled";
+		compatible = "qcom,msm-dai-slim";
+		elemental-addr = [ff ff ff fe 17 02];
+	};
+
+	wcd934x_cdc: tavil_codec {
+		status = "disabled";
+		compatible = "qcom,tavil-slim-pgd";
+		elemental-addr = [00 01 50 02 17 02];
+
+		interrupt-parent = <&wcd9xxx_intc>;
+		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+			      17 18 19 20 21 22 23 24 25 26 27 28 29
+			      30 31>;
+
+		qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+		clock-names = "wcd_clk";
+		clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
+
+		cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+		qcom,cdc-vdd-mic-bias-voltage = <3300000 3300000>;
+		qcom,cdc-vdd-mic-bias-current = <30400>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+		qcom,cdc-micbias1-mv = <1800>;
+		qcom,cdc-micbias2-mv = <1800>;
+		qcom,cdc-micbias3-mv = <1800>;
+		qcom,cdc-micbias4-mv = <1800>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+		qcom,cdc-slim-ifd = "tavil-slim-ifd";
+		qcom,cdc-slim-ifd-elemental-addr = [00 00 50 02 17 02];
+		qcom,cdc-dmic-sample-rate = <4800000>;
+		qcom,cdc-mad-dmic-rate = <600000>;
+
+		qcom,wdsp-cmpnt-dev-name = "tavil_codec";
+
+		wcd_spi_0: wcd_spi {
+			compatible = "qcom,wcd-spi-v2";
+			qcom,master-bus-num = <8>;
+			qcom,chip-select = <0>;
+			qcom,max-frequency = <24000000>;
+			qcom,mem-base-addr = <0x100000>;
+		};
+
+		wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl_usbc_audio_en1 {
+			compatible = "qcom,msm-cdc-pinctrl";
+			pinctrl-names = "aud_active", "aud_sleep";
+			pinctrl-0 = <&wcd_usbc_analog_en1_active>;
+			pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
+		};
+	};
+};
+
+&msm_dai_mi2s {
+	dai_int_mi2s0: qcom,msm-dai-q6-int-mi2s0 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <7>;
+		qcom,msm-mi2s-rx-lines = <3>;
+		qcom,msm-mi2s-tx-lines = <0>;
+	};
+
+	dai_int_mi2s1: qcom,msm-dai-q6-int-mi2s1 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <8>;
+		qcom,msm-mi2s-rx-lines = <3>;
+		qcom,msm-mi2s-tx-lines = <0>;
+	};
+
+	dai_int_mi2s2: qcom,msm-dai-q6-int-mi2s2 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <9>;
+		qcom,msm-mi2s-rx-lines = <0>;
+		qcom,msm-mi2s-tx-lines = <3>;
+	};
+
+	dai_int_mi2s3: qcom,msm-dai-q6-int-mi2s3 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <10>;
+		qcom,msm-mi2s-rx-lines = <0>;
+		qcom,msm-mi2s-tx-lines = <3>;
+	};
+
+	dai_int_mi2s4: qcom,msm-dai-q6-int-mi2s4 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <11>;
+		qcom,msm-mi2s-rx-lines = <3>;
+		qcom,msm-mi2s-tx-lines = <0>;
+	};
+
+	dai_int_mi2s5: qcom,msm-dai-q6-int-mi2s5 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <12>;
+		qcom,msm-mi2s-rx-lines = <0>;
+		qcom,msm-mi2s-tx-lines = <3>;
+	};
+
+	dai_int_mi2s6: qcom,msm-dai-q6-int-mi2s6 {
+		compatible = "qcom,msm-dai-q6-mi2s";
+		qcom,msm-dai-q6-mi2s-dev-id = <13>;
+		qcom,msm-mi2s-rx-lines = <0>;
+		qcom,msm-mi2s-tx-lines = <3>;
+	};
+};
+
+&pm660l_3 {
+	pmic_analog_codec: analog-codec@f000 {
+		status = "okay";
+		compatible = "qcom,pmic-analog-codec";
+		reg = <0xf000 0x200>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x3 0xf0 0x0 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x1 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x2 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x3 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x4 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x5 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x6 IRQ_TYPE_NONE>,
+				<0x3 0xf0 0x7 IRQ_TYPE_NONE>,
+				<0x3 0xf1 0x0 IRQ_TYPE_NONE>,
+				<0x3 0xf1 0x1 IRQ_TYPE_NONE>,
+				<0x3 0xf1 0x2 IRQ_TYPE_NONE>,
+				<0x3 0xf1 0x3 IRQ_TYPE_NONE>,
+				<0x3 0xf1 0x4 IRQ_TYPE_NONE>,
+				<0x3 0xf1 0x5 IRQ_TYPE_NONE>;
+		interrupt-names = "spk_cnp_int",
+				  "spk_clip_int",
+				  "spk_ocp_int",
+				  "ins_rem_det1",
+				  "but_rel_det",
+				  "but_press_det",
+				  "ins_rem_det",
+				  "mbhc_int",
+				  "ear_ocp_int",
+				  "hphr_ocp_int",
+				  "hphl_ocp_det",
+				  "ear_cnp_int",
+				  "hphr_cnp_int",
+				  "hphl_cnp_int";
+
+
+		cdc-vdda-cp-supply = <&pm660_s4>;
+		qcom,cdc-vdda-cp-voltage = <1900000 2050000>;
+		qcom,cdc-vdda-cp-current = <50000>;
+
+		cdc-vdd-pa-supply = <&pm660_s4>;
+		qcom,cdc-vdd-pa-voltage = <2040000 2040000>;
+		qcom,cdc-vdd-pa-current = <260000>;
+
+		cdc-vdd-mic-bias-supply = <&pm660l_l7>;
+		qcom,cdc-vdd-mic-bias-voltage = <3088000 3088000>;
+		qcom,cdc-vdd-mic-bias-current = <5000>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+
+		qcom,cdc-static-supplies = "cdc-vdda-cp",
+					   "cdc-vdd-pa";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+		/*
+		 * Not marking address @ as driver searches this child
+		 * with name msm-dig-codec
+		 */
+		msm_digital_codec: msm-dig-codec {
+			compatible = "qcom,msm-digital-codec";
+			reg = <0x62ec0000 0x0>;
+		};
+	};
+};
+
+&pm660_gpios {
+	gpio@c200 {
+		status = "ok";
+		qcom,mode = <1>;
+		qcom,pull = <4>;
+		qcom,vin-sel = <0>;
+		qcom,src-sel = <2>;
+		qcom,master-en = <1>;
+		qcom,out-strength = <2>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
new file mode 100644
index 0000000..6e92f0e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
@@ -0,0 +1,284 @@
+/* Copyright (c) 2017, 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.
+ */
+
+&soc {
+	lpi_tlmm: lpi_pinctrl@62b40000 {
+		compatible = "qcom,lpi-pinctrl";
+		reg = <0x62b40000 0x0>;
+		qcom,num-gpios = <32>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		cdc_pdm_clk_active: cdc_pdm_clk_active {
+			mux {
+				pins = "gpio18";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio18";
+				drive-strength = <8>;
+				output-high;
+			};
+		};
+
+		cdc_pdm_clk_sleep: cdc_pdm_clk_sleep {
+			mux {
+				pins = "gpio18";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio18";
+				drive-strength = <2>;
+				bias-disable;
+				output-low;
+			};
+		};
+
+		cdc_pdm_sync_active: cdc_pdm_sync_active {
+			mux {
+				pins = "gpio19";
+				function = "func3";
+			};
+
+			config {
+				pins = "gpio19";
+				drive-strength = <8>;
+				output-high;
+			};
+		};
+
+		cdc_pdm_sync_sleep: cdc_pdm_sync_sleep {
+			mux {
+				pins = "gpio19";
+				function = "func3";
+			};
+
+			config {
+				pins = "gpio19";
+				drive-strength = <2>;
+				bias-disable;
+				output-low;
+			};
+		};
+
+		cdc_pdm_rx0_active: cdc_pdm_rx0_active {
+			mux {
+				pins = "gpio21";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio21";
+				drive-strength = <8>;
+				output-high;
+			};
+		};
+
+		cdc_pdm_rx0_sleep: cdc_pdm_rx0_sleep {
+			mux {
+				pins = "gpio21";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio21";
+				drive-strength = <2>;
+				bias-disable;
+				output-low;
+			};
+		};
+
+		cdc_pdm_rx1_2_active: cdc_pdm_rx1_2_active {
+			mux {
+				pins = "gpio23", "gpio25";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio23", "gpio25";
+				drive-strength = <8>;
+				output-high;
+			};
+		};
+
+		cdc_pdm_rx1_2_sleep: cdc_pdm_rx1_2_sleep {
+			mux {
+				pins = "gpio23", "gpio25";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio23", "gpio25";
+				drive-strength = <2>;
+				bias-disable;
+				output-low;
+			};
+		};
+
+		cdc_pdm_2_gpios_active: cdc_pdm_2_gpios_active {
+			mux {
+				pins = "gpio20";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio20";
+				drive-strength = <8>;
+			};
+		};
+
+		cdc_pdm_2_gpios_sleep: cdc_pdm_2_gpios_sleep {
+			mux {
+				pins = "gpio20";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio20";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		cdc_rx0_comp_active: cdc_pdm_rx0_comp_active {
+			mux {
+				pins = "gpio22";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio22";
+				drive-strength = <8>;
+			};
+		};
+
+		cdc_rx0_comp_sleep: cdc_pdm_rx0_comp_sleep {
+			mux {
+				pins = "gpio22";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio22";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		cdc_rx1_comp_active: cdc_pdm_rx1_comp_active {
+			mux {
+				pins = "gpio24";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio24";
+				drive-strength = <8>;
+			};
+		};
+
+		cdc_rx1_comp_sleep: cdc_pdm_rx1_comp_sleep {
+			mux {
+				pins = "gpio24";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio24";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		lpi_cdc_reset_active: lpi_cdc_reset_active {
+			mux {
+				pins = "gpio29";
+				function = "func2";
+			};
+			config {
+				pins = "gpio29";
+				drive-strength = <16>;
+				output-high;
+			};
+		};
+
+		lpi_cdc_reset_sleep: lpi_cdc_reset_sleep {
+			mux {
+				pins = "gpio29";
+				function = "func2";
+			};
+
+			config {
+				pins = "gpio29";
+				drive-strength = <16>;
+				bias-disable;
+				output-low;
+			};
+		};
+
+		cdc_dmic12_gpios_active: dmic12_gpios_active {
+			mux {
+				pins = "gpio26", "gpio28";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio26", "gpio28";
+				drive-strength = <8>;
+				output-high;
+			};
+		};
+
+		cdc_dmic12_gpios_sleep: dmic12_gpios_sleep {
+			mux {
+				pins = "gpio26", "gpio28";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio26", "gpio28";
+				drive-strength = <2>;
+				bias-disable;
+				output-low;
+			};
+		};
+
+		cdc_dmic34_gpios_active: dmic34_gpios_active {
+			mux {
+				pins = "gpio27", "gpio29";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio27", "gpio29";
+				drive-strength = <8>;
+				input-enable;
+			};
+		};
+
+		cdc_dmic34_gpios_sleep: dmic34_gpios_sleep {
+			mux {
+				pins = "gpio27", "gpio29";
+				function = "func1";
+			};
+
+			config {
+				pins = "gpio27", "gpio29";
+				drive-strength = <2>;
+				pull-down;
+				input-enable;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index dcc5d1b..73df253 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1146,5 +1146,296 @@
 				};
 			};
 		};
+		/* SDC pin type */
+		sdc1_clk_on: sdc1_clk_on {
+			config {
+				pins = "sdc1_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <16>;	/* 16 MA */
+			};
+		};
+
+		sdc1_clk_off: sdc1_clk_off {
+			config {
+				pins = "sdc1_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc1_cmd_on: sdc1_cmd_on {
+			config {
+				pins = "sdc1_cmd";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc1_cmd_off: sdc1_cmd_off {
+			config {
+				pins = "sdc1_cmd";
+				num-grp-pins = <1>;
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc1_data_on: sdc1_data_on {
+			config {
+				pins = "sdc1_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc1_data_off: sdc1_data_off {
+			config {
+				pins = "sdc1_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc2_clk_on: sdc2_clk_on {
+			config {
+				pins = "sdc2_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <16>;	/* 16 MA */
+			};
+		};
+
+		sdc2_clk_off: sdc2_clk_off {
+			config {
+				pins = "sdc2_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc2_cmd_on: sdc2_cmd_on {
+			config {
+				pins = "sdc2_cmd";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc2_cmd_off: sdc2_cmd_off {
+			config {
+				pins = "sdc2_cmd";
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc2_data_on: sdc2_data_on {
+			config {
+				pins = "sdc2_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc2_data_off: sdc2_data_off {
+			config {
+				pins = "sdc2_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		/* USB C analog configuration */
+		wcd_usbc_analog_en1 {
+			wcd_usbc_analog_en1_idle: wcd_usbc_ana_en1_idle {
+				mux {
+					pins = "gpio49";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio49";
+					drive-strength = <2>;
+					bias-pull-down;
+					output-low;
+				};
+			};
+
+			wcd_usbc_analog_en1_active: wcd_usbc_ana_en1_active {
+				mux {
+					pins = "gpio49";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio49";
+					drive-strength = <2>;
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		sdw_clk_pin {
+			sdw_clk_sleep: sdw_clk_sleep {
+				mux {
+					pins = "gpio65";
+					function = "wsa_clk";
+				};
+
+				config {
+					pins = "gpio65";
+					drive-strength = <2>;
+					bias-bus-hold;
+				};
+			};
+
+			sdw_clk_active: sdw_clk_active {
+				mux {
+					pins = "gpio65";
+					function = "wsa_clk";
+				};
+
+				config {
+					pins = "gpio65";
+					drive-strength = <2>;
+					bias-bus-hold;
+				};
+			};
+		};
+
+		sdw_data_pin {
+			sdw_data_sleep: sdw_data_sleep {
+				mux {
+					pins = "gpio66";
+					function = "wsa_data";
+				};
+
+				config {
+					pins = "gpio66";
+					drive-strength = <4>;
+					bias-bus-hold;
+				};
+			};
+
+			sdw_data_active: sdw_data_active {
+				mux {
+					pins = "gpio66";
+					function = "wsa_data";
+				};
+
+				config {
+					pins = "gpio66";
+					drive-strength = <4>;
+					bias-bus-hold;
+				};
+			};
+		};
+
+		/* WSA speaker reset pins */
+		spkr_1_sd_n {
+			spkr_1_sd_n_sleep: spkr_1_sd_n_sleep {
+				mux {
+					pins = "gpio67";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio67";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;
+					input-enable;
+				};
+			};
+
+			spkr_1_sd_n_active: spkr_1_sd_n_active {
+				mux {
+					pins = "gpio67";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio67";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		spkr_2_sd_n {
+			spkr_2_sd_n_sleep: spkr_2_sd_n_sleep {
+				mux {
+					pins = "gpio68";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio68";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;
+					input-enable;
+				};
+			};
+
+			spkr_2_sd_n_active: spkr_2_sd_n_active {
+				mux {
+					pins = "gpio68";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio68";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		wcd_gnd_mic_swap {
+			wcd_gnd_mic_swap_idle: wcd_gnd_mic_swap_idle {
+				mux {
+					pins = "gpio40";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio40";
+					drive-strength = <2>;
+					bias-pull-down;
+					output-low;
+				};
+			};
+
+			wcd_gnd_mic_swap_active: wcd_gnd_mic_swap_active {
+				mux {
+					pins = "gpio40";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio40";
+					drive-strength = <2>;
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		wcd9xxx_intr {
+			wcd_intr_default: wcd_intr_default{
+				mux {
+				pins = "gpio80";
+				function = "gpio";
+				};
+
+				config {
+					pins = "gpio80";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+					input-enable;
+				};
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
index b0c436f..0a8c49f 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
@@ -15,331 +15,6 @@
 /* Stub regulators */
 
 / {
-	pm660_s4: regulator-pm660-s4 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_s4";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <2040000>;
-		regulator-max-microvolt = <2040000>;
-	};
-
-	/* pm660 S5 - VDD_MODEM supply */
-	pm660_s5_level: regulator-pm660-s5 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_s5_level";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660_s6: regulator-pm660-s6 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_s6";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <1352000>;
-		regulator-max-microvolt = <1352000>;
-	};
-
-	/* pm660l S1 - VDD_MX supply */
-	pm660l_s1_level: regulator-pm660l-s1 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_s1_level";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_s1_floor_level: regulator-pm660l-s1-floor-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_s1_floor_level";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_s1_level_ao: regulator-pm660l-s1-level-ao {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_s1_level_ao";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	/* pm660l S2 - VDD_GFX supply */
-	pm660l_s2_level: regulator-pm660l-s2 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_s2_level";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	/* pm660l S3 + S4 - VDD_CX supply */
-	pm660l_s3_level: regulator-pm660l-s3-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_s3_level";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_s3_floor_level: regulator-pm660l-s3-floor-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_s3_floor_level";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_s3_level_ao: regulator-pm660l-s3-level-ao {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_s3_level_ao";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660_l1: regulator-pm660-l1 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l1";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1200000>;
-		regulator-max-microvolt = <1250000>;
-	};
-
-	pm660_l2: regulator-pm660-l2 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l2";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1000000>;
-		regulator-max-microvolt = <1000000>;
-	};
-
-	pm660_l3: regulator-pm660-l3 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l3";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1000000>;
-		regulator-max-microvolt = <1000000>;
-	};
-
-	pm660_l5: regulator-pm660-l5 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l5";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <800000>;
-		regulator-max-microvolt = <800000>;
-	};
-
-	pm660_l6: regulator-pm660-l6 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l6";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1304000>;
-		regulator-max-microvolt = <1304000>;
-	};
-
-	pm660_l7: regulator-pm660-l7 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l7";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1200000>;
-		regulator-max-microvolt = <1200000>;
-	};
-
-	pm660_l8: regulator-pm660-l8 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l8";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l9: regulator-pm660-l9 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l9";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l10: regulator-pm660-l10 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l10";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l11: regulator-pm660-l11 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l11";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l12: regulator-pm660-l12 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l12";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l13: regulator-pm660-l13 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l13";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l14: regulator-pm660-l14 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l14";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	pm660_l15: regulator-pm660-l15 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l15";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <2950000>;
-	};
-
-	pm660_l16: regulator-pm660-l16 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l16";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <2700000>;
-		regulator-max-microvolt = <2700000>;
-	};
-
-	pm660_l17: regulator-pm660-l17 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l17";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <2950000>;
-	};
-
-	pm660_l19: regulator-pm660-l19 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660_l19";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <3312000>;
-		regulator-max-microvolt = <3312000>;
-	};
-
-	pm660l_l1: regulator-pm660l-l1 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l1";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <880000>;
-		regulator-max-microvolt = <900000>;
-	};
-
-	pm660l_l2: regulator-pm660l-l2 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l2";
-		qcom,hpm-min-load = <5000>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <2960000>;
-	};
-
-	pm660l_l3: regulator-pm660l-l3 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l3";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <2850000>;
-		regulator-max-microvolt = <3008000>;
-	};
-
-	pm660l_l4: regulator-pm660l-l4 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l4";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <2960000>;
-		regulator-max-microvolt = <2960000>;
-	};
-
-	pm660l_l5: regulator-pm660l-l5 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l5";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <2960000>;
-		regulator-max-microvolt = <2960000>;
-	};
-
-	pm660l_l6: regulator-pm660l-l6 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l6";
-		qcom,hpm-min-load = <5000>;
-		regulator-min-microvolt = <3008000>;
-		regulator-max-microvolt = <3300000>;
-	};
-
-	pm660l_l7: regulator-pm660l-l7 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l7";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <3088000>;
-		regulator-max-microvolt = <3100000>;
-	};
-
-	pm660l_l8: regulator-pm660l-l8 {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l8";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3312000>;
-	};
-
-	/* pm660l L9 = VDD_LPI_CX supply */
-	pm660l_l9_level: regulator-pm660l-l9-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l9_level";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_l9_floor_level: regulator-pm660l-l9-floor-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l9_floor_level";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	/* pm660l L10 = VDD_LPI_MX supply */
-	pm660l_l10_level: regulator-pm660l-l10-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l10_level";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_l10_floor_level: regulator-pm660l-l10-floor-level {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_l10_floor_level";
-		qcom,hpm-min-load = <10000>;
-		regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
-		regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
-	};
-
-	pm660l_bob: regulator-pm660l-bob {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "pm660l_bob";
-		regulator-min-microvolt = <3312000>;
-		regulator-max-microvolt = <3312000>;
-	};
-
 	apc0_pwrcl_vreg: regulator-pwrcl {
 		compatible = "qcom,stub-regulator";
 		regulator-name = "apc0_pwrcl_corner";
@@ -362,6 +37,598 @@
 	};
 };
 
+&soc {
+	/* RPMh regulators: */
+	rpmh-regulator-smpa4 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "smpa4";
+		pm660_s4: regulator-pm660-s4 {
+			regulator-name = "pm660_s4";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2040000>;
+			regulator-max-microvolt = <2040000>;
+			qcom,init-voltage = <2040000>;
+		};
+	};
+
+	/* pm660 S5 - VDD_MODEM supply */
+	rpmh-regulator-modemlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "mss.lvl";
+		pm660_s5_level: regulator-pm660-s5 {
+			regulator-name = "pm660_s5_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+	};
+
+	rpmh-regulator-smpa6 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "smpa6";
+		pm660_s6: regulator-pm660-s6 {
+			regulator-name = "pm660_s6";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1352000>;
+			regulator-max-microvolt = <1352000>;
+			qcom,init-voltage = <1352000>;
+		};
+	};
+
+	/* pm660l S1 - VDD_MX supply */
+	rpmh-regulator-mxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "mx.lvl";
+		pm660l_s1_level: regulator-pm660l-s1 {
+			regulator-name = "pm660l_s1_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+
+		pm660l_s1_level_ao: regulator-pm660l-s1-level-ao {
+			regulator-name = "pm660l_s1_level_ao";
+			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+	};
+
+	/* pm660l S2 - VDD_GFX supply */
+	rpmh-regulator-gfxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "gfx.lvl";
+		pm660l_s2_level: regulator-pm660l-s2 {
+			regulator-name = "pm660l_s2_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+			regulator-max-microvolt
+				= <RPMH_REGULATOR_LEVEL_MAX>;
+			qcom,init-voltage-level
+				= <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+		};
+	};
+
+	/* pm660l S3 + S4 - VDD_CX supply */
+	rpmh-regulator-cxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "cx.lvl";
+		pm660l_s3_level-parent-supply = <&pm660l_s1_level>;
+		pm660l_s3_level_ao-parent-supply = <&pm660l_s1_level_ao>;
+		pm660l_s3_level: regulator-pm660l-s3-level {
+			regulator-name = "pm660l_s3_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+			qcom,min-dropout-voltage-level = <(-1)>;
+		};
+
+		pm660l_s3_level_ao: regulator-pm660l-s3-level-ao {
+			regulator-name = "pm660l_s3_level_ao";
+			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+			qcom,min-dropout-voltage-level = <(-1)>;
+		};
+	};
+
+	rpmh-regulator-ldoa1 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa1";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l1: regulator-pm660-l1 {
+			regulator-name = "pm660_l1";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1250000>;
+			qcom,init-voltage = <1200000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa2 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa2";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l2: regulator-pm660-l2 {
+			regulator-name = "pm660_l2";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,init-voltage = <1000000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa3 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa3";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l3: regulator-pm660-l3 {
+			regulator-name = "pm660_l3";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,init-voltage = <1000000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa5 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa5";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l5: regulator-pm660-l5 {
+			regulator-name = "pm660_l5";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <800000>;
+			regulator-max-microvolt = <800000>;
+			qcom,init-voltage = <800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa6 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa6";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l6: regulator-pm660-l6 {
+			regulator-name = "pm660_l6";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1304000>;
+			regulator-max-microvolt = <1304000>;
+			qcom,init-voltage = <1304000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa7 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa7";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l7: regulator-pm660-l7 {
+			regulator-name = "pm660_l7";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa8 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa8";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l8: regulator-pm660-l8 {
+			regulator-name = "pm660_l8";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa9 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa9";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l9: regulator-pm660-l9 {
+			regulator-name = "pm660_l9";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa10 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa10";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l10: regulator-pm660-l10 {
+			regulator-name = "pm660_l10";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa11 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa11";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l11: regulator-pm660-l11 {
+			regulator-name = "pm660_l11";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa12 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa12";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l12: regulator-pm660-l12 {
+			regulator-name = "pm660_l12";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa13 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa13";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l13: regulator-pm660-l13 {
+			regulator-name = "pm660_l13";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa14 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa14";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l14: regulator-pm660-l14 {
+			regulator-name = "pm660_l14";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa15 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa15";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l15: regulator-pm660-l15 {
+			regulator-name = "pm660_l15";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa16 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa16";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l16: regulator-pm660-l16 {
+		regulator-name = "pm660_l16";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,init-voltage = <2700000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa17 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa17";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l17: regulator-pm660-l17 {
+			regulator-name = "pm660_l17";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa19 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa19";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l19: regulator-pm660-l19 {
+			regulator-name = "pm660_l19";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <3312000>;
+			regulator-max-microvolt = <3312000>;
+			qcom,init-voltage = <3312000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob1 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob1";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l1: regulator-pm660l-l1 {
+			regulator-name = "pm660l_l1";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <880000>;
+			regulator-max-microvolt = <900000>;
+			qcom,init-voltage = <880000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob2 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob2";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l2: regulator-pm660l-l2 {
+			regulator-name = "pm660l_l2";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2960000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob3 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob3";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l3: regulator-pm660l-l3 {
+			regulator-name = "pm660l_l3";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <3008000>;
+			qcom,init-voltage = <2850000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob4 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob4";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l4: regulator-pm660l-l4 {
+			regulator-name = "pm660l_l4";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2960000>;
+			regulator-max-microvolt = <2960000>;
+			qcom,init-voltage = <2960000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob5 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob5";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l5: regulator-pm660l-l5 {
+			regulator-name = "pm660l_l5";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2960000>;
+			regulator-max-microvolt = <2960000>;
+			qcom,init-voltage = <2960000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob6 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob6";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l6: regulator-pm660l-l6 {
+			regulator-name = "pm660l_l6";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <3008000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3008000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob7 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob7";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l7: regulator-pm660l-l7 {
+			regulator-name = "pm660l_l7";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <3088000>;
+			regulator-max-microvolt = <3100000>;
+			qcom,init-voltage = <3088000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldob8 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldob8";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660l_l8: regulator-pm660l-l8 {
+			regulator-name = "pm660l_l8";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3312000>;
+			qcom,init-voltage = <3300000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	/* pm660l L9 = VDD_LPI_CX supply */
+	rpmh-regulator-lcxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "lcx.lvl";
+		pm660l_l9_level: regulator-pm660l-l9-level {
+			regulator-name = "pm660l_l9_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+	};
+
+	/* pm660l L10 = VDD_LPI_MX supply */
+	rpmh-regulator-lmxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "lmx.lvl";
+		pm660l_l10_level: regulator-pm660l-l10-level {
+			regulator-name = "pm660l_l10_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+	};
+
+	rpmh-regulator-bobb1 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "bobb1";
+		pm660l_bob: regulator-pm660l-bob {
+			regulator-name = "pm660l_bob";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <3312000>;
+			regulator-max-microvolt = <3312000>;
+			qcom,init-voltage = <3312000>;
+		};
+	};
+};
+
 &pm660_charger {
 	smb2_vbus: qcom,smb2-vbus {
 		regulator-name = "smb2-vbus";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi
index 17b90c7..f2f41fd 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi
@@ -77,3 +77,24 @@
 	spm-level = <0>;
 	status = "ok";
 };
+
+&sdhc_1 {
+	vdd-supply = <&pm660l_l4>;
+	qcom,vdd-voltage-level = <2960000 2960000>;
+	qcom,vdd-current-level = <200 570000>;
+
+	vdd-io-supply = <&pm660_l8>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 325000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on  &sdc1_cmd_on &sdc1_data_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000>;
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
index 78dab37..f3e5ddb 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
@@ -245,4 +245,27 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	/* ssr - inbound entry from cdsp */
+	smp2pgpio_ssr_smp2p_5_in: qcom,smp2pgpio-ssr-smp2p-5-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <5>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	/* ssr - outbound entry to cdsp */
+	smp2pgpio_ssr_smp2p_5_out: qcom,smp2pgpio-ssr-smp2p-5-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <5>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-wcd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-wcd.dtsi
new file mode 100644
index 0000000..f8d2a04
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-wcd.dtsi
@@ -0,0 +1,167 @@
+/* Copyright (c) 2017, 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.
+ */
+
+&slim_aud {
+	tavil_codec {
+		wcd: wcd_pinctrl@5 {
+			compatible = "qcom,wcd-pinctrl";
+			qcom,num-gpios = <5>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			us_euro_sw_wcd_active: us_euro_sw_wcd_active {
+				mux {
+					pins = "gpio1";
+				};
+
+				config {
+					pins = "gpio1";
+					output-high;
+				};
+			};
+
+			us_euro_sw_wcd_sleep: us_euro_sw_wcd_sleep {
+				mux {
+					pins = "gpio1";
+				};
+
+				config {
+					pins = "gpio1";
+					output-low;
+				};
+			};
+
+			spkr_1_wcd_en_active: spkr_1_wcd_en_active {
+				mux {
+					pins = "gpio2";
+				};
+
+				config {
+					pins = "gpio2";
+					output-high;
+				};
+			};
+
+			spkr_1_wcd_en_sleep: spkr_1_wcd_en_sleep {
+				mux {
+					pins = "gpio2";
+				};
+
+				config {
+					pins = "gpio2";
+					input-enable;
+				};
+			};
+
+			spkr_2_wcd_en_active: spkr_2_sd_n_active {
+				mux {
+					pins = "gpio3";
+				};
+
+				config {
+					pins = "gpio3";
+					output-high;
+				};
+			};
+
+			spkr_2_wcd_en_sleep: spkr_2_sd_n_sleep {
+				mux {
+					pins = "gpio3";
+				};
+
+				config {
+					pins = "gpio3";
+					input-enable;
+				};
+			};
+
+			hph_en0_wcd_active: hph_en0_wcd_active {
+				mux {
+					pins = "gpio4";
+				};
+
+				config {
+					pins = "gpio4";
+					output-high;
+				};
+			};
+
+			hph_en0_wcd_sleep: hph_en0_wcd_sleep {
+				mux {
+					pins = "gpio4";
+				};
+
+				config {
+					pins = "gpio4";
+					output-low;
+				};
+			};
+
+			hph_en1_wcd_active: hph_en1_wcd_active {
+				mux {
+					pins = "gpio5";
+				};
+
+				config {
+					pins = "gpio5";
+					output-high;
+				};
+			};
+
+			hph_en1_wcd_sleep: hph_en1_wcd_sleep {
+				mux {
+					pins = "gpio5";
+				};
+
+				config {
+					pins = "gpio5";
+					output-low;
+				};
+			};
+		};
+
+		wsa_spkr_wcd_sd1: msm_cdc_pinctrll {
+			compatible = "qcom,msm-cdc-pinctrl";
+			pinctrl-names = "aud_active", "aud_sleep";
+			pinctrl-0 = <&spkr_1_wcd_en_active>;
+			pinctrl-1 = <&spkr_1_wcd_en_sleep>;
+		};
+
+		wsa_spkr_wcd_sd2: msm_cdc_pinctrlr {
+			compatible = "qcom,msm-cdc-pinctrl";
+			pinctrl-names = "aud_active", "aud_sleep";
+			pinctrl-0 = <&spkr_2_wcd_en_active>;
+			pinctrl-1 = <&spkr_2_wcd_en_sleep>;
+		};
+
+		tavil_us_euro_sw: msm_cdc_pinctrl_us_euro_sw {
+			compatible = "qcom,msm-cdc-pinctrl";
+			pinctrl-names = "aud_active", "aud_sleep";
+			pinctrl-0 = <&us_euro_sw_wcd_active>;
+			pinctrl-1 = <&us_euro_sw_wcd_sleep>;
+		};
+
+		tavil_hph_en0: msm_cdc_pinctrl_hph_en0 {
+			compatible = "qcom,msm-cdc-pinctrl";
+			pinctrl-names = "aud_active", "aud_sleep";
+			pinctrl-0 = <&hph_en0_wcd_active>;
+			pinctrl-1 = <&hph_en0_wcd_sleep>;
+		};
+
+		tavil_hph_en1: msm_cdc_pinctrl_hph_en1 {
+			compatible = "qcom,msm-cdc-pinctrl";
+			pinctrl-names = "aud_active", "aud_sleep";
+			pinctrl-0 = <&hph_en1_wcd_active>;
+			pinctrl-1 = <&hph_en1_wcd_sleep>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-wsa881x.dtsi b/arch/arm64/boot/dts/qcom/sdm670-wsa881x.dtsi
new file mode 100644
index 0000000..c35850d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-wsa881x.dtsi
@@ -0,0 +1,45 @@
+/* Copyright (c) 2017, 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.
+ */
+
+&slim_aud {
+	tavil_codec {
+		swr_master {
+			compatible = "qcom,swr-wcd";
+			#address-cells = <2>;
+			#size-cells = <0>;
+
+			wsa881x_0211: wsa881x@20170211 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170211>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_wcd_sd1>;
+			};
+
+			wsa881x_0212: wsa881x@20170212 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170212>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_wcd_sd2>;
+			};
+
+			wsa881x_0213: wsa881x@21170213 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170213>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_wcd_sd1>;
+			};
+
+			wsa881x_0214: wsa881x@21170214 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170214>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_wcd_sd2>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index a5e682c..0dec428 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -30,6 +30,7 @@
 
 	aliases {
 		ufshc1 = &ufshc_mem; /* Embedded UFS slot */
+		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
 	};
 
 	aliases {
@@ -825,6 +826,12 @@
 		reg-names = "pshold-base", "tcsr-boot-misc-detect";
 	};
 
+	aop-msg-client {
+		compatible = "qcom,debugfs-qmp-client";
+		mboxes = <&qmp_aop 0>;
+		mbox-names = "aop";
+	};
+
 	clock_rpmh: qcom,rpmhclk {
 		compatible = "qcom,dummycc";
 		clock-output-names = "rpmh_clocks";
@@ -1086,7 +1093,7 @@
 		qcom,mpu-enabled;
 	};
 
-	qmp_aop: mailbox@1799000c {
+	qmp_aop: qcom,qmp-aop@c300000 {
 		compatible = "qcom,qmp-mbox";
 		label = "aop";
 		reg = <0xc300000 0x100000>,
@@ -1094,6 +1101,7 @@
 		reg-names = "msgram", "irq-reg-base";
 		qcom,irq-mask = <0x1>;
 		interrupts = <0 389 1>;
+		priority = <0>;
 		mbox-desc-offset = <0x0>;
 		#mbox-cells = <1>;
 	};
@@ -1368,6 +1376,19 @@
 				<CONTROL_TCS   1>;
 	};
 
+	disp_rsc: mailbox@af20000 {
+		compatible = "qcom,tcs-drv";
+		label = "display_rsc";
+		reg = <0xaf20000 0x100>, <0xaf21c00 0x3000>;
+		interrupts = <0 129 0>;
+		#mbox-cells = <1>;
+		qcom,drv-id = <0>;
+		qcom,tcs-config = <SLEEP_TCS 1>,
+				<WAKE_TCS    1>,
+				<ACTIVE_TCS  0>,
+				<CONTROL_TCS 1>;
+	};
+
 	system_pm {
 		compatible = "qcom,system-pm";
 		mboxes = <&apps_rsc 0>;
@@ -1715,6 +1736,168 @@
 			memory-region = <&pil_mba_mem>;
 		};
 	};
+
+	qcom,venus@aae0000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0xaae0000 0x4000>;
+
+		vdd-supply = <&venus_gdsc>;
+		qcom,proxy-reg-names = "vdd";
+
+		clocks = <&clock_videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
+			 <&clock_videocc VIDEO_CC_VENUS_AHB_CLK>,
+			 <&clock_videocc VIDEO_CC_VENUS_CTL_AXI_CLK>;
+		clock-names = "core_clk", "iface_clk", "bus_clk";
+		qcom,proxy-clock-names = "core_clk", "iface_clk", "bus_clk";
+
+		qcom,pas-id = <9>;
+		qcom,msm-bus,name = "pil-venus";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<63 512 0 0>,
+			<63 512 0 304000>;
+		qcom,proxy-timeout-ms = <100>;
+		qcom,firmware-name = "venus";
+		memory-region = <&pil_video_mem>;
+		status = "ok";
+	};
+
+	qcom,turing@8300000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x8300000 0x100000>;
+		interrupts = <0 578 1>;
+
+		vdd_cx-supply = <&pm660l_s3_level>;
+		qcom,proxy-reg-names = "vdd_cx";
+		qcom,vdd_cx-uV-uA = <RPMH_REGULATOR_LEVEL_TURBO 100000>;
+
+		clocks = <&clock_rpmh RPMH_CXO_CLK>;
+		clock-names = "xo";
+		qcom,proxy-clock-names = "xo";
+
+		qcom,pas-id = <18>;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,smem-id = <601>;
+		qcom,sysmon-id = <7>;
+		qcom,ssctl-instance-id = <0x17>;
+		qcom,firmware-name = "cdsp";
+		memory-region = <&pil_cdsp_mem>;
+
+		/* GPIO inputs from turing */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_5_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_5_in 2 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_5_in 1 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_5_in 3 0>;
+
+		/* GPIO output to turing*/
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_5_out 0 0>;
+		status = "ok";
+	};
+
+	sdhc_1: sdhci@7c4000 {
+		compatible = "qcom,sdhci-msm-v5";
+		reg = <0x7C4000 0x1000>, <0x7C5000 0x1000>;
+		reg-names = "hc_mem", "cmdq_mem";
+
+		interrupts = <0 641 0>, <0 644 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <8>;
+		qcom,large-address-bus;
+
+		clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
+			<&clock_gcc GCC_SDCC1_APPS_CLK>;
+		clock-names = "iface_clk", "core_clk";
+
+		qcom,nonremovable;
+
+		qcom,scaling-lower-bus-speed-mode = "DDR52";
+		status = "disabled";
+	};
+
+	qcom,msm-cdsp-loader {
+		compatible = "qcom,cdsp-loader";
+		qcom,proc-img-to-load = "cdsp";
+	};
+
+	qcom,msm-adsprpc-mem {
+		compatible = "qcom,msm-adsprpc-mem-region";
+		memory-region = <&adsp_mem>;
+	};
+
+	qcom,msm_fastrpc {
+		compatible = "qcom,msm-fastrpc-compute";
+
+		qcom,msm_fastrpc_compute_cb1 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			iommus = <&apps_smmu 0x1421 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb2 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			iommus = <&apps_smmu 0x1422 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb3 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			iommus = <&apps_smmu 0x1423 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb4 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			iommus = <&apps_smmu 0x1424 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb5 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			iommus = <&apps_smmu 0x1425 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb6 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			iommus = <&apps_smmu 0x1426 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb7 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			qcom,secure-context-bank;
+			iommus = <&apps_smmu 0x1429 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb8 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			qcom,secure-context-bank;
+			iommus = <&apps_smmu 0x142A 0x30>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb9 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_smmu 0x1803 0x0>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb10 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_smmu 0x1804 0x0>;
+			dma-coherent;
+		};
+		qcom,msm_fastrpc_compute_cb11 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_smmu 0x1805 0x0>;
+			dma-coherent;
+		};
+	};
 };
 
 #include "sdm670-pinctrl.dtsi"
@@ -1742,6 +1925,18 @@
 	status = "ok";
 };
 
+&hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc {
+	status = "ok";
+};
+
+&hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc {
+	status = "ok";
+};
+
+&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc {
+	status = "ok";
+};
+
 &bps_gdsc {
 	status = "ok";
 };
@@ -1778,6 +1973,7 @@
 	clock-names = "core_root_clk";
 	clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK_SRC>;
 	qcom,force-enable-root-clk;
+	parent-supply = <&pm660l_s2_level>;
 	status = "ok";
 };
 
@@ -1798,3 +1994,4 @@
 #include "pm660.dtsi"
 #include "pm660l.dtsi"
 #include "sdm670-regulator.dtsi"
+#include "sdm670-audio.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts
index 0006937..a78672d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts
@@ -27,7 +27,7 @@
 / {
 	model = "Qualcomm Technologies, Inc. sdm845 4K Display Panel CDP";
 	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	qcom,board-id = <1 1>;
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts
index 2675b96..a776d42 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts
@@ -27,7 +27,7 @@
 / {
 	model = "Qualcomm Technologies, Inc. sdm845 4K Display Panel MTP";
 	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	qcom,board-id = <8 1>;
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
index 39c9d37..c6622d4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
@@ -27,6 +27,38 @@
 / {
 	model = "Qualcomm Technologies, Inc. sdm845 4K Display Panel QRD";
 	compatible = "qcom,sdm845-qrd", "qcom,sdm845", "qcom,qrd";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	qcom,board-id = <11 1>;
 };
+
+&dsi_nt35597_truly_dsc_cmd_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_sharp_4k_dsc_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+	qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+	qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_video_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts
index 5951f6d..20f80c9 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts
@@ -22,3 +22,35 @@
 	compatible = "qcom,sdm845-qrd", "qcom,sdm845", "qcom,qrd";
 	qcom,board-id = <11 1>;
 };
+
+&dsi_nt35597_truly_dsc_cmd_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_sharp_4k_dsc_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+	qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+	qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_video_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
index ab6ba18..f18137c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -245,7 +245,7 @@
 		compatible = "qcom,cam-sensor";
 		reg = <0x0>;
 		csiphy-sd-index = <0>;
-		sensor-position-roll = <90>;
+		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
 		sensor-position-yaw = <180>;
 		led-flash-src = <&led_flash_rear>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index cbd495a..3fa0ab3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -36,9 +36,7 @@
 			<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
 			<&clock_camcc CAM_CC_CSIPHY0_CLK>,
 			<&clock_camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>,
-			<&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
-			<&clock_camcc CAM_CC_IFE_0_CSID_CLK>,
-			<&clock_camcc CAM_CC_IFE_0_CSID_CLK_SRC>;
+			<&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>;
 		clock-names = "camnoc_axi_clk",
 			"soc_ahb_clk",
 			"slow_ahb_src_clk",
@@ -46,12 +44,10 @@
 			"cphy_rx_clk_src",
 			"csiphy0_clk",
 			"csi0phytimer_clk_src",
-			"csi0phytimer_clk",
-			"ife_0_csid_clk",
-			"ife_0_csid_clk_src";
+			"csi0phytimer_clk";
 		clock-cntl-level = "turbo";
 		clock-rates =
-			<0 0 0 0 320000000 0 269333333 0 0 384000000>;
+			<0 0 0 0 320000000 0 269333333 0>;
 		status = "ok";
 	};
 
@@ -74,9 +70,7 @@
 			<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
 			<&clock_camcc CAM_CC_CSIPHY1_CLK>,
 			<&clock_camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>,
-			<&clock_camcc CAM_CC_CSI1PHYTIMER_CLK>,
-			<&clock_camcc CAM_CC_IFE_1_CSID_CLK>,
-			<&clock_camcc CAM_CC_IFE_1_CSID_CLK_SRC>;
+			<&clock_camcc CAM_CC_CSI1PHYTIMER_CLK>;
 		clock-names = "camnoc_axi_clk",
 			"soc_ahb_clk",
 			"slow_ahb_src_clk",
@@ -84,12 +78,10 @@
 			"cphy_rx_clk_src",
 			"csiphy1_clk",
 			"csi1phytimer_clk_src",
-			"csi1phytimer_clk",
-			"ife_1_csid_clk",
-			"ife_1_csid_clk_src";
+			"csi1phytimer_clk";
 		clock-cntl-level = "turbo";
 		clock-rates =
-			<0 0 0 0 320000000 0 269333333 0 0 384000000>;
+			<0 0 0 0 320000000 0 269333333 0>;
 
 		status = "ok";
 	};
@@ -113,9 +105,7 @@
 			<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
 			<&clock_camcc CAM_CC_CSIPHY2_CLK>,
 			<&clock_camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>,
-			<&clock_camcc CAM_CC_CSI2PHYTIMER_CLK>,
-			<&clock_camcc CAM_CC_IFE_LITE_CSID_CLK>,
-			<&clock_camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>;
+			<&clock_camcc CAM_CC_CSI2PHYTIMER_CLK>;
 		clock-names = "camnoc_axi_clk",
 			"soc_ahb_clk",
 			"slow_ahb_src_clk",
@@ -123,12 +113,10 @@
 			"cphy_rx_clk_src",
 			"csiphy2_clk",
 			"csi2phytimer_clk_src",
-			"csi2phytimer_clk",
-			"ife_lite_csid_clk",
-			"ife_lite_csid_clk_src";
+			"csi2phytimer_clk";
 		clock-cntl-level = "turbo";
 		clock-rates =
-			<0 0 0 0 320000000 0 269333333 0 0 384000000>;
+			<0 0 0 0 320000000 0 269333333 0>;
 		status = "ok";
 	};
 
@@ -258,6 +246,23 @@
 			};
 		};
 
+		msm_cam_smmu_jpeg {
+			compatible = "qcom,msm-cam-smmu-cb";
+			iommus = <&apps_smmu 0x1060 0x8>,
+				<&apps_smmu 0x1068 0x8>;
+			label = "jpeg";
+			jpeg_iova_mem_map: iova-mem-map {
+				/* IO region is approximately 3.4 GB */
+				iova-mem-region-io {
+					iova-region-name = "io";
+					iova-region-start = <0x7400000>;
+					iova-region-len = <0xd8c00000>;
+					iova-region-id = <0x3>;
+					status = "ok";
+				};
+			};
+		};
+
 		msm_cam_icp_fw {
 			compatible = "qcom,msm-cam-smmu-fw-dev";
 			label="icp";
@@ -410,7 +415,7 @@
 			"csid0", "csid1", "csid2",
 			"ife0", "ife1", "ife2", "ipe0",
 			"ipe1", "cam-cdm-intf0", "cpas-cdm0", "bps0",
-			"icp0", "jpeg-dma0", "jpeg0", "fd0";
+			"icp0", "jpeg-dma0", "jpeg-enc0", "fd0";
 		client-axi-port-names =
 			"cam_hf_1", "cam_hf_2", "cam_hf_2", "cam_sf_1",
 			"cam_hf_1", "cam_hf_2", "cam_hf_2",
@@ -503,8 +508,8 @@
 		label = "cam-cdm-intf";
 		num-hw-cdm = <1>;
 		cdm-client-names = "vfe",
-			"jpeg-dma",
-			"jpeg",
+			"jpegdma",
+			"jpegenc",
 			"fd";
 		status = "ok";
 	};
@@ -887,4 +892,76 @@
 		clock-cntl-level = "turbo";
 		status = "ok";
 	};
+
+	qcom,cam-jpeg {
+		compatible = "qcom,cam-jpeg";
+		compat-hw-name = "qcom,jpegenc",
+			"qcom,jpegdma";
+		num-jpeg-enc = <1>;
+		num-jpeg-dma = <1>;
+		status = "ok";
+	};
+
+	cam_jpeg_enc: qcom,jpegenc@ac4e000 {
+		cell-index = <0>;
+		compatible = "qcom,cam_jpeg_enc";
+		reg-names = "jpege_hw";
+		reg = <0xac4e000 0x4000>;
+		reg-cam-base = <0x4e000>;
+		interrupt-names = "jpeg";
+		interrupts = <0 474 0>;
+		regulator-names = "camss-vdd";
+		camss-vdd-supply = <&titan_top_gdsc>;
+		clock-names = "camera_ahb",
+			"camera_axi",
+			"soc_ahb_clk",
+			"cpas_ahb_clk",
+			"camnoc_axi_clk",
+			"jpegenc_clk_src",
+			"jpegenc_clk";
+		clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>,
+			<&clock_gcc GCC_CAMERA_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_JPEG_CLK_SRC>,
+			<&clock_camcc CAM_CC_JPEG_CLK>;
+
+		clock-rates = <0 0 0 0 0 600000000 0>;
+		src-clock-name = "jpegenc_clk_src";
+		clock-cntl-level = "nominal";
+		status = "ok";
+	};
+
+	cam_jpeg_dma: qcom,jpegdma@0xac52000{
+		cell-index = <0>;
+		compatible = "qcom,cam_jpeg_dma";
+		reg-names = "jpegdma_hw";
+		reg = <0xac52000 0x4000>;
+		reg-cam-base = <0x52000>;
+		interrupt-names = "jpegdma";
+		interrupts = <0 475 0>;
+		regulator-names = "camss-vdd";
+		camss-vdd-supply = <&titan_top_gdsc>;
+		clock-names = "camera_ahb",
+			"camera_axi",
+			"soc_ahb_clk",
+			"cpas_ahb_clk",
+			"camnoc_axi_clk",
+			"jpegdma_clk_src",
+			"jpegdma_clk";
+		clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>,
+			<&clock_gcc GCC_CAMERA_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_JPEG_CLK_SRC>,
+			<&clock_camcc CAM_CC_JPEG_CLK>;
+
+		clock-rates = <0 0 0 0 0 600000000 0>;
+		src-clock-name = "jpegdma_clk_src";
+		clock-cntl-level = "nominal";
+		status = "ok";
+	};
+
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
index efc78e0..7991aad 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
@@ -26,6 +26,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM845 v1 CDP";
 	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	qcom,board-id = <1 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index c4ec012..3a0e4b6 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -11,6 +11,8 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include "sdm845-pmic-overlay.dtsi"
+#include "sdm845-pinctrl-overlay.dtsi"
 #include "sdm845-camera-sensor-cdp.dtsi"
 
 &vendor {
@@ -169,10 +171,6 @@
 	pinctrl-0 = <&sdc2_clk_on  &sdc2_cmd_on &sdc2_data_on>;
 	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
 
-	qcom,clk-rates = <400000 20000000 25000000
-				50000000 100000000 200000000>;
-	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-
 	extcon = <&extcon_storage_cd>;
 
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 3f05846..de50aec 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -27,26 +27,20 @@
 		compatible = "qcom,devbw";
 		governor = "bw_vbif";
 		qcom,src-dst-ports = <26 512>;
-		/*
-		 * active-only flag is used while registering the bus
-		 * governor.It helps release the bus vote when the CPU
-		 * subsystem is inactiv3
-		 */
-		qcom,active-only;
 		qcom,bw-tbl =
 			<     0 /*  off     */ >,
-			<   762 /*  100 MHz */ >,
-			<  1144 /*  150 MHz */ >,
-			<  1525 /*  200 MHz */ >,
-			<  2288 /*  300 MHz */ >,
-			<  3143 /*  412 MHz */ >,
-			<  4173 /*  547 MHz */ >,
-			<  5195 /*  681 MHz */ >,
-			<  5859 /*  768 MHz */ >,
-			<  7759 /*  1017 MHz */ >,
-			<  9887 /*  1296 MHz */ >,
-			<  11863 /*  1555 MHz */ >,
-			<  13763 /*  1804 MHz */ >;
+			<   381 /*  100 MHz */ >,
+			<   572 /*  150 MHz */ >,
+			<   762 /*  200 MHz */ >,
+			<  1144 /*  300 MHz */ >,
+			<  1571 /*  412 MHz */ >,
+			<  2086 /*  547 MHz */ >,
+			<  2597 /*  681 MHz */ >,
+			<  2929 /*  768 MHz */ >,
+			<  3879 /*  1017 MHz */ >,
+			<  4943 /*  1296 MHz */ >,
+			<  5931 /*  1555 MHz */ >,
+			<  6881 /*  1804 MHz */ >;
 	};
 
 	msm_gpu: qcom,kgsl-3d0@5000000 {
@@ -61,7 +55,7 @@
 
 		qcom,chipid = <0x06030000>;
 
-		qcom,initial-pwrlevel = <2>;
+		qcom,initial-pwrlevel = <5>;
 
 		qcom,gpu-quirk-hfi-use-reg;
 
@@ -99,23 +93,24 @@
 		qcom,gpubw-dev = <&gpubw>;
 		qcom,bus-control;
 		qcom,msm-bus,name = "grp3d";
+		qcom,bus-width = <32>;
 		qcom,msm-bus,num-cases = <13>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<26 512 0 0>,
 
-				<26 512 0 800000>,      // 1 bus=100
-				<26 512 0 1200000>,     // 2 bus=150
-				<26 512 0 1600000>,     // 3 bus=200
-				<26 512 0 2400000>,     // 4 bus=300
-				<26 512 0 3296000>,     // 5 bus=412
-				<26 512 0 4376000>,     // 6 bus=547
-				<26 512 0 5448000>,     // 7 bus=681
-				<26 512 0 6144000>,     // 8 bus=768
-				<26 512 0 8136000>,     // 9 bus=1017
-				<26 512 0 10368000>,    // 10 bus=1296
-				<26 512 0 12440000>,    // 11 bus=1555
-				<26 512 0 14432000>;    // 12 bus=1804
+				<26 512 0 400000>,      // 1 bus=100
+				<26 512 0 600000>,     // 2 bus=150
+				<26 512 0 800000>,     // 3 bus=200
+				<26 512 0 1200000>,     // 4 bus=300
+				<26 512 0 1648000>,     // 5 bus=412
+				<26 512 0 2188000>,     // 6 bus=547
+				<26 512 0 2724000>,     // 7 bus=681
+				<26 512 0 3072000>,     // 8 bus=768
+				<26 512 0 4068000>,     // 9 bus=1017
+				<26 512 0 5184000>,    // 10 bus=1296
+				<26 512 0 6220000>,    // 11 bus=1555
+				<26 512 0 7216000>;    // 12 bus=1804
 
 		/* GDSC regulator names */
 		regulator-names = "vddcx", "vdd";
@@ -170,31 +165,65 @@
 
 			qcom,gpu-pwrlevel@0 {
 				reg = <0>;
-				qcom,gpu-freq = <280000000>;
-				qcom,bus-freq = <4>;
-				qcom,bus-min = <3>;
-				qcom,bus-max = <5>;
+				qcom,gpu-freq = <600000000>;
+				qcom,bus-freq = <12>;
+				qcom,bus-min = <11>;
+				qcom,bus-max = <12>;
 			};
 
 
 			qcom,gpu-pwrlevel@1 {
 				reg = <1>;
-				qcom,gpu-freq = <280000000>;
-				qcom,bus-freq = <4>;
-				qcom,bus-min = <3>;
-				qcom,bus-max = <5>;
+				qcom,gpu-freq = <548000000>;
+				qcom,bus-freq = <12>;
+				qcom,bus-min = <10>;
+				qcom,bus-max = <12>;
 			};
 
 			qcom,gpu-pwrlevel@2 {
 				reg = <2>;
+				qcom,gpu-freq = <487000000>;
+				qcom,bus-freq = <10>;
+				qcom,bus-min = <9>;
+				qcom,bus-max = <11>;
+			};
+
+
+			qcom,gpu-pwrlevel@3 {
+				reg = <3>;
+				qcom,gpu-freq = <425000000>;
+				qcom,bus-freq = <9>;
+				qcom,bus-min = <8>;
+				qcom,bus-max = <10>;
+			};
+
+			qcom,gpu-pwrlevel@4 {
+				reg = <4>;
+				qcom,gpu-freq = <338000000>;
+				qcom,bus-freq = <8>;
+				qcom,bus-min = <7>;
+				qcom,bus-max = <9>;
+			};
+
+
+			qcom,gpu-pwrlevel@5 {
+				reg = <5>;
 				qcom,gpu-freq = <280000000>;
+				qcom,bus-freq = <5>;
+				qcom,bus-min = <5>;
+				qcom,bus-max = <7>;
+			};
+
+			qcom,gpu-pwrlevel@6 {
+				reg = <6>;
+				qcom,gpu-freq = <210000000>;
 				qcom,bus-freq = <4>;
 				qcom,bus-min = <3>;
 				qcom,bus-max = <5>;
 			};
 
-			qcom,gpu-pwrlevel@3 {
-				reg = <3>;
+			qcom,gpu-pwrlevel@7 {
+				reg = <7>;
 				qcom,gpu-freq = <0>;
 				qcom,bus-freq = <0>;
 				qcom,bus-min = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
new file mode 100644
index 0000000..cac5bc0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -0,0 +1,398 @@
+/* Copyright (c) 2016-2017, 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.
+ */
+
+/ {
+	/delete-node/regulator-pm8998-s4;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+	/delete-property/ vddio-supply;
+};
+
+&dsi_sharp_4k_dsc_cmd_display {
+	/delete-property/ vddio-supply;
+};
+
+&dsi_sharp_1080_cmd_display {
+	/delete-property/ vddio-supply;
+};
+
+&dsi_dual_sharp_1080_120hz_cmd_display {
+	/delete-property/ vddio-supply;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	vddio-supply = <&pm660_l11>;
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+};
+
+&dsi_dual_nt35597_truly_cmd_display {
+	vddio-supply = <&pm660_l11>;
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+	vddio-supply = <&pm660_l11>;
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+};
+
+&dsi_nt35597_truly_dsc_video_display {
+	vddio-supply = <&pm660_l11>;
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+};
+
+&sde_dp {
+	status = "disabled";
+	/delete-property/ vdda-1p2-supply;
+	/delete-property/ vdda-0p9-supply;
+	/delete-property/ qcom,dp-usbpd-detection;
+};
+
+&mdss_dp_pll {
+	status = "disabled";
+};
+
+&bluetooth {
+	/delete-property/ qca,bt-vdd-io-supply;
+	/delete-property/ qca,bt-vdd-xtal-supply;
+	/delete-property/ qca,bt-vdd-core-supply;
+	/delete-property/ qca,bt-vdd-pa-supply;
+	/delete-property/ qca,bt-vdd-ldo-supply;
+};
+
+&ufsphy_mem {
+	/delete-property/ vdda-phy-supply;
+	/delete-property/ vdda-pll-supply;
+};
+
+&ufshc_mem {
+	/delete-property/ vcc-supply;
+	/delete-property/ vccq2-supply;
+	/delete-property/ qcom,vddp-ref-clk-supply;
+};
+
+&ufsphy_card {
+	/delete-property/ vdda-phy-supply;
+	/delete-property/ vdda-pll-supply;
+};
+
+&ufshc_card {
+	/delete-property/ vcc-supply;
+	/delete-property/ vccq2-supply;
+	/delete-property/ qcom,vddp-ref-clk-supply;
+};
+
+&sdhc_2 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vdd-io-supply;
+};
+
+&vendor {
+	extcon_usb1 {
+		/delete-property/ id-gpio;
+		/delete-property/ vbus-gpio;
+		/delete-property/ pinctrl-names;
+		/delete-property/ pinctrl-0;
+	};
+
+	usb1_vbus_vreg {
+		/delete-property/ gpio;
+		/delete-property/ pinctrl-names;
+		/delete-property/ pinctrl-0;
+	};
+};
+
+&qupv3_se3_i2c {
+	nq@28 {
+		/delete-property/ qcom,nq-clkreq;
+		/* delete "nfc_clk_default" -- PMIC GPIO */
+		pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
+	};
+};
+
+&pcie0 {
+	/delete-property/ vreg-1.8-supply;
+	/delete-property/ vreg-0.9-supply;
+	/delete-property/ vreg-cx-supply;
+};
+
+&cam_csiphy0 {
+	/delete-property/ mipi-csi-vdd-supply;
+};
+
+&cam_csiphy1 {
+	/delete-property/ mipi-csi-vdd-supply;
+};
+
+&cam_csiphy2 {
+	/delete-property/ mipi-csi-vdd-supply;
+};
+
+&led_flash_rear {
+	/delete-property/ flash-source;
+	/delete-property/ torch-source;
+	/delete-property/ switch-source;
+};
+
+&led_flash_front {
+	/delete-property/ flash-source;
+	/delete-property/ torch-source;
+	/delete-property/ switch-source;
+};
+
+&actuator_regulator {
+	/delete-property/ vin-supply;
+};
+
+
+&eeprom_rear {
+	/delete-property/ cam_vio-supply;
+	/delete-property/ cam_vana-supply;
+};
+
+&eeprom_rear_aux {
+	/delete-property/ cam_vio-supply;
+	/delete-property/ cam_vana-supply;
+};
+
+&eeprom_front {
+	/delete-property/ cam_vio-supply;
+	/delete-property/ cam_vana-supply;
+};
+
+&cam_cci {
+	qcom,cam-sensor@0 {
+		/delete-property/ cam_vio-supply;
+		/delete-property/ cam_vana-supply;
+	};
+
+	qcom,cam-sensor@1 {
+		/delete-property/ cam_vio-supply;
+		/delete-property/ cam_vana-supply;
+	};
+
+	qcom,cam-sensor@2 {
+		/delete-property/ cam_vio-supply;
+		/delete-property/ cam_vana-supply;
+	};
+};
+
+&clock_gcc {
+	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_cx_ao-supply;
+};
+
+&clock_videocc {
+	/delete-property/ vdd_cx-supply;
+};
+
+&clock_camcc {
+	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_mx-supply;
+};
+
+&clock_dispcc {
+	/delete-property/ vdd_cx-supply;
+};
+
+&clock_gpucc {
+	/delete-property/ vdd_cx-supply;
+};
+
+&clock_gfx {
+	/delete-property/ vdd_gfx-supply;
+	/delete-property/ vdd_mx-supply;
+};
+
+&pil_modem {
+	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_mx-supply;
+};
+
+&gpu_gx_gdsc {
+	/delete-property/ parent-supply;
+};
+
+&soc {
+	/delete-node/ gpio_keys;
+
+	qcom,lpass@17300000 {
+		/delete-property/ vdd_cx-supply;
+	};
+
+	qcom,ssc@5c00000 {
+		/delete-property/ vdd_cx-supply;
+	};
+
+	qcom,spss@1880000 {
+		/delete-property/ vdd_cx-supply;
+		/delete-property/ vdd_mx-supply;
+	};
+
+	qcom,turing@8300000 {
+		/delete-property/ vdd_cx-supply;
+	};
+
+	qcom,qbt1000 {
+		/delete-property/ qcom,finger-detect-gpio;
+	};
+
+	qcom,icnss@18800000 {
+		/delete-property/ vdd-0.8-cx-mx-supply;
+		/delete-property/ vdd-1.8-xo-supply;
+		/delete-property/ vdd-1.3-rfa-supply;
+		/delete-property/ vdd-3.3-ch0-supply;
+	};
+
+	qcom,mdss_dsi_ctrl0@ae94000 {
+		vdda-1p2-supply = <&pm660_l1>;
+	};
+
+	qcom,mdss_dsi_ctrl1@ae96000 {
+		vdda-1p2-supply = <&pm660_l1>;
+	};
+
+	qcom,mdss_dsi_phy0@ae94400 {
+		vdda-0p9-supply = <&pm660l_l1>;
+	};
+
+	qcom,mdss_dsi_phy0@ae96400 {
+		vdda-0p9-supply = <&pm660l_l1>;
+	};
+
+	gpio-regulator@1 {
+		/delete-property/ gpio;
+		/delete-property/ vin-supply;
+		/delete-property/ pinctrl-names;
+		/delete-property/ pinctrl-0;
+	};
+
+	gpio-regulator@2 {
+		/delete-property/ gpio;
+		/delete-property/ vin-supply;
+		/delete-property/ pinctrl-names;
+		/delete-property/ pinctrl-0;
+	};
+
+	/delete-node/ qcom,spmi-debug@6b22000;
+
+};
+
+&wil6210 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vddio-supply;
+};
+
+&usb0 {
+	/delete-property/ extcon;
+};
+
+&qusb_phy0 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vdda18-supply;
+	/delete-property/ vdda33-supply;
+};
+
+&usb_qmp_dp_phy {
+	/delete-property/ vdd-supply;
+	/delete-property/ core-supply;
+};
+
+&qusb_phy1 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vdda18-supply;
+	/delete-property/ vdda33-supply;
+};
+
+&usb_qmp_phy {
+	/delete-property/ vdd-supply;
+	/delete-property/ core-supply;
+};
+
+&soc {
+	/* Delete all regulators */
+	/delete-node/ cprh-ctrl@17dc0000;
+	/delete-node/ cprh-ctrl@17db0000;
+	/delete-node/ rpmh-regulator-ebilvl;
+	/delete-node/ rpmh-regulator-smpa2;
+	/delete-node/ rpmh-regulator-smpa3;
+	/delete-node/ rpmh-regulator-smpa5;
+	/delete-node/ rpmh-regulator-mxlvl;
+	/delete-node/ rpmh-regulator-smpa7;
+	/delete-node/ rpmh-regulator-cxlvl;
+	/delete-node/ rpmh-regulator-ldoa1;
+	/delete-node/ rpmh-regulator-ldoa2;
+	/delete-node/ rpmh-regulator-ldoa3;
+	/delete-node/ rpmh-regulator-lmxlvl;
+	/delete-node/ rpmh-regulator-ldoa5;
+	/delete-node/ rpmh-regulator-ldoa6;
+	/delete-node/ rpmh-regulator-ldoa7;
+	/delete-node/ rpmh-regulator-ldoa8;
+	/delete-node/ rpmh-regulator-ldoa9;
+	/delete-node/ rpmh-regulator-ldoa10;
+	/delete-node/ rpmh-regulator-ldoa11;
+	/delete-node/ rpmh-regulator-ldoa12;
+	/delete-node/ rpmh-regulator-ldoa13;
+	/delete-node/ rpmh-regulator-ldoa14;
+	/delete-node/ rpmh-regulator-ldoa15;
+	/delete-node/ rpmh-regulator-ldoa16;
+	/delete-node/ rpmh-regulator-ldoa17;
+	/delete-node/ rpmh-regulator-ldoa18;
+	/delete-node/ rpmh-regulator-ldoa19;
+	/delete-node/ rpmh-regulator-ldoa20;
+	/delete-node/ rpmh-regulator-ldoa21;
+	/delete-node/ rpmh-regulator-ldoa22;
+	/delete-node/ rpmh-regulator-ldoa23;
+	/delete-node/ rpmh-regulator-ldoa24;
+	/delete-node/ rpmh-regulator-ldoa25;
+	/delete-node/ rpmh-regulator-ldoa26;
+	/delete-node/ rpmh-regulator-lcxlvl;
+	/delete-node/ rpmh-regulator-ldoa28;
+	/delete-node/ rpmh-regulator-vsa1;
+	/delete-node/ rpmh-regulator-vsa2;
+	/delete-node/ rpmh-regulator-bobb1;
+	/delete-node/ rpmh-regulator-gfxlvl;
+	/delete-node/ rpmh-regulator-msslvl;
+	/delete-node/ rpmh-regulator-smpc3;
+};
+
+&spmi_bus {
+	/delete-node/ qcom,pm8998@0;
+	/delete-node/ qcom,pm8998@1;
+	/delete-node/ qcom,pm8005@4;
+	/delete-node/ qcom,pm8005@5;
+};
+
+/delete-node/ &pmi8998_lsid0;
+/delete-node/ &pmi8998_lsid1;
+/delete-node/ &ext_5v_boost;
+
+#include "pm660.dtsi"
+#include "pm660l.dtsi"
+#include "sdm670-regulator.dtsi"
+
+&soc {
+	/delete-node/ thermal-zones;
+};
+
+&lmh_dcvs1 {
+	/delete-property/ isens_vref-supply;
+	/delete-property/ isens-vref-settings;
+};
+
+&pm660l_wled {
+	qcom,led-strings-list = [01 02];
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi
new file mode 100644
index 0000000..f861ca3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi
@@ -0,0 +1,81 @@
+/* Copyright (c) 2017, 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 "sdm670-audio.dtsi"
+
+&msm_audio_ion {
+	iommus = <&apps_smmu 0x1821 0x0>;
+	qcom,smmu-sid-mask = /bits/ 64 <0xf>;
+};
+
+&qupv3_se8_spi {
+	status = "okay";
+};
+
+&pm660l_3 {
+	/delete-node/analog-codec;
+};
+
+&soc {
+	/delete-node/msm-sdw-codec@62ec1000;
+	/delete-node/sound;
+	/delete-node/cdc_pdm_pinctrl;
+	/delete-node/wsa_spkr_en1_pinctrl;
+	/delete-node/wsa_spkr_en2_pinctrl;
+	/delete-node/sdw_clk_data_pinctrl;
+};
+
+&msm_audio_ion {
+	iommus = <&apps_smmu 0x1821 0x0>;
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+	qcom,gpio-connect = <&tlmm 54 0>;
+};
+
+&wdsp_mgr {
+	status = "okay";
+};
+
+&wdsp_glink {
+	status = "okay";
+};
+
+&slim_aud {
+	status = "okay";
+};
+
+&dai_slim {
+	status = "okay";
+};
+
+&wcd934x_cdc {
+	status = "okay";
+};
+
+&clock_audio_lnbb {
+	status = "okay";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&tavil_snd {
+	status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
new file mode 100644
index 0000000..da59bcf
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
@@ -0,0 +1,30 @@
+/* Copyright (c) 2017, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v1 Interposer SDM670 CDP";
+	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
new file mode 100644
index 0000000..ebb5e8f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2017, 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm845-interposer-sdm670.dtsi"
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM sdm845 v1 Interposer SDM670 CDP";
+	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+	qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
new file mode 100644
index 0000000..ad15615
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
@@ -0,0 +1,15 @@
+/* Copyright (c) 2017, 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 "sdm845-cdp.dtsi"
+#include "sdm845-interposer-pm660.dtsi"
+#include "sdm845-interposer-sdm670-audio.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
new file mode 100644
index 0000000..3ca15b9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
@@ -0,0 +1,30 @@
+/* Copyright (c) 2017, 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v1 Interposer SDM670 MTP";
+	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <8 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
new file mode 100644
index 0000000..39664f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2017, 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm845-interposer-sdm670.dtsi"
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM sdm845 v1 Interposer SDM670 MTP";
+	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+	qcom,board-id = <8 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
new file mode 100644
index 0000000..c709770
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2017, 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 "sdm845-mtp.dtsi"
+#include "sdm845-interposer-pm660.dtsi"
+#include "sdm845-interposer-sdm670-audio.dtsi"
+
+&qupv3_se10_i2c {
+	/delete-node/ qcom,smb1355@8;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dts
new file mode 100644
index 0000000..c5e4ae1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dts
@@ -0,0 +1,21 @@
+/* Copyright (c) 2017, 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.
+ */
+
+/dts-v1/;
+
+#include "sdm845-interposer-sdm670.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 Interposer SDM670";
+	compatible = "qcom,sdm845";
+	qcom,msm-id = <321 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dtsi
new file mode 100644
index 0000000..9341507
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dtsi
@@ -0,0 +1,20 @@
+/* Copyright (c) 2017, 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 "sdm845.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 Interposer SDM670";
+	compatible = "qcom,sdm845";
+	qcom,msm-id = <321 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
index 45941a1..2d1d9b6 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
@@ -26,6 +26,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM845 v1 MTP";
 	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	qcom,board-id = <8 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 1453975..c3e8b60 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -11,6 +11,8 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include "sdm845-pmic-overlay.dtsi"
+#include "sdm845-pinctrl-overlay.dtsi"
 #include "sdm845-camera-sensor-mtp.dtsi"
 #include "smb1355.dtsi"
 
@@ -245,10 +247,6 @@
 	pinctrl-0 = <&sdc2_clk_on  &sdc2_cmd_on &sdc2_data_on>;
 	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
 
-	qcom,clk-rates = <400000 20000000 25000000
-				50000000 100000000 200000000>;
-	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-
 	extcon = <&extcon_storage_cd>;
 
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl-overlay.dtsi
new file mode 100644
index 0000000..8dd75b69
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl-overlay.dtsi
@@ -0,0 +1,51 @@
+/* Copyright (c) 2017, 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.
+ */
+
+&pmi8998_gpios {
+	usb2_vbus_boost {
+		usb2_vbus_boost_default: usb2_vbus_boost_default {
+			pins = "gpio2";
+			function = "normal";
+			output-low;
+			power-source = <0>;
+		};
+	};
+
+	usb2_vbus_det {
+		usb2_vbus_det_default: usb2_vbus_det_default {
+			pins = "gpio8";
+			function = "normal";
+			input-enable;
+			bias-pull-down;
+			power-source = <1>;	/* VPH input supply */
+		};
+	};
+
+	usb2_id_det {
+		usb2_id_det_default: usb2_id_det_default {
+			pins = "gpio9";
+			function = "normal";
+			input-enable;
+			bias-pull-up;
+			power-source = <0>;
+		};
+	};
+
+	usb2_ext_5v_boost {
+		usb2_ext_5v_boost_default: usb2_ext_5v_boost_default {
+			pins = "gpio10";
+			function = "normal";
+			output-low;
+			power-source = <0>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index 2a7b6d1..3e27297 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -1400,6 +1400,90 @@
 			};
 		};
 
+		quat_tdm {
+			quat_tdm_sleep: quat_tdm_sleep {
+				mux {
+					pins = "gpio58", "gpio59";
+					function = "qua_mi2s";
+				};
+
+				config {
+					pins = "gpio58", "gpio59";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+
+			quat_tdm_active: quat_tdm_active {
+				mux {
+					pins = "gpio58", "gpio59";
+					function = "qua_mi2s";
+				};
+
+				config {
+					pins = "gpio58", "gpio59";
+					drive-strength = <8>;   /* 8 mA */
+					bias-disable;           /* NO PULL */
+				};
+			};
+		};
+
+		quat_tdm_dout {
+			quat_tdm_dout_sleep: quat_tdm_dout_sleep {
+				mux {
+					pins = "gpio61";
+					function = "qua_mi2s";
+				};
+
+				config {
+					pins = "gpio61";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+
+			quat_tdm_dout_active: quat_tdm_dout_active {
+				mux {
+					pins = "gpio61";
+					function = "qua_mi2s";
+				};
+
+				config {
+					pins = "gpio61";
+					drive-strength = <2>;   /* 2 mA */
+					bias-disable;           /* NO PULL */
+				};
+			};
+		};
+
+		quat_tdm_din {
+			quat_tdm_din_sleep: quat_tdm_din_sleep {
+				mux {
+					pins = "gpio60";
+					function = "qua_mi2s";
+				};
+
+				config {
+					pins = "gpio60";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+
+			quat_tdm_din_active: quat_tdm_din_active {
+				mux {
+					pins = "gpio60";
+					function = "qua_mi2s";
+				};
+
+				config {
+					pins = "gpio60";
+					drive-strength = <2>;   /* 2 mA */
+					bias-disable;           /* NO PULL */
+				};
+			};
+		};
+
 		/* QUPv3 South SE mappings */
 		/* SE 0 pin mappings */
 		qupv3_se0_i2c_pins: qupv3_se0_i2c_pins {
@@ -2667,7 +2751,7 @@
 
 			config {
 				pins = "gpio80","gpio79";
-				bias-disable; /* No PULL */
+				bias-pull-down; /* PULL DOWN */
 				drive-strength = <2>; /* 2 MA */
 			};
 		};
@@ -2723,7 +2807,7 @@
 
 			config {
 				pins = "gpio28";
-				bias-disable; /* No PULL */
+				bias-pull-down; /* PULL DOWN */
 				drive-strength = <2>; /* 2 MA */
 			};
 		};
@@ -2780,7 +2864,7 @@
 			};
 			config {
 				pins = "gpio9","gpio8";
-				bias-disable; /* No PULL */
+				bias-pull-down; /* PULL DOWN */
 				drive-strength = <2>; /* 2 MA */
 			};
 		};
@@ -2927,43 +3011,3 @@
 		};
 	};
 };
-
-&pmi8998_gpios {
-	usb2_vbus_boost {
-		usb2_vbus_boost_default: usb2_vbus_boost_default {
-			pins = "gpio2";
-			function = "normal";
-			output-low;
-			power-source = <0>;
-		};
-	};
-
-	usb2_vbus_det {
-		usb2_vbus_det_default: usb2_vbus_det_default {
-			pins = "gpio8";
-			function = "normal";
-			input-enable;
-			bias-pull-down;
-			power-source = <1>;	/* VPH input supply */
-		};
-	};
-
-	usb2_id_det {
-		usb2_id_det_default: usb2_id_det_default {
-			pins = "gpio9";
-			function = "normal";
-			input-enable;
-			bias-pull-up;
-			power-source = <0>;
-		};
-	};
-
-	usb2_ext_5v_boost {
-		usb2_ext_5v_boost_default: usb2_ext_5v_boost_default {
-			pins = "gpio10";
-			function = "normal";
-			output-low;
-			power-source = <0>;
-		};
-	};
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
index 6215771..c8698c28 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
@@ -51,7 +51,7 @@
 				reg = <2>;
 				label = "l3-pc";
 				qcom,psci-mode = <0x4>;
-				qcom,latency-us = <4562>;
+				qcom,latency-us = <3201>;
 				qcom,ss-power = <408>;
 				qcom,energy-overhead = <2421840>;
 				qcom,time-overhead = <5376>;
@@ -105,7 +105,7 @@
 					reg = <1>;
 					qcom,psci-cpu-mode = <0x2>;
 					qcom,spm-cpu-mode = "ret";
-					qcom,latency-us = <86>;
+					qcom,latency-us = <119>;
 					qcom,ss-power = <449>;
 					qcom,energy-overhead = <78456>;
 					qcom,time-overhead = <167>;
@@ -115,7 +115,7 @@
 					reg = <2>;
 					qcom,spm-cpu-mode = "pc";
 					qcom,psci-cpu-mode = <0x3>;
-					qcom,latency-us = <612>;
+					qcom,latency-us = <461>;
 					qcom,ss-power = <436>;
 					qcom,energy-overhead = <418225>;
 					qcom,time-overhead = <885>;
@@ -127,7 +127,7 @@
 					reg = <3>;
 					qcom,spm-cpu-mode = "rail-pc";
 					qcom,psci-cpu-mode = <0x4>;
-					qcom,latency-us = <700>;
+					qcom,latency-us = <531>;
 					qcom,ss-power = <400>;
 					qcom,energy-overhead = <428225>;
 					qcom,time-overhead = <1000>;
@@ -157,7 +157,7 @@
 					reg = <1>;
 					qcom,psci-cpu-mode = <0x2>;
 					qcom,spm-cpu-mode = "ret";
-					qcom,latency-us = <86>;
+					qcom,latency-us = <116>;
 					qcom,ss-power = <449>;
 					qcom,energy-overhead = <78456>;
 					qcom,time-overhead = <167>;
@@ -167,7 +167,7 @@
 					reg = <2>;
 					qcom,spm-cpu-mode = "pc";
 					qcom,psci-cpu-mode = <0x3>;
-					qcom,latency-us = <612>;
+					qcom,latency-us = <621>;
 					qcom,ss-power = <436>;
 					qcom,energy-overhead = <418225>;
 					qcom,time-overhead = <885>;
@@ -179,7 +179,7 @@
 					reg = <3>;
 					qcom,spm-cpu-mode = "rail-pc";
 					qcom,psci-cpu-mode = <0x4>;
-					qcom,latency-us = <700>;
+					qcom,latency-us = <1061>;
 					qcom,ss-power = <400>;
 					qcom,energy-overhead = <428225>;
 					qcom,time-overhead = <1000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pmic-overlay.dtsi
new file mode 100644
index 0000000..000d65e7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-pmic-overlay.dtsi
@@ -0,0 +1,39 @@
+/* Copyright (c) 2017, 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 <dt-bindings/gpio/gpio.h>
+
+#include "pmi8998.dtsi"
+
+&vendor {
+	ext_5v_boost: ext_5v_boost {
+		status = "disabled";
+		compatible = "regulator-fixed";
+		regulator-name = "ext_5v_boost";
+		gpio = <&pmi8998_gpios 10 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+
+		regulator-enable-ramp-delay = <1600>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usb2_ext_5v_boost_default>;
+	};
+};
+
+&pmi8998_charger {
+	smb2_vconn: qcom,smb2-vconn {
+		regulator-name = "smb2-vconn";
+	};
+};
+
+&usb0 {
+	extcon = <&pmi8998_pdphy>, <&pmi8998_pdphy>, <&eud>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
index b11c912..361fa2f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
@@ -30,33 +30,31 @@
 	};
 };
 
-&wcd934x_cdc {
-	wcd_pinctrl@5 {
-		us_euro_sw_wcd_active {
-			mux {
-				pins = "gpio1";
-			};
-
-			config {
-				pins = "gpio1";
-				/delete-property/ output-high;
-				bias-high-impedance;
-			};
-		};
-
-		us_euro_sw_wcd_sleep {
-			mux {
-				pins = "gpio1";
-			};
-
-			config {
-				pins = "gpio1";
-				/delete-property/ output-low;
-				bias-high-impedance;
-			};
-		};
+&us_euro_sw_wcd_active {
+	mux {
+		pins = "gpio1";
 	};
 
+	config {
+		pins = "gpio1";
+		/delete-property/ output-high;
+		bias-high-impedance;
+	};
+};
+
+&us_euro_sw_wcd_sleep {
+	mux {
+		pins = "gpio1";
+	};
+
+	config {
+		pins = "gpio1";
+		/delete-property/ output-low;
+		bias-high-impedance;
+	};
+};
+
+&wcd934x_cdc {
 	swr_master {
 		wsa881x@20170211 {
 			compatible = "qcom,wsa881x";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts
index 6cead9d..c8136de 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts
@@ -26,6 +26,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM845 v1 QRD";
 	compatible = "qcom,sdm845-qrd", "qcom,sdm845", "qcom,qrd";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	qcom,board-id = <11 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 9cf18b7..6122eee 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -10,6 +10,8 @@
  * GNU General Public License for more details.
  */
 
+#include "sdm845-pmic-overlay.dtsi"
+#include "sdm845-pinctrl-overlay.dtsi"
 #include "smb1355.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 
@@ -37,8 +39,7 @@
 
 	qrd_batterydata: qcom,battery-data {
 		qcom,batt-id-range-pct = <15>;
-		#include "fg-gen3-batterydata-itech-3000mah.dtsi"
-		#include "fg-gen3-batterydata-ascent-3450mah.dtsi"
+		#include "fg-gen3-batterydata-gt3746a6-2900mah.dtsi"
 	};
 };
 
@@ -84,6 +85,7 @@
 
 &pmi8998_fg {
 	qcom,battery-data = <&qrd_batterydata>;
+	qcom,fg-bmd-en-delay-ms = <300>;
 };
 
 &smb1355_charger {
@@ -170,10 +172,6 @@
 	pinctrl-0 = <&sdc2_clk_on  &sdc2_cmd_on &sdc2_data_on>;
 	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
 
-	qcom,clk-rates = <400000 20000000 25000000
-				50000000 100000000 200000000>;
-	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-
 	extcon = <&extcon_storage_cd>;
 
 	status = "ok";
@@ -189,35 +187,42 @@
 	qcom,led-strings-list = [01 02];
 };
 
+&pmi8998_haptics {
+	qcom,vmax-mv = <1800>;
+	qcom,wave-play-rate-us = <4347>;
+	qcom,lra-auto-mode;
+	status = "okay";
+};
+
 &mdss_mdp {
 	connectors = <&sde_rscc &sde_wb>;
 };
 
-&dsi_sharp_4k_dsc_video {
+&dsi_nt35597_truly_dsc_cmd {
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 	qcom,mdss-dsi-bl-min-level = <1>;
 	qcom,mdss-dsi-bl-max-level = <4095>;
-	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
 	qcom,panel-mode-gpio = <&tlmm 52 0>;
 	qcom,platform-te-gpio = <&tlmm 10 0>;
 	qcom,platform-reset-gpio = <&tlmm 6 0>;
 	qcom,mdss-dsi-panel-orientation = "180";
 };
 
-&dsi_sharp_4k_dsc_cmd {
+&dsi_nt35597_truly_dsc_video {
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 	qcom,mdss-dsi-bl-min-level = <1>;
 	qcom,mdss-dsi-bl-max-level = <4095>;
-	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
 	qcom,panel-mode-gpio = <&tlmm 52 0>;
 	qcom,platform-te-gpio = <&tlmm 10 0>;
 	qcom,platform-reset-gpio = <&tlmm 6 0>;
 	qcom,mdss-dsi-panel-orientation = "180";
 };
 
-&dsi_sharp_4k_dsc_video_display {
+&dsi_nt35597_truly_dsc_cmd_display {
 	qcom,dsi-display-active;
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index b826768..55fe84b4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -453,7 +453,7 @@
 	};
 
 	apc1_cpr: cprh-ctrl@17db0000 {
-		compatible = "qcom,cprh-sdm845-kbss-regulator";
+		compatible = "qcom,cprh-sdm845-v1-kbss-regulator";
 		reg =	<0x17db0000 0x4000>,
 			<0x00784000 0x1000>,
 			<0x17830000 0x1000>;
@@ -792,6 +792,14 @@
 			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 		};
+
+		mx_cdev: mx-cdev-lvl {
+			compatible = "qcom,regulator-cooling-device";
+			regulator-cdev-supply = <&pm8998_s6_level>;
+			regulator-levels = <RPMH_REGULATOR_LEVEL_NOM
+					RPMH_REGULATOR_LEVEL_OFF>;
+			#cooling-cells = <2>;
+		};
 	};
 
 	rpmh-regulator-smpa7 {
@@ -854,6 +862,25 @@
 			qcom,init-voltage = <880000>;
 			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
 		};
+
+		pm8998_l1_ao: regulator-l1-ao {
+			regulator-name = "pm8998_l1_ao";
+			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+			regulator-min-microvolt = <880000>;
+			regulator-max-microvolt = <880000>;
+			qcom,init-voltage = <880000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+
+		regulator-l1-so {
+			regulator-name = "pm8998_l1_so";
+			qcom,set = <RPMH_REGULATOR_SET_SLEEP>;
+			regulator-min-microvolt = <880000>;
+			regulator-max-microvolt = <880000>;
+			qcom,init-voltage = <880000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+			qcom,init-enable = <0>;
+		};
 	};
 
 	rpmh-regulator-ldoa2 {
@@ -904,13 +931,6 @@
 			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 		};
-
-		mx_cdev: regulator-cdev {
-			compatible = "qcom,rpmh-reg-cdev";
-			mboxes = <&qmp_aop 0>;
-			qcom,reg-resource-name = "mx";
-			#cooling-cells = <2>;
-		};
 	};
 
 	rpmh-regulator-ldoa5 {
@@ -1420,22 +1440,4 @@
 			qcom,init-voltage = <600000>;
 		};
 	};
-
-	ext_5v_boost: ext_5v_boost {
-		status = "disabled";
-		compatible = "regulator-fixed";
-		regulator-name = "ext_5v_boost";
-		gpio = <&pmi8998_gpios 10 GPIO_ACTIVE_HIGH>;
-		enable-active-high;
-
-		regulator-enable-ramp-delay = <1600>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&usb2_ext_5v_boost_default>;
-	};
-};
-
-&pmi8998_charger {
-	smb2_vconn: qcom,smb2-vconn {
-		regulator-name = "smb2-vconn";
-	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
index 6991b17..e7fd8a0 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
@@ -11,6 +11,8 @@
  */
 
 #include <dt-bindings/spmi/spmi.h>
+#include "sdm845-pmic-overlay.dtsi"
+#include "sdm845-pinctrl-overlay.dtsi"
 
 &ufsphy_mem {
 	compatible = "qcom,ufs-phy-qrbtc-sdm845";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 6fb4f37..377f2fe 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -411,7 +411,17 @@
 
 		qcom,dp-usbpd-detection = <&pmi8998_pdphy>;
 
-		qcom,aux-cfg-settings = [00 13 04 00 0a 26 0a 03 bb 03];
+		qcom,aux-cfg0-settings = [20 00];
+		qcom,aux-cfg1-settings = [24 13 23 1d];
+		qcom,aux-cfg2-settings = [28 24];
+		qcom,aux-cfg3-settings = [2c 00];
+		qcom,aux-cfg4-settings = [30 0a];
+		qcom,aux-cfg5-settings = [34 26];
+		qcom,aux-cfg6-settings = [38 0a];
+		qcom,aux-cfg7-settings = [3c 03];
+		qcom,aux-cfg8-settings = [40 bb];
+		qcom,aux-cfg9-settings = [44 03];
+
 		qcom,max-pclk-frequency-khz = <576000>;
 
 		qcom,core-supply-entries {
@@ -472,108 +482,180 @@
 };
 
 &dsi_dual_nt35597_truly_video {
-	qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0D>;
 	qcom,mdss-dsi-t-clk-pre = <0x2D>;
-	qcom,display-topology = <2 0 2>,
-				<1 0 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_dual_nt35597_truly_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0D>;
 	qcom,mdss-dsi-t-clk-pre = <0x2D>;
-	qcom,display-topology = <2 0 2>,
-				<1 0 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_nt35597_truly_dsc_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 05 03 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0b>;
 	qcom,mdss-dsi-t-clk-pre = <0x23>;
-	qcom,display-topology = <1 1 1>,
-				<2 2 1>, /* dsc merge */
-				<2 1 1>; /* 3d mux */
-	qcom,default-topology-index = <1>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
+				05 03 03 04 00];
+			qcom,display-topology = <1 1 1>,
+						<2 2 1>, /* dsc merge */
+						<2 1 1>; /* 3d mux */
+			qcom,default-topology-index = <1>;
+		};
+	};
 };
 
 &dsi_nt35597_truly_dsc_video {
-	qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 05 03 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0b>;
 	qcom,mdss-dsi-t-clk-pre = <0x23>;
-	qcom,display-topology = <1 1 1>,
-				<2 2 1>, /* dsc merge */
-				<2 1 1>; /* 3d mux */
-	qcom,default-topology-index = <1>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
+				04 03 03 04 00];
+			qcom,display-topology = <1 1 1>,
+						<2 2 1>, /* dsc merge */
+						<2 1 1>; /* 3d mux */
+			qcom,default-topology-index = <1>;
+		};
+	};
 };
 
 &dsi_sharp_4k_dsc_video {
-	qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06 06 04 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0c>;
 	qcom,mdss-dsi-t-clk-pre = <0x27>;
-	qcom,display-topology = <2 2 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
+				06 04 03 04 00];
+			qcom,display-topology = <2 2 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_sharp_4k_dsc_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06 06 04 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0c>;
 	qcom,mdss-dsi-t-clk-pre = <0x27>;
-	qcom,display-topology = <2 2 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
+				06 04 03 04 00];
+			qcom,display-topology = <2 2 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_dual_sharp_1080_120hz_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09 09 06 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0f>;
 	qcom,mdss-dsi-t-clk-pre = <0x36>;
-	qcom,display-topology = <2 0 2>,
-				<1 0 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09
+				09 06 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_sharp_1080_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 1A 06 06 22 20 07 07 04 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0c>;
 	qcom,mdss-dsi-t-clk-pre = <0x29>;
-	qcom,display-topology = <1 0 1>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1A 06 06 22 20 07
+				07 04 03 04 00];
+			qcom,display-topology = <1 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_sim_vid {
-	qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0d>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
-	qcom,display-topology = <1 0 1>,
-				<2 0 1>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <1 0 1>,
+						<2 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_dual_sim_vid {
-	qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0d>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
-	qcom,display-topology = <2 0 2>,
-				<1 0 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_sim_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0d>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
-	qcom,display-topology = <1 0 1>,
-				<2 0 1>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <1 0 1>,
+						<2 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
 
 &dsi_dual_sim_cmd {
-	qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
 	qcom,mdss-dsi-t-clk-post = <0x0d>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
-	qcom,display-topology = <2 0 2>,
-				<1 0 2>;
-	qcom,default-topology-index = <0>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09
+				09 06 03 04 00];
+			qcom,display-topology = <2 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+		timing@1{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+		timing@2{
+			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
+				06 04 03 04 00];
+			qcom,display-topology = <2 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 17adbf4..121565e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -14,11 +14,9 @@
 	mdss_mdp: qcom,mdss_mdp@ae00000 {
 		compatible = "qcom,sde-kms";
 		reg = <0x0ae00000 0x81d40>,
-		      <0x0aeb0000 0x2008>,
-		      <0x0aeac000 0xf0>;
+		      <0x0aeb0000 0x2008>;
 		reg-names = "mdp_phys",
-			"vbif_phys",
-			"regdma_phys";
+			"vbif_phys";
 
 		clocks =
 			<&clock_gcc GCC_DISP_AHB_CLK>,
@@ -30,7 +28,7 @@
 		clock-names = "gcc_iface", "gcc_bus", "iface_clk",
 				"bus_clk", "core_clk", "vsync_clk";
 		clock-rate = <0 0 0 0 300000000 19200000 0>;
-		clock-max-rate = <0 0 0 0 430000000 19200000 0>;
+		clock-max-rate = <0 0 0 0 412500000 19200000 0>;
 
 		sde-vdd-supply = <&mdss_core_gdsc>;
 
@@ -181,9 +179,6 @@
 		/* offsets are relative to "mdp_phys + qcom,sde-off */
 		qcom,sde-inline-rot-clk-ctrl = <0x2bc 0x8>, <0x2bc 0xc>;
 
-		qcom,sde-reg-dma-off = <0>;
-		qcom,sde-reg-dma-version = <0x1>;
-		qcom,sde-reg-dma-trigger-off = <0x119c>;
 
 		qcom,sde-sspp-vig-blocks {
 			qcom,sde-vig-csc-off = <0x1a00>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sim.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sim.dtsi
index a03148d..efb337d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sim.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sim.dtsi
@@ -10,6 +10,9 @@
  * GNU General Public License for more details.
  */
 
+#include "sdm845-pmic-overlay.dtsi"
+#include "sdm845-pinctrl-overlay.dtsi"
+
 &pmi8998_charger {
 	qcom,suspend-input;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
index ec048ca..f721025 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
@@ -21,6 +21,8 @@
 		reg = <0x0a600000 0xf8c00>,
 		      <0x088ee000 0x400>;
 		reg-names = "core_base", "ahb2phy_base";
+		iommus = <&apps_smmu 0x740 0x0>;
+		qcom,smmu-s1-bypass;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
@@ -34,7 +36,7 @@
 		qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
 		qcom,num-gsi-evt-buffs = <0x3>;
 		qcom,use-pdc-interrupts;
-		extcon = <&pmi8998_pdphy>, <&pmi8998_pdphy>, <&eud>;
+		extcon = <0>, <0>, <&eud>;
 
 		clocks = <&clock_gcc GCC_USB30_PRIM_MASTER_CLK>,
 			 <&clock_gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
@@ -61,10 +63,10 @@
 			<MSM_BUS_MASTER_USB3 MSM_BUS_SLAVE_IPA_CFG 0 0>,
 			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3 0 0>,
 			<MSM_BUS_MASTER_USB3
-				MSM_BUS_SLAVE_EBI_CH0 240000 800000>,
+				MSM_BUS_SLAVE_EBI_CH0 240000 700000>,
 			<MSM_BUS_MASTER_USB3
 				MSM_BUS_SLAVE_IPA_CFG 0 2400>,
-			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3 0 80000>;
+			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3 0 40000>;
 
 		dwc3@a600000 {
 			compatible = "snps,dwc3";
@@ -331,6 +333,8 @@
 		reg = <0x0a800000 0xf8c00>,
 		      <0x088ee000 0x400>;
 		reg-names = "core_base", "ahb2phy_base";
+		iommus = <&apps_smmu 0x760 0x0>;
+		qcom,smmu-s1-bypass;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
@@ -368,8 +372,8 @@
 			<MSM_BUS_MASTER_USB3_1 MSM_BUS_SLAVE_EBI_CH0 0 0>,
 			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3_1 0 0>,
 			<MSM_BUS_MASTER_USB3_1
-				MSM_BUS_SLAVE_EBI_CH0 240000 800000>,
-			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3_1 0 80000>;
+				MSM_BUS_SLAVE_EBI_CH0 240000 700000>,
+			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3_1 0 40000>;
 
 		dwc3@a600000 {
 			compatible = "snps,dwc3";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index f5848c1..64d6d52 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -17,23 +17,619 @@
 	qcom,msm-id = <321 0x20000>;
 };
 
+&sdhc_2 {
+	/delete-property/ qcom,sdr104-wa;
+};
+
+/delete-node/ &apc0_cpr;
+/delete-node/ &apc1_cpr;
+
+&soc {
+	/* CPR controller regulators */
+	apc0_cpr: cprh-ctrl@17dc0000 {
+		compatible = "qcom,cprh-sdm845-v2-kbss-regulator";
+		reg =	<0x17dc0000 0x4000>,
+			<0x00784000 0x1000>,
+			<0x17840000 0x1000>;
+		reg-names = "cpr_ctrl", "fuse_base", "saw";
+		clocks = <&clock_gcc GCC_CPUSS_RBCPR_CLK>;
+		clock-names = "core_clk";
+		qcom,cpr-ctrl-name = "apc0";
+		qcom,cpr-controller-id = <0>;
+
+		qcom,cpr-sensor-time = <1000>;
+		qcom,cpr-loop-time = <5000000>;
+		qcom,cpr-idle-cycles = <15>;
+		qcom,cpr-up-down-delay-time = <3000>;
+		qcom,cpr-step-quot-init-min = <11>;
+		qcom,cpr-step-quot-init-max = <12>;
+		qcom,cpr-count-mode = <0>;		/* All at once */
+		qcom,cpr-count-repeat = <20>;
+		qcom,cpr-down-error-step-limit = <1>;
+		qcom,cpr-up-error-step-limit = <1>;
+		qcom,cpr-corner-switch-delay-time = <1042>;
+		qcom,cpr-voltage-settling-time = <1760>;
+		qcom,cpr-reset-step-quot-loop-en;
+
+		qcom,voltage-step = <4000>;
+		qcom,voltage-base = <352000>;
+		qcom,cpr-saw-use-unit-mV;
+
+		qcom,saw-avs-ctrl = <0x101C031>;
+		qcom,saw-avs-limit = <0x3B803B8>;
+
+		qcom,cpr-enable;
+		qcom,cpr-hw-closed-loop;
+
+		qcom,cpr-panic-reg-addr-list =
+			<0x17dc3a84 0x17dc3a88 0x17840c18>;
+		qcom,cpr-panic-reg-name-list =
+			"APSS_SILVER_CPRH_STATUS_0",
+			"APSS_SILVER_CPRH_STATUS_1",
+			"SILVER_SAW4_PMIC_STS";
+
+		qcom,cpr-aging-ref-voltage = <952000>;
+		vdd-supply = <&pm8998_s13>;
+
+		thread@0 {
+			qcom,cpr-thread-id = <0>;
+			qcom,cpr-consecutive-up = <0>;
+			qcom,cpr-consecutive-down = <0>;
+			qcom,cpr-up-threshold = <2>;
+			qcom,cpr-down-threshold = <2>;
+
+			apc0_pwrcl_vreg: regulator {
+				regulator-name = "apc0_pwrcl_corner";
+				regulator-min-microvolt = <1>;
+				regulator-max-microvolt = <18>;
+
+				qcom,cpr-fuse-corners = <4>;
+				qcom,cpr-fuse-combos = <16>;
+				qcom,cpr-speed-bins = <2>;
+				qcom,cpr-speed-bin-corners = <18 18>;
+				qcom,cpr-corners = <18>;
+
+				qcom,cpr-corner-fmax-map = <6 12 15 18>;
+
+				qcom,cpr-voltage-ceiling =
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 884000 1000000 1000000>;
+
+				qcom,cpr-voltage-floor =
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000>;
+
+				qcom,cpr-floor-to-ceiling-max-range =
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  40000  40000>;
+
+				qcom,corner-frequencies =
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 825600000  902400000  979200000
+					1056000000 1132800000 1228800000
+					1324800000 1420800000 1516800000
+					1612800000 1689600000 1766400000>;
+
+				qcom,cpr-ro-scaling-factor =
+					<2594 2795 2576 2761 2469 2673 2198
+					 2553 3188 3255 3191 2962 3055 2984
+					 2043 2947>,
+					<2594 2795 2576 2761 2469 2673 2198
+					 2553 3188 3255 3191 2962 3055 2984
+					 2043 2947>,
+					<2259 2389 2387 2531 2294 2464 2218
+					 2476 2525 2855 2817 2836 2740 2490
+					 1950 2632>,
+					<2259 2389 2387 2531 2294 2464 2218
+					 2476 2525 2855 2817 2836 2740 2490
+					 1950 2632>;
+
+				qcom,cpr-open-loop-voltage-fuse-adjustment =
+					<100000 100000 100000 100000>;
+
+				qcom,cpr-closed-loop-voltage-fuse-adjustment =
+					<100000 100000 100000 100000>;
+
+				qcom,allow-voltage-interpolation;
+				qcom,allow-quotient-interpolation;
+				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+				qcom,cpr-aging-max-voltage-adjustment = <15000>;
+				qcom,cpr-aging-ref-corner = <18>;
+				qcom,cpr-aging-ro-scaling-factor = <1620>;
+				qcom,allow-aging-voltage-adjustment =
+					/* Speed bin 0 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>;
+				qcom,allow-aging-open-loop-voltage-adjustment =
+					<1>;
+			};
+		};
+
+		thread@1 {
+			qcom,cpr-thread-id = <1>;
+			qcom,cpr-consecutive-up = <0>;
+			qcom,cpr-consecutive-down = <0>;
+			qcom,cpr-up-threshold = <2>;
+			qcom,cpr-down-threshold = <2>;
+
+			apc0_l3_vreg: regulator {
+				regulator-name = "apc0_l3_corner";
+				regulator-min-microvolt = <1>;
+				regulator-max-microvolt = <15>;
+
+				qcom,cpr-fuse-corners = <4>;
+				qcom,cpr-fuse-combos = <16>;
+				qcom,cpr-speed-bins = <2>;
+				qcom,cpr-speed-bin-corners = <14 15>;
+				qcom,cpr-corners =
+					/* Speed bin 0 */
+					<14 14 14 14 14 14 14 14>,
+					/* Speed bin 1 */
+					<15 15 15 15 15 15 15 15>;
+
+				qcom,cpr-corner-fmax-map =
+					/* Speed bin 0 */
+					<4 8 11 14>,
+					/* Speed bin 1 */
+					<4 8 11 15>;
+
+				qcom,cpr-voltage-ceiling =
+					/* Speed bin 0 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  884000  884000 1000000>,
+					/* Speed bin 1 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  884000  884000 1000000
+					1000000>;
+
+				qcom,cpr-voltage-floor =
+					/* Speed bin 0 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000>,
+					/* Speed bin 1 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000
+					 568000>;
+
+				qcom,cpr-floor-to-ceiling-max-range =
+					/* Speed bin 0 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  40000>,
+					/* Speed bin 1 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  40000  40000>;
+
+				qcom,corner-frequencies =
+					/* Speed bin 0 */
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 844800000  940800000 1036800000
+					1132800000 1209600000 1305600000
+					1401600000 1478400000>,
+					/* Speed bin 1 */
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 844800000  940800000 1036800000
+					1132800000 1209600000 1305600000
+					1401600000 1497600000 1593600000>;
+
+				qcom,cpr-ro-scaling-factor =
+					<2857 3056 2828 2952 2699 2796 2447
+					 2631 2630 2579 2244 3343 3287 3137
+					 3164 2656>,
+					<2857 3056 2828 2952 2699 2796 2447
+					 2631 2630 2579 2244 3343 3287 3137
+					 3164 2656>,
+					<2439 2577 2552 2667 2461 2577 2394
+					 2536 2132 2307 2191 2903 2838 2912
+					 2501 2095>,
+					<2439 2577 2552 2667 2461 2577 2394
+					 2536 2132 2307 2191 2903 2838 2912
+					 2501 2095>;
+
+				qcom,cpr-open-loop-voltage-fuse-adjustment =
+					<100000 100000 100000 100000>;
+
+				qcom,cpr-closed-loop-voltage-fuse-adjustment =
+					<100000 100000 100000 100000>;
+
+				qcom,allow-voltage-interpolation;
+				qcom,allow-quotient-interpolation;
+				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+				qcom,cpr-aging-max-voltage-adjustment = <15000>;
+				qcom,cpr-aging-ref-corner = <14>;
+				qcom,cpr-aging-ro-scaling-factor = <1620>;
+				qcom,allow-aging-voltage-adjustment =
+					/* Speed bin 0 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>;
+				qcom,allow-aging-open-loop-voltage-adjustment =
+					<1>;
+			};
+		};
+	};
+
+	apc1_cpr: cprh-ctrl@17db0000 {
+		compatible = "qcom,cprh-sdm845-v2-kbss-regulator";
+		reg =	<0x17db0000 0x4000>,
+			<0x00784000 0x1000>,
+			<0x17830000 0x1000>;
+		reg-names = "cpr_ctrl", "fuse_base", "saw";
+		clocks = <&clock_gcc GCC_CPUSS_RBCPR_CLK>;
+		clock-names = "core_clk";
+		qcom,cpr-ctrl-name = "apc1";
+		qcom,cpr-controller-id = <1>;
+
+		qcom,cpr-sensor-time = <1000>;
+		qcom,cpr-loop-time = <5000000>;
+		qcom,cpr-idle-cycles = <15>;
+		qcom,cpr-up-down-delay-time = <3000>;
+		qcom,cpr-step-quot-init-min = <9>;
+		qcom,cpr-step-quot-init-max = <14>;
+		qcom,cpr-count-mode = <0>;		/* All at once */
+		qcom,cpr-count-repeat = <20>;
+		qcom,cpr-down-error-step-limit = <1>;
+		qcom,cpr-up-error-step-limit = <1>;
+		qcom,cpr-corner-switch-delay-time = <1042>;
+		qcom,cpr-voltage-settling-time = <1760>;
+		qcom,cpr-reset-step-quot-loop-en;
+
+		qcom,apm-threshold-voltage = <800000>;
+		qcom,apm-crossover-voltage = <880000>;
+		qcom,mem-acc-threshold-voltage = <852000>;
+		qcom,mem-acc-crossover-voltage = <852000>;
+
+		qcom,voltage-step = <4000>;
+		qcom,voltage-base = <352000>;
+		qcom,cpr-saw-use-unit-mV;
+
+		qcom,saw-avs-ctrl = <0x101C031>;
+		qcom,saw-avs-limit = <0x4700470>;
+
+		qcom,cpr-enable;
+		qcom,cpr-hw-closed-loop;
+
+		qcom,cpr-panic-reg-addr-list =
+			<0x17db3a84 0x17830c18>;
+		qcom,cpr-panic-reg-name-list =
+			"APSS_GOLD_CPRH_STATUS_0", "GOLD_SAW4_PMIC_STS";
+
+		qcom,cpr-aging-ref-voltage = <1136000>;
+		vdd-supply = <&pm8998_s12>;
+
+		thread@0 {
+			qcom,cpr-thread-id = <0>;
+			qcom,cpr-consecutive-up = <0>;
+			qcom,cpr-consecutive-down = <0>;
+			qcom,cpr-up-threshold = <2>;
+			qcom,cpr-down-threshold = <2>;
+
+			apc1_perfcl_vreg: regulator {
+				regulator-name = "apc1_perfcl_corner";
+				regulator-min-microvolt = <1>;
+				regulator-max-microvolt = <33>;
+
+				qcom,cpr-fuse-corners = <5>;
+				qcom,cpr-fuse-combos = <16>;
+				qcom,cpr-speed-bins = <2>;
+				qcom,cpr-speed-bin-corners = <28 31>;
+				qcom,cpr-corners =
+					/* Speed bin 0 */
+					<28 28 28 28 28 28 28 28>,
+					/* Speed bin 1 */
+					<31 31 31 31 31 31 31 31>;
+
+				qcom,cpr-corner-fmax-map =
+					/* Speed bin 0 */
+					<7 14 22 27 28>,
+					/* Speed bin 1 */
+					<7 14 22 27 31>;
+
+				qcom,cpr-voltage-ceiling =
+					/* Speed bin 0 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  884000  884000
+					 884000  884000 1104000 1104000 1104000
+					1104000 1136000 1136000>,
+					/* Speed bin 1 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  884000  884000
+					 884000  884000 1104000 1104000 1104000
+					1104000 1136000 1136000 1136000 1136000
+					1136000>;
+
+				qcom,cpr-voltage-floor =
+					/* Speed bin 0 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000>,
+					/* Speed bin 1 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000>;
+
+				qcom,cpr-floor-to-ceiling-max-range =
+					/* Speed bin 0 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000>,
+					/* Speed bin 1 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  40000  40000  40000
+					 40000>;
+
+				qcom,corner-frequencies =
+					/* Speed bin 0 */
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 825600000  902400000  979200000
+					1056000000 1132800000 1209600000
+					1286400000 1363200000 1459200000
+					1536000000 1612800000 1689600000
+					1766400000 1843200000 1920000000
+					1996800000 2092800000 2169600000
+					2246400000 2323200000 2400000000
+					2400000000>,
+					/* Speed bin 1 */
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 825600000  902400000  979200000
+					1056000000 1132800000 1209600000
+					1286400000 1363200000 1459200000
+					1536000000 1612800000 1689600000
+					1766400000 1843200000 1920000000
+					1996800000 2092800000 2169600000
+					2246400000 2323200000 2400000000
+					2476800000 2553600000 2630400000
+					2707200000>;
+
+				qcom,cpr-ro-scaling-factor =
+					<2857 3056 2828 2952 2699 2796 2447
+					 2631 2630 2579 2244 3343 3287 3137
+					 3164 2656>,
+					<2857 3056 2828 2952 2699 2796 2447
+					 2631 2630 2579 2244 3343 3287 3137
+					 3164 2656>,
+					<2086 2208 2273 2408 2203 2327 2213
+					 2340 1755 2039 2049 2474 2437 2618
+					 2003 1675>,
+					<2086 2208 2273 2408 2203 2327 2213
+					 2340 1755 2039 2049 2474 2437 2618
+					 2003 1675>,
+					<2086 2208 2273 2408 2203 2327 2213
+					 2340 1755 2039 2049 2474 2437 2618
+					 2003 1675>;
+
+				qcom,cpr-open-loop-voltage-fuse-adjustment =
+					<100000 100000 100000 100000 100000>;
+
+				qcom,cpr-closed-loop-voltage-fuse-adjustment =
+					<100000 100000 100000 100000 100000>;
+
+				qcom,allow-voltage-interpolation;
+				qcom,allow-quotient-interpolation;
+				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+				qcom,cpr-aging-max-voltage-adjustment = <15000>;
+				qcom,cpr-aging-ref-corner = <27 31>;
+				qcom,cpr-aging-ro-scaling-factor = <1700>;
+				qcom,allow-aging-voltage-adjustment =
+					/* Speed bin 0 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>;
+				qcom,allow-aging-open-loop-voltage-adjustment =
+					<1>;
+			};
+		};
+	};
+};
+
+&clock_cpucc {
+	compatible = "qcom,clk-cpu-osm-v2";
+
+	vdd-l3-supply = <&apc0_l3_vreg>;
+	vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
+	vdd-perfcl-supply = <&apc1_perfcl_vreg>;
+
+	qcom,l3-speedbin0-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   844800000 0x4024062c 0x00002323 0x2 7 >,
+		<   940800000 0x40240731 0x00002727 0x2 8 >,
+		<  1036800000 0x40240836 0x00002b2b 0x2 9 >,
+		<  1132800000 0x402c093b 0x00002f2f 0x2 10 >,
+		<  1209600000 0x402c0a3f 0x00003232 0x2 11 >,
+		<  1305600000 0x40340b44 0x00003636 0x2 12 >,
+		<  1401600000 0x40340c49 0x00003a3a 0x2 13 >,
+		<  1478400000 0x403c0d4d 0x00003e3e 0x2 14 >;
+
+	qcom,l3-speedbin1-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   844800000 0x4024062c 0x00002323 0x2 7 >,
+		<   940800000 0x40240731 0x00002727 0x2 8 >,
+		<  1036800000 0x40240836 0x00002b2b 0x2 9 >,
+		<  1132800000 0x402c093b 0x00002f2f 0x2 10 >,
+		<  1209600000 0x402c0a3f 0x00003232 0x2 11 >,
+		<  1305600000 0x40340b44 0x00003636 0x2 12 >,
+		<  1401600000 0x40340c49 0x00003a3a 0x2 13 >,
+		<  1497600000 0x403c0d4e 0x00003e3e 0x2 14 >,
+		<  1593600000 0x403c0e53 0x00004242 0x2 15 >;
+
+	qcom,pwrcl-speedbin0-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   825600000 0x401c062b 0x00002222 0x1 7 >,
+		<   902400000 0x4024072f 0x00002626 0x1 8 >,
+		<   979200000 0x40240833 0x00002929 0x1 9 >,
+		<  1056000000 0x402c0937 0x00002c2c 0x2 10 >,
+		<  1132800000 0x402c0a3b 0x00002f2f 0x2 11 >,
+		<  1228800000 0x402c0b40 0x00003333 0x2 12 >,
+		<  1324800000 0x40340c45 0x00003737 0x2 13 >,
+		<  1420800000 0x40340d4a 0x00003b3b 0x2 14 >,
+		<  1516800000 0x403c0e4f 0x00003f3f 0x2 15 >,
+		<  1612800000 0x403c0f54 0x00004343 0x2 16 >,
+		<  1689600000 0x40441058 0x00004646 0x2 17 >,
+		<  1766400000 0x4044115c 0x00004a4a 0x2 18 >;
+
+	qcom,perfcl-speedbin0-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   825600000 0x401c062b 0x00002222 0x1 7 >,
+		<   902400000 0x4024072f 0x00002626 0x1 8 >,
+		<   979200000 0x40240833 0x00002929 0x1 9 >,
+		<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
+		<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
+		<  1209600000 0x402c0b3f 0x00003232 0x2 12 >,
+		<  1286400000 0x40340c43 0x00003636 0x2 13 >,
+		<  1363200000 0x40340d47 0x00003939 0x2 14 >,
+		<  1459200000 0x403c0e4c 0x00003d3d 0x2 15 >,
+		<  1536000000 0x403c0f50 0x00004040 0x2 16 >,
+		<  1612800000 0x403c1054 0x00004343 0x2 17 >,
+		<  1689600000 0x40441158 0x00004646 0x2 18 >,
+		<  1766400000 0x4044125c 0x00004a4a 0x2 19 >,
+		<  1843200000 0x40441360 0x00004d4d 0x2 20 >,
+		<  1920000000 0x404c1464 0x00005050 0x2 21 >,
+		<  1996800000 0x404c1568 0x00005353 0x2 22 >,
+		<  2092800000 0x4054166d 0x00005757 0x2 23 >,
+		<  2169600000 0x40541771 0x00005a5a 0x2 24 >,
+		<  2246400000 0x40541875 0x00005e5e 0x2 25 >,
+		<  2323200000 0x40541979 0x00006161 0x2 26 >,
+		<  2400000000 0x40541a7d 0x00006464 0x2 27 >;
+
+	qcom,perfcl-speedbin1-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   825600000 0x401c062b 0x00002222 0x1 7 >,
+		<   902400000 0x4024072f 0x00002626 0x1 8 >,
+		<   979200000 0x40240833 0x00002929 0x1 9 >,
+		<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
+		<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
+		<  1209600000 0x402c0b3f 0x00003232 0x2 12 >,
+		<  1286400000 0x40340c43 0x00003636 0x2 13 >,
+		<  1363200000 0x40340d47 0x00003939 0x2 14 >,
+		<  1459200000 0x403c0e4c 0x00003d3d 0x2 15 >,
+		<  1536000000 0x403c0f50 0x00004040 0x2 16 >,
+		<  1612800000 0x403c1054 0x00004343 0x2 17 >,
+		<  1689600000 0x40441158 0x00004646 0x2 18 >,
+		<  1766400000 0x4044125c 0x00004a4a 0x2 19 >,
+		<  1843200000 0x40441360 0x00004d4d 0x2 20 >,
+		<  1920000000 0x404c1464 0x00005050 0x2 21 >,
+		<  1996800000 0x404c1568 0x00005353 0x2 22 >,
+		<  2092800000 0x4054166d 0x00005757 0x2 23 >,
+		<  2169600000 0x40541771 0x00005a5a 0x2 24 >,
+		<  2246400000 0x40541875 0x00005e5e 0x2 25 >,
+		<  2323200000 0x40541979 0x00006161 0x2 26 >,
+		<  2400000000 0x40541a7d 0x00006464 0x2 27 >,
+		<  2476800000 0x40541b81 0x00006767 0x2 28 >,
+		<  2553600000 0x40541c85 0x00006a6a 0x2 29 >,
+		<  2630400000 0x40541d89 0x00006e6e 0x2 30 >,
+		<  2707200000 0x40541e8d 0x00007171 0x2 31 >;
+
+	qcom,l3-memacc-level-vc-bin0 = <8 13>;
+	qcom,l3-memacc-level-vc-bin1 = <8 13>;
+
+	qcom,pwrcl-memacc-level-vc-bin0 = <12 16>;
+
+	qcom,perfcl-memacc-level-vc-bin0 = <14 22>;
+	qcom,perfcl-memacc-level-vc-bin1 = <14 22>;
+};
+
 &clock_gcc {
-	compatible = "qcom,gcc-sdm845-v2";
+	compatible = "qcom,gcc-sdm845-v2", "syscon";
 };
 
 &clock_camcc {
-	compatible = "qcom,cam_cc-sdm845-v2";
+	compatible = "qcom,cam_cc-sdm845-v2", "syscon";
 };
 
 &clock_dispcc {
-	compatible = "qcom,dispcc-sdm845-v2";
+	compatible = "qcom,dispcc-sdm845-v2", "syscon";
+};
+
+&clock_gpucc {
+	compatible = "qcom,gpucc-sdm845-v2", "syscon";
+};
+
+&clock_gfx {
+	compatible = "qcom,gfxcc-sdm845-v2";
 };
 
 &clock_videocc {
-	compatible = "qcom,video_cc-sdm845-v2";
+	compatible = "qcom,video_cc-sdm845-v2", "syscon";
+};
+
+&clock_aop {
+	compatible = "qcom,aop-qmp-clk-v2";
 };
 
 &msm_vidc {
 	qcom,allowed-clock-rates = <100000000 200000000 330000000
 		404000000 444000000 533000000>;
 };
+
+&spss_utils {
+	qcom,spss-dev-firmware-name  = "spss2d";	/* 8 chars max */
+	qcom,spss-test-firmware-name = "spss2t";	/* 8 chars max */
+	qcom,spss-prod-firmware-name = "spss2p";	/* 8 chars max */
+};
+
+&mdss_mdp {
+	clock-max-rate = <0 0 0 0 430000000 19200000 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
index 1c07c5e..42299cd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
@@ -79,7 +79,7 @@
 			label = "venus-llcc";
 			qcom,bus-master = <MSM_BUS_MASTER_VIDEO_P0>;
 			qcom,bus-slave = <MSM_BUS_SLAVE_LLCC>;
-			qcom,bus-governor = "performance";
+			qcom,bus-governor = "msm-vidc-llcc";
 			qcom,bus-range-kbps = <17000 125700>;
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 11d553d..8105588 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -29,7 +29,7 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM845";
 	compatible = "qcom,sdm845";
-	qcom,msm-id = <321 0x0>;
+	qcom,msm-id = <321 0x10000>;
 	interrupt-parent = <&pdc>;
 
 	aliases {
@@ -515,12 +515,17 @@
 		#size-cells = <2>;
 		ranges;
 
-		removed_region1: removed_region1@85700000 {
+		hyp_region: hyp_region@85700000 {
 			no-map;
-			reg = <0 0x85700000 0 0x800000>;
+			reg = <0 0x85700000 0 0x600000>;
 		};
 
-		removed_region2: removed_region2@85fc0000 {
+		xbl_region: xbl_region@85e00000 {
+			no-map;
+			reg = <0 0x85e00000 0 0x100000>;
+		};
+
+		removed_region: removed_region@85fc0000 {
 			no-map;
 			reg = <0 0x85fc0000 0 0x2f40000>;
 		};
@@ -531,64 +536,70 @@
 			reg = <0 0x8ab00000 0 0x500000>;
 		};
 
-		pil_modem_mem: modem_region@8b000000 {
+		pil_ipa_fw_mem: pil_ipa_fw_region@8b000000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x8b000000 0 0x7300000>;
+			reg = <0 0x8b000000 0 0x10000>;
 		};
 
-		pil_video_mem: pil_video_region@92300000 {
+		pil_ipa_gsi_mem: pil_ipa_gsi_region@8b010000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x92300000 0 0x500000>;
+			reg = <0 0x8b010000 0 0x5000>;
 		};
 
-		pil_cdsp_mem: cdsp_regions@92800000 {
+		pil_gpu_mem: pil_gpu_region@8b015000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x92800000 0 0x800000>;
+			reg = <0 0x8b015000 0 0x1000>;
 		};
 
-		pil_adsp_mem: pil_adsp_region@93000000 {
+		pil_adsp_mem: pil_adsp_region@8b100000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x93000000 0 0x1a00000>;
+			reg = <0 0x8b100000 0 0x1a00000>;
 		};
 
-		pil_mba_mem: pil_mba_region@0x94a00000 {
-			compatible = "removed-dma-pool";
-			no-map;
-			reg = <0 0x94a00000 0 0x200000>;
+		wlan_fw_region: wlan_fw_region@8cb00000 {
+			compatible = "shared-dma-pool";
+			reg = <0 0x8cb00000 0 0x100000>;
 		};
 
-		pil_slpi_mem: pil_slpi_region@94c00000 {
+		pil_modem_mem: modem_region@8cc00000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x94c00000 0 0x1400000>;
+			reg = <0 0x8cc00000 0 0x7600000>;
 		};
 
-		pil_ipa_fw_mem: pil_ipa_fw_region@96000000 {
+		pil_video_mem: pil_video_region@94200000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x96000000 0 0x10000>;
+			reg = <0 0x94200000 0 0x500000>;
 		};
 
-		pil_ipa_gsi_mem: pil_ipa_gsi_region@96010000 {
+		pil_cdsp_mem: cdsp_regions@94700000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x96010000 0 0x5000>;
+			reg = <0 0x94700000 0 0x800000>;
 		};
 
-		pil_gpu_mem: pil_gpu_region@96015000 {
+		pil_mba_mem: pil_mba_region@0x94f00000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x96015000 0 0x1000>;
+			reg = <0 0x94f00000 0 0x200000>;
 		};
 
-		pil_spss_mem: spss_region@96100000 {
+		pil_slpi_mem: pil_slpi_region@95100000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x96100000 0 0x100000>;
+			reg = <0 0x95100000 0 0x1400000>;
+		};
+
+
+		pil_spss_mem: spss_region@96500000 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0 0x96500000 0 0x100000>;
 		};
 
 		adsp_mem: adsp_region {
@@ -602,7 +613,7 @@
 		qseecom_mem: qseecom_region {
 			compatible = "shared-dma-pool";
 			alloc-ranges = <0 0x00000000 0 0xffffffff>;
-			reusable;
+			no-map;
 			alignment = <0 0x400000>;
 			size = <0 0x1400000>;
 		};
@@ -935,10 +946,9 @@
 		qcom,core-dev-table =
 			<  300000  762 >,
 			<  748800 1720 >,
-			<  979200 2929 >,
-			< 1209600 3879 >,
-			< 1516800 4943 >,
-			< 1593600 5931 >;
+			< 1132800 2086 >,
+			< 1440000 2929 >,
+			< 1593600 3879 >;
 	};
 
 	devfreq_memlat_4: qcom,cpu4-memlat-mon {
@@ -948,10 +958,12 @@
 		qcom,cachemiss-ev = <0x2A>;
 		qcom,core-dev-table =
 			<  300000  762 >,
+			<  499200 1720 >,
+			<  806400 2086 >,
 			< 1036800 2929 >,
 			< 1190400 3879 >,
 			< 1574400 4943 >,
-			< 1804800 5931 >,
+			< 1728000 5931 >,
 			< 1958400 6881 >;
 	};
 
@@ -960,7 +972,6 @@
 		clock-names = "devfreq_clk";
 		clocks = <&clock_cpucc L3_CLUSTER0_VOTE_CLK>;
 		governor = "performance";
-		qcom,prepare-clk;
 	};
 
 	l3_cpu4: qcom,l3-cpu4 {
@@ -968,7 +979,6 @@
 		clock-names = "devfreq_clk";
 		clocks = <&clock_cpucc L3_CLUSTER1_VOTE_CLK>;
 		governor = "performance";
-		qcom,prepare-clk;
 	};
 
 	devfreq_l3lat_0: qcom,cpu0-l3lat-mon {
@@ -1154,8 +1164,8 @@
 			<   652800000 0x401c0422 0x00002020 0x1 5 >,
 			<   729600000 0x401c0526 0x00002020 0x1 6 >,
 			<   806400000 0x401c062a 0x00002222 0x1 7 >,
-			<   883200000 0x4024072e 0x00002525 0x2 8 >,
-			<   960000000 0x40240832 0x00002828 0x2 9 >;
+			<   883200000 0x4024072e 0x00002525 0x1 8 >,
+			<   960000000 0x40240832 0x00002828 0x1 9 >;
 
 		qcom,l3-speedbin1-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1165,10 +1175,10 @@
 			<   652800000 0x401c0422 0x00002020 0x1 5 >,
 			<   729600000 0x401c0526 0x00002020 0x1 6 >,
 			<   806400000 0x401c062a 0x00002222 0x1 7 >,
-			<   883200000 0x4024072e 0x00002525 0x2 8 >,
-			<   960000000 0x40240832 0x00002828 0x2 9 >,
-			<  1036800000 0x40240936 0x00002b2b 0x3 10 >,
-			<  1094400000 0x402c0a39 0x00002e2e 0x3 11 >;
+			<   883200000 0x4024072e 0x00002525 0x1 8 >,
+			<   960000000 0x40240832 0x00002828 0x1 9 >,
+			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
+			<  1094400000 0x402c0a39 0x00002e2e 0x1 11 >;
 
 		qcom,l3-speedbin2-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1178,12 +1188,12 @@
 			<   652800000 0x401c0422 0x00002020 0x1 5 >,
 			<   729600000 0x401c0526 0x00002020 0x1 6 >,
 			<   806400000 0x401c062a 0x00002222 0x1 7 >,
-			<   883200000 0x4024072e 0x00002525 0x2 8 >,
-			<   960000000 0x40240832 0x00002828 0x2 9 >,
-			<  1036800000 0x40240936 0x00002b2b 0x3 10 >,
-			<  1113600000 0x402c0a3a 0x00002e2e 0x3 11 >,
-			<  1209600000 0x402c0b3f 0x00003232 0x3 12 >,
-			<  1305600000 0x40340c44 0x00003636 0x3 13 >;
+			<   883200000 0x4024072e 0x00002525 0x1 8 >,
+			<   960000000 0x40240832 0x00002828 0x1 9 >,
+			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
+			<  1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
+			<  1209600000 0x402c0b3f 0x00003232 0x1 12 >,
+			<  1305600000 0x40340c44 0x00003636 0x1 13 >;
 
 		qcom,pwrcl-speedbin0-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1198,11 +1208,11 @@
 			<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
 			<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
 			<  1209600000 0x402c0b3f 0x00003232 0x1 12 >,
-			<  1286400000 0x40340c43 0x00003636 0x2 13 >,
-			<  1363200000 0x40340d47 0x00003939 0x2 14 >,
-			<  1440000000 0x40340e4b 0x00003c3c 0x2 15 >,
-			<  1516800000 0x403c0f4f 0x00003f3f 0x2 16 >,
-			<  1593600000 0x403c1053 0x00004242 0x2 17 >;
+			<  1286400000 0x40340c43 0x00003636 0x1 13 >,
+			<  1363200000 0x40340d47 0x00003939 0x1 14 >,
+			<  1440000000 0x40340e4b 0x00003c3c 0x1 15 >,
+			<  1516800000 0x403c0f4f 0x00003f3f 0x1 16 >,
+			<  1593600000 0x403c1053 0x00004242 0x1 17 >;
 
 		qcom,pwrcl-speedbin1-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1217,13 +1227,13 @@
 			<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
 			<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
 			<  1209600000 0x402c0b3f 0x00003232 0x1 12 >,
-			<  1286400000 0x40340c43 0x00003636 0x2 13 >,
-			<  1363200000 0x40340d47 0x00003939 0x2 14 >,
-			<  1440000000 0x40340e4b 0x00003c3c 0x2 15 >,
-			<  1516800000 0x403c0f4f 0x00003f3f 0x2 16 >,
-			<  1593600000 0x403c1053 0x00004242 0x2 17 >,
-			<  1651200000 0x403c1156 0x00004545 0x3 18 >,
-			<  1708800000 0x40441259 0x00004747 0x3 19 >;
+			<  1286400000 0x40340c43 0x00003636 0x1 13 >,
+			<  1363200000 0x40340d47 0x00003939 0x1 14 >,
+			<  1440000000 0x40340e4b 0x00003c3c 0x1 15 >,
+			<  1516800000 0x403c0f4f 0x00003f3f 0x1 16 >,
+			<  1593600000 0x403c1053 0x00004242 0x1 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x1 18 >,
+			<  1708800000 0x40441259 0x00004747 0x1 19 >;
 
 		qcom,pwrcl-speedbin2-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1238,13 +1248,13 @@
 			<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
 			<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
 			<  1209600000 0x402c0b3f 0x00003232 0x1 12 >,
-			<  1286400000 0x40340c43 0x00003636 0x2 13 >,
-			<  1363200000 0x40340d47 0x00003939 0x2 14 >,
-			<  1440000000 0x40340e4b 0x00003c3c 0x2 15 >,
-			<  1516800000 0x403c0f4f 0x00003f3f 0x2 16 >,
-			<  1593600000 0x403c1053 0x00004242 0x2 17 >,
-			<  1670400000 0x40441157 0x00004646 0x3 18 >,
-			<  1747200000 0x4044125b 0x00004949 0x3 19 >;
+			<  1286400000 0x40340c43 0x00003636 0x1 13 >,
+			<  1363200000 0x40340d47 0x00003939 0x1 14 >,
+			<  1440000000 0x40340e4b 0x00003c3c 0x1 15 >,
+			<  1516800000 0x403c0f4f 0x00003f3f 0x1 16 >,
+			<  1593600000 0x403c1053 0x00004242 0x1 17 >,
+			<  1670400000 0x40441157 0x00004646 0x1 18 >,
+			<  1747200000 0x4044125b 0x00004949 0x1 19 >;
 
 		qcom,perfcl-speedbin0-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1259,16 +1269,16 @@
 			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
 			<  1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
 			<  1190400000 0x402c0b3e 0x00003232 0x1 12 >,
-			<  1267200000 0x40340c42 0x00003535 0x2 13 >,
-			<  1344000000 0x40340d46 0x00003838 0x2 14 >,
-			<  1420800000 0x40340e4a 0x00003b3b 0x2 15 >,
-			<  1497600000 0x403c0f4e 0x00003e3e 0x2 16 >,
-			<  1574400000 0x403c1052 0x00004242 0x2 17 >,
-			<  1651200000 0x403c1156 0x00004545 0x2 18 >,
-			<  1728000000 0x4044125a 0x00004848 0x3 19 >,
-			<  1804800000 0x4044135e 0x00004b4b 0x3 20 >,
-			<  1881600000 0x404c1462 0x00004e4e 0x3 21 >,
-			<  1958400000 0x404c1566 0x00005252 0x3 22 >;
+			<  1267200000 0x40340c42 0x00003535 0x1 13 >,
+			<  1344000000 0x40340d46 0x00003838 0x1 14 >,
+			<  1420800000 0x40340e4a 0x00003b3b 0x1 15 >,
+			<  1497600000 0x403c0f4e 0x00003e3e 0x1 16 >,
+			<  1574400000 0x403c1052 0x00004242 0x1 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x1 18 >,
+			<  1728000000 0x4044125a 0x00004848 0x1 19 >,
+			<  1804800000 0x4044135e 0x00004b4b 0x1 20 >,
+			<  1881600000 0x404c1462 0x00004e4e 0x1 21 >,
+			<  1958400000 0x404c1566 0x00005252 0x1 22 >;
 
 		qcom,perfcl-speedbin1-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1283,18 +1293,18 @@
 			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
 			<  1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
 			<  1190400000 0x402c0b3e 0x00003232 0x1 12 >,
-			<  1267200000 0x40340c42 0x00003535 0x2 13 >,
-			<  1344000000 0x40340d46 0x00003838 0x2 14 >,
-			<  1420800000 0x40340e4a 0x00003b3b 0x2 15 >,
-			<  1497600000 0x403c0f4e 0x00003e3e 0x2 16 >,
-			<  1574400000 0x403c1052 0x00004242 0x2 17 >,
-			<  1651200000 0x403c1156 0x00004545 0x2 18 >,
-			<  1728000000 0x4044125a 0x00004848 0x3 19 >,
-			<  1804800000 0x4044135e 0x00004b4b 0x3 20 >,
-			<  1881600000 0x404c1462 0x00004e4e 0x3 21 >,
-			<  1958400000 0x404c1566 0x00005252 0x3 22 >,
-			<  2035200000 0x404c166a 0x00005555 0x3 23 >,
-			<  2092800000 0x4054176d 0x00005757 0x3 24 >;
+			<  1267200000 0x40340c42 0x00003535 0x1 13 >,
+			<  1344000000 0x40340d46 0x00003838 0x1 14 >,
+			<  1420800000 0x40340e4a 0x00003b3b 0x1 15 >,
+			<  1497600000 0x403c0f4e 0x00003e3e 0x1 16 >,
+			<  1574400000 0x403c1052 0x00004242 0x1 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x1 18 >,
+			<  1728000000 0x4044125a 0x00004848 0x1 19 >,
+			<  1804800000 0x4044135e 0x00004b4b 0x1 20 >,
+			<  1881600000 0x404c1462 0x00004e4e 0x1 21 >,
+			<  1958400000 0x404c1566 0x00005252 0x1 22 >,
+			<  2035200000 0x404c166a 0x00005555 0x1 23 >,
+			<  2092800000 0x4054176d 0x00005757 0x1 24 >;
 
 		qcom,perfcl-speedbin2-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1309,26 +1319,36 @@
 			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
 			<  1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
 			<  1190400000 0x402c0b3e 0x00003232 0x1 12 >,
-			<  1267200000 0x40340c42 0x00003535 0x2 13 >,
-			<  1344000000 0x40340d46 0x00003838 0x2 14 >,
-			<  1420800000 0x40340e4a 0x00003b3b 0x2 15 >,
-			<  1497600000 0x403c0f4e 0x00003e3e 0x2 16 >,
-			<  1574400000 0x403c1052 0x00004242 0x2 17 >,
-			<  1651200000 0x403c1156 0x00004545 0x2 18 >,
-			<  1728000000 0x4044125a 0x00004848 0x3 19 >,
-			<  1804800000 0x4044135e 0x00004b4b 0x3 20 >,
-			<  1881600000 0x404c1462 0x00004e4e 0x3 21 >,
-			<  1958400000 0x404c1566 0x00005252 0x3 22 >,
-			<  2035200000 0x404c166a 0x00005555 0x3 23 >,
-			<  2112000000 0x4054176e 0x00005858 0x3 24 >,
-			<  2208000000 0x40541873 0x00005c5c 0x3 25 >;
+			<  1267200000 0x40340c42 0x00003535 0x1 13 >,
+			<  1344000000 0x40340d46 0x00003838 0x1 14 >,
+			<  1420800000 0x40340e4a 0x00003b3b 0x1 15 >,
+			<  1497600000 0x403c0f4e 0x00003e3e 0x1 16 >,
+			<  1574400000 0x403c1052 0x00004242 0x1 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x1 18 >,
+			<  1728000000 0x4044125a 0x00004848 0x1 19 >,
+			<  1804800000 0x4044135e 0x00004b4b 0x1 20 >,
+			<  1881600000 0x404c1462 0x00004e4e 0x1 21 >,
+			<  1958400000 0x404c1566 0x00005252 0x1 22 >,
+			<  2035200000 0x404c166a 0x00005555 0x1 23 >,
+			<  2112000000 0x4054176e 0x00005858 0x1 24 >,
+			<  2208000000 0x40541873 0x00005c5c 0x1 25 >;
+
+		qcom,l3-memacc-level-vc-bin0 = <7 63>;
+		qcom,l3-memacc-level-vc-bin1 = <7 9>;
+		qcom,l3-memacc-level-vc-bin2 = <7 9>;
+
+		qcom,pwrcl-memacc-level-vc-bin0 = <12 63>;
+		qcom,pwrcl-memacc-level-vc-bin1 = <12 17>;
+		qcom,pwrcl-memacc-level-vc-bin2 = <12 17>;
+
+		qcom,perfcl-memacc-level-vc-bin0 = <12 18>;
+		qcom,perfcl-memacc-level-vc-bin1 = <12 18>;
+		qcom,perfcl-memacc-level-vc-bin2 = <12 18>;
 
 		qcom,up-timer =
 			<1000 1000 1000>;
 		qcom,down-timer =
 			<100000 100000 100000>;
-		qcom,pc-override-index =
-			<0 0 0>;
 		qcom,set-ret-inactive;
 		qcom,enable-llm-freq-vote;
 		qcom,llm-freq-up-timer =
@@ -1392,7 +1412,7 @@
 	};
 
 	clock_aop: qcom,aopclk {
-		compatible = "qcom,aop-qmp-clk";
+		compatible = "qcom,aop-qmp-clk-v1";
 		#clock-cells = <1>;
 		mboxes = <&qmp_aop 0>;
 		mbox-names = "qdss_clk";
@@ -1676,13 +1696,18 @@
 			<81 512 1338562 4096000>,
 			<1 608 1338562 4096000>;
 		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
-			100000000 200000000 4294967295>;
+			100750000 200000000 4294967295>;
 
 		qcom,sdr104-wa;
 
 		qcom,restore-after-cx-collapse;
 
-		qcom,devfreq,freq-table = <50000000 200000000>;
+		qcom,clk-rates = <400000 20000000 25000000
+					50000000 100000000 201500000>;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50",
+				      "SDR104";
+
+		qcom,devfreq,freq-table = <50000000 201500000>;
 		clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
 			<&clock_gcc GCC_SDCC2_APPS_CLK>;
 		clock-names = "iface_clk", "core_clk";
@@ -1966,6 +1991,7 @@
 
 	qcom,msm_fastrpc {
 		compatible = "qcom,msm-fastrpc-compute";
+		qcom,rpc-latency-us = <611>;
 
 		qcom,msm_fastrpc_compute_cb1 {
 			compatible = "qcom,msm-fastrpc-compute-cb";
@@ -2700,6 +2726,13 @@
 			 <&clock_gcc GCC_CE1_AXI_CLK>;
 		qcom,ce-opp-freq = <171430000>;
 		qcom,request-bw-before-clk;
+		qcom,smmu-s1-bypass;
+		iommus = <&apps_smmu 0x702 0x1>,
+			 <&apps_smmu 0x712 0x1>;
+	};
+
+	qcom_msmhdcp: qcom,msm_hdcp {
+		compatible = "qcom,msm-hdcp";
 	};
 
 	qcom_crypto: qcrypto@1de0000 {
@@ -2734,6 +2767,9 @@
 		qcom,use-sw-ahash-algo;
 		qcom,use-sw-aead-algo;
 		qcom,use-sw-hmac-algo;
+		qcom,smmu-s1-bypass;
+		iommus = <&apps_smmu 0x704 0x3>,
+			 <&apps_smmu 0x714 0x3>;
 	};
 
 	qcom,msm_gsi {
@@ -3614,6 +3650,9 @@
 			&tsif0_sync_active
 			&tsif1_signals_active
 			&tsif1_sync_active>;		/* dual-tsif-mode2 */
+
+		qcom,smmu-s1-bypass;
+		iommus = <&apps_smmu 0x20 0x0f>;
 	};
 };
 
@@ -3630,6 +3669,8 @@
 		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 		qcom,affinity = <1>;
 		#thermal-sensor-cells = <0>;
+		isens_vref-supply = <&pm8998_l1_ao>;
+		isens-vref-settings = <880000 880000 20000>;
 	};
 
 	wil6210: qcom,wil6210 {
@@ -3764,7 +3805,6 @@
 };
 
 #include "pm8998.dtsi"
-#include "pmi8998.dtsi"
 #include "pm8005.dtsi"
 #include "sdm845-regulator.dtsi"
 #include "sdm845-coresight.dtsi"
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
new file mode 100644
index 0000000..1b5eac8
--- /dev/null
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -0,0 +1,579 @@
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDM670=y
+CONFIG_PCI=y
+CONFIG_PCI_MSM=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_CMA=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_SKY2=y
+CONFIG_SMSC911X=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_USB_USBNET=y
+CONFIG_WIL6210=m
+# CONFIG_WIL6210_TRACING is not set
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_DIAG_CHAR=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SOUNDWIRE=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_SDM670=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB2=y
+CONFIG_QPNP_QNOVO=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_QTI_VIRTUAL_SENSOR=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_WCD9XXX_CODEC_CORE=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SPECTRA_CAMERA=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_TSPP1=y
+CONFIG_TSPP=m
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_PLANTRONICS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_GPI_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_MSM_11AD=m
+CONFIG_SEEMP_CORE=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_CLOCK_QPNP_DIV=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_QMP=y
+CONFIG_IOMMU_IO_PGTABLE_FAST=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
+CONFIG_TRACER_PKT=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
+CONFIG_MSM_QBT1000=y
+CONFIG_APSS_CORE_EA=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
+CONFIG_QCOMCCI_HWMON=y
+CONFIG_QCOM_M4M_HWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_RRADC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_DEBUG_ALIGN_RODATA=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index b8f115b..e2c6474 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -329,6 +329,7 @@
 CONFIG_MSM_BCL_PERIPHERAL_CTL=y
 CONFIG_QTI_THERMAL_LIMITS_DCVS=y
 CONFIG_QTI_VIRTUAL_SENSOR=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -508,10 +509,10 @@
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
 CONFIG_MSM_QBT1000=y
-CONFIG_APSS_CORE_EA=y
 CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_ARM_MEMLAT_MON=y
 CONFIG_QCOMCCI_HWMON=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 87ae1cc..b3130e1 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -51,7 +51,6 @@
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_SDM845=y
-CONFIG_ARCH_SDM670=y
 CONFIG_PCI=y
 CONFIG_PCI_MSM=y
 CONFIG_SCHED_MC=y
@@ -309,7 +308,6 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
 CONFIG_PINCTRL_SDM845=y
-CONFIG_PINCTRL_SDM670=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
@@ -336,8 +334,9 @@
 CONFIG_MSM_BCL_PERIPHERAL_CTL=y
 CONFIG_QTI_THERMAL_LIMITS_DCVS=y
 CONFIG_QTI_VIRTUAL_SENSOR=y
-CONFIG_QTI_REG_COOLING_DEVICE=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_WCD9XXX_CODEC_CORE=y
@@ -514,6 +513,7 @@
 CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_ICNSS=y
@@ -585,8 +585,10 @@
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index c24dd9a..1394fc2 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -341,8 +341,9 @@
 CONFIG_MSM_BCL_PERIPHERAL_CTL=y
 CONFIG_QTI_THERMAL_LIMITS_DCVS=y
 CONFIG_QTI_VIRTUAL_SENSOR=y
-CONFIG_QTI_REG_COOLING_DEVICE=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_WCD9XXX_CODEC_CORE=y
@@ -531,6 +532,7 @@
 CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_ICNSS=y
@@ -653,8 +655,10 @@
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index a55384f..afa23b0 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -113,12 +113,11 @@
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /*
- * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
- * use of this is to invoke "./ld.so someprog" to test out a new version of
- * the loader.  We need to make sure that it is out of the way of the program
- * that it will "exec", and that there is sufficient room for the brk.
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
  */
-#define ELF_ET_DYN_BASE	(2 * TASK_SIZE_64 / 3)
+#define ELF_ET_DYN_BASE		0x100000000UL
 
 #ifndef __ASSEMBLY__
 
@@ -169,7 +168,8 @@
 
 #ifdef CONFIG_COMPAT
 
-#define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
+/* PIE load location for compat arm. Must match ARM ELF_ET_DYN_BASE. */
+#define COMPAT_ELF_ET_DYN_BASE		0x000400000UL
 
 /* AArch32 registers. */
 #define COMPAT_ELF_NGREG		18
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6d22017..ef305f8 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -47,7 +47,7 @@
  * If the page is in the bottom half, we have to use the top half. If
  * the page is in the top half, we have to use the bottom half:
  *
- * T = __virt_to_phys(__hyp_idmap_text_start)
+ * T = __pa_symbol(__hyp_idmap_text_start)
  * if (T & BIT(VA_BITS - 1))
  *	HYP_VA_MIN = 0  //idmap in upper half
  * else
@@ -270,7 +270,7 @@
 	kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
 }
 
-#define kvm_virt_to_phys(x)		__virt_to_phys((unsigned long)(x))
+#define kvm_virt_to_phys(x)		__pa_symbol(x)
 
 void kvm_set_way_flush(struct kvm_vcpu *vcpu);
 void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 53211a0..5edb6ed 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -204,7 +204,8 @@
 #define __pa(x)			__virt_to_phys((unsigned long)(x))
 #define __va(x)			((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
-#define virt_to_pfn(x)      __phys_to_pfn(__virt_to_phys(x))
+#define virt_to_pfn(x)      __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
+#define sym_to_pfn(x)	    __phys_to_pfn(__pa_symbol(x))
 
 /*
  *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index dc06a33..88025ba 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -51,7 +51,7 @@
  */
 static inline void cpu_set_reserved_ttbr0(void)
 {
-	unsigned long ttbr = virt_to_phys(empty_zero_page);
+	unsigned long ttbr = __pa_symbol(empty_zero_page);
 
 	write_sysreg(ttbr, ttbr0_el1);
 	isb();
@@ -120,7 +120,7 @@
 	local_flush_tlb_all();
 	cpu_set_idmap_tcr_t0sz();
 
-	cpu_switch_mm(idmap_pg_dir, &init_mm);
+	cpu_switch_mm(lm_alias(idmap_pg_dir), &init_mm);
 }
 
 /*
@@ -135,7 +135,7 @@
 
 	phys_addr_t pgd_phys = virt_to_phys(pgd);
 
-	replace_phys = (void *)virt_to_phys(idmap_cpu_replace_ttbr1);
+	replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1);
 
 	cpu_install_idmap();
 	replace_phys(pgd_phys);
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 3845f33..c05ee84 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -53,7 +53,7 @@
  * for zero-mapped memory areas etc..
  */
 extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr)	pfn_to_page(PHYS_PFN(__pa(empty_zero_page)))
+#define ZERO_PAGE(vaddr)	phys_to_page(__pa_symbol(empty_zero_page))
 
 #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
 
diff --git a/arch/arm64/include/asm/stackprotector.h b/arch/arm64/include/asm/stackprotector.h
index fe5e287..b86a086 100644
--- a/arch/arm64/include/asm/stackprotector.h
+++ b/arch/arm64/include/asm/stackprotector.h
@@ -30,6 +30,7 @@
 	/* Try to get a semi random initial value. */
 	get_random_bytes(&canary, sizeof(canary));
 	canary ^= LINUX_VERSION_CODE;
+	canary &= CANARY_MASK;
 
 	current->stack_canary = canary;
 	__stack_chk_guard = current->stack_canary;
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..d0aa429 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -63,6 +63,11 @@
 #define memcpy(dst, src, len) __memcpy(dst, src, len)
 #define memmove(dst, src, len) __memmove(dst, src, len)
 #define memset(s, c, n) __memset(s, c, n)
+
+#ifndef __NO_FORTIFY
+#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
+#endif
+
 #endif
 
 #endif
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 2df5d5f..4d9222a 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -383,9 +383,9 @@
 {
 	unsigned long res = n;
 	kasan_check_write(to, n);
+	check_object_size(to, n, false);
 
 	if (access_ok(VERIFY_READ, from, n)) {
-		check_object_size(to, n, false);
 		res = __arch_copy_from_user(to, from, n);
 	}
 	if (unlikely(res))
@@ -396,9 +396,9 @@
 static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	kasan_check_read(from, n);
+	check_object_size(from, n, true);
 
 	if (access_ok(VERIFY_WRITE, to, n)) {
-		check_object_size(from, n, true);
 		n = __arch_copy_to_user(to, from, n);
 	}
 	return n;
diff --git a/arch/arm64/kernel/acpi_parking_protocol.c b/arch/arm64/kernel/acpi_parking_protocol.c
index a32b401..1f5655c 100644
--- a/arch/arm64/kernel/acpi_parking_protocol.c
+++ b/arch/arm64/kernel/acpi_parking_protocol.c
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/acpi.h>
+#include <linux/mm.h>
 #include <linux/types.h>
 
 #include <asm/cpu_ops.h>
@@ -109,7 +110,7 @@
 	 * that read this address need to convert this address to the
 	 * Boot-Loader's endianness before jumping.
 	 */
-	writeq_relaxed(__pa(secondary_entry), &mailbox->entry_point);
+	writeq_relaxed(__pa_symbol(secondary_entry), &mailbox->entry_point);
 	writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);
 
 	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index d4e9ecb..6c2b1b4 100644
--- a/arch/arm64/kernel/cpu-reset.h
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -24,7 +24,7 @@
 
 	el2_switch = el2_switch && !is_kernel_in_hyp_mode() &&
 		is_hyp_mode_available();
-	restart = (void *)virt_to_phys(__cpu_soft_restart);
+	restart = (void *)__pa_symbol(__cpu_soft_restart);
 
 	cpu_install_idmap();
 	restart(el2_switch, entry, arg0, arg1, arg2);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index af5a1e3..0127e1b 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -23,6 +23,7 @@
 #include <linux/sort.h>
 #include <linux/stop_machine.h>
 #include <linux/types.h>
+#include <linux/mm.h>
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
 #include <asm/cpu_ops.h>
@@ -737,7 +738,7 @@
 static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
 			   int __unused)
 {
-	phys_addr_t idmap_addr = virt_to_phys(__hyp_idmap_text_start);
+	phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
 
 	/*
 	 * Activate the lower HYP offset only if:
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index d55a7b0..8bed26a 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -50,9 +50,6 @@
  */
 extern int in_suspend;
 
-/* Find a symbols alias in the linear map */
-#define LMADDR(x)	phys_to_virt(virt_to_phys(x))
-
 /* Do we need to reset el2? */
 #define el2_reset_needed() (is_hyp_mode_available() && !is_kernel_in_hyp_mode())
 
@@ -102,8 +99,8 @@
 
 int pfn_is_nosave(unsigned long pfn)
 {
-	unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin);
-	unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1);
+	unsigned long nosave_begin_pfn = sym_to_pfn(&__nosave_begin);
+	unsigned long nosave_end_pfn = sym_to_pfn(&__nosave_end - 1);
 
 	return (pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn);
 }
@@ -125,12 +122,12 @@
 		return -EOVERFLOW;
 
 	arch_hdr_invariants(&hdr->invariants);
-	hdr->ttbr1_el1		= virt_to_phys(swapper_pg_dir);
+	hdr->ttbr1_el1		= __pa_symbol(swapper_pg_dir);
 	hdr->reenter_kernel	= _cpu_resume;
 
 	/* We can't use __hyp_get_vectors() because kvm may still be loaded */
 	if (el2_reset_needed())
-		hdr->__hyp_stub_vectors = virt_to_phys(__hyp_stub_vectors);
+		hdr->__hyp_stub_vectors = __pa_symbol(__hyp_stub_vectors);
 	else
 		hdr->__hyp_stub_vectors = 0;
 
@@ -460,7 +457,6 @@
 	void *zero_page;
 	size_t exit_size;
 	pgd_t *tmp_pg_dir;
-	void *lm_restore_pblist;
 	phys_addr_t phys_hibernate_exit;
 	void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
 					  void *, phys_addr_t, phys_addr_t);
@@ -481,12 +477,6 @@
 		goto out;
 
 	/*
-	 * Since we only copied the linear map, we need to find restore_pblist's
-	 * linear map address.
-	 */
-	lm_restore_pblist = LMADDR(restore_pblist);
-
-	/*
 	 * We need a zero page that is zero before & after resume in order to
 	 * to break before make on the ttbr1 page tables.
 	 */
@@ -537,7 +527,7 @@
 	}
 
 	hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
-		       resume_hdr.reenter_kernel, lm_restore_pblist,
+		       resume_hdr.reenter_kernel, restore_pblist,
 		       resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
 
 out:
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 6f2ac4f..f607b38 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -97,7 +97,7 @@
 	if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX))
 		page = vmalloc_to_page(addr);
 	else if (!module)
-		page = pfn_to_page(PHYS_PFN(__pa(addr)));
+		page = phys_to_page(__pa_symbol(addr));
 	else
 		return addr;
 
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 81762dd..716a5c2 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -20,6 +20,7 @@
 #include <linux/smp.h>
 #include <linux/delay.h>
 #include <linux/psci.h>
+#include <linux/mm.h>
 
 #include <uapi/linux/psci.h>
 
@@ -45,7 +46,7 @@
 
 static int cpu_psci_cpu_boot(unsigned int cpu)
 {
-	int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry));
+	int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa_symbol(secondary_entry));
 	if (err)
 		pr_err("failed to boot CPU%d (%d)\n", cpu, err);
 
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index ae02756..ba29095 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -44,6 +44,7 @@
 #include <linux/psci.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
+#include <linux/mm.h>
 
 #include <asm/acpi.h>
 #include <asm/fixmap.h>
@@ -212,10 +213,10 @@
 	struct memblock_region *region;
 	struct resource *res;
 
-	kernel_code.start   = virt_to_phys(_text);
-	kernel_code.end     = virt_to_phys(__init_begin - 1);
-	kernel_data.start   = virt_to_phys(_sdata);
-	kernel_data.end     = virt_to_phys(_end - 1);
+	kernel_code.start   = __pa_symbol(_text);
+	kernel_code.end     = __pa_symbol(__init_begin - 1);
+	kernel_data.start   = __pa_symbol(_sdata);
+	kernel_data.end     = __pa_symbol(_end - 1);
 
 	for_each_memblock(memory, region) {
 		res = alloc_bootmem_low(sizeof(*res));
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 9a00eee..9303465 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/smp.h>
 #include <linux/types.h>
+#include <linux/mm.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cpu_ops.h>
@@ -98,7 +99,7 @@
 	 * boot-loader's endianess before jumping. This is mandated by
 	 * the boot protocol.
 	 */
-	writeq_relaxed(__pa(secondary_holding_pen), release_addr);
+	writeq_relaxed(__pa_symbol(secondary_holding_pen), release_addr);
 	__flush_dcache_area((__force void *)release_addr,
 			    sizeof(*release_addr));
 
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 4bcfe01..ef3bdfd 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -37,7 +37,7 @@
 #include <asm/vdso.h>
 #include <asm/vdso_datapage.h>
 
-extern char vdso_start, vdso_end;
+extern char vdso_start[], vdso_end[];
 static unsigned long vdso_pages __ro_after_init;
 
 /*
@@ -123,15 +123,16 @@
 {
 	int i;
 	struct page **vdso_pagelist;
+	unsigned long pfn;
 
-	if (memcmp(&vdso_start, "\177ELF", 4)) {
+	if (memcmp(vdso_start, "\177ELF", 4)) {
 		pr_err("vDSO is not a valid ELF object!\n");
 		return -EINVAL;
 	}
 
-	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
 	pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-		vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+		vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
 
 	/* Allocate the vDSO pagelist, plus a page for the data. */
 	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
@@ -140,11 +141,14 @@
 		return -ENOMEM;
 
 	/* Grab the vDSO data page. */
-	vdso_pagelist[0] = pfn_to_page(PHYS_PFN(__pa(vdso_data)));
+	vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
+
 
 	/* Grab the vDSO code pages. */
+	pfn = sym_to_pfn(vdso_start);
+
 	for (i = 0; i < vdso_pages; i++)
-		vdso_pagelist[i + 1] = pfn_to_page(PHYS_PFN(__pa(&vdso_start)) + i);
+		vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
 
 	vdso_spec[0].pages = &vdso_pagelist[0];
 	vdso_spec[1].pages = &vdso_pagelist[1];
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index acbe515..7f90b7e 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -157,12 +157,13 @@
 				  dma_addr_t *dma_handle, gfp_t flags,
 				  unsigned long attrs)
 {
+	void *addr;
+
 	if (IS_ENABLED(CONFIG_ZONE_DMA) &&
 	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
 		flags |= GFP_DMA;
 	if (dev_get_cma_area(dev) && gfpflags_allow_blocking(flags)) {
 		struct page *page;
-		void *addr;
 
 		page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
 							get_order(size));
@@ -172,20 +173,20 @@
 		*dma_handle = phys_to_dma(dev, page_to_phys(page));
 		addr = page_address(page);
 		memset(addr, 0, size);
-
-		if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) ||
-		    (attrs & DMA_ATTR_STRONGLY_ORDERED)) {
-			/*
-			 * flush the caches here because we can't later
-			 */
-			__dma_flush_area(addr, size);
-			__dma_remap(page, size, __pgprot(0), true);
-		}
-
-		return addr;
 	} else {
-		return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+		addr = swiotlb_alloc_coherent(dev, size, dma_handle, flags);
 	}
+
+	if (addr && ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) ||
+			(attrs & DMA_ATTR_STRONGLY_ORDERED))) {
+		/*
+		 * flush the caches here because we can't later
+		 */
+		__dma_flush_area(addr, size);
+		__dma_remap(virt_to_page(addr), size, __pgprot(0), true);
+	}
+
+	return addr;
 }
 
 static void __dma_free_coherent(struct device *dev, size_t size,
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 0b9492e..f8ef496 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -36,6 +36,7 @@
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -211,8 +212,8 @@
 	 * linear mapping. Take care not to clip the kernel which may be
 	 * high in memory.
 	 */
-	memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),
-			ULLONG_MAX);
+	memblock_remove(max_t(u64, memstart_addr + linear_region_size,
+			__pa_symbol(_end)), ULLONG_MAX);
 	if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {
 		/* ensure that memstart_addr remains sufficiently aligned */
 		memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size,
@@ -227,7 +228,7 @@
 	 */
 	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
 		memblock_mem_limit_remove_map(memory_limit);
-		memblock_add(__pa(_text), (u64)(_end - _text));
+		memblock_add(__pa_symbol(_text), (u64)(_end - _text));
 	}
 
 	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
@@ -280,7 +281,7 @@
 	 * Register the kernel text, kernel data, initrd, and initial
 	 * pagetables with memblock.
 	 */
-	memblock_reserve(__pa(_text), _end - _text);
+	memblock_reserve(__pa_symbol(_text), _end - _text);
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start) {
 		memblock_reserve(initrd_start, initrd_end - initrd_start);
@@ -488,7 +489,8 @@
 
 void free_initmem(void)
 {
-	free_reserved_area(__va(__pa(__init_begin)), __va(__pa(__init_end)),
+	free_reserved_area(lm_alias(__init_begin),
+			   lm_alias(__init_end),
 			   0, "unused kernel");
 	/*
 	 * Unmap the __init region but leave the VM area in place. This
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 757009d..201d918 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/memblock.h>
 #include <linux/start_kernel.h>
+#include <linux/mm.h>
 
 #include <asm/mmu_context.h>
 #include <asm/kernel-pgtable.h>
@@ -26,6 +27,13 @@
 
 static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);
 
+/*
+ * The p*d_populate functions call virt_to_phys implicitly so they can't be used
+ * directly on kernel symbols (bm_p*d). All the early functions are called too
+ * early to use lm_alias so __p*d_populate functions must be used to populate
+ * with the physical address from __pa_symbol.
+ */
+
 static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr,
 					unsigned long end)
 {
@@ -33,12 +41,12 @@
 	unsigned long next;
 
 	if (pmd_none(*pmd))
-		pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
+		__pmd_populate(pmd, __pa_symbol(kasan_zero_pte), PMD_TYPE_TABLE);
 
 	pte = pte_offset_kimg(pmd, addr);
 	do {
 		next = addr + PAGE_SIZE;
-		set_pte(pte, pfn_pte(virt_to_pfn(kasan_zero_page),
+		set_pte(pte, pfn_pte(sym_to_pfn(kasan_zero_page),
 					PAGE_KERNEL));
 	} while (pte++, addr = next, addr != end && pte_none(*pte));
 }
@@ -51,7 +59,7 @@
 	unsigned long next;
 
 	if (pud_none(*pud))
-		pud_populate(&init_mm, pud, kasan_zero_pmd);
+		__pud_populate(pud, __pa_symbol(kasan_zero_pmd), PMD_TYPE_TABLE);
 
 	pmd = pmd_offset_kimg(pud, addr);
 	do {
@@ -68,7 +76,7 @@
 	unsigned long next;
 
 	if (pgd_none(*pgd))
-		pgd_populate(&init_mm, pgd, kasan_zero_pud);
+		__pgd_populate(pgd, __pa_symbol(kasan_zero_pud), PUD_TYPE_TABLE);
 
 	pud = pud_offset_kimg(pgd, addr);
 	do {
@@ -148,7 +156,7 @@
 	 */
 	memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir));
 	dsb(ishst);
-	cpu_replace_ttbr1(tmp_pg_dir);
+	cpu_replace_ttbr1(lm_alias(tmp_pg_dir));
 
 	clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
@@ -199,10 +207,10 @@
 	 */
 	for (i = 0; i < PTRS_PER_PTE; i++)
 		set_pte(&kasan_zero_pte[i],
-			pfn_pte(virt_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
+			pfn_pte(sym_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
 
 	memset(kasan_zero_page, 0, PAGE_SIZE);
-	cpu_replace_ttbr1(swapper_pg_dir);
+	cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
 
 	/* At this point kasan is fully initialized. Enable error messages */
 	init_task.kasan_depth = 0;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index f70b433..41efd5e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -32,6 +32,7 @@
 #include <linux/stop_machine.h>
 #include <linux/dma-contiguous.h>
 #include <linux/cma.h>
+#include <linux/mm.h>
 
 #include <asm/barrier.h>
 #include <asm/cputype.h>
@@ -357,8 +358,8 @@
 
 static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
 {
-	unsigned long kernel_start = __pa(_text);
-	unsigned long kernel_end = __pa(__init_begin);
+	unsigned long kernel_start = __pa_symbol(_text);
+	unsigned long kernel_end = __pa_symbol(__init_begin);
 
 	/*
 	 * Take care not to create a writable alias for the
@@ -425,21 +426,21 @@
 	unsigned long section_size;
 
 	section_size = (unsigned long)_etext - (unsigned long)_text;
-	create_mapping_late(__pa(_text), (unsigned long)_text,
+	create_mapping_late(__pa_symbol(_text), (unsigned long)_text,
 			    section_size, PAGE_KERNEL_ROX);
 	/*
 	 * mark .rodata as read only. Use __init_begin rather than __end_rodata
 	 * to cover NOTES and EXCEPTION_TABLE.
 	 */
 	section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata;
-	create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
+	create_mapping_late(__pa_symbol(__start_rodata), (unsigned long)__start_rodata,
 			    section_size, PAGE_KERNEL_RO);
 }
 
 static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
 				      pgprot_t prot, struct vm_struct *vma)
 {
-	phys_addr_t pa_start = __pa(va_start);
+	phys_addr_t pa_start = __pa_symbol(va_start);
 	unsigned long size = va_end - va_start;
 
 	BUG_ON(!PAGE_ALIGNED(pa_start));
@@ -487,7 +488,7 @@
 		 */
 		BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
 		set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START),
-			__pud(__pa(bm_pmd) | PUD_TYPE_TABLE));
+			__pud(__pa_symbol(bm_pmd) | PUD_TYPE_TABLE));
 		pud_clear_fixmap();
 	} else {
 		BUG();
@@ -518,7 +519,7 @@
 	 */
 	cpu_replace_ttbr1(__va(pgd_phys));
 	memcpy(swapper_pg_dir, pgd, PAGE_SIZE);
-	cpu_replace_ttbr1(swapper_pg_dir);
+	cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
 
 	pgd_clear_fixmap();
 	memblock_free(pgd_phys, PAGE_SIZE);
@@ -527,7 +528,7 @@
 	 * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd
 	 * allocated with it.
 	 */
-	memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,
+	memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,
 		      SWAPPER_DIR_SIZE - PAGE_SIZE);
 }
 
@@ -638,6 +639,12 @@
 	return &bm_pte[pte_index(addr)];
 }
 
+/*
+ * The p*d_populate functions call virt_to_phys implicitly so they can't be used
+ * directly on kernel symbols (bm_p*d). This function is called too early to use
+ * lm_alias so __p*d_populate functions must be used to populate with the
+ * physical address from __pa_symbol.
+ */
 void __init early_fixmap_init(void)
 {
 	pgd_t *pgd;
@@ -647,7 +654,7 @@
 
 	pgd = pgd_offset_k(addr);
 	if (CONFIG_PGTABLE_LEVELS > 3 &&
-	    !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa(bm_pud))) {
+	    !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa_symbol(bm_pud))) {
 		/*
 		 * We only end up here if the kernel mapping and the fixmap
 		 * share the top level pgd entry, which should only happen on
@@ -656,12 +663,14 @@
 		BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
 		pud = pud_offset_kimg(pgd, addr);
 	} else {
-		pgd_populate(&init_mm, pgd, bm_pud);
+		if (pgd_none(*pgd))
+			__pgd_populate(pgd, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
 		pud = fixmap_pud(addr);
 	}
-	pud_populate(&init_mm, pud, bm_pmd);
+	if (pud_none(*pud))
+		__pud_populate(pud, __pa_symbol(bm_pmd), PMD_TYPE_TABLE);
 	pmd = fixmap_pmd(addr);
-	pmd_populate_kernel(&init_mm, pmd, bm_pte);
+	__pmd_populate(pmd, __pa_symbol(bm_pte), PMD_TYPE_TABLE);
 
 	/*
 	 * The boot-ioremap range spans multiple pmds, for which
diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index de781cf..da80878 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -74,10 +74,7 @@
 			return __microMIPS_compute_return_epc(regs);
 		if (cpu_has_mips16)
 			return __MIPS16e_compute_return_epc(regs);
-		return regs->cp0_epc;
-	}
-
-	if (!delay_slot(regs)) {
+	} else if (!delay_slot(regs)) {
 		regs->cp0_epc += 4;
 		return 0;
 	}
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index c86b66b..c3f2fb3 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -399,7 +399,7 @@
  *
  * @regs:	Pointer to pt_regs
  * @insn:	branch instruction to decode
- * @returns:	-EFAULT on error and forces SIGBUS, and on success
+ * @returns:	-EFAULT on error and forces SIGILL, and on success
  *		returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
  *		evaluating the branch.
  *
@@ -431,7 +431,7 @@
 			/* Fall through */
 		case jr_op:
 			if (NO_R6EMU && insn.r_format.func == jr_op)
-				goto sigill_r6;
+				goto sigill_r2r6;
 			regs->cp0_epc = regs->regs[insn.r_format.rs];
 			break;
 		}
@@ -446,7 +446,7 @@
 		switch (insn.i_format.rt) {
 		case bltzl_op:
 			if (NO_R6EMU)
-				goto sigill_r6;
+				goto sigill_r2r6;
 		case bltz_op:
 			if ((long)regs->regs[insn.i_format.rs] < 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -459,7 +459,7 @@
 
 		case bgezl_op:
 			if (NO_R6EMU)
-				goto sigill_r6;
+				goto sigill_r2r6;
 		case bgez_op:
 			if ((long)regs->regs[insn.i_format.rs] >= 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -473,10 +473,8 @@
 		case bltzal_op:
 		case bltzall_op:
 			if (NO_R6EMU && (insn.i_format.rs ||
-			    insn.i_format.rt == bltzall_op)) {
-				ret = -SIGILL;
-				break;
-			}
+			    insn.i_format.rt == bltzall_op))
+				goto sigill_r2r6;
 			regs->regs[31] = epc + 8;
 			/*
 			 * OK we are here either because we hit a NAL
@@ -507,10 +505,8 @@
 		case bgezal_op:
 		case bgezall_op:
 			if (NO_R6EMU && (insn.i_format.rs ||
-			    insn.i_format.rt == bgezall_op)) {
-				ret = -SIGILL;
-				break;
-			}
+			    insn.i_format.rt == bgezall_op))
+				goto sigill_r2r6;
 			regs->regs[31] = epc + 8;
 			/*
 			 * OK we are here either because we hit a BAL
@@ -556,6 +552,7 @@
 	/*
 	 * These are unconditional and in j_format.
 	 */
+	case jalx_op:
 	case jal_op:
 		regs->regs[31] = regs->cp0_epc + 8;
 	case j_op:
@@ -573,7 +570,7 @@
 	 */
 	case beql_op:
 		if (NO_R6EMU)
-			goto sigill_r6;
+			goto sigill_r2r6;
 	case beq_op:
 		if (regs->regs[insn.i_format.rs] ==
 		    regs->regs[insn.i_format.rt]) {
@@ -587,7 +584,7 @@
 
 	case bnel_op:
 		if (NO_R6EMU)
-			goto sigill_r6;
+			goto sigill_r2r6;
 	case bne_op:
 		if (regs->regs[insn.i_format.rs] !=
 		    regs->regs[insn.i_format.rt]) {
@@ -601,7 +598,7 @@
 
 	case blezl_op: /* not really i_format */
 		if (!insn.i_format.rt && NO_R6EMU)
-			goto sigill_r6;
+			goto sigill_r2r6;
 	case blez_op:
 		/*
 		 * Compact branches for R6 for the
@@ -636,7 +633,7 @@
 
 	case bgtzl_op:
 		if (!insn.i_format.rt && NO_R6EMU)
-			goto sigill_r6;
+			goto sigill_r2r6;
 	case bgtz_op:
 		/*
 		 * Compact branches for R6 for the
@@ -774,35 +771,27 @@
 #else
 	case bc6_op:
 		/* Only valid for MIPS R6 */
-		if (!cpu_has_mips_r6) {
-			ret = -SIGILL;
-			break;
-		}
+		if (!cpu_has_mips_r6)
+			goto sigill_r6;
 		regs->cp0_epc += 8;
 		break;
 	case balc6_op:
-		if (!cpu_has_mips_r6) {
-			ret = -SIGILL;
-			break;
-		}
+		if (!cpu_has_mips_r6)
+			goto sigill_r6;
 		/* Compact branch: BALC */
 		regs->regs[31] = epc + 4;
 		epc += 4 + (insn.i_format.simmediate << 2);
 		regs->cp0_epc = epc;
 		break;
 	case pop66_op:
-		if (!cpu_has_mips_r6) {
-			ret = -SIGILL;
-			break;
-		}
+		if (!cpu_has_mips_r6)
+			goto sigill_r6;
 		/* Compact branch: BEQZC || JIC */
 		regs->cp0_epc += 8;
 		break;
 	case pop76_op:
-		if (!cpu_has_mips_r6) {
-			ret = -SIGILL;
-			break;
-		}
+		if (!cpu_has_mips_r6)
+			goto sigill_r6;
 		/* Compact branch: BNEZC || JIALC */
 		if (!insn.i_format.rs) {
 			/* JIALC: set $31/ra */
@@ -814,10 +803,8 @@
 	case pop10_op:
 	case pop30_op:
 		/* Only valid for MIPS R6 */
-		if (!cpu_has_mips_r6) {
-			ret = -SIGILL;
-			break;
-		}
+		if (!cpu_has_mips_r6)
+			goto sigill_r6;
 		/*
 		 * Compact branches:
 		 * bovc, beqc, beqzalc, bnvc, bnec, bnezlac
@@ -831,11 +818,17 @@
 	return ret;
 
 sigill_dsp:
-	printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
-	force_sig(SIGBUS, current);
+	pr_info("%s: DSP branch but not DSP ASE - sending SIGILL.\n",
+		current->comm);
+	force_sig(SIGILL, current);
+	return -EFAULT;
+sigill_r2r6:
+	pr_info("%s: R2 branch but r2-to-r6 emulator is not present - sending SIGILL.\n",
+		current->comm);
+	force_sig(SIGILL, current);
 	return -EFAULT;
 sigill_r6:
-	pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n",
+	pr_info("%s: R6 branch but no MIPSr6 ISA support - sending SIGILL.\n",
 		current->comm);
 	force_sig(SIGILL, current);
 	return -EFAULT;
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 4eff2ae..4c01ee5 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -83,7 +83,7 @@
 	}
 
 	seq_printf(m, "isa\t\t\t:"); 
-	if (cpu_has_mips_r1)
+	if (cpu_has_mips_1)
 		seq_printf(m, " mips1");
 	if (cpu_has_mips_2)
 		seq_printf(m, "%s", " mips2");
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index bf83dc1..3de0260 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -924,7 +924,7 @@
 	audit_syscall_exit(regs);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-		trace_sys_exit(regs, regs->regs[2]);
+		trace_sys_exit(regs, regs_return_value(regs));
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, 0);
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index c29d397..e6be1f62 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -371,7 +371,7 @@
 	PTR	sys_writev
 	PTR	sys_cacheflush
 	PTR	sys_cachectl
-	PTR	sys_sysmips
+	PTR	__sys_sysmips
 	PTR	sys_ni_syscall			/* 4150 */
 	PTR	sys_getsid
 	PTR	sys_fdatasync
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 0687f96..aa27daf 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -311,7 +311,7 @@
 	PTR	sys_sched_getaffinity
 	PTR	sys_cacheflush
 	PTR	sys_cachectl
-	PTR	sys_sysmips
+	PTR	__sys_sysmips
 	PTR	sys_io_setup			/* 5200 */
 	PTR	sys_io_destroy
 	PTR	sys_io_getevents
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 0331ba3..37f608f 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -302,7 +302,7 @@
 	PTR	compat_sys_sched_getaffinity
 	PTR	sys_cacheflush
 	PTR	sys_cachectl
-	PTR	sys_sysmips
+	PTR	__sys_sysmips
 	PTR	compat_sys_io_setup			/* 6200 */
 	PTR	sys_io_destroy
 	PTR	compat_sys_io_getevents
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 5a47042..7913a5c 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -371,7 +371,7 @@
 	PTR	compat_sys_writev
 	PTR	sys_cacheflush
 	PTR	sys_cachectl
-	PTR	sys_sysmips
+	PTR	__sys_sysmips
 	PTR	sys_ni_syscall			/* 4150 */
 	PTR	sys_getsid
 	PTR	sys_fdatasync
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 53a7ef9..4234b2d 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -28,6 +28,7 @@
 #include <linux/elf.h>
 
 #include <asm/asm.h>
+#include <asm/asm-eva.h>
 #include <asm/branch.h>
 #include <asm/cachectl.h>
 #include <asm/cacheflush.h>
@@ -138,10 +139,12 @@
 		__asm__ __volatile__ (
 		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"	li	%[err], 0				\n"
-		"1:	ll	%[old], (%[addr])			\n"
+		"1:							\n"
+		user_ll("%[old]", "(%[addr])")
 		"	move	%[tmp], %[new]				\n"
-		"2:	sc	%[tmp], (%[addr])			\n"
-		"	bnez	%[tmp], 4f				\n"
+		"2:							\n"
+		user_sc("%[tmp]", "(%[addr])")
+		"	beqz	%[tmp], 4f				\n"
 		"3:							\n"
 		"	.insn						\n"
 		"	.subsection 2					\n"
@@ -199,6 +202,12 @@
 	unreachable();
 }
 
+/*
+ * mips_atomic_set() normally returns directly via syscall_exit potentially
+ * clobbering static registers, so be sure to preserve them.
+ */
+save_static_function(sys_sysmips);
+
 SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
 {
 	switch (cmd) {
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index f8b7bf8..e9385bc 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -2522,6 +2522,35 @@
 	return 0;
 }
 
+/*
+ * Emulate FPU instructions.
+ *
+ * If we use FPU hardware, then we have been typically called to handle
+ * an unimplemented operation, such as where an operand is a NaN or
+ * denormalized.  In that case exit the emulation loop after a single
+ * iteration so as to let hardware execute any subsequent instructions.
+ *
+ * If we have no FPU hardware or it has been disabled, then continue
+ * emulating floating-point instructions until one of these conditions
+ * has occurred:
+ *
+ * - a non-FPU instruction has been encountered,
+ *
+ * - an attempt to emulate has ended with a signal,
+ *
+ * - the ISA mode has been switched.
+ *
+ * We need to terminate the emulation loop if we got switched to the
+ * MIPS16 mode, whether supported or not, so that we do not attempt
+ * to emulate a MIPS16 instruction as a regular MIPS FPU instruction.
+ * Similarly if we got switched to the microMIPS mode and only the
+ * regular MIPS mode is supported, so that we do not attempt to emulate
+ * a microMIPS instruction as a regular MIPS FPU instruction.  Or if
+ * we got switched to the regular MIPS mode and only the microMIPS mode
+ * is supported, so that we do not attempt to emulate a regular MIPS
+ * instruction that should cause an Address Error exception instead.
+ * For simplicity we always terminate upon an ISA mode switch.
+ */
 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	int has_fpu, void *__user *fault_addr)
 {
@@ -2607,6 +2636,15 @@
 			break;
 		if (sig)
 			break;
+		/*
+		 * We have to check for the ISA bit explicitly here,
+		 * because `get_isa16_mode' may return 0 if support
+		 * for code compression has been globally disabled,
+		 * or otherwise we may produce the wrong signal or
+		 * even proceed successfully where we must not.
+		 */
+		if ((xcp->cp0_epc ^ prevepc) & 0x1)
+			break;
 
 		cond_resched();
 	} while (xcp->cp0_epc > prevepc);
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h
index 16e0246..cb7697d 100644
--- a/arch/parisc/include/asm/dma-mapping.h
+++ b/arch/parisc/include/asm/dma-mapping.h
@@ -20,6 +20,8 @@
 ** flush/purge and allocate "regular" cacheable pages for everything.
 */
 
+#define DMA_ERROR_CODE	(~(dma_addr_t)0)
+
 #ifdef CONFIG_PA11
 extern struct dma_map_ops pcxl_dma_ops;
 extern struct dma_map_ops pcx_dma_ops;
@@ -54,12 +56,13 @@
 			break;
 		}
 	}
-	BUG_ON(!dev->platform_data);
 	return dev->platform_data;
 }
-		
-#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu)
-	
+
+#define GET_IOC(dev) ({					\
+	void *__pdata = parisc_walk_tree(dev);		\
+	__pdata ? HBA_DATA(__pdata)->iommu : NULL;	\
+})
 
 #ifdef CONFIG_IOMMU_CCIO
 struct parisc_device;
diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h
index 59be257..a812262 100644
--- a/arch/parisc/include/asm/mmu_context.h
+++ b/arch/parisc/include/asm/mmu_context.h
@@ -49,15 +49,26 @@
 	mtctl(__space_to_prot(context), 8);
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
+static inline void switch_mm_irqs_off(struct mm_struct *prev,
+		struct mm_struct *next, struct task_struct *tsk)
 {
-
 	if (prev != next) {
 		mtctl(__pa(next->pgd), 25);
 		load_context(next->context);
 	}
 }
 
+static inline void switch_mm(struct mm_struct *prev,
+		struct mm_struct *next, struct task_struct *tsk)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm_irqs_off(prev, next, tsk);
+	local_irq_restore(flags);
+}
+#define switch_mm_irqs_off switch_mm_irqs_off
+
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 3cfef1d..8ec2ff8 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -361,7 +361,7 @@
 	ENTRY_SAME(ni_syscall)	/* 263: reserved for vserver */
 	ENTRY_SAME(add_key)
 	ENTRY_SAME(request_key)		/* 265 */
-	ENTRY_SAME(keyctl)
+	ENTRY_COMP(keyctl)
 	ENTRY_SAME(ioprio_set)
 	ENTRY_SAME(ioprio_get)
 	ENTRY_SAME(inotify_init)
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 040c48f..b6f3b5e 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -366,7 +366,7 @@
 		case 15:	/* Data TLB miss fault/Data page fault */
 			/* send SIGSEGV when outside of vma */
 			if (!vma ||
-			    address < vma->vm_start || address > vma->vm_end) {
+			    address < vma->vm_start || address >= vma->vm_end) {
 				si.si_signo = SIGSEGV;
 				si.si_code = SEGV_MAPERR;
 				break;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8f01f21..b4758f5 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -84,6 +84,7 @@
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
 	select ARCH_HAS_ELF_RANDOMIZE
+	select ARCH_HAS_FORTIFY_SOURCE
 	select OF
 	select OF_EARLY_FLATTREE
 	select OF_RESERVED_MEM
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 2b90335..a2cc801 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -560,7 +560,7 @@
  * Atomically increments @v by 1, so long as @v is non-zero.
  * Returns non-zero if @v was non-zero, and zero otherwise.
  */
-static __inline__ long atomic64_inc_not_zero(atomic64_t *v)
+static __inline__ int atomic64_inc_not_zero(atomic64_t *v)
 {
 	long t1, t2;
 
@@ -579,7 +579,7 @@
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
 
-	return t1;
+	return t1 != 0;
 }
 
 #endif /* __powerpc64__ */
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index ee46ffe..743ad7a 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -23,12 +23,13 @@
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE	0x20000000
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(is_32bit_task() ? 0x000400000UL : \
+						   0x100000000UL)
 
 #define ELF_CORE_EFLAGS (is_elf2_task() ? 2 : 0)
 
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index e7d9eca..ceb168c 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1283,7 +1283,7 @@
 				"	.llong 0\n"			\
 				".previous"				\
 			: "=r" (rval) \
-			: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL)); \
+			: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
 			rval;})
 #else
 #define mftb()		({unsigned long rval;	\
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 0c84d6b..7e2af42 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -97,7 +97,8 @@
 			 (unsigned long)selected_size / SZ_1M);
 		align_size = HPT_ALIGN_PAGES << PAGE_SHIFT;
 		cma_declare_contiguous(0, selected_size, 0, align_size,
-			KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma);
+			KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, "kvm_cma",
+			&kvm_cma);
 	}
 }
 
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 6ca3b90..776c1a1 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -687,8 +687,10 @@
 	case 19:
 		switch ((instr >> 1) & 0x3ff) {
 		case 0:		/* mcrf */
-			rd = (instr >> 21) & 0x1c;
-			ra = (instr >> 16) & 0x1c;
+			rd = 7 - ((instr >> 23) & 0x7);
+			ra = 7 - ((instr >> 18) & 0x7);
+			rd *= 4;
+			ra *= 4;
 			val = (regs->ccr >> ra) & 0xf;
 			regs->ccr = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
 			goto instr_done;
@@ -968,6 +970,19 @@
 #endif
 
 		case 19:	/* mfcr */
+			if ((instr >> 20) & 1) {
+				imm = 0xf0000000UL;
+				for (sh = 0; sh < 8; ++sh) {
+					if (instr & (0x80000 >> sh)) {
+						regs->gpr[rd] = regs->ccr & imm;
+						break;
+					}
+					imm >>= 4;
+				}
+
+				goto instr_done;
+			}
+
 			regs->gpr[rd] = regs->ccr;
 			regs->gpr[rd] &= 0xffffffffUL;
 			goto instr_done;
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c
index 73bf6e1..a006f82 100644
--- a/arch/powerpc/mm/mmu_context_book3s64.c
+++ b/arch/powerpc/mm/mmu_context_book3s64.c
@@ -167,9 +167,15 @@
 	mm->context.cop_lockp = NULL;
 #endif /* CONFIG_PPC_ICSWX */
 
-	if (radix_enabled())
-		process_tb[mm->context.id].prtb1 = 0;
-	else
+	if (radix_enabled()) {
+		/*
+		 * Radix doesn't have a valid bit in the process table
+		 * entries. However we know that at least P9 implementation
+		 * will avoid caching an entry with an invalid RTS field,
+		 * and 0 is invalid. So this will do.
+		 */
+		process_tb[mm->context.id].prtb0 = 0;
+	} else
 		subpage_prot_free(mm);
 	destroy_pagetable_page(mm);
 	__destroy_context(mm->context.id);
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index f2c98f6..a7bb872 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -279,7 +279,7 @@
 				       int ssize, unsigned long inv_flags)
 {
 	unsigned long lpar_rc;
-	unsigned long flags = (newpp & 7) | H_AVPN;
+	unsigned long flags;
 	unsigned long want_v;
 
 	want_v = hpte_encode_avpn(vpn, psize, ssize);
@@ -287,6 +287,11 @@
 	pr_devel("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
 		 want_v, slot, flags, psize);
 
+	flags = (newpp & 7) | H_AVPN;
+	if (mmu_has_feature(MMU_FTR_KERNEL_RO))
+		/* Move pp0 into bit 8 (IBM 55) */
+		flags |= (newpp & HPTE_R_PP0) >> 55;
+
 	lpar_rc = plpar_pte_protect(flags, slot, want_v);
 
 	if (lpar_rc == H_NOT_FOUND) {
@@ -358,6 +363,10 @@
 	BUG_ON(slot == -1);
 
 	flags = newpp & 7;
+	if (mmu_has_feature(MMU_FTR_KERNEL_RO))
+		/* Move pp0 into bit 8 (IBM 55) */
+		flags |= (newpp & HPTE_R_PP0) >> 55;
+
 	lpar_rc = plpar_pte_protect(flags, slot, 0);
 
 	BUG_ON(lpar_rc != H_SUCCESS);
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 1736c7d..8d665f1 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -158,14 +158,13 @@
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk. 64-bit
-   tasks are aligned to 4GB. */
-#define ELF_ET_DYN_BASE (is_compat_task() ? \
-				(STACK_TOP / 3 * 2) : \
-				(STACK_TOP / 3 * 2) & ~((1UL << 32) - 1))
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(is_compat_task() ? 0x000400000UL : \
+						    0x100000000UL)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 6ba0bf9..6bc941b 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -64,6 +64,12 @@
 {
 	unsigned long mask = -1UL;
 
+	/*
+	 * No arguments for this syscall, there's nothing to do.
+	 */
+	if (!n)
+		return;
+
 	BUG_ON(i + n > 6);
 #ifdef CONFIG_COMPAT
 	if (test_tsk_thread_flag(task, TIF_31BIT))
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bada636..3735222 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -26,6 +26,7 @@
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_FAST_MULTIPLIER
+	select ARCH_HAS_FORTIFY_SOURCE
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select ARCH_HAS_GIGANTIC_PAGE		if X86_64
 	select ARCH_HAS_KCOV			if X86_64
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index c945acd..5955954 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -409,3 +409,8 @@
 	debug_putstr("done.\nBooting the kernel.\n");
 	return output;
 }
+
+void fortify_panic(const char *name)
+{
+	error("detected buffer overflow");
+}
diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
index fc61739..f960a04 100644
--- a/arch/x86/crypto/sha1_ssse3_glue.c
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
@@ -201,7 +201,7 @@
 
 static bool avx2_usable(void)
 {
-	if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2)
+	if (false && avx_usable() && boot_cpu_has(X86_FEATURE_AVX2)
 		&& boot_cpu_has(X86_FEATURE_BMI1)
 		&& boot_cpu_has(X86_FEATURE_BMI2))
 		return true;
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 94aad63..c152db2 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -245,12 +245,13 @@
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE		(TASK_SIZE / 3 * 2)
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(mmap_is_ia32() ? 0x000400000UL : \
+						  0x100000000UL)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports.  This could be done in user space,
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 78f3760..b601dda 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -405,6 +405,8 @@
 #define MSR_IA32_TSC_ADJUST             0x0000003b
 #define MSR_IA32_BNDCFGS		0x00000d90
 
+#define MSR_IA32_BNDCFGS_RSVD		0x00000ffc
+
 #define MSR_IA32_XSS			0x00000da0
 
 #define FEATURE_CONTROL_LOCKED				(1<<0)
diff --git a/arch/x86/include/asm/string_32.h b/arch/x86/include/asm/string_32.h
index 3d3e835..e9ee848 100644
--- a/arch/x86/include/asm/string_32.h
+++ b/arch/x86/include/asm/string_32.h
@@ -142,7 +142,9 @@
 }
 
 #define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, size_t);
 
+#ifndef CONFIG_FORTIFY_SOURCE
 #ifdef CONFIG_X86_USE_3DNOW
 
 #include <asm/mmx.h>
@@ -195,11 +197,15 @@
 #endif
 
 #endif
+#endif /* !CONFIG_FORTIFY_SOURCE */
 
 #define __HAVE_ARCH_MEMMOVE
 void *memmove(void *dest, const void *src, size_t n);
 
+extern int memcmp(const void *, const void *, size_t);
+#ifndef CONFIG_FORTIFY_SOURCE
 #define memcmp __builtin_memcmp
+#endif
 
 #define __HAVE_ARCH_MEMCHR
 extern void *memchr(const void *cs, int c, size_t count);
@@ -321,6 +327,8 @@
 	 : __memset_generic((s), (c), (count)))
 
 #define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, size_t);
+#ifndef CONFIG_FORTIFY_SOURCE
 #if (__GNUC__ >= 4)
 #define memset(s, c, count) __builtin_memset(s, c, count)
 #else
@@ -330,6 +338,7 @@
 				 (count))				\
 	 : __memset((s), (c), (count)))
 #endif
+#endif /* !CONFIG_FORTIFY_SOURCE */
 
 /*
  * find the first occurrence of byte 'c', or 1 past the area if none
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index a164862..f942deb 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -31,6 +31,7 @@
 extern void *memcpy(void *to, const void *from, size_t len);
 extern void *__memcpy(void *to, const void *from, size_t len);
 
+#ifndef CONFIG_FORTIFY_SOURCE
 #ifndef CONFIG_KMEMCHECK
 #if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
 #define memcpy(dst, src, len)					\
@@ -51,6 +52,7 @@
  */
 #define memcpy(dst, src, len) __inline_memcpy((dst), (src), (len))
 #endif
+#endif /* !CONFIG_FORTIFY_SOURCE */
 
 #define __HAVE_ARCH_MEMSET
 void *memset(void *s, int c, size_t n);
@@ -77,6 +79,11 @@
 #define memcpy(dst, src, len) __memcpy(dst, src, len)
 #define memmove(dst, src, len) __memmove(dst, src, len)
 #define memset(s, c, n) __memset(s, c, n)
+
+#ifndef __NO_FORTIFY
+#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
+#endif
+
 #endif
 
 __must_check int memcpy_mcsafe_unrolled(void *dst, const void *src, size_t cnt);
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index a12a047..8b678af 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -43,6 +43,7 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/smap.h>
 
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
@@ -214,10 +215,12 @@
 	__HYPERCALL_DECLS;
 	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);
 
+	stac();
 	asm volatile("call *%[call]"
 		     : __HYPERCALL_5PARAM
 		     : [call] "a" (&hypercall_page[call])
 		     : __HYPERCALL_CLOBBER5);
+	clac();
 
 	return (long)__res;
 }
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 931ced8..d3e0d04 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -338,6 +338,14 @@
 	struct mpc_intsrc mp_irq;
 
 	/*
+	 * Check bus_irq boundary.
+	 */
+	if (bus_irq >= NR_IRQS_LEGACY) {
+		pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq);
+		return;
+	}
+
+	/*
 	 * Convert 'gsi' to 'ioapic.pin'.
 	 */
 	ioapic = mp_find_ioapic(gsi);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 7249f15..cf89928 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2116,7 +2116,7 @@
 			int idx;
 			idx = find_irq_entry(apic1, pin1, mp_INT);
 			if (idx != -1 && irq_trigger(idx))
-				unmask_ioapic_irq(irq_get_chip_data(0));
+				unmask_ioapic_irq(irq_get_irq_data(0));
 		}
 		irq_domain_deactivate_irq(irq_data);
 		irq_domain_activate_irq(irq_data);
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 35058c2..9368fec 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -144,6 +144,14 @@
 	return best && (best->ebx & bit(X86_FEATURE_RTM));
 }
 
+static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_MPX));
+}
+
 static inline bool guest_cpuid_has_rdtscp(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 04e6bbb..3dc6d80 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2987,7 +2987,8 @@
 		msr_info->data = vmcs_readl(GUEST_SYSENTER_ESP);
 		break;
 	case MSR_IA32_BNDCFGS:
-		if (!kvm_mpx_supported())
+		if (!kvm_mpx_supported() ||
+		    (!msr_info->host_initiated && !guest_cpuid_has_mpx(vcpu)))
 			return 1;
 		msr_info->data = vmcs_read64(GUEST_BNDCFGS);
 		break;
@@ -3069,7 +3070,11 @@
 		vmcs_writel(GUEST_SYSENTER_ESP, data);
 		break;
 	case MSR_IA32_BNDCFGS:
-		if (!kvm_mpx_supported())
+		if (!kvm_mpx_supported() ||
+		    (!msr_info->host_initiated && !guest_cpuid_has_mpx(vcpu)))
+			return 1;
+		if (is_noncanonical_address(data & PAGE_MASK) ||
+		    (data & MSR_IA32_BNDCFGS_RSVD))
 			return 1;
 		vmcs_write64(GUEST_BNDCFGS, data);
 		break;
@@ -6474,7 +6479,6 @@
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
-	vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true);
 
 	memcpy(vmx_msr_bitmap_legacy_x2apic,
 			vmx_msr_bitmap_legacy, PAGE_SIZE);
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index cad1263..2eab7d0 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -6,7 +6,7 @@
 
 __visible void *memcpy(void *to, const void *from, size_t n)
 {
-#ifdef CONFIG_X86_USE_3DNOW
+#if defined(CONFIG_X86_USE_3DNOW) && !defined(CONFIG_FORTIFY_SOURCE)
 	return __memcpy3d(to, from, n);
 #else
 	return __memcpy(to, from, n);
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 6d52b94..20fa7c8 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -571,3 +571,35 @@
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar);
+
+/*
+ * Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff]
+ *
+ * Using the [mem 0x7fa00000-0x7fbfffff] region, e.g., by assigning it to
+ * the 00:1c.0 Root Port, causes a conflict with [io 0x1804], which is used
+ * for soft poweroff and suspend-to-RAM.
+ *
+ * As far as we know, this is related to the address space, not to the Root
+ * Port itself.  Attaching the quirk to the Root Port is a convenience, but
+ * it could probably also be a standalone DMI quirk.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=103211
+ */
+static void quirk_apple_mbp_poweroff(struct pci_dev *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+
+	if ((!dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,4") &&
+	     !dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,5")) ||
+	    pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x1c, 0))
+		return;
+
+	res = request_mem_region(0x7fa00000, 0x200000,
+				 "MacBook Pro poweroff workaround");
+	if (res)
+		dev_info(dev, "claimed %s %pR\n", res->name, res);
+	else
+		dev_info(dev, "can't work around MacBook Pro poweroff issue\n");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 22ca892..79152db 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -147,7 +147,7 @@
 module_param(ec_storm_threshold, uint, 0644);
 MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
 
-static bool ec_freeze_events __read_mostly = true;
+static bool ec_freeze_events __read_mostly = false;
 module_param(ec_freeze_events, bool, 0644);
 MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume");
 
@@ -1865,24 +1865,6 @@
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int acpi_ec_suspend_noirq(struct device *dev)
-{
-	struct acpi_ec *ec =
-		acpi_driver_data(to_acpi_device(dev));
-
-	acpi_ec_enter_noirq(ec);
-	return 0;
-}
-
-static int acpi_ec_resume_noirq(struct device *dev)
-{
-	struct acpi_ec *ec =
-		acpi_driver_data(to_acpi_device(dev));
-
-	acpi_ec_leave_noirq(ec);
-	return 0;
-}
-
 static int acpi_ec_suspend(struct device *dev)
 {
 	struct acpi_ec *ec =
@@ -1904,7 +1886,6 @@
 #endif
 
 static const struct dev_pm_ops acpi_ec_pm = {
-	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq)
 	SET_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend, acpi_ec_resume)
 };
 
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 9ef3941..f3bc901 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2945,6 +2945,8 @@
 
 static __init int nfit_init(void)
 {
+	int ret;
+
 	BUILD_BUG_ON(sizeof(struct acpi_table_nfit) != 40);
 	BUILD_BUG_ON(sizeof(struct acpi_nfit_system_address) != 56);
 	BUILD_BUG_ON(sizeof(struct acpi_nfit_memory_map) != 48);
@@ -2972,8 +2974,14 @@
 		return -ENOMEM;
 
 	nfit_mce_register();
+	ret = acpi_bus_register_driver(&acpi_nfit_driver);
+	if (ret) {
+		nfit_mce_unregister();
+		destroy_workqueue(nfit_wq);
+	}
 
-	return acpi_bus_register_driver(&acpi_nfit_driver);
+	return ret;
+
 }
 
 static __exit void nfit_exit(void)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index b351c85..632c814 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -28,10 +28,10 @@
  *    binder_node_lock() and binder_node_unlock() are
  *    used to acq/rel
  * 3) proc->inner_lock : protects the thread and node lists
- *    (proc->threads, proc->nodes) and all todo lists associated
- *    with the binder_proc (proc->todo, thread->todo,
- *    proc->delivered_death and node->async_todo), as well as
- *    thread->transaction_stack
+ *    (proc->threads, proc->waiting_threads, proc->nodes)
+ *    and all todo lists associated with the binder_proc
+ *    (proc->todo, thread->todo, proc->delivered_death and
+ *    node->async_todo), as well as thread->transaction_stack
  *    binder_inner_proc_lock() and binder_inner_proc_unlock()
  *    are used to acq/rel
  *
@@ -352,10 +352,14 @@
  *                        and by @lock)
  * @has_async_transaction: async transaction to node in progress
  *                        (protected by @lock)
+ * @sched_policy:         minimum scheduling policy for node
+ *                        (invariant after initialized)
  * @accept_fds:           file descriptor operations supported for node
  *                        (invariant after initialized)
  * @min_priority:         minimum scheduling priority
  *                        (invariant after initialized)
+ * @inherit_rt:           inherit RT scheduling policy from caller
+ *                        (invariant after initialized)
  * @async_todo:           list of async work items
  *                        (protected by @proc->inner_lock)
  *
@@ -391,6 +395,8 @@
 		/*
 		 * invariant after initialization
 		 */
+		u8 sched_policy:2;
+		u8 inherit_rt:1;
 		u8 accept_fds:1;
 		u8 min_priority;
 	};
@@ -465,6 +471,22 @@
 };
 
 /**
+ * struct binder_priority - scheduler policy and priority
+ * @sched_policy            scheduler policy
+ * @prio                    [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT
+ *
+ * The binder driver supports inheriting the following scheduler policies:
+ * SCHED_NORMAL
+ * SCHED_BATCH
+ * SCHED_FIFO
+ * SCHED_RR
+ */
+struct binder_priority {
+	unsigned int sched_policy;
+	int prio;
+};
+
+/**
  * struct binder_proc - binder process bookkeeping
  * @proc_node:            element for binder_procs list
  * @threads:              rbtree of binder_threads in this proc
@@ -476,6 +498,8 @@
  *                        (protected by @outer_lock)
  * @refs_by_node:         rbtree of refs ordered by ref->node
  *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
  * @pid                   PID of group_leader of process
  *                        (invariant after initialized)
  * @tsk                   task_struct for group_leader of process
@@ -505,8 +529,6 @@
  *                        (protected by @inner_lock)
  * @requested_threads_started: number binder threads started
  *                        (protected by @inner_lock)
- * @ready_threads:        number of threads waiting for proc work
- *                        (protected by @inner_lock)
  * @tmp_ref:              temporary reference to indicate proc is in use
  *                        (protected by @inner_lock)
  * @default_priority:     default scheduler priority
@@ -527,6 +549,7 @@
 	struct rb_root nodes;
 	struct rb_root refs_by_desc;
 	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
 	int pid;
 	struct task_struct *tsk;
 	struct files_struct *files;
@@ -541,9 +564,8 @@
 	int max_threads;
 	int requested_threads;
 	int requested_threads_started;
-	int ready_threads;
 	int tmp_ref;
-	long default_priority;
+	struct binder_priority default_priority;
 	struct dentry *debugfs_entry;
 	struct binder_alloc alloc;
 	struct binder_context *context;
@@ -557,6 +579,7 @@
 	BINDER_LOOPER_STATE_EXITED      = 0x04,
 	BINDER_LOOPER_STATE_INVALID     = 0x08,
 	BINDER_LOOPER_STATE_WAITING     = 0x10,
+	BINDER_LOOPER_STATE_POLL        = 0x20,
 };
 
 /**
@@ -565,6 +588,8 @@
  *                        (invariant after initialization)
  * @rb_node:              element for proc->threads rbtree
  *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
  * @pid:                  PID for this thread
  *                        (invariant after initialization)
  * @looper:               bitmap of looping state
@@ -588,12 +613,14 @@
  * @is_dead:              thread is dead and awaiting free
  *                        when outstanding transactions are cleaned up
  *                        (protected by @proc->inner_lock)
+ * @task:                 struct task_struct for this thread
  *
  * Bookkeeping structure for binder threads.
  */
 struct binder_thread {
 	struct binder_proc *proc;
 	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
 	int pid;
 	int looper;              /* only modified by this thread */
 	bool looper_need_return; /* can be written by other thread */
@@ -605,6 +632,7 @@
 	struct binder_stats stats;
 	atomic_t tmp_ref;
 	bool is_dead;
+	struct task_struct *task;
 };
 
 struct binder_transaction {
@@ -621,8 +649,9 @@
 	struct binder_buffer *buffer;
 	unsigned int	code;
 	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
+	struct binder_priority	priority;
+	struct binder_priority	saved_priority;
+	bool    set_priority_called;
 	kuid_t	sender_euid;
 	/**
 	 * @lock:  protects @from, @to_proc, and @to_thread
@@ -921,22 +950,271 @@
 	return retval;
 }
 
-static void binder_set_nice(long nice)
+static bool binder_has_work_ilocked(struct binder_thread *thread,
+				    bool do_proc_work)
 {
-	long min_nice;
+	return !binder_worklist_empty_ilocked(&thread->todo) ||
+		thread->looper_need_return ||
+		(do_proc_work &&
+		 !binder_worklist_empty_ilocked(&thread->proc->todo));
+}
 
-	if (can_nice(current, nice)) {
-		set_user_nice(current, nice);
+static bool binder_has_work(struct binder_thread *thread, bool do_proc_work)
+{
+	bool has_work;
+
+	binder_inner_proc_lock(thread->proc);
+	has_work = binder_has_work_ilocked(thread, do_proc_work);
+	binder_inner_proc_unlock(thread->proc);
+
+	return has_work;
+}
+
+static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread)
+{
+	return !thread->transaction_stack &&
+		binder_worklist_empty_ilocked(&thread->todo) &&
+		(thread->looper & (BINDER_LOOPER_STATE_ENTERED |
+				   BINDER_LOOPER_STATE_REGISTERED));
+}
+
+static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc,
+					       bool sync)
+{
+	struct rb_node *n;
+	struct binder_thread *thread;
+
+	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
+		thread = rb_entry(n, struct binder_thread, rb_node);
+		if (thread->looper & BINDER_LOOPER_STATE_POLL &&
+		    binder_available_for_proc_work_ilocked(thread)) {
+			if (sync)
+				wake_up_interruptible_sync(&thread->wait);
+			else
+				wake_up_interruptible(&thread->wait);
+		}
+	}
+}
+
+/**
+ * binder_select_thread_ilocked() - selects a thread for doing proc work.
+ * @proc:	process to select a thread from
+ *
+ * Note that calling this function moves the thread off the waiting_threads
+ * list, so it can only be woken up by the caller of this function, or a
+ * signal. Therefore, callers *should* always wake up the thread this function
+ * returns.
+ *
+ * Return:	If there's a thread currently waiting for process work,
+ *		returns that thread. Otherwise returns NULL.
+ */
+static struct binder_thread *
+binder_select_thread_ilocked(struct binder_proc *proc)
+{
+	struct binder_thread *thread;
+
+	BUG_ON(!spin_is_locked(&proc->inner_lock));
+	thread = list_first_entry_or_null(&proc->waiting_threads,
+					  struct binder_thread,
+					  waiting_thread_node);
+
+	if (thread)
+		list_del_init(&thread->waiting_thread_node);
+
+	return thread;
+}
+
+/**
+ * binder_wakeup_thread_ilocked() - wakes up a thread for doing proc work.
+ * @proc:	process to wake up a thread in
+ * @thread:	specific thread to wake-up (may be NULL)
+ * @sync:	whether to do a synchronous wake-up
+ *
+ * This function wakes up a thread in the @proc process.
+ * The caller may provide a specific thread to wake-up in
+ * the @thread parameter. If @thread is NULL, this function
+ * will wake up threads that have called poll().
+ *
+ * Note that for this function to work as expected, callers
+ * should first call binder_select_thread() to find a thread
+ * to handle the work (if they don't have a thread already),
+ * and pass the result into the @thread parameter.
+ */
+static void binder_wakeup_thread_ilocked(struct binder_proc *proc,
+					 struct binder_thread *thread,
+					 bool sync)
+{
+	BUG_ON(!spin_is_locked(&proc->inner_lock));
+
+	if (thread) {
+		if (sync)
+			wake_up_interruptible_sync(&thread->wait);
+		else
+			wake_up_interruptible(&thread->wait);
 		return;
 	}
-	min_nice = rlimit_to_nice(current->signal->rlim[RLIMIT_NICE].rlim_cur);
-	binder_debug(BINDER_DEBUG_PRIORITY_CAP,
-		     "%d: nice value %ld not allowed use %ld instead\n",
-		      current->pid, nice, min_nice);
-	set_user_nice(current, min_nice);
-	if (min_nice <= MAX_NICE)
+
+	/* Didn't find a thread waiting for proc work; this can happen
+	 * in two scenarios:
+	 * 1. All threads are busy handling transactions
+	 *    In that case, one of those threads should call back into
+	 *    the kernel driver soon and pick up this work.
+	 * 2. Threads are using the (e)poll interface, in which case
+	 *    they may be blocked on the waitqueue without having been
+	 *    added to waiting_threads. For this case, we just iterate
+	 *    over all threads not handling transaction work, and
+	 *    wake them all up. We wake all because we don't know whether
+	 *    a thread that called into (e)poll is handling non-binder
+	 *    work currently.
+	 */
+	binder_wakeup_poll_threads_ilocked(proc, sync);
+}
+
+static void binder_wakeup_proc_ilocked(struct binder_proc *proc)
+{
+	struct binder_thread *thread = binder_select_thread_ilocked(proc);
+
+	binder_wakeup_thread_ilocked(proc, thread, /* sync = */false);
+}
+
+static bool is_rt_policy(int policy)
+{
+	return policy == SCHED_FIFO || policy == SCHED_RR;
+}
+
+static bool is_fair_policy(int policy)
+{
+	return policy == SCHED_NORMAL || policy == SCHED_BATCH;
+}
+
+static bool binder_supported_policy(int policy)
+{
+	return is_fair_policy(policy) || is_rt_policy(policy);
+}
+
+static int to_userspace_prio(int policy, int kernel_priority)
+{
+	if (is_fair_policy(policy))
+		return PRIO_TO_NICE(kernel_priority);
+	else
+		return MAX_USER_RT_PRIO - 1 - kernel_priority;
+}
+
+static int to_kernel_prio(int policy, int user_priority)
+{
+	if (is_fair_policy(policy))
+		return NICE_TO_PRIO(user_priority);
+	else
+		return MAX_USER_RT_PRIO - 1 - user_priority;
+}
+
+static void binder_do_set_priority(struct task_struct *task,
+				   struct binder_priority desired,
+				   bool verify)
+{
+	int priority; /* user-space prio value */
+	bool has_cap_nice;
+	unsigned int policy = desired.sched_policy;
+
+	if (task->policy == policy && task->normal_prio == desired.prio)
 		return;
-	binder_user_error("%d RLIMIT_NICE not set\n", current->pid);
+
+	has_cap_nice = has_capability_noaudit(task, CAP_SYS_NICE);
+
+	priority = to_userspace_prio(policy, desired.prio);
+
+	if (verify && is_rt_policy(policy) && !has_cap_nice) {
+		long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO);
+
+		if (max_rtprio == 0) {
+			policy = SCHED_NORMAL;
+			priority = MIN_NICE;
+		} else if (priority > max_rtprio) {
+			priority = max_rtprio;
+		}
+	}
+
+	if (verify && is_fair_policy(policy) && !has_cap_nice) {
+		long min_nice = rlimit_to_nice(task_rlimit(task, RLIMIT_NICE));
+
+		if (min_nice > MAX_NICE) {
+			binder_user_error("%d RLIMIT_NICE not set\n",
+					  task->pid);
+			return;
+		} else if (priority < min_nice) {
+			priority = min_nice;
+		}
+	}
+
+	if (policy != desired.sched_policy ||
+	    to_kernel_prio(policy, priority) != desired.prio)
+		binder_debug(BINDER_DEBUG_PRIORITY_CAP,
+			     "%d: priority %d not allowed, using %d instead\n",
+			      task->pid, desired.prio,
+			      to_kernel_prio(policy, priority));
+
+	/* Set the actual priority */
+	if (task->policy != policy || is_rt_policy(policy)) {
+		struct sched_param params;
+
+		params.sched_priority = is_rt_policy(policy) ? priority : 0;
+
+		sched_setscheduler_nocheck(task,
+					   policy | SCHED_RESET_ON_FORK,
+					   &params);
+	}
+	if (is_fair_policy(policy))
+		set_user_nice(task, priority);
+}
+
+static void binder_set_priority(struct task_struct *task,
+				struct binder_priority desired)
+{
+	binder_do_set_priority(task, desired, /* verify = */ true);
+}
+
+static void binder_restore_priority(struct task_struct *task,
+				    struct binder_priority desired)
+{
+	binder_do_set_priority(task, desired, /* verify = */ false);
+}
+
+static void binder_transaction_priority(struct task_struct *task,
+					struct binder_transaction *t,
+					struct binder_priority node_prio,
+					bool inherit_rt)
+{
+	struct binder_priority desired_prio;
+
+	if (t->set_priority_called)
+		return;
+
+	t->set_priority_called = true;
+	t->saved_priority.sched_policy = task->policy;
+	t->saved_priority.prio = task->normal_prio;
+
+	if (!inherit_rt && is_rt_policy(desired_prio.sched_policy)) {
+		desired_prio.prio = NICE_TO_PRIO(0);
+		desired_prio.sched_policy = SCHED_NORMAL;
+	} else {
+		desired_prio.prio = t->priority.prio;
+		desired_prio.sched_policy = t->priority.sched_policy;
+	}
+
+	if (node_prio.prio < t->priority.prio ||
+	    (node_prio.prio == t->priority.prio &&
+	     node_prio.sched_policy == SCHED_FIFO)) {
+		/*
+		 * In case the minimum priority on the node is
+		 * higher (lower value), use that priority. If
+		 * the priority is the same, but the node uses
+		 * SCHED_FIFO, prefer SCHED_FIFO, since it can
+		 * run unbounded, unlike SCHED_RR.
+		 */
+		desired_prio = node_prio;
+	}
+
+	binder_set_priority(task, desired_prio);
 }
 
 static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc,
@@ -989,6 +1267,7 @@
 	binder_uintptr_t ptr = fp ? fp->binder : 0;
 	binder_uintptr_t cookie = fp ? fp->cookie : 0;
 	__u32 flags = fp ? fp->flags : 0;
+	s8 priority;
 
 	BUG_ON(!spin_is_locked(&proc->inner_lock));
 	while (*p) {
@@ -1020,8 +1299,12 @@
 	node->ptr = ptr;
 	node->cookie = cookie;
 	node->work.type = BINDER_WORK_NODE;
-	node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+	priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+	node->sched_policy = (flags & FLAT_BINDER_FLAG_PRIORITY_MASK) >>
+		FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT;
+	node->min_priority = to_kernel_prio(node->sched_policy, priority);
 	node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+	node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT);
 	spin_lock_init(&node->lock);
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
@@ -1140,7 +1423,7 @@
 	if (proc && (node->has_strong_ref || node->has_weak_ref)) {
 		if (list_empty(&node->work.entry)) {
 			binder_enqueue_work_ilocked(&node->work, &proc->todo);
-			wake_up_interruptible(&node->proc->wait);
+			binder_wakeup_proc_ilocked(proc);
 		}
 	} else {
 		if (hlist_empty(&node->refs) && !node->local_strong_refs &&
@@ -2386,6 +2669,80 @@
 	return 0;
 }
 
+/**
+ * binder_proc_transaction() - sends a transaction to a process and wakes it up
+ * @t:		transaction to send
+ * @proc:	process to send the transaction to
+ * @thread:	thread in @proc to send the transaction to (may be NULL)
+ *
+ * This function queues a transaction to the specified process. It will try
+ * to find a thread in the target process to handle the transaction and
+ * wake it up. If no thread is found, the work is queued to the proc
+ * waitqueue.
+ *
+ * If the @thread parameter is not NULL, the transaction is always queued
+ * to the waitlist of that specific thread.
+ *
+ * Return:	true if the transactions was successfully queued
+ *		false if the target process or thread is dead
+ */
+static bool binder_proc_transaction(struct binder_transaction *t,
+				    struct binder_proc *proc,
+				    struct binder_thread *thread)
+{
+	struct list_head *target_list = NULL;
+	struct binder_node *node = t->buffer->target_node;
+	struct binder_priority node_prio;
+	bool oneway = !!(t->flags & TF_ONE_WAY);
+	bool wakeup = true;
+
+	BUG_ON(!node);
+	binder_node_lock(node);
+	node_prio.prio = node->min_priority;
+	node_prio.sched_policy = node->sched_policy;
+
+	if (oneway) {
+		BUG_ON(thread);
+		if (node->has_async_transaction) {
+			target_list = &node->async_todo;
+			wakeup = false;
+		} else {
+			node->has_async_transaction = 1;
+		}
+	}
+
+	binder_inner_proc_lock(proc);
+
+	if (proc->is_dead || (thread && thread->is_dead)) {
+		binder_inner_proc_unlock(proc);
+		binder_node_unlock(node);
+		return false;
+	}
+
+	if (!thread && !target_list)
+		thread = binder_select_thread_ilocked(proc);
+
+	if (thread) {
+		target_list = &thread->todo;
+		binder_transaction_priority(thread->task, t, node_prio,
+					    node->inherit_rt);
+	} else if (!target_list) {
+		target_list = &proc->todo;
+	} else {
+		BUG_ON(target_list != &node->async_todo);
+	}
+
+	binder_enqueue_work_ilocked(&t->work, target_list);
+
+	if (wakeup)
+		binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */);
+
+	binder_inner_proc_unlock(proc);
+	binder_node_unlock(node);
+
+	return true;
+}
+
 static void binder_transaction(struct binder_proc *proc,
 			       struct binder_thread *thread,
 			       struct binder_transaction_data *tr, int reply,
@@ -2400,8 +2757,6 @@
 	struct binder_proc *target_proc = NULL;
 	struct binder_thread *target_thread = NULL;
 	struct binder_node *target_node = NULL;
-	struct list_head *target_list;
-	wait_queue_head_t *target_wait;
 	struct binder_transaction *in_reply_to = NULL;
 	struct binder_transaction_log_entry *e;
 	uint32_t return_error = 0;
@@ -2452,7 +2807,6 @@
 		}
 		thread->transaction_stack = in_reply_to->to_parent;
 		binder_inner_proc_unlock(proc);
-		binder_set_nice(in_reply_to->saved_priority);
 		target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
 		if (target_thread == NULL) {
 			return_error = BR_DEAD_REPLY;
@@ -2571,14 +2925,8 @@
 		}
 		binder_inner_proc_unlock(proc);
 	}
-	if (target_thread) {
+	if (target_thread)
 		e->to_thread = target_thread->pid;
-		target_list = &target_thread->todo;
-		target_wait = &target_thread->wait;
-	} else {
-		target_list = &target_proc->todo;
-		target_wait = &target_proc->wait;
-	}
 	e->to_proc = target_proc->pid;
 
 	/* TODO: reuse incoming transaction for reply */
@@ -2631,7 +2979,15 @@
 	t->to_thread = target_thread;
 	t->code = tr->code;
 	t->flags = tr->flags;
-	t->priority = task_nice(current);
+	if (!(t->flags & TF_ONE_WAY) &&
+	    binder_supported_policy(current->policy)) {
+		/* Inherit supported policies for synchronous transactions */
+		t->priority.sched_policy = current->policy;
+		t->priority.prio = current->normal_prio;
+	} else {
+		/* Otherwise, fall back to the default priority */
+		t->priority = target_proc->default_priority;
+	}
 
 	trace_binder_transaction(reply, t, target_node);
 
@@ -2857,8 +3213,10 @@
 		}
 		BUG_ON(t->buffer->async_transaction != 0);
 		binder_pop_transaction_ilocked(target_thread, in_reply_to);
-		binder_enqueue_work_ilocked(&t->work, target_list);
+		binder_enqueue_work_ilocked(&t->work, &target_thread->todo);
 		binder_inner_proc_unlock(target_proc);
+		wake_up_interruptible_sync(&target_thread->wait);
+		binder_restore_priority(current, in_reply_to->saved_priority);
 		binder_free_transaction(in_reply_to);
 	} else if (!(t->flags & TF_ONE_WAY)) {
 		BUG_ON(t->buffer->async_transaction != 0);
@@ -2867,47 +3225,17 @@
 		t->from_parent = thread->transaction_stack;
 		thread->transaction_stack = t;
 		binder_inner_proc_unlock(proc);
-		binder_inner_proc_lock(target_proc);
-		if (target_proc->is_dead ||
-				(target_thread && target_thread->is_dead)) {
-			binder_inner_proc_unlock(target_proc);
+		if (!binder_proc_transaction(t, target_proc, target_thread)) {
 			binder_inner_proc_lock(proc);
 			binder_pop_transaction_ilocked(thread, t);
 			binder_inner_proc_unlock(proc);
 			goto err_dead_proc_or_thread;
 		}
-		binder_enqueue_work_ilocked(&t->work, target_list);
-		binder_inner_proc_unlock(target_proc);
 	} else {
 		BUG_ON(target_node == NULL);
 		BUG_ON(t->buffer->async_transaction != 1);
-		binder_node_lock(target_node);
-		if (target_node->has_async_transaction) {
-			target_list = &target_node->async_todo;
-			target_wait = NULL;
-		} else
-			target_node->has_async_transaction = 1;
-		/*
-		 * Test/set of has_async_transaction
-		 * must be atomic with enqueue on
-		 * async_todo
-		 */
-		binder_inner_proc_lock(target_proc);
-		if (target_proc->is_dead ||
-				(target_thread && target_thread->is_dead)) {
-			binder_inner_proc_unlock(target_proc);
-			binder_node_unlock(target_node);
+		if (!binder_proc_transaction(t, target_proc, NULL))
 			goto err_dead_proc_or_thread;
-		}
-		binder_enqueue_work_ilocked(&t->work, target_list);
-		binder_inner_proc_unlock(target_proc);
-		binder_node_unlock(target_node);
-	}
-	if (target_wait) {
-		if (reply || !(tr->flags & TF_ONE_WAY))
-			wake_up_interruptible_sync(target_wait);
-		else
-			wake_up_interruptible(target_wait);
 	}
 	if (target_thread)
 		binder_thread_dec_tmpref(target_thread);
@@ -2977,6 +3305,7 @@
 
 	BUG_ON(thread->return_error.cmd != BR_OK);
 	if (in_reply_to) {
+		binder_restore_priority(current, in_reply_to->saved_priority);
 		thread->return_error.cmd = BR_TRANSACTION_COMPLETE;
 		binder_enqueue_work(thread->proc,
 				    &thread->return_error.work,
@@ -3347,12 +3676,13 @@
 							&ref->death->work,
 							&thread->todo);
 					else {
-						binder_enqueue_work(
-							proc,
+						binder_inner_proc_lock(proc);
+						binder_enqueue_work_ilocked(
 							&ref->death->work,
 							&proc->todo);
-						wake_up_interruptible(
-								&proc->wait);
+						binder_wakeup_proc_ilocked(
+							proc);
+						binder_inner_proc_unlock(proc);
 					}
 				}
 			} else {
@@ -3387,8 +3717,8 @@
 						binder_enqueue_work_ilocked(
 								&death->work,
 								&proc->todo);
-						wake_up_interruptible(
-								&proc->wait);
+						binder_wakeup_proc_ilocked(
+								proc);
 					}
 				} else {
 					BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
@@ -3443,7 +3773,7 @@
 					binder_enqueue_work_ilocked(
 							&death->work,
 							&proc->todo);
-					wake_up_interruptible(&proc->wait);
+					binder_wakeup_proc_ilocked(proc);
 				}
 			}
 			binder_inner_proc_unlock(proc);
@@ -3470,13 +3800,6 @@
 	}
 }
 
-static int binder_has_proc_work(struct binder_proc *proc,
-				struct binder_thread *thread)
-{
-	return !binder_worklist_empty(proc, &proc->todo) ||
-		thread->looper_need_return;
-}
-
 static int binder_has_thread_work(struct binder_thread *thread)
 {
 	return !binder_worklist_empty(thread->proc, &thread->todo) ||
@@ -3514,6 +3837,38 @@
 	return 0;
 }
 
+static int binder_wait_for_work(struct binder_thread *thread,
+				bool do_proc_work)
+{
+	DEFINE_WAIT(wait);
+	struct binder_proc *proc = thread->proc;
+	int ret = 0;
+
+	freezer_do_not_count();
+	binder_inner_proc_lock(proc);
+	for (;;) {
+		prepare_to_wait(&thread->wait, &wait, TASK_INTERRUPTIBLE);
+		if (binder_has_work_ilocked(thread, do_proc_work))
+			break;
+		if (do_proc_work)
+			list_add(&thread->waiting_thread_node,
+				 &proc->waiting_threads);
+		binder_inner_proc_unlock(proc);
+		schedule();
+		binder_inner_proc_lock(proc);
+		list_del_init(&thread->waiting_thread_node);
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	}
+	finish_wait(&thread->wait, &wait);
+	binder_inner_proc_unlock(proc);
+	freezer_count();
+
+	return ret;
+}
+
 static int binder_thread_read(struct binder_proc *proc,
 			      struct binder_thread *thread,
 			      binder_uintptr_t binder_buffer, size_t size,
@@ -3534,10 +3889,7 @@
 
 retry:
 	binder_inner_proc_lock(proc);
-	wait_for_proc_work = thread->transaction_stack == NULL &&
-		binder_worklist_empty_ilocked(&thread->todo);
-	if (wait_for_proc_work)
-		proc->ready_threads++;
+	wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
 	binder_inner_proc_unlock(proc);
 
 	thread->looper |= BINDER_LOOPER_STATE_WAITING;
@@ -3553,24 +3905,16 @@
 			wait_event_interruptible(binder_user_error_wait,
 						 binder_stop_on_user_error < 2);
 		}
-		binder_set_nice(proc->default_priority);
-		if (non_block) {
-			if (!binder_has_proc_work(proc, thread))
-				ret = -EAGAIN;
-		} else
-			ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
-	} else {
-		if (non_block) {
-			if (!binder_has_thread_work(thread))
-				ret = -EAGAIN;
-		} else
-			ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
+		binder_restore_priority(current, proc->default_priority);
 	}
 
-	binder_inner_proc_lock(proc);
-	if (wait_for_proc_work)
-		proc->ready_threads--;
-	binder_inner_proc_unlock(proc);
+	if (non_block) {
+		if (!binder_has_work(thread, wait_for_proc_work))
+			ret = -EAGAIN;
+	} else {
+		ret = binder_wait_for_work(thread, wait_for_proc_work);
+	}
+
 	thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
 
 	if (ret)
@@ -3773,16 +4117,14 @@
 		BUG_ON(t->buffer == NULL);
 		if (t->buffer->target_node) {
 			struct binder_node *target_node = t->buffer->target_node;
+			struct binder_priority node_prio;
 
 			tr.target.ptr = target_node->ptr;
 			tr.cookie =  target_node->cookie;
-			t->saved_priority = task_nice(current);
-			if (t->priority < target_node->min_priority &&
-			    !(t->flags & TF_ONE_WAY))
-				binder_set_nice(t->priority);
-			else if (!(t->flags & TF_ONE_WAY) ||
-				 t->saved_priority > target_node->min_priority)
-				binder_set_nice(target_node->min_priority);
+			node_prio.sched_policy = target_node->sched_policy;
+			node_prio.prio = target_node->min_priority;
+			binder_transaction_priority(current, t, node_prio,
+						    target_node->inherit_rt);
 			cmd = BR_TRANSACTION;
 		} else {
 			tr.target.ptr = 0;
@@ -3856,7 +4198,8 @@
 
 	*consumed = ptr - buffer;
 	binder_inner_proc_lock(proc);
-	if (proc->requested_threads + proc->ready_threads == 0 &&
+	if (proc->requested_threads == 0 &&
+	    list_empty(&thread->proc->waiting_threads) &&
 	    proc->requested_threads_started < proc->max_threads &&
 	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
 	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
@@ -3957,6 +4300,8 @@
 	binder_stats_created(BINDER_STAT_THREAD);
 	thread->proc = proc;
 	thread->pid = current->pid;
+	get_task_struct(current);
+	thread->task = current;
 	atomic_set(&thread->tmp_ref, 0);
 	init_waitqueue_head(&thread->wait);
 	INIT_LIST_HEAD(&thread->todo);
@@ -3967,7 +4312,7 @@
 	thread->return_error.cmd = BR_OK;
 	thread->reply_error.work.type = BINDER_WORK_RETURN_ERROR;
 	thread->reply_error.cmd = BR_OK;
-
+	INIT_LIST_HEAD(&new_thread->waiting_thread_node);
 	return thread;
 }
 
@@ -4007,6 +4352,7 @@
 	BUG_ON(!list_empty(&thread->todo));
 	binder_stats_deleted(BINDER_STAT_THREAD);
 	binder_proc_dec_tmpref(thread->proc);
+	put_task_struct(thread->task);
 	kfree(thread);
 }
 
@@ -4080,28 +4426,24 @@
 {
 	struct binder_proc *proc = filp->private_data;
 	struct binder_thread *thread = NULL;
-	int wait_for_proc_work;
+	bool wait_for_proc_work;
 
 	thread = binder_get_thread(proc);
 
 	binder_inner_proc_lock(thread->proc);
-	wait_for_proc_work = thread->transaction_stack == NULL &&
-		binder_worklist_empty_ilocked(&thread->todo);
+	thread->looper |= BINDER_LOOPER_STATE_POLL;
+	wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
+
 	binder_inner_proc_unlock(thread->proc);
 
-	if (wait_for_proc_work) {
-		if (binder_has_proc_work(proc, thread))
-			return POLLIN;
-		poll_wait(filp, &proc->wait, wait);
-		if (binder_has_proc_work(proc, thread))
-			return POLLIN;
-	} else {
-		if (binder_has_thread_work(thread))
-			return POLLIN;
-		poll_wait(filp, &thread->wait, wait);
-		if (binder_has_thread_work(thread))
-			return POLLIN;
-	}
+	if (binder_has_work(thread, wait_for_proc_work))
+		return POLLIN;
+
+	poll_wait(filp, &thread->wait, wait);
+
+	if (binder_has_thread_work(thread))
+		return POLLIN;
+
 	return 0;
 }
 
@@ -4148,8 +4490,10 @@
 					 &bwr.read_consumed,
 					 filp->f_flags & O_NONBLOCK);
 		trace_binder_read_done(ret);
-		if (!binder_worklist_empty(proc, &proc->todo))
-			wake_up_interruptible(&proc->wait);
+		binder_inner_proc_lock(proc);
+		if (!binder_worklist_empty_ilocked(&proc->todo))
+			binder_wakeup_proc_ilocked(proc);
+		binder_inner_proc_unlock(proc);
 		if (ret < 0) {
 			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
 				ret = -EFAULT;
@@ -4216,6 +4560,30 @@
 	return ret;
 }
 
+static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
+				struct binder_node_debug_info *info) {
+	struct rb_node *n;
+	binder_uintptr_t ptr = info->ptr;
+
+	memset(info, 0, sizeof(*info));
+
+	binder_inner_proc_lock(proc);
+	for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
+		struct binder_node *node = rb_entry(n, struct binder_node,
+						    rb_node);
+		if (node->ptr > ptr) {
+			info->ptr = node->ptr;
+			info->cookie = node->cookie;
+			info->has_strong_ref = node->has_strong_ref;
+			info->has_weak_ref = node->has_weak_ref;
+			break;
+		}
+	}
+	binder_inner_proc_unlock(proc);
+
+	return 0;
+}
+
 static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	int ret;
@@ -4283,6 +4651,24 @@
 		}
 		break;
 	}
+	case BINDER_GET_NODE_DEBUG_INFO: {
+		struct binder_node_debug_info info;
+
+		if (copy_from_user(&info, ubuf, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		ret = binder_ioctl_get_node_debug_info(proc, &info);
+		if (ret < 0)
+			goto err;
+
+		if (copy_to_user(ubuf, &info, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+		break;
+	}
 	default:
 		ret = -EINVAL;
 		goto err;
@@ -4389,8 +4775,14 @@
 	get_task_struct(current->group_leader);
 	proc->tsk = current->group_leader;
 	INIT_LIST_HEAD(&proc->todo);
-	init_waitqueue_head(&proc->wait);
-	proc->default_priority = task_nice(current);
+	if (binder_supported_policy(current->policy)) {
+		proc->default_priority.sched_policy = current->policy;
+		proc->default_priority.prio = current->normal_prio;
+	} else {
+		proc->default_priority.sched_policy = SCHED_NORMAL;
+		proc->default_priority.prio = NICE_TO_PRIO(0);
+	}
+
 	binder_dev = container_of(filp->private_data, struct binder_device,
 				  miscdev);
 	proc->context = &binder_dev->context;
@@ -4399,6 +4791,7 @@
 	binder_stats_created(BINDER_STAT_PROC);
 	proc->pid = current->group_leader->pid;
 	INIT_LIST_HEAD(&proc->delivered_death);
+	INIT_LIST_HEAD(&proc->waiting_threads);
 	filp->private_data = proc;
 
 	mutex_lock(&binder_procs_lock);
@@ -4450,7 +4843,6 @@
 		}
 	}
 	binder_inner_proc_unlock(proc);
-	wake_up_interruptible_all(&proc->wait);
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
 		     "binder_flush: %d woke %d threads\n", proc->pid,
@@ -4519,7 +4911,7 @@
 		ref->death->work.type = BINDER_WORK_DEAD_BINDER;
 		binder_enqueue_work_ilocked(&ref->death->work,
 					    &ref->proc->todo);
-		wake_up_interruptible(&ref->proc->wait);
+		binder_wakeup_proc_ilocked(ref->proc);
 		binder_inner_proc_unlock(ref->proc);
 	}
 
@@ -4683,13 +5075,14 @@
 	spin_lock(&t->lock);
 	to_proc = t->to_proc;
 	seq_printf(m,
-		   "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+		   "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %d:%d r%d",
 		   prefix, t->debug_id, t,
 		   t->from ? t->from->proc->pid : 0,
 		   t->from ? t->from->pid : 0,
 		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
-		   t->code, t->flags, t->priority, t->need_reply);
+		   t->code, t->flags, t->priority.sched_policy,
+		   t->priority.prio, t->need_reply);
 	spin_unlock(&t->lock);
 
 	if (proc != to_proc) {
@@ -4812,8 +5205,9 @@
 	hlist_for_each_entry(ref, &node->refs, node_entry)
 		count++;
 
-	seq_printf(m, "  node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d",
+	seq_printf(m, "  node %d: u%016llx c%016llx pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d",
 		   node->debug_id, (u64)node->ptr, (u64)node->cookie,
+		   node->sched_policy, node->min_priority,
 		   node->has_strong_ref, node->has_weak_ref,
 		   node->local_strong_refs, node->local_weak_refs,
 		   node->internal_strong_refs, count, node->tmp_refs);
@@ -5007,23 +5401,29 @@
 				    struct binder_proc *proc)
 {
 	struct binder_work *w;
+	struct binder_thread *thread;
 	struct rb_node *n;
-	int count, strong, weak;
+	int count, strong, weak, ready_threads;
 	size_t free_async_space =
 		binder_alloc_get_free_async_space(&proc->alloc);
 
 	seq_printf(m, "proc %d\n", proc->pid);
 	seq_printf(m, "context %s\n", proc->context->name);
 	count = 0;
+	ready_threads = 0;
 	binder_inner_proc_lock(proc);
 	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
 		count++;
+
+	list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node)
+		ready_threads++;
+
 	seq_printf(m, "  threads: %d\n", count);
 	seq_printf(m, "  requested threads: %d+%d/%d\n"
 			"  ready threads %d\n"
 			"  free async space %zd\n", proc->requested_threads,
 			proc->requested_threads_started, proc->max_threads,
-			proc->ready_threads,
+			ready_threads,
 			free_async_space);
 	count = 0;
 	for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index e167a1e1..4f638ab 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -165,7 +165,8 @@
 {
 	int ret;
 
-	ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma);
+	ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed,
+					"reserved", res_cma);
 	if (ret)
 		return ret;
 
@@ -257,7 +258,7 @@
 		return -EINVAL;
 	}
 
-	err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
+	err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma);
 	if (err) {
 		pr_err("Reserved memory: unable to setup CMA region\n");
 		return err;
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index aa5e22c..7c8f6bf 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -306,7 +306,7 @@
 			unsigned long vm_flags,
 			pgprot_t prot, const void *caller)
 {
-	int i;
+	unsigned long i;
 	struct page **pages;
 	void *ptr;
 	unsigned long pfn;
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index e023066..8c7d0f3 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1029,8 +1029,6 @@
 
 	spin_unlock_irq(&dev->power.lock);
 
-	dev_pm_domain_set(dev, &genpd->domain);
-
 	return gpd_data;
 
  err_free:
@@ -1044,8 +1042,6 @@
 static void genpd_free_dev_data(struct device *dev,
 				struct generic_pm_domain_data *gpd_data)
 {
-	dev_pm_domain_set(dev, NULL);
-
 	spin_lock_irq(&dev->power.lock);
 
 	dev->power.subsys_data->domain_data = NULL;
@@ -1082,6 +1078,8 @@
 	if (ret)
 		goto out;
 
+	dev_pm_domain_set(dev, &genpd->domain);
+
 	genpd->device_count++;
 	genpd->max_off_time_changed = true;
 
@@ -1143,6 +1141,8 @@
 	if (genpd->detach_dev)
 		genpd->detach_dev(genpd, dev);
 
+	dev_pm_domain_set(dev, NULL);
+
 	list_del_init(&pdd->list_node);
 
 	mutex_unlock(&genpd->lock);
@@ -1244,7 +1244,7 @@
 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 			      struct generic_pm_domain *subdomain)
 {
-	struct gpd_link *link;
+	struct gpd_link *l, *link;
 	int ret = -EINVAL;
 
 	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
@@ -1260,7 +1260,7 @@
 		goto out;
 	}
 
-	list_for_each_entry(link, &genpd->master_links, master_node) {
+	list_for_each_entry_safe(link, l, &genpd->master_links, master_node) {
 		if (link->slave != subdomain)
 			continue;
 
@@ -1607,12 +1607,12 @@
  */
 void of_genpd_del_provider(struct device_node *np)
 {
-	struct of_genpd_provider *cp;
+	struct of_genpd_provider *cp, *tmp;
 	struct generic_pm_domain *gpd;
 
 	mutex_lock(&gpd_list_lock);
 	mutex_lock(&of_genpd_mutex);
-	list_for_each_entry(cp, &of_genpd_providers, link) {
+	list_for_each_entry_safe(cp, tmp, &of_genpd_providers, link) {
 		if (cp->node == np) {
 			/*
 			 * For each PM domain associated with the
@@ -1752,14 +1752,14 @@
  */
 struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
 {
-	struct generic_pm_domain *gpd, *genpd = ERR_PTR(-ENOENT);
+	struct generic_pm_domain *gpd, *tmp, *genpd = ERR_PTR(-ENOENT);
 	int ret;
 
 	if (IS_ERR_OR_NULL(np))
 		return ERR_PTR(-EINVAL);
 
 	mutex_lock(&gpd_list_lock);
-	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+	list_for_each_entry_safe(gpd, tmp, &gpd_list, gpd_list_node) {
 		if (gpd->provider == &np->fwnode) {
 			ret = genpd_remove(gpd);
 			genpd = ret ? ERR_PTR(ret) : gpd;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a7b4679..39efa7e 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -268,6 +268,8 @@
 			value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
 		else if (!strcmp(buf, "any") || !strcmp(buf, "any\n"))
 			value = PM_QOS_LATENCY_ANY;
+		else
+			return -EINVAL;
 	}
 	ret = dev_pm_qos_update_user_latency_tolerance(dev, value);
 	return ret < 0 ? ret : n;
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 270cdd4..90c16d8 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -61,6 +61,8 @@
 
 static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
 
+DEFINE_STATIC_SRCU(wakeup_srcu);
+
 static struct wakeup_source deleted_ws = {
 	.name = "deleted",
 	.lock =  __SPIN_LOCK_UNLOCKED(deleted_ws.lock),
@@ -199,7 +201,7 @@
 	spin_lock_irqsave(&events_lock, flags);
 	list_del_rcu(&ws->entry);
 	spin_unlock_irqrestore(&events_lock, flags);
-	synchronize_rcu();
+	synchronize_srcu(&wakeup_srcu);
 }
 EXPORT_SYMBOL_GPL(wakeup_source_remove);
 
@@ -333,12 +335,12 @@
 void device_wakeup_arm_wake_irqs(void)
 {
 	struct wakeup_source *ws;
+	int srcuidx;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
 		dev_pm_arm_wake_irq(ws->wakeirq);
-
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 
 /**
@@ -349,12 +351,12 @@
 void device_wakeup_disarm_wake_irqs(void)
 {
 	struct wakeup_source *ws;
+	int srcuidx;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
 		dev_pm_disarm_wake_irq(ws->wakeirq);
-
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 
 /**
@@ -837,10 +839,10 @@
 void pm_print_active_wakeup_sources(void)
 {
 	struct wakeup_source *ws;
-	int active = 0;
+	int srcuidx, active = 0;
 	struct wakeup_source *last_activity_ws = NULL;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
 		if (ws->active) {
 			pr_info("active wakeup source: %s\n", ws->name);
@@ -856,7 +858,7 @@
 	if (!active && last_activity_ws)
 		pr_info("last active wakeup source: %s\n",
 			last_activity_ws->name);
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
 
@@ -983,8 +985,9 @@
 {
 	struct wakeup_source *ws;
 	ktime_t now = ktime_get();
+	int srcuidx;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
 		spin_lock_irq(&ws->lock);
 		if (ws->autosleep_enabled != set) {
@@ -998,7 +1001,7 @@
 		}
 		spin_unlock_irq(&ws->lock);
 	}
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 #endif /* CONFIG_PM_AUTOSLEEP */
 
@@ -1059,15 +1062,16 @@
 static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
 {
 	struct wakeup_source *ws;
+	int srcuidx;
 
 	seq_puts(m, "name\t\t\t\t\tactive_count\tevent_count\twakeup_count\t"
 		"expire_count\tactive_since\ttotal_time\tmax_time\t"
 		"last_change\tprevent_suspend_time\n");
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
 		print_wakeup_source_stats(m, ws);
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 
 	print_wakeup_source_stats(m, &deleted_ws);
 
diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c
index f50bf6f..8f0e632 100644
--- a/drivers/bluetooth/btfm_slim.c
+++ b/drivers/bluetooth/btfm_slim.c
@@ -496,9 +496,18 @@
 	/* Driver specific data allocation */
 	btfm_slim->dev = &slim->dev;
 	ret = btfm_slim_register_codec(&slim->dev);
+	if (ret) {
+		BTFMSLIM_ERR("error, registering slimbus codec failed");
+		goto free;
+	}
 	ret = bt_register_slimdev(&slim->dev);
+	if (ret < 0) {
+		btfm_slim_unregister_codec(&slim->dev);
+		goto free;
+	}
 	return ret;
-
+free:
+	slim_remove_device(&btfm_slim->slim_ifd);
 dealloc:
 	mutex_destroy(&btfm_slim->io_lock);
 	mutex_destroy(&btfm_slim->xfer_lock);
diff --git a/drivers/bluetooth/btfm_slim.h b/drivers/bluetooth/btfm_slim.h
index ed3a743..cc9d14d 100644
--- a/drivers/bluetooth/btfm_slim.h
+++ b/drivers/bluetooth/btfm_slim.h
@@ -162,4 +162,12 @@
  * 0
  */
 int btfm_slim_register_codec(struct device *dev);
+
+/**
+ * btfm_slim_unregister_codec: Unregister codec driver in slimbus device node
+ * @dev: device node
+ * Returns:
+ * VOID
+ */
+void btfm_slim_unregister_codec(struct device *dev);
 #endif /* BTFM_SLIM_H */
diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
index 791ea29..309648f 100644
--- a/drivers/bluetooth/btfm_slim_codec.c
+++ b/drivers/bluetooth/btfm_slim_codec.c
@@ -26,6 +26,9 @@
 #include <sound/tlv.h>
 #include <btfm_slim.h>
 
+static int bt_soc_enable_status;
+
+
 static int btfm_slim_codec_write(struct snd_soc_codec *codec, unsigned int reg,
 	unsigned int value)
 {
@@ -38,8 +41,31 @@
 	return 0;
 }
 
+static int bt_soc_status_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = bt_soc_enable_status;
+	return 1;
+}
+
+static int bt_soc_status_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	return 1;
+}
+
+static const struct snd_kcontrol_new status_controls[] = {
+	SOC_SINGLE_EXT("BT SOC status", 0, 0, 1, 0,
+			bt_soc_status_get,
+			bt_soc_status_put)
+
+};
+
+
 static int btfm_slim_codec_probe(struct snd_soc_codec *codec)
 {
+	snd_soc_add_codec_controls(codec, status_controls,
+				   ARRAY_SIZE(status_controls));
 	return 0;
 }
 
@@ -92,9 +118,6 @@
 		return;
 	}
 
-	if (dai->id == BTFM_FM_SLIM_TX)
-		goto out;
-
 	/* Search for dai->id matched port handler */
 	for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) &&
 		(ch->id != BTFM_SLIM_NUM_CODEC_DAIS) &&
@@ -108,7 +131,6 @@
 	}
 
 	btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan);
-out:
 	btfm_slim_hw_deinit(btfmslim);
 }
 
@@ -130,6 +152,7 @@
 	struct btfmslim *btfmslim = dai->dev->platform_data;
 	struct btfmslim_ch *ch;
 	uint8_t rxport, grp = false, nchan = 1;
+	bt_soc_enable_status = 0;
 
 	BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
 		dai->id, dai->rate);
@@ -171,61 +194,10 @@
 	}
 
 	ret = btfm_slim_enable_ch(btfmslim, ch, rxport, dai->rate, grp, nchan);
-	return ret;
-}
 
-static int btfm_slim_dai_hw_free(struct snd_pcm_substream *substream,
-	struct snd_soc_dai *dai)
-{
-	int ret = -EINVAL, i;
-	struct btfmslim *btfmslim = dai->dev->platform_data;
-	struct btfmslim_ch *ch;
-	uint8_t rxport, grp = false, nchan = 1;
-
-	BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
-		dai->id, dai->rate);
-
-	switch (dai->id) {
-	case BTFM_FM_SLIM_TX:
-		grp = true; nchan = 2;
-		ch = btfmslim->tx_chs;
-		rxport = 0;
-		break;
-	case BTFM_BT_SCO_SLIM_TX:
-		ch = btfmslim->tx_chs;
-		rxport = 0;
-		break;
-	case BTFM_BT_SCO_A2DP_SLIM_RX:
-	case BTFM_BT_SPLIT_A2DP_SLIM_RX:
-		ch = btfmslim->rx_chs;
-		rxport = 1;
-		break;
-	case BTFM_SLIM_NUM_CODEC_DAIS:
-	default:
-		BTFMSLIM_ERR("dai->id is invalid:%d", dai->id);
-		goto out;
-	}
-
-	if (dai->id != BTFM_FM_SLIM_TX) {
-		ret = 0;
-		goto out;
-	}
-
-	/* Search for dai->id matched port handler */
-	for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) &&
-		(ch->id != BTFM_SLIM_NUM_CODEC_DAIS) &&
-		(ch->id != dai->id); ch++, i++)
-		;
-
-	if ((ch->port == BTFM_SLIM_PGD_PORT_LAST) ||
-		(ch->id == BTFM_SLIM_NUM_CODEC_DAIS)) {
-		BTFMSLIM_ERR("ch is invalid!!");
-		goto out;
-	}
-
-	btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan);
-
-out:
+	/* save the enable channel status */
+	if (ret == 0)
+		bt_soc_enable_status = 1;
 	return ret;
 }
 
@@ -374,7 +346,6 @@
 	.shutdown = btfm_slim_dai_shutdown,
 	.hw_params = btfm_slim_dai_hw_params,
 	.prepare = btfm_slim_dai_prepare,
-	.hw_free = btfm_slim_dai_hw_free,
 	.set_channel_map = btfm_slim_dai_set_channel_map,
 	.get_channel_map = btfm_slim_dai_get_channel_map,
 };
@@ -462,5 +433,12 @@
 	return ret;
 }
 
+void btfm_slim_unregister_codec(struct device *dev)
+{
+	BTFMSLIM_DBG("");
+	/* Unregister Codec driver */
+	snd_soc_unregister_codec(dev);
+}
+
 MODULE_DESCRIPTION("BTFM Slimbus Codec driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 77e2973..3d66fff 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -82,18 +82,18 @@
 	uint8_t rxport, uint8_t enable)
 {
 	int ret = 0;
-	uint8_t reg_val = 0;
+	uint8_t reg_val = 0, en;
 	uint8_t port_bit = 0;
 	uint16_t reg;
 
 	BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
 	if (rxport) {
-		if (enable && btfmslim->sample_rate == 48000) {
-			/* For A2DP Rx */
+		if (enable) {
+			/* For SCO Rx, A2DP Rx */
 			reg_val = 0x1;
 			port_bit = port_num - 0x10;
 			reg = CHRK_SB_PGD_RX_PORTn_MULTI_CHNL_0(port_bit);
-			BTFMSLIM_DBG("writing reg_val (%d) to reg(%x) for A2DP",
+			BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
 					reg_val, reg);
 			ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
 			if (ret) {
@@ -137,15 +137,15 @@
 	reg = CHRK_SB_PGD_PORT_TX_CFGN(port_num);
 
 enable_disable_rxport:
-	if (enable) {
-		if (is_fm_port(port_num))
-			reg_val = CHRK_SB_PGD_PORT_ENABLE |
-					CHRK_SB_PGD_PORT_WM_L3;
-		else
-			reg_val = CHRK_SB_PGD_PORT_ENABLE |
-					CHRK_SB_PGD_PORT_WM_LB;
-	} else
-		reg_val = CHRK_SB_PGD_PORT_DISABLE;
+	if (enable)
+		en = CHRK_SB_PGD_PORT_ENABLE;
+	else
+		en = CHRK_SB_PGD_PORT_DISABLE;
+
+	if (is_fm_port(port_num))
+		reg_val = en | CHRK_SB_PGD_PORT_WM_L8;
+	else
+		reg_val = enable ? en | CHRK_SB_PGD_PORT_WM_LB : en;
 
 	ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
 	if (ret)
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.h b/drivers/bluetooth/btfm_slim_wcn3990.h
index 6bbdb6b..b2723ff 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.h
+++ b/drivers/bluetooth/btfm_slim_wcn3990.h
@@ -68,6 +68,7 @@
 #define CHRK_SB_PGD_PORT_WM_L1			(0x1 << 1)
 #define CHRK_SB_PGD_PORT_WM_L2			(0x2 << 1)
 #define CHRK_SB_PGD_PORT_WM_L3			(0x3 << 1)
+#define CHRK_SB_PGD_PORT_WM_L8			(0x8 << 1)
 #define CHRK_SB_PGD_PORT_WM_LB			(0xB << 1)
 
 #define CHRK_SB_PGD_PORT_RX_NUM			16
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 7bc263c..6c7c92a 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -45,7 +45,7 @@
 #include "adsprpc_compat.h"
 #include "adsprpc_shared.h"
 #include <linux/debugfs.h>
-
+#include <linux/pm_qos.h>
 #define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
 #define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
 #define TZ_PIL_AUTH_QDSP6_PROC 1
@@ -73,6 +73,7 @@
 #define PERF_KEYS "count:flush:map:copy:glink:getargs:putargs:invalidate:invoke"
 #define FASTRPC_STATIC_HANDLE_LISTENER (3)
 #define FASTRPC_STATIC_HANDLE_MAX (20)
+#define FASTRPC_LATENCY_CTRL_ENB  (1)
 
 #define PERF_END (void)0
 
@@ -235,6 +236,7 @@
 	spinlock_t hlock;
 	struct ion_client *client;
 	struct device *dev;
+	unsigned int latency;
 };
 
 struct fastrpc_mmap {
@@ -284,9 +286,12 @@
 	int cid;
 	int ssrcount;
 	int pd;
+	int file_close;
 	struct fastrpc_apps *apps;
 	struct fastrpc_perf perf;
 	struct dentry *debugfs_file;
+	struct pm_qos_request pm_qos_req;
+	int qos_request;
 };
 
 static struct fastrpc_apps gfa;
@@ -480,7 +485,7 @@
 
 	if (!IS_ERR_OR_NULL(map->handle))
 		ion_free(fl->apps->client, map->handle);
-	if (sess->smmu.enabled) {
+	if (sess && sess->smmu.enabled) {
 		if (map->size || map->phys)
 			msm_dma_unmap_sg(sess->dev,
 				map->table->sgl,
@@ -558,7 +563,9 @@
 		sess = fl->secsctx;
 	else
 		sess = fl->sctx;
-
+	VERIFY(err, !IS_ERR_OR_NULL(sess));
+	if (err)
+		goto bail;
 	VERIFY(err, !IS_ERR_OR_NULL(map->buf = dma_buf_get(fd)));
 	if (err)
 		goto bail;
@@ -1399,6 +1406,14 @@
 
 	if (fl->profile)
 		getnstimeofday(&invoket);
+
+	VERIFY(err, fl->sctx != NULL);
+	if (err)
+		goto bail;
+	VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS);
+	if (err)
+		goto bail;
+
 	if (!kernel) {
 		VERIFY(err, 0 == context_restore_interrupted(fl, inv,
 								&ctx));
@@ -1888,6 +1903,9 @@
 		return 0;
 	}
 	(void)fastrpc_release_current_dsp_process(fl);
+	spin_lock(&fl->hlock);
+	fl->file_close = 1;
+	spin_unlock(&fl->hlock);
 	fastrpc_context_list_dtor(fl);
 	fastrpc_buf_list_free(fl);
 	hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
@@ -1909,6 +1927,8 @@
 	struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
 
 	if (fl) {
+		if (fl->qos_request && pm_qos_request_active(&fl->pm_qos_req))
+			pm_qos_remove_request(&fl->pm_qos_req);
 		if (fl->debugfs_file != NULL)
 			debugfs_remove(fl->debugfs_file);
 		fastrpc_file_free(fl);
@@ -2172,6 +2192,11 @@
 		kref_init(&me->channel[cid].kref);
 		pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name,
 						MAJOR(me->dev_no), cid);
+		err = glink_queue_rx_intent(me->channel[cid].chan, NULL, 16);
+		err |= glink_queue_rx_intent(me->channel[cid].chan, NULL, 64);
+		if (err)
+			pr_warn("adsprpc: initial intent fail for %d err %d\n",
+					 cid, err);
 		if (me->channel[cid].ssrcount !=
 				 me->channel[cid].prevssrcount) {
 			me->channel[cid].prevssrcount =
@@ -2208,6 +2233,7 @@
 	if (debugfs_file != NULL)
 		fl->debugfs_file = debugfs_file;
 	memset(&fl->perf, 0, sizeof(fl->perf));
+	fl->qos_request = 0;
 	filp->private_data = fl;
 	spin_lock(&me->hlock);
 	hlist_add_head(&fl->hn, &me->drivers);
@@ -2235,11 +2261,49 @@
 		if (err)
 			goto bail;
 	}
+	VERIFY(err, fl->sctx != NULL);
+	if (err)
+		goto bail;
 	*info = (fl->sctx->smmu.enabled ? 1 : 0);
 bail:
 	return err;
 }
 
+static int fastrpc_internal_control(struct fastrpc_file *fl,
+					struct fastrpc_ioctl_control *cp)
+{
+	int err = 0;
+	int latency;
+
+	VERIFY(err, !IS_ERR_OR_NULL(fl) && !IS_ERR_OR_NULL(fl->apps));
+	if (err)
+		goto bail;
+	VERIFY(err, !IS_ERR_OR_NULL(cp));
+	if (err)
+		goto bail;
+
+	switch (cp->req) {
+	case FASTRPC_CONTROL_LATENCY:
+		latency = cp->lp.enable == FASTRPC_LATENCY_CTRL_ENB ?
+			fl->apps->latency : PM_QOS_DEFAULT_VALUE;
+		VERIFY(err, latency != 0);
+		if (err)
+			goto bail;
+		if (!fl->qos_request) {
+			pm_qos_add_request(&fl->pm_qos_req,
+				PM_QOS_CPU_DMA_LATENCY, latency);
+			fl->qos_request = 1;
+		} else
+			pm_qos_update_request(&fl->pm_qos_req, latency);
+		break;
+	default:
+		err = -ENOTTY;
+		break;
+	}
+bail:
+	return err;
+}
+
 static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
 				 unsigned long ioctl_param)
 {
@@ -2249,6 +2313,7 @@
 		struct fastrpc_ioctl_munmap munmap;
 		struct fastrpc_ioctl_init_attrs init;
 		struct fastrpc_ioctl_perf perf;
+		struct fastrpc_ioctl_control cp;
 	} p;
 	void *param = (char *)ioctl_param;
 	struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
@@ -2258,6 +2323,14 @@
 	p.inv.fds = 0;
 	p.inv.attrs = 0;
 	p.inv.crc = NULL;
+	spin_lock(&fl->hlock);
+	if (fl->file_close == 1) {
+		err = EBADF;
+		pr_warn("ADSPRPC: fastrpc_device_release is happening, So not sending any new requests to DSP");
+		spin_unlock(&fl->hlock);
+		goto bail;
+	}
+	spin_unlock(&fl->hlock);
 
 	switch (ioctl_num) {
 	case FASTRPC_IOCTL_INVOKE:
@@ -2340,6 +2413,15 @@
 		if (err)
 			goto bail;
 		break;
+	case FASTRPC_IOCTL_CONTROL:
+		VERIFY(err, 0 == copy_from_user(&p.cp, (void __user *)param,
+				sizeof(p.cp)));
+		if (err)
+			goto bail;
+		VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp)));
+		if (err)
+			goto bail;
+		break;
 	case FASTRPC_IOCTL_GETINFO:
 	    VERIFY(err, 0 == copy_from_user(&info, param, sizeof(info)));
 		if (err)
@@ -2459,7 +2541,7 @@
 		start = 0x60000000;
 	VERIFY(err, !IS_ERR_OR_NULL(sess->smmu.mapping =
 				arm_iommu_create_mapping(&platform_bus_type,
-						start, 0x7fffffff)));
+						start, 0x78000000)));
 	if (err)
 		goto bail;
 
@@ -2535,6 +2617,10 @@
 		return 0;
 	}
 
+	err = of_property_read_u32(dev->of_node, "qcom,rpc-latency-us",
+		&me->latency);
+	if (err)
+		me->latency = 0;
 	VERIFY(err, !of_platform_populate(pdev->dev.of_node,
 					  fastrpc_match_table,
 					  NULL, &pdev->dev));
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 078b4d9..21ad3f9 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -11,7 +11,6 @@
  * GNU General Public License for more details.
  *
  */
-
 #include <linux/compat.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
@@ -38,6 +37,8 @@
 		_IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
 #define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
 		_IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
+#define COMPAT_FASTRPC_IOCTL_CONTROL \
+		_IOWR('R', 12, struct compat_fastrpc_ioctl_control)
 
 struct compat_remote_buf {
 	compat_uptr_t pv;	/* buffer pointer */
@@ -108,6 +109,19 @@
 	compat_uptr_t keys;
 };
 
+#define FASTRPC_CONTROL_LATENCY   (1)
+struct compat_fastrpc_ctrl_latency {
+	compat_uint_t enable;	/* latency control enable */
+	compat_uint_t level;	/* level of control */
+};
+
+struct compat_fastrpc_ioctl_control {
+	compat_uint_t req;
+	union {
+		struct compat_fastrpc_ctrl_latency lp;
+	};
+};
+
 static int compat_get_fastrpc_ioctl_invoke(
 			struct compat_fastrpc_ioctl_invoke_crc __user *inv32,
 			struct fastrpc_ioctl_invoke_crc __user **inva,
@@ -236,6 +250,25 @@
 	return err;
 }
 
+static int compat_get_fastrpc_ioctl_control(
+			struct compat_fastrpc_ioctl_control __user *ctrl32,
+			struct fastrpc_ioctl_control __user *ctrl)
+{
+	compat_uptr_t p;
+	int err;
+
+	err = get_user(p, &ctrl32->req);
+	err |= put_user(p, &ctrl->req);
+	if (p == FASTRPC_CONTROL_LATENCY) {
+		err |= get_user(p, &ctrl32->lp.enable);
+		err |= put_user(p, &ctrl->lp.enable);
+		err |= get_user(p, &ctrl32->lp.level);
+		err |= put_user(p, &ctrl->lp.level);
+	}
+
+	return err;
+}
+
 static int compat_get_fastrpc_ioctl_init(
 			struct compat_fastrpc_ioctl_init_attrs __user *init32,
 			struct fastrpc_ioctl_init_attrs __user *init,
@@ -385,6 +418,24 @@
 	case FASTRPC_IOCTL_SETMODE:
 		return filp->f_op->unlocked_ioctl(filp, cmd,
 						(unsigned long)compat_ptr(arg));
+	case COMPAT_FASTRPC_IOCTL_CONTROL:
+	{
+		struct compat_fastrpc_ioctl_control __user *ctrl32;
+		struct fastrpc_ioctl_control __user *ctrl;
+
+		ctrl32 = compat_ptr(arg);
+		VERIFY(err, NULL != (ctrl = compat_alloc_user_space(
+							sizeof(*ctrl))));
+		if (err)
+			return -EFAULT;
+		VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
+							ctrl));
+		if (err)
+			return err;
+		err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL,
+							(unsigned long)ctrl);
+		return err;
+	}
 	case COMPAT_FASTRPC_IOCTL_GETPERF:
 	{
 		struct compat_fastrpc_ioctl_perf __user *perf32;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index e3fe064..9f964d2 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -28,6 +28,7 @@
 #define FASTRPC_IOCTL_GETPERF	_IOWR('R', 9, struct fastrpc_ioctl_perf)
 #define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs)
 #define FASTRPC_IOCTL_INVOKE_CRC _IOWR('R', 11, struct fastrpc_ioctl_invoke_crc)
+#define FASTRPC_IOCTL_CONTROL   _IOWR('R', 12, struct fastrpc_ioctl_control)
 
 #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
 #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@@ -100,7 +101,7 @@
 #define VERIFY(err, val) \
 do {\
 	VERIFY_IPRINTF(__FILE_LINE__"info: calling: " #val "\n");\
-	if (0 == (val)) {\
+	if ((val) == 0) {\
 		(err) = (err) == 0 ? -1 : (err);\
 		VERIFY_EPRINTF(__FILE_LINE__"error: %d: " #val "\n", (err));\
 	} else {\
@@ -205,6 +206,19 @@
 	uintptr_t __user keys;
 };
 
+#define FASTRPC_CONTROL_LATENCY   (1)
+struct fastrpc_ctrl_latency {
+	uint32_t enable;	//!latency control enable
+	uint32_t level;		//!level of control
+};
+
+struct fastrpc_ioctl_control {
+	uint32_t req;
+	union {
+		struct fastrpc_ctrl_latency lp;
+	};
+};
+
 struct smq_null_invoke {
 	uint64_t ctx;			/* invoke caller context */
 	uint32_t handle;	    /* handle to invoke */
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index a0a9ab6..177bbdb 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -69,6 +69,7 @@
 		"Uses Device Tree: %d\n"
 		"Apps Supports Separate CMDRSP: %d\n"
 		"Apps Supports HDLC Encoding: %d\n"
+		"Apps Supports Header Untagging: %d\n"
 		"Apps Supports Sockets: %d\n"
 		"Logging Mode: %d\n"
 		"RSP Buffer is Busy: %d\n"
@@ -83,6 +84,7 @@
 		driver->use_device_tree,
 		driver->supports_separate_cmdrsp,
 		driver->supports_apps_hdlc_encoding,
+		driver->supports_apps_header_untagging,
 		driver->supports_sockets,
 		driver->logging_mode,
 		driver->rsp_buf_busy,
@@ -94,7 +96,7 @@
 
 	for (i = 0; i < NUM_PERIPHERALS; i++) {
 		ret += scnprintf(buf+ret, buf_size-ret,
-			"p: %s Feature: %02x %02x |%c%c%c%c%c%c%c%c|\n",
+			"p: %s Feature: %02x %02x |%c%c%c%c%c%c%c%c%c|\n",
 			PERIPHERAL_STRING(i),
 			driver->feature[i].feature_mask[0],
 			driver->feature[i].feature_mask[1],
@@ -105,7 +107,8 @@
 			driver->feature[i].mask_centralization ? 'M':'m',
 			driver->feature[i].stm_support ? 'Q':'q',
 			driver->feature[i].sockets_enabled ? 'S':'s',
-			driver->feature[i].sent_feature_mask ? 'T':'t');
+			driver->feature[i].sent_feature_mask ? 'T':'t',
+			driver->feature[i].untag_header ? 'U':'u');
 	}
 
 #ifdef CONFIG_DIAG_OVER_USB
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 8aefb5a1..d734e29 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -28,7 +28,8 @@
 #define DIAG_SET_FEATURE_MASK(x) (feature_bytes[(x)/8] |= (1 << (x & 0x7)))
 
 #define diag_check_update(x)	\
-	(!info || (info && (info->peripheral_mask & MD_PERIPHERAL_MASK(x)))) \
+	(!info || (info && (info->peripheral_mask & MD_PERIPHERAL_MASK(x))) \
+	|| (info && (info->peripheral_mask & MD_PERIPHERAL_PD_MASK(x)))) \
 
 struct diag_mask_info msg_mask;
 struct diag_mask_info msg_bt_mask;
@@ -90,8 +91,8 @@
 	int err = 0;
 	int send_once = 0;
 	int header_len = sizeof(struct diag_ctrl_log_mask);
-	uint8_t *buf = NULL;
-	uint8_t *temp = NULL;
+	uint8_t *buf = NULL, *temp = NULL;
+	uint8_t upd = 0;
 	uint32_t mask_size = 0;
 	struct diag_ctrl_log_mask ctrl_pkt;
 	struct diag_mask_info *mask_info = NULL;
@@ -107,11 +108,25 @@
 		return;
 	}
 
-	if (driver->md_session_mask != 0 &&
-	    driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral))
-		mask_info = driver->md_session_map[peripheral]->log_mask;
-	else
+	if (driver->md_session_mask != 0) {
+		if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
+			if (driver->md_session_map[peripheral])
+				mask_info =
+				driver->md_session_map[peripheral]->log_mask;
+		} else if (driver->md_session_mask &
+				MD_PERIPHERAL_PD_MASK(peripheral)) {
+			upd = diag_mask_to_pd_value(driver->md_session_mask);
+			if (upd && driver->md_session_map[upd])
+				mask_info =
+				driver->md_session_map[upd]->log_mask;
+		} else {
+			DIAG_LOG(DIAG_DEBUG_MASKS,
+			"asking for mask update with unknown session mask\n");
+			return;
+		}
+	} else {
 		mask_info = &log_mask;
+	}
 
 	if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
 		return;
@@ -196,8 +211,8 @@
 
 static void diag_send_event_mask_update(uint8_t peripheral)
 {
-	uint8_t *buf = NULL;
-	uint8_t *temp = NULL;
+	uint8_t *buf = NULL, *temp = NULL;
+	uint8_t upd = 0;
 	struct diag_ctrl_event_mask header;
 	struct diag_mask_info *mask_info = NULL;
 	int num_bytes = EVENT_COUNT_TO_BYTES(driver->last_event_id);
@@ -221,11 +236,25 @@
 		return;
 	}
 
-	if (driver->md_session_mask != 0 &&
-	    (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)))
-		mask_info = driver->md_session_map[peripheral]->event_mask;
-	else
+	if (driver->md_session_mask != 0) {
+		if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
+			if (driver->md_session_map[peripheral])
+				mask_info =
+				driver->md_session_map[peripheral]->event_mask;
+		} else if (driver->md_session_mask &
+				MD_PERIPHERAL_PD_MASK(peripheral)) {
+			upd = diag_mask_to_pd_value(driver->md_session_mask);
+			if (upd && driver->md_session_map[upd])
+				mask_info =
+				driver->md_session_map[upd]->event_mask;
+		} else {
+			DIAG_LOG(DIAG_DEBUG_MASKS,
+			"asking for mask update with unknown session mask\n");
+			return;
+		}
+	} else {
 		mask_info = &event_mask;
+	}
 
 	if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
 		return;
@@ -285,8 +314,8 @@
 	int err = 0;
 	int header_len = sizeof(struct diag_ctrl_msg_mask);
 	int temp_len = 0;
-	uint8_t *buf = NULL;
-	uint8_t *temp = NULL;
+	uint8_t *buf = NULL, *temp = NULL;
+	uint8_t upd = 0;
 	uint32_t mask_size = 0;
 	struct diag_mask_info *mask_info = NULL;
 	struct diag_msg_mask_t *mask = NULL;
@@ -303,11 +332,25 @@
 		return;
 	}
 
-	if (driver->md_session_mask != 0 &&
-	    (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)))
-		mask_info = driver->md_session_map[peripheral]->msg_mask;
-	else
+	if (driver->md_session_mask != 0) {
+		if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
+			if (driver->md_session_map[peripheral])
+				mask_info =
+				driver->md_session_map[peripheral]->msg_mask;
+		} else if (driver->md_session_mask &
+				MD_PERIPHERAL_PD_MASK(peripheral)) {
+			upd = diag_mask_to_pd_value(driver->md_session_mask);
+			if (upd && driver->md_session_map[upd])
+				mask_info =
+				driver->md_session_map[upd]->msg_mask;
+		} else {
+			DIAG_LOG(DIAG_DEBUG_MASKS,
+			"asking for mask update with unknown session mask\n");
+			return;
+		}
+	} else {
 		mask_info = &msg_mask;
+	}
 
 	if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
 		return;
@@ -466,6 +509,13 @@
 		DIAG_SET_FEATURE_MASK(F_DIAG_REQ_RSP_SUPPORT);
 	if (driver->supports_apps_hdlc_encoding)
 		DIAG_SET_FEATURE_MASK(F_DIAG_APPS_HDLC_ENCODE);
+	if (driver->supports_apps_header_untagging) {
+		if (peripheral == PERIPHERAL_MODEM) {
+			DIAG_SET_FEATURE_MASK(F_DIAG_PKT_HEADER_UNTAG);
+			driver->peripheral_untag[peripheral] =
+				ENABLE_PKT_HEADER_UNTAGGING;
+		}
+	}
 	DIAG_SET_FEATURE_MASK(F_DIAG_MASK_CENTRALIZATION);
 	if (driver->supports_sockets)
 		DIAG_SET_FEATURE_MASK(F_DIAG_SOCKETS_ENABLED);
@@ -1933,17 +1983,27 @@
 void diag_send_updates_peripheral(uint8_t peripheral)
 {
 	diag_send_feature_mask_update(peripheral);
-	if (driver->time_sync_enabled)
-		diag_send_time_sync_update(peripheral);
-	mutex_lock(&driver->md_session_lock);
-	diag_send_msg_mask_update(peripheral, ALL_SSID, ALL_SSID);
-	diag_send_log_mask_update(peripheral, ALL_EQUIP_ID);
-	diag_send_event_mask_update(peripheral);
-	mutex_unlock(&driver->md_session_lock);
-	diag_send_real_time_update(peripheral,
+	/*
+	 * Masks (F3, logs and events) will be sent to
+	 * peripheral immediately following feature mask update only
+	 * if diag_id support is not present or
+	 * diag_id support is present and diag_id has been sent to
+	 * peripheral.
+	 */
+	if (!driver->feature[peripheral].diag_id_support ||
+		driver->diag_id_sent[peripheral]) {
+		if (driver->time_sync_enabled)
+			diag_send_time_sync_update(peripheral);
+		mutex_lock(&driver->md_session_lock);
+		diag_send_msg_mask_update(peripheral, ALL_SSID, ALL_SSID);
+		diag_send_log_mask_update(peripheral, ALL_EQUIP_ID);
+		diag_send_event_mask_update(peripheral);
+		mutex_unlock(&driver->md_session_lock);
+		diag_send_real_time_update(peripheral,
 				driver->real_time_mode[DIAG_LOCAL_PROC]);
-	diag_send_peripheral_buffering_mode(
-				&driver->buffering_mode[peripheral]);
+		diag_send_peripheral_buffering_mode(
+					&driver->buffering_mode[peripheral]);
+	}
 }
 
 int diag_process_apps_masks(unsigned char *buf, int len,
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 13ad402..7e3fe90 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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,6 +29,7 @@
 #include "diagmem.h"
 #include "diagfwd.h"
 #include "diagfwd_peripheral.h"
+#include "diag_ipc_logging.h"
 
 struct diag_md_info diag_md[NUM_DIAG_MD_DEV] = {
 	{
@@ -132,7 +133,7 @@
 	uint8_t found = 0;
 	unsigned long flags;
 	struct diag_md_info *ch = NULL;
-	uint8_t peripheral;
+	int peripheral;
 	struct diag_md_session_t *session_info = NULL;
 
 	if (id < 0 || id >= NUM_DIAG_MD_DEV || id >= DIAG_NUM_PROC)
@@ -141,11 +142,12 @@
 	if (!buf || len < 0)
 		return -EINVAL;
 
-	peripheral = GET_BUF_PERIPHERAL(ctx);
-	if (peripheral > NUM_PERIPHERALS)
+	peripheral = diag_md_get_peripheral(ctx);
+	if (peripheral < 0)
 		return -EINVAL;
 
-	session_info = diag_md_session_get_peripheral(peripheral);
+	session_info =
+		diag_md_session_get_peripheral(peripheral);
 	if (!session_info)
 		return -EIO;
 
@@ -214,7 +216,7 @@
 	struct diag_md_info *ch = NULL;
 	struct diag_buf_tbl_t *entry = NULL;
 	uint8_t drain_again = 0;
-	uint8_t peripheral = 0;
+	int peripheral = 0;
 	struct diag_md_session_t *session_info = NULL;
 
 	for (i = 0; i < NUM_DIAG_MD_DEV && !err; i++) {
@@ -223,12 +225,15 @@
 			entry = &ch->tbl[j];
 			if (entry->len <= 0)
 				continue;
-			peripheral = GET_BUF_PERIPHERAL(entry->ctx);
-			/* Account for Apps data as well */
-			if (peripheral > NUM_PERIPHERALS)
+
+			peripheral = diag_md_get_peripheral(entry->ctx);
+			if (peripheral < 0)
 				goto drop_data;
 			session_info =
 			diag_md_session_get_peripheral(peripheral);
+			if (!session_info)
+				goto drop_data;
+
 			if (session_info && info &&
 				(session_info->pid != info->pid))
 				continue;
@@ -320,8 +325,15 @@
 	spin_lock_irqsave(&ch->lock, flags);
 	for (i = 0; i < ch->num_tbl_entries && !found; i++) {
 		entry = &ch->tbl[i];
-		if (GET_BUF_PERIPHERAL(entry->ctx) != peripheral)
-			continue;
+
+		if (peripheral > NUM_PERIPHERALS) {
+			if (GET_PD_CTXT(entry->ctx) != peripheral)
+				continue;
+		} else {
+			if (GET_BUF_PERIPHERAL(entry->ctx) !=
+					peripheral)
+				continue;
+		}
 		found = 1;
 		if (ch->ops && ch->ops->write_done) {
 			ch->ops->write_done(entry->buf, entry->len,
diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c
index 8f5a002..e65b493 100644
--- a/drivers/char/diag/diag_mux.c
+++ b/drivers/char/diag/diag_mux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,7 +27,8 @@
 #include "diag_mux.h"
 #include "diag_usb.h"
 #include "diag_memorydevice.h"
-
+#include "diagfwd_peripheral.h"
+#include "diag_ipc_logging.h"
 
 struct diag_mux_state_t *diag_mux;
 static struct diag_logger_t usb_logger;
@@ -141,9 +142,13 @@
 	if (!diag_mux)
 		return -EIO;
 
-	peripheral = GET_BUF_PERIPHERAL(ctx);
-	if (peripheral > NUM_PERIPHERALS)
+	peripheral = diag_md_get_peripheral(ctx);
+	if (peripheral < 0) {
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+			"diag:%s:%d invalid peripheral = %d\n",
+			__func__, __LINE__, peripheral);
 		return -EINVAL;
+	}
 
 	if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask)
 		logger = diag_mux->md_ptr;
@@ -162,8 +167,13 @@
 	if (proc < 0 || proc >= NUM_MUX_PROC)
 		return -EINVAL;
 	/* Peripheral should account for Apps data as well */
-	if (peripheral > NUM_PERIPHERALS)
-		return -EINVAL;
+	if (peripheral > NUM_PERIPHERALS) {
+		if (!driver->num_pd_session)
+			return -EINVAL;
+		if (peripheral > NUM_MD_SESSIONS)
+			return -EINVAL;
+	}
+
 	if (!diag_mux)
 		return -EIO;
 
@@ -184,7 +194,8 @@
 	if (!req_mode)
 		return -EINVAL;
 
-	if (*peripheral_mask <= 0 || *peripheral_mask > DIAG_CON_ALL) {
+	if (*peripheral_mask <= 0 ||
+		(*peripheral_mask > (DIAG_CON_ALL | DIAG_CON_UPD_ALL))) {
 		pr_err("diag: mask %d in %s\n", *peripheral_mask, __func__);
 		return -EINVAL;
 	}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 8051d5d..ac3c1fd 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -58,19 +58,23 @@
 #define DIAG_CTRL_MSG_F3_MASK	11
 #define CONTROL_CHAR	0x7E
 
+#define DIAG_ID_ROOT_STRING "root"
+
 #define DIAG_CON_APSS		(0x0001)	/* Bit mask for APSS */
 #define DIAG_CON_MPSS		(0x0002)	/* Bit mask for MPSS */
 #define DIAG_CON_LPASS		(0x0004)	/* Bit mask for LPASS */
 #define DIAG_CON_WCNSS		(0x0008)	/* Bit mask for WCNSS */
 #define DIAG_CON_SENSORS	(0x0010)	/* Bit mask for Sensors */
-#define DIAG_CON_WDSP (0x0020) /* Bit mask for WDSP */
-#define DIAG_CON_CDSP (0x0040)
+#define DIAG_CON_WDSP		(0x0020)	/* Bit mask for WDSP */
+#define DIAG_CON_CDSP		(0x0040)	/* Bit mask for CDSP */
 
+#define DIAG_CON_UPD_WLAN		(0x1000) /*Bit mask for WLAN PD*/
 #define DIAG_CON_NONE		(0x0000)	/* Bit mask for No SS*/
 #define DIAG_CON_ALL		(DIAG_CON_APSS | DIAG_CON_MPSS \
 				| DIAG_CON_LPASS | DIAG_CON_WCNSS \
 				| DIAG_CON_SENSORS | DIAG_CON_WDSP \
 				| DIAG_CON_CDSP)
+#define DIAG_CON_UPD_ALL	(DIAG_CON_UPD_WLAN)
 
 #define DIAG_STM_MODEM	0x01
 #define DIAG_STM_LPASS	0x02
@@ -165,7 +169,7 @@
 #define PKT_ALLOC	1
 #define PKT_RESET	2
 
-#define FEATURE_MASK_LEN	2
+#define FEATURE_MASK_LEN	4
 
 #define DIAG_MD_NONE			0
 #define DIAG_MD_PERIPHERAL		1
@@ -209,11 +213,18 @@
 #define NUM_PERIPHERALS		6
 #define APPS_DATA		(NUM_PERIPHERALS)
 
+#define UPD_WLAN		7
+#define NUM_UPD			1
+#define MAX_PERIPHERAL_UPD			1
 /* Number of sessions possible in Memory Device Mode. +1 for Apps data */
-#define NUM_MD_SESSIONS		(NUM_PERIPHERALS + 1)
+#define NUM_MD_SESSIONS		(NUM_PERIPHERALS \
+					+ NUM_UPD + 1)
 
 #define MD_PERIPHERAL_MASK(x)	(1 << x)
 
+#define MD_PERIPHERAL_PD_MASK(x)					\
+	((x == PERIPHERAL_MODEM) ? (1 << UPD_WLAN) : 0)\
+
 /*
  * Number of stm processors includes all the peripherals and
  * apps.Added 1 below to indicate apps
@@ -439,6 +450,7 @@
 struct diag_logging_mode_param_t {
 	uint32_t req_mode;
 	uint32_t peripheral_mask;
+	uint32_t pd_mask;
 	uint8_t mode_param;
 } __packed;
 
@@ -485,11 +497,13 @@
 	uint8_t log_on_demand;
 	uint8_t separate_cmd_rsp;
 	uint8_t encode_hdlc;
+	uint8_t untag_header;
 	uint8_t peripheral_buffering;
 	uint8_t mask_centralization;
 	uint8_t stm_support;
 	uint8_t sockets_enabled;
 	uint8_t sent_feature_mask;
+	uint8_t diag_id_support;
 };
 
 struct diagchar_dev {
@@ -516,6 +530,8 @@
 	int use_device_tree;
 	int supports_separate_cmdrsp;
 	int supports_apps_hdlc_encoding;
+	int supports_apps_header_untagging;
+	int peripheral_untag[NUM_PERIPHERALS];
 	int supports_sockets;
 	/* The state requested in the STM command */
 	int stm_state_requested[NUM_STM_PROCESSORS];
@@ -612,6 +628,10 @@
 	int in_busy_dcipktdata;
 	int logging_mode;
 	int logging_mask;
+	int pd_logging_mode[NUM_UPD];
+	int pd_session_clear[NUM_UPD];
+	int num_pd_session;
+	int diag_id_sent[NUM_PERIPHERALS];
 	int mask_check;
 	uint32_t md_session_mask;
 	uint8_t md_session_mode;
@@ -672,6 +692,7 @@
 int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry);
 int diag_mask_param(void);
 void diag_clear_masks(struct diag_md_session_t *info);
+uint8_t diag_mask_to_pd_value(uint32_t peripheral_mask);
 
 void diag_record_stats(int type, int flag);
 
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index e4397c5..f0e69ef 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -393,9 +393,28 @@
 		ret |= DIAG_CON_WDSP;
 	if (peripheral_mask & MD_PERIPHERAL_MASK(PERIPHERAL_CDSP))
 		ret |= DIAG_CON_CDSP;
-
+	if (peripheral_mask & MD_PERIPHERAL_MASK(UPD_WLAN))
+		ret |= DIAG_CON_UPD_WLAN;
 	return ret;
 }
+
+uint8_t diag_mask_to_pd_value(uint32_t peripheral_mask)
+{
+	uint8_t upd = 0;
+	uint32_t pd_mask = 0;
+
+	pd_mask = diag_translate_kernel_to_user_mask(peripheral_mask);
+	switch (pd_mask) {
+	case DIAG_CON_UPD_WLAN:
+		upd = UPD_WLAN;
+		break;
+	default:
+		DIAG_LOG(DIAG_DEBUG_MASKS,
+		"asking for mask update with no pd mask set\n");
+	}
+	return upd;
+}
+
 int diag_mask_param(void)
 {
 	return diag_mask_clear_param;
@@ -423,8 +442,9 @@
 
 static void diag_close_logging_process(const int pid)
 {
-	int i;
-	int session_peripheral_mask;
+	int i, j;
+	int session_mask;
+	uint32_t p_mask;
 	struct diag_md_session_t *session_info = NULL;
 	struct diag_logging_mode_param_t params;
 
@@ -440,18 +460,33 @@
 	mutex_unlock(&driver->diag_maskclear_mutex);
 
 	mutex_lock(&driver->diagchar_mutex);
-	session_peripheral_mask = session_info->peripheral_mask;
+	session_mask = session_info->peripheral_mask;
 	diag_md_session_close(session_info);
-	mutex_unlock(&driver->diagchar_mutex);
+
+	p_mask =
+	diag_translate_kernel_to_user_mask(session_mask);
+
 	for (i = 0; i < NUM_MD_SESSIONS; i++)
-		if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask)
+		if (MD_PERIPHERAL_MASK(i) & session_mask)
 			diag_mux_close_peripheral(DIAG_LOCAL_PROC, i);
 
 	params.req_mode = USB_MODE;
 	params.mode_param = 0;
-	params.peripheral_mask =
-		diag_translate_kernel_to_user_mask(session_peripheral_mask);
-	mutex_lock(&driver->diagchar_mutex);
+	params.pd_mask = 0;
+	params.peripheral_mask = p_mask;
+
+	if (driver->num_pd_session > 0) {
+		for (i = UPD_WLAN; (i < NUM_MD_SESSIONS); i++) {
+			if (session_mask & MD_PERIPHERAL_MASK(i)) {
+				j = i - UPD_WLAN;
+				driver->pd_session_clear[j] = 1;
+				driver->pd_logging_mode[j] = 0;
+				driver->num_pd_session -= 1;
+				params.pd_mask = p_mask;
+			}
+		}
+	}
+
 	diag_switch_logging(&params);
 	mutex_unlock(&driver->diagchar_mutex);
 }
@@ -654,6 +689,11 @@
 	driver->polling_reg_flag = 0;
 	list_for_each_safe(start, temp, &driver->cmd_reg_list) {
 		item = list_entry(start, struct diag_cmd_reg_t, link);
+		if (&item->entry == NULL) {
+			pr_err("diag: In %s, unable to search command\n",
+			       __func__);
+			return;
+		}
 		polling = diag_cmd_chk_polling(&item->entry);
 		if (polling == DIAG_CMD_POLLING) {
 			driver->polling_reg_flag = 1;
@@ -793,6 +833,12 @@
 	mutex_lock(&driver->cmd_reg_mutex);
 	list_for_each_safe(start, temp, &driver->cmd_reg_list) {
 		item = list_entry(start, struct diag_cmd_reg_t, link);
+		if (&item->entry == NULL) {
+			pr_err("diag: In %s, unable to search command\n",
+			       __func__);
+			mutex_unlock(&driver->cmd_reg_mutex);
+			return;
+		}
 		if (item->pid == pid) {
 			list_del(&item->link);
 			kfree(item);
@@ -811,6 +857,12 @@
 	mutex_lock(&driver->cmd_reg_mutex);
 	list_for_each_safe(start, temp, &driver->cmd_reg_list) {
 		item = list_entry(start, struct diag_cmd_reg_t, link);
+		if (&item->entry == NULL) {
+			pr_err("diag: In %s, unable to search command\n",
+			       __func__);
+			mutex_unlock(&driver->cmd_reg_mutex);
+			return;
+		}
 		if (item->proc == proc) {
 			list_del(&item->link);
 			kfree(item);
@@ -1563,17 +1615,20 @@
 		ret |= (1 << PERIPHERAL_WDSP);
 	if (peripheral_mask & DIAG_CON_CDSP)
 		ret |= (1 << PERIPHERAL_CDSP);
+	if (peripheral_mask & DIAG_CON_UPD_WLAN)
+		ret |= (1 << UPD_WLAN);
 
 	return ret;
 }
 
 static int diag_switch_logging(struct diag_logging_mode_param_t *param)
 {
-	int new_mode;
+	int new_mode, i = 0;
 	int curr_mode;
 	int err = 0;
 	uint8_t do_switch = 1;
 	uint32_t peripheral_mask = 0;
+	uint8_t peripheral, upd;
 
 	if (!param)
 		return -EINVAL;
@@ -1584,8 +1639,41 @@
 		return -EINVAL;
 	}
 
-	peripheral_mask = diag_translate_mask(param->peripheral_mask);
-	param->peripheral_mask = peripheral_mask;
+	if (param->pd_mask) {
+		switch (param->pd_mask) {
+		case DIAG_CON_UPD_WLAN:
+			peripheral = PERIPHERAL_MODEM;
+			upd = UPD_WLAN;
+			break;
+		default:
+			DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"asking for mode switch with no pd mask set\n");
+			return -EINVAL;
+		}
+
+		if (driver->md_session_map[peripheral] &&
+			(MD_PERIPHERAL_MASK(peripheral) &
+			diag_mux->mux_mask)) {
+			DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"diag_fr: User PD is already logging onto active peripheral logging\n");
+			i = upd - UPD_WLAN;
+			driver->pd_session_clear[i] = 0;
+			return -EINVAL;
+		}
+		peripheral_mask =
+			diag_translate_mask(param->pd_mask);
+		param->peripheral_mask = peripheral_mask;
+		i = upd - UPD_WLAN;
+		if (!driver->pd_session_clear[i]) {
+			driver->pd_logging_mode[i] = 1;
+			driver->num_pd_session += 1;
+		}
+		driver->pd_session_clear[i] = 0;
+	} else {
+		peripheral_mask =
+			diag_translate_mask(param->peripheral_mask);
+		param->peripheral_mask = peripheral_mask;
+	}
 
 	switch (param->req_mode) {
 	case CALLBACK_MODE:
@@ -1605,7 +1693,7 @@
 
 	curr_mode = driver->logging_mode;
 	DIAG_LOG(DIAG_DEBUG_USERSPACE,
-		"request to switch logging from %d mask:%0x to %d mask:%0x\n",
+		"request to switch logging from %d mask:%0x to new_mode %d mask:%0x\n",
 		curr_mode, driver->md_session_mask, new_mode, peripheral_mask);
 
 	err = diag_md_session_check(curr_mode, new_mode, param, &do_switch);
@@ -1929,6 +2017,52 @@
 	return 0;
 }
 
+static int diag_ioctl_query_pd_logging(struct diag_logging_mode_param_t *param)
+{
+	int ret = -EINVAL;
+	int peripheral;
+	char *p_str = NULL;
+
+	if (!param)
+		return -EINVAL;
+
+	if (!param->pd_mask) {
+		DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"query with no pd mask set, returning error\n");
+		return -EINVAL;
+	}
+
+	switch (param->pd_mask) {
+	case DIAG_CON_UPD_WLAN:
+		peripheral = PERIPHERAL_MODEM;
+		p_str = "MODEM";
+		break;
+	default:
+		DIAG_LOG(DIAG_DEBUG_USERSPACE,
+		"Invalid pd mask, returning EINVAL\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&driver->diag_cntl_mutex);
+	DIAG_LOG(DIAG_DEBUG_USERSPACE,
+	"diag: %s: Untagging support on APPS is %s\n", __func__,
+	((driver->supports_apps_header_untagging) ?
+	"present" : "absent"));
+
+	DIAG_LOG(DIAG_DEBUG_USERSPACE,
+	"diag: %s: Tagging support on %s is %s\n",
+	__func__, p_str,
+	(driver->feature[peripheral].untag_header ?
+	"present" : "absent"));
+
+	if (driver->supports_apps_header_untagging &&
+		driver->feature[peripheral].untag_header)
+		ret = 0;
+
+	mutex_unlock(&driver->diag_cntl_mutex);
+	return ret;
+}
+
 static int diag_ioctl_register_callback(unsigned long ioarg)
 {
 	int err = 0;
@@ -2166,6 +2300,12 @@
 	case DIAG_IOCTL_HDLC_TOGGLE:
 		result = diag_ioctl_hdlc_toggle(ioarg);
 		break;
+	case DIAG_IOCTL_QUERY_PD_LOGGING:
+		if (copy_from_user((void *)&mode_param, (void __user *)ioarg,
+				   sizeof(mode_param)))
+			return -EFAULT;
+		result = diag_ioctl_query_pd_logging(&mode_param);
+		break;
 	}
 	return result;
 }
@@ -2289,6 +2429,12 @@
 	case DIAG_IOCTL_HDLC_TOGGLE:
 		result = diag_ioctl_hdlc_toggle(ioarg);
 		break;
+	case DIAG_IOCTL_QUERY_PD_LOGGING:
+		if (copy_from_user((void *)&mode_param, (void __user *)ioarg,
+				   sizeof(mode_param)))
+			return -EFAULT;
+		result = diag_ioctl_query_pd_logging(&mode_param);
+		break;
 	}
 	return result;
 }
@@ -3342,7 +3488,7 @@
 	 * to be logged to IPC
 	 */
 	diag_debug_mask = DIAG_DEBUG_PERIPHERALS | DIAG_DEBUG_DCI |
-				DIAG_DEBUG_BRIDGE;
+				DIAG_DEBUG_USERSPACE | DIAG_DEBUG_BRIDGE;
 }
 #else
 static void diag_debug_init(void)
@@ -3472,6 +3618,11 @@
 			poolsize_usb_apps + 1 + (NUM_PERIPHERALS * 6));
 	driver->num_clients = max_clients;
 	driver->logging_mode = DIAG_USB_MODE;
+	for (i = 0; i < NUM_UPD; i++) {
+		driver->pd_logging_mode[i] = 0;
+		driver->pd_session_clear[i] = 0;
+	}
+	driver->num_pd_session = 0;
 	driver->mask_check = 0;
 	driver->in_busy_pktdata = 0;
 	driver->in_busy_dcipktdata = 0;
@@ -3489,8 +3640,10 @@
 	mutex_init(&apps_data_mutex);
 	mutex_init(&driver->msg_mask_lock);
 	mutex_init(&driver->hdlc_recovery_mutex);
-	for (i = 0; i < NUM_PERIPHERALS; i++)
+	for (i = 0; i < NUM_PERIPHERALS; i++) {
 		mutex_init(&driver->diagfwd_channel_mutex[i]);
+		driver->diag_id_sent[i] = 0;
+	}
 	init_waitqueue_head(&driver->wait_q);
 	INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
 	INIT_WORK(&(driver->update_user_clients),
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 3f00a7e..b59f245 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -38,6 +38,7 @@
 #include "diag_masks.h"
 #include "diag_usb.h"
 #include "diag_mux.h"
+#include "diag_ipc_logging.h"
 
 #define STM_CMD_VERSION_OFFSET	4
 #define STM_CMD_MASK_OFFSET	5
@@ -1663,6 +1664,9 @@
 		driver->real_time_mode[i] = 1;
 	driver->supports_separate_cmdrsp = 1;
 	driver->supports_apps_hdlc_encoding = 1;
+	driver->supports_apps_header_untagging = 1;
+	for (i = 0; i < NUM_PERIPHERALS; i++)
+		driver->peripheral_untag[i] = 0;
 	mutex_init(&driver->diag_hdlc_mutex);
 	mutex_init(&driver->diag_cntl_mutex);
 	mutex_init(&driver->mode_lock);
@@ -1692,9 +1696,12 @@
 		driver->feature[i].rcvd_feature_mask = 0;
 		driver->feature[i].peripheral_buffering = 0;
 		driver->feature[i].encode_hdlc = 0;
+		driver->feature[i].untag_header =
+			DISABLE_PKT_HEADER_UNTAGGING;
 		driver->feature[i].mask_centralization = 0;
 		driver->feature[i].log_on_demand = 0;
 		driver->feature[i].sent_feature_mask = 0;
+		driver->feature[i].diag_id_support = 0;
 		driver->buffering_mode[i].peripheral = i;
 		driver->buffering_mode[i].mode = DIAG_BUFFERING_MODE_STREAMING;
 		driver->buffering_mode[i].high_wm_val = DEFAULT_HIGH_WM_VAL;
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 47c8555..677099f 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,9 +19,11 @@
  */
 #define SET_BUF_CTXT(p, d, n) \
 	(((p & 0xFF) << 16) | ((d & 0xFF) << 8) | (n & 0xFF))
+#define SET_PD_CTXT(u)		((u & 0xFF) << 24)
 #define GET_BUF_PERIPHERAL(p)	((p & 0xFF0000) >> 16)
 #define GET_BUF_TYPE(d)		((d & 0x00FF00) >> 8)
 #define GET_BUF_NUM(n)		((n & 0x0000FF))
+#define GET_PD_CTXT(u)		((u & 0xFF000000) >> 24)
 
 #define CHK_OVERFLOW(bufStart, start, end, length) \
 	((((bufStart) <= (start)) && ((end) - (start) >= (length))) ? 1 : 0)
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index c975654..d7e24fc 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -68,9 +68,9 @@
 
 	driver->feature[peripheral].sent_feature_mask = 0;
 	driver->feature[peripheral].rcvd_feature_mask = 0;
-	flush_workqueue(driver->cntl_wq);
 	reg_dirty |= PERIPHERAL_MASK(peripheral);
 	diag_cmd_remove_reg_by_proc(peripheral);
+	driver->diag_id_sent[peripheral] = 0;
 	driver->feature[peripheral].stm_support = DISABLE_STM;
 	driver->feature[peripheral].log_on_demand = 0;
 	driver->stm_state[peripheral] = DISABLE_STM;
@@ -199,6 +199,20 @@
 	}
 }
 
+static void process_upd_header_untagging_feature(uint8_t peripheral)
+{
+	if (peripheral >= NUM_PERIPHERALS)
+		return;
+
+	if (driver->supports_apps_header_untagging) {
+		driver->feature[peripheral].untag_header =
+					ENABLE_PKT_HEADER_UNTAGGING;
+	} else {
+		driver->feature[peripheral].untag_header =
+					DISABLE_PKT_HEADER_UNTAGGING;
+	}
+}
+
 static void process_command_deregistration(uint8_t *buf, uint32_t len,
 					   uint8_t peripheral)
 {
@@ -375,6 +389,8 @@
 			driver->feature[peripheral].separate_cmd_rsp = 1;
 		if (FEATURE_SUPPORTED(F_DIAG_APPS_HDLC_ENCODE))
 			process_hdlc_encoding_feature(peripheral);
+		if (FEATURE_SUPPORTED(F_DIAG_PKT_HEADER_UNTAG))
+			process_upd_header_untagging_feature(peripheral);
 		if (FEATURE_SUPPORTED(F_DIAG_STM))
 			enable_stm_feature(peripheral);
 		if (FEATURE_SUPPORTED(F_DIAG_MASK_CENTRALIZATION))
@@ -383,6 +399,8 @@
 			driver->feature[peripheral].peripheral_buffering = 1;
 		if (FEATURE_SUPPORTED(F_DIAG_SOCKETS_ENABLED))
 			enable_socket_feature(peripheral);
+		if (FEATURE_SUPPORTED(F_DIAG_DIAGID_SUPPORT))
+			driver->feature[peripheral].diag_id_support = 1;
 	}
 
 	process_socket_feature(peripheral);
@@ -707,12 +725,24 @@
 {
 	struct diag_ctrl_diagid *header = NULL;
 	struct diag_ctrl_diagid ctrl_pkt;
+	struct diagfwd_info *fwd_info_data = NULL;
+	struct diagfwd_info *fwd_info_cmd = NULL;
 	char *process_name = NULL;
 	int err = 0;
 	uint8_t local_diag_id = 0;
+	uint8_t new_request = 0;
 
 	if (!buf || len == 0 || peripheral >= NUM_PERIPHERALS)
 		return;
+
+	fwd_info_data = &peripheral_info[TYPE_DATA][peripheral];
+	if (!fwd_info_data)
+		return;
+
+	fwd_info_cmd = &peripheral_info[TYPE_CMD][peripheral];
+	if (!fwd_info_cmd)
+		return;
+
 	header = (struct diag_ctrl_diagid *)buf;
 	process_name = (char *)&header->process_name;
 	if (diag_query_diag_id(process_name, &local_diag_id))
@@ -721,7 +751,27 @@
 		diag_id++;
 		diag_add_diag_id_to_list(diag_id, process_name);
 		ctrl_pkt.diag_id = diag_id;
+		new_request = 1;
 	}
+
+	if (new_request) {
+		fwd_info_data->num_pd++;
+		fwd_info_cmd->num_pd++;
+	}
+
+	if (strnstr(process_name, DIAG_ID_ROOT_STRING, strlen(process_name))) {
+		fwd_info_cmd->diagid_root = diag_id;
+		fwd_info_data->diagid_root = diag_id;
+		driver->diag_id_sent[peripheral] = 0;
+	} else {
+		fwd_info_cmd->diagid_user[fwd_info_cmd->num_pd - 2] = diag_id;
+		fwd_info_data->diagid_user[fwd_info_data->num_pd - 2] = diag_id;
+	}
+
+	DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: peripheral = %d: diag_id string = %s,diag_id = %d\n",
+		peripheral, process_name, ctrl_pkt.diag_id);
+
 	ctrl_pkt.pkt_id = DIAG_CTRL_MSG_DIAGID;
 	ctrl_pkt.version = 1;
 	strlcpy((char *)&ctrl_pkt.process_name, process_name,
@@ -731,8 +781,21 @@
 	err = diagfwd_write(peripheral, TYPE_CNTL, &ctrl_pkt, ctrl_pkt.len +
 				sizeof(ctrl_pkt.pkt_id) + sizeof(ctrl_pkt.len));
 	if (err && err != -ENODEV) {
-		pr_err("diag: Unable to send diag id  ctrl packet to peripheral %d, err: %d\n",
+		pr_err("diag: Unable to send diag id ctrl packet to peripheral %d, err: %d\n",
 		       peripheral, err);
+	} else {
+	/*
+	 * Masks (F3, logs and events) will be sent to
+	 * peripheral immediately following feature mask update only
+	 * if diag_id support is not present or
+	 * diag_id support is present and diag_id has been sent to
+	 * peripheral.
+	 * With diag_id being sent now, mask will be updated
+	 * to peripherals.
+	 */
+		driver->diag_id_sent[peripheral] = 1;
+		diag_send_updates_peripheral(peripheral);
+		diagfwd_buffers_init(fwd_info_data);
 	}
 }
 
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 7823040..8b22d7e 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -68,6 +68,7 @@
 #define F_DIAG_SOCKETS_ENABLED			13
 #define F_DIAG_DCI_EXTENDED_HEADER_SUPPORT	14
 #define F_DIAG_DIAGID_SUPPORT	15
+#define F_DIAG_PKT_HEADER_UNTAG			16
 
 #define ENABLE_SEPARATE_CMDRSP	1
 #define DISABLE_SEPARATE_CMDRSP	0
@@ -82,6 +83,9 @@
 #define ENABLE_APPS_HDLC_ENCODING	1
 #define DISABLE_APPS_HDLC_ENCODING	0
 
+#define ENABLE_PKT_HEADER_UNTAGGING		1
+#define DISABLE_PKT_HEADER_UNTAGGING	0
+
 #define DIAG_MODE_PKT_LEN	36
 
 struct diag_ctrl_pkt_header_t {
@@ -279,6 +283,7 @@
 void diag_cntl_process_read_data(struct diagfwd_info *p_info, void *buf,
 				 int len);
 int diag_send_real_time_update(uint8_t peripheral, int real_time);
+void diag_map_pd_to_diagid(uint8_t pd, uint8_t *diag_id, int *peripheral);
 int diag_send_peripheral_buffering_mode(struct diag_buffering_mode_t *params);
 void diag_update_proc_vote(uint16_t proc, uint8_t vote, int index);
 void diag_update_real_time_vote(uint16_t proc, uint8_t real_time, int index);
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 3b8203f..955d81f 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -45,6 +45,8 @@
 static void diagfwd_cntl_close(struct diagfwd_info *fwd_info);
 static void diagfwd_dci_open(struct diagfwd_info *fwd_info);
 static void diagfwd_dci_close(struct diagfwd_info *fwd_info);
+static void diagfwd_data_read_untag_done(struct diagfwd_info *fwd_info,
+				   unsigned char *buf, int len);
 static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
 				   unsigned char *buf, int len);
 static void diagfwd_cntl_read_done(struct diagfwd_info *fwd_info,
@@ -58,7 +60,7 @@
 static struct diag_channel_ops data_ch_ops = {
 	.open = NULL,
 	.close = NULL,
-	.read_done = diagfwd_data_read_done
+	.read_done = diagfwd_data_read_untag_done
 };
 
 static struct diag_channel_ops cntl_ch_ops = {
@@ -213,6 +215,317 @@
 	return buf->len;
 }
 
+int diag_md_get_peripheral(int ctxt)
+{
+	int pd = 0, i = 0;
+	int type = 0, peripheral = -EINVAL;
+	struct diagfwd_info *fwd_info = NULL;
+
+	peripheral = GET_BUF_PERIPHERAL(ctxt);
+	if (peripheral < 0 || peripheral > NUM_PERIPHERALS)
+		return -EINVAL;
+
+	if (peripheral == APPS_DATA)
+		return peripheral;
+
+	type = GET_BUF_TYPE(ctxt);
+	if (type < 0 || type >= NUM_TYPES)
+		return -EINVAL;
+
+	fwd_info = &peripheral_info[type][peripheral];
+	if (!fwd_info)
+		return -EINVAL;
+
+	pd = GET_PD_CTXT(ctxt);
+
+	if (driver->num_pd_session) {
+		if (pd == fwd_info->diagid_root) {
+			if (peripheral > NUM_PERIPHERALS)
+				peripheral = -EINVAL;
+		} else {
+			for (i = 0; i <= (fwd_info->num_pd - 2); i++) {
+				if (pd == fwd_info->diagid_user[i]) {
+					switch (peripheral) {
+					case PERIPHERAL_MODEM:
+					if (driver->pd_logging_mode[0])
+						peripheral = UPD_WLAN;
+					break;
+					default:
+						peripheral = -EINVAL;
+						break;
+					}
+				}
+			}
+		}
+	}
+	return peripheral;
+}
+
+static void diagfwd_data_process_done(struct diagfwd_info *fwd_info,
+				   struct diagfwd_buf_t *buf, int len)
+{
+	int err = 0;
+	int write_len = 0, peripheral = 0;
+	unsigned char *write_buf = NULL;
+	struct diag_md_session_t *session_info = NULL;
+	uint8_t hdlc_disabled = 0;
+
+	if (!fwd_info || !buf || len <= 0) {
+		diag_ws_release();
+		return;
+	}
+
+	switch (fwd_info->type) {
+	case TYPE_DATA:
+	case TYPE_CMD:
+		break;
+	default:
+		pr_err_ratelimited("diag: In %s, invalid type %d for peripheral %d\n",
+			__func__, fwd_info->type,
+			fwd_info->peripheral);
+		diag_ws_release();
+		return;
+	}
+
+	mutex_lock(&driver->hdlc_disable_mutex);
+	mutex_lock(&fwd_info->data_mutex);
+
+	peripheral =
+		diag_md_get_peripheral(buf->ctxt);
+	if (peripheral < 0) {
+		pr_err("diag:%s:%d invalid peripheral = %d\n",
+			__func__, __LINE__, peripheral);
+		mutex_unlock(&fwd_info->data_mutex);
+		mutex_unlock(&driver->hdlc_disable_mutex);
+		diag_ws_release();
+		return;
+	}
+
+	session_info =
+		diag_md_session_get_peripheral(peripheral);
+	if (session_info)
+		hdlc_disabled = session_info->hdlc_disabled;
+	else
+		hdlc_disabled = driver->hdlc_disabled;
+
+	if (hdlc_disabled) {
+		/* The data is raw and and on APPS side HDLC is disabled */
+		if (!buf) {
+			pr_err("diag: In %s, no match for non encode buffer %pK, peripheral %d, type: %d\n",
+			       __func__, buf, fwd_info->peripheral,
+			       fwd_info->type);
+			goto end;
+		}
+		if (len > PERIPHERAL_BUF_SZ) {
+			pr_err("diag: In %s, Incoming buffer too large %d, peripheral %d, type: %d\n",
+			       __func__, len, fwd_info->peripheral,
+			       fwd_info->type);
+			goto end;
+		}
+		write_len = len;
+		if (write_len <= 0)
+			goto end;
+		write_buf = buf->data_raw;
+	} else {
+		if (!buf) {
+			pr_err("diag: In %s, no match for non encode buffer %pK, peripheral %d, type: %d\n",
+				__func__, buf, fwd_info->peripheral,
+				fwd_info->type);
+			goto end;
+		}
+
+		write_len = check_bufsize_for_encoding(buf, len);
+		if (write_len <= 0) {
+			pr_err("diag: error in checking buf for encoding\n");
+			goto end;
+		}
+		write_buf = buf->data;
+		err = diag_add_hdlc_encoding(write_buf, &write_len,
+			buf->data_raw, len);
+		if (err) {
+			pr_err("diag: error in adding hdlc encoding\n");
+			goto end;
+		}
+	}
+
+	if (write_len > 0) {
+		err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len,
+				     buf->ctxt);
+		if (err) {
+			pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n",
+					   __func__, err);
+			goto end;
+		}
+	}
+	mutex_unlock(&fwd_info->data_mutex);
+	mutex_unlock(&driver->hdlc_disable_mutex);
+	diagfwd_queue_read(fwd_info);
+	return;
+
+end:
+	diag_ws_release();
+	mutex_unlock(&fwd_info->data_mutex);
+	mutex_unlock(&driver->hdlc_disable_mutex);
+	if (buf) {
+		diagfwd_write_done(fwd_info->peripheral, fwd_info->type,
+				   GET_BUF_NUM(buf->ctxt));
+	}
+	diagfwd_queue_read(fwd_info);
+}
+
+static void diagfwd_data_read_untag_done(struct diagfwd_info *fwd_info,
+				   unsigned char *buf, int len)
+{
+	int i = 0;
+	int len_cpd = 0;
+	int ctxt_cpd = 0;
+	int len_upd[MAX_PERIPHERAL_UPD] = {0};
+	int ctxt_upd[MAX_PERIPHERAL_UPD] = {0};
+	int packet_len = 0, processed = 0;
+	unsigned char *temp_buf_main = NULL;
+	unsigned char *temp_buf_cpd = NULL;
+	unsigned char *temp_buf_upd[MAX_PERIPHERAL_UPD] = {NULL};
+	struct diagfwd_buf_t *temp_fwdinfo_cpd = NULL;
+	struct diagfwd_buf_t *temp_fwdinfo_upd = NULL;
+	int flag_buf_1 = 0, flag_buf_2 = 0;
+	uint8_t peripheral;
+
+	if (!fwd_info || !buf || len <= 0) {
+		diag_ws_release();
+		return;
+	}
+
+	switch (fwd_info->type) {
+	case TYPE_DATA:
+	case TYPE_CMD:
+		break;
+	default:
+		pr_err_ratelimited("diag: In %s, invalid type %d for peripheral %d\n",
+				   __func__, fwd_info->type,
+				   fwd_info->peripheral);
+		diag_ws_release();
+		return;
+	}
+	peripheral = fwd_info->peripheral;
+	if (peripheral >= NUM_PERIPHERALS)
+		return;
+
+	if (driver->feature[peripheral].encode_hdlc &&
+		driver->feature[peripheral].untag_header &&
+		driver->peripheral_untag[peripheral]) {
+		temp_buf_cpd = buf;
+		temp_buf_main = buf;
+		if (fwd_info->buf_1 &&
+			fwd_info->buf_1->data_raw == buf) {
+			flag_buf_1 = 1;
+			temp_fwdinfo_cpd = fwd_info->buf_1;
+			if (fwd_info->type == TYPE_DATA) {
+				for (i = 0; i <= (fwd_info->num_pd - 2); i++)
+					temp_buf_upd[i] =
+					fwd_info->buf_upd[i][0]->data_raw;
+			}
+		} else if (fwd_info->buf_2 &&
+					fwd_info->buf_2->data_raw == buf) {
+			flag_buf_2 = 1;
+			temp_fwdinfo_cpd = fwd_info->buf_2;
+			if (fwd_info->type == TYPE_DATA) {
+				for (i = 0; i <= (fwd_info->num_pd - 2); i++)
+					temp_buf_upd[i] =
+					fwd_info->buf_upd[i][1]->data_raw;
+			}
+		} else {
+			pr_err("diag: In %s, no match for buffer %pK, peripheral %d, type: %d\n",
+			       __func__, buf, peripheral,
+			       fwd_info->type);
+			goto end;
+		}
+
+		while (processed < len) {
+			pr_debug("diag_fr:untagged packet buf contents: %02x %02x %02x %02x\n",
+			 *temp_buf_main, *(temp_buf_main+1),
+			 *(temp_buf_main+2), *(temp_buf_main+3));
+			packet_len =
+				*(uint16_t *) (temp_buf_main + 2);
+			if (packet_len > PERIPHERAL_BUF_SZ)
+				goto end;
+			if ((*temp_buf_main) == fwd_info->diagid_root) {
+				ctxt_cpd = fwd_info->diagid_root;
+				len_cpd += packet_len;
+				if (temp_buf_cpd) {
+					memcpy(temp_buf_cpd,
+					(temp_buf_main + 4), packet_len);
+					temp_buf_cpd += packet_len;
+				}
+			} else {
+				for (i = 0; i <= (fwd_info->num_pd - 2); i++)
+					if ((*temp_buf_main) ==
+						fwd_info->diagid_user[i])
+						break;
+				ctxt_upd[i] = fwd_info->diagid_user[i];
+				if (temp_buf_upd[i]) {
+					memcpy(temp_buf_upd[i],
+					(temp_buf_main + 4), packet_len);
+					temp_buf_upd[i] += packet_len;
+				}
+				len_upd[i] += packet_len;
+			}
+			len = len - 4;
+			temp_buf_main += (packet_len + 4);
+			processed += packet_len;
+		}
+		for (i = 0; i <= (fwd_info->num_pd - 2); i++) {
+			if (fwd_info->type == TYPE_DATA && len_upd[i]) {
+				if (flag_buf_1) {
+					fwd_info->upd_len[i][0] = len_upd[i];
+					temp_fwdinfo_upd =
+						fwd_info->buf_upd[i][0];
+				} else {
+					fwd_info->upd_len[i][1] = len_upd[i];
+					temp_fwdinfo_upd =
+						fwd_info->buf_upd[i][1];
+				}
+				temp_fwdinfo_upd->ctxt &= 0x00FFFFFF;
+				temp_fwdinfo_upd->ctxt |=
+					(SET_PD_CTXT(ctxt_upd[i]));
+				atomic_set(&temp_fwdinfo_upd->in_busy, 1);
+				diagfwd_data_process_done(fwd_info,
+					temp_fwdinfo_upd, len_upd[i]);
+			} else {
+				if (flag_buf_1)
+					fwd_info->upd_len[i][0] = 0;
+				if (flag_buf_2)
+					fwd_info->upd_len[i][1] = 0;
+			}
+		}
+		if (len_cpd) {
+			if (flag_buf_1)
+				fwd_info->cpd_len_1 = len_cpd;
+			else
+				fwd_info->cpd_len_2 = len_cpd;
+			temp_fwdinfo_cpd->ctxt &= 0x00FFFFFF;
+			temp_fwdinfo_cpd->ctxt |=
+				(SET_PD_CTXT(ctxt_cpd));
+			diagfwd_data_process_done(fwd_info,
+				temp_fwdinfo_cpd, len_cpd);
+		} else {
+			if (flag_buf_1)
+				fwd_info->cpd_len_1 = 0;
+			if (flag_buf_2)
+				fwd_info->cpd_len_2 = 0;
+		}
+	} else {
+		diagfwd_data_read_done(fwd_info, buf, len);
+	}
+	return;
+end:
+	diag_ws_release();
+	if (temp_fwdinfo_cpd) {
+		diagfwd_write_done(fwd_info->peripheral, fwd_info->type,
+				   GET_BUF_NUM(temp_fwdinfo_cpd->ctxt));
+	}
+	diagfwd_queue_read(fwd_info);
+}
+
 static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
 				   unsigned char *buf, int len)
 {
@@ -413,6 +726,7 @@
 	uint8_t peripheral;
 	uint8_t transport;
 	uint8_t type;
+	int i = 0;
 	struct diagfwd_info *fwd_info = NULL;
 
 	for (transport = 0; transport < NUM_TRANSPORT; transport++) {
@@ -436,9 +750,20 @@
 			fwd_info->inited = 1;
 			fwd_info->read_bytes = 0;
 			fwd_info->write_bytes = 0;
+			fwd_info->cpd_len_1 = 0;
+			fwd_info->cpd_len_2 = 0;
+			fwd_info->num_pd = 0;
 			mutex_init(&fwd_info->buf_mutex);
 			mutex_init(&fwd_info->data_mutex);
 			spin_lock_init(&fwd_info->write_buf_lock);
+
+			for (i = 0; i < MAX_PERIPHERAL_UPD; i++) {
+				fwd_info->diagid_user[i] = 0;
+				fwd_info->upd_len[i][0] = 0;
+				fwd_info->upd_len[i][1] = 0;
+				fwd_info->buf_upd[i][0] = NULL;
+				fwd_info->buf_upd[i][1] = NULL;
+			}
 		}
 	}
 
@@ -452,9 +777,20 @@
 			fwd_info->ch_open = 0;
 			fwd_info->read_bytes = 0;
 			fwd_info->write_bytes = 0;
+			fwd_info->num_pd = 0;
+			fwd_info->cpd_len_1 = 0;
+			fwd_info->cpd_len_2 = 0;
 			spin_lock_init(&fwd_info->write_buf_lock);
 			mutex_init(&fwd_info->buf_mutex);
 			mutex_init(&fwd_info->data_mutex);
+
+			for (i = 0; i < MAX_PERIPHERAL_UPD; i++) {
+				fwd_info->diagid_user[i] = 0;
+				fwd_info->upd_len[i][0] = 0;
+				fwd_info->upd_len[i][1] = 0;
+				fwd_info->buf_upd[i][0] = NULL;
+				fwd_info->buf_upd[i][1] = NULL;
+			}
 			/*
 			 * This state shouldn't be set for Control channels
 			 * during initialization. This is set when the feature
@@ -730,6 +1066,16 @@
 	if (!fwd_info->inited || !atomic_read(&fwd_info->opened))
 		return -ENODEV;
 
+	if (type == TYPE_CMD) {
+		if (driver->feature[peripheral].untag_header)
+			if (!fwd_info->diagid_root ||
+				(!driver->diag_id_sent[peripheral])) {
+			DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+				 "diag: diag_id is not assigned yet\n");
+			return 0;
+		}
+	}
+
 	if (!(fwd_info->p_ops && fwd_info->p_ops->write && fwd_info->ctxt))
 		return -EIO;
 
@@ -897,6 +1243,9 @@
 	if (!fwd_info)
 		return -EIO;
 
+	if (fwd_info->type == TYPE_CNTL)
+		flush_workqueue(driver->cntl_wq);
+
 	mutex_lock(&driver->diagfwd_channel_mutex[fwd_info->peripheral]);
 	fwd_info->ch_open = 0;
 	if (fwd_info && fwd_info->c_ops && fwd_info->c_ops->close)
@@ -945,17 +1294,45 @@
 
 void diagfwd_write_done(uint8_t peripheral, uint8_t type, int ctxt)
 {
+	int i = 0;
 	struct diagfwd_info *fwd_info = NULL;
 
 	if (peripheral >= NUM_PERIPHERALS || type >= NUM_TYPES)
 		return;
 
 	fwd_info = &peripheral_info[type][peripheral];
-	if (ctxt == 1 && fwd_info->buf_1)
+	if (!fwd_info)
+		return;
+
+	if (ctxt == 1 && fwd_info->buf_1) {
+		/* Buffer 1 for core PD is freed */
 		atomic_set(&fwd_info->buf_1->in_busy, 0);
-	else if (ctxt == 2 && fwd_info->buf_2)
+		fwd_info->cpd_len_1 = 0;
+	} else if (ctxt == 2 && fwd_info->buf_2) {
+		/* Buffer 2 for core PD is freed */
 		atomic_set(&fwd_info->buf_2->in_busy, 0);
-	else
+		fwd_info->cpd_len_2 = 0;
+	} else if (ctxt >= 3 && (ctxt % 2)) {
+		for (i = 0; i <= (fwd_info->num_pd - 2); i++) {
+			if (fwd_info->buf_upd[i][0]) {
+				/* Buffer 1 for ith user PD is freed */
+			atomic_set(&fwd_info->buf_upd[i][0]->in_busy, 0);
+			fwd_info->upd_len[i][0] = 0;
+			}
+		if (!fwd_info->cpd_len_1)
+			atomic_set(&fwd_info->buf_1->in_busy, 0);
+		}
+	} else if (ctxt >= 4 && !(ctxt % 2)) {
+		for (i = 0; i <= (fwd_info->num_pd - 2); i++) {
+			if (fwd_info->buf_upd[i][1]) {
+				/* Buffer 2 for ith user PD is freed */
+			atomic_set(&fwd_info->buf_upd[i][0]->in_busy, 0);
+			fwd_info->upd_len[i][1] = 0;
+			}
+		if (!fwd_info->cpd_len_2)
+			atomic_set(&fwd_info->buf_2->in_busy, 0);
+		}
+	} else
 		pr_err("diag: In %s, invalid ctxt %d\n", __func__, ctxt);
 
 	diagfwd_queue_read(fwd_info);
@@ -1084,8 +1461,65 @@
 		fwd_info->p_ops->queue_read(fwd_info->ctxt);
 }
 
+static int diagfwd_buffers_allocate(struct diagfwd_info *fwd_info)
+{
+	int i, j;
+
+	for (i = 0; ((fwd_info->num_pd > 1) &&
+		(i <= (fwd_info->num_pd - 2))); i++) {
+		for (j = 0; j < NUM_WRITE_BUFFERS; j++) {
+			if (!fwd_info->buf_upd[i][j]) {
+				fwd_info->buf_upd[i][j] =
+					kzalloc(sizeof(struct diagfwd_buf_t),
+						  GFP_KERNEL);
+				if (ZERO_OR_NULL_PTR(fwd_info->buf_upd[i][j]))
+					return -ENOMEM;
+				kmemleak_not_leak(fwd_info->buf_upd[i][j]);
+			}
+
+			if (fwd_info->buf_upd[i][j] &&
+				!fwd_info->buf_upd[i][j]->data) {
+				fwd_info->buf_upd[i][j]->data =
+					kzalloc(PERIPHERAL_BUF_SZ +
+						APF_DIAG_PADDING,
+						GFP_KERNEL);
+				if (ZERO_OR_NULL_PTR(
+					fwd_info->buf_upd[i][j]->data))
+					return -ENOMEM;
+				fwd_info->buf_upd[i][j]->len =
+					PERIPHERAL_BUF_SZ;
+				kmemleak_not_leak(
+					fwd_info->buf_upd[i][j]->data);
+				fwd_info->buf_upd[i][j]->ctxt =
+					SET_BUF_CTXT(fwd_info->peripheral,
+					fwd_info->type, ((2 * i) + (j + 3)));
+			}
+
+			if (driver->supports_apps_hdlc_encoding) {
+				if (fwd_info->buf_upd[i][j] &&
+					!fwd_info->buf_upd[i][j]->data_raw) {
+					fwd_info->buf_upd[i][j]->data_raw =
+						kzalloc(PERIPHERAL_BUF_SZ +
+							APF_DIAG_PADDING,
+							GFP_KERNEL);
+					if (ZERO_OR_NULL_PTR(
+					fwd_info->buf_upd[i][j]->data_raw))
+						return -ENOMEM;
+					fwd_info->buf_upd[i][j]->len_raw =
+						PERIPHERAL_BUF_SZ;
+					kmemleak_not_leak(
+					fwd_info->buf_upd[i][j]->data_raw);
+				}
+			}
+		}
+	}
+	return 0;
+}
+
 void diagfwd_buffers_init(struct diagfwd_info *fwd_info)
 {
+	int ret = 0;
+	unsigned char *temp_char_buf;
 
 	if (!fwd_info)
 		return;
@@ -1097,18 +1531,20 @@
 	}
 
 	mutex_lock(&fwd_info->buf_mutex);
+
 	if (!fwd_info->buf_1) {
 		fwd_info->buf_1 = kzalloc(sizeof(struct diagfwd_buf_t),
 					  GFP_KERNEL);
-		if (!fwd_info->buf_1)
+		if (ZERO_OR_NULL_PTR(fwd_info->buf_1))
 			goto err;
 		kmemleak_not_leak(fwd_info->buf_1);
 	}
+
 	if (!fwd_info->buf_1->data) {
 		fwd_info->buf_1->data = kzalloc(PERIPHERAL_BUF_SZ +
 					APF_DIAG_PADDING,
 					GFP_KERNEL);
-		if (!fwd_info->buf_1->data)
+		if (ZERO_OR_NULL_PTR(fwd_info->buf_1->data))
 			goto err;
 		fwd_info->buf_1->len = PERIPHERAL_BUF_SZ;
 		kmemleak_not_leak(fwd_info->buf_1->data);
@@ -1120,7 +1556,7 @@
 		if (!fwd_info->buf_2) {
 			fwd_info->buf_2 = kzalloc(sizeof(struct diagfwd_buf_t),
 					      GFP_KERNEL);
-			if (!fwd_info->buf_2)
+			if (ZERO_OR_NULL_PTR(fwd_info->buf_2))
 				goto err;
 			kmemleak_not_leak(fwd_info->buf_2);
 		}
@@ -1129,7 +1565,7 @@
 			fwd_info->buf_2->data = kzalloc(PERIPHERAL_BUF_SZ +
 							APF_DIAG_PADDING,
 						    GFP_KERNEL);
-			if (!fwd_info->buf_2->data)
+			if (ZERO_OR_NULL_PTR(fwd_info->buf_2->data))
 				goto err;
 			fwd_info->buf_2->len = PERIPHERAL_BUF_SZ;
 			kmemleak_not_leak(fwd_info->buf_2->data);
@@ -1138,6 +1574,11 @@
 							fwd_info->type, 2);
 		}
 
+		if (driver->feature[fwd_info->peripheral].untag_header)
+			ret = diagfwd_buffers_allocate(fwd_info);
+			if (ret)
+				goto err;
+
 		if (driver->supports_apps_hdlc_encoding) {
 			/* In support of hdlc encoding */
 			if (!fwd_info->buf_1->data_raw) {
@@ -1145,34 +1586,44 @@
 					kzalloc(PERIPHERAL_BUF_SZ +
 						APF_DIAG_PADDING,
 						GFP_KERNEL);
-				if (!fwd_info->buf_1->data_raw)
+				temp_char_buf =
+					fwd_info->buf_1->data_raw;
+				if (ZERO_OR_NULL_PTR(temp_char_buf))
 					goto err;
-				fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ;
-				kmemleak_not_leak(fwd_info->buf_1->data_raw);
+				fwd_info->buf_1->len_raw =
+					PERIPHERAL_BUF_SZ;
+				kmemleak_not_leak(temp_char_buf);
 			}
+
 			if (!fwd_info->buf_2->data_raw) {
 				fwd_info->buf_2->data_raw =
 					kzalloc(PERIPHERAL_BUF_SZ +
 						APF_DIAG_PADDING,
 						GFP_KERNEL);
-				if (!fwd_info->buf_2->data_raw)
+				temp_char_buf =
+					fwd_info->buf_2->data_raw;
+				if (ZERO_OR_NULL_PTR(temp_char_buf))
 					goto err;
-				fwd_info->buf_2->len_raw = PERIPHERAL_BUF_SZ;
-				kmemleak_not_leak(fwd_info->buf_2->data_raw);
+				fwd_info->buf_2->len_raw =
+					PERIPHERAL_BUF_SZ;
+				kmemleak_not_leak(temp_char_buf);
 			}
 		}
 	}
 
-	if (fwd_info->type == TYPE_CMD && driver->supports_apps_hdlc_encoding) {
+	if (fwd_info->type == TYPE_CMD &&
+		driver->supports_apps_hdlc_encoding) {
 		/* In support of hdlc encoding */
 		if (!fwd_info->buf_1->data_raw) {
 			fwd_info->buf_1->data_raw = kzalloc(PERIPHERAL_BUF_SZ +
 						APF_DIAG_PADDING,
 							GFP_KERNEL);
-			if (!fwd_info->buf_1->data_raw)
+			temp_char_buf =
+				fwd_info->buf_1->data_raw;
+			if (ZERO_OR_NULL_PTR(temp_char_buf))
 				goto err;
 			fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ;
-			kmemleak_not_leak(fwd_info->buf_1->data_raw);
+			kmemleak_not_leak(temp_char_buf);
 		}
 	}
 
@@ -1182,10 +1633,12 @@
 err:
 	mutex_unlock(&fwd_info->buf_mutex);
 	diagfwd_buffers_exit(fwd_info);
+	return;
 }
 
 static void diagfwd_buffers_exit(struct diagfwd_info *fwd_info)
 {
+	int i = 0;
 
 	if (!fwd_info)
 		return;
@@ -1207,6 +1660,24 @@
 		kfree(fwd_info->buf_2);
 		fwd_info->buf_2 = NULL;
 	}
+	for (i = 0; i <= (fwd_info->num_pd - 2); i++) {
+		if (fwd_info->buf_upd[i][0]) {
+			kfree(fwd_info->buf_upd[i][0]->data);
+			fwd_info->buf_upd[i][0]->data = NULL;
+			kfree(fwd_info->buf_upd[i][0]->data_raw);
+			fwd_info->buf_upd[i][0]->data_raw = NULL;
+			kfree(fwd_info->buf_upd[i][0]);
+			fwd_info->buf_upd[i][0] = NULL;
+		}
+		if (fwd_info->buf_upd[i][1]) {
+			kfree(fwd_info->buf_upd[i][1]->data);
+			fwd_info->buf_upd[i][1]->data = NULL;
+			kfree(fwd_info->buf_upd[i][1]->data_raw);
+			fwd_info->buf_upd[i][1]->data_raw = NULL;
+			kfree(fwd_info->buf_upd[i][1]);
+			fwd_info->buf_upd[i][1] = NULL;
+		}
+	}
 	mutex_unlock(&fwd_info->buf_mutex);
 }
 
diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h
index 5884a12..b16670e 100644
--- a/drivers/char/diag/diagfwd_peripheral.h
+++ b/drivers/char/diag/diagfwd_peripheral.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -68,6 +68,12 @@
 	uint8_t transport;
 	uint8_t inited;
 	uint8_t ch_open;
+	uint8_t num_pd;
+	uint8_t diagid_root;
+	uint8_t diagid_user[MAX_PERIPHERAL_UPD];
+	int cpd_len_1;
+	int cpd_len_2;
+	int upd_len[MAX_PERIPHERAL_UPD][2];
 	atomic_t opened;
 	unsigned long read_bytes;
 	unsigned long write_bytes;
@@ -77,6 +83,7 @@
 	void *ctxt;
 	struct diagfwd_buf_t *buf_1;
 	struct diagfwd_buf_t *buf_2;
+	struct diagfwd_buf_t *buf_upd[MAX_PERIPHERAL_UPD][2];
 	struct diagfwd_buf_t *buf_ptr[NUM_WRITE_BUFFERS];
 	struct diag_peripheral_ops *p_ops;
 	struct diag_channel_ops *c_ops;
@@ -94,6 +101,9 @@
 
 void diagfwd_late_open(struct diagfwd_info *fwd_info);
 void diagfwd_close(uint8_t peripheral, uint8_t type);
+
+int diag_md_get_peripheral(int ctxt);
+
 int diagfwd_register(uint8_t transport, uint8_t peripheral, uint8_t type,
 		     void *ctxt, struct diag_peripheral_ops *ops,
 		     struct diagfwd_info **fwd_ctxt);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index fcdd886..172a9dc 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3877,6 +3877,9 @@
 	 * because the lower layer is allowed to hold locks while calling
 	 * message delivery.
 	 */
+
+	rcu_read_lock();
+
 	if (!run_to_completion)
 		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
 	if (intf->curr_msg == NULL && !intf->in_shutdown) {
@@ -3899,6 +3902,8 @@
 	if (newmsg)
 		intf->handlers->sender(intf->send_info, newmsg);
 
+	rcu_read_unlock();
+
 	handle_new_recv_msgs(intf);
 }
 
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 6958b5c..510fc10 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -762,6 +762,11 @@
 			       result, len, data[2]);
 		} else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
 			   || data[1] != IPMI_GET_MSG_FLAGS_CMD) {
+			/*
+			 * Don't abort here, maybe it was a queued
+			 * response to a previous command.
+			 */
+			ipmi_ssif_unlock_cond(ssif_info, flags);
 			pr_warn(PFX "Invalid response getting flags: %x %x\n",
 				data[0], data[1]);
 		} else {
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 08d1dd5..ee737ef 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -2044,8 +2044,8 @@
 
 struct batched_entropy {
 	union {
-		unsigned long entropy_long[CHACHA20_BLOCK_SIZE / sizeof(unsigned long)];
-		unsigned int entropy_int[CHACHA20_BLOCK_SIZE / sizeof(unsigned int)];
+		u64 entropy_u64[CHACHA20_BLOCK_SIZE / sizeof(u64)];
+		u32 entropy_u32[CHACHA20_BLOCK_SIZE / sizeof(u32)];
 	};
 	unsigned int position;
 };
@@ -2055,52 +2055,51 @@
  * number is either as good as RDRAND or as good as /dev/urandom, with the
  * goal of being quite fast and not depleting entropy.
  */
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_long);
-unsigned long get_random_long(void)
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
+u64 get_random_u64(void)
 {
-	unsigned long ret;
+	u64 ret;
 	struct batched_entropy *batch;
 
-	if (arch_get_random_long(&ret))
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
 		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+	    return ret;
+#endif
 
-	batch = &get_cpu_var(batched_entropy_long);
-	if (batch->position % ARRAY_SIZE(batch->entropy_long) == 0) {
-		extract_crng((u8 *)batch->entropy_long);
+	batch = &get_cpu_var(batched_entropy_u64);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		extract_crng((u8 *)batch->entropy_u64);
 		batch->position = 0;
 	}
-	ret = batch->entropy_long[batch->position++];
-	put_cpu_var(batched_entropy_long);
+	ret = batch->entropy_u64[batch->position++];
+	put_cpu_var(batched_entropy_u64);
 	return ret;
 }
-EXPORT_SYMBOL(get_random_long);
+EXPORT_SYMBOL(get_random_u64);
 
-#if BITS_PER_LONG == 32
-unsigned int get_random_int(void)
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
+u32 get_random_u32(void)
 {
-	return get_random_long();
-}
-#else
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_int);
-unsigned int get_random_int(void)
-{
-	unsigned int ret;
+	u32 ret;
 	struct batched_entropy *batch;
 
 	if (arch_get_random_int(&ret))
 		return ret;
 
-	batch = &get_cpu_var(batched_entropy_int);
-	if (batch->position % ARRAY_SIZE(batch->entropy_int) == 0) {
-		extract_crng((u8 *)batch->entropy_int);
+	batch = &get_cpu_var(batched_entropy_u32);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		extract_crng((u8 *)batch->entropy_u32);
 		batch->position = 0;
 	}
-	ret = batch->entropy_int[batch->position++];
-	put_cpu_var(batched_entropy_int);
+	ret = batch->entropy_u32[batch->position++];
+	put_cpu_var(batched_entropy_u32);
 	return ret;
 }
-#endif
-EXPORT_SYMBOL(get_random_int);
+EXPORT_SYMBOL(get_random_u32);
 
 /**
  * randomize_page - Generate a random, page aligned address
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 7cdf45b..5638333 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2631,7 +2631,46 @@
 		pr_info(fmt, ##__VA_ARGS__);		\
 } while (0)
 
-int clock_debug_print_clock(struct clk_core *c, struct seq_file *s)
+/*
+ * clock_debug_print_enabled_debug_suspend() - Print names of enabled clocks
+ * during suspend.
+ */
+static void clock_debug_print_enabled_debug_suspend(struct seq_file *s)
+{
+	struct clk_core *core;
+	int cnt = 0;
+
+	if (!mutex_trylock(&clk_debug_lock))
+		return;
+
+	clock_debug_output(s, 0, "Enabled clocks:\n");
+
+	hlist_for_each_entry(core, &clk_debug_list, debug_node) {
+		if (!core || !core->prepare_count)
+			continue;
+
+		if (core->vdd_class)
+			clock_debug_output(s, 0, " %s:%u:%u [%ld, %d]",
+					core->name, core->prepare_count,
+					core->enable_count, core->rate,
+					clk_find_vdd_level(core, core->rate));
+
+		else
+			clock_debug_output(s, 0, " %s:%u:%u [%ld]",
+					core->name, core->prepare_count,
+					core->enable_count, core->rate);
+		cnt++;
+	}
+
+	mutex_unlock(&clk_debug_lock);
+
+	if (cnt)
+		clock_debug_output(s, 0, "Enabled clock count: %d\n", cnt);
+	else
+		clock_debug_output(s, 0, "No clocks enabled.\n");
+}
+
+static int clock_debug_print_clock(struct clk_core *c, struct seq_file *s)
 {
 	char *start = "";
 	struct clk *clk;
@@ -3005,7 +3044,7 @@
 	if (likely(!debug_suspend))
 		return;
 
-	clock_debug_print_enabled_clocks(NULL);
+	clock_debug_print_enabled_debug_suspend(NULL);
 }
 EXPORT_SYMBOL_GPL(clock_debug_print_enabled);
 
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index f0db049..b52aa25 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -10,6 +10,7 @@
  */
 
 struct clk_hw;
+struct clk_core;
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
diff --git a/drivers/clk/qcom/clk-aop-qmp.c b/drivers/clk/qcom/clk-aop-qmp.c
index f6aeb19..ff229fb 100644
--- a/drivers/clk/qcom/clk-aop-qmp.c
+++ b/drivers/clk/qcom/clk-aop-qmp.c
@@ -30,7 +30,7 @@
 	void *data;
 };
 
-#define DEFINE_CLK_AOP_QMP(_name, _class, _res, _estate, _dstate)	\
+#define DEFINE_CLK_AOP_QMP(_name, _class, _res, _estate, _dstate, _flags) \
 	static struct clk_aop_qmp _name = {				\
 		.msg.class = #_class,					\
 		.msg.res = #_res,					\
@@ -40,7 +40,7 @@
 			.ops = &aop_qmp_clk_ops,			\
 			.name = #_name,					\
 			.num_parents = 0,				\
-			.flags = CLK_ENABLE_HAND_OFF,			\
+			.flags = _flags,				\
 		},							\
 	}
 
@@ -214,13 +214,25 @@
 	.is_enabled	= clk_aop_qmp_is_enabled,
 };
 
-DEFINE_CLK_AOP_QMP(qdss_qmp_clk, clock, qdss,
-		QDSS_CLK_LEVEL_DYNAMIC, QDSS_CLK_LEVEL_OFF);
+DEFINE_CLK_AOP_QMP(qdss_qmp_clk, clock, qdss, QDSS_CLK_LEVEL_DYNAMIC,
+			QDSS_CLK_LEVEL_OFF, CLK_ENABLE_HAND_OFF);
+DEFINE_CLK_AOP_QMP(qdss_ao_qmp_clk, clock, qdss_ao, QDSS_CLK_LEVEL_DYNAMIC,
+			QDSS_CLK_LEVEL_OFF, 0);
 
 static struct clk_hw *aop_qmp_clk_hws[] = {
 	[QDSS_CLK] = &qdss_qmp_clk.hw,
+	[QDSS_AO_CLK] = &qdss_ao_qmp_clk.hw,
 };
 
+/*
+ * Due to HW limitations on v1, the qdss_ao clock was not supported by the clock
+ * driver on AOP.
+ */
+static void aop_qmp_fixup_v1(void)
+{
+	aop_qmp_clk_hws[QDSS_AO_CLK] = NULL;
+}
+
 static int qmp_update_client(struct clk_hw *hw, struct device *dev,
 		struct mbox_chan *mbox)
 {
@@ -250,7 +262,7 @@
 
 static int aop_qmp_clk_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
+	struct clk *clk = NULL;
 	struct device_node *np = pdev->dev.of_node;
 	struct mbox_chan *mbox = NULL;
 	int num_clks = ARRAY_SIZE(aop_qmp_clk_hws);
@@ -264,7 +276,12 @@
 	if (ret < 0)
 		return ret;
 
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,aop-qmp-clk-v1"))
+		aop_qmp_fixup_v1();
+
 	for (i = 1; i < num_clks; i++) {
+		if (!aop_qmp_clk_hws[i])
+			continue;
 		ret = qmp_update_client(aop_qmp_clk_hws[i], &pdev->dev, mbox);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "Failed to update QMP client %d\n",
@@ -273,13 +290,17 @@
 		}
 	}
 
-	for (i = 0; i < num_clks; i++) {
-		ret = clk_aop_qmp_prepare(aop_qmp_clk_hws[i]);
-		if (ret < 0)
-			goto fail;
-	}
+	/*
+	 * Proxy vote on the QDSS clock. This is needed to avoid issues with
+	 * excessive requests on the QMP layer during the QDSS driver probe.
+	 */
+	ret = clk_aop_qmp_prepare(&qdss_qmp_clk.hw);
+	if (ret < 0)
+		goto fail;
 
 	for (i = 0; i < num_clks; i++) {
+		if (!aop_qmp_clk_hws[i])
+			continue;
 		clk = devm_clk_register(&pdev->dev, aop_qmp_clk_hws[i]);
 		if (IS_ERR(clk)) {
 			ret = PTR_ERR(clk);
@@ -303,7 +324,8 @@
 }
 
 static const struct of_device_id aop_qmp_clk_of_match[] = {
-	{ .compatible = "qcom,aop-qmp-clk", },
+	{ .compatible = "qcom,aop-qmp-clk-v1" },
+	{ .compatible = "qcom,aop-qmp-clk-v2" },
 	{}
 };
 
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 47e9fab..f93aba1 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -45,6 +45,7 @@
 #include "clk-debug.h"
 
 #define OSM_INIT_RATE			300000000UL
+#define XO_RATE				19200000UL
 #define OSM_TABLE_SIZE			40
 #define SINGLE_CORE			1
 #define MAX_CLUSTER_CNT			3
@@ -65,6 +66,7 @@
 #define PERFCL_EFUSE_MASK		0x7
 
 #define ENABLE_REG			0x0
+#define ENABLE_OSM			BIT(0)
 #define FREQ_REG			0x110
 #define VOLT_REG			0x114
 #define OVERRIDE_REG			0x118
@@ -121,6 +123,7 @@
 #define MIN_VCO_VAL			0x2b
 
 #define MAX_VC				63
+#define MEM_ACC_LEVELS_LUT		2
 #define MAX_MEM_ACC_LEVELS		3
 #define MAX_MEM_ACC_VAL_PER_LEVEL	3
 #define MAX_MEM_ACC_VALUES		(MAX_MEM_ACC_LEVELS * \
@@ -265,6 +268,7 @@
 	u32 speedbin;
 	u32 mem_acc_crossover_vc_addr;
 	u32 mem_acc_addr[MEM_ACC_ADDRS];
+	u32 mem_acc_level_vc[MEM_ACC_LEVELS_LUT];
 	u32 ramp_ctl_addr;
 	u32 apm_mode_ctl;
 	u32 apm_status_ctl;
@@ -450,6 +454,7 @@
 }
 
 static bool is_v2;
+static bool osm_tz_enabled;
 
 static inline struct clk_osm *to_clk_osm(struct clk_hw *_hw)
 {
@@ -544,23 +549,12 @@
 
 static int clk_osm_search_table(struct osm_entry *table, int entries, long rate)
 {
-	int quad_core_index, single_core_index = 0;
-	int core_count;
+	int index = 0;
 
-	for (quad_core_index = 0; quad_core_index < entries;
-						quad_core_index++) {
-		core_count = CORE_COUNT_VAL(table[quad_core_index].freq_data);
-		if (rate == table[quad_core_index].frequency &&
-					core_count == SINGLE_CORE) {
-			single_core_index = quad_core_index;
-			continue;
-		}
-		if (rate == table[quad_core_index].frequency &&
-					core_count == MAX_CORE_COUNT)
-			return quad_core_index;
+	for (index = 0; index < entries; index++) {
+		if (rate == table[index].frequency)
+			return index;
 	}
-	if (single_core_index)
-		return single_core_index;
 
 	return -EINVAL;
 }
@@ -642,7 +636,7 @@
 }
 
 
-const struct clk_ops clk_ops_l3_osm = {
+static struct clk_ops clk_ops_l3_osm = {
 	.enable = clk_osm_enable,
 	.round_rate = clk_osm_round_rate,
 	.list_rate = clk_osm_list_rate,
@@ -1054,21 +1048,6 @@
 
 static void clk_osm_program_mem_acc_regs(struct clk_osm *c)
 {
-	int curr_level, i, j = 0;
-	int mem_acc_level_map[MAX_MEM_ACC_LEVELS] = {MAX_VC, MAX_VC, MAX_VC};
-
-	curr_level = c->osm_table[0].mem_acc_level;
-	for (i = 0; i < c->num_entries; i++) {
-		if (curr_level == MAX_MEM_ACC_LEVELS)
-			break;
-
-		if (c->osm_table[i].mem_acc_level != curr_level) {
-			mem_acc_level_map[j++] =
-				c->osm_table[i].virtual_corner;
-			curr_level = c->osm_table[i].mem_acc_level;
-		}
-	}
-
 	if (c->secure_init) {
 		clk_osm_write_seq_reg(c,
 				c->pbases[OSM_BASE] + MEMACC_CROSSOVER_VC,
@@ -1078,13 +1057,8 @@
 		clk_osm_write_seq_reg(c, c->mem_acc_addr[2], DATA_MEM(50));
 		clk_osm_write_seq_reg(c, c->mem_acc_crossover_vc,
 							DATA_MEM(78));
-		clk_osm_write_seq_reg(c, mem_acc_level_map[0], DATA_MEM(79));
-		if (c == &perfcl_clk)
-			clk_osm_write_seq_reg(c, c->mem_acc_threshold_vc,
-								DATA_MEM(80));
-		else
-			clk_osm_write_seq_reg(c, mem_acc_level_map[1],
-								DATA_MEM(80));
+		clk_osm_write_seq_reg(c, c->mem_acc_level_vc[0], DATA_MEM(79));
+		clk_osm_write_seq_reg(c, c->mem_acc_level_vc[1], DATA_MEM(80));
 		/*
 		 * Note that DATA_MEM[81] -> DATA_MEM[89] values will be
 		 * confirmed post-si. Use a value of 1 for DATA_MEM[89] and
@@ -1095,13 +1069,9 @@
 		scm_io_write(c->pbases[SEQ_BASE] + DATA_MEM(78),
 						c->mem_acc_crossover_vc);
 		scm_io_write(c->pbases[SEQ_BASE] + DATA_MEM(79),
-						mem_acc_level_map[0]);
-		if (c == &perfcl_clk)
-			scm_io_write(c->pbases[SEQ_BASE] + DATA_MEM(80),
-						c->mem_acc_threshold_vc);
-		else
-			scm_io_write(c->pbases[SEQ_BASE] + DATA_MEM(80),
-						mem_acc_level_map[1]);
+						c->mem_acc_level_vc[0]);
+		scm_io_write(c->pbases[SEQ_BASE] + DATA_MEM(80),
+						c->mem_acc_level_vc[1]);
 	}
 }
 
@@ -1678,7 +1648,8 @@
 
 	/* Program LVAL corresponding to first turbo VC */
 	for (i = 0; i < c->num_entries; i++) {
-		if (c->osm_table[i].mem_acc_level == MAX_MEM_ACC_LEVELS) {
+		if (c->osm_table[i].virtual_corner ==
+					c->mem_acc_level_vc[1]) {
 			lval = c->osm_table[i].freq_data & GENMASK(7, 0);
 			break;
 		}
@@ -1885,6 +1856,7 @@
 	u32 val;
 	int core_num;
 	unsigned long flags;
+	u64 cycle_counter_ret;
 	struct clk_osm *parent, *c = logical_cpu_to_clk(cpu);
 
 	if (IS_ERR_OR_NULL(c)) {
@@ -1912,9 +1884,10 @@
 		c->total_cycle_counter += val - c->prev_cycle_counter;
 		c->prev_cycle_counter = val;
 	}
+	cycle_counter_ret = c->total_cycle_counter;
 	spin_unlock_irqrestore(&parent->lock, flags);
 
-	return c->total_cycle_counter;
+	return cycle_counter_ret;
 }
 
 static void clk_osm_setup_cycle_counters(struct clk_osm *c)
@@ -2107,6 +2080,49 @@
 	return rc;
 }
 
+static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
+{
+	u32 data, src, lval, i, j = OSM_TABLE_SIZE;
+
+	for (i = 0; i < OSM_TABLE_SIZE; i++) {
+		data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
+		src = ((data & GENMASK(31, 30)) >> 30);
+		lval = (data & GENMASK(7, 0));
+
+		if (!src)
+			c->osm_table[i].frequency = OSM_INIT_RATE;
+		else
+			c->osm_table[i].frequency = XO_RATE * lval;
+
+		data = clk_osm_read_reg(c, VOLT_REG + i * OSM_REG_SIZE);
+		c->osm_table[i].virtual_corner =
+					((data & GENMASK(21, 16)) >> 16);
+		c->osm_table[i].open_loop_volt = (data & GENMASK(11, 0));
+
+		pr_debug("index=%d freq=%ld virtual_corner=%d open_loop_voltage=%u\n",
+			 i, c->osm_table[i].frequency,
+			 c->osm_table[i].virtual_corner,
+			 c->osm_table[i].open_loop_volt);
+
+		if (i > 0 && j == OSM_TABLE_SIZE && c->osm_table[i].frequency ==
+					c->osm_table[i - 1].frequency)
+			j = i;
+	}
+
+	osm_clks_init[c->cluster_num].rate_max = devm_kcalloc(&pdev->dev,
+						 j, sizeof(unsigned long),
+						       GFP_KERNEL);
+	if (!osm_clks_init[c->cluster_num].rate_max)
+		return -ENOMEM;
+
+	for (i = 0; i < j; i++)
+		osm_clks_init[c->cluster_num].rate_max[i] =
+					c->osm_table[i].frequency;
+
+	c->num_entries = osm_clks_init[c->cluster_num].num_rate_max = j;
+	return 0;
+}
+
 static int clk_osm_parse_acd_dt_configs(struct platform_device *pdev)
 {
 	struct device_node *of = pdev->dev.of_node;
@@ -2254,6 +2270,7 @@
 {
 	struct device_node *of = pdev->dev.of_node;
 	u32 *array;
+	char memacc_str[40];
 	int rc = 0;
 	struct resource *res;
 
@@ -2473,6 +2490,36 @@
 		return -ENOMEM;
 	}
 
+	snprintf(memacc_str, ARRAY_SIZE(memacc_str),
+			"qcom,l3-memacc-level-vc-bin%d", l3_clk.speedbin);
+	rc = of_property_read_u32_array(of, memacc_str, l3_clk.mem_acc_level_vc,
+			MEM_ACC_LEVELS_LUT);
+	if (rc) {
+		dev_err(&pdev->dev, "unable to find %s property, rc=%d\n",
+						memacc_str, rc);
+		return rc;
+	}
+
+	snprintf(memacc_str, ARRAY_SIZE(memacc_str),
+			"qcom,pwrcl-memacc-level-vc-bin%d", pwrcl_clk.speedbin);
+	rc = of_property_read_u32_array(of, memacc_str,
+			pwrcl_clk.mem_acc_level_vc, MEM_ACC_LEVELS_LUT);
+	if (rc) {
+		dev_err(&pdev->dev, "unable to find %s property, rc=%d\n",
+			memacc_str, rc);
+		return rc;
+	}
+
+	snprintf(memacc_str, ARRAY_SIZE(memacc_str),
+		"qcom,perfcl-memacc-level-vc-bin%d", pwrcl_clk.speedbin);
+	rc = of_property_read_u32_array(of, memacc_str,
+			perfcl_clk.mem_acc_level_vc, MEM_ACC_LEVELS_LUT);
+	if (rc) {
+		dev_err(&pdev->dev, "unable to find %s property, rc=%d\n",
+			memacc_str, rc);
+		return rc;
+	}
+
 	l3_clk.secure_init = perfcl_clk.secure_init = pwrcl_clk.secure_init =
 		of_property_read_bool(pdev->dev.of_node, "qcom,osm-no-tz");
 
@@ -2582,6 +2629,12 @@
 		return -ENOMEM;
 	}
 
+	/* Check if OSM has been enabled already by trustzone.  */
+	if (readl_relaxed(l3_clk.vbases[OSM_BASE] + ENABLE_REG) & ENABLE_OSM) {
+		dev_info(&pdev->dev, "OSM has been initialized and enabled by TZ software\n");
+		osm_tz_enabled = true;
+	}
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"osm_pwrcl_base");
 	if (!res) {
@@ -2615,6 +2668,9 @@
 		return -ENOMEM;
 	}
 
+	if (osm_tz_enabled)
+		return rc;
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "l3_pll");
 	if (!res) {
 		dev_err(&pdev->dev,
@@ -3029,241 +3085,282 @@
 		return rc;
 	}
 
-	if (l3_clk.vbases[EFUSE_BASE]) {
-		/* Multiple speed-bins are supported */
-		pte_efuse = readl_relaxed(l3_clk.vbases[EFUSE_BASE]);
-		l3_clk.speedbin = ((pte_efuse >> L3_EFUSE_SHIFT) &
-						    L3_EFUSE_MASK);
-		snprintf(l3speedbinstr, ARRAY_SIZE(l3speedbinstr),
+	if (!osm_tz_enabled) {
+		if (l3_clk.vbases[EFUSE_BASE]) {
+			/* Multiple speed-bins are supported */
+			pte_efuse = readl_relaxed(l3_clk.vbases[EFUSE_BASE]);
+			l3_clk.speedbin = ((pte_efuse >> L3_EFUSE_SHIFT) &
+							L3_EFUSE_MASK);
+			snprintf(l3speedbinstr, ARRAY_SIZE(l3speedbinstr),
 			 "qcom,l3-speedbin%d-v%d", l3_clk.speedbin, pvs_ver);
-	}
+		}
 
-	dev_info(&pdev->dev, "using L3 speed bin %u and pvs_ver %d\n",
-		 l3_clk.speedbin, pvs_ver);
+		dev_info(&pdev->dev, "using L3 speed bin %u and pvs_ver %d\n",
+					l3_clk.speedbin, pvs_ver);
 
-	rc = clk_osm_get_lut(pdev, &l3_clk, l3speedbinstr);
-	if (rc) {
-		dev_err(&pdev->dev, "Unable to get OSM LUT for L3, rc=%d\n",
-			rc);
-		return rc;
-	}
+		rc = clk_osm_get_lut(pdev, &l3_clk, l3speedbinstr);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to get OSM LUT for L3, rc=%d\n",
+				rc);
+			return rc;
+		}
 
-	if (pwrcl_clk.vbases[EFUSE_BASE]) {
-		/* Multiple speed-bins are supported */
-		pte_efuse = readl_relaxed(pwrcl_clk.vbases[EFUSE_BASE]);
-		pwrcl_clk.speedbin = ((pte_efuse >> PWRCL_EFUSE_SHIFT) &
-						    PWRCL_EFUSE_MASK);
-		snprintf(pwrclspeedbinstr, ARRAY_SIZE(pwrclspeedbinstr),
+		if (pwrcl_clk.vbases[EFUSE_BASE]) {
+			/* Multiple speed-bins are supported */
+			pte_efuse = readl_relaxed(pwrcl_clk.vbases[EFUSE_BASE]);
+			pwrcl_clk.speedbin = ((pte_efuse >> PWRCL_EFUSE_SHIFT) &
+							PWRCL_EFUSE_MASK);
+			snprintf(pwrclspeedbinstr, ARRAY_SIZE(pwrclspeedbinstr),
 			 "qcom,pwrcl-speedbin%d-v%d", pwrcl_clk.speedbin,
 							pvs_ver);
-	}
+		}
 
-	dev_info(&pdev->dev, "using pwrcl speed bin %u and pvs_ver %d\n",
-		 pwrcl_clk.speedbin, pvs_ver);
+		dev_info(&pdev->dev, "using pwrcl speed bin %u and pvs_ver %d\n",
+					pwrcl_clk.speedbin, pvs_ver);
 
-	rc = clk_osm_get_lut(pdev, &pwrcl_clk, pwrclspeedbinstr);
-	if (rc) {
-		dev_err(&pdev->dev, "Unable to get OSM LUT for power cluster, rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	if (perfcl_clk.vbases[EFUSE_BASE]) {
-		/* Multiple speed-bins are supported */
-		pte_efuse = readl_relaxed(perfcl_clk.vbases[EFUSE_BASE]);
-		perfcl_clk.speedbin = ((pte_efuse >> PERFCL_EFUSE_SHIFT) &
-							PERFCL_EFUSE_MASK);
-		snprintf(perfclspeedbinstr, ARRAY_SIZE(perfclspeedbinstr),
-			 "qcom,perfcl-speedbin%d-v%d", perfcl_clk.speedbin,
-							pvs_ver);
-	}
-
-	dev_info(&pdev->dev, "using perfcl speed bin %u and pvs_ver %d\n",
-		 perfcl_clk.speedbin, pvs_ver);
-
-	rc = clk_osm_get_lut(pdev, &perfcl_clk, perfclspeedbinstr);
-	if (rc) {
-		dev_err(&pdev->dev, "Unable to get OSM LUT for perf cluster, rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	rc = clk_osm_parse_dt_configs(pdev);
-	if (rc) {
-		dev_err(&pdev->dev, "Unable to parse OSM device tree configurations\n");
-		return rc;
-	}
-
-	rc = clk_osm_parse_acd_dt_configs(pdev);
-	if (rc) {
-		dev_err(&pdev->dev, "Unable to parse ACD device tree configurations\n");
-		return rc;
-	}
-
-	rc = clk_osm_acd_resources_init(pdev);
-	if (rc) {
-		dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	rc = clk_osm_resolve_open_loop_voltages(&l3_clk);
-	if (rc) {
-		if (rc == -EPROBE_DEFER)
+		rc = clk_osm_get_lut(pdev, &pwrcl_clk, pwrclspeedbinstr);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to get OSM LUT for power cluster, rc=%d\n",
+				rc);
 			return rc;
-		dev_err(&pdev->dev, "Unable to determine open-loop voltages for L3, rc=%d\n",
-			rc);
-		return rc;
-	}
+		}
 
-	rc = clk_osm_resolve_open_loop_voltages(&pwrcl_clk);
-	if (rc) {
-		if (rc == -EPROBE_DEFER)
+		if (perfcl_clk.vbases[EFUSE_BASE]) {
+			/* Multiple speed-bins are supported */
+			pte_efuse =
+				readl_relaxed(perfcl_clk.vbases[EFUSE_BASE]);
+			perfcl_clk.speedbin = ((pte_efuse >> PERFCL_EFUSE_SHIFT)
+						& PERFCL_EFUSE_MASK);
+			snprintf(perfclspeedbinstr,
+				ARRAY_SIZE(perfclspeedbinstr),
+				"qcom,perfcl-speedbin%d-v%d",
+				perfcl_clk.speedbin, pvs_ver);
+		}
+
+		dev_info(&pdev->dev, "using perfcl speed bin %u and pvs_ver %d\n",
+					perfcl_clk.speedbin, pvs_ver);
+
+		rc = clk_osm_get_lut(pdev, &perfcl_clk, perfclspeedbinstr);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to get OSM LUT for perf cluster, rc=%d\n",
+				rc);
 			return rc;
-		dev_err(&pdev->dev, "Unable to determine open-loop voltages for power cluster, rc=%d\n",
-			rc);
-		return rc;
-	}
+		}
 
-	rc = clk_osm_resolve_open_loop_voltages(&perfcl_clk);
-	if (rc) {
-		if (rc == -EPROBE_DEFER)
+		rc = clk_osm_parse_dt_configs(pdev);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to parse OSM device tree configurations\n");
 			return rc;
-		dev_err(&pdev->dev, "Unable to determine open-loop voltages for perf cluster, rc=%d\n",
-			rc);
-		return rc;
-	}
+		}
 
-	rc = clk_osm_resolve_crossover_corners(&l3_clk, pdev);
-	if (rc)
-		dev_info(&pdev->dev,
-			"No APM crossover corner programmed for L3\n");
+		rc = clk_osm_parse_acd_dt_configs(pdev);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to parse ACD device tree configurations\n");
+			return rc;
+		}
 
-	rc = clk_osm_resolve_crossover_corners(&pwrcl_clk, pdev);
-	if (rc)
-		dev_info(&pdev->dev,
-			"No APM crossover corner programmed for pwrcl_clk\n");
+		rc = clk_osm_acd_resources_init(pdev);
+		if (rc) {
+			dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n",
+				rc);
+			return rc;
+		}
 
-	rc = clk_osm_resolve_crossover_corners(&perfcl_clk, pdev);
-	if (rc)
-		dev_info(&pdev->dev, "No MEM-ACC crossover corner programmed\n");
+		rc = clk_osm_resolve_open_loop_voltages(&l3_clk);
+		if (rc) {
+			if (rc == -EPROBE_DEFER)
+				return rc;
+			dev_err(&pdev->dev, "Unable to determine open-loop voltages for L3, rc=%d\n",
+				rc);
+			return rc;
+		}
+		rc = clk_osm_resolve_open_loop_voltages(&pwrcl_clk);
+		if (rc) {
+			if (rc == -EPROBE_DEFER)
+				return rc;
+			dev_err(&pdev->dev, "Unable to determine open-loop voltages for power cluster, rc=%d\n",
+				rc);
+			return rc;
+		}
+		rc = clk_osm_resolve_open_loop_voltages(&perfcl_clk);
+		if (rc) {
+			if (rc == -EPROBE_DEFER)
+				return rc;
+			dev_err(&pdev->dev, "Unable to determine open-loop voltages for perf cluster, rc=%d\n",
+				rc);
+			return rc;
+		}
 
-	clk_osm_setup_cycle_counters(&l3_clk);
-	clk_osm_setup_cycle_counters(&pwrcl_clk);
-	clk_osm_setup_cycle_counters(&perfcl_clk);
+		rc = clk_osm_resolve_crossover_corners(&l3_clk, pdev);
+		if (rc)
+			dev_info(&pdev->dev,
+				"No APM crossover corner programmed for L3\n");
+		rc = clk_osm_resolve_crossover_corners(&pwrcl_clk, pdev);
+		if (rc)
+			dev_info(&pdev->dev,
+				"No APM crossover corner programmed for pwrcl_clk\n");
+		rc = clk_osm_resolve_crossover_corners(&perfcl_clk, pdev);
+		if (rc)
+			dev_info(&pdev->dev, "No MEM-ACC crossover corner programmed\n");
 
-	clk_osm_print_osm_table(&l3_clk);
-	clk_osm_print_osm_table(&pwrcl_clk);
-	clk_osm_print_osm_table(&perfcl_clk);
+		clk_osm_setup_cycle_counters(&l3_clk);
+		clk_osm_setup_cycle_counters(&pwrcl_clk);
+		clk_osm_setup_cycle_counters(&perfcl_clk);
 
-	rc = clk_osm_setup_hw_table(&l3_clk);
-	if (rc) {
-		dev_err(&pdev->dev, "failed to setup l3 hardware table\n");
-		goto exit;
-	}
-	rc = clk_osm_setup_hw_table(&pwrcl_clk);
-	if (rc) {
-		dev_err(&pdev->dev, "failed to setup power cluster hardware table\n");
-		goto exit;
-	}
-	rc = clk_osm_setup_hw_table(&perfcl_clk);
-	if (rc) {
-		dev_err(&pdev->dev, "failed to setup perf cluster hardware table\n");
-		goto exit;
-	}
+		clk_osm_print_osm_table(&l3_clk);
+		clk_osm_print_osm_table(&pwrcl_clk);
+		clk_osm_print_osm_table(&perfcl_clk);
 
-	/* Policy tuning */
-	rc = clk_osm_set_cc_policy(pdev);
-	if (rc < 0) {
-		dev_err(&pdev->dev, "cc policy setup failed");
-		goto exit;
-	}
+		rc = clk_osm_setup_hw_table(&l3_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "failed to setup l3 hardware table\n");
+			goto exit;
+		}
+		rc = clk_osm_setup_hw_table(&pwrcl_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "failed to setup power cluster hardware table\n");
+			goto exit;
+		}
+		rc = clk_osm_setup_hw_table(&perfcl_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "failed to setup perf cluster hardware table\n");
+			goto exit;
+		}
 
-	/* LLM Freq Policy Tuning */
-	rc = clk_osm_set_llm_freq_policy(pdev);
-	if (rc < 0) {
-		dev_err(&pdev->dev, "LLM Frequency Policy setup failed");
-		goto exit;
-	}
+		/* Policy tuning */
+		rc = clk_osm_set_cc_policy(pdev);
+		if (rc < 0) {
+			dev_err(&pdev->dev, "cc policy setup failed");
+			goto exit;
+		}
 
-	/* LLM Voltage Policy Tuning */
-	rc = clk_osm_set_llm_volt_policy(pdev);
-	if (rc < 0) {
-		dev_err(&pdev->dev, "Failed to set LLM voltage Policy");
-		goto exit;
-	}
+		/* LLM Freq Policy Tuning */
+		rc = clk_osm_set_llm_freq_policy(pdev);
+		if (rc < 0) {
+			dev_err(&pdev->dev, "LLM Frequency Policy setup failed");
+			goto exit;
+		}
 
-	clk_osm_setup_fsms(&l3_clk);
-	clk_osm_setup_fsms(&pwrcl_clk);
-	clk_osm_setup_fsms(&perfcl_clk);
+		/* LLM Voltage Policy Tuning */
+		rc = clk_osm_set_llm_volt_policy(pdev);
+		if (rc < 0) {
+			dev_err(&pdev->dev, "Failed to set LLM voltage Policy");
+			goto exit;
+		}
 
-	/* Program VC at which the array power supply needs to be switched */
-	clk_osm_write_reg(&perfcl_clk, perfcl_clk.apm_threshold_vc,
+		clk_osm_setup_fsms(&l3_clk);
+		clk_osm_setup_fsms(&pwrcl_clk);
+		clk_osm_setup_fsms(&perfcl_clk);
+
+		/*
+		 * Program the VC at which the array power supply
+		 * needs to be switched.
+		 */
+		clk_osm_write_reg(&perfcl_clk, perfcl_clk.apm_threshold_vc,
 				APM_CROSSOVER_VC, OSM_BASE);
-	if (perfcl_clk.secure_init) {
-		clk_osm_write_seq_reg(&perfcl_clk, perfcl_clk.apm_crossover_vc,
-				DATA_MEM(77));
-		clk_osm_write_seq_reg(&perfcl_clk,
+		if (perfcl_clk.secure_init) {
+			clk_osm_write_seq_reg(&perfcl_clk,
+				perfcl_clk.apm_crossover_vc, DATA_MEM(77));
+			clk_osm_write_seq_reg(&perfcl_clk,
 				(0x39 | (perfcl_clk.apm_threshold_vc << 6)),
 				DATA_MEM(111));
-	} else {
-		scm_io_write(perfcl_clk.pbases[SEQ_BASE] + DATA_MEM(77),
-				perfcl_clk.apm_crossover_vc);
-		scm_io_write(perfcl_clk.pbases[SEQ_BASE] + DATA_MEM(111),
+		} else {
+			scm_io_write(perfcl_clk.pbases[SEQ_BASE] + DATA_MEM(77),
+					perfcl_clk.apm_crossover_vc);
+			scm_io_write(perfcl_clk.pbases[SEQ_BASE] +
+								DATA_MEM(111),
 				(0x39 | (perfcl_clk.apm_threshold_vc << 6)));
-	}
+		}
 
-	/*
-	 * Perform typical secure-world HW initialization
-	 * as necessary.
-	 */
-	clk_osm_do_additional_setup(&l3_clk, pdev);
-	clk_osm_do_additional_setup(&pwrcl_clk, pdev);
-	clk_osm_do_additional_setup(&perfcl_clk, pdev);
+		/*
+		 * Perform typical secure-world HW initialization
+		 * as necessary.
+		 */
+		clk_osm_do_additional_setup(&l3_clk, pdev);
+		clk_osm_do_additional_setup(&pwrcl_clk, pdev);
+		clk_osm_do_additional_setup(&perfcl_clk, pdev);
 
-	/* MEM-ACC Programming */
-	clk_osm_program_mem_acc_regs(&l3_clk);
-	clk_osm_program_mem_acc_regs(&pwrcl_clk);
-	clk_osm_program_mem_acc_regs(&perfcl_clk);
+		/* MEM-ACC Programming */
+		clk_osm_program_mem_acc_regs(&l3_clk);
+		clk_osm_program_mem_acc_regs(&pwrcl_clk);
+		clk_osm_program_mem_acc_regs(&perfcl_clk);
 
-	if (of_property_read_bool(pdev->dev.of_node, "qcom,osm-pll-setup")) {
-		clk_osm_setup_cluster_pll(&l3_clk);
-		clk_osm_setup_cluster_pll(&pwrcl_clk);
-		clk_osm_setup_cluster_pll(&perfcl_clk);
-	}
+		if (of_property_read_bool(pdev->dev.of_node,
+					"qcom,osm-pll-setup")) {
+			clk_osm_setup_cluster_pll(&l3_clk);
+			clk_osm_setup_cluster_pll(&pwrcl_clk);
+			clk_osm_setup_cluster_pll(&perfcl_clk);
+		}
 
-	/* Misc programming */
-	clk_osm_misc_programming(&l3_clk);
-	clk_osm_misc_programming(&pwrcl_clk);
-	clk_osm_misc_programming(&perfcl_clk);
+		/* Misc programming */
+		clk_osm_misc_programming(&l3_clk);
+		clk_osm_misc_programming(&pwrcl_clk);
+		clk_osm_misc_programming(&perfcl_clk);
 
-	pwrcl_clk.per_core_dcvs = perfcl_clk.per_core_dcvs =
+		rc = clk_osm_acd_init(&l3_clk);
+		if (rc) {
+			pr_err("failed to initialize ACD for L3, rc=%d\n", rc);
+			goto exit;
+		}
+		rc = clk_osm_acd_init(&pwrcl_clk);
+		if (rc) {
+			pr_err("failed to initialize ACD for pwrcl, rc=%d\n",
+									rc);
+			goto exit;
+		}
+		rc = clk_osm_acd_init(&perfcl_clk);
+		if (rc) {
+			pr_err("failed to initialize ACD for perfcl, rc=%d\n",
+									rc);
+			goto exit;
+		}
+
+		pwrcl_clk.per_core_dcvs = perfcl_clk.per_core_dcvs =
 			of_property_read_bool(pdev->dev.of_node,
 				"qcom,enable-per-core-dcvs");
-	if (pwrcl_clk.per_core_dcvs) {
+		if (pwrcl_clk.per_core_dcvs) {
+			val = clk_osm_read_reg(&pwrcl_clk, CORE_DCVS_CTRL);
+			val |= BIT(0);
+			clk_osm_write_reg(&pwrcl_clk, val, CORE_DCVS_CTRL,
+							OSM_BASE);
+			val = clk_osm_read_reg(&perfcl_clk, CORE_DCVS_CTRL);
+			val |= BIT(0);
+			clk_osm_write_reg(&perfcl_clk, val, CORE_DCVS_CTRL,
+							OSM_BASE);
+		}
+	} else {
+		/* OSM has been enabled already by trustzone */
+		rc = clk_osm_read_lut(pdev, &l3_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to read OSM LUT for L3, rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		rc = clk_osm_read_lut(pdev, &pwrcl_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to read OSM LUT for power cluster, rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		rc = clk_osm_read_lut(pdev, &perfcl_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to read OSM LUT for perf cluster, rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		/* Check if per-core DCVS is enabled/not */
 		val = clk_osm_read_reg(&pwrcl_clk, CORE_DCVS_CTRL);
-		val |= BIT(0);
-		clk_osm_write_reg(&pwrcl_clk, val, CORE_DCVS_CTRL, OSM_BASE);
+		if (val && BIT(0))
+			pwrcl_clk.per_core_dcvs = true;
 
 		val = clk_osm_read_reg(&perfcl_clk, CORE_DCVS_CTRL);
-		val |= BIT(0);
-		clk_osm_write_reg(&perfcl_clk, val, CORE_DCVS_CTRL, OSM_BASE);
-	}
+		if (val && BIT(0))
+			perfcl_clk.per_core_dcvs = true;
 
-	rc = clk_osm_acd_init(&l3_clk);
-	if (rc) {
-		pr_err("failed to initialize ACD for L3, rc=%d\n", rc);
-		goto exit;
-	}
-	rc = clk_osm_acd_init(&pwrcl_clk);
-	if (rc) {
-		pr_err("failed to initialize ACD for pwrcl, rc=%d\n", rc);
-		goto exit;
-	}
-	rc = clk_osm_acd_init(&perfcl_clk);
-	if (rc) {
-		pr_err("failed to initialize ACD for perfcl, rc=%d\n", rc);
-		goto exit;
+		clk_ops_l3_osm.enable = NULL;
 	}
 
 	spin_lock_init(&l3_clk.lock);
@@ -3290,7 +3387,23 @@
 
 	get_online_cpus();
 
-	/* Set the L3 clock to run off GPLL0 and enable OSM for the domain */
+	if (!osm_tz_enabled) {
+		populate_debugfs_dir(&l3_clk);
+		populate_debugfs_dir(&pwrcl_clk);
+		populate_debugfs_dir(&perfcl_clk);
+
+		/* Configure default rate to lowest frequency */
+		for (i = 0; i < MAX_CORE_COUNT; i++) {
+			osm_set_index(&pwrcl_clk, 0, i);
+			osm_set_index(&perfcl_clk, 0, i);
+		}
+	}
+	/*
+	 * Set the L3 clock to run off GPLL0 and enable OSM for the domain.
+	 * In the case that trustzone has already enabled OSM, bring the L3
+	 * clock rate to a safe level until the devfreq driver comes up and
+	 * votes for its desired frequency.
+	 */
 	rc = clk_set_rate(l3_clk.hw.clk, OSM_INIT_RATE);
 	if (rc) {
 		dev_err(&pdev->dev, "Unable to set init rate on L3 cluster, rc=%d\n",
@@ -3298,21 +3411,12 @@
 		goto provider_err;
 	}
 	WARN(clk_prepare_enable(l3_cluster0_vote_clk.hw.clk),
-		     "clk: Failed to enable cluster0 clock for L3\n");
+			"clk: Failed to enable cluster0 clock for L3\n");
 	WARN(clk_prepare_enable(l3_cluster1_vote_clk.hw.clk),
-		     "clk: Failed to enable cluster1 clock for L3\n");
+			"clk: Failed to enable cluster1 clock for L3\n");
 	udelay(300);
 
-	/* Configure default rate to lowest frequency */
-	for (i = 0; i < MAX_CORE_COUNT; i++) {
-		osm_set_index(&pwrcl_clk, 0, i);
-		osm_set_index(&perfcl_clk, 0, i);
-	}
-
 	populate_opp_table(pdev);
-	populate_debugfs_dir(&l3_clk);
-	populate_debugfs_dir(&pwrcl_clk);
-	populate_debugfs_dir(&perfcl_clk);
 
 	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 	register_cpu_cycle_counter_cb(&cb);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index dd69b31..7382cfa 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -138,9 +138,6 @@
 	int ret;
 	u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
 
-	if (rcg->flags & DFS_ENABLE_RCG)
-		return 0;
-
 	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
 				 CFG_SRC_SEL_MASK, cfg);
 	if (ret)
@@ -350,8 +347,9 @@
 	struct clk_hw *hw = &rcg->clkr.hw;
 	int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
+	/* Skip configuration if DFS control has been enabled for the RCG. */
 	if (rcg->flags & DFS_ENABLE_RCG)
-		return -EPERM;
+		return 0;
 
 	if (index < 0)
 		return index;
@@ -481,7 +479,7 @@
 	}
 
 	ret = clk_rcg2_configure(rcg, f);
-	if (ret && ret != -EPERM)
+	if (ret)
 		return ret;
 
 	if (rcg->flags & FORCE_ENABLE_RCG) {
@@ -1357,7 +1355,9 @@
 		"RCG flags %x\n", i, dfs_freq_tbl[i].freq, dfs_freq_tbl[i].src,
 				dfs_freq_tbl[i].pre_div, dfs_freq_tbl[i].m,
 				dfs_freq_tbl[i].n, rcg_flags);
-
+	/* Skip the safe configuration if DFS has been enabled for the RCG. */
+	if (clk->enable_safe_config)
+		clk->enable_safe_config = false;
 	clk->flags |= rcg_flags;
 	clk->freq_tbl = dfs_freq_tbl;
 err:
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 4e16155..17b2403 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -873,17 +873,6 @@
 	{ }
 };
 
-static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src_sdm845_v2[] = {
-	F(400000, P_BI_TCXO, 12, 1, 4),
-	F(9600000, P_BI_TCXO, 2, 0, 0),
-	F(19200000, P_BI_TCXO, 1, 0, 0),
-	F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
-	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
-	F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
-	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
-	{ }
-};
-
 static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
 	.cmd_rcgr = 0x1400c,
 	.mnd_width = 8,
@@ -1499,6 +1488,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_camera_ahb_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1525,6 +1515,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_camera_xo_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1619,7 +1610,7 @@
 				"gcc_cpuss_ahb_clk_src",
 			},
 			.num_parents = 1,
-			.flags = CLK_SET_RATE_PARENT,
+			.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1633,6 +1624,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_cpuss_dvm_bus_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1648,6 +1640,7 @@
 		.enable_mask = BIT(22),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_cpuss_gnoc_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1694,6 +1687,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_disp_ahb_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1754,6 +1748,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_disp_xo_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1823,6 +1818,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_gpu_cfg_ahb_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -2778,7 +2774,7 @@
 				"gcc_cpuss_ahb_clk_src",
 			},
 			.num_parents = 1,
-			.flags = CLK_SET_RATE_PARENT,
+			.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -3551,6 +3547,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_video_ahb_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -3577,6 +3574,7 @@
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
 			.name = "gcc_video_xo_clk",
+			.flags = CLK_IS_CRITICAL,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -4003,9 +4001,6 @@
 		50000000;
 	gcc_qupv3_wrap1_s7_clk_src.clkr.hw.init->rate_max[VDD_CX_NOMINAL] =
 		128000000;
-	gcc_sdcc2_apps_clk_src.freq_tbl = ftbl_gcc_sdcc2_apps_clk_src_sdm845_v2;
-	gcc_sdcc2_apps_clk_src.clkr.hw.init->rate_max[VDD_CX_LOW_L1] =
-		200000000;
 	gcc_ufs_card_axi_clk_src.freq_tbl =
 		ftbl_gcc_ufs_card_axi_clk_src_sdm845_v2;
 	gcc_ufs_card_axi_clk_src.clkr.hw.init->rate_max[VDD_CX_HIGH] =
@@ -4084,22 +4079,9 @@
 	regmap_update_bits(regmap, GCC_MMSS_MISC, 0x3, 0x3);
 	regmap_update_bits(regmap, GCC_GPU_MISC, 0x3, 0x3);
 
-	/* Keep these CPUSS clocks enabled always */
-	clk_prepare_enable(gcc_cpuss_ahb_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_sys_noc_cpuss_ahb_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_cpuss_dvm_bus_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_cpuss_gnoc_clk.clkr.hw.clk);
-
-	/* Keep the core XO clock enabled always */
-	clk_prepare_enable(gcc_camera_xo_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_disp_xo_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_video_xo_clk.clkr.hw.clk);
-
-	/* Enable for core register access */
-	clk_prepare_enable(gcc_gpu_cfg_ahb_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_disp_ahb_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_camera_ahb_clk.clkr.hw.clk);
-	clk_prepare_enable(gcc_video_ahb_clk.clkr.hw.clk);
+	/* Keep this clock on all the time on SDM845 v1 */
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,gcc-sdm845"))
+		clk_prepare_enable(gcc_aggre_noc_pcie_tbu_clk.clkr.hw.clk);
 
 	/* DFS clock registration */
 	ret = qcom_cc_register_rcg_dfs(pdev, &gcc_sdm845_dfs_desc);
diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c
index 5f1b1ef..1e98e08 100644
--- a/drivers/clk/qcom/gpucc-sdm845.c
+++ b/drivers/clk/qcom/gpucc-sdm845.c
@@ -142,6 +142,11 @@
 	.frac = 0x2aaa,
 };
 
+static const struct pll_config gpu_cc_pll1_config = {
+	.l = 0x1a,
+	.frac = 0xaaaa,
+};
+
 static struct clk_alpha_pll gpu_cc_pll0 = {
 	.offset = 0x0,
 	.vco_table = fabia_vco,
@@ -185,6 +190,26 @@
 	},
 };
 
+static struct clk_alpha_pll gpu_cc_pll1 = {
+	.offset = 0x100,
+	.vco_table = fabia_vco,
+	.num_vco = ARRAY_SIZE(fabia_vco),
+	.type = FABIA_PLL,
+	.clkr = {
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_cc_pll1",
+			.parent_names = (const char *[]){ "bi_tcxo" },
+			.num_parents = 1,
+			.ops = &clk_fabia_pll_ops,
+			VDD_MX_FMAX_MAP4(
+				MIN, 615000000,
+				LOW, 1066000000,
+				LOW_L1, 1600000000,
+				NOMINAL, 2000000000),
+		},
+	},
+};
+
 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
 	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
@@ -192,6 +217,13 @@
 	{ }
 };
 
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src_sdm845_v2[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
+	F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 gpu_cc_gmu_clk_src = {
 	.cmd_rcgr = 0x1120,
 	.mnd_width = 0,
@@ -235,6 +267,18 @@
 	{ }
 };
 
+static const struct freq_tbl  ftbl_gpu_cc_gx_gfx3d_clk_src_sdm845_v2[] = {
+	F(180000000, P_CRC_DIV,  1, 0, 0),
+	F(257000000, P_CRC_DIV,  1, 0, 0),
+	F(342000000, P_CRC_DIV,  1, 0, 0),
+	F(414000000, P_CRC_DIV,  1, 0, 0),
+	F(520000000, P_CRC_DIV,  1, 0, 0),
+	F(596000000, P_CRC_DIV,  1, 0, 0),
+	F(675000000, P_CRC_DIV,  1, 0, 0),
+	F(710000000, P_CRC_DIV,  1, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = {
 	.cmd_rcgr = 0x101c,
 	.mnd_width = 0,
@@ -510,10 +554,11 @@
 	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
 	[GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
 	[GPU_CC_PLL_TEST_CLK] = &gpu_cc_pll_test_clk.clkr,
+	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+	[GPU_CC_PLL1] = NULL,
 };
 
 static struct clk_regmap *gpu_cc_gfx_sdm845_clocks[] = {
-	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
 	[GPU_CC_PLL0_OUT_EVEN] = &gpu_cc_pll0_out_even.clkr,
 	[GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
 	[GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
@@ -553,16 +598,77 @@
 
 static const struct of_device_id gpu_cc_sdm845_match_table[] = {
 	{ .compatible = "qcom,gpucc-sdm845" },
+	{ .compatible = "qcom,gpucc-sdm845-v2" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, gpu_cc_sdm845_match_table);
 
 static const struct of_device_id gpu_cc_gfx_sdm845_match_table[] = {
 	{ .compatible = "qcom,gfxcc-sdm845" },
+	{ .compatible = "qcom,gfxcc-sdm845-v2" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, gpu_cc_gfx_sdm845_match_table);
 
+static void gpu_cc_sdm845_fixup_sdm845v2(struct regmap *regmap)
+{
+	gpu_cc_sdm845_clocks[GPU_CC_PLL1] = &gpu_cc_pll1.clkr;
+	clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+
+	gpu_cc_gmu_clk_src.freq_tbl = ftbl_gpu_cc_gmu_clk_src_sdm845_v2;
+	gpu_cc_gmu_clk_src.clkr.hw.init->rate_max[VDD_CX_LOW] = 500000000;
+}
+
+static void gpu_cc_gfx_sdm845_fixup_sdm845v2(void)
+{
+	gpu_cc_gx_gfx3d_clk_src.freq_tbl =
+				ftbl_gpu_cc_gx_gfx3d_clk_src_sdm845_v2;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_MIN] = 180000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_LOWER] =
+				257000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_LOW] = 342000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_LOW_L1] =
+				414000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_NOMINAL] =
+				520000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_NOMINAL_L1] =
+				596000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_HIGH] = 675000000;
+	gpu_cc_gx_gfx3d_clk_src.clkr.hw.init->rate_max[VDD_GX_HIGH_L1] =
+				710000000;
+}
+
+static int gpu_cc_gfx_sdm845_fixup(struct platform_device *pdev)
+{
+	const char *compat = NULL;
+	int compatlen = 0;
+
+	compat = of_get_property(pdev->dev.of_node, "compatible", &compatlen);
+	if (!compat || (compatlen <= 0))
+		return -EINVAL;
+
+	if (!strcmp(compat, "qcom,gfxcc-sdm845-v2"))
+		gpu_cc_gfx_sdm845_fixup_sdm845v2();
+
+	return 0;
+}
+
+static int gpu_cc_sdm845_fixup(struct platform_device *pdev,
+					struct regmap *regmap)
+{
+	const char *compat = NULL;
+	int compatlen = 0;
+
+	compat = of_get_property(pdev->dev.of_node, "compatible", &compatlen);
+	if (!compat || (compatlen <= 0))
+		return -EINVAL;
+
+	if (!strcmp(compat, "qcom,gpucc-sdm845-v2"))
+		gpu_cc_sdm845_fixup_sdm845v2(regmap);
+
+	return 0;
+}
+
 static int gpu_cc_gfx_sdm845_probe(struct platform_device *pdev)
 {
 	struct regmap *regmap;
@@ -596,15 +702,6 @@
 		return PTR_ERR(regmap);
 	}
 
-	/* Get MX voltage regulator for GPU PLL graphic clock. */
-	vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_mx");
-	if (IS_ERR(vdd_mx.regulator[0])) {
-		if (!(PTR_ERR(vdd_mx.regulator[0]) == -EPROBE_DEFER))
-			dev_err(&pdev->dev,
-				"Unable to get vdd_mx regulator\n");
-		return PTR_ERR(vdd_mx.regulator[0]);
-	}
-
 	/* GFX voltage regulators for GFX3D  graphic clock. */
 	vdd_gfx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_gfx");
 	if (IS_ERR(vdd_gfx.regulator[0])) {
@@ -616,6 +713,12 @@
 	/* Avoid turning on the rail during clock registration */
 	vdd_gfx.skip_handoff = true;
 
+	ret = gpu_cc_gfx_sdm845_fixup(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to do GFX clock fixup\n");
+		return ret;
+	}
+
 	clk_fabia_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
 
 	ret = qcom_cc_really_probe(pdev, &gpu_cc_gfx_sdm845_desc, regmap);
@@ -668,6 +771,21 @@
 		return PTR_ERR(vdd_cx.regulator[0]);
 	}
 
+	/* Get MX voltage regulator for GPU PLL graphic clock. */
+	vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_mx");
+	if (IS_ERR(vdd_mx.regulator[0])) {
+		if (!(PTR_ERR(vdd_mx.regulator[0]) == -EPROBE_DEFER))
+			dev_err(&pdev->dev,
+				"Unable to get vdd_mx regulator\n");
+		return PTR_ERR(vdd_mx.regulator[0]);
+	}
+
+	ret = gpu_cc_sdm845_fixup(pdev, regmap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to do GPU CC clock fixup\n");
+		return ret;
+	}
+
 	ret = qcom_cc_really_probe(pdev, &gpu_cc_sdm845_desc, regmap);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to register GPU CC clocks\n");
diff --git a/drivers/cpufreq/cpu-boost.c b/drivers/cpufreq/cpu-boost.c
index 07603fe..e67f12b 100644
--- a/drivers/cpufreq/cpu-boost.c
+++ b/drivers/cpufreq/cpu-boost.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015,2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,8 +39,8 @@
 static unsigned int input_boost_ms = 40;
 module_param(input_boost_ms, uint, 0644);
 
-static bool sched_boost_on_input;
-module_param(sched_boost_on_input, bool, 0644);
+static unsigned int sched_boost_on_input;
+module_param(sched_boost_on_input, uint, 0644);
 
 static bool sched_boost_active;
 
@@ -209,8 +209,8 @@
 	update_policy_online();
 
 	/* Enable scheduler boost to migrate tasks to big cluster */
-	if (sched_boost_on_input) {
-		ret = sched_set_boost(1);
+	if (sched_boost_on_input > 0) {
+		ret = sched_set_boost(sched_boost_on_input);
 		if (ret)
 			pr_err("cpu-boost: HMP boost enable failed\n");
 		else
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index e11ea50..5633a8f 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -55,6 +55,7 @@
 #define SCLK_HZ (32768)
 #define PSCI_POWER_STATE(reset) (reset << 30)
 #define PSCI_AFFINITY_LEVEL(lvl) ((lvl & 0x3) << 24)
+#define BIAS_HYST (bias_hyst * NSEC_PER_MSEC)
 
 enum {
 	MSM_LPM_LVL_DBG_SUSPEND_LIMITS = BIT(0),
@@ -93,6 +94,9 @@
 static uint32_t tmr_add = 100;
 module_param_named(tmr_add, tmr_add, uint, 0664);
 
+static uint32_t bias_hyst;
+module_param_named(bias_hyst, bias_hyst, uint, 0664);
+
 struct lpm_history {
 	uint32_t resi[MAXSAMPLES];
 	int mode[MAXSAMPLES];
@@ -572,6 +576,17 @@
 
 static void update_history(struct cpuidle_device *dev, int idx);
 
+static inline bool is_cpu_biased(int cpu)
+{
+	u64 now = sched_clock();
+	u64 last = sched_get_cpu_last_busy_time(cpu);
+
+	if (!last)
+		return false;
+
+	return (now - last) < BIAS_HYST;
+}
+
 static int cpu_power_select(struct cpuidle_device *dev,
 		struct lpm_cpu *cpu)
 {
@@ -596,6 +611,11 @@
 
 	next_event_us = (uint32_t)(ktime_to_us(get_next_event_time(dev->cpu)));
 
+	if (is_cpu_biased(dev->cpu)) {
+		best_level = 0;
+		goto done_select;
+	}
+
 	for (i = 0; i < cpu->nlevels; i++) {
 		struct lpm_cpu_level *level = &cpu->levels[i];
 		struct power_params *pwr_params = &level->pwr;
@@ -674,6 +694,7 @@
 			histtimer_start(htime);
 	}
 
+done_select:
 	trace_cpu_power_select(best_level, sleep_us, latency_us, next_event_us);
 
 	trace_cpu_pred_select(idx_restrict_time ? 2 : (predicted ? 1 : 0),
@@ -1031,9 +1052,7 @@
 	if (predicted && (idx < (cluster->nlevels - 1))) {
 		struct power_params *pwr_params = &cluster->levels[idx].pwr;
 
-		tick_broadcast_exit();
 		clusttimer_start(cluster, pwr_params->max_residency + tmr_add);
-		tick_broadcast_enter();
 	}
 
 	return 0;
@@ -1086,10 +1105,8 @@
 			struct power_params *pwr_params =
 						&cluster->levels[0].pwr;
 
-			tick_broadcast_exit();
 			clusttimer_start(cluster,
 					pwr_params->max_residency + tmr_add);
-			tick_broadcast_enter();
 		}
 	}
 
@@ -1196,9 +1213,6 @@
 	 * next wakeup within a cluster, in which case, CPU switches over to
 	 * use broadcast timer.
 	 */
-	if (from_idle && cpu_level->use_bc_timer)
-		tick_broadcast_enter();
-
 	if (from_idle && ((cpu_level->mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE)
 		|| (cpu_level->mode ==
 			MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)
@@ -1218,9 +1232,6 @@
 	struct lpm_cpu_level *cpu_level = &cpu->levels[cpu_index];
 	bool jtag_save_restore = cpu->levels[cpu_index].jtag_save_restore;
 
-	if (from_idle && cpu_level->use_bc_timer)
-		tick_broadcast_exit();
-
 	if (from_idle && ((cpu_level->mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE)
 		|| (cpu_level->mode ==
 			MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)
@@ -1272,6 +1283,11 @@
 	/*
 	 * idx = 0 is the default LPM state
 	 */
+	if (from_idle && cpu->levels[idx].use_bc_timer) {
+		if (tick_broadcast_enter())
+			return false;
+	}
+
 	if (!idx) {
 		stop_critical_timings();
 		wfi();
@@ -1290,6 +1306,10 @@
 	start_critical_timings();
 	update_debug_pc_event(CPU_EXIT, state_id,
 			success, 0xdeaffeed, true);
+
+	if (from_idle && cpu->levels[idx].use_bc_timer)
+		tick_broadcast_exit();
+
 	return success;
 }
 
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 97e3479..6fcf25f 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -1000,7 +1000,9 @@
 	ctx->flags |= SHA_FLAGS_FINUP;
 
 	err1 = atmel_sha_update(req);
-	if (err1 == -EINPROGRESS || err1 == -EBUSY)
+	if (err1 == -EINPROGRESS ||
+	    (err1 == -EBUSY && (ahash_request_flags(req) &
+				CRYPTO_TFM_REQ_MAY_BACKLOG)))
 		return err1;
 
 	/*
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 3bda6e5..0d743c6 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -2014,10 +2014,10 @@
 {
 	struct ablkcipher_request *req = context;
 	struct ablkcipher_edesc *edesc;
-#ifdef DEBUG
 	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
 	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
+#ifdef DEBUG
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
@@ -2037,6 +2037,14 @@
 #endif
 
 	ablkcipher_unmap(jrdev, edesc, req);
+
+	/*
+	 * The crypto API expects us to set the IV (req->info) to the last
+	 * ciphertext block. This is used e.g. by the CTS mode.
+	 */
+	scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize,
+				 ivsize, 0);
+
 	kfree(edesc);
 
 	ablkcipher_request_complete(req, err);
@@ -2047,10 +2055,10 @@
 {
 	struct ablkcipher_request *req = context;
 	struct ablkcipher_edesc *edesc;
-#ifdef DEBUG
 	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
 	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
+#ifdef DEBUG
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
@@ -2069,6 +2077,14 @@
 #endif
 
 	ablkcipher_unmap(jrdev, edesc, req);
+
+	/*
+	 * The crypto API expects us to set the IV (req->info) to the last
+	 * ciphertext block.
+	 */
+	scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize,
+				 ivsize, 0);
+
 	kfree(edesc);
 
 	ablkcipher_request_complete(req, err);
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 2474f14..631337c 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -491,7 +491,7 @@
 	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
 	if (!ret) {
 		/* in progress */
-		wait_for_completion_interruptible(&result.completion);
+		wait_for_completion(&result.completion);
 		ret = result.err;
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR,
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
index e1eaf4f..3ce1d5c 100644
--- a/drivers/crypto/caam/key_gen.c
+++ b/drivers/crypto/caam/key_gen.c
@@ -103,7 +103,7 @@
 	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
 	if (!ret) {
 		/* in progress */
-		wait_for_completion_interruptible(&result.completion);
+		wait_for_completion(&result.completion);
 		ret = result.err;
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
diff --git a/drivers/crypto/msm/compat_qcedev.c b/drivers/crypto/msm/compat_qcedev.c
index 0ca28be..d61b6f3 100644
--- a/drivers/crypto/msm/compat_qcedev.c
+++ b/drivers/crypto/msm/compat_qcedev.c
@@ -96,7 +96,6 @@
 
 	for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
 		err |= get_user(vaddr, &vbuf32->src[i].vaddr);
-		vbuf->src[i].vaddr = NULL;
 		err |= put_user(vaddr, (compat_uptr_t *)&vbuf->src[i].vaddr);
 		err |= get_user(len, &vbuf32->src[i].len);
 		err |= put_user(len, &vbuf->src[i].len);
@@ -104,7 +103,6 @@
 
 	for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
 		err |= get_user(vaddr, &vbuf32->dst[i].vaddr);
-		vbuf->dst[i].vaddr = NULL;
 		err |= put_user(vaddr, (compat_uptr_t *)&vbuf->dst[i].vaddr);
 		err |= get_user(len, &vbuf32->dst[i].len);
 		err |= put_user(len, &vbuf->dst[i].len);
@@ -122,7 +120,6 @@
 
 	for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
 		err |= get_user(vaddr, (compat_uptr_t *)&vbuf->src[i].vaddr);
-		vbuf32->src[i].vaddr = 0;
 		err |= put_user(vaddr, &vbuf32->src[i].vaddr);
 		err |= get_user(len, &vbuf->src[i].len);
 		err |= put_user(len, &vbuf32->src[i].len);
@@ -130,7 +127,6 @@
 
 	for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
 		err |= get_user(vaddr, (compat_uptr_t *)&vbuf->dst[i].vaddr);
-		vbuf32->dst[i].vaddr = 0;
 		err |= put_user(vaddr, &vbuf32->dst[i].vaddr);
 		err |= get_user(len, &vbuf->dst[i].len);
 		err |= put_user(len, &vbuf32->dst[i].len);
@@ -275,7 +271,6 @@
 
 	for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
 		err |= get_user(vaddr, &data32->data[i].vaddr);
-		data->data[i].vaddr = 0;
 		err |= put_user(vaddr, (compat_uptr_t *)&data->data[i].vaddr);
 		err |= get_user(len, &data32->data[i].len);
 		err |= put_user(len, &data->data[i].len);
@@ -294,7 +289,6 @@
 	err |= get_user(diglen, &data32->diglen);
 	err |= put_user(diglen, &data->diglen);
 	err |= get_user(authkey, &data32->authkey);
-	data->authkey = NULL;
 	err |= put_user(authkey, (compat_uptr_t *)&data->authkey);
 	err |= get_user(authklen, &data32->authklen);
 	err |= put_user(authklen, &data->authklen);
@@ -321,7 +315,6 @@
 
 	for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
 		err |= get_user(vaddr, (compat_uptr_t *)&data->data[i].vaddr);
-		data32->data[i].vaddr = 0;
 		err |= put_user(vaddr, &data32->data[i].vaddr);
 		err |= get_user(len, &data->data[i].len);
 		err |= put_user(len, &data32->data[i].len);
@@ -340,7 +333,6 @@
 	err |= get_user(diglen, &data->diglen);
 	err |= put_user(diglen, &data32->diglen);
 	err |= get_user(authkey, (compat_uptr_t *)&data->authkey);
-	data32->authkey = 0;
 	err |= put_user(authkey, &data32->authkey);
 	err |= get_user(authklen, &data->authklen);
 	err |= put_user(authklen, &data32->authklen);
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index b411726..6ed82ef 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -459,7 +459,7 @@
 		 (ICE_REV(ice_dev->ice_hw_version, MINOR) >= 1))) {
 		reg = qcom_ice_readl(ice_dev, QCOM_ICE_REGS_BYPASS_STATUS);
 		if ((reg & 0x80000000) != 0x0) {
-			pr_err("%s: Bypass failed for ice = %p",
+			pr_err("%s: Bypass failed for ice = %pK",
 				__func__, (void *)ice_dev);
 			WARN_ON(1);
 		}
@@ -485,7 +485,7 @@
 	}
 	ice_dev->ice_hw_version = rev;
 
-	dev_info(ice_dev->pdev, "QC ICE %d.%d.%d device found @0x%p\n",
+	dev_info(ice_dev->pdev, "QC ICE %d.%d.%d device found @0x%pK\n",
 					maj_rev, min_rev, step_rev,
 					ice_dev->mmio);
 
@@ -1275,7 +1275,7 @@
 		goto out;
 	}
 
-	pr_err("%s: =========== REGISTER DUMP (%p)===========\n",
+	pr_err("%s: =========== REGISTER DUMP (%pK)===========\n",
 			ice_dev->ice_instance_type, ice_dev);
 
 	pr_err("%s: ICE Control: 0x%08x | ICE Reset: 0x%08x\n",
@@ -1589,7 +1589,7 @@
 	struct ice_device *ice_dev = NULL;
 
 	if (!node) {
-		pr_err("%s: invalid node %p", __func__, node);
+		pr_err("%s: invalid node %pK", __func__, node);
 		goto out;
 	}
 
@@ -1606,13 +1606,14 @@
 
 	list_for_each_entry(ice_dev, &ice_devices, list) {
 		if (ice_dev->pdev->of_node == node) {
-			pr_info("%s: found ice device %p\n", __func__, ice_dev);
+			pr_info("%s: found ice device %pK\n", __func__,
+			ice_dev);
 			break;
 		}
 	}
 
 	ice_pdev = to_platform_device(ice_dev->pdev);
-	pr_info("%s: matching platform device %p\n", __func__, ice_pdev);
+	pr_info("%s: matching platform device %pK\n", __func__, ice_pdev);
 out:
 	return ice_pdev;
 }
@@ -1650,7 +1651,7 @@
 		}
 		ret = regulator_enable(ice_dev->reg);
 		if (ret) {
-			pr_err("%s:%p: Could not enable regulator\n",
+			pr_err("%s:%pK: Could not enable regulator\n",
 					__func__, ice_dev);
 			goto out;
 		}
@@ -1658,7 +1659,7 @@
 
 	/* Setup Clocks */
 	if (qcom_ice_enable_clocks(ice_dev, true)) {
-		pr_err("%s:%p:%s Could not enable clocks\n", __func__,
+		pr_err("%s:%pK:%s Could not enable clocks\n", __func__,
 				ice_dev, ice_dev->ice_instance_type);
 		goto out_reg;
 	}
@@ -1670,7 +1671,7 @@
 
 	ret = qcom_ice_set_bus_vote(ice_dev, vote);
 	if (ret) {
-		pr_err("%s:%p: failed %d\n", __func__, ice_dev, ret);
+		pr_err("%s:%pK: failed %d\n", __func__, ice_dev, ret);
 		goto out_clocks;
 	}
 
@@ -1702,19 +1703,19 @@
 	/* Setup Bus Vote */
 	vote = qcom_ice_get_bus_vote(ice_dev, "MIN");
 	if (vote < 0) {
-		pr_err("%s:%p: Unable to get bus vote\n", __func__, ice_dev);
+		pr_err("%s:%pK: Unable to get bus vote\n", __func__, ice_dev);
 		goto out_disable_clocks;
 	}
 
 	ret = qcom_ice_set_bus_vote(ice_dev, vote);
 	if (ret)
-		pr_err("%s:%p: failed %d\n", __func__, ice_dev, ret);
+		pr_err("%s:%pK: failed %d\n", __func__, ice_dev, ret);
 
 out_disable_clocks:
 
 	/* Setup Clocks */
 	if (qcom_ice_enable_clocks(ice_dev, false))
-		pr_err("%s:%p:%s Could not disable clocks\n", __func__,
+		pr_err("%s:%pK:%s Could not disable clocks\n", __func__,
 				ice_dev, ice_dev->ice_instance_type);
 
 	/* Setup Regulator */
@@ -1725,7 +1726,7 @@
 		}
 		ret = regulator_disable(ice_dev->reg);
 		if (ret) {
-			pr_err("%s:%p: Could not disable regulator\n",
+			pr_err("%s:%pK: Could not disable regulator\n",
 					__func__, ice_dev);
 			goto out;
 		}
diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c
index 3a2a51d..d477815 100644
--- a/drivers/crypto/msm/ota_crypto.c
+++ b/drivers/crypto/msm/ota_crypto.c
@@ -172,7 +172,7 @@
 	podev =  file->private_data;
 
 	if (podev != NULL && podev->magic != OTA_MAGIC) {
-		pr_err("%s: invalid handle %p\n",
+		pr_err("%s: invalid handle %pK\n",
 			__func__, podev);
 	}
 
@@ -440,7 +440,7 @@
 
 	podev =  file->private_data;
 	if (podev == NULL || podev->magic != OTA_MAGIC) {
-		pr_err("%s: invalid handle %p\n",
+		pr_err("%s: invalid handle %pK\n",
 			__func__, podev);
 		return -ENOENT;
 	}
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index d9ebe113..35d7542 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -33,12 +33,17 @@
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <soc/qcom/socinfo.h>
+#include <asm/dma-iommu.h>
+#include <linux/iommu.h>
 
 #include "qce.h"
 #include "qce50.h"
 #include "qcryptohw_50.h"
 #include "qce_ota.h"
 
+#define CRYPTO_SMMU_IOVA_START 0x10000000
+#define CRYPTO_SMMU_IOVA_SIZE 0x40000000
+
 #define CRYPTO_CONFIG_RESET 0xE01EF
 #define MAX_SPS_DESC_FIFO_SIZE 0xfff0
 #define QCE_MAX_NUM_DSCR    0x200
@@ -156,6 +161,8 @@
 	atomic_t last_intr_seq;
 	bool cadence_flag;
 	uint8_t *dummyreq_in_buf;
+	struct dma_iommu_mapping *smmu_mapping;
+	bool bypass_s1_smmu;
 };
 
 static void print_notify_debug(struct sps_event_notify *notify);
@@ -1157,7 +1164,7 @@
 
 #define QCE_WRITE_REG(val, addr)					\
 {									\
-	pr_info("      [0x%p] 0x%x\n", addr, (uint32_t)val);		\
+	pr_info("      [0x%pK] 0x%x\n", addr, (uint32_t)val);		\
 	writel_relaxed(val, addr);					\
 }
 
@@ -2153,6 +2160,10 @@
 	pce_sps_data = &preq_info->ce_sps;
 	qce_callback = preq_info->qce_cb;
 	areq = (struct ahash_request *) preq_info->areq;
+	if (!areq) {
+		pr_err("sha operation error. areq is NULL\n");
+		return -ENXIO;
+	}
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, preq_info->src_nents,
 				DMA_TO_DEVICE);
 	memcpy(digest, (char *)(&pce_sps_data->result->auth_iv[0]),
@@ -2728,7 +2739,7 @@
 		sps_event->callback = NULL;
 	}
 
-	pr_debug("success, %s : pipe_handle=0x%lx, desc fifo base (phy) = 0x%p\n",
+	pr_debug("success, %s : pipe_handle=0x%lx, desc fifo base (phy) = 0x%pK\n",
 		is_producer ? "PRODUCER(RX/OUT)" : "CONSUMER(TX/IN)",
 		(uintptr_t)sps_pipe_info, &sps_connect_info->desc.phys_base);
 	goto out;
@@ -2890,7 +2901,7 @@
 	bam.ipc_loglevel = QCE_BAM_DEFAULT_IPC_LOGLVL;
 	bam.options |= SPS_BAM_CACHED_WP;
 	pr_debug("bam physical base=0x%lx\n", (uintptr_t)bam.phys_addr);
-	pr_debug("bam virtual base=0x%p\n", bam.virt_addr);
+	pr_debug("bam virtual base=0x%pK\n", bam.virt_addr);
 
 	/* Register CE Peripheral BAM device to SPS driver */
 	rc = sps_register_bam_device(&bam, &pbam->handle);
@@ -2965,7 +2976,7 @@
 		request_index++;
 		if (request_index >= MAX_QCE_BAM_REQ)
 			request_index = 0;
-		if (xchg(&pce_dev->ce_request_info[request_index].
+		if (atomic_xchg(&pce_dev->ce_request_info[request_index].
 						in_use, true) == false) {
 			pce_dev->ce_request_index = request_index;
 			return request_index;
@@ -2981,7 +2992,8 @@
 		bool is_complete)
 {
 	pce_dev->ce_request_info[req_info].xfer_type = QCE_XFER_TYPE_LAST;
-	if (xchg(&pce_dev->ce_request_info[req_info].in_use, false) == true) {
+	if (atomic_xchg(&pce_dev->ce_request_info[req_info].in_use,
+						false) == true) {
 		if (req_info < MAX_QCE_BAM_REQ && is_complete)
 			atomic_dec(&pce_dev->no_of_queued_req);
 	} else
@@ -2993,7 +3005,7 @@
 	phys_addr_t addr =
 		DESC_FULL_ADDR((phys_addr_t) notify->data.transfer.iovec.flags,
 				  notify->data.transfer.iovec.addr);
-	pr_debug("sps ev_id=%d, addr=0x%pa, size=0x%x, flags=0x%x user=0x%p\n",
+	pr_debug("sps ev_id=%d, addr=0x%pa, size=0x%x, flags=0x%x user=0x%pK\n",
 			notify->event_id, &addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags,
@@ -4605,7 +4617,7 @@
 {
 	int ret = 0;
 
-	if (!(xchg(&pce_dev->ce_request_info[DUMMY_REQ_INDEX].
+	if (!(atomic_xchg(&pce_dev->ce_request_info[DUMMY_REQ_INDEX].
 				in_use, true) == false))
 		return -EBUSY;
 	ret = qce_process_sha_req(pce_dev, NULL);
@@ -5703,6 +5715,10 @@
 		pr_info("CE operating frequency is not defined, setting to default 100MHZ\n");
 		pce_dev->ce_opp_freq_hz = CE_CLK_100MHZ;
 	}
+
+	if (of_property_read_bool((&pdev->dev)->of_node, "qcom,smmu-s1-bypass"))
+		pce_dev->bypass_s1_smmu = true;
+
 	pce_dev->ce_bam_info.dest_pipe_index	=
 			2 * pce_dev->ce_bam_info.pipe_pair_index;
 	pce_dev->ce_bam_info.src_pipe_index	=
@@ -5936,6 +5952,48 @@
 	return 0;
 }
 
+static void qce_iommu_release_iomapping(struct qce_device *pce_dev)
+{
+	if (pce_dev->smmu_mapping)
+		arm_iommu_release_mapping(pce_dev->smmu_mapping);
+
+	pce_dev->smmu_mapping = NULL;
+}
+
+static int qce_smmu_init(struct qce_device *pce_dev)
+{
+	struct dma_iommu_mapping *mapping;
+	int s1_bypass = 1;
+	int ret = 0;
+
+	mapping = arm_iommu_create_mapping(&platform_bus_type,
+				CRYPTO_SMMU_IOVA_START, CRYPTO_SMMU_IOVA_SIZE);
+	if (IS_ERR(mapping)) {
+		ret = PTR_ERR(mapping);
+		pr_err("Create mapping failed, err = %d\n", ret);
+		return ret;
+	}
+
+	ret = iommu_domain_set_attr(mapping->domain,
+				DOMAIN_ATTR_S1_BYPASS, &s1_bypass);
+	if (ret < 0) {
+		pr_err("Set s1_bypass attribute failed, err = %d\n", ret);
+		goto ext_fail_set_attr;
+	}
+
+	ret = arm_iommu_attach_device(pce_dev->pdev, mapping);
+	if (ret < 0) {
+		pr_err("Attach device failed, err = %d\n", ret);
+		goto ext_fail_set_attr;
+	}
+	pce_dev->smmu_mapping = mapping;
+	return ret;
+
+ext_fail_set_attr:
+	qce_iommu_release_iomapping(pce_dev);
+	return ret;
+}
+
 /* crypto engine open function. */
 void *qce_open(struct platform_device *pdev, int *rc)
 {
@@ -5963,7 +6021,7 @@
 	}
 
 	for (i = 0; i < MAX_QCE_ALLOC_BAM_REQ; i++)
-		pce_dev->ce_request_info[i].in_use = false;
+		atomic_set(&pce_dev->ce_request_info[i].in_use, false);
 	pce_dev->ce_request_index = 0;
 
 	pce_dev->memsize = 10 * PAGE_SIZE * MAX_QCE_ALLOC_BAM_REQ;
@@ -5993,6 +6051,13 @@
 	if (*rc)
 		goto err_enable_clk;
 
+	if (pce_dev->bypass_s1_smmu) {
+		if (qce_smmu_init(pce_dev)) {
+			*rc = -EIO;
+			goto err_smmu;
+		}
+	}
+
 	if (_probe_ce_engine(pce_dev)) {
 		*rc = -ENXIO;
 		goto err;
@@ -6019,6 +6084,9 @@
 	mutex_unlock(&qce_iomap_mutex);
 	return pce_dev;
 err:
+	if (pce_dev->bypass_s1_smmu)
+		qce_iommu_release_iomapping(pce_dev);
+err_smmu:
 	qce_disable_clk(pce_dev);
 
 err_enable_clk:
@@ -6060,6 +6128,9 @@
 	kfree(pce_dev->dummyreq_in_buf);
 	kfree(pce_dev->iovec_vmem);
 
+	if (pce_dev->bypass_s1_smmu)
+		qce_iommu_release_iomapping(pce_dev);
+
 	qce_disable_clk(pce_dev);
 	__qce_deinit_clk(pce_dev);
 	mutex_unlock(&qce_iomap_mutex);
@@ -6128,12 +6199,13 @@
 void qce_dump_req(void *handle)
 {
 	int i;
+	bool req_in_use;
 	struct qce_device *pce_dev = (struct qce_device *)handle;
 
 	for (i = 0; i < MAX_QCE_BAM_REQ; i++) {
-		pr_info("qce_dump_req %d %d\n", i,
-					pce_dev->ce_request_info[i].in_use);
-		if (pce_dev->ce_request_info[i].in_use == true)
+		req_in_use = atomic_read(&pce_dev->ce_request_info[i].in_use);
+		pr_info("qce_dump_req %d %d\n", i, req_in_use);
+		if (req_in_use == true)
 			_qce_dump_descr_fifos(pce_dev, i);
 	}
 }
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index 0e60bd2..ab0d21d 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -214,7 +214,7 @@
 };
 
 struct ce_request_info {
-	bool in_use;
+	atomic_t in_use;
 	bool in_prog;
 	enum qce_xfer_type_enum	xfer_type;
 	struct ce_sps_data ce_sps;
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 5d6e0c2..9f126b3 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -57,6 +57,7 @@
 
 static DEFINE_MUTEX(send_cmd_lock);
 static DEFINE_MUTEX(qcedev_sent_bw_req);
+static DEFINE_MUTEX(hash_access_lock);
 
 static int qcedev_control_clocks(struct qcedev_control *podev, bool enable)
 {
@@ -269,7 +270,7 @@
 	handle =  file->private_data;
 	podev =  handle->cntl;
 	if (podev != NULL && podev->magic != QCEDEV_MAGIC) {
-		pr_err("%s: invalid handle %p\n",
+		pr_err("%s: invalid handle %pK\n",
 					__func__, podev);
 	}
 	kzfree(handle);
@@ -1657,7 +1658,7 @@
 	podev =  handle->cntl;
 	qcedev_areq.handle = handle;
 	if (podev == NULL || podev->magic != QCEDEV_MAGIC) {
-		pr_err("%s: invalid handle %p\n",
+		pr_err("%s: invalid handle %pK\n",
 			__func__, podev);
 		return -ENOENT;
 	}
@@ -1699,12 +1700,18 @@
 					(void __user *)arg,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
-		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+		mutex_lock(&hash_access_lock);
+		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+			mutex_unlock(&hash_access_lock);
 			return -EINVAL;
+		}
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
 		err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
-		if (err)
+		if (err) {
+			mutex_unlock(&hash_access_lock);
 			return err;
+		}
+		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
@@ -1722,32 +1729,42 @@
 					(void __user *)arg,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
-		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+		mutex_lock(&hash_access_lock);
+		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+			mutex_unlock(&hash_access_lock);
 			return -EINVAL;
+		}
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
 
 		if (qcedev_areq.sha_op_req.alg == QCEDEV_ALG_AES_CMAC) {
 			err = qcedev_hash_cmac(&qcedev_areq, handle, &sg_src);
-			if (err)
+			if (err) {
+				mutex_unlock(&hash_access_lock);
 				return err;
+			}
 		} else {
 			if (handle->sha_ctxt.init_done == false) {
 				pr_err("%s Init was not called\n", __func__);
+				mutex_unlock(&hash_access_lock);
 				return -EINVAL;
 			}
 			err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
-			if (err)
+			if (err) {
+				mutex_unlock(&hash_access_lock);
 				return err;
+			}
 		}
 
 		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
 			pr_err("Invalid sha_ctxt.diglen %d\n",
 					handle->sha_ctxt.diglen);
+			mutex_unlock(&hash_access_lock);
 			return -EINVAL;
 		}
 		memcpy(&qcedev_areq.sha_op_req.digest[0],
 				&handle->sha_ctxt.digest[0],
 				handle->sha_ctxt.diglen);
+		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
@@ -1764,16 +1781,22 @@
 					(void __user *)arg,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
-		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+		mutex_lock(&hash_access_lock);
+		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+			mutex_unlock(&hash_access_lock);
 			return -EINVAL;
+		}
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
 		err = qcedev_hash_final(&qcedev_areq, handle);
-		if (err)
+		if (err) {
+			mutex_unlock(&hash_access_lock);
 			return err;
+		}
 		qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
 		memcpy(&qcedev_areq.sha_op_req.digest[0],
 				&handle->sha_ctxt.digest[0],
 				handle->sha_ctxt.diglen);
+		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
@@ -1788,20 +1811,28 @@
 					(void __user *)arg,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
-		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+		mutex_lock(&hash_access_lock);
+		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+			mutex_unlock(&hash_access_lock);
 			return -EINVAL;
+		}
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
 		qcedev_hash_init(&qcedev_areq, handle, &sg_src);
 		err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
-		if (err)
+		if (err) {
+			mutex_unlock(&hash_access_lock);
 			return err;
+		}
 		err = qcedev_hash_final(&qcedev_areq, handle);
-		if (err)
+		if (err) {
+			mutex_unlock(&hash_access_lock);
 			return err;
+		}
 		qcedev_areq.sha_op_req.diglen =	handle->sha_ctxt.diglen;
 		memcpy(&qcedev_areq.sha_op_req.digest[0],
 				&handle->sha_ctxt.digest[0],
 				handle->sha_ctxt.diglen);
+		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index b979fb9..b3269a6 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -265,7 +265,7 @@
 	preq->arsp = NULL;
 	/* free req */
 	if (xchg(&preq->in_use, false) == false)
-		pr_warn("request info %p free already\n", preq);
+		pr_warn("request info %pK free already\n", preq);
 	else
 		atomic_dec(&pce->req_count);
 }
@@ -1759,7 +1759,7 @@
 	}
 
 #ifdef QCRYPTO_DEBUG
-	dev_info(&pengine->pdev->dev, "_qce_ahash_complete: %p ret %d\n",
+	dev_info(&pengine->pdev->dev, "_qce_ahash_complete: %pK ret %d\n",
 				areq, ret);
 #endif
 	if (digest) {
@@ -1818,7 +1818,7 @@
 	}
 
 #ifdef QCRYPTO_DEBUG
-	dev_info(&pengine->pdev->dev, "_qce_ablk_cipher_complete: %p ret %d\n",
+	dev_info(&pengine->pdev->dev, "_qce_ablk_cipher_complete: %pK ret %d\n",
 				areq, ret);
 #endif
 	if (iv)
@@ -2520,7 +2520,7 @@
 	WARN_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_ecb: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_ecb: %pK\n", req);
 #endif
 
 	if ((ctx->enc_key_len == AES_KEYSIZE_192) &&
@@ -2550,7 +2550,7 @@
 	WARN_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_cbc: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_cbc: %pK\n", req);
 #endif
 
 	if ((ctx->enc_key_len == AES_KEYSIZE_192) &&
@@ -2580,7 +2580,7 @@
 	WARN_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_ctr: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_ctr: %pK\n", req);
 #endif
 
 	if ((ctx->enc_key_len == AES_KEYSIZE_192) &&
@@ -2768,7 +2768,7 @@
 	WARN_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_ecb: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_ecb: %pK\n", req);
 #endif
 
 	if ((ctx->enc_key_len == AES_KEYSIZE_192) &&
@@ -2798,7 +2798,7 @@
 	WARN_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_cbc: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_cbc: %pK\n", req);
 #endif
 
 	if ((ctx->enc_key_len == AES_KEYSIZE_192) &&
@@ -2828,7 +2828,7 @@
 	WARN_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_ctr: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_ctr: %pK\n", req);
 #endif
 
 	if ((ctx->enc_key_len == AES_KEYSIZE_192) &&
@@ -3394,7 +3394,7 @@
 
 #ifdef QCRYPTO_DEBUG
 	dev_info(&ctx->pengine->pdev->dev,
-			 "_qcrypto_aead_encrypt_aes_cbc: %p\n", req);
+			 "_qcrypto_aead_encrypt_aes_cbc: %pK\n", req);
 #endif
 
 	rctx = aead_request_ctx(req);
@@ -3425,7 +3425,7 @@
 
 #ifdef QCRYPTO_DEBUG
 	dev_info(&ctx->pengine->pdev->dev,
-			 "_qcrypto_aead_decrypt_aes_cbc: %p\n", req);
+			 "_qcrypto_aead_decrypt_aes_cbc: %pK\n", req);
 #endif
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -4011,7 +4011,7 @@
 							unsigned int len)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base);
-
+	int ret = 0;
 	memset(&sha_ctx->authkey[0], 0, SHA1_BLOCK_SIZE);
 	if (len <= SHA1_BLOCK_SIZE) {
 		memcpy(&sha_ctx->authkey[0], key, len);
@@ -4019,16 +4019,19 @@
 	} else {
 		sha_ctx->alg = QCE_HASH_SHA1;
 		sha_ctx->diglen = SHA1_DIGEST_SIZE;
-		_sha_hmac_setkey(tfm, key, len);
+		ret = _sha_hmac_setkey(tfm, key, len);
+		if (ret)
+			pr_err("SHA1 hmac setkey failed\n");
 		sha_ctx->authkey_in_len = SHA1_BLOCK_SIZE;
 	}
-	return 0;
+	return ret;
 }
 
 static int _sha256_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
 							unsigned int len)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base);
+	int ret = 0;
 
 	memset(&sha_ctx->authkey[0], 0, SHA256_BLOCK_SIZE);
 	if (len <= SHA256_BLOCK_SIZE) {
@@ -4037,11 +4040,13 @@
 	} else {
 		sha_ctx->alg = QCE_HASH_SHA256;
 		sha_ctx->diglen = SHA256_DIGEST_SIZE;
-		_sha_hmac_setkey(tfm, key, len);
+		ret = _sha_hmac_setkey(tfm, key, len);
+		if (ret)
+			pr_err("SHA256 hmac setkey failed\n");
 		sha_ctx->authkey_in_len = SHA256_BLOCK_SIZE;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int _sha_hmac_init_ihash(struct ahash_request *req,
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 0418a2f..571de2f 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -816,7 +816,7 @@
  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
  */
 #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
-#define TALITOS_MAX_KEY_SIZE		96
+#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
 #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
 
 struct talitos_ctx {
@@ -1495,6 +1495,11 @@
 {
 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
 
+	if (keylen > TALITOS_MAX_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
 	memcpy(&ctx->key, key, keylen);
 	ctx->keylen = keylen;
 
diff --git a/drivers/edac/kryo3xx_arm64_edac.c b/drivers/edac/kryo3xx_arm64_edac.c
index f5bb3ed..5ca93a6 100644
--- a/drivers/edac/kryo3xx_arm64_edac.c
+++ b/drivers/edac/kryo3xx_arm64_edac.c
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
+#include <linux/cpu_pm.h>
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
 
@@ -125,6 +126,7 @@
 struct erp_drvdata {
 	struct edac_device_ctl_info *edev_ctl;
 	struct erp_drvdata __percpu **erp_cpu_drvdata;
+	struct notifier_block nb_pm;
 	int ppi;
 };
 
@@ -358,6 +360,19 @@
 	return IRQ_HANDLED;
 }
 
+static int kryo3xx_pmu_cpu_pm_notify(struct notifier_block *self,
+				unsigned long action, void *v)
+{
+	switch (action) {
+	case CPU_PM_EXIT:
+		kryo3xx_check_l3_scu_error(panic_handler_drvdata->edev_ctl);
+		kryo3xx_check_l1_l2_ecc(panic_handler_drvdata->edev_ctl);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
 static void initialize_registers(void *info)
 {
 	set_errxctlr_el1();
@@ -400,6 +415,7 @@
 	drv->edev_ctl->ctl_name = "cache";
 	drv->edev_ctl->panic_on_ce = ARM64_ERP_PANIC_ON_CE;
 	drv->edev_ctl->panic_on_ue = ARM64_ERP_PANIC_ON_UE;
+	drv->nb_pm.notifier_call = kryo3xx_pmu_cpu_pm_notify;
 	platform_set_drvdata(pdev, drv);
 
 	rc = edac_device_add_device(drv->edev_ctl);
@@ -424,6 +440,8 @@
 		goto out_dev;
 	}
 
+	cpu_pm_register_notifier(&(drv->nb_pm));
+
 	return 0;
 
 out_dev:
diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c
index a8ec359..4b89cbf 100644
--- a/drivers/edac/qcom_llcc_edac.c
+++ b/drivers/edac/qcom_llcc_edac.c
@@ -291,7 +291,7 @@
 
 	qcom_llcc_clear_errors(err_type, drv);
 
-	errors[err_type].func(edev_ctl, 0, 0, errors[err_type].msg);
+	errors[err_type].func(edev_ctl, 0, bank, errors[err_type].msg);
 }
 
 static void qcom_llcc_check_cache_errors
@@ -353,10 +353,26 @@
 	struct erp_drvdata *drv;
 	struct edac_device_ctl_info *edev_ctl;
 	struct device *dev = &pdev->dev;
+	u32 num_banks;
+	struct regmap *llcc_map = NULL;
+
+	llcc_map = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(llcc_map)) {
+		dev_err(dev, "no regmap for syscon llcc parent\n");
+		return -ENOMEM;
+	}
+
+	/* Find the number of LLC banks supported */
+	regmap_read(llcc_map, LLCC_COMMON_STATUS0,
+		    &num_banks);
+
+	num_banks &= LLCC_LB_CNT_MASK;
+	num_banks >>= LLCC_LB_CNT_SHIFT;
 
 	/* Allocate edac control info */
 	edev_ctl = edac_device_alloc_ctl_info(sizeof(*drv), "qcom-llcc", 1,
-			NULL, 0, 1, NULL, 0, edac_device_alloc_index());
+			"bank", num_banks, 1, NULL, 0,
+			edac_device_alloc_index());
 
 	if (!edev_ctl)
 		return -ENOMEM;
@@ -374,64 +390,59 @@
 	edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
 
 	drv = edev_ctl->pvt_info;
+	drv->num_banks = num_banks;
+	drv->llcc_map = llcc_map;
 
-	drv->llcc_map = syscon_node_to_regmap(dev->parent->of_node);
-	if (IS_ERR(drv->llcc_map)) {
-		dev_err(dev, "no regmap for syscon llcc parent\n");
-		rc = -ENOMEM;
-		goto out;
-	}
+	rc = edac_device_add_device(edev_ctl);
+	if (rc)
+		goto out_mem;
 
 	if (interrupt_mode) {
 		drv->ecc_irq = platform_get_irq_byname(pdev, "ecc_irq");
 		if (!drv->ecc_irq) {
 			rc = -ENODEV;
-			goto out;
+			goto out_dev;
 		}
 
 		rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
 				IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
 		if (rc) {
 			dev_err(dev, "failed to request ecc irq\n");
-			goto out;
+			goto out_dev;
 		}
 	}
 
-	/* Find the number of LLC banks supported */
-	regmap_read(drv->llcc_map, LLCC_COMMON_STATUS0,
-		    &drv->num_banks);
-
-	drv->num_banks &= LLCC_LB_CNT_MASK;
-	drv->num_banks >>= LLCC_LB_CNT_SHIFT;
-
 	drv->llcc_banks = devm_kzalloc(&pdev->dev,
 		sizeof(u32) * drv->num_banks, GFP_KERNEL);
 
 	if (!drv->llcc_banks) {
 		dev_err(dev, "Cannot allocate memory for llcc_banks\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_dev;
 	}
 
 	rc = of_property_read_u32_array(dev->parent->of_node,
 			"qcom,llcc-banks-off", drv->llcc_banks, drv->num_banks);
 	if (rc) {
 		dev_err(dev, "Cannot read llcc-banks-off property\n");
-		return -EINVAL;
+		goto out_dev;
 	}
 
 	rc = of_property_read_u32(dev->parent->of_node,
 			"qcom,llcc-broadcast-off", &drv->b_off);
 	if (rc) {
 		dev_err(dev, "Cannot read llcc-broadcast-off property\n");
-		return -EINVAL;
+		goto out_dev;
 	}
 
 	platform_set_drvdata(pdev, edev_ctl);
 
-	rc = edac_device_add_device(edev_ctl);
-out:
-	if (rc)
-		edac_device_free_ctl_info(edev_ctl);
+	return 0;
+
+out_dev:
+	edac_device_del_device(edev_ctl->dev);
+out_mem:
+	edac_device_free_ctl_info(edev_ctl);
 
 	return rc;
 }
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 5e23e2d..f9a1e98 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -17,6 +17,7 @@
 cflags-$(CONFIG_EFI_ARMSTUB)	+= -I$(srctree)/scripts/dtc/libfdt
 
 KBUILD_CFLAGS			:= $(cflags-y) -DDISABLE_BRANCH_PROFILING \
+				   -D__NO_FORTIFY \
 				   $(call cc-option,-ffreestanding) \
 				   $(call cc-option,-fno-stack-protector)
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index dcaf691..264899d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1419,6 +1419,9 @@
 	if (size & 0x3 || *pos & 0x3)
 		return -EINVAL;
 
+	if (*pos >= adev->mc.mc_vram_size)
+		return -ENXIO;
+
 	while (size) {
 		unsigned long flags;
 		uint32_t value;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index f59771d..db7890c 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -330,6 +330,13 @@
 			return false;
 		}
 
+		/*
+		 * ignore out-of-order messages or messages that are part of a
+		 * failed transaction
+		 */
+		if (!recv_hdr.somt && !msg->have_somt)
+			return false;
+
 		/* get length contained in this portion */
 		msg->curchunk_len = recv_hdr.msg_len;
 		msg->curchunk_hdrlen = hdrlen;
@@ -2168,7 +2175,7 @@
 }
 EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
 
-static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
+static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
 {
 	int len;
 	u8 replyblock[32];
@@ -2183,12 +2190,12 @@
 			       replyblock, len);
 	if (ret != len) {
 		DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
-		return;
+		return false;
 	}
 	ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
 	if (!ret) {
 		DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
-		return;
+		return false;
 	}
 	replylen = msg->curchunk_len + msg->curchunk_hdrlen;
 
@@ -2200,21 +2207,32 @@
 		ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply,
 				    replyblock, len);
 		if (ret != len) {
-			DRM_DEBUG_KMS("failed to read a chunk\n");
+			DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n",
+				      len, ret);
+			return false;
 		}
+
 		ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
-		if (ret == false)
+		if (!ret) {
 			DRM_DEBUG_KMS("failed to build sideband msg\n");
+			return false;
+		}
+
 		curreply += len;
 		replylen -= len;
 	}
+	return true;
 }
 
 static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
 {
 	int ret = 0;
 
-	drm_dp_get_one_sb_msg(mgr, false);
+	if (!drm_dp_get_one_sb_msg(mgr, false)) {
+		memset(&mgr->down_rep_recv, 0,
+		       sizeof(struct drm_dp_sideband_msg_rx));
+		return 0;
+	}
 
 	if (mgr->down_rep_recv.have_eomt) {
 		struct drm_dp_sideband_msg_tx *txmsg;
@@ -2270,7 +2288,12 @@
 static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
 {
 	int ret = 0;
-	drm_dp_get_one_sb_msg(mgr, true);
+
+	if (!drm_dp_get_one_sb_msg(mgr, true)) {
+		memset(&mgr->up_req_recv, 0,
+		       sizeof(struct drm_dp_sideband_msg_rx));
+		return 0;
+	}
 
 	if (mgr->up_req_recv.have_eomt) {
 		struct drm_dp_sideband_msg_req_body msg;
@@ -2322,7 +2345,9 @@
 			DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
 		}
 
-		drm_dp_put_mst_branch_device(mstb);
+		if (mstb)
+			drm_dp_put_mst_branch_device(mstb);
+
 		memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
 	}
 	return ret;
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index eeb7c49..55c484e 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -12,6 +12,7 @@
 	select QCOM_SCM
 	select SND_SOC_HDMI_CODEC if SND_SOC
 	select SYNC_FILE
+	select HDCP_QSEECOM
 	default y
 	help
 	  DRM/KMS driver for MSM/snapdragon.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index b698b65..b625996 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -3,6 +3,7 @@
 ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi
 ccflags-y += -Idrivers/gpu/drm/msm/sde
 ccflags-y += -Idrivers/media/platform/msm/sde/rotator
+ccflags-y += -Idrivers/gpu/drm/msm/hdmi
 
 msm_drm-y := \
 	dp/dp_usbpd.o \
@@ -15,6 +16,7 @@
 	dp/dp_ctrl.o \
 	dp/dp_display.o \
 	dp/dp_drm.o \
+	dp/dp_hdcp2p2.o \
 	sde/sde_crtc.o \
 	sde/sde_encoder.o \
 	sde/sde_encoder_phys_vid.o \
@@ -36,6 +38,7 @@
 	sde/sde_hw_color_proc_v4.o \
 	sde/sde_hw_ad4.o \
 	sde_edid_parser.o \
+	sde_hdcp_1x.o
 
 msm_drm-$(CONFIG_DRM_MSM_HDMI) += hdmi/hdmi.o \
 	hdmi/hdmi_audio.o \
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 67c6b2d..9106027 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -28,11 +28,13 @@
 	struct device *dev;
 	struct dp_aux dp_aux;
 	struct dp_catalog_aux *catalog;
+	struct dp_aux_cfg *cfg;
 
 	struct mutex mutex;
 	struct completion comp;
 
 	u32 aux_error_num;
+	u32 retry_cnt;
 	bool cmd_busy;
 	bool native;
 	bool read;
@@ -127,7 +129,7 @@
 
 	timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms);
 	if (!timeout) {
-		pr_err("aux write timeout\n");
+		pr_err("aux %s timeout\n", (aux->read ? "read" : "write"));
 		return -ETIMEDOUT;
 	}
 
@@ -232,6 +234,22 @@
 		dp_aux_i2c_handler(aux);
 }
 
+static void dp_aux_reconfig(struct dp_aux *dp_aux)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	aux->catalog->update_aux_cfg(aux->catalog,
+			aux->cfg, PHY_AUX_CFG1);
+	aux->catalog->reset(aux->catalog);
+}
+
 /*
  * This function does the real job to process an AUX transaction.
  * It will call aux_reset() function to reset the AUX channel,
@@ -243,6 +261,7 @@
 	ssize_t ret;
 	int const aux_cmd_native_max = 16;
 	int const aux_cmd_i2c_max = 128;
+	int const retry_count = 5;
 	struct dp_aux_private *aux = container_of(drm_aux,
 		struct dp_aux_private, drm_aux);
 
@@ -270,8 +289,14 @@
 	}
 
 	ret = dp_aux_cmd_fifo_tx(aux, msg);
-	if (ret < 0) {
-		aux->catalog->reset(aux->catalog); /* reset aux */
+	if ((ret < 0) && aux->native) {
+		aux->retry_cnt++;
+		if (!(aux->retry_cnt % retry_count))
+			aux->catalog->update_aux_cfg(aux->catalog,
+				aux->cfg, PHY_AUX_CFG1);
+		aux->catalog->reset(aux->catalog);
+		goto unlock_exit;
+	} else if (ret < 0) {
 		goto unlock_exit;
 	}
 
@@ -289,6 +314,7 @@
 
 	/* Return requested size for success or retry */
 	ret = msg->size;
+	aux->retry_cnt = 0;
 
 unlock_exit:
 	aux->cmd_busy = false;
@@ -296,11 +322,19 @@
 	return ret;
 }
 
-static void dp_aux_init(struct dp_aux *dp_aux, u32 *aux_cfg)
+static void dp_aux_reset_phy_config_indices(struct dp_aux_cfg *aux_cfg)
+{
+	int i = 0;
+
+	for (i = 0; i < PHY_AUX_CFG_MAX; i++)
+		aux_cfg[i].current_index = 0;
+}
+
+static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg)
 {
 	struct dp_aux_private *aux;
 
-	if (!dp_aux) {
+	if (!dp_aux || !aux_cfg) {
 		pr_err("invalid input\n");
 		return;
 	}
@@ -309,6 +343,8 @@
 
 	aux->catalog->reset(aux->catalog);
 	aux->catalog->enable(aux->catalog, true);
+	aux->retry_cnt = 0;
+	dp_aux_reset_phy_config_indices(aux_cfg);
 	aux->catalog->setup(aux->catalog, aux_cfg);
 }
 
@@ -365,13 +401,14 @@
 	drm_dp_aux_unregister(&aux->drm_aux);
 }
 
-struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog)
+struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
+		struct dp_aux_cfg *aux_cfg)
 {
 	int rc = 0;
 	struct dp_aux_private *aux;
 	struct dp_aux *dp_aux;
 
-	if (!catalog) {
+	if (!catalog || !aux_cfg) {
 		pr_err("invalid input\n");
 		rc = -ENODEV;
 		goto error;
@@ -389,13 +426,16 @@
 
 	aux->dev = dev;
 	aux->catalog = catalog;
+	aux->cfg = aux_cfg;
 	dp_aux = &aux->dp_aux;
+	aux->retry_cnt = 0;
 
 	dp_aux->isr     = dp_aux_isr;
 	dp_aux->init    = dp_aux_init;
 	dp_aux->deinit  = dp_aux_deinit;
 	dp_aux->drm_aux_register = dp_aux_register;
 	dp_aux->drm_aux_deregister = dp_aux_deregister;
+	dp_aux->reconfig = dp_aux_reconfig;
 
 	return dp_aux;
 error:
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
index f08c12b..5d96fd9 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.h
+++ b/drivers/gpu/drm/msm/dp/dp_aux.h
@@ -32,11 +32,13 @@
 	int (*drm_aux_register)(struct dp_aux *aux);
 	void (*drm_aux_deregister)(struct dp_aux *aux);
 	void (*isr)(struct dp_aux *aux);
-	void (*init)(struct dp_aux *aux, u32 *aux_cfg);
+	void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg);
 	void (*deinit)(struct dp_aux *aux);
+	void (*reconfig)(struct dp_aux *aux);
 };
 
-struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog);
+struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
+		struct dp_aux_cfg *aux_cfg);
 void dp_aux_put(struct dp_aux *aux);
 
 #endif /*__DP_AUX_H_*/
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5825ba8..95a7dc4 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -17,196 +17,7 @@
 #include <linux/delay.h>
 
 #include "dp_catalog.h"
-
-/* DP_TX Registers */
-#define DP_HW_VERSION				(0x00000000)
-#define DP_SW_RESET				(0x00000010)
-#define DP_PHY_CTRL				(0x00000014)
-#define DP_CLK_CTRL				(0x00000018)
-#define DP_CLK_ACTIVE				(0x0000001C)
-#define DP_INTR_STATUS				(0x00000020)
-#define DP_INTR_STATUS2				(0x00000024)
-#define DP_INTR_STATUS3				(0x00000028)
-
-#define DP_DP_HPD_CTRL				(0x00000200)
-#define DP_DP_HPD_INT_STATUS			(0x00000204)
-#define DP_DP_HPD_INT_ACK			(0x00000208)
-#define DP_DP_HPD_INT_MASK			(0x0000020C)
-#define DP_DP_HPD_REFTIMER			(0x00000218)
-#define DP_DP_HPD_EVENT_TIME_0			(0x0000021C)
-#define DP_DP_HPD_EVENT_TIME_1			(0x00000220)
-#define DP_AUX_CTRL				(0x00000230)
-#define DP_AUX_DATA				(0x00000234)
-#define DP_AUX_TRANS_CTRL			(0x00000238)
-#define DP_TIMEOUT_COUNT			(0x0000023C)
-#define DP_AUX_LIMITS				(0x00000240)
-#define DP_AUX_STATUS				(0x00000244)
-
-#define DP_DPCD_CP_IRQ				(0x201)
-#define DP_DPCD_RXSTATUS			(0x69493)
-
-#define DP_INTERRUPT_TRANS_NUM			(0x000002A0)
-
-#define DP_MAINLINK_CTRL			(0x00000400)
-#define DP_STATE_CTRL				(0x00000404)
-#define DP_CONFIGURATION_CTRL			(0x00000408)
-#define DP_SOFTWARE_MVID			(0x00000410)
-#define DP_SOFTWARE_NVID			(0x00000418)
-#define DP_TOTAL_HOR_VER			(0x0000041C)
-#define DP_START_HOR_VER_FROM_SYNC		(0x00000420)
-#define DP_HSYNC_VSYNC_WIDTH_POLARITY		(0x00000424)
-#define DP_ACTIVE_HOR_VER			(0x00000428)
-#define DP_MISC1_MISC0				(0x0000042C)
-#define DP_VALID_BOUNDARY			(0x00000430)
-#define DP_VALID_BOUNDARY_2			(0x00000434)
-#define DP_LOGICAL2PHYSCIAL_LANE_MAPPING	(0x00000438)
-
-#define DP_MAINLINK_READY			(0x00000440)
-#define DP_MAINLINK_LEVELS			(0x00000444)
-#define DP_TU					(0x0000044C)
-
-#define DP_HBR2_COMPLIANCE_SCRAMBLER_RESET	(0x00000454)
-#define DP_TEST_80BIT_CUSTOM_PATTERN_REG0	(0x000004C0)
-#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1	(0x000004C4)
-#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2	(0x000004C8)
-
-#define MMSS_DP_MISC1_MISC0			(0x0000042C)
-#define MMSS_DP_AUDIO_TIMING_GEN		(0x00000480)
-#define MMSS_DP_AUDIO_TIMING_RBR_32		(0x00000484)
-#define MMSS_DP_AUDIO_TIMING_HBR_32		(0x00000488)
-#define MMSS_DP_AUDIO_TIMING_RBR_44		(0x0000048C)
-#define MMSS_DP_AUDIO_TIMING_HBR_44		(0x00000490)
-#define MMSS_DP_AUDIO_TIMING_RBR_48		(0x00000494)
-#define MMSS_DP_AUDIO_TIMING_HBR_48		(0x00000498)
-
-#define MMSS_DP_PSR_CRC_RG			(0x00000554)
-#define MMSS_DP_PSR_CRC_B			(0x00000558)
-
-#define MMSS_DP_AUDIO_CFG			(0x00000600)
-#define MMSS_DP_AUDIO_STATUS			(0x00000604)
-#define MMSS_DP_AUDIO_PKT_CTRL			(0x00000608)
-#define MMSS_DP_AUDIO_PKT_CTRL2			(0x0000060C)
-#define MMSS_DP_AUDIO_ACR_CTRL			(0x00000610)
-#define MMSS_DP_AUDIO_CTRL_RESET		(0x00000614)
-
-#define MMSS_DP_SDP_CFG				(0x00000628)
-#define MMSS_DP_SDP_CFG2			(0x0000062C)
-#define MMSS_DP_AUDIO_TIMESTAMP_0		(0x00000630)
-#define MMSS_DP_AUDIO_TIMESTAMP_1		(0x00000634)
-
-#define MMSS_DP_AUDIO_STREAM_0			(0x00000640)
-#define MMSS_DP_AUDIO_STREAM_1			(0x00000644)
-
-#define MMSS_DP_EXTENSION_0			(0x00000650)
-#define MMSS_DP_EXTENSION_1			(0x00000654)
-#define MMSS_DP_EXTENSION_2			(0x00000658)
-#define MMSS_DP_EXTENSION_3			(0x0000065C)
-#define MMSS_DP_EXTENSION_4			(0x00000660)
-#define MMSS_DP_EXTENSION_5			(0x00000664)
-#define MMSS_DP_EXTENSION_6			(0x00000668)
-#define MMSS_DP_EXTENSION_7			(0x0000066C)
-#define MMSS_DP_EXTENSION_8			(0x00000670)
-#define MMSS_DP_EXTENSION_9			(0x00000674)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_0		(0x00000678)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_1		(0x0000067C)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_2		(0x00000680)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_3		(0x00000684)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_4		(0x00000688)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_5		(0x0000068C)
-#define MMSS_DP_AUDIO_ISRC_0			(0x00000690)
-#define MMSS_DP_AUDIO_ISRC_1			(0x00000694)
-#define MMSS_DP_AUDIO_ISRC_2			(0x00000698)
-#define MMSS_DP_AUDIO_ISRC_3			(0x0000069C)
-#define MMSS_DP_AUDIO_ISRC_4			(0x000006A0)
-#define MMSS_DP_AUDIO_ISRC_5			(0x000006A4)
-#define MMSS_DP_AUDIO_INFOFRAME_0		(0x000006A8)
-#define MMSS_DP_AUDIO_INFOFRAME_1		(0x000006AC)
-#define MMSS_DP_AUDIO_INFOFRAME_2		(0x000006B0)
-
-#define MMSS_DP_GENERIC0_0			(0x00000700)
-#define MMSS_DP_GENERIC0_1			(0x00000704)
-#define MMSS_DP_GENERIC0_2			(0x00000708)
-#define MMSS_DP_GENERIC0_3			(0x0000070C)
-#define MMSS_DP_GENERIC0_4			(0x00000710)
-#define MMSS_DP_GENERIC0_5			(0x00000714)
-#define MMSS_DP_GENERIC0_6			(0x00000718)
-#define MMSS_DP_GENERIC0_7			(0x0000071C)
-#define MMSS_DP_GENERIC0_8			(0x00000720)
-#define MMSS_DP_GENERIC0_9			(0x00000724)
-#define MMSS_DP_GENERIC1_0			(0x00000728)
-#define MMSS_DP_GENERIC1_1			(0x0000072C)
-#define MMSS_DP_GENERIC1_2			(0x00000730)
-#define MMSS_DP_GENERIC1_3			(0x00000734)
-#define MMSS_DP_GENERIC1_4			(0x00000738)
-#define MMSS_DP_GENERIC1_5			(0x0000073C)
-#define MMSS_DP_GENERIC1_6			(0x00000740)
-#define MMSS_DP_GENERIC1_7			(0x00000744)
-#define MMSS_DP_GENERIC1_8			(0x00000748)
-#define MMSS_DP_GENERIC1_9			(0x0000074C)
-
-#define MMSS_DP_TIMING_ENGINE_EN		(0x00000A10)
-#define MMSS_DP_ASYNC_FIFO_CONFIG		(0x00000A88)
-
-/*DP PHY Register offsets */
-#define DP_PHY_REVISION_ID0                     (0x00000000)
-#define DP_PHY_REVISION_ID1                     (0x00000004)
-#define DP_PHY_REVISION_ID2                     (0x00000008)
-#define DP_PHY_REVISION_ID3                     (0x0000000C)
-
-#define DP_PHY_CFG                              (0x00000010)
-#define DP_PHY_PD_CTL                           (0x00000018)
-#define DP_PHY_MODE                             (0x0000001C)
-
-#define DP_PHY_AUX_CFG0                         (0x00000020)
-#define DP_PHY_AUX_CFG1                         (0x00000024)
-#define DP_PHY_AUX_CFG2                         (0x00000028)
-#define DP_PHY_AUX_CFG3                         (0x0000002C)
-#define DP_PHY_AUX_CFG4                         (0x00000030)
-#define DP_PHY_AUX_CFG5                         (0x00000034)
-#define DP_PHY_AUX_CFG6                         (0x00000038)
-#define DP_PHY_AUX_CFG7                         (0x0000003C)
-#define DP_PHY_AUX_CFG8                         (0x00000040)
-#define DP_PHY_AUX_CFG9                         (0x00000044)
-#define DP_PHY_AUX_INTERRUPT_MASK               (0x00000048)
-#define DP_PHY_AUX_INTERRUPT_CLEAR              (0x0000004C)
-
-#define DP_PHY_SPARE0				(0x00AC)
-
-#define TXn_TX_EMP_POST1_LVL			(0x000C)
-#define TXn_TX_DRV_LVL				(0x001C)
-
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN		(0x004)
-
-/* DP MMSS_CC registers */
-#define MMSS_DP_LINK_CMD_RCGR			(0x0138)
-#define MMSS_DP_LINK_CFG_RCGR			(0x013C)
-#define MMSS_DP_PIXEL_M				(0x0174)
-#define MMSS_DP_PIXEL_N				(0x0178)
-
-/* DP HDCP 1.3 registers */
-#define DP_HDCP_CTRL                                   (0x0A0)
-#define DP_HDCP_STATUS                                 (0x0A4)
-#define DP_HDCP_SW_UPPER_AKSV                          (0x298)
-#define DP_HDCP_SW_LOWER_AKSV                          (0x29C)
-#define DP_HDCP_ENTROPY_CTRL0                          (0x750)
-#define DP_HDCP_ENTROPY_CTRL1                          (0x75C)
-#define DP_HDCP_SHA_STATUS                             (0x0C8)
-#define DP_HDCP_RCVPORT_DATA2_0                        (0x0B0)
-#define DP_HDCP_RCVPORT_DATA3                          (0x2A4)
-#define DP_HDCP_RCVPORT_DATA4                          (0x2A8)
-#define DP_HDCP_RCVPORT_DATA5                          (0x0C0)
-#define DP_HDCP_RCVPORT_DATA6                          (0x0C4)
-
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL           (0x024)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA           (0x028)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0      (0x004)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1      (0x008)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7      (0x00C)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8      (0x010)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9      (0x014)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10     (0x018)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11     (0x01C)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12     (0x020)
+#include "dp_reg.h"
 
 #define dp_read(offset) readl_relaxed((offset))
 #define dp_write(offset, data) writel_relaxed((data), (offset))
@@ -364,11 +175,37 @@
 	dp_write(base + DP_AUX_CTRL, aux_ctrl);
 }
 
-static void dp_catalog_aux_setup(struct dp_catalog_aux *aux, u32 *aux_cfg)
+static void dp_catalog_aux_update_cfg(struct dp_catalog_aux *aux,
+		struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type)
 {
 	struct dp_catalog_private *catalog;
+	u32 new_index = 0, current_index = 0;
 
-	if (!aux || !aux_cfg) {
+	if (!aux || !cfg || (type >= PHY_AUX_CFG_MAX)) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	dp_catalog_get_priv(aux);
+
+	current_index = cfg[type].current_index;
+	new_index = (current_index + 1) % cfg[type].cfg_cnt;
+	pr_debug("Updating %s from 0x%08x to 0x%08x\n",
+		dp_phy_aux_config_type_to_string(type),
+	cfg[type].lut[current_index], cfg[type].lut[new_index]);
+
+	dp_write(catalog->io->phy_io.base + cfg[type].offset,
+			cfg[type].lut[new_index]);
+	cfg[type].current_index = new_index;
+}
+
+static void dp_catalog_aux_setup(struct dp_catalog_aux *aux,
+		struct dp_aux_cfg *cfg)
+{
+	struct dp_catalog_private *catalog;
+	int i = 0;
+
+	if (!aux || !cfg) {
 		pr_err("invalid input\n");
 		return;
 	}
@@ -384,16 +221,13 @@
 		QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f);
 
 	/* DP AUX CFG register programming */
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG0, aux_cfg[0]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG1, aux_cfg[1]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG2, aux_cfg[2]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG3, aux_cfg[3]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG4, aux_cfg[4]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG5, aux_cfg[5]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG6, aux_cfg[6]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG7, aux_cfg[7]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG8, aux_cfg[8]);
-	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_CFG9, aux_cfg[9]);
+	for (i = 0; i < PHY_AUX_CFG_MAX; i++) {
+		pr_debug("%s: offset=0x%08x, value=0x%08x\n",
+			dp_phy_aux_config_type_to_string(i),
+			cfg[i].offset, cfg[i].lut[cfg[i].current_index]);
+		dp_write(catalog->io->phy_io.base + cfg[i].offset,
+			cfg[i].lut[cfg[i].current_index]);
+	}
 
 	dp_write(catalog->io->phy_io.base + DP_PHY_AUX_INTERRUPT_MASK, 0x1F);
 }
@@ -424,6 +258,22 @@
 }
 
 /* controller related catalog functions */
+static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl)
+{
+	struct dp_catalog_private *catalog;
+	void __iomem *base;
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	dp_catalog_get_priv(ctrl);
+	base = catalog->io->ctrl_io.base;
+
+	return dp_read(base + DP_HDCP_STATUS);
+}
+
 static void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog_ctrl *ctrl)
 {
 	struct dp_catalog_private *catalog;
@@ -896,6 +746,7 @@
 		.write_data    = dp_catalog_aux_write_data,
 		.write_trans   = dp_catalog_aux_write_trans,
 		.reset         = dp_catalog_aux_reset,
+		.update_aux_cfg = dp_catalog_aux_update_cfg,
 		.enable        = dp_catalog_aux_enable,
 		.setup         = dp_catalog_aux_setup,
 		.get_irq       = dp_catalog_aux_get_irq,
@@ -917,6 +768,7 @@
 		.update_vx_px   = dp_catalog_ctrl_update_vx_px,
 		.get_interrupt  = dp_catalog_ctrl_get_interrupt,
 		.update_transfer_unit = dp_catalog_ctrl_update_transfer_unit,
+		.read_hdcp_status     = dp_catalog_ctrl_read_hdcp_status,
 	};
 	struct dp_catalog_audio audio = {
 		.acr_ctrl      = dp_catalog_audio_acr_ctrl,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index c9916c72..7fde025 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -43,7 +43,10 @@
 	int (*write_trans)(struct dp_catalog_aux *aux);
 	void (*reset)(struct dp_catalog_aux *aux);
 	void (*enable)(struct dp_catalog_aux *aux, bool enable);
-	void (*setup)(struct dp_catalog_aux *aux, u32 *aux_cfg);
+	void (*update_aux_cfg)(struct dp_catalog_aux *aux,
+		struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type);
+	void (*setup)(struct dp_catalog_aux *aux,
+			struct dp_aux_cfg *aux_cfg);
 	void (*get_irq)(struct dp_catalog_aux *aux, bool cmd_busy);
 };
 
@@ -71,6 +74,7 @@
 				u8 p_level);
 	void (*get_interrupt)(struct dp_catalog_ctrl *ctrl);
 	void (*update_transfer_unit)(struct dp_catalog_ctrl *ctrl);
+	u32 (*read_hdcp_status)(struct dp_catalog_ctrl *ctrl);
 };
 
 struct dp_catalog_audio {
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index b45cf4d..b4dafe4 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -20,6 +20,7 @@
 #include <linux/debugfs.h>
 #include <linux/component.h>
 #include <linux/of_irq.h>
+#include <linux/hdcp_qseecom.h>
 
 #include "msm_drv.h"
 #include "dp_usbpd.h"
@@ -31,9 +32,25 @@
 #include "dp_panel.h"
 #include "dp_ctrl.h"
 #include "dp_display.h"
+#include "sde_hdcp.h"
 
 static struct dp_display *g_dp_display;
 
+struct dp_hdcp {
+	void *data;
+	struct sde_hdcp_ops *ops;
+
+	void *hdcp1;
+	void *hdcp2;
+
+	int enc_lvl;
+
+	bool auth_state;
+	bool hdcp1_present;
+	bool hdcp2_present;
+	bool feature_enabled;
+};
+
 struct dp_display_private {
 	char *name;
 	int irq;
@@ -55,10 +72,16 @@
 	struct dp_link    *link;
 	struct dp_panel   *panel;
 	struct dp_ctrl    *ctrl;
+	struct dp_hdcp hdcp;
 
 	struct dp_usbpd_cb usbpd_cb;
 	struct dp_display_mode mode;
 	struct dp_display dp_display;
+
+	struct workqueue_struct *hdcp_workqueue;
+	struct delayed_work hdcp_cb_work;
+	struct mutex hdcp_mutex;
+	int hdcp_status;
 };
 
 static const struct of_device_id dp_dt_match[] = {
@@ -66,6 +89,13 @@
 	{}
 };
 
+static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp)
+{
+	return dp->hdcp.feature_enabled &&
+		(dp->hdcp.hdcp1_present || dp->hdcp.hdcp2_present) &&
+		dp->hdcp.ops;
+}
+
 static irqreturn_t dp_display_irq(int irq, void *dev_id)
 {
 	struct dp_display_private *dp = dev_id;
@@ -81,6 +111,12 @@
 	/* DP aux isr */
 	dp->aux->isr(dp->aux);
 
+	/* HDCP isr */
+	if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->isr) {
+		if (dp->hdcp.ops->isr(dp->hdcp.data))
+			pr_err("dp_hdcp_isr failed\n");
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -158,6 +194,213 @@
 	return 0;
 }
 
+static void dp_display_hdcp_cb_work(struct work_struct *work)
+{
+	struct dp_display_private *dp;
+	struct delayed_work *dw = to_delayed_work(work);
+	struct sde_hdcp_ops *ops;
+	int rc = 0;
+	u32 hdcp_auth_state;
+
+	dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
+
+	rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl);
+	if (rc >= 0) {
+		hdcp_auth_state = (rc >> 20) & 0x3;
+		pr_debug("hdcp auth state %d\n", hdcp_auth_state);
+	}
+
+	ops = dp->hdcp.ops;
+
+	switch (dp->hdcp_status) {
+	case HDCP_STATE_AUTHENTICATING:
+		pr_debug("start authenticaton\n");
+
+		if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
+			rc = dp->hdcp.ops->authenticate(dp->hdcp.data);
+
+		break;
+	case HDCP_STATE_AUTHENTICATED:
+		pr_debug("hdcp authenticated\n");
+		dp->hdcp.auth_state = true;
+		break;
+	case HDCP_STATE_AUTH_FAIL:
+		dp->hdcp.auth_state = false;
+
+		if (dp->power_on) {
+			pr_debug("Reauthenticating\n");
+			if (ops && ops->reauthenticate) {
+				rc = ops->reauthenticate(dp->hdcp.data);
+				if (rc)
+					pr_err("reauth failed rc=%d\n", rc);
+			}
+		} else {
+			pr_debug("not reauthenticating, cable disconnected\n");
+		}
+
+		break;
+	default:
+		break;
+	}
+}
+
+static void dp_display_notify_hdcp_status_cb(void *ptr,
+		enum sde_hdcp_states status)
+{
+	struct dp_display_private *dp = ptr;
+
+	if (!dp) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	dp->hdcp_status = status;
+
+	if (dp->dp_display.is_connected)
+		queue_delayed_work(dp->hdcp_workqueue, &dp->hdcp_cb_work, HZ/4);
+}
+
+static int dp_display_create_hdcp_workqueue(struct dp_display_private *dp)
+{
+	dp->hdcp_workqueue = create_workqueue("sdm_dp_hdcp");
+	if (IS_ERR_OR_NULL(dp->hdcp_workqueue)) {
+		pr_err("Error creating hdcp_workqueue\n");
+		return -EPERM;
+	}
+
+	INIT_DELAYED_WORK(&dp->hdcp_cb_work, dp_display_hdcp_cb_work);
+
+	return 0;
+}
+
+static void dp_display_destroy_hdcp_workqueue(struct dp_display_private *dp)
+{
+	if (dp->hdcp_workqueue)
+		destroy_workqueue(dp->hdcp_workqueue);
+}
+
+static void dp_display_update_hdcp_info(struct dp_display_private *dp)
+{
+	void *fd = NULL;
+	struct sde_hdcp_ops *ops = NULL;
+
+	if (!dp) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (!dp->hdcp.feature_enabled) {
+		pr_debug("feature not enabled\n");
+		return;
+	}
+
+	fd = dp->hdcp.hdcp2;
+	if (fd)
+		ops = sde_dp_hdcp2p2_start(fd);
+
+	if (ops && ops->feature_supported)
+		dp->hdcp.hdcp2_present = ops->feature_supported(fd);
+	else
+		dp->hdcp.hdcp2_present = false;
+
+	pr_debug("hdcp2p2: %s\n",
+			dp->hdcp.hdcp2_present ? "supported" : "not supported");
+
+	if (!dp->hdcp.hdcp2_present) {
+		dp->hdcp.hdcp1_present = hdcp1_check_if_supported_load_app();
+
+		if (dp->hdcp.hdcp1_present) {
+			fd = dp->hdcp.hdcp1;
+			ops = sde_hdcp_1x_start(fd);
+		}
+	}
+
+	pr_debug("hdcp1x: %s\n",
+			dp->hdcp.hdcp1_present ? "supported" : "not supported");
+
+	if (dp->hdcp.hdcp2_present || dp->hdcp.hdcp1_present) {
+		dp->hdcp.data = fd;
+		dp->hdcp.ops = ops;
+	} else {
+		dp->hdcp.data = NULL;
+		dp->hdcp.ops = NULL;
+	}
+}
+
+static void dp_display_deinitialize_hdcp(struct dp_display_private *dp)
+{
+	if (!dp) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	sde_dp_hdcp2p2_deinit(dp->hdcp.data);
+	dp_display_destroy_hdcp_workqueue(dp);
+	if (&dp->hdcp_mutex)
+		mutex_destroy(&dp->hdcp_mutex);
+}
+
+static int dp_display_initialize_hdcp(struct dp_display_private *dp)
+{
+	struct sde_hdcp_init_data hdcp_init_data;
+	struct resource *res;
+	int rc = 0;
+
+	if (!dp) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&dp->hdcp_mutex);
+
+	rc = dp_display_create_hdcp_workqueue(dp);
+	if (rc) {
+		pr_err("Failed to create HDCP workqueue\n");
+		goto error;
+	}
+
+	res = platform_get_resource_byname(dp->pdev,
+		IORESOURCE_MEM, "dp_ctrl");
+	if (!res) {
+		pr_err("Error getting dp ctrl resource\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	hdcp_init_data.phy_addr      = res->start;
+	hdcp_init_data.client_id     = HDCP_CLIENT_DP;
+	hdcp_init_data.drm_aux       = dp->aux->drm_aux;
+	hdcp_init_data.cb_data       = (void *)dp;
+	hdcp_init_data.workq         = dp->hdcp_workqueue;
+	hdcp_init_data.mutex         = &dp->hdcp_mutex;
+	hdcp_init_data.sec_access    = true;
+	hdcp_init_data.notify_status = dp_display_notify_hdcp_status_cb;
+	hdcp_init_data.core_io       = &dp->parser->io.ctrl_io;
+	hdcp_init_data.qfprom_io     = &dp->parser->io.qfprom_io;
+	hdcp_init_data.hdcp_io       = &dp->parser->io.hdcp_io;
+	hdcp_init_data.revision      = &dp->panel->link_info.revision;
+
+	dp->hdcp.hdcp1 = sde_hdcp_1x_init(&hdcp_init_data);
+	if (IS_ERR_OR_NULL(dp->hdcp.hdcp1)) {
+		pr_err("Error initializing HDCP 1.x\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	pr_debug("HDCP 1.3 initialized\n");
+
+	dp->hdcp.hdcp2 = sde_dp_hdcp2p2_init(&hdcp_init_data);
+	if (!IS_ERR_OR_NULL(dp->hdcp.hdcp2))
+		pr_debug("HDCP 2.2 initialized\n");
+
+	dp->hdcp.feature_enabled = true;
+
+	return 0;
+error:
+	dp_display_deinitialize_hdcp(dp);
+	return rc;
+}
+
 static int dp_display_bind(struct device *dev, struct device *master,
 		void *data)
 {
@@ -215,6 +458,12 @@
 		pr_err("Power client create failed\n");
 		goto end;
 	}
+
+	rc = dp_display_initialize_hdcp(dp);
+	if (rc) {
+		pr_err("HDCP initialization failed\n");
+		goto end;
+	}
 end:
 	return rc;
 }
@@ -240,6 +489,7 @@
 	(void)dp->panel->sde_edid_deregister(dp->panel);
 	(void)dp->aux->drm_aux_deregister(dp->aux);
 	(void)dp_display_debugfs_deinit(dp);
+	dp_display_deinitialize_hdcp(dp);
 }
 
 static const struct component_ops dp_display_comp_ops = {
@@ -252,13 +502,10 @@
 	int rc = 0;
 	u32 max_pclk_from_edid = 0;
 
-	rc = dp->panel->read_dpcd(dp->panel);
+	rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector);
 	if (rc)
 		return rc;
 
-	sde_get_edid(dp->dp_display.connector, &dp->aux->drm_aux->ddc,
-		(void **)&dp->panel->edid_ctrl);
-
 	max_pclk_from_edid = dp->panel->get_max_pclk(dp->panel);
 
 	dp->dp_display.max_pclk_khz = min(max_pclk_from_edid,
@@ -313,6 +560,11 @@
 	/* cancel any pending request */
 	dp->ctrl->abort(dp->ctrl);
 
+	if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->off) {
+		cancel_delayed_work_sync(&dp->hdcp_cb_work);
+		dp->hdcp.ops->off(dp->hdcp.data);
+	}
+
 	dp->dp_display.is_connected = false;
 	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
 
@@ -408,6 +660,12 @@
 
 	if (dp->usbpd->hpd_irq) {
 		dp->hpd_irq_on = true;
+
+		if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) {
+			if (!dp->hdcp.ops->cp_irq(dp->hdcp.data))
+				goto end;
+		}
+
 		rc = dp->link->process_request(dp->link);
 		dp->hpd_irq_on = false;
 		if (!rc)
@@ -468,7 +726,7 @@
 		goto err;
 	}
 
-	dp->aux = dp_aux_get(dev, &dp->catalog->aux);
+	dp->aux = dp_aux_get(dev, &dp->catalog->aux, dp->parser->aux_cfg);
 	if (IS_ERR(dp->aux)) {
 		rc = PTR_ERR(dp->aux);
 		pr_err("failed to initialize aux, rc = %d\n", rc);
@@ -564,6 +822,16 @@
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
 	complete_all(&dp->notification_comp);
+
+	dp_display_update_hdcp_info(dp);
+
+	if (dp_display_is_hdcp_enabled(dp)) {
+		cancel_delayed_work_sync(&dp->hdcp_cb_work);
+
+		dp->hdcp_status = HDCP_STATE_AUTHENTICATING;
+		queue_delayed_work(dp->hdcp_workqueue,
+				&dp->hdcp_cb_work, HZ / 2);
+	}
 end:
 	return rc;
 }
@@ -581,6 +849,14 @@
 
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
+	if (dp_display_is_hdcp_enabled(dp)) {
+		dp->hdcp_status = HDCP_STATE_INACTIVE;
+
+		cancel_delayed_work_sync(&dp->hdcp_cb_work);
+		if (dp->hdcp.ops->off)
+			dp->hdcp.ops->off(dp->hdcp.data);
+	}
+
 	dp->ctrl->push_idle(dp->ctrl);
 error:
 	return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 91aafdd..c388048 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -296,24 +296,30 @@
 	return 0;
 }
 
-int dp_connector_get_topology(const struct drm_display_mode *drm_mode,
-	struct msm_display_topology *topology, u32 max_mixer_width)
+int dp_connector_get_mode_info(const struct drm_display_mode *drm_mode,
+	struct msm_mode_info *mode_info, u32 max_mixer_width)
 {
 	const u32 dual_lm = 2;
 	const u32 single_lm = 1;
 	const u32 single_intf = 1;
 	const u32 no_enc = 0;
+	struct msm_display_topology *topology;
 
-	if (!drm_mode || !topology || !max_mixer_width) {
+	if (!drm_mode || !mode_info || !max_mixer_width) {
 		pr_err("invalid params\n");
 		return -EINVAL;
 	}
 
+	topology = &mode_info->topology;
 	topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ?
 							dual_lm : single_lm;
 	topology->num_enc = no_enc;
 	topology->num_intf = single_intf;
 
+	mode_info->frame_rate = drm_mode->vrefresh;
+	mode_info->vtotal = drm_mode->vtotal;
+	mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
+
 	return 0;
 }
 
@@ -331,7 +337,6 @@
 	info->num_of_h_tiles = 1;
 	info->h_tile_instance[0] = 0;
 	info->is_connected = display->is_connected;
-	info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
 	info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID |
 		MSM_DISPLAY_CAP_HOT_PLUG;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index bef3758..5918df1 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -74,14 +74,14 @@
 		void *display);
 
 /**
- * dp_connector_get_topology - retrieve current topology for the mode selected
+ * dp_connector_get_mode_info - retrieve information of the mode selected
  * @drm_mode: Display mode set for the display
- * @topology: Out parameter. Topology for the mode.
+ * @mode_info: Out parameter. Information of the mode
  * @max_mixer_width: max width supported by HW layer mixer
  * Returns: zero on success
  */
-int dp_connector_get_topology(const struct drm_display_mode *drm_mode,
-		struct msm_display_topology *topology,
+int dp_connector_get_mode_info(const struct drm_display_mode *drm_mode,
+		struct msm_mode_info *mode_info,
 		u32 max_mixer_width);
 
 int dp_connector_get_info(struct msm_display_info *info, void *display);
diff --git a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
new file mode 100644
index 0000000..061acee
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
@@ -0,0 +1,925 @@
+/* Copyright (c) 2016-2017, 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)	"[dp-hdcp2p2] %s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/kthread.h>
+#include <linux/hdcp_qseecom.h>
+#include <drm/drm_dp_helper.h>
+
+#include "sde_hdcp.h"
+
+#define DP_INTR_STATUS2				(0x00000024)
+#define DP_INTR_STATUS3				(0x00000028)
+#define dp_read(offset) readl_relaxed((offset))
+#define dp_write(offset, data) writel_relaxed((data), (offset))
+
+enum dp_hdcp2p2_sink_status {
+	SINK_DISCONNECTED,
+	SINK_CONNECTED
+};
+
+enum dp_auth_status {
+	DP_HDCP_AUTH_STATUS_FAILURE,
+	DP_HDCP_AUTH_STATUS_SUCCESS
+};
+
+struct dp_hdcp2p2_ctrl {
+	atomic_t auth_state;
+	enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */
+	struct dp_hdcp2p2_interrupts *intr;
+	struct sde_hdcp_init_data init_data;
+	struct mutex mutex; /* mutex to protect access to ctrl */
+	struct mutex msg_lock; /* mutex to protect access to msg buffer */
+	struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/
+	struct sde_hdcp_ops *ops;
+	void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */
+	struct hdcp_txmtr_ops *lib; /* Ops for driver to call into TZ */
+	enum hdcp_wakeup_cmd wakeup_cmd;
+	enum dp_auth_status auth_status;
+
+	struct task_struct *thread;
+	struct kthread_worker worker;
+	struct kthread_work status;
+	struct kthread_work auth;
+	struct kthread_work send_msg;
+	struct kthread_work recv_msg;
+	struct kthread_work link;
+	char *msg_buf;
+	uint32_t send_msg_len; /* length of all parameters in msg */
+	uint32_t timeout;
+	uint32_t num_messages;
+	struct hdcp_msg_part msg_part[HDCP_MAX_MESSAGE_PARTS];
+	u8 sink_rx_status;
+	u8 rx_status;
+	char abort_mask;
+
+	bool cp_irq_done;
+	bool polling;
+};
+
+struct dp_hdcp2p2_int_set {
+	u32 interrupt;
+	char *name;
+	void (*func)(struct dp_hdcp2p2_ctrl *ctrl);
+};
+
+struct dp_hdcp2p2_interrupts {
+	u32 reg;
+	struct dp_hdcp2p2_int_set *int_set;
+};
+
+static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	if (ctrl->wakeup_cmd == HDCP_WKUP_CMD_AUTHENTICATE)
+		return true;
+
+	if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE)
+		return true;
+
+	return false;
+}
+
+static int dp_hdcp2p2_copy_buf(struct dp_hdcp2p2_ctrl *ctrl,
+	struct hdcp_wakeup_data *data)
+{
+	int i = 0;
+
+	if (!data || !data->message_data)
+		return 0;
+
+	mutex_lock(&ctrl->msg_lock);
+
+	ctrl->timeout = data->timeout;
+	ctrl->num_messages = data->message_data->num_messages;
+	ctrl->send_msg_len = 0; /* Total len of all messages */
+
+	for (i = 0; i < ctrl->num_messages ; i++)
+		ctrl->send_msg_len += data->message_data->messages[i].length;
+
+	memcpy(ctrl->msg_part, data->message_data->messages,
+		sizeof(data->message_data->messages));
+
+	ctrl->rx_status = data->message_data->rx_status;
+	ctrl->abort_mask = data->abort_mask;
+
+	if (!data->send_msg_len) {
+		mutex_unlock(&ctrl->msg_lock);
+		return 0;
+	}
+
+	kzfree(ctrl->msg_buf);
+
+	ctrl->msg_buf = kzalloc(ctrl->send_msg_len, GFP_KERNEL);
+
+	if (!ctrl->msg_buf) {
+		mutex_unlock(&ctrl->msg_lock);
+		return -ENOMEM;
+	}
+
+	/* ignore first byte as it contains message id */
+	memcpy(ctrl->msg_buf, data->send_msg_buf + 1, ctrl->send_msg_len);
+
+	mutex_unlock(&ctrl->msg_lock);
+
+	return 0;
+}
+
+static int dp_hdcp2p2_wakeup(struct hdcp_wakeup_data *data)
+{
+	struct dp_hdcp2p2_ctrl *ctrl;
+	u32 const default_timeout_us = 500;
+
+	if (!data) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	ctrl = data->context;
+	if (!ctrl) {
+		pr_err("invalid ctrl\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ctrl->wakeup_mutex);
+
+	ctrl->wakeup_cmd = data->cmd;
+
+	if (data->timeout)
+		ctrl->timeout = (data->timeout) * 2;
+	else
+		ctrl->timeout = default_timeout_us;
+
+	if (!dp_hdcp2p2_is_valid_state(ctrl)) {
+		pr_err("invalid state\n");
+		goto exit;
+	}
+
+	if (dp_hdcp2p2_copy_buf(ctrl, data))
+		goto exit;
+
+	if (ctrl->wakeup_cmd == HDCP_WKUP_CMD_STATUS_SUCCESS)
+		ctrl->auth_status = DP_HDCP_AUTH_STATUS_SUCCESS;
+	else if (ctrl->wakeup_cmd == HDCP_WKUP_CMD_STATUS_FAILED)
+		ctrl->auth_status = DP_HDCP_AUTH_STATUS_FAILURE;
+
+	switch (ctrl->wakeup_cmd) {
+	case HDCP_WKUP_CMD_SEND_MESSAGE:
+		kthread_queue_work(&ctrl->worker, &ctrl->send_msg);
+		break;
+	case HDCP_WKUP_CMD_RECV_MESSAGE:
+		kthread_queue_work(&ctrl->worker, &ctrl->recv_msg);
+		break;
+	case HDCP_WKUP_CMD_STATUS_SUCCESS:
+	case HDCP_WKUP_CMD_STATUS_FAILED:
+		kthread_queue_work(&ctrl->worker, &ctrl->status);
+		break;
+	case HDCP_WKUP_CMD_LINK_POLL:
+		if (ctrl->cp_irq_done)
+			kthread_queue_work(&ctrl->worker, &ctrl->recv_msg);
+		else
+			ctrl->polling = true;
+		break;
+	case HDCP_WKUP_CMD_AUTHENTICATE:
+		kthread_queue_work(&ctrl->worker, &ctrl->auth);
+		break;
+	default:
+		pr_err("invalid wakeup command %d\n", ctrl->wakeup_cmd);
+	}
+exit:
+	mutex_unlock(&ctrl->wakeup_mutex);
+
+	return 0;
+}
+
+static inline void dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl,
+	struct hdcp_lib_wakeup_data *data)
+{
+	int rc = 0;
+
+	if (ctrl && ctrl->lib && ctrl->lib->wakeup &&
+		data && (data->cmd != HDCP_LIB_WKUP_CMD_INVALID)) {
+		rc = ctrl->lib->wakeup(data);
+		if (rc)
+			pr_err("error sending %s to lib\n",
+				hdcp_lib_cmd_to_str(data->cmd));
+	}
+}
+
+static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	ctrl->sink_status = SINK_DISCONNECTED;
+	atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
+}
+
+static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable)
+{
+	void __iomem *base = ctrl->init_data.core_io->base;
+	struct dp_hdcp2p2_interrupts *intr = ctrl->intr;
+
+	while (intr && intr->reg) {
+		struct dp_hdcp2p2_int_set *int_set = intr->int_set;
+		u32 interrupts = 0;
+
+		while (int_set && int_set->interrupt) {
+			interrupts |= int_set->interrupt;
+			int_set++;
+		}
+
+		if (enable)
+			dp_write(base + intr->reg,
+				dp_read(base + intr->reg) | interrupts);
+		else
+			dp_write(base + intr->reg,
+				dp_read(base + intr->reg) & ~interrupts);
+		intr++;
+	}
+}
+
+static void dp_hdcp2p2_off(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
+	struct hdcp_wakeup_data cdata = {HDCP_WKUP_CMD_AUTHENTICATE};
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("hdcp is off\n");
+		return;
+	}
+
+	dp_hdcp2p2_set_interrupts(ctrl, false);
+
+	dp_hdcp2p2_reset(ctrl);
+
+	kthread_flush_worker(&ctrl->worker);
+
+	cdata.context = input;
+	dp_hdcp2p2_wakeup(&cdata);
+}
+
+static int dp_hdcp2p2_authenticate(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+	struct hdcp_wakeup_data cdata = {HDCP_WKUP_CMD_AUTHENTICATE};
+	int rc = 0;
+
+	kthread_flush_worker(&ctrl->worker);
+
+	dp_hdcp2p2_set_interrupts(ctrl, true);
+
+	ctrl->sink_status = SINK_CONNECTED;
+	atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING);
+
+	cdata.context = input;
+	dp_hdcp2p2_wakeup(&cdata);
+
+	return rc;
+}
+
+static int dp_hdcp2p2_reauthenticate(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	dp_hdcp2p2_reset((struct dp_hdcp2p2_ctrl *)input);
+
+	return  dp_hdcp2p2_authenticate(input);
+}
+
+static void dp_hdcp2p2_min_level_change(void *client_ctx,
+		int min_enc_level)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)client_ctx;
+	struct hdcp_lib_wakeup_data cdata = {
+		HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE};
+	bool enc_notify = true;
+	int enc_lvl;
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	switch (min_enc_level) {
+	case 0:
+		enc_lvl = HDCP_STATE_AUTH_ENC_NONE;
+		break;
+	case 1:
+		enc_lvl = HDCP_STATE_AUTH_ENC_1X;
+		break;
+	case 2:
+		enc_lvl = HDCP_STATE_AUTH_ENC_2P2;
+		break;
+	default:
+		enc_notify = false;
+	}
+
+	pr_debug("enc level changed %d\n", min_enc_level);
+
+	cdata.context = ctrl->lib_ctx;
+	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+
+	if (enc_notify && ctrl->init_data.notify_status)
+		ctrl->init_data.notify_status(ctrl->init_data.cb_data, enc_lvl);
+}
+
+static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	dp_hdcp2p2_set_interrupts(ctrl, false);
+
+	atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
+
+	/* notify DP about HDCP failure */
+	ctrl->init_data.notify_status(ctrl->init_data.cb_data,
+		HDCP_STATE_AUTH_FAIL);
+}
+
+static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl,
+	u8 *buf, int size, int offset, u32 timeout)
+{
+	int const max_size = 16;
+	int rc = 0, read_size = 0, bytes_read = 0;
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("hdcp is off\n");
+		return -EINVAL;
+	}
+
+	do {
+		read_size = min(size, max_size);
+
+		bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
+				offset, buf, read_size);
+		if (bytes_read != read_size) {
+			pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
+					offset, read_size, bytes_read);
+			break;
+		}
+
+		buf += read_size;
+		offset += read_size;
+		size -= read_size;
+	} while (size > 0);
+
+	return rc;
+}
+
+static int dp_hdcp2p2_aux_write_message(struct dp_hdcp2p2_ctrl *ctrl,
+	u8 *buf, int size, uint offset, uint timeout)
+{
+	int const max_size = 16;
+	int rc = 0, write_size = 0, bytes_written = 0;
+
+	do {
+		write_size = min(size, max_size);
+
+		bytes_written = drm_dp_dpcd_write(ctrl->init_data.drm_aux,
+				offset, buf, write_size);
+		if (bytes_written != write_size) {
+			pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
+					offset, write_size, bytes_written);
+			break;
+		}
+
+		buf += write_size;
+		offset += write_size;
+		size -= write_size;
+	} while (size > 0);
+
+	return rc;
+}
+
+static bool dp_hdcp2p2_feature_supported(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+	struct hdcp_txmtr_ops *lib = NULL;
+	bool supported = false;
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		goto end;
+	}
+
+	lib = ctrl->lib;
+	if (!lib) {
+		pr_err("invalid lib ops data\n");
+		goto end;
+	}
+
+	if (lib->feature_supported)
+		supported = lib->feature_supported(
+			ctrl->lib_ctx);
+end:
+	return supported;
+}
+
+static void dp_hdcp2p2_send_msg_work(struct kthread_work *work)
+{
+	int rc = 0;
+	struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
+		struct dp_hdcp2p2_ctrl, send_msg);
+	struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	cdata.context = ctrl->lib_ctx;
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("hdcp is off\n");
+		goto exit;
+	}
+
+	mutex_lock(&ctrl->msg_lock);
+
+	rc = dp_hdcp2p2_aux_write_message(ctrl, ctrl->msg_buf,
+			ctrl->send_msg_len, ctrl->msg_part->offset,
+			ctrl->timeout);
+	if (rc) {
+		pr_err("Error sending msg to sink %d\n", rc);
+		mutex_unlock(&ctrl->msg_lock);
+		goto exit;
+	}
+
+	cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS;
+	cdata.timeout = ctrl->timeout;
+	mutex_unlock(&ctrl->msg_lock);
+
+exit:
+	if (rc == -ETIMEDOUT)
+		cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
+	else if (rc)
+		cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED;
+
+	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+}
+
+static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	int rc = 0;
+	char *recvd_msg_buf = NULL;
+	struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID };
+
+	cdata.context = ctrl->lib_ctx;
+
+	recvd_msg_buf = kzalloc(ctrl->send_msg_len, GFP_KERNEL);
+	if (!recvd_msg_buf) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	rc = dp_hdcp2p2_aux_read_message(ctrl, recvd_msg_buf,
+		ctrl->send_msg_len, ctrl->msg_part->offset,
+		ctrl->timeout);
+	if (rc) {
+		pr_err("error reading message %d\n", rc);
+		goto exit;
+	}
+
+	cdata.recvd_msg_buf = recvd_msg_buf;
+	cdata.recvd_msg_len = ctrl->send_msg_len;
+	cdata.timeout = ctrl->timeout;
+exit:
+	if (rc == -ETIMEDOUT)
+		cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
+	else if (rc)
+		cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED;
+	else
+		cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS;
+
+	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+	kfree(recvd_msg_buf);
+
+	return rc;
+}
+
+static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work)
+{
+	struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID };
+	struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
+		struct dp_hdcp2p2_ctrl, recv_msg);
+
+	cdata.context = ctrl->lib_ctx;
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("hdcp is off\n");
+		return;
+	}
+
+	if (ctrl->rx_status) {
+		if (!ctrl->cp_irq_done) {
+			pr_debug("waiting for CP_IRQ\n");
+			ctrl->polling = true;
+			return;
+		}
+
+		if (ctrl->rx_status & ctrl->sink_rx_status) {
+			ctrl->cp_irq_done = false;
+			ctrl->sink_rx_status = 0;
+			ctrl->rx_status = 0;
+		}
+	}
+
+	dp_hdcp2p2_get_msg_from_sink(ctrl);
+}
+
+static void dp_hdcp2p2_auth_status_work(struct kthread_work *work)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
+		struct dp_hdcp2p2_ctrl, status);
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("hdcp is off\n");
+		return;
+	}
+
+	if (ctrl->auth_status == DP_HDCP_AUTH_STATUS_SUCCESS) {
+		ctrl->init_data.notify_status(ctrl->init_data.cb_data,
+			HDCP_STATE_AUTHENTICATED);
+
+		atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED);
+	} else {
+		dp_hdcp2p2_auth_failed(ctrl);
+	}
+}
+
+static void dp_hdcp2p2_link_work(struct kthread_work *work)
+{
+	int rc = 0;
+	struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
+		struct dp_hdcp2p2_ctrl, link);
+	struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
+		atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("invalid hdcp state\n");
+		return;
+	}
+
+	cdata.context = ctrl->lib_ctx;
+
+	if (ctrl->sink_rx_status & ctrl->abort_mask) {
+		if (ctrl->sink_rx_status & BIT(3))
+			pr_err("reauth_req set by sink\n");
+
+		if (ctrl->sink_rx_status & BIT(4))
+			pr_err("link failure reported by sink\n");
+
+		ctrl->sink_rx_status = 0;
+		ctrl->rx_status = 0;
+
+		rc = -ENOLINK;
+
+		cdata.cmd = HDCP_LIB_WKUP_CMD_LINK_FAILED;
+		atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
+		goto exit;
+	}
+
+	if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) {
+		ctrl->sink_rx_status = 0;
+		ctrl->rx_status = 0;
+
+		dp_hdcp2p2_get_msg_from_sink(ctrl);
+
+		ctrl->polling = false;
+	} else {
+		ctrl->cp_irq_done = true;
+	}
+exit:
+	if (rc)
+		dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+}
+
+static void dp_hdcp2p2_auth_work(struct kthread_work *work)
+{
+	struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
+	struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
+		struct dp_hdcp2p2_ctrl, auth);
+
+	cdata.context = ctrl->lib_ctx;
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING)
+		cdata.cmd = HDCP_LIB_WKUP_CMD_START;
+	else
+		cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
+
+	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+}
+
+static int dp_hdcp2p2_read_rx_status(struct dp_hdcp2p2_ctrl *ctrl,
+		u8 *rx_status)
+{
+	u32 const cp_irq_dpcd_offset = 0x201;
+	u32 const rxstatus_dpcd_offset = 0x69493;
+	ssize_t const bytes_to_read = 1;
+	ssize_t bytes_read = 0;
+	u8 buf = 0;
+	int rc = 0;
+	bool cp_irq = 0;
+
+	*rx_status = 0;
+
+	bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
+			cp_irq_dpcd_offset, &buf, bytes_to_read);
+	if (bytes_read != bytes_to_read) {
+		pr_err("cp irq read failed\n");
+		rc = bytes_read;
+		goto error;
+	}
+
+	cp_irq = buf & BIT(2);
+	pr_debug("cp_irq=0x%x\n", cp_irq);
+	buf = 0;
+
+	if (cp_irq) {
+		bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
+				rxstatus_dpcd_offset, &buf, bytes_to_read);
+		if (bytes_read != bytes_to_read) {
+			pr_err("rxstatus read failed\n");
+			rc = bytes_read;
+			goto error;
+		}
+		*rx_status = buf;
+		pr_debug("rx_status=0x%x\n", *rx_status);
+	}
+
+error:
+	return rc;
+}
+
+static int dp_hdcp2p2_cp_irq(void *input)
+{
+	int rc = 0;
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
+		atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+		pr_err("invalid hdcp state\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	ctrl->sink_rx_status = 0;
+	rc = dp_hdcp2p2_read_rx_status(ctrl, &ctrl->sink_rx_status);
+	if (rc) {
+		pr_err("failed to read rx status\n");
+		goto error;
+	}
+
+	pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status);
+
+	if (!ctrl->sink_rx_status) {
+		pr_debug("not a hdcp 2.2 irq\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	kthread_queue_work(&ctrl->worker, &ctrl->link);
+
+	return 0;
+error:
+	return rc;
+}
+
+static int dp_hdcp2p2_isr(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
+	int rc = 0;
+	struct dss_io_data *io;
+	struct dp_hdcp2p2_interrupts *intr;
+	u32 hdcp_int_val = 0;
+
+	if (!ctrl || !ctrl->init_data.core_io) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	io = ctrl->init_data.core_io;
+	intr = ctrl->intr;
+
+	while (intr && intr->reg) {
+		struct dp_hdcp2p2_int_set *int_set = intr->int_set;
+
+		hdcp_int_val = dp_read(io->base + intr->reg);
+
+		while (int_set && int_set->interrupt) {
+			if (hdcp_int_val & (int_set->interrupt >> 2)) {
+				pr_debug("%s\n", int_set->name);
+
+				if (int_set->func)
+					int_set->func(ctrl);
+
+				dp_write(io->base + intr->reg, hdcp_int_val |
+					(int_set->interrupt >> 1));
+			}
+			int_set++;
+		}
+		intr++;
+	}
+end:
+	return rc;
+}
+
+void sde_dp_hdcp2p2_deinit(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
+	struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
+
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
+	cdata.context = ctrl->lib_ctx;
+	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+
+	kthread_stop(ctrl->thread);
+
+	mutex_destroy(&ctrl->mutex);
+	mutex_destroy(&ctrl->msg_lock);
+	mutex_destroy(&ctrl->wakeup_mutex);
+	kzfree(ctrl->msg_buf);
+	kfree(ctrl);
+}
+
+void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
+{
+	int rc;
+	struct dp_hdcp2p2_ctrl *ctrl;
+	static struct hdcp_txmtr_ops txmtr_ops;
+	struct hdcp_register_data register_data;
+	static struct sde_hdcp_ops ops = {
+		.isr = dp_hdcp2p2_isr,
+		.reauthenticate = dp_hdcp2p2_reauthenticate,
+		.authenticate = dp_hdcp2p2_authenticate,
+		.feature_supported = dp_hdcp2p2_feature_supported,
+		.off = dp_hdcp2p2_off,
+		.cp_irq = dp_hdcp2p2_cp_irq,
+	};
+
+	static struct hdcp_client_ops client_ops = {
+		.wakeup = dp_hdcp2p2_wakeup,
+		.notify_lvl_change = dp_hdcp2p2_min_level_change,
+	};
+	static struct dp_hdcp2p2_int_set int_set1[] = {
+		{BIT(17), "authentication successful", NULL},
+		{BIT(20), "authentication failed", NULL},
+		{BIT(24), "encryption enabled", NULL},
+		{BIT(27), "encryption disabled", NULL},
+		{0},
+	};
+	static struct dp_hdcp2p2_int_set int_set2[] = {
+		{BIT(2),  "key fifo underflow", NULL},
+		{0},
+	};
+	static struct dp_hdcp2p2_interrupts intr[] = {
+		{DP_INTR_STATUS2, int_set1},
+		{DP_INTR_STATUS3, int_set2},
+		{0}
+	};
+
+	if (!init_data || !init_data->cb_data ||
+			!init_data->notify_status || !init_data->drm_aux) {
+		pr_err("invalid input\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return ERR_PTR(-ENOMEM);
+
+	ctrl->init_data = *init_data;
+	ctrl->lib = &txmtr_ops;
+	ctrl->msg_buf = NULL;
+
+	ctrl->sink_status = SINK_DISCONNECTED;
+	ctrl->intr = intr;
+
+	atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
+
+	ctrl->ops = &ops;
+	mutex_init(&ctrl->mutex);
+	mutex_init(&ctrl->msg_lock);
+	mutex_init(&ctrl->wakeup_mutex);
+
+	register_data.hdcp_ctx = &ctrl->lib_ctx;
+	register_data.client_ops = &client_ops;
+	register_data.txmtr_ops = &txmtr_ops;
+	register_data.device_type = HDCP_TXMTR_DP;
+	register_data.client_ctx = ctrl;
+
+	rc = hdcp_library_register(&register_data);
+	if (rc) {
+		pr_err("Unable to register with HDCP 2.2 library\n");
+		goto error;
+	}
+
+	kthread_init_worker(&ctrl->worker);
+
+	kthread_init_work(&ctrl->auth,     dp_hdcp2p2_auth_work);
+	kthread_init_work(&ctrl->send_msg, dp_hdcp2p2_send_msg_work);
+	kthread_init_work(&ctrl->recv_msg, dp_hdcp2p2_recv_msg_work);
+	kthread_init_work(&ctrl->status,   dp_hdcp2p2_auth_status_work);
+	kthread_init_work(&ctrl->link,     dp_hdcp2p2_link_work);
+
+	ctrl->thread = kthread_run(kthread_worker_fn,
+		&ctrl->worker, "dp_hdcp2p2");
+
+	if (IS_ERR(ctrl->thread)) {
+		pr_err("unable to start DP hdcp2p2 thread\n");
+		rc = PTR_ERR(ctrl->thread);
+		ctrl->thread = NULL;
+		goto error;
+	}
+
+	return ctrl;
+error:
+	kfree(ctrl);
+	return ERR_PTR(rc);
+}
+
+static bool dp_hdcp2p2_supported(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	u32 const rxcaps_dpcd_offset = 0x6921d;
+	ssize_t const bytes_to_read = 1;
+	ssize_t bytes_read = 0;
+	u8 buf = 0;
+
+	bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
+			rxcaps_dpcd_offset, &buf, bytes_to_read);
+	if (bytes_read != bytes_to_read) {
+		pr_err("RxCaps read failed\n");
+		goto error;
+	}
+
+	pr_debug("rxcaps 0x%x\n", buf);
+
+	if (buf & BIT(1))
+		return true;
+error:
+	return false;
+}
+
+struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+
+	pr_debug("Checking sink capability\n");
+	if (dp_hdcp2p2_supported(ctrl))
+		return ctrl->ops;
+	else
+		return NULL;
+}
+
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 5f25b2d..2e21033 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -28,6 +28,7 @@
 	struct dp_aux *aux;
 	struct dp_catalog_panel *catalog;
 	bool lane_switch_supported;
+	bool aux_cfg_update_done;
 };
 
 static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
@@ -80,11 +81,76 @@
 	return rc;
 }
 
+
+static int dp_panel_read_edid(struct dp_panel *dp_panel,
+	struct drm_connector *connector)
+{
+	int retry_cnt = 0;
+	const int max_retry = 10;
+	struct dp_panel_private *panel;
+
+	if (!dp_panel) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+
+	do {
+		sde_get_edid(connector, &panel->aux->drm_aux->ddc,
+			(void **)&dp_panel->edid_ctrl);
+		if (!dp_panel->edid_ctrl->edid) {
+			pr_err("EDID read failed\n");
+			retry_cnt++;
+			panel->aux->reconfig(panel->aux);
+			panel->aux_cfg_update_done = true;
+		} else {
+			return 0;
+		}
+	} while (retry_cnt < max_retry);
+
+	return -EINVAL;
+}
+
+static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
+	struct drm_connector *connector)
+{
+	int rc = 0;
+	struct dp_panel_private *panel;
+
+	if (!dp_panel || !connector) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+
+	rc = dp_panel_read_dpcd(dp_panel);
+	if (rc) {
+		pr_err("panel dpcd read failed\n");
+		return rc;
+	}
+
+	rc = dp_panel_read_edid(dp_panel, connector);
+	if (rc) {
+		pr_err("panel edid read failed\n");
+		return rc;
+	}
+
+	if (panel->aux_cfg_update_done) {
+		pr_debug("read DPCD with updated AUX config\n");
+		dp_panel_read_dpcd(dp_panel);
+		panel->aux_cfg_update_done = false;
+	}
+
+	return 0;
+}
+
 static u32 dp_panel_get_max_pclk(struct dp_panel *dp_panel)
 {
 	struct drm_dp_link *link_info;
 	const u8 num_components = 3;
-	u32 bpc, bpp, max_data_rate_khz, max_pclk_rate_khz;
+	u32 bpc = 0, bpp = 0, max_data_rate_khz = 0, max_pclk_rate_khz = 0;
 
 	if (!dp_panel) {
 		pr_err("invalid input\n");
@@ -290,12 +356,13 @@
 	panel->catalog = catalog;
 
 	dp_panel = &panel->dp_panel;
+	panel->aux_cfg_update_done = false;
 
 	dp_panel->sde_edid_register = dp_panel_edid_register;
 	dp_panel->sde_edid_deregister = dp_panel_edid_deregister;
 	dp_panel->init_info = dp_panel_init_panel_info;
 	dp_panel->timing_cfg = dp_panel_timing_cfg;
-	dp_panel->read_dpcd = dp_panel_read_dpcd;
+	dp_panel->read_sink_caps = dp_panel_read_sink_caps;
 	dp_panel->get_min_req_link_rate = dp_panel_get_min_req_link_rate;
 	dp_panel->get_max_pclk = dp_panel_get_max_pclk;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 6cca0f1..ab9a451 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -43,6 +43,7 @@
 	struct drm_dp_link link_info;
 
 	struct sde_edid_ctrl *edid_ctrl;
+	struct drm_connector *connector;
 	struct dp_panel_info pinfo;
 
 	u32 vic;
@@ -52,7 +53,8 @@
 	void (*sde_edid_deregister)(struct dp_panel *dp_panel);
 	int (*init_info)(struct dp_panel *dp_panel);
 	int (*timing_cfg)(struct dp_panel *dp_panel);
-	int (*read_dpcd)(struct dp_panel *dp_panel);
+	int (*read_sink_caps)(struct dp_panel *dp_panel,
+		struct drm_connector *connector);
 	u32 (*get_min_req_link_rate)(struct dp_panel *dp_panel);
 	u32 (*get_max_pclk)(struct dp_panel *dp_panel);
 };
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c
index e81bbb3..c85c2a2 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.c
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -101,23 +101,85 @@
 	return rc;
 }
 
+static const char *dp_get_phy_aux_config_property(u32 cfg_type)
+{
+	switch (cfg_type) {
+	case PHY_AUX_CFG0:
+		return "qcom,aux-cfg0-settings";
+	case PHY_AUX_CFG1:
+		return "qcom,aux-cfg1-settings";
+	case PHY_AUX_CFG2:
+		return "qcom,aux-cfg2-settings";
+	case PHY_AUX_CFG3:
+		return "qcom,aux-cfg3-settings";
+	case PHY_AUX_CFG4:
+		return "qcom,aux-cfg4-settings";
+	case PHY_AUX_CFG5:
+		return "qcom,aux-cfg5-settings";
+	case PHY_AUX_CFG6:
+		return "qcom,aux-cfg6-settings";
+	case PHY_AUX_CFG7:
+		return "qcom,aux-cfg7-settings";
+	case PHY_AUX_CFG8:
+		return "qcom,aux-cfg8-settings";
+	case PHY_AUX_CFG9:
+		return "qcom,aux-cfg9-settings";
+	default:
+		return "unknown";
+	}
+}
+
+static void dp_parser_phy_aux_cfg_reset(struct dp_parser *parser)
+{
+	int i = 0;
+
+	for (i = 0; i < PHY_AUX_CFG_MAX; i++)
+		parser->aux_cfg[i] = (const struct dp_aux_cfg){ 0 };
+}
+
 static int dp_parser_aux(struct dp_parser *parser)
 {
-	int len = 0, i = 0, rc = 0;
 	struct device_node *of_node = parser->pdev->dev.of_node;
+	int len = 0, i = 0, j = 0, config_count = 0;
 	const char *data;
+	int const minimum_config_count = 1;
 
-	data = of_get_property(of_node, "qcom,aux-cfg-settings", &len);
-	if (!data || (len != AUX_CFG_LEN)) {
-		pr_err("Unable to read DP AUX CFG settings\n");
-		rc = -EINVAL;
-		goto end;
+	for (i = 0; i < PHY_AUX_CFG_MAX; i++) {
+		const char *property = dp_get_phy_aux_config_property(i);
+
+		data = of_get_property(of_node, property, &len);
+		if (!data) {
+			pr_err("Unable to read %s\n", property);
+			goto error;
+		}
+
+		config_count = len - 1;
+		if ((config_count < minimum_config_count) ||
+			(config_count > DP_AUX_CFG_MAX_VALUE_CNT)) {
+			pr_err("Invalid config count (%d) configs for %s\n",
+					config_count, property);
+			goto error;
+		}
+
+		parser->aux_cfg[i].offset = data[0];
+		parser->aux_cfg[i].cfg_cnt = config_count;
+		pr_debug("%s offset=0x%x, cfg_cnt=%d\n",
+				property,
+				parser->aux_cfg[i].offset,
+				parser->aux_cfg[i].cfg_cnt);
+		for (j = 1; j < len; j++) {
+			parser->aux_cfg[i].lut[j - 1] = data[j];
+			pr_debug("%s lut[%d]=0x%x\n",
+					property,
+					i,
+					parser->aux_cfg[i].lut[j - 1]);
+		}
 	}
+		return 0;
 
-	for (i = 0; i < len; i++)
-		parser->aux_cfg[i] = data[i];
-end:
-	return rc;
+error:
+	dp_parser_phy_aux_cfg_reset(parser);
+	return -EINVAL;
 }
 
 static int dp_parser_misc(struct dp_parser *parser)
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h
index fdcdd3a..7794da5 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.h
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -93,6 +93,66 @@
 	struct pinctrl_state *state_suspend;
 };
 
+#define DP_ENUM_STR(x)	#x
+#define DP_AUX_CFG_MAX_VALUE_CNT 3
+/**
+ * struct dp_aux_cfg - DP's AUX configuration settings
+ *
+ * @cfg_cnt: count of the configurable settings for the AUX register
+ * @current_index: current index of the AUX config lut
+ * @offset: register offset of the AUX config register
+ * @lut: look up table for the AUX config values for this register
+ */
+struct dp_aux_cfg {
+	u32 cfg_cnt;
+	u32 current_index;
+	u32 offset;
+	u32 lut[DP_AUX_CFG_MAX_VALUE_CNT];
+};
+
+/* PHY AUX config registers */
+enum dp_phy_aux_config_type {
+	PHY_AUX_CFG0,
+	PHY_AUX_CFG1,
+	PHY_AUX_CFG2,
+	PHY_AUX_CFG3,
+	PHY_AUX_CFG4,
+	PHY_AUX_CFG5,
+	PHY_AUX_CFG6,
+	PHY_AUX_CFG7,
+	PHY_AUX_CFG8,
+	PHY_AUX_CFG9,
+	PHY_AUX_CFG_MAX,
+};
+
+static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type)
+{
+	switch (cfg_type) {
+	case PHY_AUX_CFG0:
+		return DP_ENUM_STR(PHY_AUX_CFG0);
+	case PHY_AUX_CFG1:
+		return DP_ENUM_STR(PHY_AUX_CFG1);
+	case PHY_AUX_CFG2:
+		return DP_ENUM_STR(PHY_AUX_CFG2);
+	case PHY_AUX_CFG3:
+		return DP_ENUM_STR(PHY_AUX_CFG3);
+	case PHY_AUX_CFG4:
+		return DP_ENUM_STR(PHY_AUX_CFG4);
+	case PHY_AUX_CFG5:
+		return DP_ENUM_STR(PHY_AUX_CFG5);
+	case PHY_AUX_CFG6:
+		return DP_ENUM_STR(PHY_AUX_CFG6);
+	case PHY_AUX_CFG7:
+		return DP_ENUM_STR(PHY_AUX_CFG7);
+	case PHY_AUX_CFG8:
+		return DP_ENUM_STR(PHY_AUX_CFG8);
+	case PHY_AUX_CFG9:
+		return DP_ENUM_STR(PHY_AUX_CFG9);
+	default:
+		return "unknown";
+	}
+}
+
 /**
  * struct dp_parser - DP parser's data exposed to clients
  *
@@ -111,7 +171,7 @@
 	struct dp_display_data disp_data;
 
 	u8 l_map[4];
-	u32 aux_cfg[AUX_CFG_LEN];
+	struct dp_aux_cfg aux_cfg[AUX_CFG_LEN];
 	u32 max_pclk_khz;
 
 	int (*parse)(struct dp_parser *parser);
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
new file mode 100644
index 0000000..30377a0
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2017, 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 _DP_REG_H_
+#define _DP_REG_H_
+
+/* DP_TX Registers */
+#define DP_HW_VERSION				(0x00000000)
+#define DP_SW_RESET				(0x00000010)
+#define DP_PHY_CTRL				(0x00000014)
+#define DP_CLK_CTRL				(0x00000018)
+#define DP_CLK_ACTIVE				(0x0000001C)
+#define DP_INTR_STATUS				(0x00000020)
+#define DP_INTR_STATUS2				(0x00000024)
+#define DP_INTR_STATUS3				(0x00000028)
+
+#define DP_DP_HPD_CTRL				(0x00000200)
+#define DP_DP_HPD_INT_STATUS			(0x00000204)
+#define DP_DP_HPD_INT_ACK			(0x00000208)
+#define DP_DP_HPD_INT_MASK			(0x0000020C)
+#define DP_DP_HPD_REFTIMER			(0x00000218)
+#define DP_DP_HPD_EVENT_TIME_0			(0x0000021C)
+#define DP_DP_HPD_EVENT_TIME_1			(0x00000220)
+#define DP_AUX_CTRL				(0x00000230)
+#define DP_AUX_DATA				(0x00000234)
+#define DP_AUX_TRANS_CTRL			(0x00000238)
+#define DP_TIMEOUT_COUNT			(0x0000023C)
+#define DP_AUX_LIMITS				(0x00000240)
+#define DP_AUX_STATUS				(0x00000244)
+
+#define DP_DPCD_CP_IRQ				(0x201)
+#define DP_DPCD_RXSTATUS			(0x69493)
+
+#define DP_INTERRUPT_TRANS_NUM			(0x000002A0)
+
+#define DP_MAINLINK_CTRL			(0x00000400)
+#define DP_STATE_CTRL				(0x00000404)
+#define DP_CONFIGURATION_CTRL			(0x00000408)
+#define DP_SOFTWARE_MVID			(0x00000410)
+#define DP_SOFTWARE_NVID			(0x00000418)
+#define DP_TOTAL_HOR_VER			(0x0000041C)
+#define DP_START_HOR_VER_FROM_SYNC		(0x00000420)
+#define DP_HSYNC_VSYNC_WIDTH_POLARITY		(0x00000424)
+#define DP_ACTIVE_HOR_VER			(0x00000428)
+#define DP_MISC1_MISC0				(0x0000042C)
+#define DP_VALID_BOUNDARY			(0x00000430)
+#define DP_VALID_BOUNDARY_2			(0x00000434)
+#define DP_LOGICAL2PHYSCIAL_LANE_MAPPING	(0x00000438)
+
+#define DP_MAINLINK_READY			(0x00000440)
+#define DP_MAINLINK_LEVELS			(0x00000444)
+#define DP_TU					(0x0000044C)
+
+#define DP_HBR2_COMPLIANCE_SCRAMBLER_RESET	(0x00000454)
+#define DP_TEST_80BIT_CUSTOM_PATTERN_REG0	(0x000004C0)
+#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1	(0x000004C4)
+#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2	(0x000004C8)
+
+#define MMSS_DP_MISC1_MISC0			(0x0000042C)
+#define MMSS_DP_AUDIO_TIMING_GEN		(0x00000480)
+#define MMSS_DP_AUDIO_TIMING_RBR_32		(0x00000484)
+#define MMSS_DP_AUDIO_TIMING_HBR_32		(0x00000488)
+#define MMSS_DP_AUDIO_TIMING_RBR_44		(0x0000048C)
+#define MMSS_DP_AUDIO_TIMING_HBR_44		(0x00000490)
+#define MMSS_DP_AUDIO_TIMING_RBR_48		(0x00000494)
+#define MMSS_DP_AUDIO_TIMING_HBR_48		(0x00000498)
+
+#define MMSS_DP_PSR_CRC_RG			(0x00000554)
+#define MMSS_DP_PSR_CRC_B			(0x00000558)
+
+#define MMSS_DP_AUDIO_CFG			(0x00000600)
+#define MMSS_DP_AUDIO_STATUS			(0x00000604)
+#define MMSS_DP_AUDIO_PKT_CTRL			(0x00000608)
+#define MMSS_DP_AUDIO_PKT_CTRL2			(0x0000060C)
+#define MMSS_DP_AUDIO_ACR_CTRL			(0x00000610)
+#define MMSS_DP_AUDIO_CTRL_RESET		(0x00000614)
+
+#define MMSS_DP_SDP_CFG				(0x00000628)
+#define MMSS_DP_SDP_CFG2			(0x0000062C)
+#define MMSS_DP_AUDIO_TIMESTAMP_0		(0x00000630)
+#define MMSS_DP_AUDIO_TIMESTAMP_1		(0x00000634)
+
+#define MMSS_DP_AUDIO_STREAM_0			(0x00000640)
+#define MMSS_DP_AUDIO_STREAM_1			(0x00000644)
+
+#define MMSS_DP_EXTENSION_0			(0x00000650)
+#define MMSS_DP_EXTENSION_1			(0x00000654)
+#define MMSS_DP_EXTENSION_2			(0x00000658)
+#define MMSS_DP_EXTENSION_3			(0x0000065C)
+#define MMSS_DP_EXTENSION_4			(0x00000660)
+#define MMSS_DP_EXTENSION_5			(0x00000664)
+#define MMSS_DP_EXTENSION_6			(0x00000668)
+#define MMSS_DP_EXTENSION_7			(0x0000066C)
+#define MMSS_DP_EXTENSION_8			(0x00000670)
+#define MMSS_DP_EXTENSION_9			(0x00000674)
+#define MMSS_DP_AUDIO_COPYMANAGEMENT_0		(0x00000678)
+#define MMSS_DP_AUDIO_COPYMANAGEMENT_1		(0x0000067C)
+#define MMSS_DP_AUDIO_COPYMANAGEMENT_2		(0x00000680)
+#define MMSS_DP_AUDIO_COPYMANAGEMENT_3		(0x00000684)
+#define MMSS_DP_AUDIO_COPYMANAGEMENT_4		(0x00000688)
+#define MMSS_DP_AUDIO_COPYMANAGEMENT_5		(0x0000068C)
+#define MMSS_DP_AUDIO_ISRC_0			(0x00000690)
+#define MMSS_DP_AUDIO_ISRC_1			(0x00000694)
+#define MMSS_DP_AUDIO_ISRC_2			(0x00000698)
+#define MMSS_DP_AUDIO_ISRC_3			(0x0000069C)
+#define MMSS_DP_AUDIO_ISRC_4			(0x000006A0)
+#define MMSS_DP_AUDIO_ISRC_5			(0x000006A4)
+#define MMSS_DP_AUDIO_INFOFRAME_0		(0x000006A8)
+#define MMSS_DP_AUDIO_INFOFRAME_1		(0x000006AC)
+#define MMSS_DP_AUDIO_INFOFRAME_2		(0x000006B0)
+
+#define MMSS_DP_GENERIC0_0			(0x00000700)
+#define MMSS_DP_GENERIC0_1			(0x00000704)
+#define MMSS_DP_GENERIC0_2			(0x00000708)
+#define MMSS_DP_GENERIC0_3			(0x0000070C)
+#define MMSS_DP_GENERIC0_4			(0x00000710)
+#define MMSS_DP_GENERIC0_5			(0x00000714)
+#define MMSS_DP_GENERIC0_6			(0x00000718)
+#define MMSS_DP_GENERIC0_7			(0x0000071C)
+#define MMSS_DP_GENERIC0_8			(0x00000720)
+#define MMSS_DP_GENERIC0_9			(0x00000724)
+#define MMSS_DP_GENERIC1_0			(0x00000728)
+#define MMSS_DP_GENERIC1_1			(0x0000072C)
+#define MMSS_DP_GENERIC1_2			(0x00000730)
+#define MMSS_DP_GENERIC1_3			(0x00000734)
+#define MMSS_DP_GENERIC1_4			(0x00000738)
+#define MMSS_DP_GENERIC1_5			(0x0000073C)
+#define MMSS_DP_GENERIC1_6			(0x00000740)
+#define MMSS_DP_GENERIC1_7			(0x00000744)
+#define MMSS_DP_GENERIC1_8			(0x00000748)
+#define MMSS_DP_GENERIC1_9			(0x0000074C)
+
+#define MMSS_DP_TIMING_ENGINE_EN		(0x00000A10)
+#define MMSS_DP_ASYNC_FIFO_CONFIG		(0x00000A88)
+
+/*DP PHY Register offsets */
+#define DP_PHY_REVISION_ID0                     (0x00000000)
+#define DP_PHY_REVISION_ID1                     (0x00000004)
+#define DP_PHY_REVISION_ID2                     (0x00000008)
+#define DP_PHY_REVISION_ID3                     (0x0000000C)
+
+#define DP_PHY_CFG                              (0x00000010)
+#define DP_PHY_PD_CTL                           (0x00000018)
+#define DP_PHY_MODE                             (0x0000001C)
+
+#define DP_PHY_AUX_CFG0                         (0x00000020)
+#define DP_PHY_AUX_CFG1                         (0x00000024)
+#define DP_PHY_AUX_CFG2                         (0x00000028)
+#define DP_PHY_AUX_CFG3                         (0x0000002C)
+#define DP_PHY_AUX_CFG4                         (0x00000030)
+#define DP_PHY_AUX_CFG5                         (0x00000034)
+#define DP_PHY_AUX_CFG6                         (0x00000038)
+#define DP_PHY_AUX_CFG7                         (0x0000003C)
+#define DP_PHY_AUX_CFG8                         (0x00000040)
+#define DP_PHY_AUX_CFG9                         (0x00000044)
+#define DP_PHY_AUX_INTERRUPT_MASK               (0x00000048)
+#define DP_PHY_AUX_INTERRUPT_CLEAR              (0x0000004C)
+
+#define DP_PHY_SPARE0				(0x00AC)
+
+#define TXn_TX_EMP_POST1_LVL			(0x000C)
+#define TXn_TX_DRV_LVL				(0x001C)
+
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN		(0x004)
+
+/* DP MMSS_CC registers */
+#define MMSS_DP_LINK_CMD_RCGR			(0x0138)
+#define MMSS_DP_LINK_CFG_RCGR			(0x013C)
+#define MMSS_DP_PIXEL_M				(0x0174)
+#define MMSS_DP_PIXEL_N				(0x0178)
+
+/* DP HDCP 1.3 registers */
+#define DP_HDCP_CTRL                                   (0x0A0)
+#define DP_HDCP_STATUS                                 (0x0A4)
+#define DP_HDCP_SW_UPPER_AKSV                          (0x298)
+#define DP_HDCP_SW_LOWER_AKSV                          (0x29C)
+#define DP_HDCP_ENTROPY_CTRL0                          (0x750)
+#define DP_HDCP_ENTROPY_CTRL1                          (0x75C)
+#define DP_HDCP_SHA_STATUS                             (0x0C8)
+#define DP_HDCP_RCVPORT_DATA2_0                        (0x0B0)
+#define DP_HDCP_RCVPORT_DATA3                          (0x2A4)
+#define DP_HDCP_RCVPORT_DATA4                          (0x2A8)
+#define DP_HDCP_RCVPORT_DATA5                          (0x0C0)
+#define DP_HDCP_RCVPORT_DATA6                          (0x0C4)
+
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL           (0x024)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA           (0x028)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0      (0x004)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1      (0x008)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7      (0x00C)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8      (0x010)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9      (0x014)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10     (0x018)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11     (0x01C)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12     (0x020)
+
+#endif /* _DP_REG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 5e76ce7..e9dabb1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -108,14 +108,15 @@
  * @ctrl:        Pointer to DSI controller hw object.
  * @version:     DSI controller version.
  * @index:       DSI controller instance ID.
+ * @phy_isolation_enabled:       DSI controller works isolated from phy.
  *
  * This function setups the catalog information in the dsi_ctrl_hw object.
  *
  * return: error code for failure and 0 for success.
  */
 int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
-			   enum dsi_ctrl_version version,
-			   u32 index)
+		   enum dsi_ctrl_version version, u32 index,
+		   bool phy_isolation_enabled)
 {
 	int rc = 0;
 
@@ -135,8 +136,11 @@
 
 	switch (version) {
 	case DSI_CTRL_VERSION_1_4:
+		dsi_catalog_cmn_init(ctrl, version);
+		break;
 	case DSI_CTRL_VERSION_2_0:
 	case DSI_CTRL_VERSION_2_2:
+		ctrl->phy_isolation_enabled = phy_isolation_enabled;
 		dsi_catalog_cmn_init(ctrl, version);
 		break;
 	default:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index e8a6ab4..e8d594c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -23,14 +23,15 @@
  * @ctrl:        Pointer to DSI controller hw object.
  * @version:     DSI controller version.
  * @index:       DSI controller instance ID.
+ * @phy_isolation_enabled:       DSI controller works isolated from phy.
  *
  * This function setups the catalog information in the dsi_ctrl_hw object.
  *
  * return: error code for failure and 0 for success.
  */
 int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
-			   enum dsi_ctrl_version version,
-			   u32 index);
+		   enum dsi_ctrl_version version, u32 index,
+		   bool phy_isolation_enabled);
 
 /**
  * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 21ef811..dcde566 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1262,13 +1262,41 @@
 	return 0;
 }
 
+static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl,
+				  struct device_node *of_node)
+{
+	u32 index = 0;
+	int rc = 0;
+
+	if (!dsi_ctrl || !of_node) {
+		pr_err("invalid dsi_ctrl:%d or of_node:%d\n",
+					dsi_ctrl != NULL, of_node != NULL);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(of_node, "cell-index", &index);
+	if (rc) {
+		pr_debug("cell index not set, default to 0\n");
+		index = 0;
+	}
+
+	dsi_ctrl->cell_index = index;
+	dsi_ctrl->name = of_get_property(of_node, "label", NULL);
+	if (!dsi_ctrl->name)
+		dsi_ctrl->name = DSI_CTRL_DEFAULT_LABEL;
+
+	dsi_ctrl->phy_isolation_enabled = of_property_read_bool(of_node,
+				    "qcom,dsi-phy-isolation-enabled");
+
+	return 0;
+}
+
 static int dsi_ctrl_dev_probe(struct platform_device *pdev)
 {
 	struct dsi_ctrl *dsi_ctrl;
 	struct dsi_ctrl_list_item *item;
 	const struct of_device_id *id;
 	enum dsi_ctrl_version version;
-	u32 index = 0;
 	int rc = 0;
 
 	id = of_match_node(msm_dsi_of_match, pdev->dev.of_node);
@@ -1285,22 +1313,18 @@
 	if (!dsi_ctrl)
 		return -ENOMEM;
 
-	rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &index);
-	if (rc) {
-		pr_debug("cell index not set, default to 0\n");
-		index = 0;
-	}
-
-	dsi_ctrl->cell_index = index;
 	dsi_ctrl->version = version;
 	dsi_ctrl->irq_info.irq_num = -1;
 	dsi_ctrl->irq_info.irq_stat_mask = 0x0;
 
 	spin_lock_init(&dsi_ctrl->irq_info.irq_lock);
 
-	dsi_ctrl->name = of_get_property(pdev->dev.of_node, "label", NULL);
-	if (!dsi_ctrl->name)
-		dsi_ctrl->name = DSI_CTRL_DEFAULT_LABEL;
+	rc = dsi_ctrl_dts_parse(dsi_ctrl, pdev->dev.of_node);
+	if (rc) {
+		pr_err("ctrl:%d dts parse failed, rc = %d\n",
+						dsi_ctrl->cell_index, rc);
+		goto fail;
+	}
 
 	rc = dsi_ctrl_init_regmap(pdev, dsi_ctrl);
 	if (rc) {
@@ -1321,7 +1345,7 @@
 	}
 
 	rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
-				    dsi_ctrl->cell_index);
+		    dsi_ctrl->cell_index, dsi_ctrl->phy_isolation_enabled);
 	if (rc) {
 		pr_err("Catalog does not support version (%d)\n",
 		       dsi_ctrl->version);
@@ -1945,6 +1969,36 @@
 	spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
 }
 
+int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl)
+{
+	if (!dsi_ctrl) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	if (dsi_ctrl->hw.ops.host_setup)
+		dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
+				&dsi_ctrl->host_config.common_config);
+
+	if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
+		if (dsi_ctrl->hw.ops.cmd_engine_setup)
+			dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
+					&dsi_ctrl->host_config.common_config,
+					&dsi_ctrl->host_config.u.cmd_engine);
+
+		if (dsi_ctrl->hw.ops.setup_cmd_stream)
+			dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
+				&dsi_ctrl->host_config.video_timing,
+				dsi_ctrl->host_config.video_timing.h_active * 3,
+				0x0, NULL);
+	} else {
+		pr_err("invalid panel mode for resolution switch\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * dsi_ctrl_host_init() - Initialize DSI host hardware.
  * @dsi_ctrl:        DSI controller handle.
@@ -2002,8 +2056,6 @@
 	dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
 	dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0);
 
-	/* Perform a soft reset before enabling dsi controller */
-	dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
 	pr_debug("[DSI_%d]Host initialization complete\n",
 		dsi_ctrl->cell_index);
 	dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 95dac1c..f10c7a6 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -190,6 +190,8 @@
  * @debugfs_root:        Root for debugfs entries.
  * @misr_enable:         Frame MISR enable/disable
  * @misr_cache:          Cached Frame MISR value
+ * @phy_isolation_enabled:    A boolean property allows to isolate the phy from
+ *                          dsi controller and run only dsi controller.
  */
 struct dsi_ctrl {
 	struct platform_device *pdev;
@@ -232,6 +234,7 @@
 	bool misr_enable;
 	u32 misr_cache;
 
+	bool phy_isolation_enabled;
 };
 
 /**
@@ -360,6 +363,17 @@
 int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl);
 
 /**
+ * dsi_ctrl_host_timing_update - reinitialize host with new timing values
+ * @dsi_ctrl:         DSI controller handle.
+ *
+ * Reinitialize DSI controller hardware with new display timing values
+ * when resolution is switched dynamically.
+ *
+ * Return: error code
+ */
+int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl);
+
+/**
  * dsi_ctrl_host_init() - Initialize DSI host hardware.
  * @dsi_ctrl:        DSI controller handle.
  *
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 2130144..57f9bcd 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -711,6 +711,8 @@
  *                          controller.
  * @supported_interrupts:   Number of supported interrupts.
  * @supported_errors:       Number of supported errors.
+ * @phy_isolation_enabled:    A boolean property allows to isolate the phy from
+ *                          dsi controller and run only dsi controller.
  */
 struct dsi_ctrl_hw {
 	void __iomem *base;
@@ -728,6 +730,8 @@
 	/* capabilities */
 	u32 supported_interrupts;
 	u64 supported_errors;
+
+	bool phy_isolation_enabled;
 };
 
 #endif /* _DSI_CTRL_HW_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 8e8e353..3fec296 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -79,7 +79,7 @@
 	DSI_W32(ctrl, DSI_CLK_CTRL, 0x23F);
 
 	/* Setup DSI control register */
-	reg_value = 0;
+	reg_value = DSI_R32(ctrl, DSI_CTRL);
 	reg_value |= (cfg->en_crc_check ? BIT(24) : 0);
 	reg_value |= (cfg->en_ecc_check ? BIT(20) : 0);
 	reg_value |= BIT(8); /* Clock lane */
@@ -90,6 +90,8 @@
 
 	DSI_W32(ctrl, DSI_CTRL, reg_value);
 
+	if (ctrl->phy_isolation_enabled)
+		DSI_W32(ctrl, DSI_DEBUG_CTRL, BIT(28));
 	pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index);
 }
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h
index 34e9e72..f8f7e13 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h
@@ -184,6 +184,7 @@
 #define DSI_DESKEW_CTRL                            (0x02BC)
 #define DSI_DESKEW_DELAY_CTRL                      (0x02C0)
 #define DSI_DESKEW_SW_TRIGGER                      (0x02C4)
+#define DSI_DEBUG_CTRL                             (0x02C8)
 #define DSI_SECURE_DISPLAY_STATUS                  (0x02CC)
 #define DSI_SECURE_DISPLAY_BLOCK_COMMAND_COLOR     (0x02D0)
 #define DSI_SECURE_DISPLAY_BLOCK_VIDEO_COLOR       (0x02D4)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index 1e6727b..fcc59ef 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -15,6 +15,7 @@
 #define _DSI_DEFS_H_
 
 #include <linux/types.h>
+#include <drm/drm_mipi_dsi.h>
 #include "msm_drv.h"
 
 #define DSI_H_TOTAL(t) (((t)->h_active) + ((t)->h_back_porch) + \
@@ -75,11 +76,13 @@
  * @DSI_MODE_FLAG_SEAMLESS:	Seamless transition requested by user
  * @DSI_MODE_FLAG_DFPS:		Seamless transition is DynamicFPS
  * @DSI_MODE_FLAG_VBLANK_PRE_MODESET:	Transition needs VBLANK before Modeset
+ * @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch
  */
 enum dsi_mode_flags {
 	DSI_MODE_FLAG_SEAMLESS			= BIT(0),
 	DSI_MODE_FLAG_DFPS			= BIT(1),
-	DSI_MODE_FLAG_VBLANK_PRE_MODESET	= BIT(2)
+	DSI_MODE_FLAG_VBLANK_PRE_MODESET	= BIT(2),
+	DSI_MODE_FLAG_DMS			= BIT(3),
 };
 
 /**
@@ -214,6 +217,68 @@
 };
 
 /**
+ * enum dsi_cmd_set_type  - DSI command set type
+ * @DSI_CMD_SET_PRE_ON:	                   Panel pre on
+ * @DSI_CMD_SET_ON:                        Panel on
+ * @DSI_CMD_SET_POST_ON:                   Panel post on
+ * @DSI_CMD_SET_PRE_OFF:                   Panel pre off
+ * @DSI_CMD_SET_OFF:                       Panel off
+ * @DSI_CMD_SET_POST_OFF:                  Panel post off
+ * @DSI_CMD_SET_PRE_RES_SWITCH:            Pre resolution switch
+ * @DSI_CMD_SET_RES_SWITCH:                Resolution switch
+ * @DSI_CMD_SET_POST_RES_SWITCH:           Post resolution switch
+ * @DSI_CMD_SET_CMD_TO_VID_SWITCH:         Cmd to video mode switch
+ * @DSI_CMD_SET_POST_CMD_TO_VID_SWITCH:    Post cmd to vid switch
+ * @DSI_CMD_SET_VID_TO_CMD_SWITCH:         Video to cmd mode switch
+ * @DSI_CMD_SET_POST_VID_TO_CMD_SWITCH:    Post vid to cmd switch
+ * @DSI_CMD_SET_PANEL_STATUS:              Panel status
+ * @DSI_CMD_SET_LP1:                       Low power mode 1
+ * @DSI_CMD_SET_LP2:                       Low power mode 2
+ * @DSI_CMD_SET_NOLP:                      Low power mode disable
+ * @DSI_CMD_SET_PPS:                       DSC PPS command
+ * @DSI_CMD_SET_ROI:			   Panel ROI update
+ * @DSI_CMD_SET_TIMING_SWITCH:             Timing switch
+ * @DSI_CMD_SET_POST_TIMING_SWITCH:        Post timing switch
+ * @DSI_CMD_SET_MAX
+ */
+enum dsi_cmd_set_type {
+	DSI_CMD_SET_PRE_ON = 0,
+	DSI_CMD_SET_ON,
+	DSI_CMD_SET_POST_ON,
+	DSI_CMD_SET_PRE_OFF,
+	DSI_CMD_SET_OFF,
+	DSI_CMD_SET_POST_OFF,
+	DSI_CMD_SET_PRE_RES_SWITCH,
+	DSI_CMD_SET_RES_SWITCH,
+	DSI_CMD_SET_POST_RES_SWITCH,
+	DSI_CMD_SET_CMD_TO_VID_SWITCH,
+	DSI_CMD_SET_POST_CMD_TO_VID_SWITCH,
+	DSI_CMD_SET_VID_TO_CMD_SWITCH,
+	DSI_CMD_SET_POST_VID_TO_CMD_SWITCH,
+	DSI_CMD_SET_PANEL_STATUS,
+	DSI_CMD_SET_LP1,
+	DSI_CMD_SET_LP2,
+	DSI_CMD_SET_NOLP,
+	DSI_CMD_SET_PPS,
+	DSI_CMD_SET_ROI,
+	DSI_CMD_SET_TIMING_SWITCH,
+	DSI_CMD_SET_POST_TIMING_SWITCH,
+	DSI_CMD_SET_MAX
+};
+
+/**
+ * enum dsi_cmd_set_state - command set state
+ * @DSI_CMD_SET_STATE_LP:   dsi low power mode
+ * @DSI_CMD_SET_STATE_HS:   dsi high speed mode
+ * @DSI_CMD_SET_STATE_MAX
+ */
+enum dsi_cmd_set_state {
+	DSI_CMD_SET_STATE_LP = 0,
+	DSI_CMD_SET_STATE_HS,
+	DSI_CMD_SET_STATE_MAX
+};
+
+/**
  * enum dsi_phy_type - DSI phy types
  * @DSI_PHY_TYPE_DPHY:
  * @DSI_PHY_TYPE_CPHY:
@@ -246,6 +311,34 @@
 };
 
 /**
+ * struct dsi_cmd_desc - description of a dsi command
+ * @msg:		dsi mipi msg packet
+ * @last_command:   indicates whether the cmd is the last one to send
+ * @post_wait_ms:   post wait duration
+ */
+struct dsi_cmd_desc {
+	struct mipi_dsi_msg msg;
+	bool last_command;
+	u32  post_wait_ms;
+};
+
+/**
+ * struct dsi_panel_cmd_set - command set of the panel
+ * @type:      type of the command
+ * @state:     state of the command
+ * @count:     number of cmds
+ * @ctrl_idx:  index of the dsi control
+ * @cmds:      arry of cmds
+ */
+struct dsi_panel_cmd_set {
+	enum dsi_cmd_set_type type;
+	enum dsi_cmd_set_state state;
+	u32 count;
+	u32 ctrl_idx;
+	struct dsi_cmd_desc *cmds;
+};
+
+/**
  * struct dsi_mode_info - video mode information dsi frame
  * @h_active:         Active width of one frame in pixels.
  * @h_back_porch:     Horizontal back porch in pixels.
@@ -397,18 +490,44 @@
 };
 
 /**
+ * struct dsi_display_mode_priv_info - private mode info that will be attached
+ *                             with each drm mode
+ * @cmd_sets:		  Command sets of the mode
+ * @phy_timing_val:       Phy timing values
+ * @phy_timing_len:       Phy timing array length
+ * @panel_jitter:         Panel jitter for RSC backoff
+ * @panel_prefill_lines:  Panel prefill lines for RSC
+ * @topology:             Topology selected for the panel
+ * @dsc:                  DSC compression info
+ * @dsc_enabled:          DSC compression enabled
+ */
+struct dsi_display_mode_priv_info {
+	struct dsi_panel_cmd_set cmd_sets[DSI_CMD_SET_MAX];
+
+	u32 *phy_timing_val;
+	u32 phy_timing_len;
+
+	u32 panel_jitter_numer;
+	u32 panel_jitter_denom;
+	u32 panel_prefill_lines;
+
+	struct msm_display_topology topology;
+	struct msm_display_dsc_info dsc;
+	bool dsc_enabled;
+};
+
+/**
  * struct dsi_display_mode - specifies mode for dsi display
  * @timing:         Timing parameters for the panel.
  * @pixel_clk_khz:  Pixel clock in Khz.
- * @panel_mode:     Panel operation mode.
  * @dsi_mode_flags: Flags to signal other drm components via private flags
+ * @priv_info:      Mode private info
  */
 struct dsi_display_mode {
 	struct dsi_mode_info timing;
 	u32 pixel_clk_khz;
-	enum dsi_op_mode panel_mode;
 	u32 dsi_mode_flags;
-	struct msm_mode_info *mode_info;
+	struct dsi_display_mode_priv_info *priv_info;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index c0c6698..04dd6a5 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -31,6 +31,7 @@
 
 #define to_dsi_display(x) container_of(x, struct dsi_display, host)
 #define INT_BASE_10 10
+#define NO_OVERRIDE -1
 
 #define MISR_BUFF_SIZE	256
 
@@ -141,6 +142,31 @@
 	}
 }
 
+int dsi_display_set_power(struct drm_connector *connector,
+		int power_mode, void *disp)
+{
+	struct dsi_display *display = disp;
+	int rc = 0;
+
+	if (!display || !display->panel) {
+		pr_err("invalid display/panel\n");
+		return -EINVAL;
+	}
+
+	switch (power_mode) {
+	case SDE_MODE_DPMS_LP1:
+		rc = dsi_panel_set_lp1(display->panel);
+		break;
+	case SDE_MODE_DPMS_LP2:
+		rc = dsi_panel_set_lp2(display->panel);
+		break;
+	default:
+		rc = dsi_panel_set_nolp(display->panel);
+		break;
+	}
+	return rc;
+}
+
 static ssize_t debugfs_dump_info_read(struct file *file,
 				      char __user *user_buf,
 				      size_t user_len,
@@ -775,29 +801,46 @@
 	return rc;
 }
 
-static int dsi_display_parse_cmdline_topology(unsigned int display_type)
+static void dsi_display_parse_cmdline_topology(struct dsi_display *display,
+					unsigned int display_type)
 {
+	char *boot_str = NULL;
 	char *str = NULL;
-	int top_index = -1;
+	unsigned long value;
 
 	if (display_type >= MAX_DSI_ACTIVE_DISPLAY) {
 		pr_err("display_type=%d not supported\n", display_type);
-		return -EINVAL;
+		return;
 	}
+
 	if (display_type == DSI_PRIMARY)
-		str = strnstr(dsi_display_primary,
-			":config", strlen(dsi_display_primary));
+		boot_str = dsi_display_primary;
 	else
-		str = strnstr(dsi_display_secondary,
-			":config", strlen(dsi_display_secondary));
+		boot_str = dsi_display_secondary;
+
+	str = strnstr(boot_str, ":config", strlen(boot_str));
 	if (!str)
-		return -EINVAL;
+		return;
 
 	if (kstrtol(str + strlen(":config"), INT_BASE_10,
-				(unsigned long *)&top_index))
-		return -EINVAL;
+				(unsigned long *)&value)) {
+		pr_err("invalid config index override: %s\n", boot_str);
+		return;
+	}
+	display->cmdline_topology = value;
 
-	return top_index;
+	str = strnstr(boot_str, ":timing", strlen(boot_str));
+	if (!str)
+		return;
+
+	if (kstrtol(str + strlen(":timing"), INT_BASE_10,
+				(unsigned long *)&value)) {
+		pr_err("invalid timing index override: %s. resetting both timing and config\n",
+			boot_str);
+		display->cmdline_topology = NO_OVERRIDE;
+		return;
+	}
+	display->cmdline_timing = value;
 }
 
 /**
@@ -1064,6 +1107,32 @@
 	return 0;
 }
 
+static int dsi_display_ctrl_update(struct dsi_display *display)
+{
+	int rc = 0;
+	int i;
+	struct dsi_display_ctrl *ctrl;
+
+	for (i = 0 ; i < display->ctrl_count; i++) {
+		ctrl = &display->ctrl[i];
+		rc = dsi_ctrl_host_timing_update(ctrl->ctrl);
+		if (rc) {
+			pr_err("[%s] failed to update host_%d, rc=%d\n",
+				   display->name, i, rc);
+			goto error_host_deinit;
+		}
+	}
+
+	return 0;
+error_host_deinit:
+	for (i = i - 1; i >= 0; i--) {
+		ctrl = &display->ctrl[i];
+		(void)dsi_ctrl_host_deinit(ctrl->ctrl);
+	}
+
+	return rc;
+}
+
 static int dsi_display_ctrl_init(struct dsi_display *display)
 {
 	int rc = 0;
@@ -2214,17 +2283,6 @@
 		goto error_ctrl_put;
 	}
 
-	if (display->panel->phy_timing_len) {
-		for (i = 0; i < display->ctrl_count; i++) {
-			ctrl = &display->ctrl[i];
-			 rc = dsi_phy_set_timing_params(ctrl->phy,
-				display->panel->phy_timing_val,
-				display->panel->phy_timing_len);
-			if (rc)
-				pr_err("failed to add DSI PHY timing params");
-		}
-	}
-
 	rc = dsi_display_parse_lane_map(display);
 	if (rc) {
 		pr_err("Lane map not found, rc=%d\n", rc);
@@ -2263,6 +2321,9 @@
 		dsi_ctrl_put(ctrl->ctrl);
 	}
 
+	if (display->panel)
+		dsi_panel_put(display->panel);
+
 	return rc;
 }
 
@@ -2301,12 +2362,12 @@
 {
 	struct dsi_display_mode *cur;
 
-	if (!display || !tgt) {
+	if (!display || !tgt || !display->panel) {
 		pr_err("Invalid params\n");
 		return false;
 	}
 
-	cur = &display->panel->mode;
+	cur = display->panel->cur_mode;
 
 	if (cur->timing.h_active != tgt->timing.h_active) {
 		pr_debug("timing.h_active differs %d %d\n",
@@ -2385,12 +2446,6 @@
 		pr_debug("pixel_clk_khz differs %d %d\n",
 				cur->pixel_clk_khz, tgt->pixel_clk_khz);
 
-	if (cur->panel_mode != tgt->panel_mode) {
-		pr_debug("panel_mode differs %d %d\n",
-				cur->panel_mode, tgt->panel_mode);
-		return false;
-	}
-
 	if (cur->dsi_mode_flags != tgt->dsi_mode_flags)
 		pr_debug("flags differs %d %d\n",
 				cur->dsi_mode_flags, tgt->dsi_mode_flags);
@@ -2408,7 +2463,7 @@
 	int rc = 0;
 	int i = 0;
 
-	if (!display || !dsi_mode) {
+	if (!display || !dsi_mode || !display->panel) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
@@ -2451,7 +2506,7 @@
 		}
 	}
 
-	panel_mode = &display->panel->mode;
+	panel_mode = display->panel->cur_mode;
 	memcpy(panel_mode, dsi_mode, sizeof(*panel_mode));
 	/*
 	 * dsi_mode_flags flags are used to communicate with other drm driver
@@ -2606,6 +2661,14 @@
 	int rc = 0;
 	int i;
 	struct dsi_display_ctrl *ctrl;
+	struct dsi_display_mode_priv_info *priv_info;
+
+	priv_info = mode->priv_info;
+	if (!priv_info) {
+		pr_err("[%s] failed to get private info of the display mode",
+			display->name);
+		return -EINVAL;
+	}
 
 	rc = dsi_panel_get_host_cfg_for_mode(display->panel,
 					     mode,
@@ -2638,6 +2701,17 @@
 			goto error;
 		}
 	}
+
+	if (priv_info->phy_timing_len) {
+		for (i = 0; i < display->ctrl_count; i++) {
+			ctrl = &display->ctrl[i];
+			 rc = dsi_phy_set_timing_params(ctrl->phy,
+				priv_info->phy_timing_val,
+				priv_info->phy_timing_len);
+			if (rc)
+				pr_err("failed to add DSI PHY timing params");
+		}
+	}
 error:
 	return rc;
 }
@@ -2864,19 +2938,10 @@
 		goto error_host_deinit;
 	}
 
-	rc = dsi_panel_get_mode_count(display->panel, &display->num_of_modes);
-	if (rc) {
-		pr_err("[%s] failed to get mode count, rc=%d\n",
-		       display->name, rc);
-		goto error_panel_deinit;
-	}
-
 	pr_info("Successfully bind display panel '%s'\n", display->name);
 	display->drm_dev = drm;
 	goto error;
 
-error_panel_deinit:
-	(void)dsi_panel_drv_deinit(display->panel);
 error_host_deinit:
 	(void)dsi_display_mipi_host_deinit(display);
 error_clk_client_deinit:
@@ -2993,8 +3058,10 @@
 		boot_displays_parsed = true;
 	}
 
-	/* Initialize cmdline_topology to use default topology */
-	display->cmdline_topology = -1;
+	/* use default topology of every mode if not overridden */
+	display->cmdline_topology = NO_OVERRIDE;
+	display->cmdline_timing = 0;
+
 	if ((!display_from_cmdline) &&
 			(boot_displays[DSI_PRIMARY].boot_disp_en)) {
 		display->is_active = dsi_display_name_compare(pdev->dev.of_node,
@@ -3020,8 +3087,8 @@
 			pr_debug("cmdline primary dsi: %s\n",
 						display->name);
 			display_from_cmdline = true;
-			display->cmdline_topology =
-				dsi_display_parse_cmdline_topology(DSI_PRIMARY);
+			dsi_display_parse_cmdline_topology(display,
+					DSI_PRIMARY);
 			primary_np = pdev->dev.of_node;
 		}
 	}
@@ -3036,9 +3103,8 @@
 				if (primary_np) {
 					if (validate_dsi_display_selection()) {
 					display->is_active = true;
-					display->cmdline_topology =
 					dsi_display_parse_cmdline_topology
-							(DSI_SECONDARY);
+						(display, DSI_SECONDARY);
 					} else {
 						boot_displays[DSI_SECONDARY]
 							.boot_disp_en = false;
@@ -3239,7 +3305,6 @@
 {
 	struct dsi_display *display;
 	struct dsi_panel_phy_props phy_props;
-	struct dsi_mode_info *timing;
 	int i, rc;
 
 	if (!info || !disp) {
@@ -3263,32 +3328,18 @@
 
 	memset(info, 0, sizeof(struct msm_display_info));
 	info->intf_type = DRM_MODE_CONNECTOR_DSI;
-	timing = &display->panel->mode.timing;
-
 	info->num_of_h_tiles = display->ctrl_count;
 	for (i = 0; i < info->num_of_h_tiles; i++)
 		info->h_tile_instance[i] = display->ctrl[i].ctrl->cell_index;
 
 	info->is_connected = true;
 	info->is_primary = true;
-	info->frame_rate = timing->refresh_rate;
-	info->vtotal = DSI_V_TOTAL(timing);
-	info->prefill_lines = display->panel->panel_prefill_lines;
-	info->jitter_numer = display->panel->panel_jitter_numer;
-	info->jitter_denom = display->panel->panel_jitter_denom;
 	info->width_mm = phy_props.panel_width_mm;
 	info->height_mm = phy_props.panel_height_mm;
 	info->max_width = 1920;
 	info->max_height = 1080;
-	info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
 
-	if (display->panel->dsc_enabled) {
-		info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
-		memcpy(&info->comp_info.dsc_info, &display->panel->dsc,
-			sizeof(struct msm_display_dsc_info));
-	}
-
-	switch (display->panel->mode.panel_mode) {
+	switch (display->panel->panel_mode) {
 	case DSI_OP_VIDEO_MODE:
 		info->capabilities |= MSM_DISPLAY_CAP_VID_MODE;
 		break;
@@ -3299,7 +3350,7 @@
 		break;
 	default:
 		pr_err("unknwown dsi panel mode %d\n",
-				display->panel->mode.panel_mode);
+				display->panel->panel_mode);
 		break;
 	}
 
@@ -3311,16 +3362,57 @@
 	return rc;
 }
 
-int dsi_display_get_modes(struct dsi_display *display,
-			  struct dsi_display_mode *modes,
-			  u32 *count)
+int dsi_display_get_mode_count(struct dsi_display *display,
+			u32 *count)
 {
-	int rc = 0;
-	int i;
 	struct dsi_dfps_capabilities dfps_caps;
-	int num_dfps_rates;
+	int num_dfps_rates, rc = 0;
 
-	if (!display || !count) {
+	if (!display || !display->panel) {
+		pr_err("invalid display:%d panel:%d\n", display != NULL,
+				display ? display->panel != NULL : 0);
+		return -EINVAL;
+	}
+
+	mutex_lock(&display->display_lock);
+
+	*count = display->panel->num_timing_nodes;
+
+	rc = dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
+	if (rc) {
+		pr_err("[%s] failed to get dfps caps from panel\n",
+				display->name);
+		goto done;
+	}
+
+	num_dfps_rates = !dfps_caps.dfps_support ? 1 :
+			dfps_caps.max_refresh_rate -
+			dfps_caps.min_refresh_rate + 1;
+
+	/* Inflate num_of_modes by fps in dfps */
+	*count = display->panel->num_timing_nodes * num_dfps_rates;
+
+done:
+	mutex_unlock(&display->display_lock);
+
+	return 0;
+}
+
+void dsi_display_put_mode(struct dsi_display *display,
+	struct dsi_display_mode *mode)
+{
+	dsi_panel_put_mode(mode);
+}
+
+int dsi_display_get_modes(struct dsi_display *display,
+			  struct dsi_display_mode *modes)
+{
+	struct dsi_dfps_capabilities dfps_caps;
+	u32 num_dfps_rates, panel_mode_count;
+	u32 mode_idx, array_idx = 0;
+	int i, rc = 0;
+
+	if (!display || !modes) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
@@ -3338,41 +3430,55 @@
 			dfps_caps.max_refresh_rate -
 			dfps_caps.min_refresh_rate + 1;
 
-	if (!modes) {
-		/* Inflate num_of_modes by fps in dfps */
-		*count = display->num_of_modes * num_dfps_rates;
-		goto error;
-	}
+	panel_mode_count = display->panel->num_timing_nodes;
 
-	for (i = 0; i < *count; i++) {
-		/* Insert the dfps "sub-modes" between main panel modes */
-		int panel_mode_idx = i / num_dfps_rates;
+	for (mode_idx = 0; mode_idx < panel_mode_count; mode_idx++) {
+		struct dsi_display_mode panel_mode;
+		int topology_override = NO_OVERRIDE;
 
-		rc = dsi_panel_get_mode(display->panel, panel_mode_idx, modes);
+		if (display->cmdline_timing == mode_idx)
+			topology_override = display->cmdline_topology;
+
+		memset(&panel_mode, 0, sizeof(panel_mode));
+
+		rc = dsi_panel_get_mode(display->panel, mode_idx,
+						&panel_mode, topology_override);
 		if (rc) {
-			pr_err("[%s] failed to get mode from panel\n",
-			       display->name);
+			pr_err("[%s] failed to get mode idx %d from panel\n",
+				   display->name, mode_idx);
 			goto error;
 		}
 
-		if (dfps_caps.dfps_support) {
-			modes->timing.refresh_rate = dfps_caps.min_refresh_rate
-					+ (i % num_dfps_rates);
-			modes->pixel_clk_khz = (DSI_H_TOTAL(&modes->timing) *
-					DSI_V_TOTAL(&modes->timing) *
-					modes->timing.refresh_rate) / 1000;
-		}
-
 		if (display->ctrl_count > 1) { /* TODO: remove if */
-			modes->timing.h_active *= display->ctrl_count;
-			modes->timing.h_front_porch *= display->ctrl_count;
-			modes->timing.h_sync_width *= display->ctrl_count;
-			modes->timing.h_back_porch *= display->ctrl_count;
-			modes->timing.h_skew *= display->ctrl_count;
-			modes->pixel_clk_khz *= display->ctrl_count;
+			panel_mode.timing.h_active *= display->ctrl_count;
+			panel_mode.timing.h_front_porch *= display->ctrl_count;
+			panel_mode.timing.h_sync_width *= display->ctrl_count;
+			panel_mode.timing.h_back_porch *= display->ctrl_count;
+			panel_mode.timing.h_skew *= display->ctrl_count;
+			panel_mode.pixel_clk_khz *= display->ctrl_count;
 		}
 
-		modes++;
+		for (i = 0; i < num_dfps_rates; i++) {
+			struct dsi_display_mode *sub_mode = &modes[array_idx];
+
+			if (!sub_mode) {
+				pr_err("invalid mode data\n");
+				return -EFAULT;
+			}
+
+			memcpy(sub_mode, &panel_mode, sizeof(panel_mode));
+
+			if (dfps_caps.dfps_support) {
+				sub_mode->timing.refresh_rate =
+					dfps_caps.min_refresh_rate +
+					(i % num_dfps_rates);
+				sub_mode->pixel_clk_khz =
+					(DSI_H_TOTAL(&sub_mode->timing) *
+					DSI_V_TOTAL(&sub_mode->timing) *
+					sub_mode->timing.refresh_rate) / 1000;
+			}
+			array_idx++;
+		}
 	}
 
 error:
@@ -3445,7 +3551,7 @@
 	int rc = 0;
 	struct dsi_display_mode adj_mode;
 
-	if (!display || !mode) {
+	if (!display || !mode || !display->panel) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
@@ -3466,6 +3572,17 @@
 		pr_err("[%s] failed to set mode\n", display->name);
 		goto error;
 	}
+
+	if (!display->panel->cur_mode) {
+		display->panel->cur_mode =
+			kzalloc(sizeof(struct dsi_display_mode), GFP_KERNEL);
+		if (!display->panel->cur_mode) {
+			rc = -ENOMEM;
+			goto error;
+		}
+	}
+
+	memcpy(display->panel->cur_mode, &adj_mode, sizeof(adj_mode));
 error:
 	mutex_unlock(&display->display_lock);
 	return rc;
@@ -3497,17 +3614,80 @@
 	return rc;
 }
 
+static int dsi_display_pre_switch(struct dsi_display *display)
+{
+	int rc = 0;
+
+	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+			DSI_CORE_CLK, DSI_CLK_ON);
+	if (rc) {
+		pr_err("[%s] failed to enable DSI core clocks, rc=%d\n",
+		       display->name, rc);
+		goto error;
+	}
+
+	rc = dsi_display_ctrl_update(display);
+	if (rc) {
+		pr_err("[%s] failed to update DSI controller, rc=%d\n",
+			   display->name, rc);
+		goto error_ctrl_clk_off;
+	}
+
+	rc = dsi_display_set_clk_src(display);
+	if (rc) {
+		pr_err("[%s] failed to set DSI link clock source, rc=%d\n",
+			display->name, rc);
+		goto error_ctrl_deinit;
+	}
+
+	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+			DSI_LINK_CLK, DSI_CLK_ON);
+	if (rc) {
+		pr_err("[%s] failed to enable DSI link clocks, rc=%d\n",
+			   display->name, rc);
+		goto error_ctrl_deinit;
+	}
+
+	goto error;
+
+error_ctrl_deinit:
+	(void)dsi_display_ctrl_deinit(display);
+error_ctrl_clk_off:
+	(void)dsi_display_clk_ctrl(display->dsi_clk_handle,
+			DSI_CORE_CLK, DSI_CLK_OFF);
+error:
+	return rc;
+}
+
 int dsi_display_prepare(struct dsi_display *display)
 {
 	int rc = 0;
+	struct dsi_display_mode *mode;
 
 	if (!display) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
 
+	if (!display->panel->cur_mode) {
+		pr_err("no valid mode set for the display");
+		return -EINVAL;
+	}
+
 	mutex_lock(&display->display_lock);
 
+	mode = display->panel->cur_mode;
+
+	if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+		/* update dsi ctrl for new mode */
+		rc = dsi_display_pre_switch(display);
+		if (rc)
+			pr_err("[%s] panel pre-prepare-res-switch failed, rc=%d\n",
+				   display->name, rc);
+
+		goto error;
+	}
+
 	rc = dsi_panel_pre_prepare(display->panel);
 	if (rc) {
 		pr_err("[%s] panel pre-prepare failed, rc=%d\n",
@@ -3536,6 +3716,13 @@
 		goto error_ctrl_clk_off;
 	}
 
+	rc = dsi_display_set_clk_src(display);
+	if (rc) {
+		pr_err("[%s] failed to set DSI link clock source, rc=%d\n",
+			display->name, rc);
+		goto error_phy_disable;
+	}
+
 	rc = dsi_display_ctrl_init(display);
 	if (rc) {
 		pr_err("[%s] failed to setup DSI controller, rc=%d\n",
@@ -3543,10 +3730,10 @@
 		goto error_phy_disable;
 	}
 
-	rc = dsi_display_set_clk_src(display);
+	rc = dsi_display_ctrl_host_enable(display);
 	if (rc) {
-		pr_err("[%s] failed to set DSI link clock source, rc=%d\n",
-			display->name, rc);
+		pr_err("[%s] failed to enable DSI host, rc=%d\n",
+		       display->name, rc);
 		goto error_ctrl_deinit;
 	}
 
@@ -3555,29 +3742,28 @@
 	if (rc) {
 		pr_err("[%s] failed to enable DSI link clocks, rc=%d\n",
 		       display->name, rc);
-		goto error_ctrl_deinit;
+		goto error_host_engine_off;
 	}
 
-	rc = dsi_display_ctrl_host_enable(display);
+	rc = dsi_display_soft_reset(display);
 	if (rc) {
-		pr_err("[%s] failed to enable DSI host, rc=%d\n",
-		       display->name, rc);
+		pr_err("[%s] failed soft reset, rc=%d\n", display->name, rc);
 		goto error_ctrl_link_off;
 	}
 
 	rc = dsi_panel_prepare(display->panel);
 	if (rc) {
 		pr_err("[%s] panel prepare failed, rc=%d\n", display->name, rc);
-		goto error_host_engine_off;
+		goto error_ctrl_link_off;
 	}
 
 	goto error;
 
-error_host_engine_off:
-	(void)dsi_display_ctrl_host_disable(display);
 error_ctrl_link_off:
 	(void)dsi_display_clk_ctrl(display->dsi_clk_handle,
 			DSI_LINK_CLK, DSI_CLK_OFF);
+error_host_engine_off:
+	(void)dsi_display_ctrl_host_disable(display);
 error_ctrl_deinit:
 	(void)dsi_display_ctrl_deinit(display);
 error_phy_disable:
@@ -3705,23 +3891,40 @@
 int dsi_display_enable(struct dsi_display *display)
 {
 	int rc = 0;
+	struct dsi_display_mode *mode;
 
-	if (!display) {
+	if (!display || !display->panel) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
 
+	if (!display->panel->cur_mode) {
+		pr_err("no valid mode set for the display");
+		return -EINVAL;
+	}
+
 	mutex_lock(&display->display_lock);
 
-	rc = dsi_panel_enable(display->panel);
-	if (rc) {
-		pr_err("[%s] failed to enable DSI panel, rc=%d\n",
-		       display->name, rc);
-		goto error;
+	mode = display->panel->cur_mode;
+
+	if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+		rc = dsi_panel_post_switch(display->panel);
+		if (rc) {
+			pr_err("[%s] failed to switch DSI panel mode, rc=%d\n",
+				   display->name, rc);
+			goto error;
+		}
+	} else {
+		rc = dsi_panel_enable(display->panel);
+		if (rc) {
+			pr_err("[%s] failed to enable DSI panel, rc=%d\n",
+			       display->name, rc);
+			goto error;
+		}
 	}
 
-	if (display->panel->dsc_enabled) {
-		display->panel->dsc.pic_width *= display->ctrl_count;
+	if (mode->priv_info->dsc_enabled) {
+		mode->priv_info->dsc.pic_width *= display->ctrl_count;
 		rc = dsi_panel_update_pps(display->panel);
 		if (rc) {
 			pr_err("[%s] panel pps cmd update failed, rc=%d\n",
@@ -3730,6 +3933,15 @@
 		}
 	}
 
+	if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+		rc = dsi_panel_switch(display->panel);
+		if (rc)
+			pr_err("[%s] failed to switch DSI panel mode, rc=%d\n",
+				   display->name, rc);
+
+		goto error;
+	}
+
 	if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
 		rc = dsi_display_vid_engine_enable(display);
 		if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index 359e04f3..1c30b9c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -141,8 +141,8 @@
  * @clock_info:       Clock sourcing for DSI display.
  * @config:           DSI host configuration information.
  * @lane_map:         Lane mapping between DSI host and Panel.
- * @num_of_modes:     Number of modes supported by display.
  * @cmdline_topology: Display topology shared from kernel command line.
+ * @cmdline_timing:   Display timing shared from kernel command line.
  * @is_tpg_enabled:   TPG state.
  * @ulps_enabled:     ulps state.
  * @clamp_enabled:    clamp state.
@@ -182,8 +182,8 @@
 	struct dsi_display_clk_info clock_info;
 	struct dsi_host_config config;
 	struct dsi_lane_map lane_map;
-	u32 num_of_modes;
 	int cmdline_topology;
+	int cmdline_timing;
 	bool is_tpg_enabled;
 	bool ulps_enabled;
 	bool clamp_enabled;
@@ -280,21 +280,36 @@
 int dsi_display_get_info(struct msm_display_info *info, void *disp);
 
 /**
+ * dsi_display_get_mode_count() - get number of modes supported by the display
+ * @display:            Handle to display.
+ * @count:              Number of modes supported
+ *
+ * Return: error code.
+ */
+int dsi_display_get_mode_count(struct dsi_display *display, u32 *count);
+
+/**
  * dsi_display_get_modes() - get modes supported by display
  * @display:            Handle to display.
  * @modes;              Pointer to array of modes. Memory allocated should be
  *			big enough to store (count * struct dsi_display_mode)
  *			elements. If modes pointer is NULL, number of modes will
  *			be stored in the memory pointed to by count.
- * @count:              If modes is NULL, number of modes will be stored. If
- *			not, mode information will be copied (number of modes
- *			copied will be equal to *count).
  *
  * Return: error code.
  */
 int dsi_display_get_modes(struct dsi_display *display,
-			  struct dsi_display_mode *modes,
-			  u32 *count);
+			  struct dsi_display_mode *modes);
+
+/**
+ * dsi_display_put_mode() - free up mode created for the display
+ * @display:            Handle to display.
+ * @mode:               Display mode to be freed up
+ *
+ * Return: error code.
+ */
+void dsi_display_put_mode(struct dsi_display *display,
+	struct dsi_display_mode *mode);
 
 /**
  * dsi_display_validate_mode() - validates if mode is supported by display
@@ -477,6 +492,22 @@
  */
 int dsi_display_soft_reset(void *display);
 
+/**
+ * dsi_display_set_power - update power/dpms setting
+ * @connector: Pointer to drm connector structure
+ * @power_mode: One of the following,
+ *              SDE_MODE_DPMS_ON
+ *              SDE_MODE_DPMS_LP1
+ *              SDE_MODE_DPMS_LP2
+ *              SDE_MODE_DPMS_STANDBY
+ *              SDE_MODE_DPMS_SUSPEND
+ *              SDE_MODE_DPMS_OFF
+ * @display: Pointer to private display structure
+ * Returns: Zero on success
+ */
+int dsi_display_set_power(struct drm_connector *connector,
+		int power_mode, void *display);
+
 /*
  * dsi_display_pre_kickoff - program kickoff-time features
  * @display: Pointer to private display structure
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c
index 93fb041..6e41f36 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 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
@@ -34,7 +34,7 @@
 	test = container_of(work, struct dsi_display_test, test_work);
 
 	display = test->display;
-	rc = dsi_display_get_modes(display, NULL, &count);
+	rc = dsi_display_get_mode_count(display, &count);
 	if (rc) {
 		pr_err("failed to get modes count, rc=%d\n", rc);
 		goto test_fail;
@@ -47,7 +47,7 @@
 		goto test_fail;
 	}
 
-	rc = dsi_display_get_modes(display, modes, &count);
+	rc = dsi_display_get_modes(display, modes);
 	if (rc) {
 		pr_err("failed to get modes, rc=%d\n", rc);
 		goto test_fail_free_modes;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index b499bd6..30e5f02 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -49,9 +49,9 @@
 	dsi_mode->timing.refresh_rate = drm_mode->vrefresh;
 
 	dsi_mode->pixel_clk_khz = drm_mode->clock;
-	dsi_mode->panel_mode = 0; /* TODO: Panel Mode */
 
-	dsi_mode->mode_info = (struct msm_mode_info *)drm_mode->private;
+	dsi_mode->priv_info =
+		(struct dsi_display_mode_priv_info *)drm_mode->private;
 
 	if (msm_is_mode_seamless(drm_mode))
 		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_SEAMLESS;
@@ -59,6 +59,8 @@
 		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS;
 	if (msm_needs_vblank_pre_modeset(drm_mode))
 		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
+	if (msm_is_mode_seamless_dms(drm_mode))
+		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
 }
 
 static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
@@ -84,7 +86,7 @@
 	drm_mode->vrefresh = dsi_mode->timing.refresh_rate;
 	drm_mode->clock = dsi_mode->pixel_clk_khz;
 
-	drm_mode->private = (int *)dsi_mode->mode_info;
+	drm_mode->private = (int *)dsi_mode->priv_info;
 
 	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)
 		drm_mode->flags |= DRM_MODE_FLAG_SEAMLESS;
@@ -92,6 +94,8 @@
 		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS;
 	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
 		drm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET;
+	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DMS)
+		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
 
 	drm_mode_set_name(drm_mode);
 }
@@ -237,10 +241,6 @@
 
 	memset(&(c_bridge->dsi_mode), 0x0, sizeof(struct dsi_display_mode));
 	convert_to_dsi_mode(adjusted_mode, &(c_bridge->dsi_mode));
-
-	pr_debug("note: using panel cmd/vid mode instead of user val\n");
-	c_bridge->dsi_mode.panel_mode =
-		c_bridge->display->panel->mode.panel_mode;
 }
 
 static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
@@ -248,9 +248,9 @@
 				  struct drm_display_mode *adjusted_mode)
 {
 	int rc = 0;
-	bool ret = true;
 	struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
 	struct dsi_display_mode dsi_mode;
+	struct drm_display_mode cur_mode;
 
 	if (!bridge || !mode || !adjusted_mode) {
 		pr_err("Invalid params\n");
@@ -263,31 +263,55 @@
 			DSI_VALIDATE_FLAG_ALLOW_ADJUST);
 	if (rc) {
 		pr_err("[%d] mode is not valid, rc=%d\n", c_bridge->id, rc);
-		ret = false;
-	} else {
-		convert_to_drm_mode(&dsi_mode, adjusted_mode);
+		return false;
 	}
 
-	return ret;
+	if (bridge->encoder && bridge->encoder->crtc) {
+		cur_mode = bridge->encoder->crtc->mode;
+
+		if (!drm_mode_equal(&cur_mode, adjusted_mode))
+			dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
+	}
+
+	convert_to_drm_mode(&dsi_mode, adjusted_mode);
+
+	return true;
 }
 
-int dsi_conn_get_topology(const struct drm_display_mode *drm_mode,
-	struct msm_display_topology *topology,
+int dsi_conn_get_mode_info(const struct drm_display_mode *drm_mode,
+	struct msm_mode_info *mode_info,
 	u32 max_mixer_width)
 {
 	struct dsi_display_mode dsi_mode;
+	struct dsi_mode_info *timing;
 
-	if (!drm_mode || !topology)
+	if (!drm_mode || !mode_info)
 		return -EINVAL;
 
 	convert_to_dsi_mode(drm_mode, &dsi_mode);
 
-	if (!dsi_mode.mode_info)
+	if (!dsi_mode.priv_info)
 		return -EINVAL;
 
-	memcpy(topology, &dsi_mode.mode_info->topology,
+	memset(mode_info, 0, sizeof(*mode_info));
+
+	timing = &dsi_mode.timing;
+	mode_info->frame_rate = dsi_mode.timing.refresh_rate;
+	mode_info->vtotal = DSI_V_TOTAL(timing);
+	mode_info->prefill_lines = dsi_mode.priv_info->panel_prefill_lines;
+	mode_info->jitter_numer = dsi_mode.priv_info->panel_jitter_numer;
+	mode_info->jitter_denom = dsi_mode.priv_info->panel_jitter_denom;
+
+	memcpy(&mode_info->topology, &dsi_mode.priv_info->topology,
 			sizeof(struct msm_display_topology));
 
+	mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
+	if (dsi_mode.priv_info->dsc_enabled) {
+		mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
+		memcpy(&mode_info->comp_info.dsc_info, &dsi_mode.priv_info->dsc,
+			sizeof(dsi_mode.priv_info->dsc));
+	}
+
 	return 0;
 }
 
@@ -343,7 +367,7 @@
 	panel = dsi_display->panel;
 	sde_kms_info_add_keystr(info, "panel name", panel->name);
 
-	switch (panel->mode.panel_mode) {
+	switch (panel->panel_mode) {
 	case DSI_OP_VIDEO_MODE:
 		sde_kms_info_add_keystr(info, "panel mode", "video");
 		break;
@@ -353,7 +377,7 @@
 				panel->cmd_config.mdp_transfer_time_us);
 		break;
 	default:
-		pr_debug("invalid panel type:%d\n", panel->mode.panel_mode);
+		pr_debug("invalid panel type:%d\n", panel->panel_mode);
 		break;
 	}
 	sde_kms_info_add_keystr(info, "dfps support",
@@ -449,6 +473,21 @@
 	return status;
 }
 
+void dsi_connector_put_modes(struct drm_connector *connector,
+	void *display)
+{
+	struct drm_display_mode *drm_mode;
+	struct dsi_display_mode dsi_mode;
+
+	if (!connector || !display)
+		return;
+
+	 list_for_each_entry(drm_mode, &connector->modes, head) {
+		convert_to_dsi_mode(drm_mode, &dsi_mode);
+		dsi_display_put_mode(display, &dsi_mode);
+	}
+}
+
 int dsi_connector_get_modes(struct drm_connector *connector,
 		void *display)
 {
@@ -466,7 +505,7 @@
 		 */
 		goto end;
 	}
-	rc = dsi_display_get_modes(display, NULL, &count);
+	rc = dsi_display_get_mode_count(display, &count);
 	if (rc) {
 		pr_err("failed to get num of modes, rc=%d\n", rc);
 		goto error;
@@ -479,7 +518,7 @@
 		goto end;
 	}
 
-	rc = dsi_display_get_modes(display, modes, &count);
+	rc = dsi_display_get_modes(display, modes);
 	if (rc) {
 		pr_err("failed to get modes, rc=%d\n", rc);
 		count = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
index 45feec9..793f8f1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
@@ -64,15 +64,22 @@
 		void *display);
 
 /**
- * dsi_conn_get_topology - retrieve current topology for the mode selected
+ * dsi_connector_put_modes - callback to free up drm modes of the connector
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display handle
+ */
+void dsi_connector_put_modes(struct drm_connector *connector,
+	void *display);
+
+/**
+ * dsi_conn_get_mode_info - retrieve information on the mode selected
  * @drm_mode: Display mode set for the display
- * @topology: Out parameter. Topology for the mode.
+ * @mode_info: Out parameter. information of the mode.
  * @max_mixer_width: max width supported by HW layer mixer
  * Returns: Zero on success
  */
-int dsi_conn_get_topology(const struct drm_display_mode *drm_mode,
-	struct msm_display_topology *topology,
-	u32 max_mixer_width);
+int dsi_conn_get_mode_info(const struct drm_display_mode *drm_mode,
+	struct msm_mode_info *mode_info, u32 max_mixer_width);
 
 /**
  * dsi_conn_mode_valid - callback to determine if specified mode is valid
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index 8bc82f5..f7b0d7f 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -471,11 +471,21 @@
 {
 	int rc = 0, i = 0;
 	ssize_t len;
-	struct dsi_cmd_desc *cmds = panel->cmd_sets[type].cmds;
-	u32 count = panel->cmd_sets[type].count;
-	enum dsi_cmd_set_state state = panel->cmd_sets[type].state;
+	struct dsi_cmd_desc *cmds;
+	u32 count;
+	enum dsi_cmd_set_state state;
+	struct dsi_display_mode *mode;
 	const struct mipi_dsi_host_ops *ops = panel->host->ops;
 
+	if (!panel || !panel->cur_mode)
+		return -EINVAL;
+
+	mode = panel->cur_mode;
+
+	cmds = mode->priv_info->cmd_sets[type].cmds;
+	count = mode->priv_info->cmd_sets[type].count;
+	state = mode->priv_info->cmd_sets[type].state;
+
 	if (count == 0) {
 		pr_debug("[%s] No commands to be sent for state(%d)\n",
 			 panel->name, type);
@@ -971,7 +981,7 @@
 					  panel->name);
 	if (rc) {
 		pr_err("[%s] failed to get pixel format, rc=%d\n",
-		       panel->name, rc);
+		panel->name, rc);
 		goto error;
 	}
 
@@ -1266,7 +1276,7 @@
 		}
 	}
 
-	panel->mode.panel_mode = panel_mode;
+	panel->panel_mode = panel_mode;
 error:
 	return rc;
 }
@@ -1333,8 +1343,13 @@
 	"qcom,video-to-cmd-mode-switch-commands",
 	"qcom,video-to-cmd-mode-post-switch-commands",
 	"qcom,mdss-dsi-panel-status-command",
+	"qcom,mdss-dsi-lp1-command",
+	"qcom,mdss-dsi-lp2-command",
+	"qcom,mdss-dsi-nolp-command",
 	"PPS not parsed from DTSI, generated dynamically",
 	"ROI not parsed from DTSI, generated dynamically",
+	"qcom,mdss-dsi-timing-switch-command",
+	"qcom,mdss-dsi-post-mode-switch-on-command",
 };
 
 const char *cmd_set_state_map[DSI_CMD_SET_MAX] = {
@@ -1352,8 +1367,13 @@
 	"qcom,video-to-cmd-mode-switch-commands-state",
 	"qcom,video-to-cmd-mode-post-switch-commands-state",
 	"qcom,mdss-dsi-panel-status-command-state",
+	"qcom,mdss-dsi-lp1-command-state",
+	"qcom,mdss-dsi-lp2-command-state",
+	"qcom,mdss-dsi-nolp-command-state",
 	"PPS not parsed from DTSI, generated dynamically",
 	"ROI not parsed from DTSI, generated dynamically",
+	"qcom,mdss-dsi-timing-switch-command-state",
+	"qcom,mdss-dsi-post-mode-switch-on-command-state",
 };
 
 static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt)
@@ -1510,29 +1530,34 @@
 
 }
 
-static int dsi_panel_parse_cmd_sets(struct dsi_panel *panel,
-				    struct device_node *of_node)
+static int dsi_panel_parse_cmd_sets(
+		struct dsi_display_mode_priv_info *priv_info,
+		struct device_node *of_node)
 {
 	int rc = 0;
 	struct dsi_panel_cmd_set *set;
 	u32 i;
 
+	if (!priv_info) {
+		pr_err("invalid mode priv info\n");
+		return -EINVAL;
+	}
+
 	for (i = DSI_CMD_SET_PRE_ON; i < DSI_CMD_SET_MAX; i++) {
-		set = &panel->cmd_sets[i];
+		set = &priv_info->cmd_sets[i];
 		set->type = i;
 		set->count = 0;
 
 		if (i == DSI_CMD_SET_PPS) {
 			rc = dsi_panel_alloc_cmd_packets(set, 1);
 			if (rc)
-				pr_err("[%s] failed to allocate cmd set %d, rc = %d\n",
-					panel->name, i, rc);
+				pr_err("failed to allocate cmd set %d, rc = %d\n",
+					i, rc);
 			set->state = DSI_CMD_SET_STATE_LP;
 		} else {
 			rc = dsi_panel_parse_cmd_sets_sub(set, i, of_node);
 			if (rc)
-				pr_debug("[%s] failed to parse set %d\n",
-					panel->name, i);
+				pr_debug("failed to parse set %d\n", i);
 		}
 	}
 
@@ -1621,13 +1646,17 @@
 	return 0;
 }
 
-static int dsi_panel_parse_jitter_config(struct dsi_panel *panel,
-				     struct device_node *of_node)
+static int dsi_panel_parse_jitter_config(
+				struct dsi_display_mode *mode,
+				struct device_node *of_node)
 {
 	int rc;
+	struct dsi_display_mode_priv_info *priv_info;
 	u32 jitter[DEFAULT_PANEL_JITTER_ARRAY_SIZE] = {0, 0};
 	u64 jitter_val = 0;
 
+	priv_info = mode->priv_info;
+
 	rc = of_property_read_u32_array(of_node, "qcom,mdss-dsi-panel-jitter",
 				jitter, DEFAULT_PANEL_JITTER_ARRAY_SIZE);
 	if (rc) {
@@ -1638,23 +1667,25 @@
 	}
 
 	if (rc || !jitter_val || (jitter_val > MAX_PANEL_JITTER)) {
-		panel->panel_jitter_numer = DEFAULT_PANEL_JITTER_NUMERATOR;
-		panel->panel_jitter_denom = DEFAULT_PANEL_JITTER_DENOMINATOR;
+		priv_info->panel_jitter_numer = DEFAULT_PANEL_JITTER_NUMERATOR;
+		priv_info->panel_jitter_denom =
+					DEFAULT_PANEL_JITTER_DENOMINATOR;
 	} else {
-		panel->panel_jitter_numer = jitter[0];
-		panel->panel_jitter_denom = jitter[1];
+		priv_info->panel_jitter_numer = jitter[0];
+		priv_info->panel_jitter_denom = jitter[1];
 	}
 
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-prefill-lines",
-				  &panel->panel_prefill_lines);
+				  &priv_info->panel_prefill_lines);
 	if (rc) {
 		pr_debug("panel prefill lines are not defined rc=%d\n", rc);
-		panel->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES;
-	} else if (panel->panel_prefill_lines >=
-					DSI_V_TOTAL(&panel->mode.timing))  {
+		priv_info->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES;
+	} else if (priv_info->panel_prefill_lines >=
+					DSI_V_TOTAL(&mode->timing)) {
 		pr_debug("invalid prefill lines config=%d setting to:%d\n",
-		      panel->panel_prefill_lines, DEFAULT_PANEL_PREFILL_LINES);
-		panel->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES;
+		priv_info->panel_prefill_lines, DEFAULT_PANEL_PREFILL_LINES);
+
+		priv_info->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES;
 	}
 
 	return 0;
@@ -2041,38 +2072,85 @@
 	return 0;
 }
 
-int dsi_panel_parse_dsc_params(struct dsi_panel *panel,
+
+static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
+				struct device_node *of_node)
+{
+	const char *data;
+	u32 len, i;
+	int rc = 0;
+	struct dsi_display_mode_priv_info *priv_info;
+
+	priv_info = mode->priv_info;
+
+	data = of_get_property(of_node,
+			"qcom,mdss-dsi-panel-phy-timings", &len);
+	if (!data) {
+		pr_debug("Unable to read Phy timing settings");
+	} else {
+		priv_info->phy_timing_val =
+			kzalloc((sizeof(u32) * len), GFP_KERNEL);
+		if (!priv_info->phy_timing_val)
+			return -EINVAL;
+
+		for (i = 0; i < len; i++)
+			priv_info->phy_timing_val[i] = data[i];
+
+		priv_info->phy_timing_len = len;
+	};
+
+	mode->pixel_clk_khz = (DSI_H_TOTAL(&mode->timing) *
+			DSI_V_TOTAL(&mode->timing) *
+			mode->timing.refresh_rate) / 1000;
+	return rc;
+}
+
+static int dsi_panel_parse_dsc_params(struct dsi_display_mode *mode,
 				struct device_node *of_node)
 {
 	u32 data;
 	int rc = -EINVAL;
 	int intf_width;
+	const char *compression;
+	struct dsi_display_mode_priv_info *priv_info;
 
-	if (!panel->dsc_enabled)
+	if (!mode || !mode->priv_info)
+		return -EINVAL;
+
+	priv_info = mode->priv_info;
+
+	priv_info->dsc_enabled = false;
+	compression = of_get_property(of_node, "qcom,compression-mode", NULL);
+	if (compression && !strcmp(compression, "dsc"))
+		priv_info->dsc_enabled = true;
+
+	if (!priv_info->dsc_enabled) {
+		pr_debug("dsc compression is not enabled for the mode");
 		return 0;
+	}
 
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-height", &data);
 	if (rc) {
 		pr_err("failed to parse qcom,mdss-dsc-slice-height\n");
 		goto error;
 	}
-	panel->dsc.slice_height = data;
+	priv_info->dsc.slice_height = data;
 
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-width", &data);
 	if (rc) {
 		pr_err("failed to parse qcom,mdss-dsc-slice-width\n");
 		goto error;
 	}
-	panel->dsc.slice_width = data;
+	priv_info->dsc.slice_width = data;
 
-	intf_width = panel->mode.timing.h_active;
-	if (intf_width % panel->dsc.slice_width) {
+	intf_width = mode->timing.h_active;
+	if (intf_width % priv_info->dsc.slice_width) {
 		pr_err("invalid slice width for the panel\n");
 		goto error;
 	}
 
-	panel->dsc.pic_width = panel->mode.timing.h_active;
-	panel->dsc.pic_height = panel->mode.timing.v_active;
+	priv_info->dsc.pic_width = mode->timing.h_active;
+	priv_info->dsc.pic_height = mode->timing.v_active;
 
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-per-pkt",
 			&data);
@@ -2080,7 +2158,7 @@
 		pr_err("failed to parse qcom,mdss-dsc-slice-per-pkt\n");
 		goto error;
 	}
-	panel->dsc.slice_per_pkt = data;
+	priv_info->dsc.slice_per_pkt = data;
 
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-component",
 		&data);
@@ -2088,7 +2166,7 @@
 		pr_err("failed to parse qcom,mdss-dsc-bit-per-component\n");
 		goto error;
 	}
-	panel->dsc.bpc = data;
+	priv_info->dsc.bpc = data;
 
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-pixel",
 			&data);
@@ -2096,16 +2174,16 @@
 		pr_err("failed to parse qcom,mdss-dsc-bit-per-pixel\n");
 		goto error;
 	}
-	panel->dsc.bpp = data;
+	priv_info->dsc.bpp = data;
 
-	panel->dsc.block_pred_enable = of_property_read_bool(of_node,
+	priv_info->dsc.block_pred_enable = of_property_read_bool(of_node,
 		"qcom,mdss-dsc-block-prediction-enable");
 
-	panel->dsc.full_frame_slices = DIV_ROUND_UP(intf_width,
-		panel->dsc.slice_width);
+	priv_info->dsc.full_frame_slices = DIV_ROUND_UP(intf_width,
+		priv_info->dsc.slice_width);
 
-	dsi_dsc_populate_static_param(&panel->dsc);
-	dsi_dsc_pclk_param_calc(&panel->dsc, intf_width);
+	dsi_dsc_populate_static_param(&priv_info->dsc);
+	dsi_dsc_pclk_param_calc(&priv_info->dsc, intf_width);
 
 error:
 	return rc;
@@ -2157,9 +2235,9 @@
 	return 0;
 }
 
-static int dsi_panel_parse_topology(struct dsi_panel *panel,
-				struct device_node *of_node,
-				int topology_override)
+static int dsi_panel_parse_topology(
+		struct dsi_display_mode_priv_info *priv_info,
+		struct device_node *of_node, int topology_override)
 {
 	struct msm_display_topology *topology;
 	u32 top_count, top_sel, *array = NULL;
@@ -2230,9 +2308,7 @@
 		topology[top_sel].num_intf);
 
 parse_done:
-	panel->mode.mode_info = kzalloc(sizeof(struct msm_mode_info),
-			GFP_KERNEL);
-	memcpy(&panel->mode.mode_info->topology, &topology[top_sel],
+	memcpy(&priv_info->topology, &topology[top_sel],
 		sizeof(struct msm_display_topology));
 parse_fail:
 	kfree(topology);
@@ -2323,14 +2399,40 @@
 	return rc;
 }
 
+static int dsi_panel_parse_dms_info(struct dsi_panel *panel,
+	struct device_node *of_node)
+{
+	int dms_enabled;
+	const char *data;
+
+	if (!of_node || !panel) {
+		pr_err("invalid params\n");
+		return -EINVAL;
+	}
+
+	panel->dms_mode = DSI_DMS_MODE_DISABLED;
+	dms_enabled = of_property_read_bool(of_node,
+		"qcom,dynamic-mode-switch-enabled");
+	if (!dms_enabled)
+		return 0;
+
+	data = of_get_property(of_node, "qcom,dynamic-mode-switch-type", NULL);
+	if (data && !strcmp(data, "dynamic-resolution-switch-immediate")) {
+		panel->dms_mode = DSI_DMS_MODE_RES_SWITCH_IMMEDIATE;
+	} else {
+		pr_err("[%s] unsupported dynamic switch mode: %s\n",
+							panel->name, data);
+		return -EINVAL;
+	}
+
+	return 0;
+};
+
 struct dsi_panel *dsi_panel_get(struct device *parent,
 				struct device_node *of_node,
 				int topology_override)
 {
 	struct dsi_panel *panel;
-	const char *data;
-	const char *compression;
-	u32 len = 0;
 	int rc = 0;
 
 	panel = kzalloc(sizeof(*panel), GFP_KERNEL);
@@ -2342,52 +2444,6 @@
 	if (!panel->name)
 		panel->name = DSI_PANEL_DEFAULT_LABEL;
 
-	panel->dsc_enabled = false;
-	compression = of_get_property(of_node, "qcom,compression-mode", NULL);
-	if (compression && !strcmp(compression, "dsc"))
-		panel->dsc_enabled = true;
-
-	rc = dsi_panel_parse_timing(&panel->mode.timing, of_node);
-	if (rc) {
-		pr_err("failed to parse panel timing, rc=%d\n", rc);
-		goto error;
-	}
-
-	rc = dsi_panel_parse_dsc_params(panel, of_node);
-	if (rc) {
-		pr_err("failed to parse dsc params, rc=%d\n", rc);
-		goto error;
-	}
-
-	data = of_get_property(of_node,
-		"qcom,mdss-dsi-panel-phy-timings", &len);
-	if (!data) {
-		pr_debug("%s:%d, Unable to read Phy timing settings",
-		       __func__, __LINE__);
-	} else {
-		int i = 0;
-
-		panel->phy_timing_val = kzalloc((sizeof(u32) * len),
-			GFP_KERNEL);
-		if (!panel->phy_timing_val) {
-			kfree(panel);
-			return ERR_PTR(-ENOMEM);
-		}
-		for (i = 0; i < len; i++)
-			panel->phy_timing_val[i] = data[i];
-	}
-	panel->phy_timing_len = len;
-
-	panel->mode.pixel_clk_khz = (DSI_H_TOTAL(&panel->mode.timing) *
-				    DSI_V_TOTAL(&panel->mode.timing) *
-				    panel->mode.timing.refresh_rate) / 1000;
-
-	rc = dsi_panel_parse_topology(panel, of_node, topology_override);
-	if (rc) {
-		pr_err("failed to parse panel topology, rc=%d\n", rc);
-		goto error;
-	}
-
 	rc = dsi_panel_parse_host_config(panel, of_node);
 	if (rc) {
 		pr_err("failed to parse host configuration, rc=%d\n", rc);
@@ -2410,12 +2466,6 @@
 		goto error;
 	}
 
-	rc = dsi_panel_parse_cmd_sets(panel, of_node);
-	if (rc) {
-		pr_err("failed to parse command sets, rc=%d\n", rc);
-		goto error;
-	}
-
 	rc = dsi_panel_parse_power_cfg(parent, panel, of_node);
 	if (rc)
 		pr_err("failed to parse power config, rc=%d\n", rc);
@@ -2428,13 +2478,10 @@
 	if (rc)
 		pr_err("failed to parse backlight config, rc=%d\n", rc);
 
-	rc = dsi_panel_parse_jitter_config(panel, of_node);
-	if (rc)
-		pr_err("failed to parse panel jitter config, rc=%d\n", rc);
 
 	rc = dsi_panel_parse_misc_features(panel, of_node);
 	if (rc)
-		pr_err("failed to parse panel features, rc=%d\n", rc);
+		pr_err("failed to parse misc features, rc=%d\n", rc);
 
 	rc = dsi_panel_parse_hdr_config(panel, of_node);
 	if (rc)
@@ -2444,6 +2491,16 @@
 	if (rc)
 		pr_debug("failed to partial update caps, rc=%d\n", rc);
 
+	rc = dsi_panel_get_mode_count(panel, of_node);
+	if (rc) {
+		pr_err("failed to get mode count, rc=%d\n", rc);
+		goto error;
+	}
+
+	rc = dsi_panel_parse_dms_info(panel, of_node);
+	if (rc)
+		pr_debug("failed to get dms info, rc=%d\n", rc);
+
 	panel->panel_of_node = of_node;
 	drm_panel_init(&panel->drm_panel);
 	mutex_init(&panel->panel_lock);
@@ -2456,14 +2513,6 @@
 
 void dsi_panel_put(struct dsi_panel *panel)
 {
-	u32 i;
-
-	for (i = 0; i < DSI_CMD_SET_MAX; i++)
-		dsi_panel_destroy_cmd_packets(&panel->cmd_sets[i]);
-
-	kfree(panel->mode.mode_info);
-
-	/* TODO:  more free */
 	kfree(panel);
 }
 
@@ -2576,20 +2625,42 @@
 	return 0;
 }
 
-int dsi_panel_get_mode_count(struct dsi_panel *panel, u32 *count)
+int dsi_panel_get_mode_count(struct dsi_panel *panel,
+	struct device_node *of_node)
 {
-	int rc = 0;
+	const u32 SINGLE_MODE_SUPPORT = 1;
+	struct device_node *timings_np;
+	int count, rc = 0;
 
-	if (!panel || !count) {
+	if (!of_node || !panel) {
 		pr_err("invalid params\n");
 		return -EINVAL;
 	}
 
-	mutex_lock(&panel->panel_lock);
-	/* TODO:  DT format has not been decided for multiple modes. */
-	*count = 1;
+	panel->num_timing_nodes = 0;
 
-	mutex_unlock(&panel->panel_lock);
+	timings_np = of_get_child_by_name(of_node,
+			"qcom,mdss-dsi-display-timings");
+	if (!timings_np) {
+		pr_err("no display timing nodes defined\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	count = of_get_child_count(timings_np);
+	if (!count || count > DSI_MODE_MAX) {
+		pr_err("invalid count of timing nodes: %d\n", count);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	/* No multiresolution support is available for video mode panels */
+	if (panel->panel_mode != DSI_OP_CMD_MODE)
+		count = SINGLE_MODE_SUPPORT;
+
+	panel->num_timing_nodes = count;
+
+error:
 	return rc;
 }
 
@@ -2629,11 +2700,27 @@
 	return rc;
 }
 
-int dsi_panel_get_mode(struct dsi_panel *panel,
-			u32 index,
-			struct dsi_display_mode *mode)
+void dsi_panel_put_mode(struct dsi_display_mode *mode)
 {
-	int rc = 0;
+	int i;
+
+	if (!mode->priv_info)
+		return;
+
+	for (i = 0; i < DSI_CMD_SET_MAX; i++)
+		dsi_panel_destroy_cmd_packets(&mode->priv_info->cmd_sets[i]);
+
+	kfree(mode->priv_info);
+}
+
+int dsi_panel_get_mode(struct dsi_panel *panel,
+			u32 index, struct dsi_display_mode *mode,
+			int topology_override)
+{
+	struct device_node *timings_np, *child_np;
+	struct dsi_display_mode_priv_info *prv_info;
+	u32 child_idx = 0;
+	int rc = 0, num_timings;
 
 	if (!panel || !mode) {
 		pr_err("invalid params\n");
@@ -2641,11 +2728,77 @@
 	}
 
 	mutex_lock(&panel->panel_lock);
-	if (index != 0)
-		rc = -ENOTSUPP; /* TODO: Support more than one mode */
-	else
-		memcpy(mode, &panel->mode, sizeof(*mode));
 
+	mode->priv_info = kzalloc(sizeof(*mode->priv_info), GFP_KERNEL);
+	if (!mode->priv_info) {
+		rc = -ENOMEM;
+		goto done;
+	}
+
+	prv_info = mode->priv_info;
+
+	timings_np = of_get_child_by_name(panel->panel_of_node,
+		"qcom,mdss-dsi-display-timings");
+	if (!timings_np) {
+		pr_err("no display timing nodes defined\n");
+		rc = -EINVAL;
+		goto parse_fail;
+	}
+
+	num_timings = of_get_child_count(timings_np);
+	if (!num_timings || num_timings > DSI_MODE_MAX) {
+		pr_err("invalid count of timing nodes: %d\n", num_timings);
+		rc = -EINVAL;
+		goto parse_fail;
+	}
+
+	for_each_child_of_node(timings_np, child_np) {
+		if (index != child_idx++)
+			continue;
+
+		rc = dsi_panel_parse_timing(&mode->timing, child_np);
+		if (rc) {
+			pr_err("failed to parse panel timing, rc=%d\n", rc);
+			goto parse_fail;
+		}
+
+		rc = dsi_panel_parse_dsc_params(mode, child_np);
+		if (rc) {
+			pr_err("failed to parse dsc params, rc=%d\n", rc);
+			goto parse_fail;
+		}
+
+		rc = dsi_panel_parse_topology(prv_info, child_np,
+				topology_override);
+		if (rc) {
+			pr_err("failed to parse panel topology, rc=%d\n", rc);
+			goto parse_fail;
+		}
+
+		rc = dsi_panel_parse_cmd_sets(prv_info, child_np);
+		if (rc) {
+			pr_err("failed to parse command sets, rc=%d\n", rc);
+			goto parse_fail;
+		}
+
+		rc = dsi_panel_parse_jitter_config(mode, child_np);
+		if (rc)
+			pr_err(
+			"failed to parse panel jitter config, rc=%d\n", rc);
+
+		rc = dsi_panel_parse_phy_timing(mode, child_np);
+		if (rc) {
+			pr_err(
+			"failed to parse panel phy timings, rc=%d\n", rc);
+			goto parse_fail;
+		}
+	}
+	goto done;
+
+parse_fail:
+	kfree(mode->priv_info);
+	mode->priv_info = NULL;
+done:
 	mutex_unlock(&panel->panel_lock);
 	return rc;
 }
@@ -2663,11 +2816,11 @@
 
 	mutex_lock(&panel->panel_lock);
 
-	config->panel_mode = panel->mode.panel_mode;
+	config->panel_mode = panel->panel_mode;
 	memcpy(&config->common_config, &panel->host_config,
 	       sizeof(config->common_config));
 
-	if (mode->panel_mode == DSI_OP_VIDEO_MODE) {
+	if (panel->panel_mode == DSI_OP_VIDEO_MODE) {
 		memcpy(&config->u.video_engine, &panel->video_config,
 		       sizeof(config->u.video_engine));
 	} else {
@@ -2677,8 +2830,8 @@
 
 	memcpy(&config->video_timing, &mode->timing,
 	       sizeof(config->video_timing));
-	config->video_timing.dsc_enabled = panel->dsc_enabled;
-	config->video_timing.dsc = &panel->dsc;
+	config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled;
+	config->video_timing.dsc = &mode->priv_info->dsc;
 
 	config->esc_clk_rate_hz = 19200000;
 	mutex_unlock(&panel->panel_lock);
@@ -2715,17 +2868,20 @@
 {
 	int rc = 0;
 	struct dsi_panel_cmd_set *set = NULL;
+	struct dsi_display_mode_priv_info *priv_info = NULL;
 
-	if (!panel) {
+	if (!panel || !panel->cur_mode) {
 		pr_err("invalid params\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&panel->panel_lock);
 
-	set = &panel->cmd_sets[DSI_CMD_SET_PPS];
+	priv_info = panel->cur_mode->priv_info;
 
-	dsi_dsc_create_pps_buf_cmd(&panel->dsc, panel->dsc_pps_cmd, 0);
+	set = &priv_info->cmd_sets[DSI_CMD_SET_PPS];
+
+	dsi_dsc_create_pps_buf_cmd(&priv_info->dsc, panel->dsc_pps_cmd, 0);
 	rc = dsi_panel_create_cmd_packets(panel->dsc_pps_cmd,
 					  DSI_CMD_PPS_SIZE, 1, set->cmds);
 	if (rc) {
@@ -2745,6 +2901,60 @@
 	return rc;
 }
 
+int dsi_panel_set_lp1(struct dsi_panel *panel)
+{
+	int rc = 0;
+
+	if (!panel) {
+		pr_err("invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&panel->panel_lock);
+	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP1);
+	if (rc)
+		pr_err("[%s] failed to send DSI_CMD_SET_LP1 cmd, rc=%d\n",
+		       panel->name, rc);
+	mutex_unlock(&panel->panel_lock);
+	return rc;
+}
+
+int dsi_panel_set_lp2(struct dsi_panel *panel)
+{
+	int rc = 0;
+
+	if (!panel) {
+		pr_err("invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&panel->panel_lock);
+	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP2);
+	if (rc)
+		pr_err("[%s] failed to send DSI_CMD_SET_LP2 cmd, rc=%d\n",
+		       panel->name, rc);
+	mutex_unlock(&panel->panel_lock);
+	return rc;
+}
+
+int dsi_panel_set_nolp(struct dsi_panel *panel)
+{
+	int rc = 0;
+
+	if (!panel) {
+		pr_err("invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&panel->panel_lock);
+	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_NOLP);
+	if (rc)
+		pr_err("[%s] failed to send DSI_CMD_SET_NOLP cmd, rc=%d\n",
+		       panel->name, rc);
+	mutex_unlock(&panel->panel_lock);
+	return rc;
+}
+
 int dsi_panel_prepare(struct dsi_panel *panel)
 {
 	int rc = 0;
@@ -2777,11 +2987,11 @@
 	return rc;
 }
 
-static int dsi_panel_roi_prepare_dcs_cmds(struct dsi_panel *panel,
+static int dsi_panel_roi_prepare_dcs_cmds(struct dsi_panel_cmd_set *set,
 		struct dsi_rect *roi, int ctrl_idx, int unicast)
 {
 	static const int ROI_CMD_LEN = 5;
-	struct dsi_panel_cmd_set *set = &panel->cmd_sets[DSI_CMD_SET_ROI];
+
 	int rc = 0;
 
 	/* DTYPE_DCS_LWRITE */
@@ -2856,13 +3066,18 @@
 		struct dsi_rect *roi)
 {
 	int rc = 0;
+	struct dsi_panel_cmd_set *set;
+	struct dsi_display_mode_priv_info *priv_info;
 
-	if (!panel) {
+	if (!panel || !panel->cur_mode) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
 
-	rc = dsi_panel_roi_prepare_dcs_cmds(panel, roi, ctrl_idx, true);
+	priv_info = panel->cur_mode->priv_info;
+	set = &priv_info->cmd_sets[DSI_CMD_SET_ROI];
+
+	rc = dsi_panel_roi_prepare_dcs_cmds(set, roi, ctrl_idx, true);
 	if (rc) {
 		pr_err("[%s] failed to prepare DSI_CMD_SET_ROI cmds, rc=%d\n",
 				panel->name, rc);
@@ -2880,11 +3095,51 @@
 
 	mutex_unlock(&panel->panel_lock);
 
-	dsi_panel_destroy_cmd_packets(&panel->cmd_sets[DSI_CMD_SET_ROI]);
+	dsi_panel_destroy_cmd_packets(set);
 
 	return rc;
 }
 
+int dsi_panel_switch(struct dsi_panel *panel)
+{
+	int rc = 0;
+
+	if (!panel) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&panel->panel_lock);
+
+	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_TIMING_SWITCH);
+	if (rc)
+		pr_err("[%s] failed to send DSI_CMD_SET_TIMING_SWITCH cmds, rc=%d\n",
+		       panel->name, rc);
+
+	mutex_unlock(&panel->panel_lock);
+	return rc;
+}
+
+int dsi_panel_post_switch(struct dsi_panel *panel)
+{
+	int rc = 0;
+
+	if (!panel) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&panel->panel_lock);
+
+	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_TIMING_SWITCH);
+	if (rc)
+		pr_err("[%s] failed to send DSI_CMD_SET_POST_TIMING_SWITCH cmds, rc=%d\n",
+		       panel->name, rc);
+
+	mutex_unlock(&panel->panel_lock);
+	return rc;
+}
+
 int dsi_panel_enable(struct dsi_panel *panel)
 {
 	int rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index 5380049..0ee23f3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -21,7 +21,6 @@
 #include <linux/errno.h>
 #include <linux/leds.h>
 #include <drm/drm_panel.h>
-#include <drm/drm_mipi_dsi.h>
 #include <drm/msm_drm.h>
 
 #include "dsi_defs.h"
@@ -33,6 +32,8 @@
 #define MAX_BL_LEVEL 4096
 #define DSI_CMD_PPS_SIZE 135
 
+#define DSI_MODE_MAX 5
+
 enum dsi_panel_rotation {
 	DSI_PANEL_ROTATE_NONE = 0,
 	DSI_PANEL_ROTATE_HV_FLIP,
@@ -40,32 +41,6 @@
 	DSI_PANEL_ROTATE_V_FLIP
 };
 
-enum dsi_cmd_set_type {
-	DSI_CMD_SET_PRE_ON = 0,
-	DSI_CMD_SET_ON,
-	DSI_CMD_SET_POST_ON,
-	DSI_CMD_SET_PRE_OFF,
-	DSI_CMD_SET_OFF,
-	DSI_CMD_SET_POST_OFF,
-	DSI_CMD_SET_PRE_RES_SWITCH,
-	DSI_CMD_SET_RES_SWITCH,
-	DSI_CMD_SET_POST_RES_SWITCH,
-	DSI_CMD_SET_CMD_TO_VID_SWITCH,
-	DSI_CMD_SET_POST_CMD_TO_VID_SWITCH,
-	DSI_CMD_SET_VID_TO_CMD_SWITCH,
-	DSI_CMD_SET_POST_VID_TO_CMD_SWITCH,
-	DSI_CMD_SET_PANEL_STATUS,
-	DSI_CMD_SET_PPS,
-	DSI_CMD_SET_ROI,
-	DSI_CMD_SET_MAX
-};
-
-enum dsi_cmd_set_state {
-	DSI_CMD_SET_STATE_LP = 0,
-	DSI_CMD_SET_STATE_HS,
-	DSI_CMD_SET_STATE_MAX
-};
-
 enum dsi_backlight_type {
 	DSI_BACKLIGHT_PWM = 0,
 	DSI_BACKLIGHT_WLED,
@@ -82,6 +57,11 @@
 	MODE_GPIO_LOW,
 };
 
+enum dsi_dms_mode {
+	DSI_DMS_MODE_DISABLED = 0,
+	DSI_DMS_MODE_RES_SWITCH_IMMEDIATE,
+};
+
 struct dsi_dfps_capabilities {
 	bool dfps_support;
 	enum dsi_dfps_type type;
@@ -101,20 +81,6 @@
 	enum dsi_panel_rotation rotation;
 };
 
-struct dsi_cmd_desc {
-	struct mipi_dsi_msg msg;
-	bool last_command;
-	u32  post_wait_ms;
-};
-
-struct dsi_panel_cmd_set {
-	enum dsi_cmd_set_type type;
-	enum dsi_cmd_set_state state;
-	u32 count;
-	int ctrl_idx;
-	struct dsi_cmd_desc *cmds;
-};
-
 struct dsi_backlight_config {
 	enum dsi_backlight_type type;
 
@@ -162,19 +128,17 @@
 	struct dsi_host_common_cfg host_config;
 	struct dsi_video_engine_cfg video_config;
 	struct dsi_cmd_engine_cfg cmd_config;
+	enum dsi_op_mode panel_mode;
 
 	struct dsi_dfps_capabilities dfps_caps;
 	struct msm_roi_caps roi_caps;
 
-	struct dsi_panel_cmd_set cmd_sets[DSI_CMD_SET_MAX];
 	struct dsi_panel_phy_props phy_props;
 
-	u32 *phy_timing_val;
-	u32 phy_timing_len;
+	struct dsi_display_mode *cur_mode;
+	u32 num_timing_nodes;
 
 	struct dsi_regulator_info power_info;
-	struct dsi_display_mode mode;
-
 	struct dsi_backlight_config bl_config;
 	struct dsi_panel_reset_config reset_config;
 	struct dsi_pinctrl_info pinctrl;
@@ -184,15 +148,11 @@
 	bool ulps_enabled;
 	bool allow_phy_power_off;
 
-	u32 panel_jitter_numer;
-	u32 panel_jitter_denom;
-	u32 panel_prefill_lines;
 	bool panel_initialized;
 	bool te_using_watchdog_timer;
 
-	bool dsc_enabled;
 	char dsc_pps_cmd[DSI_CMD_PPS_SIZE];
-	struct msm_display_dsc_info dsc;
+	enum dsi_dms_mode dms_mode;
 };
 
 static inline bool dsi_panel_ulps_feature_enabled(struct dsi_panel *panel)
@@ -208,17 +168,26 @@
 struct dsi_panel *dsi_panel_get(struct device *parent,
 				struct device_node *of_node,
 				int topology_override);
+
 void dsi_panel_put(struct dsi_panel *panel);
 
 int dsi_panel_drv_init(struct dsi_panel *panel, struct mipi_dsi_host *host);
+
 int dsi_panel_drv_deinit(struct dsi_panel *panel);
 
-int dsi_panel_get_mode_count(struct dsi_panel *panel, u32 *count);
+int dsi_panel_get_mode_count(struct dsi_panel *panel,
+		struct device_node *of_node);
+
+void dsi_panel_put_mode(struct dsi_display_mode *mode);
+
 int dsi_panel_get_mode(struct dsi_panel *panel,
 		       u32 index,
-		       struct dsi_display_mode *mode);
+		       struct dsi_display_mode *mode,
+		       int topology_override);
+
 int dsi_panel_validate_mode(struct dsi_panel *panel,
 			    struct dsi_display_mode *mode);
+
 int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel,
 				    struct dsi_display_mode *mode,
 				    struct dsi_host_config *config);
@@ -230,6 +199,12 @@
 
 int dsi_panel_pre_prepare(struct dsi_panel *panel);
 
+int dsi_panel_set_lp1(struct dsi_panel *panel);
+
+int dsi_panel_set_lp2(struct dsi_panel *panel);
+
+int dsi_panel_set_nolp(struct dsi_panel *panel);
+
 int dsi_panel_prepare(struct dsi_panel *panel);
 
 int dsi_panel_enable(struct dsi_panel *panel);
@@ -251,6 +226,10 @@
 int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
 		struct dsi_rect *roi);
 
+int dsi_panel_switch(struct dsi_panel *panel);
+
+int dsi_panel_post_switch(struct dsi_panel *panel);
+
 void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width);
 
 #endif /* _DSI_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index d97e4ef..f05d760 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -617,7 +617,7 @@
 			goto fail;
 		}
 
-		aspace = msm_gem_smmu_address_space_create(&pdev->dev,
+		aspace = msm_gem_smmu_address_space_create(dev,
 				mmu, "mdp5");
 		if (IS_ERR(aspace)) {
 			ret = PTR_ERR(aspace);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index efeea31..e9de729 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -131,6 +131,10 @@
 				&connector->encoder->crtc->state->mode))
 			continue;
 
+		if (msm_is_mode_seamless_dms(
+			       &connector->encoder->crtc->state->adjusted_mode))
+			continue;
+
 		funcs = encoder->helper_private;
 
 		DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
@@ -166,6 +170,9 @@
 		if (msm_is_mode_seamless(&crtc->state->mode))
 			continue;
 
+		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
+			continue;
+
 		funcs = crtc->helper_private;
 
 		DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index d2ac684..33ef04b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -121,13 +121,37 @@
 		msm_drm_helper_hotplug_event(dev);
 }
 
+/**
+ * msm_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * This is a wrapper for the drm_atomic_helper_check to check the modeset
+ * and state checking for planes. Additionally it checks if any secure
+ * transition(moving CRTC and planes between secure and non-secure states and
+ * vice versa) is allowed or not. When going to secure state, planes
+ * with fb_mode as dir translated only can be staged on the CRTC, and only one
+ * CRTC should be active.
+ * Also mixing of secure and non-secure is not allowed.
+ *
+ * RETURNS
+ * Zero for success or -errorno.
+ */
 int msm_atomic_check(struct drm_device *dev,
 			    struct drm_atomic_state *state)
 {
+	struct msm_drm_private *priv;
+
 	if (msm_is_suspend_blocked(dev)) {
 		DRM_DEBUG("rejecting commit during suspend\n");
 		return -EBUSY;
 	}
+
+	priv = dev->dev_private;
+	if (priv && priv->kms && priv->kms->funcs &&
+			priv->kms->funcs->atomic_check)
+		return priv->kms->funcs->atomic_check(priv->kms, state);
+
 	return drm_atomic_helper_check(dev, state);
 }
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 96ab883..c6943de 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -216,10 +216,12 @@
  * enum msm_event_wait - type of HW events to wait for
  * @MSM_ENC_COMMIT_DONE - wait for the driver to flush the registers to HW
  * @MSM_ENC_TX_COMPLETE - wait for the HW to transfer the frame to panel
+ * @MSM_ENC_VBLANK - wait for the HW VBLANK event (for driver-internal waiters)
  */
 enum msm_event_wait {
 	MSM_ENC_COMMIT_DONE = 0,
 	MSM_ENC_TX_COMPLETE,
+	MSM_ENC_VBLANK,
 };
 
 /**
@@ -387,10 +389,22 @@
 
 /**
  * struct msm_mode_info - defines all msm custom mode info
- * @topology - supported topology for the mode
+ * @frame_rate:      frame_rate of the mode
+ * @vtotal:          vtotal calculated for the mode
+ * @prefill_lines:   prefill lines based on porches.
+ * @jitter_numer:	display panel jitter numerator configuration
+ * @jitter_denom:	display panel jitter denominator configuration
+ * @topology:        supported topology for the mode
+ * @comp_info:       compression info supported
  */
 struct msm_mode_info {
+	uint32_t frame_rate;
+	uint32_t vtotal;
+	uint32_t prefill_lines;
+	uint32_t jitter_numer;
+	uint32_t jitter_denom;
 	struct msm_display_topology topology;
+	struct msm_compression_info comp_info;
 };
 
 /**
@@ -410,12 +424,6 @@
  * @is_primary:         Set to true if display is primary display
  * @is_te_using_watchdog_timer:  Boolean to indicate watchdog TE is
  *				 used instead of panel TE in cmd mode panels
- * @frame_rate:		Display frame rate
- * @prefill_lines:	prefill lines based on porches.
- * @vtotal:		display vertical total
- * @jitter_numer:	display panel jitter numerator configuration
- * @jitter_denom:	display panel jitter denominator configuration
- * @comp_info:          Compression supported by the display
  * @roi_caps:           Region of interest capability info
  */
 struct msm_display_info {
@@ -435,13 +443,6 @@
 
 	bool is_primary;
 	bool is_te_using_watchdog_timer;
-	uint32_t frame_rate;
-	uint32_t prefill_lines;
-	uint32_t vtotal;
-	uint32_t jitter_numer;
-	uint32_t jitter_denom;
-
-	struct msm_compression_info comp_info;
 	struct msm_roi_caps roi_caps;
 };
 
@@ -662,13 +663,57 @@
 
 /* For SDE  display */
 struct msm_gem_address_space *
-msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu,
+msm_gem_smmu_address_space_create(struct drm_device *dev, struct msm_mmu *mmu,
 		const char *name);
 
+/**
+ * msm_gem_add_obj_to_aspace_active_list: adds obj to active obj list in aspace
+ */
+void msm_gem_add_obj_to_aspace_active_list(
+		struct msm_gem_address_space *aspace,
+		struct drm_gem_object *obj);
+
+/**
+ * msm_gem_remove_obj_from_aspace_active_list: removes obj from  active obj
+ * list in aspace
+ */
+void msm_gem_remove_obj_from_aspace_active_list(
+		struct msm_gem_address_space *aspace,
+		struct drm_gem_object *obj);
+
+/**
+ * msm_gem_smmu_address_space_get: returns the aspace pointer for the requested
+ * domain
+ */
 struct msm_gem_address_space *
 msm_gem_smmu_address_space_get(struct drm_device *dev,
 		unsigned int domain);
 
+/**
+ * msm_gem_aspace_domain_attach_detach: function to inform the attach/detach
+ * of the domain for this aspace
+ */
+void msm_gem_aspace_domain_attach_detach_update(
+		struct msm_gem_address_space *aspace,
+		bool is_detach);
+
+/**
+ * msm_gem_address_space_register_cb: function to register callback for attach
+ * and detach of the domain
+ */
+int msm_gem_address_space_register_cb(
+		struct msm_gem_address_space *aspace,
+		void (*cb)(void *, bool),
+		void *cb_data);
+
+/**
+ * msm_gem_address_space_register_cb: function to unregister callback
+ */
+int msm_gem_address_space_unregister_cb(
+		struct msm_gem_address_space *aspace,
+		void (*cb)(void *, bool),
+		void *cb_data);
+
 int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 		struct drm_file *file);
 
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index a7d06d1..d64dcc6 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -311,6 +311,10 @@
 		if (iommu_present(&platform_bus_type)) {
 			msm_gem_unmap_vma(domain->aspace, domain,
 				msm_obj->sgt, get_dmabuf_ptr(obj));
+
+			msm_gem_remove_obj_from_aspace_active_list(
+					domain->aspace,
+					obj);
 		}
 
 		obj_remove_domain(domain);
@@ -390,10 +394,12 @@
 			msm_obj->flags);
 	}
 
-	if (!ret && domain)
+	if (!ret && domain) {
 		*iova = domain->iova;
-	else
+		msm_gem_add_obj_to_aspace_active_list(aspace, obj);
+	} else {
 		obj_remove_domain(domain);
+	}
 
 	return ret;
 }
@@ -441,6 +447,63 @@
 	// things that are no longer needed..
 }
 
+void msm_gem_aspace_domain_attach_detach_update(
+		struct msm_gem_address_space *aspace,
+		bool is_detach)
+{
+	struct msm_gem_object *msm_obj;
+	struct drm_gem_object *obj;
+	struct aspace_client *aclient;
+	int ret;
+	uint32_t iova;
+
+	if (!aspace)
+		return;
+
+	mutex_lock(&aspace->dev->struct_mutex);
+	if (is_detach) {
+		/* Indicate to clients domain is getting detached */
+		list_for_each_entry(aclient, &aspace->clients, list) {
+			if (aclient->cb)
+				aclient->cb(aclient->cb_data,
+						is_detach);
+		}
+
+		/**
+		 * Unmap active buffers,
+		 * typically clients should do this when the callback is called,
+		 * but this needs to be done for the framebuffers which are not
+		 * attached to any planes. (background apps)
+		 */
+		list_for_each_entry(msm_obj, &aspace->active_list, iova_list) {
+			obj = &msm_obj->base;
+			if (obj->import_attach) {
+				put_iova(obj);
+				put_pages(obj);
+			}
+		}
+	} else {
+		/* map active buffers */
+		list_for_each_entry(msm_obj, &aspace->active_list,
+				iova_list) {
+			obj = &msm_obj->base;
+			ret = msm_gem_get_iova_locked(obj, aspace, &iova);
+			if (ret) {
+				mutex_unlock(&obj->dev->struct_mutex);
+				return;
+			}
+		}
+
+		/* Indicate to clients domain is attached */
+		list_for_each_entry(aclient, &aspace->clients, list) {
+			if (aclient->cb)
+				aclient->cb(aclient->cb_data,
+						is_detach);
+		}
+	}
+	mutex_unlock(&aspace->dev->struct_mutex);
+}
+
 int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 		struct drm_mode_create_dumb *args)
 {
@@ -869,6 +932,7 @@
 
 	INIT_LIST_HEAD(&msm_obj->submit_entry);
 	INIT_LIST_HEAD(&msm_obj->domains);
+	INIT_LIST_HEAD(&msm_obj->iova_list);
 
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
 
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 9d41a00..c50c453 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -25,6 +25,8 @@
 #define MSM_BO_STOLEN        0x10000000    /* try to use stolen/splash memory */
 #define MSM_BO_KEEPATTRS     0x20000000     /* keep h/w bus attributes */
 
+struct msm_gem_object;
+
 struct msm_gem_aspace_ops {
 	int (*map)(struct msm_gem_address_space *, struct msm_gem_vma *,
 		struct sg_table *sgt, void *priv, unsigned int flags);
@@ -33,12 +35,35 @@
 		struct sg_table *sgt, void *priv);
 
 	void (*destroy)(struct msm_gem_address_space *);
+	void (*add_to_active)(struct msm_gem_address_space *,
+		struct msm_gem_object *);
+	void (*remove_from_active)(struct msm_gem_address_space *,
+		struct msm_gem_object *);
+	int (*register_cb)(struct msm_gem_address_space *,
+			void (*cb)(void *, bool),
+			void *);
+	int (*unregister_cb)(struct msm_gem_address_space *,
+			void (*cb)(void *, bool),
+			void *);
 };
 
+struct aspace_client {
+	void (*cb)(void *, bool);
+	void *cb_data;
+	struct list_head list;
+};
+
+
 struct msm_gem_address_space {
 	const char *name;
 	struct msm_mmu *mmu;
 	const struct msm_gem_aspace_ops *ops;
+	bool domain_attached;
+	struct drm_device *dev;
+	/* list of mapped objects */
+	struct list_head active_list;
+	/* list of clients */
+	struct list_head clients;
 };
 
 struct msm_gem_vma {
@@ -96,6 +121,7 @@
 	 * an IOMMU.  Also used for stolen/splashscreen buffer.
 	 */
 	struct drm_mm_node *vram_node;
+	struct list_head iova_list;
 };
 #define to_msm_bo(x) container_of(x, struct msm_gem_object, base)
 
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 8d727fe..c695dda 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -31,11 +31,14 @@
 #define BO_PINNED   0x2000
 
 static struct msm_gem_submit *submit_create(struct drm_device *dev,
-		struct msm_gpu *gpu, int nr_bos, int nr_cmds)
+		struct msm_gpu *gpu, uint32_t nr_bos, uint32_t nr_cmds)
 {
 	struct msm_gem_submit *submit;
-	int sz = sizeof(*submit) + (nr_bos * sizeof(submit->bos[0])) +
-			(nr_cmds * sizeof(*submit->cmd));
+	uint64_t sz = sizeof(*submit) + (nr_bos * sizeof(submit->bos[0])) +
+		(nr_cmds * sizeof(submit->cmd[0]));
+
+	if (sz > SIZE_MAX)
+		return NULL;
 
 	submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
 	if (!submit)
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index 8e56871..d02228a 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -44,6 +44,9 @@
 	struct dma_buf *buf = priv;
 	int ret;
 
+	if (!aspace || !aspace->domain_attached)
+		return -EINVAL;
+
 	if (buf)
 		ret = aspace->mmu->funcs->map_dma_buf(aspace->mmu, sgt, buf,
 			DMA_BIDIRECTIONAL, flags);
@@ -62,15 +65,109 @@
 	aspace->mmu->funcs->destroy(aspace->mmu);
 }
 
+static void smmu_aspace_add_to_active(
+		struct msm_gem_address_space *aspace,
+		struct msm_gem_object *msm_obj)
+{
+	WARN_ON(!mutex_is_locked(&aspace->dev->struct_mutex));
+	list_move_tail(&msm_obj->iova_list, &aspace->active_list);
+}
+
+static void smmu_aspace_remove_from_active(
+		struct msm_gem_address_space *aspace,
+		struct msm_gem_object *obj)
+{
+	struct msm_gem_object *msm_obj, *next;
+
+	WARN_ON(!mutex_is_locked(&aspace->dev->struct_mutex));
+
+	list_for_each_entry_safe(msm_obj, next, &aspace->active_list,
+			iova_list) {
+		if (msm_obj == obj) {
+			list_del(&msm_obj->iova_list);
+			break;
+		}
+	}
+}
+
+static int smmu_aspace_register_cb(
+		struct msm_gem_address_space *aspace,
+		void (*cb)(void *, bool),
+		void *cb_data)
+{
+	struct aspace_client *aclient = NULL;
+	struct aspace_client *temp;
+
+	if (!aspace)
+		return -EINVAL;
+
+	if (!aspace->domain_attached)
+		return -EACCES;
+
+	aclient = kzalloc(sizeof(*aclient), GFP_KERNEL);
+	if (!aclient)
+		return -ENOMEM;
+
+	aclient->cb = cb;
+	aclient->cb_data = cb_data;
+	INIT_LIST_HEAD(&aclient->list);
+
+	/* check if callback is already registered */
+	mutex_lock(&aspace->dev->struct_mutex);
+	list_for_each_entry(temp, &aspace->clients, list) {
+		if ((temp->cb == aclient->cb) &&
+			(temp->cb_data == aclient->cb_data)) {
+			kfree(aclient);
+			mutex_unlock(&aspace->dev->struct_mutex);
+			return -EEXIST;
+		}
+	}
+
+	list_move_tail(&aclient->list, &aspace->clients);
+	mutex_unlock(&aspace->dev->struct_mutex);
+
+	return 0;
+}
+
+static int smmu_aspace_unregister_cb(
+		struct msm_gem_address_space *aspace,
+		void (*cb)(void *, bool),
+		void *cb_data)
+{
+	struct aspace_client *aclient = NULL;
+	int rc = -ENOENT;
+
+	if (!aspace || !cb)
+		return -EINVAL;
+
+	mutex_lock(&aspace->dev->struct_mutex);
+	list_for_each_entry(aclient, &aspace->clients, list) {
+		if ((aclient->cb == cb) &&
+			(aclient->cb_data == cb_data)) {
+			list_del(&aclient->list);
+			kfree(aclient);
+			rc = 0;
+			break;
+		}
+	}
+	mutex_unlock(&aspace->dev->struct_mutex);
+
+	return rc;
+}
+
 
 static const struct msm_gem_aspace_ops smmu_aspace_ops = {
 	.map = smmu_aspace_map_vma,
 	.unmap = smmu_aspace_unmap_vma,
-	.destroy = smmu_aspace_destroy
+	.destroy = smmu_aspace_destroy,
+	.add_to_active = smmu_aspace_add_to_active,
+	.remove_from_active = smmu_aspace_remove_from_active,
+	.register_cb = smmu_aspace_register_cb,
+	.unregister_cb = smmu_aspace_unregister_cb,
 };
 
 struct msm_gem_address_space *
-msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu,
+msm_gem_smmu_address_space_create(struct drm_device *dev, struct msm_mmu *mmu,
 		const char *name)
 {
 	struct msm_gem_address_space *aspace;
@@ -82,9 +179,12 @@
 	if (!aspace)
 		return ERR_PTR(-ENOMEM);
 
+	aspace->dev = dev;
 	aspace->name = name;
 	aspace->mmu = mmu;
 	aspace->ops = &smmu_aspace_ops;
+	INIT_LIST_HEAD(&aspace->active_list);
+	INIT_LIST_HEAD(&aspace->clients);
 
 	return aspace;
 }
@@ -218,3 +318,44 @@
 
 	kfree(aspace);
 }
+
+void msm_gem_add_obj_to_aspace_active_list(
+		struct msm_gem_address_space *aspace,
+		struct drm_gem_object *obj)
+{
+	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+	if (aspace && aspace->ops && aspace->ops->add_to_active)
+		aspace->ops->add_to_active(aspace, msm_obj);
+}
+
+void msm_gem_remove_obj_from_aspace_active_list(
+		struct msm_gem_address_space *aspace,
+		struct drm_gem_object *obj)
+{
+	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+	if (aspace && aspace->ops && aspace->ops->remove_from_active)
+		aspace->ops->remove_from_active(aspace, msm_obj);
+}
+
+int msm_gem_address_space_register_cb(struct msm_gem_address_space *aspace,
+		void (*cb)(void *, bool),
+		void *cb_data)
+{
+	if (aspace && aspace->ops && aspace->ops->register_cb)
+		return aspace->ops->register_cb(aspace, cb, cb_data);
+
+	return -EINVAL;
+}
+
+int msm_gem_address_space_unregister_cb(struct msm_gem_address_space *aspace,
+		void (*cb)(void *, bool),
+		void *cb_data)
+{
+	if (aspace && aspace->ops && aspace->ops->unregister_cb)
+		return aspace->ops->unregister_cb(aspace, cb, cb_data);
+
+	return -EINVAL;
+}
+
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 7692bef..e7fae38 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -34,6 +34,8 @@
 #define MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS	(1<<0)
 /* Transition to new mode requires a wait-for-vblank before the modeset */
 #define MSM_MODE_FLAG_VBLANK_PRE_MODESET	(1<<1)
+/* Request to switch the connector mode */
+#define MSM_MODE_FLAG_SEAMLESS_DMS			(1<<2)
 
 /* As there are different display controller blocks depending on the
  * snapdragon version, the kms support is split out and the appropriate
@@ -75,6 +77,9 @@
 			const struct msm_format *msm_fmt,
 			const struct drm_mode_fb_cmd2 *cmd,
 			struct drm_gem_object **bos);
+	/* perform complete atomic check of given atomic state */
+	int (*atomic_check)(struct msm_kms *kms,
+			struct drm_atomic_state *state);
 	/* misc: */
 	long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
 			struct drm_encoder *encoder);
@@ -143,6 +148,12 @@
 	return (mode->flags & DRM_MODE_FLAG_SEAMLESS);
 }
 
+static inline bool msm_is_mode_seamless_dms(const struct drm_display_mode *mode)
+{
+	return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DMS)
+		: false;
+}
+
 static inline bool msm_is_mode_dynamic_fps(const struct drm_display_mode *mode)
 {
 	return ((mode->flags & DRM_MODE_FLAG_SEAMLESS) &&
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 5af26e2..08e6f79 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -45,6 +45,7 @@
 	void (*unmap_dma_buf)(struct msm_mmu *mmu, struct sg_table *sgt,
 			struct dma_buf *dma_buf, int dir);
 	void (*destroy)(struct msm_mmu *mmu);
+	bool (*is_domain_secure)(struct msm_mmu *mmu);
 };
 
 struct msm_mmu {
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 7d7f74a..730fc06 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -37,6 +37,7 @@
 	struct device *dev;
 	struct dma_iommu_mapping *mmu_mapping;
 	bool domain_attached;
+	bool secure;
 };
 
 struct msm_smmu {
@@ -275,6 +276,14 @@
 	msm_dma_unmap_sg(client->dev, sgt->sgl, sgt->nents, dir, dma_buf);
 }
 
+static bool msm_smmu_is_domain_secure(struct msm_mmu *mmu)
+{
+	struct msm_smmu *smmu = to_msm_smmu(mmu);
+	struct msm_smmu_client *client = msm_smmu_to_client(smmu);
+
+	return client->secure;
+}
+
 static const struct msm_mmu_funcs funcs = {
 	.attach = msm_smmu_attach,
 	.detach = msm_smmu_detach,
@@ -285,6 +294,7 @@
 	.map_dma_buf = msm_smmu_map_dma_buf,
 	.unmap_dma_buf = msm_smmu_unmap_dma_buf,
 	.destroy = msm_smmu_destroy,
+	.is_domain_secure = msm_smmu_is_domain_secure,
 };
 
 static struct msm_smmu_domain msm_smmu_domains[MSM_SMMU_DOMAIN_MAX] = {
@@ -458,6 +468,7 @@
 	if (domain->secure) {
 		int secure_vmid = VMID_CP_PIXEL;
 
+		client->secure = true;
 		rc = iommu_domain_set_attr(client->mmu_mapping->domain,
 				DOMAIN_ATTR_SECURE_VMID, &secure_vmid);
 		if (rc) {
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index f5e2ada..447a6c3 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -365,12 +365,60 @@
 	return c_conn->ops.get_info(info, c_conn->display);
 }
 
+static int _sde_connector_update_power_locked(struct sde_connector *c_conn)
+{
+	struct drm_connector *connector;
+	void *display;
+	int (*set_power)(struct drm_connector *, int, void *);
+	int mode, rc = 0;
+
+	if (!c_conn)
+		return -EINVAL;
+	connector = &c_conn->base;
+
+	switch (c_conn->dpms_mode) {
+	case DRM_MODE_DPMS_ON:
+		mode = c_conn->lp_mode;
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+		mode = SDE_MODE_DPMS_STANDBY;
+		break;
+	case DRM_MODE_DPMS_SUSPEND:
+		mode = SDE_MODE_DPMS_SUSPEND;
+		break;
+	case DRM_MODE_DPMS_OFF:
+		mode = SDE_MODE_DPMS_OFF;
+		break;
+	default:
+		mode = c_conn->lp_mode;
+		SDE_ERROR("conn %d dpms set to unrecognized mode %d\n",
+				connector->base.id, mode);
+		break;
+	}
+
+	SDE_EVT32(connector->base.id, c_conn->dpms_mode, c_conn->lp_mode, mode);
+	SDE_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id,
+			c_conn->dpms_mode, c_conn->lp_mode, mode);
+
+	if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) {
+		display = c_conn->display;
+		set_power = c_conn->ops.set_power;
+
+		mutex_unlock(&c_conn->lock);
+		rc = set_power(connector, mode, display);
+		mutex_lock(&c_conn->lock);
+	}
+	c_conn->last_panel_power_mode = mode;
+
+	return rc;
+}
+
 int sde_connector_pre_kickoff(struct drm_connector *connector)
 {
 	struct sde_connector *c_conn;
 	struct sde_connector_state *c_state;
 	struct msm_display_kickoff_params params;
-	int rc;
+	int idx, rc;
 
 	if (!connector) {
 		SDE_ERROR("invalid argument\n");
@@ -385,6 +433,22 @@
 		return -EINVAL;
 	}
 
+	while ((idx = msm_property_pop_dirty(&c_conn->property_info,
+					&c_state->property_state)) >= 0) {
+		switch (idx) {
+		case CONNECTOR_PROP_LP:
+			mutex_lock(&c_conn->lock);
+			c_conn->lp_mode = sde_connector_get_property(
+					connector->state, CONNECTOR_PROP_LP);
+			_sde_connector_update_power_locked(c_conn);
+			mutex_unlock(&c_conn->lock);
+			break;
+		default:
+			/* nothing to do for most properties */
+			break;
+		}
+	}
+
 	if (!c_conn->ops.pre_kickoff)
 		return 0;
 
@@ -427,6 +491,9 @@
 
 	c_conn = to_sde_connector(connector);
 
+	if (c_conn->ops.put_modes)
+		c_conn->ops.put_modes(connector, c_conn->display);
+
 	if (c_conn->blob_caps)
 		drm_property_unreference_blob(c_conn->blob_caps);
 	if (c_conn->blob_hdr)
@@ -684,56 +751,6 @@
 	return 0;
 }
 
-static int _sde_connector_update_power_locked(struct sde_connector *c_conn)
-{
-	struct drm_connector *connector;
-	void *display;
-	int (*set_power)(struct drm_connector *, int, void *);
-	int mode, rc = 0;
-
-	if (!c_conn)
-		return -EINVAL;
-	connector = &c_conn->base;
-
-	mode = c_conn->lp_mode;
-	if (c_conn->dpms_mode != DRM_MODE_DPMS_ON)
-		mode = SDE_MODE_DPMS_OFF;
-	switch (c_conn->dpms_mode) {
-	case DRM_MODE_DPMS_ON:
-		mode = c_conn->lp_mode;
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-		mode = SDE_MODE_DPMS_STANDBY;
-		break;
-	case DRM_MODE_DPMS_SUSPEND:
-		mode = SDE_MODE_DPMS_SUSPEND;
-		break;
-	case DRM_MODE_DPMS_OFF:
-		mode = SDE_MODE_DPMS_OFF;
-		break;
-	default:
-		mode = c_conn->lp_mode;
-		SDE_ERROR("conn %d dpms set to unrecognized mode %d\n",
-				connector->base.id, mode);
-		break;
-	}
-
-	SDE_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id,
-			c_conn->dpms_mode, c_conn->lp_mode, mode);
-
-	if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) {
-		display = c_conn->display;
-		set_power = c_conn->ops.set_power;
-
-		mutex_unlock(&c_conn->lock);
-		rc = set_power(connector, mode, display);
-		mutex_lock(&c_conn->lock);
-	}
-	c_conn->last_panel_power_mode = mode;
-
-	return rc;
-}
-
 static int sde_connector_atomic_set_property(struct drm_connector *connector,
 		struct drm_connector_state *state,
 		struct drm_property *property,
@@ -792,12 +809,6 @@
 				SDE_ERROR("prep fb failed, %d\n", rc);
 		}
 		break;
-	case CONNECTOR_PROP_LP:
-		mutex_lock(&c_conn->lock);
-		c_conn->lp_mode = val;
-		_sde_connector_update_power_locked(c_conn);
-		mutex_unlock(&c_conn->lock);
-		break;
 	default:
 		break;
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 1598968..4747d3a 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -65,6 +65,14 @@
 			void *display);
 
 	/**
+	 * put_modes - free up drm modes of the connector
+	 * @connector: Pointer to drm connector structure
+	 * @display: Pointer to private display handle
+	 */
+	void (*put_modes)(struct drm_connector *connector,
+			void *display);
+
+	/**
 	 * update_pps - update pps command for the display panel
 	 * @pps_cmd: Pointer to pps command
 	 * @display: Pointer to private display handle
@@ -122,14 +130,14 @@
 	int (*get_info)(struct msm_display_info *info, void *display);
 
 	/**
-	 * get_topology - retrieve current topology for the mode selected
+	 * get_mode_info - retrieve mode information
 	 * @drm_mode: Display mode set for the display
-	 * @topology: Out parameter. Topology for the mode.
+	 * @mode_info: Out parameter. information of the display mode
 	 * @max_mixer_width: max width supported by HW layer mixer
 	 * Returns: Zero on success
 	 */
-	int (*get_topology)(const struct drm_display_mode *drm_mode,
-			struct msm_display_topology *topology,
+	int (*get_mode_info)(const struct drm_display_mode *drm_mode,
+			struct msm_mode_info *mode_info,
 			u32 max_mixer_width);
 
 	/**
@@ -381,6 +389,20 @@
 }
 
 /**
+ * sde_connector_get_lp - helper accessor to retrieve LP state
+ * @connector: pointer to drm connector
+ * Returns: value of the CONNECTOR_PROP_LP property or 0
+ */
+static inline uint64_t sde_connector_get_lp(
+		struct drm_connector *connector)
+{
+	if (!connector || !connector->state)
+		return 0;
+	return sde_connector_get_property(connector->state,
+			CONNECTOR_PROP_LP);
+}
+
+/**
  * sde_connector_init - create drm connector object for a given display
  * @dev: Pointer to drm device struct
  * @encoder: Pointer to associated encoder
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 01e4f93..6f1d2b7 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -34,6 +34,7 @@
 #include "sde_color_processing.h"
 #include "sde_encoder.h"
 #include "sde_connector.h"
+#include "sde_vbif.h"
 #include "sde_power_handle.h"
 #include "sde_core_perf.h"
 #include "sde_trace.h"
@@ -65,7 +66,7 @@
 };
 
 /* default input fence timeout, in ms */
-#define SDE_CRTC_INPUT_FENCE_TIMEOUT    2000
+#define SDE_CRTC_INPUT_FENCE_TIMEOUT    10000
 
 /*
  * The default input fence timeout is 2 seconds while max allowed
@@ -180,7 +181,9 @@
  */
 static void _sde_crtc_rp_free_unused(struct sde_crtc_respool *rp)
 {
+	mutex_lock(rp->rp_lock);
 	_sde_crtc_rp_reclaim(rp, false);
+	mutex_unlock(rp->rp_lock);
 }
 
 /**
@@ -190,7 +193,10 @@
  */
 static void _sde_crtc_rp_destroy(struct sde_crtc_respool *rp)
 {
+	mutex_lock(rp->rp_lock);
+	list_del_init(&rp->rp_list);
 	_sde_crtc_rp_reclaim(rp, true);
+	mutex_unlock(rp->rp_lock);
 }
 
 /**
@@ -229,7 +235,7 @@
 	struct sde_crtc_res *res, *dup_res;
 	struct drm_crtc *crtc;
 
-	if (!rp || !dup_rp) {
+	if (!rp || !dup_rp || !rp->rp_head) {
 		SDE_ERROR("invalid resource pool\n");
 		return;
 	}
@@ -242,13 +248,16 @@
 
 	SDE_DEBUG("crtc%d.%u duplicate\n", crtc->base.id, rp->sequence_id);
 
+	mutex_lock(rp->rp_lock);
 	dup_rp->sequence_id = rp->sequence_id + 1;
 	INIT_LIST_HEAD(&dup_rp->res_list);
 	dup_rp->ops = rp->ops;
 	list_for_each_entry(res, &rp->res_list, list) {
 		dup_res = kzalloc(sizeof(struct sde_crtc_res), GFP_KERNEL);
-		if (!dup_res)
+		if (!dup_res) {
+			mutex_unlock(rp->rp_lock);
 			return;
+		}
 		INIT_LIST_HEAD(&dup_res->list);
 		atomic_set(&dup_res->refcount, 0);
 		dup_res->type = res->type;
@@ -264,28 +273,43 @@
 		if (dup_res->ops.get)
 			dup_res->ops.get(dup_res->val, 0, -1);
 	}
+
+	dup_rp->rp_lock = rp->rp_lock;
+	dup_rp->rp_head = rp->rp_head;
+	INIT_LIST_HEAD(&dup_rp->rp_list);
+	list_add_tail(&dup_rp->rp_list, rp->rp_head);
+	mutex_unlock(rp->rp_lock);
 }
 
 /**
  * _sde_crtc_rp_reset - reset resource pool after allocation
  * @rp: Pointer to original resource pool
+ * @rp_lock: Pointer to serialization resource pool lock
+ * @rp_head: Pointer to crtc resource pool head
  * return: None
  */
-static void _sde_crtc_rp_reset(struct sde_crtc_respool *rp)
+static void _sde_crtc_rp_reset(struct sde_crtc_respool *rp,
+		struct mutex *rp_lock, struct list_head *rp_head)
 {
-	if (!rp) {
+	if (!rp || !rp_lock || !rp_head) {
 		SDE_ERROR("invalid resource pool\n");
 		return;
 	}
 
+	mutex_lock(rp_lock);
+	rp->rp_lock = rp_lock;
+	rp->rp_head = rp_head;
+	INIT_LIST_HEAD(&rp->rp_list);
 	rp->sequence_id = 0;
 	INIT_LIST_HEAD(&rp->res_list);
 	rp->ops.get = _sde_crtc_hw_blk_get;
 	rp->ops.put = _sde_crtc_hw_blk_put;
+	list_add_tail(&rp->rp_list, rp->rp_head);
+	mutex_unlock(rp_lock);
 }
 
 /**
- * _sde_crtc_rp_add - add given resource to resource pool
+ * _sde_crtc_rp_add_no_lock - add given resource to resource pool without lock
  * @rp: Pointer to original resource pool
  * @type: Resource type
  * @tag: Search tag for given resource
@@ -293,8 +317,8 @@
  * @ops: Resource callback operations
  * return: 0 if success; error code otherwise
  */
-static int _sde_crtc_rp_add(struct sde_crtc_respool *rp, u32 type, u64 tag,
-		void *val, struct sde_crtc_res_ops *ops)
+static int _sde_crtc_rp_add_no_lock(struct sde_crtc_respool *rp, u32 type,
+		u64 tag, void *val, struct sde_crtc_res_ops *ops)
 {
 	struct sde_crtc_res *res;
 	struct drm_crtc *crtc;
@@ -335,6 +359,31 @@
 }
 
 /**
+ * _sde_crtc_rp_add - add given resource to resource pool
+ * @rp: Pointer to original resource pool
+ * @type: Resource type
+ * @tag: Search tag for given resource
+ * @val: Resource handle
+ * @ops: Resource callback operations
+ * return: 0 if success; error code otherwise
+ */
+static int _sde_crtc_rp_add(struct sde_crtc_respool *rp, u32 type, u64 tag,
+		void *val, struct sde_crtc_res_ops *ops)
+{
+	int rc;
+
+	if (!rp) {
+		SDE_ERROR("invalid resource pool\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(rp->rp_lock);
+	rc = _sde_crtc_rp_add_no_lock(rp, type, tag, val, ops);
+	mutex_unlock(rp->rp_lock);
+	return rc;
+}
+
+/**
  * _sde_crtc_rp_get - lookup the resource from given resource pool and obtain
  *	if available; otherwise, obtain resource from global pool
  * @rp: Pointer to original resource pool
@@ -344,6 +393,7 @@
  */
 static void *_sde_crtc_rp_get(struct sde_crtc_respool *rp, u32 type, u64 tag)
 {
+	struct sde_crtc_respool *old_rp;
 	struct sde_crtc_res *res;
 	void *val = NULL;
 	int rc;
@@ -360,6 +410,7 @@
 		return NULL;
 	}
 
+	mutex_lock(rp->rp_lock);
 	list_for_each_entry(res, &rp->res_list, list) {
 		if (res->type != type || res->tag != tag)
 			continue;
@@ -369,6 +420,7 @@
 				atomic_read(&res->refcount));
 		atomic_inc(&res->refcount);
 		res->flags &= ~SDE_CRTC_RES_FLAG_FREE;
+		mutex_unlock(rp->rp_lock);
 		return res->val;
 	}
 	list_for_each_entry(res, &rp->res_list, list) {
@@ -381,16 +433,63 @@
 		atomic_inc(&res->refcount);
 		res->tag = tag;
 		res->flags &= ~SDE_CRTC_RES_FLAG_FREE;
+		mutex_unlock(rp->rp_lock);
 		return res->val;
 	}
+	/* not in this rp, try to grab from global pool */
 	if (rp->ops.get)
 		val = rp->ops.get(NULL, type, -1);
+	if (!IS_ERR_OR_NULL(val))
+		goto add_res;
+	/*
+	 * Search older resource pools for hw blk with matching type,
+	 * necessary when resource is being used by this object,
+	 * but in previous states not yet cleaned up.
+	 *
+	 * This enables searching of all resources currently owned
+	 * by this crtc even though the resource might not be used
+	 * in the current atomic state. This allows those resources
+	 * to be re-acquired by the new atomic state immediately
+	 * without waiting for the resources to be fully released.
+	 */
+	else if (IS_ERR_OR_NULL(val) && (type < SDE_HW_BLK_MAX)) {
+		list_for_each_entry(old_rp, rp->rp_head, rp_list) {
+			if (old_rp == rp)
+				continue;
+
+			list_for_each_entry(res, &old_rp->res_list, list) {
+				if (res->type != type)
+					continue;
+				SDE_DEBUG(
+					"crtc%d.%u found res:0x%x//%pK/ in crtc%d.%d\n",
+						crtc->base.id,
+						rp->sequence_id,
+						res->type, res->val,
+						crtc->base.id,
+						old_rp->sequence_id);
+				SDE_EVT32_VERBOSE(crtc->base.id,
+						rp->sequence_id,
+						res->type, res->val,
+						crtc->base.id,
+						old_rp->sequence_id);
+				if (res->ops.get)
+					res->ops.get(res->val, 0, -1);
+				val = res->val;
+				break;
+			}
+
+			if (!IS_ERR_OR_NULL(val))
+				break;
+		}
+	}
 	if (IS_ERR_OR_NULL(val)) {
 		SDE_DEBUG("crtc%d.%u failed to get res:0x%x//\n",
 				crtc->base.id, rp->sequence_id, type);
+		mutex_unlock(rp->rp_lock);
 		return NULL;
 	}
-	rc = _sde_crtc_rp_add(rp, type, tag, val, &rp->ops);
+add_res:
+	rc = _sde_crtc_rp_add_no_lock(rp, type, tag, val, &rp->ops);
 	if (rc) {
 		SDE_ERROR("crtc%d.%u failed to add res:0x%x/0x%llx\n",
 				crtc->base.id, rp->sequence_id, type, tag);
@@ -398,6 +497,7 @@
 			rp->ops.put(val);
 		val = NULL;
 	}
+	mutex_unlock(rp->rp_lock);
 	return val;
 }
 
@@ -424,6 +524,7 @@
 		return;
 	}
 
+	mutex_lock(rp->rp_lock);
 	list_for_each_entry_safe(res, next, &rp->res_list, list) {
 		if (res->type != type || res->tag != tag)
 			continue;
@@ -440,10 +541,12 @@
 		else if (atomic_dec_return(&res->refcount) == 0)
 			res->flags |= SDE_CRTC_RES_FLAG_FREE;
 
+		mutex_unlock(rp->rp_lock);
 		return;
 	}
 	SDE_ERROR("crtc%d.%u not found res:0x%x/0x%llx\n",
 			crtc->base.id, rp->sequence_id, type, tag);
+	mutex_unlock(rp->rp_lock);
 }
 
 int sde_crtc_res_add(struct drm_crtc_state *state, u32 type, u64 tag,
@@ -1220,7 +1323,8 @@
 				state->src_w >> 16, state->src_h >> 16,
 				state->crtc_x, state->crtc_y,
 				state->crtc_w, state->crtc_h,
-				cstate->sbuf_cfg.rot_op_mode);
+				flush_tmp ? cstate->sbuf_cfg.rot_op_mode :
+				SDE_CTL_ROT_OP_MODE_OFFLINE);
 
 		stage_idx = zpos_cnt[pstate->stage]++;
 		stage_cfg->stage[pstate->stage][stage_idx] =
@@ -1472,7 +1576,7 @@
 			sde_crtc->event = NULL;
 			DRM_DEBUG_VBL("%s: send event: %pK\n",
 						sde_crtc->name, event);
-			SDE_EVT32(DRMID(crtc));
+			SDE_EVT32_VERBOSE(DRMID(crtc));
 			drm_crtc_send_vblank_event(crtc, event);
 		}
 	}
@@ -1899,7 +2003,7 @@
 		cstate->lm_bounds[i].h = adj_mode->vdisplay;
 		memcpy(&cstate->lm_roi[i], &cstate->lm_bounds[i],
 				sizeof(cstate->lm_roi[i]));
-		SDE_EVT32(DRMID(crtc), i,
+		SDE_EVT32_VERBOSE(DRMID(crtc), i,
 				cstate->lm_bounds[i].x, cstate->lm_bounds[i].y,
 				cstate->lm_bounds[i].w, cstate->lm_bounds[i].h);
 		SDE_DEBUG("%s: lm%d bnd&roi (%d,%d,%d,%d)\n", sde_crtc->name, i,
@@ -2103,7 +2207,7 @@
 		return 0;
 	}
 
-	SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_ENTRY);
+	SDE_EVT32_VERBOSE(DRMID(crtc), SDE_EVTLOG_FUNC_ENTRY);
 	ret = wait_for_completion_timeout(&sde_crtc->frame_done_comp,
 			msecs_to_jiffies(SDE_FRAME_DONE_TIMEOUT));
 	if (!ret) {
@@ -2112,13 +2216,14 @@
 		SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FATAL);
 		rc = -ETIMEDOUT;
 	}
-	SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT);
+	SDE_EVT32_VERBOSE(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT);
 
 	return rc;
 }
 
 void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
 {
+	struct drm_plane *plane;
 	struct drm_encoder *encoder;
 	struct drm_device *dev;
 	struct sde_crtc *sde_crtc;
@@ -2189,6 +2294,12 @@
 	}
 	sde_crtc->play_count++;
 
+	if (cstate->sbuf_cfg.rot_op_mode != SDE_CTL_ROT_OP_MODE_OFFLINE)
+		drm_atomic_crtc_for_each_plane(plane, crtc)
+			sde_plane_kickoff(plane);
+
+	sde_vbif_clear_errors(sde_kms);
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc != crtc)
 			continue;
@@ -2196,19 +2307,20 @@
 		sde_encoder_kickoff(encoder);
 	}
 
-	reinit_completion(&sde_crtc->frame_done_comp);
-
 end:
+	reinit_completion(&sde_crtc->frame_done_comp);
 	SDE_ATRACE_END("crtc_commit");
 	return;
 }
 
 /**
- * _sde_crtc_vblank_enable_nolock - update power resource and vblank request
+ * _sde_crtc_vblank_enable_no_lock - update power resource and vblank request
  * @sde_crtc: Pointer to sde crtc structure
  * @enable: Whether to enable/disable vblanks
+ *
+ * @Return: error code
  */
-static void _sde_crtc_vblank_enable_nolock(
+static int _sde_crtc_vblank_enable_no_lock(
 		struct sde_crtc *sde_crtc, bool enable)
 {
 	struct drm_device *dev;
@@ -2217,7 +2329,7 @@
 
 	if (!sde_crtc) {
 		SDE_ERROR("invalid crtc\n");
-		return;
+		return -EINVAL;
 	}
 
 	crtc = &sde_crtc->base;
@@ -2231,13 +2343,16 @@
 		ret = _sde_crtc_power_enable(sde_crtc, true);
 		mutex_lock(&sde_crtc->crtc_lock);
 		if (ret)
-			return;
+			return ret;
 
 		list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
 			if (enc->crtc != crtc)
 				continue;
 
-			SDE_EVT32(DRMID(crtc), DRMID(enc), enable);
+			SDE_EVT32(DRMID(&sde_crtc->base), DRMID(enc), enable,
+					sde_crtc->enabled,
+					sde_crtc->suspend,
+					sde_crtc->vblank_requested);
 
 			sde_encoder_register_vblank_callback(enc,
 					sde_crtc_vblank_cb, (void *)crtc);
@@ -2247,7 +2362,10 @@
 			if (enc->crtc != crtc)
 				continue;
 
-			SDE_EVT32(DRMID(crtc), DRMID(enc), enable);
+			SDE_EVT32(DRMID(&sde_crtc->base), DRMID(enc), enable,
+					sde_crtc->enabled,
+					sde_crtc->suspend,
+					sde_crtc->vblank_requested);
 
 			sde_encoder_register_vblank_callback(enc, NULL, NULL);
 		}
@@ -2257,6 +2375,8 @@
 		_sde_crtc_power_enable(sde_crtc, false);
 		mutex_lock(&sde_crtc->crtc_lock);
 	}
+
+	return 0;
 }
 
 /**
@@ -2269,8 +2389,7 @@
 	struct sde_crtc *sde_crtc;
 	struct msm_drm_private *priv;
 	struct sde_kms *sde_kms;
-	struct drm_event event;
-	u32 power_on;
+	int ret = 0;
 
 	if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
 		SDE_ERROR("invalid crtc\n");
@@ -2286,35 +2405,27 @@
 	sde_kms = to_sde_kms(priv->kms);
 
 	SDE_DEBUG("crtc%d suspend = %d\n", crtc->base.id, enable);
+	SDE_EVT32_VERBOSE(DRMID(crtc), enable);
 
 	mutex_lock(&sde_crtc->crtc_lock);
 
-	event.type = DRM_EVENT_CRTC_POWER;
-	event.length = sizeof(u32);
-	/*
-	 * Update CP on suspend/resume transitions
-	 */
-	if (enable && !sde_crtc->suspend) {
-		sde_cp_crtc_suspend(crtc);
-		power_on = 0;
-	} else if (!enable && sde_crtc->suspend) {
-		sde_cp_crtc_resume(crtc);
-		power_on = 1;
-	}
-
 	/*
 	 * If the vblank is enabled, release a power reference on suspend
 	 * and take it back during resume (if it is still enabled).
 	 */
+	SDE_EVT32(DRMID(&sde_crtc->base), enable, sde_crtc->enabled,
+			sde_crtc->suspend, sde_crtc->vblank_requested);
 	if (sde_crtc->suspend == enable)
 		SDE_DEBUG("crtc%d suspend already set to %d, ignoring update\n",
 				crtc->base.id, enable);
-	else if (sde_crtc->vblank_enable)
-		_sde_crtc_vblank_enable_nolock(sde_crtc, !enable);
+	else if (sde_crtc->enabled && sde_crtc->vblank_requested) {
+		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, !enable);
+		if (ret)
+			SDE_ERROR("%s vblank enable failed: %d\n",
+					sde_crtc->name, ret);
+	}
 
 	sde_crtc->suspend = enable;
-	msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
-			(u8 *)&power_on);
 	mutex_unlock(&sde_crtc->crtc_lock);
 }
 
@@ -2394,36 +2505,22 @@
 
 	_sde_crtc_set_input_fence_timeout(cstate);
 
-	_sde_crtc_rp_reset(&cstate->rp);
+	_sde_crtc_rp_reset(&cstate->rp, &sde_crtc->rp_lock,
+			&sde_crtc->rp_head);
 
 	cstate->base.crtc = crtc;
 	crtc->state = &cstate->base;
 }
 
-static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en)
-{
-	if (!sde_crtc) {
-		SDE_ERROR("invalid crtc\n");
-		return -EINVAL;
-	}
-
-	if (!sde_crtc->base.enabled || sde_crtc->suspend)
-		SDE_EVT32(DRMID(&sde_crtc->base), sde_crtc->base.enabled, en,
-				sde_crtc->vblank_enable, sde_crtc->suspend);
-	else if (sde_crtc->vblank_enable != en)
-		_sde_crtc_vblank_enable_nolock(sde_crtc, en);
-	sde_crtc->vblank_enable = en;
-
-	return 0;
-}
-
 static void sde_crtc_handle_power_event(u32 event_type, void *arg)
 {
 	struct drm_crtc *crtc = arg;
 	struct sde_crtc *sde_crtc;
+	struct drm_plane *plane;
 	struct drm_encoder *encoder;
+	struct sde_crtc_mixer *m;
 	struct drm_event event;
-	u32 power_on = 0;
+	u32 power_on = 0, i, misr_status;
 
 	if (!crtc) {
 		SDE_ERROR("invalid crtc\n");
@@ -2435,7 +2532,8 @@
 
 	SDE_EVT32(DRMID(crtc), event_type);
 
-	if (event_type == SDE_POWER_EVENT_POST_ENABLE) {
+	switch (event_type) {
+	case SDE_POWER_EVENT_POST_ENABLE:
 		/* restore encoder; crtc will be programmed during commit */
 		drm_for_each_encoder(encoder, crtc->dev) {
 			if (encoder->crtc != crtc)
@@ -2450,9 +2548,31 @@
 		power_on = 1;
 		msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
 				(u8 *)&power_on);
-	} else if (event_type == SDE_POWER_EVENT_POST_DISABLE) {
-		struct drm_plane *plane;
 
+		for (i = 0; i < sde_crtc->num_mixers; ++i) {
+			m = &sde_crtc->mixers[i];
+			if (!m->hw_lm || !m->hw_lm->ops.setup_misr ||
+					!sde_crtc->misr_enable)
+				continue;
+
+			m->hw_lm->ops.setup_misr(m->hw_lm, true,
+					sde_crtc->misr_frame_count);
+		}
+		break;
+	case SDE_POWER_EVENT_PRE_DISABLE:
+		for (i = 0; i < sde_crtc->num_mixers; ++i) {
+			m = &sde_crtc->mixers[i];
+			if (!m->hw_lm || !m->hw_lm->ops.collect_misr ||
+					!sde_crtc->misr_enable)
+				continue;
+
+			misr_status = m->hw_lm->ops.collect_misr(m->hw_lm);
+			sde_crtc->misr_data[i] = misr_status ? misr_status :
+							sde_crtc->misr_data[i];
+		}
+		sde_cp_crtc_pre_ipc(crtc);
+		break;
+	case SDE_POWER_EVENT_POST_DISABLE:
 		/*
 		 * set revalidate flag in planes, so it will be re-programmed
 		 * in the next frame update
@@ -2467,8 +2587,10 @@
 		power_on = 0;
 		msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
 				(u8 *)&power_on);
-	} else if (event_type == SDE_POWER_EVENT_PRE_DISABLE) {
-		sde_cp_crtc_pre_ipc(crtc);
+		break;
+	default:
+		SDE_DEBUG("event:%d not handled\n", event_type);
+		break;
 	}
 
 	mutex_unlock(&sde_crtc->crtc_lock);
@@ -2482,6 +2604,8 @@
 	struct msm_drm_private *priv;
 	unsigned long flags;
 	struct sde_crtc_irq_info *node = NULL;
+	struct drm_event event;
+	u32 power_on;
 	int ret;
 
 	if (!crtc || !crtc->dev || !crtc->dev->dev_private || !crtc->state) {
@@ -2498,7 +2622,15 @@
 		_sde_crtc_set_suspend(crtc, true);
 
 	mutex_lock(&sde_crtc->crtc_lock);
-	SDE_EVT32(DRMID(crtc));
+	SDE_EVT32_VERBOSE(DRMID(crtc));
+
+	/* update color processing on suspend */
+	event.type = DRM_EVENT_CRTC_POWER;
+	event.length = sizeof(u32);
+	sde_cp_crtc_suspend(crtc);
+	power_on = 0;
+	msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
+			(u8 *)&power_on);
 
 	/* wait for frame_event_done completion */
 	if (_sde_crtc_wait_for_frame_done(crtc))
@@ -2506,13 +2638,16 @@
 				crtc->base.id,
 				atomic_read(&sde_crtc->frame_pending));
 
-	if (sde_crtc->vblank_enable && !sde_crtc->suspend) {
-		SDE_DEBUG("crtc%d vblank left enabled at disable time\n",
-				crtc->base.id);
-		SDE_EVT32(DRMID(crtc), sde_crtc->vblank_enable,
-				SDE_EVTLOG_FUNC_CASE1);
-		_sde_crtc_vblank_enable_nolock(sde_crtc, false);
+	SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend,
+			sde_crtc->vblank_requested);
+	if (sde_crtc->enabled && !sde_crtc->suspend &&
+			sde_crtc->vblank_requested) {
+		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, false);
+		if (ret)
+			SDE_ERROR("%s vblank enable failed: %d\n",
+					sde_crtc->name, ret);
 	}
+	sde_crtc->enabled = false;
 
 	if (atomic_read(&sde_crtc->frame_pending)) {
 		SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending),
@@ -2563,6 +2698,8 @@
 	struct msm_drm_private *priv;
 	unsigned long flags;
 	struct sde_crtc_irq_info *node = NULL;
+	struct drm_event event;
+	u32 power_on;
 	int ret;
 
 	if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
@@ -2572,7 +2709,7 @@
 	priv = crtc->dev->dev_private;
 
 	SDE_DEBUG("crtc%d\n", crtc->base.id);
-	SDE_EVT32(DRMID(crtc));
+	SDE_EVT32_VERBOSE(DRMID(crtc));
 	sde_crtc = to_sde_crtc(crtc);
 
 	drm_for_each_encoder(encoder, crtc->dev) {
@@ -2583,13 +2720,25 @@
 	}
 
 	mutex_lock(&sde_crtc->crtc_lock);
-	if (sde_crtc->vblank_enable) {
-		/* honor user vblank request on crtc while it was disabled */
-		SDE_DEBUG("%s vblank found enabled at crtc enable time\n",
-				sde_crtc->name);
-		SDE_EVT32(DRMID(crtc), sde_crtc->vblank_enable);
-		_sde_crtc_vblank_enable_nolock(sde_crtc, true);
+	SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend,
+			sde_crtc->vblank_requested);
+	if (!sde_crtc->enabled && !sde_crtc->suspend &&
+			sde_crtc->vblank_requested) {
+		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, true);
+		if (ret)
+			SDE_ERROR("%s vblank enable failed: %d\n",
+					sde_crtc->name, ret);
 	}
+	sde_crtc->enabled = true;
+
+	/* update color processing on resume */
+	event.type = DRM_EVENT_CRTC_POWER;
+	event.length = sizeof(u32);
+	sde_cp_crtc_resume(crtc);
+	power_on = 1;
+	msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
+			(u8 *)&power_on);
+
 	mutex_unlock(&sde_crtc->crtc_lock);
 
 	spin_lock_irqsave(&sde_crtc->spin_lock, flags);
@@ -2711,6 +2860,130 @@
 	return rc;
 }
 
+static int _sde_crtc_find_plane_fb_modes(struct drm_crtc_state *state,
+		uint32_t *fb_ns,
+		uint32_t *fb_sec,
+		uint32_t *fb_ns_dir,
+		uint32_t *fb_sec_dir)
+{
+	struct drm_plane *plane;
+	const struct drm_plane_state *pstate;
+	struct sde_plane_state *sde_pstate;
+	uint32_t mode = 0;
+	int rc;
+
+	if (!state) {
+		SDE_ERROR("invalid state\n");
+		return -EINVAL;
+	}
+
+	*fb_ns = 0;
+	*fb_sec = 0;
+	*fb_ns_dir = 0;
+	*fb_sec_dir = 0;
+	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
+		if (IS_ERR_OR_NULL(pstate)) {
+			rc = PTR_ERR(pstate);
+			SDE_ERROR("crtc%d failed to get plane%d state%d\n",
+					state->crtc->base.id,
+					plane->base.id, rc);
+			return rc;
+		}
+		sde_pstate = to_sde_plane_state(pstate);
+		mode = sde_plane_get_property(sde_pstate,
+				PLANE_PROP_FB_TRANSLATION_MODE);
+		switch (mode) {
+		case SDE_DRM_FB_NON_SEC:
+			(*fb_ns)++;
+			break;
+		case SDE_DRM_FB_SEC:
+			(*fb_sec)++;
+			break;
+		case SDE_DRM_FB_NON_SEC_DIR_TRANS:
+			(*fb_ns_dir)++;
+			break;
+		case SDE_DRM_FB_SEC_DIR_TRANS:
+			(*fb_sec_dir)++;
+			break;
+		default:
+			SDE_ERROR("Error: Plane[%d], fb_trans_mode:%d",
+					plane->base.id,
+					mode);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct drm_encoder *encoder;
+	struct sde_crtc_state *cstate;
+	uint32_t secure;
+	uint32_t fb_ns = 0, fb_sec = 0, fb_ns_dir = 0, fb_sec_dir = 0;
+	int encoder_cnt = 0;
+	int rc;
+
+	if (!crtc || !state) {
+		SDE_ERROR("invalid arguments\n");
+		return -EINVAL;
+	}
+
+	cstate = to_sde_crtc_state(state);
+
+	secure = sde_crtc_get_property(cstate,
+			CRTC_PROP_SECURITY_LEVEL);
+
+	rc = _sde_crtc_find_plane_fb_modes(state,
+			&fb_ns,
+			&fb_sec,
+			&fb_ns_dir,
+			&fb_sec_dir);
+	if (rc)
+		return rc;
+
+	/**
+	 * validate planes
+	 * fb_ns_dir is for  secure display use case,
+	 * fb_sec_dir is for secure camera preview use case,
+	 * fb_sec is for secure video playback,
+	 * fb_ns is for normal non secure use cases.
+	 */
+	if (((secure == SDE_DRM_SEC_ONLY) &&
+				(fb_ns || fb_sec || fb_sec_dir)) ||
+			(fb_sec || fb_sec_dir)) {
+		SDE_ERROR(
+			"crtc%d: invalid planes fb_modes Sec:%d, NS:%d, Sec_Dir:%d, NS_Dir%d\n",
+				crtc->base.id,
+				fb_sec, fb_ns, fb_sec_dir,
+				fb_ns_dir);
+		return -EINVAL;
+	}
+
+	/**
+	 * secure_crtc is not allowed in a shared toppolgy
+	 * across different encoders.
+	 */
+	if (fb_ns_dir || fb_sec_dir) {
+		drm_for_each_encoder(encoder, crtc->dev)
+			if (encoder->crtc ==  crtc)
+				encoder_cnt++;
+
+		if (encoder_cnt >
+			MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC) {
+			SDE_ERROR(
+				"crtc%d, invalid virtual encoder crtc%d\n",
+				crtc->base.id,
+				encoder_cnt);
+			return -EINVAL;
+
+		}
+	}
+	SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id);
+	return 0;
+}
+
 static int sde_crtc_atomic_check(struct drm_crtc *crtc,
 		struct drm_crtc_state *state)
 {
@@ -2757,6 +3030,10 @@
 	_sde_crtc_setup_is_ppsplit(state);
 	_sde_crtc_setup_lm_bounds(crtc, state);
 
+	rc = _sde_crtc_check_secure_state(crtc, state);
+	if (rc)
+		return rc;
+
 	 /* get plane state for all drm planes associated with crtc state */
 	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
 		if (IS_ERR_OR_NULL(pstate)) {
@@ -2982,7 +3259,7 @@
 int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
 {
 	struct sde_crtc *sde_crtc;
-	int rc;
+	int ret;
 
 	if (!crtc) {
 		SDE_ERROR("invalid crtc\n");
@@ -2991,10 +3268,18 @@
 	sde_crtc = to_sde_crtc(crtc);
 
 	mutex_lock(&sde_crtc->crtc_lock);
-	rc = _sde_crtc_vblank_no_lock(sde_crtc, en);
+	SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled,
+			sde_crtc->suspend, sde_crtc->vblank_requested);
+	if (sde_crtc->enabled && !sde_crtc->suspend) {
+		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en);
+		if (ret)
+			SDE_ERROR("%s vblank enable failed: %d\n",
+					sde_crtc->name, ret);
+	}
+	sde_crtc->vblank_requested = en;
 	mutex_unlock(&sde_crtc->crtc_lock);
 
-	return rc;
+	return 0;
 }
 
 void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
@@ -3460,7 +3745,7 @@
 		sde_crtc->vblank_cb_time = ktime_set(0, 0);
 	}
 
-	seq_printf(s, "vblank_enable:%d\n", sde_crtc->vblank_enable);
+	seq_printf(s, "vblank_enable:%d\n", sde_crtc->vblank_requested);
 
 	mutex_unlock(&sde_crtc->crtc_lock);
 
@@ -3503,9 +3788,11 @@
 
 	mutex_lock(&sde_crtc->crtc_lock);
 	sde_crtc->misr_enable = enable;
+	sde_crtc->misr_frame_count = frame_count;
 	for (i = 0; i < sde_crtc->num_mixers; ++i) {
+		sde_crtc->misr_data[i] = 0;
 		m = &sde_crtc->mixers[i];
-		if (!m->hw_lm)
+		if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
 			continue;
 
 		m->hw_lm->ops.setup_misr(m->hw_lm, enable, frame_count);
@@ -3522,6 +3809,7 @@
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_mixer *m;
 	int i = 0, rc;
+	u32 misr_status;
 	ssize_t len = 0;
 	char buf[MISR_BUFF_SIZE + 1] = {'\0'};
 
@@ -3545,13 +3833,16 @@
 
 	for (i = 0; i < sde_crtc->num_mixers; ++i) {
 		m = &sde_crtc->mixers[i];
-		if (!m->hw_lm)
+		if (!m->hw_lm || !m->hw_lm->ops.collect_misr)
 			continue;
 
+		misr_status = m->hw_lm->ops.collect_misr(m->hw_lm);
+		sde_crtc->misr_data[i] = misr_status ? misr_status :
+							sde_crtc->misr_data[i];
 		len += snprintf(buf + len, MISR_BUFF_SIZE - len, "lm idx:%d\n",
 					m->hw_lm->idx - LM_0);
 		len += snprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n",
-				m->hw_lm->ops.collect_misr(m->hw_lm));
+							sde_crtc->misr_data[i]);
 	}
 
 buff_check:
@@ -3592,6 +3883,7 @@
 	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
 	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc->state);
 	struct sde_crtc_res *res;
+	struct sde_crtc_respool *rp;
 	int i;
 
 	seq_printf(s, "num_connectors: %d\n", cstate->num_connectors);
@@ -3609,12 +3901,16 @@
 				sde_crtc->cur_perf.max_per_pipe_ib[i]);
 	}
 
-	seq_printf(s, "rp.%d: ", cstate->rp.sequence_id);
-	list_for_each_entry(res, &cstate->rp.res_list, list)
-		seq_printf(s, "0x%x/0x%llx/%pK/%d ",
-				res->type, res->tag, res->val,
-				atomic_read(&res->refcount));
-	seq_puts(s, "\n");
+	mutex_lock(&sde_crtc->rp_lock);
+	list_for_each_entry(rp, &sde_crtc->rp_head, rp_list) {
+		seq_printf(s, "rp.%d: ", rp->sequence_id);
+		list_for_each_entry(res, &rp->res_list, list)
+			seq_printf(s, "0x%x/0x%llx/%pK/%d ",
+					res->type, res->tag, res->val,
+					atomic_read(&res->refcount));
+		seq_puts(s, "\n");
+	}
+	mutex_unlock(&sde_crtc->rp_lock);
 
 	return 0;
 }
@@ -3831,6 +4127,9 @@
 	spin_lock_init(&sde_crtc->spin_lock);
 	atomic_set(&sde_crtc->frame_pending, 0);
 
+	mutex_init(&sde_crtc->rp_lock);
+	INIT_LIST_HEAD(&sde_crtc->rp_head);
+
 	init_completion(&sde_crtc->frame_done_comp);
 
 	INIT_LIST_HEAD(&sde_crtc->frame_event_list);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 84f9ce1..f8ab110 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -123,8 +123,11 @@
  * @vblank_cb_count : count of vblank callback since last reset
  * @play_count    : frame count between crtc enable and disable
  * @vblank_cb_time  : ktime at vblank count reset
- * @vblank_enable : whether the user has requested vblank events
+ * @vblank_requested : whether the user has requested vblank events
  * @suspend         : whether or not a suspend operation is in progress
+ * @enabled       : whether the SDE CRTC is currently enabled. updated in the
+ *                  commit-thread, not state-swap time which is earlier, so
+ *                  safe to make decisions on during VBLANK on/off work
  * @feature_list  : list of color processing features supported on a crtc
  * @active_list   : list of color processing features are active
  * @dirty_list    : list of color processing features are dirty
@@ -142,8 +145,12 @@
  * @event_free_list : List of available event structures
  * @event_lock    : Spinlock around event handling code
  * @misr_enable   : boolean entry indicates misr enable/disable status.
+ * @misr_frame_count  : misr frame count provided by client
+ * @misr_data     : store misr data before turning off the clocks.
  * @power_event   : registered power event handle
  * @cur_perf      : current performance committed to clock/bandwidth driver
+ * @rp_lock       : serialization lock for resource pool
+ * @rp_head       : list of active resource pool
  */
 struct sde_crtc {
 	struct drm_crtc base;
@@ -171,8 +178,9 @@
 	u32 vblank_cb_count;
 	u64 play_count;
 	ktime_t vblank_cb_time;
-	bool vblank_enable;
+	bool vblank_requested;
 	bool suspend;
+	bool enabled;
 
 	struct list_head feature_list;
 	struct list_head active_list;
@@ -194,10 +202,15 @@
 	struct list_head event_free_list;
 	spinlock_t event_lock;
 	bool misr_enable;
+	u32 misr_frame_count;
+	u32 misr_data[CRTC_DUAL_MIXERS];
 
 	struct sde_power_event *power_event;
 
 	struct sde_core_perf_params cur_perf;
+
+	struct mutex rp_lock;
+	struct list_head rp_head;
 };
 
 #define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
@@ -242,11 +255,17 @@
 
 /**
  * sde_crtc_respool - crtc resource pool
+ * @rp_lock: pointer to serialization lock
+ * @rp_head: pointer to head of active resource pools of this crtc
+ * @rp_list: list of crtc resource pool
  * @sequence_id: sequence identifier, incremented per state duplication
  * @res_list: list of resource managed by this resource pool
  * @ops: resource operations for parent resource pool
  */
 struct sde_crtc_respool {
+	struct mutex *rp_lock;
+	struct list_head *rp_head;
+	struct list_head rp_list;
 	u32 sequence_id;
 	struct list_head res_list;
 	struct sde_crtc_res_ops ops;
@@ -492,4 +511,21 @@
 void sde_crtc_get_crtc_roi(struct drm_crtc_state *state,
 		const struct sde_rect **crtc_roi);
 
+/** sde_crt_get_secure_level - retrieve the secure level from the give state
+ *	object, this is used to determine the secure state of the crtc
+ * @crtc : Pointer to drm crtc structure
+ * @usr: Pointer to drm crtc state
+ * return: secure_level
+ */
+static inline int sde_crtc_get_secure_level(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	if (!crtc || !state)
+		return -EINVAL;
+
+	return sde_crtc_get_property(to_sde_crtc_state(state),
+			CRTC_PROP_SECURITY_LEVEL);
+}
+
+
 #endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 0e94085..3b92f7a 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -71,7 +71,11 @@
 
 #define MISR_BUFF_SIZE			256
 
-#define IDLE_TIMEOUT	64
+#define IDLE_TIMEOUT	(66 - 16/2)
+#define IDLE_SHORT_TIMEOUT	1
+
+/* Maximum number of VSYNC wait attempts for RSC state transition */
+#define MAX_RSC_WAIT	5
 
 /**
  * enum sde_enc_rc_events - events for resource control state machine
@@ -86,15 +90,29 @@
  *	Event signals the end of the data transfer after the PP FRAME_DONE
  *	event. At the end of this event, a delayed work is scheduled to go to
  *	IDLE_PC state after IDLE_TIMEOUT time.
+ * @SDE_ENC_RC_EVENT_PRE_STOP:
+ *	This event happens at NORMAL priority.
+ *	This event, when received during the ON state, set RSC to IDLE, and
+ *	and leave the RC STATE in the PRE_OFF state.
+ *	It should be followed by the STOP event as part of encoder disable.
+ *	If received during IDLE or OFF states, it will do nothing.
  * @SDE_ENC_RC_EVENT_STOP:
  *	This event happens at NORMAL priority.
- *	When this event is received, disable all the MDP/DSI core clocks
- *	and request RSC with IDLE state. Resource state should be in OFF
- *	at the end of the event.
- * @SDE_ENC_RC_EARLY_WAKEUP
+ *	When this event is received, disable all the MDP/DSI core clocks, and
+ *	disable IRQs. It should be called from the PRE_OFF or IDLE states.
+ *	IDLE is expected when IDLE_PC has run, and PRE_OFF did nothing.
+ *	PRE_OFF is expected when PRE_STOP was executed during the ON state.
+ *	Resource state should be in OFF at the end of the event.
+ * @SDE_ENC_RC_EVENT_PRE_MODESET:
  *	This event happens at NORMAL priority from a work item.
- *	Event signals that there will be frame update soon and the driver should
- *	wake up early to update the frame with minimum latency.
+ *	Event signals that there is a seamless mode switch is in prgoress. A
+ *	client needs to turn of only irq - leave clocks ON to reduce the mode
+ *	switch latency.
+ * @SDE_ENC_RC_EVENT_POST_MODESET:
+ *	This event happens at NORMAL priority from a work item.
+ *	Event signals that seamless mode switch is complete and resources are
+ *	acquired. Clients wants to turn on the irq again and update the rsc
+ *	with new vtotal.
  * @SDE_ENC_RC_EVENT_ENTER_IDLE:
  *	This event happens at NORMAL priority from a work item.
  *	Event signals that there were no frame updates for IDLE_TIMEOUT time.
@@ -104,20 +122,26 @@
 enum sde_enc_rc_events {
 	SDE_ENC_RC_EVENT_KICKOFF = 1,
 	SDE_ENC_RC_EVENT_FRAME_DONE,
+	SDE_ENC_RC_EVENT_PRE_STOP,
 	SDE_ENC_RC_EVENT_STOP,
-	SDE_ENC_RC_EVENT_EARLY_WAKE_UP,
+	SDE_ENC_RC_EVENT_PRE_MODESET,
+	SDE_ENC_RC_EVENT_POST_MODESET,
 	SDE_ENC_RC_EVENT_ENTER_IDLE
 };
 
 /*
  * enum sde_enc_rc_states - states that the resource control maintains
  * @SDE_ENC_RC_STATE_OFF: Resource is in OFF state
+ * @SDE_ENC_RC_STATE_PRE_OFF: Resource is transitioning to OFF state
  * @SDE_ENC_RC_STATE_ON: Resource is in ON state
+ * @SDE_ENC_RC_STATE_MODESET: Resource is in modeset state
  * @SDE_ENC_RC_STATE_IDLE: Resource is in IDLE state
  */
 enum sde_enc_rc_states {
 	SDE_ENC_RC_STATE_OFF,
+	SDE_ENC_RC_STATE_PRE_OFF,
 	SDE_ENC_RC_STATE_ON,
+	SDE_ENC_RC_STATE_MODESET,
 	SDE_ENC_RC_STATE_IDLE
 };
 
@@ -159,7 +183,9 @@
  * @rsc_client:			rsc client pointer
  * @rsc_state_init:		boolean to indicate rsc config init
  * @disp_info:			local copy of msm_display_info struct
+ * @mode_info:			local copy of msm_mode_info struct
  * @misr_enable:		misr enable/disable status
+ * @misr_frame_count:		misr frame count before start capturing the data
  * @idle_pc_supported:		indicate if idle power collaps is supported
  * @rc_lock:			resource control mutex lock to protect
  *				virt encoder over various state changes
@@ -168,7 +194,7 @@
  *				clks and resources after IDLE_TIMEOUT time.
  * @topology:                   topology of the display
  * @mode_set_complete:          flag to indicate modeset completion
- * @rsc_cfg:			rsc configuration
+ * @rsc_config:			rsc configuration for display vtotal, fps, etc.
  * @cur_conn_roi:		current connector roi
  * @prv_conn_roi:		previous connector roi to optimize if unchanged
  */
@@ -202,7 +228,9 @@
 	struct sde_rsc_client *rsc_client;
 	bool rsc_state_init;
 	struct msm_display_info disp_info;
+	struct msm_mode_info mode_info;
 	bool misr_enable;
+	u32 misr_frame_count;
 
 	bool idle_pc_supported;
 	struct mutex rc_lock;
@@ -211,7 +239,7 @@
 	struct msm_display_topology topology;
 	bool mode_set_complete;
 
-	struct sde_encoder_rsc_config rsc_cfg;
+	struct sde_rsc_cmd_config rsc_config;
 	struct sde_rect cur_conn_roi;
 	struct sde_rect prv_conn_roi;
 };
@@ -228,7 +256,7 @@
 		return false;
 
 	sde_enc = to_sde_encoder_virt(drm_enc);
-	comp_info = &sde_enc->disp_info.comp_info;
+	comp_info = &sde_enc->mode_info.comp_info;
 
 	return (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC);
 }
@@ -321,6 +349,8 @@
 	/* return EWOULDBLOCK since we know the wait isn't necessary */
 	if (phys_enc->enable_state == SDE_ENC_DISABLED) {
 		SDE_ERROR_PHYS(phys_enc, "encoder is disabled\n");
+		SDE_EVT32(DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
+				irq->irq_idx, intr_idx, SDE_EVTLOG_ERROR);
 		return -EWOULDBLOCK;
 	}
 
@@ -334,9 +364,9 @@
 
 	SDE_DEBUG_PHYS(phys_enc, "pending_cnt %d\n",
 			atomic_read(wait_info->atomic_cnt));
-	SDE_EVT32(DRMID(phys_enc->parent), irq->hw_idx,
-			atomic_read(wait_info->atomic_cnt),
-			SDE_EVTLOG_FUNC_ENTRY);
+	SDE_EVT32_VERBOSE(DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
+		irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0,
+		atomic_read(wait_info->atomic_cnt), SDE_EVTLOG_FUNC_ENTRY);
 
 	ret = sde_encoder_helper_wait_event_timeout(
 			DRMID(phys_enc->parent),
@@ -349,9 +379,10 @@
 		if (irq_status) {
 			unsigned long flags;
 
-			SDE_EVT32(DRMID(phys_enc->parent),
-					irq->hw_idx,
-					atomic_read(wait_info->atomic_cnt));
+			SDE_EVT32(DRMID(phys_enc->parent), intr_idx,
+				irq->hw_idx, irq->irq_idx,
+				phys_enc->hw_pp->idx - PINGPONG_0,
+				atomic_read(wait_info->atomic_cnt));
 			SDE_DEBUG_PHYS(phys_enc,
 					"done but irq %d not triggered\n",
 					irq->irq_idx);
@@ -361,13 +392,22 @@
 			ret = 0;
 		} else {
 			ret = -ETIMEDOUT;
+			SDE_EVT32(DRMID(phys_enc->parent), intr_idx,
+				irq->hw_idx, irq->irq_idx,
+				phys_enc->hw_pp->idx - PINGPONG_0,
+				atomic_read(wait_info->atomic_cnt), irq_status,
+				SDE_EVTLOG_ERROR);
 		}
 	} else {
 		ret = 0;
+		SDE_EVT32(DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
+			irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0,
+			atomic_read(wait_info->atomic_cnt));
 	}
 
-	SDE_EVT32(DRMID(phys_enc->parent), irq->hw_idx, ret,
-			SDE_EVTLOG_FUNC_EXIT);
+	SDE_EVT32_VERBOSE(DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
+		irq->irq_idx, ret, phys_enc->hw_pp->idx - PINGPONG_0,
+		atomic_read(wait_info->atomic_cnt), SDE_EVTLOG_FUNC_EXIT);
 
 	return ret;
 }
@@ -501,7 +541,7 @@
 			phys->ops.get_hw_resources(phys, hw_res, conn_state);
 	}
 
-	hw_res->topology = sde_enc->topology;
+	hw_res->topology = sde_enc->mode_info.topology;
 }
 
 void sde_encoder_destroy(struct drm_encoder *drm_enc)
@@ -625,7 +665,7 @@
 			cur_mode->hdisplay == adj_mode->hdisplay &&
 			cur_mode->vrefresh == adj_mode->vrefresh) {
 			adj_mode->private = cur_mode->private;
-			adj_mode->private_flags = cur_mode->private_flags;
+			adj_mode->private_flags |= cur_mode->private_flags;
 		}
 	}
 }
@@ -863,7 +903,7 @@
 	struct sde_encoder_phys *enc_master = sde_enc->cur_master;
 	const struct sde_rect *roi = &sde_enc->cur_conn_roi;
 	struct msm_display_dsc_info *dsc =
-		&sde_enc->disp_info.comp_info.dsc_info;
+		&sde_enc->mode_info.comp_info.dsc_info;
 
 	if (dsc == NULL || hw_dsc == NULL || hw_pp == NULL || !enc_master) {
 		SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n");
@@ -928,8 +968,8 @@
 	if (enc_master->intf_mode == INTF_MODE_VIDEO)
 		dsc_common_mode |= DSC_MODE_VIDEO;
 
-	memcpy(&dsc[0], &sde_enc->disp_info.comp_info.dsc_info, sizeof(dsc[0]));
-	memcpy(&dsc[1], &sde_enc->disp_info.comp_info.dsc_info, sizeof(dsc[1]));
+	memcpy(&dsc[0], &sde_enc->mode_info.comp_info.dsc_info, sizeof(dsc[0]));
+	memcpy(&dsc[1], &sde_enc->mode_info.comp_info.dsc_info, sizeof(dsc[1]));
 
 	/*
 	 * Since both DSC use same pic dimension, set same pic dimension
@@ -993,7 +1033,7 @@
 	struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
 	struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
 	struct msm_display_dsc_info *dsc =
-		&sde_enc->disp_info.comp_info.dsc_info;
+		&sde_enc->mode_info.comp_info.dsc_info;
 	bool half_panel_partial_update;
 	int i;
 
@@ -1129,6 +1169,7 @@
 	struct sde_kms *sde_kms;
 	struct sde_hw_mdp *hw_mdptop;
 	struct drm_encoder *drm_enc;
+	struct msm_mode_info *mode_info;
 	int i;
 
 	if (!sde_enc || !disp_info) {
@@ -1158,13 +1199,19 @@
 		return;
 	}
 
+	mode_info = &sde_enc->mode_info;
+	if (!mode_info) {
+		SDE_ERROR("invalid mode info\n");
+		return;
+	}
+
 	if (hw_mdptop->ops.setup_vsync_source &&
 			disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) {
 		for (i = 0; i < sde_enc->num_phys_encs; i++)
 			vsync_cfg.ppnumber[i] = sde_enc->hw_pp[i]->idx;
 
 		vsync_cfg.pp_count = sde_enc->num_phys_encs;
-		vsync_cfg.frame_rate = sde_enc->disp_info.frame_rate;
+		vsync_cfg.frame_rate = mode_info->frame_rate;
 		if (is_dummy)
 			vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_1;
 		else if (disp_info->is_te_using_watchdog_timer)
@@ -1177,26 +1224,35 @@
 	}
 }
 
-static int sde_encoder_update_rsc_client(
+static int _sde_encoder_update_rsc_client(
 		struct drm_encoder *drm_enc,
 		struct sde_encoder_rsc_config *config, bool enable)
 {
 	struct sde_encoder_virt *sde_enc;
+	struct drm_crtc *crtc;
 	enum sde_rsc_state rsc_state;
-	struct sde_rsc_cmd_config rsc_config;
-	int ret;
+	struct sde_rsc_cmd_config *rsc_config;
+	int ret, prefill_lines;
 	struct msm_display_info *disp_info;
+	struct msm_mode_info *mode_info;
+	int wait_vblank_crtc_id = SDE_RSC_INVALID_CRTC_ID;
+	int wait_count = 0;
+	struct drm_crtc *primary_crtc;
+	int pipe = -1;
 
-	if (!drm_enc) {
-		SDE_ERROR("invalid encoder\n");
+	if (!drm_enc || !drm_enc->crtc || !drm_enc->dev) {
+		SDE_ERROR("invalid arguments\n");
 		return -EINVAL;
 	}
 
 	sde_enc = to_sde_encoder_virt(drm_enc);
+	crtc = drm_enc->crtc;
 	disp_info = &sde_enc->disp_info;
+	mode_info = &sde_enc->mode_info;
+	rsc_config = &sde_enc->rsc_config;
 
 	if (!sde_enc->rsc_client) {
-		SDE_DEBUG("rsc client not created\n");
+		SDE_DEBUG_ENC(sde_enc, "rsc client not created\n");
 		return 0;
 	}
 
@@ -1209,40 +1265,119 @@
 		(((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) &&
 		  disp_info->is_primary) ? SDE_RSC_CMD_STATE :
 		SDE_RSC_VID_STATE) : SDE_RSC_IDLE_STATE;
+	prefill_lines = config ? mode_info->prefill_lines +
+		config->inline_rotate_prefill : mode_info->prefill_lines;
 
-	if (config && memcmp(&sde_enc->rsc_cfg, config,
-			sizeof(sde_enc->rsc_cfg)))
+	/* compare specific items and reconfigure the rsc */
+	if ((rsc_config->fps != mode_info->frame_rate) ||
+	    (rsc_config->vtotal != mode_info->vtotal) ||
+	    (rsc_config->prefill_lines != prefill_lines) ||
+	    (rsc_config->jitter_numer != mode_info->jitter_numer) ||
+	    (rsc_config->jitter_denom != mode_info->jitter_denom)) {
+		rsc_config->fps = mode_info->frame_rate;
+		rsc_config->vtotal = mode_info->vtotal;
+		rsc_config->prefill_lines = prefill_lines;
+		rsc_config->jitter_numer = mode_info->jitter_numer;
+		rsc_config->jitter_denom = mode_info->jitter_denom;
 		sde_enc->rsc_state_init = false;
+	}
 
 	if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_init
 					&& disp_info->is_primary) {
-		rsc_config.fps = disp_info->frame_rate;
-		rsc_config.vtotal = disp_info->vtotal;
-		rsc_config.prefill_lines = disp_info->prefill_lines;
-		rsc_config.jitter_numer = disp_info->jitter_numer;
-		rsc_config.jitter_denom = disp_info->jitter_denom;
-		rsc_config.prefill_lines += config ?
-				config->inline_rotate_prefill : 0;
 		/* update it only once */
 		sde_enc->rsc_state_init = true;
-		if (config)
-			sde_enc->rsc_cfg = *config;
 
 		ret = sde_rsc_client_state_update(sde_enc->rsc_client,
-			rsc_state, &rsc_config,
-			drm_enc->crtc ? drm_enc->crtc->index : -1);
+			rsc_state, rsc_config, crtc->base.id,
+			&wait_vblank_crtc_id);
 	} else {
 		ret = sde_rsc_client_state_update(sde_enc->rsc_client,
-			rsc_state, NULL,
-			drm_enc->crtc ? drm_enc->crtc->index : -1);
+			rsc_state, NULL, crtc->base.id,
+			&wait_vblank_crtc_id);
 	}
 
-	if (ret)
-		SDE_ERROR("sde rsc client update failed ret:%d\n", ret);
+	/**
+	 * if RSC performed a state change that requires a VBLANK wait, it will
+	 * set wait_vblank_crtc_id to the CRTC whose VBLANK we must wait on.
+	 *
+	 * if we are the primary display, we will need to enable and wait
+	 * locally since we hold the commit thread
+	 *
+	 * if we are an external display, we must send a signal to the primary
+	 * to enable its VBLANK and wait one, since the RSC hardware is driven
+	 * by the primary panel's VBLANK signals
+	 */
+	SDE_EVT32_VERBOSE(DRMID(drm_enc), wait_vblank_crtc_id);
+	if (ret) {
+		SDE_ERROR_ENC(sde_enc,
+				"sde rsc client update failed ret:%d\n", ret);
+		return ret;
+	} else if (wait_vblank_crtc_id == SDE_RSC_INVALID_CRTC_ID) {
+		return ret;
+	}
+
+	if (crtc->base.id != wait_vblank_crtc_id) {
+		primary_crtc = drm_crtc_find(drm_enc->dev, wait_vblank_crtc_id);
+		if (!primary_crtc) {
+			SDE_ERROR_ENC(sde_enc,
+					"failed to find primary crtc id %d\n",
+					wait_vblank_crtc_id);
+			return -EINVAL;
+		}
+		pipe = drm_crtc_index(primary_crtc);
+	}
+
+	/**
+	 * note: VBLANK is expected to be enabled at this point in
+	 * resource control state machine if on primary CRTC
+	 */
+	for (wait_count = 0; wait_count < MAX_RSC_WAIT; wait_count++) {
+		if (sde_rsc_client_is_state_update_complete(
+				sde_enc->rsc_client))
+			break;
+
+		if (crtc->base.id == wait_vblank_crtc_id)
+			ret = sde_encoder_wait_for_event(drm_enc,
+					MSM_ENC_VBLANK);
+		else
+			drm_wait_one_vblank(drm_enc->dev, pipe);
+
+		if (ret) {
+			SDE_ERROR_ENC(sde_enc,
+					"wait for vblank failed ret:%d\n", ret);
+			break;
+		}
+	}
+
+	if (wait_count >= MAX_RSC_WAIT)
+		SDE_EVT32(DRMID(drm_enc), wait_vblank_crtc_id, wait_count,
+				SDE_EVTLOG_ERROR);
 
 	return ret;
 }
 
+static void _sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable)
+{
+	struct sde_encoder_virt *sde_enc;
+	int i;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return;
+	}
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+
+	SDE_DEBUG_ENC(sde_enc, "enable:%d\n", enable);
+	for (i = 0; i < sde_enc->num_phys_encs; i++) {
+		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
+
+		if (phys && phys->ops.irq_control)
+			phys->ops.irq_control(phys, enable);
+	}
+
+}
+
 struct sde_rsc_client *sde_encoder_get_rsc_client(struct drm_encoder *drm_enc)
 {
 	struct sde_encoder_virt *sde_enc;
@@ -1253,14 +1388,43 @@
 	return sde_enc->rsc_client;
 }
 
+static void _sde_encoder_resource_control_rsc_update(
+		struct drm_encoder *drm_enc, bool enable)
+{
+	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
+	struct sde_encoder_rsc_config rsc_cfg = { 0 };
+
+	if (enable) {
+		rsc_cfg.inline_rotate_prefill =
+				sde_crtc_get_inline_prefill(drm_enc->crtc);
+
+		/* connect the TE source to actual TE GPIO to drive RSC */
+		_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info,
+				false);
+
+		_sde_encoder_update_rsc_client(drm_enc, &rsc_cfg, true);
+	} else {
+		_sde_encoder_update_rsc_client(drm_enc, NULL, false);
+
+		/**
+		 * disconnect the TE source from the actual TE GPIO for RSC
+		 *
+		 * this call is for hardware workaround on sdm845 and should
+		 * not be removed without considering the design changes for
+		 * sde rsc + command mode concurrency. It may lead to pp
+		 * timeout due to vsync from panel for command mode panel.
+		 */
+		_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info,
+				true);
+	}
+}
+
 static void _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
 		bool enable)
 {
 	struct msm_drm_private *priv;
 	struct sde_kms *sde_kms;
 	struct sde_encoder_virt *sde_enc;
-	struct sde_encoder_rsc_config rsc_cfg = { 0 };
-	int i;
 
 	sde_enc = to_sde_encoder_virt(drm_enc);
 	priv = drm_enc->dev->dev_private;
@@ -1283,43 +1447,11 @@
 		sde_connector_clk_ctrl(sde_enc->cur_master->connector, true);
 
 		/* enable all the irq */
-		for (i = 0; i < sde_enc->num_phys_encs; i++) {
-			struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
-
-			if (phys && phys->ops.irq_control)
-				phys->ops.irq_control(phys, true);
-		}
-
-		rsc_cfg.inline_rotate_prefill =
-				sde_crtc_get_inline_prefill(drm_enc->crtc);
-
-		_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info,
-									false);
-
-		/* enable RSC */
-		sde_encoder_update_rsc_client(drm_enc, &rsc_cfg, true);
+		_sde_encoder_irq_control(drm_enc, true);
 
 	} else {
-
-		/* disable RSC */
-		sde_encoder_update_rsc_client(drm_enc, NULL, false);
-
-		/**
-		 * this call is for hardware workaround on sdm845 and should
-		 * not be removed without considering the design changes for
-		 * sde rsc + command mode concurrency. It may lead to pp
-		 * timeout due to vsync from panel for command mode panel.
-		 */
-		_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info,
-									true);
 		/* disable all the irq */
-		for (i = 0; i < sde_enc->num_phys_encs; i++) {
-			struct sde_encoder_phys *phys =
-						sde_enc->phys_encs[i];
-
-			if (phys && phys->ops.irq_control)
-				phys->ops.irq_control(phys, false);
-		}
+		_sde_encoder_irq_control(drm_enc, false);
 
 		/* disable DSI clks */
 		sde_connector_clk_ctrl(sde_enc->cur_master->connector, false);
@@ -1334,10 +1466,12 @@
 static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
 		u32 sw_event)
 {
-	bool schedule_off = false;
+	bool autorefresh_enabled = false;
+	unsigned int lp, idle_timeout;
 	struct sde_encoder_virt *sde_enc;
 	struct msm_drm_private *priv;
 	struct msm_drm_thread *disp_thread;
+	int ret;
 
 	if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private ||
 			!drm_enc->crtc) {
@@ -1354,17 +1488,20 @@
 	disp_thread = &priv->disp_thread[drm_enc->crtc->index];
 
 	/*
-	 * when idle_pc is not supported, process only KICKOFF and STOP
-	 * event and return early for other events (ie video mode).
+	 * when idle_pc is not supported, process only KICKOFF, STOP and MODESET
+	 * events and return early for other events (ie video mode).
 	 */
 	if (!sde_enc->idle_pc_supported &&
 			(sw_event != SDE_ENC_RC_EVENT_KICKOFF &&
-				sw_event != SDE_ENC_RC_EVENT_STOP))
+			sw_event != SDE_ENC_RC_EVENT_PRE_MODESET &&
+			sw_event != SDE_ENC_RC_EVENT_POST_MODESET &&
+			sw_event != SDE_ENC_RC_EVENT_STOP &&
+			sw_event != SDE_ENC_RC_EVENT_PRE_STOP))
 		return 0;
 
 	SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc_supported:%d\n", sw_event,
 			sde_enc->idle_pc_supported);
-	SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+	SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
 			sde_enc->rc_state, SDE_EVTLOG_FUNC_ENTRY);
 
 	switch (sw_event) {
@@ -1383,10 +1520,19 @@
 					sw_event);
 			mutex_unlock(&sde_enc->rc_lock);
 			return 0;
+		} else if (sde_enc->rc_state != SDE_ENC_RC_STATE_OFF &&
+				sde_enc->rc_state != SDE_ENC_RC_STATE_IDLE) {
+			SDE_ERROR_ENC(sde_enc, "sw_event:%d, rc in state %d\n",
+					sw_event, sde_enc->rc_state);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					SDE_EVTLOG_ERROR);
+			mutex_unlock(&sde_enc->rc_lock);
+			return -EINVAL;
 		}
 
 		/* enable all the clks and resources */
 		_sde_encoder_resource_control_helper(drm_enc, true);
+		_sde_encoder_resource_control_rsc_update(drm_enc, true);
 
 		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
 				SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE1);
@@ -1405,6 +1551,8 @@
 		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
 			SDE_ERROR_ENC(sde_enc, "sw_event:%d,rc:%d-unexpected\n",
 					sw_event, sde_enc->rc_state);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					SDE_EVTLOG_ERROR);
 			return -EINVAL;
 		}
 
@@ -1417,18 +1565,38 @@
 			return 0;
 		}
 
-		/* schedule delayed off work */
-		kthread_queue_delayed_work(
+		/* schedule delayed off work if autorefresh is disabled */
+		if (sde_enc->cur_master &&
+			sde_enc->cur_master->ops.is_autorefresh_enabled)
+			autorefresh_enabled =
+				sde_enc->cur_master->ops.is_autorefresh_enabled(
+							sde_enc->cur_master);
+
+		/* set idle timeout based on master connector's lp value */
+		if (sde_enc->cur_master)
+			lp = sde_connector_get_lp(
+					sde_enc->cur_master->connector);
+		else
+			lp = SDE_MODE_DPMS_ON;
+
+		if (lp == SDE_MODE_DPMS_LP2)
+			idle_timeout = IDLE_SHORT_TIMEOUT;
+		else
+			idle_timeout = IDLE_TIMEOUT;
+
+		if (!autorefresh_enabled)
+			kthread_queue_delayed_work(
 				&disp_thread->worker,
 				&sde_enc->delayed_off_work,
-				msecs_to_jiffies(IDLE_TIMEOUT));
+				msecs_to_jiffies(idle_timeout));
 		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
-				SDE_EVTLOG_FUNC_CASE2);
+				autorefresh_enabled,
+				idle_timeout, SDE_EVTLOG_FUNC_CASE2);
 		SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n",
 				sw_event);
 		break;
 
-	case SDE_ENC_RC_EVENT_STOP:
+	case SDE_ENC_RC_EVENT_PRE_STOP:
 		/* cancel delayed off work, if any */
 		if (kthread_cancel_delayed_work_sync(
 				&sde_enc->delayed_off_work))
@@ -1437,79 +1605,128 @@
 
 		mutex_lock(&sde_enc->rc_lock);
 
+		/* skip if is already OFF or IDLE, resources are off already */
+		if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF ||
+				sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
+			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in %d state\n",
+					sw_event, sde_enc->rc_state);
+			mutex_unlock(&sde_enc->rc_lock);
+			return 0;
+		}
+
+		/**
+		 * IRQs are still enabled currently, which allows wait for
+		 * VBLANK which RSC may require to correctly transition to OFF
+		 */
+		_sde_encoder_resource_control_rsc_update(drm_enc, false);
+
+		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+				SDE_ENC_RC_STATE_PRE_OFF,
+				SDE_EVTLOG_FUNC_CASE3);
+
+		sde_enc->rc_state = SDE_ENC_RC_STATE_PRE_OFF;
+
+		mutex_unlock(&sde_enc->rc_lock);
+		break;
+
+	case SDE_ENC_RC_EVENT_STOP:
+		mutex_lock(&sde_enc->rc_lock);
+
 		/* return if the resource control is already in OFF state */
 		if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) {
 			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in OFF state\n",
 					sw_event);
 			mutex_unlock(&sde_enc->rc_lock);
 			return 0;
+		} else if (sde_enc->rc_state == SDE_ENC_RC_STATE_ON ||
+			   sde_enc->rc_state == SDE_ENC_RC_STATE_MODESET) {
+			SDE_ERROR_ENC(sde_enc, "sw_event:%d, rc in state %d\n",
+					sw_event, sde_enc->rc_state);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					SDE_EVTLOG_ERROR);
+			mutex_unlock(&sde_enc->rc_lock);
+			return -EINVAL;
 		}
 
-		/*
-		 * disable the clks and resources only if the resource control
-		 * is in ON state, otherwise the clks and resources would have
-		 * been disabled while going into IDLE state
+		/**
+		 * expect to arrive here only if in either idle state or pre-off
+		 * and in IDLE state the resources are already disabled
 		 */
-		if (sde_enc->rc_state == SDE_ENC_RC_STATE_ON)
+		if (sde_enc->rc_state == SDE_ENC_RC_STATE_PRE_OFF)
 			_sde_encoder_resource_control_helper(drm_enc, false);
 
 		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
-				SDE_ENC_RC_STATE_OFF, SDE_EVTLOG_FUNC_CASE3);
+				SDE_ENC_RC_STATE_OFF, SDE_EVTLOG_FUNC_CASE4);
 
 		sde_enc->rc_state = SDE_ENC_RC_STATE_OFF;
 
 		mutex_unlock(&sde_enc->rc_lock);
 		break;
 
-	case SDE_ENC_RC_EVENT_EARLY_WAKE_UP:
+	case SDE_ENC_RC_EVENT_PRE_MODESET:
 		/* cancel delayed off work, if any */
 		if (kthread_cancel_delayed_work_sync(
-				&sde_enc->delayed_off_work)) {
+				&sde_enc->delayed_off_work))
 			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
 					sw_event);
-			schedule_off = true;
-		}
 
 		mutex_lock(&sde_enc->rc_lock);
 
-		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
-				schedule_off, SDE_EVTLOG_FUNC_CASE4);
-
-		/* return if the resource control is in OFF state */
-		if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) {
-			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in OFF state\n",
-					sw_event);
-			mutex_unlock(&sde_enc->rc_lock);
-			return 0;
-		}
-
-		/*
-		 * enable all the clks and resources if resource control is
-		 * coming out of IDLE state
-		 */
-		if (sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
+		/* return if the resource control is already in ON state */
+		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
+			/* enable all the clks and resources */
 			_sde_encoder_resource_control_helper(drm_enc, true);
+
+			_sde_encoder_resource_control_rsc_update(drm_enc, true);
+
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+				SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE5);
 			sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
-			schedule_off = true;
 		}
 
-		/*
-		 * schedule off work when there are no frames pending and
-		 * 1. early wakeup cancelled off work
-		 * 2. early wakeup changed the rc_state to ON - this is to
-		 *	handle cases where early wakeup is called but no
-		 *	frame updates
-		 */
-		if (schedule_off && !sde_crtc_frame_pending(drm_enc->crtc)) {
-			/* schedule delayed off work */
-			kthread_queue_delayed_work(
-					&disp_thread->worker,
-					&sde_enc->delayed_off_work,
-					msecs_to_jiffies(IDLE_TIMEOUT));
-			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n",
-					sw_event);
+		ret = sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
+		if (ret && ret != -EWOULDBLOCK) {
+			SDE_ERROR_ENC(sde_enc,
+					"wait for commit done returned %d\n",
+					ret);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					ret, SDE_EVTLOG_ERROR);
+			mutex_unlock(&sde_enc->rc_lock);
+			return -EINVAL;
 		}
 
+		_sde_encoder_irq_control(drm_enc, false);
+
+		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+			SDE_ENC_RC_STATE_MODESET, SDE_EVTLOG_FUNC_CASE5);
+
+		sde_enc->rc_state = SDE_ENC_RC_STATE_MODESET;
+		mutex_unlock(&sde_enc->rc_lock);
+		break;
+
+	case SDE_ENC_RC_EVENT_POST_MODESET:
+		mutex_lock(&sde_enc->rc_lock);
+
+		/* return if the resource control is already in ON state */
+		if (sde_enc->rc_state != SDE_ENC_RC_STATE_MODESET) {
+			SDE_ERROR_ENC(sde_enc,
+					"sw_event:%d, rc:%d !MODESET state\n",
+					sw_event, sde_enc->rc_state);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					SDE_EVTLOG_ERROR);
+			mutex_unlock(&sde_enc->rc_lock);
+			return -EINVAL;
+		}
+
+		_sde_encoder_irq_control(drm_enc, true);
+
+		_sde_encoder_update_rsc_client(drm_enc, NULL, true);
+
+		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+				SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE6);
+
+		sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
+
 		mutex_unlock(&sde_enc->rc_lock);
 		break;
 
@@ -1517,10 +1734,10 @@
 		mutex_lock(&sde_enc->rc_lock);
 
 		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
-			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
+			SDE_ERROR_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
 					sw_event, sde_enc->rc_state);
-			SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event,
-					sde_enc->rc_state);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					SDE_EVTLOG_ERROR);
 			mutex_unlock(&sde_enc->rc_lock);
 			return 0;
 		}
@@ -1530,30 +1747,32 @@
 		 * ignore the IDLE event, it's probably a stale timer event
 		 */
 		if (sde_enc->frame_busy_mask[0]) {
-			SDE_DEBUG_ENC(sde_enc,
+			SDE_ERROR_ENC(sde_enc,
 					"sw_event:%d, rc:%d frame pending\n",
 					sw_event, sde_enc->rc_state);
-			SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event,
-					sde_enc->rc_state);
+			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+					SDE_EVTLOG_ERROR);
 			mutex_unlock(&sde_enc->rc_lock);
 			return 0;
 		}
 
 		/* disable all the clks and resources */
+		_sde_encoder_resource_control_rsc_update(drm_enc, false);
 		_sde_encoder_resource_control_helper(drm_enc, false);
 		SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
-				SDE_ENC_RC_STATE_IDLE, SDE_EVTLOG_FUNC_CASE5);
+				SDE_ENC_RC_STATE_IDLE, SDE_EVTLOG_FUNC_CASE7);
 		sde_enc->rc_state = SDE_ENC_RC_STATE_IDLE;
 
 		mutex_unlock(&sde_enc->rc_lock);
 		break;
 
 	default:
+		SDE_EVT32(DRMID(drm_enc), sw_event, SDE_EVTLOG_ERROR);
 		SDE_ERROR("unexpected sw_event: %d\n", sw_event);
 		break;
 	}
 
-	SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+	SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
 			sde_enc->rc_state, SDE_EVTLOG_FUNC_EXIT);
 	return 0;
 }
@@ -1613,7 +1832,7 @@
 
 	sde_conn = to_sde_connector(conn);
 	if (sde_conn) {
-		ret = sde_conn->ops.get_topology(adj_mode, &sde_enc->topology,
+		ret = sde_conn->ops.get_mode_info(adj_mode, &sde_enc->mode_info,
 				sde_kms->catalog->max_mixer_width);
 		if (ret) {
 			SDE_ERROR_ENC(sde_enc,
@@ -1622,6 +1841,19 @@
 		}
 	}
 
+	/* release resources before seamless mode change */
+	if (msm_is_mode_seamless_dms(adj_mode)) {
+		/* restore resource state before releasing them */
+		ret = sde_encoder_resource_control(drm_enc,
+				SDE_ENC_RC_EVENT_PRE_MODESET);
+		if (ret) {
+			SDE_ERROR_ENC(sde_enc,
+					"sde resource control failed: %d\n",
+					ret);
+			return;
+		}
+	}
+
 	/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
 	ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state,
 			conn->state, false);
@@ -1663,6 +1895,11 @@
 		}
 	}
 
+	/* update resources after seamless mode change */
+	if (msm_is_mode_seamless_dms(adj_mode))
+		sde_encoder_resource_control(&sde_enc->base,
+						SDE_ENC_RC_EVENT_POST_MODESET);
+
 	sde_enc->mode_set_complete = true;
 }
 
@@ -1730,15 +1967,19 @@
 {
 	struct sde_encoder_virt *sde_enc = NULL;
 	int i, ret = 0;
+	struct msm_compression_info *comp_info = NULL;
+	struct drm_display_mode *cur_mode = NULL;
 
 	if (!drm_enc) {
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
 	sde_enc = to_sde_encoder_virt(drm_enc);
+	comp_info = &sde_enc->mode_info.comp_info;
+	cur_mode = &sde_enc->base.crtc->state->adjusted_mode;
 
 	SDE_DEBUG_ENC(sde_enc, "\n");
-	SDE_EVT32(DRMID(drm_enc));
+	SDE_EVT32(DRMID(drm_enc), cur_mode->hdisplay, cur_mode->vdisplay);
 
 	sde_enc->cur_master = NULL;
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
@@ -1766,11 +2007,33 @@
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 
-		if (phys && (phys != sde_enc->cur_master) && phys->ops.enable)
-			phys->ops.enable(phys);
+		if (!phys)
+			continue;
+
+		phys->comp_type = comp_info->comp_type;
+		if (phys != sde_enc->cur_master) {
+			/**
+			 * on DMS request, the encoder will be enabled
+			 * already. Invoke restore to reconfigure the
+			 * new mode.
+			 */
+			if (msm_is_mode_seamless_dms(cur_mode) &&
+					phys->ops.restore)
+				phys->ops.restore(phys);
+			else if (phys->ops.enable)
+				phys->ops.enable(phys);
+		}
+
+		if (sde_enc->misr_enable && (sde_enc->disp_info.capabilities &
+		     MSM_DISPLAY_CAP_VID_MODE) && phys->ops.setup_misr)
+			phys->ops.setup_misr(phys, true,
+						sde_enc->misr_frame_count);
 	}
 
-	if (sde_enc->cur_master->ops.enable)
+	if (msm_is_mode_seamless_dms(cur_mode) &&
+			sde_enc->cur_master->ops.restore)
+		sde_enc->cur_master->ops.restore(sde_enc->cur_master);
+	else if (sde_enc->cur_master->ops.enable)
 		sde_enc->cur_master->ops.enable(sde_enc->cur_master);
 
 	_sde_encoder_virt_enable_helper(drm_enc);
@@ -1802,18 +2065,18 @@
 
 	SDE_EVT32(DRMID(drm_enc));
 
+	/* wait for idle */
+	sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
+
+	sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_STOP);
+
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 
-		if (phys && phys->ops.disable && !phys->ops.is_master(phys)) {
+		if (phys && phys->ops.disable)
 			phys->ops.disable(phys);
-			phys->connector = NULL;
-		}
 	}
 
-	if (sde_enc->cur_master && sde_enc->cur_master->ops.disable)
-		sde_enc->cur_master->ops.disable(sde_enc->cur_master);
-
 	/* after phys waits for frame-done, should be no more frames pending */
 	if (atomic_xchg(&sde_enc->frame_done_timeout, 0)) {
 		SDE_ERROR("enc%d timeout pending\n", drm_enc->base.id);
@@ -2096,7 +2359,7 @@
 				atomic_read(info->atomic_cnt) == 0, jiffies);
 		time = ktime_to_ms(ktime_get());
 
-		SDE_EVT32(drm_id, hw_id, rc, time, expected_time,
+		SDE_EVT32_VERBOSE(drm_id, hw_id, rc, time, expected_time,
 				atomic_read(info->atomic_cnt));
 	/* If we timed out, counter is valid and time is less, wait again */
 	} while (atomic_read(info->atomic_cnt) && (rc == 0) &&
@@ -2670,6 +2933,7 @@
 
 	mutex_lock(&sde_enc->enc_lock);
 	sde_enc->misr_enable = enable;
+	sde_enc->misr_frame_count = frame_count;
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 
@@ -2966,8 +3230,6 @@
 
 	SDE_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles);
 
-	phys_params.comp_type = disp_info->comp_info.comp_type;
-
 	if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE)
 		sde_enc->idle_pc_supported = sde_kms->catalog->has_idle_pc;
 
@@ -3172,6 +3434,13 @@
 		case MSM_ENC_TX_COMPLETE:
 			fn_wait = phys->ops.wait_for_tx_complete;
 			break;
+		case MSM_ENC_VBLANK:
+			fn_wait = phys->ops.wait_for_vblank;
+			break;
+		default:
+			SDE_ERROR_ENC(sde_enc, "unknown wait event %d\n",
+					event);
+			return -EINVAL;
 		};
 
 		if (phys && fn_wait) {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index c1a40f5..2098b9f 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -113,6 +113,7 @@
  *				current pending frames to hardware
  * @wait_for_tx_complete:	Wait for hardware to transfer the pixels
  *				to the panel
+ * @wait_for_vblank:		Wait for VBLANK, for sub-driver internal use
  * @prepare_for_kickoff:	Do any work necessary prior to a kickoff
  *				For CMD encoder, may wait for previous tx done
  * @handle_post_kickoff:	Do any work necessary post-kickoff work
@@ -125,6 +126,8 @@
  * @irq_control:		Handler to enable/disable all the encoder IRQs
  * @update_split_role:		Update the split role of the phys enc
  * @restore:			Restore all the encoder configs.
+ * @is_autorefresh_enabled:	provides the autorefresh current
+ *                              enable/disable state.
  */
 
 struct sde_encoder_phys_ops {
@@ -150,6 +153,7 @@
 	int (*control_vblank_irq)(struct sde_encoder_phys *enc, bool enable);
 	int (*wait_for_commit_done)(struct sde_encoder_phys *phys_enc);
 	int (*wait_for_tx_complete)(struct sde_encoder_phys *phys_enc);
+	int (*wait_for_vblank)(struct sde_encoder_phys *phys_enc);
 	void (*prepare_for_kickoff)(struct sde_encoder_phys *phys_enc,
 			struct sde_encoder_kickoff_params *params);
 	void (*handle_post_kickoff)(struct sde_encoder_phys *phys_enc);
@@ -164,6 +168,7 @@
 	void (*update_split_role)(struct sde_encoder_phys *phys_enc,
 			enum sde_enc_split_role role);
 	void (*restore)(struct sde_encoder_phys *phys);
+	bool (*is_autorefresh_enabled)(struct sde_encoder_phys *phys);
 };
 
 /**
@@ -310,9 +315,12 @@
  * @serialize_wait4pp:	serialize wait4pp feature waits for pp_done interrupt
  *			after ctl_start instead of before next frame kickoff
  * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
+ * @autorefresh: autorefresh feature state
  * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can be
  *                      signaled at the next rd_ptr_irq
- * @autorefresh: autorefresh feature state
+ * @rd_ptr_timestamp: last rd_ptr_irq timestamp
+ * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
+ * @pending_vblank_wq: Wait queue for blocking until VBLANK received
  */
 struct sde_encoder_phys_cmd {
 	struct sde_encoder_phys base;
@@ -321,6 +329,9 @@
 	int pp_timeout_report_cnt;
 	struct sde_encoder_phys_cmd_autorefresh autorefresh;
 	atomic_t pending_rd_ptr_cnt;
+	ktime_t rd_ptr_timestamp;
+	atomic_t pending_vblank_cnt;
+	wait_queue_head_t pending_vblank_wq;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 2a46636..23604bd 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -47,6 +47,12 @@
 
 #define SDE_ENC_WR_PTR_START_TIMEOUT_US 20000
 
+/*
+ * Threshold for signalling retire fences in cases where
+ * CTL_START_IRQ is received just after RD_PTR_IRQ
+ */
+#define SDE_ENC_CTL_START_THRESHOLD_US 500
+
 static inline int _sde_encoder_phys_cmd_get_idle_timeout(
 		struct sde_encoder_phys_cmd *cmd_enc)
 {
@@ -212,7 +218,7 @@
 {
 	struct sde_encoder_phys *phys_enc = arg;
 	struct sde_encoder_phys_cmd *cmd_enc;
-	bool signal_fence = false;
+	u32 event = 0;
 
 	if (!phys_enc || !phys_enc->hw_pp)
 		return;
@@ -221,48 +227,31 @@
 	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
 
 	/**
-	 * signal only for master,
-	 * - when the ctl_start irq is done and incremented
-	 *   the pending_rd_ptr_cnt.
-	 * - when ctl_start irq status bit is set. This handles the case
-	 *   where ctl_start status bit is set in hardware, but the interrupt
-	 *   is delayed due to some reason.
+	 * signal only for master, when the ctl_start irq is
+	 * done and incremented the pending_rd_ptr_cnt.
 	 */
-	if (sde_encoder_phys_cmd_is_master(phys_enc) &&
-			atomic_read(&phys_enc->pending_retire_fence_cnt)) {
+	if (sde_encoder_phys_cmd_is_master(phys_enc)
+		    && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1, 0)
+		    && atomic_add_unless(
+				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
 
-		if (atomic_add_unless(
-				&cmd_enc->pending_rd_ptr_cnt, -1, 0)) {
-			signal_fence = true;
-		} else {
-			signal_fence =
-				sde_core_irq_read_nolock(phys_enc->sde_kms,
-				    phys_enc->irq[INTR_IDX_CTL_START].irq_idx,
-				    false);
-			if (signal_fence)
-				SDE_EVT32_IRQ(DRMID(phys_enc->parent),
-				    phys_enc->hw_pp->idx - PINGPONG_0,
-				    atomic_read(
-					&phys_enc->pending_retire_fence_cnt),
-				    SDE_EVTLOG_FUNC_CASE1);
-		}
-
-		if (signal_fence && phys_enc->parent_ops.handle_frame_done) {
-			atomic_add_unless(
-				&phys_enc->pending_retire_fence_cnt, -1, 0);
+		event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
+		if (phys_enc->parent_ops.handle_frame_done)
 			phys_enc->parent_ops.handle_frame_done(
-				phys_enc->parent, phys_enc,
-				SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
-		}
+				phys_enc->parent, phys_enc, event);
 	}
 
 	SDE_EVT32_IRQ(DRMID(phys_enc->parent),
-			phys_enc->hw_pp->idx - PINGPONG_0, signal_fence, 0xfff);
+			phys_enc->hw_pp->idx - PINGPONG_0, event, 0xfff);
 
 	if (phys_enc->parent_ops.handle_vblank_virt)
 		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
 			phys_enc);
 
+	cmd_enc->rd_ptr_timestamp = ktime_get();
+
+	atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0);
+	wake_up_all(&cmd_enc->pending_vblank_wq);
 	SDE_ATRACE_END("rd_ptr_irq");
 }
 
@@ -271,6 +260,8 @@
 	struct sde_encoder_phys *phys_enc = arg;
 	struct sde_encoder_phys_cmd *cmd_enc;
 	struct sde_hw_ctl *ctl;
+	u32 event = 0;
+	s64 time_diff_us;
 
 	if (!phys_enc || !phys_enc->hw_ctl)
 		return;
@@ -279,16 +270,41 @@
 	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
 
 	ctl = phys_enc->hw_ctl;
-	SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0, 0xfff);
 	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
 
-	/*
-	 * this is required for the fence signalling to be done in rd_ptr_irq
-	 * after ctrl_start_irq
-	 */
+	time_diff_us = ktime_us_delta(ktime_get(), cmd_enc->rd_ptr_timestamp);
+
+	/* handle retire fence based on only master */
 	if (sde_encoder_phys_cmd_is_master(phys_enc)
-			&& atomic_read(&phys_enc->pending_retire_fence_cnt))
-		atomic_inc(&cmd_enc->pending_rd_ptr_cnt);
+			&& atomic_read(&phys_enc->pending_retire_fence_cnt)) {
+		/**
+		 * Handle rare cases where the ctl_start_irq is received
+		 * after rd_ptr_irq. If it falls within a threshold, it is
+		 * guaranteed the frame would be picked up in the current TE.
+		 * Signal retire fence immediately in such case.
+		 */
+		if ((time_diff_us <= SDE_ENC_CTL_START_THRESHOLD_US)
+			    && atomic_add_unless(
+				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
+
+			event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
+
+			if (phys_enc->parent_ops.handle_frame_done)
+				phys_enc->parent_ops.handle_frame_done(
+					phys_enc->parent, phys_enc, event);
+
+		/**
+		 * In ideal cases, ctl_start_irq is received before the
+		 * rd_ptr_irq, so set the atomic flag to indicate the event
+		 * and rd_ptr_irq will handle signalling the retire fence
+		 */
+		} else {
+			atomic_inc(&cmd_enc->pending_rd_ptr_cnt);
+		}
+	}
+
+	SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
+				time_diff_us, event, 0xfff);
 
 	/* Signal any waiting ctl start interrupt */
 	wake_up_all(&phys_enc->pending_kickoff_wq);
@@ -467,7 +483,8 @@
 			phys_enc->hw_pp->idx - PINGPONG_0,
 			info.rd_ptr_line_count,
 			info.wr_ptr_line_count);
-	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
+	SDE_EVT32_VERBOSE(DRMID(phys_enc->parent),
+			phys_enc->hw_pp->idx - PINGPONG_0,
 			info.wr_ptr_line_count);
 
 	ret = hw_pp->ops.poll_timeout_wr_ptr(hw_pp, timeout_us);
@@ -584,22 +601,29 @@
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
 	int ret = 0;
+	int refcount;
 
 	if (!phys_enc) {
 		SDE_ERROR("invalid encoder\n");
 		return -EINVAL;
 	}
 
+	refcount = atomic_read(&phys_enc->vblank_refcount);
+
 	/* Slave encoders don't report vblank */
 	if (!sde_encoder_phys_cmd_is_master(phys_enc))
 		goto end;
 
-	SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
-			__builtin_return_address(0),
-			enable, atomic_read(&phys_enc->vblank_refcount));
+	/* protect against negative */
+	if (!enable && refcount == 0) {
+		ret = -EINVAL;
+		goto end;
+	}
 
+	SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
+			__builtin_return_address(0), enable, refcount);
 	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
-			enable, atomic_read(&phys_enc->vblank_refcount));
+			enable, refcount);
 
 	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
 		ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR);
@@ -608,10 +632,14 @@
 				INTR_IDX_RDPTR);
 
 end:
-	if (ret)
+	if (ret) {
 		SDE_ERROR_CMDENC(cmd_enc,
-				"control vblank irq error %d, enable %d\n",
-				ret, enable);
+				"control vblank irq error %d, enable %d, refcount %d\n",
+				ret, enable, refcount);
+		SDE_EVT32(DRMID(phys_enc->parent),
+				phys_enc->hw_pp->idx - PINGPONG_0,
+				enable, refcount, SDE_EVTLOG_ERROR);
+	}
 
 	return ret;
 }
@@ -825,7 +853,7 @@
 	phys_enc->enable_state = SDE_ENC_ENABLED;
 }
 
-static bool _sde_encoder_phys_cmd_is_autorefresh_enabled(
+static bool sde_encoder_phys_cmd_is_autorefresh_enabled(
 		struct sde_encoder_phys *phys_enc)
 {
 	struct sde_hw_pingpong *hw_pp;
@@ -864,33 +892,22 @@
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
-	int ret;
 
 	if (!phys_enc || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
-	SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
+	SDE_DEBUG_CMDENC(cmd_enc, "pp %d state %d\n",
+			phys_enc->hw_pp->idx - PINGPONG_0,
+			phys_enc->enable_state);
+	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
+			phys_enc->enable_state);
 
 	if (phys_enc->enable_state == SDE_ENC_DISABLED) {
 		SDE_ERROR_CMDENC(cmd_enc, "already disabled\n");
 		return;
 	}
 
-	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0);
-
-	if (!_sde_encoder_phys_is_ppsplit_slave(phys_enc)) {
-		ret = _sde_encoder_phys_cmd_wait_for_idle(phys_enc);
-		if (ret) {
-			atomic_set(&phys_enc->pending_kickoff_cnt, 0);
-			SDE_ERROR_CMDENC(cmd_enc,
-					"pp %d failed wait for idle, %d\n",
-					phys_enc->hw_pp->idx - PINGPONG_0, ret);
-			SDE_EVT32(DRMID(phys_enc->parent),
-					phys_enc->hw_pp->idx - PINGPONG_0, ret);
-		}
-	}
-
 	if (phys_enc->hw_pp->ops.enable_tearcheck)
 		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, false);
 	phys_enc->enable_state = SDE_ENC_DISABLED;
@@ -1045,6 +1062,34 @@
 	return rc;
 }
 
+static int sde_encoder_phys_cmd_wait_for_vblank(
+		struct sde_encoder_phys *phys_enc)
+{
+	int rc = 0;
+	struct sde_encoder_phys_cmd *cmd_enc;
+	struct sde_encoder_wait_info wait_info;
+
+	if (!phys_enc)
+		return -EINVAL;
+
+	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
+
+	/* only required for master controller */
+	if (!sde_encoder_phys_cmd_is_master(phys_enc))
+		return rc;
+
+	wait_info.wq = &cmd_enc->pending_vblank_wq;
+	wait_info.atomic_cnt = &cmd_enc->pending_vblank_cnt;
+	wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(cmd_enc);
+
+	atomic_inc(&cmd_enc->pending_vblank_cnt);
+
+	rc = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_RDPTR,
+			&wait_info);
+
+	return rc;
+}
+
 static void sde_encoder_phys_cmd_update_split_role(
 		struct sde_encoder_phys *phys_enc,
 		enum sde_enc_split_role role)
@@ -1083,73 +1128,51 @@
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
+	unsigned long lock_flags;
 
 	if (!phys_enc)
 		return;
 
-	if (sde_encoder_phys_cmd_is_master(phys_enc)) {
-		unsigned long lock_flags;
+	if (!sde_encoder_phys_cmd_is_master(phys_enc))
+		return;
 
+	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
+			cmd_enc->autorefresh.cfg.enable);
 
-		SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0,
-				cmd_enc->autorefresh.cfg.enable);
+	if (!sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
+		return;
 
-		if (!_sde_encoder_phys_cmd_is_autorefresh_enabled(phys_enc))
-			return;
+	/**
+	 * Autorefresh must be disabled carefully:
+	 *  - Autorefresh must be disabled between pp_done and te
+	 *    signal prior to sdm845 targets. All targets after sdm845
+	 *    supports autorefresh disable without turning off the
+	 *    hardware TE and pp_done wait.
+	 *
+	 *  - Wait for TX to Complete
+	 *    Wait for PPDone confirms the last frame transfer is complete.
+	 *
+	 *  - Leave Autorefresh Disabled
+	 *    - Assume disable of Autorefresh since it is now safe
+	 *    - Can now safely Disable Encoder, do debug printing, etc.
+	 *     without worrying that Autorefresh will kickoff
+	 */
 
-		/**
-		 * Autorefresh must be disabled carefully:
-		 *  - Must disable while there is no ongoing transmission
-		 *  - Receiving a TE will trigger the next Autorefresh TX
-		 *  - Only safe to disable Autorefresh between PPDone and TE
-		 *  - However, that is a small time window
-		 *  - Disabling External TE gives large safe window, assuming
-		 *    internally generated TE is set to a large counter value
-		 *
-		 * If Autorefresh is active:
-		 * 1. Disable external TE
-		 *   - TE will run on an SDE counter set to large value (~200ms)
-		 *
-		 * 2. Check for ongoing TX
-		 *   - If ongoing TX, set pending_kickoff_cnt if not set already
-		 *   - We don't want to wait for a ppdone that will never
-		 *     arrive, so verify ongoing TX
-		 *
-		 * 3. Wait for TX to Complete
-		 *  - Wait for PPDone pending count to reach 0
-		 *
-		 * 4. Leave Autorefresh Disabled
-		 *   - Assume disable of Autorefresh since it is now safe
-		 *   - Can now safely Disable Encoder, do debug printing, etc.
-		 *     without worrying that Autorefresh will kickoff
-		 */
+	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
 
-		spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
+	_sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0);
 
-		/* disable external TE to prevent next autorefresh */
-		_sde_encoder_phys_cmd_connect_te(phys_enc, false);
+	/* check for outstanding TX */
+	if (_sde_encoder_phys_cmd_is_ongoing_pptx(phys_enc))
+		atomic_add_unless(&phys_enc->pending_kickoff_cnt, 1, 1);
+	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
 
-		/* verify that we disabled TE during outstanding TX */
-		if (_sde_encoder_phys_cmd_is_ongoing_pptx(phys_enc))
-			atomic_add_unless(&phys_enc->pending_kickoff_cnt, 1, 1);
+	/* wait for ppdone if necessary due to catching ongoing TX */
+	if (_sde_encoder_phys_cmd_wait_for_idle(phys_enc))
+		SDE_ERROR_CMDENC(cmd_enc, "pp:%d kickoff timed out\n",
+				phys_enc->hw_pp->idx - PINGPONG_0);
 
-		spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
-
-		/* wait for ppdone if necessary due to catching ongoing TX */
-		if (_sde_encoder_phys_cmd_wait_for_idle(phys_enc))
-			SDE_ERROR_CMDENC(cmd_enc,
-					"pp:%d kickoff timed out\n",
-					phys_enc->hw_pp->idx - PINGPONG_0);
-
-		/*
-		 * not strictly necessary for kickoff, but simplifies disable
-		 * callflow since our disable is split across multiple phys_encs
-		 */
-		_sde_encoder_phys_cmd_config_autorefresh(phys_enc, 0);
-
-		SDE_DEBUG_CMDENC(cmd_enc, "disabled autorefresh & ext TE\n");
-
-	}
+	SDE_DEBUG_CMDENC(cmd_enc, "disabled autorefresh\n");
 }
 
 static void sde_encoder_phys_cmd_handle_post_kickoff(
@@ -1200,13 +1223,16 @@
 	ops->wait_for_commit_done = sde_encoder_phys_cmd_wait_for_commit_done;
 	ops->prepare_for_kickoff = sde_encoder_phys_cmd_prepare_for_kickoff;
 	ops->wait_for_tx_complete = sde_encoder_phys_cmd_wait_for_tx_complete;
-	ops->handle_post_kickoff = sde_encoder_phys_cmd_handle_post_kickoff;
+	ops->wait_for_vblank = sde_encoder_phys_cmd_wait_for_vblank;
 	ops->trigger_start = sde_encoder_phys_cmd_trigger_start;
 	ops->needs_single_flush = sde_encoder_phys_cmd_needs_single_flush;
 	ops->hw_reset = sde_encoder_helper_hw_reset;
 	ops->irq_control = sde_encoder_phys_cmd_irq_control;
 	ops->update_split_role = sde_encoder_phys_cmd_update_split_role;
 	ops->restore = sde_encoder_phys_cmd_enable_helper;
+	ops->is_autorefresh_enabled =
+			sde_encoder_phys_cmd_is_autorefresh_enabled;
+	ops->handle_post_kickoff = sde_encoder_phys_cmd_handle_post_kickoff;
 }
 
 struct sde_encoder_phys *sde_encoder_phys_cmd_init(
@@ -1290,7 +1316,9 @@
 	atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
 	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
 	atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
+	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
 	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
+	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
 	atomic_set(&cmd_enc->autorefresh.kickoff_cnt, 0);
 	init_waitqueue_head(&cmd_enc->autorefresh.kickoff_wq);
 
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 933e4812..7850cb7 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -657,7 +657,7 @@
 	hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO;
 }
 
-static int sde_encoder_phys_vid_wait_for_vblank(
+static int _sde_encoder_phys_vid_wait_for_vblank(
 		struct sde_encoder_phys *phys_enc, bool notify)
 {
 	struct sde_encoder_wait_info wait_info;
@@ -696,10 +696,10 @@
 	return ret;
 }
 
-static int sde_encoder_phys_vid_wait_for_commit_done(
+static int sde_encoder_phys_vid_wait_for_vblank(
 		struct sde_encoder_phys *phys_enc)
 {
-	return sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
+	return _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
 }
 
 static void sde_encoder_phys_vid_prepare_for_kickoff(
@@ -781,7 +781,7 @@
 	 * scanout buffer) don't latch properly..
 	 */
 	if (sde_encoder_phys_vid_is_master(phys_enc)) {
-		ret = sde_encoder_phys_vid_wait_for_vblank(phys_enc, false);
+		ret = _sde_encoder_phys_vid_wait_for_vblank(phys_enc, false);
 		if (ret) {
 			atomic_set(&phys_enc->pending_kickoff_cnt, 0);
 			SDE_ERROR_VIDENC(vid_enc,
@@ -866,7 +866,9 @@
 	ops->destroy = sde_encoder_phys_vid_destroy;
 	ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources;
 	ops->control_vblank_irq = sde_encoder_phys_vid_control_vblank_irq;
-	ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_commit_done;
+	ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_vblank;
+	ops->wait_for_vblank = sde_encoder_phys_vid_wait_for_vblank;
+	ops->wait_for_tx_complete = sde_encoder_phys_vid_wait_for_vblank;
 	ops->prepare_for_kickoff = sde_encoder_phys_vid_prepare_for_kickoff;
 	ops->handle_post_kickoff = sde_encoder_phys_vid_handle_post_kickoff;
 	ops->needs_single_flush = sde_encoder_phys_vid_needs_single_flush;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index c95fb47..2b736e5 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -918,10 +918,12 @@
  * @pixel_format:	DRM pixel format
  * @width:		Desired fb width
  * @height:		Desired fb height
+ * @pitch:		Desired fb pitch
  */
 static int _sde_encoder_phys_wb_init_internal_fb(
 		struct sde_encoder_phys_wb *wb_enc,
-		uint32_t pixel_format, uint32_t width, uint32_t height)
+		uint32_t pixel_format, uint32_t width,
+		uint32_t height, uint32_t pitch)
 {
 	struct drm_device *dev;
 	struct drm_framebuffer *fb;
@@ -951,9 +953,11 @@
 	mode_cmd.pixel_format = pixel_format;
 	mode_cmd.width = width;
 	mode_cmd.height = height;
+	mode_cmd.pitches[0] = pitch;
 
 	size = sde_format_get_framebuffer_size(pixel_format,
-			mode_cmd.width, mode_cmd.height, 0, 0);
+			mode_cmd.width, mode_cmd.height,
+			mode_cmd.pitches, NULL, 0);
 	if (!size) {
 		SDE_DEBUG("not creating zero size buffer\n");
 		return -EINVAL;
@@ -1314,7 +1318,7 @@
 
 	/* create internal buffer for disable logic */
 	if (_sde_encoder_phys_wb_init_internal_fb(wb_enc,
-				DRM_FORMAT_RGB888, 2, 1)) {
+				DRM_FORMAT_RGB888, 2, 1, 6)) {
 		SDE_ERROR("failed to init internal fb\n");
 		goto fail_wb_init;
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index 04c9e79..3acf4c9 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -701,7 +701,8 @@
 		const struct sde_format *fmt,
 		const uint32_t width,
 		const uint32_t height,
-		struct sde_hw_fmt_layout *layout)
+		struct sde_hw_fmt_layout *layout,
+		const uint32_t *pitches)
 {
 	int i;
 
@@ -751,6 +752,17 @@
 		}
 	}
 
+	/*
+	 * linear format: allow user allocated pitches if they are greater than
+	 * the requirement.
+	 * ubwc format: pitch values are computed uniformly across
+	 * all the components based on ubwc specifications.
+	 */
+	for (i = 0; i < layout->num_planes && i < SDE_MAX_PLANES; ++i) {
+		if (pitches && layout->plane_pitch[i] < pitches[i])
+			layout->plane_pitch[i] = pitches[i];
+	}
+
 	for (i = 0; i < SDE_MAX_PLANES; i++)
 		layout->total_size += layout->plane_size[i];
 
@@ -761,7 +773,8 @@
 		const struct sde_format *fmt,
 		const uint32_t w,
 		const uint32_t h,
-		struct sde_hw_fmt_layout *layout)
+		struct sde_hw_fmt_layout *layout,
+		const uint32_t *pitches)
 {
 	if (!layout || !fmt) {
 		DRM_ERROR("invalid pointer\n");
@@ -776,7 +789,7 @@
 	if (SDE_FORMAT_IS_UBWC(fmt) || SDE_FORMAT_IS_TILE(fmt))
 		return _sde_format_get_plane_sizes_ubwc(fmt, w, h, layout);
 
-	return _sde_format_get_plane_sizes_linear(fmt, w, h, layout);
+	return _sde_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
 }
 
 int sde_format_get_block_size(const struct sde_format *fmt,
@@ -801,6 +814,7 @@
 		const uint32_t format,
 		const uint32_t width,
 		const uint32_t height,
+		const uint32_t *pitches,
 		const uint64_t *modifiers,
 		const uint32_t modifiers_len)
 {
@@ -811,7 +825,10 @@
 	if (!fmt)
 		return 0;
 
-	if (sde_format_get_plane_sizes(fmt, width, height, &layout))
+	if (!pitches)
+		return -EINVAL;
+
+	if (sde_format_get_plane_sizes(fmt, width, height, &layout, pitches))
 		layout.total_size = 0;
 
 	return layout.total_size;
@@ -917,7 +934,7 @@
 
 	/* Can now check the pitches given vs pitches expected */
 	for (i = 0; i < layout->num_planes; ++i) {
-		if (layout->plane_pitch[i] != fb->pitches[i]) {
+		if (layout->plane_pitch[i] > fb->pitches[i]) {
 			DRM_ERROR("plane %u expected pitch %u, fb %u\n",
 				i, layout->plane_pitch[i], fb->pitches[i]);
 			return -EINVAL;
@@ -959,7 +976,7 @@
 
 	/* Populate the plane sizes etc via get_format */
 	ret = sde_format_get_plane_sizes(layout->format, fb->width, fb->height,
-			layout);
+			layout, fb->pitches);
 	if (ret)
 		return ret;
 
@@ -1063,7 +1080,7 @@
 	num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);
 
 	ret = sde_format_get_plane_sizes(fmt, cmd->width, cmd->height,
-			&layout);
+			&layout, cmd->pitches);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.h b/drivers/gpu/drm/msm/sde/sde_formats.h
index 2333a72..58065ab 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.h
+++ b/drivers/gpu/drm/msm/sde/sde_formats.h
@@ -64,6 +64,8 @@
  * @w:               width of the buffer
  * @h:               height of the buffer
  * @layout:          layout of the buffer
+ * @pitches:         array of size [SDE_MAX_PLANES] to populate
+ *		     pitch for each plane
  *
  * Return: size of the buffer
  */
@@ -71,7 +73,8 @@
 		const struct sde_format *fmt,
 		const uint32_t w,
 		const uint32_t h,
-		struct sde_hw_fmt_layout *layout);
+		struct sde_hw_fmt_layout *layout,
+		const uint32_t *pitches);
 
 /**
  * sde_format_get_block_size - get block size of given format when
@@ -137,6 +140,8 @@
  * @format:            DRM pixel format
  * @width:             pixel width
  * @height:            pixel height
+ * @pitches:           array of size [SDE_MAX_PLANES] to populate
+ *		       pitch for each plane
  * @modifiers:         array to populate with drm modifiers, can be NULL
  * @modifiers_len:     length of modifers array
  *
@@ -146,6 +151,7 @@
 		const uint32_t format,
 		const uint32_t width,
 		const uint32_t height,
+		const uint32_t *pitches,
 		const uint64_t *modifiers,
 		const uint32_t modifiers_len);
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.c b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
index bbd5931..07628a17 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
@@ -62,6 +62,16 @@
 }
 
 /**
+ * _sde_hw_rot_reg_dump - perform register dump
+ * @ptr: private pointer to rotator platform device
+ * return: None
+ */
+static void _sde_hw_rot_reg_dump(void *ptr)
+{
+	sde_rotator_inline_reg_dump((struct platform_device *) ptr);
+}
+
+/**
  * sde_hw_rot_start - start rotator before any commit
  * @hw: Pointer to rotator hardware driver
  * return: 0 if success; error code otherwise
@@ -78,6 +88,10 @@
 
 	pdev = hw->caps->pdev;
 
+	rc = sde_dbg_reg_register_cb(hw->name, _sde_hw_rot_reg_dump, pdev);
+	if (rc)
+		SDE_ERROR("failed to register debug dump %d\n", rc);
+
 	hw->rot_ctx = sde_rotator_inline_open(pdev);
 	if (IS_ERR_OR_NULL(hw->rot_ctx)) {
 		rc = PTR_ERR(hw->rot_ctx);
@@ -95,13 +109,16 @@
  */
 static void sde_hw_rot_stop(struct sde_hw_rot *hw)
 {
-	if (!hw) {
+	if (!hw || !hw->caps || !hw->caps->pdev) {
 		SDE_ERROR("invalid parameter\n");
 		return;
 	}
 
 	sde_rotator_inline_release(hw->rot_ctx);
 	hw->rot_ctx = NULL;
+
+	sde_dbg_reg_unregister_cb(hw->name, _sde_hw_rot_reg_dump,
+			hw->caps->pdev);
 }
 
 /**
@@ -576,6 +593,7 @@
 		return -EINVAL;
 	}
 
+	rot_cmd.sequence_id = data->sequence_id;
 	rot_cmd.video_mode = data->video_mode;
 	rot_cmd.fps = data->fps;
 
@@ -899,6 +917,7 @@
 	c->idx = idx;
 	c->caps = cfg;
 	_setup_rot_ops(&c->ops, c->caps->features);
+	snprintf(c->name, ARRAY_SIZE(c->name), "sde_rot_%d", idx - ROT_0);
 
 	rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_ROT, idx, &sde_hw_rot_ops);
 	if (rc) {
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.h b/drivers/gpu/drm/msm/sde/sde_hw_rot.h
index e490052..1237858 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.h
@@ -18,6 +18,8 @@
 #include "sde_hw_util.h"
 #include "sde_hw_blk.h"
 
+#define SDE_HW_ROT_NAME_SIZE	80
+
 struct sde_hw_rot;
 
 /**
@@ -137,6 +139,7 @@
 struct sde_hw_rot {
 	struct sde_hw_blk base;
 	struct sde_hw_blk_reg_map hw;
+	char name[SDE_HW_ROT_NAME_SIZE];
 	int idx;
 	const struct sde_rot_cfg *caps;
 	struct sde_hw_rot_ops ops;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 85af820..d8cd75a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -316,6 +316,7 @@
 	u32 chroma_samp, unpack, src_format;
 	u32 secure = 0, secure_bit_mask;
 	u32 opmode = 0;
+	u32 fast_clear = 0;
 	u32 op_mode_off, unpack_pat_off, format_off;
 	u32 idx;
 
@@ -385,10 +386,12 @@
 		SDE_REG_WRITE(c, SSPP_FETCH_CONFIG,
 			SDE_FETCH_CONFIG_RESET_VALUE |
 			ctx->mdp->highest_bank_bit << 18);
-		if (IS_UBWC_20_SUPPORTED(ctx->catalog->ubwc_version))
+		if (IS_UBWC_20_SUPPORTED(ctx->catalog->ubwc_version)) {
+			fast_clear = fmt->alpha_enable ? BIT(31) : 0;
 			SDE_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
-					BIT(31) | (ctx->mdp->ubwc_swizzle) |
+					fast_clear | (ctx->mdp->ubwc_swizzle) |
 					(ctx->mdp->highest_bank_bit << 4));
+		}
 	}
 
 	opmode |= MDSS_MDP_OP_PE_OVERRIDE;
@@ -768,6 +771,16 @@
 	SDE_REG_WRITE(&ctx->hw, QSEED3_OP_MODE + idx, op_mode);
 }
 
+static u32 _sde_hw_sspp_get_scaler3_ver(struct sde_hw_pipe *ctx)
+{
+	u32 idx;
+
+	if (!ctx || _sspp_subblk_offset(ctx, SDE_SSPP_SCALER_QSEED3, &idx))
+		return 0;
+
+	return SDE_REG_READ(&ctx->hw, QSEED3_HW_VERSION + idx);
+}
+
 /**
  * sde_hw_sspp_setup_rects()
  */
@@ -1167,8 +1180,10 @@
 	if (sde_hw_sspp_multirect_enabled(c->cap))
 		c->ops.setup_multirect = sde_hw_sspp_setup_multirect;
 
-	if (test_bit(SDE_SSPP_SCALER_QSEED3, &features))
+	if (test_bit(SDE_SSPP_SCALER_QSEED3, &features)) {
 		c->ops.setup_scaler = _sde_hw_sspp_setup_scaler3;
+		c->ops.get_scaler_ver = _sde_hw_sspp_get_scaler3_ver;
+	}
 
 	if (test_bit(SDE_SSPP_HSIC, &features)) {
 		/* TODO: add version based assignment here as inline or macro */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index 8d14715..c19eb5c 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
@@ -575,6 +575,12 @@
 		void *scaler_cfg);
 
 	/**
+	 * get_scaler_ver - get scaler h/w version
+	 * @ctx: Pointer to pipe context
+	 */
+	u32 (*get_scaler_ver)(struct sde_hw_pipe *ctx);
+
+	/**
 	 * setup_sys_cache - setup system cache configuration
 	 * @ctx: Pointer to pipe context
 	 * @cfg: Pointer to system cache configuration
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_vbif.c b/drivers/gpu/drm/msm/sde/sde_hw_vbif.c
index b5c273a..90a2ca9 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_vbif.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_vbif.c
@@ -22,7 +22,7 @@
 #define VBIF_QOS_REMAP_01		0x0024
 #define VBIF_QOS_REMAP_10		0x0028
 #define VBIF_QOS_REMAP_11		0x002C
-#define VBIF_WRITE_GATHTER_EN		0x00AC
+#define VBIF_WRITE_GATHER_EN		0x00AC
 #define VBIF_IN_RD_LIM_CONF0		0x00B0
 #define VBIF_IN_RD_LIM_CONF1		0x00B4
 #define VBIF_IN_RD_LIM_CONF2		0x00B8
@@ -33,11 +33,34 @@
 #define VBIF_OUT_WR_LIM_CONF0		0x00D4
 #define VBIF_OUT_AXI_AMEMTYPE_CONF0	0x0160
 #define VBIF_OUT_AXI_AMEMTYPE_CONF1	0x0164
+#define VBIF_XIN_PND_ERR		0x0190
+#define VBIF_XIN_SRC_ERR		0x0194
+#define VBIF_XIN_CLR_ERR		0x019C
 #define VBIF_XIN_HALT_CTRL0		0x0200
 #define VBIF_XIN_HALT_CTRL1		0x0204
 #define VBIF_XINL_QOS_RP_REMAP_000	0x0550
 #define VBIF_XINL_QOS_LVL_REMAP_000	0x0590
 
+static void sde_hw_clear_errors(struct sde_hw_vbif *vbif,
+		u32 *pnd_errors, u32 *src_errors)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 pnd, src;
+
+	if (!vbif)
+		return;
+	c = &vbif->hw;
+	pnd = SDE_REG_READ(c, VBIF_XIN_PND_ERR);
+	src = SDE_REG_READ(c, VBIF_XIN_SRC_ERR);
+
+	if (pnd_errors)
+		*pnd_errors = pnd;
+	if (src_errors)
+		*src_errors = src;
+
+	SDE_REG_WRITE(c, VBIF_XIN_CLR_ERR, pnd | src);
+}
+
 static void sde_hw_set_mem_type(struct sde_hw_vbif *vbif,
 		u32 xin_id, u32 value)
 {
@@ -167,6 +190,21 @@
 	SDE_REG_WRITE(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high, reg_val_lvl);
 }
 
+static void sde_hw_set_write_gather_en(struct sde_hw_vbif *vbif, u32 xin_id)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 reg_val;
+
+	if (!vbif || xin_id >= MAX_XIN_COUNT)
+		return;
+
+	c = &vbif->hw;
+
+	reg_val = SDE_REG_READ(c, VBIF_WRITE_GATHER_EN);
+	reg_val |= BIT(xin_id);
+	SDE_REG_WRITE(c, VBIF_WRITE_GATHER_EN, reg_val);
+}
+
 static void _setup_vbif_ops(struct sde_hw_vbif_ops *ops,
 		unsigned long cap)
 {
@@ -177,6 +215,8 @@
 	if (test_bit(SDE_VBIF_QOS_REMAP, &cap))
 		ops->set_qos_remap = sde_hw_set_qos_remap;
 	ops->set_mem_type = sde_hw_set_mem_type;
+	ops->clear_errors = sde_hw_clear_errors;
+	ops->set_write_gather_en = sde_hw_set_write_gather_en;
 }
 
 static const struct sde_vbif_cfg *_top_offset(enum sde_vbif vbif,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_vbif.h b/drivers/gpu/drm/msm/sde/sde_hw_vbif.h
index 80a9e5a..84f0e04 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_vbif.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_vbif.h
@@ -80,6 +80,25 @@
 	 */
 	void (*set_mem_type)(struct sde_hw_vbif *vbif,
 			u32 xin_id, u32 value);
+
+	/**
+	 * clear_errors - clear any vbif errors
+	 *	This function clears any detected pending/source errors
+	 *	on the VBIF interface, and optionally returns the detected
+	 *	error mask(s).
+	 * @vbif: vbif context driver
+	 * @pnd_errors: pointer to pending error reporting variable
+	 * @src_errors: pointer to source error reporting variable
+	 */
+	void (*clear_errors)(struct sde_hw_vbif *vbif,
+		u32 *pnd_errors, u32 *src_errors);
+
+	/**
+	 * set_write_gather_en - set write_gather enable
+	 * @vbif: vbif context driver
+	 * @xin_id: client interface identifier
+	 */
+	void (*set_write_gather_en)(struct sde_hw_vbif *vbif, u32 xin_id);
 };
 
 struct sde_hw_vbif {
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 42af245..8dd6448 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -404,7 +404,7 @@
 
 	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
 
-	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
+	SDE_EVT32_VERBOSE(SDE_EVTLOG_FUNC_EXIT);
 }
 
 static void sde_kms_wait_for_tx_complete(struct msm_kms *kms,
@@ -635,14 +635,16 @@
 		.post_init =  dsi_conn_post_init,
 		.detect =     dsi_conn_detect,
 		.get_modes =  dsi_connector_get_modes,
+		.put_modes =  dsi_connector_put_modes,
 		.mode_valid = dsi_conn_mode_valid,
 		.get_info =   dsi_display_get_info,
 		.set_backlight = dsi_display_set_backlight,
 		.soft_reset   = dsi_display_soft_reset,
 		.pre_kickoff  = dsi_conn_pre_kickoff,
 		.clk_ctrl = dsi_display_clk_ctrl,
-		.get_topology = dsi_conn_get_topology,
-		.get_dst_format = dsi_display_get_dst_format
+		.set_power = dsi_display_set_power,
+		.get_mode_info = dsi_conn_get_mode_info,
+		.get_dst_format = dsi_display_get_dst_format,
 	};
 	static const struct sde_connector_ops wb_ops = {
 		.post_init =    sde_wb_connector_post_init,
@@ -651,7 +653,7 @@
 		.set_property = sde_wb_connector_set_property,
 		.get_info =     sde_wb_get_info,
 		.soft_reset =   NULL,
-		.get_topology = sde_wb_get_topology,
+		.get_mode_info = sde_wb_get_mode_info,
 		.get_dst_format = NULL
 	};
 	static const struct sde_connector_ops dp_ops = {
@@ -660,7 +662,7 @@
 		.get_modes  = dp_connector_get_modes,
 		.mode_valid = dp_connector_mode_valid,
 		.get_info   = dp_connector_get_info,
-		.get_topology   = dp_connector_get_topology,
+		.get_mode_info  = dp_connector_get_mode_info,
 	};
 	struct msm_display_info info;
 	struct drm_encoder *encoder;
@@ -1135,7 +1137,7 @@
 	}
 
 	ret = sde_format_get_plane_sizes(fbo->fmt, fbo->width, fbo->height,
-			&fbo->layout);
+			&fbo->layout, fbo->layout.plane_pitch);
 	if (ret) {
 		SDE_ERROR("failed to get plane sizes\n");
 		goto done;
@@ -1341,6 +1343,70 @@
 	sde_reg_dma_deinit();
 }
 
+int sde_kms_mmu_detach(struct sde_kms *sde_kms, bool secure_only)
+{
+	int i;
+
+	if (!sde_kms)
+		return -EINVAL;
+
+	for (i = 0; i < MSM_SMMU_DOMAIN_MAX; i++) {
+		struct msm_mmu *mmu;
+		struct msm_gem_address_space *aspace = sde_kms->aspace[i];
+
+		if (!aspace)
+			continue;
+
+		mmu = sde_kms->aspace[i]->mmu;
+
+		if (secure_only &&
+			!aspace->mmu->funcs->is_domain_secure(mmu))
+			continue;
+
+		/* cleanup aspace before detaching */
+		msm_gem_aspace_domain_attach_detach_update(aspace, true);
+
+		SDE_DEBUG("Detaching domain:%d\n", i);
+		aspace->mmu->funcs->detach(mmu, (const char **)iommu_ports,
+			ARRAY_SIZE(iommu_ports));
+
+		aspace->domain_attached = false;
+	}
+
+	return 0;
+}
+
+int sde_kms_mmu_attach(struct sde_kms *sde_kms, bool secure_only)
+{
+	int i;
+
+	if (!sde_kms)
+		return -EINVAL;
+
+	for (i = 0; i < MSM_SMMU_DOMAIN_MAX; i++) {
+		struct msm_mmu *mmu;
+		struct msm_gem_address_space *aspace = sde_kms->aspace[i];
+
+		if (!aspace)
+			continue;
+
+		mmu = sde_kms->aspace[i]->mmu;
+
+		if (secure_only &&
+			!aspace->mmu->funcs->is_domain_secure(mmu))
+			continue;
+
+		SDE_DEBUG("Attaching domain:%d\n", i);
+		aspace->mmu->funcs->attach(mmu, (const char **)iommu_ports,
+			ARRAY_SIZE(iommu_ports));
+
+		msm_gem_aspace_domain_attach_detach_update(aspace, false);
+		aspace->domain_attached = true;
+	}
+
+	return 0;
+}
+
 static void sde_kms_destroy(struct msm_kms *kms)
 {
 	struct sde_kms *sde_kms;
@@ -1373,6 +1439,103 @@
 		sde_crtc_cancel_pending_flip(priv->crtcs[i], file);
 }
 
+static int sde_kms_check_secure_transition(struct msm_kms *kms,
+		struct drm_atomic_state *state)
+{
+	struct sde_kms *sde_kms;
+	struct drm_device *dev;
+	struct drm_crtc *crtc;
+	struct drm_crtc *sec_crtc = NULL, *temp_crtc = NULL;
+	struct drm_crtc_state *crtc_state;
+	int secure_crtc_cnt = 0, active_crtc_cnt = 0;
+	int secure_global_crtc_cnt = 0, active_mode_crtc_cnt = 0;
+	int i;
+
+	if (!kms || !state) {
+		return -EINVAL;
+		SDE_ERROR("invalid arguments\n");
+	}
+
+	/* iterate state object for active and secure crtc */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		if (!crtc_state->active)
+			continue;
+		active_crtc_cnt++;
+		if (sde_crtc_get_secure_level(crtc, crtc_state) ==
+				SDE_DRM_SEC_ONLY) {
+			sec_crtc = crtc;
+			secure_crtc_cnt++;
+		}
+	}
+
+	/* bail out from further validation if no secure ctrc */
+	if (!secure_crtc_cnt)
+		return 0;
+
+	if ((secure_crtc_cnt > MAX_ALLOWED_SECURE_CLIENT_CNT) ||
+		(secure_crtc_cnt &&
+		 (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE))) {
+		SDE_ERROR("Secure check failed active:%d, secure:%d\n",
+				active_crtc_cnt, secure_crtc_cnt);
+		return -EPERM;
+	}
+
+	sde_kms = to_sde_kms(kms);
+	dev = sde_kms->dev;
+	/* iterate global list for active and secure crtc */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		if (!crtc->state->active)
+			continue;
+
+		active_mode_crtc_cnt++;
+
+		if (sde_crtc_get_secure_level(crtc, crtc->state) ==
+				SDE_DRM_SEC_ONLY) {
+			secure_global_crtc_cnt++;
+			temp_crtc = crtc;
+		}
+	}
+
+	/**
+	 * if more than one crtc is active fail
+	 * check if the previous and current commit secure
+	 * are same
+	 */
+	if (secure_crtc_cnt && ((active_mode_crtc_cnt > 1) ||
+			(secure_global_crtc_cnt && (temp_crtc != sec_crtc))))
+		SDE_ERROR("Secure check failed active:%d crtc_id:%d\n",
+				active_mode_crtc_cnt, temp_crtc->base.id);
+
+	return 0;
+}
+
+static int sde_kms_atomic_check(struct msm_kms *kms,
+		struct drm_atomic_state *state)
+{
+	struct sde_kms *sde_kms;
+	struct drm_device *dev;
+	int ret;
+
+	if (!kms || !state)
+		return -EINVAL;
+
+	sde_kms = to_sde_kms(kms);
+	dev = sde_kms->dev;
+
+	ret = drm_atomic_helper_check(dev, state);
+	if (ret)
+		return ret;
+	/*
+	 * Check if any secure transition(moving CRTC between secure and
+	 * non-secure state and vice-versa) is allowed or not. when moving
+	 * to secure state, planes with fb_mode set to dir_translated only can
+	 * be staged on the CRTC, and only one CRTC can be active during
+	 * Secure state
+	 */
+	return sde_kms_check_secure_transition(kms, state);
+}
+
 static struct msm_gem_address_space*
 _sde_kms_get_address_space(struct msm_kms *kms,
 		unsigned int domain)
@@ -1393,7 +1556,9 @@
 	if (domain >= MSM_SMMU_DOMAIN_MAX)
 		return NULL;
 
-	return sde_kms->aspace[domain];
+	return (sde_kms->aspace[domain] &&
+			sde_kms->aspace[domain]->domain_attached) ?
+		sde_kms->aspace[domain] : NULL;
 }
 
 static const struct msm_kms_funcs kms_funcs = {
@@ -1413,6 +1578,7 @@
 	.enable_vblank   = sde_kms_enable_vblank,
 	.disable_vblank  = sde_kms_disable_vblank,
 	.check_modified_format = sde_format_check_modified_format,
+	.atomic_check = sde_kms_atomic_check,
 	.get_format      = sde_get_msm_format,
 	.round_pixclk    = sde_kms_round_pixclk,
 	.destroy         = sde_kms_destroy,
@@ -1463,7 +1629,7 @@
 			continue;
 		}
 
-		aspace = msm_gem_smmu_address_space_create(sde_kms->dev->dev,
+		aspace = msm_gem_smmu_address_space_create(sde_kms->dev,
 			mmu, "sde");
 		if (IS_ERR(aspace)) {
 			ret = PTR_ERR(aspace);
@@ -1480,7 +1646,7 @@
 			msm_gem_address_space_destroy(aspace);
 			goto fail;
 		}
-
+		aspace->domain_attached = true;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index d818fdf..4c0699e 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -93,6 +93,15 @@
 /* timeout in frames waiting for frame done */
 #define SDE_FRAME_DONE_TIMEOUT	60
 
+/* max active secure client counts allowed */
+#define MAX_ALLOWED_SECURE_CLIENT_CNT	1
+
+/* max active crtc when secure client is active */
+#define MAX_ALLOWED_CRTC_CNT_DURING_SECURE	1
+
+/* max virtual encoders per secure crtc */
+#define MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC	1
+
 /*
  * struct sde_irq_callback - IRQ callback handlers
  * @list: list to callback
@@ -500,4 +509,13 @@
  */
 void sde_kms_fbo_unreference(struct sde_kms_fbo *fbo);
 
+/**
+ * smmu attach/detach functions
+ * @sde_kms: poiner to sde_kms structure
+ * @secure_only: if true only secure contexts are attached/detached, else
+ * all contexts are attached/detached/
+ */
+int sde_kms_mmu_attach(struct sde_kms *sde_kms, bool secure_only);
+int sde_kms_mmu_detach(struct sde_kms *sde_kms, bool secure_only);
+
 #endif /* __sde_kms_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 90e6caf..8a39a34 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -258,16 +258,16 @@
 				((src_width + 32) * fmt->bpp);
 		} else {
 			/* non NV12 */
-			total_fl = (fixed_buff_size / 2 - hflip_bytes) /
-				((src_width + 32) * fmt->bpp * 2);
+			total_fl = (fixed_buff_size / 2 - hflip_bytes) * 2 /
+				((src_width + 32) * fmt->bpp);
 		}
 	} else {
 		if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
-			total_fl = (fixed_buff_size / 2 - hflip_bytes) /
-				((src_width + 32) * fmt->bpp * 2);
+			total_fl = (fixed_buff_size / 2 - hflip_bytes) * 2 /
+				((src_width + 32) * fmt->bpp);
 		} else {
-			total_fl = (fixed_buff_size - hflip_bytes) /
-				((src_width + 32) * fmt->bpp * 2);
+			total_fl = (fixed_buff_size - hflip_bytes) * 2 /
+				((src_width + 32) * fmt->bpp);
 		}
 	}
 
@@ -675,7 +675,7 @@
 
 	SDE_DEBUG("plane%d size:%llu time:%llu\n",
 			plane->base.id, cfg.size, cfg.time);
-	SDE_EVT32(DRMID(plane), cfg.size, cfg.time);
+	SDE_EVT32_VERBOSE(DRMID(plane), cfg.size, cfg.time);
 	psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
 			pstate->multirect_index);
 }
@@ -925,7 +925,7 @@
 	else if (ret)
 		SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
 	else if (psde->pipe_hw->ops.setup_sourceaddress) {
-		SDE_EVT32(psde->pipe_hw->idx,
+		SDE_EVT32_VERBOSE(psde->pipe_hw->idx,
 				pipe_cfg->layout.width,
 				pipe_cfg->layout.height,
 				pipe_cfg->layout.plane_addr[0],
@@ -1753,7 +1753,7 @@
 			drm_rect_height(&rstate->out_rot_rect) >> 16,
 			rstate->out_rot_rect.x1 >> 16,
 			rstate->out_rot_rect.y1 >> 16);
-	SDE_EVT32_VERBOSE(DRMID(plane), rstate->sequence_id,
+	SDE_EVT32(DRMID(plane), rstate->sequence_id,
 			rstate->out_xpos, rstate->nplane,
 			in_rot->x1 >> 16, in_rot->y1 >> 16,
 			drm_rect_width(in_rot) >> 16,
@@ -2222,6 +2222,8 @@
 			SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
 					plane->base.id, rstate->sequence_id,
 					state->fb ? state->fb->base.id : -1);
+			SDE_EVT32(DRMID(plane), rstate->sequence_id,
+					SDE_EVTLOG_ERROR);
 			return -EINVAL;
 		}
 
@@ -2256,6 +2258,11 @@
 		if (ret)
 			return ret;
 
+		if (rstate->nplane != old_rstate->nplane ||
+				rstate->out_xpos != old_rstate->out_xpos)
+			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
+				SDE_PLANE_DIRTY_RECTS;
+
 		/* check if stream buffer is already attached to rotator */
 		_sde_plane_rot_get_fb(plane, cstate, rstate);
 
@@ -2353,16 +2360,18 @@
 	sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
 }
 
-/**
- * sde_plane_rot_flush - perform final flush related rotator options
- * @plane: Pointer to drm plane
- * @pstate: Pointer to sde plane state
- */
-static void sde_plane_rot_flush(struct drm_plane *plane,
-		struct sde_plane_state *pstate)
+void sde_plane_kickoff(struct drm_plane *plane)
 {
-	if (!plane || !pstate || !pstate->rot.rot_hw ||
-			!pstate->rot.rot_hw->ops.commit)
+	struct sde_plane_state *pstate;
+
+	if (!plane || !plane->state) {
+		SDE_ERROR("invalid plane\n");
+		return;
+	}
+
+	pstate = to_sde_plane_state(plane->state);
+
+	if (!pstate->rot.rot_hw || !pstate->rot.rot_hw->ops.commit)
 		return;
 
 	pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
@@ -3140,10 +3149,6 @@
 	return ret;
 }
 
-/**
- * sde_plane_flush - final plane operations before commit flush
- * @plane: Pointer to drm plane structure
- */
 void sde_plane_flush(struct drm_plane *plane)
 {
 	struct sde_plane *psde;
@@ -3177,9 +3182,6 @@
 	/* flag h/w flush complete */
 	if (plane->state)
 		pstate->pending = false;
-
-	/* signal inline rotator start */
-	sde_plane_rot_flush(plane, pstate);
 }
 
 static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
@@ -3806,6 +3808,10 @@
 		sde_kms_info_stop(info);
 	}
 
+	if (psde->pipe_hw && psde->pipe_hw->ops.get_scaler_ver)
+		sde_kms_info_add_keyint(info, "scaler_step_ver",
+			psde->pipe_hw->ops.get_scaler_ver(psde->pipe_hw));
+
 	sde_kms_info_add_keyint(info, "max_linewidth",
 			psde->pipe_sblk->maxlinewidth);
 	sde_kms_info_add_keyint(info, "max_upscale",
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index a5599a5..325d342 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -227,6 +227,12 @@
 void sde_plane_flush(struct drm_plane *plane);
 
 /**
+ * sde_plane_kickoff - final plane operations before commit kickoff
+ * @plane: Pointer to drm plane structure
+ */
+void sde_plane_kickoff(struct drm_plane *plane);
+
+/**
  * sde_plane_init - create new sde plane for the given pipe
  * @dev:   Pointer to DRM device
  * @pipe:  sde hardware pipe identifier
diff --git a/drivers/gpu/drm/msm/sde/sde_trace.h b/drivers/gpu/drm/msm/sde/sde_trace.h
index 47fc39b..19cda3e 100644
--- a/drivers/gpu/drm/msm/sde/sde_trace.h
+++ b/drivers/gpu/drm/msm/sde/sde_trace.h
@@ -179,7 +179,7 @@
 			memset(&__entry->data[cnt], 0,
 				(SDE_TRACE_EVTLOG_SIZE - cnt) * sizeof(u32));
 	),
-	TP_printk("%d|%s:%d|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u",
+	TP_printk("%d|%s:%d|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x",
 			__entry->pid, __get_str(evtlog_tag),
 			__entry->tag_id,
 			__entry->data[0], __entry->data[1],
diff --git a/drivers/gpu/drm/msm/sde/sde_vbif.c b/drivers/gpu/drm/msm/sde/sde_vbif.c
index 847572b..7fcd03e 100644
--- a/drivers/gpu/drm/msm/sde/sde_vbif.c
+++ b/drivers/gpu/drm/msm/sde/sde_vbif.c
@@ -184,6 +184,10 @@
 			!vbif->ops.set_halt_ctrl)
 		return;
 
+	/* set write_gather_en for all write clients */
+	if (vbif->ops.set_write_gather_en && !params->rd)
+		vbif->ops.set_write_gather_en(vbif, params->xin_id);
+
 	ot_lim = _sde_vbif_get_ot_limit(vbif, params) & 0xFF;
 
 	if (ot_lim == 0)
@@ -265,6 +269,29 @@
 		mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
 }
 
+void sde_vbif_clear_errors(struct sde_kms *sde_kms)
+{
+	struct sde_hw_vbif *vbif;
+	u32 i, pnd, src;
+
+	if (!sde_kms) {
+		SDE_ERROR("invalid argument\n");
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
+		vbif = sde_kms->hw_vbif[i];
+		if (vbif && vbif->ops.clear_errors) {
+			vbif->ops.clear_errors(vbif, &pnd, &src);
+			if (pnd || src) {
+				SDE_EVT32(i, pnd, src);
+				SDE_DEBUG("VBIF %d: pnd 0x%X, src 0x%X\n",
+						vbif->idx - VBIF_0, pnd, src);
+			}
+		}
+	}
+}
+
 void sde_vbif_init_memtypes(struct sde_kms *sde_kms)
 {
 	struct sde_hw_vbif *vbif;
diff --git a/drivers/gpu/drm/msm/sde/sde_vbif.h b/drivers/gpu/drm/msm/sde/sde_vbif.h
index f1da68b1..a4830a0 100644
--- a/drivers/gpu/drm/msm/sde/sde_vbif.h
+++ b/drivers/gpu/drm/msm/sde/sde_vbif.h
@@ -67,6 +67,12 @@
 		struct sde_vbif_set_qos_params *params);
 
 /**
+ * sde_vbif_clear_errors - clear any vbif errors
+ * @sde_kms:	SDE handler
+ */
+void sde_vbif_clear_errors(struct sde_kms *sde_kms);
+
+/**
  * sde_vbif_init_memtypes - initialize xin memory types for vbif
  * @sde_kms:	SDE handler
  */
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c
index ceda16e..145acea 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_wb.c
@@ -283,28 +283,31 @@
 			wb_dev->wb_cfg->sblk->maxlinewidth :
 			SDE_WB_MODE_MAX_WIDTH;
 	info->max_height = SDE_WB_MODE_MAX_HEIGHT;
-	info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
 	return 0;
 }
 
-int sde_wb_get_topology(const struct drm_display_mode *drm_mode,
-	struct msm_display_topology *topology, u32 max_mixer_width)
+int sde_wb_get_mode_info(const struct drm_display_mode *drm_mode,
+	struct msm_mode_info *mode_info, u32 max_mixer_width)
 {
 	const u32 dual_lm = 2;
 	const u32 single_lm = 1;
 	const u32 single_intf = 1;
 	const u32 no_enc = 0;
+	struct msm_display_topology *topology;
 
-	if (!drm_mode || !topology || !max_mixer_width) {
+	if (!drm_mode || !mode_info || !max_mixer_width) {
 		pr_err("invalid params\n");
 		return -EINVAL;
 	}
 
+	topology = &mode_info->topology;
 	topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ?
 							dual_lm : single_lm;
 	topology->num_enc = no_enc;
 	topology->num_intf = single_intf;
 
+	mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.h b/drivers/gpu/drm/msm/sde/sde_wb.h
index 205ff24..aa57d3e 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.h
+++ b/drivers/gpu/drm/msm/sde/sde_wb.h
@@ -186,15 +186,14 @@
 int sde_wb_get_info(struct msm_display_info *info, void *display);
 
 /**
- * sde_wb_get_topology - retrieve current topology for the mode selected
+ * sde_wb_get_mode_info - retrieve information of the mode selected
  * @drm_mode: Display mode set for the display
- * @topology: Out parameter. Topology for the mode.
+ * @mode_info: Out parameter. information of the mode.
  * @max_mixer_width: max width supported by HW layer mixer
  * Returns: zero on success
  */
-int sde_wb_get_topology(const struct drm_display_mode *drm_mode,
-		struct msm_display_topology *topology,
-		u32 max_mixer_width);
+int sde_wb_get_mode_info(const struct drm_display_mode *drm_mode,
+		struct msm_mode_info *mode_info, u32 max_mixer_width);
 
 /**
  * sde_wb_connector_get_wb - retrieve writeback device of the given connector
diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c
index 58448ca..7e58c2f 100644
--- a/drivers/gpu/drm/msm/sde_dbg.c
+++ b/drivers/gpu/drm/msm/sde_dbg.c
@@ -56,6 +56,8 @@
 #define MMSS_VBIF_TEST_BUS_OUT		0x230
 
 /* Vbif error info */
+#define MMSS_VBIF_PND_ERR		0x190
+#define MMSS_VBIF_SRC_ERR		0x194
 #define MMSS_VBIF_XIN_HALT_CTRL1	0x204
 #define MMSS_VBIF_ERR_INFO		0X1a0
 #define MMSS_VBIF_ERR_INFO_1		0x1a4
@@ -104,6 +106,8 @@
  * @buf: buffer used for manual register dumping
  * @buf_len:  buffer length used for manual register dumping
  * @reg_dump: address for the mem dump if no ranges used
+ * @cb: callback for external dump function, null if not defined
+ * @cb_ptr: private pointer to callback function
  */
 struct sde_dbg_reg_base {
 	struct list_head reg_base_head;
@@ -116,6 +120,8 @@
 	char *buf;
 	size_t buf_len;
 	u32 *reg_dump;
+	void (*cb)(void *ptr);
+	void *cb_ptr;
 };
 
 struct sde_debug_bus_entry {
@@ -2142,16 +2148,17 @@
 	size_t len;
 	struct sde_dbg_reg_range *range_node;
 
-	if (!dbg || !dbg->base) {
+	if (!dbg || !(dbg->base || dbg->cb)) {
 		pr_err("dbg base is null!\n");
 		return;
 	}
 
 	dev_info(sde_dbg_base.dev, "%s:=========%s DUMP=========\n", __func__,
 			dbg->name);
-
+	if (dbg->cb) {
+		dbg->cb(dbg->cb_ptr);
 	/* If there is a list to dump the registers by ranges, use the ranges */
-	if (!list_empty(&dbg->sub_range_list)) {
+	} else if (!list_empty(&dbg->sub_range_list)) {
 		/* sort the list by start address first */
 		list_sort(NULL, &dbg->sub_range_list, _sde_dump_reg_range_cmp);
 		list_for_each_entry(range_node, &dbg->sub_range_list, head) {
@@ -2300,10 +2307,14 @@
 				mem_base + head->wr_addr);
 		wmb(); /* make sure test bits were written */
 
-		if (bus->cmn.flags & DBGBUS_FLAGS_DSPP)
+		if (bus->cmn.flags & DBGBUS_FLAGS_DSPP) {
 			offset = DBGBUS_DSPP_STATUS;
-		else
+			/* keep DSPP test point enabled */
+			if (head->wr_addr != DBGBUS_DSPP)
+				writel_relaxed(0xF, mem_base + DBGBUS_DSPP);
+		} else {
 			offset = head->wr_addr + 0x4;
+		}
 
 		status = readl_relaxed(mem_base + offset);
 
@@ -2325,7 +2336,9 @@
 
 		/* Disable debug bus once we are done */
 		writel_relaxed(0, mem_base + head->wr_addr);
-
+		if (bus->cmn.flags & DBGBUS_FLAGS_DSPP &&
+						head->wr_addr != DBGBUS_DSPP)
+			writel_relaxed(0x0, mem_base + DBGBUS_DSPP);
 	}
 	_sde_dbg_enable_power(false);
 
@@ -2373,7 +2386,7 @@
 	u32 **dump_mem = NULL;
 	u32 *dump_addr = NULL;
 	u32 value, d0, d1;
-	unsigned long reg;
+	unsigned long reg, reg1, reg2;
 	struct vbif_debug_bus_entry *head;
 	phys_addr_t phys = 0;
 	int i, list_size = 0;
@@ -2447,13 +2460,18 @@
 	wmb();
 
 	/**
-	 * Extract VBIF error info based on XIN halt status.
-	 * If the XIN client is not in HALT state, then retrieve the
-	 * VBIF error info for it.
+	 * Extract VBIF error info based on XIN halt and error status.
+	 * If the XIN client is not in HALT state, or an error is detected,
+	 * then retrieve the VBIF error info for it.
 	 */
 	reg = readl_relaxed(mem_base + MMSS_VBIF_XIN_HALT_CTRL1);
-	dev_err(sde_dbg_base.dev, "XIN HALT:0x%lX\n", reg);
+	reg1 = readl_relaxed(mem_base + MMSS_VBIF_PND_ERR);
+	reg2 = readl_relaxed(mem_base + MMSS_VBIF_SRC_ERR);
+	dev_err(sde_dbg_base.dev,
+			"XIN HALT:0x%lX, PND ERR:0x%lX, SRC ERR:0x%lX\n",
+			reg, reg1, reg2);
 	reg >>= 16;
+	reg &= ~(reg1 | reg2);
 	for (i = 0; i < MMSS_VBIF_CLIENT_NUM; i++) {
 		if (!test_bit(0, &reg)) {
 			writel_relaxed(i, mem_base + MMSS_VBIF_ERR_INFO);
@@ -3172,6 +3190,60 @@
 	return 0;
 }
 
+int sde_dbg_reg_register_cb(const char *name, void (*cb)(void *), void *ptr)
+{
+	struct sde_dbg_base *dbg_base = &sde_dbg_base;
+	struct sde_dbg_reg_base *reg_base;
+
+	if (!name || !strlen(name)) {
+		pr_err("no debug name provided\n");
+		return -EINVAL;
+	}
+
+	reg_base = kzalloc(sizeof(*reg_base), GFP_KERNEL);
+	if (!reg_base)
+		return -ENOMEM;
+
+	strlcpy(reg_base->name, name, sizeof(reg_base->name));
+	reg_base->base = NULL;
+	reg_base->max_offset = 0;
+	reg_base->off = 0;
+	reg_base->cnt = DEFAULT_BASE_REG_CNT;
+	reg_base->reg_dump = NULL;
+	reg_base->cb = cb;
+	reg_base->cb_ptr = ptr;
+
+	/* Initialize list to make sure check for null list will be valid */
+	INIT_LIST_HEAD(&reg_base->sub_range_list);
+
+	pr_debug("%s cb: %pK cb_ptr: %pK\n", reg_base->name,
+			reg_base->cb, reg_base->cb_ptr);
+
+	list_add(&reg_base->reg_base_head, &dbg_base->reg_base_list);
+
+	return 0;
+}
+
+void sde_dbg_reg_unregister_cb(const char *name, void (*cb)(void *), void *ptr)
+{
+	struct sde_dbg_base *dbg_base = &sde_dbg_base;
+	struct sde_dbg_reg_base *reg_base;
+
+	if (!dbg_base)
+		return;
+
+	list_for_each_entry(reg_base, &dbg_base->reg_base_list, reg_base_head) {
+		if (strlen(reg_base->name) &&
+			!strcmp(reg_base->name, name)) {
+			pr_debug("%s cb: %pK cb_ptr: %pK\n", reg_base->name,
+					reg_base->cb, reg_base->cb_ptr);
+			list_del(&reg_base->reg_base_head);
+			kfree(reg_base);
+			break;
+		}
+	}
+}
+
 void sde_dbg_reg_register_dump_range(const char *base_name,
 		const char *range_name, u32 offset_start, u32 offset_end,
 		uint32_t xin_id)
diff --git a/drivers/gpu/drm/msm/sde_dbg.h b/drivers/gpu/drm/msm/sde_dbg.h
index e14d60e..a266574 100644
--- a/drivers/gpu/drm/msm/sde_dbg.h
+++ b/drivers/gpu/drm/msm/sde_dbg.h
@@ -25,6 +25,11 @@
 #define SDE_EVTLOG_FUNC_CASE3	0x5555
 #define SDE_EVTLOG_FUNC_CASE4	0x6666
 #define SDE_EVTLOG_FUNC_CASE5	0x7777
+#define SDE_EVTLOG_FUNC_CASE6	0x8888
+#define SDE_EVTLOG_FUNC_CASE7	0x9999
+#define SDE_EVTLOG_FUNC_CASE8	0xaaaa
+#define SDE_EVTLOG_FUNC_CASE9	0xbbbb
+#define SDE_EVTLOG_FUNC_CASE10	0xcccc
 #define SDE_EVTLOG_PANIC	0xdead
 #define SDE_EVTLOG_FATAL	0xbad
 #define SDE_EVTLOG_ERROR	0xebad
@@ -251,6 +256,26 @@
 		size_t max_offset);
 
 /**
+ * sde_dbg_reg_register_cb - register a hw register callback for later
+ *	dumping.
+ * @name:	name of base region
+ * @cb:		callback of external region
+ * @cb_ptr:	private pointer of external region
+ * Returns:	0 or -ERROR
+ */
+int sde_dbg_reg_register_cb(const char *name, void (*cb)(void *), void *ptr);
+
+/**
+ * sde_dbg_reg_unregister_cb - register a hw unregister callback for later
+ *	dumping.
+ * @name:	name of base region
+ * @cb:		callback of external region
+ * @cb_ptr:	private pointer of external region
+ * Returns:	None
+ */
+void sde_dbg_reg_unregister_cb(const char *name, void (*cb)(void *), void *ptr);
+
+/**
  * sde_dbg_reg_register_dump_range - register a hw register sub-region for
  *	later register dumping associated with base specified by
  *	sde_dbg_reg_register_base
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c
index 3c03b92..3d6c2ea 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.c
+++ b/drivers/gpu/drm/msm/sde_edid_parser.c
@@ -571,6 +571,11 @@
 	struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(input);
 	struct edid *edid = edid_ctrl->edid;
 
+	if (!edid) {
+		SDE_ERROR("invalid edid input\n");
+		return 0;
+	}
+
 	if ((edid->revision < 3) || !(edid->input & DRM_EDID_INPUT_DIGITAL))
 		return 0;
 
diff --git a/drivers/gpu/drm/msm/sde_hdcp.h b/drivers/gpu/drm/msm/sde_hdcp.h
new file mode 100644
index 0000000..05d290b
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde_hdcp.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2012, 2014-2017, 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 __SDE_HDCP_H__
+#define __SDE_HDCP_H__
+
+#include <soc/qcom/scm.h>
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include "sde_kms.h"
+
+enum sde_hdcp_client_id {
+	HDCP_CLIENT_HDMI,
+	HDCP_CLIENT_DP,
+};
+
+enum sde_hdcp_states {
+	HDCP_STATE_INACTIVE,
+	HDCP_STATE_AUTHENTICATING,
+	HDCP_STATE_AUTHENTICATED,
+	HDCP_STATE_AUTH_FAIL,
+	HDCP_STATE_AUTH_ENC_NONE,
+	HDCP_STATE_AUTH_ENC_1X,
+	HDCP_STATE_AUTH_ENC_2P2
+};
+
+struct sde_hdcp_init_data {
+	struct dss_io_data *core_io;
+	struct dss_io_data *qfprom_io;
+	struct dss_io_data *hdcp_io;
+	struct drm_dp_aux *drm_aux;
+	struct mutex *mutex;
+	struct workqueue_struct *workq;
+	void *cb_data;
+	void (*notify_status)(void *cb_data, enum sde_hdcp_states status);
+	u8 sink_rx_status;
+	unsigned char *revision;
+	u32 phy_addr;
+	bool sec_access;
+	enum sde_hdcp_client_id client_id;
+};
+
+struct sde_hdcp_ops {
+	int (*isr)(void *ptr);
+	int (*cp_irq)(void *ptr);
+	int (*reauthenticate)(void *input);
+	int (*authenticate)(void *hdcp_ctrl);
+	bool (*feature_supported)(void *input);
+	void (*off)(void *hdcp_ctrl);
+};
+
+void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data);
+void sde_hdcp_1x_deinit(void *input);
+struct sde_hdcp_ops *sde_hdcp_1x_start(void *input);
+void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data);
+void sde_dp_hdcp2p2_deinit(void *input);
+const char *sde_hdcp_state_name(enum sde_hdcp_states hdcp_state);
+struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input);
+#endif /* __SDE_HDCP_H__ */
diff --git a/drivers/gpu/drm/msm/sde_hdcp_1x.c b/drivers/gpu/drm/msm/sde_hdcp_1x.c
new file mode 100644
index 0000000..7951c23
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde_hdcp_1x.c
@@ -0,0 +1,1579 @@
+/* Copyright (c) 2010-2017, 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)	"[sde-hdcp1x] %s: " fmt, __func__
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/iopoll.h>
+#include <linux/hdcp_qseecom.h>
+#include <drm/drm_dp_helper.h>
+#include "sde_hdcp.h"
+#include "hdmi.xml.h"
+#include "video/msm_hdmi_hdcp_mgr.h"
+#include "dp/dp_reg.h"
+
+#define SDE_HDCP_STATE_NAME (sde_hdcp_state_name(hdcp->hdcp_state))
+
+/* QFPROM Registers for HDMI/HDCP */
+#define QFPROM_RAW_FEAT_CONFIG_ROW0_LSB  (0x000000F8)
+#define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB  (0x000000FC)
+#define QFPROM_RAW_VERSION_4             (0x000000A8)
+#define SEC_CTRL_HW_VERSION              (0x00006000)
+#define HDCP_KSV_LSB                     (0x000060D8)
+#define HDCP_KSV_MSB                     (0x000060DC)
+#define HDCP_KSV_VERSION_4_OFFSET        (0x00000014)
+
+/* SEC_CTRL version that supports HDCP SEL */
+#define HDCP_SEL_MIN_SEC_VERSION         (0x50010000)
+
+/* HDCP Keys state based on HDMI_HDCP_LINK0_STATUS:KEYS_STATE */
+#define HDCP_KEYS_STATE_NO_KEYS		0
+#define HDCP_KEYS_STATE_NOT_CHECKED	1
+#define HDCP_KEYS_STATE_CHECKING	2
+#define HDCP_KEYS_STATE_VALID		3
+#define HDCP_KEYS_STATE_AKSV_NOT_VALID	4
+#define HDCP_KEYS_STATE_CHKSUM_MISMATCH	5
+#define HDCP_KEYS_STATE_PROD_AKSV	6
+#define HDCP_KEYS_STATE_RESERVED	7
+
+#define TZ_HDCP_CMD_ID 0x00004401
+
+#define HDCP_INT_CLR (isr->auth_success_ack | isr->auth_fail_ack | \
+			isr->auth_fail_info_ack | isr->tx_req_ack | \
+			isr->encryption_ready_ack | \
+			isr->encryption_not_ready_ack | isr->tx_req_done_ack)
+
+#define HDCP_INT_EN (isr->auth_success_mask | isr->auth_fail_mask | \
+			isr->encryption_ready_mask | \
+			isr->encryption_not_ready_mask)
+
+#define HDCP_POLL_SLEEP_US   (20 * 1000)
+#define HDCP_POLL_TIMEOUT_US (HDCP_POLL_SLEEP_US * 100)
+
+#define sde_hdcp_1x_state(x) (hdcp->hdcp_state == x)
+
+struct sde_hdcp_sink_addr {
+	char *name;
+	u32 addr;
+	u32 len;
+};
+
+struct sde_hdcp_1x_reg_data {
+	u32 reg_id;
+	struct sde_hdcp_sink_addr *sink;
+};
+
+struct sde_hdcp_sink_addr_map {
+	/* addresses to read from sink */
+	struct sde_hdcp_sink_addr bcaps;
+	struct sde_hdcp_sink_addr bksv;
+	struct sde_hdcp_sink_addr r0;
+	struct sde_hdcp_sink_addr bstatus;
+	struct sde_hdcp_sink_addr cp_irq_status;
+	struct sde_hdcp_sink_addr ksv_fifo;
+	struct sde_hdcp_sink_addr v_h0;
+	struct sde_hdcp_sink_addr v_h1;
+	struct sde_hdcp_sink_addr v_h2;
+	struct sde_hdcp_sink_addr v_h3;
+	struct sde_hdcp_sink_addr v_h4;
+
+	/* addresses to write to sink */
+	struct sde_hdcp_sink_addr an;
+	struct sde_hdcp_sink_addr aksv;
+	struct sde_hdcp_sink_addr ainfo;
+};
+
+struct sde_hdcp_int_set {
+	/* interrupt register */
+	u32 int_reg;
+
+	/* interrupt enable/disable masks */
+	u32 auth_success_mask;
+	u32 auth_fail_mask;
+	u32 encryption_ready_mask;
+	u32 encryption_not_ready_mask;
+	u32 tx_req_mask;
+	u32 tx_req_done_mask;
+
+	/* interrupt acknowledgment */
+	u32 auth_success_ack;
+	u32 auth_fail_ack;
+	u32 auth_fail_info_ack;
+	u32 encryption_ready_ack;
+	u32 encryption_not_ready_ack;
+	u32 tx_req_ack;
+	u32 tx_req_done_ack;
+
+	/* interrupt status */
+	u32 auth_success_int;
+	u32 auth_fail_int;
+	u32 encryption_ready;
+	u32 encryption_not_ready;
+	u32 tx_req_int;
+	u32 tx_req_done_int;
+};
+
+struct sde_hdcp_reg_set {
+	u32 status;
+	u32 keys_offset;
+	u32 r0_offset;
+	u32 v_offset;
+	u32 ctrl;
+	u32 aksv_lsb;
+	u32 aksv_msb;
+	u32 entropy_ctrl0;
+	u32 entropy_ctrl1;
+	u32 sec_sha_ctrl;
+	u32 sec_sha_data;
+	u32 sha_status;
+
+	u32 data2_0;
+	u32 data3;
+	u32 data4;
+	u32 data5;
+	u32 data6;
+
+	u32 sec_data0;
+	u32 sec_data1;
+	u32 sec_data7;
+	u32 sec_data8;
+	u32 sec_data9;
+	u32 sec_data10;
+	u32 sec_data11;
+	u32 sec_data12;
+
+	u32 reset;
+	u32 reset_bit;
+
+	u32 repeater;
+};
+
+#define HDCP_REG_SET_CLIENT_HDMI \
+	{0}
+
+#define HDCP_REG_SET_CLIENT_DP \
+{DP_HDCP_STATUS, 16, 14, 13, DP_HDCP_CTRL, \
+	DP_HDCP_SW_LOWER_AKSV, DP_HDCP_SW_UPPER_AKSV, \
+	DP_HDCP_ENTROPY_CTRL0, DP_HDCP_ENTROPY_CTRL1, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA, \
+	DP_HDCP_SHA_STATUS, DP_HDCP_RCVPORT_DATA2_0, \
+	DP_HDCP_RCVPORT_DATA3, DP_HDCP_RCVPORT_DATA4, \
+	DP_HDCP_RCVPORT_DATA5, DP_HDCP_RCVPORT_DATA6, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \
+	HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, \
+	DP_SW_RESET, BIT(1), BIT(1)}
+
+#define HDCP_HDMI_SINK_ADDR_MAP \
+	{{"bcaps", 0x40, 1}, {"bksv", 0x00, 5}, {"r0'", 0x08, 2}, \
+	 {"bstatus", 0x41, 2}, {"??", 0x0, 0}, {"ksv-fifo", 0x43, 0}, \
+	 {"v_h0", 0x20, 4}, {"v_h1", 0x24, 4}, {"v_h2", 0x28, 4}, \
+	 {"v_h3", 0x2c, 4}, {"v_h4", 0x30, 4}, {"an", 0x18, 8}, \
+	 {"aksv", 0x10, 5}, {"ainfo", 0x00, 0},}
+
+#define HDCP_DP_SINK_ADDR_MAP \
+	{{"bcaps", 0x68028, 1}, {"bksv", 0x68000, 5}, {"r0'", 0x68005, 2}, \
+	 {"binfo", 0x6802A, 2}, {"cp_irq_status", 0x68029, 1}, \
+	 {"ksv-fifo", 0x6802C, 0}, {"v_h0", 0x68014, 4}, {"v_h1", 0x68018, 4}, \
+	 {"v_h2", 0x6801C, 4}, {"v_h3", 0x68020, 4}, {"v_h4", 0x68024, 4}, \
+	 {"an", 0x6800C, 8}, {"aksv", 0x68007, 5}, {"ainfo", 0x6803B, 1} }
+
+#define HDCP_HDMI_INT_SET \
+	{0}
+
+#define HDCP_DP_INT_SET \
+	{DP_INTR_STATUS2, \
+	 BIT(17), BIT(20), BIT(24), BIT(27), 0, 0, \
+	 BIT(16), BIT(19), BIT(21), BIT(23), BIT(26), 0, 0, \
+	 BIT(15), BIT(18), BIT(22), BIT(25), 0, 0}
+
+struct sde_hdcp_1x {
+	u8 bcaps;
+	u32 tp_msgid;
+	u32 an_0, an_1, aksv_0, aksv_1;
+	bool sink_r0_ready;
+	bool reauth;
+	bool ksv_ready;
+	enum sde_hdcp_states hdcp_state;
+	struct HDCP_V2V1_MSG_TOPOLOGY cached_tp;
+	struct HDCP_V2V1_MSG_TOPOLOGY current_tp;
+	struct delayed_work hdcp_auth_work;
+	struct completion r0_checked;
+	struct completion sink_r0_available;
+	struct sde_hdcp_init_data init_data;
+	struct sde_hdcp_ops *ops;
+	struct sde_hdcp_reg_set reg_set;
+	struct sde_hdcp_int_set int_set;
+	struct sde_hdcp_sink_addr_map sink_addr;
+	struct workqueue_struct *workq;
+};
+
+const char *sde_hdcp_state_name(enum sde_hdcp_states hdcp_state)
+{
+	switch (hdcp_state) {
+	case HDCP_STATE_INACTIVE:	return "HDCP_STATE_INACTIVE";
+	case HDCP_STATE_AUTHENTICATING:	return "HDCP_STATE_AUTHENTICATING";
+	case HDCP_STATE_AUTHENTICATED:	return "HDCP_STATE_AUTHENTICATED";
+	case HDCP_STATE_AUTH_FAIL:	return "HDCP_STATE_AUTH_FAIL";
+	default:			return "???";
+	}
+}
+
+static int sde_hdcp_1x_count_one(u8 *array, u8 len)
+{
+	int i, j, count = 0;
+
+	for (i = 0; i < len; i++)
+		for (j = 0; j < 8; j++)
+			count += (((array[i] >> j) & 0x1) ? 1 : 0);
+	return count;
+}
+
+static int sde_hdcp_1x_load_keys(void *input)
+{
+	int rc = 0;
+	bool use_sw_keys = false;
+	u32 reg_val;
+	u32 ksv_lsb_addr, ksv_msb_addr;
+	u32 aksv_lsb, aksv_msb;
+	u8 aksv[5];
+	struct dss_io_data *io;
+	struct dss_io_data *qfprom_io;
+	struct sde_hdcp_1x *hdcp = input;
+	struct sde_hdcp_reg_set *reg_set;
+
+	if (!hdcp || !hdcp->init_data.core_io ||
+		!hdcp->init_data.qfprom_io) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_INACTIVE) &&
+	    !sde_hdcp_1x_state(HDCP_STATE_AUTH_FAIL)) {
+		pr_err("%s: invalid state. returning\n",
+			SDE_HDCP_STATE_NAME);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	io = hdcp->init_data.core_io;
+	qfprom_io = hdcp->init_data.qfprom_io;
+	reg_set = &hdcp->reg_set;
+
+	/* On compatible hardware, use SW keys */
+	reg_val = DSS_REG_R(qfprom_io, SEC_CTRL_HW_VERSION);
+	if (reg_val >= HDCP_SEL_MIN_SEC_VERSION) {
+		reg_val = DSS_REG_R(qfprom_io,
+			QFPROM_RAW_FEAT_CONFIG_ROW0_MSB +
+			QFPROM_RAW_VERSION_4);
+
+		if (!(reg_val & BIT(23)))
+			use_sw_keys = true;
+	}
+
+	if (use_sw_keys) {
+		if (hdcp1_set_keys(&aksv_msb, &aksv_lsb)) {
+			pr_err("setting hdcp SW keys failed\n");
+			rc = -EINVAL;
+			goto end;
+		}
+	} else {
+		/* Fetch aksv from QFPROM, this info should be public. */
+		ksv_lsb_addr = HDCP_KSV_LSB;
+		ksv_msb_addr = HDCP_KSV_MSB;
+
+		if (hdcp->init_data.sec_access) {
+			ksv_lsb_addr += HDCP_KSV_VERSION_4_OFFSET;
+			ksv_msb_addr += HDCP_KSV_VERSION_4_OFFSET;
+		}
+
+		aksv_lsb = DSS_REG_R(qfprom_io, ksv_lsb_addr);
+		aksv_msb = DSS_REG_R(qfprom_io, ksv_msb_addr);
+	}
+
+	pr_debug("%s: AKSV=%02x%08x\n", SDE_HDCP_STATE_NAME,
+		aksv_msb, aksv_lsb);
+
+	aksv[0] =  aksv_lsb        & 0xFF;
+	aksv[1] = (aksv_lsb >> 8)  & 0xFF;
+	aksv[2] = (aksv_lsb >> 16) & 0xFF;
+	aksv[3] = (aksv_lsb >> 24) & 0xFF;
+	aksv[4] =  aksv_msb        & 0xFF;
+
+	/* check there are 20 ones in AKSV */
+	if (sde_hdcp_1x_count_one(aksv, 5) != 20) {
+		pr_err("AKSV bit count failed\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	DSS_REG_W(io, reg_set->aksv_lsb, aksv_lsb);
+	DSS_REG_W(io, reg_set->aksv_msb, aksv_msb);
+
+	/* Setup seed values for random number An */
+	DSS_REG_W(io, reg_set->entropy_ctrl0, 0xB1FFB0FF);
+	DSS_REG_W(io, reg_set->entropy_ctrl1, 0xF00DFACE);
+
+	/* make sure hw is programmed */
+	wmb();
+
+	/* enable hdcp engine */
+	DSS_REG_W(io, reg_set->ctrl, 0x1);
+
+	hdcp->hdcp_state = HDCP_STATE_AUTHENTICATING;
+end:
+	return rc;
+}
+
+static int sde_hdcp_1x_read(struct sde_hdcp_1x *hdcp,
+			  struct sde_hdcp_sink_addr *sink,
+			  u8 *buf, bool realign)
+{
+	int const max_size = 15;
+	int rc = 0, read_size = 0, bytes_read = 0;
+
+	if (hdcp->init_data.client_id == HDCP_CLIENT_DP) {
+		int size = sink->len, offset = sink->addr;
+
+		do {
+			read_size = min(size, max_size);
+
+			bytes_read = drm_dp_dpcd_read(hdcp->init_data.drm_aux,
+					offset, buf, read_size);
+			if (bytes_read != read_size) {
+				pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
+					offset, read_size, bytes_read);
+				break;
+			}
+
+			buf += read_size;
+			offset += read_size;
+			size -= read_size;
+		} while (size > 0);
+	}
+
+	return rc;
+}
+
+static int sde_hdcp_1x_write(struct sde_hdcp_1x *hdcp,
+			   struct sde_hdcp_sink_addr *sink, u8 *buf)
+{
+	int const max_size = 16;
+	int rc = 0, write_size = 0, bytes_written = 0;
+
+	if (hdcp->init_data.client_id == HDCP_CLIENT_DP) {
+		int size = sink->len, offset = sink->addr;
+
+		do {
+			write_size = min(size, max_size);
+
+			bytes_written =
+				drm_dp_dpcd_write(hdcp->init_data.drm_aux,
+						offset, buf, write_size);
+			if (bytes_written != write_size) {
+				pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
+					offset, write_size, bytes_written);
+				break;
+			}
+
+			buf += write_size;
+			offset += write_size;
+			size -= write_size;
+		} while (size > 0);
+	}
+
+	return rc;
+}
+
+static void sde_hdcp_1x_enable_interrupts(struct sde_hdcp_1x *hdcp)
+{
+	u32 intr_reg;
+	struct dss_io_data *io;
+	struct sde_hdcp_int_set *isr;
+
+	io = hdcp->init_data.core_io;
+	isr = &hdcp->int_set;
+
+	intr_reg = DSS_REG_R(io, isr->int_reg);
+
+	intr_reg |= HDCP_INT_CLR | HDCP_INT_EN;
+
+	DSS_REG_W(io, isr->int_reg, intr_reg);
+}
+
+static int sde_hdcp_1x_read_bcaps(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+	struct dss_io_data *hdcp_io = hdcp->init_data.hdcp_io;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	rc = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.bcaps,
+		&hdcp->bcaps, false);
+	if (rc) {
+		pr_err("error reading bcaps\n");
+		goto error;
+	}
+
+	pr_debug("bcaps read: 0x%x\n", hdcp->bcaps);
+
+	hdcp->current_tp.ds_type = hdcp->bcaps & reg_set->repeater ?
+			DS_REPEATER : DS_RECEIVER;
+
+	pr_debug("ds: %s\n", hdcp->current_tp.ds_type == DS_REPEATER ?
+			"repeater" : "receiver");
+
+	/* Write BCAPS to the hardware */
+	DSS_REG_W(hdcp_io, reg_set->sec_data12, hdcp->bcaps);
+error:
+	return rc;
+}
+
+static int sde_hdcp_1x_wait_for_hw_ready(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+	u32 link0_status;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+	struct dss_io_data *io = hdcp->init_data.core_io;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	/* Wait for HDCP keys to be checked and validated */
+	rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
+				((link0_status >> reg_set->keys_offset) & 0x7)
+					== HDCP_KEYS_STATE_VALID ||
+				!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+				HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+	if (rc) {
+		pr_err("key not ready\n");
+		goto error;
+	}
+
+	/*
+	 * 1.1_Features turned off by default.
+	 * No need to write AInfo since 1.1_Features is disabled.
+	 */
+	DSS_REG_W(io, reg_set->data4, 0);
+
+	/* Wait for An0 and An1 bit to be ready */
+	rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
+				(link0_status & (BIT(8) | BIT(9))) ||
+				!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+				HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+	if (rc) {
+		pr_err("An not ready\n");
+		goto error;
+	}
+
+	/* As per hardware recommendations, wait before reading An */
+	msleep(20);
+error:
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+		rc = -EINVAL;
+
+	return rc;
+}
+
+static int sde_hdcp_1x_send_an_aksv_to_sink(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+	u8 an[8], aksv[5];
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	an[0] =  hdcp->an_0        & 0xFF;
+	an[1] = (hdcp->an_0 >> 8)  & 0xFF;
+	an[2] = (hdcp->an_0 >> 16) & 0xFF;
+	an[3] = (hdcp->an_0 >> 24) & 0xFF;
+	an[4] =  hdcp->an_1        & 0xFF;
+	an[5] = (hdcp->an_1 >> 8)  & 0xFF;
+	an[6] = (hdcp->an_1 >> 16) & 0xFF;
+	an[7] = (hdcp->an_1 >> 24) & 0xFF;
+
+	pr_debug("an read: 0x%2x%2x%2x%2x%2x%2x%2x%2x\n",
+		an[7], an[6], an[5], an[4], an[3], an[2], an[1], an[0]);
+
+	rc = sde_hdcp_1x_write(hdcp, &hdcp->sink_addr.an, an);
+	if (rc) {
+		pr_err("error writing an to sink\n");
+		goto error;
+	}
+
+	/* Copy An and AKSV to byte arrays for transmission */
+	aksv[0] =  hdcp->aksv_0        & 0xFF;
+	aksv[1] = (hdcp->aksv_0 >> 8)  & 0xFF;
+	aksv[2] = (hdcp->aksv_0 >> 16) & 0xFF;
+	aksv[3] = (hdcp->aksv_0 >> 24) & 0xFF;
+	aksv[4] =  hdcp->aksv_1        & 0xFF;
+
+	pr_debug("aksv read: 0x%2x%2x%2x%2x%2x\n",
+		aksv[4], aksv[3], aksv[2], aksv[1], aksv[0]);
+
+	rc = sde_hdcp_1x_write(hdcp, &hdcp->sink_addr.aksv, aksv);
+	if (rc) {
+		pr_err("error writing aksv to sink\n");
+		goto error;
+	}
+error:
+	return rc;
+}
+
+static int sde_hdcp_1x_read_an_aksv_from_hw(struct sde_hdcp_1x *hdcp)
+{
+	struct dss_io_data *io = hdcp->init_data.core_io;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	hdcp->an_0 = DSS_REG_R(io, reg_set->data5);
+	if (hdcp->init_data.client_id == HDCP_CLIENT_DP) {
+		udelay(1);
+		hdcp->an_0 = DSS_REG_R(io, reg_set->data5);
+	}
+
+	hdcp->an_1 = DSS_REG_R(io, reg_set->data6);
+	if (hdcp->init_data.client_id == HDCP_CLIENT_DP) {
+		udelay(1);
+		hdcp->an_1 = DSS_REG_R(io, reg_set->data6);
+	}
+
+	/* Read AKSV */
+	hdcp->aksv_0 = DSS_REG_R(io, reg_set->data3);
+	hdcp->aksv_1 = DSS_REG_R(io, reg_set->data4);
+
+	return 0;
+}
+
+static int sde_hdcp_1x_get_bksv_from_sink(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+	u8 *bksv = hdcp->current_tp.bksv;
+	u32 link0_bksv_0, link0_bksv_1;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+	struct dss_io_data *hdcp_io  = hdcp->init_data.hdcp_io;
+
+	rc = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.bksv, bksv, false);
+	if (rc) {
+		pr_err("error reading bksv from sink\n");
+		goto error;
+	}
+
+	pr_debug("bksv read: 0x%2x%2x%2x%2x%2x\n",
+		bksv[4], bksv[3], bksv[2], bksv[1], bksv[0]);
+
+	/* check there are 20 ones in BKSV */
+	if (sde_hdcp_1x_count_one(bksv, 5) != 20) {
+		pr_err("%s: BKSV doesn't have 20 1's and 20 0's\n",
+			SDE_HDCP_STATE_NAME);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	link0_bksv_0 = bksv[3];
+	link0_bksv_0 = (link0_bksv_0 << 8) | bksv[2];
+	link0_bksv_0 = (link0_bksv_0 << 8) | bksv[1];
+	link0_bksv_0 = (link0_bksv_0 << 8) | bksv[0];
+	link0_bksv_1 = bksv[4];
+
+	DSS_REG_W(hdcp_io, reg_set->sec_data0, link0_bksv_0);
+	DSS_REG_W(hdcp_io, reg_set->sec_data1, link0_bksv_1);
+error:
+	return rc;
+}
+
+static void sde_hdcp_1x_enable_sink_irq_hpd(struct sde_hdcp_1x *hdcp)
+{
+	u8 const required_major = 1, required_minor = 2;
+	u8 sink_major = 0, sink_minor = 0;
+	u8 enable_hpd_irq = 0x1;
+	int rc;
+	unsigned char revision = *hdcp->init_data.revision;
+
+	sink_major = (revision >> 4) & 0x0f;
+	sink_minor = revision & 0x0f;
+	pr_debug("revision: %d.%d\n", sink_major, sink_minor);
+
+	if ((sink_minor < required_minor) || (sink_major < required_major) ||
+	  (hdcp->current_tp.ds_type != DS_REPEATER)) {
+		pr_debug("sink irq hpd not enabled\n");
+		return;
+	}
+
+	rc = sde_hdcp_1x_write(hdcp, &hdcp->sink_addr.ainfo, &enable_hpd_irq);
+	if (rc)
+		pr_debug("error writing ainfo to sink\n");
+}
+
+static int sde_hdcp_1x_verify_r0(struct sde_hdcp_1x *hdcp)
+{
+	int rc, r0_retry = 3;
+	u8 buf[2];
+	u32 link0_status, timeout_count;
+	u32 const r0_read_delay_us = 1;
+	u32 const r0_read_timeout_us = r0_read_delay_us * 10;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+	struct dss_io_data *io = hdcp->init_data.core_io;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	/* Wait for HDCP R0 computation to be completed */
+	rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
+				(link0_status & BIT(reg_set->r0_offset)) ||
+				!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+				HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+	if (rc) {
+		pr_err("R0 not ready\n");
+		goto error;
+	}
+
+	/*
+	 * HDCP Compliace Test case 1A-01:
+	 * Wait here at least 100ms before reading R0'
+	 */
+	if (hdcp->init_data.client_id == HDCP_CLIENT_HDMI) {
+		msleep(100);
+	} else {
+		if (!hdcp->sink_r0_ready) {
+			reinit_completion(&hdcp->sink_r0_available);
+			timeout_count = wait_for_completion_timeout(
+				&hdcp->sink_r0_available, HZ / 2);
+
+			if (hdcp->reauth) {
+				pr_err("sink R0 not ready\n");
+				rc = -EINVAL;
+				goto error;
+			}
+		}
+	}
+
+	do {
+		memset(buf, 0, sizeof(buf));
+
+		rc = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.r0,
+			buf, false);
+		if (rc) {
+			pr_err("error reading R0' from sink\n");
+			goto error;
+		}
+
+		pr_debug("sink R0'read: %2x%2x\n", buf[1], buf[0]);
+
+		DSS_REG_W(io, reg_set->data2_0, (((u32)buf[1]) << 8) | buf[0]);
+
+		rc = readl_poll_timeout(io->base + reg_set->status,
+			link0_status, (link0_status & BIT(12)) ||
+			!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+			r0_read_delay_us, r0_read_timeout_us);
+	} while (rc && --r0_retry);
+error:
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+		rc = -EINVAL;
+
+	return rc;
+}
+
+static int sde_hdcp_1x_authentication_part1(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	sde_hdcp_1x_enable_interrupts(hdcp);
+
+	rc = sde_hdcp_1x_read_bcaps(hdcp);
+	if (rc)
+		goto error;
+
+	rc = sde_hdcp_1x_wait_for_hw_ready(hdcp);
+	if (rc)
+		goto error;
+
+	rc = sde_hdcp_1x_read_an_aksv_from_hw(hdcp);
+	if (rc)
+		goto error;
+
+	rc = sde_hdcp_1x_get_bksv_from_sink(hdcp);
+	if (rc)
+		goto error;
+
+	rc = sde_hdcp_1x_send_an_aksv_to_sink(hdcp);
+	if (rc)
+		goto error;
+
+	sde_hdcp_1x_enable_sink_irq_hpd(hdcp);
+
+	rc = sde_hdcp_1x_verify_r0(hdcp);
+	if (rc)
+		goto error;
+
+	pr_info("SUCCESSFUL\n");
+
+	return 0;
+error:
+	pr_err("%s: FAILED\n", SDE_HDCP_STATE_NAME);
+
+	return rc;
+}
+
+static int sde_hdcp_1x_transfer_v_h(struct sde_hdcp_1x *hdcp)
+{
+	int rc = 0;
+	struct dss_io_data *io = hdcp->init_data.hdcp_io;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+	struct sde_hdcp_1x_reg_data reg_data[]  = {
+		{reg_set->sec_data7,  &hdcp->sink_addr.v_h0},
+		{reg_set->sec_data8,  &hdcp->sink_addr.v_h1},
+		{reg_set->sec_data9,  &hdcp->sink_addr.v_h2},
+		{reg_set->sec_data10, &hdcp->sink_addr.v_h3},
+		{reg_set->sec_data11, &hdcp->sink_addr.v_h4},
+	};
+	struct sde_hdcp_sink_addr sink = {"V", reg_data->sink->addr};
+	u32 size = ARRAY_SIZE(reg_data);
+	u8 buf[0xFF] = {0};
+	u32 i = 0, len = 0;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i++) {
+		struct sde_hdcp_1x_reg_data *rd = reg_data + i;
+
+		len += rd->sink->len;
+	}
+
+	sink.len = len;
+
+	rc = sde_hdcp_1x_read(hdcp, &sink, buf, false);
+	if (rc) {
+		pr_err("error reading %s\n", sink.name);
+		goto end;
+	}
+
+	for (i = 0; i < size; i++) {
+		struct sde_hdcp_1x_reg_data *rd = reg_data + i;
+		u32 reg_data;
+
+		memcpy(&reg_data, buf + (sizeof(u32) * i), sizeof(u32));
+		DSS_REG_W(io, rd->reg_id, reg_data);
+	}
+end:
+	return rc;
+}
+
+static int sde_hdcp_1x_validate_downstream(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+	u8 buf[2] = {0, 0};
+	u8 device_count, depth;
+	u8 max_cascade_exceeded, max_devs_exceeded;
+	u16 bstatus;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	rc = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.bstatus,
+			buf, false);
+	if (rc) {
+		pr_err("error reading bstatus\n");
+		goto end;
+	}
+
+	bstatus = buf[1];
+	bstatus = (bstatus << 8) | buf[0];
+
+	device_count = bstatus & 0x7F;
+
+	pr_debug("device count %d\n", device_count);
+
+	/* Cascaded repeater depth */
+	depth = (bstatus >> 8) & 0x7;
+	pr_debug("depth %d\n", depth);
+
+	/*
+	 * HDCP Compliance 1B-05:
+	 * Check if no. of devices connected to repeater
+	 * exceed max_devices_connected from bit 7 of Bstatus.
+	 */
+	max_devs_exceeded = (bstatus & BIT(7)) >> 7;
+	if (max_devs_exceeded == 0x01) {
+		pr_err("no. of devs connected exceed max allowed\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	/*
+	 * HDCP Compliance 1B-06:
+	 * Check if no. of cascade connected to repeater
+	 * exceed max_cascade_connected from bit 11 of Bstatus.
+	 */
+	max_cascade_exceeded = (bstatus & BIT(11)) >> 11;
+	if (max_cascade_exceeded == 0x01) {
+		pr_err("no. of cascade connections exceed max allowed\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	/* Update topology information */
+	hdcp->current_tp.dev_count = device_count;
+	hdcp->current_tp.max_cascade_exceeded = max_cascade_exceeded;
+	hdcp->current_tp.max_dev_exceeded = max_devs_exceeded;
+	hdcp->current_tp.depth = depth;
+
+	DSS_REG_W(hdcp->init_data.hdcp_io,
+		  reg_set->sec_data12, hdcp->bcaps | (bstatus << 8));
+end:
+	return rc;
+}
+
+static int sde_hdcp_1x_read_ksv_fifo(struct sde_hdcp_1x *hdcp)
+{
+	u32 ksv_read_retry = 20, ksv_bytes, rc = 0;
+	u8 *ksv_fifo = hdcp->current_tp.ksv_list;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	memset(ksv_fifo, 0, sizeof(hdcp->current_tp.ksv_list));
+
+	/* each KSV is 5 bytes long */
+	ksv_bytes = 5 * hdcp->current_tp.dev_count;
+	hdcp->sink_addr.ksv_fifo.len = ksv_bytes;
+
+	while (ksv_bytes && --ksv_read_retry) {
+		rc = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.ksv_fifo,
+				ksv_fifo, true);
+		if (rc)
+			pr_err("could not read ksv fifo (%d)\n",
+				ksv_read_retry);
+		else
+			break;
+	}
+
+	if (rc)
+		pr_err("error reading ksv_fifo\n");
+
+	return rc;
+}
+
+static int sde_hdcp_1x_write_ksv_fifo(struct sde_hdcp_1x *hdcp)
+{
+	int i, rc = 0;
+	u8 *ksv_fifo = hdcp->current_tp.ksv_list;
+	u32 ksv_bytes = hdcp->sink_addr.ksv_fifo.len;
+	struct dss_io_data *io = hdcp->init_data.core_io;
+	struct dss_io_data *sec_io = hdcp->init_data.hdcp_io;
+	struct sde_hdcp_reg_set *reg_set = &hdcp->reg_set;
+	u32 sha_status = 0, status;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	/* reset SHA Controller */
+	DSS_REG_W(sec_io, reg_set->sec_sha_ctrl, 0x1);
+	DSS_REG_W(sec_io, reg_set->sec_sha_ctrl, 0x0);
+
+	for (i = 0; i < ksv_bytes - 1; i++) {
+		/* Write KSV byte and do not set DONE bit[0] */
+		DSS_REG_W_ND(sec_io, reg_set->sec_sha_data, ksv_fifo[i] << 16);
+
+		/*
+		 * Once 64 bytes have been written, we need to poll for
+		 * HDCP_SHA_BLOCK_DONE before writing any further
+		 */
+		if (i && !((i + 1) % 64)) {
+			rc = readl_poll_timeout(io->base + reg_set->sha_status,
+				sha_status, (sha_status & BIT(0)) ||
+				!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+				HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+			if (rc) {
+				pr_err("block not done\n");
+				goto error;
+			}
+		}
+	}
+
+	/* Write l to DONE bit[0] */
+	DSS_REG_W_ND(sec_io, reg_set->sec_sha_data,
+		(ksv_fifo[ksv_bytes - 1] << 16) | 0x1);
+
+	/* Now wait for HDCP_SHA_COMP_DONE */
+	rc = readl_poll_timeout(io->base + reg_set->sha_status, sha_status,
+				(sha_status & BIT(4)) ||
+				!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+				HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+	if (rc) {
+		pr_err("V computation not done\n");
+		goto error;
+	}
+
+	/* Wait for V_MATCHES */
+	rc = readl_poll_timeout(io->base + reg_set->status, status,
+				(status & BIT(reg_set->v_offset)) ||
+				!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+				HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+	if (rc) {
+		pr_err("V mismatch\n");
+		rc = -EINVAL;
+	}
+error:
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+		rc = -EINVAL;
+
+	return rc;
+}
+
+static int sde_hdcp_1x_wait_for_ksv_ready(struct sde_hdcp_1x *hdcp)
+{
+	int rc, timeout;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Wait until READY bit is set in BCAPS, as per HDCP specifications
+	 * maximum permitted time to check for READY bit is five seconds.
+	 */
+	rc = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.bcaps,
+		&hdcp->bcaps, false);
+	if (rc) {
+		pr_err("error reading bcaps\n");
+		goto error;
+	}
+
+	if (hdcp->init_data.client_id == HDCP_CLIENT_HDMI) {
+		timeout = 50;
+
+		while (!(hdcp->bcaps & BIT(5)) && --timeout) {
+			rc = sde_hdcp_1x_read(hdcp,
+				&hdcp->sink_addr.bcaps,
+				&hdcp->bcaps, false);
+			if (rc ||
+			   !sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+				pr_err("error reading bcaps\n");
+				goto error;
+			}
+			msleep(100);
+		}
+	} else {
+		u8 cp_buf = 0;
+		struct sde_hdcp_sink_addr *sink =
+			&hdcp->sink_addr.cp_irq_status;
+
+		timeout = jiffies_to_msecs(jiffies);
+
+		while (1) {
+			rc = sde_hdcp_1x_read(hdcp, sink, &cp_buf, false);
+			if (rc)
+				goto error;
+
+			if (cp_buf & BIT(0))
+				break;
+
+			/* max timeout of 5 sec as per hdcp 1.x spec */
+			if (abs(timeout - jiffies_to_msecs(jiffies)) > 5000) {
+				timeout = 0;
+				break;
+			}
+
+			if (hdcp->ksv_ready || hdcp->reauth ||
+			    !sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+				break;
+
+			/* re-read after a minimum delay */
+			msleep(20);
+		}
+	}
+
+	if (!timeout || hdcp->reauth ||
+	    !sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("DS KSV not ready\n");
+		rc = -EINVAL;
+	} else {
+		hdcp->ksv_ready = true;
+	}
+error:
+	return rc;
+}
+
+static int sde_hdcp_1x_authentication_part2(struct sde_hdcp_1x *hdcp)
+{
+	int rc;
+	int v_retry = 3;
+
+	rc = sde_hdcp_1x_validate_downstream(hdcp);
+	if (rc)
+		goto error;
+
+	rc = sde_hdcp_1x_read_ksv_fifo(hdcp);
+	if (rc)
+		goto error;
+
+	do {
+		rc = sde_hdcp_1x_transfer_v_h(hdcp);
+		if (rc)
+			goto error;
+
+		/* do not proceed further if no device connected */
+		if (!hdcp->current_tp.dev_count)
+			goto error;
+
+		rc = sde_hdcp_1x_write_ksv_fifo(hdcp);
+	} while (--v_retry && rc);
+error:
+	if (rc) {
+		pr_err("%s: FAILED\n", SDE_HDCP_STATE_NAME);
+	} else {
+		hdcp->hdcp_state = HDCP_STATE_AUTHENTICATED;
+
+		pr_info("SUCCESSFUL\n");
+	}
+
+	return rc;
+}
+
+static void sde_hdcp_1x_cache_topology(struct sde_hdcp_1x *hdcp)
+{
+	if (!hdcp || !hdcp->init_data.core_io) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	memcpy((void *)&hdcp->cached_tp,
+		(void *) &hdcp->current_tp,
+		sizeof(hdcp->cached_tp));
+	hdcp1_cache_repeater_topology((void *)&hdcp->cached_tp);
+}
+
+static void sde_hdcp_1x_notify_topology(void)
+{
+	hdcp1_notify_topology();
+}
+
+static void sde_hdcp_1x_update_auth_status(struct sde_hdcp_1x *hdcp)
+{
+	if (sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATED)) {
+		sde_hdcp_1x_cache_topology(hdcp);
+		sde_hdcp_1x_notify_topology();
+	}
+
+	if (hdcp->init_data.notify_status &&
+	    !sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) {
+		hdcp->init_data.notify_status(
+			hdcp->init_data.cb_data,
+			hdcp->hdcp_state);
+	}
+}
+
+static void sde_hdcp_1x_auth_work(struct work_struct *work)
+{
+	int rc;
+	struct delayed_work *dw = to_delayed_work(work);
+	struct sde_hdcp_1x *hdcp = container_of(dw,
+		struct sde_hdcp_1x, hdcp_auth_work);
+	struct dss_io_data *io;
+
+	if (!hdcp) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+		pr_err("invalid state\n");
+		return;
+	}
+
+	hdcp->sink_r0_ready = false;
+	hdcp->reauth = false;
+	hdcp->ksv_ready = false;
+
+	io = hdcp->init_data.core_io;
+	/* Enabling Software DDC for HDMI and REF timer for DP */
+	if (hdcp->init_data.client_id == HDCP_CLIENT_HDMI)
+		DSS_REG_W_ND(io, REG_HDMI_DDC_ARBITRATION, DSS_REG_R(io,
+				REG_HDMI_DDC_ARBITRATION) & ~(BIT(4)));
+	else if (hdcp->init_data.client_id == HDCP_CLIENT_DP) {
+		DSS_REG_W(io, DP_DP_HPD_REFTIMER, 0x10013);
+	}
+
+	/*
+	 * program hw to enable encryption as soon as
+	 * authentication is successful.
+	 */
+	hdcp1_set_enc(true);
+
+	rc = sde_hdcp_1x_authentication_part1(hdcp);
+	if (rc)
+		goto end;
+
+	if (hdcp->current_tp.ds_type == DS_REPEATER) {
+		rc = sde_hdcp_1x_wait_for_ksv_ready(hdcp);
+		if (rc)
+			goto end;
+	} else {
+		hdcp->hdcp_state = HDCP_STATE_AUTHENTICATED;
+		goto end;
+	}
+
+	hdcp->ksv_ready = false;
+
+	rc = sde_hdcp_1x_authentication_part2(hdcp);
+	if (rc)
+		goto end;
+
+	/*
+	 * Disabling software DDC before going into part3 to make sure
+	 * there is no Arbitration between software and hardware for DDC
+	 */
+	if (hdcp->init_data.client_id == HDCP_CLIENT_HDMI)
+		DSS_REG_W_ND(io, REG_HDMI_DDC_ARBITRATION, DSS_REG_R(io,
+				REG_HDMI_DDC_ARBITRATION) | (BIT(4)));
+end:
+	if (rc && !sde_hdcp_1x_state(HDCP_STATE_INACTIVE))
+		hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL;
+
+	sde_hdcp_1x_update_auth_status(hdcp);
+}
+
+static int sde_hdcp_1x_authenticate(void *input)
+{
+	struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input;
+
+	if (!hdcp) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	flush_delayed_work(&hdcp->hdcp_auth_work);
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	if (!sde_hdcp_1x_load_keys(input)) {
+
+		queue_delayed_work(hdcp->workq,
+			&hdcp->hdcp_auth_work, HZ/2);
+	} else {
+		hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL;
+		sde_hdcp_1x_update_auth_status(hdcp);
+	}
+
+	return 0;
+} /* hdcp_1x_authenticate */
+
+static int sde_hdcp_1x_reauthenticate(void *input)
+{
+	struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input;
+	struct dss_io_data *io;
+	struct sde_hdcp_reg_set *reg_set;
+	struct sde_hdcp_int_set *isr;
+	u32 ret = 0, reg;
+
+	if (!hdcp || !hdcp->init_data.core_io) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	io = hdcp->init_data.core_io;
+	reg_set = &hdcp->reg_set;
+	isr = &hdcp->int_set;
+
+	if (!sde_hdcp_1x_state(HDCP_STATE_AUTH_FAIL)) {
+		pr_err("invalid state\n");
+		return -EINVAL;
+	}
+
+	/* Disable HDCP interrupts */
+	DSS_REG_W(io, isr->int_reg, DSS_REG_R(io, isr->int_reg) & ~HDCP_INT_EN);
+
+	reg = DSS_REG_R(io, reg_set->reset);
+	DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit);
+
+	/* Disable encryption and disable the HDCP block */
+	DSS_REG_W(io, reg_set->ctrl, 0);
+
+	DSS_REG_W(io, reg_set->reset, reg & ~reg_set->reset_bit);
+
+	hdcp->hdcp_state = HDCP_STATE_INACTIVE;
+	sde_hdcp_1x_authenticate(hdcp);
+
+	return ret;
+} /* hdcp_1x_reauthenticate */
+
+static void sde_hdcp_1x_off(void *input)
+{
+	struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input;
+	struct dss_io_data *io;
+	struct sde_hdcp_reg_set *reg_set;
+	struct sde_hdcp_int_set *isr;
+	int rc = 0;
+	u32 reg;
+
+	if (!hdcp || !hdcp->init_data.core_io) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	io = hdcp->init_data.core_io;
+	reg_set = &hdcp->reg_set;
+	isr = &hdcp->int_set;
+
+	if (sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) {
+		pr_err("invalid state\n");
+		return;
+	}
+
+	/*
+	 * Disable HDCP interrupts.
+	 * Also, need to set the state to inactive here so that any ongoing
+	 * reauth works will know that the HDCP session has been turned off.
+	 */
+	mutex_lock(hdcp->init_data.mutex);
+	DSS_REG_W(io, isr->int_reg,
+		DSS_REG_R(io, isr->int_reg) & ~HDCP_INT_EN);
+	hdcp->hdcp_state = HDCP_STATE_INACTIVE;
+	mutex_unlock(hdcp->init_data.mutex);
+
+	/* complete any wait pending */
+	complete_all(&hdcp->sink_r0_available);
+	complete_all(&hdcp->r0_checked);
+	/*
+	 * Cancel any pending auth/reauth attempts.
+	 * If one is ongoing, this will wait for it to finish.
+	 * No more reauthentiaction attempts will be scheduled since we
+	 * set the currect state to inactive.
+	 */
+	rc = cancel_delayed_work_sync(&hdcp->hdcp_auth_work);
+	if (rc)
+		pr_debug("%s: Deleted hdcp auth work\n",
+			SDE_HDCP_STATE_NAME);
+
+	hdcp1_set_enc(false);
+
+	reg = DSS_REG_R(io, reg_set->reset);
+	DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit);
+
+	/* Disable encryption and disable the HDCP block */
+	DSS_REG_W(io, reg_set->ctrl, 0);
+
+	DSS_REG_W(io, reg_set->reset, reg & ~reg_set->reset_bit);
+
+	hdcp->sink_r0_ready = false;
+
+	pr_debug("%s: HDCP: Off\n", SDE_HDCP_STATE_NAME);
+} /* hdcp_1x_off */
+
+static int sde_hdcp_1x_isr(void *input)
+{
+	struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input;
+	int rc = 0;
+	struct dss_io_data *io;
+	u32 hdcp_int_val;
+	struct sde_hdcp_reg_set *reg_set;
+	struct sde_hdcp_int_set *isr;
+
+	if (!hdcp || !hdcp->init_data.core_io) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	io = hdcp->init_data.core_io;
+	reg_set = &hdcp->reg_set;
+	isr = &hdcp->int_set;
+
+	hdcp_int_val = DSS_REG_R(io, isr->int_reg);
+
+	/* Ignore HDCP interrupts if HDCP is disabled */
+	if (sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) {
+		DSS_REG_W(io, isr->int_reg, hdcp_int_val | HDCP_INT_CLR);
+		return 0;
+	}
+
+	if (hdcp_int_val & isr->auth_success_int) {
+		/* AUTH_SUCCESS_INT */
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->auth_success_ack));
+		pr_debug("%s: AUTH SUCCESS\n", SDE_HDCP_STATE_NAME);
+
+		if (sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+			complete_all(&hdcp->r0_checked);
+	}
+
+	if (hdcp_int_val & isr->auth_fail_int) {
+		/* AUTH_FAIL_INT */
+		u32 link_status = DSS_REG_R(io, reg_set->status);
+
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->auth_fail_ack));
+
+		pr_debug("%s: AUTH FAIL, LINK0_STATUS=0x%08x\n",
+			SDE_HDCP_STATE_NAME, link_status);
+
+		if (sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATED)) {
+			hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL;
+			sde_hdcp_1x_update_auth_status(hdcp);
+		} else if (sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATING)) {
+			complete_all(&hdcp->r0_checked);
+		}
+
+		/* Clear AUTH_FAIL_INFO as well */
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->auth_fail_info_ack));
+	}
+
+	if (hdcp_int_val & isr->tx_req_int) {
+		/* DDC_XFER_REQ_INT */
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->tx_req_ack));
+		pr_debug("%s: DDC_XFER_REQ_INT received\n",
+			SDE_HDCP_STATE_NAME);
+	}
+
+	if (hdcp_int_val & isr->tx_req_done_int) {
+		/* DDC_XFER_DONE_INT */
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->tx_req_done_ack));
+		pr_debug("%s: DDC_XFER_DONE received\n",
+			SDE_HDCP_STATE_NAME);
+	}
+
+	if (hdcp_int_val & isr->encryption_ready) {
+		/* Encryption enabled */
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->encryption_ready_ack));
+		pr_debug("%s: encryption ready received\n",
+			SDE_HDCP_STATE_NAME);
+	}
+
+	if (hdcp_int_val & isr->encryption_not_ready) {
+		/* Encryption enabled */
+		DSS_REG_W(io, isr->int_reg,
+			(hdcp_int_val | isr->encryption_not_ready_ack));
+		pr_debug("%s: encryption not ready received\n",
+			SDE_HDCP_STATE_NAME);
+	}
+
+error:
+	return rc;
+}
+
+void sde_hdcp_1x_deinit(void *input)
+{
+	struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input;
+
+	if (!hdcp) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (hdcp->workq)
+		destroy_workqueue(hdcp->workq);
+
+	kfree(hdcp);
+} /* hdcp_1x_deinit */
+
+static void sde_hdcp_1x_update_client_reg_set(struct sde_hdcp_1x *hdcp)
+{
+	if (hdcp->init_data.client_id == HDCP_CLIENT_DP) {
+		struct sde_hdcp_reg_set reg_set = HDCP_REG_SET_CLIENT_DP;
+		struct sde_hdcp_sink_addr_map sink_addr = HDCP_DP_SINK_ADDR_MAP;
+		struct sde_hdcp_int_set isr = HDCP_DP_INT_SET;
+
+		hdcp->reg_set = reg_set;
+		hdcp->sink_addr = sink_addr;
+		hdcp->int_set = isr;
+	}
+}
+
+static bool sde_hdcp_1x_is_cp_irq_raised(struct sde_hdcp_1x *hdcp)
+{
+	int ret;
+	u8 buf = 0;
+	struct sde_hdcp_sink_addr sink = {"irq", 0x201, 1};
+
+	ret = sde_hdcp_1x_read(hdcp, &sink, &buf, false);
+	if (ret)
+		pr_err("error reading irq_vector\n");
+
+	return buf & BIT(2) ? true : false;
+}
+
+static void sde_hdcp_1x_clear_cp_irq(struct sde_hdcp_1x *hdcp)
+{
+	int ret;
+	u8 buf = BIT(2);
+	struct sde_hdcp_sink_addr sink = {"irq", 0x201, 1};
+
+	ret = sde_hdcp_1x_write(hdcp, &sink, &buf);
+	if (ret)
+		pr_err("error clearing irq_vector\n");
+}
+
+static int sde_hdcp_1x_cp_irq(void *input)
+{
+	struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input;
+	u8 buf = 0;
+	int ret;
+
+	if (!hdcp) {
+		pr_err("invalid input\n");
+		goto irq_not_handled;
+	}
+
+	if (!sde_hdcp_1x_is_cp_irq_raised(hdcp)) {
+		pr_debug("cp_irq not raised\n");
+		goto irq_not_handled;
+	}
+
+	ret = sde_hdcp_1x_read(hdcp, &hdcp->sink_addr.cp_irq_status,
+			&buf, false);
+	if (ret) {
+		pr_err("error reading cp_irq_status\n");
+		goto irq_not_handled;
+	}
+
+	if ((buf & BIT(2)) || (buf & BIT(3))) {
+		pr_err("%s\n",
+			buf & BIT(2) ? "LINK_INTEGRITY_FAILURE" :
+				"REAUTHENTICATION_REQUEST");
+
+		hdcp->reauth = true;
+
+		if (!sde_hdcp_1x_state(HDCP_STATE_INACTIVE))
+			hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL;
+
+		complete_all(&hdcp->sink_r0_available);
+		sde_hdcp_1x_update_auth_status(hdcp);
+	} else if (buf & BIT(1)) {
+		pr_debug("R0' AVAILABLE\n");
+		hdcp->sink_r0_ready = true;
+		complete_all(&hdcp->sink_r0_available);
+	} else if ((buf & BIT(0))) {
+		pr_debug("KSVs READY\n");
+
+		hdcp->ksv_ready = true;
+	} else {
+		pr_debug("spurious interrupt\n");
+	}
+
+	sde_hdcp_1x_clear_cp_irq(hdcp);
+	return 0;
+
+irq_not_handled:
+	return -EINVAL;
+}
+
+void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data)
+{
+	struct sde_hdcp_1x *hdcp = NULL;
+	char name[20];
+	static struct sde_hdcp_ops ops = {
+		.isr = sde_hdcp_1x_isr,
+		.cp_irq = sde_hdcp_1x_cp_irq,
+		.reauthenticate = sde_hdcp_1x_reauthenticate,
+		.authenticate = sde_hdcp_1x_authenticate,
+		.off = sde_hdcp_1x_off
+	};
+
+	if (!init_data || !init_data->core_io || !init_data->qfprom_io ||
+		!init_data->mutex || !init_data->notify_status ||
+		!init_data->workq || !init_data->cb_data) {
+		pr_err("invalid input\n");
+		goto error;
+	}
+
+	if (init_data->sec_access && !init_data->hdcp_io) {
+		pr_err("hdcp_io required\n");
+		goto error;
+	}
+
+	hdcp = kzalloc(sizeof(*hdcp), GFP_KERNEL);
+	if (!hdcp)
+		goto error;
+
+	hdcp->init_data = *init_data;
+	hdcp->ops = &ops;
+
+	snprintf(name, sizeof(name), "hdcp_1x_%d",
+		hdcp->init_data.client_id);
+
+	hdcp->workq = create_workqueue(name);
+	if (!hdcp->workq) {
+		pr_err("Error creating workqueue\n");
+		kfree(hdcp);
+		goto error;
+	}
+
+	sde_hdcp_1x_update_client_reg_set(hdcp);
+
+	INIT_DELAYED_WORK(&hdcp->hdcp_auth_work, sde_hdcp_1x_auth_work);
+
+	hdcp->hdcp_state = HDCP_STATE_INACTIVE;
+	init_completion(&hdcp->r0_checked);
+	init_completion(&hdcp->sink_r0_available);
+
+	pr_debug("HDCP module initialized. HDCP_STATE=%s\n",
+		SDE_HDCP_STATE_NAME);
+
+	return (void *)hdcp;
+
+error:
+	return NULL;
+} /* hdcp_1x_init */
+
+struct sde_hdcp_ops *sde_hdcp_1x_start(void *input)
+{
+	return ((struct sde_hdcp_1x *)input)->ops;
+}
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 28a2d4d..e5c83cb 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -76,7 +76,7 @@
 
 	if (phandle->rsc_client)
 		ret = sde_rsc_client_state_update(phandle->rsc_client,
-			rsc_state, NULL, -1);
+			rsc_state, NULL, SDE_RSC_INVALID_CRTC_ID, NULL);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index 78c325d..9cbffa5 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -16,7 +16,7 @@
 
 #define MAX_CLIENT_NAME_LEN 128
 
-#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA	1600000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA	0
 #define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA	0
 #define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA	1600000000
 #define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA	0
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 54bdd42..7a52ece 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -58,12 +58,8 @@
 #define TRY_CLK_MODE_SWITCH		0xFFFE
 #define STATE_UPDATE_NOT_ALLOWED	0xFFFD
 
-/**
- * Expected primary command mode panel vsync ranges
- * Note: update if a primary panel is expected to run lower than 60fps
- */
-#define PRIMARY_VBLANK_MIN_US (18 * 1000)
-#define PRIMARY_VBLANK_MAX_US (20 * 1000)
+/* Primary panel worst case VSYNC expected to be no less than 30fps */
+#define PRIMARY_VBLANK_WORST_CASE_MS 34
 
 static struct sde_rsc_priv *rsc_prv_list[MAX_RSC_COUNT];
 
@@ -153,9 +149,22 @@
 	state = client->current_state;
 	mutex_unlock(&rsc->client_lock);
 
-	if (state != SDE_RSC_IDLE_STATE)
-		sde_rsc_client_state_update(client, SDE_RSC_IDLE_STATE,
-								NULL, -1);
+	if (state != SDE_RSC_IDLE_STATE) {
+		int wait_vblank_crtc_id;
+
+		sde_rsc_client_state_update(client, SDE_RSC_IDLE_STATE, NULL,
+				SDE_RSC_INVALID_CRTC_ID, &wait_vblank_crtc_id);
+
+		/* if vblank wait required at shutdown, use a simple sleep */
+		if (wait_vblank_crtc_id != SDE_RSC_INVALID_CRTC_ID) {
+			pr_err("unexpected sleep required on crtc %d at rsc client destroy\n",
+					wait_vblank_crtc_id);
+			SDE_EVT32(client->id, state, rsc->current_state,
+					client->crtc_id, wait_vblank_crtc_id,
+					SDE_EVTLOG_ERROR);
+			msleep(PRIMARY_VBLANK_WORST_CASE_MS);
+		}
+	}
 	mutex_lock(&rsc->client_lock);
 	list_del_init(&client->list);
 	mutex_unlock(&rsc->client_lock);
@@ -395,7 +404,13 @@
 	/* mode 2 is infinite */
 	rsc->timer_config.rsc_time_slot_2_ns = 0xFFFFFFFF;
 
-	if (rsc->hw_ops.init) {
+	/* timer update should be called with client call */
+	if (cmd_config && rsc->hw_ops.timer_update) {
+		ret = rsc->hw_ops.timer_update(rsc);
+		if (ret)
+			pr_err("sde rsc: hw timer update failed ret:%d\n", ret);
+	/* rsc init should be called during rsc probe - one time only */
+	} else if (rsc->hw_ops.init) {
 		ret = rsc->hw_ops.init(rsc);
 		if (ret)
 			pr_err("sde rsc: hw init failed ret:%d\n", ret);
@@ -449,7 +464,8 @@
 
 static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
 	struct sde_rsc_cmd_config *config,
-	struct sde_rsc_client *caller_client)
+	struct sde_rsc_client *caller_client,
+	int *wait_vblank_crtc_id)
 {
 	struct sde_rsc_client *client;
 	int rc = STATE_UPDATE_NOT_ALLOWED;
@@ -469,9 +485,19 @@
 	if (config)
 		sde_rsc_timer_calculate(rsc, config);
 
+	/**
+	 * rsc clients can still send config at any time. If a config is
+	 * received during cmd_state then vsync_wait will execute with the logic
+	 * below. If a config is received when rsc is in AMC mode; A mode
+	 * switch will do the vsync wait. updated checks still support all cases
+	 * for dynamic mode switch and inline rotation.
+	 */
 	if (rsc->current_state == SDE_RSC_CMD_STATE) {
 		rc = 0;
-		goto vsync_wait;
+		if (config)
+			goto vsync_wait;
+		else
+			goto end;
 	}
 
 	/* any one client in video state blocks the cmd state switch */
@@ -486,15 +512,29 @@
 	}
 
 vsync_wait:
-	/* wait for vsync for vid to cmd state switch and config update */
+	/* indicate wait for vsync for vid to cmd state switch & cfg update */
 	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
-			rsc->current_state == SDE_RSC_CMD_STATE))
-		usleep_range(PRIMARY_VBLANK_MIN_US, PRIMARY_VBLANK_MAX_US);
+			rsc->current_state == SDE_RSC_CMD_STATE)) {
+		/* clear VSYNC timestamp for indication when update completes */
+		if (rsc->hw_ops.hw_vsync)
+			rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, 0, 0);
+		if (!wait_vblank_crtc_id) {
+			pr_err("invalid crtc id wait pointer, client %d\n",
+					caller_client->id);
+			SDE_EVT32(caller_client->id, rsc->current_state,
+					caller_client->crtc_id,
+					wait_vblank_crtc_id, SDE_EVTLOG_ERROR);
+			msleep(PRIMARY_VBLANK_WORST_CASE_MS);
+		} else {
+			*wait_vblank_crtc_id = rsc->primary_client->crtc_id;
+		}
+	}
 end:
 	return rc;
 }
 
-static int sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc)
+static int sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc,
+		int *wait_vblank_crtc_id)
 {
 	struct sde_rsc_client *client;
 	int rc = STATE_UPDATE_NOT_ALLOWED;
@@ -510,17 +550,27 @@
 			rpmh_mode_solver_set(rsc->disp_rsc, false);
 	}
 
-	/* wait for vsync for cmd to clk state switch */
+	/* indicate wait for vsync for cmd to clk state switch */
 	if (!rc && rsc->primary_client &&
-				(rsc->current_state == SDE_RSC_CMD_STATE))
-		usleep_range(PRIMARY_VBLANK_MIN_US, PRIMARY_VBLANK_MAX_US);
+			(rsc->current_state == SDE_RSC_CMD_STATE)) {
+		/* clear VSYNC timestamp for indication when update completes */
+		if (rsc->hw_ops.hw_vsync)
+			rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, 0, 0);
+		if (!wait_vblank_crtc_id) {
+			pr_err("invalid crtc id wait pointer provided\n");
+			msleep(PRIMARY_VBLANK_WORST_CASE_MS);
+		} else {
+			*wait_vblank_crtc_id = rsc->primary_client->crtc_id;
+		}
+	}
 end:
 	return rc;
 }
 
 static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
 	struct sde_rsc_cmd_config *config,
-	struct sde_rsc_client *caller_client)
+	struct sde_rsc_client *caller_client,
+	int *wait_vblank_crtc_id)
 {
 	int rc = 0;
 
@@ -539,16 +589,62 @@
 			rpmh_mode_solver_set(rsc->disp_rsc, false);
 	}
 
-	/* wait for vsync for cmd to vid state switch */
+	/* indicate wait for vsync for cmd to vid state switch */
 	if (!rc && rsc->primary_client &&
-			(rsc->current_state == SDE_RSC_CMD_STATE))
-		usleep_range(PRIMARY_VBLANK_MIN_US, PRIMARY_VBLANK_MAX_US);
+			(rsc->current_state == SDE_RSC_CMD_STATE)) {
+		/* clear VSYNC timestamp for indication when update completes */
+		if (rsc->hw_ops.hw_vsync)
+			rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, 0, 0);
+		if (!wait_vblank_crtc_id) {
+			pr_err("invalid crtc id wait pointer provided\n");
+			msleep(PRIMARY_VBLANK_WORST_CASE_MS);
+		} else {
+			*wait_vblank_crtc_id = rsc->primary_client->crtc_id;
+		}
+	}
 
 end:
 	return rc;
 }
 
 /**
+ * sde_rsc_client_is_state_update_complete() - check if state update is complete
+ * RSC state transition is not complete until HW receives VBLANK signal. This
+ * function checks RSC HW to determine whether that signal has been received.
+ * @client:	 Client pointer provided by sde_rsc_client_create().
+ *
+ * Return: true if the state update has completed.
+ */
+bool sde_rsc_client_is_state_update_complete(
+		struct sde_rsc_client *caller_client)
+{
+	struct sde_rsc_priv *rsc;
+	u32 vsync_timestamp0 = 0;
+
+	if (!caller_client) {
+		pr_err("invalid client for rsc state update\n");
+		return false;
+	} else if (caller_client->rsc_index >= MAX_RSC_COUNT) {
+		pr_err("invalid rsc index\n");
+		return false;
+	}
+
+	rsc = rsc_prv_list[caller_client->rsc_index];
+	if (!rsc)
+		return false;
+
+	/**
+	 * state updates clear VSYNC timestamp, check if a new one arrived.
+	 * use VSYNC mode 0 (CMD TE) always for this, per HW recommendation.
+	 */
+	if (rsc->hw_ops.hw_vsync)
+		vsync_timestamp0 = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ_VSYNC0,
+				NULL, 0, 0);
+
+	return vsync_timestamp0 != 0;
+}
+
+/**
  * sde_rsc_client_state_update() - rsc client state update
  * Video mode, cmd mode and clk state are suppoed as modes. A client need to
  * set this property during panel config time. A switching client can set the
@@ -559,12 +655,18 @@
  * @config:	 fps, vtotal, porches, etc configuration for command mode
  *               panel
  * @crtc_id:	 current client's crtc id
+ * @wait_vblank_crtc_id:	Output parameter. If set to non-zero, rsc hw
+ *				state update requires a wait for one vblank on
+ *				the primary crtc. In that case, this output
+ *				param will be set to the crtc on which to wait.
+ *				If SDE_RSC_INVALID_CRTC_ID, no wait necessary
  *
  * Return: error code.
  */
 int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
 	enum sde_rsc_state state,
-	struct sde_rsc_cmd_config *config, int crtc_id)
+	struct sde_rsc_cmd_config *config, int crtc_id,
+	int *wait_vblank_crtc_id)
 {
 	int rc = 0;
 	struct sde_rsc_priv *rsc;
@@ -581,8 +683,11 @@
 	if (!rsc)
 		return -EINVAL;
 
+	if (wait_vblank_crtc_id)
+		*wait_vblank_crtc_id = SDE_RSC_INVALID_CRTC_ID;
+
 	mutex_lock(&rsc->client_lock);
-	SDE_EVT32(caller_client->id, caller_client->current_state,
+	SDE_EVT32_VERBOSE(caller_client->id, caller_client->current_state,
 			state, rsc->current_state, SDE_EVTLOG_FUNC_ENTRY);
 	caller_client->crtc_id = crtc_id;
 	caller_client->current_state = state;
@@ -610,28 +715,31 @@
 		/* video state client might be exiting; try cmd state switch */
 		if (rc == TRY_CMD_MODE_SWITCH) {
 			rc = sde_rsc_switch_to_cmd(rsc, NULL,
-							rsc->primary_client);
+					rsc->primary_client,
+					wait_vblank_crtc_id);
 			if (!rc)
 				state = SDE_RSC_CMD_STATE;
 
 		/* cmd state client might be exiting; try clk state switch */
 		} else if (rc == TRY_CLK_MODE_SWITCH) {
-			rc = sde_rsc_switch_to_clk(rsc);
+			rc = sde_rsc_switch_to_clk(rsc, wait_vblank_crtc_id);
 			if (!rc)
 				state = SDE_RSC_CLK_STATE;
 		}
 		break;
 
 	case SDE_RSC_CMD_STATE:
-		rc = sde_rsc_switch_to_cmd(rsc, config, caller_client);
+		rc = sde_rsc_switch_to_cmd(rsc, config, caller_client,
+				wait_vblank_crtc_id);
 		break;
 
 	case SDE_RSC_VID_STATE:
-		rc = sde_rsc_switch_to_vid(rsc, config, caller_client);
+		rc = sde_rsc_switch_to_vid(rsc, config, caller_client,
+				wait_vblank_crtc_id);
 		break;
 
 	case SDE_RSC_CLK_STATE:
-		rc = sde_rsc_switch_to_clk(rsc);
+		rc = sde_rsc_switch_to_clk(rsc, wait_vblank_crtc_id);
 		break;
 
 	default:
@@ -815,7 +923,7 @@
 
 end:
 	mutex_unlock(&rsc->client_lock);
-	if (blen < 0)
+	if (blen <= 0)
 		return 0;
 
 	if (copy_to_user(buf, buffer, blen))
@@ -907,7 +1015,7 @@
 
 end:
 	mutex_unlock(&rsc->client_lock);
-	if (blen < 0)
+	if (blen <= 0)
 		return 0;
 
 	if (copy_to_user(buf, buffer, blen))
diff --git a/drivers/gpu/drm/msm/sde_rsc_hw.c b/drivers/gpu/drm/msm/sde_rsc_hw.c
index 26a3154..b474d21 100644
--- a/drivers/gpu/drm/msm/sde_rsc_hw.c
+++ b/drivers/gpu/drm/msm/sde_rsc_hw.c
@@ -296,6 +296,47 @@
 	return 0;
 }
 
+static int rsc_hw_timer_update(struct sde_rsc_priv *rsc)
+{
+	if (!rsc) {
+		pr_debug("invalid input param\n");
+		return -EINVAL;
+	}
+
+	pr_debug("rsc hw timer update\n");
+
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0,
+		rsc->timer_config.rsc_time_slot_0_ns, rsc->debug_mode);
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_TIME_SLOT_TABLE_2_DRV0,
+		rsc->timer_config.rsc_time_slot_1_ns, rsc->debug_mode);
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_TIME_SLOT_TABLE_3_DRV0,
+		rsc->timer_config.rsc_time_slot_2_ns, rsc->debug_mode);
+
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE0,
+			rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE0,
+			rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode);
+
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE1,
+			rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE1,
+			rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode);
+
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE2,
+			rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode);
+
+	dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_STATIC_WAKEUP_0,
+		rsc->timer_config.static_wakeup_time_ns, rsc->debug_mode);
+
+	dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_RSCC_MODE_THRESHOLD,
+		rsc->timer_config.rsc_mode_threshold_time_ns, rsc->debug_mode);
+
+	/* make sure that hw timers are updated */
+	wmb();
+
+	return 0;
+}
+
 static int sde_rsc_mode2_exit(struct sde_rsc_priv *rsc,
 						enum sde_rsc_state state)
 {
@@ -345,7 +386,7 @@
 		if (!test_bit(POWER_CTRL_BIT_12, &power_status)) {
 			reg = dss_reg_r(&rsc->drv_io,
 				SDE_RSCC_SEQ_PROGRAM_COUNTER, rsc->debug_mode);
-			SDE_EVT32(count, reg, power_status);
+			SDE_EVT32_VERBOSE(count, reg, power_status);
 			rc = 0;
 			break;
 		}
@@ -428,6 +469,7 @@
 
 	if (rc) {
 		pr_err("mdss gdsc power down failed rc:%d\n", rc);
+		SDE_EVT32(rc, SDE_EVTLOG_ERROR);
 		goto end;
 	}
 
@@ -675,10 +717,24 @@
 				rsc->debug_mode));
 		break;
 
+	case VSYNC_READ_VSYNC0:
+		return dss_reg_r(&rsc->wrapper_io,
+				SDE_RSCC_WRAPPER_VSYNC_TIMESTAMP0,
+				rsc->debug_mode);
+
 	case VSYNC_ENABLE:
-		reg = BIT(8) | ((mode & 0x7) < 10);
+		/* clear the current VSYNC value */
+		reg = BIT(9) | ((mode & 0x7) << 10);
 		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_DEBUG_BUS,
 					reg, rsc->debug_mode);
+
+		/* enable the VSYNC logging */
+		reg = BIT(8) | ((mode & 0x7) << 10);
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_DEBUG_BUS,
+				reg, rsc->debug_mode);
+
+		/* ensure vsync config has been written before waiting on it */
+		wmb();
 		break;
 
 	case VSYNC_DISABLE:
@@ -740,6 +796,7 @@
 	pr_debug("rsc hardware register\n");
 
 	rsc->hw_ops.init = rsc_hw_init;
+	rsc->hw_ops.timer_update = rsc_hw_timer_update;
 
 	rsc->hw_ops.tcs_wait = rsc_hw_tcs_wait;
 	rsc->hw_ops.tcs_use_ok = rsc_hw_tcs_use_ok;
diff --git a/drivers/gpu/drm/msm/sde_rsc_priv.h b/drivers/gpu/drm/msm/sde_rsc_priv.h
index b90b0ac..c96ce75 100644
--- a/drivers/gpu/drm/msm/sde_rsc_priv.h
+++ b/drivers/gpu/drm/msm/sde_rsc_priv.h
@@ -51,11 +51,13 @@
 /**
  * rsc_vsync_req: sde rsc vsync request information
  * VSYNC_READ: read vsync status
+ * VSYNC_READ_VSYNC0: read value vsync0 timestamp (cast to int from u32)
  * VSYNC_ENABLE: enable rsc wrapper vsync status
  * VSYNC_DISABLE: disable rsc wrapper vsync status
  */
 enum rsc_vsync_req {
 	VSYNC_READ,
+	VSYNC_READ_VSYNC0,
 	VSYNC_ENABLE,
 	VSYNC_DISABLE,
 };
@@ -64,6 +66,8 @@
  * struct sde_rsc_hw_ops - sde resource state coordinator hardware ops
  * @init:			Initialize the sequencer, solver, qtimer,
 				etc. hardware blocks on RSC.
+ * @timer_update:		update the static wrapper time and pdc/rsc
+				backoff time.
  * @tcs_wait:			Waits for TCS block OK to allow sending a
  *				TCS command.
  * @hw_vsync:			Enables the vsync on RSC block.
@@ -77,6 +81,7 @@
 
 struct sde_rsc_hw_ops {
 	int (*init)(struct sde_rsc_priv *rsc);
+	int (*timer_update)(struct sde_rsc_priv *rsc);
 	int (*tcs_wait)(struct sde_rsc_priv *rsc);
 	int (*hw_vsync)(struct sde_rsc_priv *rsc, enum rsc_vsync_req request,
 		char *buffer, int buffer_size, u32 mode);
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 56bb758..7bb1e53 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -30,6 +30,7 @@
 #include "radeon_audio.h"
 #include "atom.h"
 #include <linux/backlight.h>
+#include <linux/dmi.h>
 
 extern int atom_debug;
 
@@ -2183,9 +2184,17 @@
 		goto assigned;
 	}
 
-	/* on DCE32 and encoder can driver any block so just crtc id */
+	/*
+	 * On DCE32 any encoder can drive any block so usually just use crtc id,
+	 * but Apple thinks different at least on iMac10,1, so there use linkb,
+	 * otherwise the internal eDP panel will stay dark.
+	 */
 	if (ASIC_IS_DCE32(rdev)) {
-		enc_idx = radeon_crtc->crtc_id;
+		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1"))
+			enc_idx = (dig->linkb) ? 1 : 0;
+		else
+			enc_idx = radeon_crtc->crtc_id;
+
 		goto assigned;
 	}
 
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index ea36dc4..2481049 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -782,6 +782,12 @@
 	if (r600_dpm_get_vrefresh(rdev) > 120)
 		return true;
 
+	/* disable mclk switching if the refresh is >120Hz, even if the
+        * blanking period would allow it
+        */
+	if (r600_dpm_get_vrefresh(rdev) > 120)
+		return true;
+
 	if (vblank_time < switch_limit)
 		return true;
 	else
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index c18fc31..94983e8 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1343,7 +1343,6 @@
 		       mem_type);
 		return ret;
 	}
-	fence_put(man->move);
 
 	man->use_type = false;
 	man->has_type = false;
@@ -1355,6 +1354,9 @@
 		ret = (*man->func->takedown)(man);
 	}
 
+	fence_put(man->move);
+	man->move = NULL;
+
 	return ret;
 }
 EXPORT_SYMBOL(ttm_bo_clean_mm);
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 32ebe0c..431a67e 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -720,10 +720,25 @@
 
 /* VBIF registers */
 #define A6XX_VBIF_VERSION                       0x3000
+#define A6XX_VBIF_CLKON                         0x3001
+#define A6XX_VBIF_CLKON_FORCE_ON_TESTBUS_MASK   0x1
+#define A6XX_VBIF_CLKON_FORCE_ON_TESTBUS_SHIFT  0x1
 #define A6XX_VBIF_GATE_OFF_WRREQ_EN             0x302A
 #define A6XX_VBIF_XIN_HALT_CTRL0                0x3080
 #define A6XX_VBIF_XIN_HALT_CTRL0_MASK           0xF
 #define A6XX_VBIF_XIN_HALT_CTRL1                0x3081
+#define A6XX_VBIF_TEST_BUS_OUT_CTRL             0x3084
+#define A6XX_VBIF_TEST_BUS_OUT_CTRL_EN_MASK     0x1
+#define A6XX_VBIF_TEST_BUS_OUT_CTRL_EN_SHIFT    0x0
+#define A6XX_VBIF_TEST_BUS1_CTRL0               0x3085
+#define A6XX_VBIF_TEST_BUS1_CTRL1               0x3086
+#define A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL_MASK 0xF
+#define A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL_SHIFT 0x0
+#define A6XX_VBIF_TEST_BUS2_CTRL0               0x3087
+#define A6XX_VBIF_TEST_BUS2_CTRL1               0x3088
+#define A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL_MASK 0x1FF
+#define A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL_SHIFT 0x0
+#define A6XX_VBIF_TEST_BUS_OUT                  0x308C
 #define A6XX_VBIF_PERF_CNT_SEL0                 0x30d0
 #define A6XX_VBIF_PERF_CNT_SEL1                 0x30d1
 #define A6XX_VBIF_PERF_CNT_SEL2                 0x30d2
@@ -801,6 +816,7 @@
 #define A6XX_GMU_DCVS_PERF_SETTING		0x1CBFD
 #define A6XX_GMU_DCVS_BW_SETTING		0x1CBFE
 #define A6XX_GMU_DCVS_RETURN			0x1CBFF
+#define A6XX_GMU_SYS_BUS_CONFIG			0x1F40F
 #define A6XX_GMU_CM3_SYSRESET			0x1F800
 #define A6XX_GMU_CM3_BOOT_CONFIG		0x1F801
 #define A6XX_GMU_CM3_FW_BUSY			0x1F81A
@@ -859,11 +875,46 @@
 #define A6XX_GMU_HOST2GMU_INTR_INFO_1		0x1F99C
 #define A6XX_GMU_HOST2GMU_INTR_INFO_2		0x1F99D
 #define A6XX_GMU_HOST2GMU_INTR_INFO_3		0x1F99E
+#define A6XX_GMU_GENERAL_1			0x1F9C6
 #define A6XX_GMU_GENERAL_7			0x1F9CC
 
 /* ISENSE registers */
 #define A6XX_GMU_ISENSE_CTRL			0x1F95D
 #define A6XX_GPU_CS_ENABLE_REG			0x23120
+#define A6XX_GPU_GMU_CX_GMU_ISENSE_CTRL		0x1f95d
+#define A6XX_GPU_CS_AMP_CALIBRATION_CONTROL3	0x22d78
+#define A6XX_GPU_CS_AMP_CALIBRATION_CONTROL2	0x22d58
+#define A6XX_GPU_CS_A_SENSOR_CTRL_0		0x22d80
+#define A6XX_GPU_CS_A_SENSOR_CTRL_2		0x422da
+#define A6XX_GPU_CS_SENSOR_GENERAL_STATUS	0x2301a
+#define A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1	0x23157
+#define A6XX_GPU_CS_SENSOR_GENERAL_STATUS	0x2301a
+#define A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_0	0x2301d
+#define A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_2	0x2301f
+#define A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_4	0x23021
+#define A6XX_GPU_CS_AMP_CALIBRATION_DONE	0x23165
+#define A6XX_GPU_CS_AMP_PERIOD_CTRL		0x2316d
+#define A6XX_GPU_CS_AMP_CALIBRATION_DONE	0x23165
+
+#define CS_PWR_ON_STATUS			(10)
+#define AMP_SW_WRM_TRIM_START			(24)
+#define AMP_TRIM_TIMER				(6)
+#define AMP_SW_TRIM_START			(0)
+#define SS_AMPTRIM_DONE				(11)
+#define AMP_OFFSET_CHECK_MIN_ERR		(1)
+#define AMP_OFFSET_CHECK_MAX_ERR		(2)
+#define AMP_OUT_OF_RANGE_ERR			(4)
+#define TRIM_CNT_VALUE				(1)
+#define RUNTIME_CNT_VALUE			(16)
+#define TRIM_ENABLE				(0)
+
+#define AMP_ERR			(BIT(AMP_OFFSET_CHECK_MIN_ERR) || \
+				BIT(AMP_OFFSET_CHECK_MAX_ERR) || \
+				BIT(AMP_OUT_OF_RANGE_ERR))
+
+/* LM registers */
+#define A6XX_GPU_GMU_CX_GMU_PWR_THRESHOLD       0x1F94D
+
 
 #define A6XX_GMU_AO_INTERRUPT_EN		0x23B03
 #define A6XX_GMU_AO_HOST_INTERRUPT_CLR		0x23B04
@@ -890,6 +941,7 @@
 
 /* GPUCC registers */
 #define A6XX_GPU_CC_GX_GDSCR                   0x24403
+#define A6XX_GPU_CC_GX_DOMAIN_MISC		0x24542
 
 /* GPU RSC sequencer registers */
 #define	A6XX_RSCC_PDC_SEQ_START_ADDR			0x23408
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index f8bf780..7dda62a 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -327,7 +327,7 @@
 		.minor = 0,
 		.patchid = ANY_ID,
 		.features = ADRENO_64BIT | ADRENO_RPMH |
-			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION,
+			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_LM,
 		.sqefw_name = "a630_sqe.fw",
 		.zap_name = "a630_zap",
 		.gpudev = &adreno_a6xx_gpudev,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 6f465aa..6426363 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2342,6 +2342,11 @@
 		return ret;
 	}
 
+	/* Clear the busy_data stats - we're starting over from scratch */
+	adreno_dev->busy_data.gpu_busy = 0;
+	adreno_dev->busy_data.vbif_ram_cycles = 0;
+	adreno_dev->busy_data.vbif_starved_ram = 0;
+
 	/* Set the page table back to the default page table */
 	adreno_ringbuffer_set_global(adreno_dev, 0);
 	kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 4900b3a..01b877f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -642,6 +642,8 @@
 	ADRENO_REG_GMU_HOST2GMU_INTR_SET,
 	ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
 	ADRENO_REG_GMU_HOST2GMU_INTR_RAW_INFO,
+	ADRENO_REG_GMU_NMI_CONTROL_STATUS,
+	ADRENO_REG_GMU_CM3_CFG,
 	ADRENO_REG_GPMU_POWER_COUNTER_ENABLE,
 	ADRENO_REG_REGISTER_MAX,
 };
diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h
index 08fd16a..3d89d73 100644
--- a/drivers/gpu/msm/adreno_a5xx.h
+++ b/drivers/gpu/msm/adreno_a5xx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 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
@@ -151,24 +151,6 @@
 #define GPMU_ISENSE_STATUS		GENMASK(3, 0)
 #define GPMU_ISENSE_END_POINT_CAL_ERR	BIT(0)
 
-/* A5XX_GPU_CS_AMP_CALIBRATION_CONTROL1 */
-#define AMP_SW_TRIM_START		BIT(0)
-
-/* A5XX_GPU_CS_SENSOR_GENERAL_STATUS */
-#define SS_AMPTRIM_DONE			BIT(11)
-#define CS_PWR_ON_STATUS		BIT(10)
-
-/* A5XX_GPU_CS_AMP_CALIBRATION_STATUS*_* */
-#define AMP_OUT_OF_RANGE_ERR		BIT(4)
-#define AMP_OFFSET_CHECK_MAX_ERR	BIT(2)
-#define AMP_OFFSET_CHECK_MIN_ERR	BIT(1)
-
-/* A5XX_GPU_CS_AMP_CALIBRATION_DONE */
-#define SW_OPAMP_CAL_DONE           BIT(0)
-
-#define AMP_CALIBRATION_ERR (AMP_OFFSET_CHECK_MIN_ERR | \
-		AMP_OFFSET_CHECK_MAX_ERR | AMP_OUT_OF_RANGE_ERR)
-
 #define AMP_CALIBRATION_RETRY_CNT	3
 #define AMP_CALIBRATION_TIMEOUT		6
 
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index c1d2407..23c340c 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -357,7 +357,22 @@
 
 	/* enable top level HWCG */
 	kgsl_regwrite(device, A6XX_RBBM_CLOCK_CNTL, on ? 0x8AA8AA02 : 0);
-	kgsl_regwrite(device, A5XX_RBBM_ISDB_CNT, on ? 0x00000182 : 0x00000180);
+}
+
+#define LM_DEFAULT_LIMIT	6000
+
+static uint32_t lm_limit(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+
+	if (adreno_dev->lm_limit)
+		return adreno_dev->lm_limit;
+
+	if (of_property_read_u32(device->pdev->dev.of_node, "qcom,lm-limit",
+		&adreno_dev->lm_limit))
+		adreno_dev->lm_limit = LM_DEFAULT_LIMIT;
+
+	return adreno_dev->lm_limit;
 }
 
 /*
@@ -379,6 +394,9 @@
 	/* enable hardware clockgating */
 	a6xx_hwcg_set(adreno_dev, true);
 
+	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM))
+		adreno_dev->lm_threshold_count = A6XX_GMU_GENERAL_1;
+
 	adreno_vbif_start(adreno_dev, a6xx_vbif_platforms,
 			ARRAY_SIZE(a6xx_vbif_platforms));
 
@@ -544,11 +562,20 @@
 /* Ucode workaround masks */
 #define CP_INIT_UCODE_WORKAROUND_MASK BIT(5)
 
+/*
+ * Operation mode mask
+ *
+ * This ordinal provides the option to disable the
+ * save/restore of performance counters across preemption.
+ */
+#define CP_INIT_OPERATION_MODE_MASK BIT(6)
+
 #define CP_INIT_MASK (CP_INIT_MAX_CONTEXT | \
 		CP_INIT_ERROR_DETECTION_CONTROL | \
 		CP_INIT_HEADER_DUMP | \
 		CP_INIT_DEFAULT_RESET_STATE | \
-		CP_INIT_UCODE_WORKAROUND_MASK)
+		CP_INIT_UCODE_WORKAROUND_MASK | \
+		CP_INIT_OPERATION_MODE_MASK)
 
 static void _set_ordinals(struct adreno_device *adreno_dev,
 		unsigned int *cmds, unsigned int count)
@@ -581,6 +608,9 @@
 	if (CP_INIT_MASK & CP_INIT_UCODE_WORKAROUND_MASK)
 		*cmds++ = 0x00000000;
 
+	if (CP_INIT_MASK & CP_INIT_OPERATION_MODE_MASK)
+		*cmds++ = 0x00000002;
+
 	/* Pad rest of the cmds with 0's */
 	while ((unsigned int)(cmds - start) < count)
 		*cmds++ = 0x0;
@@ -904,6 +934,9 @@
 
 	/* Configure registers for idle setting. The setting is cumulative */
 
+	/* Disable GMU WB/RB buffer */
+	kgsl_gmu_regwrite(device, A6XX_GMU_SYS_BUS_CONFIG, 0x1);
+
 	kgsl_gmu_regwrite(device,
 		A6XX_GMU_PWR_COL_INTER_FRAME_CTRL,  0x9C40400);
 
@@ -935,7 +968,8 @@
 	}
 
 	/* ACD feature enablement */
-	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM))
+	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
+		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
 		kgsl_gmu_regrmw(device, A6XX_GMU_BOOT_KMD_LM_HANDSHAKE, 0,
 				BIT(10));
 
@@ -943,9 +977,6 @@
 	if (ADRENO_FEATURE(adreno_dev, ADRENO_RPMH))
 		kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, 0,
 				RPMH_ENABLE_MASK);
-
-	/* Disable reference bandgap voltage */
-	kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 1);
 }
 
 /*
@@ -1132,62 +1163,6 @@
 		dev_err(&gmu->pdev->dev, "power off SPTPRAC fail\n");
 }
 
-/*
- * a6xx_hm_enable() - Power on HM and turn on clock
- * @adreno_dev: Pointer to Adreno device
- */
-static int a6xx_hm_enable(struct adreno_device *adreno_dev)
-{
-	int ret;
-	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
-	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
-	struct gmu_device *gmu = &device->gmu;
-
-	if (regulator_is_enabled(gmu->gx_gdsc))
-		return 0;
-
-	ret = regulator_enable(gmu->gx_gdsc);
-	if (ret) {
-		dev_err(&gmu->pdev->dev,
-			"Failed to turn on GPU HM HS\n");
-		return ret;
-	}
-
-	ret = clk_set_rate(pwr->grp_clks[0],
-			pwr->pwrlevels[pwr->default_pwrlevel].
-			gpu_freq);
-	if (ret)
-		return ret;
-
-	return clk_prepare_enable(pwr->grp_clks[0]);
-}
-
-/*
- * a6xx_hm_disable() - Turn off HM clock and power off
- * @adreno_dev: Pointer to Adreno device
- */
-static int a6xx_hm_disable(struct adreno_device *adreno_dev)
-{
-	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
-	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
-	struct gmu_device *gmu = &device->gmu;
-
-	if (!regulator_is_enabled(gmu->gx_gdsc))
-		return 0;
-
-	/* Ensure that retention is on */
-	kgsl_gmu_regrmw(device, A6XX_GPU_CC_GX_GDSCR, 0,
-			A6XX_RETAIN_FF_ENABLE_ENABLE_MASK);
-
-	clk_disable_unprepare(pwr->grp_clks[0]);
-
-	clk_set_rate(pwr->grp_clks[0],
-			pwr->pwrlevels[pwr->num_pwrlevels - 1].
-			gpu_freq);
-
-	return regulator_disable(gmu->gx_gdsc);
-}
-
 #define SPTPRAC_POWER_OFF	BIT(2)
 #define SP_CLK_OFF		BIT(4)
 #define GX_GDSC_POWER_OFF	BIT(6)
@@ -1239,62 +1214,6 @@
 }
 
 /*
- * a6xx_hm_sptprac_enable() - Turn on HM and SPTPRAC
- * @device: Pointer to KGSL device
- */
-static int a6xx_hm_sptprac_enable(struct kgsl_device *device)
-{
-	int ret = 0;
-	struct gmu_device *gmu = &device->gmu;
-
-	/* If GMU does not control HM we must */
-	if (gmu->idle_level < GPU_HW_IFPC) {
-
-		ret = a6xx_hm_enable(ADRENO_DEVICE(device));
-		if (ret) {
-			dev_err(&gmu->pdev->dev, "Failed to power on GPU HM\n");
-			return ret;
-		}
-
-
-	}
-
-	/* If GMU does not control SPTPRAC we must */
-	if (gmu->idle_level < GPU_HW_SPTP_PC) {
-		ret = a6xx_sptprac_enable(ADRENO_DEVICE(device));
-		if (ret) {
-			a6xx_hm_disable(ADRENO_DEVICE(device));
-			return ret;
-		}
-	}
-
-	return ret;
-}
-
-/*
- * a6xx_hm_sptprac_disable() - Turn off SPTPRAC and HM
- * @device: Pointer to KGSL device
- */
-static int a6xx_hm_sptprac_disable(struct kgsl_device *device)
-{
-	int ret = 0;
-	struct gmu_device *gmu = &device->gmu;
-
-	/* If GMU does not control SPTPRAC we must */
-	if (gmu->idle_level < GPU_HW_SPTP_PC)
-		a6xx_sptprac_disable(ADRENO_DEVICE(device));
-
-	/* If GMU does not control HM we must */
-	if (gmu->idle_level < GPU_HW_IFPC) {
-		ret = a6xx_hm_disable(ADRENO_DEVICE(device));
-		if (ret)
-			dev_err(&gmu->pdev->dev, "Failed to power off GPU HM\n");
-	}
-
-	return ret;
-}
-
-/*
  * a6xx_gfx_rail_on() - request GMU to power GPU at given OPP.
  * @device: Pointer to KGSL device
  *
@@ -1344,6 +1263,9 @@
 	/* Disable the power counter so that the GMU is not busy */
 	kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0);
 
+	/* Turn off SPTPRAC before GMU turns off GX */
+	a6xx_sptprac_disable(adreno_dev);
+
 	if (!ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
 		ret = hfi_notify_slumber(gmu, perf_idx, bus_level);
 		return ret;
@@ -1379,7 +1301,10 @@
 {
 	struct gmu_device *gmu = &device->gmu;
 	struct device *dev = &gmu->pdev->dev;
-	int ret = 0;
+	int val;
+
+	kgsl_gmu_regread(device, A6XX_GPU_CC_GX_DOMAIN_MISC, &val);
+	WARN_ON(!(val & 0x1));
 
 	/* RSC wake sequence */
 	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
@@ -1405,25 +1330,20 @@
 
 	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);
 
-	/* Turn on the HM and SPTP head switches */
-	ret = a6xx_hm_sptprac_enable(device);
-
 	/* Enable the power counter because it was disabled before slumber */
 	kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
 
-	return ret;
+	return 0;
 error_rsc:
 	dev_err(dev, "GPU RSC sequence stuck in waking up GPU\n");
-		return -EINVAL;
+	return -EINVAL;
 }
 
 static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
 {
 	struct gmu_device *gmu = &device->gmu;
-	int val, ret = 0;
-
-	/* Turn off the SPTP and HM head switches */
-	ret = a6xx_hm_sptprac_disable(device);
+	const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	int val;
 
 	/* RSC sleep sequence */
 	kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
@@ -1446,13 +1366,87 @@
 			&val);
 	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);
 
-	kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0);
+	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
+		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
+		kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0);
 
 	/* FIXME: v2 has different procedure to trigger sequence */
 
-	return ret;
+	return 0;
 }
 
+#define KMASK(start, n) (GENMASK((start + n), (start)))
+
+static void isense_cold_trimm(struct kgsl_device *device)
+{
+	unsigned int reg;
+	struct gmu_device *gmu = &device->gmu;
+
+	kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 1);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_DONE, 0);
+
+	kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_ISENSE_CTRL, 0x1);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL3,
+		0x00000F8F);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL2,
+		0x00705161);
+	udelay(10);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_ENABLE_REG, 0x3);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_A_SENSOR_CTRL_0, 0x10040a);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_A_SENSOR_CTRL_2, 0x10040a);
+
+	kgsl_gmu_regread(device, A6XX_GPU_CS_SENSOR_GENERAL_STATUS, &reg);
+	if ((reg & BIT(CS_PWR_ON_STATUS)) != (1 << CS_PWR_ON_STATUS)) {
+		dev_err(&gmu->pdev->dev, "ERROR - ISENSE power-up\n");
+		return;
+	}
+
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1,
+		KMASK(AMP_TRIM_TIMER, 15), 70 << AMP_TRIM_TIMER);
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1,
+		KMASK(AMP_SW_TRIM_START, 1), 0 << AMP_SW_TRIM_START);
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1,
+		KMASK(AMP_SW_TRIM_START, 1), 1 << AMP_SW_TRIM_START);
+
+	if (timed_poll_check(device, A6XX_GPU_CS_SENSOR_GENERAL_STATUS,
+		BIT(SS_AMPTRIM_DONE), GMU_START_TIMEOUT,
+		BIT(SS_AMPTRIM_DONE))) {
+		dev_err(&gmu->pdev->dev, "ISENSE SS_AMPTRIM failure\n");
+		return;
+	}
+
+	kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_0, &reg);
+	if (reg & AMP_ERR) {
+		kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_0,
+			&reg);
+		dev_err(&gmu->pdev->dev,
+			"ISENSE ERROR:trimming GX 0x%08x\n", reg);
+		return;
+	}
+
+	kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_2, &reg);
+	if (reg & AMP_ERR) {
+		kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_2,
+			&reg);
+		dev_err(&gmu->pdev->dev,
+			"ISENSE ERROR:trimming SPTPRAC 0x%08x\n", reg);
+		return;
+	}
+
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_DONE, 1);
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
+		KMASK(TRIM_CNT_VALUE, 13), 20 << TRIM_CNT_VALUE);
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
+		KMASK(RUNTIME_CNT_VALUE, 9), 50 << RUNTIME_CNT_VALUE);
+
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
+		KMASK(TRIM_ENABLE, 1), 1 << TRIM_ENABLE);
+	udelay(4);
+	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
+		KMASK(TRIM_ENABLE, 1), 0 << TRIM_ENABLE);
+	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_DONE, 1);
+
+}
 /*
  * a6xx_gmu_fw_start() - set up GMU and start FW
  * @device: Pointer to KGSL device
@@ -1470,25 +1464,12 @@
 	case GMU_RESET:
 		/* fall through */
 	case GMU_COLD_BOOT:
-		/* Turn on the HM and SPTP head switches */
-		ret = a6xx_hm_sptprac_enable(device);
-		if (ret)
-			return ret;
-
 		/* Turn on TCM retention */
 		kgsl_gmu_regwrite(device, A6XX_GMU_GENERAL_7, 1);
 
-		if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags)) {
+		if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags))
 			_load_gmu_rpmh_ucode(device);
-			/* Turn on the HM and SPTP head switches */
-			ret = a6xx_hm_sptprac_enable(device);
-			if (ret)
-				return ret;
-		} else if (boot_state == GMU_RESET) {
-			ret = a6xx_hm_sptprac_enable(device);
-			if (ret)
-				return ret;
-		} else {
+		else if (boot_state != GMU_RESET) {
 			ret = a6xx_rpmh_power_on_gpu(device);
 			if (ret)
 				return ret;
@@ -1530,6 +1511,13 @@
 	kgsl_gmu_regwrite(device, A6XX_GMU_AHB_FENCE_RANGE_0,
 			FENCE_RANGE_MASK);
 
+	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
+		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) {
+		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_PWR_THRESHOLD,
+			lm_limit(adreno_dev));
+		isense_cold_trimm(device);
+	}
+
 	/* Configure power control and bring the GMU out of reset */
 	a6xx_gmu_power_config(device);
 	ret = a6xx_gmu_start(device);
@@ -1545,6 +1533,12 @@
 		}
 	}
 
+	if (gmu->idle_level < GPU_HW_SPTP_PC) {
+		ret = a6xx_sptprac_enable(adreno_dev);
+		if (ret)
+			return ret;
+	}
+
 	ret = a6xx_gmu_hfi_start(device);
 	if (ret)
 		return ret;
@@ -1759,7 +1753,8 @@
 	unsigned int val;
 	const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
-	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM))
+	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) ||
+		!test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
 		return;
 
 	kgsl_gmu_regread(device, A6XX_GPU_CS_ENABLE_REG, &val);
@@ -1775,7 +1770,8 @@
 	const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct gmu_device *gmu = &device->gmu;
 
-	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM))
+	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) ||
+		!test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
 		return 0;
 
 	kgsl_gmu_regread(device, A6XX_GMU_LLM_GLM_SLEEP_CTRL, &val);
@@ -1794,6 +1790,19 @@
 	return 0;
 }
 
+
+static void a6xx_count_throttles(struct adreno_device *adreno_dev,
+	uint64_t adj)
+{
+	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) ||
+		!test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
+		return;
+
+	kgsl_gmu_regread(KGSL_DEVICE(adreno_dev),
+		adreno_dev->lm_threshold_count,
+		&adreno_dev->lm_threshold_cross);
+}
+
 static int a6xx_complete_rpmh_votes(struct kgsl_device *device)
 {
 	int ret = 0;
@@ -1837,13 +1846,7 @@
 	/* Check no outstanding RPMh voting */
 	a6xx_complete_rpmh_votes(device);
 
-	if (gmu->idle_level < GPU_HW_IFPC) {
-		/* HM GDSC is controlled by KGSL */
-		ret = a6xx_hm_disable(ADRENO_DEVICE(device));
-		if (ret)
-			dev_err(&gmu->pdev->dev,
-				"suspend: fail: power off GPU HM\n");
-	} else if (gmu->gx_gdsc) {
+	if (gmu->gx_gdsc) {
 		if (regulator_is_enabled(gmu->gx_gdsc)) {
 			/* Switch gx gdsc control from GMU to CPU
 			 * force non-zero reference count in clk driver
@@ -2184,6 +2187,14 @@
 	return uche_client[uche_client_id & A6XX_UCHE_CLIENT_PF_CLIENT_ID_MASK];
 }
 
+static void a6xx_cp_callback(struct adreno_device *adreno_dev, int bit)
+{
+	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+
+	a6xx_preemption_trigger(adreno_dev);
+	adreno_dispatcher_schedule(device);
+}
+
 #define A6XX_INT_MASK \
 	((1 << A6XX_INT_CP_AHB_ERROR) |			\
 	 (1 << A6XX_INT_ATB_ASYNCFIFO_OVERFLOW) |	\
@@ -2221,7 +2232,7 @@
 	ADRENO_IRQ_CALLBACK(NULL), /* 17 - CP_RB_DONE_TS */
 	ADRENO_IRQ_CALLBACK(NULL), /* 18 - CP_WT_DONE_TS */
 	ADRENO_IRQ_CALLBACK(NULL), /* 19 - UNUSED */
-	ADRENO_IRQ_CALLBACK(adreno_cp_callback), /* 20 - CP_CACHE_FLUSH_TS */
+	ADRENO_IRQ_CALLBACK(a6xx_cp_callback), /* 20 - CP_CACHE_FLUSH_TS */
 	ADRENO_IRQ_CALLBACK(NULL), /* 21 - UNUSED */
 	ADRENO_IRQ_CALLBACK(a6xx_err_callback), /* 22 - RBBM_ATB_BUS_OVERFLOW */
 	/* 23 - MISC_HANG_DETECT */
@@ -2672,9 +2683,9 @@
 	if (!device->gmu.pdev)
 		return -ENODEV;
 
-	kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0);
+	kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xFF000000);
 	kgsl_regrmw(device,
-		A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xFF, 0x20);
+			A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xFF, 0x20);
 	kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1);
 
 	return 0;
@@ -2775,6 +2786,10 @@
 				A6XX_GMU_HOST2GMU_INTR_CLR),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_RAW_INFO,
 				A6XX_GMU_HOST2GMU_INTR_RAW_INFO),
+	ADRENO_REG_DEFINE(ADRENO_REG_GMU_NMI_CONTROL_STATUS,
+				A6XX_GMU_NMI_CONTROL_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_GMU_CM3_CFG,
+				A6XX_GMU_CM3_CFG),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SECVID_TRUST_CONTROL,
 				A6XX_RBBM_SECVID_TRUST_CNTL),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE,
@@ -2807,6 +2822,7 @@
 	.regulator_disable = a6xx_sptprac_disable,
 	.perfcounters = &a6xx_perfcounters,
 	.enable_pwr_counters = a6xx_enable_pwr_counters,
+	.count_throttles = a6xx_count_throttles,
 	.microcode_read = a6xx_microcode_read,
 	.enable_64bit = a6xx_enable_64bit,
 	.llc_configure_gpu_scid = a6xx_llc_configure_gpu_scid,
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 1f97888..e1f1595 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -21,6 +21,9 @@
 #include "kgsl_gmu.h"
 
 #define A6XX_NUM_CTXTS 2
+#define A6XX_NUM_AXI_ARB_BLOCKS 2
+#define A6XX_NUM_XIN_AXI_BLOCKS 5
+#define A6XX_NUM_XIN_CORE_BLOCKS 4
 
 static const unsigned int a6xx_gras_cluster[] = {
 	0x8000, 0x8006, 0x8010, 0x8092, 0x8094, 0x809D, 0x80A0, 0x80A6,
@@ -228,9 +231,9 @@
 	0x1F980, 0x1F986, 0x1F990, 0x1F99E, 0x1F9C0, 0x1F9C0, 0x1F9C5, 0x1F9CC,
 	0x1F9E0, 0x1F9E2, 0x1F9F0, 0x1F9F0, 0x1FA00, 0x1FA03,
 	/* GPU RSCC */
-	0x23740, 0x23742, 0x23744, 0x23747, 0x2374C, 0x23787, 0x237EC, 0x237EF,
-	0x237F4, 0x2382F, 0x23894, 0x23897, 0x2389C, 0x238D7, 0x2393C, 0x2393F,
-	0x23944, 0x2397F,
+	0x2348C, 0x2348C, 0x23501, 0x23502, 0x23740, 0x23742, 0x23744, 0x23747,
+	0x2374C, 0x23787, 0x237EC, 0x237EF, 0x237F4, 0x2382F, 0x23894, 0x23897,
+	0x2389C, 0x238D7, 0x2393C, 0x2393F, 0x23944, 0x2397F,
 	/* GMU AO */
 	0x23B00, 0x23B16, 0x23C00, 0x23C00,
 	/* GPU CC */
@@ -393,9 +396,12 @@
 	{ A6XX_DBGBUS_TPL1_3, 0x100, },
 };
 
+static const struct adreno_debugbus_block a6xx_vbif_debugbus_blocks = {
+	A6XX_DBGBUS_VBIF, 0x100,
+};
+
 static void __iomem *a6xx_cx_dbgc;
 static const struct adreno_debugbus_block a6xx_cx_dbgc_debugbus_blocks[] = {
-	{ A6XX_DBGBUS_VBIF, 0x100, },
 	{ A6XX_DBGBUS_GMU_CX, 0x100, },
 	{ A6XX_DBGBUS_CX, 0x100, },
 };
@@ -1076,7 +1082,7 @@
 	kgsl_regread(device, A6XX_DBGC_CFG_DBGBUS_TRACE_BUF1, val);
 }
 
-/* a6xx_snapshot_cbgc_debugbus_block() - Capture debug data for a gpu block */
+/* a6xx_snapshot_dbgc_debugbus_block() - Capture debug data for a gpu block */
 static size_t a6xx_snapshot_dbgc_debugbus_block(struct kgsl_device *device,
 	u8 *buf, size_t remain, void *priv)
 {
@@ -1115,6 +1121,89 @@
 	return size;
 }
 
+/* a6xx_snapshot_vbif_debugbus_block() - Capture debug data for VBIF block */
+static size_t a6xx_snapshot_vbif_debugbus_block(struct kgsl_device *device,
+			u8 *buf, size_t remain, void *priv)
+{
+	struct kgsl_snapshot_debugbus *header =
+		(struct kgsl_snapshot_debugbus *)buf;
+	struct adreno_debugbus_block *block = priv;
+	int i, j;
+	/*
+	 * Total number of VBIF data words considering 3 sections:
+	 * 2 arbiter blocks of 16 words
+	 * 5 AXI XIN blocks of 18 dwords each
+	 * 4 core clock side XIN blocks of 12 dwords each
+	 */
+	unsigned int dwords = (16 * A6XX_NUM_AXI_ARB_BLOCKS) +
+			(18 * A6XX_NUM_XIN_AXI_BLOCKS) +
+			(12 * A6XX_NUM_XIN_CORE_BLOCKS);
+	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
+	size_t size;
+	unsigned int reg_clk;
+
+	size = (dwords * sizeof(unsigned int)) + sizeof(*header);
+
+	if (remain < size) {
+		SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS");
+		return 0;
+	}
+	header->id = block->block_id;
+	header->count = dwords;
+
+	kgsl_regread(device, A6XX_VBIF_CLKON, &reg_clk);
+	kgsl_regwrite(device, A6XX_VBIF_CLKON, reg_clk |
+			(A6XX_VBIF_CLKON_FORCE_ON_TESTBUS_MASK <<
+			A6XX_VBIF_CLKON_FORCE_ON_TESTBUS_SHIFT));
+	kgsl_regwrite(device, A6XX_VBIF_TEST_BUS1_CTRL0, 0);
+	kgsl_regwrite(device, A6XX_VBIF_TEST_BUS_OUT_CTRL,
+			(A6XX_VBIF_TEST_BUS_OUT_CTRL_EN_MASK <<
+			A6XX_VBIF_TEST_BUS_OUT_CTRL_EN_SHIFT));
+
+	for (i = 0; i < A6XX_NUM_AXI_ARB_BLOCKS; i++) {
+		kgsl_regwrite(device, A6XX_VBIF_TEST_BUS2_CTRL0,
+			(1 << (i + 16)));
+		for (j = 0; j < 16; j++) {
+			kgsl_regwrite(device, A6XX_VBIF_TEST_BUS2_CTRL1,
+				((j & A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL_MASK)
+				<< A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL_SHIFT));
+			kgsl_regread(device, A6XX_VBIF_TEST_BUS_OUT,
+					data);
+			data++;
+		}
+	}
+
+	/* XIN blocks AXI side */
+	for (i = 0; i < A6XX_NUM_XIN_AXI_BLOCKS; i++) {
+		kgsl_regwrite(device, A6XX_VBIF_TEST_BUS2_CTRL0, 1 << i);
+		for (j = 0; j < 18; j++) {
+			kgsl_regwrite(device, A6XX_VBIF_TEST_BUS2_CTRL1,
+				((j & A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL_MASK)
+				<< A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL_SHIFT));
+			kgsl_regread(device, A6XX_VBIF_TEST_BUS_OUT,
+				data);
+			data++;
+		}
+	}
+	kgsl_regwrite(device, A6XX_VBIF_TEST_BUS2_CTRL0, 0);
+
+	/* XIN blocks core clock side */
+	for (i = 0; i < A6XX_NUM_XIN_CORE_BLOCKS; i++) {
+		kgsl_regwrite(device, A6XX_VBIF_TEST_BUS1_CTRL0, 1 << i);
+		for (j = 0; j < 12; j++) {
+			kgsl_regwrite(device, A6XX_VBIF_TEST_BUS1_CTRL1,
+				((j & A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL_MASK)
+				<< A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL_SHIFT));
+			kgsl_regread(device, A6XX_VBIF_TEST_BUS_OUT,
+				data);
+			data++;
+		}
+	}
+	/* restore the clock of VBIF */
+	kgsl_regwrite(device, A6XX_VBIF_CLKON, reg_clk);
+	return size;
+}
+
 static void _cx_dbgc_regread(unsigned int offsetwords, unsigned int *value)
 {
 	void __iomem *reg;
@@ -1310,6 +1399,10 @@
 			(void *) &a6xx_dbgc_debugbus_blocks[i]);
 	}
 
+	kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUGBUS,
+			snapshot, a6xx_snapshot_vbif_debugbus_block,
+			(void *) &a6xx_vbif_debugbus_blocks);
+
 	if (a6xx_cx_dbgc) {
 		for (i = 0; i < ARRAY_SIZE(a6xx_cx_dbgc_debugbus_blocks); i++) {
 			kgsl_snapshot_add_section(device,
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 422c434..0a45d27 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -983,6 +983,13 @@
 	spin_unlock(&dispatcher->plist_lock);
 }
 
+static inline void _decrement_submit_now(struct kgsl_device *device)
+{
+	spin_lock(&device->submit_lock);
+	device->submit_now--;
+	spin_unlock(&device->submit_lock);
+}
+
 /**
  * adreno_dispatcher_issuecmds() - Issue commmands from pending contexts
  * @adreno_dev: Pointer to the adreno device struct
@@ -992,15 +999,29 @@
 static void adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
 {
 	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
+	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+
+	spin_lock(&device->submit_lock);
+	/* If state transition to SLUMBER, schedule the work for later */
+	if (device->slumber == true) {
+		spin_unlock(&device->submit_lock);
+		goto done;
+	}
+	device->submit_now++;
+	spin_unlock(&device->submit_lock);
 
 	/* If the dispatcher is busy then schedule the work for later */
 	if (!mutex_trylock(&dispatcher->mutex)) {
-		adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
-		return;
+		_decrement_submit_now(device);
+		goto done;
 	}
 
 	_adreno_dispatcher_issuecmds(adreno_dev);
 	mutex_unlock(&dispatcher->mutex);
+	_decrement_submit_now(device);
+	return;
+done:
+	adreno_dispatcher_schedule(device);
 }
 
 /**
@@ -2452,7 +2473,7 @@
 	mutex_unlock(&device->mutex);
 }
 
-static void adreno_dispatcher_work(struct work_struct *work)
+static void adreno_dispatcher_work(struct kthread_work *work)
 {
 	struct adreno_dispatcher *dispatcher =
 		container_of(work, struct adreno_dispatcher, work);
@@ -2512,7 +2533,7 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
 
-	kgsl_schedule_work(&dispatcher->work);
+	kthread_queue_work(&kgsl_driver.worker, &dispatcher->work);
 }
 
 /**
@@ -2808,7 +2829,7 @@
 	setup_timer(&dispatcher->fault_timer, adreno_dispatcher_fault_timer,
 		(unsigned long) adreno_dev);
 
-	INIT_WORK(&dispatcher->work, adreno_dispatcher_work);
+	kthread_init_work(&dispatcher->work, adreno_dispatcher_work);
 
 	init_completion(&dispatcher->idle_gate);
 	complete_all(&dispatcher->idle_gate);
diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h
index 72545db..48f0cdc 100644
--- a/drivers/gpu/msm/adreno_dispatch.h
+++ b/drivers/gpu/msm/adreno_dispatch.h
@@ -91,7 +91,7 @@
 	atomic_t fault;
 	struct plist_head pending;
 	spinlock_t plist_lock;
-	struct work_struct work;
+	struct kthread_work work;
 	struct kobject kobj;
 	struct completion idle_gate;
 	unsigned int disp_preempt_fair_sched;
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index c6df7bb..0882447 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -548,6 +548,8 @@
 
 	mutex_unlock(&device->mutex);
 
+	debugfs_remove_recursive(drawctxt->debug_root);
+
 	/* wake threads waiting to submit commands from this context */
 	wake_up_all(&drawctxt->waiting);
 	wake_up_all(&drawctxt->wq);
@@ -569,7 +571,6 @@
 		gpudev->preemption_context_destroy(context);
 
 	drawctxt = ADRENO_CONTEXT(context);
-	debugfs_remove_recursive(drawctxt->debug_root);
 	kfree(drawctxt);
 }
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 129e99c..9968d8c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -989,7 +989,6 @@
 	 */
 
 	kgsl_process_uninit_sysfs(private);
-	debugfs_remove_recursive(private->debug_root);
 
 	process_release_sync_sources(private);
 
@@ -1001,12 +1000,14 @@
 	list_del(&private->list);
 
 	/*
-	 * Unlock the mutex before releasing the memory - this prevents a
-	 * deadlock with the IOMMU mutex if a page fault occurs
+	 * Unlock the mutex before releasing the memory and the debugfs
+	 * nodes - this prevents deadlocks with the IOMMU and debugfs
+	 * locks.
 	 */
 	mutex_unlock(&kgsl_driver.process_mutex);
 
 	process_release_memory(private);
+	debugfs_remove_recursive(private->debug_root);
 
 	kgsl_process_private_put(private);
 }
@@ -1925,12 +1926,13 @@
 	return ret;
 }
 
-static void gpuobj_free_fence_func(void *priv)
+static bool gpuobj_free_fence_func(void *priv)
 {
 	struct kgsl_mem_entry *entry = priv;
 
 	INIT_WORK(&entry->work, _deferred_put);
 	queue_work(kgsl_driver.mem_workqueue, &entry->work);
+	return true;
 }
 
 static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv,
@@ -4645,6 +4647,7 @@
 		device->id, device->reg_phys, device->reg_len);
 
 	rwlock_init(&device->context_lock);
+	spin_lock_init(&device->submit_lock);
 
 	setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device);
 
@@ -4788,6 +4791,8 @@
 static int __init kgsl_core_init(void)
 {
 	int result = 0;
+	struct sched_param param = { .sched_priority = 2 };
+
 	/* alloc major and minor device numbers */
 	result = alloc_chrdev_region(&kgsl_driver.major, 0, KGSL_DEVICE_MAX,
 		"kgsl");
@@ -4854,6 +4859,18 @@
 	kgsl_driver.mem_workqueue = alloc_workqueue("kgsl-mementry",
 		WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
 
+	kthread_init_worker(&kgsl_driver.worker);
+
+	kgsl_driver.worker_thread = kthread_run(kthread_worker_fn,
+		&kgsl_driver.worker, "kgsl_worker_thread");
+
+	if (IS_ERR(kgsl_driver.worker_thread)) {
+		pr_err("unable to start kgsl thread\n");
+		goto err;
+	}
+
+	sched_setscheduler(kgsl_driver.worker_thread, SCHED_FIFO, &param);
+
 	kgsl_events_init();
 
 	result = kgsl_drawobjs_cache_init();
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index c54e51e..f80da79 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -25,6 +25,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
+#include <linux/kthread.h>
 #include <asm/cacheflush.h>
 
 /*
@@ -151,6 +152,8 @@
 	unsigned int full_cache_threshold;
 	struct workqueue_struct *workqueue;
 	struct workqueue_struct *mem_workqueue;
+	struct kthread_worker worker;
+	struct task_struct *worker_thread;
 };
 
 extern struct kgsl_driver kgsl_driver;
@@ -300,7 +303,7 @@
 	void *priv;
 	struct list_head node;
 	unsigned int created;
-	struct work_struct work;
+	struct kthread_work work;
 	int result;
 	struct kgsl_event_group *group;
 };
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index b621ada..6bad70b 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -269,6 +269,11 @@
 	struct kgsl_pwrctrl pwrctrl;
 	int open_count;
 
+	/* For GPU inline submission */
+	uint32_t submit_now;
+	spinlock_t submit_lock;
+	bool slumber;
+
 	struct mutex mutex;
 	uint32_t state;
 	uint32_t requested_state;
@@ -664,9 +669,14 @@
 
 static inline int kgsl_state_is_awake(struct kgsl_device *device)
 {
+	struct gmu_device *gmu = &device->gmu;
+
 	if (device->state == KGSL_STATE_ACTIVE ||
 		device->state == KGSL_STATE_AWARE)
 		return true;
+	else if (kgsl_gmu_isenabled(device) &&
+			test_bit(GMU_CLK_ON, &gmu->flags))
+		return true;
 	else
 		return false;
 }
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index bca3d57..3dbaea4 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.c
@@ -158,10 +158,13 @@
 }
 
 /*
- * a generic function to retire a pending sync event and (possibly)
- * kick the dispatcher
+ * a generic function to retire a pending sync event and (possibly) kick the
+ * dispatcher.
+ * Returns false if the event was already marked for cancellation in another
+ * thread. This function should return true if this thread is responsible for
+ * freeing up the memory, and the event will not be cancelled.
  */
-static void drawobj_sync_expire(struct kgsl_device *device,
+static bool drawobj_sync_expire(struct kgsl_device *device,
 	struct kgsl_drawobj_sync_event *event)
 {
 	struct kgsl_drawobj_sync *syncobj = event->syncobj;
@@ -170,7 +173,7 @@
 	 * leave without doing anything useful
 	 */
 	if (!test_and_clear_bit(event->id, &syncobj->pending))
-		return;
+		return false;
 
 	/*
 	 * If no more pending events, delete the timer and schedule the command
@@ -183,6 +186,7 @@
 			device->ftbl->drawctxt_sched(device,
 				event->syncobj->base.context);
 	}
+	return true;
 }
 
 /*
@@ -228,18 +232,23 @@
 static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
 {
 	struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj);
-	unsigned long pending;
+	unsigned long pending = 0;
 	unsigned int i;
 
 	/* Zap the canary timer */
 	del_timer_sync(&syncobj->timer);
 
 	/*
-	 * Copy off the pending list and clear all pending events - this will
-	 * render any subsequent asynchronous callback harmless
+	 * Copy off the pending list and clear each pending event atomically -
+	 * this will render any subsequent asynchronous callback harmless.
+	 * This marks each event for deletion. If any pending fence callbacks
+	 * run between now and the actual cancel, the associated structures
+	 * are kfreed only in the cancel call.
 	 */
-	bitmap_copy(&pending, &syncobj->pending, KGSL_MAX_SYNCPOINTS);
-	bitmap_zero(&syncobj->pending, KGSL_MAX_SYNCPOINTS);
+	for_each_set_bit(i, &syncobj->pending, KGSL_MAX_SYNCPOINTS) {
+		if (test_and_clear_bit(i, &syncobj->pending))
+			__set_bit(i, &pending);
+	}
 
 	/*
 	 * Clear all pending events - this will render any subsequent async
@@ -259,8 +268,8 @@
 				drawobj_sync_func, event);
 			break;
 		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
-			if (kgsl_sync_fence_async_cancel(event->handle))
-				kgsl_drawobj_put(drawobj);
+			kgsl_sync_fence_async_cancel(event->handle);
+			kgsl_drawobj_put(drawobj);
 			break;
 		}
 	}
@@ -320,15 +329,21 @@
 }
 EXPORT_SYMBOL(kgsl_drawobj_destroy);
 
-static void drawobj_sync_fence_func(void *priv)
+static bool drawobj_sync_fence_func(void *priv)
 {
 	struct kgsl_drawobj_sync_event *event = priv;
 
 	trace_syncpoint_fence_expire(event->syncobj, event->fence_name);
 
-	drawobj_sync_expire(event->device, event);
-
-	kgsl_drawobj_put(&event->syncobj->base);
+	/*
+	 * Only call kgsl_drawobj_put() if it's not marked for cancellation
+	 * in another thread.
+	 */
+	if (drawobj_sync_expire(event->device, event)) {
+		kgsl_drawobj_put(&event->syncobj->base);
+		return true;
+	}
+	return false;
 }
 
 /* drawobj_add_sync_fence() - Add a new sync fence syncpoint
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index d042f05..759a966 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -32,7 +32,7 @@
 {
 	list_del(&event->node);
 	event->result = result;
-	queue_work(device->events_wq, &event->work);
+	kthread_queue_work(&kgsl_driver.worker, &event->work);
 }
 
 /**
@@ -42,7 +42,7 @@
  * Each event callback has its own work struct and is run on a event specific
  * workqeuue.  This is the worker that queues up the event callback function.
  */
-static void _kgsl_event_worker(struct work_struct *work)
+static void _kgsl_event_worker(struct kthread_work *work)
 {
 	struct kgsl_event *event = container_of(work, struct kgsl_event, work);
 	int id = KGSL_CONTEXT_ID(event->context);
@@ -286,7 +286,7 @@
 	event->created = jiffies;
 	event->group = group;
 
-	INIT_WORK(&event->work, _kgsl_event_worker);
+	kthread_init_work(&event->work, _kgsl_event_worker);
 
 	trace_kgsl_register_event(KGSL_CONTEXT_ID(context), timestamp, func);
 
@@ -301,7 +301,7 @@
 
 	if (timestamp_cmp(retired, timestamp) >= 0) {
 		event->result = KGSL_EVENT_RETIRED;
-		queue_work(device->events_wq, &event->work);
+		kthread_queue_work(&kgsl_driver.worker, &event->work);
 		spin_unlock(&group->lock);
 		return 0;
 	}
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index dff46d2..36fdd51 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -505,7 +505,11 @@
 	}
 
 	cmd_db_get_aux_data(res_id, (uint8_t *)arc->val, len);
-	arc->num = len >> 1;
+	for (arc->num = 1; arc->num <= MAX_GX_LEVELS; arc->num++) {
+		if (arc->num == MAX_GX_LEVELS ||
+				arc->val[arc->num - 1] >= arc->val[arc->num])
+			break;
+	}
 
 	return 0;
 }
@@ -528,35 +532,42 @@
 {
 	int i, j, k;
 	uint16_t cur_vlvl;
+	bool found_match;
 
 	/* i tracks current KGSL GPU frequency table entry
 	 * j tracks second rail voltage table entry
 	 * k tracks primary rail voltage table entry
 	 */
-	for (i = 0, k = 0; i < num_entries; k++) {
-		if (pri_rail->val[k] != vlvl[i]) {
-			if (k >= pri_rail->num)
-				return -EINVAL;
-			continue;
-		}
-		votes[i].pri_idx = k;
-		votes[i].vlvl = vlvl[i];
-		cur_vlvl = vlvl[i];
+	for (i = 0; i < num_entries; i++) {
+		found_match = false;
 
-		/* find index of second rail vlvl array element that
-		 * its vlvl >= current vlvl of primary rail
-		 */
-		for (j = 0; j < sec_rail->num; j++) {
-			if (sec_rail->val[j] >= cur_vlvl) {
-				votes[i].sec_idx = j;
+		/* Look for a primary rail voltage that matches a VLVL level */
+		for (k = 0; k < pri_rail->num; k++) {
+			if (pri_rail->val[k] == vlvl[i]) {
+				votes[i].pri_idx = k;
+				votes[i].vlvl = vlvl[i];
+				cur_vlvl = vlvl[i];
+				found_match = true;
 				break;
 			}
 		}
 
-		if (j == sec_rail->num)
-			votes[i].sec_idx = j;
+		/* If we did not find a matching VLVL level then abort */
+		if (!found_match)
+			return -EINVAL;
 
-		i++;
+		/*
+		 * Look for a secondary rail index whose VLVL value
+		 * is greater than or equal to the VLVL value of the
+		 * corresponding index of the primary rail
+		 */
+		for (j = 0; j < sec_rail->num; j++) {
+			if (sec_rail->val[j] >= cur_vlvl ||
+					j + 1 == sec_rail->num) {
+				votes[i].sec_idx = j;
+				break;
+			}
+		}
 	}
 	return 0;
 }
@@ -575,26 +586,25 @@
 		struct rpmh_arc_vals *sec_rail,
 		unsigned int type)
 {
+	struct device *dev;
+	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
 	unsigned int num_freqs;
 	struct arc_vote_desc *votes;
 	unsigned int vlvl_tbl[MAX_GX_LEVELS];
 	unsigned int *freq_tbl;
 	int i, ret;
-	/*
-	 * FIXME: remove below two arrays after OPP VLVL query API ready
-	 * struct dev_pm_opp *opp;
-	 */
-	uint16_t gpu_vlvl[] = {0, 128, 256, 384};
-	uint16_t cx_vlvl[] = {0, 48, 256};
+	struct dev_pm_opp *opp;
 
 	if (type == GPU_ARC_VOTE) {
 		num_freqs = gmu->num_gpupwrlevels;
 		votes = gmu->rpmh_votes.gx_votes;
-		freq_tbl = gmu->gmu_freqs;
+		freq_tbl = gmu->gpu_freqs;
+		dev = &device->pdev->dev;
 	} else if (type == GMU_ARC_VOTE) {
 		num_freqs = gmu->num_gmupwrlevels;
 		votes = gmu->rpmh_votes.cx_votes;
-		freq_tbl = gmu->gpu_freqs;
+		freq_tbl = gmu->gmu_freqs;
+		dev = &gmu->pdev->dev;
 	} else {
 		return -EINVAL;
 	}
@@ -606,26 +616,25 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * FIXME: Find a core's voltage VLVL value based on its frequency
-	 *	using OPP framework, waiting for David Colin, ETA Jan.
-	 */
+	memset(vlvl_tbl, 0, sizeof(vlvl_tbl));
 	for (i = 0; i < num_freqs; i++) {
-		/*
-		 * opp = dev_pm_opp_find_freq_exact(&gmu->pdev->dev,
-		 *		freq_tbl[i], true);
-		 * if (IS_ERR(opp)) {
-		 *	dev_err(&gmu->pdev->dev,
-		 *			"Failed to find opp freq %d of %s\n",
-		 *			freq_tbl[i], debug_strs[type]);
-		 *	return PTR_ERR(opp);
-		 * }
-		 * vlvl_tbl[i] = dev_pm_opp_get_voltage(opp);
-		 */
-		if (type == GPU_ARC_VOTE)
-			vlvl_tbl[i] = gpu_vlvl[i];
-		else
-			vlvl_tbl[i] = cx_vlvl[i];
+		/* Hardcode VLVL for 0 because it is not registered in OPP */
+		if (freq_tbl[i] == 0) {
+			vlvl_tbl[i] = 0;
+			continue;
+		}
+
+		/* Otherwise get the value from the OPP API */
+		opp = dev_pm_opp_find_freq_exact(dev, freq_tbl[i], true);
+		if (IS_ERR(opp)) {
+			dev_err(&gmu->pdev->dev,
+				"Failed to find opp freq %d of %s\n",
+				freq_tbl[i], debug_strs[type]);
+			return PTR_ERR(opp);
+		}
+
+		/* Values from OPP framework are offset by 1 */
+		vlvl_tbl[i] = dev_pm_opp_get_voltage(opp) - 1;
 	}
 
 	ret = setup_volt_dependency_tbl(votes,
@@ -1130,6 +1139,7 @@
 		goto error;
 
 	gmu->num_gpupwrlevels = pwr->num_pwrlevels;
+	gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
 
 	for (i = 0; i < gmu->num_gpupwrlevels; i++) {
 		int j = gmu->num_gpupwrlevels - 1 - i;
@@ -1166,6 +1176,8 @@
 	else
 		gmu->idle_level = GPU_HW_ACTIVE;
 
+	/* disable LM during boot time */
+	clear_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag);
 	return 0;
 
 error:
@@ -1206,20 +1218,11 @@
 
 static int gmu_disable_clks(struct gmu_device *gmu)
 {
-	int ret, j = 0;
-	unsigned int gmu_freq;
+	int j = 0;
 
 	if (IS_ERR_OR_NULL(gmu->clks[0]))
 		return 0;
 
-	gmu_freq = gmu->gmu_freqs[gmu->num_gmupwrlevels - 1];
-	ret = clk_set_rate(gmu->clks[0], gmu_freq);
-	if (ret) {
-		dev_err(&gmu->pdev->dev, "fail to reset GMU clk freq %d\n",
-				gmu_freq);
-		return ret;
-	}
-
 	while ((j < MAX_GMU_CLKS) && gmu->clks[j]) {
 		clk_disable_unprepare(gmu->clks[j]);
 		j++;
@@ -1332,15 +1335,44 @@
 	return 0;
 }
 
+static void gmu_snapshot(struct kgsl_device *device)
+{
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct gmu_device *gmu = &device->gmu;
+
+	if (!test_and_set_bit(GMU_FAULT, &gmu->flags)) {
+		/* Mask so there's no interrupt caused by NMI */
+		adreno_write_gmureg(adreno_dev,
+				ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF);
+
+		/* Make sure the interrupt is masked before causing it */
+		wmb();
+		adreno_write_gmureg(adreno_dev,
+			ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0);
+		adreno_write_gmureg(adreno_dev,
+			ADRENO_REG_GMU_CM3_CFG, (1 << 9));
+
+		/* Wait for the NMI to be handled */
+		wmb();
+		udelay(100);
+		kgsl_device_snapshot(device, NULL);
+
+		adreno_write_gmureg(adreno_dev,
+				ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF);
+		adreno_write_gmureg(adreno_dev,
+				ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+				(unsigned int) ~HFI_IRQ_MASK);
+	}
+}
+
 /* To be called to power on both GPU and GMU */
 int gmu_start(struct kgsl_device *device)
 {
-	int ret = 0, perf_idx;
+	int ret = 0;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	struct gmu_device *gmu = &device->gmu;
-	int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;
 
 	switch (device->state) {
 	case KGSL_STATE_INIT:
@@ -1349,13 +1381,9 @@
 		gmu_enable_gdsc(gmu);
 		gmu_enable_clks(gmu);
 
-		/* Convert to RPMh frequency index */
-		perf_idx = gmu->num_gpupwrlevels -
-				pwr->default_pwrlevel - 1;
-
 		/* Vote for 300MHz DDR for GMU to init */
 		ret = msm_bus_scale_client_update_request(gmu->pcl,
-				bus_level);
+				pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
 		if (ret) {
 			dev_err(&gmu->pdev->dev,
 					"Failed to allocate gmu b/w\n");
@@ -1374,7 +1402,8 @@
 			goto error_gpu;
 
 		/* Send default DCVS level */
-		ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
+		ret = gmu_dcvs_set(gmu, pwr->default_pwrlevel,
+				pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
 		if (ret)
 			goto error_gpu;
 
@@ -1386,8 +1415,6 @@
 		gmu_enable_gdsc(gmu);
 		gmu_enable_clks(gmu);
 
-		perf_idx = gmu->num_gpupwrlevels - gmu->wakeup_pwrlevel - 1;
-
 		ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
 				GMU_WARM_BOOT, 0);
 		if (ret)
@@ -1399,12 +1426,12 @@
 		if (ret)
 			goto error_gpu;
 
-		if (gmu->wakeup_pwrlevel != pwr->default_pwrlevel) {
-			ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
-			if (ret)
-				goto error_gpu;
-			gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
-		}
+		ret = gmu_dcvs_set(gmu, gmu->wakeup_pwrlevel,
+				pwr->pwrlevels[gmu->wakeup_pwrlevel].bus_freq);
+		if (ret)
+			goto error_gpu;
+
+		gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
 		break;
 
 	case KGSL_STATE_RESET:
@@ -1413,11 +1440,6 @@
 			gmu_enable_gdsc(gmu);
 			gmu_enable_clks(gmu);
 
-			perf_idx = gmu->num_gpupwrlevels -
-				pwr->active_pwrlevel - 1;
-
-			bus_level =
-				pwr->pwrlevels[pwr->active_pwrlevel].bus_freq;
 			ret = gpudev->rpmh_gpu_pwrctrl(
 				adreno_dev, GMU_FW_START, GMU_RESET, 0);
 			if (ret)
@@ -1430,7 +1452,9 @@
 				goto error_gpu;
 
 			/* Send DCVS level prior to reset*/
-			ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
+			ret = gmu_dcvs_set(gmu, pwr->active_pwrlevel,
+					pwr->pwrlevels[pwr->active_pwrlevel]
+					.bus_freq);
 			if (ret)
 				goto error_gpu;
 
@@ -1439,19 +1463,13 @@
 				OOB_CPINIT_CHECK_MASK,
 				OOB_CPINIT_CLEAR_MASK);
 
-		} else {
+		} else
 			gmu_fast_boot(device);
-		}
 		break;
 	default:
 		break;
 	}
 
-	/*
-	 * OOB to enable power management of GMU.
-	 * In v2, this function call shall move ahead
-	 * of hfi_start() to save power.
-	 */
 	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
 		gpudev->oob_clear(adreno_dev,
 				OOB_BOOT_SLUMBER_CLEAR_MASK);
@@ -1459,15 +1477,17 @@
 	return ret;
 
 error_gpu:
+	gmu_snapshot(device);
 	hfi_stop(gmu);
 	gmu_irq_disable(device);
-		if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
-			gpudev->oob_clear(adreno_dev,
-					OOB_BOOT_SLUMBER_CLEAR_MASK);
+	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
+		gpudev->oob_clear(adreno_dev,
+				OOB_BOOT_SLUMBER_CLEAR_MASK);
 	gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
 error_bus:
-		msm_bus_scale_client_update_request(gmu->pcl, 0);
+	msm_bus_scale_client_update_request(gmu->pcl, 0);
 error_clks:
+	gmu_snapshot(device);
 	gmu_disable_clks(gmu);
 	gmu_disable_gdsc(gmu);
 	return ret;
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index a741beb..63ca028 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -82,6 +82,7 @@
 	GMU_BOOT_INIT_DONE = 0,
 	GMU_CLK_ON = 1,
 	GMU_HFI_ON = 2,
+	GMU_FAULT = 3
 };
 
 /**
diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c
index cc878aa..68e0f3a 100644
--- a/drivers/gpu/msm/kgsl_hfi.c
+++ b/drivers/gpu/msm/kgsl_hfi.c
@@ -602,15 +602,23 @@
 	if (result)
 		return result;
 
-	/*
-	 * FW is not ready for LM configuration
-	 * without powering on GPU.
-	 */
-	/*
-	 * result = hfi_send_lmconfig(gmu);
-	 * if (result)
-	 * return result;
-	 */
+	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
+		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) {
+		gmu->lm_config.lm_type = 1;
+		gmu->lm_config.lm_sensor_type = 1;
+		gmu->lm_config.throttle_config = 1;
+		gmu->lm_config.idle_throttle_en = 0;
+		gmu->lm_config.acd_en = 0;
+		gmu->bcl_config = 0;
+		gmu->lm_dcvs_level = 0;
+
+		result = hfi_send_lmconfig(gmu);
+		if (result) {
+			dev_err(dev, "Failire enabling limits management (%d)\n",
+				result);
+			return result;
+		}
+	}
 
 	set_bit(GMU_HFI_ON, &gmu->flags);
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c
index c31a85b..685ce3e 100644
--- a/drivers/gpu/msm/kgsl_pool.c
+++ b/drivers/gpu/msm/kgsl_pool.c
@@ -65,26 +65,19 @@
 
 /* Map the page into kernel and zero it out */
 static void
-_kgsl_pool_zero_page(struct page *p, unsigned int pool_order)
+_kgsl_pool_zero_page(struct page *p)
 {
-	int i;
+	void *addr = kmap_atomic(p);
 
-	for (i = 0; i < (1 << pool_order); i++) {
-		struct page *page = nth_page(p, i);
-		void *addr = kmap_atomic(page);
-
-		memset(addr, 0, PAGE_SIZE);
-		dmac_flush_range(addr, addr + PAGE_SIZE);
-		kunmap_atomic(addr);
-	}
+	memset(addr, 0, PAGE_SIZE);
+	dmac_flush_range(addr, addr + PAGE_SIZE);
+	kunmap_atomic(addr);
 }
 
 /* Add a page to specified pool */
 static void
 _kgsl_pool_add_page(struct kgsl_page_pool *pool, struct page *p)
 {
-	_kgsl_pool_zero_page(p, pool->pool_order);
-
 	spin_lock(&pool->list_lock);
 	list_add_tail(&p->lru, &pool->page_list);
 	pool->page_count++;
@@ -329,7 +322,6 @@
 			} else
 				return -ENOMEM;
 		}
-		_kgsl_pool_zero_page(page, order);
 		goto done;
 	}
 
@@ -349,7 +341,6 @@
 			page = alloc_pages(gfp_mask, order);
 			if (page == NULL)
 				return -ENOMEM;
-			_kgsl_pool_zero_page(page, order);
 			goto done;
 		}
 	}
@@ -379,13 +370,12 @@
 			} else
 				return -ENOMEM;
 		}
-
-		_kgsl_pool_zero_page(page, order);
 	}
 
 done:
 	for (j = 0; j < (*page_size >> PAGE_SHIFT); j++) {
 		p = nth_page(page, j);
+		_kgsl_pool_zero_page(p);
 		pages[pcount] = p;
 		pcount++;
 	}
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 5c53a05c..6fd6a05 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -224,7 +224,7 @@
 {
 	struct gmu_device *gmu = &device->gmu;
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
-	int ret;
+	int ret = 0;
 
 	/* GMU scales BW */
 	if (kgsl_gmu_isenabled(device)) {
@@ -232,7 +232,7 @@
 			return 0;
 
 		ret = gmu_dcvs_set(gmu, INVALID_DCVS_IDX, buslevel);
-	} else {
+	} else if (pwr->pcl) {
 		/* Linux bus driver scales BW */
 		ret = msm_bus_scale_client_update_request(pwr->pcl, buslevel);
 	}
@@ -253,23 +253,30 @@
 {
 	struct gmu_device *gmu = &device->gmu;
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	struct kgsl_pwrlevel *pl = &pwr->pwrlevels[pwrlevel];
 	int ret = 0;
 
 	/* GMU scales GPU freq */
 	if (kgsl_gmu_isenabled(device)) {
 		/* If GMU has not been started, save it */
 		if (!(gmu->flags & GMU_HFI_ON)) {
+			/* In slumber the clock is off so we are done */
+			if (pwrlevel == (gmu->num_gpupwrlevels - 1))
+				return 0;
+
 			gmu->wakeup_pwrlevel = pwrlevel;
 			return 0;
 		}
 
+		/* If the GMU is on we cannot vote for the lowest level */
+		if (pwrlevel == (gmu->num_gpupwrlevels - 1)) {
+			WARN(1, "Cannot set 0 GPU frequency with GMU\n");
+			return -EINVAL;
+		}
 		ret = gmu_dcvs_set(gmu, pwrlevel, INVALID_DCVS_IDX);
-	} else {
+	} else
 		/* Linux clock driver scales GPU freq */
-		struct kgsl_pwrlevel *Pl = &pwr->pwrlevels[pwrlevel];
-
-		ret = clk_set_rate(pwr->grp_clks[0], Pl->gpu_freq);
-	}
+		ret = clk_set_rate(pwr->grp_clks[0], pl->gpu_freq);
 
 	if (ret)
 		KGSL_PWR_ERR(device, "GPU clk freq set failure\n");
@@ -291,7 +298,8 @@
 	unsigned long ab;
 
 	/* the bus should be ON to update the active frequency */
-	if (on && !(test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)))
+	if (!(kgsl_gmu_isenabled(device)) && on &&
+		!(test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)))
 		return;
 	/*
 	 * If the bus should remain on calculate our request and submit it,
@@ -321,9 +329,7 @@
 		msm_bus_scale_client_update_request(pwr->ocmem_pcl,
 			on ? pwr->active_pwrlevel : pwr->num_pwrlevels - 1);
 
-	/* vote for bus if gpubw-dev support is not enabled */
-	if (pwr->pcl)
-		kgsl_bus_scale_request(device, buslevel);
+	kgsl_bus_scale_request(device, buslevel);
 
 	kgsl_pwrctrl_vbif_update(ab);
 }
@@ -1049,6 +1055,8 @@
 	if (on) {
 		switch (flag) {
 		case KGSL_PWRFLAGS_CLK_ON:
+			/* make sure pwrrail is ON before enabling clocks */
+			kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON);
 			kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON,
 				KGSL_STATE_ACTIVE);
 			break;
@@ -1784,8 +1792,6 @@
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 
-	if (kgsl_gmu_isenabled(device))
-		return;
 	if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->ctrl_flags))
 		return;
 
@@ -1854,7 +1860,12 @@
 
 	if (kgsl_gmu_isenabled(device))
 		return 0;
-	if (test_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->ctrl_flags))
+	/*
+	 * Disabling the regulator means also disabling dependent clocks.
+	 * Hence don't disable it if force clock ON is set.
+	 */
+	if (test_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->ctrl_flags) ||
+		test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->ctrl_flags))
 		return 0;
 
 	if (state == KGSL_PWRFLAGS_OFF) {
@@ -2362,9 +2373,24 @@
 		   || device->state ==  KGSL_STATE_NAP) {
 
 		if (!atomic_read(&device->active_cnt)) {
+			spin_lock(&device->submit_lock);
+			if (device->submit_now) {
+				spin_unlock(&device->submit_lock);
+				goto done;
+			}
+			/* Don't allow GPU inline submission in SLUMBER */
+			if (requested_state == KGSL_STATE_SLUMBER)
+				device->slumber = true;
+			spin_unlock(&device->submit_lock);
+
 			ret = kgsl_pwrctrl_change_state(device,
 					device->requested_state);
 			if (ret == -EBUSY) {
+				if (requested_state == KGSL_STATE_SLUMBER) {
+					spin_lock(&device->submit_lock);
+					device->slumber = false;
+					spin_unlock(&device->submit_lock);
+				}
 				/*
 				 * If the GPU is currently busy, restore
 				 * the requested state and reschedule
@@ -2375,7 +2401,7 @@
 				kgsl_schedule_work(&device->idle_check_ws);
 			}
 		}
-
+done:
 		if (!ret)
 			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
 
@@ -2449,8 +2475,13 @@
 
 	kgsl_pwrctrl_pwrlevel_change(device, level);
 
-	if (kgsl_gmu_isenabled(device))
-		return gmu_start(device);
+	if (kgsl_gmu_isenabled(device)) {
+		int ret = gmu_start(device);
+
+		if (!ret)
+			kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
+		return ret;
+	}
 
 	/* Order pwrrail/clk sequence based upon platform */
 	status = kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON);
@@ -2463,8 +2494,10 @@
 
 static void kgsl_pwrctrl_disable(struct kgsl_device *device)
 {
-	if (kgsl_gmu_isenabled(device))
+	if (kgsl_gmu_isenabled(device)) {
+		kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
 		return gmu_stop(device);
+	}
 
 	/* Order pwrrail/clk sequence based upon platform */
 	device->ftbl->regulator_disable(device);
@@ -2835,6 +2868,13 @@
 	trace_kgsl_pwr_set_state(device, state);
 	device->state = state;
 	device->requested_state = KGSL_STATE_NONE;
+
+	spin_lock(&device->submit_lock);
+	if (state == KGSL_STATE_SLUMBER || state == KGSL_STATE_SUSPEND)
+		device->slumber = true;
+	else
+		device->slumber = false;
+	spin_unlock(&device->submit_lock);
 }
 
 static void kgsl_pwrctrl_request_state(struct kgsl_device *device,
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index f0f202b..5061f6a 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -741,6 +741,8 @@
 	 */
 
 	memdesc->pages = kgsl_malloc(len_alloc * sizeof(struct page *));
+	memdesc->page_count = 0;
+	memdesc->size = 0;
 
 	if (memdesc->pages == NULL) {
 		ret = -ENOMEM;
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index d75ec9d..015d07f 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -428,9 +428,14 @@
 {
 	struct kgsl_sync_fence_cb *kcb = (struct kgsl_sync_fence_cb *)cb;
 
-	kcb->func(kcb->priv);
-	fence_put(kcb->fence);
-	kfree(kcb);
+	/*
+	 * If the callback is marked for cancellation in a separate thread,
+	 * let the other thread do the cleanup.
+	 */
+	if (kcb->func(kcb->priv)) {
+		fence_put(kcb->fence);
+		kfree(kcb);
+	}
 }
 
 static void kgsl_get_fence_name(struct fence *fence,
@@ -453,7 +458,7 @@
 }
 
 struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
-	void (*func)(void *priv), void *priv, char *fence_name, int name_len)
+	bool (*func)(void *priv), void *priv, char *fence_name, int name_len)
 {
 	struct kgsl_sync_fence_cb *kcb;
 	struct fence *fence;
@@ -493,17 +498,24 @@
 	return kcb;
 }
 
-int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb)
+/*
+ * Cancel the fence async callback and do the cleanup. The caller must make
+ * sure that the callback (if run before cancelling) returns false, so that
+ * no other thread frees the pointer.
+ */
+void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb)
 {
 	if (kcb == NULL)
-		return 0;
+		return;
 
-	if (fence_remove_callback(kcb->fence, &kcb->fence_cb)) {
-		fence_put(kcb->fence);
-		kfree(kcb);
-		return 1;
-	}
-	return 0;
+	/*
+	 * After fence_remove_callback() returns, the fence callback is
+	 * either not called at all, or completed without freeing kcb.
+	 * This thread can then put the fence refcount and free kcb.
+	 */
+	fence_remove_callback(kcb->fence, &kcb->fence_cb);
+	fence_put(kcb->fence);
+	kfree(kcb);
 }
 
 struct kgsl_syncsource {
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index 99fe0e1..d58859d 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -68,13 +68,14 @@
  * fence_cb: Fence callback struct
  * fence: Pointer to the fence for which the callback is done
  * priv: Private data for the callback
- * func: Pointer to the kgsl function to call
+ * func: Pointer to the kgsl function to call. This function should return
+ * false if the sync callback is marked for cancellation in a separate thread.
  */
 struct kgsl_sync_fence_cb {
 	struct fence_cb fence_cb;
 	struct fence *fence;
 	void *priv;
-	void (*func)(void *priv);
+	bool (*func)(void *priv);
 };
 
 struct kgsl_syncsource;
@@ -91,10 +92,10 @@
 void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline);
 
 struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
-					void (*func)(void *priv), void *priv,
+					bool (*func)(void *priv), void *priv,
 					char *fence_name, int name_len);
 
-int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
+void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
 
 long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv,
 					unsigned int cmd, void *data);
@@ -143,10 +144,9 @@
 	return NULL;
 }
 
-static inline int
+static inline void
 kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb)
 {
-	return 1;
 }
 
 static inline long
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 1767810..c7690a1 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -820,14 +820,14 @@
 
 TRACE_EVENT(kgsl_mmu_pagefault,
 
-	TP_PROTO(struct kgsl_device *device, unsigned int page,
+	TP_PROTO(struct kgsl_device *device, unsigned long page,
 		 unsigned int pt, const char *op),
 
 	TP_ARGS(device, page, pt, op),
 
 	TP_STRUCT__entry(
 		__string(device_name, device->name)
-		__field(unsigned int, page)
+		__field(unsigned long, page)
 		__field(unsigned int, pt)
 		__string(op, op)
 	),
@@ -840,7 +840,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s page=0x%08x pt=%u op=%s",
+		"d_name=%s page=0x%lx pt=%u op=%s",
 		__get_str(device_name), __entry->page, __entry->pt,
 		__get_str(op)
 	)
diff --git a/drivers/hwtracing/coresight/coresight-ost.c b/drivers/hwtracing/coresight/coresight-ost.c
index 63fea00..3399c27 100644
--- a/drivers/hwtracing/coresight/coresight-ost.c
+++ b/drivers/hwtracing/coresight/coresight-ost.c
@@ -12,6 +12,7 @@
 
 #include <linux/device.h>
 #include <linux/bitmap.h>
+#include <linux/io.h>
 #include "coresight-ost.h"
 
 #define STM_USERSPACE_HEADER_SIZE	(8)
@@ -54,19 +55,40 @@
 	return ch;
 }
 
-static int stm_ost_send(void *addr, const void *data, uint32_t count)
+static int stm_ost_send(void __iomem *addr, const void *data, uint32_t size)
 {
-	struct stm_drvdata *drvdata = stmdrvdata;
-	const unsigned char *p = data;
-	size_t pos;
-	ssize_t sz;
+	uint32_t len = size;
 
-	for (pos = 0, p = data; count > pos; pos += sz, p += sz) {
-		sz = min_t(unsigned int, count - pos, drvdata->write_bytes);
-		stm_send(addr, p, sz, drvdata->write_bytes);
+	if (((unsigned long)data & 0x1) && (size >= 1)) {
+		writeb_relaxed_no_log(*(uint8_t *)data, addr);
+		data++;
+		size--;
+	}
+	if (((unsigned long)data & 0x2) && (size >= 2)) {
+		writew_relaxed_no_log(*(uint16_t *)data, addr);
+		data += 2;
+		size -= 2;
 	}
 
-	return count;
+	/* now we are 32bit aligned */
+	while (size >= 4) {
+		writel_relaxed_no_log(*(uint32_t *)data, addr);
+		data += 4;
+		size -= 4;
+	}
+
+	if (size >= 2) {
+		writew_relaxed_no_log(*(uint16_t *)data, addr);
+		data += 2;
+		size -= 2;
+	}
+	if (size >= 1) {
+		writeb_relaxed_no_log(*(uint8_t *)data, addr);
+		data++;
+		size--;
+	}
+
+	return len;
 }
 
 static void stm_channel_free(uint32_t ch)
@@ -76,10 +98,10 @@
 	clear_bit(ch, drvdata->chs.bitmap);
 }
 
-static int stm_trace_ost_header(unsigned long ch_addr, uint32_t flags,
+static int stm_trace_ost_header(void __iomem *ch_addr, uint32_t flags,
 				uint8_t entity_id, uint8_t proto_id)
 {
-	void *addr;
+	void __iomem *addr;
 	uint32_t header;
 	char *hdr;
 
@@ -93,12 +115,13 @@
 	/* header is expected to be D32M type */
 	flags |= STM_FLAG_MARKED;
 	flags &= ~STM_FLAG_TIMESTAMPED;
-	addr =  (void *)(ch_addr | stm_channel_off(STM_PKT_TYPE_DATA, flags));
+	addr = (void __iomem *)(ch_addr +
+		stm_channel_off(STM_PKT_TYPE_DATA, flags));
 
 	return stm_ost_send(addr, &header, sizeof(header));
 }
 
-static int stm_trace_data_header(void *addr)
+static int stm_trace_data_header(void __iomem *addr)
 {
 	char hdr[16];
 	int len = 0;
@@ -114,14 +137,15 @@
 	return len;
 }
 
-static int stm_trace_data(unsigned long ch_addr, uint32_t flags,
+static int stm_trace_data(void __iomem *ch_addr, uint32_t flags,
 			  const void *data, uint32_t size)
 {
-	void *addr;
+	void __iomem *addr;
 	int len = 0;
 
 	flags &= ~STM_FLAG_TIMESTAMPED;
-	addr = (void *)(ch_addr | stm_channel_off(STM_PKT_TYPE_DATA, flags));
+	addr = (void __iomem *)(ch_addr +
+		stm_channel_off(STM_PKT_TYPE_DATA, flags));
 
 	/* send the data header */
 	len += stm_trace_data_header(addr);
@@ -131,12 +155,13 @@
 	return len;
 }
 
-static int stm_trace_ost_tail(unsigned long ch_addr, uint32_t flags)
+static int stm_trace_ost_tail(void __iomem *ch_addr, uint32_t flags)
 {
-	void *addr;
+	void __iomem *addr;
 	uint32_t tail = 0x0;
 
-	addr = (void *)(ch_addr | stm_channel_off(STM_PKT_TYPE_FLAG, flags));
+	addr = (void __iomem *)(ch_addr +
+		stm_channel_off(STM_PKT_TYPE_FLAG, flags));
 
 	return stm_ost_send(addr, &tail, sizeof(tail));
 }
@@ -147,7 +172,7 @@
 	struct stm_drvdata *drvdata = stmdrvdata;
 	int len = 0;
 	uint32_t ch;
-	unsigned long ch_addr;
+	void __iomem *ch_addr;
 
 	/* allocate channel and get the channel address */
 	ch = stm_channel_alloc();
@@ -159,7 +184,7 @@
 		return 0;
 	}
 
-	ch_addr = (unsigned long)stm_channel_addr(drvdata, ch);
+	ch_addr = (void __iomem *)stm_channel_addr(drvdata, ch);
 
 	/* send the ost header */
 	len += stm_trace_ost_header(ch_addr, flags, entity_id,
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index c8f2702e..159512c 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -211,6 +211,7 @@
 	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
 		spin_lock(&drvdata->spinlock);
 		stm_disable_hw(drvdata);
+		drvdata->enable = false;
 		spin_unlock(&drvdata->spinlock);
 
 		/* Wait until the engine has completely stopped */
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index d6941ea..85fe87f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -171,8 +171,11 @@
 	if (!used)
 		kfree(buf);
 
-	if (!ret)
+	if (!ret) {
+		coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
+		coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
 		dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
+	}
 
 	return ret;
 }
@@ -244,6 +247,9 @@
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+	coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
+	coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0);
+
 	dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
 }
 
@@ -521,11 +527,13 @@
 		goto out;
 	}
 
-	/* There is no point in reading a TMC in HW FIFO mode */
-	mode = readl_relaxed(drvdata->base + TMC_MODE);
-	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-		ret = -EINVAL;
-		goto out;
+	if (drvdata->enable) {
+		/* There is no point in reading a TMC in HW FIFO mode */
+		mode = readl_relaxed(drvdata->base + TMC_MODE);
+		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+			ret = -EINVAL;
+			goto out;
+		}
 	}
 
 	val = local_read(&drvdata->mode);
@@ -565,11 +573,13 @@
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
-	/* There is no point in reading a TMC in HW FIFO mode */
-	mode = readl_relaxed(drvdata->base + TMC_MODE);
-	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		return -EINVAL;
+	if (drvdata->enable) {
+		/* There is no point in reading a TMC in HW FIFO mode */
+		mode = readl_relaxed(drvdata->base + TMC_MODE);
+		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+			spin_unlock_irqrestore(&drvdata->spinlock, flags);
+			return -EINVAL;
+		}
 	}
 
 	/* Re-enable the TMC if need be */
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 9e6f443..eb355f4 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -800,6 +800,8 @@
 			mutex_unlock(&drvdata->mem_lock);
 			return ret;
 		}
+		coresight_cti_map_trigout(drvdata->cti_flush, 3, 0);
+		coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
 	} else {
 		drvdata->usbch = usb_qdss_open("qdss", drvdata,
 					       usb_notifier);
@@ -891,6 +893,7 @@
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
+	mutex_lock(&drvdata->mem_lock);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
 		spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -902,8 +905,10 @@
 	if (val != CS_MODE_DISABLED) {
 		if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
 			__tmc_etr_disable_to_bam(drvdata);
+			spin_unlock_irqrestore(&drvdata->spinlock, flags);
 			tmc_etr_bam_disable(drvdata);
 			usb_qdss_close(drvdata->usbch);
+			goto out;
 		} else {
 			tmc_etr_disable_hw(drvdata);
 		}
@@ -911,6 +916,12 @@
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+	if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
+		coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
+		coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0);
+	}
+out:
+	mutex_unlock(&drvdata->mem_lock);
 	dev_info(drvdata->dev, "TMC-ETR disabled\n");
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 98fcd01..b97ebb8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -361,6 +361,9 @@
 		drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
 		spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+		coresight_cti_map_trigout(drvdata->cti_flush, 3, 0);
+		coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
+
 		tmc_etr_bam_disable(drvdata);
 		usb_qdss_close(drvdata->usbch);
 	} else if (!strcmp(str, str_tmc_etr_out_mode[TMC_ETR_OUT_MODE_USB])) {
@@ -381,6 +384,9 @@
 		drvdata->out_mode = TMC_ETR_OUT_MODE_USB;
 		spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+		coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0);
+		coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
+
 		drvdata->usbch = usb_qdss_open("qdss", drvdata,
 					       usb_notifier);
 		if (IS_ERR(drvdata->usbch)) {
@@ -503,6 +509,7 @@
 	struct resource *res = &adev->res;
 	struct coresight_desc desc = { 0 };
 	struct device_node *np = adev->dev.of_node;
+	struct coresight_cti_data *ctidata;
 
 	pdata = of_get_coresight_platform_data(dev, np);
 	if (IS_ERR(pdata)) {
@@ -554,6 +561,19 @@
 
 	pm_runtime_put(&adev->dev);
 
+	ctidata = of_get_coresight_cti_data(dev, adev->dev.of_node);
+	if (IS_ERR(ctidata)) {
+		dev_err(dev, "invalid cti data\n");
+	} else if (ctidata && ctidata->nr_ctis == 2) {
+		drvdata->cti_flush = coresight_cti_get(ctidata->names[0]);
+		if (IS_ERR(drvdata->cti_flush))
+			dev_err(dev, "failed to get flush cti\n");
+
+		drvdata->cti_reset = coresight_cti_get(ctidata->names[1]);
+		if (IS_ERR(drvdata->cti_reset))
+			dev_err(dev, "failed to get reset cti\n");
+	}
+
 	desc.pdata = pdata;
 	desc.dev = dev;
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index a9de0e8..6643adc 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -25,6 +25,7 @@
 #include <linux/amba/bus.h>
 #include <linux/usb_bam.h>
 #include <linux/usb/usb_qdss.h>
+#include <linux/coresight-cti.h>
 
 #define TMC_RSZ			0x004
 #define TMC_STS			0x00c
@@ -184,7 +185,8 @@
 	struct tmc_etr_bam_data	*bamdata;
 	bool			enable_to_bam;
 	bool			sticky_enable;
-
+	struct coresight_cti	*cti_flush;
+	struct coresight_cti	*cti_reset;
 };
 
 /* Generic functions */
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 946e0ba..91e7b0c 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -26,6 +26,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/qcom-geni-se.h>
 #include <linux/ipc_logging.h>
+#include <linux/dmaengine.h>
+#include <linux/msm_gpi.h>
 
 #define SE_I2C_TX_TRANS_LEN		(0x26C)
 #define SE_I2C_RX_TRANS_LEN		(0x270)
@@ -54,6 +56,7 @@
 #define SLV_ADDR_MSK		(GENMASK(15, 9))
 #define SLV_ADDR_SHFT		(9)
 
+#define I2C_PACK_EN		(BIT(0) | BIT(1))
 #define I2C_CORE2X_VOTE		(10000)
 #define GP_IRQ0			0
 #define GP_IRQ1			1
@@ -71,6 +74,12 @@
 #define I2C_ARB_LOST		GP_IRQ4
 #define DM_I2C_RX_ERR		((GP_IRQ1 | GP_IRQ3 | GP_IRQ4) >> 4)
 
+enum i2c_se_mode {
+	UNINITIALIZED,
+	FIFO_SE_DMA,
+	GSI_ONLY,
+};
+
 struct geni_i2c_dev {
 	struct device *dev;
 	void __iomem *base;
@@ -86,6 +95,24 @@
 	struct device *wrapper_dev;
 	void *ipcl;
 	int clk_fld_idx;
+	struct dma_chan *tx_c;
+	struct dma_chan *rx_c;
+	struct msm_gpi_tre cfg0_t;
+	struct msm_gpi_tre go_t;
+	struct msm_gpi_tre tx_t;
+	struct msm_gpi_tre rx_t;
+	dma_addr_t tx_ph;
+	dma_addr_t rx_ph;
+	struct msm_gpi_ctrl tx_ev;
+	struct msm_gpi_ctrl rx_ev;
+	struct scatterlist tx_sg[5]; /* lock, cfg0, go, TX, unlock */
+	struct scatterlist rx_sg;
+	int cfg_sent;
+	struct dma_async_tx_descriptor *tx_desc;
+	struct dma_async_tx_descriptor *rx_desc;
+	struct msm_gpi_dma_async_tx_cb_param tx_cb;
+	struct msm_gpi_dma_async_tx_cb_param rx_cb;
+	enum i2c_se_mode se_mode;
 };
 
 struct geni_i2c_err_log {
@@ -184,6 +211,9 @@
 		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s\n",
 			     gi2c_log[err].msg);
 	}
+	if (gi2c->se_mode == GSI_ONLY)
+		goto err_out;
+
 	if (dma) {
 		rx_st = readl_relaxed(gi2c->base + SE_DMA_RX_IRQ_STAT);
 		tx_st = readl_relaxed(gi2c->base + SE_DMA_TX_IRQ_STAT);
@@ -194,6 +224,7 @@
 	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
 		     "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
 		     dma, tx_st, rx_st, m_stat);
+err_out:
 	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
 			     "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
 			     m_cmd, geni_s, geni_ios);
@@ -305,6 +336,258 @@
 	return IRQ_HANDLED;
 }
 
+static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str,
+		       void *ptr)
+{
+	struct geni_i2c_dev *gi2c = ptr;
+	u32 m_stat = cb_str->status;
+
+	switch (cb_str->cb_event) {
+	case MSM_GPI_QUP_ERROR:
+	case MSM_GPI_QUP_SW_ERROR:
+	case MSM_GPI_QUP_MAX_EVENT:
+		/* fall through to stall impacted channel */
+	case MSM_GPI_QUP_CH_ERROR:
+	case MSM_GPI_QUP_PENDING_EVENT:
+	case MSM_GPI_QUP_EOT_DESC_MISMATCH:
+		break;
+	case MSM_GPI_QUP_NOTIFY:
+		if (m_stat & M_GP_IRQ_1_EN)
+			geni_i2c_err(gi2c, I2C_NACK);
+		if (m_stat & M_GP_IRQ_3_EN)
+			geni_i2c_err(gi2c, I2C_BUS_PROTO);
+		if (m_stat & M_GP_IRQ_4_EN)
+			geni_i2c_err(gi2c, I2C_ARB_LOST);
+		complete(&gi2c->xfer);
+		break;
+	default:
+		break;
+	}
+	if (cb_str->cb_event != MSM_GPI_QUP_NOTIFY)
+		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				"GSI QN err:0x%x, status:0x%x, err:%d\n",
+				cb_str->error_log.error_code,
+				m_stat, cb_str->cb_event);
+}
+
+static void gi2c_gsi_tx_cb(void *ptr)
+{
+	struct msm_gpi_dma_async_tx_cb_param *tx_cb = ptr;
+	struct geni_i2c_dev *gi2c = tx_cb->userdata;
+
+	if (!(gi2c->cur->flags & I2C_M_RD))
+		complete(&gi2c->xfer);
+}
+
+static void gi2c_gsi_rx_cb(void *ptr)
+{
+	struct msm_gpi_dma_async_tx_cb_param *rx_cb = ptr;
+	struct geni_i2c_dev *gi2c = rx_cb->userdata;
+
+	if (gi2c->cur->flags & I2C_M_RD) {
+		if (rx_cb->status & DM_I2C_RX_ERR) {
+			GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+				    "RX TCE Unexpected Err, stat:0x%x\n",
+				    rx_cb->status);
+			if (rx_cb->status & GP_IRQ1)
+				geni_i2c_err(gi2c, I2C_NACK);
+			if (rx_cb->status & GP_IRQ3)
+				geni_i2c_err(gi2c, I2C_BUS_PROTO);
+			if (rx_cb->status & GP_IRQ4)
+				geni_i2c_err(gi2c, I2C_ARB_LOST);
+		}
+		complete(&gi2c->xfer);
+	}
+}
+
+static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			     int num)
+{
+	struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap);
+	int i, ret = 0, timeout = 0;
+
+	if (!gi2c->tx_c) {
+		gi2c->tx_c = dma_request_slave_channel(gi2c->dev, "tx");
+		if (!gi2c->tx_c) {
+			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				    "tx dma req slv chan ret :%d\n", ret);
+			return -EIO;
+		}
+		gi2c->tx_ev.init.callback = gi2c_ev_cb;
+		gi2c->tx_ev.init.cb_param = gi2c;
+		gi2c->tx_ev.cmd = MSM_GPI_INIT;
+		gi2c->tx_c->private = &gi2c->tx_ev;
+		ret = dmaengine_slave_config(gi2c->tx_c, NULL);
+		if (ret) {
+			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				    "tx dma slave config ret :%d\n", ret);
+			return ret;
+		}
+	}
+	if (!gi2c->rx_c) {
+		gi2c->rx_c = dma_request_slave_channel(gi2c->dev, "rx");
+		if (!gi2c->rx_c) {
+			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				    "rx dma req slv chan ret :%d\n", ret);
+			return -EIO;
+		}
+		gi2c->rx_ev.init.cb_param = gi2c;
+		gi2c->rx_ev.init.callback = gi2c_ev_cb;
+		gi2c->rx_ev.cmd = MSM_GPI_INIT;
+		gi2c->rx_c->private = &gi2c->rx_ev;
+		ret = dmaengine_slave_config(gi2c->rx_c, NULL);
+		if (ret) {
+			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				    "rx dma slave config ret :%d\n", ret);
+			return ret;
+		}
+	}
+
+	if (!gi2c->cfg_sent) {
+		struct geni_i2c_clk_fld *itr = geni_i2c_clk_map +
+							gi2c->clk_fld_idx;
+		struct msm_gpi_tre *cfg0 = &gi2c->cfg0_t;
+
+		/* config0 */
+		cfg0->dword[0] = MSM_GPI_I2C_CONFIG0_TRE_DWORD0(I2C_PACK_EN,
+								itr->t_cycle,
+								itr->t_high,
+								itr->t_low);
+		cfg0->dword[1] = MSM_GPI_I2C_CONFIG0_TRE_DWORD1(0, 0);
+		cfg0->dword[2] = MSM_GPI_I2C_CONFIG0_TRE_DWORD2(0,
+								itr->clk_div);
+		cfg0->dword[3] = MSM_GPI_I2C_CONFIG0_TRE_DWORD3(0, 0, 0, 1);
+
+		gi2c->tx_cb.userdata = gi2c;
+		gi2c->rx_cb.userdata = gi2c;
+	}
+
+	for (i = 0; i < num; i++) {
+		u8 op = (msgs[i].flags & I2C_M_RD) ? 2 : 1;
+		int segs = 3 - op;
+		int index = 0;
+		int stretch = (i < (num - 1));
+		dma_cookie_t tx_cookie, rx_cookie;
+		struct msm_gpi_tre *go_t = &gi2c->go_t;
+		struct device *rx_dev = gi2c->rx_c->device->dev;
+		struct device *tx_dev = gi2c->tx_c->device->dev;
+
+		gi2c->cur = &msgs[i];
+		if (!gi2c->cfg_sent) {
+			segs++;
+			sg_init_table(gi2c->tx_sg, segs);
+			sg_set_buf(gi2c->tx_sg, &gi2c->cfg0_t,
+						sizeof(gi2c->cfg0_t));
+			gi2c->cfg_sent = 1;
+			index++;
+		} else {
+			sg_init_table(gi2c->tx_sg, segs);
+		}
+
+		go_t->dword[0] = MSM_GPI_I2C_GO_TRE_DWORD0((stretch << 2),
+							   msgs[i].addr, op);
+		go_t->dword[1] = MSM_GPI_I2C_GO_TRE_DWORD1;
+
+		if (msgs[i].flags & I2C_M_RD) {
+			go_t->dword[2] = MSM_GPI_I2C_GO_TRE_DWORD2(msgs[i].len);
+			go_t->dword[3] = MSM_GPI_I2C_GO_TRE_DWORD3(0, 0, 1, 0);
+		} else {
+			go_t->dword[2] = MSM_GPI_I2C_GO_TRE_DWORD2(0);
+			go_t->dword[3] = MSM_GPI_I2C_GO_TRE_DWORD3(0, 0, 0, 1);
+		}
+
+		sg_set_buf(&gi2c->tx_sg[index++], &gi2c->go_t,
+						  sizeof(gi2c->go_t));
+
+		if (msgs[i].flags & I2C_M_RD) {
+			sg_init_table(&gi2c->rx_sg, 1);
+			gi2c->rx_ph = dma_map_single(rx_dev, msgs[i].buf,
+						     msgs[i].len,
+						     DMA_FROM_DEVICE);
+			gi2c->rx_t.dword[0] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(gi2c->rx_ph);
+			gi2c->rx_t.dword[1] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD1(gi2c->rx_ph);
+			gi2c->rx_t.dword[2] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD2(msgs[i].len);
+			gi2c->rx_t.dword[3] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD3(0, 1, 0, 0);
+
+			sg_set_buf(&gi2c->rx_sg, &gi2c->rx_t,
+						 sizeof(gi2c->rx_t));
+			gi2c->rx_desc = dmaengine_prep_slave_sg(gi2c->rx_c,
+							&gi2c->rx_sg, 1,
+							DMA_DEV_TO_MEM,
+							(DMA_PREP_INTERRUPT |
+							 DMA_CTRL_ACK));
+			if (!gi2c->rx_desc) {
+				GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+					    "prep_slave_sg for rx failed\n");
+				gi2c->err = -ENOMEM;
+				return gi2c->err;
+			}
+			gi2c->rx_desc->callback = gi2c_gsi_rx_cb;
+			gi2c->rx_desc->callback_param = &gi2c->rx_cb;
+
+			/* Issue RX */
+			rx_cookie = dmaengine_submit(gi2c->rx_desc);
+			dma_async_issue_pending(gi2c->rx_c);
+		} else {
+			gi2c->tx_ph = dma_map_single(tx_dev, msgs[i].buf,
+						     msgs[i].len,
+						     DMA_TO_DEVICE);
+			gi2c->tx_t.dword[0] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(gi2c->tx_ph);
+			gi2c->tx_t.dword[1] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD1(gi2c->tx_ph);
+			gi2c->tx_t.dword[2] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD2(msgs[i].len);
+			gi2c->tx_t.dword[3] =
+				MSM_GPI_DMA_W_BUFFER_TRE_DWORD3(0, 1, 0, 0);
+
+			sg_set_buf(&gi2c->tx_sg[index++], &gi2c->tx_t,
+							  sizeof(gi2c->tx_t));
+		}
+
+		gi2c->tx_desc = dmaengine_prep_slave_sg(gi2c->tx_c, gi2c->tx_sg,
+						segs, DMA_MEM_TO_DEV,
+						(DMA_PREP_INTERRUPT |
+						 DMA_CTRL_ACK));
+		if (!gi2c->tx_desc) {
+			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				    "prep_slave_sg for tx failed\n");
+			gi2c->err = -ENOMEM;
+			return gi2c->err;
+		}
+		gi2c->tx_desc->callback = gi2c_gsi_tx_cb;
+		gi2c->tx_desc->callback_param = &gi2c->tx_cb;
+
+		/* Issue TX */
+		tx_cookie = dmaengine_submit(gi2c->tx_desc);
+		dma_async_issue_pending(gi2c->tx_c);
+
+		timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
+		if (msgs[i].flags & I2C_M_RD)
+			dma_unmap_single(rx_dev, gi2c->rx_ph, msgs[i].len,
+					 DMA_FROM_DEVICE);
+		else
+			dma_unmap_single(tx_dev, gi2c->tx_ph, msgs[i].len,
+					 DMA_TO_DEVICE);
+
+		if (!timeout) {
+			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+				    "GSI Txn timed out\n");
+			gi2c->err = -ETIMEDOUT;
+		}
+		if (gi2c->err) {
+			dmaengine_terminate_all(gi2c->tx_c);
+			gi2c->cfg_sent = 0;
+			return gi2c->err;
+		}
+	}
+	return gi2c->err;
+}
+
 static int geni_i2c_xfer(struct i2c_adapter *adap,
 			 struct i2c_msg msgs[],
 			 int num)
@@ -324,6 +607,11 @@
 		pm_runtime_set_suspended(gi2c->dev);
 		return ret;
 	}
+	if (gi2c->se_mode == GSI_ONLY) {
+		ret = geni_i2c_gsi_xfer(adap, msgs, num);
+		goto geni_i2c_txn_ret;
+	}
+
 	qcom_geni_i2c_conf(gi2c, 0);
 	dev_dbg(gi2c->dev, "i2c xfer:num:%d, msgs:len:%d,flg:%d\n",
 				num, msgs[0].len, msgs[0].flags);
@@ -418,8 +706,9 @@
 			break;
 		}
 	}
+geni_i2c_txn_ret:
 	if (ret == 0)
-		ret = i;
+		ret = num;
 	pm_runtime_put_sync(gi2c->dev);
 	gi2c->cur = NULL;
 	gi2c->err = 0;
@@ -592,7 +881,9 @@
 {
 	struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
 
-	disable_irq(gi2c->irq);
+	if (gi2c->se_mode == FIFO_SE_DMA)
+		disable_irq(gi2c->irq);
+
 	se_geni_resources_off(&gi2c->i2c_rsc);
 	return 0;
 }
@@ -612,16 +903,31 @@
 	if (ret)
 		return ret;
 
-	if (unlikely(!gi2c->tx_wm)) {
-		int gi2c_tx_depth = get_tx_fifo_depth(gi2c->base);
+	if (gi2c->se_mode == UNINITIALIZED) {
+		u32 se_mode = readl_relaxed(gi2c->base +
+					GENI_IF_FIFO_DISABLE_RO);
 
-		gi2c->tx_wm = gi2c_tx_depth - 1;
-		geni_se_init(gi2c->base, gi2c->tx_wm, gi2c_tx_depth);
-		se_config_packing(gi2c->base, 8, 4, true);
-		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-			    "i2c fifo depth:%d\n", gi2c_tx_depth);
+		if (se_mode) {
+			gi2c->se_mode = GSI_ONLY;
+			geni_se_select_mode(gi2c->base, GSI_DMA);
+			GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+				    "i2c in GSI ONLY mode\n");
+		} else {
+			int gi2c_tx_depth = get_tx_fifo_depth(gi2c->base);
+
+			gi2c->se_mode = FIFO_SE_DMA;
+
+			gi2c->tx_wm = gi2c_tx_depth - 1;
+			geni_se_init(gi2c->base, gi2c->tx_wm, gi2c_tx_depth);
+			se_config_packing(gi2c->base, 8, 4, true);
+			GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+				    "i2c fifo/se-dma mode. fifo depth:%d\n",
+				    gi2c_tx_depth);
+		}
 	}
-	enable_irq(gi2c->irq);
+	if (gi2c->se_mode == FIFO_SE_DMA)
+		enable_irq(gi2c->irq);
+
 	return 0;
 }
 
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8fd108d..63e82f8 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -518,6 +518,11 @@
 	struct dst_entry *dst;
 	int ret;
 
+	if (!addr->net) {
+		pr_warn_ratelimited("%s: missing namespace\n", __func__);
+		return -EINVAL;
+	}
+
 	if (src_in->sa_family == AF_INET) {
 		struct rtable *rt = NULL;
 		const struct sockaddr_in *dst_in4 =
@@ -555,7 +560,6 @@
 	}
 
 	addr->bound_dev_if = ndev->ifindex;
-	addr->net = dev_net(ndev);
 	dev_put(ndev);
 
 	return ret;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index f2d40c0..809a028 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -976,6 +976,8 @@
 		} else
 			ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
 						 qp_attr_mask);
+		qp_attr->port_num = id_priv->id.port_num;
+		*qp_attr_mask |= IB_QP_PORT;
 	} else
 		ret = -ENOSYS;
 
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 1fb31a4..0a260a0 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1823,7 +1823,7 @@
 	mr->ndescs = sg_nents;
 
 	for_each_sg(sgl, sg, sg_nents, i) {
-		if (unlikely(i > mr->max_descs))
+		if (unlikely(i >= mr->max_descs))
 			break;
 		klms[i].va = cpu_to_be64(sg_dma_address(sg) + sg_offset);
 		klms[i].bcount = cpu_to_be32(sg_dma_len(sg) - sg_offset);
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index ccf6247..4d2a346 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -980,7 +980,9 @@
 	free_rd_atomic_resource(qp, res);
 	rxe_advance_resp_resource(qp);
 
-	memcpy(SKB_TO_PKT(skb), &ack_pkt, sizeof(skb->cb));
+	memcpy(SKB_TO_PKT(skb), &ack_pkt, sizeof(ack_pkt));
+	memset((unsigned char *)SKB_TO_PKT(skb) + sizeof(ack_pkt), 0,
+	       sizeof(skb->cb) - sizeof(ack_pkt));
 
 	res->type = RXE_ATOMIC_MASK;
 	res->atomic.skb = skb;
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 140f3f3..e46e2b0 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -83,6 +83,7 @@
 static struct iscsi_transport iscsi_iser_transport;
 static struct scsi_transport_template *iscsi_iser_scsi_transport;
 static struct workqueue_struct *release_wq;
+static DEFINE_MUTEX(unbind_iser_conn_mutex);
 struct iser_global ig;
 
 int iser_debug_level = 0;
@@ -550,12 +551,14 @@
 	 */
 	if (iser_conn) {
 		mutex_lock(&iser_conn->state_mutex);
+		mutex_lock(&unbind_iser_conn_mutex);
 		iser_conn_terminate(iser_conn);
 		iscsi_conn_stop(cls_conn, flag);
 
 		/* unbind */
 		iser_conn->iscsi_conn = NULL;
 		conn->dd_data = NULL;
+		mutex_unlock(&unbind_iser_conn_mutex);
 
 		complete(&iser_conn->stop_completion);
 		mutex_unlock(&iser_conn->state_mutex);
@@ -973,13 +976,21 @@
 	struct iser_conn *iser_conn;
 	struct ib_device *ib_dev;
 
+	mutex_lock(&unbind_iser_conn_mutex);
+
 	session = starget_to_session(scsi_target(sdev))->dd_data;
 	iser_conn = session->leadconn->dd_data;
+	if (!iser_conn) {
+		mutex_unlock(&unbind_iser_conn_mutex);
+		return -ENOTCONN;
+	}
 	ib_dev = iser_conn->ib_conn.device->ib_device;
 
 	if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG))
 		blk_queue_virt_boundary(sdev->request_queue, ~MASK_4K);
 
+	mutex_unlock(&unbind_iser_conn_mutex);
+
 	return 0;
 }
 
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 6dd43f6..39d2837 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1447,7 +1447,7 @@
 isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 {
 	struct isert_conn *isert_conn = wc->qp->qp_context;
-	struct ib_device *ib_dev = isert_conn->cm_id->device;
+	struct ib_device *ib_dev = isert_conn->device->ib_device;
 
 	if (unlikely(wc->status != IB_WC_SUCCESS)) {
 		isert_print_wc(wc, "login recv");
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 0dea590..7a6f50b 100644
--- a/drivers/input/misc/hbtp_input.c
+++ b/drivers/input/misc/hbtp_input.c
@@ -47,6 +47,8 @@
 	struct input_dev *input_dev;
 	s32 count;
 	struct mutex mutex;
+	struct mutex sensormutex;
+	struct hbtp_sensor_data *sensor_data;
 	bool touch_status[HBTP_MAX_FINGER];
 #if defined(CONFIG_FB)
 	struct notifier_block fb_notif;
@@ -88,10 +90,14 @@
 	u32 power_off_delay;
 	bool manage_pin_ctrl;
 	struct kobject *sysfs_kobject;
+	s16 ROI[MAX_ROI_SIZE];
+	s16 accelBuffer[MAX_ACCEL_SIZE];
 };
 
 static struct hbtp_data *hbtp;
 
+static struct kobject *sensor_kobject;
+
 #if defined(CONFIG_FB)
 static int hbtp_fb_suspend(struct hbtp_data *ts);
 static int hbtp_fb_early_resume(struct hbtp_data *ts);
@@ -151,6 +157,46 @@
 }
 #endif
 
+static ssize_t hbtp_sensor_roi_show(struct file *dev, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t pos,
+			size_t size) {
+	mutex_lock(&hbtp->sensormutex);
+	memcpy(buf, hbtp->ROI, size);
+	mutex_unlock(&hbtp->sensormutex);
+
+	return size;
+}
+
+static ssize_t hbtp_sensor_vib_show(struct file *dev, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t pos,
+			size_t size) {
+	mutex_lock(&hbtp->sensormutex);
+	memcpy(buf, hbtp->accelBuffer, size);
+	mutex_unlock(&hbtp->sensormutex);
+
+	return size;
+}
+
+static struct bin_attribute capdata_attr = {
+	.attr = {
+		.name = "capdata",
+		.mode = 0444,
+		},
+	.size = 1024,
+	.read = hbtp_sensor_roi_show,
+	.write = NULL,
+};
+
+static struct bin_attribute vibdata_attr = {
+	.attr = {
+		.name = "vib_data",
+		.mode = 0444,
+		},
+	.size = MAX_ACCEL_SIZE*sizeof(int16_t),
+	.read = hbtp_sensor_vib_show,
+	.write = NULL,
+};
+
 static int hbtp_input_open(struct inode *inode, struct file *file)
 {
 	mutex_lock(&hbtp->mutex);
@@ -749,6 +795,22 @@
 			return -EINVAL;
 		}
 		break;
+
+	case HBTP_SET_SENSORDATA:
+		if (copy_from_user(hbtp->sensor_data, (void __user *)arg,
+					sizeof(struct hbtp_sensor_data))) {
+			pr_err("%s: Error copying data\n", __func__);
+			return -EFAULT;
+		}
+		mutex_lock(&hbtp->sensormutex);
+		memcpy(hbtp->ROI, hbtp->sensor_data->ROI, sizeof(hbtp->ROI));
+		memcpy(hbtp->accelBuffer, hbtp->sensor_data->accelBuffer,
+			sizeof(hbtp->accelBuffer));
+		mutex_unlock(&hbtp->sensormutex);
+
+		error = 0;
+		break;
+
 	default:
 		pr_err("%s: Unsupported ioctl command %u\n", __func__, cmd);
 		error = -EINVAL;
@@ -1388,13 +1450,19 @@
 
 static int __init hbtp_init(void)
 {
-	int error;
+	int error = 0;
 
 	hbtp = kzalloc(sizeof(struct hbtp_data), GFP_KERNEL);
 	if (!hbtp)
 		return -ENOMEM;
 
+	hbtp->sensor_data = kzalloc(sizeof(struct hbtp_sensor_data),
+			GFP_KERNEL);
+	if (!hbtp->sensor_data)
+		goto err_sensordata;
+
 	mutex_init(&hbtp->mutex);
+	mutex_init(&hbtp->sensormutex);
 
 	error = misc_register(&hbtp_input_misc);
 	if (error) {
@@ -1412,6 +1480,28 @@
 	}
 #endif
 
+	sensor_kobject = kobject_create_and_add("hbtpsensor", kernel_kobj);
+	if (!sensor_kobject) {
+		pr_err("%s: Could not create hbtpsensor kobject\n", __func__);
+		goto err_kobject_create;
+	}
+
+	error = sysfs_create_bin_file(sensor_kobject, &capdata_attr);
+	if (error < 0) {
+		pr_err("%s: hbtp capdata sysfs creation failed: %d\n", __func__,
+			error);
+		goto err_sysfs_create_capdata;
+	}
+	pr_debug("capdata sysfs creation success\n");
+
+	error = sysfs_create_bin_file(sensor_kobject, &vibdata_attr);
+	if (error < 0) {
+		pr_err("%s: vibdata sysfs creation failed: %d\n", __func__,
+			error);
+		goto err_sysfs_create_vibdata;
+	}
+	pr_debug("vibdata sysfs creation success\n");
+
 	error = platform_driver_register(&hbtp_pdev_driver);
 	if (error) {
 		pr_err("Failed to register platform driver: %d\n", error);
@@ -1431,12 +1521,20 @@
 	return 0;
 
 err_platform_drv_reg:
+	sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
+err_sysfs_create_vibdata:
+	sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
+err_sysfs_create_capdata:
+	kobject_put(sensor_kobject);
+err_kobject_create:
 #if defined(CONFIG_FB)
 	fb_unregister_client(&hbtp->fb_notif);
 err_fb_reg:
 #endif
 	misc_deregister(&hbtp_input_misc);
 err_misc_reg:
+	kfree(hbtp->sensor_data);
+err_sensordata:
 	kfree(hbtp);
 
 	return error;
@@ -1444,6 +1542,9 @@
 
 static void __exit hbtp_exit(void)
 {
+	sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
+	sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
+	kobject_put(sensor_kobject);
 	misc_deregister(&hbtp_input_misc);
 	if (hbtp->input_dev)
 		input_unregister_device(hbtp->input_dev);
@@ -1454,6 +1555,7 @@
 
 	platform_driver_unregister(&hbtp_pdev_driver);
 
+	kfree(hbtp->sensor_data);
 	kfree(hbtp);
 }
 
diff --git a/drivers/input/misc/keychord.c b/drivers/input/misc/keychord.c
index a5ea27a..c5ab3dd 100644
--- a/drivers/input/misc/keychord.c
+++ b/drivers/input/misc/keychord.c
@@ -232,9 +232,11 @@
 {
 	struct keychord_device *kdev = file->private_data;
 	struct input_keychord *keychords = 0;
-	struct input_keychord *keychord, *next, *end;
+	struct input_keychord *keychord;
 	int ret, i, key;
 	unsigned long flags;
+	size_t resid = count;
+	size_t key_bytes;
 
 	if (count < sizeof(struct input_keychord))
 		return -EINVAL;
@@ -265,15 +267,29 @@
 	kdev->head = kdev->tail = 0;
 
 	keychord = keychords;
-	end = (struct input_keychord *)((char *)keychord + count);
 
-	while (keychord < end) {
-		next = NEXT_KEYCHORD(keychord);
-		if (keychord->count <= 0 || next > end) {
+	while (resid > 0) {
+		/* Is the entire keychord entry header present ? */
+		if (resid < sizeof(struct input_keychord)) {
+			pr_err("keychord: Insufficient bytes present for header %zu\n",
+			       resid);
+			goto err_unlock_return;
+		}
+		resid -= sizeof(struct input_keychord);
+		if (keychord->count <= 0) {
 			pr_err("keychord: invalid keycode count %d\n",
 				keychord->count);
 			goto err_unlock_return;
 		}
+		key_bytes = keychord->count * sizeof(keychord->keycodes[0]);
+		/* Do we have all the expected keycodes ? */
+		if (resid < key_bytes) {
+			pr_err("keychord: Insufficient bytes present for keycount %zu\n",
+			       resid);
+			goto err_unlock_return;
+		}
+		resid -= key_bytes;
+
 		if (keychord->version != KEYCHORD_VERSION) {
 			pr_err("keychord: unsupported version %d\n",
 				keychord->version);
@@ -292,7 +308,7 @@
 		}
 
 		kdev->keychord_count++;
-		keychord = next;
+		keychord = NEXT_KEYCHORD(keychord);
 	}
 
 	kdev->keychords = keychords;
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 89abfdb..c84c685 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -434,8 +434,10 @@
 {
 	struct i8042_port *port = serio->port_data;
 
+	spin_lock_irq(&i8042_lock);
 	port->exists = true;
-	mb();
+	spin_unlock_irq(&i8042_lock);
+
 	return 0;
 }
 
@@ -448,16 +450,20 @@
 {
 	struct i8042_port *port = serio->port_data;
 
+	spin_lock_irq(&i8042_lock);
 	port->exists = false;
+	port->serio = NULL;
+	spin_unlock_irq(&i8042_lock);
 
 	/*
+	 * We need to make sure that interrupt handler finishes using
+	 * our serio port before we return from this function.
 	 * We synchronize with both AUX and KBD IRQs because there is
 	 * a (very unlikely) chance that AUX IRQ is raised for KBD port
 	 * and vice versa.
 	 */
 	synchronize_irq(I8042_AUX_IRQ);
 	synchronize_irq(I8042_KBD_IRQ);
-	port->serio = NULL;
 }
 
 /*
@@ -574,7 +580,7 @@
 
 	spin_unlock_irqrestore(&i8042_lock, flags);
 
-	if (likely(port->exists && !filtered))
+	if (likely(serio && !filtered))
 		serio_interrupt(serio, data, dfl);
 
  out:
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 142357e..bf93b91 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -389,6 +389,7 @@
 	/* Protects clock_refs_count */
 	spinlock_t			clock_refs_lock;
 	int				clock_refs_count;
+	int				regulator_defer;
 };
 
 struct arm_smmu_device {
@@ -789,6 +790,35 @@
 	WARN_ON(msm_bus_scale_client_update_request(pwr->bus_client, 0));
 }
 
+static int arm_smmu_disable_regulators(struct arm_smmu_power_resources *pwr)
+{
+	struct regulator_bulk_data *consumers;
+	int i;
+	int num_consumers, ret, r;
+
+	num_consumers = pwr->num_gdscs;
+	consumers = pwr->gdscs;
+	for (i = num_consumers - 1; i >= 0; --i) {
+		ret = regulator_disable_deferred(consumers[i].consumer,
+						 pwr->regulator_defer);
+		if (ret != 0)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
+	for (++i; i < num_consumers; ++i) {
+		r = regulator_enable(consumers[i].consumer);
+		if (r != 0)
+			pr_err("Failed to reename %s: %d\n",
+			       consumers[i].supply, r);
+	}
+
+	return ret;
+}
+
 /* Clocks must be prepared before this (arm_smmu_prepare_clocks) */
 static int arm_smmu_power_on_atomic(struct arm_smmu_power_resources *pwr)
 {
@@ -884,7 +914,7 @@
 	}
 
 	arm_smmu_unprepare_clocks(pwr);
-	regulator_bulk_disable(pwr->num_gdscs, pwr->gdscs);
+	arm_smmu_disable_regulators(pwr);
 	arm_smmu_unrequest_bus(pwr);
 	pwr->power_count = 0;
 	mutex_unlock(&pwr->power_lock);
@@ -3175,6 +3205,11 @@
 	u32 sctlr, sctlr_orig, fsr;
 	void __iomem *cb_base;
 
+	if (smmu->model == QCOM_SMMUV2) {
+		dev_err(smmu->dev, "ATOS support is disabled\n");
+		return 0;
+	}
+
 	ret = arm_smmu_power_on(smmu_domain->smmu->pwr);
 	if (ret)
 		return ret;
@@ -3534,6 +3569,12 @@
 	if (!pwr->gdscs)
 		return -ENOMEM;
 
+	if (!of_property_read_u32(dev->of_node,
+				  "qcom,deferred-regulator-disable-delay",
+				  &(pwr->regulator_defer)))
+		dev_info(dev, "regulator defer delay %d\n",
+			pwr->regulator_defer);
+
 	i = 0;
 	of_property_for_each_string(dev->of_node, "qcom,regulator-names",
 				prop, cname)
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 2ef496d..dde2876 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -760,16 +760,7 @@
 		if (!iopte_tblcnt(*ptep)) {
 			/* no valid mappings left under this table. free it. */
 			__arm_lpae_set_pte(ptep, 0, &iop->cfg);
-			io_pgtable_tlb_add_flush(iop, iova,
-						 entries * entry_size,
-						 ARM_LPAE_GRANULE(data),
-						 false);
 			__arm_lpae_free_pgtable(data, lvl + 1, table_base);
-		} else {
-			io_pgtable_tlb_add_flush(iop, iova,
-						 entries * entry_size,
-						 ARM_LPAE_GRANULE(data),
-						 true);
 		}
 
 		return entries * entry_size;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index daccf64..779001e 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -647,6 +647,9 @@
 	int enabled;
 	u64 val;
 
+	if (cpu >= nr_cpu_ids)
+		return -EINVAL;
+
 	if (gic_irq_in_rdist(d))
 		return -EINVAL;
 
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index 2678a00..5bd52e4 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -158,6 +158,11 @@
 #define	FLASH_LED_DISABLE			0x00
 #define	FLASH_LED_SAFETY_TMR_DISABLED		0x13
 #define	FLASH_LED_MAX_TOTAL_CURRENT_MA		3750
+#define	FLASH_LED_IRES5P0_MAX_CURR_MA		640
+#define	FLASH_LED_IRES7P5_MAX_CURR_MA		960
+#define	FLASH_LED_IRES10P0_MAX_CURR_MA		1280
+#define	FLASH_LED_IRES12P5_MAX_CURR_MA		1600
+#define	MAX_IRES_LEVELS				4
 
 /* notifier call chain for flash-led irqs */
 static ATOMIC_NOTIFIER_HEAD(irq_notifier_list);
@@ -196,13 +201,15 @@
 	struct pinctrl_state		*hw_strobe_state_suspend;
 	int				hw_strobe_gpio;
 	int				ires_ua;
+	int				default_ires_ua;
 	int				max_current;
 	int				current_ma;
 	int				prev_current_ma;
 	u8				duration;
 	u8				id;
 	u8				type;
-	u8				ires;
+	u8				ires_idx;
+	u8				default_ires_idx;
 	u8				hdrm_val;
 	u8				current_reg_val;
 	u8				strobe_ctrl;
@@ -305,6 +312,11 @@
 	125, 119, 113, 107, 149, 143, 137, 131,
 };
 
+static int max_ires_curr_ma_table[MAX_IRES_LEVELS] = {
+	FLASH_LED_IRES12P5_MAX_CURR_MA, FLASH_LED_IRES10P0_MAX_CURR_MA,
+	FLASH_LED_IRES7P5_MAX_CURR_MA, FLASH_LED_IRES5P0_MAX_CURR_MA
+};
+
 static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
 {
 	int rc;
@@ -935,6 +947,7 @@
 
 static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
 {
+	int i = 0;
 	int prgm_current_ma = value;
 	int min_ma = fnode->ires_ua / 1000;
 	struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
@@ -944,7 +957,22 @@
 	else if (value < min_ma)
 		prgm_current_ma = min_ma;
 
+	fnode->ires_idx = fnode->default_ires_idx;
+	fnode->ires_ua = fnode->default_ires_ua;
+
 	prgm_current_ma = min(prgm_current_ma, fnode->max_current);
+	if (prgm_current_ma > max_ires_curr_ma_table[fnode->ires_idx]) {
+		/* find the matching ires */
+		for (i = MAX_IRES_LEVELS - 1; i >= 0; i--) {
+			if (prgm_current_ma <= max_ires_curr_ma_table[i]) {
+				fnode->ires_idx = i;
+				fnode->ires_ua = FLASH_LED_IRES_MIN_UA +
+				      (FLASH_LED_IRES_BASE - fnode->ires_idx) *
+				      FLASH_LED_IRES_DIVISOR;
+				break;
+			}
+		}
+	}
 	fnode->current_ma = prgm_current_ma;
 	fnode->cdev.brightness = prgm_current_ma;
 	fnode->current_reg_val = CURRENT_MA_TO_REG_VAL(prgm_current_ma,
@@ -1062,7 +1090,7 @@
 	val = 0;
 	for (i = 0; i < led->num_fnodes; i++)
 		if (snode->led_mask & BIT(led->fnode[i].id))
-			val |= led->fnode[i].ires << (led->fnode[i].id * 2);
+			val |= led->fnode[i].ires_idx << (led->fnode[i].id * 2);
 
 	rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_IRES(led->base),
 						FLASH_LED_CURRENT_MASK, val);
@@ -1434,13 +1462,14 @@
 		return rc;
 	}
 
-	fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
-	fnode->ires = FLASH_LED_IRES_DEFAULT_VAL;
+	fnode->default_ires_ua = fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
+	fnode->default_ires_idx = fnode->ires_idx = FLASH_LED_IRES_DEFAULT_VAL;
 	rc = of_property_read_u32(node, "qcom,ires-ua", &val);
 	if (!rc) {
-		fnode->ires_ua = val;
-		fnode->ires = FLASH_LED_IRES_BASE -
-			(val - FLASH_LED_IRES_MIN_UA) / FLASH_LED_IRES_DIVISOR;
+		fnode->default_ires_ua = fnode->ires_ua = val;
+		fnode->default_ires_idx = fnode->ires_idx =
+			FLASH_LED_IRES_BASE - (val - FLASH_LED_IRES_MIN_UA) /
+			FLASH_LED_IRES_DIVISOR;
 	} else if (rc != -EINVAL) {
 		pr_err("Unable to read current resolution rc=%d\n", rc);
 		return rc;
diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index cb19cef..f18022b 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -160,18 +160,19 @@
 #define QPNP_WLED_MOD_EN_SHFT		7
 #define QPNP_WLED_MOD_EN		1
 #define QPNP_WLED_GATE_DRV_MASK		0xFE
-#define QPNP_WLED_SYNC_DLY_MASK		0xF8
+#define QPNP_WLED_SYNC_DLY_MASK		GENMASK(2, 0)
 #define QPNP_WLED_SYNC_DLY_MIN_US	0
 #define QPNP_WLED_SYNC_DLY_MAX_US	1400
 #define QPNP_WLED_SYNC_DLY_STEP_US	200
 #define QPNP_WLED_DEF_SYNC_DLY_US	400
-#define QPNP_WLED_FS_CURR_MASK		0xF0
+#define QPNP_WLED_FS_CURR_MASK		GENMASK(3, 0)
 #define QPNP_WLED_FS_CURR_MIN_UA	0
 #define QPNP_WLED_FS_CURR_MAX_UA	30000
 #define QPNP_WLED_FS_CURR_STEP_UA	2500
-#define QPNP_WLED_CABC_MASK		0x7F
+#define QPNP_WLED_CABC_MASK		0x80
 #define QPNP_WLED_CABC_SHIFT		7
 #define QPNP_WLED_CURR_SINK_SHIFT	4
+#define QPNP_WLED_CURR_SINK_MASK	GENMASK(7, 4)
 #define QPNP_WLED_BRIGHT_LSB_MASK	0xFF
 #define QPNP_WLED_BRIGHT_MSB_SHIFT	8
 #define QPNP_WLED_BRIGHT_MSB_MASK	0x0F
@@ -208,12 +209,14 @@
 #define QPNP_WLED_SEC_UNLOCK           0xA5
 
 #define QPNP_WLED_MAX_STRINGS		4
+#define QPNP_PM660_WLED_MAX_STRINGS	3
 #define WLED_MAX_LEVEL_4095		4095
 #define QPNP_WLED_RAMP_DLY_MS		20
 #define QPNP_WLED_TRIGGER_NONE		"none"
 #define QPNP_WLED_STR_SIZE		20
 #define QPNP_WLED_MIN_MSLEEP		20
 #define QPNP_WLED_SC_DLY_MS		20
+#define QPNP_WLED_SOFT_START_DLY_US	10000
 
 #define NUM_SUPPORTED_AVDD_VOLTAGES	6
 #define QPNP_WLED_DFLT_AVDD_MV		7600
@@ -381,6 +384,8 @@
 	u16			ramp_ms;
 	u16			ramp_step;
 	u16			cons_sync_write_delay_us;
+	u16			auto_calibration_ovp_count;
+	u16			max_strings;
 	u8			strings[QPNP_WLED_MAX_STRINGS];
 	u8			num_strings;
 	u8			loop_auto_gm_thresh;
@@ -396,6 +401,9 @@
 	bool			en_ext_pfet_sc_pro;
 	bool			prev_state;
 	bool			ovp_irq_disabled;
+	bool			auto_calib_enabled;
+	bool			auto_calib_done;
+	ktime_t			start_ovp_fault_time;
 };
 
 /* helper to read a pmic register */
@@ -531,7 +539,7 @@
 	u8 reg;
 
 	/* set brightness registers */
-	for (i = 0; i < wled->num_strings; i++) {
+	for (i = 0; i < wled->max_strings; i++) {
 		reg = level & QPNP_WLED_BRIGHT_LSB_MASK;
 		rc = qpnp_wled_write_reg(wled,
 				QPNP_WLED_BRIGHT_LSB_REG(wled->sink_base,
@@ -600,7 +608,8 @@
 	 * OVP interrupt disabled when the module is disabled.
 	 */
 	if (state) {
-		usleep_range(10000, 11000);
+		usleep_range(QPNP_WLED_SOFT_START_DLY_US,
+				QPNP_WLED_SOFT_START_DLY_US + 1000);
 		rc = qpnp_wled_psm_config(wled, false);
 		if (rc < 0)
 			return rc;
@@ -873,32 +882,25 @@
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qpnp_wled *wled = dev_get_drvdata(dev);
-	int data, i, rc, temp;
+	int data, i, rc;
 	u8 reg;
 
 	rc = kstrtoint(buf, 10, &data);
 	if (rc)
 		return rc;
 
-	for (i = 0; i < wled->num_strings; i++) {
+	for (i = 0; i < wled->max_strings; i++) {
 		if (data < QPNP_WLED_FS_CURR_MIN_UA)
 			data = QPNP_WLED_FS_CURR_MIN_UA;
 		else if (data > QPNP_WLED_FS_CURR_MAX_UA)
 			data = QPNP_WLED_FS_CURR_MAX_UA;
 
-		rc = qpnp_wled_read_reg(wled,
-				QPNP_WLED_FS_CURR_REG(wled->sink_base,
-					wled->strings[i]), &reg);
+		reg = data / QPNP_WLED_FS_CURR_STEP_UA;
+		rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_FS_CURR_REG(wled->sink_base, i),
+			QPNP_WLED_FS_CURR_MASK, reg);
 		if (rc < 0)
 			return rc;
-		reg &= QPNP_WLED_FS_CURR_MASK;
-		temp = data / QPNP_WLED_FS_CURR_STEP_UA;
-		reg |= temp;
-		rc = qpnp_wled_write_reg(wled,
-				QPNP_WLED_FS_CURR_REG(wled->sink_base,
-					wled->strings[i]), reg);
-		if (rc)
-			return rc;
 	}
 
 	wled->fs_curr_ua = data;
@@ -1090,6 +1092,229 @@
 	return 0;
 }
 
+#define AUTO_CALIB_BRIGHTNESS		16
+static int wled_auto_calibrate(struct qpnp_wled *wled)
+{
+	int rc = 0, i;
+	u8 reg = 0, sink_config = 0, sink_test = 0, sink_valid = 0, int_sts;
+
+	mutex_lock(&wled->lock);
+
+	/* disable OVP IRQ */
+	if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) {
+		disable_irq_nosync(wled->ovp_irq);
+		wled->ovp_irq_disabled = true;
+	}
+
+	/* read configured sink configuration */
+	rc = qpnp_wled_read_reg(wled,
+		QPNP_WLED_CURR_SINK_REG(wled->sink_base), &sink_config);
+	if (rc < 0) {
+		pr_err("Failed to read SINK configuration rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* disable the module before starting calibration */
+	rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
+			QPNP_WLED_MODULE_EN_MASK, 0);
+	if (rc < 0) {
+		pr_err("Failed to disable WLED module rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* set low brightness across all sinks */
+	rc = qpnp_wled_set_level(wled, AUTO_CALIB_BRIGHTNESS);
+	if (rc < 0) {
+		pr_err("Failed to set brightness for calibration rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* disable all sinks */
+	rc = qpnp_wled_write_reg(wled,
+		 QPNP_WLED_CURR_SINK_REG(wled->sink_base), 0);
+	if (rc < 0) {
+		pr_err("Failed to disable all sinks rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	rc = qpnp_wled_masked_write_reg(wled,
+		QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
+		QPNP_WLED_MODULE_EN_MASK,
+		QPNP_WLED_MODULE_EN_MASK);
+	if (rc < 0) {
+		pr_err("Failed to enable WLED module rc=%d\n", rc);
+		goto failed_calib;
+	}
+	/*
+	 * Delay for the WLED soft-start, check the OVP status
+	 * only after soft-start is complete
+	 */
+	usleep_range(QPNP_WLED_SOFT_START_DLY_US,
+			QPNP_WLED_SOFT_START_DLY_US + 1000);
+
+	/* iterate through the strings one by one */
+	for (i = 0; i < wled->max_strings; i++) {
+		sink_test = 1 << (QPNP_WLED_CURR_SINK_SHIFT + i);
+
+		/* Enable feedback control */
+		rc = qpnp_wled_write_reg(wled,
+			QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
+			i + 1);
+		if (rc < 0) {
+			pr_err("Failed to enable feedback for SINK %d rc = %d\n",
+						i + 1, rc);
+			goto failed_calib;
+		}
+
+		/* enable the sink */
+		rc = qpnp_wled_write_reg(wled,
+			QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_test);
+		if (rc < 0) {
+			pr_err("Failed to configure SINK %d rc=%d\n",
+						i + 1, rc);
+			goto failed_calib;
+		}
+
+		/* delay for WLED soft-start */
+		usleep_range(QPNP_WLED_SOFT_START_DLY_US,
+				QPNP_WLED_SOFT_START_DLY_US + 1000);
+
+		rc = qpnp_wled_read_reg(wled,
+			QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
+		if (rc < 0) {
+			pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
+			goto failed_calib;
+		}
+
+		if (int_sts & QPNP_WLED_OVP_FAULT_BIT)
+			pr_debug("WLED OVP fault detected with SINK %d\n",
+						i + 1);
+		else
+			sink_valid |= sink_test;
+	}
+
+	if (sink_valid == sink_config) {
+		pr_debug("WLED auto-calibration complete, default sink-config=%x OK!\n",
+						sink_config);
+	} else {
+		pr_warn("Invalid WLED default sink config=%x changing it to=%x\n",
+						sink_config, sink_valid);
+		sink_config = sink_valid;
+	}
+
+	if (!sink_config) {
+		pr_warn("No valid WLED sinks found\n");
+		goto failed_calib;
+	}
+
+	rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
+			QPNP_WLED_MODULE_EN_MASK, 0);
+	if (rc < 0) {
+		pr_err("Failed to disable WLED module rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* write the new sink configuration */
+	rc = qpnp_wled_write_reg(wled,
+			QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_config);
+	if (rc < 0) {
+		pr_err("Failed to reconfigure the default sink rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* MODULATOR_EN setting for valid sinks */
+	for (i = 0; i < wled->max_strings; i++) {
+		if (sink_config & (1 << (QPNP_WLED_CURR_SINK_SHIFT + i)))
+			reg = (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);
+		else
+			reg = 0x0; /* disable modulator_en for unused sink */
+
+		if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
+			reg &= QPNP_WLED_GATE_DRV_MASK;
+		else
+			reg |= ~QPNP_WLED_GATE_DRV_MASK;
+
+		rc = qpnp_wled_write_reg(wled,
+			QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
+		if (rc < 0) {
+			pr_err("Failed to configure MODULATOR_EN rc=%d\n", rc);
+			goto failed_calib;
+		}
+	}
+
+	/* restore the feedback setting */
+	rc = qpnp_wled_write_reg(wled,
+			QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
+			wled->fdbk_op);
+	if (rc < 0) {
+		pr_err("Failed to restore feedback setting rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* restore  brightness */
+	rc = qpnp_wled_set_level(wled, wled->cdev.brightness);
+	if (rc < 0) {
+		pr_err("Failed to set brightness after calibration rc=%d\n",
+						rc);
+		goto failed_calib;
+	}
+
+	rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
+			QPNP_WLED_MODULE_EN_MASK,
+			QPNP_WLED_MODULE_EN_MASK);
+	if (rc < 0) {
+		pr_err("Failed to enable WLED module rc=%d\n", rc);
+		goto failed_calib;
+	}
+
+	/* delay for WLED soft-start */
+	usleep_range(QPNP_WLED_SOFT_START_DLY_US,
+			QPNP_WLED_SOFT_START_DLY_US + 1000);
+
+failed_calib:
+	if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) {
+		enable_irq(wled->ovp_irq);
+		wled->ovp_irq_disabled = false;
+	}
+	mutex_unlock(&wled->lock);
+	return rc;
+}
+
+#define WLED_AUTO_CAL_OVP_COUNT		5
+#define WLED_AUTO_CAL_CNT_DLY_US	1000000	/* 1 second */
+static bool qpnp_wled_auto_cal_required(struct qpnp_wled *wled)
+{
+	s64 elapsed_time_us;
+
+	/*
+	 * Check if the OVP fault was an occasional one
+	 * or if its firing continuously, the latter qualifies
+	 * for an auto-calibration check.
+	 */
+	if (!wled->auto_calibration_ovp_count) {
+		wled->start_ovp_fault_time = ktime_get();
+		wled->auto_calibration_ovp_count++;
+	} else {
+		elapsed_time_us = ktime_us_delta(ktime_get(),
+				wled->start_ovp_fault_time);
+		if (elapsed_time_us > WLED_AUTO_CAL_CNT_DLY_US)
+			wled->auto_calibration_ovp_count = 0;
+		else
+			wled->auto_calibration_ovp_count++;
+
+		if (wled->auto_calibration_ovp_count >=
+				WLED_AUTO_CAL_OVP_COUNT) {
+			wled->auto_calibration_ovp_count = 0;
+			return true;
+		}
+	}
+
+	return false;
+}
+
 /* ovp irq handler */
 static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
 {
@@ -1114,6 +1339,21 @@
 	if (fault_sts & (QPNP_WLED_OVP_FAULT_BIT | QPNP_WLED_ILIM_FAULT_BIT))
 		pr_err("WLED OVP fault detected, int_sts=%x fault_sts= %x\n",
 			int_sts, fault_sts);
+
+	if (fault_sts & QPNP_WLED_OVP_FAULT_BIT) {
+		if (wled->auto_calib_enabled && !wled->auto_calib_done) {
+			if (qpnp_wled_auto_cal_required(wled)) {
+				rc = wled_auto_calibrate(wled);
+				if (rc < 0) {
+					pr_err("Failed auto-calibration rc=%d\n",
+							rc);
+					return IRQ_HANDLED;
+				}
+				wled->auto_calib_done = true;
+			}
+		}
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -1423,7 +1663,7 @@
 static int qpnp_wled_config(struct qpnp_wled *wled)
 {
 	int rc, i, temp;
-	u8 reg = 0;
+	u8 reg = 0, sink_en = 0, mask;
 
 	/* Configure display type */
 	rc = qpnp_wled_set_disp(wled, wled->ctrl_base);
@@ -1622,16 +1862,50 @@
 	rc = qpnp_wled_write_reg(wled, QPNP_WLED_CURR_SINK_REG(wled->sink_base),
 			reg);
 
+	for (i = 0; i < wled->max_strings; i++) {
+		/* SYNC DELAY */
+		if (wled->sync_dly_us > QPNP_WLED_SYNC_DLY_MAX_US)
+			wled->sync_dly_us = QPNP_WLED_SYNC_DLY_MAX_US;
+
+		reg = wled->sync_dly_us / QPNP_WLED_SYNC_DLY_STEP_US;
+		mask = QPNP_WLED_SYNC_DLY_MASK;
+		rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_SYNC_DLY_REG(wled->sink_base, i),
+			mask, reg);
+		if (rc < 0)
+			return rc;
+
+		/* FULL SCALE CURRENT */
+		if (wled->fs_curr_ua > QPNP_WLED_FS_CURR_MAX_UA)
+			wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA;
+
+		reg = wled->fs_curr_ua / QPNP_WLED_FS_CURR_STEP_UA;
+		mask = QPNP_WLED_FS_CURR_MASK;
+		rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_FS_CURR_REG(wled->sink_base, i),
+			mask, reg);
+		if (rc < 0)
+			return rc;
+
+		/* CABC */
+		reg = wled->en_cabc ? (1  << QPNP_WLED_CABC_SHIFT) : 0;
+		mask = QPNP_WLED_CABC_MASK;
+		rc = qpnp_wled_masked_write_reg(wled,
+			QPNP_WLED_CABC_REG(wled->sink_base, i),
+			mask, reg);
+		if (rc < 0)
+			return rc;
+	}
+
+	/* Settings specific to valid sinks */
 	for (i = 0; i < wled->num_strings; i++) {
-		if (wled->strings[i] >= QPNP_WLED_MAX_STRINGS) {
+		if (wled->strings[i] >= wled->max_strings) {
 			dev_err(&wled->pdev->dev, "Invalid string number\n");
 			return -EINVAL;
 		}
-
 		/* MODULATOR */
 		rc = qpnp_wled_read_reg(wled,
-				QPNP_WLED_MOD_EN_REG(wled->sink_base,
-					wled->strings[i]), &reg);
+			QPNP_WLED_MOD_EN_REG(wled->sink_base, i), &reg);
 		if (rc < 0)
 			return rc;
 		reg &= QPNP_WLED_MOD_EN_MASK;
@@ -1643,72 +1917,22 @@
 			reg |= ~QPNP_WLED_GATE_DRV_MASK;
 
 		rc = qpnp_wled_write_reg(wled,
-				QPNP_WLED_MOD_EN_REG(wled->sink_base,
-					wled->strings[i]), reg);
+			QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
 		if (rc)
 			return rc;
 
-		/* SYNC DELAY */
-		if (wled->sync_dly_us > QPNP_WLED_SYNC_DLY_MAX_US)
-			wled->sync_dly_us = QPNP_WLED_SYNC_DLY_MAX_US;
-
-		rc = qpnp_wled_read_reg(wled,
-				QPNP_WLED_SYNC_DLY_REG(wled->sink_base,
-					wled->strings[i]), &reg);
-		if (rc < 0)
-			return rc;
-		reg &= QPNP_WLED_SYNC_DLY_MASK;
-		temp = wled->sync_dly_us / QPNP_WLED_SYNC_DLY_STEP_US;
-		reg |= temp;
-		rc = qpnp_wled_write_reg(wled,
-				QPNP_WLED_SYNC_DLY_REG(wled->sink_base,
-					wled->strings[i]), reg);
-		if (rc)
-			return rc;
-
-		/* FULL SCALE CURRENT */
-		if (wled->fs_curr_ua > QPNP_WLED_FS_CURR_MAX_UA)
-			wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA;
-
-		rc = qpnp_wled_read_reg(wled,
-				QPNP_WLED_FS_CURR_REG(wled->sink_base,
-					wled->strings[i]), &reg);
-		if (rc < 0)
-			return rc;
-		reg &= QPNP_WLED_FS_CURR_MASK;
-		temp = wled->fs_curr_ua / QPNP_WLED_FS_CURR_STEP_UA;
-		reg |= temp;
-		rc = qpnp_wled_write_reg(wled,
-				QPNP_WLED_FS_CURR_REG(wled->sink_base,
-					wled->strings[i]), reg);
-		if (rc)
-			return rc;
-
-		/* CABC */
-		rc = qpnp_wled_read_reg(wled,
-				QPNP_WLED_CABC_REG(wled->sink_base,
-					wled->strings[i]), &reg);
-		if (rc < 0)
-			return rc;
-		reg &= QPNP_WLED_CABC_MASK;
-		reg |= (wled->en_cabc << QPNP_WLED_CABC_SHIFT);
-		rc = qpnp_wled_write_reg(wled,
-				QPNP_WLED_CABC_REG(wled->sink_base,
-					wled->strings[i]), reg);
-		if (rc)
-			return rc;
-
-		/* Enable CURRENT SINK */
-		rc = qpnp_wled_read_reg(wled,
-				QPNP_WLED_CURR_SINK_REG(wled->sink_base), &reg);
-		if (rc < 0)
-			return rc;
+		/* SINK EN */
 		temp = wled->strings[i] + QPNP_WLED_CURR_SINK_SHIFT;
-		reg |= (1 << temp);
-		rc = qpnp_wled_write_reg(wled,
-				QPNP_WLED_CURR_SINK_REG(wled->sink_base), reg);
-		if (rc)
-			return rc;
+		sink_en |= (1 << temp);
+	}
+	mask = QPNP_WLED_CURR_SINK_MASK;
+	rc = qpnp_wled_masked_write_reg(wled,
+		QPNP_WLED_CURR_SINK_REG(wled->sink_base),
+		mask, sink_en);
+	if (rc < 0) {
+		dev_err(&wled->pdev->dev,
+			"Failed to enable WLED sink config rc = %d\n", rc);
+		return rc;
 	}
 
 	rc = qpnp_wled_sync_reg_toggle(wled);
@@ -1728,8 +1952,13 @@
 				wled->ovp_irq, rc);
 			return rc;
 		}
-		disable_irq(wled->ovp_irq);
-		wled->ovp_irq_disabled = true;
+		rc = qpnp_wled_read_reg(wled,
+				QPNP_WLED_MODULE_EN_REG(wled->ctrl_base), &reg);
+		/* disable the OVP irq only if the module is not enabled */
+		if (!rc && !(reg & QPNP_WLED_MODULE_EN_MASK)) {
+			disable_irq(wled->ovp_irq);
+			wled->ovp_irq_disabled = true;
+		}
 	}
 
 	if (wled->sc_irq >= 0) {
@@ -2091,11 +2320,16 @@
 	wled->en_cabc = of_property_read_bool(pdev->dev.of_node,
 			"qcom,en-cabc");
 
+	if (wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
+		wled->max_strings = QPNP_PM660_WLED_MAX_STRINGS;
+	else
+		wled->max_strings = QPNP_WLED_MAX_STRINGS;
+
 	prop = of_find_property(pdev->dev.of_node,
 			"qcom,led-strings-list", &temp_val);
 	if (!prop || !temp_val || temp_val > QPNP_WLED_MAX_STRINGS) {
 		dev_err(&pdev->dev, "Invalid strings info, use default");
-		wled->num_strings = QPNP_WLED_MAX_STRINGS;
+		wled->num_strings = wled->max_strings;
 		for (i = 0; i < wled->num_strings; i++)
 			wled->strings[i] = i;
 	} else {
@@ -2118,6 +2352,9 @@
 
 	wled->lcd_psm_ctrl = of_property_read_bool(pdev->dev.of_node,
 				"qcom,lcd-psm-ctrl");
+
+	wled->auto_calib_enabled = of_property_read_bool(pdev->dev.of_node,
+					"qcom,auto-calibration-enable");
 	return 0;
 }
 
@@ -2186,13 +2423,13 @@
 	}
 
 	mutex_init(&wled->bus_lock);
+	mutex_init(&wled->lock);
 	rc = qpnp_wled_config(wled);
 	if (rc) {
 		dev_err(&pdev->dev, "wled config failed\n");
 		return rc;
 	}
 
-	mutex_init(&wled->lock);
 	INIT_WORK(&wled->work, qpnp_wled_work);
 	wled->ramp_ms = QPNP_WLED_RAMP_DLY_MS;
 	wled->ramp_step = 1;
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index 794ce78..f923db5 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -11,7 +11,7 @@
  *
  */
 
-#define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__
+#define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME
 
 #include <linux/atomic.h>
 #include <linux/bitmap.h>
@@ -253,7 +253,6 @@
 			break;
 		}
 		pos++;
-		udelay(1);
 	} while (1);
 	spin_unlock_irqrestore(&pool->lock, flags);
 
@@ -271,7 +270,7 @@
 		return;
 
 	msg = resp->msg;
-	pr_warn("Response object idx=%d:\n\tfor-tcs=%d\tin-use=%d\n",
+	pr_warn("Response object [idx=%d for-tcs=%d in-use=%d]\n",
 			resp->idx, resp->m, resp->in_use);
 	pr_warn("Msg: state=%d\n", msg->state);
 	for (i = 0; i < msg->num_payload; i++)
@@ -455,8 +454,10 @@
 			sts = read_tcs_reg(base, TCS_DRV_CMD_STATUS, m, i);
 			if ((!(sts & CMD_STATUS_ISSUED)) ||
 				((resp->msg->is_complete || cmd->complete) &&
-				(!(sts & CMD_STATUS_COMPL))))
+				(!(sts & CMD_STATUS_COMPL)))) {
 				resp->err = -EIO;
+				break;
+			}
 		}
 
 		/* Check for response if this was a read request */
@@ -474,6 +475,8 @@
 		tcs = get_tcs_from_index(drv, m);
 		if (tcs && tcs->type != ACTIVE_TCS) {
 			data = read_tcs_reg(base, TCS_DRV_CONTROL, m, 0);
+			data &= ~TCS_AMC_MODE_TRIGGER;
+			write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, data);
 			data &= ~TCS_AMC_MODE_ENABLE;
 			write_tcs_reg(base, TCS_DRV_CONTROL, m, 0, data);
 			/*
@@ -554,7 +557,7 @@
 	u32 msgid, cmd_msgid = 0;
 	u32 cmd_enable = 0;
 	u32 cmd_complete;
-	u32 enable = TCS_AMC_MODE_ENABLE;
+	u32 enable;
 	struct tcs_cmd *cmd;
 	int i;
 	void __iomem *base = drv->reg_base;
@@ -588,12 +591,22 @@
 	write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, cmd_enable);
 
 	if (trigger) {
-		/* HW req: Clear the DRV_CONTROL and enable TCS again */
-		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, 0);
+		/*
+		 * HW req: Clear the DRV_CONTROL and enable TCS again
+		 * While clearing ensure that the AMC mode trigger is cleared
+		 * and then the mode enable is cleared.
+		 */
+		enable = read_tcs_reg(base, TCS_DRV_CONTROL, m, 0);
+		enable &= ~TCS_AMC_MODE_TRIGGER;
 		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, enable);
-		/* Enable the AMC mode on the TCS */
+		enable &= ~TCS_AMC_MODE_ENABLE;
+		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, enable);
+
+		/* Enable the AMC mode on the TCS and then trigger the TCS */
+		enable = TCS_AMC_MODE_ENABLE;
+		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, enable);
 		enable |= TCS_AMC_MODE_TRIGGER;
-		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, enable);
+		write_tcs_reg(base, TCS_DRV_CONTROL, m, 0, enable);
 	}
 }
 
@@ -697,7 +710,8 @@
 	int n = 0;
 
 	/* For active requests find the first free AMC. */
-	if (tcs->type == ACTIVE_TCS)
+	if (msg->state == RPMH_ACTIVE_ONLY_STATE ||
+			msg->state == RPMH_AWAKE_STATE)
 		return find_free_tcs(tcs);
 
 	/* Find if we already have the msg in our TCS */
@@ -810,6 +824,10 @@
 		spin_lock_irqsave(&tcs->tcs_lock, flags);
 		for (i = 0; i < tcs->num_tcs; i++) {
 			m = i + tcs->tcs_offset;
+			if (!tcs_is_free(drv, m)) {
+				spin_unlock_irqrestore(&tcs->tcs_lock, flags);
+				return -EBUSY;
+			}
 			__tcs_buffer_invalidate(drv->reg_base, m);
 		}
 		/* Mark the TCS as free */
@@ -825,7 +843,7 @@
 	int n;
 	struct tcs_mbox *tcs = get_tcs_from_index(drv, m);
 	void __iomem *base = drv->reg_base;
-	u32 enable, addr, data, msgid;
+	u32 enable, addr, data, msgid, sts, irq_sts;
 
 	if (!tcs || tcs_is_free(drv, m))
 		return;
@@ -834,15 +852,24 @@
 	if (!enable)
 		return;
 
-	pr_warn("TCS-%d contents:\n", m);
+	pr_warn("RSC:%s\n", drv->name);
+
+	sts = read_tcs_reg(base, TCS_DRV_STATUS, m, 0);
+	data = read_tcs_reg(base, TCS_DRV_CONTROL, m, 0);
+	irq_sts = read_tcs_reg(base, TCS_DRV_IRQ_STATUS, 0, 0);
+	pr_warn("TCS=%d [ctrlr-sts:%s amc-mode:0x%x irq-sts:%s]\n",
+			m, sts ? "IDLE" : "BUSY", data,
+			(irq_sts & BIT(m)) ? "COMPLETED" : "PENDING");
+
 	for (n = 0; n < tcs->ncpt; n++) {
 		if (!(enable & BIT(n)))
 			continue;
 		addr = read_tcs_reg(base, TCS_DRV_CMD_ADDR, m, n);
 		data = read_tcs_reg(base, TCS_DRV_CMD_DATA, m, n);
 		msgid = read_tcs_reg(base, TCS_DRV_CMD_MSGID, m, n);
-		pr_warn("\tn=%d addr=0x%x data=0x%x hdr=0x%x\n",
-						n, addr, data, msgid);
+		sts = read_tcs_reg(base, TCS_DRV_CMD_STATUS, m, n);
+		pr_warn("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x]\n",
+						n, addr, data, msgid, sts);
 	}
 }
 
@@ -896,7 +923,8 @@
 		goto tx_fail;
 	}
 
-	if (!msg->payload || msg->num_payload > MAX_RPMH_PAYLOAD) {
+	if (!msg->payload || !msg->num_payload ||
+			msg->num_payload > MAX_RPMH_PAYLOAD) {
 		dev_err(dev, "Payload error\n");
 		ret = -EINVAL;
 		goto tx_fail;
@@ -926,8 +954,11 @@
 	 * Since we are re-purposing the wake TCS, invalidate previous
 	 * contents to avoid confusion.
 	 */
-	if (msg->state == RPMH_AWAKE_STATE)
-		tcs_mbox_invalidate(chan);
+	if (msg->state == RPMH_AWAKE_STATE) {
+		ret = tcs_mbox_invalidate(chan);
+		if (ret)
+			goto tx_fail;
+	}
 
 	/* Post the message to the TCS and trigger */
 	ret = tcs_mbox_write(chan, msg, true);
@@ -939,8 +970,10 @@
 				drv, msg, chan, TCS_M_INIT, ret);
 
 		dev_err(dev, "Error sending RPMH message %d\n", ret);
-		if (resp)
+		if (!IS_ERR(resp))
 			send_tcs_response(resp);
+		else
+			dev_err(dev, "No response object %ld\n", PTR_ERR(resp));
 		ret = 0;
 	}
 
@@ -1007,7 +1040,8 @@
 		goto tx_done;
 	}
 
-	if (msg->num_payload > MAX_RPMH_PAYLOAD) {
+	if (!msg->payload || (!msg->num_payload && !msg->invalidate) ||
+			msg->num_payload > MAX_RPMH_PAYLOAD) {
 		dev_err(dev, "Payload error\n");
 		goto tx_done;
 	}
@@ -1147,7 +1181,8 @@
 		if (tcs->num_tcs > MAX_TCS_PER_TYPE)
 			return -EINVAL;
 
-		if (st > max_tcs)
+		if (st + tcs->num_tcs > max_tcs &&
+				st + tcs->num_tcs >= sizeof(tcs->tcs_mask))
 			return -EINVAL;
 
 		tcs->tcs_mask = ((1 << tcs->num_tcs) - 1) << st;
@@ -1169,10 +1204,12 @@
 		for (j = 0; j < i; j++) {
 			ret = of_parse_phandle_with_args(np, "mboxes",
 							"#mbox-cells", j, &p);
-			if (!ret && p.np == pdev->dev.of_node)
+			of_node_put(p.np);
+			if (!ret && p.np == pdev->dev.of_node) {
+				num_chans++;
 				break;
+			}
 		}
-		num_chans++;
 	}
 
 	if (!num_chans) {
diff --git a/drivers/md/dm-android-verity.c b/drivers/md/dm-android-verity.c
index 3b19017..eb4bdf6 100644
--- a/drivers/md/dm-android-verity.c
+++ b/drivers/md/dm-android-verity.c
@@ -646,6 +646,8 @@
         android_verity_target.direct_access = dm_linear_direct_access,
 	android_verity_target.io_hints = NULL;
 
+	set_disk_ro(dm_disk(dm_table_get_md(ti->table)), 0);
+
 	err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);
 
 	if (!err) {
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index ac8235b..0d437c9 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -431,7 +431,7 @@
 	unsigned long flags;
 	struct priority_group *pg;
 	struct pgpath *pgpath;
-	bool bypassed = true;
+	unsigned bypassed = 1;
 
 	if (!atomic_read(&m->nr_valid_paths)) {
 		clear_bit(MPATHF_QUEUE_IO, &m->flags);
@@ -470,7 +470,7 @@
 	 */
 	do {
 		list_for_each_entry(pg, &m->priority_groups, list) {
-			if (pg->bypassed == bypassed)
+			if (pg->bypassed == !!bypassed)
 				continue;
 			pgpath = choose_path_in_pg(m, pg, nr_bytes);
 			if (!IS_ERR_OR_NULL(pgpath)) {
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 29e2df5..81a7875 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1073,7 +1073,7 @@
 		 */
 		DEFINE_WAIT(w);
 		for (;;) {
-			flush_signals(current);
+			sigset_t full, old;
 			prepare_to_wait(&conf->wait_barrier,
 					&w, TASK_INTERRUPTIBLE);
 			if (bio_end_sector(bio) <= mddev->suspend_lo ||
@@ -1082,7 +1082,10 @@
 			     !md_cluster_ops->area_resyncing(mddev, WRITE,
 				     bio->bi_iter.bi_sector, bio_end_sector(bio))))
 				break;
+			sigfillset(&full);
+			sigprocmask(SIG_BLOCK, &full, &old);
 			schedule();
+			sigprocmask(SIG_SETMASK, &old, NULL);
 		}
 		finish_wait(&conf->wait_barrier, &w);
 	}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f34ad2b..8f117d6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5300,12 +5300,15 @@
 				 * userspace, we want an interruptible
 				 * wait.
 				 */
-				flush_signals(current);
 				prepare_to_wait(&conf->wait_for_overlap,
 						&w, TASK_INTERRUPTIBLE);
 				if (logical_sector >= mddev->suspend_lo &&
 				    logical_sector < mddev->suspend_hi) {
+					sigset_t full, old;
+					sigfillset(&full);
+					sigprocmask(SIG_BLOCK, &full, &old);
 					schedule();
+					sigprocmask(SIG_SETMASK, &old, NULL);
 					do_prepare = true;
 				}
 				goto retry;
@@ -7557,12 +7560,10 @@
 {
 
 	if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
-		struct md_rdev *rdev;
 
 		spin_lock_irq(&conf->device_lock);
 		conf->previous_raid_disks = conf->raid_disks;
-		rdev_for_each(rdev, conf->mddev)
-			rdev->data_offset = rdev->new_data_offset;
+		md_finish_reshape(conf->mddev);
 		smp_wmb();
 		conf->reshape_progress = MaxSector;
 		conf->mddev->reshape_position = MaxSector;
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index e868f92..f2d39a9 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -448,7 +448,7 @@
 				bytes_read = 0;
 			}
 		} else {
-			if (bytes_read)
+			if (bytes_read) {
 				/*
 				 * data was read beyond the non-data event,
 				 * making it not relevant anymore
@@ -459,6 +459,7 @@
 				if (!(events->event_mask.no_wakeup_mask &
 					event->type))
 					events->wakeup_events_counter--;
+			}
 		}
 
 		events->read_index = events->notified_index;
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index 8f2556e..61611d1 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -3691,7 +3691,14 @@
 	core->nr = nr;
 	sprintf(core->name, "cx88[%d]", core->nr);
 
-	core->tvnorm = V4L2_STD_NTSC_M;
+	/*
+	 * Note: Setting initial standard here would cause first call to
+	 * cx88_set_tvnorm() to return without programming any registers.  Leave
+	 * it blank for at this point and it will get set later in
+	 * cx8800_initdev()
+	 */
+	core->tvnorm  = 0;
+
 	core->width   = 320;
 	core->height  = 240;
 	core->field   = V4L2_FIELD_INTERLACED;
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index d83eb3b..3b140ad 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -1422,7 +1422,7 @@
 
 	/* initial device configuration */
 	mutex_lock(&core->lock);
-	cx88_set_tvnorm(core, core->tvnorm);
+	cx88_set_tvnorm(core, V4L2_STD_NTSC_M);
 	v4l2_ctrl_handler_setup(&core->video_hdl);
 	v4l2_ctrl_handler_setup(&core->audio_hdl);
 	cx88_video_mux(core, 0);
diff --git a/drivers/media/platform/msm/broadcast/tspp.c b/drivers/media/platform/msm/broadcast/tspp.c
index 7717759..2c90e47 100644
--- a/drivers/media/platform/msm/broadcast/tspp.c
+++ b/drivers/media/platform/msm/broadcast/tspp.c
@@ -24,6 +24,7 @@
 #include <linux/uaccess.h>       /* copy_to_user */
 #include <linux/slab.h>          /* kfree, kzalloc */
 #include <linux/ioport.h>        /* XXX_ mem_region */
+#include <asm/dma-iommu.h>
 #include <linux/dma-mapping.h>   /* dma_XXX */
 #include <linux/dmapool.h>       /* DMA pools */
 #include <linux/delay.h>         /* msleep */
@@ -46,6 +47,7 @@
 #include <linux/msm-bus.h>
 #include <linux/interrupt.h>	/* tasklet */
 #include <asm/arch_timer.h> /* Timer */
+#include <linux/dma-buf.h>
 
 /*
  * General defines
@@ -59,6 +61,10 @@
 #define TSPP_NUM_KEYS                  8
 #define INVALID_CHANNEL                0xFFFFFFFF
 #define TSPP_BAM_DEFAULT_IPC_LOGLVL    2
+
+#define TSPP_SMMU_IOVA_START	(0x10000000)
+#define TSPP_SMMU_IOVA_SIZE	(0x40000000)
+
 /*
  * BAM descriptor FIFO size (in number of descriptors).
  * Max number of descriptors allowed by SPS which is 8K-1.
@@ -489,6 +495,7 @@
 	struct mutex mutex;
 	struct tspp_pinctrl pinctrl;
 	unsigned int tts_source; /* Time stamp source type LPASS timer/TCR */
+	struct dma_iommu_mapping *iommu_mapping;
 
 	struct dentry *dent;
 	struct dentry *debugfs_regs[ARRAY_SIZE(debugfs_tspp_regs)];
@@ -1058,6 +1065,35 @@
 	tspp_key_entry &= ~(1 << entry);
 }
 
+static int tspp_iommu_init(struct tspp_device *device)
+{
+	struct dma_iommu_mapping *iommu_map;
+
+	iommu_map = arm_iommu_create_mapping(&platform_bus_type,
+						TSPP_SMMU_IOVA_START,
+						TSPP_SMMU_IOVA_SIZE);
+	if (IS_ERR(iommu_map)) {
+		dev_err(&device->pdev->dev, "iommu_create_mapping failure\n");
+		return PTR_ERR(iommu_map);
+	}
+	if (arm_iommu_attach_device(&device->pdev->dev, iommu_map)) {
+		dev_err(&device->pdev->dev, "can't arm_iommu_attach_device\n");
+		arm_iommu_release_mapping(iommu_map);
+		return -EIO;
+	}
+
+	device->iommu_mapping = iommu_map;
+	return 0;
+}
+
+static void tspp_iommu_release_iomapping(struct tspp_device *device)
+{
+	if (device->iommu_mapping)
+		arm_iommu_release_mapping(device->iommu_mapping);
+
+	device->iommu_mapping = NULL;
+}
+
 static int tspp_alloc_buffer(u32 channel_id, struct tspp_data_descriptor *desc,
 	u32 size, struct dma_pool *dma_pool, tspp_allocator *alloc, void *user)
 {
@@ -1070,7 +1106,7 @@
 	if (alloc) {
 		TSPP_DEBUG("tspp using alloc function");
 		desc->virt_base = alloc(channel_id, size,
-			&desc->phys_base, user);
+			&desc->phys_base, &desc->dma_base, user);
 	} else {
 		if (!dma_pool)
 			desc->virt_base = dma_alloc_coherent(NULL, size,
@@ -2562,7 +2598,8 @@
 		desc->next = channel->data;
 
 		/* prepare the sps descriptor */
-		desc->sps.phys_base = desc->desc.phys_base;
+		desc->sps.phys_base = ((alloc != NULL) ? desc->desc.dma_base :
+				       desc->desc.phys_base);
 		desc->sps.base = desc->desc.virt_base;
 		desc->sps.size = desc->desc.size;
 
@@ -2600,6 +2637,121 @@
 }
 EXPORT_SYMBOL(tspp_allocate_buffers);
 
+/**
+ * tspp_attach_ion_dma_buff- attach ion dma buffer to TSPP device
+ * It will attach the DMA buffer to TSPP device to go through SMMU.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @ion_dma_buf: It contains required members for ION buffer dma mapping.
+ *
+ * Return  error status
+ *
+ */
+int tspp_attach_ion_dma_buff(u32 dev, struct tspp_ion_dma_buf_info *ion_dma_buf)
+{
+	struct tspp_device *pdev;
+	int dir = DMA_FROM_DEVICE;
+	int ret = -1;
+
+	if (NULL == ion_dma_buf || NULL == ion_dma_buf->dbuf) {
+		pr_err("tspp: invalid input argument");
+		return -EINVAL;
+	}
+
+	if (dev >= TSPP_MAX_DEVICES) {
+		pr_err("tspp: device id out of range");
+		return -ENODEV;
+	}
+
+	pdev = tspp_find_by_id(dev);
+	if (!pdev) {
+		pr_err("tspp: can't find device %i", dev);
+		return -ENODEV;
+	}
+
+	ion_dma_buf->attach = dma_buf_attach(ion_dma_buf->dbuf,
+					&pdev->pdev->dev);
+	if (IS_ERR_OR_NULL(ion_dma_buf->attach)) {
+		dev_err(&pdev->pdev->dev, "%s: dma_buf_attach fail", __func__);
+		return -ENODEV;
+	}
+	ion_dma_buf->table = dma_buf_map_attachment(ion_dma_buf->attach, dir);
+	if (IS_ERR_OR_NULL(ion_dma_buf->table)) {
+		dev_err(&pdev->pdev->dev, "dma_buf_map_attachment fail");
+		dma_buf_detach(ion_dma_buf->dbuf, ion_dma_buf->attach);
+		return -ENODEV;
+	}
+	ret = dma_map_sg(&pdev->pdev->dev, ion_dma_buf->table->sgl,
+				ion_dma_buf->table->nents, dir);
+	if (ret <= 0) {
+		dev_err(&pdev->pdev->dev, "dma_map_sg failed! ret=%d\n", ret);
+		goto unmap_attachment;
+	}
+	if (ion_dma_buf->table->nents > 1) {
+		dev_err(&pdev->pdev->dev, "no of sg table entries %d > 1\n",
+			ion_dma_buf->table->nents);
+		goto unmap_attachment;
+	}
+
+	ion_dma_buf->dma_map_base = sg_dma_address(ion_dma_buf->table->sgl);
+	ion_dma_buf->smmu_map = true;
+	return 0;
+
+unmap_attachment:
+	dma_buf_unmap_attachment(ion_dma_buf->attach, ion_dma_buf->table, dir);
+	dma_buf_detach(ion_dma_buf->dbuf, ion_dma_buf->attach);
+	dma_buf_put(ion_dma_buf->dbuf);
+
+	return ret;
+}
+EXPORT_SYMBOL(tspp_attach_ion_dma_buff);
+
+/**
+ * tspp_detach_ion_dma_buff - detach the mapped ion dma buffer from TSPP device
+ * It will detach previously mapped DMA buffer from TSPP device.
+ *
+ * @dev: TSPP device (up to TSPP_MAX_DEVICES)
+ * @ion_dma_buf: It contains required members for ION buffer dma mapping.
+ *
+ * Return  error status
+ *
+ */
+int tspp_detach_ion_dma_buff(u32 dev, struct tspp_ion_dma_buf_info *ion_dma_buf)
+{
+	struct tspp_device *pdev;
+	int dir = DMA_FROM_DEVICE;
+
+	if (ion_dma_buf == NULL || ion_dma_buf->dbuf == NULL ||
+	    ion_dma_buf->table == NULL || ion_dma_buf->table->sgl == NULL ||
+	    ion_dma_buf->smmu_map == false) {
+		pr_err("tspp: invalid input argument");
+		return -EINVAL;
+	}
+
+	if (dev >= TSPP_MAX_DEVICES) {
+		pr_err("tspp: device id out of range");
+		return -ENODEV;
+	}
+
+	pdev = tspp_find_by_id(dev);
+	if (!pdev) {
+		pr_err("tspp: can't find device %i", dev);
+		return -ENODEV;
+	}
+
+
+	dma_unmap_sg(&pdev->pdev->dev, ion_dma_buf->table->sgl,
+			ion_dma_buf->table->nents, dir);
+	dma_buf_unmap_attachment(ion_dma_buf->attach, ion_dma_buf->table, dir);
+	dma_buf_detach(ion_dma_buf->dbuf, ion_dma_buf->attach);
+	dma_buf_put(ion_dma_buf->dbuf);
+
+	ion_dma_buf->smmu_map = false;
+	return 0;
+}
+EXPORT_SYMBOL(tspp_detach_ion_dma_buff);
+
+
 /*** debugfs ***/
 static int debugfs_iomem_x32_set(void *data, u64 val)
 {
@@ -2959,6 +3111,11 @@
 		goto err_irq;
 	device->req_irqs = false;
 
+	if (tspp_iommu_init(device)) {
+		dev_err(&pdev->dev, "iommu init failed");
+		goto err_iommu;
+	}
+
 	device->tts_source = TSIF_TTS_TCR;
 	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
 		device->tsif[i].tts_source = device->tts_source;
@@ -3029,6 +3186,8 @@
 	tspp_debugfs_exit(device);
 	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
 		tsif_debugfs_exit(&device->tsif[i]);
+err_iommu:
+	tspp_iommu_release_iomapping(device);
 err_irq:
 	iounmap(device->bam_props.virt_addr);
 err_map_bam:
@@ -3099,6 +3258,9 @@
 	if (device->tsif_vreg)
 		regulator_disable(device->tsif_vreg);
 
+	tspp_iommu_release_iomapping(device);
+	arm_iommu_detach_device(&pdev->dev);
+
 	pm_runtime_disable(&pdev->dev);
 
 	kfree(device);
diff --git a/drivers/media/platform/msm/camera/Makefile b/drivers/media/platform/msm/camera/Makefile
index 99bd263..800c9ea 100644
--- a/drivers/media/platform/msm/camera/Makefile
+++ b/drivers/media/platform/msm/camera/Makefile
@@ -8,3 +8,4 @@
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_module/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg/
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
index 38f13c4..03f6e0c 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
@@ -27,23 +27,12 @@
 #include "cam_cpas_api.h"
 #include "cam_hw_intf.h"
 #include "cam_hw.h"
-
-#ifdef CONFIG_CAM_CDM_DBG
-#define CDM_CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDM_CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
-#ifdef CONFIG_CAM_CDM_DUMP_DBG
-#define CDM_DUMP_CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDM_DUMP_CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
+#include "cam_debug_util.h"
 
 #define CAM_MAX_SW_CDM_VERSION_SUPPORTED  1
 #define CAM_SW_CDM_INDEX                  0
 #define CAM_CDM_INFLIGHT_WORKS            5
-#define CAM_CDM_HW_RESET_TIMEOUT          3000
+#define CAM_CDM_HW_RESET_TIMEOUT          300
 
 #define CAM_CDM_HW_ID_MASK      0xF
 #define CAM_CDM_HW_ID_SHIFT     0x5
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c
index 3604357..6c8bde1 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-CDM-CORE %s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -32,7 +30,7 @@
 static void cam_cdm_get_client_refcount(struct cam_cdm_client *client)
 {
 	mutex_lock(&client->lock);
-	CDM_CDBG("CDM client get refcount=%d\n",
+	CAM_DBG(CAM_CDM, "CDM client get refcount=%d",
 		client->refcount);
 	client->refcount++;
 	mutex_unlock(&client->lock);
@@ -41,12 +39,12 @@
 static void cam_cdm_put_client_refcount(struct cam_cdm_client *client)
 {
 	mutex_lock(&client->lock);
-	CDM_CDBG("CDM client put refcount=%d\n",
+	CAM_DBG(CAM_CDM, "CDM client put refcount=%d",
 		client->refcount);
 	if (client->refcount > 0) {
 		client->refcount--;
 	} else {
-		pr_err("Refcount put when zero\n");
+		CAM_ERR(CAM_CDM, "Refcount put when zero");
 		WARN_ON(1);
 	}
 	mutex_unlock(&client->lock);
@@ -63,16 +61,16 @@
 		cam_version->reserved = 0;
 		return true;
 	default:
-		pr_err("CDM Version=%x not supported in util\n", ver);
+		CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", ver);
 	break;
 	}
 	return false;
 }
 
-void cam_cdm_cpas_cb(int32_t client_handle, void *userdata,
+void cam_cdm_cpas_cb(uint32_t client_handle, void *userdata,
 	enum cam_camnoc_irq_type evt_type, uint32_t evt_data)
 {
-	pr_err("CPAS error callback type=%d with data=%x\n", evt_type,
+	CAM_ERR(CAM_CDM, "CPAS error callback type=%d with data=%x", evt_type,
 		evt_data);
 }
 
@@ -84,13 +82,14 @@
 		case CAM_CDM170_VERSION:
 			return &CDM170_ops;
 		default:
-			pr_err("CDM Version=%x not supported in util\n", ver);
+			CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util",
+				ver);
 		}
 	} else if (cam_version) {
 		if ((cam_version->major == 1) && (cam_version->minor == 0) &&
 			(cam_version->incr == 0))
 			return &CDM170_ops;
-		pr_err("cam_hw_version=%x:%x:%x not supported\n",
+		CAM_ERR(CAM_CDM, "cam_hw_version=%x:%x:%x not supported",
 			cam_version->major, cam_version->minor,
 			cam_version->incr);
 	}
@@ -107,7 +106,7 @@
 		if (node->bl_tag == tag)
 			return node;
 	}
-	pr_err("Could not find the bl request for tag=%x\n", tag);
+	CAM_ERR(CAM_CDM, "Could not find the bl request for tag=%x", tag);
 
 	return NULL;
 }
@@ -135,11 +134,11 @@
 
 	for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
 		if (hw->clients[i] == NULL) {
-			CDM_CDBG("Found client slot %d\n", i);
+			CAM_DBG(CAM_CDM, "Found client slot %d", i);
 			return i;
 		}
 	}
-	pr_err("No more client slots\n");
+	CAM_ERR(CAM_CDM, "No more client slots");
 
 	return -EBUSY;
 }
@@ -153,7 +152,7 @@
 	struct cam_cdm_client *client = NULL;
 
 	if (!cdm_hw) {
-		pr_err("CDM Notify called with NULL hw info\n");
+		CAM_ERR(CAM_CDM, "CDM Notify called with NULL hw info");
 		return;
 	}
 	core = (struct cam_cdm *)cdm_hw->core_info;
@@ -166,20 +165,21 @@
 		client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
 		client = core->clients[client_idx];
 		if ((!client) || (client->handle != node->client_hdl)) {
-			pr_err("Invalid client %pK hdl=%x\n", client,
+			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
 				node->client_hdl);
 			return;
 		}
 		cam_cdm_get_client_refcount(client);
 		if (client->data.cam_cdm_callback) {
-			CDM_CDBG("Calling client=%s cb cookie=%d\n",
+			CAM_DBG(CAM_CDM, "Calling client=%s cb cookie=%d",
 				client->data.identifier, node->cookie);
 			client->data.cam_cdm_callback(node->client_hdl,
 				node->userdata, CAM_CDM_CB_STATUS_BL_SUCCESS,
 				node->cookie);
-			CDM_CDBG("Exit client cb cookie=%d\n", node->cookie);
+			CAM_DBG(CAM_CDM, "Exit client cb cookie=%d",
+				node->cookie);
 		} else {
-			pr_err("No cb registered for client hdl=%x\n",
+			CAM_ERR(CAM_CDM, "No cb registered for client hdl=%x",
 				node->client_hdl);
 		}
 		cam_cdm_put_client_refcount(client);
@@ -190,7 +190,7 @@
 		if (core->clients[i] != NULL) {
 			client = core->clients[i];
 			mutex_lock(&client->lock);
-			CDM_CDBG("Found client slot %d\n", i);
+			CAM_DBG(CAM_CDM, "Found client slot %d", i);
 			if (client->data.cam_cdm_callback) {
 				if (status == CAM_CDM_CB_STATUS_PAGEFAULT) {
 					unsigned long iova =
@@ -203,7 +203,8 @@
 						(iova & 0xFFFFFFFF));
 				}
 			} else {
-				pr_err("No cb registered for client hdl=%x\n",
+				CAM_ERR(CAM_CDM,
+					"No cb registered for client hdl=%x",
 					client->handle);
 			}
 			mutex_unlock(&client->lock);
@@ -228,24 +229,26 @@
 	client_idx = CAM_CDM_GET_CLIENT_IDX(*handle);
 	client = core->clients[client_idx];
 	if (!client) {
-		pr_err("Invalid client %pK hdl=%x\n", client, *handle);
+		CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle);
 		return -EINVAL;
 	}
 	cam_cdm_get_client_refcount(client);
 	if (*handle != client->handle) {
-		pr_err("client id given handle=%x invalid\n", *handle);
+		CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle);
 		cam_cdm_put_client_refcount(client);
 		return -EINVAL;
 	}
 	if (operation == true) {
 		if (true == client->stream_on) {
-			pr_err("Invalid CDM client is already streamed ON\n");
+			CAM_ERR(CAM_CDM,
+				"Invalid CDM client is already streamed ON");
 			cam_cdm_put_client_refcount(client);
 			return rc;
 		}
 	} else {
 		if (client->stream_on == false) {
-			pr_err("Invalid CDM client is already streamed Off\n");
+			CAM_ERR(CAM_CDM,
+				"Invalid CDM client is already streamed Off");
 			cam_cdm_put_client_refcount(client);
 			return rc;
 		}
@@ -265,26 +268,28 @@
 			rc = cam_cpas_start(core->cpas_handle,
 				&ahb_vote, &axi_vote);
 			if (rc != 0) {
-				pr_err("CPAS start failed\n");
+				CAM_ERR(CAM_CDM, "CPAS start failed");
 				goto end;
 			}
-			CDM_CDBG("CDM init first time\n");
+			CAM_DBG(CAM_CDM, "CDM init first time");
 			if (core->id == CAM_CDM_VIRTUAL) {
-				CDM_CDBG("Virtual CDM HW init first time\n");
+				CAM_DBG(CAM_CDM,
+					"Virtual CDM HW init first time");
 				rc = 0;
 			} else {
-				CDM_CDBG("CDM HW init first time\n");
+				CAM_DBG(CAM_CDM, "CDM HW init first time");
 				rc = cam_hw_cdm_init(hw_priv, NULL, 0);
 				if (rc == 0) {
 					rc = cam_hw_cdm_alloc_genirq_mem(
 						hw_priv);
 					if (rc != 0) {
-						pr_err("Genirqalloc failed\n");
+						CAM_ERR(CAM_CDM,
+							"Genirqalloc failed");
 						cam_hw_cdm_deinit(hw_priv,
 							NULL, 0);
 					}
 				} else {
-					pr_err("CDM HW init failed\n");
+					CAM_ERR(CAM_CDM, "CDM HW init failed");
 				}
 			}
 			if (rc == 0) {
@@ -292,11 +297,11 @@
 				client->stream_on = true;
 			} else {
 				if (cam_cpas_stop(core->cpas_handle))
-					pr_err("CPAS stop failed\n");
+					CAM_ERR(CAM_CDM, "CPAS stop failed");
 			}
 		} else {
 			cdm_hw->open_count++;
-			CDM_CDBG("CDM HW already ON count=%d\n",
+			CAM_DBG(CAM_CDM, "CDM HW already ON count=%d",
 				cdm_hw->open_count);
 			rc = 0;
 			client->stream_on = true;
@@ -304,35 +309,41 @@
 	} else {
 		if (cdm_hw->open_count) {
 			cdm_hw->open_count--;
-			CDM_CDBG("stream OFF CDM %d\n", cdm_hw->open_count);
+			CAM_DBG(CAM_CDM, "stream OFF CDM %d",
+				cdm_hw->open_count);
 			if (!cdm_hw->open_count) {
-				CDM_CDBG("CDM Deinit now\n");
+				CAM_DBG(CAM_CDM, "CDM Deinit now");
 				if (core->id == CAM_CDM_VIRTUAL) {
-					CDM_CDBG("Virtual CDM HW Deinit\n");
+					CAM_DBG(CAM_CDM,
+						"Virtual CDM HW Deinit");
 					rc = 0;
 				} else {
-					CDM_CDBG("CDM HW Deinit now\n");
+					CAM_DBG(CAM_CDM, "CDM HW Deinit now");
 					rc = cam_hw_cdm_deinit(
 						hw_priv, NULL, 0);
 					if (cam_hw_cdm_release_genirq_mem(
 						hw_priv))
-						pr_err("Genirq release failed\n");
+						CAM_ERR(CAM_CDM,
+							"Genirq release fail");
 				}
 				if (rc) {
-					pr_err("Deinit failed in streamoff\n");
+					CAM_ERR(CAM_CDM,
+						"Deinit failed in streamoff");
 				} else {
 					client->stream_on = false;
 					rc = cam_cpas_stop(core->cpas_handle);
 					if (rc)
-						pr_err("CPAS stop failed\n");
+						CAM_ERR(CAM_CDM,
+							"CPAS stop failed");
 				}
 			} else {
 				client->stream_on = false;
-				CDM_CDBG("Client stream off success =%d\n",
+				CAM_DBG(CAM_CDM,
+					"Client stream off success =%d",
 					cdm_hw->open_count);
 			}
 		} else {
-			CDM_CDBG("stream OFF CDM Invalid %d\n",
+			CAM_DBG(CAM_CDM, "stream OFF CDM Invalid %d",
 				cdm_hw->open_count);
 			rc = -ENXIO;
 		}
@@ -390,33 +401,35 @@
 		struct cam_cdm_client *client;
 
 		if (sizeof(struct cam_cdm_hw_intf_cmd_submit_bl) != arg_size) {
-			pr_err("Invalid CDM cmd %d arg size=%x\n", cmd,
+			CAM_ERR(CAM_CDM, "Invalid CDM cmd %d arg size=%x", cmd,
 				arg_size);
 			break;
 		}
 		req = (struct cam_cdm_hw_intf_cmd_submit_bl *)cmd_args;
 		if ((req->data->type < 0) ||
 			(req->data->type > CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA)) {
-			pr_err("Invalid req bl cmd addr type=%d\n",
+			CAM_ERR(CAM_CDM, "Invalid req bl cmd addr type=%d",
 				req->data->type);
 			break;
 		}
 		idx = CAM_CDM_GET_CLIENT_IDX(req->handle);
 		client = core->clients[idx];
 		if ((!client) || (req->handle != client->handle)) {
-			pr_err("Invalid client %pK hdl=%x\n", client,
+			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
 				req->handle);
 			break;
 		}
 		cam_cdm_get_client_refcount(client);
 		if ((req->data->flag == true) &&
 			(!client->data.cam_cdm_callback)) {
-			pr_err("CDM request cb without registering cb\n");
+			CAM_ERR(CAM_CDM,
+				"CDM request cb without registering cb");
 			cam_cdm_put_client_refcount(client);
 			break;
 		}
 		if (client->stream_on != true) {
-			pr_err("Invalid CDM needs to be streamed ON first\n");
+			CAM_ERR(CAM_CDM,
+				"Invalid CDM needs to be streamed ON first");
 			cam_cdm_put_client_refcount(client);
 			break;
 		}
@@ -434,19 +447,20 @@
 		struct cam_cdm_client *client;
 
 		if (sizeof(struct cam_cdm_acquire_data) != arg_size) {
-			pr_err("Invalid CDM cmd %d arg size=%x\n", cmd,
+			CAM_ERR(CAM_CDM, "Invalid CDM cmd %d arg size=%x", cmd,
 				arg_size);
 			break;
 		}
 
 		mutex_lock(&cdm_hw->hw_mutex);
 		data = (struct cam_cdm_acquire_data *)cmd_args;
-		CDM_CDBG("Trying to acquire client=%s in hw idx=%d\n",
+		CAM_DBG(CAM_CDM, "Trying to acquire client=%s in hw idx=%d",
 			data->identifier, core->index);
 		idx = cam_cdm_find_free_client_slot(core);
 		if ((idx < 0) || (core->clients[idx])) {
 			mutex_unlock(&cdm_hw->hw_mutex);
-			pr_err("Failed to client slots for client=%s in hw idx=%d\n",
+			CAM_ERR(CAM_CDM,
+				"Fail to client slots, client=%s in hw idx=%d",
 			data->identifier, core->index);
 			break;
 		}
@@ -477,7 +491,7 @@
 				mutex_unlock(
 					&cdm_hw->hw_mutex);
 				rc = -EPERM;
-				pr_err("Invalid ops for virtual cdm\n");
+				CAM_ERR(CAM_CDM, "Invalid ops for virtual cdm");
 				break;
 			}
 		} else {
@@ -493,7 +507,7 @@
 					idx);
 		client->stream_on = false;
 		data->handle = client->handle;
-		CDM_CDBG("Acquired client=%s in hwidx=%d\n",
+		CAM_DBG(CAM_CDM, "Acquired client=%s in hwidx=%d",
 			data->identifier, core->index);
 		mutex_unlock(&client->lock);
 		rc = 0;
@@ -505,7 +519,8 @@
 		struct cam_cdm_client *client;
 
 		if (sizeof(uint32_t) != arg_size) {
-			pr_err("Invalid CDM cmd %d size=%x for handle=%x\n",
+			CAM_ERR(CAM_CDM,
+				"Invalid CDM cmd %d size=%x for handle=%x",
 				cmd, arg_size, *handle);
 			return -EINVAL;
 		}
@@ -513,14 +528,15 @@
 		mutex_lock(&cdm_hw->hw_mutex);
 		client = core->clients[idx];
 		if ((!client) || (*handle != client->handle)) {
-			pr_err("Invalid client %pK hdl=%x\n", client, *handle);
+			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x",
+				client, *handle);
 			mutex_unlock(&cdm_hw->hw_mutex);
 			break;
 		}
 		cam_cdm_put_client_refcount(client);
 		mutex_lock(&client->lock);
 		if (client->refcount != 0) {
-			pr_err("CDM Client refcount not zero %d",
+			CAM_ERR(CAM_CDM, "CDM Client refcount not zero %d",
 				client->refcount);
 			rc = -EPERM;
 			mutex_unlock(&client->lock);
@@ -536,12 +552,12 @@
 		break;
 	}
 	case CAM_CDM_HW_INTF_CMD_RESET_HW: {
-		pr_err("CDM HW reset not supported for handle =%x\n",
+		CAM_ERR(CAM_CDM, "CDM HW reset not supported for handle =%x",
 			*((uint32_t *)cmd_args));
 		break;
 	}
 	default:
-		pr_err("CDM HW intf command not valid =%d\n", cmd);
+		CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd);
 		break;
 	}
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.h
index eb75aaa..fa3ae04 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.h
@@ -32,7 +32,7 @@
 	uint32_t arg_size);
 bool cam_cdm_set_cam_hw_version(
 	uint32_t ver, struct cam_hw_version *cam_version);
-void cam_cdm_cpas_cb(int32_t client_handle, void *userdata,
+void cam_cdm_cpas_cb(uint32_t client_handle, void *userdata,
 	enum cam_camnoc_irq_type evt_type, uint32_t evt_data);
 struct cam_cdm_utils_ops *cam_cdm_get_ops(
 	uint32_t ver, struct cam_hw_version *cam_version, bool by_cam_version);
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index 5fac7d8..5f6895c 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-CDM-HW %s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -31,7 +29,6 @@
 #include "cam_io_util.h"
 #include "cam_hw_cdm170_reg.h"
 
-
 #define CAM_HW_CDM_CPAS_0_NAME "qcom,cam170-cpas-cdm0"
 #define CAM_HW_CDM_IPE_0_NAME "qcom,cam170-ipe0-cdm"
 #define CAM_HW_CDM_IPE_1_NAME "qcom,cam170-ipe1-cdm"
@@ -65,7 +62,7 @@
 
 	if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB,
 		pending_bl)) {
-		pr_err("Failed to read CDM pending BL's\n");
+		CAM_ERR(CAM_CDM, "Failed to read CDM pending BL's");
 		rc = -EIO;
 	}
 
@@ -81,28 +78,28 @@
 
 	if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_MASK,
 		&irq_mask)) {
-		pr_err("Failed to read CDM IRQ mask\n");
+		CAM_ERR(CAM_CDM, "Failed to read CDM IRQ mask");
 		return rc;
 	}
 
 	if (enable == true) {
 		if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK,
 			(irq_mask | 0x4))) {
-			pr_err("Write failed to enable BL done irq\n");
+			CAM_ERR(CAM_CDM, "Write failed to enable BL done irq");
 		} else {
 			atomic_inc(&core->bl_done);
 			rc = 0;
-			CDM_CDBG("BL done irq enabled =%d\n",
+			CAM_DBG(CAM_CDM, "BL done irq enabled =%d",
 				atomic_read(&core->bl_done));
 		}
 	} else {
 		if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK,
 			(irq_mask & 0x70003))) {
-			pr_err("Write failed to disable BL done irq\n");
+			CAM_ERR(CAM_CDM, "Write failed to disable BL done irq");
 		} else {
 			atomic_dec(&core->bl_done);
 			rc = 0;
-			CDM_CDBG("BL done irq disable =%d\n",
+			CAM_DBG(CAM_CDM, "BL done irq disable =%d",
 				atomic_read(&core->bl_done));
 		}
 	}
@@ -115,12 +112,12 @@
 
 	if (enable == true) {
 		if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x01)) {
-			pr_err("Failed to Write CDM HW core enable\n");
+			CAM_ERR(CAM_CDM, "Failed to Write CDM HW core enable");
 			rc = -EIO;
 		}
 	} else {
 		if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x02)) {
-			pr_err("Failed to Write CDM HW core disable\n");
+			CAM_ERR(CAM_CDM, "Failed to Write CDM HW core disable");
 			rc = -EIO;
 		}
 	}
@@ -132,7 +129,7 @@
 	int rc = 0;
 
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0x10100)) {
-		pr_err("Failed to Write CDM HW core debug\n");
+		CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
 		rc = -EIO;
 	}
 
@@ -144,7 +141,7 @@
 	int rc = 0;
 
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0)) {
-		pr_err("Failed to Write CDM HW core debug\n");
+		CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
 		rc = -EIO;
 	}
 
@@ -156,31 +153,31 @@
 	uint32_t dump_reg = 0;
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg);
-	pr_err("dump core en=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump core en=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_0_REG, &dump_reg);
-	pr_err("dump scratch0=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch0=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_1_REG, &dump_reg);
-	pr_err("dump scratch1=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch1=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_2_REG, &dump_reg);
-	pr_err("dump scratch2=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch2=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_3_REG, &dump_reg);
-	pr_err("dump scratch3=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch3=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_4_REG, &dump_reg);
-	pr_err("dump scratch4=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch4=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_5_REG, &dump_reg);
-	pr_err("dump scratch5=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch5=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_6_REG, &dump_reg);
-	pr_err("dump scratch6=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch6=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_SCRATCH_7_REG, &dump_reg);
-	pr_err("dump scratch7=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "dump scratch7=%x", dump_reg);
 
 }
 
@@ -191,64 +188,65 @@
 
 	mutex_lock(&cdm_hw->hw_mutex);
 	cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg);
-	pr_err("CDM HW core status=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW core status=%x", dump_reg);
 	/* First pause CDM, If it fails still proceed to dump debug info */
 	cam_hw_cdm_enable_core(cdm_hw, false);
 	cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg);
-	pr_err("CDM HW current pending BL=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW current pending BL=%x", dump_reg);
 	loop_cnt = dump_reg;
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_DEBUG_STATUS, &dump_reg);
-	pr_err("CDM HW Debug status reg=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg);
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, &core_dbg);
 	if (core_dbg & 0x100) {
 		cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_LAST_AHB_ADDR, &dump_reg);
-		pr_err("AHB dump reglastaddr=%x\n", dump_reg);
+		CAM_ERR(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg);
 		cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_LAST_AHB_DATA, &dump_reg);
-		pr_err("AHB dump reglastdata=%x\n", dump_reg);
+		CAM_ERR(CAM_CDM, "AHB dump reglastdata=%x", dump_reg);
 	} else {
-		pr_err("CDM HW AHB dump not enable\n");
+		CAM_ERR(CAM_CDM, "CDM HW AHB dump not enable");
 	}
 
 	if (core_dbg & 0x10000) {
 		int i;
 
-		pr_err("CDM HW BL FIFO dump with loop count=%d\n", loop_cnt);
+		CAM_ERR(CAM_CDM, "CDM HW BL FIFO dump with loop count=%d",
+			loop_cnt);
 		for (i = 0 ; i < loop_cnt ; i++) {
 			cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_RB, i);
 			cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_BASE_RB,
 				&dump_reg);
-			pr_err("BL(%d) base addr =%x\n", i, dump_reg);
+			CAM_ERR(CAM_CDM, "BL(%d) base addr =%x", i, dump_reg);
 			cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_LEN_RB,
 				&dump_reg);
-			pr_err("BL(%d) len=%d tag=%d\n", i,
+			CAM_ERR(CAM_CDM, "BL(%d) len=%d tag=%d", i,
 				(dump_reg & 0xFFFFF), (dump_reg & 0xFF000000));
 		}
 	} else {
-		pr_err("CDM HW BL FIFO readback not enable\n");
+		CAM_ERR(CAM_CDM, "CDM HW BL FIFO readback not enable");
 	}
 
-	pr_err("CDM HW default dump\n");
+	CAM_ERR(CAM_CDM, "CDM HW default dump");
 	cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_CFG, &dump_reg);
-	pr_err("CDM HW core cfg=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW core cfg=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_STATUS, &dump_reg);
-	pr_err("CDM HW irq status=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW irq status=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_SET, &dump_reg);
-	pr_err("CDM HW irq set reg=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW irq set reg=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_BL_BASE, &dump_reg);
-	pr_err("CDM HW current BL base=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW current BL base=%x", dump_reg);
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_BL_LEN, &dump_reg);
-	pr_err("CDM HW current BL len=%d tag=%d\n", (dump_reg & 0xFFFFF),
-		(dump_reg & 0xFF000000));
+	CAM_ERR(CAM_CDM, "CDM HW current BL len=%d tag=%d",
+		(dump_reg & 0xFFFFF), (dump_reg & 0xFF000000));
 
 	cam_cdm_read_hw_reg(cdm_hw, CDM_DBG_CURRENT_USED_AHB_BASE, &dump_reg);
-	pr_err("CDM HW current AHB base=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW current AHB base=%x", dump_reg);
 
 	cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg);
-	pr_err("CDM HW current pending BL=%x\n", dump_reg);
+	CAM_ERR(CAM_CDM, "CDM HW current pending BL=%x", dump_reg);
 
 	/* Enable CDM back */
 	cam_hw_cdm_enable_core(cdm_hw, true);
@@ -268,43 +266,46 @@
 	do {
 		if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB,
 			&pending_bl)) {
-			pr_err("Failed to read CDM pending BL's\n");
+			CAM_ERR(CAM_CDM, "Failed to read CDM pending BL's");
 			rc = -EIO;
 			break;
 		}
 		available_bl_slots = CAM_CDM_HWFIFO_SIZE - pending_bl;
 		if (available_bl_slots < 0) {
-			pr_err("Invalid available slots %d:%d:%d\n",
+			CAM_ERR(CAM_CDM, "Invalid available slots %d:%d:%d",
 				available_bl_slots, CAM_CDM_HWFIFO_SIZE,
 				pending_bl);
 			break;
 		}
 		if (bl_count < (available_bl_slots - 1)) {
-			CDM_CDBG("BL slot available_cnt=%d requested=%d\n",
+			CAM_DBG(CAM_CDM,
+				"BL slot available_cnt=%d requested=%d",
 				(available_bl_slots - 1), bl_count);
 				rc = bl_count;
 				break;
 		} else if (0 == (available_bl_slots - 1)) {
 			rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, true);
 			if (rc) {
-				pr_err("Enable BL done irq failed\n");
+				CAM_ERR(CAM_CDM, "Enable BL done irq failed");
 				break;
 			}
 			time_left = wait_for_completion_timeout(
 				&core->bl_complete, msecs_to_jiffies(
 				CAM_CDM_BL_FIFO_WAIT_TIMEOUT));
 			if (time_left <= 0) {
-				pr_err("CDM HW BL Wait timed out failed\n");
+				CAM_ERR(CAM_CDM,
+					"CDM HW BL Wait timed out failed");
 				if (cam_hw_cdm_enable_bl_done_irq(cdm_hw,
 					false))
-					pr_err("Disable BL done irq failed\n");
+					CAM_ERR(CAM_CDM,
+						"Disable BL done irq failed");
 				rc = -EIO;
 				break;
 			}
 			if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, false))
-				pr_err("Disable BL done irq failed\n");
+				CAM_ERR(CAM_CDM, "Disable BL done irq failed");
 			rc = 0;
-			CDM_CDBG("CDM HW is ready for data\n");
+			CAM_DBG(CAM_CDM, "CDM HW is ready for data");
 		} else {
 			rc = (bl_count - (available_bl_slots - 1));
 			break;
@@ -318,12 +319,12 @@
 	uint32_t len, uint32_t tag)
 {
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_BASE_REG, src)) {
-		pr_err("Failed to write CDM base to BL base\n");
+		CAM_ERR(CAM_CDM, "Failed to write CDM base to BL base");
 		return true;
 	}
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_LEN_REG,
 		((len & 0xFFFFF) | ((tag & 0xFF) << 20)))) {
-		pr_err("Failed to write CDM BL len\n");
+		CAM_ERR(CAM_CDM, "Failed to write CDM BL len");
 		return true;
 	}
 	return false;
@@ -332,7 +333,7 @@
 bool cam_hw_cdm_commit_bl_write(struct cam_hw_info *cdm_hw)
 {
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_BL_FIFO_STORE_REG, 1)) {
-		pr_err("Failed to write CDM commit BL\n");
+		CAM_ERR(CAM_CDM, "Failed to write CDM commit BL");
 		return true;
 	}
 	return false;
@@ -347,11 +348,11 @@
 	int rc;
 
 	if (core->bl_tag > 63) {
-		pr_err("bl_tag invalid =%d\n", core->bl_tag);
+		CAM_ERR(CAM_CDM, "bl_tag invalid =%d", core->bl_tag);
 		rc = -EINVAL;
 		goto end;
 	}
-	CDM_CDBG("CDM write BL last cmd tag=%x total=%d cookie=%d\n",
+	CAM_DBG(CAM_CDM, "CDM write BL last cmd tag=%x total=%d cookie=%d",
 		core->bl_tag, req->data->cmd_arrary_count, req->data->cookie);
 	node = kzalloc(sizeof(struct cam_cdm_bl_cb_request_entry),
 			GFP_KERNEL);
@@ -372,7 +373,7 @@
 		((4 * core->ops->cdm_required_size_genirq()) - 1),
 		core->bl_tag);
 	if (rc) {
-		pr_err("CDM hw bl write failed for gen irq bltag=%d\n",
+		CAM_ERR(CAM_CDM, "CDM hw bl write failed for gen irq bltag=%d",
 			core->bl_tag);
 		list_del_init(&node->entry);
 		kfree(node);
@@ -381,7 +382,7 @@
 	}
 
 	if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
-		pr_err("Cannot commit the genirq BL with tag tag=%d\n",
+		CAM_ERR(CAM_CDM, "Cannot commit the genirq BL with tag tag=%d",
 			core->bl_tag);
 		list_del_init(&node->entry);
 		kfree(node);
@@ -403,7 +404,7 @@
 	int write_count = 0;
 
 	if (req->data->cmd_arrary_count > CAM_CDM_HWFIFO_SIZE) {
-		pr_info("requested BL more than max size, cnt=%d max=%d\n",
+		pr_info("requested BL more than max size, cnt=%d max=%d",
 			req->data->cmd_arrary_count, CAM_CDM_HWFIFO_SIZE);
 	}
 
@@ -414,7 +415,7 @@
 	mutex_lock(&client->lock);
 	rc = cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &pending_bl);
 	if (rc) {
-		pr_err("Cannot read the current BL depth\n");
+		CAM_ERR(CAM_CDM, "Cannot read the current BL depth");
 		mutex_unlock(&client->lock);
 		mutex_unlock(&cdm_hw->hw_mutex);
 		return rc;
@@ -426,14 +427,16 @@
 
 		if ((!cdm_cmd->cmd[i].len) &&
 			(cdm_cmd->cmd[i].len > 0x100000)) {
-			pr_err("cmd len(%d) is invalid cnt=%d total cnt=%d\n",
+			CAM_ERR(CAM_CDM,
+				"cmd len(%d) is invalid cnt=%d total cnt=%d",
 				cdm_cmd->cmd[i].len, i,
 				req->data->cmd_arrary_count);
 			rc = -EINVAL;
 			break;
 		}
 		if (atomic_read(&core->error)) {
-			pr_err_ratelimited("In error state cnt=%d total cnt=%d\n",
+			CAM_ERR_RATE_LIMIT(CAM_CDM,
+				"In error state cnt=%d total cnt=%d\n",
 				i, req->data->cmd_arrary_count);
 			rc = -EIO;
 			break;
@@ -442,7 +445,8 @@
 			write_count = cam_hw_cdm_wait_for_bl_fifo(cdm_hw,
 				(req->data->cmd_arrary_count - i));
 			if (write_count < 0) {
-				pr_err("wait for bl fifo failed %d:%d\n",
+				CAM_ERR(CAM_CDM,
+					"wait for bl fifo failed %d:%d",
 					i, req->data->cmd_arrary_count);
 				rc = -EIO;
 				break;
@@ -458,7 +462,8 @@
 				&len);
 		} else if (req->data->type == CAM_CDM_BL_CMD_TYPE_HW_IOVA) {
 			if (!cdm_cmd->cmd[i].bl_addr.hw_iova) {
-				pr_err("Hw bl hw_iova is invalid %d:%d\n",
+				CAM_ERR(CAM_CDM,
+					"Hw bl hw_iova is invalid %d:%d",
 					i, req->data->cmd_arrary_count);
 				rc = -EINVAL;
 				break;
@@ -468,7 +473,8 @@
 				(uint64_t)cdm_cmd->cmd[i].bl_addr.hw_iova;
 			len = cdm_cmd->cmd[i].len + cdm_cmd->cmd[i].offset;
 		} else {
-			pr_err("Only mem hdl/hw va type is supported %d\n",
+			CAM_ERR(CAM_CDM,
+				"Only mem hdl/hw va type is supported %d",
 				req->data->type);
 			rc = -EINVAL;
 			break;
@@ -476,7 +482,7 @@
 
 		if ((!rc) && (hw_vaddr_ptr) && (len) &&
 			(len >= cdm_cmd->cmd[i].offset)) {
-			CDM_CDBG("Got the HW VA\n");
+			CAM_DBG(CAM_CDM, "Got the HW VA");
 			if (core->bl_tag >=
 				(CAM_CDM_HWFIFO_SIZE - 1))
 				core->bl_tag = 0;
@@ -485,33 +491,36 @@
 					cdm_cmd->cmd[i].offset),
 				(cdm_cmd->cmd[i].len - 1), core->bl_tag);
 			if (rc) {
-				pr_err("Hw bl write failed %d:%d\n",
+				CAM_ERR(CAM_CDM, "Hw bl write failed %d:%d",
 					i, req->data->cmd_arrary_count);
 				rc = -EIO;
 				break;
 			}
 		} else {
-			pr_err("Sanity check failed for hdl=%x len=%zu:%d\n",
+			CAM_ERR(CAM_CDM,
+				"Sanity check failed for hdl=%x len=%zu:%d",
 				cdm_cmd->cmd[i].bl_addr.mem_handle, len,
 				cdm_cmd->cmd[i].offset);
-			pr_err("Sanity check failed for %d:%d\n",
+			CAM_ERR(CAM_CDM, "Sanity check failed for %d:%d",
 				i, req->data->cmd_arrary_count);
 			rc = -EINVAL;
 			break;
 		}
 
 		if (!rc) {
-			CDM_CDBG("write BL success for cnt=%d with tag=%d\n",
+			CAM_DBG(CAM_CDM,
+				"write BL success for cnt=%d with tag=%d",
 				i, core->bl_tag);
 
-			CDM_CDBG("Now commit the BL\n");
+			CAM_DBG(CAM_CDM, "Now commit the BL");
 			if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
-				pr_err("Cannot commit the BL %d tag=%d\n",
+				CAM_ERR(CAM_CDM,
+					"Cannot commit the BL %d tag=%d",
 					i, core->bl_tag);
 				rc = -EIO;
 				break;
 			}
-			CDM_CDBG("BL commit success BL %d tag=%d\n", i,
+			CAM_DBG(CAM_CDM, "BL commit success BL %d tag=%d", i,
 				core->bl_tag);
 			core->bl_tag++;
 			if ((req->data->flag == true) &&
@@ -541,12 +550,12 @@
 		cdm_hw = payload->hw;
 		core = (struct cam_cdm *)cdm_hw->core_info;
 
-		CDM_CDBG("IRQ status=%x\n", payload->irq_status);
+		CAM_DBG(CAM_CDM, "IRQ status=%x", payload->irq_status);
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
 			struct cam_cdm_bl_cb_request_entry *node;
 
-			CDM_CDBG("inline IRQ data=%x\n",
+			CAM_DBG(CAM_CDM, "inline IRQ data=%x",
 				payload->irq_data);
 			mutex_lock(&cdm_hw->hw_mutex);
 			node = cam_cdm_find_request_by_bl_tag(
@@ -560,13 +569,15 @@
 						(void *)node);
 				} else if (node->request_type ==
 						CAM_HW_CDM_BL_CB_INTERNAL) {
-					pr_err("Invalid node=%pK %d\n", node,
+					CAM_ERR(CAM_CDM,
+						"Invalid node=%pK %d", node,
 						node->request_type);
 				}
 				list_del_init(&node->entry);
 				kfree(node);
 			} else {
-				pr_err("Invalid node for inline irq status=%x data=%x\n",
+				CAM_ERR(CAM_CDM,
+					"Inval node, inline_irq st=%x data=%x",
 					payload->irq_status, payload->irq_data);
 			}
 			mutex_unlock(&cdm_hw->hw_mutex);
@@ -574,39 +585,40 @@
 
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_INFO_RST_DONE_MASK) {
-			CDM_CDBG("CDM HW reset done IRQ\n");
+			CAM_DBG(CAM_CDM, "CDM HW reset done IRQ");
 			complete(&core->reset_complete);
 		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_INFO_BL_DONE_MASK) {
 			if (atomic_read(&core->bl_done)) {
-				CDM_CDBG("CDM HW BL done IRQ\n");
+				CAM_DBG(CAM_CDM, "CDM HW BL done IRQ");
 				complete(&core->bl_complete);
 			}
 		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) {
-			pr_err_ratelimited("Invalid command IRQ, Need HW reset\n");
+			CAM_ERR_RATE_LIMIT(CAM_CDM,
+				"Invalid command IRQ, Need HW reset\n");
 			atomic_inc(&core->error);
 			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
 		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) {
-			pr_err_ratelimited("AHB Error IRQ\n");
+			CAM_ERR_RATE_LIMIT(CAM_CDM, "AHB Error IRQ\n");
 			atomic_inc(&core->error);
 			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
 			atomic_dec(&core->error);
 		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK) {
-			pr_err_ratelimited("Overflow Error IRQ\n");
+			CAM_ERR_RATE_LIMIT(CAM_CDM, "Overflow Error IRQ\n");
 			atomic_inc(&core->error);
 			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
 			atomic_dec(&core->error);
 		}
 		kfree(payload);
 	} else {
-		pr_err("NULL payload\n");
+		CAM_ERR(CAM_CDM, "NULL payload");
 	}
 
 }
@@ -622,12 +634,13 @@
 		core = (struct cam_cdm *)cdm_hw->core_info;
 		atomic_inc(&core->error);
 		cam_hw_cdm_dump_core_debug_registers(cdm_hw);
-		pr_err_ratelimited("Page fault iova addr %pK\n", (void *)iova);
+		CAM_ERR_RATE_LIMIT(CAM_CDM, "Page fault iova addr %pK\n",
+			(void *)iova);
 		cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT,
 			(void *)iova);
 		atomic_dec(&core->error);
 	} else {
-		pr_err("Invalid token\n");
+		CAM_ERR(CAM_CDM, "Invalid token");
 	}
 
 }
@@ -639,15 +652,15 @@
 	struct cam_cdm_work_payload *payload;
 	bool work_status;
 
-	CDM_CDBG("Got irq\n");
+	CAM_DBG(CAM_CDM, "Got irq");
 	payload = kzalloc(sizeof(struct cam_cdm_work_payload), GFP_ATOMIC);
 	if (payload) {
 		if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_STATUS,
 				&payload->irq_status)) {
-			pr_err("Failed to read CDM HW IRQ status\n");
+			CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status");
 		}
 		if (!payload->irq_status) {
-			pr_err_ratelimited("Invalid irq received\n");
+			CAM_ERR_RATE_LIMIT(CAM_CDM, "Invalid irq received\n");
 			kfree(payload);
 			return IRQ_HANDLED;
 		}
@@ -655,21 +668,22 @@
 			CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
 			if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_USR_DATA,
 				&payload->irq_data)) {
-				pr_err("Failed to read CDM HW IRQ data\n");
+				CAM_ERR(CAM_CDM,
+					"Failed to read CDM HW IRQ data");
 			}
 		}
-		CDM_CDBG("Got payload=%d\n", payload->irq_status);
+		CAM_DBG(CAM_CDM, "Got payload=%d", payload->irq_status);
 		payload->hw = cdm_hw;
 		INIT_WORK((struct work_struct *)&payload->work,
 			cam_hw_cdm_work);
 		if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_CLEAR,
 			payload->irq_status))
-			pr_err("Failed to Write CDM HW IRQ Clear\n");
+			CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ Clear");
 		if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_CLEAR_CMD, 0x01))
-			pr_err("Failed to Write CDM HW IRQ cmd\n");
+			CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd");
 		work_status = queue_work(cdm_core->work_queue, &payload->work);
 		if (work_status == false) {
-			pr_err("Failed to queue work for irq=%x\n",
+			CAM_ERR(CAM_CDM, "Failed to queue work for irq=%x",
 				payload->irq_status);
 			kfree(payload);
 		}
@@ -697,7 +711,7 @@
 	rc = cam_mem_mgr_request_mem(&genirq_alloc_cmd,
 		&genirq_alloc_out);
 	if (rc) {
-		pr_err("Failed to get genirq cmd space rc=%d\n", rc);
+		CAM_ERR(CAM_CDM, "Failed to get genirq cmd space rc=%d", rc);
 		goto end;
 	}
 	cdm_core->gen_irq.handle = genirq_alloc_out.mem_handle;
@@ -723,7 +737,7 @@
 	genirq_release_cmd.mem_handle = cdm_core->gen_irq.handle;
 	rc = cam_mem_mgr_release_mem(&genirq_release_cmd);
 	if (rc)
-		pr_err("Failed to put genirq cmd space for hw\n");
+		CAM_ERR(CAM_CDM, "Failed to put genirq cmd space for hw");
 
 	return rc;
 }
@@ -746,11 +760,11 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_SVS_VOTE, true);
 	if (rc) {
-		pr_err("Enable platform failed\n");
+		CAM_ERR(CAM_CDM, "Enable platform failed");
 		goto end;
 	}
 
-	CDM_CDBG("Enable soc done\n");
+	CAM_DBG(CAM_CDM, "Enable soc done");
 
 /* Before triggering the reset to HW, clear the reset complete */
 	atomic_set(&cdm_core->error, 0);
@@ -759,15 +773,15 @@
 	reinit_completion(&cdm_core->bl_complete);
 
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003)) {
-		pr_err("Failed to Write CDM HW IRQ mask\n");
+		CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ mask");
 		goto disable_return;
 	}
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_RST_CMD, 0x9)) {
-		pr_err("Failed to Write CDM HW reset\n");
+		CAM_ERR(CAM_CDM, "Failed to Write CDM HW reset");
 		goto disable_return;
 	}
 
-	CDM_CDBG("Waiting for CDM HW resetdone\n");
+	CAM_DBG(CAM_CDM, "Waiting for CDM HW resetdone");
 	time_left = wait_for_completion_timeout(&cdm_core->reset_complete,
 		msecs_to_jiffies(CAM_CDM_HW_RESET_TIMEOUT));
 
@@ -778,15 +792,16 @@
 	 * as a workaround.
 	 */
 	if (time_left <= 0) {
-		pr_err("CDM HW reset Wait failed time_left=%ld\n", time_left);
+		CAM_ERR(CAM_CDM, "CDM HW reset Wait failed time_left=%ld",
+			time_left);
 		time_left = 1;
 	}
 
 	if (time_left <= 0) {
-		pr_err("CDM HW reset Wait failed rc=%d\n", rc);
+		CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc);
 		goto disable_return;
 	} else {
-		CDM_CDBG("CDM Init success\n");
+		CAM_DBG(CAM_CDM, "CDM Init success");
 		cdm_hw->hw_state = CAM_HW_STATE_POWER_UP;
 		cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003);
 		rc = 0;
@@ -815,9 +830,9 @@
 	cdm_core = cdm_hw->core_info;
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc) {
-		pr_err("disable platform failed\n");
+		CAM_ERR(CAM_CDM, "disable platform failed");
 	} else {
-		CDM_CDBG("CDM Deinit success\n");
+		CAM_DBG(CAM_CDM, "CDM Deinit success");
 		cdm_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 	}
 
@@ -862,7 +877,7 @@
 
 	rc = cam_hw_cdm_soc_get_dt_properties(cdm_hw, msm_cam_hw_cdm_dt_match);
 	if (rc) {
-		pr_err("Failed to get dt properties\n");
+		CAM_ERR(CAM_CDM, "Failed to get dt properties");
 		goto release_mem;
 	}
 	cdm_hw_intf->hw_idx = cdm_hw->soc_info.index;
@@ -877,7 +892,8 @@
 	cdm_core->bl_tag = 0;
 	cdm_core->id = cam_hw_cdm_get_id_by_name(cdm_core->name);
 	if (cdm_core->id >= CAM_CDM_MAX) {
-		pr_err("Failed to get CDM HW name for %s\n", cdm_core->name);
+		CAM_ERR(CAM_CDM, "Failed to get CDM HW name for %s",
+			cdm_core->name);
 		goto release_private_mem;
 	}
 	INIT_LIST_HEAD(&cdm_core->bl_request_list);
@@ -894,14 +910,14 @@
 	cdm_hw_intf->hw_ops.process_cmd = cam_cdm_process_cmd;
 	mutex_lock(&cdm_hw->hw_mutex);
 
-	CDM_CDBG("type %d index %d\n", cdm_hw_intf->hw_type,
+	CAM_DBG(CAM_CDM, "type %d index %d", cdm_hw_intf->hw_type,
 		cdm_hw_intf->hw_idx);
 
 	platform_set_drvdata(pdev, cdm_hw_intf);
 
 	rc = cam_smmu_get_handle("cpas-cdm0", &cdm_core->iommu_hdl.non_secure);
 	if (rc < 0) {
-		pr_err("cpas-cdm get iommu handle failed\n");
+		CAM_ERR(CAM_CDM, "cpas-cdm get iommu handle failed");
 		goto unlock_release_mem;
 	}
 	cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure,
@@ -909,7 +925,7 @@
 
 	rc = cam_smmu_ops(cdm_core->iommu_hdl.non_secure, CAM_SMMU_ATTACH);
 	if (rc < 0) {
-		pr_err("Attach iommu non secure handle failed\n");
+		CAM_ERR(CAM_CDM, "Attach iommu non secure handle failed");
 		goto destroy_non_secure_hdl;
 	}
 	cdm_core->iommu_hdl.secure = -1;
@@ -921,7 +937,7 @@
 	rc = cam_soc_util_request_platform_resource(&cdm_hw->soc_info,
 			cam_hw_cdm_irq, cdm_hw);
 	if (rc) {
-		pr_err("Failed to request platform resource\n");
+		CAM_ERR(CAM_CDM, "Failed to request platform resource");
 		goto destroy_non_secure_hdl;
 	}
 
@@ -932,10 +948,10 @@
 	strlcpy(cpas_parms.identifier, "cpas-cdm", CAM_HW_IDENTIFIER_LENGTH);
 	rc = cam_cpas_register_client(&cpas_parms);
 	if (rc) {
-		pr_err("Virtual CDM CPAS registration failed\n");
+		CAM_ERR(CAM_CDM, "Virtual CDM CPAS registration failed");
 		goto release_platform_resource;
 	}
-	CDM_CDBG("CPAS registration successful handle=%d\n",
+	CAM_DBG(CAM_CDM, "CPAS registration successful handle=%d",
 		cpas_parms.client_handle);
 	cdm_core->cpas_handle = cpas_parms.client_handle;
 
@@ -945,54 +961,54 @@
 	axi_vote.uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
 	rc = cam_cpas_start(cdm_core->cpas_handle, &ahb_vote, &axi_vote);
 	if (rc) {
-		pr_err("CPAS start failed\n");
+		CAM_ERR(CAM_CDM, "CPAS start failed");
 		goto cpas_unregister;
 	}
 
 	rc = cam_hw_cdm_init(cdm_hw, NULL, 0);
 	if (rc) {
-		pr_err("Failed to Init CDM HW\n");
+		CAM_ERR(CAM_CDM, "Failed to Init CDM HW");
 		goto cpas_stop;
 	}
 	cdm_hw->open_count++;
 
 	if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_HW_VERSION,
 		&cdm_core->hw_version)) {
-		pr_err("Failed to read CDM HW Version\n");
+		CAM_ERR(CAM_CDM, "Failed to read CDM HW Version");
 		goto deinit;
 	}
 
 	if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_TITAN_VERSION,
 		&cdm_core->hw_family_version)) {
-		pr_err("Failed to read CDM family Version\n");
+		CAM_ERR(CAM_CDM, "Failed to read CDM family Version");
 		goto deinit;
 	}
 
-	CDM_CDBG("CDM Hw version read success family =%x hw =%x\n",
+	CAM_DBG(CAM_CDM, "CDM Hw version read success family =%x hw =%x",
 		cdm_core->hw_family_version, cdm_core->hw_version);
 	cdm_core->ops = cam_cdm_get_ops(cdm_core->hw_version, NULL,
 		false);
 	if (!cdm_core->ops) {
-		pr_err("Failed to util ops for hw\n");
+		CAM_ERR(CAM_CDM, "Failed to util ops for hw");
 		goto deinit;
 	}
 
 	if (!cam_cdm_set_cam_hw_version(cdm_core->hw_version,
 		&cdm_core->version)) {
-		pr_err("Failed to set cam he version for hw\n");
+		CAM_ERR(CAM_CDM, "Failed to set cam he version for hw");
 		goto deinit;
 	}
 
 	rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0);
 	if (rc) {
-		pr_err("Failed to Deinit CDM HW\n");
+		CAM_ERR(CAM_CDM, "Failed to Deinit CDM HW");
 		cdm_hw->open_count--;
 		goto cpas_stop;
 	}
 
 	rc = cam_cpas_stop(cdm_core->cpas_handle);
 	if (rc) {
-		pr_err("CPAS stop failed\n");
+		CAM_ERR(CAM_CDM, "CPAS stop failed");
 		cdm_hw->open_count--;
 		goto cpas_unregister;
 	}
@@ -1000,30 +1016,30 @@
 	rc = cam_cdm_intf_register_hw_cdm(cdm_hw_intf,
 		soc_private, CAM_HW_CDM, &cdm_core->index);
 	if (rc) {
-		pr_err("HW CDM Interface registration failed\n");
+		CAM_ERR(CAM_CDM, "HW CDM Interface registration failed");
 		cdm_hw->open_count--;
 		goto cpas_unregister;
 	}
 	cdm_hw->open_count--;
 	mutex_unlock(&cdm_hw->hw_mutex);
 
-	CDM_CDBG("CDM%d probe successful\n", cdm_hw_intf->hw_idx);
+	CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx);
 
 	return rc;
 
 deinit:
 	if (cam_hw_cdm_deinit(cdm_hw, NULL, 0))
-		pr_err("Deinit failed for hw\n");
+		CAM_ERR(CAM_CDM, "Deinit failed for hw");
 	cdm_hw->open_count--;
 cpas_stop:
 	if (cam_cpas_stop(cdm_core->cpas_handle))
-		pr_err("CPAS stop failed\n");
+		CAM_ERR(CAM_CDM, "CPAS stop failed");
 cpas_unregister:
 	if (cam_cpas_unregister_client(cdm_core->cpas_handle))
-		pr_err("CPAS unregister failed\n");
+		CAM_ERR(CAM_CDM, "CPAS unregister failed");
 release_platform_resource:
 	if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info))
-		pr_err("Release platform resource failed\n");
+		CAM_ERR(CAM_CDM, "Release platform resource failed");
 
 	flush_workqueue(cdm_core->work_queue);
 	destroy_workqueue(cdm_core->work_queue);
@@ -1031,7 +1047,7 @@
 	cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure,
 		NULL, cdm_hw);
 	if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure))
-		pr_err("Release iommu secure hdl failed\n");
+		CAM_ERR(CAM_CDM, "Release iommu secure hdl failed");
 unlock_release_mem:
 	mutex_unlock(&cdm_hw->hw_mutex);
 release_private_mem:
@@ -1053,26 +1069,28 @@
 
 	cdm_hw_intf = platform_get_drvdata(pdev);
 	if (!cdm_hw_intf) {
-		pr_err("Failed to get dev private data\n");
+		CAM_ERR(CAM_CDM, "Failed to get dev private data");
 		return rc;
 	}
 
 	cdm_hw = cdm_hw_intf->hw_priv;
 	if (!cdm_hw) {
-		pr_err("Failed to get hw private data for type=%d idx=%d\n",
+		CAM_ERR(CAM_CDM,
+			"Failed to get hw private data for type=%d idx=%d",
 			cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx);
 		return rc;
 	}
 
 	cdm_core = cdm_hw->core_info;
 	if (!cdm_core) {
-		pr_err("Failed to get hw core data for type=%d idx=%d\n",
+		CAM_ERR(CAM_CDM,
+			"Failed to get hw core data for type=%d idx=%d",
 			cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx);
 		return rc;
 	}
 
 	if (cdm_hw->open_count != 0) {
-		pr_err("Hw open count invalid type=%d idx=%d cnt=%d\n",
+		CAM_ERR(CAM_CDM, "Hw open count invalid type=%d idx=%d cnt=%d",
 			cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx,
 			cdm_hw->open_count);
 		return rc;
@@ -1080,24 +1098,24 @@
 
 	rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0);
 	if (rc) {
-		pr_err("Deinit failed for hw\n");
+		CAM_ERR(CAM_CDM, "Deinit failed for hw");
 		return rc;
 	}
 
 	rc = cam_cpas_unregister_client(cdm_core->cpas_handle);
 	if (rc) {
-		pr_err("CPAS unregister failed\n");
+		CAM_ERR(CAM_CDM, "CPAS unregister failed");
 		return rc;
 	}
 
 	if (cam_soc_util_release_platform_resource(&cdm_hw->soc_info))
-		pr_err("Release platform resource failed\n");
+		CAM_ERR(CAM_CDM, "Release platform resource failed");
 
 	flush_workqueue(cdm_core->work_queue);
 	destroy_workqueue(cdm_core->work_queue);
 
 	if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure))
-		pr_err("Release iommu secure hdl failed\n");
+		CAM_ERR(CAM_CDM, "Release iommu secure hdl failed");
 	cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure,
 		NULL, cdm_hw);
 
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
index 59f5b92..fa98be2 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-CDM-INTF %s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -41,10 +39,10 @@
 
 	mutex_lock(&cam_cdm_mgr_lock);
 	if (cdm_mgr.probe_done == false) {
-		pr_err("CDM intf mgr not probed yet\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr not probed yet");
 		rc = -EPERM;
 	} else {
-		CDM_CDBG("CDM intf mgr get refcount=%d\n",
+		CAM_DBG(CAM_CDM, "CDM intf mgr get refcount=%d",
 			cdm_mgr.refcount);
 		cdm_mgr.refcount++;
 	}
@@ -56,14 +54,14 @@
 {
 	mutex_lock(&cam_cdm_mgr_lock);
 	if (cdm_mgr.probe_done == false) {
-		pr_err("CDM intf mgr not probed yet\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr not probed yet");
 	} else {
-		CDM_CDBG("CDM intf mgr put refcount=%d\n",
+		CAM_DBG(CAM_CDM, "CDM intf mgr put refcount=%d",
 			cdm_mgr.refcount);
 		if (cdm_mgr.refcount > 0) {
 			cdm_mgr.refcount--;
 		} else {
-			pr_err("Refcount put when zero\n");
+			CAM_ERR(CAM_CDM, "Refcount put when zero");
 			WARN_ON(1);
 		}
 	}
@@ -90,20 +88,20 @@
 	int rc = -EPERM, i, j;
 	char client_name[128];
 
-	CDM_CDBG("Looking for HW id of =%s and index=%d\n",
+	CAM_DBG(CAM_CDM, "Looking for HW id of =%s and index=%d",
 		identifier, cell_index);
 	snprintf(client_name, sizeof(client_name), "%s", identifier);
-	CDM_CDBG("Looking for HW id of %s count:%d\n", client_name,
+	CAM_DBG(CAM_CDM, "Looking for HW id of %s count:%d", client_name,
 		cdm_mgr.cdm_count);
 	mutex_lock(&cam_cdm_mgr_lock);
 	for (i = 0; i < cdm_mgr.cdm_count; i++) {
 		mutex_lock(&cdm_mgr.nodes[i].lock);
-		CDM_CDBG("dt_num_supported_clients=%d\n",
+		CAM_DBG(CAM_CDM, "dt_num_supported_clients=%d",
 			cdm_mgr.nodes[i].data->dt_num_supported_clients);
 
 		for (j = 0; j <
 			cdm_mgr.nodes[i].data->dt_num_supported_clients; j++) {
-			CDM_CDBG("client name:%s\n",
+			CAM_DBG(CAM_CDM, "client name:%s",
 				cdm_mgr.nodes[i].data->dt_cdm_client_name[j]);
 			if (!strcmp(
 				cdm_mgr.nodes[i].data->dt_cdm_client_name[j],
@@ -131,10 +129,10 @@
 		return -EINVAL;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		return rc;
 	}
-	CDM_CDBG("Looking for Iommu handle of %s\n", identifier);
+	CAM_DBG(CAM_CDM, "Looking for Iommu handle of %s", identifier);
 
 	for (i = 0; i < cdm_mgr.cdm_count; i++) {
 		mutex_lock(&cdm_mgr.nodes[i].lock);
@@ -173,39 +171,41 @@
 		return -EINVAL;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		return rc;
 	}
 
 	if (data->id > CAM_CDM_HW_ANY) {
-		pr_err("only CAM_CDM_VIRTUAL/CAM_CDM_HW_ANY is supported\n");
+		CAM_ERR(CAM_CDM,
+			"only CAM_CDM_VIRTUAL/CAM_CDM_HW_ANY is supported");
 		rc = -EPERM;
 		goto end;
 	}
 	rc = get_cdm_index_by_id(data->identifier, data->cell_index,
 		&hw_index);
 	if ((rc < 0) && (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM)) {
-		pr_err("Failed to identify associated hw id\n");
+		CAM_ERR(CAM_CDM, "Failed to identify associated hw id");
 		goto end;
 	} else {
-		CDM_CDBG("hw_index:%d\n", hw_index);
+		CAM_DBG(CAM_CDM, "hw_index:%d", hw_index);
 		hw = cdm_mgr.nodes[hw_index].device;
 		if (hw && hw->hw_ops.process_cmd) {
 			rc = hw->hw_ops.process_cmd(hw->hw_priv,
 					CAM_CDM_HW_INTF_CMD_ACQUIRE, data,
 					sizeof(struct cam_cdm_acquire_data));
 			if (rc < 0) {
-				pr_err("CDM hw acquire failed\n");
+				CAM_ERR(CAM_CDM, "CDM hw acquire failed");
 				goto end;
 			}
 		} else {
-			pr_err("idx %d doesn't have acquire ops\n", hw_index);
+			CAM_ERR(CAM_CDM, "idx %d doesn't have acquire ops",
+				hw_index);
 			rc = -EPERM;
 		}
 	}
 end:
 	if (rc < 0) {
-		pr_err("CDM acquire failed for id=%d name=%s, idx=%d\n",
+		CAM_ERR(CAM_CDM, "CDM acquire failed for id=%d name=%s, idx=%d",
 			data->id, data->identifier, data->cell_index);
 		put_cdm_mgr_refcount();
 	}
@@ -220,7 +220,7 @@
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		return rc;
 	}
 
@@ -232,10 +232,11 @@
 					CAM_CDM_HW_INTF_CMD_RELEASE, &handle,
 					sizeof(handle));
 			if (rc < 0)
-				pr_err("hw release failed for handle=%x\n",
+				CAM_ERR(CAM_CDM,
+					"hw release failed for handle=%x",
 					handle);
 		} else
-			pr_err("hw idx %d doesn't have release ops\n",
+			CAM_ERR(CAM_CDM, "hw idx %d doesn't have release ops",
 				hw_index);
 	}
 	put_cdm_mgr_refcount();
@@ -257,7 +258,7 @@
 		return rc;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		rc = -EPERM;
 		return rc;
 	}
@@ -274,10 +275,11 @@
 				CAM_CDM_HW_INTF_CMD_SUBMIT_BL, &req,
 				sizeof(struct cam_cdm_hw_intf_cmd_submit_bl));
 			if (rc < 0)
-				pr_err("hw submit bl failed for handle=%x\n",
+				CAM_ERR(CAM_CDM,
+					"hw submit bl failed for handle=%x",
 					handle);
 		} else {
-			pr_err("hw idx %d doesn't have submit ops\n",
+			CAM_ERR(CAM_CDM, "hw idx %d doesn't have submit ops",
 				hw_index);
 		}
 	}
@@ -294,7 +296,7 @@
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		rc = -EPERM;
 		return rc;
 	}
@@ -306,10 +308,12 @@
 				rc = hw->hw_ops.start(hw->hw_priv, &handle,
 						sizeof(uint32_t));
 				if (rc < 0)
-					pr_err("hw start failed handle=%x\n",
+					CAM_ERR(CAM_CDM,
+						"hw start failed handle=%x",
 						handle);
 			} else {
-				pr_err("hw idx %d doesn't have start ops\n",
+				CAM_ERR(CAM_CDM,
+					"hw idx %d doesn't have start ops",
 					hw_index);
 			}
 	}
@@ -326,7 +330,7 @@
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		rc = -EPERM;
 		return rc;
 	}
@@ -338,10 +342,10 @@
 			rc = hw->hw_ops.stop(hw->hw_priv, &handle,
 					sizeof(uint32_t));
 			if (rc < 0)
-				pr_err("hw stop failed handle=%x\n",
+				CAM_ERR(CAM_CDM, "hw stop failed handle=%x",
 					handle);
 		} else {
-			pr_err("hw idx %d doesn't have stop ops\n",
+			CAM_ERR(CAM_CDM, "hw idx %d doesn't have stop ops",
 				hw_index);
 		}
 	}
@@ -358,7 +362,7 @@
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		rc = -EPERM;
 		return rc;
 	}
@@ -371,10 +375,11 @@
 					CAM_CDM_HW_INTF_CMD_RESET_HW, &handle,
 					sizeof(handle));
 			if (rc < 0)
-				pr_err("CDM hw release failed for handle=%x\n",
+				CAM_ERR(CAM_CDM,
+					"CDM hw release failed for handle=%x",
 					handle);
 		} else {
-			pr_err("hw idx %d doesn't have release ops\n",
+			CAM_ERR(CAM_CDM, "hw idx %d doesn't have release ops",
 				hw_index);
 		}
 	}
@@ -394,7 +399,7 @@
 		return rc;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		return rc;
 	}
 
@@ -417,7 +422,7 @@
 		cdm_mgr.cdm_count++;
 		rc = 0;
 	} else {
-		pr_err("CDM registration failed type=%d count=%d\n",
+		CAM_ERR(CAM_CDM, "CDM registration failed type=%d count=%d",
 			type, cdm_mgr.cdm_count);
 	}
 	mutex_unlock(&cam_cdm_mgr_lock);
@@ -436,7 +441,7 @@
 		return rc;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		rc = -EPERM;
 		return rc;
 	}
@@ -459,7 +464,7 @@
 		cdm_mgr.cdm_count--;
 		rc = 0;
 	} else {
-		pr_err("CDM Deregistration failed type=%d index=%d\n",
+		CAM_ERR(CAM_CDM, "CDM Deregistration failed type=%d index=%d",
 			type, index);
 	}
 	mutex_unlock(&cam_cdm_mgr_lock);
@@ -474,7 +479,7 @@
 
 	rc = cam_cdm_intf_mgr_soc_get_dt_properties(pdev, &cdm_mgr);
 	if (rc) {
-		pr_err("Failed to get dt properties\n");
+		CAM_ERR(CAM_CDM, "Failed to get dt properties");
 		return rc;
 	}
 	mutex_lock(&cam_cdm_mgr_lock);
@@ -494,7 +499,8 @@
 		for (i = 0 ; i < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM; i++) {
 			if (cdm_mgr.nodes[i].device || cdm_mgr.nodes[i].data ||
 				(cdm_mgr.nodes[i].refcount != 0))
-				pr_err("Valid node present in index=%d\n", i);
+				CAM_ERR(CAM_CDM,
+					"Valid node present in index=%d", i);
 			mutex_destroy(&cdm_mgr.nodes[i].lock);
 			cdm_mgr.nodes[i].device = NULL;
 			cdm_mgr.nodes[i].data = NULL;
@@ -511,19 +517,19 @@
 	int i, rc = -EBUSY;
 
 	if (get_cdm_mgr_refcount()) {
-		pr_err("CDM intf mgr get refcount failed\n");
+		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
 		return rc;
 	}
 
 	if (cam_virtual_cdm_remove(pdev)) {
-		pr_err("Virtual CDM remove failed\n");
+		CAM_ERR(CAM_CDM, "Virtual CDM remove failed");
 		goto end;
 	}
 	put_cdm_mgr_refcount();
 
 	mutex_lock(&cam_cdm_mgr_lock);
 	if (cdm_mgr.refcount != 0) {
-		pr_err("cdm manger refcount not zero %d\n",
+		CAM_ERR(CAM_CDM, "cdm manger refcount not zero %d",
 			cdm_mgr.refcount);
 		goto end;
 	}
@@ -531,7 +537,7 @@
 	for (i = 0 ; i < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM; i++) {
 		if (cdm_mgr.nodes[i].device || cdm_mgr.nodes[i].data ||
 			(cdm_mgr.nodes[i].refcount != 0)) {
-			pr_err("Valid node present in index=%d\n", i);
+			CAM_ERR(CAM_CDM, "Valid node present in index=%d", i);
 			mutex_unlock(&cam_cdm_mgr_lock);
 			goto end;
 		}
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c
index fbf185c..f8b0d3d 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-CDM-SOC %s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -40,27 +38,29 @@
 	resource_size_t mem_len =
 		cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size;
 
-	CDM_CDBG("E: b=%pK blen=%d reg=%x off=%x\n", (void *)base,
+	CAM_DBG(CAM_CDM, "E: b=%pK blen=%d reg=%x off=%x", (void __iomem *)base,
 		(int)mem_len, reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl,
 		reg)));
-	CDM_CDBG("E: b=%pK reg=%x off=%x\n", (void *)base,
+	CAM_DBG(CAM_CDM, "E: b=%pK reg=%x off=%x", (void __iomem *)base,
 		reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)));
 
 	if ((reg > cdm->offset_tbl->offset_max_size) ||
 		(reg > cdm->offset_tbl->last_offset)) {
-		pr_err_ratelimited("Invalid reg=%d\n", reg);
+		CAM_ERR_RATE_LIMIT(CAM_CDM, "Invalid reg=%d\n", reg);
 		goto permission_error;
 	} else {
 		reg_addr = (base + (CAM_CDM_OFFSET_FROM_REG(
 				cdm->offset_tbl, reg)));
 		if (reg_addr > (base + mem_len)) {
-			pr_err_ratelimited("Invalid mapped region %d\n", reg);
+			CAM_ERR_RATE_LIMIT(CAM_CDM,
+				"Invalid mapped region %d", reg);
 			goto permission_error;
 		}
 		*value = cam_io_r_mb(reg_addr);
-		CDM_CDBG("X b=%pK reg=%x off=%x val=%x\n",
-			(void *)base, reg, (CAM_CDM_OFFSET_FROM_REG(
-				cdm->offset_tbl, reg)),	*value);
+		CAM_DBG(CAM_CDM, "X b=%pK reg=%x off=%x val=%x",
+			(void __iomem *)base, reg,
+			(CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)),
+			*value);
 		return false;
 	}
 permission_error:
@@ -79,18 +79,20 @@
 	resource_size_t mem_len =
 		cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size;
 
-	CDM_CDBG("E: b=%pK reg=%x off=%x val=%x\n", (void *)base,
+	CAM_DBG(CAM_CDM, "E: b=%pK reg=%x off=%x val=%x", (void __iomem *)base,
 		reg, (CAM_CDM_OFFSET_FROM_REG(cdm->offset_tbl, reg)), value);
 
 	if ((reg > cdm->offset_tbl->offset_max_size) ||
 		(reg > cdm->offset_tbl->last_offset)) {
-		pr_err_ratelimited("CDM accessing invalid reg=%d\n", reg);
+		CAM_ERR_RATE_LIMIT(CAM_CDM, "CDM accessing invalid reg=%d\n",
+			reg);
 		goto permission_error;
 	} else {
 		reg_addr = (base + CAM_CDM_OFFSET_FROM_REG(
 				cdm->offset_tbl, reg));
 		if (reg_addr > (base + mem_len)) {
-			pr_err_ratelimited("Accessing invalid region %d:%d\n",
+			CAM_ERR_RATE_LIMIT(CAM_CDM,
+				"Accessing invalid region %d:%d\n",
 				reg, (CAM_CDM_OFFSET_FROM_REG(
 				cdm->offset_tbl, reg)));
 			goto permission_error;
@@ -111,17 +113,17 @@
 	ptr->dt_num_supported_clients = of_property_count_strings(
 						pdev->dev.of_node,
 						"cdm-client-names");
-	CDM_CDBG("Num supported cdm_client = %d\n",
+	CAM_DBG(CAM_CDM, "Num supported cdm_client = %d",
 		ptr->dt_num_supported_clients);
 	if (ptr->dt_num_supported_clients >
 		CAM_PER_CDM_MAX_REGISTERED_CLIENTS) {
-		pr_err("Invalid count of client names count=%d\n",
+		CAM_ERR(CAM_CDM, "Invalid count of client names count=%d",
 			ptr->dt_num_supported_clients);
 		rc = -EINVAL;
 		return rc;
 	}
 	if (ptr->dt_num_supported_clients < 0) {
-		CDM_CDBG("No cdm client names found\n");
+		CAM_DBG(CAM_CDM, "No cdm client names found");
 		ptr->dt_num_supported_clients = 0;
 		ptr->dt_cdm_shared = false;
 	} else {
@@ -130,10 +132,10 @@
 	for (i = 0; i < ptr->dt_num_supported_clients; i++) {
 		rc = of_property_read_string_index(pdev->dev.of_node,
 			"cdm-client-names", i, &(ptr->dt_cdm_client_name[i]));
-		CDM_CDBG("cdm-client-names[%d] = %s\n",	i,
+		CAM_DBG(CAM_CDM, "cdm-client-names[%d] = %s",	i,
 			ptr->dt_cdm_client_name[i]);
 		if (rc < 0) {
-			pr_err("Reading cdm-client-names failed\n");
+			CAM_ERR(CAM_CDM, "Reading cdm-client-names failed");
 			break;
 		}
 	}
@@ -156,7 +158,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_ptr);
 	if (rc != 0) {
-		pr_err("Failed to retrieve the CDM dt properties\n");
+		CAM_ERR(CAM_CDM, "Failed to retrieve the CDM dt properties");
 	} else {
 		soc_ptr->soc_private = kzalloc(
 				sizeof(struct cam_cdm_private_dt_data),
@@ -167,15 +169,15 @@
 		rc = cam_cdm_soc_load_dt_private(soc_ptr->pdev,
 			soc_ptr->soc_private);
 		if (rc != 0) {
-			pr_err("Failed to load CDM dt private data\n");
+			CAM_ERR(CAM_CDM, "Failed to load CDM dt private data");
 			goto error;
 		}
 		id = of_match_node(table, soc_ptr->pdev->dev.of_node);
 		if ((!id) || !(id->data)) {
-			pr_err("Failed to retrieve the CDM id table\n");
+			CAM_ERR(CAM_CDM, "Failed to retrieve the CDM id table");
 			goto error;
 		}
-		CDM_CDBG("CDM Hw Id compatible =%s\n", id->compatible);
+		CAM_DBG(CAM_CDM, "CDM Hw Id compatible =%s", id->compatible);
 		((struct cam_cdm *)cdm_hw->core_info)->offset_tbl =
 			(struct cam_cdm_reg_offset_table *)id->data;
 		strlcpy(((struct cam_cdm *)cdm_hw->core_info)->name,
@@ -199,7 +201,8 @@
 
 	rc = of_property_read_u32(pdev->dev.of_node,
 		"num-hw-cdm", &mgr->dt_supported_hw_cdm);
-	CDM_CDBG("Number of HW cdm supported =%d\n", mgr->dt_supported_hw_cdm);
+	CAM_DBG(CAM_CDM, "Number of HW cdm supported =%d",
+		mgr->dt_supported_hw_cdm);
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
index a3de3d1..c8b830f 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-CDM-UTIL %s:%d " fmt, __func__, __LINE__
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -245,7 +243,7 @@
 		*dst++ = *src++;
 	}
 
-	return pCmdBuffer;
+	return dst;
 }
 
 uint32_t *cdm_write_dmi(uint32_t *pCmdBuffer, uint8_t dmiCmd,
@@ -327,7 +325,7 @@
 
 	for (i = 0; i < base_array_size; i++) {
 		if (base_table[i])
-			CDM_CDBG("In loop %d ioremap for %x addr=%x\n",
+			CAM_DBG(CAM_CDM, "In loop %d ioremap for %x addr=%x",
 			i, (base_table[i])->mem_cam_base, hw_base);
 		if ((base_table[i]) &&
 			((base_table[i])->mem_cam_base == hw_base)) {
@@ -349,7 +347,7 @@
 
 	if ((cmd_buf_size < cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)) ||
 		(!base_addr)) {
-		pr_err(" invalid base addr and data length  %d %pK\n",
+		CAM_ERR(CAM_CDM, "invalid base addr and data length  %d %pK",
 			cmd_buf_size, base_addr);
 		return -EINVAL;
 	}
@@ -359,7 +357,7 @@
 		(((reg_cont->count * sizeof(uint32_t)) +
 			cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)) >
 			cmd_buf_size)) {
-		pr_err(" buffer size %d is not sufficient for count%d\n",
+		CAM_ERR(CAM_CDM, "buffer size %d is not sufficient for count%d",
 			cmd_buf_size, reg_cont->count);
 		return -EINVAL;
 	}
@@ -381,7 +379,7 @@
 	uint32_t *data;
 
 	if (!base_addr) {
-		pr_err("invalid base address\n");
+		CAM_ERR(CAM_CDM, "invalid base address");
 		return -EINVAL;
 	}
 
@@ -390,15 +388,16 @@
 		(((reg_random->count * (sizeof(uint32_t) * 2)) +
 		cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM)) >
 			cmd_buf_size)) {
-		pr_err("invalid reg_count  %d cmd_buf_size %d\n",
+		CAM_ERR(CAM_CDM, "invalid reg_count  %d cmd_buf_size %d",
 			reg_random->count, cmd_buf_size);
 		return -EINVAL;
 	}
 	data = cmd_buf + cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
 
 	for (i = 0; i < reg_random->count; i++) {
-		CDM_DUMP_CDBG("reg random: offset 0x%llx, value 0x%x\n",
-			((uint64_t) base_addr + data[0]), data[1]);
+		CAM_DBG(CAM_CDM, "reg random: offset %pK, value 0x%x",
+			((void __iomem *)(base_addr + data[0])),
+			data[1]);
 		cam_io_w(data[1], base_addr + data[0]);
 		data += 2;
 	}
@@ -420,7 +419,8 @@
 	swd_dmi = (struct cdm_dmi_cmd *)cmd_buf;
 
 	if (cmd_buf_size < (cdm_required_size_dmi() + swd_dmi->length + 1)) {
-		pr_err("invalid CDM_SWD_DMI length %d\n", swd_dmi->length + 1);
+		CAM_ERR(CAM_CDM, "invalid CDM_SWD_DMI length %d",
+			swd_dmi->length + 1);
 		return -EINVAL;
 	}
 	data = cmd_buf + cdm_required_size_dmi();
@@ -457,7 +457,7 @@
 	total_cmd_buf_size = cmd_buf_size;
 
 	while (cmd_buf_size > 0) {
-		CDM_CDBG("cmd data=%x\n", *cmd_buf);
+		CAM_DBG(CAM_CDM, "cmd data=%x", *cmd_buf);
 		cdm_cmd_type = (*cmd_buf >> CAM_CDM_COMMAND_OFFSET);
 		switch (cdm_cmd_type) {
 		case CAM_CDM_CMD_REG_CONT: {
@@ -488,7 +488,8 @@
 		case CAM_CDM_CMD_SWD_DMI_32:
 		case CAM_CDM_CMD_SWD_DMI_64: {
 			if (*current_device_base == 0) {
-				pr_err("Got SWI DMI cmd =%d for invalid hw\n",
+				CAM_ERR(CAM_CDM,
+					"Got SWI DMI cmd =%d for invalid hw",
 					cdm_cmd_type);
 				ret = -EINVAL;
 				break;
@@ -513,11 +514,12 @@
 				change_base_cmd->base, base_array_size,
 				base_table, current_device_base);
 			if (ret != 0) {
-				pr_err("Get ioremap change base failed %x\n",
+				CAM_ERR(CAM_CDM,
+					"Get ioremap change base failed %x",
 					change_base_cmd->base);
 				break;
 			}
-			CDM_CDBG("Got ioremap for %x addr=%pK\n",
+			CAM_DBG(CAM_CDM, "Got ioremap for %x addr=%pK",
 				change_base_cmd->base,
 				current_device_base);
 			cmd_buf_size -= (4 *
@@ -526,7 +528,7 @@
 			}
 			break;
 		default:
-			pr_err(" unsupported cdm_cmd_type type 0%x\n",
+			CAM_ERR(CAM_CDM, "unsupported cdm_cmd_type type 0%x",
 			cdm_cmd_type);
 			ret = -EINVAL;
 			break;
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
index bfe14e1..b230d4e 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-CDM-VIRTUAL %s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -46,7 +44,7 @@
 		if (payload->irq_status & 0x2) {
 			struct cam_cdm_bl_cb_request_entry *node;
 
-			CDM_CDBG("CDM HW Gen/inline IRQ with data=%x\n",
+			CAM_DBG(CAM_CDM, "CDM HW Gen/inline IRQ with data=%x",
 				payload->irq_data);
 			mutex_lock(&cdm_hw->hw_mutex);
 			node = cam_cdm_find_request_by_bl_tag(
@@ -60,18 +58,18 @@
 						(void *)node);
 				} else if (node->request_type ==
 					CAM_HW_CDM_BL_CB_INTERNAL) {
-					pr_err("Invalid node=%pK %d\n", node,
-						node->request_type);
+					CAM_ERR(CAM_CDM, "Invalid node=%pK %d",
+						node, node->request_type);
 				}
 				list_del_init(&node->entry);
 				kfree(node);
 			} else {
-				pr_err("Invalid node for inline irq\n");
+				CAM_ERR(CAM_CDM, "Invalid node for inline irq");
 			}
 			mutex_unlock(&cdm_hw->hw_mutex);
 		}
 		if (payload->irq_status & 0x1) {
-			CDM_CDBG("CDM HW reset done IRQ\n");
+			CAM_DBG(CAM_CDM, "CDM HW reset done IRQ");
 			complete(&core->reset_complete);
 		}
 		kfree(payload);
@@ -94,7 +92,8 @@
 
 		if ((!cdm_cmd->cmd[i].len) &&
 			(cdm_cmd->cmd[i].len > 0x100000)) {
-			pr_err("len(%d) is invalid count=%d total cnt=%d\n",
+			CAM_ERR(CAM_CDM,
+				"len(%d) is invalid count=%d total cnt=%d",
 				cdm_cmd->cmd[i].len, i,
 				req->data->cmd_arrary_count);
 			rc = -EINVAL;
@@ -111,7 +110,8 @@
 				(uint64_t)cdm_cmd->cmd[i].bl_addr.kernel_iova;
 			len = cdm_cmd->cmd[i].offset + cdm_cmd->cmd[i].len;
 		} else {
-			pr_err("Only mem hdl/Kernel va type is supported %d\n",
+			CAM_ERR(CAM_CDM,
+				"Only mem hdl/Kernel va type is supported %d",
 				req->data->type);
 			rc = -EINVAL;
 			break;
@@ -119,7 +119,8 @@
 
 		if ((!rc) && (vaddr_ptr) && (len) &&
 			(len >= cdm_cmd->cmd[i].offset)) {
-			CDM_CDBG("hdl=%x vaddr=%pK offset=%d cmdlen=%d:%zu\n",
+			CAM_DBG(CAM_CDM,
+				"hdl=%x vaddr=%pK offset=%d cmdlen=%d:%zu",
 				cdm_cmd->cmd[i].bl_addr.mem_handle,
 				(void *)vaddr_ptr, cdm_cmd->cmd[i].offset,
 				cdm_cmd->cmd[i].len, len);
@@ -130,15 +131,17 @@
 				cdm_cmd->cmd[i].len, client->data.base_array,
 				client->data.base_array_cnt, core->bl_tag);
 			if (rc) {
-				pr_err("write failed for cnt=%d:%d\n",
+				CAM_ERR(CAM_CDM, "write failed for cnt=%d:%d",
 					i, req->data->cmd_arrary_count);
 				break;
 			}
 		} else {
-			pr_err("Sanity check failed for hdl=%x len=%zu:%d\n",
+			CAM_ERR(CAM_CDM,
+				"Sanity check failed for hdl=%x len=%zu:%d",
 				cdm_cmd->cmd[i].bl_addr.mem_handle, len,
 				cdm_cmd->cmd[i].offset);
-			pr_err("Sanity check failed for cmd_count=%d cnt=%d\n",
+			CAM_ERR(CAM_CDM,
+				"Sanity check failed for cmd_count=%d cnt=%d",
 				i, req->data->cmd_arrary_count);
 			rc = -EINVAL;
 			break;
@@ -146,7 +149,8 @@
 		if (!rc) {
 			struct cam_cdm_work_payload *payload;
 
-			CDM_CDBG("write BL success for cnt=%d with tag=%d\n",
+			CAM_DBG(CAM_CDM,
+				"write BL success for cnt=%d with tag=%d",
 				i, core->bl_tag);
 			if ((true == req->data->flag) &&
 				(i == req->data->cmd_arrary_count)) {
@@ -184,7 +188,8 @@
 					}
 			}
 			core->bl_tag++;
-			CDM_CDBG("Now commit the BL nothing for virtual\n");
+			CAM_DBG(CAM_CDM,
+				"Now commit the BL nothing for virtual");
 			if (!rc && (core->bl_tag == 63))
 				core->bl_tag = 0;
 		}
@@ -230,7 +235,7 @@
 
 	rc = cam_cdm_soc_load_dt_private(pdev, cdm_hw->soc_info.soc_private);
 	if (rc) {
-		pr_err("Failed to load CDM dt private data\n");
+		CAM_ERR(CAM_CDM, "Failed to load CDM dt private data");
 		kfree(cdm_hw->soc_info.soc_private);
 		cdm_hw->soc_info.soc_private = NULL;
 		goto soc_load_failed;
@@ -257,7 +262,7 @@
 	cdm_hw_intf->hw_ops.write = NULL;
 	cdm_hw_intf->hw_ops.process_cmd = cam_cdm_process_cmd;
 
-	CDM_CDBG("type %d index %d\n", cdm_hw_intf->hw_type,
+	CAM_DBG(CAM_CDM, "type %d index %d", cdm_hw_intf->hw_type,
 		cdm_hw_intf->hw_idx);
 
 	platform_set_drvdata(pdev, cdm_hw_intf);
@@ -285,22 +290,23 @@
 		CAM_HW_IDENTIFIER_LENGTH);
 	rc = cam_cpas_register_client(&cpas_parms);
 	if (rc) {
-		pr_err("Virtual CDM CPAS registration failed\n");
+		CAM_ERR(CAM_CDM, "Virtual CDM CPAS registration failed");
 		goto cpas_registration_failed;
 	}
-	CDM_CDBG("CPAS registration successful handle=%d\n",
+	CAM_DBG(CAM_CDM, "CPAS registration successful handle=%d",
 		cpas_parms.client_handle);
 	cdm_core->cpas_handle = cpas_parms.client_handle;
 
-	CDM_CDBG("CDM%d probe successful\n", cdm_hw_intf->hw_idx);
+	CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx);
 
 	rc = cam_cdm_intf_register_hw_cdm(cdm_hw_intf,
 			soc_private, CAM_VIRTUAL_CDM, &cdm_core->index);
 	if (rc) {
-		pr_err("Virtual CDM Interface registration failed\n");
+		CAM_ERR(CAM_CDM, "Virtual CDM Interface registration failed");
 		goto intf_registration_failed;
 	}
-	CDM_CDBG("CDM%d registered to intf successful\n", cdm_hw_intf->hw_idx);
+	CAM_DBG(CAM_CDM, "CDM%d registered to intf successful",
+		cdm_hw_intf->hw_idx);
 	mutex_unlock(&cdm_hw->hw_mutex);
 
 	return 0;
@@ -328,27 +334,29 @@
 
 	cdm_hw_intf = platform_get_drvdata(pdev);
 	if (!cdm_hw_intf) {
-		pr_err("Failed to get dev private data\n");
+		CAM_ERR(CAM_CDM, "Failed to get dev private data");
 		return rc;
 	}
 
 	cdm_hw = cdm_hw_intf->hw_priv;
 	if (!cdm_hw) {
-		pr_err("Failed to get virtual private data for type=%d idx=%d\n",
+		CAM_ERR(CAM_CDM,
+			"Failed to get virtual private data for type=%d idx=%d",
 			cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx);
 		return rc;
 	}
 
 	cdm_core = cdm_hw->core_info;
 	if (!cdm_core) {
-		pr_err("Failed to get virtual core data for type=%d idx=%d\n",
+		CAM_ERR(CAM_CDM,
+			"Failed to get virtual core data for type=%d idx=%d",
 			cdm_hw_intf->hw_type, cdm_hw_intf->hw_idx);
 		return rc;
 	}
 
 	rc = cam_cpas_unregister_client(cdm_core->cpas_handle);
 	if (rc) {
-		pr_err("CPAS unregister failed\n");
+		CAM_ERR(CAM_CDM, "CPAS unregister failed");
 		return rc;
 	}
 
@@ -356,7 +364,8 @@
 			cdm_hw->soc_info.soc_private, CAM_VIRTUAL_CDM,
 			cdm_core->index);
 	if (rc) {
-		pr_err("Virtual CDM Interface de-registration failed\n");
+		CAM_ERR(CAM_CDM,
+			"Virtual CDM Interface de-registration failed");
 		return rc;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index fac8900..8f625ae 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include "cam_context.h"
+#include "cam_debug_util.h"
 
 static int cam_context_handle_hw_event(void *context, uint32_t evt_id,
 	void *evt_data)
@@ -21,7 +22,7 @@
 	struct cam_context *ctx = (struct cam_context *)context;
 
 	if (!ctx || !ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
@@ -29,8 +30,9 @@
 		rc = ctx->state_machine[ctx->state].irq_ops(ctx, evt_id,
 			evt_data);
 	else
-		pr_debug("%s: No function to handle event %d in dev %d, state %d\n",
-				__func__, evt_id, ctx->dev_hdl, ctx->state);
+		CAM_DBG(CAM_CORE,
+			"No function to handle event %d in dev %d, state %d",
+			evt_id, ctx->dev_hdl, ctx->state);
 	return rc;
 }
 
@@ -40,12 +42,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n'", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!info) {
-		pr_err("%s: Invalid get device info payload.\n", __func__);
+		CAM_ERR(CAM_CORE, "Invalid get device info payload");
 		return -EINVAL;
 	}
 
@@ -54,8 +56,8 @@
 		rc = ctx->state_machine[ctx->state].crm_ops.get_dev_info(
 			ctx, info);
 	} else {
-		pr_err("%s: No get device info in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_ERR(CAM_CORE, "No get device info in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -69,12 +71,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!link) {
-		pr_err("%s: Invalid link payload.\n", __func__);
+		CAM_ERR(CAM_CORE, "Invalid link payload");
 		return -EINVAL;
 	}
 
@@ -82,7 +84,7 @@
 	if (ctx->state_machine[ctx->state].crm_ops.link) {
 		rc = ctx->state_machine[ctx->state].crm_ops.link(ctx, link);
 	} else {
-		pr_err("%s: No crm link in dev %d, state %d\n", __func__,
+		CAM_ERR(CAM_CORE, "No crm link in dev %d, state %d",
 			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
@@ -97,12 +99,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready!\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!unlink) {
-		pr_err("%s: Invalid unlink payload.\n", __func__);
+		CAM_ERR(CAM_CORE, "Invalid unlink payload");
 		return -EINVAL;
 	}
 
@@ -111,8 +113,8 @@
 		rc = ctx->state_machine[ctx->state].crm_ops.unlink(
 			ctx, unlink);
 	} else {
-		pr_err("%s: No crm unlink in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_ERR(CAM_CORE, "No crm unlink in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -126,12 +128,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n'", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!apply) {
-		pr_err("%s: Invalid apply request payload.\n'", __func__);
+		CAM_ERR(CAM_CORE, "Invalid apply request payload");
 		return -EINVAL;
 	}
 
@@ -140,8 +142,8 @@
 		rc = ctx->state_machine[ctx->state].crm_ops.apply_req(ctx,
 			apply);
 	} else {
-		pr_err("%s: No crm apply req in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_ERR(CAM_CORE, "No crm apply req in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -155,7 +157,7 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
@@ -164,8 +166,8 @@
 		rc = ctx->state_machine[ctx->state].crm_ops.flush_req(ctx,
 			flush);
 	} else {
-		pr_err("%s: No crm flush req in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_ERR(CAM_CORE, "No crm flush req in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -179,13 +181,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!cmd) {
-		pr_err("%s: Invalid acquire device command payload.\n",
-			__func__);
+		CAM_ERR(CAM_CORE, "Invalid acquire device command payload");
 		return -EINVAL;
 	}
 
@@ -194,8 +195,8 @@
 		rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_dev(
 			ctx, cmd);
 	} else {
-		pr_err("%s: No acquire device in dev %d, state %d\n",
-			__func__, cmd->dev_handle, ctx->state);
+		CAM_ERR(CAM_CORE, "No acquire device in dev %d, state %d",
+			cmd->dev_handle, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -209,13 +210,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!cmd) {
-		pr_err("%s: Invalid release device command payload.\n",
-			__func__);
+		CAM_ERR(CAM_CORE, "Invalid release device command payload");
 		return -EINVAL;
 	}
 
@@ -224,8 +224,8 @@
 		rc = ctx->state_machine[ctx->state].ioctl_ops.release_dev(
 			ctx, cmd);
 	} else {
-		pr_err("%s: No release device in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_ERR(CAM_CORE, "No release device in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -239,13 +239,12 @@
 	int rc;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: context is not ready\n'", __func__);
+		CAM_ERR(CAM_CORE, "context is not ready");
 		return -EINVAL;
 	}
 
 	if (!cmd) {
-		pr_err("%s: Invalid config device command payload.\n",
-			__func__);
+		CAM_ERR(CAM_CORE, "Invalid config device command payload");
 		return -EINVAL;
 	}
 
@@ -254,8 +253,8 @@
 		rc = ctx->state_machine[ctx->state].ioctl_ops.config_dev(
 			ctx, cmd);
 	} else {
-		pr_err("%s: No config device in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_ERR(CAM_CORE, "No config device in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
@@ -269,13 +268,12 @@
 	int rc = 0;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!cmd) {
-		pr_err("%s: Invalid start device command payload.\n",
-			__func__);
+		CAM_ERR(CAM_CORE, "Invalid start device command payload");
 		return -EINVAL;
 	}
 
@@ -285,8 +283,8 @@
 			ctx, cmd);
 	else
 		/* start device can be optional for some driver */
-		pr_debug("%s: No start device in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_DBG(CAM_CORE, "No start device in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 
 	mutex_unlock(&ctx->ctx_mutex);
 
@@ -299,13 +297,12 @@
 	int rc = 0;
 
 	if (!ctx->state_machine) {
-		pr_err("%s: Context is not ready.\n'", __func__);
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
 	if (!cmd) {
-		pr_err("%s: Invalid stop device command payload.\n",
-			__func__);
+		CAM_ERR(CAM_CORE, "Invalid stop device command payload");
 		return -EINVAL;
 	}
 
@@ -315,8 +312,8 @@
 			ctx, cmd);
 	else
 		/* stop device can be optional for some driver */
-		pr_warn("%s: No stop device in dev %d, state %d\n",
-			__func__, ctx->dev_hdl, ctx->state);
+		CAM_WARN(CAM_CORE, "No stop device in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
 	mutex_unlock(&ctx->ctx_mutex);
 
 	return rc;
@@ -332,7 +329,7 @@
 
 	/* crm_node_intf is optinal */
 	if (!ctx || !hw_mgr_intf || !req_list) {
-		pr_err("%s: Invalid input parameters\n", __func__);
+		CAM_ERR(CAM_CORE, "Invalid input parameters");
 		return -EINVAL;
 	}
 
@@ -375,7 +372,7 @@
 	 * so we just free the memory for the context
 	 */
 	if (ctx->state != CAM_CTX_AVAILABLE)
-		pr_err("%s: Device did not shutdown cleanly.\n", __func__);
+		CAM_ERR(CAM_CORE, "Device did not shutdown cleanly");
 
 	memset(ctx, 0, sizeof(*ctx));
 
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index e934dff..1ee82b5 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CTXT-UTILS %s:%d " fmt, __func__, __LINE__
-
 #include <linux/debugfs.h>
 #include <linux/videodev2.h>
 #include <linux/slab.h>
@@ -25,6 +23,7 @@
 #include "cam_req_mgr_util.h"
 #include "cam_sync_api.h"
 #include "cam_trace.h"
+#include "cam_debug_util.h"
 
 int cam_context_buf_done_from_hw(struct cam_context *ctx,
 	void *done_event_data, uint32_t bubble_state)
@@ -35,8 +34,13 @@
 	struct cam_hw_done_event_data *done =
 		(struct cam_hw_done_event_data *)done_event_data;
 
+	if (!ctx || !done) {
+		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, done);
+		return -EINVAL;
+	}
+
 	if (list_empty(&ctx->active_req_list)) {
-		pr_err("Buf done with no active request\n");
+		CAM_ERR(CAM_CTXT, "no active request");
 		return -EIO;
 	}
 
@@ -46,13 +50,13 @@
 	trace_cam_buf_done("UTILS", ctx, req);
 
 	if (done->request_id != req->request_id) {
-		pr_err("mismatch: done request [%lld], active request [%lld]\n",
+		CAM_ERR(CAM_CTXT, "mismatch: done req[%lld], active req[%lld]",
 			done->request_id, req->request_id);
 		return -EIO;
 	}
 
 	if (!req->num_out_map_entries) {
-		pr_err("active request with no output fence objects to signal\n");
+		CAM_ERR(CAM_CTXT, "no output fence to signal");
 		return -EIO;
 	}
 
@@ -79,14 +83,20 @@
 	struct cam_ctx_request *req;
 	struct cam_hw_config_args cfg;
 
+	if (!ctx || !apply) {
+		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, apply);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	if (!ctx->hw_mgr_intf) {
-		pr_err("HW interface is not ready\n");
+		CAM_ERR(CAM_CTXT, "HW interface is not ready");
 		rc = -EFAULT;
 		goto end;
 	}
 
 	if (list_empty(&ctx->pending_req_list)) {
-		pr_err("No available request for Apply id %lld\n",
+		CAM_ERR(CAM_CTXT, "No available request for Apply id %lld",
 			apply->request_id);
 		rc = -EFAULT;
 		goto end;
@@ -103,7 +113,7 @@
 	cfg.num_hw_update_entries = req->num_hw_update_entries;
 	cfg.out_map_entries = req->out_map_entries;
 	cfg.num_out_map_entries = req->num_out_map_entries;
-	cfg.priv = (void *)&req->request_id;
+	cfg.priv = req->req_priv;
 	list_add_tail(&req->list, &ctx->active_req_list);
 
 	rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
@@ -120,6 +130,11 @@
 	struct cam_ctx_request *req = NULL;
 	struct cam_req_mgr_apply_request apply;
 
+	if (!ctx) {
+		CAM_ERR(CAM_CTXT, "Invalid input param");
+		return;
+	}
+
 	spin_lock(&ctx->lock);
 	if (!list_empty(&ctx->pending_req_list))
 		req = list_first_entry(&ctx->pending_req_list,
@@ -127,7 +142,7 @@
 	spin_unlock(&ctx->lock);
 
 	if (!req) {
-		pr_err("No more request obj free\n");
+		CAM_ERR(CAM_CTXT, "No more request obj free");
 		return;
 	}
 
@@ -145,8 +160,13 @@
 	struct cam_hw_release_args arg;
 	struct cam_ctx_request *req;
 
+	if (!ctx) {
+		CAM_ERR(CAM_CTXT, "Invalid input param");
+		return -EINVAL;
+	}
+
 	if ((!ctx->hw_mgr_intf) || (!ctx->hw_mgr_intf->hw_release)) {
-		pr_err("HW interface is not ready\n");
+		CAM_ERR(CAM_CTXT, "HW interface is not ready");
 		return -EINVAL;
 	}
 
@@ -168,7 +188,7 @@
 		req = list_first_entry(&ctx->active_req_list,
 			struct cam_ctx_request, list);
 		list_del_init(&req->list);
-		pr_debug("signal fence in active list. fence num %d\n",
+		CAM_DBG(CAM_CTXT, "signal fence in active list, num %d",
 			req->num_out_map_entries);
 		for (i = 0; i < req->num_out_map_entries; i++) {
 			if (req->out_map_entries[i].sync_id > 0)
@@ -187,7 +207,7 @@
 				cam_sync_deregister_callback(
 					cam_context_sync_callback, ctx,
 					req->in_map_entries[i].sync_id);
-		pr_debug("signal out fence in pending list. fence num %d\n",
+		CAM_DBG(CAM_CTXT, "signal fence in pending list, num %d",
 			req->num_out_map_entries);
 		for (i = 0; i < req->num_out_map_entries; i++)
 			if (req->out_map_entries[i].sync_id > 0)
@@ -210,8 +230,14 @@
 	size_t len = 0;
 	int32_t i = 0;
 
+	if (!ctx || !cmd) {
+		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	if (!ctx->hw_mgr_intf) {
-		pr_err("HW interface is not ready\n");
+		CAM_ERR(CAM_CTXT, "HW interface is not ready");
 		rc = -EFAULT;
 		goto end;
 	}
@@ -225,7 +251,7 @@
 	spin_unlock(&ctx->lock);
 
 	if (!req) {
-		pr_err("No more request obj free\n");
+		CAM_ERR(CAM_CTXT, "No more request obj free");
 		rc = -ENOMEM;
 		goto end;
 	}
@@ -239,20 +265,12 @@
 		(uint64_t *) &packet_addr,
 		&len);
 	if (rc != 0) {
-		pr_err("Can not get packet address\n");
+		CAM_ERR(CAM_CTXT, "Can not get packet address");
 		rc = -EINVAL;
 		goto free_req;
 	}
 
 	packet = (struct cam_packet *) (packet_addr + cmd->offset);
-	pr_debug("pack_handle %llx\n", cmd->packet_handle);
-	pr_debug("packet address is 0x%llx\n", packet_addr);
-	pr_debug("packet with length %zu, offset 0x%llx\n",
-		len, cmd->offset);
-	pr_debug("Packet request id 0x%llx\n",
-		packet->header.request_id);
-	pr_debug("Packet size 0x%x\n", packet->header.size);
-	pr_debug("packet op %d\n", packet->header.op_code);
 
 	/* preprocess the configuration */
 	memset(&cfg, 0, sizeof(cfg));
@@ -269,7 +287,7 @@
 	rc = ctx->hw_mgr_intf->hw_prepare_update(
 		ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
 	if (rc != 0) {
-		pr_err("Prepare config packet failed in HW layer\n");
+		CAM_ERR(CAM_CTXT, "Prepare config packet failed in HW layer");
 		rc = -EFAULT;
 		goto free_req;
 	}
@@ -289,7 +307,7 @@
 					cam_context_sync_callback,
 					(void *)ctx,
 					req->in_map_entries[i].sync_id);
-			pr_debug("register in fence callback: %d ret = %d\n",
+			CAM_DBG(CAM_CTXT, "register in fence cb: %d ret = %d",
 				req->in_map_entries[i].sync_id, rc);
 		}
 		goto end;
@@ -302,7 +320,6 @@
 	list_add_tail(&req->list, &ctx->free_req_list);
 	spin_unlock(&ctx->lock);
 end:
-	pr_debug("Config dev successful\n");
 	return rc;
 }
 
@@ -314,26 +331,31 @@
 	struct cam_create_dev_hdl req_hdl_param;
 	struct cam_hw_release_args release;
 
+	if (!ctx || !cmd) {
+		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	if (!ctx->hw_mgr_intf) {
-		pr_err("HW interface is not ready\n");
+		CAM_ERR(CAM_CTXT, "HW interface is not ready");
 		rc = -EFAULT;
 		goto end;
 	}
 
-	pr_debug("acquire cmd: session_hdl 0x%x, num_resources %d\n",
-		cmd->session_handle, cmd->num_resources);
-	pr_debug(" handle type %d, res %lld\n", cmd->handle_type,
+	CAM_DBG(CAM_CTXT, "ses hdl: %x, num_res: %d, type: %d, res: %lld",
+		cmd->session_handle, cmd->num_resources, cmd->handle_type,
 		cmd->resource_hdl);
 
 	if (cmd->num_resources > CAM_CTX_RES_MAX) {
-		pr_err("Too much resources in the acquire\n");
+		CAM_ERR(CAM_CTXT, "resource limit exceeded");
 		rc = -ENOMEM;
 		goto end;
 	}
 
 	/* for now we only support user pointer */
 	if (cmd->handle_type != 1)  {
-		pr_err("Only user pointer is supported");
+		CAM_ERR(CAM_CTXT, "Only user pointer is supported");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -344,15 +366,11 @@
 	param.num_acq = cmd->num_resources;
 	param.acquire_info = cmd->resource_hdl;
 
-	pr_debug("ctx %pK: acquire hw resource: hw_intf: 0x%pK, priv 0x%pK",
-		ctx, ctx->hw_mgr_intf, ctx->hw_mgr_intf->hw_mgr_priv);
-	pr_debug("acquire_hw_func 0x%pK\n", ctx->hw_mgr_intf->hw_acquire);
-
 	/* call HW manager to reserve the resource */
 	rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv,
 		&param);
 	if (rc != 0) {
-		pr_err("Acquire device failed\n");
+		CAM_ERR(CAM_CTXT, "Acquire device failed");
 		goto end;
 	}
 
@@ -365,11 +383,10 @@
 	req_hdl_param.media_entity_flag = 0;
 	req_hdl_param.priv = ctx;
 
-	pr_debug("get device handle from bridge\n");
 	ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param);
 	if (ctx->dev_hdl <= 0) {
 		rc = -EFAULT;
-		pr_err("Can not create device handle\n");
+		CAM_ERR(CAM_CTXT, "Can not create device handle");
 		goto free_hw;
 	}
 	cmd->dev_handle = ctx->dev_hdl;
@@ -377,7 +394,6 @@
 	/* store session information */
 	ctx->session_hdl = cmd->session_handle;
 
-	pr_err("dev_handle = %x\n", cmd->dev_handle);
 	return rc;
 
 free_hw:
@@ -394,31 +410,37 @@
 	int rc = 0;
 	struct cam_hw_start_args arg;
 
+	if (!ctx || !cmd) {
+		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	if (!ctx->hw_mgr_intf) {
-		pr_err("HW interface is not ready\n");
+		CAM_ERR(CAM_CTXT, "HW interface is not ready");
 		rc = -EFAULT;
 		goto end;
 	}
 
 	if ((cmd->session_handle != ctx->session_hdl) ||
 		(cmd->dev_handle != ctx->dev_hdl)) {
-		pr_err("Invalid session hdl[%d], dev_handle[%d]\n",
+		CAM_ERR(CAM_CTXT, "Invalid session hdl[%d], dev_handle[%d]",
 			cmd->session_handle, cmd->dev_handle);
 		rc = -EPERM;
 		goto end;
 	}
 
 	if (ctx->hw_mgr_intf->hw_start) {
+		arg.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
 		rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
 				&arg);
 		if (rc) {
 			/* HW failure. user need to clean up the resource */
-			pr_err("Start HW failed\n");
+			CAM_ERR(CAM_CTXT, "Start HW failed");
 			goto end;
 		}
 	}
 
-	pr_debug("start device success\n");
 end:
 	return rc;
 }
@@ -430,8 +452,14 @@
 	struct cam_hw_stop_args stop;
 	struct cam_ctx_request *req;
 
+	if (!ctx) {
+		CAM_ERR(CAM_CTXT, "Invalid input param");
+		rc = -EINVAL;
+		goto end;
+	}
+
 	if (!ctx->hw_mgr_intf) {
-		pr_err("HW interface is not ready\n");
+		CAM_ERR(CAM_CTXT, "HW interface is not ready");
 		rc = -EFAULT;
 		goto end;
 	}
@@ -449,7 +477,7 @@
 		req = list_first_entry(&ctx->pending_req_list,
 				struct cam_ctx_request, list);
 		list_del_init(&req->list);
-		pr_debug("signal fence in pending list. fence num %d\n",
+		CAM_DBG(CAM_CTXT, "signal fence in pending list. fence num %d",
 			req->num_out_map_entries);
 		for (i = 0; i < req->num_out_map_entries; i++)
 			if (req->out_map_entries[i].sync_id != -1)
@@ -462,7 +490,7 @@
 		req = list_first_entry(&ctx->active_req_list,
 				struct cam_ctx_request, list);
 		list_del_init(&req->list);
-		pr_debug("signal fence in active list. fence num %d\n",
+		CAM_DBG(CAM_CTXT, "signal fence in active list. fence num %d",
 			req->num_out_map_entries);
 		for (i = 0; i < req->num_out_map_entries; i++)
 			if (req->out_map_entries[i].sync_id != -1)
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index fa26ea0..043f44d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -16,7 +16,7 @@
 
 #include "cam_node.h"
 #include "cam_trace.h"
-
+#include "cam_debug_util.h"
 static void  __cam_node_handle_shutdown(struct cam_node *node)
 {
 	if (node->hw_mgr_intf.hw_close)
@@ -30,7 +30,7 @@
 	int rc = -EFAULT;
 
 	if (!query) {
-		pr_err("%s: Invalid params\n", __func__);
+		CAM_ERR(CAM_CORE, "Invalid params");
 		return -EINVAL;
 	}
 
@@ -65,7 +65,7 @@
 
 	rc = cam_context_handle_acquire_dev(ctx, acquire);
 	if (rc) {
-		pr_err("%s: Acquire device failed\n", __func__);
+		CAM_ERR(CAM_CORE, "Acquire device failed");
 		goto free_ctx;
 	}
 
@@ -87,19 +87,19 @@
 		return -EINVAL;
 
 	if (start->dev_handle <= 0) {
-		pr_err("Invalid device handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid device handle for context");
 		return -EINVAL;
 	}
 
 	if (start->session_handle <= 0) {
-		pr_err("Invalid session handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid session handle for context");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_context *)cam_get_device_priv(start->dev_handle);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, start->dev_handle);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			start->dev_handle);
 		return -EINVAL;
 	}
 
@@ -115,19 +115,19 @@
 		return -EINVAL;
 
 	if (stop->dev_handle <= 0) {
-		pr_err("Invalid device handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid device handle for context");
 		return -EINVAL;
 	}
 
 	if (stop->session_handle <= 0) {
-		pr_err("Invalid session handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid session handle for context");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_context *)cam_get_device_priv(stop->dev_handle);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, stop->dev_handle);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			stop->dev_handle);
 		return -EINVAL;
 	}
 
@@ -143,19 +143,19 @@
 		return -EINVAL;
 
 	if (config->dev_handle <= 0) {
-		pr_err("Invalid device handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid device handle for context");
 		return -EINVAL;
 	}
 
 	if (config->session_handle <= 0) {
-		pr_err("Invalid session handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid session handle for context");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_context *)cam_get_device_priv(config->dev_handle);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, config->dev_handle);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			config->dev_handle);
 		return -EINVAL;
 	}
 
@@ -172,29 +172,29 @@
 		return -EINVAL;
 
 	if (release->dev_handle <= 0) {
-		pr_err("Invalid device handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid device handle for context");
 		return -EINVAL;
 	}
 
 	if (release->session_handle <= 0) {
-		pr_err("Invalid session handle for context\n");
+		CAM_ERR(CAM_CORE, "Invalid session handle for context");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, release->dev_handle);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			release->dev_handle);
 		return -EINVAL;
 	}
 
 	rc = cam_context_handle_release_dev(ctx, release);
 	if (rc)
-		pr_err("%s: context release failed\n", __func__);
+		CAM_ERR(CAM_CORE, "context release failed");
 
 	rc = cam_destroy_device_hdl(release->dev_handle);
 	if (rc)
-		pr_err("%s: destroy device handle is failed\n", __func__);
+		CAM_ERR(CAM_CORE, "destroy device handle is failed");
 
 	mutex_lock(&node->list_mutex);
 	list_add_tail(&ctx->list, &node->free_ctx_list);
@@ -211,8 +211,8 @@
 
 	ctx = (struct cam_context *) cam_get_device_priv(info->dev_hdl);
 	if (!ctx) {
-		pr_err("%s: Can not get context  for handle %d\n",
-			__func__, info->dev_hdl);
+		CAM_ERR(CAM_CORE, "Can not get context  for handle %d",
+			info->dev_hdl);
 		return -EINVAL;
 	}
 	return cam_context_handle_crm_get_dev_info(ctx, info);
@@ -229,8 +229,8 @@
 
 	ctx = (struct cam_context *) cam_get_device_priv(setup->dev_hdl);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, setup->dev_hdl);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			setup->dev_hdl);
 		return -EINVAL;
 	}
 
@@ -251,8 +251,8 @@
 
 	ctx = (struct cam_context *) cam_get_device_priv(apply->dev_hdl);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, apply->dev_hdl);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			apply->dev_hdl);
 		return -EINVAL;
 	}
 
@@ -266,14 +266,14 @@
 	struct cam_context *ctx = NULL;
 
 	if (!flush) {
-		pr_err("%s: Invalid flush request payload\n", __func__);
+		CAM_ERR(CAM_CORE, "Invalid flush request payload");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_context *) cam_get_device_priv(flush->dev_hdl);
 	if (!ctx) {
-		pr_err("%s: Can not get context for handle %d\n",
-			__func__, flush->dev_hdl);
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			flush->dev_hdl);
 		return -EINVAL;
 	}
 
@@ -285,7 +285,7 @@
 	if (node)
 		memset(node, 0, sizeof(*node));
 
-	pr_debug("%s: deinit complete!\n", __func__);
+	CAM_DBG(CAM_CORE, "deinit complete");
 
 	return 0;
 }
@@ -317,8 +317,8 @@
 	node->ctx_size = ctx_size;
 	for (i = 0; i < ctx_size; i++) {
 		if (!ctx_list[i].state_machine) {
-			pr_err("%s: camera context %d is not initialized!",
-				__func__, i);
+			CAM_ERR(CAM_CORE,
+				"camera context %d is not initialized", i);
 			rc = -1;
 			goto err;
 		}
@@ -328,7 +328,7 @@
 
 	node->state = CAM_NODE_STATE_INIT;
 err:
-	pr_debug("%s: Exit. (rc = %d)\n", __func__, rc);
+	CAM_DBG(CAM_CORE, "Exit. (rc = %d)", rc);
 	return rc;
 }
 
@@ -339,7 +339,7 @@
 	if (!cmd)
 		return -EINVAL;
 
-	pr_debug("%s: handle cmd %d\n", __func__, cmd->op_code);
+	CAM_DBG(CAM_CORE, "handle cmd %d", cmd->op_code);
 
 	switch (cmd->op_code) {
 	case CAM_QUERY_CAP: {
@@ -353,8 +353,8 @@
 
 		rc = __cam_node_handle_query_cap(node, &query);
 		if (rc) {
-			pr_err("%s: querycap is failed(rc = %d)\n",
-				__func__,  rc);
+			CAM_ERR(CAM_CORE, "querycap is failed(rc = %d)",
+				rc);
 			break;
 		}
 
@@ -374,8 +374,8 @@
 		}
 		rc = __cam_node_handle_acquire_dev(node, &acquire);
 		if (rc) {
-			pr_err("%s: acquire device failed(rc = %d)\n",
-				__func__, rc);
+			CAM_ERR(CAM_CORE, "acquire device failed(rc = %d)",
+				rc);
 			break;
 		}
 		if (copy_to_user((void __user *)cmd->handle, &acquire,
@@ -392,8 +392,8 @@
 		else {
 			rc = __cam_node_handle_start_dev(node, &start);
 			if (rc)
-				pr_err("%s: start device failed(rc = %d)\n",
-					__func__, rc);
+				CAM_ERR(CAM_CORE,
+					"start device failed(rc = %d)", rc);
 		}
 		break;
 	}
@@ -406,8 +406,8 @@
 		else {
 			rc = __cam_node_handle_stop_dev(node, &stop);
 			if (rc)
-				pr_err("%s: stop device failed(rc = %d)\n",
-					__func__, rc);
+				CAM_ERR(CAM_CORE,
+					"stop device failed(rc = %d)", rc);
 		}
 		break;
 	}
@@ -420,8 +420,8 @@
 		else {
 			rc = __cam_node_handle_config_dev(node, &config);
 			if (rc)
-				pr_err("%s: config device failed(rc = %d)\n",
-					__func__, rc);
+				CAM_ERR(CAM_CORE,
+					"config device failed(rc = %d)", rc);
 		}
 		break;
 	}
@@ -434,8 +434,8 @@
 		else {
 			rc = __cam_node_handle_release_dev(node, &release);
 			if (rc)
-				pr_err("%s: release device failed(rc = %d)\n",
-					__func__, rc);
+				CAM_ERR(CAM_CORE,
+					"release device failed(rc = %d)", rc);
 		}
 		break;
 	}
@@ -443,7 +443,7 @@
 		__cam_node_handle_shutdown(node);
 		break;
 	default:
-		pr_err("Unknown op code %d\n", cmd->op_code);
+		CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code);
 		rc = -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_subdev.c b/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
index 8664ce8..d690508 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
@@ -12,6 +12,7 @@
 
 #include "cam_subdev.h"
 #include "cam_node.h"
+#include "cam_debug_util.h"
 
 /**
  * cam_subdev_subscribe_event()
@@ -63,7 +64,7 @@
 			(struct cam_control *) arg);
 		break;
 	default:
-		pr_err("Invalid command %d for %s!\n", cmd,
+		CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd,
 			node->name);
 		rc = -EINVAL;
 	}
@@ -80,7 +81,7 @@
 
 	if (copy_from_user(&cmd_data, (void __user *)arg,
 		sizeof(cmd_data))) {
-		pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+		CAM_ERR(CAM_CORE, "Failed to copy from user_ptr=%pK size=%zu",
 			(void __user *)arg, sizeof(cmd_data));
 		return -EFAULT;
 	}
@@ -88,7 +89,8 @@
 	if (!rc) {
 		if (copy_to_user((void __user *)arg, &cmd_data,
 			sizeof(cmd_data))) {
-			pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+			CAM_ERR(CAM_CORE,
+				"Failed to copy to user_ptr=%pK size=%zu",
 				(void __user *)arg, sizeof(cmd_data));
 			rc = -EFAULT;
 		}
@@ -147,8 +149,8 @@
 
 	rc = cam_register_subdev(sd);
 	if (rc) {
-		pr_err("%s: cam_register_subdev() failed for dev: %s!\n",
-			__func__, sd->name);
+		CAM_ERR(CAM_CORE, "cam_register_subdev() failed for dev: %s",
+			sd->name);
 		goto err;
 	}
 	platform_set_drvdata(sd->pdev, sd);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index 813f392..82035e9 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
@@ -21,22 +21,6 @@
 #include "cam_cpas_hw_intf.h"
 #include "cam_cpas_soc.h"
 
-int cam_cpas_util_get_string_index(const char **strings,
-	uint32_t num_strings, char *matching_string, uint32_t *index)
-{
-	int i;
-
-	for (i = 0; i < num_strings; i++) {
-		if (strnstr(strings[i], matching_string, strlen(strings[i]))) {
-			CPAS_CDBG("matched %s : %d\n", matching_string, i);
-			*index = i;
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
 int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
 	enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
 {
@@ -62,7 +46,7 @@
 		value = reg_info->value;
 	}
 
-	CPAS_CDBG("Base[%d] Offset[0x%8x] Value[0x%8x]\n",
+	CAM_DBG(CAM_CPAS, "Base[%d] Offset[0x%8x] Value[0x%8x]",
 		reg_base, reg_info->offset, value);
 
 	cam_io_w_mb(value, soc_info->reg_map[reg_base_index].mem_base +
@@ -75,13 +59,13 @@
 	struct cam_cpas_bus_client *bus_client, unsigned int level)
 {
 	if (!bus_client->valid || (bus_client->dyn_vote == true)) {
-		pr_err("Invalid params %d %d\n", bus_client->valid,
+		CAM_ERR(CAM_CPAS, "Invalid params %d %d", bus_client->valid,
 			bus_client->dyn_vote);
 		return -EINVAL;
 	}
 
 	if (level >= bus_client->num_usecases) {
-		pr_err("Invalid vote level=%d, usecases=%d\n", level,
+		CAM_ERR(CAM_CPAS, "Invalid vote level=%d, usecases=%d", level,
 			bus_client->num_usecases);
 		return -EINVAL;
 	}
@@ -89,7 +73,8 @@
 	if (level == bus_client->curr_vote_level)
 		return 0;
 
-	CPAS_CDBG("Bus client[%d] index[%d]\n", bus_client->client_id, level);
+	CAM_DBG(CAM_CPAS, "Bus client[%d] index[%d]", bus_client->client_id,
+		level);
 	msm_bus_scale_client_update_request(bus_client->client_id, level);
 	bus_client->curr_vote_level = level;
 
@@ -104,14 +89,14 @@
 	int idx = 0;
 
 	if (!bus_client->valid) {
-		pr_err("bus client not valid\n");
+		CAM_ERR(CAM_CPAS, "bus client not valid");
 		return -EINVAL;
 	}
 
 	if ((bus_client->num_usecases != 2) ||
 		(bus_client->num_paths != 1) ||
 		(bus_client->dyn_vote != true)) {
-		pr_err("dynamic update not allowed %d %d %d\n",
+		CAM_ERR(CAM_CPAS, "dynamic update not allowed %d %d %d",
 			bus_client->num_usecases, bus_client->num_paths,
 			bus_client->dyn_vote);
 		return -EINVAL;
@@ -120,7 +105,7 @@
 	mutex_lock(&bus_client->lock);
 
 	if (bus_client->curr_vote_level > 1) {
-		pr_err("curr_vote_level %d cannot be greater than 1\n",
+		CAM_ERR(CAM_CPAS, "curr_vote_level %d cannot be greater than 1",
 			bus_client->curr_vote_level);
 		mutex_unlock(&bus_client->lock);
 		return -EINVAL;
@@ -136,7 +121,7 @@
 	path->vectors[0].ab = ab;
 	path->vectors[0].ib = ib;
 
-	CPAS_CDBG("Bus client[%d] :ab[%llu] ib[%llu], index[%d]\n",
+	CAM_DBG(CAM_CPAS, "Bus client[%d] :ab[%llu] ib[%llu], index[%d]",
 		bus_client->client_id, ab, ib, idx);
 	msm_bus_scale_client_update_request(bus_client->client_id, idx);
 
@@ -154,20 +139,20 @@
 	pdata = msm_bus_pdata_from_node(soc_info->pdev,
 		dev_node);
 	if (!pdata) {
-		pr_err("failed get_pdata\n");
+		CAM_ERR(CAM_CPAS, "failed get_pdata");
 		return -EINVAL;
 	}
 
 	if ((pdata->num_usecases == 0) ||
 		(pdata->usecase[0].num_paths == 0)) {
-		pr_err("usecase=%d\n", pdata->num_usecases);
+		CAM_ERR(CAM_CPAS, "usecase=%d", pdata->num_usecases);
 		rc = -EINVAL;
 		goto error;
 	}
 
 	client_id = msm_bus_scale_register_client(pdata);
 	if (!client_id) {
-		pr_err("failed in register ahb bus client\n");
+		CAM_ERR(CAM_CPAS, "failed in register ahb bus client");
 		rc = -EINVAL;
 		goto error;
 	}
@@ -176,7 +161,8 @@
 		"qcom,msm-bus-vector-dyn-vote");
 
 	if (bus_client->dyn_vote && (pdata->num_usecases != 2)) {
-		pr_err("Excess or less vectors %d\n", pdata->num_usecases);
+		CAM_ERR(CAM_CPAS, "Excess or less vectors %d",
+			pdata->num_usecases);
 		rc = -EINVAL;
 		goto fail_unregister_client;
 	}
@@ -193,7 +179,7 @@
 	bus_client->valid = true;
 	mutex_init(&bus_client->lock);
 
-	CPAS_CDBG("Bus Client : src=%d, dst=%d, bus_client=%d\n",
+	CAM_DBG(CAM_CPAS, "Bus Client : src=%d, dst=%d, bus_client=%d",
 		bus_client->src, bus_client->dst, bus_client->client_id);
 
 	return 0;
@@ -268,7 +254,7 @@
 	axi_port_list_node = of_find_node_by_name(soc_info->pdev->dev.of_node,
 		"qcom,axi-port-list");
 	if (!axi_port_list_node) {
-		pr_err("Node qcom,axi-port-list not found.\n");
+		CAM_ERR(CAM_CPAS, "Node qcom,axi-port-list not found.");
 		return -EINVAL;
 	}
 
@@ -286,14 +272,15 @@
 			"qcom,axi-port-name", 0,
 			(const char **)&axi_port->axi_port_name);
 		if (rc) {
-			pr_err("failed to read qcom,axi-port-name rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS,
+				"failed to read qcom,axi-port-name rc=%d", rc);
 			goto port_name_fail;
 		}
 
 		axi_port_mnoc_node = of_find_node_by_name(axi_port_node,
 			"qcom,axi-port-mnoc");
 		if (!axi_port_mnoc_node) {
-			pr_err("Node qcom,axi-port-mnoc not found.\n");
+			CAM_ERR(CAM_CPAS, "Node qcom,axi-port-mnoc not found.");
 			rc = -EINVAL;
 			goto mnoc_node_get_fail;
 		}
@@ -308,7 +295,8 @@
 			axi_port_camnoc_node = of_find_node_by_name(
 				axi_port_node, "qcom,axi-port-camnoc");
 			if (!axi_port_camnoc_node) {
-				pr_err("Node qcom,axi-port-camnoc not found\n");
+				CAM_ERR(CAM_CPAS,
+					"Node qcom,axi-port-camnoc not found");
 				rc = -EINVAL;
 				goto camnoc_node_get_fail;
 			}
@@ -358,7 +346,8 @@
 	rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client,
 		(enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE);
 	if (rc) {
-		pr_err("Failed in AHB vote, enable=%d, rc=%d\n", enable, rc);
+		CAM_ERR(CAM_CPAS, "Failed in AHB vote, enable=%d, rc=%d",
+			enable, rc);
 		return rc;
 	}
 
@@ -375,7 +364,8 @@
 		rc = cam_cpas_util_vote_bus_client_bw(&curr_port->mnoc_bus,
 			mnoc_bw, 0);
 		if (rc) {
-			pr_err("Failed in mnoc vote, enable=%d, rc=%d\n",
+			CAM_ERR(CAM_CPAS,
+				"Failed in mnoc vote, enable=%d, rc=%d",
 				enable, rc);
 			goto remove_ahb_vote;
 		}
@@ -384,7 +374,8 @@
 			cam_cpas_util_vote_bus_client_bw(
 				&curr_port->camnoc_bus, camnoc_bw, 0);
 			if (rc) {
-				pr_err("Failed in mnoc vote, enable=%d, %d\n",
+				CAM_ERR(CAM_CPAS,
+					"Failed in mnoc vote, enable=%d, %d",
 					enable, rc);
 				cam_cpas_util_vote_bus_client_bw(
 					&curr_port->mnoc_bus, 0, 0);
@@ -446,7 +437,8 @@
 	int rc = 0;
 
 	if (reg_base_index < 0 || reg_base_index >= soc_info->num_reg_map) {
-		pr_err("Invalid reg_base=%d, reg_base_index=%d, num_map=%d\n",
+		CAM_ERR(CAM_CPAS,
+			"Invalid reg_base=%d, reg_base_index=%d, num_map=%d",
 			reg_base, reg_base_index, soc_info->num_reg_map);
 		return -EINVAL;
 	}
@@ -457,7 +449,7 @@
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("client has not started%d\n", client_indx);
+		CAM_ERR(CAM_CPAS, "client has not started%d", client_indx);
 		rc = -EPERM;
 		goto unlock_client;
 	}
@@ -489,7 +481,8 @@
 		return -EINVAL;
 
 	if (reg_base_index < 0 || reg_base_index >= soc_info->num_reg_map) {
-		pr_err("Invalid reg_base=%d, reg_base_index=%d, num_map=%d\n",
+		CAM_ERR(CAM_CPAS,
+			"Invalid reg_base=%d, reg_base_index=%d, num_map=%d",
 			reg_base, reg_base_index, soc_info->num_reg_map);
 		return -EINVAL;
 	}
@@ -500,7 +493,7 @@
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("client has not started%d\n", client_indx);
+		CAM_ERR(CAM_CPAS, "client has not started%d", client_indx);
 		rc = -EPERM;
 		goto unlock_client;
 	}
@@ -531,7 +524,7 @@
 	int rc = 0;
 
 	if (!axi_port) {
-		pr_err("axi port does not exists\n");
+		CAM_ERR(CAM_CPAS, "axi port does not exists");
 		return -EINVAL;
 	}
 
@@ -563,7 +556,8 @@
 	if ((!soc_private->axi_camnoc_based) && (mnoc_bw < camnoc_bw))
 		mnoc_bw = camnoc_bw;
 
-	CPAS_CDBG("axi[(%d, %d),(%d, %d)] : camnoc_bw[%llu], mnoc_bw[%llu]\n",
+	CAM_DBG(CAM_CPAS,
+		"axi[(%d, %d),(%d, %d)] : camnoc_bw[%llu], mnoc_bw[%llu]",
 		axi_port->mnoc_bus.src, axi_port->mnoc_bus.dst,
 		axi_port->camnoc_bus.src, axi_port->camnoc_bus.dst,
 		camnoc_bw, mnoc_bw);
@@ -571,7 +565,8 @@
 	rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
 		mnoc_bw, 0);
 	if (rc) {
-		pr_err("Failed in mnoc vote ab[%llu] ib[%llu] rc=%d\n",
+		CAM_ERR(CAM_CPAS,
+			"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
 			mnoc_bw, mnoc_bw, rc);
 		goto unlock_axi_port;
 	}
@@ -580,7 +575,8 @@
 		rc = cam_cpas_util_vote_bus_client_bw(&axi_port->camnoc_bus,
 			camnoc_bw, 0);
 		if (rc) {
-			pr_err("Failed camnoc vote ab[%llu] ib[%llu] rc=%d\n",
+			CAM_ERR(CAM_CPAS,
+				"Failed camnoc vote ab[%llu] ib[%llu] rc=%d",
 				camnoc_bw, camnoc_bw, rc);
 			goto unlock_axi_port;
 		}
@@ -600,7 +596,8 @@
 
 	if (!axi_vote || ((axi_vote->compressed_bw == 0) &&
 		(axi_vote->uncompressed_bw == 0))) {
-		pr_err("Invalid vote, client_handle=%d\n", client_handle);
+		CAM_ERR(CAM_CPAS, "Invalid vote, client_handle=%d",
+			client_handle);
 		return -EINVAL;
 	}
 
@@ -610,12 +607,13 @@
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("client has not started %d\n", client_indx);
+		CAM_ERR(CAM_CPAS, "client has not started %d", client_indx);
 		rc = -EPERM;
 		goto unlock_client;
 	}
 
-	CPAS_CDBG("Client[%d] Requested compressed[%llu], uncompressed[%llu]\n",
+	CAM_DBG(CAM_CPAS,
+		"Client[%d] Requested compressed[%llu], uncompressed[%llu]",
 		client_indx, axi_vote->compressed_bw,
 		axi_vote->uncompressed_bw);
 
@@ -640,13 +638,14 @@
 	int i;
 
 	if (!dev || !req_level) {
-		pr_err("Invalid params %pK, %pK\n", dev, req_level);
+		CAM_ERR(CAM_CPAS, "Invalid params %pK, %pK", dev, req_level);
 		return -EINVAL;
 	}
 
 	opp = dev_pm_opp_find_freq_ceil(dev, &corner_freq);
 	if (IS_ERR(opp)) {
-		pr_err("Error on OPP freq :%ld, %pK\n", corner_freq, opp);
+		CAM_ERR(CAM_CPAS, "Error on OPP freq :%ld, %pK",
+			corner_freq, opp);
 		return -EINVAL;
 	}
 
@@ -656,7 +655,8 @@
 		if (corner == soc_private->vdd_ahb[i].vdd_corner)
 			level = soc_private->vdd_ahb[i].ahb_level;
 
-	CPAS_CDBG("From OPP table : freq=[%ld][%ld], corner=%d, level=%d\n",
+	CAM_DBG(CAM_CPAS,
+		"From OPP table : freq=[%ld][%ld], corner=%d, level=%d",
 		freq, corner_freq, corner, level);
 
 	*req_level = level;
@@ -675,7 +675,7 @@
 	int i, rc = 0;
 
 	if (!ahb_bus_client->valid) {
-		pr_err("AHB Bus client not valid\n");
+		CAM_ERR(CAM_CPAS, "AHB Bus client not valid");
 		return -EINVAL;
 	}
 
@@ -694,7 +694,7 @@
 	mutex_lock(&ahb_bus_client->lock);
 	cpas_client->ahb_level = required_level;
 
-	CPAS_CDBG("Clients required level[%d], curr_level[%d]\n",
+	CAM_DBG(CAM_CPAS, "Clients required level[%d], curr_level[%d]",
 		required_level, ahb_bus_client->curr_vote_level);
 
 	if (required_level == ahb_bus_client->curr_vote_level)
@@ -707,19 +707,20 @@
 			highest_level = cpas_core->cpas_client[i]->ahb_level;
 	}
 
-	CPAS_CDBG("Required highest_level[%d]\n", highest_level);
+	CAM_DBG(CAM_CPAS, "Required highest_level[%d]", highest_level);
 
 	rc = cam_cpas_util_vote_bus_client_level(ahb_bus_client,
 		highest_level);
 	if (rc) {
-		pr_err("Failed in ahb vote, level=%d, rc=%d\n",
+		CAM_ERR(CAM_CPAS, "Failed in ahb vote, level=%d, rc=%d",
 			highest_level, rc);
 		goto unlock_bus_client;
 	}
 
 	rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info, highest_level);
 	if (rc) {
-		pr_err("Failed in scaling clock rate level %d for AHB\n",
+		CAM_ERR(CAM_CPAS,
+			"Failed in scaling clock rate level %d for AHB",
 			highest_level);
 		goto unlock_bus_client;
 	}
@@ -740,7 +741,7 @@
 	int rc = 0;
 
 	if (!ahb_vote || (ahb_vote->vote.level == 0)) {
-		pr_err("Invalid AHB vote, %pK\n", ahb_vote);
+		CAM_ERR(CAM_CPAS, "Invalid AHB vote, %pK", ahb_vote);
 		return -EINVAL;
 	}
 
@@ -750,12 +751,13 @@
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("client has not started %d\n", client_indx);
+		CAM_ERR(CAM_CPAS, "client has not started %d", client_indx);
 		rc = -EPERM;
 		goto unlock_client;
 	}
 
-	CPAS_CDBG("client[%d] : type[%d], level[%d], freq[%ld], applied[%d]\n",
+	CAM_DBG(CAM_CPAS,
+		"client[%d] : type[%d], level[%d], freq[%ld], applied[%d]",
 		client_indx, ahb_vote->type, ahb_vote->vote.level,
 		ahb_vote->vote.freq,
 		cpas_core->cpas_client[client_indx]->ahb_level);
@@ -782,12 +784,13 @@
 	int rc;
 
 	if (!hw_priv || !start_args) {
-		pr_err("Invalid arguments %pK %pK\n", hw_priv, start_args);
+		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
+			hw_priv, start_args);
 		return -EINVAL;
 	}
 
 	if (sizeof(struct cam_cpas_hw_cmd_start) != arg_size) {
-		pr_err("HW_CAPS size mismatch %ld %d\n",
+		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
 			sizeof(struct cam_cpas_hw_cmd_start), arg_size);
 		return -EINVAL;
 	}
@@ -804,7 +807,7 @@
 
 	if ((ahb_vote->vote.level == 0) || ((axi_vote->compressed_bw == 0) &&
 		(axi_vote->uncompressed_bw == 0))) {
-		pr_err("Invalid vote ahb[%d], axi[%llu], [%llu]\n",
+		CAM_ERR(CAM_CPAS, "Invalid vote ahb[%d], axi[%llu], [%llu]",
 			ahb_vote->vote.level, axi_vote->compressed_bw,
 			axi_vote->uncompressed_bw);
 		return -EINVAL;
@@ -817,20 +820,20 @@
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
-		pr_err("client is not registered %d\n", client_indx);
+		CAM_ERR(CAM_CPAS, "client is not registered %d", client_indx);
 		rc = -EPERM;
 		goto done;
 	}
 
 	if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("Client %d is in start state\n", client_indx);
+		CAM_ERR(CAM_CPAS, "Client %d is in start state", client_indx);
 		rc = -EPERM;
 		goto done;
 	}
 
 	cpas_client = cpas_core->cpas_client[client_indx];
 
-	CPAS_CDBG("AHB :client[%d] type[%d], level[%d], applied[%d]\n",
+	CAM_DBG(CAM_CPAS, "AHB :client[%d] type[%d], level[%d], applied[%d]",
 		client_indx, ahb_vote->type, ahb_vote->vote.level,
 		cpas_client->ahb_level);
 	rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client,
@@ -838,7 +841,8 @@
 	if (rc)
 		goto done;
 
-	CPAS_CDBG("AXI client[%d] compressed_bw[%llu], uncompressed_bw[%llu]\n",
+	CAM_DBG(CAM_CPAS,
+		"AXI client[%d] compressed_bw[%llu], uncompressed_bw[%llu]",
 		client_indx, axi_vote->compressed_bw,
 		axi_vote->uncompressed_bw);
 	rc = cam_cpas_util_apply_client_axi_vote(cpas_core,
@@ -850,7 +854,7 @@
 		rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info,
 			applied_level);
 		if (rc) {
-			pr_err("enable_resorce failed, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc);
 			goto done;
 		}
 
@@ -859,7 +863,8 @@
 			if (rc) {
 				cam_cpas_soc_disable_resources(
 					&cpas_hw->soc_info);
-				pr_err("failed in power_on settings rc=%d\n",
+				CAM_ERR(CAM_CPAS,
+					"failed in power_on settings rc=%d",
 					rc);
 				goto done;
 			}
@@ -870,7 +875,7 @@
 	cpas_client->started = true;
 	cpas_core->streamon_clients++;
 
-	CPAS_CDBG("client_indx=%d, streamon_clients=%d\n",
+	CAM_DBG(CAM_CPAS, "client_indx=%d, streamon_clients=%d",
 		client_indx, cpas_core->streamon_clients);
 done:
 	mutex_unlock(&cpas_core->client_mutex[client_indx]);
@@ -892,12 +897,13 @@
 	int rc = 0;
 
 	if (!hw_priv || !stop_args) {
-		pr_err("Invalid arguments %pK %pK\n", hw_priv, stop_args);
+		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
+			hw_priv, stop_args);
 		return -EINVAL;
 	}
 
 	if (sizeof(struct cam_cpas_hw_cmd_stop) != arg_size) {
-		pr_err("HW_CAPS size mismatch %ld %d\n",
+		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
 			sizeof(struct cam_cpas_hw_cmd_stop), arg_size);
 		return -EINVAL;
 	}
@@ -913,11 +919,11 @@
 	mutex_lock(&cpas_hw->hw_mutex);
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
-	CPAS_CDBG("client_indx=%d, streamon_clients=%d\n",
+	CAM_DBG(CAM_CPAS, "client_indx=%d, streamon_clients=%d",
 		client_indx, cpas_core->streamon_clients);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("Client %d is not started\n", client_indx);
+		CAM_ERR(CAM_CPAS, "Client %d is not started", client_indx);
 		rc = -EPERM;
 		goto done;
 	}
@@ -930,7 +936,8 @@
 		if (cpas_core->internal_ops.power_off) {
 			rc = cpas_core->internal_ops.power_off(cpas_hw);
 			if (rc) {
-				pr_err("failed in power_off settings rc=%d\n",
+				CAM_ERR(CAM_CPAS,
+					"failed in power_off settings rc=%d",
 					rc);
 				/* Do not return error, passthrough */
 			}
@@ -938,7 +945,7 @@
 
 		rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
 		if (rc) {
-			pr_err("disable_resorce failed, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc);
 			goto done;
 		}
 		cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
@@ -970,12 +977,13 @@
 	int rc = 0;
 
 	if (!hw_priv || !init_hw_args) {
-		pr_err("Invalid arguments %pK %pK\n", hw_priv, init_hw_args);
+		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
+			hw_priv, init_hw_args);
 		return -EINVAL;
 	}
 
 	if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
-		pr_err("INIT HW size mismatch %ld %d\n",
+		CAM_ERR(CAM_CPAS, "INIT HW size mismatch %ld %d",
 			sizeof(struct cam_cpas_hw_caps), arg_size);
 		return -EINVAL;
 	}
@@ -1002,7 +1010,7 @@
 	struct cam_cpas_private_soc *soc_private =
 		(struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
 
-	CPAS_CDBG("Register params : identifier=%s, cell_index=%d\n",
+	CAM_DBG(CAM_CPAS, "Register params : identifier=%s, cell_index=%d",
 		register_params->identifier, register_params->cell_index);
 
 	if (soc_private->client_id_based)
@@ -1015,11 +1023,11 @@
 
 	mutex_lock(&cpas_hw->hw_mutex);
 
-	rc = cam_cpas_util_get_string_index(soc_private->client_name,
+	rc = cam_common_util_get_string_index(soc_private->client_name,
 		soc_private->num_clients, client_name, &client_indx);
 	if (rc || !CAM_CPAS_CLIENT_VALID(client_indx) ||
 		CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
-		pr_err("Invalid Client register : %s %d, %d\n",
+		CAM_ERR(CAM_CPAS, "Invalid Client register : %s %d, %d",
 			register_params->identifier,
 			register_params->cell_index, client_indx);
 		mutex_unlock(&cpas_hw->hw_mutex);
@@ -1035,7 +1043,8 @@
 	rc = cam_cpas_util_insert_client_to_axi_port(cpas_core, soc_private,
 		cpas_client, client_indx);
 	if (rc) {
-		pr_err("axi_port_insert failed client_indx=%d, rc=%d\n",
+		CAM_ERR(CAM_CPAS,
+			"axi_port_insert failed client_indx=%d, rc=%d",
 			client_indx, rc);
 		kfree(cpas_client);
 		mutex_unlock(&cpas_hw->hw_mutex);
@@ -1051,7 +1060,7 @@
 
 	mutex_unlock(&cpas_hw->hw_mutex);
 
-	CPAS_CDBG("client_indx=%d, registered_clients=%d\n",
+	CAM_DBG(CAM_CPAS, "client_indx=%d, registered_clients=%d",
 		client_indx, cpas_core->registered_clients);
 
 	return 0;
@@ -1071,13 +1080,13 @@
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
-		pr_err("client not registered %d\n", client_indx);
+		CAM_ERR(CAM_CPAS, "client not registered %d", client_indx);
 		rc = -EPERM;
 		goto done;
 	}
 
 	if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
-		pr_err("Client %d is not stopped\n", client_indx);
+		CAM_ERR(CAM_CPAS, "Client %d is not stopped", client_indx);
 		rc = -EPERM;
 		goto done;
 	}
@@ -1085,7 +1094,7 @@
 	cam_cpas_util_remove_client_from_axi_port(
 		cpas_core->cpas_client[client_indx]);
 
-	CPAS_CDBG("client_indx=%d, registered_clients=%d\n",
+	CAM_DBG(CAM_CPAS, "client_indx=%d, registered_clients=%d",
 		client_indx, cpas_core->registered_clients);
 
 	kfree(cpas_core->cpas_client[client_indx]);
@@ -1105,12 +1114,13 @@
 	struct cam_cpas_hw_caps *hw_caps;
 
 	if (!hw_priv || !get_hw_cap_args) {
-		pr_err("Invalid arguments %pK %pK\n", hw_priv, get_hw_cap_args);
+		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
+			hw_priv, get_hw_cap_args);
 		return -EINVAL;
 	}
 
 	if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
-		pr_err("HW_CAPS size mismatch %ld %d\n",
+		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
 			sizeof(struct cam_cpas_hw_caps), arg_size);
 		return -EINVAL;
 	}
@@ -1132,8 +1142,8 @@
 
 	if (!hw_priv || !cmd_args ||
 		(cmd_type >= CAM_CPAS_HW_CMD_INVALID)) {
-		pr_err("Invalid arguments %pK %pK %d\n", hw_priv, cmd_args,
-			cmd_type);
+		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK %d",
+			hw_priv, cmd_args, cmd_type);
 		return -EINVAL;
 	}
 
@@ -1142,7 +1152,7 @@
 		struct cam_cpas_register_params *register_params;
 
 		if (sizeof(struct cam_cpas_register_params) != arg_size) {
-			pr_err("cmd_type %d, size mismatch %d\n",
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
 				cmd_type, arg_size);
 			break;
 		}
@@ -1155,7 +1165,7 @@
 		uint32_t *client_handle;
 
 		if (sizeof(uint32_t) != arg_size) {
-			pr_err("cmd_type %d, size mismatch %d\n",
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
 				cmd_type, arg_size);
 			break;
 		}
@@ -1169,7 +1179,7 @@
 
 		if (sizeof(struct cam_cpas_hw_cmd_reg_read_write) !=
 			arg_size) {
-			pr_err("cmd_type %d, size mismatch %d\n",
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
 				cmd_type, arg_size);
 			break;
 		}
@@ -1186,7 +1196,7 @@
 
 		if (sizeof(struct cam_cpas_hw_cmd_reg_read_write) !=
 			arg_size) {
-			pr_err("cmd_type %d, size mismatch %d\n",
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
 				cmd_type, arg_size);
 			break;
 		}
@@ -1203,7 +1213,7 @@
 		struct cam_cpas_hw_cmd_ahb_vote *cmd_ahb_vote;
 
 		if (sizeof(struct cam_cpas_hw_cmd_ahb_vote) != arg_size) {
-			pr_err("cmd_type %d, size mismatch %d\n",
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
 				cmd_type, arg_size);
 			break;
 		}
@@ -1217,7 +1227,7 @@
 		struct cam_cpas_hw_cmd_axi_vote *cmd_axi_vote;
 
 		if (sizeof(struct cam_cpas_hw_cmd_axi_vote) != arg_size) {
-			pr_err("cmd_type %d, size mismatch %d\n",
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
 				cmd_type, arg_size);
 			break;
 		}
@@ -1228,7 +1238,7 @@
 		break;
 	}
 	default:
-		pr_err("CPAS HW command not valid =%d\n", cmd_type);
+		CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type);
 		break;
 	}
 
@@ -1274,7 +1284,7 @@
 	rc = of_property_read_string_index(of_node, "arch-compat", 0,
 		(const char **)&compat_str);
 	if (rc) {
-		pr_err("failed to get arch-compat rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed to get arch-compat rc=%d", rc);
 		return -EINVAL;
 	}
 
@@ -1285,7 +1295,7 @@
 		hw_intf->hw_type = CAM_HW_CPASTOP;
 		rc = cam_cpastop_get_internal_ops(internal_ops);
 	} else {
-		pr_err("arch-compat %s not supported\n", compat_str);
+		CAM_ERR(CAM_CPAS, "arch-compat %s not supported", compat_str);
 		rc = -EINVAL;
 	}
 
@@ -1375,7 +1385,7 @@
 
 	rc = cam_cpas_util_client_setup(cpas_hw);
 	if (rc) {
-		pr_err("failed in client setup, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in client setup, rc=%d", rc);
 		goto deinit_platform_res;
 	}
 
@@ -1383,13 +1393,13 @@
 		cpas_hw->soc_info.pdev->dev.of_node,
 		&cpas_core->ahb_bus_client);
 	if (rc) {
-		pr_err("failed in ahb setup, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in ahb setup, rc=%d", rc);
 		goto client_cleanup;
 	}
 
 	rc = cam_cpas_util_axi_setup(cpas_core, &cpas_hw->soc_info);
 	if (rc) {
-		pr_err("failed in axi setup, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in axi setup, rc=%d", rc);
 		goto ahb_cleanup;
 	}
 
@@ -1400,18 +1410,18 @@
 
 	rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, CAM_SVS_VOTE);
 	if (rc) {
-		pr_err("failed in soc_enable_resources, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in soc_enable_resources, rc=%d", rc);
 		goto remove_default_vote;
 	}
 
 	if (internal_ops->get_hw_info) {
 		rc = internal_ops->get_hw_info(cpas_hw, &cpas_core->hw_caps);
 		if (rc) {
-			pr_err("failed in get_hw_info, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "failed in get_hw_info, rc=%d", rc);
 			goto disable_soc_res;
 		}
 	} else {
-		pr_err("Invalid get_hw_info\n");
+		CAM_ERR(CAM_CPAS, "Invalid get_hw_info");
 		goto disable_soc_res;
 	}
 
@@ -1422,7 +1432,7 @@
 
 	rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
 	if (rc) {
-		pr_err("failed in soc_disable_resources, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
 		goto remove_default_vote;
 	}
 
@@ -1453,7 +1463,7 @@
 	kfree(cpas_core);
 	kfree(cpas_hw);
 	kfree(cpas_hw_intf);
-	pr_err("failed in hw probe\n");
+	CAM_ERR(CAM_CPAS, "failed in hw probe");
 	return rc;
 }
 
@@ -1463,7 +1473,7 @@
 	struct cam_cpas *cpas_core;
 
 	if (!cpas_hw_intf) {
-		pr_err("cpas interface not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas interface not initialized");
 		return -EINVAL;
 	}
 
@@ -1471,7 +1481,7 @@
 	cpas_core = (struct cam_cpas *)cpas_hw->core_info;
 
 	if (cpas_hw->hw_state == CAM_HW_STATE_POWER_UP) {
-		pr_err("cpas hw is in power up state\n");
+		CAM_ERR(CAM_CPAS, "cpas hw is in power up state");
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
index 6d4fafe..bbc99b7 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
@@ -15,6 +15,7 @@
 
 #include "cam_cpas_api.h"
 #include "cam_cpas_hw_intf.h"
+#include "cam_common_util.h"
 
 #define CPAS_MAX_CLIENTS 20
 #define CAM_CPAS_INFLIGHT_WORKS 5
@@ -192,7 +193,5 @@
 
 int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
 	enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info);
-int cam_cpas_util_get_string_index(const char **strings,
-	uint32_t num_strings, char *matching_string, uint32_t *index);
 
 #endif /* _CAM_CPAS_HW_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw_intf.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw_intf.h
index 9ee5a43..fa4018e 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw_intf.h
@@ -18,16 +18,7 @@
 #include "cam_cpas_api.h"
 #include "cam_hw.h"
 #include "cam_hw_intf.h"
-
-#ifdef CONFIG_CAM_CPAS_DBG
-#define CPAS_CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CPAS_CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-#undef pr_fmt
-#define pr_fmt(fmt) "CAM-CPAS %s:%d " fmt, __func__, __LINE__
-
-#define BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift)
+#include "cam_debug_util.h"
 
 /* Number of times to retry while polling */
 #define CAM_CPAS_POLL_RETRY_CNT 5
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
index aba0caa..3846784 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
@@ -55,12 +55,12 @@
 	struct cam_hw_version *cpas_version)
 {
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
 	if (!camera_family || !camera_version || !cpas_version) {
-		pr_err("invalid input %pK %pK %pK\n", camera_family,
+		CAM_ERR(CAM_CPAS, "invalid input %pK %pK %pK", camera_family,
 			camera_version, cpas_version);
 		return -EINVAL;
 	}
@@ -80,7 +80,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -98,9 +98,9 @@
 			CAM_CPAS_HW_CMD_REG_WRITE, &cmd_reg_write,
 			sizeof(struct cam_cpas_hw_cmd_reg_read_write));
 		if (rc)
-			pr_err("Failed in process_cmd, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
 	} else {
-		pr_err("Invalid process_cmd ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
 		rc = -EINVAL;
 	}
 
@@ -115,12 +115,12 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
 	if (!value) {
-		pr_err("Invalid arg value\n");
+		CAM_ERR(CAM_CPAS, "Invalid arg value");
 		return -EINVAL;
 	}
 
@@ -138,13 +138,13 @@
 			CAM_CPAS_HW_CMD_REG_READ, &cmd_reg_read,
 			sizeof(struct cam_cpas_hw_cmd_reg_read_write));
 		if (rc) {
-			pr_err("Failed in process_cmd, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
 			return rc;
 		}
 
 		*value = cmd_reg_read.value;
 	} else {
-		pr_err("Invalid process_cmd ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
 		rc = -EINVAL;
 	}
 
@@ -158,7 +158,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -173,9 +173,9 @@
 			CAM_CPAS_HW_CMD_AXI_VOTE, &cmd_axi_vote,
 			sizeof(struct cam_cpas_hw_cmd_axi_vote));
 		if (rc)
-			pr_err("Failed in process_cmd, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
 	} else {
-		pr_err("Invalid process_cmd ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
 		rc = -EINVAL;
 	}
 
@@ -189,7 +189,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -204,9 +204,9 @@
 			CAM_CPAS_HW_CMD_AHB_VOTE, &cmd_ahb_vote,
 			sizeof(struct cam_cpas_hw_cmd_ahb_vote));
 		if (rc)
-			pr_err("Failed in process_cmd, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
 	} else {
-		pr_err("Invalid process_cmd ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
 		rc = -EINVAL;
 	}
 
@@ -219,7 +219,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -232,9 +232,9 @@
 			g_cpas_intf->hw_intf->hw_priv, &cmd_hw_stop,
 			sizeof(struct cam_cpas_hw_cmd_stop));
 		if (rc)
-			pr_err("Failed in stop, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in stop, rc=%d", rc);
 	} else {
-		pr_err("Invalid stop ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid stop ops");
 		rc = -EINVAL;
 	}
 
@@ -248,7 +248,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -263,9 +263,9 @@
 			g_cpas_intf->hw_intf->hw_priv, &cmd_hw_start,
 			sizeof(struct cam_cpas_hw_cmd_start));
 		if (rc)
-			pr_err("Failed in start, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in start, rc=%d", rc);
 	} else {
-		pr_err("Invalid start ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid start ops");
 		rc = -EINVAL;
 	}
 
@@ -278,7 +278,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -288,9 +288,9 @@
 			CAM_CPAS_HW_CMD_UNREGISTER_CLIENT,
 			&client_handle, sizeof(uint32_t));
 		if (rc)
-			pr_err("Failed in process_cmd, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
 	} else {
-		pr_err("Invalid process_cmd ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
 		rc = -EINVAL;
 	}
 
@@ -304,7 +304,7 @@
 	int rc;
 
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
@@ -314,9 +314,9 @@
 			CAM_CPAS_HW_CMD_REGISTER_CLIENT, register_params,
 			sizeof(struct cam_cpas_register_params));
 		if (rc)
-			pr_err("Failed in process_cmd, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
 	} else {
-		pr_err("Invalid process_cmd ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
 		rc = -EINVAL;
 	}
 
@@ -330,7 +330,7 @@
 	int rc = 0;
 
 	if (!cmd) {
-		pr_err("Invalid input cmd\n");
+		CAM_ERR(CAM_CPAS, "Invalid input cmd");
 		return -EINVAL;
 	}
 
@@ -341,7 +341,8 @@
 		rc = copy_from_user(&query, (void __user *) cmd->handle,
 			sizeof(query));
 		if (rc) {
-			pr_err("Failed in copy from user, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
+				rc);
 			break;
 		}
 
@@ -353,14 +354,14 @@
 		rc = copy_to_user((void __user *) cmd->handle, &query,
 			sizeof(query));
 		if (rc)
-			pr_err("Failed in copy to user, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc);
 
 		break;
 	}
 	case CAM_SD_SHUTDOWN:
 		break;
 	default:
-		pr_err("Unknown op code %d for CPAS\n", cmd->op_code);
+		CAM_ERR(CAM_CPAS, "Unknown op code %d for CPAS", cmd->op_code);
 		rc = -EINVAL;
 		break;
 	}
@@ -374,13 +375,13 @@
 	struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
 
 	if (!cpas_intf || !cpas_intf->probe_done) {
-		pr_err("CPAS not initialized\n");
+		CAM_ERR(CAM_CPAS, "CPAS not initialized");
 		return -ENODEV;
 	}
 
 	mutex_lock(&cpas_intf->intf_lock);
 	cpas_intf->open_cnt++;
-	CPAS_CDBG("CPAS Subdev open count %d\n", cpas_intf->open_cnt);
+	CAM_DBG(CAM_CPAS, "CPAS Subdev open count %d", cpas_intf->open_cnt);
 	mutex_unlock(&cpas_intf->intf_lock);
 
 	return 0;
@@ -392,13 +393,13 @@
 	struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
 
 	if (!cpas_intf || !cpas_intf->probe_done) {
-		pr_err("CPAS not initialized\n");
+		CAM_ERR(CAM_CPAS, "CPAS not initialized");
 		return -ENODEV;
 	}
 
 	mutex_lock(&cpas_intf->intf_lock);
 	cpas_intf->open_cnt--;
-	CPAS_CDBG("CPAS Subdev close count %d\n", cpas_intf->open_cnt);
+	CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt);
 	mutex_unlock(&cpas_intf->intf_lock);
 
 	return 0;
@@ -411,7 +412,7 @@
 	struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
 
 	if (!cpas_intf || !cpas_intf->probe_done) {
-		pr_err("CPAS not initialized\n");
+		CAM_ERR(CAM_CPAS, "CPAS not initialized");
 		return -ENODEV;
 	}
 
@@ -420,7 +421,7 @@
 		rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg);
 		break;
 	default:
-		pr_err("Invalid command %d for CPAS!\n", cmd);
+		CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd);
 		rc = -EINVAL;
 		break;
 	}
@@ -437,13 +438,13 @@
 	struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
 
 	if (!cpas_intf || !cpas_intf->probe_done) {
-		pr_err("CPAS not initialized\n");
+		CAM_ERR(CAM_CPAS, "CPAS not initialized");
 		return -ENODEV;
 	}
 
 	if (copy_from_user(&cmd_data, (void __user *)arg,
 		sizeof(cmd_data))) {
-		pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+		CAM_ERR(CAM_CPAS, "Failed to copy from user_ptr=%pK size=%zu",
 			(void __user *)arg, sizeof(cmd_data));
 		return -EFAULT;
 	}
@@ -453,7 +454,7 @@
 		rc = cam_cpas_subdev_cmd(cpas_intf, &cmd_data);
 		break;
 	default:
-		pr_err("Invalid command %d for CPAS!\n", cmd);
+		CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd);
 		rc = -EINVAL;
 		break;
 	}
@@ -461,7 +462,8 @@
 	if (!rc) {
 		if (copy_to_user((void __user *)arg, &cmd_data,
 			sizeof(cmd_data))) {
-			pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+			CAM_ERR(CAM_CPAS,
+				"Failed to copy to user_ptr=%pK size=%zu",
 				(void __user *)arg, sizeof(cmd_data));
 			rc = -EFAULT;
 		}
@@ -508,7 +510,8 @@
 
 	rc = cam_register_subdev(subdev);
 	if (rc) {
-		pr_err("failed register subdev: %s!\n", CAM_CPAS_DEV_NAME);
+		CAM_ERR(CAM_CPAS, "failed register subdev: %s!",
+			CAM_CPAS_DEV_NAME);
 		return rc;
 	}
 
@@ -523,7 +526,7 @@
 	int rc;
 
 	if (g_cpas_intf) {
-		pr_err("cpas dev proble already done\n");
+		CAM_ERR(CAM_CPAS, "cpas dev proble already done");
 		return -EALREADY;
 	}
 
@@ -536,7 +539,7 @@
 
 	rc = cam_cpas_hw_probe(pdev, &g_cpas_intf->hw_intf);
 	if (rc || (g_cpas_intf->hw_intf == NULL)) {
-		pr_err("Failed in hw probe, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "Failed in hw probe, rc=%d", rc);
 		goto error_destroy_mem;
 	}
 
@@ -546,11 +549,11 @@
 		rc = hw_intf->hw_ops.get_hw_caps(hw_intf->hw_priv,
 			hw_caps, sizeof(struct cam_cpas_hw_caps));
 		if (rc) {
-			pr_err("Failed in get_hw_caps, rc=%d\n", rc);
+			CAM_ERR(CAM_CPAS, "Failed in get_hw_caps, rc=%d", rc);
 			goto error_hw_remove;
 		}
 	} else {
-		pr_err("Invalid get_hw_caps ops\n");
+		CAM_ERR(CAM_CPAS, "Invalid get_hw_caps ops");
 		goto error_hw_remove;
 	}
 
@@ -559,7 +562,8 @@
 		goto error_hw_remove;
 
 	g_cpas_intf->probe_done = true;
-	CPAS_CDBG("CPAS INTF Probe success %d, %d.%d.%d, %d.%d.%d, 0x%x\n",
+	CAM_DBG(CAM_CPAS,
+		"CPAS INTF Probe success %d, %d.%d.%d, %d.%d.%d, 0x%x",
 		hw_caps->camera_family, hw_caps->camera_version.major,
 		hw_caps->camera_version.minor, hw_caps->camera_version.incr,
 		hw_caps->cpas_version.major, hw_caps->cpas_version.minor,
@@ -573,14 +577,14 @@
 	mutex_destroy(&g_cpas_intf->intf_lock);
 	kfree(g_cpas_intf);
 	g_cpas_intf = NULL;
-	pr_err("CPAS probe failed\n");
+	CAM_ERR(CAM_CPAS, "CPAS probe failed");
 	return rc;
 }
 
 static int cam_cpas_dev_remove(struct platform_device *dev)
 {
 	if (!CAM_CPAS_INTF_INITIALIZED()) {
-		pr_err("cpas intf not initialized\n");
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
 		return -ENODEV;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
index 09c2ae5..f85f461 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
@@ -29,7 +29,8 @@
 	int count = 0, i = 0, rc = 0;
 
 	if (!soc_private || !pdev) {
-		pr_err("invalid input arg %pK %pK\n", soc_private, pdev);
+		CAM_ERR(CAM_CPAS, "invalid input arg %pK %pK",
+			soc_private, pdev);
 		return -EINVAL;
 	}
 
@@ -38,7 +39,8 @@
 	rc = of_property_read_string_index(of_node, "arch-compat", 0,
 		(const char **)&soc_private->arch_compat);
 	if (rc) {
-		pr_err("device %s failed to read arch-compat\n", pdev->name);
+		CAM_ERR(CAM_CPAS, "device %s failed to read arch-compat",
+			pdev->name);
 		return rc;
 	}
 
@@ -47,12 +49,13 @@
 
 	count = of_property_count_strings(of_node, "client-names");
 	if (count <= 0) {
-		pr_err("no client-names found\n");
+		CAM_ERR(CAM_CPAS, "no client-names found");
 		count = 0;
 		return -EINVAL;
 	}
 	soc_private->num_clients = count;
-	CPAS_CDBG("arch-compat=%s, client_id_based = %d, num_clients=%d\n",
+	CAM_DBG(CAM_CPAS,
+		"arch-compat=%s, client_id_based = %d, num_clients=%d",
 		soc_private->arch_compat, soc_private->client_id_based,
 		soc_private->num_clients);
 
@@ -60,15 +63,16 @@
 		rc = of_property_read_string_index(of_node,
 			"client-names", i, &soc_private->client_name[i]);
 		if (rc) {
-			pr_err("no client-name at cnt=%d\n", i);
+			CAM_ERR(CAM_CPAS, "no client-name at cnt=%d", i);
 			return -ENODEV;
 		}
-		CPAS_CDBG("Client[%d] : %s\n", i, soc_private->client_name[i]);
+		CAM_DBG(CAM_CPAS, "Client[%d] : %s", i,
+			soc_private->client_name[i]);
 	}
 
 	count = of_property_count_strings(of_node, "client-axi-port-names");
 	if ((count <= 0) || (count != soc_private->num_clients)) {
-		pr_err("incorrect client-axi-port-names info %d %d\n",
+		CAM_ERR(CAM_CPAS, "incorrect client-axi-port-names info %d %d",
 			count, soc_private->num_clients);
 		count = 0;
 		return -EINVAL;
@@ -79,10 +83,10 @@
 			"client-axi-port-names", i,
 			&soc_private->client_axi_port_name[i]);
 		if (rc) {
-			pr_err("no client-name at cnt=%d\n", i);
+			CAM_ERR(CAM_CPAS, "no client-name at cnt=%d", i);
 			return -ENODEV;
 		}
-		CPAS_CDBG("Client AXI Port[%d] : %s\n", i,
+		CAM_DBG(CAM_CPAS, "Client AXI Port[%d] : %s", i,
 			soc_private->client_axi_port_name[i]);
 	}
 
@@ -99,25 +103,29 @@
 			rc = of_property_read_u32_index(of_node, "vdd-corners",
 				i, &soc_private->vdd_ahb[i].vdd_corner);
 			if (rc) {
-				pr_err("vdd-corners failed at index=%d\n", i);
+				CAM_ERR(CAM_CPAS,
+					"vdd-corners failed at index=%d", i);
 				return -ENODEV;
 			}
 
 			rc = of_property_read_string_index(of_node,
 				"vdd-corner-ahb-mapping", i, &ahb_string);
 			if (rc) {
-				pr_err("no ahb-mapping at index=%d\n", i);
+				CAM_ERR(CAM_CPAS,
+					"no ahb-mapping at index=%d", i);
 				return -ENODEV;
 			}
 
 			rc = cam_soc_util_get_level_from_string(ahb_string,
 				&soc_private->vdd_ahb[i].ahb_level);
 			if (rc) {
-				pr_err("invalid ahb-string at index=%d\n", i);
+				CAM_ERR(CAM_CPAS,
+					"invalid ahb-string at index=%d", i);
 				return -EINVAL;
 			}
 
-			CPAS_CDBG("Vdd-AHB mapping [%d] : [%d] [%s] [%d]\n", i,
+			CAM_DBG(CAM_CPAS,
+				"Vdd-AHB mapping [%d] : [%d] [%s] [%d]", i,
 				soc_private->vdd_ahb[i].vdd_corner,
 				ahb_string, soc_private->vdd_ahb[i].ahb_level);
 		}
@@ -135,19 +143,20 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc) {
-		pr_err("failed in get_dt_properties, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in get_dt_properties, rc=%d", rc);
 		return rc;
 	}
 
 	if (soc_info->irq_line && !irq_handler) {
-		pr_err("Invalid IRQ handler\n");
+		CAM_ERR(CAM_CPAS, "Invalid IRQ handler");
 		return -EINVAL;
 	}
 
 	rc = cam_soc_util_request_platform_resource(soc_info, irq_handler,
 		irq_data);
 	if (rc) {
-		pr_err("failed in request_platform_resource, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in request_platform_resource, rc=%d",
+			rc);
 		return rc;
 	}
 
@@ -160,7 +169,7 @@
 
 	rc = cam_cpas_get_custom_dt_info(soc_info->pdev, soc_info->soc_private);
 	if (rc) {
-		pr_err("failed in get_custom_info, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "failed in get_custom_info, rc=%d", rc);
 		goto free_soc_private;
 	}
 
@@ -179,7 +188,7 @@
 
 	rc = cam_soc_util_release_platform_resource(soc_info);
 	if (rc)
-		pr_err("release platform failed, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "release platform failed, rc=%d", rc);
 
 	kfree(soc_info->soc_private);
 	soc_info->soc_private = NULL;
@@ -195,7 +204,7 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		default_level, true);
 	if (rc)
-		pr_err("enable platform resource failed, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "enable platform resource failed, rc=%d", rc);
 
 	return rc;
 }
@@ -206,7 +215,7 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc)
-		pr_err("disable platform failed, rc=%d\n", rc);
+		CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc);
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_cpas/camss_top/cam_camsstop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/camss_top/cam_camsstop_hw.c
index 95e26c5..0669070 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/camss_top/cam_camsstop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/camss_top/cam_camsstop_hw.c
@@ -29,13 +29,13 @@
 
 	reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x0);
 	hw_caps->camera_version.major =
-		BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c);
 	hw_caps->camera_version.minor =
-		BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10);
 	hw_caps->camera_version.incr =
-		BITS_MASK_SHIFT(reg_value, 0xffff, 0x0);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0);
 
-	CPAS_CDBG("Family %d, version %d.%d.%d\n",
+	CAM_DBG(CAM_FD, "Family %d, version %d.%d.%d",
 		hw_caps->camera_family, hw_caps->camera_version.major,
 		hw_caps->camera_version.minor, hw_caps->camera_version.incr);
 
@@ -49,21 +49,22 @@
 	int rc;
 
 	if (num_reg_map > CAM_CPAS_REG_MAX) {
-		pr_err("invalid num_reg_map=%d\n", num_reg_map);
+		CAM_ERR(CAM_CPAS, "invalid num_reg_map=%d", num_reg_map);
 		return -EINVAL;
 	}
 
 	if (soc_info->num_mem_block > CAM_SOC_MAX_BLOCK) {
-		pr_err("invalid num_mem_block=%d\n", soc_info->num_mem_block);
+		CAM_ERR(CAM_CPAS, "invalid num_mem_block=%d",
+			soc_info->num_mem_block);
 		return -EINVAL;
 	}
 
-	rc = cam_cpas_util_get_string_index(soc_info->mem_block_name,
+	rc = cam_common_util_get_string_index(soc_info->mem_block_name,
 		soc_info->num_mem_block, "cam_camss", &index);
 	if ((rc == 0) && (index < num_reg_map)) {
 		regbase_index[CAM_CPAS_REG_CAMSS] = index;
 	} else {
-		pr_err("regbase not found for CAM_CPAS_REG_CAMSS\n");
+		CAM_ERR(CAM_CPAS, "regbase not found for CAM_CPAS_REG_CAMSS");
 		return -EINVAL;
 	}
 
@@ -73,7 +74,7 @@
 int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops)
 {
 	if (!internal_ops) {
-		pr_err("invalid NULL param\n");
+		CAM_ERR(CAM_CPAS, "invalid NULL param");
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index b901410..d9133b9 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -20,6 +20,7 @@
 #include "cam_io_util.h"
 #include "cam_cpas_soc.h"
 #include "cpastop100.h"
+#include "cpastop_v170_110.h"
 
 struct cam_camnoc_info *camnoc_info;
 
@@ -38,24 +39,24 @@
 
 	reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x0);
 	hw_caps->camera_version.major =
-		BITS_MASK_SHIFT(reg_value, 0xff0000, 0x10);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xff0000, 0x10);
 	hw_caps->camera_version.minor =
-		BITS_MASK_SHIFT(reg_value, 0xff00, 0x8);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xff00, 0x8);
 	hw_caps->camera_version.incr =
-		BITS_MASK_SHIFT(reg_value, 0xff, 0x0);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xff, 0x0);
 
 	reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x4);
 	hw_caps->cpas_version.major =
-		BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xf0000000, 0x1c);
 	hw_caps->cpas_version.minor =
-		BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xfff0000, 0x10);
 	hw_caps->cpas_version.incr =
-		BITS_MASK_SHIFT(reg_value, 0xffff, 0x0);
+		CAM_BITS_MASK_SHIFT(reg_value, 0xffff, 0x0);
 
 	reg_value = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + 0x8);
 	hw_caps->camera_capability = reg_value;
 
-	CPAS_CDBG("Family %d, version %d.%d.%d, cpas %d.%d.%d, cap 0x%x\n",
+	CAM_DBG(CAM_FD, "Family %d, version %d.%d.%d, cpas %d.%d.%d, cap 0x%x",
 		hw_caps->camera_family, hw_caps->camera_version.major,
 		hw_caps->camera_version.minor, hw_caps->camera_version.incr,
 		hw_caps->cpas_version.major, hw_caps->cpas_version.minor,
@@ -71,31 +72,32 @@
 	int rc;
 
 	if (num_reg_map > CAM_CPAS_REG_MAX) {
-		pr_err("invalid num_reg_map=%d\n", num_reg_map);
+		CAM_ERR(CAM_CPAS, "invalid num_reg_map=%d", num_reg_map);
 		return -EINVAL;
 	}
 
 	if (soc_info->num_mem_block > CAM_SOC_MAX_BLOCK) {
-		pr_err("invalid num_mem_block=%d\n", soc_info->num_mem_block);
+		CAM_ERR(CAM_CPAS, "invalid num_mem_block=%d",
+			soc_info->num_mem_block);
 		return -EINVAL;
 	}
 
-	rc = cam_cpas_util_get_string_index(soc_info->mem_block_name,
+	rc = cam_common_util_get_string_index(soc_info->mem_block_name,
 		soc_info->num_mem_block, "cam_cpas_top", &index);
 	if ((rc == 0) && (index < num_reg_map)) {
 		regbase_index[CAM_CPAS_REG_CPASTOP] = index;
 	} else {
-		pr_err("regbase not found for CPASTOP, rc=%d, %d %d\n",
+		CAM_ERR(CAM_CPAS, "regbase not found for CPASTOP, rc=%d, %d %d",
 			rc, index, num_reg_map);
 		return -EINVAL;
 	}
 
-	rc = cam_cpas_util_get_string_index(soc_info->mem_block_name,
+	rc = cam_common_util_get_string_index(soc_info->mem_block_name,
 		soc_info->num_mem_block, "cam_camnoc", &index);
 	if ((rc == 0) && (index < num_reg_map)) {
 		regbase_index[CAM_CPAS_REG_CAMNOC] = index;
 	} else {
-		pr_err("regbase not found for CAMNOC, rc=%d, %d %d\n",
+		CAM_ERR(CAM_CPAS, "regbase not found for CAMNOC, rc=%d, %d %d",
 			rc, index, num_reg_map);
 		return -EINVAL;
 	}
@@ -124,7 +126,8 @@
 		reg_value[3] = cam_io_r_mb(
 			soc_info->reg_map[camnoc_index].mem_base +
 			camnoc_info->error_logger[i + 3]);
-		pr_err("offset[0x%x] values [0x%x] [0x%x] [0x%x] [0x%x]\n",
+		CAM_ERR(CAM_CPAS,
+			"offset[0x%x] values [0x%x] [0x%x] [0x%x] [0x%x]",
 			camnoc_info->error_logger[i], reg_value[0],
 			reg_value[1], reg_value[2], reg_value[3]);
 	}
@@ -139,7 +142,7 @@
 		reg_value[2] = cam_io_r_mb(
 			soc_info->reg_map[camnoc_index].mem_base +
 			camnoc_info->error_logger[i + 2]);
-		pr_err("offset[0x%x] values [0x%x] [0x%x] [0x%x]\n",
+		CAM_ERR(CAM_CPAS, "offset[0x%x] values [0x%x] [0x%x] [0x%x]",
 			camnoc_info->error_logger[i], reg_value[0],
 			reg_value[1], reg_value[2]);
 		i = i + 3;
@@ -152,7 +155,7 @@
 		reg_value[1] = cam_io_r_mb(
 			soc_info->reg_map[camnoc_index].mem_base +
 			camnoc_info->error_logger[i + 1]);
-		pr_err("offset[0x%x] values [0x%x] [0x%x]\n",
+		CAM_ERR(CAM_CPAS, "offset[0x%x] values [0x%x] [0x%x]",
 			camnoc_info->error_logger[i], reg_value[0],
 			reg_value[1]);
 		i = i + 2;
@@ -162,7 +165,7 @@
 		reg_value[0] = cam_io_r_mb(
 			soc_info->reg_map[camnoc_index].mem_base +
 			camnoc_info->error_logger[i]);
-		pr_err("offset[0x%x] values [0x%x]\n",
+		CAM_ERR(CAM_CPAS, "offset[0x%x] values [0x%x]",
 			camnoc_info->error_logger[i], reg_value[0]);
 	}
 
@@ -178,7 +181,8 @@
 	reg_value = cam_io_r_mb(soc_info->reg_map[camnoc_index].mem_base +
 		camnoc_info->irq_err[i].err_status.offset);
 
-	pr_err("Dumping ubwc error status [%d]: offset[0x%x] value[0x%x]\n",
+	CAM_ERR(CAM_CPAS,
+		"Dumping ubwc error status [%d]: offset[0x%x] value[0x%x]",
 		i, camnoc_info->irq_err[i].err_status.offset, reg_value);
 
 	return reg_value;
@@ -186,7 +190,7 @@
 
 static int cam_cpastop_handle_ahb_timeout_err(struct cam_hw_info *cpas_hw)
 {
-	pr_err("ahb timout error\n");
+	CAM_ERR(CAM_CPAS, "ahb timout error");
 
 	return 0;
 }
@@ -229,7 +233,8 @@
 	int i;
 	struct cam_cpas_client *cpas_client;
 
-	CPAS_CDBG("Notify CB : num_clients=%d, registered=%d, started=%d\n",
+	CAM_DBG(CAM_CPAS,
+		"Notify CB : num_clients=%d, registered=%d, started=%d",
 		cpas_core->num_clients, cpas_core->registered_clients,
 		cpas_core->streamon_clients);
 
@@ -237,7 +242,8 @@
 		if (CAM_CPAS_CLIENT_STARTED(cpas_core, i)) {
 			cpas_client = cpas_core->cpas_client[i];
 			if (cpas_client->data.cam_cpas_client_cb) {
-				CPAS_CDBG("Calling client CB %d : %d 0x%x\n",
+				CAM_DBG(CAM_CPAS,
+					"Calling client CB %d : %d 0x%x",
 					i, irq_type, irq_data);
 				cpas_client->data.cam_cpas_client_cb(
 					cpas_client->data.client_handle,
@@ -261,7 +267,7 @@
 
 	payload = container_of(work, struct cam_cpas_work_payload, work);
 	if (!payload) {
-		pr_err("NULL payload");
+		CAM_ERR(CAM_CPAS, "NULL payload");
 		return;
 	}
 
@@ -273,7 +279,7 @@
 		if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) &&
 			(camnoc_info->irq_err[i].enable)) {
 			irq_type = camnoc_info->irq_err[i].irq_type;
-			pr_err("Error occurred, type=%d\n", irq_type);
+			CAM_ERR(CAM_CPAS, "Error occurred, type=%d", irq_type);
 			irq_data = 0;
 
 			switch (irq_type) {
@@ -293,10 +299,10 @@
 					cpas_hw);
 				break;
 			case CAM_CAMNOC_HW_IRQ_CAMNOC_TEST:
-				CPAS_CDBG("TEST IRQ\n");
+				CAM_DBG(CAM_CPAS, "TEST IRQ");
 				break;
 			default:
-				pr_err("Invalid IRQ type\n");
+				CAM_ERR(CAM_CPAS, "Invalid IRQ type");
 				break;
 			}
 
@@ -309,7 +315,7 @@
 	}
 
 	if (payload->irq_status)
-		pr_err("IRQ not handled irq_status=0x%x\n",
+		CAM_ERR(CAM_CPAS, "IRQ not handled irq_status=0x%x",
 			payload->irq_status);
 
 	kfree(payload);
@@ -331,7 +337,7 @@
 		soc_info->reg_map[camnoc_index].mem_base +
 		camnoc_info->irq_sbm->sbm_status.offset);
 
-	CPAS_CDBG("IRQ callback, irq_status=0x%x\n", payload->irq_status);
+	CAM_DBG(CAM_CPAS, "IRQ callback, irq_status=0x%x", payload->irq_status);
 
 	payload->hw = cpas_hw;
 	INIT_WORK((struct work_struct *)&payload->work, cam_cpastop_work);
@@ -396,7 +402,8 @@
 			CAM_CPAS_POLL_RETRY_CNT,
 			CAM_CPAS_POLL_MIN_USECS, CAM_CPAS_POLL_MAX_USECS);
 		if (rc) {
-			pr_err("camnoc flush slave pending trans failed\n");
+			CAM_ERR(CAM_CPAS,
+				"camnoc flush slave pending trans failed");
 			/* Do not return error, passthrough */
 		}
 	}
@@ -414,15 +421,19 @@
 			(hw_caps->cpas_version.minor == 0) &&
 			(hw_caps->cpas_version.incr == 0)) {
 			camnoc_info = &cam170_cpas100_camnoc_info;
+		} else if ((hw_caps->cpas_version.major == 1) &&
+			(hw_caps->cpas_version.minor == 1) &&
+			(hw_caps->cpas_version.incr == 0)) {
+			camnoc_info = &cam170_cpas110_camnoc_info;
 		} else {
-			pr_err("CPAS Version not supported %d.%d.%d\n",
+			CAM_ERR(CAM_CPAS, "CPAS Version not supported %d.%d.%d",
 				hw_caps->cpas_version.major,
 				hw_caps->cpas_version.minor,
 				hw_caps->cpas_version.incr);
 			return -EINVAL;
 		}
 	} else {
-		pr_err("Camera Version not supported %d.%d.%d\n",
+		CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d",
 			hw_caps->camera_version.major,
 			hw_caps->camera_version.minor,
 			hw_caps->camera_version.incr);
@@ -435,7 +446,7 @@
 int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops)
 {
 	if (!internal_ops) {
-		pr_err("invalid NULL param\n");
+		CAM_ERR(CAM_CPAS, "invalid NULL param");
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
new file mode 100644
index 0000000..f4d0e36
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
@@ -0,0 +1,542 @@
+/* Copyright (c) 2017, 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 _CPASTOP_V170_110_H_
+#define _CPASTOP_V170_110_H_
+
+#define TEST_IRQ_ENABLE 0
+
+static struct cam_camnoc_irq_sbm cam_cpas110_irq_sbm = {
+	.sbm_enable = {
+		.access_type = CAM_REG_TYPE_READ_WRITE,
+		.enable = true,
+		.offset = 0x2040, /* SBM_FAULTINEN0_LOW */
+		.value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/
+			0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+			0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */
+			0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */
+			0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */
+			0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */
+			(TEST_IRQ_ENABLE ?
+			0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */
+			0x0),
+	},
+	.sbm_status = {
+		.access_type = CAM_REG_TYPE_READ,
+		.enable = true,
+		.offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */
+	},
+	.sbm_clear = {
+		.access_type = CAM_REG_TYPE_WRITE,
+		.enable = true,
+		.offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */
+		.value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
+	}
+};
+
+static struct cam_camnoc_irq_err
+	cam_cpas110_irq_err[] = {
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
+		.enable = true,
+		.sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+			.value = 1,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+		},
+		.err_clear = {
+			.access_type = CAM_REG_TYPE_WRITE,
+			.enable = true,
+			.offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR,
+		.enable = true,
+		.sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0x5a0, /* SPECIFIC_IFE02_ENCERREN_LOW */
+			.value = 1,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0x590, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */
+		},
+		.err_clear = {
+			.access_type = CAM_REG_TYPE_WRITE,
+			.enable = true,
+			.offset = 0x598, /* SPECIFIC_IFE02_ENCERRCLR_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR,
+		.enable = true,
+		.sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0x9a0, /* SPECIFIC_IFE13_ENCERREN_LOW */
+			.value = 1,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0x990, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */
+		},
+		.err_clear = {
+			.access_type = CAM_REG_TYPE_WRITE,
+			.enable = true,
+			.offset = 0x998, /* SPECIFIC_IFE13_ENCERRCLR_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR,
+		.enable = true,
+		.sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0xd20, /* SPECIFIC_IBL_RD_DECERREN_LOW */
+			.value = 1,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0xd10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */
+		},
+		.err_clear = {
+			.access_type = CAM_REG_TYPE_WRITE,
+			.enable = true,
+			.offset = 0xd18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR,
+		.enable = true,
+		.sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0x11a0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */
+			.value = 1,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0x1190,
+			/* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */
+		},
+		.err_clear = {
+			.access_type = CAM_REG_TYPE_WRITE,
+			.enable = true,
+			.offset = 0x1198, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT,
+		.enable = true,
+		.sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+			.value = 0x1,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+		},
+		.err_clear = {
+			.enable = false,
+		},
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1,
+		.enable = false,
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2,
+		.enable = false,
+	},
+	{
+		.irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST,
+		.enable = TEST_IRQ_ENABLE ? true : false,
+		.sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */
+		.err_enable = {
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.enable = true,
+			.offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+			.value = 0x5,
+		},
+		.err_status = {
+			.access_type = CAM_REG_TYPE_READ,
+			.enable = true,
+			.offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+		},
+		.err_clear = {
+			.enable = false,
+		},
+	},
+};
+
+static struct cam_camnoc_specific
+	cam_cpas110_camnoc_specific[] = {
+	{
+		.port_type = CAM_CAMNOC_CDM,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */
+			.value = 0x22222222,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */
+			.value = 0x22222222,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 1,
+			.offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */
+			.mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
+			.shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
+			.value = 0,
+		},
+		.danger_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */
+			.value = 0x0,
+		},
+		.safe_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */
+			.value = 0x0,
+		},
+		.ubwc_ctl = {
+			.enable = false,
+		},
+	},
+	{
+		.port_type = CAM_CAMNOC_IFE02,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */
+			.value = 0x66665433,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */
+			.value = 0x66666666,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 1,
+			.offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */
+			/* SPECIFIC_IFE02_URGENCY_LOW_WRITE_MASK */
+			.mask = 0x70,
+			/* SPECIFIC_IFE02_URGENCY_LOW_WRITE_SHIFT */
+			.shift = 0x4,
+			.value = 3,
+		},
+		.danger_lut = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */
+			.value = 0xFFFFFF00,
+		},
+		.safe_lut = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */
+			.value = 0x3,
+		},
+		.ubwc_ctl = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.port_type = CAM_CAMNOC_IFE13,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */
+			.value = 0x66665433,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */
+			.value = 0x66666666,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 1,
+			.offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */
+			/* SPECIFIC_IFE13_URGENCY_LOW_WRITE_MASK */
+			.mask = 0x70,
+			/* SPECIFIC_IFE13_URGENCY_LOW_WRITE_SHIFT */
+			.shift = 0x4,
+			.value = 3,
+		},
+		.danger_lut = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */
+			.value = 0xFFFFFF00,
+		},
+		.safe_lut = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */
+			.value = 0x3,
+		},
+		.ubwc_ctl = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.port_type = CAM_CAMNOC_IPE_BPS_LRME_READ,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */
+			.value = 0x33333333,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */
+			.value = 0x33333333,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 1,
+			.offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */
+			/* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */
+			.mask = 0x7,
+			/* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */
+			.shift = 0x0,
+			.value = 3,
+		},
+		.danger_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */
+			.value = 0x0,
+		},
+		.safe_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */
+			.value = 0x0,
+		},
+		.ubwc_ctl = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */
+			.value = 0x33333333,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */
+			.value = 0x33333333,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 1,
+			.offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+			/* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
+			.mask = 0x70,
+			/* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
+			.shift = 0x4,
+			.value = 3,
+		},
+		.danger_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */
+			.value = 0x0,
+		},
+		.safe_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */
+			.value = 0x0,
+		},
+		.ubwc_ctl = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+			.value = 1,
+		},
+	},
+	{
+		.port_type = CAM_CAMNOC_JPEG,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */
+			.value = 0x22222222,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */
+			.value = 0x22222222,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */
+			.value = 0x22,
+		},
+		.danger_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */
+			.value = 0x0,
+		},
+		.safe_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */
+			.value = 0x0,
+		},
+		.ubwc_ctl = {
+			.enable = false,
+		},
+	},
+	{
+		.port_type = CAM_CAMNOC_FD,
+		.enable = false,
+	},
+	{
+		.port_type = CAM_CAMNOC_ICP,
+		.enable = false,
+	}
+};
+
+static uint32_t cam_cpas110_slave_error_logger[] = {
+	0x2700, /* ERRLOGGER_SWID_LOW */
+	0x2704, /* ERRLOGGER_SWID_HIGH */
+	0x2708, /* ERRLOGGER_MAINCTL_LOW */
+	0x2710, /* ERRLOGGER_ERRVLD_LOW */
+	0x2720, /* ERRLOGGER_ERRLOG0_LOW */
+	0x2724, /* ERRLOGGER_ERRLOG0_HIGH */
+	0x2728, /* ERRLOGGER_ERRLOG1_LOW */
+	0x272c, /* ERRLOGGER_ERRLOG1_HIGH */
+	0x2730, /* ERRLOGGER_ERRLOG2_LOW */
+	0x2734, /* ERRLOGGER_ERRLOG2_HIGH */
+	0x2738, /* ERRLOGGER_ERRLOG3_LOW */
+	0x273c, /* ERRLOGGER_ERRLOG3_HIGH */
+};
+
+static struct cam_cpas_hw_errata_wa_list cam170_cpas110_errata_wa_list = {
+	.camnoc_flush_slave_pending_trans = {
+		.enable = true,
+		.data.reg_info = {
+			.access_type = CAM_REG_TYPE_READ,
+			.offset = 0x2100, /* SidebandManager_SenseIn0_Low */
+			.mask = 0xE0000, /* Bits 17, 18, 19 */
+			.value = 0, /* expected to be 0 */
+		},
+	},
+};
+
+static struct cam_camnoc_info cam170_cpas110_camnoc_info = {
+	.specific = &cam_cpas110_camnoc_specific[0],
+	.specific_size = sizeof(cam_cpas110_camnoc_specific) /
+		sizeof(cam_cpas110_camnoc_specific[0]),
+	.irq_sbm = &cam_cpas110_irq_sbm,
+	.irq_err = &cam_cpas110_irq_err[0],
+	.irq_err_size = sizeof(cam_cpas110_irq_err) /
+		sizeof(cam_cpas110_irq_err[0]),
+	.error_logger = &cam_cpas110_slave_error_logger[0],
+	.error_logger_size = sizeof(cam_cpas110_slave_error_logger) /
+		sizeof(cam_cpas110_slave_error_logger[0]),
+	.errata_wa_list = &cam170_cpas110_errata_wa_list,
+};
+
+#endif /* _CPASTOP_V170_110_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h b/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h
index 801d09d..3977b68 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h
@@ -94,7 +94,7 @@
 	struct device  *dev;
 	void           *userdata;
 	void          (*cam_cpas_client_cb)(
-			int32_t                   client_handle,
+			uint32_t                  client_handle,
 			void                     *userdata,
 			enum cam_camnoc_irq_type  event_type,
 			uint32_t                  event_data);
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
index 776847d..15bd98c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-ICP-CTXT %s:%d " fmt, __func__, __LINE__
-
 #include <linux/debugfs.h>
 #include <linux/videodev2.h>
 #include <linux/slab.h>
@@ -26,6 +24,7 @@
 #include "cam_req_mgr_util.h"
 #include "cam_mem_mgr.h"
 #include "cam_trace.h"
+#include "cam_debug_util.h"
 
 static int __cam_icp_acquire_dev_in_available(struct cam_context *ctx,
 	struct cam_acquire_dev_cmd *cmd)
@@ -48,7 +47,7 @@
 
 	rc = cam_context_release_dev_to_hw(ctx, cmd);
 	if (rc)
-		pr_err("Unable to release device\n");
+		CAM_ERR(CAM_ICP, "Unable to release device");
 
 	ctx->state = CAM_CTX_AVAILABLE;
 	trace_cam_context_state("ICP", ctx);
@@ -76,7 +75,7 @@
 
 	rc = cam_context_prepare_dev_to_hw(ctx, cmd);
 	if (rc)
-		pr_err("Unable to prepare device\n");
+		CAM_ERR(CAM_ICP, "Failed to prepare device");
 
 	return rc;
 }
@@ -88,7 +87,7 @@
 
 	rc = cam_context_stop_dev_to_hw(ctx);
 	if (rc)
-		pr_err("Unable to stop device\n");
+		CAM_ERR(CAM_ICP, "Failed to stop device");
 
 	ctx->state = CAM_CTX_ACQUIRED;
 	trace_cam_context_state("ICP", ctx);
@@ -102,11 +101,11 @@
 
 	rc = __cam_icp_stop_dev_in_ready(ctx, NULL);
 	if (rc)
-		pr_err("Unable to stop device\n");
+		CAM_ERR(CAM_ICP, "Failed to stop device");
 
 	rc = __cam_icp_release_dev_in_acquired(ctx, cmd);
 	if (rc)
-		pr_err("Unable to stop device\n");
+		CAM_ERR(CAM_ICP, "Failed to release device");
 
 	return rc;
 }
@@ -167,7 +166,7 @@
 	int rc;
 
 	if ((!ctx) || (!ctx->base) || (!hw_intf)) {
-		pr_err("Invalid params: %pK %pK\n", ctx, hw_intf);
+		CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", ctx, hw_intf);
 		rc = -EINVAL;
 		goto err;
 	}
@@ -175,7 +174,7 @@
 	rc = cam_context_init(ctx->base, NULL, hw_intf, ctx->req_base,
 		CAM_CTX_REQ_MAX);
 	if (rc) {
-		pr_err("Camera Context Base init failed!\n");
+		CAM_ERR(CAM_ICP, "Camera Context Base init failed");
 		goto err;
 	}
 
@@ -190,7 +189,7 @@
 int cam_icp_context_deinit(struct cam_icp_context *ctx)
 {
 	if ((!ctx) || (!ctx->base)) {
-		pr_err("Invalid params: %pK\n", ctx);
+		CAM_ERR(CAM_ICP, "Invalid params: %pK", ctx);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
index 69c2e03..bbdff27 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-ICP %s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -36,6 +34,7 @@
 #include "cam_icp_context.h"
 #include "cam_hw_mgr_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
+#include "cam_debug_util.h"
 
 #define CAM_ICP_DEV_NAME        "cam-icp"
 
@@ -65,13 +64,13 @@
 
 	mutex_lock(&g_icp_dev.icp_lock);
 	if (g_icp_dev.open_cnt >= 1) {
-		pr_err("ICP subdev is already opened\n");
+		CAM_ERR(CAM_ICP, "ICP subdev is already opened");
 		rc = -EALREADY;
 		goto end;
 	}
 
 	if (!node) {
-		pr_err("Invalid args\n");
+		CAM_ERR(CAM_ICP, "Invalid args");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -79,7 +78,7 @@
 	hw_mgr_intf = &node->hw_mgr_intf;
 	rc = hw_mgr_intf->download_fw(hw_mgr_intf->hw_mgr_priv, NULL);
 	if (rc < 0) {
-		pr_err("FW download failed\n");
+		CAM_ERR(CAM_ICP, "FW download failed");
 		goto end;
 	}
 	g_icp_dev.open_cnt++;
@@ -97,27 +96,27 @@
 
 	mutex_lock(&g_icp_dev.icp_lock);
 	if (g_icp_dev.open_cnt <= 0) {
-		pr_err("ICP subdev is already closed\n");
+		CAM_ERR(CAM_ICP, "ICP subdev is already closed");
 		rc = -EINVAL;
 		goto end;
 	}
 	g_icp_dev.open_cnt--;
 	if (!node) {
-		pr_err("Invalid args\n");
+		CAM_ERR(CAM_ICP, "Invalid args");
 		rc = -EINVAL;
 		goto end;
 	}
 
 	hw_mgr_intf = &node->hw_mgr_intf;
 	if (!hw_mgr_intf) {
-		pr_err("hw_mgr_intf is not initialized\n");
+		CAM_ERR(CAM_ICP, "hw_mgr_intf is not initialized");
 		rc = -EINVAL;
 		goto end;
 	}
 
 	rc = hw_mgr_intf->hw_close(hw_mgr_intf->hw_mgr_priv, NULL);
 	if (rc < 0) {
-		pr_err("HW close failed\n");
+		CAM_ERR(CAM_ICP, "HW close failed");
 		goto end;
 	}
 
@@ -138,7 +137,7 @@
 	struct cam_hw_mgr_intf *hw_mgr_intf;
 
 	if (!pdev) {
-		pr_err("pdev is NULL\n");
+		CAM_ERR(CAM_ICP, "pdev is NULL");
 		return -EINVAL;
 	}
 
@@ -147,7 +146,7 @@
 	rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME,
 		CAM_ICP_DEVICE_TYPE);
 	if (rc) {
-		pr_err("ICP cam_subdev_probe failed!\n");
+		CAM_ERR(CAM_ICP, "ICP cam_subdev_probe failed");
 		goto probe_fail;
 	}
 
@@ -161,26 +160,24 @@
 
 	rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf);
 	if (rc) {
-		pr_err("ICP HW manager init failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "ICP HW manager init failed: %d", rc);
 		goto hw_init_fail;
 	}
 
-	pr_debug("Initializing the ICP contexts\n");
 	for (i = 0; i < CAM_CTX_MAX; i++) {
 		g_icp_dev.ctx_icp[i].base = &g_icp_dev.ctx[i];
 		rc = cam_icp_context_init(&g_icp_dev.ctx_icp[i],
 					hw_mgr_intf);
 		if (rc) {
-			pr_err("ICP context init failed!\n");
+			CAM_ERR(CAM_ICP, "ICP context init failed");
 			goto ctx_fail;
 		}
 	}
 
-	pr_debug("Initializing the ICP Node\n");
 	rc = cam_node_init(node, hw_mgr_intf, g_icp_dev.ctx,
 				CAM_CTX_MAX, CAM_ICP_DEV_NAME);
 	if (rc) {
-		pr_err("ICP node init failed!\n");
+		CAM_ERR(CAM_ICP, "ICP node init failed");
 		goto ctx_fail;
 	}
 
@@ -207,20 +204,20 @@
 	struct cam_subdev *subdev;
 
 	if (!pdev) {
-		pr_err("pdev is NULL\n");
-		return -EINVAL;
+		CAM_ERR(CAM_ICP, "pdev is NULL");
+		return -ENODEV;
 	}
 
 	sd = platform_get_drvdata(pdev);
 	if (!sd) {
-		pr_err("V4l2 subdev is NULL\n");
-		return -EINVAL;
+		CAM_ERR(CAM_ICP, "V4l2 subdev is NULL");
+		return -ENODEV;
 	}
 
 	subdev = v4l2_get_subdevdata(sd);
 	if (!subdev) {
-		pr_err("cam subdev is NULL\n");
-		return -EINVAL;
+		CAM_ERR(CAM_ICP, "cam subdev is NULL");
+		return -ENODEV;
 	}
 
 	for (i = 0; i < CAM_CTX_MAX; i++)
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index b763a39..48e1f1c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "HFI-FW %s:%d " fmt, __func__, __LINE__
-
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -27,6 +25,7 @@
 #include "hfi_session_defs.h"
 #include "hfi_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
+#include "cam_debug_util.h"
 
 #define HFI_VERSION_INFO_MAJOR_VAL  1
 #define HFI_VERSION_INFO_MINOR_VAL  1
@@ -39,11 +38,10 @@
 #define HFI_VERSION_INFO_STEP_BMSK   0xFF
 #define HFI_VERSION_INFO_STEP_SHFT  0
 
-#undef  HFI_DBG
-#define HFI_DBG(fmt, args...) pr_debug(fmt, ##args)
-
 static struct hfi_info *g_hfi;
 unsigned int g_icp_mmu_hdl;
+static DEFINE_MUTEX(hfi_cmd_q_mutex);
+static DEFINE_MUTEX(hfi_msg_q_mutex);
 
 int hfi_write_cmd(void *cmd_ptr)
 {
@@ -52,23 +50,25 @@
 	struct hfi_qtbl *q_tbl;
 	struct hfi_q_hdr *q;
 	int rc = 0;
-	int i = 0;
 
 	if (!cmd_ptr) {
-		pr_err("Invalid args\n");
+		CAM_ERR(CAM_HFI, "command is null");
 		return -EINVAL;
 	}
 
-	if (!g_hfi || (g_hfi->hfi_state != HFI_READY)) {
-		pr_err("HFI interface not ready yet\n");
-		return -EIO;
+	mutex_lock(&hfi_cmd_q_mutex);
+	if (!g_hfi) {
+		CAM_ERR(CAM_HFI, "HFI interface not setup");
+		rc = -ENODEV;
+		goto err;
 	}
 
-	mutex_lock(&g_hfi->cmd_q_lock);
-	if (!g_hfi->cmd_q_state) {
-		pr_err("HFI command interface not ready yet\n");
-		mutex_unlock(&g_hfi->cmd_q_lock);
-		return -EIO;
+	if (g_hfi->hfi_state != HFI_READY ||
+		!g_hfi->cmd_q_state) {
+		CAM_ERR(CAM_HFI, "HFI state: %u, cmd q state: %u",
+			g_hfi->hfi_state, g_hfi->cmd_q_state);
+		rc = -ENODEV;
+		goto err;
 	}
 
 	q_tbl = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
@@ -78,24 +78,20 @@
 
 	size_in_words = (*(uint32_t *)cmd_ptr) >> BYTE_WORD_SHIFT;
 	if (!size_in_words) {
-		pr_debug("failed");
+		CAM_DBG(CAM_HFI, "failed");
 		rc = -EINVAL;
 		goto err;
 	}
 
-	HFI_DBG("size_in_words : %u, q->qhdr_write_idx %x\n", size_in_words,
-		q->qhdr_write_idx);
-
 	read_idx = q->qhdr_read_idx;
 	empty_space = (q->qhdr_write_idx >= read_idx) ?
 		(q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) :
 		(read_idx - q->qhdr_write_idx);
 	if (empty_space <= size_in_words) {
-		pr_err("failed");
+		CAM_ERR(CAM_HFI, "failed");
 		rc = -EIO;
 		goto err;
 	}
-	HFI_DBG("empty_space : %u\n", empty_space);
 
 	new_write_idx = q->qhdr_write_idx + size_in_words;
 	write_ptr = (uint32_t *)(write_q + q->qhdr_write_idx);
@@ -110,15 +106,12 @@
 		memcpy(write_q, (uint8_t *)cmd_ptr + temp,
 			new_write_idx << BYTE_WORD_SHIFT);
 	}
-	for (i = 0; i < size_in_words; i++)
-		pr_debug("%x\n", write_ptr[i]);
 
 	q->qhdr_write_idx = new_write_idx;
-	HFI_DBG("q->qhdr_write_idx %x\n", q->qhdr_write_idx);
 	cam_io_w((uint32_t)INTR_ENABLE,
 		g_hfi->csr_base + HFI_REG_A5_CSR_HOST2ICPINT);
 err:
-	mutex_unlock(&g_hfi->cmd_q_lock);
+	mutex_unlock(&hfi_cmd_q_mutex);
 	return rc;
 }
 
@@ -129,32 +122,40 @@
 	uint32_t new_read_idx, size_in_words, temp;
 	uint32_t *read_q, *read_ptr;
 	int rc = 0;
-	int i = 0;
 
-	if (!pmsg || q_id > Q_DBG) {
-		pr_err("Inavlid args\n");
+	if (!pmsg) {
+		CAM_ERR(CAM_HFI, "Invalid msg");
 		return -EINVAL;
 	}
 
-	if (!g_hfi || (g_hfi->hfi_state != HFI_READY)) {
-		pr_err("HFI interface not ready yet\n");
-		return -EIO;
+	if (q_id > Q_DBG) {
+		CAM_ERR(CAM_HFI, "Inavlid q :%u", q_id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hfi_msg_q_mutex);
+	if (!g_hfi) {
+		CAM_ERR(CAM_HFI, "hfi not set up yet");
+		rc = -ENODEV;
+		goto err;
+	}
+
+	if ((g_hfi->hfi_state != HFI_READY) ||
+		!g_hfi->msg_q_state) {
+		CAM_ERR(CAM_HFI, "hfi state: %u, msg q state: %u",
+			g_hfi->hfi_state, g_hfi->msg_q_state);
+		rc = -ENODEV;
+		goto err;
 	}
 
 	q_tbl_ptr = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
 	q = &q_tbl_ptr->q_hdr[q_id];
 
 	if (q->qhdr_read_idx == q->qhdr_write_idx) {
-		pr_debug("FW or Q not ready, hfi state : %u, r idx : %u, w idx : %u\n",
+		CAM_DBG(CAM_HFI, "Q not ready, state:%u, r idx:%u, w idx:%u",
 			g_hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx);
-		return -EIO;
-	}
-
-	mutex_lock(&g_hfi->msg_q_lock);
-	if (!g_hfi->msg_q_state) {
-		pr_err("HFI message interface not ready yet\n");
-		mutex_unlock(&g_hfi->msg_q_lock);
-		return -EIO;
+		rc = -EIO;
+		goto err;
 	}
 
 	if (q_id == Q_MSG)
@@ -165,12 +166,9 @@
 	read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx);
 	size_in_words = (*read_ptr) >> BYTE_WORD_SHIFT;
 
-	HFI_DBG("size_in_words : %u, read_ptr : %pK\n", size_in_words,
-		(void *)read_ptr);
-
 	if ((size_in_words == 0) ||
 		(size_in_words > ICP_HFI_MAX_MSG_SIZE_IN_WORDS)) {
-		pr_err("invalid HFI message packet size - 0x%08x\n",
+		CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x",
 			size_in_words << BYTE_WORD_SHIFT);
 		q->qhdr_read_idx = q->qhdr_write_idx;
 		rc = -EIO;
@@ -178,7 +176,6 @@
 	}
 
 	new_read_idx = q->qhdr_read_idx + size_in_words;
-	HFI_DBG("new_read_idx : %u\n", new_read_idx);
 
 	if (new_read_idx < q->qhdr_q_size) {
 		memcpy(pmsg, read_ptr, size_in_words << BYTE_WORD_SHIFT);
@@ -190,12 +187,9 @@
 			new_read_idx << BYTE_WORD_SHIFT);
 	}
 
-	for (i = 0; i < size_in_words; i++)
-		HFI_DBG("%x\n", read_ptr[i]);
-
 	q->qhdr_read_idx = new_read_idx;
 err:
-	mutex_unlock(&g_hfi->msg_q_lock);
+	mutex_unlock(&hfi_msg_q_mutex);
 	return rc;
 }
 
@@ -265,7 +259,7 @@
 	case HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT:
 		break;
 	default:
-		pr_err("command not supported :%d\n", type);
+		CAM_ERR(CAM_HFI, "command not supported :%d", type);
 		break;
 	}
 }
@@ -277,7 +271,7 @@
 	struct cam_icp_query_cap_cmd *query_cmd = NULL;
 
 	if (!query_buf) {
-		pr_err("%s: query buf is NULL\n", __func__);
+		CAM_ERR(CAM_HFI, "query buf is NULL");
 		return -EINVAL;
 	}
 
@@ -332,6 +326,9 @@
 	struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr;
 	uint32_t hw_version, fw_version, status = 0;
 
+	mutex_lock(&hfi_cmd_q_mutex);
+	mutex_lock(&hfi_msg_q_mutex);
+
 	if (!g_hfi) {
 		g_hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL);
 		if (!g_hfi) {
@@ -340,13 +337,13 @@
 		}
 	}
 
-	HFI_DBG("g_hfi: %pK\n", (void *)g_hfi);
 	if (g_hfi->hfi_state != HFI_DEINIT) {
-		pr_err("hfi_init: invalid state\n");
+		CAM_ERR(CAM_HFI, "hfi_init: invalid state");
 		return -EINVAL;
 	}
 
 	memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map));
+	g_hfi->hfi_state = HFI_DEINIT;
 
 	if (debug) {
 		cam_io_w_mb(
@@ -373,7 +370,6 @@
 	qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS;
 
 	/* setup host-to-firmware command queue */
-	pr_debug("updating the command queue info\n");
 	cmd_q_hdr = &qtbl->q_hdr[Q_CMD];
 	cmd_q_hdr->qhdr_status = QHDR_ACTIVE;
 	cmd_q_hdr->qhdr_start_addr = hfi_mem->cmd_q.iova;
@@ -384,7 +380,6 @@
 	cmd_q_hdr->qhdr_write_idx = RESET;
 
 	/* setup firmware-to-Host message queue */
-	pr_debug("updating the message queue info\n");
 	msg_q_hdr = &qtbl->q_hdr[Q_MSG];
 	msg_q_hdr->qhdr_status = QHDR_ACTIVE;
 	msg_q_hdr->qhdr_start_addr = hfi_mem->msg_q.iova;
@@ -395,7 +390,6 @@
 	msg_q_hdr->qhdr_write_idx = RESET;
 
 	/* setup firmware-to-Host message queue */
-	pr_debug("updating the debug queue info\n");
 	dbg_q_hdr = &qtbl->q_hdr[Q_DBG];
 	dbg_q_hdr->qhdr_status = QHDR_ACTIVE;
 	dbg_q_hdr->qhdr_start_addr = hfi_mem->dbg_q.iova;
@@ -404,7 +398,6 @@
 	dbg_q_hdr->qhdr_pkt_drop_cnt = RESET;
 	dbg_q_hdr->qhdr_read_idx = RESET;
 	dbg_q_hdr->qhdr_write_idx = RESET;
-	pr_debug("Done updating the debug queue info\n");
 
 	switch (event_driven_mode) {
 	case INTR_MODE:
@@ -473,7 +466,8 @@
 		break;
 
 	default:
-		pr_err("Invalid event driven mode :%u", event_driven_mode);
+		CAM_ERR(CAM_HFI, "Invalid event driven mode :%u",
+			event_driven_mode);
 		break;
 	}
 
@@ -490,56 +484,58 @@
 		icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
 
 	hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION);
-	HFI_DBG("hw version : [%x]\n", hw_version);
 
 	rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
 		status, status != ICP_INIT_RESP_SUCCESS, 15, 200);
 	if (rc) {
-		pr_err("timed out , status = %u\n", status);
+		CAM_ERR(CAM_HFI, "timed out , status = %u", status);
 		goto regions_fail;
 	}
 
 	fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
-	HFI_DBG("fw version : %u[%x]\n", fw_version, fw_version);
+	CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]",
+		hw_version, fw_version);
 
 	g_hfi->csr_base = icp_base;
 	g_hfi->hfi_state = HFI_READY;
 	g_hfi->cmd_q_state = true;
 	g_hfi->msg_q_state = true;
-	mutex_init(&g_hfi->cmd_q_lock);
-	mutex_init(&g_hfi->msg_q_lock);
 	cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
 
+	mutex_unlock(&hfi_cmd_q_mutex);
+	mutex_unlock(&hfi_msg_q_mutex);
+
 	return rc;
 regions_fail:
 	kfree(g_hfi);
 alloc_fail:
+	mutex_unlock(&hfi_cmd_q_mutex);
+	mutex_unlock(&hfi_msg_q_mutex);
 	return rc;
 }
 
 
 void cam_hfi_deinit(void)
 {
+	mutex_lock(&hfi_cmd_q_mutex);
+	mutex_lock(&hfi_msg_q_mutex);
+
 	if (!g_hfi) {
-		pr_err("hfi path not established yet\n");
-		return;
+		CAM_ERR(CAM_HFI, "hfi path not established yet");
+		goto err;
 	}
+
+	g_hfi->cmd_q_state = false;
+	g_hfi->msg_q_state = false;
+
 	cam_io_w((uint32_t)INTR_DISABLE,
 		g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN);
-
-	mutex_lock(&g_hfi->cmd_q_lock);
-	g_hfi->cmd_q_state = false;
-	mutex_unlock(&g_hfi->cmd_q_lock);
-
-	mutex_lock(&g_hfi->msg_q_lock);
-	g_hfi->msg_q_state = false;
-	mutex_unlock(&g_hfi->msg_q_lock);
-
-	mutex_destroy(&g_hfi->cmd_q_lock);
-	mutex_destroy(&g_hfi->msg_q_lock);
-
-	kfree(g_hfi);
+	kzfree(g_hfi);
 	g_hfi = NULL;
+
+err:
+	mutex_unlock(&hfi_cmd_q_mutex);
+	mutex_unlock(&hfi_msg_q_mutex);
 }
 
 void icp_enable_fw_debug(void)
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
index 9f6f940..e200f6f 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "A5-CORE %s:%d " fmt, __func__, __LINE__
-
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/debugfs.h>
@@ -35,6 +33,7 @@
 #include "hfi_sys_defs.h"
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
+#include "cam_debug_util.h"
 
 static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info,
 	struct cam_icp_cpas_vote *cpas_vote)
@@ -50,7 +49,7 @@
 			&cpas_vote->axi_vote);
 
 	if (rc)
-		pr_err("cpas vote is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc);
 
 	return rc;
 }
@@ -60,26 +59,26 @@
 	struct elf32_hdr *elf_hdr;
 
 	if (!elf) {
-		pr_err("Invalid params\n");
+		CAM_ERR(CAM_ICP, "Invalid params");
 		return -EINVAL;
 	}
 
 	elf_hdr = (struct elf32_hdr *)elf;
 
 	if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG)) {
-		pr_err("ICP elf identifier is failed\n");
+		CAM_ERR(CAM_ICP, "ICP elf identifier is failed");
 		return -EINVAL;
 	}
 
 	/* check architecture */
 	if (elf_hdr->e_machine != EM_ARM) {
-		pr_err("unsupported arch\n");
+		CAM_ERR(CAM_ICP, "unsupported arch");
 		return -EINVAL;
 	}
 
 	/* check elf bit format */
 	if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
-		pr_err("elf doesn't support 32 bit format\n");
+		CAM_ERR(CAM_ICP, "elf doesn't support 32 bit format");
 		return -EINVAL;
 	}
 
@@ -97,7 +96,7 @@
 	struct elf32_phdr *prg_hdr;
 
 	if (!elf || !fw_size) {
-		pr_err("invalid args\n");
+		CAM_ERR(CAM_ICP, "invalid args");
 		return -EINVAL;
 	}
 
@@ -109,11 +108,11 @@
 	prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
 
 	if (!prg_hdr) {
-		pr_err("failed to get elf program header attr\n");
+		CAM_ERR(CAM_ICP, "failed to get elf program header attr");
 		return -EINVAL;
 	}
 
-	pr_debug("num_prg_hdrs = %d\n", num_prg_hdrs);
+	CAM_DBG(CAM_ICP, "num_prg_hdrs = %d", num_prg_hdrs);
 	for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
 		if (prg_hdr->p_flags == 0)
 			continue;
@@ -121,7 +120,7 @@
 		seg_mem_size = (prg_hdr->p_memsz + prg_hdr->p_align - 1) &
 					~(prg_hdr->p_align - 1);
 		seg_mem_size += prg_hdr->p_vaddr;
-		pr_debug("p_memsz = %x p_align = %x p_vaddr = %x seg_mem_size = %x\n",
+		CAM_DBG(CAM_ICP, "memsz:%x align:%x addr:%x seg_mem_size:%x",
 			(int)prg_hdr->p_memsz, (int)prg_hdr->p_align,
 			(int)prg_hdr->p_vaddr, (int)seg_mem_size);
 		if (*fw_size < seg_mem_size)
@@ -130,7 +129,7 @@
 	}
 
 	if (*fw_size == 0) {
-		pr_err("invalid elf fw file\n");
+		CAM_ERR(CAM_ICP, "invalid elf fw file");
 		return -EINVAL;
 	}
 
@@ -155,7 +154,7 @@
 	prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
 
 	if (!prg_hdr) {
-		pr_err("failed to get elf program header attr\n");
+		CAM_ERR(CAM_ICP, "failed to get elf program header attr");
 		return -EINVAL;
 	}
 
@@ -163,15 +162,14 @@
 		if (prg_hdr->p_flags == 0)
 			continue;
 
-		pr_debug("Loading FW header size: %u\n", prg_hdr->p_filesz);
+		CAM_DBG(CAM_ICP, "Loading FW header size: %u",
+			prg_hdr->p_filesz);
 		if (prg_hdr->p_filesz != 0) {
 			src = (u8 *)((u8 *)elf + prg_hdr->p_offset);
 			dest = (u8 *)(((u8 *)core_info->fw_kva_addr) +
 						prg_hdr->p_vaddr);
 
 			memcpy_toio(dest, src, prg_hdr->p_filesz);
-			pr_debug("fw kva: %pK, p_vaddr: 0x%x\n",
-					dest, prg_hdr->p_vaddr);
 		}
 	}
 
@@ -191,7 +189,7 @@
 	struct a5_soc_info *cam_a5_soc_info = NULL;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
@@ -202,44 +200,38 @@
 	cam_a5_soc_info = soc_info->soc_private;
 
 	rc = request_firmware(&core_info->fw_elf, "CAMERA_ICP.elf", &pdev->dev);
-	pr_debug("request_firmware: %d\n", rc);
-	if (rc < 0) {
-		pr_err("Failed to locate fw\n");
+	if (rc) {
+		CAM_ERR(CAM_ICP, "Failed to locate fw: %d", rc);
 		return rc;
 	}
 
 	if (!core_info->fw_elf) {
-		pr_err("request_firmware is failed\n");
+		CAM_ERR(CAM_ICP, "Invalid elf size");
 		return -EINVAL;
 	}
 
 	fw_start = core_info->fw_elf->data;
 	rc = cam_icp_validate_fw(fw_start);
-	if (rc < 0) {
-		pr_err("fw elf validation failed\n");
+	if (rc) {
+		CAM_ERR(CAM_ICP, "fw elf validation failed");
 		return -EINVAL;
 	}
 
 	rc = cam_icp_get_fw_size(fw_start, &fw_size);
-	if (rc < 0) {
-		pr_err("unable to get fw file size\n");
+	if (rc) {
+		CAM_ERR(CAM_ICP, "unable to get fw size");
 		return rc;
 	}
-	pr_debug("cam_icp_get_fw_size: %u\n", fw_size);
-
-	/* Check FW firmware memory allocation is OK or not */
-	pr_debug("cam_icp_get_fw_size: %u %llu\n",
-		fw_size, core_info->fw_buf_len);
 
 	if (core_info->fw_buf_len < fw_size) {
-		pr_err("fw allocation failed\n");
+		CAM_ERR(CAM_ICP, "mismatch in fw size: %u %llu",
+			fw_size, core_info->fw_buf_len);
 		goto fw_alloc_failed;
 	}
 
-	/* download fw */
 	rc = cam_icp_program_fw(fw_start, core_info);
-	if (rc < 0) {
-		pr_err("fw program is failed\n");
+	if (rc) {
+		CAM_ERR(CAM_ICP, "fw program is failed");
 		goto fw_program_failed;
 	}
 
@@ -259,7 +251,7 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
@@ -267,7 +259,8 @@
 	core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
 
 	if ((!soc_info) || (!core_info)) {
-		pr_err("soc_info = %pK core_info = %pK\n", soc_info, core_info);
+		CAM_ERR(CAM_ICP, "soc_info: %pK core_info: %pK",
+			soc_info, core_info);
 		return -EINVAL;
 	}
 
@@ -279,16 +272,16 @@
 	rc = cam_cpas_start(core_info->cpas_handle,
 		&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
 	if (rc) {
-		pr_err("cpass start failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "cpass start failed: %d", rc);
 		return rc;
 	}
 	core_info->cpas_start = true;
 
 	rc = cam_a5_enable_soc_resources(soc_info);
 	if (rc) {
-		pr_err("soc enable is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "soc enable is failed: %d", rc);
 		if (cam_cpas_stop(core_info->cpas_handle))
-			pr_err("cpas stop is failed\n");
+			CAM_ERR(CAM_ICP, "cpas stop is failed");
 		else
 			core_info->cpas_start = false;
 	}
@@ -305,24 +298,25 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
 	soc_info = &a5_dev->soc_info;
 	core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
 	if ((!soc_info) || (!core_info)) {
-		pr_err("soc_info = %pK core_info = %pK\n", soc_info, core_info);
+		CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
 		return -EINVAL;
 	}
 
 	rc = cam_a5_disable_soc_resources(soc_info);
 	if (rc)
-		pr_err("soc disable is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc);
 
 	if (core_info->cpas_start) {
 		if (cam_cpas_stop(core_info->cpas_handle))
-			pr_err("cpas stop is failed\n");
+			CAM_ERR(CAM_ICP, "cpas stop is failed");
 		else
 			core_info->cpas_start = false;
 	}
@@ -339,7 +333,7 @@
 	uint32_t irq_status = 0;
 
 	if (!data) {
-		pr_err("Invalid cam_dev_info or query_cap args\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info or query_cap args");
 		return IRQ_HANDLED;
 	}
 
@@ -354,18 +348,15 @@
 			soc_info->reg_map[A5_SIERRA_BASE].mem_base +
 			core_info->a5_hw_info->a5_host_int_clr);
 
-	pr_debug("irq_status = %x\n", irq_status);
-	if (irq_status & A5_HOST_INT)
-		pr_debug("A5 to Host interrupt, read msg Q\n");
-
 	if ((irq_status & A5_WDT_0) ||
 		(irq_status & A5_WDT_1)) {
-		pr_err_ratelimited("watch dog interrupt from A5\n");
+		CAM_ERR_RATE_LIMIT(CAM_ICP, "watch dog interrupt from A5");
 	}
 
 	if (core_info->irq_cb.icp_hw_mgr_cb)
 		core_info->irq_cb.icp_hw_mgr_cb(irq_status,
 					core_info->irq_cb.data);
+
 	return IRQ_HANDLED;
 }
 
@@ -379,12 +370,12 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_ICP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	if (cmd_type >= CAM_ICP_A5_CMD_MAX) {
-		pr_err("Invalid command : %x\n", cmd_type);
+		CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type);
 		return -EINVAL;
 	}
 
@@ -401,7 +392,7 @@
 		struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args;
 
 		if (!cmd_args) {
-			pr_err("cmd args NULL\n");
+			CAM_ERR(CAM_ICP, "cmd args NULL");
 			return -EINVAL;
 		}
 
@@ -409,15 +400,16 @@
 		core_info->fw_kva_addr = fw_buf_info->kva;
 		core_info->fw_buf_len = fw_buf_info->len;
 
-		pr_debug("fw buf info = %x %llx %lld\n", core_info->fw_buf,
-			core_info->fw_kva_addr, core_info->fw_buf_len);
+		CAM_DBG(CAM_ICP, "fw buf info = %x %llx %lld",
+			core_info->fw_buf, core_info->fw_kva_addr,
+			core_info->fw_buf_len);
 		break;
 	}
 	case CAM_ICP_A5_SET_IRQ_CB: {
 		struct cam_icp_a5_set_irq_cb *irq_cb = cmd_args;
 
 		if (!cmd_args) {
-			pr_err("cmd args NULL\n");
+			CAM_ERR(CAM_ICP, "cmd args NULL");
 			return -EINVAL;
 		}
 
@@ -433,7 +425,7 @@
 		struct cam_icp_cpas_vote *cpas_vote = cmd_args;
 
 		if (!cmd_args) {
-			pr_err("cmd args NULL\n");
+			CAM_ERR(CAM_ICP, "cmd args NULL");
 			return -EINVAL;
 		}
 
@@ -445,7 +437,7 @@
 		struct cam_icp_cpas_vote *cpas_vote = cmd_args;
 
 		if (!cmd_args) {
-			pr_err("cmd args NULL\n");
+			CAM_ERR(CAM_ICP, "cmd args NULL");
 			return -EINVAL;
 		}
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c
index f649c3b..08b934e 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c
@@ -23,6 +23,7 @@
 #include "cam_a5_hw_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
+#include "cam_debug_util.h"
 
 struct a5_soc_info cam_a5_soc_info;
 EXPORT_SYMBOL(cam_a5_soc_info);
@@ -64,7 +65,7 @@
 
 	rc = cam_cpas_register_client(&cpas_register_params);
 	if (rc < 0) {
-		pr_err("cam_cpas_register_client is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "failed: %d", rc);
 		return rc;
 	}
 
@@ -101,7 +102,7 @@
 	a5_dev_intf->hw_ops.process_cmd = cam_a5_process_cmd;
 	a5_dev_intf->hw_type = CAM_ICP_DEV_A5;
 
-	pr_debug("%s: type %d index %d\n", __func__,
+	CAM_DBG(CAM_ICP, "type %d index %d",
 		a5_dev_intf->hw_type,
 		a5_dev_intf->hw_idx);
 
@@ -118,9 +119,9 @@
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
 	if (!match_dev) {
-		pr_err("%s: No a5 hardware info\n", __func__);
+		CAM_ERR(CAM_ICP, "No a5 hardware info");
 		rc = -EINVAL;
-		goto pr_err;
+		goto match_err;
 	}
 	hw_info = (struct cam_a5_device_hw_info *)match_dev->data;
 	core_info->a5_hw_info = hw_info;
@@ -130,16 +131,16 @@
 	rc = cam_a5_init_soc_resources(&a5_dev->soc_info, cam_a5_irq,
 		a5_dev);
 	if (rc < 0) {
-		pr_err("%s: failed to init_soc\n", __func__);
+		CAM_ERR(CAM_ICP, "failed to init_soc");
 		goto init_soc_failure;
 	}
 
-	pr_debug("cam_a5_init_soc_resources : %pK\n",
+	CAM_DBG(CAM_ICP, "soc info : %pK",
 				(void *)&a5_dev->soc_info);
 	rc = cam_a5_register_cpas(&a5_dev->soc_info,
 			core_info, a5_dev_intf->hw_idx);
 	if (rc < 0) {
-		pr_err("a5 cpas registration failed\n");
+		CAM_ERR(CAM_ICP, "a5 cpas registration failed");
 		goto cpas_reg_failed;
 	}
 	a5_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
@@ -147,13 +148,13 @@
 	spin_lock_init(&a5_dev->hw_lock);
 	init_completion(&a5_dev->hw_complete);
 
-	pr_debug("%s: A5%d probe successful\n", __func__,
+	CAM_DBG(CAM_ICP, "A5%d probe successful",
 		a5_dev_intf->hw_idx);
 	return 0;
 
 cpas_reg_failed:
 init_soc_failure:
-pr_err:
+match_err:
 	kfree(a5_dev->core_info);
 core_info_alloc_failure:
 	kfree(a5_dev);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_soc.c
index a98f01f..f252931 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_soc.c
@@ -18,9 +18,7 @@
 #include <media/cam_icp.h>
 #include "a5_soc.h"
 #include "cam_soc_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static int cam_a5_get_dt_properties(struct cam_hw_soc_info *soc_info)
 {
@@ -35,7 +33,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("%s: get a5 dt prop is failed\n", __func__);
+		CAM_ERR(CAM_ICP, "get a5 dt prop is failed");
 		return rc;
 	}
 
@@ -44,7 +42,7 @@
 
 	rc = of_property_read_string(of_node, "fw_name", &fw_name);
 	if (rc < 0)
-		pr_err("%s: fw_name read failed\n", __func__);
+		CAM_ERR(CAM_ICP, "fw_name read failed");
 
 	return rc;
 }
@@ -85,7 +83,7 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, true);
 	if (rc)
-		pr_err("%s: enable platform failed\n", __func__);
+		CAM_ERR(CAM_ICP, "enable platform failed");
 
 	return rc;
 }
@@ -96,7 +94,7 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc)
-		pr_err("%s: disable platform failed\n", __func__);
+		CAM_ERR(CAM_ICP, "disable platform failed");
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
index cabdc8a..557eaf1 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "BPS-CORE %s:%d " fmt, __func__, __LINE__
-
 #include <linux/of.h>
 #include <linux/debugfs.h>
 #include <linux/videodev2.h>
@@ -31,6 +29,7 @@
 #include "cam_icp_hw_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
+#include "cam_debug_util.h"
 
 static int cam_bps_cpas_vote(struct cam_bps_device_core_info *core_info,
 			struct cam_icp_cpas_vote *cpas_vote)
@@ -45,7 +44,7 @@
 				&cpas_vote->axi_vote);
 
 	if (rc < 0)
-		pr_err("cpas vote is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc);
 
 	return rc;
 }
@@ -61,7 +60,7 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
@@ -69,7 +68,8 @@
 	core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
 
 	if ((!soc_info) || (!core_info)) {
-		pr_err("soc_info = %pK core_info = %pK\n", soc_info, core_info);
+		CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
 		return -EINVAL;
 	}
 
@@ -81,16 +81,16 @@
 	rc = cam_cpas_start(core_info->cpas_handle,
 			&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
 	if (rc) {
-		pr_err("cpass start failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "cpass start failed: %d", rc);
 		return rc;
 	}
 	core_info->cpas_start = true;
 
 	rc = cam_bps_enable_soc_resources(soc_info);
 	if (rc) {
-		pr_err("soc enable is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "soc enable is failed: %d", rc);
 		if (cam_cpas_stop(core_info->cpas_handle))
-			pr_err("cpas stop is failed\n");
+			CAM_ERR(CAM_ICP, "cpas stop is failed");
 		else
 			core_info->cpas_start = false;
 	}
@@ -107,24 +107,25 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
 	soc_info = &bps_dev->soc_info;
 	core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
 	if ((!soc_info) || (!core_info)) {
-		pr_err("soc_info = %pK core_info = %pK\n", soc_info, core_info);
+		CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
 		return -EINVAL;
 	}
 
 	rc = cam_bps_disable_soc_resources(soc_info);
 	if (rc)
-		pr_err("soc disable is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc);
 
 	if (core_info->cpas_start) {
 		if (cam_cpas_stop(core_info->cpas_handle))
-			pr_err("cpas stop is failed\n");
+			CAM_ERR(CAM_ICP, "cpas stop is failed");
 		else
 			core_info->cpas_start = false;
 	}
@@ -142,12 +143,12 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_ICP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	if (cmd_type >= CAM_ICP_BPS_CMD_MAX) {
-		pr_err("Invalid command : %x\n", cmd_type);
+		CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type);
 		return -EINVAL;
 	}
 
@@ -160,7 +161,7 @@
 		struct cam_icp_cpas_vote *cpas_vote = cmd_args;
 
 		if (!cmd_args) {
-			pr_err("cmd args NULL\n");
+			CAM_ERR(CAM_ICP, "cmd args NULL");
 			return -EINVAL;
 		}
 
@@ -172,7 +173,7 @@
 		struct cam_icp_cpas_vote *cpas_vote = cmd_args;
 
 		if (!cmd_args) {
-			pr_err("cmd args NULL\n");
+			CAM_ERR(CAM_ICP, "cmd args NULL");
 			return -EINVAL;
 		}
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c
index c3477ee..ddff677 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c
@@ -23,9 +23,7 @@
 #include "cam_icp_hw_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 struct cam_bps_device_hw_info cam_bps_hw_info = {
 	.reserved = 0,
@@ -47,7 +45,7 @@
 
 	rc = cam_cpas_register_client(&cpas_register_params);
 	if (rc < 0) {
-		pr_err("cam_cpas_register_client is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "failed: %d", rc);
 		return rc;
 	}
 	core_info->cpas_handle = cpas_register_params.client_handle;
@@ -95,7 +93,7 @@
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
 	if (!match_dev) {
-		pr_err("%s: No bps hardware info\n", __func__);
+		CAM_ERR(CAM_ICP, "No bps hardware info");
 		kfree(bps_dev->core_info);
 		kfree(bps_dev);
 		kfree(bps_dev_intf);
@@ -108,13 +106,13 @@
 	rc = cam_bps_init_soc_resources(&bps_dev->soc_info, cam_bps_irq,
 		bps_dev);
 	if (rc < 0) {
-		pr_err("%s: failed to init_soc\n", __func__);
+		CAM_ERR(CAM_ICP, "failed to init_soc");
 		kfree(bps_dev->core_info);
 		kfree(bps_dev);
 		kfree(bps_dev_intf);
 		return rc;
 	}
-	pr_debug("cam_bps_init_soc_resources : %pK\n",
+	CAM_DBG(CAM_ICP, "soc info : %pK",
 		(void *)&bps_dev->soc_info);
 
 	rc = cam_bps_register_cpas(&bps_dev->soc_info,
@@ -129,7 +127,7 @@
 	mutex_init(&bps_dev->hw_mutex);
 	spin_lock_init(&bps_dev->hw_lock);
 	init_completion(&bps_dev->hw_complete);
-	pr_debug("%s: BPS%d probe successful\n", __func__,
+	CAM_DBG(CAM_ICP, "BPS%d probe successful",
 		bps_dev_intf->hw_idx);
 
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
index 8a3c7ac..54e898c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
@@ -18,9 +18,7 @@
 #include <media/cam_icp.h>
 #include "bps_soc.h"
 #include "cam_soc_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static int cam_bps_get_dt_properties(struct cam_hw_soc_info *soc_info)
 {
@@ -28,7 +26,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0)
-		pr_err("get bps dt prop is failed\n");
+		CAM_ERR(CAM_ICP, "get bps dt prop is failed");
 
 	return rc;
 }
@@ -69,7 +67,7 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, false);
 	if (rc)
-		pr_err("%s: enable platform failed\n", __func__);
+		CAM_ERR(CAM_ICP, "enable platform failed");
 
 	return rc;
 }
@@ -80,7 +78,7 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
 	if (rc)
-		pr_err("%s: disable platform failed\n", __func__);
+		CAM_ERR(CAM_ICP, "disable platform failed");
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index f273a7b..1b3afc0 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "ICP-HW-MGR %s:%d " fmt, __func__, __LINE__
-
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -46,9 +44,7 @@
 #include "cam_mem_mgr.h"
 #include "a5_core.h"
 #include "hfi_sys_defs.h"
-
-#undef  ICP_DBG
-#define ICP_DBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 #define ICP_WORKQ_NUM_TASK 30
 #define ICP_WORKQ_TASK_CMD_TYPE 1
@@ -80,7 +76,7 @@
 	struct cam_icp_hw_mgr *hw_mgr;
 
 	if (!data || !priv) {
-		pr_err("Invalid params%pK %pK\n", data, priv);
+		CAM_ERR(CAM_ICP, "Invalid params%pK %pK", data, priv);
 		return -EINVAL;
 	}
 
@@ -88,7 +84,6 @@
 	task_data = (struct hfi_cmd_work_data *)data;
 
 	rc = hfi_write_cmd(task_data->data);
-	ICP_DBG("task type : %u, rc : %d\n", task_data->type, rc);
 
 	return rc;
 }
@@ -106,14 +101,15 @@
 
 	ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
 	if (ioconfig_ack->err_type != HFI_ERR_SYS_NONE) {
-		pr_err("failed with error : %u\n", ioconfig_ack->err_type);
+		CAM_ERR(CAM_ICP, "failed with error : %u",
+			ioconfig_ack->err_type);
 		return -EIO;
 	}
 
 	frame_done =
 		(struct hfi_msg_frame_process_done *)ioconfig_ack->msg_data;
 	if (frame_done->result) {
-		pr_err("result : %u\n", frame_done->result);
+		CAM_ERR(CAM_ICP, "result : %u", frame_done->result);
 		return -EIO;
 	}
 
@@ -126,7 +122,7 @@
 			break;
 
 	if (i >= CAM_FRAME_CMD_MAX) {
-		pr_err("unable to find pkt in ctx data for req_id =%lld\n",
+		CAM_ERR(CAM_ICP, "pkt not found in ctx data for req_id =%lld",
 			request_id);
 		return -EINVAL;
 	}
@@ -136,7 +132,7 @@
 	ctx_data->ctxt_event_cb(ctx_data->context_priv, false, &buf_data);
 
 	/* now release memory for hfi frame process command */
-	ICP_DBG("matching request id: %lld\n",
+	CAM_DBG(CAM_ICP, "matching request id: %lld",
 			hfi_frame_process->request_id[idx]);
 	mutex_lock(&ctx_data->hfi_frame_process.lock);
 	hfi_frame_process->request_id[idx] = 0;
@@ -153,40 +149,37 @@
 	struct hfi_msg_bps_common *bps_config_ack = NULL;
 
 	ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
-	ICP_DBG("opcode : %u\n", ioconfig_ack->opcode);
 
 	if (ioconfig_ack->opcode == HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO) {
 		ipe_config_ack =
 			(struct hfi_msg_ipe_config *)(ioconfig_ack->msg_data);
 		if (ipe_config_ack->rc) {
-			pr_err("rc = %d err = %u\n",
+			CAM_ERR(CAM_ICP, "rc = %d err = %u",
 				ipe_config_ack->rc, ioconfig_ack->err_type);
 			return -EIO;
 		}
 		ctx_data =
 			(struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
 		if (!ctx_data) {
-			pr_err("wrong ctx data from IPE response\n");
+			CAM_ERR(CAM_ICP, "wrong ctx data from IPE response");
 			return -EINVAL;
 		}
 
 		mutex_lock(&ctx_data->ctx_mutex);
 		ctx_data->scratch_mem_size = ipe_config_ack->scratch_mem_size;
 		mutex_unlock(&ctx_data->ctx_mutex);
-		ICP_DBG("scratch_mem_size = %u\n",
-			ipe_config_ack->scratch_mem_size);
 	} else {
 		bps_config_ack =
 			(struct hfi_msg_bps_common *)(ioconfig_ack->msg_data);
 		if (bps_config_ack->rc) {
-			pr_err("rc : %u, opcode :%u\n",
+			CAM_ERR(CAM_ICP, "rc : %u, opcode :%u",
 				bps_config_ack->rc, ioconfig_ack->opcode);
 			return -EIO;
 		}
 		ctx_data =
 			(struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
 		if (!ctx_data) {
-			pr_err("wrong ctx data from BPS response\n");
+			CAM_ERR(CAM_ICP, "wrong ctx data from BPS response");
 			return -EINVAL;
 		}
 	}
@@ -202,22 +195,20 @@
 
 	create_handle_ack = (struct hfi_msg_create_handle_ack *)msg_ptr;
 	if (!create_handle_ack) {
-		pr_err("Invalid create_handle_ack\n");
+		CAM_ERR(CAM_ICP, "Invalid create_handle_ack");
 		return -EINVAL;
 	}
 
-	ICP_DBG("err type : %u\n", create_handle_ack->err_type);
-
 	ctx_data = (struct cam_icp_hw_ctx_data *)create_handle_ack->user_data1;
 	if (!ctx_data) {
-		pr_err("Invalid ctx_data\n");
+		CAM_ERR(CAM_ICP, "Invalid ctx_data");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ctx_data->ctx_mutex);
 	ctx_data->fw_handle = create_handle_ack->fw_handle;
 	mutex_unlock(&ctx_data->ctx_mutex);
-	ICP_DBG("fw_handle = %x\n", ctx_data->fw_handle);
+	CAM_DBG(CAM_ICP, "fw_handle = %x", ctx_data->fw_handle);
 	complete(&ctx_data->wait_complete);
 
 	return 0;
@@ -230,18 +221,16 @@
 
 	ping_ack = (struct hfi_msg_ping_ack *)msg_ptr;
 	if (!ping_ack) {
-		pr_err("Empty ping ack message\n");
+		CAM_ERR(CAM_ICP, "Empty ping ack message");
 		return -EINVAL;
 	}
 
 	ctx_data = (struct cam_icp_hw_ctx_data *)ping_ack->user_data;
 	if (!ctx_data) {
-		pr_err("Invalid ctx_data\n");
+		CAM_ERR(CAM_ICP, "Invalid ctx_data");
 		return -EINVAL;
 	}
 
-	ICP_DBG("%x %x %pK\n", ping_ack->size, ping_ack->pkt_type,
-		(void *)ping_ack->user_data);
 	complete(&ctx_data->wait_complete);
 
 	return 0;
@@ -254,7 +243,7 @@
 	switch (msg_ptr[ICP_PACKET_OPCODE]) {
 	case HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO:
 	case HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO:
-		ICP_DBG("received HFI_IPEBPS_CMD_OPCODE_IPE/BPS_CONFIG_IO:\n");
+		CAM_DBG(CAM_ICP, "received IPE/BPS_CONFIG_IO:");
 		rc = cam_icp_mgr_process_msg_config_io(msg_ptr);
 		if (rc)
 			return rc;
@@ -262,13 +251,12 @@
 
 	case HFI_IPEBPS_CMD_OPCODE_IPE_FRAME_PROCESS:
 	case HFI_IPEBPS_CMD_OPCODE_BPS_FRAME_PROCESS:
-		ICP_DBG("received OPCODE_IPE/BPS_FRAME_PROCESS:\n");
 		rc = cam_icp_mgr_process_msg_frame_process(msg_ptr);
 		if (rc)
 			return rc;
 		break;
 	default:
-		pr_err("Invalid opcode : %u\n",
+		CAM_ERR(CAM_ICP, "Invalid opcode : %u",
 			msg_ptr[ICP_PACKET_OPCODE]);
 		break;
 	}
@@ -287,14 +275,14 @@
 	case HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY:
 	case HFI_IPEBPS_CMD_OPCODE_IPE_ABORT:
 	case HFI_IPEBPS_CMD_OPCODE_BPS_ABORT:
-		ICP_DBG("received IPE/BPS_DESTROY/ABORT:\n");
+		CAM_DBG(CAM_ICP, "received IPE/BPS_DESTROY/ABORT:");
 		ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
 		ctx_data =
 			(struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
 		complete(&ctx_data->wait_complete);
 		break;
 	default:
-		pr_err("Invalid opcode : %u\n",
+		CAM_ERR(CAM_ICP, "Invalid opcode : %u",
 			msg_ptr[ICP_PACKET_OPCODE]);
 		rc = -EINVAL;
 		break;
@@ -312,37 +300,35 @@
 	int read_len;
 
 	if (!data || !priv) {
-		pr_err("Invalid data\n");
+		CAM_ERR(CAM_ICP, "Invalid data");
 		return -EINVAL;
 	}
 
 	task_data = data;
 	hw_mgr = priv;
-	ICP_DBG("irq status : %u\n", task_data->irq_status);
 
 	read_len = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG);
 	if (read_len < 0) {
-		ICP_DBG("Unable to read msg q\n");
+		CAM_DBG(CAM_ICP, "Unable to read msg q");
 		return read_len;
 	}
 
 	msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf;
-	ICP_DBG("packet type: %x\n", msg_ptr[ICP_PACKET_TYPE]);
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	switch (msg_ptr[ICP_PACKET_TYPE]) {
 	case HFI_MSG_SYS_INIT_DONE:
-		ICP_DBG("received HFI_MSG_SYS_INIT_DONE\n");
+		CAM_DBG(CAM_ICP, "received SYS_INIT_DONE");
 		complete(&hw_mgr->a5_complete);
 		break;
 
 	case HFI_MSG_SYS_PING_ACK:
-		ICP_DBG("received HFI_MSG_SYS_PING_ACK\n");
+		CAM_DBG(CAM_ICP, "received SYS_PING_ACK");
 		rc = cam_icp_mgr_process_msg_ping_ack(msg_ptr);
 		break;
 
 	case HFI_MSG_IPEBPS_CREATE_HANDLE_ACK:
-		ICP_DBG("received HFI_MSG_IPEBPS_CREATE_HANDLE_ACK\n");
+		CAM_DBG(CAM_ICP, "received IPEBPS_CREATE_HANDLE_ACK");
 		rc = cam_icp_mgr_process_msg_create_handle(msg_ptr);
 		break;
 
@@ -355,11 +341,12 @@
 		break;
 
 	case HFI_MSG_EVENT_NOTIFY:
-		ICP_DBG("received HFI_MSG_EVENT_NOTIFY\n");
+		CAM_DBG(CAM_ICP, "received EVENT_NOTIFY");
 		break;
 
 	default:
-		pr_err("invalid msg : %u\n", msg_ptr[ICP_PACKET_TYPE]);
+		CAM_ERR(CAM_ICP, "invalid msg : %u",
+			msg_ptr[ICP_PACKET_TYPE]);
 		break;
 	}
 
@@ -379,7 +366,7 @@
 	spin_lock_irqsave(&hw_mgr->hw_mgr_lock, flags);
 	task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work);
 	if (!task) {
-		pr_err("no empty task\n");
+		CAM_ERR(CAM_ICP, "no empty task");
 		spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags);
 		return -ENOMEM;
 	}
@@ -424,12 +411,8 @@
 		return rc;
 
 	*qtbl = out;
-	ICP_DBG("kva = %llX\n", out.kva);
-	ICP_DBG("qtbl IOVA = %X\n", out.iova);
-	ICP_DBG("SMMU HDL = %X\n", out.smmu_hdl);
-	ICP_DBG("MEM HDL = %X\n", out.mem_handle);
-	ICP_DBG("length = %lld\n", out.len);
-	ICP_DBG("region = %d\n", out.region);
+	CAM_DBG(CAM_ICP, "kva: %llX, iova: %x, hdl: %x, len: %lld",
+		out.kva, out.iova, out.mem_handle, out.len);
 
 	return rc;
 }
@@ -451,9 +434,8 @@
 	icp_hw_mgr.hfi_mem.fw_buf.iova = iova;
 	icp_hw_mgr.hfi_mem.fw_buf.smmu_hdl = icp_hw_mgr.iommu_hdl;
 
-	ICP_DBG("kva = %llX\n", kvaddr);
-	ICP_DBG("IOVA = %llX\n", iova);
-	ICP_DBG("length = %zu\n", len);
+	CAM_DBG(CAM_ICP, "kva: %llX, iova: %llx, len: %zu",
+		kvaddr, iova, len);
 
 	return rc;
 }
@@ -466,43 +448,43 @@
 		CAM_SMMU_REGION_SHARED,
 		&icp_hw_mgr.hfi_mem.shmem);
 	if (rc) {
-		pr_err("Unable to get shared memory info\n");
+		CAM_ERR(CAM_ICP, "Unable to get shared memory info");
 		return rc;
 	}
 
 	rc = cam_icp_allocate_fw_mem();
 	if (rc) {
-		pr_err("Unable to allocate FW memory\n");
+		CAM_ERR(CAM_ICP, "Unable to allocate FW memory");
 		return rc;
 	}
 
 	rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.qtbl);
 	if (rc) {
-		pr_err("Unable to allocate qtbl memory\n");
+		CAM_ERR(CAM_ICP, "Unable to allocate qtbl memory");
 		goto qtbl_alloc_failed;
 	}
 
 	rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.cmd_q);
 	if (rc) {
-		pr_err("Unable to allocate cmd q memory\n");
+		CAM_ERR(CAM_ICP, "Unable to allocate cmd q memory");
 		goto cmd_q_alloc_failed;
 	}
 
 	rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.msg_q);
 	if (rc) {
-		pr_err("Unable to allocate msg q memory\n");
+		CAM_ERR(CAM_ICP, "Unable to allocate msg q memory");
 		goto msg_q_alloc_failed;
 	}
 
 	rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.dbg_q);
 	if (rc) {
-		pr_err("Unable to allocate dbg q memory\n");
+		CAM_ERR(CAM_ICP, "Unable to allocate dbg q memory");
 		goto dbg_q_alloc_failed;
 	}
 
 	rc = cam_icp_alloc_shared_mem(&icp_hw_mgr.hfi_mem.sec_heap);
 	if (rc) {
-		pr_err("Unable to allocate sec heap q memory\n");
+		CAM_ERR(CAM_ICP, "Unable to allocate sec heap q memory");
 		goto sec_heap_alloc_failed;
 	}
 
@@ -586,13 +568,13 @@
 	if (rc)
 		return rc;
 
-	ICP_DBG("fw_handle = %x ctx_data = %pK\n",
+	CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK",
 		ctx_data->fw_handle, ctx_data);
 	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
 			msecs_to_jiffies((timeout)));
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
-		ICP_DBG("FW timeout/err in abort handle command\n");
+		CAM_DBG(CAM_ICP, "FW timeout/err in abort handle command");
 	}
 
 	return rc;
@@ -640,13 +622,13 @@
 	if (rc)
 		return rc;
 
-	ICP_DBG("fw_handle = %x ctx_data = %pK\n",
+	CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK",
 		ctx_data->fw_handle, ctx_data);
 	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
 			msecs_to_jiffies((timeout)));
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
-		ICP_DBG("FW response timeout: %d\n", rc);
+		CAM_ERR(CAM_ICP, "FW response timeout: %d", rc);
 	}
 
 	return rc;
@@ -657,13 +639,12 @@
 	int i = 0;
 
 	if (ctx_id >= CAM_ICP_CTX_MAX) {
-		pr_err("ctx_id is wrong: %d\n", ctx_id);
+		CAM_ERR(CAM_ICP, "ctx_id is wrong: %d", ctx_id);
 		return -EINVAL;
 	}
 
 	mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
 	if (!hw_mgr->ctx_data[ctx_id].in_use) {
-		ICP_DBG("ctx is not in use: %d\n", ctx_id);
 		mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
 		return 0;
 	}
@@ -704,7 +685,7 @@
 	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
 
 	if ((!a5_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) {
-		pr_err("dev intfs are wrong, failed to close\n");
+		CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close");
 		return;
 	}
 
@@ -725,14 +706,14 @@
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	if ((hw_mgr->fw_download ==  false) && (!hw_mgr->ctxt_cnt)) {
-		ICP_DBG("hw mgr is already closed\n");
+		CAM_DBG(CAM_ICP, "hw mgr is already closed");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		return 0;
 	}
 
 	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
 	if (!a5_dev_intf) {
-		pr_err("a5_dev_intf is NULL\n");
+		CAM_ERR(CAM_ICP, "a5_dev_intf is NULL");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		return -EINVAL;
 	}
@@ -744,7 +725,7 @@
 		CAM_ICP_A5_SET_IRQ_CB,
 		&irq_cb, sizeof(irq_cb));
 	if (rc)
-		pr_err("deregister irq call back failed\n");
+		CAM_ERR(CAM_ICP, "deregister irq call back failed");
 
 	fw_buf_info.kva = 0;
 	fw_buf_info.iova = 0;
@@ -755,7 +736,7 @@
 		&fw_buf_info,
 		sizeof(fw_buf_info));
 	if (rc)
-		pr_err("nullify the fw buf failed\n");
+		CAM_ERR(CAM_ICP, "nullify the fw buf failed");
 
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 	for (i = 0; i < CAM_ICP_CTX_MAX; i++)
@@ -784,7 +765,7 @@
 	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
 
 	if ((!a5_dev_intf) || (!ipe0_dev_intf) || (!bps_dev_intf)) {
-		pr_err("dev intfs are wrong\n");
+		CAM_ERR(CAM_ICP, "dev intfs are wrong");
 		return -EINVAL;
 	}
 
@@ -877,30 +858,18 @@
 	hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva;
 	hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova;
 	hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len;
-	ICP_DBG("kva = %llX\n", hfi_mem.qtbl.kva);
-	ICP_DBG("IOVA = %X\n", hfi_mem.qtbl.iova);
-	ICP_DBG("length = %lld\n", hfi_mem.qtbl.len);
 
 	hfi_mem.cmd_q.kva = icp_hw_mgr.hfi_mem.cmd_q.kva;
 	hfi_mem.cmd_q.iova = icp_hw_mgr.hfi_mem.cmd_q.iova;
 	hfi_mem.cmd_q.len = icp_hw_mgr.hfi_mem.cmd_q.len;
-	ICP_DBG("kva = %llX\n", hfi_mem.cmd_q.kva);
-	ICP_DBG("IOVA = %X\n", hfi_mem.cmd_q.iova);
-	ICP_DBG("length = %lld\n", hfi_mem.cmd_q.len);
 
 	hfi_mem.msg_q.kva = icp_hw_mgr.hfi_mem.msg_q.kva;
 	hfi_mem.msg_q.iova = icp_hw_mgr.hfi_mem.msg_q.iova;
 	hfi_mem.msg_q.len = icp_hw_mgr.hfi_mem.msg_q.len;
-	ICP_DBG("kva = %llX\n", hfi_mem.msg_q.kva);
-	ICP_DBG("IOVA = %X\n", hfi_mem.msg_q.iova);
-	ICP_DBG("length = %lld\n", hfi_mem.msg_q.len);
 
 	hfi_mem.dbg_q.kva = icp_hw_mgr.hfi_mem.dbg_q.kva;
 	hfi_mem.dbg_q.iova = icp_hw_mgr.hfi_mem.dbg_q.iova;
 	hfi_mem.dbg_q.len = icp_hw_mgr.hfi_mem.dbg_q.len;
-	ICP_DBG("kva = %llX\n", hfi_mem.dbg_q.kva);
-	ICP_DBG("IOVA = %X\n",  hfi_mem.dbg_q.iova);
-	ICP_DBG("length = %lld\n", hfi_mem.dbg_q.len);
 
 	hfi_mem.sec_heap.kva = icp_hw_mgr.hfi_mem.sec_heap.kva;
 	hfi_mem.sec_heap.iova = icp_hw_mgr.hfi_mem.sec_heap.iova;
@@ -908,6 +877,7 @@
 
 	hfi_mem.shmem.iova = icp_hw_mgr.hfi_mem.shmem.iova_start;
 	hfi_mem.shmem.len = icp_hw_mgr.hfi_mem.shmem.iova_len;
+
 	return cam_hfi_init(0, &hfi_mem,
 		a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
 		hw_mgr->a5_debug);
@@ -922,7 +892,7 @@
 
 	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
 	reinit_completion(&hw_mgr->a5_complete);
-	ICP_DBG("Sending HFI init command\n");
+	CAM_DBG(CAM_ICP, "Sending HFI init command");
 	rc = a5_dev_intf->hw_ops.process_cmd(
 		a5_dev_intf->hw_priv,
 		CAM_ICP_A5_SEND_INIT,
@@ -930,14 +900,13 @@
 	if (rc)
 		return rc;
 
-	ICP_DBG("Wait for INIT DONE Message\n");
 	rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.a5_complete,
 		msecs_to_jiffies((timeout)));
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
-		ICP_DBG("FW response timed out %d\n", rc);
+		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 	}
-	ICP_DBG("Done Waiting for INIT DONE Message\n");
+	CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
 
 	return rc;
 }
@@ -950,13 +919,13 @@
 	int rc = 0;
 
 	if (!hw_mgr) {
-		pr_err("hw_mgr is NULL\n");
+		CAM_ERR(CAM_ICP, "hw_mgr is NULL");
 		return -EINVAL;
 	}
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	if (hw_mgr->fw_download) {
-		ICP_DBG("FW already downloaded\n");
+		CAM_DBG(CAM_ICP, "FW already downloaded");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		return rc;
 	}
@@ -998,7 +967,7 @@
 		NULL, 0);
 	hw_mgr->fw_download = true;
 	hw_mgr->ctxt_cnt = 0;
-	ICP_DBG("FW download done successfully\n");
+	CAM_DBG(CAM_ICP, "FW download done successfully");
 	if (!download_fw_args)
 		cam_icp_mgr_hw_close(hw_mgr, NULL);
 	return rc;
@@ -1040,19 +1009,17 @@
 
 	request_id = *(uint64_t *)config_args->priv;
 	hw_update_entries = config_args->hw_update_entries;
-	ICP_DBG("req_id = %lld %pK\n", request_id, config_args->priv);
+	CAM_DBG(CAM_ICP, "req_id = %lld %pK", request_id, config_args->priv);
 
 	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
 	if (!task) {
-		pr_err("no empty task\n");
+		CAM_ERR(CAM_ICP, "no empty task");
 		return -ENOMEM;
 	}
 
 	task_data = (struct hfi_cmd_work_data *)task->payload;
 	task_data->data = (void *)hw_update_entries->addr;
 	hfi_cmd = (struct hfi_cmd_ipebps_async *)hw_update_entries->addr;
-	ICP_DBG("request from hfi_cmd :%llu, hfi_cmd: %pK\n",
-		hfi_cmd->user_data2, hfi_cmd);
 	task_data->request_id = request_id;
 	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
 	task->process_cb = cam_icp_mgr_process_cmd;
@@ -1070,19 +1037,20 @@
 	struct cam_icp_hw_ctx_data *ctx_data = NULL;
 
 	if (!hw_mgr || !config_args) {
-		pr_err("Invalid arguments %pK %pK\n", hw_mgr, config_args);
+		CAM_ERR(CAM_ICP, "Invalid arguments %pK %pK",
+			hw_mgr, config_args);
 		return -EINVAL;
 	}
 
 	if (!config_args->num_hw_update_entries) {
-		pr_err("No hw update enteries are available\n");
+		CAM_ERR(CAM_ICP, "No hw update enteries are available");
 		return -EINVAL;
 	}
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	ctx_data = config_args->ctxt_to_hw_map;
 	if (!ctx_data->in_use) {
-		pr_err("ctx is not in use\n");
+		CAM_ERR(CAM_ICP, "ctx is not in use");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		rc = -EINVAL;
 		goto config_err;
@@ -1117,7 +1085,7 @@
 	hfi_cmd->user_data1 = (uint64_t)ctx_data;
 	hfi_cmd->user_data2 = request_id;
 
-	ICP_DBG("ctx_data : %pK, request_id :%lld cmd_buf %x\n",
+	CAM_DBG(CAM_ICP, "ctx_data : %pK, request_id :%lld cmd_buf %x",
 		(void *)ctx_data->context_priv, request_id,
 		fw_cmd_buf_iova_addr);
 
@@ -1126,32 +1094,18 @@
 
 static int cam_icp_mgr_pkt_validation(struct cam_packet *packet)
 {
-	ICP_DBG("packet header : opcode = %x size = %x",
-		packet->header.op_code,	packet->header.size);
-
-	ICP_DBG(" req_id = %x flags = %x\n",
-		(uint32_t)packet->header.request_id, packet->header.flags);
-
-	ICP_DBG("packet data : c_off = %x c_num = %x\n",
-		packet->cmd_buf_offset,	packet->num_cmd_buf);
-
-	ICP_DBG("io_off = %x io_num = %x p_off = %x p_num = %x %x %x\n",
-		packet->io_configs_offset, packet->num_io_configs,
-		packet->patch_offset, packet->num_patches,
-		packet->kmd_cmd_buf_index, packet->kmd_cmd_buf_offset);
-
 	if (((packet->header.op_code & 0xff) !=
 		CAM_ICP_OPCODE_IPE_UPDATE) &&
 		((packet->header.op_code & 0xff) !=
 		CAM_ICP_OPCODE_BPS_UPDATE)) {
-		pr_err("Invalid Opcode in pkt: %d\n",
+		CAM_ERR(CAM_ICP, "Invalid Opcode in pkt: %d",
 			packet->header.op_code & 0xff);
 		return -EINVAL;
 	}
 
 	if ((packet->num_cmd_buf > 1) || (!packet->num_patches) ||
 		(!packet->num_io_configs)) {
-		pr_err("wrong number of cmd/patch info: %u %u\n",
+		CAM_ERR(CAM_ICP, "wrong number of cmd/patch info: %u %u",
 			packet->num_cmd_buf, packet->num_patches);
 		return -EINVAL;
 	}
@@ -1170,18 +1124,15 @@
 
 	cmd_desc = (struct cam_cmd_buf_desc *)
 		((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
-	ICP_DBG("packet = %pK cmd_desc = %pK size = %lu\n",
-		(void *)packet, (void *)cmd_desc,
-		sizeof(struct cam_cmd_buf_desc));
 
 	rc = cam_mem_get_io_buf(cmd_desc->mem_handle,
 		hw_mgr->iommu_hdl, &iova_addr, &fw_cmd_buf_len);
 	if (rc) {
-		pr_err("unable to get src buf info for cmd buf: %x\n",
+		CAM_ERR(CAM_ICP, "unable to get src buf info for cmd buf: %x",
 			hw_mgr->iommu_hdl);
 		return rc;
 	}
-	ICP_DBG("cmd_buf desc cpu and iova address: %pK %zu\n",
+	CAM_DBG(CAM_ICP, "cmd_buf desc cpu and iova address: %pK %zu",
 		(void *)iova_addr, fw_cmd_buf_len);
 
 	*fw_cmd_buf_iova_addr = iova_addr;
@@ -1190,65 +1141,32 @@
 	return rc;
 }
 
-static int cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr,
+static void cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr,
 	struct cam_icp_hw_ctx_data *ctx_data,
 	struct cam_packet *packet,
 	struct cam_hw_prepare_update_args *prepare_args)
 {
-	int        rc = 0, i, j;
-	int32_t    sync_in_obj[CAM_ICP_IPE_IMAGE_MAX];
-	int32_t    merged_sync_in_obj;
+	int i, j, k;
 	struct cam_buf_io_cfg *io_cfg_ptr = NULL;
 
 	io_cfg_ptr = (struct cam_buf_io_cfg *) ((uint32_t *) &packet->payload +
 				packet->io_configs_offset/4);
-	ICP_DBG("packet = %pK io_cfg_ptr = %pK size = %lu\n",
-		(void *)packet, (void *)io_cfg_ptr,
-		sizeof(struct cam_buf_io_cfg));
-
 	prepare_args->num_out_map_entries = 0;
-	for (i = 0, j = 0; i < packet->num_io_configs; i++) {
+	prepare_args->num_in_map_entries = 0;
+
+	for (i = 0, j = 0, k = 0; i < packet->num_io_configs; i++) {
 		if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) {
-			ICP_DBG("direction is i : %d :%u\n",
-				i, io_cfg_ptr[i].direction);
-			ICP_DBG("fence is i : %d :%d\n",
-				i, io_cfg_ptr[i].fence);
-			continue;
+			prepare_args->in_map_entries[j++].sync_id =
+				io_cfg_ptr[i].fence;
+			prepare_args->num_in_map_entries++;
+		} else {
+			prepare_args->out_map_entries[k++].sync_id =
+				io_cfg_ptr[i].fence;
+			prepare_args->num_out_map_entries++;
 		}
-
-		prepare_args->out_map_entries[j++].sync_id =
-			io_cfg_ptr[i].fence;
-		prepare_args->num_out_map_entries++;
-		ICP_DBG(" out fence = %x index = %d\n", io_cfg_ptr[i].fence, i);
+		CAM_DBG(CAM_ICP, "dir[%d]: %u, fence: %u",
+			i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence);
 	}
-
-	for (i = 0, j = 0; i < packet->num_io_configs; i++) {
-		if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) {
-			sync_in_obj[j++] = io_cfg_ptr[i].fence;
-			ICP_DBG(" in fence = %x index = %d\n",
-					io_cfg_ptr[i].fence, i);
-		}
-	}
-
-	if (j == 1) {
-		merged_sync_in_obj = sync_in_obj[j - 1];
-	} else if (j > 1) {
-		rc = cam_sync_merge(&sync_in_obj[0], j, &merged_sync_in_obj);
-		if (rc) {
-			pr_err("unable to create in merged object: %d\n", rc);
-			return rc;
-		}
-	} else {
-		pr_err("no input fence provided %u\n", j);
-		return -EINVAL;
-	}
-
-	prepare_args->in_map_entries[0].sync_id = merged_sync_in_obj;
-	prepare_args->in_map_entries[0].resource_handle =
-		ctx_data->icp_dev_acquire_info->dev_type;
-	prepare_args->num_in_map_entries = 1;
-
-	return rc;
 }
 
 static int cam_icp_mgr_update_hfi_frame_process(
@@ -1263,7 +1181,7 @@
 	index = find_first_zero_bit(ctx_data->hfi_frame_process.bitmap,
 		ctx_data->hfi_frame_process.bits);
 	if (index < 0 || index >= CAM_FRAME_CMD_MAX) {
-		pr_err("request idx is wrong: %d\n", index);
+		CAM_ERR(CAM_ICP, "request idx is wrong: %d", index);
 		mutex_unlock(&ctx_data->hfi_frame_process.lock);
 		return -EINVAL;
 	}
@@ -1272,8 +1190,7 @@
 
 	ctx_data->hfi_frame_process.request_id[index] =
 		packet->header.request_id;
-	ICP_DBG("slot[%d]: %lld\n", index,
-		ctx_data->hfi_frame_process.request_id[index]);
+
 	*idx = index;
 
 	return 0;
@@ -1293,7 +1210,7 @@
 		prepare_hw_update_args;
 
 	if ((!prepare_args) || (!hw_mgr) || (!prepare_args->packet)) {
-		pr_err("Invalid args\n");
+		CAM_ERR(CAM_ICP, "Invalid args");
 		return -EINVAL;
 	}
 
@@ -1301,7 +1218,7 @@
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	if (!ctx_data->in_use) {
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
-		pr_err("ctx is not in use\n");
+		CAM_ERR(CAM_ICP, "ctx is not in use");
 		return -EINVAL;
 	}
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -1322,10 +1239,8 @@
 	if (rc)
 		return rc;
 
-	rc = cam_icp_mgr_process_io_cfg(hw_mgr, ctx_data,
+	cam_icp_mgr_process_io_cfg(hw_mgr, ctx_data,
 		packet, prepare_args);
-	if (rc)
-		return rc;
 
 	rc = cam_icp_mgr_update_hfi_frame_process(ctx_data, packet,
 		prepare_args, &idx);
@@ -1346,9 +1261,6 @@
 	prepare_args->num_hw_update_entries = 1;
 	prepare_args->hw_update_entries[0].addr = (uint64_t)hfi_cmd;
 	prepare_args->priv = &ctx_data->hfi_frame_process.request_id[idx];
-	ICP_DBG("slot : %d, hfi_cmd : %pK, request : %lld\n", idx,
-		(void *)hfi_cmd,
-		ctx_data->hfi_frame_process.request_id[idx]);
 
 	return rc;
 }
@@ -1385,14 +1297,14 @@
 	struct cam_icp_hw_ctx_data *ctx_data = NULL;
 
 	if (!release_hw || !hw_mgr) {
-		pr_err("Invalid args: %pK %pK\n", release_hw, hw_mgr);
+		CAM_ERR(CAM_ICP, "Invalid args: %pK %pK", release_hw, hw_mgr);
 		return -EINVAL;
 	}
 
 	ctx_data = release_hw->ctxt_to_hw_map;
 	ctx_id = ctx_data->ctx_id;
 	if (ctx_id < 0 || ctx_id >= CAM_ICP_CTX_MAX) {
-		pr_err("Invalid ctx id: %d\n", ctx_id);
+		CAM_ERR(CAM_ICP, "Invalid ctx id: %d", ctx_id);
 		return -EINVAL;
 	}
 
@@ -1430,8 +1342,7 @@
 		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
 
 	reinit_completion(&ctx_data->wait_complete);
-	ICP_DBG("Sending HFI_CMD_IPEBPS_ASYNC_COMMAND: opcode :%u\n",
-						ioconfig_cmd.opcode);
+
 	ioconfig_cmd.num_fw_handles = 1;
 	ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
 	ioconfig_cmd.payload.indirect = io_buf_addr;
@@ -1447,13 +1358,11 @@
 	if (rc)
 		return rc;
 
-	ICP_DBG("fw_hdl = %x ctx_data = %pK\n", ctx_data->fw_handle, ctx_data);
-
 	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
 			msecs_to_jiffies((timeout)));
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
-		ICP_DBG("FW response timed out %d\n", rc);
+		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 	}
 
 	return rc;
@@ -1477,9 +1386,6 @@
 	create_handle.pkt_type = HFI_CMD_IPEBPS_CREATE_HANDLE;
 	create_handle.handle_type = dev_type;
 	create_handle.user_data1 = (uint64_t)ctx_data;
-	ICP_DBG("%x %x %x %pK\n", create_handle.size,	create_handle.pkt_type,
-		create_handle.handle_type, (void *)create_handle.user_data1);
-	ICP_DBG("Sending HFI_CMD_IPEBPS_CREATE_HANDLE\n");
 
 	reinit_completion(&ctx_data->wait_complete);
 	task_data = (struct hfi_cmd_work_data *)task->payload;
@@ -1496,7 +1402,7 @@
 			msecs_to_jiffies((timeout)));
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
-		ICP_DBG("FW response timed out %d\n", rc);
+		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 	}
 
 	return rc;
@@ -1513,16 +1419,13 @@
 
 	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
 	if (!task) {
-		pr_err("No free task to send ping command\n");
+		CAM_ERR(CAM_ICP, "No free task to send ping command");
 		return -ENOMEM;
 	}
 
 	ping_pkt.size = sizeof(struct hfi_cmd_ping_pkt);
 	ping_pkt.pkt_type = HFI_CMD_SYS_PING;
 	ping_pkt.user_data = (uint64_t)ctx_data;
-	ICP_DBG("Sending HFI_CMD_SYS_PING\n");
-	ICP_DBG("%x %x %pK\n", ping_pkt.size,	ping_pkt.pkt_type,
-		(void *)ping_pkt.user_data);
 
 	init_completion(&ctx_data->wait_complete);
 	task_data = (struct hfi_cmd_work_data *)task->payload;
@@ -1540,7 +1443,7 @@
 			msecs_to_jiffies((timeout)));
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
-		ICP_DBG("FW response timed out %d\n", rc);
+		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 	}
 
 	return rc;
@@ -1561,7 +1464,7 @@
 		return -EFAULT;
 
 	if (icp_dev_acquire_info.num_out_res > ICP_MAX_OUTPUT_SUPPORTED) {
-		pr_err("num of out resources exceeding : %u\n",
+		CAM_ERR(CAM_ICP, "num of out resources exceeding : %u",
 			icp_dev_acquire_info.num_out_res);
 		return -EINVAL;
 	}
@@ -1580,7 +1483,7 @@
 		return -EFAULT;
 	}
 
-	ICP_DBG("%x %x %x %x %x %x %x\n",
+	CAM_DBG(CAM_ICP, "%x %x %x %x %x %x %x",
 		ctx_data->icp_dev_acquire_info->dev_type,
 		ctx_data->icp_dev_acquire_info->in_res.format,
 		ctx_data->icp_dev_acquire_info->in_res.width,
@@ -1591,7 +1494,7 @@
 
 	p_icp_out = ctx_data->icp_dev_acquire_info->out_res;
 	for (i = 0; i < ctx_data->icp_dev_acquire_info->num_out_res; i++)
-		ICP_DBG("out[i] %x %x %x %x\n",
+		CAM_DBG(CAM_ICP, "out[i] %x %x %x %x",
 			p_icp_out[i].format,
 			p_icp_out[i].width,
 			p_icp_out[i].height,
@@ -1612,20 +1515,21 @@
 	struct cam_icp_acquire_dev_info *icp_dev_acquire_info;
 
 	if ((!hw_mgr_priv) || (!acquire_hw_args)) {
-		pr_err("Invalid params: %pK %pK\n", hw_mgr_priv,
+		CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", hw_mgr_priv,
 			acquire_hw_args);
 		return -EINVAL;
 	}
 
 	if (args->num_acq > 1) {
-		pr_err("number of resources are wrong: %u\n", args->num_acq);
+		CAM_ERR(CAM_ICP, "number of resources are wrong: %u",
+			args->num_acq);
 		return -EINVAL;
 	}
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	ctx_id = cam_icp_mgr_get_free_ctx(hw_mgr);
 	if (ctx_id >= CAM_ICP_CTX_MAX) {
-		pr_err("No free ctx space in hw_mgr\n");
+		CAM_ERR(CAM_ICP, "No free ctx space in hw_mgr");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		return -ENOSPC;
 	}
@@ -1655,13 +1559,13 @@
 			&io_buf_addr, &io_buf_size);
 
 	if (rc) {
-		pr_err("unable to get src buf info from io desc\n");
+		CAM_ERR(CAM_ICP, "unable to get src buf info from io desc");
 		goto get_io_buf_failed;
 	}
-	ICP_DBG("io_config_cmd_handle : %d\n",
-		icp_dev_acquire_info->io_config_cmd_handle);
-	ICP_DBG("io_buf_addr : %pK\n", (void *)io_buf_addr);
-	ICP_DBG("io_buf_size : %zu\n", io_buf_size);
+
+	CAM_DBG(CAM_ICP, "hdl: %d, addr: %pK, size: %zu",
+		icp_dev_acquire_info->io_config_cmd_handle,
+		(void *)io_buf_addr, io_buf_size);
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	if (!hw_mgr->ctxt_cnt) {
@@ -1675,20 +1579,20 @@
 
 	rc = cam_icp_mgr_send_ping(ctx_data);
 	if (rc) {
-		pr_err("ping ack not received\n");
+		CAM_ERR(CAM_ICP, "ping ack not received");
 		goto send_ping_failed;
 	}
 
 	rc = cam_icp_mgr_create_handle(icp_dev_acquire_info->dev_type,
 		ctx_data);
 	if (rc) {
-		pr_err("create handle failed\n");
+		CAM_ERR(CAM_ICP, "create handle failed");
 		goto create_handle_failed;
 	}
 
 	rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr);
 	if (rc) {
-		pr_err("IO Config command failed\n");
+		CAM_ERR(CAM_ICP, "IO Config command failed");
 		goto ioconfig_failed;
 	}
 
@@ -1711,7 +1615,7 @@
 		icp_dev_acquire_info, sizeof(struct cam_icp_acquire_dev_info)))
 		goto copy_to_user_failed;
 
-	ICP_DBG("scratch mem size = %x fw_handle = %x\n",
+	CAM_DBG(CAM_ICP, "scratch size = %x fw_handle = %x",
 			(unsigned int)icp_dev_acquire_info->scratch_mem_size,
 			(unsigned int)ctx_data->fw_handle);
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
@@ -1744,14 +1648,15 @@
 	struct cam_query_cap_cmd *query_cap = hw_caps_args;
 
 	if ((!hw_mgr_priv) || (!hw_caps_args)) {
-		pr_err("Invalid params: %pK %pK\n", hw_mgr_priv, hw_caps_args);
+		CAM_ERR(CAM_ICP, "Invalid params: %pK %pK",
+			hw_mgr_priv, hw_caps_args);
 		return -EINVAL;
 	}
 
 	if (copy_from_user(&icp_hw_mgr.icp_caps,
 		(void __user *)query_cap->caps_handle,
 		sizeof(struct cam_icp_query_cap_cmd))) {
-		pr_err("copy_from_user failed\n");
+		CAM_ERR(CAM_ICP, "copy_from_user failed");
 		return -EFAULT;
 	}
 
@@ -1765,7 +1670,7 @@
 
 	if (copy_to_user((void __user *)query_cap->caps_handle,
 		&icp_hw_mgr.icp_caps, sizeof(struct cam_icp_query_cap_cmd))) {
-		pr_err("copy_to_user failed\n");
+		CAM_ERR(CAM_ICP, "copy_to_user failed");
 		rc = -EFAULT;
 		goto hfi_get_caps_fail;
 	}
@@ -1788,7 +1693,7 @@
 
 	hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl;
 	if (!of_node || !hw_mgr_intf) {
-		pr_err("Invalid args of_node %pK hw_mgr %pK\n",
+		CAM_ERR(CAM_ICP, "Invalid args of_node %pK hw_mgr %pK",
 			of_node, hw_mgr_intf);
 		return -EINVAL;
 	}
@@ -1811,7 +1716,7 @@
 	/* Get number of device objects */
 	count = of_property_count_strings(of_node, "compat-hw-name");
 	if (!count) {
-		pr_err("no compat hw found in dev tree, count = %d\n", count);
+		CAM_ERR(CAM_ICP, "no compat hw found, count = %d", count);
 		rc = -EINVAL;
 		goto num_dev_failed;
 	}
@@ -1819,7 +1724,7 @@
 	/* Get number of a5 device nodes and a5 mem allocation */
 	rc = of_property_read_u32(of_node, "num-a5", &num_dev);
 	if (rc) {
-		pr_err("getting num of a5 failed\n");
+		CAM_ERR(CAM_ICP, "getting num of a5 failed");
 		goto num_dev_failed;
 	}
 
@@ -1833,7 +1738,7 @@
 	/* Get number of ipe device nodes and ipe mem allocation */
 	rc = of_property_read_u32(of_node, "num-ipe", &num_dev);
 	if (rc) {
-		pr_err("getting number of ipe dev nodes failed\n");
+		CAM_ERR(CAM_ICP, "getting number of ipe dev nodes failed");
 		goto num_ipe_failed;
 	}
 
@@ -1847,7 +1752,7 @@
 	/* Get number of bps device nodes and bps mem allocation */
 	rc = of_property_read_u32(of_node, "num-bps", &num_dev);
 	if (rc) {
-		pr_err("read num bps devices failed\n");
+		CAM_ERR(CAM_ICP, "read num bps devices failed");
 		goto num_bps_failed;
 	}
 	icp_hw_mgr.devices[CAM_ICP_DEV_BPS] = kzalloc(
@@ -1861,20 +1766,20 @@
 		rc = of_property_read_string_index(of_node, "compat-hw-name",
 			i, &name);
 		if (rc) {
-			pr_err("getting dev object name failed\n");
+			CAM_ERR(CAM_ICP, "getting dev object name failed");
 			goto compat_hw_name_failed;
 		}
 
 		child_node = of_find_node_by_name(NULL, name);
 		if (!child_node) {
-			pr_err("error! Cannot find node in dtsi %s\n", name);
+			CAM_ERR(CAM_ICP, "Cannot find node in dtsi %s", name);
 			rc = -ENODEV;
 			goto compat_hw_name_failed;
 		}
 
 		child_pdev = of_find_device_by_node(child_node);
 		if (!child_pdev) {
-			pr_err("failed to find device on bus %s\n",
+			CAM_ERR(CAM_ICP, "failed to find device on bus %s",
 				child_node->name);
 			rc = -ENODEV;
 			of_node_put(child_node);
@@ -1884,13 +1789,10 @@
 		child_dev_intf = (struct cam_hw_intf *)platform_get_drvdata(
 			child_pdev);
 		if (!child_dev_intf) {
-			pr_err("no child device\n");
+			CAM_ERR(CAM_ICP, "no child device");
 			of_node_put(child_node);
 			goto compat_hw_name_failed;
 		}
-		ICP_DBG("child_intf %pK\n", child_dev_intf);
-		ICP_DBG("child type %d index %d\n",	child_dev_intf->hw_type,
-				child_dev_intf->hw_idx);
 
 		icp_hw_mgr.devices[child_dev_intf->hw_type]
 			[child_dev_intf->hw_idx] = child_dev_intf;
@@ -1900,27 +1802,27 @@
 
 	rc = cam_smmu_get_handle("icp", &icp_hw_mgr.iommu_hdl);
 	if (rc) {
-		pr_err("icp get iommu handle failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "icp get iommu handle failed: %d", rc);
 		goto compat_hw_name_failed;
 	}
 
 	rc = cam_smmu_ops(icp_hw_mgr.iommu_hdl, CAM_SMMU_ATTACH);
 	if (rc) {
-		pr_err("icp attach failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "icp attach failed: %d", rc);
 		goto icp_attach_failed;
 	}
 
 	rc = cam_req_mgr_workq_create("icp_command_queue", ICP_WORKQ_NUM_TASK,
 		&icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ);
 	if (rc) {
-		pr_err("unable to create a worker\n");
+		CAM_ERR(CAM_ICP, "unable to create a worker");
 		goto cmd_work_failed;
 	}
 
 	rc = cam_req_mgr_workq_create("icp_message_queue", ICP_WORKQ_NUM_TASK,
 		&icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ);
 	if (rc) {
-		pr_err("unable to create a worker\n");
+		CAM_ERR(CAM_ICP, "unable to create a worker");
 		goto msg_work_failed;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
index 99b45aa..b7b3d7b 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "IPE-CORE %s:%d " fmt, __func__, __LINE__
-
 #include <linux/of.h>
 #include <linux/debugfs.h>
 #include <linux/videodev2.h>
@@ -30,6 +28,7 @@
 #include "cam_ipe_hw_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
+#include "cam_debug_util.h"
 
 static int cam_ipe_caps_vote(struct cam_ipe_device_core_info *core_info,
 	struct cam_icp_cpas_vote *cpas_vote)
@@ -44,7 +43,7 @@
 			&cpas_vote->axi_vote);
 
 	if (rc)
-		pr_err("cpas vote is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc);
 
 	return rc;
 }
@@ -59,7 +58,7 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
@@ -67,7 +66,8 @@
 	core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
 
 	if ((!soc_info) || (!core_info)) {
-		pr_err("soc_info = %pK core_info = %pK\n", soc_info, core_info);
+		CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
 		return -EINVAL;
 	}
 
@@ -79,16 +79,16 @@
 	rc = cam_cpas_start(core_info->cpas_handle,
 		&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
 	if (rc) {
-		pr_err("cpass start failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "cpass start failed: %d", rc);
 		return rc;
 	}
 	core_info->cpas_start = true;
 
 	rc = cam_ipe_enable_soc_resources(soc_info);
 	if (rc) {
-		pr_err("soc enable is failed : %d\n", rc);
+		CAM_ERR(CAM_ICP, "soc enable is failed : %d", rc);
 		if (cam_cpas_stop(core_info->cpas_handle))
-			pr_err("cpas stop is failed\n");
+			CAM_ERR(CAM_ICP, "cpas stop is failed");
 		else
 			core_info->cpas_start = false;
 	}
@@ -105,24 +105,25 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid cam_dev_info\n");
+		CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
 		return -EINVAL;
 	}
 
 	soc_info = &ipe_dev->soc_info;
 	core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
 	if ((!soc_info) || (!core_info)) {
-		pr_err("soc_info = %pK core_info = %pK\n", soc_info, core_info);
+		CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
 		return -EINVAL;
 	}
 
 	rc = cam_ipe_disable_soc_resources(soc_info);
 	if (rc)
-		pr_err("soc disable is failed : %d\n", rc);
+		CAM_ERR(CAM_ICP, "soc disable is failed : %d", rc);
 
 	if (core_info->cpas_start) {
 		if (cam_cpas_stop(core_info->cpas_handle))
-			pr_err("cpas stop is failed\n");
+			CAM_ERR(CAM_ICP, "cpas stop is failed");
 		else
 			core_info->cpas_start = false;
 	}
@@ -140,12 +141,12 @@
 	int rc = 0;
 
 	if (!device_priv) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_ICP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	if (cmd_type >= CAM_ICP_IPE_CMD_MAX) {
-		pr_err("Invalid command : %x\n", cmd_type);
+		CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c
index 0efb1de..d95246f 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c
@@ -23,9 +23,7 @@
 #include "cam_icp_hw_intf.h"
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 struct cam_ipe_device_hw_info cam_ipe_hw_info = {
 	.reserved = 0,
@@ -47,7 +45,7 @@
 
 	rc = cam_cpas_register_client(&cpas_register_params);
 	if (rc < 0) {
-		pr_err("cam_cpas_register_client is failed: %d\n", rc);
+		CAM_ERR(CAM_ICP, "failed: %d", rc);
 		return rc;
 	}
 	core_info->cpas_handle = cpas_register_params.client_handle;
@@ -83,7 +81,7 @@
 	ipe_dev_intf->hw_ops.process_cmd = cam_ipe_process_cmd;
 	ipe_dev_intf->hw_type = CAM_ICP_DEV_IPE;
 
-	pr_debug("%s: type %d index %d\n", __func__,
+	CAM_DBG(CAM_ICP, "type %d index %d",
 		ipe_dev_intf->hw_type,
 		ipe_dev_intf->hw_idx);
 
@@ -101,7 +99,7 @@
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
 	if (!match_dev) {
-		pr_debug("%s: No ipe hardware info\n", __func__);
+		CAM_DBG(CAM_ICP, "No ipe hardware info");
 		kfree(ipe_dev->core_info);
 		kfree(ipe_dev);
 		kfree(ipe_dev_intf);
@@ -114,14 +112,14 @@
 	rc = cam_ipe_init_soc_resources(&ipe_dev->soc_info, cam_ipe_irq,
 		ipe_dev);
 	if (rc < 0) {
-		pr_err("%s: failed to init_soc\n", __func__);
+		CAM_ERR(CAM_ICP, "failed to init_soc");
 		kfree(ipe_dev->core_info);
 		kfree(ipe_dev);
 		kfree(ipe_dev_intf);
 		return rc;
 	}
 
-	pr_debug("cam_ipe_init_soc_resources : %pK\n",
+	CAM_DBG(CAM_ICP, "cam_ipe_init_soc_resources : %pK",
 		(void *)&ipe_dev->soc_info);
 	rc = cam_ipe_register_cpas(&ipe_dev->soc_info,
 		core_info, ipe_dev_intf->hw_idx);
@@ -136,7 +134,7 @@
 	spin_lock_init(&ipe_dev->hw_lock);
 	init_completion(&ipe_dev->hw_complete);
 
-	pr_debug("%s: IPE%d probe successful\n", __func__,
+	CAM_DBG(CAM_ICP, "IPE%d probe successful",
 		ipe_dev_intf->hw_idx);
 
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
index e691dad..26dd6d2 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
@@ -18,9 +18,7 @@
 #include <media/cam_icp.h>
 #include "ipe_soc.h"
 #include "cam_soc_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static int cam_ipe_get_dt_properties(struct cam_hw_soc_info *soc_info)
 {
@@ -28,7 +26,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0)
-		pr_err("get ipe dt prop is failed\n");
+		CAM_ERR(CAM_ICP, "get ipe dt prop is failed");
 
 	return rc;
 }
@@ -69,7 +67,7 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, false);
 	if (rc) {
-		pr_err("%s: enable platform failed\n", __func__);
+		CAM_ERR(CAM_ICP, "enable platform failed");
 		return rc;
 	}
 
@@ -82,7 +80,7 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
 	if (rc)
-		pr_err("%s: enable platform failed\n", __func__);
+		CAM_ERR(CAM_ICP, "enable platform failed");
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 766ea89..a6f60f5 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -22,9 +22,7 @@
 #include "cam_sync_api.h"
 #include "cam_req_mgr_dev.h"
 #include "cam_trace.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data)
 {
@@ -57,7 +55,7 @@
 	case CAM_ISP_HW_EVENT_DONE:
 		break;
 	default:
-		CDBG("%s: Invalid Event Type %d\n", __func__, evt_id);
+		CAM_DBG(CAM_ISP, "Invalid Event Type %d", evt_id);
 	}
 
 	return ts;
@@ -75,11 +73,11 @@
 	struct cam_context *ctx = ctx_isp->base;
 
 	if (list_empty(&ctx->active_req_list)) {
-		CDBG("Buf done with no active request!\n");
+		CAM_DBG(CAM_ISP, "Buf done with no active request!");
 		goto end;
 	}
 
-	CDBG("%s: Enter with bubble_state %d\n", __func__, bubble_state);
+	CAM_DBG(CAM_ISP, "Enter with bubble_state %d", bubble_state);
 
 	req = list_first_entry(&ctx->active_req_list,
 			struct cam_ctx_request, list);
@@ -95,29 +93,30 @@
 		}
 
 		if (j == req_isp->num_fence_map_out) {
-			pr_err("Can not find matching lane handle 0x%x!\n",
+			CAM_ERR(CAM_ISP,
+				"Can not find matching lane handle 0x%x!",
 				done->resource_handle[i]);
 			rc = -EINVAL;
 			continue;
 		}
 
 		if (!bubble_state) {
-			CDBG("%s: Sync with success: fd 0x%x\n", __func__,
+			CAM_DBG(CAM_ISP, "Sync with success: fd 0x%x",
 				   req_isp->fence_map_out[j].sync_id);
 			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
 				CAM_SYNC_STATE_SIGNALED_SUCCESS);
 			if (rc)
-				pr_err("%s: Sync failed with rc = %d\n",
-					__func__, rc);
+				CAM_ERR(CAM_ISP, "Sync failed with rc = %d",
+					 rc);
 
 		} else if (!req_isp->bubble_report) {
-			CDBG("%s: Sync with failure: fd 0x%x\n", __func__,
+			CAM_DBG(CAM_ISP, "Sync with failure: fd 0x%x",
 				   req_isp->fence_map_out[j].sync_id);
 			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
 				CAM_SYNC_STATE_SIGNALED_ERROR);
 			if (rc)
-				pr_err("%s: Sync failed with rc = %d\n",
-					__func__, rc);
+				CAM_ERR(CAM_ISP, "Sync failed with rc = %d",
+					 rc);
 		} else {
 			/*
 			 * Ignore the buffer done if bubble detect is on
@@ -130,7 +129,7 @@
 			continue;
 		}
 
-		CDBG("%s: req %lld, reset sync id 0x%x\n", __func__,
+		CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x",
 			   req->request_id,
 			   req_isp->fence_map_out[j].sync_id);
 		req_isp->num_acked++;
@@ -141,8 +140,9 @@
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->free_req_list);
 		ctx_isp->active_req_cnt--;
-		CDBG("%s: Move active request %lld to free list(cnt = %d)\n",
-			__func__, req->request_id, ctx_isp->active_req_cnt);
+		CAM_DBG(CAM_ISP,
+			"Move active request %lld to free list(cnt = %d)",
+			 req->request_id, ctx_isp->active_req_cnt);
 	}
 
 end:
@@ -162,15 +162,17 @@
 	req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
 	req_msg.u.frame_msg.sof_status = sof_event_status;
 
-	CDBG("%s: request id:%lld frame number:%lld SOF time stamp:0x%llx\n",
-		__func__, request_id, ctx_isp->frame_id,
+	CAM_DBG(CAM_ISP,
+		"request id:%lld frame number:%lld SOF time stamp:0x%llx",
+		 request_id, ctx_isp->frame_id,
 		ctx_isp->sof_timestamp_val);
-	CDBG("%s sof status:%d\n", __func__, sof_event_status);
+	CAM_DBG(CAM_ISP, " sof status:%d", sof_event_status);
 
 	if (cam_req_mgr_notify_frame_message(&req_msg,
 		V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT))
-		pr_err("%s: Error in notifying the sof time for req id:%lld\n",
-				__func__, request_id);
+		CAM_ERR(CAM_ISP,
+			"Error in notifying the sof time for req id:%lld",
+			request_id);
 }
 
 static int __cam_isp_ctx_reg_upd_in_activated_state(
@@ -182,7 +184,7 @@
 	struct cam_isp_ctx_req  *req_isp;
 
 	if (list_empty(&ctx->pending_req_list)) {
-		pr_err("Reg upd ack with no pending request\n");
+		CAM_ERR(CAM_ISP, "Reg upd ack with no pending request");
 		goto end;
 	}
 	req = list_first_entry(&ctx->pending_req_list,
@@ -193,13 +195,14 @@
 	if (req_isp->num_fence_map_out != 0) {
 		list_add_tail(&req->list, &ctx->active_req_list);
 		ctx_isp->active_req_cnt++;
-		CDBG("%s: move request %lld to active list(cnt = %d)\n",
-			__func__, req->request_id, ctx_isp->active_req_cnt);
+		CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+			 req->request_id, ctx_isp->active_req_cnt);
 	} else {
 		/* no io config, so the request is completed. */
 		list_add_tail(&req->list, &ctx->free_req_list);
-		CDBG("%s: move active request %lld to free list(cnt = %d)\n",
-			__func__, req->request_id, ctx_isp->active_req_cnt);
+		CAM_DBG(CAM_ISP,
+			"move active request %lld to free list(cnt = %d)",
+			 req->request_id, ctx_isp->active_req_cnt);
 	}
 
 	/*
@@ -207,7 +210,7 @@
 	 * state so change substate here.
 	 */
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
-	CDBG("%s: next substate %d\n", __func__, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
 
 end:
 	return rc;
@@ -235,7 +238,7 @@
 		notify.frame_id = ctx_isp->frame_id;
 
 		ctx->ctx_crm_intf->notify_sof(&notify);
-		CDBG("%s: Notify CRM  SOF frame %lld\n", __func__,
+		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
 			ctx_isp->frame_id);
 
 		list_for_each_entry(req, &ctx->active_req_list, list) {
@@ -249,7 +252,7 @@
 		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
 			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
 	} else {
-		pr_err("%s: Can not notify SOF to CRM\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
 	}
 
 	return 0;
@@ -263,13 +266,13 @@
 	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
 
 	if (!evt_data) {
-		pr_err("%s: in valid sof event data\n", __func__);
+		CAM_ERR(CAM_ISP, "in valid sof event data");
 		return -EINVAL;
 	}
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
-	CDBG("%s: frame id: %lld time stamp:0x%llx\n", __func__,
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
 	return rc;
@@ -284,7 +287,7 @@
 	struct cam_context *ctx = ctx_isp->base;
 
 	if (ctx->state != CAM_CTX_ACTIVATED) {
-		CDBG("%s: invalid RUP\n", __func__);
+		CAM_DBG(CAM_ISP, "invalid RUP");
 		goto end;
 	}
 
@@ -303,8 +306,9 @@
 			/* need to handle the buf done */
 			list_add_tail(&req->list, &ctx->active_req_list);
 			ctx_isp->active_req_cnt++;
-			CDBG("%s: move request %lld to active list(cnt = %d)\n",
-				__func__, req->request_id,
+			CAM_DBG(CAM_ISP,
+				"move request %lld to active list(cnt = %d)",
+				 req->request_id,
 				ctx_isp->active_req_cnt);
 			ctx_isp->substate_activated =
 				CAM_ISP_CTX_ACTIVATED_EPOCH;
@@ -327,7 +331,7 @@
 		 * If no pending req in epoch, this is an error case.
 		 * The recovery is to go back to sof state
 		 */
-		pr_err("%s: No pending request\n", __func__);
+		CAM_ERR(CAM_ISP, "No pending request");
 		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
 
 		/* Send SOF event as empty frame*/
@@ -341,7 +345,7 @@
 		list);
 	req_isp = (struct cam_isp_ctx_req *)req->req_priv;
 
-	CDBG("Report Bubble flag %d\n", req_isp->bubble_report);
+	CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
 	if (req_isp->bubble_report && ctx->ctx_crm_intf &&
 		ctx->ctx_crm_intf->notify_err) {
 		struct cam_req_mgr_error_notify notify;
@@ -351,7 +355,7 @@
 		notify.req_id = req->request_id;
 		notify.error = CRM_KMD_ERR_BUBBLE;
 		ctx->ctx_crm_intf->notify_err(&notify);
-		CDBG("%s: Notify CRM about Bubble frame %lld\n", __func__,
+		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
 			ctx_isp->frame_id);
 	} else {
 		/*
@@ -361,8 +365,8 @@
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->active_req_list);
 		ctx_isp->active_req_cnt++;
-		CDBG("%s: move request %lld to active list(cnt = %d)\n",
-			__func__, req->request_id, ctx_isp->active_req_cnt);
+		CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+			 req->request_id, ctx_isp->active_req_cnt);
 		req_isp->bubble_report = 0;
 	}
 
@@ -371,7 +375,7 @@
 		CAM_REQ_MGR_SOF_EVENT_ERROR);
 
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
-	CDBG("%s: next substate %d\n", __func__,
+	CAM_DBG(CAM_ISP, "next substate %d",
 		ctx_isp->substate_activated);
 end:
 	return 0;
@@ -398,7 +402,7 @@
 	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
 
 	if (!evt_data) {
-		pr_err("%s: in valid sof event data\n", __func__);
+		CAM_ERR(CAM_ISP, "in valid sof event data");
 		return -EINVAL;
 	}
 
@@ -408,9 +412,9 @@
 	if (list_empty(&ctx->active_req_list))
 		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
 	else
-		CDBG("%s: Still need to wait for the buf done\n", __func__);
+		CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
 
-	CDBG("%s: next substate %d\n", __func__,
+	CAM_DBG(CAM_ISP, "next substate %d",
 		ctx_isp->substate_activated);
 
 	return rc;
@@ -456,7 +460,7 @@
 		 * If no pending req in epoch, this is an error case.
 		 * Just go back to the bubble state.
 		 */
-		pr_err("%s: No pending request.\n", __func__);
+		CAM_ERR(CAM_ISP, "No pending request.");
 		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
 			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
 
@@ -477,7 +481,7 @@
 		notify.req_id = req->request_id;
 		notify.error = CRM_KMD_ERR_BUBBLE;
 		ctx->ctx_crm_intf->notify_err(&notify);
-		CDBG("%s: Notify CRM about Bubble frame %lld\n", __func__,
+		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
 			ctx_isp->frame_id);
 	} else {
 		/*
@@ -487,8 +491,8 @@
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->active_req_list);
 		ctx_isp->active_req_cnt++;
-		CDBG("%s: move request %lld to active list(cnt = %d)\n",
-			__func__, req->request_id, ctx_isp->active_req_cnt);
+		CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+			 req->request_id, ctx_isp->active_req_cnt);
 		req_isp->bubble_report = 0;
 	}
 
@@ -497,7 +501,7 @@
 		CAM_REQ_MGR_SOF_EVENT_ERROR);
 
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
-	CDBG("%s: next substate %d\n", __func__, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
 end:
 	return 0;
 }
@@ -526,7 +530,7 @@
 
 	uint32_t error_type = error_event_data->error_type;
 
-	CDBG("%s: Enter error_type = %d\n", __func__, error_type);
+	CAM_DBG(CAM_ISP, "Enter error_type = %d", error_type);
 	if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) ||
 		(error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW))
 		notify.error = CRM_KMD_ERR_FATAL;
@@ -538,7 +542,7 @@
 	 */
 
 	if (list_empty(&ctx->active_req_list)) {
-		pr_err("handling error with no active request!\n");
+		CAM_ERR(CAM_ISP, "handling error with no active request");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -552,10 +556,10 @@
 		notify.req_id = req->request_id;
 
 		ctx->ctx_crm_intf->notify_err(&notify);
-		pr_err("%s: Notify CRM about ERROR frame %lld\n", __func__,
+		CAM_ERR(CAM_ISP, "Notify CRM about ERROR frame %lld",
 			ctx_isp->frame_id);
 	} else {
-		pr_err("%s: Can not notify ERRROR to CRM\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not notify ERRROR to CRM");
 		rc = -EFAULT;
 	}
 
@@ -564,7 +568,7 @@
 	/* might need to check if active list is empty */
 
 end:
-	CDBG("%s: Exit\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -641,8 +645,8 @@
 	struct cam_hw_config_args        cfg;
 
 	if (list_empty(&ctx->pending_req_list)) {
-		pr_err("%s: No available request for Apply id %lld\n",
-			__func__, apply->request_id);
+		CAM_ERR(CAM_ISP, "No available request for Apply id %lld",
+			apply->request_id);
 		rc = -EFAULT;
 		goto end;
 	}
@@ -655,8 +659,9 @@
 	 */
 	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
 	if (ctx_isp->active_req_cnt >=  2) {
-		CDBG("%s: Reject apply request due to congestion(cnt = %d)\n",
-				__func__, ctx_isp->active_req_cnt);
+		CAM_DBG(CAM_ISP,
+			"Reject apply request due to congestion(cnt = %d)",
+			ctx_isp->active_req_cnt);
 		rc = -EFAULT;
 		goto end;
 	}
@@ -673,7 +678,7 @@
 		goto end;
 	}
 
-	CDBG("%s: Apply request %lld\n", __func__, req->request_id);
+	CAM_DBG(CAM_ISP, "Apply request %lld", req->request_id);
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 
 	req_isp->bubble_report = apply->report_if_bubble;
@@ -684,11 +689,11 @@
 
 	rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
 	if (rc) {
-		pr_err("%s: Can not apply the configuration\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not apply the configuration");
 	} else {
 		spin_lock_bh(&ctx->lock);
 		ctx_isp->substate_activated = next_state;
-		CDBG("%s: new state %d\n", __func__, next_state);
+		CAM_DBG(CAM_ISP, "new state %d", next_state);
 		spin_unlock_bh(&ctx->lock);
 	}
 end:
@@ -702,11 +707,11 @@
 	struct cam_isp_context *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
 
-	CDBG("%s: current substate %d\n", __func__,
+	CAM_DBG(CAM_ISP, "current substate %d",
 		ctx_isp->substate_activated);
 	rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
 		CAM_ISP_CTX_ACTIVATED_APPLIED);
-	CDBG("%s: new substate %d\n", __func__, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
 
 	return rc;
 }
@@ -718,11 +723,11 @@
 	struct cam_isp_context *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
 
-	CDBG("%s: current substate %d\n", __func__,
+	CAM_DBG(CAM_ISP, "current substate %d",
 		ctx_isp->substate_activated);
 	rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
 		CAM_ISP_CTX_ACTIVATED_APPLIED);
-	CDBG("%s: new substate %d\n", __func__, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
 
 	return rc;
 }
@@ -734,11 +739,11 @@
 	struct cam_isp_context *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
 
-	CDBG("%s: current substate %d\n", __func__,
+	CAM_DBG(CAM_ISP, "current substate %d",
 		ctx_isp->substate_activated);
 	rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
 		CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED);
-	CDBG("%s: new substate %d\n", __func__, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
 
 	return rc;
 }
@@ -755,7 +760,7 @@
 	spin_lock(&ctx->lock);
 	if (list_empty(req_list)) {
 		spin_unlock(&ctx->lock);
-		CDBG("%s: request list is empty\n", __func__);
+		CAM_DBG(CAM_ISP, "request list is empty");
 		return 0;
 	}
 
@@ -768,15 +773,15 @@
 		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 		for (i = 0; i < req_isp->num_fence_map_out; i++) {
 			if (req_isp->fence_map_out[i].sync_id != -1) {
-				CDBG("%s: Flush req 0x%llx, fence %d\n",
-					__func__, req->request_id,
+				CAM_DBG(CAM_ISP, "Flush req 0x%llx, fence %d",
+					 req->request_id,
 					req_isp->fence_map_out[i].sync_id);
 				rc = cam_sync_signal(
 					req_isp->fence_map_out[i].sync_id,
 					CAM_SYNC_STATE_SIGNALED_ERROR);
 				if (rc)
-					pr_err_ratelimited("%s: signal fence failed\n",
-						__func__);
+					CAM_ERR_RATE_LIMIT(CAM_ISP,
+						"signal fence failed\n");
 				req_isp->fence_map_out[i].sync_id = -1;
 			}
 		}
@@ -792,8 +797,9 @@
 
 	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ &&
 		!cancel_req_id_found)
-		CDBG("%s:Flush request id:%lld is not found in the list\n",
-			__func__, flush_req->req_id);
+		CAM_DBG(CAM_ISP,
+			"Flush request id:%lld is not found in the list",
+			flush_req->req_id);
 
 	return 0;
 }
@@ -804,10 +810,10 @@
 {
 	int rc = 0;
 
-	CDBG("%s: try to flush pending list\n", __func__);
+	CAM_DBG(CAM_ISP, "try to flush pending list");
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
-	CDBG("%s: Flush request in top state %d\n",
-		__func__, ctx->state);
+	CAM_DBG(CAM_ISP, "Flush request in top state %d",
+		 ctx->state);
 	return rc;
 }
 
@@ -817,7 +823,7 @@
 {
 	int rc = 0;
 
-	CDBG("%s: try to flush pending list\n", __func__);
+	CAM_DBG(CAM_ISP, "try to flush pending list");
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
 
 	/* if nothing is in pending req list, change state to acquire*/
@@ -828,8 +834,8 @@
 
 	trace_cam_context_state("ISP", ctx);
 
-	CDBG("%s: Flush request in ready state. next state %d\n",
-		__func__, ctx->state);
+	CAM_DBG(CAM_ISP, "Flush request in ready state. next state %d",
+		 ctx->state);
 	return rc;
 }
 
@@ -879,6 +885,412 @@
 	},
 };
 
+static int __cam_isp_ctx_rdi_only_sof_in_top_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	int rc = 0;
+	struct cam_context                    *ctx = ctx_isp->base;
+	struct cam_req_mgr_sof_notify          notify;
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+	uint64_t                               request_id  = 0;
+
+	if (!evt_data) {
+		CAM_ERR(CAM_ISP, "in valid sof event data");
+		return -EINVAL;
+	}
+
+	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+	/*
+	 * notify reqmgr with sof signal. Note, due to scheduling delay
+	 * we can run into situation that two active requests has already
+	 * be in the active queue while we try to do the notification.
+	 * In this case, we need to skip the current notification. This
+	 * helps the state machine to catch up the delay.
+	 */
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof &&
+		ctx_isp->active_req_cnt <= 2) {
+		notify.link_hdl = ctx->link_hdl;
+		notify.dev_hdl = ctx->dev_hdl;
+		notify.frame_id = ctx_isp->frame_id;
+
+		ctx->ctx_crm_intf->notify_sof(&notify);
+		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
+			ctx_isp->frame_id);
+
+		/*
+		 * It is idle frame with out any applied request id, send
+		 * request id as zero
+		 */
+		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+	} else {
+		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
+	}
+
+	if (list_empty(&ctx->active_req_list))
+		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+	else
+		CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
+
+	CAM_DBG(CAM_ISP, "next substate %d",
+		ctx_isp->substate_activated);
+	return rc;
+}
+
+static int __cam_isp_ctx_rdi_only_sof_in_applied_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+
+	if (!evt_data) {
+		CAM_ERR(CAM_ISP, "in valid sof event data");
+		return -EINVAL;
+	}
+
+	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED;
+	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+
+	return 0;
+}
+
+static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	struct cam_ctx_request    *req;
+	struct cam_isp_ctx_req    *req_isp;
+	struct cam_context        *ctx = ctx_isp->base;
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+	uint64_t  request_id = 0;
+
+	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+	if (list_empty(&ctx->pending_req_list)) {
+		/*
+		 * If no pending req in epoch, this is an error case.
+		 * The recovery is to go back to sof state
+		 */
+		CAM_ERR(CAM_ISP, "No pending request");
+		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+
+		/* Send SOF event as empty frame*/
+		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+		goto end;
+	}
+
+	req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
+		list);
+	req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+
+	CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
+	if (req_isp->bubble_report && ctx->ctx_crm_intf &&
+		ctx->ctx_crm_intf->notify_err) {
+		struct cam_req_mgr_error_notify notify;
+
+		notify.link_hdl = ctx->link_hdl;
+		notify.dev_hdl = ctx->dev_hdl;
+		notify.req_id = req->request_id;
+		notify.error = CRM_KMD_ERR_BUBBLE;
+		ctx->ctx_crm_intf->notify_err(&notify);
+		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
+			ctx_isp->frame_id);
+	} else {
+		/*
+		 * Since can not bubble report, always move the request to
+		 * active list.
+		 */
+		list_del_init(&req->list);
+		list_add_tail(&req->list, &ctx->active_req_list);
+		ctx_isp->active_req_cnt++;
+		CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+			req->request_id, ctx_isp->active_req_cnt);
+		req_isp->bubble_report = 0;
+	}
+
+	request_id = req->request_id;
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_ERROR);
+
+	/* change the state to bubble, as reg update has not come */
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
+	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+end:
+	return 0;
+}
+
+static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	uint32_t i;
+	struct cam_ctx_request                *req;
+	struct cam_context                    *ctx = ctx_isp->base;
+	struct cam_req_mgr_sof_notify          notify;
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+	struct cam_isp_ctx_req                *req_isp;
+	uint64_t                               request_id  = 0;
+
+	if (!evt_data) {
+		CAM_ERR(CAM_ISP, "in valid sof event data");
+		return -EINVAL;
+	}
+
+	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+	/*
+	 * Signal all active requests with error and move the  all the active
+	 * requests to free list
+	 */
+	while (!list_empty(&ctx->active_req_list)) {
+		req = list_first_entry(&ctx->active_req_list,
+				struct cam_ctx_request, list);
+		list_del_init(&req->list);
+		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+		CAM_DBG(CAM_ISP, "signal fence in active list. fence num %d",
+			req_isp->num_fence_map_out);
+		for (i = 0; i < req_isp->num_fence_map_out; i++)
+			if (req_isp->fence_map_out[i].sync_id != -1) {
+				cam_sync_signal(
+					req_isp->fence_map_out[i].sync_id,
+					CAM_SYNC_STATE_SIGNALED_ERROR);
+			}
+		list_add_tail(&req->list, &ctx->free_req_list);
+	}
+
+	/* notify reqmgr with sof signal */
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
+		notify.link_hdl = ctx->link_hdl;
+		notify.dev_hdl = ctx->dev_hdl;
+		notify.frame_id = ctx_isp->frame_id;
+
+		ctx->ctx_crm_intf->notify_sof(&notify);
+		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
+			ctx_isp->frame_id);
+
+	} else {
+		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
+	}
+
+	/*
+	 * It is idle frame with out any applied request id, send
+	 * request id as zero
+	 */
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+
+	CAM_DBG(CAM_ISP, "next substate %d",
+		ctx_isp->substate_activated);
+
+	return 0;
+}
+
+static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	struct cam_ctx_request  *req;
+	struct cam_context      *ctx = ctx_isp->base;
+	struct cam_isp_ctx_req  *req_isp;
+	struct cam_req_mgr_sof_notify  notify;
+	uint64_t  request_id  = 0;
+
+	/* notify reqmgr with sof signal*/
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
+		if (list_empty(&ctx->pending_req_list)) {
+			CAM_ERR(CAM_ISP, "Reg upd ack with no pending request");
+			goto error;
+		}
+		req = list_first_entry(&ctx->pending_req_list,
+				struct cam_ctx_request, list);
+		list_del_init(&req->list);
+
+		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+		request_id = req->request_id;
+		if (req_isp->num_fence_map_out != 0) {
+			list_add_tail(&req->list, &ctx->active_req_list);
+			ctx_isp->active_req_cnt++;
+			CAM_DBG(CAM_ISP,
+				"move request %lld to active list(cnt = %d)",
+				req->request_id, ctx_isp->active_req_cnt);
+		} else {
+			/* no io config, so the request is completed. */
+			list_add_tail(&req->list, &ctx->free_req_list);
+			CAM_DBG(CAM_ISP,
+				"move active req %lld to free list(cnt=%d)",
+				req->request_id, ctx_isp->active_req_cnt);
+		}
+
+		notify.link_hdl = ctx->link_hdl;
+		notify.dev_hdl = ctx->dev_hdl;
+		notify.frame_id = ctx_isp->frame_id;
+
+		ctx->ctx_crm_intf->notify_sof(&notify);
+		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
+			ctx_isp->frame_id);
+	} else {
+		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
+	}
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
+	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+
+	return 0;
+error:
+	/* Send SOF event as idle frame*/
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+	/*
+	 * There is no request in the pending list, move the sub state machine
+	 * to SOF sub state
+	 */
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+
+	return 0;
+}
+
+static struct cam_isp_ctx_irq_ops
+	cam_isp_ctx_rdi_only_activated_state_machine_irq
+			[CAM_ISP_CTX_ACTIVATED_MAX] = {
+	/* SOF */
+	{
+		.irq_ops = {
+			NULL,
+			__cam_isp_ctx_rdi_only_sof_in_top_state,
+			__cam_isp_ctx_reg_upd_in_sof,
+			NULL,
+			NULL,
+			NULL,
+		},
+	},
+	/* APPLIED */
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			__cam_isp_ctx_rdi_only_sof_in_applied_state,
+			NULL,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_applied,
+		},
+	},
+	/* EPOCH */
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			__cam_isp_ctx_rdi_only_sof_in_top_state,
+			NULL,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_epoch,
+		},
+	},
+	/* BUBBLE*/
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			__cam_isp_ctx_rdi_only_sof_in_bubble_state,
+			NULL,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_bubble,
+		},
+	},
+	/* BUBBLE APPLIED ie PRE_BUBBLE */
+	{
+		.irq_ops = {
+			__cam_isp_ctx_handle_error,
+			__cam_isp_ctx_rdi_only_sof_in_bubble_applied,
+			__cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_bubble_applied,
+		},
+	},
+
+	/* HALT */
+	{
+	},
+};
+
+static int __cam_isp_ctx_rdi_only_apply_req_top_state(
+	struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
+{
+	int rc = 0;
+	struct cam_isp_context *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+
+	CAM_DBG(CAM_ISP, "current substate %d",
+		ctx_isp->substate_activated);
+	rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
+		CAM_ISP_CTX_ACTIVATED_APPLIED);
+	CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
+
+	return rc;
+}
+
+static struct cam_ctx_ops
+	cam_isp_ctx_rdi_only_activated_state_machine
+		[CAM_ISP_CTX_ACTIVATED_MAX] = {
+	/* SOF */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {
+			.apply_req = __cam_isp_ctx_rdi_only_apply_req_top_state,
+		},
+		.irq_ops = NULL,
+	},
+	/* APPLIED */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
+	/* EPOCH */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {
+			.apply_req = __cam_isp_ctx_rdi_only_apply_req_top_state,
+		},
+		.irq_ops = NULL,
+	},
+	/* PRE BUBBLE */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
+	/* BUBBLE */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
+	/* HALT */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
+};
+
 
 /* top level state machine */
 static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
@@ -910,20 +1322,20 @@
 	 * But we still add some sanity check code here to help the debug
 	 */
 	if (!list_empty(&ctx->active_req_list))
-		pr_err("%s: Active list is not empty\n", __func__);
+		CAM_ERR(CAM_ISP, "Active list is not empty");
 
 	/* Flush all the pending request list  */
 	flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
 	flush_req.link_hdl = ctx->link_hdl;
 	flush_req.dev_hdl = ctx->dev_hdl;
 
-	CDBG("%s: try to flush pending list\n", __func__);
+	CAM_DBG(CAM_ISP, "try to flush pending list");
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
 
 	ctx->state = CAM_CTX_AVAILABLE;
 
 	trace_cam_context_state("ISP", ctx);
-	CDBG("%s: next state %d\n", __func__, ctx->state);
+	CAM_DBG(CAM_ISP, "next state %d", ctx->state);
 	return rc;
 }
 
@@ -941,7 +1353,7 @@
 	struct cam_isp_context           *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
 
-	CDBG("%s: get free request object......\n", __func__);
+	CAM_DBG(CAM_ISP, "get free request object......");
 
 	/* get free request */
 	spin_lock_bh(&ctx->lock);
@@ -953,7 +1365,7 @@
 	spin_unlock_bh(&ctx->lock);
 
 	if (!req) {
-		pr_err("%s: No more request obj free\n", __func__);
+		CAM_ERR(CAM_ISP, "No more request obj free");
 		rc = -ENOMEM;
 		goto end;
 	}
@@ -965,20 +1377,20 @@
 	rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle,
 		(uint64_t *) &packet_addr, &len);
 	if (rc != 0) {
-		pr_err("%s: Can not get packet address\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not get packet address");
 		rc = -EINVAL;
 		goto free_req;
 	}
 
 	packet = (struct cam_packet *) (packet_addr + cmd->offset);
-	CDBG("%s: pack_handle %llx\n", __func__, cmd->packet_handle);
-	CDBG("%s: packet address is 0x%llx\n", __func__, packet_addr);
-	CDBG("%s: packet with length %zu, offset 0x%llx\n", __func__,
+	CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle);
+	CAM_DBG(CAM_ISP, "packet address is 0x%llx", packet_addr);
+	CAM_DBG(CAM_ISP, "packet with length %zu, offset 0x%llx",
 		len, cmd->offset);
-	CDBG("%s: Packet request id %lld\n", __func__,
+	CAM_DBG(CAM_ISP, "Packet request id %lld",
 		packet->header.request_id);
-	CDBG("%s: Packet size 0x%x\n", __func__, packet->header.size);
-	CDBG("%s: packet op %d\n", __func__, packet->header.op_code);
+	CAM_DBG(CAM_ISP, "Packet size 0x%x", packet->header.size);
+	CAM_DBG(CAM_ISP, "packet op %d", packet->header.op_code);
 
 	/* preprocess the configuration */
 	memset(&cfg, 0, sizeof(cfg));
@@ -991,13 +1403,12 @@
 	cfg.out_map_entries = req_isp->fence_map_out;
 	cfg.in_map_entries = req_isp->fence_map_in;
 
-	CDBG("%s: try to prepare config packet......\n", __func__);
+	CAM_DBG(CAM_ISP, "try to prepare config packet......");
 
 	rc = ctx->hw_mgr_intf->hw_prepare_update(
 		ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
 	if (rc != 0) {
-		pr_err("%s: Prepare config packet failed in HW layer\n",
-			__func__);
+		CAM_ERR(CAM_ISP, "Prepare config packet failed in HW layer");
 		rc = -EFAULT;
 		goto free_req;
 	}
@@ -1006,8 +1417,8 @@
 	req_isp->num_fence_map_in = cfg.num_in_map_entries;
 	req_isp->num_acked = 0;
 
-	CDBG("%s: num_entry: %d, num fence out: %d, num fence in: %d\n",
-		__func__, req_isp->num_cfg, req_isp->num_fence_map_out,
+	CAM_DBG(CAM_ISP, "num_entry: %d, num fence out: %d, num fence in: %d",
+		 req_isp->num_cfg, req_isp->num_fence_map_out,
 		req_isp->num_fence_map_in);
 
 	req->request_id = packet->header.request_id;
@@ -1019,20 +1430,20 @@
 		add_req.req_id   = req->request_id;
 		rc = ctx->ctx_crm_intf->add_req(&add_req);
 		if (rc) {
-			pr_err("%s: Error: Adding request id=%llu\n", __func__,
+			CAM_ERR(CAM_ISP, "Error: Adding request id=%llu",
 				req->request_id);
 				goto free_req;
 		}
 	}
 
-	CDBG("%s: Packet request id 0x%llx\n", __func__,
+	CAM_DBG(CAM_ISP, "Packet request id 0x%llx",
 		packet->header.request_id);
 
 	spin_lock_bh(&ctx->lock);
 	list_add_tail(&req->list, &ctx->pending_req_list);
 	spin_unlock_bh(&ctx->lock);
 
-	CDBG("%s: Preprocessing Config %lld successful\n", __func__,
+	CAM_DBG(CAM_ISP, "Preprocessing Config %lld successful",
 		req->request_id);
 
 	return rc;
@@ -1055,26 +1466,28 @@
 	struct cam_hw_release_args       release;
 	struct cam_isp_context          *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
+	struct cam_isp_hw_cmd_args       hw_cmd_args;
 
 	if (!ctx->hw_mgr_intf) {
-		pr_err("HW interface is not ready!\n");
+		CAM_ERR(CAM_ISP, "HW interface is not ready");
 		rc = -EFAULT;
 		goto end;
 	}
 
-	CDBG("%s: session_hdl 0x%x, num_resources %d, hdl type %d, res %lld\n",
-		 __func__, cmd->session_handle, cmd->num_resources,
+	CAM_DBG(CAM_ISP,
+		"session_hdl 0x%x, num_resources %d, hdl type %d, res %lld",
+		cmd->session_handle, cmd->num_resources,
 		cmd->handle_type, cmd->resource_hdl);
 
 	if (cmd->num_resources > CAM_ISP_CTX_RES_MAX) {
-		pr_err("Too much resources in the acquire!\n");
+		CAM_ERR(CAM_ISP, "Too much resources in the acquire");
 		rc = -ENOMEM;
 		goto end;
 	}
 
 	/* for now we only support user pointer */
 	if (cmd->handle_type != 1)  {
-		pr_err("%s: Only user pointer is supported!", __func__);
+		CAM_ERR(CAM_ISP, "Only user pointer is supported");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1086,8 +1499,8 @@
 		goto end;
 	}
 
-	CDBG("%s: start copy %d resources from user\n",
-		__func__, cmd->num_resources);
+	CAM_DBG(CAM_ISP, "start copy %d resources from user",
+		 cmd->num_resources);
 
 	if (copy_from_user(isp_res, (void __user *)cmd->resource_hdl,
 		sizeof(*isp_res)*cmd->num_resources)) {
@@ -1104,10 +1517,39 @@
 	rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv,
 		&param);
 	if (rc != 0) {
-		pr_err("Acquire device failed\n");
+		CAM_ERR(CAM_ISP, "Acquire device failed");
 		goto free_res;
 	}
 
+	/* Query the context has rdi only resource */
+	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
+	hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+	rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+				&hw_cmd_args);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "HW command failed");
+		goto free_hw;
+	}
+
+	if (hw_cmd_args.u.is_rdi_only_context) {
+		/*
+		 * this context has rdi only resource assign rdi only
+		 * state machine
+		 */
+		CAM_DBG(CAM_ISP, "RDI only session Context");
+
+		ctx_isp->substate_machine_irq =
+			cam_isp_ctx_rdi_only_activated_state_machine_irq;
+		ctx_isp->substate_machine =
+			cam_isp_ctx_rdi_only_activated_state_machine;
+	} else {
+		CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
+		ctx_isp->substate_machine_irq =
+			cam_isp_ctx_activated_state_machine_irq;
+		ctx_isp->substate_machine =
+			cam_isp_ctx_activated_state_machine;
+	}
+
 	ctx_isp->hw_ctx = param.ctxt_to_hw_map;
 
 	req_hdl_param.session_hdl = cmd->session_handle;
@@ -1117,11 +1559,11 @@
 	req_hdl_param.ops = ctx->crm_ctx_intf;
 	req_hdl_param.priv = ctx;
 
-	CDBG("%s: get device handle form bridge\n", __func__);
+	CAM_DBG(CAM_ISP, "get device handle form bridge");
 	ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param);
 	if (ctx->dev_hdl <= 0) {
 		rc = -EFAULT;
-		pr_err("Can not create device handle\n");
+		CAM_ERR(CAM_ISP, "Can not create device handle");
 		goto free_hw;
 	}
 	cmd->dev_handle = ctx->dev_hdl;
@@ -1132,7 +1574,7 @@
 	ctx->state = CAM_CTX_ACQUIRED;
 
 	trace_cam_context_state("ISP", ctx);
-	CDBG("%s:%d: Acquire success.\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "Acquire success.");
 	kfree(isp_res);
 	return rc;
 
@@ -1158,7 +1600,7 @@
 		trace_cam_context_state("ISP", ctx);
 	}
 
-	CDBG("%s: next state %d\n", __func__, ctx->state);
+	CAM_DBG(CAM_ISP, "next state %d", ctx->state);
 	return rc;
 }
 
@@ -1167,7 +1609,7 @@
 {
 	int rc = 0;
 
-	CDBG("%s:%d: Enter.........\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "Enter.........");
 
 	ctx->link_hdl = link->link_hdl;
 	ctx->ctx_crm_intf = link->crm_cb;
@@ -1178,7 +1620,7 @@
 		trace_cam_context_state("ISP", ctx);
 	}
 
-	CDBG("%s: next state %d\n", __func__, ctx->state);
+	CAM_DBG(CAM_ISP, "next state %d", ctx->state);
 
 	return rc;
 }
@@ -1225,8 +1667,7 @@
 
 	if (list_empty(&ctx->pending_req_list)) {
 		/* should never happen */
-		pr_err("%s: Start device with empty configuration\n",
-			__func__);
+		CAM_ERR(CAM_ISP, "Start device with empty configuration");
 		rc = -EFAULT;
 		goto end;
 	} else {
@@ -1236,8 +1677,7 @@
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 
 	if (!ctx_isp->hw_ctx) {
-		pr_err("%s:%d: Wrong hw context pointer.\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Wrong hw context pointer.");
 		rc = -EFAULT;
 		goto end;
 	}
@@ -1260,12 +1700,12 @@
 	rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg);
 	if (rc) {
 		/* HW failure. user need to clean up the resource */
-		pr_err("Start HW failed\n");
+		CAM_ERR(CAM_ISP, "Start HW failed");
 		ctx->state = CAM_CTX_READY;
 		trace_cam_context_state("ISP", ctx);
 		goto end;
 	}
-	CDBG("%s: start device success\n", __func__);
+	CAM_DBG(CAM_ISP, "start device success");
 end:
 	return rc;
 }
@@ -1298,7 +1738,7 @@
 	spin_lock_bh(&ctx->lock);
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT;
 	spin_unlock_bh(&ctx->lock);
-	CDBG("%s: next substate %d", __func__, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
 
 	/* stop hw first */
 	if (ctx_isp->hw_ctx) {
@@ -1312,8 +1752,8 @@
 				struct cam_ctx_request, list);
 		list_del_init(&req->list);
 		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		CDBG("%s: signal fence in pending list. fence num %d\n",
-			__func__, req_isp->num_fence_map_out);
+		CAM_DBG(CAM_ISP, "signal fence in pending list. fence num %d",
+			 req_isp->num_fence_map_out);
 		for (i = 0; i < req_isp->num_fence_map_out; i++)
 			if (req_isp->fence_map_out[i].sync_id != -1) {
 				cam_sync_signal(
@@ -1328,8 +1768,8 @@
 				struct cam_ctx_request, list);
 		list_del_init(&req->list);
 		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		CDBG("%s: signal fence in active list. fence num %d\n",
-			__func__, req_isp->num_fence_map_out);
+		CAM_DBG(CAM_ISP, "signal fence in active list. fence num %d",
+			 req_isp->num_fence_map_out);
 		for (i = 0; i < req_isp->num_fence_map_out; i++)
 			if (req_isp->fence_map_out[i].sync_id != -1) {
 				cam_sync_signal(
@@ -1342,7 +1782,7 @@
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
 
-	CDBG("%s: next state %d", __func__, ctx->state);
+	CAM_DBG(CAM_ISP, "next state %d", ctx->state);
 	return rc;
 }
 
@@ -1394,21 +1834,21 @@
 		(struct cam_isp_context *) ctx->ctx_priv;
 
 	trace_cam_apply_req("ISP", apply);
-	CDBG("%s: Enter: apply req in Substate %d request _id:%lld\n",
-		__func__, ctx_isp->substate_activated, apply->request_id);
+	CAM_DBG(CAM_ISP, "Enter: apply req in Substate %d request _id:%lld",
+		 ctx_isp->substate_activated, apply->request_id);
 	if (ctx_isp->substate_machine[ctx_isp->substate_activated].
 		crm_ops.apply_req) {
 		rc = ctx_isp->substate_machine[ctx_isp->substate_activated].
 			crm_ops.apply_req(ctx, apply);
 	} else {
-		pr_err("%s: No handle function in activated substate %d\n",
-			__func__, ctx_isp->substate_activated);
+		CAM_ERR(CAM_ISP, "No handle function in activated substate %d",
+			 ctx_isp->substate_activated);
 		rc = -EFAULT;
 	}
 
 	if (rc)
-		pr_err("%s: Apply failed in active substate %d\n",
-			__func__, ctx_isp->substate_activated);
+		CAM_ERR(CAM_ISP, "Apply failed in active substate %d",
+			 ctx_isp->substate_activated);
 	return rc;
 }
 
@@ -1427,18 +1867,18 @@
 	trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id,
 		__cam_isp_ctx_get_event_ts(evt_id, evt_data));
 
-	CDBG("%s: Enter: State %d, Substate %d, evt id %d\n",
-		__func__, ctx->state, ctx_isp->substate_activated, evt_id);
+	CAM_DBG(CAM_ISP, "Enter: State %d, Substate %d, evt id %d",
+		 ctx->state, ctx_isp->substate_activated, evt_id);
 	if (ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
 		irq_ops[evt_id]) {
 		rc = ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
 			irq_ops[evt_id](ctx_isp, evt_data);
 	} else {
-		CDBG("%s: No handle function for substate %d\n", __func__,
+		CAM_DBG(CAM_ISP, "No handle function for substate %d",
 			ctx_isp->substate_activated);
 	}
-	CDBG("%s: Exit: State %d Substate %d\n",
-		__func__, ctx->state, ctx_isp->substate_activated);
+	CAM_DBG(CAM_ISP, "Exit: State %d Substate %d",
+		 ctx->state, ctx_isp->substate_activated);
 	spin_unlock_bh(&ctx->lock);
 	return rc;
 }
@@ -1513,7 +1953,7 @@
 	int i;
 
 	if (!ctx || !ctx_base) {
-		pr_err("%s: Invalid Context\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid Context");
 		goto err;
 	}
 
@@ -1538,7 +1978,7 @@
 	rc = cam_context_init(ctx_base, crm_node_intf, hw_intf, ctx->req_base,
 		CAM_CTX_REQ_MAX);
 	if (rc) {
-		pr_err("%s: Camera Context Base init failed\n", __func__);
+		CAM_ERR(CAM_ISP, "Camera Context Base init failed");
 		goto err;
 	}
 
@@ -1558,7 +1998,7 @@
 		cam_context_deinit(ctx->base);
 
 	if (ctx->substate_activated != CAM_ISP_CTX_ACTIVATED_SOF)
-		pr_err("%s: ISP context substate is invalid\n", __func__);
+		CAM_ERR(CAM_ISP, "ISP context substate is invalid");
 
 	memset(ctx, 0, sizeof(*ctx));
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
index 4c819cf..2bf7795 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
@@ -25,6 +25,7 @@
 #include "cam_hw_mgr_intf.h"
 #include "cam_isp_hw_mgr_intf.h"
 #include "cam_node.h"
+#include "cam_debug_util.h"
 
 static struct cam_isp_dev g_isp_dev;
 
@@ -44,13 +45,13 @@
 	for (i = 0; i < CAM_CTX_MAX; i++) {
 		rc = cam_isp_context_deinit(&g_isp_dev.ctx_isp[i]);
 		if (rc)
-			pr_err("%s: ISP context %d deinit failed\n",
-				__func__, i);
+			CAM_ERR(CAM_ISP, "ISP context %d deinit failed",
+				 i);
 	}
 
 	rc = cam_subdev_remove(&g_isp_dev.sd);
 	if (rc)
-		pr_err("%s: Unregister failed\n", __func__);
+		CAM_ERR(CAM_ISP, "Unregister failed");
 
 	memset(&g_isp_dev, 0, sizeof(g_isp_dev));
 	return 0;
@@ -67,7 +68,7 @@
 	rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME,
 		CAM_IFE_DEVICE_TYPE);
 	if (rc) {
-		pr_err("%s: ISP cam_subdev_probe failed!\n", __func__);
+		CAM_ERR(CAM_ISP, "ISP cam_subdev_probe failed!");
 		goto err;
 	}
 	node = (struct cam_node *) g_isp_dev.sd.token;
@@ -75,7 +76,7 @@
 	memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf));
 	rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf);
 	if (rc != 0) {
-		pr_err("%s: Can not initialized ISP HW manager!\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!");
 		goto unregister;
 	}
 
@@ -85,7 +86,7 @@
 			&node->crm_node_intf,
 			&node->hw_mgr_intf);
 		if (rc) {
-			pr_err("%s: ISP context init failed!\n", __func__);
+			CAM_ERR(CAM_ISP, "ISP context init failed!");
 			goto unregister;
 		}
 	}
@@ -93,11 +94,11 @@
 	rc = cam_node_init(node, &hw_mgr_intf, g_isp_dev.ctx, CAM_CTX_MAX,
 		CAM_ISP_DEV_NAME);
 	if (rc) {
-		pr_err("%s: ISP node init failed!\n", __func__);
+		CAM_ERR(CAM_ISP, "ISP node init failed!");
 		goto unregister;
 	}
 
-	pr_info("%s: Camera ISP probe complete\n", __func__);
+	CAM_INFO(CAM_ISP, "Camera ISP probe complete");
 
 	return 0;
 unregister:
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index cb38d8f..4a5b1c3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -24,9 +24,7 @@
 #include "cam_ife_hw_mgr.h"
 #include "cam_cdm_intf_api.h"
 #include "cam_packet_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 #define CAM_IFE_HW_ENTRIES_MAX  20
 
@@ -41,7 +39,7 @@
 	struct cam_query_cap_cmd          *query = hw_caps_args;
 	struct cam_isp_query_cap_cmd       query_isp;
 
-	CDBG("%s: enter\n", __func__);
+	CAM_DBG(CAM_ISP, "enter");
 
 	if (copy_from_user(&query_isp, (void __user *)query->caps_handle,
 		sizeof(struct cam_isp_query_cap_cmd))) {
@@ -66,7 +64,7 @@
 		sizeof(struct cam_isp_query_cap_cmd)))
 		rc = -EFAULT;
 
-	CDBG("%s: exit rc :%d !\n", __func__, rc);
+	CAM_DBG(CAM_ISP, "exit rc :%d !", rc);
 
 	return rc;
 }
@@ -100,7 +98,7 @@
 		if (!isp_hw_res->hw_res[i])
 			continue;
 		hw_intf = isp_hw_res->hw_res[i]->hw_intf;
-		CDBG("%s: enabled vfe hardware %d\n", __func__,
+		CAM_DBG(CAM_ISP, "enabled vfe hardware %d",
 			hw_intf->hw_idx);
 		if (hw_intf->hw_ops.init) {
 			rc = hw_intf->hw_ops.init(hw_intf->hw_priv,
@@ -113,7 +111,7 @@
 
 	return 0;
 err:
-	pr_err("%s: INIT HW res failed! (type:%d, id:%d)", __func__,
+	CAM_ERR(CAM_ISP, "INIT HW res failed! (type:%d, id:%d)",
 		isp_hw_res->res_type, isp_hw_res->res_id);
 	return rc;
 }
@@ -134,19 +132,18 @@
 				isp_hw_res->hw_res[i],
 				sizeof(struct cam_isp_resource_node));
 			if (rc) {
-				pr_err("%s: Can not start HW resources!\n",
-					__func__);
+				CAM_ERR(CAM_ISP, "Can not start HW resources!");
 				goto err;
 			}
 		} else {
-			pr_err("%s:function null\n", __func__);
+			CAM_ERR(CAM_ISP, "function null");
 			goto err;
 		}
 	}
 
 	return 0;
 err:
-	pr_err("%s: Start hw res failed! (type:%d, id:%d)", __func__,
+	CAM_ERR(CAM_ISP, "Start hw res failed! (type:%d, id:%d)",
 		isp_hw_res->res_type, isp_hw_res->res_id);
 	return rc;
 }
@@ -166,7 +163,7 @@
 				isp_hw_res->hw_res[i],
 				sizeof(struct cam_isp_resource_node));
 		else
-			pr_err("%s:stop null\n", __func__);
+			CAM_ERR(CAM_ISP, "stop null");
 	}
 }
 
@@ -213,7 +210,7 @@
 			struct cam_ife_hw_mgr_res, list);
 		list_del_init(&res_ptr->list);
 	} else {
-		pr_err("No more free ife hw mgr ctx!\n");
+		CAM_ERR(CAM_ISP, "No more free ife hw mgr ctx!");
 		rc = -1;
 	}
 	*res = res_ptr;
@@ -237,11 +234,12 @@
 				isp_hw_res->hw_res[i],
 				sizeof(struct cam_isp_resource_node));
 			if (rc)
-				pr_err("%s:Release hw resrouce id %d failed!\n",
-					__func__, isp_hw_res->res_id);
+				CAM_ERR(CAM_ISP,
+					"Release hw resrouce id %d failed!",
+					isp_hw_res->res_id);
 			isp_hw_res->hw_res[i] = NULL;
 		} else
-			pr_err("%s:Release null\n", __func__);
+			CAM_ERR(CAM_ISP, "Release null");
 	}
 	/* caller should make sure the resource is in a list */
 	list_del_init(&isp_hw_res->list);
@@ -328,8 +326,8 @@
 	ife_ctx->common.cb_priv = NULL;
 	memset(ife_ctx->common.event_cb, 0, sizeof(ife_ctx->common.event_cb));
 
-	CDBG("%s:%d: release context completed ctx id:%d\n",
-		__func__, __LINE__, ife_ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "release context completed ctx id:%d",
+		ife_ctx->ctx_index);
 
 	return 0;
 }
@@ -364,7 +362,7 @@
 			struct cam_ife_hw_mgr_ctx, list);
 		list_del_init(&ctx_ptr->list);
 	} else {
-		pr_err("No more free ife hw mgr ctx!\n");
+		CAM_ERR(CAM_ISP, "No more free ife hw mgr ctx!");
 		rc = -1;
 	}
 	*ife_ctx = ctx_ptr;
@@ -381,7 +379,7 @@
 	uint32_t    i;
 
 	if (!ctx->num_base) {
-		CDBG("%s: Add split id = %d for base idx = %d\n", __func__,
+		CAM_DBG(CAM_ISP, "Add split id = %d for base idx = %d",
 			split_id, base_idx);
 		ctx->base[0].split_id = split_id;
 		ctx->base[0].idx      = base_idx;
@@ -400,8 +398,8 @@
 		}
 
 		if (i == CAM_IFE_HW_NUM_MAX) {
-			CDBG("%s: Add split id = %d for base idx = %d\n",
-				__func__, split_id, base_idx);
+			CAM_DBG(CAM_ISP, "Add split id = %d for base idx = %d",
+				 split_id, base_idx);
 			ctx->base[ctx->num_base].split_id = split_id;
 			ctx->base[ctx->num_base].idx      = base_idx;
 			ctx->num_base++;
@@ -417,7 +415,7 @@
 	uint32_t i;
 
 	if (list_empty(&ctx->res_list_ife_src)) {
-		pr_err("%s: Error! Mux List empty\n", __func__);
+		CAM_ERR(CAM_ISP, "Error! Mux List empty");
 		return -ENODEV;
 	}
 
@@ -440,7 +438,7 @@
 						res->hw_intf->hw_idx);
 		}
 	}
-	CDBG("%s: ctx base num = %d\n", __func__, ctx->num_base);
+	CAM_DBG(CAM_ISP, "ctx base num = %d", ctx->num_base);
 
 	return 0;
 }
@@ -474,7 +472,7 @@
 		vfe_out_res_id = CAM_ISP_IFE_OUT_RES_RDI_3;
 		break;
 	default:
-		pr_err("%s: invalid resource type\n", __func__);
+		CAM_ERR(CAM_ISP, "invalid resource type");
 		goto err;
 	}
 
@@ -498,15 +496,15 @@
 			&vfe_acquire,
 			sizeof(struct cam_vfe_acquire_args));
 		if (rc) {
-			pr_err("%s: Can not acquire out resource 0x%x\n",
-				__func__, out_port->res_type);
+			CAM_ERR(CAM_ISP, "Can not acquire out resource 0x%x",
+				 out_port->res_type);
 			goto err;
 		}
 		break;
 	}
 
 	if (i == in_port->num_out_res) {
-		pr_err("%s: Can not acquire out resource\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not acquire out resource");
 		goto err;
 	}
 
@@ -536,16 +534,16 @@
 		out_port = &in_port->data[i];
 		k = out_port->res_type & 0xFF;
 		if (k >= CAM_IFE_HW_OUT_RES_MAX) {
-			pr_err("%s: invalid output resource type 0x%x\n",
-				__func__, out_port->res_type);
+			CAM_ERR(CAM_ISP, "invalid output resource type 0x%x",
+				 out_port->res_type);
 			continue;
 		}
 
 		if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
 			continue;
 
-		CDBG("%s: res_type 0x%x\n",
-			__func__, out_port->res_type);
+		CAM_DBG(CAM_ISP, "res_type 0x%x",
+			 out_port->res_type);
 
 		ife_out_res = &ife_ctx->res_list_ife_out[k];
 		ife_out_res->is_dual_vfe = in_port->usage_type;
@@ -587,15 +585,16 @@
 				&vfe_acquire,
 				sizeof(struct cam_vfe_acquire_args));
 			if (rc) {
-				pr_err("%s:Can not acquire out resource 0x%x\n",
-					__func__, out_port->res_type);
+				CAM_ERR(CAM_ISP,
+					"Can not acquire out resource 0x%x",
+					out_port->res_type);
 				goto err;
 			}
 
 			ife_out_res->hw_res[j] =
 				vfe_acquire.vfe_out.rsrc_node;
-			CDBG("%s: resource type :0x%x res id:0x%x\n",
-				__func__, ife_out_res->hw_res[j]->res_type,
+			CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x",
+				ife_out_res->hw_res[j]->res_type,
 				ife_out_res->hw_res[j]->res_id);
 
 		}
@@ -635,8 +634,7 @@
 				ife_src_res, in_port);
 			break;
 		default:
-			pr_err("%s: Fatal: Unknown IFE SRC resource!\n",
-				__func__);
+			CAM_ERR(CAM_ISP, "Fatal: Unknown IFE SRC resource!");
 			break;
 		}
 		if (rc)
@@ -670,7 +668,7 @@
 		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
 			&ife_src_res);
 		if (rc) {
-			pr_err("%s: No more free hw mgr resource!\n", __func__);
+			CAM_ERR(CAM_ISP, "No more free hw mgr resource!");
 			goto err;
 		}
 		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src,
@@ -710,8 +708,7 @@
 			vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
 			break;
 		default:
-			pr_err("%s: Wrong IFE CSID Resource Node!\n",
-				__func__);
+			CAM_ERR(CAM_ISP, "Wrong IFE CSID Resource Node!");
 			goto err;
 		}
 		ife_src_res->res_type = vfe_acquire.rsrc_type;
@@ -736,13 +733,15 @@
 					&vfe_acquire,
 					sizeof(struct cam_vfe_acquire_args));
 			if (rc) {
-				pr_err("%s:Can not acquire IFE HW res %d!\n",
-					__func__, csid_res->res_id);
+				CAM_ERR(CAM_ISP,
+					"Can not acquire IFE HW res %d",
+					csid_res->res_id);
 				goto err;
 			}
 			ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
-			CDBG("%s:acquire success res type :0x%x res id:0x%x\n",
-				__func__, ife_src_res->hw_res[i]->res_type,
+			CAM_DBG(CAM_ISP,
+				"acquire success res type :0x%x res id:0x%x",
+				ife_src_res->hw_res[i]->res_type,
 				ife_src_res->hw_res[i]->res_id);
 
 		}
@@ -779,7 +778,7 @@
 
 	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res);
 	if (rc) {
-		pr_err("%s: No more free hw mgr resource!\n", __func__);
+		CAM_ERR(CAM_ISP, "No more free hw mgr resource!");
 		goto err;
 	}
 	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
@@ -810,13 +809,12 @@
 	}
 
 	if (i == CAM_IFE_CSID_HW_NUM_MAX) {
-		pr_err("%s: Can not acquire ife csid ipp resrouce!\n",
-			__func__);
+		CAM_ERR(CAM_ISP, "Can not acquire ife csid ipp resrouce!");
 		goto err;
 	}
 
-	CDBG("%s: acquired csid(%d) left ipp resrouce successfully!\n",
-		__func__, i);
+	CAM_DBG(CAM_ISP, "acquired csid(%d) left ipp resrouce successfully!",
+		 i);
 
 	csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH;
 	csid_res->res_id = CAM_IFE_PIX_PATH_RES_IPP;
@@ -841,14 +839,14 @@
 		}
 
 		if (j == CAM_IFE_CSID_HW_NUM_MAX) {
-			pr_err("%s: Can not acquire ife csid rdi resrouce!\n",
-				__func__);
+			CAM_ERR(CAM_ISP,
+				"Can not acquire ife csid rdi resrouce!");
 			goto err;
 		}
 		csid_res->hw_res[1] = csid_acquire.node_res;
 
-		CDBG("%s:acquired csid(%d)right ipp resrouce successfully!\n",
-			__func__, j);
+		CAM_DBG(CAM_ISP,
+			"acquired csid(%d)right ipp resrouce successfully!", j);
 
 	}
 	csid_res->parent = &ife_ctx->res_list_ife_in;
@@ -881,7 +879,7 @@
 		break;
 	default:
 		path_id = CAM_IFE_PIX_PATH_RES_MAX;
-		CDBG("%s: maximum rdi output type exceeded\n", __func__);
+		CAM_DBG(CAM_ISP, "maximum rdi output type exceeded");
 		break;
 	}
 
@@ -912,7 +910,7 @@
 		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
 			&csid_res);
 		if (rc) {
-			pr_err("%s: No more free hw mgr resource!\n",
+			CAM_ERR(CAM_ISP, "No more free hw mgr resource!",
 				__func__);
 			goto err;
 		}
@@ -930,6 +928,7 @@
 		csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
 		csid_acquire.cid = cid_res_id;
 		csid_acquire.in_port = in_port;
+		csid_acquire.out_port = out_port;
 		csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
 
 		for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
@@ -946,8 +945,8 @@
 		}
 
 		if (j == CAM_IFE_CSID_HW_NUM_MAX) {
-			pr_err("%s: Can not acquire ife csid rdi resrouce!\n",
-				__func__);
+			CAM_ERR(CAM_ISP,
+				"Can not acquire ife csid rdi resrouce!");
 			goto err;
 		}
 
@@ -980,7 +979,7 @@
 		ife_ctx->res_list_ife_in.res_id = in_port->res_type;
 		ife_ctx->res_list_ife_in.is_dual_vfe = in_port->usage_type;
 	} else if (ife_ctx->res_list_ife_in.res_id != in_port->res_type) {
-		pr_err("%s: No Free resource for this context!\n", __func__);
+		CAM_ERR(CAM_ISP, "No Free resource for this context!");
 		goto err;
 	} else {
 		/* else do nothing */
@@ -1034,7 +1033,7 @@
 	/* no dual vfe for TPG */
 	if ((in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) &&
 		(in_port->usage_type != 0)) {
-		pr_err("%s: No Dual VFE on TPG input!\n", __func__);
+		CAM_ERR(CAM_ISP, "No Dual VFE on TPG input!");
 		goto err;
 	}
 
@@ -1042,7 +1041,7 @@
 
 	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
 	if (rc) {
-		pr_err("%s: No more free hw mgr resource!\n", __func__);
+		CAM_ERR(CAM_ISP, "No more free hw mgr resource!");
 		goto err;
 	}
 	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
@@ -1064,8 +1063,7 @@
 	}
 
 	if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
-		pr_err("%s: Can not acquire ife csid rdi resrouce!\n",
-			__func__);
+		CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resrouce!");
 		goto err;
 	}
 
@@ -1095,8 +1093,8 @@
 		}
 
 		if (j == CAM_IFE_CSID_HW_NUM_MAX) {
-			pr_err("%s: Can not acquire ife csid rdi resrouce!\n",
-				__func__);
+			CAM_ERR(CAM_ISP,
+				"Can not acquire ife csid rdi resrouce!");
 			goto err;
 		}
 		cid_res->hw_res[1] = csid_acquire.node_res;
@@ -1112,7 +1110,8 @@
 }
 static int cam_ife_mgr_acquire_hw_for_ctx(
 	struct cam_ife_hw_mgr_ctx          *ife_ctx,
-	struct cam_isp_in_port_info        *in_port)
+	struct cam_isp_in_port_info        *in_port,
+	uint32_t  *num_pix_port, uint32_t  *num_rdi_port)
 {
 	int rc                                    = -1;
 	int is_dual_vfe                           = 0;
@@ -1125,16 +1124,14 @@
 	/* get root node resource */
 	rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port);
 	if (rc) {
-		pr_err("%s:%d: Can not acquire csid rx resource!\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Can not acquire csid rx resource!");
 		goto err;
 	}
 
 	/* get cid resource */
 	rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id);
 	if (rc) {
-		pr_err("%s%d: Acquire IFE CID resource Failed!\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed!");
 		goto err;
 	}
 
@@ -1142,7 +1139,7 @@
 		&pixel_count, &rdi_count);
 
 	if (!pixel_count && !rdi_count) {
-		pr_err("%s: Error! no PIX or RDI resource\n", __func__);
+		CAM_ERR(CAM_ISP, "Error! no PIX or RDI resource");
 		return -EINVAL;
 	}
 
@@ -1151,8 +1148,8 @@
 		rc = cam_ife_hw_mgr_acquire_res_ife_csid_ipp(ife_ctx, in_port,
 				cid_res_id);
 		if (rc) {
-			pr_err("%s%d: Acquire IFE CSID IPP resource Failed!\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ISP,
+				"Acquire IFE CSID IPP resource Failed!");
 			goto err;
 		}
 	}
@@ -1162,8 +1159,8 @@
 		rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port,
 			cid_res_id);
 		if (rc) {
-			pr_err("%s%d: Acquire IFE CSID RDI resource Failed!\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ISP,
+				"Acquire IFE CSID RDI resource Failed!");
 			goto err;
 		}
 	}
@@ -1171,18 +1168,19 @@
 	/* get ife src resource */
 	rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
 	if (rc) {
-		pr_err("%s%d: Acquire IFE SRC resource Failed!\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Acquire IFE SRC resource Failed!");
 		goto err;
 	}
 
 	rc = cam_ife_hw_mgr_acquire_res_ife_out(ife_ctx, in_port);
 	if (rc) {
-		pr_err("%s%d: Acquire IFE OUT resource Failed!\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Acquire IFE OUT resource Failed!");
 		goto err;
 	}
 
+	*num_pix_port += pixel_count;
+	*num_rdi_port += rdi_count;
+
 	return 0;
 err:
 	/* release resource at the acquire entry funciton */
@@ -1192,11 +1190,11 @@
 void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
 	enum cam_cdm_cb_status status, uint32_t cookie)
 {
-	CDBG("%s: Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%d\n",
-		__func__, handle, userdata, status, cookie);
+	CAM_DBG(CAM_ISP,
+		"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%d",
+		 handle, userdata, status, cookie);
 }
 
-
 /* entry function: acquire_hw */
 static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv,
 					void *acquire_hw_args)
@@ -1208,19 +1206,21 @@
 	struct cam_ife_hw_mgr_ctx         *ife_ctx;
 	struct cam_isp_in_port_info       *in_port = NULL;
 	struct cam_isp_resource           *isp_resource = NULL;
-	struct cam_cdm_acquire_data cdm_acquire;
+	struct cam_cdm_acquire_data        cdm_acquire;
+	uint32_t                           num_pix_port = 0;
+	uint32_t                           num_rdi_port = 0;
 
-	CDBG("%s: Enter...\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter...");
 
 	if (!acquire_args || acquire_args->num_acq <= 0) {
-		pr_err("%s: Nothing to acquire. Seems like error\n", __func__);
+		CAM_ERR(CAM_ISP, "Nothing to acquire. Seems like error");
 		return -EINVAL;
 	}
 
 	/* get the ife ctx */
 	rc = cam_ife_hw_mgr_get_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx);
 	if (rc || !ife_ctx) {
-		pr_err("Get ife hw context failed!\n");
+		CAM_ERR(CAM_ISP, "Get ife hw context failed!");
 		goto err;
 	}
 
@@ -1247,12 +1247,12 @@
 	cdm_acquire.id = CAM_CDM_VIRTUAL;
 	cdm_acquire.cam_cdm_callback = cam_ife_cam_cdm_callback;
 	if (!cam_cdm_acquire(&cdm_acquire)) {
-		CDBG("Successfully acquired the CDM HW hdl=%x\n",
+		CAM_DBG(CAM_ISP, "Successfully acquired the CDM HW hdl=%x",
 			cdm_acquire.handle);
 		ife_ctx->cdm_handle = cdm_acquire.handle;
 		ife_ctx->cdm_ops = cdm_acquire.ops;
 	} else {
-		pr_err("Failed to acquire the CDM HW\n");
+		CAM_ERR(CAM_ISP, "Failed to acquire the CDM HW");
 		goto err;
 	}
 
@@ -1263,32 +1263,38 @@
 		if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT)
 			continue;
 
-		CDBG("%s: start copy from user handle %lld with len = %d\n",
-			__func__, isp_resource[i].res_hdl,
+		CAM_DBG(CAM_ISP,
+			"start copy from user handle %lld with len = %d",
+			isp_resource[i].res_hdl,
 			isp_resource[i].length);
 
 		in_port = memdup_user((void __user *)isp_resource[i].res_hdl,
 			isp_resource[i].length);
 		if (in_port > 0) {
-			rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port);
+			rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
+				&num_pix_port, &num_rdi_port);
 			kfree(in_port);
 			if (rc) {
-				pr_err("%s: can not acquire resource!\n",
-					__func__);
+				CAM_ERR(CAM_ISP, "can not acquire resource");
 				goto free_res;
 			}
 		} else {
-			pr_err("%s: copy from user failed with in_port = %pK",
-				__func__, in_port);
+			CAM_ERR(CAM_ISP,
+				"copy from user failed with in_port = %pK",
+				in_port);
 			rc = -EFAULT;
 			goto free_res;
 		}
 	}
+
+	/* Check whether context has only RDI resource */
+	if (!num_pix_port)
+		ife_ctx->is_rdi_only_context = 1;
+
 	/* Process base info */
 	rc = cam_ife_mgr_process_base_info(ife_ctx);
 	if (rc) {
-		pr_err("%s: Error process) base info!\n",
-			__func__);
+		CAM_ERR(CAM_ISP, "Error process) base info!");
 		return -EINVAL;
 	}
 
@@ -1297,14 +1303,14 @@
 
 	cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx);
 
-	CDBG("%s: Exit...(success)!\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit...(success)!");
 
 	return 0;
 free_res:
 	cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx);
 	cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->free_ctx_list, &ife_ctx);
 err:
-	CDBG("%s: Exit...(rc=%d)!\n", __func__, rc);
+	CAM_DBG(CAM_ISP, "Exit...(rc=%d)!", rc);
 	return rc;
 }
 
@@ -1318,25 +1324,25 @@
 	struct cam_cdm_bl_request *cdm_cmd;
 	struct cam_ife_hw_mgr_ctx *ctx;
 
-	CDBG("%s: Enter\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter");
 	if (!hw_mgr_priv || !config_hw_args) {
-		pr_err("%s%d: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	cfg = config_hw_args;
 	ctx = (struct cam_ife_hw_mgr_ctx *)cfg->ctxt_to_hw_map;
 	if (!ctx) {
-		pr_err("%s: Fatal: Invalid context is used!\n", __func__);
+		CAM_ERR(CAM_ISP, "Fatal: Invalid context is used!");
 		return -EPERM;
 	}
 
 	if (!ctx->ctx_in_use || !ctx->cdm_cmd) {
-		pr_err("%s: Invalid context parameters !\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid context parameters !");
 		return -EPERM;
 	}
 
-	CDBG("%s:%d Enter ctx id:%d\n", __func__, __LINE__, ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "Enter ctx id:%d", ctx->ctx_index);
 
 	if (cfg->num_hw_update_entries > 0) {
 		cdm_cmd = ctx->cdm_cmd;
@@ -1355,11 +1361,11 @@
 
 		rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd);
 		if (rc)
-			pr_err("Failed to apply the configs\n");
+			CAM_ERR(CAM_ISP, "Failed to apply the configs");
 	} else {
-		pr_err("No commands to config\n");
+		CAM_ERR(CAM_ISP, "No commands to config");
 	}
-	CDBG("%s: Exit\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit");
 
 	return rc;
 }
@@ -1374,22 +1380,21 @@
 	uint32_t                          i, master_base_idx = 0;
 
 	if (!hw_mgr_priv || !stop_hw_args) {
-		pr_err("%s%d: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 	ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
-		pr_err("%s: Fatal: Invalid context is used!\n", __func__);
+		CAM_ERR(CAM_ISP, "Fatal: Invalid context is used!");
 		return -EPERM;
 	}
 
-	CDBG("%s%d: Enter...ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "Enter...ctx id:%d",
 		ctx->ctx_index);
 
 	/* stop resource will remove the irq mask from the hardware */
 	if (!ctx->num_base) {
-		pr_err("%s%d: error number of bases are zero\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "error number of bases are zero");
 		return -EINVAL;
 	}
 
@@ -1445,7 +1450,7 @@
 
 	/* update vote bandwidth should be done at the HW layer */
 
-	CDBG("%s%d Exit...ctx id:%d rc :%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "Exit...ctx id:%d rc :%d",
 		ctx->ctx_index, rc);
 
 	return rc;
@@ -1461,23 +1466,22 @@
 	uint32_t                          i, master_base_idx = 0;
 
 	if (!hw_mgr_priv || !stop_hw_args) {
-		pr_err("%s%d: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 	ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
-		pr_err("%s: Fatal: Invalid context is used!\n", __func__);
+		CAM_ERR(CAM_ISP, "Fatal: Invalid context is used!");
 		return -EPERM;
 	}
 
-	CDBG("%s%d: Enter...ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, " Enter...ctx id:%d",
 		ctx->ctx_index);
 
 	/* Note:stop resource will remove the irq mask from the hardware */
 
 	if (!ctx->num_base) {
-		pr_err("%s%d: error number of bases are zero\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "error number of bases are zero");
 		return -EINVAL;
 	}
 
@@ -1522,8 +1526,8 @@
 	}
 
 	if (cam_cdm_stream_off(ctx->cdm_handle))
-		pr_err("%s%d: CDM stream off failed %d\n",
-			__func__, __LINE__, ctx->cdm_handle);
+		CAM_ERR(CAM_ISP, "CDM stream off failed %d",
+			ctx->cdm_handle);
 
 	/* IFE mux in resources */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
@@ -1559,8 +1563,7 @@
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
 		cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
 
-	CDBG("%s%d Exit...ctx id:%d rc :%d\n", __func__, __LINE__,
-		ctx->ctx_index, rc);
+	CAM_DBG(CAM_ISP, "Exit...ctx id:%d rc :%d", ctx->ctx_index, rc);
 
 	return rc;
 }
@@ -1574,7 +1577,7 @@
 	struct cam_csid_reset_cfg_args  csid_reset_args;
 
 	if (!hw_mgr) {
-		CDBG("%s: Invalid arguments\n", __func__);
+		CAM_DBG(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -1596,13 +1599,13 @@
 	for (i = 0; i < CAM_VFE_HW_NUM_MAX; i++) {
 		if (hw_idx != hw_mgr->ife_devices[i]->hw_idx)
 			continue;
-		CDBG("%d:VFE (id = %d) reset\n", __LINE__, hw_idx);
+		CAM_DBG(CAM_ISP, "VFE (id = %d) reset", hw_idx);
 		vfe_hw_intf = hw_mgr->ife_devices[i];
 		vfe_hw_intf->hw_ops.reset(vfe_hw_intf->hw_priv, NULL, 0);
 		break;
 	}
 
-	CDBG("%d: Exit Successfully\n", __LINE__);
+	CAM_DBG(CAM_ISP, "Exit Successfully");
 	return 0;
 }
 
@@ -1616,74 +1619,68 @@
 	uint32_t                          i;
 
 	if (!hw_mgr_priv || !start_hw_args) {
-		pr_err("%s%d: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
-		pr_err("%s: Invalid context is used!\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid context is used!");
 		return -EPERM;
 	}
 
-	CDBG("%s%d Enter... ctx id:%d\n", __func__, __LINE__,
-		ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "Enter... ctx id:%d", ctx->ctx_index);
 
-	CDBG("%s%d START IFE OUT ... in ctx id:%d\n", __func__, __LINE__,
-		ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index);
 	/* start the IFE out devices */
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
 		rc = cam_ife_hw_mgr_start_hw_res(&ctx->res_list_ife_out[i]);
 		if (rc) {
-			pr_err("%s: Can not start IFE OUT (%d)!\n",
-				__func__, i);
+			CAM_ERR(CAM_ISP, "Can not start IFE OUT (%d)!", i);
 			goto err;
 		}
 	}
 
-	CDBG("%s%d START IFE SRC ... in ctx id:%d\n", __func__, __LINE__,
-		ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d", ctx->ctx_index);
 	/* Start the IFE mux in devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not start IFE MUX (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
-	CDBG("%s:%d: START CSID HW ... in ctx id:%d\n", __func__, __LINE__,
-		ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d", ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not start IFE CSID (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
-	CDBG("%s%d START CID SRC ... in ctx id:%d\n", __func__, __LINE__,
-		ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "START CID SRC ... in ctx id:%d", ctx->ctx_index);
 	/* Start the IFE CID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not start IFE CSID (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
 	/* Start IFE root node: do nothing */
-	CDBG("%s: Exit...(success)\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit...(success)");
 	return 0;
 
 err:
 	cam_ife_mgr_stop_hw(hw_mgr_priv, start_hw_args);
-	CDBG("%s: Exit...(rc=%d)\n", __func__, rc);
+	CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc);
 	return rc;
 }
 
@@ -1696,17 +1693,17 @@
 	uint32_t                          i;
 
 	if (!hw_mgr_priv || !start_hw_args) {
-		pr_err("%s%d: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
-		pr_err("%s: Invalid context is used!\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid context is used!");
 		return -EPERM;
 	}
 
-	CDBG("%s%d Enter... ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "Enter... ctx id:%d",
 		ctx->ctx_index);
 
 	/* update Bandwidth should be done at the hw layer */
@@ -1715,127 +1712,127 @@
 
 	/* INIT IFE Root: do nothing */
 
-	CDBG("%s%d INIT IFE CID ... in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
 		ctx->ctx_index);
 	/* INIT IFE CID */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
 		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not INIT IFE CID.(id :%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not INIT IFE CID.(id :%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
 
-	CDBG("%s%d INIT IFE csid ... in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
 		ctx->ctx_index);
 
 	/* INIT IFE csid */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
 		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not INIT IFE CSID.(id :%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not INIT IFE CSID.(id :%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
 	/* INIT IFE SRC */
-	CDBG("%s%d INIT IFE SRC in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
 		ctx->ctx_index);
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
 		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not INIT IFE SRC (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
 	/* INIT IFE OUT */
-	CDBG("%s%d INIT IFE OUT RESOURCES in ctx id:%d\n", __func__,
-		__LINE__, ctx->ctx_index);
+	CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
+		ctx->ctx_index);
 
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
 		rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
 		if (rc) {
-			pr_err("%s: Can not INIT IFE OUT (%d)!\n",
-				__func__, ctx->res_list_ife_out[i].res_id);
+			CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)!",
+				 ctx->res_list_ife_out[i].res_id);
 			goto err;
 		}
 	}
 
-	CDBG("%s: start cdm interface\n", __func__);
+	CAM_DBG(CAM_ISP, "start cdm interface");
 	rc = cam_cdm_stream_on(ctx->cdm_handle);
 	if (rc) {
-		pr_err("%s: Can not start cdm (%d)!\n",
-			__func__, ctx->cdm_handle);
+		CAM_ERR(CAM_ISP, "Can not start cdm (%d)!",
+			 ctx->cdm_handle);
 		goto err;
 	}
 
 	/* Apply initial configuration */
-	CDBG("%s: Config HW\n", __func__);
+	CAM_DBG(CAM_ISP, "Config HW");
 	rc = cam_ife_mgr_config_hw(hw_mgr_priv, start_hw_args);
 	if (rc) {
-		pr_err("%s: Config HW failed\n", __func__);
+		CAM_ERR(CAM_ISP, "Config HW failed");
 		goto err;
 	}
 
-	CDBG("%s%d START IFE OUT ... in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d",
 		ctx->ctx_index);
 	/* start the IFE out devices */
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
 		rc = cam_ife_hw_mgr_start_hw_res(&ctx->res_list_ife_out[i]);
 		if (rc) {
-			pr_err("%s: Can not start IFE OUT (%d)!\n",
-				__func__, i);
+			CAM_ERR(CAM_ISP, "Can not start IFE OUT (%d)!",
+				 i);
 			goto err;
 		}
 	}
 
-	CDBG("%s%d START IFE SRC ... in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d",
 		ctx->ctx_index);
 	/* Start the IFE mux in devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not start IFE MUX (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
-	CDBG("%s:%d: START CSID HW ... in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d",
 		ctx->ctx_index);
 	/* Start the IFE CSID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not start IFE CSID (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
-	CDBG("%s%d START CID SRC ... in ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "START CID SRC ... in ctx id:%d",
 		ctx->ctx_index);
 	/* Start the IFE CID HW devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res);
 		if (rc) {
-			pr_err("%s: Can not start IFE CSID (%d)!\n",
-				__func__, hw_mgr_res->res_id);
+			CAM_ERR(CAM_ISP, "Can not start IFE CSID (%d)!",
+				 hw_mgr_res->res_id);
 			goto err;
 		}
 	}
 
 	/* Start IFE root node: do nothing */
-	CDBG("%s: Exit...(success)\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit...(success)");
 	return 0;
 err:
 	cam_ife_mgr_stop_hw(hw_mgr_priv, start_hw_args);
-	CDBG("%s: Exit...(rc=%d)\n", __func__, rc);
+	CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc);
 	return rc;
 }
 
@@ -1858,17 +1855,17 @@
 	struct cam_ife_hw_mgr_ctx        *ctx;
 
 	if (!hw_mgr_priv || !release_hw_args) {
-		pr_err("%s%d: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	ctx = (struct cam_ife_hw_mgr_ctx *)release_args->ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
-		pr_err("%s: Fatal: Invalid context is used!\n", __func__);
+		CAM_ERR(CAM_ISP, "Fatal: Invalid context is used!");
 		return -EPERM;
 	}
 
-	CDBG("%s%d Enter...ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "Enter...ctx id:%d",
 		ctx->ctx_index);
 
 	/* we should called the stop hw before this already */
@@ -1884,7 +1881,7 @@
 	/* clean context */
 	list_del_init(&ctx->list);
 	ctx->ctx_in_use = 0;
-	CDBG("%s%d Exit...ctx id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "Exit...ctx id:%d",
 		ctx->ctx_index);
 	cam_ife_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx);
 	return rc;
@@ -1898,34 +1895,34 @@
 		(struct cam_hw_prepare_update_args *) prepare_hw_update_args;
 	struct cam_ife_hw_mgr_ctx        *ctx;
 	struct cam_ife_hw_mgr            *hw_mgr;
-	struct cam_isp_kmd_buf_info       kmd_buf;
+	struct cam_kmd_buf_info           kmd_buf;
 	uint32_t                          i;
 	bool                              fill_fence = true;
 
 	if (!hw_mgr_priv || !prepare_hw_update_args) {
-		pr_err("%s: Invalid args\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid args");
 		return -EINVAL;
 	}
 
-	CDBG("%s:%d enter\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "enter");
 
 	ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map;
 	hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv;
 
-	rc = cam_isp_validate_packet(prepare->packet);
+	rc = cam_packet_util_validate_packet(prepare->packet);
 	if (rc)
 		return rc;
 
-	CDBG("%s:%d enter\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "enter");
 	/* Pre parse the packet*/
-	rc = cam_isp_get_kmd_buffer(prepare->packet, &kmd_buf);
+	rc = cam_packet_util_get_kmd_buffer(prepare->packet, &kmd_buf);
 	if (rc)
 		return rc;
 
 	rc = cam_packet_util_process_patches(prepare->packet,
 		hw_mgr->mgr_common.cmd_iommu_hdl);
 	if (rc) {
-		pr_err("%s: Patch ISP packet failed.\n", __func__);
+		CAM_ERR(CAM_ISP, "Patch ISP packet failed.");
 		return rc;
 	}
 
@@ -1934,7 +1931,7 @@
 	prepare->num_out_map_entries = 0;
 
 	for (i = 0; i < ctx->num_base; i++) {
-		CDBG("%s: process cmd buffer for device %d\n", __func__, i);
+		CAM_DBG(CAM_ISP, "process cmd buffer for device %d", i);
 
 		/* Add change base */
 		rc = cam_isp_add_change_base(prepare, &ctx->res_list_ife_src,
@@ -1982,6 +1979,41 @@
 	return rc;
 }
 
+static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
+{
+	int rc = 0;
+	struct cam_isp_hw_cmd_args  *hw_cmd_args  = cmd_args;
+	struct cam_ife_hw_mgr_ctx   *ctx;
+
+	if (!hw_mgr_priv || !cmd_args) {
+		CAM_ERR(CAM_ISP, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map;
+	if (!ctx || !ctx->ctx_in_use) {
+		CAM_ERR(CAM_ISP, "Fatal: Invalid context is used!");
+		return -EPERM;
+	}
+
+	switch (hw_cmd_args->cmd_type) {
+	case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT:
+		if (ctx->is_rdi_only_context)
+			hw_cmd_args->u.is_rdi_only_context = 1;
+		else
+			hw_cmd_args->u.is_rdi_only_context = 0;
+
+		break;
+	default:
+		CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
+			hw_cmd_args->cmd_type);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
 static int cam_ife_mgr_cmd_get_sof_timestamp(
 	struct cam_ife_hw_mgr_ctx      *ife_ctx,
 	uint64_t                       *time_stamp)
@@ -2028,7 +2060,7 @@
 	}
 end:
 	if (rc)
-		pr_err("%s:error in getting sof time stamp\n", __func__);
+		CAM_ERR(CAM_ISP, "error in getting sof time stamp");
 
 	return rc;
 }
@@ -2046,13 +2078,14 @@
 	struct cam_ife_hw_mgr_ctx        *ctx = NULL;
 
 	/* Here recovery is performed */
-	CDBG("%s:Enter: ErrorType = %d\n", __func__, error_type);
+	CAM_DBG(CAM_ISP, "Enter: ErrorType = %d", error_type);
 
 	switch (error_type) {
 	case CAM_ISP_HW_ERROR_OVERFLOW:
 	case CAM_ISP_HW_ERROR_BUSIF_OVERFLOW:
 		if (!recovery_data->affected_ctx[0]) {
-			pr_err("No context is affected but recovery called\n");
+			CAM_ERR(CAM_ISP,
+				"No context is affected but recovery called");
 			kfree(recovery_data);
 			return 0;
 		}
@@ -2080,9 +2113,9 @@
 		break;
 
 	default:
-		pr_err("%s: Invalid Error\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid Error");
 	}
-	CDBG("%s:Exit: ErrorType = %d\n", __func__, error_type);
+	CAM_DBG(CAM_ISP, "Exit: ErrorType = %d", error_type);
 
 	kfree(recovery_data);
 	return rc;
@@ -2105,12 +2138,11 @@
 	memcpy(recovery_data, ife_mgr_recovery_data,
 			sizeof(struct cam_hw_event_recovery_data));
 
-	CDBG("%s: Enter: error_type (%d)\n", __func__,
-		recovery_data->error_type);
+	CAM_DBG(CAM_ISP, "Enter: error_type (%d)", recovery_data->error_type);
 
 	task = cam_req_mgr_workq_get_task(g_ife_hw_mgr.workq);
 	if (!task) {
-		pr_err("%s: No empty task frame\n", __func__);
+		CAM_ERR(CAM_ISP, "No empty task frame");
 		kfree(recovery_data);
 		return -ENOMEM;
 	}
@@ -2139,7 +2171,7 @@
 	uint32_t max_idx =  ife_hwr_mgr_ctx->num_base;
 	uint32_t ctx_affected_core_idx[CAM_IFE_HW_NUM_MAX] = {0};
 
-	CDBG("%s:Enter:max_idx = %d\n", __func__, max_idx);
+	CAM_DBG(CAM_ISP, "Enter:max_idx = %d", max_idx);
 
 	while (i < max_idx) {
 		if (affected_core[ife_hwr_mgr_ctx->base[i].idx])
@@ -2160,7 +2192,7 @@
 			j = j - 1;
 		}
 	}
-	CDBG("%s:Exit\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -2186,11 +2218,11 @@
 	struct cam_hw_stop_args          stop_args;
 	uint32_t i = 0;
 
-	CDBG("%s:Enter\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter");
 	return 0;
 
 	if (!recovery_data) {
-		pr_err("%s: recovery_data parameter is NULL\n",
+		CAM_ERR(CAM_ISP, "recovery_data parameter is NULL",
 			__func__);
 		return -EINVAL;
 	}
@@ -2207,7 +2239,7 @@
 		 * Check if current core_idx matches the HW associated
 		 * with this context
 		 */
-		CDBG("%s:Calling match Hw idx\n", __func__);
+		CAM_DBG(CAM_ISP, "Calling match Hw idx");
 		if (cam_ife_hw_mgr_match_hw_idx(ife_hwr_mgr_ctx, affected_core))
 			continue;
 
@@ -2217,7 +2249,7 @@
 		stop_args.ctxt_to_hw_map = ife_hwr_mgr_ctx;
 
 		/* Add affected_context in list of recovery data*/
-		CDBG("%s:Add new entry in affected_ctx_list\n", __func__);
+		CAM_DBG(CAM_ISP, "Add new entry in affected_ctx_list");
 		if (recovery_data->no_of_context < CAM_CTX_MAX)
 			recovery_data->affected_ctx[
 				recovery_data->no_of_context++] =
@@ -2230,7 +2262,7 @@
 		 */
 		if (!cam_ife_mgr_stop_hw_in_overflow(&hw_mgr_priv,
 			&stop_args)) {
-			CDBG("%s:Calling Error handler CB\n", __func__);
+			CAM_DBG(CAM_ISP, "Calling Error handler CB");
 			ife_hwr_irq_err_cb(ife_hwr_mgr_ctx->common.cb_priv,
 				CAM_ISP_HW_EVENT_ERROR, error_event_data);
 		}
@@ -2238,10 +2270,10 @@
 	/* fill the affected_core in recovery data */
 	for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
 		recovery_data->affected_core[i] = affected_core[i];
-		CDBG("%s: Vfe core %d is affected (%d)\n",
-			__func__, i, recovery_data->affected_core[i]);
+		CAM_DBG(CAM_ISP, "Vfe core %d is affected (%d)",
+			 i, recovery_data->affected_core[i]);
 	}
-	CDBG("%s:Exit\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit");
 	return 0;
 }
 
@@ -2261,7 +2293,7 @@
 	core_idx = evt_payload->core_index;
 
 	rc = evt_payload->error_type;
-	CDBG("%s: Enter: error_type (%d)\n", __func__, evt_payload->error_type);
+	CAM_DBG(CAM_ISP, "Enter: error_type (%d)", evt_payload->error_type);
 	switch (evt_payload->error_type) {
 	case CAM_ISP_HW_ERROR_OVERFLOW:
 	case CAM_ISP_HW_ERROR_P2I_ERROR:
@@ -2280,11 +2312,11 @@
 		cam_ife_hw_mgr_do_error_recovery(&recovery_data);
 		break;
 	default:
-		CDBG("%s: None error. Error type (%d)\n", __func__,
+		CAM_DBG(CAM_ISP, "None error. Error type (%d)",
 			evt_payload->error_type);
 	}
 
-	CDBG("%s: Exit (%d)\n", __func__, rc);
+	CAM_DBG(CAM_ISP, "Exit (%d)", rc);
 	return rc;
 }
 
@@ -2294,26 +2326,26 @@
  * of dual VFE.
  * RDI path does not support DUAl VFE
  */
-static int cam_ife_hw_mgr_handle_rup_for_camif_hw_res(
+static int cam_ife_hw_mgr_handle_reg_update(
 	void                              *handler_priv,
 	void                              *payload)
 {
 	struct cam_isp_resource_node            *hw_res;
 	struct cam_ife_hw_mgr_ctx               *ife_hwr_mgr_ctx;
 	struct cam_vfe_top_irq_evt_payload      *evt_payload;
-	struct cam_ife_hw_mgr_res               *isp_ife_camif_res = NULL;
+	struct cam_ife_hw_mgr_res               *ife_src_res = NULL;
 	cam_hw_event_cb_func                     ife_hwr_irq_rup_cb;
 	struct cam_isp_hw_reg_update_event_data  rup_event_data;
 	uint32_t  core_idx;
 	uint32_t  rup_status = -EINVAL;
 
-	CDBG("%s: Enter\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter");
 
 	ife_hwr_mgr_ctx = handler_priv;
 	evt_payload = payload;
 
 	if (!handler_priv || !payload) {
-		pr_err("%s: Invalid Parameter\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid Parameter");
 		return -EPERM;
 	}
 
@@ -2322,65 +2354,82 @@
 		ife_hwr_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_REG_UPDATE];
 
 	evt_payload->evt_id = CAM_ISP_HW_EVENT_REG_UPDATE;
-	list_for_each_entry(isp_ife_camif_res,
+	list_for_each_entry(ife_src_res,
 			&ife_hwr_mgr_ctx->res_list_ife_src, list) {
 
-		if (isp_ife_camif_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
+		if (ife_src_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
 			continue;
 
-		CDBG("%s: camif resource id = %d, curr_core_idx = %d\n",
-			__func__, isp_ife_camif_res->res_id, core_idx);
-		switch (isp_ife_camif_res->res_id) {
+		CAM_DBG(CAM_ISP, "resource id = %d, curr_core_idx = %d",
+			 ife_src_res->res_id, core_idx);
+		switch (ife_src_res->res_id) {
 		case CAM_ISP_HW_VFE_IN_CAMIF:
-			if (isp_ife_camif_res->is_dual_vfe)
+			if (ife_src_res->is_dual_vfe)
 				/* It checks for slave core RUP ACK*/
-				hw_res = isp_ife_camif_res->hw_res[1];
+				hw_res = ife_src_res->hw_res[1];
 			else
-				hw_res = isp_ife_camif_res->hw_res[0];
+				hw_res = ife_src_res->hw_res[0];
 
 			if (!hw_res) {
-				pr_err("%s: CAMIF device is NULL\n", __func__);
+				CAM_ERR(CAM_ISP, "CAMIF device is NULL");
 				break;
 			}
-			CDBG("%s: current_core_id = %d , core_idx res = %d\n",
-					__func__, core_idx,
-					hw_res->hw_intf->hw_idx);
+			CAM_DBG(CAM_ISP,
+				"current_core_id = %d , core_idx res = %d",
+				 core_idx, hw_res->hw_intf->hw_idx);
 
 			if (core_idx == hw_res->hw_intf->hw_idx) {
 				rup_status = hw_res->bottom_half_handler(
 					hw_res, evt_payload);
 			}
+
+			if (!rup_status) {
+				ife_hwr_irq_rup_cb(
+					ife_hwr_mgr_ctx->common.cb_priv,
+					CAM_ISP_HW_EVENT_REG_UPDATE,
+					&rup_event_data);
+			}
 			break;
 
 		case CAM_ISP_HW_VFE_IN_RDI0:
 		case CAM_ISP_HW_VFE_IN_RDI1:
 		case CAM_ISP_HW_VFE_IN_RDI2:
-			hw_res = isp_ife_camif_res->hw_res[0];
+		case CAM_ISP_HW_VFE_IN_RDI3:
+			if (!ife_hwr_mgr_ctx->is_rdi_only_context)
+				continue;
+
+			/*
+			 * This is RDI only context, send Reg update and epoch
+			 * HW event to cam context
+			 */
+			hw_res = ife_src_res->hw_res[0];
 
 			if (!hw_res) {
-				pr_err("%s: RDI Device is NULL\n", __func__);
+				CAM_ERR(CAM_ISP, "RDI Device is NULL");
 				break;
 			}
+
 			if (core_idx == hw_res->hw_intf->hw_idx)
-				/* Need to process rdi reg update */
-				rup_status = -EINVAL;
+				rup_status = hw_res->bottom_half_handler(
+					hw_res, evt_payload);
+
+			if (!rup_status) {
+				/* Send the Reg update hw event */
+				ife_hwr_irq_rup_cb(
+					ife_hwr_mgr_ctx->common.cb_priv,
+					CAM_ISP_HW_EVENT_REG_UPDATE,
+					&rup_event_data);
+			}
 			break;
 		default:
-			pr_err("%s: invalid resource id (%d)", __func__,
-				isp_ife_camif_res->res_id);
-		}
-
-		/* only do callback for pixel reg update for now */
-		if (!rup_status && (isp_ife_camif_res->res_id ==
-			CAM_ISP_HW_VFE_IN_CAMIF)) {
-			ife_hwr_irq_rup_cb(ife_hwr_mgr_ctx->common.cb_priv,
-				CAM_ISP_HW_EVENT_REG_UPDATE, &rup_event_data);
+			CAM_ERR(CAM_ISP, "Invalid resource id (%d)",
+				ife_src_res->res_id);
 		}
 
 	}
 
 	if (!rup_status)
-		CDBG("%s: Exit rup_status = %d\n", __func__, rup_status);
+		CAM_DBG(CAM_ISP, "Exit rup_status = %d", rup_status);
 
 	return 0;
 }
@@ -2406,13 +2455,13 @@
 	if ((epoch_cnt[core_idx0] - epoch_cnt[core_idx1] > 1) ||
 		(epoch_cnt[core_idx1] - epoch_cnt[core_idx0] > 1)) {
 
-		pr_warn("%s:One of the VFE of dual VFE cound not generate error\n",
-			__func__);
+		CAM_WARN(CAM_ISP,
+			"One of the VFE of dual VFE cound not generate error");
 		rc = -1;
 		return rc;
 	}
 
-	CDBG("Only one core_index has given EPOCH\n");
+	CAM_DBG(CAM_ISP, "Only one core_index has given EPOCH");
 
 	return rc;
 }
@@ -2434,7 +2483,7 @@
 	uint32_t  core_index0;
 	uint32_t  core_index1;
 
-	CDBG("%s:Enter\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter");
 
 	ife_hwr_mgr_ctx = handler_priv;
 	evt_payload = payload;
@@ -2459,8 +2508,7 @@
 		case 0:
 			/* EPOCH check for Left side VFE */
 			if (!hw_res_l) {
-				pr_err("%s: Left Device is NULL\n",
-					__func__);
+				CAM_ERR(CAM_ISP, "Left Device is NULL");
 				break;
 			}
 
@@ -2481,8 +2529,7 @@
 			/* SOF check for Left side VFE (Master)*/
 
 			if ((!hw_res_l) || (!hw_res_r)) {
-				pr_err("%s: Dual VFE Device is NULL\n",
-					__func__);
+				CAM_ERR(CAM_ISP, "Dual VFE Device is NULL");
 				break;
 			}
 			if (core_idx == hw_res_l->hw_intf->hw_idx) {
@@ -2520,13 +2567,13 @@
 
 		/* Error */
 		default:
-			pr_err("%s: error with hw_res\n", __func__);
+			CAM_ERR(CAM_ISP, "error with hw_res");
 
 		}
 	}
 
 	if (!epoch_status)
-		CDBG("%s: Exit epoch_status = %d\n", __func__, epoch_status);
+		CAM_DBG(CAM_ISP, "Exit epoch_status = %d", epoch_status);
 
 	return 0;
 }
@@ -2552,134 +2599,56 @@
 	if ((sof_cnt[core_idx0] - sof_cnt[core_idx1] > 1) ||
 		(sof_cnt[core_idx1] - sof_cnt[core_idx0] > 1)) {
 
-		pr_err("%s: One VFE of dual VFE cound not generate SOF\n",
-					__func__);
+		CAM_ERR(CAM_ISP, "One VFE of dual VFE cound not generate SOF");
 		rc = -1;
 		return rc;
 	}
 
-	pr_info("Only one core_index has given SOF\n");
+	CAM_INFO(CAM_ISP, "Only one core_index has given SOF");
 
 	return rc;
 }
 
-static int cam_ife_hw_mgr_handle_sof_for_camif_hw_res(
-	void                              *handler_priv,
-	void                              *payload)
+static int cam_ife_hw_mgr_process_camif_sof(
+	struct cam_ife_hw_mgr_res            *isp_ife_camif_res,
+	struct cam_ife_hw_mgr_ctx            *ife_hwr_mgr_ctx,
+	struct cam_vfe_top_irq_evt_payload   *evt_payload)
 {
-	int32_t rc = -1;
+	struct cam_isp_hw_sof_event_data      sof_done_event_data;
+	cam_hw_event_cb_func                  ife_hwr_irq_sof_cb;
 	struct cam_isp_resource_node         *hw_res_l = NULL;
 	struct cam_isp_resource_node         *hw_res_r = NULL;
-	struct cam_ife_hw_mgr_ctx            *ife_hwr_mgr_ctx;
-	struct cam_vfe_top_irq_evt_payload   *evt_payload;
-	struct cam_ife_hw_mgr_res            *isp_ife_camif_res = NULL;
-	cam_hw_event_cb_func                  ife_hwr_irq_sof_cb;
-	struct cam_isp_hw_sof_event_data      sof_done_event_data;
+	int32_t rc = -EINVAL;
 	uint32_t  core_idx;
 	uint32_t  sof_status = 0;
 	uint32_t  core_index0;
 	uint32_t  core_index1;
 
-	CDBG("%s:Enter\n", __func__);
-
-	ife_hwr_mgr_ctx = handler_priv;
-	evt_payload = payload;
-	if (!evt_payload) {
-		pr_err("%s: no payload\n", __func__);
-		return IRQ_HANDLED;
-	}
+	CAM_DBG(CAM_ISP, "Enter");
 	core_idx = evt_payload->core_index;
+	hw_res_l = isp_ife_camif_res->hw_res[0];
+	hw_res_r = isp_ife_camif_res->hw_res[1];
+	CAM_DBG(CAM_ISP, "is_dual_vfe ? = %d",
+		isp_ife_camif_res->is_dual_vfe);
+
 	ife_hwr_irq_sof_cb =
 		ife_hwr_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF];
 
-	evt_payload->evt_id = CAM_ISP_HW_EVENT_SOF;
-
-	list_for_each_entry(isp_ife_camif_res,
-		&ife_hwr_mgr_ctx->res_list_ife_src, list) {
-
-		if ((isp_ife_camif_res->res_type ==
-			CAM_IFE_HW_MGR_RES_UNINIT) ||
-			(isp_ife_camif_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF))
-			continue;
-
-		hw_res_l = isp_ife_camif_res->hw_res[0];
-		hw_res_r = isp_ife_camif_res->hw_res[1];
-
-		CDBG("%s:is_dual_vfe ? = %d\n", __func__,
-			isp_ife_camif_res->is_dual_vfe);
-		switch (isp_ife_camif_res->is_dual_vfe) {
-		/* Handling Single VFE Scenario */
-		case 0:
-			/* SOF check for Left side VFE */
-			if (!hw_res_l) {
-				pr_err("%s: VFE Device is NULL\n",
-					__func__);
-				break;
-			}
-			CDBG("%s: curr_core_idx = %d, core idx hw = %d\n",
-					__func__, core_idx,
-					hw_res_l->hw_intf->hw_idx);
-
-			if (core_idx == hw_res_l->hw_intf->hw_idx) {
-				sof_status = hw_res_l->bottom_half_handler(
-					hw_res_l, evt_payload);
-				if (!sof_status) {
-					cam_ife_mgr_cmd_get_sof_timestamp(
-						ife_hwr_mgr_ctx,
-						&sof_done_event_data.timestamp);
-
-					ife_hwr_irq_sof_cb(
-						ife_hwr_mgr_ctx->common.cb_priv,
-						CAM_ISP_HW_EVENT_SOF,
-						&sof_done_event_data);
-				}
-			}
-
+	switch (isp_ife_camif_res->is_dual_vfe) {
+	/* Handling Single VFE Scenario */
+	case 0:
+		/* SOF check for Left side VFE */
+		if (!hw_res_l) {
+			CAM_ERR(CAM_ISP, "VFE Device is NULL");
 			break;
+		}
+		CAM_DBG(CAM_ISP, "curr_core_idx = %d,core idx hw = %d",
+			core_idx, hw_res_l->hw_intf->hw_idx);
 
-		/* Handling Dual VFE Scenario */
-		case 1:
-			/* SOF check for Left side VFE */
-
-			if (!hw_res_l) {
-				pr_err("%s: VFE Device is NULL\n",
-					__func__);
-				break;
-			}
-			CDBG("%s: curr_core_idx = %d, idx associated hw = %d\n",
-					__func__, core_idx,
-					hw_res_l->hw_intf->hw_idx);
-
-			if (core_idx == hw_res_l->hw_intf->hw_idx) {
-				sof_status = hw_res_l->bottom_half_handler(
-					hw_res_l, evt_payload);
-				if (!sof_status)
-					ife_hwr_mgr_ctx->sof_cnt[core_idx]++;
-			}
-
-			/* SOF check for Right side VFE */
-			if (!hw_res_r) {
-				pr_err("%s: VFE Device is NULL\n",
-					__func__);
-				break;
-			}
-			CDBG("%s: curr_core_idx = %d, idx associated hw = %d\n",
-					__func__, core_idx,
-					hw_res_r->hw_intf->hw_idx);
-			if (core_idx == hw_res_r->hw_intf->hw_idx) {
-				sof_status = hw_res_r->bottom_half_handler(
-					hw_res_r, evt_payload);
-				if (!sof_status)
-					ife_hwr_mgr_ctx->sof_cnt[core_idx]++;
-			}
-
-			core_index0 = hw_res_l->hw_intf->hw_idx;
-			core_index1 = hw_res_r->hw_intf->hw_idx;
-
-			rc = cam_ife_hw_mgr_check_sof_for_dual_vfe(
-				ife_hwr_mgr_ctx, core_index0, core_index1);
-
-			if (!rc) {
+		if (core_idx == hw_res_l->hw_intf->hw_idx) {
+			sof_status = hw_res_l->bottom_half_handler(hw_res_l,
+				evt_payload);
+			if (!sof_status) {
 				cam_ife_mgr_cmd_get_sof_timestamp(
 					ife_hwr_mgr_ctx,
 					&sof_done_event_data.timestamp);
@@ -2689,14 +2658,138 @@
 					CAM_ISP_HW_EVENT_SOF,
 					&sof_done_event_data);
 			}
+		}
+
+		break;
+
+	/* Handling Dual VFE Scenario */
+	case 1:
+		/* SOF check for Left side VFE */
+
+		if (!hw_res_l) {
+			CAM_ERR(CAM_ISP, "VFE Device is NULL");
+			break;
+		}
+		CAM_DBG(CAM_ISP, "curr_core_idx = %d, res hw idx= %d",
+				 core_idx,
+				hw_res_l->hw_intf->hw_idx);
+
+		if (core_idx == hw_res_l->hw_intf->hw_idx) {
+			sof_status = hw_res_l->bottom_half_handler(
+				hw_res_l, evt_payload);
+			if (!sof_status)
+				ife_hwr_mgr_ctx->sof_cnt[core_idx]++;
+		}
+
+		/* SOF check for Right side VFE */
+		if (!hw_res_r) {
+			CAM_ERR(CAM_ISP, "VFE Device is NULL");
+			break;
+		}
+		CAM_DBG(CAM_ISP, "curr_core_idx = %d, ews hw idx= %d",
+				 core_idx,
+				hw_res_r->hw_intf->hw_idx);
+		if (core_idx == hw_res_r->hw_intf->hw_idx) {
+			sof_status = hw_res_r->bottom_half_handler(hw_res_r,
+				evt_payload);
+			if (!sof_status)
+				ife_hwr_mgr_ctx->sof_cnt[core_idx]++;
+		}
+
+		core_index0 = hw_res_l->hw_intf->hw_idx;
+		core_index1 = hw_res_r->hw_intf->hw_idx;
+
+		rc = cam_ife_hw_mgr_check_sof_for_dual_vfe(ife_hwr_mgr_ctx,
+			core_index0, core_index1);
+
+		if (!rc)
+			ife_hwr_irq_sof_cb(ife_hwr_mgr_ctx->common.cb_priv,
+				CAM_ISP_HW_EVENT_SOF, &sof_done_event_data);
+
+		break;
+
+	default:
+		CAM_ERR(CAM_ISP, "error with hw_res");
+		break;
+	}
+
+	CAM_DBG(CAM_ISP, "Exit (sof_status = %d)!", sof_status);
+
+	return 0;
+}
+
+static int cam_ife_hw_mgr_handle_sof(
+	void                              *handler_priv,
+	void                              *payload)
+{
+	int32_t rc = -EINVAL;
+	struct cam_isp_resource_node         *hw_res = NULL;
+	struct cam_ife_hw_mgr_ctx            *ife_hw_mgr_ctx;
+	struct cam_vfe_top_irq_evt_payload   *evt_payload;
+	struct cam_ife_hw_mgr_res            *ife_src_res = NULL;
+	cam_hw_event_cb_func                  ife_hw_irq_sof_cb;
+	struct cam_isp_hw_sof_event_data      sof_done_event_data;
+	uint32_t  sof_status = 0;
+
+	CAM_DBG(CAM_ISP, "Enter");
+
+	ife_hw_mgr_ctx = handler_priv;
+	evt_payload = payload;
+	if (!evt_payload) {
+		CAM_ERR(CAM_ISP, "no payload");
+		return IRQ_HANDLED;
+	}
+	ife_hw_irq_sof_cb =
+		ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF];
+
+	evt_payload->evt_id = CAM_ISP_HW_EVENT_SOF;
+
+	list_for_each_entry(ife_src_res,
+		&ife_hw_mgr_ctx->res_list_ife_src, list) {
+
+		if (ife_src_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
+			continue;
+
+		switch (ife_src_res->res_id) {
+		case CAM_ISP_HW_VFE_IN_RDI0:
+		case CAM_ISP_HW_VFE_IN_RDI1:
+		case CAM_ISP_HW_VFE_IN_RDI2:
+		case CAM_ISP_HW_VFE_IN_RDI3:
+			/* check if it is rdi only context */
+			if (ife_hw_mgr_ctx->is_rdi_only_context) {
+				hw_res = ife_src_res->hw_res[0];
+				sof_status = hw_res->bottom_half_handler(
+					hw_res, evt_payload);
+
+				if (!sof_status) {
+					cam_ife_mgr_cmd_get_sof_timestamp(
+						ife_hw_mgr_ctx,
+						&sof_done_event_data.timestamp);
+
+					ife_hw_irq_sof_cb(
+						ife_hw_mgr_ctx->common.cb_priv,
+						CAM_ISP_HW_EVENT_SOF,
+						&sof_done_event_data);
+				}
+
+				CAM_DBG(CAM_ISP, "sof_status = %d", sof_status);
+
+				/* this is RDI only context so exit from here */
+				return 0;
+			}
 			break;
 
+		case CAM_ISP_HW_VFE_IN_CAMIF:
+			rc = cam_ife_hw_mgr_process_camif_sof(ife_src_res,
+				ife_hw_mgr_ctx, evt_payload);
+			break;
 		default:
-			pr_err("%s: error with hw_res\n", __func__);
+			CAM_ERR(CAM_ISP, "Invalid resource id :%d",
+				ife_src_res->res_id);
+			break;
 		}
 	}
 
-	CDBG("%s: Exit (sof_status = %d)!\n", __func__, sof_status);
 	return 0;
 }
 
@@ -2719,7 +2812,7 @@
 	uint32_t  error_resc_handle[CAM_IFE_HW_OUT_RES_MAX];
 	uint32_t  num_of_error_handles = 0;
 
-	CDBG("%s:Enter\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter");
 
 	ife_hwr_mgr_ctx = evt_payload->ctx;
 	ife_hwr_irq_wm_done_cb =
@@ -2782,7 +2875,7 @@
 			/* Report for Successful buf_done event if any */
 			if (buf_done_event_data.num_handles > 0 &&
 				ife_hwr_irq_wm_done_cb) {
-				CDBG("%s: notify isp context\n", __func__);
+				CAM_DBG(CAM_ISP, "notify isp context");
 				ife_hwr_irq_wm_done_cb(
 					ife_hwr_mgr_ctx->common.cb_priv,
 					CAM_ISP_HW_EVENT_DONE,
@@ -2802,8 +2895,9 @@
 			break;
 		}
 		if (!buf_done_status)
-			CDBG("buf_done status:(%d),out_res->res_id: 0x%x\n",
-			buf_done_status, isp_ife_out_res->res_id);
+			CAM_DBG(CAM_ISP,
+				"buf_done status:(%d),out_res->res_id: 0x%x",
+				buf_done_status, isp_ife_out_res->res_id);
 	}
 
 	return rc;
@@ -2824,8 +2918,8 @@
 	 * for the first phase, we are going to reset entire HW.
 	 */
 
-	CDBG("%s: Exit (buf_done_status (Error) = %d)!\n", __func__,
-			buf_done_status);
+	CAM_DBG(CAM_ISP, "Exit (buf_done_status (Error) = %d)!",
+		buf_done_status);
 	return rc;
 }
 
@@ -2842,16 +2936,19 @@
 	evt_payload = evt_payload_priv;
 	ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)evt_payload->ctx;
 
-	CDBG("addr of evt_payload = %llx\n", (uint64_t)evt_payload);
-	CDBG("bus_irq_status_0: = %x\n", evt_payload->irq_reg_val[0]);
-	CDBG("bus_irq_status_1: = %x\n", evt_payload->irq_reg_val[1]);
-	CDBG("bus_irq_status_2: = %x\n", evt_payload->irq_reg_val[2]);
-	CDBG("bus_irq_comp_err: = %x\n", evt_payload->irq_reg_val[3]);
-	CDBG("bus_irq_comp_owrt: = %x\n", evt_payload->irq_reg_val[4]);
-	CDBG("bus_irq_dual_comp_err: = %x\n", evt_payload->irq_reg_val[5]);
-	CDBG("bus_irq_dual_comp_owrt: = %x\n", evt_payload->irq_reg_val[6]);
+	CAM_DBG(CAM_ISP, "addr of evt_payload = %llx", (uint64_t)evt_payload);
+	CAM_DBG(CAM_ISP, "bus_irq_status_0: = %x", evt_payload->irq_reg_val[0]);
+	CAM_DBG(CAM_ISP, "bus_irq_status_1: = %x", evt_payload->irq_reg_val[1]);
+	CAM_DBG(CAM_ISP, "bus_irq_status_2: = %x", evt_payload->irq_reg_val[2]);
+	CAM_DBG(CAM_ISP, "bus_irq_comp_err: = %x", evt_payload->irq_reg_val[3]);
+	CAM_DBG(CAM_ISP, "bus_irq_comp_owrt: = %x",
+		evt_payload->irq_reg_val[4]);
+	CAM_DBG(CAM_ISP, "bus_irq_dual_comp_err: = %x",
+		evt_payload->irq_reg_val[5]);
+	CAM_DBG(CAM_ISP, "bus_irq_dual_comp_owrt: = %x",
+		evt_payload->irq_reg_val[6]);
 
-	CDBG("%s: Calling Buf_done\n", __func__);
+	CAM_DBG(CAM_ISP, "Calling Buf_done");
 	/* WM Done */
 	return cam_ife_hw_mgr_handle_buf_done_for_hw_res(ife_hwr_mgr_ctx,
 		evt_payload_priv);
@@ -2869,10 +2966,11 @@
 	evt_payload = evt_payload_priv;
 	ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)handler_priv;
 
-	CDBG("addr of evt_payload = %llx\n", (uint64_t)evt_payload);
-	CDBG("irq_status_0: = %x\n", evt_payload->irq_reg_val[0]);
-	CDBG("irq_status_1: = %x\n", evt_payload->irq_reg_val[1]);
-	CDBG("Violation register: = %x\n", evt_payload->irq_reg_val[2]);
+	CAM_DBG(CAM_ISP, "addr of evt_payload = %llx", (uint64_t)evt_payload);
+	CAM_DBG(CAM_ISP, "irq_status_0: = %x", evt_payload->irq_reg_val[0]);
+	CAM_DBG(CAM_ISP, "irq_status_1: = %x", evt_payload->irq_reg_val[1]);
+	CAM_DBG(CAM_ISP, "Violation register: = %x",
+		evt_payload->irq_reg_val[2]);
 
 	/*
 	 * If overflow/overwrite/error/violation are pending
@@ -2882,22 +2980,22 @@
 	rc = cam_ife_hw_mgr_handle_camif_error(ife_hwr_mgr_ctx,
 		evt_payload_priv);
 	if (rc) {
-		pr_err("%s: Encountered Error (%d), ignoring other irqs\n",
-			__func__, rc);
+		CAM_ERR(CAM_ISP, "Encountered Error (%d), ignoring other irqs",
+			 rc);
 		return IRQ_HANDLED;
 	}
 
-	CDBG("%s: Calling SOF\n", __func__);
+	CAM_DBG(CAM_ISP, "Calling SOF");
 	/* SOF IRQ */
-	cam_ife_hw_mgr_handle_sof_for_camif_hw_res(ife_hwr_mgr_ctx,
+	cam_ife_hw_mgr_handle_sof(ife_hwr_mgr_ctx,
 		evt_payload_priv);
 
-	CDBG("%s: Calling RUP\n", __func__);
+	CAM_DBG(CAM_ISP, "Calling RUP");
 	/* REG UPDATE */
-	cam_ife_hw_mgr_handle_rup_for_camif_hw_res(ife_hwr_mgr_ctx,
+	cam_ife_hw_mgr_handle_reg_update(ife_hwr_mgr_ctx,
 		evt_payload_priv);
 
-	CDBG("%s: Calling EPOCH\n", __func__);
+	CAM_DBG(CAM_ISP, "Calling EPOCH");
 	/* EPOCH IRQ */
 	cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(ife_hwr_mgr_ctx,
 		evt_payload_priv);
@@ -2943,15 +3041,14 @@
 	int i, j;
 	struct cam_iommu_handle cdm_handles;
 
-	CDBG("%s: Enter\n", __func__);
+	CAM_DBG(CAM_ISP, "Enter");
 
 	memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr));
 
 	mutex_init(&g_ife_hw_mgr.ctx_mutex);
 
 	if (CAM_IFE_HW_NUM_MAX != CAM_IFE_CSID_HW_NUM_MAX) {
-		pr_err("%s: Fatal, CSID num is different then IFE num!\n",
-			__func__);
+		CAM_ERR(CAM_ISP, "Fatal, CSID num is different then IFE num!");
 		goto end;
 	}
 
@@ -2967,15 +3064,16 @@
 			j++;
 
 			g_ife_hw_mgr.cdm_reg_map[i] = &soc_info->reg_map[0];
-			CDBG("reg_map: mem base = 0x%llx, cam_base = 0x%llx\n",
-				(uint64_t) soc_info->reg_map[0].mem_base,
+			CAM_DBG(CAM_ISP,
+				"reg_map: mem base = %pK cam_base = 0x%llx",
+				(void __iomem *)soc_info->reg_map[0].mem_base,
 				(uint64_t) soc_info->reg_map[0].mem_cam_base);
 		} else {
 			g_ife_hw_mgr.cdm_reg_map[i] = NULL;
 		}
 	}
 	if (j == 0) {
-		pr_err("%s: no valid IFE HW!\n", __func__);
+		CAM_ERR(CAM_ISP, "no valid IFE HW!");
 		goto end;
 	}
 
@@ -2986,7 +3084,7 @@
 			j++;
 	}
 	if (!j) {
-		pr_err("%s: no valid IFE CSID HW!\n", __func__);
+		CAM_ERR(CAM_ISP, "no valid IFE CSID HW!");
 		goto end;
 	}
 
@@ -3005,26 +3103,27 @@
 	 */
 	if (cam_smmu_get_handle("ife",
 		&g_ife_hw_mgr.mgr_common.img_iommu_hdl)) {
-		pr_err("%s: Can not get iommu handle.\n", __func__);
+		CAM_ERR(CAM_ISP, "Can not get iommu handle.");
 		goto end;
 	}
 
 	if (cam_smmu_ops(g_ife_hw_mgr.mgr_common.img_iommu_hdl,
 		CAM_SMMU_ATTACH)) {
-		pr_err("%s: Attach iommu handle failed.\n", __func__);
+		CAM_ERR(CAM_ISP, "Attach iommu handle failed.");
 		goto end;
 	}
 
-	CDBG("got iommu_handle=%d\n", g_ife_hw_mgr.mgr_common.img_iommu_hdl);
+	CAM_DBG(CAM_ISP, "got iommu_handle=%d",
+		g_ife_hw_mgr.mgr_common.img_iommu_hdl);
 	g_ife_hw_mgr.mgr_common.img_iommu_hdl_secure = -1;
 
 	if (!cam_cdm_get_iommu_handle("ife", &cdm_handles)) {
-		CDBG("Successfully acquired the CDM iommu handles\n");
+		CAM_DBG(CAM_ISP, "Successfully acquired the CDM iommu handles");
 		g_ife_hw_mgr.mgr_common.cmd_iommu_hdl = cdm_handles.non_secure;
 		g_ife_hw_mgr.mgr_common.cmd_iommu_hdl_secure =
 			cdm_handles.secure;
 	} else {
-		CDBG("Failed to acquire the CDM iommu handles\n");
+		CAM_DBG(CAM_ISP, "Failed to acquire the CDM iommu handles");
 		g_ife_hw_mgr.mgr_common.cmd_iommu_hdl = -1;
 		g_ife_hw_mgr.mgr_common.cmd_iommu_hdl_secure = -1;
 	}
@@ -3059,7 +3158,7 @@
 				 sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
 		if (!g_ife_hw_mgr.ctx_pool[i].cdm_cmd) {
 			rc = -ENOMEM;
-			pr_err("Allocation Failed for cdm command\n");
+			CAM_ERR(CAM_ISP, "Allocation Failed for cdm command");
 			goto end;
 		}
 
@@ -3080,7 +3179,7 @@
 			&g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ);
 
 	if (rc < 0) {
-		pr_err("%s: Unable to create worker\n", __func__);
+		CAM_ERR(CAM_ISP, "Unable to create worker");
 		goto end;
 	}
 
@@ -3095,8 +3194,9 @@
 	hw_mgr_intf->hw_release = cam_ife_mgr_release_hw;
 	hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update;
 	hw_mgr_intf->hw_config = cam_ife_mgr_config_hw;
+	hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd;
 
-	CDBG("%s: Exit\n", __func__);
+	CAM_DBG(CAM_ISP, "Exit");
 	return 0;
 end:
 	if (rc) {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 174d2ce..6dfdb21 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -108,6 +108,7 @@
  * @epoch_cnt               epoch count value per core, used for dual VFE
  * @overflow_pending        flat to specify the overflow is pending for the
  *                          context
+ * @is_rdi_only_context     flag to specify the context has only rdi resource
  */
 struct cam_ife_hw_mgr_ctx {
 	struct list_head                list;
@@ -138,6 +139,7 @@
 	uint32_t                        sof_cnt[CAM_IFE_HW_NUM_MAX];
 	uint32_t                        epoch_cnt[CAM_IFE_HW_NUM_MAX];
 	atomic_t                        overflow_pending;
+	uint32_t                        is_rdi_only_context;
 
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c
index 2e23222..2f18895 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c
@@ -12,6 +12,7 @@
 
 #include "cam_isp_hw_mgr_intf.h"
 #include "cam_ife_hw_mgr.h"
+#include "cam_debug_util.h"
 
 
 int cam_isp_hw_mgr_init(struct device_node *of_node,
@@ -26,7 +27,7 @@
 	if (strnstr(compat_str, "ife", strlen(compat_str)))
 		rc = cam_ife_hw_mgr_init(hw_mgr);
 	else {
-		pr_err("%s: Invalid ISP hw type\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid ISP hw type");
 		rc = -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index 3c72279..0a0eecb 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -15,130 +15,13 @@
 #include "cam_mem_mgr.h"
 #include "cam_vfe_hw_intf.h"
 #include "cam_isp_packet_parser.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-
-static int cam_isp_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
-	size_t *len)
-{
-	int rc = 0;
-	uint64_t kmd_buf_addr = 0;
-
-	rc = cam_mem_get_cpu_buf(handle, &kmd_buf_addr, len);
-	if (rc) {
-		pr_err("%s:%d Unable to get the virtual address rc:%d\n",
-			__func__, __LINE__, rc);
-		rc = -ENOMEM;
-	} else {
-		if (kmd_buf_addr && *len)
-			*buf_addr = (uint32_t *)kmd_buf_addr;
-		else {
-			pr_err("%s:%d Invalid addr and length :%ld\n",
-				__func__, __LINE__, *len);
-			rc = -ENOMEM;
-		}
-	}
-	return rc;
-}
-
-static int cam_isp_validate_cmd_desc(
-	struct cam_cmd_buf_desc *cmd_desc)
-{
-	if (cmd_desc->length > cmd_desc->size ||
-		(cmd_desc->mem_handle <= 0)) {
-		pr_err("%s:%d invalid cmd arg %d %d %d %d\n",
-			__func__, __LINE__, cmd_desc->offset,
-			cmd_desc->length, cmd_desc->mem_handle,
-			cmd_desc->size);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int cam_isp_validate_packet(struct cam_packet *packet)
-{
-	if (!packet)
-		return -EINVAL;
-
-	CDBG("%s:%d num cmd buf:%d num of io config:%d kmd buf index:%d\n",
-		__func__, __LINE__, packet->num_cmd_buf,
-		packet->num_io_configs, packet->kmd_cmd_buf_index);
-
-	if (packet->kmd_cmd_buf_index >= packet->num_cmd_buf ||
-		(!packet->header.size) ||
-		packet->cmd_buf_offset > packet->header.size ||
-		packet->io_configs_offset > packet->header.size)  {
-		pr_err("%s:%d invalid packet:%d %d %d %d %d\n",
-			__func__, __LINE__, packet->kmd_cmd_buf_index,
-			packet->num_cmd_buf, packet->cmd_buf_offset,
-			packet->io_configs_offset, packet->header.size);
-		return -EINVAL;
-	}
-
-	CDBG("%s:%d exit\n", __func__, __LINE__);
-	return 0;
-}
-
-int cam_isp_get_kmd_buffer(struct cam_packet *packet,
-	struct cam_isp_kmd_buf_info *kmd_buf)
-{
-	int                      rc = 0;
-	size_t                   len = 0;
-	struct cam_cmd_buf_desc *cmd_desc;
-	uint32_t                *cpu_addr;
-
-	if (!packet || !kmd_buf) {
-		pr_err("%s:%d Invalid arg\n", __func__, __LINE__);
-		rc = -EINVAL;
-		return rc;
-	}
-
-	/* Take first command descriptor and add offset to it for kmd*/
-	cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)
-			&packet->payload + packet->cmd_buf_offset);
-	cmd_desc += packet->kmd_cmd_buf_index;
-
-	CDBG("%s:%d enter\n", __func__, __LINE__);
-	rc = cam_isp_validate_cmd_desc(cmd_desc);
-	if (rc)
-		return rc;
-
-	CDBG("%s:%d enter\n", __func__, __LINE__);
-	rc = cam_isp_get_cmd_mem_addr(cmd_desc->mem_handle, &cpu_addr,
-		&len);
-	if (rc)
-		return rc;
-
-	if (len < cmd_desc->size) {
-		pr_err("%s:%d invalid memory len:%ld and cmd desc size:%d\n",
-			__func__, __LINE__, len, cmd_desc->size);
-		return -EINVAL;
-	}
-
-	cpu_addr += cmd_desc->offset/4 + packet->kmd_cmd_buf_offset/4;
-	CDBG("%s:%d total size %d, cmd size: %d, KMD buffer size: %d\n",
-		__func__, __LINE__, cmd_desc->size, cmd_desc->length,
-		cmd_desc->size - cmd_desc->length);
-	CDBG("%s:%d: handle 0x%x, cmd offset %d, kmd offset %d, addr 0x%pK\n",
-		__func__, __LINE__, cmd_desc->mem_handle, cmd_desc->offset,
-		packet->kmd_cmd_buf_offset, cpu_addr);
-
-	kmd_buf->cpu_addr   = cpu_addr;
-	kmd_buf->handle     = cmd_desc->mem_handle;
-	kmd_buf->offset     = cmd_desc->offset + packet->kmd_cmd_buf_offset;
-	kmd_buf->size       = cmd_desc->size - cmd_desc->length;
-	kmd_buf->used_bytes = 0;
-
-	return rc;
-}
+#include "cam_debug_util.h"
 
 int cam_isp_add_change_base(
 	struct cam_hw_prepare_update_args      *prepare,
 	struct list_head                       *res_list_isp_src,
 	uint32_t                                base_idx,
-	struct cam_isp_kmd_buf_info            *kmd_buf_info)
+	struct cam_kmd_buf_info                *kmd_buf_info)
 {
 	int rc = -EINVAL;
 	struct cam_ife_hw_mgr_res       *hw_mgr_res;
@@ -152,9 +35,8 @@
 
 	/* Max one hw entries required for each base */
 	if (num_ent + 1 >= prepare->max_hw_update_entries) {
-		pr_err("%s:%d Insufficient  HW entries :%d %d\n",
-			__func__, __LINE__, num_ent,
-			prepare->max_hw_update_entries);
+		CAM_ERR(CAM_ISP, "Insufficient  HW entries :%d %d",
+			num_ent, prepare->max_hw_update_entries);
 		return -EINVAL;
 	}
 
@@ -220,8 +102,8 @@
 			((uint8_t *)&prepare->packet->payload +
 			prepare->packet->cmd_buf_offset);
 
-	CDBG("%s:%d split id = %d, number of command buffers:%d\n", __func__,
-		__LINE__, split_id, prepare->packet->num_cmd_buf);
+	CAM_DBG(CAM_ISP, "split id = %d, number of command buffers:%d",
+		split_id, prepare->packet->num_cmd_buf);
 
 	for (i = 0; i < prepare->packet->num_cmd_buf; i++) {
 		if (!cmd_desc[i].length)
@@ -229,19 +111,18 @@
 
 		/* One hw entry space required for left or right or common */
 		if (num_ent + 1 >= prepare->max_hw_update_entries) {
-			pr_err("%s:%d Insufficient  HW entries :%d %d\n",
-				__func__, __LINE__, num_ent,
-				prepare->max_hw_update_entries);
+			CAM_ERR(CAM_ISP, "Insufficient  HW entries :%d %d",
+				num_ent, prepare->max_hw_update_entries);
 			return -EINVAL;
 		}
 
-		rc = cam_isp_validate_cmd_desc(&cmd_desc[i]);
+		rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]);
 		if (rc)
 			return rc;
 
 		cmd_meta_data = cmd_desc[i].meta_data;
 
-		CDBG("%s:%d meta type: %d, split_id: %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_ISP, "meta type: %d, split_id: %d",
 			cmd_meta_data, split_id);
 
 		switch (cmd_meta_data) {
@@ -288,8 +169,8 @@
 			num_ent++;
 			break;
 		default:
-			pr_err("%s:%d invalid cdm command meta data %d\n",
-			__func__, __LINE__, cmd_meta_data);
+			CAM_ERR(CAM_ISP, "invalid cdm command meta data %d",
+				cmd_meta_data);
 			return -EINVAL;
 		}
 	}
@@ -304,7 +185,7 @@
 	int                                   iommu_hdl,
 	struct cam_hw_prepare_update_args    *prepare,
 	uint32_t                              base_idx,
-	struct cam_isp_kmd_buf_info          *kmd_buf_info,
+	struct cam_kmd_buf_info              *kmd_buf_info,
 	struct cam_ife_hw_mgr_res            *res_list_isp_out,
 	uint32_t                              size_isp_out,
 	bool                                  fill_fence)
@@ -331,33 +212,31 @@
 	/* Max one hw entries required for each base */
 	if (prepare->num_hw_update_entries + 1 >=
 			prepare->max_hw_update_entries) {
-		pr_err("%s:%d Insufficient  HW entries :%d %d\n",
-			__func__, __LINE__, prepare->num_hw_update_entries,
+		CAM_ERR(CAM_ISP, "Insufficient  HW entries :%d %d",
+			prepare->num_hw_update_entries,
 			prepare->max_hw_update_entries);
 		return -EINVAL;
 	}
 
 	for (i = 0; i < prepare->packet->num_io_configs; i++) {
-		CDBG("%s:%d ======= io config idx %d ============\n",
-			__func__, __LINE__, i);
-		CDBG("%s:%d resource_type:%d fence:%d\n", __func__, __LINE__,
+		CAM_DBG(CAM_ISP, "======= io config idx %d ============", i);
+		CAM_DBG(CAM_ISP, "resource_type:%d fence:%d",
 			io_cfg[i].resource_type, io_cfg[i].fence);
-		CDBG("%s:%d format: %d\n", __func__, __LINE__,
-			io_cfg[i].format);
-		CDBG("%s:%d direction %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format);
+		CAM_DBG(CAM_ISP, "direction %d",
 			io_cfg[i].direction);
 
 		if (io_cfg[i].direction == CAM_BUF_OUTPUT) {
 			res_id_out = io_cfg[i].resource_type & 0xFF;
 			if (res_id_out >= size_isp_out) {
-				pr_err("%s:%d invalid out restype:%x\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_ISP, "invalid out restype:%x",
 					io_cfg[i].resource_type);
 				return -EINVAL;
 			}
 
-			CDBG("%s:%d configure output io with fill fence %d\n",
-				__func__, __LINE__, fill_fence);
+			CAM_DBG(CAM_ISP,
+				"configure output io with fill fence %d",
+				fill_fence);
 			if (fill_fence) {
 				if (num_out_buf <
 					prepare->max_out_map_entries) {
@@ -368,8 +247,7 @@
 						sync_id = io_cfg[i].fence;
 					num_out_buf++;
 				} else {
-					pr_err("%s:%d ln_out:%d max_ln:%d\n",
-						__func__, __LINE__,
+					CAM_ERR(CAM_ISP, "ln_out:%d max_ln:%d",
 						num_out_buf,
 						prepare->max_out_map_entries);
 					return -EINVAL;
@@ -378,15 +256,15 @@
 
 			hw_mgr_res = &res_list_isp_out[res_id_out];
 			if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT) {
-				pr_err("%s:%d io res id:%d not valid\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_ISP, "io res id:%d not valid",
 					io_cfg[i].resource_type);
 				return -EINVAL;
 			}
 		} else if (io_cfg[i].direction == CAM_BUF_INPUT) {
 			res_id_in = io_cfg[i].resource_type & 0xFF;
-			CDBG("%s:%d configure input io with fill fence %d\n",
-				__func__, __LINE__, fill_fence);
+			CAM_DBG(CAM_ISP,
+				"configure input io with fill fence %d",
+				fill_fence);
 			if (fill_fence) {
 				if (num_in_buf < prepare->max_in_map_entries) {
 					prepare->in_map_entries[num_in_buf].
@@ -397,8 +275,7 @@
 							io_cfg[i].fence;
 					num_in_buf++;
 				} else {
-					pr_err("%s:%d ln_in:%d imax_ln:%d\n",
-						__func__, __LINE__,
+					CAM_ERR(CAM_ISP, "ln_in:%d imax_ln:%d",
 						num_in_buf,
 						prepare->max_in_map_entries);
 					return -EINVAL;
@@ -406,13 +283,12 @@
 			}
 			continue;
 		} else {
-			pr_err("%s:%d Invalid io config direction :%d\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_ISP, "Invalid io config direction :%d",
 				io_cfg[i].direction);
 			return -EINVAL;
 		}
 
-		CDBG("%s:%d setup mem io\n", __func__, __LINE__);
+		CAM_DBG(CAM_ISP, "setup mem io");
 		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
 			if (!hw_mgr_res->hw_res[j])
 				continue;
@@ -422,9 +298,9 @@
 
 			res = hw_mgr_res->hw_res[j];
 			if (res->res_id != io_cfg[i].resource_type) {
-				pr_err("%s:%d wm err res id:%d io res id:%d\n",
-					__func__, __LINE__, res->res_id,
-					io_cfg[i].resource_type);
+				CAM_ERR(CAM_ISP,
+					"wm err res id:%d io res id:%d",
+					res->res_id, io_cfg[i].resource_type);
 				return -EINVAL;
 			}
 
@@ -439,14 +315,16 @@
 					io_cfg[i].mem_handle[plane_id],
 					iommu_hdl, &io_addr[plane_id], &size);
 				if (rc) {
-					pr_err("%s:%d no io addr for plane%d\n",
-						__func__, __LINE__, plane_id);
+					CAM_ERR(CAM_ISP,
+						"no io addr for plane%d",
+						plane_id);
 					rc = -ENOMEM;
 					return rc;
 				}
 
 				if (io_addr[plane_id] >> 32) {
-					pr_err("Invalid mapped address\n");
+					CAM_ERR(CAM_ISP,
+						"Invalid mapped address");
 					rc = -EINVAL;
 					return rc;
 				}
@@ -454,13 +332,13 @@
 				/* need to update with offset */
 				io_addr[plane_id] +=
 						io_cfg[i].offsets[plane_id];
-				CDBG("%s: get io_addr for plane %d: 0x%llx\n",
-					__func__, plane_id,
-					io_addr[plane_id]);
+				CAM_DBG(CAM_ISP,
+					"get io_addr for plane %d: 0x%llx",
+					plane_id, io_addr[plane_id]);
 			}
 			if (!plane_id) {
-				pr_err("%s:%d No valid planes for res%d\n",
-					__func__, __LINE__, res->res_id);
+				CAM_ERR(CAM_ISP, "No valid planes for res%d",
+					res->res_id);
 				rc = -ENOMEM;
 				return rc;
 			}
@@ -471,8 +349,9 @@
 					(kmd_buf_info->used_bytes +
 					io_cfg_used_bytes);
 			} else {
-				pr_err("%s:%d no free kmd memory for base %d\n",
-					__func__, __LINE__, base_idx);
+				CAM_ERR(CAM_ISP,
+					"no free kmd memory for base %d",
+					base_idx);
 				rc = -ENOMEM;
 				return rc;
 			}
@@ -485,8 +364,8 @@
 			update_buf.num_buf   = plane_id;
 			update_buf.io_cfg    = &io_cfg[i];
 
-			CDBG("%s:%d: cmd buffer 0x%pK, size %d\n", __func__,
-				__LINE__, update_buf.cdm.cmd_buf_addr,
+			CAM_DBG(CAM_ISP, "cmd buffer 0x%pK, size %d",
+				update_buf.cdm.cmd_buf_addr,
 				update_buf.cdm.size);
 			rc = res->hw_intf->hw_ops.process_cmd(
 				res->hw_intf->hw_priv,
@@ -494,8 +373,8 @@
 				sizeof(struct cam_isp_hw_get_buf_update));
 
 			if (rc) {
-				pr_err("%s:%d get buf cmd error:%d\n",
-					__func__, __LINE__, res->res_id);
+				CAM_ERR(CAM_ISP, "get buf cmd error:%d",
+					res->res_id);
 				rc = -ENOMEM;
 				return rc;
 			}
@@ -503,7 +382,7 @@
 		}
 	}
 
-	CDBG("%s: io_cfg_used_bytes %d, fill_fence %d\n", __func__,
+	CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d",
 		io_cfg_used_bytes, fill_fence);
 	if (io_cfg_used_bytes) {
 		/* Update the HW entries */
@@ -533,7 +412,7 @@
 	struct cam_hw_prepare_update_args    *prepare,
 	struct list_head                     *res_list_isp_src,
 	uint32_t                              base_idx,
-	struct cam_isp_kmd_buf_info          *kmd_buf_info)
+	struct cam_kmd_buf_info              *kmd_buf_info)
 {
 	int rc = -EINVAL;
 	struct cam_isp_resource_node         *res;
@@ -546,8 +425,7 @@
 	/* Max one hw entries required for each base */
 	if (prepare->num_hw_update_entries + 1 >=
 				prepare->max_hw_update_entries) {
-		pr_err("%s:%d Insufficient  HW entries :%d %d\n",
-			__func__, __LINE__,
+		CAM_ERR(CAM_ISP, "Insufficient  HW entries :%d %d",
 			prepare->num_hw_update_entries,
 			prepare->max_hw_update_entries);
 		return -EINVAL;
@@ -572,9 +450,8 @@
 					(kmd_buf_info->used_bytes +
 					reg_update_size);
 			} else {
-				pr_err("%s:%d no free mem %d %d %d\n",
-					__func__, __LINE__, base_idx,
-					kmd_buf_info->size,
+				CAM_ERR(CAM_ISP, "no free mem %d %d %d",
+					base_idx, kmd_buf_info->size,
 					kmd_buf_info->used_bytes +
 					reg_update_size);
 				rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c
index ecc71b3..4a7eff8 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
@@ -19,9 +17,7 @@
 #include <linux/ratelimit.h>
 #include "cam_tasklet_util.h"
 #include "cam_irq_controller.h"
-
-#undef  CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 #define CAM_TASKLETQ_SIZE              256
 
@@ -95,14 +91,14 @@
 	*tasklet_cmd = NULL;
 
 	if (!atomic_read(&tasklet->tasklet_active)) {
-		pr_err_ratelimited("Tasklet is not active!\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active!\n");
 		rc = -EPIPE;
 		return rc;
 	}
 
 	spin_lock_irqsave(&tasklet->tasklet_lock, flags);
 	if (list_empty(&tasklet->free_cmd_list)) {
-		pr_err_ratelimited("No more free tasklet cmd!\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "No more free tasklet cmd!\n");
 		rc = -ENODEV;
 		goto spin_unlock;
 	} else {
@@ -162,22 +158,22 @@
 	*tasklet_cmd = NULL;
 
 	if (!atomic_read(&tasklet->tasklet_active)) {
-		pr_err("Tasklet is not active!\n");
+		CAM_ERR(CAM_ISP, "Tasklet is not active!");
 		rc = -EPIPE;
 		return rc;
 	}
 
-	CDBG("Dequeue before lock.\n");
+	CAM_DBG(CAM_ISP, "Dequeue before lock.");
 	spin_lock_irqsave(&tasklet->tasklet_lock, flags);
 	if (list_empty(&tasklet->used_cmd_list)) {
-		CDBG("End of list reached. Exit\n");
+		CAM_DBG(CAM_ISP, "End of list reached. Exit");
 		rc = -ENODEV;
 		goto spin_unlock;
 	} else {
 		*tasklet_cmd = list_first_entry(&tasklet->used_cmd_list,
 			struct cam_tasklet_queue_cmd, list);
 		list_del_init(&(*tasklet_cmd)->list);
-		CDBG("Dequeue Successful\n");
+		CAM_DBG(CAM_ISP, "Dequeue Successful");
 	}
 
 spin_unlock:
@@ -197,14 +193,14 @@
 	int                            rc;
 
 	if (!bottom_half) {
-		pr_err("NULL bottom half\n");
+		CAM_ERR(CAM_ISP, "NULL bottom half");
 		return -EINVAL;
 	}
 
 	rc = cam_tasklet_get_cmd(tasklet, &tasklet_cmd);
 
 	if (tasklet_cmd) {
-		CDBG("%s: Enqueue tasklet cmd\n", __func__);
+		CAM_DBG(CAM_ISP, "Enqueue tasklet cmd");
 		tasklet_cmd->bottom_half_handler = bottom_half_handler;
 		tasklet_cmd->payload = evt_payload_priv;
 		spin_lock_irqsave(&tasklet->tasklet_lock, flags);
@@ -213,7 +209,7 @@
 		spin_unlock_irqrestore(&tasklet->tasklet_lock, flags);
 		tasklet_schedule(&tasklet->tasklet);
 	} else {
-		pr_err("%s: tasklet cmd is NULL!\n", __func__);
+		CAM_ERR(CAM_ISP, "tasklet cmd is NULL!");
 	}
 
 	return rc;
@@ -229,7 +225,8 @@
 
 	tasklet = kzalloc(sizeof(struct cam_tasklet_info), GFP_KERNEL);
 	if (!tasklet) {
-		CDBG("Error! Unable to allocate memory for tasklet");
+		CAM_DBG(CAM_ISP,
+			"Error! Unable to allocate memory for tasklet");
 		*tasklet_info = NULL;
 		return -ENOMEM;
 	}
@@ -271,7 +268,8 @@
 	struct cam_tasklet_queue_cmd  *tasklet_cmd_temp;
 
 	if (atomic_read(&tasklet->tasklet_active)) {
-		pr_err("Tasklet already active. idx = %d\n", tasklet->index);
+		CAM_ERR(CAM_ISP, "Tasklet already active. idx = %d",
+			tasklet->index);
 		return -EBUSY;
 	}
 	atomic_set(&tasklet->tasklet_active, 1);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
index 9730fc2..7ac729f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
@@ -18,47 +18,7 @@
 #include "cam_isp_hw_mgr_intf.h"
 #include "cam_ife_hw_mgr.h"
 #include "cam_hw_intf.h"
-
-/**
- * @brief                  KMD scratch buffer information
- *
- * @handle:                Memory handle
- * @cpu_addr:              Cpu address
- * @offset:                Offset from the start of the buffer
- * @size:                  Size of the buffer
- * @used_bytes:            Used memory in bytes
- *
- */
-struct cam_isp_kmd_buf_info {
-	int        handle;
-	uint32_t  *cpu_addr;
-	uint32_t   offset;
-	uint32_t   size;
-	uint32_t   used_bytes;
-};
-
-
-/**
- * @brief                  Validate the packet
- *
- * @packet:                Packet to be validated
- *
- * @return:                0 for success
- *                         -EINVAL for Fail
- */
-int cam_isp_validate_packet(struct cam_packet *packet);
-
-/**
- * @brief                  Get the kmd buffer from the packet command descriptor
- *
- * @packet:                Packet data
- * @kmd_buf:               Extracted the KMD buffer information
- *
- * @return:                0 for success
- *                         -EINVAL for Fail
- */
-int cam_isp_get_kmd_buffer(struct cam_packet *packet,
-	struct cam_isp_kmd_buf_info *kmd_buf_info);
+#include "cam_packet_util.h"
 
 /**
  * @brief                  Add change base in the hw entries list
@@ -77,7 +37,7 @@
 	struct cam_hw_prepare_update_args     *prepare,
 	struct list_head                      *res_list_isp_src,
 	uint32_t                               base_idx,
-	struct cam_isp_kmd_buf_info           *kmd_buf_info);
+	struct cam_kmd_buf_info               *kmd_buf_info);
 
 /**
  * @brief                  Add command buffer in the HW entries list for given
@@ -112,7 +72,7 @@
 int cam_isp_add_io_buffers(int	 iommu_hdl,
 	struct cam_hw_prepare_update_args    *prepare,
 	uint32_t                              base_idx,
-	struct cam_isp_kmd_buf_info          *kmd_buf_info,
+	struct cam_kmd_buf_info              *kmd_buf_info,
 	struct cam_ife_hw_mgr_res            *res_list_isp_out,
 	uint32_t                              size_isp_out,
 	bool                                  fill_fence);
@@ -134,7 +94,7 @@
 	struct cam_hw_prepare_update_args    *prepare,
 	struct list_head                     *res_list_isp_src,
 	uint32_t                              base_idx,
-	struct cam_isp_kmd_buf_info          *kmd_buf_info);
+	struct cam_kmd_buf_info              *kmd_buf_info);
 
 
 #endif /*_CAM_ISP_HW_PARSER_H */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index 9a42b6e..2341b38 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -10,16 +10,12 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include "cam_io_util.h"
 #include "cam_irq_controller.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 /**
  * struct cam_irq_evt_handler:
@@ -143,21 +139,21 @@
 
 	if (!register_info->num_registers || !register_info->irq_reg_set ||
 		!name || !mem_base) {
-		pr_err("Invalid parameters\n");
+		CAM_ERR(CAM_ISP, "Invalid parameters");
 		rc = -EINVAL;
 		return rc;
 	}
 
 	controller = kzalloc(sizeof(struct cam_irq_controller), GFP_KERNEL);
 	if (!controller) {
-		CDBG("Failed to allocate IRQ Controller\n");
+		CAM_DBG(CAM_ISP, "Failed to allocate IRQ Controller");
 		return -ENOMEM;
 	}
 
 	controller->irq_register_arr = kzalloc(register_info->num_registers *
 		sizeof(struct cam_irq_register_obj), GFP_KERNEL);
 	if (!controller->irq_register_arr) {
-		CDBG("Failed to allocate IRQ register Arr\n");
+		CAM_DBG(CAM_ISP, "Failed to allocate IRQ register Arr");
 		rc = -ENOMEM;
 		goto reg_alloc_error;
 	}
@@ -165,7 +161,7 @@
 	controller->irq_status_arr = kzalloc(register_info->num_registers *
 		sizeof(uint32_t), GFP_KERNEL);
 	if (!controller->irq_status_arr) {
-		CDBG("Failed to allocate IRQ status Arr\n");
+		CAM_DBG(CAM_ISP, "Failed to allocate IRQ status Arr");
 		rc = -ENOMEM;
 		goto status_alloc_error;
 	}
@@ -174,14 +170,14 @@
 		kzalloc(register_info->num_registers * sizeof(uint32_t),
 		GFP_KERNEL);
 	if (!controller->th_payload.evt_status_arr) {
-		CDBG("Failed to allocate BH payload bit mask Arr\n");
+		CAM_DBG(CAM_ISP, "Failed to allocate BH payload bit mask Arr");
 		rc = -ENOMEM;
 		goto evt_mask_alloc_error;
 	}
 
 	controller->name = name;
 
-	CDBG("num_registers: %d\n", register_info->num_registers);
+	CAM_DBG(CAM_ISP, "num_registers: %d", register_info->num_registers);
 	for (i = 0; i < register_info->num_registers; i++) {
 		controller->irq_register_arr[i].index = i;
 		controller->irq_register_arr[i].mask_reg_offset =
@@ -190,11 +186,11 @@
 			register_info->irq_reg_set[i].clear_reg_offset;
 		controller->irq_register_arr[i].status_reg_offset =
 			register_info->irq_reg_set[i].status_reg_offset;
-		CDBG("i %d mask_reg_offset: 0x%x\n", i,
+		CAM_DBG(CAM_ISP, "i %d mask_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].mask_reg_offset);
-		CDBG("i %d clear_reg_offset: 0x%x\n", i,
+		CAM_DBG(CAM_ISP, "i %d clear_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].clear_reg_offset);
-		CDBG("i %d status_reg_offset: 0x%x\n", i,
+		CAM_DBG(CAM_ISP, "i %d status_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].status_reg_offset);
 	}
 	controller->num_registers        = register_info->num_registers;
@@ -202,11 +198,11 @@
 	controller->global_clear_offset  = register_info->global_clear_offset;
 	controller->mem_base             = mem_base;
 
-	CDBG("global_clear_bitmask: 0x%x\n",
+	CAM_DBG(CAM_ISP, "global_clear_bitmask: 0x%x",
 		controller->global_clear_bitmask);
-	CDBG("global_clear_offset: 0x%x\n",
+	CAM_DBG(CAM_ISP, "global_clear_offset: 0x%x",
 		controller->global_clear_offset);
-	CDBG("mem_base: 0x%llx\n", (uint64_t)controller->mem_base);
+	CAM_DBG(CAM_ISP, "mem_base: %pK", (void __iomem *)controller->mem_base);
 
 	INIT_LIST_HEAD(&controller->evt_handler_list_head);
 	for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++)
@@ -246,19 +242,21 @@
 	unsigned long               flags;
 
 	if (!controller || !handler_priv || !evt_bit_mask_arr) {
-		pr_err("Invalid params: ctlr=%pK handler_priv=%pK bit_mask_arr = %pK\n",
+		CAM_ERR(CAM_ISP,
+			"Inval params: ctlr=%pK hdl_priv=%pK bit_mask_arr=%pK",
 			controller, handler_priv, evt_bit_mask_arr);
 		return -EINVAL;
 	}
 
 	if (!top_half_handler) {
-		pr_err("Missing top half handler\n");
+		CAM_ERR(CAM_ISP, "Missing top half handler");
 		return -EINVAL;
 	}
 
 	if (bottom_half_handler &&
 		(!bottom_half || !bottom_half_enqueue_func)) {
-		pr_err("Invalid params: bh_handler=%pK bh=%pK bh_enq_f=%pK\n",
+		CAM_ERR(CAM_ISP,
+			"Invalid params: bh_handler=%pK bh=%pK bh_enq_f=%pK",
 			bottom_half_handler,
 			bottom_half,
 			bottom_half_enqueue_func);
@@ -266,21 +264,21 @@
 	}
 
 	if (priority >= CAM_IRQ_PRIORITY_MAX) {
-		pr_err("Invalid priority=%u, max=%u\n", priority,
+		CAM_ERR(CAM_ISP, "Invalid priority=%u, max=%u", priority,
 			CAM_IRQ_PRIORITY_MAX);
 		return -EINVAL;
 	}
 
 	evt_handler = kzalloc(sizeof(struct cam_irq_evt_handler), GFP_KERNEL);
 	if (!evt_handler) {
-		CDBG("Error allocating hlist_node\n");
+		CAM_DBG(CAM_ISP, "Error allocating hlist_node");
 		return -ENOMEM;
 	}
 
 	evt_handler->evt_bit_mask_arr = kzalloc(sizeof(uint32_t) *
 		controller->num_registers, GFP_KERNEL);
 	if (!evt_handler->evt_bit_mask_arr) {
-		CDBG("Error allocating hlist_node\n");
+		CAM_DBG(CAM_ISP, "Error allocating hlist_node");
 		rc = -ENOMEM;
 		goto free_evt_handler;
 	}
@@ -346,7 +344,7 @@
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
-			CDBG("unsubscribe item %d\n", handle);
+			CAM_DBG(CAM_ISP, "unsubscribe item %d", handle);
 			list_del_init(&evt_handler->list_node);
 			list_del_init(&evt_handler->th_list_node);
 			found = 1;
@@ -429,7 +427,7 @@
 	int                             rc = -EINVAL;
 	int                             i;
 
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 
 	if (list_empty(th_list_head))
 		return;
@@ -441,7 +439,7 @@
 		if (!is_irq_match)
 			continue;
 
-		CDBG("match found\n");
+		CAM_DBG(CAM_ISP, "match found");
 
 		cam_irq_th_payload_init(th_payload);
 		th_payload->handler_priv  = evt_handler->handler_priv;
@@ -462,7 +460,7 @@
 				(void *)th_payload);
 
 		if (!rc && evt_handler->bottom_half_handler) {
-			CDBG("Enqueuing bottom half for %s\n",
+			CAM_DBG(CAM_ISP, "Enqueuing bottom half for %s",
 				controller->name);
 			if (evt_handler->bottom_half_enqueue_func) {
 				evt_handler->bottom_half_enqueue_func(
@@ -474,7 +472,7 @@
 		}
 	}
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 }
 
 irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv)
@@ -487,7 +485,7 @@
 	if (!controller)
 		return IRQ_NONE;
 
-	CDBG("locking controller %pK name %s rw_lock %pK\n",
+	CAM_DBG(CAM_ISP, "locking controller %pK name %s rw_lock %pK",
 		controller, controller->name, &controller->rw_lock);
 	read_lock(&controller->rw_lock);
 	for (i = 0; i < controller->num_registers; i++) {
@@ -497,7 +495,7 @@
 		cam_io_w_mb(controller->irq_status_arr[i],
 			controller->mem_base +
 			controller->irq_register_arr[i].clear_reg_offset);
-		CDBG("Read irq status%d (0x%x) = 0x%x\n", i,
+		CAM_DBG(CAM_ISP, "Read irq status%d (0x%x) = 0x%x", i,
 			controller->irq_register_arr[i].status_reg_offset,
 			controller->irq_status_arr[i]);
 		for (j = 0; j < CAM_IRQ_PRIORITY_MAX; j++) {
@@ -505,25 +503,26 @@
 				top_half_enable_mask[j] &
 				controller->irq_status_arr[i])
 				need_th_processing[j] = true;
-				CDBG("i %d j %d need_th_processing = %d\n",
+				CAM_DBG(CAM_ISP,
+					"i %d j %d need_th_processing = %d",
 					i, j, need_th_processing[j]);
 		}
 	}
 	read_unlock(&controller->rw_lock);
-	CDBG("unlocked controller %pK name %s rw_lock %pK\n",
+	CAM_DBG(CAM_ISP, "unlocked controller %pK name %s rw_lock %pK",
 		controller, controller->name, &controller->rw_lock);
 
-	CDBG("Status Registers read Successful\n");
+	CAM_DBG(CAM_ISP, "Status Registers read Successful");
 
 	if (controller->global_clear_offset)
 		cam_io_w_mb(controller->global_clear_bitmask,
 			controller->mem_base + controller->global_clear_offset);
 
-	CDBG("Status Clear done\n");
+	CAM_DBG(CAM_ISP, "Status Clear done");
 
 	for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++) {
 		if (need_th_processing[i]) {
-			CDBG("%s: Invoke TH processing\n", __func__);
+			CAM_DBG(CAM_ISP, "Invoke TH processing");
 			cam_irq_controller_th_processing(controller,
 				&controller->th_list_head[i]);
 		}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index b32bdb2..0480cd3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -115,6 +115,28 @@
 	uint64_t             timestamp;
 };
 
+/* enum cam_isp_hw_mgr_command - Hardware manager command type */
+enum cam_isp_hw_mgr_command {
+	CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT,
+	CAM_ISP_HW_MGR_CMD_MAX,
+};
+
+/**
+ * struct cam_isp_hw_cmd_args - Payload for hw manager command
+ *
+ * @ctxt_to_hw_map:        HW context from the acquire
+ * @cmd_type               HW command type
+ * @get_context            Get context type information
+ */
+struct cam_isp_hw_cmd_args {
+	void                               *ctxt_to_hw_map;
+	uint32_t                            cmd_type;
+	union {
+		uint32_t                      is_rdi_only_context;
+	} u;
+};
+
+
 /**
  * cam_isp_hw_mgr_init()
  *
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile
index 1615d21f..4c6745c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile
@@ -1,5 +1,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index e779aef..a2f773e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -19,10 +19,7 @@
 #include "cam_isp_hw.h"
 #include "cam_soc_util.h"
 #include "cam_io_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-
+#include "cam_debug_util.h"
 
 /* Timeout value in msec */
 #define IFE_CSID_TIMEOUT                               1000
@@ -62,79 +59,127 @@
 	return rc;
 }
 
-static int cam_ife_csid_get_format(uint32_t  res_id,
-	uint32_t decode_fmt, uint32_t *path_fmt, uint32_t *plain_fmt)
+static int cam_ife_csid_get_format(uint32_t input_fmt,
+	uint32_t *path_fmt)
 {
 	int rc = 0;
 
-	if (res_id >= CAM_IFE_PIX_PATH_RES_RDI_0 &&
-		res_id <= CAM_IFE_PIX_PATH_RES_RDI_3) {
-		*path_fmt = 0xf;
-		return 0;
-	}
-
-	switch (decode_fmt) {
+	switch (input_fmt) {
 	case CAM_FORMAT_MIPI_RAW_6:
 		*path_fmt  = 0;
-		*plain_fmt = 0;
 		break;
 	case CAM_FORMAT_MIPI_RAW_8:
 		*path_fmt  = 1;
-		*plain_fmt = 0;
 		break;
 	case CAM_FORMAT_MIPI_RAW_10:
 		*path_fmt  = 2;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_MIPI_RAW_12:
 		*path_fmt  = 3;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_MIPI_RAW_14:
 		*path_fmt  = 4;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_MIPI_RAW_16:
 		*path_fmt  = 5;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_MIPI_RAW_20:
 		*path_fmt  = 6;
-		*plain_fmt = 2;
 		break;
 	case CAM_FORMAT_DPCM_10_6_10:
 		*path_fmt  = 7;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_DPCM_10_8_10:
 		*path_fmt  = 8;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_DPCM_12_6_12:
 		*path_fmt  = 9;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_DPCM_12_8_12:
 		*path_fmt  = 0xA;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_DPCM_14_8_14:
 		*path_fmt  = 0xB;
-		*plain_fmt = 1;
 		break;
 	case CAM_FORMAT_DPCM_14_10_14:
 		*path_fmt  = 0xC;
-		*plain_fmt = 1;
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d un supported format\n",
-		__func__, __LINE__, decode_fmt);
+		CAM_ERR(CAM_ISP, "CSID:%d un supported format",
+			input_fmt);
 		rc = -EINVAL;
 	}
 
 	return rc;
 }
 
+static int cam_ife_csid_get_rdi_format(uint32_t input_fmt,
+	uint32_t output_fmt, uint32_t *path_fmt, uint32_t *plain_fmt)
+{
+	int rc = 0;
+
+	CAM_DBG(CAM_ISP, "input format:%d output format:%d",
+		 input_fmt, output_fmt);
+
+	switch (output_fmt) {
+	case CAM_FORMAT_MIPI_RAW_6:
+	case CAM_FORMAT_MIPI_RAW_8:
+	case CAM_FORMAT_MIPI_RAW_10:
+	case CAM_FORMAT_MIPI_RAW_12:
+	case CAM_FORMAT_MIPI_RAW_14:
+	case CAM_FORMAT_MIPI_RAW_16:
+	case CAM_FORMAT_MIPI_RAW_20:
+	case CAM_FORMAT_DPCM_10_6_10:
+	case CAM_FORMAT_DPCM_10_8_10:
+	case CAM_FORMAT_DPCM_12_6_12:
+	case CAM_FORMAT_DPCM_12_8_12:
+	case CAM_FORMAT_DPCM_14_8_14:
+	case CAM_FORMAT_DPCM_14_10_14:
+		*path_fmt  = 0xF;
+		*plain_fmt = 0;
+		break;
+
+	case CAM_FORMAT_PLAIN8:
+		rc = cam_ife_csid_get_format(input_fmt, path_fmt);
+		if (rc)
+			goto error;
+
+		*plain_fmt = 0;
+		break;
+	case CAM_FORMAT_PLAIN16_8:
+	case CAM_FORMAT_PLAIN16_10:
+	case CAM_FORMAT_PLAIN16_12:
+	case CAM_FORMAT_PLAIN16_14:
+	case CAM_FORMAT_PLAIN16_16:
+		rc = cam_ife_csid_get_format(input_fmt, path_fmt);
+		if (rc)
+			goto error;
+
+		*plain_fmt = 1;
+		break;
+	case CAM_FORMAT_PLAIN32_20:
+		rc = cam_ife_csid_get_format(input_fmt, path_fmt);
+		if (rc)
+			goto error;
+
+		*plain_fmt = 2;
+		break;
+	default:
+		*path_fmt  = 0xF;
+		*plain_fmt = 0;
+		break;
+	}
+
+	CAM_DBG(CAM_ISP, "path format value:%d plain format value:%d",
+		 *path_fmt, *plain_fmt);
+
+	return 0;
+error:
+	return rc;
+
+}
+
+
 static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
 	struct cam_isp_resource_node **res, int32_t vc, uint32_t dt,
 	uint32_t res_type)
@@ -166,8 +211,8 @@
 
 	if (i == CAM_IFE_CSID_CID_RES_MAX) {
 		if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
-			pr_err("%s:%d:CSID:%d TPG CID not available\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+			CAM_ERR(CAM_ISP, "CSID:%d TPG CID not available",
+				 csid_hw->hw_intf->hw_idx);
 			rc = -EINVAL;
 		}
 
@@ -182,8 +227,7 @@
 				csid_hw->cid_res[j].res_state =
 					CAM_ISP_RESOURCE_STATE_RESERVED;
 				*res = &csid_hw->cid_res[j];
-				CDBG("%s:%d:CSID:%d CID %d allocated\n",
-					__func__, __LINE__,
+				CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
 					csid_hw->hw_intf->hw_idx,
 					csid_hw->cid_res[j].res_id);
 				break;
@@ -191,8 +235,8 @@
 		}
 
 		if (j == CAM_IFE_CSID_CID_RES_MAX) {
-			pr_err("%s:%d:CSID:%d Free cid is not available\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+			CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available",
+				 csid_hw->hw_intf->hw_idx);
 			rc = -EINVAL;
 		}
 	}
@@ -213,13 +257,13 @@
 	csid_reg = csid_hw->csid_info->csid_reg;
 
 	if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		pr_err("%s:%d:CSID:%d Invalid HW State:%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid HW State:%d",
+			csid_hw->hw_intf->hw_idx,
 			csid_hw->hw_info->hw_state);
 		return -EINVAL;
 	}
 
-	CDBG("%s:%d:CSID:%d Csid reset\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d Csid reset",
 		csid_hw->hw_intf->hw_idx);
 
 	init_completion(&csid_hw->csid_top_complete);
@@ -287,14 +331,12 @@
 		soc_info->reg_map[0].mem_base +
 		csid_reg->cmn_reg->csid_rst_strobes_addr);
 
-	CDBG("%s:%d: Waiting for reset complete from irq handler\n",
-		__func__, __LINE__);
-
+	CAM_DBG(CAM_ISP, " Waiting for reset complete from irq handler");
 	rc = wait_for_completion_timeout(&csid_hw->csid_top_complete,
 		msecs_to_jiffies(IFE_CSID_TIMEOUT));
 	if (rc <= 0) {
-		pr_err("%s:%d:CSID:%d reset completion in fail rc = %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx, rc);
+		CAM_ERR(CAM_ISP, "CSID:%d reset completion in fail rc = %d",
+			 csid_hw->hw_intf->hw_idx, rc);
 		if (rc == 0)
 			rc = -ETIMEDOUT;
 	} else {
@@ -331,26 +373,26 @@
 	res      = reset->node_res;
 
 	if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		pr_err("%s:%d:CSID:%d Invalid hw state :%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid hw state :%d",
+			csid_hw->hw_intf->hw_idx,
 			csid_hw->hw_info->hw_state);
 		return -EINVAL;
 	}
 
 	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
-		CDBG("%s:%d:CSID:%d Invalid res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id);
+		CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_id);
 		rc = -EINVAL;
 		goto end;
 	}
 
-	CDBG("%s:%d:CSID:%d resource:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d resource:%d",
 		csid_hw->hw_intf->hw_idx, res->res_id);
 
 	if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) {
 		if (!csid_reg->ipp_reg) {
-			pr_err("%s:%d:CSID:%d IPP not supported :%d\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+			CAM_ERR(CAM_ISP, "CSID:%d IPP not supported :%d",
+				 csid_hw->hw_intf->hw_idx,
 				res->res_id);
 			return -EINVAL;
 		}
@@ -368,8 +410,8 @@
 	} else {
 		id = res->res_id;
 		if (!csid_reg->rdi_reg[id]) {
-			pr_err("%s:%d:CSID:%d RDI res not supported :%d\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+			CAM_ERR(CAM_ISP, "CSID:%d RDI res not supported :%d",
+				 csid_hw->hw_intf->hw_idx,
 				res->res_id);
 			return -EINVAL;
 		}
@@ -401,8 +443,8 @@
 	rc = wait_for_completion_timeout(complete,
 		msecs_to_jiffies(IFE_CSID_TIMEOUT));
 	if (rc <= 0) {
-		pr_err("%s:%d CSID:%d Res id %d fail rc = %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Res id %d fail rc = %d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id,  rc);
 		if (rc == 0)
 			rc = -ETIMEDOUT;
@@ -423,8 +465,9 @@
 	int rc = 0;
 	struct cam_ife_csid_cid_data       *cid_data;
 
-	CDBG("%s:%d CSID:%d res_sel:%d Lane type:%d lane_num:%d dt:%d vc:%d\n",
-		__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+	CAM_DBG(CAM_ISP,
+		"CSID:%d res_sel:%d Lane type:%d lane_num:%d dt:%d vc:%d",
+		csid_hw->hw_intf->hw_idx,
 		cid_reserv->in_port->res_type,
 		cid_reserv->in_port->lane_type,
 		cid_reserv->in_port->lane_num,
@@ -432,8 +475,8 @@
 		cid_reserv->in_port->vc);
 
 	if (cid_reserv->in_port->res_type >= CAM_ISP_IFE_IN_RES_MAX) {
-		pr_err("%s:%d:CSID:%d  Invalid phy sel %d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d  Invalid phy sel %d",
+			csid_hw->hw_intf->hw_idx,
 			cid_reserv->in_port->res_type);
 		rc = -EINVAL;
 		goto end;
@@ -441,8 +484,8 @@
 
 	if (cid_reserv->in_port->lane_type >= CAM_ISP_LANE_TYPE_MAX &&
 		cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
-		pr_err("%s:%d:CSID:%d  Invalid lane type %d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d  Invalid lane type %d",
+			csid_hw->hw_intf->hw_idx,
 			cid_reserv->in_port->lane_type);
 		rc = -EINVAL;
 		goto end;
@@ -451,8 +494,8 @@
 	if ((cid_reserv->in_port->lane_type ==  CAM_ISP_LANE_TYPE_DPHY &&
 		cid_reserv->in_port->lane_num > 4) &&
 		cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
-		pr_err("%s:%d:CSID:%d Invalid lane num %d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid lane num %d",
+			csid_hw->hw_intf->hw_idx,
 			cid_reserv->in_port->lane_num);
 		rc = -EINVAL;
 		goto end;
@@ -460,8 +503,8 @@
 	if ((cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_CPHY &&
 		cid_reserv->in_port->lane_num > 3) &&
 		cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
-		pr_err("%s:%d: CSID:%d Invalid lane type %d & num %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, " CSID:%d Invalid lane type %d & num %d",
+			 csid_hw->hw_intf->hw_idx,
 			cid_reserv->in_port->lane_type,
 			cid_reserv->in_port->lane_num);
 		rc = -EINVAL;
@@ -471,8 +514,8 @@
 	/* CSID  CSI2 v2.0 supports 31 vc  */
 	if (cid_reserv->in_port->dt > 0x3f ||
 		cid_reserv->in_port->vc > 0x1f) {
-		pr_err("%s:%d:CSID:%d Invalid vc:%d dt %d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d",
+			csid_hw->hw_intf->hw_idx,
 			cid_reserv->in_port->vc, cid_reserv->in_port->dt);
 		rc = -EINVAL;
 		goto end;
@@ -481,8 +524,8 @@
 	if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG && (
 		(cid_reserv->in_port->format < CAM_FORMAT_MIPI_RAW_8 &&
 		cid_reserv->in_port->format > CAM_FORMAT_MIPI_RAW_16))) {
-		pr_err("%s:%d: CSID:%d Invalid tpg decode fmt %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, " CSID:%d Invalid tpg decode fmt %d",
+			 csid_hw->hw_intf->hw_idx,
 			cid_reserv->in_port->format);
 		rc = -EINVAL;
 		goto end;
@@ -538,8 +581,7 @@
 			csid_hw->csi2_rx_cfg.phy_sel = 0;
 			if (cid_reserv->in_port->format >
 			    CAM_FORMAT_MIPI_RAW_16) {
-				pr_err("%s:%d: Wrong TPG format\n", __func__,
-					__LINE__);
+				CAM_ERR(CAM_ISP, " Wrong TPG format");
 				rc = -EINVAL;
 				goto end;
 			}
@@ -562,8 +604,9 @@
 		cid_reserv->node_res = &csid_hw->cid_res[0];
 		csid_hw->csi2_reserve_cnt++;
 
-		CDBG("%s:%d:CSID:%d CID :%d resource acquired successfully\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP,
+			"CSID:%d CID :%d resource acquired successfully",
+			csid_hw->hw_intf->hw_idx,
 			cid_reserv->node_res->res_id);
 	} else {
 		rc = cam_ife_csid_cid_get(csid_hw, &cid_reserv->node_res,
@@ -572,14 +615,13 @@
 		/* if success then increment the reserve count */
 		if (!rc) {
 			if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
-				pr_err("%s:%d:CSID%d reserve cnt reached max\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_ISP,
+					"CSID%d reserve cnt reached max",
 					csid_hw->hw_intf->hw_idx);
 				rc = -EINVAL;
 			} else {
 				csid_hw->csi2_reserve_cnt++;
-				CDBG("%s:%d:CSID:%d CID:%d acquired\n",
-					__func__, __LINE__,
+				CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired",
 					csid_hw->hw_intf->hw_idx,
 					cid_reserv->node_res->res_id);
 			}
@@ -601,8 +643,8 @@
 	/* CSID  CSI2 v2.0 supports 31 vc */
 	if (reserve->in_port->dt > 0x3f || reserve->in_port->vc > 0x1f ||
 		(reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX)) {
-		pr_err("%s:%d:CSID:%d Invalid vc:%d dt %d mode:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d mode:%d",
+			 csid_hw->hw_intf->hw_idx,
 			reserve->in_port->vc, reserve->in_port->dt,
 			reserve->sync_mode);
 		rc = -EINVAL;
@@ -613,8 +655,9 @@
 	case CAM_IFE_PIX_PATH_RES_IPP:
 		if (csid_hw->ipp_res.res_state !=
 			CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-			CDBG("%s:%d:CSID:%d IPP resource not available %d\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+			CAM_DBG(CAM_ISP,
+				"CSID:%d IPP resource not available %d",
+				csid_hw->hw_intf->hw_idx,
 				csid_hw->ipp_res.res_state);
 			rc = -EINVAL;
 			goto end;
@@ -622,8 +665,8 @@
 
 		if (cam_ife_csid_is_ipp_format_supported(
 				reserve->in_port->format)) {
-			pr_err("%s:%d:CSID:%d res id:%d un support format %d\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_ISP,
+				"CSID:%d res id:%d un support format %d",
 				csid_hw->hw_intf->hw_idx, reserve->res_id,
 				reserve->in_port->format);
 			rc = -EINVAL;
@@ -632,8 +675,8 @@
 
 		/* assign the IPP resource */
 		res = &csid_hw->ipp_res;
-		CDBG("%s:%d:CSID:%d IPP resource:%d acquired successfully\n",
-			__func__, __LINE__,
+		CAM_DBG(CAM_ISP,
+			"CSID:%d IPP resource:%d acquired successfully",
 			csid_hw->hw_intf->hw_idx, res->res_id);
 
 			break;
@@ -643,23 +686,24 @@
 	case CAM_IFE_PIX_PATH_RES_RDI_3:
 		if (csid_hw->rdi_res[reserve->res_id].res_state !=
 			CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-			CDBG("%s:%d:CSID:%d RDI:%d resource not available %d\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+			CAM_DBG(CAM_ISP,
+				"CSID:%d RDI:%d resource not available %d",
+				csid_hw->hw_intf->hw_idx,
 				reserve->res_id,
 				csid_hw->rdi_res[reserve->res_id].res_state);
 			rc = -EINVAL;
 			goto end;
 		} else {
 			res = &csid_hw->rdi_res[reserve->res_id];
-			CDBG("%s:%d:CSID:%d RDI resource:%d acquire success\n",
-				__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+			CAM_DBG(CAM_ISP,
+				"CSID:%d RDI resource:%d acquire success",
+				csid_hw->hw_intf->hw_idx,
 				res->res_id);
 		}
 
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d Invalid res id:%d\n",
-			__func__, __LINE__,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res id:%d",
 			csid_hw->hw_intf->hw_idx, reserve->res_id);
 		rc = -EINVAL;
 		goto end;
@@ -668,6 +712,18 @@
 	res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 	path_data = (struct cam_ife_csid_path_cfg   *)res->res_priv;
 
+	/* store the output format for RDI */
+	switch (reserve->res_id) {
+	case CAM_IFE_PIX_PATH_RES_RDI_0:
+	case CAM_IFE_PIX_PATH_RES_RDI_1:
+	case CAM_IFE_PIX_PATH_RES_RDI_2:
+	case CAM_IFE_PIX_PATH_RES_RDI_3:
+		path_data->output_fmt = reserve->out_port->format;
+		break;
+	default:
+		break;
+	}
+
 	path_data->cid = reserve->cid;
 	path_data->decode_fmt = reserve->in_port->format;
 	path_data->master_idx = reserve->master_idx;
@@ -711,31 +767,30 @@
 
 	/* overflow check before increment */
 	if (csid_hw->hw_info->open_count == UINT_MAX) {
-		pr_err("%s:%d:CSID:%d Open count reached max\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx);
+		CAM_ERR(CAM_ISP, "CSID:%d Open count reached max",
+			csid_hw->hw_intf->hw_idx);
 		return -EINVAL;
 	}
 
 	/* Increment ref Count */
 	csid_hw->hw_info->open_count++;
 	if (csid_hw->hw_info->open_count > 1) {
-		CDBG("%s:%d: CSID hw has already been enabled\n",
-			__func__, __LINE__);
+		CAM_DBG(CAM_ISP, "CSID hw has already been enabled");
 		return rc;
 	}
 
-	CDBG("%s:%d:CSID:%d init CSID HW\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d init CSID HW",
 		csid_hw->hw_intf->hw_idx);
 
 	rc = cam_ife_csid_enable_soc_resources(soc_info);
 	if (rc) {
-		pr_err("%s:%d:CSID:%d Enable SOC failed\n", __func__, __LINE__,
+		CAM_ERR(CAM_ISP, "CSID:%d Enable SOC failed",
 			csid_hw->hw_intf->hw_idx);
 		goto err;
 	}
 
 
-	CDBG("%s:%d:CSID:%d enable top irq interrupt\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d enable top irq interrupt",
 		csid_hw->hw_intf->hw_idx);
 
 	csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP;
@@ -745,8 +800,8 @@
 
 	rc = cam_ife_csid_global_reset(csid_hw);
 	if (rc) {
-		pr_err("%s:%d CSID:%d csid_reset fail rc = %d\n",
-			 __func__, __LINE__, csid_hw->hw_intf->hw_idx, rc);
+		CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d",
+			  csid_hw->hw_intf->hw_idx, rc);
 		rc = -ETIMEDOUT;
 		goto disable_soc;
 	}
@@ -756,7 +811,7 @@
 	 * SW register reset also reset the mask irq, so poll the irq status
 	 * to check the reset complete.
 	 */
-	CDBG("%s:%d:CSID:%d Reset Software registers\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d Reset Software registers",
 			csid_hw->hw_intf->hw_idx);
 
 	cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb_sw_all,
@@ -768,8 +823,7 @@
 			status, (status & 0x1) == 0x1,
 		CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
 	if (rc < 0) {
-		pr_err("%s:%d: software register reset timeout.....\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "software register reset timeout.....");
 		rc = -ETIMEDOUT;
 		goto disable_soc;
 	}
@@ -801,7 +855,7 @@
 
 	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
 			csid_reg->cmn_reg->csid_hw_version_addr);
-	CDBG("%s:%d:CSID:%d CSID HW version: 0x%x\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x",
 		csid_hw->hw_intf->hw_idx, val);
 
 	return 0;
@@ -830,7 +884,7 @@
 	soc_info = &csid_hw->hw_info->soc_info;
 	csid_reg = csid_hw->csid_info->csid_reg;
 
-	CDBG("%s:%d:CSID:%d De-init CSID HW\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d De-init CSID HW",
 		csid_hw->hw_intf->hw_idx);
 
 	/*disable the top IRQ interrupt */
@@ -839,8 +893,8 @@
 
 	rc = cam_ife_csid_disable_soc_resources(soc_info);
 	if (rc)
-		pr_err("%s:%d:CSID:%d Disable CSID SOC failed\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx);
+		CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed",
+			csid_hw->hw_intf->hw_idx);
 
 	csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
 	return rc;
@@ -856,8 +910,8 @@
 	csid_hw->tpg_start_cnt++;
 	if (csid_hw->tpg_start_cnt == 1) {
 		/*Enable the TPG */
-		CDBG("%s:%d CSID:%d start CSID TPG\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx);
+		CAM_DBG(CAM_ISP, "CSID:%d start CSID TPG",
+			csid_hw->hw_intf->hw_idx);
 
 		soc_info = &csid_hw->hw_info->soc_info;
 		{
@@ -865,44 +919,37 @@
 			uint32_t i;
 			uint32_t base = 0x600;
 
-			CDBG("%s:%d: ================== TPG ===============\n",
-				__func__, __LINE__);
+			CAM_DBG(CAM_ISP, "================ TPG ============");
 			for (i = 0; i < 16; i++) {
 				val = cam_io_r_mb(
 					soc_info->reg_map[0].mem_base +
 					base + i * 4);
-				CDBG("%s:%d reg 0x%x = 0x%x\n",
-					__func__, __LINE__,
+				CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x",
 					(base + i*4), val);
 			}
 
-			CDBG("%s:%d: ================== IPP ===============\n",
-				__func__, __LINE__);
+			CAM_DBG(CAM_ISP, "================ IPP =============");
 			base = 0x200;
 			for (i = 0; i < 10; i++) {
 				val = cam_io_r_mb(
 					soc_info->reg_map[0].mem_base +
 					base + i * 4);
-				CDBG("%s:%d reg 0x%x = 0x%x\n",
-					__func__, __LINE__,
+				CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x",
 					(base + i*4), val);
 			}
 
-			CDBG("%s:%d: ================== RX ===============\n",
-				__func__, __LINE__);
+			CAM_DBG(CAM_ISP, "================ RX =============");
 			base = 0x100;
 			for (i = 0; i < 5; i++) {
 				val = cam_io_r_mb(
 					soc_info->reg_map[0].mem_base +
 					base + i * 4);
-				CDBG("%s:%d reg 0x%x = 0x%x\n",
-					__func__, __LINE__,
+				CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x",
 					(base + i*4), val);
 			}
 		}
 
-		CDBG("%s:%d: =============== TPG control ===============\n",
-			__func__, __LINE__);
+		CAM_DBG(CAM_ISP, "============ TPG control ============");
 		val = (4 << 20);
 		val |= (0x80 << 8);
 		val |= (((csid_hw->csi2_rx_cfg.lane_num - 1) & 0x3) << 4);
@@ -912,8 +959,7 @@
 			csid_tpg_ctrl_addr);
 
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base + 0x600);
-		CDBG("%s:%d reg 0x%x = 0x%x\n", __func__, __LINE__,
-			0x600, val);
+		CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", 0x600, val);
 	}
 
 	return 0;
@@ -934,8 +980,8 @@
 
 	/* disable the TPG */
 	if (!csid_hw->tpg_start_cnt) {
-		CDBG("%s:%d CSID:%d stop CSID TPG\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx);
+		CAM_DBG(CAM_ISP, "CSID:%d stop CSID TPG",
+			csid_hw->hw_intf->hw_idx);
 
 		/*stop the TPG */
 		cam_io_w_mb(0,  soc_info->reg_map[0].mem_base +
@@ -956,8 +1002,8 @@
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
 
-	CDBG("%s:%d CSID:%d TPG config\n", __func__,
-		__LINE__, csid_hw->hw_intf->hw_idx);
+	CAM_DBG(CAM_ISP, "CSID:%d TPG config",
+		csid_hw->hw_intf->hw_idx);
 
 	/* configure one DT, infinite frames */
 	val = (0 << 16) | (1 << 10) | CAM_IFE_CSID_TPG_VC_VAL;
@@ -1012,13 +1058,13 @@
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
-	CDBG("%s:%d CSID:%d count:%d config csi2 rx\n", __func__,
-		__LINE__, csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
+	CAM_DBG(CAM_ISP, "CSID:%d count:%d config csi2 rx",
+		csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
 
 	/* overflow check before increment */
 	if (csid_hw->csi2_cfg_cnt == UINT_MAX) {
-		pr_err("%s:%d:CSID:%d Open count reached max\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx);
+		CAM_ERR(CAM_ISP, "CSID:%d Open count reached max",
+			csid_hw->hw_intf->hw_idx);
 		return -EINVAL;
 	}
 
@@ -1081,15 +1127,15 @@
 	struct cam_hw_soc_info              *soc_info;
 
 	if (res->res_id >= CAM_IFE_CSID_CID_MAX) {
-		pr_err("%s:%d CSID:%d Invalid res id :%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id);
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res id :%d",
+			csid_hw->hw_intf->hw_idx, res->res_id);
 		return -EINVAL;
 	}
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
-	CDBG("%s:%d CSID:%d cnt : %d Disable csi2 rx\n", __func__,
-		__LINE__, csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
+	CAM_DBG(CAM_ISP, "CSID:%d cnt : %d Disable csi2 rx",
+		csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
 
 	if (csid_hw->csi2_cfg_cnt)
 		csid_hw->csi2_cfg_cnt--;
@@ -1114,22 +1160,21 @@
 	struct cam_ife_csid_path_cfg           *path_data;
 	struct cam_ife_csid_reg_offset         *csid_reg;
 	struct cam_hw_soc_info                 *soc_info;
-	uint32_t path_format = 0, plain_format = 0, val = 0;
+	uint32_t path_format = 0, val = 0;
 
 	path_data = (struct cam_ife_csid_path_cfg  *) res->res_priv;
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
 
 	if (!csid_reg->ipp_reg) {
-		pr_err("%s:%d CSID:%d IPP:%d is not supported on HW\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d IPP:%d is not supported on HW",
+			csid_hw->hw_intf->hw_idx,
 			res->res_id);
 		return -EINVAL;
 	}
 
-	CDBG("%s:%d: Enabled IPP Path.......\n", __func__, __LINE__);
-	rc = cam_ife_csid_get_format(res->res_id,
-		path_data->decode_fmt, &path_format, &plain_format);
+	CAM_DBG(CAM_ISP, "Enabled IPP Path.......");
+	rc = cam_ife_csid_get_format(path_data->decode_fmt, &path_format);
 	if (rc)
 		return rc;
 
@@ -1232,15 +1277,16 @@
 	soc_info = &csid_hw->hw_info->soc_info;
 
 	if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) {
-		pr_err("%s:%d:CSID:%d Res type %d res_id:%d in wrong state %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP,
+			"CSID:%d Res type %d res_id:%d in wrong state %d",
+			csid_hw->hw_intf->hw_idx,
 			res->res_type, res->res_id, res->res_state);
 		rc = -EINVAL;
 	}
 
 	if (!csid_reg->ipp_reg) {
-		pr_err("%s:%d:CSID:%d IPP %d is not supported on HW\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d IPP %d is not supported on HW",
+			csid_hw->hw_intf->hw_idx,
 			res->res_id);
 		rc = -EINVAL;
 	}
@@ -1270,20 +1316,21 @@
 	soc_info = &csid_hw->hw_info->soc_info;
 
 	if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) {
-		pr_err("%s:%d:CSID:%d res type:%d res_id:%d Invalid state%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP,
+			"CSID:%d res type:%d res_id:%d Invalid state%d",
+			csid_hw->hw_intf->hw_idx,
 			res->res_type, res->res_id, res->res_state);
 		return -EINVAL;
 	}
 
 	if (!csid_reg->ipp_reg) {
-		pr_err("%s:%d:CSID:%d IPP %d not supported on HW\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d IPP %d not supported on HW",
+			csid_hw->hw_intf->hw_idx,
 			res->res_id);
 		return -EINVAL;
 	}
 
-	CDBG("%s:%d: enable IPP path.......\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "enable IPP path.......");
 
 	/*Resume at frame boundary */
 	if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
@@ -1300,8 +1347,7 @@
 	/* for slave mode, not need to resume for slave device */
 
 	/* Enable the required ipp interrupts */
-	val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW|
-		CSID_PATH_INFO_INPUT_SOF|CSID_PATH_INFO_INPUT_EOF;
+	val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
 	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 		csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
 
@@ -1326,40 +1372,40 @@
 	soc_info = &csid_hw->hw_info->soc_info;
 
 	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
-		CDBG("%s:%d:CSID:%d Invalid res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id);
+		CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_id);
 		return -EINVAL;
 	}
 
 	if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
 		res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
-		CDBG("%s:%d:CSID:%d Res:%d already in stopped state:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id, res->res_state);
 		return rc;
 	}
 
 	if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
-		CDBG("%s:%d:CSID:%d Res:%d Invalid state%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d Invalid state%d",
+			csid_hw->hw_intf->hw_idx, res->res_id,
 			res->res_state);
 		return -EINVAL;
 	}
 
 	if (!csid_reg->ipp_reg) {
-		pr_err("%s:%d:CSID:%d IPP%d is not supported on HW\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id);
+		CAM_ERR(CAM_ISP, "CSID:%d IPP%d is not supported on HW",
+			csid_hw->hw_intf->hw_idx, res->res_id);
 		return -EINVAL;
 	}
 
 	if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY &&
 		stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
-		pr_err("%s:%d:CSID:%d un supported stop command:%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, stop_cmd);
+		CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d",
+			csid_hw->hw_intf->hw_idx, stop_cmd);
 		return -EINVAL;
 	}
 
-	CDBG("%s:%d CSID:%d res_id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d res_id:%d",
 		csid_hw->hw_intf->hw_idx, res->res_id);
 
 	if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
@@ -1411,13 +1457,13 @@
 
 	id = res->res_id;
 	if (!csid_reg->rdi_reg[id]) {
-		pr_err("%s:%d CSID:%d RDI:%d is not supported on HW\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx, id);
+		CAM_ERR(CAM_ISP, "CSID:%d RDI:%d is not supported on HW",
+			 csid_hw->hw_intf->hw_idx, id);
 		return -EINVAL;
 	}
 
-	rc = cam_ife_csid_get_format(res->res_id,
-		path_data->decode_fmt, &path_format, &plain_fmt);
+	rc = cam_ife_csid_get_rdi_format(path_data->decode_fmt,
+		path_data->output_fmt, &path_format, &plain_fmt);
 	if (rc)
 		return rc;
 
@@ -1514,8 +1560,8 @@
 	if (res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3 ||
 		res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
 		!csid_reg->rdi_reg[id]) {
-		pr_err("%s:%d:CSID:%d Invalid res id%d state:%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d state:%d",
+			csid_hw->hw_intf->hw_idx, res->res_id,
 			res->res_state);
 		return -EINVAL;
 	}
@@ -1546,8 +1592,9 @@
 	if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
 		res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3 ||
 		!csid_reg->rdi_reg[id]) {
-		pr_err("%s:%d:CSID:%d invalid res type:%d res_id:%d state%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP,
+			"CSID:%d invalid res type:%d res_id:%d state%d",
+			csid_hw->hw_intf->hw_idx,
 			res->res_type, res->res_id, res->res_state);
 		return -EINVAL;
 	}
@@ -1558,8 +1605,7 @@
 			csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
 
 	/* Enable the required RDI interrupts */
-	val = (CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW|
-		CSID_PATH_INFO_INPUT_SOF | CSID_PATH_INFO_INPUT_EOF);
+	val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
 	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 		csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
 
@@ -1585,35 +1631,35 @@
 
 	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX ||
 		!csid_reg->rdi_reg[res->res_id]) {
-		CDBG("%s:%d:CSID:%d Invalid res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id);
+		CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_id);
 		return -EINVAL;
 	}
 
 	if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
 		res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
-		CDBG("%s:%d:CSID:%d Res:%d already in stopped state:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id, res->res_state);
 		return rc;
 	}
 
 	if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
-		CDBG("%s:%d:CSID:%d Res:%d Invalid res_state%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d Invalid res_state%d",
+			csid_hw->hw_intf->hw_idx, res->res_id,
 			res->res_state);
 		return -EINVAL;
 	}
 
 	if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY &&
 		stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
-		pr_err("%s:%d:CSID:%d un supported stop command:%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, stop_cmd);
+		CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d",
+			csid_hw->hw_intf->hw_idx, stop_cmd);
 		return -EINVAL;
 	}
 
 
-	CDBG("%s:%d CSID:%d res_id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d res_id:%d",
 		csid_hw->hw_intf->hw_idx, res->res_id);
 
 	init_completion(&csid_hw->csid_rdin_complete[id]);
@@ -1654,15 +1700,15 @@
 
 	if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH ||
 		res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
-		CDBG("%s:%d:CSID:%d Invalid res_type:%d res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_type,
+		CAM_DBG(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_type,
 			res->res_id);
 		return -EINVAL;
 	}
 
 	if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		pr_err("%s:%d:CSID:%d Invalid dev state :%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d",
+			csid_hw->hw_intf->hw_idx,
 			csid_hw->hw_info->hw_state);
 		return -EINVAL;
 	}
@@ -1706,22 +1752,22 @@
 	soc_info = &csid_hw->hw_info->soc_info;
 
 	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
-		CDBG("%s:%d:CSID:%d Invalid res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id);
+		CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_id);
 		return -EINVAL;
 	}
 
 	if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
 		res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
-		CDBG("%s:%d:CSID:%d Res:%d already in stopped state:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id, res->res_state);
 		return rc;
 	}
 
 	if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
-		CDBG("%s:%d:CSID:%d Res:%d Invalid state%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_id,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d Invalid state%d",
+			csid_hw->hw_intf->hw_idx, res->res_id,
 			res->res_state);
 		return -EINVAL;
 	}
@@ -1734,8 +1780,8 @@
 	rc = wait_for_completion_timeout(complete,
 		msecs_to_jiffies(IFE_CSID_TIMEOUT));
 	if (rc <= 0) {
-		pr_err("%s:%d:CSID%d stop at frame boundary failid:%drc:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID%d stop at frame boundary failid:%drc:%d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id, rc);
 		if (rc == 0)
 			/* continue even have timeout */
@@ -1774,7 +1820,7 @@
 	struct cam_ife_csid_reg_offset  *csid_reg;
 
 	if (!hw_priv || !get_hw_cap_args) {
-		pr_err("%s:%d:CSID: Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
 		return -EINVAL;
 	}
 
@@ -1789,8 +1835,9 @@
 	hw_caps->minor_version = csid_reg->cmn_reg->minor_version;
 	hw_caps->version_incr = csid_reg->cmn_reg->version_incr;
 
-	CDBG("%s:%d:CSID:%d No rdis:%d, no pix:%d, major:%d minor:%d ver :%d\n",
-		__func__, __LINE__, csid_hw->hw_intf->hw_idx, hw_caps->no_rdis,
+	CAM_DBG(CAM_ISP,
+		"CSID:%d No rdis:%d, no pix:%d, major:%d minor:%d ver :%d",
+		csid_hw->hw_intf->hw_idx, hw_caps->no_rdis,
 		hw_caps->no_pix, hw_caps->major_version, hw_caps->minor_version,
 		hw_caps->version_incr);
 
@@ -1807,7 +1854,7 @@
 
 	if (!hw_priv || !reset_args || (arg_size !=
 		sizeof(struct cam_csid_reset_cfg_args))) {
-		pr_err("%s:%d:CSID:Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID:Invalid args");
 		return -EINVAL;
 	}
 
@@ -1823,8 +1870,8 @@
 		rc = cam_ife_csid_path_reset(csid_hw, reset);
 		break;
 	default:
-		pr_err("%s:%d:CSID:Invalid reset type :%d\n", __func__,
-			__LINE__, reset->reset_type);
+		CAM_ERR(CAM_ISP, "CSID:Invalid reset type :%d",
+			reset->reset_type);
 		rc = -EINVAL;
 		break;
 	}
@@ -1842,7 +1889,7 @@
 
 	if (!hw_priv || !reserve_args || (arg_size !=
 		sizeof(struct cam_csid_hw_reserve_resource_args))) {
-		pr_err("%s:%d:CSID: Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
 		return -EINVAL;
 	}
 
@@ -1859,8 +1906,8 @@
 		rc = cam_ife_csid_path_reserve(csid_hw, reserv);
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d Invalid res type :%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, reserv->res_type);
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res type :%d",
+			csid_hw->hw_intf->hw_idx, reserv->res_type);
 		rc = -EINVAL;
 		break;
 	}
@@ -1879,7 +1926,7 @@
 
 	if (!hw_priv || !release_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("%s:%d:CSID: Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
 		return -EINVAL;
 	}
 
@@ -1892,31 +1939,33 @@
 		res->res_id >= CAM_IFE_CSID_CID_MAX) ||
 		(res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
 		res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) {
-		pr_err("%s:%d:CSID:%d Invalid res type:%d res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_type,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_type,
 			res->res_id);
 		rc = -EINVAL;
 		goto end;
 	}
 
 	if (res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-		CDBG("%s:%d:CSID:%d res type:%d Res %d  in released state\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP,
+			"CSID:%d res type:%d Res %d  in released state",
+			csid_hw->hw_intf->hw_idx,
 			res->res_type, res->res_id);
 		goto end;
 	}
 
 	if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
 		res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
-		CDBG("%s:%d:CSID:%d res type:%d Res id:%d invalid state:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP,
+			"CSID:%d res type:%d Res id:%d invalid state:%d",
+			csid_hw->hw_intf->hw_idx,
 			res->res_type, res->res_id, res->res_state);
 		rc = -EINVAL;
 		goto end;
 	}
 
-	CDBG("%s:%d:CSID:%d res type :%d Resource id:%d\n", __func__, __LINE__,
-			csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
+	CAM_DBG(CAM_ISP, "CSID:%d res type :%d Resource id:%d",
+		csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
 
 	switch (res->res_type) {
 	case CAM_ISP_RESOURCE_CID:
@@ -1934,8 +1983,8 @@
 			memset(&csid_hw->csi2_rx_cfg, 0,
 				sizeof(struct cam_ife_csid_csi2_rx_cfg));
 
-		CDBG("%s:%d:CSID:%d res id :%d cnt:%d reserv cnt:%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP, "CSID:%d res id :%d cnt:%d reserv cnt:%d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id, cid_data->cnt, csid_hw->csi2_reserve_cnt);
 
 		break;
@@ -1943,8 +1992,8 @@
 		res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d Invalid res type:%d res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_type,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_type,
 			res->res_id);
 		rc = -EINVAL;
 		break;
@@ -1966,7 +2015,7 @@
 
 	if (!hw_priv || !init_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("%s:%d:CSID: Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
 		return -EINVAL;
 	}
 
@@ -1980,8 +2029,8 @@
 		res->res_id >= CAM_IFE_CSID_CID_MAX) ||
 		(res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
 		res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) {
-		pr_err("%s:%d:CSID:%d Invalid res tpe:%d res id%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_type,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res tpe:%d res id%d",
+			csid_hw->hw_intf->hw_idx, res->res_type,
 			res->res_id);
 		rc = -EINVAL;
 		goto end;
@@ -1990,14 +2039,15 @@
 
 	if ((res->res_type == CAM_ISP_RESOURCE_PIX_PATH) &&
 		(res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) {
-		pr_err("%s:%d:CSID:%d res type:%d res_id:%dInvalid state %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP,
+			"CSID:%d res type:%d res_id:%dInvalid state %d",
+			csid_hw->hw_intf->hw_idx,
 			res->res_type, res->res_id, res->res_state);
 		rc = -EINVAL;
 		goto end;
 	}
 
-	CDBG("%s:%d CSID:%d res type :%d res_id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d res type :%d res_id:%d",
 		csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
 
 
@@ -2018,8 +2068,8 @@
 
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d Invalid res type state %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res type state %d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_type);
 		break;
 	}
@@ -2041,7 +2091,7 @@
 
 	if (!hw_priv || !deinit_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("%s:%d:CSID:Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID:Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -2051,8 +2101,8 @@
 
 	mutex_lock(&csid_hw->hw_info->hw_mutex);
 	if (res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
-		CDBG("%s:%d:CSID:%d Res:%d already in De-init state\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in De-init state",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_id);
 		goto end;
 	}
@@ -2069,8 +2119,8 @@
 
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d Invalid Res type %d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid Res type %d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_type);
 		goto end;
 	}
@@ -2094,7 +2144,7 @@
 
 	if (!hw_priv || !start_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("%s:%d:CSID: Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
 		return -EINVAL;
 	}
 
@@ -2103,19 +2153,18 @@
 	res = (struct cam_isp_resource_node *)start_args;
 	csid_reg = csid_hw->csid_info->csid_reg;
 
-	mutex_lock(&csid_hw->hw_info->hw_mutex);
 	if ((res->res_type == CAM_ISP_RESOURCE_CID &&
 		res->res_id >= CAM_IFE_CSID_CID_MAX) ||
 		(res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
 		res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) {
-		CDBG("%s:%d:CSID:%d Invalid res tpe:%d res id:%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, res->res_type,
+		CAM_DBG(CAM_ISP, "CSID:%d Invalid res tpe:%d res id:%d",
+			csid_hw->hw_intf->hw_idx, res->res_type,
 			res->res_id);
 		rc = -EINVAL;
 		goto end;
 	}
 
-	CDBG("%s:%d CSID:%d res_type :%d res_id:%d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d",
 		csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
 
 	switch (res->res_type) {
@@ -2130,13 +2179,12 @@
 			rc = cam_ife_csid_enable_rdi_path(csid_hw, res);
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d Invalid res type%d\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx,
+		CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
+			 csid_hw->hw_intf->hw_idx,
 			res->res_type);
 		break;
 	}
 end:
-	mutex_unlock(&csid_hw->hw_info->hw_mutex);
 	return rc;
 }
 
@@ -2152,14 +2200,13 @@
 
 	if (!hw_priv || !stop_args ||
 		(arg_size != sizeof(struct cam_csid_hw_stop_args))) {
-		pr_err("%s:%d:CSID: Invalid args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
 		return -EINVAL;
 	}
 	csid_stop = (struct cam_csid_hw_stop_args  *) stop_args;
 	csid_hw_info = (struct cam_hw_info  *)hw_priv;
 	csid_hw = (struct cam_ife_csid_hw   *)csid_hw_info->core_info;
 
-	mutex_lock(&csid_hw->hw_info->hw_mutex);
 	/* Stop the resource first */
 	for (i = 0; i < csid_stop->num_res; i++) {
 		res = csid_stop->node_res[i];
@@ -2178,8 +2225,8 @@
 
 			break;
 		default:
-			pr_err("%s:%d:CSID:%d Invalid res type%d\n", __func__,
-				__LINE__, csid_hw->hw_intf->hw_idx,
+			CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
+				csid_hw->hw_intf->hw_idx,
 				res->res_type);
 			break;
 		}
@@ -2191,9 +2238,10 @@
 		if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
 			csid_stop->stop_cmd == CAM_CSID_HALT_AT_FRAME_BOUNDARY)
 			rc = cam_ife_csid_res_wait_for_halt(csid_hw, res);
+		else
+			res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
 	}
 
-	mutex_unlock(&csid_hw->hw_info->hw_mutex);
 	return rc;
 
 }
@@ -2201,7 +2249,7 @@
 static int cam_ife_csid_read(void *hw_priv,
 	void *read_args, uint32_t arg_size)
 {
-	pr_err("%s:%d:CSID: un supported\n", __func__, __LINE__);
+	CAM_ERR(CAM_ISP, "CSID: un supported");
 
 	return -EINVAL;
 }
@@ -2209,7 +2257,7 @@
 static int cam_ife_csid_write(void *hw_priv,
 	void *write_args, uint32_t arg_size)
 {
-	pr_err("%s:%d:CSID: un supported\n", __func__, __LINE__);
+	CAM_ERR(CAM_ISP, "CSID: un supported");
 	return -EINVAL;
 }
 
@@ -2221,7 +2269,7 @@
 	struct cam_hw_info                   *csid_hw_info;
 
 	if (!hw_priv || !cmd_args) {
-		pr_err("%s:%d:CSID: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -2233,8 +2281,8 @@
 		rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args);
 		break;
 	default:
-		pr_err("%s:%d:CSID:%d un supported cmd:%d\n", __func__,
-			__LINE__, csid_hw->hw_intf->hw_idx, cmd_type);
+		CAM_ERR(CAM_ISP, "CSID:%d un supported cmd:%d",
+			csid_hw->hw_intf->hw_idx, cmd_type);
 		rc = -EINVAL;
 		break;
 	}
@@ -2253,11 +2301,10 @@
 
 	csid_hw = (struct cam_ife_csid_hw *)data;
 
-	CDBG("%s:%d:CSID %d IRQ Handling\n", __func__, __LINE__,
-		csid_hw->hw_intf->hw_idx);
+	CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx);
 
 	if (!data) {
-		pr_err("%s:%d:CSID: Invalid arguments\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
 		return IRQ_HANDLED;
 	}
 
@@ -2296,55 +2343,52 @@
 	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
 		csid_reg->cmn_reg->csid_irq_cmd_addr);
 
-	CDBG("%s:%d: irq_status_rx = 0x%x\n", __func__, __LINE__,
-		irq_status_rx);
-	CDBG("%s:%d: irq_status_ipp = 0x%x\n", __func__, __LINE__,
-		irq_status_ipp);
+	CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
+	CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
 
 	if (irq_status_top) {
-		CDBG("%s:%d: CSID global reset complete......Exit\n",
-			__func__, __LINE__);
+		CAM_DBG(CAM_ISP, "CSID global reset complete......Exit");
 		complete(&csid_hw->csid_top_complete);
 		return IRQ_HANDLED;
 	}
 
 
 	if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) {
-		CDBG("%s:%d: csi rx reset complete\n", __func__, __LINE__);
+		CAM_DBG(CAM_ISP, "csi rx reset complete");
 		complete(&csid_hw->csid_csi2_complete);
 	}
 
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
-		pr_err_ratelimited("%s:%d:CSID:%d lane 0 over flow\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d lane 0 over flow",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
-		pr_err_ratelimited("%s:%d:CSID:%d lane 1 over flow\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d lane 1 over flow",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
-		pr_err_ratelimited("%s:%d:CSID:%d lane 2 over flow\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d lane 2 over flow",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
-		pr_err_ratelimited("%s:%d:CSID:%d lane 3 over flow\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d lane 3 over flow",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
-		pr_err_ratelimited("%s:%d:CSID:%d TG OVER  FLOW\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d TG OVER  FLOW",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
-		pr_err_ratelimited("%s:%d:CSID:%d CPHY_EOT_RECEPTION\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d CPHY_EOT_RECEPTION",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
-		pr_err_ratelimited("%s:%d:CSID:%d CPHY_SOT_RECEPTION\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d CPHY_SOT_RECEPTION",
+			 csid_hw->hw_intf->hw_idx);
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
-		pr_err_ratelimited("%s:%d:CSID:%d CPHY_PH_CRC\n",
-			__func__, __LINE__, csid_hw->hw_intf->hw_idx);
+		pr_err_ratelimited("CSID:%d CPHY_PH_CRC",
+			 csid_hw->hw_intf->hw_idx);
 	}
 
 	/*read the IPP errors */
@@ -2352,25 +2396,23 @@
 		/* IPP reset done bit */
 		if (irq_status_ipp &
 			BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
-			CDBG("%s%d: CSID IPP reset complete\n",
-				__func__, __LINE__);
+			CAM_DBG(CAM_ISP, "CSID IPP reset complete");
 			complete(&csid_hw->csid_ipp_complete);
 		}
 		if (irq_status_ipp & CSID_PATH_INFO_INPUT_SOF)
-			CDBG("%s: CSID IPP SOF received\n", __func__);
+			CAM_DBG(CAM_ISP, "CSID IPP SOF received");
 		if (irq_status_ipp & CSID_PATH_INFO_INPUT_SOL)
-			CDBG("%s: CSID IPP SOL received\n", __func__);
+			CAM_DBG(CAM_ISP, "CSID IPP SOL received");
 		if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOL)
-			CDBG("%s: CSID IPP EOL received\n", __func__);
+			CAM_DBG(CAM_ISP, "CSID IPP EOL received");
 		if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOF)
-			CDBG("%s: CSID IPP EOF received\n", __func__);
+			CAM_DBG(CAM_ISP, "CSID IPP EOF received");
 
 		if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOF)
 			complete(&csid_hw->csid_ipp_complete);
 
 		if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
-			pr_err("%s:%d:CSID:%d IPP fifo over flow\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_ISP, "CSID:%d IPP fifo over flow",
 				csid_hw->hw_intf->hw_idx);
 			/*Stop IPP path immediately */
 			cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
@@ -2382,17 +2424,20 @@
 	for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++) {
 		if (irq_status_rdi[i] &
 			BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
-			CDBG("%s:%d: CSID rdi%d reset complete\n",
-				__func__, __LINE__, i);
+			CAM_DBG(CAM_ISP, "CSID rdi%d reset complete", i);
 			complete(&csid_hw->csid_rdin_complete[i]);
 		}
 
+		if (irq_status_rdi[i]  & CSID_PATH_INFO_INPUT_SOF)
+			CAM_DBG(CAM_ISP, "CSID RDI SOF received");
+		if (irq_status_rdi[i]  & CSID_PATH_INFO_INPUT_EOF)
+			CAM_DBG(CAM_ISP, "CSID RDI EOF received");
+
 		if (irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF)
 			complete(&csid_hw->csid_rdin_complete[i]);
 
 		if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
-			pr_err("%s:%d:CSID:%d RDI fifo over flow\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_ISP, "CSID:%d RDI fifo over flow",
 				csid_hw->hw_intf->hw_idx);
 			/*Stop RDI path immediately */
 			cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
@@ -2401,7 +2446,7 @@
 		}
 	}
 
-	CDBG("%s:%d:IRQ Handling exit\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "IRQ Handling exit");
 	return IRQ_HANDLED;
 }
 
@@ -2416,8 +2461,7 @@
 	struct cam_ife_csid_hw               *ife_csid_hw = NULL;
 
 	if (csid_idx >= CAM_IFE_CSID_HW_RES_MAX) {
-		pr_err("%s:%d: Invalid csid index:%d\n", __func__, __LINE__,
-			csid_idx);
+		CAM_ERR(CAM_ISP, "Invalid csid index:%d", csid_idx);
 		return rc;
 	}
 
@@ -2427,7 +2471,7 @@
 	ife_csid_hw->hw_intf = csid_hw_intf;
 	ife_csid_hw->hw_info = csid_hw_info;
 
-	CDBG("%s:%d: type %d index %d\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "type %d index %d",
 		ife_csid_hw->hw_intf->hw_type, csid_idx);
 
 
@@ -2446,8 +2490,7 @@
 	rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info,
 			cam_ife_csid_irq, ife_csid_hw);
 	if (rc < 0) {
-		pr_err("%s:%d:CSID:%d Failed to init_soc\n", __func__, __LINE__,
-			csid_idx);
+		CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc", csid_idx);
 		goto err;
 	}
 
@@ -2539,7 +2582,7 @@
 	uint32_t i;
 
 	if (!ife_csid_hw) {
-		pr_err("%s:%d: Invalid param\n", __func__, __LINE__);
+		CAM_ERR(CAM_ISP, "Invalid param");
 		return rc;
 	}
 
@@ -2553,8 +2596,7 @@
 	for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++)
 		kfree(ife_csid_hw->cid_res[i].res_priv);
 
+	cam_ife_csid_deinit_soc_resources(&ife_csid_hw->hw_info->soc_info);
 
 	return 0;
 }
-
-
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 60e184b..ef585c3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -354,6 +354,7 @@
  * @dt :            Data type number
  * @cid             cid number, it is same as DT_ID number in HW
  * @decode_fmt:     input decode format
+ * @output_fmt:     output resource format, needed for RDI resource
  * @crop_enable:    crop is enable or disabled, if enabled
  *                  then remaining parameters are valid.
  * @start_pixel:    start pixel
@@ -373,6 +374,7 @@
 	uint32_t                        dt;
 	uint32_t                        cid;
 	uint32_t                        decode_fmt;
+	uint32_t                        output_fmt;
 	bool                            crop_enable;
 	uint32_t                        start_pixel;
 	uint32_t                        width;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c
index 003d83f..5a57046 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c
@@ -16,9 +16,7 @@
 #include "cam_ife_csid_core.h"
 #include "cam_ife_csid_dev.h"
 #include "cam_ife_csid_hw_intf.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static struct cam_hw_intf *cam_ife_csid_hw_list[CAM_IFE_CSID_HW_RES_MAX] = {
 	0, 0, 0, 0};
@@ -34,7 +32,7 @@
 	uint32_t                        csid_dev_idx;
 	int                             rc = 0;
 
-	CDBG("%s:%d probe called\n", __func__, __LINE__);
+	CAM_DBG(CAM_ISP, "probe called");
 
 	csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL);
 	if (!csid_hw_intf) {
@@ -60,8 +58,7 @@
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
 	if (!match_dev) {
-		pr_err("%s:%d No matching table for the IFE CSID HW!\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ISP, "No matching table for the IFE CSID HW!");
 		rc = -EINVAL;
 		goto free_dev;
 	}
@@ -72,6 +69,7 @@
 
 	csid_hw_info->core_info = csid_dev;
 	csid_hw_info->soc_info.pdev = pdev;
+	csid_hw_info->soc_info.index = csid_dev_idx;
 
 	csid_hw_data = (struct cam_ife_csid_hw_info  *)match_dev->data;
 	/* need to setup the pdev before call the ife hw probe init */
@@ -82,7 +80,7 @@
 		goto free_dev;
 
 	platform_set_drvdata(pdev, csid_dev);
-	CDBG("%s:%d CSID:%d probe successful\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d probe successful",
 		csid_hw_intf->hw_idx);
 
 
@@ -113,7 +111,7 @@
 	csid_hw_intf = csid_dev->hw_intf;
 	csid_hw_info = csid_dev->hw_info;
 
-	CDBG("%s:%d CSID:%d remove\n", __func__, __LINE__,
+	CAM_DBG(CAM_ISP, "CSID:%d remove",
 		csid_dev->hw_intf->hw_idx);
 
 	cam_ife_csid_hw_deinit(csid_dev);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
index 4ed4da5..36c6df0 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
@@ -15,7 +15,6 @@
 #include "cam_ife_csid_core.h"
 #include "cam_ife_csid_dev.h"
 
-
 #define CAM_CSID_LITE_DRV_NAME                    "csid_lite_170"
 #define CAM_CSID_LITE_VERSION_V170                 0x10070000
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
index c718bba..72050aa 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
@@ -9,11 +9,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
+#include <linux/slab.h>
 #include "cam_ife_csid_soc.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
 
 static int cam_ife_csid_get_dt_properties(struct cam_hw_soc_info *soc_info)
 {
@@ -50,6 +49,14 @@
 	irq_handler_t csid_irq_handler, void *irq_data)
 {
 	int rc = 0;
+	struct cam_cpas_register_params   cpas_register_param;
+	struct cam_csid_soc_private      *soc_private;
+
+	soc_private = kzalloc(sizeof(struct cam_csid_soc_private), GFP_KERNEL);
+	if (!soc_private)
+		return -ENOMEM;
+
+	soc_info->soc_private = soc_private;
 
 	rc = cam_ife_csid_get_dt_properties(soc_info);
 	if (rc < 0)
@@ -59,36 +66,117 @@
 
 	rc = cam_ife_csid_request_platform_resource(soc_info, csid_irq_handler,
 		irq_data);
+	if (rc < 0) {
+		CAM_ERR(CAM_ISP,
+			"Error Request platform resources failed rc=%d", rc);
+		goto free_soc_private;
+	}
+
+	memset(&cpas_register_param, 0, sizeof(cpas_register_param));
+	strlcpy(cpas_register_param.identifier, "csid",
+		CAM_HW_IDENTIFIER_LENGTH);
+	cpas_register_param.cell_index = soc_info->index;
+	cpas_register_param.dev = &soc_info->pdev->dev;
+	rc = cam_cpas_register_client(&cpas_register_param);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
+		goto release_soc;
+	} else {
+		soc_private->cpas_handle = cpas_register_param.client_handle;
+	}
+
+	return rc;
+
+release_soc:
+	cam_soc_util_release_platform_resource(soc_info);
+free_soc_private:
+	kfree(soc_private);
+
+	return rc;
+}
+
+int cam_ife_csid_deinit_soc_resources(
+	struct cam_hw_soc_info *soc_info)
+{
+	int rc = 0;
+	struct cam_csid_soc_private       *soc_private;
+
+	soc_private = soc_info->soc_private;
+	if (!soc_private) {
+		CAM_ERR(CAM_ISP, "Error soc_private NULL");
+		return -ENODEV;
+	}
+
+	rc = cam_cpas_unregister_client(soc_private->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
+
+	rc = cam_soc_util_release_platform_resource(soc_info);
 	if (rc < 0)
 		return rc;
 
-	CDBG("%s: mem_base is 0x%llx\n", __func__,
-		(uint64_t) soc_info->reg_map[0].mem_base);
-
 	return rc;
 }
 
 int cam_ife_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
+	struct cam_csid_soc_private       *soc_private;
+	struct cam_ahb_vote ahb_vote;
+	struct cam_axi_vote axi_vote;
+
+	soc_private = soc_info->soc_private;
+
+	ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	ahb_vote.vote.level = CAM_SVS_VOTE;
+	axi_vote.compressed_bw = 640000000;
+	axi_vote.uncompressed_bw = 640000000;
+
+	CAM_DBG(CAM_ISP, "csid vote compressed_bw:%lld uncompressed_bw:%lld",
+		axi_vote.compressed_bw, axi_vote.uncompressed_bw);
+
+	rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Error CPAS start failed");
+		rc = -EFAULT;
+		goto end;
+	}
 
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, true);
 	if (rc) {
-		pr_err("%s: enable platform failed\n", __func__);
-		return rc;
+		CAM_ERR(CAM_ISP, "enable platform failed");
+		goto stop_cpas;
 	}
 
 	return rc;
+
+stop_cpas:
+	cam_cpas_stop(soc_private->cpas_handle);
+end:
+	return rc;
 }
 
 int cam_ife_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc = 0;
+	struct cam_csid_soc_private       *soc_private;
+
+	if (!soc_info) {
+		CAM_ERR(CAM_ISP, "Error Invalid params");
+		return -EINVAL;
+	}
+	soc_private = soc_info->soc_private;
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc)
-		pr_err("%s: Disable platform failed\n", __func__);
+		CAM_ERR(CAM_ISP, "Disable platform failed");
+
+	rc = cam_cpas_stop(soc_private->cpas_handle);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Error CPAS stop failed rc=%d", rc);
+		return rc;
+	}
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h
index 218e05a..1a30722 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h
@@ -15,6 +15,19 @@
 
 #include "cam_isp_hw.h"
 
+/*
+ * struct cam_csid_soc_private:
+ *
+ * @Brief:                   Private SOC data specific to CSID HW Driver
+ *
+ * @cpas_handle:             Handle returned on registering with CPAS driver.
+ *                           This handle is used for all further interface
+ *                           with CPAS.
+ */
+struct cam_csid_soc_private {
+	uint32_t cpas_handle;
+};
+
 /**
  * struct csid_device_soc_info - CSID SOC info object
  *
@@ -38,6 +51,17 @@
 int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
 	irq_handler_t csid_irq_handler, void *irq_data);
 
+
+/**
+ * cam_ife_csid_deinit_soc_resources()
+ *
+ * @brief:                 csid de initialization function for the soc info
+ *
+ * @soc_info:              soc info structure pointer
+ *
+ */
+int cam_ife_csid_deinit_soc_resources(struct cam_hw_soc_info *soc_info);
+
 /**
  * cam_ife_csid_enable_soc_resources()
  *
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
index ecc6f0e..52b712a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
@@ -69,6 +69,7 @@
  *              if type is path then res id need to be filled
  * @res_id  :  res id to be reserved
  * @in_port : input port resource info
+ * @out_port: output port resource info, used for RDI path only
  * @sync_mode : Sync mode
  *              Sync mode could be master, slave or none
  * @master_idx: master device index to be configured in the slave path
@@ -83,6 +84,7 @@
 	enum cam_isp_resource_type                res_type;
 	uint32_t                                  res_id;
 	struct cam_isp_in_port_info              *in_port;
+	struct cam_isp_out_port_info             *out_port;
 	enum cam_isp_hw_sync_mode                 sync_mode;
 	uint32_t                                  master_idx;
 	uint32_t                                  cid;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index e25d973..e330c84 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/list.h>
@@ -24,9 +22,7 @@
 #include "cam_vfe_bus.h"
 #include "cam_vfe_top.h"
 #include "cam_ife_hw_mgr.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static const char drv_name[] = "vfe";
 
@@ -58,7 +54,7 @@
 	if (list_empty(&core_info->free_payload_list)) {
 		*evt_payload = NULL;
 		spin_unlock(&core_info->spin_lock);
-		pr_err_ratelimited("No free payload, core info 0x%x\n",
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload, core info 0x%x\n",
 			core_info->cpas_handle);
 		return -ENODEV;
 	}
@@ -78,11 +74,11 @@
 	unsigned long                       flags;
 
 	if (!core_info) {
-		pr_err("Invalid param core_info NULL");
+		CAM_ERR(CAM_ISP, "Invalid param core_info NULL");
 		return -EINVAL;
 	}
 	if (*evt_payload == NULL) {
-		pr_err("No payload to put\n");
+		CAM_ERR(CAM_ISP, "No payload to put");
 		return -EINVAL;
 	}
 
@@ -100,9 +96,9 @@
 	struct cam_vfe_hw_core_info       *core_info = NULL;
 	int rc = 0;
 
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 	if (!hw_priv) {
-		pr_err("%s: Invalid arguments\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -113,7 +109,7 @@
 			core_info->vfe_top->top_priv,
 			get_hw_cap_args, arg_size);
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -125,11 +121,11 @@
 
 	handler_priv = th_payload->handler_priv;
 
-	CDBG("Enter\n");
-	CDBG("IRQ status_0 = 0x%x\n", th_payload->evt_status_arr[0]);
+	CAM_DBG(CAM_ISP, "Enter");
+	CAM_DBG(CAM_ISP, "IRQ status_0 = 0x%x", th_payload->evt_status_arr[0]);
 
 	if (th_payload->evt_status_arr[0] & (1<<31)) {
-		CDBG("Calling Complete for RESET CMD\n");
+		CAM_DBG(CAM_ISP, "Calling Complete for RESET CMD");
 		complete(handler_priv->reset_complete);
 
 		/*
@@ -143,7 +139,7 @@
 		rc = 0;
 	}
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -154,9 +150,9 @@
 	struct cam_vfe_hw_core_info       *core_info = NULL;
 	int rc = 0;
 
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 	if (!hw_priv) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -164,7 +160,7 @@
 	vfe_hw->open_count++;
 	if (vfe_hw->open_count > 1) {
 		mutex_unlock(&vfe_hw->hw_mutex);
-		CDBG("VFE has already been initialized cnt %d\n",
+		CAM_DBG(CAM_ISP, "VFE has already been initialized cnt %d",
 			vfe_hw->open_count);
 		return 0;
 	}
@@ -176,24 +172,24 @@
 	/* Turn ON Regulators, Clocks and other SOC resources */
 	rc = cam_vfe_enable_soc_resources(soc_info);
 	if (rc) {
-		pr_err("Enable SOC failed\n");
+		CAM_ERR(CAM_ISP, "Enable SOC failed");
 		rc = -EFAULT;
 		goto decrement_open_cnt;
 	}
 
-	CDBG("Enable soc done\n");
+	CAM_DBG(CAM_ISP, "Enable soc done");
 
 	rc = core_info->vfe_bus->hw_ops.init(core_info->vfe_bus->bus_priv,
 		NULL, 0);
 	if (rc) {
-		pr_err("Bus HW init Failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Bus HW init Failed rc=%d", rc);
 		goto disable_soc;
 	}
 
 	/* Do HW Reset */
 	rc = cam_vfe_reset(hw_priv, NULL, 0);
 	if (rc) {
-		pr_err("Reset Failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Reset Failed rc=%d", rc);
 		goto deinit_bus;
 	}
 
@@ -217,22 +213,22 @@
 	struct cam_hw_soc_info            *soc_info = NULL;
 	int rc = 0;
 
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 	if (!hw_priv) {
-		pr_err("%s: Invalid arguments\n", __func__);
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	mutex_lock(&vfe_hw->hw_mutex);
 	if (!vfe_hw->open_count) {
 		mutex_unlock(&vfe_hw->hw_mutex);
-		pr_err("Error! Unbalanced deinit\n");
+		CAM_ERR(CAM_ISP, "Error! Unbalanced deinit");
 		return -EFAULT;
 	}
 	vfe_hw->open_count--;
 	if (vfe_hw->open_count) {
 		mutex_unlock(&vfe_hw->hw_mutex);
-		CDBG("open_cnt non-zero =%d\n", vfe_hw->open_count);
+		CAM_DBG(CAM_ISP, "open_cnt non-zero =%d", vfe_hw->open_count);
 		return 0;
 	}
 	mutex_unlock(&vfe_hw->hw_mutex);
@@ -240,14 +236,14 @@
 	soc_info = &vfe_hw->soc_info;
 
 	/* Turn OFF Regulators, Clocks and other SOC resources */
-	CDBG("Disable SOC resource\n");
+	CAM_DBG(CAM_ISP, "Disable SOC resource");
 	rc = cam_vfe_disable_soc_resources(soc_info);
 	if (rc)
-		pr_err("Disable SOC failed\n");
+		CAM_ERR(CAM_ISP, "Disable SOC failed");
 
 	vfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -258,10 +254,10 @@
 	struct cam_vfe_hw_core_info       *core_info = NULL;
 	int rc;
 
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 
 	if (!hw_priv) {
-		pr_err("Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -279,28 +275,28 @@
 		top_reset_irq_reg_mask, &core_info->irq_payload,
 		cam_vfe_reset_irq_top_half, NULL, NULL, NULL);
 	if (core_info->irq_handle < 0) {
-		pr_err("subscribe irq controller failed\n");
+		CAM_ERR(CAM_ISP, "subscribe irq controller failed");
 		return -EFAULT;
 	}
 
 	reinit_completion(&vfe_hw->hw_complete);
 
-	CDBG("calling RESET\n");
+	CAM_DBG(CAM_ISP, "calling RESET");
 	core_info->vfe_top->hw_ops.reset(core_info->vfe_top->top_priv, NULL, 0);
-	CDBG("waiting for vfe reset complete\n");
+	CAM_DBG(CAM_ISP, "waiting for vfe reset complete");
 	/* Wait for Completion or Timeout of 500ms */
 	rc = wait_for_completion_timeout(&vfe_hw->hw_complete, 500);
 	if (!rc)
-		pr_err("Error! Reset Timeout\n");
+		CAM_ERR(CAM_ISP, "Error! Reset Timeout");
 
-	CDBG("reset complete done (%d)\n", rc);
+	CAM_DBG(CAM_ISP, "reset complete done (%d)", rc);
 
 	rc = cam_irq_controller_unsubscribe_irq(
 		core_info->vfe_irq_controller, core_info->irq_handle);
 	if (rc)
-		pr_err("Error! Unsubscribe failed\n");
+		CAM_ERR(CAM_ISP, "Error! Unsubscribe failed");
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -324,12 +320,13 @@
 
 	handler_priv = th_payload->handler_priv;
 
-	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
-	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+	CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
+	CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
 
 	rc  = cam_vfe_get_evt_payload(handler_priv->core_info, &evt_payload);
 	if (rc) {
-		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+			"No tasklet_cmd is free in queue\n");
 		return rc;
 	}
 
@@ -346,14 +343,14 @@
 		evt_payload->irq_reg_val[i] = cam_io_r(handler_priv->mem_base +
 			irq_reg_offset[i]);
 	}
-	CDBG("Violation status = %x\n", evt_payload->irq_reg_val[2]);
+	CAM_DBG(CAM_ISP, "Violation status = %x", evt_payload->irq_reg_val[2]);
 
 	/*
 	 *  need to handle overflow condition here, otherwise irq storm
 	 *  will block everything.
 	 */
 	if (evt_payload->irq_reg_val[1]) {
-		pr_err("Mask all the interrupts\n");
+		CAM_ERR(CAM_ISP, "Mask all the interrupts");
 		cam_io_w(0, handler_priv->mem_base + 0x60);
 		cam_io_w(0, handler_priv->mem_base + 0x5C);
 
@@ -362,7 +359,7 @@
 
 	th_payload->evt_payload_priv = evt_payload;
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -376,7 +373,7 @@
 
 	if (!hw_priv || !reserve_args || (arg_size !=
 		sizeof(struct cam_vfe_acquire_args))) {
-		pr_err("Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid input arguments");
 		return -EINVAL;
 	}
 	core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
@@ -393,7 +390,7 @@
 			core_info->vfe_bus->bus_priv, acquire,
 			sizeof(*acquire));
 	else
-		pr_err("Invalid res type:%d\n", acquire->rsrc_type);
+		CAM_ERR(CAM_ISP, "Invalid res type:%d", acquire->rsrc_type);
 
 	mutex_unlock(&vfe_hw->hw_mutex);
 
@@ -410,7 +407,7 @@
 
 	if (!hw_priv || !release_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -427,7 +424,7 @@
 			core_info->vfe_bus->bus_priv, isp_res,
 			sizeof(*isp_res));
 	else
-		pr_err("Invalid res type:%d\n", isp_res->res_type);
+		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
 
 	mutex_unlock(&vfe_hw->hw_mutex);
 
@@ -444,7 +441,7 @@
 
 	if (!hw_priv || !start_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -473,11 +470,12 @@
 				core_info->vfe_top->top_priv, isp_res,
 				sizeof(struct cam_isp_resource_node));
 		else
-			pr_err("Error! subscribe irq controller failed\n");
+			CAM_ERR(CAM_ISP,
+				"Error! subscribe irq controller failed");
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0);
 	} else {
-		pr_err("Invalid res type:%d\n", isp_res->res_type);
+		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
 	}
 
 	mutex_unlock(&vfe_hw->hw_mutex);
@@ -494,7 +492,7 @@
 
 	if (!hw_priv || !stop_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
-		pr_err("Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -513,7 +511,7 @@
 			core_info->vfe_irq_controller, isp_res->irq_handle);
 		rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
 	} else {
-		pr_err("Invalid res type:%d\n", isp_res->res_type);
+		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
 	}
 
 	mutex_unlock(&vfe_hw->hw_mutex);
@@ -541,7 +539,7 @@
 	int rc = 0;
 
 	if (!hw_priv) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -564,7 +562,7 @@
 		break;
 
 	default:
-		pr_err("Invalid cmd type:%d\n", cmd_type);
+		CAM_ERR(CAM_ISP, "Invalid cmd type:%d", cmd_type);
 		rc = -EINVAL;
 		break;
 	}
@@ -594,13 +592,13 @@
 	int rc = -EINVAL;
 	int i;
 
-	CDBG("Enter");
+	CAM_DBG(CAM_ISP, "Enter");
 
 	rc = cam_irq_controller_init(drv_name,
 		CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX),
 		vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller);
 	if (rc) {
-		pr_err("Error! cam_irq_controller_init failed\n");
+		CAM_ERR(CAM_ISP, "Error! cam_irq_controller_init failed");
 		return rc;
 	}
 
@@ -608,7 +606,7 @@
 		soc_info, hw_intf, vfe_hw_info->top_hw_info,
 		&core_info->vfe_top);
 	if (rc) {
-		pr_err("Error! cam_vfe_top_init failed\n");
+		CAM_ERR(CAM_ISP, "Error! cam_vfe_top_init failed");
 		goto deinit_controller;
 	}
 
@@ -616,7 +614,7 @@
 		vfe_hw_info->bus_hw_info, core_info->vfe_irq_controller,
 		&core_info->vfe_bus);
 	if (rc) {
-		pr_err("Error! cam_vfe_bus_init failed\n");
+		CAM_ERR(CAM_ISP, "Error! cam_vfe_bus_init failed");
 		goto deinit_top;
 	}
 
@@ -657,16 +655,17 @@
 	rc = cam_vfe_bus_deinit(vfe_hw_info->bus_version,
 		&core_info->vfe_bus);
 	if (rc)
-		pr_err("Error cam_vfe_bus_deinit failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error cam_vfe_bus_deinit failed rc=%d", rc);
 
 	rc = cam_vfe_top_deinit(vfe_hw_info->top_version,
 		&core_info->vfe_top);
 	if (rc)
-		pr_err("Error cam_vfe_top_deinit failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error cam_vfe_top_deinit failed rc=%d", rc);
 
 	rc = cam_irq_controller_deinit(&core_info->vfe_irq_controller);
 	if (rc)
-		pr_err("Error cam_irq_controller_deinit failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP,
+			"Error cam_irq_controller_deinit failed rc=%d", rc);
 
 	spin_unlock_irqrestore(&core_info->spin_lock, flags);
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
index cdb8d6f..3e2307c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
 
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
@@ -18,9 +17,7 @@
 #include "cam_vfe_dev.h"
 #include "cam_vfe_core.h"
 #include "cam_vfe_soc.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX] = {0, 0, 0, 0};
 
@@ -62,14 +59,15 @@
 	vfe_hw_intf->hw_ops.process_cmd = cam_vfe_process_cmd;
 	vfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_VFE;
 
-	CDBG("type %d index %d\n", vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx);
+	CAM_DBG(CAM_ISP, "type %d index %d",
+		vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx);
 
 	platform_set_drvdata(pdev, vfe_hw_intf);
 
 	vfe_hw->core_info = kzalloc(sizeof(struct cam_vfe_hw_core_info),
 		GFP_KERNEL);
 	if (!vfe_hw->core_info) {
-		CDBG("Failed to alloc for core\n");
+		CAM_DBG(CAM_ISP, "Failed to alloc for core");
 		rc = -ENOMEM;
 		goto free_vfe_hw;
 	}
@@ -78,7 +76,7 @@
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
 	if (!match_dev) {
-		pr_err("Of_match Failed\n");
+		CAM_ERR(CAM_ISP, "Of_match Failed");
 		rc = -EINVAL;
 		goto free_core_info;
 	}
@@ -88,14 +86,14 @@
 	rc = cam_vfe_init_soc_resources(&vfe_hw->soc_info, cam_vfe_irq,
 		vfe_hw);
 	if (rc < 0) {
-		pr_err("Failed to init soc rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Failed to init soc rc=%d", rc);
 		goto free_core_info;
 	}
 
 	rc = cam_vfe_core_init(core_info, &vfe_hw->soc_info,
 		vfe_hw_intf, hw_info);
 	if (rc < 0) {
-		pr_err("Failed to init core rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Failed to init core rc=%d", rc);
 		goto deinit_soc;
 	}
 
@@ -110,13 +108,13 @@
 	cam_vfe_init_hw(vfe_hw, NULL, 0);
 	cam_vfe_deinit_hw(vfe_hw, NULL, 0);
 
-	CDBG("VFE%d probe successful\n", vfe_hw_intf->hw_idx);
+	CAM_DBG(CAM_ISP, "VFE%d probe successful", vfe_hw_intf->hw_idx);
 
 	return rc;
 
 deinit_soc:
 	if (cam_vfe_deinit_soc_resources(&vfe_hw->soc_info))
-		pr_err("Failed to deinit soc\n");
+		CAM_ERR(CAM_ISP, "Failed to deinit soc");
 free_core_info:
 	kfree(vfe_hw->core_info);
 free_vfe_hw:
@@ -136,44 +134,45 @@
 
 	vfe_hw_intf = platform_get_drvdata(pdev);
 	if (!vfe_hw_intf) {
-		pr_err("Error! No data in pdev\n");
+		CAM_ERR(CAM_ISP, "Error! No data in pdev");
 		return -EINVAL;
 	}
 
-	CDBG("type %d index %d\n", vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx);
+	CAM_DBG(CAM_ISP, "type %d index %d",
+		vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx);
 
 	if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX)
 		cam_vfe_hw_list[vfe_hw_intf->hw_idx] = NULL;
 
 	vfe_hw = vfe_hw_intf->hw_priv;
 	if (!vfe_hw) {
-		pr_err("Error! HW data is NULL\n");
+		CAM_ERR(CAM_ISP, "Error! HW data is NULL");
 		rc = -ENODEV;
 		goto free_vfe_hw_intf;
 	}
 
 	core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
 	if (!core_info) {
-		pr_err("Error! core data NULL");
+		CAM_ERR(CAM_ISP, "Error! core data NULL");
 		rc = -EINVAL;
 		goto deinit_soc;
 	}
 
 	rc = cam_vfe_core_deinit(core_info, core_info->vfe_hw_info);
 	if (rc < 0)
-		pr_err("Failed to deinit core rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Failed to deinit core rc=%d", rc);
 
 	kfree(vfe_hw->core_info);
 
 deinit_soc:
 	rc = cam_vfe_deinit_soc_resources(&vfe_hw->soc_info);
 	if (rc < 0)
-		pr_err("Failed to deinit soc rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Failed to deinit soc rc=%d", rc);
 
 	mutex_destroy(&vfe_hw->hw_mutex);
 	kfree(vfe_hw);
 
-	CDBG("VFE%d remove successful\n", vfe_hw_intf->hw_idx);
+	CAM_DBG(CAM_ISP, "VFE%d remove successful", vfe_hw_intf->hw_idx);
 
 free_vfe_hw_intf:
 	kfree(vfe_hw_intf);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
index fa9d86b..3b2ead2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
@@ -10,14 +10,10 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/slab.h>
 #include "cam_cpas_api.h"
 #include "cam_vfe_soc.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info)
 {
@@ -25,7 +21,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc) {
-		pr_err("Error! get DT properties failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error! get DT properties failed rc=%d", rc);
 		return rc;
 	}
 
@@ -41,7 +37,8 @@
 	rc = cam_soc_util_request_platform_resource(soc_info, vfe_irq_handler,
 		irq_data);
 	if (rc)
-		pr_err("Error! Request platform resource failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP,
+			"Error! Request platform resource failed rc=%d", rc);
 
 	return rc;
 }
@@ -52,7 +49,8 @@
 
 	rc = cam_soc_util_release_platform_resource(soc_info);
 	if (rc)
-		pr_err("Error! Release platform resource failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP,
+			"Error! Release platform resource failed rc=%d", rc);
 
 	return rc;
 }
@@ -67,21 +65,22 @@
 	soc_private = kzalloc(sizeof(struct cam_vfe_soc_private),
 		GFP_KERNEL);
 	if (!soc_private) {
-		CDBG("Error! soc_private Alloc Failed\n");
+		CAM_DBG(CAM_ISP, "Error! soc_private Alloc Failed");
 		return -ENOMEM;
 	}
 	soc_info->soc_private = soc_private;
 
 	rc = cam_vfe_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("Error! Get DT properties failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error! Get DT properties failed rc=%d", rc);
 		goto free_soc_private;
 	}
 
 	rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler,
 		irq_data);
 	if (rc < 0) {
-		pr_err("Error! Request platform resources failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP,
+			"Error! Request platform resources failed rc=%d", rc);
 		goto free_soc_private;
 	}
 
@@ -92,7 +91,7 @@
 	cpas_register_param.dev = &soc_info->pdev->dev;
 	rc = cam_cpas_register_client(&cpas_register_param);
 	if (rc) {
-		pr_err("CPAS registration failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
 		goto release_soc;
 	} else {
 		soc_private->cpas_handle = cpas_register_param.client_handle;
@@ -114,23 +113,24 @@
 	struct cam_vfe_soc_private       *soc_private;
 
 	if (!soc_info) {
-		pr_err("Error! soc_info NULL\n");
+		CAM_ERR(CAM_ISP, "Error! soc_info NULL");
 		return -ENODEV;
 	}
 
 	soc_private = soc_info->soc_private;
 	if (!soc_private) {
-		pr_err("Error! soc_private NULL\n");
+		CAM_ERR(CAM_ISP, "Error! soc_private NULL");
 		return -ENODEV;
 	}
 
 	rc = cam_cpas_unregister_client(soc_private->cpas_handle);
 	if (rc)
-		pr_err("CPAS unregistration failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
 
 	rc = cam_vfe_release_platform_resource(soc_info);
 	if (rc < 0)
-		pr_err("Error! Release platform resources failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP,
+			"Error! Release platform resources failed rc=%d", rc);
 
 	kfree(soc_private);
 
@@ -145,7 +145,7 @@
 	struct cam_axi_vote               axi_vote;
 
 	if (!soc_info) {
-		pr_err("Error! Invalid params\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid params");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -159,7 +159,7 @@
 
 	rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
 	if (rc) {
-		pr_err("Error! CPAS start failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error! CPAS start failed rc=%d", rc);
 		rc = -EFAULT;
 		goto end;
 	}
@@ -167,7 +167,7 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, true);
 	if (rc) {
-		pr_err("Error! enable platform failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error! enable platform failed rc=%d", rc);
 		goto stop_cpas;
 	}
 
@@ -186,7 +186,7 @@
 	struct cam_vfe_soc_private       *soc_private;
 
 	if (!soc_info) {
-		pr_err("Error! Invalid params\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid params");
 		rc = -EINVAL;
 		return rc;
 	}
@@ -194,13 +194,13 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc) {
-		pr_err("Disable platform failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Disable platform failed rc=%d", rc);
 		return rc;
 	}
 
 	rc = cam_cpas_stop(soc_private->cpas_handle);
 	if (rc) {
-		pr_err("Error! CPAS stop failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
 		return rc;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
index 0ac5f6d..0af32ad 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
@@ -16,9 +16,6 @@
 #include "cam_vfe_core.h"
 #include "cam_vfe_dev.h"
 
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-
 static const struct of_device_id cam_vfe170_dt_match[] = {
 	{
 		.compatible = "qcom,vfe170",
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
index b550071..275c7b5 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
@@ -117,6 +117,28 @@
 	.reg_update_cmd           = 0x000004AC,
 };
 
+static struct cam_vfe_rdi_ver2_reg vfe170_rdi_reg = {
+	.reg_update_cmd           = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_reg_data  vfe_170_rdi_0_data = {
+	.reg_update_cmd_data      = 0x2,
+	.sof_irq_mask             = 0x8000000,
+	.reg_update_irq_mask      = 0x20,
+};
+
+static struct cam_vfe_rdi_reg_data  vfe_170_rdi_1_data = {
+	.reg_update_cmd_data      = 0x4,
+	.sof_irq_mask             = 0x10000000,
+	.reg_update_irq_mask      = 0x40,
+};
+
+static struct cam_vfe_rdi_reg_data  vfe_170_rdi_2_data = {
+	.reg_update_cmd_data      = 0x8,
+	.sof_irq_mask             = 0x20000000,
+	.reg_update_irq_mask      = 0x80,
+};
+
 static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
 	.common_reg = &vfe170_top_common_reg,
 	.camif_hw_info = {
@@ -124,6 +146,16 @@
 		.camif_reg =  &vfe170_camif_reg,
 		.reg_data  =  &vfe_170_camif_reg_data,
 		},
+	.rdi_hw_info = {
+		.common_reg = &vfe170_top_common_reg,
+		.rdi_reg    = &vfe170_rdi_reg,
+		.reg_data = {
+			&vfe_170_rdi_0_data,
+			&vfe_170_rdi_1_data,
+			&vfe_170_rdi_2_data,
+			NULL,
+			},
+		},
 	.mux_type = {
 		CAM_VFE_CAMIF_VER_2_0,
 		CAM_VFE_RDI_VER_1_0,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
index 63ca5c2..c6c3272 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
@@ -10,11 +10,10 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include "cam_vfe_bus.h"
 #include "cam_vfe_bus_ver1.h"
 #include "cam_vfe_bus_ver2.h"
+#include "cam_debug_util.h"
 
 int cam_vfe_bus_init(uint32_t          bus_version,
 	struct cam_hw_soc_info        *soc_info,
@@ -31,7 +30,7 @@
 			vfe_irq_controller, vfe_bus);
 		break;
 	default:
-		pr_err("Unsupported Bus Version %x\n", bus_version);
+		CAM_ERR(CAM_ISP, "Unsupported Bus Version %x", bus_version);
 		break;
 	}
 
@@ -48,7 +47,7 @@
 		rc = cam_vfe_bus_ver2_deinit(vfe_bus);
 		break;
 	default:
-		pr_err("Unsupported Bus Version %x\n", bus_version);
+		CAM_ERR(CAM_ISP, "Unsupported Bus Version %x", bus_version);
 		break;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 489689c..5d7a1b9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/ratelimit.h>
 #include <linux/slab.h>
 #include "cam_io_util.h"
@@ -24,9 +22,7 @@
 #include "cam_vfe_bus.h"
 #include "cam_vfe_bus_ver2.h"
 #include "cam_vfe_core.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 static const char drv_name[] = "vfe_bus";
 
@@ -37,6 +33,9 @@
 
 #define CAM_VFE_BUS_VER2_PAYLOAD_MAX             256
 
+#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH           0xFF01
+#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE          0xFF01
+
 #define MAX_BUF_UPDATE_REG_NUM   \
 	(sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
 #define MAX_REG_VAL_PAIR_SIZE    \
@@ -174,7 +173,7 @@
 {
 	if (list_empty(&common_data->free_payload_list)) {
 		*evt_payload = NULL;
-		pr_err("No free payload\n");
+		CAM_ERR(CAM_ISP, "No free payload");
 		return -ENODEV;
 	}
 
@@ -192,11 +191,11 @@
 	uint32_t   status_reg0, status_reg1, status_reg2;
 
 	if (!core_info) {
-		pr_err("Invalid param core_info NULL");
+		CAM_ERR(CAM_ISP, "Invalid param core_info NULL");
 		return -EINVAL;
 	}
 	if (*evt_payload == NULL) {
-		pr_err("No payload to put\n");
+		CAM_ERR(CAM_ISP, "No payload to put");
 		return -EINVAL;
 	}
 
@@ -206,7 +205,7 @@
 	status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
 
 	if (status_reg0 || status_reg1 || status_reg2) {
-		CDBG("status0 0x%x status1 0x%x status2 0x%x\n",
+		CAM_DBG(CAM_ISP, "status0 0x%x status1 0x%x status2 0x%x",
 			status_reg0, status_reg1, status_reg2);
 		return 0;
 	}
@@ -229,7 +228,8 @@
 	*intra_client_mask = 0;
 
 	if (dual_slave_core == current_core) {
-		pr_err("Invalid params. Same core as Master and Slave\n");
+		CAM_ERR(CAM_ISP,
+			"Invalid params. Same core as Master and Slave");
 		return -EINVAL;
 	}
 
@@ -243,7 +243,7 @@
 			*intra_client_mask = 0x2;
 			break;
 		default:
-			pr_err("Invalid value for slave core %u\n",
+			CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
 				dual_slave_core);
 			rc = -EINVAL;
 			break;
@@ -258,7 +258,7 @@
 			*intra_client_mask = 0x2;
 			break;
 		default:
-			pr_err("Invalid value for slave core %u\n",
+			CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
 				dual_slave_core);
 			rc = -EINVAL;
 			break;
@@ -273,14 +273,15 @@
 			*intra_client_mask = 0x2;
 			break;
 		default:
-			pr_err("Invalid value for slave core %u\n",
+			CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
 				dual_slave_core);
 			rc = -EINVAL;
 			break;
 		}
 		break;
 	default:
-		pr_err("Invalid value for master core %u\n", current_core);
+		CAM_ERR(CAM_ISP,
+			"Invalid value for master core %u", current_core);
 		rc = -EINVAL;
 		break;
 	}
@@ -348,6 +349,19 @@
 		case CAM_FORMAT_MIPI_RAW_14:
 		case CAM_FORMAT_MIPI_RAW_16:
 		case CAM_FORMAT_MIPI_RAW_20:
+		case CAM_FORMAT_DPCM_10_6_10:
+		case CAM_FORMAT_DPCM_10_8_10:
+		case CAM_FORMAT_DPCM_12_6_12:
+		case CAM_FORMAT_DPCM_12_8_12:
+		case CAM_FORMAT_DPCM_14_8_14:
+		case CAM_FORMAT_DPCM_14_10_14:
+		case CAM_FORMAT_PLAIN8:
+		case CAM_FORMAT_PLAIN16_8:
+		case CAM_FORMAT_PLAIN16_10:
+		case CAM_FORMAT_PLAIN16_12:
+		case CAM_FORMAT_PLAIN16_14:
+		case CAM_FORMAT_PLAIN16_16:
+		case CAM_FORMAT_PLAIN32_20:
 		case CAM_FORMAT_PLAIN128:
 			return 1;
 		default:
@@ -442,7 +456,8 @@
 		break;
 	}
 
-	pr_err("Unsupported format %u for resource_type %u", format, res_type);
+	CAM_ERR(CAM_ISP, "Unsupported format %u for resource_type %u",
+		format, res_type);
 
 	return -EINVAL;
 }
@@ -635,9 +650,9 @@
 	switch (out_fmt) {
 	case CAM_FORMAT_NV21:
 	case CAM_FORMAT_NV12:
+	case CAM_FORMAT_UBWC_NV12:
+	case CAM_FORMAT_UBWC_NV12_4R:
 		return PACKER_FMT_PLAIN_8_LSB_MSB_10;
-	case CAM_FORMAT_PLAIN16_16:
-		return PACKER_FMT_PLAIN_16_16BPP;
 	case CAM_FORMAT_PLAIN64:
 		return PACKER_FMT_PLAIN_64;
 	case CAM_FORMAT_MIPI_RAW_6:
@@ -647,14 +662,20 @@
 	case CAM_FORMAT_MIPI_RAW_14:
 	case CAM_FORMAT_MIPI_RAW_16:
 	case CAM_FORMAT_MIPI_RAW_20:
-	case CAM_FORMAT_QTI_RAW_8:
-	case CAM_FORMAT_QTI_RAW_10:
-	case CAM_FORMAT_QTI_RAW_12:
-	case CAM_FORMAT_QTI_RAW_14:
 	case CAM_FORMAT_PLAIN128:
+	case CAM_FORMAT_PLAIN8:
+	case CAM_FORMAT_PLAIN16_8:
+	case CAM_FORMAT_PLAIN16_10:
+	case CAM_FORMAT_PLAIN16_12:
+	case CAM_FORMAT_PLAIN16_14:
+	case CAM_FORMAT_PLAIN16_16:
+	case CAM_FORMAT_PLAIN32_20:
 	case CAM_FORMAT_PD8:
 	case CAM_FORMAT_PD10:
 		return PACKER_FMT_PLAIN_128;
+	case CAM_FORMAT_UBWC_TP10:
+	case CAM_FORMAT_TP10:
+		return PACKER_FMT_TP_10;
 	default:
 		return PACKER_FMT_MAX;
 	}
@@ -682,7 +703,7 @@
 	/* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
 	wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
 	if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
-		pr_err("Unsupported VFE out %d plane %d\n",
+		CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d",
 			vfe_out_res_id, plane);
 		return -EINVAL;
 	}
@@ -701,55 +722,67 @@
 	rsrc_data->height = out_port_info->height;
 
 	if (rsrc_data->index < 3) {
-		rsrc_data->width = rsrc_data->width * 5/4 * rsrc_data->height;
-		rsrc_data->height = 1;
+		/* Write master 0-2 refers to RDI 0/ RDI 1/RDI 2 */
+		rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH;
+		rsrc_data->height = 0;
+		rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
+		rsrc_data->pack_fmt = 0x0;
 		rsrc_data->en_cfg = 0x3;
 	} else if (rsrc_data->index < 5 ||
 		rsrc_data->index == 7 || rsrc_data->index == 8) {
-		switch (plane) {
-		case PLANE_Y:
-			switch (rsrc_data->format) {
-			case CAM_FORMAT_UBWC_NV12:
-			case CAM_FORMAT_UBWC_NV12_4R:
-			case CAM_FORMAT_UBWC_TP10:
-				rsrc_data->en_ubwc = 1;
+		/* Write master 3, 4 - for Full OUT , 7-8  FD OUT */
+		switch (rsrc_data->format) {
+		case CAM_FORMAT_UBWC_NV12:
+		case CAM_FORMAT_UBWC_NV12_4R:
+			rsrc_data->en_ubwc = 1;
+			/* Fall through for NV12 */
+		case CAM_FORMAT_NV21:
+		case CAM_FORMAT_NV12:
+			switch (plane) {
+			case PLANE_C:
+				rsrc_data->height /= 2;
+				break;
+			case PLANE_Y:
 				break;
 			default:
-				break;
+				CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
+				return -EINVAL;
 			}
 			break;
-		case PLANE_C:
-			switch (rsrc_data->format) {
-			case CAM_FORMAT_NV21:
-			case CAM_FORMAT_NV12:
+		case CAM_FORMAT_UBWC_TP10:
+			rsrc_data->en_ubwc = 1;
+			/* Fall through for LINEAR TP10 */
+		case CAM_FORMAT_TP10:
+			rsrc_data->width = rsrc_data->width * 4 / 3;
+			switch (plane) {
+			case PLANE_C:
 				rsrc_data->height /= 2;
 				break;
-			case CAM_FORMAT_UBWC_NV12:
-			case CAM_FORMAT_UBWC_NV12_4R:
-			case CAM_FORMAT_UBWC_TP10:
-				rsrc_data->height /= 2;
-				rsrc_data->en_ubwc = 1;
+			case PLANE_Y:
 				break;
 			default:
-				break;
+				CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
+				return -EINVAL;
 			}
 			break;
 		default:
-			pr_err("Invalid plane type %d\n", plane);
+			CAM_ERR(CAM_ISP, "Invalid format %d\n",
+				rsrc_data->format);
 			return -EINVAL;
 		}
 		rsrc_data->en_cfg = 0x1;
 	} else if (rsrc_data->index >= 11) {
+		/* Write master 11-19  stats */
 		rsrc_data->width = 0;
 		rsrc_data->height = 0;
 		rsrc_data->stride = 1;
 		rsrc_data->en_cfg = 0x3;
 	} else {
+		/* Write master 5-6 DS ports , 9 - Raw dump , 10 PDAF */
 		rsrc_data->width = rsrc_data->width * 4;
 		rsrc_data->height = rsrc_data->height / 2;
 		rsrc_data->en_cfg = 0x1;
 	}
-
 	if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
 		vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
 		rsrc_data->frame_based = 1;
@@ -807,7 +840,6 @@
 
 	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
 	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
-	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->frame_inc);
 	cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
 
 	cam_io_w_mb(rsrc_data->width,
@@ -817,19 +849,14 @@
 	cam_io_w(rsrc_data->pack_fmt,
 		common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
 
-	cam_io_w(0xFFFFFFFF, common_data->mem_base +
-		rsrc_data->hw_regs->irq_subsample_pattern);
-	cam_io_w(0x0, common_data->mem_base +
-		rsrc_data->hw_regs->irq_subsample_period);
-
-	cam_io_w(0xFFFFFFFF,
-		common_data->mem_base + rsrc_data->hw_regs->framedrop_pattern);
-	cam_io_w(0x0,
-		common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
+	/* Configure stride for RDIs */
+	if (rsrc_data->index < 3)
+		cam_io_w_mb(rsrc_data->stride, (common_data->mem_base +
+			rsrc_data->hw_regs->stride));
 
 	/* Subscribe IRQ */
 	if (rsrc_data->irq_enabled) {
-		CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
+		CAM_DBG(CAM_ISP, "Subscribe WM%d IRQ", rsrc_data->index);
 		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
 			(1 << rsrc_data->index);
 		wm_res->irq_handle = cam_irq_controller_subscribe_irq(
@@ -839,24 +866,31 @@
 			cam_ife_mgr_do_tasklet_buf_done,
 			wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
 		if (wm_res->irq_handle < 0) {
-			pr_err("Subscribe IRQ failed for WM %d\n",
+			CAM_ERR(CAM_ISP, "Subscribe IRQ failed for WM %d",
 				rsrc_data->index);
 			return -EFAULT;
 		}
 	}
 
+	/* enable ubwc if needed*/
+	if (rsrc_data->en_ubwc) {
+		cam_io_w_mb(0x1, common_data->mem_base +
+			rsrc_data->hw_regs->ubwc_regs->mode_cfg);
+	}
+
 	/* Enable WM */
 	cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
 		rsrc_data->hw_regs->cfg);
 
-	CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
+	CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index,
 		rsrc_data->width, rsrc_data->height);
-	CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
+	CAM_DBG(CAM_ISP, "WM res %d pk_fmt = %d", rsrc_data->index,
 		rsrc_data->pack_fmt & PACKER_FMT_MAX);
-	CDBG("WM res %d stride = %d, burst len = %d\n",
+	CAM_DBG(CAM_ISP, "WM res %d stride = %d, burst len = %d",
 		rsrc_data->index, rsrc_data->stride, 0xf);
-	CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
-		(uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
+	CAM_DBG(CAM_ISP, "enable WM res %d offset 0x%x val 0x%x",
+		rsrc_data->index, (uint32_t) rsrc_data->hw_regs->cfg,
+		rsrc_data->en_cfg);
 
 	wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 
@@ -875,7 +909,7 @@
 	cam_io_w_mb(0x0,
 		common_data->mem_base + rsrc_data->hw_regs->cfg);
 
-	CDBG("irq_enabled %d", rsrc_data->irq_enabled);
+	CAM_DBG(CAM_ISP, "irq_enabled %d", rsrc_data->irq_enabled);
 	/* Unsubscribe IRQ */
 	if (rsrc_data->irq_enabled)
 		rc = cam_irq_controller_unsubscribe_irq(
@@ -902,18 +936,19 @@
 
 	wm_res = th_payload->handler_priv;
 	if (!wm_res) {
-		pr_err_ratelimited("Error! No resource\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
 		return -ENODEV;
 	}
 
 	rsrc_data = wm_res->res_priv;
 
-	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
-	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+	CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
+	CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
 
 	rc  = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
 	if (rc) {
-		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+			"No tasklet_cmd is free in queue\n");
 		return rc;
 	}
 
@@ -928,7 +963,7 @@
 
 	th_payload->evt_payload_priv = evt_payload;
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -954,7 +989,7 @@
 			~BIT(rsrc_data->index);
 		rc = CAM_VFE_IRQ_STATUS_SUCCESS;
 	}
-	CDBG("status_reg %x rc %d\n", status_reg, rc);
+	CAM_DBG(CAM_ISP, "status_reg %x rc %d", status_reg, rc);
 
 	if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
 		cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
@@ -973,7 +1008,7 @@
 	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
 		GFP_KERNEL);
 	if (!rsrc_data) {
-		CDBG("Failed to alloc for WM res priv\n");
+		CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv");
 		return -ENOMEM;
 	}
 	wm_res->res_priv = rsrc_data;
@@ -1011,7 +1046,7 @@
 	rsrc_data = wm_res->res_priv;
 	wm_res->res_priv = NULL;
 	if (!rsrc_data) {
-		pr_err("Error! WM res priv is NULL\n");
+		CAM_ERR(CAM_ISP, "Error! WM res priv is NULL");
 		return -ENOMEM;
 	}
 	kfree(rsrc_data);
@@ -1074,7 +1109,7 @@
 		/* First find a free group */
 		if (is_dual) {
 			if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
-				pr_err("No Free Composite Group\n");
+				CAM_ERR(CAM_ISP, "No Free Composite Group");
 				return -ENODEV;
 			}
 			comp_grp_local = list_first_entry(
@@ -1087,7 +1122,7 @@
 				&rsrc_data->intra_client_mask);
 		} else {
 			if (list_empty(&ver2_bus_priv->free_comp_grp)) {
-				pr_err("No Free Composite Group\n");
+				CAM_ERR(CAM_ISP, "No Free Composite Group");
 				return -ENODEV;
 			}
 			comp_grp_local = list_first_entry(
@@ -1113,7 +1148,7 @@
 		/* Do not support runtime change in composite mask */
 		if (comp_grp_local->res_state ==
 			CAM_ISP_RESOURCE_STATE_STREAMING) {
-			pr_err("Invalid State %d Comp Grp %u\n",
+			CAM_ERR(CAM_ISP, "Invalid State %d Comp Grp %u",
 				comp_grp_local->res_state,
 				rsrc_data->comp_grp_type);
 			return -EBUSY;
@@ -1135,7 +1170,7 @@
 	int match_found = 0;
 
 	if (!in_comp_grp) {
-		pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
+		CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data);
 		return -EINVAL;
 	}
 
@@ -1154,7 +1189,7 @@
 	}
 
 	if (!match_found) {
-		pr_err("Could not find matching Comp Grp type %u\n",
+		CAM_ERR(CAM_ISP, "Could not find matching Comp Grp type %u",
 			in_rsrc_data->comp_grp_type);
 		return -ENODEV;
 	}
@@ -1192,8 +1227,9 @@
 	cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
 		rsrc_data->hw_regs->comp_mask);
 
-	CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
-	CDBG("composite_mask addr 0x%x\n",  rsrc_data->hw_regs->comp_mask);
+	CAM_DBG(CAM_ISP, "composite_mask is 0x%x", rsrc_data->composite_mask);
+	CAM_DBG(CAM_ISP, "composite_mask addr 0x%x",
+		rsrc_data->hw_regs->comp_mask);
 
 	if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
 		rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
@@ -1218,7 +1254,7 @@
 	}
 
 	/* Subscribe IRQ */
-	CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
+	CAM_DBG(CAM_ISP, "Subscribe COMP_GRP%d IRQ", rsrc_data->comp_grp_type);
 	comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
 		common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
 		bus_irq_reg_mask, comp_grp,
@@ -1226,7 +1262,7 @@
 		cam_ife_mgr_do_tasklet_buf_done,
 		comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
 	if (comp_grp->irq_handle < 0) {
-		pr_err("Subscribe IRQ failed for comp_grp %d\n",
+		CAM_ERR(CAM_ISP, "Subscribe IRQ failed for comp_grp %d",
 			rsrc_data->comp_grp_type);
 		return -EFAULT;
 	}
@@ -1283,18 +1319,19 @@
 
 	comp_grp = th_payload->handler_priv;
 	if (!comp_grp) {
-		pr_err_ratelimited("Error! No resource\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
 		return -ENODEV;
 	}
 
 	rsrc_data = comp_grp->res_priv;
 
-	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
-	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+	CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
+	CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
 
 	rc  = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
 	if (rc) {
-		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+			"No tasklet_cmd is free in queue\n");
 		return rc;
 	}
 
@@ -1309,7 +1346,7 @@
 
 	th_payload->evt_payload_priv = evt_payload;
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
 
@@ -1326,7 +1363,7 @@
 	uint32_t                               comp_err_reg;
 	uint32_t                               comp_grp_id;
 
-	CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
+	CAM_DBG(CAM_ISP, "comp grp type %d", rsrc_data->comp_grp_type);
 
 	if (!evt_payload)
 		return rc;
@@ -1369,7 +1406,7 @@
 			rc = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 
-		CDBG("status reg = 0x%x, bit index = %d rc %d\n",
+		CAM_DBG(CAM_ISP, "status reg = 0x%x, bit index = %d rc %d",
 			status_reg, (comp_grp_id + 5), rc);
 		break;
 
@@ -1411,7 +1448,7 @@
 		break;
 	default:
 		rc = CAM_VFE_IRQ_STATUS_ERR;
-		pr_err("Error! Invalid comp_grp_type %u\n",
+		CAM_ERR(CAM_ISP, "Error! Invalid comp_grp_type %u",
 			rsrc_data->comp_grp_type);
 		break;
 	}
@@ -1433,7 +1470,7 @@
 	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
 		GFP_KERNEL);
 	if (!rsrc_data) {
-		CDBG("Failed to alloc for comp_grp_priv\n");
+		CAM_DBG(CAM_ISP, "Failed to alloc for comp_grp_priv");
 		return -ENOMEM;
 	}
 	comp_grp->res_priv = rsrc_data;
@@ -1482,7 +1519,7 @@
 	comp_grp->res_priv = NULL;
 
 	if (!rsrc_data) {
-		pr_err("Error! comp_grp_priv is NULL\n");
+		CAM_ERR(CAM_ISP, "Error! comp_grp_priv is NULL");
 		return -ENODEV;
 	}
 	kfree(rsrc_data);
@@ -1507,14 +1544,14 @@
 	struct cam_vfe_bus_ver2_vfe_out_data   *rsrc_data = NULL;
 
 	if (!bus_priv || !acquire_args) {
-		pr_err("Invalid Param");
+		CAM_ERR(CAM_ISP, "Invalid Param");
 		return -EINVAL;
 	}
 
 	out_acquire_args = &acq_args->vfe_out;
 	format = out_acquire_args->out_port_info->format;
 
-	CDBG("Acquiring resource type 0x%x\n",
+	CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
 		out_acquire_args->out_port_info->res_type);
 
 	vfe_out_res_id = cam_vfe_bus_get_out_res_id(
@@ -1528,7 +1565,7 @@
 
 	rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
 	if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-		pr_err("Resource not available: Res_id %d state:%d\n",
+		CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
 			vfe_out_res_id, rsrc_node->res_state);
 		return -EBUSY;
 	}
@@ -1555,7 +1592,8 @@
 			out_acquire_args->dual_slave_core,
 			&rsrc_data->comp_grp);
 		if (rc) {
-			pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
+			CAM_ERR(CAM_ISP,
+				"VFE%d Comp_Grp acquire fail for Out %d rc=%d",
 				rsrc_data->common_data->core_index,
 				vfe_out_res_id, rc);
 			return rc;
@@ -1579,7 +1617,8 @@
 			&rsrc_data->wm_res[i],
 			&client_done_mask);
 		if (rc) {
-			pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
+			CAM_ERR(CAM_ISP,
+				"VFE%d WM acquire failed for Out %d rc=%d",
 				rsrc_data->common_data->core_index,
 				vfe_out_res_id, rc);
 			goto release_wm;
@@ -1593,7 +1632,7 @@
 	rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 	out_acquire_args->rsrc_node = rsrc_node;
 
-	CDBG("Acquire successful\n");
+	CAM_DBG(CAM_ISP, "Acquire successful");
 	return rc;
 
 release_wm:
@@ -1614,7 +1653,7 @@
 	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
 
 	if (!bus_priv || !release_args) {
-		pr_err("Invalid input bus_priv %pK release_args %pK\n",
+		CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
 			bus_priv, release_args);
 		return -EINVAL;
 	}
@@ -1623,7 +1662,7 @@
 	rsrc_data = vfe_out->res_priv;
 
 	if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
-		pr_err("Error! Invalid resource state:%d\n",
+		CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
 			vfe_out->res_state);
 	}
 
@@ -1653,17 +1692,17 @@
 	struct cam_vfe_bus_ver2_common_data   *common_data = NULL;
 
 	if (!vfe_out) {
-		pr_err("Invalid input\n");
+		CAM_ERR(CAM_ISP, "Invalid input");
 		return -EINVAL;
 	}
 
 	rsrc_data = vfe_out->res_priv;
 	common_data = rsrc_data->common_data;
 
-	CDBG("Start resource index %d\n", rsrc_data->out_type);
+	CAM_DBG(CAM_ISP, "Start resource index %d", rsrc_data->out_type);
 
 	if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
-		pr_err("Error! Invalid resource state:%d\n",
+		CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
 			vfe_out->res_state);
 		return -EACCES;
 	}
@@ -1707,7 +1746,7 @@
 	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
 
 	if (!vfe_out) {
-		pr_err("Invalid input\n");
+		CAM_ERR(CAM_ISP, "Invalid input");
 		return -EINVAL;
 	}
 
@@ -1770,7 +1809,7 @@
 	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
 		GFP_KERNEL);
 	if (!rsrc_data) {
-		CDBG("Error! Failed to alloc for vfe out priv\n");
+		CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe out priv");
 		rc = -ENOMEM;
 		return rc;
 	}
@@ -1813,7 +1852,7 @@
 	vfe_out->res_priv = NULL;
 
 	if (!rsrc_data) {
-		pr_err("Error! vfe out priv is NULL\n");
+		CAM_ERR(CAM_ISP, "Error! vfe out priv is NULL");
 		return -ENOMEM;
 	}
 	kfree(rsrc_data);
@@ -1827,7 +1866,7 @@
 	struct cam_vfe_bus_ver2_priv          *bus_priv;
 
 	bus_priv     = th_payload->handler_priv;
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 	return cam_irq_controller_handle_irq(evt_id,
 		bus_priv->common_data.bus_irq_controller);
 }
@@ -1856,12 +1895,13 @@
 		update_buf->cdm.res->res_priv;
 
 	if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
-		pr_err("Failed! Invalid data\n");
+		CAM_ERR(CAM_ISP, "Failed! Invalid data");
 		return -EINVAL;
 	}
 
 	if (update_buf->num_buf != vfe_out_data->num_wm) {
-		pr_err("Failed! Invalid number buffers:%d required:%d\n",
+		CAM_ERR(CAM_ISP,
+			"Failed! Invalid number buffers:%d required:%d",
 			update_buf->num_buf, vfe_out_data->num_wm);
 		return -EINVAL;
 	}
@@ -1871,7 +1911,8 @@
 
 	for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
 		if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
-			pr_err("reg_val_pair %d exceeds the array limit %lu\n",
+			CAM_ERR(CAM_ISP,
+				"reg_val_pair %d exceeds the array limit %lu",
 				j, MAX_REG_VAL_PAIR_SIZE);
 			return -ENOMEM;
 		}
@@ -1879,14 +1920,14 @@
 		wm_data = vfe_out_data->wm_res[i]->res_priv;
 
 		/* For initial configuration program all bus registers */
-		if (wm_data->stride != io_cfg->planes[i].plane_stride ||
-			!wm_data->init_cfg_done) {
+		if ((wm_data->stride != io_cfg->planes[i].plane_stride ||
+			!wm_data->init_cfg_done) && (wm_data->index >= 3)) {
 			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 				wm_data->hw_regs->stride,
 				io_cfg->planes[i].plane_stride);
 			wm_data->stride = io_cfg->planes[i].plane_stride;
 		}
-		CDBG("image stride 0x%x\n", wm_data->stride);
+		CAM_DBG(CAM_ISP, "image stride 0x%x", wm_data->stride);
 
 		if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
 			!wm_data->init_cfg_done) {
@@ -1895,7 +1936,8 @@
 				io_cfg->framedrop_pattern);
 			wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
 		}
-		CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
+		CAM_DBG(CAM_ISP, "framedrop pattern 0x%x",
+			wm_data->framedrop_pattern);
 
 		if (wm_data->framedrop_period != io_cfg->framedrop_period ||
 			!wm_data->init_cfg_done) {
@@ -1904,7 +1946,8 @@
 				io_cfg->framedrop_period);
 			wm_data->framedrop_period = io_cfg->framedrop_period;
 		}
-		CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
+		CAM_DBG(CAM_ISP, "framedrop period 0x%x",
+			wm_data->framedrop_period);
 
 		if (wm_data->irq_subsample_period != io_cfg->subsample_period
 			|| !wm_data->init_cfg_done) {
@@ -1914,7 +1957,7 @@
 			wm_data->irq_subsample_period =
 				io_cfg->subsample_period;
 		}
-		CDBG("irq subsample period 0x%x\n",
+		CAM_DBG(CAM_ISP, "irq subsample period 0x%x",
 			wm_data->irq_subsample_period);
 
 		if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
@@ -1925,13 +1968,13 @@
 			wm_data->irq_subsample_pattern =
 				io_cfg->subsample_pattern;
 		}
-		CDBG("irq subsample pattern 0x%x\n",
+		CAM_DBG(CAM_ISP, "irq subsample pattern 0x%x",
 			wm_data->irq_subsample_pattern);
 
 		if (wm_data->en_ubwc) {
 			if (!wm_data->hw_regs->ubwc_regs) {
-				pr_err("%s: No UBWC register to configure.\n",
-					__func__);
+				CAM_ERR(CAM_ISP,
+					"No UBWC register to configure.");
 				return -EINVAL;
 			}
 			if (wm_data->packer_cfg !=
@@ -1943,7 +1986,8 @@
 				wm_data->packer_cfg =
 					io_cfg->planes[i].packer_config;
 			}
-			CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
+			CAM_DBG(CAM_ISP, "packer cfg 0x%x",
+				wm_data->packer_cfg);
 
 			if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
 				|| !wm_data->init_cfg_done) {
@@ -1953,7 +1997,7 @@
 				wm_data->tile_cfg =
 					io_cfg->planes[i].tile_config;
 			}
-			CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
+			CAM_DBG(CAM_ISP, "tile cfg 0x%x", wm_data->tile_cfg);
 
 			if (wm_data->h_init != io_cfg->planes[i].h_init ||
 				!wm_data->init_cfg_done) {
@@ -1962,7 +2006,7 @@
 					io_cfg->planes[i].h_init);
 				wm_data->h_init = io_cfg->planes[i].h_init;
 			}
-			CDBG("h_init 0x%x\n", wm_data->h_init);
+			CAM_DBG(CAM_ISP, "h_init 0x%x", wm_data->h_init);
 
 			if (wm_data->v_init != io_cfg->planes[i].v_init ||
 				!wm_data->init_cfg_done) {
@@ -1971,7 +2015,7 @@
 					io_cfg->planes[i].v_init);
 				wm_data->v_init = io_cfg->planes[i].v_init;
 			}
-			CDBG("v_init 0x%x\n", wm_data->v_init);
+			CAM_DBG(CAM_ISP, "v_init 0x%x", wm_data->v_init);
 
 			if (wm_data->ubwc_meta_stride !=
 				io_cfg->planes[i].meta_stride ||
@@ -1983,7 +2027,8 @@
 				wm_data->ubwc_meta_stride =
 					io_cfg->planes[i].meta_stride;
 			}
-			CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
+			CAM_DBG(CAM_ISP, "meta stride 0x%x",
+				wm_data->ubwc_meta_stride);
 
 			if (wm_data->ubwc_mode_cfg !=
 				io_cfg->planes[i].mode_config ||
@@ -1994,7 +2039,8 @@
 				wm_data->ubwc_mode_cfg =
 					io_cfg->planes[i].mode_config;
 			}
-			CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
+			CAM_DBG(CAM_ISP, "ubwc mode cfg 0x%x",
+				wm_data->ubwc_mode_cfg);
 
 			if (wm_data->ubwc_meta_offset !=
 				io_cfg->planes[i].meta_offset ||
@@ -2006,14 +2052,14 @@
 				wm_data->ubwc_meta_offset =
 					io_cfg->planes[i].meta_offset;
 			}
-			CDBG("ubwc meta offset 0x%x\n",
+			CAM_DBG(CAM_ISP, "ubwc meta offset 0x%x",
 				wm_data->ubwc_meta_offset);
 
 			/* UBWC meta address */
 			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 				wm_data->hw_regs->ubwc_regs->meta_addr,
 				update_buf->image_buf[i]);
-			CDBG("ubwc meta addr 0x%llx\n",
+			CAM_DBG(CAM_ISP, "ubwc meta addr 0x%llx",
 				update_buf->image_buf[i]);
 		}
 
@@ -2028,7 +2074,7 @@
 				wm_data->hw_regs->image_addr,
 				update_buf->image_buf[i]);
 
-		CDBG("image address 0x%x\n", reg_val_pair[j-1]);
+		CAM_DBG(CAM_ISP, "image address 0x%x", reg_val_pair[j-1]);
 
 		frame_inc = io_cfg->planes[i].plane_stride *
 			io_cfg->planes[i].slice_height;
@@ -2049,7 +2095,8 @@
 
 	/* cdm util returns dwords, need to convert to bytes */
 	if ((size * 4) > update_buf->cdm.size) {
-		pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
+		CAM_ERR(CAM_ISP,
+			"Failed! Buf size:%d insufficient, expected size:%d",
 			update_buf->cdm.size, size);
 		return -ENOMEM;
 	}
@@ -2082,7 +2129,7 @@
 	uint32_t                         top_irq_reg_mask[2] = {0};
 
 	if (!bus_priv) {
-		pr_err("Error! Invalid args\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid args");
 		return -EINVAL;
 	}
 
@@ -2099,7 +2146,7 @@
 		NULL);
 
 	if (bus_priv->irq_handle <= 0) {
-		pr_err("Failed to subscribe BUS IRQ\n");
+		CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
 		return -EFAULT;
 	}
 
@@ -2113,7 +2160,7 @@
 	int                              rc;
 
 	if (!bus_priv || (bus_priv->irq_handle <= 0)) {
-		pr_err("Error! Invalid args\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid args");
 		return -EINVAL;
 	}
 
@@ -2121,7 +2168,7 @@
 		bus_priv->common_data.vfe_irq_controller,
 		bus_priv->irq_handle);
 	if (rc)
-		pr_err("Failed to unsubscribe irq rc=%d\n", rc);
+		CAM_ERR(CAM_ISP, "Failed to unsubscribe irq rc=%d", rc);
 
 	return rc;
 }
@@ -2132,7 +2179,7 @@
 	int rc = -EINVAL;
 
 	if (!priv || !cmd_args) {
-		pr_err_ratelimited("Error! Invalid input arguments\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! Invalid input arguments\n");
 		return -EINVAL;
 	}
 
@@ -2141,7 +2188,7 @@
 		rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
 		break;
 	default:
-		pr_err_ratelimited("Error! Invalid camif process command:%d\n",
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Inval camif process command:%d\n",
 			cmd_type);
 		break;
 	}
@@ -2161,18 +2208,20 @@
 	struct cam_vfe_bus              *vfe_bus_local;
 	struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
 
-	CDBG("Enter\n");
+	CAM_DBG(CAM_ISP, "Enter");
 
 	if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
-		pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
-			soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
+		CAM_ERR(CAM_ISP,
+			"Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
+			soc_info, hw_intf, bus_hw_info);
+		CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
 		rc = -EINVAL;
 		goto end;
 	}
 
 	vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
 	if (!vfe_bus_local) {
-		CDBG("Failed to alloc for vfe_bus\n");
+		CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
 		rc = -ENOMEM;
 		goto end;
 	}
@@ -2180,7 +2229,7 @@
 	bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
 		GFP_KERNEL);
 	if (!bus_priv) {
-		CDBG("Failed to alloc for vfe_bus_priv\n");
+		CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
 		rc = -ENOMEM;
 		goto free_bus_local;
 	}
@@ -2197,7 +2246,7 @@
 		&ver2_hw_info->common_reg.irq_reg_info,
 		&bus_priv->common_data.bus_irq_controller);
 	if (rc) {
-		pr_err("Error! cam_irq_controller_init failed\n");
+		CAM_ERR(CAM_ISP, "Error! cam_irq_controller_init failed");
 		goto free_bus_priv;
 	}
 
@@ -2209,7 +2258,7 @@
 		rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
 			&bus_priv->bus_client[i]);
 		if (rc < 0) {
-			pr_err("Error! Init WM failed rc=%d\n", rc);
+			CAM_ERR(CAM_ISP, "Error! Init WM failed rc=%d", rc);
 			goto deinit_wm;
 		}
 	}
@@ -2218,7 +2267,7 @@
 		rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
 			&bus_priv->comp_grp[i]);
 		if (rc < 0) {
-			pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
+			CAM_ERR(CAM_ISP, "Init Comp Grp failed rc=%d", rc);
 			goto deinit_comp_grp;
 		}
 	}
@@ -2227,7 +2276,7 @@
 		rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
 			&bus_priv->vfe_out[i]);
 		if (rc < 0) {
-			pr_err("Error! Init VFE Out failed rc=%d\n", rc);
+			CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
 			goto deinit_vfe_out;
 		}
 	}
@@ -2251,7 +2300,7 @@
 
 	*vfe_bus = vfe_bus_local;
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 
 deinit_vfe_out:
@@ -2290,14 +2339,14 @@
 	struct cam_vfe_bus              *vfe_bus_local;
 
 	if (!vfe_bus || !*vfe_bus) {
-		pr_err("Error! Invalid input\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input");
 		return -EINVAL;
 	}
 	vfe_bus_local = *vfe_bus;
 
 	bus_priv = vfe_bus_local->bus_priv;
 	if (!bus_priv) {
-		pr_err("Error! bus_priv is NULL\n");
+		CAM_ERR(CAM_ISP, "Error! bus_priv is NULL");
 		rc = -ENODEV;
 		goto free_bus_local;
 	}
@@ -2309,19 +2358,22 @@
 	for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
 		rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
 		if (rc < 0)
-			pr_err("Error! Deinit WM failed rc=%d\n", rc);
+			CAM_ERR(CAM_ISP,
+				"Error! Deinit WM failed rc=%d", rc);
 	}
 
 	for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
 		rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
 		if (rc < 0)
-			pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
+			CAM_ERR(CAM_ISP,
+				"Error! Deinit Comp Grp failed rc=%d", rc);
 	}
 
 	for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
 		rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
 		if (rc < 0)
-			pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
+			CAM_ERR(CAM_ISP,
+				"Error! Deinit VFE Out failed rc=%d", rc);
 	}
 
 	INIT_LIST_HEAD(&bus_priv->free_comp_grp);
@@ -2331,7 +2383,8 @@
 	rc = cam_irq_controller_deinit(
 		&bus_priv->common_data.bus_irq_controller);
 	if (rc)
-		pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
+		CAM_ERR(CAM_ISP,
+			"Error! Deinit IRQ Controller failed rc=%d", rc);
 
 	kfree(vfe_bus_local->bus_priv);
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index fa00769..e70ecc5 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -10,9 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
-#include <linux/slab.h>
+ #include <linux/slab.h>
 #include <uapi/media/cam_isp.h>
 #include "cam_io_util.h"
 #include "cam_isp_hw_mgr_intf.h"
@@ -20,9 +18,7 @@
 #include "cam_vfe_top.h"
 #include "cam_vfe_top_ver2.h"
 #include "cam_vfe_camif_ver2.h"
-
-#undef  CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 struct cam_vfe_mux_camif_data {
 	void __iomem                                *mem_base;
@@ -55,7 +51,7 @@
 		rc = 0;
 		break;
 	default:
-		pr_err("Error! Invalid pix pattern:%d\n", pattern);
+		CAM_ERR(CAM_ISP, "Error! Invalid pix pattern:%d", pattern);
 		rc = -EINVAL;
 		break;
 	}
@@ -96,12 +92,12 @@
 	uint32_t                             val = 0;
 
 	if (!camif_res) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
 	if (camif_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
-		pr_err("Error! Invalid camif res res_state:%d\n",
+		CAM_ERR(CAM_ISP, "Error! Invalid camif res res_state:%d",
 			camif_res->res_state);
 		return -EINVAL;
 	}
@@ -129,7 +125,7 @@
 	/* Reg Update */
 	cam_io_w_mb(0x1, rsrc_data->mem_base + 0x4AC);
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 	return 0;
 }
 
@@ -142,7 +138,7 @@
 	int rc = 0;
 
 	if (!camif_res) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -188,26 +184,26 @@
 	payload = evt_payload_priv;
 	irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0];
 
-	CDBG("event ID:%d\n", payload->evt_id);
-	CDBG("irq_status_0 = %x\n", irq_status0);
+	CAM_DBG(CAM_ISP, "event ID:%d", payload->evt_id);
+	CAM_DBG(CAM_ISP, "irq_status_0 = %x", irq_status0);
 
 	switch (payload->evt_id) {
 	case CAM_ISP_HW_EVENT_SOF:
 		if (irq_status0 & camif_priv->reg_data->sof_irq_mask) {
-			CDBG("Received SOF\n");
+			CAM_DBG(CAM_ISP, "Received SOF");
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 		break;
 	case CAM_ISP_HW_EVENT_EPOCH:
 		if (irq_status0 & camif_priv->reg_data->epoch0_irq_mask) {
-			CDBG("Received EPOCH\n");
+			CAM_DBG(CAM_ISP, "Received EPOCH");
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 		cam_vfe_put_evt_payload(payload->core_info, &payload);
 		break;
 	case CAM_ISP_HW_EVENT_REG_UPDATE:
 		if (irq_status0 & camif_priv->reg_data->reg_update_irq_mask) {
-			CDBG("Received REG_UPDATE_ACK\n");
+			CAM_DBG(CAM_ISP, "Received REG_UPDATE_ACK");
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 		break;
@@ -215,7 +211,7 @@
 		break;
 	}
 
-	CDBG("returing status = %d\n", ret);
+	CAM_DBG(CAM_ISP, "returing status = %d", ret);
 	return ret;
 }
 
@@ -231,7 +227,7 @@
 	camif_priv = kzalloc(sizeof(struct cam_vfe_mux_camif_data),
 		GFP_KERNEL);
 	if (!camif_priv) {
-		CDBG("Error! Failed to alloc for camif_priv\n");
+		CAM_DBG(CAM_ISP, "Error! Failed to alloc for camif_priv");
 		return -ENOMEM;
 	}
 
@@ -264,7 +260,7 @@
 	camif_node->res_priv = NULL;
 
 	if (!camif_priv) {
-		pr_err("Error! camif_priv is NULL\n");
+		CAM_ERR(CAM_ISP, "Error! camif_priv is NULL");
 		return -ENODEV;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
index f96f4d9..df7b0f9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
@@ -10,21 +10,19 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/slab.h>
 #include "cam_vfe_rdi.h"
 #include "cam_isp_hw_mgr_intf.h"
 #include "cam_vfe_hw_intf.h"
 #include "cam_io_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 struct cam_vfe_mux_rdi_data {
 	void __iomem                                *mem_base;
 	struct cam_hw_intf                          *hw_intf;
 	struct cam_vfe_top_ver2_reg_offset_common   *common_reg;
+	struct cam_vfe_rdi_ver2_reg                 *rdi_reg;
+	struct cam_vfe_rdi_reg_data                 *reg_data;
 
 	enum cam_isp_hw_sync_mode          sync_mode;
 };
@@ -51,12 +49,12 @@
 	int                            rc = 0;
 
 	if (!rdi_res) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
 	if (rdi_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
-		pr_err("Error! Invalid rdi res res_state:%d\n",
+		CAM_ERR(CAM_ISP, "Error! Invalid rdi res res_state:%d",
 			rdi_res->res_state);
 		return -EINVAL;
 	}
@@ -67,7 +65,7 @@
 	/* Reg Update */
 	cam_io_w_mb(0x2, rsrc_data->mem_base + 0x4AC);
 
-	CDBG("Exit\n");
+	CAM_DBG(CAM_ISP, "Exit");
 
 	return rc;
 }
@@ -80,7 +78,7 @@
 	int rc = 0;
 
 	if (!rdi_res) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -103,13 +101,14 @@
 	int rc = -EINVAL;
 
 	if (!priv || !cmd_args) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
 	switch (cmd_type) {
 	default:
-		pr_err("Error! unsupported RDI process command:%d\n", cmd_type);
+		CAM_ERR(CAM_ISP,
+			"unsupported RDI process command:%d", cmd_type);
 		break;
 	}
 
@@ -139,23 +138,28 @@
 	payload = evt_payload_priv;
 	irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0];
 
-	CDBG("event ID:%d\n", payload->evt_id);
-	CDBG("irq_status_0 = %x\n", irq_status0);
+	CAM_DBG(CAM_ISP, "event ID:%d", payload->evt_id);
+	CAM_DBG(CAM_ISP, "irq_status_0 = %x", irq_status0);
 
 	switch (payload->evt_id) {
 	case CAM_ISP_HW_EVENT_SOF:
-		if (irq_status0 & 0x8000000)
+		if (irq_status0 & rdi_priv->reg_data->sof_irq_mask) {
+			CAM_DBG(CAM_ISP, "Received SOF");
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
 		break;
 	case CAM_ISP_HW_EVENT_REG_UPDATE:
-		if (irq_status0 & 0x20)
+		if (irq_status0 & rdi_priv->reg_data->reg_update_irq_mask) {
+			CAM_DBG(CAM_ISP, "Received REG UPDATE");
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
+		cam_vfe_put_evt_payload(payload->core_info, &payload);
 		break;
 	default:
 		break;
 	}
 
-	CDBG("returing status = %d\n", ret);
+	CAM_DBG(CAM_ISP, "returing status = %d", ret);
 	return ret;
 }
 
@@ -166,11 +170,12 @@
 	struct cam_isp_resource_node  *rdi_node)
 {
 	struct cam_vfe_mux_rdi_data     *rdi_priv = NULL;
+	struct cam_vfe_rdi_ver2_hw_info *rdi_info = rdi_hw_info;
 
 	rdi_priv = kzalloc(sizeof(struct cam_vfe_mux_rdi_data),
 			GFP_KERNEL);
 	if (!rdi_priv) {
-		CDBG("Error! Failed to alloc for rdi_priv\n");
+		CAM_DBG(CAM_ISP, "Error! Failed to alloc for rdi_priv");
 		return -ENOMEM;
 	}
 
@@ -178,6 +183,31 @@
 
 	rdi_priv->mem_base   = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base;
 	rdi_priv->hw_intf    = hw_intf;
+	rdi_priv->common_reg = rdi_info->common_reg;
+	rdi_priv->rdi_reg    = rdi_info->rdi_reg;
+
+	switch (rdi_node->res_id) {
+	case CAM_ISP_HW_VFE_IN_RDI0:
+		rdi_priv->reg_data = rdi_info->reg_data[0];
+		break;
+	case CAM_ISP_HW_VFE_IN_RDI1:
+		rdi_priv->reg_data = rdi_info->reg_data[1];
+		break;
+	case CAM_ISP_HW_VFE_IN_RDI2:
+		rdi_priv->reg_data = rdi_info->reg_data[2];
+		break;
+	case CAM_ISP_HW_VFE_IN_RDI3:
+		if (rdi_info->reg_data[3]) {
+			rdi_priv->reg_data = rdi_info->reg_data[3];
+		} else {
+			CAM_ERR(CAM_ISP, "Error! RDI3 is not supported");
+			goto err_init;
+		}
+		break;
+	default:
+		CAM_DBG(CAM_ISP, "invalid Resource id:%d", rdi_node->res_id);
+		goto err_init;
+	}
 
 	rdi_node->start = cam_vfe_rdi_resource_start;
 	rdi_node->stop  = cam_vfe_rdi_resource_stop;
@@ -185,6 +215,9 @@
 	rdi_node->bottom_half_handler = cam_vfe_rdi_handle_irq_bottom_half;
 
 	return 0;
+err_init:
+	kfree(rdi_priv);
+	return -EINVAL;
 }
 
 int cam_vfe_rdi_ver2_deinit(
@@ -200,7 +233,7 @@
 	rdi_node->res_priv = NULL;
 
 	if (!rdi_priv) {
-		pr_err("Error! rdi_priv NULL\n");
+		CAM_ERR(CAM_ISP, "Error! rdi_priv NULL");
 		return -ENODEV;
 	}
 	kfree(rdi_priv);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
index 9893474..04e4f02 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
@@ -16,18 +16,22 @@
 #include "cam_isp_hw.h"
 #include "cam_vfe_top.h"
 
+#define CAM_VFE_RDI_VER2_MAX  4
+
 struct cam_vfe_rdi_ver2_reg {
 	uint32_t     reg_update_cmd;
 };
 
 struct cam_vfe_rdi_reg_data {
+	uint32_t     reg_update_cmd_data;
+	uint32_t     sof_irq_mask;
 	uint32_t     reg_update_irq_mask;
 };
 
 struct cam_vfe_rdi_ver2_hw_info {
-	struct cam_vfe_top_ver2_reg_offset_common   *common_reg;
-	struct cam_vfe_rdi_ver2_reg               *rdi_reg;
-	struct cam_vfe_rdi_reg_data               *reg_data;
+	struct cam_vfe_top_ver2_reg_offset_common  *common_reg;
+	struct cam_vfe_rdi_ver2_reg                *rdi_reg;
+	struct cam_vfe_rdi_reg_data  *reg_data[CAM_VFE_RDI_VER2_MAX];
 };
 
 int cam_vfe_rdi_ver2_acquire_resource(
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c
index ee608fa..8eb1835 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c
@@ -10,10 +10,9 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include "cam_vfe_top.h"
 #include "cam_vfe_top_ver2.h"
+#include "cam_debug_util.h"
 
 int cam_vfe_top_init(uint32_t          top_version,
 	struct cam_hw_soc_info        *soc_info,
@@ -29,7 +28,7 @@
 			vfe_top);
 		break;
 	default:
-		pr_err("Error! Unsupported Version %x\n", top_version);
+		CAM_ERR(CAM_ISP, "Error! Unsupported Version %x", top_version);
 		break;
 	}
 
@@ -46,7 +45,7 @@
 		rc = cam_vfe_top_ver2_deinit(vfe_top);
 		break;
 	default:
-		pr_err("Error! Unsupported Version %x\n", top_version);
+		CAM_ERR(CAM_ISP, "Error! Unsupported Version %x", top_version);
 		break;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index ce7c63e..1a3eeae 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -10,17 +10,13 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/slab.h>
 #include "cam_io_util.h"
 #include "cam_cdm_util.h"
 #include "cam_vfe_hw_intf.h"
 #include "cam_vfe_top.h"
 #include "cam_vfe_top_ver2.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 struct cam_vfe_top_ver2_common_data {
 	struct cam_hw_soc_info                     *soc_info;
@@ -43,13 +39,13 @@
 	struct cam_cdm_utils_ops         *cdm_util_ops = NULL;
 
 	if (arg_size != sizeof(struct cam_isp_hw_get_cdm_args)) {
-		pr_err("Error! Invalid cmd size\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid cmd size");
 		return -EINVAL;
 	}
 
 	if (!cdm_args || !cdm_args->res || !top_priv ||
 		!top_priv->common_data.soc_info) {
-		pr_err("Error! Invalid args\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid args");
 		return -EINVAL;
 	}
 
@@ -57,22 +53,22 @@
 		(struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops;
 
 	if (!cdm_util_ops) {
-		pr_err("Invalid CDM ops\n");
+		CAM_ERR(CAM_ISP, "Invalid CDM ops");
 		return -EINVAL;
 	}
 
 	size = cdm_util_ops->cdm_required_size_changebase();
 	/* since cdm returns dwords, we need to convert it into bytes */
 	if ((size * 4) > cdm_args->size) {
-		pr_err("buf size:%d is not sufficient, expected: %d\n",
+		CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
 			cdm_args->size, size);
 		return -EINVAL;
 	}
 
 	mem_base = CAM_SOC_GET_REG_MAP_CAM_BASE(
 		top_priv->common_data.soc_info, VFE_CORE_BASE_IDX);
-	CDBG("core %d mem_base 0x%x\n", top_priv->common_data.soc_info->index,
-		mem_base);
+	CAM_DBG(CAM_ISP, "core %d mem_base 0x%x",
+		top_priv->common_data.soc_info->index, mem_base);
 
 	cdm_util_ops->cdm_write_changebase(cdm_args->cmd_buf_addr, mem_base);
 	cdm_args->used_bytes = (size * 4);
@@ -90,26 +86,26 @@
 	struct cam_cdm_utils_ops         *cdm_util_ops = NULL;
 
 	if (arg_size != sizeof(struct cam_isp_hw_get_cdm_args)) {
-		pr_err("Error! Invalid cmd size\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid cmd size");
 		return -EINVAL;
 	}
 
 	if (!cdm_args || !cdm_args->res) {
-		pr_err("Error! Invalid args\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid args");
 		return -EINVAL;
 	}
 
 	cdm_util_ops = (struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops;
 
 	if (!cdm_util_ops) {
-		pr_err("Error! Invalid CDM ops\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid CDM ops");
 		return -EINVAL;
 	}
 
 	size = cdm_util_ops->cdm_required_size_reg_random(1);
 	/* since cdm returns dwords, we need to convert it into bytes */
 	if ((size * 4) > cdm_args->size) {
-		pr_err("Error! buf size:%d is not sufficient, expected: %d\n",
+		CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
 			cdm_args->size, size);
 		return -EINVAL;
 	}
@@ -153,7 +149,7 @@
 	struct cam_vfe_top_ver2_reg_offset_common *reg_common = NULL;
 
 	if (!top_priv) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
@@ -169,7 +165,7 @@
 		CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX) +
 		reg_common->global_reset_cmd);
 
-	CDBG("Reset HW exit\n");
+	CAM_DBG(CAM_ISP, "Reset HW exit");
 	return 0;
 }
 
@@ -183,7 +179,7 @@
 	int rc = -EINVAL;
 
 	if (!device_priv || !reserve_args) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -228,16 +224,16 @@
 	struct cam_isp_resource_node            *mux_res;
 
 	if (!device_priv || !release_args) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
 	top_priv = (struct cam_vfe_top_ver2_priv   *)device_priv;
 	mux_res = (struct cam_isp_resource_node *)release_args;
 
-	CDBG("%s: Resource in state %d\n", __func__, mux_res->res_state);
+	CAM_DBG(CAM_ISP, "Resource in state %d", mux_res->res_state);
 	if (mux_res->res_state < CAM_ISP_RESOURCE_STATE_RESERVED) {
-		pr_err("Error! Resource in Invalid res_state :%d\n",
+		CAM_ERR(CAM_ISP, "Error! Resource in Invalid res_state :%d",
 			mux_res->res_state);
 		return -EINVAL;
 	}
@@ -254,7 +250,7 @@
 	int rc = 0;
 
 	if (!device_priv || !start_args) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -268,7 +264,7 @@
 		mux_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 		rc = 0;
 	} else {
-		pr_err("Invalid res id:%d\n", mux_res->res_id);
+		CAM_ERR(CAM_ISP, "Invalid res id:%d", mux_res->res_id);
 		rc = -EINVAL;
 	}
 
@@ -283,7 +279,7 @@
 	int rc = 0;
 
 	if (!device_priv || !stop_args) {
-		pr_err("Error! Invalid input arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
 		return -EINVAL;
 	}
 
@@ -295,7 +291,7 @@
 		mux_res->res_id <= CAM_ISP_HW_VFE_IN_RDI3)) {
 		rc = mux_res->stop(mux_res);
 	} else {
-		pr_err("Invalid res id:%d\n", mux_res->res_id);
+		CAM_ERR(CAM_ISP, "Invalid res id:%d", mux_res->res_id);
 		rc = -EINVAL;
 	}
 
@@ -322,7 +318,7 @@
 	struct cam_vfe_top_ver2_priv            *top_priv;
 
 	if (!device_priv || !cmd_args) {
-		pr_err("Error! Invalid arguments\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid arguments");
 		return -EINVAL;
 	}
 	top_priv = (struct cam_vfe_top_ver2_priv *)device_priv;
@@ -337,7 +333,7 @@
 		break;
 	default:
 		rc = -EINVAL;
-		pr_err("Error! Invalid cmd:%d\n", cmd_type);
+		CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);
 		break;
 	}
 
@@ -357,7 +353,7 @@
 
 	vfe_top = kzalloc(sizeof(struct cam_vfe_top), GFP_KERNEL);
 	if (!vfe_top) {
-		CDBG("Error! Failed to alloc for vfe_top\n");
+		CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe_top");
 		rc = -ENOMEM;
 		goto end;
 	}
@@ -365,7 +361,7 @@
 	top_priv = kzalloc(sizeof(struct cam_vfe_top_ver2_priv),
 		GFP_KERNEL);
 	if (!top_priv) {
-		CDBG("Error! Failed to alloc for vfe_top_priv\n");
+		CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe_top_priv");
 		rc = -ENOMEM;
 		goto free_vfe_top;
 	}
@@ -391,7 +387,8 @@
 				CAM_ISP_HW_VFE_IN_RDI0 + j++;
 
 			rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info,
-				NULL, &top_priv->mux_rsrc[i]);
+				&ver2_hw_info->rdi_hw_info,
+				&top_priv->mux_rsrc[i]);
 			if (rc)
 				goto deinit_resources;
 		}
@@ -419,10 +416,10 @@
 	for (--i; i >= 0; i--) {
 		if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
 			if (cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]))
-				pr_err("Camif Deinit failed\n");
+				CAM_ERR(CAM_ISP, "Camif Deinit failed");
 		} else {
 			if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]))
-				pr_err("RDI Deinit failed\n");
+				CAM_ERR(CAM_ISP, "RDI Deinit failed");
 		}
 		top_priv->mux_rsrc[i].res_state =
 			CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
@@ -442,19 +439,19 @@
 	struct cam_vfe_top                     *vfe_top;
 
 	if (!vfe_top_ptr) {
-		pr_err("Error! Invalid input\n");
+		CAM_ERR(CAM_ISP, "Error! Invalid input");
 		return -EINVAL;
 	}
 
 	vfe_top = *vfe_top_ptr;
 	if (!vfe_top) {
-		pr_err("Error! vfe_top NULL\n");
+		CAM_ERR(CAM_ISP, "Error! vfe_top NULL");
 		return -ENODEV;
 	}
 
 	top_priv = vfe_top->top_priv;
 	if (!top_priv) {
-		pr_err("Error! vfe_top_priv NULL\n");
+		CAM_ERR(CAM_ISP, "Error! vfe_top_priv NULL");
 		rc = -ENODEV;
 		goto free_vfe_top;
 	}
@@ -466,12 +463,12 @@
 			CAM_ISP_HW_VFE_IN_CAMIF) {
 			rc = cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]);
 			if (rc)
-				pr_err("Error! Camif deinit failed rc=%d\n",
+				CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d",
 					rc);
 		} else {
 			rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]);
 			if (rc)
-				pr_err("Error! RDI deinit failed rc=%d\n", rc);
+				CAM_ERR(CAM_ISP, "RDI deinit failed rc=%d", rc);
 		}
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
index 0813202..bafd7f2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
@@ -52,6 +52,7 @@
 struct cam_vfe_top_ver2_hw_info {
 	struct cam_vfe_top_ver2_reg_offset_common  *common_reg;
 	struct cam_vfe_camif_ver2_hw_info  camif_hw_info;
+	struct cam_vfe_rdi_ver2_hw_info    rdi_hw_info;
 	uint32_t mux_type[CAM_VFE_TOP_VER2_MUX_MAX];
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/Makefile
new file mode 100644
index 0000000..4d272d3
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_hw/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_dev.o cam_jpeg_context.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
new file mode 100644
index 0000000..a299179
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2017, 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/debugfs.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "cam_mem_mgr.h"
+#include "cam_sync_api.h"
+#include "cam_jpeg_context.h"
+#include "cam_context_utils.h"
+#include "cam_debug_util.h"
+
+static int __cam_jpeg_ctx_acquire_dev_in_available(struct cam_context *ctx,
+	struct cam_acquire_dev_cmd *cmd)
+{
+	int rc;
+
+	rc = cam_context_acquire_dev_to_hw(ctx, cmd);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Unable to Acquire device %d", rc);
+	else
+		ctx->state = CAM_CTX_ACQUIRED;
+
+	return rc;
+}
+
+static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx,
+	struct cam_release_dev_cmd *cmd)
+{
+	int rc;
+
+	rc = cam_context_release_dev_to_hw(ctx, cmd);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Unable to release device %d", rc);
+
+	ctx->state = CAM_CTX_AVAILABLE;
+
+	return rc;
+}
+
+static int __cam_jpeg_ctx_config_dev_in_acquired(struct cam_context *ctx,
+	struct cam_config_dev_cmd *cmd)
+{
+	return cam_context_prepare_dev_to_hw(ctx, cmd);
+}
+
+static int __cam_jpeg_ctx_handle_buf_done_in_acquired(void *ctx,
+	uint32_t evt_id, void *done)
+{
+	return cam_context_buf_done_from_hw(ctx, done, evt_id);
+}
+
+/* top state machine */
+static struct cam_ctx_ops
+	cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = {
+	/* Uninit */
+	{
+		.ioctl_ops = { },
+		.crm_ops = { },
+		.irq_ops = NULL,
+	},
+	/* Available */
+	{
+		.ioctl_ops = {
+			.acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available,
+		},
+		.crm_ops = { },
+		.irq_ops = NULL,
+	},
+	/* Acquired */
+	{
+		.ioctl_ops = {
+			.release_dev = __cam_jpeg_ctx_release_dev_in_acquired,
+			.config_dev = __cam_jpeg_ctx_config_dev_in_acquired,
+		},
+		.crm_ops = { },
+		.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
+	},
+};
+
+int cam_jpeg_context_init(struct cam_jpeg_context *ctx,
+	struct cam_context *ctx_base,
+	struct cam_hw_mgr_intf *hw_intf)
+{
+	int rc;
+	int i;
+
+	if (!ctx || !ctx_base) {
+		CAM_ERR(CAM_JPEG, "Invalid Context");
+		rc = -EFAULT;
+		goto err;
+	}
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->base = ctx_base;
+
+	for (i = 0; i < CAM_CTX_REQ_MAX; i++)
+		ctx->req_base[i].req_priv = ctx;
+
+	rc = cam_context_init(ctx_base, NULL, hw_intf, ctx->req_base,
+		CAM_CTX_REQ_MAX);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Camera Context Base init failed");
+		goto err;
+	}
+
+	ctx_base->state_machine = cam_jpeg_ctx_state_machine;
+	ctx_base->ctx_priv = ctx;
+
+err:
+	return rc;
+}
+
+int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx)
+{
+	if (!ctx || !ctx->base) {
+		CAM_ERR(CAM_JPEG, "Invalid params: %pK", ctx);
+		return -EINVAL;
+	}
+
+	cam_context_deinit(ctx->base);
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	return 0;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.h b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.h
new file mode 100644
index 0000000..90ac5cf
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.h
@@ -0,0 +1,72 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_CONTEXT_H_
+#define _CAM_JPEG_CONTEXT_H_
+
+#include <uapi/media/cam_jpeg.h>
+
+#include "cam_context.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+
+#define CAM_JPEG_HW_EVENT_MAX 20
+
+/**
+ * struct cam_jpeg_context - Jpeg context
+ * @base: Base jpeg cam context object
+ * @req_base: Common request structure
+ */
+struct cam_jpeg_context {
+	struct cam_context *base;
+	struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
+};
+
+/* cam jpeg context irq handling function type */
+typedef int (*cam_jpeg_hw_event_cb_func)(
+	struct cam_jpeg_context *ctx_jpeg,
+	void *evt_data);
+
+/**
+ * struct cam_jpeg_ctx_irq_ops - Function table for handling IRQ callbacks
+ *
+ * @irq_ops: Array of handle function pointers.
+ *
+ */
+struct cam_jpeg_ctx_irq_ops {
+	cam_jpeg_hw_event_cb_func irq_ops[CAM_JPEG_HW_EVENT_MAX];
+};
+
+/**
+ * cam_jpeg_context_init()
+ *
+ * @brief: Initialization function for the JPEG context
+ *
+ * @ctx: JPEG context obj to be initialized
+ * @ctx_base: Context base from cam_context
+ * @hw_intf: JPEG hw manager interface
+ *
+ */
+int cam_jpeg_context_init(struct cam_jpeg_context *ctx,
+	struct cam_context *ctx_base,
+	struct cam_hw_mgr_intf *hw_intf);
+
+/**
+ * cam_jpeg_context_deinit()
+ *
+ * @brief: Deinitialize function for the JPEG context
+ *
+ * @ctx: JPEG context obj to be deinitialized
+ *
+ */
+int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx);
+
+#endif  /* __CAM_JPEG_CONTEXT_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
new file mode 100644
index 0000000..fb68ddb
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
@@ -0,0 +1,136 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/module.h>
+#include <linux/ion.h>
+#include <linux/kernel.h>
+
+#include "cam_node.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_jpeg_dev.h"
+#include "cam_debug_util.h"
+
+#define CAM_JPEG_DEV_NAME "cam-jpeg"
+
+static struct cam_jpeg_dev g_jpeg_dev;
+
+static const struct of_device_id cam_jpeg_dt_match[] = {
+	{
+		.compatible = "qcom,cam-jpeg"
+	},
+	{ }
+};
+
+static int cam_jpeg_dev_remove(struct platform_device *pdev)
+{
+	int rc;
+	int i;
+
+	for (i = 0; i < CAM_CTX_MAX; i++) {
+		rc = cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]);
+		if (rc)
+			CAM_ERR(CAM_JPEG, "JPEG context %d deinit failed %d",
+				i, rc);
+	}
+
+	rc = cam_subdev_remove(&g_jpeg_dev.sd);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Unregister failed %d", rc);
+
+	return rc;
+}
+
+static int cam_jpeg_dev_probe(struct platform_device *pdev)
+{
+	int rc;
+	int i;
+	struct cam_hw_mgr_intf hw_mgr_intf;
+	struct cam_node *node;
+
+	rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME,
+		CAM_JPEG_DEVICE_TYPE);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "JPEG cam_subdev_probe failed %d", rc);
+		goto err;
+	}
+	node = (struct cam_node *)g_jpeg_dev.sd.token;
+
+	rc = cam_jpeg_hw_mgr_init(pdev->dev.of_node,
+		(uint64_t *)&hw_mgr_intf);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Can not initialize JPEG HWmanager %d", rc);
+		goto unregister;
+	}
+
+	for (i = 0; i < CAM_CTX_MAX; i++) {
+		rc = cam_jpeg_context_init(&g_jpeg_dev.ctx_jpeg[i],
+			&g_jpeg_dev.ctx[i],
+			&node->hw_mgr_intf);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "JPEG context init failed %d %d",
+				i, rc);
+			goto ctx_init_fail;
+		}
+	}
+
+	rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_CTX_MAX,
+		CAM_JPEG_DEV_NAME);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "JPEG node init failed %d", rc);
+		goto ctx_init_fail;
+	}
+
+	mutex_init(&g_jpeg_dev.jpeg_mutex);
+
+	CAM_INFO(CAM_JPEG, "Camera JPEG probe complete");
+
+	return rc;
+
+ctx_init_fail:
+	for (--i; i >= 0; i--)
+		if (cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]))
+			CAM_ERR(CAM_JPEG, "deinit fail %d %d", i, rc);
+unregister:
+	if (cam_subdev_remove(&g_jpeg_dev.sd))
+		CAM_ERR(CAM_JPEG, "remove fail %d", rc);
+err:
+	return rc;
+}
+
+static struct platform_driver jpeg_driver = {
+	.probe = cam_jpeg_dev_probe,
+	.remove = cam_jpeg_dev_remove,
+	.driver = {
+		.name = "cam_jpeg",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_jpeg_dt_match,
+	},
+};
+
+static int __init cam_jpeg_dev_init_module(void)
+{
+	return platform_driver_register(&jpeg_driver);
+}
+
+static void __exit cam_jpeg_dev_exit_module(void)
+{
+	platform_driver_unregister(&jpeg_driver);
+}
+
+module_init(cam_jpeg_dev_init_module);
+module_exit(cam_jpeg_dev_exit_module);
+MODULE_DESCRIPTION("MSM JPEG driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
new file mode 100644
index 0000000..deab2d5
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_DEV_H_
+#define _CAM_JPEG_DEV_H_
+
+#include "cam_subdev.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_context.h"
+#include "cam_jpeg_context.h"
+
+/**
+ * struct cam_jpeg_dev - Camera JPEG V4l2 device node
+ *
+ * @sd: Commone camera subdevice node
+ * @node: Pointer to jpeg subdevice
+ * @ctx: JPEG base context storage
+ * @ctx_jpeg: JPEG private context storage
+ * @jpeg_mutex: Jpeg dev mutex
+ */
+struct cam_jpeg_dev {
+	struct cam_subdev sd;
+	struct cam_node *node;
+	struct cam_context ctx[CAM_CTX_MAX];
+	struct cam_jpeg_context ctx_jpeg[CAM_CTX_MAX];
+	struct mutex jpeg_mutex;
+};
+#endif /* __CAM_JPEG_DEV_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/Makefile
new file mode 100644
index 0000000..08c9528
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/Makefile
@@ -0,0 +1,13 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cdm/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_hw/
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_hw/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_hw_mgr.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
new file mode 100644
index 0000000..b06b5c4
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -0,0 +1,1178 @@
+/* Copyright (c) 2017, 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/uaccess.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/debugfs.h>
+#include <media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_sync_api.h"
+#include "cam_packet_util.h"
+#include "cam_hw.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_jpeg_hw_mgr.h"
+#include "cam_enc_hw_intf.h"
+#include "cam_dma_hw_intf.h"
+#include "cam_smmu_api.h"
+#include "cam_mem_mgr.h"
+#include "cam_req_mgr_workq.h"
+#include "cam_mem_mgr.h"
+#include "cam_cdm_intf_api.h"
+#include "cam_debug_util.h"
+
+#define CAM_JPEG_HW_ENTRIES_MAX  20
+
+static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr;
+
+static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status,
+	int32_t result_size, void *data);
+static int cam_jpeg_mgr_process_cmd(void *priv, void *data);
+
+static int cam_jpeg_mgr_process_irq(void *priv, void *data)
+{
+	int rc = 0;
+	struct cam_jpeg_process_irq_work_data_t *task_data;
+	struct cam_jpeg_hw_mgr *hw_mgr;
+	int32_t i;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	struct cam_hw_done_event_data buf_data;
+	struct cam_jpeg_set_irq_cb irq_cb;
+	uint32_t dev_type = 0;
+	uint64_t kaddr;
+	uint32_t *cmd_buf_kaddr;
+	size_t cmd_buf_len;
+	struct cam_jpeg_config_inout_param_info *p_params;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+	struct crm_workq_task *task;
+	struct cam_jpeg_process_frame_work_data_t *wq_task_data;
+
+	if (!data || !priv) {
+		CAM_ERR(CAM_JPEG, "Invalid data");
+		return -EINVAL;
+	}
+
+	task_data = data;
+	hw_mgr = &g_jpeg_hw_mgr;
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)task_data->data;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		return -EINVAL;
+	}
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
+	irq_cb.data = NULL;
+	irq_cb.b_set_cb = false;
+	if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
+		CAM_ERR(CAM_JPEG, "process_cmd null ");
+		return -EINVAL;
+	}
+	rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
+		hw_mgr->devices[dev_type][0]->hw_priv,
+		CAM_JPEG_ENC_CMD_SET_IRQ_CB,
+		&irq_cb, sizeof(irq_cb));
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "CMD_SET_IRQ_CB failed %d", rc);
+		return rc;
+	}
+
+	mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex);
+	hw_mgr->device_in_use[dev_type][0] = false;
+	p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+	hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL;
+	mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex);
+
+	task = cam_req_mgr_workq_get_task(
+		g_jpeg_hw_mgr.work_process_frame);
+	if (!task) {
+		CAM_ERR(CAM_JPEG, "no empty task");
+		return -EINVAL;
+	}
+
+	wq_task_data = (struct cam_jpeg_process_frame_work_data_t *)
+		task->payload;
+	if (!task_data) {
+		CAM_ERR(CAM_JPEG, "task_data is NULL");
+		return -EINVAL;
+	}
+	wq_task_data->data = (void *)(uint64_t)dev_type;
+	wq_task_data->request_id = 0;
+	wq_task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE;
+	task->process_cb = cam_jpeg_mgr_process_cmd;
+	rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "could not enque task %d", rc);
+		return rc;
+	}
+
+	rc = cam_mem_get_cpu_buf(
+		p_cfg_req->hw_cfg_args.hw_update_entries[1].handle,
+		(uint64_t *)&kaddr, &cmd_buf_len);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d",
+			hw_mgr->iommu_hdl, rc);
+		return rc;
+	}
+
+	cmd_buf_kaddr = (uint32_t *)kaddr;
+
+	cmd_buf_kaddr =
+		(cmd_buf_kaddr +
+		(p_cfg_req->hw_cfg_args.hw_update_entries[1].offset/4));
+
+	p_params = (struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr;
+
+	p_params->output_size = task_data->result_size;
+	CAM_DBG(CAM_JPEG, "Encoded Size %d", task_data->result_size);
+
+	buf_data.num_handles = p_cfg_req->
+		hw_cfg_args.num_out_map_entries;
+	for (i = 0; i < buf_data.num_handles; i++) {
+		buf_data.resource_handle[i] =
+			p_cfg_req->hw_cfg_args.
+			out_map_entries[i].resource_handle;
+	}
+	buf_data.request_id =
+		(uint64_t)p_cfg_req->hw_cfg_args.priv;
+	ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
+
+	list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list);
+
+
+	return rc;
+}
+
+static int cam_jpeg_hw_mgr_cb(
+	uint32_t irq_status, int32_t result_size, void *data)
+{
+	int32_t rc;
+	unsigned long flags;
+	struct cam_jpeg_hw_mgr *hw_mgr = &g_jpeg_hw_mgr;
+	struct crm_workq_task *task;
+	struct cam_jpeg_process_irq_work_data_t *task_data;
+
+	spin_lock_irqsave(&hw_mgr->hw_mgr_lock, flags);
+	task = cam_req_mgr_workq_get_task(
+		g_jpeg_hw_mgr.work_process_irq_cb);
+	if (!task) {
+		CAM_ERR(CAM_JPEG, "no empty task");
+		spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags);
+		return -ENOMEM;
+	}
+
+	task_data = (struct cam_jpeg_process_irq_work_data_t *)task->payload;
+	task_data->data = data;
+	task_data->irq_status = irq_status;
+	task_data->result_size = result_size;
+	task_data->type = CAM_JPEG_WORKQ_TASK_MSG_TYPE;
+	task->process_cb = cam_jpeg_mgr_process_irq;
+
+	rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_get_free_ctx(struct cam_jpeg_hw_mgr *hw_mgr)
+{
+	int i = 0;
+	int num_ctx = CAM_JPEG_CTX_MAX;
+
+	for (i = 0; i < num_ctx; i++) {
+		mutex_lock(&hw_mgr->ctx_data[i].ctx_mutex);
+		if (hw_mgr->ctx_data[i].in_use == false) {
+			hw_mgr->ctx_data[i].in_use = true;
+			mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex);
+			break;
+		}
+		mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex);
+	}
+
+	return i;
+}
+
+
+static int cam_jpeg_mgr_release_ctx(
+	struct cam_jpeg_hw_mgr *hw_mgr, int ctx_id)
+{
+	if (ctx_id >= CAM_JPEG_CTX_MAX) {
+		CAM_ERR(CAM_JPEG, "ctx_id is wrong: %d", ctx_id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+	if (!hw_mgr->ctx_data[ctx_id].in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is already in use: %d", ctx_id);
+		mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+		return -EINVAL;
+	}
+
+	hw_mgr->ctx_data[ctx_id].in_use = 0;
+	mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+
+	return 0;
+}
+
+static int cam_jpeg_mgr_process_cmd(void *priv, void *data)
+{
+	int rc;
+	int i = 0;
+	struct cam_jpeg_hw_mgr *hw_mgr = priv;
+	struct cam_hw_update_entry *cmd;
+	struct cam_cdm_bl_request *cdm_cmd;
+	struct cam_hw_config_args *config_args = NULL;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	uint64_t request_id = 0;
+	struct cam_jpeg_process_frame_work_data_t *task_data =
+		(struct cam_jpeg_process_frame_work_data_t *)data;
+	uint32_t dev_type;
+	struct cam_jpeg_set_irq_cb irq_cb;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+	uint32_t size = 0;
+	uint32_t mem_cam_base = 0;
+	struct cam_hw_done_event_data buf_data;
+
+	CAM_DBG(CAM_JPEG, "in cam_jpeg_mgr_process_cmd");
+	if (!hw_mgr || !task_data) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK",
+			hw_mgr, task_data);
+		return -EINVAL;
+	}
+
+	if (list_empty(&hw_mgr->hw_config_req_list)) {
+		CAM_DBG(CAM_JPEG, "no available request");
+		rc = -EFAULT;
+		goto end;
+	}
+
+	p_cfg_req = list_first_entry(&hw_mgr->hw_config_req_list,
+		struct cam_jpeg_hw_cfg_req, list);
+	if (!p_cfg_req) {
+		CAM_ERR(CAM_JPEG, "no request");
+		rc = -EFAULT;
+		goto end;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	if (false == hw_mgr->device_in_use[p_cfg_req->dev_type][0]) {
+		hw_mgr->device_in_use[p_cfg_req->dev_type][0] = true;
+		hw_mgr->dev_hw_cfg_args[p_cfg_req->dev_type][0] = p_cfg_req;
+		list_del_init(&p_cfg_req->list);
+	} else {
+		CAM_ERR(CAM_JPEG, "NOT dequeing, just return");
+		rc = -EFAULT;
+		goto end;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args;
+	request_id = task_data->request_id;
+	if (request_id != (uint64_t)config_args->priv) {
+		CAM_WARN(CAM_JPEG, "not a recent req %d %d",
+			request_id, (uint64_t)config_args->priv);
+	}
+
+	if (!config_args->num_hw_update_entries) {
+		CAM_ERR(CAM_JPEG, "No hw update enteries are available");
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)config_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	if (dev_type != p_cfg_req->dev_type)
+		CAM_WARN(CAM_JPEG, "dev types not same something wrong");
+
+	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
+	irq_cb.data = (void *)ctx_data;
+	irq_cb.b_set_cb = true;
+	if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
+		CAM_ERR(CAM_JPEG, "op process_cmd null ");
+		return -EINVAL;
+	}
+	rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
+		hw_mgr->devices[dev_type][0]->hw_priv,
+		CAM_JPEG_ENC_CMD_SET_IRQ_CB,
+		&irq_cb, sizeof(irq_cb));
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "SET_IRQ_CB failed %d", rc);
+		return -EINVAL;
+	}
+
+	if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) {
+		CAM_ERR(CAM_JPEG, "op reset null ");
+		return -EINVAL;
+	}
+	rc = hw_mgr->devices[dev_type][0]->hw_ops.reset(
+		hw_mgr->devices[dev_type][0]->hw_priv,
+		NULL, 0);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc);
+		return -EINVAL;
+	}
+
+	mem_cam_base = (uint64_t)hw_mgr->cdm_reg_map[dev_type][0]->
+		mem_cam_base;
+	size = hw_mgr->cdm_info[dev_type][0].cdm_ops->
+		cdm_required_size_changebase();
+	hw_mgr->cdm_info[dev_type][0].cdm_ops->
+		cdm_write_changebase(ctx_data->cmd_chbase_buf_addr,
+		(uint64_t)hw_mgr->cdm_reg_map[dev_type][0]->mem_cam_base);
+	ctx_data->cdm_cmd_chbase->cmd_arrary_count = 1;
+	ctx_data->cdm_cmd_chbase->type = CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA;
+	ctx_data->cdm_cmd_chbase->flag = false;
+	ctx_data->cdm_cmd_chbase->userdata = NULL;
+	ctx_data->cdm_cmd_chbase->cookie = 0;
+	ctx_data->cdm_cmd_chbase->cmd[0].bl_addr.kernel_iova =
+		ctx_data->cmd_chbase_buf_addr;
+	ctx_data->cdm_cmd_chbase->cmd[0].offset = 0;
+	ctx_data->cdm_cmd_chbase->cmd[0].len = size;
+	rc = cam_cdm_submit_bls(hw_mgr->cdm_info[dev_type][0].cdm_handle,
+		ctx_data->cdm_cmd_chbase);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "failed cdm cmd %d", rc);
+
+	CAM_DBG(CAM_JPEG, "cfg e %pK num %d",
+		config_args->hw_update_entries,
+		config_args->num_hw_update_entries);
+
+	if (config_args->num_hw_update_entries > 0) {
+		cdm_cmd = ctx_data->cdm_cmd;
+		cdm_cmd->cmd_arrary_count =
+			config_args->num_hw_update_entries - 1;
+		cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE;
+		cdm_cmd->flag = false;
+		cdm_cmd->userdata = NULL;
+		cdm_cmd->cookie = 0;
+
+		for (i = 0; i <= cdm_cmd->cmd_arrary_count; i++) {
+			cmd = (config_args->hw_update_entries + i);
+			cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle;
+			cdm_cmd->cmd[i].offset = cmd->offset;
+			cdm_cmd->cmd[i].len = cmd->len;
+		}
+
+		rc = cam_cdm_submit_bls(
+			hw_mgr->cdm_info[dev_type][0].cdm_handle,
+			cdm_cmd);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "Failed to apply the configs %d",
+				rc);
+			goto end_callcb;
+		}
+
+		if (!hw_mgr->devices[dev_type][0]->hw_ops.start) {
+			CAM_ERR(CAM_JPEG, "op start null ");
+			rc = -EINVAL;
+			goto end_callcb;
+		}
+		rc = hw_mgr->devices[dev_type][0]->hw_ops.start(
+			hw_mgr->devices[dev_type][0]->hw_priv,
+			NULL, 0);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "Failed to apply the configs %d",
+				rc);
+			goto end_callcb;
+		}
+	} else {
+		CAM_ERR(CAM_JPEG, "No commands to config");
+	}
+
+	return rc;
+
+end_callcb:
+	if (p_cfg_req) {
+		buf_data.num_handles = p_cfg_req->
+			hw_cfg_args.num_out_map_entries;
+		for (i = 0; i < buf_data.num_handles; i++) {
+			buf_data.resource_handle[i] =
+				p_cfg_req->hw_cfg_args.
+				out_map_entries[i].resource_handle;
+		}
+		buf_data.request_id =
+			(uint64_t)p_cfg_req->hw_cfg_args.priv;
+		ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
+	}
+end:
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
+{
+	int rc;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_hw_config_args *config_args = config_hw_args;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	uint64_t request_id = 0;
+	struct cam_hw_update_entry *hw_update_entries;
+	struct crm_workq_task *task;
+	struct cam_jpeg_process_frame_work_data_t *task_data;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+
+	if (!hw_mgr || !config_args) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK",
+			hw_mgr, config_args);
+		return -EINVAL;
+	}
+
+	if (!config_args->num_hw_update_entries) {
+		CAM_ERR(CAM_JPEG, "No hw update enteries are available");
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)config_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+
+	if (list_empty(&hw_mgr->free_req_list)) {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		CAM_ERR(CAM_JPEG, "list empty");
+		return -ENOMEM;
+	}
+
+	p_cfg_req = list_first_entry(&hw_mgr->free_req_list,
+		struct cam_jpeg_hw_cfg_req, list);
+	list_del_init(&p_cfg_req->list);
+
+	/* Update Currently Processing Config Request */
+	p_cfg_req->hw_cfg_args = *config_args;
+	p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	request_id = (uint64_t)config_args->priv;
+	hw_update_entries = config_args->hw_update_entries;
+	CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %d %pK",
+		ctx_data, request_id, config_args->priv);
+	task = cam_req_mgr_workq_get_task(g_jpeg_hw_mgr.work_process_frame);
+	if (!task) {
+		CAM_ERR(CAM_JPEG, "no empty task");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		rc = -ENOMEM;
+		goto err_after_dq_free_list;
+	}
+
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	task_data = (struct cam_jpeg_process_frame_work_data_t *)
+		task->payload;
+	if (!task_data) {
+		CAM_ERR(CAM_JPEG, "task_data is NULL");
+		rc = -EINVAL;
+		goto err_after_dq_free_list;
+	}
+	CAM_DBG(CAM_JPEG, "cfge %pK num %d",
+		p_cfg_req->hw_cfg_args.hw_update_entries,
+		p_cfg_req->hw_cfg_args.num_hw_update_entries);
+
+	list_add_tail(&p_cfg_req->list, &hw_mgr->hw_config_req_list);
+
+	task_data->data = (void *)(int64_t)p_cfg_req->dev_type;
+	task_data->request_id = request_id;
+	task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE;
+	task->process_cb = cam_jpeg_mgr_process_cmd;
+
+	rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "failed to enqueue task %d", rc);
+		goto err_after_get_task;
+	}
+
+	return rc;
+
+err_after_get_task:
+	list_del_init(&p_cfg_req->list);
+err_after_dq_free_list:
+	list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list);
+
+	return rc;
+}
+
+
+static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
+	void *prepare_hw_update_args)
+{
+	int rc, i, j, k;
+	struct cam_hw_prepare_update_args *prepare_args =
+		prepare_hw_update_args;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	struct cam_packet *packet = NULL;
+	struct cam_cmd_buf_desc *cmd_desc = NULL;
+	struct cam_buf_io_cfg *io_cfg_ptr = NULL;
+
+	if (!prepare_args || !hw_mgr) {
+		CAM_ERR(CAM_JPEG, "Invalid args %pK %pK",
+			prepare_args, hw_mgr);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)prepare_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	packet = prepare_args->packet;
+	if (!packet) {
+		CAM_ERR(CAM_JPEG, "received packet is NULL");
+		return -EINVAL;
+	}
+
+	if (((packet->header.op_code & 0xff) != CAM_JPEG_OPCODE_ENC_UPDATE) &&
+		((packet->header.op_code
+		& 0xff) != CAM_JPEG_OPCODE_DMA_UPDATE)) {
+		CAM_ERR(CAM_JPEG, "Invalid Opcode in pkt: %d",
+			packet->header.op_code & 0xff);
+		return -EINVAL;
+	}
+	if ((packet->num_cmd_buf > 2) || !packet->num_patches ||
+		!packet->num_io_configs) {
+		CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u",
+			packet->num_cmd_buf,
+			packet->num_patches);
+		return -EINVAL;
+	}
+
+	cmd_desc = (struct cam_cmd_buf_desc *)
+		((uint32_t *)&packet->payload +
+		(packet->cmd_buf_offset / 4));
+	CAM_DBG(CAM_JPEG, "packet = %pK cmd_desc = %pK size = %lu",
+		(void *)packet, (void *)cmd_desc,
+		sizeof(struct cam_cmd_buf_desc));
+
+	rc = cam_packet_util_process_patches(packet, hw_mgr->iommu_hdl);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Patch processing failed %d", rc);
+		return rc;
+	}
+
+	io_cfg_ptr = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
+		packet->io_configs_offset / 4);
+	CAM_DBG(CAM_JPEG, "packet = %pK io_cfg_ptr = %pK size = %lu",
+		(void *)packet, (void *)io_cfg_ptr,
+		sizeof(struct cam_buf_io_cfg));
+
+	prepare_args->num_out_map_entries = 0;
+
+	for (i = 0, j = 0, k = 0; i < packet->num_io_configs; i++) {
+		if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) {
+			prepare_args->in_map_entries[j].resource_handle =
+				io_cfg_ptr[i].resource_type;
+			prepare_args->in_map_entries[j++].sync_id =
+				io_cfg_ptr[i].fence;
+			prepare_args->num_in_map_entries++;
+		} else {
+			prepare_args->in_map_entries[k].resource_handle =
+				io_cfg_ptr[i].resource_type;
+			prepare_args->out_map_entries[k++].sync_id =
+				io_cfg_ptr[i].fence;
+			prepare_args->num_out_map_entries++;
+		}
+		CAM_DBG(CAM_JPEG, "dir[%d]: %u, fence: %u",
+			i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence);
+	}
+
+	for (i = 0; i < packet->num_cmd_buf;  i++) {
+		prepare_args->hw_update_entries[i].len =
+			(uint32_t)cmd_desc[i].length;
+		prepare_args->hw_update_entries[i].handle =
+			(uint32_t)cmd_desc[i].mem_handle;
+		prepare_args->hw_update_entries[i].offset =
+			(uint32_t)cmd_desc[i].offset;
+		prepare_args->num_hw_update_entries++;
+	}
+
+	prepare_args->priv = (void *)packet->header.request_id;
+
+	CAM_DBG(CAM_JPEG, "will wait on input sync sync_id %d",
+		prepare_args->in_map_entries[0].sync_id);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
+{
+	int rc;
+	int ctx_id = 0;
+	struct cam_hw_release_args *release_hw = release_hw_args;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	uint32_t dev_type;
+
+	if (!release_hw || !hw_mgr) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)release_hw->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	hw_mgr->cdm_info[dev_type][0].ref_cnt--;
+	if (!(hw_mgr->cdm_info[dev_type][0].ref_cnt)) {
+		if (cam_cdm_stream_off(
+			hw_mgr->cdm_info[dev_type][0].cdm_handle)) {
+			CAM_ERR(CAM_JPEG, "CDM stream off failed %d",
+				hw_mgr->cdm_info[dev_type][0].cdm_handle);
+		}
+		/* release cdm handle */
+		cam_cdm_release(hw_mgr->cdm_info[dev_type][0].cdm_handle);
+	}
+
+	if (g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.deinit) {
+		rc = g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.deinit(
+			g_jpeg_hw_mgr.devices[dev_type][0]->hw_priv, NULL, 0);
+		if (rc)
+			CAM_ERR(CAM_JPEG, "Failed to Init %d HW", dev_type);
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	rc = cam_jpeg_mgr_release_ctx(hw_mgr, ctx_id);
+	if (rc) {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_JPEG, "handle %llu", ctx_data);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
+{
+	int rc;
+	int32_t ctx_id = 0;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	struct cam_hw_acquire_args *args = acquire_hw_args;
+	struct cam_jpeg_acquire_dev_info jpeg_dev_acquire_info;
+	struct cam_cdm_acquire_data cdm_acquire;
+	uint32_t dev_type;
+	uint32_t size = 0;
+
+	if ((!hw_mgr_priv) || (!acquire_hw_args)) {
+		CAM_ERR(CAM_JPEG, "Invalid params: %pK %pK", hw_mgr_priv,
+			acquire_hw_args);
+		return -EINVAL;
+	}
+
+	if (args->num_acq > 1) {
+		CAM_ERR(CAM_JPEG,
+			"number of resources are wrong: %u",
+			args->num_acq);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&jpeg_dev_acquire_info,
+			(void __user *)args->acquire_info,
+			sizeof(jpeg_dev_acquire_info))) {
+		CAM_ERR(CAM_JPEG, "copy failed");
+		return -EFAULT;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	ctx_id = cam_jpeg_mgr_get_free_ctx(hw_mgr);
+	if (ctx_id >= CAM_JPEG_CTX_MAX) {
+		CAM_ERR(CAM_JPEG, "No free ctx space in hw_mgr");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EFAULT;
+	}
+
+	ctx_data = &hw_mgr->ctx_data[ctx_id];
+
+	ctx_data->cdm_cmd =
+		kzalloc(((sizeof(struct cam_cdm_bl_request)) +
+			((CAM_JPEG_HW_ENTRIES_MAX - 1) *
+			sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
+	if (!ctx_data->cdm_cmd) {
+		rc = -ENOMEM;
+		goto acq_cdm_hdl_failed;
+	}
+
+	mutex_lock(&ctx_data->ctx_mutex);
+	ctx_data->jpeg_dev_acquire_info = jpeg_dev_acquire_info;
+	mutex_unlock(&ctx_data->ctx_mutex);
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+	if (!hw_mgr->cdm_info[dev_type][0].ref_cnt) {
+
+		if (dev_type == CAM_JPEG_RES_TYPE_ENC) {
+			memcpy(cdm_acquire.identifier,
+				"jpegenc", sizeof("jpegenc"));
+		} else {
+			memcpy(cdm_acquire.identifier,
+				"jpegdma", sizeof("jpegdma"));
+		}
+		cdm_acquire.cell_index = 0;
+		cdm_acquire.handle = 0;
+		cdm_acquire.userdata = ctx_data;
+		if (hw_mgr->cdm_reg_map[dev_type][0]) {
+			cdm_acquire.base_array[0] =
+				hw_mgr->cdm_reg_map[dev_type][0];
+		}
+		cdm_acquire.base_array_cnt = 1;
+		cdm_acquire.id = CAM_CDM_VIRTUAL;
+		cdm_acquire.cam_cdm_callback = NULL;
+
+		rc = cam_cdm_acquire(&cdm_acquire);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "Failed to acquire the CDM HW %d",
+				rc);
+			rc = -EFAULT;
+			goto acq_cdm_hdl_failed;
+		}
+		hw_mgr->cdm_info[dev_type][0].cdm_handle = cdm_acquire.handle;
+		hw_mgr->cdm_info[dev_type][0].cdm_ops = cdm_acquire.ops;
+		hw_mgr->cdm_info[dev_type][0].ref_cnt++;
+	} else {
+		hw_mgr->cdm_info[dev_type][0].ref_cnt++;
+	}
+
+	ctx_data->cdm_cmd_chbase =
+		kzalloc(((sizeof(struct cam_cdm_bl_request)) +
+			(2 * sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
+	if (!ctx_data->cdm_cmd_chbase) {
+		rc = -ENOMEM;
+		goto start_cdm_hdl_failed;
+	}
+	size = hw_mgr->cdm_info[dev_type][0].
+		cdm_ops->cdm_required_size_changebase();
+	ctx_data->cmd_chbase_buf_addr = kzalloc(size*4, GFP_KERNEL);
+	if (!ctx_data->cdm_cmd_chbase) {
+		rc = -ENOMEM;
+		goto start_cdm_hdl_failed;
+	}
+
+	if (!g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.init) {
+		CAM_ERR(CAM_JPEG, "hw op init null ");
+		rc = -EINVAL;
+		goto start_cdm_hdl_failed;
+	}
+	rc = g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.init(
+		g_jpeg_hw_mgr.devices[dev_type][0]->hw_priv,
+		ctx_data,
+		sizeof(ctx_data));
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Failed to Init %d HW", dev_type);
+		goto start_cdm_hdl_failed;
+	}
+
+	if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1)
+		if (cam_cdm_stream_on(
+			hw_mgr->cdm_info[dev_type][0].cdm_handle)) {
+			CAM_ERR(CAM_JPEG, "Can not start cdm (%d)!",
+				hw_mgr->cdm_info[dev_type][0].cdm_handle);
+			rc = -EFAULT;
+			goto start_cdm_hdl_failed;
+		}
+
+	mutex_lock(&ctx_data->ctx_mutex);
+	ctx_data->context_priv = args->context_data;
+
+	args->ctxt_to_hw_map = (void *)&(hw_mgr->ctx_data[ctx_id]);
+
+	mutex_unlock(&ctx_data->ctx_mutex);
+
+	hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb;
+
+
+	if (copy_to_user((void __user *)args->acquire_info,
+		&jpeg_dev_acquire_info,
+		sizeof(jpeg_dev_acquire_info))) {
+		rc = -EFAULT;
+		goto copy_to_user_failed;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	CAM_DBG(CAM_JPEG, "success ctx_data= %pK", ctx_data);
+
+	return rc;
+
+copy_to_user_failed:
+	cam_cdm_stream_off(hw_mgr->cdm_info[dev_type][0].cdm_handle);
+start_cdm_hdl_failed:
+	cam_cdm_release(hw_mgr->cdm_info[dev_type][0].cdm_handle);
+acq_cdm_hdl_failed:
+	kfree(ctx_data->cdm_cmd);
+	cam_jpeg_mgr_release_ctx(hw_mgr, ctx_id);
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
+{
+	int rc;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_query_cap_cmd *query_cap = hw_caps_args;
+
+	if (!hw_mgr_priv || !hw_caps_args) {
+		CAM_ERR(CAM_JPEG, "Invalid params: %pK %pK",
+			hw_mgr_priv, hw_caps_args);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	if (copy_to_user((void __user *)query_cap->caps_handle,
+		&g_jpeg_hw_mgr.jpeg_caps,
+		sizeof(struct cam_jpeg_query_cap_cmd))) {
+		CAM_ERR(CAM_JPEG, "copy_to_user failed");
+		rc = -EFAULT;
+		goto copy_error;
+	}
+	CAM_DBG(CAM_JPEG, "cam_jpeg_mgr_get_hw_caps success");
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	return 0;
+
+copy_error:
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	return rc;
+}
+
+static int cam_jpeg_setup_workqs(void)
+{
+	int rc, i;
+
+	rc = cam_req_mgr_workq_create(
+		"jpeg_command_queue",
+		CAM_JPEG_WORKQ_NUM_TASK,
+		&g_jpeg_hw_mgr.work_process_frame,
+		CRM_WORKQ_USAGE_NON_IRQ);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
+		goto work_process_frame_failed;
+	}
+
+	rc = cam_req_mgr_workq_create(
+		"jpeg_message_queue",
+		CAM_JPEG_WORKQ_NUM_TASK,
+		&g_jpeg_hw_mgr.work_process_irq_cb,
+		CRM_WORKQ_USAGE_IRQ);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
+		goto work_process_irq_cb_failed;
+	}
+
+	g_jpeg_hw_mgr.process_frame_work_data =
+		(struct cam_jpeg_process_frame_work_data_t *)
+		kzalloc(sizeof(struct cam_jpeg_process_frame_work_data_t) *
+			CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.process_frame_work_data) {
+		rc = -ENOMEM;
+		goto work_process_frame_data_failed;
+	}
+
+	g_jpeg_hw_mgr.process_irq_cb_work_data =
+		(struct cam_jpeg_process_irq_work_data_t *)
+		kzalloc(sizeof(struct cam_jpeg_process_irq_work_data_t) *
+			CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.process_irq_cb_work_data) {
+		rc = -ENOMEM;
+		goto work_process_irq_cb_data_failed;
+	}
+
+	for (i = 0; i < CAM_JPEG_WORKQ_NUM_TASK; i++)
+		g_jpeg_hw_mgr.work_process_irq_cb->task.pool[i].payload =
+			&g_jpeg_hw_mgr.process_irq_cb_work_data[i];
+
+	for (i = 0; i < CAM_JPEG_WORKQ_NUM_TASK; i++)
+		g_jpeg_hw_mgr.work_process_frame->task.pool[i].payload =
+			&g_jpeg_hw_mgr.process_frame_work_data[i];
+
+	INIT_LIST_HEAD(&g_jpeg_hw_mgr.hw_config_req_list);
+	INIT_LIST_HEAD(&g_jpeg_hw_mgr.free_req_list);
+	for (i = 0; i < CAM_JPEG_HW_CFG_Q_MAX; i++) {
+		INIT_LIST_HEAD(&(g_jpeg_hw_mgr.req_list[i].list));
+		list_add_tail(&(g_jpeg_hw_mgr.req_list[i].list),
+			&(g_jpeg_hw_mgr.free_req_list));
+	}
+
+	return rc;
+
+work_process_irq_cb_data_failed:
+	kfree(g_jpeg_hw_mgr.process_frame_work_data);
+work_process_frame_data_failed:
+	cam_req_mgr_workq_destroy(&g_jpeg_hw_mgr.work_process_irq_cb);
+work_process_irq_cb_failed:
+	cam_req_mgr_workq_destroy(&g_jpeg_hw_mgr.work_process_frame);
+work_process_frame_failed:
+
+	return rc;
+}
+
+static int cam_jpeg_init_devices(struct device_node *of_node,
+	uint32_t *p_num_enc_dev,
+	uint32_t *p_num_dma_dev)
+{
+	int count, i, rc;
+	uint32_t num_dev;
+	uint32_t num_dma_dev;
+	const char *name = NULL;
+	struct device_node *child_node = NULL;
+	struct platform_device *child_pdev = NULL;
+	struct cam_hw_intf *child_dev_intf = NULL;
+	struct cam_hw_info *enc_hw = NULL;
+	struct cam_hw_info *dma_hw = NULL;
+	struct cam_hw_soc_info *enc_soc_info = NULL;
+	struct cam_hw_soc_info *dma_soc_info = NULL;
+
+	if (!p_num_enc_dev || !p_num_dma_dev) {
+		rc = -EINVAL;
+		goto num_dev_failed;
+	}
+	count = of_property_count_strings(of_node, "compat-hw-name");
+	if (!count) {
+		CAM_ERR(CAM_JPEG,
+			"no compat hw found in dev tree, count = %d",
+			count);
+		rc = -EINVAL;
+		goto num_dev_failed;
+	}
+
+	rc = of_property_read_u32(of_node, "num-jpeg-enc", &num_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "read num enc devices failed %d", rc);
+		goto num_enc_failed;
+	}
+	g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kzalloc(
+		sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]) {
+		rc = -ENOMEM;
+		CAM_ERR(CAM_JPEG, "getting number of dma dev nodes failed");
+		goto num_enc_failed;
+	}
+
+	rc = of_property_read_u32(of_node, "num-jpeg-dma", &num_dma_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "get num dma dev nodes failed %d", rc);
+		goto num_dma_failed;
+	}
+
+	g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kzalloc(
+		sizeof(struct cam_hw_intf *) * num_dma_dev, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]) {
+		rc = -ENOMEM;
+		goto num_dma_failed;
+	}
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node, "compat-hw-name",
+			i, &name);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "getting dev object name failed");
+			goto compat_hw_name_failed;
+		}
+
+		child_node = of_find_node_by_name(NULL, name);
+		if (!child_node) {
+			CAM_ERR(CAM_JPEG,
+				"error! Cannot find node in dtsi %s", name);
+			rc = -ENODEV;
+			goto compat_hw_name_failed;
+		}
+
+		child_pdev = of_find_device_by_node(child_node);
+		if (!child_pdev) {
+			CAM_ERR(CAM_JPEG, "failed to find device on bus %s",
+				child_node->name);
+			rc = -ENODEV;
+			of_node_put(child_node);
+			goto compat_hw_name_failed;
+		}
+
+		child_dev_intf = (struct cam_hw_intf *)platform_get_drvdata(
+			child_pdev);
+		if (!child_dev_intf) {
+			CAM_ERR(CAM_JPEG, "no child device");
+			of_node_put(child_node);
+			rc = -ENODEV;
+			goto compat_hw_name_failed;
+		}
+		CAM_DBG(CAM_JPEG, "child_intf %pK type %d id %d",
+			child_dev_intf,
+			child_dev_intf->hw_type,
+			child_dev_intf->hw_idx);
+
+		if ((child_dev_intf->hw_type == CAM_JPEG_DEV_ENC &&
+			child_dev_intf->hw_idx >= num_dev) ||
+			(child_dev_intf->hw_type == CAM_JPEG_DEV_DMA &&
+			child_dev_intf->hw_idx >= num_dma_dev)) {
+			CAM_ERR(CAM_JPEG, "index out of range");
+			rc = -ENODEV;
+			goto compat_hw_name_failed;
+		}
+		g_jpeg_hw_mgr.devices[child_dev_intf->hw_type]
+			[child_dev_intf->hw_idx] = child_dev_intf;
+
+		of_node_put(child_node);
+	}
+
+	enc_hw = (struct cam_hw_info *)
+		g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_priv;
+	enc_soc_info = &enc_hw->soc_info;
+	g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_ENC][0] =
+		&enc_soc_info->reg_map[0];
+	dma_hw = (struct cam_hw_info *)
+		g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_priv;
+	dma_soc_info = &dma_hw->soc_info;
+	g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_DMA][0] =
+		&dma_soc_info->reg_map[0];
+
+	*p_num_enc_dev = num_dev;
+	*p_num_dma_dev = num_dma_dev;
+
+	return rc;
+
+compat_hw_name_failed:
+	kfree(g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]);
+num_dma_failed:
+	kfree(g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]);
+num_enc_failed:
+num_dev_failed:
+
+	return rc;
+}
+
+int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
+{
+	int i, rc;
+	uint32_t num_dev;
+	uint32_t num_dma_dev;
+	struct cam_hw_mgr_intf *hw_mgr_intf;
+	struct cam_iommu_handle cdm_handles;
+
+	hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl;
+	if (!of_node || !hw_mgr_intf) {
+		CAM_ERR(CAM_JPEG, "Invalid args of_node %pK hw_mgr %pK",
+			of_node, hw_mgr_intf);
+		return -EINVAL;
+	}
+
+	memset(hw_mgr_hdl, 0x0, sizeof(struct cam_hw_mgr_intf));
+	hw_mgr_intf->hw_mgr_priv = &g_jpeg_hw_mgr;
+	hw_mgr_intf->hw_get_caps = cam_jpeg_mgr_get_hw_caps;
+	hw_mgr_intf->hw_acquire = cam_jpeg_mgr_acquire_hw;
+	hw_mgr_intf->hw_release = cam_jpeg_mgr_release_hw;
+	hw_mgr_intf->hw_prepare_update = cam_jpeg_mgr_prepare_hw_update;
+	hw_mgr_intf->hw_config = cam_jpeg_mgr_config_hw;
+
+	mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
+	spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
+
+	for (i = 0; i < CAM_JPEG_CTX_MAX; i++)
+		mutex_init(&g_jpeg_hw_mgr.ctx_data[i].ctx_mutex);
+
+	rc = cam_jpeg_init_devices(of_node, &num_dev, &num_dma_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg init devices %d", rc);
+		goto smmu_get_failed;
+	}
+
+	rc = cam_smmu_get_handle("jpeg", &g_jpeg_hw_mgr.iommu_hdl);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg get iommu handle failed %d", rc);
+		goto smmu_get_failed;
+	}
+
+	CAM_DBG(CAM_JPEG, "mmu handle :%d", g_jpeg_hw_mgr.iommu_hdl);
+	rc = cam_smmu_ops(g_jpeg_hw_mgr.iommu_hdl, CAM_SMMU_ATTACH);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg attach failed: %d", rc);
+		goto jpeg_attach_failed;
+	}
+
+	rc = cam_cdm_get_iommu_handle("jpegenc", &cdm_handles);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "acquire cdm iommu handle Fail  %d", rc);
+		g_jpeg_hw_mgr.cdm_iommu_hdl = -1;
+		g_jpeg_hw_mgr.cdm_iommu_hdl_secure = -1;
+		goto cdm_iommu_failed;
+	}
+	g_jpeg_hw_mgr.cdm_iommu_hdl = cdm_handles.non_secure;
+	g_jpeg_hw_mgr.cdm_iommu_hdl_secure = cdm_handles.secure;
+
+	g_jpeg_hw_mgr.jpeg_caps.dev_iommu_handle.non_secure =
+		g_jpeg_hw_mgr.iommu_hdl;
+	g_jpeg_hw_mgr.jpeg_caps.dev_iommu_handle.secure =
+		g_jpeg_hw_mgr.iommu_sec_hdl;
+	g_jpeg_hw_mgr.jpeg_caps.cdm_iommu_handle.non_secure =
+		g_jpeg_hw_mgr.cdm_iommu_hdl;
+	g_jpeg_hw_mgr.jpeg_caps.cdm_iommu_handle.secure =
+		g_jpeg_hw_mgr.cdm_iommu_hdl_secure;
+	g_jpeg_hw_mgr.jpeg_caps.num_enc = num_dev;
+	g_jpeg_hw_mgr.jpeg_caps.num_dma = num_dma_dev;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.major = 4;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.minor = 2;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.incr  = 0;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.reserved = 0;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.major = 4;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.minor = 2;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.incr  = 0;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.reserved = 0;
+
+	rc = cam_jpeg_setup_workqs();
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "setup work qs failed  %d", rc);
+		goto cdm_iommu_failed;
+	}
+
+	return rc;
+
+cdm_iommu_failed:
+	cam_smmu_ops(g_jpeg_hw_mgr.iommu_hdl, CAM_SMMU_DETACH);
+	cam_smmu_destroy_handle(g_jpeg_hw_mgr.iommu_hdl);
+jpeg_attach_failed:
+	g_jpeg_hw_mgr.iommu_hdl = 0;
+smmu_get_failed:
+	mutex_destroy(&g_jpeg_hw_mgr.hw_mgr_mutex);
+	for (i = 0; i < CAM_JPEG_CTX_MAX; i++)
+		mutex_destroy(&g_jpeg_hw_mgr.ctx_data[i].ctx_mutex);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
new file mode 100644
index 0000000..9e3418d
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
@@ -0,0 +1,164 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_HW_MGR_H
+#define CAM_JPEG_HW_MGR_H
+
+#include <linux/types.h>
+#include <linux/completion.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_jpeg_hw_intf.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_hw_intf.h"
+#include "cam_req_mgr_workq.h"
+#include "cam_mem_mgr.h"
+
+#define CAM_JPEG_WORKQ_NUM_TASK      30
+#define CAM_JPEG_WORKQ_TASK_CMD_TYPE 1
+#define CAM_JPEG_WORKQ_TASK_MSG_TYPE 2
+#define CAM_JPEG_HW_CFG_Q_MAX        50
+
+/**
+ * struct cam_jpeg_process_frame_work_data_t
+ *
+ * @type: Task type
+ * @data: Pointer to command data
+ * @request_id: Request id
+ */
+struct cam_jpeg_process_frame_work_data_t {
+	uint32_t type;
+	void *data;
+	uint64_t request_id;
+};
+
+/**
+ * struct cam_jpeg_process_irq_work_data_t
+ *
+ * @type: Task type
+ * @data: Pointer to message data
+ * @result_size: Result size of enc/dma
+ * @irq_status: IRQ status
+ */
+struct cam_jpeg_process_irq_work_data_t {
+	uint32_t type;
+	void *data;
+	int32_t result_size;
+	uint32_t irq_status;
+};
+
+/**
+ * struct cam_jpeg_hw_cdm_info_t
+ *
+ * @ref_cnt: Ref count of how many times device type is acquired
+ * @cdm_handle: Cdm handle
+ * @cdm_ops: Cdm ops struct
+ */
+struct cam_jpeg_hw_cdm_info_t {
+	int ref_cnt;
+	uint32_t cdm_handle;
+	struct cam_cdm_utils_ops *cdm_ops;
+};
+
+/**
+ * struct cam_jpeg_hw_cfg_req_t
+ *
+ * @list_head: List head
+ * @hw_cfg_args: Hw config args
+ * @dev_type: Dev type for cfg request
+ */
+struct cam_jpeg_hw_cfg_req {
+	struct list_head list;
+	struct cam_hw_config_args hw_cfg_args;
+	uint32_t dev_type;
+};
+
+/**
+ * struct cam_jpeg_hw_ctx_data
+ *
+ * @context_priv: Context private data, cam_context from
+ *     acquire.
+ * @ctx_mutex: Mutex for context
+ * @jpeg_dev_acquire_info: Acquire device info
+ * @ctxt_event_cb: Context callback function
+ * @in_use: Flag for context usage
+ * @wait_complete: Completion info
+ * @cdm_cmd: Cdm cmd submitted for that context.
+ * @cdm_cmd_chbase: Change base cdm command from context
+ * @cmd_chbase_buf_addr : Change base cmd buf address
+ */
+struct cam_jpeg_hw_ctx_data {
+	void *context_priv;
+	struct mutex ctx_mutex;
+	struct cam_jpeg_acquire_dev_info jpeg_dev_acquire_info;
+	cam_hw_event_cb_func ctxt_event_cb;
+	bool in_use;
+	struct completion wait_complete;
+	struct cam_cdm_bl_request *cdm_cmd;
+	struct cam_cdm_bl_request *cdm_cmd_chbase;
+	uint32_t *cmd_chbase_buf_addr;
+};
+
+/**
+ * struct cam_jpeg_hw_mgr
+ * @hw_mgr_mutex: Mutex for JPEG hardware manager
+ * @hw_mgr_lock: Spinlock for JPEG hardware manager
+ * @ctx_data: Context data
+ * @jpeg_caps: JPEG capabilities
+ * @iommu_hdl: Non secure IOMMU handle
+ * @iommu_sec_hdl: Secure IOMMU handle
+ * @work_process_frame: Work queue for hw config requests
+ * @work_process_irq_cb: Work queue for processing IRQs.
+ * @process_frame_work_data: Work data pool for hw config
+ *     requests
+ * @process_irq_cb_work_data: Work data pool for irq requests
+ * @cdm_iommu_hdl: Iommu handle received from cdm
+ * @cdm_iommu_hdl_secure: Secure iommu handle received from cdm
+ * @devices: Core hw Devices of JPEG hardware manager
+ * @cdm_info: Cdm info for each core device.
+ * @cdm_reg_map: Regmap of each device for cdm.
+ * @device_in_use: Flag device being used for an active request
+ * @dev_hw_cfg_args: Current cfg request per core dev
+ * @hw_config_req_list: Pending hw update requests list
+ * @free_req_list: Free nodes for above list
+ * @req_list: Nodes of hw update list
+ */
+struct cam_jpeg_hw_mgr {
+	struct mutex hw_mgr_mutex;
+	spinlock_t hw_mgr_lock;
+	struct cam_jpeg_hw_ctx_data ctx_data[CAM_JPEG_CTX_MAX];
+	struct cam_jpeg_query_cap_cmd jpeg_caps;
+	int32_t iommu_hdl;
+	int32_t iommu_sec_hdl;
+	struct cam_req_mgr_core_workq *work_process_frame;
+	struct cam_req_mgr_core_workq *work_process_irq_cb;
+	struct cam_jpeg_process_frame_work_data_t *process_frame_work_data;
+	struct cam_jpeg_process_irq_work_data_t *process_irq_cb_work_data;
+	int cdm_iommu_hdl;
+	int cdm_iommu_hdl_secure;
+
+	struct cam_hw_intf **devices[CAM_JPEG_DEV_TYPE_MAX];
+	struct cam_jpeg_hw_cdm_info_t cdm_info[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+	struct cam_soc_reg_map *cdm_reg_map[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+	uint32_t device_in_use[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+	struct cam_jpeg_hw_cfg_req *dev_hw_cfg_args[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+
+	struct list_head hw_config_req_list;
+	struct list_head free_req_list;
+	struct cam_jpeg_hw_cfg_req req_list[CAM_JPEG_HW_CFG_Q_MAX];
+};
+
+#endif /* CAM_JPEG_HW_MGR_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_dma_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_dma_hw_intf.h
new file mode 100644
index 0000000..71b21b9
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_dma_hw_intf.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_DMA_HW_INTF_H
+#define CAM_JPEG_DMA_HW_INTF_H
+
+#include <uapi/media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_intf.h"
+
+enum cam_jpeg_dma_cmd_type {
+	CAM_JPEG_DMA_CMD_CDM_CFG,
+	CAM_JPEG_DMA_CMD_SET_IRQ_CB,
+	CAM_JPEG_DMA_CMD_MAX,
+};
+
+#endif /* CAM_JPEG_DMA_HW_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_enc_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_enc_hw_intf.h
new file mode 100644
index 0000000..f0b4e00
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_enc_hw_intf.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_ENC_HW_INTF_H
+#define CAM_JPEG_ENC_HW_INTF_H
+
+#include <uapi/media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_intf.h"
+
+enum cam_jpeg_enc_cmd_type {
+	CAM_JPEG_ENC_CMD_CDM_CFG,
+	CAM_JPEG_ENC_CMD_SET_IRQ_CB,
+	CAM_JPEG_ENC_CMD_MAX,
+};
+
+#endif /* CAM_JPEG_ENC_HW_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h
new file mode 100644
index 0000000..3204388
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h
@@ -0,0 +1,26 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_HW_INTF_H
+#define CAM_JPEG_HW_INTF_H
+
+#define CAM_JPEG_CTX_MAX              8
+#define CAM_JPEG_DEV_PER_TYPE_MAX     1
+
+#define CAM_JPEG_CMD_BUF_MAX_SIZE     128
+#define CAM_JPEG_MSG_BUF_MAX_SIZE     CAM_JPEG_CMD_BUF_MAX_SIZE
+
+enum cam_jpeg_hw_type {
+	CAM_JPEG_DEV_ENC,
+	CAM_JPEG_DEV_DMA,
+};
+#endif
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
new file mode 100644
index 0000000..d5c8c9d
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_HW_MGR_INTF_H
+#define CAM_JPEG_HW_MGR_INTF_H
+
+#include <uapi/media/cam_jpeg.h>
+#include <uapi/media/cam_defs.h>
+#include <linux/of.h>
+
+#include "cam_cpas_api.h"
+
+#define JPEG_TURBO_VOTE           640000000
+
+int cam_jpeg_hw_mgr_init(struct device_node *of_node,
+	uint64_t *hw_mgr_hdl);
+
+/**
+ * struct cam_jpeg_cpas_vote
+ * @ahb_vote: AHB vote info
+ * @axi_vote: AXI vote info
+ * @ahb_vote_valid: Flag for ahb vote data
+ * @axi_vote_valid: Flag for axi vote data
+ */
+struct cam_jpeg_cpas_vote {
+	struct cam_ahb_vote ahb_vote;
+	struct cam_axi_vote axi_vote;
+	uint32_t ahb_vote_valid;
+	uint32_t axi_vote_valid;
+};
+
+struct cam_jpeg_set_irq_cb {
+	int32_t (*jpeg_hw_mgr_cb)(
+		uint32_t irq_status,
+		int32_t result_size,
+		void *data);
+	void *data;
+	uint32_t b_set_cb;
+};
+
+#endif /* CAM_JPEG_HW_MGR_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile
new file mode 100644
index 0000000..23b27bf
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_dev.o jpeg_dma_core.o jpeg_dma_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c
new file mode 100644
index 0000000..05c1a95
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c
@@ -0,0 +1,165 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/debugfs.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+
+#include "cam_io_util.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "jpeg_dma_core.h"
+#include "jpeg_dma_soc.h"
+#include "cam_soc_util.h"
+#include "cam_io_util.h"
+#include "cam_dma_hw_intf.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+int cam_jpeg_dma_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_dma_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	struct cam_jpeg_cpas_vote cpas_vote;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_dma_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
+		core_info;
+
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
+	cpas_vote.axi_vote.compressed_bw = JPEG_TURBO_VOTE;
+	cpas_vote.axi_vote.uncompressed_bw = JPEG_TURBO_VOTE;
+
+	rc = cam_cpas_start(core_info->cpas_handle,
+		&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpass start failed: %d", rc);
+
+	rc = cam_jpeg_dma_enable_soc_resources(soc_info);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc);
+		cam_cpas_stop(core_info->cpas_handle);
+	}
+
+	return rc;
+}
+
+int cam_jpeg_dma_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_dma_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_dma_dev->soc_info;
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	rc = cam_jpeg_dma_disable_soc_resources(soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "soc enable failed %d", rc);
+
+	rc = cam_cpas_stop(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas stop failed: %d", rc);
+
+	return 0;
+}
+
+int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_dma_dev = device_priv;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	if (cmd_type >= CAM_JPEG_DMA_CMD_MAX) {
+		CAM_ERR(CAM_JPEG, "Invalid command : %x", cmd_type);
+		return -EINVAL;
+	}
+
+	core_info =
+		(struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
+		core_info;
+
+	switch (cmd_type) {
+	case CAM_JPEG_DMA_CMD_SET_IRQ_CB:
+	{
+		struct cam_jpeg_set_irq_cb *irq_cb = cmd_args;
+
+		if (!cmd_args) {
+			CAM_ERR(CAM_JPEG, "cmd args NULL");
+			return -EINVAL;
+		}
+		if (irq_cb->b_set_cb) {
+			core_info->irq_cb.jpeg_hw_mgr_cb =
+				irq_cb->jpeg_hw_mgr_cb;
+			core_info->irq_cb.data = irq_cb->data;
+		} else {
+			core_info->irq_cb.jpeg_hw_mgr_cb = NULL;
+			core_info->irq_cb.data = NULL;
+		}
+		rc = 0;
+		break;
+	}
+	default:
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
+irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data)
+{
+	return IRQ_HANDLED;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h
new file mode 100644
index 0000000..bb4e34a
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_DMA_CORE_H
+#define CAM_JPEG_DMA_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+
+struct cam_jpeg_dma_device_hw_info {
+	uint32_t reserved;
+};
+
+struct cam_jpeg_dma_set_irq_cb {
+	int32_t (*jpeg_hw_mgr_cb)(uint32_t irq_status,
+		int32_t result_size, void *data);
+	void *data;
+};
+
+enum cam_jpeg_dma_core_state {
+	CAM_JPEG_DMA_CORE_NOT_READY,
+	CAM_JPEG_DMA_CORE_READY,
+	CAM_JPEG_DMA_CORE_RESETTING,
+	CAM_JPEG_DMA_CORE_STATE_MAX,
+};
+
+struct cam_jpeg_dma_device_core_info {
+	enum cam_jpeg_dma_core_state core_state;
+	struct cam_jpeg_dma_device_hw_info *jpeg_dma_hw_info;
+	uint32_t cpas_handle;
+	struct cam_jpeg_dma_set_irq_cb irq_cb;
+};
+
+int cam_jpeg_dma_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_dma_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size);
+irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data);
+
+#endif /* CAM_JPEG_DMA_CORE_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
new file mode 100644
index 0000000..829bb51
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/timer.h>
+
+#include "jpeg_dma_core.h"
+#include "jpeg_dma_soc.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "cam_io_util.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = {
+	.reserved = 0,
+};
+EXPORT_SYMBOL(cam_jpeg_dma_hw_info);
+
+static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info,
+	struct cam_jpeg_dma_device_core_info *core_info,
+	uint32_t hw_idx)
+{
+	struct cam_cpas_register_params cpas_register_params;
+	int rc;
+
+	cpas_register_params.dev = &soc_info->pdev->dev;
+	memcpy(cpas_register_params.identifier, "jpeg-dma",
+		sizeof("jpeg-dma"));
+	cpas_register_params.cam_cpas_client_cb = NULL;
+	cpas_register_params.cell_index = hw_idx;
+	cpas_register_params.userdata = NULL;
+
+	rc = cam_cpas_register_client(&cpas_register_params);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc);
+		return rc;
+	}
+	core_info->cpas_handle = cpas_register_params.client_handle;
+
+	return rc;
+}
+
+static int cam_jpeg_dma_unregister_cpas(
+	struct cam_jpeg_dma_device_core_info *core_info)
+{
+	int rc;
+
+	rc = cam_cpas_unregister_client(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc);
+	core_info->cpas_handle = 0;
+
+	return rc;
+}
+
+static int cam_jpeg_dma_remove(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_dma_dev = NULL;
+	struct cam_hw_intf *jpeg_dma_dev_intf = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	int rc;
+
+	jpeg_dma_dev_intf = platform_get_drvdata(pdev);
+	if (!jpeg_dma_dev_intf) {
+		CAM_ERR(CAM_JPEG, "error No data in pdev");
+		return -EINVAL;
+	}
+
+	jpeg_dma_dev = jpeg_dma_dev_intf->hw_priv;
+	if (!jpeg_dma_dev) {
+		CAM_ERR(CAM_JPEG, "error HW data is NULL");
+		rc = -ENODEV;
+		goto free_jpeg_hw_intf;
+	}
+
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
+	if (!core_info) {
+		CAM_ERR(CAM_JPEG, "error core data NULL");
+		goto deinit_soc;
+	}
+
+	rc = cam_jpeg_dma_unregister_cpas(core_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc);
+
+	kfree(core_info);
+
+deinit_soc:
+	rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc);
+
+	mutex_destroy(&jpeg_dma_dev->hw_mutex);
+	kfree(jpeg_dma_dev);
+
+free_jpeg_hw_intf:
+	kfree(jpeg_dma_dev_intf);
+	return rc;
+}
+
+static int cam_jpeg_dma_probe(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_dma_dev = NULL;
+	struct cam_hw_intf *jpeg_dma_dev_intf = NULL;
+	const struct of_device_id *match_dev = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	struct cam_jpeg_dma_device_hw_info *hw_info = NULL;
+	int rc;
+
+	jpeg_dma_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
+	if (!jpeg_dma_dev_intf)
+		return -ENOMEM;
+
+	of_property_read_u32(pdev->dev.of_node,
+		"cell-index", &jpeg_dma_dev_intf->hw_idx);
+
+	jpeg_dma_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
+	if (!jpeg_dma_dev) {
+		rc = -ENOMEM;
+		goto error_alloc_dev;
+	}
+	jpeg_dma_dev->soc_info.pdev = pdev;
+	jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev;
+	jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw;
+	jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw;
+	jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd;
+	jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA;
+
+	platform_set_drvdata(pdev, jpeg_dma_dev_intf);
+	jpeg_dma_dev->core_info =
+		kzalloc(sizeof(struct cam_jpeg_dma_device_core_info),
+			GFP_KERNEL);
+	if (!jpeg_dma_dev->core_info) {
+		rc = -ENOMEM;
+		goto error_alloc_core;
+	}
+	core_info = (struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
+		core_info;
+
+	match_dev = of_match_device(pdev->dev.driver->of_match_table,
+		&pdev->dev);
+	if (!match_dev) {
+		CAM_ERR(CAM_JPEG, " No jpeg_dma hardware info");
+		rc = -EINVAL;
+		goto error_match_dev;
+	}
+	hw_info = (struct cam_jpeg_dma_device_hw_info *)match_dev->data;
+	core_info->jpeg_dma_hw_info = hw_info;
+	core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY;
+
+	rc = cam_jpeg_dma_init_soc_resources(&jpeg_dma_dev->soc_info,
+		cam_jpeg_dma_irq,
+		jpeg_dma_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "%failed to init_soc %d", rc);
+		goto error_match_dev;
+	}
+
+	rc = cam_jpeg_dma_register_cpas(&jpeg_dma_dev->soc_info,
+		core_info, jpeg_dma_dev_intf->hw_idx);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc);
+		goto error_reg_cpas;
+	}
+	jpeg_dma_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
+	mutex_init(&jpeg_dma_dev->hw_mutex);
+	spin_lock_init(&jpeg_dma_dev->hw_lock);
+	init_completion(&jpeg_dma_dev->hw_complete);
+
+	CAM_DBG(CAM_JPEG, " hwidx %d", jpeg_dma_dev_intf->hw_idx);
+
+	return rc;
+
+error_reg_cpas:
+	rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info);
+error_match_dev:
+	kfree(jpeg_dma_dev->core_info);
+error_alloc_core:
+	kfree(jpeg_dma_dev);
+error_alloc_dev:
+	kfree(jpeg_dma_dev_intf);
+	return rc;
+}
+
+static const struct of_device_id cam_jpeg_dma_dt_match[] = {
+	{
+		.compatible = "qcom,cam_jpeg_dma",
+		.data = &cam_jpeg_dma_hw_info,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, cam_jpeg_dma_dt_match);
+
+static struct platform_driver cam_jpeg_dma_driver = {
+	.probe = cam_jpeg_dma_probe,
+	.remove = cam_jpeg_dma_remove,
+	.driver = {
+		.name = "cam-jpeg-dma",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_jpeg_dma_dt_match,
+	},
+};
+
+static int __init cam_jpeg_dma_init_module(void)
+{
+	return platform_driver_register(&cam_jpeg_dma_driver);
+}
+
+static void __exit cam_jpeg_dma_exit_module(void)
+{
+	platform_driver_unregister(&cam_jpeg_dma_driver);
+}
+
+module_init(cam_jpeg_dma_init_module);
+module_exit(cam_jpeg_dma_exit_module);
+MODULE_DESCRIPTION("CAM JPEG_DMA driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c
new file mode 100644
index 0000000..efc161b
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c
@@ -0,0 +1,63 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+#include <media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "jpeg_dma_soc.h"
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_dma_irq_handler, void *irq_data)
+{
+	int rc;
+
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc)
+		return rc;
+
+	rc = cam_soc_util_request_platform_resource(soc_info,
+		jpeg_dma_irq_handler,
+		irq_data);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "init soc failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+		CAM_SVS_VOTE, true);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "enable platform failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "disable platform failed %d", rc);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h
new file mode 100644
index 0000000..bc9bed8
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_DMA_SOC_H_
+#define _CAM_JPEG_DMA_SOC_H_
+
+#include "cam_soc_util.h"
+
+int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_dma_irq_handler, void *irq_data);
+
+int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+#endif /* _CAM_JPEG_DMA_SOC_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile
new file mode 100644
index 0000000..b046a7f
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_dev.o jpeg_enc_core.o jpeg_enc_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
new file mode 100644
index 0000000..25405cf
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
@@ -0,0 +1,348 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/debugfs.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+
+#include "cam_io_util.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "jpeg_enc_core.h"
+#include "jpeg_enc_soc.h"
+#include "cam_soc_util.h"
+#include "cam_io_util.h"
+#include "cam_enc_hw_intf.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001
+#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000
+
+#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000
+#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
+
+#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
+#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
+
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF      (0x1<<19)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR     (0x1<<20)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR   (0x1<<21)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF (0x1<<22)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW    (0x1<<23)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM       (0x1<<24)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ   (0x1<<25)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM       (0x1<<26)
+#define CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK        (0x1<<29)
+
+#define CAM_JPEG_HW_MASK_COMP_FRAMEDONE \
+		CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK
+#define CAM_JPEG_HW_MASK_COMP_RESET_ACK \
+		CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK
+#define CAM_JPEG_HW_MASK_COMP_ERR \
+		(CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM | \
+		CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK)
+
+#define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status) \
+	(jpeg_irq_status & CAM_JPEG_HW_MASK_COMP_FRAMEDONE)
+#define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status) \
+	(jpeg_irq_status & CAM_JPEG_HW_MASK_COMP_RESET_ACK)
+#define CAM_JPEG_HW_IRQ_IS_ERR(jpeg_irq_status) \
+	(jpeg_irq_status & CAM_JPEG_HW_MASK_COMP_ERR)
+
+#define CAM_JPEG_ENC_RESET_TIMEOUT msecs_to_jiffies(500)
+
+int cam_jpeg_enc_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_jpeg_cpas_vote cpas_vote;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
+	cpas_vote.axi_vote.compressed_bw = JPEG_TURBO_VOTE;
+	cpas_vote.axi_vote.uncompressed_bw = JPEG_TURBO_VOTE;
+
+	rc = cam_cpas_start(core_info->cpas_handle,
+		&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpass start failed: %d", rc);
+
+	rc = cam_jpeg_enc_enable_soc_resources(soc_info);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc);
+		cam_cpas_stop(core_info->cpas_handle);
+	}
+
+	return rc;
+}
+
+int cam_jpeg_enc_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	rc = cam_jpeg_enc_disable_soc_resources(soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "soc enable failed %d", rc);
+
+	rc = cam_cpas_stop(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas stop failed: %d", rc);
+
+	return 0;
+}
+
+irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	uint32_t irq_status = 0;
+	uint32_t encoded_size = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return IRQ_HANDLED;
+	}
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	irq_status = cam_io_r_mb(mem_base +
+		core_info->jpeg_enc_hw_info->int_status);
+
+	cam_io_w_mb(irq_status,
+		soc_info->reg_map[0].mem_base +
+		core_info->jpeg_enc_hw_info->int_clr);
+
+	CAM_DBG(CAM_JPEG, "irq_num %d  irq_status = %x , core_state %d",
+		irq_num, irq_status, core_info->core_state);
+	if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status)) {
+		if (core_info->core_state == CAM_JPEG_ENC_CORE_READY) {
+			encoded_size = cam_io_r_mb(mem_base + 0x180);
+			if (core_info->irq_cb.jpeg_hw_mgr_cb) {
+				core_info->irq_cb.jpeg_hw_mgr_cb(irq_status,
+					encoded_size,
+					core_info->irq_cb.data);
+			} else {
+				CAM_ERR(CAM_JPEG, "unexpected done");
+			}
+		}
+
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+	}
+	if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status)) {
+		if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
+			core_info->core_state = CAM_JPEG_ENC_CORE_READY;
+			complete(&jpeg_enc_dev->hw_complete);
+		} else {
+			CAM_ERR(CAM_JPEG, "unexpected reset irq");
+		}
+	}
+	/* Unexpected/unintended HW interrupt */
+	if (CAM_JPEG_HW_IRQ_IS_ERR(irq_status)) {
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+		CAM_ERR_RATE_LIMIT(CAM_JPEG,
+			"error irq_num %d  irq_status = %x , core_state %d",
+			irq_num, irq_status, core_info->core_state);
+
+		if (core_info->irq_cb.jpeg_hw_mgr_cb) {
+			core_info->irq_cb.jpeg_hw_mgr_cb(irq_status,
+				-1,
+				core_info->irq_cb.data);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+int cam_jpeg_enc_reset_hw(void *data,
+	void *start_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+	unsigned long rem_jiffies;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+	/* maskdisable.clrirq.maskenable.resetcmd */
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
+		CAM_ERR(CAM_JPEG, "alrady resetting");
+		return 0;
+	}
+
+	reinit_completion(&jpeg_enc_dev->hw_complete);
+
+	core_info->core_state = CAM_JPEG_ENC_CORE_RESETTING;
+
+	cam_io_w_mb(0x00000000, mem_base + hw_info->int_mask);
+	cam_io_w_mb(0xFFFFFFFF, mem_base + hw_info->int_clr);
+	cam_io_w_mb(0xFFFFFFFF, mem_base + hw_info->int_mask);
+	cam_io_w_mb(0x00032093, mem_base + hw_info->reset_cmd);
+
+	rem_jiffies = wait_for_completion_timeout(&jpeg_enc_dev->hw_complete,
+		CAM_JPEG_ENC_RESET_TIMEOUT);
+	if (!rem_jiffies) {
+		CAM_ERR(CAM_JPEG, "error Reset Timeout");
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+	}
+
+	return 0;
+}
+
+int cam_jpeg_enc_start_hw(void *data,
+	void *start_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) {
+		CAM_ERR(CAM_JPEG, "Error not ready");
+		return -EINVAL;
+	}
+
+	cam_io_w_mb(0x00000001, mem_base + 0x00000010);
+
+	return 0;
+}
+
+int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = device_priv;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	if (cmd_type >= CAM_JPEG_ENC_CMD_MAX) {
+		CAM_ERR(CAM_JPEG, "Invalid command : %x", cmd_type);
+		return -EINVAL;
+	}
+
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+
+	switch (cmd_type) {
+	case CAM_JPEG_ENC_CMD_SET_IRQ_CB:
+	{
+		struct cam_jpeg_set_irq_cb *irq_cb = cmd_args;
+
+		if (!cmd_args) {
+			CAM_ERR(CAM_JPEG, "cmd args NULL");
+			return -EINVAL;
+		}
+		if (irq_cb->b_set_cb) {
+			core_info->irq_cb.jpeg_hw_mgr_cb =
+				irq_cb->jpeg_hw_mgr_cb;
+			core_info->irq_cb.data = irq_cb->data;
+		} else {
+			core_info->irq_cb.jpeg_hw_mgr_cb = NULL;
+			core_info->irq_cb.data = NULL;
+		}
+		rc = 0;
+		break;
+	}
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	if (rc)
+		CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc);
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
new file mode 100644
index 0000000..6ae4cdc
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_ENC_CORE_H
+#define CAM_JPEG_ENC_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+
+struct cam_jpeg_enc_device_hw_info {
+	uint32_t hw_version;
+	uint32_t int_status;
+	uint32_t int_clr;
+	uint32_t int_mask;
+	uint32_t reset_cmd;
+};
+
+struct cam_jpeg_enc_set_irq_cb {
+	int32_t (*jpeg_hw_mgr_cb)(uint32_t irq_status,
+		int32_t result_size, void *data);
+	void *data;
+};
+
+enum cam_jpeg_enc_core_state {
+	CAM_JPEG_ENC_CORE_NOT_READY,
+	CAM_JPEG_ENC_CORE_READY,
+	CAM_JPEG_ENC_CORE_RESETTING,
+	CAM_JPEG_ENC_CORE_STATE_MAX,
+};
+
+struct cam_jpeg_enc_device_core_info {
+	enum cam_jpeg_enc_core_state core_state;
+	struct cam_jpeg_enc_device_hw_info *jpeg_enc_hw_info;
+	uint32_t cpas_handle;
+	struct cam_jpeg_enc_set_irq_cb irq_cb;
+};
+
+int cam_jpeg_enc_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_start_hw(void *device_priv,
+	void *start_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_reset_hw(void *device_priv,
+	void *reset_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size);
+irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data);
+
+#endif /* CAM_JPEG_ENC_CORE_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
new file mode 100644
index 0000000..5dd1e1f
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/timer.h>
+
+#include "jpeg_enc_core.h"
+#include "jpeg_enc_soc.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "cam_io_util.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = {
+	.int_clr = 0x1c,
+	.int_status = 0x20,
+	.int_mask = 0x18,
+	.reset_cmd = 0x8,
+	.hw_version = 0x0,
+};
+EXPORT_SYMBOL(cam_jpeg_enc_hw_info);
+
+static int cam_jpeg_enc_register_cpas(struct cam_hw_soc_info *soc_info,
+	struct cam_jpeg_enc_device_core_info *core_info,
+	uint32_t hw_idx)
+{
+	struct cam_cpas_register_params cpas_register_params;
+	int rc;
+
+	cpas_register_params.dev = &soc_info->pdev->dev;
+	memcpy(cpas_register_params.identifier, "jpeg-enc",
+		sizeof("jpeg-enc"));
+	cpas_register_params.cam_cpas_client_cb = NULL;
+	cpas_register_params.cell_index = hw_idx;
+	cpas_register_params.userdata = NULL;
+
+	rc = cam_cpas_register_client(&cpas_register_params);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc);
+		return rc;
+	}
+	core_info->cpas_handle = cpas_register_params.client_handle;
+
+	return rc;
+}
+
+static int cam_jpeg_enc_unregister_cpas(
+	struct cam_jpeg_enc_device_core_info *core_info)
+{
+	int rc;
+
+	rc = cam_cpas_unregister_client(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc);
+	core_info->cpas_handle = 0;
+
+	return rc;
+}
+
+static int cam_jpeg_enc_remove(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_enc_dev = NULL;
+	struct cam_hw_intf *jpeg_enc_dev_intf = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	int rc;
+
+	jpeg_enc_dev_intf = platform_get_drvdata(pdev);
+	if (!jpeg_enc_dev_intf) {
+		CAM_ERR(CAM_JPEG, "error No data in pdev");
+		return -EINVAL;
+	}
+
+	jpeg_enc_dev = jpeg_enc_dev_intf->hw_priv;
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "error HW data is NULL");
+		rc = -ENODEV;
+		goto free_jpeg_hw_intf;
+	}
+
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
+	if (!core_info) {
+		CAM_ERR(CAM_JPEG, "error core data NULL");
+		goto deinit_soc;
+	}
+
+	rc = cam_jpeg_enc_unregister_cpas(core_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc);
+
+	kfree(core_info);
+
+deinit_soc:
+	rc = cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc);
+
+	mutex_destroy(&jpeg_enc_dev->hw_mutex);
+	kfree(jpeg_enc_dev);
+
+free_jpeg_hw_intf:
+	kfree(jpeg_enc_dev_intf);
+	return rc;
+}
+
+static int cam_jpeg_enc_probe(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_enc_dev = NULL;
+	struct cam_hw_intf *jpeg_enc_dev_intf = NULL;
+	const struct of_device_id *match_dev = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	int rc;
+
+	jpeg_enc_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
+	if (!jpeg_enc_dev_intf)
+		return -ENOMEM;
+
+	of_property_read_u32(pdev->dev.of_node,
+		"cell-index", &jpeg_enc_dev_intf->hw_idx);
+
+	jpeg_enc_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
+	if (!jpeg_enc_dev) {
+		rc = -ENOMEM;
+		goto error_alloc_dev;
+	}
+	jpeg_enc_dev->soc_info.pdev = pdev;
+	jpeg_enc_dev_intf->hw_priv = jpeg_enc_dev;
+	jpeg_enc_dev_intf->hw_ops.init = cam_jpeg_enc_init_hw;
+	jpeg_enc_dev_intf->hw_ops.deinit = cam_jpeg_enc_deinit_hw;
+	jpeg_enc_dev_intf->hw_ops.start = cam_jpeg_enc_start_hw;
+	jpeg_enc_dev_intf->hw_ops.reset = cam_jpeg_enc_reset_hw;
+	jpeg_enc_dev_intf->hw_ops.process_cmd = cam_jpeg_enc_process_cmd;
+	jpeg_enc_dev_intf->hw_type = CAM_JPEG_DEV_ENC;
+
+	platform_set_drvdata(pdev, jpeg_enc_dev_intf);
+	jpeg_enc_dev->core_info =
+		kzalloc(sizeof(struct cam_jpeg_enc_device_core_info),
+			GFP_KERNEL);
+	if (!jpeg_enc_dev->core_info) {
+		rc = -ENOMEM;
+		goto error_alloc_core;
+	}
+	core_info = (struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+
+	match_dev = of_match_device(pdev->dev.driver->of_match_table,
+		&pdev->dev);
+	if (!match_dev) {
+		CAM_ERR(CAM_JPEG, " No jpeg_enc hardware info");
+		rc = -EINVAL;
+		goto error_match_dev;
+	}
+	hw_info = (struct cam_jpeg_enc_device_hw_info *)match_dev->data;
+	core_info->jpeg_enc_hw_info = hw_info;
+	core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+
+	rc = cam_jpeg_enc_init_soc_resources(&jpeg_enc_dev->soc_info,
+		cam_jpeg_enc_irq,
+		jpeg_enc_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, " failed to init_soc %d", rc);
+		goto error_match_dev;
+	}
+
+	rc = cam_jpeg_enc_register_cpas(&jpeg_enc_dev->soc_info,
+		core_info, jpeg_enc_dev_intf->hw_idx);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc);
+		goto error_reg_cpas;
+	}
+	jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
+	mutex_init(&jpeg_enc_dev->hw_mutex);
+	spin_lock_init(&jpeg_enc_dev->hw_lock);
+	init_completion(&jpeg_enc_dev->hw_complete);
+
+	return rc;
+
+error_reg_cpas:
+	cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info);
+error_match_dev:
+	kfree(jpeg_enc_dev->core_info);
+error_alloc_core:
+	kfree(jpeg_enc_dev);
+error_alloc_dev:
+	kfree(jpeg_enc_dev_intf);
+
+	return rc;
+}
+
+static const struct of_device_id cam_jpeg_enc_dt_match[] = {
+	{
+		.compatible = "qcom,cam_jpeg_enc",
+		.data = &cam_jpeg_enc_hw_info,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, cam_jpeg_enc_dt_match);
+
+static struct platform_driver cam_jpeg_enc_driver = {
+	.probe = cam_jpeg_enc_probe,
+	.remove = cam_jpeg_enc_remove,
+	.driver = {
+		.name = "cam-jpeg-enc",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_jpeg_enc_dt_match,
+	},
+};
+
+static int __init cam_jpeg_enc_init_module(void)
+{
+	return platform_driver_register(&cam_jpeg_enc_driver);
+}
+
+static void __exit cam_jpeg_enc_exit_module(void)
+{
+	platform_driver_unregister(&cam_jpeg_enc_driver);
+}
+
+module_init(cam_jpeg_enc_init_module);
+module_exit(cam_jpeg_enc_exit_module);
+MODULE_DESCRIPTION("CAM JPEG_ENC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c
new file mode 100644
index 0000000..3f450cd
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c
@@ -0,0 +1,63 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+#include <media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "jpeg_enc_soc.h"
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_enc_irq_handler, void *irq_data)
+{
+	int rc;
+
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc)
+		return rc;
+
+	rc = cam_soc_util_request_platform_resource(soc_info,
+		jpeg_enc_irq_handler,
+		irq_data);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "init soc failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+		CAM_SVS_VOTE, true);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "enable platform failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "disable platform failed %d", rc);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h
new file mode 100644
index 0000000..a0485a2
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_ENC_SOC_H_
+#define _CAM_JPEG_ENC_SOC_H_
+
+#include "cam_soc_util.h"
+
+int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_enc_irq_handler, void *irq_data);
+
+int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+#endif /* _CAM_JPEG_ENC_SOC_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index 2f9db97..c150244 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -10,14 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-MEM-MGR %s:%d " fmt, __func__, __LINE__
-
-#ifdef CONFIG_MEM_MGR_DBG
-#define CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
@@ -27,6 +19,7 @@
 #include "cam_req_mgr_util.h"
 #include "cam_mem_mgr.h"
 #include "cam_smmu_api.h"
+#include "cam_debug_util.h"
 
 static struct cam_mem_table tbl;
 
@@ -36,12 +29,12 @@
 {
 	*vaddr = (uintptr_t)ion_map_kernel(tbl.client, hdl);
 	if (IS_ERR_OR_NULL((void *)*vaddr)) {
-		pr_err("kernel map fail");
+		CAM_ERR(CAM_CRM, "kernel map fail");
 		return -ENOSPC;
 	}
 
 	if (ion_handle_get_size(tbl.client, hdl, len)) {
-		pr_err("kernel get len failed");
+		CAM_ERR(CAM_CRM, "kernel get len failed");
 		ion_unmap_kernel(tbl.client, hdl);
 		return -ENOSPC;
 	}
@@ -69,7 +62,7 @@
 
 	tbl.client = msm_ion_client_create("camera_global_pool");
 	if (IS_ERR_OR_NULL(tbl.client)) {
-		pr_err("fail to create client\n");
+		CAM_ERR(CAM_CRM, "fail to create client");
 		rc = -EINVAL;
 	}
 
@@ -92,7 +85,7 @@
 
 	rc = cam_mem_util_client_create();
 	if (rc < 0) {
-		pr_err("fail to create ion client\n");
+		CAM_ERR(CAM_CRM, "fail to create ion client");
 		goto client_fail;
 	}
 
@@ -127,10 +120,12 @@
 	mutex_lock(&tbl.m_lock);
 	for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) {
 		if (!tbl.bufq[i].active) {
-			CDBG("Buffer inactive at idx=%d, continuing\n", i);
+			CAM_DBG(CAM_CRM,
+				"Buffer inactive at idx=%d, continuing", i);
 			continue;
 		} else {
-			pr_err("Active buffer at idx=%d, possible leak\n", i);
+			CAM_ERR(CAM_CRM,
+				"Active buffer at idx=%d, possible leak", i);
 		}
 
 		mutex_lock(&tbl.bufq[i].q_lock);
@@ -221,7 +216,7 @@
 		iova_ptr,
 		len_ptr);
 	if (rc < 0)
-		pr_err("fail to get buf hdl :%d", buf_handle);
+		CAM_ERR(CAM_CRM, "fail to get buf hdl :%d", buf_handle);
 
 handle_mismatch:
 	mutex_unlock(&tbl.bufq[idx].q_lock);
@@ -255,7 +250,7 @@
 
 	ion_hdl = tbl.bufq[idx].i_hdl;
 	if (!ion_hdl) {
-		pr_err("Invalid ION handle\n");
+		CAM_ERR(CAM_CRM, "Invalid ION handle");
 		rc = -EINVAL;
 		goto exit_func;
 	}
@@ -310,7 +305,7 @@
 	rc = ion_handle_get_flags(tbl.client, tbl.bufq[idx].i_hdl,
 		&ion_flag);
 	if (rc) {
-		pr_err("cache get flags failed %d\n", rc);
+		CAM_ERR(CAM_CRM, "cache get flags failed %d", rc);
 		goto fail;
 	}
 
@@ -326,7 +321,8 @@
 			ion_cache_ops = ION_IOC_CLEAN_INV_CACHES;
 			break;
 		default:
-			pr_err("invalid cache ops :%d", cmd->mem_cache_ops);
+			CAM_ERR(CAM_CRM,
+				"invalid cache ops :%d", cmd->mem_cache_ops);
 			rc = -EINVAL;
 			goto fail;
 		}
@@ -337,7 +333,7 @@
 				tbl.bufq[idx].len,
 				ion_cache_ops);
 		if (rc)
-			pr_err("cache operation failed %d\n", rc);
+			CAM_ERR(CAM_CRM, "cache operation failed %d", rc);
 	}
 fail:
 	mutex_unlock(&tbl.bufq[idx].q_lock);
@@ -360,7 +356,7 @@
 
 	*fd = ion_share_dma_buf_fd(tbl.client, *hdl);
 	if (*fd < 0) {
-		pr_err("dma buf get fd fail");
+		CAM_ERR(CAM_CRM, "dma buf get fd fail");
 		rc = -EINVAL;
 		goto get_fd_fail;
 	}
@@ -404,19 +400,19 @@
 static int cam_mem_util_check_flags(struct cam_mem_mgr_alloc_cmd *cmd)
 {
 	if (!cmd->flags) {
-		pr_err("Invalid flags\n");
+		CAM_ERR(CAM_CRM, "Invalid flags");
 		return -EINVAL;
 	}
 
 	if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) {
-		pr_err("Num of mmu hdl exceeded maximum(%d)\n",
+		CAM_ERR(CAM_CRM, "Num of mmu hdl exceeded maximum(%d)",
 			CAM_MEM_MMU_MAX_HANDLE);
 		return -EINVAL;
 	}
 
 	if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE &&
 		cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) {
-		pr_err("Kernel mapping in secure mode not allowed");
+		CAM_ERR(CAM_CRM, "Kernel mapping in secure mode not allowed");
 		return -EINVAL;
 	}
 
@@ -426,24 +422,25 @@
 static int cam_mem_util_check_map_flags(struct cam_mem_mgr_map_cmd *cmd)
 {
 	if (!cmd->flags) {
-		pr_err("Invalid flags\n");
+		CAM_ERR(CAM_CRM, "Invalid flags");
 		return -EINVAL;
 	}
 
 	if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) {
-		pr_err("Num of mmu hdl exceeded maximum(%d)\n",
+		CAM_ERR(CAM_CRM, "Num of mmu hdl exceeded maximum(%d)",
 			CAM_MEM_MMU_MAX_HANDLE);
 		return -EINVAL;
 	}
 
 	if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE &&
 		cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) {
-		pr_err("Kernel mapping in secure mode not allowed");
+		CAM_ERR(CAM_CRM, "Kernel mapping in secure mode not allowed");
 		return -EINVAL;
 	}
 
 	if (cmd->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) {
-		pr_err("Shared memory buffers are not allowed to be mapped\n");
+		CAM_ERR(CAM_CRM,
+			"Shared memory buffers are not allowed to be mapped");
 		return -EINVAL;
 	}
 
@@ -463,7 +460,7 @@
 	int dir = cam_mem_util_get_dma_dir(flags);
 
 	if (dir < 0) {
-		pr_err("fail to map DMA direction\n");
+		CAM_ERR(CAM_CRM, "fail to map DMA direction");
 		return dir;
 	}
 
@@ -476,7 +473,8 @@
 				len);
 
 			if (rc < 0) {
-				pr_err("Failed to securely map to smmu");
+				CAM_ERR(CAM_CRM,
+					"Failed to securely map to smmu");
 				goto multi_map_fail;
 			}
 		}
@@ -490,7 +488,7 @@
 				region);
 
 			if (rc < 0) {
-				pr_err("Failed to map to smmu");
+				CAM_ERR(CAM_CRM, "Failed to map to smmu");
 				goto multi_map_fail;
 			}
 		}
@@ -520,14 +518,14 @@
 	size_t len;
 
 	if (!cmd) {
-		pr_err(" Invalid argument\n");
+		CAM_ERR(CAM_CRM, " Invalid argument");
 		return -EINVAL;
 	}
 	len = cmd->len;
 
 	rc = cam_mem_util_check_flags(cmd);
 	if (rc) {
-		pr_err("Invalid flags: flags = %X\n", cmd->flags);
+		CAM_ERR(CAM_CRM, "Invalid flags: flags = %X", cmd->flags);
 		return rc;
 	}
 
@@ -535,7 +533,7 @@
 		&ion_hdl,
 		&ion_fd);
 	if (rc) {
-		pr_err("Ion allocation failed\n");
+		CAM_ERR(CAM_CRM, "Ion allocation failed");
 		return rc;
 	}
 
@@ -591,7 +589,7 @@
 	cmd->out.fd = tbl.bufq[idx].fd;
 	cmd->out.vaddr = 0;
 
-	CDBG("buf handle: %x, fd: %d, len: %zu\n",
+	CAM_DBG(CAM_CRM, "buf handle: %x, fd: %d, len: %zu",
 		cmd->out.buf_handle, cmd->out.fd,
 		tbl.bufq[idx].len);
 
@@ -613,7 +611,7 @@
 	size_t len = 0;
 
 	if (!cmd || (cmd->fd < 0)) {
-		pr_err("Invalid argument\n");
+		CAM_ERR(CAM_CRM, "Invalid argument");
 		return -EINVAL;
 	}
 
@@ -622,13 +620,13 @@
 
 	rc = cam_mem_util_check_map_flags(cmd);
 	if (rc) {
-		pr_err("Invalid flags: flags = %X\n", cmd->flags);
+		CAM_ERR(CAM_CRM, "Invalid flags: flags = %X", cmd->flags);
 		return rc;
 	}
 
 	ion_hdl = ion_import_dma_buf_fd(tbl.client, cmd->fd);
 	if (IS_ERR_OR_NULL((void *)(ion_hdl))) {
-		pr_err("Failed to import ion fd\n");
+		CAM_ERR(CAM_CRM, "Failed to import ion fd");
 		return -EINVAL;
 	}
 
@@ -690,7 +688,7 @@
 	int rc = -EINVAL;
 
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		pr_err("Incorrect index\n");
+		CAM_ERR(CAM_CRM, "Incorrect index");
 		return rc;
 	}
 
@@ -725,11 +723,11 @@
 	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
 
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		pr_err("Incorrect index\n");
+		CAM_ERR(CAM_CRM, "Incorrect index");
 		return -EINVAL;
 	}
 
-	CDBG("Flags = %X\n", tbl.bufq[idx].flags);
+	CAM_DBG(CAM_CRM, "Flags = %X", tbl.bufq[idx].flags);
 
 	if (tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS)
 		if (tbl.bufq[idx].i_hdl && tbl.bufq[idx].kmdvaddr)
@@ -755,7 +753,8 @@
 	memset(tbl.bufq[idx].hdls, 0,
 		sizeof(int32_t) * CAM_MEM_MMU_MAX_HANDLE);
 
-	CDBG("Ion handle at idx = %d freeing = %pK, fd = %d, imported %d\n",
+	CAM_DBG(CAM_CRM,
+		"Ion handle at idx = %d freeing = %pK, fd = %d, imported %d",
 		idx, tbl.bufq[idx].i_hdl, tbl.bufq[idx].fd,
 		tbl.bufq[idx].is_imported);
 
@@ -780,27 +779,28 @@
 	int rc;
 
 	if (!cmd) {
-		pr_err("Invalid argument\n");
+		CAM_ERR(CAM_CRM, "Invalid argument");
 		return -EINVAL;
 	}
 
 	idx = CAM_MEM_MGR_GET_HDL_IDX(cmd->buf_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		pr_err("Incorrect index extracted from mem handle\n");
+		CAM_ERR(CAM_CRM, "Incorrect index extracted from mem handle");
 		return -EINVAL;
 	}
 
 	if (!tbl.bufq[idx].active) {
-		pr_err("Released buffer state should be active\n");
+		CAM_ERR(CAM_CRM, "Released buffer state should be active");
 		return -EINVAL;
 	}
 
 	if (tbl.bufq[idx].buf_handle != cmd->buf_handle) {
-		pr_err("Released buf handle not matching within table\n");
+		CAM_ERR(CAM_CRM,
+			"Released buf handle not matching within table");
 		return -EINVAL;
 	}
 
-	CDBG("Releasing hdl = %u\n", cmd->buf_handle);
+	CAM_DBG(CAM_CRM, "Releasing hdl = %u", cmd->buf_handle);
 	rc = cam_mem_util_unmap(idx);
 
 	return rc;
@@ -824,14 +824,14 @@
 	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
 
 	if (!inp || !out) {
-		pr_err("Invalid params\n");
+		CAM_ERR(CAM_CRM, "Invalid params");
 		return -EINVAL;
 	}
 
 	if (!(inp->flags & CAM_MEM_FLAG_HW_READ_WRITE ||
 		inp->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS ||
 		inp->flags & CAM_MEM_FLAG_CACHE)) {
-		pr_err("Invalid flags for request mem\n");
+		CAM_ERR(CAM_CRM, "Invalid flags for request mem");
 		return -EINVAL;
 	}
 
@@ -850,20 +850,20 @@
 		&ion_fd);
 
 	if (rc) {
-		pr_err("ION alloc failed for shared buffer\n");
+		CAM_ERR(CAM_CRM, "ION alloc failed for shared buffer");
 		goto ion_fail;
 	} else {
-		CDBG("Got ION fd = %d, hdl = %pK\n", ion_fd, hdl);
+		CAM_DBG(CAM_CRM, "Got ION fd = %d, hdl = %pK", ion_fd, hdl);
 	}
 
 	rc = cam_mem_util_map_cpu_va(hdl, &kvaddr, &request_len);
 	if (rc) {
-		pr_err("Failed to get kernel vaddr\n");
+		CAM_ERR(CAM_CRM, "Failed to get kernel vaddr");
 		goto map_fail;
 	}
 
 	if (!inp->smmu_hdl) {
-		pr_err("Invalid SMMU handle\n");
+		CAM_ERR(CAM_CRM, "Invalid SMMU handle");
 		rc = -EINVAL;
 		goto smmu_fail;
 	}
@@ -884,7 +884,7 @@
 		region);
 
 	if (rc < 0) {
-		pr_err("SMMU mapping failed\n");
+		CAM_ERR(CAM_CRM, "SMMU mapping failed");
 		goto smmu_fail;
 	}
 
@@ -941,27 +941,28 @@
 	int rc;
 
 	if (!inp) {
-		pr_err("Invalid argument\n");
+		CAM_ERR(CAM_CRM, "Invalid argument");
 		return -EINVAL;
 	}
 
 	idx = CAM_MEM_MGR_GET_HDL_IDX(inp->mem_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		pr_err("Incorrect index extracted from mem handle\n");
+		CAM_ERR(CAM_CRM, "Incorrect index extracted from mem handle");
 		return -EINVAL;
 	}
 
 	if (!tbl.bufq[idx].active) {
-		pr_err("Released buffer state should be active\n");
+		CAM_ERR(CAM_CRM, "Released buffer state should be active");
 		return -EINVAL;
 	}
 
 	if (tbl.bufq[idx].buf_handle != inp->mem_handle) {
-		pr_err("Released buf handle not matching within table\n");
+		CAM_ERR(CAM_CRM,
+			"Released buf handle not matching within table");
 		return -EINVAL;
 	}
 
-	CDBG("Releasing hdl = %X\n", inp->mem_handle);
+	CAM_DBG(CAM_CRM, "Releasing hdl = %X", inp->mem_handle);
 	rc = cam_mem_util_unmap(idx);
 
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index f5dfcf2..3fd42f7 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -20,6 +20,7 @@
 #include "cam_req_mgr_workq.h"
 #include "cam_req_mgr_debug.h"
 #include "cam_trace.h"
+#include "cam_debug_util.h"
 
 static struct cam_req_mgr_core_device *g_crm_core_dev;
 
@@ -59,24 +60,25 @@
 	struct cam_req_mgr_req_tbl   *req_tbl = req->l_tbl;
 
 	if (!in_q || !req_tbl) {
-		CRM_WARN("NULL pointer %pK %pK", in_q, req_tbl);
+		CAM_WARN(CAM_CRM, "NULL pointer %pK %pK", in_q, req_tbl);
 		return -EINVAL;
 	}
-	CRM_DBG("in_q %pK %pK %d", in_q, req_tbl, req_tbl->num_slots);
+	CAM_DBG(CAM_CRM, "in_q %pK %pK %d", in_q, req_tbl, req_tbl->num_slots);
 	mutex_lock(&req->lock);
 	for (i = 0; i < in_q->num_slots; i++) {
-		CRM_DBG("IN_Q %d: idx %d, red_id %lld", i,
+		CAM_DBG(CAM_CRM, "IN_Q %d: idx %d, red_id %lld", i,
 			in_q->slot[i].idx, CRM_GET_REQ_ID(in_q, i));
 	}
 
 	while (req_tbl != NULL) {
 		for (i = 0; i < req_tbl->num_slots; i++) {
-			CRM_DBG("idx= %d, map= %x, state= %d",
+			CAM_DBG(CAM_CRM, "idx= %d, map= %x, state= %d",
 				req_tbl->slot[i].idx,
 				req_tbl->slot[i].req_ready_map,
 				req_tbl->slot[i].state);
 		}
-		CRM_DBG("TBL:id= %d, pd=%d cnt=%d mask=%x skip=%d num_slt= %d",
+		CAM_DBG(CAM_CRM,
+			"TBL:id= %d, pd=%d cnt=%d mask=%x skip=%d num_slt= %d",
 			req_tbl->id, req_tbl->pd, req_tbl->dev_count,
 			req_tbl->dev_mask, req_tbl->skip_traverse,
 			req_tbl->num_slots);
@@ -166,7 +168,7 @@
 	struct cam_req_mgr_apply    *apply_data;
 
 	if (!traverse_data->tbl || !traverse_data->apply_data) {
-		CRM_ERR("NULL pointer %pK %pK",
+		CAM_ERR(CAM_CRM, "NULL pointer %pK %pK",
 			traverse_data->tbl, traverse_data->apply_data);
 		traverse_data->result = 0;
 		return -EINVAL;
@@ -174,7 +176,7 @@
 
 	tbl = traverse_data->tbl;
 	apply_data = traverse_data->apply_data;
-	CRM_DBG("Enter pd %d idx %d state %d skip %d status %d",
+	CAM_DBG(CAM_CRM, "Enter pd %d idx %d state %d skip %d status %d",
 		tbl->pd, curr_idx, tbl->slot[curr_idx].state,
 		tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status);
 
@@ -229,7 +231,7 @@
 	in_q->slot[idx].req_id = -1;
 	in_q->slot[idx].skip_idx = 1;
 	in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
-	CRM_DBG("SET IDX SKIP on slot= %d", idx);
+	CAM_DBG(CAM_CRM, "SET IDX SKIP on slot= %d", idx);
 }
 
 /**
@@ -247,7 +249,7 @@
 		return;
 	do {
 		tbl->id = req->num_tbl++;
-		CRM_DBG("%d: pd %d skip_traverse %d delta %d",
+		CAM_DBG(CAM_CRM, "%d: pd %d skip_traverse %d delta %d",
 			tbl->id, tbl->pd, tbl->skip_traverse,
 			tbl->pd_delta);
 		tbl = tbl->next;
@@ -276,7 +278,7 @@
 	max_pd = tbl->pd;
 	do {
 		tbl->skip_traverse = max_pd - tbl->pd;
-		CRM_DBG("%d: pd %d skip_traverse %d delta %d",
+		CAM_DBG(CAM_CRM, "%d: pd %d skip_traverse %d delta %d",
 			tbl->id, tbl->pd, tbl->skip_traverse,
 			tbl->pd_delta);
 		tbl = tbl->next;
@@ -299,7 +301,7 @@
 	struct cam_req_mgr_req_queue *in_q = link->req.in_q;
 
 	slot = &in_q->slot[idx];
-	CRM_DBG("RESET: idx: %d: slot->status %d", idx, slot->status);
+	CAM_DBG(CAM_CRM, "RESET: idx: %d: slot->status %d", idx, slot->status);
 
 	/* Check if CSL has already pushed new request*/
 	if (slot->status == CRM_SLOT_STATUS_REQ_ADDED)
@@ -313,7 +315,7 @@
 
 	/* Reset all pd table slot */
 	while (tbl != NULL) {
-		CRM_DBG("pd: %d: idx %d state %d",
+		CAM_DBG(CAM_CRM, "pd: %d: idx %d state %d",
 			tbl->pd, idx, tbl->slot[idx].state);
 		tbl->slot[idx].req_ready_map = 0;
 		tbl->slot[idx].state = CRM_REQ_STATE_EMPTY;
@@ -339,13 +341,14 @@
 	__cam_req_mgr_inc_idx(&idx, 1, in_q->num_slots);
 	slot = &in_q->slot[idx];
 
-	CRM_DBG("idx: %d: slot->status %d", idx, slot->status);
+	CAM_DBG(CAM_CRM, "idx: %d: slot->status %d", idx, slot->status);
 
 	/* Check if there is new req from CSL, if not complete req */
 	if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
 		__cam_req_mgr_in_q_skip_idx(in_q, idx);
 		if (in_q->wr_idx != idx)
-			CRM_WARN("CHECK here wr %d, rd %d", in_q->wr_idx, idx);
+			CAM_WARN(CAM_CRM,
+				"CHECK here wr %d, rd %d", in_q->wr_idx, idx);
 		__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
 	}
 }
@@ -377,13 +380,13 @@
 		if (dev) {
 			pd = dev->dev_info.p_delay;
 			if (pd >= CAM_PIPELINE_DELAY_MAX) {
-				CRM_WARN("pd %d greater than max",
+				CAM_WARN(CAM_CRM, "pd %d greater than max",
 					pd);
 				continue;
 			}
 			if (link->req.apply_data[pd].skip_idx ||
 				link->req.apply_data[pd].req_id < 0) {
-				CRM_DBG("skip %d req_id %lld",
+				CAM_DBG(CAM_CRM, "skip %d req_id %lld",
 					link->req.apply_data[pd].skip_idx,
 					link->req.apply_data[pd].req_id);
 				continue;
@@ -394,7 +397,10 @@
 			idx = link->req.apply_data[pd].idx;
 			apply_req.report_if_bubble =
 				in_q->slot[idx].recover;
-			CRM_DBG("SEND: pd %d req_id %lld",
+
+			trace_cam_req_mgr_apply_request(link, &apply_req, dev);
+
+			CAM_DBG(CAM_CRM, "SEND: pd %d req_id %lld",
 				pd, apply_req.request_id);
 			if (dev->ops && dev->ops->apply_req) {
 				rc = dev->ops->apply_req(&apply_req);
@@ -404,7 +410,7 @@
 		}
 	}
 	if (rc < 0) {
-		CRM_ERR("APPLY FAILED pd %d req_id %lld",
+		CAM_ERR(CAM_CRM, "APPLY FAILED pd %d req_id %lld",
 			dev->dev_info.p_delay, apply_req.request_id);
 		/* Apply req failed notify already applied devs */
 		for (; i >= 0; i--) {
@@ -457,11 +463,12 @@
 	 */
 
 	rc = __cam_req_mgr_traverse(&traverse_data);
-	CRM_DBG("SOF: idx %d result %x pd_mask %x rc %d",
+	CAM_DBG(CAM_CRM, "SOF: idx %d result %x pd_mask %x rc %d",
 		idx, traverse_data.result, link->pd_mask, rc);
 
 	if (!rc && traverse_data.result == link->pd_mask) {
-		CRM_DBG("APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
+		CAM_DBG(CAM_CRM,
+			"APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
 			link->link_hdl, idx,
 			apply_data[2].req_id, apply_data[1].req_id,
 			apply_data[0].req_id);
@@ -498,12 +505,12 @@
 	 * - if in applied_state, somthign wrong.
 	 * - if in no_req state, no new req
 	 */
-	CRM_DBG("idx %d req_status %d",
+	CAM_DBG(CAM_CRM, "idx %d req_status %d",
 		in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
 
 	slot = &in_q->slot[in_q->rd_idx];
 	if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
-		CRM_DBG("No Pending req");
+		CAM_DBG(CAM_CRM, "No Pending req");
 		return 0;
 	}
 
@@ -517,7 +524,8 @@
 			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
 
 			if (link->state == CAM_CRM_LINK_STATE_ERR) {
-				CRM_WARN("Err recovery done idx %d status %d",
+				CAM_WARN(CAM_CRM,
+					"Err recovery done idx %d status %d",
 					in_q->rd_idx,
 					in_q->slot[in_q->rd_idx].status);
 				mutex_lock(&link->lock);
@@ -553,7 +561,8 @@
 			 *   don't expect to enter here.
 			 * @TODO: gracefully handle if recovery fails.
 			 */
-			CRM_ERR("FATAL recovery cant finish idx %d status %d",
+			CAM_ERR(CAM_CRM,
+				"FATAL recovery cant finish idx %d status %d",
 				in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
 			rc = -EPERM;
 		}
@@ -601,7 +610,7 @@
 		tbl->next = new_tbl;
 		tbl->pd_delta = tbl->pd - new_tbl->pd;
 	}
-	CRM_DBG("added pd %d tbl to link delta %d", new_tbl->pd,
+	CAM_DBG(CAM_CRM, "added pd %d tbl to link delta %d", new_tbl->pd,
 		new_tbl->pd_delta);
 }
 
@@ -620,7 +629,7 @@
 		kzalloc(sizeof(struct cam_req_mgr_req_tbl), GFP_KERNEL);
 	if (tbl != NULL) {
 		tbl->num_slots = MAX_REQ_SLOTS;
-		CRM_DBG("pd= %d slots= %d", delay, tbl->num_slots);
+		CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots);
 	}
 
 	return tbl;
@@ -637,7 +646,7 @@
 {
 	struct cam_req_mgr_req_tbl  *tbl = *l_tbl, *temp;
 
-	CRM_DBG("*l_tbl %pK", tbl);
+	CAM_DBG(CAM_CRM, "*l_tbl %pK", tbl);
 	while (tbl != NULL) {
 		temp = tbl->next;
 		kfree(tbl);
@@ -666,7 +675,7 @@
 	for (i = 0; i < in_q->num_slots; i++) {
 		slot = &in_q->slot[idx];
 		if (slot->req_id == req_id) {
-			CRM_DBG("req %lld found at %d %d status %d",
+			CAM_DBG(CAM_CRM, "req %lld found at %d %d status %d",
 				req_id, idx, slot->idx,
 				slot->status);
 			break;
@@ -694,7 +703,7 @@
 	struct cam_req_mgr_req_queue *in_q = req->in_q;
 
 	if (!in_q) {
-		CRM_ERR("NULL in_q");
+		CAM_ERR(CAM_CRM, "NULL in_q");
 		return -EINVAL;
 	}
 
@@ -729,7 +738,7 @@
 	struct cam_req_mgr_req_queue *in_q = req->in_q;
 
 	if (!in_q) {
-		CRM_ERR("NULL in_q");
+		CAM_ERR(CAM_CRM, "NULL in_q");
 		return -EINVAL;
 	}
 
@@ -758,11 +767,11 @@
 	struct cam_req_mgr_core_link *link = NULL;
 
 	if (!timer) {
-		CRM_ERR("NULL timer");
+		CAM_ERR(CAM_CRM, "NULL timer");
 		return;
 	}
 	link = (struct cam_req_mgr_core_link *)timer->parent;
-	CRM_ERR("SOF freeze for link %x", link->link_hdl);
+	CAM_ERR(CAM_CRM, "SOF freeze for link %x", link->link_hdl);
 }
 
 /**
@@ -859,12 +868,12 @@
 	struct cam_req_mgr_req_queue *in_q;
 
 	if (!session || !g_crm_core_dev) {
-		CRM_ERR("NULL session/core_dev ptr");
+		CAM_ERR(CAM_CRM, "NULL session/core_dev ptr");
 		return NULL;
 	}
 
 	if (session->num_links >= MAX_LINKS_PER_SESSION) {
-		CRM_ERR("Reached max links %d per session limit %d",
+		CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d",
 			session->num_links, MAX_LINKS_PER_SESSION);
 		return NULL;
 	}
@@ -872,7 +881,7 @@
 	link = (struct cam_req_mgr_core_link *)
 		kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
 	if (!link) {
-		CRM_ERR("failed to create link, no mem");
+		CAM_ERR(CAM_CRM, "failed to create link, no mem");
 		return NULL;
 	}
 	in_q = &session->in_q;
@@ -893,7 +902,7 @@
 	mutex_lock(&session->lock);
 	session->links[session->num_links] = link;
 	session->num_links++;
-	CRM_DBG("Active session links (%d)",
+	CAM_DBG(CAM_CRM, "Active session links (%d)",
 		session->num_links);
 	mutex_unlock(&session->lock);
 
@@ -915,14 +924,14 @@
 	int32_t   i = 0;
 
 	if (!session || !*link) {
-		CRM_ERR("NULL session/link ptr %pK %pK",
+		CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK",
 			session, *link);
 		return;
 	}
 
 	mutex_lock(&session->lock);
 	if (!session->num_links)
-		CRM_WARN("No active link or invalid state %d",
+		CAM_WARN(CAM_CRM, "No active link or invalid state %d",
 			session->num_links);
 	else {
 		for (i = 0; i < session->num_links; i++) {
@@ -930,7 +939,7 @@
 				session->links[i] = NULL;
 		}
 		session->num_links--;
-		CRM_DBG("Active session links (%d)",
+		CAM_DBG(CAM_CRM, "Active session links (%d)",
 			session->num_links);
 	}
 	kfree(*link);
@@ -959,7 +968,7 @@
 	struct cam_req_mgr_req_queue        *in_q = NULL;
 
 	if (!data || !priv) {
-		CRM_ERR("input args NULL %pK %pK", data, priv);
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -994,21 +1003,21 @@
 	struct crm_task_payload             *task_data = NULL;
 
 	if (!data || !priv) {
-		CRM_ERR("input args NULL %pK %pK", data, priv);
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
 		rc = -EINVAL;
 		goto end;
 	}
 	link = (struct cam_req_mgr_core_link *)priv;
 	task_data = (struct crm_task_payload *)data;
 	flush_info  = (struct cam_req_mgr_flush_info *)&task_data->u;
-	CRM_DBG("link_hdl %x req_id %lld type %d",
+	CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld type %d",
 		flush_info->link_hdl,
 		flush_info->req_id,
 		flush_info->flush_type);
 
 	in_q = link->req.in_q;
 
-	trace_cam_flush_req(flush_info);
+	trace_cam_flush_req(link, flush_info);
 
 	mutex_lock(&link->req.lock);
 	if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
@@ -1024,15 +1033,16 @@
 		CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
 		idx = __cam_req_mgr_find_slot_for_req(in_q, flush_info->req_id);
 		if (idx < 0) {
-			CRM_ERR("req_id %lld not found in input queue",
+			CAM_ERR(CAM_CRM, "req_id %lld not found in input queue",
 			flush_info->req_id);
 		} else {
-			CRM_DBG("req_id %lld found at idx %d",
+			CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
 				flush_info->req_id, idx);
 			slot = &in_q->slot[idx];
 			if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
 				slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
-				CRM_WARN("req_id %lld can not be cancelled",
+				CAM_WARN(CAM_CRM,
+					"req_id %lld can not be cancelled",
 					flush_info->req_id);
 				mutex_unlock(&link->req.lock);
 				return -EINVAL;
@@ -1078,14 +1088,14 @@
 	struct crm_task_payload          *task_data = NULL;
 
 	if (!data || !priv) {
-		CRM_ERR("input args NULL %pK %pK", data, priv);
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
 		rc = -EINVAL;
 		goto end;
 	}
 	link = (struct cam_req_mgr_core_link *)priv;
 	task_data = (struct crm_task_payload *)data;
 	sched_req  = (struct cam_req_mgr_sched_request *)&task_data->u;
-	CRM_DBG("link_hdl %x req_id %lld",
+	CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld",
 		sched_req->link_hdl,
 		sched_req->req_id);
 
@@ -1096,9 +1106,9 @@
 
 	if (slot->status != CRM_SLOT_STATUS_NO_REQ &&
 		slot->status != CRM_SLOT_STATUS_REQ_APPLIED)
-		CRM_WARN("in_q overwrite %d", slot->status);
+		CAM_WARN(CAM_CRM, "in_q overwrite %d", slot->status);
 
-	CRM_DBG("sched_req %lld at slot %d",
+	CAM_DBG(CAM_CRM, "sched_req %lld at slot %d",
 		sched_req->req_id, in_q->wr_idx);
 
 	slot->status = CRM_SLOT_STATUS_REQ_ADDED;
@@ -1133,7 +1143,7 @@
 	struct crm_task_payload             *task_data = NULL;
 
 	if (!data || !priv) {
-		CRM_ERR("input args NULL %pK %pK", data, priv);
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1150,7 +1160,7 @@
 		}
 	}
 	if (!tbl) {
-		CRM_ERR("dev_hdl not found %x, %x %x",
+		CAM_ERR(CAM_CRM, "dev_hdl not found %x, %x %x",
 			add_req->dev_hdl,
 			link->l_dev[0].dev_hdl,
 			link->l_dev[1].dev_hdl);
@@ -1168,7 +1178,7 @@
 	mutex_lock(&link->req.lock);
 	idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id);
 	if (idx < 0) {
-		CRM_ERR("req %lld not found in in_q", add_req->req_id);
+		CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id);
 		rc = -EBADSLT;
 		mutex_unlock(&link->req.lock);
 		goto end;
@@ -1176,19 +1186,21 @@
 	slot = &tbl->slot[idx];
 	if (slot->state != CRM_REQ_STATE_PENDING &&
 		slot->state != CRM_REQ_STATE_EMPTY) {
-		CRM_WARN("Unexpected state %d for slot %d map %x",
+		CAM_WARN(CAM_CRM, "Unexpected state %d for slot %d map %x",
 			slot->state, idx, slot->req_ready_map);
 	}
 
 	slot->state = CRM_REQ_STATE_PENDING;
 	slot->req_ready_map |= (1 << device->dev_bit);
 
-	CRM_DBG("idx %d dev_hdl %x req_id %lld pd %d ready_map %x",
+	CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x",
 		idx, add_req->dev_hdl, add_req->req_id, tbl->pd,
 		slot->req_ready_map);
 
+	trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
+
 	if (slot->req_ready_map == tbl->dev_mask) {
-		CRM_DBG("idx %d req_id %lld pd %d SLOT READY",
+		CAM_DBG(CAM_CRM, "idx %d req_id %lld pd %d SLOT READY",
 			idx, add_req->req_id, tbl->pd);
 		slot->state = CRM_REQ_STATE_READY;
 	}
@@ -1219,14 +1231,14 @@
 	struct crm_task_payload             *task_data = NULL;
 
 	if (!data || !priv) {
-		CRM_ERR("input args NULL %pK %pK", data, priv);
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
 		rc = -EINVAL;
 		goto end;
 	}
 	link = (struct cam_req_mgr_core_link *)priv;
 	task_data = (struct crm_task_payload *)data;
 	err_info  = (struct cam_req_mgr_error_notify *)&task_data->u;
-	CRM_DBG("link_hdl %x req_id %lld error %d",
+	CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld error %d",
 		err_info->link_hdl,
 		err_info->req_id,
 		err_info->error);
@@ -1237,20 +1249,22 @@
 	if (err_info->error == CRM_KMD_ERR_BUBBLE) {
 		idx = __cam_req_mgr_find_slot_for_req(in_q, err_info->req_id);
 		if (idx < 0) {
-			CRM_ERR("req_id %lld not found in input queue",
+			CAM_ERR(CAM_CRM, "req_id %lld not found in input queue",
 			err_info->req_id);
 		} else {
-			CRM_DBG("req_id %lld found at idx %d",
+			CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
 				err_info->req_id, idx);
 			slot = &in_q->slot[idx];
 			if (!slot->recover) {
-				CRM_WARN("err recovery disabled req_id %lld",
+				CAM_WARN(CAM_CRM,
+					"err recovery disabled req_id %lld",
 					err_info->req_id);
 				mutex_unlock(&link->req.lock);
 				return 0;
 			} else if (slot->status != CRM_SLOT_STATUS_REQ_PENDING
 			&& slot->status != CRM_SLOT_STATUS_REQ_APPLIED) {
-				CRM_WARN("req_id %lld can not be recovered %d",
+				CAM_WARN(CAM_CRM,
+					"req_id %lld can not be recovered %d",
 					err_info->req_id, slot->status);
 				mutex_unlock(&link->req.lock);
 				return -EINVAL;
@@ -1305,7 +1319,7 @@
 	struct crm_task_payload             *task_data = NULL;
 
 	if (!data || !priv) {
-		CRM_ERR("input args NULL %pK %pK", data, priv);
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1313,7 +1327,7 @@
 	task_data = (struct crm_task_payload *)data;
 	sof_data = (struct cam_req_mgr_sof_notify *)&task_data->u;
 
-	CRM_DBG("link_hdl %x frame_id %lld",
+	CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld",
 		sof_data->link_hdl,
 		sof_data->frame_id);
 
@@ -1324,11 +1338,11 @@
 	 * Check if current read index is in applied state, if yes make it free
 	 *    and increment read index to next slot.
 	 */
-	CRM_DBG("link_hdl %x curent idx %d req_status %d",
+	CAM_DBG(CAM_CRM, "link_hdl %x curent idx %d req_status %d",
 		link->link_hdl, in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
 
 	if (link->state == CAM_CRM_LINK_STATE_ERR)
-		CRM_WARN("Error recovery idx %d status %d",
+		CAM_WARN(CAM_CRM, "Error recovery idx %d status %d",
 			in_q->rd_idx,
 			in_q->slot[in_q->rd_idx].status);
 
@@ -1367,17 +1381,18 @@
 	struct crm_task_payload        *task_data;
 
 	if (!add_req) {
-		CRM_ERR("sof_data is NULL");
+		CAM_ERR(CAM_CRM, "sof_data is NULL");
 		rc = -EINVAL;
 		goto end;
 	}
 
-	CRM_DBG("E: dev %x dev req %lld", add_req->dev_hdl, add_req->req_id);
+	CAM_DBG(CAM_CRM, "E: dev %x dev req %lld",
+		add_req->dev_hdl, add_req->req_id);
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(add_req->link_hdl);
 
 	if (!link) {
-		CRM_DBG("link ptr NULL %x", add_req->link_hdl);
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", add_req->link_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1385,14 +1400,14 @@
 	/* Validate if req id is present in input queue */
 	idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id);
 	if (idx < 0) {
-		CRM_ERR("req %lld not found in in_q", add_req->req_id);
+		CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id);
 		rc = -ENOENT;
 		goto end;
 	}
 
 	task = cam_req_mgr_workq_get_task(link->workq);
 	if (!task) {
-		CRM_ERR("no empty task dev %x req %lld",
+		CAM_ERR(CAM_CRM, "no empty task dev %x req %lld",
 			add_req->dev_hdl, add_req->req_id);
 		rc = -EBUSY;
 		goto end;
@@ -1406,7 +1421,8 @@
 	dev_req->dev_hdl = add_req->dev_hdl;
 	task->process_cb = &cam_req_mgr_process_add_req;
 	rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
-	CRM_DBG("X: dev %x dev req %lld", add_req->dev_hdl, add_req->req_id);
+	CAM_DBG(CAM_CRM, "X: dev %x dev req %lld",
+		add_req->dev_hdl, add_req->req_id);
 
 end:
 	return rc;
@@ -1431,7 +1447,7 @@
 	struct crm_task_payload         *task_data;
 
 	if (!err_info) {
-		CRM_ERR("err_info is NULL");
+		CAM_ERR(CAM_CRM, "err_info is NULL");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1439,7 +1455,7 @@
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(err_info->link_hdl);
 	if (!link) {
-		CRM_DBG("link ptr NULL %x", err_info->link_hdl);
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1447,7 +1463,7 @@
 	crm_timer_reset(link->watchdog);
 	task = cam_req_mgr_workq_get_task(link->workq);
 	if (!task) {
-		CRM_ERR("no empty task req_id %lld", err_info->req_id);
+		CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id);
 		rc = -EBUSY;
 		goto end;
 	}
@@ -1485,7 +1501,7 @@
 	struct crm_task_payload         *task_data;
 
 	if (!sof_data) {
-		CRM_ERR("sof_data is NULL");
+		CAM_ERR(CAM_CRM, "sof_data is NULL");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1493,7 +1509,7 @@
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(sof_data->link_hdl);
 	if (!link) {
-		CRM_DBG("link ptr NULL %x", sof_data->link_hdl);
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", sof_data->link_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1501,7 +1517,8 @@
 	crm_timer_reset(link->watchdog);
 	task = cam_req_mgr_workq_get_task(link->workq);
 	if (!task) {
-		CRM_ERR("no empty task frame %lld", sof_data->frame_id);
+		CAM_ERR(CAM_CRM, "no empty task frame %lld",
+			sof_data->frame_id);
 		rc = -EBUSY;
 		goto end;
 	}
@@ -1548,7 +1565,7 @@
 		return -EPERM;
 
 	mutex_init(&link->req.lock);
-	CRM_DBG("LOCK_DBG in_q lock %pK", &link->req.lock);
+	CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
 	link->req.num_tbl = 0;
 
 	rc = __cam_req_mgr_setup_in_q(&link->req);
@@ -1565,7 +1582,7 @@
 		if (!dev->ops ||
 			!dev->ops->get_dev_info ||
 			!dev->ops->link_setup) {
-			CRM_ERR("FATAL: device ops NULL");
+			CAM_ERR(CAM_CRM, "FATAL: device ops NULL");
 			rc = -ENXIO;
 			goto error;
 		}
@@ -1573,7 +1590,10 @@
 		dev->parent = (void *)link;
 		dev->dev_info.dev_hdl = dev->dev_hdl;
 		rc = dev->ops->get_dev_info(&dev->dev_info);
-		CRM_DBG("%x: connected: %s, id %d, delay %d",
+
+		trace_cam_req_mgr_connect_device(link, &dev->dev_info);
+
+		CAM_DBG(CAM_CRM, "%x: connected: %s, id %d, delay %d",
 			link_info->session_hdl, dev->dev_info.name,
 			dev->dev_info.dev_id, dev->dev_info.p_delay);
 		if (rc < 0 ||
@@ -1581,10 +1601,10 @@
 			CAM_PIPELINE_DELAY_MAX ||
 			dev->dev_info.p_delay <
 			CAM_PIPELINE_DELAY_0) {
-			CRM_ERR("get device info failed");
+			CAM_ERR(CAM_CRM, "get device info failed");
 			goto error;
 		} else {
-			CRM_DBG("%x: connected: %s, delay %d",
+			CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
 				link_info->session_hdl,
 				dev->dev_info.name,
 				dev->dev_info.p_delay);
@@ -1613,7 +1633,7 @@
 			pd_tbl = __cam_req_mgr_find_pd_tbl(link->req.l_tbl,
 				dev->dev_info.p_delay);
 			if (!pd_tbl) {
-				CRM_ERR("pd %d tbl not found",
+				CAM_ERR(CAM_CRM, "pd %d tbl not found",
 					dev->dev_info.p_delay);
 				rc = -ENXIO;
 				goto error;
@@ -1622,7 +1642,7 @@
 			pd_tbl = __cam_req_mgr_create_pd_tbl(
 				dev->dev_info.p_delay);
 			if (pd_tbl == NULL) {
-				CRM_ERR("create new pd tbl failed");
+				CAM_ERR(CAM_CRM, "create new pd tbl failed");
 				rc = -ENXIO;
 				goto error;
 			}
@@ -1669,7 +1689,7 @@
 	struct cam_req_mgr_core_session *cam_session = NULL;
 
 	if (!ses_info) {
-		CRM_DBG("NULL session info pointer");
+		CAM_DBG(CAM_CRM, "NULL session info pointer");
 		return -EINVAL;
 	}
 	mutex_lock(&g_crm_core_dev->crm_lock);
@@ -1682,7 +1702,8 @@
 
 	session_hdl = cam_create_session_hdl((void *)cam_session);
 	if (session_hdl < 0) {
-		CRM_ERR("unable to create session_hdl = %x", session_hdl);
+		CAM_ERR(CAM_CRM, "unable to create session_hdl = %x",
+			session_hdl);
 		rc = session_hdl;
 		kfree(cam_session);
 		goto end;
@@ -1690,7 +1711,7 @@
 	ses_info->session_hdl = session_hdl;
 
 	mutex_init(&cam_session->lock);
-	CRM_DBG("LOCK_DBG session lock %pK", &cam_session->lock);
+	CAM_DBG(CAM_CRM, "LOCK_DBG session lock %pK", &cam_session->lock);
 
 	mutex_lock(&cam_session->lock);
 	cam_session->session_hdl = session_hdl;
@@ -1709,7 +1730,7 @@
 	struct cam_req_mgr_core_session *cam_session = NULL;
 
 	if (!ses_info) {
-		CRM_DBG("NULL session info pointer");
+		CAM_DBG(CAM_CRM, "NULL session info pointer");
 		return -EINVAL;
 	}
 
@@ -1717,14 +1738,14 @@
 	cam_session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(ses_info->session_hdl);
 	if (!cam_session) {
-		CRM_ERR("failed to get session priv");
+		CAM_ERR(CAM_CRM, "failed to get session priv");
 		rc = -ENOENT;
 		goto end;
 
 	}
 	mutex_lock(&cam_session->lock);
 	if (cam_session->num_links) {
-		CRM_ERR("destroy session %x num_active_links %d",
+		CAM_ERR(CAM_CRM, "destroy session %x num_active_links %d",
 			ses_info->session_hdl,
 			cam_session->num_links);
 		/* @TODO : Go through active links and destroy ? */
@@ -1736,7 +1757,7 @@
 
 	rc = cam_destroy_session_hdl(ses_info->session_hdl);
 	if (rc < 0)
-		CRM_ERR("unable to destroy session_hdl = %x rc %d",
+		CAM_ERR(CAM_CRM, "unable to destroy session_hdl = %x rc %d",
 			ses_info->session_hdl, rc);
 
 end:
@@ -1753,11 +1774,12 @@
 	struct cam_req_mgr_core_link           *link;
 
 	if (!link_info) {
-		CRM_DBG("NULL pointer");
+		CAM_DBG(CAM_CRM, "NULL pointer");
 		return -EINVAL;
 	}
 	if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) {
-		CRM_ERR("Invalid num devices %d", link_info->num_devices);
+		CAM_ERR(CAM_CRM, "Invalid num devices %d",
+			link_info->num_devices);
 		return -EINVAL;
 	}
 
@@ -1765,7 +1787,7 @@
 	cam_session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(link_info->session_hdl);
 	if (!cam_session) {
-		CRM_DBG("NULL pointer");
+		CAM_DBG(CAM_CRM, "NULL pointer");
 		return -EINVAL;
 	}
 
@@ -1774,11 +1796,11 @@
 	/* Allocate link struct and map it with session's request queue */
 	link = __cam_req_mgr_reserve_link(cam_session);
 	if (!link) {
-		CRM_ERR("failed to reserve new link");
+		CAM_ERR(CAM_CRM, "failed to reserve new link");
 		mutex_unlock(&g_crm_core_dev->crm_lock);
 		return -EINVAL;
 	}
-	CRM_DBG("link reserved %pK %x", link, link->link_hdl);
+	CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
 
 	memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
 	root_dev.session_hdl = link_info->session_hdl;
@@ -1788,7 +1810,8 @@
 	/* Create unique dev handle for link */
 	link->link_hdl = cam_create_device_hdl(&root_dev);
 	if (link->link_hdl < 0) {
-		CRM_ERR("Insufficient memory to create new device handle");
+		CAM_ERR(CAM_CRM,
+			"Insufficient memory to create new device handle");
 		mutex_unlock(&link->lock);
 		rc = link->link_hdl;
 		goto link_hdl_fail;
@@ -1800,7 +1823,8 @@
 	rc = __cam_req_mgr_create_subdevs(&link->l_dev,
 		link_info->num_devices);
 	if (rc < 0) {
-		CRM_ERR("Insufficient memory to create new crm subdevs");
+		CAM_ERR(CAM_CRM,
+			"Insufficient memory to create new crm subdevs");
 		goto create_subdev_failed;
 	}
 
@@ -1819,7 +1843,7 @@
 	rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
 		&link->workq, CRM_WORKQ_USAGE_NON_IRQ);
 	if (rc < 0) {
-		CRM_ERR("FATAL: unable to create worker");
+		CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
 		__cam_req_mgr_destroy_link_info(link);
 		goto setup_failed;
 	}
@@ -1865,18 +1889,18 @@
 	struct cam_req_mgr_core_link    *link;
 
 	if (!unlink_info) {
-		CRM_ERR("NULL pointer");
+		CAM_ERR(CAM_CRM, "NULL pointer");
 		return -EINVAL;
 	}
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
-	CRM_DBG("link_hdl %x", unlink_info->link_hdl);
+	CAM_DBG(CAM_CRM, "link_hdl %x", unlink_info->link_hdl);
 
 	/* session hdl's priv data is cam session struct */
 	cam_session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(unlink_info->session_hdl);
 	if (!cam_session) {
-		CRM_ERR("NULL pointer");
+		CAM_ERR(CAM_CRM, "NULL pointer");
 		mutex_unlock(&g_crm_core_dev->crm_lock);
 		return -EINVAL;
 	}
@@ -1884,7 +1908,7 @@
 	/* link hdl's priv data is core_link struct */
 	link = cam_get_device_priv(unlink_info->link_hdl);
 	if (!link) {
-		CRM_ERR("NULL pointer");
+		CAM_ERR(CAM_CRM, "NULL pointer");
 		mutex_unlock(&g_crm_core_dev->crm_lock);
 		return -EINVAL;
 	}
@@ -1908,7 +1932,7 @@
 	/* Destroy the link handle */
 	rc = cam_destroy_device_hdl(unlink_info->link_hdl);
 	if (rc < 0) {
-		CRM_ERR("error while destroying dev handle %d %x",
+		CAM_ERR(CAM_CRM, "error while destroying dev handle %d %x",
 			rc, link->link_hdl);
 	}
 
@@ -1929,7 +1953,7 @@
 	struct crm_task_payload           task_data;
 
 	if (!sched_req) {
-		CRM_ERR("csl_req is NULL");
+		CAM_ERR(CAM_CRM, "csl_req is NULL");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -1937,15 +1961,16 @@
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(sched_req->link_hdl);
 	if (!link) {
-		CRM_DBG("link ptr NULL %x", sched_req->link_hdl);
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", sched_req->link_hdl);
 		return -EINVAL;
 	}
 	session = (struct cam_req_mgr_core_session *)link->parent;
 	if (!session) {
-		CRM_WARN("session ptr NULL %x", sched_req->link_hdl);
+		CAM_WARN(CAM_CRM, "session ptr NULL %x", sched_req->link_hdl);
 		return -EINVAL;
 	}
-	CRM_DBG("link %x req %lld", sched_req->link_hdl, sched_req->req_id);
+	CAM_DBG(CAM_CRM, "link %x req %lld",
+		sched_req->link_hdl, sched_req->req_id);
 
 	task_data.type = CRM_WORKQ_TASK_SCHED_REQ;
 	sched = (struct cam_req_mgr_sched_request *)&task_data.u;
@@ -1960,7 +1985,8 @@
 
 	rc = cam_req_mgr_process_sched_req(link, &task_data);
 
-	CRM_DBG("DONE dev %x req %lld", sched_req->link_hdl, sched_req->req_id);
+	CAM_DBG(CAM_CRM, "DONE dev %x req %lld",
+		sched_req->link_hdl, sched_req->req_id);
 end:
 	return rc;
 }
@@ -1969,7 +1995,7 @@
 	struct cam_req_mgr_sync_mode *sync_links)
 {
 	if (!sync_links) {
-		CRM_ERR("NULL pointer");
+		CAM_ERR(CAM_CRM, "NULL pointer");
 		return -EINVAL;
 	}
 
@@ -1988,12 +2014,13 @@
 	struct cam_req_mgr_core_session  *session = NULL;
 
 	if (!flush_info) {
-		CRM_ERR("flush req is NULL");
+		CAM_ERR(CAM_CRM, "flush req is NULL");
 		rc = -EFAULT;
 		goto end;
 	}
 	if (flush_info->flush_type >= CAM_REQ_MGR_FLUSH_TYPE_MAX) {
-		CRM_ERR("incorrect flush type %x", flush_info->flush_type);
+		CAM_ERR(CAM_CRM, "incorrect flush type %x",
+			flush_info->flush_type);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -2002,12 +2029,12 @@
 	session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(flush_info->session_hdl);
 	if (!session) {
-		CRM_ERR("Invalid session %x", flush_info->session_hdl);
+		CAM_ERR(CAM_CRM, "Invalid session %x", flush_info->session_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
 	if (session->num_links <= 0) {
-		CRM_WARN("No active links in session %x",
+		CAM_WARN(CAM_CRM, "No active links in session %x",
 		flush_info->session_hdl);
 		goto end;
 	}
@@ -2015,7 +2042,7 @@
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(flush_info->link_hdl);
 	if (!link) {
-		CRM_DBG("link ptr NULL %x", flush_info->link_hdl);
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", flush_info->link_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
@@ -2047,10 +2074,10 @@
 
 int cam_req_mgr_core_device_init(void)
 {
-	CRM_DBG("Enter g_crm_core_dev %pK", g_crm_core_dev);
+	CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
 
 	if (g_crm_core_dev) {
-		CRM_WARN("core device is already initialized");
+		CAM_WARN(CAM_CRM, "core device is already initialized");
 		return 0;
 	}
 	g_crm_core_dev = (struct cam_req_mgr_core_device *)
@@ -2058,7 +2085,7 @@
 	if (!g_crm_core_dev)
 		return -ENOMEM;
 
-	CRM_DBG("g_crm_core_dev %pK", g_crm_core_dev);
+	CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev);
 	INIT_LIST_HEAD(&g_crm_core_dev->session_head);
 	mutex_init(&g_crm_core_dev->crm_lock);
 	cam_req_mgr_debug_register(g_crm_core_dev);
@@ -2069,11 +2096,11 @@
 int cam_req_mgr_core_device_deinit(void)
 {
 	if (!g_crm_core_dev) {
-		CRM_ERR("NULL pointer");
+		CAM_ERR(CAM_CRM, "NULL pointer");
 		return -EINVAL;
 	}
 
-	CRM_DBG("g_crm_core_dev %pK", g_crm_core_dev);
+	CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev);
 	mutex_destroy(&g_crm_core_dev->crm_lock);
 	kfree(g_crm_core_dev);
 	g_crm_core_dev = NULL;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core_defs.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core_defs.h
index 2a831e8..f61c41e 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core_defs.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core_defs.h
@@ -25,30 +25,5 @@
 
 #define CRM_GET_REQ_ID(in_q, idx) in_q->slot[idx].req_id
 
-#if (CRM_TRACE_ENABLE == 1)
-	#define CRM_DBG(fmt, args...) do { \
-	trace_printk("%d: [crm_dbg] "fmt"\n", __LINE__, ##args); \
-	pr_debug("%s:%d "fmt"\n", __func__, __LINE__, ##args); \
-	} while (0)
-
-	#define CRM_WARN(fmt, args...) do { \
-	trace_printk("%d: [crm_warn] "fmt"\n", __LINE__, ##args); \
-	pr_warn("%s:%d "fmt"\n", __func__, __LINE__, ##args); \
-	} while (0)
-
-	#define CRM_ERR(fmt, args...) do { \
-	trace_printk("%d: [crm_err] "fmt"\n", __LINE__, ##args); \
-	pr_err("%s:%d "fmt"\n", __func__, __LINE__, ##args);\
-	} while (0)
-#else
-	#define CRM_DBG(fmt, args...) pr_debug("%s:%d "fmt"\n", \
-	__func__, __LINE__, ##args)
-
-	#define CRM_WARN(fmt, args...) pr_warn("%s:%d "fmt"\n", \
-	__func__, __LINE__, ##args)
-
-	#define CRM_ERR(fmt, args...) pr_err("%s:%d "fmt"\n", \
-	__func__, __LINE__, ##args)
-#endif
 #endif
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
index c495088..7a2bc09 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-REQ-MGR %s:%d " fmt, __func__, __LINE__
-
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
@@ -26,6 +24,7 @@
 #include "cam_req_mgr_core.h"
 #include "cam_subdev.h"
 #include "cam_mem_mgr.h"
+#include "cam_debug_util.h"
 
 #define CAM_REQ_MGR_EVENT_MAX 30
 
@@ -108,7 +107,7 @@
 
 	rc = v4l2_fh_open(filep);
 	if (rc) {
-		pr_err("v4l2_fh_open failed: %d\n", rc);
+		CAM_ERR(CAM_CRM, "v4l2_fh_open failed: %d", rc);
 		goto end;
 	}
 
@@ -120,7 +119,7 @@
 	rc = cam_mem_mgr_init();
 	if (rc) {
 		g_dev.open_cnt--;
-		pr_err("mem mgr init failed\n");
+		CAM_ERR(CAM_CRM, "mem mgr init failed");
 		goto mem_mgr_init_fail;
 	}
 
@@ -507,19 +506,20 @@
 	int rc;
 
 	if (g_dev.state != true) {
-		pr_err("camera root device not ready yet");
+		CAM_ERR(CAM_CRM, "camera root device not ready yet");
 		return -ENODEV;
 	}
 
 	if (!csd || !csd->name) {
-		pr_err("invalid arguments");
+		CAM_ERR(CAM_CRM, "invalid arguments");
 		return -EINVAL;
 	}
 
 	mutex_lock(&g_dev.dev_lock);
 	if ((g_dev.subdev_nodes_created) &&
 		(csd->sd_flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) {
-		pr_err("dynamic node is not allowed, name: %s, type : %d",
+		CAM_ERR(CAM_CRM,
+			"dynamic node is not allowed, name: %s, type :%d",
 			csd->name, csd->ent_function);
 		rc = -EINVAL;
 		goto reg_fail;
@@ -538,7 +538,7 @@
 
 	rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd);
 	if (rc) {
-		pr_err("register subdev failed");
+		CAM_ERR(CAM_CRM, "register subdev failed");
 		goto reg_fail;
 	}
 	g_dev.count++;
@@ -552,7 +552,7 @@
 int cam_unregister_subdev(struct cam_subdev *csd)
 {
 	if (g_dev.state != true) {
-		pr_err("camera root device not ready yet");
+		CAM_ERR(CAM_CRM, "camera root device not ready yet");
 		return -ENODEV;
 	}
 
@@ -603,19 +603,19 @@
 
 	rc = cam_req_mgr_util_init();
 	if (rc) {
-		pr_err("cam req mgr util init is failed\n");
+		CAM_ERR(CAM_CRM, "cam req mgr util init is failed");
 		goto req_mgr_util_fail;
 	}
 
 	rc = cam_mem_mgr_init();
 	if (rc) {
-		pr_err("mem mgr init failed\n");
+		CAM_ERR(CAM_CRM, "mem mgr init failed");
 		goto mem_mgr_init_fail;
 	}
 
 	rc = cam_req_mgr_core_device_init();
 	if (rc) {
-		pr_err("core device setup failed\n");
+		CAM_ERR(CAM_CRM, "core device setup failed");
 		goto req_mgr_core_fail;
 	}
 
@@ -663,7 +663,7 @@
 		return -EINVAL;
 
 	if (g_dev.state != true) {
-		pr_err("camera root device not ready yet");
+		CAM_ERR(CAM_CRM, "camera root device not ready yet");
 		return -ENODEV;
 	}
 
@@ -675,7 +675,7 @@
 
 	rc = v4l2_device_register_subdev_nodes(g_dev.v4l2_dev);
 	if (rc) {
-		pr_err("failed to register the sub devices");
+		CAM_ERR(CAM_CRM, "failed to register the sub devices");
 		goto create_fail;
 	}
 
@@ -683,7 +683,7 @@
 		if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
 			continue;
 		sd->entity.name = video_device_node_name(sd->devnode);
-		pr_debug("created node :%s\n", sd->entity.name);
+		CAM_DBG(CAM_CRM, "created node :%s", sd->entity.name);
 	}
 
 	g_dev.subdev_nodes_created = true;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
index 91860f6..8faf35a 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
@@ -196,9 +196,9 @@
  * @error    : what error device hit while processing this req
  */
 struct cam_req_mgr_error_notify {
-	int32_t link_hdl;
-	int32_t dev_hdl;
-	int64_t req_id;
+	int32_t  link_hdl;
+	int32_t  dev_hdl;
+	uint64_t req_id;
 	enum cam_req_mgr_device_error error;
 };
 
@@ -210,9 +210,9 @@
  *
  */
 struct cam_req_mgr_add_request {
-	int32_t link_hdl;
-	int32_t dev_hdl;
-	int64_t req_id;
+	int32_t  link_hdl;
+	int32_t  dev_hdl;
+	uint64_t req_id;
 };
 
 
@@ -260,7 +260,7 @@
 struct cam_req_mgr_apply_request {
 	int32_t    link_hdl;
 	int32_t    dev_hdl;
-	int64_t    request_id;
+	uint64_t   request_id;
 	int32_t    report_if_bubble;
 };
 
@@ -276,7 +276,7 @@
 	int32_t     link_hdl;
 	int32_t     dev_hdl;
 	uint32_t    type;
-	int64_t     req_id;
+	uint64_t    req_id;
 };
 
 /**
@@ -286,9 +286,9 @@
  *
  */
 struct cam_req_mgr_link_evt_data {
-	int32_t link_hdl;
-	int32_t dev_hdl;
-	int64_t req_id;
+	int32_t  link_hdl;
+	int32_t  dev_hdl;
+	uint64_t req_id;
 
 	enum cam_req_mgr_link_evt_type evt_type;
 	union {
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c
index 9da445d..2aa2ab1 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c
@@ -11,12 +11,13 @@
  */
 
 #include "cam_req_mgr_timer.h"
+#include "cam_debug_util.h"
 
 void crm_timer_reset(struct cam_req_mgr_timer *crm_timer)
 {
 	if (!crm_timer)
 		return;
-	CRM_DBG("Starting timer to fire in %d ms. (jiffies=%lu)\n",
+	CAM_DBG(CAM_CRM, "Starting timer to fire in %d ms. (jiffies=%lu)\n",
 		crm_timer->expires, jiffies);
 	mod_timer(&crm_timer->sys_timer,
 		(jiffies + msecs_to_jiffies(crm_timer->expires)));
@@ -27,17 +28,17 @@
 	struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
 
 	if (!timer) {
-		CRM_ERR("NULL timer");
+		CAM_ERR(CAM_CRM, "NULL timer");
 		return;
 	}
-	CRM_DBG("timer %pK parent %pK", timer, timer->parent);
+	CAM_DBG(CAM_CRM, "timer %pK parent %pK", timer, timer->parent);
 	crm_timer_reset(timer);
 }
 
 void crm_timer_modify(struct cam_req_mgr_timer *crm_timer,
 	int32_t expires)
 {
-	CRM_DBG("new time %d", expires);
+	CAM_DBG(CAM_CRM, "new time %d", expires);
 	if (crm_timer) {
 		crm_timer->expires = expires;
 		crm_timer_reset(crm_timer);
@@ -50,7 +51,7 @@
 	int                       ret = 0;
 	struct cam_req_mgr_timer *crm_timer = NULL;
 
-	CRM_DBG("init timer %d %pK", expires, *timer);
+	CAM_DBG(CAM_CRM, "init timer %d %pK", expires, *timer);
 	if (*timer == NULL) {
 		crm_timer = (struct cam_req_mgr_timer *)
 			kzalloc(sizeof(struct cam_req_mgr_timer), GFP_KERNEL);
@@ -71,7 +72,7 @@
 		crm_timer_reset(crm_timer);
 		*timer = crm_timer;
 	} else {
-		CRM_WARN("Timer already exists!!");
+		CAM_WARN(CAM_CRM, "Timer already exists!!");
 		ret = -EINVAL;
 	}
 end:
@@ -79,7 +80,7 @@
 }
 void crm_timer_exit(struct cam_req_mgr_timer **crm_timer)
 {
-	CRM_DBG("destroy timer %pK", *crm_timer);
+	CAM_DBG(CAM_CRM, "destroy timer %pK", *crm_timer);
 	if (*crm_timer) {
 		del_timer(&(*crm_timer)->sys_timer);
 		kfree(*crm_timer);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
index 38048d5..a9134fb 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
@@ -20,12 +20,7 @@
 #include <linux/random.h>
 #include <media/cam_req_mgr.h>
 #include "cam_req_mgr_util.h"
-
-#ifdef CONFIG_CAM_REQ_MGR_UTIL_DEBUG
-#define CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
+#include "cam_debug_util.h"
 
 static struct cam_req_mgr_util_hdl_tbl *hdl_tbl;
 static DEFINE_SPINLOCK(hdl_tbl_lock);
@@ -38,7 +33,7 @@
 
 	if (hdl_tbl) {
 		rc = -EINVAL;
-		pr_err("Hdl_tbl is already present\n");
+		CAM_ERR(CAM_CRM, "Hdl_tbl is already present");
 		goto hdl_tbl_check_failed;
 	}
 
@@ -79,7 +74,7 @@
 {
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
@@ -99,14 +94,14 @@
 
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
 	for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) {
 		if (hdl_tbl->hdl[i].state == HDL_ACTIVE) {
-			pr_err("Dev handle = %x session_handle = %x\n",
+			CAM_ERR(CAM_CRM, "Dev handle = %x session_handle = %x",
 				hdl_tbl->hdl[i].hdl_value,
 				hdl_tbl->hdl[i].session_hdl);
 			hdl_tbl->hdl[i].state = HDL_FREE;
@@ -141,14 +136,14 @@
 
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
 	idx = cam_get_free_handle_index();
 	if (idx < 0) {
-		pr_err("Unable to create session handle\n");
+		CAM_ERR(CAM_CRM, "Unable to create session handle");
 		spin_unlock_bh(&hdl_tbl_lock);
 		return idx;
 	}
@@ -174,14 +169,14 @@
 
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
 	idx = cam_get_free_handle_index();
 	if (idx < 0) {
-		pr_err("Unable to create device handle\n");
+		CAM_ERR(CAM_CRM, "Unable to create device handle");
 		spin_unlock_bh(&hdl_tbl_lock);
 		return idx;
 	}
@@ -196,7 +191,7 @@
 	hdl_tbl->hdl[idx].ops = hdl_data->ops;
 	spin_unlock_bh(&hdl_tbl_lock);
 
-	pr_debug("%s: handle = %x\n", __func__, handle);
+	pr_debug("%s: handle = %x", __func__, handle);
 	return handle;
 }
 
@@ -208,29 +203,29 @@
 
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		goto device_priv_fail;
 	}
 
 	idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
 	if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
-		pr_err("Invalid idx\n");
+		CAM_ERR(CAM_CRM, "Invalid idx");
 		goto device_priv_fail;
 	}
 
 	if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) {
-		pr_err("Invalid state\n");
+		CAM_ERR(CAM_CRM, "Invalid state");
 		goto device_priv_fail;
 	}
 
 	type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
 	if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) {
-		pr_err("Invalid type\n");
+		CAM_ERR(CAM_CRM, "Invalid type");
 		goto device_priv_fail;
 	}
 
 	if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) {
-		pr_err("Invalid hdl\n");
+		CAM_ERR(CAM_CRM, "Invalid hdl");
 		goto device_priv_fail;
 	}
 
@@ -252,29 +247,29 @@
 
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		goto device_ops_fail;
 	}
 
 	idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
 	if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
-		pr_err("Invalid idx\n");
+		CAM_ERR(CAM_CRM, "Invalid idx");
 		goto device_ops_fail;
 	}
 
 	if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) {
-		pr_err("Invalid state\n");
+		CAM_ERR(CAM_CRM, "Invalid state");
 		goto device_ops_fail;
 	}
 
 	type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
 	if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) {
-		pr_err("Invalid type\n");
+		CAM_ERR(CAM_CRM, "Invalid type");
 		goto device_ops_fail;
 	}
 
 	if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) {
-		pr_err("Invalid hdl\n");
+		CAM_ERR(CAM_CRM, "Invalid hdl");
 		goto device_ops_fail;
 	}
 
@@ -295,29 +290,29 @@
 
 	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
-		pr_err("Hdl tbl is NULL\n");
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
 		goto destroy_hdl_fail;
 	}
 
 	idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
 	if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
-		pr_err("Invalid idx\n");
+		CAM_ERR(CAM_CRM, "Invalid idx");
 		goto destroy_hdl_fail;
 	}
 
 	if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) {
-		pr_err("Invalid state\n");
+		CAM_ERR(CAM_CRM, "Invalid state");
 		goto destroy_hdl_fail;
 	}
 
 	type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
 	if (type != dev_hdl_type) {
-		pr_err("Invalid type %d, %d\n", type, dev_hdl_type);
+		CAM_ERR(CAM_CRM, "Invalid type %d, %d", type, dev_hdl_type);
 		goto destroy_hdl_fail;
 	}
 
 	if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) {
-		pr_err("Invalid hdl\n");
+		CAM_ERR(CAM_CRM, "Invalid hdl");
 		goto destroy_hdl_fail;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index 38dcb42..c48a391 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -11,6 +11,7 @@
  */
 
 #include "cam_req_mgr_workq.h"
+#include "cam_debug_util.h"
 
 #define WORKQ_ACQUIRE_LOCK(workq, flags) {\
 	if ((workq)->in_irq) \
@@ -84,7 +85,7 @@
 	if (task->process_cb)
 		task->process_cb(task->priv, task->payload);
 	else
-		CRM_WARN("FATAL:no task handler registered for workq");
+		CAM_WARN(CAM_CRM, "FATAL:no task handler registered for workq");
 	cam_req_mgr_workq_put_task(task);
 
 	return 0;
@@ -100,7 +101,7 @@
 	struct crm_workq_task         *task, *task_save;
 	int32_t                        i = CRM_TASK_PRIORITY_0;
 	if (!w) {
-		CRM_ERR("NULL task pointer can not schedule");
+		CAM_ERR(CAM_CRM, "NULL task pointer can not schedule");
 		return;
 	}
 	workq = (struct cam_req_mgr_core_workq *)
@@ -113,7 +114,7 @@
 				atomic_sub(1, &workq->task.pending_cnt);
 				cam_req_mgr_process_task(task);
 			}
-			CRM_DBG("processed task %pK free_cnt %d",
+			CAM_DBG(CAM_CRM, "processed task %pK free_cnt %d",
 				task, atomic_read(&workq->task.free_cnt));
 		}
 		i++;
@@ -125,7 +126,7 @@
 	int32_t                 i = CRM_TASK_PRIORITY_0;
 	struct crm_workq_task  *task, *task_save;
 
-	CRM_DBG("pending_cnt %d",
+	CAM_DBG(CAM_CRM, "pending_cnt %d",
 		atomic_read(&workq->task.pending_cnt));
 
 	while (i < CRM_TASK_PRIORITY_MAX) {
@@ -133,7 +134,7 @@
 			list_for_each_entry_safe(task, task_save,
 				&workq->task.process_head[i], entry) {
 				cam_req_mgr_workq_put_task(task);
-				CRM_WARN("flush task %pK, %d, cnt %d",
+				CAM_WARN(CAM_CRM, "flush task %pK, %d, cnt %d",
 					task, i, atomic_read(
 					&workq->task.free_cnt));
 			}
@@ -150,13 +151,13 @@
 	unsigned long flags = 0;
 
 	if (!task) {
-		CRM_WARN("NULL task pointer can not schedule");
+		CAM_WARN(CAM_CRM, "NULL task pointer can not schedule");
 		rc = -EINVAL;
 		goto end;
 	}
 	workq = (struct cam_req_mgr_core_workq *)task->parent;
 	if (!workq) {
-		CRM_DBG("NULL workq pointer suspect mem corruption");
+		CAM_DBG(CAM_CRM, "NULL workq pointer suspect mem corruption");
 		rc = -EINVAL;
 		goto end;
 	}
@@ -167,7 +168,7 @@
 
 	if (task->cancel == 1) {
 		cam_req_mgr_workq_put_task(task);
-		CRM_WARN("task aborted and queued back to pool");
+		CAM_WARN(CAM_CRM, "task aborted and queued back to pool");
 		rc = 0;
 		goto end;
 	}
@@ -182,7 +183,7 @@
 	WORKQ_RELEASE_LOCK(workq, flags);
 
 	atomic_add(1, &workq->task.pending_cnt);
-	CRM_DBG("enq task %pK pending_cnt %d",
+	CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d",
 		task, atomic_read(&workq->task.pending_cnt));
 
 	queue_work(workq->job, &workq->work);
@@ -207,7 +208,7 @@
 			return -ENOMEM;
 
 		strlcat(buf, name, sizeof(buf));
-		CRM_DBG("create workque crm_workq-%s", name);
+		CAM_DBG(CAM_CRM, "create workque crm_workq-%s", name);
 		crm_workq->job = alloc_workqueue(buf,
 			WQ_HIGHPRI | WQ_UNBOUND, 0, NULL);
 		if (!crm_workq->job) {
@@ -218,7 +219,7 @@
 		/* Workq attributes initialization */
 		INIT_WORK(&crm_workq->work, cam_req_mgr_process_workq);
 		spin_lock_init(&crm_workq->lock_bh);
-		CRM_DBG("LOCK_DBG workq %s lock %pK",
+		CAM_DBG(CAM_CRM, "LOCK_DBG workq %s lock %pK",
 			name, &crm_workq->lock_bh);
 
 		/* Task attributes initialization */
@@ -234,7 +235,7 @@
 				crm_workq->task.num_task,
 				GFP_KERNEL);
 		if (!crm_workq->task.pool) {
-			CRM_WARN("Insufficient memory %lu",
+			CAM_WARN(CAM_CRM, "Insufficient memory %lu",
 				sizeof(struct crm_workq_task) *
 				crm_workq->task.num_task);
 			kfree(crm_workq);
@@ -250,7 +251,7 @@
 			cam_req_mgr_workq_put_task(task);
 		}
 		*workq = crm_workq;
-		CRM_DBG("free tasks %d",
+		CAM_DBG(CAM_CRM, "free tasks %d",
 			atomic_read(&crm_workq->task.free_cnt));
 	}
 
@@ -259,7 +260,7 @@
 
 void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq)
 {
-	CRM_DBG("destroy workque %pK", crm_workq);
+	CAM_DBG(CAM_CRM, "destroy workque %pK", crm_workq);
 	if (*crm_workq) {
 		crm_workq_clear_q(*crm_workq);
 		if ((*crm_workq)->job) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
index e515a40..b66480c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
@@ -4,3 +4,5 @@
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index 37dbf9e..18097b0 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -23,7 +23,7 @@
 	struct cam_cmd_i2c_info *i2c_info;
 
 	if (!a_ctrl || !cmd_buf) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -32,8 +32,8 @@
 		i2c_info->i2c_freq_mode;
 	a_ctrl->io_master_info.cci_client->sid =
 		i2c_info->slave_addr >> 1;
-	CDBG("%s:%d Slave addr: 0x%x Freq Mode: %d\n", __func__,
-		__LINE__, i2c_info->slave_addr, i2c_info->i2c_freq_mode);
+	CAM_DBG(CAM_ACTUATOR, "Slave addr: 0x%x Freq Mode: %d",
+		i2c_info->slave_addr, i2c_info->i2c_freq_mode);
 
 	return rc;
 }
@@ -46,13 +46,12 @@
 	uint32_t i, size;
 
 	if (a_ctrl == NULL || i2c_set == NULL) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
 	if (i2c_set->is_settings_valid != 1) {
-		pr_err("%s: %d :Error: Invalid settings\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, " Invalid settings");
 		return -EINVAL;
 	}
 
@@ -62,8 +61,8 @@
 			rc = camera_io_dev_write(&(a_ctrl->io_master_info),
 				&(i2c_list->i2c_settings));
 			if (rc < 0) {
-				pr_err("%s: %d :Error: Failed in Applying i2c write settings\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_ACTUATOR,
+					"Failed in Applying i2c wrt settings");
 				return rc;
 			}
 		} else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) {
@@ -82,8 +81,8 @@
 					i2c_list->i2c_settings.
 						reg_setting[i].delay);
 				if (rc < 0) {
-					pr_err("%s: %d :Error: Failed in Applying i2c poll settings\n",
-						__func__, __LINE__);
+					CAM_ERR(CAM_ACTUATOR,
+						"i2c poll apply setting Fail");
 					return rc;
 				}
 			}
@@ -99,24 +98,21 @@
 	struct cam_actuator_ctrl_t *a_ctrl = NULL;
 
 	if (!apply) {
-		pr_err("%s:%d :Error: Invalid Input Args\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Input Args");
 		return -EINVAL;
 	}
 
 	a_ctrl = (struct cam_actuator_ctrl_t *)
 		cam_get_device_priv(apply->dev_hdl);
 	if (!a_ctrl) {
-		pr_err("%s: %d :Error: Device data is NULL\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Device data is NULL");
 		return -EINVAL;
 	}
 	request_id = apply->request_id % MAX_PER_FRAME_ARRAY;
 
 	trace_cam_apply_req("Actuator", apply);
 
-	CDBG("%s:%d Request Id: %lld\n",
-		__func__, __LINE__, apply->request_id);
+	CAM_DBG(CAM_ACTUATOR, "Request Id: %lld", apply->request_id);
 
 	if ((apply->request_id ==
 		a_ctrl->i2c_data.per_frame[request_id].request_id) &&
@@ -125,8 +121,9 @@
 		rc = cam_actuator_apply_settings(a_ctrl,
 			&a_ctrl->i2c_data.per_frame[request_id]);
 		if (rc < 0) {
-			pr_err("%s:%d Failed in applying the request: %lld\n",
-				__func__, __LINE__, apply->request_id);
+			CAM_ERR(CAM_ACTUATOR,
+				"Failed in applying the request: %lld\n",
+				apply->request_id);
 			return rc;
 		}
 	}
@@ -139,12 +136,13 @@
 		a_ctrl->i2c_data.per_frame[del_req_id].request_id = 0;
 		rc = delete_request(&a_ctrl->i2c_data.per_frame[del_req_id]);
 		if (rc < 0) {
-			pr_err("%s: %d :Error: Fail deleting the req: %d err: %d\n",
-				__func__, __LINE__, del_req_id, rc);
+			CAM_ERR(CAM_ACTUATOR,
+				"Fail deleting the req: %d err: %d\n",
+				del_req_id, rc);
 			return rc;
 		}
 	} else {
-		CDBG("%s:%d No Valid Req to clean Up\n", __func__, __LINE__);
+		CAM_DBG(CAM_ACTUATOR, "No Valid Req to clean Up");
 	}
 
 	return rc;
@@ -156,15 +154,14 @@
 	struct cam_actuator_ctrl_t *a_ctrl = NULL;
 
 	if (!link) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
 	a_ctrl = (struct cam_actuator_ctrl_t *)
 		cam_get_device_priv(link->dev_hdl);
 	if (!a_ctrl) {
-		pr_err("%s:%d :Error: Device data is NULL\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Device data is NULL");
 		return -EINVAL;
 	}
 	if (link->link_enable) {
@@ -181,7 +178,7 @@
 int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info)
 {
 	if (!info) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -208,8 +205,7 @@
 	struct cam_req_mgr_add_request add_req;
 
 	if (!a_ctrl || !arg) {
-		pr_err("%s:%d :Error: Invalid Args\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -220,21 +216,21 @@
 	rc = cam_mem_get_cpu_buf(config.packet_handle,
 		(uint64_t *)&generic_ptr, &len_of_buff);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: error in converting command Handle %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %d",
+			rc);
 		return rc;
 	}
 
 	if (config.offset > len_of_buff) {
-		pr_err("%s: %d offset is out of bounds: offset: %lld len: %zu\n",
-			__func__, __LINE__, config.offset, len_of_buff);
+		CAM_ERR(CAM_ACTUATOR,
+			"offset is out of bounds: offset: %lld len: %zu",
+			config.offset, len_of_buff);
 		return -EINVAL;
 	}
 
 	csl_packet = (struct cam_packet *)(generic_ptr +
 		config.offset);
-	CDBG("%s:%d Pkt opcode: %d\n",
-		__func__, __LINE__, csl_packet->header.op_code);
+	CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
 
 	if ((csl_packet->header.op_code & 0xFFFFFF) ==
 			CAM_ACTUATOR_PACKET_OPCODE_INIT) {
@@ -246,24 +242,22 @@
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
 
 		if (csl_packet->num_cmd_buf != 2) {
-			pr_err("%s:: %d :Error: cmd Buffers in Init : %d\n",
-				__func__, __LINE__, csl_packet->num_cmd_buf);
+			CAM_ERR(CAM_ACTUATOR, "cmd Buffers in Init : %d",
+				csl_packet->num_cmd_buf);
 			return -EINVAL;
 		}
 
 		rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle,
 			(uint64_t *)&generic_ptr, &len_of_buff);
 		if (rc < 0) {
-			pr_err("%s:%d Failed to get cpu buf\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
 			return rc;
 		}
 		cmd_buf = (uint32_t *)generic_ptr;
 		cmd_buf += cmd_desc->offset / sizeof(uint32_t);
 		rc = cam_actuator_slaveInfo_pkt_parser(a_ctrl, cmd_buf);
 		if (rc < 0) {
-			pr_err("%s:%d Failed in parsing the pkt\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed in parsing the pkt");
 			return rc;
 		}
 		cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t));
@@ -272,8 +266,8 @@
 		rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
 			&cmd_desc[1], 1);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: actuator pkt parsing failed: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_ACTUATOR, "Actuator pkt parsing failed: %d",
+				rc);
 			return rc;
 		}
 	} else if ((csl_packet->header.op_code & 0xFFFFFF) ==
@@ -293,8 +287,8 @@
 		rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: actuator pkt parsing failed: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_ACTUATOR, "Actuator pkt parsing failed: %d",
+				rc);
 			return rc;
 		}
 	} else if ((csl_packet->header.op_code & 0xFFFFFF) ==
@@ -313,8 +307,8 @@
 		rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: actuator pkt parsing failed: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_ACTUATOR, "Actuator pkt parsing failed: %d",
+				rc);
 			return rc;
 		}
 	}
@@ -327,8 +321,8 @@
 		if (a_ctrl->bridge_intf.crm_cb &&
 			a_ctrl->bridge_intf.crm_cb->add_req)
 			a_ctrl->bridge_intf.crm_cb->add_req(&add_req);
-		CDBG("%s: %d Req Id: %lld added to Bridge\n",
-			__func__, __LINE__, add_req.req_id);
+		CAM_DBG(CAM_ACTUATOR, "Req Id: %lld added to Bridge",
+			add_req.req_id);
 	}
 
 	return rc;
@@ -348,8 +342,7 @@
 		return 0;
 
 	if (cnt >= CAM_SOC_MAX_REGULATOR) {
-		pr_err("%s:%d Regulators more than supported %d\n",
-			__func__, __LINE__, cnt);
+		CAM_ERR(CAM_ACTUATOR, "Regulators more than supported %d", cnt);
 		return -EINVAL;
 	}
 
@@ -372,8 +365,7 @@
 
 	rc = cam_actuator_vreg_control(a_ctrl, 1);
 	if (rc < 0) {
-		pr_err("%s:%d Actuator Reg Failed %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_ACTUATOR, "Actuator Reg Failed %d", rc);
 		return rc;
 	}
 
@@ -387,8 +379,7 @@
 		rc = cam_soc_util_enable_platform_resource(&a_ctrl->soc_info,
 			false, 0, false);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Failed in req gpio: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_ACTUATOR, "Failed in req gpio: %d", rc);
 			return rc;
 		}
 
@@ -412,7 +403,7 @@
 
 	rc = cam_actuator_vreg_control(a_ctrl, 0);
 	if (rc < 0) {
-		pr_err("%s failed %d\n", __func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Failed %d");
 		return rc;
 	}
 
@@ -430,8 +421,8 @@
 		rc |= cam_soc_util_disable_platform_resource(&a_ctrl->soc_info,
 					0, 0);
 		if (rc < 0)
-			pr_err("%s:%d Failed to disable platform resources: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_ACTUATOR,
+				"Failed to disable platform resources: %d", rc);
 	}
 
 	return rc;
@@ -444,13 +435,11 @@
 	struct cam_control *cmd = (struct cam_control *)arg;
 
 	if (!a_ctrl || !cmd) {
-		pr_err("%s: %d :Error: Invalid Args\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, " Invalid Args");
 		return -EINVAL;
 	}
 
-	pr_debug("%s:%d Opcode to Actuator: %d\n",
-		__func__, __LINE__, cmd->op_code);
+	pr_debug("Opcode to Actuator: %d", cmd->op_code);
 
 	mutex_lock(&(a_ctrl->actuator_mutex));
 	switch (cmd->op_code) {
@@ -459,8 +448,7 @@
 		struct cam_create_dev_hdl bridge_params;
 
 		if (a_ctrl->bridge_intf.device_hdl != -1) {
-			pr_err("%s:%d Device is already acquired\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Device is already acquired");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -468,8 +456,7 @@
 			(void __user *) cmd->handle,
 			sizeof(actuator_acq_dev));
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Failed Copying from user\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed Copying from user\n");
 			goto release_mutex;
 		}
 
@@ -485,12 +472,11 @@
 		a_ctrl->bridge_intf.session_hdl =
 			actuator_acq_dev.session_handle;
 
-		CDBG("%s:%d Device Handle: %d\n",
-			__func__, __LINE__, actuator_acq_dev.device_handle);
+		CAM_DBG(CAM_ACTUATOR, "Device Handle: %d",
+			actuator_acq_dev.device_handle);
 		if (copy_to_user((void __user *) cmd->handle, &actuator_acq_dev,
 			sizeof(struct cam_sensor_acquire_dev))) {
-			pr_err("%s:%d :Error: Failed Copy to User\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed Copy to User");
 			rc = -EFAULT;
 			goto release_mutex;
 		}
@@ -499,8 +485,7 @@
 		break;
 	case CAM_RELEASE_DEV: {
 		if (a_ctrl->bridge_intf.device_hdl == -1) {
-			pr_err("%s:%d :Error: link hdl: %d device hdl: %d\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_ACTUATOR, "link hdl: %d device hdl: %d",
 				a_ctrl->bridge_intf.device_hdl,
 				a_ctrl->bridge_intf.link_hdl);
 			rc = -EINVAL;
@@ -508,21 +493,19 @@
 		}
 		rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl);
 		if (rc < 0)
-			pr_err("%s:%d :Error: destroying the device hdl\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "destroying the device hdl");
 		a_ctrl->bridge_intf.device_hdl = -1;
 		a_ctrl->bridge_intf.link_hdl = -1;
 		a_ctrl->bridge_intf.session_hdl = -1;
 	}
 		break;
 	case CAM_QUERY_CAP: {
-		struct cam_actuator_query_cap actuator_cap;
+		struct cam_actuator_query_cap actuator_cap = {0};
 
 		actuator_cap.slot_info = a_ctrl->id;
 		if (copy_to_user((void __user *) cmd->handle, &actuator_cap,
 			sizeof(struct cam_actuator_query_cap))) {
-			pr_err("%s:%d :Error: Failed Copy to User\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed Copy to User");
 			rc = -EFAULT;
 			goto release_mutex;
 		}
@@ -531,28 +514,25 @@
 	case CAM_START_DEV: {
 		rc = cam_actuator_power_up(a_ctrl);
 		if (rc < 0) {
-			pr_err("%s: %d :Error: Actuator Power up failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, " Actuator Power up failed");
 			goto release_mutex;
 		}
 		rc = camera_io_init(&a_ctrl->io_master_info);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: cci_init failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "cci_init failed");
 			cam_actuator_power_down(a_ctrl);
 		}
 
 		rc = cam_actuator_apply_settings(a_ctrl,
 			&a_ctrl->i2c_data.init_settings);
 		if (rc < 0)
-			pr_err("%s: %d :Error: Cannot apply Init settings\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings");
 
 		/* Delete the request even if the apply is failed */
 		rc = delete_request(&a_ctrl->i2c_data.init_settings);
 		if (rc < 0) {
-			pr_err("%s:%d Fail in deleting the Init settings\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR,
+				"Fail in deleting the Init settings");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -561,12 +541,10 @@
 	case CAM_STOP_DEV: {
 		rc = camera_io_release(&a_ctrl->io_master_info);
 		if (rc < 0)
-			pr_err("%s:%d :Error: Failed in releasing CCI\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed in releasing CCI");
 		rc = cam_actuator_power_down(a_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Actuator Power down failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Actuator Power down failed");
 			goto release_mutex;
 		}
 	}
@@ -576,8 +554,7 @@
 			ACT_APPLY_SETTINGS_LATER;
 		rc = cam_actuator_i2c_pkt_parse(a_ctrl, arg);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Failed in actuator Parsing\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR, "Failed in actuator Parsing");
 		}
 
 		if (a_ctrl->act_apply_state ==
@@ -585,14 +562,15 @@
 			rc = cam_actuator_apply_settings(a_ctrl,
 				&a_ctrl->i2c_data.init_settings);
 			if (rc < 0)
-				pr_err("%s:%d :Error: Cannot apply Update settings\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_ACTUATOR,
+					"Cannot apply Update settings");
 
 			/* Delete the request even if the apply is failed */
 			rc = delete_request(&a_ctrl->i2c_data.init_settings);
 			if (rc < 0) {
-				pr_err("%s: %d :Error: Failed in Deleting the Init Pkt: %d\n",
-					__func__, __LINE__, rc);
+				CAM_ERR(CAM_ACTUATOR,
+					"Failed in Deleting the Init Pkt: %d",
+					rc);
 				goto release_mutex;
 			}
 		}
@@ -601,8 +579,7 @@
 	case CAM_SD_SHUTDOWN:
 		break;
 	default:
-		pr_err("%s:%d Invalid Opcode %d\n",
-			__func__, __LINE__, cmd->op_code);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Opcode %d", cmd->op_code);
 	}
 
 release_mutex:
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index f8ea769..7eba9d1 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
@@ -28,8 +28,7 @@
 		rc = cam_actuator_driver_cmd(a_ctrl, arg);
 		break;
 	default:
-		pr_err("%s:%d Invalid ioctl cmd\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd");
 		rc = -EINVAL;
 		break;
 	}
@@ -43,14 +42,14 @@
 	struct cam_actuator_ctrl_t *a_ctrl;
 
 	if (client == NULL || id == NULL) {
-		pr_err("%s:%d: :Error: Invalid Args client: %pK id: %pK\n",
-			__func__, __LINE__, client, id);
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args client: %pK id: %pK",
+			client, id);
 		return -EINVAL;
 	}
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		pr_err("%s %s :Error: i2c_check_functionality failed\n",
-			__func__, client->name);
+		CAM_ERR(CAM_ACTUATOR, "%s :: i2c_check_functionality failed",
+			 client->name);
 		rc = -EFAULT;
 		return rc;
 	}
@@ -81,7 +80,7 @@
 
 	rc = cam_actuator_parse_dt(a_ctrl, &client->dev);
 	if (rc < 0) {
-		pr_err("failed: cam_sensor_parse_dt rc %d", rc);
+		CAM_ERR(CAM_ACTUATOR, "failed: cam_sensor_parse_dt rc %d", rc);
 		goto free_mem;
 	}
 
@@ -100,7 +99,7 @@
 
 	a_ctrl = platform_get_drvdata(pdev);
 	if (!a_ctrl) {
-		pr_err("%s: Actuator device is NULL\n", __func__);
+		CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL");
 		return 0;
 	}
 
@@ -120,7 +119,7 @@
 
 	/* Handle I2C Devices */
 	if (!a_ctrl) {
-		pr_err("%s: Actuator device is NULL\n", __func__);
+		CAM_ERR(CAM_ACTUATOR, "Actuator device is NULL");
 		return -EINVAL;
 	}
 	/*Free Allocated Mem */
@@ -139,7 +138,8 @@
 
 	if (copy_from_user(&cmd_data, (void __user *)arg,
 		sizeof(cmd_data))) {
-		pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+		CAM_ERR(CAM_ACTUATOR,
+			"Failed to copy from user_ptr=%pK size=%zu\n",
 			(void __user *)arg, sizeof(cmd_data));
 		return -EFAULT;
 	}
@@ -149,21 +149,21 @@
 		cmd = VIDIOC_CAM_CONTROL;
 		rc = cam_actuator_subdev_ioctl(sd, cmd, &cmd_data);
 		if (rc < 0) {
-			pr_err("%s:%d Failed in actuator suddev handling",
-				__func__, __LINE__);
+			CAM_ERR(CAM_ACTUATOR,
+				"Failed in actuator suddev handling");
 			return rc;
 		}
 		break;
 	default:
-		pr_err("%s:%d Invalid compat ioctl: %d\n",
-			__func__, __LINE__, cmd);
+		CAM_ERR(CAM_ACTUATOR, "Invalid compat ioctl: %d", cmd);
 		rc = -EINVAL;
 	}
 
 	if (!rc) {
 		if (copy_to_user((void __user *)arg, &cmd_data,
 			sizeof(cmd_data))) {
-			pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+			CAM_ERR(CAM_ACTUATOR,
+				"Failed to copy to user_ptr=%pK size=%zu\n",
 				(void __user *)arg, sizeof(cmd_data));
 			rc = -EFAULT;
 		}
@@ -228,8 +228,7 @@
 
 	rc = cam_actuator_parse_dt(a_ctrl, &(pdev->dev));
 	if (rc < 0) {
-		pr_err("%s:%d :Error: Paring actuator dt failed rc %d",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_ACTUATOR, "Paring actuator dt failed rc %d", rc);
 		goto free_ctrl;
 	}
 
@@ -252,16 +251,15 @@
 
 	rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str));
 	if (rc < 0) {
-		pr_err("%s:%d :ERROR: Fail with cam_register_subdev\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "Fail with cam_register_subdev");
 		goto free_mem;
 	}
 
 	rc = cam_soc_util_request_platform_resource(&a_ctrl->soc_info,
 			NULL, NULL);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: Requesting Platform Resources failed rc %d",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_ACTUATOR,
+			"Requesting Platform Resources failed rc %d", rc);
 		goto free_ctrl;
 	}
 
@@ -316,14 +314,13 @@
 
 	rc = platform_driver_register(&cam_actuator_platform_driver);
 	if (rc < 0) {
-		pr_err("%s platform_driver_register failed rc = %d",
-			__func__, rc);
+		CAM_ERR(CAM_ACTUATOR,
+			"platform_driver_register failed rc = %d", rc);
 		return rc;
 	}
 	rc = i2c_add_driver(&cam_actuator_driver_i2c);
 	if (rc)
-		pr_err("%s:%d :Error: i2c_add_driver failed rc = %d",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_ACTUATOR, "i2c_add_driver failed rc = %d", rc);
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h
index 19fe4af..fdf881f3 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h
@@ -33,6 +33,7 @@
 #include <cam_subdev.h>
 #include "cam_sensor_util.h"
 #include "cam_soc_util.h"
+#include "cam_debug_util.h"
 
 #define NUM_MASTERS 2
 #define NUM_QUEUES 2
@@ -40,13 +41,6 @@
 #define TRUE  1
 #define FALSE 0
 
-#undef CDBG
-#ifdef CAM_SENSOR_DEBUG
-#define CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
 #define ACTUATOR_DRIVER_I2C "i2c_actuator"
 #define CAMX_ACTUATOR_DEV_NAME "cam-actuator-driver"
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c
index 584e4d2..ddc89a8 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c
@@ -28,8 +28,7 @@
 	struct platform_device *pdev = NULL;
 
 	if (!soc_info->pdev) {
-		pr_err("%s:%d :Error:soc_info is not initialized\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "soc_info is not initialized");
 		return -EINVAL;
 	}
 
@@ -41,27 +40,27 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: parsing common soc dt(rc %d)\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_ACTUATOR, "parsing common soc dt(rc %d)", rc);
 		return rc;
 	}
 	rc = of_property_read_u32(of_node, "cci-master",
 		&(a_ctrl->cci_i2c_master));
-	CDBG("cci-master %d, rc %d\n", a_ctrl->cci_i2c_master, rc);
+	CAM_DBG(CAM_ACTUATOR, "cci-master %d, rc %d",
+		a_ctrl->cci_i2c_master, rc);
 	if (rc < 0 || a_ctrl->cci_i2c_master >= MASTER_MAX) {
-		pr_err("%s:%d :Error: Wrong info from dt CCI master as : %d\n",
-			__func__, __LINE__, a_ctrl->cci_i2c_master);
+		CAM_ERR(CAM_ACTUATOR, "Wrong info from dt CCI master as : %d",
+			a_ctrl->cci_i2c_master);
 		return rc;
 	}
 
 	if (!soc_info->gpio_data) {
-		pr_info("%s:%d No GPIO found\n", __func__, __LINE__);
+		CAM_INFO(CAM_ACTUATOR, "No GPIO found");
 		rc = 0;
 		return rc;
 	}
 
 	if (!soc_info->gpio_data->cam_gpio_common_tbl_size) {
-		pr_info("%s:%d No GPIO found\n", __func__, __LINE__);
+		CAM_INFO(CAM_ACTUATOR, "No GPIO found");
 		return -EINVAL;
 	}
 
@@ -69,8 +68,7 @@
 		&a_ctrl->gpio_num_info);
 
 	if ((rc < 0) || (!a_ctrl->gpio_num_info)) {
-		pr_err("%s:%d No/Error Actuator GPIOs\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_ACTUATOR, "No/Error Actuator GPIOs");
 		return -EINVAL;
 	}
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
index 83e0c19..975b301 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
@@ -33,7 +33,7 @@
 		num_bytes = 4;
 		break;
 	default:
-		pr_err("%s: %d failed: %d\n", __func__, __LINE__, type);
+		CAM_ERR(CAM_CCI, "failed: %d", type);
 		num_bytes = 0;
 		break;
 	}
@@ -52,9 +52,9 @@
 	rc = wait_for_completion_timeout(
 		&cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
 	if (rc < 0) {
-		pr_err("%s:%d wait failed\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "wait failed");
 	} else if (rc == 0) {
-		pr_err("%s:%d wait timeout\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "wait timeout");
 
 		/* Set reset pending flag to TRUE */
 		cci_dev->cci_master_info[master].reset_pending = TRUE;
@@ -72,8 +72,7 @@
 			&cci_dev->cci_master_info[master].reset_complete,
 			CCI_TIMEOUT);
 		if (rc <= 0)
-			pr_err("%s:%d wait failed %d\n", __func__, __LINE__,
-				rc);
+			CAM_ERR(CAM_CCI, "wait failed %d", rc);
 	}
 }
 
@@ -91,37 +90,36 @@
 
 	read_val = cam_io_r_mb(base +
 		CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
-	CDBG("%s line %d CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d\n",
-		__func__, __LINE__, read_val, len,
+	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d",
+		read_val, len,
 		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
 	if ((read_val + len + 1) > cci_dev->
 		cci_i2c_queue_info[master][queue].max_queue_size) {
 		uint32_t reg_val = 0;
 		uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
 
-		CDBG("%s:%d CCI_I2C_REPORT_CMD\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD");
 		cam_io_w_mb(report_val,
 			base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 			reg_offset);
 		read_val++;
-		CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d, queue: %d\n",
-			__func__, __LINE__, read_val, queue);
+		CAM_DBG(CAM_CCI,
+			"CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d, queue: %d",
+			read_val, queue);
 		cam_io_w_mb(read_val, base +
 			CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
 		reg_val = 1 << ((master * 2) + queue);
-		CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "CCI_QUEUE_START_ADDR");
 		atomic_set(&cci_dev->cci_master_info[master].
 						done_pending[queue], 1);
 		cam_io_w_mb(reg_val, base +
 			CCI_QUEUE_START_ADDR);
-		CDBG("%s line %d wait_for_completion_timeout\n",
-			__func__, __LINE__);
+		CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
 		atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
 		rc = wait_for_completion_timeout(&cci_dev->
 			cci_master_info[master].report_q[queue], CCI_TIMEOUT);
 		if (rc <= 0) {
-			pr_err("%s: wait_for_completion_timeout %d\n",
-				 __func__, __LINE__);
+			CAM_ERR(CAM_CCI, "Wait_for_completion_timeout %d");
 			if (rc == 0)
 				rc = -ETIMEDOUT;
 			cam_cci_flush_queue(cci_dev, master);
@@ -129,7 +127,7 @@
 		}
 		rc = cci_dev->cci_master_info[master].status;
 		if (rc < 0)
-			pr_err("%s failed rc %d\n", __func__, rc);
+			CAM_ERR(CAM_CCI, "Failed rc %d", rc);
 	}
 
 	return rc;
@@ -147,17 +145,17 @@
 	void __iomem *base = soc_info->reg_map[0].mem_base;
 
 	if (!cci_dev) {
-		pr_err("%s: failed %d", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Failed");
 		return -EINVAL;
 	}
 
 	rc = cam_cci_validate_queue(cci_dev, 1, master, queue);
 	if (rc < 0) {
-		pr_err("%s: failed %d", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Failed %d", rc);
 		return rc;
 	}
-	CDBG("%s CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x\n",
-		__func__, CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
+	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x",
+		CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 		reg_offset, val);
 	cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 		reg_offset);
@@ -186,45 +184,44 @@
 	uint32_t reg_offset = 0;
 
 	/* CCI Top Registers */
-	CCI_DBG(" **** %s : %d CCI TOP Registers ****\n", __func__, __LINE__);
+	CAM_DBG(CAM_CCI, "****CCI TOP Registers ****");
 	for (i = 0; i < DEBUG_TOP_REG_COUNT; i++) {
 		reg_offset = DEBUG_TOP_REG_START + i * 4;
 		read_val = cam_io_r_mb(cci_dev->base + reg_offset);
-		CCI_DBG("%s : %d offset = 0x%X value = 0x%X\n",
-			__func__, __LINE__, reg_offset, read_val);
+		CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
+			reg_offset, read_val);
 	}
 
 	/* CCI Master registers */
-	CCI_DBG(" **** %s : %d CCI MASTER%d Registers ****\n",
-		__func__, __LINE__, master);
+	CAM_DBG(CAM_CCI, "****CCI MASTER %d Registers ****",
+		master);
 	for (i = 0; i < DEBUG_MASTER_REG_COUNT; i++) {
 		if (i == 6)
 			continue;
 		reg_offset = DEBUG_MASTER_REG_START + master*0x100 + i * 4;
 		read_val = cam_io_r_mb(cci_dev->base + reg_offset);
-		CCI_DBG("%s : %d offset = 0x%X value = 0x%X\n",
-			__func__, __LINE__, reg_offset, read_val);
+		CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
+			reg_offset, read_val);
 	}
 
 	/* CCI Master Queue registers */
-	CCI_DBG(" **** %s : %d CCI MASTER%d QUEUE%d Registers ****\n",
-		__func__, __LINE__, master, queue);
+	CAM_DBG(CAM_CCI, " **** CCI MASTER%d QUEUE%d Registers ****",
+		master, queue);
 	for (i = 0; i < DEBUG_MASTER_QUEUE_REG_COUNT; i++) {
 		reg_offset = DEBUG_MASTER_QUEUE_REG_START +  master*0x200 +
 			queue*0x100 + i * 4;
 		read_val = cam_io_r_mb(cci_dev->base + reg_offset);
-		CCI_DBG("%s : %d offset = 0x%X value = 0x%X\n",
-			__func__, __LINE__, reg_offset, read_val);
+		CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
+			reg_offset, read_val);
 	}
 
 	/* CCI Interrupt registers */
-	CCI_DBG(" **** %s : %d CCI Interrupt Registers ****\n",
-		__func__, __LINE__);
+	CAM_DBG(CAM_CCI, " ****CCI Interrupt Registers ****");
 	for (i = 0; i < DEBUG_INTR_REG_COUNT; i++) {
 		reg_offset = DEBUG_INTR_REG_START + i * 4;
 		read_val = cam_io_r_mb(cci_dev->base + reg_offset);
-		CCI_DBG("%s : %d offset = 0x%X value = 0x%X\n",
-			__func__, __LINE__, reg_offset, read_val);
+		CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
+			reg_offset, read_val);
 	}
 }
 #endif
@@ -236,21 +233,19 @@
 	int32_t rc = 0;
 
 	if (!cci_dev) {
-		pr_err("%s: failed %d", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "failed");
 		return -EINVAL;
 	}
 
 	rc = wait_for_completion_timeout(&cci_dev->
 		cci_master_info[master].report_q[queue], CCI_TIMEOUT);
-	CDBG("%s line %d wait DONE_for_completion_timeout\n",
-		__func__, __LINE__);
+	CAM_DBG(CAM_CCI, "wait DONE_for_completion_timeout");
 
 	if (rc <= 0) {
 #ifdef DUMP_CCI_REGISTERS
 		cam_cci_dump_registers(cci_dev, master, queue);
 #endif
-		pr_err("%s: %d wait for queue: %d\n",
-			 __func__, __LINE__, queue);
+		CAM_ERR(CAM_CCI, "wait for queue: %d", queue);
 		if (rc == 0)
 			rc = -ETIMEDOUT;
 		cam_cci_flush_queue(cci_dev, master);
@@ -258,7 +253,7 @@
 	}
 	rc = cci_dev->cci_master_info[master].status;
 	if (rc < 0) {
-		pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "failed rc %d", rc);
 		return rc;
 	}
 
@@ -278,15 +273,13 @@
 		CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
 	uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
 
-	CDBG("%s:%d CCI_I2C_REPORT_CMD curr_w_cnt: %d\n",
-		__func__, __LINE__, read_val);
+	CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD curr_w_cnt: %d", read_val);
 	cam_io_w_mb(report_val,
 		base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 		reg_offset);
 	read_val++;
 
-	CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d\n",
-		__func__, __LINE__, read_val);
+	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d", read_val);
 	cam_io_w_mb(read_val, base +
 		CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
 }
@@ -319,12 +312,12 @@
 	if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) {
 		rc = cam_cci_lock_queue(cci_dev, master, queue, 0);
 		if (rc < 0) {
-			pr_err("%s failed line %d\n", __func__, __LINE__);
+			CAM_ERR(CAM_CCI, "failed line %d");
 			return rc;
 		}
 		rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
 		if (rc < 0) {
-			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_CCI, "failed rc %d", rc);
 			return rc;
 		}
 	} else {
@@ -332,17 +325,17 @@
 						done_pending[queue], 1);
 		rc = cam_cci_wait(cci_dev, master, queue);
 		if (rc < 0) {
-			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_CCI, "failed rc %d", rc);
 			return rc;
 		}
 		rc = cam_cci_lock_queue(cci_dev, master, queue, 0);
 		if (rc < 0) {
-			pr_err("%s failed line %d\n", __func__, __LINE__);
+			CAM_ERR(CAM_CCI, "failed rc %d", rc);
 			return rc;
 		}
 		rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
 		if (rc < 0) {
-			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_CCI, "Failed rc %d", rc);
 			return rc;
 		}
 	}
@@ -362,8 +355,7 @@
 
 	read_val = cam_io_r_mb(base +
 		CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
-	CDBG("%s line %d CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d max %d\n",
-		__func__, __LINE__, read_val,
+	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d max %d", read_val,
 		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
 	return (cci_dev->
 		cci_i2c_queue_info[master][queue].max_queue_size) -
@@ -398,13 +390,13 @@
 						done_pending[queue], 1);
 		rc = cam_cci_wait(cci_dev, master, queue);
 		if (rc < 0) {
-			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_CCI, "failed rc %d", rc);
 			return rc;
 		}
 	} else {
 		rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
 		if (rc < 0) {
-			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_CCI, "failed rc %d", rc);
 			return rc;
 		}
 	}
@@ -425,7 +417,7 @@
 	uint32_t size = cmd_size;
 
 	if (!cci_dev || !c_ctrl) {
-		pr_err("%s: failed %d", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "failed");
 		return -EINVAL;
 	}
 
@@ -458,8 +450,7 @@
 	}
 
 	if (len > cci_dev->payload_size) {
-		pr_err("%s: %d Len error: %d",
-			__func__, __LINE__, len);
+		CAM_ERR(CAM_CCI, "Len error: %d", len);
 		return -EINVAL;
 	}
 
@@ -476,8 +467,8 @@
 	if (clk) {
 		cycles_per_us = ((clk/1000)*256)/1000;
 	} else {
-		pr_err("%s:%d, failed: Can use default: %d",
-			__func__, __LINE__, CYCLES_PER_MICRO_SEC_DEFAULT);
+		CAM_ERR(CAM_CCI, "failed: Can use default: %d",
+			CYCLES_PER_MICRO_SEC_DEFAULT);
 		cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT;
 	}
 
@@ -498,8 +489,8 @@
 
 	if (i2c_freq_mode >= I2C_MAX_MODES ||
 		i2c_freq_mode < I2C_STANDARD_MODE) {
-		pr_err("%s:%d Invalid frequency mode: %d\n",
-			__func__, __LINE__, (int32_t)i2c_freq_mode);
+		CAM_ERR(CAM_CCI, "Invalid frequency mode: %d",
+			(int32_t)i2c_freq_mode);
 		cci_dev->clk_level_index = -1;
 		return;
 	}
@@ -544,8 +535,7 @@
 	void __iomem *base = soc_info->reg_map[0].mem_base;
 
 	if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) {
-		pr_err("%s:%d invalid i2c_freq_mode = %d",
-			__func__, __LINE__, i2c_freq_mode);
+		CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode);
 		return -EINVAL;
 	}
 
@@ -608,28 +598,27 @@
 	void __iomem *base = soc_info->reg_map[0].mem_base;
 
 	if (i2c_cmd == NULL) {
-		pr_err("%s:%d Failed line\n", __func__,
-			__LINE__);
+		CAM_ERR(CAM_CCI, "Failed: i2c cmd is NULL");
 		return -EINVAL;
 	}
 
 	if ((!cmd_size) || (cmd_size > CCI_I2C_MAX_WRITE)) {
-		pr_err("%s:%d failed: invalid cmd_size %d\n",
-			__func__, __LINE__, cmd_size);
+		CAM_ERR(CAM_CCI, "failed: invalid cmd_size %d",
+			cmd_size);
 		return -EINVAL;
 	}
 
-	CDBG("%s addr type %d data type %d cmd_size %d\n", __func__,
+	CAM_DBG(CAM_CCI, "addr type %d data type %d cmd_size %d",
 		i2c_msg->addr_type, i2c_msg->data_type, cmd_size);
 
 	if (i2c_msg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
-		pr_err("%s:%d failed: invalid addr_type 0x%X\n",
-			__func__, __LINE__, i2c_msg->addr_type);
+		CAM_ERR(CAM_CCI, "failed: invalid addr_type 0x%X",
+			i2c_msg->addr_type);
 		return -EINVAL;
 	}
 	if (i2c_msg->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
-		pr_err("%s:%d failed: invalid data_type 0x%X\n",
-			__func__, __LINE__, i2c_msg->data_type);
+		CAM_ERR(CAM_CCI, "failed: invalid data_type 0x%X",
+			i2c_msg->data_type);
 		return -EINVAL;
 	}
 	reg_offset = master * 0x200 + queue * 0x100;
@@ -643,8 +632,8 @@
 		c_ctrl->cci_info->retries << 16 |
 		c_ctrl->cci_info->id_map << 18;
 
-	CDBG("%s CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x\n",
-		__func__, CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
+	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x",
+		CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 		reg_offset, val);
 	cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 		reg_offset);
@@ -671,7 +660,7 @@
 
 	rc = cam_cci_lock_queue(cci_dev, master, queue, 1);
 	if (rc < 0) {
-		pr_err("%s failed line %d\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "failed line %d", rc);
 		return rc;
 	}
 
@@ -681,22 +670,21 @@
 		len = cam_cci_calc_cmd_len(cci_dev, c_ctrl, cmd_size,
 			i2c_cmd, &pack);
 		if (len <= 0) {
-			pr_err("%s failed line %d\n", __func__, __LINE__);
+			CAM_ERR(CAM_CCI, "failed");
 			return -EINVAL;
 		}
 
 		read_val = cam_io_r_mb(base +
 			CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
-		CDBG("%s line %d CUR_WORD_CNT_ADDR %d len %d max %d\n",
-			__func__, __LINE__, read_val, len, max_queue_size);
+		CAM_DBG(CAM_CCI, "CUR_WORD_CNT_ADDR %d len %d max %d",
+			read_val, len, max_queue_size);
 		/* + 1 - space alocation for Report CMD */
 		if ((read_val + len + 1) > queue_size) {
 			if ((read_val + len + 1) > max_queue_size) {
 				rc = cam_cci_process_full_q(cci_dev,
 					master, queue);
 				if (rc < 0) {
-					pr_err("%s failed line %d\n",
-						__func__, __LINE__);
+					CAM_ERR(CAM_CCI, "failed rc: %d", rc);
 					return rc;
 				}
 				continue;
@@ -704,7 +692,7 @@
 			cam_cci_process_half_q(cci_dev, master, queue);
 		}
 
-		CDBG("%s cmd_size %d addr 0x%x data 0x%x\n", __func__,
+		CAM_DBG(CAM_CCI, "cmd_size %d addr 0x%x data 0x%x",
 			cmd_size, i2c_cmd->reg_addr, i2c_cmd->reg_data);
 		delay = i2c_cmd->delay;
 		i = 0;
@@ -772,8 +760,9 @@
 			cmd = 0;
 			for (j = 0; (j < 4 && k < i); j++)
 				cmd |= (data[k++] << (j * 8));
-			CDBG("%s LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d\n",
-				__func__, cmd, queue, len, read_val);
+			CAM_DBG(CAM_CCI,
+				"LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d",
+				cmd, queue, len, read_val);
 			cam_io_w_mb(cmd, base +
 				CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 				master * 0x200 + queue * 0x100);
@@ -789,8 +778,8 @@
 				0x100);
 			cmd <<= 4;
 			cmd |= CCI_I2C_WAIT_CMD;
-			CDBG("%s CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x\n",
-				__func__, cmd);
+			CAM_DBG(CAM_CCI,
+				"CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd);
 			cam_io_w_mb(cmd, base +
 				CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
 				master * 0x200 + queue * 0x100);
@@ -802,7 +791,7 @@
 
 	rc = cam_cci_transfer_end(cci_dev, master, queue);
 	if (rc < 0) {
-		pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "failed rc %d", rc);
 		return rc;
 	}
 
@@ -830,7 +819,7 @@
 
 	if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
 		|| c_ctrl->cci_info->cci_i2c_master < 0) {
-		pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Invalid I2C master addr");
 		return -EINVAL;
 	}
 
@@ -847,8 +836,7 @@
 	/* Set the I2C Frequency */
 	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
 	if (rc < 0) {
-		pr_err("%s:%d cam_cci_set_clk_param failed rc = %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
 		goto rel_mutex;
 	}
 
@@ -861,25 +849,22 @@
 		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1,
 		master, queue);
 	if (rc < 0) {
-		pr_err("%s:%d Initial validataion failed rc %d\n", __func__,
-			__LINE__, rc);
+		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
 		goto rel_mutex;
 	}
 
 	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
-		pr_err("%s:%d More than max retries\n", __func__,
-			__LINE__);
+		CAM_ERR(CAM_CCI, "More than max retries");
 		goto rel_mutex;
 	}
 
 	if (read_cfg->data == NULL) {
-		pr_err("%s:%d Data ptr is NULL\n", __func__,
-			__LINE__);
+		CAM_ERR(CAM_CCI, "Data ptr is NULL");
 		goto rel_mutex;
 	}
 
-	CDBG("%s master %d, queue %d\n", __func__, master, queue);
-	CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+	CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
+	CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
 		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
 		c_ctrl->cci_info->id_map);
 	val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
@@ -887,19 +872,20 @@
 		c_ctrl->cci_info->id_map << 18;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
-		CDBG("%s failed line %d\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
 		goto rel_mutex;
 	}
 
 	val = CCI_I2C_LOCK_CMD;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
-		CDBG("%s failed line %d\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
 		goto rel_mutex;
 	}
 
 	if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
-		pr_err("%s failed line %d\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
+			read_cfg->addr_type);
 		rc = -EINVAL;
 		goto rel_mutex;
 	}
@@ -912,34 +898,33 @@
 
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
-		CDBG("%s failed line %d\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
 		goto rel_mutex;
 	}
 
 	val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
-		CDBG("%s failed line %d\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
 		goto rel_mutex;
 	}
 
 	val = CCI_I2C_UNLOCK_CMD;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
-		CDBG("%s failed line %d\n", __func__, __LINE__);
+		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
 		goto rel_mutex;
 	}
 
 	val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
 			+ master * 0x200 + queue * 0x100);
-	CDBG("%s cur word cnt 0x%x\n", __func__, val);
+	CAM_DBG(CAM_CCI, "cur word cnt 0x%x", val);
 	cam_io_w_mb(val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR
 			+ master * 0x200 + queue * 0x100);
 
 	val = 1 << ((master * 2) + queue);
 	cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
-	CDBG("%s:%d E wait_for_completion_timeout\n", __func__,
-		__LINE__);
+	CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
 
 	rc = wait_for_completion_timeout(&cci_dev->
 		cci_master_info[master].reset_complete, CCI_TIMEOUT);
@@ -949,8 +934,7 @@
 #endif
 		if (rc == 0)
 			rc = -ETIMEDOUT;
-		pr_err("%s: %d wait_for_completion_timeout rc = %d\n",
-			 __func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "wait_for_completion_timeout rc = %d", rc);
 		cam_cci_flush_queue(cci_dev, master);
 		goto rel_mutex;
 	} else {
@@ -961,29 +945,28 @@
 		CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
 	exp_words = ((read_cfg->num_byte / 4) + 1);
 	if (read_words != exp_words) {
-		pr_err("%s:%d read_words = %d, exp words = %d\n", __func__,
-			__LINE__, read_words, exp_words);
+		CAM_ERR(CAM_CCI, "read_words = %d, exp words = %d",
+			read_words, exp_words);
 		memset(read_cfg->data, 0, read_cfg->num_byte);
 		rc = -EINVAL;
 		goto rel_mutex;
 	}
 	index = 0;
-	CDBG("%s index %d num_type %d\n", __func__, index,
-		read_cfg->num_byte);
+	CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
 	first_byte = 0;
 	do {
 		val = cam_io_r_mb(base +
 			CCI_I2C_M0_READ_DATA_ADDR + master * 0x100);
-		CDBG("%s read val 0x%x\n", __func__, val);
+		CAM_DBG(CAM_CCI, "read val 0x%x", val);
 		for (i = 0; (i < 4) && (index < read_cfg->num_byte); i++) {
-			CDBG("%s i %d index %d\n", __func__, i, index);
+			CAM_DBG(CAM_CCI, "i:%d index:%d", i, index);
 			if (!first_byte) {
-				CDBG("%s sid 0x%x\n", __func__, val & 0xFF);
+				CAM_DBG(CAM_CCI, "sid 0x%x", val & 0xFF);
 				first_byte++;
 			} else {
 				read_cfg->data[index] =
 					(val  >> (i * 8)) & 0xFF;
-				CDBG("%s data[%d] 0x%x\n", __func__, index,
+				CAM_DBG(CAM_CCI, "data[%d] 0x%x", index,
 					read_cfg->data[index]);
 				index++;
 			}
@@ -1006,20 +989,19 @@
 	cci_dev = v4l2_get_subdevdata(sd);
 
 	if (cci_dev->cci_state != CCI_STATE_ENABLED) {
-		pr_err("%s invalid cci state %d\n",
-			__func__, cci_dev->cci_state);
+		CAM_ERR(CAM_CCI, "invalid cci state %d",
+			cci_dev->cci_state);
 		return -EINVAL;
 	}
 	master = c_ctrl->cci_info->cci_i2c_master;
-	CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+	CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
 		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
 		c_ctrl->cci_info->id_map);
 
 	/* Set the I2C Frequency */
 	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
 	if (rc < 0) {
-		pr_err("%s:%d cam_cci_set_clk_param failed rc = %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
 		return rc;
 	}
 	/*
@@ -1031,18 +1013,17 @@
 		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1,
 		master, queue);
 	if (rc < 0) {
-		pr_err("%s:%d Initial validataion failed rc %d\n",
-		__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
+			rc);
 		return rc;
 	}
 	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
-		pr_err("%s:%d More than max retries\n", __func__,
-			__LINE__);
+		CAM_ERR(CAM_CCI, "More than max retries");
 		return rc;
 	}
 	rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
 	if (rc < 0) {
-		pr_err("%s failed line %d\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "failed rc: %d", rc);
 		return rc;
 	}
 
@@ -1069,7 +1050,7 @@
 		&write_async->c_ctrl, write_async->queue, write_async->sync_en);
 	mutex_unlock(&cci_master_info->mutex_q[write_async->queue]);
 	if (rc < 0)
-		pr_err("%s: %d failed\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "failed rc: %d", rc);
 
 	kfree(write_async->c_ctrl.cfg.cci_i2c_write_cfg.reg_setting);
 	kfree(write_async);
@@ -1110,7 +1091,7 @@
 		kzalloc(sizeof(struct cam_sensor_i2c_reg_array)*
 		cci_i2c_write_cfg->size, GFP_KERNEL);
 	if (!cci_i2c_write_cfg_w->reg_setting) {
-		pr_err("%s: %d Couldn't allocate memory\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Couldn't allocate memory");
 		kfree(write_async);
 		return -ENOMEM;
 	}
@@ -1140,35 +1121,33 @@
 	uint16_t read_bytes = 0;
 
 	if (!sd || !c_ctrl) {
-		pr_err("%s:%d sd %pK c_ctrl %pK\n", __func__,
-			__LINE__, sd, c_ctrl);
+		CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl);
 		return -EINVAL;
 	}
 	if (!c_ctrl->cci_info) {
-		pr_err("%s:%d cci_info NULL\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "cci_info NULL");
 		return -EINVAL;
 	}
 	cci_dev = v4l2_get_subdevdata(sd);
 	if (!cci_dev) {
-		pr_err("%s:%d cci_dev NULL\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "cci_dev NULL");
 		return -EINVAL;
 	}
 	if (cci_dev->cci_state != CCI_STATE_ENABLED) {
-		pr_err("%s invalid cci state %d\n",
-			__func__, cci_dev->cci_state);
+		CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state);
 		return -EINVAL;
 	}
 
 	if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
 			|| c_ctrl->cci_info->cci_i2c_master < 0) {
-		pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Invalid I2C master addr");
 		return -EINVAL;
 	}
 
 	master = c_ctrl->cci_info->cci_i2c_master;
 	read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
 	if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) {
-		pr_err("%s:%d read num bytes 0\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "read num bytes 0");
 		rc = -EINVAL;
 		goto ERROR;
 	}
@@ -1181,7 +1160,7 @@
 			read_cfg->num_byte = read_bytes;
 		rc = cam_cci_read(sd, c_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_CCI, "failed rc %d", rc);
 			goto ERROR;
 		}
 		if (read_bytes > CCI_READ_MAX) {
@@ -1205,8 +1184,8 @@
 
 	cci_dev = v4l2_get_subdevdata(sd);
 	if (!cci_dev || !c_ctrl) {
-		pr_err("%s:%d failed: invalid params %pK %pK\n", __func__,
-			__LINE__, cci_dev, c_ctrl);
+		CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
+			cci_dev, c_ctrl);
 		rc = -EINVAL;
 		return rc;
 	}
@@ -1225,8 +1204,7 @@
 
 	rc = cam_cci_soc_release(cci_dev);
 	if (rc < 0) {
-		pr_err("%s:%d Failed in releasing the cci: %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "Failed in releasing the cci: %d", rc);
 		cam_cpas_stop(cci_dev->cpas_handle);
 		return rc;
 	}
@@ -1246,8 +1224,8 @@
 
 	cci_dev = v4l2_get_subdevdata(sd);
 	if (!cci_dev || !c_ctrl) {
-		pr_err("%s:%d failed: invalid params %pK %pK\n", __func__,
-			__LINE__, cci_dev, c_ctrl);
+		CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
+			cci_dev, c_ctrl);
 		rc = -EINVAL;
 		return rc;
 	}
@@ -1256,7 +1234,7 @@
 
 	if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
 		|| c_ctrl->cci_info->cci_i2c_master < 0) {
-		pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Invalid I2C master addr");
 		return -EINVAL;
 	}
 
@@ -1304,8 +1282,7 @@
 {
 	int32_t rc = 0;
 
-	CDBG("%s line %d cmd %d\n", __func__, __LINE__,
-		cci_ctrl->cmd);
+	CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
 	switch (cci_ctrl->cmd) {
 	case MSM_CCI_INIT:
 		rc = cam_cci_init(sd, cci_ctrl);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
index 63655a4..dad02bf 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
@@ -37,8 +37,7 @@
 	case VIDIOC_CAM_CONTROL:
 		break;
 	default:
-		pr_err("%s:%d Invalid ioctl cmd: %d\n",
-			__func__, __LINE__, cmd);
+		CAM_ERR(CAM_CCI, "Invalid ioctl cmd: %d", cmd);
 		rc = -ENOIOCTLCMD;
 	}
 
@@ -134,13 +133,13 @@
 			base + CCI_RESET_CMD_ADDR);
 	}
 	if (irq & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) {
-		pr_err("%s:%d MASTER_0 error 0x%x\n", __func__, __LINE__, irq);
+		CAM_ERR(CAM_CCI, "MASTER_0 error 0x%x", irq);
 		cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
 		cam_io_w_mb(CCI_M0_HALT_REQ_RMSK,
 			base + CCI_HALT_REQ_ADDR);
 	}
 	if (irq & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) {
-		pr_err("%s:%d MASTER_1 error 0x%x\n", __func__, __LINE__, irq);
+		CAM_ERR(CAM_CCI, "MASTER_1 error 0x%x", irq);
 		cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
 		cam_io_w_mb(CCI_M1_HALT_REQ_RMSK,
 			base + CCI_HALT_REQ_ADDR);
@@ -192,8 +191,7 @@
 
 	rc = cam_cci_parse_dt_info(pdev, new_cci_dev);
 	if (rc < 0) {
-		pr_err("%s: %d Resource get Failed: %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "Resource get Failed: %d", rc);
 		goto cci_no_resource;
 	}
 
@@ -214,8 +212,7 @@
 
 	rc = cam_register_subdev(&(new_cci_dev->v4l2_dev_str));
 	if (rc < 0) {
-		pr_err("%s:%d :Error: Fail with cam_register_subdev\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CCI, "Fail with cam_register_subdev");
 		goto cci_no_resource;
 	}
 
@@ -230,10 +227,10 @@
 	strlcpy(cpas_parms.identifier, "cci", CAM_HW_IDENTIFIER_LENGTH);
 	rc = cam_cpas_register_client(&cpas_parms);
 	if (rc) {
-		pr_err("%s:%d CPAS registration failed\n", __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "CPAS registration failed");
 		goto cci_no_resource;
 	}
-	CDBG("CPAS registration successful handle=%d\n",
+	CAM_DBG(CAM_CCI, "CPAS registration successful handle=%d",
 		cpas_parms.client_handle);
 	new_cci_dev->cpas_handle = cpas_parms.client_handle;
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
index 6268a1b..cb01c6c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
@@ -37,6 +37,7 @@
 #include <cam_cpas_api.h>
 #include "cam_cci_hwreg.h"
 #include "cam_soc_util.h"
+#include "cam_debug_util.h"
 
 #define V4L2_IDENT_CCI 50005
 #define CCI_I2C_QUEUE_0_SIZE 128
@@ -80,16 +81,6 @@
 #define PRIORITY_QUEUE (QUEUE_0)
 #define SYNC_QUEUE (QUEUE_1)
 
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-
-#undef CCI_DBG
-#ifdef MSM_CCI_DEBUG
-#define CCI_DBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CCI_DBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
 enum cci_i2c_sync {
 	MSM_SYNC_DISABLE,
 	MSM_SYNC_ENABLE,
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
index d976788..83cb49e3 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -27,8 +27,8 @@
 
 	cci_dev = v4l2_get_subdevdata(sd);
 	if (!cci_dev || !c_ctrl) {
-		pr_err("%s:%d failed: invalid params %pK %pK\n", __func__,
-			__LINE__, cci_dev, c_ctrl);
+		CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
+			cci_dev, c_ctrl);
 		rc = -EINVAL;
 		return rc;
 	}
@@ -37,19 +37,18 @@
 	base = soc_info->reg_map[0].mem_base;
 
 	if (!soc_info || !base) {
-		pr_err("%s:%d failed: invalid params %pK %pK\n", __func__,
-			__LINE__, soc_info, base);
+		CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
+			soc_info, base);
 		rc = -EINVAL;
 		return rc;
 	}
 
-	CDBG("%s:%d Base address %pK\n", __func__, __LINE__, base);
+	CAM_DBG(CAM_CCI, "Base address %pK", base);
 
 	if (cci_dev->ref_count++) {
-		CDBG("%s:%d ref_count %d\n", __func__, __LINE__,
-			cci_dev->ref_count);
+		CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count);
 		master = c_ctrl->cci_info->cci_i2c_master;
-		CDBG("%s:%d master %d\n", __func__, __LINE__, master);
+		CAM_DBG(CAM_CCI, "master %d", master);
 		if (master < MASTER_MAX && master >= 0) {
 			mutex_lock(&cci_dev->cci_master_info[master].mutex);
 			flush_workqueue(cci_dev->write_wq[master]);
@@ -74,8 +73,7 @@
 				reset_complete,
 				CCI_TIMEOUT);
 			if (rc <= 0)
-				pr_err("%s:%d wait failed %d\n", __func__,
-					__LINE__, rc);
+				CAM_ERR(CAM_CCI, "wait failed %d", rc);
 			mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 		}
 		return 0;
@@ -89,8 +87,7 @@
 	rc = cam_cpas_start(cci_dev->cpas_handle,
 		&ahb_vote, &axi_vote);
 	if (rc != 0) {
-		pr_err("%s:%d CPAS start failed\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CCI, "CPAS start failed");
 	}
 	cam_cci_get_clk_rates(cci_dev, c_ctrl);
 
@@ -104,15 +101,13 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, true);
 	if (rc < 0) {
-		CDBG("%s:%d request platform resources failed\n", __func__,
-			__LINE__);
+		CAM_DBG(CAM_CCI, "request platform resources failed");
 		goto platform_enable_failed;
 	}
 
 	cci_dev->hw_version = cam_io_r_mb(base +
 		CCI_HW_VERSION_ADDR);
-	CDBG("%s:%d: hw_version = 0x%x\n", __func__, __LINE__,
-		cci_dev->hw_version);
+	CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version);
 
 	cci_dev->payload_size =
 		MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11;
@@ -129,12 +124,11 @@
 					max_queue_size =
 						CCI_I2C_QUEUE_1_SIZE;
 
-			CDBG("%s:%d : CCI Master[%d] :: Q0 : %d Q1 : %d\n",
-				__func__, __LINE__, i,
+			CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i
+				, cci_dev->cci_i2c_queue_info[i][j].
+					max_queue_size,
 				cci_dev->cci_i2c_queue_info[i][j].
-				max_queue_size,
-				cci_dev->cci_i2c_queue_info[i][j].
-				max_queue_size);
+					max_queue_size);
 		}
 	}
 
@@ -146,8 +140,7 @@
 		&cci_dev->cci_master_info[MASTER_0].reset_complete,
 		CCI_TIMEOUT);
 	if (rc <= 0) {
-		pr_err("%s:%d wait_for_completion_timeout\n",
-			 __func__, __LINE__);
+		CAM_ERR(CAM_CCI, "wait_for_completion_timeout");
 		if (rc == 0)
 			rc = -ETIMEDOUT;
 		goto reset_complete_failed;
@@ -162,8 +155,7 @@
 
 	for (i = 0; i < MASTER_MAX; i++) {
 		if (!cci_dev->write_wq[i]) {
-			pr_err("%s:%d Failed to flush write wq\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CCI, "Failed to flush write wq");
 			rc = -ENOMEM;
 			goto reset_complete_failed;
 		} else {
@@ -251,77 +243,75 @@
 				"qcom,i2c_custom_mode");
 
 		rc = of_property_read_u32(src_node, "hw-thigh", &val);
-		CDBG("%s:%d hw-thigh %d, rc %d\n", __func__, __LINE__, val, rc);
+		CAM_DBG(CAM_CCI, "hw-thigh %d, rc %d", val, rc);
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_thigh = val;
 			rc = of_property_read_u32(src_node, "hw-tlow",
 				&val);
-			CDBG("%s:%d hw-tlow %d, rc %d\n", __func__, __LINE__,
+			CAM_DBG(CAM_CCI, "hw-tlow %d, rc %d",
 				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_tlow = val;
 			rc = of_property_read_u32(src_node, "hw-tsu-sto",
 				&val);
-			CDBG("%s:%d hw-tsu-sto %d, rc %d\n",
-				__func__, __LINE__, val, rc);
+			CAM_DBG(CAM_CCI, "hw-tsu-sto %d, rc %d",
+				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_tsu_sto = val;
 			rc = of_property_read_u32(src_node, "hw-tsu-sta",
 				&val);
-			CDBG("%s:%d hw-tsu-sta %d, rc %d\n",
-				__func__, __LINE__, val, rc);
+			CAM_DBG(CAM_CCI, "hw-tsu-sta %d, rc %d",
+				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_tsu_sta = val;
 			rc = of_property_read_u32(src_node, "hw-thd-dat",
 				&val);
-			CDBG("%s:%d hw-thd-dat %d, rc %d\n",
-				__func__, __LINE__, val, rc);
+			CAM_DBG(CAM_CCI, "hw-thd-dat %d, rc %d",
+				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_thd_dat = val;
 			rc = of_property_read_u32(src_node, "hw-thd-sta",
 				&val);
-			CDBG("%s:%d hw-thd-sta %d, rc %d\n", __func__, __LINE__,
+			CAM_DBG(CAM_CCI, "hw-thd-sta %d, rc %d",
 				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_thd_sta = val;
 			rc = of_property_read_u32(src_node, "hw-tbuf",
 				&val);
-			CDBG("%s:%d hw-tbuf %d, rc %d\n", __func__, __LINE__,
+			CAM_DBG(CAM_CCI, "hw-tbuf %d, rc %d",
 				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_tbuf = val;
 			rc = of_property_read_u32(src_node,
 				"hw-scl-stretch-en", &val);
-			CDBG("%s:%d hw-scl-stretch-en %d, rc %d\n",
-				__func__, __LINE__, val, rc);
+			CAM_DBG(CAM_CCI, "hw-scl-stretch-en %d, rc %d",
+				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_scl_stretch_en = val;
 			rc = of_property_read_u32(src_node, "hw-trdhld",
 				&val);
-			CDBG("%s:%d hw-trdhld %d, rc %d\n",
-				__func__, __LINE__, val, rc);
+			CAM_DBG(CAM_CCI, "hw-trdhld %d, rc %d",
+				val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_trdhld = val;
 			rc = of_property_read_u32(src_node, "hw-tsp",
 				&val);
-			CDBG("%s:%d hw-tsp %d, rc %d\n", __func__, __LINE__,
-				val, rc);
+			CAM_DBG(CAM_CCI, "hw-tsp %d, rc %d", val, rc);
 		}
 		if (!rc) {
 			cci_dev->cci_clk_params[count].hw_tsp = val;
 			val = 0;
 			rc = of_property_read_u32(src_node, "cci-clk-src",
 				&val);
-			CDBG("%s:%d cci-clk-src %d, rc %d\n",
-				__func__, __LINE__, val, rc);
+			CAM_DBG(CAM_CCI, "cci-clk-src %d, rc %d", val, rc);
 			cci_dev->cci_clk_params[count].cci_clk_src = val;
 		} else
 			cam_cci_init_default_clk_params(cci_dev, count);
@@ -339,8 +329,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: Parsing DT data failed:%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "Parsing DT data failed:%d", rc);
 		return -EINVAL;
 	}
 
@@ -349,8 +338,7 @@
 	rc = cam_soc_util_request_platform_resource(soc_info,
 		cam_cci_irq, new_cci_dev);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: requesting platform resources failed:%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "requesting platform resources failed:%d", rc);
 		return -EINVAL;
 	}
 	new_cci_dev->v4l2_dev_str.pdev = pdev;
@@ -359,17 +347,15 @@
 
 	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 	if (rc)
-		pr_err("%s:%d failed to add child nodes, rc=%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "failed to add child nodes, rc=%d", rc);
 
 	for (i = 0; i < MASTER_MAX; i++) {
 		new_cci_dev->write_wq[i] = create_singlethread_workqueue(
 			"cam_cci_wq");
 		if (!new_cci_dev->write_wq[i])
-			pr_err("%s:%d Failed to create write wq\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CCI, "Failed to create write wq");
 	}
-	CDBG("%s line %d\n", __func__, __LINE__);
+	CAM_DBG(CAM_CCI, "Exit");
 	return 0;
 }
 
@@ -380,13 +366,12 @@
 		&cci_dev->soc_info;
 
 	if (!cci_dev->ref_count || cci_dev->cci_state != CCI_STATE_ENABLED) {
-		pr_err("%s:%d invalid ref count %d / cci state %d\n", __func__,
-			__LINE__, cci_dev->ref_count, cci_dev->cci_state);
+		CAM_ERR(CAM_CCI, "invalid ref count %d / cci state %d",
+			cci_dev->ref_count, cci_dev->cci_state);
 		return -EINVAL;
 	}
 	if (--cci_dev->ref_count) {
-		CDBG("%s:%d ref_count Exit %d\n", __func__, __LINE__,
-			cci_dev->ref_count);
+		CAM_DBG(CAM_CCI, "ref_count Exit %d", cci_dev->ref_count);
 		return 0;
 	}
 	for (i = 0; i < MASTER_MAX; i++)
@@ -398,8 +383,8 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc) {
-		pr_err("%s:%d: platform resources disable failed, rc=%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CCI, "platform resources disable failed, rc=%d",
+			rc);
 		return rc;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 6b20bcc..fcf76c8 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -63,7 +63,7 @@
 	size_t                  len;
 
 	if (!cfg_dev || !csiphy_dev) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -75,16 +75,16 @@
 	rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle,
 		(uint64_t *)&generic_ptr, &len);
 	if (rc < 0) {
-		pr_err("%s:%d :ERROR: Failed to get packet Mem address: %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc);
 		kfree(csiphy_dev->csiphy_info);
 		csiphy_dev->csiphy_info = NULL;
 		return rc;
 	}
 
 	if (cfg_dev->offset > len) {
-		pr_err("%s: %d offset is out of bounds: offset: %lld len: %zu\n",
-			__func__, __LINE__, cfg_dev->offset, len);
+		CAM_ERR(CAM_CSIPHY,
+			"offset is out of bounds: offset: %lld len: %zu",
+			cfg_dev->offset, len);
 		kfree(csiphy_dev->csiphy_info);
 		csiphy_dev->csiphy_info = NULL;
 		return -EINVAL;
@@ -99,8 +99,8 @@
 	rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
 		(uint64_t *)&generic_ptr, &len);
 	if (rc < 0) {
-		pr_err("%s:%d :ERROR: Failed to get cmd buf Mem address : %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CSIPHY,
+			"Failed to get cmd buf Mem address : %d", rc);
 		kfree(csiphy_dev->csiphy_info);
 		csiphy_dev->csiphy_info = NULL;
 		return rc;
@@ -158,8 +158,7 @@
 	void __iomem *base = NULL;
 
 	if (!csiphy_dev) {
-		pr_err("%s:%d Invalid Args\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -175,9 +174,9 @@
 			base +
 			csiphy_dev->ctrl_reg->csiphy_reg.
 			mipi_csiphy_interrupt_clear0_addr + 0x4*i);
-		pr_err_ratelimited(
-			"%s CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x\n",
-			__func__, soc_info->index, i, irq);
+		CAM_ERR_RATE_LIMIT(CAM_CSIPHY,
+			"CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x",
+			soc_info->index, i, irq);
 		cam_io_w_mb(0x0,
 			base +
 			csiphy_dev->ctrl_reg->csiphy_reg.
@@ -204,8 +203,7 @@
 	struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE];
 
 	if (csiphy_dev->csiphy_info == NULL) {
-		pr_err("%s:%d csiphy_info is NULL, No/Fail CONFIG_DEV ?\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "csiphy_info is NULL, No/Fail CONFIG_DEV?");
 		return -EINVAL;
 	}
 
@@ -215,7 +213,7 @@
 	csiphybase = csiphy_dev->soc_info.reg_map[0].mem_base;
 
 	if (!csiphybase) {
-		pr_err("%s: csiphybase NULL\n", __func__);
+		CAM_ERR(CAM_CSIPHY, "csiphybase NULL");
 		return -EINVAL;
 	}
 
@@ -305,7 +303,7 @@
 					reg_array[lane_pos][i].reg_addr);
 			break;
 			default:
-				CDBG("%s: %d Do Nothing\n", __func__, __LINE__);
+				CAM_DBG(CAM_CSIPHY, "Do Nothing");
 			break;
 			}
 			usleep_range(reg_array[lane_pos][i].delay*1000,
@@ -329,13 +327,11 @@
 	int32_t              rc = 0;
 
 	if (!csiphy_dev || !cmd) {
-		pr_err("%s:%d Invalid input args\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "Invalid input args");
 		return -EINVAL;
 	}
 
-	pr_debug("%s:%d Opcode received: %d\n", __func__, __LINE__,
-		cmd->op_code);
+	CAM_DBG(CAM_CSIPHY, "Opcode received: %d", cmd->op_code);
 	mutex_lock(&csiphy_dev->mutex);
 	switch (cmd->op_code) {
 	case CAM_ACQUIRE_DEV: {
@@ -348,16 +344,15 @@
 			(void __user *)cmd->handle,
 			sizeof(csiphy_acq_dev));
 		if (rc < 0) {
-			pr_err("%s:%d :ERROR: Failed copying from User\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "Failed copying from User");
 			goto release_mutex;
 		}
 
 		csiphy_acq_params.combo_mode = 0;
 
 		if (csiphy_dev->acquire_count == 2) {
-			pr_err("%s:%d CSIPHY device do not allow more than 2 acquires\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY,
+					"CSIPHY device do not allow more than 2 acquires");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -380,8 +375,7 @@
 		if (copy_to_user((void __user *)cmd->handle,
 				&csiphy_acq_dev,
 				sizeof(struct cam_sensor_acquire_dev))) {
-			pr_err("%s:%d :ERROR: Failed copying from User\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "Failed copying from User");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -391,13 +385,12 @@
 	}
 		break;
 	case CAM_QUERY_CAP: {
-		struct cam_csiphy_query_cap csiphy_cap;
+		struct cam_csiphy_query_cap csiphy_cap = {0};
 
 		cam_csiphy_query_cap(csiphy_dev, &csiphy_cap);
 		if (copy_to_user((void __user *)cmd->handle,
 			&csiphy_cap, sizeof(struct cam_csiphy_query_cap))) {
-			pr_err("%s:%d :ERROR: Failed copying from User\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "Failed copying from User");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -406,15 +399,13 @@
 	case CAM_STOP_DEV: {
 		rc = cam_csiphy_disable_hw(csiphy_dev);
 		if (rc < 0) {
-			pr_err("%s:%d Failed in csiphy release\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
 			cam_cpas_stop(csiphy_dev->cpas_handle);
 			goto release_mutex;
 		}
 		rc = cam_cpas_stop(csiphy_dev->cpas_handle);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: de-voting CPAS: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc);
 			goto release_mutex;
 		}
 	}
@@ -423,8 +414,7 @@
 		struct cam_release_dev_cmd release;
 
 		if (!csiphy_dev->acquire_count) {
-			pr_err("%s:%d No valid devices to release\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "No valid devices to release");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -437,8 +427,7 @@
 
 		rc = cam_destroy_device_hdl(release.dev_handle);
 		if (rc < 0)
-			pr_err("%s:%d :ERROR: destroying the device hdl\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "destroying the device hdl");
 		if (release.dev_handle ==
 			csiphy_dev->bridge_intf.device_hdl[0]) {
 			csiphy_dev->bridge_intf.device_hdl[0] = -1;
@@ -462,8 +451,7 @@
 		} else {
 			rc = cam_cmd_buf_parser(csiphy_dev, &config);
 			if (rc < 0) {
-				pr_err("%s:%d Fail in cmd buf parser\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_CSIPHY, "Fail in cmd buf parser");
 				goto release_mutex;
 			}
 		}
@@ -481,22 +469,19 @@
 		rc = cam_cpas_start(csiphy_dev->cpas_handle,
 			&ahb_vote, &axi_vote);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: voting CPAS: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_CSIPHY, "voting CPAS: %d", rc);
 			goto release_mutex;
 		}
 
 		rc = cam_csiphy_enable_hw(csiphy_dev);
 		if (rc != 0) {
-			pr_err("%s: %d cam_csiphy_enable_hw failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "cam_csiphy_enable_hw failed");
 			cam_cpas_stop(csiphy_dev->cpas_handle);
 			goto release_mutex;
 		}
 		rc = cam_csiphy_config_dev(csiphy_dev);
 		if (rc < 0) {
-			pr_err("%s: %d cam_csiphy_config_dev failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "cam_csiphy_config_dev failed");
 			cam_cpas_stop(csiphy_dev->cpas_handle);
 			goto release_mutex;
 		}
@@ -505,8 +490,7 @@
 	case CAM_SD_SHUTDOWN:
 		break;
 	default:
-		pr_err("%s:%d :Error: Invalid Opcode: %d\n",
-			__func__, __LINE__, cmd->op_code);
+		CAM_ERR(CAM_CSIPHY, "Invalid Opcode: %d", cmd->op_code);
 		rc = -EINVAL;
 		goto release_mutex;
 	}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
index 7783b2e..1c93a1a 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
@@ -16,13 +16,6 @@
 #include "cam_csiphy_core.h"
 #include <media/cam_sensor.h>
 
-#undef CDBG
-#ifdef CAM_CSIPHY_DEV_DEBUG
-#define CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
 static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, void *arg)
 {
@@ -33,13 +26,12 @@
 	case VIDIOC_CAM_CONTROL:
 		rc = cam_csiphy_core_cfg(csiphy_dev, arg);
 		if (rc != 0) {
-			pr_err("%s: %d :ERROR: in configuring the device\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_CSIPHY, "in configuring the device");
 			return rc;
 		}
 		break;
 	default:
-		pr_err("%s:%d :ERROR: Wrong ioctl\n", __func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd);
 		break;
 	}
 
@@ -55,7 +47,7 @@
 
 	if (copy_from_user(&cmd_data, (void __user *)arg,
 		sizeof(cmd_data))) {
-		pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+		CAM_ERR(CAM_CSIPHY, "Failed to copy from user_ptr=%pK size=%zu",
 			(void __user *)arg, sizeof(cmd_data));
 		return -EFAULT;
 	}
@@ -68,15 +60,15 @@
 		rc = cam_csiphy_subdev_ioctl(sd, cmd, &cmd_data);
 		break;
 	default:
-		pr_err("%s:%d Invalid compat ioctl cmd: %d\n",
-			__func__, __LINE__, cmd);
+		CAM_ERR(CAM_CSIPHY, "Invalid compat ioctl cmd: %d", cmd);
 		rc = -EINVAL;
 	}
 
 	if (!rc) {
 		if (copy_to_user((void __user *)arg, &cmd_data,
 			sizeof(cmd_data))) {
-			pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+			CAM_ERR(CAM_CSIPHY,
+				"Failed to copy to user_ptr=%pK size=%zu",
 				(void __user *)arg, sizeof(cmd_data));
 			rc = -EFAULT;
 		}
@@ -126,8 +118,7 @@
 
 	rc = cam_csiphy_parse_dt_info(pdev, new_csiphy_dev);
 	if (rc < 0) {
-		pr_err("%s:%d :ERROR: dt parsing failed: %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CSIPHY, "DT parsing failed: %d", rc);
 		goto csiphy_no_resource;
 	}
 
@@ -148,8 +139,7 @@
 
 	rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str));
 	if (rc < 0) {
-		pr_err("%s:%d :ERROR: In cam_register_subdev\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "cam_register_subdev Failed rc: %d", rc);
 		goto csiphy_no_resource;
 	}
 
@@ -176,11 +166,10 @@
 	strlcpy(cpas_parms.identifier, "csiphy", CAM_HW_IDENTIFIER_LENGTH);
 	rc = cam_cpas_register_client(&cpas_parms);
 	if (rc) {
-		pr_err("%s:%d CPAS registration failed\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "CPAS registration failed rc: %d", rc);
 		goto csiphy_no_resource;
 	}
-	CDBG("CPAS registration successful handle=%d\n",
+	CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d",
 		cpas_parms.client_handle);
 	new_csiphy_dev->cpas_handle = cpas_parms.client_handle;
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
index c4258bd..8ed5ba4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
@@ -34,6 +34,7 @@
 #include <cam_io_util.h>
 #include <cam_cpas_api.h>
 #include "cam_soc_util.h"
+#include "cam_debug_util.h"
 
 #define MAX_CSIPHY                  3
 #define MAX_DPHY_DATA_LN            4
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
index 6b5aba9..a79e0d4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
@@ -14,6 +14,29 @@
 #include "cam_csiphy_core.h"
 #include "include/cam_csiphy_1_0_hwreg.h"
 
+#ifdef CAM_CSIPHY_MEM_DMP
+int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info)
+{
+	int32_t rc = 0;
+	resource_size_t size = 0;
+	void __iomem *addr = NULL;
+
+	if (!soc_info) {
+		rc = -EINVAL;
+		CAM_ERR(CAM_CSIPHY, "invalid input %d", rc);
+		return rc;
+	}
+	addr = soc_info->reg_map[0].mem_base;
+	size = resource_size(soc_info->mem_block[0]);
+	rc = cam_io_dump(addr, 0, (size >> 2));
+	if (rc < 0) {
+		CAM_ERR(CAM_CSIPHY, "generating dump failed %d", rc);
+		return rc;
+	}
+	return rc;
+}
+#endif
+
 int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev)
 {
 	int32_t rc = 0;
@@ -22,16 +45,16 @@
 	soc_info = &csiphy_dev->soc_info;
 
 	if (csiphy_dev->ref_count++) {
-		pr_err("%s:%d csiphy refcount = %d\n", __func__,
-			__LINE__, csiphy_dev->ref_count);
+		CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d",
+			csiphy_dev->ref_count);
 		return rc;
 	}
 
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, ENABLE_IRQ);
 	if (rc < 0) {
-		pr_err("%s:%d failed to enable platform resources %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d",
+			rc);
 		return rc;
 	}
 
@@ -41,8 +64,7 @@
 		soc_info->clk_rate[0][csiphy_dev->csiphy_clk_index]);
 
 	if (rc < 0) {
-		pr_err("%s:%d csiphy_clk_set_rate failed\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "csiphy_clk_set_rate failed rc: %d", rc);
 		goto csiphy_disable_platform_resource;
 	}
 
@@ -62,15 +84,14 @@
 	struct cam_hw_soc_info   *soc_info;
 
 	if (!csiphy_dev || !csiphy_dev->ref_count) {
-		pr_err("%s:%d csiphy dev NULL / ref_count ZERO\n", __func__,
-			__LINE__);
+		CAM_ERR(CAM_CSIPHY, "csiphy dev NULL / ref_count ZERO");
 		return 0;
 	}
 	soc_info = &csiphy_dev->soc_info;
 
 	if (--csiphy_dev->ref_count) {
-		pr_err("%s:%d csiphy refcount = %d\n", __func__,
-			__LINE__, csiphy_dev->ref_count);
+		CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d",
+			csiphy_dev->ref_count);
 		return 0;
 	}
 
@@ -95,8 +116,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: parsing common soc dt(rc %d)\n",
-			 __func__, __LINE__, rc);
+		CAM_ERR(CAM_CSIPHY, "parsing common soc dt(rc %d)", rc);
 		return  rc;
 	}
 
@@ -117,15 +137,15 @@
 		csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
 		csiphy_dev->clk_lane = 0;
 	} else {
-		pr_err("%s:%d, invalid hw version : 0x%x\n", __func__, __LINE__,
-		csiphy_dev->hw_version);
+		CAM_ERR(CAM_CSIPHY, "invalid hw version : 0x%x",
+			csiphy_dev->hw_version);
 		rc =  -EINVAL;
 		return rc;
 	}
 
 	if (soc_info->num_clk > CSIPHY_NUM_CLK_MAX) {
-		pr_err("%s:%d invalid clk count=%d, max is %d\n", __func__,
-			__LINE__, soc_info->num_clk, CSIPHY_NUM_CLK_MAX);
+		CAM_ERR(CAM_CSIPHY, "invalid clk count=%d, max is %d",
+			soc_info->num_clk, CSIPHY_NUM_CLK_MAX);
 		return -EINVAL;
 	}
 	for (i = 0; i < soc_info->num_clk; i++) {
@@ -155,7 +175,7 @@
 			soc_info->clk_rate[0][clk_cnt];
 			csiphy_dev->csiphy_clk_index = clk_cnt;
 		}
-		CDBG("%s:%d clk_rate[%d] = %d\n", __func__, __LINE__, clk_cnt,
+		CAM_DBG(CAM_CSIPHY, "clk_rate[%d] = %d", clk_cnt,
 			soc_info->clk_rate[0][clk_cnt]);
 		clk_cnt++;
 	}
@@ -168,7 +188,7 @@
 int32_t cam_csiphy_soc_release(struct csiphy_device *csiphy_dev)
 {
 	if (!csiphy_dev) {
-		pr_err("%s:%d csiphy dev NULL\n", __func__, __LINE__);
+		CAM_ERR(CAM_CSIPHY, "csiphy dev NULL");
 		return 0;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
index 94ec79f..4430489 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
@@ -67,4 +67,12 @@
  */
 int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev);
 
+/**
+ * @soc_info: Soc info of cam hw driver module
+ *
+ * This API dumps memory for the entire mapped region
+ * (needs to be macro enabled before use)
+ */
+int cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info);
+
 #endif /* _CAM_CSIPHY_SOC_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/Makefile
new file mode 100644
index 0000000..5490992
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/Makefile
@@ -0,0 +1,8 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom_dev.o cam_eeprom_core.o cam_eeprom_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
new file mode 100644
index 0000000..96697f9
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -0,0 +1,784 @@
+/* Copyright (c) 2017, 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/crc32.h>
+#include <media/cam_sensor.h>
+
+#include "cam_eeprom_core.h"
+#include "cam_eeprom_soc.h"
+#include "cam_debug_util.h"
+
+/**
+ * cam_eeprom_read_memory() - read map data into buffer
+ * @e_ctrl:     eeprom control struct
+ * @block:      block to be read
+ *
+ * This function iterates through blocks stored in block->map, reads each
+ * region and concatenate them into the pre-allocated block->mapdata
+ */
+static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl,
+	struct cam_eeprom_memory_block_t *block)
+{
+	int                                rc = 0;
+	int                                j;
+	struct cam_sensor_i2c_reg_setting  i2c_reg_settings;
+	struct cam_sensor_i2c_reg_array    i2c_reg_array;
+	struct cam_eeprom_memory_map_t    *emap = block->map;
+	struct cam_eeprom_soc_private     *eb_info;
+	uint8_t                           *memptr = block->mapdata;
+
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "e_ctrl is NULL");
+		return -EINVAL;
+	}
+
+	eb_info = (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+
+	for (j = 0; j < block->num_map; j++) {
+		CAM_DBG(CAM_EEPROM, "slave-addr = 0x%X", emap[j].saddr);
+		if (emap[j].saddr) {
+			eb_info->i2c_info.slave_addr = emap[j].saddr;
+			rc = cam_eeprom_update_i2c_info(e_ctrl,
+				&eb_info->i2c_info);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM,
+					"failed: to update i2c info rc %d",
+					rc);
+				return rc;
+			}
+		}
+
+		if (emap[j].page.valid_size) {
+			i2c_reg_settings.addr_type = emap[j].page.addr_type;
+			i2c_reg_settings.data_type = emap[j].page.data_type;
+			i2c_reg_settings.size = 1;
+			i2c_reg_array.reg_addr = emap[j].page.addr;
+			i2c_reg_array.reg_data = emap[j].page.data;
+			i2c_reg_array.delay = emap[j].page.delay;
+			i2c_reg_settings.reg_setting = &i2c_reg_array;
+			rc = camera_io_dev_write(&e_ctrl->io_master_info,
+				&i2c_reg_settings);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM, "page write failed rc %d",
+					rc);
+				return rc;
+			}
+		}
+
+		if (emap[j].pageen.valid_size) {
+			i2c_reg_settings.addr_type = emap[j].pageen.addr_type;
+			i2c_reg_settings.data_type = emap[j].pageen.data_type;
+			i2c_reg_settings.size = 1;
+			i2c_reg_array.reg_addr = emap[j].pageen.addr;
+			i2c_reg_array.reg_data = emap[j].pageen.data;
+			i2c_reg_array.delay = emap[j].pageen.delay;
+			i2c_reg_settings.reg_setting = &i2c_reg_array;
+			rc = camera_io_dev_write(&e_ctrl->io_master_info,
+				&i2c_reg_settings);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM, "page enable failed rc %d",
+					rc);
+				return rc;
+			}
+		}
+
+		if (emap[j].poll.valid_size) {
+			rc = camera_io_dev_poll(&e_ctrl->io_master_info,
+				emap[j].poll.addr, emap[j].poll.data,
+				0, emap[j].poll.addr_type,
+				emap[j].poll.data_type,
+				emap[j].poll.delay);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM, "poll failed rc %d",
+					rc);
+				return rc;
+			}
+		}
+
+		if (emap[j].mem.valid_size) {
+			rc = camera_io_dev_read_seq(&e_ctrl->io_master_info,
+				emap[j].mem.addr, memptr,
+				emap[j].mem.addr_type,
+				emap[j].mem.valid_size);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM, "read failed rc %d",
+					rc);
+				return rc;
+			}
+			memptr += emap[j].mem.valid_size;
+		}
+
+		if (emap[j].pageen.valid_size) {
+			i2c_reg_settings.addr_type = emap[j].pageen.addr_type;
+			i2c_reg_settings.data_type = emap[j].pageen.data_type;
+			i2c_reg_settings.size = 1;
+			i2c_reg_array.reg_addr = emap[j].pageen.addr;
+			i2c_reg_array.reg_data = 0;
+			i2c_reg_array.delay = emap[j].pageen.delay;
+			i2c_reg_settings.reg_setting = &i2c_reg_array;
+			rc = camera_io_dev_write(&e_ctrl->io_master_info,
+				&i2c_reg_settings);
+
+			if (rc) {
+				CAM_ERR(CAM_EEPROM,
+					"page disable failed rc %d",
+					rc);
+				return rc;
+			}
+		}
+	}
+	return rc;
+}
+
+/**
+ * cam_eeprom_power_up - Power up eeprom hardware
+ * @e_ctrl:     ctrl structure
+ * @power_info: power up/down info for eeprom
+ *
+ * Returns success or failure
+ */
+static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl,
+	struct cam_sensor_power_ctrl_t *power_info)
+{
+	int32_t                 rc = 0;
+	struct cam_hw_soc_info *soc_info =
+		&e_ctrl->soc_info;
+
+	/* Parse and fill vreg params for power up settings */
+	rc = msm_camera_fill_vreg_params(
+		&e_ctrl->soc_info,
+		power_info->power_setting,
+		power_info->power_setting_size);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM,
+			"failed to fill vreg params for power up rc:%d", rc);
+		return rc;
+	}
+
+	/* Parse and fill vreg params for power down settings*/
+	rc = msm_camera_fill_vreg_params(
+		&e_ctrl->soc_info,
+		power_info->power_down_setting,
+		power_info->power_down_setting_size);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM,
+			"failed to fill vreg params power down rc:%d", rc);
+		return rc;
+	}
+
+	rc = cam_sensor_core_power_up(power_info, soc_info);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "failed in eeprom power up rc %d", rc);
+		return rc;
+	}
+
+	if (e_ctrl->io_master_info.master_type == CCI_MASTER) {
+		rc = camera_io_init(&(e_ctrl->io_master_info));
+		if (rc) {
+			CAM_ERR(CAM_EEPROM, "cci_init failed");
+			return -EINVAL;
+		}
+	}
+	return rc;
+}
+
+/**
+ * cam_eeprom_power_down - Power down eeprom hardware
+ * @e_ctrl:    ctrl structure
+ *
+ * Returns success or failure
+ */
+static int cam_eeprom_power_down(struct cam_eeprom_ctrl_t *e_ctrl)
+{
+	struct cam_sensor_power_ctrl_t *power_info;
+	struct cam_hw_soc_info         *soc_info;
+	struct cam_eeprom_soc_private  *soc_private;
+	int                             rc = 0;
+
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "failed: e_ctrl %pK", e_ctrl);
+		return -EINVAL;
+	}
+
+	soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	power_info = &soc_private->power_info;
+	soc_info = &e_ctrl->soc_info;
+
+	if (!power_info) {
+		CAM_ERR(CAM_EEPROM, "failed: power_info %pK", power_info);
+		return -EINVAL;
+	}
+	rc = msm_camera_power_down(power_info, soc_info);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "power down the core is failed:%d", rc);
+		return rc;
+	}
+
+	if (e_ctrl->io_master_info.master_type == CCI_MASTER)
+		camera_io_release(&(e_ctrl->io_master_info));
+
+	return rc;
+}
+
+/**
+ * cam_eeprom_match_id - match eeprom id
+ * @e_ctrl:     ctrl structure
+ *
+ * Returns success or failure
+ */
+static int cam_eeprom_match_id(struct cam_eeprom_ctrl_t *e_ctrl)
+{
+	int                      rc;
+	struct camera_io_master *client = &e_ctrl->io_master_info;
+	uint8_t                  id[2];
+
+	rc = cam_spi_query_id(client, 0, &id[0], 2);
+	if (rc)
+		return rc;
+	CAM_DBG(CAM_EEPROM, "read 0x%x 0x%x, check 0x%x 0x%x",
+		id[0], id[1], client->spi_client->mfr_id0,
+		client->spi_client->device_id0);
+	if (id[0] != client->spi_client->mfr_id0
+		|| id[1] != client->spi_client->device_id0)
+		return -ENODEV;
+	return 0;
+}
+
+/**
+ * cam_eeprom_parse_read_memory_map - Parse memory map
+ * @of_node:    device node
+ * @e_ctrl:     ctrl structure
+ *
+ * Returns success or failure
+ */
+int32_t cam_eeprom_parse_read_memory_map(struct device_node *of_node,
+	struct cam_eeprom_ctrl_t *e_ctrl)
+{
+	int32_t                         rc = 0;
+	struct cam_eeprom_soc_private  *soc_private;
+	struct cam_sensor_power_ctrl_t *power_info;
+
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "failed: e_ctrl is NULL");
+		return -EINVAL;
+	}
+
+	soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	power_info = &soc_private->power_info;
+
+	rc = cam_eeprom_parse_dt_memory_map(of_node, &e_ctrl->cal_data);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "failed: eeprom dt parse rc %d", rc);
+		return rc;
+	}
+	rc = cam_eeprom_power_up(e_ctrl, power_info);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "failed: eeprom power up rc %d", rc);
+		goto data_mem_free;
+	}
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE) {
+		rc = cam_eeprom_match_id(e_ctrl);
+		if (rc) {
+			CAM_DBG(CAM_EEPROM, "eeprom not matching %d", rc);
+			goto power_down;
+		}
+	}
+	rc = cam_eeprom_read_memory(e_ctrl, &e_ctrl->cal_data);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "read_eeprom_memory failed");
+		goto power_down;
+	}
+
+	rc = cam_eeprom_power_down(e_ctrl);
+	if (rc)
+		CAM_ERR(CAM_EEPROM, "failed: eeprom power down rc %d", rc);
+	return rc;
+power_down:
+	rc = cam_eeprom_power_down(e_ctrl);
+data_mem_free:
+	kfree(e_ctrl->cal_data.mapdata);
+	kfree(e_ctrl->cal_data.map);
+	return rc;
+}
+
+/**
+ * cam_eeprom_get_dev_handle - get device handle
+ * @e_ctrl:     ctrl structure
+ * @arg:        Camera control command argument
+ *
+ * Returns success or failure
+ */
+static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl,
+	void *arg)
+{
+	struct cam_sensor_acquire_dev    eeprom_acq_dev;
+	struct cam_create_dev_hdl        bridge_params;
+	struct cam_control              *cmd = (struct cam_control *)arg;
+
+	if (e_ctrl->bridge_intf.device_hdl != -1) {
+		CAM_ERR(CAM_EEPROM, "Device is already acquired");
+		return -EFAULT;
+	}
+	if (copy_from_user(&eeprom_acq_dev, (void __user *) cmd->handle,
+		sizeof(eeprom_acq_dev))) {
+		CAM_ERR(CAM_EEPROM,
+			"EEPROM:ACQUIRE_DEV: copy from user failed");
+		return -EFAULT;
+	}
+
+	bridge_params.session_hdl = eeprom_acq_dev.session_handle;
+	bridge_params.ops = &e_ctrl->bridge_intf.ops;
+	bridge_params.v4l2_sub_dev_flag = 0;
+	bridge_params.media_entity_flag = 0;
+	bridge_params.priv = e_ctrl;
+
+	eeprom_acq_dev.device_handle =
+		cam_create_device_hdl(&bridge_params);
+	e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle;
+	e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle;
+
+	CAM_DBG(CAM_EEPROM, "Device Handle: %d", eeprom_acq_dev.device_handle);
+	if (copy_to_user((void __user *) cmd->handle, &eeprom_acq_dev,
+		sizeof(struct cam_sensor_acquire_dev))) {
+		CAM_ERR(CAM_EEPROM, "EEPROM:ACQUIRE_DEV: copy to user failed");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+/**
+ * cam_eeprom_update_slaveInfo - Update slave info
+ * @e_ctrl:     ctrl structure
+ * @cmd_buf:    command buffer
+ *
+ * Returns success or failure
+ */
+static int32_t cam_eeprom_update_slaveInfo(struct cam_eeprom_ctrl_t *e_ctrl,
+	void *cmd_buf)
+{
+	int32_t                         rc = 0;
+	struct cam_eeprom_soc_private  *soc_private;
+	struct cam_cmd_i2c_info        *cmd_i2c_info = NULL;
+
+	soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	cmd_i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+	soc_private->i2c_info.slave_addr = cmd_i2c_info->slave_addr;
+	soc_private->i2c_info.i2c_freq_mode = cmd_i2c_info->i2c_freq_mode;
+
+	rc = cam_eeprom_update_i2c_info(e_ctrl,
+		&soc_private->i2c_info);
+	CAM_DBG(CAM_EEPROM, "Slave addr: 0x%x Freq Mode: %d",
+		soc_private->i2c_info.slave_addr,
+		soc_private->i2c_info.i2c_freq_mode);
+
+	return rc;
+}
+
+/**
+ * cam_eeprom_parse_memory_map - Parse memory map info
+ * @data:             memory block data
+ * @cmd_buf:          command buffer
+ * @cmd_length:       command buffer length
+ * @num_map:          memory map size
+ * @cmd_length_bytes: command length processed in this function
+ *
+ * Returns success or failure
+ */
+static int32_t cam_eeprom_parse_memory_map(
+	struct cam_eeprom_memory_block_t *data,
+	void *cmd_buf, int cmd_length, uint16_t *cmd_length_bytes,
+	int16_t num_map)
+{
+	int32_t                            rc = 0;
+	int32_t                            processed_size = 0;
+	struct cam_eeprom_memory_map_t    *map = data->map;
+	struct common_header              *cmm_hdr =
+		(struct common_header *)cmd_buf;
+	uint16_t                           cmd_length_in_bytes = 0;
+	struct cam_cmd_i2c_random_wr      *i2c_random_wr = NULL;
+	struct cam_cmd_i2c_continuous_rd  *i2c_cont_rd = NULL;
+	struct cam_cmd_conditional_wait   *i2c_poll = NULL;
+
+	switch (cmm_hdr->cmd_type) {
+	case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
+		i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+		cmd_length_in_bytes   = sizeof(struct cam_cmd_i2c_random_wr);
+
+		map[num_map].page.addr =
+			i2c_random_wr->random_wr_payload[0].reg_addr;
+		map[num_map].page.addr_type = i2c_random_wr->header.addr_type;
+		map[num_map].page.data =
+			i2c_random_wr->random_wr_payload[0].reg_data;
+		map[num_map].page.data_type = i2c_random_wr->header.data_type;
+		map[num_map].page.valid_size = 1;
+		cmd_buf += cmd_length_in_bytes / sizeof(int32_t);
+		processed_size +=
+			cmd_length_in_bytes;
+		break;
+	case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD:
+		i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
+		cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
+
+		map[num_map].mem.addr = i2c_cont_rd->reg_addr;
+		map[num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
+		map[num_map].mem.data_type = i2c_cont_rd->header.data_type;
+		map[num_map].mem.valid_size =
+			i2c_cont_rd->header.count;
+		cmd_buf += cmd_length_in_bytes / sizeof(int32_t);
+		processed_size +=
+			cmd_length_in_bytes;
+		data->num_data += map[num_map].mem.valid_size;
+		break;
+	case CAMERA_SENSOR_CMD_TYPE_WAIT:
+		i2c_poll = (struct cam_cmd_conditional_wait *)cmd_buf;
+		cmd_length_in_bytes = sizeof(struct cam_cmd_conditional_wait);
+
+		map[num_map].poll.addr = i2c_poll->reg_addr;
+		map[num_map].poll.addr_type = i2c_poll->addr_type;
+		map[num_map].poll.data = i2c_poll->reg_data;
+		map[num_map].poll.data_type = i2c_poll->data_type;
+		map[num_map].poll.delay = i2c_poll->timeout;
+		map[num_map].poll.valid_size = 1;
+		break;
+	default:
+		break;
+	}
+	*cmd_length_bytes = processed_size;
+	return rc;
+}
+
+/**
+ * cam_eeprom_init_pkt_parser - Parse eeprom packet
+ * @e_ctrl:       ctrl structure
+ * @csl_packet:	  csl packet received
+ *
+ * Returns success or failure
+ */
+static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
+	struct cam_packet *csl_packet)
+{
+	int32_t                         rc = 0;
+	int                             i = 0;
+	struct cam_cmd_buf_desc        *cmd_desc = NULL;
+	uint32_t                       *offset = NULL;
+	uint32_t                       *cmd_buf = NULL;
+	uint64_t                        generic_pkt_addr;
+	size_t                          pkt_len = 0;
+	uint32_t                        total_cmd_buf_in_bytes = 0;
+	uint32_t                        processed_cmd_buf_in_bytes = 0;
+	struct common_header           *cmm_hdr = NULL;
+	uint16_t                        cmd_length_in_bytes = 0;
+	struct cam_cmd_i2c_info        *i2c_info = NULL;
+	int                             num_map = -1;
+	struct cam_eeprom_memory_map_t *map;
+	struct cam_eeprom_soc_private  *soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
+
+	e_ctrl->cal_data.map = kcalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE *
+		MSM_EEPROM_MAX_MEM_MAP_CNT),
+		(sizeof(struct cam_eeprom_memory_map_t)), GFP_KERNEL);
+	if (!e_ctrl->cal_data.map) {
+		rc = -ENOMEM;
+		CAM_ERR(CAM_EEPROM, "failed");
+		return rc;
+	}
+	map = e_ctrl->cal_data.map;
+
+	offset = (uint32_t *)&csl_packet->payload;
+	offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
+	cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+
+	/* Loop through multiple command buffers */
+	for (i = 0; i < csl_packet->num_cmd_buf; i++) {
+		total_cmd_buf_in_bytes = cmd_desc[i].length;
+		processed_cmd_buf_in_bytes = 0;
+		if (!total_cmd_buf_in_bytes)
+			continue;
+		rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
+			(uint64_t *)&generic_pkt_addr, &pkt_len);
+		if (rc) {
+			CAM_ERR(CAM_EEPROM, "Failed to get cpu buf");
+			return rc;
+		}
+		cmd_buf = (uint32_t *)generic_pkt_addr;
+		if (!cmd_buf) {
+			CAM_ERR(CAM_EEPROM, "invalid cmd buf");
+			return -EINVAL;
+		}
+		cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+		/* Loop through multiple cmd formats in one cmd buffer */
+		while (processed_cmd_buf_in_bytes < total_cmd_buf_in_bytes) {
+			cmm_hdr = (struct common_header *)cmd_buf;
+			switch (cmm_hdr->cmd_type) {
+			case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
+				i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+				num_map++;
+				map[num_map].saddr = i2c_info->slave_addr;
+				rc = cam_eeprom_update_slaveInfo(e_ctrl,
+					cmd_buf);
+				cmd_length_in_bytes =
+					sizeof(struct cam_cmd_i2c_info);
+				processed_cmd_buf_in_bytes +=
+					cmd_length_in_bytes;
+				cmd_buf += cmd_length_in_bytes/4;
+				e_ctrl->cal_data.num_map = num_map + 1;
+				break;
+			case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
+			case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
+				cmd_length_in_bytes =
+					sizeof(struct cam_cmd_power);
+				rc = cam_sensor_update_power_settings(cmd_buf,
+					cmd_length_in_bytes, power_info);
+				processed_cmd_buf_in_bytes +=
+					total_cmd_buf_in_bytes;
+				cmd_buf += total_cmd_buf_in_bytes/4;
+				if (rc) {
+					CAM_ERR(CAM_EEPROM, "Failed");
+					return rc;
+				}
+				break;
+			case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
+			case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD:
+			case CAMERA_SENSOR_CMD_TYPE_WAIT:
+				rc = cam_eeprom_parse_memory_map(
+					&e_ctrl->cal_data, cmd_buf,
+					total_cmd_buf_in_bytes,
+					&cmd_length_in_bytes, num_map);
+				processed_cmd_buf_in_bytes +=
+					cmd_length_in_bytes;
+				cmd_buf += cmd_length_in_bytes/4;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+	return rc;
+}
+
+/**
+ * cam_eeprom_get_cal_data - parse the userspace IO config and
+ *                                        copy read data to share with userspace
+ * @e_ctrl:     ctrl structure
+ * @csl_packet: csl packet received
+ *
+ * Returns success or failure
+ */
+static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
+	struct cam_packet *csl_packet)
+{
+	struct cam_buf_io_cfg *io_cfg;
+	uint32_t              i = 0;
+	int                   rc = 0;
+	uint64_t              buf_addr;
+	size_t                buf_size;
+	uint8_t               *read_buffer;
+
+	io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
+		&csl_packet->payload +
+		csl_packet->io_configs_offset);
+
+	CAM_DBG(CAM_EEPROM, "number of IO configs: %d:",
+		csl_packet->num_io_configs);
+
+	for (i = 0; i < csl_packet->num_io_configs; i++) {
+		CAM_DBG(CAM_EEPROM, "Direction: %d:", io_cfg->direction);
+		if (io_cfg->direction == CAM_BUF_OUTPUT) {
+			rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0],
+				(uint64_t *)&buf_addr, &buf_size);
+			CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n",
+				(void *)buf_addr, buf_size);
+
+			read_buffer = (uint8_t *)buf_addr;
+			if (!read_buffer) {
+				CAM_ERR(CAM_EEPROM,
+					"invalid buffer to copy data");
+				return -EINVAL;
+			}
+			read_buffer += io_cfg->offsets[0];
+
+			if (buf_size < e_ctrl->cal_data.num_data) {
+				CAM_ERR(CAM_EEPROM,
+					"failed to copy, Invalid size");
+				return -EINVAL;
+			}
+
+			CAM_ERR(CAM_EEPROM, "copy the data, len:%d",
+				e_ctrl->cal_data.num_data);
+			memcpy(read_buffer, e_ctrl->cal_data.mapdata,
+					e_ctrl->cal_data.num_data);
+
+		} else {
+			CAM_ERR(CAM_EEPROM, "Invalid direction");
+			rc = -EINVAL;
+		}
+	}
+	return rc;
+}
+
+/**
+ * cam_eeprom_pkt_parse - Parse csl packet
+ * @e_ctrl:     ctrl structure
+ * @arg:        Camera control command argument
+ *
+ * Returns success or failure
+ */
+static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
+{
+	int32_t                         rc = 0;
+	struct cam_control             *ioctl_ctrl = NULL;
+	struct cam_config_dev_cmd       dev_config;
+	uint64_t                        generic_pkt_addr;
+	size_t                          pkt_len;
+	struct cam_packet              *csl_packet = NULL;
+	struct cam_eeprom_soc_private  *soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+
+	ioctl_ctrl = (struct cam_control *)arg;
+	if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
+		sizeof(dev_config)))
+		return -EFAULT;
+	rc = cam_mem_get_cpu_buf(dev_config.packet_handle,
+		(uint64_t *)&generic_pkt_addr, &pkt_len);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM,
+			"error in converting command Handle Error: %d", rc);
+		return rc;
+	}
+	csl_packet = (struct cam_packet *)
+		(generic_pkt_addr + dev_config.offset);
+	switch (csl_packet->header.op_code & 0xFFFFFF) {
+	case CAM_EEPROM_PACKET_OPCODE_INIT:
+		if (e_ctrl->userspace_probe == false) {
+			rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
+			CAM_ERR(CAM_EEPROM,
+				"Eeprom already probed at kernel boot");
+			rc = -EINVAL;
+		break;
+		}
+		if (e_ctrl->cal_data.num_data == 0) {
+			rc = cam_eeprom_init_pkt_parser(e_ctrl, csl_packet);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM,
+					"Failed in parsing the pkt");
+				return rc;
+			}
+
+			e_ctrl->cal_data.mapdata =
+				kzalloc(e_ctrl->cal_data.num_data, GFP_KERNEL);
+			if (!e_ctrl->cal_data.mapdata) {
+				rc = -ENOMEM;
+				CAM_ERR(CAM_EEPROM, "failed");
+				goto error;
+			}
+
+			rc = cam_eeprom_power_up(e_ctrl,
+				&soc_private->power_info);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM, "failed rc %d", rc);
+				goto memdata_free;
+			}
+
+			rc = cam_eeprom_read_memory(e_ctrl, &e_ctrl->cal_data);
+			if (rc) {
+				CAM_ERR(CAM_EEPROM,
+					"read_eeprom_memory failed");
+				goto power_down;
+			}
+
+			rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
+			rc = cam_eeprom_power_down(e_ctrl);
+		} else {
+			CAM_DBG(CAM_EEPROM, "Already read eeprom");
+		}
+		break;
+	default:
+		break;
+	}
+	kfree(e_ctrl->cal_data.mapdata);
+	kfree(e_ctrl->cal_data.map);
+	return rc;
+power_down:
+	rc = cam_eeprom_power_down(e_ctrl);
+memdata_free:
+	kfree(e_ctrl->cal_data.mapdata);
+error:
+	kfree(e_ctrl->cal_data.map);
+	return rc;
+}
+
+/**
+ * cam_eeprom_driver_cmd - Handle eeprom cmds
+ * @e_ctrl:     ctrl structure
+ * @arg:        Camera control command argument
+ *
+ * Returns success or failure
+ */
+int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
+{
+	int                            rc = 0;
+	struct cam_eeprom_query_cap_t  eeprom_cap;
+	struct cam_control            *cmd = (struct cam_control *)arg;
+
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "e_ctrl is NULL");
+		return -EINVAL;
+	}
+
+	mutex_lock(&(e_ctrl->eeprom_mutex));
+	switch (cmd->op_code) {
+	case CAM_QUERY_CAP:
+		eeprom_cap.slot_info = e_ctrl->subdev_id;
+		if (e_ctrl->userspace_probe == false)
+			eeprom_cap.eeprom_kernel_probe = true;
+		else
+			eeprom_cap.eeprom_kernel_probe = false;
+
+		if (copy_to_user((void __user *) cmd->handle,
+			&eeprom_cap,
+			sizeof(struct cam_eeprom_query_cap_t))) {
+			CAM_ERR(CAM_EEPROM, "Failed Copy to User");
+			return -EFAULT;
+			goto release_mutex;
+		}
+		CAM_DBG(CAM_EEPROM, "eeprom_cap: ID: %d", eeprom_cap.slot_info);
+		break;
+	case CAM_ACQUIRE_DEV:
+		rc = cam_eeprom_get_dev_handle(e_ctrl, arg);
+		if (rc) {
+			CAM_ERR(CAM_EEPROM, "Failed to acquire dev");
+			goto release_mutex;
+		}
+		break;
+	case CAM_CONFIG_DEV:
+		rc = cam_eeprom_pkt_parse(e_ctrl, arg);
+		if (rc) {
+			CAM_ERR(CAM_EEPROM, "Failed in eeprom pkt Parsing");
+			goto release_mutex;
+		}
+		break;
+	default:
+		CAM_DBG(CAM_EEPROM, "invalid opcode");
+		break;
+	}
+
+release_mutex:
+	mutex_unlock(&(e_ctrl->eeprom_mutex));
+
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.h
new file mode 100644
index 0000000..84736df
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2017, 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 _CAM_EEPROM_CORE_H_
+#define _CAM_EEPROM_CORE_H_
+
+#include "cam_eeprom_dev.h"
+
+int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg);
+int32_t cam_eeprom_parse_read_memory_map(struct device_node *of_node,
+	struct cam_eeprom_ctrl_t *e_ctrl);
+#endif
+/* _CAM_EEPROM_CORE_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
new file mode 100644
index 0000000..82dcc9c
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
@@ -0,0 +1,487 @@
+/* Copyright (c) 2017, 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 "cam_eeprom_dev.h"
+#include "cam_req_mgr_dev.h"
+#include "cam_eeprom_soc.h"
+#include "cam_eeprom_core.h"
+#include "cam_debug_util.h"
+
+static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	int                       rc     = 0;
+	struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd);
+
+	switch (cmd) {
+	case VIDIOC_CAM_CONTROL:
+		rc = cam_eeprom_driver_cmd(e_ctrl, arg);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+
+	return rc;
+}
+
+int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl,
+	struct cam_eeprom_i2c_info_t *i2c_info)
+{
+	struct cam_sensor_cci_client        *cci_client = NULL;
+
+	if (e_ctrl->io_master_info.master_type == CCI_MASTER) {
+		cci_client = e_ctrl->io_master_info.cci_client;
+		if (!cci_client) {
+			CAM_ERR(CAM_EEPROM, "failed: cci_client %pK",
+				cci_client);
+			return -EINVAL;
+		}
+		cci_client->cci_i2c_master = e_ctrl->cci_i2c_master;
+		cci_client->sid = (i2c_info->slave_addr) >> 1;
+		cci_client->retries = 3;
+		cci_client->id_map = 0;
+		cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long cam_eeprom_init_subdev_do_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, unsigned long arg)
+{
+	struct cam_control cmd_data;
+	int32_t rc = 0;
+
+	if (copy_from_user(&cmd_data, (void __user *)arg,
+		sizeof(cmd_data))) {
+		CAM_ERR(CAM_EEPROM,
+			"Failed to copy from user_ptr=%pK size=%zu",
+			(void __user *)arg, sizeof(cmd_data));
+		return -EFAULT;
+	}
+
+	switch (cmd) {
+	case VIDIOC_CAM_CONTROL:
+		rc = cam_eeprom_subdev_ioctl(sd, cmd, &cmd_data);
+		if (rc < 0) {
+			CAM_ERR(CAM_EEPROM,
+				"Failed in eeprom suddev handling rc %d",
+				rc);
+			return rc;
+		}
+		break;
+	default:
+		CAM_ERR(CAM_EEPROM, "Invalid compat ioctl: %d", cmd);
+		rc = -EINVAL;
+	}
+
+	if (!rc) {
+		if (copy_to_user((void __user *)arg, &cmd_data,
+			sizeof(cmd_data))) {
+			CAM_ERR(CAM_EEPROM,
+				"Failed to copy from user_ptr=%pK size=%zu",
+				(void __user *)arg, sizeof(cmd_data));
+			rc = -EFAULT;
+		}
+	}
+	return rc;
+}
+#endif
+
+static const struct v4l2_subdev_internal_ops cam_eeprom_internal_ops;
+
+static struct v4l2_subdev_core_ops cam_eeprom_subdev_core_ops = {
+	.ioctl = cam_eeprom_subdev_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl32 = cam_eeprom_init_subdev_do_ioctl,
+#endif
+};
+
+static struct v4l2_subdev_ops cam_eeprom_subdev_ops = {
+	.core = &cam_eeprom_subdev_core_ops,
+};
+
+static int cam_eeprom_i2c_driver_probe(struct i2c_client *client,
+	 const struct i2c_device_id *id)
+{
+	int                             rc = 0;
+	struct cam_eeprom_ctrl_t       *e_ctrl = NULL;
+	struct cam_eeprom_soc_private  *soc_private = NULL;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		CAM_ERR(CAM_EEPROM, "i2c_check_functionality failed");
+		goto probe_failure;
+	}
+
+	e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL);
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "kzalloc failed");
+		rc = -ENOMEM;
+		goto probe_failure;
+	}
+	e_ctrl->v4l2_dev_str.ops = &cam_eeprom_subdev_ops;
+	soc_private = (struct cam_eeprom_soc_private *)(id->driver_data);
+	if (!soc_private) {
+		CAM_ERR(CAM_EEPROM, "board info NULL");
+		rc = -EINVAL;
+		goto ectrl_free;
+	}
+	e_ctrl->cal_data.mapdata = NULL;
+	e_ctrl->cal_data.map = NULL;
+	e_ctrl->userspace_probe = false;
+
+	e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
+	e_ctrl->io_master_info.master_type = I2C_MASTER;
+	e_ctrl->io_master_info.client = client;
+
+	if (soc_private->i2c_info.slave_addr != 0)
+		e_ctrl->io_master_info.client->addr =
+			soc_private->i2c_info.slave_addr;
+
+	return rc;
+
+ectrl_free:
+	kfree(e_ctrl);
+probe_failure:
+	return rc;
+}
+
+static int cam_eeprom_i2c_driver_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev             *sd = i2c_get_clientdata(client);
+	struct cam_eeprom_ctrl_t       *e_ctrl;
+	struct cam_eeprom_soc_private  *soc_private;
+
+	if (!sd) {
+		CAM_ERR(CAM_EEPROM, "Subdevice is NULL");
+		return -EINVAL;
+	}
+
+	e_ctrl = (struct cam_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "eeprom device is NULL");
+		return -EINVAL;
+	}
+
+	soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	if (!soc_private) {
+		CAM_ERR(CAM_EEPROM, "soc_info.soc_private is NULL");
+		return -EINVAL;
+	}
+
+	kfree(e_ctrl->cal_data.mapdata);
+	kfree(e_ctrl->cal_data.map);
+	if (soc_private) {
+		kfree(soc_private->power_info.gpio_num_info);
+		kfree(soc_private);
+	}
+	kfree(e_ctrl);
+
+	return 0;
+}
+
+static int cam_eeprom_spi_setup(struct spi_device *spi)
+{
+	struct cam_eeprom_ctrl_t       *e_ctrl = NULL;
+	struct cam_sensor_spi_client   *spi_client;
+	struct cam_eeprom_soc_private  *eb_info;
+	struct cam_sensor_power_ctrl_t *power_info = NULL;
+	int                             rc = 0;
+
+	e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL);
+	if (!e_ctrl)
+		return -ENOMEM;
+
+	e_ctrl->v4l2_dev_str.ops = &cam_eeprom_subdev_ops;
+	e_ctrl->userspace_probe = false;
+	e_ctrl->cal_data.mapdata = NULL;
+	e_ctrl->cal_data.map = NULL;
+
+	spi_client = kzalloc(sizeof(*spi_client), GFP_KERNEL);
+	if (!spi_client) {
+		kfree(e_ctrl);
+		return -ENOMEM;
+	}
+
+	eb_info = kzalloc(sizeof(*eb_info), GFP_KERNEL);
+	if (!eb_info)
+		goto spi_free;
+	e_ctrl->soc_info.soc_private = eb_info;
+
+	e_ctrl->eeprom_device_type = MSM_CAMERA_SPI_DEVICE;
+	e_ctrl->io_master_info.spi_client = spi_client;
+	e_ctrl->io_master_info.master_type = SPI_MASTER;
+	spi_client->spi_master = spi;
+
+	power_info = &eb_info->power_info;
+	power_info->dev = &spi->dev;
+
+	/* set spi instruction info */
+	spi_client->retry_delay = 1;
+	spi_client->retries = 0;
+
+	/* Initialize mutex */
+	mutex_init(&(e_ctrl->eeprom_mutex));
+
+	rc = cam_eeprom_spi_driver_soc_init(e_ctrl);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "failed: spi soc init rc %d", rc);
+		goto board_free;
+	}
+
+	if (e_ctrl->userspace_probe == false) {
+		rc = cam_eeprom_parse_read_memory_map(spi->dev.of_node,
+			e_ctrl);
+		if (rc) {
+			CAM_ERR(CAM_EEPROM, "failed: read mem map rc %d", rc);
+			goto board_free;
+		}
+	}
+
+	return rc;
+
+board_free:
+	kfree(e_ctrl->soc_info.soc_private);
+spi_free:
+	kfree(spi_client);
+	kfree(e_ctrl);
+	return rc;
+}
+
+static int cam_eeprom_spi_driver_probe(struct spi_device *spi)
+{
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	spi_setup(spi);
+
+	CAM_DBG(CAM_EEPROM, "irq[%d] cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x]",
+		spi->irq, spi->chip_select, (spi->mode & SPI_CPHA) ? 1 : 0,
+		(spi->mode & SPI_CPOL) ? 1 : 0,
+		(spi->mode & SPI_CS_HIGH) ? 1 : 0);
+	CAM_DBG(CAM_EEPROM, "max_speed[%u]", spi->max_speed_hz);
+
+	return cam_eeprom_spi_setup(spi);
+}
+
+static int cam_eeprom_spi_driver_remove(struct spi_device *sdev)
+{
+	struct v4l2_subdev             *sd = spi_get_drvdata(sdev);
+	struct cam_eeprom_ctrl_t       *e_ctrl;
+	struct cam_eeprom_soc_private  *soc_private;
+
+	if (!sd) {
+		CAM_ERR(CAM_EEPROM, "Subdevice is NULL");
+		return -EINVAL;
+	}
+
+	e_ctrl = (struct cam_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "eeprom device is NULL");
+		return -EINVAL;
+	}
+
+	kfree(e_ctrl->io_master_info.spi_client);
+	kfree(e_ctrl->cal_data.mapdata);
+	kfree(e_ctrl->cal_data.map);
+	soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	if (soc_private) {
+		kfree(soc_private->power_info.gpio_num_info);
+		kfree(soc_private);
+	}
+	kfree(e_ctrl);
+
+	return 0;
+}
+
+static int32_t cam_eeprom_platform_driver_probe(
+	struct platform_device *pdev)
+{
+	int32_t                         rc = 0;
+	struct cam_eeprom_ctrl_t       *e_ctrl = NULL;
+	struct cam_eeprom_soc_private  *soc_private = NULL;
+
+	e_ctrl = kzalloc(sizeof(struct cam_eeprom_ctrl_t), GFP_KERNEL);
+	if (!e_ctrl)
+		return -ENOMEM;
+
+	e_ctrl->soc_info.pdev = pdev;
+	e_ctrl->eeprom_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+	e_ctrl->cal_data.mapdata = NULL;
+	e_ctrl->cal_data.map = NULL;
+	e_ctrl->userspace_probe = false;
+
+	e_ctrl->io_master_info.master_type = CCI_MASTER;
+	e_ctrl->io_master_info.cci_client = kzalloc(
+		sizeof(struct cam_sensor_cci_client), GFP_KERNEL);
+	if (!e_ctrl->io_master_info.cci_client)
+		goto free_e_ctrl;
+
+	soc_private = kzalloc(sizeof(struct cam_eeprom_soc_private),
+		GFP_KERNEL);
+	if (!soc_private) {
+		rc = -ENOMEM;
+		goto free_cci_client;
+	}
+	e_ctrl->soc_info.soc_private = soc_private;
+
+	/* Initialize mutex */
+	mutex_init(&(e_ctrl->eeprom_mutex));
+	rc = cam_eeprom_platform_driver_soc_init(e_ctrl);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "failed: soc init rc %d", rc);
+		goto free_soc;
+	}
+	rc = cam_eeprom_update_i2c_info(e_ctrl, &soc_private->i2c_info);
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "failed: to update i2c info rc %d", rc);
+		goto free_soc;
+	}
+
+	if (e_ctrl->userspace_probe == false) {
+		rc = cam_eeprom_parse_read_memory_map(pdev->dev.of_node,
+			e_ctrl);
+		if (rc) {
+			CAM_ERR(CAM_EEPROM, "failed: read mem map rc %d", rc);
+			goto free_soc;
+		}
+	}
+
+	e_ctrl->v4l2_dev_str.internal_ops = &cam_eeprom_internal_ops;
+	e_ctrl->v4l2_dev_str.ops = &cam_eeprom_subdev_ops;
+	strlcpy(e_ctrl->device_name, CAM_EEPROM_NAME,
+		sizeof(e_ctrl->device_name));
+	e_ctrl->v4l2_dev_str.name = e_ctrl->device_name;
+	e_ctrl->v4l2_dev_str.sd_flags =
+		(V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
+	e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE;
+	e_ctrl->v4l2_dev_str.token = e_ctrl;
+
+	rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str));
+	if (rc) {
+		CAM_ERR(CAM_EEPROM, "fail to create subdev");
+		goto free_soc;
+	}
+
+	e_ctrl->bridge_intf.device_hdl = -1;
+	e_ctrl->bridge_intf.ops.get_dev_info = NULL;
+	e_ctrl->bridge_intf.ops.link_setup = NULL;
+	e_ctrl->bridge_intf.ops.apply_req = NULL;
+
+	platform_set_drvdata(pdev, e_ctrl);
+	v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, e_ctrl);
+	return rc;
+free_soc:
+	kfree(soc_private);
+free_cci_client:
+	kfree(e_ctrl->io_master_info.cci_client);
+free_e_ctrl:
+	kfree(e_ctrl);
+	return rc;
+}
+
+static int cam_eeprom_platform_driver_remove(struct platform_device *pdev)
+{
+	struct cam_eeprom_ctrl_t  *e_ctrl;
+
+	e_ctrl = platform_get_drvdata(pdev);
+	if (!e_ctrl) {
+		CAM_ERR(CAM_EEPROM, "eeprom device is NULL");
+		return -EINVAL;
+	}
+
+	kfree(e_ctrl->soc_info.soc_private);
+	kfree(e_ctrl->io_master_info.cci_client);
+	kfree(e_ctrl);
+	return 0;
+}
+
+static const struct of_device_id cam_eeprom_dt_match[] = {
+	{ .compatible = "qcom,eeprom" },
+	{ }
+};
+
+
+MODULE_DEVICE_TABLE(of, cam_eeprom_dt_match);
+
+static struct platform_driver cam_eeprom_platform_driver = {
+	.driver = {
+		.name = "qcom,eeprom",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_eeprom_dt_match,
+	},
+	.probe = cam_eeprom_platform_driver_probe,
+	.remove = cam_eeprom_platform_driver_remove,
+};
+
+static const struct i2c_device_id cam_eeprom_i2c_id[] = {
+	{ "msm_eeprom", (kernel_ulong_t)NULL},
+	{ }
+};
+
+static struct i2c_driver cam_eeprom_i2c_driver = {
+	.id_table = cam_eeprom_i2c_id,
+	.probe  = cam_eeprom_i2c_driver_probe,
+	.remove = cam_eeprom_i2c_driver_remove,
+	.driver = {
+		.name = "msm_eeprom",
+	},
+};
+
+static struct spi_driver cam_eeprom_spi_driver = {
+	.driver = {
+		.name = "qcom_eeprom",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_eeprom_dt_match,
+	},
+	.probe = cam_eeprom_spi_driver_probe,
+	.remove = cam_eeprom_spi_driver_remove,
+};
+static int __init cam_eeprom_driver_init(void)
+{
+	int rc = 0;
+
+	rc = platform_driver_register(&cam_eeprom_platform_driver);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "platform_driver_register failed rc = %d",
+			rc);
+		return rc;
+	}
+
+	rc = spi_register_driver(&cam_eeprom_spi_driver);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "spi_register_driver failed rc = %d", rc);
+		return rc;
+	}
+
+	rc = i2c_add_driver(&cam_eeprom_i2c_driver);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "i2c_add_driver failed rc = %d", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+static void __exit cam_eeprom_driver_exit(void)
+{
+	platform_driver_unregister(&cam_eeprom_platform_driver);
+	spi_unregister_driver(&cam_eeprom_spi_driver);
+	i2c_del_driver(&cam_eeprom_i2c_driver);
+}
+
+module_init(cam_eeprom_driver_init);
+module_exit(cam_eeprom_driver_exit);
+MODULE_DESCRIPTION("CAM EEPROM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
new file mode 100644
index 0000000..a98bf00
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
@@ -0,0 +1,183 @@
+/* Copyright (c) 2017, 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 _CAM_EEPROM_DEV_H_
+#define _CAM_EEPROM_DEV_H_
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/cam_sensor.h>
+#include <cam_sensor_i2c.h>
+#include <cam_sensor_spi.h>
+#include <cam_sensor_io.h>
+#include <cam_cci_dev.h>
+#include <cam_req_mgr_util.h>
+#include <cam_req_mgr_interface.h>
+#include <cam_mem_mgr.h>
+#include <cam_subdev.h>
+#include "cam_soc_util.h"
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+	static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+#define PROPERTY_MAXSIZE 32
+
+#define MSM_EEPROM_MEMORY_MAP_MAX_SIZE         80
+#define MSM_EEPROM_MAX_MEM_MAP_CNT             8
+#define MSM_EEPROM_MEM_MAP_PROPERTIES_CNT      8
+
+/**
+ * struct cam_eeprom_map_t - eeprom map
+ * @data_type       :   Data type
+ * @addr_type       :   Address type
+ * @addr            :   Address
+ * @data            :   data
+ * @delay           :   Delay
+ *
+ */
+struct cam_eeprom_map_t {
+	uint32_t valid_size;
+	uint32_t addr;
+	uint32_t addr_type;
+	uint32_t data;
+	uint32_t data_type;
+	uint32_t delay;
+};
+
+/**
+ * struct cam_eeprom_memory_map_t - eeprom memory map types
+ * @page            :   page memory
+ * @pageen          :   pageen memory
+ * @poll            :   poll memory
+ * @mem             :   mem
+ * @saddr           :   slave addr
+ *
+ */
+struct cam_eeprom_memory_map_t {
+	struct cam_eeprom_map_t page;
+	struct cam_eeprom_map_t pageen;
+	struct cam_eeprom_map_t poll;
+	struct cam_eeprom_map_t mem;
+	uint32_t saddr;
+};
+
+/**
+ * struct cam_eeprom_memory_block_t - eeprom mem block info
+ * @map             :   eeprom memory map
+ * @num_map         :   number of map blocks
+ * @mapdata         :   map data
+ * @cmd_type        :   size of total mapdata
+ *
+ */
+struct cam_eeprom_memory_block_t {
+	struct cam_eeprom_memory_map_t *map;
+	uint32_t num_map;
+	uint8_t *mapdata;
+	uint32_t num_data;
+};
+
+/**
+ * struct cam_eeprom_cmm_t - camera multimodule
+ * @cmm_support     :   cmm support flag
+ * @cmm_compression :   cmm compression flag
+ * @cmm_offset      :   cmm data start offset
+ * @cmm_size        :   cmm data size
+ *
+ */
+struct cam_eeprom_cmm_t {
+	uint32_t cmm_support;
+	uint32_t cmm_compression;
+	uint32_t cmm_offset;
+	uint32_t cmm_size;
+};
+
+/**
+ * struct cam_eeprom_i2c_info_t - I2C info
+ * @slave_addr      :   slave address
+ * @i2c_freq_mode   :   i2c frequency mode
+ *
+ */
+struct cam_eeprom_i2c_info_t {
+	uint16_t slave_addr;
+	uint8_t i2c_freq_mode;
+};
+
+/**
+ * struct cam_eeprom_soc_private - eeprom soc private data structure
+ * @eeprom_name     :   eeprom name
+ * @i2c_info        :   i2c info structure
+ * @power_info      :   eeprom power info
+ * @cmm_data        :   cmm data
+ *
+ */
+struct cam_eeprom_soc_private {
+	const char *eeprom_name;
+	struct cam_eeprom_i2c_info_t i2c_info;
+	struct cam_sensor_power_ctrl_t power_info;
+	struct cam_eeprom_cmm_t cmm_data;
+};
+
+/**
+ * struct cam_eeprom_intf_params - bridge interface params
+ * @device_hdl   : Device Handle
+ * @session_hdl  : Session Handle
+ * @ops          : KMD operations
+ * @crm_cb       : Callback API pointers
+ */
+struct cam_eeprom_intf_params {
+	int32_t device_hdl;
+	int32_t session_hdl;
+	int32_t link_hdl;
+	struct cam_req_mgr_kmd_ops ops;
+	struct cam_req_mgr_crm_cb *crm_cb;
+};
+
+/**
+ * struct cam_cmd_conditional_wait - Conditional wait command
+ * @pdev            :   platform device
+ * @spi             :   spi device
+ * @eeprom_mutex    :   eeprom mutex
+ * @soc_info        :   eeprom soc related info
+ * @io_master_info  :   Information about the communication master
+ * @gpio_num_info   :   gpio info
+ * @cci_i2c_master  :   I2C structure
+ * @v4l2_dev_str    :   V4L2 device structure
+ * @bridge_intf     :   bridge interface params
+ * @subdev_id       :   subdev id
+ * @userspace_probe :   flag indicates userspace or kernel probe
+ * @cal_data        :   Calibration data
+ * @device_name     :   Device name
+ *
+ */
+struct cam_eeprom_ctrl_t {
+	struct platform_device *pdev;
+	struct spi_device *spi;
+	struct mutex eeprom_mutex;
+	struct cam_hw_soc_info soc_info;
+	struct camera_io_master io_master_info;
+	struct msm_camera_gpio_num_info *gpio_num_info;
+	enum cci_i2c_master_t cci_i2c_master;
+	struct cam_subdev v4l2_dev_str;
+	struct cam_eeprom_intf_params bridge_intf;
+	enum msm_camera_device_type_t eeprom_device_type;
+	uint32_t subdev_id;
+	bool userspace_probe;
+	struct cam_eeprom_memory_block_t cal_data;
+	char device_name[20];
+};
+
+int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl,
+	struct cam_eeprom_i2c_info_t *i2c_info);
+
+#endif /*_CAM_EEPROM_DEV_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
new file mode 100644
index 0000000..84e723f
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
@@ -0,0 +1,323 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/of_gpio.h>
+#include <cam_sensor_cmn_header.h>
+#include <cam_sensor_util.h>
+#include <cam_sensor_io.h>
+#include <cam_req_mgr_util.h>
+
+#include "cam_eeprom_soc.h"
+#include "cam_debug_util.h"
+
+/*
+ * cam_eeprom_parse_memory_map() - parse memory map in device node
+ * @of:         device node
+ * @data:       memory block for output
+ *
+ * This functions parses @of to fill @data.  It allocates map itself, parses
+ * the @of node, calculate total data length, and allocates required buffer.
+ * It only fills the map, but does not perform actual reading.
+ */
+int cam_eeprom_parse_dt_memory_map(struct device_node *node,
+	struct cam_eeprom_memory_block_t *data)
+{
+	int       i, rc = 0;
+	char      property[PROPERTY_MAXSIZE];
+	uint32_t  count = MSM_EEPROM_MEM_MAP_PROPERTIES_CNT;
+	struct    cam_eeprom_memory_map_t *map;
+
+	snprintf(property, PROPERTY_MAXSIZE, "num-blocks");
+	rc = of_property_read_u32(node, property, &data->num_map);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "failed: num-blocks not available rc %d",
+			rc);
+		return rc;
+	}
+
+	map = kzalloc((sizeof(*map) * data->num_map), GFP_KERNEL);
+	if (!map) {
+		rc = -ENOMEM;
+		return rc;
+	}
+	data->map = map;
+
+	for (i = 0; i < data->num_map; i++) {
+		snprintf(property, PROPERTY_MAXSIZE, "page%d", i);
+		rc = of_property_read_u32_array(node, property,
+			(uint32_t *) &map[i].page, count);
+		if (rc < 0) {
+			CAM_ERR(CAM_EEPROM, "failed: page not available rc %d",
+				rc);
+			goto ERROR;
+		}
+
+		snprintf(property, PROPERTY_MAXSIZE, "pageen%d", i);
+		rc = of_property_read_u32_array(node, property,
+			(uint32_t *) &map[i].pageen, count);
+		if (rc < 0)
+			CAM_DBG(CAM_EEPROM, "pageen not needed");
+
+		snprintf(property, PROPERTY_MAXSIZE, "saddr%d", i);
+		rc = of_property_read_u32_array(node, property,
+			(uint32_t *) &map[i].saddr, 1);
+		if (rc < 0)
+			CAM_DBG(CAM_EEPROM, "saddr not needed - block %d", i);
+
+		snprintf(property, PROPERTY_MAXSIZE, "poll%d", i);
+		rc = of_property_read_u32_array(node, property,
+			(uint32_t *) &map[i].poll, count);
+		if (rc < 0) {
+			CAM_ERR(CAM_EEPROM, "failed: poll not available rc %d",
+				rc);
+			goto ERROR;
+		}
+
+		snprintf(property, PROPERTY_MAXSIZE, "mem%d", i);
+		rc = of_property_read_u32_array(node, property,
+			(uint32_t *) &map[i].mem, count);
+		if (rc < 0) {
+			CAM_ERR(CAM_EEPROM, "failed: mem not available rc %d",
+				rc);
+			goto ERROR;
+		}
+		data->num_data += map[i].mem.valid_size;
+	}
+
+	data->mapdata = kzalloc(data->num_data, GFP_KERNEL);
+	if (!data->mapdata) {
+		rc = -ENOMEM;
+		goto ERROR;
+	}
+	return rc;
+
+ERROR:
+	kfree(data->map);
+	memset(data, 0, sizeof(*data));
+	return rc;
+}
+
+/**
+ * @e_ctrl: ctrl structure
+ *
+ * Parses eeprom dt
+ */
+static int cam_eeprom_get_dt_data(struct cam_eeprom_ctrl_t *e_ctrl)
+{
+	int                             rc = 0;
+	struct cam_hw_soc_info         *soc_info = &e_ctrl->soc_info;
+	struct cam_eeprom_soc_private  *soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
+	struct device_node             *of_node = NULL;
+
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
+		of_node = e_ctrl->io_master_info.
+			spi_client->spi_master->dev.of_node;
+	else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+		of_node = soc_info->pdev->dev.of_node;
+
+	if (!of_node) {
+		CAM_ERR(CAM_EEPROM, "of_node is NULL, device type %d",
+			e_ctrl->eeprom_device_type);
+		return -EINVAL;
+	}
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "cam_soc_util_get_dt_properties rc %d",
+			rc);
+		return rc;
+	}
+
+	if (e_ctrl->userspace_probe == false) {
+		rc = cam_get_dt_power_setting_data(of_node,
+			soc_info, power_info);
+		if (rc < 0) {
+			CAM_ERR(CAM_EEPROM, "failed in getting power settings");
+			return rc;
+		}
+	}
+
+	if (!soc_info->gpio_data) {
+		CAM_INFO(CAM_EEPROM, "No GPIO found");
+		return 0;
+	}
+
+	if (!soc_info->gpio_data->cam_gpio_common_tbl_size) {
+		CAM_INFO(CAM_EEPROM, "No GPIO found");
+		return -EINVAL;
+	}
+
+	rc = cam_sensor_util_init_gpio_pin_tbl(soc_info,
+		&power_info->gpio_num_info);
+	if ((rc < 0) || (!power_info->gpio_num_info)) {
+		CAM_ERR(CAM_EEPROM, "No/Error EEPROM GPIOs");
+		return -EINVAL;
+	}
+
+	return rc;
+}
+
+/**
+ * @eb_info: eeprom private data structure
+ * @of_node: eeprom device node
+ *
+ * This function parses the eeprom dt to get the MM data
+ */
+static int cam_eeprom_cmm_dts(struct cam_eeprom_soc_private *eb_info,
+	struct device_node *of_node)
+{
+	int                      rc = 0;
+	struct cam_eeprom_cmm_t *cmm_data = &eb_info->cmm_data;
+
+	cmm_data->cmm_support =
+		of_property_read_bool(of_node, "cmm-data-support");
+	if (!cmm_data->cmm_support) {
+		CAM_DBG(CAM_EEPROM, "No cmm support");
+		return 0;
+	}
+
+	cmm_data->cmm_compression =
+		of_property_read_bool(of_node, "cmm-data-compressed");
+
+	rc = of_property_read_u32(of_node, "cmm-data-offset",
+		&cmm_data->cmm_offset);
+	if (rc < 0)
+		CAM_DBG(CAM_EEPROM, "No MM offset data rc %d", rc);
+
+	rc = of_property_read_u32(of_node, "cmm-data-size",
+		&cmm_data->cmm_size);
+	if (rc < 0)
+		CAM_DBG(CAM_EEPROM, "No MM size data rc %d", rc);
+
+	CAM_DBG(CAM_EEPROM, "cmm_compr %d, cmm_offset %d, cmm_size %d",
+		cmm_data->cmm_compression, cmm_data->cmm_offset,
+		cmm_data->cmm_size);
+	return 0;
+}
+
+/**
+ * @e_ctrl: ctrl structure
+ *
+ * This function is called from cam_eeprom_spi_driver_probe, it parses
+ * the eeprom dt node and decides for userspace or kernel probe.
+ */
+int cam_eeprom_spi_driver_soc_init(struct cam_eeprom_ctrl_t *e_ctrl)
+{
+	int                             rc = 0;
+	struct cam_eeprom_soc_private  *soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+
+	rc = of_property_read_u32(e_ctrl->spi->dev.of_node, "cell-index",
+		&e_ctrl->subdev_id);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "failed rc %d", rc);
+		return rc;
+	}
+	rc = of_property_read_string(e_ctrl->spi->dev.of_node,
+		"eeprom-name", &soc_private->eeprom_name);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "failed rc %d", rc);
+		e_ctrl->userspace_probe = true;
+	}
+
+	CAM_DBG(CAM_EEPROM, "eeprom-name %s, rc %d", soc_private->eeprom_name,
+		rc);
+	rc = cam_eeprom_cmm_dts(soc_private,
+		e_ctrl->io_master_info.spi_client->spi_master->dev.of_node);
+	if (rc < 0)
+		CAM_DBG(CAM_EEPROM, "MM data not available rc %d", rc);
+	rc = cam_eeprom_get_dt_data(e_ctrl);
+	if (rc < 0)
+		CAM_DBG(CAM_EEPROM, "failed: eeprom get dt data rc %d", rc);
+
+	return rc;
+}
+
+/**
+ * @e_ctrl: ctrl structure
+ *
+ * This function is called from cam_eeprom_platform_driver_probe, it parses
+ * the eeprom dt node and decides for userspace or kernel probe.
+ */
+int cam_eeprom_platform_driver_soc_init(struct cam_eeprom_ctrl_t *e_ctrl)
+{
+	int                             rc = 0;
+	struct cam_hw_soc_info         *soc_info = &e_ctrl->soc_info;
+	struct device_node             *of_node = NULL;
+	struct platform_device         *pdev = NULL;
+	struct cam_eeprom_soc_private  *soc_private =
+		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
+	uint32_t                        temp;
+
+	if (!soc_info->pdev) {
+		CAM_ERR(CAM_EEPROM, "Error:soc_info is not initialized");
+		return -EINVAL;
+	}
+
+	pdev = soc_info->pdev;
+	of_node = pdev->dev.of_node;
+	if (!of_node) {
+		CAM_ERR(CAM_EEPROM, "dev.of_node NULL");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(of_node, "cell-index",
+		&e_ctrl->subdev_id);
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "failed rc %d\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32(of_node, "cci-master",
+		&e_ctrl->cci_i2c_master);
+	if (rc < 0) {
+		CAM_DBG(CAM_EEPROM, "failed rc %d", rc);
+		return rc;
+	}
+
+	rc = of_property_read_string(of_node, "eeprom-name",
+		&soc_private->eeprom_name);
+	if (rc < 0) {
+		CAM_DBG(CAM_EEPROM, "kernel probe is not enabled");
+		e_ctrl->userspace_probe = true;
+	}
+
+	rc = cam_eeprom_get_dt_data(e_ctrl);
+	if (rc < 0)
+		CAM_DBG(CAM_EEPROM, "failed: eeprom get dt data rc %d", rc);
+
+	if (e_ctrl->userspace_probe == false) {
+		rc = of_property_read_u32(of_node, "slave-addr", &temp);
+		if (rc < 0)
+			CAM_DBG(CAM_EEPROM, "failed: no slave-addr rc %d", rc);
+
+		soc_private->i2c_info.slave_addr = temp;
+
+		rc = of_property_read_u32(of_node, "i2c-freq-mode", &temp);
+		soc_private->i2c_info.i2c_freq_mode = temp;
+		if (rc < 0) {
+			CAM_ERR(CAM_EEPROM,
+				"i2c-freq-mode read fail %d", rc);
+			soc_private->i2c_info.i2c_freq_mode = 0;
+		}
+		if (soc_private->i2c_info.i2c_freq_mode	>= I2C_MAX_MODES) {
+			CAM_ERR(CAM_EEPROM, "invalid i2c_freq_mode = %d",
+				soc_private->i2c_info.i2c_freq_mode);
+			soc_private->i2c_info.i2c_freq_mode = 0;
+		}
+		CAM_DBG(CAM_EEPROM, "slave-addr = 0x%X",
+			soc_private->i2c_info.slave_addr);
+	}
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h
new file mode 100644
index 0000000..02e59d7
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2017, 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 _CAM_EEPROM_SOC_H_
+#define _CAM_EEPROM_SOC_H_
+
+#include "cam_eeprom_dev.h"
+
+int cam_eeprom_parse_dt_memory_map(struct device_node *of,
+	struct cam_eeprom_memory_block_t *data);
+
+int cam_eeprom_platform_driver_soc_init(struct cam_eeprom_ctrl_t *e_ctrl);
+int cam_eeprom_spi_driver_soc_init(struct cam_eeprom_ctrl_t *e_ctrl);
+#endif/* _CAM_EEPROM_SOC_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile
new file mode 100644
index 0000000..9aab0e4
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile
@@ -0,0 +1,9 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash_dev.o cam_flash_core.o cam_flash_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
new file mode 100644
index 0000000..7af7efc
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -0,0 +1,741 @@
+/* Copyright (c) 2017, 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 "cam_sensor_cmn_header.h"
+#include "cam_flash_core.h"
+
+int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
+	enum cam_flash_state state)
+{
+	int rc = 0;
+
+	if (!(flash_ctrl->switch_trigger)) {
+		CAM_ERR(CAM_FLASH, "Invalid argument");
+		return -EINVAL;
+	}
+
+	if ((state == CAM_FLASH_STATE_INIT) &&
+		(flash_ctrl->is_regulator_enabled == false)) {
+		rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
+			ENABLE_REGULATOR, NULL);
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "regulator enable failed rc = %d",
+				rc);
+			return rc;
+		}
+		flash_ctrl->is_regulator_enabled = true;
+	} else if ((state == CAM_FLASH_STATE_RELEASE) &&
+		(flash_ctrl->is_regulator_enabled == true)) {
+		rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
+			DISABLE_REGULATOR, NULL);
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "regulator disable failed rc = %d",
+				rc);
+			return rc;
+		}
+		flash_ctrl->is_regulator_enabled = false;
+	} else {
+		CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
+			flash_ctrl->flash_state);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
+	struct cam_flash_frame_setting *flash_data, enum camera_flash_opcode op)
+{
+	uint32_t curr = 0, max_current = 0;
+	struct cam_flash_private_soc *soc_private = NULL;
+	int i = 0;
+
+	if (!flash_ctrl || !flash_data) {
+		CAM_ERR(CAM_FLASH, "Fctrl or Data NULL");
+		return -EINVAL;
+	}
+
+	soc_private = (struct cam_flash_private_soc *)
+		&flash_ctrl->soc_info.soc_private;
+
+	if (op == CAMERA_SENSOR_FLASH_OP_FIRELOW) {
+		for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
+			if (flash_ctrl->torch_trigger[i]) {
+				max_current = soc_private->torch_max_current[i];
+
+				if (flash_data->led_current_ma[i] <=
+					max_current)
+					curr = flash_data->led_current_ma[i];
+				else
+					curr = soc_private->torch_op_current[i];
+
+				CAM_DBG(CAM_FLASH,
+					"Led_Current[%d] = %d", i, curr);
+				led_trigger_event(flash_ctrl->torch_trigger[i],
+					curr);
+			}
+		}
+	} else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
+		for (i = 0; i < flash_ctrl->flash_num_sources; i++) {
+			if (flash_ctrl->flash_trigger[i]) {
+				max_current = soc_private->flash_max_current[i];
+
+				if (flash_data->led_current_ma[i] <=
+					max_current)
+					curr = flash_data->led_current_ma[i];
+				else
+					curr = soc_private->flash_op_current[i];
+
+				CAM_DBG(CAM_FLASH, "LED flash_current[%d]: %d",
+					i, curr);
+				led_trigger_event(flash_ctrl->flash_trigger[i],
+					curr);
+			}
+		}
+	} else {
+		CAM_ERR(CAM_FLASH, "Wrong Operation: %d", op);
+		return -EINVAL;
+	}
+
+	if (flash_ctrl->switch_trigger)
+		led_trigger_event(flash_ctrl->switch_trigger, LED_SWITCH_ON);
+
+	return 0;
+}
+
+int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
+{
+	int i = 0;
+
+	if (!flash_ctrl) {
+		CAM_ERR(CAM_FLASH, "Flash control Null");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < flash_ctrl->flash_num_sources; i++)
+		if (flash_ctrl->flash_trigger[i])
+			led_trigger_event(flash_ctrl->flash_trigger[i],
+				LED_OFF);
+
+	for (i = 0; i < flash_ctrl->torch_num_sources; i++)
+		if (flash_ctrl->torch_trigger[i])
+			led_trigger_event(flash_ctrl->torch_trigger[i],
+				LED_OFF);
+
+	if (flash_ctrl->switch_trigger)
+		led_trigger_event(flash_ctrl->switch_trigger,
+			LED_SWITCH_OFF);
+
+	return 0;
+}
+
+static int cam_flash_low(
+	struct cam_flash_ctrl *flash_ctrl,
+	struct cam_flash_frame_setting *flash_data)
+{
+	int i = 0, rc = 0;
+
+	if (!flash_data) {
+		CAM_ERR(CAM_FLASH, "Flash Data Null");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < flash_ctrl->flash_num_sources; i++)
+		if (flash_ctrl->flash_trigger[i])
+			led_trigger_event(flash_ctrl->flash_trigger[i],
+				LED_OFF);
+
+	rc = cam_flash_ops(flash_ctrl, flash_data,
+		CAMERA_SENSOR_FLASH_OP_FIRELOW);
+	if (rc)
+		CAM_ERR(CAM_FLASH, "Fire Torch failed: %d", rc);
+
+	return rc;
+}
+
+static int cam_flash_high(
+	struct cam_flash_ctrl *flash_ctrl,
+	struct cam_flash_frame_setting *flash_data)
+{
+	int i = 0, rc = 0;
+
+	if (!flash_data) {
+		CAM_ERR(CAM_FLASH, "Flash Data Null");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < flash_ctrl->torch_num_sources; i++)
+		if (flash_ctrl->torch_trigger[i])
+			led_trigger_event(flash_ctrl->torch_trigger[i],
+				LED_OFF);
+
+	rc = cam_flash_ops(flash_ctrl, flash_data,
+		CAMERA_SENSOR_FLASH_OP_FIREHIGH);
+	if (rc)
+		CAM_ERR(CAM_FLASH, "Fire Flash Failed: %d", rc);
+
+	return rc;
+}
+
+static int delete_req(struct cam_flash_ctrl *fctrl, uint64_t req_id)
+{
+	int i = 0;
+	int frame_offset = 0;
+	struct cam_flash_frame_setting *flash_data = NULL;
+
+	if (req_id == 0) {
+		flash_data = &fctrl->nrt_info;
+		if ((fctrl->nrt_info.cmn_attr.cmd_type ==
+			CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) ||
+			(fctrl->nrt_info.cmn_attr.cmd_type ==
+			CAMERA_SENSOR_FLASH_CMD_TYPE_RER)) {
+			flash_data->cmn_attr.is_settings_valid = false;
+			for (i = 0; i < flash_data->cmn_attr.count; i++)
+				flash_data->led_current_ma[i] = 0;
+		} else {
+			fctrl->flash_init_setting.cmn_attr.
+				is_settings_valid = false;
+		}
+	} else {
+		frame_offset = (req_id + MAX_PER_FRAME_ARRAY -
+			CAM_FLASH_PIPELINE_DELAY) % 8;
+		flash_data = &fctrl->per_frame[frame_offset];
+		if (req_id > flash_data->cmn_attr.request_id) {
+			flash_data->cmn_attr.request_id = 0;
+			flash_data->cmn_attr.is_settings_valid = false;
+			for (i = 0; i < flash_data->cmn_attr.count; i++)
+				flash_data->led_current_ma[i] = 0;
+		}
+	}
+
+	return 0;
+}
+
+int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl,
+	uint64_t req_id)
+{
+	int rc = 0, i = 0;
+	int frame_offset = 0;
+	uint16_t num_iterations;
+	struct cam_flash_frame_setting *flash_data = NULL;
+
+	if (req_id == 0) {
+		if (fctrl->nrt_info.cmn_attr.cmd_type ==
+			CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) {
+			flash_data = &fctrl->nrt_info;
+			if (flash_data->opcode ==
+				CAMERA_SENSOR_FLASH_OP_FIRELOW) {
+				if (!(fctrl->is_regulator_enabled)) {
+					rc = cam_flash_prepare(fctrl,
+						CAM_FLASH_STATE_INIT);
+					if (rc) {
+						CAM_ERR(CAM_FLASH,
+							"Reg Enable Failed %d",
+							rc);
+						goto nrt_del_req;
+					}
+					fctrl->flash_state =
+						CAM_FLASH_STATE_INIT;
+					rc = cam_flash_low(fctrl, flash_data);
+					if (rc) {
+						CAM_ERR(CAM_FLASH,
+							"Torch ON failed : %d",
+							rc);
+						goto nrt_del_req;
+					}
+					fctrl->flash_state =
+						CAM_FLASH_STATE_LOW;
+				}
+			} else if (flash_data->opcode ==
+				CAMERA_SENSOR_FLASH_OP_OFF) {
+				if (fctrl->flash_state !=
+					CAM_FLASH_STATE_INIT) {
+					rc = cam_flash_off(fctrl);
+					if (rc)
+						CAM_ERR(CAM_FLASH,
+							"LED off failed: %d",
+							rc);
+				}
+
+				rc = cam_flash_prepare(fctrl,
+					CAM_FLASH_STATE_RELEASE);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+						"Regulator Disable failed %d",
+						rc);
+					goto nrt_del_req;
+				}
+
+				fctrl->flash_state =
+					CAM_FLASH_STATE_RELEASE;
+				fctrl->is_regulator_enabled = false;
+			}
+		} else if (fctrl->nrt_info.cmn_attr.cmd_type ==
+			CAMERA_SENSOR_FLASH_CMD_TYPE_RER) {
+			flash_data = &fctrl->nrt_info;
+
+			if (fctrl->flash_state != CAM_FLASH_STATE_INIT) {
+				rc = cam_flash_off(fctrl);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+						"Flash off failed: %d",
+						rc);
+				} else {
+					fctrl->flash_state =
+						CAM_FLASH_STATE_INIT;
+				}
+			}
+
+			num_iterations = flash_data->num_iterations;
+			for (i = 0; i < num_iterations; i++) {
+				/* Turn On Torch */
+				if (fctrl->flash_state ==
+					CAM_FLASH_STATE_INIT) {
+					rc = cam_flash_low(fctrl, flash_data);
+					if (rc) {
+						CAM_ERR(CAM_FLASH,
+							"Fire Torch Failed");
+						goto nrt_del_req;
+					}
+					fctrl->flash_state =
+						CAM_FLASH_STATE_LOW;
+				}
+				usleep_range(
+				flash_data->led_on_delay_ms * 1000,
+				flash_data->led_on_delay_ms * 1000 + 100);
+
+				/* Turn Off Torch */
+				rc = cam_flash_off(fctrl);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+						"Flash off failed: %d",
+						rc);
+					continue;
+				}
+				fctrl->flash_state = CAM_FLASH_STATE_INIT;
+				usleep_range(
+				flash_data->led_off_delay_ms * 1000,
+				flash_data->led_off_delay_ms * 1000 + 100);
+			}
+		}
+	} else {
+		frame_offset = req_id % MAX_PER_FRAME_ARRAY;
+		flash_data = &fctrl->per_frame[frame_offset];
+
+		if ((flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREHIGH) &&
+			(flash_data->cmn_attr.is_settings_valid)) {
+			/* Turn On Flash */
+			if (fctrl->flash_state == CAM_FLASH_STATE_INIT) {
+				rc = cam_flash_high(fctrl, flash_data);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+						"Flash ON failed: rc= %d",
+						rc);
+					goto apply_setting_err;
+				}
+				fctrl->flash_state = CAM_FLASH_STATE_HIGH;
+			}
+		} else if ((flash_data->opcode ==
+			CAMERA_SENSOR_FLASH_OP_FIRELOW) &&
+			(flash_data->cmn_attr.is_settings_valid)) {
+			/* Turn Off Flash */
+			if (fctrl->flash_state == CAM_FLASH_STATE_INIT) {
+				rc = cam_flash_low(fctrl, flash_data);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+						"Torch ON failed: rc= %d",
+						rc);
+					goto apply_setting_err;
+				}
+				fctrl->flash_state = CAM_FLASH_STATE_LOW;
+			}
+		} else if ((flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) &&
+			(flash_data->cmn_attr.is_settings_valid)) {
+			if ((fctrl->flash_state != CAM_FLASH_STATE_RELEASE) ||
+				(fctrl->flash_state != CAM_FLASH_STATE_INIT)) {
+				rc = cam_flash_off(fctrl);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+						"Flash off failed %d", rc);
+				} else {
+					fctrl->flash_state =
+						CAM_FLASH_STATE_INIT;
+				}
+			}
+		} else {
+			CAM_ERR(CAM_FLASH, "Wrong opcode : %d",
+				flash_data->opcode);
+			rc = -EINVAL;
+			goto apply_setting_err;
+		}
+	}
+
+nrt_del_req:
+	delete_req(fctrl, req_id);
+apply_setting_err:
+	return rc;
+}
+
+int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
+{
+	int rc = 0, i = 0;
+	uint64_t generic_ptr;
+	uint32_t *cmd_buf =  NULL;
+	uint32_t *offset = NULL;
+	uint32_t frame_offset = 0;
+	size_t len_of_buffer;
+	struct cam_control *ioctl_ctrl = NULL;
+	struct cam_packet *csl_packet = NULL;
+	struct cam_cmd_buf_desc *cmd_desc = NULL;
+	struct common_header *cmn_hdr;
+	struct cam_config_dev_cmd config;
+	struct cam_req_mgr_add_request add_req;
+	struct cam_flash_init *cam_flash_info = NULL;
+	struct cam_flash_set_rer *flash_rer_info = NULL;
+	struct cam_flash_set_on_off *flash_operation_info = NULL;
+	struct cam_flash_query_curr *flash_query_info = NULL;
+
+	if (!fctrl || !arg) {
+		CAM_ERR(CAM_FLASH, "fctrl/arg is NULL");
+		return -EINVAL;
+	}
+	/* getting CSL Packet */
+	ioctl_ctrl = (struct cam_control *)arg;
+
+	if (copy_from_user((&config), (void __user *) ioctl_ctrl->handle,
+		sizeof(config))) {
+		CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed");
+		rc = -EFAULT;
+		return rc;
+	}
+
+	rc = cam_mem_get_cpu_buf(config.packet_handle,
+		(uint64_t *)&generic_ptr, &len_of_buffer);
+	if (rc) {
+		CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
+		return rc;
+	}
+
+	csl_packet = (struct cam_packet *)generic_ptr;
+
+	switch (csl_packet->header.op_code & 0xFFFFFF) {
+	case CAM_FLASH_PACKET_OPCODE_INIT: {
+		/* INIT packet*/
+		offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+			csl_packet->cmd_buf_offset);
+		fctrl->flash_init_setting.cmn_attr.request_id = 0;
+		fctrl->flash_init_setting.cmn_attr.is_settings_valid = true;
+		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+		rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
+			(uint64_t *)&generic_ptr, &len_of_buffer);
+		cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+			cmd_desc->offset);
+		cam_flash_info = (struct cam_flash_init *)cmd_buf;
+
+		switch (cam_flash_info->cmd_type) {
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT:
+			fctrl->flash_type = cam_flash_info->flash_type;
+			fctrl->is_regulator_enabled = false;
+			fctrl->nrt_info.cmn_attr.cmd_type =
+				CAMERA_SENSOR_FLASH_CMD_TYPE_INIT;
+			break;
+		default:
+			CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
+				cam_flash_info->cmd_type);
+			return -EINVAL;
+		}
+		break;
+	}
+	case CAM_FLASH_PACKET_OPCODE_SET_OPS: {
+		offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+			csl_packet->cmd_buf_offset);
+		frame_offset = csl_packet->header.request_id %
+			MAX_PER_FRAME_ARRAY;
+		fctrl->per_frame[frame_offset].cmn_attr.request_id =
+			csl_packet->header.request_id;
+		fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid =
+			true;
+		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+		rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
+			(uint64_t *)&generic_ptr, &len_of_buffer);
+		cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+			cmd_desc->offset);
+		cmn_hdr = (struct common_header *)cmd_buf;
+
+		switch (cmn_hdr->cmd_type) {
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: {
+			CAM_DBG(CAM_FLASH,
+				"CAMERA_FLASH_CMD_TYPE_OPS case called");
+			flash_operation_info =
+				(struct cam_flash_set_on_off *) cmd_buf;
+			fctrl->per_frame[frame_offset].opcode =
+				flash_operation_info->opcode;
+			fctrl->per_frame[frame_offset].cmn_attr.count =
+				flash_operation_info->count;
+			for (i = 0; i < flash_operation_info->count; i++)
+				fctrl->per_frame[frame_offset].led_current_ma[i]
+					= flash_operation_info->
+					led_current_ma[i];
+			break;
+		}
+		default:
+			CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
+				cmn_hdr->cmd_type);
+			return -EINVAL;
+		}
+
+		break;
+	}
+	case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: {
+		offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+			csl_packet->cmd_buf_offset);
+		fctrl->nrt_info.cmn_attr.is_settings_valid = true;
+		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+		rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
+			(uint64_t *)&generic_ptr, &len_of_buffer);
+		cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+			cmd_desc->offset);
+		cmn_hdr = (struct common_header *)cmd_buf;
+
+		switch (cmn_hdr->cmd_type) {
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET: {
+			CAM_DBG(CAM_FLASH, "Widget Flash Operation");
+			flash_operation_info =
+				(struct cam_flash_set_on_off *) cmd_buf;
+			fctrl->nrt_info.cmn_attr.count =
+				flash_operation_info->count;
+			fctrl->nrt_info.cmn_attr.request_id = 0;
+			fctrl->nrt_info.opcode =
+				flash_operation_info->opcode;
+			fctrl->nrt_info.cmn_attr.cmd_type =
+				CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET;
+
+			for (i = 0; i < flash_operation_info->count; i++)
+				fctrl->nrt_info.led_current_ma[i] =
+					flash_operation_info->led_current_ma[i];
+
+			mutex_lock(&fctrl->flash_wq_mutex);
+			rc = cam_flash_apply_setting(fctrl, 0);
+			if (rc)
+				CAM_ERR(CAM_FLASH, "Apply setting failed: %d",
+					rc);
+			mutex_unlock(&fctrl->flash_wq_mutex);
+			return rc;
+		}
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR: {
+			int query_curr_ma = 0;
+
+			flash_query_info =
+				(struct cam_flash_query_curr *)cmd_buf;
+
+			rc = qpnp_flash_led_prepare(fctrl->switch_trigger,
+				QUERY_MAX_CURRENT, &query_curr_ma);
+			CAM_DBG(CAM_FLASH, "query_curr_ma = %d",
+				query_curr_ma);
+			if (rc) {
+				CAM_ERR(CAM_FLASH,
+				"Query current failed with rc=%d", rc);
+				return rc;
+			}
+			flash_query_info->query_current_ma = query_curr_ma;
+			break;
+		}
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_RER: {
+			rc = 0;
+			flash_rer_info = (struct cam_flash_set_rer *)cmd_buf;
+			fctrl->nrt_info.cmn_attr.cmd_type =
+				CAMERA_SENSOR_FLASH_CMD_TYPE_RER;
+			fctrl->nrt_info.opcode = flash_rer_info->opcode;
+			fctrl->nrt_info.cmn_attr.count = flash_rer_info->count;
+			fctrl->nrt_info.cmn_attr.request_id = 0;
+			fctrl->nrt_info.num_iterations =
+				flash_rer_info->num_iteration;
+			fctrl->nrt_info.led_on_delay_ms =
+				flash_rer_info->led_on_delay_ms;
+			fctrl->nrt_info.led_off_delay_ms =
+				flash_rer_info->led_off_delay_ms;
+
+			for (i = 0; i < flash_rer_info->count; i++)
+				fctrl->nrt_info.led_current_ma[i] =
+					flash_rer_info->led_current_ma[i];
+
+
+			mutex_lock(&fctrl->flash_wq_mutex);
+			rc = cam_flash_apply_setting(fctrl, 0);
+			if (rc)
+				CAM_ERR(CAM_FLASH, "apply_setting failed: %d",
+					rc);
+			mutex_unlock(&fctrl->flash_wq_mutex);
+			return rc;
+		}
+		default:
+			CAM_ERR(CAM_FLASH, "Wrong cmd_type : %d",
+				cmn_hdr->cmd_type);
+			return -EINVAL;
+		}
+
+		break;
+	}
+	case CAM_PKT_NOP_OPCODE: {
+		goto update_req_mgr;
+	}
+	default:
+		CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
+			(csl_packet->header.op_code & 0xFFFFFF));
+		return -EINVAL;
+	}
+update_req_mgr:
+	if (((csl_packet->header.op_code  & 0xFFFFF) ==
+		CAM_PKT_NOP_OPCODE) ||
+		((csl_packet->header.op_code & 0xFFFFF) ==
+		CAM_FLASH_PACKET_OPCODE_SET_OPS)) {
+		add_req.link_hdl = fctrl->bridge_intf.link_hdl;
+		add_req.req_id = csl_packet->header.request_id;
+		add_req.dev_hdl = fctrl->bridge_intf.device_hdl;
+		if (fctrl->bridge_intf.crm_cb &&
+			fctrl->bridge_intf.crm_cb->add_req)
+			fctrl->bridge_intf.crm_cb->add_req(&add_req);
+		CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id);
+	}
+
+	return rc;
+}
+
+int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info)
+{
+	info->dev_id = CAM_REQ_MGR_DEVICE_FLASH;
+	strlcpy(info->name, CAM_FLASH_NAME, sizeof(info->name));
+	info->p_delay = CAM_FLASH_PIPELINE_DELAY;
+	return 0;
+}
+
+int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link)
+{
+	struct cam_flash_ctrl *fctrl = NULL;
+
+	if (!link)
+		return -EINVAL;
+
+	fctrl = (struct cam_flash_ctrl *)cam_get_device_priv(link->dev_hdl);
+	if (!fctrl) {
+		CAM_ERR(CAM_FLASH, " Device data is NULL");
+		return -EINVAL;
+	}
+
+	if (link->link_enable) {
+		fctrl->bridge_intf.link_hdl = link->link_hdl;
+		fctrl->bridge_intf.crm_cb = link->crm_cb;
+	} else {
+		fctrl->bridge_intf.link_hdl = -1;
+		fctrl->bridge_intf.crm_cb = NULL;
+	}
+
+	return 0;
+}
+
+static int cam_flash_flush_nrt(struct cam_flash_ctrl *fctrl)
+{
+	int j = 0;
+	struct cam_flash_frame_setting *nrt_settings;
+
+	if (!fctrl)
+		return -EINVAL;
+
+	nrt_settings = &fctrl->nrt_info;
+
+	if (nrt_settings->cmn_attr.cmd_type ==
+		CAMERA_SENSOR_FLASH_CMD_TYPE_INIT) {
+		fctrl->flash_init_setting.cmn_attr.is_settings_valid = false;
+	} else if ((nrt_settings->cmn_attr.cmd_type ==
+		CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) ||
+		(nrt_settings->cmn_attr.cmd_type ==
+		CAMERA_SENSOR_FLASH_CMD_TYPE_RER)) {
+		fctrl->nrt_info.cmn_attr.is_settings_valid = false;
+		fctrl->nrt_info.cmn_attr.count = 0;
+		fctrl->nrt_info.num_iterations = 0;
+		fctrl->nrt_info.led_on_delay_ms = 0;
+		fctrl->nrt_info.led_off_delay_ms = 0;
+		for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++)
+			fctrl->nrt_info.led_current_ma[j] = 0;
+	}
+
+	return 0;
+}
+
+int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush)
+{
+	int rc = 0;
+	int i = 0, j = 0;
+	struct cam_flash_ctrl *fctrl = NULL;
+	int frame_offset = 0;
+
+	fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(flush->dev_hdl);
+	if (!fctrl) {
+		CAM_ERR(CAM_FLASH, "Device data is NULL");
+		return -EINVAL;
+	}
+
+	if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+	/* flush all requests*/
+		for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
+			fctrl->per_frame[i].cmn_attr.request_id = 0;
+			fctrl->per_frame[i].cmn_attr.is_settings_valid = false;
+			fctrl->per_frame[i].cmn_attr.count = 0;
+			for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++)
+				fctrl->per_frame[i].led_current_ma[j] = 0;
+		}
+
+		rc = cam_flash_flush_nrt(fctrl);
+		if (rc)
+			CAM_ERR(CAM_FLASH, "NonRealTime flush error");
+	} else if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
+	/* flush request with req_id*/
+		frame_offset = flush->req_id % MAX_PER_FRAME_ARRAY;
+		fctrl->per_frame[frame_offset].cmn_attr.request_id = 0;
+		fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid =
+			false;
+		fctrl->per_frame[frame_offset].cmn_attr.count = 0;
+		for (i = 0; i < CAM_FLASH_MAX_LED_TRIGGERS; i++)
+			fctrl->per_frame[frame_offset].led_current_ma[i] = 0;
+	}
+	return rc;
+}
+
+int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply)
+{
+	int rc = 0;
+	struct cam_flash_ctrl *fctrl = NULL;
+
+	if (!apply)
+		return -EINVAL;
+
+	fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(apply->dev_hdl);
+	if (!fctrl) {
+		CAM_ERR(CAM_FLASH, "Device data is NULL");
+		rc = -EINVAL;
+		goto free_resource;
+	}
+
+	if (!(apply->report_if_bubble)) {
+		mutex_lock(&fctrl->flash_wq_mutex);
+		rc = cam_flash_apply_setting(fctrl, apply->request_id);
+		if (rc)
+			CAM_ERR(CAM_FLASH, "apply_setting failed with rc=%d",
+				rc);
+		mutex_unlock(&fctrl->flash_wq_mutex);
+	}
+
+free_resource:
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h
new file mode 100644
index 0000000..4b0cf8d
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2017, 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 _CAM_FLASH_CORE_H_
+#define _CAM_FLASH_CORE_H_
+
+#include <linux/leds-qpnp-flash.h>
+#include <media/cam_sensor.h>
+#include "cam_flash_dev.h"
+#include "cam_sync_api.h"
+#include "cam_mem_mgr_api.h"
+
+int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg);
+int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info);
+int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link);
+int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id);
+int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply);
+int cam_flash_process_evt(struct cam_req_mgr_link_evt_data *event_data);
+int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush);
+int cam_flash_off(struct cam_flash_ctrl *fctrl);
+int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
+	enum cam_flash_state state);
+
+#endif /*_CAM_FLASH_CORE_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
new file mode 100644
index 0000000..32df2f1
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -0,0 +1,361 @@
+/* Copyright (c) 2017, 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 "cam_flash_dev.h"
+#include "cam_flash_soc.h"
+#include "cam_flash_core.h"
+
+static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
+		void *arg, struct cam_flash_private_soc *soc_private)
+{
+	int rc = 0;
+	int i = 0;
+	struct cam_control *cmd = (struct cam_control *)arg;
+
+	if (!fctrl || !arg) {
+		CAM_ERR(CAM_FLASH, "fctrl/arg is NULL with arg:%pK fctrl%pK",
+			fctrl, arg);
+		return -EINVAL;
+	}
+
+	mutex_lock(&(fctrl->flash_mutex));
+	switch (cmd->op_code) {
+	case CAM_ACQUIRE_DEV: {
+		struct cam_sensor_acquire_dev flash_acq_dev;
+		struct cam_create_dev_hdl bridge_params;
+
+		CAM_DBG(CAM_FLASH, "CAM_ACQUIRE_DEV");
+		if (fctrl->bridge_intf.device_hdl != -1) {
+			CAM_ERR(CAM_FLASH, "Device is already acquired");
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+
+		rc = copy_from_user(&flash_acq_dev, (void __user *)cmd->handle,
+			sizeof(flash_acq_dev));
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "Failed Copying from User");
+			goto release_mutex;
+		}
+
+		bridge_params.session_hdl = flash_acq_dev.session_handle;
+		bridge_params.ops = &fctrl->bridge_intf.ops;
+		bridge_params.v4l2_sub_dev_flag = 0;
+		bridge_params.media_entity_flag = 0;
+		bridge_params.priv = fctrl;
+
+		flash_acq_dev.device_handle =
+			cam_create_device_hdl(&bridge_params);
+		fctrl->bridge_intf.device_hdl =
+			flash_acq_dev.device_handle;
+		fctrl->bridge_intf.session_hdl =
+			flash_acq_dev.session_handle;
+
+		rc = copy_to_user((void __user *) cmd->handle, &flash_acq_dev,
+			sizeof(struct cam_sensor_acquire_dev));
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "Failed Copy to User with rc = %d",
+				rc);
+			rc = -EFAULT;
+			goto release_mutex;
+		}
+		break;
+	}
+	case CAM_RELEASE_DEV: {
+		CAM_DBG(CAM_FLASH, "CAM_RELEASE_DEV");
+		if (fctrl->bridge_intf.device_hdl == -1) {
+			CAM_ERR(CAM_FLASH,
+				"Invalid Handle: Link Hdl: %d device hdl: %d",
+				fctrl->bridge_intf.device_hdl,
+				fctrl->bridge_intf.link_hdl);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+		rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl);
+		if (rc)
+			CAM_ERR(CAM_FLASH,
+				"Failed in destroying the device Handle rc= %d",
+				rc);
+		fctrl->bridge_intf.device_hdl = -1;
+		fctrl->bridge_intf.link_hdl = -1;
+		fctrl->bridge_intf.session_hdl = -1;
+		break;
+	}
+	case CAM_QUERY_CAP: {
+		struct cam_flash_query_cap_info flash_cap;
+
+		CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP");
+		flash_cap.slot_info = fctrl->soc_info.index;
+		for (i = 0; i < fctrl->flash_num_sources; i++) {
+			flash_cap.max_current_flash[i] =
+				soc_private->flash_max_current[i];
+			flash_cap.max_duration_flash[i] =
+				soc_private->flash_max_duration[i];
+		}
+
+		for (i = 0; i < fctrl->torch_num_sources; i++)
+			flash_cap.max_current_torch[i] =
+				soc_private->torch_max_current[i];
+
+		if (copy_to_user((void __user *) cmd->handle, &flash_cap,
+			sizeof(struct cam_flash_query_cap_info))) {
+			CAM_ERR(CAM_FLASH, "Failed Copy to User");
+			rc = -EFAULT;
+			goto release_mutex;
+		}
+		break;
+	}
+	case CAM_START_DEV: {
+		CAM_DBG(CAM_FLASH, "CAM_START_DEV");
+		rc = cam_flash_prepare(fctrl, CAM_FLASH_STATE_INIT);
+		if (rc) {
+			CAM_ERR(CAM_FLASH,
+				"Enable Regulator Failed rc = %d", rc);
+			goto release_mutex;
+		}
+		fctrl->flash_state = CAM_FLASH_STATE_INIT;
+		rc = cam_flash_apply_setting(fctrl, 0);
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc);
+			goto release_mutex;
+		}
+		break;
+	}
+	case CAM_STOP_DEV: {
+		CAM_DBG(CAM_FLASH, "CAM_STOP_DEV");
+		if (fctrl->flash_state != CAM_FLASH_STATE_INIT)
+			cam_flash_off(fctrl);
+
+		rc = cam_flash_prepare(fctrl, CAM_FLASH_STATE_RELEASE);
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "Disable Regulator Failed ret = %d",
+				rc);
+			goto release_mutex;
+		}
+		fctrl->flash_state = CAM_FLASH_STATE_RELEASE;
+
+		break;
+	}
+	case CAM_CONFIG_DEV: {
+		CAM_DBG(CAM_FLASH, "CAM_CONFIG_DEV");
+		rc = cam_flash_parser(fctrl, arg);
+		if (rc) {
+			CAM_ERR(CAM_FLASH, "Failed Flash Config: rc=%d\n", rc);
+			goto release_mutex;
+		}
+		break;
+	}
+	default:
+		CAM_ERR(CAM_FLASH, "Invalid Opcode: %d", cmd->op_code);
+		rc = -EINVAL;
+	}
+
+release_mutex:
+	mutex_unlock(&(fctrl->flash_mutex));
+	return rc;
+}
+
+static const struct of_device_id cam_flash_dt_match[] = {
+	{.compatible = "qcom,camera-flash", .data = NULL},
+	{}
+};
+
+static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	int rc = 0;
+	struct cam_flash_ctrl *fctrl = NULL;
+	struct cam_flash_private_soc *soc_private = NULL;
+
+	CAM_DBG(CAM_FLASH, "Enter");
+
+	fctrl = v4l2_get_subdevdata(sd);
+	soc_private = fctrl->soc_info.soc_private;
+
+	switch (cmd) {
+	case VIDIOC_CAM_CONTROL: {
+		rc = cam_flash_driver_cmd(fctrl, arg,
+			soc_private);
+		break;
+	}
+	default:
+		CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type");
+		rc = -EINVAL;
+		break;
+	}
+
+	CAM_DBG(CAM_FLASH, "Exit");
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+static long cam_flash_subdev_do_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, unsigned long arg)
+{
+	struct cam_control cmd_data;
+	int32_t rc = 0;
+
+	if (copy_from_user(&cmd_data, (void __user *)arg,
+		sizeof(cmd_data))) {
+		CAM_ERR(CAM_FLASH,
+			"Failed to copy from user_ptr=%pK size=%zu",
+			(void __user *)arg, sizeof(cmd_data));
+		return -EFAULT;
+	}
+
+	switch (cmd) {
+	case VIDIOC_CAM_CONTROL: {
+		rc = cam_flash_subdev_ioctl(sd, cmd, &cmd_data);
+		if (rc)
+			CAM_ERR(CAM_FLASH, "cam_flash_ioctl failed");
+		break;
+	}
+	default:
+		CAM_ERR(CAM_FLASH, "Invalid compat ioctl cmd_type:%d",
+			cmd);
+		rc = -EINVAL;
+	}
+
+	if (!rc) {
+		if (copy_to_user((void __user *)arg, &cmd_data,
+			sizeof(cmd_data))) {
+			CAM_ERR(CAM_FLASH,
+				"Failed to copy to user_ptr=%pK size=%zu",
+				(void __user *)arg, sizeof(cmd_data));
+			rc = -EFAULT;
+		}
+	}
+
+	return rc;
+}
+#endif
+
+static int cam_flash_platform_remove(struct platform_device *pdev)
+{
+	struct cam_flash_ctrl *fctrl;
+
+	fctrl = platform_get_drvdata(pdev);
+	if (!fctrl) {
+		CAM_ERR(CAM_FLASH, "Flash device is NULL");
+		return 0;
+	}
+
+	devm_kfree(&pdev->dev, fctrl);
+
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = {
+	.ioctl = cam_flash_subdev_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl32 = cam_flash_subdev_do_ioctl
+#endif
+};
+
+static struct v4l2_subdev_ops cam_flash_subdev_ops = {
+	.core = &cam_flash_subdev_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops cam_flash_internal_ops;
+
+static int32_t cam_flash_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	struct cam_flash_ctrl *flash_ctrl = NULL;
+
+	CAM_DBG(CAM_FLASH, "Enter");
+	if (!pdev->dev.of_node) {
+		CAM_ERR(CAM_FLASH, "of_node NULL");
+		return -EINVAL;
+	}
+
+	flash_ctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL);
+	if (!flash_ctrl)
+		return -ENOMEM;
+
+	flash_ctrl->pdev = pdev;
+	flash_ctrl->soc_info.pdev = pdev;
+
+	rc = cam_flash_get_dt_data(flash_ctrl, &flash_ctrl->soc_info);
+	if (rc) {
+		CAM_ERR(CAM_FLASH, "cam_flash_get_dt_data failed with %d", rc);
+		kfree(flash_ctrl);
+		return -EINVAL;
+	}
+
+	flash_ctrl->v4l2_dev_str.internal_ops =
+		&cam_flash_internal_ops;
+	flash_ctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops;
+	flash_ctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME;
+	flash_ctrl->v4l2_dev_str.sd_flags =
+		V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+	flash_ctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE;
+	flash_ctrl->v4l2_dev_str.token = flash_ctrl;
+
+	rc = cam_register_subdev(&(flash_ctrl->v4l2_dev_str));
+	if (rc) {
+		CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc);
+		goto free_resource;
+	}
+	flash_ctrl->bridge_intf.device_hdl = -1;
+	flash_ctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info;
+	flash_ctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
+	flash_ctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
+	flash_ctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
+
+	platform_set_drvdata(pdev, flash_ctrl);
+	v4l2_set_subdevdata(&flash_ctrl->v4l2_dev_str.sd, flash_ctrl);
+
+	mutex_init(&(flash_ctrl->flash_mutex));
+	mutex_init(&(flash_ctrl->flash_wq_mutex));
+
+	CAM_DBG(CAM_FLASH, "Probe success");
+	return rc;
+free_resource:
+	kfree(flash_ctrl);
+	return rc;
+}
+
+MODULE_DEVICE_TABLE(of, cam_flash_dt_match);
+
+static struct platform_driver cam_flash_platform_driver = {
+	.probe = cam_flash_platform_probe,
+	.remove = cam_flash_platform_remove,
+	.driver = {
+		.name = "CAM-FLASH-DRIVER",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_flash_dt_match,
+	},
+};
+
+static int __init cam_flash_init_module(void)
+{
+	int32_t rc = 0;
+
+	rc = platform_driver_register(&cam_flash_platform_driver);
+	if (rc)
+		CAM_ERR(CAM_FLASH, "platform probe for flash failed");
+
+	return rc;
+}
+
+static void __exit cam_flash_exit_module(void)
+{
+	platform_driver_unregister(&cam_flash_platform_driver);
+}
+
+module_init(cam_flash_init_module);
+module_exit(cam_flash_exit_module);
+MODULE_DESCRIPTION("CAM FLASH");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
new file mode 100644
index 0000000..1897eb6
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
@@ -0,0 +1,181 @@
+/* Copyright (c) 2017, 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 _CAM_FLASH_DEV_H_
+#define _CAM_FLASH_DEV_H_
+
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/cam_sensor.h>
+#include <media/cam_req_mgr.h>
+#include "cam_req_mgr_util.h"
+#include "cam_req_mgr_interface.h"
+#include "cam_subdev.h"
+#include "cam_mem_mgr.h"
+#include "cam_sensor_cmn_header.h"
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+#define CAMX_FLASH_DEV_NAME "cam-flash-dev"
+
+#define CAM_FLASH_PIPELINE_DELAY 1
+
+#define CAM_FLASH_PACKET_OPCODE_INIT                 0
+#define CAM_FLASH_PACKET_OPCODE_SET_OPS              1
+#define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2
+
+enum cam_flash_switch_trigger_ops {
+	LED_SWITCH_OFF = 0,
+	LED_SWITCH_ON,
+};
+
+enum cam_flash_state {
+	CAM_FLASH_STATE_INIT,
+	CAM_FLASH_STATE_LOW,
+	CAM_FLASH_STATE_HIGH,
+	CAM_FLASH_STATE_RELEASE,
+};
+
+/**
+ * struct cam_flash_intf_params
+ * @device_hdl   : Device Handle
+ * @session_hdl  : Session Handle
+ * @link_hdl     : Link Handle
+ * @ops          : KMD operations
+ * @crm_cb       : Callback API pointers
+ */
+struct cam_flash_intf_params {
+	int32_t                     device_hdl;
+	int32_t                     session_hdl;
+	int32_t                     link_hdl;
+	struct cam_req_mgr_kmd_ops  ops;
+	struct cam_req_mgr_crm_cb  *crm_cb;
+};
+
+/**
+ * struct cam_flash_common_attr
+ * @is_settings_valid  : Notify the valid settings
+ * @request_id         : Request id provided by umd
+ * @count              : Number of led count
+ * @cmd_type           : Command buffer type
+ */
+struct cam_flash_common_attr {
+	bool     is_settings_valid;
+	int32_t  request_id;
+	uint16_t count;
+	uint8_t  cmd_type;
+};
+
+/**
+ * struct flash_init_packet
+ * @cmn_attr   : Provides common attributes
+ * @flash_type : Flash type(PMIC/I2C/GPIO)
+ */
+struct cam_flash_init_packet {
+	struct cam_flash_common_attr  cmn_attr;
+	uint8_t                       flash_type;
+};
+
+/**
+ * struct flash_frame_setting
+ * @cmn_attr         : Provides common attributes
+ * @num_iterations   : Iterations used to perform RER
+ * @led_on_delay_ms  : LED on time in milisec
+ * @led_off_delay_ms : LED off time in milisec
+ * @opcode           : Command buffer opcode
+ * @led_current_ma[] : LED current array in miliamps
+ *
+ */
+struct cam_flash_frame_setting {
+	struct cam_flash_common_attr cmn_attr;
+	uint16_t                     num_iterations;
+	uint16_t                     led_on_delay_ms;
+	uint16_t                     led_off_delay_ms;
+	int8_t                       opcode;
+	uint32_t                     led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS];
+};
+
+/**
+ *  struct cam_flash_private_soc
+ * @switch_trigger_name : Switch trigger name
+ * @flash_trigger_name  : Flash trigger name array
+ * @flash_op_current    : Flash operational current
+ * @flash_max_current   : Max supported current for LED in flash mode
+ * @flash_max_duration  : Max turn on duration for LED in Flash mode
+ * @torch_trigger_name  : Torch trigger name array
+ * @torch_op_current    : Torch operational current
+ * @torch_max_current   : Max supported current for LED in torch mode
+ */
+
+struct cam_flash_private_soc {
+	const char   *switch_trigger_name;
+	const char   *flash_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t     flash_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t     flash_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t     flash_max_duration[CAM_FLASH_MAX_LED_TRIGGERS];
+	const char   *torch_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t     torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t     torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
+};
+
+/**
+ *  struct cam_flash_ctrl
+ * @soc_info            : Soc related information
+ * @pdev                : Platform device
+ * @per_frame[]         : Per_frame setting array
+ * @nrt_info            : NonRealTime settings
+ * @of_node             : Of Node ptr
+ * @v4l2_dev_str        : V4L2 device structure
+ * @bridge_intf         : CRM interface
+ * @flash_init_setting  : Init command buffer structure
+ * @switch_trigger      : Switch trigger ptr
+ * @flash_num_sources   : Number of flash sources
+ * @torch_num_source    : Number of torch sources
+ * @flash_mutex         : Mutex for flash operations
+ * @flash_wq_mutex      : Mutex for flash apply setting
+ * @flash_state         : Current flash state (LOW/OFF/ON/INIT)
+ * @flash_type          : Flash types (PMIC/I2C/GPIO)
+ * @is_regulator_enable : Regulator disable/enable notifier
+ * @flash_trigger       : Flash trigger ptr
+ * @torch_trigger       : Torch trigger ptr
+ */
+struct cam_flash_ctrl {
+	struct cam_hw_soc_info          soc_info;
+	struct platform_device         *pdev;
+	struct cam_flash_frame_setting  per_frame[MAX_PER_FRAME_ARRAY];
+	struct cam_flash_frame_setting  nrt_info;
+	struct device_node             *of_node;
+	struct cam_subdev               v4l2_dev_str;
+	struct cam_flash_intf_params    bridge_intf;
+	struct cam_flash_init_packet    flash_init_setting;
+	struct led_trigger             *switch_trigger;
+	uint32_t                        flash_num_sources;
+	uint32_t                        torch_num_sources;
+	struct mutex                    flash_mutex;
+	struct mutex                    flash_wq_mutex;
+	enum   cam_flash_state          flash_state;
+	uint8_t                         flash_type;
+	bool                            is_regulator_enabled;
+	struct led_trigger           *flash_trigger[CAM_FLASH_MAX_LED_TRIGGERS];
+	struct led_trigger           *torch_trigger[CAM_FLASH_MAX_LED_TRIGGERS];
+};
+
+#endif /*_CAM_FLASH_DEV_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c
new file mode 100644
index 0000000..a9ab169
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c
@@ -0,0 +1,224 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/of_gpio.h>
+#include "cam_flash_soc.h"
+
+static int32_t cam_get_source_node_info(
+	struct device_node *of_node,
+	struct cam_flash_ctrl *fctrl,
+	struct cam_flash_private_soc *soc_private)
+{
+	int32_t rc = 0;
+	uint32_t count = 0, i = 0;
+	struct device_node *flash_src_node = NULL;
+	struct device_node *torch_src_node = NULL;
+	struct device_node *switch_src_node = NULL;
+
+	switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
+	if (!switch_src_node) {
+		CAM_DBG(CAM_FLASH, "switch_src_node NULL");
+	} else {
+		rc = of_property_read_string(switch_src_node,
+			"qcom,default-led-trigger",
+			&soc_private->switch_trigger_name);
+		if (rc) {
+			CAM_ERR(CAM_FLASH,
+				"default-led-trigger read failed rc=%d", rc);
+		} else {
+			CAM_DBG(CAM_FLASH, "switch trigger %s",
+				soc_private->switch_trigger_name);
+			led_trigger_register_simple(
+				soc_private->switch_trigger_name,
+				&fctrl->switch_trigger);
+		}
+
+		of_node_put(switch_src_node);
+	}
+
+	if (of_get_property(of_node, "flash-source", &count)) {
+		count /= sizeof(uint32_t);
+
+		if (count > CAM_FLASH_MAX_LED_TRIGGERS) {
+			CAM_ERR(CAM_FLASH, "Invalid LED count: %d", count);
+			return -EINVAL;
+		}
+
+		fctrl->flash_num_sources = count;
+
+		for (i = 0; i < count; i++) {
+			flash_src_node = of_parse_phandle(of_node,
+				"flash-source", i);
+			if (!flash_src_node) {
+				CAM_WARN(CAM_FLASH, "flash_src_node NULL");
+				continue;
+			}
+
+			rc = of_property_read_string(flash_src_node,
+				"qcom,default-led-trigger",
+				&soc_private->flash_trigger_name[i]);
+			if (rc) {
+				CAM_WARN(CAM_FLASH,
+				"defalut-led-trigger read failed rc=%d", rc);
+				of_node_put(flash_src_node);
+				continue;
+			}
+
+			CAM_DBG(CAM_FLASH, "default trigger %s",
+				soc_private->flash_trigger_name[i]);
+
+			/* Read operational-current */
+			rc = of_property_read_u32(flash_src_node,
+				"qcom,current-ma",
+				&soc_private->flash_op_current[i]);
+			if (rc) {
+				CAM_WARN(CAM_FLASH, "op-current: read failed");
+				of_node_put(flash_src_node);
+				continue;
+			}
+
+			/* Read max-current */
+			rc = of_property_read_u32(flash_src_node,
+				"qcom,max-current",
+				&soc_private->flash_max_current[i]);
+			if (rc) {
+				CAM_WARN(CAM_FLASH,
+					"max-current: read failed");
+				of_node_put(flash_src_node);
+				continue;
+			}
+
+			/* Read max-duration */
+			rc = of_property_read_u32(flash_src_node,
+				"qcom,duration-ms",
+				&soc_private->flash_max_duration[i]);
+			if (rc)
+				CAM_WARN(CAM_FLASH,
+					"max-duration: read failed");
+
+			of_node_put(flash_src_node);
+
+			CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
+				i, soc_private->flash_max_current[i]);
+
+			led_trigger_register_simple(
+				soc_private->flash_trigger_name[i],
+				&fctrl->flash_trigger[i]);
+		}
+	}
+
+	if (of_get_property(of_node, "torch-source", &count)) {
+		count /= sizeof(uint32_t);
+		if (count > CAM_FLASH_MAX_LED_TRIGGERS) {
+			CAM_ERR(CAM_FLASH, "Invalid LED count : %d", count);
+			return -EINVAL;
+		}
+
+		fctrl->torch_num_sources = count;
+
+		CAM_DBG(CAM_FLASH, "torch_num_sources = %d",
+			fctrl->torch_num_sources);
+		for (i = 0; i < count; i++) {
+			torch_src_node = of_parse_phandle(of_node,
+				"torch-source", i);
+			if (!torch_src_node) {
+				CAM_WARN(CAM_FLASH, "torch_src_node NULL");
+				continue;
+			}
+
+			rc = of_property_read_string(torch_src_node,
+				"qcom,default-led-trigger",
+				&soc_private->torch_trigger_name[i]);
+			if (rc < 0) {
+				CAM_WARN(CAM_FLASH,
+					"default-trigger read failed");
+				of_node_put(torch_src_node);
+				continue;
+			}
+
+			/* Read operational-current */
+			rc = of_property_read_u32(torch_src_node,
+				"qcom,current-ma",
+				&soc_private->torch_op_current[i]);
+			if (rc < 0) {
+				CAM_WARN(CAM_FLASH, "current: read failed");
+				of_node_put(torch_src_node);
+				continue;
+			}
+
+			/* Read max-current */
+			rc = of_property_read_u32(torch_src_node,
+				"qcom,max-current",
+				&soc_private->torch_max_current[i]);
+			if (rc < 0) {
+				CAM_WARN(CAM_FLASH,
+					"max-current: read failed");
+				of_node_put(torch_src_node);
+				continue;
+			}
+
+			of_node_put(torch_src_node);
+
+			CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
+				i, soc_private->torch_max_current[i]);
+
+			led_trigger_register_simple(
+				soc_private->torch_trigger_name[i],
+				&fctrl->torch_trigger[i]);
+		}
+	}
+
+	return rc;
+}
+
+int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl,
+	struct cam_hw_soc_info *soc_info)
+{
+	int32_t rc = 0;
+	struct device_node *of_node = NULL;
+
+	if (!fctrl) {
+		CAM_ERR(CAM_FLASH, "NULL flash control structure");
+		return -EINVAL;
+	}
+
+	of_node = fctrl->pdev->dev.of_node;
+
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc < 0) {
+		CAM_ERR(CAM_FLASH, "Get_dt_properties failed rc %d", rc);
+		return rc;
+	}
+
+	soc_info->soc_private =
+		kzalloc(sizeof(struct cam_flash_private_soc), GFP_KERNEL);
+	if (!soc_info->soc_private) {
+		rc = -ENOMEM;
+		goto release_soc_res;
+	}
+
+	rc = cam_get_source_node_info(of_node, fctrl, soc_info->soc_private);
+	if (rc < 0) {
+		CAM_ERR(CAM_FLASH,
+			"cam_flash_get_pmic_source_info failed rc %d", rc);
+		goto free_soc_private;
+	}
+
+	return rc;
+
+free_soc_private:
+	kfree(soc_info->soc_private);
+release_soc_res:
+	cam_soc_util_release_platform_resource(soc_info);
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.h
new file mode 100644
index 0000000..2e1da69
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2017, 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 _CAM_FLASH_SOC_H_
+#define _CAM_FLASH_SOC_H_
+
+#include "cam_flash_dev.h"
+
+int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl,
+	struct cam_hw_soc_info *soc_info);
+
+#endif /*_CAM_FLASH_SOC_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index be8306c..f6e6a9a 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -35,8 +35,7 @@
 	ioctl_ctrl = (struct cam_control *)arg;
 
 	if (ioctl_ctrl->handle_type != CAM_HANDLE_USER_POINTER) {
-		pr_err("%s:%d :Error: Invalid Handle Type\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid Handle Type");
 		return -EINVAL;
 	}
 
@@ -49,22 +48,21 @@
 		(uint64_t *)&generic_ptr,
 		&len_of_buff);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: Failed in getting the buffer: %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "Failed in getting the buffer: %d", rc);
 		return rc;
 	}
 
 	csl_packet = (struct cam_packet *)(generic_ptr +
 		config.offset);
 	if (config.offset > len_of_buff) {
-		pr_err("%s: %d offset is out of bounds: off: %lld len: %zu\n",
-			__func__, __LINE__, config.offset, len_of_buff);
+		CAM_ERR(CAM_SENSOR,
+			"offset is out of bounds: off: %lld len: %zu",
+			 config.offset, len_of_buff);
 		return -EINVAL;
 	}
 
 	i2c_data = &(s_ctrl->i2c_data);
-	CDBG("%s:%d Header OpCode: %d\n",
-		__func__, __LINE__, csl_packet->header.op_code);
+	CAM_DBG(CAM_SENSOR, "Header OpCode: %d", csl_packet->header.op_code);
 	if ((csl_packet->header.op_code & 0xFFFFFF) ==
 		CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG) {
 		i2c_reg_settings = &i2c_data->init_settings;
@@ -76,16 +74,16 @@
 			&i2c_data->
 			per_frame[csl_packet->header.request_id %
 			MAX_PER_FRAME_ARRAY];
-		CDBG("%s:%d Received Packet: %lld\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "Received Packet: %lld",
 			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY);
 		if (i2c_reg_settings->is_settings_valid == 1) {
-			pr_err("%s:%d :Error: Already some pkt in offset req : %lld\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_SENSOR,
+				"Already some pkt in offset req : %lld",
 				csl_packet->header.request_id);
 			rc = delete_request(i2c_reg_settings);
 			if (rc < 0) {
-				pr_err("%s: %d :Error: Failed in Deleting the err: %d\n",
-					__func__, __LINE__, rc);
+				CAM_ERR(CAM_SENSOR,
+					"Failed in Deleting the err: %d", rc);
 				return rc;
 			}
 		}
@@ -97,7 +95,7 @@
 		CAM_PKT_NOP_OPCODE) {
 		goto update_req_mgr;
 	} else {
-		pr_err("%s:%d Invalid Packet Header\n", __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid Packet Header");
 		return -EINVAL;
 	}
 
@@ -107,8 +105,7 @@
 
 	rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, cmd_desc, 1);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: Fail parsing I2C Pkt: %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc);
 		return rc;
 	}
 
@@ -118,14 +115,14 @@
 		CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE)) {
 		add_req.link_hdl = s_ctrl->bridge_intf.link_hdl;
 		add_req.req_id = csl_packet->header.request_id;
-		CDBG("%s:%d Rxed Req Id: %lld\n",
-			__func__, __LINE__, csl_packet->header.request_id);
+		CAM_DBG(CAM_SENSOR, " Rxed Req Id: %lld",
+			 csl_packet->header.request_id);
 		add_req.dev_hdl = s_ctrl->bridge_intf.device_hdl;
 		if (s_ctrl->bridge_intf.crm_cb &&
 			s_ctrl->bridge_intf.crm_cb->add_req)
 			s_ctrl->bridge_intf.crm_cb->add_req(&add_req);
-		CDBG("%s:%d add req to req mgr: %lld\n",
-			__func__, __LINE__, add_req.req_id);
+		CAM_DBG(CAM_SENSOR, " add req to req mgr: %lld",
+			add_req.req_id);
 	}
 	return rc;
 }
@@ -139,7 +136,8 @@
 	if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
 		cci_client = s_ctrl->io_master_info.cci_client;
 		if (!cci_client) {
-			pr_err("failed: cci_client %pK", cci_client);
+			CAM_ERR(CAM_SENSOR, "failed: cci_client %pK",
+				cci_client);
 			return -EINVAL;
 		}
 		cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;
@@ -147,8 +145,7 @@
 		cci_client->retries = 3;
 		cci_client->id_map = 0;
 		cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
-		CDBG("%s:%d Master: %d sid: %d freq_mode: %d\n",
-			__func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, " Master: %d sid: %d freq_mode: %d",
 			cci_client->cci_i2c_master, i2c_info->slave_addr,
 			i2c_info->i2c_freq_mode);
 	}
@@ -170,211 +167,14 @@
 
 	s_ctrl->sensor_probe_addr_type =  probe_info->addr_type;
 	s_ctrl->sensor_probe_data_type =  probe_info->data_type;
-	CDBG("%s:%d Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x\n",
-		__func__, __LINE__,
+	CAM_DBG(CAM_SENSOR,
+		"Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x",
 		s_ctrl->sensordata->slave_info.sensor_id_reg_addr,
 		s_ctrl->sensordata->slave_info.sensor_id,
 		s_ctrl->sensordata->slave_info.sensor_id_mask);
 	return rc;
 }
 
-int32_t cam_sensor_update_power_settings(void *cmd_buf,
-	int cmd_length, struct cam_sensor_ctrl_t *s_ctrl)
-{
-	int32_t rc = 0, tot_size = 0, last_cmd_type = 0;
-	int32_t i = 0, pwr_up = 0, pwr_down = 0;
-	void *ptr = cmd_buf, *scr;
-	struct cam_cmd_power *pwr_cmd = (struct cam_cmd_power *)cmd_buf;
-	struct common_header *cmm_hdr = (struct common_header *)cmd_buf;
-	struct cam_sensor_power_ctrl_t *power_info =
-		&s_ctrl->sensordata->power_info;
-
-	if (!pwr_cmd || !cmd_length) {
-		pr_err("%s:%d Invalid Args: pwr_cmd %pK, cmd_length: %d\n",
-			__func__, __LINE__, pwr_cmd, cmd_length);
-		return -EINVAL;
-	}
-
-	power_info->power_setting_size = 0;
-	power_info->power_setting =
-		(struct cam_sensor_power_setting *)
-		kzalloc(sizeof(struct cam_sensor_power_setting) *
-			MAX_POWER_CONFIG, GFP_KERNEL);
-	if (!power_info->power_setting)
-		return -ENOMEM;
-
-	power_info->power_down_setting =
-		(struct cam_sensor_power_setting *)
-		kzalloc(sizeof(struct cam_sensor_power_setting) *
-			MAX_POWER_CONFIG, GFP_KERNEL);
-	if (!power_info->power_down_setting) {
-		rc = -ENOMEM;
-		goto free_power_settings;
-	}
-
-	while (tot_size < cmd_length) {
-		if (cmm_hdr->cmd_type ==
-			CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
-			struct cam_cmd_power *pwr_cmd =
-				(struct cam_cmd_power *)ptr;
-
-			power_info->
-				power_setting_size +=
-				pwr_cmd->count;
-			scr = ptr + sizeof(struct cam_cmd_power);
-			tot_size = tot_size + sizeof(struct cam_cmd_power);
-
-			if (pwr_cmd->count == 0)
-				CDBG("%s:%d Un expected Command\n",
-					__func__, __LINE__);
-
-			for (i = 0; i < pwr_cmd->count; i++, pwr_up++) {
-				power_info->
-					power_setting[pwr_up].seq_type =
-					pwr_cmd->power_settings[i].
-						power_seq_type;
-				power_info->
-					power_setting[pwr_up].config_val =
-					pwr_cmd->power_settings[i].
-						config_val_low;
-				power_info->power_setting[pwr_up].delay = 0;
-				if (i) {
-					scr = scr +
-						sizeof(
-						struct cam_power_settings);
-					tot_size = tot_size +
-						sizeof(
-						struct cam_power_settings);
-				}
-				if (tot_size > cmd_length) {
-					pr_err("%s:%d :Error: Command Buffer is wrong\n",
-						__func__, __LINE__);
-					rc = -EINVAL;
-					goto free_power_down_settings;
-				}
-				CDBG("Seq Type[%d]: %d Config_val: %ldn",
-					pwr_up,
-					power_info->
-						power_setting[pwr_up].seq_type,
-					power_info->
-						power_setting[pwr_up].
-						config_val);
-			}
-			last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP;
-			ptr = (void *) scr;
-			cmm_hdr = (struct common_header *)ptr;
-		} else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT) {
-			struct cam_cmd_unconditional_wait *wait_cmd =
-				(struct cam_cmd_unconditional_wait *)ptr;
-			if (wait_cmd->op_code ==
-				CAMERA_SENSOR_WAIT_OP_SW_UCND) {
-				if (last_cmd_type ==
-					CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
-					if (pwr_up > 0)
-						power_info->
-							power_setting
-							[pwr_up - 1].delay +=
-							wait_cmd->delay;
-					else
-						pr_err("%s:%d Delay is expected only after valid power up setting\n",
-							__func__, __LINE__);
-				} else if (last_cmd_type ==
-					CAMERA_SENSOR_CMD_TYPE_PWR_DOWN) {
-					if (pwr_down > 0)
-						power_info->
-							power_down_setting
-							[pwr_down - 1].delay +=
-							wait_cmd->delay;
-					else
-						pr_err("%s:%d Delay is expected only after valid power down setting\n",
-							__func__, __LINE__);
-				}
-			} else
-				CDBG("%s:%d Invalid op code: %d\n",
-					__func__, __LINE__, wait_cmd->op_code);
-			tot_size = tot_size +
-				sizeof(struct cam_cmd_unconditional_wait);
-			if (tot_size > cmd_length) {
-				pr_err("Command Buffer is wrong\n");
-				return -EINVAL;
-			}
-			scr = (void *) (wait_cmd);
-			ptr = (void *)
-				(scr +
-				sizeof(struct cam_cmd_unconditional_wait));
-			CDBG("%s:%d ptr: %pK sizeof: %d Next: %pK\n",
-				__func__, __LINE__, scr,
-				(int32_t)sizeof(
-				struct cam_cmd_unconditional_wait), ptr);
-
-			cmm_hdr = (struct common_header *)ptr;
-		} else if (cmm_hdr->cmd_type ==
-			CAMERA_SENSOR_CMD_TYPE_PWR_DOWN) {
-			struct cam_cmd_power *pwr_cmd =
-				(struct cam_cmd_power *)ptr;
-
-			scr = ptr + sizeof(struct cam_cmd_power);
-			tot_size = tot_size + sizeof(struct cam_cmd_power);
-			power_info->power_down_setting_size += pwr_cmd->count;
-
-			if (pwr_cmd->count == 0)
-				pr_err("%s:%d Invalid Command\n",
-					__func__, __LINE__);
-
-			for (i = 0; i < pwr_cmd->count; i++, pwr_down++) {
-				power_info->
-					power_down_setting[pwr_down].
-					seq_type =
-					pwr_cmd->power_settings[i].
-					power_seq_type;
-				power_info->
-					power_down_setting[pwr_down].
-					config_val =
-					pwr_cmd->power_settings[i].
-					config_val_low;
-				power_info->
-					power_down_setting[pwr_down].delay = 0;
-				if (i) {
-					scr = scr +
-						sizeof(
-						struct cam_power_settings);
-					tot_size =
-						tot_size +
-						sizeof(
-						struct cam_power_settings);
-				}
-				if (tot_size > cmd_length) {
-					pr_err("Command Buffer is wrong\n");
-					rc = -EINVAL;
-					goto free_power_down_settings;
-				}
-				CDBG("%s:%d Seq Type[%d]: %d Config_val: %ldn",
-					__func__, __LINE__,
-					pwr_down,
-					power_info->
-						power_down_setting[pwr_down].
-						seq_type,
-					power_info->
-						power_down_setting[pwr_down].
-						config_val);
-			}
-			last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN;
-			ptr = (void *) scr;
-			cmm_hdr = (struct common_header *)ptr;
-		} else {
-			pr_err("%s:%d: :Error: Un expected Header Type: %d\n",
-				__func__, __LINE__, cmm_hdr->cmd_type);
-		}
-	}
-
-	return rc;
-free_power_down_settings:
-	kfree(power_info->power_down_setting);
-free_power_settings:
-	kfree(power_info->power_setting);
-	return rc;
-}
-
 int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
 	struct cam_sensor_ctrl_t *s_ctrl,
 	int32_t cmd_buf_num, int cmd_buf_length)
@@ -389,16 +189,14 @@
 		i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
 		rc = cam_sensor_update_i2c_info(i2c_info, s_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d Failed in Updating the i2c Info\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "Failed in Updating the i2c Info");
 			return rc;
 		}
 		probe_info = (struct cam_cmd_probe *)
 			(cmd_buf + sizeof(struct cam_cmd_i2c_info));
 		rc = cam_sensor_update_slave_info(probe_info, s_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Updating the slave Info\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "Updating the slave Info");
 			return rc;
 		}
 		cmd_buf = probe_info;
@@ -406,16 +204,16 @@
 		break;
 	case 1: {
 		rc = cam_sensor_update_power_settings(cmd_buf,
-			cmd_buf_length, s_ctrl);
+			cmd_buf_length, &s_ctrl->sensordata->power_info);
 		if (rc < 0) {
-			pr_err("Failed in updating power settings\n");
+			CAM_ERR(CAM_SENSOR,
+				"Failed in updating power settings");
 			return rc;
 		}
 	}
 		break;
 	default:
-		pr_err("%s:%d Invalid command buffer\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid command buffer");
 		break;
 	}
 	return rc;
@@ -434,21 +232,19 @@
 	rc = cam_mem_get_cpu_buf(handle,
 		(uint64_t *)&packet, &len);
 	if (rc < 0) {
-		pr_err("%s: %d Failed to get the command Buffer\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Failed to get the command Buffer");
 		return -EINVAL;
 	}
 	pkt = (struct cam_packet *)packet;
 	cmd_desc = (struct cam_cmd_buf_desc *)
 		((uint32_t *)&pkt->payload + pkt->cmd_buf_offset/4);
 	if (cmd_desc == NULL) {
-		pr_err("%s: %d command descriptor pos is invalid\n",
-		__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "command descriptor pos is invalid");
 		return -EINVAL;
 	}
 	if (pkt->num_cmd_buf != 2) {
-		pr_err("%s: %d Expected More Command Buffers : %d\n",
-			__func__, __LINE__, pkt->num_cmd_buf);
+		CAM_ERR(CAM_SENSOR, "Expected More Command Buffers : %d",
+			 pkt->num_cmd_buf);
 		return -EINVAL;
 	}
 	for (i = 0; i < pkt->num_cmd_buf; i++) {
@@ -457,8 +253,8 @@
 		rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
 			(uint64_t *)&cmd_buf1, &len);
 		if (rc < 0) {
-			pr_err("%s: %d Failed to parse the command Buffer Header\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR,
+				"Failed to parse the command Buffer Header");
 			return -EINVAL;
 		}
 		cmd_buf = (uint32_t *)cmd_buf1;
@@ -468,8 +264,8 @@
 		rc = cam_handle_cmd_buffers_for_probe(ptr, s_ctrl,
 			i, cmd_desc[i].length);
 		if (rc < 0) {
-			pr_err("%s: %d Failed to parse the command Buffer Header\n",
-			__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR,
+				"Failed to parse the command Buffer Header");
 			return -EINVAL;
 		}
 	}
@@ -525,8 +321,8 @@
 	slave_info = &(s_ctrl->sensordata->slave_info);
 
 	if (!slave_info) {
-		pr_err("%s:%d failed: %pK\n",
-			__func__, __LINE__, slave_info);
+		CAM_ERR(CAM_SENSOR, " failed: %pK",
+			 slave_info);
 		return -EINVAL;
 	}
 
@@ -536,11 +332,11 @@
 		&chipid, CAMERA_SENSOR_I2C_TYPE_WORD,
 		CAMERA_SENSOR_I2C_TYPE_WORD);
 
-	CDBG("%s:%d read id: 0x%x expected id 0x%x:\n",
-			__func__, __LINE__, chipid, slave_info->sensor_id);
+	CAM_DBG(CAM_SENSOR, "read id: 0x%x expected id 0x%x:",
+			 chipid, slave_info->sensor_id);
 	if (cam_sensor_id_by_mask(s_ctrl, chipid) != slave_info->sensor_id) {
-		pr_err("%s: chip id %x does not match %x\n",
-				__func__, chipid, slave_info->sensor_id);
+		CAM_ERR(CAM_SENSOR, "chip id %x does not match %x",
+				chipid, slave_info->sensor_id);
 		return -ENODEV;
 	}
 	return rc;
@@ -557,8 +353,7 @@
 		&s_ctrl->sensordata->power_info;
 
 	if (!s_ctrl || !arg) {
-		pr_err("%s: %d s_ctrl is NULL\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "s_ctrl is NULL");
 		return -EINVAL;
 	}
 
@@ -566,7 +361,8 @@
 	switch (cmd->op_code) {
 	case CAM_SENSOR_PROBE_CMD: {
 		if (s_ctrl->is_probe_succeed == 1) {
-			pr_err("Already Sensor Probed in the slot\n");
+			CAM_ERR(CAM_SENSOR,
+				"Already Sensor Probed in the slot");
 			break;
 		}
 		/* Allocate memory for power up setting */
@@ -592,15 +388,14 @@
 			CAM_HANDLE_MEM_HANDLE) {
 			rc = cam_handle_mem_ptr(cmd->handle, s_ctrl);
 			if (rc < 0) {
-				pr_err("%s: %d Get Buffer Handle Failed\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_SENSOR, "Get Buffer Handle Failed");
 				kfree(pu);
 				kfree(pd);
 				goto release_mutex;
 			}
 		} else {
-			pr_err("%s:%d :Error: Invalid Command Type: %d",
-				__func__, __LINE__, cmd->handle_type);
+			CAM_ERR(CAM_SENSOR, "Invalid Command Type: %d",
+				 cmd->handle_type);
 		}
 
 		/* Parse and fill vreg params for powerup settings */
@@ -609,8 +404,9 @@
 			s_ctrl->sensordata->power_info.power_setting,
 			s_ctrl->sensordata->power_info.power_setting_size);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Fail in filling vreg params for PUP rc %d",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR,
+				"Fail in filling vreg params for PUP rc %d",
+				 rc);
 			kfree(pu);
 			kfree(pd);
 			goto release_mutex;
@@ -622,8 +418,9 @@
 			s_ctrl->sensordata->power_info.power_down_setting,
 			s_ctrl->sensordata->power_info.power_down_setting_size);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Fail in filling vreg params for PDOWN rc %d",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR,
+				"Fail in filling vreg params for PDOWN rc %d",
+				 rc);
 			kfree(pu);
 			kfree(pd);
 			goto release_mutex;
@@ -632,7 +429,7 @@
 		/* Power up and probe sensor */
 		rc = cam_sensor_power_up(s_ctrl);
 		if (rc < 0) {
-			pr_err("power up failed");
+			CAM_ERR(CAM_SENSOR, "power up failed");
 			cam_sensor_power_down(s_ctrl);
 			kfree(pu);
 			kfree(pd);
@@ -649,13 +446,11 @@
 			goto release_mutex;
 		}
 
-		CDBG("%s:%d Probe Succeeded on the slot: %d\n",
-			__func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "Probe Succeeded on the slot: %d",
 			s_ctrl->soc_info.index);
 		rc = cam_sensor_power_down(s_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: fail in Sensor Power Down\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "fail in Sensor Power Down");
 			kfree(pu);
 			kfree(pd);
 			goto release_mutex;
@@ -672,15 +467,14 @@
 		struct cam_create_dev_hdl bridge_params;
 
 		if (s_ctrl->bridge_intf.device_hdl != -1) {
-			pr_err("%s:%d Device is already acquired\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "Device is already acquired");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
 		rc = copy_from_user(&sensor_acq_dev,
 			(void __user *) cmd->handle, sizeof(sensor_acq_dev));
 		if (rc < 0) {
-			pr_err("Failed Copying from user\n");
+			CAM_ERR(CAM_SENSOR, "Failed Copying from user");
 			goto release_mutex;
 		}
 
@@ -695,11 +489,11 @@
 		s_ctrl->bridge_intf.device_hdl = sensor_acq_dev.device_handle;
 		s_ctrl->bridge_intf.session_hdl = sensor_acq_dev.session_handle;
 
-		CDBG("%s:%d Device Handle: %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "Device Handle: %d",
 			sensor_acq_dev.device_handle);
 		if (copy_to_user((void __user *) cmd->handle, &sensor_acq_dev,
 			sizeof(struct cam_sensor_acquire_dev))) {
-			pr_err("Failed Copy to User\n");
+			CAM_ERR(CAM_SENSOR, "Failed Copy to User");
 			rc = -EFAULT;
 			goto release_mutex;
 		}
@@ -707,8 +501,8 @@
 		break;
 	case CAM_RELEASE_DEV: {
 		if (s_ctrl->bridge_intf.device_hdl == -1) {
-			pr_err("%s:%d Invalid Handles: link hdl: %d device hdl: %d\n",
-				__func__, __LINE__,
+			CAM_ERR(CAM_SENSOR,
+				"Invalid Handles: link hdl: %d device hdl: %d",
 				s_ctrl->bridge_intf.device_hdl,
 				s_ctrl->bridge_intf.link_hdl);
 			rc = -EINVAL;
@@ -716,8 +510,8 @@
 		}
 		rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
 		if (rc < 0)
-			pr_err("%s:%d Failed in destroying the device hdl\n",
-			__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR,
+				"failed in destroying the device hdl");
 		s_ctrl->bridge_intf.device_hdl = -1;
 		s_ctrl->bridge_intf.link_hdl = -1;
 		s_ctrl->bridge_intf.session_hdl = -1;
@@ -729,7 +523,7 @@
 		cam_sensor_query_cap(s_ctrl, &sensor_cap);
 		if (copy_to_user((void __user *) cmd->handle, &sensor_cap,
 			sizeof(struct  cam_sensor_query_cap))) {
-			pr_err("Failed Copy to User\n");
+			CAM_ERR(CAM_SENSOR, "Failed Copy to User");
 			rc = -EFAULT;
 			goto release_mutex;
 		}
@@ -738,19 +532,18 @@
 	case CAM_START_DEV: {
 		rc = cam_sensor_power_up(s_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Sensor Power up failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "Sensor Power up failed");
 			goto release_mutex;
 		}
 		rc = cam_sensor_apply_settings(s_ctrl, 0);
 		if (rc < 0) {
-			pr_err("cannot apply settings\n");
+			CAM_ERR(CAM_SENSOR, "cannot apply settings");
 			goto release_mutex;
 		}
 		rc = delete_request(&s_ctrl->i2c_data.init_settings);
 		if (rc < 0) {
-			pr_err("%s:%d Fail in deleting the Init settings\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR,
+				"Fail in deleting the Init settings");
 			rc = -EINVAL;
 			goto release_mutex;
 		}
@@ -759,8 +552,7 @@
 	case CAM_STOP_DEV: {
 		rc = cam_sensor_power_down(s_ctrl);
 		if (rc < 0) {
-			pr_err("%s:%d Sensor Power Down failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "Sensor Power Down failed");
 			goto release_mutex;
 		}
 	}
@@ -768,8 +560,7 @@
 	case CAM_CONFIG_DEV: {
 		rc = cam_sensor_i2c_pkt_parse(s_ctrl, arg);
 		if (rc < 0) {
-			pr_err("%s:%d :Error: Failed CCI Config: %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "Failed CCI Config: %d", rc);
 			goto release_mutex;
 		}
 	}
@@ -777,8 +568,7 @@
 	case CAM_SD_SHUTDOWN:
 		break;
 	default:
-		pr_err("%s:%d :Error: Invalid Opcode: %d\n",
-			__func__, __LINE__, cmd->op_code);
+		CAM_ERR(CAM_SENSOR, "Invalid Opcode: %d", cmd->op_code);
 		rc = -EINVAL;
 		goto release_mutex;
 	}
@@ -812,7 +602,7 @@
 	s_ctrl = (struct cam_sensor_ctrl_t *)
 		cam_get_device_priv(link->dev_hdl);
 	if (!s_ctrl) {
-		pr_err("%s: Device data is NULL\n", __func__);
+		CAM_ERR(CAM_SENSOR, "Device data is NULL");
 		return -EINVAL;
 	}
 	if (link->link_enable) {
@@ -849,8 +639,7 @@
 		&s_ctrl->soc_info;
 
 	if (!s_ctrl) {
-		pr_err("%s:%d failed: %pK\n",
-			__func__, __LINE__, s_ctrl);
+		CAM_ERR(CAM_SENSOR, "failed: %pK", s_ctrl);
 		return -EINVAL;
 	}
 
@@ -858,23 +647,20 @@
 	slave_info = &(s_ctrl->sensordata->slave_info);
 
 	if (!power_info || !slave_info) {
-		pr_err("%s:%d failed: %pK %pK\n",
-			__func__, __LINE__, power_info,
-			slave_info);
+		CAM_ERR(CAM_SENSOR, "failed: %pK %pK", power_info, slave_info);
 		return -EINVAL;
 	}
 
 	rc = cam_sensor_core_power_up(power_info, soc_info);
 	if (rc < 0) {
-		pr_err("%s:%d power up the core is failed:%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc);
 		return rc;
 	}
 
 	if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
 		rc = camera_io_init(&(s_ctrl->io_master_info));
 		if (rc < 0) {
-			pr_err("%s cci_init failed\n", __func__);
+			CAM_ERR(CAM_SENSOR, "cci_init failed");
 			return -EINVAL;
 		}
 	}
@@ -891,8 +677,7 @@
 	int rc = 0;
 
 	if (!s_ctrl) {
-		pr_err("%s:%d failed: s_ctrl %pK\n",
-			__func__, __LINE__, s_ctrl);
+		CAM_ERR(CAM_SENSOR, "failed: s_ctrl %pK", s_ctrl);
 		return -EINVAL;
 	}
 
@@ -900,14 +685,12 @@
 	soc_info = &s_ctrl->soc_info;
 
 	if (!power_info) {
-		pr_err("%s:%d failed: power_info %pK\n",
-			__func__, __LINE__, power_info);
+		CAM_ERR(CAM_SENSOR, "failed: power_info %pK", power_info);
 		return -EINVAL;
 	}
 	rc = msm_camera_power_down(power_info, soc_info);
 	if (rc < 0) {
-		pr_err("%s:%d power down the core is failed:%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "power down the core is failed:%d", rc);
 		return rc;
 	}
 
@@ -935,15 +718,16 @@
 					&(s_ctrl->io_master_info),
 					&(i2c_list->i2c_settings));
 				if (rc < 0) {
-					pr_err("Failed to write the I2C settings\n");
+					CAM_ERR(CAM_SENSOR,
+					"Failed to write the I2C settings");
 					return rc;
 				}
 			}
 			rc = delete_request(&(s_ctrl->i2c_data.init_settings));
 			i2c_set->is_settings_valid = 0;
 			if (rc < 0) {
-				pr_err("%s:%d :Error: Failed in deleting the Init request: %d\n",
-					__func__, __LINE__, rc);
+				CAM_ERR(CAM_SENSOR,
+				"Failed in deleting the Init request: %d", rc);
 			}
 		}
 	} else {
@@ -957,8 +741,9 @@
 					&(s_ctrl->io_master_info),
 					&(i2c_list->i2c_settings));
 				if (rc < 0) {
-					pr_err("%s:%d :Error: Fail to write the I2C settings: %d\n",
-						__func__, __LINE__, rc);
+					CAM_ERR(CAM_SENSOR,
+					"Fail to write the I2C settings: %d",
+						 rc);
 					return rc;
 				}
 			}
@@ -966,8 +751,8 @@
 				MAX_PER_FRAME_ARRAY -
 				MAX_SYSTEM_PIPELINE_DELAY) %
 				MAX_PER_FRAME_ARRAY;
-			CDBG("%s:%d Deleting the Request: %d\n",
-				__func__, __LINE__,	del_req_id);
+			CAM_DBG(CAM_SENSOR, "Deleting the Request: %d",
+				del_req_id);
 			if (req_id >
 				s_ctrl->i2c_data.per_frame[del_req_id].
 				request_id) {
@@ -977,13 +762,13 @@
 					&(s_ctrl->i2c_data.
 					per_frame[del_req_id]));
 				if (rc < 0)
-					pr_err("%s:%d :Error: Failed in deleting the request: %d rc: %d\n",
-						__func__, __LINE__,
+					CAM_ERR(CAM_SENSOR,
+						"Delete request Fail:%d rc:%d",
 						del_req_id, rc);
 			}
 		} else {
-			CDBG("%s:%d Invalid/NOP request to apply: %lld\n",
-				__func__, __LINE__, req_id);
+			CAM_DBG(CAM_SENSOR,
+				"Invalid/NOP request to apply: %lld", req_id);
 		}
 	}
 	return rc;
@@ -1000,14 +785,11 @@
 	s_ctrl = (struct cam_sensor_ctrl_t *)
 		cam_get_device_priv(apply->dev_hdl);
 	if (!s_ctrl) {
-		pr_err("%s: Device data is NULL\n", __func__);
+		CAM_ERR(CAM_SENSOR, "Device data is NULL");
 		return -EINVAL;
 	}
-	CDBG("%s:%d Req Id: %lld\n", __func__, __LINE__,
-		apply->request_id);
-
+	CAM_DBG(CAM_SENSOR, " Req Id: %lld", apply->request_id);
 	trace_cam_apply_req("Sensor", apply);
-
 	rc = cam_sensor_apply_settings(s_ctrl, apply->request_id);
 	return rc;
 }
@@ -1025,7 +807,7 @@
 	s_ctrl = (struct cam_sensor_ctrl_t *)
 		cam_get_device_priv(flush_req->dev_hdl);
 	if (!s_ctrl) {
-		pr_err("%s: Device data is NULL\n", __func__);
+		CAM_ERR(CAM_SENSOR, "Device data is NULL");
 		return -EINVAL;
 	}
 
@@ -1039,8 +821,8 @@
 		if (i2c_set->is_settings_valid == 1) {
 			rc = delete_request(i2c_set);
 			if (rc < 0)
-				pr_err("%s:%d :Error: delete request: %lld rc: %d\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR,
+					"delete request: %lld rc: %d",
 					i2c_set->request_id, rc);
 
 			if (flush_req->type ==
@@ -1053,7 +835,8 @@
 
 	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ &&
 		!cancel_req_id_found)
-		CDBG("%s:Flush request id:%lld not found in the pending list\n",
-			__func__, flush_req->req_id);
+		CAM_DBG(CAM_SENSOR,
+			"Flush request id:%lld not found in the pending list",
+			flush_req->req_id);
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c
index c06a1b3..40cf689 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c
@@ -27,8 +27,7 @@
 		rc = cam_sensor_driver_cmd(s_ctrl, arg);
 		break;
 	default:
-		pr_err("%s:%d Invalid ioctl cmd: %d\n",
-			__func__, __LINE__, cmd);
+		CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd);
 		rc = -EINVAL;
 		break;
 	}
@@ -42,8 +41,8 @@
 	struct cam_sensor_ctrl_t *s_ctrl;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		pr_err("%s %s :Error: i2c_check_functionality failed\n",
-			__func__, client->name);
+		CAM_ERR(CAM_SENSOR,
+			"%s :i2c_check_functionality failed", client->name);
 		return -EFAULT;
 	}
 
@@ -60,8 +59,7 @@
 
 	rc = cam_sensor_parse_dt(s_ctrl);
 	if (rc < 0) {
-		pr_err("%s:%d :Error: cam_sensor_parse_dt rc %d",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "cam_sensor_parse_dt rc %d", rc);
 		goto free_s_ctrl;
 	}
 
@@ -77,7 +75,7 @@
 
 	s_ctrl = platform_get_drvdata(pdev);
 	if (!s_ctrl) {
-		pr_err("%s: sensor device is NULL\n", __func__);
+		CAM_ERR(CAM_SENSOR, "sensor device is NULL");
 		return 0;
 	}
 
@@ -92,7 +90,7 @@
 	struct cam_sensor_ctrl_t  *s_ctrl = i2c_get_clientdata(client);
 
 	if (!s_ctrl) {
-		pr_err("%s: sensor device is NULL\n", __func__);
+		CAM_ERR(CAM_SENSOR, "sensor device is NULL");
 		return 0;
 	}
 
@@ -111,7 +109,7 @@
 
 	if (copy_from_user(&cmd_data, (void __user *)arg,
 		sizeof(cmd_data))) {
-		pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+		CAM_ERR(CAM_SENSOR, "Failed to copy from user_ptr=%pK size=%zu",
 			(void __user *)arg, sizeof(cmd_data));
 		return -EFAULT;
 	}
@@ -120,19 +118,18 @@
 	case VIDIOC_CAM_CONTROL:
 		rc = cam_sensor_subdev_ioctl(sd, cmd, &cmd_data);
 		if (rc < 0)
-			pr_err("%s:%d cam_sensor_subdev_ioctl failed\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "cam_sensor_subdev_ioctl failed");
 		break;
 	default:
-		pr_err("%s:%d Invalid compat ioctl cmd_type: %d\n",
-			__func__, __LINE__, cmd);
+		CAM_ERR(CAM_SENSOR, "Invalid compat ioctl cmd_type: %d", cmd);
 		rc = -EINVAL;
 	}
 
 	if (!rc) {
 		if (copy_to_user((void __user *)arg, &cmd_data,
 			sizeof(cmd_data))) {
-			pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+			CAM_ERR(CAM_SENSOR,
+				"Failed to copy to user_ptr=%pK size=%zu",
 				(void __user *)arg, sizeof(cmd_data));
 			rc = -EFAULT;
 		}
@@ -188,7 +185,7 @@
 
 	rc = cam_sensor_parse_dt(s_ctrl);
 	if (rc < 0) {
-		pr_err("failed: cam_sensor_parse_dt rc %d", rc);
+		CAM_ERR(CAM_SENSOR, "failed: cam_sensor_parse_dt rc %d", rc);
 		goto free_s_ctrl;
 	}
 
@@ -211,8 +208,7 @@
 
 	rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str));
 	if (rc < 0) {
-		pr_err("%s:%d :ERROR: Fail with cam_register_subdev\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev");
 		goto free_s_ctrl;
 	}
 
@@ -278,11 +274,11 @@
 
 	rc = platform_driver_register(&cam_sensor_platform_driver);
 	if (rc)
-		pr_err("%s platform_driver_register failed rc = %d",
-			__func__, rc);
+		CAM_ERR(CAM_SENSOR, "platform_driver_register failed rc = %d",
+			rc);
 	rc = i2c_add_driver(&cam_sensor_driver_i2c);
 	if (rc)
-		pr_err("%s i2c_add_driver failed rc = %d", __func__, rc);
+		CAM_ERR(CAM_SENSOR, "i2c_add_driver failed rc = %d", rc);
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
index ae14c9d..f3c70c4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
@@ -31,6 +31,7 @@
 #include <cam_sensor_cmn_header.h>
 #include <cam_subdev.h>
 #include <cam_sensor_io.h>
+#include "cam_debug_util.h"
 
 #define NUM_MASTERS 2
 #define NUM_QUEUES 2
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
index 78edec1..c10d634 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
@@ -34,13 +34,12 @@
 
 	src_node = of_parse_phandle(of_node, "actuator-src", 0);
 	if (!src_node) {
-		CDBG("%s:%d src_node NULL\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, "src_node NULL");
 	} else {
 		rc = of_property_read_u32(src_node, "cell-index", &val);
-		CDBG("%s:%d actuator cell index %d, rc %d\n", __func__,
-			__LINE__, val, rc);
+		CAM_DBG(CAM_SENSOR, "actuator cell index %d, rc %d", val, rc);
 		if (rc < 0) {
-			pr_err("%s:%d failed %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "failed %d", rc);
 			of_node_put(src_node);
 			return rc;
 		}
@@ -50,13 +49,12 @@
 
 	src_node = of_parse_phandle(of_node, "ois-src", 0);
 	if (!src_node) {
-		CDBG("%s:%d src_node NULL\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, "src_node NULL");
 	} else {
 		rc = of_property_read_u32(src_node, "cell-index", &val);
-		CDBG("%s:%d ois cell index %d, rc %d\n", __func__, __LINE__,
-			val, rc);
+		CAM_DBG(CAM_SENSOR, " ois cell index %d, rc %d", val, rc);
 		if (rc < 0) {
-			pr_err("%s:%d failed %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "failed %d",  rc);
 			of_node_put(src_node);
 			return rc;
 		}
@@ -66,13 +64,12 @@
 
 	src_node = of_parse_phandle(of_node, "eeprom-src", 0);
 	if (!src_node) {
-		CDBG("%s:%d eeprom src_node NULL\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, "eeprom src_node NULL");
 	} else {
 		rc = of_property_read_u32(src_node, "cell-index", &val);
-		CDBG("%s:%d eeprom cell index %d, rc %d\n", __func__, __LINE__,
-			val, rc);
+		CAM_DBG(CAM_SENSOR, "eeprom cell index %d, rc %d", val, rc);
 		if (rc < 0) {
-			pr_err("%s:%d failed %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "failed %d", rc);
 			of_node_put(src_node);
 			return rc;
 		}
@@ -82,13 +79,12 @@
 
 	src_node = of_parse_phandle(of_node, "led-flash-src", 0);
 	if (!src_node) {
-		CDBG("%s:%d src_node NULL\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, " src_node NULL");
 	} else {
 		rc = of_property_read_u32(src_node, "cell-index", &val);
-		CDBG("%s:%d led flash cell index %d, rc %d\n", __func__,
-			__LINE__, val, rc);
+		CAM_DBG(CAM_SENSOR, "led flash cell index %d, rc %d", val, rc);
 		if (rc < 0) {
-			pr_err("%s:%d failed %d\n", __func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "failed %d", rc);
 			of_node_put(src_node);
 			return rc;
 		}
@@ -98,8 +94,7 @@
 
 	rc = of_property_read_u32(of_node, "csiphy-sd-index", &val);
 	if (rc < 0)
-		pr_err("%s:%d :Error: paring the dt node for csiphy rc %d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "paring the dt node for csiphy rc %d", rc);
 	else
 		sensor_info->subdev_id[SUB_MODULE_CSIPHY] = val;
 
@@ -120,15 +115,14 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("%s:%d Failed to read DT properties rc %d",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "Failed to read DT properties rc %d", rc);
 		goto FREE_SENSOR_DATA;
 	}
 
 	rc =  cam_sensor_util_init_gpio_pin_tbl(soc_info,
 			&sensordata->power_info.gpio_num_info);
 	if (rc < 0) {
-		pr_err("%s:%d Failed to read gpios %d", __func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "Failed to read gpios %d", rc);
 		goto FREE_SENSOR_DATA;
 	}
 
@@ -136,8 +130,7 @@
 
 	/* Validate cell_id */
 	if (s_ctrl->id >= MAX_CAMERAS) {
-		pr_err("%s:%d Failed invalid cell_id %d", __func__, __LINE__,
-			s_ctrl->id);
+		CAM_ERR(CAM_SENSOR, "Failed invalid cell_id %d", s_ctrl->id);
 		rc = -EINVAL;
 		goto FREE_SENSOR_DATA;
 	}
@@ -145,16 +138,15 @@
 	/* Read subdev info */
 	rc = cam_sensor_get_sub_module_index(of_node, sensordata);
 	if (rc < 0) {
-		pr_err("%s:%d failed to get sub module index, rc=%d\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "failed to get sub module index, rc=%d",
+			 rc);
 		goto FREE_SENSOR_DATA;
 	}
 
 	/* Get CCI master */
 	rc = of_property_read_u32(of_node, "cci-master",
 		&s_ctrl->cci_i2c_master);
-	CDBG("%s:%d cci-master %d, rc %d", __func__, __LINE__,
-		s_ctrl->cci_i2c_master, rc);
+	CAM_DBG(CAM_SENSOR, "cci-master %d, rc %d", s_ctrl->cci_i2c_master, rc);
 	if (rc < 0) {
 		/* Set default master 0 */
 		s_ctrl->cci_i2c_master = MASTER_0;
@@ -163,17 +155,17 @@
 
 	if (of_property_read_u32(of_node, "sensor-position-pitch",
 		&sensordata->pos_pitch) < 0) {
-		CDBG("%s:%d Invalid sensor position\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, "Invalid sensor position");
 		sensordata->pos_pitch = 360;
 	}
 	if (of_property_read_u32(of_node, "sensor-position-roll",
 		&sensordata->pos_roll) < 0) {
-		CDBG("%s:%d Invalid sensor position\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, "Invalid sensor position");
 		sensordata->pos_roll = 360;
 	}
 	if (of_property_read_u32(of_node, "sensor-position-yaw",
 		&sensordata->pos_yaw) < 0) {
-		CDBG("%s:%d Invalid sensor position\n", __func__, __LINE__);
+		CAM_DBG(CAM_SENSOR, "Invalid sensor position");
 		sensordata->pos_yaw = 360;
 	}
 
@@ -188,13 +180,13 @@
 {
 	/* Validate input parameters */
 	if (!s_ctrl) {
-		pr_err("%s:%d failed: invalid params s_ctrl %pK\n", __func__,
-			__LINE__, s_ctrl);
+		CAM_ERR(CAM_SENSOR, "failed: invalid params s_ctrl %pK",
+			s_ctrl);
 		return -EINVAL;
 	}
 
-	CDBG("%s: %d master_type: %d\n", __func__, __LINE__,
-		s_ctrl->io_master_info.master_type);
+	CAM_DBG(CAM_SENSOR,
+		"master_type: %d", s_ctrl->io_master_info.master_type);
 	/* Initialize cci_client */
 	if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
 		s_ctrl->io_master_info.cci_client = kzalloc(sizeof(
@@ -203,8 +195,8 @@
 			return -ENOMEM;
 
 	} else {
-		pr_err("%s:%d Invalid master / Master type Not supported\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR,
+			"Invalid master / Master type Not supported");
 		return -EINVAL;
 	}
 
@@ -219,30 +211,28 @@
 	/* Parse dt information and store in sensor control structure */
 	rc = cam_sensor_driver_get_dt_data(s_ctrl);
 	if (rc < 0) {
-		pr_err("%s:%d Failed to get dt data rc %d", __func__, __LINE__,
-			rc);
+		CAM_ERR(CAM_SENSOR, "Failed to get dt data rc %d", rc);
 		return rc;
 	}
 
 	/* Initialize mutex */
 	mutex_init(&(s_ctrl->cam_sensor_mutex));
 
-	CDBG("%s: %d\n", __func__, __LINE__);
 	/* Initialize default parameters */
 	for (i = 0; i < soc_info->num_clk; i++) {
 		soc_info->clk[i] = devm_clk_get(&soc_info->pdev->dev,
 					soc_info->clk_name[i]);
 		if (!soc_info->clk[i]) {
-			pr_err("%s:%d get failed for %s\n",
-				__func__, __LINE__, soc_info->clk_name[i]);
+			CAM_ERR(CAM_SENSOR, "get failed for %s",
+				 soc_info->clk_name[i]);
 			rc = -ENOENT;
 			return rc;
 		}
 	}
 	rc = msm_sensor_init_default_params(s_ctrl);
 	if (rc < 0) {
-		pr_err("%s;%d failed: msm_sensor_init_default_params rc %d",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR,
+			"failed: msm_sensor_init_default_params rc %d", rc);
 		goto FREE_DT_DATA;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile
index 4c3b8e8..6a0a0e1 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile
@@ -6,4 +6,4 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o cam_sensor_spi.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
index 40a69ef..ca648f01 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
@@ -14,9 +14,6 @@
 #include "cam_sensor_i2c.h"
 #include "cam_cci_dev.h"
 
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-
 int32_t cam_cci_i2c_read(struct cam_sensor_cci_client *cci_client,
 	uint32_t addr, uint32_t *data,
 	enum camera_sensor_i2c_type addr_type,
@@ -41,9 +38,10 @@
 	rc = v4l2_subdev_call(cci_client->cci_subdev,
 		core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
 	if (rc < 0) {
-		pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "line %d rc = %d", rc);
 		return rc;
 	}
+
 	rc = cci_ctrl.status;
 	if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE)
 		*data = buf[0];
@@ -58,6 +56,46 @@
 	return rc;
 }
 
+int32_t cam_camera_cci_i2c_read_seq(struct cam_sensor_cci_client *cci_client,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type,
+	uint32_t num_byte)
+{
+	int32_t                    rc = -EFAULT;
+	unsigned char             *buf = NULL;
+	int                        i = 0;
+	struct cam_cci_ctrl        cci_ctrl;
+
+	if ((addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX)
+		|| (num_byte > I2C_REG_DATA_MAX)) {
+		CAM_ERR(CAM_SENSOR, "addr_type %d num_byte %d", addr_type,
+			num_byte);
+		return rc;
+	}
+
+	buf = kzalloc(num_byte, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	cci_ctrl.cmd = MSM_CCI_I2C_READ;
+	cci_ctrl.cci_info = cci_client;
+	cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
+	cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = addr_type;
+	cci_ctrl.cfg.cci_i2c_read_cfg.data = buf;
+	cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = num_byte;
+	cci_ctrl.status = -EFAULT;
+	rc = v4l2_subdev_call(cci_client->cci_subdev,
+		core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
+	rc = cci_ctrl.status;
+	CAM_DBG(CAM_SENSOR, "addr = 0x%x, rc = %d", addr, rc);
+	for (i = 0; i < num_byte; i++) {
+		data[i] = buf[i];
+		CAM_DBG(CAM_SENSOR, "Byte %d: Data: 0x%x\n", i, data[i]);
+	}
+	kfree(buf);
+	return rc;
+}
+
 static int32_t cam_cci_i2c_write_table_cmd(
 	struct camera_io_master *client,
 	struct cam_sensor_i2c_reg_setting *write_setting,
@@ -85,7 +123,7 @@
 	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
 		core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
 	if (rc < 0) {
-		pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "Failed rc = %d", rc);
 		return rc;
 	}
 	rc = cci_ctrl.status;
@@ -135,12 +173,12 @@
 	int32_t rc = -EINVAL;
 	int32_t i = 0;
 
-	CDBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
-		__func__, addr, data, data_type);
+	CAM_DBG(CAM_SENSOR, "addr: 0x%x data: 0x%x dt: %d",
+		addr, data, data_type);
 
 	if (delay_ms > MAX_POLL_DELAY_MS) {
-		pr_err("%s:%d invalid delay = %d max_delay = %d\n",
-			__func__, __LINE__, delay_ms, MAX_POLL_DELAY_MS);
+		CAM_ERR(CAM_SENSOR, "invalid delay = %d max_delay = %d",
+			delay_ms, MAX_POLL_DELAY_MS);
 		return -EINVAL;
 	}
 	for (i = 0; i < delay_ms; i++) {
@@ -154,11 +192,10 @@
 
 	/* If rc is 1 then read is successful but poll is failure */
 	if (rc == 1)
-		pr_err("%s:%d poll failed rc=%d(non-fatal)\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "poll failed rc=%d(non-fatal)",	rc);
 
 	if (rc < 0)
-		pr_err("%s:%d poll failed rc=%d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "poll failed rc=%d", rc);
 
 	return rc;
 }
@@ -169,13 +206,12 @@
 	int32_t rc = 0;
 	struct cam_cci_ctrl cci_ctrl;
 
-	CDBG("%s line %d\n", __func__, __LINE__);
 	cci_ctrl.cmd = cci_cmd;
 	cci_ctrl.cci_info = cci_client;
 	rc = v4l2_subdev_call(cci_client->cci_subdev,
 		core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
 	if (rc < 0) {
-		pr_err("%s line %d rc = %d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "Failed rc = %d", rc);
 		return rc;
 	}
 	return cci_ctrl.status;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h
index 06e8104..6207a8a 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h
@@ -26,6 +26,8 @@
 #define I2C_COMPARE_MATCH 0
 #define I2C_COMPARE_MISMATCH 1
 
+#define I2C_REG_DATA_MAX       (8*1024)
+
 /**
  * @client: CCI client structure
  * @data: I2C data
@@ -41,6 +43,20 @@
 
 /**
  * @client: CCI client structure
+ * @addr: I2c address
+ * @data: I2C data
+ * @addr_type: I2c address type
+ * @num_byte: number of bytes
+ *
+ * This API handles CCI sequential read
+ */
+int32_t cam_camera_cci_i2c_read_seq(struct cam_sensor_cci_client *client,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type,
+	uint32_t num_byte);
+
+/**
+ * @client: CCI client structure
  * @cci_cmd: CCI command type
  *
  * This API handles CCI random write
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
index 3e1b331..154f4ad 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
@@ -22,7 +22,7 @@
 	int16_t mask = data_mask & 0xFF;
 
 	if (!io_master_info) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -34,8 +34,8 @@
 			addr, data, data_mask, addr_type, data_type,
 			delay_ms);
 	} else {
-		pr_err("%s:%d Invalid Comm. Master:%d\n", __func__,
-			__LINE__, io_master_info->master_type);
+		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+			io_master_info->master_type);
 		return -EINVAL;
 	}
 }
@@ -46,7 +46,7 @@
 	enum camera_sensor_i2c_type data_type)
 {
 	if (!io_master_info) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -56,18 +56,44 @@
 	} else if (io_master_info->master_type == I2C_MASTER) {
 		return cam_qup_i2c_read(io_master_info->client,
 			addr, data, addr_type, data_type);
+	} else if (io_master_info->master_type == SPI_MASTER) {
+		return cam_spi_read(io_master_info,
+			addr, data, addr_type);
 	} else {
-		pr_err("%s:%d Invalid Comm. Master:%d\n", __func__,
-			__LINE__, io_master_info->master_type);
+		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+			io_master_info->master_type);
 		return -EINVAL;
 	}
+	return 0;
+}
+
+int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type, int32_t num_bytes)
+{
+	if (io_master_info->master_type == CCI_MASTER) {
+		return cam_camera_cci_i2c_read_seq(io_master_info->cci_client,
+			addr, data, addr_type, num_bytes);
+	} else if (io_master_info->master_type == I2C_MASTER) {
+		return cam_qup_i2c_read_seq(io_master_info->client,
+			addr, data, addr_type, num_bytes);
+	} else if (io_master_info->master_type == SPI_MASTER) {
+		return cam_spi_read(io_master_info,
+			addr, (uint32_t *)data, addr_type);
+	} else {
+		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+			io_master_info->master_type);
+		return -EINVAL;
+	}
+	return 0;
 }
 
 int32_t camera_io_dev_write(struct camera_io_master *io_master_info,
 	struct cam_sensor_i2c_reg_setting *write_setting)
 {
 	if (!write_setting || !io_master_info) {
-		pr_err("Input parameters not valid ws: %pK ioinfo: %pK",
+		CAM_ERR(CAM_SENSOR,
+			"Input parameters not valid ws: %pK ioinfo: %pK",
 			write_setting, io_master_info);
 		return -EINVAL;
 	}
@@ -79,8 +105,8 @@
 		return cam_qup_i2c_write_table(io_master_info,
 			write_setting);
 	} else {
-		pr_err("%s:%d Invalid Comm. Master:%d\n", __func__,
-			__LINE__, io_master_info->master_type);
+		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+			io_master_info->master_type);
 		return -EINVAL;
 	}
 }
@@ -88,7 +114,7 @@
 int32_t camera_io_init(struct camera_io_master *io_master_info)
 {
 	if (!io_master_info) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -98,8 +124,8 @@
 		return cam_sensor_cci_i2c_util(io_master_info->cci_client,
 			MSM_CCI_INIT);
 	} else {
-		pr_err("%s:%d Invalid Comm. Master:%d\n", __func__,
-			__LINE__, io_master_info->master_type);
+		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+			io_master_info->master_type);
 		return -EINVAL;
 	}
 }
@@ -107,7 +133,7 @@
 int32_t camera_io_release(struct camera_io_master *io_master_info)
 {
 	if (!io_master_info) {
-		pr_err("%s:%d Invalid Args\n", __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid Args");
 		return -EINVAL;
 	}
 
@@ -115,8 +141,8 @@
 		return cam_sensor_cci_i2c_util(io_master_info->cci_client,
 			MSM_CCI_RELEASE);
 	} else {
-		pr_err("%s:%d Invalid Comm. Master:%d\n", __func__,
-			__LINE__, io_master_info->master_type);
+		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+			io_master_info->master_type);
 		return -EINVAL;
 	}
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.h
index f721afd..9a60fd0e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.h
@@ -52,16 +52,15 @@
  * @io_master_info: I2C/SPI master information
  * @addr: I2C address
  * @data: I2C data
- * @addr_type: I2C addr type
+ * @data_type: I2C data type
  * @num_bytes: number of bytes
  *
- * This API abstracts sequential read functionality based on master type
+ * This API abstracts read functionality based on master type
  */
 int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
 	uint32_t addr, uint8_t *data,
 	enum camera_sensor_i2c_type addr_type,
-	uint32_t num_bytes);
-
+	int32_t num_bytes);
 
 /**
  * @io_master_info: I2C/SPI master information
@@ -103,4 +102,6 @@
 	enum camera_sensor_i2c_type addr_type,
 	uint32_t delay_ms);
 
+#include "cam_sensor_i2c.h"
+#include "cam_sensor_spi.h"
 #endif /* _CAM_SENSOR_IO_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c
index b25b1855..72e51ee 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c
@@ -40,7 +40,7 @@
 	};
 	rc = i2c_transfer(dev_client->adapter, msgs, 2);
 	if (rc < 0)
-		pr_err("%s:failed 0x%x\n", __func__, saddr);
+		CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr);
 	return rc;
 }
 
@@ -61,7 +61,7 @@
 	};
 	rc = i2c_transfer(dev_client->client->adapter, msg, 1);
 	if (rc < 0)
-		pr_err("%s: failed 0x%x\n", __func__, saddr);
+		CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr);
 	return rc;
 }
 
@@ -77,8 +77,7 @@
 		|| addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX
 		|| data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
 		|| data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
-		pr_err("ERR: %s Failed with addr/data_type verfication\n",
-			__func__);
+		CAM_ERR(CAM_SENSOR, "Failed with addr/data_type verfication");
 		return rc;
 	}
 
@@ -105,7 +104,7 @@
 
 	rc = cam_qup_i2c_rxdata(client, buf, addr_type, data_type);
 	if (rc < 0) {
-		pr_err("%s fail\n", __func__);
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
 		goto read_fail;
 	}
 
@@ -119,7 +118,7 @@
 		*data = buf[0] << 24 | buf[1] << 16 |
 			buf[2] << 8 | buf[3];
 
-	CDBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data);
+	CAM_DBG(CAM_SENSOR, "addr = 0x%x data: 0x%x", addr, *data);
 read_fail:
 	kfree(buf);
 	buf = NULL;
@@ -137,14 +136,13 @@
 
 	if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
 		|| addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
-		pr_err("ERR: %s Failed with addr_type verification\n",
-			__func__);
+		CAM_ERR(CAM_SENSOR, "Failed with addr_type verification");
 		return rc;
 	}
 
 	if ((num_byte == 0) || (num_byte > I2C_REG_DATA_MAX)) {
-		pr_err("%s: Error num_byte:0x%x max supported:0x%x\n",
-			__func__, num_byte, I2C_REG_DATA_MAX);
+		CAM_ERR(CAM_SENSOR, "num_byte:0x%x max supported:0x%x",
+			num_byte, I2C_REG_DATA_MAX);
 		return rc;
 	}
 
@@ -170,7 +168,7 @@
 
 	rc = cam_qup_i2c_rxdata(client, buf, addr_type, num_byte);
 	if (rc < 0) {
-		pr_err("%s fail\n", __func__);
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
 		goto read_seq_fail;
 	}
 
@@ -213,8 +211,8 @@
 	int i = 0;
 
 	if ((delay_ms > MAX_POLL_DELAY_MS) || (delay_ms == 0)) {
-		pr_err("%s:%d invalid delay = %d max_delay = %d\n",
-			__func__, __LINE__, delay_ms, MAX_POLL_DELAY_MS);
+		CAM_ERR(CAM_SENSOR, "invalid delay = %d max_delay = %d",
+			delay_ms, MAX_POLL_DELAY_MS);
 		return -EINVAL;
 	}
 
@@ -234,10 +232,9 @@
 	}
 	/* If rc is MISMATCH then read is successful but poll is failure */
 	if (rc == I2C_COMPARE_MISMATCH)
-		pr_err("%s:%d poll failed rc=%d(non-fatal)\n",
-			__func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "poll failed rc=%d(non-fatal)", rc);
 	if (rc < 0)
-		pr_err("%s:%d poll failed rc=%d\n", __func__, __LINE__, rc);
+		CAM_ERR(CAM_SENSOR, "poll failed rc=%d", rc);
 
 	return rc;
 }
@@ -251,20 +248,17 @@
 	unsigned char buf[I2C_REG_MAX_BUF_SIZE];
 	uint8_t len = 0;
 
-	CDBG("%s reg addr = 0x%x data type: %d\n",
-			  __func__, reg_setting->reg_addr, data_type);
+	CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d",
+			reg_setting->reg_addr, data_type);
 	if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
 		buf[0] = reg_setting->reg_addr;
-		CDBG("%s byte %d: 0x%x\n", __func__,
-			len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
 		len = 1;
 	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
 		buf[0] = reg_setting->reg_addr >> 8;
 		buf[1] = reg_setting->reg_addr;
-		CDBG("%s byte %d: 0x%x\n", __func__,
-			len, buf[len]);
-		CDBG("%s byte %d: 0x%x\n", __func__,
-			len+1, buf[len+1]);
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]);
 		len = 2;
 	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
 		buf[0] = reg_setting->reg_addr >> 16;
@@ -278,47 +272,47 @@
 		buf[3] = reg_setting->reg_addr;
 		len = 4;
 	} else {
-		pr_err("%s: Invalid I2C addr type\n", __func__);
+		CAM_ERR(CAM_SENSOR, "Invalid I2C addr type");
 		return -EINVAL;
 	}
 
-	CDBG("Data: 0x%x\n", reg_setting->reg_data);
+	CAM_DBG(CAM_SENSOR, "Data: 0x%x", reg_setting->reg_data);
 	if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
 		buf[len] = reg_setting->reg_data;
-		CDBG("Byte %d: 0x%x\n", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
 		len += 1;
 	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
 		buf[len] = reg_setting->reg_data >> 8;
 		buf[len+1] = reg_setting->reg_data;
-		CDBG("Byte %d: 0x%x\n", len, buf[len]);
-		CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]);
 		len += 2;
 	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) {
 		buf[len] = reg_setting->reg_data >> 16;
 		buf[len + 1] = reg_setting->reg_data >> 8;
 		buf[len + 2] = reg_setting->reg_data;
-		CDBG("Byte %d: 0x%x\n", len, buf[len]);
-		CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]);
-		CDBG("Byte %d: 0x%x\n", len+2, buf[len+2]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]);
 		len += 3;
 	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
 		buf[len] = reg_setting->reg_data >> 24;
 		buf[len + 1] = reg_setting->reg_data >> 16;
 		buf[len + 2] = reg_setting->reg_data >> 8;
 		buf[len + 3] = reg_setting->reg_data;
-		CDBG("Byte %d: 0x%x\n", len, buf[len]);
-		CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]);
-		CDBG("Byte %d: 0x%x\n", len+2, buf[len+2]);
-		CDBG("Byte %d: 0x%x\n", len+3, buf[len+3]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+3, buf[len+3]);
 		len += 4;
 	} else {
-		pr_err("%s: Invalid Data Type\n", __func__);
+		CAM_ERR(CAM_SENSOR, "Invalid Data Type");
 		return -EINVAL;
 	}
 
 	rc = cam_qup_i2c_txdata(client, buf, len);
 	if (rc < 0)
-		pr_err("%s fail\n", __func__);
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
 	return rc;
 }
 
@@ -341,7 +335,7 @@
 	reg_setting = write_setting->reg_setting;
 
 	for (i = 0; i < write_setting->size; i++) {
-		CDBG("%s addr 0x%x data 0x%x\n", __func__,
+		CAM_DBG(CAM_SENSOR, "addr 0x%x data 0x%x",
 			reg_setting->reg_addr, reg_setting->reg_data);
 
 		rc = cam_qup_i2c_write(client, reg_setting,
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c
new file mode 100644
index 0000000..4011aa0
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c
@@ -0,0 +1,469 @@
+/* Copyright (c) 2017, 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 "cam_sensor_spi.h"
+#include "cam_debug_util.h"
+
+static int cam_spi_txfr(struct spi_device *spi, char *txbuf,
+	char *rxbuf, int num_byte)
+{
+	struct spi_transfer txfr;
+	struct spi_message msg;
+
+	memset(&txfr, 0, sizeof(txfr));
+	txfr.tx_buf = txbuf;
+	txfr.rx_buf = rxbuf;
+	txfr.len = num_byte;
+	spi_message_init(&msg);
+	spi_message_add_tail(&txfr, &msg);
+
+	return spi_sync(spi, &msg);
+}
+
+static int cam_spi_txfr_read(struct spi_device *spi, char *txbuf,
+	char *rxbuf, int txlen, int rxlen)
+{
+	struct spi_transfer tx;
+	struct spi_transfer rx;
+	struct spi_message m;
+
+	memset(&tx, 0, sizeof(tx));
+	memset(&rx, 0, sizeof(rx));
+	tx.tx_buf = txbuf;
+	rx.rx_buf = rxbuf;
+	tx.len = txlen;
+	rx.len = rxlen;
+	spi_message_init(&m);
+	spi_message_add_tail(&tx, &m);
+	spi_message_add_tail(&rx, &m);
+	return spi_sync(spi, &m);
+}
+
+/**
+ * cam_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 cam_set_addr(uint32_t addr, uint8_t addr_len,
+	enum camera_sensor_i2c_type type,
+	char *str)
+{
+	int i, len;
+
+	if (!addr_len)
+		return;
+
+	if (addr_len < type)
+		CAM_DBG(CAM_EEPROM, "omitting higher bits in address");
+
+	/* 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;
+	}
+
+}
+
+/**
+ * cam_spi_tx_helper() - wrapper for SPI transaction
+ * @client:     io client
+ * @inst:       inst of this transaction
+ * @addr:       device addr following the inst
+ * @data:       output byte array (could be NULL)
+ * @num_byte:   size of @data
+ * @tx, rx:     optional transfer buffer.  It must be at least header
+ *              + @num_byte long.
+ *
+ * This is the core function for SPI transaction, except for writes.  It first
+ * checks address type, then allocates required memory for tx/rx buffers.
+ * It sends out <opcode><addr>, and optionally receives @num_byte of response,
+ * if @data is not NULL.  This function does not check for wait conditions,
+ * and will return immediately once bus transaction finishes.
+ *
+ * This function will allocate buffers of header + @num_byte long.  For
+ * large transfers, the allocation could fail.  External buffer @tx, @rx
+ * should be passed in to bypass allocation.  The size of buffer should be
+ * at least header + num_byte long.  Since buffer is managed externally,
+ * @data will be ignored, and read results will be in @rx.
+ * @tx, @rx also can be used for repeated transfers to improve performance.
+ */
+static int32_t cam_spi_tx_helper(struct camera_io_master *client,
+	struct cam_camera_spi_inst *inst, uint32_t addr, uint8_t *data,
+	uint32_t num_byte, char *tx, char *rx)
+{
+	int32_t rc = -EINVAL;
+	struct spi_device *spi = client->spi_client->spi_master;
+	char *ctx = NULL, *crx = NULL;
+	uint32_t len, hlen;
+	uint8_t retries = client->spi_client->retries;
+	enum camera_sensor_i2c_type addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
+
+	if (addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX)
+		return rc;
+
+	hlen = cam_camera_spi_get_hlen(inst);
+	len = hlen + num_byte;
+
+	if (tx) {
+		ctx = tx;
+	} else {
+		ctx = kzalloc(len, GFP_KERNEL | GFP_DMA);
+		if (!ctx)
+			return -ENOMEM;
+	}
+
+	if (num_byte) {
+		if (rx) {
+			crx = rx;
+		} else {
+			crx = kzalloc(len, GFP_KERNEL | GFP_DMA);
+			if (!crx) {
+				if (!tx)
+					kfree(ctx);
+				return -ENOMEM;
+			}
+		}
+	} else {
+		crx = NULL;
+	}
+
+	ctx[0] = inst->opcode;
+	cam_set_addr(addr, inst->addr_len, addr_type, ctx + 1);
+	while ((rc = cam_spi_txfr(spi, ctx, crx, len)) && retries) {
+		retries--;
+		msleep(client->spi_client->retry_delay);
+	}
+	if (rc < 0) {
+		CAM_ERR(CAM_EEPROM, "failed: spi txfr rc %d", rc);
+		goto out;
+	}
+	if (data && num_byte && !rx)
+		memcpy(data, crx + hlen, num_byte);
+
+out:
+	if (!tx)
+		kfree(ctx);
+	if (!rx)
+		kfree(crx);
+	return rc;
+}
+
+static int32_t cam_spi_tx_read(struct camera_io_master *client,
+	struct cam_camera_spi_inst *inst, uint32_t addr, uint8_t *data,
+	uint32_t num_byte, char *tx, char *rx)
+{
+	int32_t rc = -EINVAL;
+	struct spi_device *spi = client->spi_client->spi_master;
+	char *ctx = NULL, *crx = NULL;
+	uint32_t hlen;
+	uint8_t retries = client->spi_client->retries;
+	enum camera_sensor_i2c_type addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
+
+	if ((addr_type != CAMERA_SENSOR_I2C_TYPE_WORD)
+		&& (addr_type != CAMERA_SENSOR_I2C_TYPE_BYTE)
+		&& (addr_type != CAMERA_SENSOR_I2C_TYPE_3B))
+		return rc;
+
+	hlen = cam_camera_spi_get_hlen(inst);
+	if (tx) {
+		ctx = tx;
+	} else {
+		ctx = kzalloc(hlen, GFP_KERNEL | GFP_DMA);
+		if (!ctx)
+			return -ENOMEM;
+	}
+	if (num_byte) {
+		if (rx) {
+			crx = rx;
+		} else {
+			crx = kzalloc(num_byte, GFP_KERNEL | GFP_DMA);
+			if (!crx) {
+				if (!tx)
+					kfree(ctx);
+				return -ENOMEM;
+			}
+		}
+	} else {
+		crx = NULL;
+	}
+
+	ctx[0] = inst->opcode;
+	if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+		cam_set_addr(addr, inst->addr_len, addr_type,
+			ctx + 1);
+	} else {
+		ctx[1] = (addr >> BITS_PER_BYTE) & 0xFF;
+		ctx[2] = (addr & 0xFF);
+		ctx[3] = 0;
+	}
+	CAM_DBG(CAM_EEPROM, "tx(%u): %02x %02x %02x %02x", hlen, ctx[0],
+		ctx[1], ctx[2],	ctx[3]);
+	while ((rc = cam_spi_txfr_read(spi, ctx, crx, hlen, num_byte))
+			&& retries) {
+		retries--;
+		msleep(client->spi_client->retry_delay);
+	}
+	if (rc < 0) {
+		CAM_ERR(CAM_SENSOR, "failed %d", rc);
+		goto out;
+	}
+	if (data && num_byte && !rx)
+		memcpy(data, crx, num_byte);
+out:
+	if (!tx)
+		kfree(ctx);
+	if (!rx)
+		kfree(crx);
+	return rc;
+}
+
+int cam_spi_read(struct camera_io_master *client,
+	uint32_t addr, uint32_t *data,
+	enum camera_sensor_i2c_type data_type)
+{
+	int rc = -EINVAL;
+	uint8_t temp[CAMERA_SENSOR_I2C_TYPE_MAX];
+
+	if ((data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID)
+		|| (data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))
+		return rc;
+
+	rc = cam_spi_tx_read(client,
+		&client->spi_client->cmd_tbl.read, addr, &temp[0],
+		data_type, NULL, NULL);
+	if (rc < 0) {
+		CAM_ERR(CAM_SENSOR, "failed %d", rc);
+		return rc;
+	}
+
+	if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE)
+		*data = temp[0];
+	else
+		*data = (temp[0] << BITS_PER_BYTE) | temp[1];
+
+	CAM_DBG(CAM_SENSOR, "addr 0x%x, data %u", addr, *data);
+	return rc;
+}
+
+int cam_spi_query_id(struct camera_io_master *client,
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
+{
+	return cam_spi_tx_helper(client,
+		&client->spi_client->cmd_tbl.query_id, addr, data, num_byte,
+		NULL, NULL);
+}
+
+static int32_t cam_spi_read_status_reg(
+	struct camera_io_master *client, uint8_t *status)
+{
+	struct cam_camera_spi_inst *rs =
+		&client->spi_client->cmd_tbl.read_status;
+
+	if (rs->addr_len != 0) {
+		CAM_ERR(CAM_SENSOR, "not implemented yet");
+		return -ENXIO;
+	}
+	return cam_spi_tx_helper(client, rs, 0, status, 1, NULL, NULL);
+}
+
+static int32_t cam_spi_device_busy(struct camera_io_master *client,
+	uint8_t *busy)
+{
+	int rc;
+	uint8_t st = 0;
+
+	rc = cam_spi_read_status_reg(client,  &st);
+	if (rc < 0) {
+		CAM_ERR(CAM_SENSOR, "failed to read status reg");
+		return rc;
+	}
+	*busy = st & client->spi_client->busy_mask;
+	return 0;
+}
+
+static int32_t cam_spi_wait(struct camera_io_master *client,
+	struct cam_camera_spi_inst *inst)
+{
+	uint8_t busy;
+	int i, rc;
+
+	CAM_DBG(CAM_SENSOR, "op 0x%x wait start", inst->opcode);
+	for (i = 0; i < inst->delay_count; i++) {
+		rc = cam_spi_device_busy(client, &busy);
+		if (rc < 0)
+			return rc;
+		if (!busy)
+			break;
+		msleep(inst->delay_intv);
+		CAM_DBG(CAM_SENSOR, "op 0x%x wait", inst->opcode);
+	}
+	if (i > inst->delay_count) {
+		CAM_ERR(CAM_SENSOR, "op %x timed out", inst->opcode);
+		return -ETIMEDOUT;
+	}
+	CAM_DBG(CAM_SENSOR, "op %x finished", inst->opcode);
+	return 0;
+}
+
+static int32_t cam_spi_write_enable(
+	struct camera_io_master *client)
+{
+	struct cam_camera_spi_inst *we =
+		&client->spi_client->cmd_tbl.write_enable;
+	int rc;
+
+	if (we->opcode == 0)
+		return 0;
+	if (we->addr_len != 0) {
+		CAM_ERR(CAM_SENSOR, "not implemented yet");
+		return -EINVAL;
+	}
+	rc = cam_spi_tx_helper(client, we, 0, NULL, 0, NULL, NULL);
+	if (rc < 0)
+		CAM_ERR(CAM_SENSOR, "write enable failed");
+	return rc;
+}
+
+/**
+ * cam_spi_page_program() - core function to perform write
+ * @client: need for obtaining SPI device
+ * @addr: address to program on device
+ * @data: data to write
+ * @len: size of data
+ * @tx: tx buffer, size >= header + len
+ *
+ * This function performs SPI write, and has no boundary check.  Writing range
+ * should not cross page boundary, or data will be corrupted.  Transaction is
+ * guaranteed to be finished when it returns.  This function should never be
+ * used outside cam_spi_write_seq().
+ */
+static int32_t cam_spi_page_program(struct camera_io_master *client,
+	uint32_t addr, uint8_t *data, uint16_t len, uint8_t *tx)
+{
+	int rc;
+	struct cam_camera_spi_inst *pg =
+		&client->spi_client->cmd_tbl.page_program;
+	struct spi_device *spi = client->spi_client->spi_master;
+	uint8_t retries = client->spi_client->retries;
+	uint8_t header_len = sizeof(pg->opcode) + pg->addr_len + pg->dummy_len;
+	enum camera_sensor_i2c_type addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
+
+	CAM_DBG(CAM_SENSOR, "addr 0x%x, size 0x%x", addr, len);
+	rc = cam_spi_write_enable(client);
+	if (rc < 0)
+		return rc;
+	memset(tx, 0, header_len);
+	tx[0] = pg->opcode;
+	cam_set_addr(addr, pg->addr_len, addr_type, tx + 1);
+	memcpy(tx + header_len, data, len);
+	CAM_DBG(CAM_SENSOR, "tx(%u): %02x %02x %02x %02x",
+		len, tx[0], tx[1], tx[2], tx[3]);
+	while ((rc = spi_write(spi, tx, len + header_len)) && retries) {
+		rc = cam_spi_wait(client, pg);
+		msleep(client->spi_client->retry_delay);
+		retries--;
+	}
+	if (rc < 0) {
+		CAM_ERR(CAM_SENSOR, "failed %d", rc);
+		return rc;
+	}
+	rc = cam_spi_wait(client, pg);
+		return rc;
+}
+
+int cam_spi_write(struct camera_io_master *client,
+	uint32_t addr, uint16_t data,
+	enum camera_sensor_i2c_type data_type)
+{
+	struct cam_camera_spi_inst *pg =
+		&client->spi_client->cmd_tbl.page_program;
+	uint8_t header_len = sizeof(pg->opcode) + pg->addr_len + pg->dummy_len;
+	uint16_t len = 0;
+	char buf[2];
+	char *tx;
+	int rc = -EINVAL;
+	enum camera_sensor_i2c_type addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
+
+	if ((addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX)
+		|| (data_type != CAMERA_SENSOR_I2C_TYPE_BYTE
+		&& data_type != CAMERA_SENSOR_I2C_TYPE_WORD))
+		return rc;
+	CAM_DBG(CAM_EEPROM, "Data: 0x%x", data);
+	len = header_len + (uint8_t)data_type;
+	tx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+	if (!tx)
+		goto NOMEM;
+	if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
+		buf[0] = data;
+		CAM_DBG(CAM_EEPROM, "Byte %d: 0x%x", len, buf[0]);
+	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+		buf[0] = (data >> BITS_PER_BYTE) & 0x00FF;
+		buf[1] = (data & 0x00FF);
+	}
+	rc = cam_spi_page_program(client, addr, buf,
+		(uint16_t)data_type, tx);
+	if (rc < 0)
+		goto ERROR;
+	goto OUT;
+NOMEM:
+	CAM_ERR(CAM_SENSOR, "memory allocation failed");
+	return -ENOMEM;
+ERROR:
+	CAM_ERR(CAM_SENSOR, "error write");
+OUT:
+	kfree(tx);
+	return rc;
+}
+
+int cam_spi_write_table(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting)
+{
+	int i;
+	int rc = -EFAULT;
+	struct cam_sensor_i2c_reg_array *reg_setting;
+	uint16_t client_addr_type;
+	enum camera_sensor_i2c_type addr_type;
+
+	if (!client || !write_setting)
+		return rc;
+	if (write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX
+		|| (write_setting->data_type != CAMERA_SENSOR_I2C_TYPE_BYTE
+		&& write_setting->data_type != CAMERA_SENSOR_I2C_TYPE_WORD))
+		return rc;
+	reg_setting = write_setting->reg_setting;
+	client_addr_type = addr_type;
+	addr_type = write_setting->addr_type;
+	for (i = 0; i < write_setting->size; i++) {
+		CAM_DBG(CAM_SENSOR, "addr %x data %x",
+			reg_setting->reg_addr, reg_setting->reg_data);
+		rc = cam_spi_write(client, reg_setting->reg_addr,
+			reg_setting->reg_data, write_setting->data_type);
+		if (rc < 0)
+			break;
+		reg_setting++;
+	}
+		if (write_setting->delay > 20)
+			msleep(write_setting->delay);
+		else if (write_setting->delay)
+			usleep_range(write_setting->delay * 1000,
+			(write_setting->delay
+			* 1000) + 1000);
+	addr_type = client_addr_type;
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h
new file mode 100644
index 0000000..a497491
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h
@@ -0,0 +1,93 @@
+/* Copyright (c) 2017, 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 _CAM_SENSOR_SPI_H_
+#define _CAM_SENSOR_SPI_H_
+
+#include <linux/spi/spi.h>
+#include <media/cam_sensor.h>
+#include "cam_sensor_i2c.h"
+
+#define MAX_SPI_SIZE 110
+#define SPI_DYNAMIC_ALLOC
+
+struct cam_camera_spi_inst {
+	uint8_t opcode;
+	uint8_t addr_len;
+	uint8_t dummy_len;
+	uint8_t delay_intv;
+	uint8_t delay_count;
+};
+
+struct cam_spi_write_burst_data {
+	u8 data_msb;
+	u8 data_lsb;
+};
+
+struct cam_spi_write_burst_packet {
+	u8 cmd;
+	u8 addr_msb;
+	u8 addr_lsb;
+	struct cam_spi_write_burst_data data_arr[MAX_SPI_SIZE];
+};
+
+struct cam_camera_burst_info {
+	uint32_t burst_addr;
+	uint32_t burst_start;
+	uint32_t burst_len;
+	uint32_t chunk_size;
+};
+
+struct cam_camera_spi_inst_tbl {
+	struct cam_camera_spi_inst read;
+	struct cam_camera_spi_inst read_seq;
+	struct cam_camera_spi_inst query_id;
+	struct cam_camera_spi_inst page_program;
+	struct cam_camera_spi_inst write_enable;
+	struct cam_camera_spi_inst read_status;
+	struct cam_camera_spi_inst erase;
+};
+
+struct cam_sensor_spi_client {
+	struct spi_device *spi_master;
+	struct cam_camera_spi_inst_tbl cmd_tbl;
+	uint8_t device_id0;
+	uint8_t device_id1;
+	uint8_t mfr_id0;
+	uint8_t mfr_id1;
+	uint8_t retry_delay;
+	uint8_t retries;
+	uint8_t busy_mask;
+	uint16_t page_size;
+	uint32_t erase_size;
+};
+static __always_inline
+uint16_t cam_camera_spi_get_hlen(struct cam_camera_spi_inst *inst)
+{
+	return sizeof(inst->opcode) + inst->addr_len + inst->dummy_len;
+}
+
+int cam_spi_read(struct camera_io_master *client,
+	uint32_t addr, uint32_t *data,
+	enum camera_sensor_i2c_type data_type);
+
+int cam_spi_query_id(struct camera_io_master *client,
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
+
+int cam_spi_write(struct camera_io_master *client,
+	uint32_t addr, uint16_t data,
+	enum camera_sensor_i2c_type data_type);
+
+int cam_spi_write_table(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting);
+
+#endif
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index d12ff2b..6520042b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -31,6 +31,8 @@
 #define CAM_SENSOR_NAME    "cam-sensor"
 #define CAM_ACTUATOR_NAME  "cam-actuator"
 #define CAM_CSIPHY_NAME    "cam-csiphy"
+#define CAM_FLASH_NAME     "cam-flash"
+#define CAM_EEPROM_NAME    "cam-eeprom"
 
 #define MAX_SYSTEM_PIPELINE_DELAY 2
 
@@ -47,6 +49,11 @@
 	CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR,
 	CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD,
 	CAMERA_SENSOR_CMD_TYPE_WAIT,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_INIT,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_RER,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET,
 	CAMERA_SENSOR_CMD_TYPE_MAX,
 };
 
@@ -69,6 +76,14 @@
 	CAMERA_SENSOR_WAIT_OP_MAX,
 };
 
+enum camera_flash_opcode {
+	CAMERA_SENSOR_FLASH_OP_INVALID,
+	CAMERA_SENSOR_FLASH_OP_OFF,
+	CAMERA_SENSOR_FLASH_OP_FIRELOW,
+	CAMERA_SENSOR_FLASH_OP_FIREHIGH,
+	CAMERA_SENSOR_FLASH_OP_MAX,
+};
+
 enum camera_sensor_i2c_type {
 	CAMERA_SENSOR_I2C_TYPE_INVALID,
 	CAMERA_SENSOR_I2C_TYPE_BYTE,
@@ -146,6 +161,10 @@
 	CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS
 };
 
+enum cam_eeprom_packet_opcodes {
+	CAM_EEPROM_PACKET_OPCODE_INIT
+};
+
 enum msm_bus_perf_setting {
 	S_INIT,
 	S_PREVIEW,
@@ -166,6 +185,12 @@
 	MSM_CAMERA_SPI_DEVICE,
 };
 
+enum cam_flash_device_type {
+	CAMERA_FLASH_DEVICE_TYPE_PMIC = 0,
+	CAMERA_FLASH_DEVICE_TYPE_I2C,
+	CAMERA_FLASH_DEVICE_TYPE_GPIO,
+};
+
 enum cci_i2c_master_t {
 	MASTER_0,
 	MASTER_1,
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 9f16e93..b1698ca 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include "cam_sensor_util.h"
+#include <cam_mem_mgr.h>
 
 #define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend"
 #define CAM_SENSOR_PINCTRL_STATE_DEFAULT "cam_default"
@@ -19,9 +20,6 @@
 #define VALIDATE_VOLTAGE(min, max, config_val) ((config_val) && \
 	(config_val >= min) && (config_val <= max))
 
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-
 static struct i2c_settings_list*
 	cam_sensor_get_i2c_ptr(struct i2c_settings_array *i2c_reg_settings,
 		uint32_t size)
@@ -56,8 +54,7 @@
 	int32_t rc = 0;
 
 	if (i2c_array == NULL) {
-		pr_err("%s:%d ::FATAL:: Invalid argument\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "FATAL:: Invalid argument");
 		return -EINVAL;
 	}
 
@@ -86,8 +83,7 @@
 	struct i2c_settings_list *i2c_list = NULL;
 
 	if (i2c_list == NULL) {
-		pr_err("%s:%d Invalid list ptr\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid list ptr");
 		return -EINVAL;
 	}
 
@@ -109,8 +105,7 @@
 			sizeof(
 			struct cam_cmd_unconditional_wait);
 	} else {
-		pr_err("%s: %d Error: Delay Rxed Before any buffer: %d\n",
-			__func__, __LINE__, offset);
+		CAM_ERR(CAM_SENSOR, "Delay Rxed Before any buffer: %d", offset);
 		return -EINVAL;
 	}
 
@@ -131,8 +126,7 @@
 	i2c_list =
 		cam_sensor_get_i2c_ptr(i2c_reg_settings, 1);
 	if (!i2c_list || !i2c_list->i2c_settings.reg_setting) {
-		pr_err("%s: %d Failed in allocating mem for list\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Failed in allocating mem for list");
 		return -ENOMEM;
 	}
 
@@ -171,8 +165,7 @@
 		cam_cmd_i2c_random_wr->header.count);
 	if (i2c_list == NULL ||
 		i2c_list->i2c_settings.reg_setting == NULL) {
-		pr_err("%s: %d Failed in allocating i2c_list\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Failed in allocating i2c_list");
 		return -ENOMEM;
 	}
 
@@ -234,8 +227,8 @@
 		 * be spread across multiple cmd buffers
 		 */
 
-		CDBG("%s:%d Total cmd Buf in Bytes: %d\n", __func__,
-			__LINE__, cmd_desc[i].length);
+		CAM_DBG(CAM_SENSOR, "Total cmd Buf in Bytes: %d",
+			cmd_desc[i].length);
 
 		if (!cmd_desc[i].length)
 			continue;
@@ -244,10 +237,9 @@
 			(uint64_t *)&generic_ptr, &len_of_buff);
 		cmd_buf = (uint32_t *)generic_ptr;
 		if (rc < 0) {
-			pr_err("%s:%d Failed in getting cmd hdl: %d Err: %d Buffer Len: %ld\n",
-				__func__, __LINE__,
-				cmd_desc[i].mem_handle, rc,
-				len_of_buff);
+			CAM_ERR(CAM_SENSOR,
+				"cmd hdl failed:%d, Err: %d, Buffer_len: %ld",
+				cmd_desc[i].mem_handle, rc, len_of_buff);
 			return rc;
 		}
 		cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
@@ -267,8 +259,8 @@
 					i2c_reg_settings,
 					&cmd_length_in_bytes, &j, &list);
 				if (rc < 0) {
-					pr_err("%s:%d :Error: Failed in random read %d\n",
-						__func__, __LINE__, rc);
+					CAM_ERR(CAM_SENSOR,
+						"Failed in random read %d", rc);
 					return rc;
 				}
 
@@ -288,8 +280,9 @@
 						i2c_reg_settings, j, &byte_cnt,
 						list);
 					if (rc < 0) {
-						pr_err("%s:%d :Error: Failed in handling delay %d\n",
-							__func__, __LINE__, rc);
+						CAM_ERR(CAM_SENSOR,
+							"delay hdl failed: %d",
+							rc);
 						return rc;
 					}
 
@@ -299,21 +292,22 @@
 						&cmd_buf, i2c_reg_settings,
 						&byte_cnt, &j, &list);
 					if (rc < 0) {
-						pr_err("%s:%d :Error: Failed in random read %d\n",
-							__func__, __LINE__, rc);
+						CAM_ERR(CAM_SENSOR,
+							"Random read fail: %d",
+							rc);
 						return rc;
 					}
 				} else {
-					pr_err("%s: %d Wrong Wait Command: %d\n",
-						__func__, __LINE__,
+					CAM_ERR(CAM_SENSOR,
+						"Wrong Wait Command: %d",
 						generic_op_code);
 					return -EINVAL;
 				}
 				break;
 			}
 			default:
-				pr_err("%s:%d Invalid Command Type:%d\n",
-					__func__, __LINE__, cmm_hdr->cmd_type);
+				CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d",
+					 cmm_hdr->cmd_type);
 				return -EINVAL;
 			}
 		}
@@ -333,20 +327,18 @@
 
 	/* Validate input parameters */
 	if (!soc_info || !power_setting) {
-		pr_err("%s:%d failed: soc_info %pK power_setting %pK", __func__,
-			__LINE__,  soc_info, power_setting);
+		CAM_ERR(CAM_SENSOR, "failed: soc_info %pK power_setting %pK",
+			soc_info, power_setting);
 		return -EINVAL;
 	}
 
 	num_vreg = soc_info->num_rgltr;
 
 	if (num_vreg <= 0) {
-		pr_err("%s:%d failed: num_vreg %d", __func__, __LINE__,
-			num_vreg);
+		CAM_ERR(CAM_SENSOR, "failed: num_vreg %d", num_vreg);
 		return -EINVAL;
 	}
 
-
 	for (i = 0; i < power_setting_size; i++) {
 		switch (power_setting[i].seq_type) {
 		case SENSOR_VDIG:
@@ -354,8 +346,8 @@
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_vdig")) {
 
-					CDBG("%s:%d i %d j %d cam_vdig\n",
-						__func__, __LINE__, i, j);
+					CAM_DBG(CAM_SENSOR,
+						"i: %d j: %d cam_vdig", i, j);
 					power_setting[i].seq_val = j;
 
 					if (VALIDATE_VOLTAGE(
@@ -378,8 +370,8 @@
 
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_vio")) {
-					CDBG("%s:%d i %d j %d cam_vio\n",
-						__func__, __LINE__, i, j);
+					CAM_DBG(CAM_SENSOR,
+						"i: %d j: %d cam_vio", i, j);
 					power_setting[i].seq_val = j;
 
 					if (VALIDATE_VOLTAGE(
@@ -403,8 +395,8 @@
 
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_vana")) {
-					CDBG("%s:%d i %d j %d cam_vana\n",
-						__func__, __LINE__, i, j);
+					CAM_DBG(CAM_SENSOR,
+						"i: %d j: %d cam_vana", i, j);
 					power_setting[i].seq_val = j;
 
 					if (VALIDATE_VOLTAGE(
@@ -428,8 +420,8 @@
 
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_vaf")) {
-					CDBG("%s:%d i %d j %d cam_vaf\n",
-						__func__, __LINE__, i, j);
+					CAM_DBG(CAM_SENSOR,
+						"i: %d j: %d cam_vaf", i, j);
 					power_setting[i].seq_val = j;
 
 					if (VALIDATE_VOLTAGE(
@@ -454,8 +446,8 @@
 
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_v_custom1")) {
-					CDBG("%s:%d i %d j %d cam_vcustom1\n",
-						__func__, __LINE__, i, j);
+					CAM_DBG(CAM_SENSOR,
+						"i:%d j:%d cam_vcustom1", i, j);
 					power_setting[i].seq_val = j;
 
 					if (VALIDATE_VOLTAGE(
@@ -478,8 +470,8 @@
 
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_v_custom2")) {
-					CDBG("%s:%d i %d j %d cam_vcustom2\n",
-						__func__, __LINE__, i, j);
+					CAM_DBG(CAM_SENSOR,
+						"i:%d j:%d cam_vcustom2", i, j);
 					power_setting[i].seq_val = j;
 
 					if (VALIDATE_VOLTAGE(
@@ -498,8 +490,8 @@
 			break;
 
 		default: {
-			pr_err("%s:%d invalid seq_val %d\n", __func__,
-				__LINE__, power_setting[i].seq_val);
+			CAM_ERR(CAM_SENSOR, "invalid seq_val %d",
+				power_setting[i].seq_val);
 			break;
 			}
 		}
@@ -520,19 +512,19 @@
 	size = gpio_conf->cam_gpio_req_tbl_size;
 
 	if (gpio_conf->cam_gpio_common_tbl_size <= 0) {
-		pr_info("%s:%d No GPIO entry\n", __func__, __LINE__);
+		CAM_INFO(CAM_SENSOR, "No GPIO entry");
 		return 0;
 	}
 
 	if (!gpio_tbl || !size) {
-		pr_err("%s:%d invalid gpio_tbl %pK / size %d\n", __func__,
-			__LINE__, gpio_tbl, size);
+		CAM_ERR(CAM_SENSOR, "invalid gpio_tbl %pK / size %d",
+			gpio_tbl, size);
 		return -EINVAL;
 	}
 
 	for (i = 0; i < size; i++) {
-		CDBG("%s:%d i %d, gpio %d dir %ld\n", __func__, __LINE__, i,
-				gpio_tbl[i].gpio, gpio_tbl[i].flags);
+		CAM_DBG(CAM_SENSOR, "i: %d, gpio %d dir %ld",  i,
+			gpio_tbl[i].gpio, gpio_tbl[i].flags);
 	}
 
 	if (gpio_en) {
@@ -545,8 +537,7 @@
 				 * apply new gpios, outout a error message
 				 * for driver bringup debug
 				 */
-				pr_err("%s:%d gpio %d:%s request fails\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR, "gpio %d:%s request fails",
 					gpio_tbl[i].gpio, gpio_tbl[i].label);
 			}
 		}
@@ -557,6 +548,308 @@
 	return rc;
 }
 
+int32_t cam_sensor_update_power_settings(void *cmd_buf,
+	int cmd_length, struct cam_sensor_power_ctrl_t *power_info)
+{
+	int32_t rc = 0, tot_size = 0, last_cmd_type = 0;
+	int32_t i = 0, pwr_up = 0, pwr_down = 0;
+	void *ptr = cmd_buf, *scr;
+	struct cam_cmd_power *pwr_cmd = (struct cam_cmd_power *)cmd_buf;
+	struct common_header *cmm_hdr = (struct common_header *)cmd_buf;
+
+	if (!pwr_cmd || !cmd_length) {
+		CAM_ERR(CAM_SENSOR, "Invalid Args: pwr_cmd %pK, cmd_length: %d",
+			pwr_cmd, cmd_length);
+		return -EINVAL;
+	}
+
+	power_info->power_setting_size = 0;
+	power_info->power_setting =
+		(struct cam_sensor_power_setting *)
+		kzalloc(sizeof(struct cam_sensor_power_setting) *
+			MAX_POWER_CONFIG, GFP_KERNEL);
+	if (!power_info->power_setting)
+		return -ENOMEM;
+
+	power_info->power_down_setting_size = 0;
+	power_info->power_down_setting =
+		(struct cam_sensor_power_setting *)
+		kzalloc(sizeof(struct cam_sensor_power_setting) *
+			MAX_POWER_CONFIG, GFP_KERNEL);
+	if (!power_info->power_down_setting) {
+		rc = -ENOMEM;
+		goto free_power_settings;
+	}
+
+	while (tot_size < cmd_length) {
+		if (cmm_hdr->cmd_type ==
+			CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
+			struct cam_cmd_power *pwr_cmd =
+				(struct cam_cmd_power *)ptr;
+
+			power_info->
+				power_setting_size +=
+				pwr_cmd->count;
+			scr = ptr + sizeof(struct cam_cmd_power);
+			tot_size = tot_size + sizeof(struct cam_cmd_power);
+
+			if (pwr_cmd->count == 0)
+				CAM_DBG(CAM_SENSOR, "Un expected Command");
+
+			for (i = 0; i < pwr_cmd->count; i++, pwr_up++) {
+				power_info->
+					power_setting[pwr_up].seq_type =
+					pwr_cmd->power_settings[i].
+						power_seq_type;
+				power_info->
+					power_setting[pwr_up].config_val =
+					pwr_cmd->power_settings[i].
+						config_val_low;
+				power_info->power_setting[pwr_up].delay = 0;
+				if (i) {
+					scr = scr +
+						sizeof(
+						struct cam_power_settings);
+					tot_size = tot_size +
+						sizeof(
+						struct cam_power_settings);
+				}
+				if (tot_size > cmd_length) {
+					CAM_ERR(CAM_SENSOR,
+						"Error: Cmd Buffer is wrong");
+					rc = -EINVAL;
+					goto free_power_down_settings;
+				}
+				CAM_DBG(CAM_SENSOR,
+					"Seq Type[%d]: %d Config_val: %ld",
+					pwr_up,
+					power_info->
+						power_setting[pwr_up].seq_type,
+					power_info->
+						power_setting[pwr_up].
+						config_val);
+			}
+			last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP;
+			ptr = (void *) scr;
+			cmm_hdr = (struct common_header *)ptr;
+		} else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT) {
+			struct cam_cmd_unconditional_wait *wait_cmd =
+				(struct cam_cmd_unconditional_wait *)ptr;
+			if (wait_cmd->op_code ==
+				CAMERA_SENSOR_WAIT_OP_SW_UCND) {
+				if (last_cmd_type ==
+					CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
+					if (pwr_up > 0)
+						power_info->
+							power_setting
+							[pwr_up - 1].delay +=
+							wait_cmd->delay;
+					else
+						CAM_ERR(CAM_SENSOR,
+							"Delay is expected only after valid power up setting");
+				} else if (last_cmd_type ==
+					CAMERA_SENSOR_CMD_TYPE_PWR_DOWN) {
+					if (pwr_down > 0)
+						power_info->
+							power_down_setting
+							[pwr_down - 1].delay +=
+							wait_cmd->delay;
+					else
+						CAM_ERR(CAM_SENSOR,
+							"Delay is expected only after valid power up setting");
+				}
+			} else
+				CAM_DBG(CAM_SENSOR, "Invalid op code: %d",
+					wait_cmd->op_code);
+			tot_size = tot_size +
+				sizeof(struct cam_cmd_unconditional_wait);
+			if (tot_size > cmd_length) {
+				CAM_ERR(CAM_SENSOR, "Command Buffer is wrong");
+				return -EINVAL;
+			}
+			scr = (void *) (wait_cmd);
+			ptr = (void *)
+				(scr +
+				sizeof(struct cam_cmd_unconditional_wait));
+			CAM_DBG(CAM_SENSOR, "ptr: %pK sizeof: %d Next: %pK",
+				scr, (int32_t)sizeof(
+				struct cam_cmd_unconditional_wait), ptr);
+
+			cmm_hdr = (struct common_header *)ptr;
+		} else if (cmm_hdr->cmd_type ==
+			CAMERA_SENSOR_CMD_TYPE_PWR_DOWN) {
+			struct cam_cmd_power *pwr_cmd =
+				(struct cam_cmd_power *)ptr;
+
+			scr = ptr + sizeof(struct cam_cmd_power);
+			tot_size = tot_size + sizeof(struct cam_cmd_power);
+			power_info->power_down_setting_size += pwr_cmd->count;
+
+			if (pwr_cmd->count == 0)
+				CAM_ERR(CAM_SENSOR, "Invalid Command");
+
+			for (i = 0; i < pwr_cmd->count; i++, pwr_down++) {
+				power_info->
+					power_down_setting[pwr_down].
+					seq_type =
+					pwr_cmd->power_settings[i].
+					power_seq_type;
+				power_info->
+					power_down_setting[pwr_down].
+					config_val =
+					pwr_cmd->power_settings[i].
+					config_val_low;
+				power_info->
+					power_down_setting[pwr_down].delay = 0;
+				if (i) {
+					scr = scr +
+						sizeof(
+						struct cam_power_settings);
+					tot_size =
+						tot_size +
+						sizeof(
+						struct cam_power_settings);
+				}
+				if (tot_size > cmd_length) {
+					CAM_ERR(CAM_SENSOR,
+						"Command Buffer is wrong");
+					rc = -EINVAL;
+					goto free_power_down_settings;
+				}
+				CAM_DBG(CAM_SENSOR,
+					"Seq Type[%d]: %d Config_val: %ld",
+					pwr_down,
+					power_info->
+						power_down_setting[pwr_down].
+						seq_type,
+					power_info->
+						power_down_setting[pwr_down].
+						config_val);
+			}
+			last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN;
+			ptr = (void *) scr;
+			cmm_hdr = (struct common_header *)ptr;
+		} else {
+			CAM_ERR(CAM_SENSOR,
+				"Error: Un expected Header Type: %d",
+				cmm_hdr->cmd_type);
+		}
+	}
+
+	return rc;
+free_power_down_settings:
+	kfree(power_info->power_down_setting);
+free_power_settings:
+	kfree(power_info->power_setting);
+	return rc;
+}
+
+int cam_get_dt_power_setting_data(struct device_node *of_node,
+	struct cam_hw_soc_info *soc_info,
+	struct cam_sensor_power_ctrl_t *power_info)
+{
+	int rc = 0, i;
+	int count = 0;
+	const char *seq_name = NULL;
+	uint32_t *array = NULL;
+	struct cam_sensor_power_setting *ps;
+	int c, end;
+
+	if (!power_info)
+		return -EINVAL;
+
+	count = of_property_count_strings(of_node, "qcom,cam-power-seq-type");
+	power_info->power_setting_size = count;
+
+	CAM_DBG(CAM_SENSOR, "qcom,cam-power-seq-type count %d", count);
+
+	if (count <= 0)
+		return 0;
+
+	ps = kcalloc(count, sizeof(*ps), GFP_KERNEL);
+	if (!ps)
+		return -ENOMEM;
+	power_info->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);
+		if (rc < 0) {
+			CAM_ERR(CAM_SENSOR, "failed");
+			goto ERROR1;
+		}
+		CAM_DBG(CAM_SENSOR, "seq_name[%d] = %s", i, seq_name);
+		if (!strcmp(seq_name, "cam_vio")) {
+			ps[i].seq_type = SENSOR_VIO;
+		} else if (!strcmp(seq_name, "cam_vana")) {
+			ps[i].seq_type = SENSOR_VANA;
+		} else if (!strcmp(seq_name, "cam_clk")) {
+			ps[i].seq_type = SENSOR_MCLK;
+		} else {
+			CAM_ERR(CAM_SENSOR, "unrecognized seq-type %s",
+				seq_name);
+			rc = -EILSEQ;
+			goto ERROR1;
+		}
+		CAM_DBG(CAM_SENSOR, "seq_type[%d] %d", i, ps[i].seq_type);
+	}
+
+	array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL);
+	if (!array) {
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-cfg-val",
+		array, count);
+	if (rc < 0) {
+		CAM_ERR(CAM_SENSOR, "failed ");
+		goto ERROR2;
+	}
+
+	for (i = 0; i < count; i++) {
+		ps[i].config_val = array[i];
+		CAM_DBG(CAM_SENSOR, "power_setting[%d].config_val = %ld", i,
+			ps[i].config_val);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-delay",
+		array, count);
+	if (rc < 0) {
+		CAM_ERR(CAM_SENSOR, "failed");
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		ps[i].delay = array[i];
+		CAM_DBG(CAM_SENSOR, "power_setting[%d].delay = %d", i,
+			ps[i].delay);
+	}
+	kfree(array);
+
+	power_info->power_down_setting =
+		kzalloc(sizeof(*ps) * count, GFP_KERNEL);
+
+	if (!power_info->power_down_setting) {
+		CAM_ERR(CAM_SENSOR, "failed");
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+	power_info->power_down_setting_size = count;
+
+	end = count - 1;
+
+	for (c = 0; c < count; c++) {
+		power_info->power_down_setting[c] = ps[end];
+		end--;
+	}
+	return rc;
+ERROR2:
+	kfree(array);
+ERROR1:
+	kfree(ps);
+	return rc;
+}
 
 int cam_sensor_util_init_gpio_pin_tbl(
 	struct cam_hw_soc_info *soc_info,
@@ -574,22 +867,19 @@
 
 	gconf = soc_info->gpio_data;
 	if (!gconf) {
-		pr_err("%s:%d No gpio_common_table is found\n",
-			 __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "No gpio_common_table is found");
 		return -EINVAL;
 	}
 
 	if (!gconf->cam_gpio_common_tbl) {
-		pr_err("%s:%d gpio_common_table is not initialized\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "gpio_common_table is not initialized");
 		return -EINVAL;
 	}
 
 	gpio_array_size = gconf->cam_gpio_common_tbl_size;
 
 	if (!gpio_array_size) {
-		pr_err("%s:%d invalid size of gpio table\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "invalid size of gpio table");
 		return -EINVAL;
 	}
 
@@ -602,12 +892,10 @@
 	rc = of_property_read_u32(of_node, "gpio-vana", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-vana failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "read gpio-vana failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-vana invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-vana invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -615,38 +903,34 @@
 				gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_VANA] = 1;
 
-		CDBG("%s:%d gpio-vana %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-vana %d",
 			gpio_num_info->gpio_num[SENSOR_VANA]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-vio", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-vio failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "read gpio-vio failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-vio invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-vio invalid %d", val);
 			goto free_gpio_info;
 		}
 		gpio_num_info->gpio_num[SENSOR_VIO] =
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_VIO] = 1;
 
-		CDBG("%s:%d gpio-vio %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-vio %d",
 			gpio_num_info->gpio_num[SENSOR_VIO]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-vaf", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-vaf failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "read gpio-vaf failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-vaf invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-vaf invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -654,19 +938,17 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_VAF] = 1;
 
-		CDBG("%s:%d gpio-vaf %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-vaf %d",
 			gpio_num_info->gpio_num[SENSOR_VAF]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-vdig", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-vdig failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "read gpio-vdig failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-vdig invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-vdig invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -674,19 +956,17 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_VDIG] = 1;
 
-		CDBG("%s:%d gpio-vdig %d\n", __func__, __LINE__,
-			gpio_num_info->gpio_num[SENSOR_VDIG]);
+		CAM_DBG(CAM_SENSOR, "gpio-vdig %d",
+				gpio_num_info->gpio_num[SENSOR_VDIG]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-reset", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-reset failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR, "read gpio-reset failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-reset invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-reset invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -694,19 +974,18 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_RESET] = 1;
 
-		CDBG("%s:%d gpio-reset %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-reset %d",
 			gpio_num_info->gpio_num[SENSOR_RESET]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-standby", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-standby failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR,
+				"read gpio-standby failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-standby invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-standby invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -714,19 +993,18 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_STANDBY] = 1;
 
-		CDBG("%s:%d gpio-standby %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-standby %d",
 			gpio_num_info->gpio_num[SENSOR_STANDBY]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-af-pwdm", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-af-pwdm failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR,
+				"read gpio-af-pwdm failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-af-pwdm invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-af-pwdm invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -734,19 +1012,18 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_VAF_PWDM] = 1;
 
-		CDBG("%s:%d gpio-af-pwdm %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-af-pwdm %d",
 			gpio_num_info->gpio_num[SENSOR_VAF_PWDM]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-custom1", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-custom1 failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR,
+				"read gpio-custom1 failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-custom1 invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-custom1 invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -754,19 +1031,18 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_CUSTOM_GPIO1] = 1;
 
-		CDBG("%s:%d gpio-custom1 %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-custom1 %d",
 			gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1]);
 	}
 
 	rc = of_property_read_u32(of_node, "gpio-custom2", &val);
 	if (rc != -EINVAL) {
 		if (rc < 0) {
-			pr_err("%s:%d read gpio-custom2 failed rc %d\n",
-				__func__, __LINE__, rc);
+			CAM_ERR(CAM_SENSOR,
+				"read gpio-custom2 failed rc %d", rc);
 			goto free_gpio_info;
 		} else if (val >= gpio_array_size) {
-			pr_err("%s:%d gpio-custom2 invalid %d\n",
-				__func__, __LINE__, val);
+			CAM_ERR(CAM_SENSOR, "gpio-custom2 invalid %d", val);
 			rc = -EINVAL;
 			goto free_gpio_info;
 		}
@@ -774,7 +1050,7 @@
 			gconf->cam_gpio_common_tbl[val].gpio;
 		gpio_num_info->valid[SENSOR_CUSTOM_GPIO2] = 1;
 
-		CDBG("%s:%d gpio-custom2 %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "gpio-custom2 %d",
 			gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2]);
 	} else {
 		rc = 0;
@@ -793,24 +1069,23 @@
 
 	sensor_pctrl->pinctrl = devm_pinctrl_get(dev);
 	if (IS_ERR_OR_NULL(sensor_pctrl->pinctrl)) {
-		pr_err("%s:%d Getting pinctrl handle failed\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Getting pinctrl handle failed");
 		return -EINVAL;
 	}
 	sensor_pctrl->gpio_state_active =
 		pinctrl_lookup_state(sensor_pctrl->pinctrl,
 				CAM_SENSOR_PINCTRL_STATE_DEFAULT);
 	if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_active)) {
-		pr_err("%s:%d Failed to get the active state pinctrl handle\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR,
+			"Failed to get the active state pinctrl handle");
 		return -EINVAL;
 	}
 	sensor_pctrl->gpio_state_suspend
 		= pinctrl_lookup_state(sensor_pctrl->pinctrl,
 				CAM_SENSOR_PINCTRL_STATE_SLEEP);
 	if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_suspend)) {
-		pr_err("%s:%d Failed to get the suspend state pinctrl handle\n",
-				__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR,
+			"Failed to get the suspend state pinctrl handle");
 		return -EINVAL;
 	}
 	return 0;
@@ -821,19 +1096,17 @@
 	int gpio_offset = -1;
 
 	if (!gpio_num_info) {
-		pr_err("%s:%d Input Parameters are not proper\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Input Parameters are not proper");
 		return -EINVAL;
 	}
 
-	CDBG("%s: %d Seq type: %d, config: %d", __func__, __LINE__,
-		seq_type, val);
+	CAM_DBG(CAM_SENSOR, "Seq type: %d, config: %d", seq_type, val);
 
 	gpio_offset = seq_type;
 
 	if (gpio_num_info->valid[gpio_offset] == 1) {
-		CDBG("%s: %d VALID GPIO offset: %d, seqtype: %d\n",
-			__func__, __LINE__, gpio_offset, seq_type);
+		CAM_DBG(CAM_SENSOR, "VALID GPIO offset: %d, seqtype: %d",
+			 gpio_offset, seq_type);
 		gpio_set_value_cansleep(
 			gpio_num_info->gpio_num
 			[gpio_offset], val);
@@ -850,9 +1123,9 @@
 	struct cam_sensor_power_setting *power_setting = NULL;
 	struct msm_camera_gpio_num_info *gpio_num_info = NULL;
 
-	CDBG("%s:%d\n", __func__, __LINE__);
+	CAM_DBG(CAM_SENSOR, "Enter");
 	if (!ctrl) {
-		pr_err("%s:%d Invalid ctrl handle\n", __func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Invalid ctrl handle");
 		return -EINVAL;
 	}
 
@@ -860,15 +1133,13 @@
 	num_vreg = soc_info->num_rgltr;
 
 	if ((num_vreg == 0) || (num_vreg > CAM_SOC_MAX_REGULATOR)) {
-		pr_err("%s:%d Regulators are not initialized\n",
-			__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Regulators are not initialized");
 		return -EINVAL;
 	}
 
 	ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev);
 	if (ret < 0) {
-		pr_err("%s:%d Initialization of pinctrl failed\n",
-				__func__, __LINE__);
+		CAM_ERR(CAM_SENSOR, "Initialization of pinctrl failed");
 		ctrl->cam_pinctrl_status = 0;
 	} else {
 		ctrl->cam_pinctrl_status = 1;
@@ -882,19 +1153,18 @@
 		ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
 			ctrl->pinctrl_info.gpio_state_active);
 		if (ret)
-			pr_err("%s:%d cannot set pin to active state",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "cannot set pin to active state");
 	}
 
 	for (index = 0; index < ctrl->power_setting_size; index++) {
-		CDBG("%s:%d index %d\n", __func__, __LINE__, index);
+		CAM_DBG(CAM_SENSOR, "index: %d",  index);
 		power_setting = &ctrl->power_setting[index];
+		CAM_DBG(CAM_SENSOR, "seq_type %d", power_setting->seq_type);
 
 		switch (power_setting->seq_type) {
 		case SENSOR_MCLK:
 			if (power_setting->seq_val >= soc_info->num_clk) {
-				pr_err("%s:%d :Error: clk index %d >= max %u\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR, "clk index %d >= max %u",
 					power_setting->seq_val,
 					soc_info->num_clk);
 				goto power_up_failed;
@@ -902,8 +1172,8 @@
 			for (j = 0; j < num_vreg; j++) {
 				if (!strcmp(soc_info->rgltr_name[j],
 					"cam_clk")) {
-					CDBG("%s:%d Enable cam_clk: %d\n",
-						__func__, __LINE__, j);
+					CAM_DBG(CAM_SENSOR,
+						"Enable cam_clk: %d", j);
 
 					soc_info->rgltr[j] =
 					regulator_get(
@@ -915,8 +1185,8 @@
 						rc = PTR_ERR(
 							soc_info->rgltr[j]);
 						rc = rc ? rc : -EINVAL;
-						pr_err("%s:%d :vreg %s %d\n",
-							__func__, __LINE__,
+						CAM_ERR(CAM_SENSOR,
+							"vreg %s %d",
 							soc_info->rgltr_name[j],
 							rc);
 						soc_info->rgltr[j] = NULL;
@@ -947,8 +1217,7 @@
 			}
 
 			if (rc < 0) {
-				pr_err("%s:%d clk enable failed\n", __func__,
-					__LINE__);
+				CAM_ERR(CAM_SENSOR, "clk enable failed");
 				goto power_up_failed;
 			}
 			break;
@@ -957,20 +1226,17 @@
 		case SENSOR_CUSTOM_GPIO1:
 		case SENSOR_CUSTOM_GPIO2:
 			if (no_gpio) {
-				pr_err("%s:%d request gpio failed\n", __func__,
-					__LINE__);
+				CAM_ERR(CAM_SENSOR, "request gpio failed");
 				return no_gpio;
 			}
 			if (power_setting->seq_val >= CAM_VREG_MAX ||
 				!gpio_num_info) {
-				pr_err("%s:%d gpio index %d >= max %d\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR, "gpio index %d >= max %d",
 					power_setting->seq_val,
 					CAM_VREG_MAX);
 				goto power_up_failed;
 			}
-			CDBG("%s:%d gpio set val %d\n",
-				__func__, __LINE__,
+			CAM_DBG(CAM_SENSOR, "gpio set val %d",
 				gpio_num_info->gpio_num
 				[power_setting->seq_val]);
 
@@ -978,8 +1244,8 @@
 				power_setting->seq_type,
 				gpio_num_info, 1);
 			if (rc < 0) {
-				pr_err("%s:%d Error in handling VREG GPIO\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_SENSOR,
+					"Error in handling VREG GPIO");
 				goto power_up_failed;
 			}
 			break;
@@ -994,15 +1260,13 @@
 				break;
 
 			if (power_setting->seq_val >= CAM_VREG_MAX) {
-				pr_err("%s:%d vreg index %d >= max %d\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR, "vreg index %d >= max %d",
 					power_setting->seq_val,
 					CAM_VREG_MAX);
 				goto power_up_failed;
 			}
 			if (power_setting->seq_val < num_vreg) {
-				CDBG("%s:%d Enable Regulator\n",
-					__func__, __LINE__);
+				CAM_DBG(CAM_SENSOR, "Enable Regulator");
 				vreg_idx = power_setting->seq_val;
 
 				soc_info->rgltr[vreg_idx] =
@@ -1013,8 +1277,7 @@
 					rc = PTR_ERR(soc_info->rgltr[vreg_idx]);
 					rc = rc ? rc : -EINVAL;
 
-					pr_err("%s:%d, %s get failed %d\n",
-						__func__, __LINE__,
+					CAM_ERR(CAM_SENSOR, "%s get failed %d",
 						soc_info->rgltr_name[vreg_idx],
 						rc);
 
@@ -1033,22 +1296,21 @@
 						soc_info->rgltr[vreg_idx];
 			}
 			else
-				pr_err("%s: %d usr_idx:%d dts_idx:%d\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR, "usr_idx:%d dts_idx:%d",
 					power_setting->seq_val, num_vreg);
 
 			rc = msm_cam_sensor_handle_reg_gpio(
 				power_setting->seq_type,
 				gpio_num_info, 1);
 			if (rc < 0) {
-				pr_err("%s:%d Error in handling VREG GPIO\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_SENSOR,
+					"Error in handling VREG GPIO");
 				goto power_up_failed;
 			}
 			break;
 		default:
-			pr_err("%s:%d error power seq type %d\n", __func__,
-				__LINE__, power_setting->seq_type);
+			CAM_ERR(CAM_SENSOR, "error power seq type %d",
+				power_setting->seq_type);
 			break;
 		}
 		if (power_setting->delay > 20)
@@ -1060,11 +1322,11 @@
 
 	return 0;
 power_up_failed:
-	pr_err("%s:%d failed\n", __func__, __LINE__);
+	CAM_ERR(CAM_SENSOR, "failed");
 	for (index--; index >= 0; index--) {
-		CDBG("%s:%d index %d\n", __func__, __LINE__, index);
+		CAM_DBG(CAM_SENSOR, "index %d",  index);
 		power_setting = &ctrl->power_setting[index];
-		CDBG("%s:%d type %d\n", __func__, __LINE__,
+		CAM_DBG(CAM_SENSOR, "type %d",
 			power_setting->seq_type);
 		switch (power_setting->seq_type) {
 		case SENSOR_RESET:
@@ -1088,8 +1350,7 @@
 		case SENSOR_CUSTOM_REG1:
 		case SENSOR_CUSTOM_REG2:
 			if (power_setting->seq_val < num_vreg) {
-				CDBG("%s:%d Disable Regulator\n",
-					__func__, __LINE__);
+				CAM_DBG(CAM_SENSOR, "Disable Regulator");
 				vreg_idx = power_setting->seq_val;
 
 				rc =  cam_soc_util_regulator_disable(
@@ -1105,8 +1366,7 @@
 
 			}
 			else
-				pr_err("%s:%d:seq_val: %d > num_vreg: %d\n",
-					__func__, __LINE__,
+				CAM_ERR(CAM_SENSOR, "seq_val:%d > num_vreg: %d",
 					power_setting->seq_val, num_vreg);
 
 			msm_cam_sensor_handle_reg_gpio(power_setting->seq_type,
@@ -1114,8 +1374,8 @@
 
 			break;
 		default:
-			pr_err("%s:%d error power seq type %d\n", __func__,
-				__LINE__, power_setting->seq_type);
+			CAM_ERR(CAM_SENSOR, "error power seq type %d",
+				power_setting->seq_type);
 			break;
 		}
 		if (power_setting->delay > 20) {
@@ -1129,8 +1389,7 @@
 		ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
 				ctrl->pinctrl_info.gpio_state_suspend);
 		if (ret)
-			pr_err("%s:%d cannot set pin to suspend state\n",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state");
 		devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
 	}
 	ctrl->cam_pinctrl_status = 0;
@@ -1186,8 +1445,7 @@
 			}
 
 			if (ps != NULL) {
-				CDBG("%s:%d Disable Regulator\n",
-					__func__, __LINE__);
+				CAM_DBG(CAM_SENSOR, "Disable Regulator");
 
 				rc = cam_soc_util_regulator_disable(
 					soc_info->rgltr[j],
@@ -1214,9 +1472,9 @@
 	struct cam_sensor_power_setting *ps;
 	struct msm_camera_gpio_num_info *gpio_num_info = NULL;
 
-	CDBG("%s:%d\n", __func__, __LINE__);
+	CAM_DBG(CAM_SENSOR, "Enter");
 	if (!ctrl || !soc_info) {
-		pr_err("%s:%d failed ctrl %pK\n", __func__, __LINE__, ctrl);
+		CAM_ERR(CAM_SENSOR, "failed ctrl %pK",  ctrl);
 		return -EINVAL;
 	}
 
@@ -1224,16 +1482,16 @@
 	num_vreg = soc_info->num_rgltr;
 
 	for (index = 0; index < ctrl->power_down_setting_size; index++) {
-		CDBG("%s:%d index %d\n", __func__, __LINE__, index);
+		CAM_DBG(CAM_SENSOR, "index %d",  index);
 		pd = &ctrl->power_down_setting[index];
 		ps = NULL;
-		CDBG("%s:%d type %d\n", __func__, __LINE__, pd->seq_type);
+		CAM_DBG(CAM_SENSOR, "type %d",  pd->seq_type);
 		switch (pd->seq_type) {
 		case SENSOR_MCLK:
 			ret = cam_config_mclk_reg(ctrl, soc_info, index);
 			if (ret < 0) {
-				pr_err("%s:%d :Error: in config clk reg\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_SENSOR,
+					"config clk reg failed rc: %d", ret);
 				return ret;
 			}
 			//cam_soc_util_clk_disable_default(soc_info);
@@ -1272,8 +1530,8 @@
 				pd->seq_val);
 			if (ps) {
 				if (pd->seq_val < num_vreg) {
-					CDBG("%s:%d Disable Regulator\n",
-						__func__, __LINE__);
+					CAM_DBG(CAM_SENSOR,
+						"Disable Regulator");
 					ret =  cam_soc_util_regulator_disable(
 					soc_info->rgltr[ps->seq_val],
 					soc_info->rgltr_name[ps->seq_val],
@@ -1286,23 +1544,24 @@
 						soc_info->rgltr[ps->seq_val];
 				}
 				else
-					pr_err("%s:%d:seq_val:%d > num_vreg: %d\n",
-						__func__, __LINE__, pd->seq_val,
+					CAM_ERR(CAM_SENSOR,
+						"seq_val:%d > num_vreg: %d",
+						 pd->seq_val,
 						num_vreg);
 			} else
-				pr_err("%s:%d error in power up/down seq\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_SENSOR,
+					"error in power up/down seq");
 
 			ret = msm_cam_sensor_handle_reg_gpio(pd->seq_type,
 				gpio_num_info, GPIOF_OUT_INIT_LOW);
 
 			if (ret < 0)
-				pr_err("%s:%d Error disabling VREG GPIO\n",
-					__func__, __LINE__);
+				CAM_ERR(CAM_SENSOR,
+					"Error disabling VREG GPIO");
 			break;
 		default:
-			pr_err("%s:%d error power seq type %d\n", __func__,
-				__LINE__, pd->seq_type);
+			CAM_ERR(CAM_SENSOR, "error power seq type %d",
+				pd->seq_type);
 			break;
 		}
 		if (pd->delay > 20)
@@ -1316,8 +1575,7 @@
 		ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
 				ctrl->pinctrl_info.gpio_state_suspend);
 		if (ret)
-			pr_err("%s:%d cannot set pin to suspend state",
-				__func__, __LINE__);
+			CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state");
 		devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
index 912f06b..8a26369 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -23,11 +23,12 @@
 #include <cam_req_mgr_interface.h>
 #include <cam_mem_mgr.h>
 #include "cam_soc_util.h"
+#include "cam_debug_util.h"
 
 #define INVALID_VREG 100
 
-int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
-	struct camera_vreg_t *cam_vreg, int num_vreg,
+int cam_get_dt_power_setting_data(struct device_node *of_node,
+	struct cam_hw_soc_info *soc_info,
 	struct cam_sensor_power_ctrl_t *power_info);
 
 int msm_camera_pinctrl_init
@@ -52,4 +53,7 @@
 int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info,
 	struct cam_sensor_power_setting *power_setting,
 	uint16_t power_setting_size);
+
+int32_t cam_sensor_update_power_settings(void *cmd_buf,
+	int cmd_length, struct cam_sensor_power_ctrl_t *power_info);
 #endif /* _CAM_SENSOR_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_smmu/Makefile b/drivers/media/platform/msm/camera/cam_smmu/Makefile
index 3619da7..e17dac6 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/Makefile
+++ b/drivers/media/platform/msm/camera/cam_smmu/Makefile
@@ -1 +1,3 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu_api.o
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index ca0dfac..ff7a0e5 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-SMMU %s:%d " fmt, __func__, __LINE__
-
 #include <linux/module.h>
 #include <linux/dma-buf.h>
 #include <asm/dma-iommu.h>
@@ -25,6 +23,7 @@
 #include <linux/genalloc.h>
 
 #include "cam_smmu_api.h"
+#include "cam_debug_util.h"
 
 #define SHARED_MEM_POOL_GRANULARITY 12
 
@@ -39,12 +38,6 @@
 #define GET_SMMU_HDL(x, y) (((x) << COOKIE_SIZE) | ((y) & COOKIE_MASK))
 #define GET_SMMU_TABLE_IDX(x) (((x) >> COOKIE_SIZE) & COOKIE_MASK)
 
-#ifdef CONFIG_CAM_SMMU_DBG
-#define CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
 struct firmware_alloc_info {
 	struct device *fw_dev;
 	void *fw_kva;
@@ -223,7 +216,7 @@
 
 	mutex_lock(&iommu_cb_set.payload_list_lock);
 	if (list_empty(&iommu_cb_set.payload_list)) {
-		pr_err("Payload list empty\n");
+		CAM_ERR(CAM_SMMU, "Payload list empty");
 		mutex_unlock(&iommu_cb_set.payload_list_lock);
 		return;
 	}
@@ -256,10 +249,11 @@
 {
 	struct cam_dma_buff_info *mapping;
 
-	pr_err("index = %d\n", idx);
+	CAM_ERR(CAM_SMMU, "index = %d", idx);
 	list_for_each_entry(mapping,
 		&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
-		pr_err("ion_fd = %d, paddr= 0x%pK, len = %u, region = %d\n",
+		CAM_ERR(CAM_SMMU,
+			"ion_fd = %d, paddr= 0x%pK, len = %u, region = %d",
 			 mapping->ion_fd, (void *)mapping->paddr,
 			 (unsigned int)mapping->len,
 			 mapping->region_id);
@@ -271,10 +265,10 @@
 	int i;
 
 	for (i = 0; i < iommu_cb_set.cb_num; i++) {
-		pr_err("i= %d, handle= %d, name_addr=%pK\n", i,
+		CAM_ERR(CAM_SMMU, "i= %d, handle= %d, name_addr=%pK", i,
 			   (int)iommu_cb_set.cb_info[i].handle,
 			   (void *)iommu_cb_set.cb_info[i].name);
-		pr_err("dev = %pK\n", iommu_cb_set.cb_info[i].dev);
+		CAM_ERR(CAM_SMMU, "dev = %pK", iommu_cb_set.cb_info[i].dev);
 	}
 }
 
@@ -290,18 +284,21 @@
 		end_addr = (unsigned long)mapping->paddr + mapping->len;
 
 		if (start_addr <= current_addr && current_addr < end_addr) {
-			pr_err("va %pK valid: range:%pK-%pK, fd = %d cb: %s\n",
+			CAM_ERR(CAM_SMMU,
+				"va %pK valid: range:%pK-%pK, fd = %d cb: %s",
 				vaddr, (void *)start_addr, (void *)end_addr,
 				mapping->ion_fd,
 				iommu_cb_set.cb_info[idx].name);
 			goto end;
 		} else {
-			CDBG("va %pK is not in this range: %pK-%pK, fd = %d\n",
+			CAM_DBG(CAM_SMMU,
+				"va %pK is not in this range: %pK-%pK, fd = %d",
 				vaddr, (void *)start_addr, (void *)end_addr,
 				mapping->ion_fd);
 		}
 	}
-	pr_err("Cannot find vaddr:%pK in SMMU %s uses invalid virt address\n",
+	CAM_ERR(CAM_SMMU,
+		"Cannot find vaddr:%pK in SMMU %s uses invalid virt address",
 		vaddr, iommu_cb_set.cb_info[idx].name);
 end:
 	return;
@@ -315,20 +312,22 @@
 	int idx, i = 0;
 
 	if (!token || (handle == HANDLE_INIT)) {
-		pr_err("Error: token is NULL or invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: token is NULL or invalid handle");
 		return;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 		return;
@@ -336,7 +335,8 @@
 
 	if (client_page_fault_handler) {
 		if (iommu_cb_set.cb_info[idx].cb_count == CAM_SMMU_CB_MAX) {
-			pr_err("%s Should not regiester more handlers\n",
+			CAM_ERR(CAM_SMMU,
+				"%s Should not regiester more handlers",
 				iommu_cb_set.cb_info[idx].name);
 			mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 			return;
@@ -361,7 +361,8 @@
 			}
 		}
 		if (i == CAM_SMMU_CB_MAX)
-			pr_err("Error: hdl %x no matching tokens: %s\n",
+			CAM_ERR(CAM_SMMU,
+				"Error: hdl %x no matching tokens: %s",
 				handle, iommu_cb_set.cb_info[idx].name);
 	}
 	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
@@ -376,9 +377,10 @@
 	struct cam_smmu_work_payload *payload;
 
 	if (!token) {
-		pr_err("Error: token is NULL\n");
-		pr_err("Error: domain = %pK, device = %pK\n", domain, dev);
-		pr_err("iova = %lX, flags = %d\n", iova, flags);
+		CAM_ERR(CAM_SMMU, "Error: token is NULL");
+		CAM_ERR(CAM_SMMU, "Error: domain = %pK, device = %pK",
+			domain, dev);
+		CAM_ERR(CAM_SMMU, "iova = %lX, flags = %d", iova, flags);
 		return 0;
 	}
 
@@ -390,7 +392,8 @@
 	}
 
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: index is not valid, index = %d, token = %s\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: index is not valid, index = %d, token = %s",
 			idx, cb_name);
 		return 0;
 	}
@@ -427,7 +430,7 @@
 		return IOMMU_READ|IOMMU_WRITE;
 	case CAM_SMMU_MAP_INVALID:
 	default:
-		pr_err("Error: Direction is invalid. dir = %d\n", dir);
+		CAM_ERR(CAM_SMMU, "Error: Direction is invalid. dir = %d", dir);
 		break;
 	};
 	return IOMMU_INVALID_DIR;
@@ -445,7 +448,8 @@
 		return DMA_BIDIRECTIONAL;
 	case CAM_SMMU_MAP_INVALID:
 	default:
-		pr_err("Error: Direction is invalid. dir = %d\n", (int)dir);
+		CAM_ERR(CAM_SMMU, "Error: Direction is invalid. dir = %d",
+			(int)dir);
 		break;
 	}
 	return DMA_NONE;
@@ -478,7 +482,8 @@
 	int i;
 
 	if (hdl == HANDLE_INIT) {
-		CDBG("iommu handle is init number. Need to try again\n");
+		CAM_DBG(CAM_SMMU,
+			"iommu handle is init number. Need to try again");
 		return 1;
 	}
 
@@ -487,7 +492,8 @@
 			continue;
 
 		if (iommu_cb_set.cb_info[i].handle == hdl) {
-			CDBG("iommu handle %d conflicts\n", (int)hdl);
+			CAM_DBG(CAM_SMMU, "iommu handle %d conflicts",
+				(int)hdl);
 			return 1;
 		}
 	}
@@ -503,7 +509,7 @@
 
 	get_random_bytes(&rand, COOKIE_NUM_BYTE);
 	hdl = GET_SMMU_HDL(idx, rand);
-	CDBG("create handle value = %x\n", (int)hdl);
+	CAM_DBG(CAM_SMMU, "create handle value = %x", (int)hdl);
 	return hdl;
 }
 
@@ -515,7 +521,8 @@
 	/* attach the mapping to device */
 	rc = arm_iommu_attach_device(cb->dev, cb->mapping);
 	if (rc < 0) {
-		pr_err("Error: ARM IOMMU attach failed. ret = %d\n", rc);
+		CAM_ERR(CAM_SMMU, "Error: ARM IOMMU attach failed. ret = %d",
+			rc);
 		rc = -ENODEV;
 	}
 
@@ -533,7 +540,8 @@
 		if (!strcmp(iommu_cb_set.cb_info[i].name, name)) {
 			mutex_lock(&iommu_cb_set.cb_info[i].lock);
 			if (iommu_cb_set.cb_info[i].handle != HANDLE_INIT) {
-				pr_err("Error: %s already got handle 0x%x\n",
+				CAM_ERR(CAM_SMMU,
+					"Error: %s already got handle 0x%x",
 					name,
 					iommu_cb_set.cb_info[i].handle);
 				mutex_unlock(&iommu_cb_set.cb_info[i].lock);
@@ -549,14 +557,15 @@
 			iommu_cb_set.cb_info[i].handle = handle;
 			iommu_cb_set.cb_info[i].cb_count = 0;
 			*hdl = handle;
-			CDBG("%s creates handle 0x%x\n", name, handle);
+			CAM_DBG(CAM_SMMU, "%s creates handle 0x%x",
+				name, handle);
 			mutex_unlock(&iommu_cb_set.cb_info[i].lock);
 			return 0;
 		}
 	}
 
-	pr_err("Error: Cannot find name %s or all handle exist!\n",
-			name);
+	CAM_ERR(CAM_SMMU, "Error: Cannot find name %s or all handle exist",
+		name);
 	cam_smmu_print_table();
 	return -EINVAL;
 }
@@ -571,7 +580,8 @@
 
 	if (!count) {
 		err = -EINVAL;
-		pr_err("Page count is zero, size passed = %zu\n", size);
+		CAM_ERR(CAM_SMMU, "Page count is zero, size passed = %zu",
+			size);
 		goto bail;
 	}
 
@@ -630,12 +640,12 @@
 			      (1 << mapping->order) - 1) >> mapping->order;
 
 	if (!addr) {
-		pr_err("Error: Invalid address\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid address");
 		return -EINVAL;
 	}
 
 	if (start + count > mapping->bits) {
-		pr_err("Error: Invalid page bits in scratch map\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid page bits in scratch map");
 		return -EINVAL;
 	}
 
@@ -657,13 +667,13 @@
 	list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list,
 			list) {
 		if (mapping->paddr == virt_addr) {
-			CDBG("Found virtual address %lx\n",
+			CAM_DBG(CAM_SMMU, "Found virtual address %lx",
 				 (unsigned long)virt_addr);
 			return mapping;
 		}
 	}
 
-	pr_err("Error: Cannot find virtual address %lx by index %d\n",
+	CAM_ERR(CAM_SMMU, "Error: Cannot find virtual address %lx by index %d",
 		(unsigned long)virt_addr, idx);
 	return NULL;
 }
@@ -676,12 +686,12 @@
 	list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list,
 			list) {
 		if (mapping->ion_fd == ion_fd) {
-			CDBG(" find ion_fd %d\n", ion_fd);
+			CAM_DBG(CAM_SMMU, "find ion_fd %d", ion_fd);
 			return mapping;
 		}
 	}
 
-	pr_err("Error: Cannot find fd %d by index %d\n",
+	CAM_ERR(CAM_SMMU, "Error: Cannot find fd %d by index %d",
 		ion_fd, idx);
 	return NULL;
 }
@@ -693,7 +703,7 @@
 
 	list_for_each_entry_safe(mapping_info, temp,
 			&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
-		CDBG("Free mapping address %pK, i = %d, fd = %d\n",
+		CAM_DBG(CAM_SMMU, "Free mapping address %pK, i = %d, fd = %d",
 			(void *)mapping_info->paddr, idx,
 			mapping_info->ion_fd);
 
@@ -708,10 +718,12 @@
 					idx);
 
 		if (ret < 0) {
-			pr_err("Buffer delete failed: idx = %d\n", idx);
-			pr_err("Buffer delete failed: addr = %lx, fd = %d\n",
-					(unsigned long)mapping_info->paddr,
-					mapping_info->ion_fd);
+			CAM_ERR(CAM_SMMU, "Buffer delete failed: idx = %d",
+				idx);
+			CAM_ERR(CAM_SMMU,
+				"Buffer delete failed: addr = %lx, fd = %d",
+				(unsigned long)mapping_info->paddr,
+				mapping_info->ion_fd);
 			/*
 			 * Ignore this error and continue to delete other
 			 * buffers in the list
@@ -730,13 +742,13 @@
 	} else if (iommu_cb_set.cb_info[idx].state == CAM_SMMU_DETACH) {
 		ret = cam_smmu_attach_device(idx);
 		if (ret < 0) {
-			pr_err("Error: ATTACH fail\n");
+			CAM_ERR(CAM_SMMU, "Error: ATTACH fail");
 			return -ENODEV;
 		}
 		iommu_cb_set.cb_info[idx].state = CAM_SMMU_ATTACH;
 		ret = 0;
 	} else {
-		pr_err("Error: Not detach/attach: %d\n",
+		CAM_ERR(CAM_SMMU, "Error: Not detach/attach: %d",
 			iommu_cb_set.cb_info[idx].state);
 		ret = -EINVAL;
 	}
@@ -768,28 +780,32 @@
 	uint32_t vaddr = 0;
 
 	if (!iova || !size || (smmu_hdl == HANDLE_INIT)) {
-		pr_err("Error: Input args are invalid\n");
+		CAM_ERR(CAM_SMMU, "Error: Input args are invalid");
 		return -EINVAL;
 	}
 
-	CDBG("Allocating iova size = %zu for smmu hdl=%X\n", size, smmu_hdl);
+	CAM_DBG(CAM_SMMU, "Allocating iova size = %zu for smmu hdl=%X",
+		size, smmu_hdl);
 
 	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, smmu_hdl);
 		return -EINVAL;
 	}
 
 	if (iommu_cb_set.cb_info[idx].handle != smmu_hdl) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, smmu_hdl);
 		rc = -EINVAL;
 		goto get_addr_end;
 	}
 
 	if (!iommu_cb_set.cb_info[idx].shared_support) {
-		pr_err("Error: Shared memory not supported for hdl = %X\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: Shared memory not supported for hdl = %X",
 			smmu_hdl);
 		rc = -EINVAL;
 		goto get_addr_end;
@@ -812,19 +828,21 @@
 	int idx;
 
 	if (!size || (smmu_hdl == HANDLE_INIT)) {
-		pr_err("Error: Input args are invalid\n");
+		CAM_ERR(CAM_SMMU, "Error: Input args are invalid");
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, smmu_hdl);
 		return -EINVAL;
 	}
 
 	if (iommu_cb_set.cb_info[idx].handle != smmu_hdl) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, smmu_hdl);
 		rc = -EINVAL;
 		goto get_addr_end;
@@ -848,45 +866,47 @@
 	struct iommu_domain *domain;
 
 	if (!iova || !len || !cpuva || (smmu_hdl == HANDLE_INIT)) {
-		pr_err("Error: Input args are invalid\n");
+		CAM_ERR(CAM_SMMU, "Error: Input args are invalid");
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, smmu_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
 
 	if (!iommu_cb_set.cb_info[idx].firmware_support) {
-		pr_err("Firmware memory not supported for this SMMU handle\n");
+		CAM_ERR(CAM_SMMU,
+			"Firmware memory not supported for this SMMU handle");
 		rc = -EINVAL;
 		goto end;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].is_fw_allocated) {
-		pr_err("Trying to allocate twice\n");
+		CAM_ERR(CAM_SMMU, "Trying to allocate twice");
 		rc = -ENOMEM;
 		goto unlock_and_end;
 	}
 
 	firmware_len = iommu_cb_set.cb_info[idx].firmware_info.iova_len;
 	firmware_start = iommu_cb_set.cb_info[idx].firmware_info.iova_start;
-	CDBG("Firmware area len from DT = %zu\n", firmware_len);
+	CAM_DBG(CAM_SMMU, "Firmware area len from DT = %zu", firmware_len);
 
 	icp_fw.fw_kva = dma_alloc_coherent(icp_fw.fw_dev,
 		firmware_len,
 		&icp_fw.fw_dma_hdl,
 		GFP_KERNEL);
 	if (!icp_fw.fw_kva) {
-		pr_err("FW memory alloc failed\n");
+		CAM_ERR(CAM_SMMU, "FW memory alloc failed");
 		rc = -ENOMEM;
 		goto unlock_and_end;
 	} else {
-		CDBG("DMA alloc returned fw = %pK, hdl = %pK\n",
+		CAM_DBG(CAM_SMMU, "DMA alloc returned fw = %pK, hdl = %pK",
 			icp_fw.fw_kva, (void *)icp_fw.fw_dma_hdl);
 	}
 
@@ -898,7 +918,7 @@
 		IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV);
 
 	if (rc) {
-		pr_err("Failed to map FW into IOMMU\n");
+		CAM_ERR(CAM_SMMU, "Failed to map FW into IOMMU");
 		rc = -ENOMEM;
 		goto alloc_fail;
 	}
@@ -933,27 +953,30 @@
 	size_t unmapped = 0;
 
 	if (smmu_hdl == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, smmu_hdl);
 		rc = -EINVAL;
 		goto end;
 	}
 
 	if (!iommu_cb_set.cb_info[idx].firmware_support) {
-		pr_err("Firmware memory not supported for this SMMU handle\n");
+		CAM_ERR(CAM_SMMU,
+			"Firmware memory not supported for this SMMU handle");
 		rc = -EINVAL;
 		goto end;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (!iommu_cb_set.cb_info[idx].is_fw_allocated) {
-		pr_err("Trying to deallocate firmware that is not allocated\n");
+		CAM_ERR(CAM_SMMU,
+			"Trying to deallocate firmware that is not allocated");
 		rc = -ENOMEM;
 		goto unlock_and_end;
 	}
@@ -966,7 +989,7 @@
 		firmware_len);
 
 	if (unmapped != firmware_len) {
-		pr_err("Only %zu unmapped out of total %zu\n",
+		CAM_ERR(CAM_SMMU, "Only %zu unmapped out of total %zu",
 			unmapped,
 			firmware_len);
 		rc = -EINVAL;
@@ -997,18 +1020,18 @@
 	struct cam_context_bank_info *cb = NULL;
 
 	if (!region_info) {
-		pr_err("Invalid region_info pointer\n");
+		CAM_ERR(CAM_SMMU, "Invalid region_info pointer");
 		return -EINVAL;
 	}
 
 	if (smmu_hdl == HANDLE_INIT) {
-		pr_err("Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Invalid handle");
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU, "Handle or index invalid. idx = %d hdl = %x",
 			idx, smmu_hdl);
 		return -EINVAL;
 	}
@@ -1016,7 +1039,7 @@
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	cb = &iommu_cb_set.cb_info[idx];
 	if (!cb) {
-		pr_err("SMMU context bank pointer invalid\n");
+		CAM_ERR(CAM_SMMU, "SMMU context bank pointer invalid");
 		mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 		return -EINVAL;
 	}
@@ -1024,7 +1047,7 @@
 	switch (region_id) {
 	case CAM_SMMU_REGION_FIRMWARE:
 		if (!cb->firmware_support) {
-			pr_err("Firmware not supported\n");
+			CAM_ERR(CAM_SMMU, "Firmware not supported");
 			mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 			return -ENODEV;
 		}
@@ -1033,7 +1056,7 @@
 		break;
 	case CAM_SMMU_REGION_SHARED:
 		if (!cb->shared_support) {
-			pr_err("Shared mem not supported\n");
+			CAM_ERR(CAM_SMMU, "Shared mem not supported");
 			mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 			return -ENODEV;
 		}
@@ -1042,7 +1065,7 @@
 		break;
 	case CAM_SMMU_REGION_SCRATCH:
 		if (!cb->scratch_buf_support) {
-			pr_err("Scratch memory not supported\n");
+			CAM_ERR(CAM_SMMU, "Scratch memory not supported");
 			mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 			return -ENODEV;
 		}
@@ -1051,7 +1074,7 @@
 		break;
 	case CAM_SMMU_REGION_IO:
 		if (!cb->io_support) {
-			pr_err("IO memory not supported\n");
+			CAM_ERR(CAM_SMMU, "IO memory not supported");
 			mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 			return -ENODEV;
 		}
@@ -1059,7 +1082,7 @@
 		region_info->iova_len = cb->io_info.iova_len;
 		break;
 	default:
-		pr_err("Invalid region id: %d for smmu hdl: %X\n",
+		CAM_ERR(CAM_SMMU, "Invalid region id: %d for smmu hdl: %X",
 			smmu_hdl, region_id);
 		mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 		return -EINVAL;
@@ -1088,28 +1111,28 @@
 	buf = dma_buf_get(ion_fd);
 	if (IS_ERR_OR_NULL(buf)) {
 		rc = PTR_ERR(buf);
-		pr_err("Error: dma get buf failed. fd = %d\n", ion_fd);
+		CAM_ERR(CAM_SMMU, "Error: dma get buf failed. fd = %d", ion_fd);
 		goto err_out;
 	}
 
 	attach = dma_buf_attach(buf, iommu_cb_set.cb_info[idx].dev);
 	if (IS_ERR_OR_NULL(attach)) {
 		rc = PTR_ERR(attach);
-		pr_err("Error: dma buf attach failed\n");
+		CAM_ERR(CAM_SMMU, "Error: dma buf attach failed");
 		goto err_put;
 	}
 
 	table = dma_buf_map_attachment(attach, dma_dir);
 	if (IS_ERR_OR_NULL(table)) {
 		rc = PTR_ERR(table);
-		pr_err("Error: dma buf map attachment failed\n");
+		CAM_ERR(CAM_SMMU, "Error: dma buf map attachment failed");
 		goto err_detach;
 	}
 
 	if (region_id == CAM_SMMU_REGION_SHARED) {
 		domain = iommu_cb_set.cb_info[idx].mapping->domain;
 		if (!domain) {
-			pr_err("CB has no domain set\n");
+			CAM_ERR(CAM_SMMU, "CB has no domain set");
 			goto err_unmap_sg;
 		}
 
@@ -1118,7 +1141,8 @@
 			&iova);
 
 		if (rc < 0) {
-			pr_err("IOVA alloc failed for shared memory\n");
+			CAM_ERR(CAM_SMMU,
+				"IOVA alloc failed for shared memory");
 			goto err_unmap_sg;
 		}
 
@@ -1129,17 +1153,17 @@
 			IOMMU_READ | IOMMU_WRITE);
 
 		if (size < 0) {
-			pr_err("IOMMU mapping failed\n");
+			CAM_ERR(CAM_SMMU, "IOMMU mapping failed");
 			rc = cam_smmu_free_iova(iova,
 				size,
 				iommu_cb_set.cb_info[idx].handle);
 
 			if (rc)
-				pr_err("IOVA free failed\n");
+				CAM_ERR(CAM_SMMU, "IOVA free failed");
 			rc = -ENOMEM;
 			goto err_unmap_sg;
 		} else {
-			CDBG("iommu_map_sg returned %zu\n", size);
+			CAM_DBG(CAM_SMMU, "iommu_map_sg returned %zu", size);
 			*paddr_ptr = iova;
 			*len_ptr = size;
 		}
@@ -1148,7 +1172,7 @@
 			table->sgl, table->nents, dma_dir, buf);
 
 		if (rc != table->nents) {
-			pr_err("Error: msm_dma_map_sg_lazy failed\n");
+			CAM_ERR(CAM_SMMU, "Error: msm_dma_map_sg_lazy failed");
 			rc = -ENOMEM;
 			goto err_unmap_sg;
 		} else {
@@ -1156,22 +1180,23 @@
 			*len_ptr = (size_t)sg_dma_len(table->sgl);
 		}
 	} else {
-		pr_err("Error: Wrong region id passed for %s\n", __func__);
+		CAM_ERR(CAM_SMMU, "Error: Wrong region id passed");
 		rc = -EINVAL;
 		goto err_unmap_sg;
 	}
 
 	if (table->sgl) {
-		CDBG("DMA buf: %pK, device: %pK, attach: %pK, table: %pK\n",
-				(void *)buf,
-				(void *)iommu_cb_set.cb_info[idx].dev,
-				(void *)attach, (void *)table);
-		CDBG("table sgl: %pK, rc: %d, dma_address: 0x%x\n",
-				(void *)table->sgl, rc,
-				(unsigned int)table->sgl->dma_address);
+		CAM_DBG(CAM_SMMU,
+			"DMA buf: %pK, device: %pK, attach: %pK, table: %pK",
+			(void *)buf,
+			(void *)iommu_cb_set.cb_info[idx].dev,
+			(void *)attach, (void *)table);
+		CAM_DBG(CAM_SMMU, "table sgl: %pK, rc: %d, dma_address: 0x%x",
+			(void *)table->sgl, rc,
+			(unsigned int)table->sgl->dma_address);
 	} else {
 		rc = -EINVAL;
-		pr_err("Error: table sgl is null\n");
+		CAM_ERR(CAM_SMMU, "Error: table sgl is null");
 		goto err_unmap_sg;
 	}
 
@@ -1192,13 +1217,13 @@
 	mapping_info->region_id = region_id;
 
 	if (!*paddr_ptr || !*len_ptr) {
-		pr_err("Error: Space Allocation failed!\n");
+		CAM_ERR(CAM_SMMU, "Error: Space Allocation failed");
 		kfree(mapping_info);
 		rc = -ENOSPC;
 		goto err_alloc;
 	}
-	CDBG("ion_fd = %d, dev = %pK, paddr= %pK, len = %u\n", ion_fd,
-		(void *)iommu_cb_set.cb_info[idx].dev,
+	CAM_DBG(CAM_SMMU, "ion_fd = %d, dev = %pK, paddr= %pK, len = %u",
+		ion_fd, (void *)iommu_cb_set.cb_info[idx].dev,
 		(void *)*paddr_ptr, (unsigned int)*len_ptr);
 
 	/* add to the list */
@@ -1241,17 +1266,19 @@
 
 	if ((!mapping_info->buf) || (!mapping_info->table) ||
 		(!mapping_info->attach)) {
-		pr_err("Error: Invalid params dev = %pK, table = %pK\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: Invalid params dev = %pK, table = %pK",
 			(void *)iommu_cb_set.cb_info[idx].dev,
 			(void *)mapping_info->table);
-		pr_err("Error:dma_buf = %pK, attach = %pK\n",
+		CAM_ERR(CAM_SMMU, "Error:dma_buf = %pK, attach = %pK",
 			(void *)mapping_info->buf,
 			(void *)mapping_info->attach);
 		return -EINVAL;
 	}
 
 	if (mapping_info->region_id == CAM_SMMU_REGION_SHARED) {
-		CDBG("Removing SHARED buffer paddr = %pK, len = %zu\n",
+		CAM_DBG(CAM_SMMU,
+			"Removing SHARED buffer paddr = %pK, len = %zu",
 			(void *)mapping_info->paddr, mapping_info->len);
 
 		domain = iommu_cb_set.cb_info[idx].mapping->domain;
@@ -1261,8 +1288,8 @@
 			mapping_info->len);
 
 		if (size != mapping_info->len) {
-			pr_err("IOMMU unmap failed\n");
-			pr_err("Unmapped = %zu, requested = %zu\n",
+			CAM_ERR(CAM_SMMU, "IOMMU unmap failed");
+			CAM_ERR(CAM_SMMU, "Unmapped = %zu, requested = %zu",
 				size,
 				mapping_info->len);
 		}
@@ -1272,7 +1299,7 @@
 			iommu_cb_set.cb_info[idx].handle);
 
 		if (rc)
-			pr_err("IOVA free failed\n");
+			CAM_ERR(CAM_SMMU, "IOVA free failed");
 
 	} else if (mapping_info->region_id == CAM_SMMU_REGION_IO) {
 		msm_dma_unmap_sg(iommu_cb_set.cb_info[idx].dev,
@@ -1317,19 +1344,19 @@
 	int ret = 0;
 
 	if (!identifier) {
-		pr_err("Error: iommu hardware name is NULL\n");
+		CAM_ERR(CAM_SMMU, "Error: iommu hardware name is NULL");
 		return -EINVAL;
 	}
 
 	if (!handle_ptr) {
-		pr_err("Error: handle pointer is NULL\n");
+		CAM_ERR(CAM_SMMU, "Error: handle pointer is NULL");
 		return -EINVAL;
 	}
 
 	/* create and put handle in the table */
 	ret = cam_smmu_create_add_handle_in_table(identifier, handle_ptr);
 	if (ret < 0)
-		pr_err("Error: %s get handle fail\n", identifier);
+		CAM_ERR(CAM_SMMU, "Error: %s get handle fail", identifier);
 
 	return ret;
 }
@@ -1340,20 +1367,21 @@
 	int ret = 0, idx;
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: Index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU, "Error: Index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 		return -EINVAL;
@@ -1371,7 +1399,7 @@
 	case CAM_SMMU_VOTE:
 	case CAM_SMMU_DEVOTE:
 	default:
-		pr_err("Error: idx = %d, ops = %d\n", idx, ops);
+		CAM_ERR(CAM_SMMU, "Error: idx = %d, ops = %d", idx, ops);
 		ret = -EINVAL;
 	}
 	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
@@ -1396,10 +1424,10 @@
 	struct page *page;
 	struct sg_table *table = NULL;
 
-	CDBG("%s: nents = %lu, idx = %d, virt_len  = %zx\n",
-		__func__, nents, idx, virt_len);
-	CDBG("%s: phys_len = %zx, iommu_dir = %d, virt_addr = %pK\n",
-		__func__, phys_len, iommu_dir, virt_addr);
+	CAM_DBG(CAM_SMMU, "nents = %lu, idx = %d, virt_len  = %zx",
+		nents, idx, virt_len);
+	CAM_DBG(CAM_SMMU, "phys_len = %zx, iommu_dir = %d, virt_addr = %pK",
+		phys_len, iommu_dir, virt_addr);
 
 	/*
 	 * This table will go inside the 'mapping' structure
@@ -1435,7 +1463,8 @@
 		virt_len, &iova);
 
 	if (rc < 0) {
-		pr_err("Could not find valid iova for scratch buffer");
+		CAM_ERR(CAM_SMMU,
+			"Could not find valid iova for scratch buffer");
 		goto err_iommu_map;
 	}
 
@@ -1444,7 +1473,7 @@
 		table->sgl,
 		table->nents,
 		iommu_dir) != virt_len) {
-		pr_err("iommu_map_sg() failed");
+		CAM_ERR(CAM_SMMU, "iommu_map_sg() failed");
 		goto err_iommu_map;
 	}
 
@@ -1466,22 +1495,23 @@
 	mapping_info->phys_len = phys_len;
 	mapping_info->region_id = CAM_SMMU_REGION_SCRATCH;
 
-	CDBG("%s: paddr = %pK, len = %zx, phys_len = %zx",
-		__func__, (void *)mapping_info->paddr,
+	CAM_DBG(CAM_SMMU, "paddr = %pK, len = %zx, phys_len = %zx",
+		(void *)mapping_info->paddr,
 		mapping_info->len, mapping_info->phys_len);
 
 	list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list);
 
 	*virt_addr = (dma_addr_t)iova;
 
-	CDBG("%s: mapped virtual address = %lx\n", __func__,
+	CAM_DBG(CAM_SMMU, "mapped virtual address = %lx",
 		(unsigned long)*virt_addr);
 	return 0;
 
 err_mapping_info:
 	unmapped = iommu_unmap(domain, iova,  virt_len);
 	if (unmapped != virt_len)
-		pr_err("Unmapped only %zx instead of %zx", unmapped, virt_len);
+		CAM_ERR(CAM_SMMU, "Unmapped only %zx instead of %zx",
+			unmapped, virt_len);
 err_iommu_map:
 	__free_pages(page, get_order(phys_len));
 err_page_alloc:
@@ -1504,7 +1534,8 @@
 		&iommu_cb_set.cb_info[idx].scratch_map;
 
 	if (!mapping_info->table) {
-		pr_err("Error: Invalid params: dev = %pK, table = %pK",
+		CAM_ERR(CAM_SMMU,
+			"Error: Invalid params: dev = %pK, table = %pK",
 			(void *)iommu_cb_set.cb_info[idx].dev,
 			(void *)mapping_info->table);
 		return -EINVAL;
@@ -1513,14 +1544,15 @@
 	/* Clean up the mapping_info struct from the list */
 	unmapped = iommu_unmap(domain, mapping_info->paddr, mapping_info->len);
 	if (unmapped != mapping_info->len)
-		pr_err("Unmapped only %zx instead of %zx",
+		CAM_ERR(CAM_SMMU, "Unmapped only %zx instead of %zx",
 			unmapped, mapping_info->len);
 
 	rc = cam_smmu_free_scratch_va(scratch_map,
 		mapping_info->paddr,
 		mapping_info->len);
 	if (rc < 0) {
-		pr_err("Error: Invalid iova while freeing scratch buffer\n");
+		CAM_ERR(CAM_SMMU,
+			"Error: Invalid iova while freeing scratch buffer");
 		rc = -EINVAL;
 	}
 
@@ -1546,67 +1578,74 @@
 	unsigned int iommu_dir;
 
 	if (!paddr_ptr || !virt_len || !phys_len) {
-		pr_err("Error: Input pointer or lengths invalid\n");
+		CAM_ERR(CAM_SMMU, "Error: Input pointer or lengths invalid");
 		return -EINVAL;
 	}
 
 	if (virt_len < phys_len) {
-		pr_err("Error: virt_len > phys_len\n");
+		CAM_ERR(CAM_SMMU, "Error: virt_len > phys_len");
 		return -EINVAL;
 	}
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	iommu_dir = cam_smmu_translate_dir_to_iommu_dir(dir);
 	if (iommu_dir == IOMMU_INVALID_DIR) {
-		pr_err("Error: translate direction failed. dir = %d\n", dir);
+		CAM_ERR(CAM_SMMU,
+			"Error: translate direction failed. dir = %d", dir);
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		rc = -EINVAL;
 		goto error;
 	}
 
 	if (!iommu_cb_set.cb_info[idx].scratch_buf_support) {
-		pr_err("Error: Context bank does not support scratch bufs\n");
+		CAM_ERR(CAM_SMMU,
+			"Error: Context bank does not support scratch bufs");
 		rc = -EINVAL;
 		goto error;
 	}
 
-	CDBG("%s: smmu handle = %x, idx = %d, dir = %d\n",
-		__func__, handle, idx, dir);
-	CDBG("%s: virt_len = %zx, phys_len  = %zx\n",
-		__func__, phys_len, virt_len);
+	CAM_DBG(CAM_SMMU, "smmu handle = %x, idx = %d, dir = %d",
+		handle, idx, dir);
+	CAM_DBG(CAM_SMMU, "virt_len = %zx, phys_len  = %zx",
+		phys_len, virt_len);
 
 	if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
-		pr_err("Err:Dev %s should call SMMU attach before map buffer\n",
-				iommu_cb_set.cb_info[idx].name);
+		CAM_ERR(CAM_SMMU,
+			"Err:Dev %s should call SMMU attach before map buffer",
+			iommu_cb_set.cb_info[idx].name);
 		rc = -EINVAL;
 		goto error;
 	}
 
 	if (!IS_ALIGNED(virt_len, PAGE_SIZE)) {
-		pr_err("Requested scratch buffer length not page aligned\n");
+		CAM_ERR(CAM_SMMU,
+			"Requested scratch buffer length not page aligned");
 		rc = -EINVAL;
 		goto error;
 	}
 
 	if (!IS_ALIGNED(virt_len, phys_len)) {
-		pr_err("Requested virt length not aligned with phys length\n");
+		CAM_ERR(CAM_SMMU,
+			"Requested virt length not aligned with phys length");
 		rc = -EINVAL;
 		goto error;
 	}
@@ -1617,7 +1656,7 @@
 		iommu_dir,
 		paddr_ptr);
 	if (rc < 0)
-		pr_err("Error: mapping or add list fail\n");
+		CAM_ERR(CAM_SMMU, "Error: mapping or add list fail");
 
 error:
 	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
@@ -1632,28 +1671,31 @@
 	struct cam_dma_buff_info *mapping_info;
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	/* find index in the iommu_cb_set.cb_info */
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		rc = -EINVAL;
 		goto handle_err;
 	}
 
 	if (!iommu_cb_set.cb_info[idx].scratch_buf_support) {
-		pr_err("Error: Context bank does not support scratch buffers\n");
+		CAM_ERR(CAM_SMMU,
+			"Error: Context bank does not support scratch buffers");
 		rc = -EINVAL;
 		goto handle_err;
 	}
@@ -1663,7 +1705,7 @@
 	 */
 	mapping_info = cam_smmu_find_mapping_by_virt_address(idx, paddr);
 	if (!mapping_info) {
-		pr_err("Error: Invalid params\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid params");
 		rc = -ENODEV;
 		goto handle_err;
 	}
@@ -1671,7 +1713,7 @@
 	/* unmapping one buffer from device */
 	rc = cam_smmu_free_scratch_buffer_remove_from_list(mapping_info, idx);
 	if (rc < 0) {
-		pr_err("Error: unmap or remove list fail\n");
+		CAM_ERR(CAM_SMMU, "Error: unmap or remove list fail");
 		goto handle_err;
 	}
 
@@ -1698,12 +1740,12 @@
 	enum cam_smmu_buf_state buf_state;
 
 	if (!paddr_ptr || !len_ptr) {
-		pr_err("Input pointers are invalid\n");
+		CAM_ERR(CAM_SMMU, "Input pointers are invalid");
 		return -EINVAL;
 	}
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Invalid handle");
 		return -EINVAL;
 	}
 
@@ -1714,27 +1756,28 @@
 
 	dma_dir = cam_smmu_translate_dir(dir);
 	if (dma_dir == DMA_NONE) {
-		pr_err("translate direction failed. dir = %d\n", dir);
+		CAM_ERR(CAM_SMMU, "translate direction failed. dir = %d", dir);
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU, "handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU, "hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		rc = -EINVAL;
 		goto get_addr_end;
 	}
 
 	if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
-		pr_err("Err:Dev %s should call SMMU attach before map buffer\n",
+		CAM_ERR(CAM_SMMU,
+			"Err:Dev %s should call SMMU attach before map buffer",
 				iommu_cb_set.cb_info[idx].name);
 		rc = -EINVAL;
 		goto get_addr_end;
@@ -1743,15 +1786,16 @@
 	buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr,
 		len_ptr);
 	if (buf_state == CAM_SMMU_BUFF_EXIST) {
-		CDBG("ion_fd:%d already in the list, give same addr back",
-				 ion_fd);
+		CAM_ERR(CAM_SMMU,
+			"ion_fd:%d already in the list, give same addr back",
+			 ion_fd);
 		rc = -EALREADY;
 		goto get_addr_end;
 	}
 	rc = cam_smmu_map_buffer_and_add_to_list(idx, ion_fd, dma_dir,
 			paddr_ptr, len_ptr, region_id);
 	if (rc < 0)
-		pr_err("mapping or add list fail\n");
+		CAM_ERR(CAM_SMMU, "mapping or add list fail");
 
 get_addr_end:
 	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
@@ -1767,12 +1811,12 @@
 	enum cam_smmu_buf_state buf_state;
 
 	if (!paddr_ptr || !len_ptr) {
-		pr_err("Error: Input pointers are invalid\n");
+		CAM_ERR(CAM_SMMU, "Error: Input pointers are invalid");
 		return -EINVAL;
 	}
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
@@ -1782,14 +1826,16 @@
 
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		rc = -EINVAL;
 		goto get_addr_end;
@@ -1797,7 +1843,7 @@
 
 	buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr);
 	if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) {
-		CDBG("ion_fd:%d not in the mapped list", ion_fd);
+		CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd);
 		rc = -EINVAL;
 		goto get_addr_end;
 	}
@@ -1823,21 +1869,23 @@
 	struct cam_dma_buff_info *mapping_info;
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	/* find index in the iommu_cb_set.cb_info */
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		rc = -EINVAL;
 		goto unmap_end;
@@ -1846,17 +1894,17 @@
 	/* Based on ion fd and index, we can find mapping info of buffer */
 	mapping_info = cam_smmu_find_mapping_by_ion_index(idx, ion_fd);
 	if (!mapping_info) {
-		pr_err("Error: Invalid params! idx = %d, fd = %d\n",
+		CAM_ERR(CAM_SMMU, "Error: Invalid params idx = %d, fd = %d",
 			idx, ion_fd);
 		rc = -EINVAL;
 		goto unmap_end;
 	}
 
 	/* Unmapping one buffer from device */
-	CDBG("SMMU: removing buffer idx = %d\n", idx);
+	CAM_DBG(CAM_SMMU, "SMMU: removing buffer idx = %d", idx);
 	rc = cam_smmu_unmap_buf_and_remove_from_list(mapping_info, idx);
 	if (rc < 0)
-		pr_err("Error: unmap or remove list fail\n");
+		CAM_ERR(CAM_SMMU, "Error: unmap or remove list fail");
 
 unmap_end:
 	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
@@ -1871,21 +1919,23 @@
 	struct cam_dma_buff_info *mapping_info;
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	/* find index in the iommu_cb_set.cb_info */
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		rc = -EINVAL;
 		goto put_addr_end;
@@ -1894,7 +1944,7 @@
 	/* based on ion fd and index, we can find mapping info of buffer */
 	mapping_info = cam_smmu_find_mapping_by_ion_index(idx, ion_fd);
 	if (!mapping_info) {
-		pr_err("Error: Invalid params! idx = %d, fd = %d\n",
+		CAM_ERR(CAM_SMMU, "Error: Invalid params idx = %d, fd = %d",
 			idx, ion_fd);
 		rc = -EINVAL;
 		goto put_addr_end;
@@ -1911,27 +1961,29 @@
 	int idx;
 
 	if (handle == HANDLE_INIT) {
-		pr_err("Error: Invalid handle\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid handle");
 		return -EINVAL;
 	}
 
 	idx = GET_SMMU_TABLE_IDX(handle);
 	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
 			idx, handle);
 		return -EINVAL;
 	}
 
 	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
 	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+		CAM_ERR(CAM_SMMU,
+			"Error: hdl is not valid, table_hdl = %x, hdl = %x",
 			iommu_cb_set.cb_info[idx].handle, handle);
 		mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
 		return -EINVAL;
 	}
 
 	if (!list_empty_careful(&iommu_cb_set.cb_info[idx].smmu_buf_list)) {
-		pr_err("Client %s buffer list is not clean!\n",
+		CAM_ERR(CAM_SMMU, "Client %s buffer list is not clean",
 			iommu_cb_set.cb_info[idx].name);
 		cam_smmu_print_list(idx);
 		cam_smmu_clean_buffer_list(idx);
@@ -1981,7 +2033,7 @@
 	int rc = 0;
 
 	if (!cb || !dev) {
-		pr_err("Error: invalid input params\n");
+		CAM_ERR(CAM_SMMU, "Error: invalid input params");
 		return -EINVAL;
 	}
 
@@ -2001,12 +2053,13 @@
 			cb->shared_info.iova_len,
 			-1);
 
-		CDBG("Shared mem start->%lX\n",
+		CAM_DBG(CAM_SMMU, "Shared mem start->%lX",
 			(unsigned long)cb->shared_info.iova_start);
-		CDBG("Shared mem len->%zu\n", cb->shared_info.iova_len);
+		CAM_DBG(CAM_SMMU, "Shared mem len->%zu",
+			cb->shared_info.iova_len);
 
 		if (rc) {
-			pr_err("Genpool chunk creation failed\n");
+			CAM_ERR(CAM_SMMU, "Genpool chunk creation failed");
 			gen_pool_destroy(cb->shared_mem_pool);
 			cb->shared_mem_pool = NULL;
 			return rc;
@@ -2019,7 +2072,8 @@
 			cb->scratch_info.iova_len,
 			0);
 		if (rc < 0) {
-			pr_err("Error: failed to create scratch map\n");
+			CAM_ERR(CAM_SMMU,
+				"Error: failed to create scratch map");
 			rc = -ENODEV;
 			goto end;
 		}
@@ -2030,12 +2084,12 @@
 		cb->mapping = arm_iommu_create_mapping(&platform_bus_type,
 			cb->io_info.iova_start, cb->io_info.iova_len);
 		if (IS_ERR(cb->mapping)) {
-			pr_err("Error: create mapping Failed\n");
+			CAM_ERR(CAM_SMMU, "Error: create mapping Failed");
 			rc = -ENODEV;
 			goto end;
 		}
 	} else {
-		pr_err("Context bank does not have IO region\n");
+		CAM_ERR(CAM_SMMU, "Context bank does not have IO region");
 		rc = -ENODEV;
 		goto end;
 	}
@@ -2060,7 +2114,7 @@
 	struct device_node *domains_child_node = NULL;
 
 	if (!dev) {
-		pr_err("Error: Invalid device\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid device");
 		return -ENODEV;
 	}
 
@@ -2078,7 +2132,7 @@
 	}
 
 	if (iommu_cb_set.cb_num == 0) {
-		pr_err("Error: no context banks present\n");
+		CAM_ERR(CAM_SMMU, "Error: no context banks present");
 		return -ENOENT;
 	}
 
@@ -2088,14 +2142,14 @@
 		GFP_KERNEL);
 
 	if (!iommu_cb_set.cb_info) {
-		pr_err("Error: cannot allocate context banks\n");
+		CAM_ERR(CAM_SMMU, "Error: cannot allocate context banks");
 		return -ENOMEM;
 	}
 
 	cam_smmu_reset_iommu_table(CAM_SMMU_TABLE_INIT);
 	iommu_cb_set.cb_init_count = 0;
 
-	CDBG("no of context banks :%d\n", iommu_cb_set.cb_num);
+	CAM_DBG(CAM_SMMU, "no of context banks :%d", iommu_cb_set.cb_num);
 	return 0;
 }
 
@@ -2109,13 +2163,13 @@
 	int num_regions = 0;
 
 	if (!of_node || !cb) {
-		pr_err("Invalid argument(s)\n");
+		CAM_ERR(CAM_SMMU, "Invalid argument(s)");
 		return -EINVAL;
 	}
 
 	mem_map_node = of_get_child_by_name(of_node, "iova-mem-map");
 	if (!mem_map_node) {
-		pr_err("iova-mem-map not present\n");
+		CAM_ERR(CAM_SMMU, "iova-mem-map not present");
 		return -EINVAL;
 	}
 
@@ -2129,7 +2183,7 @@
 			"iova-region-name", &region_name);
 		if (rc < 0) {
 			of_node_put(mem_map_node);
-			pr_err("IOVA region not found\n");
+			CAM_ERR(CAM_SMMU, "IOVA region not found");
 			return -EINVAL;
 		}
 
@@ -2137,7 +2191,7 @@
 			"iova-region-start", &region_start);
 		if (rc < 0) {
 			of_node_put(mem_map_node);
-			pr_err("Failed to read iova-region-start\n");
+			CAM_ERR(CAM_SMMU, "Failed to read iova-region-start");
 			return -EINVAL;
 		}
 
@@ -2145,7 +2199,7 @@
 			"iova-region-len", &region_len);
 		if (rc < 0) {
 			of_node_put(mem_map_node);
-			pr_err("Failed to read iova-region-len\n");
+			CAM_ERR(CAM_SMMU, "Failed to read iova-region-len");
 			return -EINVAL;
 		}
 
@@ -2153,7 +2207,7 @@
 			"iova-region-id", &region_id);
 		if (rc < 0) {
 			of_node_put(mem_map_node);
-			pr_err("Failed to read iova-region-id\n");
+			CAM_ERR(CAM_SMMU, "Failed to read iova-region-id");
 			return -EINVAL;
 		}
 
@@ -2179,20 +2233,22 @@
 			cb->io_info.iova_len = region_len;
 			break;
 		default:
-			pr_err("Incorrect region id present in DT file: %d\n",
+			CAM_ERR(CAM_SMMU,
+				"Incorrect region id present in DT file: %d",
 				region_id);
 		}
 
-		CDBG("Found label -> %s\n", cb->name);
-		CDBG("Found region -> %s\n", region_name);
-		CDBG("region_start -> %X\n", region_start);
-		CDBG("region_len -> %X\n", region_len);
-		CDBG("region_id -> %X\n", region_id);
+		CAM_DBG(CAM_SMMU, "Found label -> %s", cb->name);
+		CAM_DBG(CAM_SMMU, "Found region -> %s", region_name);
+		CAM_DBG(CAM_SMMU, "region_start -> %X", region_start);
+		CAM_DBG(CAM_SMMU, "region_len -> %X", region_len);
+		CAM_DBG(CAM_SMMU, "region_id -> %X", region_id);
 	}
 	of_node_put(mem_map_node);
 
 	if (!num_regions) {
-		pr_err("No memory regions found, at least one needed\n");
+		CAM_ERR(CAM_SMMU,
+			"No memory regions found, at least one needed");
 		rc = -ENODEV;
 	}
 
@@ -2207,13 +2263,13 @@
 	struct device *ctx = NULL;
 
 	if (!dev) {
-		pr_err("Error: Invalid device\n");
+		CAM_ERR(CAM_SMMU, "Error: Invalid device");
 		return -ENODEV;
 	}
 
 	/* check the bounds */
 	if (iommu_cb_set.cb_init_count >= iommu_cb_set.cb_num) {
-		pr_err("Error: populate more than allocated cb\n");
+		CAM_ERR(CAM_SMMU, "Error: populate more than allocated cb");
 		rc = -EBADHANDLE;
 		goto cb_init_fail;
 	}
@@ -2224,29 +2280,31 @@
 	/* set the name of the context bank */
 	rc = of_property_read_string(dev->of_node, "label", &cb->name);
 	if (rc < 0) {
-		pr_err("Error: failed to read label from sub device\n");
+		CAM_ERR(CAM_SMMU,
+			"Error: failed to read label from sub device");
 		goto cb_init_fail;
 	}
 
 	rc = cam_smmu_get_memory_regions_info(dev->of_node,
 		cb);
 	if (rc < 0) {
-		pr_err("Error: Getting region info\n");
+		CAM_ERR(CAM_SMMU, "Error: Getting region info");
 		return rc;
 	}
 
 	/* set up the iommu mapping for the  context bank */
 	if (type == CAM_QSMMU) {
-		pr_err("Error: QSMMU ctx not supported for : %s\n", cb->name);
+		CAM_ERR(CAM_SMMU, "Error: QSMMU ctx not supported for : %s",
+			cb->name);
 		return -ENODEV;
 	}
 
 	ctx = dev;
-	CDBG("getting Arm SMMU ctx : %s\n", cb->name);
+	CAM_DBG(CAM_SMMU, "getting Arm SMMU ctx : %s", cb->name);
 
 	rc = cam_smmu_setup_cb(cb, ctx);
 	if (rc < 0) {
-		pr_err("Error: failed to setup cb : %s\n", cb->name);
+		CAM_ERR(CAM_SMMU, "Error: failed to setup cb : %s", cb->name);
 		goto cb_init_fail;
 	}
 
@@ -2258,7 +2316,7 @@
 	/* increment count to next bank */
 	iommu_cb_set.cb_init_count++;
 
-	CDBG("X: cb init count :%d\n", iommu_cb_set.cb_init_count);
+	CAM_DBG(CAM_SMMU, "X: cb init count :%d", iommu_cb_set.cb_init_count);
 
 cb_init_fail:
 	return rc;
@@ -2272,14 +2330,14 @@
 	if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu")) {
 		rc = cam_alloc_smmu_context_banks(dev);
 		if (rc < 0) {
-			pr_err("Error: allocating context banks\n");
+			CAM_ERR(CAM_SMMU, "Error: allocating context banks");
 			return -ENOMEM;
 		}
 	}
 	if (of_device_is_compatible(dev->of_node, "qcom,msm-cam-smmu-cb")) {
 		rc = cam_populate_smmu_context_banks(dev, CAM_ARM_SMMU);
 		if (rc < 0) {
-			pr_err("Error: populating context banks\n");
+			CAM_ERR(CAM_SMMU, "Error: populating context banks");
 			return -ENOMEM;
 		}
 		return rc;
@@ -2287,7 +2345,7 @@
 	if (of_device_is_compatible(dev->of_node, "qcom,qsmmu-cam-cb")) {
 		rc = cam_populate_smmu_context_banks(dev, CAM_QSMMU);
 		if (rc < 0) {
-			pr_err("Error: populating context banks\n");
+			CAM_ERR(CAM_SMMU, "Error: populating context banks");
 			return -ENOMEM;
 		}
 		return rc;
@@ -2304,7 +2362,7 @@
 	rc = of_platform_populate(pdev->dev.of_node, msm_cam_smmu_dt_match,
 				NULL, &pdev->dev);
 	if (rc < 0) {
-		pr_err("Error: populating devices\n");
+		CAM_ERR(CAM_SMMU, "Error: populating devices");
 	} else {
 		INIT_WORK(&iommu_cb_set.smmu_work, cam_smmu_page_fault_work);
 		mutex_init(&iommu_cb_set.payload_list_lock);
diff --git a/drivers/media/platform/msm/camera/cam_sync/Makefile b/drivers/media/platform/msm/camera/cam_sync/Makefile
index e3012cb..8e884ca 100644
--- a/drivers/media/platform/msm/camera/cam_sync/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sync/Makefile
@@ -1 +1,3 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_sync.o cam_sync_util.o
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index 96f40e1..644cb63 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-SYNC %s:%d " fmt, __func__, __LINE__
-
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/irqflags.h>
@@ -19,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/debugfs.h>
 #include "cam_sync_util.h"
+#include "cam_debug_util.h"
 
 struct sync_device *sync_dev;
 
@@ -35,7 +34,8 @@
 
 	rc = cam_sync_init_object(sync_dev->sync_table, idx, name);
 	if (rc) {
-		pr_err("Error: Unable to init row at idx = %ld\n", idx);
+		CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld",
+			idx);
 		spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
 		return -EINVAL;
 	}
@@ -62,7 +62,8 @@
 	row = sync_dev->sync_table + sync_obj;
 
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj %d",
 			sync_obj);
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
 		return -EINVAL;
@@ -124,7 +125,8 @@
 	row = sync_dev->sync_table + sync_obj;
 
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj = %d",
 			sync_obj);
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
 		return -EINVAL;
@@ -157,12 +159,14 @@
 	/* Objects to be signaled will be added into this list */
 	INIT_LIST_HEAD(&sync_list);
 
-	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0)
+	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) {
+		CAM_ERR(CAM_SYNC, "Error: Out of range sync obj");
 		return -EINVAL;
-
+	}
 	row = sync_dev->sync_table + sync_obj;
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj = %d",
 			sync_obj);
 		return -EINVAL;
 	}
@@ -170,14 +174,15 @@
 	spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]);
 	if (row->type == CAM_SYNC_TYPE_GROUP) {
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-		pr_err("Error: Signaling a GROUP sync object = %d\n",
+		CAM_ERR(CAM_SYNC, "Error: Signaling a GROUP sync object = %d",
 			sync_obj);
 		return -EINVAL;
 	}
 
 	if (row->state != CAM_SYNC_STATE_ACTIVE) {
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-		pr_err("Error: Sync object already signaled sync_obj = %d",
+		CAM_ERR(CAM_SYNC,
+			"Error: Sync object already signaled sync_obj = %d",
 			sync_obj);
 		return -EALREADY;
 	}
@@ -185,7 +190,8 @@
 	if (status != CAM_SYNC_STATE_SIGNALED_SUCCESS &&
 		status != CAM_SYNC_STATE_SIGNALED_ERROR) {
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-		pr_err("Error: signaling with undefined status = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: signaling with undefined status = %d",
 			status);
 		return -EINVAL;
 	}
@@ -297,18 +303,20 @@
 	rc = cam_sync_util_validate_merge(sync_obj,
 		num_objs);
 	if (rc < 0) {
-		pr_err("Validation failed, Merge not allowed");
+		CAM_ERR(CAM_SYNC, "Validation failed, Merge not allowed");
 		return -EINVAL;
 	}
 
 	rc = cam_sync_util_find_and_set_empty_row(sync_dev, &idx);
 	if (rc < 0) {
-		pr_err("Error: Unable to find empty row, table full");
+		CAM_ERR(CAM_SYNC,
+			"Error: Unable to find empty row, table full");
 		return -EINVAL;
 	}
 
 	if (idx <= 0 || idx >= CAM_SYNC_MAX_OBJS) {
-		pr_err("Error: Invalid empty row index returned = %ld", idx);
+		CAM_ERR(CAM_SYNC,
+			"Error: Invalid empty row index returned = %ld", idx);
 		return -EINVAL;
 	}
 
@@ -317,7 +325,8 @@
 		num_objs);
 
 	if (rc < 0) {
-		pr_err("Error: Unable to init row at idx = %ld\n", idx);
+		CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld",
+			idx);
 		return -EINVAL;
 	}
 
@@ -335,7 +344,8 @@
 
 	row = sync_dev->sync_table + sync_obj;
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj: idx = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj: idx = %d",
 			sync_obj);
 		return -EINVAL;
 	}
@@ -356,7 +366,8 @@
 	row = sync_dev->sync_table + sync_obj;
 
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj = %d",
 			sync_obj);
 		return -EINVAL;
 	}
@@ -365,15 +376,16 @@
 		msecs_to_jiffies(timeout_ms));
 
 	if (!timeleft) {
-		pr_err("Error: cam_sync_wait() timed out for sync obj = %d\n",
-			sync_obj);
+		CAM_ERR(CAM_SYNC,
+			"Error: timed out for sync obj = %d", sync_obj);
 		rc = -ETIMEDOUT;
 	} else {
 		switch (row->state) {
 		case CAM_SYNC_STATE_INVALID:
 		case CAM_SYNC_STATE_ACTIVE:
 		case CAM_SYNC_STATE_SIGNALED_ERROR:
-			pr_err("Error: Wait on invalid state = %d, obj = %d\n",
+			CAM_ERR(CAM_SYNC,
+				"Error: Wait on invalid state = %d, obj = %d",
 				row->state, sync_obj);
 			rc = -EINVAL;
 			break;
@@ -566,7 +578,8 @@
 	row =  sync_dev->sync_table + sync_obj;
 
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj = %d",
 			sync_obj);
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
 		kfree(user_payload_kernel);
@@ -616,12 +629,12 @@
 	struct sync_table_row *row = NULL;
 
 	if (k_ioctl->size != sizeof(struct cam_sync_userpayload_info)) {
-		CDBG("Incorrect ioctl size\n");
+		CAM_ERR(CAM_SYNC, "Incorrect ioctl size");
 		return -EINVAL;
 	}
 
 	if (!k_ioctl->ioctl_ptr) {
-		CDBG("Invalid embedded ioctl ptr\n");
+		CAM_ERR(CAM_SYNC, "Invalid embedded ioctl ptr");
 		return -EINVAL;
 	}
 
@@ -638,7 +651,8 @@
 	row =  sync_dev->sync_table + sync_obj;
 
 	if (row->state == CAM_SYNC_STATE_INVALID) {
-		pr_err("Error: accessing an uninitialized sync obj = %d\n",
+		CAM_ERR(CAM_SYNC,
+			"Error: accessing an uninitialized sync obj = %d",
 			sync_obj);
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
 		return -EINVAL;
@@ -667,7 +681,7 @@
 	struct cam_private_ioctl_arg k_ioctl;
 
 	if (!sync_dev) {
-		pr_err("%s sync_dev NULL\n", __func__);
+		CAM_ERR(CAM_SYNC, "sync_dev NULL");
 		return -EINVAL;
 	}
 
@@ -735,7 +749,7 @@
 	struct sync_device *sync_dev = video_drvdata(filep);
 
 	if (!sync_dev) {
-		pr_err("%s Sync device NULL\n", __func__);
+		CAM_ERR(CAM_SYNC, "Sync device NULL");
 		return -ENODEV;
 	}
 
@@ -752,7 +766,7 @@
 		sync_dev->cam_sync_eventq = filep->private_data;
 		spin_unlock_bh(&sync_dev->cam_sync_eventq_lock);
 	} else {
-		pr_err("v4l2_fh_open failed : %d\n", rc);
+		CAM_ERR(CAM_SYNC, "v4l2_fh_open failed : %d", rc);
 	}
 	mutex_unlock(&sync_dev->table_lock);
 
@@ -766,7 +780,7 @@
 	struct sync_device *sync_dev = video_drvdata(filep);
 
 	if (!sync_dev) {
-		pr_err("%s Sync device NULL\n", __func__);
+		CAM_ERR(CAM_SYNC, "Sync device NULL");
 		rc = -ENODEV;
 		return rc;
 	}
@@ -784,11 +798,13 @@
 			 */
 			rc = cam_sync_signal(i, CAM_SYNC_STATE_SIGNALED_ERROR);
 			if (rc < 0)
-				pr_err("Cleanup signal failed: idx = %d\n", i);
+				CAM_ERR(CAM_SYNC,
+					"Cleanup signal failed: idx = %d", i);
 
 			rc = cam_sync_destroy(i);
 			if (rc < 0)
-				pr_err("Cleanup destroy failed: idx = %d\n", i);
+				CAM_ERR(CAM_SYNC,
+					"Cleanup destroy failed: idx = %d", i);
 		}
 	}
 	mutex_unlock(&sync_dev->table_lock);
@@ -951,7 +967,8 @@
 		WQ_HIGHPRI | WQ_UNBOUND, 0);
 
 	if (!sync_dev->work_queue) {
-		pr_err("Error: high priority work queue creation failed!\n");
+		CAM_ERR(CAM_SYNC,
+			"Error: high priority work queue creation failed");
 		rc = -ENOMEM;
 		goto v4l2_fail;
 	}
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index 3b3cbff..c62aacf 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "CAM-SYNC-UTIL %s:%d " fmt, __func__, __LINE__
-
 #include "cam_sync_util.h"
 
 int cam_sync_util_find_and_set_empty_row(struct sync_device *sync_dev,
@@ -85,7 +83,8 @@
 			active_count++;
 			break;
 		default:
-			pr_err("Invalid state of child object during merge\n");
+			CAM_ERR(CAM_SYNC,
+				"Invalid state of child object during merge");
 			return CAM_SYNC_STATE_SIGNALED_ERROR;
 		}
 	}
@@ -256,7 +255,7 @@
 	struct sync_table_row *row = NULL;
 
 	if (num_objs <= 1) {
-		pr_err("Single object merge is not allowed\n");
+		CAM_ERR(CAM_SYNC, "Single object merge is not allowed");
 		return -EINVAL;
 	}
 
@@ -265,7 +264,8 @@
 		spin_lock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
 		if (row->type == CAM_SYNC_TYPE_GROUP ||
 			row->state == CAM_SYNC_STATE_INVALID) {
-			pr_err("Group obj %d can't be merged or obj UNINIT\n",
+			CAM_ERR(CAM_SYNC,
+				"Group obj %d can't be merged or obj UNINIT",
 				sync_obj[i]);
 			spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
 			return -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
index 9dedd14..8b60ce1 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
@@ -16,6 +16,7 @@
 
 #include <cam_sync_api.h>
 #include "cam_sync_private.h"
+#include "cam_debug_util.h"
 
 extern struct sync_device *sync_dev;
 
diff --git a/drivers/media/platform/msm/camera/cam_utils/Makefile b/drivers/media/platform/msm/camera/cam_utils/Makefile
index 370651f..4702963 100644
--- a/drivers/media/platform/msm/camera/cam_utils/Makefile
+++ b/drivers/media/platform/msm/camera/cam_utils/Makefile
@@ -2,4 +2,4 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr/
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o cam_common_util.o
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_common_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.c
new file mode 100644
index 0000000..199d3ea
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.c
@@ -0,0 +1,35 @@
+/* Copyright (c) 2017, 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/string.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+#include "cam_common_util.h"
+#include "cam_debug_util.h"
+
+int cam_common_util_get_string_index(const char **strings,
+	uint32_t num_strings, char *matching_string, uint32_t *index)
+{
+	int i;
+
+	for (i = 0; i < num_strings; i++) {
+		if (strnstr(strings[i], matching_string, strlen(strings[i]))) {
+			CAM_DBG(CAM_UTIL, "matched %s : %d\n",
+				matching_string, i);
+			*index = i;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h
new file mode 100644
index 0000000..d6a11b7
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2017, 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 _CAM_COMMON_UTIL_H_
+#define _CAM_COMMON_UTIL_H_
+
+#define CAM_BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift)
+
+/**
+ * cam_common_util_get_string_index()
+ *
+ * @brief                  Match the string from list of strings to return
+ *                         matching index
+ *
+ * @strings:               Pointer to list of strings
+ * @num_strings:           Number of strings in 'strings'
+ * @matching_string:       String to match
+ * @index:                 Pointer to index to return matching index
+ *
+ * @return:                0 for success
+ *                         -EINVAL for Fail
+ */
+int cam_common_util_get_string_index(const char **strings,
+	uint32_t num_strings, char *matching_string, uint32_t *index);
+
+#endif /* _CAM_COMMON_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
index eb5e7d8..21f90ca 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
@@ -11,9 +11,14 @@
  */
 
 #include <linux/io.h>
+#include <linux/module.h>
+
 #include "cam_debug_util.h"
 
-static const char *cam_debug_module_id_to_name(unsigned int module_id)
+static uint debug_mdl;
+module_param(debug_mdl, uint, 0644);
+
+const char *cam_get_module_name(unsigned int module_id)
 {
 	const char *name = NULL;
 
@@ -57,6 +62,27 @@
 	case CAM_FLASH:
 		name = "CAM-FLASH";
 		break;
+	case CAM_ACTUATOR:
+		name = "CAM-ACTUATOR";
+		break;
+	case CAM_CCI:
+		name = "CAM-CCI";
+		break;
+	case CAM_CSIPHY:
+		name = "CAM-CSIPHY";
+		break;
+	case CAM_EEPROM:
+		name = "CAM-EEPROM";
+		break;
+	case CAM_UTIL:
+		name = "CAM-UTIL";
+		break;
+	case CAM_CTXT:
+		name = "CAM-CTXT";
+		break;
+	case CAM_HFI:
+		name = "CAM-HFI";
+		break;
 	default:
 		name = "CAM";
 		break;
@@ -69,31 +95,37 @@
 	const char *func, const int line, const char *fmt, ...)
 {
 	char str_buffer[STR_BUFFER_MAX_LENGTH];
-	const char *module_name;
 	va_list args;
 
 	va_start(args, fmt);
-	vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args);
-	va_end(args);
-
-	module_name = cam_debug_module_id_to_name(module_id);
 
 	switch (dbg_level) {
-	case CAM_LEVEL_INFO:
-		pr_info("CAM_INFO: %s: %s: %d: %s\n",
-			module_name, func, line, str_buffer);
-		break;
-	case CAM_LEVEL_WARN:
-		pr_warn("CAM_WARN: %s: %s: %d: %s\n",
-			module_name, func, line, str_buffer);
+	case CAM_LEVEL_DBG:
+		if (debug_mdl & module_id) {
+			vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args);
+			pr_info("CAM_DBG: %s: %s: %d: %s\n",
+				cam_get_module_name(module_id),
+				func, line, str_buffer);
+			va_end(args);
+		}
 		break;
 	case CAM_LEVEL_ERR:
+		vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args);
 		pr_err("CAM_ERR: %s: %s: %d: %s\n",
-			module_name, func, line, str_buffer);
+			cam_get_module_name(module_id), func, line, str_buffer);
+		va_end(args);
 		break;
-	case CAM_LEVEL_DBG:
-		pr_info("CAM_DBG: %s: %s: %d: %s\n",
-			module_name, func, line, str_buffer);
+	case CAM_LEVEL_INFO:
+		vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args);
+		pr_info("CAM_INFO: %s: %s: %d: %s\n",
+			cam_get_module_name(module_id), func, line, str_buffer);
+		va_end(args);
+		break;
+	case CAM_LEVEL_WARN:
+		vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args);
+		pr_warn("CAM_WARN: %s: %s: %d: %s\n",
+			cam_get_module_name(module_id), func, line, str_buffer);
+		va_end(args);
 		break;
 	default:
 		break;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
index 34adb0e..7275d56 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
@@ -13,22 +13,28 @@
 #ifndef _CAM_DEBUG_UTIL_H_
 #define _CAM_DEBUG_UTIL_H_
 
-#define CAM_CDM    (1 << 0)
-#define CAM_CORE   (1 << 1)
-#define CAM_CPAS   (1 << 2)
-#define CAM_ISP    (1 << 3)
-#define CAM_CRM    (1 << 4)
-#define CAM_SENSOR (1 << 5)
-#define CAM_SMMU   (1 << 6)
-#define CAM_SYNC   (1 << 7)
-#define CAM_ICP    (1 << 8)
-#define CAM_JPEG   (1 << 9)
-#define CAM_FD     (1 << 10)
-#define CAM_LRME   (1 << 11)
-#define CAM_FLASH  (1 << 12)
+#define CAM_CDM        (1 << 0)
+#define CAM_CORE       (1 << 1)
+#define CAM_CPAS       (1 << 2)
+#define CAM_ISP        (1 << 3)
+#define CAM_CRM        (1 << 4)
+#define CAM_SENSOR     (1 << 5)
+#define CAM_SMMU       (1 << 6)
+#define CAM_SYNC       (1 << 7)
+#define CAM_ICP        (1 << 8)
+#define CAM_JPEG       (1 << 9)
+#define CAM_FD         (1 << 10)
+#define CAM_LRME       (1 << 11)
+#define CAM_FLASH      (1 << 12)
+#define CAM_ACTUATOR   (1 << 13)
+#define CAM_CCI        (1 << 14)
+#define CAM_CSIPHY     (1 << 15)
+#define CAM_EEPROM     (1 << 16)
+#define CAM_UTIL       (1 << 17)
+#define CAM_HFI        (1 << 18)
+#define CAM_CTXT       (1 << 19)
 
 #define STR_BUFFER_MAX_LENGTH  1024
-#define GROUP                  0x0000
 
 enum cam_debug_level {
 	CAM_LEVEL_INFO,
@@ -40,61 +46,61 @@
 /*
  *  cam_debug_log()
  *
- * @brief:        Get the Module name form module ID and print
- *                respective debug logs
+ * @brief     :  Get the Module name from module ID and print
+ *               respective debug logs
  *
  * @module_id :  Respective Module ID which is calling this function
  * @dbg_level :  Debug level from cam_module_debug_level enum entries
- * @func :       Function which is calling to print logs
- * @line :       Line number associated with the function which is calling
+ * @func      :  Function which is calling to print logs
+ * @line      :  Line number associated with the function which is calling
  *               to print log
- * @fmt  :       Formatted string which needs to be print in the log
+ * @fmt       :  Formatted string which needs to be print in the log
  *
  */
 void cam_debug_log(unsigned int module_id, enum cam_debug_level dbg_level,
 	const char *func, const int line, const char *fmt, ...);
 
 /*
+ * cam_get_module_name()
+ *
+ * @brief     :  Get the module name from module ID
+ *
+ * @module_id :  Module ID which is using this function
+ */
+const char *cam_get_module_name(unsigned int module_id);
+
+/*
  * CAM_ERR
- * @brief :     This Macro will print error logs
+ * @brief    :  This Macro will print error logs
  *
  * @__module :  Respective module id which is been calling this Macro
- * @fmt :       Formatted string which needs to be print in log
- * @args:       Arguments which needs to be print in log
+ * @fmt      :  Formatted string which needs to be print in log
+ * @args     :  Arguments which needs to be print in log
  */
 #define CAM_ERR(__module, fmt, args...)                            \
-	{                                                          \
-		cam_debug_log(__module, CAM_LEVEL_ERR,             \
-			__func__, __LINE__, fmt, ##args);          \
-	}
+	cam_debug_log(__module, CAM_LEVEL_ERR, __func__, __LINE__, fmt, ##args)
 
 /*
  * CAM_WARN
- * @brief :     This Macro will print warning logs
+ * @brief    :  This Macro will print warning logs
  *
  * @__module :  Respective module id which is been calling this Macro
  * @fmt      :  Formatted string which needs to be print in log
  * @args     :  Arguments which needs to be print in log
  */
 #define CAM_WARN(__module, fmt, args...)                           \
-	{                                                          \
-		cam_debug_log(__module, CAM_LEVEL_WARN,            \
-			__func__, __LINE__, fmt, ##args);          \
-	}
+	cam_debug_log(__module, CAM_LEVEL_WARN, __func__, __LINE__, fmt, ##args)
 
 /*
  * CAM_INFO
- * @brief :     This Macro will print Information logs
+ * @brief    :  This Macro will print Information logs
  *
  * @__module :  Respective module id which is been calling this Macro
  * @fmt      :  Formatted string which needs to be print in log
  * @args     :  Arguments which needs to be print in log
  */
 #define CAM_INFO(__module, fmt, args...)                           \
-	{                                                          \
-		cam_debug_log(__module, CAM_LEVEL_INFO,            \
-			__func__, __LINE__, fmt, ##args);          \
-	}
+	cam_debug_log(__module, CAM_LEVEL_INFO, __func__, __LINE__, fmt, ##args)
 
 /*
  * CAM_DBG
@@ -105,11 +111,14 @@
  * @args     :  Arguments which needs to be print in log
  */
 #define CAM_DBG(__module, fmt, args...)                            \
-	do {                                                       \
-		if (GROUP & __module) {                            \
-			cam_debug_log(__module, CAM_LEVEL_DBG,     \
-				__func__, __LINE__, fmt, ##args);  \
-		}                                                  \
-	} while (0)
+	cam_debug_log(__module, CAM_LEVEL_DBG, __func__, __LINE__, fmt, ##args)
+
+/*
+ * CAM_ERR_RATE_LIMIT
+ * @brief :     This Macro will prevent error print logs with ratelimit
+ */
+#define CAM_ERR_RATE_LIMIT(__module, fmt, args...)                 \
+	pr_err_ratelimited("CAM_ERR: %s: %s: %d\n" fmt,            \
+		cam_get_module_name(__module), __func__,  __LINE__, ##args)
 
 #endif /* _CAM_DEBUG_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
index 78cd9d8..c1fbb2a 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
@@ -10,22 +10,18 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include "cam_io_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 int cam_io_w(uint32_t data, void __iomem *addr)
 {
 	if (!addr)
 		return -EINVAL;
 
-	CDBG("0x%pK %08x\n", addr, data);
+	CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
 	writel_relaxed(data, addr);
 
 	return 0;
@@ -36,7 +32,7 @@
 	if (!addr)
 		return -EINVAL;
 
-	CDBG("0x%pK %08x\n", addr, data);
+	CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
 	/* Ensure previous writes are done */
 	wmb();
 	writel_relaxed(data, addr);
@@ -49,12 +45,12 @@
 	uint32_t data;
 
 	if (!addr) {
-		pr_err("Invalid args\n");
+		CAM_ERR(CAM_UTIL, "Invalid args");
 		return 0;
 	}
 
 	data = readl_relaxed(addr);
-	CDBG("0x%pK %08x\n", addr, data);
+	CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
 
 	return data;
 }
@@ -64,14 +60,14 @@
 	uint32_t data;
 
 	if (!addr) {
-		pr_err("Invalid args\n");
+		CAM_ERR(CAM_UTIL, "Invalid args");
 		return 0;
 	}
 
 	/* Ensure previous read is done */
 	rmb();
 	data = readl_relaxed(addr);
-	CDBG("0x%pK %08x\n", addr, data);
+	CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
 
 	return data;
 }
@@ -86,10 +82,10 @@
 	if (!dest_addr || !src_addr)
 		return -EINVAL;
 
-	CDBG("%pK %pK %d\n", dest_addr, src_addr, len);
+	CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len);
 
 	for (i = 0; i < len/4; i++) {
-		CDBG("0x%pK %08x\n", d, *s);
+		CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s);
 		writel_relaxed(*s++, d++);
 	}
 
@@ -106,7 +102,7 @@
 	if (!dest_addr || !src_addr)
 		return -EINVAL;
 
-	CDBG("%pK %pK %d\n", dest_addr, src_addr, len);
+	CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len);
 
 	/*
 	 * Do not use cam_io_w_mb to avoid double wmb() after a write
@@ -114,7 +110,7 @@
 	 */
 	wmb();
 	for (i = 0; i < (len / 4); i++) {
-		CDBG("0x%pK %08x\n", d, *s);
+		CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s);
 		writel_relaxed(*s++, d++);
 	}
 
@@ -138,7 +134,7 @@
 	}
 
 	if (cnt > retry) {
-		pr_debug("Poll failed by value\n");
+		CAM_DBG(CAM_UTIL, "Poll failed by value");
 		rc = -EINVAL;
 	}
 
@@ -163,7 +159,7 @@
 	}
 
 	if (cnt > retry) {
-		pr_debug("Poll failed with mask\n");
+		CAM_DBG(CAM_UTIL, "Poll failed with mask");
 		rc = -EINVAL;
 	}
 
@@ -179,7 +175,7 @@
 		return -EINVAL;
 
 	for (i = 0; i < len; i++) {
-		CDBG("i= %d len =%d val=%x addr =%pK\n",
+		CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK",
 			i, len, data[i], addr);
 		writel_relaxed(data[i], addr);
 	}
@@ -196,7 +192,7 @@
 		return -EINVAL;
 
 	for (i = 0; i < len; i++) {
-		CDBG("i= %d len =%d val=%x addr =%pK\n",
+		CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK",
 			i, len, data[i], addr);
 		/* Ensure previous writes are done */
 		wmb();
@@ -217,7 +213,7 @@
 		return -EINVAL;
 
 	for (i = 0; i < len; i++) {
-		CDBG("i= %d len =%d val=%x addr_base =%pK reg=%x\n",
+		CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x",
 			i, len, __VAL(i), addr_base, __OFFSET(i));
 		writel_relaxed(__VAL(i), addr_base + __OFFSET(i));
 	}
@@ -236,7 +232,7 @@
 	/* Ensure write is done */
 	wmb();
 	for (i = 0; i < len; i++) {
-		CDBG("i= %d len =%d val=%x addr_base =%pK reg=%x\n",
+		CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x",
 			i, len, __VAL(i), addr_base, __OFFSET(i));
 		writel_relaxed(__VAL(i), addr_base + __OFFSET(i));
 	}
@@ -254,7 +250,8 @@
 	int           i;
 	uint32_t      data;
 
-	CDBG("addr=%pK offset=0x%x size=%d\n", base_addr, start_offset, size);
+	CAM_DBG(CAM_UTIL, "addr=%pK offset=0x%x size=%d",
+		base_addr, start_offset, size);
 
 	if (!base_addr || (size <= 0))
 		return -EINVAL;
@@ -265,19 +262,19 @@
 		if (i % NUM_REGISTER_PER_LINE == 0) {
 			snprintf(p_str, 12, "0x%08x: ",
 				REG_OFFSET(start_offset, i));
-			p_str += 12;
+			p_str += 11;
 		}
 		data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i));
 		snprintf(p_str, 9, "%08x ", data);
-		p_str += 9;
+		p_str += 8;
 		if ((i + 1) % NUM_REGISTER_PER_LINE == 0) {
-			pr_err("%s\n", line_str);
+			CAM_ERR(CAM_UTIL, "%s", line_str);
 			line_str[0] = '\0';
 			p_str = line_str;
 		}
 	}
 	if (line_str[0] != '\0')
-		pr_err("%s\n", line_str);
+		CAM_ERR(CAM_UTIL, "%s", line_str);
 
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
index 6d90c1e..a1cdfe9 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
@@ -10,13 +10,118 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+#include <linux/types.h>
+#include <linux/slab.h>
 
 #include "cam_mem_mgr.h"
 #include "cam_packet_util.h"
+#include "cam_debug_util.h"
 
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+static int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
+	size_t *len)
+{
+	int rc = 0;
+	uint64_t kmd_buf_addr = 0;
+
+	rc = cam_mem_get_cpu_buf(handle, &kmd_buf_addr, len);
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "Unable to get the virtual address %d", rc);
+	} else {
+		if (kmd_buf_addr && *len) {
+			*buf_addr = (uint32_t *)kmd_buf_addr;
+		} else {
+			CAM_ERR(CAM_UTIL, "Invalid addr and length :%ld", *len);
+			rc = -ENOMEM;
+		}
+	}
+	return rc;
+}
+
+int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc)
+{
+	if ((cmd_desc->length > cmd_desc->size) ||
+		(cmd_desc->mem_handle <= 0)) {
+		CAM_ERR(CAM_UTIL, "invalid cmd arg %d %d %d %d",
+			cmd_desc->offset, cmd_desc->length,
+			cmd_desc->mem_handle, cmd_desc->size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int cam_packet_util_validate_packet(struct cam_packet *packet)
+{
+	if (!packet)
+		return -EINVAL;
+
+	CAM_DBG(CAM_UTIL, "num cmd buf:%d num of io config:%d kmd buf index:%d",
+		packet->num_cmd_buf, packet->num_io_configs,
+		packet->kmd_cmd_buf_index);
+
+	if ((packet->kmd_cmd_buf_index >= packet->num_cmd_buf) ||
+		(!packet->header.size) ||
+		(packet->cmd_buf_offset > packet->header.size) ||
+		(packet->io_configs_offset > packet->header.size))  {
+		CAM_ERR(CAM_UTIL, "invalid packet:%d %d %d %d %d",
+			packet->kmd_cmd_buf_index,
+			packet->num_cmd_buf, packet->cmd_buf_offset,
+			packet->io_configs_offset, packet->header.size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
+	struct cam_kmd_buf_info *kmd_buf)
+{
+	int                      rc = 0;
+	size_t                   len = 0;
+	struct cam_cmd_buf_desc *cmd_desc;
+	uint32_t                *cpu_addr;
+
+	if (!packet || !kmd_buf) {
+		CAM_ERR(CAM_UTIL, "Invalid arg %pK %pK", packet, kmd_buf);
+		return -EINVAL;
+	}
+
+	/* Take first command descriptor and add offset to it for kmd*/
+	cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)
+		&packet->payload + packet->cmd_buf_offset);
+	cmd_desc += packet->kmd_cmd_buf_index;
+
+	rc = cam_packet_util_validate_cmd_desc(cmd_desc);
+	if (rc)
+		return rc;
+
+	rc = cam_packet_util_get_cmd_mem_addr(cmd_desc->mem_handle, &cpu_addr,
+		&len);
+	if (rc)
+		return rc;
+
+	if (len < cmd_desc->size) {
+		CAM_ERR(CAM_UTIL, "invalid memory len:%ld and cmd desc size:%d",
+			len, cmd_desc->size);
+		return -EINVAL;
+	}
+
+	cpu_addr += (cmd_desc->offset / 4) + (packet->kmd_cmd_buf_offset / 4);
+	CAM_DBG(CAM_UTIL, "total size %d, cmd size: %d, KMD buffer size: %d",
+		cmd_desc->size, cmd_desc->length,
+		cmd_desc->size - cmd_desc->length);
+	CAM_DBG(CAM_UTIL, "hdl 0x%x, cmd offset %d, kmd offset %d, addr 0x%pK",
+		cmd_desc->mem_handle, cmd_desc->offset,
+		packet->kmd_cmd_buf_offset, cpu_addr);
+
+	kmd_buf->cpu_addr   = cpu_addr;
+	kmd_buf->handle     = cmd_desc->mem_handle;
+	kmd_buf->offset     = cmd_desc->offset + packet->kmd_cmd_buf_offset;
+	kmd_buf->size       = cmd_desc->size - cmd_desc->length;
+	kmd_buf->used_bytes = 0;
+
+	return rc;
+}
 
 int cam_packet_util_process_patches(struct cam_packet *packet,
 	int32_t iommu_hdl)
@@ -36,7 +141,7 @@
 	patch_desc = (struct cam_patch_desc *)
 			((uint32_t *) &packet->payload +
 			packet->patch_offset/4);
-	CDBG("packet = %pK patch_desc = %pK size = %lu\n",
+	CAM_DBG(CAM_UTIL, "packet = %pK patch_desc = %pK size = %lu",
 			(void *)packet, (void *)patch_desc,
 			sizeof(struct cam_patch_desc));
 
@@ -44,7 +149,7 @@
 		rc = cam_mem_get_io_buf(patch_desc[i].src_buf_hdl,
 			iommu_hdl, &iova_addr, &src_buf_size);
 		if (rc < 0) {
-			pr_err("unable to get src buf address\n");
+			CAM_ERR(CAM_UTIL, "unable to get src buf address");
 			return rc;
 		}
 		src_buf_iova_addr = (uint32_t *)iova_addr;
@@ -53,12 +158,12 @@
 		rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl,
 			&cpu_addr, &dst_buf_len);
 		if (rc < 0) {
-			pr_err("unable to get dst buf address\n");
+			CAM_ERR(CAM_UTIL, "unable to get dst buf address");
 			return rc;
 		}
 		dst_cpu_addr = (uint32_t *)cpu_addr;
 
-		CDBG("i = %d patch info = %x %x %x %x\n", i,
+		CAM_DBG(CAM_UTIL, "i = %d patch info = %x %x %x %x", i,
 			patch_desc[i].dst_buf_hdl, patch_desc[i].dst_offset,
 			patch_desc[i].src_buf_hdl, patch_desc[i].src_offset);
 
@@ -68,7 +173,8 @@
 
 		*dst_cpu_addr = temp;
 
-		CDBG("patch is done for dst %pK with src %pK value %llx\n",
+		CAM_DBG(CAM_UTIL,
+			"patch is done for dst %pK with src %pK value %llx",
 			dst_cpu_addr, src_buf_iova_addr,
 			*((uint64_t *)dst_cpu_addr));
 	}
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
index 614e868..8b590a7 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
@@ -16,6 +16,62 @@
 #include <uapi/media/cam_defs.h>
 
 /**
+ * @brief                  KMD scratch buffer information
+ *
+ * @handle:                Memory handle
+ * @cpu_addr:              Cpu address
+ * @offset:                Offset from the start of the buffer
+ * @size:                  Size of the buffer
+ * @used_bytes:            Used memory in bytes
+ *
+ */
+struct cam_kmd_buf_info {
+	int        handle;
+	uint32_t  *cpu_addr;
+	uint32_t   offset;
+	uint32_t   size;
+	uint32_t   used_bytes;
+};
+
+/**
+ * cam_packet_util_validate_packet()
+ *
+ * @brief                  Validate the packet
+ *
+ * @packet:                Packet to be validated
+ *
+ * @return:                0 for success
+ *                         -EINVAL for Fail
+ */
+int cam_packet_util_validate_packet(struct cam_packet *packet);
+
+/**
+ * cam_packet_util_validate_cmd_desc()
+ *
+ * @brief                  Validate the packet
+ *
+ * @cmd_desc:              Command descriptor to be validated
+ *
+ * @return:                0 for success
+ *                         -EINVAL for Fail
+ */
+int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc);
+
+/**
+ * cam_packet_util_get_kmd_buffer()
+ *
+ * @brief                  Get the kmd buffer from the packet command descriptor
+ *
+ * @packet:                Packet data
+ * @kmd_buf:               Extracted the KMD buffer information
+ *
+ * @return:                0 for success
+ *                         -EINVAL for Fail
+ */
+int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
+	struct cam_kmd_buf_info *kmd_buf_info);
+
+/**
  * cam_packet_util_process_patches()
  *
  * @brief:              Replace the handle in Packet to Address using the
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 1d86bb1..e5c7dbb 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -10,17 +10,13 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
-
 #include <linux/of.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include "cam_soc_util.h"
-
-#undef CDBG
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#include "cam_debug_util.h"
 
 int cam_soc_util_get_level_from_string(const char *string,
 	enum cam_vote_level *level)
@@ -43,7 +39,7 @@
 	} else if (!strcmp(string, "turbo")) {
 		*level = CAM_TURBO_VOTE;
 	} else {
-		pr_err("Invalid string %s\n", string);
+		CAM_ERR(CAM_UTIL, "Invalid string %s", string);
 		return -EINVAL;
 	}
 
@@ -68,7 +64,8 @@
 	enum cam_vote_level *apply_level)
 {
 	if (req_level >= CAM_MAX_VOTE) {
-		pr_err("Invalid clock level parameter %d\n", req_level);
+		CAM_ERR(CAM_UTIL, "Invalid clock level parameter %d",
+			req_level);
 		return -EINVAL;
 	}
 
@@ -84,13 +81,15 @@
 			}
 
 		if (i == CAM_MAX_VOTE) {
-			pr_err("No valid clock level found to apply, req=%d\n",
+			CAM_ERR(CAM_UTIL,
+				"No valid clock level found to apply, req=%d",
 				req_level);
 			return -EINVAL;
 		}
 	}
 
-	CDBG("Req level %d, Applying %d\n", req_level, *apply_level);
+	CAM_DBG(CAM_UTIL, "Req level %d, Applying %d",
+		req_level, *apply_level);
 
 	return 0;
 }
@@ -98,12 +97,12 @@
 int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info)
 {
 	if (!soc_info) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_UTIL, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	if (!soc_info->irq_line) {
-		pr_err("No IRQ line available\n");
+		CAM_ERR(CAM_UTIL, "No IRQ line available");
 		return -ENODEV;
 	}
 
@@ -115,12 +114,12 @@
 int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info)
 {
 	if (!soc_info) {
-		pr_err("Invalid arguments\n");
+		CAM_ERR(CAM_UTIL, "Invalid arguments");
 		return -EINVAL;
 	}
 
 	if (!soc_info->irq_line) {
-		pr_err("No IRQ line available\n");
+		CAM_ERR(CAM_UTIL, "No IRQ line available");
 		return -ENODEV;
 	}
 
@@ -129,6 +128,30 @@
 	return 0;
 }
 
+long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info,
+	uint32_t clk_index, unsigned long clk_rate)
+{
+	if (!soc_info || (clk_index >= soc_info->num_clk) || (clk_rate == 0)) {
+		CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d %lld",
+			soc_info, clk_index, clk_rate);
+		return clk_rate;
+	}
+
+	return clk_round_rate(soc_info->clk[clk_index], clk_rate);
+}
+
+int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info,
+	uint32_t clk_index, unsigned long flags)
+{
+	if (!soc_info || (clk_index >= soc_info->num_clk)) {
+		CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d",
+			soc_info, clk_index);
+		return -EINVAL;
+	}
+
+	return clk_set_flags(soc_info->clk[clk_index], flags);
+}
+
 int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
 	int32_t clk_rate)
 {
@@ -138,33 +161,34 @@
 	if (!clk || !clk_name)
 		return -EINVAL;
 
-	CDBG("set %s, rate %d\n", clk_name, clk_rate);
+	CAM_DBG(CAM_UTIL, "set %s, rate %d", clk_name, clk_rate);
 	if (clk_rate > 0) {
 		clk_rate_round = clk_round_rate(clk, clk_rate);
-		CDBG("new_rate %ld\n", clk_rate_round);
+		CAM_DBG(CAM_UTIL, "new_rate %ld", clk_rate_round);
 		if (clk_rate_round < 0) {
-			pr_err("round failed for clock %s rc = %ld\n",
+			CAM_ERR(CAM_UTIL, "round failed for clock %s rc = %ld",
 				clk_name, clk_rate_round);
 			return clk_rate_round;
 		}
 		rc = clk_set_rate(clk, clk_rate_round);
 		if (rc) {
-			pr_err("set_rate failed on %s\n", clk_name);
+			CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
 			return rc;
 		}
 	} else if (clk_rate == INIT_RATE) {
 		clk_rate_round = clk_get_rate(clk);
-		CDBG("init new_rate %ld\n", clk_rate_round);
+		CAM_DBG(CAM_UTIL, "init new_rate %ld", clk_rate_round);
 		if (clk_rate_round == 0) {
 			clk_rate_round = clk_round_rate(clk, 0);
 			if (clk_rate_round <= 0) {
-				pr_err("round rate failed on %s\n", clk_name);
+				CAM_ERR(CAM_UTIL, "round rate failed on %s",
+					clk_name);
 				return clk_rate_round;
 			}
 		}
 		rc = clk_set_rate(clk, clk_rate_round);
 		if (rc) {
-			pr_err("set_rate failed on %s\n", clk_name);
+			CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
 			return rc;
 		}
 	}
@@ -186,7 +210,7 @@
 
 	rc = clk_prepare_enable(clk);
 	if (rc) {
-		pr_err("enable failed for %s: rc(%d)\n", clk_name, rc);
+		CAM_ERR(CAM_UTIL, "enable failed for %s: rc(%d)", clk_name, rc);
 		return rc;
 	}
 
@@ -198,7 +222,7 @@
 	if (!clk || !clk_name)
 		return -EINVAL;
 
-	CDBG("disable %s\n", clk_name);
+	CAM_DBG(CAM_UTIL, "disable %s", clk_name);
 	clk_disable_unprepare(clk);
 
 	return 0;
@@ -223,7 +247,8 @@
 
 	if ((soc_info->num_clk == 0) ||
 		(soc_info->num_clk >= CAM_SOC_MAX_CLK)) {
-		pr_err("Invalid number of clock %d\n", soc_info->num_clk);
+		CAM_ERR(CAM_UTIL, "Invalid number of clock %d",
+			soc_info->num_clk);
 		return -EINVAL;
 	}
 
@@ -304,14 +329,14 @@
 
 	count = of_property_count_strings(of_node, "clock-names");
 
-	CDBG("count = %d\n", count);
+	CAM_DBG(CAM_UTIL, "count = %d", count);
 	if (count > CAM_SOC_MAX_CLK) {
-		pr_err("invalid count of clocks, count=%d", count);
+		CAM_ERR(CAM_UTIL, "invalid count of clocks, count=%d", count);
 		rc = -EINVAL;
 		return rc;
 	}
 	if (count <= 0) {
-		CDBG("No clock-names found\n");
+		CAM_DBG(CAM_UTIL, "No clock-names found");
 		count = 0;
 		soc_info->num_clk = count;
 		return 0;
@@ -321,9 +346,11 @@
 	for (i = 0; i < count; i++) {
 		rc = of_property_read_string_index(of_node, "clock-names",
 				i, &(soc_info->clk_name[i]));
-		CDBG("clock-names[%d] = %s\n", i, soc_info->clk_name[i]);
+		CAM_DBG(CAM_UTIL, "clock-names[%d] = %s",
+			i, soc_info->clk_name[i]);
 		if (rc) {
-			pr_err("i= %d count= %d reading clock-names failed\n",
+			CAM_ERR(CAM_UTIL,
+				"i= %d count= %d reading clock-names failed",
 				i, count);
 			return rc;
 		}
@@ -331,12 +358,13 @@
 
 	num_clk_rates = of_property_count_u32_elems(of_node, "clock-rates");
 	if (num_clk_rates <= 0) {
-		pr_err("reading clock-rates count failed\n");
+		CAM_ERR(CAM_UTIL, "reading clock-rates count failed");
 		return -EINVAL;
 	}
 
 	if ((num_clk_rates % soc_info->num_clk) != 0) {
-		pr_err("mismatch clk/rates, No of clocks=%d, No of rates=%d\n",
+		CAM_ERR(CAM_UTIL,
+			"mismatch clk/rates, No of clocks=%d, No of rates=%d",
 			soc_info->num_clk, num_clk_rates);
 		return -EINVAL;
 	}
@@ -346,7 +374,8 @@
 	num_clk_level_strings = of_property_count_strings(of_node,
 		"clock-cntl-level");
 	if (num_clk_level_strings != num_clk_levels) {
-		pr_err("Mismatch No of levels=%d, No of level string=%d\n",
+		CAM_ERR(CAM_UTIL,
+			"Mismatch No of levels=%d, No of level string=%d",
 			num_clk_levels, num_clk_level_strings);
 		return -EINVAL;
 	}
@@ -355,7 +384,8 @@
 		rc = of_property_read_string_index(of_node,
 			"clock-cntl-level", i, &clk_cntl_lvl_string);
 		if (rc) {
-			pr_err("Error reading clock-cntl-level, rc=%d\n", rc);
+			CAM_ERR(CAM_UTIL,
+				"Error reading clock-cntl-level, rc=%d", rc);
 			return rc;
 		}
 
@@ -364,14 +394,16 @@
 		if (rc)
 			return rc;
 
-		CDBG("[%d] : %s %d\n", i, clk_cntl_lvl_string, level);
+		CAM_DBG(CAM_UTIL,
+			"[%d] : %s %d", i, clk_cntl_lvl_string, level);
 		soc_info->clk_level_valid[level] = true;
 		for (j = 0; j < soc_info->num_clk; j++) {
 			rc = of_property_read_u32_index(of_node, "clock-rates",
 				((i * soc_info->num_clk) + j),
 				&soc_info->clk_rate[level][j]);
 			if (rc) {
-				pr_err("Error reading clock-rates, rc=%d\n",
+				CAM_ERR(CAM_UTIL,
+					"Error reading clock-rates, rc=%d",
 					rc);
 				return rc;
 			}
@@ -381,7 +413,8 @@
 				(long)NO_SET_RATE :
 				soc_info->clk_rate[level][j];
 
-			CDBG("soc_info->clk_rate[%d][%d] = %d\n", level, j,
+			CAM_DBG(CAM_UTIL, "soc_info->clk_rate[%d][%d] = %d",
+				level, j,
 				soc_info->clk_rate[level][j]);
 		}
 	}
@@ -390,7 +423,7 @@
 	rc = of_property_read_string_index(of_node, "src-clock-name", 0,
 		&src_clk_str);
 	if (rc || !src_clk_str) {
-		CDBG("No src_clk_str found\n");
+		CAM_DBG(CAM_UTIL, "No src_clk_str found");
 		rc = 0;
 		/* Bottom loop is dependent on src_clk_str. So return here */
 		return rc;
@@ -399,7 +432,8 @@
 	for (i = 0; i < soc_info->num_clk; i++) {
 		if (strcmp(soc_info->clk_name[i], src_clk_str) == 0) {
 			soc_info->src_clk_idx = i;
-			CDBG("src clock = %s, index = %d\n", src_clk_str, i);
+			CAM_DBG(CAM_UTIL, "src clock = %s, index = %d",
+				src_clk_str, i);
 			break;
 		}
 	}
@@ -415,7 +449,8 @@
 
 	if ((soc_info->num_clk == 0) ||
 		(soc_info->num_clk >= CAM_SOC_MAX_CLK)) {
-		pr_err("Invalid number of clock %d\n", soc_info->num_clk);
+		CAM_ERR(CAM_UTIL, "Invalid number of clock %d",
+			soc_info->num_clk);
 		return -EINVAL;
 	}
 
@@ -448,7 +483,7 @@
 
 	count /= sizeof(uint32_t);
 	if (!count) {
-		pr_err("gpio-req-tbl-num 0\n");
+		CAM_ERR(CAM_UTIL, "gpio-req-tbl-num 0");
 		return 0;
 	}
 
@@ -467,30 +502,32 @@
 	rc = of_property_read_u32_array(of_node, "gpio-req-tbl-num",
 		val_array, count);
 	if (rc) {
-		pr_err("failed in reading gpio-req-tbl-num, rc = %d\n", rc);
+		CAM_ERR(CAM_UTIL, "failed in reading gpio-req-tbl-num, rc = %d",
+			rc);
 		goto free_gpio_req_tbl;
 	}
 
 	for (i = 0; i < count; i++) {
 		if (val_array[i] >= gpio_array_size) {
-			pr_err("gpio req tbl index %d invalid\n", val_array[i]);
+			CAM_ERR(CAM_UTIL, "gpio req tbl index %d invalid",
+				val_array[i]);
 			goto free_gpio_req_tbl;
 		}
 		gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
-		CDBG("cam_gpio_req_tbl[%d].gpio = %d\n", i,
+		CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].gpio = %d", i,
 			gconf->cam_gpio_req_tbl[i].gpio);
 	}
 
 	rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags",
 		val_array, count);
 	if (rc) {
-		pr_err("Failed in gpio-req-tbl-flags, rc %d\n", rc);
+		CAM_ERR(CAM_UTIL, "Failed in gpio-req-tbl-flags, rc %d", rc);
 		goto free_gpio_req_tbl;
 	}
 
 	for (i = 0; i < count; i++) {
 		gconf->cam_gpio_req_tbl[i].flags = val_array[i];
-		CDBG("cam_gpio_req_tbl[%d].flags = %ld\n", i,
+		CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].flags = %ld", i,
 			gconf->cam_gpio_req_tbl[i].flags);
 	}
 
@@ -499,10 +536,10 @@
 			"gpio-req-tbl-label", i,
 			&gconf->cam_gpio_req_tbl[i].label);
 		if (rc) {
-			pr_err("Failed rc %d\n", rc);
+			CAM_ERR(CAM_UTIL, "Failed rc %d", rc);
 			goto free_gpio_req_tbl;
 		}
-		CDBG("cam_gpio_req_tbl[%d].label = %s\n", i,
+		CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].label = %s", i,
 			gconf->cam_gpio_req_tbl[i].label);
 	}
 
@@ -536,7 +573,7 @@
 
 	/* Validate input parameters */
 	if (!of_node) {
-		pr_err("Invalid param of_node\n");
+		CAM_ERR(CAM_UTIL, "Invalid param of_node");
 		return -EINVAL;
 	}
 
@@ -545,7 +582,7 @@
 	if (gpio_array_size <= 0)
 		return 0;
 
-	CDBG("gpio count %d\n", gpio_array_size);
+	CAM_DBG(CAM_UTIL, "gpio count %d", gpio_array_size);
 
 	gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL);
 	if (!gpio_array)
@@ -553,7 +590,7 @@
 
 	for (i = 0; i < gpio_array_size; i++) {
 		gpio_array[i] = of_get_gpio(of_node, i);
-		CDBG("gpio_array[%d] = %d", i, gpio_array[i]);
+		CAM_DBG(CAM_UTIL, "gpio_array[%d] = %d", i, gpio_array[i]);
 	}
 
 	gconf = kzalloc(sizeof(*gconf), GFP_KERNEL);
@@ -563,7 +600,7 @@
 	rc = cam_soc_util_get_dt_gpio_req_tbl(of_node, gconf, gpio_array,
 		gpio_array_size);
 	if (rc) {
-		pr_err("failed in msm_camera_get_dt_gpio_req_tbl\n");
+		CAM_ERR(CAM_UTIL, "failed in msm_camera_get_dt_gpio_req_tbl");
 		goto free_gpio_array;
 	}
 
@@ -603,23 +640,23 @@
 
 
 	if (!gpio_conf) {
-		CDBG("No GPIO entry\n");
+		CAM_DBG(CAM_UTIL, "No GPIO entry");
 		return 0;
 	}
 	if (gpio_conf->cam_gpio_common_tbl_size <= 0) {
-		pr_err("GPIO table size is invalid\n");
+		CAM_ERR(CAM_UTIL, "GPIO table size is invalid");
 		return -EINVAL;
 	}
 	size = gpio_conf->cam_gpio_req_tbl_size;
 	gpio_tbl = gpio_conf->cam_gpio_req_tbl;
 
 	if (!gpio_tbl || !size) {
-		pr_err("Invalid gpio_tbl %pK / size %d\n",
+		CAM_ERR(CAM_UTIL, "Invalid gpio_tbl %pK / size %d",
 			gpio_tbl, size);
 		return -EINVAL;
 	}
 	for (i = 0; i < size; i++) {
-		CDBG("i=%d, gpio=%d dir=%ld\n", i,
+		CAM_DBG(CAM_UTIL, "i=%d, gpio=%d dir=%ld", i,
 			gpio_tbl[i].gpio, gpio_tbl[i].flags);
 	}
 	if (gpio_en) {
@@ -632,7 +669,7 @@
 				 * apply new gpios, outout a error message
 				 * for driver bringup debug
 				 */
-				pr_err("gpio %d:%s request fails\n",
+				CAM_ERR(CAM_UTIL, "gpio %d:%s request fails",
 					gpio_tbl[i].gpio, gpio_tbl[i].label);
 			}
 		}
@@ -651,7 +688,7 @@
 	struct platform_device *pdev = NULL;
 
 	if (!soc_info || !soc_info->pdev) {
-		pr_err("Invalid parameters\n");
+		CAM_ERR(CAM_UTIL, "Invalid parameters");
 		return -EINVAL;
 	}
 
@@ -662,7 +699,7 @@
 	count = of_property_count_strings(of_node, "regulator-names");
 	if (count != -EINVAL) {
 		if (count <= 0) {
-			pr_err("no regulators found\n");
+			CAM_ERR(CAM_UTIL, "no regulators found");
 			count = 0;
 			return -EINVAL;
 		}
@@ -670,22 +707,23 @@
 		soc_info->num_rgltr = count;
 
 	} else {
-		CDBG("No regulators node found\n");
+		CAM_DBG(CAM_UTIL, "No regulators node found");
 		return 0;
 	}
 
 	for (i = 0; i < soc_info->num_rgltr; i++) {
 		rc = of_property_read_string_index(of_node,
 			"regulator-names", i, &soc_info->rgltr_name[i]);
-		CDBG("rgltr_name[%d] = %s\n", i, soc_info->rgltr_name[i]);
+		CAM_DBG(CAM_UTIL, "rgltr_name[%d] = %s",
+			i, soc_info->rgltr_name[i]);
 		if (rc) {
-			pr_err("no regulator resource at cnt=%d\n", i);
+			CAM_ERR(CAM_UTIL, "no regulator resource at cnt=%d", i);
 			return -ENODEV;
 		}
 	}
 
 	if (!of_property_read_bool(of_node, "rgltr-cntrl-support")) {
-		CDBG("No regulator control parameter defined\n");
+		CAM_DBG(CAM_UTIL, "No regulator control parameter defined");
 		soc_info->rgltr_ctrl_support = false;
 		return 0;
 	}
@@ -695,21 +733,21 @@
 	rc = of_property_read_u32_array(of_node, "rgltr-min-voltage",
 		soc_info->rgltr_min_volt, soc_info->num_rgltr);
 	if (rc) {
-		pr_err("No minimum volatage value found, rc=%d\n", rc);
+		CAM_ERR(CAM_UTIL, "No minimum volatage value found, rc=%d", rc);
 		return -EINVAL;
 	}
 
 	rc = of_property_read_u32_array(of_node, "rgltr-max-voltage",
 		soc_info->rgltr_max_volt, soc_info->num_rgltr);
 	if (rc) {
-		pr_err("No maximum volatage value found, rc=%d\n", rc);
+		CAM_ERR(CAM_UTIL, "No maximum volatage value found, rc=%d", rc);
 		return -EINVAL;
 	}
 
 	rc = of_property_read_u32_array(of_node, "rgltr-load-current",
 		soc_info->rgltr_op_mode, soc_info->num_rgltr);
 	if (rc) {
-		pr_err("No Load curent found rc=%d\n", rc);
+		CAM_ERR(CAM_UTIL, "No Load curent found rc=%d", rc);
 		return -EINVAL;
 	}
 
@@ -730,12 +768,13 @@
 
 	rc = of_property_read_u32(of_node, "cell-index", &soc_info->index);
 	if (rc) {
-		pr_err("device %s failed to read cell-index\n", pdev->name);
+		CAM_ERR(CAM_UTIL, "device %s failed to read cell-index",
+			pdev->name);
 		return rc;
 	}
 	count = of_property_count_strings(of_node, "reg-names");
 	if (count <= 0) {
-		pr_err("no reg-names found\n");
+		CAM_ERR(CAM_UTIL, "no reg-names found");
 		count = 0;
 	}
 	soc_info->num_mem_block = count;
@@ -744,7 +783,7 @@
 		rc = of_property_read_string_index(of_node, "reg-names", i,
 			&soc_info->mem_block_name[i]);
 		if (rc) {
-			pr_err("failed to read reg-names at %d\n", i);
+			CAM_ERR(CAM_UTIL, "failed to read reg-names at %d", i);
 			return rc;
 		}
 		soc_info->mem_block[i] =
@@ -752,7 +791,7 @@
 			soc_info->mem_block_name[i]);
 
 		if (!soc_info->mem_block[i]) {
-			pr_err("no mem resource by name %s\n",
+			CAM_ERR(CAM_UTIL, "no mem resource by name %s",
 				soc_info->mem_block_name[i]);
 			rc = -ENODEV;
 			return rc;
@@ -763,7 +802,7 @@
 		rc = of_property_read_u32_array(of_node, "reg-cam-base",
 			soc_info->mem_block_cam_base, soc_info->num_mem_block);
 		if (rc) {
-			pr_err("Error reading register offsets\n");
+			CAM_ERR(CAM_UTIL, "Error reading register offsets");
 			return rc;
 		}
 	}
@@ -771,13 +810,13 @@
 	rc = of_property_read_string_index(of_node, "interrupt-names", 0,
 		&soc_info->irq_name);
 	if (rc) {
-		pr_warn("No interrupt line present\n");
+		CAM_WARN(CAM_UTIL, "No interrupt line present");
 		rc = 0;
 	} else {
 		soc_info->irq_line = platform_get_resource_byname(pdev,
 			IORESOURCE_IRQ, soc_info->irq_name);
 		if (!soc_info->irq_line) {
-			pr_err("no irq resource\n");
+			CAM_ERR(CAM_UTIL, "no irq resource");
 			rc = -ENODEV;
 			return rc;
 		}
@@ -817,7 +856,7 @@
 	if (IS_ERR_OR_NULL(*reg)) {
 		rc = PTR_ERR(*reg);
 		rc = rc ? rc : -EINVAL;
-		pr_err("Regulator %s get failed %d\n", rgltr_name, rc);
+		CAM_ERR(CAM_UTIL, "Regulator %s get failed %d", rgltr_name, rc);
 		*reg = NULL;
 	}
 	return rc;
@@ -831,13 +870,13 @@
 	int32_t rc = 0;
 
 	if (!rgltr) {
-		pr_err("Invalid NULL parameter\n");
+		CAM_ERR(CAM_UTIL, "Invalid NULL parameter");
 		return -EINVAL;
 	}
 
 	rc = regulator_disable(rgltr);
 	if (rc) {
-		pr_err("%s regulator disable failed\n", rgltr_name);
+		CAM_ERR(CAM_UTIL, "%s regulator disable failed", rgltr_name);
 		return rc;
 	}
 
@@ -864,31 +903,32 @@
 	int32_t rc = 0;
 
 	if (!rgltr) {
-		pr_err("Invalid NULL parameter\n");
+		CAM_ERR(CAM_UTIL, "Invalid NULL parameter");
 		return -EINVAL;
 	}
 
 	if (regulator_count_voltages(rgltr) > 0) {
-		CDBG("voltage min=%d, max=%d\n",
+		CAM_DBG(CAM_UTIL, "voltage min=%d, max=%d",
 			rgltr_min_volt, rgltr_max_volt);
 
 		rc = regulator_set_voltage(
 			rgltr, rgltr_min_volt, rgltr_max_volt);
 		if (rc) {
-			pr_err("%s set voltage failed\n", rgltr_name);
+			CAM_ERR(CAM_UTIL, "%s set voltage failed", rgltr_name);
 			return rc;
 		}
 
 		rc = regulator_set_load(rgltr, rgltr_op_mode);
 		if (rc) {
-			pr_err("%s set optimum mode failed\n", rgltr_name);
+			CAM_ERR(CAM_UTIL, "%s set optimum mode failed",
+				rgltr_name);
 			return rc;
 		}
 	}
 
 	rc = regulator_enable(rgltr);
 	if (rc) {
-		pr_err("%s regulator_enable failed\n", rgltr_name);
+		CAM_ERR(CAM_UTIL, "%s regulator_enable failed", rgltr_name);
 		return rc;
 	}
 
@@ -909,7 +949,7 @@
 
 	device_pctrl->pinctrl = devm_pinctrl_get(dev);
 	if (IS_ERR_OR_NULL(device_pctrl->pinctrl)) {
-		CDBG("Pinctrl not available\n");
+		CAM_DBG(CAM_UTIL, "Pinctrl not available");
 		device_pctrl->pinctrl = NULL;
 		return 0;
 	}
@@ -917,7 +957,8 @@
 		pinctrl_lookup_state(device_pctrl->pinctrl,
 				CAM_SOC_PINCTRL_STATE_DEFAULT);
 	if (IS_ERR_OR_NULL(device_pctrl->gpio_state_active)) {
-		pr_err("Failed to get the active state pinctrl handle\n");
+		CAM_ERR(CAM_UTIL,
+			"Failed to get the active state pinctrl handle");
 		device_pctrl->gpio_state_active = NULL;
 		return -EINVAL;
 	}
@@ -925,7 +966,8 @@
 		= pinctrl_lookup_state(device_pctrl->pinctrl,
 				CAM_SOC_PINCTRL_STATE_SLEEP);
 	if (IS_ERR_OR_NULL(device_pctrl->gpio_state_suspend)) {
-		pr_err("Failed to get the suspend state pinctrl handle\n");
+		CAM_ERR(CAM_UTIL,
+			"Failed to get the suspend state pinctrl handle");
 		device_pctrl->gpio_state_suspend = NULL;
 		return -EINVAL;
 	}
@@ -973,7 +1015,8 @@
 		}
 
 		if (rc) {
-			pr_err("%s enable failed\n", soc_info->rgltr_name[j]);
+			CAM_ERR(CAM_UTIL, "%s enable failed",
+				soc_info->rgltr_name[j]);
 			goto disable_rgltr;
 		}
 	}
@@ -1007,7 +1050,7 @@
 
 
 	if (!soc_info || !soc_info->pdev) {
-		pr_err("Invalid parameters\n");
+		CAM_ERR(CAM_UTIL, "Invalid parameters");
 		return -EINVAL;
 	}
 
@@ -1018,7 +1061,8 @@
 			if (!request_mem_region(soc_info->mem_block[i]->start,
 				resource_size(soc_info->mem_block[i]),
 				soc_info->mem_block_name[i])){
-				pr_err("Error Mem Region request Failed:%s\n",
+				CAM_ERR(CAM_UTIL,
+					"Error Mem Region request Failed:%s",
 					soc_info->mem_block_name[i]);
 				rc = -ENOMEM;
 				goto unmap_base;
@@ -1028,7 +1072,7 @@
 			soc_info->mem_block[i]->start,
 			resource_size(soc_info->mem_block[i]));
 		if (!soc_info->reg_map[i].mem_base) {
-			pr_err("i= %d base NULL\n", i);
+			CAM_ERR(CAM_UTIL, "i= %d base NULL", i);
 			rc = -ENOMEM;
 			goto unmap_base;
 		}
@@ -1041,7 +1085,7 @@
 
 	for (i = 0; i < soc_info->num_rgltr; i++) {
 		if (soc_info->rgltr_name[i] == NULL) {
-			pr_err("can't find regulator name\n");
+			CAM_ERR(CAM_UTIL, "can't find regulator name");
 			goto put_regulator;
 		}
 
@@ -1056,7 +1100,7 @@
 			handler, IRQF_TRIGGER_RISING,
 			soc_info->irq_name, irq_data);
 		if (rc) {
-			pr_err("irq request fail\n");
+			CAM_ERR(CAM_UTIL, "irq request fail");
 			rc = -EBUSY;
 			goto put_regulator;
 		}
@@ -1069,7 +1113,8 @@
 		soc_info->clk[i] = clk_get(&soc_info->pdev->dev,
 			soc_info->clk_name[i]);
 		if (!soc_info->clk[i]) {
-			pr_err("get failed for %s\n", soc_info->clk_name[i]);
+			CAM_ERR(CAM_UTIL, "get failed for %s",
+				soc_info->clk_name[i]);
 			rc = -ENOENT;
 			goto put_clk;
 		}
@@ -1077,11 +1122,11 @@
 
 	rc = cam_soc_util_request_pinctrl(soc_info);
 	if (rc)
-		CDBG("Failed in request pinctrl, rc=%d\n", rc);
+		CAM_DBG(CAM_UTIL, "Failed in request pinctrl, rc=%d", rc);
 
 	rc = cam_soc_util_request_gpio_table(soc_info, true);
 	if (rc) {
-		pr_err("Failed in request gpio table, rc=%d\n", rc);
+		CAM_ERR(CAM_UTIL, "Failed in request gpio table, rc=%d", rc);
 		goto put_clk;
 	}
 
@@ -1135,7 +1180,7 @@
 	struct platform_device *pdev = NULL;
 
 	if (!soc_info || !soc_info->pdev) {
-		pr_err("Invalid parameter\n");
+		CAM_ERR(CAM_UTIL, "Invalid parameter");
 		return -EINVAL;
 	}
 
@@ -1186,7 +1231,7 @@
 
 	rc = cam_soc_util_regulator_enable_default(soc_info);
 	if (rc) {
-		pr_err("Regulators enable failed\n");
+		CAM_ERR(CAM_UTIL, "Regulators enable failed");
 		return rc;
 	}
 
@@ -1257,7 +1302,7 @@
 {
 	void __iomem     *base_addr = NULL;
 
-	CDBG("base_idx %u size=%d\n", base_index, size);
+	CAM_DBG(CAM_UTIL, "base_idx %u size=%d", base_index, size);
 
 	if (!soc_info || base_index >= soc_info->num_reg_map ||
 		size <= 0 || (offset + size) >=
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 7eb7578..ae92cab 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/clk/qcom.h>
 
 #include "cam_io_util.h"
 
@@ -328,6 +329,35 @@
 	bool disable_clocks, bool disable_irq);
 
 /**
+ * cam_soc_util_get_clk_round_rate()
+ *
+ * @brief:              Get the rounded clock rate for the given clock's
+ *                      clock rate value
+ *
+ * @soc_info:           Device soc information
+ * @clk_index:          Clock index in soc_info for which round rate is needed
+ * @clk_rate:           Input clock rate for which rounded rate is needed
+ *
+ * @return:             Rounded clock rate
+ */
+long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info,
+	uint32_t clk_index, unsigned long clk_rate);
+
+/**
+ * cam_soc_util_set_clk_flags()
+ *
+ * @brief:              Camera SOC util to set the flags for a specified clock
+ *
+ * @soc_info:           Device soc information
+ * @clk_index:          Clock index in soc_info for which flags are to be set
+ * @flags:              Flags to set
+ *
+ * @return:             Success or Failure
+ */
+int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info,
+	 uint32_t clk_index, unsigned long flags);
+
+/**
  * cam_soc_util_set_clk_rate()
  *
  * @brief:              Set the rate on a given clock.
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_trace.h b/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
index f233799..2e9e61f 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
@@ -23,6 +23,8 @@
 
 #include <linux/tracepoint.h>
 #include <media/cam_req_mgr.h>
+#include "cam_req_mgr_core.h"
+#include "cam_req_mgr_interface.h"
 #include "cam_context.h"
 
 TRACE_EVENT(cam_context_state,
@@ -107,19 +109,112 @@
 );
 
 TRACE_EVENT(cam_flush_req,
-	TP_PROTO(struct cam_req_mgr_flush_info *info),
-	TP_ARGS(info),
+	TP_PROTO(struct cam_req_mgr_core_link *link,
+		struct cam_req_mgr_flush_info *info),
+	TP_ARGS(link, info),
 	TP_STRUCT__entry(
 		__field(uint32_t, type)
 		__field(int64_t, req_id)
+		__field(void*, link)
+		__field(void*, session)
 	),
 	TP_fast_assign(
-		__entry->type   = info->flush_type;
-		__entry->req_id = info->req_id;
+		__entry->type    = info->flush_type;
+		__entry->req_id  = info->req_id;
+		__entry->link    = link;
+		__entry->session = link->parent;
 	),
 	TP_printk(
-		"FlushRequest type=%u request=%llu",
-			__entry->type, __entry->req_id
+		"FlushRequest type=%u request=%llu link=%pK session=%pK",
+			__entry->type, __entry->req_id, __entry->link,
+			__entry->session
+	)
+);
+
+TRACE_EVENT(cam_req_mgr_connect_device,
+	TP_PROTO(struct cam_req_mgr_core_link *link,
+		struct cam_req_mgr_device_info *info),
+	TP_ARGS(link, info),
+	TP_STRUCT__entry(
+		__string(name, info->name)
+		__field(uint32_t, id)
+		__field(uint32_t, delay)
+		__field(void*, link)
+		__field(void*, session)
+	),
+	TP_fast_assign(
+		__assign_str(name, info->name);
+		__entry->id      = info->dev_id;
+		__entry->delay   = info->p_delay;
+		__entry->link    = link;
+		__entry->session = link->parent;
+	),
+	TP_printk(
+		"ReqMgr Connect name=%s id=%u pd=%d link=%pK session=%pK",
+			__get_str(name), __entry->id, __entry->delay,
+			__entry->link, __entry->session
+	)
+);
+
+TRACE_EVENT(cam_req_mgr_apply_request,
+	TP_PROTO(struct cam_req_mgr_core_link *link,
+		struct cam_req_mgr_apply_request *req,
+		struct cam_req_mgr_connected_device *dev),
+	TP_ARGS(link, req, dev),
+	TP_STRUCT__entry(
+		__string(name, dev->dev_info.name)
+		__field(uint32_t, dev_id)
+		__field(uint64_t, req_id)
+		__field(void*, link)
+		__field(void*, session)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev->dev_info.name);
+		__entry->dev_id  = dev->dev_info.dev_id;
+		__entry->req_id  = req->request_id;
+		__entry->link    = link;
+		__entry->session = link->parent;
+	),
+	TP_printk(
+		"ReqMgr ApplyRequest devname=%s devid=%u request=%lld link=%pK session=%pK",
+			__get_str(name), __entry->dev_id, __entry->req_id,
+			__entry->link, __entry->session
+	)
+);
+
+TRACE_EVENT(cam_req_mgr_add_req,
+	TP_PROTO(struct cam_req_mgr_core_link *link,
+		int idx, struct cam_req_mgr_add_request *add_req,
+		struct cam_req_mgr_req_tbl *tbl,
+		struct cam_req_mgr_connected_device *dev),
+	TP_ARGS(link, idx, add_req, tbl, dev),
+	TP_STRUCT__entry(
+		__string(name, dev->dev_info.name)
+		__field(uint32_t, dev_id)
+		__field(uint64_t, req_id)
+		__field(uint32_t, slot_id)
+		__field(uint32_t, delay)
+		__field(uint32_t, readymap)
+		__field(uint32_t, devicemap)
+		__field(void*, link)
+		__field(void*, session)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev->dev_info.name);
+		__entry->dev_id    = dev->dev_info.dev_id;
+		__entry->req_id    = add_req->req_id;
+		__entry->slot_id   = idx;
+		__entry->delay     = tbl->pd;
+		__entry->readymap  = tbl->slot[idx].req_ready_map;
+		__entry->devicemap = tbl->dev_mask;
+		__entry->link      = link;
+		__entry->session   = link->parent;
+	),
+	TP_printk(
+		"ReqMgr AddRequest devname=%s devid=%d request=%lld slot=%d pd=%d readymap=%x devicemap=%d link=%pk session=%pK",
+			__get_str(name), __entry->dev_id, __entry->req_id,
+			__entry->slot_id, __entry->delay, __entry->readymap,
+			__entry->devicemap, __entry->link, __entry->session
 	)
 );
 #endif /* _CAM_TRACE_H */
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index da7ecce..a075ed9 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/vmalloc.h>
+#include <linux/dma-buf.h>
 #include <linux/qcom_tspp.h>
 #include "mpq_dvb_debug.h"
 #include "mpq_dmx_plugin_common.h"
@@ -189,6 +190,10 @@
 
 		/* Mutex protecting the data-structure */
 		struct mutex mutex;
+
+		/* ion dma buffer mapping structure */
+		struct tspp_ion_dma_buf_info ch_ion_dma_buf;
+
 	} tsif[TSIF_COUNT];
 
 	/* ION client used for TSPP data buffer allocation */
@@ -196,7 +201,8 @@
 } mpq_dmx_tspp_info;
 
 static void *tspp_mem_allocator(int channel_id, u32 size,
-				phys_addr_t *phys_base, void *user)
+				phys_addr_t *phys_base, dma_addr_t *dma_base,
+				void *user)
 {
 	void *virt_addr = NULL;
 	int i = TSPP_GET_TSIF_NUM(channel_id);
@@ -213,6 +219,10 @@
 		(mpq_dmx_tspp_info.tsif[i].ch_mem_heap_phys_base +
 		(mpq_dmx_tspp_info.tsif[i].buff_index * size));
 
+	*dma_base =
+		(mpq_dmx_tspp_info.tsif[i].ch_ion_dma_buf.dma_map_base +
+		(mpq_dmx_tspp_info.tsif[i].buff_index * size));
+
 	mpq_dmx_tspp_info.tsif[i].buff_index++;
 
 	return virt_addr;
@@ -539,6 +549,9 @@
 
 	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_virt_base = NULL;
 	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle = NULL;
+
+	tspp_detach_ion_dma_buff(0,
+		&mpq_dmx_tspp_info.tsif[tsif].ch_ion_dma_buf);
 }
 
 /**
@@ -589,6 +602,24 @@
 		return -ENOMEM;
 	}
 
+	mpq_dmx_tspp_info.tsif[tsif].ch_ion_dma_buf.dbuf = ion_share_dma_buf(
+			mpq_dmx_tspp_info.ion_client,
+			mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle);
+	if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[tsif].ch_ion_dma_buf.dbuf)) {
+		MPQ_DVB_ERR_PRINT("%s: ion_share_dma_buf failed\n", __func__);
+		mpq_dmx_channel_mem_free(tsif);
+		return -ENOMEM;
+	}
+
+	result = tspp_attach_ion_dma_buff(0,
+				&mpq_dmx_tspp_info.tsif[tsif].ch_ion_dma_buf);
+	if (result) {
+		MPQ_DVB_ERR_PRINT("%s: tspp_attach_ion_dma_buff failed\n",
+					 __func__);
+		mpq_dmx_channel_mem_free(tsif);
+		return result;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 9d10b06..d36d601 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -325,7 +325,7 @@
 	if (mgr->rsc_client)
 		ret = sde_rsc_client_state_update(mgr->rsc_client,
 				on ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE,
-				NULL, -1);
+				NULL, SDE_RSC_INVALID_CRTC_ID, NULL);
 	else
 		ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
 			mgr->module_power.num_vreg, on);
@@ -341,8 +341,6 @@
 	if (!on) {
 		mgr->minimum_bw_vote = 0;
 		sde_rotator_update_perf(mgr);
-	} else {
-		sde_mdp_init_vbif();
 	}
 
 	mgr->regulator_enable = on;
@@ -426,6 +424,9 @@
 			if (ret)
 				goto error_rot_sub;
 
+			/* reinitialize static vbif setting */
+			sde_mdp_init_vbif();
+
 			/* Active+Sleep */
 			msm_bus_scale_client_update_context(
 				mgr->data_bus.bus_hdl, false,
@@ -945,6 +946,11 @@
 				"timeout waiting for hw resource, a:%d p:%d\n",
 				atomic_read(&hw->num_active),
 				hw->pending_count);
+			SDEROT_EVTLOG(entry->item.session_id,
+					entry->item.sequence_id,
+					atomic_read(&hw->num_active),
+					hw->pending_count,
+					SDE_ROT_EVTLOG_ERROR);
 			return NULL;
 		}
 	}
@@ -1603,9 +1609,14 @@
 		entry->item.flags,
 		entry->dnsc_factor_w, entry->dnsc_factor_h);
 
-	wait_for_completion_timeout(
+	ret = wait_for_completion_timeout(
 			&entry->item.inline_start,
 			msecs_to_jiffies(ROT_INLINE_START_TIMEOUT_IN_MS));
+	if (!ret) {
+		SDEROT_WARN("timeout waiting for inline start\n");
+		SDEROT_EVTLOG(entry->item.session_id, entry->item.sequence_id,
+				SDE_ROT_EVTLOG_ERROR);
+	}
 
 	if (entry->item.ts)
 		entry->item.ts[SDE_ROTATOR_TS_START] = ktime_get();
@@ -2335,6 +2346,7 @@
 
 	if (config->output.sbuf && mgr->sbuf_ctx != private && mgr->sbuf_ctx) {
 		SDEROT_ERR("too many sbuf sessions\n");
+		ret = -EBUSY;
 		goto done;
 	}
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index da36e38..2a9573d 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -21,6 +21,7 @@
 #include "sde_rotator_base.h"
 #include "sde_rotator_core.h"
 #include "sde_rotator_dev.h"
+#include "sde_rotator_trace.h"
 
 #ifdef CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG
 #define SDE_EVTLOG_DEFAULT_ENABLE 1
@@ -639,12 +640,13 @@
 /*
  * sde_rot_dump_panic - Issue evtlog dump and generic panic
  */
-void sde_rot_dump_panic(void)
+void sde_rot_dump_panic(bool do_panic)
 {
 	sde_rot_evtlog_dump_all();
 	sde_rot_dump_reg_all();
 
-	panic("sde_rotator");
+	if (do_panic)
+		panic("sde_rotator");
 }
 
 /*
@@ -740,6 +742,8 @@
 		(sde_rot_dbg_evtlog.curr + 1) % SDE_ROT_EVTLOG_ENTRY;
 	sde_rot_dbg_evtlog.last++;
 
+	trace_sde_rot_evtlog(name, line, log->data_cnt, log->data);
+
 	spin_unlock_irqrestore(&sde_rot_xlock, flags);
 }
 
@@ -1434,6 +1438,13 @@
 		return NULL;
 	}
 
+	if (!debugfs_create_u32("open_timeout", 0644,
+			debugfs_root, &rot_dev->open_timeout)) {
+		SDEROT_ERR("fail create open_timeout\n");
+		debugfs_remove_recursive(debugfs_root);
+		return NULL;
+	}
+
 	if (!debugfs_create_u32("disable_syscache", 0644,
 			debugfs_root, &rot_dev->disable_syscache)) {
 		SDEROT_ERR("fail create disable_syscache\n");
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h
index c6d0151..2fc8e3f 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h
@@ -18,6 +18,9 @@
 
 #define SDE_ROT_DATA_LIMITER (-1)
 #define SDE_ROT_EVTLOG_TOUT_DATA_LIMITER (NULL)
+#define SDE_ROT_EVTLOG_PANIC		0xdead
+#define SDE_ROT_EVTLOG_FATAL		0xbad
+#define SDE_ROT_EVTLOG_ERROR		0xebad
 
 enum sde_rot_dbg_reg_dump_flag {
 	SDE_ROT_DBG_DUMP_IN_LOG = BIT(0),
@@ -39,7 +42,7 @@
 		SDE_ROT_EVTLOG_TOUT_DATA_LIMITER)
 
 void sde_rot_evtlog(const char *name, int line, int flag, ...);
-void sde_rot_dump_panic(void);
+void sde_rot_dump_panic(bool do_panic);
 void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...);
 
 struct sde_rotator_device;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index d300de2..bf7a917 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -46,6 +46,9 @@
 /* acquire fence time out, following other driver fence time out practice */
 #define SDE_ROTATOR_FENCE_TIMEOUT	MSEC_PER_SEC
 
+/* Timeout (msec) waiting for ctx open */
+#define SDE_ROTATOR_CTX_OPEN_TIMEOUT	500
+
 /* Rotator default fps */
 #define SDE_ROTATOR_DEFAULT_FPS	60
 
@@ -457,6 +460,9 @@
 				"timeout to stream off s:%d t:%d p:%d\n",
 				ctx->session_id, q->type,
 				!list_empty(&ctx->pending_list));
+		SDEROT_EVTLOG(ctx->session_id, q->type,
+				!list_empty(&ctx->pending_list),
+				SDE_ROT_EVTLOG_ERROR);
 		sde_rot_mgr_lock(rot_dev->mgr);
 		sde_rotator_cancel_all_requests(rot_dev->mgr, ctx->private);
 		sde_rot_mgr_unlock(rot_dev->mgr);
@@ -486,7 +492,7 @@
 			struct sde_rotator_vbinfo *vbinfo =
 					&ctx->vbinfo_cap[i];
 
-			if (vbinfo->fence && vbinfo->fd < 0) {
+			if (vbinfo->fence) {
 				/* fence is not used */
 				SDEDEV_DBG(rot_dev->dev,
 						"put fence s:%d t:%d i:%d\n",
@@ -893,6 +899,29 @@
 		goto error_lock;
 	}
 
+	/* wait until exclusive ctx, if exists, finishes or timeout */
+	while (rot_dev->excl_ctx) {
+		SDEROT_DBG("waiting to open %s session %d ...\n",
+				file ? "v4l2" : "excl",	rot_dev->session_id);
+		mutex_unlock(&rot_dev->lock);
+		ret = wait_event_interruptible_timeout(rot_dev->open_wq,
+				!rot_dev->excl_ctx,
+				msecs_to_jiffies(rot_dev->open_timeout));
+		if (ret < 0) {
+			goto error_lock;
+		} else if (!ret) {
+			SDEROT_WARN("timeout to open session %d\n",
+					rot_dev->session_id);
+			SDEROT_EVTLOG(rot_dev->session_id,
+					SDE_ROT_EVTLOG_ERROR);
+			ret = -EBUSY;
+			goto error_lock;
+		} else if (mutex_lock_interruptible(&rot_dev->lock)) {
+			ret = -ERESTARTSYS;
+			goto error_lock;
+		}
+	}
+
 	ctx->rot_dev = rot_dev;
 	ctx->file = file;
 
@@ -991,8 +1020,8 @@
 	}
 	sde_rot_mgr_unlock(rot_dev->mgr);
 
-	/* Create control */
 	if (ctx->file) {
+		/* Create control */
 		ctrl_handler = &ctx->ctrl_handler;
 		v4l2_ctrl_handler_init(ctrl_handler, 4);
 		v4l2_ctrl_new_std(ctrl_handler,
@@ -1012,7 +1041,14 @@
 		}
 		ctx->fh.ctrl_handler = ctrl_handler;
 		v4l2_ctrl_handler_setup(ctrl_handler);
+	} else {
+		/* acquire exclusive context */
+		SDEDEV_DBG(rot_dev->dev, "acquire exclusive session id:%u\n",
+				ctx->session_id);
+		SDEROT_EVTLOG(ctx->session_id);
+		rot_dev->excl_ctx = ctx;
 	}
+
 	mutex_unlock(&rot_dev->lock);
 
 	SDEDEV_DBG(ctx->rot_dev->dev, "SDE v4l2 rotator open success\n");
@@ -1059,6 +1095,12 @@
 
 	SDEDEV_DBG(rot_dev->dev, "release s:%d\n", session_id);
 	mutex_lock(&rot_dev->lock);
+	if (rot_dev->excl_ctx == ctx) {
+		SDEDEV_DBG(rot_dev->dev, "release exclusive session id:%u\n",
+				session_id);
+		SDEROT_EVTLOG(session_id);
+		rot_dev->excl_ctx = NULL;
+	}
 	if (ctx->file) {
 		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 		SDEDEV_DBG(rot_dev->dev, "release streams s:%d\n", session_id);
@@ -1105,6 +1147,7 @@
 	kfree(ctx->vbinfo_out);
 	kfree(ctx->vbinfo_cap);
 	kfree(ctx);
+	wake_up_interruptible(&rot_dev->open_wq);
 	mutex_unlock(&rot_dev->lock);
 	SDEDEV_DBG(rot_dev->dev, "release complete s:%d\n", session_id);
 	return 0;
@@ -1451,15 +1494,14 @@
 	SDEROT_EVTLOG(ctx->session_id, cmd->sequence_id,
 		cmd->src_rect_x, cmd->src_rect_y,
 		cmd->src_rect_w, cmd->src_rect_h,
-		cmd->src_width, cmd->src_height,
 		cmd->src_pixfmt,
-		cmd->dst_rect_x, cmd->dst_rect_y,
 		cmd->dst_rect_w, cmd->dst_rect_h,
 		cmd->dst_pixfmt,
-		cmd->rot90, cmd->hflip, cmd->vflip, cmd->secure, cmd->fps,
-		cmd->clkrate, cmd->data_bw,
-		cmd->dst_writeback, cmd->video_mode, cmd_type);
-
+		(cmd->rot90 << 0) | (cmd->hflip << 1) | (cmd->vflip << 2) |
+		(cmd->secure << 3) | (cmd->dst_writeback << 4) |
+		(cmd->video_mode << 5),
+		cmd->fps, cmd->clkrate, cmd->data_bw,
+		cmd_type);
 
 	sde_rot_mgr_lock(rot_dev->mgr);
 
@@ -1677,13 +1719,17 @@
 			ret = wait_event_timeout(ctx->wait_queue,
 				sde_rotator_is_request_retired(request),
 				msecs_to_jiffies(rot_dev->streamoff_timeout));
-			if (!ret)
+			if (!ret) {
 				SDEROT_ERR("timeout w/o retire s:%d\n",
 						ctx->session_id);
-			else if (ret == 1)
+				SDEROT_EVTLOG(ctx->session_id,
+						SDE_ROT_EVTLOG_ERROR);
+			} else if (ret == 1) {
 				SDEROT_ERR("timeout w/ retire s:%d\n",
 						ctx->session_id);
-
+				SDEROT_EVTLOG(ctx->session_id,
+						SDE_ROT_EVTLOG_ERROR);
+			}
 			sde_rot_mgr_lock(rot_dev->mgr);
 		}
 
@@ -1708,6 +1754,12 @@
 }
 EXPORT_SYMBOL(sde_rotator_inline_commit);
 
+void sde_rotator_inline_reg_dump(struct platform_device *pdev)
+{
+	sde_rot_dump_panic(false);
+}
+EXPORT_SYMBOL(sde_rotator_inline_reg_dump);
+
 /*
  * sde_rotator_open - Rotator device open method.
  * @file: Pointer to file struct.
@@ -2158,7 +2210,7 @@
 			&& (buf->index < ctx->nbuf_cap)) {
 		int idx = buf->index;
 
-		if (ctx->vbinfo_cap[idx].fence && ctx->vbinfo_cap[idx].fd < 0) {
+		if (ctx->vbinfo_cap[idx].fence) {
 			/* fence is not used */
 			SDEDEV_DBG(ctx->rot_dev->dev, "put fence s:%d i:%d\n",
 					ctx->session_id, idx);
@@ -2487,6 +2539,7 @@
 	struct msm_sde_rotator_fence *fence = arg;
 	struct msm_sde_rotator_comp_ratio *comp_ratio = arg;
 	struct sde_rotator_vbinfo *vbinfo;
+	int ret;
 
 	switch (cmd) {
 	case VIDIOC_S_SDE_ROTATOR_FENCE:
@@ -2545,17 +2598,37 @@
 
 		vbinfo = &ctx->vbinfo_cap[fence->index];
 
-		if (vbinfo->fence == NULL) {
-			vbinfo->fd = -1;
-		} else {
-			vbinfo->fd =
-				sde_rotator_get_sync_fence_fd(vbinfo->fence);
-			if (vbinfo->fd < 0) {
+		if (!vbinfo)
+			return -EINVAL;
+
+		if (vbinfo->fence) {
+			ret = sde_rotator_get_sync_fence_fd(vbinfo->fence);
+			if (ret < 0) {
 				SDEDEV_ERR(rot_dev->dev,
-					"fail get fence fd s:%d\n",
-					ctx->session_id);
-				return vbinfo->fd;
+						"fail get fence fd s:%d\n",
+						ctx->session_id);
+				return ret;
 			}
+
+			/**
+			 * Loose any reference to sync fence once we pass
+			 * it to user. Driver does not clean up user
+			 * unclosed fence descriptors.
+			 */
+			vbinfo->fence = NULL;
+
+			/**
+			 * Cache fence descriptor in case user calls this
+			 * ioctl multiple times. Cached value would be stale
+			 * if user duplicated and closed old descriptor.
+			 */
+			vbinfo->fd = ret;
+		} else if (!sde_rotator_get_fd_sync_fence(vbinfo->fd)) {
+			/**
+			 * User has closed cached fence descriptor.
+			 * Invalidate descriptor cache.
+			 */
+			vbinfo->fd = -1;
 		}
 		fence->fd = vbinfo->fd;
 
@@ -2878,6 +2951,9 @@
 				"error waiting for fence s:%d.%d fd:%d r:%d\n",
 				ctx->session_id,
 				vbinfo_cap->fence_ts, vbinfo_out->fd, ret);
+			SDEROT_EVTLOG(ctx->session_id, vbinfo_cap->fence_ts,
+					vbinfo_out->fd, ret,
+					SDE_ROT_EVTLOG_ERROR);
 			goto error_fence_wait;
 		} else {
 			SDEDEV_DBG(rot_dev->dev, "fence exit s:%d.%d fd:%d\n",
@@ -3278,6 +3354,8 @@
 	rot_dev->min_bw = 0;
 	rot_dev->min_overhead_us = 0;
 	rot_dev->drvdata = sde_rotator_get_drv_data(&pdev->dev);
+	rot_dev->open_timeout = SDE_ROTATOR_CTX_OPEN_TIMEOUT;
+	init_waitqueue_head(&rot_dev->open_wq);
 
 	rot_dev->pdev = pdev;
 	rot_dev->dev = &pdev->dev;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h
index 627ea86..5ea9e15 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h
@@ -205,6 +205,9 @@
  * @min_overhead_us: Override the minimum overhead in us from perf calculation
  * @debugfs_root: Pointer to debugfs directory entry.
  * @stats: placeholder for rotator statistics
+ * @open_timeout: maximum wait time for ctx open in msec
+ * @open_wq: wait queue for ctx open
+ * @excl_ctx: Pointer to exclusive ctx
  */
 struct sde_rotator_device {
 	struct mutex lock;
@@ -227,6 +230,9 @@
 	struct sde_rotator_statistics stats;
 	struct dentry *debugfs_root;
 	struct dentry *perf_root;
+	u32 open_timeout;
+	wait_queue_head_t open_wq;
+	struct sde_rotator_ctx *excl_ctx;
 };
 
 static inline
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
index 705eb27..474662e 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
@@ -112,5 +112,6 @@
 int sde_rotator_inline_commit(void *handle, struct sde_rotator_inline_cmd *cmd,
 		enum sde_rotator_inline_cmd_type cmd_type);
 int sde_rotator_inline_release(void *handle);
+void sde_rotator_inline_reg_dump(struct platform_device *pdev);
 
 #endif /* __SDE_ROTATOR_INLINE_H__ */
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_trace.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_trace.h
index 691e2ec..5ba37b3 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_trace.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2015-2017, 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
@@ -295,6 +295,40 @@
 
 );
 
+#define SDE_ROT_TRACE_EVTLOG_SIZE	15
+TRACE_EVENT(sde_rot_evtlog,
+	TP_PROTO(const char *tag, u32 tag_id, u32 cnt, u32 data[]),
+	TP_ARGS(tag, tag_id, cnt, data),
+	TP_STRUCT__entry(
+			__field(int, pid)
+			__string(evtlog_tag, tag)
+			__field(u32, tag_id)
+			__array(u32, data, SDE_ROT_TRACE_EVTLOG_SIZE)
+	),
+	TP_fast_assign(
+			__entry->pid = current->tgid;
+			__assign_str(evtlog_tag, tag);
+			__entry->tag_id = tag_id;
+			if (cnt > SDE_ROT_TRACE_EVTLOG_SIZE)
+				cnt = SDE_ROT_TRACE_EVTLOG_SIZE;
+			memcpy(__entry->data, data, cnt * sizeof(u32));
+			memset(&__entry->data[cnt], 0,
+				(SDE_ROT_TRACE_EVTLOG_SIZE - cnt) *
+				sizeof(u32));
+	),
+	TP_printk("%d|%s:%d|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x",
+			__entry->pid, __get_str(evtlog_tag),
+			__entry->tag_id,
+			__entry->data[0], __entry->data[1],
+			__entry->data[2], __entry->data[3],
+			__entry->data[4], __entry->data[5],
+			__entry->data[6], __entry->data[7],
+			__entry->data[8], __entry->data[9],
+			__entry->data[10], __entry->data[11],
+			__entry->data[12], __entry->data[13],
+			__entry->data[14])
+)
+
 #endif /* if !defined(TRACE_SDE_ROTATOR_H) ||
 	*		defined(TRACE_HEADER_MULTI_READ)
 	*/
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index a7b1852..a93f054 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -330,7 +330,9 @@
 	 */
 	/* Decoder parameters */
 	int width, height, lcu_size, dpb_bpp, opb_bpp, fps, opb_factor;
-	bool unified_dpb_opb, dpb_compression_enabled, opb_compression_enabled;
+	bool unified_dpb_opb, dpb_compression_enabled, opb_compression_enabled,
+		llc_ref_read_l2_cache_enabled = false,
+		llc_vpss_ds_line_buf_enabled = false;
 	fp_t dpb_opb_scaling_ratio, dpb_read_compression_factor,
 		dpb_write_compression_factor, opb_compression_factor,
 		qsmmu_bw_overhead_factor, height_ratio;
@@ -342,7 +344,8 @@
 	fp_t bins_to_bit_factor, dpb_write_factor, ten_bpc_packing_factor,
 		ten_bpc_bpp_factor, vsp_read_factor, vsp_write_factor,
 		bw_for_1x_8bpc, dpb_bw_for_1x,
-		motion_vector_complexity = 0, row_cache_penalty = 0, opb_bw = 0;
+		motion_vector_complexity = 0, row_cache_penalty = 0, opb_bw = 0,
+		dpb_total = 0;
 
 	/* Output parameters */
 	struct {
@@ -352,6 +355,10 @@
 			total;
 	} ddr = {0};
 
+	struct {
+		fp_t dpb_read, opb_read, total;
+	} llc = {0};
+
 	unsigned long ret = 0;
 	unsigned int integer_part, frac_part;
 
@@ -407,6 +414,11 @@
 	opb_compression_factor = !opb_compression_enabled ? FP_ONE :
 		__compression_ratio(__lut(width, height, fps), opb_bpp);
 
+	llc_ref_read_l2_cache_enabled = llc_vpss_ds_line_buf_enabled = false;
+	if (d->use_sys_cache) {
+		llc_ref_read_l2_cache_enabled = true;
+		llc_vpss_ds_line_buf_enabled = true;
+	}
 
 	/* Derived parameters setup */
 	lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
@@ -462,6 +474,12 @@
 
 	ddr.dpb_write = fp_div(fp_mult(dpb_bw_for_1x, dpb_write_factor),
 		dpb_write_compression_factor);
+	dpb_total = ddr.dpb_read + ddr.dpb_write;
+	if (llc_ref_read_l2_cache_enabled) {
+		row_cache_penalty = FP(1, 30, 100);
+		ddr.dpb_read = fp_div(ddr.dpb_read, row_cache_penalty);
+		llc.dpb_read = dpb_total - ddr.dpb_read;
+	}
 
 	opb_factor = dpb_bpp == 8 ? 8 : 4;
 
@@ -473,6 +491,11 @@
 		FP(1, 50, 100)), dpb_opb_scaling_ratio),
 			opb_compression_factor);
 
+	if (llc_vpss_ds_line_buf_enabled) {
+		llc.opb_read = ddr.opb_read;
+		ddr.opb_write -= ddr.opb_read;
+		ddr.opb_read = 0;
+	}
 	ddr.total = ddr.vsp_read + ddr.vsp_write +
 		ddr.collocated_read + ddr.collocated_write +
 		ddr.opb_read + ddr.opb_write +
@@ -481,6 +504,7 @@
 	qsmmu_bw_overhead_factor = FP(1, 3, 100);
 
 	ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
+	llc.total = llc.dpb_read + llc.opb_read;
 
 	/* Dump all the variables for easier debugging */
 	if (debug) {
@@ -521,6 +545,8 @@
 		{"DERIVED PARAMETERS (2)", "", DUMP_HEADER_MAGIC},
 		{"MV complexity", DUMP_FP_FMT, motion_vector_complexity},
 		{"row cache penalty", DUMP_FP_FMT, row_cache_penalty},
+		{"qsmmu_bw_overhead_factor", DUMP_FP_FMT,
+			qsmmu_bw_overhead_factor},
 		{"OPB B/W (single instance)", DUMP_FP_FMT, opb_bw},
 
 		{"INTERMEDIATE DDR B/W", "", DUMP_HEADER_MAGIC},
@@ -536,6 +562,8 @@
 		{"OPB write", DUMP_FP_FMT, ddr.opb_write},
 		{"DPB read", DUMP_FP_FMT, ddr.dpb_read},
 		{"DPB write", DUMP_FP_FMT, ddr.dpb_write},
+		{"LLC DPB read", DUMP_FP_FMT, llc.dpb_read},
+		{"LLC OPB read", DUMP_FP_FMT, llc.opb_read},
 
 		};
 		__dump(dump, ARRAY_SIZE(dump));
@@ -546,7 +574,7 @@
 		ret = kbps(fp_round(ddr.total));
 		break;
 	case GOVERNOR_LLCC:
-		dprintk(VIDC_PROF, "LLCC Voting not supported yet\n");
+		ret = kbps(fp_round(llc.total));
 		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
@@ -565,32 +593,25 @@
 	 */
 	/* Encoder Parameters */
 
-	enum hal_video_codec standard;
-	int width, height, fps;
-	enum hal_uncompressed_format dpb_color_format;
-	enum hal_uncompressed_format original_color_format;
+	int width, height, fps, dpb_bpp, lcu_per_frame, lcu_size,
+		vertical_tile_width, colocated_bytes_per_lcu, bitrate,
+		ref_overlap_bw_factor;
+	enum hal_uncompressed_format dpb_color_format, original_color_format;
 	bool dpb_compression_enabled, original_compression_enabled,
-		two_stage_encoding, low_power, rotation, cropping_or_scaling;
+		work_mode_1, low_power, rotation, cropping_or_scaling,
+		b_frames_enabled = false,
+		llc_dual_core_ref_read_buf_enabled = false,
+		llc_top_line_buf_enabled = false,
+		llc_ref_chroma_cache_enabled = false;
 	fp_t dpb_compression_factor, original_compression_factor,
-		qsmmu_bw_overhead_factor;
-	bool b_frames_enabled;
-
-	/* Derived Parameters */
-	int lcu_size;
-	enum gop {
-		GOP_IBBP,
-		GOP_IPPP,
-	} gop;
-	unsigned long bitrate;
-	fp_t bins_to_bit_factor, chroma_luma_factor_dpb, one_frame_bw_dpb,
-		 chroma_luma_factor_original, one_frame_bw_original,
-		 line_buffer_size_per_lcu, line_buffer_size, line_buffer_bw,
-		 bw_increase_p, bw_increase_b;
-	int collocated_mv_per_lcu, max_transaction_size,
-		search_window_size_vertical_p, search_window_factor_p,
-		search_window_factor_bw_p,
-		search_window_size_vertical_b, search_window_factor_b,
-		search_window_factor_bw_b;
+		input_compression_factor, qsmmu_bw_overhead_factor,
+		ref_y_bw_factor, ref_cb_cr_bw_factor, ten_bpc_bpp_factor,
+		bw_for_1x_8bpc, dpb_bw_for_1x, ref_cb_cr_read,
+		bins_to_bit_factor, ref_y_read,	ten_bpc_packing_factor,
+		dpb_write_factor, ref_overlap_bw, llc_ref_y_read,
+		llc_ref_cb_cr_read;
+	fp_t integer_part, frac_part;
+	unsigned long ret = 0;
 
 	/* Output paramaters */
 	struct {
@@ -599,27 +620,49 @@
 			original_write, dpb_read, dpb_write, total;
 	} ddr = {0};
 
-	unsigned long ret = 0;
-	fp_t integer_part, frac_part;
+	struct {
+		fp_t dpb_read, line_buffer, total;
+	} llc = {0};
 
 	/* Encoder Parameters setup */
+	ten_bpc_packing_factor = FP(1, 67, 1000);
+	ten_bpc_bpp_factor = FP(1, 1, 4);
+	rotation = false;
+	cropping_or_scaling = false;
+	vertical_tile_width = 960;
+	ref_y_bw_factor = FP(1, 30, 100);
+	ref_cb_cr_bw_factor = FP(1, 50, 100);
+	dpb_write_factor = FP(1, 8, 100);
 
-	standard = d->codec;
+
+	/* Derived Parameters */
+	lcu_size = d->lcu_size;
+	fps = d->fps;
+	b_frames_enabled = d->b_frames_enabled;
 	width = max(d->input_width, BASELINE_DIMENSIONS.width);
 	height = max(d->input_height, BASELINE_DIMENSIONS.height);
+	bitrate = __lut(width, height, fps)->bitrate;
+	lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
+		DIV_ROUND_UP(height, lcu_size);
 
 	dpb_color_format = HAL_COLOR_FORMAT_NV12_UBWC;
 	original_color_format = d->num_formats >= 1 ?
 		d->color_formats[0] : HAL_UNUSED_COLOR;
 
-	fps = d->fps;
+	dpb_bpp = d->num_formats >= 1 ? __bpp(d->color_formats[0]) : INT_MAX;
 
 	dpb_compression_enabled = __ubwc(dpb_color_format);
 	original_compression_enabled = __ubwc(original_color_format);
 
-	two_stage_encoding = false;
+	work_mode_1 = d->work_mode == VIDC_WORK_MODE_1;
 	low_power = d->power_mode == VIDC_POWER_LOW;
-	b_frames_enabled = false;
+	bins_to_bit_factor = work_mode_1 ?
+		FP_INT(0) : FP_INT(4);
+
+	if (d->use_sys_cache) {
+		llc_dual_core_ref_read_buf_enabled = true;
+		llc_ref_chroma_cache_enabled = true;
+	}
 
 	/*
 	 * Convert Q16 number into Integer and Fractional part upto 2 places.
@@ -636,96 +679,106 @@
 
 	dpb_compression_factor = FP(integer_part, frac_part, 100);
 
-	original_compression_factor = dpb_compression_factor;
+	integer_part = d->input_cr >> 16;
+	frac_part =
+		((d->input_cr - (integer_part * 65536)) * 100) >> 16;
 
-	rotation = false;
-	cropping_or_scaling = false;
+	input_compression_factor = FP(integer_part, frac_part, 100);
 
-	/* Derived Parameters */
-	lcu_size = 16;
-	gop = b_frames_enabled ? GOP_IBBP : GOP_IPPP;
-	bitrate = __lut(width, height, fps)->bitrate;
-	bins_to_bit_factor = FP(1, 6, 10);
+	original_compression_factor =
+		original_compression_enabled ? d->use_dpb_read ?
+			dpb_compression_factor : input_compression_factor :
+		FP_ONE;
 
-	/*
-	 * FIXME: Minor color format related hack: a lot of the derived params
-	 * depend on the YUV bitdepth as a variable.  However, we don't have
-	 * appropriate enums defined yet (hence no support).  As a result omit
-	 * a lot of the checks (which should look like the snippet below) in
-	 * favour of hardcoding.
-	 *      dpb_color_format == YUV420 ? 0.5 :
-	 *      dpb_color_format == YUV422 ? 1.0 : 2.0
-	 * Similar hacks are annotated inline in code with the string "CF hack"
-	 * for documentation purposes.
-	 */
-	chroma_luma_factor_dpb = FP(0, 1, 2);
-	one_frame_bw_dpb = fp_mult(FP_ONE + chroma_luma_factor_dpb,
-			fp_div(FP_INT(width * height * fps),
-				FP_INT(1000 * 1000)));
-
-	chroma_luma_factor_original = FP(0, 1, 2); /* XXX: CF hack */
-	one_frame_bw_original = fp_mult(FP_ONE + chroma_luma_factor_original,
-			fp_div(FP_INT(width * height * fps),
-				FP_INT(1000 * 1000)));
-
-	line_buffer_size_per_lcu = FP_ZERO;
-	if (lcu_size == 16)
-		line_buffer_size_per_lcu = FP_INT(128) + fp_mult(FP_INT(256),
-					FP_ONE /*XXX: CF hack */);
-	else
-		line_buffer_size_per_lcu = FP_INT(192) + fp_mult(FP_INT(512),
-					FP_ONE /*XXX: CF hack */);
-
-	line_buffer_size = fp_div(
-			fp_mult(FP_INT(width / lcu_size),
-				line_buffer_size_per_lcu),
-			FP_INT(1024));
-	line_buffer_bw = fp_mult(line_buffer_size,
-			fp_div(FP_INT((height / lcu_size /
-				(two_stage_encoding ? 2 : 1) - 1) * fps),
-				FP_INT(1000)));
-
-	collocated_mv_per_lcu = lcu_size == 16 ? 16 : 64;
-	max_transaction_size = 256;
-
-	search_window_size_vertical_p = low_power ? 32 :
-					b_frames_enabled ? 80 :
-					width > 2048 ? 64 : 48;
-	search_window_factor_p = search_window_size_vertical_p * 2 / lcu_size;
-	search_window_factor_bw_p = !two_stage_encoding ?
-		search_window_size_vertical_p * 2 / lcu_size + 1 :
-		(search_window_size_vertical_p * 2 / lcu_size + 2) / 2;
-	bw_increase_p = fp_mult(one_frame_bw_dpb,
-			FP_INT(search_window_factor_bw_p - 1) / 3);
-
-	search_window_size_vertical_b = 48;
-	search_window_factor_b = search_window_size_vertical_b * 2 / lcu_size;
-	search_window_factor_bw_b = !two_stage_encoding ?
-		search_window_size_vertical_b * 2 / lcu_size + 1 :
-		(search_window_size_vertical_b * 2 / lcu_size + 2) / 2;
-	bw_increase_b = fp_mult(one_frame_bw_dpb,
-			FP_INT((search_window_factor_bw_b - 1) / 3));
-
-	/* Output parameters for DDR */
 	ddr.vsp_read = fp_mult(fp_div(FP_INT(bitrate), FP_INT(8)),
 			bins_to_bit_factor);
 	ddr.vsp_write = ddr.vsp_read + fp_div(FP_INT(bitrate), FP_INT(8));
 
-	ddr.collocated_read = fp_div(FP_INT(DIV_ROUND_UP(width, lcu_size) *
-			DIV_ROUND_UP(height, lcu_size) *
-			collocated_mv_per_lcu * fps), FP_INT(1000 * 1000));
+	colocated_bytes_per_lcu = lcu_size == 16 ? 16 :
+				lcu_size == 32 ? 64 : 256;
+
+	ddr.collocated_read = FP_INT(lcu_per_frame *
+			colocated_bytes_per_lcu * fps / bps(1));
+
 	ddr.collocated_write = ddr.collocated_read;
 
+	ddr.line_buffer_read = FP_INT(16 * lcu_per_frame * fps / bps(1));
+
 	ddr.line_buffer_write = ddr.line_buffer_read;
 
-	ddr.original_read = fp_div(one_frame_bw_original,
-			original_compression_factor);
+	llc.line_buffer = ddr.line_buffer_read + ddr.line_buffer_write;
+	if (llc_top_line_buf_enabled)
+		ddr.line_buffer_read = ddr.line_buffer_write = FP_INT(0);
+
+	llc.line_buffer -= (ddr.line_buffer_read + ddr.line_buffer_write);
+
+	bw_for_1x_8bpc = fp_div(FP_INT(width * height), FP_INT(32 * 8));
+
+	bw_for_1x_8bpc = fp_mult(bw_for_1x_8bpc,
+		fp_div(FP_INT(256 * 30), FP_INT(1000 * 1000)));
+
+	dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc :
+		fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor,
+			ten_bpc_bpp_factor));
+
+	ddr.original_read = fp_div(fp_mult(FP(1, 50, 100), dpb_bw_for_1x),
+		input_compression_factor);
+
 	ddr.original_write = FP_ZERO;
 
-	ddr.dpb_read = FP_ZERO;
+	ref_y_bw_factor =
+		width == vertical_tile_width ? FP_INT(1) : ref_y_bw_factor;
 
-	ddr.dpb_read = fp_div(ddr.dpb_read, dpb_compression_factor);
-	ddr.dpb_write = fp_div(one_frame_bw_dpb, dpb_compression_factor);
+	ref_y_read = fp_mult(ref_y_bw_factor, dpb_bw_for_1x);
+
+	ref_y_read = fp_div(ref_y_read, dpb_compression_factor);
+
+	ref_y_read =
+		b_frames_enabled ? fp_mult(ref_y_read, FP_INT(2)) : ref_y_read;
+
+	llc_ref_y_read = ref_y_read;
+	if (llc_dual_core_ref_read_buf_enabled)
+		ref_y_read = fp_div(ref_y_read, FP_INT(2));
+
+	llc_ref_y_read -= ref_y_read;
+
+	ref_cb_cr_read = fp_mult(ref_cb_cr_bw_factor, dpb_bw_for_1x);
+
+	ref_cb_cr_read = fp_div(ref_cb_cr_read, dpb_compression_factor);
+
+	ref_cb_cr_read =
+		b_frames_enabled ? fp_mult(ref_cb_cr_read, FP_INT(2)) :
+					ref_cb_cr_read;
+
+	llc_ref_cb_cr_read = ref_cb_cr_read;
+
+	if (llc_ref_chroma_cache_enabled)
+		ref_cb_cr_read = fp_div(ref_cb_cr_read, ref_cb_cr_bw_factor);
+
+	if (llc_dual_core_ref_read_buf_enabled)
+		ref_cb_cr_read = fp_div(ref_cb_cr_read, FP_INT(2));
+
+	llc_ref_cb_cr_read -= ref_cb_cr_read;
+
+	ddr.dpb_write = fp_mult(dpb_write_factor, dpb_bw_for_1x);
+
+	ddr.dpb_write = fp_mult(ddr.dpb_write, FP(1, 50, 100));
+
+	ddr.dpb_write = fp_div(ddr.dpb_write, input_compression_factor);
+
+	ref_overlap_bw_factor =
+		width <= vertical_tile_width ? FP_INT(0) : FP_INT(1);
+
+	ref_overlap_bw = fp_mult(ddr.dpb_write, ref_overlap_bw_factor);
+
+	ref_overlap_bw = fp_div(ref_overlap_bw, dpb_write_factor);
+
+	ref_overlap_bw = fp_mult(ref_overlap_bw,
+		(dpb_write_factor - FP_INT(1)));
+
+	ddr.dpb_read = ref_y_read + ref_cb_cr_read + ref_overlap_bw;
+
+	llc.dpb_read = llc_ref_y_read + llc_ref_cb_cr_read;
 
 	ddr.total = ddr.vsp_read + ddr.vsp_write +
 		ddr.collocated_read + ddr.collocated_write +
@@ -733,13 +786,14 @@
 		ddr.original_read + ddr.original_write +
 		ddr.dpb_read + ddr.dpb_write;
 
+	llc.total = llc.dpb_read + llc.line_buffer;
+
 	qsmmu_bw_overhead_factor = FP(1, 3, 100);
 	ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
 
 	if (debug) {
 		struct dump dump[] = {
 		{"ENCODER PARAMETERS", "", DUMP_HEADER_MAGIC},
-		{"standard", "%#x", standard},
 		{"width", "%d", width},
 		{"height", "%d", height},
 		{"DPB format", "%#x", dpb_color_format},
@@ -748,8 +802,8 @@
 		{"DPB compression enable", "%d", dpb_compression_enabled},
 		{"original compression enable", "%d",
 			original_compression_enabled},
-		{"two stage encoding", "%d", two_stage_encoding},
 		{"low power mode", "%d", low_power},
+		{"Work Mode", "%d", work_mode_1},
 		{"DPB compression factor", DUMP_FP_FMT,
 			dpb_compression_factor},
 		{"original compression factor", DUMP_FP_FMT,
@@ -759,46 +813,27 @@
 
 		{"DERIVED PARAMETERS", "", DUMP_HEADER_MAGIC},
 		{"LCU size", "%d", lcu_size},
-		{"GOB pattern", "%d", gop},
 		{"bitrate (Mbit/sec)", "%lu", bitrate},
 		{"bins to bit factor", DUMP_FP_FMT, bins_to_bit_factor},
-		{"B-frames enabled", "%d", b_frames_enabled},
-		{"search window size vertical (B)", "%d",
-			search_window_size_vertical_b},
-		{"search window factor (B)", "%d", search_window_factor_b},
-		{"search window factor BW (B)", "%d",
-			search_window_factor_bw_b},
-		{"bw increase (MB/s) (B)", DUMP_FP_FMT, bw_increase_b},
-		{"search window size vertical (P)", "%d",
-			search_window_size_vertical_p},
-		{"search window factor (P)", "%d", search_window_factor_p},
-		{"search window factor BW (P)", "%d",
-			search_window_factor_bw_p},
-		{"bw increase (MB/s) (P)", DUMP_FP_FMT, bw_increase_p},
-		{"chroma/luma factor DPB", DUMP_FP_FMT,
-			chroma_luma_factor_dpb},
-		{"one frame BW DPB (MB/s)", DUMP_FP_FMT, one_frame_bw_dpb},
-		{"chroma/Luma factor original", DUMP_FP_FMT,
-			chroma_luma_factor_original},
-		{"one frame BW original (MB/s)", DUMP_FP_FMT,
-			one_frame_bw_original},
-		{"line buffer size per LCU", DUMP_FP_FMT,
-			line_buffer_size_per_lcu},
-		{"line buffer size (KB)", DUMP_FP_FMT, line_buffer_size},
-		{"line buffer BW (MB/s)", DUMP_FP_FMT, line_buffer_bw},
-		{"collocated MVs per LCU", "%d", collocated_mv_per_lcu},
+		{"qsmmu_bw_overhead_factor",
+			 DUMP_FP_FMT, qsmmu_bw_overhead_factor},
 
 		{"INTERMEDIATE B/W DDR", "", DUMP_HEADER_MAGIC},
+		{"ref_y_read", DUMP_FP_FMT, ref_y_read},
+		{"ref_cb_cr_read", DUMP_FP_FMT, ref_cb_cr_read},
+		{"ref_overlap_bw", DUMP_FP_FMT, ref_overlap_bw},
 		{"VSP read", DUMP_FP_FMT, ddr.vsp_read},
-		{"VSP read", DUMP_FP_FMT, ddr.vsp_write},
+		{"VSP write", DUMP_FP_FMT, ddr.vsp_write},
 		{"collocated read", DUMP_FP_FMT, ddr.collocated_read},
-		{"collocated read", DUMP_FP_FMT, ddr.collocated_write},
+		{"collocated write", DUMP_FP_FMT, ddr.collocated_write},
 		{"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read},
-		{"line buffer read", DUMP_FP_FMT, ddr.line_buffer_write},
+		{"line buffer write", DUMP_FP_FMT, ddr.line_buffer_write},
 		{"original read", DUMP_FP_FMT, ddr.original_read},
-		{"original read", DUMP_FP_FMT, ddr.original_write},
+		{"original write", DUMP_FP_FMT, ddr.original_write},
 		{"DPB read", DUMP_FP_FMT, ddr.dpb_read},
 		{"DPB write", DUMP_FP_FMT, ddr.dpb_write},
+		{"LLC DPB read", DUMP_FP_FMT, llc.dpb_read},
+		{"LLC Line buffer", DUMP_FP_FMT, llc.line_buffer},
 		};
 		__dump(dump, ARRAY_SIZE(dump));
 	}
@@ -808,7 +843,7 @@
 		ret = kbps(fp_round(ddr.total));
 		break;
 	case GOVERNOR_LLCC:
-		dprintk(VIDC_PROF, "LLCC Voting not supported yet\n");
+		ret = kbps(fp_round(llc.total));
 		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 32e79f2..e49ea72 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1238,10 +1238,8 @@
 			pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_VFR;
 			break;
 		case HAL_RATE_CONTROL_VBR_CFR:
-			pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
-			break;
 		case HAL_RATE_CONTROL_VBR_VFR:
-			pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
+			pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
 			break;
 		case HAL_RATE_CONTROL_MBR_CFR:
 			pkt->rg_property_data[1] = HFI_RATE_CONTROL_MBR_CFR;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index e5d1576..efe4ca3 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -775,6 +775,47 @@
 	return size;
 }
 
+static int copy_profile_caps_to_sessions(struct hfi_profile_level *prof,
+		u32 profile_count, struct msm_vidc_capability *capabilities,
+		u32 num_sessions, u32 codecs, u32 domain)
+{
+	u32 i = 0, j = 0;
+	struct msm_vidc_capability *capability;
+	u32 sess_codec;
+	u32 sess_domain;
+
+	/*
+	 * iterate over num_sessions and copy all the profile capabilities
+	 * to matching sessions.
+	 */
+	for (i = 0; i < num_sessions; i++) {
+		sess_codec = 0;
+		sess_domain = 0;
+		capability = &capabilities[i];
+
+		if (capability->codec)
+			sess_codec =
+				vidc_get_hfi_codec(capability->codec);
+		if (capability->domain)
+			sess_domain =
+				vidc_get_hfi_domain(capability->domain);
+
+		if (!(sess_codec & codecs && sess_domain & domain))
+			continue;
+
+		capability->profile_level.profile_count = profile_count;
+		for (j = 0; j < profile_count; j++) {
+			/* HFI and HAL follow same enums, hence no conversion */
+			capability->profile_level.profile_level[j].profile =
+				prof[j].profile;
+			capability->profile_level.profile_level[j].level =
+				prof[j].level;
+		}
+	}
+
+	return 0;
+}
+
 static int copy_caps_to_sessions(struct hfi_capability_supported *cap,
 		u32 num_caps, struct msm_vidc_capability *capabilities,
 		u32 num_sessions, u32 codecs, u32 domain)
@@ -914,38 +955,25 @@
 		}
 		case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
 		{
-			struct msm_vidc_capability capability;
-			char *ptr = NULL;
-			u32 count = 0;
-			u32 prof_count = 0;
-			struct hfi_profile_level *prof_level;
 			struct hfi_profile_level_supported *prop =
 				(struct hfi_profile_level_supported *)
 				(data_ptr + next_offset);
 
-			ptr = (char *) &prop->rg_profile_level[0];
-			prof_count = prop->profile_count;
-			next_offset += sizeof(u32);
+			next_offset += sizeof(u32) +
+				prop->profile_count *
+				sizeof(struct hfi_profile_level);
 
-			if (prof_count > MAX_PROFILE_COUNT) {
-				prof_count = MAX_PROFILE_COUNT;
+			if (prop->profile_count > MAX_PROFILE_COUNT) {
+				prop->profile_count = MAX_PROFILE_COUNT;
 				dprintk(VIDC_WARN,
 					"prop count exceeds max profile count\n");
 				break;
 			}
-			while (prof_count) {
-				prof_level = (struct hfi_profile_level *)ptr;
-				capability.
-				profile_level.profile_level[count].profile
-					= prof_level->profile;
-				capability.
-				profile_level.profile_level[count].level
-					= prof_level->level;
-				prof_count--;
-				count++;
-				ptr += sizeof(struct hfi_profile_level);
-				next_offset += sizeof(struct hfi_profile_level);
-			}
+
+			copy_profile_caps_to_sessions(
+					&prop->rg_profile_level[0],
+					prop->profile_count, capabilities,
+					num_sessions, codecs, domain);
 			num_properties--;
 			break;
 		}
@@ -1140,6 +1168,12 @@
 			buffreq->buffer[10].buffer_type =
 				HAL_BUFFER_INTERNAL_PERSIST_1;
 			break;
+		case HFI_BUFFER_COMMON_INTERNAL_RECON:
+			memcpy(&buffreq->buffer[11], hfi_buf_req,
+			sizeof(struct hfi_buffer_requirements));
+			buffreq->buffer[11].buffer_type =
+				HAL_BUFFER_INTERNAL_RECON;
+			break;
 		default:
 			dprintk(VIDC_ERR,
 			"hal_process_sess_get_prop_buf_req: bad_buffer_type: %d\n",
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 8c63469..54766a2 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -347,6 +347,14 @@
 	}
 
 	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
+
+	mutex_lock(&core->lock);
+	core->vote_data = kcalloc(MAX_SUPPORTED_INSTANCES,
+		sizeof(*core->vote_data), GFP_KERNEL);
+	if (!core->vote_data)
+		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
+	mutex_unlock(&core->lock);
+
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 5c587e2..69070d5 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1553,23 +1553,25 @@
 			break;
 		}
 
-		buff_req_buffer = get_buff_req_buffer(inst,
-			HAL_BUFFER_EXTRADATA_INPUT);
-
 		extra_idx = EXTRADATA_IDX(inst->bufq[OUTPUT_PORT].num_planes);
+		if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+			buff_req_buffer = get_buff_req_buffer(inst,
+						HAL_BUFFER_EXTRADATA_INPUT);
 
-		inst->bufq[OUTPUT_PORT].plane_sizes[extra_idx] =
-			buff_req_buffer ?
-			buff_req_buffer->buffer_size : 0;
-
-		buff_req_buffer = get_buff_req_buffer(inst,
-			HAL_BUFFER_EXTRADATA_OUTPUT);
+			inst->bufq[OUTPUT_PORT].plane_sizes[extra_idx] =
+					buff_req_buffer ?
+					buff_req_buffer->buffer_size : 0;
+		}
 
 		extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
-		inst->bufq[CAPTURE_PORT].plane_sizes[extra_idx] =
-			buff_req_buffer ?
-			buff_req_buffer->buffer_size : 0;
+		if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+			buff_req_buffer = get_buff_req_buffer(inst,
+						HAL_BUFFER_EXTRADATA_OUTPUT);
 
+			inst->bufq[CAPTURE_PORT].plane_sizes[extra_idx] =
+				buff_req_buffer ?
+				buff_req_buffer->buffer_size : 0;
+		}
 		property_id = 0;
 		}
 		break;
@@ -1597,7 +1599,7 @@
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME:
 		property_id = HAL_CONFIG_VENC_USELTRFRAME;
-		use_ltr.ref_ltr = ctrl->val;
+		use_ltr.ref_ltr = 0x1 << ctrl->val;
 		use_ltr.use_constraint = false;
 		use_ltr.frames = 0;
 		pdata = &use_ltr;
@@ -2360,6 +2362,7 @@
 			rc = -EINVAL;
 			goto exit;
 		}
+		inst->clk_data.opb_fourcc = f->fmt.pix_mp.pixelformat;
 		memcpy(&inst->fmts[fmt->type], fmt,
 				sizeof(struct msm_vidc_format));
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 427568c..971e57a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -140,7 +140,8 @@
 int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *ctrl)
 {
 	struct msm_vidc_inst *inst = instance;
-	int rc = 0;
+	struct hal_profile_level_supported *prof_level_supported;
+	int rc = 0, i = 0, profile_mask = 0, v4l2_prof_value = 0, max_level = 0;
 
 	if (!inst || !ctrl)
 		return -EINVAL;
@@ -178,6 +179,43 @@
 	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
 		msm_vidc_ctrl_get_range(ctrl, &inst->capability.slice_bytes);
 		break;
+	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
+	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
+	{
+		prof_level_supported = &inst->capability.profile_level;
+		for (i = 0; i < prof_level_supported->profile_count; i++) {
+			v4l2_prof_value = msm_comm_hal_to_v4l2(ctrl->id,
+				prof_level_supported->profile_level[i].profile);
+			if (v4l2_prof_value == -EINVAL) {
+				dprintk(VIDC_WARN, "Invalid profile");
+				rc = -EINVAL;
+			}
+			profile_mask |= (1 << v4l2_prof_value);
+		}
+		ctrl->flags = profile_mask;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+	case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
+	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
+	{
+		prof_level_supported = &inst->capability.profile_level;
+		for (i = 0; i < prof_level_supported->profile_count; i++) {
+			if (max_level < prof_level_supported->
+				profile_level[i].level) {
+				max_level = prof_level_supported->
+					profile_level[i].level;
+			}
+		}
+		ctrl->maximum = msm_comm_hal_to_v4l2(ctrl->id, max_level);
+		if (ctrl->maximum == -EINVAL) {
+			dprintk(VIDC_WARN, "Invalid max level");
+			rc = -EINVAL;
+		}
+		break;
+	}
 	default:
 		rc = -EINVAL;
 	}
@@ -426,6 +464,12 @@
 		if (vb2->type != type || vb2->index != index)
 			continue;
 
+		if (mbuf->flags & MSM_VIDC_FLAG_RBR_PENDING) {
+			print_vidc_buffer(VIDC_DBG,
+				"skip rel buf (rbr pending)", inst, mbuf);
+			continue;
+		}
+
 		print_vidc_buffer(VIDC_DBG, "release buf", inst, mbuf);
 		msm_comm_unmap_vidc_buffer(inst, mbuf);
 		list_del(&mbuf->list);
@@ -442,6 +486,7 @@
 	struct msm_vidc_inst *inst = instance;
 	int rc = 0, i = 0;
 	struct buf_queue *q = NULL;
+	u32 cr = 0;
 
 	if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
 		dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
@@ -453,8 +498,16 @@
 		b->m.planes[i].m.fd = b->m.planes[i].reserved[0];
 		b->m.planes[i].data_offset = b->m.planes[i].reserved[1];
 	}
+
 	msm_comm_qbuf_cache_operations(inst, b);
 
+	/* Compression ratio is valid only for Encoder YUV buffers. */
+	if (inst->session_type == MSM_VIDC_ENCODER &&
+			b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		cr = b->m.planes[0].reserved[2];
+		msm_comm_update_input_cr(inst, b->index, cr);
+	}
+
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
 		dprintk(VIDC_ERR,
@@ -712,7 +765,6 @@
 		rc = set_buffer_count(inst, bufreq->buffer_count_min_host,
 			bufreq->buffer_count_actual, HAL_BUFFER_INPUT);
 		}
-
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: {
 		buffer_type = msm_comm_get_hal_output_buffer(inst);
@@ -1116,7 +1168,7 @@
 
 	q->mem_ops = &msm_vidc_vb2_mem_ops;
 	q->drv_priv = inst;
-	q->allow_zero_bytesused = 1;
+	q->allow_zero_bytesused = !V4L2_TYPE_IS_OUTPUT(type);
 	q->copy_timestamp = 1;
 	return vb2_queue_init(q);
 }
@@ -1494,11 +1546,13 @@
 
 	INIT_MSM_VIDC_LIST(&inst->scratchbufs);
 	INIT_MSM_VIDC_LIST(&inst->freqs);
+	INIT_MSM_VIDC_LIST(&inst->input_crs);
 	INIT_MSM_VIDC_LIST(&inst->persistbufs);
 	INIT_MSM_VIDC_LIST(&inst->pending_getpropq);
 	INIT_MSM_VIDC_LIST(&inst->outputbufs);
 	INIT_MSM_VIDC_LIST(&inst->registeredbufs);
 	INIT_MSM_VIDC_LIST(&inst->reconbufs);
+	INIT_MSM_VIDC_LIST(&inst->eosbufs);
 
 	kref_init(&inst->kref);
 
@@ -1603,6 +1657,9 @@
 	DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
 	DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
 	DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->freqs);
+	DEINIT_MSM_VIDC_LIST(&inst->input_crs);
 
 	kfree(inst);
 	inst = NULL;
@@ -1632,6 +1689,8 @@
 
 	msm_comm_free_freq_table(inst);
 
+	msm_comm_free_input_cr_table(inst);
+
 	if (msm_comm_release_scratch_buffers(inst, false))
 		dprintk(VIDC_ERR,
 			"Failed to release scratch buffers\n");
@@ -1650,6 +1709,8 @@
 	 */
 	msm_comm_validate_output_buffers(inst);
 
+	msm_comm_release_eos_buffers(inst);
+
 	if (msm_comm_release_output_buffers(inst, true))
 		dprintk(VIDC_ERR,
 			"Failed to release output buffers\n");
@@ -1694,6 +1755,9 @@
 	DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
 	DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
 	DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->freqs);
+	DEINIT_MSM_VIDC_LIST(&inst->input_crs);
 
 	mutex_destroy(&inst->sync_lock);
 	mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 4327309..51023f0 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -19,6 +19,9 @@
 #define MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR (1 << 16)
 #define MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR (4 << 16)
 
+#define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16)
+#define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16)
+
 static inline unsigned long int get_ubwc_compression_ratio(
 	struct ubwc_cr_stats_info_type ubwc_stats_info)
 {
@@ -90,36 +93,56 @@
 	mutex_unlock(&inst->reconbufs.lock);
 }
 
-static int fill_recon_stats(struct msm_vidc_inst *inst,
+static int fill_dynamic_stats(struct msm_vidc_inst *inst,
 	struct vidc_bus_vote_data *vote_data)
 {
-	struct recon_buf *binfo;
-	u32 CR = 0, min_cf = MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR,
-		max_cf = MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR;
+	struct recon_buf *binfo, *nextb;
+	struct vidc_input_cr_data *temp, *next;
+	u32 min_cf = 0, max_cf = 0;
+	u32 min_input_cr = 0, max_input_cr = 0, min_cr = 0, max_cr = 0;
 
 	mutex_lock(&inst->reconbufs.lock);
-	list_for_each_entry(binfo, &inst->reconbufs.list, list) {
-		CR = max(CR, binfo->CR);
+	list_for_each_entry_safe(binfo, nextb, &inst->reconbufs.list, list) {
+		min_cr = min(min_cr, binfo->CR);
+		max_cr = max(max_cr, binfo->CR);
 		min_cf = min(min_cf, binfo->CF);
 		max_cf = max(max_cf, binfo->CF);
 	}
 	mutex_unlock(&inst->reconbufs.lock);
 
+	mutex_lock(&inst->input_crs.lock);
+	list_for_each_entry_safe(temp, next, &inst->input_crs.list, list) {
+		min_input_cr = min(min_input_cr, temp->input_cr);
+		max_input_cr = max(max_input_cr, temp->input_cr);
+	}
+	mutex_unlock(&inst->input_crs.lock);
+
 	/* Sanitize CF values from HW . */
 	max_cf = min_t(u32, max_cf, MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR);
 	min_cf = max_t(u32, min_cf, MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR);
+	max_cr = min_t(u32, max_cr, MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO);
+	min_cr = max_t(u32, min_cr, MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO);
+	max_input_cr = min_t(u32,
+		max_input_cr, MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO);
+	min_input_cr = max_t(u32,
+		min_input_cr, MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO);
 
-	vote_data->compression_ratio = CR;
+	vote_data->compression_ratio = min_cr;
 	vote_data->complexity_factor = max_cf;
+	vote_data->input_cr = min_input_cr;
 	vote_data->use_dpb_read = false;
+
+	/* Check if driver can vote for lower bus BW */
 	if (inst->clk_data.load <= inst->clk_data.load_norm) {
+		vote_data->compression_ratio = max_cr;
 		vote_data->complexity_factor = min_cf;
+		vote_data->input_cr = max_input_cr;
 		vote_data->use_dpb_read = true;
 	}
 
-	dprintk(VIDC_DBG,
-		"Compression Ratio = %d Complexity Factor = %d\n",
-			vote_data->compression_ratio,
+	dprintk(VIDC_PROF,
+		"Input CR = %d Recon CR = %d Complexity Factor = %d\n",
+			vote_data->input_cr, vote_data->compression_ratio,
 			vote_data->complexity_factor);
 
 	return 0;
@@ -139,15 +162,16 @@
 
 	hdev = core->device;
 
+	mutex_lock(&core->lock);
 	vote_data = core->vote_data;
 	if (!vote_data) {
 		dprintk(VIDC_PROF,
 			"Failed to get vote_data for inst %pK\n",
 				inst);
+		mutex_unlock(&core->lock);
 		return -EINVAL;
 	}
 
-	mutex_lock(&core->lock);
 	list_for_each_entry(inst, &core->instances, list) {
 		int codec = 0;
 		struct msm_vidc_buffer *temp, *next;
@@ -157,6 +181,7 @@
 		if (!inst) {
 			dprintk(VIDC_ERR, "%s Invalid args\n",
 				__func__);
+			mutex_unlock(&core->lock);
 			return -EINVAL;
 		}
 
@@ -165,7 +190,7 @@
 				&inst->registeredbufs.list, list) {
 			if (temp->vvb.vb2_buf.type ==
 				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
-					temp->deferred) {
+					temp->flags & MSM_VIDC_FLAG_DEFERRED) {
 				filled_len = max(filled_len,
 					temp->vvb.vb2_buf.planes[0].bytesused);
 				device_addr = temp->smem[0].device_addr;
@@ -184,6 +209,8 @@
 			inst->fmts[OUTPUT_PORT].fourcc :
 			inst->fmts[CAPTURE_PORT].fourcc;
 
+		memset(&(vote_data[i]), 0x0, sizeof(struct vidc_bus_vote_data));
+
 		vote_data[i].domain = get_hal_domain(inst->session_type);
 		vote_data[i].codec = get_hal_codec(codec);
 		vote_data[i].input_width =  max(inst->prop.width[OUTPUT_PORT],
@@ -196,6 +223,9 @@
 				max(inst->prop.height[CAPTURE_PORT],
 				inst->prop.height[OUTPUT_PORT]);
 		vote_data[i].lcu_size = codec == V4L2_PIX_FMT_HEVC ? 32 : 16;
+		vote_data[i].b_frames_enabled =
+			msm_comm_g_ctrl_for_id(inst,
+				V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES) != 0;
 
 		if (inst->clk_data.operating_rate)
 			vote_data[i].fps =
@@ -225,9 +255,9 @@
 			vote_data[i].num_formats = 2;
 		}
 		vote_data[i].work_mode = inst->clk_data.work_mode;
-		fill_recon_stats(inst, &vote_data[i]);
+		fill_dynamic_stats(inst, &vote_data[i]);
 
-		if (core->resources.sys_cache_enabled)
+		if (core->resources.sys_cache_res_set)
 			vote_data[i].use_sys_cache = true;
 
 		i++;
@@ -354,10 +384,15 @@
 
 	if (!found) {
 		temp = kzalloc(sizeof(*temp), GFP_KERNEL);
+		if (!temp) {
+			dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
+			goto exit;
+		}
 		temp->freq = freq;
 		temp->device_addr = device_addr;
 		list_add_tail(&temp->list, &inst->freqs.list);
 	}
+exit:
 	mutex_unlock(&inst->freqs.lock);
 }
 
@@ -413,6 +448,48 @@
 	mutex_unlock(&inst->freqs.lock);
 }
 
+void msm_comm_free_input_cr_table(struct msm_vidc_inst *inst)
+{
+	struct vidc_input_cr_data *temp, *next;
+
+	mutex_lock(&inst->input_crs.lock);
+	list_for_each_entry_safe(temp, next, &inst->input_crs.list, list) {
+		list_del(&temp->list);
+		kfree(temp);
+	}
+	INIT_LIST_HEAD(&inst->input_crs.list);
+	mutex_unlock(&inst->input_crs.lock);
+}
+
+void msm_comm_update_input_cr(struct msm_vidc_inst *inst,
+	u32 index, u32 cr)
+{
+	struct vidc_input_cr_data *temp, *next;
+	bool found = false;
+
+	mutex_lock(&inst->input_crs.lock);
+	list_for_each_entry_safe(temp, next, &inst->input_crs.list, list) {
+		if (temp->index == index) {
+			temp->input_cr = cr;
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		temp = kzalloc(sizeof(*temp), GFP_KERNEL);
+		if (!temp)  {
+			dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
+			goto exit;
+		}
+		temp->index = index;
+		temp->input_cr = cr;
+		list_add_tail(&temp->list, &inst->input_crs.list);
+	}
+exit:
+	mutex_unlock(&inst->input_crs.lock);
+}
+
 static unsigned long msm_vidc_max_freq(struct msm_vidc_core *core)
 {
 	struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
@@ -599,7 +676,7 @@
 	list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
 		if (temp->vvb.vb2_buf.type ==
 				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
-					temp->deferred) {
+					temp->flags & MSM_VIDC_FLAG_DEFERRED) {
 			filled_len = max(filled_len,
 				temp->vvb.vb2_buf.planes[0].bytesused);
 			device_addr = temp->smem[0].device_addr;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index 705cb7c..707f034 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -33,6 +33,9 @@
 int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst);
 void msm_vidc_clear_freq_entry(struct msm_vidc_inst *inst,
 	u32 device_addr);
+void msm_comm_free_input_cr_table(struct msm_vidc_inst *inst);
+void msm_comm_update_input_cr(struct msm_vidc_inst *inst, u32 index,
+	u32 cr);
 void update_recon_stats(struct msm_vidc_inst *inst,
 	struct recon_stats_type *recon_stats);
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 03ad0a0..69a9fc1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -35,8 +35,6 @@
 		V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE
 #define L_MODE V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
 
-#define MAX_SUPPORTED_INSTANCES 16
-
 const char *const mpeg_video_vidc_extradata[] = {
 	"Extradata none",
 	"Extradata MB Quantization",
@@ -81,7 +79,6 @@
 static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst);
 static void handle_session_error(enum hal_command_response cmd, void *data);
 static void msm_vidc_print_running_insts(struct msm_vidc_core *core);
-static void msm_comm_print_debug_info(struct msm_vidc_inst *inst);
 
 bool msm_comm_turbo_session(struct msm_vidc_inst *inst)
 {
@@ -957,8 +954,8 @@
 	/* This should come from sys_init_done */
 	core->resources.max_inst_count =
 		sys_init_msg->max_sessions_supported ?
-		sys_init_msg->max_sessions_supported :
-		MAX_SUPPORTED_INSTANCES;
+		min_t(u32, sys_init_msg->max_sessions_supported,
+		MAX_SUPPORTED_INSTANCES) : MAX_SUPPORTED_INSTANCES;
 
 	core->resources.max_secure_inst_count =
 		core->resources.max_secure_inst_count ?
@@ -979,11 +976,6 @@
 		__func__, core->codec_count, core->enc_codec_supported,
 		core->dec_codec_supported);
 
-	core->vote_data = kcalloc(MAX_SUPPORTED_INSTANCES,
-		sizeof(core->vote_data), GFP_KERNEL);
-	if (!core->vote_data)
-		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
-
 	complete(&(core->completions[index]));
 }
 
@@ -1434,6 +1426,15 @@
 	print_cap("max_work_modes", &inst->capability.max_work_modes);
 	print_cap("ubwc_cr_stats", &inst->capability.ubwc_cr_stats);
 
+	dprintk(VIDC_DBG, "profile count : %u",
+		inst->capability.profile_level.profile_count);
+	for (i = 0; i < inst->capability.profile_level.profile_count; i++) {
+		dprintk(VIDC_DBG, "profile : %u ", inst->capability.
+			profile_level.profile_level[i].profile);
+		dprintk(VIDC_DBG, "level   : %u ", inst->capability.
+			profile_level.profile_level[i].level);
+	}
+
 	signal_session_msg_receipt(cmd, inst);
 
 	/*
@@ -2036,6 +2037,7 @@
 	}
 
 	dprintk(VIDC_WARN, "SYS_ERROR received for core %pK\n", core);
+	msm_vidc_noc_error_info(core);
 	call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
 	list_for_each_entry(inst, &core->instances, list) {
 		dprintk(VIDC_WARN,
@@ -2180,6 +2182,26 @@
 	return 0;
 }
 
+static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr)
+{
+	struct eos_buf *temp, *next;
+	bool found = false;
+
+	mutex_lock(&inst->eosbufs.lock);
+	list_for_each_entry_safe(temp, next, &inst->eosbufs.list, list) {
+		if (temp->smem.device_addr == device_addr) {
+			found = true;
+			list_del(&temp->list);
+			msm_comm_smem_free(inst, &temp->smem);
+			kfree(temp);
+			break;
+		}
+	}
+	mutex_unlock(&inst->eosbufs.lock);
+
+	return found;
+}
+
 static void handle_ebd(enum hal_command_response cmd, void *data)
 {
 	struct msm_vidc_cb_data_done *response = data;
@@ -2204,6 +2226,13 @@
 	}
 
 	empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
+	/* If this is internal EOS buffer, handle it in driver */
+	if (is_eos_buffer(inst, empty_buf_done->packet_buffer)) {
+		dprintk(VIDC_DBG, "Received EOS buffer %pK\n",
+			(void *)(u64)empty_buf_done->packet_buffer);
+		goto exit;
+	}
+
 	planes[0] = empty_buf_done->packet_buffer;
 	planes[1] = empty_buf_done->extra_data_buffer;
 
@@ -2688,8 +2717,6 @@
 int msm_comm_check_core_init(struct msm_vidc_core *core)
 {
 	int rc = 0;
-	struct hfi_device *hdev;
-	struct msm_vidc_inst *inst = NULL;
 
 	mutex_lock(&core->lock);
 	if (core->state >= VIDC_CORE_INIT_DONE) {
@@ -2698,29 +2725,12 @@
 		goto exit;
 	}
 	dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
-	hdev = (struct hfi_device *)core->device;
 	rc = wait_for_completion_timeout(
 		&core->completions[SYS_MSG_INDEX(HAL_SYS_INIT_DONE)],
 		msecs_to_jiffies(core->resources.msm_vidc_hw_rsp_timeout));
 	if (!rc) {
 		dprintk(VIDC_ERR, "%s: Wait interrupted or timed out: %d\n",
 				__func__, SYS_MSG_INDEX(HAL_SYS_INIT_DONE));
-		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
-		dprintk(VIDC_ERR,
-			"SYS_INIT timeout can potentially crash the system\n");
-		/*
-		 * For SYS_INIT, there will not be any inst pointer.
-		 * Just grab one of the inst from instances list and
-		 * use it.
-		 */
-		inst = list_first_entry(&core->instances,
-			struct msm_vidc_inst, list);
-
-		mutex_unlock(&core->lock);
-		msm_comm_print_debug_info(inst);
-		mutex_lock(&core->lock);
-
-		msm_vidc_handle_hw_error(core);
 		rc = -EIO;
 		goto exit;
 	} else {
@@ -3686,6 +3696,64 @@
 		rc = msm_comm_session_continue(inst);
 		break;
 	}
+	case V4L2_DEC_CMD_STOP:
+	{
+		struct vidc_frame_data data = {0};
+		struct hfi_device *hdev;
+		struct eos_buf *binfo;
+		u32 smem_flags = 0;
+
+		get_inst(inst->core, inst);
+		if (inst->session_type != MSM_VIDC_DECODER) {
+			dprintk(VIDC_DBG,
+				"Non-Decoder session. DEC_STOP is not valid\n");
+			rc = -EINVAL;
+			goto exit;
+		}
+
+		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+		if (!binfo) {
+			dprintk(VIDC_ERR, "%s: Out of memory\n", __func__);
+			rc = -ENOMEM;
+			goto exit;
+		}
+
+		if (inst->flags & VIDC_SECURE)
+			smem_flags |= SMEM_SECURE;
+
+		rc = msm_comm_smem_alloc(inst,
+				SZ_4K, 1, smem_flags,
+				HAL_BUFFER_INPUT, 0, &binfo->smem);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Failed to allocate output memory\n");
+			goto exit;
+		}
+
+		mutex_lock(&inst->eosbufs.lock);
+		list_add_tail(&binfo->list, &inst->eosbufs.list);
+		mutex_unlock(&inst->eosbufs.lock);
+
+		data.alloc_len = binfo->smem.size;
+		data.device_addr = binfo->smem.device_addr;
+		data.clnt_data = data.device_addr;
+		data.buffer_type = HAL_BUFFER_INPUT;
+		data.filled_len = 0;
+		data.offset = 0;
+		data.flags = HAL_BUFFERFLAG_EOS;
+		data.timestamp = LLONG_MAX;
+		data.extradata_addr = data.device_addr;
+		data.extradata_size = 0;
+		dprintk(VIDC_DBG, "Queueing EOS buffer %pK\n",
+			(void *)(u64)data.device_addr);
+		hdev = inst->core->device;
+
+		rc = call_hfi_op(hdev, session_etb, inst->session,
+				&data);
+exit:
+		put_inst(inst);
+		break;
+	}
 	default:
 		dprintk(VIDC_ERR, "Unknown Command %d\n", which_cmd);
 		rc = -ENOTSUPP;
@@ -3772,7 +3840,7 @@
 			continue;
 
 		/* count only deferred buffers */
-		if (!mbuf->deferred)
+		if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
 			continue;
 
 		++count;
@@ -3800,7 +3868,7 @@
 			continue;
 
 		/* count only deferred buffers */
-		if (!mbuf->deferred)
+		if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
 			continue;
 
 		++count;
@@ -3848,6 +3916,41 @@
 	}
 }
 
+static int msm_comm_qbuf_rbr(struct msm_vidc_inst *inst,
+		struct msm_vidc_buffer *mbuf)
+{
+	int rc = 0;
+	struct hfi_device *hdev;
+	struct vidc_frame_data frame_data = {0};
+
+	if (!inst || !inst->core || !inst->core->device || !mbuf) {
+		dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
+	if (inst->state == MSM_VIDC_CORE_INVALID) {
+		dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_comm_scale_clocks_and_bus(inst);
+	populate_frame_data(&frame_data, mbuf, inst);
+
+	rc = call_hfi_op(hdev, session_ftb, inst->session, &frame_data);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to issue ftb: %d\n", rc);
+		goto err_bad_input;
+	}
+
+	log_frame(inst, &frame_data, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+err_bad_input:
+	return rc;
+}
+
+
 /*
  * Attempts to queue `vb` to hardware.  If, for various reasons, the buffer
  * cannot be queued to hardware, the buffer will be staged for commit in the
@@ -3879,10 +3982,6 @@
 		return -EINVAL;
 	}
 
-	/* initially assume every buffer is going to be deferred */
-	if (mbuf)
-		mbuf->deferred = true;
-
 	batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
 		== V4L2_VIDC_QBUF_BATCHED;
 	capture_count = (batch_mode ? &count_single_batch : &count_buffers)
@@ -3910,7 +4009,7 @@
 
 	if (defer) {
 		if (mbuf) {
-			mbuf->deferred = true;
+			mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
 			print_vidc_buffer(VIDC_DBG, "deferred qbuf",
 				inst, mbuf);
 		}
@@ -3951,7 +4050,7 @@
 	list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
 		struct vidc_frame_data *frame_data = NULL;
 
-		if (!temp->deferred)
+		if (!(temp->flags & MSM_VIDC_FLAG_DEFERRED))
 			continue;
 
 		switch (temp->vvb.vb2_buf.type) {
@@ -3973,7 +4072,7 @@
 		populate_frame_data(frame_data, temp, inst);
 
 		/* this buffer going to be queued (not deferred) */
-		temp->deferred = false;
+		temp->flags &= ~MSM_VIDC_FLAG_DEFERRED;
 
 		print_vidc_buffer(VIDC_DBG, "qbuf", inst, temp);
 	}
@@ -4067,9 +4166,14 @@
 		return -EINVAL;
 	}
 	extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT);
-
 	bufreq->buffer_count_min_host = bufreq->buffer_count_min +
 		extra_buffers;
+	bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT);
+	if (bufreq) {
+		if (bufreq->buffer_count_min)
+			bufreq->buffer_count_min_host =
+				bufreq->buffer_count_min + extra_buffers;
+	}
 
 	if (msm_comm_get_stream_output_mode(inst) ==
 			HAL_VIDEO_DECODER_SECONDARY) {
@@ -4467,6 +4571,26 @@
 	return rc;
 }
 
+void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst)
+{
+	struct eos_buf *buf, *next;
+
+	if (!inst) {
+		dprintk(VIDC_ERR,
+			"Invalid instance pointer = %pK\n", inst);
+		return;
+	}
+
+	mutex_lock(&inst->eosbufs.lock);
+	list_for_each_entry_safe(buf, next, &inst->eosbufs.list, list) {
+		list_del(&buf->list);
+		kfree(buf);
+	}
+	INIT_LIST_HEAD(&inst->eosbufs.list);
+	mutex_unlock(&inst->eosbufs.lock);
+}
+
+
 int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst)
 {
 	struct recon_buf *buf, *next;
@@ -4666,8 +4790,7 @@
 		return 0;
 	}
 
-	if (!list_empty(&inst->reconbufs.list))
-		msm_comm_release_recon_buffers(inst);
+	msm_comm_release_recon_buffers(inst);
 
 	for (i = 0; i < internal_buf->buffer_count_actual; i++) {
 		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
@@ -4725,10 +4848,16 @@
 				&inst->bufq[port].vb2_bufq.queued_list) {
 			struct vb2_buffer *vb = container_of(ptr,
 					struct vb2_buffer, queued_entry);
-			vb->planes[0].bytesused = 0;
-			print_vb2_buffer(VIDC_ERR, "flush in invalid",
-				inst, vb);
-			vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+			if (vb->state == VB2_BUF_STATE_ACTIVE) {
+				vb->planes[0].bytesused = 0;
+				print_vb2_buffer(VIDC_ERR, "flush in invalid",
+					inst, vb);
+				vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+			} else {
+				dprintk(VIDC_WARN,
+					"%s VB is in state %d not in ACTIVE state\n"
+					, __func__, vb->state);
+			}
 		}
 		mutex_unlock(&inst->bufq[port].lock);
 	}
@@ -4738,7 +4867,7 @@
 
 int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
 {
-	int rc =  0;
+	int i, rc =  0;
 	bool ip_flush = false;
 	bool op_flush = false;
 	struct msm_vidc_buffer *mbuf, *next;
@@ -4763,8 +4892,6 @@
 		return 0;
 	}
 
-	/* Finish FLUSH As Soon As Possible. */
-
 	msm_clock_data_reset(inst);
 
 	if (inst->state == MSM_VIDC_CORE_INVALID) {
@@ -4777,22 +4904,41 @@
 
 	mutex_lock(&inst->registeredbufs.lock);
 	list_for_each_entry_safe(mbuf, next, &inst->registeredbufs.list, list) {
-		/* flush only deferred buffers (which are not queued yet) */
-		if (!mbuf->deferred)
-			continue;
-
-		/* don't flush input buffers if flush not requested on it */
+		/* don't flush input buffers if input flush is not requested */
 		if (!ip_flush && mbuf->vvb.vb2_buf.type ==
 				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 			continue;
 
+		/* flush only deferred or rbr pending buffers */
+		if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED ||
+			mbuf->flags & MSM_VIDC_FLAG_RBR_PENDING))
+			continue;
+
+		/*
+		 * flush buffers which are queued by client already,
+		 * the refcount will be two or more for those buffers.
+		 */
+		if (!(mbuf->smem[0].refcount >= 2))
+			continue;
+
 		print_vidc_buffer(VIDC_DBG, "flush buf", inst, mbuf);
 		msm_comm_flush_vidc_buffer(inst, mbuf);
-		msm_comm_unmap_vidc_buffer(inst, mbuf);
 
-		/* remove from list */
-		list_del(&mbuf->list);
-		kref_put_mbuf(mbuf);
+		for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
+			if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
+				print_vidc_buffer(VIDC_ERR,
+					"dqbuf: unmap failed.", inst, mbuf);
+			if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
+				print_vidc_buffer(VIDC_ERR,
+					"dqbuf: unmap failed..", inst, mbuf);
+		}
+		if (!mbuf->smem[0].refcount) {
+			list_del(&mbuf->list);
+			kref_put_mbuf(mbuf);
+		} else {
+			/* buffer is no more a deferred buffer */
+			mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
+		}
 	}
 	mutex_unlock(&inst->registeredbufs.lock);
 
@@ -4924,6 +5070,28 @@
 	return ret;
 };
 
+int msm_vidc_noc_error_info(struct msm_vidc_core *core)
+{
+	struct hfi_device *hdev;
+
+	if (!core || !core->device) {
+		dprintk(VIDC_WARN, "%s: Invalid parameters: %pK\n",
+			__func__, core);
+		return -EINVAL;
+	}
+
+	if (!core->resources.non_fatal_pagefaults)
+		return 0;
+
+	if (!core->smmu_fault_handled)
+		return 0;
+
+	hdev = core->device;
+	call_hfi_op(hdev, noc_error_info, hdev->hfi_device_data);
+
+	return 0;
+}
+
 int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
 	enum hal_ssr_trigger_type type)
 {
@@ -5076,6 +5244,8 @@
 	int rc = 0;
 	struct hfi_device *hdev;
 	struct msm_vidc_core *core;
+	u32 output_height, output_width;
+	u32 rotation;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
@@ -5097,34 +5267,47 @@
 		return -ENOTSUPP;
 	}
 
+	rotation =  msm_comm_g_ctrl_for_id(inst,
+					V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
+
+	output_height = inst->prop.height[CAPTURE_PORT];
+	output_width = inst->prop.width[CAPTURE_PORT];
+
+	if ((output_width != output_height) &&
+		(rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
+		rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
+
+		output_width = inst->prop.height[CAPTURE_PORT];
+		output_height = inst->prop.width[CAPTURE_PORT];
+		dprintk(VIDC_DBG,
+			"Rotation=%u Swapped Output W=%u H=%u to check capability",
+			rotation, output_width, output_height);
+	}
+
 	if (!rc) {
-		if (inst->prop.width[CAPTURE_PORT] < capability->width.min ||
-			inst->prop.height[CAPTURE_PORT] <
-			capability->height.min) {
+		if (output_width < capability->width.min ||
+			output_height < capability->height.min) {
 			dprintk(VIDC_ERR,
 				"Unsupported WxH = (%u)x(%u), min supported is - (%u)x(%u)\n",
-				inst->prop.width[CAPTURE_PORT],
-				inst->prop.height[CAPTURE_PORT],
+				output_width,
+				output_height,
 				capability->width.min,
 				capability->height.min);
 			rc = -ENOTSUPP;
 		}
-		if (!rc && inst->prop.width[CAPTURE_PORT] >
-			capability->width.max) {
+		if (!rc && output_width > capability->width.max) {
 			dprintk(VIDC_ERR,
 				"Unsupported width = %u supported max width = %u\n",
-				inst->prop.width[CAPTURE_PORT],
+				output_width,
 				capability->width.max);
 				rc = -ENOTSUPP;
 		}
 
-		if (!rc && inst->prop.height[CAPTURE_PORT]
-			* inst->prop.width[CAPTURE_PORT] >
+		if (!rc && output_height * output_width >
 			capability->width.max * capability->height.max) {
 			dprintk(VIDC_ERR,
 			"Unsupported WxH = (%u)x(%u), max supported is - (%u)x(%u)\n",
-			inst->prop.width[CAPTURE_PORT],
-			inst->prop.height[CAPTURE_PORT],
+			output_width, output_height,
 			capability->width.max, capability->height.max);
 			rc = -ENOTSUPP;
 		}
@@ -5353,8 +5536,8 @@
 			}
 		} else if (inst->session_type == MSM_VIDC_ENCODER) {
 			if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-				if (!i) /* yuv */
-					skip = true;
+				/* yuv and extradata */
+				skip = true;
 			} else if (b->type ==
 					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 				if (!i) /* bitstream */
@@ -5589,32 +5772,6 @@
 	mutex_unlock(&inst->outputbufs.lock);
 }
 
-static void msm_comm_print_debug_info(struct msm_vidc_inst *inst)
-{
-	struct msm_vidc_core *core = NULL;
-	struct msm_vidc_inst *temp = NULL;
-
-	if (!inst || !inst->core) {
-		dprintk(VIDC_ERR, "%s - invalid param %pK %pK\n",
-				__func__, inst, core);
-		return;
-	}
-	core = inst->core;
-
-	dprintk(VIDC_ERR, "Venus core frequency = %lu", core->curr_freq);
-	mutex_lock(&core->lock);
-	dprintk(VIDC_ERR, "Printing instance info that caused Error\n");
-	msm_comm_print_inst_info(inst);
-	dprintk(VIDC_ERR, "Printing remaining instances info\n");
-	list_for_each_entry(temp, &core->instances, list) {
-		/* inst already printed above. Hence don't repeat.*/
-		if (temp == inst)
-			continue;
-		msm_comm_print_inst_info(temp);
-	}
-	mutex_unlock(&core->lock);
-}
-
 int msm_comm_session_continue(void *instance)
 {
 	struct msm_vidc_inst *inst = instance;
@@ -5694,27 +5851,27 @@
 
 	if (vb2->num_planes == 1)
 		dprintk(tag,
-			"%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d\n",
+			"%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d mflags 0x%x\n",
 			str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
 			"OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
 			vb2->index, vb2->planes[0].m.fd,
 			vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
 			vb2->planes[0].length, vb2->planes[0].bytesused,
 			mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
-			mbuf->smem[0].refcount);
+			mbuf->smem[0].refcount, mbuf->flags);
 	else
 		dprintk(tag,
-			"%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d, extradata: fd %d off %d daddr %x size %d filled %d refcnt %d\n",
+			"%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d mflags 0x%x, extradata: fd %d off %d daddr %x size %d filled %d refcnt %d\n",
 			str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
 			"OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
 			vb2->index, vb2->planes[0].m.fd,
 			vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
 			vb2->planes[0].length, vb2->planes[0].bytesused,
 			mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
-			mbuf->smem[0].refcount, vb2->planes[1].m.fd,
-			vb2->planes[1].data_offset, mbuf->smem[1].device_addr,
-			vb2->planes[1].length, vb2->planes[1].bytesused,
-			mbuf->smem[1].refcount);
+			mbuf->smem[0].refcount, mbuf->flags,
+			vb2->planes[1].m.fd, vb2->planes[1].data_offset,
+			mbuf->smem[1].device_addr, vb2->planes[1].length,
+			vb2->planes[1].bytesused, mbuf->smem[1].refcount);
 }
 
 void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
@@ -5733,13 +5890,14 @@
 			vb2->planes[0].bytesused);
 	else
 		dprintk(tag,
-			"%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d\n",
+			"%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d filled %d\n",
 			str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
 			"OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
 			vb2->index, vb2->planes[0].m.fd,
 			vb2->planes[0].data_offset, vb2->planes[0].length,
 			vb2->planes[0].bytesused, vb2->planes[1].m.fd,
-			vb2->planes[1].data_offset, vb2->planes[1].length);
+			vb2->planes[1].data_offset, vb2->planes[1].length,
+			vb2->planes[1].bytesused);
 }
 
 void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
@@ -5759,7 +5917,7 @@
 			v4l2->m.planes[0].bytesused);
 	else
 		dprintk(tag,
-			"%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d\n",
+			"%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d filled %d\n",
 			str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
 			"OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
 			v4l2->index, v4l2->m.planes[0].m.fd,
@@ -5768,7 +5926,8 @@
 			v4l2->m.planes[0].bytesused,
 			v4l2->m.planes[1].m.fd,
 			v4l2->m.planes[1].data_offset,
-			v4l2->m.planes[1].length);
+			v4l2->m.planes[1].length,
+			v4l2->m.planes[1].bytesused);
 }
 
 bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst,
@@ -5959,8 +6118,11 @@
 		 * always compare dma_buf addresses which is guaranteed
 		 * to be same across the processes (duplicate fds).
 		 */
-		dma_planes[i] = (unsigned long)dma_buf_get(vb2->planes[i].m.fd);
-		dma_buf_put((struct dma_buf *)dma_planes[i]);
+		dma_planes[i] = (unsigned long)msm_smem_get_dma_buf(
+				vb2->planes[i].m.fd);
+		if (!dma_planes[i])
+			return NULL;
+		msm_smem_put_dma_buf((struct dma_buf *)dma_planes[i]);
 	}
 
 	mutex_lock(&inst->registeredbufs.lock);
@@ -5983,6 +6145,9 @@
 		kref_init(&mbuf->kref);
 	}
 
+	/* Initially assume all the buffer are going to be deferred */
+	mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
+
 	vbuf = to_vb2_v4l2_buffer(vb2);
 	memcpy(&mbuf->vvb, vbuf, sizeof(struct vb2_v4l2_buffer));
 	vb = &mbuf->vvb.vb2_buf;
@@ -6029,6 +6194,16 @@
 			if (found_plane0)
 				rc = -EEXIST;
 		}
+		/*
+		 * If RBR pending on this buffer then enable RBR_PENDING flag
+		 * and clear the DEFERRED flag to avoid this buffer getting
+		 * queued to video hardware in msm_comm_qbuf() which tries to
+		 * queue all the DEFERRED buffers.
+		 */
+		if (rc == -EEXIST) {
+			mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING;
+			mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
+		}
 	}
 
 	/* add the new buffer to list */
@@ -6125,10 +6300,14 @@
 		}
 	}
 	if (found) {
+		/* send RBR event to client */
 		msm_vidc_queue_rbr_event(inst,
 			mbuf->vvb.vb2_buf.planes[0].m.fd,
 			mbuf->vvb.vb2_buf.planes[0].data_offset);
 
+		/* clear RBR_PENDING flag */
+		mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
+
 		for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
 			if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
 				print_vidc_buffer(VIDC_ERR,
@@ -6164,7 +6343,7 @@
 	if (!found)
 		goto unlock;
 
-	/* found means client queued the buffer already */
+	/* buffer found means client queued the buffer already */
 	if (inst->in_reconfig || inst->in_flush) {
 		print_vidc_buffer(VIDC_DBG, "rbr flush buf", inst, mbuf);
 		msm_comm_flush_vidc_buffer(inst, mbuf);
@@ -6176,12 +6355,16 @@
 		/* don't queue the buffer */
 		found = false;
 	}
+	/* clear DEFERRED flag, if any, as the buffer is going to be queued */
+	if (found)
+		mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
+
 unlock:
 	mutex_unlock(&inst->registeredbufs.lock);
 
 	if (found) {
 		print_vidc_buffer(VIDC_DBG, "rbr qbuf", inst, mbuf);
-		rc = msm_comm_qbuf(inst, mbuf);
+		rc = msm_comm_qbuf_rbr(inst, mbuf);
 		if (rc)
 			print_vidc_buffer(VIDC_ERR,
 				"rbr qbuf failed", inst, mbuf);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 18ba4a5..4a06f19 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -56,6 +56,7 @@
 					bool check_for_reuse);
 int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst);
 int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst);
+void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst);
 int msm_comm_release_output_buffers(struct msm_vidc_inst *inst,
 	bool force_release);
 void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index e554a46..1ad28ba 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -49,6 +49,7 @@
 #define MAX_NUM_OUTPUT_BUFFERS VIDEO_MAX_FRAME // same as VB2_MAX_FRAME
 #define MAX_NUM_CAPTURE_BUFFERS VIDEO_MAX_FRAME // same as VB2_MAX_FRAME
 
+#define MAX_SUPPORTED_INSTANCES 16
 
 /* Maintains the number of FTB's between each FBD over a window */
 #define DCVS_FTB_WINDOW 16
@@ -143,6 +144,12 @@
 	unsigned long freq;
 };
 
+struct vidc_input_cr_data {
+	struct list_head list;
+	u32 index;
+	u32 input_cr;
+};
+
 struct recon_buf {
 	struct list_head list;
 	u32 buffer_index;
@@ -150,6 +157,11 @@
 	u32 CF;
 };
 
+struct eos_buf {
+	struct list_head list;
+	struct msm_smem smem;
+};
+
 struct internal_buf {
 	struct list_head list;
 	enum hal_buffer buffer_type;
@@ -321,11 +333,13 @@
 	struct msm_vidc_format fmts[MAX_PORT_NUM];
 	struct buf_queue bufq[MAX_PORT_NUM];
 	struct msm_vidc_list freqs;
+	struct msm_vidc_list input_crs;
 	struct msm_vidc_list scratchbufs;
 	struct msm_vidc_list persistbufs;
 	struct msm_vidc_list pending_getpropq;
 	struct msm_vidc_list outputbufs;
 	struct msm_vidc_list reconbufs;
+	struct msm_vidc_list eosbufs;
 	struct msm_vidc_list registeredbufs;
 	struct buffer_requirements buff_req;
 	struct smem_client *mem_client;
@@ -381,16 +395,22 @@
 void handle_cmd_response(enum hal_command_response cmd, void *data);
 int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
 	enum hal_ssr_trigger_type type);
+int msm_vidc_noc_error_info(struct msm_vidc_core *core);
 int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
 int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
 void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type);
 
+enum msm_vidc_flags {
+	MSM_VIDC_FLAG_DEFERRED            = BIT(0),
+	MSM_VIDC_FLAG_RBR_PENDING         = BIT(1),
+};
+
 struct msm_vidc_buffer {
 	struct list_head list;
 	struct kref kref;
 	struct msm_smem smem[VIDEO_MAX_PLANES];
 	struct vb2_v4l2_buffer vvb;
-	bool deferred;
+	enum msm_vidc_flags flags;
 };
 
 void msm_comm_handle_thermal_event(void);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index 8a701cb..027e76e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -68,6 +68,10 @@
 		.value = 1,
 	},
 	{
+		.key = "qcom,domain-attr-non-fatal-faults",
+		.value = 1,
+	},
+	{
 		.key = "qcom,max-secure-instances",
 		.value = 5,
 	},
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 039b457..46fb75f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -785,6 +785,9 @@
 			"qcom,fw-unload-delay");
 	res->msm_vidc_hw_rsp_timeout = find_key_value(platform_data,
 			"qcom,hw-resp-timeout");
+	res->non_fatal_pagefaults = find_key_value(platform_data,
+			"qcom,domain-attr-non-fatal-faults");
+
 	return rc;
 
 }
@@ -980,8 +983,13 @@
 		return -EINVAL;
 	}
 
-	if (core->smmu_fault_handled)
+	if (core->smmu_fault_handled) {
+		if (core->resources.non_fatal_pagefaults) {
+			msm_vidc_noc_error_info(core);
+			MSM_VIDC_ERROR(true);
+		}
 		return -ENOSYS;
+	}
 
 	dprintk(VIDC_ERR, "%s - faulting address: %lx\n", __func__, iova);
 
@@ -1061,6 +1069,21 @@
 		goto err_setup_cb;
 	}
 
+	if (core->resources.non_fatal_pagefaults) {
+		int data = 1;
+
+		dprintk(VIDC_DBG, "set non-fatal-faults attribute on %s\n",
+				dev_name(dev));
+		rc = iommu_domain_set_attr(cb->mapping->domain,
+					DOMAIN_ATTR_NON_FATAL_FAULTS, &data);
+		if (rc) {
+			dprintk(VIDC_WARN,
+				"%s: set non fatal attribute failed: %s %d\n",
+				__func__, dev_name(dev), rc);
+			/* ignore the error */
+		}
+	}
+
 	iommu_set_fault_handler(cb->mapping->domain,
 		msm_vidc_smmu_fault_handler, (void *)core);
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 755f0c86..31d5a42 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -161,7 +161,7 @@
 	uint32_t dcvs_tbl_size;
 	struct dcvs_limit *dcvs_limit;
 	bool sys_cache_present;
-	bool sys_cache_enabled;
+	bool sys_cache_res_set;
 	struct subcache_set subcache_set;
 	struct reg_set reg_set;
 	struct addr_set qdss_addr_set;
@@ -189,6 +189,7 @@
 	int msm_vidc_hw_rsp_timeout;
 	int msm_vidc_firmware_unload_delay;
 	uint32_t msm_vidc_pwr_collapse_delay;
+	bool non_fatal_pagefaults;
 	struct msm_vidc_codec_data *codec_data;
 	int codec_data_count;
 };
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index b430d14..69fc2e0 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -99,8 +99,10 @@
 static void __unload_fw(struct venus_hfi_device *device);
 static int __tzbsp_set_video_state(enum tzbsp_video_state state);
 static int __enable_subcaches(struct venus_hfi_device *device);
+static int __set_subcaches(struct venus_hfi_device *device);
+static int __release_subcaches(struct venus_hfi_device *device);
 static int __disable_subcaches(struct venus_hfi_device *device);
-
+static int venus_hfi_noc_error_info(void *dev);
 
 /**
  * Utility function to enforce some of our assumptions.  Spam calls to this
@@ -1747,10 +1749,8 @@
 		dprintk(VIDC_WARN, "Failed to send image version pkt to f/w\n");
 
 	rc = __enable_subcaches(device);
-	if (rc) {
-		dprintk(VIDC_WARN,
-			"Failed to enable subcaches, err = %d\n", rc);
-	}
+	if (!rc)
+		__set_subcaches(device);
 
 	if (dev->res->pm_qos_latency_us) {
 #ifdef CONFIG_SMP
@@ -2804,9 +2804,11 @@
 		}
 	}
 
+	__flush_debug_queue(device, device->raw_packet);
+
 	rc = __suspend(device);
 	if (rc)
-		dprintk(VIDC_ERR, "Failed venus power off\n");
+		dprintk(VIDC_ERR, "Failed __suspend\n");
 
 	/* Cancel pending delayed works if any */
 	cancel_delayed_work(&venus_hfi_pm_work);
@@ -3405,6 +3407,15 @@
 			.exit = NULL,
 		};
 
+		if (!strcmp(bus->governor, "msm-vidc-llcc")) {
+			if (msm_vidc_syscache_disable) {
+				dprintk(VIDC_DBG,
+					 "Skipping LLC bus init %s: %s\n",
+				bus->name, bus->governor);
+				continue;
+			}
+		}
+
 		/*
 		 * This is stupid, but there's no other easy way to ahold
 		 * of struct bus_info in venus_hfi_devfreq_*()
@@ -3763,39 +3774,64 @@
 	int rc = 0;
 	u32 c = 0;
 	struct subcache_info *sinfo;
-	u32 resource[VIDC_MAX_SUBCACHE_SIZE];
-	struct hfi_resource_syscache_info_type *sc_res_info;
-	struct hfi_resource_subcache_type *sc_res;
-	struct vidc_resource_hdr rhdr;
 
 	if (msm_vidc_syscache_disable || !is_sys_cache_present(device))
 		return 0;
 
-	memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
-
-	sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
-	sc_res = &(sc_res_info->rg_subcache_entries[0]);
-
 	/* Activate subcaches */
 	venus_hfi_for_each_subcache(device, sinfo) {
 		rc = llcc_slice_activate(sinfo->subcache);
 		if (rc) {
 			dprintk(VIDC_ERR, "Failed to activate %s: %d\n",
 				sinfo->name, rc);
-			continue;
+			goto err_activate_fail;
 		}
 		sinfo->isactive = true;
-
-		/* Update the entry */
-		sc_res[c].size = sinfo->subcache->llcc_slice_size;
-		sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
-		dprintk(VIDC_DBG, "Activate subcache %s\n", sinfo->name);
+		dprintk(VIDC_DBG, "Activated subcache %s\n", sinfo->name);
 		c++;
 	}
 
+	dprintk(VIDC_DBG, "Activated %d Subcaches to Venus\n", c);
+
+	return 0;
+
+err_activate_fail:
+	__release_subcaches(device);
+	__disable_subcaches(device);
+	return -EINVAL;
+}
+
+static int __set_subcaches(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	u32 c = 0;
+	struct subcache_info *sinfo;
+	u32 resource[VIDC_MAX_SUBCACHE_SIZE];
+	struct hfi_resource_syscache_info_type *sc_res_info;
+	struct hfi_resource_subcache_type *sc_res;
+	struct vidc_resource_hdr rhdr;
+
+	if (device->res->sys_cache_res_set) {
+		dprintk(VIDC_DBG, "Subcaches already set to Venus\n");
+		return 0;
+	}
+
+	memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
+
+	sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
+	sc_res = &(sc_res_info->rg_subcache_entries[0]);
+
+	venus_hfi_for_each_subcache(device, sinfo) {
+		if (sinfo->isactive == true) {
+			sc_res[c].size = sinfo->subcache->llcc_slice_size;
+			sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
+			c++;
+		}
+	}
+
 	/* Set resource to Venus for activated subcaches */
 	if (c) {
-		dprintk(VIDC_DBG, "Setting Subcaches\n");
+		dprintk(VIDC_DBG, "Setting %d Subcaches\n", c);
 
 		rhdr.resource_handle = sc_res_info; /* cookie */
 		rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
@@ -3814,9 +3850,8 @@
 			sinfo->isset = true;
 	}
 
-	dprintk(VIDC_DBG, "Activated & Set Subcaches to Venus\n");
-
-	device->res->sys_cache_enabled = true;
+	dprintk(VIDC_DBG, "Set Subcaches done to Venus\n");
+	device->res->sys_cache_res_set = true;
 
 	return 0;
 
@@ -3826,7 +3861,7 @@
 	return rc;
 }
 
-static int __disable_subcaches(struct venus_hfi_device *device)
+static int __release_subcaches(struct venus_hfi_device *device)
 {
 	struct subcache_info *sinfo;
 	int rc = 0;
@@ -3839,8 +3874,6 @@
 	if (msm_vidc_syscache_disable || !is_sys_cache_present(device))
 		return 0;
 
-	dprintk(VIDC_DBG, "Disabling Subcaches\n");
-
 	memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
 
 	sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
@@ -3858,16 +3891,29 @@
 	}
 
 	if (c > 0) {
+		dprintk(VIDC_DBG, "Releasing %d subcaches\n", c);
 		rhdr.resource_handle = sc_res_info; /* cookie */
 		rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
 
 		rc = __core_release_resource(device, &rhdr);
 		if (rc)
-			dprintk(VIDC_ERR, "Failed to release subcaches\n");
-
-		dprintk(VIDC_DBG, "Release %d subcaches\n", c);
+			dprintk(VIDC_ERR,
+				"Failed to release %d subcaches\n", c);
 	}
 
+	device->res->sys_cache_res_set = false;
+
+	return rc;
+}
+
+static int __disable_subcaches(struct venus_hfi_device *device)
+{
+	struct subcache_info *sinfo;
+	int rc = 0;
+
+	if (msm_vidc_syscache_disable || !is_sys_cache_present(device))
+		return 0;
+
 	/* De-activate subcaches */
 	venus_hfi_for_each_subcache_reverse(device, sinfo) {
 		if (sinfo->isactive == true) {
@@ -3883,8 +3929,6 @@
 		}
 	}
 
-	device->res->sys_cache_enabled = false;
-
 	return rc;
 }
 
@@ -3984,10 +4028,7 @@
 		return 0;
 	}
 
-	dprintk(VIDC_PROF, "Entering power collapse\n");
-
-	if (__disable_subcaches(device))
-		dprintk(VIDC_ERR, "Failed to disable subcaches\n");
+	dprintk(VIDC_PROF, "Entering suspend\n");
 
 	if (device->res->pm_qos_latency_us &&
 		pm_qos_request_active(&device->qos))
@@ -3999,8 +4040,10 @@
 		goto err_tzbsp_suspend;
 	}
 
+	__disable_subcaches(device);
+
 	__venus_power_off(device);
-	dprintk(VIDC_PROF, "Venus power collapsed\n");
+	dprintk(VIDC_PROF, "Venus power off\n");
 	return rc;
 
 err_tzbsp_suspend:
@@ -4061,10 +4104,8 @@
 	__sys_set_debug(device, msm_vidc_fw_debug);
 
 	rc = __enable_subcaches(device);
-	if (rc) {
-		dprintk(VIDC_WARN,
-			"Failed to enable subcaches, err = %d\n", rc);
-	}
+	if (!rc)
+		__set_subcaches(device);
 
 	dprintk(VIDC_PROF, "Resumed from power collapse\n");
 exit:
@@ -4231,6 +4272,64 @@
 	return rc;
 }
 
+static int venus_hfi_noc_error_info(void *dev)
+{
+	struct venus_hfi_device *device;
+	u32 val = 0;
+
+	if (!dev) {
+		dprintk(VIDC_ERR, "%s: null device\n", __func__);
+		return -EINVAL;
+	}
+	device = dev;
+
+	mutex_lock(&device->lock);
+	dprintk(VIDC_ERR, "%s: non error information\n", __func__);
+
+	val = __read_register(device, 0x0C500);
+	dprintk(VIDC_ERR, "NOC_ERR_SWID_LOW(0x00AA0C500):     %#x\n", val);
+
+	val = __read_register(device, 0x0C504);
+	dprintk(VIDC_ERR, "NOC_ERR_SWID_HIGH(0x00AA0C504):    %#x\n", val);
+
+	val = __read_register(device, 0x0C508);
+	dprintk(VIDC_ERR, "NOC_ERR_MAINCTL_LOW(0x00AA0C508):  %#x\n", val);
+
+	val = __read_register(device, 0x0C510);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRVLD_LOW(0x00AA0C510):   %#x\n", val);
+
+	val = __read_register(device, 0x0C518);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRCLR_LOW(0x00AA0C518):   %#x\n", val);
+
+	val = __read_register(device, 0x0C520);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG0_LOW(0x00AA0C520):  %#x\n", val);
+
+	val = __read_register(device, 0x0C524);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG0_HIGH(0x00AA0C524): %#x\n", val);
+
+	val = __read_register(device, 0x0C528);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG1_LOW(0x00AA0C528):  %#x\n", val);
+
+	val = __read_register(device, 0x0C52C);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG1_HIGH(0x00AA0C52C): %#x\n", val);
+
+	val = __read_register(device, 0x0C530);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG2_LOW(0x00AA0C530):  %#x\n", val);
+
+	val = __read_register(device, 0x0C534);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG2_HIGH(0x00AA0C534): %#x\n", val);
+
+	val = __read_register(device, 0x0C538);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG3_LOW(0x00AA0C538):  %#x\n", val);
+
+	val = __read_register(device, 0x0C53C);
+	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG3_HIGH(0x00AA0C53C): %#x\n", val);
+
+	mutex_unlock(&device->lock);
+
+	return 0;
+}
+
 static int __initialize_packetization(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -4402,6 +4501,7 @@
 	hdev->get_core_capabilities = venus_hfi_get_core_capabilities;
 	hdev->suspend = venus_hfi_suspend;
 	hdev->flush_debug_queue = venus_hfi_flush_debug_queue;
+	hdev->noc_error_info = venus_hfi_noc_error_info;
 	hdev->get_default_properties = venus_hfi_get_default_properties;
 }
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index fbd3b02..6852587 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1345,11 +1345,13 @@
 	int output_height, output_width;
 	int compression_ratio;
 	int complexity_factor;
+	int input_cr;
 	bool use_dpb_read;
 	unsigned int lcu_size;
 	enum msm_vidc_power_mode power_mode;
 	enum hal_work_mode work_mode;
 	bool use_sys_cache;
+	bool b_frames_enabled;
 };
 
 struct vidc_clk_scale_data {
@@ -1409,6 +1411,7 @@
 	int (*get_core_capabilities)(void *dev);
 	int (*suspend)(void *dev);
 	int (*flush_debug_queue)(void *dev);
+	int (*noc_error_info)(void *dev);
 	enum hal_default_properties (*get_default_properties)(void *dev);
 };
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index a522918..6a239b3 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -81,6 +81,7 @@
 #define HFI_VIDEO_CODEC_VP8				0x00001000
 #define HFI_VIDEO_CODEC_HEVC				0x00002000
 #define HFI_VIDEO_CODEC_VP9				0x00004000
+#define HFI_VIDEO_CODEC_TME				0x00008000
 
 #define HFI_PROFILE_UNKNOWN					0x00000000
 #define HFI_H264_PROFILE_BASELINE			0x00000001
@@ -150,6 +151,13 @@
 #define HFI_HEVC_TIER_MAIN	0x1
 #define HFI_HEVC_TIER_HIGH0	0x2
 
+#define  HFI_TME_PROFILE_DEFAULT	0x00000001
+#define  HFI_TME_PROFILE_FRC		0x00000002
+#define  HFI_TME_PROFILE_ASW		0x00000004
+#define  HFI_TME_PROFILE_DFS_BOKEH	0x00000008
+
+#define HFI_TME_LEVEL_INTEGER		0x00000001
+
 #define HFI_BUFFER_INPUT				(HFI_COMMON_BASE + 0x1)
 #define HFI_BUFFER_OUTPUT				(HFI_COMMON_BASE + 0x2)
 #define HFI_BUFFER_OUTPUT2				(HFI_COMMON_BASE + 0x3)
@@ -229,6 +237,8 @@
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x011)
 #define  HFI_PROPERTY_PARAM_WORK_MODE                       \
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x015)
+#define  HFI_PROPERTY_TME_VERSION_SUPPORTED                 \
+	(HFI_PROPERTY_PARAM_COMMON_START + 0x016)
 
 #define HFI_PROPERTY_CONFIG_COMMON_START				\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x2000)
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 52dc794..1da2c94 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -1099,10 +1099,10 @@
 			       struct s5p_jpeg_ctx *ctx)
 {
 	int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
-	unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0,
-		     sof_len = 0;
-	unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER],
-		     dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
+	unsigned int height = 0, width = 0, word, subsampling = 0;
+	unsigned int sos = 0, sof = 0, sof_len = 0;
+	unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER];
+	unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
 	long length;
 	struct s5p_jpeg_buffer jpeg_buffer;
 
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 86cc70fe25..2d4b836 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1629,7 +1629,7 @@
 	if (kc == KEY_KEYBOARD && !ictx->release_code) {
 		ictx->last_keycode = kc;
 		if (!nomouse) {
-			ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
+			ictx->pad_mouse = !ictx->pad_mouse;
 			dev_dbg(dev, "toggling to %s mode\n",
 				ictx->pad_mouse ? "mouse" : "keyboard");
 			spin_unlock_irqrestore(&ictx->kc_lock, flags);
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
index 283495c..aab8eee 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
@@ -320,7 +320,7 @@
 static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
 				  u8 index, u8 *wdata)
 {
-	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+	int ret = mxl111sf_ctrl_msg(state, wdata[0],
 				    &wdata[1], 25, NULL, 0);
 	mxl_fail(ret);
 
@@ -330,7 +330,7 @@
 static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
 				 u8 index, u8 *wdata, u8 *rdata)
 {
-	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+	int ret = mxl111sf_ctrl_msg(state, wdata[0],
 				    &wdata[1], 25, rdata, 24);
 	mxl_fail(ret);
 
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 5d676b5..f1f4486 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -24,9 +24,6 @@
 #include "lgdt3305.h"
 #include "lg2160.h"
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
-
 int dvb_usb_mxl111sf_debug;
 module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level "
@@ -56,27 +53,34 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
 		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
 {
+	struct dvb_usb_device *d = state->d;
 	int wo = (rbuf == NULL || rlen == 0); /* write-only */
 	int ret;
-	u8 sndbuf[MAX_XFER_SIZE];
 
-	if (1 + wlen > sizeof(sndbuf)) {
+	if (1 + wlen > MXL_MAX_XFER_SIZE) {
 		pr_warn("%s: len=%d is too big!\n", __func__, wlen);
 		return -EOPNOTSUPP;
 	}
 
 	pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
 
-	memset(sndbuf, 0, 1+wlen);
+	mutex_lock(&state->msg_lock);
+	memset(state->sndbuf, 0, 1+wlen);
+	memset(state->rcvbuf, 0, rlen);
 
-	sndbuf[0] = cmd;
-	memcpy(&sndbuf[1], wbuf, wlen);
+	state->sndbuf[0] = cmd;
+	memcpy(&state->sndbuf[1], wbuf, wlen);
 
-	ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) :
-		dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen);
+	ret = (wo) ? dvb_usbv2_generic_write(d, state->sndbuf, 1+wlen) :
+		dvb_usbv2_generic_rw(d, state->sndbuf, 1+wlen, state->rcvbuf,
+				     rlen);
+
+	memcpy(rbuf, state->rcvbuf, rlen);
+	mutex_unlock(&state->msg_lock);
+
 	mxl_fail(ret);
 
 	return ret;
@@ -92,7 +96,7 @@
 	u8 buf[2];
 	int ret;
 
-	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+	ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_READ, &addr, 1, buf, 2);
 	if (mxl_fail(ret)) {
 		mxl_debug("error reading reg: 0x%02x", addr);
 		goto fail;
@@ -118,7 +122,7 @@
 
 	pr_debug("W: (0x%02x, 0x%02x)\n", addr, data);
 
-	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+	ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
 	if (mxl_fail(ret))
 		pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
 	return ret;
@@ -922,6 +926,8 @@
 	static u8 eeprom[256];
 	struct i2c_client c;
 
+	mutex_init(&state->msg_lock);
+
 	ret = get_chip_info(state);
 	if (mxl_fail(ret))
 		pr_err("failed to get chip info during probe");
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
index 846260e..3e6f588 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
@@ -19,6 +19,9 @@
 #include <media/tveeprom.h>
 #include <media/media-entity.h>
 
+/* Max transfer size done by I2C transfer functions */
+#define MXL_MAX_XFER_SIZE  64
+
 #define MXL_EP1_REG_READ     1
 #define MXL_EP2_REG_WRITE    2
 #define MXL_EP3_INTERRUPT    3
@@ -86,6 +89,9 @@
 	struct mutex fe_lock;
 	u8 num_frontends;
 	struct mxl111sf_adap_state adap_state[3];
+	u8 sndbuf[MXL_MAX_XFER_SIZE];
+	u8 rcvbuf[MXL_MAX_XFER_SIZE];
+	struct mutex msg_lock;
 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
 	struct media_entity tuner;
 	struct media_pad tuner_pads[2];
@@ -108,7 +114,7 @@
 
 /* needed for hardware i2c functions in mxl111sf-i2c.c:
  * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
 		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
 
 #define mxl_printk(kern, fmt, arg...) \
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index c2ee6e3..252ab99 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -1992,6 +1992,9 @@
 	if (!found)
 		return -ENOENT;
 
+	if (ctrl->info.size < mapping->size)
+		return -EINVAL;
+
 	if (mutex_lock_interruptible(&chain->ctrl_mutex))
 		return -ERESTARTSYS;
 
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 232c290..a12d5ca 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1280,6 +1280,10 @@
 		ret = -EINVAL;
 		goto err_codec;
 	}
+
+	if (pdata->has_buck_vsel_gpio)
+		msm_cdc_pinctrl_select_active_state(pdata->buck_vsel_ctl_np);
+
 	device_id = slim_get_device_id(slim);
 	if (!device_id) {
 		dev_err(&slim->dev, "%s: Error, no device id\n", __func__);
diff --git a/drivers/mfd/wcd9xxx-utils.c b/drivers/mfd/wcd9xxx-utils.c
index 8d3d4ad..f72585a 100644
--- a/drivers/mfd/wcd9xxx-utils.c
+++ b/drivers/mfd/wcd9xxx-utils.c
@@ -342,6 +342,19 @@
 		goto err_parse_dt_prop;
 	}
 
+	pdata->has_buck_vsel_gpio = of_property_read_bool(dev->of_node,
+						"qcom,has-buck-vsel-gpio");
+	if (pdata->has_buck_vsel_gpio) {
+		pdata->buck_vsel_ctl_np = of_parse_phandle(dev->of_node,
+				"qcom,buck-vsel-gpio-node", 0);
+		if (!pdata->buck_vsel_ctl_np) {
+			dev_err(dev, "%s No entry for %s property in node %s\n",
+				__func__, "qcom,buck-vsel-gpio-node",
+				dev->of_node->full_name);
+			goto err_parse_dt_prop;
+		}
+	}
+
 	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-mclk-clk-rate",
 					   &prop_val)))
 		pdata->mclk_rate = prop_val;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e203ba6..2e5da54 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -479,6 +479,15 @@
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config HDCP_QSEECOM
+	tristate "QTI High-Bandwidth Digital Content Protection Module"
+	help
+	  This module implements HDCP 2.2 features over external interfaces
+	  such as the DisplayPort interface. It exposes APIs for the interface
+	  driver to communicate with QTI Secure Execution Environment (QSEE)
+	  via the QSEECOM Driver and also communicates with the Receiver via
+	  APIs exposed by the interface driver.
+
 config QSEECOM
         tristate "QTI Secure Execution Communicator driver"
         help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e1c6ae1..cfea4a5 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,6 +49,7 @@
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
+obj-$(CONFIG_HDCP_QSEECOM)	+= hdcp.o
 obj-$(CONFIG_QSEECOM)		+= qseecom.o
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 65fed71..cc91f7b 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -375,6 +375,7 @@
 			 struct device *dev)
 {
 	struct enclosure_component *cdev;
+	int err;
 
 	if (!edev || component >= edev->components)
 		return -EINVAL;
@@ -384,12 +385,17 @@
 	if (cdev->dev == dev)
 		return -EEXIST;
 
-	if (cdev->dev)
+	if (cdev->dev) {
 		enclosure_remove_links(cdev);
-
-	put_device(cdev->dev);
+		put_device(cdev->dev);
+	}
 	cdev->dev = get_device(dev);
-	return enclosure_add_links(cdev);
+	err = enclosure_add_links(cdev);
+	if (err) {
+		put_device(cdev->dev);
+		cdev->dev = NULL;
+	}
+	return err;
 }
 EXPORT_SYMBOL_GPL(enclosure_add_device);
 
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
new file mode 100644
index 0000000..eab93cc
--- /dev/null
+++ b/drivers/misc/hdcp.c
@@ -0,0 +1,2549 @@
+/* Copyright (c) 2015-2017, 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)	"[hdcp-lib] %s: " fmt, __func__
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/uaccess.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/errno.h>
+#include <linux/hdcp_qseecom.h>
+#include <linux/kthread.h>
+#include <linux/of.h>
+#include <video/msm_hdmi_hdcp_mgr.h>
+
+#include "qseecom_kernel.h"
+
+#define CLASS_NAME "hdcp"
+#define DRIVER_NAME "msm_hdcp"
+#define TZAPP_NAME            "hdcp2p2"
+#define HDCP1_APP_NAME        "hdcp1"
+#define QSEECOM_SBUFF_SIZE    0x1000
+
+#define MAX_TX_MESSAGE_SIZE	129
+#define MAX_RX_MESSAGE_SIZE	534
+#define MAX_TOPOLOGY_ELEMS	32
+#define HDCP1_AKSV_SIZE         8
+
+/* parameters related to LC_Init message */
+#define MESSAGE_ID_SIZE            1
+#define LC_INIT_MESSAGE_SIZE       (MESSAGE_ID_SIZE+BITS_64_IN_BYTES)
+
+/* parameters related to SKE_Send_EKS message */
+#define SKE_SEND_EKS_MESSAGE_SIZE \
+	(MESSAGE_ID_SIZE+BITS_128_IN_BYTES+BITS_64_IN_BYTES)
+
+/* all message IDs */
+#define INVALID_MESSAGE_ID               0
+#define AKE_INIT_MESSAGE_ID              2
+#define AKE_SEND_CERT_MESSAGE_ID         3
+#define AKE_NO_STORED_KM_MESSAGE_ID      4
+#define AKE_STORED_KM_MESSAGE_ID         5
+#define AKE_SEND_H_PRIME_MESSAGE_ID      7
+#define AKE_SEND_PAIRING_INFO_MESSAGE_ID 8
+#define LC_INIT_MESSAGE_ID               9
+#define LC_SEND_L_PRIME_MESSAGE_ID      10
+#define SKE_SEND_EKS_MESSAGE_ID         11
+#define REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID 12
+#define REPEATER_AUTH_SEND_ACK_MESSAGE_ID      15
+#define REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID 16
+#define REPEATER_AUTH_STREAM_READY_MESSAGE_ID  17
+#define SKE_SEND_TYPE_ID                       18
+#define HDCP2P2_MAX_MESSAGES                   19
+
+#define HDCP1_SET_KEY_MESSAGE_ID       202
+#define HDCP1_SET_ENC_MESSAGE_ID       205
+
+#define BITS_40_IN_BYTES      5
+#define BITS_64_IN_BYTES      8
+#define BITS_128_IN_BYTES    16
+#define RXCAPS_SIZE           3
+#define RXINFO_SIZE           2
+#define SEQ_NUM_V_SIZE        3
+
+#define RCVR_ID_SIZE BITS_40_IN_BYTES
+#define MAX_RCVR_IDS_ALLOWED_IN_LIST 31
+#define MAX_RCVR_ID_LIST_SIZE \
+		(RCVR_ID_SIZE * MAX_RCVR_IDS_ALLOWED_IN_LIST)
+/*
+ * Minimum wait as per standard is 200 ms. Keep it 220 ms
+ * to be on safe side.
+ */
+#define SLEEP_SET_HW_KEY_MS 220
+
+/* hdcp command status */
+#define HDCP_SUCCESS      0
+
+/* flags set by tz in response message */
+#define HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST       1
+
+#define HDCP_TXMTR_SERVICE_ID                 0x0001000
+#define SERVICE_CREATE_CMD(x)                 (HDCP_TXMTR_SERVICE_ID | x)
+
+#define HDCP_TXMTR_INIT                       SERVICE_CREATE_CMD(1)
+#define HDCP_TXMTR_DEINIT                     SERVICE_CREATE_CMD(2)
+#define HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE   SERVICE_CREATE_CMD(3)
+#define HDCP_TXMTR_SEND_MESSAGE_TIMEOUT       SERVICE_CREATE_CMD(4)
+#define HDCP_TXMTR_SET_HW_KEY                 SERVICE_CREATE_CMD(5)
+#define HDCP_TXMTR_QUERY_STREAM_TYPE          SERVICE_CREATE_CMD(6)
+#define HDCP_LIB_INIT                         SERVICE_CREATE_CMD(11)
+#define HDCP_LIB_DEINIT                       SERVICE_CREATE_CMD(12)
+#define HDCP_TXMTR_GET_VERSION                SERVICE_CREATE_CMD(14)
+#define HDCP_TXMTR_VERIFY_KEY                 SERVICE_CREATE_CMD(15)
+#define HDCP_SESSION_INIT                     SERVICE_CREATE_CMD(16)
+#define HDCP_SESSION_DEINIT                   SERVICE_CREATE_CMD(17)
+#define HDCP_TXMTR_START_AUTHENTICATE         SERVICE_CREATE_CMD(18)
+
+#define HCDP_TXMTR_GET_MAJOR_VERSION(v) (((v) >> 16) & 0xFF)
+#define HCDP_TXMTR_GET_MINOR_VERSION(v) (((v) >> 8) & 0xFF)
+#define HCDP_TXMTR_GET_PATCH_VERSION(v) ((v) & 0xFF)
+
+#define HDCP_CLIENT_MAJOR_VERSION 2
+#define HDCP_CLIENT_MINOR_VERSION 1
+#define HDCP_CLIENT_PATCH_VERSION 0
+#define HDCP_CLIENT_MAKE_VERSION(maj, min, patch) \
+	((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF))
+
+#define REAUTH_REQ BIT(3)
+#define LINK_INTEGRITY_FAILURE BIT(4)
+
+#define HDCP_LIB_EXECUTE(x) {\
+		kthread_queue_work(&handle->worker, &handle->wk_##x);\
+}
+
+static const struct hdcp_msg_data hdcp_msg_lookup[HDCP2P2_MAX_MESSAGES] = {
+	[AKE_INIT_MESSAGE_ID] = { 2,
+		{ {"rtx", 0x69000, 8}, {"TxCaps", 0x69008, 3} },
+		0 },
+	[AKE_SEND_CERT_MESSAGE_ID] = { 3,
+		{ {"cert-rx", 0x6900B, 522}, {"rrx", 0x69215, 8},
+			{"RxCaps", 0x6921D, 3} },
+		0 },
+	[AKE_NO_STORED_KM_MESSAGE_ID] = { 1,
+		{ {"Ekpub_km", 0x69220, 128} },
+		0 },
+	[AKE_STORED_KM_MESSAGE_ID] = { 2,
+		{ {"Ekh_km", 0x692A0, 16}, {"m", 0x692B0, 16} },
+		0 },
+	[AKE_SEND_H_PRIME_MESSAGE_ID] = { 1,
+		{ {"H'", 0x692C0, 32} },
+		(1 << 1) },
+	[AKE_SEND_PAIRING_INFO_MESSAGE_ID] =  { 1,
+		{ {"Ekh_km", 0x692E0, 16} },
+		(1 << 2) },
+	[LC_INIT_MESSAGE_ID] = { 1,
+		{ {"rn", 0x692F0, 8} },
+		0 },
+	[LC_SEND_L_PRIME_MESSAGE_ID] = { 1,
+		{ {"L'", 0x692F8, 32} },
+		0 },
+	[SKE_SEND_EKS_MESSAGE_ID] = { 2,
+		{ {"Edkey_ks", 0x69318, 16}, {"riv", 0x69328, 8} },
+		0 },
+	[SKE_SEND_TYPE_ID] = { 1,
+		{ {"type", 0x69494, 1} },
+		0 },
+	[REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID] = { 4,
+		{ {"RxInfo", 0x69330, 2}, {"seq_num_V", 0x69332, 3},
+			{"V'", 0x69335, 16}, {"ridlist", 0x69345, 155} },
+		(1 << 0) },
+	[REPEATER_AUTH_SEND_ACK_MESSAGE_ID] = { 1,
+		{ {"V", 0x693E0, 16} },
+		0 },
+	[REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID] = { 3,
+		{ {"seq_num_M", 0x693F0, 3}, {"k", 0x693F3, 2},
+			{"streamID_Type", 0x693F5, 126} },
+		0 },
+	[REPEATER_AUTH_STREAM_READY_MESSAGE_ID] = { 1,
+		{ {"M'", 0x69473, 32} },
+		0 }
+};
+
+enum hdcp_state {
+	HDCP_STATE_INIT = 0x00,
+	HDCP_STATE_APP_LOADED = 0x01,
+	HDCP_STATE_SESSION_INIT = 0x02,
+	HDCP_STATE_TXMTR_INIT = 0x04,
+	HDCP_STATE_AUTHENTICATED = 0x08,
+	HDCP_STATE_ERROR = 0x10
+};
+
+enum hdcp_element {
+	HDCP_TYPE_UNKNOWN,
+	HDCP_TYPE_RECEIVER,
+	HDCP_TYPE_REPEATER,
+};
+
+enum hdcp_version {
+	HDCP_VERSION_UNKNOWN,
+	HDCP_VERSION_2_2,
+	HDCP_VERSION_1_4
+};
+
+struct receiver_info {
+	unsigned char rcvrInfo[RCVR_ID_SIZE];
+	enum hdcp_element elem_type;
+	enum hdcp_version hdcp_version;
+};
+
+struct topology_info {
+	unsigned int nNumRcvrs;
+	struct receiver_info rcvinfo[MAX_TOPOLOGY_ELEMS];
+};
+
+struct __attribute__ ((__packed__)) hdcp1_key_set_req {
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp1_key_set_rsp {
+	uint32_t commandid;
+	uint32_t ret;
+	uint8_t ksv[HDCP1_AKSV_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_version_req {
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_version_rsp {
+	uint32_t commandid;
+	uint32_t commandId;
+	uint32_t appversion;
+};
+
+struct __attribute__ ((__packed__)) hdcp_verify_key_req {
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_verify_key_rsp {
+	uint32_t status;
+	uint32_t commandId;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_init_req_v1 {
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_init_rsp_v1 {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t ctxhandle;
+	uint32_t timeout;
+	uint32_t msglen;
+	uint8_t message[MAX_TX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_init_req {
+	uint32_t commandid;
+	uint32_t clientversion;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_init_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t appversion;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_deinit_req {
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_deinit_rsp {
+	uint32_t status;
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_session_init_req {
+	uint32_t commandid;
+	uint32_t deviceid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_session_init_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t sessionid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_session_deinit_req {
+	uint32_t commandid;
+	uint32_t sessionid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_lib_session_deinit_rsp {
+	uint32_t status;
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_tx_init_req_v1 {
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_tx_init_rsp_v1 {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t ctxhandle;
+	uint32_t timeout;
+	uint32_t msglen;
+	uint8_t message[MAX_TX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_tx_init_req {
+	uint32_t commandid;
+	uint32_t sessionid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_tx_init_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t ctxhandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_deinit_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_deinit_rsp {
+	uint32_t status;
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_rcvd_msg_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+	uint32_t msglen;
+	uint8_t msg[MAX_RX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_rcvd_msg_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t state;
+	uint32_t timeout;
+	uint32_t flag;
+	uint32_t msglen;
+	uint8_t msg[MAX_TX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_set_hw_key_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_set_hw_key_rsp {
+	uint32_t status;
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_send_timeout_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_send_timeout_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t timeout;
+	uint32_t msglen;
+	uint8_t message[MAX_TX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_query_stream_type_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_query_stream_type_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t timeout;
+	uint32_t msglen;
+	uint8_t msg[MAX_TX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_set_stream_type_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+	uint8_t streamtype;
+};
+
+struct __attribute__ ((__packed__)) hdcp_set_stream_type_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t timeout;
+	uint32_t msglen;
+	uint8_t message[MAX_TX_MESSAGE_SIZE];
+};
+
+struct __attribute__ ((__packed__)) hdcp_update_srm_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+	uint32_t srmoffset;
+	uint32_t srmlength;
+};
+
+struct __attribute__ ((__packed__)) hdcp_update_srm_rsp {
+	uint32_t status;
+	uint32_t commandid;
+};
+
+struct __attribute__ ((__packed__)) hdcp_get_topology_req {
+	uint32_t commandid;
+	uint32_t ctxhandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_get_topology_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	struct topology_info topologyinfo;
+};
+
+struct __attribute__ ((__packed__)) rxvr_info_struct {
+	uint8_t rcvrCert[522];
+	uint8_t rrx[BITS_64_IN_BYTES];
+	uint8_t rxcaps[RXCAPS_SIZE];
+	bool repeater;
+};
+
+struct __attribute__ ((__packed__)) repeater_info_struct {
+	uint8_t RxInfo[RXINFO_SIZE];
+	uint8_t seq_num_V[SEQ_NUM_V_SIZE];
+	bool seq_num_V_Rollover_flag;
+	uint8_t ReceiverIDList[MAX_RCVR_ID_LIST_SIZE];
+	uint32_t ReceiverIDListLen;
+};
+
+struct __attribute__ ((__packed__)) hdcp1_set_enc_req {
+	uint32_t commandid;
+	uint32_t enable;
+};
+
+struct __attribute__ ((__packed__)) hdcp1_set_enc_rsp {
+	uint32_t commandid;
+	uint32_t ret;
+};
+
+struct __attribute__ ((__packed__)) hdcp_start_auth_req {
+	uint32_t commandid;
+	uint32_t ctxHandle;
+};
+
+struct __attribute__ ((__packed__)) hdcp_start_auth_rsp {
+	uint32_t status;
+	uint32_t commandid;
+	uint32_t ctxhandle;
+	uint32_t timeout;
+	uint32_t msglen;
+	uint8_t message[MAX_TX_MESSAGE_SIZE];
+};
+
+struct hdcp_lib_handle {
+	unsigned char *listener_buf;
+	uint32_t msglen;
+	uint32_t tz_ctxhandle;
+	uint32_t hdcp_timeout;
+	uint32_t timeout_left;
+	uint32_t wait_timeout;
+	bool no_stored_km_flag;
+	bool feature_supported;
+	bool authenticated;
+	void *client_ctx;
+	struct hdcp_client_ops *client_ops;
+	struct mutex msg_lock;
+	struct mutex wakeup_mutex;
+	enum hdcp_state hdcp_state;
+	enum hdcp_lib_wakeup_cmd wakeup_cmd;
+	bool repeater_flag;
+	bool update_stream;
+	struct qseecom_handle *qseecom_handle;
+	int last_msg_sent;
+	int last_msg;
+	char *last_msg_recvd_buf;
+	uint32_t last_msg_recvd_len;
+	atomic_t hdcp_off;
+	uint32_t session_id;
+	enum hdcp_device_type device_type;
+
+	struct task_struct *thread;
+	struct completion poll_wait;
+
+	struct kthread_worker worker;
+	struct kthread_work wk_init;
+	struct kthread_work wk_msg_sent;
+	struct kthread_work wk_msg_recvd;
+	struct kthread_work wk_timeout;
+	struct kthread_work wk_clean;
+	struct kthread_work wk_wait;
+	struct kthread_work wk_stream;
+
+	int (*hdcp_app_init)(struct hdcp_lib_handle *handle);
+	int (*hdcp_txmtr_init)(struct hdcp_lib_handle *handle);
+};
+
+struct hdcp_lib_message_map {
+	int msg_id;
+	const char *msg_name;
+};
+
+struct msm_hdcp_mgr {
+	struct platform_device *pdev;
+	dev_t dev_num;
+	struct cdev cdev;
+	struct class *class;
+	struct device *device;
+	struct HDCP_V2V1_MSG_TOPOLOGY cached_tp;
+	u32 tp_msgid;
+	void *client_ctx;
+	struct hdcp_lib_handle *handle;
+};
+
+static struct msm_hdcp_mgr *hdcp_drv_mgr;
+static struct hdcp_lib_handle *drv_client_handle;
+
+static void hdcp_lib_clean(struct hdcp_lib_handle *handle);
+static void hdcp_lib_init(struct hdcp_lib_handle *handle);
+static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle);
+static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle);
+static void hdcp_lib_timeout(struct hdcp_lib_handle *handle);
+static void hdcp_lib_stream(struct hdcp_lib_handle *handle);
+static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle);
+
+static struct qseecom_handle *hdcp1_handle;
+static bool hdcp1_supported = true;
+static bool hdcp1_enc_enabled;
+static struct mutex hdcp1_ta_cmd_lock;
+
+static const char *hdcp_lib_message_name(int msg_id)
+{
+	/*
+	 * Message ID map. The first number indicates the message number
+	 * assigned to the message by the HDCP 2.2 spec. This is also the first
+	 * byte of every HDCP 2.2 authentication protocol message.
+	 */
+	static struct hdcp_lib_message_map hdcp_lib_msg_map[] = {
+		{2, "AKE_INIT"},
+		{3, "AKE_SEND_CERT"},
+		{4, "AKE_NO_STORED_KM"},
+		{5, "AKE_STORED_KM"},
+		{7, "AKE_SEND_H_PRIME"},
+		{8, "AKE_SEND_PAIRING_INFO"},
+		{9, "LC_INIT"},
+		{10, "LC_SEND_L_PRIME"},
+		{11, "SKE_SEND_EKS"},
+		{12, "REPEATER_AUTH_SEND_RECEIVERID_LIST"},
+		{15, "REPEATER_AUTH_SEND_ACK"},
+		{16, "REPEATER_AUTH_STREAM_MANAGE"},
+		{17, "REPEATER_AUTH_STREAM_READY"},
+		{18, "SKE_SEND_TYPE_ID"},
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hdcp_lib_msg_map); i++) {
+		if (msg_id == hdcp_lib_msg_map[i].msg_id)
+			return hdcp_lib_msg_map[i].msg_name;
+	}
+	return "UNKNOWN";
+}
+
+static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
+				     struct hdcp_wakeup_data *data)
+{
+	switch (handle->last_msg) {
+	case INVALID_MESSAGE_ID:
+		return AKE_INIT_MESSAGE_ID;
+	case AKE_INIT_MESSAGE_ID:
+		return AKE_SEND_CERT_MESSAGE_ID;
+	case AKE_SEND_CERT_MESSAGE_ID:
+		if (handle->no_stored_km_flag)
+			return AKE_NO_STORED_KM_MESSAGE_ID;
+		else
+			return AKE_STORED_KM_MESSAGE_ID;
+	case AKE_STORED_KM_MESSAGE_ID:
+	case AKE_NO_STORED_KM_MESSAGE_ID:
+		return AKE_SEND_H_PRIME_MESSAGE_ID;
+	case AKE_SEND_H_PRIME_MESSAGE_ID:
+		if (handle->no_stored_km_flag)
+			return AKE_SEND_PAIRING_INFO_MESSAGE_ID;
+		else
+			return LC_INIT_MESSAGE_ID;
+	case AKE_SEND_PAIRING_INFO_MESSAGE_ID:
+		return LC_INIT_MESSAGE_ID;
+	case LC_INIT_MESSAGE_ID:
+		return LC_SEND_L_PRIME_MESSAGE_ID;
+	case LC_SEND_L_PRIME_MESSAGE_ID:
+		return SKE_SEND_EKS_MESSAGE_ID;
+	case SKE_SEND_EKS_MESSAGE_ID:
+		if (!handle->repeater_flag)
+			return SKE_SEND_TYPE_ID;
+	case SKE_SEND_TYPE_ID:
+	case REPEATER_AUTH_STREAM_READY_MESSAGE_ID:
+	case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
+		if (!handle->repeater_flag)
+			return INVALID_MESSAGE_ID;
+
+		if (data->cmd == HDCP_WKUP_CMD_SEND_MESSAGE)
+			return REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID;
+		else
+			return REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID;
+	case REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID:
+		return REPEATER_AUTH_SEND_ACK_MESSAGE_ID;
+	case REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID:
+		return REPEATER_AUTH_STREAM_READY_MESSAGE_ID;
+	default:
+		pr_err("Uknown message ID (%d)", handle->last_msg);
+		return -EINVAL;
+	}
+}
+
+static void hdcp_lib_wait_for_response(struct hdcp_lib_handle *handle,
+				       struct hdcp_wakeup_data *data)
+{
+	switch (handle->last_msg) {
+	case AKE_SEND_H_PRIME_MESSAGE_ID:
+		if (handle->no_stored_km_flag)
+			handle->wait_timeout = HZ;
+		else
+			handle->wait_timeout = HZ / 4;
+		break;
+	case AKE_SEND_PAIRING_INFO_MESSAGE_ID:
+		handle->wait_timeout = HZ / 4;
+		break;
+	case REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID:
+		if (!handle->authenticated)
+			handle->wait_timeout = HZ * 3;
+		else
+			handle->wait_timeout = 0;
+		break;
+	default:
+		handle->wait_timeout = 0;
+	}
+
+	if (handle->wait_timeout)
+		kthread_queue_work(&handle->worker, &handle->wk_wait);
+}
+
+static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
+				  struct hdcp_wakeup_data *data)
+{
+	int rc = 0, i;
+
+	if (!handle || !handle->client_ops || !handle->client_ops->wakeup ||
+	    !data || (data->cmd == HDCP_WKUP_CMD_INVALID))
+		return;
+
+	data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE;
+
+	if (data->cmd == HDCP_WKUP_CMD_RECV_MESSAGE ||
+	    data->cmd == HDCP_WKUP_CMD_LINK_POLL)
+		handle->last_msg = hdcp_lib_get_next_message(handle, data);
+
+	if (handle->last_msg != INVALID_MESSAGE_ID &&
+	    data->cmd != HDCP_WKUP_CMD_STATUS_SUCCESS &&
+	    data->cmd != HDCP_WKUP_CMD_STATUS_FAILED) {
+		u32 msg_num, rx_status;
+		const struct hdcp_msg_part *msg;
+
+		pr_debug("lib->client: %s (%s)\n",
+			hdcp_cmd_to_str(data->cmd),
+			hdcp_lib_message_name(handle->last_msg));
+
+		data->message_data = &hdcp_msg_lookup[handle->last_msg];
+
+		msg_num = data->message_data->num_messages;
+		msg = data->message_data->messages;
+		rx_status = data->message_data->rx_status;
+
+		pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
+
+		for (i = 0; i < msg_num; i++)
+			pr_debug("%10s | %6x | %4d\n",
+				msg[i].name, msg[i].offset,
+				msg[i].length);
+	} else {
+		pr_debug("lib->client: %s\n", hdcp_cmd_to_str(data->cmd));
+	}
+
+	rc = handle->client_ops->wakeup(data);
+	if (rc)
+		pr_err("error sending %s to client\n",
+		       hdcp_cmd_to_str(data->cmd));
+
+	hdcp_lib_wait_for_response(handle, data);
+}
+
+static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
+{
+	char msg_name[50];
+	struct hdcp_wakeup_data cdata = {
+		HDCP_WKUP_CMD_SEND_MESSAGE
+	};
+
+	cdata.context = handle->client_ctx;
+	cdata.send_msg_buf = handle->listener_buf;
+	cdata.send_msg_len = handle->msglen;
+	cdata.timeout = handle->hdcp_timeout;
+
+	snprintf(msg_name, sizeof(msg_name), "%s: ",
+		hdcp_lib_message_name((int)cdata.send_msg_buf[0]));
+
+	print_hex_dump(KERN_DEBUG, msg_name,
+		DUMP_PREFIX_NONE, 16, 1, cdata.send_msg_buf,
+		cdata.send_msg_len, false);
+
+	hdcp_lib_wakeup_client(handle, &cdata);
+}
+
+static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_set_hw_key_req *req_buf;
+	struct hdcp_set_hw_key_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	/*
+	 * wait at least 200ms before enabling encryption
+	 * as per hdcp2p2 sepcifications.
+	 */
+	msleep(SLEEP_SET_HW_KEY_MS);
+
+	req_buf = (struct hdcp_set_hw_key_req *)(handle->qseecom_handle->sbuf);
+	req_buf->commandid = HDCP_TXMTR_SET_HW_KEY;
+	req_buf->ctxhandle = handle->tz_ctxhandle;
+
+	rsp_buf = (struct hdcp_set_hw_key_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_set_hw_key_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_set_hw_key_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_set_hw_key_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status < 0)) {
+		pr_err("qseecom cmd failed with err = %d status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	/* reached an authenticated state */
+	handle->hdcp_state |= HDCP_STATE_AUTHENTICATED;
+
+	pr_debug("success\n");
+	return 0;
+error:
+	if (handle && !atomic_read(&handle->hdcp_off))
+		HDCP_LIB_EXECUTE(clean);
+
+	return rc;
+}
+
+static int hdcp_lib_get_version(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_version_req *req_buf;
+	struct hdcp_version_rsp *rsp_buf;
+	uint32_t app_major_version = 0;
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("library not loaded\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/* get the TZ hdcp2p2 app version */
+	req_buf = (struct hdcp_version_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_TXMTR_GET_VERSION;
+
+	rsp_buf = (struct hdcp_version_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_version_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle,
+				  req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_lib_init_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_lib_init_rsp)));
+
+	if (rc < 0) {
+		pr_err("qseecom cmd failed err = %d\n", rc);
+		goto exit;
+	}
+
+	app_major_version = HCDP_TXMTR_GET_MAJOR_VERSION(rsp_buf->appversion);
+
+	pr_debug("hdcp2p2 app major version %d, app version %d\n",
+		 app_major_version, rsp_buf->appversion);
+
+exit:
+	return rc;
+}
+
+static int hdcp_lib_verify_keys(struct hdcp_lib_handle *handle)
+{
+	int rc = -EINVAL;
+	struct hdcp_verify_key_req *req_buf;
+	struct hdcp_verify_key_rsp *rsp_buf;
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("app not loaded\n");
+		goto exit;
+	}
+
+	req_buf = (struct hdcp_verify_key_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_TXMTR_VERIFY_KEY;
+
+	rsp_buf = (struct hdcp_verify_key_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_verify_key_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle,
+				  req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_verify_key_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_verify_key_rsp)));
+
+	if (rc < 0) {
+		pr_err("qseecom cmd failed err = %d\n", rc);
+		goto exit;
+	}
+
+	return rsp_buf->status;
+exit:
+	return rc;
+}
+
+static int hdcp_app_init(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_lib_init_req *req_buf;
+	struct hdcp_lib_init_rsp *rsp_buf;
+	uint32_t app_minor_version = 0;
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("library not loaded\n");
+		goto exit;
+	}
+
+	/* now load the app by sending hdcp_lib_init */
+	req_buf = (struct hdcp_lib_init_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_LIB_INIT;
+	req_buf->clientversion =
+	    HDCP_CLIENT_MAKE_VERSION(HDCP_CLIENT_MAJOR_VERSION,
+				     HDCP_CLIENT_MINOR_VERSION,
+				     HDCP_CLIENT_PATCH_VERSION);
+	rsp_buf = (struct hdcp_lib_init_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_lib_init_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle,
+				  req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_lib_init_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_lib_init_rsp)));
+
+	if (rc < 0) {
+		pr_err("qseecom cmd failed err = %d\n", rc);
+		goto exit;
+	}
+
+	app_minor_version = HCDP_TXMTR_GET_MINOR_VERSION(rsp_buf->appversion);
+	if (app_minor_version != HDCP_CLIENT_MINOR_VERSION) {
+		pr_err
+		    ("client-app minor version mismatch app(%d), client(%d)\n",
+		     app_minor_version, HDCP_CLIENT_MINOR_VERSION);
+		rc = -1;
+		goto exit;
+	}
+	pr_debug("success\n");
+	pr_debug("client version major(%d), minor(%d), patch(%d)\n",
+		 HDCP_CLIENT_MAJOR_VERSION, HDCP_CLIENT_MINOR_VERSION,
+		 HDCP_CLIENT_PATCH_VERSION);
+	pr_debug("app version major(%d), minor(%d), patch(%d)\n",
+		 HCDP_TXMTR_GET_MAJOR_VERSION(rsp_buf->appversion),
+		 HCDP_TXMTR_GET_MINOR_VERSION(rsp_buf->appversion),
+		 HCDP_TXMTR_GET_PATCH_VERSION(rsp_buf->appversion));
+
+exit:
+	return rc;
+}
+
+static int hdcp_lib_library_load(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		goto exit;
+	}
+
+	if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
+		pr_err("library already loaded\n");
+		goto exit;
+	}
+
+	/*
+	 * allocating resource for qseecom handle
+	 * the app is not loaded here
+	 */
+	rc = qseecom_start_app(&(handle->qseecom_handle),
+			       TZAPP_NAME, QSEECOM_SBUFF_SIZE);
+	if (rc) {
+		pr_err("qseecom_start_app failed %d\n", rc);
+		goto exit;
+	}
+
+	handle->hdcp_state |= HDCP_STATE_APP_LOADED;
+	pr_debug("qseecom_start_app success\n");
+
+	rc = hdcp_lib_get_version(handle);
+	if (rc) {
+		pr_err("library get version failed\n");
+		goto exit;
+	}
+
+	handle->hdcp_app_init = hdcp_app_init;
+	handle->hdcp_txmtr_init = hdcp_lib_txmtr_init;
+
+	if (handle->hdcp_app_init == NULL) {
+		pr_err("invalid app init function pointer\n");
+		goto exit;
+	}
+
+	rc = handle->hdcp_app_init(handle);
+	if (rc) {
+		pr_err("app init failed\n");
+		goto exit;
+	}
+exit:
+	return rc;
+}
+
+static int hdcp_lib_library_unload(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_lib_deinit_req *req_buf;
+	struct hdcp_lib_deinit_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("library not loaded\n");
+		return rc;
+	}
+
+	/* unloading app by sending hdcp_lib_deinit cmd */
+	req_buf = (struct hdcp_lib_deinit_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_LIB_DEINIT;
+	rsp_buf = (struct hdcp_lib_deinit_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_lib_deinit_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle,
+				  req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_lib_deinit_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_lib_deinit_rsp)));
+
+	if (rc < 0) {
+		pr_err("qseecom cmd failed err = %d\n", rc);
+		goto exit;
+	}
+
+	/* deallocate the resources for qseecom handle */
+	rc = qseecom_shutdown_app(&handle->qseecom_handle);
+	if (rc) {
+		pr_err("qseecom_shutdown_app failed err: %d\n", rc);
+		goto exit;
+	}
+
+	handle->hdcp_state &= ~HDCP_STATE_APP_LOADED;
+	pr_debug("success\n");
+exit:
+	return rc;
+}
+
+static int hdcp_lib_session_init(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_lib_session_init_req *req_buf;
+	struct hdcp_lib_session_init_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("app not loaded\n");
+		goto exit;
+	}
+
+	if (handle->hdcp_state & HDCP_STATE_SESSION_INIT) {
+		pr_err("session already initialized\n");
+		goto exit;
+	}
+
+	/* send HDCP_Session_Init command to TZ */
+	req_buf =
+	    (struct hdcp_lib_session_init_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_SESSION_INIT;
+	req_buf->deviceid = handle->device_type;
+	rsp_buf = (struct hdcp_lib_session_init_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_lib_session_init_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_lib_session_init_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_lib_session_init_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) ||
+	    (rsp_buf->commandid != HDCP_SESSION_INIT)) {
+		pr_err("qseecom cmd failed with err = %d, status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	pr_debug("session id %d\n", rsp_buf->sessionid);
+
+	handle->session_id = rsp_buf->sessionid;
+	handle->hdcp_state |= HDCP_STATE_SESSION_INIT;
+
+	pr_debug("success\n");
+exit:
+	return rc;
+}
+
+static int hdcp_lib_session_deinit(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_lib_session_deinit_req *req_buf;
+	struct hdcp_lib_session_deinit_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("app not loaded\n");
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) {
+		/* unload library here */
+		pr_err("session not initialized\n");
+		goto exit;
+	}
+
+	/* send command to TZ */
+	req_buf =
+	    (struct hdcp_lib_session_deinit_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_SESSION_DEINIT;
+	req_buf->sessionid = handle->session_id;
+	rsp_buf = (struct hdcp_lib_session_deinit_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_lib_session_deinit_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_lib_session_deinit_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_lib_session_deinit_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status < 0) ||
+	    (rsp_buf->commandid != HDCP_SESSION_DEINIT)) {
+		pr_err("qseecom cmd failed with err = %d status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	handle->hdcp_state &= ~HDCP_STATE_SESSION_INIT;
+	pr_debug("success\n");
+exit:
+	return rc;
+}
+
+static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_tx_init_req *req_buf;
+	struct hdcp_tx_init_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) {
+		pr_err("session not initialized\n");
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("library not loaded\n");
+		goto exit;
+	}
+
+	/* send HDCP_Txmtr_Init command to TZ */
+	req_buf = (struct hdcp_tx_init_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_TXMTR_INIT;
+	req_buf->sessionid = handle->session_id;
+	rsp_buf = (struct hdcp_tx_init_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_tx_init_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_tx_init_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_tx_init_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) ||
+	    (rsp_buf->commandid != HDCP_TXMTR_INIT)) {
+		pr_err("qseecom cmd failed with err = %d, status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	handle->tz_ctxhandle = rsp_buf->ctxhandle;
+	handle->hdcp_state |= HDCP_STATE_TXMTR_INIT;
+
+	pr_debug("success\n");
+exit:
+	return rc;
+}
+
+static int hdcp_lib_txmtr_deinit(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_deinit_req *req_buf;
+	struct hdcp_deinit_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+		pr_err("app not loaded\n");
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) {
+		/* unload library here */
+		pr_err("txmtr not initialized\n");
+		goto exit;
+	}
+
+	/* send command to TZ */
+	req_buf = (struct hdcp_deinit_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_TXMTR_DEINIT;
+	req_buf->ctxhandle = handle->tz_ctxhandle;
+	rsp_buf = (struct hdcp_deinit_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_deinit_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status < 0) ||
+	    (rsp_buf->commandid != HDCP_TXMTR_DEINIT)) {
+		pr_err("qseecom cmd failed with err = %d status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	handle->hdcp_state &= ~HDCP_STATE_TXMTR_INIT;
+	pr_debug("success\n");
+exit:
+	return rc;
+}
+
+static int hdcp_lib_start_auth(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_start_auth_req *req_buf;
+	struct hdcp_start_auth_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) {
+		pr_err("session not initialized\n");
+		goto exit;
+	}
+
+	if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) {
+		pr_err("txmtr not initialized\n");
+		goto exit;
+	}
+
+	/* send HDCP_Txmtr_Start_Auth command to TZ */
+	req_buf = (struct hdcp_start_auth_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_TXMTR_START_AUTHENTICATE;
+	req_buf->ctxHandle = handle->tz_ctxhandle;
+	rsp_buf = (struct hdcp_start_auth_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_start_auth_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_start_auth_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_start_auth_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) ||
+	    (rsp_buf->commandid != HDCP_TXMTR_START_AUTHENTICATE) ||
+	    (rsp_buf->msglen <= 0) || (rsp_buf->message == NULL)) {
+		pr_err("qseecom cmd failed with err = %d, status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	pr_debug("recvd %s from TZ at %dms\n",
+		 hdcp_lib_message_name((int)rsp_buf->message[0]),
+		 jiffies_to_msecs(jiffies));
+
+	handle->last_msg = (int)rsp_buf->message[0];
+
+	/* send the response to HDMI driver */
+	memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
+	memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
+	       rsp_buf->msglen);
+	handle->msglen = rsp_buf->msglen;
+	handle->hdcp_timeout = rsp_buf->timeout;
+
+	handle->tz_ctxhandle = rsp_buf->ctxhandle;
+
+	pr_debug("success\n");
+exit:
+	return rc;
+}
+
+static void hdcp_lib_stream(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_query_stream_type_req *req_buf;
+	struct hdcp_query_stream_type_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		return;
+	}
+
+	if (atomic_read(&handle->hdcp_off)) {
+		pr_debug("invalid state, hdcp off\n");
+		return;
+	}
+
+	if (!handle->repeater_flag) {
+		pr_debug("invalid state, not a repeater\n");
+		return;
+	}
+
+	/* send command to TZ */
+	req_buf =
+	    (struct hdcp_query_stream_type_req *)handle->qseecom_handle->sbuf;
+	req_buf->commandid = HDCP_TXMTR_QUERY_STREAM_TYPE;
+	req_buf->ctxhandle = handle->tz_ctxhandle;
+	rsp_buf = (struct hdcp_query_stream_type_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	     QSEECOM_ALIGN(sizeof(struct hdcp_query_stream_type_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_query_stream_type_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_query_stream_type_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status < 0) || (rsp_buf->msglen <= 0) ||
+	    (rsp_buf->commandid != HDCP_TXMTR_QUERY_STREAM_TYPE) ||
+	    (rsp_buf->msg == NULL)) {
+		pr_err("qseecom cmd failed with err=%d status=%d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	pr_debug("message received from TZ: %s\n",
+		 hdcp_lib_message_name((int)rsp_buf->msg[0]));
+
+	handle->last_msg = (int)rsp_buf->msg[0];
+
+	memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
+	memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg,
+	       rsp_buf->msglen);
+	handle->hdcp_timeout = rsp_buf->timeout;
+	handle->msglen = rsp_buf->msglen;
+exit:
+	if (!rc && !atomic_read(&handle->hdcp_off))
+		hdcp_lib_send_message(handle);
+}
+
+static void hdcp_lib_query_stream_work(struct kthread_work *work)
+{
+	struct hdcp_lib_handle *handle = container_of(work,
+						      struct hdcp_lib_handle,
+						      wk_stream);
+
+	hdcp_lib_stream(handle);
+}
+
+static bool hdcp_lib_client_feature_supported(void *phdcpcontext)
+{
+	int rc = 0;
+	bool supported = false;
+	struct hdcp_lib_handle *handle = phdcpcontext;
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		goto exit;
+	}
+
+	if (handle->feature_supported) {
+		supported = true;
+		goto exit;
+	}
+
+	rc = hdcp_lib_library_load(handle);
+	if (!rc) {
+		if (!hdcp_lib_verify_keys(handle)) {
+			pr_debug("HDCP2p2 supported\n");
+			handle->feature_supported = true;
+			supported = true;
+		}
+		hdcp_lib_library_unload(handle);
+	}
+exit:
+	return supported;
+}
+
+static void hdcp_lib_check_worker_status(struct hdcp_lib_handle *handle)
+{
+	if (!list_empty(&handle->wk_init.node))
+		pr_debug("init work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_init)
+		pr_debug("init work executing\n");
+
+	if (!list_empty(&handle->wk_msg_sent.node))
+		pr_debug("msg_sent work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_msg_sent)
+		pr_debug("msg_sent work executing\n");
+
+	if (!list_empty(&handle->wk_msg_recvd.node))
+		pr_debug("msg_recvd work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_msg_recvd)
+		pr_debug("msg_recvd work executing\n");
+
+	if (!list_empty(&handle->wk_timeout.node))
+		pr_debug("timeout work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_timeout)
+		pr_debug("timeout work executing\n");
+
+	if (!list_empty(&handle->wk_clean.node))
+		pr_debug("clean work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_clean)
+		pr_debug("clean work executing\n");
+
+	if (!list_empty(&handle->wk_wait.node))
+		pr_debug("wait work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_wait)
+		pr_debug("wait work executing\n");
+
+	if (!list_empty(&handle->wk_stream.node))
+		pr_debug("stream work queued\n");
+
+	if (handle->worker.current_work == &handle->wk_stream)
+		pr_debug("stream work executing\n");
+}
+
+static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+
+	if (!list_empty(&handle->worker.work_list))
+		hdcp_lib_check_worker_status(handle);
+
+	if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) {
+		if (!list_empty(&handle->worker.work_list)) {
+			pr_debug("error: queue not empty\n");
+			rc = -EBUSY;
+			goto exit;
+		}
+
+		if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
+			pr_debug("library already loaded\n");
+			rc = -EBUSY;
+			goto exit;
+		}
+	} else {
+		if (atomic_read(&handle->hdcp_off)) {
+			pr_debug("hdcp2.2 session tearing down\n");
+			goto exit;
+		}
+
+		if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+			pr_debug("hdcp 2.2 app not loaded\n");
+			goto exit;
+		}
+	}
+exit:
+	return rc;
+}
+
+static int hdcp_lib_wakeup_thread(struct hdcp_lib_wakeup_data *data)
+{
+	struct hdcp_lib_handle *handle;
+	int rc = 0;
+
+	if (!data)
+		return -EINVAL;
+
+	handle = data->context;
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->wakeup_mutex);
+
+	handle->wakeup_cmd = data->cmd;
+	handle->timeout_left = data->timeout;
+
+	pr_debug("client->lib: %s (%s)\n",
+		hdcp_lib_cmd_to_str(data->cmd),
+		hdcp_lib_message_name(handle->last_msg));
+
+	rc = hdcp_lib_check_valid_state(handle);
+	if (rc)
+		goto exit;
+
+	mutex_lock(&handle->msg_lock);
+	if (data->recvd_msg_len) {
+		kzfree(handle->last_msg_recvd_buf);
+
+		handle->last_msg_recvd_len = data->recvd_msg_len;
+		handle->last_msg_recvd_buf = kzalloc(data->recvd_msg_len,
+						     GFP_KERNEL);
+		if (!handle->last_msg_recvd_buf) {
+			rc = -ENOMEM;
+			mutex_unlock(&handle->msg_lock);
+			goto exit;
+		}
+
+		memcpy(handle->last_msg_recvd_buf, data->recvd_msg_buf,
+		       data->recvd_msg_len);
+	}
+	mutex_unlock(&handle->msg_lock);
+
+	if (!completion_done(&handle->poll_wait))
+		complete_all(&handle->poll_wait);
+
+	switch (handle->wakeup_cmd) {
+	case HDCP_LIB_WKUP_CMD_START:
+		handle->no_stored_km_flag = 0;
+		handle->repeater_flag = false;
+		handle->update_stream = false;
+		handle->last_msg_sent = 0;
+		handle->last_msg = INVALID_MESSAGE_ID;
+		handle->hdcp_timeout = 0;
+		handle->timeout_left = 0;
+		atomic_set(&handle->hdcp_off, 0);
+		handle->hdcp_state = HDCP_STATE_INIT;
+
+		HDCP_LIB_EXECUTE(init);
+		break;
+	case HDCP_LIB_WKUP_CMD_STOP:
+		atomic_set(&handle->hdcp_off, 1);
+
+		HDCP_LIB_EXECUTE(clean);
+		break;
+	case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:
+		handle->last_msg_sent = handle->listener_buf[0];
+
+		HDCP_LIB_EXECUTE(msg_sent);
+		break;
+	case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
+	case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
+	case HDCP_LIB_WKUP_CMD_LINK_FAILED:
+		handle->hdcp_state |= HDCP_STATE_ERROR;
+		HDCP_LIB_EXECUTE(clean);
+		break;
+	case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
+		HDCP_LIB_EXECUTE(msg_recvd);
+		break;
+	case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
+		HDCP_LIB_EXECUTE(timeout);
+		break;
+	case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
+		HDCP_LIB_EXECUTE(stream);
+		break;
+	default:
+		pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
+	}
+exit:
+	mutex_unlock(&handle->wakeup_mutex);
+
+	return rc;
+}
+
+static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle)
+{
+	struct hdcp_wakeup_data cdata = { HDCP_WKUP_CMD_INVALID };
+
+	if (!handle) {
+		pr_err("invalid handle\n");
+		return;
+	}
+
+	cdata.context = handle->client_ctx;
+
+	switch (handle->last_msg_sent) {
+	case SKE_SEND_TYPE_ID:
+		if (!hdcp_lib_enable_encryption(handle)) {
+			handle->authenticated = true;
+
+			cdata.cmd = HDCP_WKUP_CMD_STATUS_SUCCESS;
+			hdcp_lib_wakeup_client(handle, &cdata);
+		}
+
+		/* poll for link check */
+		cdata.cmd = HDCP_WKUP_CMD_LINK_POLL;
+		break;
+	case SKE_SEND_EKS_MESSAGE_ID:
+		if (handle->repeater_flag) {
+			/* poll for link check */
+			cdata.cmd = HDCP_WKUP_CMD_LINK_POLL;
+		} else {
+			memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
+			handle->listener_buf[0] = SKE_SEND_TYPE_ID;
+			handle->msglen = 2;
+			cdata.cmd = HDCP_WKUP_CMD_SEND_MESSAGE;
+			cdata.send_msg_buf = handle->listener_buf;
+			cdata.send_msg_len = handle->msglen;
+			handle->last_msg = hdcp_lib_get_next_message(handle,
+						&cdata);
+		}
+		break;
+	case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
+		pr_debug("Repeater authentication successful\n");
+
+		if (handle->update_stream) {
+			HDCP_LIB_EXECUTE(stream);
+			handle->update_stream = false;
+		} else {
+			cdata.cmd = HDCP_WKUP_CMD_LINK_POLL;
+		}
+		break;
+	default:
+		cdata.cmd = HDCP_WKUP_CMD_RECV_MESSAGE;
+		cdata.timeout = handle->timeout_left;
+	}
+
+	hdcp_lib_wakeup_client(handle, &cdata);
+}
+
+static void hdcp_lib_msg_sent_work(struct kthread_work *work)
+{
+	struct hdcp_lib_handle *handle = container_of(work,
+						      struct hdcp_lib_handle,
+						      wk_msg_sent);
+
+	if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) {
+		pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
+		return;
+	}
+
+	hdcp_lib_msg_sent(handle);
+}
+
+static void hdcp_lib_init(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+
+	if (!handle) {
+		pr_err("invalid handle\n");
+		return;
+	}
+
+	if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_START) {
+		pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
+		return;
+	}
+
+	rc = hdcp_lib_library_load(handle);
+	if (rc)
+		goto exit;
+
+	rc = hdcp_lib_session_init(handle);
+	if (rc)
+		goto exit;
+
+	if (handle->hdcp_txmtr_init == NULL) {
+		pr_err("invalid txmtr init function pointer\n");
+		return;
+	}
+
+	rc = handle->hdcp_txmtr_init(handle);
+	if (rc)
+		goto exit;
+
+	rc = hdcp_lib_start_auth(handle);
+	if (rc)
+		goto exit;
+
+	hdcp_lib_send_message(handle);
+
+	return;
+exit:
+	HDCP_LIB_EXECUTE(clean);
+}
+
+static void hdcp_lib_init_work(struct kthread_work *work)
+{
+	struct hdcp_lib_handle *handle = container_of(work,
+						      struct hdcp_lib_handle,
+						      wk_init);
+
+	hdcp_lib_init(handle);
+}
+
+static void hdcp_lib_timeout(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_send_timeout_req *req_buf;
+	struct hdcp_send_timeout_rsp *rsp_buf;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_debug("invalid handle\n");
+		return;
+	}
+
+	if (atomic_read(&handle->hdcp_off)) {
+		pr_debug("invalid state, hdcp off\n");
+		return;
+	}
+
+	req_buf = (struct hdcp_send_timeout_req *)
+	    (handle->qseecom_handle->sbuf);
+	req_buf->commandid = HDCP_TXMTR_SEND_MESSAGE_TIMEOUT;
+	req_buf->ctxhandle = handle->tz_ctxhandle;
+
+	rsp_buf = (struct hdcp_send_timeout_rsp *)
+	    (handle->qseecom_handle->sbuf +
+	    QSEECOM_ALIGN(sizeof(struct hdcp_send_timeout_req)));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_send_timeout_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct
+						 hdcp_send_timeout_rsp)));
+
+	if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS)) {
+		pr_err("qseecom cmd failed for with err = %d status = %d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (rsp_buf->commandid == HDCP_TXMTR_SEND_MESSAGE_TIMEOUT) {
+		pr_err("HDCP_TXMTR_SEND_MESSAGE_TIMEOUT\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	/*
+	 * if the response contains LC_Init message
+	 * send the message again to TZ
+	 */
+	if ((rsp_buf->commandid == HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) &&
+	    ((int)rsp_buf->message[0] == LC_INIT_MESSAGE_ID) &&
+	    (rsp_buf->msglen == LC_INIT_MESSAGE_SIZE)) {
+		if (!atomic_read(&handle->hdcp_off)) {
+			/* keep local copy of TZ response */
+			memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
+			memcpy(handle->listener_buf,
+			       (unsigned char *)rsp_buf->message,
+			       rsp_buf->msglen);
+			handle->hdcp_timeout = rsp_buf->timeout;
+			handle->msglen = rsp_buf->msglen;
+
+			hdcp_lib_send_message(handle);
+		}
+	}
+
+	return;
+error:
+	if (!atomic_read(&handle->hdcp_off))
+		HDCP_LIB_EXECUTE(clean);
+}
+
+static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
+{
+	struct hdcp_lib_handle *handle = container_of(work,
+						      struct hdcp_lib_handle,
+						      wk_timeout);
+
+	hdcp_lib_timeout(handle);
+}
+
+static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
+{
+	struct hdcp_wakeup_data cdata = { HDCP_WKUP_CMD_INVALID };
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	handle->authenticated = false;
+
+	hdcp_lib_txmtr_deinit(handle);
+	hdcp_lib_session_deinit(handle);
+	hdcp_lib_library_unload(handle);
+
+	cdata.context = handle->client_ctx;
+	cdata.cmd = HDCP_WKUP_CMD_STATUS_FAILED;
+
+	if (!atomic_read(&handle->hdcp_off))
+		hdcp_lib_wakeup_client(handle, &cdata);
+
+	atomic_set(&handle->hdcp_off, 1);
+}
+
+static void hdcp_lib_cleanup_work(struct kthread_work *work)
+{
+
+	struct hdcp_lib_handle *handle = container_of(work,
+						      struct hdcp_lib_handle,
+						      wk_clean);
+
+	hdcp_lib_clean(handle);
+}
+
+static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
+{
+	int rc = 0;
+	struct hdcp_wakeup_data cdata = { HDCP_WKUP_CMD_INVALID };
+	struct hdcp_rcvd_msg_req *req_buf;
+	struct hdcp_rcvd_msg_rsp *rsp_buf;
+	uint32_t msglen;
+	char *msg = NULL;
+	char msg_name[50];
+	uint32_t message_id_bytes = 0;
+
+	if (!handle || !handle->qseecom_handle ||
+	    !handle->qseecom_handle->sbuf) {
+		pr_err("invalid handle\n");
+		return;
+	}
+
+	if (atomic_read(&handle->hdcp_off)) {
+		pr_debug("invalid state, hdcp off\n");
+		return;
+	}
+
+	cdata.context = handle->client_ctx;
+
+	mutex_lock(&handle->msg_lock);
+	msglen = handle->last_msg_recvd_len;
+
+	if (msglen <= 0) {
+		pr_err("invalid msg len\n");
+		mutex_unlock(&handle->msg_lock);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/* If the client is DP then allocate extra byte for message ID. */
+	if (handle->device_type == HDCP_TXMTR_DP)
+		message_id_bytes = 1;
+
+	msglen += message_id_bytes;
+
+	msg = kzalloc(msglen, GFP_KERNEL);
+	if (!msg) {
+		mutex_unlock(&handle->msg_lock);
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	/* copy the message id if needed */
+	if (message_id_bytes)
+		memcpy(msg, &handle->last_msg, message_id_bytes);
+
+	memcpy(msg + message_id_bytes,
+		handle->last_msg_recvd_buf,
+		handle->last_msg_recvd_len);
+
+	mutex_unlock(&handle->msg_lock);
+
+	snprintf(msg_name, sizeof(msg_name), "%s: ",
+		hdcp_lib_message_name((int)msg[0]));
+
+	print_hex_dump(KERN_DEBUG, msg_name,
+		DUMP_PREFIX_NONE, 16, 1, msg, msglen, false);
+
+	/* send the message to QSEECOM */
+	req_buf = (struct hdcp_rcvd_msg_req *)(handle->qseecom_handle->sbuf);
+	req_buf->commandid = HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE;
+	memcpy(req_buf->msg, msg, msglen);
+	req_buf->msglen = msglen;
+	req_buf->ctxhandle = handle->tz_ctxhandle;
+
+	rsp_buf =
+	    (struct hdcp_rcvd_msg_rsp *)(handle->qseecom_handle->sbuf +
+					 QSEECOM_ALIGN(sizeof
+						       (struct
+							hdcp_rcvd_msg_req)));
+
+	pr_debug("writing %s to TZ at %dms\n",
+		 hdcp_lib_message_name((int)msg[0]), jiffies_to_msecs(jiffies));
+
+	rc = qseecom_send_command(handle->qseecom_handle, req_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_rcvd_msg_req)),
+				  rsp_buf,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp_rcvd_msg_rsp)));
+
+	/* get next message from sink if we receive H PRIME on no store km */
+	if ((msg[0] == AKE_SEND_H_PRIME_MESSAGE_ID) &&
+	    handle->no_stored_km_flag) {
+		handle->hdcp_timeout = rsp_buf->timeout;
+
+		cdata.cmd = HDCP_WKUP_CMD_RECV_MESSAGE;
+		cdata.timeout = handle->hdcp_timeout;
+
+		goto exit;
+	}
+
+	if ((msg[0] == REPEATER_AUTH_STREAM_READY_MESSAGE_ID) &&
+	    (rc == 0) && (rsp_buf->status == 0)) {
+		pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n");
+
+		if (!handle->authenticated &&
+		    !hdcp_lib_enable_encryption(handle)) {
+			handle->authenticated = true;
+
+			cdata.cmd = HDCP_WKUP_CMD_STATUS_SUCCESS;
+			hdcp_lib_wakeup_client(handle, &cdata);
+		}
+
+		cdata.cmd = HDCP_WKUP_CMD_LINK_POLL;
+		goto exit;
+	}
+
+	if ((rc < 0) || (rsp_buf->status != 0) || (rsp_buf->msglen <= 0) ||
+	    (rsp_buf->commandid != HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) ||
+	    (rsp_buf->msg == NULL)) {
+		pr_err("qseecom cmd failed with err=%d status=%d\n",
+		       rc, rsp_buf->status);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	pr_debug("recvd %s from TZ at %dms\n",
+		 hdcp_lib_message_name((int)rsp_buf->msg[0]),
+		 jiffies_to_msecs(jiffies));
+
+	handle->last_msg = (int)rsp_buf->msg[0];
+
+	/* set the flag if response is AKE_No_Stored_km */
+	if (((int)rsp_buf->msg[0] == AKE_NO_STORED_KM_MESSAGE_ID)) {
+		pr_debug("Setting no_stored_km_flag\n");
+		handle->no_stored_km_flag = 1;
+	} else {
+		handle->no_stored_km_flag = 0;
+	}
+
+	/* check if it's a repeater */
+	if ((rsp_buf->msg[0] == SKE_SEND_EKS_MESSAGE_ID) &&
+	    (rsp_buf->msglen == SKE_SEND_EKS_MESSAGE_SIZE)) {
+		if ((rsp_buf->flag ==
+		     HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST) &&
+		    (rsp_buf->timeout > 0))
+			handle->repeater_flag = true;
+		handle->update_stream = true;
+	}
+
+	memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
+	memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg,
+	       rsp_buf->msglen);
+	handle->hdcp_timeout = rsp_buf->timeout;
+	handle->msglen = rsp_buf->msglen;
+
+	if (!atomic_read(&handle->hdcp_off))
+		hdcp_lib_send_message(handle);
+exit:
+	kzfree(msg);
+
+	hdcp_lib_wakeup_client(handle, &cdata);
+
+	if (rc && !atomic_read(&handle->hdcp_off))
+		HDCP_LIB_EXECUTE(clean);
+}
+
+static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
+{
+	struct hdcp_lib_handle *handle = container_of(work,
+						      struct hdcp_lib_handle,
+						      wk_msg_recvd);
+
+	hdcp_lib_msg_recvd(handle);
+}
+
+static void hdcp_lib_wait_work(struct kthread_work *work)
+{
+	u32 timeout;
+	struct hdcp_lib_handle *handle = container_of(work,
+				struct hdcp_lib_handle, wk_wait);
+
+	if (!handle) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (atomic_read(&handle->hdcp_off)) {
+		pr_debug("invalid state: hdcp off\n");
+		return;
+	}
+
+	if (handle->hdcp_state & HDCP_STATE_ERROR) {
+		pr_debug("invalid state: hdcp error\n");
+		return;
+	}
+
+	reinit_completion(&handle->poll_wait);
+	timeout = wait_for_completion_timeout(&handle->poll_wait,
+			handle->wait_timeout);
+	if (!timeout) {
+		pr_err("wait timeout\n");
+
+		if (!atomic_read(&handle->hdcp_off))
+			HDCP_LIB_EXECUTE(clean);
+	}
+
+	handle->wait_timeout = 0;
+}
+
+bool hdcp1_check_if_supported_load_app(void)
+{
+	int rc = 0;
+
+	/* start hdcp1 app */
+	if (hdcp1_supported && !hdcp1_handle) {
+		rc = qseecom_start_app(&hdcp1_handle, HDCP1_APP_NAME,
+				       QSEECOM_SBUFF_SIZE);
+		if (rc) {
+			pr_err("qseecom_start_app failed %d\n", rc);
+			hdcp1_supported = false;
+		} else {
+			mutex_init(&hdcp1_ta_cmd_lock);
+		}
+	}
+
+	pr_debug("hdcp1 app %s loaded\n",
+		 hdcp1_supported ? "successfully" : "not");
+
+	return hdcp1_supported;
+}
+
+/* APIs exposed to all clients */
+int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
+{
+	int rc = 0;
+	struct hdcp1_key_set_req *key_set_req;
+	struct hdcp1_key_set_rsp *key_set_rsp;
+
+	if (aksv_msb == NULL || aksv_lsb == NULL)
+		return -EINVAL;
+
+	if (!hdcp1_supported || !hdcp1_handle)
+		return -EINVAL;
+
+	/* set keys and request aksv */
+	key_set_req = (struct hdcp1_key_set_req *)hdcp1_handle->sbuf;
+	key_set_req->commandid = HDCP1_SET_KEY_MESSAGE_ID;
+	key_set_rsp = (struct hdcp1_key_set_rsp *)(hdcp1_handle->sbuf +
+			   QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_req)));
+	rc = qseecom_send_command(hdcp1_handle, key_set_req,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp1_key_set_req)),
+				  key_set_rsp,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp1_key_set_rsp)));
+
+	if (rc < 0) {
+		pr_err("qseecom cmd failed err=%d\n", rc);
+		return -ENOKEY;
+	}
+
+	rc = key_set_rsp->ret;
+	if (rc) {
+		pr_err("set key cmd failed, rsp=%d\n", key_set_rsp->ret);
+		return -ENOKEY;
+	}
+
+	/* copy bytes into msb and lsb */
+	*aksv_msb = key_set_rsp->ksv[0] << 24;
+	*aksv_msb |= key_set_rsp->ksv[1] << 16;
+	*aksv_msb |= key_set_rsp->ksv[2] << 8;
+	*aksv_msb |= key_set_rsp->ksv[3];
+	*aksv_lsb = key_set_rsp->ksv[4] << 24;
+	*aksv_lsb |= key_set_rsp->ksv[5] << 16;
+	*aksv_lsb |= key_set_rsp->ksv[6] << 8;
+	*aksv_lsb |= key_set_rsp->ksv[7];
+
+	return 0;
+}
+
+int hdcp1_set_enc(bool enable)
+{
+	int rc = 0;
+	struct hdcp1_set_enc_req *set_enc_req;
+	struct hdcp1_set_enc_rsp *set_enc_rsp;
+
+	mutex_lock(&hdcp1_ta_cmd_lock);
+
+	if (!hdcp1_supported || !hdcp1_handle) {
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (hdcp1_enc_enabled == enable) {
+		pr_info("already %s\n", enable ? "enabled" : "disabled");
+		goto end;
+	}
+
+	/* set keys and request aksv */
+	set_enc_req = (struct hdcp1_set_enc_req *)hdcp1_handle->sbuf;
+	set_enc_req->commandid = HDCP1_SET_ENC_MESSAGE_ID;
+	set_enc_req->enable = enable;
+	set_enc_rsp = (struct hdcp1_set_enc_rsp *)(hdcp1_handle->sbuf +
+			QSEECOM_ALIGN(sizeof(struct hdcp1_set_enc_req)));
+	rc = qseecom_send_command(hdcp1_handle, set_enc_req,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp1_set_enc_req)),
+				  set_enc_rsp,
+				  QSEECOM_ALIGN(sizeof
+						(struct hdcp1_set_enc_rsp)));
+
+	if (rc < 0) {
+		pr_err("qseecom cmd failed err=%d\n", rc);
+		goto end;
+	}
+
+	rc = set_enc_rsp->ret;
+	if (rc) {
+		pr_err("enc cmd failed, rsp=%d\n", set_enc_rsp->ret);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	hdcp1_enc_enabled = enable;
+	pr_info("%s success\n", enable ? "enable" : "disable");
+end:
+	mutex_unlock(&hdcp1_ta_cmd_lock);
+	return rc;
+}
+
+int hdcp_library_register(struct hdcp_register_data *data)
+{
+	int rc = 0;
+	struct hdcp_lib_handle *handle = NULL;
+
+	if (!data) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	if (!data->txmtr_ops) {
+		pr_err("invalid input: txmtr context\n");
+		return -EINVAL;
+	}
+
+	if (!data->client_ops) {
+		pr_err("invalid input: client_ops\n");
+		return -EINVAL;
+	}
+
+	if (!data->hdcp_ctx) {
+		pr_err("invalid input: hdcp_ctx\n");
+		return -EINVAL;
+	}
+
+	/* populate ops to be called by client */
+	data->txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
+	data->txmtr_ops->wakeup = hdcp_lib_wakeup_thread;
+
+	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+	if (!handle) {
+		rc = -ENOMEM;
+		goto unlock;
+	}
+
+	handle->client_ctx = data->client_ctx;
+	handle->client_ops = data->client_ops;
+	handle->hdcp_app_init = NULL;
+	handle->hdcp_txmtr_init = NULL;
+	handle->device_type = data->device_type;
+
+	atomic_set(&handle->hdcp_off, 0);
+
+	mutex_init(&handle->msg_lock);
+	mutex_init(&handle->wakeup_mutex);
+
+	kthread_init_worker(&handle->worker);
+
+	kthread_init_work(&handle->wk_init, hdcp_lib_init_work);
+	kthread_init_work(&handle->wk_msg_sent, hdcp_lib_msg_sent_work);
+	kthread_init_work(&handle->wk_msg_recvd, hdcp_lib_msg_recvd_work);
+	kthread_init_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work);
+	kthread_init_work(&handle->wk_clean, hdcp_lib_cleanup_work);
+	kthread_init_work(&handle->wk_wait, hdcp_lib_wait_work);
+	kthread_init_work(&handle->wk_stream, hdcp_lib_query_stream_work);
+
+	init_completion(&handle->poll_wait);
+
+	handle->listener_buf = kzalloc(MAX_TX_MESSAGE_SIZE, GFP_KERNEL);
+	if (!(handle->listener_buf)) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	*data->hdcp_ctx = handle;
+	/* Cache the client ctx to be used later
+	 * HDCP driver probe happens earlier than
+	 * SDE driver probe hence caching it to
+	 * be used later.
+	 */
+
+	drv_client_handle = handle;
+	handle->thread = kthread_run(kthread_worker_fn,
+				     &handle->worker, "hdcp_tz_lib");
+
+	if (IS_ERR(handle->thread)) {
+		pr_err("unable to start lib thread\n");
+		rc = PTR_ERR(handle->thread);
+		handle->thread = NULL;
+		goto error;
+	}
+
+	return 0;
+error:
+	kzfree(handle->listener_buf);
+	handle->listener_buf = NULL;
+	kzfree(handle);
+	handle = NULL;
+unlock:
+	return rc;
+}
+EXPORT_SYMBOL(hdcp_library_register);
+
+void hdcp_library_deregister(void *phdcpcontext)
+{
+	struct hdcp_lib_handle *handle = phdcpcontext;
+
+	if (!handle)
+		return;
+
+	kthread_stop(handle->thread);
+
+	kzfree(handle->qseecom_handle);
+	kzfree(handle->last_msg_recvd_buf);
+
+	mutex_destroy(&handle->wakeup_mutex);
+
+	kzfree(handle->listener_buf);
+	kzfree(handle);
+}
+EXPORT_SYMBOL(hdcp_library_deregister);
+
+void hdcp1_notify_topology(void)
+{
+	char *envp[4];
+	char *a;
+	char *b;
+
+	if (!hdcp_drv_mgr) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	a = kzalloc(SZ_16, GFP_KERNEL);
+
+	if (!a)
+		return;
+
+	b = kzalloc(SZ_16, GFP_KERNEL);
+
+	if (!b) {
+		kfree(a);
+		return;
+	}
+
+	envp[0] = "HDCP_MGR_EVENT=MSG_READY";
+	envp[1] = a;
+	envp[2] = b;
+	envp[3] = NULL;
+
+	snprintf(envp[1], 16, "%d", (int)DOWN_CHECK_TOPOLOGY);
+	snprintf(envp[2], 16, "%d", (int)HDCP_V1_TX);
+
+	kobject_uevent_env(&hdcp_drv_mgr->device->kobj, KOBJ_CHANGE, envp);
+	kfree(a);
+	kfree(b);
+}
+
+static ssize_t msm_hdcp_1x_sysfs_rda_tp(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+
+	if (!hdcp_drv_mgr) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	switch (hdcp_drv_mgr->tp_msgid) {
+	case DOWN_CHECK_TOPOLOGY:
+	case DOWN_REQUEST_TOPOLOGY:
+		buf[MSG_ID_IDX]   = hdcp_drv_mgr->tp_msgid;
+		buf[RET_CODE_IDX] = HDCP_AUTHED;
+		ret = HEADER_LEN;
+
+		memcpy(buf + HEADER_LEN, &hdcp_drv_mgr->cached_tp,
+			   sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
+
+		ret += sizeof(struct HDCP_V2V1_MSG_TOPOLOGY);
+
+		/* clear the flag once data is read back to user space*/
+		hdcp_drv_mgr->tp_msgid = -1;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static ssize_t msm_hdcp_1x_sysfs_wta_tp(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int msgid = 0;
+	ssize_t ret = count;
+
+	if (!hdcp_drv_mgr || !buf) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	msgid = buf[0];
+
+	switch (msgid) {
+	case DOWN_CHECK_TOPOLOGY:
+	case DOWN_REQUEST_TOPOLOGY:
+		hdcp_drv_mgr->tp_msgid = msgid;
+		break;
+		/* more cases added here */
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static ssize_t hdcp2p2_sysfs_wta_min_level_change(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc;
+	int min_enc_lvl;
+	struct hdcp_lib_handle *handle;
+	ssize_t ret = count;
+
+	if (!hdcp_drv_mgr) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	handle = hdcp_drv_mgr->handle;
+
+	rc = kstrtoint(buf, 10, &min_enc_lvl);
+	if (rc) {
+		pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		return -EINVAL;
+	}
+
+	if (handle && handle->client_ops->notify_lvl_change) {
+		handle->client_ops->notify_lvl_change(handle->client_ctx,
+		min_enc_lvl);
+	}
+
+	return ret;
+}
+
+static DEVICE_ATTR(tp, 0644, msm_hdcp_1x_sysfs_rda_tp,
+	msm_hdcp_1x_sysfs_wta_tp);
+
+static DEVICE_ATTR(min_level_change, 0200, NULL,
+	hdcp2p2_sysfs_wta_min_level_change);
+
+void hdcp1_cache_repeater_topology(void *hdcp1_cached_tp)
+{
+	if (!hdcp_drv_mgr) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	memcpy((void *)&hdcp_drv_mgr->cached_tp,
+		   hdcp1_cached_tp,
+		   sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
+}
+
+static struct attribute *msm_hdcp_fs_attrs[] = {
+	&dev_attr_tp.attr,
+	&dev_attr_min_level_change.attr,
+	NULL
+};
+
+static struct attribute_group msm_hdcp_fs_attr_group = {
+	.attrs = msm_hdcp_fs_attrs
+};
+
+static int msm_hdcp_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int msm_hdcp_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations msm_hdcp_fops = {
+	.owner = THIS_MODULE,
+	.open = msm_hdcp_open,
+	.release = msm_hdcp_close,
+};
+
+static const struct of_device_id msm_hdcp_dt_match[] = {
+	{ .compatible = "qcom,msm-hdcp",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_hdcp_dt_match);
+
+static int msm_hdcp_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	hdcp_drv_mgr = devm_kzalloc(&pdev->dev, sizeof(struct msm_hdcp_mgr),
+						   GFP_KERNEL);
+	if (!hdcp_drv_mgr)
+		return -ENOMEM;
+
+	hdcp_drv_mgr->pdev = pdev;
+
+	platform_set_drvdata(pdev, hdcp_drv_mgr);
+
+	ret = alloc_chrdev_region(&hdcp_drv_mgr->dev_num, 0, 1, DRIVER_NAME);
+	if (ret  < 0) {
+		pr_err("alloc_chrdev_region failed ret = %d\n", ret);
+		goto error_get_dev_num;
+	}
+
+	hdcp_drv_mgr->class = class_create(THIS_MODULE, CLASS_NAME);
+	if (IS_ERR(hdcp_drv_mgr->class)) {
+		ret = PTR_ERR(hdcp_drv_mgr->class);
+		pr_err("couldn't create class rc = %d\n", ret);
+		goto error_class_create;
+	}
+
+	hdcp_drv_mgr->device = device_create(hdcp_drv_mgr->class, NULL,
+		hdcp_drv_mgr->dev_num, NULL, DRIVER_NAME);
+	if (IS_ERR(hdcp_drv_mgr->device)) {
+		ret = PTR_ERR(hdcp_drv_mgr->device);
+		pr_err("device_create failed %d\n", ret);
+		goto error_class_device_create;
+	}
+
+	cdev_init(&hdcp_drv_mgr->cdev, &msm_hdcp_fops);
+	ret = cdev_add(&hdcp_drv_mgr->cdev,
+			MKDEV(MAJOR(hdcp_drv_mgr->dev_num), 0), 1);
+	if (ret < 0) {
+		pr_err("cdev_add failed %d\n", ret);
+		goto error_cdev_add;
+	}
+
+	ret = sysfs_create_group(&hdcp_drv_mgr->device->kobj,
+			&msm_hdcp_fs_attr_group);
+	if (ret)
+		pr_err("unable to register rotator sysfs nodes\n");
+
+	/* Store the handle in the hdcp drv mgr
+	 * to be used for the sysfs notifications
+	 */
+	hdcp_drv_mgr->handle = drv_client_handle;
+
+	return 0;
+error_cdev_add:
+	device_destroy(hdcp_drv_mgr->class, hdcp_drv_mgr->dev_num);
+error_class_device_create:
+	class_destroy(hdcp_drv_mgr->class);
+error_class_create:
+	unregister_chrdev_region(hdcp_drv_mgr->dev_num, 1);
+error_get_dev_num:
+	devm_kfree(&pdev->dev, hdcp_drv_mgr);
+	hdcp_drv_mgr = NULL;
+	return ret;
+}
+
+static int msm_hdcp_remove(struct platform_device *pdev)
+{
+	struct msm_hdcp_mgr *mgr;
+
+	mgr = (struct msm_hdcp_mgr *)platform_get_drvdata(pdev);
+	if (!mgr)
+		return -ENODEV;
+
+	sysfs_remove_group(&hdcp_drv_mgr->device->kobj,
+	&msm_hdcp_fs_attr_group);
+	cdev_del(&hdcp_drv_mgr->cdev);
+	device_destroy(hdcp_drv_mgr->class, hdcp_drv_mgr->dev_num);
+	class_destroy(hdcp_drv_mgr->class);
+	unregister_chrdev_region(hdcp_drv_mgr->dev_num, 1);
+
+	devm_kfree(&pdev->dev, hdcp_drv_mgr);
+	hdcp_drv_mgr = NULL;
+	return 0;
+}
+
+static struct platform_driver msm_hdcp_driver = {
+	.probe = msm_hdcp_probe,
+	.remove = msm_hdcp_remove,
+	.driver = {
+		.name = "msm_hdcp",
+		.of_match_table = msm_hdcp_dt_match,
+		.pm = NULL,
+	}
+};
+
+static int __init msm_hdcp_init(void)
+{
+	return platform_driver_register(&msm_hdcp_driver);
+}
+
+static void __exit msm_hdcp_exit(void)
+{
+	return platform_driver_unregister(&msm_hdcp_driver);
+}
+
+module_init(msm_hdcp_init);
+module_exit(msm_hdcp_exit);
+
+MODULE_DESCRIPTION("MSM HDCP driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index fdf954c..cfa1039 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -21,6 +21,8 @@
 void lkdtm_HUNG_TASK(void);
 void lkdtm_ATOMIC_UNDERFLOW(void);
 void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_CORRUPT_LIST_ADD(void);
+void lkdtm_CORRUPT_LIST_DEL(void);
 
 /* lkdtm_heap.c */
 void lkdtm_OVERWRITE_ALLOCATION(void);
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 182ae18..bb3bb8e 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -5,8 +5,13 @@
  * test source files.
  */
 #include "lkdtm.h"
+#include <linux/list.h>
 #include <linux/sched.h>
 
+struct lkdtm_list {
+	struct list_head node;
+};
+
 /*
  * Make sure our attempts to over run the kernel stack doesn't trigger
  * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -75,12 +80,18 @@
 	(void) recursive_loop(recur_count);
 }
 
+static noinline void __lkdtm_CORRUPT_STACK(void *stack)
+{
+	memset(stack, 'a', 64);
+}
+
 noinline void lkdtm_CORRUPT_STACK(void)
 {
 	/* Use default char array length that triggers stack protection. */
 	char data[8];
+	__lkdtm_CORRUPT_STACK(&data);
 
-	memset((void *)data, 0, 64);
+	pr_info("Corrupted stack with '%16s'...\n", data);
 }
 
 void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void)
@@ -146,3 +157,66 @@
 	pr_info("attempting bad atomic overflow\n");
 	atomic_inc(&over);
 }
+
+void lkdtm_CORRUPT_LIST_ADD(void)
+{
+	/*
+	 * Initially, an empty list via LIST_HEAD:
+	 *	test_head.next = &test_head
+	 *	test_head.prev = &test_head
+	 */
+	LIST_HEAD(test_head);
+	struct lkdtm_list good, bad;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	pr_info("attempting good list addition\n");
+
+	/*
+	 * Adding to the list performs these actions:
+	 *	test_head.next->prev = &good.node
+	 *	good.node.next = test_head.next
+	 *	good.node.prev = test_head
+	 *	test_head.next = good.node
+	 */
+	list_add(&good.node, &test_head);
+
+	pr_info("attempting corrupted list addition\n");
+	/*
+	 * In simulating this "write what where" primitive, the "what" is
+	 * the address of &bad.node, and the "where" is the address held
+	 * by "redirection".
+	 */
+	test_head.next = redirection;
+	list_add(&bad.node, &test_head);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_add() corruption not detected!\n");
+}
+
+void lkdtm_CORRUPT_LIST_DEL(void)
+{
+	LIST_HEAD(test_head);
+	struct lkdtm_list item;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	list_add(&item.node, &test_head);
+
+	pr_info("attempting good list removal\n");
+	list_del(&item.node);
+
+	pr_info("attempting corrupted list removal\n");
+	list_add(&item.node, &test_head);
+
+	/* As with the list_add() test above, this corrupts "next". */
+	item.node.next = redirection;
+	list_del(&item.node);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_del() corruption not detected!\n");
+}
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index f9154b8..7eeb71a 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -197,6 +197,8 @@
 	CRASHTYPE(EXCEPTION),
 	CRASHTYPE(LOOP),
 	CRASHTYPE(OVERFLOW),
+	CRASHTYPE(CORRUPT_LIST_ADD),
+	CRASHTYPE(CORRUPT_LIST_DEL),
 	CRASHTYPE(CORRUPT_STACK),
 	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
 	CRASHTYPE(OVERWRITE_ALLOCATION),
diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
index 80f6e57..2f927bd 100644
--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
+++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
@@ -26,11 +26,14 @@
 #include <linux/debugfs.h>
 #include <linux/msm_audio_ion.h>
 #include <linux/compat.h>
+#include <linux/mutex.h>
 #include "audio_utils_aio.h"
 #ifdef CONFIG_USE_DEV_CTRL_VOLUME
 #include <linux/qdsp6v2/audio_dev_ctl.h>
 #endif /*CONFIG_USE_DEV_CTRL_VOLUME*/
+static DEFINE_MUTEX(lock);
 #ifdef CONFIG_DEBUG_FS
+
 int audio_aio_debug_open(struct inode *inode, struct file *file)
 {
 	file->private_data = inode->i_private;
@@ -43,29 +46,37 @@
 	const int debug_bufmax = 4096;
 	static char buffer[4096];
 	int n = 0;
-	struct q6audio_aio *audio = file->private_data;
+	struct q6audio_aio *audio;
 
-	mutex_lock(&audio->lock);
-	n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"enabled %d\n", audio->enabled);
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"stopped %d\n", audio->stopped);
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"feedback %d\n", audio->feedback);
-	mutex_unlock(&audio->lock);
-	/* Following variables are only useful for debugging when
-	 * when playback halts unexpectedly. Thus, no mutual exclusion
-	 * enforced
-	 */
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"wflush %d\n", audio->wflush);
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"rflush %d\n", audio->rflush);
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"inqueue empty %d\n", list_empty(&audio->in_queue));
-	n += scnprintf(buffer + n, debug_bufmax - n,
-			"outqueue empty %d\n", list_empty(&audio->out_queue));
+	mutex_lock(&lock);
+	if (file->private_data != NULL) {
+		audio = file->private_data;
+		mutex_lock(&audio->lock);
+		n = scnprintf(buffer, debug_bufmax, "opened %d\n",
+				audio->opened);
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"enabled %d\n", audio->enabled);
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"stopped %d\n", audio->stopped);
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"feedback %d\n", audio->feedback);
+		mutex_unlock(&audio->lock);
+		/* Following variables are only useful for debugging when
+		 * when playback halts unexpectedly. Thus, no mutual exclusion
+		 * enforced
+		 */
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"wflush %d\n", audio->wflush);
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"rflush %d\n", audio->rflush);
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"inqueue empty %d\n",
+				list_empty(&audio->in_queue));
+		n += scnprintf(buffer + n, debug_bufmax - n,
+				"outqueue empty %d\n",
+				list_empty(&audio->out_queue));
+	}
+	mutex_unlock(&lock);
 	buffer[n] = 0;
 	return simple_read_from_buffer(buf, count, ppos, buffer, n);
 }
@@ -580,6 +591,7 @@
 	struct q6audio_aio *audio = file->private_data;
 
 	pr_debug("%s[%pK]\n", __func__, audio);
+	mutex_lock(&lock);
 	mutex_lock(&audio->lock);
 	mutex_lock(&audio->read_lock);
 	mutex_lock(&audio->write_lock);
@@ -622,6 +634,8 @@
 #endif
 	kfree(audio->codec_cfg);
 	kfree(audio);
+	file->private_data = NULL;
+	mutex_unlock(&lock);
 	return 0;
 }
 
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c6f3496..120fd54 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -4589,6 +4589,10 @@
 
 	dev_set_drvdata(&card->dev, md);
 
+#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
+	mmc_set_bus_resume_policy(card->host, 1);
+#endif
+
 	if (mmc_add_disk(md))
 		goto out;
 
@@ -4632,6 +4636,9 @@
 	pm_runtime_put_noidle(&card->dev);
 	mmc_blk_remove_req(md);
 	dev_set_drvdata(&card->dev, NULL);
+#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
+	mmc_set_bus_resume_policy(card->host, 0);
+#endif
 }
 
 static int _mmc_blk_suspend(struct mmc_card *card, bool wait)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 0bf89b4..978dd9a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -4472,7 +4472,7 @@
 
 	BUG_ON(host->card);
 
-	mmc_register_extcon(host);
+	mmc_unregister_extcon(host);
 
 	mmc_claim_host(host);
 	mmc_power_off(host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3184dcd..409718b 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2944,6 +2944,7 @@
 		return -EBUSY;
 	}
 
+	MMC_TRACE(host, "%s\n", __func__);
 	err = _mmc_suspend(host, true);
 	if (err)
 		pr_err("%s: error %d doing aggressive suspend\n",
@@ -2962,6 +2963,7 @@
 	int err;
 	ktime_t start = ktime_get();
 
+	MMC_TRACE(host, "%s\n", __func__);
 	err = _mmc_resume(host);
 	if (err && err != -ENOMEDIUM)
 		pr_err("%s: error %d doing runtime resume\n",
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index acc4ae0..d624b48 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -212,6 +212,38 @@
 }
 
 static
+int sdhci_msm_ice_get_cfg(struct sdhci_msm_host *msm_host, struct request *req,
+			unsigned int *bypass, short *key_index)
+{
+	int err = 0;
+	struct ice_data_setting ice_set;
+
+	memset(&ice_set, 0, sizeof(struct ice_data_setting));
+	if (msm_host->ice.vops->config_start) {
+		err = msm_host->ice.vops->config_start(
+						msm_host->ice.pdev,
+						req, &ice_set, false);
+		if (err) {
+			pr_err("%s: ice config failed %d\n",
+					mmc_hostname(msm_host->mmc), err);
+			return err;
+		}
+	}
+	/* if writing data command */
+	if (rq_data_dir(req) == WRITE)
+		*bypass = ice_set.encr_bypass ?
+				SDHCI_MSM_ICE_ENABLE_BYPASS :
+				SDHCI_MSM_ICE_DISABLE_BYPASS;
+	/* if reading data command */
+	else if (rq_data_dir(req) == READ)
+		*bypass = ice_set.decr_bypass ?
+				SDHCI_MSM_ICE_ENABLE_BYPASS :
+				SDHCI_MSM_ICE_DISABLE_BYPASS;
+	*key_index = ice_set.crypto_data.key_index;
+	return err;
+}
+
+static
 void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba,
 			u32 slot, unsigned int bypass, short key_index)
 {
@@ -250,7 +282,7 @@
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	int err = 0;
-	struct ice_data_setting ice_set;
+	short key_index = 0;
 	sector_t lba = 0;
 	unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
 	struct request *req;
@@ -261,41 +293,22 @@
 		return -EINVAL;
 	}
 
-	BUG_ON(!mrq);
-	memset(&ice_set, 0, sizeof(struct ice_data_setting));
+	WARN_ON(!mrq);
+	if (!mrq)
+		return -EINVAL;
 	req = mrq->req;
 	if (req) {
 		lba = req->__sector;
-		if (msm_host->ice.vops->config_start) {
-			err = msm_host->ice.vops->config_start(
-							msm_host->ice.pdev,
-							req, &ice_set, false);
-			if (err) {
-				pr_err("%s: ice config failed %d\n",
-						mmc_hostname(host->mmc), err);
-				return err;
-			}
-		}
-		/* if writing data command */
-		if (rq_data_dir(req) == WRITE)
-			bypass = ice_set.encr_bypass ?
-					SDHCI_MSM_ICE_ENABLE_BYPASS :
-					SDHCI_MSM_ICE_DISABLE_BYPASS;
-		/* if reading data command */
-		else if (rq_data_dir(req) == READ)
-			bypass = ice_set.decr_bypass ?
-					SDHCI_MSM_ICE_ENABLE_BYPASS :
-					SDHCI_MSM_ICE_DISABLE_BYPASS;
-		pr_debug("%s: %s: slot %d encr_bypass %d bypass %d decr_bypass %d key_index %d\n",
+		err = sdhci_msm_ice_get_cfg(msm_host, req, &bypass, &key_index);
+		if (err)
+			return err;
+		pr_debug("%s: %s: slot %d bypass %d key_index %d\n",
 				mmc_hostname(host->mmc),
 				(rq_data_dir(req) == WRITE) ? "WRITE" : "READ",
-				slot, ice_set.encr_bypass, bypass,
-				ice_set.decr_bypass,
-				ice_set.crypto_data.key_index);
+				slot, bypass, key_index);
 	}
 
-	sdhci_msm_ice_update_cfg(host, lba, slot, bypass,
-				ice_set.crypto_data.key_index);
+	sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index);
 	return 0;
 }
 
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index b6c17ec0..1e25b31 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -691,7 +691,7 @@
 		mclk_freq = 5;
 	else if (host->clock <= 187000000)
 		mclk_freq = 6;
-	else if (host->clock <= 200000000)
+	else if (host->clock <= 208000000)
 		mclk_freq = 7;
 
 	writel_relaxed(((readl_relaxed(host->ioaddr +
@@ -2492,15 +2492,31 @@
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	const struct sdhci_msm_offset *msm_host_offset =
 					msm_host->offset;
+	unsigned int irq_flags = 0;
+	struct irq_desc *pwr_irq_desc = irq_to_desc(msm_host->pwr_irq);
 
-	pr_err("%s: PWRCTL_STATUS: 0x%08x | PWRCTL_MASK: 0x%08x | PWRCTL_CTL: 0x%08x\n",
+	if (pwr_irq_desc)
+		irq_flags = ACCESS_PRIVATE(pwr_irq_desc->irq_data.common,
+				state_use_accessors);
+
+	pr_err("%s: PWRCTL_STATUS: 0x%08x | PWRCTL_MASK: 0x%08x | PWRCTL_CTL: 0x%08x, pwr isr state=0x%x\n",
 		mmc_hostname(host->mmc),
 		sdhci_msm_readl_relaxed(host,
 			msm_host_offset->CORE_PWRCTL_STATUS),
 		sdhci_msm_readl_relaxed(host,
 			msm_host_offset->CORE_PWRCTL_MASK),
 		sdhci_msm_readl_relaxed(host,
-			msm_host_offset->CORE_PWRCTL_CTL));
+			msm_host_offset->CORE_PWRCTL_CTL), irq_flags);
+
+	MMC_TRACE(host->mmc,
+		"%s: Sts: 0x%08x | Mask: 0x%08x | Ctrl: 0x%08x, pwr isr state=0x%x\n",
+		__func__,
+		sdhci_msm_readb_relaxed(host,
+			msm_host_offset->CORE_PWRCTL_STATUS),
+		sdhci_msm_readb_relaxed(host,
+			msm_host_offset->CORE_PWRCTL_MASK),
+		sdhci_msm_readb_relaxed(host,
+			msm_host_offset->CORE_PWRCTL_CTL), irq_flags);
 }
 
 static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
@@ -2772,10 +2788,14 @@
 	if (done)
 		init_completion(&msm_host->pwr_irq_completion);
 	else if (!wait_for_completion_timeout(&msm_host->pwr_irq_completion,
-				msecs_to_jiffies(MSM_PWR_IRQ_TIMEOUT_MS)))
+				msecs_to_jiffies(MSM_PWR_IRQ_TIMEOUT_MS))) {
 		__WARN_printf("%s: request(%d) timed out waiting for pwr_irq\n",
 					mmc_hostname(host->mmc), req_type);
-
+		MMC_TRACE(host->mmc,
+			"%s: request(%d) timed out waiting for pwr_irq\n",
+			__func__, req_type);
+		sdhci_msm_dump_pwr_ctrl_regs(host);
+	}
 	pr_debug("%s: %s: request %d done\n", mmc_hostname(host->mmc),
 			__func__, req_type);
 }
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 3eada3b..68e49bb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -245,6 +245,8 @@
 		if (timeout == 0) {
 			pr_err("%s: Reset 0x%x never completed.\n",
 				mmc_hostname(host->mmc), (int)mask);
+			MMC_TRACE(host->mmc, "%s: Reset 0x%x never completed\n",
+					__func__, (int)mask);
 			if ((host->quirks2 & SDHCI_QUIRK2_USE_RESET_WORKAROUND)
 				&& host->ops->reset_workaround) {
 				if (!host->reset_wa_applied) {
@@ -1244,6 +1246,9 @@
 		if (timeout == 0) {
 			pr_err("%s: Controller never released inhibit bit(s).\n",
 			       mmc_hostname(host->mmc));
+			MMC_TRACE(host->mmc,
+			"%s :Controller never released inhibit bit(s)\n",
+			__func__);
 			sdhci_dumpregs(host);
 			cmd->error = -EIO;
 			sdhci_finish_mrq(host, cmd->mrq);
@@ -1302,12 +1307,12 @@
 	if (cmd->data)
 		host->data_start_time = ktime_get();
 	trace_mmc_cmd_rw_start(cmd->opcode, cmd->arg, cmd->flags);
+	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
 	MMC_TRACE(host->mmc,
 		"%s: updated 0x8=0x%08x 0xC=0x%08x 0xE=0x%08x\n", __func__,
 		sdhci_readl(host, SDHCI_ARGUMENT),
 		sdhci_readw(host, SDHCI_TRANSFER_MODE),
 		sdhci_readw(host, SDHCI_COMMAND));
-	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
 }
 EXPORT_SYMBOL_GPL(sdhci_send_command);
 
@@ -1533,6 +1538,8 @@
 		if (timeout == 0) {
 			pr_err("%s: Internal clock never stabilised.\n",
 			       mmc_hostname(host->mmc));
+			MMC_TRACE(host->mmc,
+			"%s: Internal clock never stabilised.\n", __func__);
 			sdhci_dumpregs(host);
 			return;
 		}
@@ -2917,6 +2924,7 @@
 	    (host->cmd && sdhci_data_line_cmd(host->cmd))) {
 		pr_err("%s: Timeout waiting for hardware interrupt.\n",
 		       mmc_hostname(host->mmc));
+		MMC_TRACE(host->mmc, "Timeout waiting for h/w interrupt\n");
 		sdhci_dumpregs(host);
 
 		if (host->data) {
@@ -2959,6 +2967,9 @@
 			return;
 		pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
 		       mmc_hostname(host->mmc), (unsigned)intmask);
+		MMC_TRACE(host->mmc,
+		"Got command interrupt 0x%08x even though no command operation was in progress.\n",
+		(unsigned int)intmask);
 		sdhci_dumpregs(host);
 		return;
 	}
@@ -3111,6 +3122,9 @@
 
 		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
 		       mmc_hostname(host->mmc), (unsigned)intmask);
+		MMC_TRACE(host->mmc,
+		"Got data interrupt 0x%08x even though no data operation was in progress.\n",
+		(unsigned int)intmask);
 		sdhci_dumpregs(host);
 
 		return;
@@ -3146,6 +3160,11 @@
 			       mmc_hostname(host->mmc), intmask,
 			       host->data->error, ktime_to_ms(ktime_sub(
 			       ktime_get(), host->data_start_time)));
+			MMC_TRACE(host->mmc,
+				"data txfr (0x%08x) error: %d after %lld ms\n",
+				intmask, host->data->error,
+				ktime_to_ms(ktime_sub(ktime_get(),
+				host->data_start_time)));
 
 			if (!host->mmc->sdr104_wa ||
 			    (host->mmc->ios.timing != MMC_TIMING_UHS_SDR104))
@@ -3399,6 +3418,8 @@
 	if (unexpected) {
 		pr_err("%s: Unexpected interrupt 0x%08x.\n",
 			   mmc_hostname(host->mmc), unexpected);
+		MMC_TRACE(host->mmc, "Unexpected interrupt 0x%08x.\n",
+				unexpected);
 		sdhci_dumpregs(host);
 	}
 
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
index 380a641..258bc8d 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -230,7 +230,7 @@
 	/* Wait for 100ms as Octeon resets. */
 	mdelay(100);
 
-	if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1) == 0x1234ULL) {
+	if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1)) {
 		dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Soft reset failed\n",
 			oct->octeon_id);
 		return 1;
diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
index e779af8..cda32d5 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
@@ -48,7 +48,7 @@
 	/* Wait for 10ms as Octeon resets. */
 	mdelay(100);
 
-	if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1) == 0x1234ULL) {
+	if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1)) {
 		dev_err(&oct->pci_dev->dev, "Soft reset failed\n");
 		return 1;
 	}
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index a61447f..1264a36 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -246,6 +246,7 @@
 			E1000_STATUS_FUNC_SHIFT;
 
 	/* Set phy->phy_addr and phy->id. */
+	igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, 0);
 	ret_val = igb_get_phy_id_82575(hw);
 	if (ret_val)
 		return ret_val;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index ea58234..9d37229 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2671,8 +2671,6 @@
 		PPORT_802_3_GET(pstats, a_frame_check_sequence_errors);
 	stats->rx_frame_errors = PPORT_802_3_GET(pstats, a_alignment_errors);
 	stats->tx_aborted_errors = PPORT_2863_GET(pstats, if_out_discards);
-	stats->tx_carrier_errors =
-		PPORT_802_3_GET(pstats, a_symbol_error_during_carrier);
 	stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
 			   stats->rx_frame_errors;
 	stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 2115c8a..8beecd6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -67,6 +67,7 @@
 
 enum {
 	MLX5_DROP_NEW_HEALTH_WORK,
+	MLX5_DROP_NEW_RECOVERY_WORK,
 };
 
 static u8 get_nic_state(struct mlx5_core_dev *dev)
@@ -193,7 +194,7 @@
 	mlx5_handle_bad_state(dev);
 
 	spin_lock(&health->wq_lock);
-	if (!test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags))
+	if (!test_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags))
 		schedule_delayed_work(&health->recover_work, recover_delay);
 	else
 		dev_err(&dev->pdev->dev,
@@ -328,6 +329,7 @@
 	init_timer(&health->timer);
 	health->sick = 0;
 	clear_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags);
+	clear_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
 	health->health = &dev->iseg->health;
 	health->health_counter = &dev->iseg->health_counter;
 
@@ -350,11 +352,22 @@
 
 	spin_lock(&health->wq_lock);
 	set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags);
+	set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
 	spin_unlock(&health->wq_lock);
 	cancel_delayed_work_sync(&health->recover_work);
 	cancel_work_sync(&health->work);
 }
 
+void mlx5_drain_health_recovery(struct mlx5_core_dev *dev)
+{
+	struct mlx5_core_health *health = &dev->priv.health;
+
+	spin_lock(&health->wq_lock);
+	set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
+	spin_unlock(&health->wq_lock);
+	cancel_delayed_work_sync(&dev->priv.health.recover_work);
+}
+
 void mlx5_health_cleanup(struct mlx5_core_dev *dev)
 {
 	struct mlx5_core_health *health = &dev->priv.health;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 5bea0bf..b3309f2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -1169,7 +1169,7 @@
 	int err = 0;
 
 	if (cleanup)
-		mlx5_drain_health_wq(dev);
+		mlx5_drain_health_recovery(dev);
 
 	mutex_lock(&dev->intf_state_mutex);
 	if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 4ca4613..b1af7cd 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1505,8 +1505,8 @@
 		*index = entry->index;
 		resolved = false;
 	} else if (removing) {
-		ofdpa_neigh_del(trans, found);
 		*index = found->index;
+		ofdpa_neigh_del(trans, found);
 	} else if (updating) {
 		ofdpa_neigh_update(found, trans, NULL, false);
 		resolved = !is_zero_ether_addr(found->eth_dst);
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 00279da..c4ada72 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -4399,12 +4399,9 @@
 	struct efx_ef10_filter_table *table = efx->filter_state;
 	struct net_device *net_dev = efx->net_dev;
 	struct netdev_hw_addr *uc;
-	int addr_count;
 	unsigned int i;
 
-	addr_count = netdev_uc_count(net_dev);
 	table->uc_promisc = !!(net_dev->flags & IFF_PROMISC);
-	table->dev_uc_count = 1 + addr_count;
 	ether_addr_copy(table->dev_uc_list[0].addr, net_dev->dev_addr);
 	i = 1;
 	netdev_for_each_uc_addr(uc, net_dev) {
@@ -4415,6 +4412,8 @@
 		ether_addr_copy(table->dev_uc_list[i].addr, uc->addr);
 		i++;
 	}
+
+	table->dev_uc_count = i;
 }
 
 static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
@@ -4422,11 +4421,10 @@
 	struct efx_ef10_filter_table *table = efx->filter_state;
 	struct net_device *net_dev = efx->net_dev;
 	struct netdev_hw_addr *mc;
-	unsigned int i, addr_count;
+	unsigned int i;
 
 	table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI));
 
-	addr_count = netdev_mc_count(net_dev);
 	i = 0;
 	netdev_for_each_mc_addr(mc, net_dev) {
 		if (i >= EFX_EF10_FILTER_DEV_MC_MAX) {
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 4865221..b88f7d6 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -908,7 +908,7 @@
 	if (overflow) {
 		pr_debug("tx timestamp queue overflow, count %d\n", overflow);
 		while (skb) {
-			skb_complete_tx_timestamp(skb, NULL);
+			kfree_skb(skb);
 			skb = skb_dequeue(&dp83640->tx_queue);
 		}
 		return;
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index fab56c9..2229188 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -622,6 +622,8 @@
 	if ((regval & 0xFF) == 0xFF) {
 		phy_init_hw(phydev);
 		phydev->link = 0;
+		if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
+			phydev->drv->config_intr(phydev);
 	}
 
 	return 0;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 642df93..578bd50 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -787,15 +787,10 @@
 static void vrf_dev_uninit(struct net_device *dev)
 {
 	struct net_vrf *vrf = netdev_priv(dev);
-	struct net_device *port_dev;
-	struct list_head *iter;
 
 	vrf_rtable_release(dev, vrf);
 	vrf_rt6_release(dev, vrf);
 
-	netdev_for_each_lower_dev(dev, port_dev, iter)
-		vrf_del_slave(dev, port_dev);
-
 	free_percpu(dev->dstats);
 	dev->dstats = NULL;
 }
@@ -1232,6 +1227,12 @@
 
 static void vrf_dellink(struct net_device *dev, struct list_head *head)
 {
+	struct net_device *port_dev;
+	struct list_head *iter;
+
+	netdev_for_each_lower_dev(dev, port_dev, iter)
+		vrf_del_slave(dev, port_dev);
+
 	unregister_netdevice_queue(dev, head);
 }
 
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 963e533..983e941 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -227,15 +227,15 @@
 
 static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni)
 {
-	struct vxlan_dev *vxlan;
+	struct vxlan_dev_node *node;
 
 	/* For flow based devices, map all packets to VNI 0 */
 	if (vs->flags & VXLAN_F_COLLECT_METADATA)
 		vni = 0;
 
-	hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) {
-		if (vxlan->default_dst.remote_vni == vni)
-			return vxlan;
+	hlist_for_each_entry_rcu(node, vni_head(vs, vni), hlist) {
+		if (node->vxlan->default_dst.remote_vni == vni)
+			return node->vxlan;
 	}
 
 	return NULL;
@@ -2309,17 +2309,22 @@
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 
 	spin_lock(&vn->sock_lock);
-	hlist_del_init_rcu(&vxlan->hlist);
+	hlist_del_init_rcu(&vxlan->hlist4.hlist);
+#if IS_ENABLED(CONFIG_IPV6)
+	hlist_del_init_rcu(&vxlan->hlist6.hlist);
+#endif
 	spin_unlock(&vn->sock_lock);
 }
 
-static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
+static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan,
+			     struct vxlan_dev_node *node)
 {
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 	__be32 vni = vxlan->default_dst.remote_vni;
 
+	node->vxlan = vxlan;
 	spin_lock(&vn->sock_lock);
-	hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
+	hlist_add_head_rcu(&node->hlist, vni_head(vs, vni));
 	spin_unlock(&vn->sock_lock);
 }
 
@@ -2778,6 +2783,7 @@
 {
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 	struct vxlan_sock *vs = NULL;
+	struct vxlan_dev_node *node;
 
 	if (!vxlan->cfg.no_share) {
 		spin_lock(&vn->sock_lock);
@@ -2795,12 +2801,16 @@
 	if (IS_ERR(vs))
 		return PTR_ERR(vs);
 #if IS_ENABLED(CONFIG_IPV6)
-	if (ipv6)
+	if (ipv6) {
 		rcu_assign_pointer(vxlan->vn6_sock, vs);
-	else
+		node = &vxlan->hlist6;
+	} else
 #endif
+	{
 		rcu_assign_pointer(vxlan->vn4_sock, vs);
-	vxlan_vs_add_dev(vs, vxlan);
+		node = &vxlan->hlist4;
+	}
+	vxlan_vs_add_dev(vs, vxlan, node);
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index ae304355..fe5102c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1821,8 +1821,6 @@
 static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum)
 {
 	REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR);
-	REG_SET_BIT(ah, 0x9864, 0x7f000);
-	REG_SET_BIT(ah, 0x9924, 0x7f00fe);
 	REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
 	REG_WRITE(ah, AR_CR, AR_CR_RXD);
 	REG_WRITE(ah, AR_DLCL_IFS(qnum), 0);
diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
index d38e50f..e0374eb 100644
--- a/drivers/net/wireless/ath/ath9k/rng.c
+++ b/drivers/net/wireless/ath/ath9k/rng.c
@@ -120,6 +120,8 @@
 
 void ath9k_rng_stop(struct ath_softc *sc)
 {
-	if (sc->rng_task)
+	if (sc->rng_task) {
 		kthread_stop(sc->rng_task);
+		sc->rng_task = NULL;
+	}
 }
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index 16aca9e..1fa7f84 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -189,22 +189,27 @@
 	if (strtobool(buf, &start))
 		return -EINVAL;
 
+	mutex_lock(&sc->mutex);
+
 	if (start == sc->tx99_state) {
 		if (!start)
-			return count;
+			goto out;
 		ath_dbg(common, XMIT, "Resetting TX99\n");
 		ath9k_tx99_deinit(sc);
 	}
 
 	if (!start) {
 		ath9k_tx99_deinit(sc);
-		return count;
+		goto out;
 	}
 
 	r = ath9k_tx99_init(sc);
-	if (r)
+	if (r) {
+		mutex_unlock(&sc->mutex);
 		return r;
-
+	}
+out:
+	mutex_unlock(&sc->mutex);
 	return count;
 }
 
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index bb36fe5..70379c8 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -965,6 +965,9 @@
 	wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
 			  len, true);
 
+	if (len < sizeof(struct ieee80211_hdr_3addr))
+		return -EINVAL;
+
 	cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
 	if (!cmd) {
 		rc = -ENOMEM;
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 0ac657d..a0a676b 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -799,8 +799,12 @@
 	struct wireless_dev *wdev = wil_to_wdev(wil);
 	struct cfg80211_mgmt_tx_params params;
 	int rc;
-	void *frame = kmalloc(len, GFP_KERNEL);
+	void *frame;
 
+	if (!len)
+		return -EINVAL;
+
+	frame = kmalloc(len, GFP_KERNEL);
 	if (!frame)
 		return -ENOMEM;
 
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index ae0952f..3028f18 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -592,7 +592,8 @@
 			cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
 					     assoc_req_ie, assoc_req_ielen,
 					     assoc_resp_ie, assoc_resp_ielen,
-					     WLAN_STATUS_SUCCESS, GFP_KERNEL);
+					     WLAN_STATUS_SUCCESS, GFP_KERNEL,
+					     NL80211_TIMEOUT_UNSPECIFIED);
 		}
 		wil->bss = NULL;
 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 72139b5..746f8c9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -705,7 +705,7 @@
 int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
 			   struct sk_buff_head *pktq, uint totlen)
 {
-	struct sk_buff *glom_skb;
+	struct sk_buff *glom_skb = NULL;
 	struct sk_buff *skb;
 	u32 addr = sdiodev->sbwad;
 	int err = 0;
@@ -726,10 +726,8 @@
 			return -ENOMEM;
 		err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
 					 glom_skb);
-		if (err) {
-			brcmu_pkt_buf_free_skb(glom_skb);
+		if (err)
 			goto done;
-		}
 
 		skb_queue_walk(pktq, skb) {
 			memcpy(skb->data, glom_skb->data, skb->len);
@@ -740,6 +738,7 @@
 					    pktq);
 
 done:
+	brcmu_pkt_buf_free_skb(glom_skb);
 	return err;
 }
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 01d44f9..b85398c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -4930,6 +4930,11 @@
 		cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
 					GFP_KERNEL);
 	} else if (ieee80211_is_action(mgmt->frame_control)) {
+		if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {
+			brcmf_err("invalid action frame length\n");
+			err = -EINVAL;
+			goto exit;
+		}
 		af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
 		if (af_params == NULL) {
 			brcmf_err("unable to allocate frame\n");
@@ -6873,7 +6878,7 @@
 	wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
 	if (!wiphy) {
 		brcmf_err("Could not allocate wiphy device\n");
-		return NULL;
+		goto ops_out;
 	}
 	memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
 	set_wiphy_dev(wiphy, busdev);
@@ -7007,6 +7012,7 @@
 	ifp->vif = NULL;
 wiphy_out:
 	brcmf_free_wiphy(wiphy);
+ops_out:
 	kfree(ops);
 	return NULL;
 }
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index f949ad2b..fa3547e 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -70,10 +70,10 @@
 #define WSPI_MAX_CHUNK_SIZE    4092
 
 /*
- * wl18xx driver aggregation buffer size is (13 * PAGE_SIZE) compared to
- * (4 * PAGE_SIZE) for wl12xx, so use the larger buffer needed for wl18xx
+ * wl18xx driver aggregation buffer size is (13 * 4K) compared to
+ * (4 * 4K) for wl12xx, so use the larger buffer needed for wl18xx
  */
-#define SPI_AGGR_BUFFER_SIZE (13 * PAGE_SIZE)
+#define SPI_AGGR_BUFFER_SIZE (13 * SZ_4K)
 
 /* Maximum number of SPI write chunks */
 #define WSPI_MAX_NUM_OF_CHUNKS \
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 599cf50..cd442e4 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -281,6 +281,7 @@
 {
 	RING_IDX req_prod = queue->rx.req_prod_pvt;
 	int notify;
+	int err = 0;
 
 	if (unlikely(!netif_carrier_ok(queue->info->netdev)))
 		return;
@@ -295,8 +296,10 @@
 		struct xen_netif_rx_request *req;
 
 		skb = xennet_alloc_one_rx_buffer(queue);
-		if (!skb)
+		if (!skb) {
+			err = -ENOMEM;
 			break;
+		}
 
 		id = xennet_rxidx(req_prod);
 
@@ -320,8 +323,13 @@
 
 	queue->rx.req_prod_pvt = req_prod;
 
-	/* Not enough requests? Try again later. */
-	if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) {
+	/* Try again later if there are not enough requests or skb allocation
+	 * failed.
+	 * Enough requests is quantified as the sum of newly created slots and
+	 * the unconsumed slots at the backend.
+	 */
+	if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN ||
+	    unlikely(err)) {
 		mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
 		return;
 	}
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c
index f8dcdf4..af62c4c 100644
--- a/drivers/nfc/nfcmrvl/fw_dnld.c
+++ b/drivers/nfc/nfcmrvl/fw_dnld.c
@@ -459,7 +459,7 @@
 
 	INIT_WORK(&priv->fw_dnld.rx_work, fw_dnld_rx_work);
 	snprintf(name, sizeof(name), "%s_nfcmrvl_fw_dnld_rx_wq",
-		 dev_name(priv->dev));
+		 dev_name(&priv->ndev->nfc_dev->dev));
 	priv->fw_dnld.rx_wq = create_singlethread_workqueue(name);
 	if (!priv->fw_dnld.rx_wq)
 		return -ENOMEM;
@@ -496,6 +496,7 @@
 {
 	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
 	struct nfcmrvl_fw_dnld *fw_dnld = &priv->fw_dnld;
+	int res;
 
 	if (!priv->support_fw_dnld)
 		return -ENOTSUPP;
@@ -511,7 +512,9 @@
 	 */
 
 	/* Retrieve FW binary */
-	if (request_firmware(&fw_dnld->fw, firmware_name, priv->dev) < 0) {
+	res = request_firmware(&fw_dnld->fw, firmware_name,
+			       &ndev->nfc_dev->dev);
+	if (res < 0) {
 		nfc_err(priv->dev, "failed to retrieve FW %s", firmware_name);
 		return -ENOENT;
 	}
diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
index 51c8240..a446590 100644
--- a/drivers/nfc/nfcmrvl/main.c
+++ b/drivers/nfc/nfcmrvl/main.c
@@ -124,12 +124,13 @@
 	memcpy(&priv->config, pdata, sizeof(*pdata));
 
 	if (priv->config.reset_n_io) {
-		rc = devm_gpio_request_one(dev,
-					   priv->config.reset_n_io,
-					   GPIOF_OUT_INIT_LOW,
-					   "nfcmrvl_reset_n");
-		if (rc < 0)
+		rc = gpio_request_one(priv->config.reset_n_io,
+				      GPIOF_OUT_INIT_LOW,
+				      "nfcmrvl_reset_n");
+		if (rc < 0) {
+			priv->config.reset_n_io = 0;
 			nfc_err(dev, "failed to request reset_n io\n");
+		}
 	}
 
 	if (phy == NFCMRVL_PHY_SPI) {
@@ -154,32 +155,36 @@
 	if (!priv->ndev) {
 		nfc_err(dev, "nci_allocate_device failed\n");
 		rc = -ENOMEM;
-		goto error;
+		goto error_free_gpio;
 	}
 
-	nci_set_drvdata(priv->ndev, priv);
-
-	rc = nci_register_device(priv->ndev);
-	if (rc) {
-		nfc_err(dev, "nci_register_device failed %d\n", rc);
-		goto error_free_dev;
-	}
-
-	/* Ensure that controller is powered off */
-	nfcmrvl_chip_halt(priv);
-
 	rc = nfcmrvl_fw_dnld_init(priv);
 	if (rc) {
 		nfc_err(dev, "failed to initialize FW download %d\n", rc);
 		goto error_free_dev;
 	}
 
+	nci_set_drvdata(priv->ndev, priv);
+
+	rc = nci_register_device(priv->ndev);
+	if (rc) {
+		nfc_err(dev, "nci_register_device failed %d\n", rc);
+		goto error_fw_dnld_deinit;
+	}
+
+	/* Ensure that controller is powered off */
+	nfcmrvl_chip_halt(priv);
+
 	nfc_info(dev, "registered with nci successfully\n");
 	return priv;
 
+error_fw_dnld_deinit:
+	nfcmrvl_fw_dnld_deinit(priv);
 error_free_dev:
 	nci_free_device(priv->ndev);
-error:
+error_free_gpio:
+	if (priv->config.reset_n_io)
+		gpio_free(priv->config.reset_n_io);
 	kfree(priv);
 	return ERR_PTR(rc);
 }
@@ -195,7 +200,7 @@
 	nfcmrvl_fw_dnld_deinit(priv);
 
 	if (priv->config.reset_n_io)
-		devm_gpio_free(priv->dev, priv->config.reset_n_io);
+		gpio_free(priv->config.reset_n_io);
 
 	nci_unregister_device(ndev);
 	nci_free_device(ndev);
diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c
index 83a99e3..6c0c301 100644
--- a/drivers/nfc/nfcmrvl/uart.c
+++ b/drivers/nfc/nfcmrvl/uart.c
@@ -109,6 +109,7 @@
 	struct nfcmrvl_private *priv;
 	struct nfcmrvl_platform_data *pdata = NULL;
 	struct nfcmrvl_platform_data config;
+	struct device *dev = nu->tty->dev;
 
 	/*
 	 * Platform data cannot be used here since usually it is already used
@@ -116,9 +117,8 @@
 	 * and check if DT entries were added.
 	 */
 
-	if (nu->tty->dev->parent && nu->tty->dev->parent->of_node)
-		if (nfcmrvl_uart_parse_dt(nu->tty->dev->parent->of_node,
-					  &config) == 0)
+	if (dev && dev->parent && dev->parent->of_node)
+		if (nfcmrvl_uart_parse_dt(dev->parent->of_node, &config) == 0)
 			pdata = &config;
 
 	if (!pdata) {
@@ -131,7 +131,7 @@
 	}
 
 	priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_UART, nu, &uart_ops,
-					nu->tty->dev, pdata);
+					dev, pdata);
 	if (IS_ERR(priv))
 		return PTR_ERR(priv);
 
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 368795a..94733f7 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1203,10 +1203,13 @@
 		struct page *page, bool is_write)
 {
 	struct btt *btt = bdev->bd_disk->private_data;
+	int rc;
 
-	btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, is_write, sector);
-	page_endio(page, is_write, 0);
-	return 0;
+	rc = btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, is_write, sector);
+	if (rc == 0)
+		page_endio(page, is_write, 0);
+
+	return rc;
 }
 
 
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index 7ceba08..18a0bea 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -450,14 +450,15 @@
 static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len)
 {
 	const unsigned int sector_size = 512;
-	sector_t start_sector;
+	sector_t start_sector, end_sector;
 	u64 num_sectors;
 	u32 rem;
 
 	start_sector = div_u64(ns_offset, sector_size);
-	num_sectors = div_u64_rem(len, sector_size, &rem);
+	end_sector = div_u64_rem(ns_offset + len, sector_size, &rem);
 	if (rem)
-		num_sectors++;
+		end_sector++;
+	num_sectors = end_sector - start_sector;
 
 	if (unlikely(num_sectors > (u64)INT_MAX)) {
 		u64 remaining = num_sectors;
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 3222f3e..286fda4 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -88,7 +88,7 @@
 
 struct nvme_rdma_queue {
 	struct nvme_rdma_qe	*rsp_ring;
-	u8			sig_count;
+	atomic_t		sig_count;
 	int			queue_size;
 	size_t			cmnd_capsule_len;
 	struct nvme_rdma_ctrl	*ctrl;
@@ -555,6 +555,7 @@
 		queue->cmnd_capsule_len = sizeof(struct nvme_command);
 
 	queue->queue_size = queue_size;
+	atomic_set(&queue->sig_count, 0);
 
 	queue->cm_id = rdma_create_id(&init_net, nvme_rdma_cm_handler, queue,
 			RDMA_PS_TCP, IB_QPT_RC);
@@ -1011,17 +1012,16 @@
 		nvme_rdma_wr_error(cq, wc, "SEND");
 }
 
-static inline int nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue)
+/*
+ * We want to signal completion at least every queue depth/2.  This returns the
+ * largest power of two that is not above half of (queue size + 1) to optimize
+ * (avoid divisions).
+ */
+static inline bool nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue)
 {
-	int sig_limit;
+	int limit = 1 << ilog2((queue->queue_size + 1) / 2);
 
-	/*
-	 * We signal completion every queue depth/2 and also handle the
-	 * degenerated case of a  device with queue_depth=1, where we
-	 * would need to signal every message.
-	 */
-	sig_limit = max(queue->queue_size / 2, 1);
-	return (++queue->sig_count % sig_limit) == 0;
+	return (atomic_inc_return(&queue->sig_count) & (limit - 1)) == 0;
 }
 
 static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 965911d..1b4d93e 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -488,21 +488,24 @@
 
 	rval = device_add(&nvmem->dev);
 	if (rval)
-		goto out;
+		goto err_put_device;
 
 	if (config->compat) {
 		rval = nvmem_setup_compat(nvmem, config);
 		if (rval)
-			goto out;
+			goto err_device_del;
 	}
 
 	if (config->cells)
 		nvmem_add_cells(nvmem, config);
 
 	return nvmem;
-out:
-	ida_simple_remove(&nvmem_ida, nvmem->id);
-	kfree(nvmem);
+
+err_device_del:
+	device_del(&nvmem->dev);
+err_put_device:
+	put_device(&nvmem->dev);
+
 	return ERR_PTR(rval);
 }
 EXPORT_SYMBOL_GPL(nvmem_register);
diff --git a/drivers/of/device.c b/drivers/of/device.c
index fd5cfad..f7a9701 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -225,6 +225,7 @@
 
 	return tsize;
 }
+EXPORT_SYMBOL_GPL(of_device_get_modalias);
 
 /**
  * of_device_uevent - Display OF related uevent information
@@ -287,3 +288,4 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(of_device_uevent_modalias);
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 3ed6238..c4953ec 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -741,6 +741,8 @@
 
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return DMA_ERROR_CODE;
 
 	BUG_ON(size <= 0);
 
@@ -814,6 +816,10 @@
 	
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 
 	DBG_RUN("%s() iovp 0x%lx/%x\n",
 		__func__, (long)iova, size);
@@ -918,6 +924,8 @@
 	
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return 0;
 	
 	DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
 
@@ -990,6 +998,10 @@
 
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 
 	DBG_RUN_SG("%s() START %d entries, %p,%x\n",
 		__func__, nents, sg_virt(sglist), sglist->length);
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 1133b5c..5c63b92 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -154,7 +154,10 @@
 };
 
 /* Looks nice and keeps the compiler happy */
-#define DINO_DEV(d) ((struct dino_device *) d)
+#define DINO_DEV(d) ({				\
+	void *__pdata = d;			\
+	BUG_ON(!__pdata);			\
+	(struct dino_device *)__pdata; })
 
 
 /*
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 2ec2aef..bc286cb 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -111,8 +111,10 @@
 
 
 /* Looks nice and keeps the compiler happy */
-#define LBA_DEV(d) ((struct lba_device *) (d))
-
+#define LBA_DEV(d) ({				\
+	void *__pdata = d;			\
+	BUG_ON(!__pdata);			\
+	(struct lba_device *)__pdata; })
 
 /*
 ** Only allow 8 subsidiary busses per LBA
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 151b86b..56918d1 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -691,6 +691,8 @@
 		return 0;
 
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return 0;
 
 	/*
 	 * check if mask is >= than the current max IO Virt Address
@@ -722,6 +724,8 @@
 	int pide;
 
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return DMA_ERROR_CODE;
 
 	/* save offset bits */
 	offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
@@ -813,6 +817,10 @@
 	DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size);
 
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 	offset = iova & ~IOVP_MASK;
 	iova ^= offset;        /* clear offset bits */
 	size += offset;
@@ -952,6 +960,8 @@
 	DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
 
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return 0;
 
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
@@ -1037,6 +1047,10 @@
 		__func__, nents, sg_virt(sglist), sglist->length);
 
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 
 #ifdef SBA_COLLECT_STATS
 	ioc->usg_calls++;
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
index 3452983..03ebfd5 100644
--- a/drivers/pci/host/pcie-rockchip.c
+++ b/drivers/pci/host/pcie-rockchip.c
@@ -131,6 +131,7 @@
 		 PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
 		 PCIE_CORE_INT_MMVC)
 
+#define PCIE_RC_CONFIG_NORMAL_BASE	0x800000
 #define PCIE_RC_CONFIG_BASE		0xa00000
 #define PCIE_RC_CONFIG_VENDOR		(PCIE_RC_CONFIG_BASE + 0x00)
 #define PCIE_RC_CONFIG_RID_CCR		(PCIE_RC_CONFIG_BASE + 0x08)
@@ -267,7 +268,9 @@
 static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
 				     int where, int size, u32 *val)
 {
-	void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where;
+	void __iomem *addr;
+
+	addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + where;
 
 	if (!IS_ALIGNED((uintptr_t)addr, size)) {
 		*val = 0;
@@ -291,11 +294,13 @@
 				     int where, int size, u32 val)
 {
 	u32 mask, tmp, offset;
+	void __iomem *addr;
 
 	offset = where & ~0x3;
+	addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offset;
 
 	if (size == 4) {
-		writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
+		writel(val, addr);
 		return PCIBIOS_SUCCESSFUL;
 	}
 
@@ -306,9 +311,9 @@
 	 * corrupt RW1C bits in adjacent registers.  But the hardware
 	 * doesn't support smaller writes.
 	 */
-	tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
+	tmp = readl(addr) & mask;
 	tmp |= val << ((where & 0x3) * 8);
-	writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
+	writel(tmp, addr);
 
 	return PCIBIOS_SUCCESSFUL;
 }
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 1ccce1c..8a68e2b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -954,6 +954,7 @@
 		return pci_legacy_resume_early(dev);
 
 	pci_update_current_state(pci_dev, PCI_D0);
+	pci_restore_state(pci_dev);
 
 	if (drv && drv->pm && drv->pm->thaw_noirq)
 		error = drv->pm->thaw_noirq(dev);
diff --git a/drivers/pinctrl/qcom/pinctrl-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpi.c
index 11f954e..39c35b7 100644
--- a/drivers/pinctrl/qcom/pinctrl-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-lpi.c
@@ -26,7 +26,7 @@
 #include "../core.h"
 #include "../pinctrl-utils.h"
 
-#define LPI_ADDRESS_SIZE			0xC000
+#define LPI_ADDRESS_SIZE			0x20000
 
 #define LPI_GPIO_REG_VAL_CTL			0x00
 #define LPI_GPIO_REG_DIR_CTL			0x04
@@ -109,35 +109,35 @@
 	0x00000000,
 	0x00001000,
 	0x00002000,
-	0x00002010,
 	0x00003000,
-	0x00003010,
 	0x00004000,
-	0x00004010,
 	0x00005000,
-	0x00005010,
-	0x00005020,
-	0x00005030,
 	0x00006000,
-	0x00006010,
 	0x00007000,
-	0x00007010,
-	0x00005040,
-	0x00005050,
 	0x00008000,
-	0x00008010,
-	0x00008020,
-	0x00008030,
-	0x00008040,
-	0x00008050,
-	0x00008060,
-	0x00008070,
 	0x00009000,
-	0x00009010,
 	0x0000A000,
-	0x0000A010,
 	0x0000B000,
-	0x0000B010,
+	0x0000C000,
+	0x0000D000,
+	0x0000E000,
+	0x0000F000,
+	0x00010000,
+	0x00011000,
+	0x00012000,
+	0x00013000,
+	0x00014000,
+	0x00015000,
+	0x00016000,
+	0x00017000,
+	0x00018000,
+	0x00019000,
+	0x0001A000,
+	0x0001B000,
+	0x0001C000,
+	0x0001D000,
+	0x0001E000,
+	0x0001F000,
 };
 
 static const char *const lpi_gpio_functions[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 9520166..c6a5d29 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -40,6 +40,7 @@
 
 #define MAX_NR_GPIO 300
 #define PS_HOLD_OFFSET 0x820
+#define STATUS_OFFSET 0x10
 
 /**
  * struct msm_pinctrl - state for a pinctrl-msm device
@@ -74,6 +75,35 @@
 
 static struct msm_pinctrl *msm_pinctrl_data;
 
+static u32 msm_pinctrl_find_base(const struct msm_pinctrl_soc_data *soc_data,
+					u32 gpio_id)
+{
+	int i;
+	u32 val;
+
+	if (gpio_id >= soc_data->ngpios || !soc_data->pin_base)
+		return 0;
+
+	if (soc_data->pin_base[gpio_id])
+		return soc_data->pin_base[gpio_id];
+
+	for (i = 0; i < soc_data->n_tile_offsets; i++) {
+		val = readl_relaxed(msm_pinctrl_data->regs +
+			soc_data->tile_offsets[i] + STATUS_OFFSET
+			+ soc_data->reg_size * gpio_id);
+		if (val) {
+			soc_data->pin_base[gpio_id] = soc_data->tile_offsets[i];
+			return soc_data->tile_offsets[i];
+		}
+	}
+
+	/* In the case that the soc_data does not support dynamic base
+	 * detection, we return 0 here.
+	 */
+	WARN_ONCE(1, "%s:Dynamic base detection is not supported\n", __func__);
+	return 0;
+}
+
 static int msm_get_groups_count(struct pinctrl_dev *pctldev)
 {
 	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -143,10 +173,11 @@
 	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 	const struct msm_pingroup *g;
 	unsigned long flags;
-	u32 val, mask;
+	u32 val, mask, base;
 	int i;
 
 	g = &pctrl->soc->groups[group];
+	base = msm_pinctrl_find_base(pctrl->soc, group);
 	mask = GENMASK(g->mux_bit + order_base_2(g->nfuncs) - 1, g->mux_bit);
 
 	for (i = 0; i < g->nfuncs; i++) {
@@ -159,10 +190,10 @@
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->ctl_reg);
+	val = readl(pctrl->regs + base + g->ctl_reg);
 	val &= ~mask;
 	val |= i << g->mux_bit;
-	writel(val, pctrl->regs + g->ctl_reg);
+	writel(val, pctrl->regs + base + g->ctl_reg);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 
@@ -227,15 +258,16 @@
 	unsigned arg;
 	unsigned bit;
 	int ret;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[group];
+	base = msm_pinctrl_find_base(pctrl->soc, group);
 
 	ret = msm_config_reg(pctrl, g, param, &mask, &bit);
 	if (ret < 0)
 		return ret;
 
-	val = readl(pctrl->regs + g->ctl_reg);
+	val = readl(pctrl->regs + base + g->ctl_reg);
 	arg = (val >> bit) & mask;
 
 	/* Convert register value to pinconf value */
@@ -260,7 +292,7 @@
 		if (!arg)
 			return -EINVAL;
 
-		val = readl(pctrl->regs + g->io_reg);
+		val = readl(pctrl->regs + base + g->io_reg);
 		arg = !!(val & BIT(g->in_bit));
 		break;
 	case PIN_CONFIG_INPUT_ENABLE:
@@ -291,11 +323,12 @@
 	unsigned arg;
 	unsigned bit;
 	int ret;
-	u32 val;
+	u32 val, base;
 	int i;
 
 	g = &pctrl->soc->groups[group];
 
+	base = msm_pinctrl_find_base(pctrl->soc, group);
 	for (i = 0; i < num_configs; i++) {
 		param = pinconf_to_config_param(configs[i]);
 		arg = pinconf_to_config_argument(configs[i]);
@@ -328,12 +361,12 @@
 		case PIN_CONFIG_OUTPUT:
 			/* set output value */
 			spin_lock_irqsave(&pctrl->lock, flags);
-			val = readl(pctrl->regs + g->io_reg);
+			val = readl(pctrl->regs + base + g->io_reg);
 			if (arg)
 				val |= BIT(g->out_bit);
 			else
 				val &= ~BIT(g->out_bit);
-			writel(val, pctrl->regs + g->io_reg);
+			writel(val, pctrl->regs + base + g->io_reg);
 			spin_unlock_irqrestore(&pctrl->lock, flags);
 
 			/* enable output */
@@ -356,10 +389,10 @@
 		}
 
 		spin_lock_irqsave(&pctrl->lock, flags);
-		val = readl(pctrl->regs + g->ctl_reg);
+		val = readl(pctrl->regs + base + g->ctl_reg);
 		val &= ~(mask << bit);
 		val |= arg << bit;
-		writel(val, pctrl->regs + g->ctl_reg);
+		writel(val, pctrl->regs + base + g->ctl_reg);
 		spin_unlock_irqrestore(&pctrl->lock, flags);
 	}
 
@@ -384,15 +417,16 @@
 	const struct msm_pingroup *g;
 	struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[offset];
+	base = msm_pinctrl_find_base(pctrl->soc, offset);
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->ctl_reg);
+	val = readl(pctrl->regs + base + g->ctl_reg);
 	val &= ~BIT(g->oe_bit);
-	writel(val, pctrl->regs + g->ctl_reg);
+	writel(val, pctrl->regs + base + g->ctl_reg);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 
@@ -404,22 +438,23 @@
 	const struct msm_pingroup *g;
 	struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[offset];
+	base = msm_pinctrl_find_base(pctrl->soc, offset);
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->io_reg);
+	val = readl(pctrl->regs + base + g->io_reg);
 	if (value)
 		val |= BIT(g->out_bit);
 	else
 		val &= ~BIT(g->out_bit);
-	writel(val, pctrl->regs + g->io_reg);
+	writel(val, pctrl->regs + base + g->io_reg);
 
-	val = readl(pctrl->regs + g->ctl_reg);
+	val = readl(pctrl->regs + base + g->ctl_reg);
 	val |= BIT(g->oe_bit);
-	writel(val, pctrl->regs + g->ctl_reg);
+	writel(val, pctrl->regs + base + g->ctl_reg);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 
@@ -430,11 +465,12 @@
 {
 	const struct msm_pingroup *g;
 	struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[offset];
+	base = msm_pinctrl_find_base(pctrl->soc, offset);
 
-	val = readl(pctrl->regs + g->io_reg);
+	val = readl(pctrl->regs + base + g->io_reg);
 	return !!(val & BIT(g->in_bit));
 }
 
@@ -443,18 +479,19 @@
 	const struct msm_pingroup *g;
 	struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[offset];
+	base = msm_pinctrl_find_base(pctrl->soc, offset);
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->io_reg);
+	val = readl(pctrl->regs + base + g->io_reg);
 	if (value)
 		val |= BIT(g->out_bit);
 	else
 		val &= ~BIT(g->out_bit);
-	writel(val, pctrl->regs + g->io_reg);
+	writel(val, pctrl->regs + base + g->io_reg);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 }
@@ -474,7 +511,7 @@
 	int is_out;
 	int drive;
 	int pull;
-	u32 ctl_reg;
+	u32 ctl_reg, base;
 
 	static const char * const pulls[] = {
 		"no pull",
@@ -484,7 +521,9 @@
 	};
 
 	g = &pctrl->soc->groups[offset];
-	ctl_reg = readl(pctrl->regs + g->ctl_reg);
+	base = msm_pinctrl_find_base(pctrl->soc, offset);
+
+	ctl_reg = readl(pctrl->regs + base + g->ctl_reg);
 
 	is_out = !!(ctl_reg & BIT(g->oe_bit));
 	func = (ctl_reg >> g->mux_bit) & 7;
@@ -543,21 +582,21 @@
  */
 static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl,
 					  const struct msm_pingroup *g,
-					  struct irq_data *d)
+					  struct irq_data *d, u32 base)
 {
 	int loop_limit = 100;
 	unsigned val, val2, intstat;
 	unsigned pol;
 
 	do {
-		val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
+		val = readl(pctrl->regs + base + g->io_reg) & BIT(g->in_bit);
 
-		pol = readl(pctrl->regs + g->intr_cfg_reg);
+		pol = readl(pctrl->regs + base + g->intr_cfg_reg);
 		pol ^= BIT(g->intr_polarity_bit);
-		writel(pol, pctrl->regs + g->intr_cfg_reg);
+		writel(pol, pctrl->regs + base + g->intr_cfg_reg);
 
-		val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
-		intstat = readl(pctrl->regs + g->intr_status_reg);
+		val2 = readl(pctrl->regs + base + g->io_reg) & BIT(g->in_bit);
+		intstat = readl(pctrl->regs + base + g->intr_status_reg);
 		if (intstat || (val == val2))
 			return;
 	} while (loop_limit-- > 0);
@@ -571,15 +610,16 @@
 	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct msm_pingroup *g;
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[d->hwirq];
+	base = msm_pinctrl_find_base(pctrl->soc, d->hwirq);
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->intr_cfg_reg);
+	val = readl(pctrl->regs + base + g->intr_cfg_reg);
 	val &= ~BIT(g->intr_enable_bit);
-	writel(val, pctrl->regs + g->intr_cfg_reg);
+	writel(val, pctrl->regs + base + g->intr_cfg_reg);
 
 	clear_bit(d->hwirq, pctrl->enabled_irqs);
 
@@ -592,15 +632,16 @@
 	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct msm_pingroup *g;
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[d->hwirq];
+	base = msm_pinctrl_find_base(pctrl->soc, d->hwirq);
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->intr_cfg_reg);
+	val = readl(pctrl->regs + base + g->intr_cfg_reg);
 	val |= BIT(g->intr_enable_bit);
-	writel(val, pctrl->regs + g->intr_cfg_reg);
+	writel(val, pctrl->regs + base + g->intr_cfg_reg);
 
 	set_bit(d->hwirq, pctrl->enabled_irqs);
 
@@ -613,21 +654,22 @@
 	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct msm_pingroup *g;
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[d->hwirq];
+	base = msm_pinctrl_find_base(pctrl->soc, d->hwirq);
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->intr_status_reg);
+	val = readl(pctrl->regs + base + g->intr_status_reg);
 	if (g->intr_ack_high)
 		val |= BIT(g->intr_status_bit);
 	else
 		val &= ~BIT(g->intr_status_bit);
-	writel(val, pctrl->regs + g->intr_status_reg);
+	writel(val, pctrl->regs + base + g->intr_status_reg);
 
 	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
-		msm_gpio_update_dual_edge_pos(pctrl, g, d);
+		msm_gpio_update_dual_edge_pos(pctrl, g, d, base);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 }
@@ -638,10 +680,10 @@
 	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct msm_pingroup *g;
 	unsigned long flags;
-	u32 val;
+	u32 val, base;
 
 	g = &pctrl->soc->groups[d->hwirq];
-
+	base = msm_pinctrl_find_base(pctrl->soc, d->hwirq);
 	spin_lock_irqsave(&pctrl->lock, flags);
 
 	/*
@@ -653,17 +695,17 @@
 		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
 
 	/* Route interrupts to application cpu */
-	val = readl(pctrl->regs + g->intr_target_reg);
+	val = readl(pctrl->regs + base + g->intr_target_reg);
 	val &= ~(7 << g->intr_target_bit);
 	val |= g->intr_target_kpss_val << g->intr_target_bit;
-	writel(val, pctrl->regs + g->intr_target_reg);
+	writel(val, pctrl->regs + base + g->intr_target_reg);
 
 	/* Update configuration for gpio.
 	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
 	 * internal circuitry of TLMM, toggling the RAW_STATUS
 	 * could cause the INTR_STATUS to be set for EDGE interrupts.
 	 */
-	val = readl(pctrl->regs + g->intr_cfg_reg);
+	val = readl(pctrl->regs + base + g->intr_cfg_reg);
 	val |= BIT(g->intr_raw_status_bit);
 	if (g->intr_detection_width == 2) {
 		val &= ~(3 << g->intr_detection_bit);
@@ -711,10 +753,10 @@
 	} else {
 		BUG();
 	}
-	writel(val, pctrl->regs + g->intr_cfg_reg);
+	writel(val, pctrl->regs + base + g->intr_cfg_reg);
 
 	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
-		msm_gpio_update_dual_edge_pos(pctrl, g, d);
+		msm_gpio_update_dual_edge_pos(pctrl, g, d, base);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 
@@ -843,7 +885,7 @@
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int irq_pin;
 	int handled = 0;
-	u32 val;
+	u32 val, base;
 	int i;
 
 	chained_irq_enter(chip, desc);
@@ -854,7 +896,8 @@
 	 */
 	for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) {
 		g = &pctrl->soc->groups[i];
-		val = readl(pctrl->regs + g->intr_status_reg);
+		base = msm_pinctrl_find_base(pctrl->soc, i);
+		val = readl(pctrl->regs + base + g->intr_status_reg);
 		if (val & BIT(g->intr_status_bit)) {
 			irq_pin = irq_find_mapping(gc->irqdomain, i);
 			generic_handle_irq(irq_pin);
@@ -951,7 +994,7 @@
 	ret = gpiochip_irqchip_add(chip,
 				   &msm_gpio_irq_chip,
 				   0,
-				   handle_edge_irq,
+				   handle_fasteoi_irq,
 				   IRQ_TYPE_NONE);
 	if (ret) {
 		dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
@@ -1016,6 +1059,7 @@
 	const struct msm_pingroup *g;
 	const char *name = "null";
 	struct msm_pinctrl *pctrl = msm_pinctrl_data;
+	u32 base;
 
 	if (!msm_show_resume_irq_mask)
 		return;
@@ -1023,7 +1067,8 @@
 	spin_lock_irqsave(&pctrl->lock, flags);
 	for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) {
 		g = &pctrl->soc->groups[i];
-		val = readl_relaxed(pctrl->regs + g->intr_status_reg);
+		base = msm_pinctrl_find_base(pctrl->soc, i);
+		val = readl_relaxed(pctrl->regs + base + g->intr_status_reg);
 		if (val & BIT(g->intr_status_bit)) {
 			irq = irq_find_mapping(pctrl->chip.irqdomain, i);
 			desc = irq_to_desc(irq);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 0e223e0..375a962 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -129,6 +129,10 @@
 	unsigned ngpios;
 	const struct msm_dir_conn *dir_conn;
 	unsigned int n_dir_conns;
+	const u32 *tile_offsets;
+	unsigned int n_tile_offsets;
+	u32 *pin_base;
+	unsigned int reg_size;
 };
 
 int msm_pinctrl_probe(struct platform_device *pdev,
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c
index 1f742f8..b454cc442 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm670.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c
@@ -25,12 +25,8 @@
 		.ngroups = ARRAY_SIZE(fname##_groups),	\
 	}
 
-#define NORTH	0x00500000
-#define SOUTH	0x00900000
-#define WEST	0x00100000
-#define DUMMY	0x0
 #define REG_SIZE 0x1000
-#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
 	{						\
 		.name = "gpio" #id,			\
 		.pins = gpio##id##_pins,		\
@@ -48,11 +44,11 @@
 			msm_mux_##f9			\
 		},					\
 		.nfuncs = 10,				\
-		.ctl_reg = base + REG_SIZE * id,		\
-		.io_reg = base + 0x4 + REG_SIZE * id,		\
-		.intr_cfg_reg = base + 0x8 + REG_SIZE * id,	\
-		.intr_status_reg = base + 0xc + REG_SIZE * id,	\
-		.intr_target_reg = base + 0x8 + REG_SIZE * id,	\
+		.ctl_reg = REG_SIZE * id,		\
+		.io_reg = 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = 0x8 + REG_SIZE * id,	\
+		.intr_status_reg = 0xc + REG_SIZE * id,	\
+		.intr_target_reg = 0x8 + REG_SIZE * id,	\
 		.mux_bit = 2,			\
 		.pull_bit = 0,			\
 		.drv_bit = 6,			\
@@ -118,6 +114,10 @@
 		.intr_detection_bit = -1,		\
 		.intr_detection_width = -1,		\
 	}
+
+static const u32 sdm670_tile_offsets[] = {0x100000, 0x500000, 0x900000};
+static u32 sdm670_pin_base[150];
+
 static const struct pinctrl_pin_desc sdm670_pins[] = {
 	PINCTRL_PIN(0, "GPIO_0"),
 	PINCTRL_PIN(1, "GPIO_1"),
@@ -1332,249 +1332,249 @@
  * Clients would not be able to request these dummy pin groups.
  */
 static const struct msm_pingroup sdm670_groups[] = {
-	[0] = PINGROUP(0, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
-	[1] = PINGROUP(1, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
-	[2] = PINGROUP(2, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
-	[3] = PINGROUP(3, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
-	[4] = PINGROUP(4, NORTH, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
-	[5] = PINGROUP(5, NORTH, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
-	[6] = PINGROUP(6, NORTH, qup9, NA, ddr_pxi0, NA, NA, NA, NA, NA, NA),
-	[7] = PINGROUP(7, NORTH, qup9, ddr_bist, NA, atest_tsens2,
+	[0] = PINGROUP(0, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[1] = PINGROUP(1, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[2] = PINGROUP(2, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[3] = PINGROUP(3, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[4] = PINGROUP(4, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[5] = PINGROUP(5, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[6] = PINGROUP(6, qup9, NA, ddr_pxi0, NA, NA, NA, NA, NA, NA),
+	[7] = PINGROUP(7, qup9, ddr_bist, NA, atest_tsens2,
 		       vsense_trigger, atest_usb1, ddr_pxi0, NA, NA),
-	[8] = PINGROUP(8, WEST, qup_l4, GP_PDM1, ddr_bist, NA, NA, NA, NA, NA,
+	[8] = PINGROUP(8, qup_l4, GP_PDM1, ddr_bist, NA, NA, NA, NA, NA,
 		       NA),
-	[9] = PINGROUP(9, WEST, qup_l5, ddr_bist, NA, NA, NA, NA, NA, NA, NA),
-	[10] = PINGROUP(10, NORTH, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1,
+	[9] = PINGROUP(9, qup_l5, ddr_bist, NA, NA, NA, NA, NA, NA, NA),
+	[10] = PINGROUP(10, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1,
 			atest_usb11, ddr_pxi2, NA, NA, NA),
-	[11] = PINGROUP(11, NORTH, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0,
+	[11] = PINGROUP(11, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0,
 			atest_usb10, ddr_pxi2, NA, NA, NA),
-	[12] = PINGROUP(12, SOUTH, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, NA,
+	[12] = PINGROUP(12, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, NA,
 			NA, NA, NA, NA),
-	[13] = PINGROUP(13, WEST, cam_mclk, pll_bypassnl, qdss_gpio0, ddr_pxi3,
+	[13] = PINGROUP(13, cam_mclk, pll_bypassnl, qdss_gpio0, ddr_pxi3,
 			NA, NA, NA, NA, NA),
-	[14] = PINGROUP(14, WEST, cam_mclk, pll_reset, qdss_gpio1, NA, NA, NA,
+	[14] = PINGROUP(14, cam_mclk, pll_reset, qdss_gpio1, NA, NA, NA,
 			NA, NA, NA),
-	[15] = PINGROUP(15, WEST, cam_mclk, qdss_gpio2, NA, NA, NA, NA, NA, NA,
+	[15] = PINGROUP(15, cam_mclk, qdss_gpio2, NA, NA, NA, NA, NA, NA,
 			NA),
-	[16] = PINGROUP(16, WEST, cam_mclk, qdss_gpio3, NA, NA, NA, NA, NA, NA,
+	[16] = PINGROUP(16, cam_mclk, qdss_gpio3, NA, NA, NA, NA, NA, NA,
 			NA),
-	[17] = PINGROUP(17, WEST, cci_i2c, qup1, qdss_gpio4, NA, NA, NA, NA,
+	[17] = PINGROUP(17, cci_i2c, qup1, qdss_gpio4, NA, NA, NA, NA,
 			NA, NA),
-	[18] = PINGROUP(18, WEST, cci_i2c, qup1, NA, qdss_gpio5, NA, NA, NA,
+	[18] = PINGROUP(18, cci_i2c, qup1, NA, qdss_gpio5, NA, NA, NA,
 			NA, NA),
-	[19] = PINGROUP(19, WEST, cci_i2c, qup1, NA, qdss_gpio6, NA, NA, NA,
+	[19] = PINGROUP(19, cci_i2c, qup1, NA, qdss_gpio6, NA, NA, NA,
 			NA, NA),
-	[20] = PINGROUP(20, WEST, cci_i2c, qup1, NA, qdss_gpio7, NA, NA, NA,
+	[20] = PINGROUP(20, cci_i2c, qup1, NA, qdss_gpio7, NA, NA, NA,
 			NA, NA),
-	[21] = PINGROUP(21, WEST, cci_timer0, gcc_gp2, qdss_gpio8, NA, NA, NA,
+	[21] = PINGROUP(21, cci_timer0, gcc_gp2, qdss_gpio8, NA, NA, NA,
 			NA, NA, NA),
-	[22] = PINGROUP(22, WEST, cci_timer1, gcc_gp3, qdss_gpio, NA, NA, NA,
+	[22] = PINGROUP(22, cci_timer1, gcc_gp3, qdss_gpio, NA, NA, NA,
 			NA, NA, NA),
-	[23] = PINGROUP(23, WEST, cci_timer2, qdss_gpio9, NA, NA, NA, NA, NA,
+	[23] = PINGROUP(23, cci_timer2, qdss_gpio9, NA, NA, NA, NA, NA,
 			NA, NA),
-	[24] = PINGROUP(24, WEST, cci_timer3, cci_async, qdss_gpio10, NA, NA,
+	[24] = PINGROUP(24, cci_timer3, cci_async, qdss_gpio10, NA, NA,
 			NA, NA, NA, NA),
-	[25] = PINGROUP(25, WEST, cci_timer4, cci_async, qdss_gpio11, NA, NA,
+	[25] = PINGROUP(25, cci_timer4, cci_async, qdss_gpio11, NA, NA,
 			NA, NA, NA, NA),
-	[26] = PINGROUP(26, WEST, cci_async, qdss_gpio12, JITTER_BIST, NA, NA,
+	[26] = PINGROUP(26, cci_async, qdss_gpio12, JITTER_BIST, NA, NA,
 			NA, NA, NA, NA),
-	[27] = PINGROUP(27, WEST, qup2, qdss_gpio13, PLL_BIST, NA, NA, NA, NA,
+	[27] = PINGROUP(27, qup2, qdss_gpio13, PLL_BIST, NA, NA, NA, NA,
 			NA, NA),
-	[28] = PINGROUP(28, WEST, qup2, qdss_gpio14, AGERA_PLL, NA, NA, NA, NA,
+	[28] = PINGROUP(28, qup2, qdss_gpio14, AGERA_PLL, NA, NA, NA, NA,
 			NA, NA),
-	[29] = PINGROUP(29, WEST, qup2, NA, phase_flag1, qdss_gpio15,
+	[29] = PINGROUP(29, qup2, NA, phase_flag1, qdss_gpio15,
 			atest_tsens, NA, NA, NA, NA),
-	[30] = PINGROUP(30, WEST, qup2, phase_flag2, qdss_gpio, NA, NA, NA, NA,
+	[30] = PINGROUP(30, qup2, phase_flag2, qdss_gpio, NA, NA, NA, NA,
 			NA, NA),
-	[31] = PINGROUP(31, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
-	[32] = PINGROUP(32, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
-	[33] = PINGROUP(33, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
-	[34] = PINGROUP(34, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
-	[35] = PINGROUP(35, NORTH, pci_e0, QUP_L4, JITTER_BIST, NA, NA, NA, NA,
+	[31] = PINGROUP(31, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[32] = PINGROUP(32, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[33] = PINGROUP(33, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[34] = PINGROUP(34, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[35] = PINGROUP(35, pci_e0, QUP_L4, JITTER_BIST, NA, NA, NA, NA,
 			NA, NA),
-	[36] = PINGROUP(36, NORTH, pci_e0, QUP_L5, PLL_BIST, NA, NA, NA, NA,
+	[36] = PINGROUP(36, pci_e0, QUP_L5, PLL_BIST, NA, NA, NA, NA,
 			NA, NA),
-	[37] = PINGROUP(37, NORTH, QUP_L6, AGERA_PLL, NA, NA, NA, NA, NA, NA,
+	[37] = PINGROUP(37, QUP_L6, AGERA_PLL, NA, NA, NA, NA, NA, NA,
 			NA),
-	[38] = PINGROUP(38, NORTH, usb_phy, NA, NA, NA, NA, NA, NA, NA, NA),
-	[39] = PINGROUP(39, NORTH, lpass_slimbus, NA, NA, NA, NA, NA, NA, NA,
+	[38] = PINGROUP(38, usb_phy, NA, NA, NA, NA, NA, NA, NA, NA),
+	[39] = PINGROUP(39, lpass_slimbus, NA, NA, NA, NA, NA, NA, NA,
 			NA),
-	[40] = PINGROUP(40, NORTH, sd_write, tsif1_error, NA, NA, NA, NA, NA,
+	[40] = PINGROUP(40, sd_write, tsif1_error, NA, NA, NA, NA, NA,
 			NA, NA),
-	[41] = PINGROUP(41, SOUTH, qup3, NA, qdss_gpio6, NA, NA, NA, NA, NA,
+	[41] = PINGROUP(41, qup3, NA, qdss_gpio6, NA, NA, NA, NA, NA,
 			NA),
-	[42] = PINGROUP(42, SOUTH, qup3, NA, qdss_gpio7, NA, NA, NA, NA, NA,
+	[42] = PINGROUP(42, qup3, NA, qdss_gpio7, NA, NA, NA, NA, NA,
 			NA),
-	[43] = PINGROUP(43, SOUTH, qup3, NA, qdss_gpio14, NA, NA, NA, NA, NA,
+	[43] = PINGROUP(43, qup3, NA, qdss_gpio14, NA, NA, NA, NA, NA,
 			NA),
-	[44] = PINGROUP(44, SOUTH, qup3, NA, qdss_gpio15, NA, NA, NA, NA, NA,
+	[44] = PINGROUP(44, qup3, NA, qdss_gpio15, NA, NA, NA, NA, NA,
 			NA),
-	[45] = PINGROUP(45, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
-	[46] = PINGROUP(46, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
-	[47] = PINGROUP(47, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
-	[48] = PINGROUP(48, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
-	[49] = PINGROUP(49, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
-	[50] = PINGROUP(50, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
-	[51] = PINGROUP(51, NORTH, qup12, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
-	[52] = PINGROUP(52, NORTH, qup12, phase_flag16, qdss_cti, NA, NA, NA,
+	[45] = PINGROUP(45, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[46] = PINGROUP(46, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[47] = PINGROUP(47, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[48] = PINGROUP(48, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[49] = PINGROUP(49, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[50] = PINGROUP(50, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[51] = PINGROUP(51, qup12, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[52] = PINGROUP(52, qup12, phase_flag16, qdss_cti, NA, NA, NA,
 			NA, NA, NA),
-	[53] = PINGROUP(53, NORTH, qup10, phase_flag11, NA, NA, NA, NA, NA, NA,
+	[53] = PINGROUP(53, qup10, phase_flag11, NA, NA, NA, NA, NA, NA,
 			NA),
-	[54] = PINGROUP(54, NORTH, qup10, GP_PDM0, phase_flag12, NA,
+	[54] = PINGROUP(54, qup10, GP_PDM0, phase_flag12, NA,
 			wlan1_adc1, atest_usb13, ddr_pxi1, NA, NA),
-	[55] = PINGROUP(55, NORTH, qup10, phase_flag13, NA, wlan1_adc0,
+	[55] = PINGROUP(55, qup10, phase_flag13, NA, wlan1_adc0,
 			atest_usb12, ddr_pxi1, NA, NA, NA),
-	[56] = PINGROUP(56, NORTH, qup10, phase_flag17, NA, NA, NA, NA, NA, NA,
+	[56] = PINGROUP(56, qup10, phase_flag17, NA, NA, NA, NA, NA, NA,
 			NA),
-	[57] = PINGROUP(57, NORTH, qua_mi2s, gcc_gp1, phase_flag18, NA, NA, NA,
+	[57] = PINGROUP(57, qua_mi2s, gcc_gp1, phase_flag18, NA, NA, NA,
 			NA, NA, NA),
-	[58] = PINGROUP(58, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[59] = PINGROUP(59, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[60] = PINGROUP(60, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[61] = PINGROUP(61, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[62] = PINGROUP(62, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[63] = PINGROUP(63, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[64] = PINGROUP(64, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[65] = PINGROUP(65, NORTH, pri_mi2s, qup8, wsa_clk, NA, NA, NA, NA, NA,
+	[58] = PINGROUP(58, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[59] = PINGROUP(59, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[60] = PINGROUP(60, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[61] = PINGROUP(61, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[62] = PINGROUP(62, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[63] = PINGROUP(63, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[64] = PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[65] = PINGROUP(65, pri_mi2s, qup8, wsa_clk, NA, NA, NA, NA, NA,
 			NA),
-	[66] = PINGROUP(66, NORTH, pri_mi2s_ws, qup8, wsa_data, GP_PDM1, NA,
+	[66] = PINGROUP(66, pri_mi2s_ws, qup8, wsa_data, GP_PDM1, NA,
 			NA, NA, NA, NA),
-	[67] = PINGROUP(67, NORTH, pri_mi2s, qup8, NA, atest_usb2, NA, NA, NA,
+	[67] = PINGROUP(67, pri_mi2s, qup8, NA, atest_usb2, NA, NA, NA,
 			NA, NA),
-	[68] = PINGROUP(68, NORTH, pri_mi2s, qup8, NA, atest_usb23, NA, NA, NA,
+	[68] = PINGROUP(68, pri_mi2s, qup8, NA, atest_usb23, NA, NA, NA,
 			NA, NA),
-	[69] = PINGROUP(69, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[70] = PINGROUP(70, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[71] = PINGROUP(71, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[72] = PINGROUP(72, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[73] = PINGROUP(73, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[74] = PINGROUP(74, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[75] = PINGROUP(75, NORTH, ter_mi2s, phase_flag8, qdss_gpio8,
+	[69] = PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[70] = PINGROUP(70, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[71] = PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[72] = PINGROUP(72, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[73] = PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[74] = PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[75] = PINGROUP(75, ter_mi2s, phase_flag8, qdss_gpio8,
 			atest_usb22, QUP_L4, NA, NA, NA, NA),
-	[76] = PINGROUP(76, NORTH, ter_mi2s, phase_flag9, qdss_gpio9,
+	[76] = PINGROUP(76, ter_mi2s, phase_flag9, qdss_gpio9,
 			atest_usb21, QUP_L5, NA, NA, NA, NA),
-	[77] = PINGROUP(77, NORTH, ter_mi2s, phase_flag4, qdss_gpio10,
+	[77] = PINGROUP(77, ter_mi2s, phase_flag4, qdss_gpio10,
 			atest_usb20, QUP_L6, NA, NA, NA, NA),
-	[78] = PINGROUP(78, NORTH, ter_mi2s, gcc_gp1, NA, NA, NA, NA, NA, NA,
+	[78] = PINGROUP(78, ter_mi2s, gcc_gp1, NA, NA, NA, NA, NA, NA,
 			NA),
-	[79] = PINGROUP(79, NORTH, sec_mi2s, GP_PDM2, NA, qdss_gpio11, NA, NA,
+	[79] = PINGROUP(79, sec_mi2s, GP_PDM2, NA, qdss_gpio11, NA, NA,
 			NA, NA, NA),
-	[80] = PINGROUP(80, NORTH, sec_mi2s, NA, qdss_gpio12, NA, NA, NA, NA,
+	[80] = PINGROUP(80, sec_mi2s, NA, qdss_gpio12, NA, NA, NA, NA,
 			NA, NA),
-	[81] = PINGROUP(81, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
-	[82] = PINGROUP(82, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
-	[83] = PINGROUP(83, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
-	[84] = PINGROUP(84, NORTH, qup15, NA, NA, NA, NA, NA, NA, NA, NA),
-	[85] = PINGROUP(85, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
-	[86] = PINGROUP(86, SOUTH, qup5, copy_gp, NA, NA, NA, NA, NA, NA, NA),
-	[87] = PINGROUP(87, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
-	[88] = PINGROUP(88, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
-	[89] = PINGROUP(89, SOUTH, tsif1_clk, qup4, tgu_ch3, phase_flag10, NA,
+	[81] = PINGROUP(81, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[82] = PINGROUP(82, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[83] = PINGROUP(83, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[84] = PINGROUP(84, qup15, NA, NA, NA, NA, NA, NA, NA, NA),
+	[85] = PINGROUP(85, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[86] = PINGROUP(86, qup5, copy_gp, NA, NA, NA, NA, NA, NA, NA),
+	[87] = PINGROUP(87, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[88] = PINGROUP(88, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[89] = PINGROUP(89, tsif1_clk, qup4, tgu_ch3, phase_flag10, NA,
 			NA, NA, NA, NA),
-	[90] = PINGROUP(90, SOUTH, tsif1_en, mdp_vsync0, qup4, mdp_vsync1,
+	[90] = PINGROUP(90, tsif1_en, mdp_vsync0, qup4, mdp_vsync1,
 			mdp_vsync2, mdp_vsync3, tgu_ch0, phase_flag0, qdss_cti),
-	[91] = PINGROUP(91, SOUTH, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA,
+	[91] = PINGROUP(91, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA,
 			qdss_cti, NA, NA, NA),
-	[92] = PINGROUP(92, SOUTH, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2,
+	[92] = PINGROUP(92, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2,
 			NA, NA, NA, NA),
-	[93] = PINGROUP(93, SOUTH, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13,
+	[93] = PINGROUP(93, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13,
 			NA, NA, NA, NA),
-	[94] = PINGROUP(94, SOUTH, tsif2_en, sdc42, qup7, NA, NA, NA, NA, NA,
+	[94] = PINGROUP(94, tsif2_en, sdc42, qup7, NA, NA, NA, NA, NA,
 			NA),
-	[95] = PINGROUP(95, SOUTH, tsif2_data, sdc41, qup7, GP_PDM0, NA, NA,
+	[95] = PINGROUP(95, tsif2_data, sdc41, qup7, GP_PDM0, NA, NA,
 			NA, NA, NA),
-	[96] = PINGROUP(96, SOUTH, tsif2_sync, sdc40, qup7, phase_flag3, NA,
+	[96] = PINGROUP(96, tsif2_sync, sdc40, qup7, phase_flag3, NA,
 			NA, NA, NA, NA),
-	[97] = PINGROUP(97, WEST, NA, NA, mdp_vsync, ldo_en, NA, NA, NA, NA,
+	[97] = PINGROUP(97, NA, NA, mdp_vsync, ldo_en, NA, NA, NA, NA,
 			NA),
-	[98] = PINGROUP(98, WEST, NA, mdp_vsync, ldo_update, NA, NA, NA, NA,
+	[98] = PINGROUP(98, NA, mdp_vsync, ldo_update, NA, NA, NA, NA,
 			NA, NA),
-	[99] = PINGROUP(99, NORTH, phase_flag14, prng_rosc, NA, NA, NA, NA, NA,
+	[99] = PINGROUP(99, phase_flag14, prng_rosc, NA, NA, NA, NA, NA,
 			NA, NA),
-	[100] = PINGROUP(100, WEST, phase_flag15, NA, NA, NA, NA, NA, NA, NA,
+	[100] = PINGROUP(100, phase_flag15, NA, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[101] = PINGROUP(101, WEST, NA, phase_flag5, NA, NA, NA, NA, NA, NA,
+	[101] = PINGROUP(101, NA, phase_flag5, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[102] = PINGROUP(102, WEST, pci_e1, prng_rosc, NA, NA, NA, NA, NA, NA,
+	[102] = PINGROUP(102, pci_e1, prng_rosc, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[103] = PINGROUP(103, WEST, pci_e1, COPY_PHASE, NA, NA, NA, NA, NA, NA,
+	[103] = PINGROUP(103, pci_e1, COPY_PHASE, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[104] = PINGROUP(104, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[105] = PINGROUP(105, NORTH, uim2_data, qup13, qup_l4, NA, NA, NA, NA,
+	[104] = PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[105] = PINGROUP(105, uim2_data, qup13, qup_l4, NA, NA, NA, NA,
 			 NA, NA),
-	[106] = PINGROUP(106, NORTH, uim2_clk, qup13, qup_l5, NA, NA, NA, NA,
+	[106] = PINGROUP(106, uim2_clk, qup13, qup_l5, NA, NA, NA, NA,
 			 NA, NA),
-	[107] = PINGROUP(107, NORTH, uim2_reset, qup13, qup_l6, NA, NA, NA, NA,
+	[107] = PINGROUP(107, uim2_reset, qup13, qup_l6, NA, NA, NA, NA,
 			 NA, NA),
-	[108] = PINGROUP(108, NORTH, uim2_present, qup13, NA, NA, NA, NA, NA,
+	[108] = PINGROUP(108, uim2_present, qup13, NA, NA, NA, NA, NA,
 			 NA, NA),
-	[109] = PINGROUP(109, NORTH, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
-	[110] = PINGROUP(110, NORTH, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
-	[111] = PINGROUP(111, NORTH, uim1_reset, NA, NA, NA, NA, NA, NA, NA,
+	[109] = PINGROUP(109, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	[110] = PINGROUP(110, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	[111] = PINGROUP(111, uim1_reset, NA, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[112] = PINGROUP(112, NORTH, uim1_present, NA, NA, NA, NA, NA, NA, NA,
+	[112] = PINGROUP(112, uim1_present, NA, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[113] = PINGROUP(113, NORTH, uim_batt, edp_hot, NA, NA, NA, NA, NA, NA,
+	[113] = PINGROUP(113, uim_batt, edp_hot, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[114] = PINGROUP(114, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA,
+	[114] = PINGROUP(114, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA,
 			 NA, NA),
-	[115] = PINGROUP(115, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA,
+	[115] = PINGROUP(115, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA,
 			 NA, NA),
-	[116] = PINGROUP(116, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[117] = PINGROUP(117, NORTH, NA, qdss_gpio0, atest_char, NA, NA, NA,
+	[116] = PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[117] = PINGROUP(117, NA, qdss_gpio0, atest_char, NA, NA, NA,
 			 NA, NA, NA),
-	[118] = PINGROUP(118, NORTH, adsp_ext, NA, qdss_gpio1, atest_char3, NA,
+	[118] = PINGROUP(118, adsp_ext, NA, qdss_gpio1, atest_char3, NA,
 			 NA, NA, NA, NA),
-	[119] = PINGROUP(119, NORTH, NA, qdss_gpio2, atest_char2, NA, NA, NA,
+	[119] = PINGROUP(119, NA, qdss_gpio2, atest_char2, NA, NA, NA,
 			 NA, NA, NA),
-	[120] = PINGROUP(120, NORTH, NA, qdss_gpio3, atest_char1, NA, NA, NA,
+	[120] = PINGROUP(120, NA, qdss_gpio3, atest_char1, NA, NA, NA,
 			 NA, NA, NA),
-	[121] = PINGROUP(121, NORTH, NA, qdss_gpio4, atest_char0, NA, NA, NA,
+	[121] = PINGROUP(121, NA, qdss_gpio4, atest_char0, NA, NA, NA,
 			 NA, NA, NA),
-	[122] = PINGROUP(122, NORTH, NA, qdss_gpio5, NA, NA, NA, NA, NA, NA,
+	[122] = PINGROUP(122, NA, qdss_gpio5, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[123] = PINGROUP(123, NORTH, qup_l4, NA, qdss_gpio, NA, NA, NA, NA, NA,
+	[123] = PINGROUP(123, qup_l4, NA, qdss_gpio, NA, NA, NA, NA, NA,
 			 NA),
-	[124] = PINGROUP(124, NORTH, qup_l5, NA, qdss_gpio, NA, NA, NA, NA, NA,
+	[124] = PINGROUP(124, qup_l5, NA, qdss_gpio, NA, NA, NA, NA, NA,
 			 NA),
-	[125] = PINGROUP(125, NORTH, qup_l6, NA, NA, NA, NA, NA, NA, NA, NA),
-	[126] = PINGROUP(126, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[127] = PINGROUP(127, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[128] = PINGROUP(128, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA,
+	[125] = PINGROUP(125, qup_l6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[126] = PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[127] = PINGROUP(127, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[128] = PINGROUP(128, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA,
 			 NA, NA),
-	[129] = PINGROUP(129, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA,
+	[129] = PINGROUP(129, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA,
 			 NA, NA),
-	[130] = PINGROUP(130, WEST, qlink_request, NA, NA, NA, NA, NA, NA, NA,
+	[130] = PINGROUP(130, qlink_request, NA, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[131] = PINGROUP(131, WEST, qlink_enable, NA, NA, NA, NA, NA, NA, NA,
+	[131] = PINGROUP(131, qlink_enable, NA, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[132] = PINGROUP(132, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[133] = PINGROUP(133, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[134] = PINGROUP(134, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[135] = PINGROUP(135, WEST, NA, pa_indicator, NA, NA, NA, NA, NA, NA,
+	[132] = PINGROUP(132, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[133] = PINGROUP(133, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[134] = PINGROUP(134, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[135] = PINGROUP(135, NA, pa_indicator, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[136] = PINGROUP(136, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[137] = PINGROUP(137, WEST, NA, NA, phase_flag26, NA, NA, NA, NA, NA,
+	[136] = PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[137] = PINGROUP(137, NA, NA, phase_flag26, NA, NA, NA, NA, NA,
 			 NA),
-	[138] = PINGROUP(138, WEST, NA, NA, phase_flag27, NA, NA, NA, NA, NA,
+	[138] = PINGROUP(138, NA, NA, phase_flag27, NA, NA, NA, NA, NA,
 			 NA),
-	[139] = PINGROUP(139, WEST, NA, phase_flag28, NA, NA, NA, NA, NA, NA,
+	[139] = PINGROUP(139, NA, phase_flag28, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[140] = PINGROUP(140, WEST, NA, NA, phase_flag6, NA, NA, NA, NA, NA,
+	[140] = PINGROUP(140, NA, NA, phase_flag6, NA, NA, NA, NA, NA,
 			 NA),
-	[141] = PINGROUP(141, WEST, NA, phase_flag29, NA, NA, NA, NA, NA, NA,
+	[141] = PINGROUP(141, NA, phase_flag29, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[142] = PINGROUP(142, WEST, NA, phase_flag30, NA, NA, NA, NA, NA, NA,
+	[142] = PINGROUP(142, NA, phase_flag30, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[143] = PINGROUP(143, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, phase_flag31,
+	[143] = PINGROUP(143, NA, NAV_PPS, NAV_PPS, GPS_TX, phase_flag31,
 			 NA, NA, NA, NA),
-	[144] = PINGROUP(144, SOUTH, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA),
-	[145] = PINGROUP(145, SOUTH, mss_lte, GPS_TX, NA, NA, NA, NA, NA, NA,
+	[144] = PINGROUP(144, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA),
+	[145] = PINGROUP(145, mss_lte, GPS_TX, NA, NA, NA, NA, NA, NA,
 			 NA),
-	[146] = PINGROUP(146, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[147] = PINGROUP(147, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[148] = PINGROUP(148, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[149] = PINGROUP(149, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[146] = PINGROUP(146, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[147] = PINGROUP(147, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[148] = PINGROUP(148, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[149] = PINGROUP(149, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[150] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x599000, 15, 0),
 	[151] = SDC_QDSD_PINGROUP(sdc1_clk, 0x599000, 13, 6),
 	[152] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x599000, 11, 3),
@@ -1585,6 +1585,74 @@
 	[157] = UFS_RESET(ufs_reset, 0x99f000),
 };
 
+static const struct msm_dir_conn sdm670_dir_conn[] = {
+	{1, 510},
+	{3, 511},
+	{5, 512},
+	{10, 513},
+	{11, 514},
+	{20, 515},
+	{22, 516},
+	{24, 517},
+	{26, 518},
+	{30, 519},
+	{31, 639},
+	{32, 521},
+	{34, 522},
+	{36, 523},
+	{37, 524},
+	{38, 525},
+	{39, 526},
+	{40, 527},
+	{41, 637},
+	{43, 529},
+	{44, 530},
+	{46, 531},
+	{48, 532},
+	{49, 640},
+	{52, 534},
+	{53, 535},
+	{54, 536},
+	{56, 537},
+	{57, 538},
+	{66, 546},
+	{68, 547},
+	{77, 550},
+	{78, 551},
+	{79, 552},
+	{80, 553},
+	{84, 554},
+	{85, 555},
+	{86, 556},
+	{88, 557},
+	{89, 638},
+	{91, 559},
+	{92, 560},
+	{95, 561},
+	{96, 562},
+	{97, 563},
+	{101, 564},
+	{103, 565},
+	{115, 570},
+	{116, 571},
+	{117, 572},
+	{118, 573},
+	{119, 609},
+	{120, 610},
+	{121, 611},
+	{122, 612},
+	{123, 613},
+	{124, 614},
+	{125, 615},
+	{127, 617},
+	{128, 618},
+	{129, 619},
+	{130, 620},
+	{132, 621},
+	{133, 622},
+	{145, 623},
+};
+
 static const struct msm_pinctrl_soc_data sdm670_pinctrl = {
 	.pins = sdm670_pins,
 	.npins = ARRAY_SIZE(sdm670_pins),
@@ -1593,6 +1661,12 @@
 	.groups = sdm670_groups,
 	.ngroups = ARRAY_SIZE(sdm670_groups),
 	.ngpios = 150,
+	.dir_conn = sdm670_dir_conn,
+	.n_dir_conns = ARRAY_SIZE(sdm670_dir_conn),
+	.tile_offsets = sdm670_tile_offsets,
+	.n_tile_offsets = ARRAY_SIZE(sdm670_tile_offsets),
+	.pin_base = sdm670_pin_base,
+	.reg_size = REG_SIZE,
 };
 
 static int sdm670_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index 7d125eb..8faabb0 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -25,10 +25,8 @@
 		.ngroups = ARRAY_SIZE(fname##_groups),	\
 	}
 
-#define NORTH	0x00500000
-#define SOUTH	0x00900000
 #define REG_SIZE 0x1000
-#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
 	{						\
 		.name = "gpio" #id,			\
 		.pins = gpio##id##_pins,		\
@@ -46,11 +44,11 @@
 			msm_mux_##f9			\
 		},					\
 		.nfuncs = 10,				\
-		.ctl_reg = base + REG_SIZE * id,		\
-		.io_reg = base + 0x4 + REG_SIZE * id,		\
-		.intr_cfg_reg = base + 0x8 + REG_SIZE * id,	\
-		.intr_status_reg = base + 0xc + REG_SIZE * id,	\
-		.intr_target_reg = base + 0x8 + REG_SIZE * id,	\
+		.ctl_reg = REG_SIZE * id,		\
+		.io_reg = 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = 0x8 + REG_SIZE * id,	\
+		.intr_status_reg = 0xc + REG_SIZE * id,	\
+		.intr_target_reg = 0x8 + REG_SIZE * id,	\
 		.mux_bit = 2,			\
 		.pull_bit = 0,			\
 		.drv_bit = 6,			\
@@ -116,6 +114,10 @@
 		.intr_detection_bit = -1,		\
 		.intr_detection_width = -1,		\
 	}
+
+static const u32 sdm845_tile_offsets[] = {0x500000, 0x900000, 0x100000};
+static u32 sdm845_pin_base[150];
+
 static const struct pinctrl_pin_desc sdm845_pins[] = {
 	PINCTRL_PIN(0, "GPIO_0"),
 	PINCTRL_PIN(1, "GPIO_1"),
@@ -432,306 +434,99 @@
 static const unsigned int ufs_reset_pins[] = { 153 };
 
 enum sdm845_functions {
-	msm_mux_gpio,
-	msm_mux_qup0,
-	msm_mux_reserved0,
-	msm_mux_reserved1,
-	msm_mux_reserved2,
-	msm_mux_reserved3,
-	msm_mux_qup9,
-	msm_mux_qdss_cti,
-	msm_mux_reserved4,
-	msm_mux_reserved5,
-	msm_mux_ddr_pxi0,
-	msm_mux_reserved6,
-	msm_mux_ddr_bist,
-	msm_mux_atest_tsens2,
-	msm_mux_vsense_trigger,
-	msm_mux_atest_usb1,
-	msm_mux_reserved7,
-	msm_mux_qup_l4,
-	msm_mux_wlan1_adc1,
-	msm_mux_atest_usb13,
-	msm_mux_ddr_pxi1,
-	msm_mux_reserved8,
-	msm_mux_qup_l5,
-	msm_mux_wlan1_adc0,
-	msm_mux_atest_usb12,
-	msm_mux_reserved9,
-	msm_mux_mdp_vsync,
-	msm_mux_qup_l6,
-	msm_mux_wlan2_adc1,
-	msm_mux_atest_usb11,
-	msm_mux_ddr_pxi2,
-	msm_mux_reserved10,
-	msm_mux_edp_lcd,
-	msm_mux_dbg_out,
-	msm_mux_wlan2_adc0,
-	msm_mux_atest_usb10,
-	msm_mux_reserved11,
-	msm_mux_m_voc,
-	msm_mux_tsif1_sync,
 	msm_mux_ddr_pxi3,
-	msm_mux_reserved12,
 	msm_mux_cam_mclk,
 	msm_mux_pll_bypassnl,
 	msm_mux_qdss_gpio0,
-	msm_mux_reserved13,
 	msm_mux_pll_reset,
 	msm_mux_qdss_gpio1,
-	msm_mux_reserved14,
 	msm_mux_qdss_gpio2,
-	msm_mux_reserved15,
 	msm_mux_qdss_gpio3,
-	msm_mux_reserved16,
 	msm_mux_cci_i2c,
 	msm_mux_qup1,
 	msm_mux_qdss_gpio4,
-	msm_mux_reserved17,
 	msm_mux_qdss_gpio5,
-	msm_mux_reserved18,
 	msm_mux_qdss_gpio6,
-	msm_mux_reserved19,
 	msm_mux_qdss_gpio7,
-	msm_mux_reserved20,
 	msm_mux_cci_timer0,
 	msm_mux_gcc_gp2,
 	msm_mux_qdss_gpio8,
-	msm_mux_reserved21,
 	msm_mux_cci_timer1,
 	msm_mux_gcc_gp3,
 	msm_mux_qdss_gpio,
-	msm_mux_reserved22,
 	msm_mux_cci_timer2,
 	msm_mux_qdss_gpio9,
-	msm_mux_reserved23,
 	msm_mux_cci_timer3,
 	msm_mux_cci_async,
 	msm_mux_qdss_gpio10,
-	msm_mux_reserved24,
 	msm_mux_cci_timer4,
 	msm_mux_qdss_gpio11,
-	msm_mux_reserved25,
 	msm_mux_qdss_gpio12,
-	msm_mux_reserved26,
 	msm_mux_qup2,
 	msm_mux_qdss_gpio13,
-	msm_mux_reserved27,
 	msm_mux_qdss_gpio14,
-	msm_mux_reserved28,
 	msm_mux_phase_flag1,
 	msm_mux_qdss_gpio15,
-	msm_mux_reserved29,
 	msm_mux_phase_flag2,
-	msm_mux_reserved30,
 	msm_mux_qup11,
 	msm_mux_qup14,
-	msm_mux_reserved96,
-	msm_mux_ldo_en,
-	msm_mux_reserved97,
-	msm_mux_ldo_update,
-	msm_mux_reserved98,
-	msm_mux_phase_flag14,
-	msm_mux_reserved99,
-	msm_mux_phase_flag15,
-	msm_mux_reserved100,
-	msm_mux_reserved101,
-	msm_mux_pci_e1,
-	msm_mux_prng_rosc,
-	msm_mux_reserved102,
-	msm_mux_phase_flag5,
-	msm_mux_reserved103,
-	msm_mux_reserved104,
-	msm_mux_uim2_data,
-	msm_mux_qup13,
-	msm_mux_reserved105,
-	msm_mux_uim2_clk,
-	msm_mux_reserved106,
-	msm_mux_uim2_reset,
-	msm_mux_reserved107,
-	msm_mux_uim2_present,
-	msm_mux_reserved108,
-	msm_mux_uim1_data,
-	msm_mux_reserved109,
-	msm_mux_uim1_clk,
-	msm_mux_reserved110,
-	msm_mux_uim1_reset,
-	msm_mux_reserved111,
-	msm_mux_uim1_present,
-	msm_mux_reserved112,
-	msm_mux_uim_batt,
-	msm_mux_edp_hot,
-	msm_mux_reserved113,
-	msm_mux_nav_pps,
-	msm_mux_reserved114,
-	msm_mux_reserved115,
-	msm_mux_reserved116,
-	msm_mux_atest_char,
-	msm_mux_reserved117,
-	msm_mux_adsp_ext,
-	msm_mux_atest_char3,
-	msm_mux_reserved118,
-	msm_mux_atest_char2,
-	msm_mux_reserved119,
-	msm_mux_atest_char1,
-	msm_mux_reserved120,
-	msm_mux_atest_char0,
-	msm_mux_reserved121,
-	msm_mux_reserved122,
-	msm_mux_reserved123,
-	msm_mux_reserved124,
-	msm_mux_reserved125,
-	msm_mux_reserved126,
-	msm_mux_reserved127,
-	msm_mux_reserved128,
-	msm_mux_reserved129,
-	msm_mux_qlink_request,
-	msm_mux_reserved130,
-	msm_mux_qlink_enable,
-	msm_mux_reserved131,
-	msm_mux_reserved132,
-	msm_mux_reserved133,
-	msm_mux_reserved134,
-	msm_mux_pa_indicator,
-	msm_mux_reserved135,
-	msm_mux_reserved136,
-	msm_mux_phase_flag26,
-	msm_mux_reserved137,
-	msm_mux_phase_flag27,
-	msm_mux_reserved138,
-	msm_mux_phase_flag28,
-	msm_mux_reserved139,
-	msm_mux_phase_flag6,
-	msm_mux_reserved140,
-	msm_mux_phase_flag29,
-	msm_mux_reserved141,
-	msm_mux_phase_flag30,
-	msm_mux_reserved142,
-	msm_mux_phase_flag31,
-	msm_mux_reserved143,
-	msm_mux_mss_lte,
-	msm_mux_reserved144,
-	msm_mux_reserved145,
-	msm_mux_reserved146,
-	msm_mux_reserved147,
-	msm_mux_reserved148,
-	msm_mux_reserved149,
-	msm_mux_reserved31,
-	msm_mux_reserved32,
-	msm_mux_reserved33,
-	msm_mux_reserved34,
 	msm_mux_pci_e0,
 	msm_mux_jitter_bist,
-	msm_mux_reserved35,
 	msm_mux_pll_bist,
 	msm_mux_atest_tsens,
-	msm_mux_reserved36,
 	msm_mux_agera_pll,
-	msm_mux_reserved37,
 	msm_mux_usb_phy,
-	msm_mux_reserved38,
 	msm_mux_lpass_slimbus,
-	msm_mux_reserved39,
 	msm_mux_sd_write,
 	msm_mux_tsif1_error,
-	msm_mux_reserved40,
 	msm_mux_qup3,
-	msm_mux_reserved41,
-	msm_mux_reserved42,
-	msm_mux_reserved43,
-	msm_mux_reserved44,
 	msm_mux_qup6,
-	msm_mux_reserved45,
-	msm_mux_reserved46,
-	msm_mux_reserved47,
-	msm_mux_reserved48,
 	msm_mux_qup12,
-	msm_mux_reserved49,
-	msm_mux_reserved50,
-	msm_mux_reserved51,
 	msm_mux_phase_flag16,
-	msm_mux_reserved52,
 	msm_mux_qup10,
 	msm_mux_phase_flag11,
-	msm_mux_reserved53,
 	msm_mux_phase_flag12,
-	msm_mux_reserved54,
 	msm_mux_phase_flag13,
-	msm_mux_reserved55,
 	msm_mux_phase_flag17,
-	msm_mux_reserved56,
 	msm_mux_qua_mi2s,
 	msm_mux_gcc_gp1,
 	msm_mux_phase_flag18,
-	msm_mux_reserved57,
 	msm_mux_phase_flag19,
-	msm_mux_reserved58,
 	msm_mux_phase_flag20,
-	msm_mux_reserved59,
 	msm_mux_cri_trng0,
 	msm_mux_phase_flag21,
-	msm_mux_reserved60,
 	msm_mux_cri_trng1,
 	msm_mux_phase_flag22,
-	msm_mux_reserved61,
 	msm_mux_cri_trng,
 	msm_mux_phase_flag23,
-	msm_mux_reserved62,
 	msm_mux_phase_flag24,
-	msm_mux_reserved63,
 	msm_mux_pri_mi2s,
 	msm_mux_sp_cmu,
 	msm_mux_phase_flag25,
-	msm_mux_reserved64,
 	msm_mux_qup8,
-	msm_mux_reserved65,
 	msm_mux_pri_mi2s_ws,
-	msm_mux_reserved66,
-	msm_mux_reserved67,
-	msm_mux_reserved68,
 	msm_mux_spkr_i2s,
 	msm_mux_audio_ref,
-	msm_mux_reserved69,
-	msm_mux_reserved70,
 	msm_mux_tsense_pwm1,
 	msm_mux_tsense_pwm2,
-	msm_mux_reserved71,
-	msm_mux_reserved72,
 	msm_mux_btfm_slimbus,
 	msm_mux_atest_usb2,
-	msm_mux_reserved73,
 	msm_mux_ter_mi2s,
 	msm_mux_phase_flag7,
 	msm_mux_atest_usb23,
-	msm_mux_reserved74,
 	msm_mux_phase_flag8,
 	msm_mux_atest_usb22,
-	msm_mux_reserved75,
 	msm_mux_phase_flag9,
 	msm_mux_atest_usb21,
-	msm_mux_reserved76,
 	msm_mux_phase_flag4,
 	msm_mux_atest_usb20,
-	msm_mux_reserved77,
-	msm_mux_reserved78,
 	msm_mux_sec_mi2s,
-	msm_mux_reserved79,
-	msm_mux_reserved80,
 	msm_mux_qup15,
-	msm_mux_reserved81,
-	msm_mux_reserved82,
-	msm_mux_reserved83,
-	msm_mux_reserved84,
 	msm_mux_qup5,
-	msm_mux_reserved85,
-	msm_mux_reserved86,
-	msm_mux_reserved87,
-	msm_mux_reserved88,
 	msm_mux_tsif1_clk,
 	msm_mux_qup4,
 	msm_mux_tgu_ch3,
 	msm_mux_phase_flag10,
-	msm_mux_reserved89,
 	msm_mux_tsif1_en,
 	msm_mux_mdp_vsync0,
 	msm_mux_mdp_vsync1,
@@ -739,32 +534,552 @@
 	msm_mux_mdp_vsync3,
 	msm_mux_tgu_ch0,
 	msm_mux_phase_flag0,
-	msm_mux_reserved90,
 	msm_mux_tsif1_data,
 	msm_mux_sdc4_cmd,
 	msm_mux_tgu_ch1,
-	msm_mux_reserved91,
 	msm_mux_tsif2_error,
 	msm_mux_sdc43,
 	msm_mux_vfr_1,
 	msm_mux_tgu_ch2,
-	msm_mux_reserved92,
 	msm_mux_tsif2_clk,
 	msm_mux_sdc4_clk,
 	msm_mux_qup7,
-	msm_mux_reserved93,
 	msm_mux_tsif2_en,
 	msm_mux_sdc42,
-	msm_mux_reserved94,
 	msm_mux_tsif2_data,
 	msm_mux_sdc41,
-	msm_mux_reserved95,
 	msm_mux_tsif2_sync,
 	msm_mux_sdc40,
 	msm_mux_phase_flag3,
+	msm_mux_ldo_en,
+	msm_mux_ldo_update,
+	msm_mux_phase_flag14,
+	msm_mux_phase_flag15,
+	msm_mux_pci_e1,
+	msm_mux_prng_rosc,
+	msm_mux_phase_flag5,
+	msm_mux_uim2_data,
+	msm_mux_qup13,
+	msm_mux_uim2_clk,
+	msm_mux_uim2_reset,
+	msm_mux_uim2_present,
+	msm_mux_uim1_data,
+	msm_mux_uim1_clk,
+	msm_mux_uim1_reset,
+	msm_mux_uim1_present,
+	msm_mux_uim_batt,
+	msm_mux_edp_hot,
+	msm_mux_nav_pps,
+	msm_mux_atest_char,
+	msm_mux_adsp_ext,
+	msm_mux_atest_char3,
+	msm_mux_atest_char2,
+	msm_mux_atest_char1,
+	msm_mux_atest_char0,
+	msm_mux_qlink_request,
+	msm_mux_qlink_enable,
+	msm_mux_pa_indicator,
+	msm_mux_phase_flag26,
+	msm_mux_phase_flag27,
+	msm_mux_phase_flag28,
+	msm_mux_phase_flag6,
+	msm_mux_phase_flag29,
+	msm_mux_phase_flag30,
+	msm_mux_phase_flag31,
+	msm_mux_mss_lte,
+	msm_mux_qup0,
+	msm_mux_gpio,
+	msm_mux_qup9,
+	msm_mux_qdss_cti,
+	msm_mux_ddr_pxi0,
+	msm_mux_ddr_bist,
+	msm_mux_atest_tsens2,
+	msm_mux_vsense_trigger,
+	msm_mux_atest_usb1,
+	msm_mux_qup_l4,
+	msm_mux_wlan1_adc1,
+	msm_mux_atest_usb13,
+	msm_mux_ddr_pxi1,
+	msm_mux_qup_l5,
+	msm_mux_wlan1_adc0,
+	msm_mux_atest_usb12,
+	msm_mux_mdp_vsync,
+	msm_mux_qup_l6,
+	msm_mux_wlan2_adc1,
+	msm_mux_atest_usb11,
+	msm_mux_ddr_pxi2,
+	msm_mux_edp_lcd,
+	msm_mux_dbg_out,
+	msm_mux_wlan2_adc0,
+	msm_mux_atest_usb10,
+	msm_mux_m_voc,
+	msm_mux_tsif1_sync,
 	msm_mux_NA,
 };
 
+static const char * const ddr_pxi3_groups[] = {
+	"gpio12", "gpio13",
+};
+static const char * const cam_mclk_groups[] = {
+	"gpio13", "gpio14", "gpio15", "gpio16",
+};
+static const char * const pll_bypassnl_groups[] = {
+	"gpio13",
+};
+static const char * const qdss_gpio0_groups[] = {
+	"gpio13", "gpio117",
+};
+static const char * const pll_reset_groups[] = {
+	"gpio14",
+};
+static const char * const qdss_gpio1_groups[] = {
+	"gpio14", "gpio118",
+};
+static const char * const qdss_gpio2_groups[] = {
+	"gpio15", "gpio119",
+};
+static const char * const qdss_gpio3_groups[] = {
+	"gpio16", "gpio120",
+};
+static const char * const cci_i2c_groups[] = {
+	"gpio17", "gpio18", "gpio19", "gpio20",
+};
+static const char * const qup1_groups[] = {
+	"gpio17", "gpio18", "gpio19", "gpio20",
+};
+static const char * const qdss_gpio4_groups[] = {
+	"gpio17", "gpio121",
+};
+static const char * const qdss_gpio5_groups[] = {
+	"gpio18", "gpio122",
+};
+static const char * const qdss_gpio6_groups[] = {
+	"gpio19", "gpio41",
+};
+static const char * const qdss_gpio7_groups[] = {
+	"gpio20", "gpio42",
+};
+static const char * const cci_timer0_groups[] = {
+	"gpio21",
+};
+static const char * const gcc_gp2_groups[] = {
+	"gpio21", "gpio58",
+};
+static const char * const qdss_gpio8_groups[] = {
+	"gpio21", "gpio75",
+};
+static const char * const cci_timer1_groups[] = {
+	"gpio22",
+};
+static const char * const gcc_gp3_groups[] = {
+	"gpio22", "gpio59",
+};
+static const char * const qdss_gpio_groups[] = {
+	"gpio22", "gpio30", "gpio123", "gpio124",
+};
+static const char * const cci_timer2_groups[] = {
+	"gpio23",
+};
+static const char * const qdss_gpio9_groups[] = {
+	"gpio23", "gpio76",
+};
+static const char * const cci_timer3_groups[] = {
+	"gpio24",
+};
+static const char * const cci_async_groups[] = {
+	"gpio24", "gpio25", "gpio26",
+};
+static const char * const qdss_gpio10_groups[] = {
+	"gpio24", "gpio77",
+};
+static const char * const cci_timer4_groups[] = {
+	"gpio25",
+};
+static const char * const qdss_gpio11_groups[] = {
+	"gpio25", "gpio79",
+};
+static const char * const qdss_gpio12_groups[] = {
+	"gpio26", "gpio80",
+};
+static const char * const qup2_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30",
+};
+static const char * const qdss_gpio13_groups[] = {
+	"gpio27", "gpio93",
+};
+static const char * const qdss_gpio14_groups[] = {
+	"gpio28", "gpio43",
+};
+static const char * const phase_flag1_groups[] = {
+	"gpio29",
+};
+static const char * const qdss_gpio15_groups[] = {
+	"gpio29", "gpio44",
+};
+static const char * const phase_flag2_groups[] = {
+	"gpio30",
+};
+static const char * const qup11_groups[] = {
+	"gpio31", "gpio32", "gpio33", "gpio34",
+};
+static const char * const qup14_groups[] = {
+	"gpio31", "gpio32", "gpio33", "gpio34",
+};
+static const char * const pci_e0_groups[] = {
+	"gpio35", "gpio36",
+};
+static const char * const jitter_bist_groups[] = {
+	"gpio35",
+};
+static const char * const pll_bist_groups[] = {
+	"gpio36",
+};
+static const char * const atest_tsens_groups[] = {
+	"gpio36",
+};
+static const char * const agera_pll_groups[] = {
+	"gpio37",
+};
+static const char * const usb_phy_groups[] = {
+	"gpio38",
+};
+static const char * const lpass_slimbus_groups[] = {
+	"gpio39", "gpio70", "gpio71", "gpio72",
+};
+static const char * const sd_write_groups[] = {
+	"gpio40",
+};
+static const char * const tsif1_error_groups[] = {
+	"gpio40",
+};
+static const char * const qup3_groups[] = {
+	"gpio41", "gpio42", "gpio43", "gpio44",
+};
+static const char * const qup6_groups[] = {
+	"gpio45", "gpio46", "gpio47", "gpio48",
+};
+static const char * const qup12_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const phase_flag16_groups[] = {
+	"gpio52",
+};
+static const char * const qup10_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const phase_flag11_groups[] = {
+	"gpio53",
+};
+static const char * const phase_flag12_groups[] = {
+	"gpio54",
+};
+static const char * const phase_flag13_groups[] = {
+	"gpio55",
+};
+static const char * const phase_flag17_groups[] = {
+	"gpio56",
+};
+static const char * const qua_mi2s_groups[] = {
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+};
+static const char * const gcc_gp1_groups[] = {
+	"gpio57", "gpio78",
+};
+static const char * const phase_flag18_groups[] = {
+	"gpio57",
+};
+static const char * const phase_flag19_groups[] = {
+	"gpio58",
+};
+static const char * const phase_flag20_groups[] = {
+	"gpio59",
+};
+static const char * const cri_trng0_groups[] = {
+	"gpio60",
+};
+static const char * const phase_flag21_groups[] = {
+	"gpio60",
+};
+static const char * const cri_trng1_groups[] = {
+	"gpio61",
+};
+static const char * const phase_flag22_groups[] = {
+	"gpio61",
+};
+static const char * const cri_trng_groups[] = {
+	"gpio62",
+};
+static const char * const phase_flag23_groups[] = {
+	"gpio62",
+};
+static const char * const phase_flag24_groups[] = {
+	"gpio63",
+};
+static const char * const pri_mi2s_groups[] = {
+	"gpio64", "gpio65", "gpio67", "gpio68",
+};
+static const char * const sp_cmu_groups[] = {
+	"gpio64",
+};
+static const char * const phase_flag25_groups[] = {
+	"gpio64",
+};
+static const char * const qup8_groups[] = {
+	"gpio65", "gpio66", "gpio67", "gpio68",
+};
+static const char * const pri_mi2s_ws_groups[] = {
+	"gpio66",
+};
+static const char * const spkr_i2s_groups[] = {
+	"gpio69", "gpio70", "gpio71", "gpio72",
+};
+static const char * const audio_ref_groups[] = {
+	"gpio69",
+};
+static const char * const tsense_pwm1_groups[] = {
+	"gpio71",
+};
+static const char * const tsense_pwm2_groups[] = {
+	"gpio71",
+};
+static const char * const btfm_slimbus_groups[] = {
+	"gpio73", "gpio74",
+};
+static const char * const atest_usb2_groups[] = {
+	"gpio73",
+};
+static const char * const ter_mi2s_groups[] = {
+	"gpio74", "gpio75", "gpio76", "gpio77", "gpio78",
+};
+static const char * const phase_flag7_groups[] = {
+	"gpio74",
+};
+static const char * const atest_usb23_groups[] = {
+	"gpio74",
+};
+static const char * const phase_flag8_groups[] = {
+	"gpio75",
+};
+static const char * const atest_usb22_groups[] = {
+	"gpio75",
+};
+static const char * const phase_flag9_groups[] = {
+	"gpio76",
+};
+static const char * const atest_usb21_groups[] = {
+	"gpio76",
+};
+static const char * const phase_flag4_groups[] = {
+	"gpio77",
+};
+static const char * const atest_usb20_groups[] = {
+	"gpio77",
+};
+static const char * const sec_mi2s_groups[] = {
+	"gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+};
+static const char * const qup15_groups[] = {
+	"gpio81", "gpio82", "gpio83", "gpio84",
+};
+static const char * const qup5_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const tsif1_clk_groups[] = {
+	"gpio89",
+};
+static const char * const qup4_groups[] = {
+	"gpio89", "gpio90", "gpio91", "gpio92",
+};
+static const char * const tgu_ch3_groups[] = {
+	"gpio89",
+};
+static const char * const phase_flag10_groups[] = {
+	"gpio89",
+};
+static const char * const tsif1_en_groups[] = {
+	"gpio90",
+};
+static const char * const mdp_vsync0_groups[] = {
+	"gpio90",
+};
+static const char * const mdp_vsync1_groups[] = {
+	"gpio90",
+};
+static const char * const mdp_vsync2_groups[] = {
+	"gpio90",
+};
+static const char * const mdp_vsync3_groups[] = {
+	"gpio90",
+};
+static const char * const tgu_ch0_groups[] = {
+	"gpio90",
+};
+static const char * const phase_flag0_groups[] = {
+	"gpio90",
+};
+static const char * const tsif1_data_groups[] = {
+	"gpio91",
+};
+static const char * const sdc4_cmd_groups[] = {
+	"gpio91",
+};
+static const char * const tgu_ch1_groups[] = {
+	"gpio91",
+};
+static const char * const tsif2_error_groups[] = {
+	"gpio92",
+};
+static const char * const sdc43_groups[] = {
+	"gpio92",
+};
+static const char * const vfr_1_groups[] = {
+	"gpio92",
+};
+static const char * const tgu_ch2_groups[] = {
+	"gpio92",
+};
+static const char * const tsif2_clk_groups[] = {
+	"gpio93",
+};
+static const char * const sdc4_clk_groups[] = {
+	"gpio93",
+};
+static const char * const qup7_groups[] = {
+	"gpio93", "gpio94", "gpio95", "gpio96",
+};
+static const char * const tsif2_en_groups[] = {
+	"gpio94",
+};
+static const char * const sdc42_groups[] = {
+	"gpio94",
+};
+static const char * const tsif2_data_groups[] = {
+	"gpio95",
+};
+static const char * const sdc41_groups[] = {
+	"gpio95",
+};
+static const char * const tsif2_sync_groups[] = {
+	"gpio96",
+};
+static const char * const sdc40_groups[] = {
+	"gpio96",
+};
+static const char * const phase_flag3_groups[] = {
+	"gpio96",
+};
+static const char * const ldo_en_groups[] = {
+	"gpio97",
+};
+static const char * const ldo_update_groups[] = {
+	"gpio98",
+};
+static const char * const phase_flag14_groups[] = {
+	"gpio99",
+};
+static const char * const phase_flag15_groups[] = {
+	"gpio100",
+};
+static const char * const pci_e1_groups[] = {
+	"gpio102", "gpio103",
+};
+static const char * const prng_rosc_groups[] = {
+	"gpio102",
+};
+static const char * const phase_flag5_groups[] = {
+	"gpio103",
+};
+static const char * const uim2_data_groups[] = {
+	"gpio105",
+};
+static const char * const qup13_groups[] = {
+	"gpio105", "gpio106", "gpio107", "gpio108",
+};
+static const char * const uim2_clk_groups[] = {
+	"gpio106",
+};
+static const char * const uim2_reset_groups[] = {
+	"gpio107",
+};
+static const char * const uim2_present_groups[] = {
+	"gpio108",
+};
+static const char * const uim1_data_groups[] = {
+	"gpio109",
+};
+static const char * const uim1_clk_groups[] = {
+	"gpio110",
+};
+static const char * const uim1_reset_groups[] = {
+	"gpio111",
+};
+static const char * const uim1_present_groups[] = {
+	"gpio112",
+};
+static const char * const uim_batt_groups[] = {
+	"gpio113",
+};
+static const char * const edp_hot_groups[] = {
+	"gpio113",
+};
+static const char * const nav_pps_groups[] = {
+	"gpio114", "gpio114", "gpio115", "gpio115", "gpio128", "gpio128",
+	"gpio129", "gpio129", "gpio143", "gpio143",
+};
+static const char * const atest_char_groups[] = {
+	"gpio117",
+};
+static const char * const adsp_ext_groups[] = {
+	"gpio118",
+};
+static const char * const atest_char3_groups[] = {
+	"gpio118",
+};
+static const char * const atest_char2_groups[] = {
+	"gpio119",
+};
+static const char * const atest_char1_groups[] = {
+	"gpio120",
+};
+static const char * const atest_char0_groups[] = {
+	"gpio121",
+};
+static const char * const qlink_request_groups[] = {
+	"gpio130",
+};
+static const char * const qlink_enable_groups[] = {
+	"gpio131",
+};
+static const char * const pa_indicator_groups[] = {
+	"gpio135",
+};
+static const char * const phase_flag26_groups[] = {
+	"gpio137",
+};
+static const char * const phase_flag27_groups[] = {
+	"gpio138",
+};
+static const char * const phase_flag28_groups[] = {
+	"gpio139",
+};
+static const char * const phase_flag6_groups[] = {
+	"gpio140",
+};
+static const char * const phase_flag29_groups[] = {
+	"gpio141",
+};
+static const char * const phase_flag30_groups[] = {
+	"gpio142",
+};
+static const char * const phase_flag31_groups[] = {
+	"gpio143",
+};
+static const char * const mss_lte_groups[] = {
+	"gpio144", "gpio145",
+};
+static const char * const qup0_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
 static const char * const gpio_groups[] = {
 	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
 	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
@@ -790,21 +1105,6 @@
 	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
 	"gpio147", "gpio148", "gpio149",
 };
-static const char * const qup0_groups[] = {
-	"gpio0", "gpio1", "gpio2", "gpio3",
-};
-static const char * const reserved0_groups[] = {
-	"gpio0",
-};
-static const char * const reserved1_groups[] = {
-	"gpio1",
-};
-static const char * const reserved2_groups[] = {
-	"gpio2",
-};
-static const char * const reserved3_groups[] = {
-	"gpio3",
-};
 static const char * const qup9_groups[] = {
 	"gpio4", "gpio5", "gpio6", "gpio7",
 };
@@ -812,18 +1112,9 @@
 	"gpio4", "gpio5", "gpio51", "gpio52", "gpio62", "gpio63", "gpio90",
 	"gpio91",
 };
-static const char * const reserved4_groups[] = {
-	"gpio4",
-};
-static const char * const reserved5_groups[] = {
-	"gpio5",
-};
 static const char * const ddr_pxi0_groups[] = {
 	"gpio6", "gpio7",
 };
-static const char * const reserved6_groups[] = {
-	"gpio6",
-};
 static const char * const ddr_bist_groups[] = {
 	"gpio7", "gpio8", "gpio9", "gpio10",
 };
@@ -836,9 +1127,6 @@
 static const char * const atest_usb1_groups[] = {
 	"gpio7",
 };
-static const char * const reserved7_groups[] = {
-	"gpio7",
-};
 static const char * const qup_l4_groups[] = {
 	"gpio8", "gpio35", "gpio105", "gpio123",
 };
@@ -851,9 +1139,6 @@
 static const char * const ddr_pxi1_groups[] = {
 	"gpio8", "gpio9",
 };
-static const char * const reserved8_groups[] = {
-	"gpio8",
-};
 static const char * const qup_l5_groups[] = {
 	"gpio9", "gpio36", "gpio106", "gpio124",
 };
@@ -863,9 +1148,6 @@
 static const char * const atest_usb12_groups[] = {
 	"gpio9",
 };
-static const char * const reserved9_groups[] = {
-	"gpio9",
-};
 static const char * const mdp_vsync_groups[] = {
 	"gpio10", "gpio11", "gpio12", "gpio97", "gpio98",
 };
@@ -881,9 +1163,6 @@
 static const char * const ddr_pxi2_groups[] = {
 	"gpio10", "gpio11",
 };
-static const char * const reserved10_groups[] = {
-	"gpio10",
-};
 static const char * const edp_lcd_groups[] = {
 	"gpio11",
 };
@@ -896,1191 +1175,107 @@
 static const char * const atest_usb10_groups[] = {
 	"gpio11",
 };
-static const char * const reserved11_groups[] = {
-	"gpio11",
-};
 static const char * const m_voc_groups[] = {
 	"gpio12",
 };
 static const char * const tsif1_sync_groups[] = {
 	"gpio12",
 };
-static const char * const ddr_pxi3_groups[] = {
-	"gpio12", "gpio13",
-};
-static const char * const reserved12_groups[] = {
-	"gpio12",
-};
-static const char * const cam_mclk_groups[] = {
-	"gpio13", "gpio14", "gpio15", "gpio16",
-};
-static const char * const pll_bypassnl_groups[] = {
-	"gpio13",
-};
-static const char * const qdss_gpio0_groups[] = {
-	"gpio13", "gpio117",
-};
-static const char * const reserved13_groups[] = {
-	"gpio13",
-};
-static const char * const pll_reset_groups[] = {
-	"gpio14",
-};
-static const char * const qdss_gpio1_groups[] = {
-	"gpio14", "gpio118",
-};
-static const char * const reserved14_groups[] = {
-	"gpio14",
-};
-static const char * const qdss_gpio2_groups[] = {
-	"gpio15", "gpio119",
-};
-static const char * const reserved15_groups[] = {
-	"gpio15",
-};
-static const char * const qdss_gpio3_groups[] = {
-	"gpio16", "gpio120",
-};
-static const char * const reserved16_groups[] = {
-	"gpio16",
-};
-static const char * const cci_i2c_groups[] = {
-	"gpio17", "gpio18", "gpio19", "gpio20",
-};
-static const char * const qup1_groups[] = {
-	"gpio17", "gpio18", "gpio19", "gpio20",
-};
-static const char * const qdss_gpio4_groups[] = {
-	"gpio17", "gpio121",
-};
-static const char * const reserved17_groups[] = {
-	"gpio17",
-};
-static const char * const qdss_gpio5_groups[] = {
-	"gpio18", "gpio122",
-};
-static const char * const reserved18_groups[] = {
-	"gpio18",
-};
-static const char * const qdss_gpio6_groups[] = {
-	"gpio19", "gpio41",
-};
-static const char * const reserved19_groups[] = {
-	"gpio19",
-};
-static const char * const qdss_gpio7_groups[] = {
-	"gpio20", "gpio42",
-};
-static const char * const reserved20_groups[] = {
-	"gpio20",
-};
-static const char * const cci_timer0_groups[] = {
-	"gpio21",
-};
-static const char * const gcc_gp2_groups[] = {
-	"gpio21", "gpio58",
-};
-static const char * const qdss_gpio8_groups[] = {
-	"gpio21", "gpio75",
-};
-static const char * const reserved21_groups[] = {
-	"gpio21",
-};
-static const char * const cci_timer1_groups[] = {
-	"gpio22",
-};
-static const char * const gcc_gp3_groups[] = {
-	"gpio22", "gpio59",
-};
-static const char * const qdss_gpio_groups[] = {
-	"gpio22", "gpio30", "gpio123", "gpio124",
-};
-static const char * const reserved22_groups[] = {
-	"gpio22",
-};
-static const char * const cci_timer2_groups[] = {
-	"gpio23",
-};
-static const char * const qdss_gpio9_groups[] = {
-	"gpio23", "gpio76",
-};
-static const char * const reserved23_groups[] = {
-	"gpio23",
-};
-static const char * const cci_timer3_groups[] = {
-	"gpio24",
-};
-static const char * const cci_async_groups[] = {
-	"gpio24", "gpio25", "gpio26",
-};
-static const char * const qdss_gpio10_groups[] = {
-	"gpio24", "gpio77",
-};
-static const char * const reserved24_groups[] = {
-	"gpio24",
-};
-static const char * const cci_timer4_groups[] = {
-	"gpio25",
-};
-static const char * const qdss_gpio11_groups[] = {
-	"gpio25", "gpio79",
-};
-static const char * const reserved25_groups[] = {
-	"gpio25",
-};
-static const char * const qdss_gpio12_groups[] = {
-	"gpio26", "gpio80",
-};
-static const char * const reserved26_groups[] = {
-	"gpio26",
-};
-static const char * const qup2_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30",
-};
-static const char * const qdss_gpio13_groups[] = {
-	"gpio27", "gpio93",
-};
-static const char * const reserved27_groups[] = {
-	"gpio27",
-};
-static const char * const qdss_gpio14_groups[] = {
-	"gpio28", "gpio43",
-};
-static const char * const reserved28_groups[] = {
-	"gpio28",
-};
-static const char * const phase_flag1_groups[] = {
-	"gpio29",
-};
-static const char * const qdss_gpio15_groups[] = {
-	"gpio29", "gpio44",
-};
-static const char * const reserved29_groups[] = {
-	"gpio29",
-};
-static const char * const phase_flag2_groups[] = {
-	"gpio30",
-};
-static const char * const reserved30_groups[] = {
-	"gpio30",
-};
-static const char * const qup11_groups[] = {
-	"gpio31", "gpio32", "gpio33", "gpio34",
-};
-static const char * const qup14_groups[] = {
-	"gpio31", "gpio32", "gpio33", "gpio34",
-};
-static const char * const reserved96_groups[] = {
-	"gpio96",
-};
-static const char * const ldo_en_groups[] = {
-	"gpio97",
-};
-static const char * const reserved97_groups[] = {
-	"gpio97",
-};
-static const char * const ldo_update_groups[] = {
-	"gpio98",
-};
-static const char * const reserved98_groups[] = {
-	"gpio98",
-};
-static const char * const phase_flag14_groups[] = {
-	"gpio99",
-};
-static const char * const reserved99_groups[] = {
-	"gpio99",
-};
-static const char * const phase_flag15_groups[] = {
-	"gpio100",
-};
-static const char * const reserved100_groups[] = {
-	"gpio100",
-};
-static const char * const reserved101_groups[] = {
-	"gpio101",
-};
-static const char * const pci_e1_groups[] = {
-	"gpio102", "gpio103",
-};
-static const char * const prng_rosc_groups[] = {
-	"gpio102",
-};
-static const char * const reserved102_groups[] = {
-	"gpio102",
-};
-static const char * const phase_flag5_groups[] = {
-	"gpio103",
-};
-static const char * const reserved103_groups[] = {
-	"gpio103",
-};
-static const char * const reserved104_groups[] = {
-	"gpio104",
-};
-static const char * const uim2_data_groups[] = {
-	"gpio105",
-};
-static const char * const qup13_groups[] = {
-	"gpio105", "gpio106", "gpio107", "gpio108",
-};
-static const char * const reserved105_groups[] = {
-	"gpio105",
-};
-static const char * const uim2_clk_groups[] = {
-	"gpio106",
-};
-static const char * const reserved106_groups[] = {
-	"gpio106",
-};
-static const char * const uim2_reset_groups[] = {
-	"gpio107",
-};
-static const char * const reserved107_groups[] = {
-	"gpio107",
-};
-static const char * const uim2_present_groups[] = {
-	"gpio108",
-};
-static const char * const reserved108_groups[] = {
-	"gpio108",
-};
-static const char * const uim1_data_groups[] = {
-	"gpio109",
-};
-static const char * const reserved109_groups[] = {
-	"gpio109",
-};
-static const char * const uim1_clk_groups[] = {
-	"gpio110",
-};
-static const char * const reserved110_groups[] = {
-	"gpio110",
-};
-static const char * const uim1_reset_groups[] = {
-	"gpio111",
-};
-static const char * const reserved111_groups[] = {
-	"gpio111",
-};
-static const char * const uim1_present_groups[] = {
-	"gpio112",
-};
-static const char * const reserved112_groups[] = {
-	"gpio112",
-};
-static const char * const uim_batt_groups[] = {
-	"gpio113",
-};
-static const char * const edp_hot_groups[] = {
-	"gpio113",
-};
-static const char * const reserved113_groups[] = {
-	"gpio113",
-};
-static const char * const nav_pps_groups[] = {
-	"gpio114", "gpio114", "gpio115", "gpio115", "gpio128", "gpio128",
-	"gpio129", "gpio129", "gpio143", "gpio143",
-};
-static const char * const reserved114_groups[] = {
-	"gpio114",
-};
-static const char * const reserved115_groups[] = {
-	"gpio115",
-};
-static const char * const reserved116_groups[] = {
-	"gpio116",
-};
-static const char * const atest_char_groups[] = {
-	"gpio117",
-};
-static const char * const reserved117_groups[] = {
-	"gpio117",
-};
-static const char * const adsp_ext_groups[] = {
-	"gpio118",
-};
-static const char * const atest_char3_groups[] = {
-	"gpio118",
-};
-static const char * const reserved118_groups[] = {
-	"gpio118",
-};
-static const char * const atest_char2_groups[] = {
-	"gpio119",
-};
-static const char * const reserved119_groups[] = {
-	"gpio119",
-};
-static const char * const atest_char1_groups[] = {
-	"gpio120",
-};
-static const char * const reserved120_groups[] = {
-	"gpio120",
-};
-static const char * const atest_char0_groups[] = {
-	"gpio121",
-};
-static const char * const reserved121_groups[] = {
-	"gpio121",
-};
-static const char * const reserved122_groups[] = {
-	"gpio122",
-};
-static const char * const reserved123_groups[] = {
-	"gpio123",
-};
-static const char * const reserved124_groups[] = {
-	"gpio124",
-};
-static const char * const reserved125_groups[] = {
-	"gpio125",
-};
-static const char * const reserved126_groups[] = {
-	"gpio126",
-};
-static const char * const reserved127_groups[] = {
-	"gpio127",
-};
-static const char * const reserved128_groups[] = {
-	"gpio128",
-};
-static const char * const reserved129_groups[] = {
-	"gpio129",
-};
-static const char * const qlink_request_groups[] = {
-	"gpio130",
-};
-static const char * const reserved130_groups[] = {
-	"gpio130",
-};
-static const char * const qlink_enable_groups[] = {
-	"gpio131",
-};
-static const char * const reserved131_groups[] = {
-	"gpio131",
-};
-static const char * const reserved132_groups[] = {
-	"gpio132",
-};
-static const char * const reserved133_groups[] = {
-	"gpio133",
-};
-static const char * const reserved134_groups[] = {
-	"gpio134",
-};
-static const char * const pa_indicator_groups[] = {
-	"gpio135",
-};
-static const char * const reserved135_groups[] = {
-	"gpio135",
-};
-static const char * const reserved136_groups[] = {
-	"gpio136",
-};
-static const char * const phase_flag26_groups[] = {
-	"gpio137",
-};
-static const char * const reserved137_groups[] = {
-	"gpio137",
-};
-static const char * const phase_flag27_groups[] = {
-	"gpio138",
-};
-static const char * const reserved138_groups[] = {
-	"gpio138",
-};
-static const char * const phase_flag28_groups[] = {
-	"gpio139",
-};
-static const char * const reserved139_groups[] = {
-	"gpio139",
-};
-static const char * const phase_flag6_groups[] = {
-	"gpio140",
-};
-static const char * const reserved140_groups[] = {
-	"gpio140",
-};
-static const char * const phase_flag29_groups[] = {
-	"gpio141",
-};
-static const char * const reserved141_groups[] = {
-	"gpio141",
-};
-static const char * const phase_flag30_groups[] = {
-	"gpio142",
-};
-static const char * const reserved142_groups[] = {
-	"gpio142",
-};
-static const char * const phase_flag31_groups[] = {
-	"gpio143",
-};
-static const char * const reserved143_groups[] = {
-	"gpio143",
-};
-static const char * const mss_lte_groups[] = {
-	"gpio144", "gpio145",
-};
-static const char * const reserved144_groups[] = {
-	"gpio144",
-};
-static const char * const reserved145_groups[] = {
-	"gpio145",
-};
-static const char * const reserved146_groups[] = {
-	"gpio146",
-};
-static const char * const reserved147_groups[] = {
-	"gpio147",
-};
-static const char * const reserved148_groups[] = {
-	"gpio148",
-};
-static const char * const reserved149_groups[] = {
-	"gpio149", "gpio149",
-};
-static const char * const reserved31_groups[] = {
-	"gpio31",
-};
-static const char * const reserved32_groups[] = {
-	"gpio32",
-};
-static const char * const reserved33_groups[] = {
-	"gpio33",
-};
-static const char * const reserved34_groups[] = {
-	"gpio34",
-};
-static const char * const pci_e0_groups[] = {
-	"gpio35", "gpio36",
-};
-static const char * const jitter_bist_groups[] = {
-	"gpio35",
-};
-static const char * const reserved35_groups[] = {
-	"gpio35",
-};
-static const char * const pll_bist_groups[] = {
-	"gpio36",
-};
-static const char * const atest_tsens_groups[] = {
-	"gpio36",
-};
-static const char * const reserved36_groups[] = {
-	"gpio36",
-};
-static const char * const agera_pll_groups[] = {
-	"gpio37",
-};
-static const char * const reserved37_groups[] = {
-	"gpio37",
-};
-static const char * const usb_phy_groups[] = {
-	"gpio38",
-};
-static const char * const reserved38_groups[] = {
-	"gpio38",
-};
-static const char * const lpass_slimbus_groups[] = {
-	"gpio39", "gpio70", "gpio71", "gpio72",
-};
-static const char * const reserved39_groups[] = {
-	"gpio39",
-};
-static const char * const sd_write_groups[] = {
-	"gpio40",
-};
-static const char * const tsif1_error_groups[] = {
-	"gpio40",
-};
-static const char * const reserved40_groups[] = {
-	"gpio40",
-};
-static const char * const qup3_groups[] = {
-	"gpio41", "gpio42", "gpio43", "gpio44",
-};
-static const char * const reserved41_groups[] = {
-	"gpio41",
-};
-static const char * const reserved42_groups[] = {
-	"gpio42",
-};
-static const char * const reserved43_groups[] = {
-	"gpio43",
-};
-static const char * const reserved44_groups[] = {
-	"gpio44",
-};
-static const char * const qup6_groups[] = {
-	"gpio45", "gpio46", "gpio47", "gpio48",
-};
-static const char * const reserved45_groups[] = {
-	"gpio45",
-};
-static const char * const reserved46_groups[] = {
-	"gpio46",
-};
-static const char * const reserved47_groups[] = {
-	"gpio47",
-};
-static const char * const reserved48_groups[] = {
-	"gpio48",
-};
-static const char * const qup12_groups[] = {
-	"gpio49", "gpio50", "gpio51", "gpio52",
-};
-static const char * const reserved49_groups[] = {
-	"gpio49",
-};
-static const char * const reserved50_groups[] = {
-	"gpio50",
-};
-static const char * const reserved51_groups[] = {
-	"gpio51",
-};
-static const char * const phase_flag16_groups[] = {
-	"gpio52",
-};
-static const char * const reserved52_groups[] = {
-	"gpio52",
-};
-static const char * const qup10_groups[] = {
-	"gpio53", "gpio54", "gpio55", "gpio56",
-};
-static const char * const phase_flag11_groups[] = {
-	"gpio53",
-};
-static const char * const reserved53_groups[] = {
-	"gpio53",
-};
-static const char * const phase_flag12_groups[] = {
-	"gpio54",
-};
-static const char * const reserved54_groups[] = {
-	"gpio54",
-};
-static const char * const phase_flag13_groups[] = {
-	"gpio55",
-};
-static const char * const reserved55_groups[] = {
-	"gpio55",
-};
-static const char * const phase_flag17_groups[] = {
-	"gpio56",
-};
-static const char * const reserved56_groups[] = {
-	"gpio56",
-};
-static const char * const qua_mi2s_groups[] = {
-	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
-};
-static const char * const gcc_gp1_groups[] = {
-	"gpio57", "gpio78",
-};
-static const char * const phase_flag18_groups[] = {
-	"gpio57",
-};
-static const char * const reserved57_groups[] = {
-	"gpio57",
-};
-static const char * const phase_flag19_groups[] = {
-	"gpio58",
-};
-static const char * const reserved58_groups[] = {
-	"gpio58",
-};
-static const char * const phase_flag20_groups[] = {
-	"gpio59",
-};
-static const char * const reserved59_groups[] = {
-	"gpio59",
-};
-static const char * const cri_trng0_groups[] = {
-	"gpio60",
-};
-static const char * const phase_flag21_groups[] = {
-	"gpio60",
-};
-static const char * const reserved60_groups[] = {
-	"gpio60",
-};
-static const char * const cri_trng1_groups[] = {
-	"gpio61",
-};
-static const char * const phase_flag22_groups[] = {
-	"gpio61",
-};
-static const char * const reserved61_groups[] = {
-	"gpio61",
-};
-static const char * const cri_trng_groups[] = {
-	"gpio62",
-};
-static const char * const phase_flag23_groups[] = {
-	"gpio62",
-};
-static const char * const reserved62_groups[] = {
-	"gpio62",
-};
-static const char * const phase_flag24_groups[] = {
-	"gpio63",
-};
-static const char * const reserved63_groups[] = {
-	"gpio63",
-};
-static const char * const pri_mi2s_groups[] = {
-	"gpio64", "gpio65", "gpio67", "gpio68",
-};
-static const char * const sp_cmu_groups[] = {
-	"gpio64",
-};
-static const char * const phase_flag25_groups[] = {
-	"gpio64",
-};
-static const char * const reserved64_groups[] = {
-	"gpio64",
-};
-static const char * const qup8_groups[] = {
-	"gpio65", "gpio66", "gpio67", "gpio68",
-};
-static const char * const reserved65_groups[] = {
-	"gpio65",
-};
-static const char * const pri_mi2s_ws_groups[] = {
-	"gpio66",
-};
-static const char * const reserved66_groups[] = {
-	"gpio66",
-};
-static const char * const reserved67_groups[] = {
-	"gpio67",
-};
-static const char * const reserved68_groups[] = {
-	"gpio68",
-};
-static const char * const spkr_i2s_groups[] = {
-	"gpio69", "gpio70", "gpio71", "gpio72",
-};
-static const char * const audio_ref_groups[] = {
-	"gpio69",
-};
-static const char * const reserved69_groups[] = {
-	"gpio69",
-};
-static const char * const reserved70_groups[] = {
-	"gpio70",
-};
-static const char * const tsense_pwm1_groups[] = {
-	"gpio71",
-};
-static const char * const tsense_pwm2_groups[] = {
-	"gpio71",
-};
-static const char * const reserved71_groups[] = {
-	"gpio71",
-};
-static const char * const reserved72_groups[] = {
-	"gpio72",
-};
-static const char * const btfm_slimbus_groups[] = {
-	"gpio73", "gpio74",
-};
-static const char * const atest_usb2_groups[] = {
-	"gpio73",
-};
-static const char * const reserved73_groups[] = {
-	"gpio73",
-};
-static const char * const ter_mi2s_groups[] = {
-	"gpio74", "gpio75", "gpio76", "gpio77", "gpio78",
-};
-static const char * const phase_flag7_groups[] = {
-	"gpio74",
-};
-static const char * const atest_usb23_groups[] = {
-	"gpio74",
-};
-static const char * const reserved74_groups[] = {
-	"gpio74",
-};
-static const char * const phase_flag8_groups[] = {
-	"gpio75",
-};
-static const char * const atest_usb22_groups[] = {
-	"gpio75",
-};
-static const char * const reserved75_groups[] = {
-	"gpio75",
-};
-static const char * const phase_flag9_groups[] = {
-	"gpio76",
-};
-static const char * const atest_usb21_groups[] = {
-	"gpio76",
-};
-static const char * const reserved76_groups[] = {
-	"gpio76",
-};
-static const char * const phase_flag4_groups[] = {
-	"gpio77",
-};
-static const char * const atest_usb20_groups[] = {
-	"gpio77",
-};
-static const char * const reserved77_groups[] = {
-	"gpio77",
-};
-static const char * const reserved78_groups[] = {
-	"gpio78",
-};
-static const char * const sec_mi2s_groups[] = {
-	"gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
-};
-static const char * const reserved79_groups[] = {
-	"gpio79",
-};
-static const char * const reserved80_groups[] = {
-	"gpio80",
-};
-static const char * const qup15_groups[] = {
-	"gpio81", "gpio82", "gpio83", "gpio84",
-};
-static const char * const reserved81_groups[] = {
-	"gpio81",
-};
-static const char * const reserved82_groups[] = {
-	"gpio82",
-};
-static const char * const reserved83_groups[] = {
-	"gpio83",
-};
-static const char * const reserved84_groups[] = {
-	"gpio84",
-};
-static const char * const qup5_groups[] = {
-	"gpio85", "gpio86", "gpio87", "gpio88",
-};
-static const char * const reserved85_groups[] = {
-	"gpio85",
-};
-static const char * const reserved86_groups[] = {
-	"gpio86",
-};
-static const char * const reserved87_groups[] = {
-	"gpio87",
-};
-static const char * const reserved88_groups[] = {
-	"gpio88",
-};
-static const char * const tsif1_clk_groups[] = {
-	"gpio89",
-};
-static const char * const qup4_groups[] = {
-	"gpio89", "gpio90", "gpio91", "gpio92",
-};
-static const char * const tgu_ch3_groups[] = {
-	"gpio89",
-};
-static const char * const phase_flag10_groups[] = {
-	"gpio89",
-};
-static const char * const reserved89_groups[] = {
-	"gpio89",
-};
-static const char * const tsif1_en_groups[] = {
-	"gpio90",
-};
-static const char * const mdp_vsync0_groups[] = {
-	"gpio90",
-};
-static const char * const mdp_vsync1_groups[] = {
-	"gpio90",
-};
-static const char * const mdp_vsync2_groups[] = {
-	"gpio90",
-};
-static const char * const mdp_vsync3_groups[] = {
-	"gpio90",
-};
-static const char * const tgu_ch0_groups[] = {
-	"gpio90",
-};
-static const char * const phase_flag0_groups[] = {
-	"gpio90",
-};
-static const char * const reserved90_groups[] = {
-	"gpio90",
-};
-static const char * const tsif1_data_groups[] = {
-	"gpio91",
-};
-static const char * const sdc4_cmd_groups[] = {
-	"gpio91",
-};
-static const char * const tgu_ch1_groups[] = {
-	"gpio91",
-};
-static const char * const reserved91_groups[] = {
-	"gpio91",
-};
-static const char * const tsif2_error_groups[] = {
-	"gpio92",
-};
-static const char * const sdc43_groups[] = {
-	"gpio92",
-};
-static const char * const vfr_1_groups[] = {
-	"gpio92",
-};
-static const char * const tgu_ch2_groups[] = {
-	"gpio92",
-};
-static const char * const reserved92_groups[] = {
-	"gpio92",
-};
-static const char * const tsif2_clk_groups[] = {
-	"gpio93",
-};
-static const char * const sdc4_clk_groups[] = {
-	"gpio93",
-};
-static const char * const qup7_groups[] = {
-	"gpio93", "gpio94", "gpio95", "gpio96",
-};
-static const char * const reserved93_groups[] = {
-	"gpio93",
-};
-static const char * const tsif2_en_groups[] = {
-	"gpio94",
-};
-static const char * const sdc42_groups[] = {
-	"gpio94",
-};
-static const char * const reserved94_groups[] = {
-	"gpio94",
-};
-static const char * const tsif2_data_groups[] = {
-	"gpio95",
-};
-static const char * const sdc41_groups[] = {
-	"gpio95",
-};
-static const char * const reserved95_groups[] = {
-	"gpio95",
-};
-static const char * const tsif2_sync_groups[] = {
-	"gpio96",
-};
-static const char * const sdc40_groups[] = {
-	"gpio96",
-};
-static const char * const phase_flag3_groups[] = {
-	"gpio96",
-};
 
 static const struct msm_function sdm845_functions[] = {
-	FUNCTION(gpio),
-	FUNCTION(qup0),
-	FUNCTION(reserved0),
-	FUNCTION(reserved1),
-	FUNCTION(reserved2),
-	FUNCTION(reserved3),
-	FUNCTION(qup9),
-	FUNCTION(qdss_cti),
-	FUNCTION(reserved4),
-	FUNCTION(reserved5),
-	FUNCTION(ddr_pxi0),
-	FUNCTION(reserved6),
-	FUNCTION(ddr_bist),
-	FUNCTION(atest_tsens2),
-	FUNCTION(vsense_trigger),
-	FUNCTION(atest_usb1),
-	FUNCTION(reserved7),
-	FUNCTION(qup_l4),
-	FUNCTION(wlan1_adc1),
-	FUNCTION(atest_usb13),
-	FUNCTION(ddr_pxi1),
-	FUNCTION(reserved8),
-	FUNCTION(qup_l5),
-	FUNCTION(wlan1_adc0),
-	FUNCTION(atest_usb12),
-	FUNCTION(reserved9),
-	FUNCTION(mdp_vsync),
-	FUNCTION(qup_l6),
-	FUNCTION(wlan2_adc1),
-	FUNCTION(atest_usb11),
-	FUNCTION(ddr_pxi2),
-	FUNCTION(reserved10),
-	FUNCTION(edp_lcd),
-	FUNCTION(dbg_out),
-	FUNCTION(wlan2_adc0),
-	FUNCTION(atest_usb10),
-	FUNCTION(reserved11),
-	FUNCTION(m_voc),
-	FUNCTION(tsif1_sync),
 	FUNCTION(ddr_pxi3),
-	FUNCTION(reserved12),
 	FUNCTION(cam_mclk),
 	FUNCTION(pll_bypassnl),
 	FUNCTION(qdss_gpio0),
-	FUNCTION(reserved13),
 	FUNCTION(pll_reset),
 	FUNCTION(qdss_gpio1),
-	FUNCTION(reserved14),
 	FUNCTION(qdss_gpio2),
-	FUNCTION(reserved15),
 	FUNCTION(qdss_gpio3),
-	FUNCTION(reserved16),
 	FUNCTION(cci_i2c),
 	FUNCTION(qup1),
 	FUNCTION(qdss_gpio4),
-	FUNCTION(reserved17),
 	FUNCTION(qdss_gpio5),
-	FUNCTION(reserved18),
 	FUNCTION(qdss_gpio6),
-	FUNCTION(reserved19),
 	FUNCTION(qdss_gpio7),
-	FUNCTION(reserved20),
 	FUNCTION(cci_timer0),
 	FUNCTION(gcc_gp2),
 	FUNCTION(qdss_gpio8),
-	FUNCTION(reserved21),
 	FUNCTION(cci_timer1),
 	FUNCTION(gcc_gp3),
 	FUNCTION(qdss_gpio),
-	FUNCTION(reserved22),
 	FUNCTION(cci_timer2),
 	FUNCTION(qdss_gpio9),
-	FUNCTION(reserved23),
 	FUNCTION(cci_timer3),
 	FUNCTION(cci_async),
 	FUNCTION(qdss_gpio10),
-	FUNCTION(reserved24),
 	FUNCTION(cci_timer4),
 	FUNCTION(qdss_gpio11),
-	FUNCTION(reserved25),
 	FUNCTION(qdss_gpio12),
-	FUNCTION(reserved26),
 	FUNCTION(qup2),
 	FUNCTION(qdss_gpio13),
-	FUNCTION(reserved27),
 	FUNCTION(qdss_gpio14),
-	FUNCTION(reserved28),
 	FUNCTION(phase_flag1),
 	FUNCTION(qdss_gpio15),
-	FUNCTION(reserved29),
 	FUNCTION(phase_flag2),
-	FUNCTION(reserved30),
 	FUNCTION(qup11),
 	FUNCTION(qup14),
-	FUNCTION(reserved96),
-	FUNCTION(ldo_en),
-	FUNCTION(reserved97),
-	FUNCTION(ldo_update),
-	FUNCTION(reserved98),
-	FUNCTION(phase_flag14),
-	FUNCTION(reserved99),
-	FUNCTION(phase_flag15),
-	FUNCTION(reserved100),
-	FUNCTION(reserved101),
-	FUNCTION(pci_e1),
-	FUNCTION(prng_rosc),
-	FUNCTION(reserved102),
-	FUNCTION(phase_flag5),
-	FUNCTION(reserved103),
-	FUNCTION(reserved104),
-	FUNCTION(uim2_data),
-	FUNCTION(qup13),
-	FUNCTION(reserved105),
-	FUNCTION(uim2_clk),
-	FUNCTION(reserved106),
-	FUNCTION(uim2_reset),
-	FUNCTION(reserved107),
-	FUNCTION(uim2_present),
-	FUNCTION(reserved108),
-	FUNCTION(uim1_data),
-	FUNCTION(reserved109),
-	FUNCTION(uim1_clk),
-	FUNCTION(reserved110),
-	FUNCTION(uim1_reset),
-	FUNCTION(reserved111),
-	FUNCTION(uim1_present),
-	FUNCTION(reserved112),
-	FUNCTION(uim_batt),
-	FUNCTION(edp_hot),
-	FUNCTION(reserved113),
-	FUNCTION(nav_pps),
-	FUNCTION(reserved114),
-	FUNCTION(reserved115),
-	FUNCTION(reserved116),
-	FUNCTION(atest_char),
-	FUNCTION(reserved117),
-	FUNCTION(adsp_ext),
-	FUNCTION(atest_char3),
-	FUNCTION(reserved118),
-	FUNCTION(atest_char2),
-	FUNCTION(reserved119),
-	FUNCTION(atest_char1),
-	FUNCTION(reserved120),
-	FUNCTION(atest_char0),
-	FUNCTION(reserved121),
-	FUNCTION(reserved122),
-	FUNCTION(reserved123),
-	FUNCTION(reserved124),
-	FUNCTION(reserved125),
-	FUNCTION(reserved126),
-	FUNCTION(reserved127),
-	FUNCTION(reserved128),
-	FUNCTION(reserved129),
-	FUNCTION(qlink_request),
-	FUNCTION(reserved130),
-	FUNCTION(qlink_enable),
-	FUNCTION(reserved131),
-	FUNCTION(reserved132),
-	FUNCTION(reserved133),
-	FUNCTION(reserved134),
-	FUNCTION(pa_indicator),
-	FUNCTION(reserved135),
-	FUNCTION(reserved136),
-	FUNCTION(phase_flag26),
-	FUNCTION(reserved137),
-	FUNCTION(phase_flag27),
-	FUNCTION(reserved138),
-	FUNCTION(phase_flag28),
-	FUNCTION(reserved139),
-	FUNCTION(phase_flag6),
-	FUNCTION(reserved140),
-	FUNCTION(phase_flag29),
-	FUNCTION(reserved141),
-	FUNCTION(phase_flag30),
-	FUNCTION(reserved142),
-	FUNCTION(phase_flag31),
-	FUNCTION(reserved143),
-	FUNCTION(mss_lte),
-	FUNCTION(reserved144),
-	FUNCTION(reserved145),
-	FUNCTION(reserved146),
-	FUNCTION(reserved147),
-	FUNCTION(reserved148),
-	FUNCTION(reserved149),
-	FUNCTION(reserved31),
-	FUNCTION(reserved32),
-	FUNCTION(reserved33),
-	FUNCTION(reserved34),
 	FUNCTION(pci_e0),
 	FUNCTION(jitter_bist),
-	FUNCTION(reserved35),
 	FUNCTION(pll_bist),
 	FUNCTION(atest_tsens),
-	FUNCTION(reserved36),
 	FUNCTION(agera_pll),
-	FUNCTION(reserved37),
 	FUNCTION(usb_phy),
-	FUNCTION(reserved38),
 	FUNCTION(lpass_slimbus),
-	FUNCTION(reserved39),
 	FUNCTION(sd_write),
 	FUNCTION(tsif1_error),
-	FUNCTION(reserved40),
 	FUNCTION(qup3),
-	FUNCTION(reserved41),
-	FUNCTION(reserved42),
-	FUNCTION(reserved43),
-	FUNCTION(reserved44),
 	FUNCTION(qup6),
-	FUNCTION(reserved45),
-	FUNCTION(reserved46),
-	FUNCTION(reserved47),
-	FUNCTION(reserved48),
 	FUNCTION(qup12),
-	FUNCTION(reserved49),
-	FUNCTION(reserved50),
-	FUNCTION(reserved51),
 	FUNCTION(phase_flag16),
-	FUNCTION(reserved52),
 	FUNCTION(qup10),
 	FUNCTION(phase_flag11),
-	FUNCTION(reserved53),
 	FUNCTION(phase_flag12),
-	FUNCTION(reserved54),
 	FUNCTION(phase_flag13),
-	FUNCTION(reserved55),
 	FUNCTION(phase_flag17),
-	FUNCTION(reserved56),
 	FUNCTION(qua_mi2s),
 	FUNCTION(gcc_gp1),
 	FUNCTION(phase_flag18),
-	FUNCTION(reserved57),
 	FUNCTION(phase_flag19),
-	FUNCTION(reserved58),
 	FUNCTION(phase_flag20),
-	FUNCTION(reserved59),
 	FUNCTION(cri_trng0),
 	FUNCTION(phase_flag21),
-	FUNCTION(reserved60),
 	FUNCTION(cri_trng1),
 	FUNCTION(phase_flag22),
-	FUNCTION(reserved61),
 	FUNCTION(cri_trng),
 	FUNCTION(phase_flag23),
-	FUNCTION(reserved62),
 	FUNCTION(phase_flag24),
-	FUNCTION(reserved63),
 	FUNCTION(pri_mi2s),
 	FUNCTION(sp_cmu),
 	FUNCTION(phase_flag25),
-	FUNCTION(reserved64),
 	FUNCTION(qup8),
-	FUNCTION(reserved65),
 	FUNCTION(pri_mi2s_ws),
-	FUNCTION(reserved66),
-	FUNCTION(reserved67),
-	FUNCTION(reserved68),
 	FUNCTION(spkr_i2s),
 	FUNCTION(audio_ref),
-	FUNCTION(reserved69),
-	FUNCTION(reserved70),
 	FUNCTION(tsense_pwm1),
 	FUNCTION(tsense_pwm2),
-	FUNCTION(reserved71),
-	FUNCTION(reserved72),
 	FUNCTION(btfm_slimbus),
 	FUNCTION(atest_usb2),
-	FUNCTION(reserved73),
 	FUNCTION(ter_mi2s),
 	FUNCTION(phase_flag7),
 	FUNCTION(atest_usb23),
-	FUNCTION(reserved74),
 	FUNCTION(phase_flag8),
 	FUNCTION(atest_usb22),
-	FUNCTION(reserved75),
 	FUNCTION(phase_flag9),
 	FUNCTION(atest_usb21),
-	FUNCTION(reserved76),
 	FUNCTION(phase_flag4),
 	FUNCTION(atest_usb20),
-	FUNCTION(reserved77),
-	FUNCTION(reserved78),
 	FUNCTION(sec_mi2s),
-	FUNCTION(reserved79),
-	FUNCTION(reserved80),
 	FUNCTION(qup15),
-	FUNCTION(reserved81),
-	FUNCTION(reserved82),
-	FUNCTION(reserved83),
-	FUNCTION(reserved84),
 	FUNCTION(qup5),
-	FUNCTION(reserved85),
-	FUNCTION(reserved86),
-	FUNCTION(reserved87),
-	FUNCTION(reserved88),
 	FUNCTION(tsif1_clk),
 	FUNCTION(qup4),
 	FUNCTION(tgu_ch3),
 	FUNCTION(phase_flag10),
-	FUNCTION(reserved89),
 	FUNCTION(tsif1_en),
 	FUNCTION(mdp_vsync0),
 	FUNCTION(mdp_vsync1),
@@ -2088,293 +1283,347 @@
 	FUNCTION(mdp_vsync3),
 	FUNCTION(tgu_ch0),
 	FUNCTION(phase_flag0),
-	FUNCTION(reserved90),
 	FUNCTION(tsif1_data),
 	FUNCTION(sdc4_cmd),
 	FUNCTION(tgu_ch1),
-	FUNCTION(reserved91),
 	FUNCTION(tsif2_error),
 	FUNCTION(sdc43),
 	FUNCTION(vfr_1),
 	FUNCTION(tgu_ch2),
-	FUNCTION(reserved92),
 	FUNCTION(tsif2_clk),
 	FUNCTION(sdc4_clk),
 	FUNCTION(qup7),
-	FUNCTION(reserved93),
 	FUNCTION(tsif2_en),
 	FUNCTION(sdc42),
-	FUNCTION(reserved94),
 	FUNCTION(tsif2_data),
 	FUNCTION(sdc41),
-	FUNCTION(reserved95),
 	FUNCTION(tsif2_sync),
 	FUNCTION(sdc40),
 	FUNCTION(phase_flag3),
+	FUNCTION(ldo_en),
+	FUNCTION(ldo_update),
+	FUNCTION(phase_flag14),
+	FUNCTION(phase_flag15),
+	FUNCTION(pci_e1),
+	FUNCTION(prng_rosc),
+	FUNCTION(phase_flag5),
+	FUNCTION(uim2_data),
+	FUNCTION(qup13),
+	FUNCTION(uim2_clk),
+	FUNCTION(uim2_reset),
+	FUNCTION(uim2_present),
+	FUNCTION(uim1_data),
+	FUNCTION(uim1_clk),
+	FUNCTION(uim1_reset),
+	FUNCTION(uim1_present),
+	FUNCTION(uim_batt),
+	FUNCTION(edp_hot),
+	FUNCTION(nav_pps),
+	FUNCTION(atest_char),
+	FUNCTION(adsp_ext),
+	FUNCTION(atest_char3),
+	FUNCTION(atest_char2),
+	FUNCTION(atest_char1),
+	FUNCTION(atest_char0),
+	FUNCTION(qlink_request),
+	FUNCTION(qlink_enable),
+	FUNCTION(pa_indicator),
+	FUNCTION(phase_flag26),
+	FUNCTION(phase_flag27),
+	FUNCTION(phase_flag28),
+	FUNCTION(phase_flag6),
+	FUNCTION(phase_flag29),
+	FUNCTION(phase_flag30),
+	FUNCTION(phase_flag31),
+	FUNCTION(mss_lte),
+	FUNCTION(qup0),
+	FUNCTION(gpio),
+	FUNCTION(qup9),
+	FUNCTION(qdss_cti),
+	FUNCTION(ddr_pxi0),
+	FUNCTION(ddr_bist),
+	FUNCTION(atest_tsens2),
+	FUNCTION(vsense_trigger),
+	FUNCTION(atest_usb1),
+	FUNCTION(qup_l4),
+	FUNCTION(wlan1_adc1),
+	FUNCTION(atest_usb13),
+	FUNCTION(ddr_pxi1),
+	FUNCTION(qup_l5),
+	FUNCTION(wlan1_adc0),
+	FUNCTION(atest_usb12),
+	FUNCTION(mdp_vsync),
+	FUNCTION(qup_l6),
+	FUNCTION(wlan2_adc1),
+	FUNCTION(atest_usb11),
+	FUNCTION(ddr_pxi2),
+	FUNCTION(edp_lcd),
+	FUNCTION(dbg_out),
+	FUNCTION(wlan2_adc0),
+	FUNCTION(atest_usb10),
+	FUNCTION(m_voc),
+	FUNCTION(tsif1_sync),
 };
 
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
 static const struct msm_pingroup sdm845_groups[] = {
-	PINGROUP(0, NORTH, qup0, NA, reserved0, NA, NA, NA, NA, NA, NA),
-	PINGROUP(1, NORTH, qup0, NA, reserved1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(2, NORTH, qup0, NA, reserved2, NA, NA, NA, NA, NA, NA),
-	PINGROUP(3, NORTH, qup0, NA, reserved3, NA, NA, NA, NA, NA, NA),
-	PINGROUP(4, NORTH, qup9, qdss_cti, reserved4, NA, NA, NA, NA, NA, NA),
-	PINGROUP(5, NORTH, qup9, qdss_cti, reserved5, NA, NA, NA, NA, NA, NA),
-	PINGROUP(6, NORTH, qup9, NA, ddr_pxi0, reserved6, NA, NA, NA, NA, NA),
-	PINGROUP(7, NORTH, qup9, ddr_bist, NA, atest_tsens2, vsense_trigger,
-		 atest_usb1, ddr_pxi0, reserved7, NA),
-	PINGROUP(8, NORTH, qup_l4, NA, ddr_bist, NA, NA, wlan1_adc1,
-		 atest_usb13, ddr_pxi1, reserved8),
-	PINGROUP(9, NORTH, qup_l5, ddr_bist, NA, wlan1_adc0, atest_usb12,
-		 ddr_pxi1, reserved9, NA, NA),
-	PINGROUP(10, NORTH, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1,
-		 atest_usb11, ddr_pxi2, reserved10, NA, NA),
-	PINGROUP(11, NORTH, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0,
-		 atest_usb10, ddr_pxi2, reserved11, NA, NA),
-	PINGROUP(12, SOUTH, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, reserved12,
-		 NA, NA, NA, NA),
-	PINGROUP(13, SOUTH, cam_mclk, pll_bypassnl, qdss_gpio0, ddr_pxi3,
-		 reserved13, NA, NA, NA, NA),
-	PINGROUP(14, SOUTH, cam_mclk, pll_reset, qdss_gpio1, reserved14, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(15, SOUTH, cam_mclk, qdss_gpio2, reserved15, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(16, SOUTH, cam_mclk, qdss_gpio3, reserved16, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(17, SOUTH, cci_i2c, qup1, qdss_gpio4, reserved17, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(18, SOUTH, cci_i2c, qup1, NA, qdss_gpio5, reserved18, NA, NA,
-		 NA, NA),
-	PINGROUP(19, SOUTH, cci_i2c, qup1, NA, qdss_gpio6, reserved19, NA, NA,
-		 NA, NA),
-	PINGROUP(20, SOUTH, cci_i2c, qup1, NA, qdss_gpio7, reserved20, NA, NA,
-		 NA, NA),
-	PINGROUP(21, SOUTH, cci_timer0, gcc_gp2, qdss_gpio8, reserved21, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(22, SOUTH, cci_timer1, gcc_gp3, qdss_gpio, reserved22, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(23, SOUTH, cci_timer2, qdss_gpio9, reserved23, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(24, SOUTH, cci_timer3, cci_async, qdss_gpio10, reserved24, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(25, SOUTH, cci_timer4, cci_async, qdss_gpio11, reserved25, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(26, SOUTH, cci_async, qdss_gpio12, reserved26, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(27, NORTH, qup2, qdss_gpio13, reserved27, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(28, NORTH, qup2, qdss_gpio14, reserved28, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(29, NORTH, qup2, NA, phase_flag1, qdss_gpio15, reserved29, NA,
-		 NA, NA, NA),
-	PINGROUP(30, NORTH, qup2, phase_flag2, qdss_gpio, reserved30, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(31, NORTH, qup11, qup14, reserved31, NA, NA, NA, NA, NA, NA),
-	PINGROUP(32, NORTH, qup11, qup14, NA, reserved32, NA, NA, NA, NA, NA),
-	PINGROUP(33, NORTH, qup11, qup14, NA, reserved33, NA, NA, NA, NA, NA),
-	PINGROUP(34, NORTH, qup11, qup14, NA, reserved34, NA, NA, NA, NA, NA),
-	PINGROUP(35, SOUTH, pci_e0, qup_l4, jitter_bist, NA, reserved35, NA,
-		 NA, NA, NA),
-	PINGROUP(36, SOUTH, pci_e0, qup_l5, pll_bist, NA, atest_tsens,
-		 reserved36, NA, NA, NA),
-	PINGROUP(37, SOUTH, qup_l6, agera_pll, NA, reserved37, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(38, NORTH, usb_phy, NA, reserved38, NA, NA, NA, NA, NA, NA),
-	PINGROUP(39, NORTH, lpass_slimbus, NA, reserved39, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(40, SOUTH, sd_write, tsif1_error, NA, reserved40, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(41, SOUTH, qup3, NA, qdss_gpio6, reserved41, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(42, SOUTH, qup3, NA, qdss_gpio7, reserved42, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(43, SOUTH, qup3, NA, qdss_gpio14, reserved43, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(44, SOUTH, qup3, NA, qdss_gpio15, reserved44, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(45, NORTH, qup6, NA, reserved45, NA, NA, NA, NA, NA, NA),
-	PINGROUP(46, NORTH, qup6, NA, reserved46, NA, NA, NA, NA, NA, NA),
-	PINGROUP(47, NORTH, qup6, reserved47, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(48, NORTH, qup6, reserved48, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(49, NORTH, qup12, reserved49, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(50, NORTH, qup12, reserved50, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(51, NORTH, qup12, qdss_cti, reserved51, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(52, NORTH, qup12, phase_flag16, qdss_cti, reserved52, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(53, NORTH, qup10, phase_flag11, reserved53, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(54, NORTH, qup10, NA, phase_flag12, reserved54, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(55, NORTH, qup10, phase_flag13, reserved55, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(56, NORTH, qup10, phase_flag17, reserved56, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(57, NORTH, qua_mi2s, gcc_gp1, phase_flag18, reserved57, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(58, NORTH, qua_mi2s, gcc_gp2, phase_flag19, reserved58, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(59, NORTH, qua_mi2s, gcc_gp3, phase_flag20, reserved59, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(60, NORTH, qua_mi2s, cri_trng0, phase_flag21, reserved60, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(61, NORTH, qua_mi2s, cri_trng1, phase_flag22, reserved61, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(62, NORTH, qua_mi2s, cri_trng, phase_flag23, qdss_cti,
-		 reserved62, NA, NA, NA, NA),
-	PINGROUP(63, NORTH, qua_mi2s, NA, phase_flag24, qdss_cti, reserved63,
-		 NA, NA, NA, NA),
-	PINGROUP(64, NORTH, pri_mi2s, sp_cmu, phase_flag25, reserved64, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(65, NORTH, pri_mi2s, qup8, reserved65, NA, NA, NA, NA, NA, NA),
-	PINGROUP(66, NORTH, pri_mi2s_ws, qup8, reserved66, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(67, NORTH, pri_mi2s, qup8, reserved67, NA, NA, NA, NA, NA, NA),
-	PINGROUP(68, NORTH, pri_mi2s, qup8, reserved68, NA, NA, NA, NA, NA, NA),
-	PINGROUP(69, NORTH, spkr_i2s, audio_ref, reserved69, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(70, NORTH, lpass_slimbus, spkr_i2s, reserved70, NA, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(71, NORTH, lpass_slimbus, spkr_i2s, tsense_pwm1, tsense_pwm2,
-		 reserved71, NA, NA, NA, NA),
-	PINGROUP(72, NORTH, lpass_slimbus, spkr_i2s, reserved72, NA, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(73, NORTH, btfm_slimbus, atest_usb2, reserved73, NA, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(74, NORTH, btfm_slimbus, ter_mi2s, phase_flag7, atest_usb23,
-		 reserved74, NA, NA, NA, NA),
-	PINGROUP(75, NORTH, ter_mi2s, phase_flag8, qdss_gpio8, atest_usb22,
-		 reserved75, NA, NA, NA, NA),
-	PINGROUP(76, NORTH, ter_mi2s, phase_flag9, qdss_gpio9, atest_usb21,
-		 reserved76, NA, NA, NA, NA),
-	PINGROUP(77, NORTH, ter_mi2s, phase_flag4, qdss_gpio10, atest_usb20,
-		 reserved77, NA, NA, NA, NA),
-	PINGROUP(78, NORTH, ter_mi2s, gcc_gp1, reserved78, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(79, NORTH, sec_mi2s, NA, NA, qdss_gpio11, reserved79, NA, NA,
-		 NA, NA),
-	PINGROUP(80, NORTH, sec_mi2s, NA, qdss_gpio12, reserved80, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(81, NORTH, sec_mi2s, qup15, NA, reserved81, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(82, NORTH, sec_mi2s, qup15, NA, reserved82, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(83, NORTH, sec_mi2s, qup15, NA, reserved83, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(84, NORTH, qup15, NA, reserved84, NA, NA, NA, NA, NA, NA),
-	PINGROUP(85, SOUTH, qup5, NA, reserved85, NA, NA, NA, NA, NA, NA),
-	PINGROUP(86, SOUTH, qup5, NA, NA, reserved86, NA, NA, NA, NA, NA),
-	PINGROUP(87, SOUTH, qup5, NA, reserved87, NA, NA, NA, NA, NA, NA),
-	PINGROUP(88, SOUTH, qup5, NA, reserved88, NA, NA, NA, NA, NA, NA),
-	PINGROUP(89, SOUTH, tsif1_clk, qup4, tgu_ch3, phase_flag10, reserved89,
-		 NA, NA, NA, NA),
-	PINGROUP(90, SOUTH, tsif1_en, mdp_vsync0, qup4, mdp_vsync1, mdp_vsync2,
-		 mdp_vsync3, tgu_ch0, phase_flag0, qdss_cti),
-	PINGROUP(91, SOUTH, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA, qdss_cti,
-		 reserved91, NA, NA),
-	PINGROUP(92, SOUTH, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2, NA,
-		 reserved92, NA, NA),
-	PINGROUP(93, SOUTH, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13,
-		 reserved93, NA, NA, NA),
-	PINGROUP(94, SOUTH, tsif2_en, sdc42, qup7, NA, reserved94, NA, NA, NA,
-		 NA),
-	PINGROUP(95, SOUTH, tsif2_data, sdc41, qup7, NA, NA, reserved95, NA,
-		 NA, NA),
-	PINGROUP(96, SOUTH, tsif2_sync, sdc40, qup7, phase_flag3, reserved96,
-		 NA, NA, NA, NA),
-	PINGROUP(97, NORTH, NA, NA, mdp_vsync, ldo_en, reserved97, NA, NA, NA,
-		 NA),
-	PINGROUP(98, NORTH, NA, mdp_vsync, ldo_update, reserved98, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(99, NORTH, phase_flag14, reserved99, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(100, NORTH, phase_flag15, reserved100, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(101, NORTH, NA, reserved101, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(102, NORTH, pci_e1, prng_rosc, reserved102, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(103, NORTH, pci_e1, phase_flag5, reserved103, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(104, NORTH, NA, reserved104, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(105, NORTH, uim2_data, qup13, qup_l4, NA, reserved105, NA, NA,
-		 NA, NA),
-	PINGROUP(106, NORTH, uim2_clk, qup13, qup_l5, NA, reserved106, NA, NA,
-		 NA, NA),
-	PINGROUP(107, NORTH, uim2_reset, qup13, qup_l6, reserved107, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(108, NORTH, uim2_present, qup13, reserved108, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(109, NORTH, uim1_data, reserved109, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(110, NORTH, uim1_clk, reserved110, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(111, NORTH, uim1_reset, reserved111, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(112, NORTH, uim1_present, reserved112, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(113, NORTH, uim_batt, edp_hot, reserved113, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(114, NORTH, NA, nav_pps, nav_pps, NA, NA, reserved114, NA, NA,
-		 NA),
-	PINGROUP(115, NORTH, NA, nav_pps, nav_pps, NA, NA, reserved115, NA, NA,
-		 NA),
-	PINGROUP(116, NORTH, NA, reserved116, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(117, NORTH, NA, qdss_gpio0, atest_char, reserved117, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(118, NORTH, adsp_ext, NA, qdss_gpio1, atest_char3,
-		 reserved118, NA, NA, NA, NA),
-	PINGROUP(119, NORTH, NA, qdss_gpio2, atest_char2, reserved119, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(120, NORTH, NA, qdss_gpio3, atest_char1, reserved120, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(121, NORTH, NA, qdss_gpio4, atest_char0, reserved121, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(122, NORTH, NA, qdss_gpio5, reserved122, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(123, NORTH, qup_l4, NA, qdss_gpio, reserved123, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(124, NORTH, qup_l5, NA, qdss_gpio, reserved124, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(125, NORTH, qup_l6, NA, reserved125, NA, NA, NA, NA, NA, NA),
-	PINGROUP(126, NORTH, NA, reserved126, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(127, NORTH, NA, reserved127, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(128, NORTH, nav_pps, nav_pps, NA, NA, reserved128, NA, NA, NA,
-		 NA),
-	PINGROUP(129, NORTH, nav_pps, nav_pps, NA, NA, reserved129, NA, NA, NA,
-		 NA),
-	PINGROUP(130, NORTH, qlink_request, NA, reserved130, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(131, NORTH, qlink_enable, NA, reserved131, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(132, NORTH, NA, NA, reserved132, NA, NA, NA, NA, NA, NA),
-	PINGROUP(133, NORTH, NA, reserved133, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(134, NORTH, NA, reserved134, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(135, NORTH, NA, pa_indicator, NA, reserved135, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(136, NORTH, NA, reserved136, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(137, NORTH, NA, NA, phase_flag26, reserved137, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(138, NORTH, NA, NA, phase_flag27, reserved138, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(139, NORTH, NA, phase_flag28, reserved139, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(140, NORTH, NA, NA, phase_flag6, reserved140, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(141, NORTH, NA, phase_flag29, reserved141, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(142, NORTH, NA, phase_flag30, reserved142, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(143, NORTH, NA, nav_pps, nav_pps, NA, phase_flag31,
-		 reserved143, NA, NA, NA),
-	PINGROUP(144, NORTH, mss_lte, reserved144, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(145, NORTH, mss_lte, NA, reserved145, NA, NA, NA, NA, NA, NA),
-	PINGROUP(146, NORTH, NA, NA, reserved146, NA, NA, NA, NA, NA, NA),
-	PINGROUP(147, NORTH, NA, NA, reserved147, NA, NA, NA, NA, NA, NA),
-	PINGROUP(148, NORTH, NA, reserved148, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(149, NORTH, NA, reserved149, NA, NA, NA, NA, NA, NA, NA),
-	SDC_QDSD_PINGROUP(sdc2_clk, 0x99a000, 14, 6),
-	SDC_QDSD_PINGROUP(sdc2_cmd, 0x99a000, 11, 3),
-	SDC_QDSD_PINGROUP(sdc2_data, 0x99a000, 9, 0),
-	UFS_RESET(ufs_reset, 0x99f000),
+	[0] = PINGROUP(0, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[1] = PINGROUP(1, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[2] = PINGROUP(2, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[3] = PINGROUP(3, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[4] = PINGROUP(4, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[5] = PINGROUP(5, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[6] = PINGROUP(6, qup9, NA, ddr_pxi0, NA, NA, NA, NA, NA, NA),
+	[7] = PINGROUP(7, qup9, ddr_bist, NA, atest_tsens2,
+		       vsense_trigger, atest_usb1, ddr_pxi0, NA, NA),
+	[8] = PINGROUP(8, qup_l4, NA, ddr_bist, NA, NA, wlan1_adc1,
+		       atest_usb13, ddr_pxi1, NA),
+	[9] = PINGROUP(9, qup_l5, ddr_bist, NA, wlan1_adc0, atest_usb12,
+		       ddr_pxi1, NA, NA, NA),
+	[10] = PINGROUP(10, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1,
+			atest_usb11, ddr_pxi2, NA, NA, NA),
+	[11] = PINGROUP(11, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0,
+			atest_usb10, ddr_pxi2, NA, NA, NA),
+	[12] = PINGROUP(12, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, NA,
+			NA, NA, NA, NA),
+	[13] = PINGROUP(13, cam_mclk, pll_bypassnl, qdss_gpio0,
+			ddr_pxi3, NA, NA, NA, NA, NA),
+	[14] = PINGROUP(14, cam_mclk, pll_reset, qdss_gpio1, NA, NA, NA,
+			NA, NA, NA),
+	[15] = PINGROUP(15, cam_mclk, qdss_gpio2, NA, NA, NA, NA, NA,
+			NA, NA),
+	[16] = PINGROUP(16, cam_mclk, qdss_gpio3, NA, NA, NA, NA, NA,
+			NA, NA),
+	[17] = PINGROUP(17, cci_i2c, qup1, qdss_gpio4, NA, NA, NA, NA,
+			NA, NA),
+	[18] = PINGROUP(18, cci_i2c, qup1, NA, qdss_gpio5, NA, NA, NA,
+			NA, NA),
+	[19] = PINGROUP(19, cci_i2c, qup1, NA, qdss_gpio6, NA, NA, NA,
+			NA, NA),
+	[20] = PINGROUP(20, cci_i2c, qup1, NA, qdss_gpio7, NA, NA, NA,
+			NA, NA),
+	[21] = PINGROUP(21, cci_timer0, gcc_gp2, qdss_gpio8, NA, NA, NA,
+			NA, NA, NA),
+	[22] = PINGROUP(22, cci_timer1, gcc_gp3, qdss_gpio, NA, NA, NA,
+			NA, NA, NA),
+	[23] = PINGROUP(23, cci_timer2, qdss_gpio9, NA, NA, NA, NA, NA,
+			NA, NA),
+	[24] = PINGROUP(24, cci_timer3, cci_async, qdss_gpio10, NA, NA,
+			NA, NA, NA, NA),
+	[25] = PINGROUP(25, cci_timer4, cci_async, qdss_gpio11, NA, NA,
+			NA, NA, NA, NA),
+	[26] = PINGROUP(26, cci_async, qdss_gpio12, NA, NA, NA, NA, NA,
+			NA, NA),
+	[27] = PINGROUP(27, qup2, qdss_gpio13, NA, NA, NA, NA, NA, NA,
+			NA),
+	[28] = PINGROUP(28, qup2, qdss_gpio14, NA, NA, NA, NA, NA, NA,
+			NA),
+	[29] = PINGROUP(29, qup2, NA, phase_flag1, qdss_gpio15, NA, NA,
+			NA, NA, NA),
+	[30] = PINGROUP(30, qup2, phase_flag2, qdss_gpio, NA, NA, NA, NA,
+			NA, NA),
+	[31] = PINGROUP(31, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[32] = PINGROUP(32, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[33] = PINGROUP(33, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[34] = PINGROUP(34, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[35] = PINGROUP(35, pci_e0, qup_l4, jitter_bist, NA, NA, NA, NA,
+			NA, NA),
+	[36] = PINGROUP(36, pci_e0, qup_l5, pll_bist, NA, atest_tsens,
+			NA, NA, NA, NA),
+	[37] = PINGROUP(37, qup_l6, agera_pll, NA, NA, NA, NA, NA, NA,
+			NA),
+	[38] = PINGROUP(38, usb_phy, NA, NA, NA, NA, NA, NA, NA, NA),
+	[39] = PINGROUP(39, lpass_slimbus, NA, NA, NA, NA, NA, NA, NA,
+			NA),
+	[40] = PINGROUP(40, sd_write, tsif1_error, NA, NA, NA, NA, NA,
+			NA, NA),
+	[41] = PINGROUP(41, qup3, NA, qdss_gpio6, NA, NA, NA, NA, NA, NA),
+	[42] = PINGROUP(42, qup3, NA, qdss_gpio7, NA, NA, NA, NA, NA, NA),
+	[43] = PINGROUP(43, qup3, NA, qdss_gpio14, NA, NA, NA, NA, NA,
+			NA),
+	[44] = PINGROUP(44, qup3, NA, qdss_gpio15, NA, NA, NA, NA, NA,
+			NA),
+	[45] = PINGROUP(45, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[46] = PINGROUP(46, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[47] = PINGROUP(47, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[48] = PINGROUP(48, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[49] = PINGROUP(49, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[50] = PINGROUP(50, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[51] = PINGROUP(51, qup12, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[52] = PINGROUP(52, qup12, phase_flag16, qdss_cti, NA, NA, NA,
+			NA, NA, NA),
+	[53] = PINGROUP(53, qup10, phase_flag11, NA, NA, NA, NA, NA, NA,
+			NA),
+	[54] = PINGROUP(54, qup10, NA, phase_flag12, NA, NA, NA, NA, NA,
+			NA),
+	[55] = PINGROUP(55, qup10, phase_flag13, NA, NA, NA, NA, NA, NA,
+			NA),
+	[56] = PINGROUP(56, qup10, phase_flag17, NA, NA, NA, NA, NA, NA,
+			NA),
+	[57] = PINGROUP(57, qua_mi2s, gcc_gp1, phase_flag18, NA, NA, NA,
+			NA, NA, NA),
+	[58] = PINGROUP(58, qua_mi2s, gcc_gp2, phase_flag19, NA, NA, NA,
+			NA, NA, NA),
+	[59] = PINGROUP(59, qua_mi2s, gcc_gp3, phase_flag20, NA, NA, NA,
+			NA, NA, NA),
+	[60] = PINGROUP(60, qua_mi2s, cri_trng0, phase_flag21, NA, NA,
+			NA, NA, NA, NA),
+	[61] = PINGROUP(61, qua_mi2s, cri_trng1, phase_flag22, NA, NA,
+			NA, NA, NA, NA),
+	[62] = PINGROUP(62, qua_mi2s, cri_trng, phase_flag23, qdss_cti,
+			NA, NA, NA, NA, NA),
+	[63] = PINGROUP(63, qua_mi2s, NA, phase_flag24, qdss_cti, NA,
+			NA, NA, NA, NA),
+	[64] = PINGROUP(64, pri_mi2s, sp_cmu, phase_flag25, NA, NA, NA,
+			NA, NA, NA),
+	[65] = PINGROUP(65, pri_mi2s, qup8, NA, NA, NA, NA, NA, NA, NA),
+	[66] = PINGROUP(66, pri_mi2s_ws, qup8, NA, NA, NA, NA, NA, NA,
+			NA),
+	[67] = PINGROUP(67, pri_mi2s, qup8, NA, NA, NA, NA, NA, NA, NA),
+	[68] = PINGROUP(68, pri_mi2s, qup8, NA, NA, NA, NA, NA, NA, NA),
+	[69] = PINGROUP(69, spkr_i2s, audio_ref, NA, NA, NA, NA, NA, NA,
+			NA),
+	[70] = PINGROUP(70, lpass_slimbus, spkr_i2s, NA, NA, NA, NA, NA,
+			NA, NA),
+	[71] = PINGROUP(71, lpass_slimbus, spkr_i2s, tsense_pwm1,
+			tsense_pwm2, NA, NA, NA, NA, NA),
+	[72] = PINGROUP(72, lpass_slimbus, spkr_i2s, NA, NA, NA, NA, NA,
+			NA, NA),
+	[73] = PINGROUP(73, btfm_slimbus, atest_usb2, NA, NA, NA, NA, NA,
+			NA, NA),
+	[74] = PINGROUP(74, btfm_slimbus, ter_mi2s, phase_flag7,
+			atest_usb23, NA, NA, NA, NA, NA),
+	[75] = PINGROUP(75, ter_mi2s, phase_flag8, qdss_gpio8,
+			atest_usb22, NA, NA, NA, NA, NA),
+	[76] = PINGROUP(76, ter_mi2s, phase_flag9, qdss_gpio9,
+			atest_usb21, NA, NA, NA, NA, NA),
+	[77] = PINGROUP(77, ter_mi2s, phase_flag4, qdss_gpio10,
+			atest_usb20, NA, NA, NA, NA, NA),
+	[78] = PINGROUP(78, ter_mi2s, gcc_gp1, NA, NA, NA, NA, NA, NA,
+			NA),
+	[79] = PINGROUP(79, sec_mi2s, NA, NA, qdss_gpio11, NA, NA, NA,
+			NA, NA),
+	[80] = PINGROUP(80, sec_mi2s, NA, qdss_gpio12, NA, NA, NA, NA,
+			NA, NA),
+	[81] = PINGROUP(81, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[82] = PINGROUP(82, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[83] = PINGROUP(83, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[84] = PINGROUP(84, qup15, NA, NA, NA, NA, NA, NA, NA, NA),
+	[85] = PINGROUP(85, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[86] = PINGROUP(86, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[87] = PINGROUP(87, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[88] = PINGROUP(88, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[89] = PINGROUP(89, tsif1_clk, qup4, tgu_ch3, phase_flag10, NA,
+			NA, NA, NA, NA),
+	[90] = PINGROUP(90, tsif1_en, mdp_vsync0, qup4, mdp_vsync1,
+			mdp_vsync2, mdp_vsync3, tgu_ch0, phase_flag0, qdss_cti),
+	[91] = PINGROUP(91, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA,
+			qdss_cti, NA, NA, NA),
+	[92] = PINGROUP(92, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2,
+			NA, NA, NA, NA),
+	[93] = PINGROUP(93, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13,
+			NA, NA, NA, NA),
+	[94] = PINGROUP(94, tsif2_en, sdc42, qup7, NA, NA, NA, NA, NA,
+			NA),
+	[95] = PINGROUP(95, tsif2_data, sdc41, qup7, NA, NA, NA, NA, NA,
+			NA),
+	[96] = PINGROUP(96, tsif2_sync, sdc40, qup7, phase_flag3, NA,
+			NA, NA, NA, NA),
+	[97] = PINGROUP(97, NA, NA, mdp_vsync, ldo_en, NA, NA, NA, NA,
+			NA),
+	[98] = PINGROUP(98, NA, mdp_vsync, ldo_update, NA, NA, NA, NA,
+			NA, NA),
+	[99] = PINGROUP(99, phase_flag14, NA, NA, NA, NA, NA, NA, NA,
+			NA),
+	[100] = PINGROUP(100, phase_flag15, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[101] = PINGROUP(101, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[102] = PINGROUP(102, pci_e1, prng_rosc, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[103] = PINGROUP(103, pci_e1, phase_flag5, NA, NA, NA, NA, NA,
+			 NA, NA),
+	[104] = PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[105] = PINGROUP(105, uim2_data, qup13, qup_l4, NA, NA, NA, NA,
+			 NA, NA),
+	[106] = PINGROUP(106, uim2_clk, qup13, qup_l5, NA, NA, NA, NA,
+			 NA, NA),
+	[107] = PINGROUP(107, uim2_reset, qup13, qup_l6, NA, NA, NA, NA,
+			 NA, NA),
+	[108] = PINGROUP(108, uim2_present, qup13, NA, NA, NA, NA, NA,
+			 NA, NA),
+	[109] = PINGROUP(109, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	[110] = PINGROUP(110, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	[111] = PINGROUP(111, uim1_reset, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[112] = PINGROUP(112, uim1_present, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[113] = PINGROUP(113, uim_batt, edp_hot, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[114] = PINGROUP(114, NA, nav_pps, nav_pps, NA, NA, NA, NA, NA,
+			 NA),
+	[115] = PINGROUP(115, NA, nav_pps, nav_pps, NA, NA, NA, NA, NA,
+			 NA),
+	[116] = PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[117] = PINGROUP(117, NA, qdss_gpio0, atest_char, NA, NA, NA,
+			 NA, NA, NA),
+	[118] = PINGROUP(118, adsp_ext, NA, qdss_gpio1, atest_char3, NA,
+			 NA, NA, NA, NA),
+	[119] = PINGROUP(119, NA, qdss_gpio2, atest_char2, NA, NA, NA,
+			 NA, NA, NA),
+	[120] = PINGROUP(120, NA, qdss_gpio3, atest_char1, NA, NA, NA,
+			 NA, NA, NA),
+	[121] = PINGROUP(121, NA, qdss_gpio4, atest_char0, NA, NA, NA,
+			 NA, NA, NA),
+	[122] = PINGROUP(122, NA, qdss_gpio5, NA, NA, NA, NA, NA, NA, NA),
+	[123] = PINGROUP(123, qup_l4, NA, qdss_gpio, NA, NA, NA, NA, NA,
+			 NA),
+	[124] = PINGROUP(124, qup_l5, NA, qdss_gpio, NA, NA, NA, NA, NA,
+			 NA),
+	[125] = PINGROUP(125, qup_l6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[126] = PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[127] = PINGROUP(127, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[128] = PINGROUP(128, nav_pps, nav_pps, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[129] = PINGROUP(129, nav_pps, nav_pps, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[130] = PINGROUP(130, qlink_request, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[131] = PINGROUP(131, qlink_enable, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[132] = PINGROUP(132, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[133] = PINGROUP(133, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[134] = PINGROUP(134, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[135] = PINGROUP(135, NA, pa_indicator, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[136] = PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[137] = PINGROUP(137, NA, NA, phase_flag26, NA, NA, NA, NA, NA,
+			 NA),
+	[138] = PINGROUP(138, NA, NA, phase_flag27, NA, NA, NA, NA, NA,
+			 NA),
+	[139] = PINGROUP(139, NA, phase_flag28, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[140] = PINGROUP(140, NA, NA, phase_flag6, NA, NA, NA, NA, NA,
+			 NA),
+	[141] = PINGROUP(141, NA, phase_flag29, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[142] = PINGROUP(142, NA, phase_flag30, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[143] = PINGROUP(143, NA, nav_pps, nav_pps, NA, phase_flag31,
+			 NA, NA, NA, NA),
+	[144] = PINGROUP(144, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA),
+	[145] = PINGROUP(145, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA),
+	[146] = PINGROUP(146, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[147] = PINGROUP(147, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[148] = PINGROUP(148, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[149] = PINGROUP(149, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[150] = SDC_QDSD_PINGROUP(sdc2_clk, 0x99a000, 14, 6),
+	[151] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x99a000, 11, 3),
+	[152] = SDC_QDSD_PINGROUP(sdc2_data, 0x99a000, 9, 0),
+	[153] = UFS_RESET(ufs_reset, 0x99f000),
 };
 
 static const struct msm_dir_conn sdm845_dir_conn[] = {
@@ -2465,6 +1714,10 @@
 	.ngpios = 150,
 	.dir_conn = sdm845_dir_conn,
 	.n_dir_conns = ARRAY_SIZE(sdm845_dir_conn),
+	.tile_offsets = sdm845_tile_offsets,
+	.n_tile_offsets = ARRAY_SIZE(sdm845_tile_offsets),
+	.pin_base = sdm845_pin_base,
+	.reg_size = REG_SIZE,
 };
 
 static int sdm845_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 9f417bb..4a9232e 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -2582,6 +2582,21 @@
 EXPORT_SYMBOL(ipa_stop_gsi_channel);
 
 /**
+ * ipa_start_gsi_channel()- Startsa GSI channel in IPA
+ *
+ * Return value: 0 on success, negative otherwise
+ */
+int ipa_start_gsi_channel(u32 clnt_hdl)
+{
+	int ret;
+
+	IPA_API_DISPATCH_RETURN(ipa_start_gsi_channel, clnt_hdl);
+
+	return ret;
+}
+EXPORT_SYMBOL(ipa_start_gsi_channel);
+
+/**
  * ipa_get_version_string() - Get string representation of IPA version
  * @ver: IPA version
  *
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 133e058..20471eb 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -324,6 +324,8 @@
 
 	int (*ipa_stop_gsi_channel)(u32 clnt_hdl);
 
+	int (*ipa_start_gsi_channel)(u32 clnt_hdl);
+
 	struct iommu_domain *(*ipa_get_smmu_domain)(void);
 
 	int (*ipa_disable_apps_wan_cons_deaggr)(uint32_t agg_size,
diff --git a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
index 79da63e..a623d0b 100644
--- a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -114,6 +114,7 @@
  * @send_dl_skb: client callback for sending skb in downlink direction
  * @stats: statistics, how many packets were transmitted using the SW bridge
  * @is_conencted: is bridge connected ?
+ * @is_suspended: is bridge suspended ?
  * @mode: ODU mode (router/bridge)
  * @lock: for the initialization, connect and disconnect synchronization
  * @llv6_addr: link local IPv6 address of ODU network interface
@@ -122,6 +123,8 @@
  * @odu_prod_hdl: handle for IPA_CLIENT_ODU_PROD pipe
  * @odu_emb_cons_hdl: handle for IPA_CLIENT_ODU_EMB_CONS pipe
  * @odu_teth_cons_hdl: handle for IPA_CLIENT_ODU_TETH_CONS pipe
+ * @rm_comp: completion object for IP RM
+ * @wakeup_request: client callback to wakeup
  */
 struct odu_bridge_ctx {
 	struct class *class;
@@ -135,6 +138,7 @@
 	int (*send_dl_skb)(void *priv, struct sk_buff *skb);
 	struct stats stats;
 	bool is_connected;
+	bool is_suspended;
 	enum odu_bridge_mode mode;
 	struct mutex lock;
 	struct in6_addr llv6_addr;
@@ -146,6 +150,8 @@
 	u32 ipa_sys_desc_size;
 	void *logbuf;
 	void *logbuf_low;
+	struct completion rm_comp;
+	void (*wakeup_request)(void *);
 };
 static struct odu_bridge_ctx *odu_bridge_ctx;
 
@@ -1246,6 +1252,288 @@
 }
 EXPORT_SYMBOL(odu_bridge_cleanup);
 
+/* IPA Bridge implementation */
+#ifdef CONFIG_IPA3
+
+static void ipa_br_rm_notify(void *user_data, enum ipa_rm_event event,
+	unsigned long data)
+{
+	if (event == IPA_RM_RESOURCE_GRANTED)
+		complete(&odu_bridge_ctx->rm_comp);
+}
+
+static int ipa_br_request_prod(void)
+{
+	int res;
+
+	ODU_BRIDGE_FUNC_ENTRY();
+
+	reinit_completion(&odu_bridge_ctx->rm_comp);
+	ODU_BRIDGE_DBG("requesting odu prod\n");
+	res = ipa_rm_request_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
+	if (res) {
+		if (res != -EINPROGRESS) {
+			ODU_BRIDGE_ERR("failed to request prod %d\n", res);
+			return res;
+		}
+		wait_for_completion(&odu_bridge_ctx->rm_comp);
+	}
+
+	ODU_BRIDGE_FUNC_EXIT();
+	return 0;
+
+}
+
+static int ipa_br_release_prod(void)
+{
+	int res;
+
+	ODU_BRIDGE_FUNC_ENTRY();
+
+	reinit_completion(&odu_bridge_ctx->rm_comp);
+	ODU_BRIDGE_DBG("requesting odu prod\n");
+	res = ipa_rm_release_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
+	if (res) {
+		ODU_BRIDGE_ERR("failed to release prod %d\n", res);
+		return res;
+	}
+
+	ODU_BRIDGE_FUNC_EXIT();
+	return 0;
+
+}
+
+static int ipa_br_cons_request(void)
+{
+	ODU_BRIDGE_FUNC_ENTRY();
+	if (odu_bridge_ctx->is_suspended)
+		odu_bridge_ctx->wakeup_request(odu_bridge_ctx->priv);
+	ODU_BRIDGE_FUNC_EXIT();
+	return 0;
+}
+
+static int ipa_br_cons_release(void)
+{
+	ODU_BRIDGE_FUNC_ENTRY();
+	ODU_BRIDGE_FUNC_EXIT();
+	return 0;
+}
+
+/* IPA Bridge API is the new API which will replaces old odu_bridge API */
+int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl)
+{
+	int ret;
+	struct ipa_rm_create_params create_params;
+
+	if (!params || !params->wakeup_request || !hdl) {
+		ODU_BRIDGE_ERR("NULL arg\n");
+		return -EINVAL;
+	}
+
+
+	ret = odu_bridge_init(&params->info);
+	if (ret)
+		return ret;
+
+	odu_bridge_ctx->wakeup_request = params->wakeup_request;
+
+	/* create IPA RM resources for power management */
+	init_completion(&odu_bridge_ctx->rm_comp);
+	memset(&create_params, 0, sizeof(create_params));
+	create_params.name = IPA_RM_RESOURCE_ODU_ADAPT_PROD;
+	create_params.reg_params.user_data = odu_bridge_ctx;
+	create_params.reg_params.notify_cb = ipa_br_rm_notify;
+	create_params.floor_voltage = IPA_VOLTAGE_SVS;
+	ret = ipa_rm_create_resource(&create_params);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to create RM prod %d\n", ret);
+		goto fail_rm_prod;
+	}
+
+	ret = ipa_rm_add_dependency_sync(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+		IPA_RM_RESOURCE_APPS_CONS);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to add ODU->APPS dependency %d\n", ret);
+		goto fail_add_dep;
+	}
+
+	memset(&create_params, 0, sizeof(create_params));
+	create_params.name = IPA_RM_RESOURCE_ODU_ADAPT_CONS;
+	create_params.request_resource = ipa_br_cons_request;
+	create_params.release_resource = ipa_br_cons_release;
+	create_params.floor_voltage = IPA_VOLTAGE_SVS;
+	ret = ipa_rm_create_resource(&create_params);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to create RM cons %d\n", ret);
+		goto fail_rm_cons;
+	}
+
+	/* handle is ignored for now */
+	*hdl = 0;
+
+	return 0;
+
+fail_rm_cons:
+	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+		IPA_RM_RESOURCE_APPS_CONS);
+fail_add_dep:
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
+fail_rm_prod:
+	odu_bridge_cleanup();
+	return ret;
+}
+EXPORT_SYMBOL(ipa_bridge_init);
+
+int ipa_bridge_connect(u32 hdl)
+{
+	int ret;
+
+	if (!odu_bridge_ctx) {
+		ODU_BRIDGE_ERR("Not initialized\n");
+		return -EFAULT;
+	}
+
+	if (odu_bridge_ctx->is_connected) {
+		ODU_BRIDGE_ERR("already connected\n");
+		return -EFAULT;
+	}
+
+	ret = ipa_br_request_prod();
+	if (ret)
+		return ret;
+
+	return odu_bridge_connect();
+}
+EXPORT_SYMBOL(ipa_bridge_connect);
+
+int ipa_bridge_set_perf_profile(u32 hdl, u32 bandwidth)
+{
+	struct ipa_rm_perf_profile profile = {0};
+	int ret;
+
+	profile.max_supported_bandwidth_mbps = bandwidth;
+	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_ODU_ADAPT_PROD, &profile);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to set perf profile to prod %d\n", ret);
+		return ret;
+	}
+
+	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_ODU_ADAPT_CONS, &profile);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to set perf profile to cons %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_bridge_set_perf_profile);
+
+int ipa_bridge_disconnect(u32 hdl)
+{
+	int ret;
+
+	ret = odu_bridge_disconnect();
+	if (ret)
+		return ret;
+
+	ret = ipa_br_release_prod();
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_bridge_disconnect);
+
+int ipa_bridge_suspend(u32 hdl)
+{
+	int ret;
+
+	if (!odu_bridge_ctx) {
+		ODU_BRIDGE_ERR("Not initialized\n");
+		return -EFAULT;
+	}
+
+	if (!odu_bridge_ctx->is_connected) {
+		ODU_BRIDGE_ERR("bridge is  disconnected\n");
+		return -EFAULT;
+	}
+
+	if (odu_bridge_ctx->is_suspended) {
+		ODU_BRIDGE_ERR("bridge is already suspended\n");
+		return -EFAULT;
+	}
+
+	/* stop cons channel to prevent downlink data during suspend */
+	ret = ipa_stop_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to stop CONS channel %d\n", ret);
+		return ret;
+	}
+
+	ret = ipa_br_release_prod();
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to release prod %d\n", ret);
+		ipa_start_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
+		return ret;
+	}
+	odu_bridge_ctx->is_suspended = true;
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_bridge_suspend);
+
+int ipa_bridge_resume(u32 hdl)
+{
+	int ret;
+
+	if (!odu_bridge_ctx) {
+		ODU_BRIDGE_ERR("Not initialized\n");
+		return -EFAULT;
+	}
+
+	if (!odu_bridge_ctx->is_connected) {
+		ODU_BRIDGE_ERR("bridge is  disconnected\n");
+		return -EFAULT;
+	}
+
+	if (!odu_bridge_ctx->is_suspended) {
+		ODU_BRIDGE_ERR("bridge is not suspended\n");
+		return -EFAULT;
+	}
+
+	ret = ipa_br_request_prod();
+	if (ret)
+		return ret;
+
+	ret = ipa_start_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
+	if (ret) {
+		ODU_BRIDGE_ERR("failed to start CONS channel %d\n", ret);
+		return ret;
+	}
+	odu_bridge_ctx->is_suspended = false;
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_bridge_resume);
+
+int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb,
+	struct ipa_tx_meta *metadata)
+{
+	return odu_bridge_tx_dp(skb, metadata);
+}
+EXPORT_SYMBOL(ipa_bridge_tx_dp);
+
+int ipa_bridge_cleanup(u32 hdl)
+{
+	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+		IPA_RM_RESOURCE_APPS_CONS);
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS);
+	return odu_bridge_cleanup();
+}
+EXPORT_SYMBOL(ipa_bridge_cleanup);
+
+#endif /* CONFIG_IPA3 */
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("ODU bridge driver");
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 07bca0c..32c8b25 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -384,5 +384,6 @@
 			      void *user_data);
 void ipa_ntn_uc_dereg_rdyCB(void);
 const char *ipa_get_version_string(enum ipa_hw_type ver);
+int ipa_start_gsi_channel(u32 clnt_hdl);
 
 #endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 53ab299..bfd0446 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -641,7 +641,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_nat_dma_cmd *)param)->entries,
 				pre_entry);
 			retval = -EFAULT;
@@ -688,7 +688,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_hdr *)param)->num_hdrs,
 				pre_entry);
 			retval = -EFAULT;
@@ -727,7 +727,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_hdr *)param)->num_hdls,
 				pre_entry);
 			retval = -EFAULT;
@@ -767,7 +767,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_rt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -807,7 +807,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_mdfy_rt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -847,7 +847,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_rt_rule *)param)->num_hdls,
 				pre_entry);
 			retval = -EFAULT;
@@ -886,7 +886,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_flt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -926,7 +926,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_flt_rule *)param)->
 				num_hdls,
 				pre_entry);
@@ -966,7 +966,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_mdfy_flt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -1104,7 +1104,7 @@
 		if (unlikely(((struct ipa_ioc_query_intf_tx_props *)
 			param)->num_tx_props
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_query_intf_tx_props *)
 				param)->num_tx_props, pre_entry);
 			retval = -EFAULT;
@@ -1149,7 +1149,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_query_intf_rx_props *)
 			param)->num_rx_props != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_query_intf_rx_props *)
 				param)->num_rx_props, pre_entry);
 			retval = -EFAULT;
@@ -1194,7 +1194,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_query_intf_ext_props *)
 			param)->num_ext_props != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_query_intf_ext_props *)
 				param)->num_ext_props, pre_entry);
 			retval = -EFAULT;
@@ -1232,7 +1232,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_msg_meta *)param)->msg_len
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_msg_meta *)param)->msg_len,
 				pre_entry);
 			retval = -EFAULT;
@@ -1372,7 +1372,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *)
 			param)->num_proc_ctxs != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_hdr_proc_ctx *)
 				param)->num_proc_ctxs, pre_entry);
 			retval = -EFAULT;
@@ -1411,7 +1411,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *)
 			param)->num_hdls != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_hdr_proc_ctx *)param)->
 				num_hdls,
 				pre_entry);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
index 8d9f0e0..f7b0864 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
@@ -1015,25 +1015,25 @@
 	if (rule->action != IPA_PASS_TO_EXCEPTION) {
 		if (!rule->eq_attrib_type) {
 			if (!rule->rt_tbl_hdl) {
-				IPAERR("invalid RT tbl\n");
+				IPAERR_RL("invalid RT tbl\n");
 				goto error;
 			}
 
 			rt_tbl = ipa_id_find(rule->rt_tbl_hdl);
 			if (rt_tbl == NULL) {
-				IPAERR("RT tbl not found\n");
+				IPAERR_RL("RT tbl not found\n");
 				goto error;
 			}
 
 			if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) {
-				IPAERR("RT table cookie is invalid\n");
+				IPAERR_RL("RT table cookie is invalid\n");
 				goto error;
 			}
 		} else {
 			if (rule->rt_tbl_idx > ((ip == IPA_IP_v4) ?
 				IPA_MEM_PART(v4_modem_rt_index_hi) :
 				IPA_MEM_PART(v6_modem_rt_index_hi))) {
-				IPAERR("invalid RT tbl\n");
+				IPAERR_RL("invalid RT tbl\n");
 				goto error;
 			}
 		}
@@ -1089,12 +1089,12 @@
 
 	entry = ipa_id_find(rule_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EINVAL;
 	}
 
 	if (entry->cookie != IPA_FLT_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		return -EINVAL;
 	}
 	id = entry->id;
@@ -1121,12 +1121,12 @@
 
 	entry = ipa_id_find(frule->rule_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		goto error;
 	}
 
 	if (entry->cookie != IPA_FLT_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		goto error;
 	}
 
@@ -1136,25 +1136,25 @@
 	if (frule->rule.action != IPA_PASS_TO_EXCEPTION) {
 		if (!frule->rule.eq_attrib_type) {
 			if (!frule->rule.rt_tbl_hdl) {
-				IPAERR("invalid RT tbl\n");
+				IPAERR_RL("invalid RT tbl\n");
 				goto error;
 			}
 
 			rt_tbl = ipa_id_find(frule->rule.rt_tbl_hdl);
 			if (rt_tbl == NULL) {
-				IPAERR("RT tbl not found\n");
+				IPAERR_RL("RT tbl not found\n");
 				goto error;
 			}
 
 			if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) {
-				IPAERR("RT table cookie is invalid\n");
+				IPAERR_RL("RT table cookie is invalid\n");
 				goto error;
 			}
 		} else {
 			if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ?
 				IPA_MEM_PART(v4_modem_rt_index_hi) :
 				IPA_MEM_PART(v6_modem_rt_index_hi))) {
-				IPAERR("invalid RT tbl\n");
+				IPAERR_RL("invalid RT tbl\n");
 				goto error;
 			}
 		}
@@ -1178,7 +1178,7 @@
 	struct ipa_flt_tbl *tbl;
 
 	if (rule == NULL || rule_hdl == NULL) {
-		IPAERR("bad parms rule=%p rule_hdl=%p\n", rule, rule_hdl);
+		IPAERR_RL("bad parms rule=%p rule_hdl=%p\n", rule, rule_hdl);
 
 		return -EINVAL;
 	}
@@ -1197,14 +1197,14 @@
 	int ipa_ep_idx;
 
 	if (rule == NULL || rule_hdl == NULL || ep >= IPA_CLIENT_MAX) {
-		IPAERR("bad parms rule=%p rule_hdl=%p ep=%d\n", rule,
+		IPAERR_RL("bad parms rule=%p rule_hdl=%p ep=%d\n", rule,
 				rule_hdl, ep);
 
 		return -EINVAL;
 	}
 	ipa_ep_idx = ipa2_get_ep_mapping(ep);
 	if (ipa_ep_idx == IPA_FLT_TABLE_INDEX_NOT_FOUND) {
-		IPAERR("ep not valid ep=%d\n", ep);
+		IPAERR_RL("ep not valid ep=%d\n", ep);
 		return -EINVAL;
 	}
 	if (ipa_ctx->ep[ipa_ep_idx].valid == 0)
@@ -1231,7 +1231,7 @@
 
 	if (rules == NULL || rules->num_rules == 0 ||
 			rules->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 
 		return -EINVAL;
 	}
@@ -1249,7 +1249,7 @@
 					rules->rules[i].at_rear,
 					&rules->rules[i].flt_rule_hdl);
 		if (result) {
-			IPAERR("failed to add flt rule %d\n", i);
+			IPAERR_RL("failed to add flt rule %d\n", i);
 			rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED;
 		} else {
 			rules->rules[i].status = 0;
@@ -1282,14 +1282,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa_del_flt_rule(hdls->hdl[i].hdl)) {
-			IPAERR("failed to del rt rule %i\n", i);
+			IPAERR_RL("failed to del rt rule %i\n", i);
 			hdls->hdl[i].status = IPA_FLT_STATUS_OF_DEL_FAILED;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1322,14 +1322,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa_ctx->lock);
 	for (i = 0; i < hdls->num_rules; i++) {
 		if (__ipa_mdfy_flt_rule(&hdls->rules[i], hdls->ip)) {
-			IPAERR("failed to mdfy rt rule %i\n", i);
+			IPAERR_RL("failed to mdfy rt rule %i\n", i);
 			hdls->rules[i].status = IPA_FLT_STATUS_OF_MDFY_FAILED;
 		} else {
 			hdls->rules[i].status = 0;
@@ -1363,7 +1363,7 @@
 	int result;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1399,7 +1399,7 @@
 	int id;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index a6a7613..d4e39d7 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -558,13 +558,13 @@
 		proc_ctx->type, proc_ctx->hdr_hdl);
 
 	if (!HDR_PROC_TYPE_IS_VALID(proc_ctx->type)) {
-		IPAERR("invalid processing type %d\n", proc_ctx->type);
+		IPAERR_RL("invalid processing type %d\n", proc_ctx->type);
 		return -EINVAL;
 	}
 
 	hdr_entry = ipa_id_find(proc_ctx->hdr_hdl);
 	if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE)) {
-		IPAERR("hdr_hdl is invalid\n");
+		IPAERR_RL("hdr_hdl is invalid\n");
 		return -EINVAL;
 	}
 
@@ -592,7 +592,7 @@
 			ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN1]) {
 		bin = IPA_HDR_PROC_CTX_BIN1;
 	} else {
-		IPAERR("unexpected needed len %d\n", needed_len);
+		IPAERR_RL("unexpected needed len %d\n", needed_len);
 		WARN_ON(1);
 		goto bad_len;
 	}
@@ -602,7 +602,7 @@
 		IPA_MEM_PART(apps_hdr_proc_ctx_size_ddr);
 	if (list_empty(&htbl->head_free_offset_list[bin])) {
 		if (htbl->end + ipa_hdr_proc_ctx_bin_sz[bin] > mem_size) {
-			IPAERR("hdr proc ctx table overflow\n");
+			IPAERR_RL("hdr proc ctx table overflow\n");
 			goto bad_len;
 		}
 
@@ -649,8 +649,7 @@
 	return 0;
 
 ipa_insert_failed:
-	if (offset)
-		list_move(&offset->link,
+	list_move(&offset->link,
 		&htbl->head_free_offset_list[offset->bin]);
 	entry->offset_entry = NULL;
 	list_del(&entry->link);
@@ -676,12 +675,12 @@
 	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 
 	if (hdr->hdr_len == 0 || hdr->hdr_len > IPA_HDR_MAX_SIZE) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		goto error;
 	}
 
 	if (!HDR_TYPE_IS_VALID(hdr->type)) {
-		IPAERR("invalid hdr type %d\n", hdr->type);
+		IPAERR_RL("invalid hdr type %d\n", hdr->type);
 		goto error;
 	}
 
@@ -713,7 +712,7 @@
 	else if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN4])
 		bin = IPA_HDR_BIN4;
 	else {
-		IPAERR("unexpected hdr len %d\n", hdr->hdr_len);
+		IPAERR_RL("unexpected hdr len %d\n", hdr->hdr_len);
 		goto bad_hdr_len;
 	}
 
@@ -844,7 +843,7 @@
 
 	entry = ipa_id_find(proc_ctx_hdl);
 	if (!entry || (entry->cookie != IPA_PROC_HDR_COOKIE)) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -852,7 +851,7 @@
 		htbl->proc_ctx_cnt, entry->offset_entry->offset);
 
 	if (by_user && entry->user_deleted) {
-		IPAERR("proc_ctx already deleted by user\n");
+		IPAERR_RL("proc_ctx already deleted by user\n");
 		return -EINVAL;
 	}
 
@@ -890,12 +889,12 @@
 
 	entry = ipa_id_find(hdr_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EINVAL;
 	}
 
 	if (entry->cookie != IPA_HDR_COOKIE) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -907,7 +906,7 @@
 			htbl->hdr_cnt, entry->offset_entry->offset);
 
 	if (by_user && entry->user_deleted) {
-		IPAERR("hdr already deleted by user\n");
+		IPAERR_RL("hdr already deleted by user\n");
 		return -EINVAL;
 	}
 
@@ -956,12 +955,12 @@
 	int result = -EFAULT;
 
 	if (unlikely(!ipa_ctx)) {
-		IPAERR("IPA driver was not initialized\n");
+		IPAERR_RL("IPA driver was not initialized\n");
 		return -EINVAL;
 	}
 
 	if (hdrs == NULL || hdrs->num_hdrs == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -970,7 +969,7 @@
 			hdrs->num_hdrs);
 	for (i = 0; i < hdrs->num_hdrs; i++) {
 		if (__ipa_add_hdr(&hdrs->hdr[i])) {
-			IPAERR("failed to add hdr %d\n", i);
+			IPAERR_RL("failed to add hdr %d\n", i);
 			hdrs->hdr[i].status = -1;
 		} else {
 			hdrs->hdr[i].status = 0;
@@ -1011,14 +1010,14 @@
 	}
 
 	if (hdls == NULL || hdls->num_hdls == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) {
-			IPAERR("failed to del hdr %i\n", i);
+			IPAERR_RL("failed to del hdr %i\n", i);
 			hdls->hdl[i].status = -1;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1067,13 +1066,13 @@
 
 	if (ipa_ctx->ipa_hw_type <= IPA_HW_v2_0 ||
 	    ipa_ctx->ipa_hw_type == IPA_HW_v2_6L) {
-		IPAERR("Processing context not supported on IPA HW %d\n",
+		IPAERR_RL("Processing context not supported on IPA HW %d\n",
 			ipa_ctx->ipa_hw_type);
 		return -EFAULT;
 	}
 
 	if (proc_ctxs == NULL || proc_ctxs->num_proc_ctxs == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1082,7 +1081,7 @@
 			proc_ctxs->num_proc_ctxs);
 	for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) {
 		if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) {
-			IPAERR("failed to add hdr pric ctx %d\n", i);
+			IPAERR_RL("failed to add hdr pric ctx %d\n", i);
 			proc_ctxs->proc_ctx[i].status = -1;
 		} else {
 			proc_ctxs->proc_ctx[i].status = 0;
@@ -1127,14 +1126,14 @@
 	}
 
 	if (hdls == NULL || hdls->num_hdls == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) {
-			IPAERR("failed to del hdr %i\n", i);
+			IPAERR_RL("failed to del hdr %i\n", i);
 			hdls->hdl[i].status = -1;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1371,7 +1370,7 @@
 	}
 
 	if (lookup == NULL) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 	mutex_lock(&ipa_ctx->lock);
@@ -1458,13 +1457,13 @@
 
 	entry = ipa_id_find(hdr_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		result = -EINVAL;
 		goto bail;
 	}
 
 	if (entry->cookie != IPA_HDR_COOKIE) {
-		IPAERR("invalid header entry\n");
+		IPAERR_RL("invalid header entry\n");
 		result = -EINVAL;
 		goto bail;
 	}
@@ -1493,7 +1492,7 @@
 	int result = -EFAULT;
 
 	if (copy == NULL) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 	mutex_lock(&ipa_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 0c2410f..141bff1 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -68,6 +68,18 @@
 #define IPAERR(fmt, args...) \
 	pr_err(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
 
+#define IPAERR_RL(fmt, args...) \
+	do { \
+		pr_err_ratelimited(DRV_NAME " %s:%d " fmt, __func__, \
+		__LINE__, ## args);\
+		if (ipa_ctx) { \
+			IPA_IPC_LOGGING(ipa_ctx->logbuf, \
+				DRV_NAME " %s:%d " fmt, ## args); \
+			IPA_IPC_LOGGING(ipa_ctx->logbuf_low, \
+				DRV_NAME " %s:%d " fmt, ## args); \
+		} \
+	} while (0)
+
 #define WLAN_AMPDU_TX_EP 15
 #define WLAN_PROD_TX_EP  19
 #define WLAN1_CONS_RX_EP  14
@@ -1730,9 +1742,6 @@
 	iowrite32(val, base + offset);
 }
 
-int ipa_bridge_init(void);
-void ipa_bridge_cleanup(void);
-
 ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
 		 loff_t *f_pos);
 int ipa_pull_msg(struct ipa_msg_meta *meta, char *buff, size_t count);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index 12b1a99..e6954b7 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -404,13 +404,13 @@
 
 	if (meta == NULL || (buff == NULL && callback != NULL) ||
 	    (buff != NULL && callback == NULL)) {
-		IPAERR("invalid param meta=%p buff=%p, callback=%p\n",
+		IPAERR_RL("invalid param meta=%p buff=%p, callback=%p\n",
 		       meta, buff, callback);
 		return -EINVAL;
 	}
 
 	if (meta->msg_type >= IPA_EVENT_MAX_NUM) {
-		IPAERR("unsupported message type %d\n", meta->msg_type);
+		IPAERR_RL("unsupported message type %d\n", meta->msg_type);
 		return -EINVAL;
 	}
 
@@ -633,7 +633,7 @@
 	int result = -EINVAL;
 
 	if (meta == NULL || buff == NULL || !count) {
-		IPAERR("invalid param name=%p buff=%p count=%zu\n",
+		IPAERR_RL("invalid param name=%p buff=%p count=%zu\n",
 				meta, buff, count);
 		return result;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
index a7f983e..50b2706 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
@@ -252,8 +252,8 @@
 
 	mutex_lock(&nat_ctx->lock);
 	if (strcmp(mem->dev_name, NAT_DEV_NAME)) {
-		IPAERR("Nat device name mismatch\n");
-		IPAERR("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name);
+		IPAERR_RL("Nat device name mismatch\n");
+		IPAERR_RL("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name);
 		result = -EPERM;
 		goto bail;
 	}
@@ -272,7 +272,7 @@
 
 	if (mem->size <= 0 ||
 			nat_ctx->is_dev_init == true) {
-		IPAERR("Invalid Parameters or device is already init\n");
+		IPAERR_RL("Invalid Parameters or device is already init\n");
 		result = -EPERM;
 		goto bail;
 	}
@@ -335,8 +335,8 @@
 
 	/* check for integer overflow */
 	if (init->ipv4_rules_offset >
-		UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1))) {
-		IPAERR("Detected overflow\n");
+		(UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1)))) {
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Table Entry offset is not
@@ -345,8 +345,8 @@
 	tmp = init->ipv4_rules_offset +
 		(TBL_ENTRY_SIZE * (init->table_entries + 1));
 	if (tmp > ipa_ctx->nat_mem.size) {
-		IPAERR("Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->ipv4_rules_offset, (init->table_entries + 1),
 			tmp, ipa_ctx->nat_mem.size);
 		return -EPERM;
@@ -355,7 +355,7 @@
 	/* check for integer overflow */
 	if (init->expn_rules_offset >
 		UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries)) {
-		IPAERR("Detected overflow\n");
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Expn Table Entry offset is not
@@ -364,8 +364,8 @@
 	tmp = init->expn_rules_offset +
 		(TBL_ENTRY_SIZE * init->expn_table_entries);
 	if (tmp > ipa_ctx->nat_mem.size) {
-		IPAERR("Expn Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Expn Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->expn_rules_offset, init->expn_table_entries,
 			tmp, ipa_ctx->nat_mem.size);
 		return -EPERM;
@@ -374,7 +374,7 @@
 	/* check for integer overflow */
 	if (init->index_offset >
 		UINT_MAX - (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1))) {
-		IPAERR("Detected overflow\n");
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Indx Table Entry offset is not
@@ -383,8 +383,8 @@
 	tmp = init->index_offset +
 		(INDX_TBL_ENTRY_SIZE * (init->table_entries + 1));
 	if (tmp > ipa_ctx->nat_mem.size) {
-		IPAERR("Indx Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Indx Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->index_offset, (init->table_entries + 1),
 			tmp, ipa_ctx->nat_mem.size);
 		return -EPERM;
@@ -392,8 +392,8 @@
 
 	/* check for integer overflow */
 	if (init->index_expn_offset >
-		UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries)) {
-		IPAERR("Detected overflow\n");
+		(UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries))) {
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Expn Table entry offset is not
@@ -402,8 +402,8 @@
 	tmp = init->index_expn_offset +
 		(INDX_TBL_ENTRY_SIZE * init->expn_table_entries);
 	if (tmp > ipa_ctx->nat_mem.size) {
-		IPAERR("Indx Expn Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Indx Expn Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->index_expn_offset, init->expn_table_entries,
 			tmp, ipa_ctx->nat_mem.size);
 		return -EPERM;
@@ -448,16 +448,16 @@
 				(init->expn_rules_offset > offset) ||
 				(init->index_offset > offset) ||
 				(init->index_expn_offset > offset)) {
-			IPAERR("Failed due to integer overflow\n");
-			IPAERR("nat.mem.dma_handle: 0x%pa\n",
+			IPAERR_RL("Failed due to integer overflow\n");
+			IPAERR_RL("nat.mem.dma_handle: 0x%pa\n",
 				&ipa_ctx->nat_mem.dma_handle);
-			IPAERR("ipv4_rules_offset: 0x%x\n",
+			IPAERR_RL("ipv4_rules_offset: 0x%x\n",
 				init->ipv4_rules_offset);
-			IPAERR("expn_rules_offset: 0x%x\n",
+			IPAERR_RL("expn_rules_offset: 0x%x\n",
 				init->expn_rules_offset);
-			IPAERR("index_offset: 0x%x\n",
+			IPAERR_RL("index_offset: 0x%x\n",
 				init->index_offset);
-			IPAERR("index_expn_offset: 0x%x\n",
+			IPAERR_RL("index_expn_offset: 0x%x\n",
 				init->index_expn_offset);
 			result = -EPERM;
 			goto free_mem;
@@ -513,7 +513,7 @@
 	desc[1].len = size;
 	IPADBG("posting v4 init command\n");
 	if (ipa_send_cmd(2, desc)) {
-		IPAERR("Fail to send immediate command\n");
+		IPAERR_RL("Fail to send immediate command\n");
 		result = -EPERM;
 		goto free_mem;
 	}
@@ -578,7 +578,7 @@
 
 	IPADBG("\n");
 	if (dma->entries <= 0) {
-		IPAERR("Invalid number of commands %d\n",
+		IPAERR_RL("Invalid number of commands %d\n",
 			dma->entries);
 		ret = -EPERM;
 		goto bail;
@@ -586,7 +586,7 @@
 
 	for (cnt = 0; cnt < dma->entries; cnt++) {
 		if (dma->dma[cnt].table_index >= 1) {
-			IPAERR("Invalid table index %d\n",
+			IPAERR_RL("Invalid table index %d\n",
 				dma->dma[cnt].table_index);
 			ret = -EPERM;
 			goto bail;
@@ -597,7 +597,7 @@
 			if (dma->dma[cnt].offset >=
 				(ipa_ctx->nat_mem.size_base_tables + 1) *
 				NAT_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -609,7 +609,7 @@
 			if (dma->dma[cnt].offset >=
 				ipa_ctx->nat_mem.size_expansion_tables *
 				NAT_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -621,7 +621,7 @@
 			if (dma->dma[cnt].offset >=
 				(ipa_ctx->nat_mem.size_base_tables + 1) *
 				NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -633,7 +633,7 @@
 			if (dma->dma[cnt].offset >=
 				ipa_ctx->nat_mem.size_expansion_tables *
 				NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -642,7 +642,7 @@
 			break;
 
 		default:
-			IPAERR("Invalid base_addr %d\n",
+			IPAERR_RL("Invalid base_addr %d\n",
 				dma->dma[cnt].base_addr);
 			ret = -EPERM;
 			goto bail;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 1faa795..50930d3 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -850,7 +850,7 @@
 	struct ipa_rt_tbl *entry;
 
 	if (in->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -942,12 +942,12 @@
 	u32 id;
 
 	if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) {
-		IPAERR("bad parms\n");
+		IPAERR_RL("bad parms\n");
 		return -EINVAL;
 	}
 	id = entry->id;
 	if (ipa_id_find(id) == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EPERM;
 	}
 
@@ -1086,7 +1086,7 @@
 	int ret;
 
 	if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1096,7 +1096,7 @@
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
 					&rules->rules[i].rt_rule_hdl)) {
-			IPAERR("failed to add rt rule %d\n", i);
+			IPAERR_RL("failed to add rt rule %d\n", i);
 			rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED;
 		} else {
 			rules->rules[i].status = 0;
@@ -1123,12 +1123,12 @@
 	entry = ipa_id_find(rule_hdl);
 
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EINVAL;
 	}
 
 	if (entry->cookie != IPA_RT_RULE_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		return -EINVAL;
 	}
 
@@ -1142,7 +1142,7 @@
 			entry->tbl->rule_cnt);
 	if (entry->tbl->rule_cnt == 0 && entry->tbl->ref_cnt == 0) {
 		if (__ipa_del_rt_tbl(entry->tbl))
-			IPAERR("fail to del RT tbl\n");
+			IPAERR_RL("fail to del RT tbl\n");
 	}
 	entry->cookie = 0;
 	id = entry->id;
@@ -1169,14 +1169,14 @@
 	int ret;
 
 	if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa_del_rt_rule(hdls->hdl[i].hdl)) {
-			IPAERR("failed to del rt rule %i\n", i);
+			IPAERR_RL("failed to del rt rule %i\n", i);
 			hdls->hdl[i].status = IPA_RT_STATUS_OF_DEL_FAILED;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1209,7 +1209,7 @@
 	int ret;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1253,7 +1253,7 @@
 	int id;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1271,7 +1271,7 @@
 	 * filtering rules point to routing tables
 	 */
 	if (ipa2_reset_flt(ip))
-		IPAERR("fail to reset flt ip=%d\n", ip);
+		IPAERR_RL("fail to reset flt ip=%d\n", ip);
 
 	set = &ipa_ctx->rt_tbl_set[ip];
 	rset = &ipa_ctx->reap_rt_tbl_set[ip];
@@ -1357,21 +1357,27 @@
 	int result = -EFAULT;
 
 	if (lookup == NULL || lookup->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 	mutex_lock(&ipa_ctx->lock);
 	entry = __ipa_find_rt_tbl(lookup->ip, lookup->name);
 	if (entry && entry->cookie == IPA_RT_TBL_COOKIE) {
+		if (entry->ref_cnt == U32_MAX) {
+			IPAERR("fail: ref count crossed limit\n");
+			goto ret;
+		}
 		entry->ref_cnt++;
 		lookup->hdl = entry->id;
 
 		/* commit for get */
 		if (ipa_ctx->ctrl->ipa_commit_rt(lookup->ip))
-			IPAERR("fail to commit RT tbl\n");
+			IPAERR_RL("fail to commit RT tbl\n");
 
 		result = 0;
 	}
+
+ret:
 	mutex_unlock(&ipa_ctx->lock);
 
 	return result;
@@ -1389,18 +1395,18 @@
 {
 	struct ipa_rt_tbl *entry;
 	enum ipa_ip_type ip = IPA_IP_MAX;
-	int result;
+	int result = 0;
 
 	mutex_lock(&ipa_ctx->lock);
 	entry = ipa_id_find(rt_tbl_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		result = -EINVAL;
 		goto ret;
 	}
 
 	if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) {
-		IPAERR("bad parms\n");
+		IPAERR_RL("bad parms\n");
 		result = -EINVAL;
 		goto ret;
 	}
@@ -1418,10 +1424,10 @@
 	entry->ref_cnt--;
 	if (entry->ref_cnt == 0 && entry->rule_cnt == 0) {
 		if (__ipa_del_rt_tbl(entry))
-			IPAERR("fail to del RT tbl\n");
+			IPAERR_RL("fail to del RT tbl\n");
 		/* commit for put */
 		if (ipa_ctx->ctrl->ipa_commit_rt(ip))
-			IPAERR("fail to commit RT tbl\n");
+			IPAERR_RL("fail to commit RT tbl\n");
 	}
 
 	result = 0;
@@ -1441,19 +1447,19 @@
 	if (rtrule->rule.hdr_hdl) {
 		hdr = ipa_id_find(rtrule->rule.hdr_hdl);
 		if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) {
-			IPAERR("rt rule does not point to valid hdr\n");
+			IPAERR_RL("rt rule does not point to valid hdr\n");
 			goto error;
 		}
 	}
 
 	entry = ipa_id_find(rtrule->rt_rule_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		goto error;
 	}
 
 	if (entry->cookie != IPA_RT_RULE_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		goto error;
 	}
 
@@ -1486,14 +1492,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa_ctx->lock);
 	for (i = 0; i < hdls->num_rules; i++) {
 		if (__ipa_mdfy_rt_rule(&hdls->rules[i])) {
-			IPAERR("failed to mdfy rt rule %i\n", i);
+			IPAERR_RL("failed to mdfy rt rule %i\n", i);
 			hdls->rules[i].status = IPA_RT_STATUS_OF_MDFY_FAILED;
 		} else {
 			hdls->rules[i].status = 0;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
index b7815cb..a454382 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
@@ -1673,7 +1673,7 @@
 
 	if (clnt_hdl >= ipa_ctx->ipa_num_pipes ||
 	    ipa_ctx->ep[clnt_hdl].valid == 0) {
-		IPAERR("bad parm, %d\n", clnt_hdl);
+		IPAERR_RL("bad parm, %d\n", clnt_hdl);
 		return -EINVAL;
 	}
 
@@ -1686,7 +1686,7 @@
 	ep = &ipa_ctx->ep[clnt_hdl];
 
 	if (!(ep->uc_offload_state & IPA_WDI_CONNECTED)) {
-		IPAERR("WDI channel bad state %d\n", ep->uc_offload_state);
+		IPAERR_RL("WDI channel bad state %d\n", ep->uc_offload_state);
 		return -EFAULT;
 	}
 
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index b133f9c..2c88244 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -847,7 +847,7 @@
 	}
 
 	if (client >= IPA_CLIENT_MAX || client < 0) {
-		IPAERR("Bad client number! client =%d\n", client);
+		IPAERR_RL("Bad client number! client =%d\n", client);
 		return INVALID_EP_MAPPING_INDEX;
 	}
 
@@ -1700,7 +1700,7 @@
 		if (attrib->attrib_mask & IPA_FLT_NEXT_HDR ||
 		    attrib->attrib_mask & IPA_FLT_TC || attrib->attrib_mask &
 		    IPA_FLT_FLOW_LABEL) {
-			IPAERR("v6 attrib's specified for v4 rule\n");
+			IPAERR_RL("v6 attrib's specified for v4 rule\n");
 			return -EPERM;
 		}
 
@@ -1712,7 +1712,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
 			if (ipa_ofst_meq32[ofst_meq32] == -1) {
-				IPAERR("ran out of meq32 eq\n");
+				IPAERR_RL("ran out of meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq32[ofst_meq32];
@@ -1732,7 +1732,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SRC_ADDR) {
 			if (ipa_ofst_meq32[ofst_meq32] == -1) {
-				IPAERR("ran out of meq32 eq\n");
+				IPAERR_RL("ran out of meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq32[ofst_meq32];
@@ -1746,7 +1746,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_DST_ADDR) {
 			if (ipa_ofst_meq32[ofst_meq32] == -1) {
-				IPAERR("ran out of meq32 eq\n");
+				IPAERR_RL("ran out of meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq32[ofst_meq32];
@@ -1760,11 +1760,11 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SRC_PORT_RANGE) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			if (attrib->src_port_hi < attrib->src_port_lo) {
-				IPAERR("bad src port range param\n");
+				IPAERR_RL("bad src port range param\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -1778,11 +1778,11 @@
 
 		if (attrib->attrib_mask & IPA_FLT_DST_PORT_RANGE) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			if (attrib->dst_port_hi < attrib->dst_port_lo) {
-				IPAERR("bad dst port range param\n");
+				IPAERR_RL("bad dst port range param\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -1796,7 +1796,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_TYPE) {
 			if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) {
-				IPAERR("ran out of ihl_meq32 eq\n");
+				IPAERR_RL("ran out of ihl_meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32];
@@ -1809,7 +1809,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_CODE) {
 			if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) {
-				IPAERR("ran out of ihl_meq32 eq\n");
+				IPAERR_RL("ran out of ihl_meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32];
@@ -1822,7 +1822,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SPI) {
 			if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) {
-				IPAERR("ran out of ihl_meq32 eq\n");
+				IPAERR_RL("ran out of ihl_meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32];
@@ -1836,7 +1836,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SRC_PORT) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -1850,7 +1850,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_DST_PORT) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -1877,7 +1877,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -1892,7 +1892,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -1907,7 +1907,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -1922,7 +1922,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -1937,7 +1937,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) {
 			if (ipa_ofst_meq32[ofst_meq32] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq32[ofst_meq32];
@@ -1955,7 +1955,7 @@
 		/* error check */
 		if (attrib->attrib_mask & IPA_FLT_TOS ||
 		    attrib->attrib_mask & IPA_FLT_PROTOCOL) {
-			IPAERR("v4 attrib's specified for v6 rule\n");
+			IPAERR_RL("v4 attrib's specified for v6 rule\n");
 			return -EPERM;
 		}
 
@@ -1967,7 +1967,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_TYPE) {
 			if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) {
-				IPAERR("ran out of ihl_meq32 eq\n");
+				IPAERR_RL("ran out of ihl_meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32];
@@ -1980,7 +1980,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_CODE) {
 			if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) {
-				IPAERR("ran out of ihl_meq32 eq\n");
+				IPAERR_RL("ran out of ihl_meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32];
@@ -1993,7 +1993,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SPI) {
 			if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) {
-				IPAERR("ran out of ihl_meq32 eq\n");
+				IPAERR_RL("ran out of ihl_meq32 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32];
@@ -2007,7 +2007,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SRC_PORT) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -2021,7 +2021,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_DST_PORT) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -2035,11 +2035,11 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SRC_PORT_RANGE) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			if (attrib->src_port_hi < attrib->src_port_lo) {
-				IPAERR("bad src port range param\n");
+				IPAERR_RL("bad src port range param\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -2053,11 +2053,11 @@
 
 		if (attrib->attrib_mask & IPA_FLT_DST_PORT_RANGE) {
 			if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) {
-				IPAERR("ran out of ihl_rng16 eq\n");
+				IPAERR_RL("ran out of ihl_rng16 eq\n");
 				return -EPERM;
 			}
 			if (attrib->dst_port_hi < attrib->dst_port_lo) {
-				IPAERR("bad dst port range param\n");
+				IPAERR_RL("bad dst port range param\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16];
@@ -2071,7 +2071,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_SRC_ADDR) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2097,7 +2097,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_DST_ADDR) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2129,7 +2129,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2174,7 +2174,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2189,7 +2189,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2204,7 +2204,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2219,7 +2219,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) {
 			if (ipa_ofst_meq128[ofst_meq128] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq128[ofst_meq128];
@@ -2234,7 +2234,7 @@
 
 		if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) {
 			if (ipa_ofst_meq32[ofst_meq32] == -1) {
-				IPAERR("ran out of meq128 eq\n");
+				IPAERR_RL("ran out of meq128 eq\n");
 				return -EPERM;
 			}
 			*en_rule |= ipa_ofst_meq32[ofst_meq32];
@@ -2247,7 +2247,7 @@
 		}
 
 	} else {
-		IPAERR("unsupported ip %d\n", ip);
+		IPAERR_RL("unsupported ip %d\n", ip);
 		return -EPERM;
 	}
 
@@ -2257,7 +2257,7 @@
 	 */
 	if (attrib->attrib_mask == 0) {
 		if (ipa_ofst_meq32[ofst_meq32] == -1) {
-			IPAERR("ran out of meq32 eq\n");
+			IPAERR_RL("ran out of meq32 eq\n");
 			return -EPERM;
 		}
 		*en_rule |= ipa_ofst_meq32[ofst_meq32];
@@ -3548,19 +3548,19 @@
 	}
 
 	if (param_in->client  >= IPA_CLIENT_MAX) {
-		IPAERR("bad parm client:%d\n", param_in->client);
+		IPAERR_RL("bad parm client:%d\n", param_in->client);
 		goto fail;
 	}
 
 	ipa_ep_idx = ipa2_get_ep_mapping(param_in->client);
 	if (ipa_ep_idx == -1) {
-		IPAERR("Invalid client.\n");
+		IPAERR_RL("Invalid client.\n");
 		goto fail;
 	}
 
 	ep = &ipa_ctx->ep[ipa_ep_idx];
 	if (!ep->valid) {
-		IPAERR("EP not allocated.\n");
+		IPAERR_RL("EP not allocated.\n");
 		goto fail;
 	}
 
@@ -3574,7 +3574,7 @@
 		ipa_ctx->ep[ipa_ep_idx].cfg.meta = meta;
 		result = ipa_write_qmapid_wdi_pipe(ipa_ep_idx, meta.qmap_id);
 		if (result)
-			IPAERR("qmap_id %d write failed on ep=%d\n",
+			IPAERR_RL("qmap_id %d write failed on ep=%d\n",
 					meta.qmap_id, ipa_ep_idx);
 		result = 0;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index 0bdfea9..9c75202 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -1877,7 +1877,9 @@
 	if (ret < 0)
 		IPAWANERR("Error deleting resource %d, ret=%d\n",
 			IPA_RM_RESOURCE_Q6_PROD, ret);
-	destroy_workqueue(ipa_rm_q6_workqueue);
+
+	if (ipa_rm_q6_workqueue)
+		destroy_workqueue(ipa_rm_q6_workqueue);
 }
 
 static void wake_tx_queue(struct work_struct *work)
@@ -2186,7 +2188,10 @@
 		IPAWANERR("Error deleting resource %d, ret=%d\n",
 		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
 create_rsrc_err:
-	q6_deinitialize_rm();
+
+	if (!atomic_read(&is_ssr))
+		q6_deinitialize_rm();
+
 q6_init_err:
 	free_netdev(ipa_netdevs[0]);
 	ipa_netdevs[0] = NULL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/Makefile b/drivers/platform/msm/ipa/ipa_v3/Makefile
index a4faaea..e3f8d45 100644
--- a/drivers/platform/msm/ipa/ipa_v3/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v3/Makefile
@@ -3,6 +3,7 @@
 obj-$(CONFIG_IPA3) += ipat.o
 ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o \
 	ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o \
-	ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o ipa_uc_ntn.o
+	ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o ipa_uc_ntn.o \
+	ipa_hw_stats.o
 
 obj-$(CONFIG_RMNET_IPA3) += rmnet_ipa.o ipa_qmi_service_v01.o ipa_qmi_service.o rmnet_ipa_fd_ioctl.o
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 4b056f6c..4d4e993 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -266,7 +266,9 @@
 	int cnt = 0;
 	int start_idx;
 	int end_idx;
+	unsigned long flags;
 
+	spin_lock_irqsave(&ipa3_ctx->ipa3_active_clients_logging.lock, flags);
 	start_idx = (ipa3_ctx->ipa3_active_clients_logging.log_tail + 1) %
 			IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES;
 	end_idx = ipa3_ctx->ipa3_active_clients_logging.log_head;
@@ -277,6 +279,8 @@
 				.log_buffer[i]);
 		cnt += nbytes;
 	}
+	spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
+		flags);
 
 	return cnt;
 }
@@ -286,7 +290,9 @@
 	int i;
 	struct ipa3_active_client_htable_entry *iterator;
 	int cnt = 0;
+	unsigned long flags;
 
+	spin_lock_irqsave(&ipa3_ctx->ipa3_active_clients_logging.lock, flags);
 	cnt = scnprintf(buf, size, "\n---- Active Clients Table ----\n");
 	hash_for_each(ipa3_ctx->ipa3_active_clients_logging.htable, i,
 			iterator, list) {
@@ -319,6 +325,8 @@
 	cnt += scnprintf(buf + cnt, size - cnt,
 			"\nTotal active clients count: %d\n",
 			atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
+	spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
+		flags);
 
 	return cnt;
 }
@@ -368,6 +376,7 @@
 {
 	int i;
 
+	spin_lock_init(&ipa3_ctx->ipa3_active_clients_logging.lock);
 	ipa3_ctx->ipa3_active_clients_logging.log_buffer[0] = kzalloc(
 			IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES *
 			sizeof(char[IPA3_ACTIVE_CLIENTS_LOG_LINE_LEN]),
@@ -399,20 +408,28 @@
 
 void ipa3_active_clients_log_clear(void)
 {
-	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipa3_ctx->ipa3_active_clients_logging.lock, flags);
 	ipa3_ctx->ipa3_active_clients_logging.log_head = 0;
 	ipa3_ctx->ipa3_active_clients_logging.log_tail =
 			IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1;
-	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
+	spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
+		flags);
 }
 
 static void ipa3_active_clients_log_destroy(void)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipa3_ctx->ipa3_active_clients_logging.lock, flags);
 	ipa3_ctx->ipa3_active_clients_logging.log_rdy = 0;
 	kfree(ipa3_ctx->ipa3_active_clients_logging.log_buffer[0]);
 	ipa3_ctx->ipa3_active_clients_logging.log_head = 0;
 	ipa3_ctx->ipa3_active_clients_logging.log_tail =
 			IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1;
+	spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
+		flags);
 }
 
 enum ipa_smmu_cb_type {
@@ -542,7 +559,7 @@
 	msg_meta.msg_len = sizeof(struct ipa_wan_msg);
 	retval = ipa3_send_msg(&msg_meta, wan_msg, ipa3_wan_msg_free_cb);
 	if (retval) {
-		IPAERR("ipa3_send_msg failed: %d\n", retval);
+		IPAERR_RL("ipa3_send_msg failed: %d\n", retval);
 		kfree(wan_msg);
 		return retval;
 	}
@@ -719,7 +736,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_nat_dma_cmd *)param)->entries,
 				pre_entry);
 			retval = -EFAULT;
@@ -778,7 +795,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_hdr *)param)->num_hdrs,
 				pre_entry);
 			retval = -EFAULT;
@@ -817,7 +834,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_hdr *)param)->num_hdls,
 				pre_entry);
 			retval = -EFAULT;
@@ -857,7 +874,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_rt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -897,7 +914,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_rt_rule_after *)param)->
 			num_rules != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_rt_rule_after *)param)->
 				num_rules,
 				pre_entry);
@@ -939,7 +956,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_mdfy_rt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -979,7 +996,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_rt_rule *)param)->num_hdls,
 				pre_entry);
 			retval = -EFAULT;
@@ -1018,7 +1035,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_flt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -1060,7 +1077,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_flt_rule_after *)param)->
 			num_rules != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_flt_rule_after *)param)->
 				num_rules,
 				pre_entry);
@@ -1101,7 +1118,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_flt_rule *)param)->
 				num_hdls,
 				pre_entry);
@@ -1141,7 +1158,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_mdfy_flt_rule *)param)->
 				num_rules,
 				pre_entry);
@@ -1279,7 +1296,7 @@
 		if (unlikely(((struct ipa_ioc_query_intf_tx_props *)
 			param)->num_tx_props
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_query_intf_tx_props *)
 				param)->num_tx_props, pre_entry);
 			retval = -EFAULT;
@@ -1324,7 +1341,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_query_intf_rx_props *)
 			param)->num_rx_props != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_query_intf_rx_props *)
 				param)->num_rx_props, pre_entry);
 			retval = -EFAULT;
@@ -1369,7 +1386,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_query_intf_ext_props *)
 			param)->num_ext_props != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_query_intf_ext_props *)
 				param)->num_ext_props, pre_entry);
 			retval = -EFAULT;
@@ -1407,7 +1424,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_msg_meta *)param)->msg_len
 			!= pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_msg_meta *)param)->msg_len,
 				pre_entry);
 			retval = -EFAULT;
@@ -1547,7 +1564,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *)
 			param)->num_proc_ctxs != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_add_hdr_proc_ctx *)
 				param)->num_proc_ctxs, pre_entry);
 			retval = -EFAULT;
@@ -1586,7 +1603,7 @@
 		/* add check in case user-space module compromised */
 		if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *)
 			param)->num_hdls != pre_entry)) {
-			IPAERR("current %d pre %d\n",
+			IPAERR_RL("current %d pre %d\n",
 				((struct ipa_ioc_del_hdr_proc_ctx *)param)->
 				num_hdls,
 				pre_entry);
@@ -3402,7 +3419,10 @@
 	struct ipa3_active_client_htable_entry *hfound;
 	u32 hkey;
 	char str_to_hash[IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN];
+	unsigned long flags;
 
+	spin_lock_irqsave(&ipa3_ctx->ipa3_active_clients_logging.lock, flags);
+	int_ctx = true;
 	hfound = NULL;
 	memset(str_to_hash, 0, IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN);
 	strlcpy(str_to_hash, id->id_string, IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN);
@@ -3422,6 +3442,9 @@
 				int_ctx ? GFP_ATOMIC : GFP_KERNEL);
 		if (hentry == NULL) {
 			IPAERR("failed allocating active clients hash entry");
+			spin_unlock_irqrestore(
+				&ipa3_ctx->ipa3_active_clients_logging.lock,
+				flags);
 			return;
 		}
 		hentry->type = id->type;
@@ -3446,6 +3469,8 @@
 				id->id_string, id->file, id->line);
 		ipa3_active_clients_log_insert(temp_str);
 	}
+	spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
+		flags);
 }
 
 void ipa3_active_clients_log_dec(struct ipa_active_client_logging_info *id,
@@ -3922,14 +3947,17 @@
 	int i;
 	struct ipa3_flt_tbl *flt_tbl;
 
+	idr_destroy(&ipa3_ctx->flt_rule_ids[IPA_IP_v4]);
+	idr_destroy(&ipa3_ctx->flt_rule_ids[IPA_IP_v6]);
+
 	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
 		if (!ipa_is_ep_support_flt(i))
 			continue;
 
 		flt_tbl = &ipa3_ctx->flt_tbl[i][IPA_IP_v4];
-		idr_destroy(&flt_tbl->rule_ids);
+		flt_tbl->rule_ids = NULL;
 		flt_tbl = &ipa3_ctx->flt_tbl[i][IPA_IP_v6];
-		idr_destroy(&flt_tbl->rule_ids);
+		flt_tbl->rule_ids = NULL;
 	}
 }
 
@@ -4104,6 +4132,7 @@
 	struct ipa3_uc_hdlrs uc_hdlrs = { 0 };
 	struct ipa3_flt_tbl *flt_tbl;
 	int i;
+	struct idr *idr;
 
 	if (ipa3_ctx == NULL) {
 		IPADBG("IPA driver haven't initialized\n");
@@ -4127,6 +4156,11 @@
 	/* Assign resource limitation to each group */
 	ipa3_set_resorce_groups_min_max_limits();
 
+	idr = &(ipa3_ctx->flt_rule_ids[IPA_IP_v4]);
+	idr_init(idr);
+	idr = &(ipa3_ctx->flt_rule_ids[IPA_IP_v6]);
+	idr_init(idr);
+
 	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
 		if (!ipa_is_ep_support_flt(i))
 			continue;
@@ -4137,7 +4171,7 @@
 			!ipa3_ctx->ip4_flt_tbl_hash_lcl;
 		flt_tbl->in_sys[IPA_RULE_NON_HASHABLE] =
 			!ipa3_ctx->ip4_flt_tbl_nhash_lcl;
-		idr_init(&flt_tbl->rule_ids);
+		flt_tbl->rule_ids = &ipa3_ctx->flt_rule_ids[IPA_IP_v4];
 
 		flt_tbl = &ipa3_ctx->flt_tbl[i][IPA_IP_v6];
 		INIT_LIST_HEAD(&flt_tbl->head_flt_rule_list);
@@ -4145,7 +4179,7 @@
 			!ipa3_ctx->ip6_flt_tbl_hash_lcl;
 		flt_tbl->in_sys[IPA_RULE_NON_HASHABLE] =
 			!ipa3_ctx->ip6_flt_tbl_nhash_lcl;
-		idr_init(&flt_tbl->rule_ids);
+		flt_tbl->rule_ids = &ipa3_ctx->flt_rule_ids[IPA_IP_v6];
 	}
 
 	if (!ipa3_ctx->apply_rg10_wa) {
@@ -4230,6 +4264,12 @@
 	else
 		IPADBG(":ntn init ok\n");
 
+	result = ipa_hw_stats_init();
+	if (result)
+		IPAERR("fail to init stats %d\n", result);
+	else
+		IPADBG(":stats init ok\n");
+
 	ipa3_register_panic_hdlr();
 
 	ipa3_ctx->q6_proxy_clk_vote_valid = true;
@@ -4790,12 +4830,16 @@
 				hdr_proc_ctx_tbl.head_free_offset_list[i]);
 	}
 	INIT_LIST_HEAD(&ipa3_ctx->rt_tbl_set[IPA_IP_v4].head_rt_tbl_list);
+	idr_init(&ipa3_ctx->rt_tbl_set[IPA_IP_v4].rule_ids);
 	INIT_LIST_HEAD(&ipa3_ctx->rt_tbl_set[IPA_IP_v6].head_rt_tbl_list);
+	idr_init(&ipa3_ctx->rt_tbl_set[IPA_IP_v6].rule_ids);
 
 	rset = &ipa3_ctx->reap_rt_tbl_set[IPA_IP_v4];
 	INIT_LIST_HEAD(&rset->head_rt_tbl_list);
+	idr_init(&rset->rule_ids);
 	rset = &ipa3_ctx->reap_rt_tbl_set[IPA_IP_v6];
 	INIT_LIST_HEAD(&rset->head_rt_tbl_list);
+	idr_init(&rset->rule_ids);
 
 	INIT_LIST_HEAD(&ipa3_ctx->intf_list);
 	INIT_LIST_HEAD(&ipa3_ctx->msg_list);
@@ -4915,6 +4959,12 @@
 fail_device_create:
 	unregister_chrdev_region(ipa3_ctx->dev_num, 1);
 fail_alloc_chrdev_region:
+	rset = &ipa3_ctx->reap_rt_tbl_set[IPA_IP_v6];
+	idr_destroy(&rset->rule_ids);
+	rset = &ipa3_ctx->reap_rt_tbl_set[IPA_IP_v4];
+	idr_destroy(&rset->rule_ids);
+	idr_destroy(&ipa3_ctx->rt_tbl_set[IPA_IP_v6].rule_ids);
+	idr_destroy(&ipa3_ctx->rt_tbl_set[IPA_IP_v4].rule_ids);
 	ipa3_free_dma_task_for_gsi();
 fail_dma_task:
 	idr_destroy(&ipa3_ctx->ipa_idr);
@@ -5570,6 +5620,10 @@
 	struct device_node *node = dev->of_node;
 	int res;
 
+	if (ipa3_ctx == NULL) {
+		IPAERR("ipa3_ctx was not initialized\n");
+		return -ENXIO;
+	}
 	IPADBG("node->name=%s\n", node->name);
 	if (strcmp("qcom,smp2pgpio_map_ipa_1_out", node->name) == 0) {
 		res = of_get_gpio(node, 0);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index f172dc4..9486b0a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -2169,6 +2169,8 @@
 		goto fail;
 	}
 
+	ipa_debugfs_init_stats(dent);
+
 	return;
 
 fail:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
index a95547c..5a29cbc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
@@ -941,10 +941,10 @@
 
 	ipa3_dma_debugfs_destroy();
 	kmem_cache_destroy(ipa3_dma_ctx->ipa_dma_xfer_wrapper_cache);
-	kfree(ipa3_dma_ctx);
 	dma_free_coherent(ipa3_ctx->pdev, IPA_DMA_DUMMY_BUFF_SZ * 4,
 		ipa3_dma_ctx->ipa_dma_dummy_src_sync.base,
 		ipa3_dma_ctx->ipa_dma_dummy_src_sync.phys_base);
+	kfree(ipa3_dma_ctx);
 	ipa3_dma_ctx = NULL;
 
 	IPADMA_FUNC_EXIT();
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 018467a..02c5991 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -2574,6 +2574,7 @@
 		WARN_ON(1);
 		return;
 	}
+	spin_lock_bh(&sys->spinlock);
 	rx_pkt_expected = list_first_entry(&sys->head_desc_list,
 					   struct ipa3_rx_pkt_wrapper,
 					   link);
@@ -2581,6 +2582,7 @@
 	sys->len--;
 	if (size)
 		rx_pkt_expected->len = size;
+	spin_unlock_bh(&sys->spinlock);
 	rx_skb = rx_pkt_expected->data.skb;
 	dma_unmap_single(ipa3_ctx->pdev, rx_pkt_expected->data.dma_addr,
 			sys->rx_buff_sz, DMA_FROM_DEVICE);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
index b1e50ac..beca549 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
@@ -806,7 +806,7 @@
 	if (rule->rule_id) {
 		id = rule->rule_id;
 	} else {
-		id = ipa3_alloc_rule_id(&tbl->rule_ids);
+		id = ipa3_alloc_rule_id(tbl->rule_ids);
 		if (id < 0) {
 			IPAERR("failed to allocate rule id\n");
 			WARN_ON(1);
@@ -880,7 +880,7 @@
 	list_del(&entry->link);
 	/* if rule id was allocated from idr, remove it */
 	if (!(entry->rule_id & ipahal_get_rule_id_hi_bit()))
-		idr_remove(&entry->tbl->rule_ids, entry->rule_id);
+		idr_remove(entry->tbl->rule_ids, entry->rule_id);
 	kmem_cache_free(ipa3_ctx->flt_rule_cache, entry);
 
 error:
@@ -900,7 +900,7 @@
 		goto error;
 
 	if (rule == NULL || rule_hdl == NULL) {
-		IPAERR("bad parms rule=%p rule_hdl=%p\n", rule,
+		IPAERR_RL("bad parms rule=%p rule_hdl=%p\n", rule,
 				rule_hdl);
 		goto error;
 	}
@@ -927,7 +927,7 @@
 	list_del(&entry->link);
 	/* if rule id was allocated from idr, remove it */
 	if (!(entry->rule_id & ipahal_get_rule_id_hi_bit()))
-		idr_remove(&entry->tbl->rule_ids, entry->rule_id);
+		idr_remove(entry->tbl->rule_ids, entry->rule_id);
 	kmem_cache_free(ipa3_ctx->flt_rule_cache, entry);
 
 error:
@@ -942,12 +942,12 @@
 
 	entry = ipa3_id_find(rule_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EINVAL;
 	}
 
 	if (entry->cookie != IPA_FLT_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		return -EINVAL;
 	}
 	id = entry->id;
@@ -961,7 +961,7 @@
 	entry->cookie = 0;
 	/* if rule id was allocated from idr, remove it */
 	if (!(entry->rule_id & ipahal_get_rule_id_hi_bit()))
-		idr_remove(&entry->tbl->rule_ids, entry->rule_id);
+		idr_remove(entry->tbl->rule_ids, entry->rule_id);
 
 	kmem_cache_free(ipa3_ctx->flt_rule_cache, entry);
 
@@ -979,12 +979,12 @@
 
 	entry = ipa3_id_find(frule->rule_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		goto error;
 	}
 
 	if (entry->cookie != IPA_FLT_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		goto error;
 	}
 
@@ -994,25 +994,25 @@
 	if (frule->rule.action != IPA_PASS_TO_EXCEPTION) {
 		if (!frule->rule.eq_attrib_type) {
 			if (!frule->rule.rt_tbl_hdl) {
-				IPAERR("invalid RT tbl\n");
+				IPAERR_RL("invalid RT tbl\n");
 				goto error;
 			}
 
 			rt_tbl = ipa3_id_find(frule->rule.rt_tbl_hdl);
 			if (rt_tbl == NULL) {
-				IPAERR("RT tbl not found\n");
+				IPAERR_RL("RT tbl not found\n");
 				goto error;
 			}
 
 			if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) {
-				IPAERR("RT table cookie is invalid\n");
+				IPAERR_RL("RT table cookie is invalid\n");
 				goto error;
 			}
 		} else {
 			if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ?
 				IPA_MEM_PART(v4_modem_rt_index_hi) :
 				IPA_MEM_PART(v6_modem_rt_index_hi))) {
-				IPAERR("invalid RT tbl\n");
+				IPAERR_RL("invalid RT tbl\n");
 				goto error;
 			}
 		}
@@ -1057,7 +1057,7 @@
 	int ipa_ep_idx;
 
 	if (rule == NULL || rule_hdl == NULL || ep >= IPA_CLIENT_MAX) {
-		IPAERR("bad parms rule=%p rule_hdl=%p ep=%d\n", rule,
+		IPAERR_RL("bad parms rule=%p rule_hdl=%p ep=%d\n", rule,
 				rule_hdl, ep);
 
 		return -EINVAL;
@@ -1087,7 +1087,7 @@
 
 	if (rules == NULL || rules->num_rules == 0 ||
 			rules->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1102,7 +1102,7 @@
 			result = -1;
 
 		if (result) {
-			IPAERR("failed to add flt rule %d\n", i);
+			IPAERR_RL("failed to add flt rule %d\n", i);
 			rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED;
 		} else {
 			rules->rules[i].status = 0;
@@ -1110,7 +1110,7 @@
 	}
 
 	if (rules->global) {
-		IPAERR("no support for global filter rules\n");
+		IPAERR_RL("no support for global filter rules\n");
 		result = -EPERM;
 		goto bail;
 	}
@@ -1145,12 +1145,12 @@
 
 	if (rules == NULL || rules->num_rules == 0 ||
 			rules->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	if (rules->ep >= IPA_CLIENT_MAX) {
-		IPAERR("bad parms ep=%d\n", rules->ep);
+		IPAERR_RL("bad parms ep=%d\n", rules->ep);
 		return -EINVAL;
 	}
 
@@ -1165,20 +1165,20 @@
 
 	entry = ipa3_id_find(rules->add_after_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		result = -EINVAL;
 		goto bail;
 	}
 
 	if (entry->tbl != tbl) {
-		IPAERR("given entry does not match the table\n");
+		IPAERR_RL("given entry does not match the table\n");
 		result = -EINVAL;
 		goto bail;
 	}
 
 	if (tbl->sticky_rear)
 		if (&entry->link == tbl->head_flt_rule_list.prev) {
-			IPAERR("cannot add rule at end of a sticky table");
+			IPAERR_RL("cannot add rule at end of a sticky table");
 			result = -EINVAL;
 			goto bail;
 		}
@@ -1200,7 +1200,7 @@
 				&entry);
 
 		if (result) {
-			IPAERR("failed to add flt rule %d\n", i);
+			IPAERR_RL("failed to add flt rule %d\n", i);
 			rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED;
 		} else {
 			rules->rules[i].status = 0;
@@ -1234,14 +1234,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa3_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa_del_flt_rule(hdls->hdl[i].hdl)) {
-			IPAERR("failed to del flt rule %i\n", i);
+			IPAERR_RL("failed to del flt rule %i\n", i);
 			hdls->hdl[i].status = IPA_FLT_STATUS_OF_DEL_FAILED;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1274,14 +1274,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa3_ctx->lock);
 	for (i = 0; i < hdls->num_rules; i++) {
 		if (__ipa_mdfy_flt_rule(&hdls->rules[i], hdls->ip)) {
-			IPAERR("failed to mdfy flt rule %i\n", i);
+			IPAERR_RL("failed to mdfy flt rule %i\n", i);
 			hdls->rules[i].status = IPA_FLT_STATUS_OF_MDFY_FAILED;
 		} else {
 			hdls->rules[i].status = 0;
@@ -1315,7 +1315,7 @@
 	int result;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1351,7 +1351,7 @@
 	int id;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1374,7 +1374,7 @@
 				entry->rt_tbl->ref_cnt--;
 			/* if rule id was allocated from idr, remove it */
 			if (!(entry->rule_id & ipahal_get_rule_id_hi_bit()))
-				idr_remove(&entry->tbl->rule_ids,
+				idr_remove(entry->tbl->rule_ids,
 					entry->rule_id);
 			entry->cookie = 0;
 			id = entry->id;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index 0c1832c..cc29f8f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -66,12 +66,29 @@
 {
 	struct ipa3_hdr_proc_ctx_entry *entry;
 	int ret;
+	int ep;
 
 	list_for_each_entry(entry,
 			&ipa3_ctx->hdr_proc_ctx_tbl.head_proc_ctx_entry_list,
 			link) {
 		IPADBG_LOW("processing type %d ofst=%d\n",
 			entry->type, entry->offset_entry->offset);
+
+		if (entry->l2tp_params.is_dst_pipe_valid) {
+			ep = ipa3_get_ep_mapping(entry->l2tp_params.dst_pipe);
+			if (ep >= 0) {
+				entry->l2tp_params.hdr_remove_param.
+					hdr_ofst_pkt_size_valid = ipa3_ctx->
+					ep[ep].cfg.hdr.hdr_ofst_pkt_size_valid;
+				entry->l2tp_params.hdr_remove_param.
+					hdr_ofst_pkt_size = ipa3_ctx->ep[ep].
+					cfg.hdr.hdr_ofst_pkt_size;
+				entry->l2tp_params.hdr_remove_param.
+					hdr_endianness = ipa3_ctx->ep[ep].
+					cfg.hdr_ext.hdr_little_endian ? 0 : 1;
+			}
+		}
+
 		ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base,
 				entry->offset_entry->offset,
 				entry->hdr->hdr_len,
@@ -327,17 +344,17 @@
 		proc_ctx->type, proc_ctx->hdr_hdl);
 
 	if (!HDR_PROC_TYPE_IS_VALID(proc_ctx->type)) {
-		IPAERR("invalid processing type %d\n", proc_ctx->type);
+		IPAERR_RL("invalid processing type %d\n", proc_ctx->type);
 		return -EINVAL;
 	}
 
 	hdr_entry = ipa3_id_find(proc_ctx->hdr_hdl);
 	if (!hdr_entry) {
-		IPAERR("hdr_hdl is invalid\n");
+		IPAERR_RL("hdr_hdl is invalid\n");
 		return -EINVAL;
 	}
 	if (hdr_entry->cookie != IPA_HDR_COOKIE) {
-		IPAERR("Invalid header cookie %u\n", hdr_entry->cookie);
+		IPAERR_RL("Invalid header cookie %u\n", hdr_entry->cookie);
 		WARN_ON(1);
 		return -EINVAL;
 	}
@@ -367,7 +384,7 @@
 			ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN1]) {
 		bin = IPA_HDR_PROC_CTX_BIN1;
 	} else {
-		IPAERR("unexpected needed len %d\n", needed_len);
+		IPAERR_RL("unexpected needed len %d\n", needed_len);
 		WARN_ON(1);
 		goto bad_len;
 	}
@@ -377,7 +394,7 @@
 		IPA_MEM_PART(apps_hdr_proc_ctx_size_ddr);
 	if (list_empty(&htbl->head_free_offset_list[bin])) {
 		if (htbl->end + ipa_hdr_proc_ctx_bin_sz[bin] > mem_size) {
-			IPAERR("hdr proc ctx table overflow\n");
+			IPAERR_RL("hdr proc ctx table overflow\n");
 			goto bad_len;
 		}
 
@@ -424,8 +441,7 @@
 	return 0;
 
 ipa_insert_failed:
-	if (offset)
-		list_move(&offset->link,
+	list_move(&offset->link,
 		&htbl->head_free_offset_list[offset->bin]);
 	entry->offset_entry = NULL;
 	list_del(&entry->link);
@@ -450,12 +466,12 @@
 	int mem_size;
 
 	if (hdr->hdr_len == 0 || hdr->hdr_len > IPA_HDR_MAX_SIZE) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		goto error;
 	}
 
 	if (!HDR_TYPE_IS_VALID(hdr->type)) {
-		IPAERR("invalid hdr type %d\n", hdr->type);
+		IPAERR_RL("invalid hdr type %d\n", hdr->type);
 		goto error;
 	}
 
@@ -487,7 +503,7 @@
 	else if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN4])
 		bin = IPA_HDR_BIN4;
 	else {
-		IPAERR("unexpected hdr len %d\n", hdr->hdr_len);
+		IPAERR_RL("unexpected hdr len %d\n", hdr->hdr_len);
 		goto bad_hdr_len;
 	}
 
@@ -609,7 +625,7 @@
 
 	entry = ipa3_id_find(proc_ctx_hdl);
 	if (!entry || (entry->cookie != IPA_PROC_HDR_COOKIE)) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -617,7 +633,7 @@
 		htbl->proc_ctx_cnt, entry->offset_entry->offset);
 
 	if (by_user && entry->user_deleted) {
-		IPAERR("proc_ctx already deleted by user\n");
+		IPAERR_RL("proc_ctx already deleted by user\n");
 		return -EINVAL;
 	}
 
@@ -655,12 +671,12 @@
 
 	entry = ipa3_id_find(hdr_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EINVAL;
 	}
 
 	if (entry->cookie != IPA_HDR_COOKIE) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -673,7 +689,7 @@
 			entry->offset_entry->offset);
 
 	if (by_user && entry->user_deleted) {
-		IPAERR("proc_ctx already deleted by user\n");
+		IPAERR_RL("proc_ctx already deleted by user\n");
 		return -EINVAL;
 	}
 
@@ -722,7 +738,7 @@
 	int result = -EFAULT;
 
 	if (hdrs == NULL || hdrs->num_hdrs == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -731,7 +747,7 @@
 			hdrs->num_hdrs);
 	for (i = 0; i < hdrs->num_hdrs; i++) {
 		if (__ipa_add_hdr(&hdrs->hdr[i])) {
-			IPAERR("failed to add hdr %d\n", i);
+			IPAERR_RL("failed to add hdr %d\n", i);
 			hdrs->hdr[i].status = -1;
 		} else {
 			hdrs->hdr[i].status = 0;
@@ -767,14 +783,14 @@
 	int result = -EFAULT;
 
 	if (hdls == NULL || hdls->num_hdls == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa3_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa3_del_hdr(hdls->hdl[i].hdl, by_user)) {
-			IPAERR("failed to del hdr %i\n", i);
+			IPAERR_RL("failed to del hdr %i\n", i);
 			hdls->hdl[i].status = -1;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -822,7 +838,7 @@
 	int result = -EFAULT;
 
 	if (proc_ctxs == NULL || proc_ctxs->num_proc_ctxs == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -831,7 +847,7 @@
 			proc_ctxs->num_proc_ctxs);
 	for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) {
 		if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) {
-			IPAERR("failed to add hdr pric ctx %d\n", i);
+			IPAERR_RL("failed to add hdr pric ctx %d\n", i);
 			proc_ctxs->proc_ctx[i].status = -1;
 		} else {
 			proc_ctxs->proc_ctx[i].status = 0;
@@ -869,14 +885,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_hdls == 0) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa3_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa3_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) {
-			IPAERR("failed to del hdr %i\n", i);
+			IPAERR_RL("failed to del hdr %i\n", i);
 			hdls->hdl[i].status = -1;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1083,7 +1099,7 @@
 	struct ipa3_hdr_entry *entry;
 
 	if (strnlen(name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) {
-		IPAERR("Header name too long: %s\n", name);
+		IPAERR_RL("Header name too long: %s\n", name);
 		return NULL;
 	}
 
@@ -1113,7 +1129,7 @@
 	int result = -1;
 
 	if (lookup == NULL) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 	mutex_lock(&ipa3_ctx->lock);
@@ -1200,13 +1216,13 @@
 
 	entry = ipa3_id_find(hdr_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		result = -EINVAL;
 		goto bail;
 	}
 
 	if (entry->cookie != IPA_HDR_COOKIE) {
-		IPAERR("invalid header entry\n");
+		IPAERR_RL("invalid header entry\n");
 		result = -EINVAL;
 		goto bail;
 	}
@@ -1235,7 +1251,7 @@
 	int result = -EFAULT;
 
 	if (copy == NULL) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 	mutex_lock(&ipa3_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
new file mode 100644
index 0000000..8a4d945
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
@@ -0,0 +1,1973 @@
+/* Copyright (c) 2017, 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/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "ipa_i.h"
+#include "ipahal/ipahal.h"
+#include "ipahal/ipahal_hw_stats.h"
+
+#define IPA_CLIENT_BIT_32(client) \
+	((ipa3_get_ep_mapping(client) >= 0 && \
+		ipa3_get_ep_mapping(client) < IPA_STATS_MAX_PIPE_BIT) ? \
+		(1 << ipa3_get_ep_mapping(client)) : 0)
+
+int ipa_hw_stats_init(void)
+{
+	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
+		return 0;
+
+	/* initialize stats here */
+	ipa3_ctx->hw_stats.enabled = true;
+	return 0;
+}
+
+int ipa_init_quota_stats(u32 pipe_bitmask)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipahal_imm_cmd_register_write quota_base = {0};
+	struct ipahal_imm_cmd_pyld *quota_base_pyld;
+	struct ipahal_imm_cmd_register_write quota_mask = {0};
+	struct ipahal_imm_cmd_pyld *quota_mask_pyld;
+	struct ipa3_desc desc[3] = { {0} };
+	dma_addr_t dma_address;
+	int ret;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	/* reset driver's cache */
+	memset(&ipa3_ctx->hw_stats.quota, 0, sizeof(ipa3_ctx->hw_stats.quota));
+	ipa3_ctx->hw_stats.quota.init.enabled_bitmask = pipe_bitmask;
+	IPADBG_LOW("pipe_bitmask=0x%x\n", pipe_bitmask);
+
+	pyld = ipahal_stats_generate_init_pyld(IPAHAL_HW_STATS_QUOTA,
+		&ipa3_ctx->hw_stats.quota.init, false);
+	if (!pyld) {
+		IPAERR("failed to generate pyld\n");
+		return -EPERM;
+	}
+
+	if (pyld->len > IPA_MEM_PART(stats_quota_size)) {
+		IPAERR("SRAM partition too small: %d needed %d\n",
+			IPA_MEM_PART(stats_quota_size), pyld->len);
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	dma_address = dma_map_single(ipa3_ctx->pdev,
+		pyld->data,
+		pyld->len,
+		DMA_TO_DEVICE);
+	if (dma_mapping_error(ipa3_ctx->pdev, dma_address)) {
+		IPAERR("failed to DMA map\n");
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	/* setting the registers and init the stats pyld are done atomically */
+	quota_mask.skip_pipeline_clear = false;
+	quota_mask.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	quota_mask.offset = ipahal_get_reg_n_ofst(IPA_STAT_QUOTA_MASK_n,
+		ipa3_ctx->ee);
+	quota_mask.value = pipe_bitmask;
+	quota_mask.value_mask = ~0;
+	quota_mask_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&quota_mask, false);
+	if (!quota_mask_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto unmap;
+	}
+	desc[0].opcode = quota_mask_pyld->opcode;
+	desc[0].pyld = quota_mask_pyld->data;
+	desc[0].len = quota_mask_pyld->len;
+	desc[0].type = IPA_IMM_CMD_DESC;
+
+	quota_base.skip_pipeline_clear = false;
+	quota_base.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	quota_base.offset = ipahal_get_reg_n_ofst(IPA_STAT_QUOTA_BASE_n,
+		ipa3_ctx->ee);
+	quota_base.value = ipa3_ctx->smem_restricted_bytes +
+		IPA_MEM_PART(stats_quota_ofst);
+	quota_base.value_mask = ~0;
+	quota_base_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&quota_base, false);
+	if (!quota_base_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_quota_mask;
+	}
+	desc[1].opcode = quota_base_pyld->opcode;
+	desc[1].pyld = quota_base_pyld->data;
+	desc[1].len = quota_base_pyld->len;
+	desc[1].type = IPA_IMM_CMD_DESC;
+
+	cmd.is_read = false;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	cmd.size = pyld->len;
+	cmd.system_addr = dma_address;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+			IPA_MEM_PART(stats_quota_ofst);
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_quota_base;
+	}
+	desc[2].opcode = cmd_pyld->opcode;
+	desc[2].pyld = cmd_pyld->data;
+	desc[2].len = cmd_pyld->len;
+	desc[2].type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(3, desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	ret = 0;
+
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+destroy_quota_base:
+	ipahal_destroy_imm_cmd(quota_base_pyld);
+destroy_quota_mask:
+	ipahal_destroy_imm_cmd(quota_mask_pyld);
+unmap:
+	dma_unmap_single(ipa3_ctx->pdev, dma_address, pyld->len, DMA_TO_DEVICE);
+destroy_init_pyld:
+	ipahal_destroy_stats_init_pyld(pyld);
+	return ret;
+}
+
+int ipa_get_quota_stats(struct ipa_quota_stats_all *out)
+{
+	int i;
+	int ret;
+	struct ipahal_stats_get_offset_quota get_offset = { { 0 } };
+	struct ipahal_stats_offset offset = { 0 };
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipa_mem_buffer mem;
+	struct ipa3_desc desc = { 0 };
+	struct ipahal_stats_quota_all *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	get_offset.init = ipa3_ctx->hw_stats.quota.init;
+	ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_QUOTA, &get_offset,
+		&offset);
+	if (ret) {
+		IPAERR("failed to get offset from hal %d\n", ret);
+		return ret;
+	}
+
+	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+
+	mem.size = offset.size;
+	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
+		mem.size,
+		&mem.phys_base,
+		GFP_KERNEL);
+	if (!mem.base) {
+		IPAERR("fail to alloc DMA memory");
+		return ret;
+	}
+
+	cmd.is_read = true;
+	cmd.clear_after_read = true;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+	cmd.size = mem.size;
+	cmd.system_addr = mem.phys_base;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+		IPA_MEM_PART(stats_quota_ofst) + offset.offset;
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto free_dma_mem;
+	}
+	desc.opcode = cmd_pyld->opcode;
+	desc.pyld = cmd_pyld->data;
+	desc.len = cmd_pyld->len;
+	desc.type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(1, &desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	stats = kzalloc(sizeof(*stats), GFP_KERNEL);
+	if (!stats) {
+		IPADBG("failed to alloc memory\n");
+		ret = -ENOMEM;
+		goto destroy_imm;
+	}
+
+	ret = ipahal_parse_stats(IPAHAL_HW_STATS_QUOTA,
+		&ipa3_ctx->hw_stats.quota.init, mem.base, stats);
+	if (ret) {
+		IPAERR("failed to parse stats (error %d)\n", ret);
+		goto free_stats;
+	}
+
+	/*
+	 * update driver cache.
+	 * the stats were read from hardware with clear_after_read meaning
+	 * hardware stats are 0 now
+	 */
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		int ep_idx = ipa3_get_ep_mapping(i);
+
+		if (ep_idx == -1 || ep_idx >= IPA3_MAX_NUM_PIPES)
+			continue;
+
+		if (ipa3_ctx->ep[ep_idx].client != i)
+			continue;
+
+		ipa3_ctx->hw_stats.quota.stats.client[i].num_ipv4_bytes +=
+			stats->stats[ep_idx].num_ipv4_bytes;
+		ipa3_ctx->hw_stats.quota.stats.client[i].num_ipv4_pkts +=
+			stats->stats[ep_idx].num_ipv4_pkts;
+		ipa3_ctx->hw_stats.quota.stats.client[i].num_ipv6_bytes +=
+			stats->stats[ep_idx].num_ipv6_bytes;
+		ipa3_ctx->hw_stats.quota.stats.client[i].num_ipv6_pkts +=
+			stats->stats[ep_idx].num_ipv6_pkts;
+	}
+
+	/* copy results to out parameter */
+	if (out)
+		*out = ipa3_ctx->hw_stats.quota.stats;
+	ret = 0;
+free_stats:
+	kfree(stats);
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+free_dma_mem:
+	dma_free_coherent(ipa3_ctx->pdev, mem.size, mem.base, mem.phys_base);
+	return ret;
+
+}
+
+int ipa_reset_quota_stats(enum ipa_client_type client)
+{
+	int ret;
+	struct ipa_quota_stats *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (client >= IPA_CLIENT_MAX) {
+		IPAERR("invalid client %d\n", client);
+		return -EINVAL;
+	}
+
+	/* reading stats will reset them in hardware */
+	ret = ipa_get_quota_stats(NULL);
+	if (ret) {
+		IPAERR("ipa_get_quota_stats failed %d\n", ret);
+		return ret;
+	}
+
+	/* reset driver's cache */
+	stats = &ipa3_ctx->hw_stats.quota.stats.client[client];
+	memset(stats, 0, sizeof(*stats));
+	return 0;
+}
+
+int ipa_reset_all_quota_stats(void)
+{
+	int ret;
+	struct ipa_quota_stats_all *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	/* reading stats will reset them in hardware */
+	ret = ipa_get_quota_stats(NULL);
+	if (ret) {
+		IPAERR("ipa_get_quota_stats failed %d\n", ret);
+		return ret;
+	}
+
+	/* reset driver's cache */
+	stats = &ipa3_ctx->hw_stats.quota.stats;
+	memset(stats, 0, sizeof(*stats));
+	return 0;
+}
+
+int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipahal_imm_cmd_register_write teth_base = {0};
+	struct ipahal_imm_cmd_pyld *teth_base_pyld;
+	struct ipahal_imm_cmd_register_write teth_mask = { 0 };
+	struct ipahal_imm_cmd_pyld *teth_mask_pyld;
+	struct ipa3_desc desc[3] = { {0} };
+	dma_addr_t dma_address;
+	int ret;
+	int i;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (!in || !in->prod_mask) {
+		IPAERR("invalid params\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < IPA_STATS_MAX_PIPE_BIT; i++) {
+		if ((in->prod_mask & (1 << i)) && !in->dst_ep_mask[i]) {
+			IPAERR("prod %d doesn't have cons\n", i);
+			return -EINVAL;
+		}
+	}
+	IPADBG_LOW("prod_mask=0x%x\n", in->prod_mask);
+
+	/* reset driver's cache */
+	memset(&ipa3_ctx->hw_stats.teth.init, 0,
+		sizeof(ipa3_ctx->hw_stats.teth.init));
+	for (i = 0; i < IPA_CLIENT_MAX; i++)
+		memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0,
+			sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i]));
+	ipa3_ctx->hw_stats.teth.init.prod_bitmask = in->prod_mask;
+	memcpy(ipa3_ctx->hw_stats.teth.init.cons_bitmask, in->dst_ep_mask,
+		sizeof(ipa3_ctx->hw_stats.teth.init.cons_bitmask));
+
+
+	pyld = ipahal_stats_generate_init_pyld(IPAHAL_HW_STATS_TETHERING,
+		&ipa3_ctx->hw_stats.teth.init, false);
+	if (!pyld) {
+		IPAERR("failed to generate pyld\n");
+		return -EPERM;
+	}
+
+	if (pyld->len > IPA_MEM_PART(stats_tethering_size)) {
+		IPAERR("SRAM partition too small: %d needed %d\n",
+			IPA_MEM_PART(stats_tethering_size), pyld->len);
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	dma_address = dma_map_single(ipa3_ctx->pdev,
+		pyld->data,
+		pyld->len,
+		DMA_TO_DEVICE);
+	if (dma_mapping_error(ipa3_ctx->pdev, dma_address)) {
+		IPAERR("failed to DMA map\n");
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	/* setting the registers and init the stats pyld are done atomically */
+	teth_mask.skip_pipeline_clear = false;
+	teth_mask.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	teth_mask.offset = ipahal_get_reg_n_ofst(IPA_STAT_TETHERING_MASK_n,
+		ipa3_ctx->ee);
+	teth_mask.value = in->prod_mask;
+	teth_mask.value_mask = ~0;
+	teth_mask_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&teth_mask, false);
+	if (!teth_mask_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto unmap;
+	}
+	desc[0].opcode = teth_mask_pyld->opcode;
+	desc[0].pyld = teth_mask_pyld->data;
+	desc[0].len = teth_mask_pyld->len;
+	desc[0].type = IPA_IMM_CMD_DESC;
+
+	teth_base.skip_pipeline_clear = false;
+	teth_base.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	teth_base.offset = ipahal_get_reg_n_ofst(IPA_STAT_TETHERING_BASE_n,
+		ipa3_ctx->ee);
+	teth_base.value = ipa3_ctx->smem_restricted_bytes +
+		IPA_MEM_PART(stats_tethering_ofst);
+	teth_base.value_mask = ~0;
+	teth_base_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&teth_base, false);
+	if (!teth_base_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_teth_mask;
+	}
+	desc[1].opcode = teth_base_pyld->opcode;
+	desc[1].pyld = teth_base_pyld->data;
+	desc[1].len = teth_base_pyld->len;
+	desc[1].type = IPA_IMM_CMD_DESC;
+
+	cmd.is_read = false;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	cmd.size = pyld->len;
+	cmd.system_addr = dma_address;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+			IPA_MEM_PART(stats_tethering_ofst);
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_teth_base;
+	}
+	desc[2].opcode = cmd_pyld->opcode;
+	desc[2].pyld = cmd_pyld->data;
+	desc[2].len = cmd_pyld->len;
+	desc[2].type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(3, desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	ret = 0;
+
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+destroy_teth_base:
+	ipahal_destroy_imm_cmd(teth_base_pyld);
+destroy_teth_mask:
+	ipahal_destroy_imm_cmd(teth_mask_pyld);
+unmap:
+	dma_unmap_single(ipa3_ctx->pdev, dma_address, pyld->len, DMA_TO_DEVICE);
+destroy_init_pyld:
+	ipahal_destroy_stats_init_pyld(pyld);
+	return ret;
+}
+
+int ipa_get_teth_stats(enum ipa_client_type prod,
+	struct ipa_quota_stats_all *out)
+{
+	int i, j;
+	int ret;
+	struct ipahal_stats_get_offset_tethering get_offset = { { 0 } };
+	struct ipahal_stats_offset offset = {0};
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipa_mem_buffer mem;
+	struct ipa3_desc desc = { 0 };
+	struct ipahal_stats_tethering_all *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (!IPA_CLIENT_IS_PROD(prod) || ipa3_get_ep_mapping(prod) == -1) {
+		IPAERR("invalid prod %d\n", prod);
+		return -EINVAL;
+	}
+
+	get_offset.init = ipa3_ctx->hw_stats.teth.init;
+	ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_TETHERING, &get_offset,
+		&offset);
+	if (ret) {
+		IPAERR("failed to get offset from hal %d\n", ret);
+		return ret;
+	}
+
+	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+
+	mem.size = offset.size;
+	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
+		mem.size,
+		&mem.phys_base,
+		GFP_KERNEL);
+	if (!mem.base) {
+		IPAERR("fail to alloc DMA memory\n");
+		return ret;
+	}
+
+	cmd.is_read = true;
+	cmd.clear_after_read = true;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+	cmd.size = mem.size;
+	cmd.system_addr = mem.phys_base;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+		IPA_MEM_PART(stats_tethering_ofst) + offset.offset;
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto free_dma_mem;
+	}
+	desc.opcode = cmd_pyld->opcode;
+	desc.pyld = cmd_pyld->data;
+	desc.len = cmd_pyld->len;
+	desc.type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(1, &desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	stats = kzalloc(sizeof(*stats), GFP_KERNEL);
+	if (!stats) {
+		IPADBG("failed to alloc memory\n");
+		ret = -ENOMEM;
+		goto destroy_imm;
+	}
+
+	ret = ipahal_parse_stats(IPAHAL_HW_STATS_TETHERING,
+		&ipa3_ctx->hw_stats.teth.init, mem.base, stats);
+	if (ret) {
+		IPAERR("failed to parse stats (error %d)\n", ret);
+		goto free_stats;
+	}
+
+	/*
+	 * update driver cache.
+	 * the stats were read from hardware with clear_after_read meaning
+	 * hardware stats are 0 now
+	 */
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		for (j = 0; j < IPA_CLIENT_MAX; j++) {
+			struct ipa_hw_stats_teth *sw_stats =
+				&ipa3_ctx->hw_stats.teth;
+			int prod_idx = ipa3_get_ep_mapping(i);
+			int cons_idx = ipa3_get_ep_mapping(j);
+
+			if (prod_idx == -1 || prod_idx >= IPA3_MAX_NUM_PIPES)
+				continue;
+
+			if (cons_idx == -1 || cons_idx >= IPA3_MAX_NUM_PIPES)
+				continue;
+
+			if (ipa3_ctx->ep[prod_idx].client != i ||
+			    ipa3_ctx->ep[cons_idx].client != j)
+				continue;
+
+			sw_stats->prod_stats[i].client[j].num_ipv4_bytes +=
+				stats->stats[prod_idx][cons_idx].num_ipv4_bytes;
+			sw_stats->prod_stats[i].client[j].num_ipv4_pkts +=
+				stats->stats[prod_idx][cons_idx].num_ipv4_pkts;
+			sw_stats->prod_stats[i].client[j].num_ipv6_bytes +=
+				stats->stats[prod_idx][cons_idx].num_ipv6_bytes;
+			sw_stats->prod_stats[i].client[j].num_ipv6_pkts +=
+				stats->stats[prod_idx][cons_idx].num_ipv6_pkts;
+		}
+	}
+
+	if (!out) {
+		ret = 0;
+		goto free_stats;
+	}
+
+	/* copy results to out parameter */
+	*out = ipa3_ctx->hw_stats.teth.prod_stats[prod];
+
+	ret = 0;
+free_stats:
+	kfree(stats);
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+free_dma_mem:
+	dma_free_coherent(ipa3_ctx->pdev, mem.size, mem.base, mem.phys_base);
+	return ret;
+
+}
+
+int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons)
+{
+	int ret;
+	struct ipa_quota_stats *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (!IPA_CLIENT_IS_PROD(prod) || !IPA_CLIENT_IS_CONS(cons)) {
+		IPAERR("invalid prod %d or cons %d\n", prod, cons);
+		return -EINVAL;
+	}
+
+	/* reading stats will reset them in hardware */
+	ret = ipa_get_teth_stats(prod, NULL);
+	if (ret) {
+		IPAERR("ipa_get_teth_stats failed %d\n", ret);
+		return ret;
+	}
+
+	/* reset driver's cache */
+	stats = &ipa3_ctx->hw_stats.teth.prod_stats[prod].client[cons];
+	memset(stats, 0, sizeof(*stats));
+	return 0;
+}
+
+int ipa_reset_all_cons_teth_stats(enum ipa_client_type prod)
+{
+	int ret;
+	int i;
+	struct ipa_quota_stats *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (!IPA_CLIENT_IS_PROD(prod)) {
+		IPAERR("invalid prod %d\n", prod);
+		return -EINVAL;
+	}
+
+	/* reading stats will reset them in hardware */
+	ret = ipa_get_teth_stats(prod, NULL);
+	if (ret) {
+		IPAERR("ipa_get_teth_stats failed %d\n", ret);
+		return ret;
+	}
+
+	/* reset driver's cache */
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		stats = &ipa3_ctx->hw_stats.teth.prod_stats[prod].client[i];
+		memset(stats, 0, sizeof(*stats));
+	}
+
+	return 0;
+}
+
+int ipa_reset_all_teth_stats(void)
+{
+	int i;
+	int ret;
+	struct ipa_quota_stats_all *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	/* reading stats will reset them in hardware */
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		if (IPA_CLIENT_IS_PROD(i) && ipa3_get_ep_mapping(i) != -1) {
+			ret = ipa_get_teth_stats(i, NULL);
+			if (ret) {
+				IPAERR("ipa_get_teth_stats failed %d\n", ret);
+				return ret;
+			}
+			/* a single iteration will reset all hardware stats */
+			break;
+		}
+	}
+
+	/* reset driver's cache */
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		stats = &ipa3_ctx->hw_stats.teth.prod_stats[i];
+		memset(stats, 0, sizeof(*stats));
+	}
+
+	return 0;
+}
+
+int ipa_flt_rt_stats_add_rule_id(enum ipa_ip_type ip, bool filtering,
+	u16 rule_id)
+{
+	int rule_idx, rule_bit;
+	u32 *bmsk_ptr;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (ip < 0 || ip >= IPA_IP_MAX) {
+		IPAERR("wrong ip type %d\n", ip);
+		return -EINVAL;
+	}
+
+	rule_idx = rule_id / 32;
+	rule_bit = rule_id % 32;
+
+	if (rule_idx >= IPAHAL_MAX_RULE_ID_32) {
+		IPAERR("invalid rule_id %d\n", rule_id);
+		return -EINVAL;
+	}
+
+	if (ip == IPA_IP_v4 && filtering)
+		bmsk_ptr =
+			ipa3_ctx->hw_stats.flt_rt.flt_v4_init.rule_id_bitmask;
+	else if (ip == IPA_IP_v4)
+		bmsk_ptr =
+			ipa3_ctx->hw_stats.flt_rt.rt_v4_init.rule_id_bitmask;
+	else if (ip == IPA_IP_v6 && filtering)
+		bmsk_ptr =
+			ipa3_ctx->hw_stats.flt_rt.flt_v6_init.rule_id_bitmask;
+	else
+		bmsk_ptr =
+			ipa3_ctx->hw_stats.flt_rt.rt_v6_init.rule_id_bitmask;
+
+	bmsk_ptr[rule_idx] |= (1 << rule_bit);
+
+	return 0;
+}
+
+int ipa_flt_rt_stats_start(enum ipa_ip_type ip, bool filtering)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	int smem_ofst, smem_size, stats_base, start_id_ofst, end_id_ofst;
+	int start_id, end_id;
+	struct ipahal_stats_init_flt_rt *init;
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipahal_imm_cmd_register_write flt_rt_base = {0};
+	struct ipahal_imm_cmd_pyld *flt_rt_base_pyld;
+	struct ipahal_imm_cmd_register_write flt_rt_start_id = {0};
+	struct ipahal_imm_cmd_pyld *flt_rt_start_id_pyld;
+	struct ipahal_imm_cmd_register_write flt_rt_end_id = { 0 };
+	struct ipahal_imm_cmd_pyld *flt_rt_end_id_pyld;
+	struct ipa3_desc desc[4] = { {0} };
+	dma_addr_t dma_address;
+	int ret;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (ip == IPA_IP_v4 && filtering) {
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v4_init;
+		smem_ofst = IPA_MEM_PART(stats_flt_v4_ofst);
+		smem_size = IPA_MEM_PART(stats_flt_v4_size);
+		stats_base = ipahal_get_reg_ofst(IPA_STAT_FILTER_IPV4_BASE);
+		start_id_ofst =
+			ipahal_get_reg_ofst(IPA_STAT_FILTER_IPV4_START_ID);
+		end_id_ofst = ipahal_get_reg_ofst(IPA_STAT_FILTER_IPV4_END_ID);
+	} else if (ip == IPA_IP_v4) {
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v4_init;
+		smem_ofst = IPA_MEM_PART(stats_rt_v4_ofst);
+		smem_size = IPA_MEM_PART(stats_rt_v4_size);
+		stats_base = ipahal_get_reg_ofst(IPA_STAT_ROUTER_IPV4_BASE);
+		start_id_ofst =
+			ipahal_get_reg_ofst(IPA_STAT_ROUTER_IPV4_START_ID);
+		end_id_ofst = ipahal_get_reg_ofst(IPA_STAT_ROUTER_IPV4_END_ID);
+	} else if (ip == IPA_IP_v6 && filtering) {
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v6_init;
+		smem_ofst = IPA_MEM_PART(stats_flt_v6_ofst);
+		smem_size = IPA_MEM_PART(stats_flt_v6_size);
+		stats_base = ipahal_get_reg_ofst(IPA_STAT_FILTER_IPV6_BASE);
+		start_id_ofst =
+			ipahal_get_reg_ofst(IPA_STAT_FILTER_IPV6_START_ID);
+		end_id_ofst = ipahal_get_reg_ofst(IPA_STAT_FILTER_IPV6_END_ID);
+	} else {
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v6_init;
+		smem_ofst = IPA_MEM_PART(stats_rt_v6_ofst);
+		smem_size = IPA_MEM_PART(stats_rt_v6_size);
+		stats_base = ipahal_get_reg_ofst(IPA_STAT_ROUTER_IPV6_BASE);
+		start_id_ofst =
+			ipahal_get_reg_ofst(IPA_STAT_ROUTER_IPV6_START_ID);
+		end_id_ofst = ipahal_get_reg_ofst(IPA_STAT_ROUTER_IPV6_END_ID);
+	}
+
+	for (start_id = 0; start_id < IPAHAL_MAX_RULE_ID_32; start_id++) {
+		if (init->rule_id_bitmask[start_id])
+			break;
+	}
+
+	if (start_id == IPAHAL_MAX_RULE_ID_32) {
+		IPAERR("empty rule ids\n");
+		return -EINVAL;
+	}
+
+	/* every rule_id_bitmask contains 32 rules */
+	start_id *= 32;
+
+	for (end_id = IPAHAL_MAX_RULE_ID_32 - 1; end_id >= 0; end_id--) {
+		if (init->rule_id_bitmask[end_id])
+			break;
+	}
+	end_id = (end_id + 1) * 32 - 1;
+
+	pyld = ipahal_stats_generate_init_pyld(IPAHAL_HW_STATS_FNR, init,
+		false);
+	if (!pyld) {
+		IPAERR("failed to generate pyld\n");
+		return -EPERM;
+	}
+
+	if (pyld->len > smem_size) {
+		IPAERR("SRAM partition too small: %d needed %d\n",
+			smem_size, pyld->len);
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	dma_address = dma_map_single(ipa3_ctx->pdev,
+		pyld->data,
+		pyld->len,
+		DMA_TO_DEVICE);
+	if (dma_mapping_error(ipa3_ctx->pdev, dma_address)) {
+		IPAERR("failed to DMA map\n");
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	/* setting the registers and init the stats pyld are done atomically */
+	flt_rt_start_id.skip_pipeline_clear = false;
+	flt_rt_start_id.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	flt_rt_start_id.offset = start_id_ofst;
+	flt_rt_start_id.value = start_id;
+	flt_rt_start_id.value_mask = 0x3FF;
+	flt_rt_start_id_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_REGISTER_WRITE, &flt_rt_start_id, false);
+	if (!flt_rt_start_id_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto unmap;
+	}
+	desc[0].opcode = flt_rt_start_id_pyld->opcode;
+	desc[0].pyld = flt_rt_start_id_pyld->data;
+	desc[0].len = flt_rt_start_id_pyld->len;
+	desc[0].type = IPA_IMM_CMD_DESC;
+
+	flt_rt_end_id.skip_pipeline_clear = false;
+	flt_rt_end_id.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	flt_rt_end_id.offset = end_id_ofst;
+	flt_rt_end_id.value = end_id;
+	flt_rt_end_id.value_mask = 0x3FF;
+	flt_rt_end_id_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_REGISTER_WRITE, &flt_rt_end_id, false);
+	if (!flt_rt_end_id_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_flt_rt_start_id;
+	}
+	desc[1].opcode = flt_rt_end_id_pyld->opcode;
+	desc[1].pyld = flt_rt_end_id_pyld->data;
+	desc[1].len = flt_rt_end_id_pyld->len;
+	desc[1].type = IPA_IMM_CMD_DESC;
+
+	flt_rt_base.skip_pipeline_clear = false;
+	flt_rt_base.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	flt_rt_base.offset = stats_base;
+	flt_rt_base.value = ipa3_ctx->smem_restricted_bytes +
+		smem_ofst;
+	flt_rt_base.value_mask = ~0;
+	flt_rt_base_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&flt_rt_base, false);
+	if (!flt_rt_base_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_flt_rt_end_id;
+	}
+	desc[2].opcode = flt_rt_base_pyld->opcode;
+	desc[2].pyld = flt_rt_base_pyld->data;
+	desc[2].len = flt_rt_base_pyld->len;
+	desc[2].type = IPA_IMM_CMD_DESC;
+
+	cmd.is_read = false;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	cmd.size = pyld->len;
+	cmd.system_addr = dma_address;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+			smem_ofst;
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_flt_rt_base;
+	}
+	desc[3].opcode = cmd_pyld->opcode;
+	desc[3].pyld = cmd_pyld->data;
+	desc[3].len = cmd_pyld->len;
+	desc[3].type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(4, desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	ret = 0;
+
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+destroy_flt_rt_base:
+	ipahal_destroy_imm_cmd(flt_rt_base_pyld);
+destroy_flt_rt_end_id:
+	ipahal_destroy_imm_cmd(flt_rt_end_id_pyld);
+destroy_flt_rt_start_id:
+	ipahal_destroy_imm_cmd(flt_rt_start_id_pyld);
+unmap:
+	dma_unmap_single(ipa3_ctx->pdev, dma_address, pyld->len, DMA_TO_DEVICE);
+destroy_init_pyld:
+	ipahal_destroy_stats_init_pyld(pyld);
+	return ret;
+}
+
+int ipa_flt_rt_stats_clear_rule_ids(enum ipa_ip_type ip, bool filtering)
+{
+	struct ipahal_stats_init_flt_rt *init;
+	int i;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (ip < 0 || ip >= IPA_IP_MAX) {
+		IPAERR("wrong ip type %d\n", ip);
+		return -EINVAL;
+	}
+
+	if (ip == IPA_IP_v4 && filtering)
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v4_init;
+	else if (ip == IPA_IP_v4)
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v4_init;
+	else if (ip == IPA_IP_v6 && filtering)
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v6_init;
+	else
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v6_init;
+
+	for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++)
+		init->rule_id_bitmask[i] = 0;
+
+	return 0;
+}
+
+static int __ipa_get_flt_rt_stats(enum ipa_ip_type ip, bool filtering,
+	u16 rule_id, struct ipa_flt_rt_stats *out)
+{
+	int ret;
+	int smem_ofst;
+	bool clear = false;
+	struct ipahal_stats_get_offset_flt_rt *get_offset;
+	struct ipahal_stats_offset offset = { 0 };
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipa_mem_buffer mem;
+	struct ipa3_desc desc = { 0 };
+	struct ipahal_stats_flt_rt stats;
+
+	if (rule_id >= IPAHAL_MAX_RULE_ID_32 * 32) {
+		IPAERR("invalid rule_id %d\n", rule_id);
+		return -EINVAL;
+	}
+
+	if (out == NULL)
+		clear = true;
+
+	get_offset = kzalloc(sizeof(*get_offset), GFP_KERNEL);
+	if (!get_offset) {
+		IPADBG("no mem\n");
+		return -ENOMEM;
+	}
+
+	if (ip == IPA_IP_v4 && filtering) {
+		get_offset->init = ipa3_ctx->hw_stats.flt_rt.flt_v4_init;
+		smem_ofst = IPA_MEM_PART(stats_flt_v4_ofst);
+	} else if (ip == IPA_IP_v4) {
+		get_offset->init = ipa3_ctx->hw_stats.flt_rt.rt_v4_init;
+		smem_ofst = IPA_MEM_PART(stats_rt_v4_ofst);
+	} else if (ip == IPA_IP_v6 && filtering) {
+		get_offset->init = ipa3_ctx->hw_stats.flt_rt.flt_v6_init;
+		smem_ofst = IPA_MEM_PART(stats_flt_v6_ofst);
+	} else {
+		get_offset->init = ipa3_ctx->hw_stats.flt_rt.rt_v6_init;
+		smem_ofst = IPA_MEM_PART(stats_rt_v6_ofst);
+	}
+
+	get_offset->rule_id = rule_id;
+
+	ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_FNR, get_offset,
+		&offset);
+	if (ret) {
+		IPAERR("failed to get offset from hal %d\n", ret);
+		goto free_offset;
+	}
+
+	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+
+	mem.size = offset.size;
+	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
+		mem.size,
+		&mem.phys_base,
+		GFP_KERNEL);
+	if (!mem.base) {
+		IPAERR("fail to alloc DMA memory\n");
+		goto free_offset;
+	}
+
+	cmd.is_read = true;
+	cmd.clear_after_read = clear;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+	cmd.size = mem.size;
+	cmd.system_addr = mem.phys_base;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+		smem_ofst + offset.offset;
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto free_dma_mem;
+	}
+	desc.opcode = cmd_pyld->opcode;
+	desc.pyld = cmd_pyld->data;
+	desc.len = cmd_pyld->len;
+	desc.type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(1, &desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	ret = ipahal_parse_stats(IPAHAL_HW_STATS_FNR,
+		&get_offset->init, mem.base, &stats);
+	if (ret) {
+		IPAERR("failed to parse stats (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	if (out) {
+		out->num_pkts = stats.num_packets;
+		out->num_pkts_hash = stats.num_packets_hash;
+	}
+
+	ret = 0;
+
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+free_dma_mem:
+	dma_free_coherent(ipa3_ctx->pdev, mem.size, mem.base, mem.phys_base);
+free_offset:
+	kfree(get_offset);
+	return ret;
+
+}
+
+
+int ipa_get_flt_rt_stats(enum ipa_ip_type ip, bool filtering, u16 rule_id,
+	struct ipa_flt_rt_stats *out)
+{
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (ip < 0 || ip >= IPA_IP_MAX) {
+		IPAERR("wrong ip type %d\n", ip);
+		return -EINVAL;
+	}
+
+	return __ipa_get_flt_rt_stats(ip, filtering, rule_id, out);
+}
+
+int ipa_reset_flt_rt_stats(enum ipa_ip_type ip, bool filtering, u16 rule_id)
+{
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (ip < 0 || ip >= IPA_IP_MAX) {
+		IPAERR("wrong ip type %d\n", ip);
+		return -EINVAL;
+	}
+
+	return __ipa_get_flt_rt_stats(ip, filtering, rule_id, NULL);
+}
+
+int ipa_reset_all_flt_rt_stats(enum ipa_ip_type ip, bool filtering)
+{
+	struct ipahal_stats_init_flt_rt *init;
+	int i;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	if (ip < 0 || ip >= IPA_IP_MAX) {
+		IPAERR("wrong ip type %d\n", ip);
+		return -EINVAL;
+	}
+
+	if (ip == IPA_IP_v4 && filtering)
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v4_init;
+	else if (ip == IPA_IP_v4)
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v4_init;
+	else if (ip == IPA_IP_v6 && filtering)
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v6_init;
+	else
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v6_init;
+
+	for (i = 0; i < IPAHAL_MAX_RULE_ID_32 * 32; i++) {
+		int idx = i / 32;
+		int bit = i % 32;
+
+		if (init->rule_id_bitmask[idx] & (1 << bit))
+			__ipa_get_flt_rt_stats(ip, filtering, i, NULL);
+	}
+
+	return 0;
+}
+
+int ipa_init_drop_stats(u32 pipe_bitmask)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipahal_imm_cmd_register_write drop_base = {0};
+	struct ipahal_imm_cmd_pyld *drop_base_pyld;
+	struct ipahal_imm_cmd_register_write drop_mask = {0};
+	struct ipahal_imm_cmd_pyld *drop_mask_pyld;
+	struct ipa3_desc desc[3] = { {0} };
+	dma_addr_t dma_address;
+	int ret;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	/* reset driver's cache */
+	memset(&ipa3_ctx->hw_stats.drop, 0, sizeof(ipa3_ctx->hw_stats.drop));
+	ipa3_ctx->hw_stats.drop.init.enabled_bitmask = pipe_bitmask;
+	IPADBG_LOW("pipe_bitmask=0x%x\n", pipe_bitmask);
+
+	pyld = ipahal_stats_generate_init_pyld(IPAHAL_HW_STATS_DROP,
+		&ipa3_ctx->hw_stats.drop.init, false);
+	if (!pyld) {
+		IPAERR("failed to generate pyld\n");
+		return -EPERM;
+	}
+
+	if (pyld->len > IPA_MEM_PART(stats_drop_size)) {
+		IPAERR("SRAM partition too small: %d needed %d\n",
+			IPA_MEM_PART(stats_drop_size), pyld->len);
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	dma_address = dma_map_single(ipa3_ctx->pdev,
+		pyld->data,
+		pyld->len,
+		DMA_TO_DEVICE);
+	if (dma_mapping_error(ipa3_ctx->pdev, dma_address)) {
+		IPAERR("failed to DMA map\n");
+		ret = -EPERM;
+		goto destroy_init_pyld;
+	}
+
+	/* setting the registers and init the stats pyld are done atomically */
+	drop_mask.skip_pipeline_clear = false;
+	drop_mask.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	drop_mask.offset = ipahal_get_reg_n_ofst(IPA_STAT_DROP_CNT_MASK_n,
+		ipa3_ctx->ee);
+	drop_mask.value = pipe_bitmask;
+	drop_mask.value_mask = ~0;
+	drop_mask_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&drop_mask, false);
+	if (!drop_mask_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto unmap;
+	}
+	desc[0].opcode = drop_mask_pyld->opcode;
+	desc[0].pyld = drop_mask_pyld->data;
+	desc[0].len = drop_mask_pyld->len;
+	desc[0].type = IPA_IMM_CMD_DESC;
+
+	drop_base.skip_pipeline_clear = false;
+	drop_base.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	drop_base.offset = ipahal_get_reg_n_ofst(IPA_STAT_DROP_CNT_BASE_n,
+		ipa3_ctx->ee);
+	drop_base.value = ipa3_ctx->smem_restricted_bytes +
+		IPA_MEM_PART(stats_drop_ofst);
+	drop_base.value_mask = ~0;
+	drop_base_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
+		&drop_base, false);
+	if (!drop_base_pyld) {
+		IPAERR("failed to construct register_write imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_drop_mask;
+	}
+	desc[1].opcode = drop_base_pyld->opcode;
+	desc[1].pyld = drop_base_pyld->data;
+	desc[1].len = drop_base_pyld->len;
+	desc[1].type = IPA_IMM_CMD_DESC;
+
+	cmd.is_read = false;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+	cmd.size = pyld->len;
+	cmd.system_addr = dma_address;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+			IPA_MEM_PART(stats_drop_ofst);
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto destroy_drop_base;
+	}
+	desc[2].opcode = cmd_pyld->opcode;
+	desc[2].pyld = cmd_pyld->data;
+	desc[2].len = cmd_pyld->len;
+	desc[2].type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(3, desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	ret = 0;
+
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+destroy_drop_base:
+	ipahal_destroy_imm_cmd(drop_base_pyld);
+destroy_drop_mask:
+	ipahal_destroy_imm_cmd(drop_mask_pyld);
+unmap:
+	dma_unmap_single(ipa3_ctx->pdev, dma_address, pyld->len, DMA_TO_DEVICE);
+destroy_init_pyld:
+	ipahal_destroy_stats_init_pyld(pyld);
+	return ret;
+}
+
+int ipa_get_drop_stats(struct ipa_drop_stats_all *out)
+{
+	int i;
+	int ret;
+	struct ipahal_stats_get_offset_drop get_offset = { { 0 } };
+	struct ipahal_stats_offset offset = { 0 };
+	struct ipahal_imm_cmd_dma_shared_mem cmd = { 0 };
+	struct ipahal_imm_cmd_pyld *cmd_pyld;
+	struct ipa_mem_buffer mem;
+	struct ipa3_desc desc = { 0 };
+	struct ipahal_stats_drop_all *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	get_offset.init = ipa3_ctx->hw_stats.drop.init;
+	ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_DROP, &get_offset,
+		&offset);
+	if (ret) {
+		IPAERR("failed to get offset from hal %d\n", ret);
+		return ret;
+	}
+
+	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
+
+	mem.size = offset.size;
+	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
+		mem.size,
+		&mem.phys_base,
+		GFP_KERNEL);
+	if (!mem.base) {
+		IPAERR("fail to alloc DMA memory\n");
+		return ret;
+	}
+
+	cmd.is_read = true;
+	cmd.clear_after_read = true;
+	cmd.skip_pipeline_clear = false;
+	cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+	cmd.size = mem.size;
+	cmd.system_addr = mem.phys_base;
+	cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
+		IPA_MEM_PART(stats_drop_ofst) + offset.offset;
+	cmd_pyld = ipahal_construct_imm_cmd(
+		IPA_IMM_CMD_DMA_SHARED_MEM, &cmd, false);
+	if (!cmd_pyld) {
+		IPAERR("failed to construct dma_shared_mem imm cmd\n");
+		ret = -ENOMEM;
+		goto free_dma_mem;
+	}
+	desc.opcode = cmd_pyld->opcode;
+	desc.pyld = cmd_pyld->data;
+	desc.len = cmd_pyld->len;
+	desc.type = IPA_IMM_CMD_DESC;
+
+	ret = ipa3_send_cmd(1, &desc);
+	if (ret) {
+		IPAERR("failed to send immediate command (error %d)\n", ret);
+		goto destroy_imm;
+	}
+
+	stats = kzalloc(sizeof(*stats), GFP_KERNEL);
+	if (!stats) {
+		IPADBG("failed to alloc memory\n");
+		ret = -ENOMEM;
+		goto destroy_imm;
+	}
+
+	ret = ipahal_parse_stats(IPAHAL_HW_STATS_DROP,
+		&ipa3_ctx->hw_stats.drop.init, mem.base, stats);
+	if (ret) {
+		IPAERR("failed to parse stats (error %d)\n", ret);
+		goto free_stats;
+	}
+
+	/*
+	 * update driver cache.
+	 * the stats were read from hardware with clear_after_read meaning
+	 * hardware stats are 0 now
+	 */
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		int ep_idx = ipa3_get_ep_mapping(i);
+
+		if (ep_idx == -1 || ep_idx >= IPA3_MAX_NUM_PIPES)
+			continue;
+
+		if (ipa3_ctx->ep[ep_idx].client != i)
+			continue;
+
+		ipa3_ctx->hw_stats.drop.stats.client[i].drop_byte_cnt +=
+			stats->stats[ep_idx].drop_byte_cnt;
+		ipa3_ctx->hw_stats.drop.stats.client[i].drop_packet_cnt +=
+			stats->stats[ep_idx].drop_packet_cnt;
+	}
+
+
+	if (!out) {
+		ret = 0;
+		goto free_stats;
+	}
+
+	/* copy results to out parameter */
+	*out = ipa3_ctx->hw_stats.drop.stats;
+
+	ret = 0;
+free_stats:
+	kfree(stats);
+destroy_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+free_dma_mem:
+	dma_free_coherent(ipa3_ctx->pdev, mem.size, mem.base, mem.phys_base);
+	return ret;
+
+}
+
+int ipa_reset_drop_stats(enum ipa_client_type client)
+{
+	int ret;
+	struct ipa_drop_stats *stats;
+
+	if (client >= IPA_CLIENT_MAX) {
+		IPAERR("invalid client %d\n", client);
+		return -EINVAL;
+	}
+
+	/* reading stats will reset them in hardware */
+	ret = ipa_get_drop_stats(NULL);
+	if (ret) {
+		IPAERR("ipa_get_drop_stats failed %d\n", ret);
+		return ret;
+	}
+
+	/* reset driver's cache */
+	stats = &ipa3_ctx->hw_stats.drop.stats.client[client];
+	memset(stats, 0, sizeof(*stats));
+	return 0;
+}
+
+int ipa_reset_all_drop_stats(void)
+{
+	int ret;
+	struct ipa_drop_stats_all *stats;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	/* reading stats will reset them in hardware */
+	ret = ipa_get_drop_stats(NULL);
+	if (ret) {
+		IPAERR("ipa_get_drop_stats failed %d\n", ret);
+		return ret;
+	}
+
+	/* reset driver's cache */
+	stats = &ipa3_ctx->hw_stats.drop.stats;
+	memset(stats, 0, sizeof(*stats));
+	return 0;
+}
+
+
+#ifndef CONFIG_DEBUG_FS
+int ipa_debugfs_init_stats(struct dentry *parent) { return 0; }
+#else
+#define IPA_MAX_MSG_LEN 4096
+static char dbg_buff[IPA_MAX_MSG_LEN];
+
+static ssize_t ipa_debugfs_reset_quota_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	unsigned long missing;
+	s8 client = 0;
+	int ret;
+
+	mutex_lock(&ipa3_ctx->lock);
+	if (sizeof(dbg_buff) < count + 1) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	missing = copy_from_user(dbg_buff, ubuf, count);
+	if (missing) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	dbg_buff[count] = '\0';
+	if (kstrtos8(dbg_buff, 0, &client)) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	if (client == -1)
+		ipa_reset_all_quota_stats();
+	else
+		ipa_reset_quota_stats(client);
+
+	ret = count;
+bail:
+	mutex_unlock(&ipa3_ctx->lock);
+	return ret;
+}
+
+static ssize_t ipa_debugfs_print_quota_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	int nbytes = 0;
+	struct ipa_quota_stats_all *out;
+	int i;
+	int res;
+
+	out = kzalloc(sizeof(*out), GFP_KERNEL);
+	if (!out)
+		return -ENOMEM;
+
+	mutex_lock(&ipa3_ctx->lock);
+	res = ipa_get_quota_stats(out);
+	if (res) {
+		mutex_unlock(&ipa3_ctx->lock);
+		kfree(out);
+		return res;
+	}
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		int ep_idx = ipa3_get_ep_mapping(i);
+
+		if (ep_idx == -1)
+			continue;
+
+		if (IPA_CLIENT_IS_TEST(i))
+			continue;
+
+		if (!(ipa3_ctx->hw_stats.quota.init.enabled_bitmask &
+			(1 << ep_idx)))
+			continue;
+
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"%s:\n",
+			ipa_clients_strings[i]);
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"num_ipv4_bytes=%llu\n",
+			out->client[i].num_ipv4_bytes);
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"num_ipv6_bytes=%llu\n",
+			out->client[i].num_ipv6_bytes);
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"num_ipv4_pkts=%u\n",
+			out->client[i].num_ipv4_pkts);
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"num_ipv6_pkts=%u\n",
+			out->client[i].num_ipv6_pkts);
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"\n");
+
+	}
+	mutex_unlock(&ipa3_ctx->lock);
+	kfree(out);
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t ipa_debugfs_reset_tethering_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	unsigned long missing;
+	s8 client = 0;
+	int ret;
+
+	mutex_lock(&ipa3_ctx->lock);
+	if (sizeof(dbg_buff) < count + 1) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	missing = copy_from_user(dbg_buff, ubuf, count);
+	if (missing) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	dbg_buff[count] = '\0';
+	if (kstrtos8(dbg_buff, 0, &client)) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	if (client == -1)
+		ipa_reset_all_teth_stats();
+	else
+		ipa_reset_all_cons_teth_stats(client);
+
+	ret = count;
+bail:
+	mutex_unlock(&ipa3_ctx->lock);
+	return ret;
+}
+
+static ssize_t ipa_debugfs_print_tethering_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	int nbytes = 0;
+	struct ipa_quota_stats_all *out;
+	int i, j;
+	int res;
+
+	out = kzalloc(sizeof(*out), GFP_KERNEL);
+	if (!out)
+		return -ENOMEM;
+
+	mutex_lock(&ipa3_ctx->lock);
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		int ep_idx = ipa3_get_ep_mapping(i);
+
+		if (ep_idx == -1)
+			continue;
+
+		if (!IPA_CLIENT_IS_PROD(i))
+			continue;
+
+		if (IPA_CLIENT_IS_TEST(i))
+			continue;
+
+		if (!(ipa3_ctx->hw_stats.teth.init.prod_bitmask &
+			(1 << ep_idx)))
+			continue;
+
+		res = ipa_get_teth_stats(i, out);
+		if (res) {
+			mutex_unlock(&ipa3_ctx->lock);
+			kfree(out);
+			return res;
+		}
+
+		for (j = 0; j < IPA_CLIENT_MAX; j++) {
+			int cons_idx = ipa3_get_ep_mapping(j);
+
+			if (cons_idx == -1)
+				continue;
+
+			if (IPA_CLIENT_IS_TEST(j))
+				continue;
+
+			if (!(ipa3_ctx->hw_stats.teth.init.cons_bitmask[ep_idx]
+				& (1 << cons_idx)))
+				continue;
+
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"%s->%s:\n",
+				ipa_clients_strings[i],
+				ipa_clients_strings[j]);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"num_ipv4_bytes=%llu\n",
+				out->client[j].num_ipv4_bytes);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"num_ipv6_bytes=%llu\n",
+				out->client[j].num_ipv6_bytes);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"num_ipv4_pkts=%u\n",
+				out->client[j].num_ipv4_pkts);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"num_ipv6_pkts=%u\n",
+				out->client[j].num_ipv6_pkts);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"\n");
+		}
+	}
+	mutex_unlock(&ipa3_ctx->lock);
+	kfree(out);
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t ipa_debugfs_control_flt_rt_stats(enum ipa_ip_type ip,
+	bool filtering, struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	unsigned long missing;
+	u16 rule_id = 0;
+	int ret;
+
+	mutex_lock(&ipa3_ctx->lock);
+	if (sizeof(dbg_buff) < count + 1) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	missing = copy_from_user(dbg_buff, ubuf, count);
+	if (missing) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	dbg_buff[count] = '\0';
+		if (strcmp(dbg_buff, "start\n") == 0) {
+		ipa_flt_rt_stats_start(ip, filtering);
+	} else if (strcmp(dbg_buff, "clear\n") == 0) {
+		ipa_flt_rt_stats_clear_rule_ids(ip, filtering);
+	} else if (strcmp(dbg_buff, "reset\n") == 0) {
+		ipa_reset_all_flt_rt_stats(ip, filtering);
+	} else {
+		if (kstrtou16(dbg_buff, 0, &rule_id)) {
+			ret = -EFAULT;
+			goto bail;
+		}
+		ipa_flt_rt_stats_add_rule_id(ip, filtering, rule_id);
+	}
+
+	ret = count;
+bail:
+	mutex_unlock(&ipa3_ctx->lock);
+	return ret;
+}
+
+static ssize_t ipa_debugfs_print_flt_rt_stats(enum ipa_ip_type ip,
+	bool filtering, struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	int nbytes = 0;
+	struct ipahal_stats_init_flt_rt *init;
+	struct ipa_flt_rt_stats out;
+	int i;
+	int res;
+
+	if (ip == IPA_IP_v4 && filtering)
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v4_init;
+	else if (ip == IPA_IP_v4)
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v4_init;
+	else if (ip == IPA_IP_v6 && filtering)
+		init = &ipa3_ctx->hw_stats.flt_rt.flt_v6_init;
+	else
+		init = &ipa3_ctx->hw_stats.flt_rt.rt_v6_init;
+
+	mutex_lock(&ipa3_ctx->lock);
+	for (i = 0; i < IPAHAL_MAX_RULE_ID_32 * 32; i++) {
+		int idx = i / 32;
+		int bit = i % 32;
+
+		if (init->rule_id_bitmask[idx] & (1 << bit)) {
+			res = ipa_get_flt_rt_stats(ip, filtering, i, &out);
+			if (res) {
+				mutex_unlock(&ipa3_ctx->lock);
+				return res;
+			}
+
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"rule_id: %d\n", i);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"num_pkts: %d\n",
+				out.num_pkts);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"num_pkts_hash: %d\n",
+				out.num_pkts_hash);
+			nbytes += scnprintf(dbg_buff + nbytes,
+				IPA_MAX_MSG_LEN - nbytes,
+				"\n");
+		}
+	}
+
+	mutex_unlock(&ipa3_ctx->lock);
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t ipa_debugfs_reset_drop_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	unsigned long missing;
+	s8 client = 0;
+	int ret;
+
+	mutex_lock(&ipa3_ctx->lock);
+	if (sizeof(dbg_buff) < count + 1) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	missing = copy_from_user(dbg_buff, ubuf, count);
+	if (missing) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	dbg_buff[count] = '\0';
+	if (kstrtos8(dbg_buff, 0, &client)) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	if (client == -1)
+		ipa_reset_all_drop_stats();
+	else
+		ipa_reset_drop_stats(client);
+
+	ret = count;
+bail:
+	mutex_unlock(&ipa3_ctx->lock);
+	return count;
+}
+
+static ssize_t ipa_debugfs_print_drop_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	int nbytes = 0;
+	struct ipa_drop_stats_all *out;
+	int i;
+	int res;
+
+	out = kzalloc(sizeof(*out), GFP_KERNEL);
+	if (!out)
+		return -ENOMEM;
+
+	mutex_lock(&ipa3_ctx->lock);
+	res = ipa_get_drop_stats(out);
+	if (res) {
+		mutex_unlock(&ipa3_ctx->lock);
+		kfree(out);
+		return res;
+	}
+
+	for (i = 0; i < IPA_CLIENT_MAX; i++) {
+		int ep_idx = ipa3_get_ep_mapping(i);
+
+		if (ep_idx == -1)
+			continue;
+
+		if (!IPA_CLIENT_IS_CONS(i))
+			continue;
+
+		if (IPA_CLIENT_IS_TEST(i))
+			continue;
+
+		if (!(ipa3_ctx->hw_stats.drop.init.enabled_bitmask &
+			(1 << ep_idx)))
+			continue;
+
+
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"%s:\n",
+			ipa_clients_strings[i]);
+
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"drop_byte_cnt=%u\n",
+			out->client[i].drop_byte_cnt);
+
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"drop_packet_cnt=%u\n",
+			out->client[i].drop_packet_cnt);
+		nbytes += scnprintf(dbg_buff + nbytes,
+			IPA_MAX_MSG_LEN - nbytes,
+			"\n");
+	}
+	mutex_unlock(&ipa3_ctx->lock);
+	kfree(out);
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t ipa_debugfs_control_flt_v4_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_control_flt_rt_stats(IPA_IP_v4, true, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_control_flt_v6_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_control_flt_rt_stats(IPA_IP_v6, true, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_control_rt_v4_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_control_flt_rt_stats(IPA_IP_v4, false, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_control_rt_v6_stats(struct file *file,
+	const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_control_flt_rt_stats(IPA_IP_v6, false, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_print_flt_v4_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_print_flt_rt_stats(IPA_IP_v4, true, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_print_flt_v6_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_print_flt_rt_stats(IPA_IP_v6, true, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_print_rt_v4_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_print_flt_rt_stats(IPA_IP_v4, false, file, ubuf,
+		count, ppos);
+}
+
+static ssize_t ipa_debugfs_print_rt_v6_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	return ipa_debugfs_print_flt_rt_stats(IPA_IP_v6, false, file, ubuf,
+		count, ppos);
+}
+
+static const struct file_operations ipa3_quota_ops = {
+	.read = ipa_debugfs_print_quota_stats,
+	.write = ipa_debugfs_reset_quota_stats,
+};
+
+static const struct file_operations ipa3_tethering_ops = {
+	.read = ipa_debugfs_print_tethering_stats,
+	.write = ipa_debugfs_reset_tethering_stats,
+};
+
+static const struct file_operations ipa3_flt_v4_ops = {
+	.read = ipa_debugfs_print_flt_v4_stats,
+	.write = ipa_debugfs_control_flt_v4_stats,
+};
+
+static const struct file_operations ipa3_flt_v6_ops = {
+	.read = ipa_debugfs_print_flt_v6_stats,
+	.write = ipa_debugfs_control_flt_v6_stats,
+};
+
+static const struct file_operations ipa3_rt_v4_ops = {
+	.read = ipa_debugfs_print_rt_v4_stats,
+	.write = ipa_debugfs_control_rt_v4_stats,
+};
+
+static const struct file_operations ipa3_rt_v6_ops = {
+	.read = ipa_debugfs_print_rt_v6_stats,
+	.write = ipa_debugfs_control_rt_v6_stats,
+};
+
+static const struct file_operations ipa3_drop_ops = {
+	.read = ipa_debugfs_print_drop_stats,
+	.write = ipa_debugfs_reset_drop_stats,
+};
+
+
+int ipa_debugfs_init_stats(struct dentry *parent)
+{
+	const mode_t read_write_mode = 0664;
+	struct dentry *file;
+	struct dentry *dent;
+
+	if (!ipa3_ctx->hw_stats.enabled)
+		return 0;
+
+	dent = debugfs_create_dir("hw_stats", parent);
+	if (IS_ERR_OR_NULL(dent)) {
+		IPAERR("fail to create folder in debug_fs\n");
+		return -EFAULT;
+	}
+
+	file = debugfs_create_file("quota", read_write_mode, dent, NULL,
+		&ipa3_quota_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "quota");
+		goto fail;
+	}
+
+	file = debugfs_create_file("drop", read_write_mode, dent, NULL,
+		&ipa3_drop_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "drop");
+		goto fail;
+	}
+
+	file = debugfs_create_file("tethering", read_write_mode, dent, NULL,
+		&ipa3_tethering_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "tethering");
+		goto fail;
+	}
+
+	file = debugfs_create_file("flt_v4", read_write_mode, dent, NULL,
+		&ipa3_flt_v4_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "flt_v4");
+		goto fail;
+	}
+
+	file = debugfs_create_file("flt_v6", read_write_mode, dent, NULL,
+		&ipa3_flt_v6_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "flt_v6");
+		goto fail;
+	}
+
+	file = debugfs_create_file("rt_v4", read_write_mode, dent, NULL,
+		&ipa3_rt_v4_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "rt_v4");
+		goto fail;
+	}
+
+	file = debugfs_create_file("rt_v6", read_write_mode, dent, NULL,
+		&ipa3_rt_v6_ops);
+	if (IS_ERR_OR_NULL(file)) {
+		IPAERR("fail to create file %s\n", "rt_v6");
+		goto fail;
+	}
+
+	return 0;
+fail:
+	debugfs_remove_recursive(dent);
+	return -EFAULT;
+}
+#endif
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 1bed1c8..43fd4d1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -33,6 +33,7 @@
 #include "ipahal/ipahal_reg.h"
 #include "ipahal/ipahal.h"
 #include "ipahal/ipahal_fltrt.h"
+#include "ipahal/ipahal_hw_stats.h"
 #include "../ipa_common_i.h"
 #include "ipa_uc_offload_i.h"
 
@@ -100,6 +101,18 @@
 		} \
 	} while (0)
 
+#define IPAERR_RL(fmt, args...) \
+	do { \
+		pr_err_ratelimited(DRV_NAME " %s:%d " fmt, __func__,\
+		__LINE__, ## args);\
+		if (ipa3_ctx) { \
+			IPA_IPC_LOGGING(ipa3_ctx->logbuf, \
+				DRV_NAME " %s:%d " fmt, ## args); \
+			IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, \
+				DRV_NAME " %s:%d " fmt, ## args); \
+		} \
+	} while (0)
+
 #define WLAN_AMPDU_TX_EP 15
 #define WLAN_PROD_TX_EP  19
 #define WLAN1_CONS_RX_EP  14
@@ -175,6 +188,7 @@
 };
 
 struct ipa3_active_clients_log_ctx {
+	spinlock_t lock;
 	char *log_buffer[IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES];
 	int log_head;
 	int log_tail;
@@ -238,7 +252,7 @@
  * @curr_mem: current routing tables block in sys memory
  * @prev_mem: previous routing table block in sys memory
  * @id: routing table id
- * @rule_ids: idr structure that holds the rule_id for each rule
+ * @rule_ids: common idr structure that holds the rule_id for each rule
  */
 struct ipa3_rt_tbl {
 	struct list_head link;
@@ -254,7 +268,7 @@
 	struct ipa_mem_buffer curr_mem[IPA_RULE_TYPE_MAX];
 	struct ipa_mem_buffer prev_mem[IPA_RULE_TYPE_MAX];
 	int id;
-	struct idr rule_ids;
+	struct idr *rule_ids;
 };
 
 /**
@@ -341,7 +355,7 @@
 	struct list_head link;
 	u32 cookie;
 	enum ipa_hdr_proc_type type;
-	union ipa_l2tp_hdr_proc_ctx_params l2tp_params;
+	struct ipa_l2tp_hdr_proc_ctx_params l2tp_params;
 	struct ipa3_hdr_proc_ctx_offset_entry *offset_entry;
 	struct ipa3_hdr_entry *hdr;
 	u32 ref_cnt;
@@ -376,7 +390,7 @@
  * @end: the last header index
  * @curr_mem: current filter tables block in sys memory
  * @prev_mem: previous filter table block in sys memory
- * @rule_ids: idr structure that holds the rule_id for each rule
+ * @rule_ids: common idr structure that holds the rule_id for each rule
  */
 struct ipa3_flt_tbl {
 	struct list_head head_flt_rule_list;
@@ -386,7 +400,7 @@
 	struct ipa_mem_buffer curr_mem[IPA_RULE_TYPE_MAX];
 	struct ipa_mem_buffer prev_mem[IPA_RULE_TYPE_MAX];
 	bool sticky_rear;
-	struct idr rule_ids;
+	struct idr *rule_ids;
 };
 
 /**
@@ -420,10 +434,12 @@
  * struct ipa3_rt_tbl_set - collection of routing tables
  * @head_rt_tbl_list: collection of routing tables
  * @tbl_cnt: number of routing tables
+ * @rule_ids: idr structure that holds the rule_id for each rule
  */
 struct ipa3_rt_tbl_set {
 	struct list_head head_rt_tbl_list;
 	u32 tbl_cnt;
+	struct idr rule_ids;
 };
 
 /**
@@ -1022,6 +1038,56 @@
 	struct ipahal_imm_cmd_pyld *cmd_pyld;
 };
 
+struct ipa_quota_stats {
+	u64 num_ipv4_bytes;
+	u64 num_ipv6_bytes;
+	u32 num_ipv4_pkts;
+	u32 num_ipv6_pkts;
+};
+
+struct ipa_quota_stats_all {
+	struct ipa_quota_stats client[IPA_CLIENT_MAX];
+};
+
+struct ipa_drop_stats {
+	u32 drop_packet_cnt;
+	u32 drop_byte_cnt;
+};
+
+struct ipa_drop_stats_all {
+	struct ipa_drop_stats client[IPA_CLIENT_MAX];
+};
+
+struct ipa_hw_stats_quota {
+	struct ipahal_stats_init_quota init;
+	struct ipa_quota_stats_all stats;
+};
+
+struct ipa_hw_stats_teth {
+	struct ipahal_stats_init_tethering init;
+	struct ipa_quota_stats_all prod_stats[IPA_CLIENT_MAX];
+};
+
+struct ipa_hw_stats_flt_rt {
+	struct ipahal_stats_init_flt_rt flt_v4_init;
+	struct ipahal_stats_init_flt_rt flt_v6_init;
+	struct ipahal_stats_init_flt_rt rt_v4_init;
+	struct ipahal_stats_init_flt_rt rt_v6_init;
+};
+
+struct ipa_hw_stats_drop {
+	struct ipahal_stats_init_drop init;
+	struct ipa_drop_stats_all stats;
+};
+
+struct ipa_hw_stats {
+	bool enabled;
+	struct ipa_hw_stats_quota quota;
+	struct ipa_hw_stats_teth teth;
+	struct ipa_hw_stats_flt_rt flt_rt;
+	struct ipa_hw_stats_drop drop;
+};
+
 /**
  * struct ipa3_context - IPA context
  * @class: pointer to the struct class
@@ -1035,6 +1101,7 @@
  * @ep_flt_num: End-points supporting filtering number
  * @resume_on_connect: resume ep on ipa connect
  * @flt_tbl: list of all IPA filter tables
+ * @flt_rule_ids: idr structure that holds the rule_id for each rule
  * @mode: IPA operating mode
  * @mmio: iomem
  * @ipa_wrapper_base: IPA wrapper base address
@@ -1120,6 +1187,7 @@
 	u32 ep_flt_num;
 	bool resume_on_connect[IPA_CLIENT_MAX];
 	struct ipa3_flt_tbl flt_tbl[IPA3_MAX_NUM_PIPES][IPA_IP_MAX];
+	struct idr flt_rule_ids[IPA_IP_MAX];
 	void __iomem *mmio;
 	u32 ipa_wrapper_base;
 	u32 ipa_wrapper_size;
@@ -1234,6 +1302,7 @@
 	u32 ipa_tz_unlock_reg_num;
 	struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
 	struct ipa_dma_task_info dma_task_info;
+	struct ipa_hw_stats hw_stats;
 };
 
 struct ipa3_plat_drv_res {
@@ -1346,6 +1415,48 @@
  * +-------------------------+
  * |    CANARY               |
  * +-------------------------+
+ * | QUOTA STATS             |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * | TETH STATS              |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * | V4 FLT STATS            |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * | V6 FLT STATS            |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * | V4 RT STATS             |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * | V6 RT STATS             |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * | DROP STATS              |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
  * |  MODEM MEM              |
  * +-------------------------+
  * |    CANARY               |
@@ -1428,6 +1539,20 @@
 	u32 uc_event_ring_size;
 	u32 pdn_config_ofst;
 	u32 pdn_config_size;
+	u32 stats_quota_ofst;
+	u32 stats_quota_size;
+	u32 stats_tethering_ofst;
+	u32 stats_tethering_size;
+	u32 stats_flt_v4_ofst;
+	u32 stats_flt_v4_size;
+	u32 stats_flt_v6_ofst;
+	u32 stats_flt_v6_size;
+	u32 stats_rt_v4_ofst;
+	u32 stats_rt_v4_size;
+	u32 stats_rt_v6_ofst;
+	u32 stats_rt_v6_size;
+	u32 stats_drop_ofst;
+	u32 stats_drop_size;
 };
 
 struct ipa3_controller {
@@ -1875,10 +2000,6 @@
 				void *private_data,
 				void *interrupt_data);
 
-
-int ipa_bridge_init(void);
-void ipa_bridge_cleanup(void);
-
 ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
 		 loff_t *f_pos);
 int ipa3_pull_msg(struct ipa_msg_meta *meta, char *buff, size_t count);
@@ -1978,6 +2099,65 @@
 	(enum ipa_client_type client);
 void ipa3_uc_rg10_write_reg(enum ipahal_reg_name reg, u32 n, u32 val);
 
+/* Hardware stats */
+
+#define IPA_STATS_MAX_PIPE_BIT 32
+
+struct ipa_teth_stats_endpoints {
+	u32 prod_mask;
+	u32 dst_ep_mask[IPA_STATS_MAX_PIPE_BIT];
+};
+
+struct ipa_flt_rt_stats {
+	u32 num_pkts;
+	u32 num_pkts_hash;
+};
+
+int ipa_hw_stats_init(void);
+
+int ipa_debugfs_init_stats(struct dentry *parent);
+
+int ipa_init_quota_stats(u32 pipe_bitmask);
+
+int ipa_get_quota_stats(struct ipa_quota_stats_all *out);
+
+int ipa_reset_quota_stats(enum ipa_client_type client);
+
+int ipa_reset_all_quota_stats(void);
+
+int ipa_init_drop_stats(u32 pipe_bitmask);
+
+int ipa_get_drop_stats(struct ipa_drop_stats_all *out);
+
+int ipa_reset_drop_stats(enum ipa_client_type client);
+
+int ipa_reset_all_drop_stats(void);
+
+int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in);
+
+int ipa_get_teth_stats(enum ipa_client_type prod,
+	struct ipa_quota_stats_all *out);
+
+int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons);
+
+int ipa_reset_all_cons_teth_stats(enum ipa_client_type prod);
+
+int ipa_reset_all_teth_stats(void);
+
+int ipa_flt_rt_stats_add_rule_id(enum ipa_ip_type ip, bool filtering,
+	u16 rule_id);
+
+int ipa_flt_rt_stats_start(enum ipa_ip_type ip, bool filtering);
+
+int ipa_flt_rt_stats_clear_rule_ids(enum ipa_ip_type ip, bool filtering);
+
+int ipa_get_flt_rt_stats(enum ipa_ip_type ip, bool filtering, u16 rule_id,
+	struct ipa_flt_rt_stats *out);
+
+int ipa_reset_flt_rt_stats(enum ipa_ip_type ip, bool filtering, u16 rule_id);
+
+int ipa_reset_all_flt_rt_stats(enum ipa_ip_type ip, bool filtering);
+
 u32 ipa3_get_num_pipes(void);
 struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(void);
 struct ipa_smmu_cb_ctx *ipa3_get_wlan_smmu_ctx(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index 38e8d4e..2bd7b79 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -227,7 +227,7 @@
 
 	if (strnlen(lookup->name, IPA_RESOURCE_NAME_MAX) ==
 			IPA_RESOURCE_NAME_MAX) {
-		IPAERR("Interface name too long. (%s)\n", lookup->name);
+		IPAERR_RL("Interface name too long. (%s)\n", lookup->name);
 		return result;
 	}
 
@@ -268,7 +268,7 @@
 	}
 
 	if (strnlen(tx->name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) {
-		IPAERR("Interface name too long. (%s)\n", tx->name);
+		IPAERR_RL("Interface name too long. (%s)\n", tx->name);
 		return result;
 	}
 
@@ -315,7 +315,7 @@
 	}
 
 	if (strnlen(rx->name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) {
-		IPAERR("Interface name too long. (%s)\n", rx->name);
+		IPAERR_RL("Interface name too long. (%s)\n", rx->name);
 		return result;
 	}
 
@@ -410,13 +410,13 @@
 
 	if (meta == NULL || (buff == NULL && callback != NULL) ||
 	    (buff != NULL && callback == NULL)) {
-		IPAERR("invalid param meta=%p buff=%p, callback=%p\n",
+		IPAERR_RL("invalid param meta=%p buff=%p, callback=%p\n",
 		       meta, buff, callback);
 		return -EINVAL;
 	}
 
 	if (meta->msg_type >= IPA_EVENT_MAX_NUM) {
-		IPAERR("unsupported message type %d\n", meta->msg_type);
+		IPAERR_RL("unsupported message type %d\n", meta->msg_type);
 		return -EINVAL;
 	}
 
@@ -640,7 +640,7 @@
 	int result = -EINVAL;
 
 	if (meta == NULL || buff == NULL || !count) {
-		IPAERR("invalid param name=%p buff=%p count=%zu\n",
+		IPAERR_RL("invalid param name=%p buff=%p count=%zu\n",
 				meta, buff, count);
 		return result;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
index a153f2d..958fc6c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
@@ -253,8 +253,8 @@
 
 	mutex_lock(&nat_ctx->lock);
 	if (strcmp(mem->dev_name, NAT_DEV_NAME)) {
-		IPAERR("Nat device name mismatch\n");
-		IPAERR("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name);
+		IPAERR_RL("Nat device name mismatch\n");
+		IPAERR_RL("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name);
 		result = -EPERM;
 		goto bail;
 	}
@@ -273,7 +273,7 @@
 
 	if (mem->size <= 0 ||
 			nat_ctx->is_dev_init == true) {
-		IPAERR("Invalid Parameters or device is already init\n");
+		IPAERR_RL("Invalid Parameters or device is already init\n");
 		result = -EPERM;
 		goto bail;
 	}
@@ -371,7 +371,7 @@
 	/* check for integer overflow */
 	if (init->ipv4_rules_offset >
 		UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1))) {
-		IPAERR("Detected overflow\n");
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Table Entry offset is not
@@ -380,8 +380,8 @@
 	tmp = init->ipv4_rules_offset +
 		(TBL_ENTRY_SIZE * (init->table_entries + 1));
 	if (tmp > ipa3_ctx->nat_mem.size) {
-		IPAERR("Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->ipv4_rules_offset, (init->table_entries + 1),
 			tmp, ipa3_ctx->nat_mem.size);
 		return -EPERM;
@@ -389,8 +389,8 @@
 
 	/* check for integer overflow */
 	if (init->expn_rules_offset >
-		UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries)) {
-		IPAERR("Detected overflow\n");
+		(UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries))) {
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Expn Table Entry offset is not
@@ -399,8 +399,8 @@
 	tmp = init->expn_rules_offset +
 		(TBL_ENTRY_SIZE * init->expn_table_entries);
 	if (tmp > ipa3_ctx->nat_mem.size) {
-		IPAERR("Expn Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Expn Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->expn_rules_offset, init->expn_table_entries,
 			tmp, ipa3_ctx->nat_mem.size);
 		return -EPERM;
@@ -409,7 +409,7 @@
 	/* check for integer overflow */
 	if (init->index_offset >
 		UINT_MAX - (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1))) {
-		IPAERR("Detected overflow\n");
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Indx Table Entry offset is not
@@ -418,8 +418,8 @@
 	tmp = init->index_offset +
 		(INDX_TBL_ENTRY_SIZE * (init->table_entries + 1));
 	if (tmp > ipa3_ctx->nat_mem.size) {
-		IPAERR("Indx Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Indx Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->index_offset, (init->table_entries + 1),
 			tmp, ipa3_ctx->nat_mem.size);
 		return -EPERM;
@@ -428,7 +428,7 @@
 	/* check for integer overflow */
 	if (init->index_expn_offset >
 		UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries)) {
-		IPAERR("Detected overflow\n");
+		IPAERR_RL("Detected overflow\n");
 		return -EPERM;
 	}
 	/* Check Expn Table entry offset is not
@@ -437,8 +437,8 @@
 	tmp = init->index_expn_offset +
 		(INDX_TBL_ENTRY_SIZE * init->expn_table_entries);
 	if (tmp > ipa3_ctx->nat_mem.size) {
-		IPAERR("Indx Expn Table rules offset not valid\n");
-		IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n",
+		IPAERR_RL("Indx Expn Table rules offset not valid\n");
+		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
 			init->index_expn_offset, init->expn_table_entries,
 			tmp, ipa3_ctx->nat_mem.size);
 		return -EPERM;
@@ -476,16 +476,16 @@
 				(init->expn_rules_offset > offset) ||
 				(init->index_offset > offset) ||
 				(init->index_expn_offset > offset)) {
-			IPAERR("Failed due to integer overflow\n");
-			IPAERR("nat.mem.dma_handle: 0x%pa\n",
+			IPAERR_RL("Failed due to integer overflow\n");
+			IPAERR_RL("nat.mem.dma_handle: 0x%pa\n",
 				&ipa3_ctx->nat_mem.dma_handle);
-			IPAERR("ipv4_rules_offset: 0x%x\n",
+			IPAERR_RL("ipv4_rules_offset: 0x%x\n",
 				init->ipv4_rules_offset);
-			IPAERR("expn_rules_offset: 0x%x\n",
+			IPAERR_RL("expn_rules_offset: 0x%x\n",
 				init->expn_rules_offset);
-			IPAERR("index_offset: 0x%x\n",
+			IPAERR_RL("index_offset: 0x%x\n",
 				init->index_offset);
-			IPAERR("index_expn_offset: 0x%x\n",
+			IPAERR_RL("index_expn_offset: 0x%x\n",
 				init->index_expn_offset);
 			result = -EPERM;
 			goto destroy_imm_cmd;
@@ -544,7 +544,7 @@
 	cmd_pyld[num_cmd] = ipahal_construct_imm_cmd(
 		IPA_IMM_CMD_IP_V4_NAT_INIT, &cmd, false);
 	if (!cmd_pyld[num_cmd]) {
-		IPAERR("Fail to construct ip_v4_nat_init imm cmd\n");
+		IPAERR_RL("Fail to construct ip_v4_nat_init imm cmd\n");
 		result = -EPERM;
 		goto destroy_imm_cmd;
 	}
@@ -747,7 +747,7 @@
 
 	IPADBG("\n");
 	if (dma->entries <= 0) {
-		IPAERR("Invalid number of commands %d\n",
+		IPAERR_RL("Invalid number of commands %d\n",
 			dma->entries);
 		ret = -EPERM;
 		goto bail;
@@ -755,7 +755,7 @@
 
 	for (cnt = 0; cnt < dma->entries; cnt++) {
 		if (dma->dma[cnt].table_index >= 1) {
-			IPAERR("Invalid table index %d\n",
+			IPAERR_RL("Invalid table index %d\n",
 				dma->dma[cnt].table_index);
 			ret = -EPERM;
 			goto bail;
@@ -766,7 +766,7 @@
 			if (dma->dma[cnt].offset >=
 				(ipa3_ctx->nat_mem.size_base_tables + 1) *
 				NAT_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -778,7 +778,7 @@
 			if (dma->dma[cnt].offset >=
 				ipa3_ctx->nat_mem.size_expansion_tables *
 				NAT_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -790,7 +790,7 @@
 			if (dma->dma[cnt].offset >=
 				(ipa3_ctx->nat_mem.size_base_tables + 1) *
 				NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -802,7 +802,7 @@
 			if (dma->dma[cnt].offset >=
 				ipa3_ctx->nat_mem.size_expansion_tables *
 				NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
-				IPAERR("Invalid offset %d\n",
+				IPAERR_RL("Invalid offset %d\n",
 					dma->dma[cnt].offset);
 				ret = -EPERM;
 				goto bail;
@@ -811,7 +811,7 @@
 			break;
 
 		default:
-			IPAERR("Invalid base_addr %d\n",
+			IPAERR_RL("Invalid base_addr %d\n",
 				dma->dma[cnt].base_addr);
 			ret = -EPERM;
 			goto bail;
@@ -853,7 +853,7 @@
 		cmd.data = dma->dma[cnt].data;
 		cmd_pyld = ipahal_construct_imm_cmd(cmd_name, &cmd, false);
 		if (!cmd_pyld) {
-			IPAERR("Fail to construct nat_dma imm cmd\n");
+			IPAERR_RL("Fail to construct nat_dma imm cmd\n");
 			continue;
 		}
 		desc[1].type = IPA_IMM_CMD_DESC;
@@ -1016,7 +1016,7 @@
 	cmd_pyld = ipahal_construct_imm_cmd(
 		IPA_IMM_CMD_IP_V4_NAT_INIT, &cmd, false);
 	if (!cmd_pyld) {
-		IPAERR("Fail to construct ip_v4_nat_init imm cmd\n");
+		IPAERR_RL("Fail to construct ip_v4_nat_init imm cmd\n");
 		result = -EPERM;
 		goto destroy_regwrt_imm_cmd;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 80c3996..61bccc6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -808,6 +808,11 @@
 		return -EINVAL;
 	}
 
+	if (req->source_pipe_index == -1) {
+		IPAWANERR("Source pipe index invalid\n");
+		return -EINVAL;
+	}
+
 	mutex_lock(&ipa3_qmi_lock);
 	if (ipa3_qmi_ctx != NULL) {
 		/* cache the qmi_filter_request */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 234b945..ef0158e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -694,7 +694,7 @@
 	struct ipa3_rt_tbl_set *set;
 
 	if (strnlen(name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) {
-		IPAERR("Name too long: %s\n", name);
+		IPAERR_RL("Name too long: %s\n", name);
 		return NULL;
 	}
 
@@ -720,7 +720,7 @@
 	struct ipa3_rt_tbl *entry;
 
 	if (in->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -746,7 +746,7 @@
 	int max_tbl_indx;
 
 	if (name == NULL) {
-		IPAERR("no tbl name\n");
+		IPAERR_RL("no tbl name\n");
 		goto error;
 	}
 
@@ -759,7 +759,7 @@
 			max(IPA_MEM_PART(v6_modem_rt_index_hi),
 			IPA_MEM_PART(v6_apps_rt_index_hi));
 	} else {
-		IPAERR("bad ip family type\n");
+		IPAERR_RL("bad ip family type\n");
 		goto error;
 	}
 
@@ -801,7 +801,7 @@
 			!ipa3_ctx->ip4_rt_tbl_nhash_lcl :
 			!ipa3_ctx->ip6_rt_tbl_nhash_lcl;
 		set->tbl_cnt++;
-		idr_init(&entry->rule_ids);
+		entry->rule_ids = &set->rule_ids;
 		list_add(&entry->link, &set->head_rt_tbl_list);
 
 		IPADBG("add rt tbl idx=%d tbl_cnt=%d ip=%d\n", entry->idx,
@@ -820,7 +820,7 @@
 ipa_insert_failed:
 	set->tbl_cnt--;
 	list_del(&entry->link);
-	idr_destroy(&entry->rule_ids);
+	idr_destroy(entry->rule_ids);
 fail_rt_idx_alloc:
 	entry->cookie = 0;
 	kmem_cache_free(ipa3_ctx->rt_tbl_cache, entry);
@@ -835,12 +835,12 @@
 	struct ipa3_rt_tbl_set *rset;
 
 	if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) {
-		IPAERR("bad parms\n");
+		IPAERR_RL("bad parms\n");
 		return -EINVAL;
 	}
 	id = entry->id;
 	if (ipa3_id_find(id) == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EPERM;
 	}
 
@@ -855,7 +855,7 @@
 
 	rset = &ipa3_ctx->reap_rt_tbl_set[ip];
 
-	idr_destroy(&entry->rule_ids);
+	entry->rule_ids = NULL;
 	if (entry->in_sys[IPA_RULE_HASHABLE] ||
 		entry->in_sys[IPA_RULE_NON_HASHABLE]) {
 		list_move(&entry->link, &rset->head_rt_tbl_list);
@@ -923,7 +923,7 @@
 	(*(entry))->tbl = tbl;
 	(*(entry))->hdr = hdr;
 	(*(entry))->proc_ctx = proc_ctx;
-	id = ipa3_alloc_rule_id(&tbl->rule_ids);
+	id = ipa3_alloc_rule_id(tbl->rule_ids);
 	if (id < 0) {
 		IPAERR("failed to allocate rule id\n");
 		WARN_ON(1);
@@ -967,7 +967,7 @@
 		entry->hdr->ref_cnt--;
 	else if (entry->proc_ctx)
 		entry->proc_ctx->ref_cnt--;
-	idr_remove(&tbl->rule_ids, entry->rule_id);
+	idr_remove(tbl->rule_ids, entry->rule_id);
 	list_del(&entry->link);
 	kmem_cache_free(ipa3_ctx->rt_rule_cache, entry);
 	return -EPERM;
@@ -987,7 +987,7 @@
 
 	tbl = __ipa_add_rt_tbl(ip, name);
 	if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) {
-		IPAERR("failed adding rt tbl name = %s\n",
+		IPAERR_RL("failed adding rt tbl name = %s\n",
 			name ? name : "");
 		goto error;
 	}
@@ -997,8 +997,8 @@
 	 */
 	if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) &&
 	    (tbl->rule_cnt > 0) && (at_rear != 0)) {
-		IPAERR("cannot add rule at end of tbl rule_cnt=%d at_rear=%d\n",
-		       tbl->rule_cnt, at_rear);
+		IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d at_rear=%d"
+				, tbl->rule_cnt, at_rear);
 		goto error;
 	}
 
@@ -1068,7 +1068,7 @@
 	int ret;
 
 	if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1078,7 +1078,7 @@
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
 					&rules->rules[i].rt_rule_hdl)) {
-			IPAERR("failed to add rt rule %d\n", i);
+			IPAERR_RL("failed to add rt rule %d\n", i);
 			rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED;
 		} else {
 			rules->rules[i].status = 0;
@@ -1114,7 +1114,7 @@
 	struct ipa3_rt_entry *entry = NULL;
 
 	if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1122,28 +1122,28 @@
 
 	tbl = __ipa3_find_rt_tbl(rules->ip, rules->rt_tbl_name);
 	if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) {
-		IPAERR("failed finding rt tbl name = %s\n",
+		IPAERR_RL("failed finding rt tbl name = %s\n",
 			rules->rt_tbl_name ? rules->rt_tbl_name : "");
 		ret = -EINVAL;
 		goto bail;
 	}
 
 	if (tbl->rule_cnt <= 0) {
-		IPAERR("tbl->rule_cnt <= 0");
+		IPAERR_RL("tbl->rule_cnt <= 0");
 		ret = -EINVAL;
 		goto bail;
 	}
 
 	entry = ipa3_id_find(rules->add_after_hdl);
 	if (!entry) {
-		IPAERR("failed finding rule %d in rt tbls\n",
+		IPAERR_RL("failed finding rule %d in rt tbls\n",
 			rules->add_after_hdl);
 		ret = -EINVAL;
 		goto bail;
 	}
 
 	if (entry->tbl != tbl) {
-		IPAERR("given rt rule does not match the table\n");
+		IPAERR_RL("given rt rule does not match the table\n");
 		ret = -EINVAL;
 		goto bail;
 	}
@@ -1154,7 +1154,7 @@
 	 */
 	if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) &&
 			(&entry->link == tbl->head_rt_rule_list.prev)) {
-		IPAERR("cannot add rule at end of tbl rule_cnt=%d\n",
+		IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d\n",
 			tbl->rule_cnt);
 		ret = -EINVAL;
 		goto bail;
@@ -1171,7 +1171,7 @@
 					&rules->rules[i].rule,
 					&rules->rules[i].rt_rule_hdl,
 					&entry)) {
-			IPAERR("failed to add rt rule %d\n", i);
+			IPAERR_RL("failed to add rt rule %d\n", i);
 			rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED;
 		} else {
 			rules->rules[i].status = 0;
@@ -1180,7 +1180,7 @@
 
 	if (rules->commit)
 		if (ipa3_ctx->ctrl->ipa3_commit_rt(rules->ip)) {
-			IPAERR("failed to commit\n");
+			IPAERR_RL("failed to commit\n");
 			ret = -EPERM;
 			goto bail;
 		}
@@ -1201,12 +1201,12 @@
 	entry = ipa3_id_find(rule_hdl);
 
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		return -EINVAL;
 	}
 
 	if (entry->cookie != IPA_RT_RULE_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		return -EINVAL;
 	}
 
@@ -1219,10 +1219,10 @@
 	IPADBG("del rt rule tbl_idx=%d rule_cnt=%d rule_id=%d\n ref_cnt=%u",
 		entry->tbl->idx, entry->tbl->rule_cnt,
 		entry->rule_id, entry->tbl->ref_cnt);
-	idr_remove(&entry->tbl->rule_ids, entry->rule_id);
+	idr_remove(entry->tbl->rule_ids, entry->rule_id);
 	if (entry->tbl->rule_cnt == 0 && entry->tbl->ref_cnt == 0) {
 		if (__ipa_del_rt_tbl(entry->tbl))
-			IPAERR("fail to del RT tbl\n");
+			IPAERR_RL("fail to del RT tbl\n");
 	}
 	entry->cookie = 0;
 	id = entry->id;
@@ -1249,14 +1249,14 @@
 	int ret;
 
 	if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa3_ctx->lock);
 	for (i = 0; i < hdls->num_hdls; i++) {
 		if (__ipa3_del_rt_rule(hdls->hdl[i].hdl)) {
-			IPAERR("failed to del rt rule %i\n", i);
+			IPAERR_RL("failed to del rt rule %i\n", i);
 			hdls->hdl[i].status = IPA_RT_STATUS_OF_DEL_FAILED;
 		} else {
 			hdls->hdl[i].status = 0;
@@ -1289,7 +1289,7 @@
 	int ret;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1333,7 +1333,7 @@
 	int id;
 
 	if (ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
@@ -1349,7 +1349,7 @@
 	 * filtering rules point to routing tables
 	 */
 	if (ipa3_reset_flt(ip))
-		IPAERR("fail to reset flt ip=%d\n", ip);
+		IPAERR_RL("fail to reset flt ip=%d\n", ip);
 
 	set = &ipa3_ctx->rt_tbl_set[ip];
 	rset = &ipa3_ctx->reap_rt_tbl_set[ip];
@@ -1378,7 +1378,7 @@
 			else if (rule->proc_ctx)
 				__ipa3_release_hdr_proc_ctx(rule->proc_ctx->id);
 			rule->cookie = 0;
-			idr_remove(&tbl->rule_ids, rule->rule_id);
+			idr_remove(tbl->rule_ids, rule->rule_id);
 			id = rule->id;
 			kmem_cache_free(ipa3_ctx->rt_rule_cache, rule);
 
@@ -1395,7 +1395,7 @@
 
 		/* do not remove the "default" routing tbl which has index 0 */
 		if (tbl->idx != apps_start_idx) {
-			idr_destroy(&tbl->rule_ids);
+			tbl->rule_ids = NULL;
 			if (tbl->in_sys[IPA_RULE_HASHABLE] ||
 				tbl->in_sys[IPA_RULE_NON_HASHABLE]) {
 				list_move(&tbl->link, &rset->head_rt_tbl_list);
@@ -1438,21 +1438,27 @@
 	int result = -EFAULT;
 
 	if (lookup == NULL || lookup->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 	mutex_lock(&ipa3_ctx->lock);
 	entry = __ipa3_find_rt_tbl(lookup->ip, lookup->name);
 	if (entry && entry->cookie == IPA_RT_TBL_COOKIE) {
+		if (entry->ref_cnt == U32_MAX) {
+			IPAERR("fail: ref count crossed limit\n");
+			goto ret;
+		}
 		entry->ref_cnt++;
 		lookup->hdl = entry->id;
 
 		/* commit for get */
 		if (ipa3_ctx->ctrl->ipa3_commit_rt(lookup->ip))
-			IPAERR("fail to commit RT tbl\n");
+			IPAERR_RL("fail to commit RT tbl\n");
 
 		result = 0;
 	}
+
+ret:
 	mutex_unlock(&ipa3_ctx->lock);
 
 	return result;
@@ -1470,18 +1476,18 @@
 {
 	struct ipa3_rt_tbl *entry;
 	enum ipa_ip_type ip = IPA_IP_MAX;
-	int result;
+	int result = 0;
 
 	mutex_lock(&ipa3_ctx->lock);
 	entry = ipa3_id_find(rt_tbl_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		result = -EINVAL;
 		goto ret;
 	}
 
 	if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) {
-		IPAERR("bad parms\n");
+		IPAERR_RL("bad parms\n");
 		result = -EINVAL;
 		goto ret;
 	}
@@ -1501,10 +1507,10 @@
 		IPADBG("zero ref_cnt, delete rt tbl (idx=%u)\n",
 			entry->idx);
 		if (__ipa_del_rt_tbl(entry))
-			IPAERR("fail to del RT tbl\n");
+			IPAERR_RL("fail to del RT tbl\n");
 		/* commit for put */
 		if (ipa3_ctx->ctrl->ipa3_commit_rt(ip))
-			IPAERR("fail to commit RT tbl\n");
+			IPAERR_RL("fail to commit RT tbl\n");
 	}
 
 	result = 0;
@@ -1525,26 +1531,26 @@
 	if (rtrule->rule.hdr_hdl) {
 		hdr = ipa3_id_find(rtrule->rule.hdr_hdl);
 		if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) {
-			IPAERR("rt rule does not point to valid hdr\n");
+			IPAERR_RL("rt rule does not point to valid hdr\n");
 			goto error;
 		}
 	} else if (rtrule->rule.hdr_proc_ctx_hdl) {
 		proc_ctx = ipa3_id_find(rtrule->rule.hdr_proc_ctx_hdl);
 		if ((proc_ctx == NULL) ||
 			(proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) {
-			IPAERR("rt rule does not point to valid proc ctx\n");
+			IPAERR_RL("rt rule does not point to valid proc ctx\n");
 			goto error;
 		}
 	}
 
 	entry = ipa3_id_find(rtrule->rt_rule_hdl);
 	if (entry == NULL) {
-		IPAERR("lookup failed\n");
+		IPAERR_RL("lookup failed\n");
 		goto error;
 	}
 
 	if (entry->cookie != IPA_RT_RULE_COOKIE) {
-		IPAERR("bad params\n");
+		IPAERR_RL("bad params\n");
 		goto error;
 	}
 
@@ -1585,14 +1591,14 @@
 	int result;
 
 	if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) {
-		IPAERR("bad parm\n");
+		IPAERR_RL("bad parm\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&ipa3_ctx->lock);
 	for (i = 0; i < hdls->num_rules; i++) {
 		if (__ipa_mdfy_rt_rule(&hdls->rules[i])) {
-			IPAERR("failed to mdfy rt rule %i\n", i);
+			IPAERR_RL("failed to mdfy rt rule %i\n", i);
 			hdls->rules[i].status = IPA_RT_STATUS_OF_MDFY_FAILED;
 		} else {
 			hdls->rules[i].status = 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 60dc04f..c97d2b3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -1668,7 +1668,7 @@
 
 	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
 	    ipa3_ctx->ep[clnt_hdl].valid == 0) {
-		IPAERR("bad parm, %d\n", clnt_hdl);
+		IPAERR_RL("bad parm, %d\n", clnt_hdl);
 		return -EINVAL;
 	}
 
@@ -1681,7 +1681,7 @@
 	ep = &ipa3_ctx->ep[clnt_hdl];
 
 	if (!(ep->uc_offload_state & IPA_WDI_CONNECTED)) {
-		IPAERR("WDI channel bad state %d\n", ep->uc_offload_state);
+		IPAERR_RL("WDI channel bad state %d\n", ep->uc_offload_state);
 		return -EFAULT;
 	}
 	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl));
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index a251359..8fe15bc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -21,6 +21,7 @@
 #include "ipa_i.h"
 #include "ipahal/ipahal.h"
 #include "ipahal/ipahal_fltrt.h"
+#include "ipahal/ipahal_hw_stats.h"
 #include "../ipa_rm_i.h"
 
 #define IPA_V3_0_CLK_RATE_SVS (75 * 1000 * 1000UL)
@@ -1141,7 +1142,7 @@
 	[IPA_4_0][IPA_CLIENT_ODU_PROD]            = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
-			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
+			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 0, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_ETHERNET_PROD]	  = {
@@ -1988,7 +1989,7 @@
  */
 int ipa3_cfg_filter(u32 disable)
 {
-	IPAERR("Filter disable is not supported!\n");
+	IPAERR_RL("Filter disable is not supported!\n");
 	return -EPERM;
 }
 
@@ -2123,7 +2124,7 @@
 	int ipa_ep_idx;
 
 	if (client >= IPA_CLIENT_MAX || client < 0) {
-		IPAERR("Bad client number! client =%d\n", client);
+		IPAERR_RL("Bad client number! client =%d\n", client);
 		return IPA_EP_NOT_ALLOCATED;
 	}
 
@@ -3281,19 +3282,19 @@
 	int result = -EINVAL;
 
 	if (param_in->client  >= IPA_CLIENT_MAX) {
-		IPAERR("bad parm client:%d\n", param_in->client);
+		IPAERR_RL("bad parm client:%d\n", param_in->client);
 		goto fail;
 	}
 
 	ipa_ep_idx = ipa3_get_ep_mapping(param_in->client);
 	if (ipa_ep_idx == -1) {
-		IPAERR("Invalid client.\n");
+		IPAERR_RL("Invalid client.\n");
 		goto fail;
 	}
 
 	ep = &ipa3_ctx->ep[ipa_ep_idx];
 	if (!ep->valid) {
-		IPAERR("EP not allocated.\n");
+		IPAERR_RL("EP not allocated.\n");
 		goto fail;
 	}
 
@@ -3307,7 +3308,7 @@
 		ipa3_ctx->ep[ipa_ep_idx].cfg.meta = meta;
 		result = ipa3_write_qmapid_wdi_pipe(ipa_ep_idx, meta.qmap_id);
 		if (result)
-			IPAERR("qmap_id %d write failed on ep=%d\n",
+			IPAERR_RL("qmap_id %d write failed on ep=%d\n",
 					meta.qmap_id, ipa_ep_idx);
 		result = 0;
 	}
@@ -4061,7 +4062,7 @@
 			IPAHAL_FULL_PIPELINE_CLEAR;
 		reg_write_agg_close.offset =
 			ipahal_get_reg_ofst(IPA_AGGR_FORCE_CLOSE);
-		ipahal_get_aggr_force_close_valmask(1<<i, &valmask);
+		ipahal_get_aggr_force_close_valmask(i, &valmask);
 		reg_write_agg_close.value = valmask.val;
 		reg_write_agg_close.value_mask = valmask.mask;
 		cmd_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
@@ -4455,6 +4456,7 @@
 	api_ctrl->ipa_create_wdi_mapping = ipa3_create_wdi_mapping;
 	api_ctrl->ipa_get_gsi_ep_info = ipa3_get_gsi_ep_info;
 	api_ctrl->ipa_stop_gsi_channel = ipa3_stop_gsi_channel;
+	api_ctrl->ipa_start_gsi_channel = ipa3_start_gsi_channel;
 	api_ctrl->ipa_register_ipa_ready_cb = ipa3_register_ipa_ready_cb;
 	api_ctrl->ipa_inc_client_enable_clks = ipa3_inc_client_enable_clks;
 	api_ctrl->ipa_dec_client_disable_clks = ipa3_dec_client_disable_clks;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile b/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile
index b945eb06..67e491b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_IPA3) += ipa_hal.o
 
-ipa_hal-y := ipahal.o ipahal_reg.o ipahal_fltrt.o
+ipa_hal-y := ipahal.o ipahal_reg.o ipahal_fltrt.o ipahal_hw_stats.o
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 57d44e3..56fed2a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -15,6 +15,8 @@
 #include "ipahal_i.h"
 #include "ipahal_reg_i.h"
 #include "ipahal_fltrt_i.h"
+#include "ipahal_hw_stats_i.h"
+
 
 struct ipahal_context *ipahal_ctx;
 
@@ -48,9 +50,6 @@
 	__stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT),
 };
 
-#define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
-		(kzalloc((__size), ((__is_atomic_ctx)?GFP_ATOMIC:GFP_KERNEL)))
-
 static u16 ipahal_imm_cmd_get_opcode(enum ipahal_imm_cmd_name cmd);
 
 
@@ -1167,7 +1166,7 @@
 		u32 hdr_len, bool is_hdr_proc_ctx,
 		dma_addr_t phys_base, u32 hdr_base_addr,
 		struct ipa_hdr_offset_entry *offset_entry,
-		union ipa_l2tp_hdr_proc_ctx_params l2tp_params){
+		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params){
 	if (type == IPA_HDR_PROC_NONE) {
 		struct ipa_hw_hdr_proc_ctx_add_hdr_seq *ctx;
 
@@ -1230,6 +1229,17 @@
 			l2tp_params.hdr_remove_param.hdr_len_remove;
 		ctx->l2tp_params.l2tp_params.eth_hdr_retained =
 			l2tp_params.hdr_remove_param.eth_hdr_retained;
+		ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size_valid =
+			l2tp_params.hdr_remove_param.hdr_ofst_pkt_size_valid;
+		ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size =
+			l2tp_params.hdr_remove_param.hdr_ofst_pkt_size;
+		ctx->l2tp_params.l2tp_params.hdr_endianness =
+			l2tp_params.hdr_remove_param.hdr_endianness;
+		IPAHAL_DBG("hdr ofst valid: %d, hdr ofst pkt size: %d\n",
+			ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size_valid,
+			ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size);
+		IPAHAL_DBG("endianness: %d\n",
+			ctx->l2tp_params.l2tp_params.hdr_endianness);
 
 		IPAHAL_DBG("command id %d\n", ctx->l2tp_params.tlv.value);
 		ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
@@ -1304,7 +1314,7 @@
 			bool is_hdr_proc_ctx, dma_addr_t phys_base,
 			u32 hdr_base_addr,
 			struct ipa_hdr_offset_entry *offset_entry,
-			union ipa_l2tp_hdr_proc_ctx_params l2tp_params);
+			struct ipa_l2tp_hdr_proc_ctx_params l2tp_params);
 
 	int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type);
 };
@@ -1375,7 +1385,7 @@
 		void *const base, u32 offset, u32 hdr_len,
 		bool is_hdr_proc_ctx, dma_addr_t phys_base,
 		u32 hdr_base_addr, struct ipa_hdr_offset_entry *offset_entry,
-		union ipa_l2tp_hdr_proc_ctx_params l2tp_params)
+		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params)
 {
 	IPAHAL_DBG(
 		"type %d, base %p, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %d, offset_entry %p\n"
@@ -1504,6 +1514,12 @@
 		goto bail_free_ctx;
 	}
 
+	if (ipahal_hw_stats_init(ipa_hw_type)) {
+		IPAHAL_ERR("failed to init ipahal hw stats\n");
+		result = -EFAULT;
+		goto bail_free_ctx;
+	}
+
 	ipahal_debugfs_init();
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 0f322b5..56b884b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -637,7 +637,7 @@
 		bool is_hdr_proc_ctx, dma_addr_t phys_base,
 		u32 hdr_base_addr,
 		struct ipa_hdr_offset_entry *offset_entry,
-		union ipa_l2tp_hdr_proc_ctx_params l2tp_params);
+		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params);
 
 /*
  * ipahal_get_proc_ctx_needed_len() - calculates the needed length for addition
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c
new file mode 100644
index 0000000..c711ff4
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c
@@ -0,0 +1,557 @@
+/* Copyright (c) 2017, 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 "ipahal_hw_stats.h"
+#include "ipahal_hw_stats_i.h"
+#include "ipahal_i.h"
+
+struct ipahal_hw_stats_obj {
+	struct ipahal_stats_init_pyld *(*generate_init_pyld)(void *params,
+		bool is_atomic_ctx);
+	int (*get_offset)(void *params, struct ipahal_stats_offset *out);
+	int (*parse_stats)(void *init_params, void *raw_stats,
+		void *parsed_stats);
+};
+
+static int _count_ones(u32 number)
+{
+	int count = 0;
+
+	while (number) {
+		count++;
+		number = number & (number - 1);
+	}
+
+	return count;
+}
+
+static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_quota(
+	void *params, bool is_atomic_ctx)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_stats_init_quota *in =
+		(struct ipahal_stats_init_quota *)params;
+	int entries = _count_ones(in->enabled_bitmask);
+
+	IPAHAL_DBG_LOW("entries = %d\n", entries);
+	pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
+		entries * sizeof(struct ipahal_stats_quota_hw), is_atomic_ctx);
+	if (!pyld) {
+		IPAHAL_ERR("no mem\n");
+		return NULL;
+	}
+
+	pyld->len = entries * sizeof(struct ipahal_stats_quota_hw);
+	return pyld;
+}
+
+static int ipahal_get_offset_quota(void *params,
+	struct ipahal_stats_offset *out)
+{
+	struct ipahal_stats_get_offset_quota *in =
+		(struct ipahal_stats_get_offset_quota *)params;
+	int entries = _count_ones(in->init.enabled_bitmask);
+
+	IPAHAL_DBG_LOW("\n");
+	out->offset = 0;
+	out->size = entries * sizeof(struct ipahal_stats_quota_hw);
+
+	return 0;
+}
+
+static int ipahal_parse_stats_quota(void *init_params, void *raw_stats,
+	void *parsed_stats)
+{
+	struct ipahal_stats_init_quota *init =
+		(struct ipahal_stats_init_quota *)init_params;
+	struct ipahal_stats_quota_hw *raw_hw =
+		(struct ipahal_stats_quota_hw *)raw_stats;
+	struct ipahal_stats_quota_all *out =
+		(struct ipahal_stats_quota_all *)parsed_stats;
+	int stat_idx = 0;
+	int i;
+
+	memset(out, 0, sizeof(*out));
+	IPAHAL_DBG_LOW("\n");
+	for (i = 0; i < IPAHAL_MAX_PIPES; i++) {
+		if (init->enabled_bitmask & (1 << i)) {
+			IPAHAL_DBG_LOW("pipe %d stat_idx %d\n", i, stat_idx);
+			out->stats[i].num_ipv4_bytes =
+				raw_hw[stat_idx].num_ipv4_bytes;
+			out->stats[i].num_ipv4_pkts =
+				raw_hw[stat_idx].num_ipv4_pkts;
+			out->stats[i].num_ipv6_pkts =
+				raw_hw[stat_idx].num_ipv6_pkts;
+			out->stats[i].num_ipv6_bytes =
+				raw_hw[stat_idx].num_ipv6_bytes;
+			stat_idx++;
+		}
+	}
+
+	return 0;
+}
+
+static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_tethering(
+	void *params, bool is_atomic_ctx)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_stats_init_tethering *in =
+		(struct ipahal_stats_init_tethering *)params;
+	int hdr_entries = _count_ones(in->prod_bitmask);
+	int entries = 0;
+	int i;
+	void *pyld_ptr;
+	u32 incremental_offset;
+
+	IPAHAL_DBG_LOW("prod entries = %d\n", hdr_entries);
+	for (i = 0; i < sizeof(in->prod_bitmask) * 8; i++) {
+		if (in->prod_bitmask & (1 << i)) {
+			if (in->cons_bitmask[i] == 0) {
+				IPAHAL_ERR("no cons bitmask for prod %d\n", i);
+				return NULL;
+			}
+			entries += _count_ones(in->cons_bitmask[i]);
+		}
+	}
+	IPAHAL_DBG_LOW("sum all entries = %d\n", entries);
+
+	pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
+		hdr_entries * sizeof(struct ipahal_stats_tethering_hdr_hw) +
+		entries * sizeof(struct ipahal_stats_tethering_hw),
+		is_atomic_ctx);
+	if (!pyld) {
+		IPAHAL_ERR("no mem\n");
+		return NULL;
+	}
+
+	pyld->len = hdr_entries * sizeof(struct ipahal_stats_tethering_hdr_hw) +
+		entries * sizeof(struct ipahal_stats_tethering_hw);
+
+	pyld_ptr = pyld->data;
+	incremental_offset =
+		(hdr_entries * sizeof(struct ipahal_stats_tethering_hdr_hw))
+			/ 8;
+	for (i = 0; i < sizeof(in->prod_bitmask) * 8; i++) {
+		if (in->prod_bitmask & (1 << i)) {
+			struct ipahal_stats_tethering_hdr_hw *hdr = pyld_ptr;
+
+			hdr->dst_mask = in->cons_bitmask[i];
+			hdr->offset = incremental_offset;
+			IPAHAL_DBG_LOW("hdr->dst_mask=0x%x\n", hdr->dst_mask);
+			IPAHAL_DBG_LOW("hdr->offset=0x%x\n", hdr->offset);
+			/* add the stats entry */
+			incremental_offset += _count_ones(in->cons_bitmask[i]) *
+				sizeof(struct ipahal_stats_tethering_hw) / 8;
+			pyld_ptr += sizeof(*hdr);
+		}
+	}
+
+	return pyld;
+}
+
+static int ipahal_get_offset_tethering(void *params,
+	struct ipahal_stats_offset *out)
+{
+	struct ipahal_stats_get_offset_tethering *in =
+		(struct ipahal_stats_get_offset_tethering *)params;
+	int entries = 0;
+	int i;
+
+	for (i = 0; i < sizeof(in->init.prod_bitmask) * 8; i++) {
+		if (in->init.prod_bitmask & (1 << i)) {
+			if (in->init.cons_bitmask[i] == 0) {
+				IPAHAL_ERR("no cons bitmask for prod %d\n", i);
+				return -EPERM;
+			}
+			entries += _count_ones(in->init.cons_bitmask[i]);
+		}
+	}
+	IPAHAL_DBG_LOW("sum all entries = %d\n", entries);
+
+	/* skip the header */
+	out->offset = _count_ones(in->init.prod_bitmask) *
+		sizeof(struct ipahal_stats_tethering_hdr_hw);
+	out->size = entries * sizeof(struct ipahal_stats_tethering_hw);
+
+	return 0;
+}
+
+static int ipahal_parse_stats_tethering(void *init_params, void *raw_stats,
+	void *parsed_stats)
+{
+	struct ipahal_stats_init_tethering *init =
+		(struct ipahal_stats_init_tethering *)init_params;
+	struct ipahal_stats_tethering_hw *raw_hw =
+		(struct ipahal_stats_tethering_hw *)raw_stats;
+	struct ipahal_stats_tethering_all *out =
+		(struct ipahal_stats_tethering_all *)parsed_stats;
+	int i, j;
+	int stat_idx = 0;
+
+	memset(out, 0, sizeof(*out));
+	IPAHAL_DBG_LOW("\n");
+	for (i = 0; i < IPAHAL_MAX_PIPES; i++) {
+		for (j = 0; j < IPAHAL_MAX_PIPES; j++) {
+			if ((init->prod_bitmask & (1 << i)) &&
+			    init->cons_bitmask[i] & (1 << j)) {
+				IPAHAL_DBG_LOW("prod %d cons %d\n", i, j);
+				IPAHAL_DBG_LOW("stat_idx %d\n", stat_idx);
+				out->stats[i][j].num_ipv4_bytes =
+					raw_hw[stat_idx].num_ipv4_bytes;
+				IPAHAL_DBG_LOW("num_ipv4_bytes %lld\n",
+					out->stats[i][j].num_ipv4_bytes);
+				out->stats[i][j].num_ipv4_pkts =
+					raw_hw[stat_idx].num_ipv4_pkts;
+				IPAHAL_DBG_LOW("num_ipv4_pkts %lld\n",
+					out->stats[i][j].num_ipv4_pkts);
+				out->stats[i][j].num_ipv6_pkts =
+					raw_hw[stat_idx].num_ipv6_pkts;
+				IPAHAL_DBG_LOW("num_ipv6_pkts %lld\n",
+					out->stats[i][j].num_ipv6_pkts);
+				out->stats[i][j].num_ipv6_bytes =
+					raw_hw[stat_idx].num_ipv6_bytes;
+				IPAHAL_DBG_LOW("num_ipv6_bytes %lld\n",
+					out->stats[i][j].num_ipv6_bytes);
+				stat_idx++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_flt_rt(
+	void *params, bool is_atomic_ctx)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_stats_init_flt_rt *in =
+		(struct ipahal_stats_init_flt_rt *)params;
+	int hdr_entries;
+	int num_rules = 0;
+	int i, start_entry;
+	void *pyld_ptr;
+	u32 incremental_offset;
+
+	for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++)
+		num_rules += _count_ones(in->rule_id_bitmask[i]);
+
+	if (num_rules == 0) {
+		IPAHAL_ERR("no rule ids provided\n");
+		return NULL;
+	}
+	IPAHAL_DBG_LOW("num_rules = %d\n", num_rules);
+
+	hdr_entries = IPAHAL_MAX_RULE_ID_32;
+	for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++) {
+		if (in->rule_id_bitmask[i] != 0)
+			break;
+		hdr_entries--;
+	}
+	start_entry = i;
+
+	for (i = IPAHAL_MAX_RULE_ID_32 - 1; i >= start_entry; i--) {
+		if (in->rule_id_bitmask[i] != 0)
+			break;
+		hdr_entries--;
+	}
+	IPAHAL_DBG_LOW("hdr_entries = %d\n", hdr_entries);
+
+	pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
+		hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw) +
+		num_rules * sizeof(struct ipahal_stats_flt_rt_hw),
+		is_atomic_ctx);
+	if (!pyld) {
+		IPAHAL_ERR("no mem\n");
+		return NULL;
+	}
+
+	pyld->len = hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw) +
+		num_rules * sizeof(struct ipahal_stats_flt_rt_hw);
+
+	pyld_ptr = pyld->data;
+	incremental_offset =
+		(hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw))
+			/ 8;
+	for (i = start_entry; i < hdr_entries; i++) {
+		struct ipahal_stats_flt_rt_hdr_hw *hdr = pyld_ptr;
+
+		hdr->en_mask = in->rule_id_bitmask[i];
+		hdr->cnt_offset = incremental_offset;
+		/* add the stats entry */
+		incremental_offset += _count_ones(in->rule_id_bitmask[i]) *
+			sizeof(struct ipahal_stats_flt_rt_hw) / 8;
+		pyld_ptr += sizeof(*hdr);
+	}
+
+	return pyld;
+}
+
+static int ipahal_get_offset_flt_rt(void *params,
+	struct ipahal_stats_offset *out)
+{
+	struct ipahal_stats_get_offset_flt_rt *in =
+		(struct ipahal_stats_get_offset_flt_rt *)params;
+	int i;
+	int hdr_entries;
+	int skip_rules = 0;
+	int start_entry;
+	int rule_bit = in->rule_id % 32;
+	int rule_idx = in->rule_id / 32;
+
+	if (rule_idx >= IPAHAL_MAX_RULE_ID_32) {
+		IPAHAL_ERR("invalid rule_id %d\n", in->rule_id);
+		return -EPERM;
+	}
+
+	hdr_entries = IPAHAL_MAX_RULE_ID_32;
+	for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++) {
+		if (in->init.rule_id_bitmask[i] != 0)
+			break;
+		hdr_entries--;
+	}
+
+	if (hdr_entries == 0) {
+		IPAHAL_ERR("no rule ids provided\n");
+		return -EPERM;
+	}
+	start_entry = i;
+
+	for (i = IPAHAL_MAX_RULE_ID_32 - 1; i >= 0; i--) {
+		if (in->init.rule_id_bitmask[i] != 0)
+			break;
+		hdr_entries--;
+	}
+	IPAHAL_DBG_LOW("hdr_entries = %d\n", hdr_entries);
+
+	/* skip the header */
+	out->offset = hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw);
+
+	/* skip the previous rules  */
+	for (i = start_entry; i < rule_idx; i++)
+		skip_rules += _count_ones(in->init.rule_id_bitmask[i]);
+
+	for (i = 0; i < rule_bit; i++)
+		if (in->init.rule_id_bitmask[rule_idx] & (1 << i))
+			skip_rules++;
+
+	out->offset += skip_rules * sizeof(struct ipahal_stats_flt_rt_hw);
+	out->size = sizeof(struct ipahal_stats_flt_rt_hw);
+
+	return 0;
+}
+
+static int ipahal_parse_stats_flt_rt(void *init_params, void *raw_stats,
+	void *parsed_stats)
+{
+	struct ipahal_stats_flt_rt_hw *raw_hw =
+		(struct ipahal_stats_flt_rt_hw *)raw_stats;
+	struct ipahal_stats_flt_rt *out =
+		(struct ipahal_stats_flt_rt *)parsed_stats;
+
+	memset(out, 0, sizeof(*out));
+	IPAHAL_DBG_LOW("\n");
+	out->num_packets = raw_hw->num_packets;
+	out->num_packets_hash = raw_hw->num_packets_hash;
+
+	return 0;
+}
+
+static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_drop(
+	void *params, bool is_atomic_ctx)
+{
+	struct ipahal_stats_init_pyld *pyld;
+	struct ipahal_stats_init_drop *in =
+		(struct ipahal_stats_init_drop *)params;
+	int entries = _count_ones(in->enabled_bitmask);
+
+	IPAHAL_DBG_LOW("entries = %d\n", entries);
+	pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
+		entries * sizeof(struct ipahal_stats_drop_hw), is_atomic_ctx);
+	if (!pyld) {
+		IPAHAL_ERR("no mem\n");
+		return NULL;
+	}
+
+	pyld->len = entries * sizeof(struct ipahal_stats_drop_hw);
+
+	return pyld;
+}
+
+static int ipahal_get_offset_drop(void *params,
+	struct ipahal_stats_offset *out)
+{
+	struct ipahal_stats_get_offset_drop *in =
+		(struct ipahal_stats_get_offset_drop *)params;
+	int entries = _count_ones(in->init.enabled_bitmask);
+
+	IPAHAL_DBG_LOW("\n");
+	out->offset = 0;
+	out->size = entries * sizeof(struct ipahal_stats_drop_hw);
+
+	return 0;
+}
+
+static int ipahal_parse_stats_drop(void *init_params, void *raw_stats,
+	void *parsed_stats)
+{
+	struct ipahal_stats_init_drop *init =
+		(struct ipahal_stats_init_drop *)init_params;
+	struct ipahal_stats_drop_hw *raw_hw =
+		(struct ipahal_stats_drop_hw *)raw_stats;
+	struct ipahal_stats_drop_all *out =
+		(struct ipahal_stats_drop_all *)parsed_stats;
+	int stat_idx = 0;
+	int i;
+
+	memset(out, 0, sizeof(*out));
+	IPAHAL_DBG_LOW("\n");
+	for (i = 0; i < IPAHAL_MAX_PIPES; i++) {
+		if (init->enabled_bitmask & (1 << i)) {
+			out->stats[i].drop_byte_cnt =
+				raw_hw[stat_idx].drop_byte_cnt;
+			out->stats[i].drop_packet_cnt =
+				raw_hw[stat_idx].drop_packet_cnt;
+			stat_idx++;
+		}
+	}
+
+	return 0;
+}
+
+static struct ipahal_hw_stats_obj
+	ipahal_hw_stats_objs[IPA_HW_MAX][IPAHAL_HW_STATS_MAX] = {
+	/* IPAv4 */
+	[IPA_HW_v4_0][IPAHAL_HW_STATS_QUOTA] = {
+		ipahal_generate_init_pyld_quota,
+		ipahal_get_offset_quota,
+		ipahal_parse_stats_quota
+	},
+	[IPA_HW_v4_0][IPAHAL_HW_STATS_TETHERING] = {
+		ipahal_generate_init_pyld_tethering,
+		ipahal_get_offset_tethering,
+		ipahal_parse_stats_tethering
+	},
+	[IPA_HW_v4_0][IPAHAL_HW_STATS_FNR] = {
+		ipahal_generate_init_pyld_flt_rt,
+		ipahal_get_offset_flt_rt,
+		ipahal_parse_stats_flt_rt
+	},
+	[IPA_HW_v4_0][IPAHAL_HW_STATS_DROP] = {
+		ipahal_generate_init_pyld_drop,
+		ipahal_get_offset_drop,
+		ipahal_parse_stats_drop
+	},
+};
+
+int ipahal_hw_stats_init(enum ipa_hw_type ipa_hw_type)
+{
+	int i;
+	int j;
+	struct ipahal_hw_stats_obj zero_obj;
+
+	IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+
+	if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+		IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+		return -EINVAL;
+	}
+
+	memset(&zero_obj, 0, sizeof(zero_obj));
+	for (i = IPA_HW_v4_0 ; i < ipa_hw_type ; i++) {
+		for (j = 0; j < IPAHAL_HW_STATS_MAX; j++) {
+			if (!memcmp(&ipahal_hw_stats_objs[i + 1][j], &zero_obj,
+				sizeof(struct ipahal_hw_stats_obj))) {
+				memcpy(&ipahal_hw_stats_objs[i + 1][j],
+					&ipahal_hw_stats_objs[i][j],
+					sizeof(struct ipahal_hw_stats_obj));
+			} else {
+				/*
+				 * explicitly overridden stat.
+				 * Check validity
+				 */
+				if (!ipahal_hw_stats_objs[i + 1][j].
+					get_offset) {
+					IPAHAL_ERR(
+					  "stat=%d get_offset null ver=%d\n",
+					  j, i+1);
+					WARN_ON(1);
+				}
+				if (!ipahal_hw_stats_objs[i + 1][j].
+				    parse_stats) {
+					IPAHAL_ERR(
+					  "stat=%d parse_stats null ver=%d\n",
+						j, i + 1);
+					WARN_ON(1);
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+int ipahal_stats_get_offset(enum ipahal_hw_stats_type type, void *params,
+	struct ipahal_stats_offset *out)
+{
+	if (type < 0 || type >= IPAHAL_HW_STATS_MAX) {
+		IPAHAL_ERR("Invalid type stat=%d\n", type);
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	if (!params || !out) {
+		IPAHAL_ERR("Null arg\n");
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	return ipahal_hw_stats_objs[ipahal_ctx->hw_type][type].get_offset(
+		params, out);
+}
+
+struct ipahal_stats_init_pyld *ipahal_stats_generate_init_pyld(
+	enum ipahal_hw_stats_type type, void *params, bool is_atomic_ctx)
+{
+	if (type < 0 || type >= IPAHAL_HW_STATS_MAX) {
+		IPAHAL_ERR("Invalid type stat=%d\n", type);
+		WARN_ON(1);
+		return NULL;
+	}
+
+	if (!params) {
+		IPAHAL_ERR("Null arg\n");
+		WARN_ON(1);
+		return NULL;
+	}
+
+	return ipahal_hw_stats_objs[ipahal_ctx->hw_type][type].
+		generate_init_pyld(params, is_atomic_ctx);
+}
+
+int ipahal_parse_stats(enum ipahal_hw_stats_type type, void *init_params,
+	void *raw_stats, void *parsed_stats)
+{
+	if (type < 0 || type >= IPAHAL_HW_STATS_MAX) {
+		IPAHAL_ERR("Invalid type stat=%d\n", type);
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	if (!raw_stats || !parsed_stats) {
+		IPAHAL_ERR("Null arg\n");
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	return ipahal_hw_stats_objs[ipahal_ctx->hw_type][type].parse_stats(
+		init_params, raw_stats, parsed_stats);
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.h
new file mode 100644
index 0000000..cbb1dc3
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.h
@@ -0,0 +1,248 @@
+/* Copyright (c) 2017, 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 _IPAHAL_HW_STATS_H_
+#define _IPAHAL_HW_STATS_H_
+
+#include <linux/ipa.h>
+
+#define IPAHAL_MAX_PIPES 32
+#define IPAHAL_MAX_RULE_ID_32 (1024 / 32) /* 10 bits of rule id */
+
+enum ipahal_hw_stats_type {
+	IPAHAL_HW_STATS_QUOTA,
+	IPAHAL_HW_STATS_TETHERING,
+	IPAHAL_HW_STATS_FNR,
+	IPAHAL_HW_STATS_DROP,
+	IPAHAL_HW_STATS_MAX
+};
+
+/*
+ * struct ipahal_stats_init_pyld - Statistics initialization payload
+ * @len: length of payload
+ * @data: actual payload data
+ */
+struct ipahal_stats_init_pyld {
+	u16 len;
+	u16 reserved;
+	u8 data[0];
+};
+
+/*
+ * struct ipahal_stats_offset - Statistics offset parameters
+ * @offset: offset of the statistic from beginning of stats table
+ * @size: size of the statistics
+ */
+struct ipahal_stats_offset {
+	u32 offset;
+	u16 size;
+};
+
+/*
+ * struct ipahal_stats_init_quota - Initializations parameters for quota
+ * @enabled_bitmask: bit mask of pipes to be monitored
+ */
+struct ipahal_stats_init_quota {
+	u32 enabled_bitmask;
+};
+
+/*
+ * struct ipahal_stats_get_offset_quota - Get offset parameters for quota
+ * @init: initialization parameters used in initialization of stats
+ */
+struct ipahal_stats_get_offset_quota {
+	struct ipahal_stats_init_quota init;
+};
+
+/*
+ * struct ipahal_stats_quota - Quota statistics
+ * @num_ipv4_bytes: IPv4 bytes
+ * @num_ipv6_bytes: IPv6 bytes
+ * @num_ipv4_pkts: IPv4 packets
+ * @num_ipv6_pkts: IPv6 packets
+ */
+struct ipahal_stats_quota {
+	u64 num_ipv4_bytes;
+	u64 num_ipv6_bytes;
+	u64 num_ipv4_pkts;
+	u64 num_ipv6_pkts;
+};
+
+/*
+ * struct ipahal_stats_quota_all - Quota statistics for all pipes
+ * @stats: array of statistics per pipe
+ */
+struct ipahal_stats_quota_all {
+	struct ipahal_stats_quota stats[IPAHAL_MAX_PIPES];
+};
+
+/*
+ * struct ipahal_stats_init_tethering - Initializations parameters for tethering
+ * @prod_bitmask: bit mask of producer pipes to be monitored
+ * @cons_bitmask: bit mask of consumer pipes to be monitored per producer
+ */
+struct ipahal_stats_init_tethering {
+	u32 prod_bitmask;
+	u32 cons_bitmask[IPAHAL_MAX_PIPES];
+};
+
+/*
+ * struct ipahal_stats_get_offset_tethering - Get offset parameters for
+ *	tethering
+ * @init: initialization parameters used in initialization of stats
+ */
+struct ipahal_stats_get_offset_tethering {
+	struct ipahal_stats_init_tethering init;
+};
+
+/*
+ * struct ipahal_stats_tethering - Tethering statistics
+ * @num_ipv4_bytes: IPv4 bytes
+ * @num_ipv6_bytes: IPv6 bytes
+ * @num_ipv4_pkts: IPv4 packets
+ * @num_ipv6_pkts: IPv6 packets
+ */
+struct ipahal_stats_tethering {
+	u64 num_ipv4_bytes;
+	u64 num_ipv6_bytes;
+	u64 num_ipv4_pkts;
+	u64 num_ipv6_pkts;
+};
+
+/*
+ * struct ipahal_stats_tethering_all - Tethering statistics for all pipes
+ * @stats: matrix of statistics per pair of pipes
+ */
+struct ipahal_stats_tethering_all {
+	struct ipahal_stats_tethering
+		stats[IPAHAL_MAX_PIPES][IPAHAL_MAX_PIPES];
+};
+
+/*
+ * struct ipahal_stats_init_flt_rt - Initializations parameters for flt_rt
+ * @rule_id_bitmask: array describes which rule ids to monitor.
+ *	rule_id bit is determined by:
+ *		index to the array => rule_id / 32
+ *		bit to enable => rule_id % 32
+ */
+struct ipahal_stats_init_flt_rt {
+	u32 rule_id_bitmask[IPAHAL_MAX_RULE_ID_32];
+};
+
+/*
+ * struct ipahal_stats_get_offset_flt_rt - Get offset parameters for flt_rt
+ * @init: initialization parameters used in initialization of stats
+ * @rule_id: rule_id to get the offset for
+ */
+struct ipahal_stats_get_offset_flt_rt {
+	struct ipahal_stats_init_flt_rt init;
+	u32 rule_id;
+};
+
+/*
+ * struct ipahal_stats_flt_rt - flt_rt statistics
+ * @num_packets: Total number of packets hit this rule
+ * @num_packets_hash: Total number of packets hit this rule in hash table
+ */
+struct ipahal_stats_flt_rt {
+	u32 num_packets;
+	u32 num_packets_hash;
+};
+
+/*
+ * struct ipahal_stats_init_drop - Initializations parameters for Drop
+ * @enabled_bitmask: bit mask of pipes to be monitored
+ */
+struct ipahal_stats_init_drop {
+	u32 enabled_bitmask;
+};
+
+/*
+ * struct ipahal_stats_get_offset_drop - Get offset parameters for Drop
+ * @init: initialization parameters used in initialization of stats
+ */
+struct ipahal_stats_get_offset_drop {
+	struct ipahal_stats_init_drop init;
+};
+
+/*
+ * struct ipahal_stats_drop - Packet Drop statistics
+ * @drop_packet_cnt: number of packets dropped
+ * @drop_byte_cnt: number of bytes dropped
+ */
+struct ipahal_stats_drop {
+	u32 drop_packet_cnt;
+	u32 drop_byte_cnt;
+};
+
+/*
+ * struct ipahal_stats_drop_all - Drop statistics for all pipes
+ * @stats: array of statistics per pipes
+ */
+struct ipahal_stats_drop_all {
+	struct ipahal_stats_drop stats[IPAHAL_MAX_PIPES];
+};
+
+/*
+ * ipahal_stats_generate_init_pyld - Generate the init payload for stats
+ * @type: type of stats
+ * @params: init_pyld parameters based of stats type
+ * @is_atomic_ctx: is calling context atomic ?
+ *
+ * This function will generate the initialization payload for a particular
+ * statistic in hardware. IPA driver is expected to use this payload to
+ * initialize the SRAM.
+ *
+ * Return: pointer to ipahal_stats_init_pyld on success or NULL on failure.
+ */
+struct ipahal_stats_init_pyld *ipahal_stats_generate_init_pyld(
+	enum ipahal_hw_stats_type type, void *params, bool is_atomic_ctx);
+
+/*
+ * ipahal_destroy_stats_init_pyld() - Destroy/Release bulk that was built
+ *  by the ipahal_stats_generate_init_pyld function.
+ */
+static inline void ipahal_destroy_stats_init_pyld(
+	struct ipahal_stats_init_pyld *pyld)
+{
+	kfree(pyld);
+}
+
+/*
+ * ipahal_stats_get_offset - Get the offset / size of payload for stats
+ * @type: type of stats
+ * @params: get_offset parameters based of stats type
+ * @out: out parameter for the offset and size.
+ *
+ * This function will return the offset of the counter from beginning of
+ * the table.IPA driver is expected to read this portion in SRAM and pass
+ * it to ipahal_parse_stats() to interprete the stats.
+ *
+ * Return: 0 on success and negative on failure
+ */
+int ipahal_stats_get_offset(enum ipahal_hw_stats_type type, void *params,
+	struct ipahal_stats_offset *out);
+
+/*
+ * ipahal_parse_stats - parse statistics
+ * @type: type of stats
+ * @init_params: init_pyld parameters used on init
+ * @raw_stats: stats read from IPA SRAM
+ * @parsed_stats: pointer to parsed stats based on type
+ *
+ * Return: 0 on success and negative on failure
+ */
+int ipahal_parse_stats(enum ipahal_hw_stats_type type, void *init_params,
+	void *raw_stats, void *parsed_stats);
+
+
+#endif /* _IPAHAL_HW_STATS_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats_i.h
new file mode 100644
index 0000000..3bb761d
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats_i.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2017, 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 _IPAHAL_HW_STATS_I_H_
+#define _IPAHAL_HW_STATS_I_H_
+
+#include "ipahal_hw_stats.h"
+
+int ipahal_hw_stats_init(enum ipa_hw_type ipa_hw_type);
+
+struct ipahal_stats_quota_hw {
+	u64 num_ipv4_bytes;
+	u64 num_ipv4_pkts:32;
+	u64 num_ipv6_pkts:32;
+	u64 num_ipv6_bytes;
+};
+
+struct ipahal_stats_tethering_hdr_hw {
+	u64 dst_mask:32;
+	u64 offset:32;
+};
+
+struct ipahal_stats_tethering_hw {
+	u64 num_ipv4_bytes;
+	u64 num_ipv4_pkts:32;
+	u64 num_ipv6_pkts:32;
+	u64 num_ipv6_bytes;
+};
+
+struct ipahal_stats_flt_rt_hdr_hw {
+	u64 en_mask:32;
+	u64 reserved:16;
+	u64 cnt_offset:16;
+};
+
+struct ipahal_stats_flt_rt_hw {
+	u64 num_packets_hash:32;
+	u64 num_packets:32;
+};
+
+struct ipahal_stats_drop_hw {
+	u64 drop_byte_cnt:40;
+	u64 drop_packet_cnt:24;
+};
+
+#endif /* _IPAHAL_HW_STATS_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index 1c4b287..5eb1aef 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -46,6 +46,9 @@
 			IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \
 	} while (0)
 
+#define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
+	(kzalloc((__size), ((__is_atomic_ctx) ? GFP_ATOMIC : GFP_KERNEL)))
+
 /*
  * struct ipahal_context - HAL global context data
  * @hw_type: IPA H/W type/version.
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 0dccb5b..dc71414 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -87,6 +87,24 @@
 	__stringify(IPA_DPS_SEQUENCER_FIRST),
 	__stringify(IPA_HPS_SEQUENCER_FIRST),
 	__stringify(IPA_CLKON_CFG),
+	__stringify(IPA_STAT_QUOTA_BASE_n),
+	__stringify(IPA_STAT_QUOTA_MASK_n),
+	__stringify(IPA_STAT_TETHERING_BASE_n),
+	__stringify(IPA_STAT_TETHERING_MASK_n),
+	__stringify(IPA_STAT_FILTER_IPV4_BASE),
+	__stringify(IPA_STAT_FILTER_IPV6_BASE),
+	__stringify(IPA_STAT_ROUTER_IPV4_BASE),
+	__stringify(IPA_STAT_ROUTER_IPV6_BASE),
+	__stringify(IPA_STAT_FILTER_IPV4_START_ID),
+	__stringify(IPA_STAT_FILTER_IPV6_START_ID),
+	__stringify(IPA_STAT_ROUTER_IPV4_START_ID),
+	__stringify(IPA_STAT_ROUTER_IPV6_START_ID),
+	__stringify(IPA_STAT_FILTER_IPV4_END_ID),
+	__stringify(IPA_STAT_FILTER_IPV6_END_ID),
+	__stringify(IPA_STAT_ROUTER_IPV4_END_ID),
+	__stringify(IPA_STAT_ROUTER_IPV6_END_ID),
+	__stringify(IPA_STAT_DROP_CNT_BASE_n),
+	__stringify(IPA_STAT_DROP_CNT_MASK_n),
 };
 
 static void ipareg_construct_dummy(enum ipahal_reg_name reg,
@@ -1510,6 +1528,60 @@
 		ipareg_construct_endp_init_conn_track_n,
 		ipareg_parse_dummy,
 		0x00000850, 0x70},
+	[IPA_HW_v4_0][IPA_STAT_QUOTA_BASE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000700, 0x4 },
+	[IPA_HW_v4_0][IPA_STAT_QUOTA_MASK_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000708, 0x4 },
+	[IPA_HW_v4_0][IPA_STAT_TETHERING_BASE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000710, 0x4 },
+	[IPA_HW_v4_0][IPA_STAT_TETHERING_MASK_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000718, 0x4 },
+	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV4_BASE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000720, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV6_BASE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000724, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV4_BASE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000728, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV6_BASE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000072C, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV4_START_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000730, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV6_START_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000734, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV4_START_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000738, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV6_START_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000073C, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV4_END_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000740, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV6_END_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000744, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV4_END_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000748, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV6_END_ID] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000074C, 0x0 },
+	[IPA_HW_v4_0][IPA_STAT_DROP_CNT_BASE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000750, 0x4 },
+	[IPA_HW_v4_0][IPA_STAT_DROP_CNT_MASK_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000758, 0x4 },
 };
 
 /*
@@ -1853,6 +1925,11 @@
 		IPA_AGGR_FORCE_CLOSE_AGGR_FORCE_CLOSE_PIPE_BITMAP_BMSK_V4_0;
 	}
 
+	if (ep_idx > (sizeof(valmask->val) * 8 - 1)) {
+		IPAHAL_ERR("too big ep_idx %d\n", ep_idx);
+		ipa_assert();
+		return;
+	}
 	IPA_SETFIELD_IN_REG(valmask->val, 1 << ep_idx, shft, bmsk);
 	valmask->mask = bmsk << shft;
 }
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index 3df49ce..a2864cd 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -90,6 +90,24 @@
 	IPA_DPS_SEQUENCER_FIRST,
 	IPA_HPS_SEQUENCER_FIRST,
 	IPA_CLKON_CFG,
+	IPA_STAT_QUOTA_BASE_n,
+	IPA_STAT_QUOTA_MASK_n,
+	IPA_STAT_TETHERING_BASE_n,
+	IPA_STAT_TETHERING_MASK_n,
+	IPA_STAT_FILTER_IPV4_BASE,
+	IPA_STAT_FILTER_IPV6_BASE,
+	IPA_STAT_ROUTER_IPV4_BASE,
+	IPA_STAT_ROUTER_IPV6_BASE,
+	IPA_STAT_FILTER_IPV4_START_ID,
+	IPA_STAT_FILTER_IPV6_START_ID,
+	IPA_STAT_ROUTER_IPV4_START_ID,
+	IPA_STAT_ROUTER_IPV6_START_ID,
+	IPA_STAT_FILTER_IPV4_END_ID,
+	IPA_STAT_FILTER_IPV6_END_ID,
+	IPA_STAT_ROUTER_IPV4_END_ID,
+	IPA_STAT_ROUTER_IPV6_END_ID,
+	IPA_STAT_DROP_CNT_BASE_n,
+	IPA_STAT_DROP_CNT_MASK_n,
 	IPA_REG_MAX,
 };
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index b19c71a..b119a69 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -702,6 +702,11 @@
 	/* send ipa_fltr_installed_notif_req_msg_v01 to Q6*/
 	req->source_pipe_index =
 		ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_PROD);
+	if (req->source_pipe_index == IPA_EP_NOT_ALLOCATED) {
+		IPAWANERR("ep mapping failed\n");
+		retval = -EFAULT;
+	}
+
 	req->install_status = QMI_RESULT_SUCCESS_V01;
 	req->rule_id_valid = 1;
 	req->rule_id_len = rmnet_ipa3_ctx->num_q6_rules;
@@ -1927,7 +1932,9 @@
 	if (ret < 0)
 		IPAWANERR("Error deleting resource %d, ret=%d\n",
 			IPA_RM_RESOURCE_Q6_PROD, ret);
-	destroy_workqueue(rmnet_ipa3_ctx->rm_q6_wq);
+
+	if (rmnet_ipa3_ctx->rm_q6_wq)
+		destroy_workqueue(rmnet_ipa3_ctx->rm_q6_wq);
 }
 
 static void ipa3_wake_tx_queue(struct work_struct *work)
@@ -2267,7 +2274,10 @@
 		IPAWANERR("Error deleting resource %d, ret=%d\n",
 		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
 create_rsrc_err:
-	ipa3_q6_deinitialize_rm();
+
+	if (!atomic_read(&rmnet_ipa3_ctx->is_ssr))
+		ipa3_q6_deinitialize_rm();
+
 q6_init_err:
 	free_netdev(dev);
 	rmnet_ipa3_ctx->wwan_priv = NULL;
diff --git a/drivers/platform/msm/ipa/test/Makefile b/drivers/platform/msm/ipa/test/Makefile
index c20fd2b..af46bf2 100644
--- a/drivers/platform/msm/ipa/test/Makefile
+++ b/drivers/platform/msm/ipa/test/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
-ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o ipa_test_dma.o
+ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o ipa_test_dma.o ipa_test_hw_stats.o
diff --git a/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c b/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c
new file mode 100644
index 0000000..d37920e
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c
@@ -0,0 +1,330 @@
+/* Copyright (c) 2017, 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 "ipa_ut_framework.h"
+#include <linux/netdevice.h>
+
+struct ipa_test_hw_stats_ctx {
+	u32 odu_prod_hdl;
+	u32 odu_cons_hdl;
+	u32 rt4_usb;
+	u32 rt6_usb;
+	u32 rt4_odu_cons;
+	u32 rt6_odu_cons;
+	atomic_t odu_pending;
+};
+
+static struct ipa_test_hw_stats_ctx *ctx;
+
+static int ipa_test_hw_stats_suite_setup(void **ppriv)
+{
+	IPA_UT_DBG("Start Setup\n");
+
+	if (!ctx)
+		ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+
+	return 0;
+}
+
+static int ipa_test_hw_stats_suite_teardown(void *priv)
+{
+	IPA_UT_DBG("Start Teardown\n");
+
+	return 0;
+}
+
+static void odu_prod_notify(void *priv, enum ipa_dp_evt_type evt,
+	unsigned long data)
+{
+	struct sk_buff *skb = (struct sk_buff *)data;
+
+	switch (evt) {
+	case IPA_RECEIVE:
+		dev_kfree_skb_any(skb);
+		break;
+	case IPA_WRITE_DONE:
+		atomic_dec(&ctx->odu_pending);
+		dev_kfree_skb_any(skb);
+		break;
+	default:
+		IPA_UT_ERR("unexpected evt %d\n", evt);
+	}
+}
+static void odu_cons_notify(void *priv, enum ipa_dp_evt_type evt,
+	unsigned long data)
+{
+	struct sk_buff *skb = (struct sk_buff *)data;
+	int ret;
+
+	switch (evt) {
+	case IPA_RECEIVE:
+		if (atomic_read(&ctx->odu_pending) >= 64)
+			msleep(20);
+		atomic_inc(&ctx->odu_pending);
+		skb_put(skb, 100);
+		ret = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, NULL);
+		while (ret) {
+			msleep(100);
+			ret = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, NULL);
+		}
+		break;
+	case IPA_WRITE_DONE:
+		dev_kfree_skb_any(skb);
+		break;
+	default:
+		IPA_UT_ERR("unexpected evt %d\n", evt);
+	}
+}
+
+static int ipa_test_hw_stats_configure(void *priv)
+{
+	struct ipa_sys_connect_params odu_prod_params;
+	struct ipa_sys_connect_params odu_emb_cons_params;
+	int res;
+
+	/* first connect all additional pipe */
+	memset(&odu_prod_params, 0, sizeof(odu_prod_params));
+	memset(&odu_emb_cons_params, 0, sizeof(odu_emb_cons_params));
+
+	odu_prod_params.client = IPA_CLIENT_ODU_PROD;
+	odu_prod_params.desc_fifo_sz = 0x1000;
+	odu_prod_params.priv = NULL;
+	odu_prod_params.notify = odu_prod_notify;
+	res = ipa_setup_sys_pipe(&odu_prod_params,
+		&ctx->odu_prod_hdl);
+	if (res) {
+		IPA_UT_ERR("fail to setup sys pipe ODU_PROD %d\n", res);
+		return res;
+	}
+
+	odu_emb_cons_params.client = IPA_CLIENT_ODU_EMB_CONS;
+	odu_emb_cons_params.desc_fifo_sz = 0x1000;
+	odu_emb_cons_params.priv = NULL;
+	odu_emb_cons_params.notify = odu_cons_notify;
+	res = ipa_setup_sys_pipe(&odu_emb_cons_params,
+		&ctx->odu_cons_hdl);
+	if (res) {
+		IPA_UT_ERR("fail to setup sys pipe ODU_EMB_CONS %d\n", res);
+		ipa_teardown_sys_pipe(ctx->odu_prod_hdl);
+		return res;
+	}
+
+	IPA_UT_INFO("Configured. Please connect USB RNDIS now\n");
+
+	return 0;
+}
+
+static int ipa_test_hw_stats_add_FnR(void *priv)
+{
+	struct ipa_ioc_add_rt_rule *rt_rule;
+	struct ipa_ioc_add_flt_rule *flt_rule;
+	struct ipa_ioc_get_rt_tbl rt_lookup;
+	int ret;
+
+	rt_rule = kzalloc(sizeof(*rt_rule) + 1 * sizeof(struct ipa_rt_rule_add),
+		GFP_KERNEL);
+	if (!rt_rule) {
+		IPA_UT_DBG("no mem\n");
+		return -ENOMEM;
+	}
+
+	flt_rule = kzalloc(sizeof(*flt_rule) +
+		1 * sizeof(struct ipa_flt_rule_add), GFP_KERNEL);
+	if (!flt_rule) {
+		IPA_UT_DBG("no mem\n");
+		ret = -ENOMEM;
+		goto free_rt;
+	}
+
+	rt_rule->commit = 1;
+	rt_rule->ip = IPA_IP_v4;
+	rt_lookup.ip = rt_rule->ip;
+	strlcpy(rt_rule->rt_tbl_name, "V4_RT_TO_USB_CONS",
+		IPA_RESOURCE_NAME_MAX);
+	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
+	rt_rule->num_rules = 1;
+	rt_rule->rules[0].rule.dst = IPA_CLIENT_USB_CONS;
+	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	rt_rule->rules[0].rule.attrib.dst_port = 5002;
+	rt_rule->rules[0].rule.hashable = true;
+	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	if (ipa_get_rt_tbl(&rt_lookup)) {
+		IPA_UT_ERR("failed to query V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	ctx->rt4_usb = rt_lookup.hdl;
+
+	memset(rt_rule, 0, sizeof(*rt_rule));
+	rt_rule->commit = 1;
+	rt_rule->ip = IPA_IP_v6;
+	rt_lookup.ip = rt_rule->ip;
+	strlcpy(rt_rule->rt_tbl_name, "V6_RT_TO_USB_CONS",
+		IPA_RESOURCE_NAME_MAX);
+	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
+	rt_rule->num_rules = 1;
+	rt_rule->rules[0].rule.dst = IPA_CLIENT_USB_CONS;
+	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	rt_rule->rules[0].rule.attrib.dst_port = 5002;
+	rt_rule->rules[0].rule.hashable = true;
+	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	if (ipa_get_rt_tbl(&rt_lookup)) {
+		IPA_UT_ERR("failed to query V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	ctx->rt6_usb = rt_lookup.hdl;
+
+	memset(rt_rule, 0, sizeof(*rt_rule));
+	rt_rule->commit = 1;
+	rt_rule->ip = IPA_IP_v4;
+	rt_lookup.ip = rt_rule->ip;
+	strlcpy(rt_rule->rt_tbl_name, "V4_RT_TO_ODU_CONS",
+		IPA_RESOURCE_NAME_MAX);
+	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
+	rt_rule->num_rules = 1;
+	rt_rule->rules[0].rule.dst = IPA_CLIENT_ODU_EMB_CONS;
+	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	rt_rule->rules[0].rule.attrib.dst_port = 5002;
+	rt_rule->rules[0].rule.hashable = true;
+	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	if (ipa_get_rt_tbl(&rt_lookup)) {
+		IPA_UT_ERR("failed to query V4 rules\n");
+		return -EFAULT;
+	}
+	ctx->rt4_odu_cons = rt_lookup.hdl;
+
+	memset(rt_rule, 0, sizeof(*rt_rule));
+	rt_rule->commit = 1;
+	rt_rule->ip = IPA_IP_v6;
+	rt_lookup.ip = rt_rule->ip;
+	strlcpy(rt_rule->rt_tbl_name, "V6_RT_TO_ODU_CONS",
+		IPA_RESOURCE_NAME_MAX);
+	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
+	rt_rule->num_rules = 1;
+	rt_rule->rules[0].rule.dst = IPA_CLIENT_ODU_EMB_CONS;
+	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	rt_rule->rules[0].rule.attrib.dst_port = 5002;
+	rt_rule->rules[0].rule.hashable = true;
+	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	if (ipa_get_rt_tbl(&rt_lookup)) {
+		IPA_UT_ERR("failed to query V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+	ctx->rt6_odu_cons = rt_lookup.hdl;
+
+	flt_rule->commit = 1;
+	flt_rule->ip = IPA_IP_v4;
+	flt_rule->ep = IPA_CLIENT_USB_PROD;
+	flt_rule->num_rules = 1;
+	flt_rule->rules[0].at_rear = 1;
+	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
+	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	flt_rule->rules[0].rule.attrib.dst_port = 5002;
+	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt4_odu_cons;
+	flt_rule->rules[0].rule.hashable = 1;
+	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+
+	memset(flt_rule, 0, sizeof(*flt_rule));
+	flt_rule->commit = 1;
+	flt_rule->ip = IPA_IP_v6;
+	flt_rule->ep = IPA_CLIENT_USB_PROD;
+	flt_rule->num_rules = 1;
+	flt_rule->rules[0].at_rear = 1;
+	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
+	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	flt_rule->rules[0].rule.attrib.dst_port = 5002;
+	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt6_odu_cons;
+	flt_rule->rules[0].rule.hashable = 1;
+	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V6 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+
+	memset(flt_rule, 0, sizeof(*flt_rule));
+	flt_rule->commit = 1;
+	flt_rule->ip = IPA_IP_v4;
+	flt_rule->ep = IPA_CLIENT_ODU_PROD;
+	flt_rule->num_rules = 1;
+	flt_rule->rules[0].at_rear = 1;
+	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
+	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	flt_rule->rules[0].rule.attrib.dst_port = 5002;
+	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt4_usb;
+	flt_rule->rules[0].rule.hashable = 1;
+	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V4 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+
+	memset(flt_rule, 0, sizeof(*flt_rule));
+	flt_rule->commit = 1;
+	flt_rule->ip = IPA_IP_v6;
+	flt_rule->ep = IPA_CLIENT_ODU_PROD;
+	flt_rule->num_rules = 1;
+	flt_rule->rules[0].at_rear = 1;
+	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
+	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
+	flt_rule->rules[0].rule.attrib.dst_port = 5002;
+	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt6_usb;
+	flt_rule->rules[0].rule.hashable = 1;
+	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
+		IPA_UT_ERR("failed to install V6 rules\n");
+		ret = -EFAULT;
+		goto free_flt;
+	}
+
+	IPA_UT_INFO(
+		"Rules added. Please start data transfer on ports 5001/5002\n");
+	ret = 0;
+free_flt:
+	kfree(flt_rule);
+free_rt:
+	kfree(rt_rule);
+	return ret;
+
+}
+
+/* Suite definition block */
+IPA_UT_DEFINE_SUITE_START(hw_stats, "HW stats test",
+	ipa_test_hw_stats_suite_setup, ipa_test_hw_stats_suite_teardown)
+{
+	IPA_UT_ADD_TEST(configure, "Configure the setup",
+		ipa_test_hw_stats_configure, false, IPA_HW_v4_0, IPA_HW_MAX),
+
+	IPA_UT_ADD_TEST(add_rules, "Add FLT and RT rules",
+		ipa_test_hw_stats_add_FnR, false, IPA_HW_v4_0, IPA_HW_MAX),
+
+} IPA_UT_DEFINE_SUITE_END(hw_stats);
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
index 4a9d3b0..823edcf 100644
--- a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
+++ b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
@@ -23,6 +23,7 @@
 IPA_UT_DECLARE_SUITE(mhi);
 IPA_UT_DECLARE_SUITE(dma);
 IPA_UT_DECLARE_SUITE(example);
+IPA_UT_DECLARE_SUITE(hw_stats);
 
 
 /**
@@ -34,6 +35,7 @@
 	IPA_UT_REGISTER_SUITE(mhi),
 	IPA_UT_REGISTER_SUITE(dma),
 	IPA_UT_REGISTER_SUITE(example),
+	IPA_UT_REGISTER_SUITE(hw_stats),
 } IPA_UT_DEFINE_ALL_SUITES_END;
 
 #endif /* _IPA_UT_SUITE_LIST_H_ */
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index 7c77280..2818d56 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -293,20 +293,31 @@
 
 static int geni_se_select_gsi_mode(void __iomem *base)
 {
-	unsigned int io_mode = 0;
 	unsigned int geni_dma_mode = 0;
 	unsigned int gsi_event_en = 0;
+	unsigned int common_geni_m_irq_en = 0;
+	unsigned int common_geni_s_irq_en = 0;
 
+	common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
+	common_geni_s_irq_en = geni_read_reg(base, SE_GENI_S_IRQ_EN);
+	common_geni_m_irq_en &=
+			~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
+			M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+	common_geni_s_irq_en &= ~S_CMD_DONE_EN;
 	geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
 	gsi_event_en = geni_read_reg(base, SE_GSI_EVENT_EN);
-	io_mode = geni_read_reg(base, SE_IRQ_EN);
 
 	geni_dma_mode |= GENI_DMA_MODE_EN;
-	io_mode &= ~(DMA_TX_IRQ_EN | DMA_RX_IRQ_EN);
 	gsi_event_en |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN |
 				GENI_M_EVENT_EN | GENI_S_EVENT_EN);
 
-	geni_write_reg(io_mode, base, SE_IRQ_EN);
+	geni_write_reg(0, base, SE_IRQ_EN);
+	geni_write_reg(common_geni_s_irq_en, base, SE_GENI_S_IRQ_EN);
+	geni_write_reg(common_geni_m_irq_en, base, SE_GENI_M_IRQ_EN);
+	geni_write_reg(0xFFFFFFFF, base, SE_GENI_M_IRQ_CLEAR);
+	geni_write_reg(0xFFFFFFFF, base, SE_GENI_S_IRQ_CLEAR);
+	geni_write_reg(0xFFFFFFFF, base, SE_DMA_TX_IRQ_CLR);
+	geni_write_reg(0xFFFFFFFF, base, SE_DMA_RX_IRQ_CLR);
 	geni_write_reg(geni_dma_mode, base, SE_GENI_DMA_MODE_EN);
 	geni_write_reg(gsi_event_en, base, SE_GSI_EVENT_EN);
 	return 0;
@@ -691,7 +702,7 @@
 			     struct se_geni_rsc *rsc)
 {
 	unsigned long flags;
-	struct se_geni_rsc *tmp;
+	struct se_geni_rsc *tmp = NULL;
 	struct list_head *ins_list_head;
 	bool bus_bw_update = false;
 	int ret = 0;
@@ -709,7 +720,7 @@
 	list_add(&rsc->ib_list, ins_list_head);
 	/* Currently inserted node has greater average BW value */
 	if (ins_list_head == &geni_se_dev->ib_list_head)
-		geni_se_dev->cur_ib = tmp->ib;
+		geni_se_dev->cur_ib = rsc->ib;
 
 	bus_bw_update = geni_se_check_bus_bw(geni_se_dev);
 	spin_unlock_irqrestore(&geni_se_dev->ab_ib_lock, flags);
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c
index 204142b..a23f069 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.c
+++ b/drivers/platform/msm/seemp_core/seemp_logk.c
@@ -30,6 +30,7 @@
 #define YEAR_BASE 1900
 
 #define EL2_SCM_ID 0x02001902
+#define KP_EL2_REPORT_REVISION 0x01000101
 
 static struct seemp_logk_dev *slogk_dev;
 
@@ -610,6 +611,9 @@
 		/ sizeof(struct el2_report_data_t);
 	header = (struct el2_report_header_t *) el2_shared_mem;
 
+	if (header->report_version < KP_EL2_REPORT_REVISION)
+		return -EINVAL;
+
 	while (!kthread_should_stop()) {
 		for (i = 1; i < num_entries + 1; i++) {
 			struct el2_report_data_t *report;
@@ -628,7 +632,8 @@
 					|| report->sequence_number >
 						last_sequence_number)) {
 				seemp_logk_rtic(report->report_type,
-					report->actor,
+					((struct task_struct *) report->actor)
+						->pid,
 					/* leave this empty until
 					 * asset id is provided
 					 */
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 62e0978..92321ad 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -3095,84 +3095,6 @@
 	return 0;
 }
 
-static ssize_t
-usb_bam_show_inactivity_timer(struct device *dev, struct device_attribute *attr,
-		    char *buf)
-{
-	char *buff = buf;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(bam_enable_strings); i++) {
-		buff += snprintf(buff, PAGE_SIZE, "%s: %dms\n",
-					bam_enable_strings[i],
-					msm_usb_bam[i].inactivity_timer_ms);
-	}
-
-	return buff - buf;
-}
-
-static ssize_t usb_bam_store_inactivity_timer(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buff, size_t count)
-{
-	char buf[USB_BAM_MAX_STR_LEN];
-	char *trimmed_buf, *bam_str, *bam_name, *timer;
-	int timer_d;
-	int bam, ret;
-
-	if (strnstr(buff, "help", USB_BAM_MAX_STR_LEN)) {
-		pr_info("Usage: <bam_name> <ms>,<bam_name> <ms>,...\n");
-		pr_info("\tbam_name: [%s, %s, %s]\n",
-			bam_enable_strings[DWC3_CTRL],
-			bam_enable_strings[CI_CTRL],
-			bam_enable_strings[HSIC_CTRL]);
-		pr_info("\tms: time in ms. Use 0 to disable timer\n");
-		return count;
-	}
-
-	strlcpy(buf, buff, sizeof(buf));
-	trimmed_buf = strim(buf);
-
-	while (trimmed_buf) {
-		bam_str = strsep(&trimmed_buf, ",");
-		if (bam_str) {
-			bam_name = strsep(&bam_str, " ");
-			bam = get_bam_type_from_core_name(bam_name);
-			if (bam < 0 || bam >= MAX_BAMS) {
-				log_event_err("%s: Invalid bam, type=%d ,name=%s\n",
-					__func__, bam, bam_name);
-				return -EINVAL;
-			}
-
-			timer = strsep(&bam_str, " ");
-
-			if (!timer)
-				continue;
-
-			ret = kstrtoint(timer, 0, &timer_d);
-			if (ret) {
-				log_event_err("%s: err:%d with value:(%d)\n",
-						__func__, ret, timer_d);
-				return ret;
-			}
-
-			/* Apply new timer setting if bam has running pipes */
-			if (msm_usb_bam[bam].inactivity_timer_ms != timer_d) {
-				msm_usb_bam[bam].inactivity_timer_ms = timer_d;
-				if (msm_usb_bam[bam].pipes_enabled_per_bam > 0
-						&& !info[bam].in_lpm)
-					usb_bam_set_inactivity_timer(bam);
-			}
-		}
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(inactivity_timer, 0600,
-		   usb_bam_show_inactivity_timer,
-		   usb_bam_store_inactivity_timer);
-
 static int usb_bam_panic_notifier(struct notifier_block *this,
 		unsigned long event, void *ptr)
 {
@@ -3221,12 +3143,6 @@
 
 	dev_dbg(&pdev->dev, "usb_bam_probe\n");
 
-	ret = device_create_file(&pdev->dev, &dev_attr_inactivity_timer);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to create fs node\n");
-		return ret;
-	}
-
 	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!io_res) {
 		dev_err(&pdev->dev, "missing BAM memory resource\n");
diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile
index bc19b24..6cc83ab 100644
--- a/drivers/power/supply/qcom/Makefile
+++ b/drivers/power/supply/qcom/Makefile
@@ -2,6 +2,6 @@
 obj-$(CONFIG_SMB135X_CHARGER)   += smb135x-charger.o pmic-voter.o
 obj-$(CONFIG_SMB1355_SLAVE_CHARGER)   += smb1355-charger.o pmic-voter.o
 obj-$(CONFIG_SMB1351_USB_CHARGER) += smb1351-charger.o pmic-voter.o battery.o
-obj-$(CONFIG_QPNP_SMB2)		+= qpnp-smb2.o smb-lib.o pmic-voter.o storm-watch.o battery.o
+obj-$(CONFIG_QPNP_SMB2)		+= step-chg-jeita.o battery.o qpnp-smb2.o smb-lib.o pmic-voter.o storm-watch.o
 obj-$(CONFIG_SMB138X_CHARGER)	+= smb138x-charger.o smb-lib.o pmic-voter.o storm-watch.o battery.o
 obj-$(CONFIG_QPNP_QNOVO)	+= qpnp-qnovo.o battery.o
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 486e8c3..7f6d346 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -1082,6 +1082,8 @@
 		goto unreg_notifier;
 	}
 
+	chip->taper_pct = 100;
+
 	the_chip = chip;
 
 	return 0;
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index cdd09dd..dd5f78f 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -67,6 +67,7 @@
 #define MAX_LINE_LENGTH			(ADDR_LEN + (ITEMS_PER_LINE *	\
 					CHARS_PER_ITEM) + 1)		\
 
+#define NUM_PARTITIONS			3
 #define FG_SRAM_ADDRESS_MAX		255
 #define FG_SRAM_LEN			504
 #define PROFILE_LEN			224
@@ -192,6 +193,18 @@
 		int val);
 };
 
+struct fg_dma_address {
+	/* Starting word address of the partition */
+	u16 partition_start;
+	/* Last word address of the partition */
+	u16 partition_end;
+	/*
+	 * Byte offset in the FG_DMA peripheral that maps to the partition_start
+	 * in SRAM
+	 */
+	u16 spmi_addr_base;
+};
+
 enum fg_alg_flag_id {
 	ALG_FLAG_SOC_LT_OTG_MIN = 0,
 	ALG_FLAG_SOC_LT_RECHARGE,
@@ -265,6 +278,7 @@
 	int	slope_limit_temp;
 	int	esr_pulse_thresh_ma;
 	int	esr_meas_curr_ma;
+	int	bmd_en_delay_ms;
 	int	jeita_thresholds[NUM_JEITA_LEVELS];
 	int	ki_coeff_soc[KI_COEFF_SOC_LEVELS];
 	int	ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS];
@@ -360,12 +374,12 @@
 	struct power_supply	*parallel_psy;
 	struct iio_channel	*batt_id_chan;
 	struct iio_channel	*die_temp_chan;
-	struct fg_memif		*sram;
 	struct fg_irq_info	*irqs;
 	struct votable		*awake_votable;
 	struct votable		*delta_bsoc_irq_en_votable;
 	struct votable		*batt_miss_irq_en_votable;
 	struct fg_sram_param	*sp;
+	struct fg_dma_address	*addr_map;
 	struct fg_alg_flag	*alg_flags;
 	int			*debug_mask;
 	char			batt_profile[PROFILE_LEN];
@@ -409,8 +423,10 @@
 	bool			esr_flt_cold_temp_en;
 	bool			slope_limit_en;
 	bool			use_ima_single_mode;
+	bool			use_dma;
 	struct completion	soc_update;
 	struct completion	soc_ready;
+	struct completion	mem_grant;
 	struct delayed_work	profile_load_work;
 	struct work_struct	status_change_work;
 	struct work_struct	cycle_count_work;
@@ -459,10 +475,15 @@
 			u8 offset, u8 *val, int len);
 extern int fg_interleaved_mem_write(struct fg_chip *chip, u16 address,
 			u8 offset, u8 *val, int len, bool atomic_access);
+extern int fg_direct_mem_read(struct fg_chip *chip, u16 address,
+			u8 offset, u8 *val, int len);
+extern int fg_direct_mem_write(struct fg_chip *chip, u16 address,
+			u8 offset, u8 *val, int len, bool atomic_access);
 extern int fg_read(struct fg_chip *chip, int addr, u8 *val, int len);
 extern int fg_write(struct fg_chip *chip, int addr, u8 *val, int len);
 extern int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val);
 extern int fg_ima_init(struct fg_chip *chip);
+extern int fg_dma_init(struct fg_chip *chip);
 extern int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts);
 extern int fg_clear_dma_errors_if_any(struct fg_chip *chip);
 extern int fg_debugfs_create(struct fg_chip *chip);
diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c
index 8a949bf..0abc9df 100644
--- a/drivers/power/supply/qcom/fg-memif.c
+++ b/drivers/power/supply/qcom/fg-memif.c
@@ -746,6 +746,257 @@
 	return rc;
 }
 
+#define MEM_GRANT_WAIT_MS	200
+static int fg_direct_mem_request(struct fg_chip *chip, bool request)
+{
+	int rc, ret;
+	u8 val, mask;
+	bool tried_again = false;
+
+	if (request)
+		reinit_completion(&chip->mem_grant);
+
+	mask = MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT;
+	val = request ? MEM_ACCESS_REQ_BIT : 0;
+	rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), mask, val);
+	if (rc < 0) {
+		pr_err("failed to configure mem_if_mem_intf_cfg rc=%d\n", rc);
+		return rc;
+	}
+
+	mask = MEM_ARB_LO_LATENCY_EN_BIT | MEM_ARB_REQ_BIT;
+	val = request ? mask : 0;
+	rc = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip), mask, val);
+	if (rc < 0) {
+		pr_err("failed to configure mem_if_mem_arb_cfg rc:%d\n", rc);
+		return rc;
+	}
+
+	if (request)
+		pr_debug("requesting access\n");
+	else
+		pr_debug("releasing access\n");
+
+	if (!request)
+		return 0;
+
+wait:
+	ret = wait_for_completion_interruptible_timeout(
+		&chip->mem_grant, msecs_to_jiffies(MEM_GRANT_WAIT_MS));
+	/* If we were interrupted wait again one more time. */
+	if (ret <= 0) {
+		if ((ret == -ERESTARTSYS || ret == 0) && !tried_again) {
+			pr_debug("trying again, ret=%d\n", ret);
+			tried_again = true;
+			goto wait;
+		} else {
+			pr_err("wait for mem_grant timed out ret=%d\n",
+				ret);
+		}
+	}
+
+	if (ret <= 0) {
+		val = 0;
+		mask = MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT;
+		rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), mask,
+					val);
+		if (rc < 0) {
+			pr_err("failed to configure mem_if_mem_intf_cfg rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		mask = MEM_ARB_LO_LATENCY_EN_BIT | MEM_ARB_REQ_BIT;
+		rc = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip), mask,
+					val);
+		if (rc < 0) {
+			pr_err("failed to configure mem_if_mem_arb_cfg rc:%d\n",
+				rc);
+			return rc;
+		}
+
+		return -ETIMEDOUT;
+	}
+
+	return rc;
+}
+
+static int fg_get_dma_address(struct fg_chip *chip, u16 sram_addr, u8 offset,
+				u16 *addr)
+{
+	int i;
+	u16 start_sram_addr, end_sram_addr;
+
+	for (i = 0; i < NUM_PARTITIONS; i++) {
+		start_sram_addr = chip->addr_map[i].partition_start;
+		end_sram_addr = chip->addr_map[i].partition_end;
+		if (sram_addr >= start_sram_addr &&
+			sram_addr <= end_sram_addr) {
+			*addr = chip->addr_map[i].spmi_addr_base + offset +
+					(sram_addr - start_sram_addr) *
+						BYTES_PER_SRAM_WORD;
+			return 0;
+		}
+	}
+
+	pr_err("Couldn't find address for %d from address map\n", sram_addr);
+	return -ENXIO;
+}
+
+static int fg_get_partition_count(struct fg_chip *chip, u16 sram_addr, int len,
+				int *count)
+{
+	int i, num = 0;
+	u16 end_addr, last_addr = 0;
+
+	end_addr = sram_addr + len / BYTES_PER_SRAM_WORD;
+	if (!(len % BYTES_PER_SRAM_WORD))
+		end_addr -= 1;
+
+	if (sram_addr == end_addr) {
+		*count = 1;
+		return 0;
+	}
+
+	for (i = 0; i < NUM_PARTITIONS; i++) {
+		pr_debug("address: %d last_addr: %d\n", sram_addr, last_addr);
+		if (sram_addr >= chip->addr_map[i].partition_start
+			&& sram_addr <= chip->addr_map[i].partition_end
+			&& last_addr < end_addr) {
+			num++;
+			last_addr = chip->addr_map[i].partition_end;
+			sram_addr = chip->addr_map[i+1].partition_start;
+		}
+	}
+
+	if (num > 0) {
+		*count = num;
+		return 0;
+	}
+
+	pr_err("Couldn't find number of partitions for address %d\n",
+		sram_addr);
+	return -ENXIO;
+}
+
+static int fg_get_partition_avail_bytes(struct fg_chip *chip, u16 sram_addr,
+					int len, int *rem_len)
+{
+	int i, part_len = 0, temp;
+	u16 end_addr;
+
+	for (i = 0; i < NUM_PARTITIONS; i++) {
+		if (sram_addr >= chip->addr_map[i].partition_start
+			&& sram_addr <= chip->addr_map[i].partition_end) {
+			part_len = (chip->addr_map[i].partition_end -
+					chip->addr_map[i].partition_start + 1);
+			part_len *= BYTES_PER_SRAM_WORD;
+			end_addr = chip->addr_map[i].partition_end;
+			break;
+		}
+	}
+
+	if (part_len <= 0) {
+		pr_err("Bad address? total_len=%d\n", part_len);
+		return -ENXIO;
+	}
+
+	temp = (end_addr - sram_addr + 1) * BYTES_PER_SRAM_WORD;
+	if (temp > part_len || !temp) {
+		pr_err("Bad length=%d\n", temp);
+		return -ENXIO;
+	}
+
+	*rem_len = temp;
+	pr_debug("address %d len %d rem_len %d\n", sram_addr, len, *rem_len);
+	return 0;
+}
+
+static int __fg_direct_mem_rw(struct fg_chip *chip, u16 sram_addr, u8 offset,
+				u8 *val, int len, bool access)
+{
+	int rc, ret, num_partitions, num_bytes = 0;
+	u16 addr;
+	u8 *ptr = val;
+	char *temp_str;
+
+	if (offset > 3) {
+		pr_err("offset too large %d\n", offset);
+		return -EINVAL;
+	}
+
+	rc = fg_get_partition_count(chip, sram_addr, len, &num_partitions);
+	if (rc < 0)
+		return rc;
+
+	pr_debug("number of partitions: %d\n", num_partitions);
+
+	rc = fg_direct_mem_request(chip, true);
+	if (rc < 0) {
+		pr_err("Error in requesting direct_mem access rc=%d\n", rc);
+		return rc;
+	}
+
+	while (num_partitions-- && len) {
+		rc = fg_get_dma_address(chip, sram_addr, offset, &addr);
+		if (rc < 0) {
+			pr_err("Incorrect address %d/offset %d\n", sram_addr,
+				offset);
+			break;
+		}
+
+		rc = fg_get_partition_avail_bytes(chip, sram_addr + offset, len,
+						&num_bytes);
+		if (rc < 0)
+			break;
+
+		if (num_bytes > len)
+			num_bytes = len;
+
+		pr_debug("reading from address: [%d %d] dma_address = %x\n",
+			sram_addr, offset, addr);
+
+		if (access == FG_READ) {
+			rc = fg_read(chip, addr, ptr, num_bytes);
+			temp_str = "read";
+		} else {
+			rc = fg_write(chip, addr, ptr, num_bytes);
+			temp_str = "write";
+		}
+
+		if (rc < 0) {
+			pr_err("Error in %sing address %d rc=%d\n", temp_str,
+				sram_addr, rc);
+			break;
+		}
+
+		ptr += num_bytes;
+		len -= num_bytes;
+		sram_addr += (num_bytes / BYTES_PER_SRAM_WORD);
+		offset = 0;
+	}
+
+	ret = fg_direct_mem_request(chip, false);
+	if (ret < 0) {
+		pr_err("Error in releasing direct_mem access rc=%d\n", rc);
+		return ret;
+	}
+
+	return rc;
+}
+
+int fg_direct_mem_read(struct fg_chip *chip, u16 sram_addr, u8 offset,
+				u8 *val, int len)
+{
+	return __fg_direct_mem_rw(chip, sram_addr, offset, val, len, FG_READ);
+}
+
+int fg_direct_mem_write(struct fg_chip *chip, u16 sram_addr, u8 offset,
+				u8 *val, int len, bool atomic_access)
+{
+	return __fg_direct_mem_rw(chip, sram_addr, offset, val, len, FG_WRITE);
+}
+
 int fg_ima_init(struct fg_chip *chip)
 {
 	int rc;
@@ -778,3 +1029,59 @@
 
 	return 0;
 }
+
+/*
+ * This SRAM partition to DMA address partition mapping remains identical for
+ * PMICs that use GEN3 FG.
+ */
+static struct fg_dma_address fg_gen3_addr_map[NUM_PARTITIONS] = {
+	/* system partition */
+	{
+		.partition_start = 0,
+		.partition_end = 23,
+		.spmi_addr_base = FG_DMA0_BASE + SRAM_ADDR_OFFSET,
+	},
+	/* battery profile partition */
+	{
+		.partition_start = 24,
+		.partition_end = 79,
+		.spmi_addr_base = FG_DMA1_BASE + SRAM_ADDR_OFFSET,
+	},
+	/* scratch pad partition */
+	{
+		.partition_start = 80,
+		.partition_end =  125,
+		.spmi_addr_base = FG_DMA2_BASE + SRAM_ADDR_OFFSET,
+	},
+};
+int fg_dma_init(struct fg_chip *chip)
+{
+	int rc;
+
+	chip->addr_map = fg_gen3_addr_map;
+
+	/* Clear DMA errors if any before clearing IMA errors */
+	rc = fg_clear_dma_errors_if_any(chip);
+	if (rc < 0) {
+		pr_err("Error in checking DMA errors rc:%d\n", rc);
+		return rc;
+	}
+
+	/* Configure the DMA peripheral addressing to partition */
+	rc = fg_masked_write(chip, MEM_IF_DMA_CTL(chip), ADDR_KIND_BIT,
+				ADDR_KIND_BIT);
+	if (rc < 0) {
+		pr_err("failed to configure DMA_CTL rc:%d\n", rc);
+		return rc;
+	}
+
+	/* Release the DMA initially so that request can happen */
+	rc = fg_direct_mem_request(chip, false);
+	if (rc < 0) {
+		pr_err("Error in releasing direct_mem access rc=%d\n",
+			rc);
+		return rc;
+	}
+
+	return 0;
+}
diff --git a/drivers/power/supply/qcom/fg-reg.h b/drivers/power/supply/qcom/fg-reg.h
index cd0b2fb..8ca4376 100644
--- a/drivers/power/supply/qcom/fg-reg.h
+++ b/drivers/power/supply/qcom/fg-reg.h
@@ -31,6 +31,7 @@
 #define BATT_SOC_LOW_PWR_STS(chip)		(chip->batt_soc_base + 0x56)
 
 /* BATT_SOC_INT_RT_STS */
+#define SOC_READY_BIT				BIT(1)
 #define MSOC_EMPTY_BIT				BIT(5)
 
 /* BATT_SOC_EN_CTL */
@@ -266,6 +267,7 @@
 
 /* FG_MEM_IF register and bit definitions */
 #define MEM_IF_INT_RT_STS(chip)			((chip->mem_if_base) + 0x10)
+#define MEM_IF_MEM_ARB_CFG(chip)		((chip->mem_if_base) + 0x40)
 #define MEM_IF_MEM_INTF_CFG(chip)		((chip->mem_if_base) + 0x50)
 #define MEM_IF_IMA_CTL(chip)			((chip->mem_if_base) + 0x51)
 #define MEM_IF_IMA_CFG(chip)			((chip->mem_if_base) + 0x52)
@@ -286,6 +288,11 @@
 
 /* MEM_IF_INT_RT_STS */
 #define MEM_XCP_BIT				BIT(1)
+#define MEM_GNT_BIT				BIT(2)
+
+/* MEM_IF_MEM_ARB_CFG */
+#define MEM_ARB_LO_LATENCY_EN_BIT		BIT(1)
+#define MEM_ARB_REQ_BIT				BIT(0)
 
 /* MEM_IF_MEM_INTF_CFG */
 #define MEM_ACCESS_REQ_BIT			BIT(7)
@@ -325,5 +332,13 @@
 #define DMA_READ_ERROR_BIT			BIT(2)
 
 /* MEM_IF_DMA_CTL */
+#define ADDR_KIND_BIT				BIT(1)
 #define DMA_CLEAR_LOG_BIT			BIT(0)
+
+/* FG_DMAx */
+#define FG_DMA0_BASE				0x4800
+#define FG_DMA1_BASE				0x4900
+#define FG_DMA2_BASE				0x4A00
+#define FG_DMA3_BASE				0x4B00
+#define SRAM_ADDR_OFFSET			0x20
 #endif
diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c
index 38d9594..d9ca47c 100644
--- a/drivers/power/supply/qcom/fg-util.c
+++ b/drivers/power/supply/qcom/fg-util.c
@@ -255,8 +255,6 @@
 		reinit_completion(&chip->soc_update);
 		enable_irq(chip->irqs[SOC_UPDATE_IRQ].irq);
 		atomic_access = true;
-	} else {
-		flags = FG_IMA_DEFAULT;
 	}
 wait:
 	/*
@@ -282,11 +280,17 @@
 		}
 	}
 
-	rc = fg_interleaved_mem_write(chip, address, offset, val, len,
-			atomic_access);
+	if (chip->use_dma)
+		rc = fg_direct_mem_write(chip, address, offset, val, len,
+				false);
+	else
+		rc = fg_interleaved_mem_write(chip, address, offset, val, len,
+				atomic_access);
+
 	if (rc < 0)
 		pr_err("Error in writing SRAM address 0x%x[%d], rc=%d\n",
 			address, offset, rc);
+
 out:
 	if (atomic_access)
 		disable_irq_nosync(chip->irqs[SOC_UPDATE_IRQ].irq);
@@ -313,9 +317,14 @@
 
 	if (!(flags & FG_IMA_NO_WLOCK))
 		vote(chip->awake_votable, SRAM_READ, true, 0);
+
 	mutex_lock(&chip->sram_rw_lock);
 
-	rc = fg_interleaved_mem_read(chip, address, offset, val, len);
+	if (chip->use_dma)
+		rc = fg_direct_mem_read(chip, address, offset, val, len);
+	else
+		rc = fg_interleaved_mem_read(chip, address, offset, val, len);
+
 	if (rc < 0)
 		pr_err("Error in reading SRAM address 0x%x[%d], rc=%d\n",
 			address, offset, rc);
diff --git a/drivers/power/supply/qcom/pmic-voter.c b/drivers/power/supply/qcom/pmic-voter.c
index 10a1c54..e0a5150 100644
--- a/drivers/power/supply/qcom/pmic-voter.c
+++ b/drivers/power/supply/qcom/pmic-voter.c
@@ -438,12 +438,14 @@
 int rerun_election(struct votable *votable)
 {
 	int rc = 0;
+	int effective_result;
 
 	lock_votable(votable);
+	effective_result = get_effective_result_locked(votable);
 	if (votable->callback)
 		rc = votable->callback(votable,
-				votable->data,
-			votable->effective_result,
+			votable->data,
+			effective_result,
 			get_client_str(votable, votable->effective_client_id));
 	unlock_votable(votable);
 	return rc;
@@ -519,11 +521,10 @@
 
 	lock_votable(votable);
 
-	seq_printf(m, "Votable %s:\n", votable->name);
-	seq_puts(m, "clients:\n");
 	for (i = 0; i < votable->num_clients; i++) {
 		if (votable->client_strs[i]) {
-			seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n",
+			seq_printf(m, "%s: %s:\t\t\ten=%d v=%d\n",
+					votable->name,
 					votable->client_strs[i],
 					votable->votes[i].enabled,
 					votable->votes[i].value);
@@ -542,11 +543,11 @@
 		break;
 	}
 
-	seq_printf(m, "type: %s\n", type_str);
-	seq_puts(m, "Effective:\n");
 	effective_client_str = get_effective_client_locked(votable);
-	seq_printf(m, "%-15s:\t\tv=%d\n",
+	seq_printf(m, "%s: effective=%s type=%s v=%d\n",
+			votable->name,
 			effective_client_str ? effective_client_str : "none",
+			type_str,
 			get_effective_result_locked(votable));
 	unlock_votable(votable);
 
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index e5a3a07..7c94744 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -75,6 +75,8 @@
 #define ESR_TIMER_CHG_MAX_OFFSET	0
 #define ESR_TIMER_CHG_INIT_WORD		18
 #define ESR_TIMER_CHG_INIT_OFFSET	2
+#define ESR_EXTRACTION_ENABLE_WORD	19
+#define ESR_EXTRACTION_ENABLE_OFFSET	0
 #define PROFILE_LOAD_WORD		24
 #define PROFILE_LOAD_OFFSET		0
 #define ESR_RSLOW_DISCHG_WORD		34
@@ -533,7 +535,7 @@
 	rc = fg_sram_read(chip, chip->sp[id].addr_word, chip->sp[id].addr_byte,
 		buf, chip->sp[id].len, FG_IMA_DEFAULT);
 	if (rc < 0) {
-		pr_err("Error reading address 0x%04x[%d] rc=%d\n",
+		pr_err("Error reading address %d[%d] rc=%d\n",
 			chip->sp[id].addr_word, chip->sp[id].addr_byte, rc);
 		return rc;
 	}
@@ -892,8 +894,8 @@
 		goto out;
 	}
 
-	/* Wait for 200ms before enabling BMD again */
-	msleep(200);
+	/* Wait for BATT_ID to settle down before enabling BMD again */
+	msleep(chip->dt.bmd_en_delay_ms);
 
 	fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);
 	chip->batt_id_ohms = batt_id;
@@ -1611,7 +1613,7 @@
 static int fg_charge_full_update(struct fg_chip *chip)
 {
 	union power_supply_propval prop = {0, };
-	int rc, msoc, bsoc, recharge_soc;
+	int rc, msoc, bsoc, recharge_soc, msoc_raw;
 	u8 full_soc[2] = {0xFF, 0xFF};
 
 	if (!chip->dt.hold_soc_while_full)
@@ -1647,6 +1649,7 @@
 		pr_err("Error in getting msoc, rc=%d\n", rc);
 		goto out;
 	}
+	msoc_raw = DIV_ROUND_CLOSEST(msoc * FULL_SOC_RAW, FULL_CAPACITY);
 
 	fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d full: %d\n",
 		msoc, bsoc, chip->health, chip->charge_status,
@@ -1670,7 +1673,7 @@
 			fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
 				msoc);
 		}
-	} else if ((bsoc >> 8) <= recharge_soc && chip->charge_full) {
+	} else if (msoc_raw < recharge_soc && chip->charge_full) {
 		chip->delta_soc = FULL_CAPACITY - msoc;
 
 		/*
@@ -1700,8 +1703,8 @@
 				rc);
 			goto out;
 		}
-		fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d delta_soc: %d\n",
-			bsoc >> 8, recharge_soc, chip->delta_soc);
+		fg_dbg(chip, FG_STATUS, "msoc_raw = %d bsoc: %d recharge_soc: %d delta_soc: %d\n",
+			msoc_raw, bsoc >> 8, recharge_soc, chip->delta_soc);
 	} else {
 		goto out;
 	}
@@ -3032,6 +3035,89 @@
 	return 0;
 }
 
+static int fg_force_esr_meas(struct fg_chip *chip)
+{
+	int rc;
+	int esr_uohms;
+
+	/* force esr extraction enable */
+	rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
+			ESR_EXTRACTION_ENABLE_OFFSET, BIT(0), BIT(0),
+			FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("failed to enable esr extn rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
+			LD_REG_CTRL_BIT, 0);
+	if (rc < 0) {
+		pr_err("Error in configuring qnovo_cfg rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = fg_masked_write(chip, BATT_INFO_TM_MISC1(chip),
+			ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT,
+			ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT);
+	if (rc < 0) {
+		pr_err("Error in configuring force ESR rc=%d\n", rc);
+		return rc;
+	}
+
+	/* wait 1.5 seconds for hw to measure ESR */
+	msleep(1500);
+	rc = fg_masked_write(chip, BATT_INFO_TM_MISC1(chip),
+			ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT,
+			0);
+	if (rc < 0) {
+		pr_err("Error in restoring force ESR rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
+			LD_REG_CTRL_BIT, LD_REG_CTRL_BIT);
+	if (rc < 0) {
+		pr_err("Error in restoring qnovo_cfg rc=%d\n", rc);
+		return rc;
+	}
+
+	/* force esr extraction disable */
+	rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
+			ESR_EXTRACTION_ENABLE_OFFSET, BIT(0), 0,
+			FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("failed to disable esr extn rc=%d\n", rc);
+		return rc;
+	}
+
+	fg_get_battery_resistance(chip, &esr_uohms);
+	fg_dbg(chip, FG_STATUS, "ESR uohms = %d\n", esr_uohms);
+
+	return rc;
+}
+
+static int fg_prepare_for_qnovo(struct fg_chip *chip, int qnovo_enable)
+{
+	int rc;
+
+	/* force esr extraction disable when qnovo enables */
+	rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
+			ESR_EXTRACTION_ENABLE_OFFSET,
+			BIT(0), qnovo_enable ? 0 : BIT(0),
+			FG_IMA_DEFAULT);
+	if (rc < 0)
+		pr_err("Error in configuring esr extraction rc=%d\n", rc);
+
+	rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
+			LD_REG_CTRL_BIT,
+			qnovo_enable ? LD_REG_CTRL_BIT : 0);
+	if (rc < 0) {
+		pr_err("Error in configuring qnovo_cfg rc=%d\n", rc);
+		return rc;
+	}
+	fg_dbg(chip, FG_STATUS, "Prepared for Qnovo\n");
+	return 0;
+}
 /* PSY CALLBACKS STAY HERE */
 
 static int fg_psy_get_property(struct power_supply *psy,
@@ -3140,6 +3226,12 @@
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 		rc = fg_set_constant_chg_voltage(chip, pval->intval);
 		break;
+	case POWER_SUPPLY_PROP_RESISTANCE:
+		rc = fg_force_esr_meas(chip);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE:
+		rc = fg_prepare_for_qnovo(chip, pval->intval);
+		break;
 	default:
 		break;
 	}
@@ -3503,6 +3595,9 @@
 
 static int fg_memif_init(struct fg_chip *chip)
 {
+	if (chip->use_dma)
+		return fg_dma_init(chip);
+
 	return fg_ima_init(chip);
 }
 
@@ -3542,6 +3637,26 @@
 
 /* INTERRUPT HANDLERS STAY HERE */
 
+static irqreturn_t fg_dma_grant_irq_handler(int irq, void *data)
+{
+	struct fg_chip *chip = data;
+	u8 status;
+	int rc;
+
+	rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
+	if (rc < 0) {
+		pr_err("failed to read addr=0x%04x, rc=%d\n",
+			MEM_IF_INT_RT_STS(chip), rc);
+		return IRQ_HANDLED;
+	}
+
+	fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
+	if (status & MEM_GNT_BIT)
+		complete_all(&chip->mem_grant);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
 {
 	struct fg_chip *chip = data;
@@ -3822,7 +3937,8 @@
 	/* MEM_IF irqs */
 	[DMA_GRANT_IRQ] = {
 		.name		= "dma-grant",
-		.handler	= fg_dummy_irq_handler,
+		.handler	= fg_dma_grant_irq_handler,
+		.wakeable	= true,
 	},
 	[MEM_XCP_IRQ] = {
 		.name		= "mem-xcp",
@@ -4011,6 +4127,7 @@
 #define DEFAULT_ESR_CLAMP_MOHMS		20
 #define DEFAULT_ESR_PULSE_THRESH_MA	110
 #define DEFAULT_ESR_MEAS_CURR_MA	120
+#define DEFAULT_BMD_EN_DELAY_MS	200
 static int fg_parse_dt(struct fg_chip *chip)
 {
 	struct device_node *child, *revid_node, *node = chip->dev->of_node;
@@ -4046,6 +4163,7 @@
 
 	switch (chip->pmic_rev_id->pmic_subtype) {
 	case PMI8998_SUBTYPE:
+		chip->use_dma = true;
 		if (chip->pmic_rev_id->rev4 < PMI8998_V2P0_REV4) {
 			chip->sp = pmi8998_v1_sram_params;
 			chip->alg_flags = pmi8998_v1_alg_flags;
@@ -4356,6 +4474,13 @@
 			chip->dt.esr_meas_curr_ma = temp;
 	}
 
+	chip->dt.bmd_en_delay_ms = DEFAULT_BMD_EN_DELAY_MS;
+	rc = of_property_read_u32(node, "qcom,fg-bmd-en-delay-ms", &temp);
+	if (!rc) {
+		if (temp > DEFAULT_BMD_EN_DELAY_MS)
+			chip->dt.bmd_en_delay_ms = temp;
+	}
+
 	return 0;
 }
 
@@ -4466,6 +4591,7 @@
 	mutex_init(&chip->charge_full_lock);
 	init_completion(&chip->soc_update);
 	init_completion(&chip->soc_ready);
+	init_completion(&chip->mem_grant);
 	INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
 	INIT_WORK(&chip->status_change_work, status_change_work);
 	INIT_WORK(&chip->cycle_count_work, cycle_count_work);
@@ -4479,6 +4605,25 @@
 		goto exit;
 	}
 
+	platform_set_drvdata(pdev, chip);
+
+	rc = fg_register_interrupts(chip);
+	if (rc < 0) {
+		dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
+			rc);
+		goto exit;
+	}
+
+	/* Keep SOC_UPDATE irq disabled until we require it */
+	if (fg_irqs[SOC_UPDATE_IRQ].irq)
+		disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
+
+	/* Keep BSOC_DELTA_IRQ disabled until we require it */
+	vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER, false, 0);
+
+	/* Keep BATT_MISSING_IRQ disabled until we require it */
+	vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, false, 0);
+
 	rc = fg_hw_init(chip);
 	if (rc < 0) {
 		dev_err(chip->dev, "Error in initializing FG hardware, rc:%d\n",
@@ -4486,8 +4631,6 @@
 		goto exit;
 	}
 
-	platform_set_drvdata(pdev, chip);
-
 	/* Register the power supply */
 	fg_psy_cfg.drv_data = chip;
 	fg_psy_cfg.of_node = NULL;
@@ -4508,23 +4651,6 @@
 		goto exit;
 	}
 
-	rc = fg_register_interrupts(chip);
-	if (rc < 0) {
-		dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
-			rc);
-		goto exit;
-	}
-
-	/* Keep SOC_UPDATE_IRQ disabled until we require it */
-	if (fg_irqs[SOC_UPDATE_IRQ].irq)
-		disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
-
-	/* Keep BSOC_DELTA_IRQ disabled until we require it */
-	vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER, false, 0);
-
-	/* Keep BATT_MISSING_IRQ disabled until we require it */
-	vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, false, 0);
-
 	rc = fg_debugfs_create(chip);
 	if (rc < 0) {
 		dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index eb97eb0..cf90f90 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -20,6 +20,7 @@
 #include <linux/of_irq.h>
 #include <linux/qpnp/qpnp-revid.h>
 #include <linux/pmic-voter.h>
+#include <linux/delay.h>
 
 #define QNOVO_REVISION1		0x00
 #define QNOVO_REVISION2		0x01
@@ -114,6 +115,17 @@
 #define OK_TO_QNOVO_VOTER	"ok_to_qnovo_voter"
 
 #define QNOVO_VOTER		"qnovo_voter"
+#define FG_AVAILABLE_VOTER	"FG_AVAILABLE_VOTER"
+#define QNOVO_OVERALL_VOTER	"QNOVO_OVERALL_VOTER"
+#define QNI_PT_VOTER		"QNI_PT_VOTER"
+#define ESR_VOTER		"ESR_VOTER"
+
+#define HW_OK_TO_QNOVO_VOTER	"HW_OK_TO_QNOVO_VOTER"
+#define CHG_READY_VOTER		"CHG_READY_VOTER"
+#define USB_READY_VOTER		"USB_READY_VOTER"
+#define DC_READY_VOTER		"DC_READY_VOTER"
+
+#define PT_RESTART_VOTER	"PT_RESTART_VOTER"
 
 struct qnovo_dt_props {
 	bool			external_rsense;
@@ -127,6 +139,10 @@
 	struct qnovo_dt_props	dt;
 	struct device		*dev;
 	struct votable		*disable_votable;
+	struct votable		*pt_dis_votable;
+	struct votable		*not_ok_to_qnovo_votable;
+	struct votable		*chg_ready_votable;
+	struct votable		*awake_votable;
 	struct class		qnovo_class;
 	struct pmic_revid_data	*pmic_rev_id;
 	u32			wa_flags;
@@ -138,10 +154,18 @@
 	s64			v_gain_mega;
 	struct notifier_block	nb;
 	struct power_supply	*batt_psy;
+	struct power_supply	*bms_psy;
+	struct power_supply	*usb_psy;
+	struct power_supply	*dc_psy;
 	struct work_struct	status_change_work;
 	int			fv_uV_request;
 	int			fcc_uA_request;
-	bool			ok_to_qnovo;
+	int			usb_present;
+	int			dc_present;
+	struct delayed_work	usb_debounce_work;
+	struct delayed_work	dc_debounce_work;
+
+	struct delayed_work	ptrain_restart_work;
 };
 
 static int debug_mask;
@@ -229,6 +253,39 @@
 	return true;
 }
 
+static bool is_fg_available(struct qnovo *chip)
+{
+	if (!chip->bms_psy)
+		chip->bms_psy = power_supply_get_by_name("bms");
+
+	if (!chip->bms_psy)
+		return false;
+
+	return true;
+}
+
+static bool is_usb_available(struct qnovo *chip)
+{
+	if (!chip->usb_psy)
+		chip->usb_psy = power_supply_get_by_name("usb");
+
+	if (!chip->usb_psy)
+		return false;
+
+	return true;
+}
+
+static bool is_dc_available(struct qnovo *chip)
+{
+	if (!chip->dc_psy)
+		chip->dc_psy = power_supply_get_by_name("dc");
+
+	if (!chip->dc_psy)
+		return false;
+
+	return true;
+}
+
 static int qnovo_batt_psy_update(struct qnovo *chip, bool disable)
 {
 	union power_supply_propval pval = {0};
@@ -281,10 +338,86 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * fg must be available for enable FG_AVAILABLE_VOTER
+	 * won't enable it otherwise
+	 */
+
+	if (is_fg_available(chip))
+		power_supply_set_property(chip->bms_psy,
+				POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE,
+				&pval);
+
+	vote(chip->pt_dis_votable, QNOVO_OVERALL_VOTER, disable, 0);
 	rc = qnovo_batt_psy_update(chip, disable);
 	return rc;
 }
 
+static int pt_dis_votable_cb(struct votable *votable, void *data, int disable,
+					const char *client)
+{
+	struct qnovo *chip = data;
+	int rc;
+
+	if (disable) {
+		cancel_delayed_work_sync(&chip->ptrain_restart_work);
+		vote(chip->awake_votable, PT_RESTART_VOTER, false, 0);
+	}
+
+	rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
+				 (bool)disable ? 0 : QNOVO_PTRAIN_EN_BIT);
+	if (rc < 0) {
+		dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
+			(bool)disable ? "disable" : "enable", rc);
+		return rc;
+	}
+
+	if (!disable) {
+		vote(chip->awake_votable, PT_RESTART_VOTER, true, 0);
+		schedule_delayed_work(&chip->ptrain_restart_work,
+				msecs_to_jiffies(20));
+	}
+
+	return 0;
+}
+
+static int not_ok_to_qnovo_cb(struct votable *votable, void *data,
+					int not_ok_to_qnovo,
+					const char *client)
+{
+	struct qnovo *chip = data;
+
+	vote(chip->disable_votable, OK_TO_QNOVO_VOTER, not_ok_to_qnovo, 0);
+	if (not_ok_to_qnovo)
+		vote(chip->disable_votable, USER_VOTER, true, 0);
+
+	kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+	return 0;
+}
+
+static int chg_ready_cb(struct votable *votable, void *data, int ready,
+					const char *client)
+{
+	struct qnovo *chip = data;
+
+	vote(chip->not_ok_to_qnovo_votable, CHG_READY_VOTER, !ready, 0);
+
+	return 0;
+}
+
+static int awake_cb(struct votable *votable, void *data, int awake,
+					const char *client)
+{
+	struct qnovo *chip = data;
+
+	if (awake)
+		pm_stay_awake(chip->dev);
+	else
+		pm_relax(chip->dev);
+
+	return 0;
+}
+
 static int qnovo_parse_dt(struct qnovo *chip)
 {
 	struct device_node *node = chip->dev->of_node;
@@ -626,8 +759,9 @@
 			char *buf)
 {
 	struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
+	int val = get_effective_result(chip->not_ok_to_qnovo_votable);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", chip->ok_to_qnovo);
+	return snprintf(buf, PAGE_SIZE, "%d\n", !val);
 }
 
 static ssize_t qnovo_enable_show(struct class *c, struct class_attribute *attr,
@@ -656,21 +790,10 @@
 static ssize_t pt_enable_show(struct class *c, struct class_attribute *attr,
 			char *ubuf)
 {
-	int i = attr - qnovo_attributes;
 	struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
-	u8 buf[2] = {0, 0};
-	u16 regval;
-	int rc;
+	int val = get_effective_result(chip->pt_dis_votable);
 
-	rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
-	if (rc < 0) {
-		pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
-		return -EINVAL;
-	}
-	regval = buf[1] << 8 | buf[0];
-
-	return snprintf(ubuf, PAGE_SIZE, "%d\n",
-				(int)(regval & QNOVO_PTRAIN_EN_BIT));
+	return snprintf(ubuf, PAGE_SIZE, "%d\n", !val);
 }
 
 static ssize_t pt_enable_store(struct class *c, struct class_attribute *attr,
@@ -678,21 +801,12 @@
 {
 	struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
 	unsigned long val;
-	int rc = 0;
-
-	if (get_effective_result(chip->disable_votable))
-		return -EINVAL;
 
 	if (kstrtoul(ubuf, 0, &val))
 		return -EINVAL;
 
-	rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
-				 (bool)val ? QNOVO_PTRAIN_EN_BIT : 0);
-	if (rc < 0) {
-		dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
-			(bool)val ? "enable" : "disable", rc);
-		return rc;
-	}
+	/* val being 0, userspace wishes to disable pt so vote true */
+	vote(chip->pt_dis_votable, QNI_PT_VOTER, val ? false : true, 0);
 
 	return count;
 }
@@ -1116,41 +1230,146 @@
 {
 	u8 val = 0;
 	int rc;
-	bool ok_to_qnovo;
-	bool changed = false;
+	bool hw_ok_to_qnovo;
 
 	rc = qnovo_read(chip, QNOVO_ERROR_STS2, &val, 1);
 	if (rc < 0) {
 		pr_err("Couldn't read error sts rc = %d\n", rc);
-		ok_to_qnovo = false;
+		hw_ok_to_qnovo = false;
 	} else {
 		/*
 		 * For CV mode keep qnovo enabled, userspace is expected to
 		 * disable it after few runs
 		 */
-		ok_to_qnovo = (val == ERR_CV_MODE || val == 0) ? true : false;
+		hw_ok_to_qnovo = (val == ERR_CV_MODE || val == 0) ?
+			true : false;
 	}
 
-	if (chip->ok_to_qnovo ^ ok_to_qnovo) {
-
-		vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !ok_to_qnovo, 0);
-		if (!ok_to_qnovo)
-			vote(chip->disable_votable, USER_VOTER, true, 0);
-
-		chip->ok_to_qnovo = ok_to_qnovo;
-		changed = true;
-	}
-
-	return changed;
+	vote(chip->not_ok_to_qnovo_votable, HW_OK_TO_QNOVO_VOTER,
+					!hw_ok_to_qnovo, 0);
+	return 0;
 }
 
+static void usb_debounce_work(struct work_struct *work)
+{
+	struct qnovo *chip = container_of(work,
+				struct qnovo, usb_debounce_work.work);
+
+	vote(chip->chg_ready_votable, USB_READY_VOTER, true, 0);
+	vote(chip->awake_votable, USB_READY_VOTER, false, 0);
+}
+
+static void dc_debounce_work(struct work_struct *work)
+{
+	struct qnovo *chip = container_of(work,
+				struct qnovo, dc_debounce_work.work);
+
+	vote(chip->chg_ready_votable, DC_READY_VOTER, true, 0);
+	vote(chip->awake_votable, DC_READY_VOTER, false, 0);
+}
+
+#define DEBOUNCE_MS 15000  /* 15 seconds */
 static void status_change_work(struct work_struct *work)
 {
 	struct qnovo *chip = container_of(work,
 			struct qnovo, status_change_work);
+	union power_supply_propval pval;
+	bool usb_present = false, dc_present = false;
+	int rc;
 
-	if (qnovo_update_status(chip))
-		kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+	if (is_fg_available(chip))
+		vote(chip->disable_votable, FG_AVAILABLE_VOTER, false, 0);
+
+	if (is_usb_available(chip)) {
+		rc = power_supply_get_property(chip->usb_psy,
+				POWER_SUPPLY_PROP_PRESENT, &pval);
+		usb_present = (rc < 0) ? 0 : pval.intval;
+	}
+
+	if (chip->usb_present && !usb_present) {
+		/* removal */
+		chip->usb_present = 0;
+		cancel_delayed_work_sync(&chip->usb_debounce_work);
+		vote(chip->awake_votable, USB_READY_VOTER, false, 0);
+		vote(chip->chg_ready_votable, USB_READY_VOTER, false, 0);
+	} else if (!chip->usb_present && usb_present) {
+		/* insertion */
+		chip->usb_present = 1;
+		vote(chip->awake_votable, USB_READY_VOTER, true, 0);
+		schedule_delayed_work(&chip->usb_debounce_work,
+				msecs_to_jiffies(DEBOUNCE_MS));
+	}
+
+	if (is_dc_available(chip)) {
+		rc = power_supply_get_property(chip->dc_psy,
+			POWER_SUPPLY_PROP_PRESENT,
+			&pval);
+		dc_present = (rc < 0) ? 0 : pval.intval;
+	}
+
+	if (usb_present)
+		dc_present = 0;
+
+	if (chip->dc_present && !dc_present) {
+		/* removal */
+		chip->dc_present = 0;
+		cancel_delayed_work_sync(&chip->dc_debounce_work);
+		vote(chip->awake_votable, DC_READY_VOTER, false, 0);
+		vote(chip->chg_ready_votable, DC_READY_VOTER, false, 0);
+	} else if (!chip->dc_present && dc_present) {
+		/* insertion */
+		chip->dc_present = 1;
+		vote(chip->awake_votable, DC_READY_VOTER, true, 0);
+		schedule_delayed_work(&chip->dc_debounce_work,
+				msecs_to_jiffies(DEBOUNCE_MS));
+	}
+
+	qnovo_update_status(chip);
+}
+
+static void ptrain_restart_work(struct work_struct *work)
+{
+	struct qnovo *chip = container_of(work,
+				struct qnovo, ptrain_restart_work.work);
+	u8 pt_t1, pt_t2;
+	int rc;
+
+	rc = qnovo_read(chip, QNOVO_PTTIME_STS, &pt_t1, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "Couldn't read QNOVO_PTTIME_STS rc = %d\n",
+			rc);
+		goto clean_up;
+	}
+
+	/* pttime increments every 2 seconds */
+	msleep(2100);
+
+	rc = qnovo_read(chip, QNOVO_PTTIME_STS, &pt_t2, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "Couldn't read QNOVO_PTTIME_STS rc = %d\n",
+			rc);
+		goto clean_up;
+	}
+
+	if (pt_t1 != pt_t2)
+		goto clean_up;
+
+	/* Toggle pt enable to restart pulse train */
+	rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT, 0);
+	if (rc < 0) {
+		dev_err(chip->dev, "Couldn't disable pulse train rc=%d\n", rc);
+		goto clean_up;
+	}
+	msleep(1000);
+	rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
+				QNOVO_PTRAIN_EN_BIT);
+	if (rc < 0) {
+		dev_err(chip->dev, "Couldn't enable pulse train rc=%d\n", rc);
+		goto clean_up;
+	}
+
+clean_up:
+	vote(chip->awake_votable, PT_RESTART_VOTER, false, 0);
 }
 
 static int qnovo_notifier_call(struct notifier_block *nb,
@@ -1162,7 +1381,10 @@
 	if (ev != PSY_EVENT_PROP_CHANGED)
 		return NOTIFY_OK;
 
-	if (strcmp(psy->desc->name, "battery") == 0)
+	if (strcmp(psy->desc->name, "battery") == 0
+		|| strcmp(psy->desc->name, "bms") == 0
+		|| strcmp(psy->desc->name, "usb") == 0
+		|| strcmp(psy->desc->name, "dc") == 0)
 		schedule_work(&chip->status_change_work);
 
 	return NOTIFY_OK;
@@ -1171,7 +1393,23 @@
 static irqreturn_t handle_ptrain_done(int irq, void *data)
 {
 	struct qnovo *chip = data;
+	union power_supply_propval pval = {0};
 
+	/*
+	 * hw resets pt_en bit once ptrain_done triggers.
+	 * vote on behalf of QNI to disable it such that
+	 * once QNI enables it, the votable state changes
+	 * and the callback that sets it is indeed invoked
+	 */
+	vote(chip->pt_dis_votable, QNI_PT_VOTER, true, 0);
+
+	vote(chip->pt_dis_votable, ESR_VOTER, true, 0);
+	if (is_fg_available(chip))
+		power_supply_set_property(chip->bms_psy,
+				POWER_SUPPLY_PROP_RESISTANCE,
+				&pval);
+
+	vote(chip->pt_dis_votable, ESR_VOTER, false, 0);
 	qnovo_update_status(chip);
 	kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
 	return IRQ_HANDLED;
@@ -1186,6 +1424,11 @@
 	u8 val;
 
 	vote(chip->disable_votable, USER_VOTER, true, 0);
+	vote(chip->disable_votable, FG_AVAILABLE_VOTER, true, 0);
+
+	vote(chip->pt_dis_votable, QNI_PT_VOTER, true, 0);
+	vote(chip->pt_dis_votable, QNOVO_OVERALL_VOTER, true, 0);
+	vote(chip->pt_dis_votable, ESR_VOTER, false, 0);
 
 	val = 0;
 	rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1);
@@ -1349,12 +1592,45 @@
 		goto cleanup;
 	}
 
+	chip->pt_dis_votable = create_votable("QNOVO_PT_DIS", VOTE_SET_ANY,
+					pt_dis_votable_cb, chip);
+	if (IS_ERR(chip->pt_dis_votable)) {
+		rc = PTR_ERR(chip->pt_dis_votable);
+		goto destroy_disable_votable;
+	}
+
+	chip->not_ok_to_qnovo_votable = create_votable("QNOVO_NOT_OK",
+					VOTE_SET_ANY,
+					not_ok_to_qnovo_cb, chip);
+	if (IS_ERR(chip->not_ok_to_qnovo_votable)) {
+		rc = PTR_ERR(chip->not_ok_to_qnovo_votable);
+		goto destroy_pt_dis_votable;
+	}
+
+	chip->chg_ready_votable = create_votable("QNOVO_CHG_READY",
+					VOTE_SET_ANY,
+					chg_ready_cb, chip);
+	if (IS_ERR(chip->chg_ready_votable)) {
+		rc = PTR_ERR(chip->chg_ready_votable);
+		goto destroy_not_ok_to_qnovo_votable;
+	}
+
+	chip->awake_votable = create_votable("QNOVO_AWAKE", VOTE_SET_ANY,
+					awake_cb, chip);
+	if (IS_ERR(chip->awake_votable)) {
+		rc = PTR_ERR(chip->awake_votable);
+		goto destroy_chg_ready_votable;
+	}
+
 	INIT_WORK(&chip->status_change_work, status_change_work);
+	INIT_DELAYED_WORK(&chip->dc_debounce_work, dc_debounce_work);
+	INIT_DELAYED_WORK(&chip->usb_debounce_work, usb_debounce_work);
+	INIT_DELAYED_WORK(&chip->ptrain_restart_work, ptrain_restart_work);
 
 	rc = qnovo_hw_init(chip);
 	if (rc < 0) {
 		pr_err("Couldn't initialize hardware rc=%d\n", rc);
-		goto destroy_votable;
+		goto destroy_awake_votable;
 	}
 
 	rc = qnovo_register_notifier(chip);
@@ -1390,7 +1666,15 @@
 
 unreg_notifier:
 	power_supply_unreg_notifier(&chip->nb);
-destroy_votable:
+destroy_awake_votable:
+	destroy_votable(chip->awake_votable);
+destroy_chg_ready_votable:
+	destroy_votable(chip->chg_ready_votable);
+destroy_not_ok_to_qnovo_votable:
+	destroy_votable(chip->not_ok_to_qnovo_votable);
+destroy_pt_dis_votable:
+	destroy_votable(chip->pt_dis_votable);
+destroy_disable_votable:
 	destroy_votable(chip->disable_votable);
 cleanup:
 	platform_set_drvdata(pdev, NULL);
@@ -1403,6 +1687,9 @@
 
 	class_unregister(&chip->qnovo_class);
 	power_supply_unreg_notifier(&chip->nb);
+	destroy_votable(chip->chg_ready_votable);
+	destroy_votable(chip->not_ok_to_qnovo_votable);
+	destroy_votable(chip->pt_dis_votable);
 	destroy_votable(chip->disable_votable);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index e94873c..b3de8d0 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -19,6 +19,7 @@
 #include <linux/power_supply.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/log2.h>
 #include <linux/qpnp/qpnp-revid.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
@@ -122,87 +123,6 @@
 		.max_u	= 1575000,
 		.step_u	= 25000,
 	},
-	.step_soc_threshold[0]		= {
-		.name	= "step charge soc threshold 1",
-		.reg	= STEP_CHG_SOC_OR_BATT_V_TH1_REG,
-		.min_u	= 0,
-		.max_u	= 100,
-		.step_u	= 1,
-	},
-	.step_soc_threshold[1]		= {
-		.name	= "step charge soc threshold 2",
-		.reg	= STEP_CHG_SOC_OR_BATT_V_TH2_REG,
-		.min_u	= 0,
-		.max_u	= 100,
-		.step_u	= 1,
-	},
-	.step_soc_threshold[2]         = {
-		.name	= "step charge soc threshold 3",
-		.reg	= STEP_CHG_SOC_OR_BATT_V_TH3_REG,
-		.min_u	= 0,
-		.max_u	= 100,
-		.step_u	= 1,
-	},
-	.step_soc_threshold[3]         = {
-		.name	= "step charge soc threshold 4",
-		.reg	= STEP_CHG_SOC_OR_BATT_V_TH4_REG,
-		.min_u	= 0,
-		.max_u	= 100,
-		.step_u	= 1,
-	},
-	.step_soc			= {
-		.name	= "step charge soc",
-		.reg	= STEP_CHG_SOC_VBATT_V_REG,
-		.min_u	= 0,
-		.max_u	= 100,
-		.step_u	= 1,
-		.set_proc	= smblib_mapping_soc_from_field_value,
-	},
-	.step_cc_delta[0]	= {
-		.name	= "step charge current delta 1",
-		.reg	= STEP_CHG_CURRENT_DELTA1_REG,
-		.min_u	= 100000,
-		.max_u	= 3200000,
-		.step_u	= 100000,
-		.get_proc	= smblib_mapping_cc_delta_to_field_value,
-		.set_proc	= smblib_mapping_cc_delta_from_field_value,
-	},
-	.step_cc_delta[1]	= {
-		.name	= "step charge current delta 2",
-		.reg	= STEP_CHG_CURRENT_DELTA2_REG,
-		.min_u	= 100000,
-		.max_u	= 3200000,
-		.step_u	= 100000,
-		.get_proc	= smblib_mapping_cc_delta_to_field_value,
-		.set_proc	= smblib_mapping_cc_delta_from_field_value,
-	},
-	.step_cc_delta[2]	= {
-		.name	= "step charge current delta 3",
-		.reg	= STEP_CHG_CURRENT_DELTA3_REG,
-		.min_u	= 100000,
-		.max_u	= 3200000,
-		.step_u	= 100000,
-		.get_proc	= smblib_mapping_cc_delta_to_field_value,
-		.set_proc	= smblib_mapping_cc_delta_from_field_value,
-	},
-	.step_cc_delta[3]	= {
-		.name	= "step charge current delta 4",
-		.reg	= STEP_CHG_CURRENT_DELTA4_REG,
-		.min_u	= 100000,
-		.max_u	= 3200000,
-		.step_u	= 100000,
-		.get_proc	= smblib_mapping_cc_delta_to_field_value,
-		.set_proc	= smblib_mapping_cc_delta_from_field_value,
-	},
-	.step_cc_delta[4]	= {
-		.name	= "step charge current delta 5",
-		.reg	= STEP_CHG_CURRENT_DELTA5_REG,
-		.min_u	= 100000,
-		.max_u	= 3200000,
-		.step_u	= 100000,
-		.get_proc	= smblib_mapping_cc_delta_to_field_value,
-		.set_proc	= smblib_mapping_cc_delta_from_field_value,
-	},
 	.freq_buck		= {
 		.name	= "buck switching frequency",
 		.reg	= CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG,
@@ -236,7 +156,6 @@
 	},
 };
 
-#define STEP_CHARGING_MAX_STEPS	5
 struct smb_dt_props {
 	int	usb_icl_ua;
 	int	dc_icl_ua;
@@ -244,14 +163,13 @@
 	int	wipower_max_uw;
 	int	min_freq_khz;
 	int	max_freq_khz;
-	u32	step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
-	s32	step_cc_delta[STEP_CHARGING_MAX_STEPS];
 	struct	device_node *revid_dev_node;
 	int	float_option;
 	int	chg_inhibit_thr_mv;
 	bool	no_battery;
 	bool	hvdcp_disable;
 	bool	auto_recharge_soc;
+	int	wd_bark_time;
 };
 
 struct smb2 {
@@ -273,6 +191,11 @@
 #define MICRO_1P5A		1500000
 #define MICRO_P1A		100000
 #define OTG_DEFAULT_DEGLITCH_TIME_MS	50
+#define MIN_WD_BARK_TIME		16
+#define DEFAULT_WD_BARK_TIME		64
+#define BITE_WDOG_TIMEOUT_8S		0x3
+#define BARK_WDOG_TIMEOUT_MASK		GENMASK(3, 2)
+#define BARK_WDOG_TIMEOUT_SHIFT		2
 static int smb2_parse_dt(struct smb2 *chip)
 {
 	struct smb_charger *chg = &chip->chg;
@@ -284,27 +207,16 @@
 		return -EINVAL;
 	}
 
-	chg->step_chg_enabled = true;
+	chg->step_chg_enabled = of_property_read_bool(node,
+				"qcom,step-charging-enable");
 
-	if (of_property_count_u32_elems(node, "qcom,step-soc-thresholds")
-			!= STEP_CHARGING_MAX_STEPS - 1)
-		chg->step_chg_enabled = false;
+	chg->sw_jeita_enabled = of_property_read_bool(node,
+				"qcom,sw-jeita-enable");
 
-	rc = of_property_read_u32_array(node, "qcom,step-soc-thresholds",
-			chip->dt.step_soc_threshold,
-			STEP_CHARGING_MAX_STEPS - 1);
-	if (rc < 0)
-		chg->step_chg_enabled = false;
-
-	if (of_property_count_u32_elems(node, "qcom,step-current-deltas")
-			!= STEP_CHARGING_MAX_STEPS)
-		chg->step_chg_enabled = false;
-
-	rc = of_property_read_u32_array(node, "qcom,step-current-deltas",
-			chip->dt.step_cc_delta,
-			STEP_CHARGING_MAX_STEPS);
-	if (rc < 0)
-		chg->step_chg_enabled = false;
+	rc = of_property_read_u32(node, "qcom,wd-bark-time-secs",
+					&chip->dt.wd_bark_time);
+	if (rc < 0 || chip->dt.wd_bark_time < MIN_WD_BARK_TIME)
+		chip->dt.wd_bark_time = DEFAULT_WD_BARK_TIME;
 
 	chip->dt.no_battery = of_property_read_bool(node,
 						"qcom,batteryless-platform");
@@ -988,7 +900,6 @@
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
 	POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
-	POWER_SUPPLY_PROP_STEP_CHARGING_STEP,
 	POWER_SUPPLY_PROP_CHARGE_DONE,
 	POWER_SUPPLY_PROP_PARALLEL_DISABLE,
 	POWER_SUPPLY_PROP_SET_SHIP_MODE,
@@ -1051,9 +962,6 @@
 	case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
 		val->intval = chg->step_chg_enabled;
 		break;
-	case POWER_SUPPLY_PROP_STEP_CHARGING_STEP:
-		rc = smblib_get_prop_step_chg_step(chg, val);
-		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 		rc = smblib_get_prop_batt_voltage_now(chg, val);
 		break;
@@ -1167,6 +1075,9 @@
 			vote(chg->fcc_votable, BATT_PROFILE_VOTER, false, 0);
 		}
 		break;
+	case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
+		chg->step_chg_enabled = !!val->intval;
+		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 		chg->batt_profile_fcc_ua = val->intval;
 		vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
@@ -1207,6 +1118,7 @@
 	case POWER_SUPPLY_PROP_DP_DM:
 	case POWER_SUPPLY_PROP_RERUN_AICL:
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
+	case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
 		return 1;
 	default:
 		break;
@@ -1334,73 +1246,6 @@
 /***************************
  * HARDWARE INITIALIZATION *
  ***************************/
-static int smb2_config_step_charging(struct smb2 *chip)
-{
-	struct smb_charger *chg = &chip->chg;
-	int rc = 0;
-	int i;
-
-	if (!chg->step_chg_enabled)
-		return rc;
-
-	for (i = 0; i < STEP_CHARGING_MAX_STEPS - 1; i++) {
-		rc = smblib_set_charge_param(chg,
-					     &chg->param.step_soc_threshold[i],
-					     chip->dt.step_soc_threshold[i]);
-		if (rc < 0) {
-			pr_err("Couldn't configure soc thresholds rc = %d\n",
-				rc);
-			goto err_out;
-		}
-	}
-
-	for (i = 0; i < STEP_CHARGING_MAX_STEPS; i++) {
-		rc = smblib_set_charge_param(chg, &chg->param.step_cc_delta[i],
-					     chip->dt.step_cc_delta[i]);
-		if (rc < 0) {
-			pr_err("Couldn't configure cc delta rc = %d\n",
-				rc);
-			goto err_out;
-		}
-	}
-
-	rc = smblib_write(chg, STEP_CHG_UPDATE_REQUEST_TIMEOUT_CFG_REG,
-			  STEP_CHG_UPDATE_REQUEST_TIMEOUT_40S);
-	if (rc < 0) {
-		dev_err(chg->dev,
-			"Couldn't configure soc request timeout reg rc=%d\n",
-			 rc);
-		goto err_out;
-	}
-
-	rc = smblib_write(chg, STEP_CHG_UPDATE_FAIL_TIMEOUT_CFG_REG,
-			  STEP_CHG_UPDATE_FAIL_TIMEOUT_120S);
-	if (rc < 0) {
-		dev_err(chg->dev,
-			"Couldn't configure soc fail timeout reg rc=%d\n",
-			rc);
-		goto err_out;
-	}
-
-	/*
-	 *  enable step charging, source soc, standard mode, go to final
-	 *  state in case of failure.
-	 */
-	rc = smblib_write(chg, CHGR_STEP_CHG_MODE_CFG_REG,
-			       STEP_CHARGING_ENABLE_BIT |
-			       STEP_CHARGING_SOURCE_SELECT_BIT |
-			       STEP_CHARGING_SOC_FAIL_OPTION_BIT);
-	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't configure charger rc=%d\n", rc);
-		goto err_out;
-	}
-
-	return 0;
-err_out:
-	chg->step_chg_enabled = false;
-	return rc;
-}
-
 static int smb2_config_wipower_input_power(struct smb2 *chip, int uw)
 {
 	int rc;
@@ -1576,7 +1421,7 @@
 {
 	struct smb_charger *chg = &chip->chg;
 	int rc;
-	u8 stat;
+	u8 stat, val;
 
 	if (chip->dt.no_battery)
 		chg->fake_capacity = 50;
@@ -1724,11 +1569,27 @@
 		return rc;
 	}
 
-	/* configure step charging */
-	rc = smb2_config_step_charging(chip);
-	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't configure step charging rc=%d\n",
-			rc);
+	val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT) &
+						BARK_WDOG_TIMEOUT_MASK;
+	val |= BITE_WDOG_TIMEOUT_8S;
+	rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG,
+			BITE_WDOG_DISABLE_CHARGING_CFG_BIT |
+			BARK_WDOG_TIMEOUT_MASK | BITE_WDOG_TIMEOUT_MASK,
+			val);
+	if (rc) {
+		pr_err("Couldn't configue WD config rc=%d\n", rc);
+		return rc;
+	}
+
+	/* enable WD BARK and enable it on plugin */
+	rc = smblib_masked_write(chg, WD_CFG_REG,
+			WATCHDOG_TRIGGER_AFP_EN_BIT |
+			WDOG_TIMER_EN_ON_PLUGIN_BIT |
+			BARK_WDOG_INT_EN_BIT,
+			WDOG_TIMER_EN_ON_PLUGIN_BIT |
+			BARK_WDOG_INT_EN_BIT);
+	if (rc) {
+		pr_err("Couldn't configue WD config rc=%d\n", rc);
 		return rc;
 	}
 
@@ -1787,6 +1648,13 @@
 		return rc;
 	}
 
+	rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
+	if (rc < 0) {
+		dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
+			rc);
+		return rc;
+	}
+
 	switch (chip->dt.chg_inhibit_thr_mv) {
 	case 50:
 		rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
@@ -1851,6 +1719,12 @@
 	struct smb_charger *chg = &chip->chg;
 	int rc;
 
+	/* In case the usb path is suspended, we would have missed disabling
+	 * the icl change interrupt because the interrupt could have been
+	 * not requested
+	 */
+	rerun_election(chg->usb_icl_votable);
+
 	/* configure power role for dual-role */
 	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
 				 TYPEC_POWER_ROLE_CMD_MASK, 0);
@@ -1942,8 +1816,8 @@
 	smblib_handle_usb_source_change(0, &irq_data);
 	smblib_handle_chg_state_change(0, &irq_data);
 	smblib_handle_icl_change(0, &irq_data);
-	smblib_handle_step_chg_state_change(0, &irq_data);
-	smblib_handle_step_chg_soc_update_request(0, &irq_data);
+	smblib_handle_batt_temp_changed(0, &irq_data);
+	smblib_handle_wdog_bark(0, &irq_data);
 
 	return 0;
 }
@@ -1965,18 +1839,15 @@
 	},
 	[STEP_CHG_STATE_CHANGE_IRQ] = {
 		.name		= "step-chg-state-change",
-		.handler	= smblib_handle_step_chg_state_change,
-		.wake		= true,
+		.handler	= NULL,
 	},
 	[STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
 		.name		= "step-chg-soc-update-fail",
-		.handler	= smblib_handle_step_chg_soc_update_fail,
-		.wake		= true,
+		.handler	= NULL,
 	},
 	[STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
 		.name		= "step-chg-soc-update-request",
-		.handler	= smblib_handle_step_chg_soc_update_request,
-		.wake		= true,
+		.handler	= NULL,
 	},
 /* OTG IRQs */
 	[OTG_FAIL_IRQ] = {
@@ -1999,6 +1870,7 @@
 	[BATT_TEMP_IRQ] = {
 		.name		= "bat-temp",
 		.handler	= smblib_handle_batt_temp_changed,
+		.wake		= true,
 	},
 	[BATT_OCP_IRQ] = {
 		.name		= "bat-ocp",
@@ -2094,7 +1966,8 @@
 	},
 	[WDOG_BARK_IRQ] = {
 		.name		= "wdog-bark",
-		.handler	= NULL,
+		.handler	= smblib_handle_wdog_bark,
+		.wake		= true,
 	},
 	[AICL_FAIL_IRQ] = {
 		.name		= "aicl-fail",
@@ -2200,6 +2073,8 @@
 				return rc;
 		}
 	}
+	if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq)
+		chg->usb_icl_change_irq_enabled = true;
 
 	return rc;
 }
@@ -2332,18 +2207,18 @@
 		return rc;
 	}
 
-	rc = smblib_init(chg);
-	if (rc < 0) {
-		pr_err("Smblib_init failed rc=%d\n", rc);
-		goto cleanup;
-	}
-
 	rc = smb2_parse_dt(chip);
 	if (rc < 0) {
 		pr_err("Couldn't parse device tree rc=%d\n", rc);
 		goto cleanup;
 	}
 
+	rc = smblib_init(chg);
+	if (rc < 0) {
+		pr_err("Smblib_init failed rc=%d\n", rc);
+		goto cleanup;
+	}
+
 	/* set driver data before resources request it */
 	platform_set_drvdata(pdev, chip);
 
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 3f26e5e..5ae653e 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -22,6 +22,7 @@
 #include "smb-lib.h"
 #include "smb-reg.h"
 #include "battery.h"
+#include "step-chg-jeita.h"
 #include "storm-watch.h"
 
 #define smblib_err(chg, fmt, ...)		\
@@ -101,35 +102,6 @@
 	return rc;
 }
 
-static int smblib_get_step_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
-{
-	int rc, step_state;
-	u8 stat;
-
-	if (!chg->step_chg_enabled) {
-		*cc_delta_ua = 0;
-		return 0;
-	}
-
-	rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	step_state = (stat & STEP_CHARGING_STATUS_MASK) >>
-				STEP_CHARGING_STATUS_SHIFT;
-	rc = smblib_get_charge_param(chg, &chg->param.step_cc_delta[step_state],
-				     cc_delta_ua);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
-		return rc;
-	}
-
-	return 0;
-}
-
 static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
 {
 	int rc, cc_minus_ua;
@@ -148,7 +120,7 @@
 	}
 
 	rc = smblib_get_charge_param(chg, &chg->param.jeita_cc_comp,
-				     &cc_minus_ua);
+					&cc_minus_ua);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't get jeita cc minus rc=%d\n", rc);
 		return rc;
@@ -401,31 +373,17 @@
 	return rc;
 }
 
-static int step_charge_soc_update(struct smb_charger *chg, int capacity)
-{
-	int rc = 0;
-
-	rc = smblib_set_charge_param(chg, &chg->param.step_soc, capacity);
-	if (rc < 0) {
-		smblib_err(chg, "Error in updating soc, rc=%d\n", rc);
-		return rc;
-	}
-
-	rc = smblib_write(chg, STEP_CHG_SOC_VBATT_V_UPDATE_REG,
-			STEP_CHG_SOC_VBATT_V_UPDATE_BIT);
-	if (rc < 0) {
-		smblib_err(chg,
-			"Couldn't set STEP_CHG_SOC_VBATT_V_UPDATE_REG rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	return rc;
-}
-
 int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend)
 {
 	int rc = 0;
+	int irq = chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq;
+
+	if (suspend && irq) {
+		if (chg->usb_icl_change_irq_enabled) {
+			disable_irq_nosync(irq);
+			chg->usb_icl_change_irq_enabled = false;
+		}
+	}
 
 	rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
 				 suspend ? USBIN_SUSPEND_BIT : 0);
@@ -433,6 +391,13 @@
 		smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n",
 			suspend ? "suspend" : "resume", rc);
 
+	if (!suspend && irq) {
+		if (!chg->usb_icl_change_irq_enabled) {
+			enable_irq(irq);
+			chg->usb_icl_change_irq_enabled = true;
+		}
+	}
+
 	return rc;
 }
 
@@ -522,6 +487,45 @@
 /********************
  * HELPER FUNCTIONS *
  ********************/
+static int smblib_request_dpdm(struct smb_charger *chg, bool enable)
+{
+	int rc = 0;
+
+	/* fetch the DPDM regulator */
+	if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
+				"dpdm-supply", NULL)) {
+		chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
+		if (IS_ERR(chg->dpdm_reg)) {
+			rc = PTR_ERR(chg->dpdm_reg);
+			smblib_err(chg, "Couldn't get dpdm regulator rc=%d\n",
+					rc);
+			chg->dpdm_reg = NULL;
+			return rc;
+		}
+	}
+
+	if (enable) {
+		if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
+			smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
+			rc = regulator_enable(chg->dpdm_reg);
+			if (rc < 0)
+				smblib_err(chg,
+					"Couldn't enable dpdm regulator rc=%d\n",
+					rc);
+		}
+	} else {
+		if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
+			smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
+			rc = regulator_disable(chg->dpdm_reg);
+			if (rc < 0)
+				smblib_err(chg,
+					"Couldn't disable dpdm regulator rc=%d\n",
+					rc);
+		}
+	}
+
+	return rc;
+}
 
 static void smblib_rerun_apsd(struct smb_charger *chg)
 {
@@ -548,10 +552,17 @@
 	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 
 	/* if PD is active, APSD is disabled so won't have a valid result */
-	if (chg->pd_active)
+	if (chg->pd_active) {
 		chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
-	else
+	} else {
+		/*
+		 * Update real charger type only if its not FLOAT
+		 * detected as as SDP
+		 */
+		if (!(apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT &&
+			chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
 		chg->real_charger_type = apsd_result->pst;
+	}
 
 	smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
 					apsd_result->name, chg->pd_active);
@@ -634,13 +645,9 @@
 
 	cancel_delayed_work_sync(&chg->pl_enable_work);
 
-	if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
-		smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
-		rc = regulator_disable(chg->dpdm_reg);
-		if (rc < 0)
-			smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
-				rc);
-	}
+	rc = smblib_request_dpdm(chg, false);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't to disable DPDM rc=%d\n", rc);
 
 	if (chg->wa_flags & BOOST_BACK_WA) {
 		data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
@@ -732,24 +739,9 @@
 	if (!val.intval)
 		return 0;
 
-	/* fetch the DPDM regulator */
-	if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
-						"dpdm-supply", NULL)) {
-		chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
-		if (IS_ERR(chg->dpdm_reg)) {
-			smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
-				PTR_ERR(chg->dpdm_reg));
-			chg->dpdm_reg = NULL;
-		}
-	}
-
-	if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
-		smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
-		rc = regulator_enable(chg->dpdm_reg);
-		if (rc < 0)
-			smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
-				rc);
-	}
+	rc = smblib_request_dpdm(chg, true);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
 
 	chg->uusb_apsd_rerun_done = true;
 	smblib_rerun_apsd(chg);
@@ -819,6 +811,7 @@
 {
 	int rc;
 	u8 icl_options;
+	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 
 	/* power source is SDP */
 	switch (icl_ua) {
@@ -843,6 +836,21 @@
 		return -EINVAL;
 	}
 
+	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB &&
+		apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT) {
+		/*
+		 * change the float charger configuration to SDP, if this
+		 * is the case of SDP being detected as FLOAT
+		 */
+		rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+			FORCE_FLOAT_SDP_CFG_BIT, FORCE_FLOAT_SDP_CFG_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't set float ICL options rc=%d\n",
+						rc);
+			return rc;
+		}
+	}
+
 	rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
 		CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
 	if (rc < 0) {
@@ -884,7 +892,6 @@
 	if (icl_ua < USBIN_25MA)
 		return smblib_set_usb_suspend(chg, true);
 
-	disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq);
 	if (icl_ua == INT_MAX)
 		goto override_suspend_config;
 
@@ -942,7 +949,6 @@
 	}
 
 enable_icl_changed_interrupt:
-	enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq);
 	return rc;
 }
 
@@ -1318,11 +1324,84 @@
 #define MAX_RETRY		15
 #define MIN_DELAY_US		2000
 #define MAX_DELAY_US		9000
+static int otg_current[] = {250000, 500000, 1000000, 1500000};
+static int smblib_enable_otg_wa(struct smb_charger *chg)
+{
+	u8 stat;
+	int rc, i, retry_count = 0, min_delay = MIN_DELAY_US;
+
+	for (i = 0; i < ARRAY_SIZE(otg_current); i++) {
+		smblib_dbg(chg, PR_OTG, "enabling OTG with %duA\n",
+						otg_current[i]);
+		rc = smblib_set_charge_param(chg, &chg->param.otg_cl,
+						otg_current[i]);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't set otg limit rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc);
+			return rc;
+		}
+
+		retry_count = 0;
+		min_delay = MIN_DELAY_US;
+		do {
+			usleep_range(min_delay, min_delay + 100);
+			rc = smblib_read(chg, OTG_STATUS_REG, &stat);
+			if (rc < 0) {
+				smblib_err(chg, "Couldn't read OTG status rc=%d\n",
+							rc);
+				goto out;
+			}
+
+			if (stat & BOOST_SOFTSTART_DONE_BIT) {
+				rc = smblib_set_charge_param(chg,
+					&chg->param.otg_cl, chg->otg_cl_ua);
+				if (rc < 0) {
+					smblib_err(chg, "Couldn't set otg limit rc=%d\n",
+							rc);
+					goto out;
+				}
+				break;
+			}
+			/* increase the delay for following iterations */
+			if (retry_count > 5)
+				min_delay = MAX_DELAY_US;
+
+		} while (retry_count++ < MAX_RETRY);
+
+		if (retry_count >= MAX_RETRY) {
+			smblib_dbg(chg, PR_OTG, "OTG enable failed with %duA\n",
+								otg_current[i]);
+			rc = smblib_write(chg, CMD_OTG_REG, 0);
+			if (rc < 0) {
+				smblib_err(chg, "disable OTG rc=%d\n", rc);
+				goto out;
+			}
+		} else {
+			smblib_dbg(chg, PR_OTG, "OTG enabled\n");
+			return 0;
+		}
+	}
+
+	if (i == ARRAY_SIZE(otg_current)) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	return 0;
+out:
+	smblib_write(chg, CMD_OTG_REG, 0);
+	return rc;
+}
+
 static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev)
 {
 	struct smb_charger *chg = rdev_get_drvdata(rdev);
-	int rc, retry_count = 0, min_delay = MIN_DELAY_US;
-	u8 stat;
+	int rc;
 
 	smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n");
 	rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
@@ -1335,48 +1414,17 @@
 	}
 
 	smblib_dbg(chg, PR_OTG, "enabling OTG\n");
-	rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc);
-		return rc;
-	}
 
 	if (chg->wa_flags & OTG_WA) {
-		/* check for softstart */
-		do {
-			usleep_range(min_delay, min_delay + 100);
-			rc = smblib_read(chg, OTG_STATUS_REG, &stat);
-			if (rc < 0) {
-				smblib_err(chg,
-					"Couldn't read OTG status rc=%d\n",
-					rc);
-				goto out;
-			}
-
-			if (stat & BOOST_SOFTSTART_DONE_BIT) {
-				rc = smblib_set_charge_param(chg,
-					&chg->param.otg_cl, chg->otg_cl_ua);
-				if (rc < 0)
-					smblib_err(chg,
-						"Couldn't set otg limit\n");
-				break;
-			}
-
-			/* increase the delay for following iterations */
-			if (retry_count > 5)
-				min_delay = MAX_DELAY_US;
-		} while (retry_count++ < MAX_RETRY);
-
-		if (retry_count >= MAX_RETRY) {
-			smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n");
-			goto out;
-		}
+		rc = smblib_enable_otg_wa(chg);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc);
+	} else {
+		rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc);
 	}
 
-	return 0;
-out:
-	/* disable OTG if softstart failed */
-	smblib_write(chg, CMD_OTG_REG, 0);
 	return rc;
 }
 
@@ -1522,8 +1570,8 @@
 				union power_supply_propval *val)
 {
 	union power_supply_propval pval = {0, };
-	bool usb_online, dc_online;
-	u8 stat;
+	bool usb_online, dc_online, qnovo_en;
+	u8 stat, pt_en_cmd;
 	int rc;
 
 	rc = smblib_get_prop_usb_online(chg, &pval);
@@ -1591,11 +1639,22 @@
 		smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
 				rc);
 			return rc;
-		}
+	}
 
 	stat &= ENABLE_TRICKLE_BIT | ENABLE_PRE_CHARGING_BIT |
 		 ENABLE_FAST_CHARGING_BIT | ENABLE_FULLON_MODE_BIT;
-	if (!stat)
+
+	rc = smblib_read(chg, QNOVO_PT_ENABLE_CMD_REG, &pt_en_cmd);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read QNOVO_PT_ENABLE_CMD_REG rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	qnovo_en = (bool)(pt_en_cmd & QNOVO_PT_ENABLE_CMD_BIT);
+
+	/* ignore stat7 when qnovo is enabled */
+	if (!qnovo_en && !stat)
 		val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 
 	return 0;
@@ -1755,30 +1814,6 @@
 	return rc;
 }
 
-int smblib_get_prop_step_chg_step(struct smb_charger *chg,
-				union power_supply_propval *val)
-{
-	int rc;
-	u8 stat;
-
-	if (!chg->step_chg_enabled) {
-		val->intval = -1;
-		return 0;
-	}
-
-	rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	val->intval = (stat & STEP_CHARGING_STATUS_MASK) >>
-				STEP_CHARGING_STATUS_SHIFT;
-
-	return rc;
-}
-
 int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
 					union power_supply_propval *val)
 {
@@ -2346,16 +2381,9 @@
 int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
 						union power_supply_propval *val)
 {
-	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 	int rc, pulses;
 
-	val->intval = MICRO_5V;
-	if (apsd_result == NULL) {
-		smblib_err(chg, "APSD result is NULL\n");
-		return 0;
-	}
-
-	switch (apsd_result->pst) {
+	switch (chg->real_charger_type) {
 	case POWER_SUPPLY_TYPE_USB_HVDCP_3:
 		rc = smblib_get_pulse_cnt(chg, &pulses);
 		if (rc < 0) {
@@ -2365,6 +2393,9 @@
 		}
 		val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses;
 		break;
+	case POWER_SUPPLY_TYPE_USB_PD:
+		val->intval = chg->voltage_min_uv;
+		break;
 	default:
 		val->intval = MICRO_5V;
 		break;
@@ -2427,6 +2458,31 @@
 	return 0;
 }
 
+#define SDP_CURRENT_UA			500000
+#define CDP_CURRENT_UA			1500000
+#define DCP_CURRENT_UA			1500000
+#define HVDCP_CURRENT_UA		3000000
+#define TYPEC_DEFAULT_CURRENT_UA	900000
+#define TYPEC_MEDIUM_CURRENT_UA		1500000
+#define TYPEC_HIGH_CURRENT_UA		3000000
+static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
+{
+	int rp_ua;
+
+	switch (typec_mode) {
+	case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
+		rp_ua = TYPEC_HIGH_CURRENT_UA;
+		break;
+	case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
+	case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
+	/* fall through */
+	default:
+		rp_ua = DCP_CURRENT_UA;
+	}
+
+	return rp_ua;
+}
+
 /*******************
  * USB PSY SETTERS *
  * *****************/
@@ -2444,14 +2500,54 @@
 	return rc;
 }
 
+static int smblib_handle_usb_current(struct smb_charger *chg,
+					int usb_current)
+{
+	int rc = 0, rp_ua, typec_mode;
+
+	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
+		if (usb_current == -ETIMEDOUT) {
+			/*
+			 * Valid FLOAT charger, report the current based
+			 * of Rp
+			 */
+			typec_mode = smblib_get_prop_typec_mode(chg);
+			rp_ua = get_rp_based_dcp_current(chg, typec_mode);
+			rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
+								true, rp_ua);
+			if (rc < 0)
+				return rc;
+		} else {
+			/*
+			 * FLOAT charger detected as SDP by USB driver,
+			 * charge with the requested current and update the
+			 * real_charger_type
+			 */
+			chg->real_charger_type = POWER_SUPPLY_TYPE_USB;
+			rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+						true, usb_current);
+			if (rc < 0)
+				return rc;
+			rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
+							false, 0);
+			if (rc < 0)
+				return rc;
+		}
+	} else {
+		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+					true, usb_current);
+	}
+
+	return rc;
+}
+
 int smblib_set_prop_usb_current_max(struct smb_charger *chg,
 				    const union power_supply_propval *val)
 {
 	int rc = 0;
 
 	if (!chg->pd_active) {
-		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
-				true, val->intval);
+		rc = smblib_handle_usb_current(chg, val->intval);
 	} else if (chg->system_suspend_supported) {
 		if (val->intval <= USBIN_25MA)
 			rc = vote(chg->usb_icl_votable,
@@ -2547,6 +2643,7 @@
 	}
 
 	chg->voltage_min_uv = min_uv;
+	power_supply_changed(chg->usb_main_psy);
 	return rc;
 }
 
@@ -2834,46 +2931,72 @@
 	return rc;
 }
 
+static int smblib_recover_from_soft_jeita(struct smb_charger *chg)
+{
+	u8 stat_1, stat_2;
+	int rc;
+
+	rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat_1);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat_2);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	if ((chg->jeita_status && !(stat_2 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK) &&
+		((stat_1 & BATTERY_CHARGER_STATUS_MASK) == TERMINATE_CHARGE))) {
+		/*
+		 * We are moving from JEITA soft -> Normal and charging
+		 * is terminated
+		 */
+		rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG, 0);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't disable charging rc=%d\n",
+						rc);
+			return rc;
+		}
+		rc = smblib_write(chg, CHARGING_ENABLE_CMD_REG,
+						CHARGING_ENABLE_CMD_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't enable charging rc=%d\n",
+						rc);
+			return rc;
+		}
+	}
+
+	chg->jeita_status = stat_2 & BAT_TEMP_STATUS_SOFT_LIMIT_MASK;
+
+	return 0;
+}
+
 /************************
  * USB MAIN PSY GETTERS *
  ************************/
 int smblib_get_prop_fcc_delta(struct smb_charger *chg,
-			       union power_supply_propval *val)
+				union power_supply_propval *val)
 {
-	int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0;
-
-	rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
-		step_cc_delta_ua = 0;
-	} else {
-		hw_cc_delta_ua = step_cc_delta_ua;
-	}
+	int rc, jeita_cc_delta_ua = 0;
 
 	rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc);
 		jeita_cc_delta_ua = 0;
-	} else if (jeita_cc_delta_ua < 0) {
-		/* HW will take the min between JEITA and step charge */
-		hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua);
 	}
 
-	val->intval = hw_cc_delta_ua;
+	val->intval = jeita_cc_delta_ua;
 	return 0;
 }
 
 /************************
  * USB MAIN PSY SETTERS *
  ************************/
-
-#define SDP_CURRENT_UA			500000
-#define CDP_CURRENT_UA			1500000
-#define DCP_CURRENT_UA			1500000
-#define HVDCP_CURRENT_UA		3000000
-#define TYPEC_DEFAULT_CURRENT_UA	900000
-#define TYPEC_MEDIUM_CURRENT_UA		1500000
-#define TYPEC_HIGH_CURRENT_UA		3000000
 int smblib_get_charge_current(struct smb_charger *chg,
 				int *total_current_ua)
 {
@@ -3040,61 +3163,18 @@
 	return IRQ_HANDLED;
 }
 
-irqreturn_t smblib_handle_step_chg_state_change(int irq, void *data)
-{
-	struct smb_irq_data *irq_data = data;
-	struct smb_charger *chg = irq_data->parent_data;
-
-	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
-
-	if (chg->step_chg_enabled)
-		rerun_election(chg->fcc_votable);
-
-	return IRQ_HANDLED;
-}
-
-irqreturn_t smblib_handle_step_chg_soc_update_fail(int irq, void *data)
-{
-	struct smb_irq_data *irq_data = data;
-	struct smb_charger *chg = irq_data->parent_data;
-
-	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
-
-	if (chg->step_chg_enabled)
-		rerun_election(chg->fcc_votable);
-
-	return IRQ_HANDLED;
-}
-
-#define STEP_SOC_REQ_MS	3000
-irqreturn_t smblib_handle_step_chg_soc_update_request(int irq, void *data)
-{
-	struct smb_irq_data *irq_data = data;
-	struct smb_charger *chg = irq_data->parent_data;
-	int rc;
-	union power_supply_propval pval = {0, };
-
-	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
-
-	if (!chg->bms_psy) {
-		schedule_delayed_work(&chg->step_soc_req_work,
-				      msecs_to_jiffies(STEP_SOC_REQ_MS));
-		return IRQ_HANDLED;
-	}
-
-	rc = smblib_get_prop_batt_capacity(chg, &pval);
-	if (rc < 0)
-		smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
-	else
-		step_charge_soc_update(chg, pval.intval);
-
-	return IRQ_HANDLED;
-}
-
 irqreturn_t smblib_handle_batt_temp_changed(int irq, void *data)
 {
 	struct smb_irq_data *irq_data = data;
 	struct smb_charger *chg = irq_data->parent_data;
+	int rc;
+
+	rc = smblib_recover_from_soft_jeita(chg);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't recover chg from soft jeita rc=%d\n",
+				rc);
+		return IRQ_HANDLED;
+	}
 
 	rerun_election(chg->fcc_votable);
 	power_supply_changed(chg->batt_psy);
@@ -3207,25 +3287,10 @@
 	smblib_set_opt_freq_buck(chg, vbus_rising ? chg->chg_freq.freq_5V :
 						chg->chg_freq.freq_removal);
 
-	/* fetch the DPDM regulator */
-	if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
-						"dpdm-supply", NULL)) {
-		chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
-		if (IS_ERR(chg->dpdm_reg)) {
-			smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
-				PTR_ERR(chg->dpdm_reg));
-			chg->dpdm_reg = NULL;
-		}
-	}
-
 	if (vbus_rising) {
-		if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
-			smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
-			rc = regulator_enable(chg->dpdm_reg);
-			if (rc < 0)
-				smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
-					rc);
-		}
+		rc = smblib_request_dpdm(chg, true);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
 
 		/* Schedule work to enable parallel charger */
 		vote(chg->awake_votable, PL_DELAY_VOTER, true, 0);
@@ -3245,13 +3310,9 @@
 			}
 		}
 
-		if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
-			smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
-			rc = regulator_disable(chg->dpdm_reg);
-			if (rc < 0)
-				smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
-					rc);
-		}
+		rc = smblib_request_dpdm(chg, false);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
 	}
 
 	if (chg->micro_usb_mode)
@@ -3472,24 +3533,6 @@
 		   rising ? "rising" : "falling");
 }
 
-static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
-{
-	int rp_ua;
-
-	switch (typec_mode) {
-	case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
-		rp_ua = TYPEC_HIGH_CURRENT_UA;
-		break;
-	case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
-	case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
-	/* fall through */
-	default:
-		rp_ua = DCP_CURRENT_UA;
-	}
-
-	return rp_ua;
-}
-
 static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
 {
 	int typec_mode;
@@ -3515,11 +3558,17 @@
 		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
 		break;
 	case POWER_SUPPLY_TYPE_USB_DCP:
-	case POWER_SUPPLY_TYPE_USB_FLOAT:
 		typec_mode = smblib_get_prop_typec_mode(chg);
 		rp_ua = get_rp_based_dcp_current(chg, typec_mode);
 		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
 		break;
+	case POWER_SUPPLY_TYPE_USB_FLOAT:
+		/*
+		 * limit ICL to 100mA, the USB driver will enumerate to check
+		 * if this is a SDP and appropriately set the current
+		 */
+		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
+		break;
 	case POWER_SUPPLY_TYPE_USB_HVDCP:
 	case POWER_SUPPLY_TYPE_USB_HVDCP_3:
 		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000);
@@ -3655,13 +3704,9 @@
 
 	chg->cc2_detach_wa_active = false;
 
-	if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
-		smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
-		rc = regulator_disable(chg->dpdm_reg);
-		if (rc < 0)
-			smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
-				rc);
-	}
+	rc = smblib_request_dpdm(chg, false);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
 
 	if (chg->wa_flags & BOOST_BACK_WA) {
 		data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
@@ -3720,6 +3765,13 @@
 	chg->pd_hard_reset = 0;
 	chg->typec_legacy_valid = false;
 
+	/* write back the default FLOAT charger configuration */
+	rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+				(u8)FLOAT_OPTIONS_MASK, chg->float_cfg);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't write float charger options rc=%d\n",
+			rc);
+
 	/* reset back to 120mS tCC debounce */
 	rc = smblib_masked_write(chg, MISC_CFG_REG, TCC_DEBOUNCE_20MS_BIT, 0);
 	if (rc < 0)
@@ -3799,10 +3851,14 @@
 		smblib_err(chg, "Couldn't disable APSD_START_ON_CC rc=%d\n",
 									rc);
 
-	if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT)
+	if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT) {
 		typec_sink_insertion(chg);
-	else
+	} else {
+		rc = smblib_request_dpdm(chg, true);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
 		typec_sink_removal(chg);
+	}
 }
 
 static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
@@ -3815,6 +3871,24 @@
 		return;
 
 	/*
+	 * if APSD indicates FLOAT and the USB stack had detected SDP,
+	 * do not respond to Rp changes as we do not confirm that its
+	 * a legacy cable
+	 */
+	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+		return;
+	/*
+	 * We want the ICL vote @ 100mA for a FLOAT charger
+	 * until the detection by the USB stack is complete.
+	 * Ignore the Rp changes unless there is a
+	 * pre-existing valid vote.
+	 */
+	if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT &&
+		get_client_vote(chg->usb_icl_votable,
+			LEGACY_UNKNOWN_VOTER) <= 100000)
+		return;
+
+	/*
 	 * handle Rp change for DCP/FLOAT/OCP.
 	 * Update the current only if the Rp is different from
 	 * the last Rp value.
@@ -4011,10 +4085,15 @@
 	struct smb_charger *chg = irq_data->parent_data;
 	int rc;
 
+	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
+
 	rc = smblib_write(chg, BARK_BITE_WDOG_PET_REG, BARK_BITE_WDOG_PET_BIT);
 	if (rc < 0)
 		smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc);
 
+	if (chg->step_chg_enabled || chg->sw_jeita_enabled)
+		power_supply_changed(chg->batt_psy);
+
 	return IRQ_HANDLED;
 }
 
@@ -4097,22 +4176,6 @@
 		power_supply_changed(chg->batt_psy);
 }
 
-static void step_soc_req_work(struct work_struct *work)
-{
-	struct smb_charger *chg = container_of(work, struct smb_charger,
-						step_soc_req_work.work);
-	union power_supply_propval pval = {0, };
-	int rc;
-
-	rc = smblib_get_prop_batt_capacity(chg, &pval);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
-		return;
-	}
-
-	step_charge_soc_update(chg, pval.intval);
-}
-
 static void clear_hdc_work(struct work_struct *work)
 {
 	struct smb_charger *chg = container_of(work, struct smb_charger,
@@ -4645,7 +4708,6 @@
 	INIT_WORK(&chg->bms_update_work, bms_update_work);
 	INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work);
 	INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work);
-	INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work);
 	INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work);
 	INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work);
 	INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work);
@@ -4667,6 +4729,14 @@
 			return rc;
 		}
 
+		rc = qcom_step_chg_init(chg->step_chg_enabled,
+						chg->sw_jeita_enabled);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't init qcom_step_chg_init rc=%d\n",
+				rc);
+			return rc;
+		}
+
 		rc = smblib_create_votables(chg);
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't create votables rc=%d\n",
@@ -4701,7 +4771,6 @@
 		cancel_work_sync(&chg->bms_update_work);
 		cancel_work_sync(&chg->rdstd_cc2_detach_work);
 		cancel_delayed_work_sync(&chg->hvdcp_detect_work);
-		cancel_delayed_work_sync(&chg->step_soc_req_work);
 		cancel_delayed_work_sync(&chg->clear_hdc_work);
 		cancel_work_sync(&chg->otg_oc_work);
 		cancel_work_sync(&chg->vconn_oc_work);
@@ -4713,6 +4782,7 @@
 		cancel_delayed_work_sync(&chg->bb_removal_work);
 		power_supply_unreg_notifier(&chg->nb);
 		smblib_destroy_votables(chg);
+		qcom_step_chg_deinit();
 		qcom_batt_deinit();
 		break;
 	case PARALLEL_SLAVE:
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index c08d404..5b59597 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -192,9 +192,6 @@
 	struct smb_chg_param	dc_icl_div2_mid_hv;
 	struct smb_chg_param	dc_icl_div2_hv;
 	struct smb_chg_param	jeita_cc_comp;
-	struct smb_chg_param	step_soc_threshold[4];
-	struct smb_chg_param	step_soc;
-	struct smb_chg_param	step_cc_delta[5];
 	struct smb_chg_param	freq_buck;
 	struct smb_chg_param	freq_boost;
 };
@@ -289,7 +286,6 @@
 	struct work_struct	rdstd_cc2_detach_work;
 	struct delayed_work	hvdcp_detect_work;
 	struct delayed_work	ps_change_timeout_work;
-	struct delayed_work	step_soc_req_work;
 	struct delayed_work	clear_hdc_work;
 	struct work_struct	otg_oc_work;
 	struct work_struct	vconn_oc_work;
@@ -312,6 +308,7 @@
 	int			dcp_icl_ua;
 	int			fake_capacity;
 	bool			step_chg_enabled;
+	bool			sw_jeita_enabled;
 	bool			is_hdc;
 	bool			chg_done;
 	bool			micro_usb_mode;
@@ -330,6 +327,9 @@
 	int			fake_input_current_limited;
 	bool			pr_swap_in_progress;
 	int			typec_mode;
+	int			usb_icl_change_irq_enabled;
+	u32			jeita_status;
+	u8			float_cfg;
 
 	/* workaround flag */
 	u32			wa_flags;
@@ -384,9 +384,6 @@
 irqreturn_t smblib_handle_debug(int irq, void *data);
 irqreturn_t smblib_handle_otg_overcurrent(int irq, void *data);
 irqreturn_t smblib_handle_chg_state_change(int irq, void *data);
-irqreturn_t smblib_handle_step_chg_state_change(int irq, void *data);
-irqreturn_t smblib_handle_step_chg_soc_update_fail(int irq, void *data);
-irqreturn_t smblib_handle_step_chg_soc_update_request(int irq, void *data);
 irqreturn_t smblib_handle_batt_temp_changed(int irq, void *data);
 irqreturn_t smblib_handle_batt_psy_changed(int irq, void *data);
 irqreturn_t smblib_handle_usb_psy_changed(int irq, void *data);
@@ -426,9 +423,6 @@
 				union power_supply_propval *val);
 int smblib_get_prop_batt_temp(struct smb_charger *chg,
 				union power_supply_propval *val);
-int smblib_get_prop_step_chg_step(struct smb_charger *chg,
-				union power_supply_propval *val);
-
 int smblib_set_prop_input_suspend(struct smb_charger *chg,
 				const union power_supply_propval *val);
 int smblib_set_prop_batt_capacity(struct smb_charger *chg,
@@ -508,7 +502,7 @@
 void smblib_suspend_on_debug_battery(struct smb_charger *chg);
 int smblib_rerun_apsd_if_required(struct smb_charger *chg);
 int smblib_get_prop_fcc_delta(struct smb_charger *chg,
-			       union power_supply_propval *val);
+				union power_supply_propval *val);
 int smblib_icl_override(struct smb_charger *chg, bool override);
 int smblib_dp_dm(struct smb_charger *chg, int val);
 int smblib_rerun_aicl(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index ca0a2c6..dd949e7 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -845,6 +845,13 @@
 		}
 	}
 
+	/* configure to a fixed 700khz freq to avoid tdie errors */
+	rc = smblib_set_charge_param(chg, &chg->param.freq_buck, 700);
+	if (rc < 0) {
+		pr_err("Couldn't configure 700Khz switch freq rc=%d\n", rc);
+		return rc;
+	}
+
 	/* enable watchdog bark and bite interrupts, and disable the watchdog */
 	rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT
 			| WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT
diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c
new file mode 100644
index 0000000..053aac3
--- /dev/null
+++ b/drivers/power/supply/qcom/step-chg-jeita.c
@@ -0,0 +1,494 @@
+/* Copyright (c) 2017 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) "QCOM-STEPCHG: %s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/pmic-voter.h>
+#include "step-chg-jeita.h"
+
+#define MAX_STEP_CHG_ENTRIES	8
+#define STEP_CHG_VOTER		"STEP_CHG_VOTER"
+#define JEITA_VOTER		"JEITA_VOTER"
+
+#define is_between(left, right, value) \
+		(((left) >= (right) && (left) >= (value) \
+			&& (value) >= (right)) \
+		|| ((left) <= (right) && (left) <= (value) \
+			&& (value) <= (right)))
+
+struct range_data {
+	u32 low_threshold;
+	u32 high_threshold;
+	u32 value;
+};
+
+struct step_chg_cfg {
+	u32			psy_prop;
+	char			*prop_name;
+	int			hysteresis;
+	struct range_data	fcc_cfg[MAX_STEP_CHG_ENTRIES];
+};
+
+struct jeita_fcc_cfg {
+	u32			psy_prop;
+	char			*prop_name;
+	int			hysteresis;
+	struct range_data	fcc_cfg[MAX_STEP_CHG_ENTRIES];
+};
+
+struct jeita_fv_cfg {
+	u32			psy_prop;
+	char			*prop_name;
+	int			hysteresis;
+	struct range_data	fv_cfg[MAX_STEP_CHG_ENTRIES];
+};
+
+struct step_chg_info {
+	ktime_t			step_last_update_time;
+	ktime_t			jeita_last_update_time;
+	bool			step_chg_enable;
+	bool			sw_jeita_enable;
+	int			jeita_fcc_index;
+	int			jeita_fv_index;
+	int			step_index;
+
+	struct votable		*fcc_votable;
+	struct votable		*fv_votable;
+	struct wakeup_source	*step_chg_ws;
+	struct power_supply	*batt_psy;
+	struct delayed_work	status_change_work;
+	struct notifier_block	nb;
+};
+
+static struct step_chg_info *the_chip;
+
+#define STEP_CHG_HYSTERISIS_DELAY_US		5000000 /* 5 secs */
+
+/*
+ * Step Charging Configuration
+ * Update the table based on the battery profile
+ * Supports VBATT and SOC based source
+ * range data must be in increasing ranges and shouldn't overlap
+ */
+static struct step_chg_cfg step_chg_config = {
+	.psy_prop	= POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	.prop_name	= "VBATT",
+	.hysteresis	= 100000, /* 100mV */
+	.fcc_cfg	= {
+		/* VBAT_LOW	VBAT_HIGH	FCC */
+		{3600000,	4000000,	3000000},
+		{4001000,	4200000,	2800000},
+		{4201000,	4400000,	2000000},
+	},
+	/*
+	 *	SOC STEP-CHG configuration example.
+	 *
+	 *	.psy_prop = POWER_SUPPLY_PROP_CAPACITY,
+	 *	.prop_name = "SOC",
+	 *	.fcc_cfg	= {
+	 *		//SOC_LOW	SOC_HIGH	FCC
+	 *		{20,		70,		3000000},
+	 *		{70,		90,		2750000},
+	 *		{90,		100,		2500000},
+	 *	},
+	 */
+};
+
+/*
+ * Jeita Charging Configuration
+ * Update the table based on the battery profile
+ * Please ensure that the TEMP ranges are programmed in the hw so that
+ * an interrupt is issued and a consequent psy changed will cause us to
+ * react immediately.
+ * range data must be in increasing ranges and shouldn't overlap.
+ * Gaps are okay
+ */
+static struct jeita_fcc_cfg jeita_fcc_config = {
+	.psy_prop	= POWER_SUPPLY_PROP_TEMP,
+	.prop_name	= "BATT_TEMP",
+	.hysteresis	= 10, /* 1degC hysteresis */
+	.fcc_cfg	= {
+		/* TEMP_LOW	TEMP_HIGH	FCC */
+		{0,		100,		600000},
+		{101,		200,		2000000},
+		{201,		450,		3000000},
+		{451,		550,		600000},
+	},
+};
+
+static struct jeita_fv_cfg jeita_fv_config = {
+	.psy_prop	= POWER_SUPPLY_PROP_TEMP,
+	.prop_name	= "BATT_TEMP",
+	.hysteresis	= 10, /* 1degC hysteresis */
+	.fv_cfg		= {
+		/* TEMP_LOW	TEMP_HIGH	FCC */
+		{0,		100,		4200000},
+		{101,		450,		4400000},
+		{451,		550,		4200000},
+	},
+};
+
+static bool is_batt_available(struct step_chg_info *chip)
+{
+	if (!chip->batt_psy)
+		chip->batt_psy = power_supply_get_by_name("battery");
+
+	if (!chip->batt_psy)
+		return false;
+
+	return true;
+}
+
+static int get_val(struct range_data *range, int hysteresis, int current_index,
+		int threshold,
+		int *new_index, int *val)
+{
+	int i;
+
+	*new_index = -EINVAL;
+	/* first find the matching index without hysteresis */
+	for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
+		if (is_between(range[i].low_threshold,
+			range[i].high_threshold, threshold)) {
+			*new_index = i;
+			*val = range[i].value;
+		}
+
+	/* if nothing was found, return -ENODATA */
+	if (*new_index == -EINVAL)
+		return -ENODATA;
+	/*
+	 * If we don't have a current_index return this
+	 * newfound value. There is no hysterisis from out of range
+	 * to in range transition
+	 */
+	if (current_index == -EINVAL)
+		return 0;
+
+	/*
+	 * Check for hysteresis if it in the neighbourhood
+	 * of our current index.
+	 */
+	if (*new_index == current_index + 1) {
+		if (threshold < range[*new_index].low_threshold + hysteresis) {
+			/*
+			 * Stay in the current index, threshold is not higher
+			 * by hysteresis amount
+			 */
+			*new_index = current_index;
+			*val = range[current_index].value;
+		}
+	} else if (*new_index == current_index - 1) {
+		if (threshold > range[*new_index].high_threshold - hysteresis) {
+			/*
+			 * stay in the current index, threshold is not lower
+			 * by hysteresis amount
+			 */
+			*new_index = current_index;
+			*val = range[current_index].value;
+		}
+	}
+	return 0;
+}
+
+static int handle_step_chg_config(struct step_chg_info *chip)
+{
+	union power_supply_propval pval = {0, };
+	int rc = 0, fcc_ua = 0;
+	u64 elapsed_us;
+
+	elapsed_us = ktime_us_delta(ktime_get(), chip->step_last_update_time);
+	if (elapsed_us < STEP_CHG_HYSTERISIS_DELAY_US)
+		goto reschedule;
+
+	rc = power_supply_get_property(chip->batt_psy,
+		POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, &pval);
+	if (rc < 0)
+		chip->step_chg_enable = 0;
+	else
+		chip->step_chg_enable = pval.intval;
+
+	if (!chip->step_chg_enable) {
+		if (chip->fcc_votable)
+			vote(chip->fcc_votable, STEP_CHG_VOTER, false, 0);
+		goto update_time;
+	}
+
+	rc = power_supply_get_property(chip->batt_psy,
+				step_chg_config.psy_prop, &pval);
+	if (rc < 0) {
+		pr_err("Couldn't read %s property rc=%d\n",
+				step_chg_config.prop_name, rc);
+		return rc;
+	}
+
+	rc = get_val(step_chg_config.fcc_cfg, step_chg_config.hysteresis,
+			chip->step_index,
+			pval.intval,
+			&chip->step_index,
+			&fcc_ua);
+	if (rc < 0) {
+		/* remove the vote if no step-based fcc is found */
+		if (chip->fcc_votable)
+			vote(chip->fcc_votable, STEP_CHG_VOTER, false, 0);
+		goto update_time;
+	}
+
+	if (!chip->fcc_votable)
+		chip->fcc_votable = find_votable("FCC");
+	if (!chip->fcc_votable)
+		return -EINVAL;
+
+	vote(chip->fcc_votable, STEP_CHG_VOTER, true, fcc_ua);
+
+	pr_debug("%s = %d Step-FCC = %duA\n",
+		step_chg_config.prop_name, pval.intval, fcc_ua);
+
+update_time:
+	chip->step_last_update_time = ktime_get();
+	return 0;
+
+reschedule:
+	/* reschedule 1000uS after the remaining time */
+	return (STEP_CHG_HYSTERISIS_DELAY_US - elapsed_us + 1000);
+}
+
+static int handle_jeita(struct step_chg_info *chip)
+{
+	union power_supply_propval pval = {0, };
+	int rc = 0, fcc_ua = 0, fv_uv = 0;
+	u64 elapsed_us;
+
+	if (!chip->sw_jeita_enable) {
+		if (chip->fcc_votable)
+			vote(chip->fcc_votable, JEITA_VOTER, false, 0);
+		if (chip->fv_votable)
+			vote(chip->fv_votable, JEITA_VOTER, false, 0);
+		return 0;
+	}
+
+	elapsed_us = ktime_us_delta(ktime_get(), chip->jeita_last_update_time);
+	if (elapsed_us < STEP_CHG_HYSTERISIS_DELAY_US)
+		goto reschedule;
+
+	rc = power_supply_get_property(chip->batt_psy,
+				jeita_fcc_config.psy_prop, &pval);
+	if (rc < 0) {
+		pr_err("Couldn't read %s property rc=%d\n",
+				step_chg_config.prop_name, rc);
+		return rc;
+	}
+
+	rc = get_val(jeita_fcc_config.fcc_cfg, jeita_fcc_config.hysteresis,
+			chip->jeita_fcc_index,
+			pval.intval,
+			&chip->jeita_fcc_index,
+			&fcc_ua);
+	if (rc < 0) {
+		/* remove the vote if no step-based fcc is found */
+		if (chip->fcc_votable)
+			vote(chip->fcc_votable, JEITA_VOTER, false, 0);
+		goto update_time;
+	}
+
+	if (!chip->fcc_votable)
+		chip->fcc_votable = find_votable("FCC");
+	if (!chip->fcc_votable)
+		/* changing FCC is a must */
+		return -EINVAL;
+
+	vote(chip->fcc_votable, JEITA_VOTER, true, fcc_ua);
+
+	rc = get_val(jeita_fv_config.fv_cfg, jeita_fv_config.hysteresis,
+			chip->jeita_fv_index,
+			pval.intval,
+			&chip->jeita_fv_index,
+			&fv_uv);
+	if (rc < 0) {
+		/* remove the vote if no step-based fcc is found */
+		if (chip->fv_votable)
+			vote(chip->fv_votable, JEITA_VOTER, false, 0);
+		goto update_time;
+	}
+
+	chip->fv_votable = find_votable("FV");
+	if (!chip->fv_votable)
+		goto update_time;
+
+	vote(chip->fv_votable, JEITA_VOTER, true, fv_uv);
+
+	pr_debug("%s = %d FCC = %duA FV = %duV\n",
+		step_chg_config.prop_name, pval.intval, fcc_ua, fv_uv);
+
+update_time:
+	chip->jeita_last_update_time = ktime_get();
+	return 0;
+
+reschedule:
+	/* reschedule 1000uS after the remaining time */
+	return (STEP_CHG_HYSTERISIS_DELAY_US - elapsed_us + 1000);
+}
+
+static void status_change_work(struct work_struct *work)
+{
+	struct step_chg_info *chip = container_of(work,
+			struct step_chg_info, status_change_work.work);
+	int rc = 0;
+	int reschedule_us;
+	int reschedule_jeita_work_us = 0;
+	int reschedule_step_work_us = 0;
+
+	if (!is_batt_available(chip))
+		return;
+
+	/* skip elapsed_us debounce for handling battery temperature */
+	rc = handle_jeita(chip);
+	if (rc > 0)
+		reschedule_jeita_work_us = rc;
+	else if (rc < 0)
+		pr_err("Couldn't handle sw jeita rc = %d\n", rc);
+
+	rc = handle_step_chg_config(chip);
+	if (rc > 0)
+		reschedule_step_work_us = rc;
+	if (rc < 0)
+		pr_err("Couldn't handle step rc = %d\n", rc);
+
+	reschedule_us = min(reschedule_jeita_work_us, reschedule_step_work_us);
+	if (reschedule_us == 0)
+		__pm_relax(chip->step_chg_ws);
+	else
+		schedule_delayed_work(&chip->status_change_work,
+				usecs_to_jiffies(reschedule_us));
+}
+
+static int step_chg_notifier_call(struct notifier_block *nb,
+		unsigned long ev, void *v)
+{
+	struct power_supply *psy = v;
+	struct step_chg_info *chip = container_of(nb, struct step_chg_info, nb);
+
+	if (ev != PSY_EVENT_PROP_CHANGED)
+		return NOTIFY_OK;
+
+	if ((strcmp(psy->desc->name, "battery") == 0)) {
+		__pm_stay_awake(chip->step_chg_ws);
+		schedule_delayed_work(&chip->status_change_work, 0);
+	}
+
+	return NOTIFY_OK;
+}
+
+static int step_chg_register_notifier(struct step_chg_info *chip)
+{
+	int rc;
+
+	chip->nb.notifier_call = step_chg_notifier_call;
+	rc = power_supply_reg_notifier(&chip->nb);
+	if (rc < 0) {
+		pr_err("Couldn't register psy notifier rc = %d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+int qcom_step_chg_init(bool step_chg_enable, bool sw_jeita_enable)
+{
+	int rc;
+	struct step_chg_info *chip;
+
+	if (the_chip) {
+		pr_err("Already initialized\n");
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->step_chg_ws = wakeup_source_register("qcom-step-chg");
+	if (!chip->step_chg_ws) {
+		rc = -EINVAL;
+		goto cleanup;
+	}
+
+	chip->step_chg_enable = step_chg_enable;
+	chip->sw_jeita_enable = sw_jeita_enable;
+
+	chip->step_index = -EINVAL;
+	chip->jeita_fcc_index = -EINVAL;
+	chip->jeita_fv_index = -EINVAL;
+
+	if (step_chg_enable && (!step_chg_config.psy_prop ||
+				!step_chg_config.prop_name)) {
+		/* fail if step-chg configuration is invalid */
+		pr_err("Step-chg configuration not defined - fail\n");
+		rc = -ENODATA;
+		goto release_wakeup_source;
+	}
+
+	if (sw_jeita_enable && (!jeita_fcc_config.psy_prop ||
+				!jeita_fcc_config.prop_name)) {
+		/* fail if step-chg configuration is invalid */
+		pr_err("Jeita TEMP configuration not defined - fail\n");
+		rc = -ENODATA;
+		goto release_wakeup_source;
+	}
+
+	if (sw_jeita_enable && (!jeita_fv_config.psy_prop ||
+				!jeita_fv_config.prop_name)) {
+		/* fail if step-chg configuration is invalid */
+		pr_err("Jeita TEMP configuration not defined - fail\n");
+		rc = -ENODATA;
+		goto release_wakeup_source;
+	}
+
+	INIT_DELAYED_WORK(&chip->status_change_work, status_change_work);
+
+	rc = step_chg_register_notifier(chip);
+	if (rc < 0) {
+		pr_err("Couldn't register psy notifier rc = %d\n", rc);
+		goto release_wakeup_source;
+	}
+
+	the_chip = chip;
+
+	if (step_chg_enable)
+		pr_info("Step charging enabled. Using %s source\n",
+				step_chg_config.prop_name);
+
+	return 0;
+
+release_wakeup_source:
+	wakeup_source_unregister(chip->step_chg_ws);
+cleanup:
+	kfree(chip);
+	return rc;
+}
+
+void qcom_step_chg_deinit(void)
+{
+	struct step_chg_info *chip = the_chip;
+
+	if (!chip)
+		return;
+
+	cancel_delayed_work_sync(&chip->status_change_work);
+	power_supply_unreg_notifier(&chip->nb);
+	wakeup_source_unregister(chip->step_chg_ws);
+	the_chip = NULL;
+	kfree(chip);
+}
diff --git a/drivers/power/supply/qcom/step-chg-jeita.h b/drivers/power/supply/qcom/step-chg-jeita.h
new file mode 100644
index 0000000..5bb2b99
--- /dev/null
+++ b/drivers/power/supply/qcom/step-chg-jeita.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2017 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 __STEP_CHG_H__
+#define __STEP_CHG_H__
+int qcom_step_chg_init(bool step_chg_enable, bool sw_jeita_enable);
+void qcom_step_chg_deinit(void);
+#endif /* __STEP_CHG_H__ */
diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c
index b1e6a3b..9510016 100644
--- a/drivers/regulator/cpr3-regulator.c
+++ b/drivers/regulator/cpr3-regulator.c
@@ -1316,6 +1316,27 @@
 static int cprh_regulator_aging_adjust(struct cpr3_controller *ctrl);
 
 /**
+ * cpr3_regulator_cprh_initialized() - checks if CPRh has already been
+ *		initialized by the boot loader
+ * @ctrl:		Pointer to the CPR3 controller
+ *
+ * Return: true if CPRh controller is already initialized else false
+ */
+static bool cpr3_regulator_cprh_initialized(struct cpr3_controller *ctrl)
+{
+	u32 reg;
+
+	if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH)
+		return false;
+
+	ctrl->cpr_hw_version = readl_relaxed(ctrl->cpr_ctrl_base
+						+ CPR3_REG_CPR_VERSION);
+	reg = readl_relaxed(ctrl->cpr_ctrl_base + CPRH_REG_CTL(ctrl));
+
+	return reg & CPRH_CTL_OSM_ENABLED;
+}
+
+/**
  * cpr3_regulator_init_cprh() - performs hardware initialization at the
  *		controller and thread level required for CPRh operation.
  * @ctrl:		Pointer to the CPR3 controller
@@ -6459,6 +6480,11 @@
 	}
 	ctrl->cpr_ctrl_base = devm_ioremap(dev, res->start, resource_size(res));
 
+	if (cpr3_regulator_cprh_initialized(ctrl)) {
+		cpr3_err(ctrl, "CPRh controller already initialized by boot loader\n");
+		return -EPERM;
+	}
+
 	if (ctrl->aging_possible_mask) {
 		/*
 		 * Aging possible register address is required if an aging
diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c
index deb0ce5..c393940 100644
--- a/drivers/regulator/cprh-kbss-regulator.c
+++ b/drivers/regulator/cprh-kbss-regulator.c
@@ -38,12 +38,10 @@
 #define SDM660_KBSS_FUSE_CORNERS			5
 
 #define SDM845_KBSS_POWER_CLUSTER_FUSE_CORNERS		4
-#define SDM845_KBSS_PERFORMANCE_CLUSTER_FUSE_CORNERS	3
-/*
- * This must be set to the larger of SDM845_KBSS_POWER_CLUSTER_FUSE_CORNERS and
- * SDM845_KBSS_PERFORMANCE_CLUSTER_FUSE_CORNERS values.
- */
-#define SDM845_KBSS_MAX_FUSE_CORNERS			4
+#define SDM845_V1_KBSS_PERF_CLUSTER_FUSE_CORNERS	3
+#define SDM845_V2_KBSS_PERF_CLUSTER_FUSE_CORNERS	5
+/* This must be set to the largest of SDM845 FUSE_CORNERS values. */
+#define SDM845_KBSS_MAX_FUSE_CORNERS			5
 
 /**
  * struct cprh_kbss_fuses - KBSS specific fuse data
@@ -153,18 +151,38 @@
 #define CPRH_KBSS_PERFORMANCE_CLUSTER_THREAD_ID	0
 
 static const char * const
-cprh_sdm845_kbss_fuse_corner_name[2][SDM845_KBSS_MAX_FUSE_CORNERS] = {
+cprh_sdm845_v1_kbss_fuse_corner_name[2][SDM845_KBSS_MAX_FUSE_CORNERS] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		"LowSVS",
 		"SVS_L1",
 		"NOM_L1",
 		"TURBO",
+		"",
 	},
 	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
 		"SVS",
 		"NOM",
 		"TURBO_L2",
 		"",
+		"",
+	},
+};
+
+static const char * const
+cprh_sdm845_v2_kbss_fuse_corner_name[2][SDM845_KBSS_MAX_FUSE_CORNERS] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		"LowSVS",
+		"SVS_L1",
+		"NOM",
+		"TURBO",
+		"",
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		"LowSVS",
+		"SVS",
+		"NOM_L1",
+		"TURBO_L2",
+		"BINNING",
 	},
 };
 
@@ -334,7 +352,7 @@
  *		 different fuse rows.
  */
 static const struct cpr3_fuse_param
-sdm845_kbss_ro_sel_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
+sdm845_v1_kbss_ro_sel_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
 			{{66, 52, 55}, {} },
@@ -359,7 +377,34 @@
 };
 
 static const struct cpr3_fuse_param
-sdm845_kbss_init_voltage_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
+sdm845_v2_kbss_ro_sel_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
+			{{66, 52, 55}, {} },
+			{{66, 48, 51}, {} },
+			{{66, 44, 47}, {} },
+			{{66, 40, 43}, {} },
+		},
+		[CPRH_KBSS_L3_THREAD_ID] = {
+			{{66, 52, 55}, {} },
+			{{66, 48, 51}, {} },
+			{{66, 44, 47}, {} },
+			{{66, 40, 43}, {} },
+		},
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		[CPRH_KBSS_PERFORMANCE_CLUSTER_THREAD_ID] = {
+			{{73,  5,  8}, {} },
+			{{70, 12, 15}, {} },
+			{{70,  8, 11}, {} },
+			{{70,  4,  7}, {} },
+			{{70,  0,  3}, {} },
+		},
+	},
+};
+
+static const struct cpr3_fuse_param
+sdm845_v1_kbss_init_voltage_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
 			{{67, 10, 15}, {} },
@@ -384,7 +429,34 @@
 };
 
 static const struct cpr3_fuse_param
-sdm845_kbss_target_quot_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
+sdm845_v2_kbss_init_voltage_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
+			{{67, 10, 15}, {} },
+			{{67,  4,  9}, {} },
+			{{66, 62, 63}, {67,  0,  3}, {} },
+			{{66, 56, 61}, {} },
+		},
+		[CPRH_KBSS_L3_THREAD_ID] = {
+			{{68, 50, 55}, {} },
+			{{68, 44, 49}, {} },
+			{{68, 38, 43}, {} },
+			{{68, 32, 37}, {} },
+		},
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		[CPRH_KBSS_PERFORMANCE_CLUSTER_THREAD_ID] = {
+			{{72, 10, 15}, {} },
+			{{70, 34, 39}, {} },
+			{{70, 28, 33}, {} },
+			{{70, 22, 27}, {} },
+			{{70, 16, 21}, {} },
+		},
+	},
+};
+
+static const struct cpr3_fuse_param
+sdm845_v1_kbss_target_quot_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
 			{{67, 52, 63}, {} },
@@ -409,7 +481,34 @@
 };
 
 static const struct cpr3_fuse_param
-sdm845_kbss_quot_offset_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][2] = {
+sdm845_v2_kbss_target_quot_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][3] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
+			{{67, 52, 63}, {} },
+			{{67, 40, 51}, {} },
+			{{67, 28, 39}, {} },
+			{{67, 16, 27}, {} },
+		},
+		[CPRH_KBSS_L3_THREAD_ID] = {
+			{{69, 28, 39}, {} },
+			{{69, 16, 27}, {} },
+			{{69,  4, 15}, {} },
+			{{68, 56, 63}, {69, 0, 3}, {} },
+		},
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		[CPRH_KBSS_PERFORMANCE_CLUSTER_THREAD_ID] = {
+			{{72, 16, 27}, {} },
+			{{71, 12, 23}, {} },
+			{{71,  0, 11}, {} },
+			{{70, 52, 63}, {} },
+			{{70, 40, 51}, {} },
+		},
+	},
+};
+
+static const struct cpr3_fuse_param
+sdm845_v1_kbss_quot_offset_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][2] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
 			{{} },
@@ -433,6 +532,33 @@
 	},
 };
 
+static const struct cpr3_fuse_param
+sdm845_v2_kbss_quot_offset_param[2][2][SDM845_KBSS_MAX_FUSE_CORNERS][2] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
+			{{} },
+			{{68, 16, 23}, {} },
+			{{68,  8, 15}, {} },
+			{{68,  0,  7}, {} },
+		},
+		[CPRH_KBSS_L3_THREAD_ID] = {
+			{{} },
+			{{69, 56, 63}, {} },
+			{{69, 48, 55}, {} },
+			{{69, 40, 47}, {} },
+		},
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		[CPRH_KBSS_PERFORMANCE_CLUSTER_THREAD_ID] = {
+			{{} },
+			{{72, 28, 35}, {} },
+			{{71, 40, 47}, {} },
+			{{71, 32, 39}, {} },
+			{{71, 24, 31}, {} },
+		},
+	},
+};
+
 static const struct cpr3_fuse_param msm8998_cpr_fusing_rev_param[] = {
 	{39, 51, 53},
 	{},
@@ -443,11 +569,16 @@
 	{},
 };
 
-static const struct cpr3_fuse_param sdm845_cpr_fusing_rev_param[] = {
+static const struct cpr3_fuse_param sdm845_v1_cpr_fusing_rev_param[] = {
 	{73, 3, 5},
 	{},
 };
 
+static const struct cpr3_fuse_param sdm845_v2_cpr_fusing_rev_param[] = {
+	{75, 34, 36},
+	{},
+};
+
 static const struct cpr3_fuse_param kbss_speed_bin_param[] = {
 	{38, 29, 31},
 	{},
@@ -490,7 +621,7 @@
 };
 
 static const struct cpr3_fuse_param
-sdm845_kbss_aging_init_quot_diff_param[2][2] = {
+sdm845_v1_kbss_aging_init_quot_diff_param[2][2] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		{68, 21, 28},
 		{},
@@ -501,6 +632,18 @@
 	},
 };
 
+static const struct cpr3_fuse_param
+sdm845_v2_kbss_aging_init_quot_diff_param[2][2] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		{68, 24, 31},
+		{},
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		{71, 48, 55},
+		{},
+	},
+};
+
 /*
  * Open loop voltage fuse reference voltages in microvolts for MSM8998 v1
  */
@@ -556,7 +699,7 @@
  * Open loop voltage fuse reference voltages in microvolts for SDM845
  */
 static const int
-sdm845_kbss_fuse_ref_volt[2][2][SDM845_KBSS_MAX_FUSE_CORNERS] = {
+sdm845_v1_kbss_fuse_ref_volt[2][2][SDM845_KBSS_MAX_FUSE_CORNERS] = {
 	[CPRH_KBSS_POWER_CLUSTER_ID] = {
 		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
 			688000,
@@ -580,6 +723,33 @@
 	},
 };
 
+static const int
+sdm845_v2_kbss_fuse_ref_volt[2][2][SDM845_KBSS_MAX_FUSE_CORNERS] = {
+	[CPRH_KBSS_POWER_CLUSTER_ID] = {
+		[CPRH_KBSS_POWER_CLUSTER_THREAD_ID] = {
+			688000,
+			812000,
+			828000,
+			952000,
+		},
+		[CPRH_KBSS_L3_THREAD_ID] = {
+			688000,
+			812000,
+			828000,
+			952000,
+		},
+	},
+	[CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = {
+		[CPRH_KBSS_PERFORMANCE_CLUSTER_THREAD_ID] = {
+			 688000,
+			 812000,
+			 884000,
+			1000000,
+			1000000,
+		},
+	},
+};
+
 #define CPRH_KBSS_FUSE_STEP_VOLT		10000
 #define CPRH_SDM845_KBSS_FUSE_STEP_VOLT		8000
 #define CPRH_KBSS_VOLTAGE_FUSE_SIZE		6
@@ -880,9 +1050,11 @@
 		struct cprh_kbss_fuses *fuse)
 {
 	void __iomem *base = vreg->thread->ctrl->fuse_base;
+	bool is_v1 = (vreg->thread->ctrl->soc_revision == SDM845_V1_SOC_ID);
 	int i, cid, tid, rc;
 
-	rc = cpr3_read_fuse_param(base, sdm845_cpr_fusing_rev_param,
+	rc = cpr3_read_fuse_param(base, is_v1 ? sdm845_v1_cpr_fusing_rev_param
+					      : sdm845_v2_cpr_fusing_rev_param,
 				&fuse->cpr_fusing_rev);
 	if (rc) {
 		cpr3_err(vreg, "Unable to read CPR fusing revision fuse, rc=%d\n",
@@ -895,8 +1067,9 @@
 	cid = vreg->thread->ctrl->ctrl_id;
 
 	for (i = 0; i < vreg->fuse_corner_count; i++) {
-		rc = cpr3_read_fuse_param(base,
-				sdm845_kbss_init_voltage_param[cid][tid][i],
+		rc = cpr3_read_fuse_param(base, is_v1 ?
+				sdm845_v1_kbss_init_voltage_param[cid][tid][i] :
+				sdm845_v2_kbss_init_voltage_param[cid][tid][i],
 				&fuse->init_voltage[i]);
 		if (rc) {
 			cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n",
@@ -904,8 +1077,9 @@
 			return rc;
 		}
 
-		rc = cpr3_read_fuse_param(base,
-				sdm845_kbss_target_quot_param[cid][tid][i],
+		rc = cpr3_read_fuse_param(base, is_v1 ?
+				sdm845_v1_kbss_target_quot_param[cid][tid][i] :
+				sdm845_v2_kbss_target_quot_param[cid][tid][i],
 				&fuse->target_quot[i]);
 		if (rc) {
 			cpr3_err(vreg, "Unable to read fuse-corner %d target quotient fuse, rc=%d\n",
@@ -913,8 +1087,9 @@
 			return rc;
 		}
 
-		rc = cpr3_read_fuse_param(base,
-				sdm845_kbss_ro_sel_param[cid][tid][i],
+		rc = cpr3_read_fuse_param(base, is_v1 ?
+				sdm845_v1_kbss_ro_sel_param[cid][tid][i] :
+				sdm845_v2_kbss_ro_sel_param[cid][tid][i],
 				&fuse->ro_sel[i]);
 		if (rc) {
 			cpr3_err(vreg, "Unable to read fuse-corner %d RO select fuse, rc=%d\n",
@@ -922,8 +1097,9 @@
 			return rc;
 		}
 
-		rc = cpr3_read_fuse_param(base,
-				sdm845_kbss_quot_offset_param[cid][tid][i],
+		rc = cpr3_read_fuse_param(base, is_v1 ?
+				sdm845_v1_kbss_quot_offset_param[cid][tid][i] :
+				sdm845_v2_kbss_quot_offset_param[cid][tid][i],
 				&fuse->quot_offset[i]);
 		if (rc) {
 			cpr3_err(vreg, "Unable to read fuse-corner %d quotient offset fuse, rc=%d\n",
@@ -932,8 +1108,9 @@
 		}
 	}
 
-	rc = cpr3_read_fuse_param(base,
-				sdm845_kbss_aging_init_quot_diff_param[cid],
+	rc = cpr3_read_fuse_param(base, is_v1 ?
+				sdm845_v1_kbss_aging_init_quot_diff_param[cid] :
+				sdm845_v2_kbss_aging_init_quot_diff_param[cid],
 				&fuse->aging_init_quot_diff);
 	if (rc) {
 		cpr3_err(vreg, "Unable to read aging initial quotient difference fuse, rc=%d\n",
@@ -994,11 +1171,16 @@
 		fuse_corners = MSM8998_KBSS_FUSE_CORNERS;
 		break;
 	case SDM845_V1_SOC_ID:
+		fuse_corners = vreg->thread->ctrl->ctrl_id
+					== CPRH_KBSS_POWER_CLUSTER_ID
+				? SDM845_KBSS_POWER_CLUSTER_FUSE_CORNERS
+				: SDM845_V1_KBSS_PERF_CLUSTER_FUSE_CORNERS;
+		break;
 	case SDM845_V2_SOC_ID:
 		fuse_corners = vreg->thread->ctrl->ctrl_id
 					== CPRH_KBSS_POWER_CLUSTER_ID
 				? SDM845_KBSS_POWER_CLUSTER_FUSE_CORNERS
-				: SDM845_KBSS_PERFORMANCE_CLUSTER_FUSE_CORNERS;
+				: SDM845_V2_KBSS_PERF_CLUSTER_FUSE_CORNERS;
 		break;
 	default:
 		cpr3_err(vreg, "unsupported soc id = %d\n", soc_revision);
@@ -1156,10 +1338,14 @@
 		corner_name = cprh_msm8998_kbss_fuse_corner_name;
 		break;
 	case SDM845_V1_SOC_ID:
+		tid = cprh_kbss_get_thread_id(vreg->thread);
+		ref_volt = sdm845_v1_kbss_fuse_ref_volt[id][tid];
+		corner_name = cprh_sdm845_v1_kbss_fuse_corner_name[id];
+		break;
 	case SDM845_V2_SOC_ID:
 		tid = cprh_kbss_get_thread_id(vreg->thread);
-		ref_volt = sdm845_kbss_fuse_ref_volt[id][tid];
-		corner_name = cprh_sdm845_kbss_fuse_corner_name[id];
+		ref_volt = sdm845_v2_kbss_fuse_ref_volt[id][tid];
+		corner_name = cprh_sdm845_v2_kbss_fuse_corner_name[id];
 		break;
 	default:
 		cpr3_err(vreg, "unsupported soc id = %d\n", soc_revision);
@@ -1744,8 +1930,13 @@
 			CPRH_MSM8998_KBSS_FUSE_CORNER_TURBO_L1;
 		break;
 	case SDM845_V1_SOC_ID:
+		corner_name = cprh_sdm845_v1_kbss_fuse_corner_name[
+						vreg->thread->ctrl->ctrl_id];
+		lowest_fuse_corner = 0;
+		highest_fuse_corner = vreg->fuse_corner_count - 1;
+		break;
 	case SDM845_V2_SOC_ID:
-		corner_name = cprh_sdm845_kbss_fuse_corner_name[
+		corner_name = cprh_sdm845_v2_kbss_fuse_corner_name[
 						vreg->thread->ctrl->ctrl_id];
 		lowest_fuse_corner = 0;
 		highest_fuse_corner = vreg->fuse_corner_count - 1;
diff --git a/drivers/regulator/rpmh-regulator.c b/drivers/regulator/rpmh-regulator.c
index 1ba8926..562b05a 100644
--- a/drivers/regulator/rpmh-regulator.c
+++ b/drivers/regulator/rpmh-regulator.c
@@ -433,6 +433,7 @@
 	bool sleep_set_differs = aggr_vreg->sleep_request_sent;
 	bool wait_for_ack = aggr_vreg->always_wait_for_ack
 				|| aggr_vreg->next_wait_for_ack;
+	bool resend_active = false;
 	int i, j, max_reg_index, rc;
 	enum rpmh_state state;
 	u32 sent_mask;
@@ -471,6 +472,12 @@
 			if ((req_active.reg[i] != req_sleep.reg[i])
 			    && (req_sleep.valid & BIT(i))) {
 				sleep_set_differs = true;
+				/*
+				 * Resend full active set request so that
+				 * all parameters are specified in the wake-only
+				 * state request.
+				 */
+				resend_active = !aggr_vreg->use_awake_state;
 				break;
 			}
 		}
@@ -523,7 +530,7 @@
 		if ((req_active.valid & BIT(i))
 		    && (!(aggr_vreg->aggr_req_active.valid & BIT(i))
 			|| aggr_vreg->aggr_req_active.reg[i]
-				!= req_active.reg[i])) {
+				!= req_active.reg[i] || resend_active)) {
 			cmd[j].addr = aggr_vreg->addr + i * 4;
 			cmd[j].data = req_active.reg[i];
 			j++;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index a06069b..1d57b34 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -384,11 +384,12 @@
 		= container_of(kref, struct scsi_target, reap_ref);
 
 	/*
-	 * if we get here and the target is still in the CREATED state that
+	 * if we get here and the target is still in a CREATED state that
 	 * means it was allocated but never made visible (because a scan
 	 * turned up no LUNs), so don't call device_del() on it.
 	 */
-	if (starget->state != STARGET_CREATED) {
+	if ((starget->state != STARGET_CREATED) &&
+	    (starget->state != STARGET_CREATED_REMOVE)) {
 		transport_remove_device(&starget->dev);
 		device_del(&starget->dev);
 	}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index e90a8e1..f14d95e 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1371,11 +1371,15 @@
 	spin_lock_irqsave(shost->host_lock, flags);
 	list_for_each_entry(starget, &shost->__targets, siblings) {
 		if (starget->state == STARGET_DEL ||
-		    starget->state == STARGET_REMOVE)
+		    starget->state == STARGET_REMOVE ||
+		    starget->state == STARGET_CREATED_REMOVE)
 			continue;
 		if (starget->dev.parent == dev || &starget->dev == dev) {
 			kref_get(&starget->reap_ref);
-			starget->state = STARGET_REMOVE;
+			if (starget->state == STARGET_CREATED)
+				starget->state = STARGET_CREATED_REMOVE;
+			else
+				starget->state = STARGET_REMOVE;
 			spin_unlock_irqrestore(shost->host_lock, flags);
 			__scsi_remove_target(starget);
 			scsi_target_reap(starget);
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 5a578f1..557ca19 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -1469,6 +1469,11 @@
 	hba->debugfs_files.err_occurred = true;
 }
 
+void ufsdbg_clr_err_state(struct ufs_hba *hba)
+{
+	hba->debugfs_files.err_occurred = false;
+}
+
 DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_err_state,
 			ufsdbg_read_err_state,
 			ufsdbg_clear_err_state,
diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
index 13848e8..8ae5eb4 100644
--- a/drivers/scsi/ufs/ufs-debugfs.h
+++ b/drivers/scsi/ufs/ufs-debugfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 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
@@ -38,6 +38,7 @@
 void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset, int num_regs,
 				char *str, void *priv);
 void ufsdbg_set_err_state(struct ufs_hba *hba);
+void ufsdbg_clr_err_state(struct ufs_hba *hba);
 #else
 static inline void ufsdbg_add_debugfs(struct ufs_hba *hba)
 {
@@ -52,6 +53,9 @@
 void ufsdbg_set_err_state(struct ufs_hba *hba)
 {
 }
+void ufsdbg_clr_err_state(struct ufs_hba *hba)
+{
+}
 #endif
 
 #ifdef CONFIG_UFS_FAULT_INJECTION
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f85a67d..0ae51b9 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -65,6 +65,9 @@
 #define UFS_MAX_LUNS		(SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
 #define UFS_UPIU_WLUN_ID	(1 << 7)
 #define UFS_UPIU_MAX_GENERAL_LUN	8
+#define UFS_MAX_WLUS			4
+#define UFS_MAX_LUS	(UFS_UPIU_MAX_GENERAL_LUN + UFS_MAX_WLUS)
+
 #define QUERY_DESC_IDN_CONFIGURATION	QUERY_DESC_IDN_CONFIGURAION
 
 /* Well known logical unit id in LUN field of UPIU */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 370e092..c132dbc 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -331,6 +331,26 @@
 	return ufs_pm_lvl_states[lvl].link_state;
 }
 
+static inline void ufshcd_set_card_online(struct ufs_hba *hba)
+{
+	atomic_set(&hba->card_state, UFS_CARD_STATE_ONLINE);
+}
+
+static inline void ufshcd_set_card_offline(struct ufs_hba *hba)
+{
+	atomic_set(&hba->card_state, UFS_CARD_STATE_OFFLINE);
+}
+
+static inline bool ufshcd_is_card_online(struct ufs_hba *hba)
+{
+	return (atomic_read(&hba->card_state) == UFS_CARD_STATE_ONLINE);
+}
+
+static inline bool ufshcd_is_card_offline(struct ufs_hba *hba)
+{
+	return (atomic_read(&hba->card_state) == UFS_CARD_STATE_OFFLINE);
+}
+
 static inline enum ufs_pm_level
 ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
 					enum uic_link_state link_state)
@@ -384,6 +404,7 @@
 				unsigned long *freq, u32 flags);
 static int ufshcd_devfreq_get_dev_status(struct device *dev,
 		struct devfreq_dev_status *stat);
+static void __ufshcd_shutdown_clkscaling(struct ufs_hba *hba);
 
 #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
 static struct devfreq_simple_ondemand_data ufshcd_ondemand_data = {
@@ -1487,7 +1508,7 @@
 		hba->clk_gating.state = REQ_CLKS_ON;
 		trace_ufshcd_clk_gating(dev_name(hba->dev),
 			hba->clk_gating.state);
-		queue_work(hba->clk_gating.ungating_workq,
+		queue_work(hba->clk_gating.clk_gating_workq,
 				&hba->clk_gating.ungate_work);
 		/*
 		 * fall through to check if we should wait for this
@@ -1755,7 +1776,8 @@
 	struct ufs_hba *hba = container_of(timer, struct ufs_hba,
 					   clk_gating.gate_hrtimer);
 
-	schedule_work(&hba->clk_gating.gate_work);
+	queue_work(hba->clk_gating.clk_gating_workq,
+				&hba->clk_gating.gate_work);
 
 	return HRTIMER_NORESTART;
 }
@@ -1763,7 +1785,7 @@
 static void ufshcd_init_clk_gating(struct ufs_hba *hba)
 {
 	struct ufs_clk_gating *gating = &hba->clk_gating;
-	char wq_name[sizeof("ufs_clk_ungating_00")];
+	char wq_name[sizeof("ufs_clk_gating_00")];
 
 	hba->clk_gating.state = CLKS_ON;
 
@@ -1792,9 +1814,10 @@
 	hrtimer_init(&gating->gate_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	gating->gate_hrtimer.function = ufshcd_clkgate_hrtimer_handler;
 
-	snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_ungating_%d",
+	snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d",
 			hba->host->host_no);
-	hba->clk_gating.ungating_workq = create_singlethread_workqueue(wq_name);
+	hba->clk_gating.clk_gating_workq =
+		create_singlethread_workqueue(wq_name);
 
 	gating->is_enabled = true;
 
@@ -1858,7 +1881,7 @@
 	device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
 	ufshcd_cancel_gate_work(hba);
 	cancel_work_sync(&hba->clk_gating.ungate_work);
-	destroy_workqueue(hba->clk_gating.ungating_workq);
+	destroy_workqueue(hba->clk_gating.clk_gating_workq);
 }
 
 static void ufshcd_set_auto_hibern8_timer(struct ufs_hba *hba, u32 delay)
@@ -2981,6 +3004,12 @@
 		has_read_lock = true;
 	}
 
+	/*
+	 * err might be non-zero here but logic later in this function
+	 * assumes that err is set to 0.
+	 */
+	err = 0;
+
 	spin_lock_irqsave(hba->host->host_lock, flags);
 
 	/* if error handling is in progress, return host busy */
@@ -2989,6 +3018,12 @@
 		goto out_unlock;
 	}
 
+	if (hba->extcon && ufshcd_is_card_offline(hba)) {
+		set_host_byte(cmd, DID_BAD_TARGET);
+		cmd->scsi_done(cmd);
+		goto out_unlock;
+	}
+
 	switch (hba->ufshcd_state) {
 	case UFSHCD_STATE_OPERATIONAL:
 		break;
@@ -5150,6 +5185,14 @@
 out:
 	if (ret)
 		dev_err(hba->dev, "link startup failed %d\n", ret);
+	/*
+	 * For some external cards, link startup succeeds only after few link
+	 * startup attempts and err_state may get set in this case.
+	 * But as the link startup has finally succeded, we are clearing the
+	 * error state.
+	 */
+	else if (hba->extcon)
+		ufsdbg_clr_err_state(hba);
 
 	return ret;
 }
@@ -5594,8 +5637,15 @@
 				__func__, (intr_status & UIC_HIBERNATE_ENTER) ?
 				"Enter" : "Exit",
 				intr_status, ufshcd_get_upmcrs(hba));
-			__ufshcd_print_host_regs(hba, true);
-			ufshcd_print_host_state(hba);
+			/*
+			 * It is possible to see auto-h8 errors during card
+			 * removal, so set this flag and let the error handler
+			 * decide if this error is seen while card was present
+			 * or due to card removal.
+			 * If error is seen during card removal, we don't want
+			 * to printout the debug messages.
+			 */
+			hba->auto_h8_err = true;
 			schedule_work(&hba->eh_work);
 			retval = IRQ_HANDLED;
 		}
@@ -6195,6 +6245,32 @@
 	hba = container_of(work, struct ufs_hba, eh_work);
 
 	spin_lock_irqsave(hba->host->host_lock, flags);
+	if (hba->extcon) {
+		if (ufshcd_is_card_online(hba)) {
+			spin_unlock_irqrestore(hba->host->host_lock, flags);
+			/*
+			 * TODO: need better way to ensure that this delay is
+			 * more than extcon's debounce-ms
+			 */
+			msleep(300);
+			spin_lock_irqsave(hba->host->host_lock, flags);
+		}
+
+		/*
+		 * ignore error if card was online and offline/removed now or
+		 * card was already offline.
+		 */
+		if (ufshcd_is_card_offline(hba)) {
+			hba->saved_err = 0;
+			hba->saved_uic_err = 0;
+			hba->saved_ce_err = 0;
+			hba->auto_h8_err = false;
+			hba->force_host_reset = false;
+			hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+			goto out;
+		}
+	}
+
 	ufsdbg_set_err_state(hba);
 
 	if (hba->ufshcd_state == UFSHCD_STATE_RESET)
@@ -6239,7 +6315,8 @@
 	 * Dump controller state before resetting. Transfer requests state
 	 * will be dump as part of the request completion.
 	 */
-	if (hba->saved_err & (INT_FATAL_ERRORS | UIC_ERROR)) {
+	if ((hba->saved_err & (INT_FATAL_ERRORS | UIC_ERROR)) ||
+	    hba->auto_h8_err) {
 		dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x",
 			__func__, hba->saved_err, hba->saved_uic_err);
 		if (!hba->silence_err_logs) {
@@ -6252,6 +6329,7 @@
 			ufshcd_print_cmd_log(hba);
 			spin_lock_irqsave(hba->host->host_lock, flags);
 		}
+		hba->auto_h8_err = false;
 	}
 
 	if ((hba->saved_err & INT_FATAL_ERRORS)
@@ -6490,7 +6568,10 @@
 			queue_eh_work = true;
 	}
 
-	if (queue_eh_work) {
+	if (hba->extcon && ufshcd_is_card_offline(hba)) {
+		/* ignore UIC errors if card is offline */
+		retval |= IRQ_HANDLED;
+	} else if (queue_eh_work) {
 		/*
 		 * update the transfer error masks to sticky bits, let's do this
 		 * irrespective of current ufshcd_state.
@@ -7836,6 +7917,13 @@
 	if (ret) {
 		ufshcd_set_ufs_dev_poweroff(hba);
 		ufshcd_set_link_off(hba);
+		if (hba->extcon) {
+			if (!ufshcd_is_card_online(hba))
+				ufsdbg_clr_err_state(hba);
+			ufshcd_set_card_offline(hba);
+		}
+	} else if (hba->extcon) {
+		ufshcd_set_card_online(hba);
 	}
 
 	/*
@@ -7851,22 +7939,60 @@
 	return ret;
 }
 
+static void ufshcd_remove_device(struct ufs_hba *hba)
+{
+	struct scsi_device *sdev;
+	struct scsi_device *sdev_cache[UFS_MAX_LUS];
+	int sdev_count = 0, i;
+	unsigned long flags;
+
+	ufshcd_hold_all(hba);
+	/* Reset the host controller */
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->silence_err_logs = true;
+	ufshcd_hba_stop(hba, false);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ufshcd_set_ufs_dev_poweroff(hba);
+	ufshcd_set_link_off(hba);
+	__ufshcd_shutdown_clkscaling(hba);
+
+	/* Complete requests that have door-bell cleared by h/w */
+	ufshcd_complete_requests(hba);
+
+	/* remove all scsi devices */
+	list_for_each_entry(sdev, &hba->host->__devices, siblings) {
+		if (sdev_count < UFS_MAX_LUS) {
+			sdev_cache[sdev_count] = sdev;
+			sdev_count++;
+		}
+	}
+
+	for (i = 0; i < sdev_count; i++)
+		scsi_remove_device(sdev_cache[i]);
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->silence_err_logs = false;
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ufshcd_release_all(hba);
+}
+
 static void ufshcd_card_detect_handler(struct work_struct *work)
 {
 	struct ufs_hba *hba;
 
 	hba = container_of(work, struct ufs_hba, card_detect_work);
-	if (hba->card_detect_event &&
-	    (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL)) {
-		dev_dbg(hba->dev, "%s: card detect notification received\n",
-			 __func__);
+
+	if (ufshcd_is_card_online(hba) && !hba->sdev_ufs_device) {
 		pm_runtime_get_sync(hba->dev);
 		ufshcd_detect_device(hba);
+		/* ufshcd_probe_hba() calls pm_runtime_put_sync() on exit */
+	} else if (ufshcd_is_card_offline(hba) && hba->sdev_ufs_device) {
+		pm_runtime_get_sync(hba->dev);
+		ufshcd_remove_device(hba);
 		pm_runtime_put_sync(hba->dev);
-	} else {
-		dev_dbg(hba->dev, "%s: card removed notification received\n",
-			 __func__);
-		/* TODO: remove the scsi device instances */
+		ufsdbg_clr_err_state(hba);
 	}
 }
 
@@ -7875,9 +8001,23 @@
 {
 	struct ufs_hba *hba = container_of(nb, struct ufs_hba, card_detect_nb);
 
-	hba->card_detect_event = event;
-	schedule_work(&hba->card_detect_work);
+	if (event)
+		ufshcd_set_card_online(hba);
+	else
+		ufshcd_set_card_offline(hba);
 
+	if (ufshcd_is_card_offline(hba) && !hba->sdev_ufs_device)
+		goto out;
+
+	/*
+	 * card insertion/removal are very infrequent events and having this
+	 * message helps if there is some issue with card detection/removal.
+	 */
+	dev_info(hba->dev, "%s: card %s notification rcvd\n",
+		__func__, ufshcd_is_card_online(hba) ? "inserted" : "removed");
+
+	schedule_work(&hba->card_detect_work);
+out:
 	return NOTIFY_DONE;
 }
 
@@ -9156,7 +9296,9 @@
 	if (ret)
 		goto disable_vreg;
 
-	if (ufshcd_is_link_off(hba))
+	if (hba->extcon &&
+	    (ufshcd_is_card_offline(hba) ||
+	     (ufshcd_is_card_online(hba) && !hba->sdev_ufs_device)))
 		goto skip_dev_ops;
 
 	if (ufshcd_is_link_hibern8(hba)) {
@@ -9515,7 +9657,7 @@
 	ufshcd_add_spm_lvl_sysfs_nodes(hba);
 }
 
-static void ufshcd_shutdown_clkscaling(struct ufs_hba *hba)
+static void __ufshcd_shutdown_clkscaling(struct ufs_hba *hba)
 {
 	bool suspend = false;
 	unsigned long flags;
@@ -9532,7 +9674,6 @@
 	 * doesn't race with shutdown
 	 */
 	if (ufshcd_is_clkscaling_supported(hba)) {
-		device_remove_file(hba->dev, &hba->clk_scaling.enable_attr);
 		cancel_work_sync(&hba->clk_scaling.suspend_work);
 		cancel_work_sync(&hba->clk_scaling.resume_work);
 		if (suspend)
@@ -9540,8 +9681,16 @@
 	}
 
 	/* Unregister so that devfreq_monitor can't race with shutdown */
-	if (hba->devfreq)
+	if (hba->devfreq) {
 		devfreq_remove_device(hba->devfreq);
+		hba->devfreq = NULL;
+	}
+}
+
+static void ufshcd_shutdown_clkscaling(struct ufs_hba *hba)
+{
+	__ufshcd_shutdown_clkscaling(hba);
+	device_remove_file(hba->dev, &hba->clk_scaling.enable_attr);
 }
 
 /**
@@ -9876,6 +10025,9 @@
 {
 	int ret = 0;
 
+	if (hba->extcon && ufshcd_is_card_offline(hba))
+		return 0;
+
 	/* let's not get into low power until clock scaling is completed */
 	hba->ufs_stats.clk_hold.ctx = CLK_SCALE_WORK;
 	ufshcd_hold_all(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 343f327..fc855db 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -446,7 +446,7 @@
 	struct device_attribute enable_attr;
 	bool is_enabled;
 	int active_reqs;
-	struct workqueue_struct *ungating_workq;
+	struct workqueue_struct *clk_gating_workq;
 };
 
 /* Hibern8 state  */
@@ -688,6 +688,13 @@
 	u32 seq_num;
 };
 
+/* UFS card state - hotplug state */
+enum ufshcd_card_state {
+	UFS_CARD_STATE_UNKNOWN	= 0,
+	UFS_CARD_STATE_ONLINE	= 1,
+	UFS_CARD_STATE_OFFLINE	= 2,
+};
+
 /**
  * struct ufs_hba - per adapter private structure
  * @mmio_base: UFSHCI base register address
@@ -737,7 +744,7 @@
  * @extcon: pointer to external connector device
  * @card_detect_nb: card detector notifier registered with @extcon
  * @card_detect_work: work to exectute the card detect function
- * @card_detect_event: card detect event, 0 = removed, 1 = inserted
+ * @card_state: card state event, enum ufshcd_card_state defines possible states
  * @vreg_info: UFS device voltage regulator information
  * @clk_list_head: UFS host controller clocks list node head
  * @pwr_info: holds current power mode
@@ -875,6 +882,7 @@
 	u32 saved_ce_err;
 	bool silence_err_logs;
 	bool force_host_reset;
+	bool auto_h8_err;
 
 	/* Device management request data */
 	struct ufs_dev_cmd dev_cmd;
@@ -914,7 +922,7 @@
 	struct extcon_dev *extcon;
 	struct notifier_block card_detect_nb;
 	struct work_struct card_detect_work;
-	unsigned long card_detect_event;
+	atomic_t card_state;
 
 	struct ufs_pa_layer_attr pwr_info;
 	struct ufs_pwr_mode_info max_pwr_info;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 5be06ba..38eff96 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -752,3 +752,10 @@
 	  to Alway On processor using QMP transport.
 
 source "drivers/soc/qcom/memshare/Kconfig"
+
+config QSEE_IPC_IRQ_BRIDGE
+	tristate "QSEE IPC Interrupt Bridge"
+	help
+	  This module enables bridging an Inter-Processor Communication(IPC)
+	  interrupt from a remote subsystem directed towards Qualcomm
+	  Technologies, Inc. Secure Execution Environment(QSEE).
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 9736cdc..2d7d62a 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -79,3 +79,4 @@
 obj-$(CONFIG_QTI_RPM_STATS_LOG) += rpm_stats.o
 obj-$(CONFIG_QCOM_SMCINVOKE) += smcinvoke.o
 obj-$(CONFIG_QMP_DEBUGFS_CLIENT) += qmp-debugfs-client.o
+obj-$(CONFIG_QSEE_IPC_IRQ_BRIDGE) += qsee_ipc_irq_bridge.o
diff --git a/drivers/soc/qcom/early_random.c b/drivers/soc/qcom/early_random.c
index 06601dd..641f70e 100644
--- a/drivers/soc/qcom/early_random.c
+++ b/drivers/soc/qcom/early_random.c
@@ -38,6 +38,7 @@
 	int ret;
 	u32 resp;
 	struct scm_desc desc;
+	u64 bytes_received;
 
 	data.out_buf = (uint8_t *) virt_to_phys(random_buffer);
 	desc.args[0] = (unsigned long) data.out_buf;
@@ -46,18 +47,18 @@
 
 	dmac_flush_range(random_buffer, random_buffer + RANDOM_BUFFER_SIZE);
 
-	if (!is_scm_armv8())
+	if (!is_scm_armv8()) {
 		ret = scm_call_noalloc(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data,
 				sizeof(data), &resp, sizeof(resp),
 				common_scm_buf,
 				SCM_BUFFER_SIZE(common_scm_buf));
-	else
+		bytes_received = resp;
+	} else {
 		ret = scm_call2(SCM_SIP_FNID(TZ_SVC_CRYPTO, PRNG_CMD_ID),
 					&desc);
-
+		bytes_received = desc.ret[0];
+	}
 	if (!ret) {
-		u64 bytes_received = desc.ret[0];
-
 		if (bytes_received != SZ_512)
 			pr_warn("Did not receive the expected number of bytes from PRNG: %llu\n",
 				bytes_received);
diff --git a/drivers/soc/qcom/eud.c b/drivers/soc/qcom/eud.c
index 92dbd48..51c08c6 100644
--- a/drivers/soc/qcom/eud.c
+++ b/drivers/soc/qcom/eud.c
@@ -70,6 +70,7 @@
 	struct extcon_dev		*extcon;
 	struct uart_port		port;
 	struct work_struct		eud_work;
+	struct power_supply		*batt_psy;
 };
 
 static const unsigned int eud_extcon_cable[] = {
@@ -176,17 +177,33 @@
 
 module_param_cb(enable, &eud_param_ops, &enable, 0644);
 
+static bool is_batt_available(struct eud_chip *chip)
+{
+	if (!chip->batt_psy)
+		chip->batt_psy = power_supply_get_by_name("battery");
+
+	if (!chip->batt_psy)
+		return false;
+
+	return true;
+}
+
 static void eud_event_notifier(struct work_struct *eud_work)
 {
 	struct eud_chip *chip = container_of(eud_work, struct eud_chip,
 					eud_work);
+	union power_supply_propval pval;
 
 	if (chip->int_status == EUD_INT_VBUS)
 		extcon_set_state_sync(chip->extcon, chip->extcon_id,
 					chip->usb_attach);
-	else if (chip->int_status == EUD_INT_CHGR)
-		extcon_set_state_sync(chip->extcon, chip->extcon_id,
-					chip->chgr_enable);
+	else if (chip->int_status == EUD_INT_CHGR) {
+		if (is_batt_available(chip)) {
+			pval.intval = !chip->chgr_enable;
+			power_supply_set_property(chip->batt_psy,
+				POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+		}
+	}
 }
 
 static void usb_attach_detach(struct eud_chip *chip)
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index d31bf8d..1d605e3 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -30,7 +30,6 @@
 #include "glink_private.h"
 #include "glink_xprt_if.h"
 
-#define GLINK_CTX_CANARY 0x58544324 /* "$CTX" */
 /* Number of internal IPC Logging log pages */
 #define NUM_LOG_PAGES	10
 #define GLINK_PM_QOS_HOLDOFF_MS		10
@@ -40,7 +39,6 @@
 
 #define GLINK_KTHREAD_PRIO 1
 
-static rwlock_t magic_lock;
 /**
  * struct glink_qos_priority_bin - Packet Scheduler's priority bucket
  * @max_rate_kBps:	Maximum rate supported by the priority bucket.
@@ -232,6 +230,8 @@
  * @req_rate_kBps:			Current QoS request by the channel.
  * @tx_intent_cnt:			Intent count to transmit soon in future.
  * @tx_cnt:				Packets to be picked by tx scheduler.
+ * @rt_vote_on:				Number of times RT vote on is called.
+ * @rt_vote_off:			Number of times RT vote off is called.
  */
 struct channel_ctx {
 	struct rwref_lock ch_state_lhb2;
@@ -312,7 +312,9 @@
 	unsigned long req_rate_kBps;
 	uint32_t tx_intent_cnt;
 	uint32_t tx_cnt;
-	uint32_t magic_number;
+
+	uint32_t rt_vote_on;
+	uint32_t rt_vote_off;
 };
 
 static struct glink_core_if core_impl;
@@ -443,33 +445,15 @@
 
 static int glink_get_ch_ctx(struct channel_ctx *ctx)
 {
-	unsigned long flags;
-
 	if (!ctx)
 		return -EINVAL;
-	read_lock_irqsave(&magic_lock, flags);
-	if (ctx->magic_number != GLINK_CTX_CANARY) {
-		read_unlock_irqrestore(&magic_lock, flags);
-		return -EINVAL;
-	}
 	rwref_get(&ctx->ch_state_lhb2);
-	read_unlock_irqrestore(&magic_lock, flags);
 	return 0;
 }
 
-static int glink_put_ch_ctx(struct channel_ctx *ctx, bool update_magic)
+static void glink_put_ch_ctx(struct channel_ctx *ctx)
 {
-	unsigned long flags;
-
-	if (!update_magic) {
-		rwref_put(&ctx->ch_state_lhb2);
-		return 0;
-	}
-	write_lock_irqsave(&magic_lock, flags);
-	ctx->magic_number = 0;
 	rwref_put(&ctx->ch_state_lhb2);
-	write_unlock_irqrestore(&magic_lock, flags);
-	return 0;
 }
 
 /**
@@ -1931,13 +1915,13 @@
 		}
 
 		ctx->transport_ptr = xprt_ctx;
+		rwref_get(&ctx->ch_state_lhb2);
 		list_add_tail(&ctx->port_list_node, &xprt_ctx->channels);
 
 		GLINK_INFO_PERF_CH_XPRT(ctx, xprt_ctx,
 			"%s: local:GLINK_CHANNEL_CLOSED\n",
 			__func__);
 	}
-	rwref_get(&ctx->ch_state_lhb2);
 	spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
 	rwref_write_put(&xprt_ctx->xprt_state_lhb0);
 	mutex_lock(&xprt_ctx->xprt_dbgfs_lock_lhb4);
@@ -2419,6 +2403,25 @@
 }
 
 /**
+ * dummy_rx_rt_vote() - Dummy RX Realtime thread vote
+ * @if_ptr:	The transport to transmit on.
+
+ */
+static int dummy_rx_rt_vote(struct glink_transport_if *if_ptr)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
+ * dummy_rx_rt_unvote() - Dummy RX Realtime thread unvote
+ * @if_ptr:	The transport to transmit on.
+ */
+static int dummy_rx_rt_unvote(struct glink_transport_if *if_ptr)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
  * notif_if_up_all_xprts() - Check and notify existing transport state if up
  * @notif_info:	Data structure containing transport information to be notified.
  *
@@ -2600,7 +2603,6 @@
 	ctx->notify_tx_abort = cfg->notify_tx_abort;
 	ctx->notify_rx_tracer_pkt = cfg->notify_rx_tracer_pkt;
 	ctx->notify_remote_rx_intent = cfg->notify_remote_rx_intent;
-	ctx->magic_number = GLINK_CTX_CANARY;
 
 	if (!ctx->notify_rx_intent_req)
 		ctx->notify_rx_intent_req = glink_dummy_notify_rx_intent_req;
@@ -2742,13 +2744,13 @@
 
 	GLINK_INFO_CH(ctx, "%s: Closing channel, ctx: %p\n", __func__, ctx);
 	if (ctx->local_open_state == GLINK_CHANNEL_CLOSED) {
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return 0;
 	}
 
 	if (ctx->local_open_state == GLINK_CHANNEL_CLOSING) {
 		/* close already pending */
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
@@ -2813,7 +2815,7 @@
 
 	rwref_put(&ctx->ch_state_lhb2);
 	rwref_read_put(&xprt_ctx->xprt_state_lhb0);
-	glink_put_ch_ctx(ctx, true);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_close);
@@ -3029,13 +3031,13 @@
 		xprt_schedule_tx(ctx->transport_ptr, ctx, tx_info);
 
 	rwref_read_put(&ctx->ch_state_lhb2);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 
 glink_tx_common_err:
 	rwref_read_put(&ctx->ch_state_lhb2);
 glink_tx_common_err_2:
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	kfree(tx_info);
 	return ret;
 }
@@ -3085,7 +3087,7 @@
 		/* Can only queue rx intents if channel is fully opened */
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
@@ -3094,14 +3096,14 @@
 		GLINK_ERR_CH(ctx,
 			"%s: Intent pointer allocation failed size[%zu]\n",
 			__func__, size);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -ENOMEM;
 	}
 	GLINK_DBG_CH(ctx, "%s: L[%u]:%zu\n", __func__, intent_ptr->id,
 			intent_ptr->intent_size);
 
 	if (ctx->transport_ptr->capabilities & GCAP_INTENTLESS) {
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return ret;
 	}
 
@@ -3111,7 +3113,7 @@
 	if (ret)
 		/* unable to transmit, dequeue intent */
 		ch_remove_local_rx_intent(ctx, intent_ptr->id);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_queue_rx_intent);
@@ -3143,12 +3145,12 @@
 		if (size <= intent->intent_size) {
 			spin_unlock_irqrestore(
 				&ctx->local_rx_intent_lst_lock_lhc1, flags);
-			glink_put_ch_ctx(ctx, false);
+			glink_put_ch_ctx(ctx);
 			return true;
 		}
 	}
 	spin_unlock_irqrestore(&ctx->local_rx_intent_lst_lock_lhc1, flags);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return false;
 }
 EXPORT_SYMBOL(glink_rx_intent_exists);
@@ -3177,7 +3179,7 @@
 	if (IS_ERR_OR_NULL(liid_ptr)) {
 		/* invalid pointer */
 		GLINK_ERR_CH(ctx, "%s: Invalid pointer %p\n", __func__, ptr);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EINVAL;
 	}
 
@@ -3203,7 +3205,7 @@
 	/* send rx done */
 	ctx->transport_ptr->ops->tx_cmd_local_rx_done(ctx->transport_ptr->ops,
 			ctx->lcid, id, reuse);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_rx_done);
@@ -3257,7 +3259,7 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
@@ -3267,7 +3269,7 @@
 			ctx->lcid, ctx->lsigs);
 	GLINK_INFO_CH(ctx, "%s: Sent SIGNAL SET command\n", __func__);
 
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_sigs_set);
@@ -3293,12 +3295,12 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
 	*sigs = ctx->lsigs;
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return 0;
 }
 EXPORT_SYMBOL(glink_sigs_local_get);
@@ -3325,12 +3327,12 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
 	*sigs = ctx->rsigs;
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return 0;
 }
 EXPORT_SYMBOL(glink_sigs_remote_get);
@@ -3434,7 +3436,7 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
@@ -3444,7 +3446,7 @@
 	if (ret < 0)
 		GLINK_ERR_CH(ctx, "%s: QoS %lu:%zu cannot be met\n",
 			     __func__, latency_us, pkt_size);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_qos_latency);
@@ -3468,12 +3470,12 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
 	ret = glink_qos_reset_priority(ctx);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_qos_cancel);
@@ -3500,7 +3502,7 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EBUSY;
 	}
 
@@ -3509,7 +3511,7 @@
 	ret = glink_qos_add_ch_tx_intent(ctx);
 	spin_unlock(&ctx->tx_lists_lock_lhc3);
 	spin_unlock_irqrestore(&ctx->transport_ptr->tx_ready_lock_lhb3, flags);
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ret;
 }
 EXPORT_SYMBOL(glink_qos_start);
@@ -3537,11 +3539,11 @@
 	if (!ch_is_fully_opened(ctx)) {
 		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
 			__func__);
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return (unsigned long)-EBUSY;
 	}
 
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ctx->transport_ptr->ops->get_power_vote_ramp_time(
 			ctx->transport_ptr->ops,
 			glink_prio_to_power_state(ctx->transport_ptr,
@@ -3549,6 +3551,61 @@
 }
 EXPORT_SYMBOL(glink_qos_get_ramp_time);
 
+
+/**
+ * glink_start_rx_rt() - Vote for RT thread priority on RX.
+ * @handle:	Channel handle for which transaction are occurring.
+ *
+ * Return: 0 on success, standard Linux error codes on failure
+ */
+int glink_start_rx_rt(void *handle)
+{
+	struct channel_ctx *ctx = (struct channel_ctx *)handle;
+	int ret;
+
+	ret = glink_get_ch_ctx(ctx);
+	if (ret)
+		return ret;
+	if (!ch_is_fully_opened(ctx)) {
+		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
+			__func__);
+		glink_put_ch_ctx(ctx);
+		return -EBUSY;
+	}
+	ret = ctx->transport_ptr->ops->rx_rt_vote(ctx->transport_ptr->ops);
+	ctx->rt_vote_on++;
+	GLINK_INFO_CH(ctx, "%s: Voting RX Realtime Thread %d", __func__, ret);
+	glink_put_ch_ctx(ctx);
+	return ret;
+}
+
+/**
+ * glink_end_rx_rt() - Vote for RT thread priority on RX.
+ * @handle:	Channel handle for which transaction are occurring.
+ *
+ * Return: 0 on success, standard Linux error codes on failure
+ */
+int glink_end_rx_rt(void *handle)
+{
+	struct channel_ctx *ctx = (struct channel_ctx *)handle;
+	int ret;
+
+	ret = glink_get_ch_ctx(ctx);
+	if (ret)
+		return ret;
+	if (!ch_is_fully_opened(ctx)) {
+		GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n",
+			__func__);
+		glink_put_ch_ctx(ctx);
+		return -EBUSY;
+	}
+	ret = ctx->transport_ptr->ops->rx_rt_unvote(ctx->transport_ptr->ops);
+	ctx->rt_vote_off++;
+	GLINK_INFO_CH(ctx, "%s: Unvoting RX Realtime Thread %d", __func__, ret);
+	glink_put_ch_ctx(ctx);
+	return ret;
+}
+
 /**
  * glink_rpm_rx_poll() - Poll and receive any available events
  * @handle:	Channel handle in which this operation is performed.
@@ -3631,10 +3688,10 @@
 	if (ret)
 		return ret;
 	if (!ctx->transport_ptr) {
-		glink_put_ch_ctx(ctx, false);
+		glink_put_ch_ctx(ctx);
 		return -EOPNOTSUPP;
 	}
-	glink_put_ch_ctx(ctx, false);
+	glink_put_ch_ctx(ctx);
 	return ctx->transport_ptr->ops->wait_link_down(ctx->transport_ptr->ops);
 }
 EXPORT_SYMBOL(glink_wait_link_down);
@@ -3956,6 +4013,10 @@
 		if_ptr->power_vote = dummy_power_vote;
 	if (!if_ptr->power_unvote)
 		if_ptr->power_unvote = dummy_power_unvote;
+	if (!if_ptr->rx_rt_vote)
+		if_ptr->rx_rt_vote = dummy_rx_rt_vote;
+	if (!if_ptr->rx_rt_unvote)
+		if_ptr->rx_rt_unvote = dummy_rx_rt_unvote;
 	xprt_ptr->capabilities = 0;
 	xprt_ptr->ops = if_ptr;
 	spin_lock_init(&xprt_ptr->xprt_ctx_lock_lhb1);
@@ -6175,7 +6236,6 @@
 static int glink_init(void)
 {
 	log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "glink", 0);
-	rwlock_init(&magic_lock);
 	if (!log_ctx)
 		GLINK_ERR("%s: unable to create log context\n", __func__);
 	glink_debugfs_init();
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index 94dffa5..384347d 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -182,6 +182,8 @@
  * @deferred_cmds:		List of deferred commands that need to be
  *				processed in process context.
  * @deferred_cmds_cnt:		Number of deferred commands in queue.
+ * @rt_vote_lock:		Serialize access to RT rx votes
+ * @rt_votes:			Vote count for RT rx thread priority
  * @num_pw_states:		Size of @ramp_time_us.
  * @ramp_time_us:		Array of ramp times in microseconds where array
  *				index position represents a power state.
@@ -221,6 +223,8 @@
 	spinlock_t rx_lock;
 	struct list_head deferred_cmds;
 	uint32_t deferred_cmds_cnt;
+	spinlock_t rt_vote_lock;
+	uint32_t rt_votes;
 	uint32_t num_pw_states;
 	unsigned long *ramp_time_us;
 	struct mailbox_config_info *mailbox;
@@ -2125,6 +2129,52 @@
 }
 
 /**
+ * rx_rt_vote() - Increment and RX thread RT vote
+ * @if_ptr:	The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int rx_rt_vote(struct glink_transport_if *if_ptr)
+{
+	struct edge_info *einfo;
+	struct sched_param param = { .sched_priority = 1 };
+	int ret = 0;
+	unsigned long flags;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+	spin_lock_irqsave(&einfo->rt_vote_lock, flags);
+	if (!einfo->rt_votes)
+		ret = sched_setscheduler_nocheck(einfo->task, SCHED_FIFO,
+							&param);
+	einfo->rt_votes++;
+	spin_unlock_irqrestore(&einfo->rt_vote_lock, flags);
+	return ret;
+}
+
+/**
+ * rx_rt_unvote() - Remove a RX thread RT vote
+ * @if_ptr:	The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int rx_rt_unvote(struct glink_transport_if *if_ptr)
+{
+	struct edge_info *einfo;
+	struct sched_param param = { .sched_priority = 0 };
+	int ret = 0;
+	unsigned long flags;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+	spin_lock_irqsave(&einfo->rt_vote_lock, flags);
+	einfo->rt_votes--;
+	if (!einfo->rt_votes)
+		ret = sched_setscheduler_nocheck(einfo->task, SCHED_NORMAL,
+							&param);
+	spin_unlock_irqrestore(&einfo->rt_vote_lock, flags);
+	return ret;
+}
+
+/**
  * negotiate_features_v1() - determine what features of a version can be used
  * @if_ptr:	The transport for which features are negotiated for.
  * @version:	The version negotiated.
@@ -2169,6 +2219,8 @@
 	einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time;
 	einfo->xprt_if.power_vote = power_vote;
 	einfo->xprt_if.power_unvote = power_unvote;
+	einfo->xprt_if.rx_rt_vote = rx_rt_vote;
+	einfo->xprt_if.rx_rt_unvote = rx_rt_unvote;
 }
 
 /**
@@ -2341,6 +2393,8 @@
 	init_srcu_struct(&einfo->use_ref);
 	spin_lock_init(&einfo->rx_lock);
 	INIT_LIST_HEAD(&einfo->deferred_cmds);
+	spin_lock_init(&einfo->rt_vote_lock);
+	einfo->rt_votes = 0;
 
 	mutex_lock(&probe_lock);
 	if (edge_infos[einfo->remote_proc_id]) {
diff --git a/drivers/soc/qcom/glink_xprt_if.h b/drivers/soc/qcom/glink_xprt_if.h
index f4d5a3b..47c1580 100644
--- a/drivers/soc/qcom/glink_xprt_if.h
+++ b/drivers/soc/qcom/glink_xprt_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -141,6 +141,8 @@
 			struct glink_transport_if *if_ptr, uint32_t state);
 	int (*power_vote)(struct glink_transport_if *if_ptr, uint32_t state);
 	int (*power_unvote)(struct glink_transport_if *if_ptr);
+	int (*rx_rt_vote)(struct glink_transport_if *if_ptr);
+	int (*rx_rt_unvote)(struct glink_transport_if *if_ptr);
 	/*
 	 * Keep data pointers at the end of the structure after all function
 	 * pointer to allow for in-place initialization.
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 0b6c80d..a2ab266 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -84,34 +84,58 @@
 	} while (0)
 
 #define icnss_pr_err(_fmt, ...) do {					\
-		pr_err(_fmt, ##__VA_ARGS__);				\
-		icnss_ipc_log_string("ERR: " pr_fmt(_fmt),		\
-				     ##__VA_ARGS__);			\
+	printk("%s" pr_fmt(_fmt), KERN_ERR, ##__VA_ARGS__);		\
+	icnss_ipc_log_string("%s" pr_fmt(_fmt), "",			\
+			     ##__VA_ARGS__);				\
 	} while (0)
 
 #define icnss_pr_warn(_fmt, ...) do {					\
-		pr_warn(_fmt, ##__VA_ARGS__);				\
-		icnss_ipc_log_string("WRN: " pr_fmt(_fmt),		\
-				     ##__VA_ARGS__);			\
+	printk("%s" pr_fmt(_fmt), KERN_WARNING, ##__VA_ARGS__);		\
+	icnss_ipc_log_string("%s" pr_fmt(_fmt), "",			\
+			     ##__VA_ARGS__);				\
 	} while (0)
 
 #define icnss_pr_info(_fmt, ...) do {					\
-		pr_info(_fmt, ##__VA_ARGS__);				\
-		icnss_ipc_log_string("INF: " pr_fmt(_fmt),		\
-				     ##__VA_ARGS__);			\
+	printk("%s" pr_fmt(_fmt), KERN_INFO, ##__VA_ARGS__);		\
+	icnss_ipc_log_string("%s" pr_fmt(_fmt), "",			\
+			     ##__VA_ARGS__);				\
 	} while (0)
 
+#if defined(CONFIG_DYNAMIC_DEBUG)
 #define icnss_pr_dbg(_fmt, ...) do {					\
-		pr_debug(_fmt, ##__VA_ARGS__);				\
-		icnss_ipc_log_string("DBG: " pr_fmt(_fmt),		\
-				     ##__VA_ARGS__);			\
+	pr_debug(_fmt, ##__VA_ARGS__);					\
+	icnss_ipc_log_string(pr_fmt(_fmt), ##__VA_ARGS__);		\
 	} while (0)
 
 #define icnss_pr_vdbg(_fmt, ...) do {					\
-		pr_debug(_fmt, ##__VA_ARGS__);				\
-		icnss_ipc_log_long_string("DBG: " pr_fmt(_fmt),		\
-				     ##__VA_ARGS__);			\
+	pr_debug(_fmt, ##__VA_ARGS__);					\
+	icnss_ipc_log_long_string(pr_fmt(_fmt), ##__VA_ARGS__);		\
 	} while (0)
+#elif defined(DEBUG)
+#define icnss_pr_dbg(_fmt, ...) do {					\
+	printk("%s" pr_fmt(_fmt), KERN_DEBUG, ##__VA_ARGS__);		\
+	icnss_ipc_log_string("%s" pr_fmt(_fmt), "",			\
+			     ##__VA_ARGS__);				\
+	} while (0)
+
+#define icnss_pr_vdbg(_fmt, ...) do {					\
+	printk("%s" pr_fmt(_fmt), KERN_DEBUG, ##__VA_ARGS__);		\
+	icnss_ipc_log_long_string("%s" pr_fmt(_fmt), "",		\
+				  ##__VA_ARGS__);			\
+	} while (0)
+#else
+#define icnss_pr_dbg(_fmt, ...) do {					\
+	no_printk("%s" pr_fmt(_fmt), KERN_DEBUG, ##__VA_ARGS__);	\
+	icnss_ipc_log_string("%s" pr_fmt(_fmt), "",			\
+		     ##__VA_ARGS__);					\
+	} while (0)
+
+#define icnss_pr_vdbg(_fmt, ...) do {					\
+	no_printk("%s" pr_fmt(_fmt), KERN_DEBUG, ##__VA_ARGS__);	\
+	icnss_ipc_log_long_string("%s" pr_fmt(_fmt), "",		\
+				  ##__VA_ARGS__);			\
+	} while (0)
+#endif
 
 #ifdef CONFIG_ICNSS_DEBUG
 #define ICNSS_ASSERT(_condition) do {					\
@@ -242,7 +266,6 @@
 struct icnss_event_pd_service_down_data {
 	bool crashed;
 	bool fw_rejuvenate;
-	bool wdog_bite;
 };
 
 struct icnss_driver_event {
@@ -267,7 +290,6 @@
 	ICNSS_PD_RESTART,
 	ICNSS_MSA0_ASSIGNED,
 	ICNSS_WLFW_EXISTS,
-	ICNSS_WDOG_BITE,
 	ICNSS_SHUTDOWN_DONE,
 	ICNSS_HOST_TRIGGERED_PDR,
 };
@@ -2125,10 +2147,7 @@
 
 	icnss_pm_relax(priv);
 
-	if (test_bit(ICNSS_WDOG_BITE, &priv->state)) {
-		icnss_call_driver_shutdown(priv);
-		clear_bit(ICNSS_WDOG_BITE, &priv->state);
-	}
+	icnss_call_driver_shutdown(priv);
 
 	clear_bit(ICNSS_PD_RESTART, &priv->state);
 
@@ -2278,8 +2297,7 @@
 static int icnss_fw_crashed(struct icnss_priv *priv,
 			    struct icnss_event_pd_service_down_data *event_data)
 {
-	icnss_pr_dbg("FW crashed, state: 0x%lx, wdog_bite: %d\n",
-		     priv->state, event_data->wdog_bite);
+	icnss_pr_dbg("FW crashed, state: 0x%lx\n", priv->state);
 
 	set_bit(ICNSS_PD_RESTART, &priv->state);
 	clear_bit(ICNSS_FW_READY, &priv->state);
@@ -2289,17 +2307,9 @@
 	if (test_bit(ICNSS_DRIVER_PROBED, &priv->state))
 		icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_CRASHED, NULL);
 
-	if (event_data->wdog_bite) {
-		set_bit(ICNSS_WDOG_BITE, &priv->state);
-		goto out;
-	}
-
-	icnss_call_driver_shutdown(priv);
-
 	if (event_data->fw_rejuvenate)
 		wlfw_rejuvenate_ack_send_sync_msg(priv);
 
-out:
 	return 0;
 }
 
@@ -2496,9 +2506,6 @@
 
 	event_data->crashed = notif->crashed;
 
-	if (notif->crashed == CRASH_STATUS_WDOG_BITE)
-		event_data->wdog_bite = true;
-
 	fw_down_data.crashed = !!notif->crashed;
 	icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN, &fw_down_data);
 
@@ -2588,7 +2595,6 @@
 
 	switch (*state) {
 	case ROOT_PD_WDOG_BITE:
-		event_data->wdog_bite = true;
 		priv->stats.recovery.root_pd_crash++;
 		break;
 	case ROOT_PD_SHUTDOWN:
@@ -3822,9 +3828,6 @@
 		case ICNSS_WLFW_EXISTS:
 			seq_puts(s, "WLAN FW EXISTS");
 			continue;
-		case ICNSS_WDOG_BITE:
-			seq_puts(s, "MODEM WDOG BITE");
-			continue;
 		case ICNSS_SHUTDOWN_DONE:
 			seq_puts(s, "SHUTDOWN DONE");
 			continue;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_dbg.c b/drivers/soc/qcom/msm_bus/msm_bus_dbg.c
index 015edb3..df29233 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_dbg.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_dbg.c
@@ -38,6 +38,7 @@
 static struct dentry *clients;
 static struct dentry *dir;
 static DEFINE_MUTEX(msm_bus_dbg_fablist_lock);
+static DEFINE_RT_MUTEX(msm_bus_dbg_cllist_lock);
 struct msm_bus_dbg_state {
 	uint32_t cl;
 	uint8_t enable;
@@ -289,7 +290,9 @@
 	struct msm_bus_cldata *cldata = NULL;
 	const struct msm_bus_client_handle *handle = file->private_data;
 	int found = 0;
+	ssize_t ret;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if ((cldata->clid == cl) ||
 			(cldata->handle && (cldata->handle == handle))) {
@@ -298,12 +301,17 @@
 		}
 	}
 
-	if (!found)
+	if (!found) {
+		rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 		return 0;
+	}
 
 	bsize = cldata->size;
-	return simple_read_from_buffer(buf, count, ppos,
+	ret = simple_read_from_buffer(buf, count, ppos,
 		cldata->buffer, bsize);
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+
+	return ret;
 }
 
 static int client_data_open(struct inode *inode, struct file *file)
@@ -339,7 +347,9 @@
 		return -ENOMEM;
 	}
 	cldata->handle = pdata;
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_add_tail(&cldata->list, &cl_list);
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 	return 0;
 }
 
@@ -352,6 +362,7 @@
 	bool found = false;
 	char *buf = NULL;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->handle == pdata) {
 			found = true;
@@ -359,12 +370,15 @@
 		}
 	}
 
-	if (!found)
+	if (!found) {
+		rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 		return -ENOENT;
+	}
 
 	if (cldata->file == NULL) {
 		if (pdata->name == NULL) {
 			MSM_BUS_DBG("Client doesn't have a name\n");
+			rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 			return -EINVAL;
 		}
 		cldata->file = debugfs_create_file(pdata->name, S_IRUGO,
@@ -393,6 +407,7 @@
 	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu  ", ib);
 	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n");
 	cldata->size = i;
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 
 	trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec,
 		pdata->name, pdata->mas, pdata->slv, ab, ib);
@@ -404,6 +419,7 @@
 {
 	struct msm_bus_cldata *cldata = NULL;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->handle == pdata) {
 			debugfs_remove(cldata->file);
@@ -412,6 +428,7 @@
 			break;
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 }
 
 static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata,
@@ -429,7 +446,9 @@
 	cldata->clid = clid;
 	cldata->file = file;
 	cldata->size = 0;
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_add_tail(&cldata->list, &cl_list);
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 	return 0;
 }
 
@@ -437,13 +456,16 @@
 {
 	struct msm_bus_cldata *cldata = NULL;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->clid == clid) {
+			debugfs_remove(cldata->file);
 			list_del(&cldata->list);
 			kfree(cldata);
 			break;
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 }
 
 static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata,
@@ -455,6 +477,7 @@
 	struct timespec ts;
 	int found = 0;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->clid == clid) {
 			found = 1;
@@ -462,11 +485,14 @@
 		}
 	}
 
-	if (!found)
+	if (!found) {
+		rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 		return -ENOENT;
+	}
 
 	if (cldata->file == NULL) {
 		if (pdata->name == NULL) {
+			rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 			MSM_BUS_DBG("Client doesn't have a name\n");
 			return -EINVAL;
 		}
@@ -514,21 +540,11 @@
 
 	cldata->index = index;
 	cldata->size = i;
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+
 	return i;
 }
 
-static int msm_bus_dbg_update_request(struct msm_bus_cldata *cldata, int index)
-{
-	int ret = 0;
-
-	if ((index < 0) || (index > cldata->pdata->num_usecases)) {
-		MSM_BUS_DBG("Invalid index!\n");
-		return -EINVAL;
-	}
-	ret = msm_bus_scale_client_update_request(cldata->clid, index);
-	return ret;
-}
-
 static ssize_t  msm_bus_dbg_update_request_write(struct file *file,
 	const char __user *ubuf, size_t cnt, loff_t *ppos)
 {
@@ -538,19 +554,26 @@
 	char *chid;
 	char *buf = kmalloc((sizeof(char) * (cnt + 1)), GFP_KERNEL);
 	int found = 0;
+	uint32_t clid;
+	ssize_t res = cnt;
 
 	if (!buf || IS_ERR(buf)) {
 		MSM_BUS_ERR("Memory allocation for buffer failed\n");
 		return -ENOMEM;
 	}
-	if (cnt == 0)
-		return 0;
-	if (copy_from_user(buf, ubuf, cnt))
-		return -EFAULT;
+	if (cnt == 0) {
+		res = 0;
+		goto out;
+	}
+	if (copy_from_user(buf, ubuf, cnt)) {
+		res = -EFAULT;
+		goto out;
+	}
 	buf[cnt] = '\0';
 	chid = buf;
 	MSM_BUS_DBG("buffer: %s\n size: %zu\n", buf, sizeof(ubuf));
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (strnstr(chid, cldata->pdata->name, cnt)) {
 			found = 1;
@@ -559,23 +582,37 @@
 			if (chid) {
 				ret = kstrtoul(chid, 10, &index);
 				if (ret) {
-					MSM_BUS_DBG("Index conversion failed\n"
-							);
-					return -EFAULT;
+					MSM_BUS_DBG("Index conversion\n"
+						" failed\n");
+					rt_mutex_unlock(
+						&msm_bus_dbg_cllist_lock);
+					res = -EFAULT;
+					goto out;
 				}
 			} else {
-				MSM_BUS_DBG("Error parsing input.\n"
-						"Index not found\n");
+				MSM_BUS_DBG("Error parsing input. Index not\n"
+					" found\n");
 				found = 0;
 			}
+			if ((index < 0) ||
+					(index > cldata->pdata->num_usecases)) {
+				MSM_BUS_DBG("Invalid index!\n");
+				rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+				res = -EINVAL;
+				goto out;
+			}
+			clid = cldata->clid;
 			break;
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 
 	if (found)
-		msm_bus_dbg_update_request(cldata, index);
+		msm_bus_scale_client_update_request(clid, index);
+
+out:
 	kfree(buf);
-	return cnt;
+	return res;
 }
 
 /**
@@ -598,8 +635,10 @@
 			break;
 		}
 	}
-	if (!found)
+	if (!found) {
+		mutex_unlock(&msm_bus_dbg_fablist_lock);
 		return -ENOENT;
+	}
 	bsize = fablist->size;
 	ret = simple_read_from_buffer(buf, count, ppos,
 		fablist->buffer, bsize);
@@ -689,8 +728,10 @@
 			break;
 		}
 	}
-	if (!found)
+	if (!found) {
+		mutex_unlock(&msm_bus_dbg_fablist_lock);
 		return -ENOENT;
+	}
 
 	if (fablist->file == NULL) {
 		MSM_BUS_DBG("Fabric dbg entry does not exist\n");
@@ -741,6 +782,8 @@
 		"\nDumping curent client votes to trace log\n");
 	if (*ppos)
 		goto exit_dump_clients_read;
+
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (IS_ERR_OR_NULL(cldata->pdata))
 			continue;
@@ -756,6 +799,7 @@
 			cldata->pdata->active_only);
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 exit_dump_clients_read:
 	return simple_read_from_buffer(buf, count, ppos, msg, cnt);
 }
@@ -880,6 +924,7 @@
 		goto err;
 	}
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->pdata) {
 			if (cldata->pdata->name == NULL) {
@@ -899,6 +944,7 @@
 							&client_data_fops);
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 
 	if (debugfs_create_file("dump_clients", S_IRUGO | S_IWUSR,
 		clients, NULL, &msm_bus_dbg_dump_clients_fops) == NULL)
@@ -911,6 +957,7 @@
 		if (fablist->file == NULL) {
 			MSM_BUS_DBG("Cannot create files for commit data\n");
 			kfree(rules_buf);
+			mutex_unlock(&msm_bus_dbg_fablist_lock);
 			goto err;
 		}
 	}
@@ -930,10 +977,14 @@
 	struct msm_bus_cldata *cldata = NULL, *cldata_temp;
 
 	debugfs_remove_recursive(dir);
+
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) {
 		list_del(&cldata->list);
 		kfree(cldata);
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+
 	mutex_lock(&msm_bus_dbg_fablist_lock);
 	list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) {
 		list_del(&fablist->list);
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index 185d862..0e5ead0 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -595,6 +595,9 @@
 		cnt_vcd++;
 	}
 
+	if (!cnt_active)
+		goto exit_msm_bus_commit_data;
+
 	n_active = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
 	if (!n_active)
 		return -ENOMEM;
@@ -624,42 +627,54 @@
 		MSM_BUS_ERR("%s: Error invalidating mbox: %d\n",
 						__func__, ret);
 
-	if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE)
+	if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE) {
 		ret = rpmh_write(cur_mbox, cur_rsc->rscdev->req_state,
 						cmdlist_active, cnt_active);
-	else
+		/*
+		 * Ignore -EBUSY from rpmh_write if it's an AWAKE_STATE
+		 * request since AWAKE requests are invalid when
+		 * the display RSC is in solver mode and the bus driver
+		 * does not know the current state of the display RSC.
+		 */
+		if (ret && ret != -EBUSY)
+			MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
+						__func__, ret);
+	} else {
 		ret = rpmh_write_passthru(cur_mbox, cur_rsc->rscdev->req_state,
 						cmdlist_active, n_active);
-	if (ret)
-		MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
+		if (ret)
+			MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
 						__func__, ret);
-
-
-	ret = rpmh_write_passthru(cur_mbox, RPMH_WAKE_ONLY_STATE,
-						cmdlist_wake, n_wake);
-	if (ret)
-		MSM_BUS_ERR("%s: error sending wake sets: %d\n",
-						__func__, ret);
-
-	ret = rpmh_write_passthru(cur_mbox, RPMH_SLEEP_STATE,
-						cmdlist_sleep, n_sleep);
-	if (ret)
-		MSM_BUS_ERR("%s: error sending sleep sets: %d\n",
-						__func__, ret);
-
-	list_for_each_entry_safe(node, node_tmp, clist, link) {
-		bcm_clist_clean(node);
-		node->dirty = false;
-		list_del_init(&node->link);
+	}
+	if (cnt_wake) {
+		ret = rpmh_write_passthru(cur_mbox, RPMH_WAKE_ONLY_STATE,
+							cmdlist_wake, n_wake);
+		if (ret)
+			MSM_BUS_ERR("%s: error sending wake sets: %d\n",
+							__func__, ret);
+	}
+	if (cnt_sleep) {
+		ret = rpmh_write_passthru(cur_mbox, RPMH_SLEEP_STATE,
+							cmdlist_sleep, n_sleep);
+		if (ret)
+			MSM_BUS_ERR("%s: error sending sleep sets: %d\n",
+							__func__, ret);
 	}
 
-	cur_rsc = NULL;
 	kfree(cmdlist_active);
 	kfree(cmdlist_wake);
 	kfree(cmdlist_sleep);
 	kfree(n_active);
 	kfree(n_wake);
 	kfree(n_sleep);
+
+exit_msm_bus_commit_data:
+	list_for_each_entry_safe(node, node_tmp, clist, link) {
+		bcm_clist_clean(node);
+		node->dirty = false;
+		list_del_init(&node->link);
+	}
+	cur_rsc = NULL;
 	return ret;
 }
 
diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c
index 25e6a9d..979c628 100644
--- a/drivers/soc/qcom/msm_performance.c
+++ b/drivers/soc/qcom/msm_performance.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/kthread.h>
+#include <soc/qcom/msm-core.h>
 
 static struct mutex managed_cpus_lock;
 
diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c
index 67a5e05..e4ada03 100644
--- a/drivers/soc/qcom/qbt1000.c
+++ b/drivers/soc/qcom/qbt1000.c
@@ -342,6 +342,13 @@
 			goto end;
 		}
 
+		if (strcmp(app.name, FP_APP_NAME)) {
+			dev_err(drvdata->dev, "%s: Invalid app name\n",
+				__func__);
+			rc = -EINVAL;
+			goto end;
+		}
+
 		if (drvdata->app_handle) {
 			dev_err(drvdata->dev, "%s: LOAD app already loaded, unloading first\n",
 				__func__);
@@ -388,9 +395,7 @@
 
 		pr_debug("app %s load after\n", app.name);
 
-		if (!strcmp(app.name, FP_APP_NAME))
-			drvdata->fp_app_handle = drvdata->app_handle;
-
+		drvdata->fp_app_handle = drvdata->app_handle;
 		break;
 	}
 	case QBT1000_UNLOAD_APP:
diff --git a/drivers/soc/qcom/qsee_ipc_irq_bridge.c b/drivers/soc/qcom/qsee_ipc_irq_bridge.c
new file mode 100644
index 0000000..ac3dcc3
--- /dev/null
+++ b/drivers/soc/qcom/qsee_ipc_irq_bridge.c
@@ -0,0 +1,624 @@
+/* Copyright (c) 2016-2017, 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/cdev.h>
+#include <linux/interrupt.h>
+#include <linux/ipc_logging.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <soc/qcom/subsystem_notif.h>
+#include <soc/qcom/subsystem_restart.h>
+
+#define MODULE_NAME "qsee_ipc_irq_bridge"
+#define DEVICE_NAME MODULE_NAME
+#define NUM_LOG_PAGES 4
+
+#define QIIB_DBG(x...) do { \
+	if (qiib_info->log_ctx) \
+		ipc_log_string(qiib_info->log_ctx, x); \
+	else \
+		pr_debug(x); \
+	} while (0)
+
+#define QIIB_ERR(x...) do { \
+	pr_err(x); \
+	if (qiib_info->log_ctx) \
+		ipc_log_string(qiib_info->log_ctx, x); \
+	} while (0)
+
+static void qiib_cleanup(void);
+
+/**
+ * qiib_dev - QSEE IPC IRQ bridge device
+ * @dev_list:		qiib device list.
+ * @i:			Index to this character device.
+ * @dev_name:		Device node name used by the clients.
+ * @cdev:		structure to the internal character device.
+ * @devicep:		Pointer to the qiib class device structure.
+ * @poll_wait_queue:	poll thread wait queue.
+ * @irq_num:		IRQ number usd for this device.
+ * @rx_irq_reset_reg:	Reference to the register to reset the rx irq
+ *			line, if applicable.
+ * @irq_mask:		Mask written to @rx_irq_reset_reg to clear the irq.
+ * @irq_pending_count:	The number of IRQs pending.
+ * @irq_pending_count_lock: Lock to protect @irq_pending_cont.
+ * @ssr_name:		Name of the subsystem recognized by the SSR framework.
+ * @nb:			SSR Notifier callback.
+ * @notifier_handle:	SSR Notifier handle.
+ * @in_reset:		Flag to check the SSR state.
+ */
+struct qiib_dev {
+	struct list_head dev_list;
+	uint32_t i;
+
+	const char *dev_name;
+	struct cdev cdev;
+	struct device *devicep;
+
+	wait_queue_head_t poll_wait_queue;
+
+	uint32_t irq_line;
+	void __iomem *rx_irq_reset_reg;
+	uint32_t irq_mask;
+	uint32_t irq_pending_count;
+	spinlock_t irq_pending_count_lock;
+
+	const char *ssr_name;
+	struct notifier_block nb;
+	void *notifier_handle;
+	bool in_reset;
+};
+
+/**
+ * qiib_driver_data - QSEE IPC IRQ bridge driver data
+ * @list:		list of all nodes devices.
+ * @list_lock:		lock to synchronize the @list access.
+ * @nprots:		Number of device nodes.
+ * @classp:		Pointer to the device class.
+ * @dev_num:		qiib device number.
+ * @log_ctx:		pointer to the ipc logging context.
+ */
+struct qiib_driver_data {
+	struct list_head list;
+	struct mutex list_lock;
+
+	int nports;
+	struct class *classp;
+	dev_t dev_num;
+
+	void *log_ctx;
+};
+
+static struct qiib_driver_data *qiib_info;
+
+/**
+ * qiib_driver_data_init() - Initialize the QIIB driver data.
+ *
+ * This function used to initialize the driver specific data
+ * during the module init.
+ *
+ * Return:	0 for success, Standard Linux errors
+ */
+static int qiib_driver_data_init(void)
+{
+	qiib_info = kzalloc(sizeof(*qiib_info), GFP_KERNEL);
+	if (!qiib_info)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&qiib_info->list);
+	mutex_init(&qiib_info->list_lock);
+
+	qiib_info->log_ctx = ipc_log_context_create(NUM_LOG_PAGES,
+						"qsee_ipc_irq_bridge", 0);
+	if (!qiib_info->log_ctx)
+		QIIB_ERR("%s: unable to create logging context\n", __func__);
+
+	return 0;
+}
+
+/**
+ * qiib_driver_data_deinit() - De-Initialize the QIIB driver data.
+ *
+ * This function used to de-initialize the driver specific data
+ * during the module exit.
+ */
+static void qiib_driver_data_deinit(void)
+{
+	qiib_cleanup();
+	if (!qiib_info->log_ctx)
+		ipc_log_context_destroy(qiib_info->log_ctx);
+	kfree(qiib_info);
+	qiib_info = NULL;
+}
+
+/**
+ * qiib_restart_notifier_cb() - SSR restart notifier callback function
+ * @this:	Notifier block used by the SSR framework
+ * @code:	The SSR code for which stage of restart is occurring
+ * @data:	Structure containing private data - not used here.
+ *
+ * This function is a callback for the SSR framework. From here we initiate
+ * our handling of SSR.
+ *
+ * Return: Status of SSR handling
+ */
+static int qiib_restart_notifier_cb(struct notifier_block *this,
+				  unsigned long code,
+				  void *data)
+{
+	struct qiib_dev *devp = container_of(this, struct qiib_dev, nb);
+
+	if (code == SUBSYS_BEFORE_SHUTDOWN) {
+		QIIB_DBG("%s: %s: subsystem restart for %s\n", __func__,
+				"SUBSYS_BEFORE_SHUTDOWN",
+				devp->ssr_name);
+		devp->in_reset = true;
+		wake_up_interruptible(&devp->poll_wait_queue);
+	} else if (code == SUBSYS_AFTER_POWERUP) {
+		QIIB_DBG("%s: %s: subsystem restart for %s\n", __func__,
+				"SUBSYS_AFTER_POWERUP",
+				devp->ssr_name);
+		devp->in_reset = false;
+	}
+	return NOTIFY_DONE;
+}
+
+/**
+ * qiib_poll() - poll() syscall for the qiib device
+ * @file:	Pointer to the file structure.
+ * @wait:	pointer to Poll table.
+ *
+ * This function is used to poll on the qiib device when
+ * userspace client do a poll() system call. All input arguments are
+ * validated by the virtual file system before calling this function.
+ *
+ * Return: POLLIN for interrupt intercepted case and POLLRDHUP for SSR.
+ */
+static unsigned int qiib_poll(struct file *file, poll_table *wait)
+{
+	struct qiib_dev *devp = file->private_data;
+	unsigned int mask = 0;
+	unsigned long flags;
+
+	if (!devp) {
+		QIIB_ERR("%s on NULL device\n", __func__);
+		return POLLERR;
+	}
+
+	if (devp->in_reset)
+		return POLLRDHUP;
+
+	poll_wait(file, &devp->poll_wait_queue, wait);
+	spin_lock_irqsave(&devp->irq_pending_count_lock, flags);
+	if (devp->irq_pending_count) {
+		mask |= POLLIN;
+		QIIB_DBG("%s set POLLIN on [%s] count[%d]\n",
+					__func__, devp->dev_name,
+					devp->irq_pending_count);
+		devp->irq_pending_count = 0;
+	}
+	spin_unlock_irqrestore(&devp->irq_pending_count_lock, flags);
+
+	if (devp->in_reset) {
+		mask |= POLLRDHUP;
+		QIIB_DBG("%s set POLLRDHUP on [%s] count[%d]\n",
+					__func__, devp->dev_name,
+					devp->irq_pending_count);
+	}
+	return mask;
+}
+
+/**
+ * qiib_open() - open() syscall for the qiib device
+ * @inode:	Pointer to the inode structure.
+ * @file:	Pointer to the file structure.
+ *
+ * This function is used to open the qiib device when
+ * userspace client do a open() system call. All input arguments are
+ * validated by the virtual file system before calling this function.
+ *
+ * Return:	0 for success, Standard Linux errors
+ */
+static int qiib_open(struct inode *inode, struct file *file)
+{
+	struct qiib_dev *devp = NULL;
+
+	devp = container_of(inode->i_cdev, struct qiib_dev, cdev);
+	if (!devp) {
+		QIIB_ERR("%s on NULL device\n", __func__);
+		return -EINVAL;
+	}
+	file->private_data = devp;
+	QIIB_DBG("%s on [%s]\n", __func__, devp->dev_name);
+	return 0;
+}
+
+/**
+ * qiib_release() - release operation on qiibdevice
+ * @inode:	Pointer to the inode structure.
+ * @file:	Pointer to the file structure.
+ *
+ * This function is used to release the qiib device when
+ * userspace client do a close() system call. All input arguments are
+ * validated by the virtual file system before calling this function.
+ */
+static int qiib_release(struct inode *inode, struct file *file)
+{
+	struct qiib_dev *devp = file->private_data;
+
+	if (!devp) {
+		QIIB_ERR("%s on NULL device\n", __func__);
+		return -EINVAL;
+	}
+
+	QIIB_DBG("%s on [%s]\n", __func__, devp->dev_name);
+	return 0;
+}
+
+static const struct file_operations qiib_fops = {
+	.owner = THIS_MODULE,
+	.open = qiib_open,
+	.release = qiib_release,
+	.poll = qiib_poll,
+};
+
+/**
+ * qiib_add_device() - Initialize qiib device and add cdev
+ * @devp:	pointer to the qiib device.
+ * @i:		index of the qiib device.
+ *
+ * Return:	0 for success, Standard Linux errors
+ */
+static int qiib_add_device(struct qiib_dev *devp, int i)
+{
+	int ret = 0;
+
+	devp->i = i;
+	init_waitqueue_head(&devp->poll_wait_queue);
+	spin_lock_init(&devp->irq_pending_count_lock);
+
+	cdev_init(&devp->cdev, &qiib_fops);
+	devp->cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&devp->cdev, qiib_info->dev_num + i, 1);
+	if (IS_ERR_VALUE((unsigned long)ret)) {
+		QIIB_ERR("%s: cdev_add() failed for dev [%s] ret:%i\n",
+			__func__, devp->dev_name, ret);
+		return ret;
+	}
+
+	devp->devicep = device_create(qiib_info->classp,
+			      NULL,
+			      (qiib_info->dev_num + i),
+			      NULL,
+			      devp->dev_name);
+
+	if (IS_ERR_OR_NULL(devp->devicep)) {
+		QIIB_ERR("%s: device_create() failed for dev [%s]\n",
+			__func__, devp->dev_name);
+		ret = -ENOMEM;
+		cdev_del(&devp->cdev);
+		return ret;
+	}
+
+	mutex_lock(&qiib_info->list_lock);
+	list_add(&devp->dev_list, &qiib_info->list);
+	mutex_unlock(&qiib_info->list_lock);
+
+	return ret;
+}
+
+static irqreturn_t qiib_irq_handler(int irq, void *priv)
+{
+	struct qiib_dev *devp = priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&devp->irq_pending_count_lock, flags);
+	devp->irq_pending_count++;
+	spin_unlock_irqrestore(&devp->irq_pending_count_lock, flags);
+	wake_up_interruptible(&devp->poll_wait_queue);
+
+	if (devp->rx_irq_reset_reg)
+		writel_relaxed(devp->irq_mask, devp->rx_irq_reset_reg);
+
+	QIIB_DBG("%s name[%s] pend_count[%d]\n", __func__,
+				devp->dev_name, devp->irq_pending_count);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * qiib_parse_node() - parse node from device tree binding
+ * @node:	pointer to device tree node
+ * @devp:	pointer to the qiib device
+ *
+ * Return:	0 on success, -ENODEV on failure.
+ */
+static int qiib_parse_node(struct device_node *node, struct qiib_dev *devp)
+{
+	char *key;
+	const char *subsys_name;
+	const char *dev_name;
+	uint32_t irqtype;
+	uint32_t irq_clear[2];
+	struct irq_data *irqtype_data;
+	int ret = -ENODEV;
+
+	key = "qcom,dev-name";
+	dev_name = of_get_property(node, key, NULL);
+	if (!dev_name) {
+		QIIB_ERR("%s: missing key: %s\n", __func__, key);
+		goto missing_key;
+	}
+	QIIB_DBG("%s: %s = %s\n", __func__, key, dev_name);
+
+	key = "interrupts";
+	devp->irq_line = irq_of_parse_and_map(node, 0);
+	if (!devp->irq_line) {
+		QIIB_ERR("%s: missing key: %s\n", __func__, key);
+		goto missing_key;
+	}
+	QIIB_DBG("%s: %s = %d\n", __func__, key, devp->irq_line);
+
+	irqtype_data = irq_get_irq_data(devp->irq_line);
+	if (!irqtype_data) {
+		QIIB_ERR("%s: get irqdata fail:%d\n", __func__, devp->irq_line);
+		goto missing_key;
+	}
+	irqtype = irqd_get_trigger_type(irqtype_data);
+	QIIB_DBG("%s: irqtype = %d\n", __func__, irqtype);
+
+	key = "label";
+	subsys_name = of_get_property(node, key, NULL);
+	if (!subsys_name) {
+		QIIB_ERR("%s: missing key: %s\n", __func__, key);
+		goto missing_key;
+	}
+	QIIB_DBG("%s: %s = %s\n", __func__, key, subsys_name);
+
+	if (irqtype & IRQF_TRIGGER_HIGH) {
+		key = "qcom,rx-irq-clr-mask";
+		ret = of_property_read_u32(node, key, &devp->irq_mask);
+		if (ret) {
+			QIIB_ERR("%s: missing key: %s\n", __func__, key);
+			ret = -ENODEV;
+			goto missing_key;
+		}
+		QIIB_DBG("%s: %s = %d\n", __func__, key, devp->irq_mask);
+
+		key = "qcom,rx-irq-clr";
+		ret = of_property_read_u32_array(node, key, irq_clear,
+							ARRAY_SIZE(irq_clear));
+		if (ret) {
+			QIIB_ERR("%s: missing key: %s\n", __func__, key);
+			ret = -ENODEV;
+			goto missing_key;
+		}
+
+		devp->rx_irq_reset_reg = ioremap_nocache(irq_clear[0],
+								irq_clear[1]);
+		if (!devp->rx_irq_reset_reg) {
+			QIIB_ERR("%s: unable to map rx reset reg\n", __func__);
+			ret = -ENOMEM;
+			goto missing_key;
+		}
+	}
+
+	devp->dev_name = dev_name;
+	devp->ssr_name = subsys_name;
+	devp->nb.notifier_call = qiib_restart_notifier_cb;
+
+	devp->notifier_handle = subsys_notif_register_notifier(devp->ssr_name,
+								&devp->nb);
+	if (IS_ERR_OR_NULL(devp->notifier_handle)) {
+		QIIB_ERR("%s: Could not register SSR notifier cb\n", __func__);
+		ret = -EINVAL;
+		goto ssr_reg_fail;
+	}
+
+	ret = request_irq(devp->irq_line, qiib_irq_handler,
+			irqtype | IRQF_NO_SUSPEND,
+			devp->dev_name, devp);
+	if (ret < 0) {
+		QIIB_ERR("%s: request_irq() failed on %d\n", __func__,
+				devp->irq_line);
+		goto req_irq_fail;
+	} else {
+		ret = enable_irq_wake(devp->irq_line);
+		if (ret < 0)
+			QIIB_ERR("%s: enable_irq_wake() failed on %d\n",
+					__func__, devp->irq_line);
+	}
+
+	return ret;
+
+req_irq_fail:
+	subsys_notif_unregister_notifier(devp->notifier_handle,	&devp->nb);
+ssr_reg_fail:
+	if (devp->rx_irq_reset_reg) {
+		iounmap(devp->rx_irq_reset_reg);
+		devp->rx_irq_reset_reg = NULL;
+	}
+missing_key:
+	return ret;
+}
+
+/**
+ * qiib_cleanup - cleanup all the resources
+ *
+ * This function remove all the memory and unregister
+ * the char device region.
+ */
+static void qiib_cleanup(void)
+{
+	struct qiib_dev *devp;
+	struct qiib_dev *index;
+
+	mutex_lock(&qiib_info->list_lock);
+	list_for_each_entry_safe(devp, index, &qiib_info->list, dev_list) {
+		cdev_del(&devp->cdev);
+		list_del(&devp->dev_list);
+		device_destroy(qiib_info->classp,
+			       MKDEV(MAJOR(qiib_info->dev_num), devp->i));
+		if (devp->notifier_handle)
+			subsys_notif_unregister_notifier(devp->notifier_handle,
+								&devp->nb);
+		kfree(devp);
+	}
+	mutex_unlock(&qiib_info->list_lock);
+
+	if (!IS_ERR_OR_NULL(qiib_info->classp))
+		class_destroy(qiib_info->classp);
+
+	unregister_chrdev_region(MAJOR(qiib_info->dev_num), qiib_info->nports);
+}
+
+/**
+ * qiib_alloc_chrdev_region() - allocate the char device region
+ *
+ * This function allocate memory for qiib character-device region and
+ * create the class.
+ */
+static int qiib_alloc_chrdev_region(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&qiib_info->dev_num,
+			       0,
+			       qiib_info->nports,
+			       DEVICE_NAME);
+	if (IS_ERR_VALUE((unsigned long)ret)) {
+		QIIB_ERR("%s: alloc_chrdev_region() failed ret:%i\n",
+			__func__, ret);
+		return ret;
+	}
+
+	qiib_info->classp = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(qiib_info->classp)) {
+		QIIB_ERR("%s: class_create() failed ENOMEM\n", __func__);
+		ret = -ENOMEM;
+		unregister_chrdev_region(MAJOR(qiib_info->dev_num),
+						qiib_info->nports);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int qsee_ipc_irq_bridge_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct device_node *node;
+	struct qiib_dev *devp;
+	int i = 0;
+
+	qiib_info->nports = of_get_available_child_count(pdev->dev.of_node);
+	if (!qiib_info->nports) {
+		QIIB_ERR("%s:Fail nports = %d\n", __func__, qiib_info->nports);
+		return -EINVAL;
+	}
+
+	ret = qiib_alloc_chrdev_region();
+	if (ret) {
+		QIIB_ERR("%s: chrdev_region allocation failed ret:%i\n",
+			__func__, ret);
+		return ret;
+	}
+
+	for_each_available_child_of_node(pdev->dev.of_node, node) {
+		devp = kzalloc(sizeof(*devp), GFP_KERNEL);
+		if (IS_ERR_OR_NULL(devp)) {
+			QIIB_ERR("%s:Allocation failed id:%d\n", __func__, i);
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		ret = qiib_parse_node(node, devp);
+		if (ret) {
+			QIIB_ERR("%s:qiib_parse_node failed %d\n", __func__, i);
+			kfree(devp);
+			goto error;
+		}
+
+		ret = qiib_add_device(devp, i);
+		if (ret < 0) {
+			QIIB_ERR("%s: add [%s] device failed ret=%d\n",
+					__func__, devp->dev_name, ret);
+			kfree(devp);
+			goto error;
+		}
+		i++;
+	}
+
+	QIIB_DBG("%s: Driver Initialized.\n", __func__);
+	return 0;
+
+error:
+	qiib_cleanup();
+	return ret;
+}
+
+static int qsee_ipc_irq_bridge_remove(struct platform_device *pdev)
+{
+	qiib_cleanup();
+	return 0;
+}
+
+static const struct of_device_id qsee_ipc_irq_bridge_match_table[] = {
+	{ .compatible = "qcom,qsee-ipc-irq-bridge" },
+	{},
+};
+
+static struct platform_driver qsee_ipc_irq_bridge_driver = {
+	.probe = qsee_ipc_irq_bridge_probe,
+	.remove = qsee_ipc_irq_bridge_remove,
+	.driver = {
+		.name = MODULE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = qsee_ipc_irq_bridge_match_table,
+	 },
+};
+
+static int __init qsee_ipc_irq_bridge_init(void)
+{
+	int ret;
+
+	ret = qiib_driver_data_init();
+	if (ret) {
+		QIIB_ERR("%s: driver data init failed %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = platform_driver_register(&qsee_ipc_irq_bridge_driver);
+	if (ret) {
+		QIIB_ERR("%s: platform driver register failed %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+module_init(qsee_ipc_irq_bridge_init);
+
+static void __exit qsee_ipc_irq_bridge_exit(void)
+{
+	platform_driver_unregister(&qsee_ipc_irq_bridge_driver);
+	qiib_driver_data_deinit();
+}
+module_exit(qsee_ipc_irq_bridge_exit);
+MODULE_DESCRIPTION("QSEE IPC interrupt bridge");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 17e0a4c..8580484 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -77,6 +77,8 @@
 	DECLARE_BITMAP(fast_req, RPMH_MAX_FAST_RES);
 	bool dirty;
 	bool in_solver_mode;
+	/* Cache sleep and wake requests sent as passthru */
+	struct rpmh_msg *passthru_cache[2 * RPMH_MAX_REQ_IN_BATCH];
 };
 
 struct rpmh_client {
@@ -111,17 +113,24 @@
 	return msg;
 }
 
+static void __free_msg_to_pool(struct rpmh_msg *rpm_msg)
+{
+	struct rpmh_mbox *rpm = rpm_msg->rc->rpmh;
+
+	/* If we allocated the pool, set it as available */
+	if (rpm_msg->bit >= 0 && rpm_msg->bit != RPMH_MAX_FAST_RES) {
+		bitmap_clear(rpm->fast_req, rpm_msg->bit, 1);
+	}
+}
+
 static void free_msg_to_pool(struct rpmh_msg *rpm_msg)
 {
 	struct rpmh_mbox *rpm = rpm_msg->rc->rpmh;
 	unsigned long flags;
 
-	/* If we allocated the pool, set it as available */
-	if (rpm_msg->bit >= 0 && rpm_msg->bit != RPMH_MAX_FAST_RES) {
-		spin_lock_irqsave(&rpm->lock, flags);
-		bitmap_clear(rpm->fast_req, rpm_msg->bit, 1);
-		spin_unlock_irqrestore(&rpm->lock, flags);
-	}
+	spin_lock_irqsave(&rpm->lock, flags);
+	__free_msg_to_pool(rpm_msg);
+	spin_unlock_irqrestore(&rpm->lock, flags);
 }
 
 static void rpmh_rx_cb(struct mbox_client *cl, void *msg)
@@ -181,6 +190,7 @@
 {
 	int ret;
 	int count = 4;
+	int skip = 0;
 
 	do {
 		ret = wait_for_completion_timeout(compl, RPMH_TIMEOUT);
@@ -192,7 +202,12 @@
 			return;
 		}
 		if (!count) {
+			if (skip++ % 100)
+				continue;
+			dev_err(rc->dev,
+				"RPMH waiting for interrupt from AOSS\n");
 			mbox_chan_debug(rc->chan);
+			BUG();
 		} else {
 			dev_err(rc->dev,
 			"RPMH response timeout (%d) addr=0x%x,data=0x%x\n",
@@ -511,6 +526,70 @@
 }
 EXPORT_SYMBOL(rpmh_write);
 
+static int cache_passthru(struct rpmh_client *rc, struct rpmh_msg **rpm_msg,
+					int count)
+{
+	struct rpmh_mbox *rpm = rc->rpmh;
+	unsigned long flags;
+	int ret = 0;
+	int index = 0;
+	int i;
+
+	spin_lock_irqsave(&rpm->lock, flags);
+	while (rpm->passthru_cache[index])
+		index++;
+	if (index + count >=  2 * RPMH_MAX_REQ_IN_BATCH) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	for (i = 0; i < count; i++)
+		rpm->passthru_cache[index + i] = rpm_msg[i];
+fail:
+	spin_unlock_irqrestore(&rpm->lock, flags);
+
+	return ret;
+}
+
+static int flush_passthru(struct rpmh_client *rc)
+{
+	struct rpmh_mbox *rpm = rc->rpmh;
+	struct rpmh_msg *rpm_msg;
+	unsigned long flags;
+	int ret = 0;
+	int i;
+
+	/* Send Sleep/Wake requests to the controller, expect no response */
+	spin_lock_irqsave(&rpm->lock, flags);
+	for (i = 0; rpm->passthru_cache[i]; i++) {
+		rpm_msg = rpm->passthru_cache[i];
+		ret = mbox_send_controller_data(rc->chan, &rpm_msg->msg);
+		if (ret)
+			goto fail;
+	}
+fail:
+	spin_unlock_irqrestore(&rpm->lock, flags);
+
+	return ret;
+}
+
+static void invalidate_passthru(struct rpmh_client *rc)
+{
+	struct rpmh_mbox *rpm = rc->rpmh;
+	unsigned long flags;
+	int index = 0;
+	int i;
+
+	spin_lock_irqsave(&rpm->lock, flags);
+	while (rpm->passthru_cache[index])
+		index++;
+	for (i = 0; i < index; i++) {
+		__free_msg_to_pool(rpm->passthru_cache[i]);
+		rpm->passthru_cache[i] = NULL;
+	}
+	spin_unlock_irqrestore(&rpm->lock, flags);
+}
+
 /**
  * rpmh_write_passthru: Write multiple batches of RPMH commands without caching
  *
@@ -530,7 +609,7 @@
 int rpmh_write_passthru(struct rpmh_client *rc, enum rpmh_state state,
 			struct tcs_cmd *cmd, int *n)
 {
-	struct rpmh_msg *rpm_msg[RPMH_MAX_REQ_IN_BATCH];
+	struct rpmh_msg *rpm_msg[RPMH_MAX_REQ_IN_BATCH] = { NULL };
 	DECLARE_COMPLETION_ONSTACK(compl);
 	atomic_t wait_count = ATOMIC_INIT(0); /* overwritten */
 	int count = 0;
@@ -548,7 +627,7 @@
 	if (ret)
 		return ret;
 
-	while (n[count++])
+	while (n[count++] > 0)
 		;
 	count--;
 	if (!count || count > RPMH_MAX_REQ_IN_BATCH)
@@ -607,14 +686,11 @@
 			rpmh_tx_done(&rc->client, &rpm_msg[j]->msg, ret);
 		wait_for_tx_done(rc, &compl, addr, data);
 	} else {
-		/* Send Sleep requests to the controller, expect no response */
-		for (i = 0; i < count; i++) {
-			rpm_msg[i]->completion = NULL;
-			ret = mbox_send_controller_data(rc->chan,
-						&rpm_msg[i]->msg);
-			free_msg_to_pool(rpm_msg[i]);
-		}
-		return 0;
+		/*
+		 * Cache sleep/wake data in store.
+		 * But flush passthru first before flushing all other data.
+		 */
+		return cache_passthru(rc, rpm_msg, count);
 	}
 
 	return 0;
@@ -674,7 +750,7 @@
 {
 	DEFINE_RPMH_MSG_ONSTACK(rc, 0, NULL, NULL, rpm_msg);
 
-	if (IS_ERR_OR_NULL(rc) ||  n > MAX_RPMH_PAYLOAD)
+	if (IS_ERR_OR_NULL(rc) || n <= 0 || n > MAX_RPMH_PAYLOAD)
 		return -EINVAL;
 
 	if (rpmh_standalone)
@@ -710,6 +786,8 @@
 	if (rpmh_standalone)
 		return 0;
 
+	invalidate_passthru(rc);
+
 	rpm = rc->rpmh;
 	rpm_msg.msg.invalidate = true;
 	rpm_msg.msg.is_complete = false;
@@ -823,6 +901,11 @@
 	}
 	spin_unlock_irqrestore(&rpm->lock, flags);
 
+	/* First flush the cached passthru's */
+	ret = flush_passthru(rc);
+	if (ret)
+		return ret;
+
 	/*
 	 * Nobody else should be calling this function other than sleep,
 	 * hence we can run without locks.
@@ -906,8 +989,10 @@
 
 	rpmh->msg_pool = kzalloc(sizeof(struct rpmh_msg) *
 				RPMH_MAX_FAST_RES, GFP_KERNEL);
-	if (!rpmh->msg_pool)
+	if (!rpmh->msg_pool) {
+		of_node_put(spec.np);
 		return ERR_PTR(-ENOMEM);
+	}
 
 	rpmh->mbox_dn = spec.np;
 	INIT_LIST_HEAD(&rpmh->resources);
diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c
index fcb3731..ac5cc54 100644
--- a/drivers/soc/qcom/scm.c
+++ b/drivers/soc/qcom/scm.c
@@ -397,18 +397,22 @@
 			__asmeq("%1", R1_STR)
 			__asmeq("%2", R2_STR)
 			__asmeq("%3", R3_STR)
-			__asmeq("%4", R0_STR)
-			__asmeq("%5", R1_STR)
-			__asmeq("%6", R2_STR)
-			__asmeq("%7", R3_STR)
-			__asmeq("%8", R4_STR)
-			__asmeq("%9", R5_STR)
-			__asmeq("%10", R6_STR)
+			__asmeq("%4", R4_STR)
+			__asmeq("%5", R5_STR)
+			__asmeq("%6", R6_STR)
+			__asmeq("%7", R0_STR)
+			__asmeq("%8", R1_STR)
+			__asmeq("%9", R2_STR)
+			__asmeq("%10", R3_STR)
+			__asmeq("%11", R4_STR)
+			__asmeq("%12", R5_STR)
+			__asmeq("%13", R6_STR)
 #ifdef REQUIRES_SEC
 			".arch_extension sec\n"
 #endif
 			"smc	#0\n"
-			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
+			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3),
+			  "=r" (r4), "=r" (r5), "=r" (r6)
 			: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
 			  "r" (r5), "r" (r6)
 			: "x7", "x8", "x9", "x10", "x11", "x12", "x13",
@@ -442,18 +446,22 @@
 			__asmeq("%1", R1_STR)
 			__asmeq("%2", R2_STR)
 			__asmeq("%3", R3_STR)
-			__asmeq("%4", R0_STR)
-			__asmeq("%5", R1_STR)
-			__asmeq("%6", R2_STR)
-			__asmeq("%7", R3_STR)
-			__asmeq("%8", R4_STR)
-			__asmeq("%9", R5_STR)
-			__asmeq("%10", R6_STR)
+			__asmeq("%4", R4_STR)
+			__asmeq("%5", R5_STR)
+			__asmeq("%6", R6_STR)
+			__asmeq("%7", R0_STR)
+			__asmeq("%8", R1_STR)
+			__asmeq("%9", R2_STR)
+			__asmeq("%10", R3_STR)
+			__asmeq("%11", R4_STR)
+			__asmeq("%12", R5_STR)
+			__asmeq("%13", R6_STR)
 #ifdef REQUIRES_SEC
 			".arch_extension sec\n"
 #endif
 			"smc	#0\n"
-			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
+			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3),
+			  "=r" (r4), "=r" (r5), "=r" (r6)
 			: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
 			  "r" (r5), "r" (r6)
 			: "x7", "x8", "x9", "x10", "x11", "x12", "x13",
@@ -490,18 +498,22 @@
 			__asmeq("%1", R1_STR)
 			__asmeq("%2", R2_STR)
 			__asmeq("%3", R3_STR)
-			__asmeq("%4", R0_STR)
-			__asmeq("%5", R1_STR)
-			__asmeq("%6", R2_STR)
-			__asmeq("%7", R3_STR)
-			__asmeq("%8", R4_STR)
-			__asmeq("%9", R5_STR)
-			__asmeq("%10", R6_STR)
+			__asmeq("%4", R4_STR)
+			__asmeq("%5", R5_STR)
+			__asmeq("%6", R6_STR)
+			__asmeq("%7", R0_STR)
+			__asmeq("%8", R1_STR)
+			__asmeq("%9", R2_STR)
+			__asmeq("%10", R3_STR)
+			__asmeq("%11", R4_STR)
+			__asmeq("%12", R5_STR)
+			__asmeq("%13", R6_STR)
 #ifdef REQUIRES_SEC
 			".arch_extension sec\n"
 #endif
 			"smc	#0\n"
-			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
+			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3),
+			  "=r" (r4), "=r" (r5), "=r" (r6)
 			: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4),
 			 "r" (r5), "r" (r6));
 
@@ -668,10 +680,6 @@
 
 		desc->ret[0] = desc->ret[1] = desc->ret[2] = 0;
 
-		pr_debug("scm_call: func id %#llx, args: %#x, %#llx, %#llx, %#llx, %#llx\n",
-			x0, desc->arginfo, desc->args[0], desc->args[1],
-			desc->args[2], desc->x5);
-
 		trace_scm_call_start(x0, desc);
 
 		if (scm_version == SCM_ARMV8_64)
@@ -701,10 +709,8 @@
 	}  while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
 
 	if (ret < 0)
-		pr_err("scm_call failed: func id %#llx, arginfo: %#x, args: %#llx, %#llx, %#llx, %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
-			x0, desc->arginfo, desc->args[0], desc->args[1],
-			desc->args[2], desc->x5, ret, desc->ret[0],
-			desc->ret[1], desc->ret[2]);
+		pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
+			x0, ret, desc->ret[0], desc->ret[1], desc->ret[2]);
 
 	if (arglen > N_REGISTER_ARGS)
 		kfree(desc->extra_arg_buf);
@@ -737,10 +743,6 @@
 
 	x0 = fn_id | BIT(SMC_ATOMIC_SYSCALL) | scm_version_mask;
 
-	pr_debug("scm_call: func id %#llx, args: %#x, %#llx, %#llx, %#llx, %#llx\n",
-		x0, desc->arginfo, desc->args[0], desc->args[1],
-		desc->args[2], desc->x5);
-
 	if (scm_version == SCM_ARMV8_64)
 		ret = __scm_call_armv8_64(x0, desc->arginfo, desc->args[0],
 					  desc->args[1], desc->args[2],
@@ -752,9 +754,8 @@
 					  desc->x5, &desc->ret[0],
 					  &desc->ret[1], &desc->ret[2]);
 	if (ret < 0)
-		pr_err("scm_call failed: func id %#llx, arginfo: %#x, args: %#llx, %#llx, %#llx, %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
-			x0, desc->arginfo, desc->args[0], desc->args[1],
-			desc->args[2], desc->x5, ret, desc->ret[0],
+		pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
+			x0, ret, desc->ret[0],
 			desc->ret[1], desc->ret[2]);
 
 	if (arglen > N_REGISTER_ARGS)
diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c
index 49fd7fe..6553ac0 100644
--- a/drivers/soc/qcom/secure_buffer.c
+++ b/drivers/soc/qcom/secure_buffer.c
@@ -25,29 +25,12 @@
 
 DEFINE_MUTEX(secure_buffer_mutex);
 
-struct cp2_mem_chunks {
-	u32 chunk_list;
-	u32 chunk_list_size;
-	u32 chunk_size;
-} __attribute__ ((__packed__));
-
-struct cp2_lock_req {
-	struct cp2_mem_chunks chunks;
-	u32 mem_usage;
-	u32 lock;
-} __attribute__ ((__packed__));
-
-
 struct mem_prot_info {
 	phys_addr_t addr;
 	u64 size;
 };
 
 #define MEM_PROT_ASSIGN_ID		0x16
-#define MEM_PROTECT_LOCK_ID2		0x0A
-#define MEM_PROTECT_LOCK_ID2_FLAT	0x11
-#define V2_CHUNK_SIZE		SZ_1M
-#define FEATURE_ID_CP 12
 
 struct dest_vm_and_perm_info {
 	u32 vm;
@@ -59,137 +42,6 @@
 static void *qcom_secure_mem;
 #define QCOM_SECURE_MEM_SIZE (512*1024)
 
-static int secure_buffer_change_chunk(u32 chunks,
-				u32 nchunks,
-				u32 chunk_size,
-				int lock)
-{
-	struct cp2_lock_req request;
-	u32 resp;
-	int ret;
-	struct scm_desc desc = {0};
-
-	desc.args[0] = request.chunks.chunk_list = chunks;
-	desc.args[1] = request.chunks.chunk_list_size = nchunks;
-	desc.args[2] = request.chunks.chunk_size = chunk_size;
-	/* Usage is now always 0 */
-	desc.args[3] = request.mem_usage = 0;
-	desc.args[4] = request.lock = lock;
-	desc.args[5] = 0;
-	desc.arginfo = SCM_ARGS(6, SCM_RW, SCM_VAL, SCM_VAL, SCM_VAL, SCM_VAL,
-				SCM_VAL);
-
-	kmap_flush_unused();
-	kmap_atomic_flush_unused();
-
-	if (!is_scm_armv8()) {
-		ret = scm_call(SCM_SVC_MP, MEM_PROTECT_LOCK_ID2,
-				&request, sizeof(request), &resp, sizeof(resp));
-	} else {
-		ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
-				MEM_PROTECT_LOCK_ID2_FLAT), &desc);
-		resp = desc.ret[0];
-	}
-
-	return ret;
-}
-
-
-
-static int secure_buffer_change_table(struct sg_table *table, int lock)
-{
-	int i, j;
-	int ret = -EINVAL;
-	u32 *chunk_list;
-	struct scatterlist *sg;
-
-	for_each_sg(table->sgl, sg, table->nents, i) {
-		int nchunks;
-		int size = sg->length;
-		int chunk_list_len;
-		phys_addr_t chunk_list_phys;
-
-		/*
-		 * This should theoretically be a phys_addr_t but the protocol
-		 * indicates this should be a u32.
-		 */
-		u32 base;
-		u64 tmp = sg_dma_address(sg);
-
-		WARN((tmp >> 32) & 0xffffffff,
-			"%s: there are ones in the upper 32 bits of the sg at %p! They will be truncated! Address: 0x%llx\n",
-			__func__, sg, tmp);
-		if (unlikely(!size || (size % V2_CHUNK_SIZE))) {
-			WARN(1,
-				"%s: chunk %d has invalid size: 0x%x. Must be a multiple of 0x%x\n",
-				__func__, i, size, V2_CHUNK_SIZE);
-			return -EINVAL;
-		}
-
-		base = (u32)tmp;
-
-		nchunks = size / V2_CHUNK_SIZE;
-		chunk_list_len = sizeof(u32)*nchunks;
-
-		chunk_list = kzalloc(chunk_list_len, GFP_KERNEL);
-
-		if (!chunk_list)
-			return -ENOMEM;
-
-		chunk_list_phys = virt_to_phys(chunk_list);
-		for (j = 0; j < nchunks; j++)
-			chunk_list[j] = base + j * V2_CHUNK_SIZE;
-
-		/*
-		 * Flush the chunk list before sending the memory to the
-		 * secure environment to ensure the data is actually present
-		 * in RAM
-		 */
-		dmac_flush_range(chunk_list, chunk_list + chunk_list_len);
-
-		ret = secure_buffer_change_chunk(virt_to_phys(chunk_list),
-				nchunks, V2_CHUNK_SIZE, lock);
-
-		if (!ret) {
-			/*
-			 * Set or clear the private page flag to communicate the
-			 * status of the chunk to other entities
-			 */
-			if (lock)
-				SetPagePrivate(sg_page(sg));
-			else
-				ClearPagePrivate(sg_page(sg));
-		}
-
-		kfree(chunk_list);
-	}
-
-	return ret;
-}
-
-int msm_secure_table(struct sg_table *table)
-{
-	int ret;
-
-	mutex_lock(&secure_buffer_mutex);
-	ret = secure_buffer_change_table(table, 1);
-	mutex_unlock(&secure_buffer_mutex);
-
-	return ret;
-
-}
-
-int msm_unsecure_table(struct sg_table *table)
-{
-	int ret;
-
-	mutex_lock(&secure_buffer_mutex);
-	ret = secure_buffer_change_table(table, 0);
-	mutex_unlock(&secure_buffer_mutex);
-	return ret;
-
-}
-
 static struct dest_vm_and_perm_info *
 populate_dest_info(int *dest_vmids, int nelements, int *dest_perms,
 		   size_t *size_in_bytes)
@@ -426,20 +278,6 @@
 	}
 }
 
-#define MAKE_CP_VERSION(major, minor, patch) \
-	(((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
-
-bool msm_secure_v2_is_supported(void)
-{
-	int version = scm_get_feat_version(FEATURE_ID_CP);
-
-	/*
-	 * if the version is < 1.1.0 then dynamic buffer allocation is
-	 * not supported
-	 */
-	return version >= MAKE_CP_VERSION(1, 1, 0);
-}
-
 static int __init alloc_secure_shared_memory(void)
 {
 	int ret = 0;
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 221ae0c..f4c67f1 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -84,6 +84,7 @@
 struct ind_req_resp {
 	char service_path[SERVREG_NOTIF_NAME_LENGTH];
 	int transaction_id;
+	int curr_state;
 };
 
 /*
@@ -200,8 +201,30 @@
 	struct qmi_servreg_notif_set_ack_req_msg_v01 req;
 	struct msg_desc req_desc, resp_desc;
 	struct qmi_servreg_notif_set_ack_resp_msg_v01 resp = { { 0, 0 } };
+	struct service_notif_info *service_notif;
+	enum pd_subsys_state state = USER_PD_STATE_CHANGE;
 	int rc;
 
+	service_notif = _find_service_info(data->ind_msg.service_path);
+	if (!service_notif)
+		return;
+	if ((int)data->ind_msg.curr_state < QMI_STATE_MIN_VAL ||
+		(int)data->ind_msg.curr_state > QMI_STATE_MAX_VAL)
+		pr_err("Unexpected indication notification state %d\n",
+			data->ind_msg.curr_state);
+	else {
+		mutex_lock(&notif_add_lock);
+		mutex_lock(&service_list_lock);
+		rc = service_notif_queue_notification(service_notif,
+			data->ind_msg.curr_state, &state);
+		if (rc & NOTIFY_STOP_MASK)
+			pr_err("Notifier callback aborted for %s with error %d\n",
+				data->ind_msg.service_path, rc);
+		service_notif->curr_state = data->ind_msg.curr_state;
+		mutex_unlock(&service_list_lock);
+		mutex_unlock(&notif_add_lock);
+	}
+
 	req.transaction_id = data->ind_msg.transaction_id;
 	snprintf(req.service_name, ARRAY_SIZE(req.service_name), "%s",
 						data->ind_msg.service_path);
@@ -236,11 +259,9 @@
 				unsigned int msg_len, void *ind_cb_priv)
 {
 	struct qmi_client_info *data = (struct qmi_client_info *)ind_cb_priv;
-	struct service_notif_info *service_notif;
 	struct msg_desc ind_desc;
 	struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg = {
 					QMI_STATE_MIN_VAL, "", 0xFFFF };
-	enum pd_subsys_state state = USER_PD_STATE_CHANGE;
 	int rc;
 
 	ind_desc.msg_id = SERVREG_NOTIF_STATE_UPDATED_IND_MSG;
@@ -256,27 +277,8 @@
 		ind_msg.service_name, ind_msg.curr_state,
 		ind_msg.transaction_id);
 
-	service_notif = _find_service_info(ind_msg.service_name);
-	if (!service_notif)
-		return;
-
-	if ((int)ind_msg.curr_state < QMI_STATE_MIN_VAL ||
-			(int)ind_msg.curr_state > QMI_STATE_MAX_VAL)
-		pr_err("Unexpected indication notification state %d\n",
-							ind_msg.curr_state);
-	else {
-		mutex_lock(&notif_add_lock);
-		mutex_lock(&service_list_lock);
-		rc = service_notif_queue_notification(service_notif,
-					ind_msg.curr_state, &state);
-		if (rc & NOTIFY_STOP_MASK)
-			pr_err("Notifier callback aborted for %s with error %d\n",
-						ind_msg.service_name, rc);
-		service_notif->curr_state = ind_msg.curr_state;
-		mutex_unlock(&service_list_lock);
-		mutex_unlock(&notif_add_lock);
-	}
 	data->ind_msg.transaction_id = ind_msg.transaction_id;
+	data->ind_msg.curr_state = ind_msg.curr_state;
 	snprintf(data->ind_msg.service_path,
 		ARRAY_SIZE(data->ind_msg.service_path), "%s",
 		ind_msg.service_name);
@@ -373,6 +375,12 @@
 	mutex_unlock(&qmi_client_release_lock);
 	pr_info("Connection established between QMI handle and %d service\n",
 							data->instance_id);
+	/* Register for indication messages about service */
+	rc = qmi_register_ind_cb(data->clnt_handle,
+		root_service_service_ind_cb, (void *)data);
+	if (rc < 0)
+		pr_err("Indication callback register failed(instance-id: %d) rc:%d\n",
+			data->instance_id, rc);
 	mutex_lock(&notif_add_lock);
 	mutex_lock(&service_list_lock);
 	list_for_each_entry(service_notif, &service_list, list) {
@@ -395,12 +403,6 @@
 	}
 	mutex_unlock(&service_list_lock);
 	mutex_unlock(&notif_add_lock);
-	/* Register for indication messages about service */
-	rc = qmi_register_ind_cb(data->clnt_handle,
-		root_service_service_ind_cb, (void *)data);
-	if (rc < 0)
-		pr_err("Indication callback register failed(instance-id: %d) rc:%d\n",
-							data->instance_id, rc);
 }
 
 static void root_service_service_exit(struct qmi_client_info *data,
diff --git a/drivers/soc/qcom/smp2p_sleepstate.c b/drivers/soc/qcom/smp2p_sleepstate.c
index 5b0129e..9c764aa 100644
--- a/drivers/soc/qcom/smp2p_sleepstate.c
+++ b/drivers/soc/qcom/smp2p_sleepstate.c
@@ -14,6 +14,8 @@
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include <linux/delay.h>
+#include <linux/ipc_router.h>
 #include "smp2p_private.h"
 
 #define SET_DELAY (2 * HZ)
@@ -35,10 +37,14 @@
 	switch (event) {
 	case PM_SUSPEND_PREPARE:
 		gpio_set_value(slst_gpio_base_id + PROC_AWAKE_ID, 0);
+		msleep(25); /* To be tuned based on SMP2P latencies */
+		msm_ipc_router_set_ws_allowed(true);
 		break;
 
 	case PM_POST_SUSPEND:
 		gpio_set_value(slst_gpio_base_id + PROC_AWAKE_ID, 1);
+		msleep(25); /* To be tuned based on SMP2P latencies */
+		msm_ipc_router_set_ws_allowed(false);
 		break;
 	}
 	return NOTIFY_DONE;
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 31760ee..c69429c 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -592,10 +592,11 @@
 }
 EXPORT_SYMBOL_GPL(socinfo_get_id);
 
-static char *socinfo_get_id_string(void)
+char *socinfo_get_id_string(void)
 {
 	return (socinfo) ? cpu_of_id[socinfo->v0_1.id].soc_id_string : NULL;
 }
+EXPORT_SYMBOL(socinfo_get_id_string);
 
 uint32_t socinfo_get_version(void)
 {
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index 1c7c4a1..806b756 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -93,8 +93,6 @@
 /* SPCOM driver name */
 #define DEVICE_NAME	"spcom"
 
-#define SPCOM_MAX_CHANNELS	0x20
-
 /* maximum ION buffers should be >= SPCOM_MAX_CHANNELS  */
 #define SPCOM_MAX_ION_BUF_PER_CH (SPCOM_MAX_CHANNELS + 4)
 
@@ -195,6 +193,7 @@
 	 * glink state: CONNECTED / LOCAL_DISCONNECTED, REMOTE_DISCONNECTED
 	 */
 	unsigned int glink_state;
+	bool is_closing;
 
 	/* Events notification */
 	struct completion connect;
@@ -244,7 +243,7 @@
 	int channel_count;
 
 	/* private */
-	struct mutex lock;
+	struct mutex cmd_lock;
 
 	/* Link state */
 	struct completion link_state_changed;
@@ -483,7 +482,17 @@
 	switch (event) {
 	case GLINK_CONNECTED:
 		pr_debug("GLINK_CONNECTED, ch name [%s].\n", ch->name);
+		mutex_lock(&ch->lock);
+
+		if (ch->is_closing) {
+			pr_err("Unexpected CONNECTED while closing [%s].\n",
+				ch->name);
+			mutex_unlock(&ch->lock);
+			return;
+		}
+
 		ch->glink_state = event;
+
 		/*
 		 * if spcom_notify_state() is called within glink_open()
 		 * then ch->glink_handle is not updated yet.
@@ -493,17 +502,28 @@
 			ch->glink_handle = handle;
 		}
 
-		/* prepare default rx buffer after connected */
+		/* signal before unlock mutex & before calling glink */
+		complete_all(&ch->connect);
+
+		/*
+		 * Prepare default rx buffer.
+		 * glink_queue_rx_intent() can be called only AFTER connected.
+		 * We do it here, ASAP, to allow rx data.
+		 */
+
+		pr_debug("call glink_queue_rx_intent() ch [%s].\n", ch->name);
 		ret = glink_queue_rx_intent(ch->glink_handle,
 					    ch, ch->rx_buf_size);
 		if (ret) {
 			pr_err("glink_queue_rx_intent() err [%d]\n", ret);
 		} else {
-			pr_debug("rx buf is ready, size [%zu].\n",
+			pr_debug("rx buf is ready, size [%zu]\n",
 				 ch->rx_buf_size);
 			ch->rx_buf_ready = true;
 		}
-		complete_all(&ch->connect);
+
+		pr_debug("GLINK_CONNECTED, ch name [%s] done.\n", ch->name);
+		mutex_unlock(&ch->lock);
 		break;
 	case GLINK_LOCAL_DISCONNECTED:
 		/*
@@ -556,9 +576,7 @@
 static bool spcom_notify_rx_intent_req(void *handle, const void *priv,
 				       size_t req_size)
 {
-	struct spcom_channel *ch = (struct spcom_channel *) priv;
-
-	pr_err("Unexpected intent request for ch [%s].\n", ch->name);
+	pr_err("Unexpected intent request\n");
 
 	return false;
 }
@@ -670,6 +688,13 @@
 	ch->glink_state = GLINK_LOCAL_DISCONNECTED;
 	ch->actual_rx_size = 0;
 	ch->rx_buf_size = SPCOM_RX_BUF_SIZE;
+	ch->is_closing = false;
+	ch->glink_handle = NULL;
+	ch->ref_count = 0;
+	ch->rx_abort = false;
+	ch->tx_abort = false;
+	ch->txn_id = INITIAL_TXN_ID; /* use non-zero nonce for debug */
+	ch->pid = 0;
 
 	return 0;
 }
@@ -739,6 +764,8 @@
 	/* init completion before calling glink_open() */
 	reinit_completion(&ch->connect);
 
+	ch->is_closing = false;
+
 	handle = glink_open(&cfg);
 	if (IS_ERR_OR_NULL(handle)) {
 		pr_err("glink_open failed.\n");
@@ -753,6 +780,8 @@
 	ch->pid = current_pid();
 	ch->txn_id = INITIAL_TXN_ID;
 
+	mutex_unlock(&ch->lock);
+
 	pr_debug("Wait for connection on channel [%s] timeout_msec [%d].\n",
 		 name, timeout_msec);
 
@@ -769,8 +798,6 @@
 		pr_debug("Channel [%s] opened, no timeout.\n", name);
 	}
 
-	mutex_unlock(&ch->lock);
-
 	return 0;
 exit_err:
 	mutex_unlock(&ch->lock);
@@ -797,6 +824,8 @@
 		return 0;
 	}
 
+	ch->is_closing = true;
+
 	ret = glink_close(ch->glink_handle);
 	if (ret)
 		pr_err("glink_close() fail, ret [%d].\n", ret);
@@ -812,6 +841,7 @@
 	ch->pid = 0;
 
 	pr_debug("Channel closed [%s].\n", ch->name);
+
 	mutex_unlock(&ch->lock);
 
 	return 0;
@@ -1090,12 +1120,12 @@
 
 	if (!spcom_is_ready()) {
 		pr_err("spcom is not ready.\n");
-			return NULL;
+		return NULL;
 	}
 
 	if (!info) {
 		pr_err("Invalid parameter.\n");
-			return NULL;
+		return NULL;
 	}
 	name = info->ch_name;
 
@@ -1924,18 +1954,6 @@
 }
 
 /**
- * spcom_handle_fake_ssr_command() - Handle fake ssr command from user space.
- */
-static int spcom_handle_fake_ssr_command(struct spcom_channel *ch, int arg)
-{
-	pr_debug("Start Fake glink SSR subsystem [%s].\n", spcom_edge);
-	glink_ssr(spcom_edge);
-	pr_debug("Fake glink SSR subsystem [%s] done.\n", spcom_edge);
-
-	return 0;
-}
-
-/**
  * spcom_handle_write() - Handle user space write commands.
  *
  * @buf:	command buffer.
@@ -1964,6 +1982,8 @@
 	swap_id = htonl(cmd->cmd_id);
 	memcpy(cmd_name, &swap_id, sizeof(int));
 
+	mutex_lock(&spcom_dev->cmd_lock);
+
 	pr_debug("cmd_id [0x%x] cmd_name [%s].\n", cmd_id, cmd_name);
 
 	switch (cmd_id) {
@@ -1979,17 +1999,16 @@
 	case SPCOM_CMD_UNLOCK_ION_BUF:
 		ret = spcom_handle_unlock_ion_buf_command(ch, buf, buf_size);
 		break;
-	case SPCOM_CMD_FSSR:
-		ret = spcom_handle_fake_ssr_command(ch, cmd->arg);
-		break;
 	case SPCOM_CMD_CREATE_CHANNEL:
 		ret = spcom_handle_create_channel_command(buf, buf_size);
 		break;
 	default:
 		pr_err("Invalid Command Id [0x%x].\n", (int) cmd->cmd_id);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 
+	mutex_unlock(&spcom_dev->cmd_lock);
+
 	return ret;
 }
 
@@ -2690,7 +2709,7 @@
 		return -ENOMEM;
 
 	spcom_dev = dev;
-	mutex_init(&dev->lock);
+	mutex_init(&spcom_dev->cmd_lock);
 	init_completion(&dev->link_state_changed);
 	spcom_dev->link_state = GLINK_LINK_STATE_DOWN;
 
@@ -2763,7 +2782,7 @@
 {
 	int ret;
 
-	pr_info("spcom driver Ver 1.0 23-Nov-2015.\n");
+	pr_info("spcom driver version 1.1 17-July-2017.\n");
 
 	ret = platform_driver_register(&spcom_driver);
 	if (ret)
diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c
index f8f6829..01eb260 100644
--- a/drivers/soc/qcom/subsys-pil-tz.c
+++ b/drivers/soc/qcom/subsys-pil-tz.c
@@ -795,6 +795,33 @@
 	return rc;
 }
 
+static int pil_deinit_image_trusted(struct pil_desc *pil)
+{
+	struct pil_tz_data *d = desc_to_data(pil);
+	u32 proc, scm_ret = 0;
+	int rc;
+	struct scm_desc desc = {0};
+
+	if (d->subsys_desc.no_auth)
+		return 0;
+
+	desc.args[0] = proc = d->pas_id;
+	desc.arginfo = SCM_ARGS(1);
+
+	if (!is_scm_armv8()) {
+		rc = scm_call(SCM_SVC_PIL, PAS_SHUTDOWN_CMD, &proc,
+			      sizeof(proc), &scm_ret, sizeof(scm_ret));
+	} else {
+		rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD),
+			       &desc);
+		scm_ret = desc.ret[0];
+	}
+
+	if (rc)
+		return rc;
+	return scm_ret;
+}
+
 static struct pil_reset_ops pil_ops_trusted = {
 	.init_image = pil_init_image_trusted,
 	.mem_setup =  pil_mem_setup_trusted,
@@ -802,6 +829,7 @@
 	.shutdown = pil_shutdown_trusted,
 	.proxy_vote = pil_make_proxy_vote,
 	.proxy_unvote = pil_remove_proxy_vote,
+	.deinit_image = pil_deinit_image_trusted,
 };
 
 static void log_failure_reason(const struct pil_tz_data *d)
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index ad3eb187..6acb731 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -12,18 +12,21 @@
  *
  */
 #include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/ipc_logging.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/qcom-geni-se.h>
+#include <linux/msm_gpi.h>
 #include <linux/spi/spi.h>
 
 #define SPI_NUM_CHIPSELECT	(4)
 #define SPI_XFER_TIMEOUT_MS	(250)
-#define SPI_OVERSAMPLING	(2)
 /* SPI SE specific registers */
 #define SE_SPI_CPHA		(0x224)
 #define SE_SPI_LOOPBACK		(0x22C)
@@ -80,6 +83,36 @@
 #define POST_CMD_DELAY		BIT(4)
 
 #define SPI_CORE2X_VOTE		(10000)
+/* GSI CONFIG0 TRE Params */
+/* Flags bit fields */
+#define GSI_LOOPBACK_EN		(BIT(0))
+#define GSI_CS_TOGGLE		(BIT(3))
+#define GSI_CPHA		(BIT(4))
+#define GSI_CPOL		(BIT(5))
+
+#define MAX_TX_SG		(3)
+#define NUM_SPI_XFER		(8)
+
+struct gsi_desc_cb {
+	struct spi_master *spi;
+	struct spi_transfer *xfer;
+};
+
+struct spi_geni_gsi {
+	struct msm_gpi_tre config0_tre;
+	struct msm_gpi_tre go_tre;
+	struct msm_gpi_tre tx_dma_tre;
+	struct msm_gpi_tre rx_dma_tre;
+	struct scatterlist tx_sg[MAX_TX_SG];
+	struct scatterlist rx_sg;
+	dma_cookie_t tx_cookie;
+	dma_cookie_t rx_cookie;
+	struct msm_gpi_dma_async_tx_cb_param tx_cb_param;
+	struct msm_gpi_dma_async_tx_cb_param rx_cb_param;
+	struct dma_async_tx_descriptor *tx_desc;
+	struct dma_async_tx_descriptor *rx_desc;
+	struct gsi_desc_cb desc_cb;
+};
 
 struct spi_geni_master {
 	struct se_geni_rsc spi_rsc;
@@ -100,6 +133,20 @@
 	struct spi_transfer *cur_xfer;
 	struct completion xfer_done;
 	struct device *wrapper_dev;
+	int oversampling;
+	struct spi_geni_gsi *gsi;
+	struct dma_chan *tx;
+	struct dma_chan *rx;
+	struct msm_gpi_ctrl tx_event;
+	struct msm_gpi_ctrl rx_event;
+	struct completion tx_cb;
+	struct completion rx_cb;
+	bool qn_err;
+	int cur_xfer_mode;
+	int num_tx_eot;
+	int num_rx_eot;
+	int num_xfers;
+	void *ipc;
 };
 
 static struct spi_master *get_spi_master(struct device *dev)
@@ -110,69 +157,68 @@
 	return spi;
 }
 
-static int do_spi_clk_cfg(u32 speed_hz, struct spi_geni_master *mas)
+static int get_spi_clk_cfg(u32 speed_hz, struct spi_geni_master *mas,
+			int *clk_idx, int *clk_div)
 {
 	unsigned long sclk_freq;
-	int div = 0;
-	int idx;
 	struct se_geni_rsc *rsc = &mas->spi_rsc;
-	u32 clk_sel = geni_read_reg(mas->base, SE_GENI_CLK_SEL);
-	u32 m_clk_cfg = geni_read_reg(mas->base, GENI_SER_M_CLK_CFG);
-	int ret;
+	int ret = 0;
 
-	clk_sel &= ~CLK_SEL_MSK;
-	m_clk_cfg &= ~CLK_DIV_MSK;
-
-	ret = geni_se_clk_freq_match(&mas->spi_rsc, speed_hz, &idx,
-					&sclk_freq, true);
+	ret = geni_se_clk_freq_match(&mas->spi_rsc,
+				(speed_hz * mas->oversampling), clk_idx,
+				&sclk_freq, true);
 	if (ret) {
 		dev_err(mas->dev, "%s: Failed(%d) to find src clk for 0x%x\n",
 						__func__, ret, speed_hz);
 		return ret;
 	}
 
-	div = ((sclk_freq / SPI_OVERSAMPLING) / speed_hz);
-	if (!div)
+	*clk_div = ((sclk_freq / mas->oversampling) / speed_hz);
+	if (!(*clk_div)) {
+		dev_err(mas->dev, "%s:Err:sclk:%lu oversampling:%d speed:%u\n",
+			__func__, sclk_freq, mas->oversampling, speed_hz);
 		return -EINVAL;
+	}
 
 	dev_dbg(mas->dev, "%s: req %u sclk %lu, idx %d, div %d\n", __func__,
-						speed_hz, sclk_freq, idx, div);
-	clk_sel |= (idx & CLK_SEL_MSK);
-	m_clk_cfg |= ((div << CLK_DIV_SHFT) | SER_CLK_EN);
+				speed_hz, sclk_freq, *clk_idx, *clk_div);
 	ret = clk_set_rate(rsc->se_clk, sclk_freq);
 	if (ret)
-		return ret;
-
-	geni_write_reg(clk_sel, mas->base, SE_GENI_CLK_SEL);
-	geni_write_reg(m_clk_cfg, mas->base, GENI_SER_M_CLK_CFG);
-	return 0;
+		dev_err(mas->dev, "%s: clk_set_rate failed %d\n",
+							__func__, ret);
+	return ret;
 }
 
 static void spi_setup_word_len(struct spi_geni_master *mas, u32 mode,
 						int bits_per_word)
 {
-	int pack_words = mas->tx_fifo_width / bits_per_word;
+	int pack_words = 0;
 	bool msb_first = (mode & SPI_LSB_FIRST) ? false : true;
 	u32 word_len = geni_read_reg(mas->base, SE_SPI_WORD_LEN);
 
+	if (!(mas->tx_fifo_width % bits_per_word))
+		pack_words = mas->tx_fifo_width / bits_per_word;
 	word_len &= ~WORD_LEN_MSK;
 	word_len |= ((bits_per_word - MIN_WORD_LEN) & WORD_LEN_MSK);
 	se_config_packing(mas->base, bits_per_word, pack_words, msb_first);
 	geni_write_reg(word_len, mas->base, SE_SPI_WORD_LEN);
 }
 
-static int spi_geni_prepare_message(struct spi_master *spi_mas,
-					struct spi_message *spi_msg)
+static int setup_fifo_params(struct spi_device *spi_slv,
+					struct spi_master *spi)
 {
-	struct spi_device *spi_slv = spi_msg->spi;
-	struct spi_geni_master *mas = spi_master_get_devdata(spi_mas);
+	struct spi_geni_master *mas = spi_master_get_devdata(spi);
 	u16 mode = spi_slv->mode;
 	u32 loopback_cfg = geni_read_reg(mas->base, SE_SPI_LOOPBACK);
 	u32 cpol = geni_read_reg(mas->base, SE_SPI_CPOL);
 	u32 cpha = geni_read_reg(mas->base, SE_SPI_CPHA);
 	u32 demux_sel = 0;
 	u32 demux_output_inv = 0;
+	u32 clk_sel = geni_read_reg(mas->base, SE_GENI_CLK_SEL);
+	u32 m_clk_cfg = geni_read_reg(mas->base, GENI_SER_M_CLK_CFG);
 	int ret = 0;
+	int idx;
+	int div;
 
 	loopback_cfg &= ~LOOPBACK_MSK;
 	cpol &= ~CPOL;
@@ -194,21 +240,434 @@
 	mas->cur_speed_hz = spi_slv->max_speed_hz;
 	mas->cur_word_len = spi_slv->bits_per_word;
 
-	ret = do_spi_clk_cfg(mas->cur_speed_hz, mas);
+	ret = get_spi_clk_cfg(mas->cur_speed_hz, mas, &idx, &div);
 	if (ret) {
-		dev_err(&spi_mas->dev, "Err setting clks ret(%d) for %d\n",
+		dev_err(mas->dev, "Err setting clks ret(%d) for %d\n",
 							ret, mas->cur_speed_hz);
-		goto prepare_message_exit;
+		goto setup_fifo_params_exit;
 	}
+
+	clk_sel |= (idx & CLK_SEL_MSK);
+	m_clk_cfg |= ((div << CLK_DIV_SHFT) | SER_CLK_EN);
 	spi_setup_word_len(mas, spi_slv->mode, spi_slv->bits_per_word);
 	geni_write_reg(loopback_cfg, mas->base, SE_SPI_LOOPBACK);
 	geni_write_reg(demux_sel, mas->base, SE_SPI_DEMUX_SEL);
 	geni_write_reg(cpha, mas->base, SE_SPI_CPHA);
 	geni_write_reg(cpol, mas->base, SE_SPI_CPOL);
 	geni_write_reg(demux_output_inv, mas->base, SE_SPI_DEMUX_OUTPUT_INV);
+	geni_write_reg(clk_sel, mas->base, SE_GENI_CLK_SEL);
+	geni_write_reg(m_clk_cfg, mas->base, GENI_SER_M_CLK_CFG);
 	/* Ensure message level attributes are written before returning */
 	mb();
-prepare_message_exit:
+setup_fifo_params_exit:
+	return ret;
+}
+
+
+static int select_xfer_mode(struct spi_master *spi,
+				struct spi_message *spi_msg)
+{
+	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+	int mode = FIFO_MODE;
+	int fifo_disable = (geni_read_reg(mas->base, GENI_IF_FIFO_DISABLE_RO) &
+							FIFO_IF_DISABLE);
+	bool dma_chan_valid =
+		!(IS_ERR_OR_NULL(mas->tx) || IS_ERR_OR_NULL(mas->rx));
+
+	/*
+	 * If FIFO Interface is disabled and there are no DMA channels then we
+	 * can't do this transfer.
+	 * If FIFO interface is disabled, we can do GSI only,
+	 * else pick FIFO mode.
+	 */
+	if (fifo_disable && !dma_chan_valid)
+		mode = -EINVAL;
+	else if (fifo_disable)
+		mode = GSI_DMA;
+	else
+		mode = FIFO_MODE;
+	return mode;
+}
+
+static struct msm_gpi_tre *setup_config0_tre(struct spi_transfer *xfer,
+				struct spi_geni_master *mas, u16 mode)
+{
+	struct msm_gpi_tre *c0_tre = &mas->gsi[mas->num_xfers].config0_tre;
+	u8 flags = 0;
+	u8 word_len = 0;
+	u8 pack = 0;
+	int div = 0;
+	int idx = 0;
+	int ret = 0;
+
+	if (IS_ERR_OR_NULL(c0_tre))
+		return c0_tre;
+
+	if (mode & SPI_LOOP)
+		flags |= GSI_LOOPBACK_EN;
+
+	if (mode & SPI_CPOL)
+		flags |= GSI_CPOL;
+
+	if (mode & SPI_CPHA)
+		flags |= GSI_CPHA;
+
+	if (xfer->cs_change)
+		flags |= GSI_CS_TOGGLE;
+
+	word_len = xfer->bits_per_word - MIN_WORD_LEN;
+	if (mas->tx_fifo_width % xfer->bits_per_word)
+		pack = 0;
+	else
+		pack |= (GSI_TX_PACK_EN | GSI_RX_PACK_EN);
+	ret = get_spi_clk_cfg(mas->cur_speed_hz, mas, &idx, &div);
+	if (ret) {
+		dev_err(mas->dev, "%s:Err setting clks:%d\n", __func__, ret);
+		return ERR_PTR(ret);
+	}
+	c0_tre->dword[0] = MSM_GPI_SPI_CONFIG0_TRE_DWORD0(pack, flags,
+								word_len);
+	c0_tre->dword[1] = MSM_GPI_SPI_CONFIG0_TRE_DWORD1(0, 0, 0);
+	c0_tre->dword[2] = MSM_GPI_SPI_CONFIG0_TRE_DWORD2(idx, div);
+	c0_tre->dword[3] = MSM_GPI_SPI_CONFIG0_TRE_DWORD3(0, 0, 0, 1);
+	GENI_SE_DBG(mas->ipc, false, mas->dev,
+		"%s: flags 0x%x word %d pack %d idx %d div %d\n",
+		__func__, flags, word_len, pack, idx, div);
+	return c0_tre;
+}
+
+static struct msm_gpi_tre *setup_go_tre(int cmd, int cs, int rx_len, int flags,
+				struct spi_geni_master *mas)
+{
+	struct msm_gpi_tre *go_tre = &mas->gsi[mas->num_xfers].go_tre;
+	int chain;
+	int eot;
+	int eob;
+
+	if (IS_ERR_OR_NULL(go_tre))
+		return go_tre;
+
+	go_tre->dword[0] = MSM_GPI_SPI_GO_TRE_DWORD0(flags, cs, cmd);
+	go_tre->dword[1] = MSM_GPI_SPI_GO_TRE_DWORD1;
+	go_tre->dword[2] = MSM_GPI_SPI_GO_TRE_DWORD2(rx_len);
+	if (cmd == SPI_RX_ONLY) {
+		eot = 0;
+		chain = 0;
+		eob = 1;
+	} else {
+		eot = 0;
+		chain = 1;
+		eob = 0;
+	}
+	go_tre->dword[3] = MSM_GPI_SPI_GO_TRE_DWORD3(0, eot, eob, chain);
+	GENI_SE_DBG(mas->ipc, false, mas->dev,
+		"%s: rx len %d flags 0x%x cs %d cmd %d eot %d eob %d chain %d\n",
+		__func__, rx_len, flags, cs, cmd, eot, eob, chain);
+	return go_tre;
+}
+
+static struct msm_gpi_tre *setup_dma_tre(struct msm_gpi_tre *tre,
+					dma_addr_t buf, u32 len,
+					struct spi_geni_master *mas,
+					bool is_tx)
+{
+	if (IS_ERR_OR_NULL(tre))
+		return tre;
+
+	tre->dword[0] = MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(buf);
+	tre->dword[1] = MSM_GPI_DMA_W_BUFFER_TRE_DWORD1(buf);
+	tre->dword[2] = MSM_GPI_DMA_W_BUFFER_TRE_DWORD2(len);
+	tre->dword[3] = MSM_GPI_DMA_W_BUFFER_TRE_DWORD3(0, is_tx, 0, 0);
+	return tre;
+}
+
+static void spi_gsi_ch_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb,
+				void *ptr)
+{
+	struct spi_master *spi = ptr;
+	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+
+	switch (cb->cb_event) {
+	case MSM_GPI_QUP_NOTIFY:
+	case MSM_GPI_QUP_MAX_EVENT:
+		GENI_SE_DBG(mas->ipc, false, mas->dev,
+				"%s:cb_ev%d status%llu ts%llu count%llu\n",
+				__func__, cb->cb_event, cb->status,
+				cb->timestamp, cb->count);
+		break;
+	case MSM_GPI_QUP_ERROR:
+	case MSM_GPI_QUP_CH_ERROR:
+	case MSM_GPI_QUP_FW_ERROR:
+	case MSM_GPI_QUP_PENDING_EVENT:
+	case MSM_GPI_QUP_EOT_DESC_MISMATCH:
+	case MSM_GPI_QUP_SW_ERROR:
+		GENI_SE_ERR(mas->ipc, true, mas->dev,
+				"%s: cb_ev %d status %llu ts %llu count %llu\n",
+				__func__, cb->cb_event, cb->status,
+				cb->timestamp, cb->count);
+		GENI_SE_ERR(mas->ipc, true, mas->dev,
+				"err.routine %u, err.type %u, err.code %u\n",
+				cb->error_log.routine,
+				cb->error_log.type,
+				cb->error_log.error_code);
+		mas->qn_err = true;
+		complete_all(&mas->tx_cb);
+		complete_all(&mas->rx_cb);
+
+		break;
+	};
+}
+
+static void spi_gsi_rx_callback(void *cb)
+{
+	struct msm_gpi_dma_async_tx_cb_param *cb_param =
+			(struct msm_gpi_dma_async_tx_cb_param *)cb;
+	struct gsi_desc_cb *desc_cb = (struct gsi_desc_cb *)cb_param->userdata;
+	struct spi_master *spi = desc_cb->spi;
+	struct spi_transfer *xfer = desc_cb->xfer;
+	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+
+	if (xfer->rx_buf) {
+		if (cb_param->status == MSM_GPI_TCE_UNEXP_ERR) {
+			GENI_SE_ERR(mas->ipc, true, mas->dev,
+			"%s: Unexpected GSI CB error\n", __func__);
+			return;
+		}
+		if (cb_param->length == xfer->len) {
+			GENI_SE_DBG(mas->ipc, false, mas->dev,
+			"%s\n", __func__);
+			complete(&mas->rx_cb);
+		} else {
+			GENI_SE_ERR(mas->ipc, true, mas->dev,
+			"%s: Length mismatch. Expected %d Callback %d\n",
+			__func__, xfer->len, cb_param->length);
+		}
+	}
+}
+
+static void spi_gsi_tx_callback(void *cb)
+{
+	struct msm_gpi_dma_async_tx_cb_param *cb_param = cb;
+	struct gsi_desc_cb *desc_cb = (struct gsi_desc_cb *)cb_param->userdata;
+	struct spi_master *spi = desc_cb->spi;
+	struct spi_transfer *xfer = desc_cb->xfer;
+	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+
+	if (xfer->tx_buf) {
+		if (cb_param->status == MSM_GPI_TCE_UNEXP_ERR) {
+			GENI_SE_ERR(mas->ipc, true, mas->dev,
+			"%s: Unexpected GSI CB error\n", __func__);
+			return;
+		}
+		if (cb_param->length == xfer->len) {
+			GENI_SE_DBG(mas->ipc, false, mas->dev,
+			"%s\n", __func__);
+			complete(&mas->tx_cb);
+		} else {
+			GENI_SE_ERR(mas->ipc, true, mas->dev,
+			"%s: Length mismatch. Expected %d Callback %d\n",
+			__func__, xfer->len, cb_param->length);
+		}
+	}
+}
+
+static int setup_gsi_xfer(struct spi_transfer *xfer,
+				struct spi_geni_master *mas,
+				struct spi_device *spi_slv,
+				struct spi_master *spi)
+{
+	int ret = 0;
+	struct msm_gpi_tre *c0_tre = NULL;
+	struct msm_gpi_tre *go_tre = NULL;
+	struct msm_gpi_tre *tx_tre = NULL;
+	struct msm_gpi_tre *rx_tre = NULL;
+	struct scatterlist *xfer_tx_sg = mas->gsi[mas->num_xfers].tx_sg;
+	struct scatterlist *xfer_rx_sg = &mas->gsi[mas->num_xfers].rx_sg;
+	int rx_nent = 0;
+	int tx_nent = 0;
+	u8 cmd = 0;
+	u8 cs = 0;
+	u32 rx_len = 0;
+	int go_flags = 0;
+	unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+
+	if ((xfer->bits_per_word != mas->cur_word_len) ||
+		(xfer->speed_hz != mas->cur_speed_hz)) {
+		mas->cur_word_len = xfer->bits_per_word;
+		mas->cur_speed_hz = xfer->speed_hz;
+		tx_nent++;
+		c0_tre = setup_config0_tre(xfer, mas, spi_slv->mode);
+		if (IS_ERR_OR_NULL(c0_tre)) {
+			dev_err(mas->dev, "%s:Err setting c0tre:%d\n",
+							__func__, ret);
+			return PTR_ERR(c0_tre);
+		}
+	}
+
+	if (xfer->tx_buf && xfer->rx_buf) {
+		cmd = SPI_FULL_DUPLEX;
+		tx_nent += 2;
+		rx_nent++;
+		rx_len = ((xfer->len << 3) / mas->cur_word_len);
+	} else if (xfer->tx_buf) {
+		cmd = SPI_TX_ONLY;
+		tx_nent += 2;
+	} else if (xfer->rx_buf) {
+		cmd = SPI_RX_ONLY;
+		tx_nent++;
+		rx_nent++;
+		rx_len = ((xfer->len << 3) / mas->cur_word_len);
+	}
+
+	cs |= spi_slv->chip_select;
+	if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
+		go_flags |= FRAGMENTATION;
+	go_tre = setup_go_tre(cmd, cs, rx_len, go_flags, mas);
+
+	sg_init_table(xfer_tx_sg, tx_nent);
+	if (rx_nent)
+		sg_init_table(xfer_rx_sg, rx_nent);
+
+	if (c0_tre)
+		sg_set_buf(xfer_tx_sg++, c0_tre, sizeof(*c0_tre));
+
+	sg_set_buf(xfer_tx_sg++, go_tre, sizeof(*go_tre));
+	mas->gsi[mas->num_xfers].desc_cb.spi = spi;
+	mas->gsi[mas->num_xfers].desc_cb.xfer = xfer;
+	if (cmd & SPI_RX_ONLY) {
+		rx_tre = &mas->gsi[mas->num_xfers].rx_dma_tre;
+		rx_tre = setup_dma_tre(rx_tre, xfer->rx_dma, xfer->len, mas, 0);
+		if (IS_ERR_OR_NULL(rx_tre)) {
+			dev_err(mas->dev, "Err setting up rx tre\n");
+			return PTR_ERR(rx_tre);
+		}
+		sg_set_buf(xfer_rx_sg, rx_tre, sizeof(*rx_tre));
+		mas->gsi[mas->num_xfers].rx_desc =
+			dmaengine_prep_slave_sg(mas->rx,
+				&mas->gsi[mas->num_xfers].rx_sg, rx_nent,
+						DMA_DEV_TO_MEM, flags);
+		if (IS_ERR_OR_NULL(mas->gsi[mas->num_xfers].rx_desc)) {
+			dev_err(mas->dev, "Err setting up rx desc\n");
+			return -EIO;
+		}
+		mas->gsi[mas->num_xfers].rx_desc->callback =
+					spi_gsi_rx_callback;
+		mas->gsi[mas->num_xfers].rx_desc->callback_param =
+					&mas->gsi[mas->num_xfers].rx_cb_param;
+		mas->gsi[mas->num_xfers].rx_cb_param.userdata =
+					&mas->gsi[mas->num_xfers].desc_cb;
+		mas->num_rx_eot++;
+	}
+
+	if (cmd & SPI_TX_ONLY) {
+		tx_tre = &mas->gsi[mas->num_xfers].tx_dma_tre;
+		tx_tre = setup_dma_tre(tx_tre, xfer->tx_dma, xfer->len, mas, 1);
+		if (IS_ERR_OR_NULL(tx_tre)) {
+			dev_err(mas->dev, "Err setting up tx tre\n");
+			return PTR_ERR(tx_tre);
+		}
+		sg_set_buf(xfer_tx_sg++, tx_tre, sizeof(*tx_tre));
+		mas->num_tx_eot++;
+	}
+	mas->gsi[mas->num_xfers].tx_desc = dmaengine_prep_slave_sg(mas->tx,
+					mas->gsi[mas->num_xfers].tx_sg, tx_nent,
+					DMA_MEM_TO_DEV, flags);
+	if (IS_ERR_OR_NULL(mas->gsi[mas->num_xfers].tx_desc)) {
+		dev_err(mas->dev, "Err setting up tx desc\n");
+		return -EIO;
+	}
+	mas->gsi[mas->num_xfers].tx_desc->callback = spi_gsi_tx_callback;
+	mas->gsi[mas->num_xfers].tx_desc->callback_param =
+					&mas->gsi[mas->num_xfers].tx_cb_param;
+	mas->gsi[mas->num_xfers].tx_cb_param.userdata =
+					&mas->gsi[mas->num_xfers].desc_cb;
+	mas->gsi[mas->num_xfers].tx_cookie =
+			dmaengine_submit(mas->gsi[mas->num_xfers].tx_desc);
+	if (mas->num_rx_eot)
+		mas->gsi[mas->num_xfers].rx_cookie =
+			dmaengine_submit(mas->gsi[mas->num_xfers].rx_desc);
+	dma_async_issue_pending(mas->tx);
+	if (mas->num_rx_eot)
+		dma_async_issue_pending(mas->rx);
+	mas->num_xfers++;
+	return ret;
+}
+
+static int spi_geni_map_buf(struct spi_geni_master *mas,
+				struct spi_message *msg)
+{
+	struct spi_transfer *xfer;
+	struct device *gsi_dev = mas->dev;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (xfer->rx_buf) {
+			xfer->rx_dma = dma_map_single(gsi_dev, xfer->rx_buf,
+						xfer->len, DMA_FROM_DEVICE);
+			if (dma_mapping_error(mas->dev, xfer->rx_dma)) {
+				dev_err(mas->dev, "Err mapping buf\n");
+				return -ENOMEM;
+			}
+		}
+
+		if (xfer->tx_buf) {
+			xfer->tx_dma = dma_map_single(gsi_dev,
+				(void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE);
+			if (dma_mapping_error(gsi_dev, xfer->tx_dma)) {
+				dev_err(mas->dev, "Err mapping buf\n");
+				dma_unmap_single(gsi_dev, xfer->rx_dma,
+						xfer->len, DMA_FROM_DEVICE);
+				return -ENOMEM;
+			}
+		}
+	};
+
+	return 0;
+}
+
+static void spi_geni_unmap_buf(struct spi_geni_master *mas,
+				struct spi_message *msg)
+{
+	struct spi_transfer *xfer;
+	struct device *gsi_dev = mas->dev;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (xfer->rx_buf)
+			dma_unmap_single(gsi_dev, xfer->rx_dma,
+						xfer->len, DMA_FROM_DEVICE);
+		if (xfer->tx_buf)
+			dma_unmap_single(gsi_dev, xfer->tx_dma,
+						xfer->len, DMA_TO_DEVICE);
+	};
+}
+
+static int spi_geni_prepare_message(struct spi_master *spi,
+					struct spi_message *spi_msg)
+{
+	int ret = 0;
+	struct spi_geni_master *mas = spi_master_get_devdata(spi);
+
+	mas->cur_xfer_mode = select_xfer_mode(spi, spi_msg);
+
+	if (mas->cur_xfer_mode == FIFO_MODE) {
+		geni_se_select_mode(mas->base, FIFO_MODE);
+		reinit_completion(&mas->xfer_done);
+		setup_fifo_params(spi_msg->spi, spi);
+	} else if (mas->cur_xfer_mode == GSI_DMA) {
+		mas->num_tx_eot = 0;
+		mas->num_rx_eot = 0;
+		mas->num_xfers = 0;
+		reinit_completion(&mas->tx_cb);
+		reinit_completion(&mas->rx_cb);
+		memset(mas->gsi, 0,
+				(sizeof(struct spi_geni_gsi) * NUM_SPI_XFER));
+		geni_se_select_mode(mas->base, GSI_DMA);
+		dmaengine_resume(mas->tx);
+		ret = spi_geni_map_buf(mas, spi_msg);
+	} else {
+		dev_err(mas->dev, "%s: Couldn't select mode %d", __func__,
+							mas->cur_xfer_mode);
+		ret = -EINVAL;
+	}
 	return ret;
 }
 
@@ -219,6 +678,10 @@
 
 	mas->cur_speed_hz = 0;
 	mas->cur_word_len = 0;
+	if (mas->cur_xfer_mode == GSI_DMA) {
+		dmaengine_pause(mas->tx);
+		spi_geni_unmap_buf(mas, spi_msg);
+	}
 	return 0;
 }
 
@@ -238,22 +701,89 @@
 
 	if (unlikely(!mas->setup)) {
 		int proto = get_se_proto(mas->base);
+		unsigned int major;
+		unsigned int minor;
+		unsigned int step;
+		int hw_ver;
 
 		if (unlikely(proto != SPI)) {
 			dev_err(mas->dev, "Invalid proto %d\n", proto);
 			return -ENXIO;
 		}
 		geni_se_init(mas->base, 0x0, (mas->tx_fifo_depth - 2));
-		geni_se_select_mode(mas->base, FIFO_MODE);
 		mas->tx_fifo_depth = get_tx_fifo_depth(mas->base);
 		mas->rx_fifo_depth = get_rx_fifo_depth(mas->base);
 		mas->tx_fifo_width = get_tx_fifo_width(mas->base);
+		mas->oversampling = 1;
 		/* Transmit an entire FIFO worth of data per IRQ */
 		mas->tx_wm = 1;
-		dev_dbg(mas->dev, "tx_fifo %d rx_fifo %d tx_width %d\n",
+
+		mas->tx = dma_request_slave_channel(mas->dev, "tx");
+		if (IS_ERR_OR_NULL(mas->tx)) {
+			dev_info(mas->dev, "Failed to get tx DMA ch %ld",
+							PTR_ERR(mas->tx));
+		} else {
+			mas->rx = dma_request_slave_channel(mas->dev, "rx");
+			if (IS_ERR_OR_NULL(mas->rx)) {
+				dev_info(mas->dev, "Failed to get rx DMA ch %ld",
+							PTR_ERR(mas->rx));
+				dma_release_channel(mas->tx);
+			}
+			mas->gsi = devm_kzalloc(mas->dev,
+				(sizeof(struct spi_geni_gsi) * NUM_SPI_XFER),
+				GFP_KERNEL);
+			if (IS_ERR_OR_NULL(mas->gsi)) {
+				dev_err(mas->dev, "Failed to get GSI mem\n");
+				dma_release_channel(mas->tx);
+				dma_release_channel(mas->rx);
+				mas->tx = NULL;
+				mas->rx = NULL;
+				goto setup_ipc;
+			}
+			mas->tx_event.init.callback = spi_gsi_ch_cb;
+			mas->tx_event.init.cb_param = spi;
+			mas->tx_event.cmd = MSM_GPI_INIT;
+			mas->tx->private = &mas->tx_event;
+			mas->rx_event.init.callback = spi_gsi_ch_cb;
+			mas->rx_event.init.cb_param = spi;
+			mas->rx_event.cmd = MSM_GPI_INIT;
+			mas->rx->private = &mas->rx_event;
+			if (dmaengine_slave_config(mas->tx, NULL)) {
+				dev_err(mas->dev, "Failed to Config Tx\n");
+				dma_release_channel(mas->tx);
+				dma_release_channel(mas->rx);
+				mas->tx = NULL;
+				mas->rx = NULL;
+				goto setup_ipc;
+			}
+			if (dmaengine_slave_config(mas->rx, NULL)) {
+				dev_err(mas->dev, "Failed to Config Rx\n");
+				dma_release_channel(mas->tx);
+				dma_release_channel(mas->rx);
+				mas->tx = NULL;
+				mas->rx = NULL;
+				goto setup_ipc;
+			}
+
+		}
+setup_ipc:
+		mas->ipc = ipc_log_context_create(4, dev_name(mas->dev), 0);
+		dev_info(mas->dev, "tx_fifo %d rx_fifo %d tx_width %d\n",
 			mas->tx_fifo_depth, mas->rx_fifo_depth,
 			mas->tx_fifo_width);
 		mas->setup = true;
+		hw_ver = geni_se_qupv3_hw_version(mas->wrapper_dev, &major,
+							&minor, &step);
+		if (hw_ver)
+			dev_err(mas->dev, "%s:Err getting HW version %d\n",
+							__func__, hw_ver);
+		else {
+			if ((major == 1) && (minor == 0))
+				mas->oversampling = 2;
+			GENI_SE_DBG(mas->ipc, false, mas->dev,
+				"%s:Major:%d Minor:%d step:%dos%d\n",
+			__func__, major, minor, step, mas->oversampling);
+		}
 	}
 exit_prepare_transfer_hardware:
 	return ret;
@@ -281,6 +811,29 @@
 		mas->cur_word_len = xfer->bits_per_word;
 	}
 
+	/* Speed and bits per word can be overridden per transfer */
+	if (xfer->speed_hz != mas->cur_speed_hz) {
+		int ret = 0;
+		u32 clk_sel = geni_read_reg(mas->base, SE_GENI_CLK_SEL);
+		u32 m_clk_cfg = geni_read_reg(mas->base, GENI_SER_M_CLK_CFG);
+		int idx = 0;
+		int div = 0;
+
+		ret = get_spi_clk_cfg(xfer->speed_hz, mas, &idx, &div);
+		if (ret) {
+			dev_err(mas->dev, "%s:Err setting clks:%d\n",
+								__func__, ret);
+			return;
+		}
+		mas->cur_speed_hz = xfer->speed_hz;
+		clk_sel |= (idx & CLK_SEL_MSK);
+		m_clk_cfg |= ((div << CLK_DIV_SHFT) | SER_CLK_EN);
+		geni_write_reg(clk_sel, mas->base, SE_GENI_CLK_SEL);
+		geni_write_reg(m_clk_cfg, mas->base, GENI_SER_M_CLK_CFG);
+	}
+
+	mas->tx_rem_bytes = 0;
+	mas->rx_rem_bytes = 0;
 	if (xfer->tx_buf && xfer->rx_buf)
 		m_cmd = SPI_FULL_DUPLEX;
 	else if (xfer->tx_buf)
@@ -291,7 +844,7 @@
 	spi_tx_cfg &= ~CS_TOGGLE;
 	if (xfer->cs_change)
 		spi_tx_cfg |= CS_TOGGLE;
-	trans_len = ((xfer->len / (mas->cur_word_len >> 3)) & TRANS_LEN_MSK);
+	trans_len = ((xfer->len << 3) / mas->cur_word_len) & TRANS_LEN_MSK;
 	if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
 		m_param |= FRAGMENTATION;
 
@@ -307,7 +860,8 @@
 	}
 	geni_write_reg(spi_tx_cfg, mas->base, SE_SPI_TRANS_CFG);
 	geni_setup_m_cmd(mas->base, m_cmd, m_param);
-	geni_write_reg(mas->tx_wm, mas->base, SE_GENI_TX_WATERMARK_REG);
+	if (m_cmd & SPI_TX_ONLY)
+		geni_write_reg(mas->tx_wm, mas->base, SE_GENI_TX_WATERMARK_REG);
 	/* Ensure all writes are done before the WM interrupt */
 	mb();
 }
@@ -315,17 +869,7 @@
 static void handle_fifo_timeout(struct spi_geni_master *mas)
 {
 	unsigned long timeout;
-	u32 tx_trans_len = geni_read_reg(mas->base, SE_SPI_TX_TRANS_LEN);
-	u32 rx_trans_len = geni_read_reg(mas->base, SE_SPI_RX_TRANS_LEN);
-	u32 spi_tx_cfg = geni_read_reg(mas->base, SE_SPI_TRANS_CFG);
-	u32 m_cmd = geni_read_reg(mas->base, SE_GENI_M_CMD0);
 
-	/* Timed-out on a FIFO xfer, print relevant reg info. */
-	dev_err(mas->dev, "tx_rem_bytes %d rx_rem_bytes %d\n",
-			mas->tx_rem_bytes, mas->rx_rem_bytes);
-	dev_err(mas->dev, "tx_trans_len %d rx_trans_len %d\n", tx_trans_len,
-								rx_trans_len);
-	dev_err(mas->dev, "spi_tx_cfg 0x%x m_cmd 0x%x\n", spi_tx_cfg, m_cmd);
 	reinit_completion(&mas->xfer_done);
 	geni_cancel_m_cmd(mas->base);
 	/* Ensure cmd cancel is written */
@@ -357,30 +901,64 @@
 		return -EINVAL;
 	}
 
-	reinit_completion(&mas->xfer_done);
-	/* Speed and bits per word can be overridden per transfer */
-	if (xfer->speed_hz != mas->cur_speed_hz) {
-		mas->cur_speed_hz = xfer->speed_hz;
-		ret = do_spi_clk_cfg(mas->cur_speed_hz, mas);
-		if (ret) {
-			dev_err(mas->dev, "%s:Err setting clks:%d\n",
-								__func__, ret);
-			goto geni_transfer_one_exit;
-		}
-	}
-
-	setup_fifo_xfer(xfer, mas, slv->mode, spi);
-	timeout = wait_for_completion_timeout(&mas->xfer_done,
+	if (mas->cur_xfer_mode == FIFO_MODE) {
+		setup_fifo_xfer(xfer, mas, slv->mode, spi);
+		timeout = wait_for_completion_timeout(&mas->xfer_done,
 					msecs_to_jiffies(SPI_XFER_TIMEOUT_MS));
-	if (!timeout) {
-		dev_err(mas->dev, "Xfer[len %d tx %p rx %p n %d] timed out.\n",
+		if (!timeout) {
+			GENI_SE_ERR(mas->ipc, true, mas->dev,
+				"Xfer[len %d tx %pK rx %pK n %d] timed out.\n",
 						xfer->len, xfer->tx_buf,
 						xfer->rx_buf,
 						xfer->bits_per_word);
-		ret = -ETIMEDOUT;
-		handle_fifo_timeout(mas);
+			mas->cur_xfer = NULL;
+			ret = -ETIMEDOUT;
+			goto err_fifo_geni_transfer_one;
+		}
+	} else {
+		setup_gsi_xfer(xfer, mas, slv, spi);
+		if ((mas->num_xfers >= NUM_SPI_XFER) ||
+			(list_is_last(&xfer->transfer_list,
+					&spi->cur_msg->transfers))) {
+			int i;
+
+			for (i = 0 ; i < mas->num_tx_eot; i++) {
+				timeout =
+				wait_for_completion_interruptible_timeout(
+					&mas->tx_cb,
+					msecs_to_jiffies(SPI_XFER_TIMEOUT_MS));
+				if (timeout <= 0) {
+					GENI_SE_ERR(mas->ipc, true, mas->dev,
+					"Tx[%d] timeout%lu\n", i, timeout);
+					ret = -ETIMEDOUT;
+					goto err_gsi_geni_transfer_one;
+				}
+			}
+			for (i = 0 ; i < mas->num_rx_eot; i++) {
+				timeout =
+				wait_for_completion_interruptible_timeout(
+					&mas->rx_cb,
+					msecs_to_jiffies(SPI_XFER_TIMEOUT_MS));
+				if (timeout <= 0) {
+					GENI_SE_ERR(mas->ipc, true, mas->dev,
+					 "Rx[%d] timeout%lu\n", i, timeout);
+					ret = -ETIMEDOUT;
+					goto err_gsi_geni_transfer_one;
+				}
+			}
+			if (mas->qn_err) {
+				ret = -EIO;
+				mas->qn_err = false;
+				goto err_gsi_geni_transfer_one;
+			}
+		}
 	}
-geni_transfer_one_exit:
+	return ret;
+err_gsi_geni_transfer_one:
+	dmaengine_terminate_all(mas->tx);
+	return ret;
+err_fifo_geni_transfer_one:
+	handle_fifo_timeout(mas);
 	return ret;
 }
 
@@ -389,8 +967,12 @@
 	int i = 0;
 	int tx_fifo_width = (mas->tx_fifo_width >> 3);
 	int max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * tx_fifo_width;
-	const u8 *tx_buf = mas->cur_xfer->tx_buf;
+	const u8 *tx_buf = NULL;
 
+	if (!mas->cur_xfer)
+		return;
+
+	tx_buf = mas->cur_xfer->tx_buf;
 	tx_buf += (mas->cur_xfer->len - mas->tx_rem_bytes);
 	max_bytes = min_t(int, mas->tx_rem_bytes, max_bytes);
 	while (i < max_bytes) {
@@ -421,8 +1003,12 @@
 	u32 rx_fifo_status = geni_read_reg(mas->base, SE_GENI_RX_FIFO_STATUS);
 	int rx_bytes = 0;
 	int rx_wc = 0;
-	u8 *rx_buf = mas->cur_xfer->rx_buf;
+	u8 *rx_buf = NULL;
 
+	if (!mas->cur_xfer)
+		return;
+
+	rx_buf = mas->cur_xfer->rx_buf;
 	rx_wc = (rx_fifo_status & RX_FIFO_WC_MSK);
 	if (rx_fifo_status & RX_LAST) {
 		int rx_last_byte_valid =
@@ -608,6 +1194,8 @@
 	spi->auto_runtime_pm = false;
 
 	init_completion(&geni_mas->xfer_done);
+	init_completion(&geni_mas->tx_cb);
+	init_completion(&geni_mas->rx_cb);
 	pm_runtime_enable(&pdev->dev);
 	ret = spi_register_master(spi);
 	if (ret) {
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index a8107cc..df8900a 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -365,11 +365,23 @@
 	return 0;
 }
 
+static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	int ret;
+
+	ret = of_device_uevent_modalias(dev, env);
+	if (ret != -ENODEV)
+		return ret;
+
+	return 0;
+}
+
 static struct bus_type spmi_bus_type = {
 	.name		= "spmi",
 	.match		= spmi_device_match,
 	.probe		= spmi_drv_probe,
 	.remove		= spmi_drv_remove,
+	.uevent		= spmi_drv_uevent,
 };
 
 /**
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c
index 675b974..ce9dc7e 100644
--- a/drivers/staging/android/fiq_debugger/fiq_debugger.c
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c
@@ -30,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
+#include <linux/sysrq.h>
 #include <linux/timer.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -400,7 +401,7 @@
 		cmd += 6;
 		while (*cmd == ' ')
 			cmd++;
-		if (cmd != '\0')
+		if ((cmd != '\0') && sysrq_on())
 			kernel_restart(cmd);
 		else
 			kernel_restart(NULL);
@@ -430,29 +431,39 @@
 static void fiq_debugger_help(struct fiq_debugger_state *state)
 {
 	fiq_debugger_printf(&state->output,
-				"FIQ Debugger commands:\n"
-				" pc            PC status\n"
-				" regs          Register dump\n"
-				" allregs       Extended Register dump\n"
-				" bt            Stack trace\n"
-				" reboot [<c>]  Reboot with command <c>\n"
-				" reset [<c>]   Hard reset with command <c>\n"
-				" irqs          Interupt status\n"
-				" kmsg          Kernel log\n"
-				" version       Kernel version\n");
+			"FIQ Debugger commands:\n");
+	if (sysrq_on()) {
+		fiq_debugger_printf(&state->output,
+			" pc            PC status\n"
+			" regs          Register dump\n"
+			" allregs       Extended Register dump\n"
+			" bt            Stack trace\n");
+		fiq_debugger_printf(&state->output,
+			" reboot [<c>]  Reboot with command <c>\n"
+			" reset [<c>]   Hard reset with command <c>\n"
+			" irqs          Interrupt status\n"
+			" kmsg          Kernel log\n"
+			" version       Kernel version\n");
+		fiq_debugger_printf(&state->output,
+			" cpu           Current CPU\n"
+			" cpu <number>  Switch to CPU<number>\n"
+			" sysrq         sysrq options\n"
+			" sysrq <param> Execute sysrq with <param>\n");
+	} else {
+		fiq_debugger_printf(&state->output,
+			" reboot        Reboot\n"
+			" reset         Hard reset\n"
+			" irqs          Interrupt status\n");
+	}
 	fiq_debugger_printf(&state->output,
-				" sleep         Allow sleep while in FIQ\n"
-				" nosleep       Disable sleep while in FIQ\n"
-				" console       Switch terminal to console\n"
-				" cpu           Current CPU\n"
-				" cpu <number>  Switch to CPU<number>\n");
-	fiq_debugger_printf(&state->output,
-				" ps            Process list\n"
-				" sysrq         sysrq options\n"
-				" sysrq <param> Execute sysrq with <param>\n");
+			" sleep         Allow sleep while in FIQ\n"
+			" nosleep       Disable sleep while in FIQ\n"
+			" console       Switch terminal to console\n"
+			" ps            Process list\n");
 #ifdef CONFIG_KGDB
-	fiq_debugger_printf(&state->output,
-				" kgdb          Enter kernel debugger\n");
+	if (fiq_kgdb_enable) {
+		fiq_debugger_printf(&state->output,
+			" kgdb          Enter kernel debugger\n");
 #endif
 }
 
@@ -484,18 +495,23 @@
 	if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
 		fiq_debugger_help(state);
 	} else if (!strcmp(cmd, "pc")) {
-		fiq_debugger_dump_pc(&state->output, regs);
+		if (sysrq_on())
+			fiq_debugger_dump_pc(&state->output, regs);
 	} else if (!strcmp(cmd, "regs")) {
-		fiq_debugger_dump_regs(&state->output, regs);
+		if (sysrq_on())
+			fiq_debugger_dump_regs(&state->output, regs);
 	} else if (!strcmp(cmd, "allregs")) {
-		fiq_debugger_dump_allregs(&state->output, regs);
+		if (sysrq_on())
+			fiq_debugger_dump_allregs(&state->output, regs);
 	} else if (!strcmp(cmd, "bt")) {
-		fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp);
+		if (sysrq_on())
+			fiq_debugger_dump_stacktrace(&state->output, regs,
+						     100, svc_sp);
 	} else if (!strncmp(cmd, "reset", 5)) {
 		cmd += 5;
 		while (*cmd == ' ')
 			cmd++;
-		if (*cmd) {
+		if (*cmd && sysrq_on()) {
 			char tmp_cmd[32];
 			strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd));
 			machine_restart(tmp_cmd);
@@ -505,9 +521,12 @@
 	} else if (!strcmp(cmd, "irqs")) {
 		fiq_debugger_dump_irqs(state);
 	} else if (!strcmp(cmd, "kmsg")) {
-		fiq_debugger_dump_kernel_log(state);
+		if (sysrq_on())
+			fiq_debugger_dump_kernel_log(state);
 	} else if (!strcmp(cmd, "version")) {
-		fiq_debugger_printf(&state->output, "%s\n", linux_banner);
+		if (sysrq_on())
+			fiq_debugger_printf(&state->output, "%s\n",
+					    linux_banner);
 	} else if (!strcmp(cmd, "sleep")) {
 		state->no_sleep = false;
 		fiq_debugger_printf(&state->output, "enabling sleep\n");
@@ -519,14 +538,17 @@
 		fiq_debugger_uart_flush(state);
 		state->console_enable = true;
 	} else if (!strcmp(cmd, "cpu")) {
-		fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu);
-	} else if (!strncmp(cmd, "cpu ", 4)) {
+		if (sysrq_on())
+			fiq_debugger_printf(&state->output, "cpu %d\n",
+					    state->current_cpu);
+	} else if (!strncmp(cmd, "cpu ", 4) && sysrq_on()) {
 		unsigned long cpu = 0;
 		if (kstrtoul(cmd + 4, 10, &cpu) == 0)
 			fiq_debugger_switch_cpu(state, cpu);
 		else
 			fiq_debugger_printf(&state->output, "invalid cpu\n");
-		fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu);
+		fiq_debugger_printf(&state->output, "cpu %d\n",
+				    state->current_cpu);
 	} else {
 		if (state->debug_busy) {
 			fiq_debugger_printf(&state->output,
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 4082a7d..168383ec 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -16,6 +16,7 @@
  *
  */
 
+#include <linux/atomic.h>
 #include <linux/err.h>
 #include <linux/file.h>
 #include <linux/freezer.h>
@@ -264,7 +265,7 @@
 	mutex_lock(&dev->buffer_lock);
 	ion_buffer_add(dev, buffer);
 	mutex_unlock(&dev->buffer_lock);
-	atomic_add(len, &heap->total_allocated);
+	atomic_long_add(len, &heap->total_allocated);
 	return buffer;
 
 err:
@@ -282,7 +283,7 @@
 		buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
 	buffer->heap->ops->unmap_dma(buffer->heap, buffer);
 
-	atomic_sub(buffer->size, &buffer->heap->total_allocated);
+	atomic_long_sub(buffer->size, &buffer->heap->total_allocated);
 	buffer->heap->ops->free(buffer);
 	vfree(buffer->pages);
 	kfree(buffer);
@@ -320,7 +321,7 @@
 {
 	mutex_lock(&buffer->lock);
 	if (buffer->handle_count == 0)
-		atomic_add(buffer->size, &buffer->heap->total_handles);
+		atomic_long_add(buffer->size, &buffer->heap->total_handles);
 
 	buffer->handle_count++;
 	mutex_unlock(&buffer->lock);
@@ -346,7 +347,7 @@
 		task = current->group_leader;
 		get_task_comm(buffer->task_comm, task);
 		buffer->pid = task_pid_nr(task);
-		atomic_sub(buffer->size, &buffer->heap->total_handles);
+		atomic_long_sub(buffer->size, &buffer->heap->total_handles);
 	}
 	mutex_unlock(&buffer->lock);
 }
@@ -402,6 +403,15 @@
 	kref_get(&handle->ref);
 }
 
+/* Must hold the client lock */
+static struct ion_handle* ion_handle_get_check_overflow(struct ion_handle *handle)
+{
+	if (atomic_read(&handle->ref.refcount) + 1 == 0)
+		return ERR_PTR(-EOVERFLOW);
+	ion_handle_get(handle);
+	return handle;
+}
+
 static int ion_handle_put_nolock(struct ion_handle *handle)
 {
 	int ret;
@@ -448,9 +458,9 @@
 
 	handle = idr_find(&client->idr, id);
 	if (handle)
-		ion_handle_get(handle);
+		return ion_handle_get_check_overflow(handle);
 
-	return handle ? handle : ERR_PTR(-EINVAL);
+	return ERR_PTR(-EINVAL);
 }
 
 struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
@@ -1394,7 +1404,7 @@
 	/* if a handle exists for this buffer just take a reference to it */
 	handle = ion_handle_lookup(client, buffer);
 	if (!IS_ERR(handle)) {
-		ion_handle_get(handle);
+		handle = ion_handle_get_check_overflow(handle);
 		mutex_unlock(&client->lock);
 		goto end;
 	}
@@ -1838,10 +1848,10 @@
 		"Total orphaned size");
 	pr_info("---------------------------------\n");
 	plist_for_each_entry(heap, &dev->heaps, node) {
-		pr_info("%16.s 0x%16.x 0x%16.x\n",
-			heap->name, atomic_read(&heap->total_allocated),
-			atomic_read(&heap->total_allocated) -
-			atomic_read(&heap->total_handles));
+		pr_info("%16.s 0x%16.lx 0x%16.lx\n",
+			heap->name, atomic_long_read(&heap->total_allocated),
+			atomic_long_read(&heap->total_allocated) -
+			atomic_long_read(&heap->total_handles));
 		if (heap->debug_show)
 			heap->debug_show(heap, NULL, 0);
 	}
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index ff6436f..b264ec2 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -241,14 +241,18 @@
 
 static void ion_secure_cma_free(struct ion_buffer *buffer)
 {
-	int ret = 0;
+	int i, ret = 0;
 	int *source_vm_list;
 	int source_nelems;
 	int dest_vmid;
 	int dest_perms;
+	struct sg_table *sgt;
+	struct scatterlist *sg;
 	struct ion_cma_buffer_info *info = buffer->priv_virt;
 
 	source_nelems = count_set_bits(buffer->flags & ION_FLAGS_CP_MASK);
+	if (!source_nelems)
+		return;
 	source_vm_list = kcalloc(source_nelems, sizeof(*source_vm_list),
 				 GFP_KERNEL);
 	if (!source_vm_list)
@@ -262,7 +266,8 @@
 	dest_vmid = VMID_HLOS;
 	dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC;
 
-	ret = hyp_assign_table(info->table, source_vm_list, source_nelems,
+	sgt = info->table;
+	ret = hyp_assign_table(sgt, source_vm_list, source_nelems,
 			       &dest_vmid, &dest_perms, 1);
 	if (ret) {
 		pr_err("%s: Not freeing memory since assign failed\n",
@@ -270,6 +275,9 @@
 		goto out_free_source;
 	}
 
+	for_each_sg(sgt->sgl, sg, sgt->nents, i)
+		ClearPagePrivate(sg_page(sg));
+
 	ion_cma_free(buffer);
 out_free_source:
 	kfree(source_vm_list);
@@ -280,17 +288,23 @@
 			struct ion_buffer *buffer, unsigned long len,
 			unsigned long align, unsigned long flags)
 {
-	int ret = 0;
+	int i, ret = 0;
 	int count;
 	int source_vm;
 	int *dest_vm_list = NULL;
 	int *dest_perms = NULL;
 	int dest_nelems;
 	struct ion_cma_buffer_info *info;
+	struct sg_table *sgt;
+	struct scatterlist *sg;
 
 	source_vm = VMID_HLOS;
 
 	dest_nelems = count_set_bits(flags & ION_FLAGS_CP_MASK);
+	if (!dest_nelems) {
+		ret = -EINVAL;
+		goto out;
+	}
 	dest_vm_list = kcalloc(dest_nelems, sizeof(*dest_vm_list), GFP_KERNEL);
 	if (!dest_vm_list) {
 		ret = -ENOMEM;
@@ -321,13 +335,18 @@
 	}
 
 	info = buffer->priv_virt;
-	ret = hyp_assign_table(info->table, &source_vm, 1,
-			dest_vm_list, dest_perms, dest_nelems);
+	sgt = info->table;
+	ret = hyp_assign_table(sgt, &source_vm, 1, dest_vm_list, dest_perms,
+			       dest_nelems);
 	if (ret) {
 		pr_err("%s: Assign call failed\n", __func__);
 		goto err;
 	}
 
+	/* Set the private bit to indicate that we've secured this */
+	for_each_sg(sgt->sgl, sg, sgt->nents, i)
+		SetPagePrivate(sg_page(sg));
+
 	kfree(dest_vm_list);
 	kfree(dest_perms);
 	return ret;
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index aa2d2d7..bb119cc 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -216,8 +216,8 @@
 	struct task_struct *task;
 
 	int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
-	atomic_t total_allocated;
-	atomic_t total_handles;
+	atomic_long_t total_allocated;
+	atomic_long_t total_handles;
 };
 
 /**
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index c0cda28..616375a 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -51,6 +51,7 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/almk.h>
+#include <linux/show_mem_notifier.h>
 
 #ifdef CONFIG_HIGHMEM
 #define _ZONE ZONE_HIGHMEM
@@ -525,7 +526,7 @@
 			task_set_lmk_waiting(selected);
 		task_unlock(selected);
 		trace_lowmemory_kill(selected, cache_size, cache_limit, free);
-		lowmem_print(1, "Killing '%s' (%d), adj %hd,\n"
+		lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n"
 			"to free %ldkB on behalf of '%s' (%d) because\n"
 			"cache %ldkB is below limit %ldkB for oom score %hd\n"
 			"Free memory is %ldkB above reserved.\n"
@@ -534,7 +535,7 @@
 			"Total free pages is %ldkB\n"
 			"Total file cache is %ldkB\n"
 			"GFP mask is 0x%x\n",
-			selected->comm, selected->pid,
+			selected->comm, selected->pid, selected->tgid,
 			selected_oom_score_adj,
 			selected_tasksize * (long)(PAGE_SIZE / 1024),
 			current->comm, current->pid,
@@ -552,6 +553,7 @@
 
 		if (lowmem_debug_level >= 2 && selected_oom_score_adj == 0) {
 			show_mem(SHOW_MEM_FILTER_NODES);
+			show_mem_call_notifiers();
 			dump_tasks(NULL, NULL);
 		}
 
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 1c967c3..a574885 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -3078,8 +3078,7 @@
 		/* following line: 2-1 per STC */
 		ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
 		ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG);
-		/* following line: N-1 per STC */
-		ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG);
+		ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG);
 	} else { /* TRIG_EXT */
 		/* FIXME:  assert scan_begin_arg != 0, ret failure otherwise */
 		devpriv->ao_cmd2  |= NISTC_AO_CMD2_BC_GATE_ENA;
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
index b27de88..995f2da 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
@@ -1650,8 +1650,13 @@
 	ibmsg = tx->tx_msg;
 	ibmsg->ibm_u.immediate.ibim_hdr = *hdr;
 
-	copy_from_iter(&ibmsg->ibm_u.immediate.ibim_payload, IBLND_MSG_SIZE,
-		       &from);
+	rc = copy_from_iter(&ibmsg->ibm_u.immediate.ibim_payload, payload_nob,
+			    &from);
+	if (rc != payload_nob) {
+		kiblnd_pool_free_node(&tx->tx_pool->tpo_pool, &tx->tx_list);
+		return -EFAULT;
+	}
+
 	nob = offsetof(struct kib_immediate_msg, ibim_payload[payload_nob]);
 	kiblnd_init_tx_msg(ni, tx, IBLND_MSG_IMMEDIATE, nob);
 
@@ -1751,8 +1756,14 @@
 			break;
 		}
 
-		copy_to_iter(&rxmsg->ibm_u.immediate.ibim_payload,
-			     IBLND_MSG_SIZE, to);
+		rc = copy_to_iter(&rxmsg->ibm_u.immediate.ibim_payload, rlen,
+				  to);
+		if (rc != rlen) {
+			rc = -EFAULT;
+			break;
+		}
+
+		rc = 0;
 		lnet_finalize(ni, lntmsg, 0);
 		break;
 
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 68e1e6b..b432153 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -43,6 +43,7 @@
 	{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
 	{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
 	{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+	{USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
 	{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
 	{}	/* Terminating entry */
 };
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
index becb4bb..01438fa 100644
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ b/drivers/staging/rts5208/rtsx_scsi.c
@@ -536,7 +536,7 @@
 
 	if (sendbytes > 8) {
 		memcpy(buf, inquiry_buf, 8);
-		memcpy(buf + 8, inquiry_string,	sendbytes - 8);
+		strncpy(buf + 8, inquiry_string, sendbytes - 8);
 		if (pro_formatter_flag) {
 			/* Additional Length */
 			buf[4] = 0x33;
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 7d90e25..86ace14 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -1049,6 +1049,26 @@
 	return err;
 }
 
+static int lynxfb_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+	struct apertures_struct *ap;
+	bool primary = false;
+
+	ap = alloc_apertures(1);
+	if (!ap)
+		return -ENOMEM;
+
+	ap->ranges[0].base = pci_resource_start(pdev, 0);
+	ap->ranges[0].size = pci_resource_len(pdev, 0);
+#ifdef CONFIG_X86
+	primary = pdev->resource[PCI_ROM_RESOURCE].flags &
+					IORESOURCE_ROM_SHADOW;
+#endif
+	remove_conflicting_framebuffers(ap, "sm750_fb1", primary);
+	kfree(ap);
+	return 0;
+}
+
 static int lynxfb_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *ent)
 {
@@ -1057,6 +1077,10 @@
 	int fbidx;
 	int err;
 
+	err = lynxfb_kick_out_firmware_fb(pdev);
+	if (err)
+		return err;
+
 	/* enable device */
 	err = pcim_enable_device(pdev);
 	if (err)
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 7e70fe8..9cbbc9c 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -802,6 +802,7 @@
 DEF_TPG_ATTRIB(t10_pi);
 DEF_TPG_ATTRIB(fabric_prot_type);
 DEF_TPG_ATTRIB(tpg_enabled_sendtargets);
+DEF_TPG_ATTRIB(login_keys_workaround);
 
 static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
 	&iscsi_tpg_attrib_attr_authentication,
@@ -817,6 +818,7 @@
 	&iscsi_tpg_attrib_attr_t10_pi,
 	&iscsi_tpg_attrib_attr_fabric_prot_type,
 	&iscsi_tpg_attrib_attr_tpg_enabled_sendtargets,
+	&iscsi_tpg_attrib_attr_login_keys_workaround,
 	NULL,
 };
 
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 89d34bd..6693d7c 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -819,7 +819,8 @@
 			SENDER_TARGET,
 			login->rsp_buf,
 			&login->rsp_length,
-			conn->param_list);
+			conn->param_list,
+			conn->tpg->tpg_attrib.login_keys_workaround);
 	if (ret < 0)
 		return -1;
 
@@ -889,7 +890,8 @@
 			SENDER_TARGET,
 			login->rsp_buf,
 			&login->rsp_length,
-			conn->param_list);
+			conn->param_list,
+			conn->tpg->tpg_attrib.login_keys_workaround);
 	if (ret < 0) {
 		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
 				ISCSI_LOGIN_STATUS_INIT_ERR);
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 4a073339a..0151776 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -765,7 +765,8 @@
 	return 0;
 }
 
-static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param)
+static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param,
+						    bool keys_workaround)
 {
 	if (IS_TYPE_BOOL_AND(param)) {
 		if (!strcmp(param->value, NO))
@@ -773,19 +774,31 @@
 	} else if (IS_TYPE_BOOL_OR(param)) {
 		if (!strcmp(param->value, YES))
 			SET_PSTATE_REPLY_OPTIONAL(param);
-		 /*
-		  * Required for gPXE iSCSI boot client
-		  */
-		if (!strcmp(param->name, IMMEDIATEDATA))
-			SET_PSTATE_REPLY_OPTIONAL(param);
+
+		if (keys_workaround) {
+			/*
+			 * Required for gPXE iSCSI boot client
+			 */
+			if (!strcmp(param->name, IMMEDIATEDATA))
+				SET_PSTATE_REPLY_OPTIONAL(param);
+		}
 	} else if (IS_TYPE_NUMBER(param)) {
 		if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
 			SET_PSTATE_REPLY_OPTIONAL(param);
-		/*
-		 * Required for gPXE iSCSI boot client
-		 */
-		if (!strcmp(param->name, MAXCONNECTIONS))
-			SET_PSTATE_REPLY_OPTIONAL(param);
+
+		if (keys_workaround) {
+			/*
+			 * Required for Mellanox Flexboot PXE boot ROM
+			 */
+			if (!strcmp(param->name, FIRSTBURSTLENGTH))
+				SET_PSTATE_REPLY_OPTIONAL(param);
+
+			/*
+			 * Required for gPXE iSCSI boot client
+			 */
+			if (!strcmp(param->name, MAXCONNECTIONS))
+				SET_PSTATE_REPLY_OPTIONAL(param);
+		}
 	} else if (IS_PHASE_DECLARATIVE(param))
 		SET_PSTATE_REPLY_OPTIONAL(param);
 }
@@ -1422,7 +1435,8 @@
 	u8 sender,
 	char *textbuf,
 	u32 *length,
-	struct iscsi_param_list *param_list)
+	struct iscsi_param_list *param_list,
+	bool keys_workaround)
 {
 	char *output_buf = NULL;
 	struct iscsi_extra_response *er;
@@ -1458,7 +1472,8 @@
 			*length += 1;
 			output_buf = textbuf + *length;
 			SET_PSTATE_PROPOSER(param);
-			iscsi_check_proposer_for_optional_reply(param);
+			iscsi_check_proposer_for_optional_reply(param,
+							        keys_workaround);
 			pr_debug("Sending key: %s=%s\n",
 				param->name, param->value);
 		}
diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h
index a0751e3..17a58c2 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.h
+++ b/drivers/target/iscsi/iscsi_target_parameters.h
@@ -40,7 +40,7 @@
 extern int iscsi_update_param_value(struct iscsi_param *, char *);
 extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *);
 extern int iscsi_encode_text_output(u8, u8, char *, u32 *,
-			struct iscsi_param_list *);
+			struct iscsi_param_list *, bool);
 extern int iscsi_check_negotiated_keys(struct iscsi_param_list *);
 extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *,
 			struct iscsi_param_list *);
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 205a509..63e1dcc 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -227,6 +227,7 @@
 	a->t10_pi = TA_DEFAULT_T10_PI;
 	a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE;
 	a->tpg_enabled_sendtargets = TA_DEFAULT_TPG_ENABLED_SENDTARGETS;
+	a->login_keys_workaround = TA_DEFAULT_LOGIN_KEYS_WORKAROUND;
 }
 
 int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg)
@@ -899,3 +900,21 @@
 
 	return 0;
 }
+
+int iscsit_ta_login_keys_workaround(
+	struct iscsi_portal_group *tpg,
+	u32 flag)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if ((flag != 0) && (flag != 1)) {
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
+	}
+
+	a->login_keys_workaround = flag;
+	pr_debug("iSCSI_TPG[%hu] - TPG enabled bit for login keys workaround: %s ",
+		tpg->tpgt, (a->login_keys_workaround) ? "ON" : "OFF");
+
+	return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
index 2da2119..901a712 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.h
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -39,5 +39,6 @@
 extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_tpg_enabled_sendtargets(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_login_keys_workaround(struct iscsi_portal_group *, u32);
 
 #endif /* ISCSI_TARGET_TPG_H */
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 1f9bfa4..e8a1f5c 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -753,6 +753,15 @@
 	if (cmd->transport_state & CMD_T_ABORTED ||
 	    cmd->transport_state & CMD_T_STOP) {
 		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+		/*
+		 * If COMPARE_AND_WRITE was stopped by __transport_wait_for_tasks(),
+		 * release se_device->caw_sem obtained by sbc_compare_and_write()
+		 * since target_complete_ok_work() or target_complete_failure_work()
+		 * won't be called to invoke the normal CAW completion callbacks.
+		 */
+		if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) {
+			up(&dev->caw_sem);
+		}
 		complete_all(&cmd->t_transport_stop_comp);
 		return;
 	} else if (!success) {
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index cd5bde3..09f7f20 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -205,8 +205,10 @@
 	mutex_lock(&cooling_list_lock);
 	list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 		if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) {
+			unsigned long level = get_level(cpufreq_dev, freq);
+
 			mutex_unlock(&cooling_list_lock);
-			return get_level(cpufreq_dev, freq);
+			return level;
 		}
 	}
 	mutex_unlock(&cooling_list_lock);
diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c
index 83905ff..7e98927 100644
--- a/drivers/thermal/max77620_thermal.c
+++ b/drivers/thermal/max77620_thermal.c
@@ -104,8 +104,6 @@
 		return -EINVAL;
 	}
 
-	pdev->dev.of_node = pdev->dev.parent->of_node;
-
 	mtherm->dev = &pdev->dev;
 	mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
 	if (!mtherm->rmap) {
@@ -113,6 +111,14 @@
 		return -ENODEV;
 	}
 
+	/*
+	 * Drop any current reference to a device-tree node and get a
+	 * reference to the parent's node which will be balanced on reprobe or
+	 * on platform-device release.
+	 */
+	of_node_put(pdev->dev.of_node);
+	pdev->dev.of_node = of_node_get(pdev->dev.parent->of_node);
+
 	mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
 				mtherm, &max77620_thermal_ops);
 	if (IS_ERR(mtherm->tz_device)) {
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
index be33725..e7d6241 100644
--- a/drivers/thermal/qcom/Kconfig
+++ b/drivers/thermal/qcom/Kconfig
@@ -41,14 +41,14 @@
 	  sensors to query for temperature and the aggregation logic to
 	  determine the virtual sensor temperature.
 
-config QTI_REG_COOLING_DEVICE
-	bool "QTI Regulator cooling device"
+config QTI_AOP_REG_COOLING_DEVICE
+	bool "QTI AOP Regulator cooling device"
 	depends on THERMAL_OF && MSM_QMP
 	help
-	  This enables the Regulator cooling device. This cooling device
-	  will be used by QTI chipset to place a floor voltage restriction at
-	  low temperatures. The regulator cooling device will message the AOP
-	  using mail box to establish the floor voltage.
+	  This enables the AOP based Regulator cooling device. This cooling
+	  device will be used by QTI chipset to place a floor voltage
+	  restriction at low temperatures. The cooling device will message
+	  the AOP using mail box to establish the floor voltage.
 
 config QTI_QMI_COOLING_DEVICE
 	bool "QTI QMI cooling devices"
@@ -60,3 +60,14 @@
 	   remote subsystem voltage restriction at low temperatures etc.
 	   The QMI cooling device will interface with remote subsystem
 	   using QTI QMI interface.
+
+config REGULATOR_COOLING_DEVICE
+	bool "Regulator voltage floor cooling device"
+	depends on REGULATOR && THERMAL_OF
+	help
+	  This implements a mitigation device to place a minimum voltage floor
+	  on a particular regulator. This mitigation device will be used by low
+	  temperature reliability rules to mitigate a regulator at nominal
+	  voltage.
+
+	  If you want this support, you should say Y here.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 000c6e7..257b714 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -3,5 +3,6 @@
 obj-$(CONFIG_MSM_BCL_PERIPHERAL_CTL) += bcl_peripheral.o
 obj-$(CONFIG_QTI_THERMAL_LIMITS_DCVS) += msm_lmh_dcvs.o lmh_dbg.o
 obj-$(CONFIG_QTI_VIRTUAL_SENSOR) += qti_virtual_sensor.o
-obj-$(CONFIG_QTI_REG_COOLING_DEVICE) += regulator_cooling.o
+obj-$(CONFIG_QTI_AOP_REG_COOLING_DEVICE) += regulator_aop_cdev.o
+obj-$(CONFIG_REGULATOR_COOLING_DEVICE) += regulator_cdev.o
 obj-$(CONFIG_QTI_QMI_COOLING_DEVICE) += thermal_mitigation_device_service_v01.o qmi_cooling.o
diff --git a/drivers/thermal/qcom/msm_lmh_dcvs.c b/drivers/thermal/qcom/msm_lmh_dcvs.c
index 4284b6c..d590d24 100644
--- a/drivers/thermal/qcom/msm_lmh_dcvs.c
+++ b/drivers/thermal/qcom/msm_lmh_dcvs.c
@@ -26,6 +26,7 @@
 #include <linux/pm_opp.h>
 #include <linux/cpu_cooling.h>
 #include <linux/atomic.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
@@ -102,10 +103,12 @@
 	unsigned long max_freq;
 	unsigned long min_freq;
 	unsigned long hw_freq_limit;
+	struct device_attribute lmh_freq_attr;
 	struct list_head list;
 	atomic_t is_irq_enabled;
 	struct mutex access_lock;
 	struct __limits_cdev_data *cdev_data;
+	struct regulator *isens_reg;
 };
 
 LIST_HEAD(lmh_dcvs_hw_list);
@@ -430,6 +433,60 @@
 	return 0;
 }
 
+static void limits_isens_vref_ldo_init(struct platform_device *pdev,
+					struct limits_dcvs_hw *hw)
+{
+	int ret = 0;
+	uint32_t settings[3];
+
+	hw->isens_reg = devm_regulator_get(&pdev->dev, "isens_vref");
+	if (IS_ERR_OR_NULL(hw->isens_reg)) {
+		if (PTR_ERR(hw->isens_reg) == -ENODEV)
+			return;
+
+		pr_err("Regulator:isens_vref init error:%ld\n",
+			PTR_ERR(hw->isens_reg));
+		return;
+	}
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+					"isens-vref-settings",
+					settings, 3);
+	if (ret) {
+		pr_err("Regulator:isens_vref settings read error:%d\n",
+				ret);
+		devm_regulator_put(hw->isens_reg);
+		return;
+	}
+	ret = regulator_set_voltage(hw->isens_reg, settings[0], settings[1]);
+	if (ret) {
+		pr_err("Regulator:isens_vref set voltage error:%d\n", ret);
+		devm_regulator_put(hw->isens_reg);
+		return;
+	}
+	ret = regulator_set_load(hw->isens_reg, settings[2]);
+	if (ret) {
+		pr_err("Regulator:isens_vref set load error:%d\n", ret);
+		devm_regulator_put(hw->isens_reg);
+		return;
+	}
+	if (regulator_enable(hw->isens_reg)) {
+		pr_err("Failed to enable regulator:isens_vref\n");
+		devm_regulator_put(hw->isens_reg);
+		return;
+	}
+}
+
+static ssize_t
+lmh_freq_limit_show(struct device *dev, struct device_attribute *devattr,
+		       char *buf)
+{
+	struct limits_dcvs_hw *hw = container_of(devattr,
+						struct limits_dcvs_hw,
+						lmh_freq_attr);
+
+	return snprintf(buf, PAGE_SIZE, "%lu\n", hw->hw_freq_limit);
+}
+
 static int limits_dcvs_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -585,6 +642,11 @@
 		ret = 0;
 		goto probe_exit;
 	}
+	limits_isens_vref_ldo_init(pdev, hw);
+	hw->lmh_freq_attr.attr.name = "lmh_freq_limit";
+	hw->lmh_freq_attr.show = lmh_freq_limit_show;
+	hw->lmh_freq_attr.attr.mode = 0444;
+	device_create_file(&pdev->dev, &hw->lmh_freq_attr);
 
 probe_exit:
 	mutex_lock(&lmh_dcvs_list_access);
diff --git a/drivers/thermal/qcom/regulator_cooling.c b/drivers/thermal/qcom/regulator_aop_cdev.c
similarity index 98%
rename from drivers/thermal/qcom/regulator_cooling.c
rename to drivers/thermal/qcom/regulator_aop_cdev.c
index 3cbf198..965be2f 100644
--- a/drivers/thermal/qcom/regulator_cooling.c
+++ b/drivers/thermal/qcom/regulator_aop_cdev.c
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 #include <linux/mailbox_client.h>
 
-#define REG_CDEV_DRIVER "reg-cooling-device"
+#define REG_CDEV_DRIVER "reg-aop-cooling-device"
 #define REG_MSG_FORMAT "{class:volt_flr, event:zero_temp, res:%s, value:%s}"
 #define REG_CDEV_MAX_STATE 1
 #define MBOX_TOUT_MS 1000
diff --git a/drivers/thermal/qcom/regulator_cdev.c b/drivers/thermal/qcom/regulator_cdev.c
new file mode 100644
index 0000000..a770dcb
--- /dev/null
+++ b/drivers/thermal/qcom/regulator_cdev.c
@@ -0,0 +1,184 @@
+/* Copyright (c) 2017, 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/platform_device.h>
+#include <linux/thermal.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+
+#define REG_CDEV_DRIVER "reg-cooling-device"
+
+struct reg_cooling_device {
+	struct regulator		*reg;
+	struct thermal_cooling_device	*cool_dev;
+	unsigned int			min_reg_state;
+	unsigned int			*lvl;
+	unsigned int			lvl_ct;
+	char				reg_name[THERMAL_NAME_LENGTH];
+	bool				reg_enable;
+};
+
+static int reg_get_max_state(struct thermal_cooling_device *cdev,
+				 unsigned long *state)
+{
+	struct reg_cooling_device *reg_dev = cdev->devdata;
+
+	*state = reg_dev->lvl_ct;
+	return 0;
+}
+
+static int reg_get_min_state(struct thermal_cooling_device *cdev,
+				 unsigned long *state)
+{
+	struct reg_cooling_device *reg_dev = cdev->devdata;
+
+	*state = reg_dev->min_reg_state;
+	return 0;
+}
+
+static int reg_set_min_state(struct thermal_cooling_device *cdev,
+				 unsigned long state)
+{
+	struct reg_cooling_device *reg_dev = cdev->devdata;
+	int ret = 0;
+
+	if (state > reg_dev->lvl_ct)
+		state = reg_dev->lvl_ct;
+
+	if (reg_dev->min_reg_state == state)
+		return ret;
+
+	ret = regulator_set_voltage(reg_dev->reg,
+			reg_dev->lvl[state], INT_MAX);
+	if (ret) {
+		dev_err(&cdev->device,
+			"switching to floor %lu err:%d\n",
+			state, ret);
+		return ret;
+	}
+	if (reg_dev->reg_enable && state == reg_dev->lvl_ct) {
+		ret = regulator_disable(reg_dev->reg);
+		if (ret) {
+			dev_err(&cdev->device,
+				"regulator disable err:%d\n", ret);
+			return ret;
+		}
+		reg_dev->reg_enable = false;
+	} else if (!reg_dev->reg_enable && state != reg_dev->lvl_ct) {
+		ret = regulator_enable(reg_dev->reg);
+		if (ret) {
+			dev_err(&cdev->device,
+				"regulator enable err:%d\n", ret);
+			return ret;
+		}
+		reg_dev->reg_enable = true;
+	}
+	reg_dev->min_reg_state = state;
+
+	return ret;
+}
+
+static int reg_get_cur_state(struct thermal_cooling_device *cdev,
+				 unsigned long *state)
+{
+	*state = 0;
+	return 0;
+}
+
+static int reg_set_cur_state(struct thermal_cooling_device *cdev,
+				 unsigned long state)
+{
+	/* regulator cooling device doesn't support voltage ceil */
+	return 0;
+}
+
+static struct thermal_cooling_device_ops reg_device_ops = {
+	.get_max_state = reg_get_max_state,
+	.get_cur_state = reg_get_cur_state,
+	.set_cur_state = reg_set_cur_state,
+	.set_min_state = reg_set_min_state,
+	.get_min_state = reg_get_min_state,
+};
+
+static int reg_cdev_probe(struct platform_device *pdev)
+{
+	struct reg_cooling_device *reg_dev;
+	int ret = 0;
+	struct device_node *np;
+
+	np = dev_of_node(&pdev->dev);
+	if (!np) {
+		dev_err(&pdev->dev,
+			"of node not available for cooling device\n");
+		return -EINVAL;
+	}
+
+	reg_dev = devm_kzalloc(&pdev->dev, sizeof(*reg_dev), GFP_KERNEL);
+	if (!reg_dev)
+		return -ENOMEM;
+
+	reg_dev->reg = devm_regulator_get(&pdev->dev, "regulator-cdev");
+	if (IS_ERR_OR_NULL(reg_dev->reg)) {
+		ret = PTR_ERR(reg_dev->reg);
+		dev_err(&pdev->dev, "regulator register err:%d\n", ret);
+		return ret;
+	}
+	ret = of_property_count_u32_elems(np, "regulator-levels");
+	if (ret <= 0) {
+		dev_err(&pdev->dev, "Invalid levels err:%d\n", ret);
+		return ret;
+	}
+	reg_dev->lvl_ct = ret;
+	reg_dev->lvl = devm_kcalloc(&pdev->dev, reg_dev->lvl_ct,
+			sizeof(*reg_dev->lvl), GFP_KERNEL);
+	if (!reg_dev->lvl)
+		return -ENOMEM;
+	ret = of_property_read_u32_array(np, "regulator-levels",
+				reg_dev->lvl, reg_dev->lvl_ct);
+	if (ret) {
+		dev_err(&pdev->dev, "cdev level fetch err:%d\n", ret);
+		return ret;
+	}
+	/* level count is an index and it depicts the max possible index */
+	reg_dev->lvl_ct--;
+	reg_dev->min_reg_state = reg_dev->lvl_ct;
+	reg_dev->reg_enable = false;
+	strlcpy(reg_dev->reg_name, np->name, THERMAL_NAME_LENGTH);
+
+	reg_dev->cool_dev = thermal_of_cooling_device_register(
+					np, reg_dev->reg_name, reg_dev,
+					&reg_device_ops);
+	if (IS_ERR(reg_dev->cool_dev)) {
+		ret = PTR_ERR(reg_dev->cool_dev);
+		dev_err(&pdev->dev, "regulator cdev register err:%d\n",
+				ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static const struct of_device_id reg_cdev_of_match[] = {
+	{.compatible = "qcom,regulator-cooling-device", },
+	{}
+};
+
+static struct platform_driver reg_cdev_driver = {
+	.driver = {
+		.name = REG_CDEV_DRIVER,
+		.of_match_table = reg_cdev_of_match,
+	},
+	.probe = reg_cdev_probe,
+};
+builtin_platform_driver(reg_cdev_driver);
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 95ef027..2bfe1b5 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -477,6 +477,7 @@
 	 * So, start monitoring again.
 	 */
 	monitor_thermal_zone(tz);
+	trace_thermal_handle_trip(tz, trip);
 }
 
 /**
@@ -567,6 +568,7 @@
 	ret = tz->ops->set_trips(tz, low, high);
 	if (ret)
 		dev_err(&tz->device, "Failed to set trips: %d\n", ret);
+	trace_thermal_set_trip(tz);
 
 exit:
 	mutex_unlock(&tz->lock);
@@ -621,6 +623,7 @@
 	if (!tz->ops->get_temp)
 		return;
 
+	trace_thermal_device_update(tz, event);
 	update_temperature(tz);
 
 	thermal_zone_set_trips(tz);
@@ -1934,6 +1937,7 @@
 				current_target = instance->target;
 		}
 	}
+	trace_cdev_update_start(cdev);
 	cdev->ops->set_cur_state(cdev, current_target);
 	if (cdev->ops->set_min_state)
 		cdev->ops->set_min_state(cdev, min_target);
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 17cdac4..11b4958 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -26,6 +26,7 @@
 #include <linux/qcom-geni-se.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
+#include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
@@ -107,9 +108,12 @@
 #define UART_CORE2X_VOTE	(10000)
 
 #define WAKEBYTE_TIMEOUT_MSEC	(2000)
-#define IPC_LOG_PWR_PAGES	(2)
-#define IPC_LOG_MISC_PAGES	(2)
-#define IPC_LOG_TX_RX_PAGES	(3)
+#define WAIT_XFER_MAX_ITER	(50)
+#define WAIT_XFER_MAX_TIMEOUT_US	(10000)
+#define WAIT_XFER_MIN_TIMEOUT_US	(9000)
+#define IPC_LOG_PWR_PAGES	(6)
+#define IPC_LOG_MISC_PAGES	(6)
+#define IPC_LOG_TX_RX_PAGES	(8)
 #define DATA_BYTES_PER_LINE	(32)
 
 #define IPC_LOG_MSG(ctx, x...) do { \
@@ -117,6 +121,7 @@
 		ipc_log_string(ctx, x); \
 } while (0)
 
+#define DMA_RX_BUF_SIZE		(512)
 struct msm_geni_serial_port {
 	struct uart_port uport;
 	char name[20];
@@ -136,6 +141,10 @@
 			unsigned int rx_last);
 	struct device *wrapper_dev;
 	struct se_geni_rsc serial_rsc;
+	dma_addr_t tx_dma;
+	unsigned int xmit_size;
+	void *rx_buf;
+	dma_addr_t rx_dma;
 	int loopback;
 	int wakeup_irq;
 	unsigned char wakeup_byte;
@@ -146,6 +155,7 @@
 	void *ipc_log_misc;
 	unsigned int cur_baud;
 	int ioctl_count;
+	int edge_count;
 };
 
 static const struct uart_ops msm_geni_serial_pops;
@@ -221,27 +231,66 @@
 					(unsigned int)addr, size, buf);
 }
 
-static bool check_tx_active(struct uart_port *uport)
+static bool check_transfers_inflight(struct uart_port *uport)
 {
-	/*
-	 * Poll if the GENI STATUS bit for TX is cleared. If the bit is
-	 * clear (poll condition met), return false, meaning tx isn't active
-	 * else return true. So return not of the poll return.
-	 */
-	return !msm_geni_serial_poll_bit(uport, SE_GENI_STATUS,
-					M_GENI_CMD_ACTIVE, false);
+	bool xfer_on = false;
+	bool tx_active = false;
+	bool tx_empty = false;
+	bool m_cmd_active = false;
+	bool rx_active = false;
+	u32 rx_fifo_status = 0;
+	u32 geni_status = geni_read_reg_nolog(uport->membase,
+						SE_GENI_STATUS);
+	/* Possible stop tx is called multiple times. */
+	m_cmd_active = geni_status & M_GENI_CMD_ACTIVE;
+	tx_empty = msm_geni_serial_tx_empty(uport);
+	tx_active = m_cmd_active || !tx_empty;
+	rx_fifo_status = geni_read_reg_nolog(uport->membase,
+						SE_GENI_RX_FIFO_STATUS);
+	if (rx_fifo_status)
+		rx_active = true;
+
+	if (rx_active || tx_active)
+		xfer_on = true;
+
+	return xfer_on;
+}
+
+static void wait_for_transfers_inflight(struct uart_port *uport)
+{
+	int iter = 0;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+
+	while (iter < WAIT_XFER_MAX_ITER) {
+		if (check_transfers_inflight(uport)) {
+			usleep_range(WAIT_XFER_MIN_TIMEOUT_US,
+					WAIT_XFER_MAX_TIMEOUT_US);
+			iter++;
+		} else {
+			break;
+		}
+	}
+	if (check_transfers_inflight(uport)) {
+		u32 geni_status = geni_read_reg_nolog(uport->membase,
+								SE_GENI_STATUS);
+		u32 geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS);
+		u32 rx_fifo_status = geni_read_reg_nolog(uport->membase,
+							SE_GENI_RX_FIFO_STATUS);
+
+		IPC_LOG_MSG(port->ipc_log_misc,
+			"%s IOS 0x%x geni status 0x%x rx fifo 0x%x\n",
+			__func__, geni_ios, geni_status, rx_fifo_status);
+	}
 }
 
 static int vote_clock_on(struct uart_port *uport)
 {
-	int ret = 0;
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
-	int usage_count = atomic_read(&uport->dev->power.usage_count);
+	int ret = 0;
 
 	if (!pm_runtime_enabled(uport->dev)) {
 		dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
-		ret = -EPERM;
-		return ret;
+		return -EPERM;
 	}
 	ret = msm_geni_serial_power_on(uport);
 	if (ret) {
@@ -249,39 +298,31 @@
 		return ret;
 	}
 	port->ioctl_count++;
-	__pm_relax(&port->geni_wake);
-	IPC_LOG_MSG(port->ipc_log_pwr, "%s rpm %d ioctl %d\n",
-				__func__, usage_count, port->ioctl_count);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s%s ioctl %d\n", __func__,
+					current->comm, port->ioctl_count);
 	return 0;
 }
 
 static int vote_clock_off(struct uart_port *uport)
 {
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
-	int ret = 0;
-	int usage_count = atomic_read(&uport->dev->power.usage_count);
 
 	if (!pm_runtime_enabled(uport->dev)) {
 		dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
-		ret = -EPERM;
-		return ret;
+		return -EPERM;
 	}
-	/* Check on going Tx. Don't block on this for now. */
-	if (check_tx_active(uport))
-		dev_warn(uport->dev, "%s: Vote off called during active Tx",
-								__func__);
 	if (!port->ioctl_count) {
 		dev_warn(uport->dev, "%s:Imbalanced vote off ioctl %d\n",
-						 __func__, usage_count);
+						__func__, port->ioctl_count);
 		IPC_LOG_MSG(port->ipc_log_pwr,
-				"%s:Imbalanced vote_off from userspace rpm%d",
-				__func__, usage_count);
-		return 0;
+				"%s:Imbalanced vote_off from userspace. %d",
+				__func__, port->ioctl_count);
+		return -EPERM;
 	}
 	port->ioctl_count--;
 	msm_geni_serial_power_off(uport);
-	IPC_LOG_MSG(port->ipc_log_pwr, "%s rpm %d ioctl %d\n",
-				__func__, usage_count, port->ioctl_count);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s%s ioctl %d\n", __func__,
+				current->comm, port->ioctl_count);
 	return 0;
 };
 
@@ -311,14 +352,11 @@
 
 static void msm_geni_serial_break_ctl(struct uart_port *uport, int ctl)
 {
-	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
-		dev_err(uport->dev, "%s Device suspended,vote clocks on.\n",
-							__func__);
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
 		return;
-	}
 
 	if (ctl) {
-		check_tx_active(uport);
+		wait_for_transfers_inflight(uport);
 		geni_setup_m_cmd(uport->membase, UART_START_BREAK, 0);
 	} else {
 		geni_setup_m_cmd(uport->membase, UART_STOP_BREAK, 0);
@@ -357,11 +395,8 @@
 {
 	u32 uart_manual_rfr = 0;
 
-	if (pm_runtime_status_suspended(uport->dev)) {
-		dev_info(uport->dev, "%sDevice suspended,vote clocks on\n",
-						__func__);
+	if (pm_runtime_status_suspended(uport->dev))
 		return;
-	}
 	if (!(mctrl & TIOCM_RTS))
 		uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_NOT_READY);
 	geni_write_reg_nolog(uart_manual_rfr, uport->membase,
@@ -396,9 +431,12 @@
 static int msm_geni_serial_power_on(struct uart_port *uport)
 {
 	int ret = 0;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 
 	ret = pm_runtime_get_sync(uport->dev);
 	if (ret < 0) {
+		IPC_LOG_MSG(port->ipc_log_pwr, "%s Err\n", __func__);
+		WARN_ON_ONCE(1);
 		pm_runtime_put_noidle(uport->dev);
 		pm_runtime_set_suspended(uport->dev);
 		return ret;
@@ -685,32 +723,98 @@
 
 #endif /* (CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)) */
 
+static int msm_geni_serial_prep_dma_tx(struct uart_port *uport)
+{
+	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+	struct circ_buf *xmit = &uport->state->xmit;
+	unsigned int xmit_size;
+	int ret = 0;
+
+	xmit_size = uart_circ_chars_pending(xmit);
+	if (xmit_size < WAKEUP_CHARS)
+		uart_write_wakeup(uport);
+
+	if (xmit_size > (UART_XMIT_SIZE - xmit->tail))
+		xmit_size = UART_XMIT_SIZE - xmit->tail;
+
+	if (!xmit_size)
+		return ret;
+
+	dump_ipc(msm_port->ipc_log_tx, "DMA Tx",
+		 (char *)&xmit->buf[xmit->tail], 0, xmit_size);
+	msm_geni_serial_setup_tx(uport, xmit_size);
+	ret = geni_se_tx_dma_prep(msm_port->wrapper_dev, uport->membase,
+			&xmit->buf[xmit->tail], xmit_size, &msm_port->tx_dma);
+	if (!ret) {
+		msm_port->xmit_size = xmit_size;
+	} else {
+		geni_write_reg_nolog(0, uport->membase,
+					SE_UART_TX_TRANS_LEN);
+		geni_cancel_m_cmd(uport->membase);
+		if (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
+						M_CMD_CANCEL_EN, true)) {
+			geni_abort_m_cmd(uport->membase);
+			msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
+							M_CMD_ABORT_EN, true);
+			geni_write_reg_nolog(M_CMD_ABORT_EN, uport->membase,
+							SE_GENI_M_IRQ_CLEAR);
+		}
+		geni_write_reg_nolog(M_CMD_CANCEL_EN, uport->membase,
+							SE_GENI_M_IRQ_CLEAR);
+		IPC_LOG_MSG(msm_port->ipc_log_tx, "%s: DMA map failure %d\n",
+								__func__, ret);
+		msm_port->tx_dma = (dma_addr_t)NULL;
+		msm_port->xmit_size = 0;
+	}
+	return ret;
+}
+
 static void msm_geni_serial_start_tx(struct uart_port *uport)
 {
 	unsigned int geni_m_irq_en;
 	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
 	unsigned int geni_status;
+	unsigned int geni_ios;
 
 	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
 		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+		IPC_LOG_MSG(msm_port->ipc_log_misc,
+				"%s.Device is suspended.\n", __func__);
 		return;
 	}
 
-	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
-	if (geni_status & M_GENI_CMD_ACTIVE)
-		return;
+	if (msm_port->xfer_mode == FIFO_MODE) {
+		geni_status = geni_read_reg_nolog(uport->membase,
+						  SE_GENI_STATUS);
+		if (geni_status & M_GENI_CMD_ACTIVE)
+			goto check_flow_ctrl;
 
-	if (!msm_geni_serial_tx_empty(uport))
-		return;
+		if (!msm_geni_serial_tx_empty(uport))
+			goto check_flow_ctrl;
 
-	geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
-	geni_m_irq_en |= (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN);
+		geni_m_irq_en = geni_read_reg_nolog(uport->membase,
+						    SE_GENI_M_IRQ_EN);
+		geni_m_irq_en |= (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN);
 
-	geni_write_reg_nolog(msm_port->tx_wm, uport->membase,
+		geni_write_reg_nolog(msm_port->tx_wm, uport->membase,
 						SE_GENI_TX_WATERMARK_REG);
-	geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
-	/* Geni command setup/irq enables should complete before returning.*/
-	mb();
+		geni_write_reg_nolog(geni_m_irq_en, uport->membase,
+							SE_GENI_M_IRQ_EN);
+		/* Geni command setup should complete before returning.*/
+		mb();
+	} else if (msm_port->xfer_mode == SE_DMA) {
+		if (msm_port->tx_dma)
+			goto check_flow_ctrl;
+
+		msm_geni_serial_prep_dma_tx(uport);
+	}
+	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
+	return;
+check_flow_ctrl:
+	geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS);
+	if (!(geni_ios & IO2_DATA_IN))
+		IPC_LOG_MSG(msm_port->ipc_log_misc, "%s: ios: 0x%08x\n",
+							__func__, geni_ios);
 }
 
 static void msm_geni_serial_stop_tx(struct uart_port *uport)
@@ -719,12 +823,30 @@
 	unsigned int geni_status;
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 
-	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+		IPC_LOG_MSG(port->ipc_log_misc,
+				"%s.Device is suspended.\n", __func__);
 		return;
+	}
 
 	geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
-	geni_m_irq_en &= ~(M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN);
-	geni_write_reg_nolog(0, uport->membase, SE_GENI_TX_WATERMARK_REG);
+	geni_m_irq_en &= ~M_CMD_DONE_EN;
+	if (port->xfer_mode == FIFO_MODE) {
+		geni_m_irq_en &= ~M_TX_FIFO_WATERMARK_EN;
+		geni_write_reg_nolog(0, uport->membase,
+				     SE_GENI_TX_WATERMARK_REG);
+	} else if (port->xfer_mode == SE_DMA) {
+		if (port->tx_dma) {
+			geni_write_reg_nolog(1, uport->membase,
+					     SE_DMA_TX_FSM_RST);
+			geni_se_tx_dma_unprep(port->wrapper_dev, port->tx_dma,
+					   port->xmit_size);
+			port->tx_dma = (dma_addr_t)NULL;
+		}
+	}
+	port->xmit_size = 0;
+
 	geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
 
 	geni_status = geni_read_reg_nolog(uport->membase,
@@ -754,26 +876,57 @@
 	unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
 	unsigned int geni_status;
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+	int ret;
 
-	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+		IPC_LOG_MSG(port->ipc_log_misc,
+				"%s.Device is suspended.\n", __func__);
 		return;
+	}
 
 	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
 	if (geni_status & S_GENI_CMD_ACTIVE)
 		msm_geni_serial_abort_rx(uport);
-	geni_s_irq_en = geni_read_reg_nolog(uport->membase,
-						SE_GENI_S_IRQ_EN);
-	geni_m_irq_en = geni_read_reg_nolog(uport->membase,
-						SE_GENI_M_IRQ_EN);
-	geni_s_irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
-	geni_m_irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
+
 	se_get_packing_config(8, 4, false, &cfg0, &cfg1);
 	geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_RX_PACKING_CFG0);
 	geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_RX_PACKING_CFG1);
 	geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT);
 	geni_setup_s_cmd(uport->membase, UART_START_READ, 0);
-	geni_write_reg_nolog(geni_s_irq_en, uport->membase, SE_GENI_S_IRQ_EN);
-	geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
+
+	if (port->xfer_mode == FIFO_MODE) {
+		geni_s_irq_en = geni_read_reg_nolog(uport->membase,
+							SE_GENI_S_IRQ_EN);
+		geni_m_irq_en = geni_read_reg_nolog(uport->membase,
+							SE_GENI_M_IRQ_EN);
+
+		geni_s_irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
+		geni_m_irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
+
+		geni_write_reg_nolog(geni_s_irq_en, uport->membase,
+							SE_GENI_S_IRQ_EN);
+		geni_write_reg_nolog(geni_m_irq_en, uport->membase,
+							SE_GENI_M_IRQ_EN);
+	} else if (port->xfer_mode == SE_DMA) {
+		port->rx_buf = kzalloc(DMA_RX_BUF_SIZE, GFP_KERNEL);
+		if (!port->rx_buf) {
+			dev_err(uport->dev, "%s: kzalloc failed\n",
+				__func__);
+			msm_geni_serial_abort_rx(uport);
+			return;
+		}
+
+		ret = geni_se_rx_dma_prep(port->wrapper_dev, uport->membase,
+				port->rx_buf, DMA_RX_BUF_SIZE, &port->rx_dma);
+		if (ret) {
+			dev_err(uport->dev, "%s: RX Prep dma failed %d\n",
+				__func__, ret);
+			kfree(port->rx_buf);
+			msm_geni_serial_abort_rx(uport);
+			return;
+		}
+	}
 	/*
 	 * Ensure the writes to the secondary sequencer and interrupt enables
 	 * go through.
@@ -787,25 +940,42 @@
 	unsigned int geni_s_irq_en;
 	unsigned int geni_m_irq_en;
 	unsigned int geni_status;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 
-	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+		IPC_LOG_MSG(port->ipc_log_misc,
+				"%s.Device is suspended.\n", __func__);
 		return;
+	}
 
-	geni_s_irq_en = geni_read_reg_nolog(uport->membase,
-						SE_GENI_S_IRQ_EN);
-	geni_m_irq_en = geni_read_reg_nolog(uport->membase,
-						SE_GENI_M_IRQ_EN);
-	geni_s_irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
-	geni_m_irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+	if (port->xfer_mode == FIFO_MODE) {
+		geni_s_irq_en = geni_read_reg_nolog(uport->membase,
+							SE_GENI_S_IRQ_EN);
+		geni_m_irq_en = geni_read_reg_nolog(uport->membase,
+							SE_GENI_M_IRQ_EN);
+		geni_s_irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
+		geni_m_irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
 
-	geni_write_reg_nolog(geni_s_irq_en, uport->membase, SE_GENI_S_IRQ_EN);
-	geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
+		geni_write_reg_nolog(geni_s_irq_en, uport->membase,
+							SE_GENI_S_IRQ_EN);
+		geni_write_reg_nolog(geni_m_irq_en, uport->membase,
+							SE_GENI_M_IRQ_EN);
+	} else if (port->xfer_mode == SE_DMA && port->rx_dma) {
+		geni_write_reg_nolog(1, uport->membase,	SE_DMA_RX_FSM_RST);
+		geni_se_rx_dma_unprep(port->wrapper_dev, port->rx_dma,
+						      DMA_RX_BUF_SIZE);
+		kfree(port->rx_buf);
+		port->rx_buf = NULL;
+		port->rx_dma = (dma_addr_t)NULL;
+	}
 
 	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
 	/* Possible stop rx is called multiple times. */
 	if (!(geni_status & S_GENI_CMD_ACTIVE))
 		return;
 	msm_geni_serial_abort_rx(uport);
+	IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);
 }
 
 static int handle_rx_hs(struct uart_port *uport,
@@ -878,6 +1048,8 @@
 		(uart_console(uport) ? 1 : (msm_port->tx_fifo_width >> 3));
 	unsigned int geni_m_irq_en;
 
+	xmit->tail = (xmit->tail + msm_port->xmit_size) & (UART_XMIT_SIZE - 1);
+	msm_port->xmit_size = 0;
 	tx_fifo_status = geni_read_reg_nolog(uport->membase,
 					SE_GENI_TX_FIFO_STATUS);
 	if (uart_circ_empty(xmit) && !tx_fifo_status) {
@@ -914,15 +1086,16 @@
 	while (i < xmit_size) {
 		unsigned int tx_bytes;
 		unsigned int buf = 0;
+		int temp_tail;
 		int c;
 
 		tx_bytes = ((bytes_remaining < fifo_width_bytes) ?
 					bytes_remaining : fifo_width_bytes);
 
+		temp_tail = (xmit->tail + i) & (UART_XMIT_SIZE - 1);
 		for (c = 0; c < tx_bytes ; c++)
-			buf |= (xmit->buf[xmit->tail + c] << (c * 8));
+			buf |= (xmit->buf[temp_tail + c] << (c * 8));
 		geni_write_reg_nolog(buf, uport->membase, SE_GENI_TX_FIFOn);
-		xmit->tail = (xmit->tail + tx_bytes) & (UART_XMIT_SIZE - 1);
 		i += tx_bytes;
 		uport->icount.tx += tx_bytes;
 		bytes_remaining -= tx_bytes;
@@ -930,48 +1103,137 @@
 		wmb();
 	}
 	msm_geni_serial_poll_cancel_tx(uport);
+	if (uart_console(uport))
+		xmit->tail = (xmit->tail + xmit_size) & (UART_XMIT_SIZE - 1);
+	else
+		msm_port->xmit_size = xmit_size;
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(uport);
 exit_handle_tx:
 	return ret;
 }
 
+static int msm_geni_serial_handle_dma_rx(struct uart_port *uport)
+{
+	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+	unsigned int rx_bytes = 0;
+	struct tty_port *tport;
+	int ret;
+	unsigned int geni_status;
+
+	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
+	/* Possible stop rx is called */
+	if (!(geni_status & S_GENI_CMD_ACTIVE))
+		return 0;
+
+	geni_se_rx_dma_unprep(msm_port->wrapper_dev, msm_port->rx_dma,
+			      DMA_RX_BUF_SIZE);
+	rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN);
+	if (unlikely(!msm_port->rx_buf || !rx_bytes)) {
+		IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: Rx_buf %pK Size %d\n",
+					__func__, msm_port->rx_buf, rx_bytes);
+		return 0;
+	}
+
+	tport = &uport->state->port;
+	ret = tty_insert_flip_string(tport, (unsigned char *)(msm_port->rx_buf),
+				     rx_bytes);
+	if (ret != rx_bytes) {
+		dev_err(uport->dev, "%s: ret %d rx_bytes %d\n", __func__,
+								ret, rx_bytes);
+		WARN_ON(1);
+	}
+	uport->icount.rx += ret;
+	tty_flip_buffer_push(tport);
+	dump_ipc(msm_port->ipc_log_rx, "DMA Rx", (char *)msm_port->rx_buf, 0,
+								rx_bytes);
+	ret = geni_se_rx_dma_prep(msm_port->wrapper_dev, uport->membase,
+			msm_port->rx_buf, DMA_RX_BUF_SIZE, &msm_port->rx_dma);
+	if (ret)
+		IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: %d\n", __func__, ret);
+	return ret;
+}
+
+static int msm_geni_serial_handle_dma_tx(struct uart_port *uport)
+{
+	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+	struct circ_buf *xmit = &uport->state->xmit;
+
+	xmit->tail = (xmit->tail + msm_port->xmit_size) & (UART_XMIT_SIZE - 1);
+	geni_se_tx_dma_unprep(msm_port->wrapper_dev, msm_port->tx_dma,
+				msm_port->xmit_size);
+	uport->icount.tx += msm_port->xmit_size;
+	msm_port->tx_dma = (dma_addr_t)NULL;
+	msm_port->xmit_size = 0;
+
+	if (!uart_circ_empty(xmit))
+		msm_geni_serial_prep_dma_tx(uport);
+	else
+		uart_write_wakeup(uport);
+	return 0;
+}
+
 static irqreturn_t msm_geni_serial_isr(int isr, void *dev)
 {
 	unsigned int m_irq_status;
 	unsigned int s_irq_status;
+	unsigned int dma;
+	unsigned int dma_tx_status;
+	unsigned int dma_rx_status;
 	struct uart_port *uport = dev;
 	unsigned long flags;
 	unsigned int m_irq_en;
+	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
 	if (uart_console(uport) && uport->suspended)
 		goto exit_geni_serial_isr;
-	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+		IPC_LOG_MSG(msm_port->ipc_log_misc,
+				"%s.Device is suspended.\n", __func__);
 		goto exit_geni_serial_isr;
+	}
 	m_irq_status = geni_read_reg_nolog(uport->membase,
 						SE_GENI_M_IRQ_STATUS);
 	s_irq_status = geni_read_reg_nolog(uport->membase,
 						SE_GENI_S_IRQ_STATUS);
-	geni_write_reg_nolog(m_irq_status, uport->membase,
-						SE_GENI_M_IRQ_CLEAR);
-	geni_write_reg_nolog(s_irq_status, uport->membase,
-						SE_GENI_S_IRQ_CLEAR);
 	m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
+	dma = geni_read_reg_nolog(uport->membase, SE_GENI_DMA_MODE_EN);
+	dma_tx_status = geni_read_reg_nolog(uport->membase, SE_DMA_TX_IRQ_STAT);
+	dma_rx_status = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_STAT);
+
+	geni_write_reg_nolog(m_irq_status, uport->membase, SE_GENI_M_IRQ_CLEAR);
+	geni_write_reg_nolog(s_irq_status, uport->membase, SE_GENI_S_IRQ_CLEAR);
 
 	if ((m_irq_status & M_ILLEGAL_CMD_EN)) {
 		WARN_ON(1);
 		goto exit_geni_serial_isr;
 	}
 
-	if ((s_irq_status & S_RX_FIFO_WATERMARK_EN) ||
-		(s_irq_status & S_RX_FIFO_LAST_EN)) {
-		msm_geni_serial_handle_rx(uport);
-	}
+	if (!dma) {
+		if ((s_irq_status & S_RX_FIFO_WATERMARK_EN) ||
+			(s_irq_status & S_RX_FIFO_LAST_EN))
+			msm_geni_serial_handle_rx(uport);
 
-	if ((m_irq_status & m_irq_en) &
-	    (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN))
-		msm_geni_serial_handle_tx(uport);
+		if ((m_irq_status & m_irq_en) &
+		    (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN))
+			msm_geni_serial_handle_tx(uport);
+	} else {
+		if (dma_tx_status) {
+			geni_write_reg_nolog(dma_tx_status, uport->membase,
+					     SE_DMA_TX_IRQ_CLR);
+			if (dma_tx_status & TX_DMA_DONE)
+				msm_geni_serial_handle_dma_tx(uport);
+		}
+
+		if (dma_rx_status) {
+			geni_write_reg_nolog(dma_rx_status, uport->membase,
+					     SE_DMA_RX_IRQ_CLR);
+			if (dma_rx_status & RX_DMA_DONE)
+				msm_geni_serial_handle_dma_rx(uport);
+		}
+	}
 
 exit_geni_serial_isr:
 	spin_unlock_irqrestore(&uport->lock, flags);
@@ -986,16 +1248,19 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uport->lock, flags);
-	if (port->wakeup_byte) {
+	IPC_LOG_MSG(port->ipc_log_rx, "%s: Edge-Count %d\n", __func__,
+							port->edge_count);
+	if (port->wakeup_byte && (port->edge_count == 2)) {
 		tty = uport->state->port.tty;
 		tty_insert_flip_char(tty->port, port->wakeup_byte, TTY_NORMAL);
 		IPC_LOG_MSG(port->ipc_log_rx, "%s: Inject 0x%x\n",
 					__func__, port->wakeup_byte);
+		port->edge_count = 0;
 		tty_flip_buffer_push(tty->port);
+		__pm_wakeup_event(&port->geni_wake, WAKEBYTE_TIMEOUT_MSEC);
+	} else if (port->edge_count < 2) {
+		port->edge_count++;
 	}
-	__pm_wakeup_event(&port->geni_wake, WAKEBYTE_TIMEOUT_MSEC);
-	IPC_LOG_MSG(port->ipc_log_misc, "%s:Holding Wake Lock for %d ms\n",
-					__func__, WAKEBYTE_TIMEOUT_MSEC);
 	spin_unlock_irqrestore(&uport->lock, flags);
 	return IRQ_HANDLED;
 }
@@ -1052,25 +1317,29 @@
 	unsigned long flags;
 
 	/* Stop the console before stopping the current tx */
-	if (uart_console(uport))
+	if (uart_console(uport)) {
 		console_stop(uport->cons);
+	} else {
+		msm_geni_serial_power_on(uport);
+		wait_for_transfers_inflight(uport);
+	}
 
+	disable_irq(uport->irq);
+	free_irq(uport->irq, msm_port);
 	spin_lock_irqsave(&uport->lock, flags);
 	msm_geni_serial_stop_tx(uport);
 	msm_geni_serial_stop_rx(uport);
 	spin_unlock_irqrestore(&uport->lock, flags);
 
-	disable_irq(uport->irq);
-	free_irq(uport->irq, msm_port);
 	if (uart_console(uport)) {
 		se_geni_resources_off(&msm_port->serial_rsc);
 	} else {
+		msm_geni_serial_power_off(uport);
 		if (msm_port->wakeup_irq > 0) {
+			irq_set_irq_wake(msm_port->wakeup_irq, 0);
 			disable_irq(msm_port->wakeup_irq);
 			free_irq(msm_port->wakeup_irq, msm_port);
 		}
-		__pm_relax(&msm_port->geni_wake);
-		msm_geni_serial_power_off(uport);
 	}
 	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
 }
@@ -1085,7 +1354,7 @@
 	set_rfr_wm(msm_port);
 	if (!uart_console(uport)) {
 		/* For now only assume FIFO mode. */
-		msm_port->xfer_mode = FIFO_MODE;
+		msm_port->xfer_mode = SE_DMA;
 		se_get_packing_config(8, 4, false, &cfg0, &cfg1);
 		geni_write_reg_nolog(cfg0, uport->membase,
 						SE_GENI_TX_PACKING_CFG0);
@@ -1183,8 +1452,11 @@
 
 	if (likely(!uart_console(uport))) {
 		ret = msm_geni_serial_power_on(&msm_port->uport);
-		if (ret)
-			goto exit_startup;
+		if (ret) {
+			dev_err(uport->dev, "%s:Failed to power on %d\n",
+							__func__, ret);
+			return ret;
+		}
 	}
 
 	if (unlikely(get_se_proto(uport->membase) != UART)) {
@@ -1217,8 +1489,7 @@
 	}
 
 	if (msm_port->wakeup_irq > 0) {
-		ret = request_threaded_irq(msm_port->wakeup_irq, NULL,
-				msm_geni_wakeup_isr,
+		ret = request_irq(msm_port->wakeup_irq, msm_geni_wakeup_isr,
 				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 				"hs_uart_wakeup", uport);
 		if (unlikely(ret)) {
@@ -1227,9 +1498,17 @@
 			goto exit_startup;
 		}
 		disable_irq(msm_port->wakeup_irq);
+		ret = irq_set_irq_wake(msm_port->wakeup_irq, 1);
+		if (unlikely(ret)) {
+			dev_err(uport->dev, "%s:Failed to set IRQ wake:%d\n",
+					__func__, ret);
+			goto exit_startup;
+		}
 	}
 	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
 exit_startup:
+	if (likely(!uart_console(uport)))
+		msm_geni_serial_power_off(&msm_port->uport);
 	return ret;
 }
 
@@ -1316,6 +1595,11 @@
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 	unsigned long clk_rate;
 
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		IPC_LOG_MSG(port->ipc_log_pwr,
+			"%s Device suspended,vote clocks on.\n", __func__);
+		return;
+	}
 	/* baud rate */
 	baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
 	port->cur_baud = baud;
@@ -1412,15 +1696,81 @@
 {
 	unsigned int tx_fifo_status;
 	unsigned int is_tx_empty = 1;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 
-	tx_fifo_status = geni_read_reg_nolog(uport->membase,
-					SE_GENI_TX_FIFO_STATUS);
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		IPC_LOG_MSG(port->ipc_log_pwr,
+			"%s Device suspended,vote clocks on.\n", __func__);
+		return 1;
+	}
+
+	if (port->xfer_mode == SE_DMA)
+		tx_fifo_status = port->tx_dma ? 1 : 0;
+	else
+		tx_fifo_status = geni_read_reg_nolog(uport->membase,
+						SE_GENI_TX_FIFO_STATUS);
 	if (tx_fifo_status)
 		is_tx_empty = 0;
 
 	return is_tx_empty;
 }
 
+static ssize_t msm_geni_serial_xfer_mode_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
+	ssize_t ret = 0;
+
+	if (port->xfer_mode == FIFO_MODE)
+		ret = snprintf(buf, sizeof("FIFO\n"), "FIFO\n");
+	else if (port->xfer_mode == SE_DMA)
+		ret = snprintf(buf, sizeof("SE_DMA\n"), "SE_DMA\n");
+
+	return ret;
+}
+
+static ssize_t msm_geni_serial_xfer_mode_store(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t size)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
+	struct uart_port *uport = &port->uport;
+	int xfer_mode = port->xfer_mode;
+	unsigned long flags;
+
+	if (uart_console(uport))
+		return -EOPNOTSUPP;
+
+	if (strnstr(buf, "FIFO", strlen("FIFO"))) {
+		xfer_mode = FIFO_MODE;
+	} else if (strnstr(buf, "SE_DMA", strlen("SE_DMA"))) {
+		xfer_mode = SE_DMA;
+	} else {
+		dev_err(dev, "%s: Invalid input %s\n", __func__, buf);
+		return -EINVAL;
+	}
+
+	if (xfer_mode == port->xfer_mode)
+		return size;
+
+	msm_geni_serial_power_on(uport);
+	spin_lock_irqsave(&uport->lock, flags);
+	msm_geni_serial_stop_tx(uport);
+	msm_geni_serial_stop_rx(uport);
+	port->xfer_mode = xfer_mode;
+	geni_se_select_mode(uport->membase, port->xfer_mode);
+	spin_unlock_irqrestore(&uport->lock, flags);
+	msm_geni_serial_start_rx(uport);
+	msm_geni_serial_power_off(uport);
+
+	return size;
+}
+
+static DEVICE_ATTR(xfer_mode, 0644, msm_geni_serial_xfer_mode_show,
+					msm_geni_serial_xfer_mode_store);
+
 #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
 static int __init msm_geni_console_setup(struct console *co, char *options)
 {
@@ -1671,6 +2021,7 @@
 	bool is_console = false;
 	struct platform_device *wrapper_pdev;
 	struct device_node *wrapper_ph_node;
+	u32 wake_char = 0;
 
 	id = of_match_device(msm_geni_device_tbl, &pdev->dev);
 	if (id) {
@@ -1733,9 +2084,14 @@
 	if (ret)
 		goto exit_geni_serial_probe;
 
-	if (of_property_read_u8(pdev->dev.of_node, "qcom,wakeup-byte",
-					&dev_port->wakeup_byte))
-		dev_info(&pdev->dev, "No Wakeup byte specified\n");
+	if (of_property_read_u32(pdev->dev.of_node, "qcom,wakeup-byte",
+					&wake_char)) {
+		dev_dbg(&pdev->dev, "No Wakeup byte specified\n");
+	} else {
+		dev_port->wakeup_byte = (u8)wake_char;
+		dev_info(&pdev->dev, "Wakeup byte 0x%x\n",
+					dev_port->wakeup_byte);
+	}
 
 	dev_port->serial_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
 	if (IS_ERR(dev_port->serial_rsc.se_clk)) {
@@ -1830,6 +2186,7 @@
 	dev_info(&pdev->dev, "Serial port%d added.FifoSize %d is_console%d\n",
 				line, uport->fifosize, is_console);
 	device_create_file(uport->dev, &dev_attr_loopback);
+	device_create_file(uport->dev, &dev_attr_xfer_mode);
 	msm_geni_serial_debug_init(uport);
 	dev_port->port_setup = false;
 	return uart_add_one_port(drv, uport);
@@ -1857,14 +2214,28 @@
 	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
 	int ret = 0;
 
+	wait_for_transfers_inflight(&port->uport);
 	ret = se_geni_resources_off(&port->serial_rsc);
 	if (ret) {
 		dev_err(dev, "%s: Error ret %d\n", __func__, ret);
 		goto exit_runtime_suspend;
 	}
-	if (port->wakeup_irq > 0)
+	disable_irq(port->uport.irq);
+	if (port->wakeup_irq > 0) {
+		struct se_geni_rsc *rsc = &port->serial_rsc;
+
+		port->edge_count = 0;
+		ret = pinctrl_select_state(rsc->geni_pinctrl,
+						rsc->geni_gpio_active);
+		if (ret) {
+			dev_err(dev, "%s: Error %d pinctrl_select_state\n",
+							__func__, ret);
+			goto exit_runtime_suspend;
+		}
 		enable_irq(port->wakeup_irq);
+	}
 	IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__);
+	__pm_relax(&port->geni_wake);
 exit_runtime_suspend:
 	return ret;
 }
@@ -1875,13 +2246,21 @@
 	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
 	int ret = 0;
 
+	/*
+	 * Do an unconditional relax followed by a stay awake in case the
+	 * wake source is activated by the wakeup isr.
+	 */
+	__pm_relax(&port->geni_wake);
+	__pm_stay_awake(&port->geni_wake);
 	if (port->wakeup_irq > 0)
 		disable_irq(port->wakeup_irq);
 	ret = se_geni_resources_on(&port->serial_rsc);
 	if (ret) {
 		dev_err(dev, "%s: Error ret %d\n", __func__, ret);
+		__pm_relax(&port->geni_wake);
 		goto exit_runtime_resume;
 	}
+	enable_irq(port->uport.irq);
 	IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__);
 exit_runtime_resume:
 	return ret;
@@ -1897,10 +2276,20 @@
 		uart_suspend_port((struct uart_driver *)uport->private_data,
 					uport);
 	} else {
+		struct uart_state *state = uport->state;
+		struct tty_port *tty_port = &state->port;
+
+		mutex_lock(&tty_port->mutex);
 		if (!pm_runtime_status_suspended(dev)) {
-			dev_info(dev, "%s: Is still active\n", __func__);
+			dev_err(dev, "%s:Active userspace vote; ioctl_cnt %d\n",
+					__func__, port->ioctl_count);
+			IPC_LOG_MSG(port->ipc_log_pwr,
+				"%s:Active userspace vote; ioctl_cnt %d\n",
+					__func__, port->ioctl_count);
+			mutex_unlock(&tty_port->mutex);
 			return -EBUSY;
 		}
+		mutex_unlock(&tty_port->mutex);
 	}
 	return 0;
 }
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 701c085..94c3718 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -55,10 +55,11 @@
 static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
-static bool sysrq_on(void)
+bool sysrq_on(void)
 {
 	return sysrq_enabled || sysrq_always_enabled;
 }
+EXPORT_SYMBOL(sysrq_on);
 
 /*
  * A value of 1 means 'all', other nonzero values are an op mask:
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 8c3bf3d..ce2c3c6 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2711,13 +2711,13 @@
 	 * related to the kernel should not use this.
 	 */
 			data = vt_get_shift_state();
-			ret = __put_user(data, p);
+			ret = put_user(data, p);
 			break;
 		case TIOCL_GETMOUSEREPORTING:
 			console_lock();	/* May be overkill */
 			data = mouse_reporting();
 			console_unlock();
-			ret = __put_user(data, p);
+			ret = put_user(data, p);
 			break;
 		case TIOCL_SETVESABLANK:
 			console_lock();
@@ -2726,7 +2726,7 @@
 			break;
 		case TIOCL_GETKMSGREDIRECT:
 			data = vt_get_kmsg_redirect();
-			ret = __put_user(data, p);
+			ret = put_user(data, p);
 			break;
 		case TIOCL_SETKMSGREDIRECT:
 			if (!capable(CAP_SYS_ADMIN)) {
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index a876d47..f16491c 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1770,6 +1770,9 @@
 	{ USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */
 	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
 	},
+	{ USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
+	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
+	},
 
 	{ USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
 	.driver_info = CLEAR_HALT_CONDITIONS,
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index eef716b..3fd2b54 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -981,6 +981,15 @@
 		case USB_PTM_CAP_TYPE:
 			dev->bos->ptm_cap =
 				(struct usb_ptm_cap_descriptor *)buffer;
+			break;
+		case USB_CAP_TYPE_CONFIG_SUMMARY:
+			/* one such desc per configuration */
+			if (!dev->bos->num_config_summary_desc)
+				dev->bos->config_summary =
+				(struct usb_config_summary_descriptor *)buffer;
+
+			dev->bos->num_config_summary_desc++;
+			break;
 		default:
 			break;
 		}
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 358ca8d..0f10ff2 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -19,6 +19,8 @@
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v3.h>
 #include "usb.h"
 
 static inline const char *plural(int n)
@@ -40,6 +42,34 @@
 		&& desc->bInterfaceProtocol == 1;
 }
 
+static int usb_audio_max_rev_config(struct usb_host_bos *bos)
+{
+	int desc_cnt, func_cnt, numfunc;
+	int num_cfg_desc;
+	struct usb_config_summary_descriptor *conf_summary;
+
+	if (!bos || !bos->config_summary)
+		goto done;
+
+	conf_summary = bos->config_summary;
+	num_cfg_desc = bos->num_config_summary_desc;
+
+	for (desc_cnt = 0; desc_cnt < num_cfg_desc; desc_cnt++) {
+		numfunc = conf_summary->bNumFunctions;
+		for (func_cnt = 0; func_cnt < numfunc; func_cnt++) {
+			/* honor device preferred config */
+			if (conf_summary->cs_info[func_cnt].bClass ==
+				USB_CLASS_AUDIO &&
+				conf_summary->cs_info[func_cnt].bSubClass !=
+				FULL_ADC_3_0)
+				return conf_summary->bConfigurationValue;
+		}
+	}
+
+done:
+	return -EINVAL;
+}
+
 int usb_choose_configuration(struct usb_device *udev)
 {
 	int i;
@@ -130,7 +160,6 @@
 			best = c;
 			break;
 		}
-
 		/* If all the remaining configs are vendor-specific,
 		 * choose the first one. */
 		else if (!best)
@@ -143,7 +172,10 @@
 			insufficient_power, plural(insufficient_power));
 
 	if (best) {
-		i = best->desc.bConfigurationValue;
+		/* choose usb audio class preferred config if available */
+		i = usb_audio_max_rev_config(udev->bos);
+		if (i < 0)
+			i = best->desc.bConfigurationValue;
 		dev_dbg(&udev->dev,
 			"configuration #%d chosen from %d choice%s\n",
 			i, num_configs, plural(num_configs));
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 0dc81d2..aca5d97 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -55,6 +55,8 @@
 #include "debug.h"
 #include "xhci.h"
 
+#define SDP_CONNETION_CHECK_TIME 10000 /* in ms */
+
 /* time out to wait for USB cable status notification (in ms)*/
 #define SM_INIT_TIMEOUT 30000
 
@@ -250,6 +252,7 @@
 	struct notifier_block	vbus_nb;
 	struct notifier_block	id_nb;
 	struct notifier_block	eud_event_nb;
+	struct notifier_block	host_restart_nb;
 
 	struct notifier_block	host_nb;
 
@@ -262,6 +265,7 @@
 	int pm_qos_latency;
 	struct pm_qos_request pm_qos_req_dma;
 	struct delayed_work perf_vote_work;
+	struct delayed_work sdp_check;
 };
 
 #define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -282,6 +286,8 @@
 static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc);
 static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA);
 static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event);
+static int dwc3_restart_usb_host_mode(struct notifier_block *nb,
+					unsigned long event, void *ptr);
 
 static inline bool is_valid_usb_speed(struct dwc3 *dwc, int speed)
 {
@@ -2138,7 +2144,6 @@
 static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
 {
 	int ret;
-	bool can_suspend_ssphy;
 	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
 	struct dwc3_event_buffer *evt;
 	struct usb_irq *uirq;
@@ -2195,10 +2200,6 @@
 	if (ret)
 		return ret;
 
-	/* Initialize variables here */
-	can_suspend_ssphy = !(mdwc->in_host_mode &&
-				dwc3_msm_is_host_superspeed(mdwc));
-
 	/* Disable core irq */
 	if (dwc->irq)
 		disable_irq(dwc->irq);
@@ -2214,7 +2215,7 @@
 	usb_phy_set_suspend(mdwc->hs_phy, 1);
 
 	/* Suspend SS PHY */
-	if (dwc->maximum_speed == USB_SPEED_SUPER && can_suspend_ssphy) {
+	if (dwc->maximum_speed == USB_SPEED_SUPER) {
 		/* indicate phy about SS mode */
 		if (dwc3_msm_is_superspeed(mdwc))
 			mdwc->ss_phy->flags |= DEVICE_IN_SS_MODE;
@@ -2818,6 +2819,25 @@
 	return NOTIFY_DONE;
 }
 
+
+static void check_for_sdp_connection(struct work_struct *w)
+{
+	struct dwc3_msm *mdwc =
+		container_of(w, struct dwc3_msm, sdp_check.work);
+	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+
+	if (!mdwc->vbus_active)
+		return;
+
+	/* floating D+/D- lines detected */
+	if (dwc->gadget.state < USB_STATE_DEFAULT &&
+		dwc3_gadget_get_link_state(dwc) != DWC3_LINK_STATE_CMPLY) {
+		mdwc->vbus_active = 0;
+		dbg_event(0xFF, "Q RW SPD CHK", mdwc->vbus_active);
+		queue_work(mdwc->dwc3_wq, &mdwc->resume_work);
+	}
+}
+
 static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
 	unsigned long event, void *ptr)
 {
@@ -2904,12 +2924,21 @@
 	if (!IS_ERR(edev)) {
 		mdwc->extcon_id = edev;
 		mdwc->id_nb.notifier_call = dwc3_msm_id_notifier;
+		mdwc->host_restart_nb.notifier_call =
+					dwc3_restart_usb_host_mode;
 		ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
 				&mdwc->id_nb);
 		if (ret < 0) {
 			dev_err(mdwc->dev, "failed to register notifier for USB-HOST\n");
 			goto err;
 		}
+
+		ret = extcon_register_blocking_notifier(edev, EXTCON_USB_HOST,
+							&mdwc->host_restart_nb);
+		if (ret < 0) {
+			dev_err(mdwc->dev, "failed to register blocking notifier\n");
+			goto err1;
+		}
 	}
 
 	edev = NULL;
@@ -2918,7 +2947,7 @@
 		edev = extcon_get_edev_by_phandle(mdwc->dev, 2);
 		if (IS_ERR(edev) && PTR_ERR(edev) != -ENODEV) {
 			ret = PTR_ERR(edev);
-			goto err;
+			goto err1;
 		}
 	}
 
@@ -2929,11 +2958,15 @@
 				&mdwc->eud_event_nb);
 		if (ret < 0) {
 			dev_err(mdwc->dev, "failed to register notifier for EUD-USB\n");
-			goto err1;
+			goto err2;
 		}
 	}
 
 	return 0;
+err2:
+	if (mdwc->extcon_id)
+		extcon_unregister_blocking_notifier(mdwc->extcon_id,
+				EXTCON_USB_HOST, &mdwc->host_restart_nb);
 err1:
 	if (mdwc->extcon_id)
 		extcon_unregister_notifier(mdwc->extcon_id, EXTCON_USB_HOST,
@@ -3104,6 +3137,7 @@
 	INIT_WORK(&mdwc->vbus_draw_work, dwc3_msm_vbus_draw_work);
 	INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work);
 	INIT_DELAYED_WORK(&mdwc->perf_vote_work, msm_dwc3_perf_vote_work);
+	INIT_DELAYED_WORK(&mdwc->sdp_check, check_for_sdp_connection);
 
 	mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0);
 	if (!mdwc->dwc3_wq) {
@@ -3859,34 +3893,83 @@
 	return 0;
 }
 
-static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA)
+/* speed: 0 - USB_SPEED_HIGH, 1 - USB_SPEED_SUPER */
+static int dwc3_restart_usb_host_mode(struct notifier_block *nb,
+				unsigned long event, void *ptr)
+{
+	struct dwc3_msm *mdwc;
+	struct dwc3 *dwc;
+	int ret = -EINVAL, usb_speed;
+
+	mdwc = container_of(nb, struct dwc3_msm, host_restart_nb);
+	dwc = platform_get_drvdata(mdwc->dwc3);
+
+	usb_speed = (event == 0 ? USB_SPEED_HIGH : USB_SPEED_SUPER);
+	if (dwc->maximum_speed == usb_speed)
+		goto err;
+
+	dbg_event(0xFF, "stop_host_mode", dwc->maximum_speed);
+	ret = dwc3_otg_start_host(mdwc, 0);
+	if (ret)
+		goto err;
+
+	/*
+	 * stop host mode functionality performs autosuspend with mdwc
+	 * device, and it may take sometime to call PM runtime suspend.
+	 * Hence call pm_runtime_suspend() API to invoke PM runtime
+	 * suspend immediately to put USB controller and PHYs into suspend.
+	 */
+	ret = pm_runtime_suspend(mdwc->dev);
+	dbg_event(0xFF, "pm_runtime_sus", ret);
+
+	dwc->maximum_speed = usb_speed;
+	mdwc->otg_state = OTG_STATE_B_IDLE;
+	schedule_delayed_work(&mdwc->sm_work, 0);
+	dbg_event(0xFF, "complete_host_change", dwc->maximum_speed);
+err:
+	return ret;
+}
+
+static int get_psy_type(struct dwc3_msm *mdwc)
 {
 	union power_supply_propval pval = {0};
-	int ret;
 
 	if (mdwc->charging_disabled)
-		return 0;
-
-	if (mdwc->max_power == mA)
-		return 0;
+		return -EINVAL;
 
 	if (!mdwc->usb_psy) {
 		mdwc->usb_psy = power_supply_get_by_name("usb");
 		if (!mdwc->usb_psy) {
-			dev_warn(mdwc->dev, "Could not get usb power_supply\n");
+			dev_err(mdwc->dev, "Could not get usb psy\n");
 			return -ENODEV;
 		}
 	}
 
-	power_supply_get_property(mdwc->usb_psy,
-			POWER_SUPPLY_PROP_REAL_TYPE, &pval);
-	if (pval.intval != POWER_SUPPLY_TYPE_USB)
+	power_supply_get_property(mdwc->usb_psy, POWER_SUPPLY_PROP_REAL_TYPE,
+			&pval);
+
+	return pval.intval;
+}
+
+static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA)
+{
+	union power_supply_propval pval = {0};
+	int ret, psy_type;
+
+	if (mdwc->max_power == mA)
 		return 0;
 
-	dev_info(mdwc->dev, "Avail curr from USB = %u\n", mA);
+	psy_type = get_psy_type(mdwc);
+	if (psy_type == POWER_SUPPLY_TYPE_USB) {
+		dev_info(mdwc->dev, "Avail curr from USB = %u\n", mA);
+		/* Set max current limit in uA */
+		pval.intval = 1000 * mA;
+	} else if (psy_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
+		pval.intval = -ETIMEDOUT;
+	} else {
+		return 0;
+	}
 
-	/* Set max current limit in uA */
-	pval.intval = 1000 * mA;
 	ret = power_supply_set_property(mdwc->usb_psy,
 				POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
 	if (ret) {
@@ -3957,6 +4040,10 @@
 			work = 1;
 		} else if (test_bit(B_SESS_VLD, &mdwc->inputs)) {
 			dev_dbg(mdwc->dev, "b_sess_vld\n");
+			if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_FLOAT)
+				queue_delayed_work(mdwc->dwc3_wq,
+						&mdwc->sdp_check,
+				msecs_to_jiffies(SDP_CONNETION_CHECK_TIME));
 			/*
 			 * Increment pm usage count upon cable connect. Count
 			 * is decremented in OTG_STATE_B_PERIPHERAL state on
@@ -3979,6 +4066,7 @@
 				!test_bit(ID, &mdwc->inputs)) {
 			dev_dbg(mdwc->dev, "!id || !bsv\n");
 			mdwc->otg_state = OTG_STATE_B_IDLE;
+			cancel_delayed_work_sync(&mdwc->sdp_check);
 			dwc3_otg_start_peripheral(mdwc, 0);
 			/*
 			 * Decrement pm usage count upon cable disconnect
@@ -4011,6 +4099,7 @@
 		if (!test_bit(B_SESS_VLD, &mdwc->inputs)) {
 			dev_dbg(mdwc->dev, "BSUSP: !bsv\n");
 			mdwc->otg_state = OTG_STATE_B_IDLE;
+			cancel_delayed_work_sync(&mdwc->sdp_check);
 			dwc3_otg_start_peripheral(mdwc, 0);
 		} else if (!test_bit(B_SUSPEND, &mdwc->inputs)) {
 			dev_dbg(mdwc->dev, "BSUSP !susp\n");
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 5396557..f910990 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -138,21 +138,28 @@
 	struct list_head list;
 };
 
+#define MAX_USB_STRING_LEN	126
+#define MAX_USB_STRING_WITH_NULL_LEN	(MAX_USB_STRING_LEN+1)
+
 static int usb_string_copy(const char *s, char **s_copy)
 {
 	int ret;
 	char *str;
 	char *copy = *s_copy;
 	ret = strlen(s);
-	if (ret > 126)
+	if (ret > MAX_USB_STRING_LEN)
 		return -EOVERFLOW;
 
-	str = kstrdup(s, GFP_KERNEL);
-	if (!str)
-		return -ENOMEM;
+	if (copy) {
+		str = copy;
+	} else {
+		str = kmalloc(MAX_USB_STRING_WITH_NULL_LEN, GFP_KERNEL);
+		if (!str)
+			return -ENOMEM;
+	}
+	strncpy(str, s, MAX_USB_STRING_WITH_NULL_LEN);
 	if (str[ret - 1] == '\n')
 		str[ret - 1] = '\0';
-	kfree(copy);
 	*s_copy = str;
 	return 0;
 }
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 51ab794..1590927 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -1029,8 +1029,14 @@
 	config_group_init_type_name(&fi_audio->func_inst.group, "",
 						&audio_source_func_type);
 
-	snprintf(device_name, AUDIO_SOURCE_DEV_NAME_LENGTH,
+	if (!count) {
+		snprintf(device_name, AUDIO_SOURCE_DEV_NAME_LENGTH,
+					"f_audio_source");
+		count++;
+	} else {
+		snprintf(device_name, AUDIO_SOURCE_DEV_NAME_LENGTH,
 					"f_audio_source%d", count++);
+	}
 
 	dev = create_function_device(device_name);
 
diff --git a/drivers/usb/gadget/function/f_ccid.c b/drivers/usb/gadget/function/f_ccid.c
index 1801a6c..7817f1c 100644
--- a/drivers/usb/gadget/function/f_ccid.c
+++ b/drivers/usb/gadget/function/f_ccid.c
@@ -26,7 +26,7 @@
 #include "f_ccid.h"
 
 #define BULK_IN_BUFFER_SIZE sizeof(struct ccid_bulk_in_header)
-#define BULK_OUT_BUFFER_SIZE sizeof(struct ccid_bulk_out_header)
+#define BULK_OUT_BUFFER_SIZE 1024
 #define CTRL_BUF_SIZE	4
 #define FUNCTION_NAME	"ccid"
 #define MAX_INST_NAME_LEN	40
@@ -629,14 +629,14 @@
 	struct f_ccid *ccid_dev =  fp->private_data;
 	struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
 	struct usb_request *req;
-	int r = count, xfer;
+	int r = count, xfer, len;
 	int ret;
 	unsigned long flags;
 
 	pr_debug("ccid_bulk_read(%zu)\n", count);
 
 	if (count > BULK_OUT_BUFFER_SIZE) {
-		pr_err("%s: max_buffer_size:%zu given_pkt_size:%zu\n",
+		pr_err("%s: max_buffer_size:%d given_pkt_size:%zu\n",
 				__func__, BULK_OUT_BUFFER_SIZE, count);
 		return -ENOMEM;
 	}
@@ -647,6 +647,7 @@
 		goto done;
 	}
 
+	len = ALIGN(count, ccid_dev->out->maxpacket);
 requeue_req:
 	spin_lock_irqsave(&ccid_dev->lock, flags);
 	if (!atomic_read(&ccid_dev->online)) {
@@ -655,7 +656,7 @@
 	}
 	/* queue a request */
 	req = bulk_dev->rx_req;
-	req->length = count;
+	req->length = len;
 	bulk_dev->rx_done = 0;
 	spin_unlock_irqrestore(&ccid_dev->lock, flags);
 	ret = usb_ep_queue(ccid_dev->out, req, GFP_KERNEL);
@@ -688,6 +689,9 @@
 			spin_unlock_irqrestore(&ccid_dev->lock, flags);
 			goto requeue_req;
 		}
+		if (req->actual > count)
+			pr_err("%s More data received(%d) than required(%zu)\n",
+						__func__, req->actual, count);
 		xfer = (req->actual < count) ? req->actual : count;
 		atomic_set(&bulk_dev->rx_req_busy, 1);
 		spin_unlock_irqrestore(&ccid_dev->lock, flags);
@@ -875,7 +879,8 @@
 		count = CTRL_BUF_SIZE;
 
 	ret = wait_event_interruptible(ctrl_dev->tx_wait_q,
-					 ctrl_dev->tx_ctrl_done);
+					 ctrl_dev->tx_ctrl_done ||
+					!atomic_read(&ccid_dev->online));
 	if (ret < 0)
 		return ret;
 	ctrl_dev->tx_ctrl_done = 0;
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 102003d..ca8ed69 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -137,6 +137,7 @@
 	} perf[MAX_ITERATION];
 	unsigned int dbg_read_index;
 	unsigned int dbg_write_index;
+	struct mutex  read_mutex;
 };
 
 static struct usb_interface_descriptor mtp_interface_desc = {
@@ -626,11 +627,18 @@
 	dev->state = STATE_BUSY;
 	spin_unlock_irq(&dev->lock);
 
+	mutex_lock(&dev->read_mutex);
+	if (dev->state == STATE_OFFLINE) {
+		r = -EIO;
+		mutex_unlock(&dev->read_mutex);
+		goto done;
+	}
 requeue_req:
 	/* queue a request */
 	req = dev->rx_req[0];
 	req->length = len;
 	dev->rx_done = 0;
+	mutex_unlock(&dev->read_mutex);
 	ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
 	if (ret < 0) {
 		r = -EIO;
@@ -656,6 +664,7 @@
 		usb_ep_dequeue(dev->ep_out, req);
 		goto done;
 	}
+	mutex_lock(&dev->read_mutex);
 	if (dev->state == STATE_BUSY) {
 		/* If we got a 0-len packet, throw it back and try again. */
 		if (req->actual == 0)
@@ -669,6 +678,7 @@
 	} else
 		r = -EIO;
 
+	mutex_unlock(&dev->read_mutex);
 done:
 	spin_lock_irq(&dev->lock);
 	if (dev->state == STATE_CANCELED)
@@ -920,6 +930,12 @@
 
 	while (count > 0 || write_req) {
 		if (count > 0) {
+			mutex_lock(&dev->read_mutex);
+			if (dev->state == STATE_OFFLINE) {
+				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
+				break;
+			}
 			/* queue a request */
 			read_req = dev->rx_req[cur_buf];
 			cur_buf = (cur_buf + 1) % RX_REQ_MAX;
@@ -928,6 +944,7 @@
 			read_req->length = mtp_rx_req_len;
 
 			dev->rx_done = 0;
+			mutex_unlock(&dev->read_mutex);
 			ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL);
 			if (ret < 0) {
 				r = -EIO;
@@ -940,15 +957,23 @@
 		if (write_req) {
 			DBG(cdev, "rx %p %d\n", write_req, write_req->actual);
 			start_time = ktime_get();
+			mutex_lock(&dev->read_mutex);
+			if (dev->state == STATE_OFFLINE) {
+				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
+				break;
+			}
 			ret = vfs_write(filp, write_req->buf, write_req->actual,
 				&offset);
 			DBG(cdev, "vfs_write %d\n", ret);
 			if (ret != write_req->actual) {
 				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
 				if (dev->state != STATE_OFFLINE)
 					dev->state = STATE_ERROR;
 				break;
 			}
+			mutex_unlock(&dev->read_mutex);
 			dev->perf[dev->dbg_write_index].vfs_wtime =
 				ktime_to_us(ktime_sub(ktime_get(), start_time));
 			dev->perf[dev->dbg_write_index].vfs_wbytes = ret;
@@ -976,6 +1001,13 @@
 				r = read_req->status;
 				break;
 			}
+
+			mutex_lock(&dev->read_mutex);
+			if (dev->state == STATE_OFFLINE) {
+				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
+				break;
+			}
 			/* Check if we aligned the size due to MTU constraint */
 			if (count < read_req->length)
 				read_req->actual = (read_req->actual > count ?
@@ -996,6 +1028,7 @@
 
 			write_req = read_req;
 			read_req = NULL;
+			mutex_unlock(&dev->read_mutex);
 		}
 	}
 
@@ -1446,12 +1479,14 @@
 	int i;
 
 	mtp_string_defs[INTERFACE_STRING_INDEX].id = 0;
+	mutex_lock(&dev->read_mutex);
 	while ((req = mtp_req_get(dev, &dev->tx_idle)))
 		mtp_request_free(req, dev->ep_in);
 	for (i = 0; i < RX_REQ_MAX; i++)
 		mtp_request_free(dev->rx_req[i], dev->ep_out);
 	while ((req = mtp_req_get(dev, &dev->intr_idle)))
 		mtp_request_free(req, dev->ep_intr);
+	mutex_unlock(&dev->read_mutex);
 	dev->state = STATE_OFFLINE;
 	kfree(f->os_desc_table);
 	f->os_desc_n = 0;
@@ -1791,6 +1826,8 @@
 	usb_os_desc_prepare_interf_dir(&fi_mtp->func_inst.group, 1,
 					descs, names, THIS_MODULE);
 
+	mutex_init(&fi_mtp->dev->read_mutex);
+
 	return  &fi_mtp->func_inst;
 }
 EXPORT_SYMBOL_GPL(alloc_inst_mtp_ptp);
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index a9a1e4c..c8989c6 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -77,6 +77,16 @@
 #define USB_INTEL_USB3_PSSEN   0xD8
 #define USB_INTEL_USB3PRM      0xDC
 
+/* ASMEDIA quirk use */
+#define ASMT_DATA_WRITE0_REG	0xF8
+#define ASMT_DATA_WRITE1_REG	0xFC
+#define ASMT_CONTROL_REG	0xE0
+#define ASMT_CONTROL_WRITE_BIT	0x02
+#define ASMT_WRITEREG_CMD	0x10423
+#define ASMT_FLOWCTL_ADDR	0xFA30
+#define ASMT_FLOWCTL_DATA	0xBA
+#define ASMT_PSEUDO_DATA	0
+
 /*
  * amd_chipset_gen values represent AMD different chipset generations
  */
@@ -412,6 +422,50 @@
 }
 EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
 
+static int usb_asmedia_wait_write(struct pci_dev *pdev)
+{
+	unsigned long retry_count;
+	unsigned char value;
+
+	for (retry_count = 1000; retry_count > 0; --retry_count) {
+
+		pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
+
+		if (value == 0xff) {
+			dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
+			return -EIO;
+		}
+
+		if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
+			return 0;
+
+		usleep_range(40, 60);
+	}
+
+	dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
+	return -ETIMEDOUT;
+}
+
+void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
+{
+	if (usb_asmedia_wait_write(pdev) != 0)
+		return;
+
+	/* send command and address to device */
+	pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
+	pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
+	pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
+
+	if (usb_asmedia_wait_write(pdev) != 0)
+		return;
+
+	/* send data to device */
+	pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
+	pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
+	pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
+}
+EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
+
 void usb_amd_quirk_pll_enable(void)
 {
 	usb_amd_quirk_pll(0);
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index c622ddf..6463fdb 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -11,6 +11,7 @@
 void usb_amd_dev_put(void);
 void usb_amd_quirk_pll_disable(void);
 void usb_amd_quirk_pll_enable(void);
+void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
 void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
 void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
 void sb800_prefetch(struct device *dev, int on);
@@ -18,6 +19,7 @@
 struct pci_dev;
 static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
+static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
 static inline void usb_amd_dev_put(void) {}
 static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
 static inline void sb800_prefetch(struct device *dev, int on) {}
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index b0c4f12..e9a8c3f 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -798,6 +798,9 @@
 			clear_bit(wIndex, &bus_state->resuming_ports);
 
 			set_bit(wIndex, &bus_state->rexit_ports);
+
+			xhci_test_and_clear_bit(xhci, port_array, wIndex,
+						PORT_PLC);
 			xhci_set_link_state(xhci, port_array, wIndex,
 					XDEV_U0);
 
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 672751e..2383344 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -59,6 +59,8 @@
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_2			0x43bb
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_1			0x43bc
 
+#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI		0x1142
+
 static const char hcd_name[] = "xhci_hcd";
 
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -217,6 +219,10 @@
 			pdev->device == 0x1142)
 		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
+	if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+		pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI)
+		xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL;
+
 	if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
 		xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 5d434e0..e185bbe 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -860,13 +860,16 @@
 			(ep->ep_state & EP_GETTING_NO_STREAMS)) {
 		int stream_id;
 
-		for (stream_id = 0; stream_id < ep->stream_info->num_streams;
+		for (stream_id = 1; stream_id < ep->stream_info->num_streams;
 				stream_id++) {
+			ring = ep->stream_info->stream_rings[stream_id];
+			if (!ring)
+				continue;
+
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 					"Killing URBs for slot ID %u, ep index %u, stream %u",
-					slot_id, ep_index, stream_id + 1);
-			xhci_kill_ring_urbs(xhci,
-					ep->stream_info->stream_rings[stream_id]);
+					slot_id, ep_index, stream_id);
+			xhci_kill_ring_urbs(xhci, ring);
 		}
 	} else {
 		ring = ep->ring;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ec9ff3e..15bf308 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -201,6 +201,9 @@
 	if (ret)
 		return ret;
 
+	if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
+		usb_asmedia_modifyflowcontrol(to_pci_dev(xhci_to_hcd(xhci)->self.controller));
+
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			 "Wait for controller to be ready for doorbell rings");
 	/*
@@ -1134,6 +1137,9 @@
 	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running)
 		compliance_mode_recovery_timer_init(xhci);
 
+	if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
+		usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
+
 	/* Re-enable port polling. */
 	xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
 	set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3a7fb29..757d045 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1669,6 +1669,7 @@
 #define XHCI_BROKEN_PORT_PED	(1 << 25)
 #define XHCI_LIMIT_ENDPOINT_INTERVAL_7	(1 << 26)
 #define XHCI_U2_DISABLE_WAKE	(1 << 27)
+#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL	(1 << 28)
 
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 1fad512..574ff79 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -38,6 +38,10 @@
 module_param(disable_usb_pd, bool, 0644);
 MODULE_PARM_DESC(disable_usb_pd, "Disable USB PD for USB3.1 compliance testing");
 
+static bool rev3_sink_only;
+module_param(rev3_sink_only, bool, 0644);
+MODULE_PARM_DESC(rev3_sink_only, "Enable power delivery rev3.0 sink only mode");
+
 enum usbpd_state {
 	PE_UNKNOWN,
 	PE_ERROR_RECOVERY,
@@ -377,6 +381,8 @@
 	struct list_head	svid_handlers;
 
 	struct list_head	instance;
+
+	u16			ss_lane_svid;
 };
 
 static LIST_HEAD(_usbpd);	/* useful for debugging */
@@ -445,6 +451,47 @@
 	extcon_set_state_sync(pd->extcon, EXTCON_USB, 1);
 }
 
+/**
+ * This API allows client driver to request for releasing SS lanes. It should
+ * not be called from atomic context.
+ *
+ * @pd - USBPD handler
+ * @hdlr - client's handler
+ *
+ * @returns int - Success - 0, else negative error code
+ */
+static int usbpd_release_ss_lane(struct usbpd *pd,
+				struct usbpd_svid_handler *hdlr)
+{
+	int ret = 0;
+
+	if (!hdlr || !pd)
+		return -EINVAL;
+
+	usbpd_dbg(&pd->dev, "hdlr:%pK svid:%d", hdlr, hdlr->svid);
+	/*
+	 * If USB SS lanes are already used by one client, and other client is
+	 * requesting for same or same client requesting again, return -EBUSY.
+	 */
+	if (pd->ss_lane_svid) {
+		usbpd_dbg(&pd->dev, "-EBUSY: ss_lanes are already used by(%d)",
+							pd->ss_lane_svid);
+		ret = -EBUSY;
+		goto err_exit;
+	}
+
+	ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 0);
+	if (ret) {
+		usbpd_err(&pd->dev, "err(%d) for releasing ss lane", ret);
+		goto err_exit;
+	}
+
+	pd->ss_lane_svid = hdlr->svid;
+
+err_exit:
+	return ret;
+}
+
 static int set_power_role(struct usbpd *pd, enum power_role pr)
 {
 	union power_supply_propval val = {0};
@@ -490,21 +537,18 @@
 	pd->send_dr_swap = false;
 }
 
-static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data,
-		size_t num_data, enum pd_msg_type type)
+static int pd_send_msg(struct usbpd *pd, u8 msg_type, const u32 *data,
+		size_t num_data, enum pd_sop_type sop)
 {
 	int ret;
 	u16 hdr;
 
-	hdr = PD_MSG_HDR(hdr_type, pd->current_dr, pd->current_pr,
+	hdr = PD_MSG_HDR(msg_type, pd->current_dr, pd->current_pr,
 			pd->tx_msgid, num_data, pd->spec_rev);
-	ret = pd_phy_write(hdr, (u8 *)data, num_data * sizeof(u32), type, 15);
-	/* TODO figure out timeout. based on tReceive=1.1ms x nRetryCount? */
 
-	if (ret < 0)
+	ret = pd_phy_write(hdr, (u8 *)data, num_data * sizeof(u32), sop);
+	if (ret)
 		return ret;
-	else if (ret != num_data * sizeof(u32))
-		return -EIO;
 
 	pd->tx_msgid = (pd->tx_msgid + 1) & PD_MAX_MSG_ID;
 	return 0;
@@ -566,7 +610,7 @@
 
 static int pd_eval_src_caps(struct usbpd *pd)
 {
-	int obj_cnt;
+	int i;
 	union power_supply_propval val;
 	u32 first_pdo = pd->received_pdos[0];
 
@@ -583,11 +627,20 @@
 	power_supply_set_property(pd->usb_psy,
 			POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED, &val);
 
-	for (obj_cnt = 1; obj_cnt < PD_MAX_DATA_OBJ; obj_cnt++) {
-		if ((PD_SRC_PDO_TYPE(pd->received_pdos[obj_cnt]) ==
+	if (pd->spec_rev == USBPD_REV_30 && !rev3_sink_only) {
+		bool pps_found = false;
+
+		/* downgrade to 2.0 if no PPS */
+		for (i = 1; i < PD_MAX_DATA_OBJ; i++) {
+			if ((PD_SRC_PDO_TYPE(pd->received_pdos[i]) ==
 					PD_SRC_PDO_TYPE_AUGMENTED) &&
-				!PD_APDO_PPS(pd->received_pdos[obj_cnt]))
-			pd->spec_rev = USBPD_REV_30;
+				!PD_APDO_PPS(pd->received_pdos[i])) {
+				pps_found = true;
+				break;
+			}
+		}
+		if (!pps_found)
+			pd->spec_rev = USBPD_REV_20;
 	}
 
 	/* Select the first PDO (vSafe5V) immediately. */
@@ -605,7 +658,7 @@
 	/* Force CC logic to source/sink to keep Rp/Rd unchanged */
 	set_power_role(pd, pd->current_pr);
 	pd->hard_reset_count++;
-	pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
+	pd_phy_signal(HARD_RESET_SIG);
 	pd->in_pr_swap = false;
 	power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_PR_SWAP, &val);
 }
@@ -621,12 +674,12 @@
 		queue_work(pd->wq, &pd->sm_work);
 }
 
-static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
+static void phy_sig_received(struct usbpd *pd, enum pd_sig_type sig)
 {
 	union power_supply_propval val = {1};
 
-	if (type != HARD_RESET_SIG) {
-		usbpd_err(&pd->dev, "invalid signal (%d) received\n", type);
+	if (sig != HARD_RESET_SIG) {
+		usbpd_err(&pd->dev, "invalid signal (%d) received\n", sig);
 		return;
 	}
 
@@ -641,16 +694,16 @@
 	kick_sm(pd, 0);
 }
 
-static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type,
+static void phy_msg_received(struct usbpd *pd, enum pd_sop_type sop,
 		u8 *buf, size_t len)
 {
 	struct rx_msg *rx_msg;
 	unsigned long flags;
 	u16 header;
 
-	if (type != SOP_MSG) {
+	if (sop != SOP_MSG) {
 		usbpd_err(&pd->dev, "invalid msg type (%d) received; only SOP supported\n",
-				type);
+				sop);
 		return;
 	}
 
@@ -688,6 +741,10 @@
 		return;
 	}
 
+	/* if spec rev differs (i.e. is older), update PHY */
+	if (PD_MSG_HDR_REV(header) < pd->spec_rev)
+		pd->spec_rev = PD_MSG_HDR_REV(header);
+
 	rx_msg = kzalloc(sizeof(*rx_msg), GFP_KERNEL);
 	if (!rx_msg)
 		return;
@@ -764,6 +821,7 @@
 		if (pd->current_dr == DR_NONE) {
 			pd->current_dr = DR_DFP;
 			start_usb_host(pd, true);
+			pd->ss_lane_svid = 0x0;
 		}
 
 		dual_role_instance_changed(pd->dual_role);
@@ -773,6 +831,8 @@
 		power_supply_set_property(pd->usb_psy,
 				POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val);
 
+		/* support only PD 2.0 as a source */
+		pd->spec_rev = USBPD_REV_20;
 		pd_reset_protocol(pd);
 
 		if (!pd->in_pr_swap) {
@@ -926,6 +986,7 @@
 
 			if (pd->psy_type == POWER_SUPPLY_TYPE_USB ||
 				pd->psy_type == POWER_SUPPLY_TYPE_USB_CDP ||
+				pd->psy_type == POWER_SUPPLY_TYPE_USB_FLOAT ||
 				usb_compliance_mode)
 				start_usb_peripheral(pd);
 		}
@@ -943,6 +1004,11 @@
 		if (!val.intval || disable_usb_pd)
 			break;
 
+		/*
+		 * support up to PD 3.0 as a sink; if source is 2.0
+		 * phy_msg_received() will handle the downgrade.
+		 */
+		pd->spec_rev = USBPD_REV_30;
 		pd_reset_protocol(pd);
 
 		if (!pd->in_pr_swap) {
@@ -1083,6 +1149,7 @@
 	usbpd_dbg(&pd->dev, "registered handler for SVID 0x%04x\n", hdlr->svid);
 
 	list_add_tail(&hdlr->entry, &pd->svid_handlers);
+	hdlr->request_usb_ss_lane = usbpd_release_ss_lane;
 
 	/* already connected with this SVID discovered? */
 	if (pd->vdm_state >= DISCOVERED_SVIDS) {
@@ -1432,6 +1499,7 @@
 static void dr_swap(struct usbpd *pd)
 {
 	reset_vdm_state(pd);
+	usbpd_dbg(&pd->dev, "dr_swap: current_dr(%d)\n", pd->current_dr);
 
 	if (pd->current_dr == DR_DFP) {
 		stop_usb_host(pd);
@@ -1439,9 +1507,9 @@
 		pd->current_dr = DR_UFP;
 	} else if (pd->current_dr == DR_UFP) {
 		stop_usb_peripheral(pd);
+		start_usb_host(pd, true);
 		pd->current_dr = DR_DFP;
 
-		/* don't start USB host until after SVDM discovery */
 		usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_IDENTITY,
 				SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0);
 	}
@@ -1628,6 +1696,8 @@
 		/* set due to dual_role class "mode" change */
 		if (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE)
 			val.intval = pd->forced_pr;
+		else if (rev3_sink_only)
+			val.intval = POWER_SUPPLY_TYPEC_PR_SINK;
 		else
 			/* Set CC back to DRP toggle */
 			val.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
@@ -2467,6 +2537,16 @@
 		if (pd->current_pr == PR_SINK)
 			return 0;
 
+		/*
+		 * Unexpected if not in PR swap; need to force disconnect from
+		 * source so we can turn off VBUS, Vconn, PD PHY etc.
+		 */
+		if (pd->current_pr == PR_SRC) {
+			usbpd_info(&pd->dev, "Forcing disconnect from source mode\n");
+			pd->current_pr = PR_NONE;
+			break;
+		}
+
 		pd->current_pr = PR_SINK;
 		break;
 
@@ -3344,8 +3424,6 @@
 		pd->dual_role->drv_data = pd;
 	}
 
-	/* default support as PD 2.0 source or sink */
-	pd->spec_rev = USBPD_REV_20;
 	pd->current_pr = PR_NONE;
 	pd->current_dr = DR_NONE;
 	list_add_tail(&pd->instance, &_usbpd);
diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c
index 1f5306f..735774a 100644
--- a/drivers/usb/pd/qpnp-pdphy.c
+++ b/drivers/usb/pd/qpnp-pdphy.c
@@ -80,6 +80,10 @@
 #define VDD_PDPHY_VOL_MAX		3088000 /* uV */
 #define VDD_PDPHY_HPM_LOAD		3000 /* uA */
 
+/* timers */
+#define RECEIVER_RESPONSE_TIME		15	/* tReceiverResponse */
+#define HARD_RESET_COMPLETE_TIME	5	/* tHardResetComplete */
+
 struct usb_pdphy {
 	struct device *dev;
 	struct regmap *regmap;
@@ -96,8 +100,8 @@
 	int msg_tx_discarded_irq;
 	int msg_rx_discarded_irq;
 
-	void (*signal_cb)(struct usbpd *pd, enum pd_sig_type type);
-	void (*msg_rx_cb)(struct usbpd *pd, enum pd_msg_type type,
+	void (*signal_cb)(struct usbpd *pd, enum pd_sig_type sig);
+	void (*msg_rx_cb)(struct usbpd *pd, enum pd_sop_type sop,
 			  u8 *buf, size_t len);
 	void (*shutdown_cb)(struct usbpd *pd);
 
@@ -401,14 +405,13 @@
 }
 EXPORT_SYMBOL(pd_phy_open);
 
-int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
+int pd_phy_signal(enum pd_sig_type sig)
 {
 	u8 val;
 	int ret;
 	struct usb_pdphy *pdphy = __pdphy;
 
-	dev_dbg(pdphy->dev, "%s: type %d timeout %u\n", __func__, type,
-			timeout_ms);
+	dev_dbg(pdphy->dev, "%s: type %d\n", __func__, sig);
 
 	if (!pdphy) {
 		pr_err("%s: pdphy not found\n", __func__);
@@ -428,7 +431,7 @@
 
 	usleep_range(2, 3);
 
-	val = (type == CABLE_RESET_SIG ? TX_CONTROL_FRAME_TYPE_CABLE_RESET : 0)
+	val = (sig == CABLE_RESET_SIG ? TX_CONTROL_FRAME_TYPE_CABLE_RESET : 0)
 		| TX_CONTROL_SEND_SIGNAL;
 
 	ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val);
@@ -436,7 +439,8 @@
 		return ret;
 
 	ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
-		pdphy->tx_status != -EINPROGRESS, msecs_to_jiffies(timeout_ms));
+		pdphy->tx_status != -EINPROGRESS,
+		msecs_to_jiffies(HARD_RESET_COMPLETE_TIME));
 	if (ret <= 0) {
 		dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
 		return ret ? ret : -ETIMEDOUT;
@@ -447,7 +451,7 @@
 	if (pdphy->tx_status)
 		return pdphy->tx_status;
 
-	if (type == HARD_RESET_SIG)
+	if (sig == HARD_RESET_SIG)
 		/* Frame filter is reconfigured in pd_phy_open() */
 		return pdphy_reg_write(pdphy, USB_PDPHY_FRAME_FILTER, 0);
 
@@ -455,16 +459,15 @@
 }
 EXPORT_SYMBOL(pd_phy_signal);
 
-int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
-	enum pd_msg_type type, unsigned int timeout_ms)
+int pd_phy_write(u16 hdr, const u8 *data, size_t data_len, enum pd_sop_type sop)
 {
 	u8 val;
 	int ret;
 	size_t total_len = data_len + USB_PDPHY_MSG_HDR_LEN;
 	struct usb_pdphy *pdphy = __pdphy;
 
-	dev_dbg(pdphy->dev, "%s: hdr %x frame type %d timeout %u\n",
-			__func__, hdr, type, timeout_ms);
+	dev_dbg(pdphy->dev, "%s: hdr %x frame sop_type %d\n",
+			__func__, hdr, sop);
 
 	if (data && data_len)
 		print_hex_dump_debug("tx data obj:", DUMP_PREFIX_NONE, 32, 4,
@@ -518,14 +521,15 @@
 
 	usleep_range(2, 3);
 
-	val = TX_CONTROL_RETRY_COUNT | (type << 2) | TX_CONTROL_SEND_MSG;
+	val = TX_CONTROL_RETRY_COUNT | (sop << 2) | TX_CONTROL_SEND_MSG;
 
 	ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val);
 	if (ret)
 		return ret;
 
 	ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
-		pdphy->tx_status != -EINPROGRESS, msecs_to_jiffies(timeout_ms));
+		pdphy->tx_status != -EINPROGRESS,
+		msecs_to_jiffies(RECEIVER_RESPONSE_TIME));
 	if (ret <= 0) {
 		dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
 		return ret ? ret : -ETIMEDOUT;
@@ -534,7 +538,7 @@
 	if (hdr && !pdphy->tx_status)
 		pdphy->tx_bytes += data_len + USB_PDPHY_MSG_HDR_LEN;
 
-	return pdphy->tx_status ? pdphy->tx_status : data_len;
+	return pdphy->tx_status ? pdphy->tx_status : 0;
 }
 EXPORT_SYMBOL(pd_phy_write);
 
diff --git a/drivers/usb/pd/usbpd.h b/drivers/usb/pd/usbpd.h
index 1087017..9b6053e 100644
--- a/drivers/usb/pd/usbpd.h
+++ b/drivers/usb/pd/usbpd.h
@@ -45,7 +45,7 @@
 	CABLE_RESET_SIG,
 };
 
-enum pd_msg_type {
+enum pd_sop_type {
 	SOP_MSG = 0,
 	SOPI_MSG,
 	SOPII_MSG,
@@ -61,8 +61,8 @@
 #define FRAME_FILTER_EN_HARD_RESET	BIT(5)
 
 struct pd_phy_params {
-	void		(*signal_cb)(struct usbpd *pd, enum pd_sig_type type);
-	void		(*msg_rx_cb)(struct usbpd *pd, enum pd_msg_type type,
+	void		(*signal_cb)(struct usbpd *pd, enum pd_sig_type sig);
+	void		(*msg_rx_cb)(struct usbpd *pd, enum pd_sop_type sop,
 					u8 *buf, size_t len);
 	void		(*shutdown_cb)(struct usbpd *pd);
 	enum data_role	data_role;
@@ -72,9 +72,9 @@
 
 #if IS_ENABLED(CONFIG_QPNP_USB_PDPHY)
 int pd_phy_open(struct pd_phy_params *params);
-int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms);
+int pd_phy_signal(enum pd_sig_type sig);
 int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
-	enum pd_msg_type type, unsigned int timeout_ms);
+		enum pd_sop_type sop);
 int pd_phy_update_roles(enum data_role dr, enum power_role pr);
 void pd_phy_close(void);
 #else
@@ -83,13 +83,13 @@
 	return -ENODEV;
 }
 
-static inline int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
+static inline int pd_phy_signal(enum pd_sig_type type)
 {
 	return -ENODEV;
 }
 
 static inline int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
-	enum pd_msg_type type, unsigned int timeout_ms)
+		enum pd_sop_type sop)
 {
 	return -ENODEV;
 }
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 012a37a..7994208 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -752,8 +752,10 @@
 	struct usbhs_priv *priv = dev_get_drvdata(dev);
 	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
 
-	if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+	if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
 		usbhsc_power_ctrl(priv, 1);
+		usbhs_mod_autonomy_mode(priv);
+	}
 
 	usbhs_platform_call(priv, phy_reset, pdev);
 
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 5bc7a61..93fba90 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -37,6 +37,7 @@
 struct usbhsg_uep {
 	struct usb_ep		 ep;
 	struct usbhs_pipe	*pipe;
+	spinlock_t		lock;	/* protect the pipe */
 
 	char ep_name[EP_NAME_SIZE];
 
@@ -636,10 +637,16 @@
 static int usbhsg_ep_disable(struct usb_ep *ep)
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+	struct usbhs_pipe *pipe;
+	unsigned long flags;
+	int ret = 0;
 
-	if (!pipe)
-		return -EINVAL;
+	spin_lock_irqsave(&uep->lock, flags);
+	pipe = usbhsg_uep_to_pipe(uep);
+	if (!pipe) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	usbhsg_pipe_disable(uep);
 	usbhs_pipe_free(pipe);
@@ -647,6 +654,9 @@
 	uep->pipe->mod_private	= NULL;
 	uep->pipe		= NULL;
 
+out:
+	spin_unlock_irqrestore(&uep->lock, flags);
+
 	return 0;
 }
 
@@ -696,8 +706,11 @@
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+	struct usbhs_pipe *pipe;
+	unsigned long flags;
 
+	spin_lock_irqsave(&uep->lock, flags);
+	pipe = usbhsg_uep_to_pipe(uep);
 	if (pipe)
 		usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
 
@@ -706,6 +719,7 @@
 	 * even if the pipe is NULL.
 	 */
 	usbhsg_queue_pop(uep, ureq, -ECONNRESET);
+	spin_unlock_irqrestore(&uep->lock, flags);
 
 	return 0;
 }
@@ -852,10 +866,10 @@
 {
 	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
-	struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
+	struct usbhsg_uep *uep;
 	struct device *dev = usbhs_priv_to_dev(priv);
 	unsigned long flags;
-	int ret = 0;
+	int ret = 0, i;
 
 	/********************  spin lock ********************/
 	usbhs_lock(priv, flags);
@@ -887,7 +901,9 @@
 	usbhs_sys_set_test_mode(priv, 0);
 	usbhs_sys_function_ctrl(priv, 0);
 
-	usbhsg_ep_disable(&dcp->ep);
+	/* disable all eps */
+	usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
+		usbhsg_ep_disable(&uep->ep);
 
 	dev_dbg(dev, "stop gadget\n");
 
@@ -1069,6 +1085,7 @@
 		ret = -ENOMEM;
 		goto usbhs_mod_gadget_probe_err_gpriv;
 	}
+	spin_lock_init(&uep->lock);
 
 	gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
 	dev_info(dev, "%stransceiver found\n",
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index fba4005..6a7720e 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1529,8 +1529,11 @@
 
 	/* Make sure driver was initialized */
 
-	if (us->extra == NULL)
+	if (us->extra == NULL) {
 		usb_stor_dbg(us, "ERROR Driver not initialized\n");
+		srb->result = DID_ERROR << 16;
+		return;
+	}
 
 	scsi_set_resid(srb, 0);
 	/* scsi_bufflen might change in protocol translation to ata */
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index d1d70e0..881fc3a 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -419,6 +419,34 @@
 	kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock);
 }
 
+struct vfio_group_put_work {
+	struct work_struct work;
+	struct vfio_group *group;
+};
+
+static void vfio_group_put_bg(struct work_struct *work)
+{
+	struct vfio_group_put_work *do_work;
+
+	do_work = container_of(work, struct vfio_group_put_work, work);
+
+	vfio_group_put(do_work->group);
+	kfree(do_work);
+}
+
+static void vfio_group_schedule_put(struct vfio_group *group)
+{
+	struct vfio_group_put_work *do_work;
+
+	do_work = kmalloc(sizeof(*do_work), GFP_KERNEL);
+	if (WARN_ON(!do_work))
+		return;
+
+	INIT_WORK(&do_work->work, vfio_group_put_bg);
+	do_work->group = group;
+	schedule_work(&do_work->work);
+}
+
 /* Assume group_lock or group reference is held */
 static void vfio_group_get(struct vfio_group *group)
 {
@@ -743,7 +771,14 @@
 		break;
 	}
 
-	vfio_group_put(group);
+	/*
+	 * If we're the last reference to the group, the group will be
+	 * released, which includes unregistering the iommu group notifier.
+	 * We hold a read-lock on that notifier list, unregistering needs
+	 * a write-lock... deadlock.  Release our reference asynchronously
+	 * to avoid that situation.
+	 */
+	vfio_group_schedule_put(group);
 	return NOTIFY_OK;
 }
 
@@ -1716,6 +1751,15 @@
 }
 EXPORT_SYMBOL_GPL(vfio_group_put_external_user);
 
+bool vfio_external_group_match_file(struct vfio_group *test_group,
+				    struct file *filep)
+{
+	struct vfio_group *group = filep->private_data;
+
+	return (filep->f_op == &vfio_group_fops) && (group == test_group);
+}
+EXPORT_SYMBOL_GPL(vfio_external_group_match_file);
+
 int vfio_external_user_iommu_id(struct vfio_group *group)
 {
 	return iommu_group_id(group->iommu_group);
diff --git a/drivers/video/adf/adf_client.c b/drivers/video/adf/adf_client.c
index 8061d8e..75b2f0b 100644
--- a/drivers/video/adf/adf_client.c
+++ b/drivers/video/adf/adf_client.c
@@ -305,8 +305,10 @@
 	}
 
 done:
-	if (ret < 0)
+	if (ret < 0) {
 		adf_buffer_mapping_cleanup(mapping, buf);
+		memset(mapping, 0, sizeof(*mapping));
+	}
 
 	return ret;
 }
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index d6950e0..980f328 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -134,9 +134,7 @@
 	struct page *pages[VSCSI_MAX_GRANTS];
 
 	struct se_cmd se_cmd;
-};
 
-struct scsiback_tmr {
 	atomic_t tmr_complete;
 	wait_queue_head_t tmr_wait;
 };
@@ -599,26 +597,20 @@
 	struct scsiback_tpg *tpg = pending_req->v2p->tpg;
 	struct scsiback_nexus *nexus = tpg->tpg_nexus;
 	struct se_cmd *se_cmd = &pending_req->se_cmd;
-	struct scsiback_tmr *tmr;
 	u64 unpacked_lun = pending_req->v2p->lun;
 	int rc, err = FAILED;
 
-	tmr = kzalloc(sizeof(struct scsiback_tmr), GFP_KERNEL);
-	if (!tmr) {
-		target_put_sess_cmd(se_cmd);
-		goto err;
-	}
-
-	init_waitqueue_head(&tmr->tmr_wait);
+	init_waitqueue_head(&pending_req->tmr_wait);
 
 	rc = target_submit_tmr(&pending_req->se_cmd, nexus->tvn_se_sess,
 			       &pending_req->sense_buffer[0],
-			       unpacked_lun, tmr, act, GFP_KERNEL,
+			       unpacked_lun, NULL, act, GFP_KERNEL,
 			       tag, TARGET_SCF_ACK_KREF);
 	if (rc)
 		goto err;
 
-	wait_event(tmr->tmr_wait, atomic_read(&tmr->tmr_complete));
+	wait_event(pending_req->tmr_wait,
+		   atomic_read(&pending_req->tmr_complete));
 
 	err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
 		SUCCESS : FAILED;
@@ -626,9 +618,8 @@
 	scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
 	transport_generic_free_cmd(&pending_req->se_cmd, 1);
 	return;
+
 err:
-	if (tmr)
-		kfree(tmr);
 	scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
 }
 
@@ -1389,12 +1380,6 @@
 static void scsiback_release_cmd(struct se_cmd *se_cmd)
 {
 	struct se_session *se_sess = se_cmd->se_sess;
-	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
-
-	if (se_tmr && se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
-		struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr;
-		kfree(tmr);
-	}
 
 	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
 }
@@ -1455,11 +1440,11 @@
 
 static void scsiback_queue_tm_rsp(struct se_cmd *se_cmd)
 {
-	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
-	struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr;
+	struct vscsibk_pend *pending_req = container_of(se_cmd,
+				struct vscsibk_pend, se_cmd);
 
-	atomic_set(&tmr->tmr_complete, 1);
-	wake_up(&tmr->tmr_wait);
+	atomic_set(&pending_req->tmr_complete, 1);
+	wake_up(&pending_req->tmr_wait);
 }
 
 static void scsiback_aborted_task(struct se_cmd *se_cmd)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index cfd724f..1fdf4e5 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -911,17 +911,60 @@
 		elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
 
 		vaddr = elf_ppnt->p_vaddr;
+		/*
+		 * If we are loading ET_EXEC or we have already performed
+		 * the ET_DYN load_addr calculations, proceed normally.
+		 */
 		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
 			elf_flags |= MAP_FIXED;
 		} else if (loc->elf_ex.e_type == ET_DYN) {
-			/* Try and get dynamic programs out of the way of the
-			 * default mmap base, as well as whatever program they
-			 * might try to exec.  This is because the brk will
-			 * follow the loader, and is not movable.  */
-			load_bias = ELF_ET_DYN_BASE - vaddr;
-			if (current->flags & PF_RANDOMIZE)
-				load_bias += arch_mmap_rnd();
-			load_bias = ELF_PAGESTART(load_bias);
+			/*
+			 * This logic is run once for the first LOAD Program
+			 * Header for ET_DYN binaries to calculate the
+			 * randomization (load_bias) for all the LOAD
+			 * Program Headers, and to calculate the entire
+			 * size of the ELF mapping (total_size). (Note that
+			 * load_addr_set is set to true later once the
+			 * initial mapping is performed.)
+			 *
+			 * There are effectively two types of ET_DYN
+			 * binaries: programs (i.e. PIE: ET_DYN with INTERP)
+			 * and loaders (ET_DYN without INTERP, since they
+			 * _are_ the ELF interpreter). The loaders must
+			 * be loaded away from programs since the program
+			 * may otherwise collide with the loader (especially
+			 * for ET_EXEC which does not have a randomized
+			 * position). For example to handle invocations of
+			 * "./ld.so someprog" to test out a new version of
+			 * the loader, the subsequent program that the
+			 * loader loads must avoid the loader itself, so
+			 * they cannot share the same load range. Sufficient
+			 * room for the brk must be allocated with the
+			 * loader as well, since brk must be available with
+			 * the loader.
+			 *
+			 * Therefore, programs are loaded offset from
+			 * ELF_ET_DYN_BASE and loaders are loaded into the
+			 * independently randomized mmap region (0 load_bias
+			 * without MAP_FIXED).
+			 */
+			if (elf_interpreter) {
+				load_bias = ELF_ET_DYN_BASE;
+				if (current->flags & PF_RANDOMIZE)
+					load_bias += arch_mmap_rnd();
+				elf_flags |= MAP_FIXED;
+			} else
+				load_bias = 0;
+
+			/*
+			 * Since load_bias is used for all subsequent loading
+			 * calculations, we must lower it by the first vaddr
+			 * so that the remaining calculations based on the
+			 * ELF vaddrs will be correctly offset. The result
+			 * is then page aligned.
+			 */
+			load_bias = ELF_PAGESTART(load_bias - vaddr);
+
 			total_size = total_mapping_size(elf_phdata,
 							loc->elf_ex.e_phnum);
 			if (!total_size) {
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 247b8df..8d8370d 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -78,12 +78,6 @@
 	switch (type) {
 	case ACL_TYPE_ACCESS:
 		name = XATTR_NAME_POSIX_ACL_ACCESS;
-		if (acl) {
-			ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
-			if (ret)
-				return ret;
-		}
-		ret = 0;
 		break;
 	case ACL_TYPE_DEFAULT:
 		if (!S_ISDIR(inode->i_mode))
@@ -119,6 +113,13 @@
 
 int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
+	int ret;
+
+	if (type == ACL_TYPE_ACCESS && acl) {
+		ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+		if (ret)
+			return ret;
+	}
 	return __btrfs_set_acl(NULL, inode, acl, type);
 }
 
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index aca0d88..cec2569 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -292,6 +292,11 @@
 		if (ret < 0)
 			err = ret;
 		dput(last);
+		/* last_name no longer match cache index */
+		if (fi->readdir_cache_idx >= 0) {
+			fi->readdir_cache_idx = -1;
+			fi->dir_release_count = 0;
+		}
 	}
 	return err;
 }
diff --git a/fs/dcache.c b/fs/dcache.c
index 362396a..7171f0d 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1133,11 +1133,12 @@
 		LIST_HEAD(dispose);
 
 		freed = list_lru_walk(&sb->s_dentry_lru,
-			dentry_lru_isolate_shrink, &dispose, UINT_MAX);
+			dentry_lru_isolate_shrink, &dispose, 1024);
 
 		this_cpu_sub(nr_dentry_unused, freed);
 		shrink_dentry_list(&dispose);
-	} while (freed > 0);
+		cond_resched();
+	} while (list_lru_count(&sb->s_dentry_lru) > 0);
 }
 EXPORT_SYMBOL(shrink_dcache_sb);
 
diff --git a/fs/exec.c b/fs/exec.c
index 26ab263..3e2de29 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -215,8 +215,7 @@
 
 	if (write) {
 		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
-		unsigned long ptr_size;
-		struct rlimit *rlim;
+		unsigned long ptr_size, limit;
 
 		/*
 		 * Since the stack will hold pointers to the strings, we
@@ -245,14 +244,16 @@
 			return page;
 
 		/*
-		 * Limit to 1/4-th the stack size for the argv+env strings.
+		 * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
+		 * (whichever is smaller) for the argv+env strings.
 		 * This ensures that:
 		 *  - the remaining binfmt code will not run out of stack space,
 		 *  - the program will have a reasonable amount of stack left
 		 *    to work from.
 		 */
-		rlim = current->signal->rlim;
-		if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4)
+		limit = _STK_LIM / 4 * 3;
+		limit = min(limit, rlimit(RLIMIT_STACK) / 4);
+		if (size > limit)
 			goto fail;
 	}
 
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 79dafa7..069c0dc 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -175,11 +175,8 @@
 	return acl;
 }
 
-/*
- * inode->i_mutex: down
- */
-int
-ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+static int
+__ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
 	int name_index;
 	void *value = NULL;
@@ -189,13 +186,6 @@
 	switch(type) {
 		case ACL_TYPE_ACCESS:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
-			if (acl) {
-				error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
-				if (error)
-					return error;
-				inode->i_ctime = current_time(inode);
-				mark_inode_dirty(inode);
-			}
 			break;
 
 		case ACL_TYPE_DEFAULT:
@@ -222,6 +212,24 @@
 }
 
 /*
+ * inode->i_mutex: down
+ */
+int
+ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+	int error;
+
+	if (type == ACL_TYPE_ACCESS && acl) {
+		error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+		if (error)
+			return error;
+		inode->i_ctime = current_time(inode);
+		mark_inode_dirty(inode);
+	}
+	return __ext2_set_acl(inode, acl, type);
+}
+
+/*
  * Initialize the ACLs of a new inode. Called from ext2_new_inode.
  *
  * dir->i_mutex: down
@@ -238,12 +246,12 @@
 		return error;
 
 	if (default_acl) {
-		error = ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+		error = __ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
 		posix_acl_release(default_acl);
 	}
 	if (acl) {
 		if (!error)
-			error = ext2_set_acl(inode, acl, ACL_TYPE_ACCESS);
+			error = __ext2_set_acl(inode, acl, ACL_TYPE_ACCESS);
 		posix_acl_release(acl);
 	}
 	return error;
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 6fe23af..55aa29c 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -211,7 +211,7 @@
 	switch (type) {
 	case ACL_TYPE_ACCESS:
 		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
-		if (acl) {
+		if (acl && !ipage) {
 			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 			if (error)
 				return error;
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index 60da84a..5d75cc4 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -5,4 +5,4 @@
 obj-$(CONFIG_FUSE_FS) += fuse.o
 obj-$(CONFIG_CUSE) += cuse.o
 
-fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o
+fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o passthrough.o
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 83511cb..658fa9e 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -7,6 +7,7 @@
 */
 
 #include "fuse_i.h"
+#include "fuse_passthrough.h"
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -550,9 +551,14 @@
 	       args->out.numargs * sizeof(struct fuse_arg));
 	fuse_request_send(fc, req);
 	ret = req->out.h.error;
-	if (!ret && args->out.argvar) {
-		BUG_ON(args->out.numargs != 1);
-		ret = req->out.args[0].size;
+	if (!ret) {
+		if (args->out.argvar) {
+			WARN_ON(args->out.numargs != 1);
+			ret = req->out.args[0].size;
+		}
+
+		if (req->passthrough_filp != NULL)
+			args->out.passthrough_filp = req->passthrough_filp;
 	}
 	fuse_put_request(fc, req);
 
@@ -1890,6 +1896,9 @@
 	}
 	fuse_copy_finish(cs);
 
+	fuse_setup_passthrough(fc, req);
+
+
 	spin_lock(&fpq->lock);
 	clear_bit(FR_LOCKED, &req->flags);
 	if (!fpq->connected)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index fc8ba62..c7c3c96 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -491,6 +491,7 @@
 	args.out.args[0].value = &outentry;
 	args.out.args[1].size = sizeof(outopen);
 	args.out.args[1].value = &outopen;
+	args.out.passthrough_filp = NULL;
 	err = fuse_simple_request(fc, &args);
 	if (err)
 		goto out_free_ff;
@@ -502,6 +503,8 @@
 	ff->fh = outopen.fh;
 	ff->nodeid = outentry.nodeid;
 	ff->open_flags = outopen.open_flags;
+	if (args.out.passthrough_filp != NULL)
+		ff->passthrough_filp = args.out.passthrough_filp;
 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
 	if (!inode) {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 5ec5870..75c95659 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -7,6 +7,7 @@
 */
 
 #include "fuse_i.h"
+#include "fuse_passthrough.h"
 
 #include <linux/pagemap.h>
 #include <linux/slab.h>
@@ -21,8 +22,10 @@
 static const struct file_operations fuse_direct_io_file_operations;
 
 static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
-			  int opcode, struct fuse_open_out *outargp)
+			  int opcode, struct fuse_open_out *outargp,
+			  struct file **passthrough_filpp)
 {
+	int ret_val;
 	struct fuse_open_in inarg;
 	FUSE_ARGS(args);
 
@@ -38,8 +41,14 @@
 	args.out.numargs = 1;
 	args.out.args[0].size = sizeof(*outargp);
 	args.out.args[0].value = outargp;
+	args.out.passthrough_filp = NULL;
 
-	return fuse_simple_request(fc, &args);
+	ret_val = fuse_simple_request(fc, &args);
+
+	if (args.out.passthrough_filp != NULL)
+		*passthrough_filpp = args.out.passthrough_filp;
+
+	return ret_val;
 }
 
 struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
@@ -50,6 +59,11 @@
 	if (unlikely(!ff))
 		return NULL;
 
+	ff->passthrough_filp = NULL;
+	ff->passthrough_enabled = 0;
+	if (fc->passthrough)
+		ff->passthrough_enabled = 1;
+
 	ff->fc = fc;
 	ff->reserved_req = fuse_request_alloc(0);
 	if (unlikely(!ff->reserved_req)) {
@@ -118,6 +132,7 @@
 		 bool isdir)
 {
 	struct fuse_file *ff;
+	struct file *passthrough_filp = NULL;
 	int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
 
 	ff = fuse_file_alloc(fc);
@@ -130,11 +145,12 @@
 		struct fuse_open_out outarg;
 		int err;
 
-		err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
+		err = fuse_send_open(fc, nodeid, file, opcode, &outarg,
+				     &(passthrough_filp));
 		if (!err) {
 			ff->fh = outarg.fh;
 			ff->open_flags = outarg.open_flags;
-
+			ff->passthrough_filp = passthrough_filp;
 		} else if (err != -ENOSYS || isdir) {
 			fuse_file_free(ff);
 			return err;
@@ -253,6 +269,8 @@
 	if (unlikely(!ff))
 		return;
 
+	fuse_passthrough_release(ff);
+
 	req = ff->reserved_req;
 	fuse_prepare_release(ff, file->f_flags, opcode);
 
@@ -917,8 +935,10 @@
 
 static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
+	ssize_t ret_val;
 	struct inode *inode = iocb->ki_filp->f_mapping->host;
 	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_file *ff = iocb->ki_filp->private_data;
 
 	/*
 	 * In auto invalidate mode, always update attributes on read.
@@ -933,7 +953,12 @@
 			return err;
 	}
 
-	return generic_file_read_iter(iocb, to);
+	if (ff && ff->passthrough_enabled && ff->passthrough_filp)
+		ret_val = fuse_passthrough_read_iter(iocb, to);
+	else
+		ret_val = generic_file_read_iter(iocb, to);
+
+	return ret_val;
 }
 
 static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
@@ -1165,6 +1190,7 @@
 static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
 	struct file *file = iocb->ki_filp;
+	struct fuse_file *ff = file->private_data;
 	struct address_space *mapping = file->f_mapping;
 	ssize_t written = 0;
 	ssize_t written_buffered = 0;
@@ -1198,6 +1224,11 @@
 	if (err)
 		goto out;
 
+	if (ff && ff->passthrough_enabled && ff->passthrough_filp) {
+		written = fuse_passthrough_write_iter(iocb, from);
+		goto out;
+	}
+
 	if (iocb->ki_flags & IOCB_DIRECT) {
 		loff_t pos = iocb->ki_pos;
 		written = generic_file_direct_write(iocb, from);
@@ -2069,6 +2100,9 @@
 
 static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
+	struct fuse_file *ff = file->private_data;
+
+	ff->passthrough_enabled = 0;
 	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
 		fuse_link_write_file(file);
 
@@ -2079,6 +2113,9 @@
 
 static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
 {
+	struct fuse_file *ff = file->private_data;
+
+	ff->passthrough_enabled = 0;
 	/* Can't provide the coherency needed for MAP_SHARED */
 	if (vma->vm_flags & VM_MAYSHARE)
 		return -ENODEV;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6b30a12..cc2c82c 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -153,6 +153,10 @@
 
 	/** Has flock been performed on this file? */
 	bool flock:1;
+
+	/* the read write file */
+	struct file *passthrough_filp;
+	bool passthrough_enabled;
 };
 
 /** One input argument of a request */
@@ -232,6 +236,7 @@
 		unsigned argvar:1;
 		unsigned numargs;
 		struct fuse_arg args[2];
+		struct file *passthrough_filp;
 	} out;
 };
 
@@ -382,6 +387,9 @@
 
 	/** Request is stolen from fuse_file->reserved_req */
 	struct file *stolen_file;
+
+	/** fuse passthrough file  */
+	struct file *passthrough_filp;
 };
 
 struct fuse_iqueue {
@@ -542,6 +550,9 @@
 	/** handle fs handles killing suid/sgid/cap on write/chown/trunc */
 	unsigned handle_killpriv:1;
 
+	/** passthrough IO. */
+	unsigned passthrough:1;
+
 	/*
 	 * The following bitfields are only for optimization purposes
 	 * and hence races in setting them will not cause malfunction
diff --git a/fs/fuse/fuse_passthrough.h b/fs/fuse/fuse_passthrough.h
new file mode 100644
index 0000000..12429ac
--- /dev/null
+++ b/fs/fuse/fuse_passthrough.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015-2017, 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 _FS_FUSE_PASSTHROUGH_H
+#define _FS_FUSE_PASSTHROUGH_H
+
+#include "fuse_i.h"
+
+#include <linux/fuse.h>
+#include <linux/file.h>
+
+void fuse_setup_passthrough(struct fuse_conn *fc, struct fuse_req *req);
+
+ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to);
+
+ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from);
+
+void fuse_passthrough_release(struct fuse_file *ff);
+
+#endif /* _FS_FUSE_PASSTHROUGH_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 6fe6a88..f1512c8 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -915,6 +915,12 @@
 				fc->parallel_dirops = 1;
 			if (arg->flags & FUSE_HANDLE_KILLPRIV)
 				fc->handle_killpriv = 1;
+			if (arg->flags & FUSE_PASSTHROUGH) {
+				fc->passthrough = 1;
+				/* Prevent further stacking */
+				fc->sb->s_stack_depth =
+					FILESYSTEM_MAX_STACK_DEPTH;
+			}
 			if (arg->time_gran && arg->time_gran <= 1000000000)
 				fc->sb->s_time_gran = arg->time_gran;
 			if ((arg->flags & FUSE_POSIX_ACL)) {
diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
new file mode 100644
index 0000000..c92c40b
--- /dev/null
+++ b/fs/fuse/passthrough.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015-2017, 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 "fuse_passthrough.h"
+
+#include <linux/aio.h>
+#include <linux/fs_stack.h>
+
+void fuse_setup_passthrough(struct fuse_conn *fc, struct fuse_req *req)
+{
+	int daemon_fd, fs_stack_depth;
+	unsigned int open_out_index;
+	struct file *passthrough_filp;
+	struct inode *passthrough_inode;
+	struct super_block *passthrough_sb;
+	struct fuse_open_out *open_out;
+
+	req->passthrough_filp = NULL;
+
+	if (!(fc->passthrough))
+		return;
+
+	if ((req->in.h.opcode != FUSE_OPEN) &&
+	    (req->in.h.opcode != FUSE_CREATE))
+		return;
+
+	open_out_index = req->in.numargs - 1;
+
+	WARN_ON(open_out_index != 0 && open_out_index != 1);
+	WARN_ON(req->out.args[open_out_index].size != sizeof(*open_out));
+
+	open_out = req->out.args[open_out_index].value;
+
+	daemon_fd = (int)open_out->passthrough_fd;
+	if (daemon_fd < 0)
+		return;
+
+	passthrough_filp = fget_raw(daemon_fd);
+	if (!passthrough_filp)
+		return;
+
+	passthrough_inode = file_inode(passthrough_filp);
+	passthrough_sb = passthrough_inode->i_sb;
+	fs_stack_depth = passthrough_sb->s_stack_depth + 1;
+
+	/* If we reached the stacking limit go through regular io */
+	if (fs_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+		/* Release the passthrough file. */
+		fput(passthrough_filp);
+		pr_err("FUSE: maximum fs stacking depth exceeded, cannot use passthrough for this file\n");
+		return;
+	}
+	req->passthrough_filp = passthrough_filp;
+}
+
+
+static ssize_t fuse_passthrough_read_write_iter(struct kiocb *iocb,
+					    struct iov_iter *iter, int do_write)
+{
+	ssize_t ret_val;
+	struct fuse_file *ff;
+	struct file *fuse_file, *passthrough_filp;
+	struct inode *fuse_inode, *passthrough_inode;
+	struct fuse_conn *fc;
+
+	ff = iocb->ki_filp->private_data;
+	fuse_file = iocb->ki_filp;
+	passthrough_filp = ff->passthrough_filp;
+	fc = ff->fc;
+
+	/* lock passthrough file to prevent it from being released */
+	get_file(passthrough_filp);
+	iocb->ki_filp = passthrough_filp;
+	fuse_inode = fuse_file->f_path.dentry->d_inode;
+	passthrough_inode = file_inode(passthrough_filp);
+
+	if (do_write) {
+		if (!passthrough_filp->f_op->write_iter)
+			return -EIO;
+
+		ret_val = passthrough_filp->f_op->write_iter(iocb, iter);
+
+		if (ret_val >= 0 || ret_val == -EIOCBQUEUED) {
+			spin_lock(&fc->lock);
+			fsstack_copy_inode_size(fuse_inode, passthrough_inode);
+			spin_unlock(&fc->lock);
+			fsstack_copy_attr_times(fuse_inode, passthrough_inode);
+		}
+	} else {
+		if (!passthrough_filp->f_op->read_iter)
+			return -EIO;
+
+		ret_val = passthrough_filp->f_op->read_iter(iocb, iter);
+		if (ret_val >= 0 || ret_val == -EIOCBQUEUED)
+			fsstack_copy_attr_atime(fuse_inode, passthrough_inode);
+	}
+
+	iocb->ki_filp = fuse_file;
+
+	/* unlock passthrough file */
+	fput(passthrough_filp);
+
+	return ret_val;
+}
+
+ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	return fuse_passthrough_read_write_iter(iocb, to, 0);
+}
+
+ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+	return fuse_passthrough_read_write_iter(iocb, from, 1);
+}
+
+void fuse_passthrough_release(struct fuse_file *ff)
+{
+	if (!(ff->passthrough_filp))
+		return;
+
+	/* Release the passthrough file. */
+	fput(ff->passthrough_filp);
+	ff->passthrough_filp = NULL;
+}
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
index 9b92058..6bb5d7c 100644
--- a/fs/hfsplus/posix_acl.c
+++ b/fs/hfsplus/posix_acl.c
@@ -51,8 +51,8 @@
 	return acl;
 }
 
-int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
-		int type)
+static int __hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
+				   int type)
 {
 	int err;
 	char *xattr_name;
@@ -64,12 +64,6 @@
 	switch (type) {
 	case ACL_TYPE_ACCESS:
 		xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
-		if (acl) {
-			err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
-			if (err)
-				return err;
-		}
-		err = 0;
 		break;
 
 	case ACL_TYPE_DEFAULT:
@@ -105,6 +99,18 @@
 	return err;
 }
 
+int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+	int err;
+
+	if (type == ACL_TYPE_ACCESS && acl) {
+		err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+		if (err)
+			return err;
+	}
+	return __hfsplus_set_posix_acl(inode, acl, type);
+}
+
 int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
 {
 	int err = 0;
@@ -122,15 +128,15 @@
 		return err;
 
 	if (default_acl) {
-		err = hfsplus_set_posix_acl(inode, default_acl,
-					    ACL_TYPE_DEFAULT);
+		err = __hfsplus_set_posix_acl(inode, default_acl,
+					      ACL_TYPE_DEFAULT);
 		posix_acl_release(default_acl);
 	}
 
 	if (acl) {
 		if (!err)
-			err = hfsplus_set_posix_acl(inode, acl,
-						    ACL_TYPE_ACCESS);
+			err = __hfsplus_set_posix_acl(inode, acl,
+						      ACL_TYPE_ACCESS);
 		posix_acl_release(acl);
 	}
 	return err;
diff --git a/fs/mount.h b/fs/mount.h
index d8295f2..3603884 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -58,6 +58,7 @@
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
 	struct mountpoint *mnt_mp;	/* where is it mounted */
 	struct hlist_node mnt_mp_list;	/* list mounts with the same mountpoint */
+	struct list_head mnt_umounting; /* list entry for umount propagation */
 #ifdef CONFIG_FSNOTIFY
 	struct hlist_head mnt_fsnotify_marks;
 	__u32 mnt_fsnotify_mask;
diff --git a/fs/namespace.c b/fs/namespace.c
index 5147334..7731f77 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -237,6 +237,7 @@
 		INIT_LIST_HEAD(&mnt->mnt_slave_list);
 		INIT_LIST_HEAD(&mnt->mnt_slave);
 		INIT_HLIST_NODE(&mnt->mnt_mp_list);
+		INIT_LIST_HEAD(&mnt->mnt_umounting);
 #ifdef CONFIG_FSNOTIFY
 		INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks);
 #endif
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 53e02b8..d04ec381 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1167,11 +1167,13 @@
 	/* Force a full look up iff the parent directory has changed */
 	if (!nfs_is_exclusive_create(dir, flags) &&
 	    nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
-
-		if (nfs_lookup_verify_inode(inode, flags)) {
+		error = nfs_lookup_verify_inode(inode, flags);
+		if (error) {
 			if (flags & LOOKUP_RCU)
 				return -ECHILD;
-			goto out_zap_parent;
+			if (error == -ESTALE)
+				goto out_zap_parent;
+			goto out_error;
 		}
 		goto out_valid;
 	}
@@ -1195,8 +1197,10 @@
 	trace_nfs_lookup_revalidate_enter(dir, dentry, flags);
 	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
 	trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error);
-	if (error)
+	if (error == -ESTALE || error == -ENOENT)
 		goto out_bad;
+	if (error)
+		goto out_error;
 	if (nfs_compare_fh(NFS_FH(inode), fhandle))
 		goto out_bad;
 	if ((error = nfs_refresh_inode(inode, fattr)) != 0)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bf4ec5e..76ae256 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1278,9 +1278,9 @@
 		return 0;
 	/* Has the inode gone and changed behind our back? */
 	if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
-		return -EIO;
+		return -ESTALE;
 	if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
-		return -EIO;
+		return -ESTALE;
 
 	if (!nfs_file_has_buffered_writers(nfsi)) {
 		/* Verify a few of the more important attributes */
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 0e10085..e7c8ac4 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1146,6 +1146,7 @@
 	unsigned int stacklen = 0;
 	unsigned int i;
 	bool remote = false;
+	struct cred *cred;
 	int err;
 
 	err = -ENOMEM;
@@ -1309,10 +1310,14 @@
 	else
 		sb->s_d_op = &ovl_dentry_operations;
 
-	ufs->creator_cred = prepare_creds();
-	if (!ufs->creator_cred)
+	err = -ENOMEM;
+	ufs->creator_cred = cred = prepare_creds();
+	if (!cred)
 		goto out_put_lower_mnt;
 
+	/* Never override disk quota limits or use reserved space */
+	cap_lower(cred->cap_effective, CAP_SYS_RESOURCE);
+
 	err = -ENOMEM;
 	oe = ovl_alloc_entry(numlower);
 	if (!oe)
diff --git a/fs/pnode.c b/fs/pnode.c
index e4e428d..ddb846f 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -24,6 +24,11 @@
 	return list_entry(p->mnt_slave_list.next, struct mount, mnt_slave);
 }
 
+static inline struct mount *last_slave(struct mount *p)
+{
+	return list_entry(p->mnt_slave_list.prev, struct mount, mnt_slave);
+}
+
 static inline struct mount *next_slave(struct mount *p)
 {
 	return list_entry(p->mnt_slave.next, struct mount, mnt_slave);
@@ -164,6 +169,19 @@
 	}
 }
 
+static struct mount *skip_propagation_subtree(struct mount *m,
+						struct mount *origin)
+{
+	/*
+	 * Advance m such that propagation_next will not return
+	 * the slaves of m.
+	 */
+	if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
+		m = last_slave(m);
+
+	return m;
+}
+
 static struct mount *next_group(struct mount *m, struct mount *origin)
 {
 	while (1) {
@@ -415,68 +433,107 @@
 	}
 }
 
-/*
- * Mark all mounts that the MNT_LOCKED logic will allow to be unmounted.
- */
-static void mark_umount_candidates(struct mount *mnt)
+static void umount_one(struct mount *mnt, struct list_head *to_umount)
 {
-	struct mount *parent = mnt->mnt_parent;
-	struct mount *m;
-
-	BUG_ON(parent == mnt);
-
-	for (m = propagation_next(parent, parent); m;
-			m = propagation_next(m, parent)) {
-		struct mount *child = __lookup_mnt(&m->mnt,
-						mnt->mnt_mountpoint);
-		if (!child || (child->mnt.mnt_flags & MNT_UMOUNT))
-			continue;
-		if (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m)) {
-			SET_MNT_MARK(child);
-		}
-	}
+	CLEAR_MNT_MARK(mnt);
+	mnt->mnt.mnt_flags |= MNT_UMOUNT;
+	list_del_init(&mnt->mnt_child);
+	list_del_init(&mnt->mnt_umounting);
+	list_move_tail(&mnt->mnt_list, to_umount);
 }
 
 /*
  * NOTE: unmounting 'mnt' naturally propagates to all other mounts its
  * parent propagates to.
  */
-static void __propagate_umount(struct mount *mnt)
+static bool __propagate_umount(struct mount *mnt,
+			       struct list_head *to_umount,
+			       struct list_head *to_restore)
 {
-	struct mount *parent = mnt->mnt_parent;
-	struct mount *m;
+	bool progress = false;
+	struct mount *child;
 
-	BUG_ON(parent == mnt);
+	/*
+	 * The state of the parent won't change if this mount is
+	 * already unmounted or marked as without children.
+	 */
+	if (mnt->mnt.mnt_flags & (MNT_UMOUNT | MNT_MARKED))
+		goto out;
 
-	for (m = propagation_next(parent, parent); m;
-			m = propagation_next(m, parent)) {
-		struct mount *topper;
-		struct mount *child = __lookup_mnt(&m->mnt,
-						mnt->mnt_mountpoint);
-		/*
-		 * umount the child only if the child has no children
-		 * and the child is marked safe to unmount.
-		 */
-		if (!child || !IS_MNT_MARKED(child))
+	/* Verify topper is the only grandchild that has not been
+	 * speculatively unmounted.
+	 */
+	list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
+		if (child->mnt_mountpoint == mnt->mnt.mnt_root)
 			continue;
-		CLEAR_MNT_MARK(child);
+		if (!list_empty(&child->mnt_umounting) && IS_MNT_MARKED(child))
+			continue;
+		/* Found a mounted child */
+		goto children;
+	}
 
-		/* If there is exactly one mount covering all of child
-		 * replace child with that mount.
-		 */
-		topper = find_topper(child);
-		if (topper)
-			mnt_change_mountpoint(child->mnt_parent, child->mnt_mp,
-					      topper);
+	/* Mark mounts that can be unmounted if not locked */
+	SET_MNT_MARK(mnt);
+	progress = true;
 
-		if (list_empty(&child->mnt_mounts)) {
-			list_del_init(&child->mnt_child);
-			child->mnt.mnt_flags |= MNT_UMOUNT;
-			list_move_tail(&child->mnt_list, &mnt->mnt_list);
+	/* If a mount is without children and not locked umount it. */
+	if (!IS_MNT_LOCKED(mnt)) {
+		umount_one(mnt, to_umount);
+	} else {
+children:
+		list_move_tail(&mnt->mnt_umounting, to_restore);
+	}
+out:
+	return progress;
+}
+
+static void umount_list(struct list_head *to_umount,
+			struct list_head *to_restore)
+{
+	struct mount *mnt, *child, *tmp;
+	list_for_each_entry(mnt, to_umount, mnt_list) {
+		list_for_each_entry_safe(child, tmp, &mnt->mnt_mounts, mnt_child) {
+			/* topper? */
+			if (child->mnt_mountpoint == mnt->mnt.mnt_root)
+				list_move_tail(&child->mnt_umounting, to_restore);
+			else
+				umount_one(child, to_umount);
 		}
 	}
 }
 
+static void restore_mounts(struct list_head *to_restore)
+{
+	/* Restore mounts to a clean working state */
+	while (!list_empty(to_restore)) {
+		struct mount *mnt, *parent;
+		struct mountpoint *mp;
+
+		mnt = list_first_entry(to_restore, struct mount, mnt_umounting);
+		CLEAR_MNT_MARK(mnt);
+		list_del_init(&mnt->mnt_umounting);
+
+		/* Should this mount be reparented? */
+		mp = mnt->mnt_mp;
+		parent = mnt->mnt_parent;
+		while (parent->mnt.mnt_flags & MNT_UMOUNT) {
+			mp = parent->mnt_mp;
+			parent = parent->mnt_parent;
+		}
+		if (parent != mnt->mnt_parent)
+			mnt_change_mountpoint(parent, mp, mnt);
+	}
+}
+
+static void cleanup_umount_visitations(struct list_head *visited)
+{
+	while (!list_empty(visited)) {
+		struct mount *mnt =
+			list_first_entry(visited, struct mount, mnt_umounting);
+		list_del_init(&mnt->mnt_umounting);
+	}
+}
+
 /*
  * collect all mounts that receive propagation from the mount in @list,
  * and return these additional mounts in the same list.
@@ -487,12 +544,69 @@
 int propagate_umount(struct list_head *list)
 {
 	struct mount *mnt;
+	LIST_HEAD(to_restore);
+	LIST_HEAD(to_umount);
+	LIST_HEAD(visited);
 
-	list_for_each_entry_reverse(mnt, list, mnt_list)
-		mark_umount_candidates(mnt);
+	/* Find candidates for unmounting */
+	list_for_each_entry_reverse(mnt, list, mnt_list) {
+		struct mount *parent = mnt->mnt_parent;
+		struct mount *m;
 
-	list_for_each_entry(mnt, list, mnt_list)
-		__propagate_umount(mnt);
+		/*
+		 * If this mount has already been visited it is known that it's
+		 * entire peer group and all of their slaves in the propagation
+		 * tree for the mountpoint has already been visited and there is
+		 * no need to visit them again.
+		 */
+		if (!list_empty(&mnt->mnt_umounting))
+			continue;
+
+		list_add_tail(&mnt->mnt_umounting, &visited);
+		for (m = propagation_next(parent, parent); m;
+		     m = propagation_next(m, parent)) {
+			struct mount *child = __lookup_mnt(&m->mnt,
+							   mnt->mnt_mountpoint);
+			if (!child)
+				continue;
+
+			if (!list_empty(&child->mnt_umounting)) {
+				/*
+				 * If the child has already been visited it is
+				 * know that it's entire peer group and all of
+				 * their slaves in the propgation tree for the
+				 * mountpoint has already been visited and there
+				 * is no need to visit this subtree again.
+				 */
+				m = skip_propagation_subtree(m, parent);
+				continue;
+			} else if (child->mnt.mnt_flags & MNT_UMOUNT) {
+				/*
+				 * We have come accross an partially unmounted
+				 * mount in list that has not been visited yet.
+				 * Remember it has been visited and continue
+				 * about our merry way.
+				 */
+				list_add_tail(&child->mnt_umounting, &visited);
+				continue;
+			}
+
+			/* Check the child and parents while progress is made */
+			while (__propagate_umount(child,
+						  &to_umount, &to_restore)) {
+				/* Is the parent a umount candidate? */
+				child = child->mnt_parent;
+				if (list_empty(&child->mnt_umounting))
+					break;
+			}
+		}
+	}
+
+	umount_list(&to_umount, &to_restore);
+	restore_mounts(&to_restore);
+	cleanup_umount_visitations(&visited);
+	list_splice_tail(&to_umount, list);
+
 	return 0;
 }
 
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 71b62b8..c585e7e 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1617,6 +1617,9 @@
 		if (vma->vm_file)
 			continue;
 
+		if (vma->vm_flags & VM_LOCKED)
+			continue;
+
 		if (!rp.nr_to_reclaim)
 			break;
 
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 3d2256a..d92a1dc 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -37,7 +37,14 @@
 	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
 	reiserfs_write_unlock(inode->i_sb);
 	if (error == 0) {
+		if (type == ACL_TYPE_ACCESS && acl) {
+			error = posix_acl_update_mode(inode, &inode->i_mode,
+						      &acl);
+			if (error)
+				goto unlock;
+		}
 		error = __reiserfs_set_acl(&th, inode, type, acl);
+unlock:
 		reiserfs_write_lock(inode->i_sb);
 		error2 = journal_end(&th);
 		reiserfs_write_unlock(inode->i_sb);
@@ -241,11 +248,6 @@
 	switch (type) {
 	case ACL_TYPE_ACCESS:
 		name = XATTR_NAME_POSIX_ACL_ACCESS;
-		if (acl) {
-			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
-			if (error)
-				return error;
-		}
 		break;
 	case ACL_TYPE_DEFAULT:
 		name = XATTR_NAME_POSIX_ACL_DEFAULT;
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index d48da41..683b492 100644
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -773,13 +773,9 @@
 	 * afterwards in the other cases: we fsstack_copy_inode_size from
 	 * the lower level.
 	 */
-	if (current->mm)
-		down_write(&current->mm->mmap_sem);
 	if (ia->ia_valid & ATTR_SIZE) {
 		err = inode_newsize_ok(&tmp, ia->ia_size);
 		if (err) {
-			if (current->mm)
-				up_write(&current->mm->mmap_sem);
 			goto out;
 		}
 		truncate_setsize(inode, ia->ia_size);
@@ -802,8 +798,6 @@
 	err = notify_change2(lower_mnt, lower_dentry, &lower_ia, /* note: lower_ia */
 			NULL);
 	inode_unlock(d_inode(lower_dentry));
-	if (current->mm)
-		up_write(&current->mm->mmap_sem);
 	if (err)
 		goto out;
 
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 91bc76dc..7d764e3 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -576,7 +576,7 @@
 	/* Make sure to also account for extended attributes */
 	len += host_ui->data_len;
 
-	dent = kmalloc(len, GFP_NOFS);
+	dent = kzalloc(len, GFP_NOFS);
 	if (!dent)
 		return -ENOMEM;
 
@@ -952,7 +952,7 @@
 	if (twoparents)
 		len += plen;
 
-	dent1 = kmalloc(len, GFP_NOFS);
+	dent1 = kzalloc(len, GFP_NOFS);
 	if (!dent1)
 		return -ENOMEM;
 
@@ -1102,7 +1102,7 @@
 	len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
 	if (move)
 		len += plen;
-	dent = kmalloc(len, GFP_NOFS);
+	dent = kzalloc(len, GFP_NOFS);
 	if (!dent)
 		return -ENOMEM;
 
@@ -1466,7 +1466,7 @@
 	hlen = host_ui->data_len + UBIFS_INO_NODE_SZ;
 	len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);
 
-	xent = kmalloc(len, GFP_NOFS);
+	xent = kzalloc(len, GFP_NOFS);
 	if (!xent)
 		return -ENOMEM;
 
@@ -1573,7 +1573,7 @@
 	aligned_len1 = ALIGN(len1, 8);
 	aligned_len = aligned_len1 + ALIGN(len2, 8);
 
-	ino = kmalloc(aligned_len, GFP_NOFS);
+	ino = kzalloc(aligned_len, GFP_NOFS);
 	if (!ino)
 		return -ENOMEM;
 
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 129b18a..0359435 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1243,8 +1243,8 @@
 			return err;
 		}
 set_size:
-		truncate_setsize(inode, newsize);
 		up_write(&iinfo->i_data_sem);
+		truncate_setsize(inode, newsize);
 	} else {
 		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
 			down_write(&iinfo->i_data_sem);
@@ -1261,9 +1261,9 @@
 					  udf_get_block);
 		if (err)
 			return err;
+		truncate_setsize(inode, newsize);
 		down_write(&iinfo->i_data_sem);
 		udf_clear_extent_cache(inode);
-		truncate_setsize(inode, newsize);
 		udf_truncate_extents(inode);
 		up_write(&iinfo->i_data_sem);
 	}
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index b468e04..7034e17 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -170,8 +170,8 @@
 	return acl;
 }
 
-STATIC int
-__xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+int
+__xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
 	struct xfs_inode *ip = XFS_I(inode);
 	unsigned char *ea_name;
@@ -268,5 +268,5 @@
 	}
 
  set_acl:
-	return __xfs_set_acl(inode, type, acl);
+	return __xfs_set_acl(inode, acl, type);
 }
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 286fa89..0432731 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -24,6 +24,7 @@
 #ifdef CONFIG_XFS_POSIX_ACL
 extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
 extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
+extern int __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 #else
 static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
 {
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index f5e0f60..a1247c3 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -190,12 +190,12 @@
 
 #ifdef CONFIG_XFS_POSIX_ACL
 	if (default_acl) {
-		error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+		error = __xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
 		if (error)
 			goto out_cleanup_inode;
 	}
 	if (acl) {
-		error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+		error = __xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
 		if (error)
 			goto out_cleanup_inode;
 	}
diff --git a/include/dt-bindings/clock/qcom,aop-qmp.h b/include/dt-bindings/clock/qcom,aop-qmp.h
index b88dc36..7898c47 100644
--- a/include/dt-bindings/clock/qcom,aop-qmp.h
+++ b/include/dt-bindings/clock/qcom,aop-qmp.h
@@ -25,5 +25,5 @@
 
 /* clocks id */
 #define QDSS_CLK			0
-
+#define QDSS_AO_CLK			1
 #endif
diff --git a/include/dt-bindings/clock/qcom,gpucc-sdm845.h b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
index 323beaf..74a742a 100644
--- a/include/dt-bindings/clock/qcom,gpucc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
@@ -44,6 +44,7 @@
 #define GPU_CC_GMU_CLK_SRC					26
 #define GPU_CC_CX_GFX3D_CLK					27
 #define GPU_CC_CX_GFX3D_SLV_CLK					28
+#define GPU_CC_PLL0						29
 
 /* GPUCC reset clock registers */
 #define GPUCC_GPU_CC_ACD_BCR					0
@@ -55,7 +56,6 @@
 #define GPUCC_GPU_CC_XO_BCR					6
 
 /* GFX3D clock registers */
-#define GPU_CC_PLL0						0
 #define GPU_CC_PLL0_OUT_EVEN					1
 #define GPU_CC_GX_GFX3D_CLK_SRC					2
 #define GPU_CC_GX_GFX3D_CLK					3
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 29f9e77..d04f178 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -18,13 +18,15 @@
 extern unsigned long totalcma_pages;
 extern phys_addr_t cma_get_base(const struct cma *cma);
 extern unsigned long cma_get_size(const struct cma *cma);
+extern const char *cma_get_name(const struct cma *cma);
 
 extern int __init cma_declare_contiguous(phys_addr_t base,
 			phys_addr_t size, phys_addr_t limit,
 			phys_addr_t alignment, unsigned int order_per_bit,
-			bool fixed, struct cma **res_cma);
+			bool fixed, const char *name, struct cma **res_cma);
 extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 					unsigned int order_per_bit,
+					const char *name,
 					struct cma **res_cma);
 extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align);
 extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 9f93d18..edf88bd 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -40,6 +40,7 @@
 	CPUHP_SLAB_PREPARE,
 	CPUHP_MD_RAID5_PREPARE,
 	CPUHP_RCUTREE_PREP,
+	CPUHP_CORE_CTL_ISOLATION_DEAD,
 	CPUHP_CPUIDLE_COUPLED_PREPARE,
 	CPUHP_POWERPC_PMAC_PREPARE,
 	CPUHP_POWERPC_MMU_CTX_PREPARE,
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 4fbc62e..b49f866 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -251,6 +251,23 @@
 		(cpu) = cpumask_next_zero((cpu), (mask)),	\
 		(cpu) < nr_cpu_ids;)
 
+extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap);
+
+/**
+ * for_each_cpu_wrap - iterate over every cpu in a mask, starting at a specified location
+ * @cpu: the (optionally unsigned) integer iterator
+ * @mask: the cpumask poiter
+ * @start: the start location
+ *
+ * The implementation does not assume any bit in @mask is set (including @start).
+ *
+ * After the loop, cpu is >= nr_cpu_ids.
+ */
+#define for_each_cpu_wrap(cpu, mask, start)					\
+	for ((cpu) = cpumask_next_wrap((start)-1, (mask), (start), false);	\
+	     (cpu) < nr_cpumask_bits;						\
+	     (cpu) = cpumask_next_wrap((cpu), (mask), (start), true))
+
 /**
  * for_each_cpu_and - iterate over every cpu in both masks
  * @cpu: the (optionally unsigned) integer iterator
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 1731c3a..95fe239 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -65,6 +65,7 @@
 #define DIAG_IOCTL_PERIPHERAL_BUF_DRAIN		36
 #define DIAG_IOCTL_REGISTER_CALLBACK	37
 #define DIAG_IOCTL_HDLC_TOGGLE	38
+#define DIAG_IOCTL_QUERY_PD_LOGGING	39
 
 /* PC Tools IDs */
 #define APQ8060_TOOLS_ID	4062
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
new file mode 100644
index 0000000..20f5cba
--- /dev/null
+++ b/include/linux/hdcp_qseecom.h
@@ -0,0 +1,224 @@
+/* Copyright (c) 2015-2017, 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 __HDCP_QSEECOM_H
+#define __HDCP_QSEECOM_H
+#include <linux/types.h>
+
+#define HDCP_MAX_MESSAGE_PARTS 4
+
+/**
+ * enum hdcp_lib_wakeup_cmd - commands for interacting with HDCP driver
+ * @HDCP_LIB_WKUP_CMD_INVALID:           initialization value
+ * @HDCP_LIB_WKUP_CMD_START:             start authentication
+ * @HDCP_LIB_WKUP_CMD_STOP:              stop authentication
+ * @HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:  sending message to sink succeeded
+ * @HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:   sending message to sink failed
+ * @HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:  receiving message from sink succeeded
+ * @HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:   receiving message from sink failed
+ * @HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:  receiving message from sink timed out
+ * @HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE: start content stream processing
+ * @HDCP_LIB_WKUP_CMD_LINK_FAILED:       link failure notification
+ */
+enum hdcp_lib_wakeup_cmd {
+	HDCP_LIB_WKUP_CMD_INVALID,
+	HDCP_LIB_WKUP_CMD_START,
+	HDCP_LIB_WKUP_CMD_STOP,
+	HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS,
+	HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED,
+	HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS,
+	HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED,
+	HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT,
+	HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE,
+	HDCP_LIB_WKUP_CMD_LINK_FAILED,
+};
+
+/**
+ * enum hdcp_wakeup_cmd - commands for interacting with display transport layer
+ * @HDCP_WKUP_CMD_INVALID:        initialization value
+ * @HDCP_WKUP_CMD_SEND_MESSAGE:   send message to sink
+ * @HDCP_WKUP_CMD_RECV_MESSAGE:   receive message from sink
+ * @HDCP_WKUP_CMD_STATUS_SUCCESS: successfully communicated with TrustZone
+ * @HDCP_WKUP_CMD_STATUS_FAILED:  failed to communicate with TrustZone
+ * @HDCP_WKUP_CMD_LINK_POLL:      poll the HDCP link
+ * @HDCP_WKUP_CMD_AUTHENTICATE:   start authentication
+ */
+enum hdcp_wakeup_cmd {
+	HDCP_WKUP_CMD_INVALID,
+	HDCP_WKUP_CMD_SEND_MESSAGE,
+	HDCP_WKUP_CMD_RECV_MESSAGE,
+	HDCP_WKUP_CMD_STATUS_SUCCESS,
+	HDCP_WKUP_CMD_STATUS_FAILED,
+	HDCP_WKUP_CMD_LINK_POLL,
+	HDCP_WKUP_CMD_AUTHENTICATE
+};
+
+/**
+ * struct hdcp_lib_wakeup_data - command and data send to HDCP driver
+ * @cmd:                 command type
+ * @context:             void pointer to the HDCP driver instance
+ * @recvd_msg_buf:       message received from the sink
+ * @recvd_msg_len:       length of message received from the sink
+ * @timeout:             time out value for timed transactions
+ */
+struct hdcp_lib_wakeup_data {
+	enum hdcp_lib_wakeup_cmd cmd;
+	void *context;
+	char *recvd_msg_buf;
+	uint32_t recvd_msg_len;
+	uint32_t timeout;
+};
+
+/**
+ * struct hdcp_msg_part - a single part of an HDCP 2.2 message
+ * @name:       user readable message name
+ * @offset:     message part offset
+ * @length      message part length
+ */
+struct hdcp_msg_part {
+	char *name;
+	uint32_t offset;
+	uint32_t length;
+};
+
+/**
+ * struct hdcp_msg_data - a full HDCP 2.2 message containing one or more parts
+ * @num_messages:   total number of parts in a full message
+ * @messages:       array containing num_messages parts
+ * @rx_status:      value of rx_status register
+ */
+struct hdcp_msg_data {
+	uint32_t num_messages;
+	struct hdcp_msg_part messages[HDCP_MAX_MESSAGE_PARTS];
+	uint8_t rx_status;
+};
+
+/**
+ * struct hdcp_wakeup_data - command and data sent to display transport layer
+ * @cmd:            command type
+ * @context:        void pointer to the display transport layer
+ * @send_msg_buf:   buffer containing message to be sent to sink
+ * @send_msg_len:   length of the message to be sent to sink
+ * @timeout:        timeout value for timed transactions
+ * @abort_mask:     mask used to determine whether HDCP link is valid
+ * @message_data:   a pointer to the message description
+ */
+struct hdcp_wakeup_data {
+	enum hdcp_wakeup_cmd cmd;
+	void *context;
+	char *send_msg_buf;
+	uint32_t send_msg_len;
+	uint32_t timeout;
+	uint8_t abort_mask;
+	const struct hdcp_msg_data *message_data;
+};
+
+static inline char *hdcp_cmd_to_str(uint32_t cmd)
+{
+	switch (cmd) {
+	case HDCP_WKUP_CMD_SEND_MESSAGE:
+		return "HDCP_WKUP_CMD_SEND_MESSAGE";
+	case HDCP_WKUP_CMD_RECV_MESSAGE:
+		return "HDCP_WKUP_CMD_RECV_MESSAGE";
+	case HDCP_WKUP_CMD_STATUS_SUCCESS:
+		return "HDCP_WKUP_CMD_STATUS_SUCCESS";
+	case HDCP_WKUP_CMD_STATUS_FAILED:
+		return "HDCP_WKUP_CMD_STATUS_FAIL";
+	case HDCP_WKUP_CMD_LINK_POLL:
+		return "HDCP_WKUP_CMD_LINK_POLL";
+	case HDCP_WKUP_CMD_AUTHENTICATE:
+		return "HDCP_WKUP_CMD_AUTHENTICATE";
+	default:
+		return "???";
+	}
+}
+
+static inline char *hdcp_lib_cmd_to_str(uint32_t cmd)
+{
+	switch (cmd) {
+	case HDCP_LIB_WKUP_CMD_START:
+		return "HDCP_LIB_WKUP_CMD_START";
+	case HDCP_LIB_WKUP_CMD_STOP:
+		return "HDCP_LIB_WKUP_CMD_STOP";
+	case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:
+		return "HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS";
+	case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
+		return "HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED";
+	case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
+		return "HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS";
+	case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
+		return "HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED";
+	case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
+		return "HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT";
+	case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
+		return "HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE";
+	case HDCP_LIB_WKUP_CMD_LINK_FAILED:
+		return "HDCP_LIB_WKUP_CMD_LINK_FAILED";
+	default:
+		return "???";
+	}
+}
+
+/**
+ * struct hdcp_txmtr_ops - interface to HDCP Driver
+ * @wakeup:                  wake the HDCP driver with a new command
+ * @feature_supported:       checks for HDCP support on the target device
+ */
+struct hdcp_txmtr_ops {
+	int (*wakeup)(struct hdcp_lib_wakeup_data *data);
+	bool (*feature_supported)(void *phdcpcontext);
+};
+
+/**
+ * struct hdcp_client_ops - call back functions to display transport layer
+ * @wakeup:            wake up display transport layer with a new command
+ * @notify_lvl_change  notify of encryption level changes
+ */
+struct hdcp_client_ops {
+	int (*wakeup)(struct hdcp_wakeup_data *data);
+	void (*notify_lvl_change)(void *client_ctx, int min_lvl);
+};
+
+/**
+ * enum hdcp_device_type - display interface types
+ * @HDCP_TXMTR_HDMI:  HDMI interface
+ * @HDCP_TXMTR_DP:  DisplayPort interface
+ */
+enum hdcp_device_type {
+	HDCP_TXMTR_HDMI = 0x8001,
+	HDCP_TXMTR_DP = 0x8002
+};
+
+/**
+ * struct hdcp_register_data - data used in HDCP driver clients' registration
+ * @client_ops:          call back functions from the client
+ * @txmtr_ops:           HDCP driver interface
+ * @device_type:         display interface type of the client
+ * @client_ctx:          void pointer to client data object
+ * @hdcp_ctx:            void pointer to HDCP driver reference for client use
+ */
+struct hdcp_register_data {
+	struct hdcp_client_ops *client_ops;
+	struct hdcp_txmtr_ops *txmtr_ops;
+	enum hdcp_device_type device_type;
+	void *client_ctx;
+	void **hdcp_ctx;
+};
+
+int hdcp_library_register(struct hdcp_register_data *data);
+void hdcp_library_deregister(void *phdcpcontext);
+bool hdcp1_check_if_supported_load_app(void);
+int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb);
+int hdcp1_set_enc(bool enable);
+void hdcp1_cache_repeater_topology(void *hdcp1_cached_tp);
+void hdcp1_notify_topology(void);
+#endif /* __HDCP_QSEECOM_H */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a80516f..aa2b4e4 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1576,6 +1576,9 @@
 #define WLAN_AUTH_SHARED_KEY 1
 #define WLAN_AUTH_FT 2
 #define WLAN_AUTH_SAE 3
+#define WLAN_AUTH_FILS_SK 4
+#define WLAN_AUTH_FILS_SK_PFS 5
+#define WLAN_AUTH_FILS_PK 6
 #define WLAN_AUTH_LEAP 128
 
 #define WLAN_AUTH_CHALLENGE_LEN 128
@@ -1715,6 +1718,9 @@
 	WLAN_STATUS_REJECT_DSE_BAND = 96,
 	WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
 	WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
+	/* 802.11ai */
+	WLAN_STATUS_FILS_AUTHENTICATION_FAILURE = 108,
+	WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER = 109,
 };
 
 
@@ -2073,6 +2079,15 @@
 #define IEEE80211_GCMP_MIC_LEN		16
 #define IEEE80211_GCMP_PN_LEN		6
 
+#define FILS_NONCE_LEN			16
+#define FILS_MAX_KEK_LEN		64
+
+#define FILS_ERP_MAX_USERNAME_LEN	16
+#define FILS_ERP_MAX_REALM_LEN		253
+#define FILS_ERP_MAX_RRK_LEN		64
+
+#define PMK_MAX_LEN			48
+
 /* Public action codes */
 enum ieee80211_pub_actioncode {
 	WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
@@ -2296,31 +2311,37 @@
 };
 
 
-/* cipher suite selectors */
-#define WLAN_CIPHER_SUITE_USE_GROUP	0x000FAC00
-#define WLAN_CIPHER_SUITE_WEP40		0x000FAC01
-#define WLAN_CIPHER_SUITE_TKIP		0x000FAC02
-/* reserved: 				0x000FAC03 */
-#define WLAN_CIPHER_SUITE_CCMP		0x000FAC04
-#define WLAN_CIPHER_SUITE_WEP104	0x000FAC05
-#define WLAN_CIPHER_SUITE_AES_CMAC	0x000FAC06
-#define WLAN_CIPHER_SUITE_GCMP		0x000FAC08
-#define WLAN_CIPHER_SUITE_GCMP_256	0x000FAC09
-#define WLAN_CIPHER_SUITE_CCMP_256	0x000FAC0A
-#define WLAN_CIPHER_SUITE_BIP_GMAC_128	0x000FAC0B
-#define WLAN_CIPHER_SUITE_BIP_GMAC_256	0x000FAC0C
-#define WLAN_CIPHER_SUITE_BIP_CMAC_256	0x000FAC0D
+#define SUITE(oui, id)	(((oui) << 8) | (id))
 
-#define WLAN_CIPHER_SUITE_SMS4		0x00147201
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP	SUITE(0x000FAC, 0)
+#define WLAN_CIPHER_SUITE_WEP40		SUITE(0x000FAC, 1)
+#define WLAN_CIPHER_SUITE_TKIP		SUITE(0x000FAC, 2)
+/* reserved:				SUITE(0x000FAC, 3) */
+#define WLAN_CIPHER_SUITE_CCMP		SUITE(0x000FAC, 4)
+#define WLAN_CIPHER_SUITE_WEP104	SUITE(0x000FAC, 5)
+#define WLAN_CIPHER_SUITE_AES_CMAC	SUITE(0x000FAC, 6)
+#define WLAN_CIPHER_SUITE_GCMP		SUITE(0x000FAC, 8)
+#define WLAN_CIPHER_SUITE_GCMP_256	SUITE(0x000FAC, 9)
+#define WLAN_CIPHER_SUITE_CCMP_256	SUITE(0x000FAC, 10)
+#define WLAN_CIPHER_SUITE_BIP_GMAC_128	SUITE(0x000FAC, 11)
+#define WLAN_CIPHER_SUITE_BIP_GMAC_256	SUITE(0x000FAC, 12)
+#define WLAN_CIPHER_SUITE_BIP_CMAC_256	SUITE(0x000FAC, 13)
+
+#define WLAN_CIPHER_SUITE_SMS4		SUITE(0x001472, 1)
 
 /* AKM suite selectors */
-#define WLAN_AKM_SUITE_8021X		0x000FAC01
-#define WLAN_AKM_SUITE_PSK		0x000FAC02
-#define WLAN_AKM_SUITE_8021X_SHA256	0x000FAC05
-#define WLAN_AKM_SUITE_PSK_SHA256	0x000FAC06
-#define WLAN_AKM_SUITE_TDLS		0x000FAC07
-#define WLAN_AKM_SUITE_SAE		0x000FAC08
-#define WLAN_AKM_SUITE_FT_OVER_SAE	0x000FAC09
+#define WLAN_AKM_SUITE_8021X		SUITE(0x000FAC, 1)
+#define WLAN_AKM_SUITE_PSK		SUITE(0x000FAC, 2)
+#define WLAN_AKM_SUITE_8021X_SHA256	SUITE(0x000FAC, 5)
+#define WLAN_AKM_SUITE_PSK_SHA256	SUITE(0x000FAC, 6)
+#define WLAN_AKM_SUITE_TDLS		SUITE(0x000FAC, 7)
+#define WLAN_AKM_SUITE_SAE		SUITE(0x000FAC, 8)
+#define WLAN_AKM_SUITE_FT_OVER_SAE	SUITE(0x000FAC, 9)
+#define WLAN_AKM_SUITE_FILS_SHA256	SUITE(0x000FAC, 14)
+#define WLAN_AKM_SUITE_FILS_SHA384	SUITE(0x000FAC, 15)
+#define WLAN_AKM_SUITE_FT_FILS_SHA256	SUITE(0x000FAC, 16)
+#define WLAN_AKM_SUITE_FT_FILS_SHA384	SUITE(0x000FAC, 17)
 
 #define WLAN_MAX_KEY_LEN		32
 
diff --git a/include/linux/ipa_odu_bridge.h b/include/linux/ipa_odu_bridge.h
index 5d30a97..e7f75b7 100644
--- a/include/linux/ipa_odu_bridge.h
+++ b/include/linux/ipa_odu_bridge.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,7 +39,85 @@
 	u32 ipa_desc_size;
 };
 
-#if defined CONFIG_IPA || defined CONFIG_IPA3
+/**
+ * struct ipa_bridge_init_params - parameters for IPA bridge initialization API
+ *
+ * @info: structure contains initialization information
+ * @wakeup_request: callback to client to indicate there is downlink data
+ *	available. Client is expected to call ipa_bridge_resume() to start
+ *	receiving data
+ */
+struct ipa_bridge_init_params {
+	struct odu_bridge_params info;
+	void (*wakeup_request)(void *);
+};
+
+#ifdef CONFIG_IPA3
+
+int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl);
+
+int ipa_bridge_connect(u32 hdl);
+
+int ipa_bridge_set_perf_profile(u32 hdl, u32 bandwidth);
+
+int ipa_bridge_disconnect(u32 hdl);
+
+int ipa_bridge_suspend(u32 hdl);
+
+int ipa_bridge_resume(u32 hdl);
+
+int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb,
+	struct ipa_tx_meta *metadata);
+
+int ipa_bridge_cleanup(u32 hdl);
+
+#else
+
+static inline int ipa_bridge_init(struct odu_bridge_params *params, u32 *hdl)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_connect(u32 hdl)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_set_perf_profile(u32 hdl, u32 bandwidth)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_disconnect(u32 hdl)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_suspend(u32 hdl)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_resume(u32 hdl)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb,
+struct ipa_tx_meta *metadata)
+{
+	return -EPERM;
+}
+
+static inline int ipa_bridge_cleanup(u32 hdl)
+{
+	return -EPERM;
+}
+
+#endif /* CONFIG_IPA3 */
+
+/* Below API is deprecated. Please use the API above */
+# if defined CONFIG_IPA || defined CONFIG_IPA3
 
 int odu_bridge_init(struct odu_bridge_params *params);
 
diff --git a/include/linux/ipc_router.h b/include/linux/ipc_router.h
index 767551e..c18290f 100644
--- a/include/linux/ipc_router.h
+++ b/include/linux/ipc_router.h
@@ -144,6 +144,7 @@
 	uint32_t num_rx;
 	unsigned long num_tx_bytes;
 	unsigned long num_rx_bytes;
+	uint32_t last_served_svc_id;
 	void *priv;
 };
 
diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h
index 2a663c6..b01d294 100644
--- a/include/linux/libfdt_env.h
+++ b/include/linux/libfdt_env.h
@@ -1,6 +1,7 @@
 #ifndef _LIBFDT_ENV_H
 #define _LIBFDT_ENV_H
 
+#include <linux/kernel.h>
 #include <linux/string.h>
 
 #include <asm/byteorder.h>
diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h
index cb0ba9f..fa7fd03 100644
--- a/include/linux/list_lru.h
+++ b/include/linux/list_lru.h
@@ -44,6 +44,7 @@
 	/* for cgroup aware lrus points to per cgroup lists, otherwise NULL */
 	struct list_lru_memcg	*memcg_lrus;
 #endif
+	long nr_items;
 } ____cacheline_aligned_in_smp;
 
 struct list_lru {
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 558adfa..8f5af30 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1921,6 +1921,13 @@
 }
 #endif /* CONFIG_SECURITY_SELINUX_DISABLE */
 
+/* Currently required to handle SELinux runtime hook disable. */
+#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
+#define __lsm_ro_after_init
+#else
+#define __lsm_ro_after_init	__ro_after_init
+#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
+
 extern int __init security_module_enable(const char *module);
 extern void __init capability_add_hooks(void);
 #ifdef CONFIG_SECURITY_YAMA
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index f188e85..cfe4724 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -179,6 +179,8 @@
 	int irq_base;
 	int num_irqs;
 	int reset_gpio;
+	bool has_buck_vsel_gpio;
+	struct device_node *buck_vsel_ctl_np;
 	struct device_node *wcd_rst_np;
 	struct wcd9xxx_amic amic_settings;
 	struct slim_device slimbus_slave_device;
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index e1a903a..6a620e0 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -788,6 +788,7 @@
 void mlx5_start_health_poll(struct mlx5_core_dev *dev);
 void mlx5_stop_health_poll(struct mlx5_core_dev *dev);
 void mlx5_drain_health_wq(struct mlx5_core_dev *dev);
+void mlx5_drain_health_recovery(struct mlx5_core_dev *dev);
 int mlx5_buf_alloc_node(struct mlx5_core_dev *dev, int size,
 			struct mlx5_buf *buf, int node);
 int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, struct mlx5_buf *buf);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2b423f7..9b21e2a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -76,6 +76,10 @@
 #define page_to_virt(x)	__va(PFN_PHYS(page_to_pfn(x)))
 #endif
 
+#ifndef lm_alias
+#define lm_alias(x)	__va(__pa_symbol(x))
+#endif
+
 /*
  * To prevent common memory management code establishing
  * a zero page mapping on a read fault.
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 2938206..aa4c1ed 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -82,7 +82,7 @@
 #define GENI_SER_M_CLK_CFG		(0x48)
 #define GENI_SER_S_CLK_CFG		(0x4C)
 #define GENI_CLK_CTRL_RO		(0x60)
-#define GENI_IF_DISABLE_RO		(0x64)
+#define GENI_IF_FIFO_DISABLE_RO		(0x64)
 #define GENI_FW_REVISION_RO		(0x68)
 #define GENI_FW_S_REVISION_RO		(0x6C)
 #define SE_GENI_CLK_SEL			(0x7C)
@@ -147,7 +147,8 @@
 
 /* CLK_CTRL_RO fields */
 
-/* IF_DISABLE_RO fields */
+/* FIFO_IF_DISABLE_RO fields */
+#define FIFO_IF_DISABLE			(BIT(0))
 
 /* FW_REVISION_RO fields */
 #define FW_REV_PROTOCOL_MSK	(GENMASK(15, 8))
@@ -330,6 +331,12 @@
 #define DEFAULT_BUS_WIDTH	(4)
 #define DEFAULT_SE_CLK		(19200000)
 
+/* GSI TRE fields */
+/* Packing fields */
+#define GSI_TX_PACK_EN          (BIT(0))
+#define GSI_RX_PACK_EN          (BIT(1))
+#define GSI_PRESERVE_PACK       (BIT(2))
+
 #define GENI_SE_ERR(log_ctx, print, dev, x...) do { \
 if (log_ctx) \
 	ipc_log_string(log_ctx, x); \
diff --git a/include/linux/qcom_tspp.h b/include/linux/qcom_tspp.h
index 1b34c38..7a9e569 100644
--- a/include/linux/qcom_tspp.h
+++ b/include/linux/qcom_tspp.h
@@ -16,6 +16,7 @@
 struct tspp_data_descriptor {
 	void *virt_base;   /* logical address of the actual data */
 	phys_addr_t phys_base; /* physical address of the actual data */
+	dma_addr_t dma_base; /* DMA address of the actual data */
 	u32 size;          /* size of buffer in bytes */
 	int id;            /* unique identifier */
 	void *user;        /* user-defined data */
@@ -75,9 +76,17 @@
 	TSIF_TTS_LPASS_TIMER	/* Time stamps from AV/Qtimer Timer  */
 };
 
+struct tspp_ion_dma_buf_info {
+	struct dma_buf *dbuf;
+	struct dma_buf_attachment *attach;
+	struct sg_table *table;
+	bool smmu_map;
+	dma_addr_t dma_map_base;
+};
+
 typedef void (tspp_notifier)(int channel_id, void *user);
 typedef void* (tspp_allocator)(int channel_id, u32 size,
-	phys_addr_t *phys_base, void *user);
+	      phys_addr_t *phys_base, dma_addr_t *dma_base, void *user);
 typedef void (tspp_memfree)(int channel_id, u32 size,
 	void *virt_base, phys_addr_t phys_base, void *user);
 
@@ -105,4 +114,9 @@
 int tspp_get_lpass_time_counter(u32 dev, enum tspp_source source,
 			u64 *lpass_time_counter);
 
+int tspp_attach_ion_dma_buff(u32 dev,
+	struct tspp_ion_dma_buf_info *ion_dma_buf);
+
+int tspp_detach_ion_dma_buff(u32 dev,
+	struct tspp_ion_dma_buf_info *ion_dma_buf);
 #endif /* _MSM_TSPP_H_ */
diff --git a/include/linux/random.h b/include/linux/random.h
index 16ab429..1fa0dc8 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -42,8 +42,42 @@
 extern const struct file_operations random_fops, urandom_fops;
 #endif
 
-unsigned int get_random_int(void);
-unsigned long get_random_long(void);
+u32 get_random_u32(void);
+u64 get_random_u64(void);
+static inline unsigned int get_random_int(void)
+{
+	return get_random_u32();
+}
+static inline unsigned long get_random_long(void)
+{
+#if BITS_PER_LONG == 64
+	return get_random_u64();
+#else
+	return get_random_u32();
+#endif
+}
+
+/*
+ * On 64-bit architectures, protect against non-terminated C string overflows
+ * by zeroing out the first byte of the canary; this leaves 56 bits of entropy.
+ */
+#ifdef CONFIG_64BIT
+# ifdef __LITTLE_ENDIAN
+#  define CANARY_MASK 0xffffffffffffff00UL
+# else /* big endian, 64 bits: */
+#  define CANARY_MASK 0x00ffffffffffffffUL
+# endif
+#else /* 32 bits: */
+# define CANARY_MASK 0xffffffffUL
+#endif
+
+static inline unsigned long get_random_canary(void)
+{
+	unsigned long val = get_random_long();
+
+	return val & CANARY_MASK;
+}
+
 unsigned long randomize_page(unsigned long start, unsigned long range);
 
 u32 prandom_u32(void);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 7627c76..0737cb6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -183,6 +183,7 @@
 				     unsigned int *max_nr,
 				     unsigned int *big_max_nr);
 extern unsigned int sched_get_cpu_util(int cpu);
+extern u64 sched_get_cpu_last_busy_time(int cpu);
 #else
 static inline void sched_update_nr_prod(int cpu, long delta, bool inc)
 {
@@ -196,6 +197,10 @@
 {
 	return 0;
 }
+static inline u64 sched_get_cpu_last_busy_time(int cpu)
+{
+	return 0;
+}
 #endif
 
 extern void calc_global_load(unsigned long ticks);
@@ -3882,6 +3887,7 @@
 #define SCHED_CPUFREQ_IOWAIT	(1U << 2)
 #define SCHED_CPUFREQ_INTERCLUSTER_MIG (1U << 3)
 #define SCHED_CPUFREQ_WALT (1U << 4)
+#define SCHED_CPUFREQ_PL	(1U << 5)
 
 #define SCHED_CPUFREQ_RT_DL	(SCHED_CPUFREQ_RT | SCHED_CPUFREQ_DL)
 
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index 322bc23..3597d55 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -24,13 +24,9 @@
 extern unsigned int sysctl_sched_cstate_aware;
 extern unsigned int sysctl_sched_capacity_margin;
 extern unsigned int sysctl_sched_capacity_margin_down;
-#ifdef CONFIG_SCHED_WALT
-extern unsigned int sysctl_sched_use_walt_cpu_util;
-extern unsigned int sysctl_sched_use_walt_task_util;
-extern unsigned int sysctl_sched_init_task_load_pct;
-#endif
 
 #ifdef CONFIG_SCHED_WALT
+extern unsigned int sysctl_sched_init_task_load_pct;
 extern unsigned int sysctl_sched_cpu_high_irqload;
 extern unsigned int sysctl_sched_use_walt_cpu_util;
 extern unsigned int sysctl_sched_use_walt_task_util;
@@ -72,9 +68,6 @@
 extern int sched_migrate_notify_proc_handler(struct ctl_table *table,
 		int write, void __user *buffer, size_t *lenp, loff_t *ppos);
 
-extern int sched_hmp_proc_update_handler(struct ctl_table *table,
-		int write, void __user *buffer, size_t *lenp, loff_t *ppos);
-
 extern int sched_boost_handler(struct ctl_table *table, int write,
 			void __user *buffer, size_t *lenp, loff_t *ppos);
 
diff --git a/include/linux/sde_rsc.h b/include/linux/sde_rsc.h
index 0320210..19e76db 100644
--- a/include/linux/sde_rsc.h
+++ b/include/linux/sde_rsc.h
@@ -21,6 +21,9 @@
 
 #define MAX_RSC_CLIENT_NAME_LEN 128
 
+/* DRM Object IDs are numbered excluding 0, use 0 to indicate invalid CRTC */
+#define SDE_RSC_INVALID_CRTC_ID 0
+
 /**
  * event will be triggered before sde core power collapse,
  * mdss gdsc is still on
@@ -169,12 +172,29 @@
  * @config:	 fps, vtotal, porches, etc configuration for command mode
  *               panel
  * @crtc_id:	 current client's crtc id
+ * @wait_vblank_crtc_id:	Output parameter. If set to non-zero, rsc hw
+ *				state update requires a wait for one vblank on
+ *				the primary crtc. In that case, this output
+ *				param will be set to the crtc on which to wait.
+ *				If SDE_RSC_INVALID_CRTC_ID, no wait necessary
  *
  * Return: error code.
  */
 int sde_rsc_client_state_update(struct sde_rsc_client *client,
 	enum sde_rsc_state state,
-	struct sde_rsc_cmd_config *config, int crtc_id);
+	struct sde_rsc_cmd_config *config, int crtc_id,
+	int *wait_vblank_crtc_id);
+
+/**
+ * sde_rsc_client_is_state_update_complete() - check if state update is complete
+ * RSC state transition is not complete until HW receives VBLANK signal. This
+ * function checks RSC HW to determine whether that signal has been received.
+ * @client:	 Client pointer provided by sde_rsc_client_create().
+ *
+ * Return: true if the state update has completed.
+ */
+bool sde_rsc_client_is_state_update_complete(
+		struct sde_rsc_client *caller_client);
 
 /**
  * sde_rsc_client_vote() - ab/ib vote from rsc client
@@ -244,6 +264,12 @@
 	return 0;
 }
 
+static inline bool sde_rsc_client_is_state_update_complete(
+		struct sde_rsc_client *caller_client)
+{
+	return false;
+}
+
 static inline int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
 	u32 bus_id, u64 ab_vote, u64 ib_vote)
 {
diff --git a/include/linux/seemp_instrumentation.h b/include/linux/seemp_instrumentation.h
index ff09bd2..1db7a44 100644
--- a/include/linux/seemp_instrumentation.h
+++ b/include/linux/seemp_instrumentation.h
@@ -69,7 +69,7 @@
 	seemp_logk_kernel_end(blck);
 }
 
-static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
+static inline void seemp_logk_rtic(__u8 type, pid_t pid, __u8 asset_id[0x20],
 		__u8 asset_category, __u8 response)
 {
 	char *buf = NULL;
@@ -80,8 +80,8 @@
 		return;
 
 	SEEMP_LOGK_RECORD(SEEMP_API_kernel__rtic,
-		"app_pid=%llu,rtic_type=%u,asset_id=%s,asset_category=%u,response=%u",
-		actor, type, asset_id, asset_category, response);
+		"app_pid=%d,rtic_type=%u,asset_id=%s,asset_category=%u,response=%u",
+		pid, type, asset_id, asset_category, response);
 
 	seemp_logk_kernel_end(blck);
 }
diff --git a/include/linux/string.h b/include/linux/string.h
index 26b6f6a..4e510df 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -169,4 +169,204 @@
 	return tail ? tail + 1 : path;
 }
 
+#define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))
+#define __RENAME(x) __asm__(#x)
+
+void fortify_panic(const char *name) __noreturn __cold;
+void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
+void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
+void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
+
+#if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
+__FORTIFY_INLINE char *strcpy(char *p, const char *q)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (p_size == (size_t)-1 && q_size == (size_t)-1)
+		return __builtin_strcpy(p, q);
+	if (strscpy(p, q, p_size < q_size ? p_size : q_size) < 0)
+		fortify_panic(__func__);
+	return p;
+}
+
+__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (__builtin_constant_p(size) && p_size < size)
+		__write_overflow();
+	if (p_size < size)
+		fortify_panic(__func__);
+	return __builtin_strncpy(p, q, size);
+}
+
+__FORTIFY_INLINE char *strcat(char *p, const char *q)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (p_size == (size_t)-1)
+		return __builtin_strcat(p, q);
+	if (strlcat(p, q, p_size) >= p_size)
+		fortify_panic(__func__);
+	return p;
+}
+
+__FORTIFY_INLINE __kernel_size_t strlen(const char *p)
+{
+	__kernel_size_t ret;
+	size_t p_size = __builtin_object_size(p, 0);
+	if (p_size == (size_t)-1)
+		return __builtin_strlen(p);
+	ret = strnlen(p, p_size);
+	if (p_size <= ret)
+		fortify_panic(__func__);
+	return ret;
+}
+
+extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
+__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	__kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
+	if (p_size <= ret && maxlen != ret)
+		fortify_panic(__func__);
+	return ret;
+}
+
+/* defined after fortified strlen to reuse it */
+extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
+__FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
+{
+	size_t ret;
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (p_size == (size_t)-1 && q_size == (size_t)-1)
+		return __real_strlcpy(p, q, size);
+	ret = strlen(q);
+	if (size) {
+		size_t len = (ret >= size) ? size - 1 : ret;
+		if (__builtin_constant_p(len) && len >= p_size)
+			__write_overflow();
+		if (len >= p_size)
+			fortify_panic(__func__);
+		__builtin_memcpy(p, q, len);
+		p[len] = '\0';
+	}
+	return ret;
+}
+
+/* defined after fortified strlen and strnlen to reuse them */
+__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
+{
+	size_t p_len, copy_len;
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (p_size == (size_t)-1 && q_size == (size_t)-1)
+		return __builtin_strncat(p, q, count);
+	p_len = strlen(p);
+	copy_len = strnlen(q, count);
+	if (p_size < p_len + copy_len + 1)
+		fortify_panic(__func__);
+	__builtin_memcpy(p + p_len, q, copy_len);
+	p[p_len + copy_len] = '\0';
+	return p;
+}
+
+__FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (__builtin_constant_p(size) && p_size < size)
+		__write_overflow();
+	if (p_size < size)
+		fortify_panic(__func__);
+	return __builtin_memset(p, c, size);
+}
+
+__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (__builtin_constant_p(size)) {
+		if (p_size < size)
+			__write_overflow();
+		if (q_size < size)
+			__read_overflow2();
+	}
+	if (p_size < size || q_size < size)
+		fortify_panic(__func__);
+	return __builtin_memcpy(p, q, size);
+}
+
+__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (__builtin_constant_p(size)) {
+		if (p_size < size)
+			__write_overflow();
+		if (q_size < size)
+			__read_overflow2();
+	}
+	if (p_size < size || q_size < size)
+		fortify_panic(__func__);
+	return __builtin_memmove(p, q, size);
+}
+
+extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
+__FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (__builtin_constant_p(size) && p_size < size)
+		__read_overflow();
+	if (p_size < size)
+		fortify_panic(__func__);
+	return __real_memscan(p, c, size);
+}
+
+__FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (__builtin_constant_p(size)) {
+		if (p_size < size)
+			__read_overflow();
+		if (q_size < size)
+			__read_overflow2();
+	}
+	if (p_size < size || q_size < size)
+		fortify_panic(__func__);
+	return __builtin_memcmp(p, q, size);
+}
+
+__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (__builtin_constant_p(size) && p_size < size)
+		__read_overflow();
+	if (p_size < size)
+		fortify_panic(__func__);
+	return __builtin_memchr(p, c, size);
+}
+
+void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
+__FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (__builtin_constant_p(size) && p_size < size)
+		__read_overflow();
+	if (p_size < size)
+		fortify_panic(__func__);
+	return __real_memchr_inv(p, c, size);
+}
+
+extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup);
+__FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	if (__builtin_constant_p(size) && p_size < size)
+		__read_overflow();
+	if (p_size < size)
+		fortify_panic(__func__);
+	return __real_kmemdup(p, size, gfp);
+}
+#endif
+
 #endif /* _LINUX_STRING_H_ */
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index 387fa7d..d802692 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -42,6 +42,7 @@
  * are available -- else NULL's).
  */
 
+bool sysrq_on(void);
 void handle_sysrq(int key);
 void __handle_sysrq(int key, bool check_mask);
 int register_sysrq_key(int key, struct sysrq_key_op *op);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 1f39661..0f9fff3 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -333,6 +333,8 @@
 	struct usb_ssp_cap_descriptor	*ssp_cap;
 	struct usb_ss_container_id_descriptor	*ss_id;
 	struct usb_ptm_cap_descriptor	*ptm_cap;
+	struct usb_config_summary_descriptor	*config_summary;
+	unsigned int	num_config_summary_desc;
 };
 
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
diff --git a/include/linux/usb/audio-v3.h b/include/linux/usb/audio-v3.h
index f2322f3..b6cc17b 100644
--- a/include/linux/usb/audio-v3.h
+++ b/include/linux/usb/audio-v3.h
@@ -50,7 +50,8 @@
 #define CLUSTER_ID_MONO		0x0001
 #define CLUSTER_ID_STEREO	0x0002
 
-#define FULL_ADC_PROFILE	0x01
+/* A.2 audio function subclass codes */
+#define FULL_ADC_3_0		0x01
 
 /* BADD Profile IDs */
 #define PROF_GENERIC_IO		0x20
diff --git a/include/linux/usb/usbpd.h b/include/linux/usb/usbpd.h
index 3566a7a..4dbd91f 100644
--- a/include/linux/usb/usbpd.h
+++ b/include/linux/usb/usbpd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -46,6 +46,10 @@
 	void (*connect)(struct usbpd_svid_handler *hdlr);
 	void (*disconnect)(struct usbpd_svid_handler *hdlr);
 
+	/* DP driver -> PE driver for requesting USB SS lanes */
+	int (*request_usb_ss_lane)(struct usbpd *pd,
+			struct usbpd_svid_handler *hdlr);
+
 	/* Unstructured VDM */
 	void (*vdm_received)(struct usbpd_svid_handler *hdlr, u32 vdm_hdr,
 			const u32 *vdos, int num_vdos);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 0ecae0b..ed46675 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -88,6 +88,8 @@
  */
 extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
 extern void vfio_group_put_external_user(struct vfio_group *group);
+extern bool vfio_external_group_match_file(struct vfio_group *group,
+					   struct file *filep);
 extern int vfio_external_user_iommu_id(struct vfio_group *group);
 extern long vfio_external_check_extension(struct vfio_group *group,
 					  unsigned long arg);
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 826eef8..f113e0e 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -84,6 +84,7 @@
 			const void *caller);
 
 extern void vfree(const void *addr);
+extern void vfree_atomic(const void *addr);
 
 extern void *vmap(struct page **pages, unsigned int count,
 			unsigned long flags, pgprot_t prot);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 45dbffb..82b4b53 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -24,6 +24,30 @@
 #include <linux/net.h>
 #include <net/regulatory.h>
 
+/* backport support for new cfg80211 ops "update_connect_params" */
+#define CFG80211_UPDATE_CONNECT_PARAMS 1
+
+/**
+ *  backport support for NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA
+ *  and NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED.
+ */
+#define CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME 1
+
+/* backport support for NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI */
+#define CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN 1
+
+/* backport support for specifying reason for connect timeout */
+#define CFG80211_CONNECT_TIMEOUT_REASON_CODE 1
+
+/* Indicate backport support for the new connect done api */
+#define CFG80211_CONNECT_DONE 1
+
+/* Indicate backport support for FILS SK offload in cfg80211 */
+#define CFG80211_FILS_SK_OFFLOAD_SUPPORT 1
+
+/* Indicate support for including KEK length in rekey data */
+#define CFG80211_REKEY_DATA_KEK_LEN 1
+
 /**
  * DOC: Introduction
  *
@@ -784,19 +808,15 @@
  * @iftype_num: array with the number of interfaces of each interface
  *	type.  The index is the interface type as specified in &enum
  *	nl80211_iftype.
- * @beacon_int_gcd: a value specifying GCD of all beaconing interfaces,
- *	the GCD of a single value is considered the value itself, so for
- *	a single interface this should be set to that interface's beacon
- *	interval
- * @beacon_int_different: a flag indicating whether or not all beacon
- *	intervals (of beaconing interfaces) are different or not.
+ * @new_beacon_int: set this to the beacon interval of a new interface
+ *	that's not operating yet, if such is to be checked as part of
+ *	the verification
  */
 struct iface_combination_params {
 	int num_different_channels;
 	u8 radar_detect;
 	int iftype_num[NUM_NL80211_IFTYPES];
-	u32 beacon_int_gcd;
-	bool beacon_int_different;
+	u32 new_beacon_int;
 };
 
 /**
@@ -1596,6 +1616,17 @@
 };
 
 /**
+ * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment.
+ *
+ * @band: band of BSS which should match for RSSI level adjustment.
+ * @delta: value of RSSI level adjustment.
+ */
+struct cfg80211_bss_select_adjust {
+	enum nl80211_band band;
+	s8 delta;
+};
+
+/**
  * struct cfg80211_sched_scan_request - scheduled scan request description
  *
  * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
@@ -1630,6 +1661,16 @@
  *	cycle.  The driver may ignore this parameter and start
  *	immediately (or at any other time), if this feature is not
  *	supported.
+ * @relative_rssi_set: Indicates whether @relative_rssi is set or not.
+ * @relative_rssi: Relative RSSI threshold in dB to restrict scan result
+ *	reporting in connected state to cases where a matching BSS is determined
+ *	to have better or slightly worse RSSI than the current connected BSS.
+ *	The relative RSSI threshold values are ignored in disconnected state.
+ * @rssi_adjust: delta dB of RSSI preference to be given to the BSSs that belong
+ *	to the specified band while deciding whether a better BSS is reported
+ *	using @relative_rssi. If delta is a negative number, the BSSs that
+ *	belong to the specified band will be penalized by delta dB in relative
+ *	comparisions.
  */
 struct cfg80211_sched_scan_request {
 	struct cfg80211_ssid *ssids;
@@ -1649,6 +1690,10 @@
 	u8 mac_addr[ETH_ALEN] __aligned(2);
 	u8 mac_addr_mask[ETH_ALEN] __aligned(2);
 
+	bool relative_rssi_set;
+	s8 relative_rssi;
+	struct cfg80211_bss_select_adjust rssi_adjust;
+
 	/* internal */
 	struct wiphy *wiphy;
 	struct net_device *dev;
@@ -1789,9 +1834,11 @@
  * @key_len: length of WEP key for shared key authentication
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
- * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
- *	Authentication transaction sequence number field.
- * @sae_data_len: Length of sae_data buffer in octets
+ * @auth_data: Fields and elements in Authentication frames. This contains
+ *	the authentication frame body (non-IE and IE data), excluding the
+ *	Authentication algorithm number, i.e., starting at the Authentication
+ *	transaction sequence number field.
+ * @auth_data_len: Length of auth_data buffer in octets
  */
 struct cfg80211_auth_request {
 	struct cfg80211_bss *bss;
@@ -1800,8 +1847,8 @@
 	enum nl80211_auth_type auth_type;
 	const u8 *key;
 	u8 key_len, key_idx;
-	const u8 *sae_data;
-	size_t sae_data_len;
+	const u8 *auth_data;
+	size_t auth_data_len;
 };
 
 /**
@@ -1842,6 +1889,12 @@
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
  * @vht_capa: VHT capability override
  * @vht_capa_mask: VHT capability mask indicating which fields to use
+ * @fils_kek: FILS KEK for protecting (Re)Association Request/Response frame or
+ *	%NULL if FILS is not used.
+ * @fils_kek_len: Length of fils_kek in octets
+ * @fils_nonces: FILS nonces (part of AAD) for protecting (Re)Association
+ *	Request/Response frame or %NULL if FILS is not used. This field starts
+ *	with 16 octets of STA Nonce followed by 16 octets of AP Nonce.
  */
 struct cfg80211_assoc_request {
 	struct cfg80211_bss *bss;
@@ -1853,6 +1906,9 @@
 	struct ieee80211_ht_cap ht_capa;
 	struct ieee80211_ht_cap ht_capa_mask;
 	struct ieee80211_vht_cap vht_capa, vht_capa_mask;
+	const u8 *fils_kek;
+	size_t fils_kek_len;
+	const u8 *fils_nonces;
 };
 
 /**
@@ -1946,17 +2002,6 @@
 };
 
 /**
- * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment.
- *
- * @band: band of BSS which should match for RSSI level adjustment.
- * @delta: value of RSSI level adjustment.
- */
-struct cfg80211_bss_select_adjust {
-	enum nl80211_band band;
-	s8 delta;
-};
-
-/**
  * struct cfg80211_bss_selection - connection parameters for BSS selection.
  *
  * @behaviour: requested BSS selection behaviour.
@@ -2016,6 +2061,19 @@
  *	the BSSID of the current association, i.e., to the value that is
  *	included in the Current AP address field of the Reassociation Request
  *	frame.
+ * @fils_erp_username: EAP re-authentication protocol (ERP) username part of the
+ *	NAI or %NULL if not specified. This is used to construct FILS wrapped
+ *	data IE.
+ * @fils_erp_username_len: Length of @fils_erp_username in octets.
+ * @fils_erp_realm: EAP re-authentication protocol (ERP) realm part of NAI or
+ *	%NULL if not specified. This specifies the domain name of ER server and
+ *	is used to construct FILS wrapped data IE.
+ * @fils_erp_realm_len: Length of @fils_erp_realm in octets.
+ * @fils_erp_next_seq_num: The next sequence number to use in the FILS ERP
+ *	messages. This is also used to construct FILS wrapped data IE.
+ * @fils_erp_rrk: ERP re-authentication Root Key (rRK) used to derive additional
+ *	keys in FILS or %NULL if not specified.
+ * @fils_erp_rrk_len: Length of @fils_erp_rrk in octets.
  */
 struct cfg80211_connect_params {
 	struct ieee80211_channel *channel;
@@ -2041,6 +2099,30 @@
 	bool pbss;
 	struct cfg80211_bss_selection bss_select;
 	const u8 *prev_bssid;
+	const u8 *fils_erp_username;
+	size_t fils_erp_username_len;
+	const u8 *fils_erp_realm;
+	size_t fils_erp_realm_len;
+	u16 fils_erp_next_seq_num;
+	const u8 *fils_erp_rrk;
+	size_t fils_erp_rrk_len;
+};
+
+/**
+ * enum cfg80211_connect_params_changed - Connection parameters being updated
+ *
+ * This enum provides information of all connect parameters that
+ * have to be updated as part of update_connect_params() call.
+ *
+ * @UPDATE_ASSOC_IES: Indicates whether association request IEs are updated
+ * @UPDATE_FILS_ERP_INFO: Indicates that FILS connection parameters (realm,
+ *	username, erp sequence number and rrk) are updated
+ * @UPDATE_AUTH_TYPE: Indicates that Authentication type is updated
+ */
+enum cfg80211_connect_params_changed {
+	UPDATE_ASSOC_IES		= BIT(0),
+	UPDATE_FILS_ERP_INFO		= BIT(1),
+	UPDATE_AUTH_TYPE		= BIT(2),
 };
 
 /**
@@ -2067,12 +2149,27 @@
  * This structure is passed to the set/del_pmksa() method for PMKSA
  * caching.
  *
- * @bssid: The AP's BSSID.
- * @pmkid: The PMK material itself.
+ * @bssid: The AP's BSSID (may be %NULL).
+ * @pmkid: The identifier to refer a PMKSA.
+ * @pmk: The PMK for the PMKSA identified by @pmkid. This is used for key
+ *	derivation by a FILS STA. Otherwise, %NULL.
+ * @pmk_len: Length of the @pmk. The length of @pmk can differ depending on
+ *	the hash algorithm used to generate this.
+ * @ssid: SSID to specify the ESS within which a PMKSA is valid when using FILS
+ *	cache identifier (may be %NULL).
+ * @ssid_len: Length of the @ssid in octets.
+ * @cache_id: 2-octet cache identifier advertized by a FILS AP identifying the
+ *	scope of PMKSA. This is valid only if @ssid_len is non-zero (may be
+ *	%NULL).
  */
 struct cfg80211_pmksa {
 	const u8 *bssid;
 	const u8 *pmkid;
+	const u8 *pmk;
+	size_t pmk_len;
+	const u8 *ssid;
+	size_t ssid_len;
+	const u8 *cache_id;
 };
 
 /**
@@ -2247,12 +2344,14 @@
 
 /**
  * struct cfg80211_gtk_rekey_data - rekey data
- * @kek: key encryption key (NL80211_KEK_LEN bytes)
+ * @kek: key encryption key
  * @kck: key confirmation key (NL80211_KCK_LEN bytes)
  * @replay_ctr: replay counter (NL80211_REPLAY_CTR_LEN bytes)
+ * @kek_len: Length of @kek in octets
  */
 struct cfg80211_gtk_rekey_data {
 	const u8 *kek, *kck, *replay_ctr;
+	size_t kek_len;
 };
 
 /**
@@ -2564,10 +2663,17 @@
  *	cases, the result of roaming is indicated with a call to
  *	cfg80211_roamed() or cfg80211_roamed_bss().
  *	(invoked with the wireless_dev mutex held)
+ * @update_connect_params: Update the connect parameters while connected to a
+ *	BSS. The updated parameters can be used by driver/firmware for
+ *	subsequent BSS selection (roaming) decisions and to form the
+ *	Authentication/(Re)Association Request frames. This call does not
+ *	request an immediate disassociation or reassociation with the current
+ *	BSS, i.e., this impacts only subsequent (re)associations. The bits in
+ *	changed are defined in &enum cfg80211_connect_params_changed.
+ *	(invoked with the wireless_dev mutex held)
  * @disconnect: Disconnect from the BSS/ESS. Once done, call
  *	cfg80211_disconnected().
  *	(invoked with the wireless_dev mutex held)
- *
  * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
  *	cfg80211_ibss_joined(), also call that function when changing BSSID due
  *	to a merge.
@@ -2734,6 +2840,8 @@
  * @nan_change_conf: changes NAN configuration. The changed parameters must
  *	be specified in @changes (using &enum cfg80211_nan_conf_changes);
  *	All other parameters must be ignored.
+ *
+ * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2848,6 +2956,10 @@
 
 	int	(*connect)(struct wiphy *wiphy, struct net_device *dev,
 			   struct cfg80211_connect_params *sme);
+	int	(*update_connect_params)(struct wiphy *wiphy,
+					 struct net_device *dev,
+					 struct cfg80211_connect_params *sme,
+					 u32 changed);
 	int	(*disconnect)(struct wiphy *wiphy, struct net_device *dev,
 			      u16 reason_code);
 
@@ -3010,6 +3122,10 @@
 				   struct wireless_dev *wdev,
 				   struct cfg80211_nan_conf *conf,
 				   u32 changes);
+
+	int	(*set_multicast_to_unicast)(struct wiphy *wiphy,
+					    struct net_device *dev,
+					    const bool enabled);
 };
 
 /*
@@ -4999,6 +5115,78 @@
 #endif
 
 /**
+ * struct cfg80211_connect_resp_params - Connection response params
+ * @status: Status code, %WLAN_STATUS_SUCCESS for successful connection, use
+ *	%WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
+ *	the real status code for failures. If this call is used to report a
+ *	failure due to a timeout (e.g., not receiving an Authentication frame
+ *	from the AP) instead of an explicit rejection by the AP, -1 is used to
+ *	indicate that this is a failure, but without a status code.
+ *	@timeout_reason is used to report the reason for the timeout in that
+ *	case.
+ * @bssid: The BSSID of the AP (may be %NULL)
+ * @bss: Entry of bss to which STA got connected to, can be obtained through
+ *	cfg80211_get_bss() (may be %NULL). Only one parameter among @bssid and
+ *	@bss needs to be specified.
+ * @req_ie: Association request IEs (may be %NULL)
+ * @req_ie_len: Association request IEs length
+ * @resp_ie: Association response IEs (may be %NULL)
+ * @resp_ie_len: Association response IEs length
+ * @fils_kek: KEK derived from a successful FILS connection (may be %NULL)
+ * @fils_kek_len: Length of @fils_kek in octets
+ * @update_erp_next_seq_num: Boolean value to specify whether the value in
+ *	@fils_erp_next_seq_num is valid.
+ * @fils_erp_next_seq_num: The next sequence number to use in ERP message in
+ *	FILS Authentication. This value should be specified irrespective of the
+ *	status for a FILS connection.
+ * @pmk: A new PMK if derived from a successful FILS connection (may be %NULL).
+ * @pmk_len: Length of @pmk in octets
+ * @pmkid: A new PMKID if derived from a successful FILS connection or the PMKID
+ *	used for this FILS connection (may be %NULL).
+ * @timeout_reason: Reason for connection timeout. This is used when the
+ *	connection fails due to a timeout instead of an explicit rejection from
+ *	the AP. %NL80211_TIMEOUT_UNSPECIFIED is used when the timeout reason is
+ *	not known. This value is used only if @status < 0 to indicate that the
+ *	failure is due to a timeout and not due to explicit rejection by the AP.
+ *	This value is ignored in other cases (@status >= 0).
+ */
+struct cfg80211_connect_resp_params {
+	int status;
+	const u8 *bssid;
+	struct cfg80211_bss *bss;
+	const u8 *req_ie;
+	size_t req_ie_len;
+	const u8 *resp_ie;
+	size_t resp_ie_len;
+	const u8 *fils_kek;
+	size_t fils_kek_len;
+	bool update_erp_next_seq_num;
+	u16 fils_erp_next_seq_num;
+	const u8 *pmk;
+	size_t pmk_len;
+	const u8 *pmkid;
+	enum nl80211_timeout_reason timeout_reason;
+};
+
+/**
+ * cfg80211_connect_done - notify cfg80211 of connection result
+ *
+ * @dev: network device
+ * @params: connection response parameters
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver once execution of the connection
+ * request from connect() has been completed. This is similar to
+ * cfg80211_connect_bss(), but takes a structure pointer for connection response
+ * parameters. Only one of the functions among cfg80211_connect_bss(),
+ * cfg80211_connect_result(), cfg80211_connect_timeout(),
+ * and cfg80211_connect_done() should be called.
+ */
+void cfg80211_connect_done(struct net_device *dev,
+			   struct cfg80211_connect_resp_params *params,
+			   gfp_t gfp);
+
+/**
  * cfg80211_connect_bss - notify cfg80211 of connection result
  *
  * @dev: network device
@@ -5009,20 +5197,50 @@
  * @req_ie_len: association request IEs length
  * @resp_ie: association response IEs (may be %NULL)
  * @resp_ie_len: assoc response IEs length
- * @status: status code, 0 for successful connection, use
- *      %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
- *      the real status code for failures.
+ * @status: status code, %WLAN_STATUS_SUCCESS for successful connection, use
+ *	%WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
+ *	the real status code for failures. If this call is used to report a
+ *	failure due to a timeout (e.g., not receiving an Authentication frame
+ *	from the AP) instead of an explicit rejection by the AP, -1 is used to
+ *	indicate that this is a failure, but without a status code.
+ *	@timeout_reason is used to report the reason for the timeout in that
+ *	case.
  * @gfp: allocation flags
+ * @timeout_reason: reason for connection timeout. This is used when the
+ *	connection fails due to a timeout instead of an explicit rejection from
+ *	the AP. %NL80211_TIMEOUT_UNSPECIFIED is used when the timeout reason is
+ *	not known. This value is used only if @status < 0 to indicate that the
+ *	failure is due to a timeout and not due to explicit rejection by the AP.
+ *	This value is ignored in other cases (@status >= 0).
  *
- * It should be called by the underlying driver whenever connect() has
- * succeeded. This is similar to cfg80211_connect_result(), but with the
- * option of identifying the exact bss entry for the connection. Only one of
- * these functions should be called.
+ * It should be called by the underlying driver once execution of the connection
+ * request from connect() has been completed. This is similar to
+ * cfg80211_connect_result(), but with the option of identifying the exact bss
+ * entry for the connection. Only one of the functions among
+ * cfg80211_connect_bss(), cfg80211_connect_result(),
+ * cfg80211_connect_timeout(), and cfg80211_connect_done() should be called.
  */
-void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
-			  struct cfg80211_bss *bss, const u8 *req_ie,
-			  size_t req_ie_len, const u8 *resp_ie,
-			  size_t resp_ie_len, int status, gfp_t gfp);
+static inline void
+cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
+		     struct cfg80211_bss *bss, const u8 *req_ie,
+		     size_t req_ie_len, const u8 *resp_ie,
+		     size_t resp_ie_len, int status, gfp_t gfp,
+		     enum nl80211_timeout_reason timeout_reason)
+{
+	struct cfg80211_connect_resp_params params;
+
+	memset(&params, 0, sizeof(params));
+	params.status = status;
+	params.bssid = bssid;
+	params.bss = bss;
+	params.req_ie = req_ie;
+	params.req_ie_len = req_ie_len;
+	params.resp_ie = resp_ie;
+	params.resp_ie_len = resp_ie_len;
+	params.timeout_reason = timeout_reason;
+
+	cfg80211_connect_done(dev, &params, gfp);
+}
 
 /**
  * cfg80211_connect_result - notify cfg80211 of connection result
@@ -5033,13 +5251,16 @@
  * @req_ie_len: association request IEs length
  * @resp_ie: association response IEs (may be %NULL)
  * @resp_ie_len: assoc response IEs length
- * @status: status code, 0 for successful connection, use
+ * @status: status code, %WLAN_STATUS_SUCCESS for successful connection, use
  *	%WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
  *	the real status code for failures.
  * @gfp: allocation flags
  *
- * It should be called by the underlying driver whenever connect() has
- * succeeded.
+ * It should be called by the underlying driver once execution of the connection
+ * request from connect() has been completed. This is similar to
+ * cfg80211_connect_bss() which allows the exact bss entry to be specified. Only
+ * one of the functions among cfg80211_connect_bss(), cfg80211_connect_result(),
+ * cfg80211_connect_timeout(), and cfg80211_connect_done() should be called.
  */
 static inline void
 cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
@@ -5048,7 +5269,8 @@
 			u16 status, gfp_t gfp)
 {
 	cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie,
-			     resp_ie_len, status, gfp);
+			     resp_ie_len, status, gfp,
+			     NL80211_TIMEOUT_UNSPECIFIED);
 }
 
 /**
@@ -5059,19 +5281,23 @@
  * @req_ie: association request IEs (maybe be %NULL)
  * @req_ie_len: association request IEs length
  * @gfp: allocation flags
+ * @timeout_reason: reason for connection timeout.
  *
  * It should be called by the underlying driver whenever connect() has failed
  * in a sequence where no explicit authentication/association rejection was
  * received from the AP. This could happen, e.g., due to not being able to send
  * out the Authentication or Association Request frame or timing out while
- * waiting for the response.
+ * waiting for the response. Only one of the functions among
+ * cfg80211_connect_bss(), cfg80211_connect_result(),
+ * cfg80211_connect_timeout(), and cfg80211_connect_done() should be called.
  */
 static inline void
 cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
-			 const u8 *req_ie, size_t req_ie_len, gfp_t gfp)
+			 const u8 *req_ie, size_t req_ie_len, gfp_t gfp,
+			 enum nl80211_timeout_reason timeout_reason)
 {
 	cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1,
-			     gfp);
+			     gfp, timeout_reason);
 }
 
 /**
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index f5e625f..4341731 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -22,6 +22,7 @@
 #include <net/flow.h>
 #include <net/ip6_fib.h>
 #include <net/sock.h>
+#include <net/lwtunnel.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/route.h>
@@ -233,4 +234,11 @@
 		return daddr;
 }
 
+static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b)
+{
+	return a->dst.dev == b->dst.dev &&
+	       a->rt6i_idev == b->rt6i_idev &&
+	       ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) &&
+	       !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate);
+}
 #endif
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 308adc4..9fce47e 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -221,9 +221,17 @@
 	bool			no_share;
 };
 
+struct vxlan_dev_node {
+	struct hlist_node hlist;
+	struct vxlan_dev *vxlan;
+};
+
 /* Pseudo network device */
 struct vxlan_dev {
-	struct hlist_node hlist;	/* vni hash table */
+	struct vxlan_dev_node hlist4;	/* vni hash table for IPv4 socket */
+#if IS_ENABLED(CONFIG_IPV6)
+	struct vxlan_dev_node hlist6;	/* vni hash table for IPv6 socket */
+#endif
 	struct list_head  next;		/* vxlan's per namespace list */
 	struct vxlan_sock __rcu *vn4_sock;	/* listening socket for IPv4 */
 #if IS_ENABLED(CONFIG_IPV6)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 9d249f6..69fa6b3 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -254,6 +254,7 @@
 	STARGET_CREATED = 1,
 	STARGET_RUNNING,
 	STARGET_REMOVE,
+	STARGET_CREATED_REMOVE,
 	STARGET_DEL,
 };
 
diff --git a/include/soc/qcom/glink.h b/include/soc/qcom/glink.h
index 7b86481..4522b11 100644
--- a/include/soc/qcom/glink.h
+++ b/include/soc/qcom/glink.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017 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
@@ -340,6 +340,22 @@
  */
 unsigned long glink_qos_get_ramp_time(void *handle, size_t pkt_size);
 
+/**
+ * glink_start_rx_rt() - Vote for RT thread priority on RX.
+ * @handle:	Channel handle for which transaction are occurring.
+ *
+ * Return: 0 on success, standard Linux error codes on failure
+ */
+int glink_start_rx_rt(void *handle);
+
+/**
+ * glink_end_rx_rt() - Vote for RT thread priority on RX.
+ * @handle:	Channel handle for which transaction are occurring.
+ *
+ * Return: 0 on success, standard Linux error codes on failure
+ */
+int glink_end_rx_rt(void *handle);
+
 #else /* CONFIG_MSM_GLINK */
 static inline void *glink_open(const struct glink_open_config *cfg_ptr)
 {
@@ -428,5 +444,16 @@
 {
 	return 0;
 }
+
+static inline int glink_start_rx_rt(void *handle)
+{
+	return -ENODEV;
+}
+
+static inline int glink_end_rx_rt(void *handle)
+{
+	return -ENODEV;
+}
+
 #endif /* CONFIG_MSM_GLINK */
 #endif /* _SOC_QCOM_GLINK_H_ */
diff --git a/include/soc/qcom/msm-core.h b/include/soc/qcom/msm-core.h
index cd44615..f1c06a6 100644
--- a/include/soc/qcom/msm-core.h
+++ b/include/soc/qcom/msm-core.h
@@ -16,9 +16,12 @@
 #ifdef CONFIG_APSS_CORE_EA
 void set_cpu_throttled(struct cpumask *mask, bool throttling);
 struct blocking_notifier_head *get_power_update_notifier(void);
+void trigger_cpu_pwr_stats_calc(void);
+struct cpu_pwr_stats *get_cpu_pwr_stats(void);
 #else
 static inline void set_cpu_throttled(struct cpumask *mask, bool throttling) {}
 struct blocking_notifier_head *get_power_update_notifier(void) {return NULL; }
+static inline void trigger_cpu_pwr_stats_calc(void) {}
+struct cpu_pwr_stats *get_cpu_pwr_stats(void) {return NULL; }
 #endif
 #endif
-
diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h
index 665708d..12fa374 100644
--- a/include/soc/qcom/secure_buffer.h
+++ b/include/soc/qcom/secure_buffer.h
@@ -50,8 +50,6 @@
 #define PERM_EXEC			0x1
 
 #ifdef CONFIG_QCOM_SECURE_BUFFER
-int msm_secure_table(struct sg_table *table);
-int msm_unsecure_table(struct sg_table *table);
 int hyp_assign_table(struct sg_table *table,
 			u32 *source_vm_list, int source_nelems,
 			int *dest_vmids, int *dest_perms,
@@ -59,17 +57,8 @@
 extern int hyp_assign_phys(phys_addr_t addr, u64 size,
 			u32 *source_vmlist, int source_nelems,
 			int *dest_vmids, int *dest_perms, int dest_nelems);
-bool msm_secure_v2_is_supported(void);
 const char *msm_secure_vmid_to_string(int secure_vmid);
 #else
-static inline int msm_secure_table(struct sg_table *table)
-{
-	return -EINVAL;
-}
-static inline int msm_unsecure_table(struct sg_table *table)
-{
-	return -EINVAL;
-}
 static inline int hyp_assign_table(struct sg_table *table,
 			u32 *source_vm_list, int source_nelems,
 			int *dest_vmids, int *dest_perms,
@@ -85,10 +74,6 @@
 	return -EINVAL;
 }
 
-static inline bool msm_secure_v2_is_supported(void)
-{
-	return false;
-}
 static inline const char *msm_secure_vmid_to_string(int secure_vmid)
 {
 	return "N/A";
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index dc404e4..f196d40 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -233,6 +233,7 @@
 uint32_t socinfo_get_version(void);
 uint32_t socinfo_get_raw_id(void);
 char *socinfo_get_build_id(void);
+char *socinfo_get_id_string(void);
 uint32_t socinfo_get_platform_type(void);
 uint32_t socinfo_get_platform_subtype(void);
 uint32_t socinfo_get_platform_version(void);
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 14f6445..aa95178 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -8537,6 +8537,8 @@
 #define VSS_ICOMMON_CMD_GET_PARAM_V2	0x0001133E
 #define VSS_ICOMMON_RSP_GET_PARAM	0x00011008
 
+#define VSS_MAX_AVCS_NUM_SERVICES	25
+
 /* ID of the Bass Boost module.
  * This module supports the following parameter IDs:
  *  - #AUDPROC_PARAM_ID_BASS_BOOST_ENABLE
@@ -9197,6 +9199,74 @@
  */
 } __packed;
 
+/* Q6Core Specific */
+#define AVCS_CMD_GET_FWK_VERSION (0x0001292C)
+#define AVCS_CMDRSP_GET_FWK_VERSION (0x0001292D)
+
+#define AVCS_SERVICE_ID_ALL (0xFFFFFFFF)
+#define APRV2_IDS_SERVICE_ID_ADSP_CVP_V	(0xB)
+
+struct avcs_get_fwk_version {
+	/*
+	 * Indicates the major version of the AVS build.
+	 * This value is incremented on chipset family boundaries.
+	 */
+	uint32_t build_major_version;
+
+	/*
+	 * Minor version of the AVS build.
+	 * This value represents the mainline to which the AVS build belongs.
+	 */
+	uint32_t build_minor_version;
+
+	/* Indicates the AVS branch version to which the image belongs. */
+	uint32_t build_branch_version;
+
+	/* Indicates the AVS sub-branch or customer product line information. */
+	uint32_t build_subbranch_version;
+
+	/* Number of supported AVS services in the current build. */
+	uint32_t num_services;
+};
+
+struct avs_svc_api_info {
+	/*
+	 * APRV2 service IDs for the individual static services.
+	 *
+	 *	 @values
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_CORE_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_AFE_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_ASM_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_ADM_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_MVM_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_CVS_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_CVP_V
+	 *	 - APRV2_IDS_SERVICE_ID_ADSP_LSM_V
+	 */
+	uint32_t service_id;
+
+	/*
+	 * Indicates the API version of the service.
+	 *
+	 * Each new API update that warrants a change on the HLOS side triggers
+	 * an increment in the version.
+	 */
+	uint32_t api_version;
+
+	/*
+	 * Indicates the API increments on a sub-branch (not on the mainline).
+	 *
+	 * API branch version numbers can increment independently on different
+	 * sub-branches.
+	 */
+	uint32_t api_branch_version;
+};
+
+struct avcs_fwk_ver_info {
+	struct avcs_get_fwk_version avcs_fwk_version;
+	struct avs_svc_api_info *services;
+} __packed;
+
 /* LSM Specific */
 #define VW_FEAT_DIM					(39)
 
diff --git a/include/sound/q6core.h b/include/sound/q6core.h
index 0b8309a..111af67 100644
--- a/include/sound/q6core.h
+++ b/include/sound/q6core.h
@@ -13,6 +13,7 @@
 #ifndef __Q6CORE_H__
 #define __Q6CORE_H__
 #include <linux/qdsp6v2/apr.h>
+#include <sound/apr_audio-v2.h>
 
 
 
@@ -21,6 +22,11 @@
 
 bool q6core_is_adsp_ready(void);
 
+int q6core_get_service_version(uint32_t service_id,
+			       struct avcs_fwk_ver_info *ver_info,
+			       size_t size);
+size_t q6core_get_avcs_service_size(uint32_t service_id);
+
 #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
 #define DTS_EAGLE_LICENSE_ID           0x00028346
 struct adsp_dts_eagle {
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index 4ac24f5..33b2e75 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -64,6 +64,14 @@
 #define TA_DEFAULT_FABRIC_PROT_TYPE	0
 /* TPG status needs to be enabled to return sendtargets discovery endpoint info */
 #define TA_DEFAULT_TPG_ENABLED_SENDTARGETS 1
+/*
+ * Used to control the sending of keys with optional to respond state bit,
+ * as a workaround for non RFC compliant initiators,that do not propose,
+ * nor respond to specific keys required for login to complete.
+ *
+ * See iscsi_check_proposer_for_optional_reply() for more details.
+ */
+#define TA_DEFAULT_LOGIN_KEYS_WORKAROUND 1
 
 #define ISCSI_IOV_DATA_BUFFER		5
 
@@ -766,6 +774,7 @@
 	u8			t10_pi;
 	u32			fabric_prot_type;
 	u32			tpg_enabled_sendtargets;
+	u32			login_keys_workaround;
 	struct iscsi_portal_group *tpg;
 };
 
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index df323d4..cf3f5e3 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -245,7 +245,7 @@
 		__entry->pred_demand     = p->ravg.pred_demand;
 		memcpy(__entry->hist, p->ravg.sum_history,
 					RAVG_HIST_SIZE_MAX * sizeof(u32));
-		__entry->nr_big_tasks   = rq->hmp_stats.nr_big_tasks;
+		__entry->nr_big_tasks   = rq->walt_stats.nr_big_tasks;
 		__entry->cpu            = rq->cpu;
 	),
 
@@ -563,10 +563,10 @@
 		__entry->cpu			= rq->cpu;
 		__entry->idle			= idle;
 		__entry->nr_running		= rq->nr_running;
-		__entry->nr_big_tasks		= rq->hmp_stats.nr_big_tasks;
+		__entry->nr_big_tasks		= rq->walt_stats.nr_big_tasks;
 		__entry->load_scale_factor	= cpu_load_scale_factor(rq->cpu);
 		__entry->capacity		= cpu_capacity(rq->cpu);
-		__entry->cumulative_runnable_avg = rq->hmp_stats.cumulative_runnable_avg;
+		__entry->cumulative_runnable_avg = rq->walt_stats.cumulative_runnable_avg;
 		__entry->irqload		= irqload;
 		__entry->max_freq		= cpu_max_freq(rq->cpu);
 		__entry->power_cost		= power_cost;
@@ -618,7 +618,7 @@
 		__entry->grp_rq_ps	= rq->grp_time.prev_runnable_sum;
 		__entry->nt_ps		= rq->nt_prev_runnable_sum;
 		__entry->grp_nt_ps	= rq->grp_time.nt_prev_runnable_sum;
-		__entry->pl		= rq->hmp_stats.pred_demands_sum;
+		__entry->pl		= rq->walt_stats.pred_demands_sum;
 		__entry->load		= load;
 	),
 
diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h
index 031ae49..c0475a2 100644
--- a/include/trace/events/thermal.h
+++ b/include/trace/events/thermal.h
@@ -45,6 +45,23 @@
 		__entry->temp)
 );
 
+TRACE_EVENT(cdev_update_start,
+
+	TP_PROTO(struct thermal_cooling_device *cdev),
+
+	TP_ARGS(cdev),
+
+	TP_STRUCT__entry(
+		__string(type, cdev->type)
+	),
+
+	TP_fast_assign(
+		__assign_str(type, cdev->type);
+	),
+
+	TP_printk("type=%s update start", __get_str(type))
+);
+
 TRACE_EVENT(cdev_update,
 
 	TP_PROTO(struct thermal_cooling_device *cdev, unsigned long target,
@@ -98,6 +115,75 @@
 		show_tzt_type(__entry->trip_type))
 );
 
+TRACE_EVENT(thermal_handle_trip,
+
+	TP_PROTO(struct thermal_zone_device *tz, int trip),
+
+	TP_ARGS(tz, trip),
+
+	TP_STRUCT__entry(
+		__string(thermal_zone, tz->type)
+		__field(int, id)
+		__field(int, trip)
+	),
+
+	TP_fast_assign(
+		__assign_str(thermal_zone, tz->type);
+		__entry->id = tz->id;
+		__entry->trip = trip;
+	),
+
+	TP_printk("thermal_zone=%s id=%d handle trip=%d",
+		__get_str(thermal_zone), __entry->id, __entry->trip)
+);
+
+TRACE_EVENT(thermal_device_update,
+
+	TP_PROTO(struct thermal_zone_device *tz, int event),
+
+	TP_ARGS(tz, event),
+
+	TP_STRUCT__entry(
+		__string(thermal_zone, tz->type)
+		__field(int, id)
+		__field(int, event)
+	),
+
+	TP_fast_assign(
+		__assign_str(thermal_zone, tz->type);
+		__entry->id = tz->id;
+		__entry->event = event;
+	),
+
+	TP_printk("thermal_zone=%s id=%d received event:%d",
+		__get_str(thermal_zone), __entry->id, __entry->event)
+);
+
+TRACE_EVENT(thermal_set_trip,
+
+	TP_PROTO(struct thermal_zone_device *tz),
+
+	TP_ARGS(tz),
+
+	TP_STRUCT__entry(
+		__string(thermal_zone, tz->type)
+		__field(int, id)
+		__field(int, low)
+		__field(int, high)
+	),
+
+	TP_fast_assign(
+		__assign_str(thermal_zone, tz->type);
+		__entry->id = tz->id;
+		__entry->low = tz->prev_low_trip;
+		__entry->high = tz->prev_high_trip;
+	),
+
+	TP_printk("thermal_zone=%s id=%d low trip=%d high trip=%d",
+		__get_str(thermal_zone), __entry->id, __entry->low,
+		__entry->high)
+);
+
 TRACE_EVENT(thermal_power_cpu_get_power,
 	TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load,
 		size_t load_len, u32 dynamic_power, u32 static_power),
diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index 7668b57..5539933 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -37,9 +37,56 @@
 	BINDER_TYPE_PTR		= B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
 };
 
-enum {
+/**
+ * enum flat_binder_object_shifts: shift values for flat_binder_object_flags
+ * @FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT: shift for getting scheduler policy.
+ *
+ */
+enum flat_binder_object_shifts {
+	FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT = 9,
+};
+
+/**
+ * enum flat_binder_object_flags - flags for use in flat_binder_object.flags
+ */
+enum flat_binder_object_flags {
+	/**
+	 * @FLAT_BINDER_FLAG_PRIORITY_MASK: bit-mask for min scheduler priority
+	 *
+	 * These bits can be used to set the minimum scheduler priority
+	 * at which transactions into this node should run. Valid values
+	 * in these bits depend on the scheduler policy encoded in
+	 * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK.
+	 *
+	 * For SCHED_NORMAL/SCHED_BATCH, the valid range is between [-20..19]
+	 * For SCHED_FIFO/SCHED_RR, the value can run between [1..99]
+	 */
 	FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+	/**
+	 * @FLAT_BINDER_FLAG_ACCEPTS_FDS: whether the node accepts fds.
+	 */
 	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+	/**
+	 * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK: bit-mask for scheduling policy
+	 *
+	 * These two bits can be used to set the min scheduling policy at which
+	 * transactions on this node should run. These match the UAPI
+	 * scheduler policy values, eg:
+	 * 00b: SCHED_NORMAL
+	 * 01b: SCHED_FIFO
+	 * 10b: SCHED_RR
+	 * 11b: SCHED_BATCH
+	 */
+	FLAT_BINDER_FLAG_SCHED_POLICY_MASK =
+		3U << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT,
+
+	/**
+	 * @FLAT_BINDER_FLAG_INHERIT_RT: whether the node inherits RT policy
+	 *
+	 * Only when set, calls into this node will inherit a real-time
+	 * scheduling policy from the caller (for synchronous transactions).
+	 */
+	FLAT_BINDER_FLAG_INHERIT_RT = 0x800,
 };
 
 #ifdef BINDER_IPC_32BIT
@@ -186,6 +233,19 @@
 #define BINDER_CURRENT_PROTOCOL_VERSION 8
 #endif
 
+/*
+ * Use with BINDER_GET_NODE_DEBUG_INFO, driver reads ptr, writes to all fields.
+ * Set ptr to NULL for the first call to get the info for the first node, and
+ * then repeat the call passing the previously returned value to get the next
+ * nodes.  ptr will be 0 when there are no more nodes.
+ */
+struct binder_node_debug_info {
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	__u32            has_strong_ref;
+	__u32            has_weak_ref;
+};
+
 #define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
 #define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
 #define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
@@ -193,6 +253,7 @@
 #define BINDER_SET_CONTEXT_MGR		_IOW('b', 7, __s32)
 #define BINDER_THREAD_EXIT		_IOW('b', 8, __s32)
 #define BINDER_VERSION			_IOWR('b', 9, struct binder_version)
+#define BINDER_GET_NODE_DEBUG_INFO	_IOWR('b', 11, struct binder_node_debug_info)
 
 /*
  * NOTE: Two special error codes you should check for when calling
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 0932378..e645f17 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -266,6 +266,7 @@
 #define FUSE_PARALLEL_DIROPS    (1 << 18)
 #define FUSE_HANDLE_KILLPRIV	(1 << 19)
 #define FUSE_POSIX_ACL		(1 << 20)
+#define FUSE_PASSTHROUGH	(1 << 21)
 
 /**
  * CUSE INIT request/reply flags
@@ -498,7 +499,7 @@
 struct fuse_open_out {
 	uint64_t	fh;
 	uint32_t	open_flags;
-	uint32_t	padding;
+	int32_t   passthrough_fd;
 };
 
 struct fuse_release_in {
diff --git a/include/uapi/linux/hbtp_input.h b/include/uapi/linux/hbtp_input.h
index 9173c2a..3b124ff 100644
--- a/include/uapi/linux/hbtp_input.h
+++ b/include/uapi/linux/hbtp_input.h
@@ -6,6 +6,8 @@
 #define HBTP_MAX_FINGER		20
 #define HBTP_ABS_MT_FIRST	ABS_MT_TOUCH_MAJOR
 #define HBTP_ABS_MT_LAST	ABS_MT_TOOL_Y
+#define MAX_ROI_SIZE		144
+#define MAX_ACCEL_SIZE		128
 
 #define HBTP_EVENT_TYPE_DISPLAY	"EVENT_TYPE=HBTP_DISPLAY"
 
@@ -20,6 +22,11 @@
 	__s32 orientation;
 };
 
+struct hbtp_sensor_data {
+	__s16 accelBuffer[MAX_ACCEL_SIZE];
+	__s16 ROI[MAX_ROI_SIZE];
+};
+
 struct hbtp_input_mt {
 	__s32 num_touches;
 	struct hbtp_input_touch touches[HBTP_MAX_FINGER];
@@ -68,6 +75,8 @@
 					enum hbtp_afe_signal)
 #define HBTP_SET_POWER_CTRL	_IOW(HBTP_INPUT_IOCTL_BASE, 206, \
 					enum hbtp_afe_power_ctrl)
+#define HBTP_SET_SENSORDATA	_IOW(HBTP_INPUT_IOCTL_BASE, 207, \
+					struct hbtp_sensor_data)
 
 #endif	/* _UAPI_HBTP_INPUT_H */
 
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index 939ad08..5fdbdd8 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -892,22 +892,37 @@
  * @hdr_len_remove: Specifies how much of the header needs to
 		be removed in bytes
  * @eth_hdr_retained: Specifies if Ethernet header is retained or not
+ * @hdr_ofst_pkt_size_valid: Specifies if the Header offset is valid
+ * @hdr_ofst_pkt_size: If hdr_ofst_pkt_size_valid =1, this indicates where the
+		packet size field (2bytes) resides
+ * @hdr_endianness: 0:little endian, 1:big endian
  */
 struct ipa_l2tp_header_remove_procparams {
 	uint32_t hdr_len_remove:8;
 	uint32_t eth_hdr_retained:1;
-	uint32_t reserved:23;
+	/* Following fields are valid if eth_hdr_retained =1 ( bridge mode) */
+	uint32_t hdr_ofst_pkt_size_valid:1;
+	uint32_t hdr_ofst_pkt_size:6;
+	uint32_t hdr_endianness:1;
+	uint32_t reserved:15;
 };
 
 /**
- * union ipa_l2tp_hdr_proc_ctx_params -
+ * struct ipa_l2tp_hdr_proc_ctx_params -
  * @hdr_add_param: parameters for header add
  * @hdr_remove_param: parameters for header remove
+ * @is_dst_pipe_valid: if dst pipe is valid
+ * @dst_pipe: destination pipe
  */
-union ipa_l2tp_hdr_proc_ctx_params {
+struct ipa_l2tp_hdr_proc_ctx_params {
 	struct ipa_l2tp_header_add_procparams hdr_add_param;
 	struct ipa_l2tp_header_remove_procparams hdr_remove_param;
+	uint8_t is_dst_pipe_valid;
+	enum ipa_client_type dst_pipe;
 };
+
+#define L2TP_USER_SPACE_SPECIFY_DST_PIPE
+
 /**
  * struct ipa_hdr_proc_ctx_add - processing context descriptor includes
  * in and out parameters
@@ -924,7 +939,7 @@
 	uint32_t hdr_hdl;
 	uint32_t proc_ctx_hdl;
 	int status;
-	union ipa_l2tp_hdr_proc_ctx_params l2tp_params;
+	struct ipa_l2tp_hdr_proc_ctx_params l2tp_params;
 };
 
 #define IPA_L2TP_HDR_PROC_SUPPORT
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7d1e3b2..8c0fc7b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -173,6 +173,42 @@
  */
 
 /**
+ * DOC: FILS shared key authentication offload
+ *
+ * FILS shared key authentication offload can be advertized by drivers by
+ * setting @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD flag. The drivers that support
+ * FILS shared key authentication offload should be able to construct the
+ * authentication and association frames for FILS shared key authentication and
+ * eventually do a key derivation as per IEEE 802.11ai. The below additional
+ * parameters should be given to driver in %NL80211_CMD_CONNECT.
+ *	%NL80211_ATTR_FILS_ERP_USERNAME - used to construct keyname_nai
+ *	%NL80211_ATTR_FILS_ERP_REALM - used to construct keyname_nai
+ *	%NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used to construct erp message
+ *	%NL80211_ATTR_FILS_ERP_RRK - used to generate the rIK and rMSK
+ * rIK should be used to generate an authentication tag on the ERP message and
+ * rMSK should be used to derive a PMKSA.
+ * rIK, rMSK should be generated and keyname_nai, sequence number should be used
+ * as specified in IETF RFC 6696.
+ *
+ * When FILS shared key authentication is completed, driver needs to provide the
+ * below additional parameters to userspace.
+ *	%NL80211_ATTR_FILS_KEK - used for key renewal
+ *	%NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used in further EAP-RP exchanges
+ *	%NL80211_ATTR_PMKID - used to identify the PMKSA used/generated
+ *	%Nl80211_ATTR_PMK - used to update PMKSA cache in userspace
+ * The PMKSA can be maintained in userspace persistently so that it can be used
+ * later after reboots or wifi turn off/on also.
+ *
+ * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertized by a FILS
+ * capable AP supporting PMK caching. It specifies the scope within which the
+ * PMKSAs are cached in an ESS. %NL80211_CMD_SET_PMKSA and
+ * %NL80211_CMD_DEL_PMKSA are enhanced to allow support for PMKSA caching based
+ * on FILS cache identifier. Additionally %NL80211_ATTR_PMK is used with
+ * %NL80211_SET_PMKSA to specify the PMK corresponding to a PMKSA for driver to
+ * use in a FILS shared key connection with PMKSA caching.
+ */
+
+/**
  * enum nl80211_commands - supported nl80211 commands
  *
  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -370,10 +406,18 @@
  * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
  *	NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
  *
- * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry, using %NL80211_ATTR_MAC
- *	(for the BSSID) and %NL80211_ATTR_PMKID.
+ * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry using %NL80211_ATTR_MAC
+ *	(for the BSSID), %NL80211_ATTR_PMKID, and optionally %NL80211_ATTR_PMK
+ *	(PMK is used for PTKSA derivation in case of FILS shared key offload) or
+ *	using %NL80211_ATTR_SSID, %NL80211_ATTR_FILS_CACHE_ID,
+ *	%NL80211_ATTR_PMKID, and %NL80211_ATTR_PMK in case of FILS
+ *	authentication where %NL80211_ATTR_FILS_CACHE_ID is the identifier
+ *	advertized by a FILS capable AP identifying the scope of PMKSA in an
+ *	ESS.
  * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC
- *	(for the BSSID) and %NL80211_ATTR_PMKID.
+ *	(for the BSSID) and %NL80211_ATTR_PMKID or using %NL80211_ATTR_SSID,
+ *	%NL80211_ATTR_FILS_CACHE_ID, and %NL80211_ATTR_PMKID in case of FILS
+ *	authentication.
  * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries.
  *
  * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
@@ -600,6 +644,20 @@
  *
  * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
  *
+ * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform
+ *	multicast to unicast conversion. When enabled, all multicast packets
+ *	with ethertype ARP, IPv4 or IPv6 (possibly within an 802.1Q header)
+ *	will be sent out to each station once with the destination (multicast)
+ *	MAC address replaced by the station's MAC address. Note that this may
+ *	break certain expectations of the receiver, e.g. the ability to drop
+ *	unicast IP packets encapsulated in multicast L2 frames, or the ability
+ *	to not send destination unreachable messages in such cases.
+ *	This can only be toggled per BSS. Configure this on an interface of
+ *	type %NL80211_IFTYPE_AP. It applies to all its VLAN interfaces
+ *	(%NL80211_IFTYPE_AP_VLAN), except for those in 4addr (WDS) mode.
+ *	If %NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED is not present with this
+ *	command, the feature is disabled.
+ *
  * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
  *	mesh config parameters may be given.
  * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
@@ -874,6 +932,12 @@
  *	This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and
  *	%NL80211_ATTR_COOKIE.
  *
+ * @NL80211_CMD_UPDATE_CONNECT_PARAMS: Update one or more connect parameters
+ *	for subsequent roaming cases if the driver or firmware uses internal
+ *	BSS selection. This command can be issued only while connected and it
+ *	does not result in a change for the current association. Currently,
+ *	only the %NL80211_ATTR_IE data is used and updated with this command.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1069,6 +1133,10 @@
 	NL80211_CMD_CHANGE_NAN_CONFIG,
 	NL80211_CMD_NAN_MATCH,
 
+	NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+
+	NL80211_CMD_UPDATE_CONNECT_PARAMS,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1638,8 +1706,16 @@
  *	the connection request from a station. nl80211_connect_failed_reason
  *	enum has different reasons of connection failure.
  *
- * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
- *	with the Authentication transaction sequence number field.
+ * @NL80211_ATTR_AUTH_DATA: Fields and elements in Authentication frames.
+ *	This contains the authentication frame body (non-IE and IE data),
+ *	excluding the Authentication algorithm number, i.e., starting at the
+ *	Authentication transaction sequence number field. It is used with
+ *	authentication algorithms that need special fields to be added into
+ *	the frames (SAE and FILS). Currently, only the SAE cases use the
+ *	initial two fields (Authentication transaction sequence number and
+ *	Status code). However, those fields are included in the attribute data
+ *	for all authentication algorithms to keep the attribute definition
+ *	consistent.
  *
  * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
  *	association request when used with NL80211_CMD_NEW_STATION)
@@ -1936,10 +2012,61 @@
  *	attribute.
  * @NL80211_ATTR_NAN_MATCH: used to report a match. This is a nested attribute.
  *	See &enum nl80211_nan_match_attributes.
+ * @NL80211_ATTR_FILS_KEK: KEK for FILS (Re)Association Request/Response frame
+ *	protection.
+ * @NL80211_ATTR_FILS_NONCES: Nonces (part of AAD) for FILS (Re)Association
+ *	Request/Response frame protection. This attribute contains the 16 octet
+ *	STA Nonce followed by 16 octets of AP Nonce.
+ *
+ * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast
+ *	packets should be send out as unicast to all stations (flag attribute).
  *
  * @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
  *	used in various commands/events for specifying the BSSID.
  *
+ * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI: Relative RSSI threshold by which
+ *	other BSSs has to be better or slightly worse than the current
+ *	connected BSS so that they get reported to user space.
+ *	This will give an opportunity to userspace to consider connecting to
+ *	other matching BSSs which have better or slightly worse RSSI than
+ *	the current connected BSS by using an offloaded operation to avoid
+ *	unnecessary wakeups.
+ *
+ * @NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST: When present the RSSI level for BSSs in
+ *	the specified band is to be adjusted before doing
+ *	%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparision to figure out
+ *	better BSSs. The attribute value is a packed structure
+ *	value as specified by &struct nl80211_bss_select_rssi_adjust.
+ *
+ * @NL80211_ATTR_TIMEOUT_REASON: The reason for which an operation timed out.
+ *	u32 attribute with an &enum nl80211_timeout_reason value. This is used,
+ *	e.g., with %NL80211_CMD_CONNECT event.
+ *
+ * @NL80211_ATTR_FILS_ERP_USERNAME: EAP Re-authentication Protocol (ERP)
+ *	username part of NAI used to refer keys rRK and rIK. This is used with
+ *	%NL80211_CMD_CONNECT.
+ *
+ * @NL80211_ATTR_FILS_ERP_REALM: EAP Re-authentication Protocol (ERP) realm part
+ *	of NAI specifying the domain name of the ER server. This is used with
+ *	%NL80211_CMD_CONNECT.
+ *
+ * @NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM: Unsigned 16-bit ERP next sequence number
+ *	to use in ERP messages. This is used in generating the FILS wrapped data
+ *	for FILS authentication and is used with %NL80211_CMD_CONNECT.
+ *
+ * @NL80211_ATTR_FILS_ERP_RRK: ERP re-authentication Root Key (rRK) for the
+ *	NAI specified by %NL80211_ATTR_FILS_ERP_USERNAME and
+ *	%NL80211_ATTR_FILS_ERP_REALM. This is used for generating rIK and rMSK
+ *	from successful FILS authentication and is used with
+ *	%NL80211_CMD_CONNECT.
+ *
+ * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertized by a FILS AP
+ *	identifying the scope of PMKSAs. This is used with
+ *	@NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA.
+ *
+ * @NL80211_ATTR_PMK: PMK for the PMKSA identified by %NL80211_ATTR_PMKID.
+ *	This is used with @NL80211_CMD_SET_PMKSA.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2198,7 +2325,7 @@
 
 	NL80211_ATTR_CONN_FAILED_REASON,
 
-	NL80211_ATTR_SAE_DATA,
+	NL80211_ATTR_AUTH_DATA,
 
 	NL80211_ATTR_VHT_CAPABILITY,
 
@@ -2339,8 +2466,26 @@
 	NL80211_ATTR_NAN_FUNC,
 	NL80211_ATTR_NAN_MATCH,
 
+	NL80211_ATTR_FILS_KEK,
+	NL80211_ATTR_FILS_NONCES,
+
+	NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
+
 	NL80211_ATTR_BSSID,
 
+	NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
+	NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+
+	NL80211_ATTR_TIMEOUT_REASON,
+
+	NL80211_ATTR_FILS_ERP_USERNAME,
+	NL80211_ATTR_FILS_ERP_REALM,
+	NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
+	NL80211_ATTR_FILS_ERP_RRK,
+	NL80211_ATTR_FILS_CACHE_ID,
+
+	NL80211_ATTR_PMK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2352,6 +2497,7 @@
 #define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
 #define	NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
 #define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER
+#define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA
 
 /*
  * Allow user space programs to use #ifdef on new attributes by defining them
@@ -3032,6 +3178,13 @@
  *	how this API was implemented in the past. Also, due to the same problem,
  *	the only way to create a matchset with only an RSSI filter (with this
  *	attribute) is if there's only a single matchset with the RSSI attribute.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI: Flag indicating whether
+ *	%NL80211_SCHED_SCAN_MATCH_ATTR_RSSI to be used as absolute RSSI or
+ *	relative to current bss's RSSI.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST: When present the RSSI level for
+ *	BSS-es in the specified band is to be adjusted before doing
+ *	RSSI-based BSS selection. The attribute value is a packed structure
+ *	value as specified by &struct nl80211_bss_select_rssi_adjust.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
  *	attribute number currently defined
  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3041,6 +3194,8 @@
 
 	NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
 	NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
+	NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
+	NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
 
 	/* keep last */
 	__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -3665,6 +3820,9 @@
  * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
  * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
  * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
+ * @NL80211_AUTHTYPE_FILS_SK: Fast Initial Link Setup shared key
+ * @NL80211_AUTHTYPE_FILS_SK_PFS: Fast Initial Link Setup shared key with PFS
+ * @NL80211_AUTHTYPE_FILS_PK: Fast Initial Link Setup public key
  * @__NL80211_AUTHTYPE_NUM: internal
  * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
  * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -3677,6 +3835,9 @@
 	NL80211_AUTHTYPE_FT,
 	NL80211_AUTHTYPE_NETWORK_EAP,
 	NL80211_AUTHTYPE_SAE,
+	NL80211_AUTHTYPE_FILS_SK,
+	NL80211_AUTHTYPE_FILS_SK_PFS,
+	NL80211_AUTHTYPE_FILS_PK,
 
 	/* keep last */
 	__NL80211_AUTHTYPE_NUM,
@@ -4643,6 +4804,20 @@
  *	configuration (AP/mesh) with HT rates.
  * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
  *	configuration (AP/mesh) with VHT rates.
+ * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link Setup
+ *	with user space SME (NL80211_CMD_AUTHENTICATE) in station mode.
+ * @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA: This driver supports randomized TA
+ *	in @NL80211_CMD_FRAME while not associated.
+ * @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED: This driver supports
+ *	randomized TA in @NL80211_CMD_FRAME while associated.
+ * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports sched_scan
+ *	for reporting BSSs with better RSSI than the current connected BSS
+ *	(%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI).
+ * @NL80211_EXT_FEATURE_CQM_RSSI_LIST: With this driver the
+ *	%NL80211_ATTR_CQM_RSSI_THOLD attribute accepts a list of zero or more
+ *	RSSI threshold values to monitor rather than exactly one threshold.
+ * @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD: Driver SME supports FILS shared key
+ *	authentication with %NL80211_CMD_CONNECT.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4657,6 +4832,12 @@
 	NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
 	NL80211_EXT_FEATURE_BEACON_RATE_HT,
 	NL80211_EXT_FEATURE_BEACON_RATE_VHT,
+	NL80211_EXT_FEATURE_FILS_STA,
+	NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA,
+	NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED,
+	NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
+	NL80211_EXT_FEATURE_CQM_RSSI_LIST,
+	NL80211_EXT_FEATURE_FILS_SK_OFFLOAD,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
@@ -4696,6 +4877,21 @@
 };
 
 /**
+ * enum nl80211_timeout_reason - timeout reasons
+ *
+ * @NL80211_TIMEOUT_UNSPECIFIED: Timeout reason unspecified.
+ * @NL80211_TIMEOUT_SCAN: Scan (AP discovery) timed out.
+ * @NL80211_TIMEOUT_AUTH: Authentication timed out.
+ * @NL80211_TIMEOUT_ASSOC: Association timed out.
+ */
+enum nl80211_timeout_reason {
+	NL80211_TIMEOUT_UNSPECIFIED,
+	NL80211_TIMEOUT_SCAN,
+	NL80211_TIMEOUT_AUTH,
+	NL80211_TIMEOUT_ASSOC,
+};
+
+/**
  * enum nl80211_scan_flags -  scan request control flags
  *
  * Scan request control flags are used to control the handling
diff --git a/include/uapi/linux/spcom.h b/include/uapi/linux/spcom.h
index 9b6b9b7..39b1be0 100644
--- a/include/uapi/linux/spcom.h
+++ b/include/uapi/linux/spcom.h
@@ -30,6 +30,12 @@
  * with special size SPCOM_GET_NEXT_REQUEST_SIZE.
  */
 
+/*
+ * Maximum number of channel between Secure Processor and HLOS.
+ * including predefined channels, like "sp_kernel".
+ */
+#define SPCOM_MAX_CHANNELS	0x20
+
 /* Maximum size (including null) for channel names */
 #define SPCOM_CHANNEL_NAME_SIZE		32
 
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
index a8acc24..0e5ce0d 100644
--- a/include/uapi/linux/usb/ch9.h
+++ b/include/uapi/linux/usb/ch9.h
@@ -1051,6 +1051,30 @@
  */
 #define USB_DT_USB_SSP_CAP_SIZE(ssac)	(16 + ssac * 4)
 
+/*
+ * Configuration Summary descriptors: Defines a list of functions in the
+ * configuration. This descriptor may be used by Host software to decide
+ * which Configuration to use to obtain the desired functionality.
+ */
+#define	USB_CAP_TYPE_CONFIG_SUMMARY	0x10
+
+struct function_class_info {
+	__u8 bClass;
+	__u8 bSubClass;
+	__u8 bProtocol;
+};
+
+struct usb_config_summary_descriptor {
+	__u8 bLength;
+	__u8 bDescriptorType;
+	__u8 bDevCapabilityType;
+	__u16 bcdVersion;
+	__u8 bConfigurationValue;
+	__u8 bMaxPower;
+	__u8 bNumFunctions;
+	struct function_class_info cs_info[];
+} __attribute__((packed));
+
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild
index 98844ac..4ded0a4 100644
--- a/include/uapi/media/Kbuild
+++ b/include/uapi/media/Kbuild
@@ -4,6 +4,7 @@
 header-y += cam_isp.h
 header-y += cam_isp_vfe.h
 header-y += cam_isp_ife.h
+header-y += cam_jpeg.h
 header-y += cam_req_mgr.h
 header-y += cam_sensor.h
 header-y += cam_sync.h
diff --git a/include/uapi/media/cam_jpeg.h b/include/uapi/media/cam_jpeg.h
new file mode 100644
index 0000000..f3082f3
--- /dev/null
+++ b/include/uapi/media/cam_jpeg.h
@@ -0,0 +1,117 @@
+#ifndef __UAPI_CAM_JPEG_H__
+#define __UAPI_CAM_JPEG_H__
+
+#include "cam_defs.h"
+
+/* enc, dma, cdm(enc/dma) are used in querycap */
+#define CAM_JPEG_DEV_TYPE_ENC      0
+#define CAM_JPEG_DEV_TYPE_DMA      1
+#define CAM_JPEG_DEV_TYPE_MAX      2
+
+#define CAM_JPEG_NUM_DEV_PER_RES_MAX      1
+
+/* definitions needed for jpeg aquire device */
+#define CAM_JPEG_RES_TYPE_ENC        0
+#define CAM_JPEG_RES_TYPE_DMA        1
+#define CAM_JPEG_RES_TYPE_MAX        2
+
+/* packet opcode types */
+#define CAM_JPEG_OPCODE_ENC_UPDATE 0
+#define CAM_JPEG_OPCODE_DMA_UPDATE 1
+
+/* ENC input port resource type */
+#define CAM_JPEG_ENC_INPUT_IMAGE                 0x0
+
+/* ENC output port resource type */
+#define CAM_JPEG_ENC_OUTPUT_IMAGE                0x1
+
+#define CAM_JPEG_ENC_IO_IMAGES_MAX               0x2
+
+/* DMA input port resource type */
+#define CAM_JPEG_DMA_INPUT_IMAGE                 0x0
+
+/* DMA output port resource type */
+#define CAM_JPEG_DMA_OUTPUT_IMAGE                0x1
+
+#define CAM_JPEG_DMA_IO_IMAGES_MAX               0x2
+
+#define CAM_JPEG_IMAGE_MAX                       0x2
+
+/**
+ * struct cam_jpeg_dev_ver - Device information for particular hw type
+ *
+ * This is used to get device version info of JPEG ENC, JPEG DMA
+ * from hardware and use this info in CAM_QUERY_CAP IOCTL
+ *
+ * @size : Size of struct passed
+ * @dev_type: Hardware type for the cap info(jpeg enc, jpeg dma)
+ * @hw_ver: Major, minor and incr values of a device version
+ */
+struct cam_jpeg_dev_ver {
+	uint32_t size;
+	uint32_t dev_type;
+	struct cam_hw_version hw_ver;
+};
+
+/**
+ * struct cam_jpeg_query_cap_cmd - JPEG query device capability payload
+ *
+ * @dev_iommu_handle: Jpeg iommu handles for secure/non secure
+ *      modes
+ * @cdm_iommu_handle: Iommu handles for secure/non secure modes
+ * @num_enc: Number of encoder
+ * @num_dma: Number of dma
+ * @dev_ver: Returned device capability array
+ */
+struct cam_jpeg_query_cap_cmd {
+	struct cam_iommu_handle dev_iommu_handle;
+	struct cam_iommu_handle cdm_iommu_handle;
+	uint32_t num_enc;
+	uint32_t num_dma;
+	struct cam_jpeg_dev_ver dev_ver[CAM_JPEG_DEV_TYPE_MAX];
+};
+
+/**
+ * struct cam_jpeg_res_info - JPEG output resource info
+ *
+ * @format: Format of the resource
+ * @width:  Width in pixels
+ * @height: Height in lines
+ * @fps:  Fps
+ */
+struct cam_jpeg_res_info {
+	uint32_t format;
+	uint32_t width;
+	uint32_t height;
+	uint32_t fps;
+};
+
+/**
+ * struct cam_jpeg_acquire_dev_info - An JPEG device info
+ *
+ * @dev_type: Device type (ENC/DMA)
+ * @reserved: Reserved Bytes
+ * @in_res: In resource info
+ * @in_res: Iut resource info
+ */
+struct cam_jpeg_acquire_dev_info {
+	uint32_t dev_type;
+	uint32_t reserved;
+	struct cam_jpeg_res_info in_res;
+	struct cam_jpeg_res_info out_res;
+};
+
+/**
+ * struct cam_jpeg_config_inout_param_info - JPEG Config time
+ *     input output params
+ *
+ * @clk_index: Input Param- clock selection index.(-1 default)
+ * @output_size: Output Param - jpeg encode/dma output size in
+ *     bytes
+ */
+struct cam_jpeg_config_inout_param_info {
+	int32_t clk_index;
+	int32_t output_size;
+};
+
+#endif /* __UAPI_CAM_JPEG_H__ */
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index e073c5c..23a8ccf 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -22,6 +22,7 @@
 #define CAM_ACTUATOR_DEVICE_TYPE  (CAM_DEVICE_TYPE_BASE + 9)
 #define CAM_CCI_DEVICE_TYPE       (CAM_DEVICE_TYPE_BASE + 10)
 #define CAM_FLASH_DEVICE_TYPE     (CAM_DEVICE_TYPE_BASE + 11)
+#define CAM_EEPROM_DEVICE_TYPE    (CAM_DEVICE_TYPE_BASE + 12)
 
 /* cam_req_mgr hdl info */
 #define CAM_REQ_MGR_HDL_IDX_POS           8
diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h
index 83f1a02..ac370ba 100644
--- a/include/uapi/media/cam_sensor.h
+++ b/include/uapi/media/cam_sensor.h
@@ -6,7 +6,7 @@
 #include <media/cam_defs.h>
 
 #define CAM_SENSOR_PROBE_CMD   (CAM_COMMON_OPCODE_MAX + 1)
-#define CAM_SENSOR_MAX_LED_TRIGGERS 3
+#define CAM_FLASH_MAX_LED_TRIGGERS 3
 /**
  * struct cam_sensor_query_cap - capabilities info for sensor
  *
@@ -63,6 +63,18 @@
 } __attribute__((packed));
 
 /**
+ * struct cam_eeprom_query_cap_t - capabilities info for eeprom
+ *
+ * @slot_info                  :  Indicates about the slotId or cell Index
+ * @eeprom_kernel_probe        :  Indicates about the kernel or userspace probe
+ */
+struct cam_eeprom_query_cap_t {
+	uint32_t            slot_info;
+	uint16_t            eeprom_kernel_probe;
+	uint16_t            reserved;
+} __attribute__((packed));
+
+/**
  * struct cam_cmd_i2c_info - Contains slave I2C related info
  *
  * @slave_addr      :    Slave address
@@ -360,7 +372,7 @@
 	uint16_t    reserved;
 	uint32_t    led_on_delay_ms;
 	uint32_t    led_off_delay_ms;
-	uint32_t    led_current_ma[CAM_SENSOR_MAX_LED_TRIGGERS];
+	uint32_t    led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS];
 } __attribute__((packed));
 
 /**
@@ -379,7 +391,7 @@
 	uint16_t    count;
 	uint8_t     opcode;
 	uint8_t     cmd_type;
-	uint32_t    led_current_ma[CAM_SENSOR_MAX_LED_TRIGGERS];
+	uint32_t    led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS];
 } __attribute__((packed));
 
 /**
@@ -409,9 +421,9 @@
  */
 struct cam_flash_query_cap_info {
 	uint32_t    slot_info;
-	uint32_t    max_current_flash[CAM_SENSOR_MAX_LED_TRIGGERS];
-	uint32_t    max_duration_flash[CAM_SENSOR_MAX_LED_TRIGGERS];
-	uint32_t    max_current_torch[CAM_SENSOR_MAX_LED_TRIGGERS];
+	uint32_t    max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t    max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS];
+	uint32_t    max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS];
 } __attribute__ ((packed));
 
 #endif
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 44c17f4..8ce679d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -885,6 +885,11 @@
 	if (err)
 		return err;
 
+	if (is_pointer_value(env, insn->src_reg)) {
+		verbose("R%d leaks addr into mem\n", insn->src_reg);
+		return -EACCES;
+	}
+
 	/* check whether atomic_add can read the memory */
 	err = check_mem_access(env, insn->dst_reg, insn->off,
 			       BPF_SIZE(insn->code), BPF_READ, -1);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index c0644f4..7bb21fd 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -6616,7 +6616,7 @@
 		struct task_struct *task;
 		int count = 0;
 
-		seq_printf(seq, "css_set %p\n", cset);
+		seq_printf(seq, "css_set %pK\n", cset);
 
 		list_for_each_entry(task, &cset->tasks, cg_list) {
 			if (count++ > MAX_TASKS_SHOWN_PER_CSS)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index e2ac135..d1bed63 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -358,6 +358,32 @@
 	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
 };
 
+/* The shared events struct. */
+#define SHARED_EVENTS_MAX 7
+
+struct shared_events_str {
+	/*
+	 * Mutex to serialize access to shared list. Needed for the
+	 * read/modify/write sequences.
+	 */
+	struct mutex		list_mutex;
+
+	/*
+	 * A 1 bit for an index indicates that the slot is being used for
+	 * an event. A 0 means that the slot can be used.
+	 */
+	DECLARE_BITMAP(used_mask, SHARED_EVENTS_MAX);
+
+	/*
+	 * The kernel events that are shared for a cpu;
+	 */
+	struct perf_event	*events[SHARED_EVENTS_MAX];
+	struct perf_event_attr	attr[SHARED_EVENTS_MAX];
+	atomic_t		refcount[SHARED_EVENTS_MAX];
+};
+
+static struct shared_events_str __percpu *shared_events;
+
 /*
  * perf_sched_events : >0 events exist
  * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
@@ -4079,6 +4105,35 @@
 static void perf_addr_filters_splice(struct perf_event *event,
 				       struct list_head *head);
 
+static int
+perf_event_delete_kernel_shared(struct perf_event *event)
+{
+	int rc = -1, cpu = event->cpu;
+	struct shared_events_str *shrd_events;
+	unsigned long idx;
+
+	if (!shared_events || (u32)cpu >= nr_cpu_ids)
+		return 0;
+
+	shrd_events = per_cpu_ptr(shared_events, cpu);
+
+	mutex_lock(&shrd_events->list_mutex);
+
+	for_each_set_bit(idx, shrd_events->used_mask, SHARED_EVENTS_MAX) {
+		if (shrd_events->events[idx] == event) {
+			if (atomic_dec_and_test(&shrd_events->refcount[idx])) {
+				clear_bit(idx, shrd_events->used_mask);
+				shrd_events->events[idx] = NULL;
+			}
+			rc = (int)atomic_read(&shrd_events->refcount[idx]);
+			break;
+		}
+	}
+
+	mutex_unlock(&shrd_events->list_mutex);
+	return rc;
+}
+
 static void _free_event(struct perf_event *event)
 {
 	irq_work_sync(&event->pending);
@@ -4216,8 +4271,12 @@
 		goto no_ctx;
 	}
 
-	if (!is_kernel_event(event))
+	if (!is_kernel_event(event)) {
 		perf_remove_from_owner(event);
+	} else {
+		if (perf_event_delete_kernel_shared(event) > 0)
+			return 0;
+	}
 
 	ctx = perf_event_ctx_lock(event);
 	WARN_ON_ONCE(ctx->parent_ctx);
@@ -7112,21 +7171,6 @@
 	perf_output_end(&handle);
 }
 
-static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs)
-{
-	/*
-	 * Due to interrupt latency (AKA "skid"), we may enter the
-	 * kernel before taking an overflow, even if the PMU is only
-	 * counting user events.
-	 * To avoid leaking information to userspace, we must always
-	 * reject kernel samples when exclude_kernel is set.
-	 */
-	if (event->attr.exclude_kernel && !user_mode(regs))
-		return false;
-
-	return true;
-}
-
 /*
  * Generic event overflow handling, sampling.
  */
@@ -7174,12 +7218,6 @@
 	}
 
 	/*
-	 * For security, drop the skid kernel samples if necessary.
-	 */
-	if (!sample_is_allowed(event, regs))
-		return ret;
-
-	/*
 	 * XXX event_limit might not quite work as expected on inherited
 	 * events
 	 */
@@ -10064,6 +10102,103 @@
 	return err;
 }
 
+static struct perf_event *
+perf_event_create_kernel_shared_check(struct perf_event_attr *attr, int cpu,
+				 struct task_struct *task,
+				 perf_overflow_handler_t overflow_handler,
+				 void *context)
+{
+	unsigned long idx;
+	struct perf_event *event;
+	struct shared_events_str *shrd_events;
+
+	/*
+	 * Have to be per cpu events for sharing
+	 */
+	if (!shared_events || (u32)cpu >= nr_cpu_ids)
+		return NULL;
+
+	/*
+	 * Can't handle these type requests for sharing right now.
+	 */
+	if (task || context || overflow_handler ||
+	    (attr->type != PERF_TYPE_HARDWARE &&
+	     attr->type != PERF_TYPE_RAW))
+		return NULL;
+
+	/*
+	 * Using per_cpu_ptr (or could do cross cpu call which is what most of
+	 * perf does to access per cpu data structures
+	 */
+	shrd_events = per_cpu_ptr(shared_events, cpu);
+
+	mutex_lock(&shrd_events->list_mutex);
+
+	event = NULL;
+	for_each_set_bit(idx, shrd_events->used_mask, SHARED_EVENTS_MAX) {
+		if (memcmp(attr, &shrd_events->attr[idx],
+		    sizeof(shrd_events->attr[idx])) == 0) {
+			atomic_inc(&shrd_events->refcount[idx]);
+			event = shrd_events->events[idx];
+			break;
+		}
+	}
+	mutex_unlock(&shrd_events->list_mutex);
+	return event;
+}
+
+static void
+perf_event_create_kernel_shared_add(struct perf_event_attr *attr, int cpu,
+				 struct task_struct *task,
+				 perf_overflow_handler_t overflow_handler,
+				 void *context,
+				 struct perf_event *event)
+{
+	unsigned long idx;
+	struct shared_events_str *shrd_events;
+
+	/*
+	 * Have to be per cpu events for sharing
+	 */
+	if (!shared_events || (u32)cpu >= nr_cpu_ids)
+		return;
+
+	/*
+	 * Can't handle these type requests for sharing right now.
+	 */
+	if (task || context || overflow_handler ||
+	    (attr->type != PERF_TYPE_HARDWARE &&
+	     attr->type != PERF_TYPE_RAW))
+		return;
+
+	/*
+	 * Using per_cpu_ptr (or could do cross cpu call which is what most of
+	 * perf does to access per cpu data structures
+	 */
+	shrd_events = per_cpu_ptr(shared_events, cpu);
+
+	mutex_lock(&shrd_events->list_mutex);
+
+	/*
+	 * If we are in this routine, we know that this event isn't already in
+	 * the shared list. Check if slot available in shared list
+	 */
+	idx = find_first_zero_bit(shrd_events->used_mask, SHARED_EVENTS_MAX);
+
+	if (idx >= SHARED_EVENTS_MAX)
+		goto out;
+
+	/*
+	 * The event isn't in the list and there is an empty slot so add it.
+	 */
+	shrd_events->attr[idx]   = *attr;
+	shrd_events->events[idx] = event;
+	set_bit(idx, shrd_events->used_mask);
+	atomic_set(&shrd_events->refcount[idx], 1);
+out:
+	mutex_unlock(&shrd_events->list_mutex);
+}
+
 /**
  * perf_event_create_kernel_counter
  *
@@ -10082,6 +10217,14 @@
 	int err;
 
 	/*
+	 * Check if the requested attributes match a shared event
+	 */
+	event = perf_event_create_kernel_shared_check(attr, cpu,
+				 task, overflow_handler, context);
+	if (event)
+		return event;
+
+	/*
 	 * Get the target context (task or percpu):
 	 */
 
@@ -10117,6 +10260,11 @@
 	perf_unpin_context(ctx);
 	mutex_unlock(&ctx->mutex);
 
+	/*
+	 * Check if can add event to shared list
+	 */
+	perf_event_create_kernel_shared_add(attr, cpu,
+			 task, overflow_handler, context, event);
 	return event;
 
 err_unlock:
@@ -10940,10 +11088,21 @@
 
 void __init perf_event_init(void)
 {
-	int ret;
+	int ret, cpu;
 
 	idr_init(&pmu_idr);
 
+	shared_events = alloc_percpu(struct shared_events_str);
+	if (!shared_events) {
+		WARN(1, "alloc_percpu failed for shared_events struct");
+	} else {
+		for_each_possible_cpu(cpu) {
+			struct shared_events_str *shrd_events =
+				per_cpu_ptr(shared_events, cpu);
+
+			mutex_init(&shrd_events->list_mutex);
+		}
+	}
 	perf_event_init_all_cpus();
 	init_srcu_struct(&pmus_srcu);
 	perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);
diff --git a/kernel/extable.c b/kernel/extable.c
index e820cce..4f06fc3 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -66,7 +66,7 @@
 	return 0;
 }
 
-int core_kernel_text(unsigned long addr)
+int notrace core_kernel_text(unsigned long addr)
 {
 	if (addr >= (unsigned long)_stext &&
 	    addr < (unsigned long)_etext)
diff --git a/kernel/fork.c b/kernel/fork.c
index f90327b..39c0709 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1015,8 +1015,7 @@
 
 	mm = get_task_mm(task);
 	if (mm && mm != current->mm &&
-			!ptrace_may_access(task, mode) &&
-			!capable(CAP_SYS_RESOURCE)) {
+			!ptrace_may_access(task, mode)) {
 		mmput(mm);
 		mm = ERR_PTR(-EACCES);
 	}
@@ -1518,6 +1517,18 @@
 	if (!p)
 		goto fork_out;
 
+	/*
+	 * This _must_ happen before we call free_task(), i.e. before we jump
+	 * to any of the bad_fork_* labels. This is to avoid freeing
+	 * p->set_child_tid which is (ab)used as a kthread's data pointer for
+	 * kernel threads (PF_KTHREAD).
+	 */
+	p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
+	/*
+	 * Clear TID on mm_release()?
+	 */
+	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
+
 	ftrace_graph_init_task(p);
 
 	rt_mutex_init_task(p);
@@ -1679,11 +1690,6 @@
 		}
 	}
 
-	p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
-	/*
-	 * Clear TID on mm_release()?
-	 */
-	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
 #ifdef CONFIG_BLOCK
 	p->plug = NULL;
 #endif
diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c
index 007482b..4684b75 100644
--- a/kernel/irq/cpuhotplug.c
+++ b/kernel/irq/cpuhotplug.c
@@ -69,7 +69,7 @@
 	if (!c->irq_set_affinity) {
 		pr_debug("IRQ%u: unable to set affinity\n", d->irq);
 	} else {
-		int r = irq_do_set_affinity(d, affinity, false);
+		int r = irq_set_affinity_locked(d, affinity, false);
 		if (r)
 			pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n",
 					    d->irq, r);
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 037c321..38f7665 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -25,13 +25,6 @@
 #include <linux/vmalloc.h>
 #include "kexec_internal.h"
 
-/*
- * Declare these symbols weak so that if architecture provides a purgatory,
- * these will be overridden.
- */
-char __weak kexec_purgatory[0];
-size_t __weak kexec_purgatory_size = 0;
-
 static int kexec_calculate_store_digests(struct kimage *image);
 
 /* Architectures can provide this probe function */
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index 0a52315..f95fd2c 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -37,6 +37,8 @@
 };
 
 void kimage_file_post_load_cleanup(struct kimage *image);
+extern char kexec_purgatory[];
+extern size_t kexec_purgatory_size;
 #else /* CONFIG_KEXEC_FILE */
 static inline void kimage_file_post_load_cleanup(struct kimage *image) { }
 #endif /* CONFIG_KEXEC_FILE */
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 56583e7..e3944c4 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -1767,6 +1767,7 @@
 	if (READ_ONCE(rdp_leader->nocb_leader_sleep) || force) {
 		/* Prior smp_mb__after_atomic() orders against prior enqueue. */
 		WRITE_ONCE(rdp_leader->nocb_leader_sleep, false);
+		smp_mb(); /* ->nocb_leader_sleep before swake_up(). */
 		swake_up(&rdp_leader->nocb_wq);
 	}
 }
@@ -2021,6 +2022,7 @@
 	 * nocb_gp_head, where they await a grace period.
 	 */
 	gotcbs = false;
+	smp_mb(); /* wakeup before ->nocb_head reads. */
 	for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) {
 		rdp->nocb_gp_head = READ_ONCE(rdp->nocb_head);
 		if (!rdp->nocb_gp_head)
diff --git a/kernel/sched/boost.c b/kernel/sched/boost.c
index 1a3309b..1ccd19d 100644
--- a/kernel/sched/boost.c
+++ b/kernel/sched/boost.c
@@ -32,7 +32,7 @@
 {
 	struct rq *rq = cpu_rq(cpu);
 
-	if (!test_and_set_bit(BOOST_KICK, &rq->hmp_flags))
+	if (!test_and_set_bit(BOOST_KICK, &rq->walt_flags))
 		smp_send_reschedule(cpu);
 }
 
@@ -57,14 +57,14 @@
 	int cpu = smp_processor_id();
 	struct rq *rq = cpu_rq(cpu);
 
-	return test_bit(BOOST_KICK, &rq->hmp_flags);
+	return test_bit(BOOST_KICK, &rq->walt_flags);
 }
 
 void clear_boost_kick(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
 
-	clear_bit(BOOST_KICK, &rq->hmp_flags);
+	clear_bit(BOOST_KICK, &rq->walt_flags);
 }
 
 /*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 46e4643..7722ade 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1283,6 +1283,8 @@
 #endif
 #endif
 
+	trace_sched_migrate_task(p, new_cpu, task_util(p));
+
 	if (task_cpu(p) != new_cpu) {
 		if (p->sched_class->migrate_task_rq)
 			p->sched_class->migrate_task_rq(p);
@@ -1679,7 +1681,7 @@
 	return cpu;
 }
 
-void update_avg(u64 *avg, u64 sample)
+static void update_avg(u64 *avg, u64 sample)
 {
 	s64 diff = sample - *avg;
 	*avg += diff >> 3;
@@ -2187,9 +2189,6 @@
 		notif_required = true;
 	}
 
-	if (!__task_in_cum_window_demand(cpu_rq(cpu), p))
-		inc_cum_window_demand(cpu_rq(cpu), p, task_load(p));
-
 	note_task_waking(p, wallclock);
 #endif /* CONFIG_SMP */
 
@@ -2199,6 +2198,15 @@
 out:
 	raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
+	if (success && sched_predl) {
+		raw_spin_lock_irqsave(&cpu_rq(cpu)->lock, flags);
+		if (do_pl_notif(cpu_rq(cpu)))
+			cpufreq_update_util(cpu_rq(cpu),
+					    SCHED_CPUFREQ_WALT |
+					    SCHED_CPUFREQ_PL);
+		raw_spin_unlock_irqrestore(&cpu_rq(cpu)->lock, flags);
+	}
+
 	return success;
 }
 
@@ -2249,8 +2257,6 @@
 
 		update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 		update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
-		if (!__task_in_cum_window_demand(rq, p))
-			inc_cum_window_demand(rq, p, task_load(p));
 		cpufreq_update_util(rq, 0);
 		ttwu_activate(rq, p, ENQUEUE_WAKEUP);
 		note_task_waking(p, wallclock);
@@ -5952,13 +5958,7 @@
 		set_rq_online(rq);
 	raw_spin_unlock(&rq->lock);
 
-	/*
-	 * We might have been in tickless state. Clear NOHZ flags to avoid
-	 * us being kicked for helping out with balancing
-	 */
-	nohz_balance_clear_nohz_mask(cpu);
-
-	clear_hmp_request(cpu);
+	clear_walt_request(cpu);
 	local_irq_enable();
 	return 0;
 }
@@ -6691,6 +6691,9 @@
  * Build an iteration mask that can exclude certain CPUs from the upwards
  * domain traversal.
  *
+ * Only CPUs that can arrive at this group should be considered to continue
+ * balancing.
+ *
  * Asymmetric node setups can result in situations where the domain tree is of
  * unequal depth, make sure to skip domains that already cover the entire
  * range.
@@ -6702,18 +6705,31 @@
  */
 static void build_group_mask(struct sched_domain *sd, struct sched_group *sg)
 {
-	const struct cpumask *span = sched_domain_span(sd);
+	const struct cpumask *sg_span = sched_group_cpus(sg);
 	struct sd_data *sdd = sd->private;
 	struct sched_domain *sibling;
 	int i;
 
-	for_each_cpu(i, span) {
+	for_each_cpu(i, sg_span) {
 		sibling = *per_cpu_ptr(sdd->sd, i);
-		if (!cpumask_test_cpu(i, sched_domain_span(sibling)))
+
+		/*
+		 * Can happen in the asymmetric case, where these siblings are
+		 * unused. The mask will not be empty because those CPUs that
+		 * do have the top domain _should_ span the domain.
+		 */
+		if (!sibling->child)
+			continue;
+
+		/* If we would not end up here, we can't continue from here */
+		if (!cpumask_equal(sg_span, sched_domain_span(sibling->child)))
 			continue;
 
 		cpumask_set_cpu(i, sched_group_mask(sg));
 	}
+
+	/* We must not have empty masks here */
+	WARN_ON_ONCE(cpumask_empty(sched_group_mask(sg)));
 }
 
 /*
@@ -6737,7 +6753,7 @@
 
 	cpumask_clear(covered);
 
-	for_each_cpu(i, span) {
+	for_each_cpu_wrap(i, span, cpu) {
 		struct cpumask *sg_span;
 
 		if (cpumask_test_cpu(i, covered))
@@ -8068,7 +8084,7 @@
 	BUG_ON(rq->nr_running != 1);
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 
-	clear_hmp_request(cpu);
+	clear_walt_request(cpu);
 
 	calc_load_migrate(rq);
 	update_max_interval();
@@ -8078,22 +8094,6 @@
 }
 #endif
 
-#ifdef CONFIG_SCHED_SMT
-DEFINE_STATIC_KEY_FALSE(sched_smt_present);
-
-static void sched_init_smt(void)
-{
-	/*
-	 * We've enumerated all CPUs and will assume that if any CPU
-	 * has SMT siblings, CPU0 will too.
-	 */
-	if (cpumask_weight(cpu_smt_mask(0)) > 1)
-		static_branch_enable(&sched_smt_present);
-}
-#else
-static inline void sched_init_smt(void) { }
-#endif
-
 void __init sched_init_smp(void)
 {
 	cpumask_var_t non_isolated_cpus;
@@ -8125,9 +8125,6 @@
 
 	init_sched_rt_class();
 	init_sched_dl_class();
-
-	sched_init_smt();
-
 	sched_smp_initialized = true;
 }
 
@@ -8308,7 +8305,6 @@
 		rq->avg_idle = 2*sysctl_sched_migration_cost;
 		rq->max_idle_balance_cost = sysctl_sched_migration_cost;
 		rq->push_task = NULL;
-
 		walt_sched_init(rq);
 
 		INIT_LIST_HEAD(&rq->cfs_tasks);
@@ -9578,8 +9574,13 @@
 	wallclock = sched_ktime_clock();
 	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 	dequeue_task(rq, p, 0);
+	/*
+	 * task's contribution is already removed from the
+	 * cumulative window demand in dequeue. As the
+	 * task's stats are reset, the next enqueue does
+	 * not change the cumulative window demand.
+	 */
 	reset_task_stats(p);
-	dec_cum_window_demand(rq, p);
 	p->ravg.mark_start = wallclock;
 	p->ravg.sum_history[0] = EXITING_TASK_MARKER;
 	free_task_load_ptrs(p);
@@ -9589,3 +9590,5 @@
 	task_rq_unlock(rq, p, &rf);
 }
 #endif /* CONFIG_SCHED_WALT */
+
+__read_mostly bool sched_predl;
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index 4c3bf526..e56af41 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -13,7 +13,6 @@
 #define pr_fmt(fmt)	"core_ctl: " fmt
 
 #include <linux/init.h>
-#include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/cpufreq.h>
@@ -877,21 +876,18 @@
 	return 0;
 }
 
-static int __ref cpu_callback(struct notifier_block *nfb,
-				unsigned long action, void *hcpu)
+static int isolation_cpuhp_state(unsigned int cpu,  bool online)
 {
-	uint32_t cpu = (uintptr_t)hcpu;
 	struct cpu_data *state = &per_cpu(cpu_state, cpu);
 	struct cluster_data *cluster = state->cluster;
 	unsigned int need;
-	bool do_wakeup, unisolated = false;
+	bool do_wakeup = false, unisolated = false;
 	unsigned long flags;
 
 	if (unlikely(!cluster || !cluster->inited))
-		return NOTIFY_DONE;
+		return 0;
 
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_ONLINE:
+	if (online) {
 		cluster->active_cpus = get_active_cpu_count(cluster);
 
 		/*
@@ -901,9 +897,7 @@
 		 * reject trying to online CPUs.
 		 */
 		move_cpu_lru(state);
-		break;
-
-	case CPU_DEAD:
+	} else {
 		/*
 		 * We don't want to have a CPU both offline and isolated.
 		 * So unisolate a CPU that went down if it was isolated by us.
@@ -919,9 +913,6 @@
 
 		state->busy = 0;
 		cluster->active_cpus = get_active_cpu_count(cluster);
-		break;
-	default:
-		return NOTIFY_DONE;
 	}
 
 	need = apply_limits(cluster, cluster->need_cpus);
@@ -933,12 +924,18 @@
 	if (do_wakeup)
 		wake_up_core_ctl_thread(cluster);
 
-	return NOTIFY_OK;
+	return 0;
 }
 
-static struct notifier_block __refdata cpu_notifier = {
-	.notifier_call = cpu_callback,
-};
+static int core_ctl_isolation_online_cpu(unsigned int cpu)
+{
+	return isolation_cpuhp_state(cpu, true);
+}
+
+static int core_ctl_isolation_dead_cpu(unsigned int cpu)
+{
+	return isolation_cpuhp_state(cpu, false);
+}
 
 /* ============================ init code ============================== */
 
@@ -1068,7 +1065,13 @@
 	if (should_skip(cpu_possible_mask))
 		return 0;
 
-	register_cpu_notifier(&cpu_notifier);
+	cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+			"core_ctl/isolation:online",
+			core_ctl_isolation_online_cpu, NULL);
+
+	cpuhp_setup_state_nocalls(CPUHP_CORE_CTL_ISOLATION_DEAD,
+			"core_ctl/isolation:dead",
+			NULL, core_ctl_isolation_dead_cpu);
 
 	for_each_cpu(cpu, &cpus) {
 		int ret;
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index dce76d1..1b53241 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -15,7 +15,7 @@
 #include <linux/kthread.h>
 #include <linux/slab.h>
 #include <trace/events/power.h>
-
+#include <linux/sched/sysctl.h>
 #include "sched.h"
 
 #define SUGOV_KTHREAD_PRIORITY	50
@@ -216,6 +216,10 @@
 				u64 upto)
 {
 	u64 delta_ns, cycles;
+
+	if (unlikely(!sysctl_sched_use_walt_cpu_util))
+		return;
+
 	/* Track cycles in current window */
 	delta_ns = upto - sg_policy->last_cyc_update_time;
 	cycles = (prev_freq * delta_ns) / (NSEC_PER_SEC / KHZ);
@@ -229,6 +233,9 @@
 	u64 last_ws = sg_policy->last_ws;
 	unsigned int avg_freq;
 
+	if (unlikely(!sysctl_sched_use_walt_cpu_util))
+		return;
+
 	WARN_ON(curr_ws < last_ws);
 	if (curr_ws <= last_ws)
 		return;
@@ -259,6 +266,9 @@
 	unsigned long cpu_util = sg_cpu->util;
 	bool is_hiload;
 
+	if (unlikely(!sysctl_sched_use_walt_cpu_util))
+		return;
+
 	is_hiload = (cpu_util >= mult_frac(sg_policy->avg_cap,
 					   HISPEED_LOAD,
 					   100));
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 10a807c..08d4511 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -19,41 +19,6 @@
 
 #include <linux/slab.h>
 
-#ifdef CONFIG_SCHED_WALT
-
-static void
-inc_hmp_sched_stats_dl(struct rq *rq, struct task_struct *p)
-{
-	inc_cumulative_runnable_avg(&rq->hmp_stats, p);
-}
-
-static void
-dec_hmp_sched_stats_dl(struct rq *rq, struct task_struct *p)
-{
-	dec_cumulative_runnable_avg(&rq->hmp_stats, p);
-}
-
-static void
-fixup_hmp_sched_stats_dl(struct rq *rq, struct task_struct *p,
-			 u32 new_task_load, u32 new_pred_demand)
-{
-	s64 task_load_delta = (s64)new_task_load - task_load(p);
-	s64 pred_demand_delta = PRED_DEMAND_DELTA;
-
-	fixup_cumulative_runnable_avg(&rq->hmp_stats, p, task_load_delta,
-				      pred_demand_delta);
-}
-
-#else	/* CONFIG_SCHED_WALT */
-
-static inline void
-inc_hmp_sched_stats_dl(struct rq *rq, struct task_struct *p) { }
-
-static inline void
-dec_hmp_sched_stats_dl(struct rq *rq, struct task_struct *p) { }
-
-#endif	/* CONFIG_SCHED_WALT */
-
 struct dl_bandwidth def_dl_bandwidth;
 
 static inline struct task_struct *dl_task_of(struct sched_dl_entity *dl_se)
@@ -865,7 +830,7 @@
 	WARN_ON(!dl_prio(prio));
 	dl_rq->dl_nr_running++;
 	add_nr_running(rq_of_dl_rq(dl_rq), 1);
-	inc_hmp_sched_stats_dl(rq_of_dl_rq(dl_rq), dl_task_of(dl_se));
+	walt_inc_cumulative_runnable_avg(rq_of_dl_rq(dl_rq), dl_task_of(dl_se));
 
 	inc_dl_deadline(dl_rq, deadline);
 	inc_dl_migration(dl_se, dl_rq);
@@ -880,7 +845,7 @@
 	WARN_ON(!dl_rq->dl_nr_running);
 	dl_rq->dl_nr_running--;
 	sub_nr_running(rq_of_dl_rq(dl_rq), 1);
-	dec_hmp_sched_stats_dl(rq_of_dl_rq(dl_rq), dl_task_of(dl_se));
+	walt_dec_cumulative_runnable_avg(rq_of_dl_rq(dl_rq), dl_task_of(dl_se));
 
 	dec_dl_deadline(dl_rq, dl_se->deadline);
 	dec_dl_migration(dl_se, dl_rq);
@@ -1845,7 +1810,7 @@
 
 	.update_curr		= update_curr_dl,
 #ifdef CONFIG_SCHED_WALT
-	.fixup_hmp_sched_stats	= fixup_hmp_sched_stats_dl,
+	.fixup_walt_sched_stats	= fixup_walt_sched_stats_common,
 #endif
 };
 
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index b520691..0f8c0b2 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -600,12 +600,6 @@
 			cfs_rq->throttle_count);
 	SEQ_printf(m, "  .%-30s: %d\n", "runtime_enabled",
 			cfs_rq->runtime_enabled);
-#ifdef CONFIG_SCHED_WALT
-	SEQ_printf(m, "  .%-30s: %d\n", "nr_big_tasks",
-			cfs_rq->hmp_stats.nr_big_tasks);
-	SEQ_printf(m, "  .%-30s: %llu\n", "cumulative_runnable_avg",
-			cfs_rq->hmp_stats.cumulative_runnable_avg);
-#endif
 #endif
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
@@ -706,10 +700,10 @@
 	P(cluster->max_freq);
 	P(cluster->exec_scale_factor);
 #ifdef CONFIG_SCHED_WALT
-	P(hmp_stats.nr_big_tasks);
+	P(walt_stats.nr_big_tasks);
 #endif
-	SEQ_printf(m, "  .%-30s: %llu\n", "hmp_stats.cumulative_runnable_avg",
-			rq->hmp_stats.cumulative_runnable_avg);
+	SEQ_printf(m, "  .%-30s: %llu\n", "walt_stats.cumulative_runnable_avg",
+			rq->walt_stats.cumulative_runnable_avg);
 #endif
 #undef P
 #undef PN
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e0ab4d6..62a29ed 100755
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -37,50 +37,39 @@
 #include "walt.h"
 #include <trace/events/sched.h>
 
-/* QHMP/Zone forward declarations */
-
-struct lb_env;
-struct sd_lb_stats;
-struct sg_lb_stats;
-
 #ifdef CONFIG_SCHED_WALT
-static void fixup_hmp_sched_stats_fair(struct rq *rq, struct task_struct *p,
-				       u32 new_task_load, u32 new_pred_demand);
-#endif
 
-static inline void inc_cfs_rq_hmp_stats(struct cfs_rq *cfs_rq,
-				 struct task_struct *p, int change_cra) { }
-static inline void dec_cfs_rq_hmp_stats(struct cfs_rq *cfs_rq,
-				 struct task_struct *p, int change_cra) { }
-static inline void dec_throttled_cfs_rq_hmp_stats(
-				struct hmp_sched_stats *stats,
-				struct cfs_rq *cfs_rq) { }
-static inline void inc_throttled_cfs_rq_hmp_stats(
-				struct hmp_sched_stats *stats,
-				struct cfs_rq *cfs_rq) { }
-static inline void init_cfs_rq_hmp_stats(struct cfs_rq *cfs_rq) { }
-
-#ifdef CONFIG_SMP
-
-static inline int
-bail_inter_cluster_balance(struct lb_env *env, struct sd_lb_stats *sds)
-{
-	return 0;
-}
-
-static inline bool update_sd_pick_busiest_active_balance(struct lb_env *env,
-						  struct sd_lb_stats *sds,
-						  struct sched_group *sg,
-						  struct sg_lb_stats *sgs)
-{
-	return false;
-}
-#endif /* CONFIG_SMP */
-
-#ifdef CONFIG_SCHED_WALT
 static inline bool task_fits_max(struct task_struct *p, int cpu);
+static void walt_fixup_sched_stats_fair(struct rq *rq, struct task_struct *p,
+					u32 new_task_load, u32 new_pred_demand);
+static void walt_fixup_nr_big_tasks(struct rq *rq, struct task_struct *p,
+				    int delta, bool inc);
+#endif /* CONFIG_SCHED_WALT */
+
+#if defined(CONFIG_SCHED_WALT) && defined(CONFIG_CFS_BANDWIDTH)
+
+static void walt_init_cfs_rq_stats(struct cfs_rq *cfs_rq);
+static void walt_inc_cfs_rq_stats(struct cfs_rq *cfs_rq,
+				  struct task_struct *p);
+static void walt_dec_cfs_rq_stats(struct cfs_rq *cfs_rq,
+				  struct task_struct *p);
+static void walt_inc_throttled_cfs_rq_stats(struct walt_sched_stats *stats,
+					    struct cfs_rq *cfs_rq);
+static void walt_dec_throttled_cfs_rq_stats(struct walt_sched_stats *stats,
+					    struct cfs_rq *cfs_rq);
+#else
+static inline void walt_init_cfs_rq_stats(struct cfs_rq *cfs_rq) {}
+static inline void
+walt_inc_cfs_rq_stats(struct cfs_rq *cfs_rq, struct task_struct *p) {}
+static inline void
+walt_dec_cfs_rq_stats(struct cfs_rq *cfs_rq, struct task_struct *p) {}
+
+#define walt_inc_throttled_cfs_rq_stats(...)
+#define walt_dec_throttled_cfs_rq_stats(...)
+
 #endif
 
+
 /*
  * Targeted preemption latency for CPU-bound tasks:
  * (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds)
@@ -4047,7 +4036,7 @@
 		if (dequeue)
 			dequeue_entity(qcfs_rq, se, DEQUEUE_SLEEP);
 		qcfs_rq->h_nr_running -= task_delta;
-		dec_throttled_cfs_rq_hmp_stats(&qcfs_rq->hmp_stats, cfs_rq);
+		walt_dec_throttled_cfs_rq_stats(&qcfs_rq->walt_stats, cfs_rq);
 
 		if (qcfs_rq->load.weight)
 			dequeue = 0;
@@ -4055,7 +4044,7 @@
 
 	if (!se) {
 		sub_nr_running(rq, task_delta);
-		dec_throttled_cfs_rq_hmp_stats(&rq->hmp_stats, cfs_rq);
+		walt_dec_throttled_cfs_rq_stats(&rq->walt_stats, cfs_rq);
 	}
 
 	cfs_rq->throttled = 1;
@@ -4077,11 +4066,6 @@
 		start_cfs_bandwidth(cfs_b);
 
 	raw_spin_unlock(&cfs_b->lock);
-
-	/* Log effect on hmp stats after throttling */
-	trace_sched_cpu_load_cgroup(rq, idle_cpu(cpu_of(rq)),
-				sched_irqload(cpu_of(rq)),
-				power_cost(cpu_of(rq), 0));
 }
 
 void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
@@ -4119,7 +4103,7 @@
 		if (enqueue)
 			enqueue_entity(cfs_rq, se, ENQUEUE_WAKEUP);
 		cfs_rq->h_nr_running += task_delta;
-		inc_throttled_cfs_rq_hmp_stats(&cfs_rq->hmp_stats, tcfs_rq);
+		walt_inc_throttled_cfs_rq_stats(&cfs_rq->walt_stats, tcfs_rq);
 
 		if (cfs_rq_throttled(cfs_rq))
 			break;
@@ -4127,17 +4111,12 @@
 
 	if (!se) {
 		add_nr_running(rq, task_delta);
-		inc_throttled_cfs_rq_hmp_stats(&rq->hmp_stats, tcfs_rq);
+		walt_inc_throttled_cfs_rq_stats(&rq->walt_stats, tcfs_rq);
 	}
 
 	/* determine whether we need to wake up potentially idle cpu */
 	if (rq->curr == rq->idle && rq->cfs.nr_running)
 		resched_curr(rq);
-
-	/* Log effect on hmp stats after un-throttling */
-	trace_sched_cpu_load_cgroup(rq, idle_cpu(cpu_of(rq)),
-				sched_irqload(cpu_of(rq)),
-				power_cost(cpu_of(rq), 0));
 }
 
 static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b,
@@ -4475,7 +4454,7 @@
 {
 	cfs_rq->runtime_enabled = 0;
 	INIT_LIST_HEAD(&cfs_rq->throttled_list);
-	init_cfs_rq_hmp_stats(cfs_rq);
+	walt_init_cfs_rq_stats(cfs_rq);
 }
 
 void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
@@ -4670,6 +4649,9 @@
 	int task_wakeup = flags & ENQUEUE_WAKEUP;
 #endif
 
+#ifdef CONFIG_SCHED_WALT
+	p->misfit = !task_fits_max(p, rq->cpu);
+#endif
 	/*
 	 * If in_iowait is set, the code below may not trigger any cpufreq
 	 * utilization updates, so do it here explicitly with the IOWAIT flag
@@ -4693,7 +4675,7 @@
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 		cfs_rq->h_nr_running++;
-		inc_cfs_rq_hmp_stats(cfs_rq, p, 1);
+		walt_inc_cfs_rq_stats(cfs_rq, p);
 
 		flags = ENQUEUE_WAKEUP;
 	}
@@ -4701,7 +4683,7 @@
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
 		cfs_rq->h_nr_running++;
-		inc_cfs_rq_hmp_stats(cfs_rq, p, 1);
+		walt_inc_cfs_rq_stats(cfs_rq, p);
 
 		if (cfs_rq_throttled(cfs_rq))
 			break;
@@ -4712,10 +4694,7 @@
 
 	if (!se) {
 		add_nr_running(rq, 1);
-#ifdef CONFIG_SCHED_WALT
-		p->misfit = !task_fits_max(p, rq->cpu);
-#endif
-		inc_rq_hmp_stats(rq, p, 1);
+		inc_rq_walt_stats(rq, p);
 	}
 
 #ifdef CONFIG_SMP
@@ -4771,7 +4750,7 @@
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 		cfs_rq->h_nr_running--;
-		dec_cfs_rq_hmp_stats(cfs_rq, p, 1);
+		walt_dec_cfs_rq_stats(cfs_rq, p);
 
 		/* Don't dequeue parent if it has other entities besides us */
 		if (cfs_rq->load.weight) {
@@ -4791,7 +4770,7 @@
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
 		cfs_rq->h_nr_running--;
-		dec_cfs_rq_hmp_stats(cfs_rq, p, 1);
+		walt_dec_cfs_rq_stats(cfs_rq, p);
 
 		if (cfs_rq_throttled(cfs_rq))
 			break;
@@ -4802,7 +4781,7 @@
 
 	if (!se) {
 		sub_nr_running(rq, 1);
-		dec_rq_hmp_stats(rq, p, 1);
+		dec_rq_walt_stats(rq, p);
 	}
 
 #ifdef CONFIG_SMP
@@ -5344,18 +5323,6 @@
 	return DIV_ROUND_UP(util << SCHED_CAPACITY_SHIFT, capacity);
 }
 
-static inline int task_util(struct task_struct *p)
-{
-#ifdef CONFIG_SCHED_WALT
-	if (!walt_disabled && sysctl_sched_use_walt_task_util) {
-		u64 demand = p->ravg.demand;
-
-		return (demand << 10) / sched_ravg_window;
-	}
-#endif
-	return p->se.avg.util_avg;
-}
-
 static inline bool
 bias_to_waker_cpu(struct task_struct *p, int cpu, struct cpumask *rtg_target)
 {
@@ -6177,43 +6144,6 @@
 	return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu;
 }
 
-/*
- * Implement a for_each_cpu() variant that starts the scan at a given cpu
- * (@start), and wraps around.
- *
- * This is used to scan for idle CPUs; such that not all CPUs looking for an
- * idle CPU find the same CPU. The down-side is that tasks tend to cycle
- * through the LLC domain.
- *
- * Especially tbench is found sensitive to this.
- */
-
-static int cpumask_next_wrap(int n, const struct cpumask *mask, int start, int *wrapped)
-{
-	int next;
-
-again:
-	next = find_next_bit(cpumask_bits(mask), nr_cpumask_bits, n+1);
-
-	if (*wrapped) {
-		if (next >= start)
-			return nr_cpumask_bits;
-	} else {
-		if (next >= nr_cpumask_bits) {
-			*wrapped = 1;
-			n = -1;
-			goto again;
-		}
-	}
-
-	return next;
-}
-
-#define for_each_cpu_wrap(cpu, mask, start, wrap)				\
-	for ((wrap) = 0, (cpu) = (start)-1;					\
-		(cpu) = cpumask_next_wrap((cpu), (mask), (start), &(wrap)),	\
-		(cpu) < nr_cpumask_bits; )
-
 #ifdef CONFIG_SCHED_SMT
 
 static inline void set_idle_cores(int cpu, int val)
@@ -6243,7 +6173,7 @@
  * Since SMT siblings share all cache levels, inspecting this limited remote
  * state should be fairly cheap.
  */
-void __update_idle_core(struct rq *rq)
+void update_idle_core(struct rq *rq)
 {
 	int core = cpu_of(rq);
 	int cpu;
@@ -6273,17 +6203,14 @@
 static int select_idle_core(struct task_struct *p, struct sched_domain *sd, int target)
 {
 	struct cpumask *cpus = this_cpu_cpumask_var_ptr(select_idle_mask);
-	int core, cpu, wrap;
-
-	if (!static_branch_likely(&sched_smt_present))
-		return -1;
+	int core, cpu;
 
 	if (!test_idle_cores(target, false))
 		return -1;
 
 	cpumask_and(cpus, sched_domain_span(sd), tsk_cpus_allowed(p));
 
-	for_each_cpu_wrap(core, cpus, target, wrap) {
+	for_each_cpu_wrap(core, cpus, target) {
 		bool idle = true;
 
 		for_each_cpu(cpu, cpu_smt_mask(core)) {
@@ -6311,9 +6238,6 @@
 {
 	int cpu;
 
-	if (!static_branch_likely(&sched_smt_present))
-		return -1;
-
 	for_each_cpu(cpu, cpu_smt_mask(target)) {
 		if (!cpumask_test_cpu(cpu, tsk_cpus_allowed(p)))
 			continue;
@@ -6351,7 +6275,7 @@
 	u64 avg_cost, avg_idle = this_rq()->avg_idle;
 	u64 time, cost;
 	s64 delta;
-	int cpu, wrap;
+	int cpu;
 
 	this_sd = rcu_dereference(*this_cpu_ptr(&sd_llc));
 	if (!this_sd)
@@ -6368,7 +6292,7 @@
 
 	time = local_clock();
 
-	for_each_cpu_wrap(cpu, sched_domain_span(sd), target, wrap) {
+	for_each_cpu_wrap(cpu, sched_domain_span(sd), target) {
 		if (!cpumask_test_cpu(cpu, tsk_cpus_allowed(p)))
 			continue;
 		if (cpu_isolated(cpu))
@@ -8657,9 +8581,6 @@
 {
 	struct sg_lb_stats *busiest = &sds->busiest_stat;
 
-	if (update_sd_pick_busiest_active_balance(env, sds, sg, sgs))
-		return true;
-
 	if (sgs->group_type > busiest->group_type)
 		return true;
 
@@ -9123,9 +9044,6 @@
 	if (env->flags & LBF_BIG_TASK_ACTIVE_BALANCE)
 		goto force_balance;
 
-	if (bail_inter_cluster_balance(env, &sds))
-		goto out_balanced;
-
 	sds.avg_load = (SCHED_CAPACITY_SCALE * sds.total_load)
 						/ sds.total_capacity;
 
@@ -9970,6 +9888,8 @@
 	if (sd) {
 		cpumask_and(&cpumask, nohz.idle_cpus_mask,
 			    sched_domain_span(sd));
+		cpumask_andnot(&cpumask, &cpumask,
+			    cpu_isolated_mask);
 		ilb = cpumask_first(&cpumask);
 	}
 	rcu_read_unlock();
@@ -9978,8 +9898,11 @@
 		if (!energy_aware() ||
 		    (capacity_orig_of(cpu) ==
 		     cpu_rq(cpu)->rd->max_cpu_capacity.val ||
-		     cpu_overutilized(cpu)))
-			ilb = cpumask_first(nohz.idle_cpus_mask);
+		     cpu_overutilized(cpu))) {
+			cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
+			    cpu_isolated_mask);
+			ilb = cpumask_first(&cpumask);
+		}
 	}
 
 	if (ilb < nr_cpu_ids && idle_cpu(ilb))
@@ -10016,21 +9939,16 @@
 	return;
 }
 
-void nohz_balance_clear_nohz_mask(int cpu)
-{
-	if (likely(cpumask_test_cpu(cpu, nohz.idle_cpus_mask))) {
-		cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
-		atomic_dec(&nohz.nr_cpus);
-	}
-}
-
 void nohz_balance_exit_idle(unsigned int cpu)
 {
 	if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
 		/*
 		 * Completely isolated CPUs don't ever set, so we must test.
 		 */
-		nohz_balance_clear_nohz_mask(cpu);
+		if (likely(cpumask_test_cpu(cpu, nohz.idle_cpus_mask))) {
+			cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+			atomic_dec(&nohz.nr_cpus);
+		}
 		clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
 	}
 }
@@ -10305,6 +10223,7 @@
 	int nr_busy;
 	int cpu = rq->cpu;
 	bool kick = false;
+	cpumask_t cpumask;
 
 	if (unlikely(rq->idle_balance))
 		return false;
@@ -10320,7 +10239,8 @@
 	 * None are in tickless mode and hence no need for NOHZ idle load
 	 * balancing.
 	 */
-	if (likely(!atomic_read(&nohz.nr_cpus)))
+	cpumask_andnot(&cpumask, nohz.idle_cpus_mask, cpu_isolated_mask);
+	if (cpumask_empty(&cpumask))
 		return false;
 
 	if (time_before(now, nohz.next_balance))
@@ -10354,8 +10274,7 @@
 	}
 
 	sd = rcu_dereference(per_cpu(sd_asym, cpu));
-	if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
-				  sched_domain_span(sd)) < cpu)) {
+	if (sd && (cpumask_first_and(&cpumask, sched_domain_span(sd)) < cpu)) {
 		kick = true;
 		goto unlock;
 	}
@@ -10379,6 +10298,13 @@
 						CPU_IDLE : CPU_NOT_IDLE;
 
 	/*
+	 * Since core isolation doesn't update nohz.idle_cpus_mask, there
+	 * is a possibility this nohz kicked cpu could be isolated. Hence
+	 * return if the cpu is isolated.
+	 */
+	if (cpu_isolated(this_rq->cpu))
+		return;
+	/*
 	 * If this cpu has a pending nohz_balance_kick, then do the
 	 * balancing on behalf of the other idle cpus whose ticks are
 	 * stopped. Do nohz_idle_balance *before* rebalance_domains to
@@ -10458,7 +10384,7 @@
 	rq->misfit_task = misfit;
 
 	if (old_misfit != misfit) {
-		adjust_nr_big_tasks(&rq->hmp_stats, 1, misfit);
+		walt_fixup_nr_big_tasks(rq, curr, 1, misfit);
 		curr->misfit = misfit;
 	}
 #endif
@@ -10923,7 +10849,7 @@
 	.task_change_group	= task_change_group_fair,
 #endif
 #ifdef CONFIG_SCHED_WALT
-	.fixup_hmp_sched_stats	= fixup_hmp_sched_stats_fair,
+	.fixup_walt_sched_stats	= walt_fixup_sched_stats_fair,
 #endif
 };
 
@@ -10973,70 +10899,68 @@
 }
 
 /* WALT sched implementation begins here */
+#ifdef CONFIG_SCHED_WALT
 
-#if defined(CONFIG_SCHED_WALT) && defined(CONFIG_CFS_BANDWIDTH)
-static inline struct task_group *next_task_group(struct task_group *tg)
+#ifdef CONFIG_CFS_BANDWIDTH
+
+static void walt_init_cfs_rq_stats(struct cfs_rq *cfs_rq)
 {
-	tg = list_entry_rcu(tg->list.next, typeof(struct task_group), list);
-
-	return (&tg->list == &task_groups) ? NULL : tg;
+	cfs_rq->walt_stats.nr_big_tasks = 0;
+	cfs_rq->walt_stats.cumulative_runnable_avg = 0;
+	cfs_rq->walt_stats.pred_demands_sum = 0;
 }
 
-/* Iterate over all cfs_rq in a cpu */
-#define for_each_cfs_rq(cfs_rq, tg, cpu)	\
-	for (tg = container_of(&task_groups, struct task_group, list);	\
-		((tg = next_task_group(tg)) && (cfs_rq = tg->cfs_rq[cpu]));)
-
-void reset_cfs_rq_hmp_stats(int cpu, int reset_cra)
+static void walt_inc_cfs_rq_stats(struct cfs_rq *cfs_rq, struct task_struct *p)
 {
-	struct task_group *tg;
-	struct cfs_rq *cfs_rq;
-
-	rcu_read_lock();
-
-	for_each_cfs_rq(cfs_rq, tg, cpu)
-		reset_hmp_stats(&cfs_rq->hmp_stats, reset_cra);
-
-	rcu_read_unlock();
+	inc_nr_big_task(&cfs_rq->walt_stats, p);
+	fixup_cumulative_runnable_avg(&cfs_rq->walt_stats, p->ravg.demand,
+				      p->ravg.pred_demand);
 }
 
-static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq);
-
-static void inc_cfs_rq_hmp_stats(struct cfs_rq *cfs_rq,
-	 struct task_struct *p, int change_cra);
-static void dec_cfs_rq_hmp_stats(struct cfs_rq *cfs_rq,
-	 struct task_struct *p, int change_cra);
-
-/* Add task's contribution to a cpu' HMP statistics */
-void inc_hmp_sched_stats_fair(struct rq *rq,
-			struct task_struct *p, int change_cra)
+static void walt_dec_cfs_rq_stats(struct cfs_rq *cfs_rq, struct task_struct *p)
 {
-	struct cfs_rq *cfs_rq;
-	struct sched_entity *se = &p->se;
+	dec_nr_big_task(&cfs_rq->walt_stats, p);
+	fixup_cumulative_runnable_avg(&cfs_rq->walt_stats, -(s64)p->ravg.demand,
+				      -(s64)p->ravg.pred_demand);
+}
+
+static void walt_inc_throttled_cfs_rq_stats(struct walt_sched_stats *stats,
+					    struct cfs_rq *tcfs_rq)
+{
+	struct rq *rq = rq_of(tcfs_rq);
+
+	stats->nr_big_tasks += tcfs_rq->walt_stats.nr_big_tasks;
+	fixup_cumulative_runnable_avg(stats,
+				tcfs_rq->walt_stats.cumulative_runnable_avg,
+				tcfs_rq->walt_stats.pred_demands_sum);
+
+	if (stats == &rq->walt_stats)
+		walt_fixup_cum_window_demand(rq,
+			tcfs_rq->walt_stats.cumulative_runnable_avg);
+
+}
+
+static void walt_dec_throttled_cfs_rq_stats(struct walt_sched_stats *stats,
+					    struct cfs_rq *tcfs_rq)
+{
+	struct rq *rq = rq_of(tcfs_rq);
+
+	stats->nr_big_tasks -= tcfs_rq->walt_stats.nr_big_tasks;
+	fixup_cumulative_runnable_avg(stats,
+				-tcfs_rq->walt_stats.cumulative_runnable_avg,
+				-tcfs_rq->walt_stats.pred_demands_sum);
 
 	/*
-	 * Although below check is not strictly required  (as
-	 * inc/dec_nr_big_task and inc/dec_cumulative_runnable_avg called
-	 * from inc_cfs_rq_hmp_stats() have similar checks), we gain a bit on
-	 * efficiency by short-circuiting for_each_sched_entity() loop when
-	 * sched_disable_window_stats
+	 * We remove the throttled cfs_rq's tasks's contribution from the
+	 * cumulative window demand so that the same can be added
+	 * unconditionally when the cfs_rq is unthrottled.
 	 */
-	if (sched_disable_window_stats)
-		return;
-
-	for_each_sched_entity(se) {
-		cfs_rq = cfs_rq_of(se);
-		inc_cfs_rq_hmp_stats(cfs_rq, p, change_cra);
-		if (cfs_rq_throttled(cfs_rq))
-			break;
-	}
-
-	/* Update rq->hmp_stats only if we didn't find any throttled cfs_rq */
-	if (!se)
-		inc_rq_hmp_stats(rq, p, change_cra);
+	if (stats == &rq->walt_stats)
+		walt_fixup_cum_window_demand(rq,
+			-tcfs_rq->walt_stats.cumulative_runnable_avg);
 }
 
-static void fixup_hmp_sched_stats_fair(struct rq *rq, struct task_struct *p,
+static void walt_fixup_sched_stats_fair(struct rq *rq, struct task_struct *p,
 				       u32 new_task_load, u32 new_pred_demand)
 {
 	struct cfs_rq *cfs_rq;
@@ -11047,47 +10971,91 @@
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
 
-		fixup_cumulative_runnable_avg(&cfs_rq->hmp_stats, p,
+		fixup_cumulative_runnable_avg(&cfs_rq->walt_stats,
 					      task_load_delta,
 					      pred_demand_delta);
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 	}
 
-	/* Fix up rq->hmp_stats only if we didn't find any throttled cfs_rq */
+	/* Fix up rq->walt_stats only if we didn't find any throttled cfs_rq */
 	if (!se) {
-		fixup_cumulative_runnable_avg(&rq->hmp_stats, p,
+		fixup_cumulative_runnable_avg(&rq->walt_stats,
 					      task_load_delta,
 					      pred_demand_delta);
+		walt_fixup_cum_window_demand(rq, task_load_delta);
 	}
 }
 
-#elif defined(CONFIG_SCHED_WALT)
-
-inline void reset_cfs_rq_hmp_stats(int cpu, int reset_cra) { }
-
-static void
-fixup_hmp_sched_stats_fair(struct rq *rq, struct task_struct *p,
-			   u32 new_task_load, u32 new_pred_demand)
+static void walt_fixup_nr_big_tasks(struct rq *rq, struct task_struct *p,
+				    int delta, bool inc)
 {
-	s64 task_load_delta = (s64)new_task_load - task_load(p);
-	s64 pred_demand_delta = PRED_DEMAND_DELTA;
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &p->se;
 
-	fixup_cumulative_runnable_avg(&rq->hmp_stats, p, task_load_delta,
-				      pred_demand_delta);
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+
+		cfs_rq->walt_stats.nr_big_tasks += inc ? delta : -delta;
+		BUG_ON(cfs_rq->walt_stats.nr_big_tasks < 0);
+
+		if (cfs_rq_throttled(cfs_rq))
+			break;
+	}
+
+	/* Fix up rq->walt_stats only if we didn't find any throttled cfs_rq */
+	if (!se)
+		walt_adjust_nr_big_tasks(rq, delta, inc);
 }
 
-static inline int task_will_be_throttled(struct task_struct *p)
+/*
+ * Check if task is part of a hierarchy where some cfs_rq does not have any
+ * runtime left.
+ *
+ * We can't rely on throttled_hierarchy() to do this test, as
+ * cfs_rq->throttle_count will not be updated yet when this function is called
+ * from scheduler_tick()
+ */
+static int task_will_be_throttled(struct task_struct *p)
 {
+	struct sched_entity *se = &p->se;
+	struct cfs_rq *cfs_rq;
+
+	if (!cfs_bandwidth_used())
+		return 0;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		if (!cfs_rq->runtime_enabled)
+			continue;
+		if (cfs_rq->runtime_remaining <= 0)
+			return 1;
+	}
+
 	return 0;
 }
 
-void inc_hmp_sched_stats_fair(struct rq *rq,
-			struct task_struct *p, int change_cra)
+#else /* CONFIG_CFS_BANDWIDTH */
+
+static void walt_fixup_sched_stats_fair(struct rq *rq, struct task_struct *p,
+				       u32 new_task_load, u32 new_pred_demand)
 {
-	inc_nr_big_task(&rq->hmp_stats, p);
+	fixup_walt_sched_stats_common(rq, p, new_task_load, new_pred_demand);
 }
 
+static void walt_fixup_nr_big_tasks(struct rq *rq, struct task_struct *p,
+				    int delta, bool inc)
+{
+	walt_adjust_nr_big_tasks(rq, delta, inc);
+}
+
+static int task_will_be_throttled(struct task_struct *p)
+{
+	return false;
+}
+
+#endif /* CONFIG_CFS_BANDWIDTH */
+
 static inline int
 kick_active_balance(struct rq *rq, struct task_struct *p, int new_cpu)
 {
@@ -11108,17 +11076,6 @@
 	return rc;
 }
 
-#else
-
-static inline int task_will_be_throttled(struct task_struct *p)
-{
-	return 0;
-}
-
-#endif
-
-#if defined(CONFIG_SCHED_WALT)
-
 static DEFINE_RAW_SPINLOCK(migration_lock);
 void check_for_migration(struct rq *rq, struct task_struct *p)
 {
@@ -11131,6 +11088,9 @@
 		    rq->curr->nr_cpus_allowed == 1)
 			return;
 
+		if (task_will_be_throttled(p))
+			return;
+
 		raw_spin_lock(&migration_lock);
 		rcu_read_lock();
 		new_cpu = energy_aware_wake_cpu(p, cpu, 0);
diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c
index b852cbe..5405d3f 100644
--- a/kernel/sched/idle_task.c
+++ b/kernel/sched/idle_task.c
@@ -78,14 +78,6 @@
 {
 }
 
-#ifdef CONFIG_SCHED_WALT
-static void
-fixup_hmp_sched_stats_idle(struct rq *rq, struct task_struct *p,
-			   u32 new_task_load, u32 new_pred_demand)
-{
-}
-#endif
-
 /*
  * Simple, special scheduling class for the per-CPU idle tasks:
  */
@@ -114,7 +106,4 @@
 	.prio_changed		= prio_changed_idle,
 	.switched_to		= switched_to_idle,
 	.update_curr		= update_curr_idle,
-#ifdef CONFIG_SCHED_WALT
-	.fixup_hmp_sched_stats	= fixup_hmp_sched_stats_idle,
-#endif
 };
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 2b556d0..6b935e7 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -11,45 +11,6 @@
 #include <linux/irq_work.h>
 #include <trace/events/sched.h>
 
-#ifdef CONFIG_SCHED_WALT
-
-static void
-inc_hmp_sched_stats_rt(struct rq *rq, struct task_struct *p)
-{
-	inc_cumulative_runnable_avg(&rq->hmp_stats, p);
-}
-
-static void
-dec_hmp_sched_stats_rt(struct rq *rq, struct task_struct *p)
-{
-	dec_cumulative_runnable_avg(&rq->hmp_stats, p);
-}
-
-static void
-fixup_hmp_sched_stats_rt(struct rq *rq, struct task_struct *p,
-			 u32 new_task_load, u32 new_pred_demand)
-{
-	s64 task_load_delta = (s64)new_task_load - task_load(p);
-	s64 pred_demand_delta = PRED_DEMAND_DELTA;
-
-	fixup_cumulative_runnable_avg(&rq->hmp_stats, p, task_load_delta,
-				      pred_demand_delta);
-}
-
-#ifdef CONFIG_SMP
-static int find_lowest_rq(struct task_struct *task);
-
-#endif /* CONFIG_SMP */
-#else  /* CONFIG_SCHED_WALT */
-
-static inline void
-inc_hmp_sched_stats_rt(struct rq *rq, struct task_struct *p) { }
-
-static inline void
-dec_hmp_sched_stats_rt(struct rq *rq, struct task_struct *p) { }
-
-#endif	/* CONFIG_SCHED_WALT */
-
 #include "walt.h"
 
 int sched_rr_timeslice = RR_TIMESLICE;
@@ -1421,7 +1382,7 @@
 		rt_se->timeout = 0;
 
 	enqueue_rt_entity(rt_se, flags);
-	inc_hmp_sched_stats_rt(rq, p);
+	walt_inc_cumulative_runnable_avg(rq, p);
 
 	if (!task_current(rq, p) && tsk_nr_cpus_allowed(p) > 1)
 		enqueue_pushable_task(rq, p);
@@ -1433,7 +1394,7 @@
 
 	update_curr_rt(rq);
 	dequeue_rt_entity(rt_se, flags);
-	dec_hmp_sched_stats_rt(rq, p);
+	walt_dec_cumulative_runnable_avg(rq, p);
 
 	dequeue_pushable_task(rq, p);
 }
@@ -1752,18 +1713,6 @@
 
 static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask);
 
-static inline unsigned long task_util(struct task_struct *p)
-{
-#ifdef CONFIG_SCHED_WALT
-	if (!walt_disabled && sysctl_sched_use_walt_task_util) {
-		u64 demand = p->ravg.demand;
-
-		return (demand << 10) / sched_ravg_window;
-	}
-#endif
-	return p->se.avg.util_avg;
-}
-
 static int find_lowest_rq(struct task_struct *task)
 {
 	struct sched_domain *sd;
@@ -2623,7 +2572,7 @@
 
 	.update_curr		= update_curr_rt,
 #ifdef CONFIG_SCHED_WALT
-	.fixup_hmp_sched_stats	= fixup_hmp_sched_stats_rt,
+	.fixup_walt_sched_stats	= fixup_walt_sched_stats_common,
 #endif
 };
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index f12e67f..318d289 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -25,10 +25,12 @@
 struct rq;
 struct cpuidle_state;
 
+extern __read_mostly bool sched_predl;
+
 #ifdef CONFIG_SCHED_WALT
 extern unsigned int sched_ravg_window;
 
-struct hmp_sched_stats {
+struct walt_sched_stats {
 	int nr_big_tasks;
 	u64 cumulative_runnable_avg;
 	u64 pred_demands_sum;
@@ -106,6 +108,12 @@
 static inline void cpu_load_update_active(struct rq *this_rq) { }
 #endif
 
+#ifdef CONFIG_SCHED_SMT
+extern void update_idle_core(struct rq *rq);
+#else
+static inline void update_idle_core(struct rq *rq) { }
+#endif
+
 /*
  * Helpers for converting nanosecond timing to jiffy resolution
  */
@@ -503,13 +511,10 @@
 	struct list_head leaf_cfs_rq_list;
 	struct task_group *tg;	/* group that "owns" this runqueue */
 
-#ifdef CONFIG_SCHED_WALT
-	u64 cumulative_runnable_avg;
-#endif
-
 #ifdef CONFIG_CFS_BANDWIDTH
+
 #ifdef CONFIG_SCHED_WALT
-	struct hmp_sched_stats hmp_stats;
+	struct walt_sched_stats walt_stats;
 #endif
 
 	int runtime_enabled;
@@ -768,13 +773,13 @@
 #ifdef CONFIG_SCHED_WALT
 	struct sched_cluster *cluster;
 	struct cpumask freq_domain_cpumask;
-	struct hmp_sched_stats hmp_stats;
+	struct walt_sched_stats walt_stats;
 
 	int cstate, wakeup_latency, wakeup_energy;
 	u64 window_start;
 	s64 cum_window_start;
 	u64 load_reported_window;
-	unsigned long hmp_flags;
+	unsigned long walt_flags;
 
 	u64 cur_irqload;
 	u64 avg_irqload;
@@ -859,23 +864,6 @@
 #endif
 }
 
-
-#ifdef CONFIG_SCHED_SMT
-
-extern struct static_key_false sched_smt_present;
-
-extern void __update_idle_core(struct rq *rq);
-
-static inline void update_idle_core(struct rq *rq)
-{
-	if (static_branch_unlikely(&sched_smt_present))
-		__update_idle_core(rq);
-}
-
-#else
-static inline void update_idle_core(struct rq *rq) { }
-#endif
-
 DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
 
 #define cpu_rq(cpu)		(&per_cpu(runqueues, (cpu)))
@@ -1424,7 +1412,7 @@
 	void (*task_change_group) (struct task_struct *p, int type);
 #endif
 #ifdef CONFIG_SCHED_WALT
-	void (*fixup_hmp_sched_stats)(struct rq *rq, struct task_struct *p,
+	void (*fixup_walt_sched_stats)(struct rq *rq, struct task_struct *p,
 				      u32 new_task_load, u32 new_pred_demand);
 #endif
 };
@@ -1456,7 +1444,6 @@
 extern void update_group_capacity(struct sched_domain *sd, int cpu);
 
 extern void trigger_load_balance(struct rq *rq);
-extern void nohz_balance_clear_nohz_mask(int cpu);
 
 extern void set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask);
 
@@ -1716,9 +1703,18 @@
 	return cpu_rq(cpu)->cpu_capacity_orig;
 }
 
-extern unsigned int sysctl_sched_use_walt_cpu_util;
 extern unsigned int walt_disabled;
 
+static inline unsigned long task_util(struct task_struct *p)
+{
+#ifdef CONFIG_SCHED_WALT
+	if (!walt_disabled && sysctl_sched_use_walt_task_util)
+		return p->ravg.demand /
+		       (sched_ravg_window >> SCHED_CAPACITY_SHIFT);
+#endif
+	return p->se.avg.util_avg;
+}
+
 /*
  * cpu_util returns the amount of capacity of a CPU that is used by CFS
  * tasks. The unit of the return value must be the one of capacity so we can
@@ -1752,7 +1748,7 @@
 
 #ifdef CONFIG_SCHED_WALT
 	if (!walt_disabled && sysctl_sched_use_walt_cpu_util) {
-		util = cpu_rq(cpu)->hmp_stats.cumulative_runnable_avg;
+		util = cpu_rq(cpu)->walt_stats.cumulative_runnable_avg;
 		util = div64_u64(util,
 				 sched_ravg_window >> SCHED_CAPACITY_SHIFT);
 	}
@@ -1816,13 +1812,18 @@
 		if (walt_load) {
 			u64 nl = cpu_rq(cpu)->nt_prev_runnable_sum +
 				rq->grp_time.nt_prev_runnable_sum;
+			u64 pl = rq->walt_stats.pred_demands_sum;
 
 			nl = div64_u64(nl, sched_ravg_window >>
 						SCHED_CAPACITY_SHIFT);
+			pl = div64_u64(pl, sched_ravg_window >>
+						SCHED_CAPACITY_SHIFT);
 
 			walt_load->prev_window_util = util;
 			walt_load->nl = nl;
-			walt_load->pl = 0;
+			walt_load->pl = pl;
+			rq->old_busy_time = util;
+			rq->old_estimated_time = pl;
 			walt_load->ws = rq->window_start;
 		}
 	}
@@ -2206,14 +2207,12 @@
 #ifdef CONFIG_SCHED_WALT
 u64 sched_ktime_clock(void);
 void note_task_waking(struct task_struct *p, u64 wallclock);
-extern void update_avg_burst(struct task_struct *p);
 #else /* CONFIG_SCHED_WALT */
 static inline u64 sched_ktime_clock(void)
 {
 	return 0;
 }
 static inline void note_task_waking(struct task_struct *p, u64 wallclock) { }
-static inline void update_avg_burst(struct task_struct *p) { }
 #endif /* CONFIG_SCHED_WALT */
 
 #ifdef CONFIG_CPU_FREQ
@@ -2246,6 +2245,9 @@
 	struct update_util_data *data;
 
 #ifdef CONFIG_SCHED_WALT
+	unsigned int exception_flags = SCHED_CPUFREQ_INTERCLUSTER_MIG |
+						SCHED_CPUFREQ_PL;
+
 	/*
 	 * Skip if we've already reported, but not if this is an inter-cluster
 	 * migration. Also only allow WALT update sites.
@@ -2254,7 +2256,7 @@
 		return;
 	if (!sched_disable_window_stats &&
 		(rq->load_reported_window == rq->window_start) &&
-		!(flags & SCHED_CPUFREQ_INTERCLUSTER_MIG))
+		!(flags & exception_flags))
 		return;
 	rq->load_reported_window = rq->window_start;
 #endif
@@ -2348,13 +2350,11 @@
 extern unsigned int  __read_mostly sched_load_granule;
 
 extern int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb);
-extern void reset_cpu_hmp_stats(int cpu, int reset_cra);
 extern int update_preferred_cluster(struct related_thread_group *grp,
 			struct task_struct *p, u32 old_load);
 extern void set_preferred_cluster(struct related_thread_group *grp);
 extern void add_new_task_to_grp(struct task_struct *new);
 extern unsigned int update_freq_aggregate_threshold(unsigned int threshold);
-extern void update_avg(u64 *avg, u64 sample);
 
 #define NO_BOOST 0
 #define FULL_THROTTLE_BOOST 1
@@ -2482,6 +2482,11 @@
 	return cpu_max_possible_capacity(cpu) == max_possible_capacity;
 }
 
+static inline bool is_min_capacity_cpu(int cpu)
+{
+	return cpu_max_possible_capacity(cpu) == min_max_possible_capacity;
+}
+
 /*
  * 'load' is in reference to "best cpu" at its best frequency.
  * Scale that in reference to a given cpu, accounting for how bad it is
@@ -2574,54 +2579,11 @@
 #define	BOOST_KICK	0
 #define	CPU_RESERVED	1
 
-static inline u64 cpu_cravg_sync(int cpu, int sync)
-{
-	struct rq *rq = cpu_rq(cpu);
-	u64 load;
-
-	load = rq->hmp_stats.cumulative_runnable_avg;
-
-	/*
-	 * If load is being checked in a sync wakeup environment,
-	 * we may want to discount the load of the currently running
-	 * task.
-	 */
-	if (sync && cpu == smp_processor_id()) {
-		if (load > rq->curr->ravg.demand)
-			load -= rq->curr->ravg.demand;
-		else
-			load = 0;
-	}
-
-	return load;
-}
-
-extern int power_delta_exceeded(unsigned int cpu_cost, unsigned int base_cost);
-extern void reset_all_window_stats(u64 window_start, unsigned int window_size);
 extern int sched_boost(void);
-extern int task_load_will_fit(struct task_struct *p, u64 task_load, int cpu,
-					enum sched_boost_policy boost_policy);
-extern int task_will_fit(struct task_struct *p, int cpu);
-extern u64 cpu_load(int cpu);
-extern u64 cpu_load_sync(int cpu, int sync);
 extern int preferred_cluster(struct sched_cluster *cluster,
 						struct task_struct *p);
-extern void inc_rq_hmp_stats(struct rq *rq,
-				struct task_struct *p, int change_cra);
-extern void dec_rq_hmp_stats(struct rq *rq,
-				struct task_struct *p, int change_cra);
-extern void reset_hmp_stats(struct hmp_sched_stats *stats, int reset_cra);
-extern int upmigrate_discouraged(struct task_struct *p);
 extern struct sched_cluster *rq_cluster(struct rq *rq);
-extern int nr_big_tasks(struct rq *rq);
 extern void reset_task_stats(struct task_struct *p);
-extern void reset_cfs_rq_hmp_stats(int cpu, int reset_cra);
-extern void inc_hmp_sched_stats_fair(struct rq *rq,
-			struct task_struct *p, int change_cra);
-extern u64 cpu_upmigrate_discourage_read_u64(struct cgroup_subsys_state *css,
-					struct cftype *cft);
-extern int cpu_upmigrate_discourage_write_u64(struct cgroup_subsys_state *css,
-				struct cftype *cft, u64 upmigrate_discourage);
 extern void clear_top_tasks_bitmap(unsigned long *bitmap);
 
 #if defined(CONFIG_SCHED_TUNE) && defined(CONFIG_CGROUP_SCHEDTUNE)
@@ -2657,53 +2619,42 @@
 {
 	struct rq *rq = cpu_rq(cpu);
 
-	return test_bit(CPU_RESERVED, &rq->hmp_flags);
+	return test_bit(CPU_RESERVED, &rq->walt_flags);
 }
 
 static inline int mark_reserved(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
 
-	return test_and_set_bit(CPU_RESERVED, &rq->hmp_flags);
+	return test_and_set_bit(CPU_RESERVED, &rq->walt_flags);
 }
 
 static inline void clear_reserved(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
 
-	clear_bit(CPU_RESERVED, &rq->hmp_flags);
-}
-
-static inline bool
-__task_in_cum_window_demand(struct rq *rq, struct task_struct *p)
-{
-	return (p->on_rq || p->last_sleep_ts >= rq->window_start);
+	clear_bit(CPU_RESERVED, &rq->walt_flags);
 }
 
 static inline bool
 task_in_cum_window_demand(struct rq *rq, struct task_struct *p)
 {
-	return cpu_of(rq) == task_cpu(p) && __task_in_cum_window_demand(rq, p);
+	return cpu_of(rq) == task_cpu(p) && (p->on_rq || p->last_sleep_ts >=
+							 rq->window_start);
 }
 
-static inline void
-dec_cum_window_demand(struct rq *rq, struct task_struct *p)
-{
-	rq->cum_window_demand -= p->ravg.demand;
-	WARN_ON_ONCE(rq->cum_window_demand < 0);
-}
-
-static inline void
-inc_cum_window_demand(struct rq *rq, struct task_struct *p, s64 delta)
+static inline void walt_fixup_cum_window_demand(struct rq *rq, s64 delta)
 {
 	rq->cum_window_demand += delta;
+	if (unlikely((s64)rq->cum_window_demand < 0))
+		rq->cum_window_demand = 0;
 }
 
 extern void update_cpu_cluster_capacity(const cpumask_t *cpus);
 
 extern unsigned long thermal_cap(int cpu);
 
-extern void clear_hmp_request(int cpu);
+extern void clear_walt_request(int cpu);
 
 extern int got_boost_kick(void);
 extern void clear_boost_kick(int cpu);
@@ -2719,7 +2670,7 @@
 
 #else	/* CONFIG_SCHED_WALT */
 
-struct hmp_sched_stats;
+struct walt_sched_stats;
 struct related_thread_group;
 struct sched_cluster;
 
@@ -2730,43 +2681,14 @@
 
 static inline void check_for_migration(struct rq *rq, struct task_struct *p) { }
 
-static inline int task_will_fit(struct task_struct *p, int cpu)
-{
-	return 1;
-}
-
 static inline int sched_boost(void)
 {
 	return 0;
 }
 
-static inline int is_big_task(struct task_struct *p)
-{
-	return 0;
-}
-
-static inline int nr_big_tasks(struct rq *rq)
-{
-	return 0;
-}
-
-static inline int is_cpu_throttling_imminent(int cpu)
-{
-	return 0;
-}
-
-static inline int is_task_migration_throttled(struct task_struct *p)
-{
-	return 0;
-}
-
+static inline bool hmp_capable(void) { return false; }
 static inline bool is_max_capacity_cpu(int cpu) { return true; }
-
-static inline void
-inc_rq_hmp_stats(struct rq *rq, struct task_struct *p, int change_cra) { }
-
-static inline void
-dec_rq_hmp_stats(struct rq *rq, struct task_struct *p, int change_cra) { }
+static inline bool is_min_capacity_cpu(int cpu) { return true; }
 
 static inline int
 preferred_cluster(struct sched_cluster *cluster, struct task_struct *p)
@@ -2828,17 +2750,7 @@
 #define trace_sched_cpu_load_cgroup(...)
 #define trace_sched_cpu_load_wakeup(...)
 
-static inline bool
-__task_in_cum_window_demand(struct rq *rq, struct task_struct *p)
-{
-	return 0;
-}
-
-static inline void
-dec_cum_window_demand(struct rq *rq, struct task_struct *p) { }
-
-static inline void
-inc_cum_window_demand(struct rq *rq, struct task_struct *p, s64 delta) { }
+static inline void walt_fixup_cum_window_demand(struct rq *rq, s64 delta) { }
 
 static inline void update_cpu_cluster_capacity(const cpumask_t *cpus) { }
 
@@ -2849,7 +2761,7 @@
 }
 #endif
 
-static inline void clear_hmp_request(int cpu) { }
+static inline void clear_walt_request(int cpu) { }
 
 static inline int got_boost_kick(void)
 {
diff --git a/kernel/sched/sched_avg.c b/kernel/sched/sched_avg.c
index 4238924..166c643 100644
--- a/kernel/sched/sched_avg.c
+++ b/kernel/sched/sched_avg.c
@@ -33,6 +33,8 @@
 static DEFINE_PER_CPU(spinlock_t, nr_lock) = __SPIN_LOCK_UNLOCKED(nr_lock);
 static s64 last_get_time;
 
+static DEFINE_PER_CPU(atomic64_t, last_busy_time) = ATOMIC64_INIT(0);
+
 #define DIV64_U64_ROUNDUP(X, Y) div64_u64((X) + (Y - 1), Y)
 /**
  * sched_get_nr_running_avg
@@ -120,6 +122,27 @@
 }
 EXPORT_SYMBOL(sched_get_nr_running_avg);
 
+#define BUSY_NR_RUN		3
+#define BUSY_LOAD_FACTOR	2
+static inline void update_last_busy_time(int cpu, bool dequeue,
+				unsigned long prev_nr_run, u64 curr_time)
+{
+	bool nr_run_trigger = false, load_trigger = false;
+
+	if (!hmp_capable() || is_min_capacity_cpu(cpu))
+		return;
+
+	if (prev_nr_run >= BUSY_NR_RUN && per_cpu(nr, cpu) < BUSY_NR_RUN)
+		nr_run_trigger = true;
+
+	if (dequeue && (cpu_util(cpu) * BUSY_LOAD_FACTOR) >
+			capacity_orig_of(cpu))
+		load_trigger = true;
+
+	if (nr_run_trigger || load_trigger)
+		atomic64_set(&per_cpu(last_busy_time, cpu), curr_time);
+}
+
 /**
  * sched_update_nr_prod
  * @cpu: The core id of the nr running driver.
@@ -148,6 +171,8 @@
 	if (per_cpu(nr, cpu) > per_cpu(nr_max, cpu))
 		per_cpu(nr_max, cpu) = per_cpu(nr, cpu);
 
+	update_last_busy_time(cpu, !inc, nr_running, curr_time);
+
 	per_cpu(nr_prod_sum, cpu) += nr_running * diff;
 	per_cpu(nr_big_prod_sum, cpu) += nr_eligible_big_tasks(cpu) * diff;
 	per_cpu(iowait_prod_sum, cpu) += nr_iowait_cpu(cpu) * diff;
@@ -184,3 +209,8 @@
 	busy = (util * 100) / capacity;
 	return busy;
 }
+
+u64 sched_get_cpu_last_busy_time(int cpu)
+{
+	return atomic64_read(&per_cpu(last_busy_time, cpu));
+}
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c
index dcc4a36..11a1888 100644
--- a/kernel/sched/stop_task.c
+++ b/kernel/sched/stop_task.c
@@ -18,41 +18,6 @@
 }
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_SCHED_WALT
-
-static void
-inc_hmp_sched_stats_stop(struct rq *rq, struct task_struct *p)
-{
-	inc_cumulative_runnable_avg(&rq->hmp_stats, p);
-}
-
-static void
-dec_hmp_sched_stats_stop(struct rq *rq, struct task_struct *p)
-{
-	dec_cumulative_runnable_avg(&rq->hmp_stats, p);
-}
-
-static void
-fixup_hmp_sched_stats_stop(struct rq *rq, struct task_struct *p,
-			   u32 new_task_load, u32 new_pred_demand)
-{
-	s64 task_load_delta = (s64)new_task_load - task_load(p);
-	s64 pred_demand_delta = PRED_DEMAND_DELTA;
-
-	fixup_cumulative_runnable_avg(&rq->hmp_stats, p, task_load_delta,
-				      pred_demand_delta);
-}
-
-#else	/* CONFIG_SCHED_WALT */
-
-static inline void
-inc_hmp_sched_stats_stop(struct rq *rq, struct task_struct *p) { }
-
-static inline void
-dec_hmp_sched_stats_stop(struct rq *rq, struct task_struct *p) { }
-
-#endif	/* CONFIG_SCHED_WALT */
-
 static void
 check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags)
 {
@@ -78,14 +43,14 @@
 enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags)
 {
 	add_nr_running(rq, 1);
-	inc_hmp_sched_stats_stop(rq, p);
+	walt_inc_cumulative_runnable_avg(rq, p);
 }
 
 static void
 dequeue_task_stop(struct rq *rq, struct task_struct *p, int flags)
 {
 	sub_nr_running(rq, 1);
-	dec_hmp_sched_stats_stop(rq, p);
+	walt_dec_cumulative_runnable_avg(rq, p);
 }
 
 static void yield_task_stop(struct rq *rq)
@@ -173,6 +138,6 @@
 	.switched_to		= switched_to_stop,
 	.update_curr		= update_curr_stop,
 #ifdef CONFIG_SCHED_WALT
-	.fixup_hmp_sched_stats	= fixup_hmp_sched_stats_stop,
+	.fixup_walt_sched_stats	= fixup_walt_sched_stats_common,
 #endif
 };
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 6f7d34d..48f3512 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -116,8 +116,6 @@
  * IMPORTANT: Initialize both copies to same value!!
  */
 
-static __read_mostly bool sched_predl;
-
 __read_mostly unsigned int sched_ravg_hist_size = 5;
 __read_mostly unsigned int sysctl_sched_ravg_hist_size = 5;
 
@@ -207,27 +205,28 @@
 }
 early_param("sched_predl", set_sched_predl);
 
-void inc_rq_hmp_stats(struct rq *rq, struct task_struct *p, int change_cra)
+void inc_rq_walt_stats(struct rq *rq, struct task_struct *p)
 {
-	inc_nr_big_task(&rq->hmp_stats, p);
-	if (change_cra)
-		inc_cumulative_runnable_avg(&rq->hmp_stats, p);
+	inc_nr_big_task(&rq->walt_stats, p);
+	walt_inc_cumulative_runnable_avg(rq, p);
 }
 
-void dec_rq_hmp_stats(struct rq *rq, struct task_struct *p, int change_cra)
+void dec_rq_walt_stats(struct rq *rq, struct task_struct *p)
 {
-	dec_nr_big_task(&rq->hmp_stats, p);
-	if (change_cra)
-		dec_cumulative_runnable_avg(&rq->hmp_stats, p);
+	dec_nr_big_task(&rq->walt_stats, p);
+	walt_dec_cumulative_runnable_avg(rq, p);
 }
 
-void reset_hmp_stats(struct hmp_sched_stats *stats, int reset_cra)
+void fixup_walt_sched_stats_common(struct rq *rq, struct task_struct *p,
+				   u32 new_task_load, u32 new_pred_demand)
 {
-	stats->nr_big_tasks = 0; /* never happens on EAS */
-	if (reset_cra) {
-		stats->cumulative_runnable_avg = 0;
-		stats->pred_demands_sum = 0;
-	}
+	s64 task_load_delta = (s64)new_task_load - task_load(p);
+	s64 pred_demand_delta = PRED_DEMAND_DELTA;
+
+	fixup_cumulative_runnable_avg(&rq->walt_stats, task_load_delta,
+				      pred_demand_delta);
+
+	walt_fixup_cum_window_demand(rq, task_load_delta);
 }
 
 /*
@@ -295,9 +294,7 @@
 	nr_windows = div64_u64(delta, sched_ravg_window);
 	rq->window_start += (u64)nr_windows * (u64)sched_ravg_window;
 
-	rq->cum_window_demand = rq->hmp_stats.cumulative_runnable_avg;
-	if (event == PUT_PREV_TASK)
-		rq->cum_window_demand += rq->curr->ravg.demand;
+	rq->cum_window_demand = rq->walt_stats.cumulative_runnable_avg;
 
 	return old_window_start;
 }
@@ -379,12 +376,12 @@
 	struct rq *rq = cpu_rq(cpu);
 
 	if (!is_max_capacity_cpu(cpu))
-		return rq->hmp_stats.nr_big_tasks;
+		return rq->walt_stats.nr_big_tasks;
 
 	return rq->nr_running;
 }
 
-void clear_hmp_request(int cpu)
+void clear_walt_request(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
 	unsigned long flags;
@@ -622,20 +619,6 @@
 	raw_spin_unlock(&cluster->load_lock);
 }
 
-static inline void
-init_new_task_load_hmp(struct task_struct *p, bool idle_task)
-{
-}
-
-static inline void
-update_task_burst(struct task_struct *p, struct rq *rq, int event, int runtime)
-{
-}
-
-static void reset_task_stats_hmp(struct task_struct *p)
-{
-}
-
 static inline void inter_cluster_migration_fixup
 	(struct task_struct *p, int new_cpu, int task_cpu, bool new_task)
 {
@@ -788,9 +771,15 @@
 
 	update_task_cpu_cycles(p, new_cpu);
 
-	if (__task_in_cum_window_demand(src_rq, p)) {
-		dec_cum_window_demand(src_rq, p);
-		inc_cum_window_demand(dest_rq, p, p->ravg.demand);
+	/*
+	 * When a task is migrating during the wakeup, adjust
+	 * the task's contribution towards cumulative window
+	 * demand.
+	 */
+	if (p->state == TASK_WAKING && p->last_sleep_ts >=
+				       src_rq->window_start) {
+		walt_fixup_cum_window_demand(src_rq, -(s64)p->ravg.demand);
+		walt_fixup_cum_window_demand(dest_rq, p->ravg.demand);
 	}
 
 	new_task = is_new_task(p);
@@ -1071,7 +1060,7 @@
 
 	if (task_on_rq_queued(p) && (!task_has_dl_policy(p) ||
 				!p->dl.dl_throttled))
-		p->sched_class->fixup_hmp_sched_stats(rq, p,
+		p->sched_class->fixup_walt_sched_stats(rq, p,
 				p->ravg.demand,
 				new);
 
@@ -1288,6 +1277,33 @@
 	return delta;
 }
 
+/* Convert busy time to frequency equivalent
+ * Assumes load is scaled to 1024
+ */
+static inline unsigned int load_to_freq(struct rq *rq, u64 load)
+{
+	return mult_frac(cpu_max_possible_freq(cpu_of(rq)), load,
+			 capacity_orig_of(cpu_of(rq)));
+}
+
+bool do_pl_notif(struct rq *rq)
+{
+	u64 prev = rq->old_busy_time;
+	u64 pl = rq->walt_stats.pred_demands_sum;
+	int cpu = cpu_of(rq);
+
+	/* If already at max freq, bail out */
+	if (capacity_orig_of(cpu) == capacity_curr_of(cpu))
+		return false;
+
+	prev = max(prev, rq->old_estimated_time);
+
+	pl = div64_u64(pl, sched_ravg_window >> SCHED_CAPACITY_SHIFT);
+
+	/* 400 MHz filter. */
+	return (pl > prev) && (load_to_freq(rq, pl - prev) > 400000);
+}
+
 static void rollover_cpu_window(struct rq *rq, bool full_window)
 {
 	u64 curr_sum = rq->curr_runnable_sum;
@@ -1666,21 +1682,28 @@
 
 	/*
 	 * A throttled deadline sched class task gets dequeued without
-	 * changing p->on_rq. Since the dequeue decrements hmp stats
+	 * changing p->on_rq. Since the dequeue decrements walt stats
 	 * avoid decrementing it here again.
+	 *
+	 * When window is rolled over, the cumulative window demand
+	 * is reset to the cumulative runnable average (contribution from
+	 * the tasks on the runqueue). If the current task is dequeued
+	 * already, it's demand is not included in the cumulative runnable
+	 * average. So add the task demand separately to cumulative window
+	 * demand.
 	 */
-	if (task_on_rq_queued(p) && (!task_has_dl_policy(p) ||
-						!p->dl.dl_throttled))
-		p->sched_class->fixup_hmp_sched_stats(rq, p, demand,
-						      pred_demand);
+	if (!task_has_dl_policy(p) || !p->dl.dl_throttled) {
+		if (task_on_rq_queued(p))
+			p->sched_class->fixup_walt_sched_stats(rq, p, demand,
+							       pred_demand);
+		else if (rq->curr == p)
+			walt_fixup_cum_window_demand(rq, demand);
+	}
 
 	p->ravg.demand = demand;
 	p->ravg.coloc_demand = div64_u64(sum, sched_ravg_hist_size);
 	p->ravg.pred_demand = pred_demand;
 
-	if (__task_in_cum_window_demand(rq, p))
-		inc_cum_window_demand(rq, p, p->ravg.demand - prev_demand);
-
 done:
 	trace_sched_update_history(rq, p, runtime, samples, event);
 }
@@ -1879,7 +1902,7 @@
 void update_task_ravg(struct task_struct *p, struct rq *rq, int event,
 						u64 wallclock, u64 irqtime)
 {
-	u64 runtime, old_window_start;
+	u64 old_window_start;
 
 	if (!rq->window_start || sched_disable_window_stats ||
 	    p->ravg.mark_start == wallclock)
@@ -1895,9 +1918,7 @@
 	}
 
 	update_task_rq_cpu_cycles(p, rq, event, wallclock, irqtime);
-	runtime = update_task_demand(p, rq, event, wallclock);
-	if (runtime)
-		update_task_burst(p, rq, event, runtime);
+	update_task_demand(p, rq, event, wallclock);
 	update_cpu_busy_time(p, rq, event, wallclock, irqtime);
 	update_task_pred_demand(rq, p, event);
 done:
@@ -1938,8 +1959,6 @@
 	memset(&p->ravg, 0, sizeof(struct ravg));
 	p->cpu_cycles = 0;
 
-	init_new_task_load_hmp(p, idle_task);
-
 	p->ravg.curr_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), GFP_KERNEL);
 	p->ravg.prev_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), GFP_KERNEL);
 
@@ -1995,8 +2014,6 @@
 	p->ravg.curr_window_cpu = curr_window_ptr;
 	p->ravg.prev_window_cpu = prev_window_ptr;
 
-	reset_task_stats_hmp(p);
-
 	/* Retain EXITING_TASK marker */
 	p->ravg.sum_history[0] = sum;
 }
@@ -3069,11 +3086,11 @@
 	cpumask_set_cpu(cpu_of(rq), &rq->freq_domain_cpumask);
 	init_irq_work(&walt_migration_irq_work, walt_irq_work);
 	init_irq_work(&walt_cpufreq_irq_work, walt_irq_work);
-	rq->hmp_stats.cumulative_runnable_avg = 0;
+	rq->walt_stats.cumulative_runnable_avg = 0;
 	rq->window_start = 0;
 	rq->cum_window_start = 0;
-	rq->hmp_stats.nr_big_tasks = 0;
-	rq->hmp_flags = 0;
+	rq->walt_stats.nr_big_tasks = 0;
+	rq->walt_flags = 0;
 	rq->cur_irqload = 0;
 	rq->avg_irqload = 0;
 	rq->irqload_ts = 0;
@@ -3096,7 +3113,7 @@
 	rq->old_busy_time = 0;
 	rq->old_estimated_time = 0;
 	rq->old_busy_time_group = 0;
-	rq->hmp_stats.pred_demands_sum = 0;
+	rq->walt_stats.pred_demands_sum = 0;
 	rq->ed_task = NULL;
 	rq->curr_table = 0;
 	rq->prev_top = 0;
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
index 3f4739e..535f14b 100644
--- a/kernel/sched/walt.h
+++ b/kernel/sched/walt.h
@@ -66,7 +66,7 @@
 extern unsigned int nr_eligible_big_tasks(int cpu);
 
 static inline void
-inc_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p)
+inc_nr_big_task(struct walt_sched_stats *stats, struct task_struct *p)
 {
 	if (sched_disable_window_stats)
 		return;
@@ -76,7 +76,7 @@
 }
 
 static inline void
-dec_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p)
+dec_nr_big_task(struct walt_sched_stats *stats, struct task_struct *p)
 {
 	if (sched_disable_window_stats)
 		return;
@@ -88,57 +88,20 @@
 }
 
 static inline void
-adjust_nr_big_tasks(struct hmp_sched_stats *stats, int delta, bool inc)
+walt_adjust_nr_big_tasks(struct rq *rq, int delta, bool inc)
 {
-	struct rq *rq = container_of(stats, struct rq, hmp_stats);
-
 	if (sched_disable_window_stats)
 		return;
 
 	sched_update_nr_prod(cpu_of(rq), 0, true);
-	stats->nr_big_tasks += inc ? delta : -delta;
+	rq->walt_stats.nr_big_tasks += inc ? delta : -delta;
 
-	BUG_ON(stats->nr_big_tasks < 0);
+	BUG_ON(rq->walt_stats.nr_big_tasks < 0);
 }
 
 static inline void
-inc_cumulative_runnable_avg(struct hmp_sched_stats *stats,
-				 struct task_struct *p)
-{
-	u32 task_load;
-
-	if (sched_disable_window_stats)
-		return;
-
-	task_load = sched_disable_window_stats ? 0 : p->ravg.demand;
-
-	stats->cumulative_runnable_avg += task_load;
-	stats->pred_demands_sum += p->ravg.pred_demand;
-}
-
-static inline void
-dec_cumulative_runnable_avg(struct hmp_sched_stats *stats,
-				struct task_struct *p)
-{
-	u32 task_load;
-
-	if (sched_disable_window_stats)
-		return;
-
-	task_load = sched_disable_window_stats ? 0 : p->ravg.demand;
-
-	stats->cumulative_runnable_avg -= task_load;
-
-	BUG_ON((s64)stats->cumulative_runnable_avg < 0);
-
-	stats->pred_demands_sum -= p->ravg.pred_demand;
-	BUG_ON((s64)stats->pred_demands_sum < 0);
-}
-
-static inline void
-fixup_cumulative_runnable_avg(struct hmp_sched_stats *stats,
-			      struct task_struct *p, s64 task_load_delta,
-			      s64 pred_demand_delta)
+fixup_cumulative_runnable_avg(struct walt_sched_stats *stats,
+			      s64 task_load_delta, s64 pred_demand_delta)
 {
 	if (sched_disable_window_stats)
 		return;
@@ -150,17 +113,56 @@
 	BUG_ON((s64)stats->pred_demands_sum < 0);
 }
 
-extern void inc_rq_hmp_stats(struct rq *rq,
-				struct task_struct *p, int change_cra);
-extern void dec_rq_hmp_stats(struct rq *rq,
-				struct task_struct *p, int change_cra);
-extern void reset_hmp_stats(struct hmp_sched_stats *stats, int reset_cra);
+static inline void
+walt_inc_cumulative_runnable_avg(struct rq *rq, struct task_struct *p)
+{
+	if (sched_disable_window_stats)
+		return;
+
+	fixup_cumulative_runnable_avg(&rq->walt_stats, p->ravg.demand,
+				      p->ravg.pred_demand);
+
+	/*
+	 * Add a task's contribution to the cumulative window demand when
+	 *
+	 * (1) task is enqueued with on_rq = 1 i.e migration,
+	 *     prio/cgroup/class change.
+	 * (2) task is waking for the first time in this window.
+	 */
+	if (p->on_rq || (p->last_sleep_ts < rq->window_start))
+		walt_fixup_cum_window_demand(rq, p->ravg.demand);
+}
+
+static inline void
+walt_dec_cumulative_runnable_avg(struct rq *rq, struct task_struct *p)
+{
+	if (sched_disable_window_stats)
+		return;
+
+	fixup_cumulative_runnable_avg(&rq->walt_stats, -(s64)p->ravg.demand,
+				      -(s64)p->ravg.pred_demand);
+
+	/*
+	 * on_rq will be 1 for sleeping tasks. So check if the task
+	 * is migrating or dequeuing in RUNNING state to change the
+	 * prio/cgroup/class.
+	 */
+	if (task_on_rq_migrating(p) || p->state == TASK_RUNNING)
+		walt_fixup_cum_window_demand(rq, -(s64)p->ravg.demand);
+}
+
+extern void fixup_walt_sched_stats_common(struct rq *rq, struct task_struct *p,
+					  u32 new_task_load,
+					  u32 new_pred_demand);
+extern void inc_rq_walt_stats(struct rq *rq, struct task_struct *p);
+extern void dec_rq_walt_stats(struct rq *rq, struct task_struct *p);
 extern void fixup_busy_time(struct task_struct *p, int new_cpu);
 extern void init_new_task_load(struct task_struct *p, bool idle_task);
 extern void mark_task_starting(struct task_struct *p);
 extern void set_window_start(struct rq *rq);
 void account_irqtime(int cpu, struct task_struct *curr, u64 delta,
                                   u64 wallclock);
+extern bool do_pl_notif(struct rq *rq);
 
 #define SCHED_HIGH_IRQ_TIMEOUT 3
 static inline u64 sched_irqload(int cpu)
@@ -297,8 +299,8 @@
 
 static inline void update_task_ravg(struct task_struct *p, struct rq *rq,
 				int event, u64 wallclock, u64 irqtime) { }
-static inline void inc_cumulative_runnable_avg(struct hmp_sched_stats *stats,
-		 struct task_struct *p)
+static inline void walt_inc_cumulative_runnable_avg(struct rq *rq,
+		struct task_struct *p)
 {
 }
 
@@ -307,21 +309,21 @@
 	return 0;
 }
 
-static inline void adjust_nr_big_tasks(struct hmp_sched_stats *stats,
+static inline void walt_adjust_nr_big_tasks(struct rq *rq,
 		int delta, bool inc)
 {
 }
 
-static inline void inc_nr_big_task(struct hmp_sched_stats *stats,
+static inline void inc_nr_big_task(struct walt_sched_stats *stats,
 		struct task_struct *p)
 {
 }
 
-static inline void dec_nr_big_task(struct hmp_sched_stats *stats,
+static inline void dec_nr_big_task(struct walt_sched_stats *stats,
 		struct task_struct *p)
 {
 }
-static inline void dec_cumulative_runnable_avg(struct hmp_sched_stats *stats,
+static inline void walt_dec_cumulative_runnable_avg(struct rq *rq,
 		 struct task_struct *p)
 {
 }
@@ -348,6 +350,19 @@
 }
 
 static inline int same_cluster(int src_cpu, int dst_cpu) { return 1; }
+static inline bool do_pl_notif(struct rq *rq) { return false; }
+
+static inline void
+inc_rq_walt_stats(struct rq *rq, struct task_struct *p) { }
+
+static inline void
+dec_rq_walt_stats(struct rq *rq, struct task_struct *p) { }
+
+static inline void
+fixup_walt_sched_stats_common(struct rq *rq, struct task_struct *p,
+			      u32 new_task_load, u32 new_pred_demand)
+{
+}
 
 #endif /* CONFIG_SCHED_WALT */
 
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 5dfdf39..842928a 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -845,7 +845,8 @@
 	 * Rate limit to the tick as a hot fix to prevent DOS. Will be
 	 * mopped up later.
 	 */
-	if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC)
+	if (timr->it.alarm.interval.tv64 &&
+			ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC)
 		timr->it.alarm.interval = ktime_set(0, TICK_NSEC);
 
 	exp = timespec_to_ktime(new_setting->it_value);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 221eb59..4f7ea84 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3590,7 +3590,7 @@
 	int exclude_mod = 0;
 	int found = 0;
 	int ret;
-	int clear_filter;
+	int clear_filter = 0;
 
 	if (func) {
 		func_g.type = filter_parse_regex(func, len, &func_g.search,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ebf9498..4a848f7 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1928,7 +1928,7 @@
 #endif
 		((pc & NMI_MASK    ) ? TRACE_FLAG_NMI     : 0) |
 		((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) |
-		((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
+		((pc & SOFTIRQ_OFFSET) ? TRACE_FLAG_SOFTIRQ : 0) |
 		(tif_need_resched() ? TRACE_FLAG_NEED_RESCHED : 0) |
 		(test_preempt_need_resched() ? TRACE_FLAG_PREEMPT_RESCHED : 0);
 }
@@ -7257,6 +7257,7 @@
 	}
 	kfree(tr->topts);
 
+	free_cpumask_var(tr->tracing_cpumask);
 	kfree(tr->name);
 	kfree(tr);
 
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 562fa69..997ac0b 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -259,7 +259,8 @@
 void perf_trace_del(struct perf_event *p_event, int flags)
 {
 	struct trace_event_call *tp_event = p_event->tp_event;
-	hlist_del_rcu(&p_event->hlist_entry);
+	if (!hlist_unhashed(&p_event->hlist_entry))
+		hlist_del_rcu(&p_event->hlist_entry);
 	tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event);
 }
 
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 81dedaa..4731a08 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -43,6 +43,38 @@
 }
 EXPORT_SYMBOL(cpumask_any_but);
 
+/**
+ * cpumask_next_wrap - helper to implement for_each_cpu_wrap
+ * @n: the cpu prior to the place to search
+ * @mask: the cpumask pointer
+ * @start: the start point of the iteration
+ * @wrap: assume @n crossing @start terminates the iteration
+ *
+ * Returns >= nr_cpu_ids on completion
+ *
+ * Note: the @wrap argument is required for the start condition when
+ * we cannot assume @start is set in @mask.
+ */
+int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap)
+{
+	int next;
+
+again:
+	next = cpumask_next(n, mask);
+
+	if (wrap && n < start && next >= start) {
+		return nr_cpumask_bits;
+
+	} else if (next >= nr_cpumask_bits) {
+		wrap = true;
+		n = -1;
+		goto again;
+	}
+
+	return next;
+}
+EXPORT_SYMBOL(cpumask_next_wrap);
+
 /* These are not inline because of header tangles. */
 #ifdef CONFIG_CPUMASK_OFFSTACK
 /**
diff --git a/lib/string.c b/lib/string.c
index ed83562..ccabe16 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -952,3 +952,10 @@
 	return s;
 }
 EXPORT_SYMBOL(strreplace);
+
+void fortify_panic(const char *name)
+{
+	pr_emerg("detected buffer overflow in %s\n", name);
+	BUG();
+}
+EXPORT_SYMBOL(fortify_panic);
diff --git a/mm/cma.c b/mm/cma.c
index 3322b30..2984dac 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -36,6 +36,7 @@
 #include <linux/highmem.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/show_mem_notifier.h>
 #include <trace/events/cma.h>
 
 #include "cma.h"
@@ -54,6 +55,11 @@
 	return cma->count << PAGE_SHIFT;
 }
 
+const char *cma_get_name(const struct cma *cma)
+{
+	return cma->name ? cma->name : "(undefined)";
+}
+
 static unsigned long cma_bitmap_aligned_mask(const struct cma *cma,
 					     int align_order)
 {
@@ -95,6 +101,29 @@
 	mutex_unlock(&cma->lock);
 }
 
+static int cma_showmem_notifier(struct notifier_block *nb,
+				   unsigned long action, void *data)
+{
+	int i;
+	unsigned long used;
+	struct cma *cma;
+
+	for (i = 0; i < cma_area_count; i++) {
+		cma = &cma_areas[i];
+		used = bitmap_weight(cma->bitmap,
+				     (int)cma_bitmap_maxno(cma));
+		used <<= cma->order_per_bit;
+		pr_info("cma-%d pages: => %lu used of %lu total pages\n",
+			i, used, cma->count);
+	}
+
+	return 0;
+}
+
+static struct notifier_block cma_nb = {
+	.notifier_call = cma_showmem_notifier,
+};
+
 static int __init cma_activate_area(struct cma *cma)
 {
 	int bitmap_size = BITS_TO_LONGS(cma_bitmap_maxno(cma)) * sizeof(long);
@@ -158,6 +187,8 @@
 			return ret;
 	}
 
+	show_mem_notifier_register(&cma_nb);
+
 	return 0;
 }
 core_initcall(cma_init_reserved_areas);
@@ -173,6 +204,7 @@
  */
 int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 				 unsigned int order_per_bit,
+				 const char *name,
 				 struct cma **res_cma)
 {
 	struct cma *cma;
@@ -203,6 +235,13 @@
 	 * subsystems (like slab allocator) are available.
 	 */
 	cma = &cma_areas[cma_area_count];
+	if (name) {
+		cma->name = name;
+	} else {
+		cma->name = kasprintf(GFP_KERNEL, "cma%d\n", cma_area_count);
+		if (!cma->name)
+			return -ENOMEM;
+	}
 	cma->base_pfn = PFN_DOWN(base);
 	cma->count = size >> PAGE_SHIFT;
 	cma->order_per_bit = order_per_bit;
@@ -234,7 +273,7 @@
 int __init cma_declare_contiguous(phys_addr_t base,
 			phys_addr_t size, phys_addr_t limit,
 			phys_addr_t alignment, unsigned int order_per_bit,
-			bool fixed, struct cma **res_cma)
+			bool fixed, const char *name, struct cma **res_cma)
 {
 	phys_addr_t memblock_end = memblock_end_of_DRAM();
 	phys_addr_t highmem_start;
@@ -345,7 +384,7 @@
 		base = addr;
 	}
 
-	ret = cma_init_reserved_mem(base, size, order_per_bit, res_cma);
+	ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma);
 	if (ret)
 		goto err;
 
@@ -358,6 +397,32 @@
 	return ret;
 }
 
+#ifdef CONFIG_CMA_DEBUG
+static void cma_debug_show_areas(struct cma *cma)
+{
+	unsigned long next_zero_bit, next_set_bit;
+	unsigned long start = 0;
+	unsigned int nr_zero, nr_total = 0;
+
+	mutex_lock(&cma->lock);
+	pr_info("number of available pages: ");
+	for (;;) {
+		next_zero_bit = find_next_zero_bit(cma->bitmap, cma->count, start);
+		if (next_zero_bit >= cma->count)
+			break;
+		next_set_bit = find_next_bit(cma->bitmap, cma->count, next_zero_bit);
+		nr_zero = next_set_bit - next_zero_bit;
+		pr_cont("%s%u@%lu", nr_total ? "+" : "", nr_zero, next_zero_bit);
+		nr_total += nr_zero;
+		start = next_zero_bit + nr_zero;
+	}
+	pr_cont("=> %u free of %lu total pages\n", nr_total, cma->count);
+	mutex_unlock(&cma->lock);
+}
+#else
+static inline void cma_debug_show_areas(struct cma *cma) { }
+#endif
+
 /**
  * cma_alloc() - allocate pages from contiguous area
  * @cma:   Contiguous memory region for which the allocation is performed.
@@ -374,8 +439,8 @@
 	unsigned long start = 0;
 	unsigned long bitmap_maxno, bitmap_no, bitmap_count;
 	struct page *page = NULL;
-	int ret;
 	int retry_after_sleep = 0;
+	int ret = -ENOMEM;
 
 	if (!cma || !cma->count)
 		return NULL;
@@ -452,6 +517,12 @@
 
 	trace_cma_alloc(pfn, page, count, align);
 
+	if (ret) {
+		pr_info("%s: alloc failed, req-size: %zu pages, ret: %d\n",
+			__func__, count, ret);
+		cma_debug_show_areas(cma);
+	}
+
 	pr_debug("%s(): returned %p\n", __func__, page);
 	return page;
 }
diff --git a/mm/cma.h b/mm/cma.h
index 17c75a4..4986128 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -11,6 +11,7 @@
 	struct hlist_head mem_head;
 	spinlock_t mem_head_lock;
 #endif
+	const char *name;
 };
 
 extern struct cma cma_areas[MAX_CMA_AREAS];
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
index f8e4b60..3f7f84c 100644
--- a/mm/cma_debug.c
+++ b/mm/cma_debug.c
@@ -167,7 +167,7 @@
 	char name[16];
 	int u32s;
 
-	sprintf(name, "cma-%d", idx);
+	scnprintf(name, sizeof(name), "cma-%s", cma->name);
 
 	tmp = debugfs_create_dir(name, cma_debugfs_root);
 
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index e7d5db9..8258e9e 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1373,8 +1373,8 @@
 		get_page(page);
 		spin_unlock(ptl);
 		split_huge_page(page);
-		put_page(page);
 		unlock_page(page);
+		put_page(page);
 		goto out_unlocked;
 	}
 
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 234676e..7a40fa2 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -117,6 +117,7 @@
 		l = list_lru_from_kmem(nlru, item);
 		list_add_tail(item, &l->list);
 		l->nr_items++;
+		nlru->nr_items++;
 		spin_unlock(&nlru->lock);
 		return true;
 	}
@@ -136,6 +137,7 @@
 		l = list_lru_from_kmem(nlru, item);
 		list_del_init(item);
 		l->nr_items--;
+		nlru->nr_items--;
 		spin_unlock(&nlru->lock);
 		return true;
 	}
@@ -183,15 +185,10 @@
 
 unsigned long list_lru_count_node(struct list_lru *lru, int nid)
 {
-	long count = 0;
-	int memcg_idx;
+	struct list_lru_node *nlru;
 
-	count += __list_lru_count_one(lru, nid, -1);
-	if (list_lru_memcg_aware(lru)) {
-		for_each_memcg_cache_index(memcg_idx)
-			count += __list_lru_count_one(lru, nid, memcg_idx);
-	}
-	return count;
+	nlru = &lru->node[nid];
+	return nlru->nr_items;
 }
 EXPORT_SYMBOL_GPL(list_lru_count_node);
 
@@ -226,6 +223,7 @@
 			assert_spin_locked(&nlru->lock);
 		case LRU_REMOVED:
 			isolated++;
+			nlru->nr_items--;
 			/*
 			 * If the lru lock has been dropped, our list
 			 * traversal is now invalid and so we have to
diff --git a/mm/mmap.c b/mm/mmap.c
index b8f91e0e..6f90f07 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2237,7 +2237,7 @@
 
 	/* Guard against exceeding limits of the address space. */
 	address &= PAGE_MASK;
-	if (address >= TASK_SIZE)
+	if (address >= (TASK_SIZE & PAGE_MASK))
 		return -ENOMEM;
 	address += PAGE_SIZE;
 
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2efa9c9..3a22b14 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -37,6 +37,7 @@
 #include <linux/ratelimit.h>
 #include <linux/kthread.h>
 #include <linux/init.h>
+#include <linux/show_mem_notifier.h>
 
 #include <asm/tlb.h>
 #include "internal.h"
@@ -416,8 +417,11 @@
 	dump_stack();
 	if (oc->memcg)
 		mem_cgroup_print_oom_info(oc->memcg, p);
-	else
+	else {
 		show_mem(SHOW_MEM_FILTER_NODES);
+		show_mem_call_notifiers();
+	}
+
 	if (sysctl_oom_dump_tasks)
 		dump_tasks(oc->memcg, oc->nodemask);
 }
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bdd2bea..44085b2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -64,6 +64,7 @@
 #include <linux/page_owner.h>
 #include <linux/kthread.h>
 #include <linux/memcontrol.h>
+#include <linux/show_mem_notifier.h>
 
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -3130,8 +3131,10 @@
 	pr_cont(", mode:%#x(%pGg)\n", gfp_mask, &gfp_mask);
 
 	dump_stack();
-	if (!should_suppress_show_mem())
+	if (!should_suppress_show_mem()) {
 		show_mem(filter);
+		show_mem_call_notifiers();
+	}
 }
 
 static inline struct page *
diff --git a/mm/page_owner.c b/mm/page_owner.c
index d2db436..65e24fb 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -285,7 +285,11 @@
 				continue;
 
 			if (PageBuddy(page)) {
-				pfn += (1UL << page_order(page)) - 1;
+				unsigned long freepage_order;
+
+				freepage_order = page_order_unsafe(page);
+				if (freepage_order < MAX_ORDER)
+					pfn += (1UL << freepage_order) - 1;
 				continue;
 			}
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ad182e6..ed89128 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -426,7 +426,7 @@
 	BUG_ON(offset_in_page(size));
 	BUG_ON(!is_power_of_2(align));
 
-	might_sleep_if(gfpflags_allow_blocking(gfp_mask));
+	might_sleep();
 
 	va = kmalloc_node(sizeof(struct vmap_area),
 			gfp_mask & GFP_RECLAIM_MASK, node);
@@ -662,6 +662,13 @@
 
 static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
 
+/*
+ * Serialize vmap purging.  There is no actual criticial section protected
+ * by this look, but we want to avoid concurrent calls for performance
+ * reasons and to make the pcpu_get_vm_areas more deterministic.
+ */
+static DEFINE_MUTEX(vmap_purge_lock);
+
 /* for per-CPU blocks */
 static void purge_fragmented_blocks_allcpus(void);
 
@@ -676,59 +683,40 @@
 
 /*
  * Purges all lazily-freed vmap areas.
- *
- * If sync is 0 then don't purge if there is already a purge in progress.
- * If force_flush is 1, then flush kernel TLBs between *start and *end even
- * if we found no lazy vmap areas to unmap (callers can use this to optimise
- * their own TLB flushing).
- * Returns with *start = min(*start, lowest purged address)
- *              *end = max(*end, highest purged address)
  */
-static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
-					int sync, int force_flush)
+static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
 {
-	static DEFINE_SPINLOCK(purge_lock);
 	struct llist_node *valist;
 	struct vmap_area *va;
 	struct vmap_area *n_va;
-	int nr = 0;
+	bool do_free = false;
 
-	/*
-	 * If sync is 0 but force_flush is 1, we'll go sync anyway but callers
-	 * should not expect such behaviour. This just simplifies locking for
-	 * the case that isn't actually used at the moment anyway.
-	 */
-	if (!sync && !force_flush) {
-		if (!spin_trylock(&purge_lock))
-			return;
-	} else
-		spin_lock(&purge_lock);
-
-	if (sync)
-		purge_fragmented_blocks_allcpus();
+	lockdep_assert_held(&vmap_purge_lock);
 
 	valist = llist_del_all(&vmap_purge_list);
 	llist_for_each_entry(va, valist, purge_list) {
-		if (va->va_start < *start)
-			*start = va->va_start;
-		if (va->va_end > *end)
-			*end = va->va_end;
-		nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
+		if (va->va_start < start)
+			start = va->va_start;
+		if (va->va_end > end)
+			end = va->va_end;
+		do_free = true;
 	}
 
-	if (nr)
+	if (!do_free)
+		return false;
+
+	flush_tlb_kernel_range(start, end);
+
+	spin_lock(&vmap_area_lock);
+	llist_for_each_entry_safe(va, n_va, valist, purge_list) {
+		int nr = (va->va_end - va->va_start) >> PAGE_SHIFT;
+
+		__free_vmap_area(va);
 		atomic_sub(nr, &vmap_lazy_nr);
-
-	if (nr || force_flush)
-		flush_tlb_kernel_range(*start, *end);
-
-	if (nr) {
-		spin_lock(&vmap_area_lock);
-		llist_for_each_entry_safe(va, n_va, valist, purge_list)
-			__free_vmap_area(va);
-		spin_unlock(&vmap_area_lock);
+		cond_resched_lock(&vmap_area_lock);
 	}
-	spin_unlock(&purge_lock);
+	spin_unlock(&vmap_area_lock);
+	return true;
 }
 
 /*
@@ -737,9 +725,10 @@
  */
 static void try_purge_vmap_area_lazy(void)
 {
-	unsigned long start = ULONG_MAX, end = 0;
-
-	__purge_vmap_area_lazy(&start, &end, 0, 0);
+	if (mutex_trylock(&vmap_purge_lock)) {
+		__purge_vmap_area_lazy(ULONG_MAX, 0);
+		mutex_unlock(&vmap_purge_lock);
+	}
 }
 
 /*
@@ -747,9 +736,10 @@
  */
 static void purge_vmap_area_lazy(void)
 {
-	unsigned long start = ULONG_MAX, end = 0;
-
-	__purge_vmap_area_lazy(&start, &end, 1, 0);
+	mutex_lock(&vmap_purge_lock);
+	purge_fragmented_blocks_allcpus();
+	__purge_vmap_area_lazy(ULONG_MAX, 0);
+	mutex_unlock(&vmap_purge_lock);
 }
 
 /*
@@ -772,22 +762,13 @@
 }
 
 /*
- * Free and unmap a vmap area, caller ensuring flush_cache_vunmap had been
- * called for the correct range previously.
- */
-static void free_unmap_vmap_area_noflush(struct vmap_area *va)
-{
-	unmap_vmap_area(va);
-	free_vmap_area_noflush(va);
-}
-
-/*
  * Free and unmap a vmap area
  */
 static void free_unmap_vmap_area(struct vmap_area *va)
 {
 	flush_cache_vunmap(va->va_start, va->va_end);
-	free_unmap_vmap_area_noflush(va);
+	unmap_vmap_area(va);
+	free_vmap_area_noflush(va);
 }
 
 static struct vmap_area *find_vmap_area(unsigned long addr)
@@ -801,16 +782,6 @@
 	return va;
 }
 
-static void free_unmap_vmap_area_addr(unsigned long addr)
-{
-	struct vmap_area *va;
-
-	va = find_vmap_area(addr);
-	BUG_ON(!va);
-	free_unmap_vmap_area(va);
-}
-
-
 /*** Per cpu kva allocator ***/
 
 /*
@@ -1131,6 +1102,8 @@
 	if (unlikely(!vmap_initialized))
 		return;
 
+	might_sleep();
+
 	for_each_possible_cpu(cpu) {
 		struct vmap_block_queue *vbq = &per_cpu(vmap_block_queue, cpu);
 		struct vmap_block *vb;
@@ -1155,7 +1128,11 @@
 		rcu_read_unlock();
 	}
 
-	__purge_vmap_area_lazy(&start, &end, 1, flush);
+	mutex_lock(&vmap_purge_lock);
+	purge_fragmented_blocks_allcpus();
+	if (!__purge_vmap_area_lazy(start, end) && flush)
+		flush_tlb_kernel_range(start, end);
+	mutex_unlock(&vmap_purge_lock);
 }
 EXPORT_SYMBOL_GPL(vm_unmap_aliases);
 
@@ -1168,7 +1145,9 @@
 {
 	unsigned long size = (unsigned long)count << PAGE_SHIFT;
 	unsigned long addr = (unsigned long)mem;
+	struct vmap_area *va;
 
+	might_sleep();
 	BUG_ON(!addr);
 	BUG_ON(addr < VMALLOC_START);
 	BUG_ON(addr > VMALLOC_END);
@@ -1177,10 +1156,14 @@
 	debug_check_no_locks_freed(mem, size);
 	vmap_debug_free_range(addr, addr+size);
 
-	if (likely(count <= VMAP_MAX_ALLOC))
+	if (likely(count <= VMAP_MAX_ALLOC)) {
 		vb_free(mem, size);
-	else
-		free_unmap_vmap_area_addr(addr);
+		return;
+	}
+
+	va = find_vmap_area(addr);
+	BUG_ON(!va);
+	free_unmap_vmap_area(va);
 }
 EXPORT_SYMBOL(vm_unmap_ram);
 
@@ -1554,6 +1537,8 @@
 {
 	struct vmap_area *va;
 
+	might_sleep();
+
 	va = find_vmap_area((unsigned long)addr);
 	if (va && va->flags & VM_VM_AREA) {
 		struct vm_struct *vm = va->vm;
@@ -1609,7 +1594,39 @@
 	kfree(area);
 	return;
 }
- 
+
+static inline void __vfree_deferred(const void *addr)
+{
+	/*
+	 * Use raw_cpu_ptr() because this can be called from preemptible
+	 * context. Preemption is absolutely fine here, because the llist_add()
+	 * implementation is lockless, so it works even if we are adding to
+	 * nother cpu's list.  schedule_work() should be fine with this too.
+	 */
+	struct vfree_deferred *p = raw_cpu_ptr(&vfree_deferred);
+
+	if (llist_add((struct llist_node *)addr, &p->list))
+		schedule_work(&p->wq);
+}
+
+/**
+ *	vfree_atomic  -  release memory allocated by vmalloc()
+ *	@addr:		memory base address
+ *
+ *	This one is just like vfree() but can be called in any atomic context
+ *	except NMIs.
+ */
+void vfree_atomic(const void *addr)
+{
+	BUG_ON(in_nmi());
+
+	kmemleak_free(addr);
+
+	if (!addr)
+		return;
+	__vfree_deferred(addr);
+}
+
 /**
  *	vfree  -  release memory allocated by vmalloc()
  *	@addr:		memory base address
@@ -1632,11 +1649,9 @@
 
 	if (!addr)
 		return;
-	if (unlikely(in_interrupt())) {
-		struct vfree_deferred *p = this_cpu_ptr(&vfree_deferred);
-		if (llist_add((struct llist_node *)addr, &p->list))
-			schedule_work(&p->wq);
-	} else
+	if (unlikely(in_interrupt()))
+		__vfree_deferred(addr);
+	else
 		__vunmap(addr, 1);
 }
 EXPORT_SYMBOL(vfree);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 42098b4..513c37a 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1122,6 +1122,7 @@
 
 /* Walk all the zones in a node and print using a callback */
 static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
+		bool nolock,
 		void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
 {
 	struct zone *zone;
@@ -1132,9 +1133,11 @@
 		if (!populated_zone(zone))
 			continue;
 
-		spin_lock_irqsave(&zone->lock, flags);
+		if (!nolock)
+			spin_lock_irqsave(&zone->lock, flags);
 		print(m, pgdat, zone);
-		spin_unlock_irqrestore(&zone->lock, flags);
+		if (!nolock)
+			spin_unlock_irqrestore(&zone->lock, flags);
 	}
 }
 #endif
@@ -1157,7 +1160,7 @@
 static int frag_show(struct seq_file *m, void *arg)
 {
 	pg_data_t *pgdat = (pg_data_t *)arg;
-	walk_zones_in_node(m, pgdat, frag_show_print);
+	walk_zones_in_node(m, pgdat, false, frag_show_print);
 	return 0;
 }
 
@@ -1198,7 +1201,7 @@
 		seq_printf(m, "%6d ", order);
 	seq_putc(m, '\n');
 
-	walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print);
+	walk_zones_in_node(m, pgdat, false, pagetypeinfo_showfree_print);
 
 	return 0;
 }
@@ -1250,7 +1253,8 @@
 	for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
 		seq_printf(m, "%12s ", migratetype_names[mtype]);
 	seq_putc(m, '\n');
-	walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print);
+	walk_zones_in_node(m, pgdat, false,
+		pagetypeinfo_showblockcount_print);
 
 	return 0;
 }
@@ -1276,7 +1280,8 @@
 		seq_printf(m, "%12s ", migratetype_names[mtype]);
 	seq_putc(m, '\n');
 
-	walk_zones_in_node(m, pgdat, pagetypeinfo_showmixedcount_print);
+	walk_zones_in_node(m, pgdat, true,
+		pagetypeinfo_showmixedcount_print);
 #endif /* CONFIG_PAGE_OWNER */
 }
 
@@ -1433,7 +1438,7 @@
 static int zoneinfo_show(struct seq_file *m, void *arg)
 {
 	pg_data_t *pgdat = (pg_data_t *)arg;
-	walk_zones_in_node(m, pgdat, zoneinfo_show_print);
+	walk_zones_in_node(m, pgdat, false, zoneinfo_show_print);
 	return 0;
 }
 
@@ -1862,7 +1867,7 @@
 	if (!node_state(pgdat->node_id, N_MEMORY))
 		return 0;
 
-	walk_zones_in_node(m, pgdat, unusable_show_print);
+	walk_zones_in_node(m, pgdat, false, unusable_show_print);
 
 	return 0;
 }
@@ -1914,7 +1919,7 @@
 {
 	pg_data_t *pgdat = (pg_data_t *)arg;
 
-	walk_zones_in_node(m, pgdat, extfrag_show_print);
+	walk_zones_in_node(m, pgdat, false, extfrag_show_print);
 
 	return 0;
 }
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 43faf2a..658c900 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -23,6 +23,7 @@
 #include <linux/debugfs.h>
 #include <linux/scatterlist.h>
 #include <linux/crypto.h>
+#include <crypto/algapi.h>
 #include <crypto/b128ops.h>
 #include <crypto/hash.h>
 
@@ -506,7 +507,7 @@
 	if (err)
 		return false;
 
-	return !memcmp(bdaddr->b, hash, 3);
+	return !crypto_memneq(bdaddr->b, hash, 3);
 }
 
 int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
@@ -559,7 +560,7 @@
 			/* This is unlikely, but we need to check that
 			 * we didn't accidentially generate a debug key.
 			 */
-			if (memcmp(smp->local_sk, debug_sk, 32))
+			if (crypto_memneq(smp->local_sk, debug_sk, 32))
 				break;
 		}
 		smp->debug_key = false;
@@ -973,7 +974,7 @@
 	if (ret)
 		return SMP_UNSPECIFIED;
 
-	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
+	if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) {
 		BT_ERR("Pairing failed (confirmation values mismatch)");
 		return SMP_CONFIRM_FAILED;
 	}
@@ -1473,7 +1474,7 @@
 			   smp->rrnd, r, cfm))
 			return SMP_UNSPECIFIED;
 
-		if (memcmp(smp->pcnf, cfm, 16))
+		if (crypto_memneq(smp->pcnf, cfm, 16))
 			return SMP_CONFIRM_FAILED;
 
 		smp->passkey_round++;
@@ -1857,7 +1858,7 @@
 			/* This is unlikely, but we need to check that
 			 * we didn't accidentially generate a debug key.
 			 */
-			if (memcmp(smp->local_sk, debug_sk, 32))
+			if (crypto_memneq(smp->local_sk, debug_sk, 32))
 				break;
 		}
 	}
@@ -2122,7 +2123,7 @@
 		if (err)
 			return SMP_UNSPECIFIED;
 
-		if (memcmp(smp->pcnf, cfm, 16))
+		if (crypto_memneq(smp->pcnf, cfm, 16))
 			return SMP_CONFIRM_FAILED;
 	} else {
 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
@@ -2603,7 +2604,7 @@
 		if (err)
 			return SMP_UNSPECIFIED;
 
-		if (memcmp(cfm.confirm_val, smp->pcnf, 16))
+		if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16))
 			return SMP_CONFIRM_FAILED;
 	}
 
@@ -2636,7 +2637,7 @@
 	else
 		hcon->pending_sec_level = BT_SECURITY_FIPS;
 
-	if (!memcmp(debug_pk, smp->remote_pk, 64))
+	if (!crypto_memneq(debug_pk, smp->remote_pk, 64))
 		set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
 
 	if (smp->method == DSP_PASSKEY) {
@@ -2735,7 +2736,7 @@
 	if (err)
 		return SMP_UNSPECIFIED;
 
-	if (memcmp(check->e, e, 16))
+	if (crypto_memneq(check->e, e, 16))
 		return SMP_DHKEY_CHECK_FAILED;
 
 	if (!hcon->out) {
@@ -3446,7 +3447,7 @@
 	if (err)
 		return err;
 
-	if (memcmp(res, exp, 3))
+	if (crypto_memneq(res, exp, 3))
 		return -EINVAL;
 
 	return 0;
@@ -3476,7 +3477,7 @@
 	if (err)
 		return err;
 
-	if (memcmp(res, exp, 16))
+	if (crypto_memneq(res, exp, 16))
 		return -EINVAL;
 
 	return 0;
@@ -3501,7 +3502,7 @@
 	if (err)
 		return err;
 
-	if (memcmp(res, exp, 16))
+	if (crypto_memneq(res, exp, 16))
 		return -EINVAL;
 
 	return 0;
@@ -3533,7 +3534,7 @@
 	if (err)
 		return err;
 
-	if (memcmp(res, exp, 16))
+	if (crypto_memneq(res, exp, 16))
 		return -EINVAL;
 
 	return 0;
@@ -3567,10 +3568,10 @@
 	if (err)
 		return err;
 
-	if (memcmp(mackey, exp_mackey, 16))
+	if (crypto_memneq(mackey, exp_mackey, 16))
 		return -EINVAL;
 
-	if (memcmp(ltk, exp_ltk, 16))
+	if (crypto_memneq(ltk, exp_ltk, 16))
 		return -EINVAL;
 
 	return 0;
@@ -3603,7 +3604,7 @@
 	if (err)
 		return err;
 
-	if (memcmp(res, exp, 16))
+	if (crypto_memneq(res, exp, 16))
 		return -EINVAL;
 
 	return 0;
@@ -3657,7 +3658,7 @@
 	if (err)
 		return err;
 
-	if (memcmp(res, exp, 16))
+	if (crypto_memneq(res, exp, 16))
 		return -EINVAL;
 
 	return 0;
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 7dbc80d..6406010e 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -323,7 +323,8 @@
 			__mdb_entry_to_br_ip(entry, &complete_info->ip);
 			mdb.obj.complete_priv = complete_info;
 			mdb.obj.complete = br_mdb_complete;
-			switchdev_port_obj_add(port_dev, &mdb.obj);
+			if (switchdev_port_obj_add(port_dev, &mdb.obj))
+				kfree(complete_info);
 		}
 	} else if (port_dev && type == RTM_DELMDB) {
 		switchdev_port_obj_del(port_dev, &mdb.obj);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8c1860a..7e168d0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4648,6 +4648,12 @@
 }
 EXPORT_SYMBOL(gro_find_complete_by_type);
 
+static void napi_skb_free_stolen_head(struct sk_buff *skb)
+{
+	skb_dst_drop(skb);
+	kmem_cache_free(skbuff_head_cache, skb);
+}
+
 static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
 	switch (ret) {
@@ -4661,12 +4667,10 @@
 		break;
 
 	case GRO_MERGED_FREE:
-		if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
-			skb_dst_drop(skb);
-			kmem_cache_free(skbuff_head_cache, skb);
-		} else {
+		if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
+			napi_skb_free_stolen_head(skb);
+		else
 			__kfree_skb(skb);
-		}
 		break;
 
 	case GRO_HELD:
@@ -4736,10 +4740,16 @@
 		break;
 
 	case GRO_DROP:
-	case GRO_MERGED_FREE:
 		napi_reuse_skb(napi, skb);
 		break;
 
+	case GRO_MERGED_FREE:
+		if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
+			napi_skb_free_stolen_head(skb);
+		else
+			napi_reuse_skb(napi, skb);
+		break;
+
 	case GRO_MERGED:
 		break;
 	}
@@ -7551,7 +7561,7 @@
 {
 #if BITS_PER_LONG == 64
 	BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats));
-	memcpy(stats64, netdev_stats, sizeof(*stats64));
+	memcpy(stats64, netdev_stats, sizeof(*netdev_stats));
 	/* zero out counters that only exist in rtnl_link_stats64 */
 	memset((char *)stats64 + sizeof(*netdev_stats), 0,
 	       sizeof(*stats64) - sizeof(*netdev_stats));
@@ -7593,9 +7603,9 @@
 	} else {
 		netdev_stats_to_stats64(storage, &dev->stats);
 	}
-	storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
-	storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
-	storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
+	storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped);
+	storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped);
+	storage->rx_nohandler += (unsigned long)atomic_long_read(&dev->rx_nohandler);
 	return storage;
 }
 EXPORT_SYMBOL(dev_get_stats);
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index 7c8af29f..a28b1af 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -363,6 +363,8 @@
 			svc_id = rport_ptr->server->name.service;
 			svc_ins = rport_ptr->server->name.instance;
 			port_type = CLIENT_PORT;
+			port_ptr->last_served_svc_id =
+					rport_ptr->server->name.service;
 		} else if (port_ptr && (port_ptr->type == SERVER_PORT)) {
 			svc_id = port_ptr->port_name.service;
 			svc_ins = port_ptr->port_name.instance;
@@ -1330,8 +1332,9 @@
 	mutex_init(&port_ptr->port_rx_q_lock_lhc3);
 	init_waitqueue_head(&port_ptr->port_rx_wait_q);
 	snprintf(port_ptr->rx_ws_name, MAX_WS_NAME_SZ,
-		 "ipc%08x_%s",
+		 "ipc%08x_%d_%s",
 		 port_ptr->this_port.port_id,
+		 task_pid_nr(current),
 		 current->comm);
 	port_ptr->port_rx_ws = wakeup_source_register(port_ptr->rx_ws_name);
 	if (!port_ptr->port_rx_ws) {
@@ -3847,15 +3850,18 @@
 	int j;
 	struct msm_ipc_port *port_ptr;
 
-	seq_printf(s, "%-11s|%-11s|\n", "Node_id", "Port_id");
+	seq_printf(s, "%-11s|%-11s|%-32s|%-11s|\n",
+		   "Node_id", "Port_id", "Wakelock", "Last SVCID");
 	seq_puts(s, "------------------------------------------------------------\n");
 	down_read(&local_ports_lock_lhc2);
 	for (j = 0; j < LP_HASH_SIZE; j++) {
 		list_for_each_entry(port_ptr, &local_ports[j], list) {
 			mutex_lock(&port_ptr->port_lock_lhc3);
-			seq_printf(s, "0x%08x |0x%08x |\n",
+			seq_printf(s, "0x%08x |0x%08x |%-32s|0x%08x |\n",
 				   port_ptr->this_port.node_id,
-				   port_ptr->this_port.port_id);
+				   port_ptr->this_port.port_id,
+				   port_ptr->rx_ws_name,
+				   port_ptr->last_served_svc_id);
 			mutex_unlock(&port_ptr->port_lock_lhc3);
 		}
 	}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c27382f..7c90130 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2309,6 +2309,8 @@
 	tcp_init_send_head(sk);
 	memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
 	__sk_dst_reset(sk);
+	dst_release(sk->sk_rx_dst);
+	sk->sk_rx_dst = NULL;
 	tcp_saved_syn_free(tp);
 
 	WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f24b9f4..fe5305a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1879,15 +1879,7 @@
 	if (dad_failed)
 		ifp->flags |= IFA_F_DADFAILED;
 
-	if (ifp->flags&IFA_F_PERMANENT) {
-		spin_lock_bh(&ifp->lock);
-		addrconf_del_dad_work(ifp);
-		ifp->flags |= IFA_F_TENTATIVE;
-		spin_unlock_bh(&ifp->lock);
-		if (dad_failed)
-			ipv6_ifa_notify(0, ifp);
-		in6_ifa_put(ifp);
-	} else if (ifp->flags&IFA_F_TEMPORARY) {
+	if (ifp->flags&IFA_F_TEMPORARY) {
 		struct inet6_ifaddr *ifpub;
 		spin_lock_bh(&ifp->lock);
 		ifpub = ifp->ifpub;
@@ -1900,6 +1892,14 @@
 			spin_unlock_bh(&ifp->lock);
 		}
 		ipv6_del_addr(ifp);
+	} else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) {
+		spin_lock_bh(&ifp->lock);
+		addrconf_del_dad_work(ifp);
+		ifp->flags |= IFA_F_TENTATIVE;
+		spin_unlock_bh(&ifp->lock);
+		if (dad_failed)
+			ipv6_ifa_notify(0, ifp);
+		in6_ifa_put(ifp);
 	} else {
 		ipv6_del_addr(ifp);
 	}
@@ -3356,6 +3356,7 @@
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct netdev_notifier_changeupper_info *info;
 	struct inet6_dev *idev = __in6_dev_get(dev);
+	struct net *net = dev_net(dev);
 	int run_pending = 0;
 	int err;
 
@@ -3371,7 +3372,7 @@
 	case NETDEV_CHANGEMTU:
 		/* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
 		if (dev->mtu < IPV6_MIN_MTU) {
-			addrconf_ifdown(dev, 1);
+			addrconf_ifdown(dev, dev != net->loopback_dev);
 			break;
 		}
 
@@ -3487,7 +3488,7 @@
 			 * IPV6_MIN_MTU stop IPv6 on this interface.
 			 */
 			if (dev->mtu < IPV6_MIN_MTU)
-				addrconf_ifdown(dev, 1);
+				addrconf_ifdown(dev, dev != net->loopback_dev);
 		}
 		break;
 
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 636d4d8..4345ee3 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -771,10 +771,7 @@
 				goto next_iter;
 			}
 
-			if (iter->dst.dev == rt->dst.dev &&
-			    iter->rt6i_idev == rt->rt6i_idev &&
-			    ipv6_addr_equal(&iter->rt6i_gateway,
-					    &rt->rt6i_gateway)) {
+			if (rt6_duplicate_nexthop(iter, rt)) {
 				if (rt->rt6i_nsiblings)
 					rt->rt6i_nsiblings = 0;
 				if (!(iter->rt6i_flags & RTF_EXPIRES))
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0b21d61..d8123f6 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2922,17 +2922,11 @@
 				 struct rt6_info *rt, struct fib6_config *r_cfg)
 {
 	struct rt6_nh *nh;
-	struct rt6_info *rtnh;
 	int err = -EEXIST;
 
 	list_for_each_entry(nh, rt6_nh_list, next) {
 		/* check if rt6_info already exists */
-		rtnh = nh->rt6_info;
-
-		if (rtnh->dst.dev == rt->dst.dev &&
-		    rtnh->rt6i_idev == rt->rt6i_idev &&
-		    ipv6_addr_equal(&rtnh->rt6i_gateway,
-				    &rt->rt6i_gateway))
+		if (rt6_duplicate_nexthop(nh->rt6_info, rt))
 			return err;
 	}
 
diff --git a/net/key/af_key.c b/net/key/af_key.c
index e67c28e..d8d95b6 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -65,6 +65,10 @@
 	} dump;
 };
 
+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
+			       xfrm_address_t *saddr, xfrm_address_t *daddr,
+			       u16 *family);
+
 static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
 {
 	return (struct pfkey_sock *)sk;
@@ -1922,19 +1926,14 @@
 
 	/* addresses present only in tunnel mode */
 	if (t->mode == XFRM_MODE_TUNNEL) {
-		u8 *sa = (u8 *) (rq + 1);
-		int family, socklen;
+		int err;
 
-		family = pfkey_sockaddr_extract((struct sockaddr *)sa,
-						&t->saddr);
-		if (!family)
-			return -EINVAL;
-
-		socklen = pfkey_sockaddr_len(family);
-		if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
-					   &t->id.daddr) != family)
-			return -EINVAL;
-		t->encap_family = family;
+		err = parse_sockaddr_pair(
+			(struct sockaddr *)(rq + 1),
+			rq->sadb_x_ipsecrequest_len - sizeof(*rq),
+			&t->saddr, &t->id.daddr, &t->encap_family);
+		if (err)
+			return err;
 	} else
 		t->encap_family = xp->family;
 
@@ -1954,7 +1953,11 @@
 	if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
 		return -EINVAL;
 
-	while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+	while (len >= sizeof(*rq)) {
+		if (len < rq->sadb_x_ipsecrequest_len ||
+		    rq->sadb_x_ipsecrequest_len < sizeof(*rq))
+			return -EINVAL;
+
 		if ((err = parse_ipsecrequest(xp, rq)) < 0)
 			return err;
 		len -= rq->sadb_x_ipsecrequest_len;
@@ -2417,7 +2420,6 @@
 	return err;
 }
 
-#ifdef CONFIG_NET_KEY_MIGRATE
 static int pfkey_sockaddr_pair_size(sa_family_t family)
 {
 	return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
@@ -2429,7 +2431,7 @@
 {
 	int af, socklen;
 
-	if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
+	if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
 		return -EINVAL;
 
 	af = pfkey_sockaddr_extract(sa, saddr);
@@ -2445,6 +2447,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET_KEY_MIGRATE
 static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
 				    struct xfrm_migrate *m)
 {
@@ -2452,13 +2455,14 @@
 	struct sadb_x_ipsecrequest *rq2;
 	int mode;
 
-	if (len <= sizeof(struct sadb_x_ipsecrequest) ||
-	    len < rq1->sadb_x_ipsecrequest_len)
+	if (len < sizeof(*rq1) ||
+	    len < rq1->sadb_x_ipsecrequest_len ||
+	    rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
 		return -EINVAL;
 
 	/* old endoints */
 	err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
-				  rq1->sadb_x_ipsecrequest_len,
+				  rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
 				  &m->old_saddr, &m->old_daddr,
 				  &m->old_family);
 	if (err)
@@ -2467,13 +2471,14 @@
 	rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
 	len -= rq1->sadb_x_ipsecrequest_len;
 
-	if (len <= sizeof(struct sadb_x_ipsecrequest) ||
-	    len < rq2->sadb_x_ipsecrequest_len)
+	if (len <= sizeof(*rq2) ||
+	    len < rq2->sadb_x_ipsecrequest_len ||
+	    rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
 		return -EINVAL;
 
 	/* new endpoints */
 	err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
-				  rq2->sadb_x_ipsecrequest_len,
+				  rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
 				  &m->new_saddr, &m->new_daddr,
 				  &m->new_family);
 	if (err)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1118c61..b2c706c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4486,20 +4486,20 @@
 		return -EOPNOTSUPP;
 	}
 
-	auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
+	auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
 			    req->ie_len, GFP_KERNEL);
 	if (!auth_data)
 		return -ENOMEM;
 
 	auth_data->bss = req->bss;
 
-	if (req->sae_data_len >= 4) {
-		__le16 *pos = (__le16 *) req->sae_data;
+	if (req->auth_data_len >= 4) {
+		__le16 *pos = (__le16 *)req->auth_data;
 		auth_data->sae_trans = le16_to_cpu(pos[0]);
 		auth_data->sae_status = le16_to_cpu(pos[1]);
-		memcpy(auth_data->data, req->sae_data + 4,
-		       req->sae_data_len - 4);
-		auth_data->data_len += req->sae_data_len - 4;
+		memcpy(auth_data->data, req->auth_data + 4,
+		       req->auth_data_len - 4);
+		auth_data->data_len += req->auth_data_len - 4;
 	}
 
 	if (req->ie && req->ie_len) {
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 2c1b498..e34d3f6 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -849,10 +849,8 @@
 {
 	unsigned int verdict = NF_DROP;
 
-	if (IP_VS_FWD_METHOD(cp) != 0) {
-		pr_err("shouldn't reach here, because the box is on the "
-		       "half connection in the tun/dr module.\n");
-	}
+	if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+		goto ignore_cp;
 
 	/* Ensure the checksum is correct */
 	if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
@@ -886,6 +884,8 @@
 		ip_vs_notrack(skb);
 	else
 		ip_vs_update_conntrack(skb, cp, 0);
+
+ignore_cp:
 	verdict = NF_ACCEPT;
 
 out:
@@ -1385,8 +1385,11 @@
 	 */
 	cp = pp->conn_out_get(ipvs, af, skb, &iph);
 
-	if (likely(cp))
+	if (likely(cp)) {
+		if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+			goto ignore_cp;
 		return handle_response(af, skb, pd, cp, &iph, hooknum);
+	}
 
 	/* Check for real-server-started requests */
 	if (atomic_read(&ipvs->conn_out_counter)) {
@@ -1444,9 +1447,15 @@
 			}
 		}
 	}
+
+out:
 	IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
 		      "ip_vs_out: packet continues traversal as normal");
 	return NF_ACCEPT;
+
+ignore_cp:
+	__ip_vs_conn_put(cp);
+	goto out;
 }
 
 /*
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 122bb81..5cf33df 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -982,6 +982,8 @@
 			kfree(se);
 	}
 
+	ida_simple_remove(&nfc_index_ida, dev->idx);
+
 	kfree(dev);
 }
 
@@ -1056,6 +1058,7 @@
 				    int tx_headroom, int tx_tailroom)
 {
 	struct nfc_dev *dev;
+	int rc;
 
 	if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
 	    !ops->deactivate_target || !ops->im_transceive)
@@ -1068,6 +1071,15 @@
 	if (!dev)
 		return NULL;
 
+	rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
+	if (rc < 0)
+		goto err_free_dev;
+	dev->idx = rc;
+
+	dev->dev.class = &nfc_class;
+	dev_set_name(&dev->dev, "nfc%d", dev->idx);
+	device_initialize(&dev->dev);
+
 	dev->ops = ops;
 	dev->supported_protocols = supported_protocols;
 	dev->tx_headroom = tx_headroom;
@@ -1090,6 +1102,11 @@
 	}
 
 	return dev;
+
+err_free_dev:
+	kfree(dev);
+
+	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(nfc_allocate_device);
 
@@ -1104,14 +1121,6 @@
 
 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
-	dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
-	if (dev->idx < 0)
-		return dev->idx;
-
-	dev->dev.class = &nfc_class;
-	dev_set_name(&dev->dev, "nfc%d", dev->idx);
-	device_initialize(&dev->dev);
-
 	mutex_lock(&nfc_devlist_mutex);
 	nfc_devlist_generation++;
 	rc = device_add(&dev->dev);
@@ -1149,12 +1158,10 @@
  */
 void nfc_unregister_device(struct nfc_dev *dev)
 {
-	int rc, id;
+	int rc;
 
 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
-	id = dev->idx;
-
 	if (dev->rfkill) {
 		rfkill_unregister(dev->rfkill);
 		rfkill_destroy(dev->rfkill);
@@ -1179,8 +1186,6 @@
 	nfc_devlist_generation++;
 	device_del(&dev->dev);
 	mutex_unlock(&nfc_devlist_mutex);
-
-	ida_simple_remove(&nfc_index_ida, id);
 }
 EXPORT_SYMBOL(nfc_unregister_device);
 
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index b9edf5f..e31dea1 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -76,7 +76,8 @@
 	struct sockaddr_nfc_llcp llcp_addr;
 	int len, ret = 0;
 
-	if (!addr || addr->sa_family != AF_NFC)
+	if (!addr || alen < offsetofend(struct sockaddr, sa_family) ||
+	    addr->sa_family != AF_NFC)
 		return -EINVAL;
 
 	pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
@@ -150,7 +151,8 @@
 	struct sockaddr_nfc_llcp llcp_addr;
 	int len, ret = 0;
 
-	if (!addr || addr->sa_family != AF_NFC)
+	if (!addr || alen < offsetofend(struct sockaddr, sa_family) ||
+	    addr->sa_family != AF_NFC)
 		return -EINVAL;
 
 	pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
@@ -661,8 +663,7 @@
 
 	pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
 
-	if (!addr || len < sizeof(struct sockaddr_nfc) ||
-	    addr->sa_family != AF_NFC)
+	if (!addr || len < sizeof(*addr) || addr->sa_family != AF_NFC)
 		return -EINVAL;
 
 	if (addr->service_name_len == 0 && addr->dsap == 0)
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 61fff42..85a3d9e 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -1173,8 +1173,7 @@
 	return ndev;
 
 free_nfc:
-	kfree(ndev->nfc_dev);
-
+	nfc_free_device(ndev->nfc_dev);
 free_nci:
 	kfree(ndev);
 	return NULL;
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index ea023b3..102c681 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -910,7 +910,9 @@
 	u32 device_idx, target_idx, protocol;
 	int rc;
 
-	if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+	if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+	    !info->attrs[NFC_ATTR_TARGET_INDEX] ||
+	    !info->attrs[NFC_ATTR_PROTOCOLS])
 		return -EINVAL;
 
 	device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index e0b23fb..525b624 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -129,7 +129,7 @@
 	if (!sock) /* module unload or netns delete in progress */
 		return -ENETUNREACH;
 
-	ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family,
+	ret = sock_create_lite(sock->sk->sk_family,
 			       sock->sk->sk_type, sock->sk->sk_protocol,
 			       &new_sock);
 	if (ret)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c2225cc..daf6624 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1008,6 +1008,9 @@
 
 		return sch;
 	}
+	/* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
+	if (ops->destroy)
+		ops->destroy(sch);
 err_out3:
 	dev_put(dev);
 	kfree((char *) sch - sch->padded);
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index e3d0458..2fae8b5 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -627,7 +627,9 @@
 			q->hhf_arrays[i] = hhf_zalloc(HHF_ARRAYS_LEN *
 						      sizeof(u32));
 			if (!q->hhf_arrays[i]) {
-				hhf_destroy(sch);
+				/* Note: hhf_destroy() will be called
+				 * by our caller.
+				 */
 				return -ENOMEM;
 			}
 		}
@@ -638,7 +640,9 @@
 			q->hhf_valid_bits[i] = hhf_zalloc(HHF_ARRAYS_LEN /
 							  BITS_PER_BYTE);
 			if (!q->hhf_valid_bits[i]) {
-				hhf_destroy(sch);
+				/* Note: hhf_destroy() will be called
+				 * by our caller.
+				 */
 				return -ENOMEM;
 			}
 		}
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index 2bc8d7f..20b7f16 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -52,7 +52,7 @@
 	/* pre-allocate qdiscs, attachment can't fail */
 	priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),
 			       GFP_KERNEL);
-	if (priv->qdiscs == NULL)
+	if (!priv->qdiscs)
 		return -ENOMEM;
 
 	for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
@@ -60,18 +60,14 @@
 		qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx),
 					  TC_H_MAKE(TC_H_MAJ(sch->handle),
 						    TC_H_MIN(ntx + 1)));
-		if (qdisc == NULL)
-			goto err;
+		if (!qdisc)
+			return -ENOMEM;
 		priv->qdiscs[ntx] = qdisc;
 		qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
 	}
 
 	sch->flags |= TCQ_F_MQROOT;
 	return 0;
-
-err:
-	mq_destroy(sch);
-	return -ENOMEM;
 }
 
 static void mq_attach(struct Qdisc *sch)
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index b5c502c..9226834 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -118,10 +118,8 @@
 	/* pre-allocate qdisc, attachment can't fail */
 	priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),
 			       GFP_KERNEL);
-	if (priv->qdiscs == NULL) {
-		err = -ENOMEM;
-		goto err;
-	}
+	if (!priv->qdiscs)
+		return -ENOMEM;
 
 	for (i = 0; i < dev->num_tx_queues; i++) {
 		dev_queue = netdev_get_tx_queue(dev, i);
@@ -129,10 +127,9 @@
 					  get_default_qdisc_ops(dev, i),
 					  TC_H_MAKE(TC_H_MAJ(sch->handle),
 						    TC_H_MIN(i + 1)));
-		if (qdisc == NULL) {
-			err = -ENOMEM;
-			goto err;
-		}
+		if (!qdisc)
+			return -ENOMEM;
+
 		priv->qdiscs[i] = qdisc;
 		qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
 	}
@@ -148,7 +145,7 @@
 		priv->hw_owned = 1;
 		err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
 		if (err)
-			goto err;
+			return err;
 	} else {
 		netdev_set_num_tc(dev, qopt->num_tc);
 		for (i = 0; i < qopt->num_tc; i++)
@@ -162,10 +159,6 @@
 
 	sch->flags |= TCQ_F_MQROOT;
 	return 0;
-
-err:
-	mqprio_destroy(sch);
-	return err;
 }
 
 static void mqprio_attach(struct Qdisc *sch)
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 7f195ed..bc5e995 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -742,9 +742,10 @@
 	q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
 	q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows);
 	if (!q->ht || !q->slots) {
-		sfq_destroy(sch);
+		/* Note: sfq_destroy() will be called by our caller */
 		return -ENOMEM;
 	}
+
 	for (i = 0; i < q->divisor; i++)
 		q->ht[i] = SFQ_EMPTY_SLOT;
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 90115ce..79aec90 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -34,6 +34,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include <crypto/algapi.h>
 #include <crypto/hash.h>
 #include <crypto/skcipher.h>
 #include <linux/err.h>
@@ -927,7 +928,7 @@
 	if (ret)
 		goto out_err;
 
-	if (memcmp(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) {
+	if (crypto_memneq(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) {
 		ret = GSS_S_BAD_SIG;
 		goto out_err;
 	}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 80890c0..cf7063a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -220,15 +220,7 @@
 	enum cfg80211_event_type type;
 
 	union {
-		struct {
-			u8 bssid[ETH_ALEN];
-			const u8 *req_ie;
-			const u8 *resp_ie;
-			size_t req_ie_len;
-			size_t resp_ie_len;
-			struct cfg80211_bss *bss;
-			int status; /* -1 = failed; 0..65535 = status code */
-		} cr;
+		struct cfg80211_connect_resp_params cr;
 		struct {
 			const u8 *req_ie;
 			const u8 *resp_ie;
@@ -346,7 +338,7 @@
 		       const u8 *ssid, int ssid_len,
 		       const u8 *ie, int ie_len,
 		       const u8 *key, int key_len, int key_idx,
-		       const u8 *sae_data, int sae_data_len);
+		       const u8 *auth_data, int auth_data_len);
 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			struct net_device *dev,
 			struct ieee80211_channel *chan,
@@ -384,11 +376,9 @@
 		     struct cfg80211_connect_params *connect,
 		     struct cfg80211_cached_keys *connkeys,
 		     const u8 *prev_bssid);
-void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
-			       const u8 *req_ie, size_t req_ie_len,
-			       const u8 *resp_ie, size_t resp_ie_len,
-			       int status, bool wextev,
-			       struct cfg80211_bss *bss);
+void __cfg80211_connect_result(struct net_device *dev,
+			       struct cfg80211_connect_resp_params *params,
+			       bool wextev);
 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
 			     size_t ie_len, u16 reason, bool from_ap);
 int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index a2dff71..413deff 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -538,6 +538,12 @@
 	(5490 - 5730 @ 160), (24), DFS
 	(5735 - 5835 @ 80), (30)
 
+country GI: DFS-ETSI
+	(2402 - 2482 @ 40), (20)
+	(5170 - 5250 @ 80), (23), AUTO-BW
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5490 - 5710 @ 160), (30), DFS
+
 country GL: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
@@ -678,10 +684,6 @@
 	(5170 - 5330 @ 160), (23)
 	(5735 - 5835 @ 80), (30)
 
-country IR:
-	(2402 - 2482 @ 40), (20)
-	(5735 - 5835 @ 80), (30)
-
 country IS: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
@@ -764,19 +766,12 @@
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (20), AUTO-BW
 	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
-	(5490 - 5710 @ 160), (30), DFS
+	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5835 @ 80), (30)
 	# 60 GHz band channels 1-4,
 	# ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99
 	(57240 - 65880 @ 2160), (43)
 
-country KP: DFS-ETSI
-	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (20)
-	(5250 - 5330 @ 80), (20), DFS
-	(5490 - 5630 @ 80), (30), DFS
-	(5735 - 5815 @ 80), (30)
-
 country KW: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
@@ -1022,7 +1017,7 @@
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
 	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
-	(5490 - 5710 @ 160), (30), DFS
+	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5835 @ 80), (33)
 
 country NG: DFS-ETSI
@@ -1338,9 +1333,6 @@
 	(5250 - 5330 @ 20), (23), DFS
 	(5735 - 5835 @ 20), (30)
 
-country SY:
-	(2402 - 2482 @ 40), (20)
-
 country TC: DFS-FCC
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (24), AUTO-BW
@@ -1426,7 +1418,7 @@
 
 country US: DFS-FCC
 	(2402 - 2472 @ 40), (30)
-	(5170 - 5250 @ 80), (24), AUTO-BW
+	(5170 - 5250 @ 80), (30), AUTO-BW
 	(5250 - 5330 @ 80), (24), DFS, AUTO-BW
 	(5490 - 5730 @ 160), (24), DFS
 	(5735 - 5835 @ 80), (30)
@@ -1467,7 +1459,7 @@
 	(5490 - 5710 @ 160), (30), DFS
 
 country VE: DFS-FCC
-	(2402 - 2482 @ 40), (30)
+	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
         (5250 - 5330 @ 80), (23), DFS, AUTO-BW
 	(5735 - 5835 @ 80), (30)
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 76775a2..5499e9f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -26,9 +26,16 @@
 	struct wiphy *wiphy = wdev->wiphy;
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
-	u8 *ie = mgmt->u.assoc_resp.variable;
-	int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
-	u16 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+	struct cfg80211_connect_resp_params cr;
+
+	memset(&cr, 0, sizeof(cr));
+	cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code);
+	cr.bssid = mgmt->bssid;
+	cr.bss = bss;
+	cr.resp_ie = mgmt->u.assoc_resp.variable;
+	cr.resp_ie_len =
+		len - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+	cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED;
 
 	trace_cfg80211_send_rx_assoc(dev, bss);
 
@@ -38,7 +45,7 @@
 	 * and got a reject -- we only try again with an assoc
 	 * frame instead of reassoc.
 	 */
-	if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) {
+	if (cfg80211_sme_rx_assoc_resp(wdev, cr.status)) {
 		cfg80211_unhold_bss(bss_from_pub(bss));
 		cfg80211_put_bss(wiphy, bss);
 		return;
@@ -46,9 +53,7 @@
 
 	nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues);
 	/* update current_bss etc., consumes the bss reference */
-	__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
-				  status_code,
-				  status_code == WLAN_STATUS_SUCCESS, bss);
+	__cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS);
 }
 EXPORT_SYMBOL(cfg80211_rx_assoc_resp);
 
@@ -216,14 +221,14 @@
 		       const u8 *ssid, int ssid_len,
 		       const u8 *ie, int ie_len,
 		       const u8 *key, int key_len, int key_idx,
-		       const u8 *sae_data, int sae_data_len)
+		       const u8 *auth_data, int auth_data_len)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_auth_request req = {
 		.ie = ie,
 		.ie_len = ie_len,
-		.sae_data = sae_data,
-		.sae_data_len = sae_data_len,
+		.auth_data = auth_data,
+		.auth_data_len = auth_data_len,
 		.auth_type = auth_type,
 		.key = key,
 		.key_len = key_len,
@@ -657,8 +662,25 @@
 			return err;
 	}
 
-	if (!ether_addr_equal(mgmt->sa, wdev_address(wdev)))
-		return -EINVAL;
+	if (!ether_addr_equal(mgmt->sa, wdev_address(wdev))) {
+		/* Allow random TA to be used with Public Action frames if the
+		 * driver has indicated support for this. Otherwise, only allow
+		 * the local address to be used.
+		 */
+		if (!ieee80211_is_action(mgmt->frame_control) ||
+		    mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
+			return -EINVAL;
+		if (!wdev->current_bss &&
+		    !wiphy_ext_feature_isset(
+			    &rdev->wiphy,
+			    NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
+			return -EINVAL;
+		if (wdev->current_bss &&
+		    !wiphy_ext_feature_isset(
+			    &rdev->wiphy,
+			    NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
+			return -EINVAL;
+	}
 
 	/* Transmit the Action frame as requested by user space */
 	return rdev_mgmt_tx(rdev, wdev, params, cookie);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4ba0d590..ebd9a4b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -305,8 +305,7 @@
 	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
 	[NL80211_ATTR_PID] = { .type = NLA_U32 },
 	[NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
-	[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
-				 .len = WLAN_PMKID_LEN },
+	[NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN },
 	[NL80211_ATTR_DURATION] = { .type = NLA_U32 },
 	[NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
 	[NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
@@ -357,11 +356,12 @@
 	[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
 	[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
 	[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
-	[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
+	[NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
 	[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
 	[NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
 	[NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
+	[NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 },
 	[NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
 	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
@@ -414,7 +414,25 @@
 	[NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
 	[NL80211_ATTR_NAN_DUAL] = { .type = NLA_U8 },
 	[NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
+	[NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
+				    .len = FILS_MAX_KEK_LEN },
+	[NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
+	[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
 	[NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
+	[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
+	[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
+		.len = sizeof(struct nl80211_bss_select_rssi_adjust)
+	},
+	[NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
+	[NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
+					     .len = FILS_ERP_MAX_USERNAME_LEN },
+	[NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
+					  .len = FILS_ERP_MAX_REALM_LEN },
+	[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
+	[NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
+					.len = FILS_ERP_MAX_RRK_LEN },
+	[NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
+	[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
 };
 
 /* policy for the key attributes */
@@ -481,7 +499,8 @@
 /* policy for GTK rekey offload attributes */
 static const struct nla_policy
 nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
-	[NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
+	[NL80211_REKEY_DATA_KEK] = { .type = NLA_BINARY,
+				     .len = FILS_MAX_KEK_LEN },
 	[NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
 	[NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
 };
@@ -512,7 +531,7 @@
 static const struct nla_policy
 nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
 	[NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
-	[NL80211_NAN_FUNC_SERVICE_ID] = { .type = NLA_BINARY,
+	[NL80211_NAN_FUNC_SERVICE_ID] = {
 				    .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
 	[NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
 	[NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
@@ -1609,6 +1628,8 @@
 			if (rdev->wiphy.features &
 					NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
 				CMD(add_tx_ts, ADD_TX_TS);
+			CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
+			CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
 		}
 		/* add into the if now */
 #undef CMD
@@ -3747,12 +3768,36 @@
 		if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
 		    auth_type == NL80211_AUTHTYPE_SAE)
 			return false;
+		if (!wiphy_ext_feature_isset(&rdev->wiphy,
+					     NL80211_EXT_FEATURE_FILS_STA) &&
+		    (auth_type == NL80211_AUTHTYPE_FILS_SK ||
+		     auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+		     auth_type == NL80211_AUTHTYPE_FILS_PK))
+			return false;
 		return true;
 	case NL80211_CMD_CONNECT:
+		/* SAE not supported yet */
+		if (auth_type == NL80211_AUTHTYPE_SAE)
+			return false;
+		/* FILS with SK PFS or PK not supported yet */
+		if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+		    auth_type == NL80211_AUTHTYPE_FILS_PK)
+			return false;
+		if (!wiphy_ext_feature_isset(
+			    &rdev->wiphy,
+			    NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
+		    auth_type == NL80211_AUTHTYPE_FILS_SK)
+			return false;
+		return true;
 	case NL80211_CMD_START_AP:
 		/* SAE not supported yet */
 		if (auth_type == NL80211_AUTHTYPE_SAE)
 			return false;
+		/* FILS not supported yet */
+		if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
+		    auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+		    auth_type == NL80211_AUTHTYPE_FILS_PK)
+			return false;
 		return true;
 	default:
 		return false;
@@ -6331,6 +6376,10 @@
 	struct nlattr *attr1, *attr2;
 	int n_channels = 0, tmp1, tmp2;
 
+	nla_for_each_nested(attr1, freqs, tmp1)
+		if (nla_len(attr1) != sizeof(u32))
+			return 0;
+
 	nla_for_each_nested(attr1, freqs, tmp1) {
 		n_channels++;
 		/*
@@ -6923,6 +6972,12 @@
 	if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
 		return ERR_PTR(-EINVAL);
 
+	if (!wiphy_ext_feature_isset(
+		    wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
+	    (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
+	     attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
+		return ERR_PTR(-EINVAL);
+
 	request = kzalloc(sizeof(*request)
 			+ sizeof(*request->ssids) * n_ssids
 			+ sizeof(*request->match_sets) * n_match_sets
@@ -7129,6 +7184,26 @@
 		request->delay =
 			nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
 
+	if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
+		request->relative_rssi = nla_get_s8(
+			attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
+		request->relative_rssi_set = true;
+	}
+
+	if (request->relative_rssi_set &&
+	    attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
+		struct nl80211_bss_select_rssi_adjust *rssi_adjust;
+
+		rssi_adjust = nla_data(
+			attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
+		request->rssi_adjust.band = rssi_adjust->band;
+		request->rssi_adjust.delta = rssi_adjust->delta;
+		if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
+			err = -EINVAL;
+			goto out_free;
+		}
+	}
+
 	err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
 	if (err)
 		goto out_free;
@@ -7724,8 +7799,8 @@
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct net_device *dev = info->user_ptr[1];
 	struct ieee80211_channel *chan;
-	const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
-	int err, ssid_len, ie_len = 0, sae_data_len = 0;
+	const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
+	int err, ssid_len, ie_len = 0, auth_data_len = 0;
 	enum nl80211_auth_type auth_type;
 	struct key_parse key;
 	bool local_state_change;
@@ -7805,17 +7880,23 @@
 	if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
 		return -EINVAL;
 
-	if (auth_type == NL80211_AUTHTYPE_SAE &&
-	    !info->attrs[NL80211_ATTR_SAE_DATA])
+	if ((auth_type == NL80211_AUTHTYPE_SAE ||
+	     auth_type == NL80211_AUTHTYPE_FILS_SK ||
+	     auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+	     auth_type == NL80211_AUTHTYPE_FILS_PK) &&
+	    !info->attrs[NL80211_ATTR_AUTH_DATA])
 		return -EINVAL;
 
-	if (info->attrs[NL80211_ATTR_SAE_DATA]) {
-		if (auth_type != NL80211_AUTHTYPE_SAE)
+	if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
+		if (auth_type != NL80211_AUTHTYPE_SAE &&
+		    auth_type != NL80211_AUTHTYPE_FILS_SK &&
+		    auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
+		    auth_type != NL80211_AUTHTYPE_FILS_PK)
 			return -EINVAL;
-		sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
-		sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
+		auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
+		auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
 		/* need to include at least Auth Transaction and Status Code */
-		if (sae_data_len < 4)
+		if (auth_data_len < 4)
 			return -EINVAL;
 	}
 
@@ -7832,7 +7913,7 @@
 	err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
 				 ssid, ssid_len, ie, ie_len,
 				 key.p.key, key.p.key_len, key.idx,
-				 sae_data, sae_data_len);
+				 auth_data, auth_data_len);
 	wdev_unlock(dev->ieee80211_ptr);
 	return err;
 }
@@ -8011,6 +8092,15 @@
 		req.flags |= ASSOC_REQ_USE_RRM;
 	}
 
+	if (info->attrs[NL80211_ATTR_FILS_KEK]) {
+		req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
+		req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
+		if (!info->attrs[NL80211_ATTR_FILS_NONCES])
+			return -EINVAL;
+		req.fils_nonces =
+			nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
+	}
+
 	err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
 	if (!err) {
 		wdev_lock(dev->ieee80211_ptr);
@@ -8734,6 +8824,35 @@
 		}
 	}
 
+	if (wiphy_ext_feature_isset(&rdev->wiphy,
+				    NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
+		connect.fils_erp_username =
+			nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
+		connect.fils_erp_username_len =
+			nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
+		connect.fils_erp_realm =
+			nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
+		connect.fils_erp_realm_len =
+			nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
+		connect.fils_erp_next_seq_num =
+			nla_get_u16(
+			   info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
+		connect.fils_erp_rrk =
+			nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
+		connect.fils_erp_rrk_len =
+			nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
+	} else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
+		   info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
+		   info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
+		   info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
+		kzfree(connkeys);
+		return -EINVAL;
+	}
+
 	wdev_lock(dev->ieee80211_ptr);
 	err = cfg80211_connect(rdev, dev, &connect, connkeys,
 			       connect.prev_bssid);
@@ -8743,6 +8862,76 @@
 	return err;
 }
 
+static int nl80211_update_connect_params(struct sk_buff *skb,
+					 struct genl_info *info)
+{
+	struct cfg80211_connect_params connect = {};
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	u32 changed = 0;
+	int ret;
+
+	if (!rdev->ops->update_connect_params)
+		return -EOPNOTSUPP;
+
+	if (info->attrs[NL80211_ATTR_IE]) {
+		if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+			return -EINVAL;
+		connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+		connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+		changed |= UPDATE_ASSOC_IES;
+	}
+
+	if (wiphy_ext_feature_isset(&rdev->wiphy,
+				    NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
+	    info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
+		connect.fils_erp_username =
+			nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
+		connect.fils_erp_username_len =
+			nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
+		connect.fils_erp_realm =
+			nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
+		connect.fils_erp_realm_len =
+			nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
+		connect.fils_erp_next_seq_num =
+			nla_get_u16(
+			   info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
+		connect.fils_erp_rrk =
+			nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
+		connect.fils_erp_rrk_len =
+			nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
+		changed |= UPDATE_FILS_ERP_INFO;
+	} else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
+		   info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
+		   info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
+		   info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
+		return -EINVAL;
+	}
+
+	if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
+		u32 auth_type =
+			nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
+		if (!nl80211_valid_auth_type(rdev, auth_type,
+					     NL80211_CMD_CONNECT))
+			return -EINVAL;
+		connect.auth_type = auth_type;
+		changed |= UPDATE_AUTH_TYPE;
+	}
+
+	wdev_lock(dev->ieee80211_ptr);
+	if (!wdev->current_bss)
+		ret = -ENOLINK;
+	else
+		ret = rdev_update_connect_params(rdev, dev, &connect, changed);
+	wdev_unlock(dev->ieee80211_ptr);
+
+	return ret;
+}
+
 static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -8809,14 +8998,28 @@
 
 	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
 
-	if (!info->attrs[NL80211_ATTR_MAC])
-		return -EINVAL;
-
 	if (!info->attrs[NL80211_ATTR_PMKID])
 		return -EINVAL;
 
 	pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
-	pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+	if (info->attrs[NL80211_ATTR_MAC]) {
+		pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+	} else if (info->attrs[NL80211_ATTR_SSID] &&
+		   info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
+		   (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
+		    info->attrs[NL80211_ATTR_PMK])) {
+		pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+		pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+		pmksa.cache_id =
+			nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
+	} else {
+		return -EINVAL;
+	}
+	if (info->attrs[NL80211_ATTR_PMK]) {
+		pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
+		pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
+	}
 
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
 	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
@@ -9604,6 +9807,20 @@
 	if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
 		return -ENOBUFS;
 
+	if (req->relative_rssi_set) {
+		struct nl80211_bss_select_rssi_adjust rssi_adjust;
+
+		if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
+			       req->relative_rssi))
+			return -ENOBUFS;
+
+		rssi_adjust.band = req->rssi_adjust.band;
+		rssi_adjust.delta = req->rssi_adjust.delta;
+		if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+			    sizeof(rssi_adjust), &rssi_adjust))
+			return -ENOBUFS;
+	}
+
 	freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
 	if (!freqs)
 		return -ENOBUFS;
@@ -10392,15 +10609,27 @@
 	if (err)
 		return err;
 
+	if (!tb[NL80211_REKEY_DATA_KEK] || !tb[NL80211_REKEY_DATA_REPLAY_CTR] ||
+	    (!wiphy_ext_feature_isset(&rdev->wiphy,
+				      NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
+	     !wiphy_ext_feature_isset(&rdev->wiphy,
+				      NL80211_EXT_FEATURE_FILS_STA) &&
+	     !tb[NL80211_REKEY_DATA_KCK]))
+		return -EINVAL;
+
 	if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
 		return -ERANGE;
-	if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
+	if (nla_len(tb[NL80211_REKEY_DATA_KEK]) < NL80211_KEK_LEN)
 		return -ERANGE;
-	if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
+	if (tb[NL80211_REKEY_DATA_KCK] &&
+	    nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
 		return -ERANGE;
 
+	memset(&rekey_data, 0, sizeof(rekey_data));
 	rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
-	rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
+	rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
+	if (tb[NL80211_REKEY_DATA_KCK])
+		rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
 	rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
 
 	wdev_lock(wdev);
@@ -11739,6 +11968,31 @@
 	return 0;
 }
 
+static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
+					    struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	const struct nlattr *nla;
+	bool enabled;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	if (!rdev->ops->set_multicast_to_unicast)
+		return -EOPNOTSUPP;
+
+	if (wdev->iftype != NL80211_IFTYPE_AP &&
+	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
+
+	nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
+	enabled = nla_get_flag(nla);
+
+	return rdev_set_multicast_to_unicast(rdev, dev, enabled);
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -12192,6 +12446,14 @@
 				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
+		.cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
+		.doit = nl80211_update_connect_params,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
 		.cmd = NL80211_CMD_DISCONNECT,
 		.doit = nl80211_disconnect,
 		.policy = nl80211_policy,
@@ -12612,6 +12874,14 @@
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+		.doit = nl80211_set_multicast_to_unicast,
+		.policy = nl80211_policy,
+		.flags = GENL_UNS_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 /* notification functions */
@@ -12941,7 +13211,7 @@
 	struct sk_buff *msg;
 	void *hdr;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	msg = nlmsg_new(100 + len, gfp);
 	if (!msg)
 		return;
 
@@ -13085,15 +13355,16 @@
 }
 
 void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
-				 struct net_device *netdev, const u8 *bssid,
-				 const u8 *req_ie, size_t req_ie_len,
-				 const u8 *resp_ie, size_t resp_ie_len,
-				 int status, gfp_t gfp)
+				 struct net_device *netdev,
+				 struct cfg80211_connect_resp_params *cr,
+				 gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
+			cr->fils_kek_len + cr->pmk_len +
+			(cr->pmkid ? WLAN_PMKID_LEN : 0), gfp);
 	if (!msg)
 		return;
 
@@ -13105,15 +13376,31 @@
 
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
-	    (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) ||
+	    (cr->bssid &&
+	     nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, cr->bssid)) ||
 	    nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
-			status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
-			status) ||
-	    (status < 0 && nla_put_flag(msg, NL80211_ATTR_TIMED_OUT)) ||
-	    (req_ie &&
-	     nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
-	    (resp_ie &&
-	     nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie)))
+			cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
+			cr->status) ||
+	    (cr->status < 0 &&
+	     (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
+	      nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
+			  cr->timeout_reason))) ||
+	    (cr->req_ie &&
+	     nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
+	    (cr->resp_ie &&
+	     nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
+		     cr->resp_ie)) ||
+	    (cr->update_erp_next_seq_num &&
+	     nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
+			 cr->fils_erp_next_seq_num)) ||
+	    (cr->status == WLAN_STATUS_SUCCESS &&
+	     ((cr->fils_kek &&
+	       nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils_kek_len,
+		       cr->fils_kek)) ||
+	      (cr->pmk &&
+	       nla_put(msg, NL80211_ATTR_PMK, cr->pmk_len, cr->pmk)) ||
+	      (cr->pmkid &&
+	       nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->pmkid)))))
 		goto nla_put_failure;
 
 	genlmsg_end(msg, hdr);
@@ -13135,7 +13422,7 @@
 	struct sk_buff *msg;
 	void *hdr;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	msg = nlmsg_new(100 + req_ie_len + resp_ie_len, gfp);
 	if (!msg)
 		return;
 
@@ -13172,7 +13459,7 @@
 	struct sk_buff *msg;
 	void *hdr;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
 	if (!msg)
 		return;
 
@@ -13248,7 +13535,7 @@
 
 	trace_cfg80211_notify_new_peer_candidate(dev, addr);
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	msg = nlmsg_new(100 + ie_len, gfp);
 	if (!msg)
 		return;
 
@@ -13619,7 +13906,7 @@
 	struct sk_buff *msg;
 	void *hdr;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	msg = nlmsg_new(100 + len, gfp);
 	if (!msg)
 		return -ENOMEM;
 
@@ -13663,7 +13950,7 @@
 
 	trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	msg = nlmsg_new(100 + len, gfp);
 	if (!msg)
 		return;
 
@@ -14472,7 +14759,7 @@
 	if (!ft_event->target_ap)
 		return;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	msg = nlmsg_new(100 + ft_event->ric_ies_len, GFP_KERNEL);
 	if (!msg)
 		return;
 
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 7e3821d..2a84d18 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -55,10 +55,9 @@
 				struct net_device *netdev,
 				const u8 *addr, gfp_t gfp);
 void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
-				 struct net_device *netdev, const u8 *bssid,
-				 const u8 *req_ie, size_t req_ie_len,
-				 const u8 *resp_ie, size_t resp_ie_len,
-				 int status, gfp_t gfp);
+				 struct net_device *netdev,
+				 struct cfg80211_connect_resp_params *params,
+				 gfp_t gfp);
 void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
 			 struct net_device *netdev, const u8 *bssid,
 			 const u8 *req_ie, size_t req_ie_len,
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 11cf83c..2f42507 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -490,6 +490,18 @@
 	return ret;
 }
 
+static inline int
+rdev_update_connect_params(struct cfg80211_registered_device *rdev,
+			   struct net_device *dev,
+			   struct cfg80211_connect_params *sme, u32 changed)
+{
+	int ret;
+	trace_rdev_update_connect_params(&rdev->wiphy, dev, sme, changed);
+	ret = rdev->ops->update_connect_params(&rdev->wiphy, dev, sme, changed);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 static inline int rdev_disconnect(struct cfg80211_registered_device *rdev,
 				  struct net_device *dev, u16 reason_code)
 {
@@ -562,6 +574,18 @@
 	return ret;
 }
 
+static inline int
+rdev_set_multicast_to_unicast(struct cfg80211_registered_device *rdev,
+			      struct net_device *dev,
+			      const bool enabled)
+{
+	int ret;
+	trace_rdev_set_multicast_to_unicast(&rdev->wiphy, dev, enabled);
+	ret = rdev->ops->set_multicast_to_unicast(&rdev->wiphy, dev, enabled);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
 {
 	trace_rdev_rfkill_poll(&rdev->wiphy);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8ae2e20..d7e6abc 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -34,10 +34,11 @@
 		CFG80211_CONN_SCAN_AGAIN,
 		CFG80211_CONN_AUTHENTICATE_NEXT,
 		CFG80211_CONN_AUTHENTICATING,
-		CFG80211_CONN_AUTH_FAILED,
+		CFG80211_CONN_AUTH_FAILED_TIMEOUT,
 		CFG80211_CONN_ASSOCIATE_NEXT,
 		CFG80211_CONN_ASSOCIATING,
 		CFG80211_CONN_ASSOC_FAILED,
+		CFG80211_CONN_ASSOC_FAILED_TIMEOUT,
 		CFG80211_CONN_DEAUTH,
 		CFG80211_CONN_ABANDON,
 		CFG80211_CONN_CONNECTED,
@@ -163,7 +164,8 @@
 	return err;
 }
 
-static int cfg80211_conn_do_work(struct wireless_dev *wdev)
+static int cfg80211_conn_do_work(struct wireless_dev *wdev,
+				 enum nl80211_timeout_reason *treason)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 	struct cfg80211_connect_params *params;
@@ -194,7 +196,8 @@
 					  NULL, 0,
 					  params->key, params->key_len,
 					  params->key_idx, NULL, 0);
-	case CFG80211_CONN_AUTH_FAILED:
+	case CFG80211_CONN_AUTH_FAILED_TIMEOUT:
+		*treason = NL80211_TIMEOUT_AUTH;
 		return -ENOTCONN;
 	case CFG80211_CONN_ASSOCIATE_NEXT:
 		if (WARN_ON(!rdev->ops->assoc))
@@ -221,6 +224,9 @@
 					     WLAN_REASON_DEAUTH_LEAVING,
 					     false);
 		return err;
+	case CFG80211_CONN_ASSOC_FAILED_TIMEOUT:
+		*treason = NL80211_TIMEOUT_ASSOC;
+		/* fall through */
 	case CFG80211_CONN_ASSOC_FAILED:
 		cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
 				     NULL, 0,
@@ -246,6 +252,7 @@
 		container_of(work, struct cfg80211_registered_device, conn_work);
 	struct wireless_dev *wdev;
 	u8 bssid_buf[ETH_ALEN], *bssid = NULL;
+	enum nl80211_timeout_reason treason;
 
 	rtnl_lock();
 
@@ -267,10 +274,15 @@
 			memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
 			bssid = bssid_buf;
 		}
-		if (cfg80211_conn_do_work(wdev)) {
-			__cfg80211_connect_result(
-					wdev->netdev, bssid,
-					NULL, 0, NULL, 0, -1, false, NULL);
+		treason = NL80211_TIMEOUT_UNSPECIFIED;
+		if (cfg80211_conn_do_work(wdev, &treason)) {
+			struct cfg80211_connect_resp_params cr;
+
+			memset(&cr, 0, sizeof(cr));
+			cr.status = -1;
+			cr.bssid = bssid;
+			cr.timeout_reason = treason;
+			__cfg80211_connect_result(wdev->netdev, &cr, false);
 		}
 		wdev_unlock(wdev);
 	}
@@ -373,9 +385,13 @@
 		wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
 		schedule_work(&rdev->conn_work);
 	} else if (status_code != WLAN_STATUS_SUCCESS) {
-		__cfg80211_connect_result(wdev->netdev, mgmt->bssid,
-					  NULL, 0, NULL, 0,
-					  status_code, false, NULL);
+		struct cfg80211_connect_resp_params cr;
+
+		memset(&cr, 0, sizeof(cr));
+		cr.status = status_code;
+		cr.bssid = mgmt->bssid;
+		cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED;
+		__cfg80211_connect_result(wdev->netdev, &cr, false);
 	} else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
 		wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
 		schedule_work(&rdev->conn_work);
@@ -423,7 +439,7 @@
 	if (!wdev->conn)
 		return;
 
-	wdev->conn->state = CFG80211_CONN_AUTH_FAILED;
+	wdev->conn->state = CFG80211_CONN_AUTH_FAILED_TIMEOUT;
 	schedule_work(&rdev->conn_work);
 }
 
@@ -445,7 +461,7 @@
 	if (!wdev->conn)
 		return;
 
-	wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
+	wdev->conn->state = CFG80211_CONN_ASSOC_FAILED_TIMEOUT;
 	schedule_work(&rdev->conn_work);
 }
 
@@ -587,7 +603,9 @@
 
 	/* we're good if we have a matching bss struct */
 	if (bss) {
-		err = cfg80211_conn_do_work(wdev);
+		enum nl80211_timeout_reason treason;
+
+		err = cfg80211_conn_do_work(wdev, &treason);
 		cfg80211_put_bss(wdev->wiphy, bss);
 	} else {
 		/* otherwise we'll need to scan for the AP first */
@@ -681,11 +699,9 @@
  */
 
 /* This method must consume bss one way or another */
-void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
-			       const u8 *req_ie, size_t req_ie_len,
-			       const u8 *resp_ie, size_t resp_ie_len,
-			       int status, bool wextev,
-			       struct cfg80211_bss *bss)
+void __cfg80211_connect_result(struct net_device *dev,
+			       struct cfg80211_connect_resp_params *cr,
+			       bool wextev)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	const u8 *country_ie;
@@ -697,48 +713,48 @@
 
 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
 		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) {
-		cfg80211_put_bss(wdev->wiphy, bss);
+		cfg80211_put_bss(wdev->wiphy, cr->bss);
 		return;
 	}
 
-	nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev,
-				    bssid, req_ie, req_ie_len,
-				    resp_ie, resp_ie_len,
-				    status, GFP_KERNEL);
+	nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
+				    GFP_KERNEL);
 
 #ifdef CONFIG_CFG80211_WEXT
 	if (wextev) {
-		if (req_ie && status == WLAN_STATUS_SUCCESS) {
+		if (cr->req_ie && cr->status == WLAN_STATUS_SUCCESS) {
 			memset(&wrqu, 0, sizeof(wrqu));
-			wrqu.data.length = req_ie_len;
-			wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, req_ie);
+			wrqu.data.length = cr->req_ie_len;
+			wireless_send_event(dev, IWEVASSOCREQIE, &wrqu,
+					    cr->req_ie);
 		}
 
-		if (resp_ie && status == WLAN_STATUS_SUCCESS) {
+		if (cr->resp_ie && cr->status == WLAN_STATUS_SUCCESS) {
 			memset(&wrqu, 0, sizeof(wrqu));
-			wrqu.data.length = resp_ie_len;
-			wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+			wrqu.data.length = cr->resp_ie_len;
+			wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu,
+					    cr->resp_ie);
 		}
 
 		memset(&wrqu, 0, sizeof(wrqu));
 		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-		if (bssid && status == WLAN_STATUS_SUCCESS) {
-			memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
-			memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
+		if (cr->bssid && cr->status == WLAN_STATUS_SUCCESS) {
+			memcpy(wrqu.ap_addr.sa_data, cr->bssid, ETH_ALEN);
+			memcpy(wdev->wext.prev_bssid, cr->bssid, ETH_ALEN);
 			wdev->wext.prev_bssid_valid = true;
 		}
 		wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 	}
 #endif
 
-	if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+	if (!cr->bss && (cr->status == WLAN_STATUS_SUCCESS)) {
 		WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect);
-		bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-				       wdev->ssid, wdev->ssid_len,
-				       wdev->conn_bss_type,
-				       IEEE80211_PRIVACY_ANY);
-		if (bss)
-			cfg80211_hold_bss(bss_from_pub(bss));
+		cr->bss = cfg80211_get_bss(wdev->wiphy, NULL, cr->bssid,
+					   wdev->ssid, wdev->ssid_len,
+					   wdev->conn_bss_type,
+					   IEEE80211_PRIVACY_ANY);
+		if (cr->bss)
+			cfg80211_hold_bss(bss_from_pub(cr->bss));
 	}
 
 	if (wdev->current_bss) {
@@ -747,28 +763,28 @@
 		wdev->current_bss = NULL;
 	}
 
-	if (status != WLAN_STATUS_SUCCESS) {
+	if (cr->status != WLAN_STATUS_SUCCESS) {
 		kzfree(wdev->connect_keys);
 		wdev->connect_keys = NULL;
 		wdev->ssid_len = 0;
-		if (bss) {
-			cfg80211_unhold_bss(bss_from_pub(bss));
-			cfg80211_put_bss(wdev->wiphy, bss);
+		if (cr->bss) {
+			cfg80211_unhold_bss(bss_from_pub(cr->bss));
+			cfg80211_put_bss(wdev->wiphy, cr->bss);
 		}
 		cfg80211_sme_free(wdev);
 		return;
 	}
 
-	if (WARN_ON(!bss))
+	if (WARN_ON(!cr->bss))
 		return;
 
-	wdev->current_bss = bss_from_pub(bss);
+	wdev->current_bss = bss_from_pub(cr->bss);
 
 	if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP))
 		cfg80211_upload_connect_keys(wdev);
 
 	rcu_read_lock();
-	country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+	country_ie = ieee80211_bss_get_ie(cr->bss, WLAN_EID_COUNTRY);
 	if (!country_ie) {
 		rcu_read_unlock();
 		return;
@@ -785,62 +801,95 @@
 	 * - country_ie + 2, the start of the country ie data, and
 	 * - and country_ie[1] which is the IE length
 	 */
-	regulatory_hint_country_ie(wdev->wiphy, bss->channel->band,
+	regulatory_hint_country_ie(wdev->wiphy, cr->bss->channel->band,
 				   country_ie + 2, country_ie[1]);
 	kfree(country_ie);
 }
 
 /* Consumes bss object one way or another */
-void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
-			  struct cfg80211_bss *bss, const u8 *req_ie,
-			  size_t req_ie_len, const u8 *resp_ie,
-			  size_t resp_ie_len, int status, gfp_t gfp)
+void cfg80211_connect_done(struct net_device *dev,
+			   struct cfg80211_connect_resp_params *params,
+			   gfp_t gfp)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 	struct cfg80211_event *ev;
 	unsigned long flags;
+	u8 *next;
 
-	if (bss) {
+	if (params->bss) {
 		/* Make sure the bss entry provided by the driver is valid. */
-		struct cfg80211_internal_bss *ibss = bss_from_pub(bss);
+		struct cfg80211_internal_bss *ibss = bss_from_pub(params->bss);
 
 		if (WARN_ON(list_empty(&ibss->list))) {
-			cfg80211_put_bss(wdev->wiphy, bss);
+			cfg80211_put_bss(wdev->wiphy, params->bss);
 			return;
 		}
 	}
 
-	ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
+	ev = kzalloc(sizeof(*ev) + (params->bssid ? ETH_ALEN : 0) +
+		     params->req_ie_len + params->resp_ie_len +
+		     params->fils_kek_len + params->pmk_len +
+		     (params->pmkid ? WLAN_PMKID_LEN : 0), gfp);
 	if (!ev) {
-		cfg80211_put_bss(wdev->wiphy, bss);
+		cfg80211_put_bss(wdev->wiphy, params->bss);
 		return;
 	}
 
 	ev->type = EVENT_CONNECT_RESULT;
-	if (bssid)
-		memcpy(ev->cr.bssid, bssid, ETH_ALEN);
-	if (req_ie_len) {
-		ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
-		ev->cr.req_ie_len = req_ie_len;
-		memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
+	next = ((u8 *)ev) + sizeof(*ev);
+	if (params->bssid) {
+		ev->cr.bssid = next;
+		memcpy((void *)ev->cr.bssid, params->bssid, ETH_ALEN);
+		next += ETH_ALEN;
 	}
-	if (resp_ie_len) {
-		ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
-		ev->cr.resp_ie_len = resp_ie_len;
-		memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
+	if (params->req_ie_len) {
+		ev->cr.req_ie = next;
+		ev->cr.req_ie_len = params->req_ie_len;
+		memcpy((void *)ev->cr.req_ie, params->req_ie,
+		       params->req_ie_len);
+		next += params->req_ie_len;
 	}
-	if (bss)
-		cfg80211_hold_bss(bss_from_pub(bss));
-	ev->cr.bss = bss;
-	ev->cr.status = status;
+	if (params->resp_ie_len) {
+		ev->cr.resp_ie = next;
+		ev->cr.resp_ie_len = params->resp_ie_len;
+		memcpy((void *)ev->cr.resp_ie, params->resp_ie,
+		       params->resp_ie_len);
+		next += params->resp_ie_len;
+	}
+	if (params->fils_kek_len) {
+		ev->cr.fils_kek = next;
+		ev->cr.fils_kek_len = params->fils_kek_len;
+		memcpy((void *)ev->cr.fils_kek, params->fils_kek,
+		       params->fils_kek_len);
+		next += params->fils_kek_len;
+	}
+	if (params->pmk_len) {
+		ev->cr.pmk = next;
+		ev->cr.pmk_len = params->pmk_len;
+		memcpy((void *)ev->cr.pmk, params->pmk, params->pmk_len);
+		next += params->pmk_len;
+	}
+	if (params->pmkid) {
+		ev->cr.pmkid = next;
+		memcpy((void *)ev->cr.pmkid, params->pmkid, WLAN_PMKID_LEN);
+		next += WLAN_PMKID_LEN;
+	}
+	ev->cr.update_erp_next_seq_num = params->update_erp_next_seq_num;
+	if (params->update_erp_next_seq_num)
+		ev->cr.fils_erp_next_seq_num = params->fils_erp_next_seq_num;
+	if (params->bss)
+		cfg80211_hold_bss(bss_from_pub(params->bss));
+	ev->cr.bss = params->bss;
+	ev->cr.status = params->status;
+	ev->cr.timeout_reason = params->timeout_reason;
 
 	spin_lock_irqsave(&wdev->event_lock, flags);
 	list_add_tail(&ev->list, &wdev->event_list);
 	spin_unlock_irqrestore(&wdev->event_lock, flags);
 	queue_work(cfg80211_wq, &rdev->event_work);
 }
-EXPORT_SYMBOL(cfg80211_connect_bss);
+EXPORT_SYMBOL(cfg80211_connect_done);
 
 /* Consumes bss object one way or another */
 void __cfg80211_roamed(struct wireless_dev *wdev,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a3d0a91b..ea1b47e 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1281,6 +1281,24 @@
 		  __entry->wpa_versions, __entry->flags, MAC_PR_ARG(prev_bssid))
 );
 
+TRACE_EVENT(rdev_update_connect_params,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		 struct cfg80211_connect_params *sme, u32 changed),
+	TP_ARGS(wiphy, netdev, sme, changed),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__field(u32, changed)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		__entry->changed = changed;
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", parameters changed: %u",
+		  WIPHY_PR_ARG, NETDEV_PR_ARG,  __entry->changed)
+);
+
 TRACE_EVENT(rdev_set_cqm_rssi_config,
 	TP_PROTO(struct wiphy *wiphy,
 		 struct net_device *netdev, s32 rssi_thold,
@@ -3030,6 +3048,25 @@
 	TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
 	TP_ARGS(wiphy, wdev)
 );
+
+TRACE_EVENT(rdev_set_multicast_to_unicast,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		 const bool enabled),
+	TP_ARGS(wiphy, netdev, enabled),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__field(bool, enabled)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		__entry->enabled = enabled;
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s",
+		  WIPHY_PR_ARG, NETDEV_PR_ARG,
+		  BOOL_TO_STR(__entry->enabled))
+);
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 877e9d3..8ac413f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -15,6 +15,7 @@
 #include <linux/mpls.h>
 #include <net/ndisc.h>
 #include <linux/if_arp.h>
+#include <linux/gcd.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -935,7 +936,6 @@
 {
 	struct cfg80211_event *ev;
 	unsigned long flags;
-	const u8 *bssid = NULL;
 
 	spin_lock_irqsave(&wdev->event_lock, flags);
 	while (!list_empty(&wdev->event_list)) {
@@ -947,15 +947,10 @@
 		wdev_lock(wdev);
 		switch (ev->type) {
 		case EVENT_CONNECT_RESULT:
-			if (!is_zero_ether_addr(ev->cr.bssid))
-				bssid = ev->cr.bssid;
 			__cfg80211_connect_result(
-				wdev->netdev, bssid,
-				ev->cr.req_ie, ev->cr.req_ie_len,
-				ev->cr.resp_ie, ev->cr.resp_ie_len,
-				ev->cr.status,
-				ev->cr.status == WLAN_STATUS_SUCCESS,
-				ev->cr.bss);
+				wdev->netdev,
+				&ev->cr,
+				ev->cr.status == WLAN_STATUS_SUCCESS);
 			break;
 		case EVENT_ROAMED:
 			__cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie,
@@ -1559,47 +1554,53 @@
 }
 EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
 
+static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
+				       u32 *beacon_int_gcd,
+				       bool *beacon_int_different)
+{
+	struct wireless_dev *wdev;
+
+	*beacon_int_gcd = 0;
+	*beacon_int_different = false;
+
+	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
+		if (!wdev->beacon_interval)
+			continue;
+
+		if (!*beacon_int_gcd) {
+			*beacon_int_gcd = wdev->beacon_interval;
+			continue;
+		}
+
+		if (wdev->beacon_interval == *beacon_int_gcd)
+			continue;
+
+		*beacon_int_different = true;
+		*beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
+	}
+
+	if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
+		if (*beacon_int_gcd)
+			*beacon_int_different = true;
+		*beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
+	}
+}
+
 int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 				 enum nl80211_iftype iftype, u32 beacon_int)
 {
-	struct wireless_dev *wdev;
-	struct iface_combination_params params = {
-		.beacon_int_gcd = beacon_int,	/* GCD(n) = n */
-	};
+	/*
+	 * This is just a basic pre-condition check; if interface combinations
+	 * are possible the driver must already be checking those with a call
+	 * to cfg80211_check_combinations(), in which case we'll validate more
+	 * through the cfg80211_calculate_bi_data() call and code in
+	 * cfg80211_iter_combinations().
+	 */
 
 	if (beacon_int < 10 || beacon_int > 10000)
 		return -EINVAL;
 
-	params.iftype_num[iftype] = 1;
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-		if (!wdev->beacon_interval)
-			continue;
-
-		params.iftype_num[wdev->iftype]++;
-	}
-
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-		u32 bi_prev = wdev->beacon_interval;
-
-		if (!wdev->beacon_interval)
-			continue;
-
-		/* slight optimisation - skip identical BIs */
-		if (wdev->beacon_interval == beacon_int)
-			continue;
-
-		params.beacon_int_different = true;
-
-		/* Get the GCD */
-		while (bi_prev != 0) {
-			u32 tmp_bi = bi_prev;
-
-			bi_prev = params.beacon_int_gcd % bi_prev;
-			params.beacon_int_gcd = tmp_bi;
-		}
-	}
-
-	return cfg80211_check_combinations(&rdev->wiphy, &params);
+	return 0;
 }
 
 int cfg80211_iter_combinations(struct wiphy *wiphy,
@@ -1613,6 +1614,21 @@
 	int i, j, iftype;
 	int num_interfaces = 0;
 	u32 used_iftypes = 0;
+	u32 beacon_int_gcd;
+	bool beacon_int_different;
+
+	/*
+	 * This is a bit strange, since the iteration used to rely only on
+	 * the data given by the driver, but here it now relies on context,
+	 * in form of the currently operating interfaces.
+	 * This is OK for all current users, and saves us from having to
+	 * push the GCD calculations into all the drivers.
+	 * In the future, this should probably rely more on data that's in
+	 * cfg80211 already - the only thing not would appear to be any new
+	 * interfaces (while being brought up) and channel/radar data.
+	 */
+	cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
+				   &beacon_int_gcd, &beacon_int_different);
 
 	if (params->radar_detect) {
 		rcu_read_lock();
@@ -1675,12 +1691,11 @@
 		if ((all_iftypes & used_iftypes) != used_iftypes)
 			goto cont;
 
-		if (params->beacon_int_gcd) {
+		if (beacon_int_gcd) {
 			if (c->beacon_int_min_gcd &&
-			    params->beacon_int_gcd < c->beacon_int_min_gcd)
-				return -EINVAL;
-			if (!c->beacon_int_min_gcd &&
-			    params->beacon_int_different)
+			    beacon_int_gcd < c->beacon_int_min_gcd)
+				goto cont;
+			if (!c->beacon_int_min_gcd && beacon_int_different)
 				goto cont;
 		}
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index a0d45ef..71ea359 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3654,7 +3654,7 @@
 				$fixedline =~ s/\s*=\s*$/ = {/;
 				fix_insert_line($fixlinenr, $fixedline);
 				$fixedline = $line;
-				$fixedline =~ s/^(.\s*){\s*/$1/;
+				$fixedline =~ s/^(.\s*)\{\s*/$1/;
 				fix_insert_line($fixlinenr, $fixedline);
 			}
 		}
@@ -3995,7 +3995,7 @@
 				my $fixedline = rtrim($prevrawline) . " {";
 				fix_insert_line($fixlinenr, $fixedline);
 				$fixedline = $rawline;
-				$fixedline =~ s/^(.\s*){\s*/$1\t/;
+				$fixedline =~ s/^(.\s*)\{\s*/$1\t/;
 				if ($fixedline !~ /^\+\s*$/) {
 					fix_insert_line($fixlinenr, $fixedline);
 				}
@@ -4484,7 +4484,7 @@
 			if (ERROR("SPACING",
 				  "space required before the open brace '{'\n" . $herecurr) &&
 			    $fix) {
-				$fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/;
+				$fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/;
 			}
 		}
 
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 22286a1..14fb793 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -71,6 +71,20 @@
 		return -FDT_ERR_BADMAGIC;
 	}
 
+	if (fdt_off_dt_struct(fdt) > (UINT_MAX - fdt_size_dt_struct(fdt)))
+		return FDT_ERR_BADOFFSET;
+
+	if (fdt_off_dt_strings(fdt) > (UINT_MAX -  fdt_size_dt_strings(fdt)))
+		return FDT_ERR_BADOFFSET;
+
+	if ((fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))
+	    > fdt_totalsize(fdt))
+		return FDT_ERR_BADOFFSET;
+
+	if ((fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))
+	    > fdt_totalsize(fdt))
+		return FDT_ERR_BADOFFSET;
+
 	return 0;
 }
 
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8be02b1..468e169 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -396,7 +396,7 @@
 static void _fdt_packblocks(const char *old, char *new,
 			    int mem_rsv_size, int struct_size)
 {
-	int mem_rsv_off, struct_off, strings_off;
+	uint32_t mem_rsv_off, struct_off, strings_off;
 
 	mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
 	struct_off = mem_rsv_off + mem_rsv_size;
diff --git a/security/Kconfig b/security/Kconfig
index 59aea7d..5693989 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -40,6 +40,11 @@
 
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_WRITABLE_HOOKS
+	depends on SECURITY
+	bool
+	default n
+
 config SECURITYFS
 	bool "Enable the securityfs filesystem"
 	help
@@ -167,6 +172,13 @@
 	  been removed. This config is intended to be used only while
 	  trying to find such users.
 
+config FORTIFY_SOURCE
+	bool "Harden common str/mem functions against buffer overflows"
+	depends on ARCH_HAS_FORTIFY_SOURCE
+	help
+	  Detect overflows of buffers in common string and memory functions
+	  where the compiler can determine and validate the buffer sizes.
+
 source security/selinux/Kconfig
 source security/smack/Kconfig
 source security/tomoyo/Kconfig
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 41b8cb1..57bc405 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -584,7 +584,7 @@
 	return error;
 }
 
-static struct security_hook_list apparmor_hooks[] = {
+static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
 	LSM_HOOK_INIT(capget, apparmor_capget),
diff --git a/security/commoncap.c b/security/commoncap.c
index a8e4aac..3e44d01 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -1081,7 +1081,7 @@
 
 #ifdef CONFIG_SECURITY
 
-struct security_hook_list capability_hooks[] = {
+struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(capable, cap_capable),
 	LSM_HOOK_INIT(settime, cap_settime),
 	LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 89a46f1..afd4ab9 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -174,7 +174,7 @@
 	return 0;
 }
 
-static struct security_hook_list loadpin_hooks[] = {
+static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
 	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
 };
diff --git a/security/security.c b/security/security.c
index 1ba5274..6a7b359 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1590,7 +1590,7 @@
 }
 #endif /* CONFIG_AUDIT */
 
-struct security_hook_heads security_hook_heads = {
+struct security_hook_heads security_hook_heads __lsm_ro_after_init = {
 	.binder_set_context_mgr =
 		LIST_HEAD_INIT(security_hook_heads.binder_set_context_mgr),
 	.binder_transaction =
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index ea7e3ef..8af7a69 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -40,6 +40,7 @@
 config SECURITY_SELINUX_DISABLE
 	bool "NSA SELinux runtime disable"
 	depends on SECURITY_SELINUX
+	select SECURITY_WRITABLE_HOOKS
 	default n
 	help
 	  This option enables writing to a selinuxfs node 'disable', which
@@ -50,6 +51,11 @@
 	  portability across platforms where boot parameters are difficult
 	  to employ.
 
+	  NOTE: selecting this option will disable the '__ro_after_init'
+	  kernel hardening feature for security hooks.   Please consider
+	  using the selinux=0 boot parameter instead of enabling this
+	  option.
+
 	  If you are unsure how to answer this question, answer N.
 
 config SECURITY_SELINUX_DEVELOP
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 20b2e7d..e26ecb0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6079,7 +6079,7 @@
 
 #endif
 
-static struct security_hook_list selinux_hooks[] = {
+static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
 	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
 	LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1cb0602..b75c31a 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4611,7 +4611,7 @@
 	return 0;
 }
 
-static struct security_hook_list smack_hooks[] = {
+static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
 	LSM_HOOK_INIT(syslog, smack_syslog),
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 75c9987..f1dce33 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -496,7 +496,7 @@
  * tomoyo_security_ops is a "struct security_operations" which is used for
  * registering TOMOYO.
  */
-static struct security_hook_list tomoyo_hooks[] = {
+static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank),
 	LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
 	LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer),
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 0309f21..70aa64c 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -414,7 +414,7 @@
 	return rc;
 }
 
-static struct security_hook_list yama_hooks[] = {
+static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
 	LSM_HOOK_INIT(task_prctl, yama_task_prctl),
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index a472bf2..01c67be 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1159,7 +1159,7 @@
 
 config SND_SOC_MSM_HDMI_CODEC_RX
 	bool "HDMI Audio Playback"
-	depends on FB_MSM_MDSS_HDMI_PANEL && (SND_SOC_APQ8084 || SND_SOC_MSM8994 || SND_SOC_MSM8996 || SND_SOC_MSM8998 || SND_SOC_SDM660_COMMON)
+	depends on FB_MSM_MDSS_HDMI_PANEL && (SND_SOC_APQ8084 || SND_SOC_MSM8994 || SND_SOC_MSM8996 || SND_SOC_MSM8998 || SND_SOC_660)
 	help
 	HDMI audio drivers should be built only if the platform
         supports hdmi panel.
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index d8b5ae6..daf05d8 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -162,14 +162,7 @@
 snd-soc-wcd934x-objs := wcd934x.o
 snd-soc-wcd9xxx-objs := wcd9xxx-common-v2.o wcd9xxx-resmgr-v2.o \
 			wcdcal-hwdep.o wcd-dsp-mgr.o wcd-dsp-utils.o \
-			wcd9xxx-soc-init.o
-ifeq ($(CONFIG_COMMON_CLK_MSM), y)
-	snd-soc-wcd9xxx-objs += audio-ext-clk.o
-endif
-
-ifeq ($(CONFIG_COMMON_CLK_QCOM), y)
-	snd-soc-wcd9xxx-objs += audio-ext-clk-up.o
-endif
+			wcd9xxx-soc-init.o audio-ext-clk-up.o
 snd-soc-wcd-cpe-objs := wcd_cpe_services.o wcd_cpe_core.o
 snd-soc-wsa881x-objs := wsa881x.o wsa881x-tables.o wsa881x-regmap.o wsa881x-temp-sensor.o
 snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o
diff --git a/sound/soc/codecs/audio-ext-clk.c b/sound/soc/codecs/audio-ext-clk.c
deleted file mode 100644
index 72f16f5..0000000
--- a/sound/soc/codecs/audio-ext-clk.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/clk/msm-clk-provider.h>
-#include <linux/clk/msm-clk.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <dt-bindings/clock/audio-ext-clk.h>
-#include <sound/q6afe-v2.h>
-#include "audio-ext-clk-up.h"
-
-struct pinctrl_info {
-	struct pinctrl *pinctrl;
-	struct pinctrl_state *sleep;
-	struct pinctrl_state *active;
-};
-
-struct audio_ext_ap_clk {
-	bool enabled;
-	int gpio;
-	struct clk c;
-};
-
-struct audio_ext_pmi_clk {
-	int gpio;
-	struct clk c;
-};
-
-struct audio_ext_ap_clk2 {
-	bool enabled;
-	struct pinctrl_info pnctrl_info;
-	struct clk c;
-};
-
-static struct afe_clk_set clk2_config = {
-	Q6AFE_LPASS_CLK_CONFIG_API_VERSION,
-	Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR,
-	Q6AFE_LPASS_IBIT_CLK_11_P2896_MHZ,
-	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
-	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
-	0,
-};
-
-static inline struct audio_ext_ap_clk *to_audio_ap_clk(struct clk *clk)
-{
-	return container_of(clk, struct audio_ext_ap_clk, c);
-}
-
-static int audio_ext_clk_prepare(struct clk *clk)
-{
-	struct audio_ext_ap_clk *audio_clk = to_audio_ap_clk(clk);
-
-	pr_debug("%s: gpio: %d\n", __func__, audio_clk->gpio);
-	if (gpio_is_valid(audio_clk->gpio))
-		return gpio_direction_output(audio_clk->gpio, 1);
-	return 0;
-}
-
-static void audio_ext_clk_unprepare(struct clk *clk)
-{
-	struct audio_ext_ap_clk *audio_clk = to_audio_ap_clk(clk);
-
-	pr_debug("%s: gpio: %d\n", __func__, audio_clk->gpio);
-	if (gpio_is_valid(audio_clk->gpio))
-		gpio_direction_output(audio_clk->gpio, 0);
-}
-
-static inline struct audio_ext_ap_clk2 *to_audio_ap_clk2(struct clk *clk)
-{
-	return container_of(clk, struct audio_ext_ap_clk2, c);
-}
-
-static int audio_ext_clk2_prepare(struct clk *clk)
-{
-	struct audio_ext_ap_clk2 *audio_clk2 = to_audio_ap_clk2(clk);
-	struct pinctrl_info *pnctrl_info = &audio_clk2->pnctrl_info;
-	int ret;
-
-
-	if (!pnctrl_info->pinctrl || !pnctrl_info->active)
-		return 0;
-
-	ret = pinctrl_select_state(pnctrl_info->pinctrl,
-				   pnctrl_info->active);
-	if (ret) {
-		pr_err("%s: active state select failed with %d\n",
-			__func__, ret);
-		return -EIO;
-	}
-
-	clk2_config.enable = 1;
-	ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk2_config);
-	if (ret < 0) {
-		pr_err("%s: failed to set clock, ret = %d\n", __func__, ret);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void audio_ext_clk2_unprepare(struct clk *clk)
-{
-	struct audio_ext_ap_clk2 *audio_clk2 = to_audio_ap_clk2(clk);
-	struct pinctrl_info *pnctrl_info = &audio_clk2->pnctrl_info;
-	int ret;
-
-	if (!pnctrl_info->pinctrl || !pnctrl_info->sleep)
-		return;
-
-	ret = pinctrl_select_state(pnctrl_info->pinctrl,
-				   pnctrl_info->sleep);
-	if (ret)
-		pr_err("%s: sleep state select failed with %d\n",
-			__func__, ret);
-
-	clk2_config.enable = 0;
-	ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk2_config);
-	if (ret < 0)
-		pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret);
-}
-
-static const struct clk_ops audio_ext_ap_clk_ops = {
-	.prepare = audio_ext_clk_prepare,
-	.unprepare = audio_ext_clk_unprepare,
-};
-
-static const struct clk_ops audio_ext_ap_clk2_ops = {
-	.prepare = audio_ext_clk2_prepare,
-	.unprepare = audio_ext_clk2_unprepare,
-};
-
-static struct audio_ext_pmi_clk audio_pmi_clk = {
-	.gpio = -EINVAL,
-	.c = {
-		.dbg_name = "audio_ext_pmi_clk",
-		.ops = &clk_ops_dummy,
-		CLK_INIT(audio_pmi_clk.c),
-	},
-};
-
-static struct audio_ext_pmi_clk audio_pmi_lnbb_clk = {
-	.gpio = -EINVAL,
-	.c = {
-		.dbg_name = "audio_ext_pmi_lnbb_clk",
-		.ops = &clk_ops_dummy,
-		CLK_INIT(audio_pmi_lnbb_clk.c),
-	},
-};
-
-static struct audio_ext_ap_clk audio_ap_clk = {
-	.gpio = -EINVAL,
-	.c = {
-		.dbg_name = "audio_ext_ap_clk",
-		.ops = &audio_ext_ap_clk_ops,
-		CLK_INIT(audio_ap_clk.c),
-	},
-};
-
-static struct audio_ext_ap_clk2 audio_ap_clk2 = {
-	.c = {
-		.dbg_name = "audio_ext_ap_clk2",
-		.ops = &audio_ext_ap_clk2_ops,
-		CLK_INIT(audio_ap_clk2.c),
-	},
-};
-
-static struct clk_lookup audio_ref_clock[] = {
-	CLK_LIST(audio_ap_clk),
-	CLK_LIST(audio_pmi_clk),
-	CLK_LIST(audio_pmi_lnbb_clk),
-	CLK_LIST(audio_ap_clk2),
-};
-
-static int audio_get_pinctrl(struct platform_device *pdev)
-{
-	struct pinctrl_info *pnctrl_info;
-	struct pinctrl *pinctrl;
-	int ret;
-
-	pnctrl_info = &audio_ap_clk2.pnctrl_info;
-
-	if (pnctrl_info->pinctrl) {
-		dev_dbg(&pdev->dev, "%s: already requested before\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	pinctrl = devm_pinctrl_get(&pdev->dev);
-	if (IS_ERR_OR_NULL(pinctrl)) {
-		dev_dbg(&pdev->dev, "%s: Unable to get pinctrl handle\n",
-			__func__);
-		return -EINVAL;
-	}
-	pnctrl_info->pinctrl = pinctrl;
-	/* get all state handles from Device Tree */
-	pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
-	if (IS_ERR(pnctrl_info->sleep)) {
-		dev_err(&pdev->dev, "%s: could not get sleep pinstate\n",
-			__func__);
-		goto err;
-	}
-	pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
-	if (IS_ERR(pnctrl_info->active)) {
-		dev_err(&pdev->dev, "%s: could not get active pinstate\n",
-			__func__);
-		goto err;
-	}
-	/* Reset the TLMM pins to a default state */
-	ret = pinctrl_select_state(pnctrl_info->pinctrl,
-				   pnctrl_info->sleep);
-	if (ret) {
-		dev_err(&pdev->dev, "%s: Disable TLMM pins failed with %d\n",
-			__func__, ret);
-		goto err;
-	}
-	return 0;
-
-err:
-	devm_pinctrl_put(pnctrl_info->pinctrl);
-	return -EINVAL;
-}
-
-static int audio_ref_clk_probe(struct platform_device *pdev)
-{
-	int clk_gpio;
-	int ret;
-	struct clk *audio_clk;
-
-	clk_gpio = of_get_named_gpio(pdev->dev.of_node,
-				     "qcom,audio-ref-clk-gpio", 0);
-	if (clk_gpio > 0) {
-		ret = gpio_request(clk_gpio, "EXT_CLK");
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Request ext clk gpio failed %d, err:%d\n",
-				clk_gpio, ret);
-			goto err;
-		}
-		if (of_property_read_bool(pdev->dev.of_node,
-					"qcom,node_has_rpm_clock")) {
-			audio_clk = clk_get(&pdev->dev, NULL);
-			if (IS_ERR(audio_clk)) {
-				dev_err(&pdev->dev, "Failed to get RPM div clk\n");
-				ret = PTR_ERR(audio_clk);
-				goto err_gpio;
-			}
-			audio_pmi_clk.c.parent = audio_clk;
-			audio_pmi_clk.gpio = clk_gpio;
-		} else
-			audio_ap_clk.gpio = clk_gpio;
-
-	} else {
-		if (of_property_read_bool(pdev->dev.of_node,
-					"qcom,node_has_rpm_clock")) {
-			audio_clk = clk_get(&pdev->dev, NULL);
-			if (IS_ERR(audio_clk)) {
-				dev_err(&pdev->dev, "Failed to get lnbbclk2\n");
-				ret = PTR_ERR(audio_clk);
-				goto err;
-			}
-			audio_pmi_lnbb_clk.c.parent = audio_clk;
-			audio_pmi_lnbb_clk.gpio = -EINVAL;
-		}
-	}
-
-	ret = audio_get_pinctrl(pdev);
-	if (ret)
-		dev_dbg(&pdev->dev, "%s: Parsing pinctrl failed\n",
-			__func__);
-
-	ret = of_msm_clock_register(pdev->dev.of_node, audio_ref_clock,
-			      ARRAY_SIZE(audio_ref_clock));
-	if (ret) {
-		dev_err(&pdev->dev, "%s: audio ref clock register failed\n",
-			__func__);
-		goto err_gpio;
-	}
-
-	return 0;
-
-err_gpio:
-	gpio_free(clk_gpio);
-
-err:
-	return ret;
-}
-
-static int audio_ref_clk_remove(struct platform_device *pdev)
-{
-	struct pinctrl_info *pnctrl_info = &audio_ap_clk2.pnctrl_info;
-
-	if (audio_pmi_clk.gpio > 0)
-		gpio_free(audio_pmi_clk.gpio);
-	else if (audio_ap_clk.gpio > 0)
-		gpio_free(audio_ap_clk.gpio);
-
-	if (pnctrl_info->pinctrl) {
-		devm_pinctrl_put(pnctrl_info->pinctrl);
-		pnctrl_info->pinctrl = NULL;
-	}
-
-	return 0;
-}
-
-static const struct of_device_id audio_ref_clk_match[] = {
-	{.compatible = "qcom,audio-ref-clk"},
-	{}
-};
-MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
-
-static struct platform_driver audio_ref_clk_driver = {
-	.driver = {
-		.name = "audio-ref-clk",
-		.owner = THIS_MODULE,
-		.of_match_table = audio_ref_clk_match,
-	},
-	.probe = audio_ref_clk_probe,
-	.remove = audio_ref_clk_remove,
-};
-
-int audio_ref_clk_platform_init(void)
-{
-	return platform_driver_register(&audio_ref_clk_driver);
-}
-
-void audio_ref_clk_platform_exit(void)
-{
-	platform_driver_unregister(&audio_ref_clk_driver);
-}
-
-MODULE_DESCRIPTION("Audio Ref Clock module platform driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c b/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c
index 34227a0..a253aea 100644
--- a/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c
+++ b/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c
@@ -1376,15 +1376,19 @@
 	struct snd_info_entry *version_entry;
 	struct msm_sdw_priv *msm_sdw;
 	struct snd_soc_card *card;
+	char name[80];
 
 	if (!codec_root || !codec)
 		return -EINVAL;
 
 	msm_sdw = snd_soc_codec_get_drvdata(codec);
 	card = codec->component.card;
+
+	snprintf(name, sizeof(name), "%x.%s", (u32)msm_sdw->sdw_base_addr,
+			"msm-sdw-codec");
 	msm_sdw->entry = snd_info_create_subdir(codec_root->module,
-						  "152c1000.msm-sdw-codec",
-						  codec_root);
+						(const char *)name,
+						codec_root);
 	if (!msm_sdw->entry) {
 		dev_err(codec->dev, "%s: failed to create msm_sdw entry\n",
 			__func__);
diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c
index a6d46ae..6cc9f8c 100644
--- a/sound/soc/codecs/wcd-dsp-mgr.c
+++ b/sound/soc/codecs/wcd-dsp-mgr.c
@@ -417,22 +417,23 @@
 	/* Go through the list of segments and download one by one */
 	list_for_each_entry(seg, wdsp->seg_list, list) {
 		ret = wdsp_load_each_segment(wdsp, seg);
-		if (ret < 0) {
-			wdsp_broadcast_event_downseq(wdsp,
-						     WDSP_EVENT_DLOAD_FAILED,
-						     NULL);
+		if (ret)
 			goto dload_error;
-		}
 	}
 
+	/* Flush the list before setting status and notifying components */
+	wdsp_flush_segment_list(wdsp->seg_list);
+
 	WDSP_SET_STATUS(wdsp, status);
 
 	/* Notify all components that image is downloaded */
 	wdsp_broadcast_event_downseq(wdsp, post, NULL);
+done:
+	return ret;
 
 dload_error:
 	wdsp_flush_segment_list(wdsp->seg_list);
-done:
+	wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_DLOAD_FAILED, NULL);
 	return ret;
 }
 
@@ -486,10 +487,14 @@
 	/* Make sure wdsp is in good state */
 	if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
 		WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
-		ret = -EINVAL;
-		goto done;
+		return -EINVAL;
 	}
 
+	/*
+	 * Acquire SSR mutex lock to make sure enablement of DSP
+	 * does not race with SSR handling.
+	 */
+	WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
 	/* Download the read-write sections of image */
 	ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_WRITE);
 	if (ret < 0) {
@@ -510,6 +515,7 @@
 	wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_BOOTUP, NULL);
 	WDSP_SET_STATUS(wdsp, WDSP_STATUS_BOOTED);
 done:
+	WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
 	return ret;
 }
 
diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
index 8da0425..b62f26c 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
+++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
@@ -763,10 +763,6 @@
 	case WDSP_EVENT_DLOAD_FAILED:
 	case WDSP_EVENT_POST_SHUTDOWN:
 
-		if (event == WDSP_EVENT_POST_DLOAD_CODE)
-			/* Mark DSP online since code download is complete */
-			wcd_cntl_change_online_state(cntl, 1);
-
 		/* Disable CPAR */
 		wcd_cntl_cpar_ctrl(cntl, false);
 		/* Disable all the clocks */
@@ -775,6 +771,10 @@
 			dev_err(codec->dev,
 				"%s: Failed to disable clocks, err = %d\n",
 				__func__, ret);
+
+		if (event == WDSP_EVENT_POST_DLOAD_CODE)
+			/* Mark DSP online since code download is complete */
+			wcd_cntl_change_online_state(cntl, 1);
 		break;
 
 	case WDSP_EVENT_PRE_DLOAD_DATA:
diff --git a/sound/soc/codecs/wsa881x.h b/sound/soc/codecs/wsa881x.h
index be234ac..fbc60d8 100644
--- a/sound/soc/codecs/wsa881x.h
+++ b/sound/soc/codecs/wsa881x.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 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,9 +20,10 @@
 
 #define WSA881X_MAX_SWR_PORTS   4
 
+#if IS_ENABLED(CONFIG_SND_SOC_WSA881X)
 extern int wsa881x_set_channel_map(struct snd_soc_codec *codec, u8 *port,
-				u8 num_port, unsigned int *ch_mask,
-				unsigned int *ch_rate);
+				   u8 num_port, unsigned int *ch_mask,
+				   unsigned int *ch_rate);
 
 extern const u8 wsa881x_reg_readable[WSA881X_CACHE_SIZE];
 extern struct regmap_config wsa881x_regmap_config;
@@ -31,4 +32,25 @@
 					struct snd_soc_codec *codec);
 void wsa881x_regmap_defaults(struct regmap *regmap, u8 version);
 
+#else
+extern int wsa881x_set_channel_map(struct snd_soc_codec *codec, u8 *port,
+				   u8 num_port, unsigned int *ch_mask,
+				   unsigned int *ch_rate)
+{
+	return 0;
+}
+
+extern int wsa881x_codec_info_create_codec_entry(
+					struct snd_info_entry *codec_root,
+					struct snd_soc_codec *codec)
+{
+	return 0;
+}
+
+void wsa881x_regmap_defaults(struct regmap *regmap, u8 version)
+{
+}
+
+#endif
+
 #endif /* _WSA881X_H */
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index abadd08..5fbfe3d 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -160,34 +160,6 @@
 	the machine driver and the corresponding
 	DAI-links
 
-config SND_SOC_MSM8996
-	tristate "SoC Machine driver for MSM8996 boards"
-	depends on ARCH_MSM8996
-	select SND_SOC_COMPRESS
-	select SND_SOC_QDSP6V2
-	select SND_SOC_MSM_STUB
-	select SND_SOC_MSM_HOSTLESS_PCM
-	select SND_DYNAMIC_MINORS
-	select MSM_QDSP6_APRV2
-	select MSM_QDSP6V2_CODECS
-	select SND_SOC_WCD9335
-	select SND_SOC_WSA881X
-	select SND_SOC_MSM_HDMI_CODEC_RX
-	select DTS_SRS_TM
-	select QTI_PP
-	select QTI_PP_AUDIOSPHERE
-	select SND_SOC_CPE
-	select MSM_ULTRASOUND
-	select DOLBY_DS2
-	select SND_HWDEP
-        select DTS_EAGLE
-	help
-	 To add support for SoC audio on MSM8996.
-	 This will enable sound soc drivers which
-	 interfaces with DSP, also it will enable
-	 the machine driver and the corresponding
-	 DAI-links
-
 config SND_SOC_MACHINE_MSM8998
 	tristate "SoC Machine driver for MSM8998 boards"
 	select SND_SOC_WSA881X
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index caf8843..93fddb5 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -12,17 +12,13 @@
 snd-soc-cpe-objs := msm-cpe-lsm.o
 obj-$(CONFIG_SND_SOC_CPE) += snd-soc-cpe.o
 
-# for MSM8996 sound card driver
-snd-soc-msm8996-objs := msm8996.o
-obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o
-
 # for MSM8998 sound card driver
 snd-soc-msm8998-objs := msm8998.o
 obj-$(CONFIG_SND_SOC_MACHINE_MSM8998) += snd-soc-msm8998.o
 
 # for SDM660 sound card driver
 snd-soc-sdm660-common-objs := sdm660-common.o
-obj-$(CONFIG_SND_SOC_SDM660_COMMON) += snd-soc-sdm660-common.o
+obj-$(CONFIG_SND_SOC_660) += snd-soc-sdm660-common.o
 
 # for SDM660 sound card driver
 snd-soc-int-codec-objs := sdm660-internal.o
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 30a4d59..89a9cc2 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -2376,8 +2376,20 @@
 			.rate_min =	8000,
 			.rate_max = 384000,
 		},
+		.capture = {
+			.stream_name = "MultiMedia10 Capture",
+			.aif_name = "MM_UL10",
+			.rates = (SNDRV_PCM_RATE_8000_48000 |
+				  SNDRV_PCM_RATE_KNOT),
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE |
+				    SNDRV_PCM_FMTBIT_S24_3LE),
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
 		.name = "MultiMedia10",
 		.probe = fe_dai_probe,
 	},
diff --git a/sound/soc/msm/msm8996.c b/sound/soc/msm/msm8996.c
deleted file mode 100644
index 0890037..0000000
--- a/sound/soc/msm/msm8996.c
+++ /dev/null
@@ -1,4007 +0,0 @@
-/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/switch.h>
-#include <linux/input.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/pcm.h>
-#include <sound/jack.h>
-#include <sound/q6afe-v2.h>
-#include <sound/q6core.h>
-#include <sound/pcm_params.h>
-#include <sound/info.h>
-#include <device_event.h>
-#include "qdsp6v2/msm-pcm-routing-v2.h"
-#include "../codecs/wcd9xxx-common.h"
-#include "../codecs/wcd9330.h"
-#include "../codecs/wcd9335.h"
-#include "../codecs/wsa881x.h"
-
-#define DRV_NAME "msm8996-asoc-snd"
-
-#define SAMPLING_RATE_8KHZ      8000
-#define SAMPLING_RATE_16KHZ     16000
-#define SAMPLING_RATE_32KHZ     32000
-#define SAMPLING_RATE_48KHZ     48000
-#define SAMPLING_RATE_96KHZ     96000
-#define SAMPLING_RATE_192KHZ    192000
-#define SAMPLING_RATE_44P1KHZ   44100
-
-#define MSM8996_SPK_ON     1
-#define MSM8996_HIFI_ON    1
-
-#define WCD9XXX_MBHC_DEF_BUTTONS    8
-#define WCD9XXX_MBHC_DEF_RLOADS     5
-#define CODEC_EXT_CLK_RATE         9600000
-#define ADSP_STATE_READY_TIMEOUT_MS    3000
-#define DEV_NAME_STR_LEN            32
-
-#define WSA8810_NAME_1 "wsa881x.20170211"
-#define WSA8810_NAME_2 "wsa881x.20170212"
-
-static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
-static int slim0_tx_sample_rate = SAMPLING_RATE_48KHZ;
-static int slim1_tx_sample_rate = SAMPLING_RATE_48KHZ;
-static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-static int slim0_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-static int slim1_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-static int msm8996_auxpcm_rate = SAMPLING_RATE_8KHZ;
-static int slim5_rx_sample_rate = SAMPLING_RATE_48KHZ;
-static int slim5_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-static int slim6_rx_sample_rate = SAMPLING_RATE_48KHZ;
-static int slim6_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-
-static struct platform_device *spdev;
-static int ext_us_amp_gpio = -1;
-static int msm8996_spk_control = 1;
-static int msm_slim_0_rx_ch = 1;
-static int msm_slim_0_tx_ch = 1;
-static int msm_slim_1_tx_ch = 1;
-static int msm_slim_5_rx_ch = 1;
-static int msm_slim_6_rx_ch = 1;
-static int msm_hifi_control;
-static int msm_vi_feed_tx_ch = 2;
-
-static int msm_hdmi_rx_ch = 2;
-static int msm_proxy_rx_ch = 2;
-static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
-static int msm_tert_mi2s_tx_ch = 2;
-
-static bool codec_reg_done;
-
-static const char *const hifi_function[] = {"Off", "On"};
-static const char *const pin_states[] = {"Disable", "active"};
-static const char *const spk_function[] = {"Off", "On"};
-static const char *const slim0_rx_ch_text[] = {"One", "Two"};
-static const char *const slim5_rx_ch_text[] = {"One", "Two"};
-static const char *const slim6_rx_ch_text[] = {"One", "Two"};
-static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four",
-						"Five", "Six", "Seven",
-						"Eight"};
-static const char *const vi_feed_ch_text[] = {"One", "Two"};
-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", "S24_3LE"};
-static char const *slim5_rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
-static char const *slim6_rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
-static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
-					"KHZ_192", "KHZ_44P1", "KHZ_8",
-					"KHZ_16", "KHZ_32"};
-static char const *slim5_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
-						  "KHZ_192", "KHZ_44P1"};
-static char const *slim6_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
-						  "KHZ_192", "KHZ_44P1"};
-static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
-	"Five", "Six", "Seven", "Eight"};
-
-static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
-					"KHZ_192"};
-
-static const char *const auxpcm_rate_text[] = {"8000", "16000"};
-static const struct soc_enum msm8996_auxpcm_enum[] = {
-		SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
-};
-
-static struct afe_clk_set mi2s_tx_clk = {
-	AFE_API_VERSION_I2S_CONFIG,
-	Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
-	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
-	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
-	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
-	0,
-};
-
-struct msm8996_wsa881x_dev_info {
-	struct device_node *of_node;
-	u32 index;
-};
-
-static struct snd_soc_aux_dev *msm8996_aux_dev;
-static struct snd_soc_codec_conf *msm8996_codec_conf;
-
-struct msm8996_asoc_mach_data {
-	u32 mclk_freq;
-	int us_euro_gpio;
-	int hph_en1_gpio;
-	int hph_en0_gpio;
-	struct snd_info_entry *codec_root;
-};
-
-struct msm8996_asoc_wcd93xx_codec {
-	void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
-				   enum afe_config_type config_type);
-	void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec);
-};
-
-static struct msm8996_asoc_wcd93xx_codec msm8996_codec_fn;
-
-struct msm8996_liquid_dock_dev {
-	int dock_plug_gpio;
-	int dock_plug_irq;
-	int dock_plug_det;
-	struct work_struct irq_work;
-	struct switch_dev audio_sdev;
-};
-static struct msm8996_liquid_dock_dev *msm8996_liquid_dock_dev;
-
-static void *adsp_state_notifier;
-static void *def_tasha_mbhc_cal(void);
-static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
-					int enable, bool dapm);
-static int msm8996_wsa881x_init(struct snd_soc_component *component);
-
-/*
- * Need to report LINEIN
- * if R/L channel impedance is larger than 5K ohm
- */
-static struct wcd_mbhc_config wcd_mbhc_cfg = {
-	.read_fw_bin = false,
-	.calibration = NULL,
-	.detect_extn_cable = true,
-	.mono_stero_detection = false,
-	.swap_gnd_mic = NULL,
-	.hs_ext_micbias = true,
-	.key_code[0] = KEY_MEDIA,
-	.key_code[1] = KEY_VOICECOMMAND,
-	.key_code[2] = KEY_VOLUMEUP,
-	.key_code[3] = KEY_VOLUMEDOWN,
-	.key_code[4] = 0,
-	.key_code[5] = 0,
-	.key_code[6] = 0,
-	.key_code[7] = 0,
-	.linein_th = 5000,
-	.moisture_en = true,
-	.mbhc_micbias = MIC_BIAS_2,
-	.anc_micbias = MIC_BIAS_2,
-	.enable_anc_mic_detect = false,
-};
-
-static inline int param_is_mask(int p)
-{
-	return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
-			(p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
-}
-
-static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
-					     int n)
-{
-	return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
-}
-
-static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
-{
-	if (bit >= SNDRV_MASK_MAX)
-		return;
-	if (param_is_mask(n)) {
-		struct snd_mask *m = param_to_mask(p, n);
-
-		m->bits[0] = 0;
-		m->bits[1] = 0;
-		m->bits[bit >> 5] |= (1 << (bit & 31));
-	}
-}
-
-static void msm8996_liquid_docking_irq_work(struct work_struct *work)
-{
-	struct msm8996_liquid_dock_dev *dock_dev =
-		container_of(work, struct msm8996_liquid_dock_dev,
-			     irq_work);
-
-	dock_dev->dock_plug_det =
-		gpio_get_value(dock_dev->dock_plug_gpio);
-
-	switch_set_state(&dock_dev->audio_sdev, dock_dev->dock_plug_det);
-	/* notify to audio daemon */
-	sysfs_notify(&dock_dev->audio_sdev.dev->kobj, NULL, "state");
-}
-
-static irqreturn_t msm8996_liquid_docking_irq_handler(int irq, void *dev)
-{
-	struct msm8996_liquid_dock_dev *dock_dev = dev;
-
-	/* switch speakers should not run in interrupt context */
-	schedule_work(&dock_dev->irq_work);
-	return IRQ_HANDLED;
-}
-
-static int msm8996_liquid_init_docking(void)
-{
-	int ret = 0;
-	int dock_plug_gpio = 0;
-
-	/* plug in docking speaker+plug in device OR unplug one of them */
-	u32 dock_plug_irq_flags = IRQF_TRIGGER_RISING |
-				  IRQF_TRIGGER_FALLING |
-				  IRQF_SHARED;
-
-	dock_plug_gpio = of_get_named_gpio(spdev->dev.of_node,
-					   "qcom,dock-plug-det-irq", 0);
-
-	if (dock_plug_gpio >= 0) {
-		msm8996_liquid_dock_dev =
-		 kzalloc(sizeof(*msm8996_liquid_dock_dev), GFP_KERNEL);
-		if (!msm8996_liquid_dock_dev) {
-			ret = -ENOMEM;
-			goto exit;
-		}
-
-		msm8996_liquid_dock_dev->dock_plug_gpio = dock_plug_gpio;
-
-		ret = gpio_request(msm8996_liquid_dock_dev->dock_plug_gpio,
-					   "dock-plug-det-irq");
-		if (ret) {
-			pr_err("%s:failed request msm8996_liquid_dock_plug_gpio err = %d\n",
-				__func__, ret);
-			ret = -EINVAL;
-			goto fail_dock_gpio;
-		}
-
-		msm8996_liquid_dock_dev->dock_plug_det =
-			gpio_get_value(
-				msm8996_liquid_dock_dev->dock_plug_gpio);
-		msm8996_liquid_dock_dev->dock_plug_irq =
-			gpio_to_irq(
-				msm8996_liquid_dock_dev->dock_plug_gpio);
-
-		ret = request_irq(msm8996_liquid_dock_dev->dock_plug_irq,
-				  msm8996_liquid_docking_irq_handler,
-				  dock_plug_irq_flags,
-				  "liquid_dock_plug_irq",
-				  msm8996_liquid_dock_dev);
-		if (ret < 0) {
-			pr_err("%s: Request Irq Failed err = %d\n",
-				__func__, ret);
-			goto fail_dock_gpio;
-		}
-
-		msm8996_liquid_dock_dev->audio_sdev.name =
-						QC_AUDIO_EXTERNAL_SPK_1_EVENT;
-
-		if (switch_dev_register(
-			 &msm8996_liquid_dock_dev->audio_sdev) < 0) {
-			pr_err("%s: dock device register in switch diretory failed\n",
-				__func__);
-			goto fail_switch_dev;
-		}
-
-		INIT_WORK(
-			&msm8996_liquid_dock_dev->irq_work,
-			msm8996_liquid_docking_irq_work);
-	}
-	return 0;
-
-fail_switch_dev:
-	free_irq(msm8996_liquid_dock_dev->dock_plug_irq,
-				msm8996_liquid_dock_dev);
-fail_dock_gpio:
-	gpio_free(msm8996_liquid_dock_dev->dock_plug_gpio);
-exit:
-	kfree(msm8996_liquid_dock_dev);
-	msm8996_liquid_dock_dev = NULL;
-	return ret;
-}
-
-static void msm8996_ext_control(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
-
-	pr_debug("%s: msm8996_spk_control = %d", __func__,
-		 msm8996_spk_control);
-	if (msm8996_spk_control == MSM8996_SPK_ON) {
-		snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
-		snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
-	} else {
-		snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp");
-		snd_soc_dapm_disable_pin(dapm, "Lineout_2 amp");
-	}
-	snd_soc_dapm_sync(dapm);
-}
-
-static int msm8996_get_spk(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm8996_spk_control = %d\n",
-			 __func__, msm8996_spk_control);
-	ucontrol->value.integer.value[0] = msm8996_spk_control;
-	return 0;
-}
-
-static int msm8996_set_spk(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
-
-	pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n",
-		 __func__, ucontrol->value.integer.value[0]);
-	if (msm8996_spk_control == ucontrol->value.integer.value[0])
-		return 0;
-
-	msm8996_spk_control = ucontrol->value.integer.value[0];
-	msm8996_ext_control(codec);
-	return 1;
-}
-
-static int msm8996_hifi_ctrl(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
-	struct snd_soc_card *card = codec->component.card;
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(card);
-
-	pr_debug("%s: msm_hifi_control = %d", __func__,
-		 msm_hifi_control);
-	if (pdata->hph_en1_gpio < 0) {
-		pr_err("%s: hph_en1_gpio is invalid\n", __func__);
-		return -EINVAL;
-	}
-	if (msm_hifi_control == MSM8996_HIFI_ON) {
-		gpio_direction_output(pdata->hph_en1_gpio, 1);
-		/* 5msec delay needed as per HW requirement */
-		usleep_range(5000, 5010);
-	} else {
-		gpio_direction_output(pdata->hph_en1_gpio, 0);
-	}
-	snd_soc_dapm_sync(dapm);
-	return 0;
-}
-
-static int msm8996_hifi_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_hifi_control = %d\n",
-			 __func__, msm_hifi_control);
-	ucontrol->value.integer.value[0] = msm_hifi_control;
-	return 0;
-}
-
-static int msm8996_hifi_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
-
-	pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n",
-		 __func__, ucontrol->value.integer.value[0]);
-
-	msm_hifi_control = ucontrol->value.integer.value[0];
-	msm8996_hifi_ctrl(codec);
-	return 1;
-}
-
-static int msm8996_ext_us_amp_init(void)
-{
-	int ret = 0;
-
-	ext_us_amp_gpio = of_get_named_gpio(spdev->dev.of_node,
-				"qcom,ext-ult-spk-amp-gpio", 0);
-	if (ext_us_amp_gpio >= 0) {
-		ret = gpio_request(ext_us_amp_gpio, "ext_us_amp_gpio");
-		if (ret) {
-			pr_err("%s: ext_us_amp_gpio request failed, ret:%d\n",
-				__func__, ret);
-			return ret;
-		}
-		gpio_direction_output(ext_us_amp_gpio, 0);
-	}
-	return ret;
-}
-
-static void msm8996_ext_us_amp_enable(u32 on)
-{
-	if (on)
-		gpio_direction_output(ext_us_amp_gpio, 1);
-	else
-		gpio_direction_output(ext_us_amp_gpio, 0);
-
-	pr_debug("%s: US Emitter GPIO enable:%s\n", __func__,
-			on ? "Enable" : "Disable");
-}
-
-static int msm_ext_ultrasound_event(struct snd_soc_dapm_widget *w,
-				    struct snd_kcontrol *k, int event)
-{
-	pr_debug("%s()\n", __func__);
-	if (strcmp(w->name, "ultrasound amp")) {
-		if (!gpio_is_valid(ext_us_amp_gpio)) {
-			pr_err("%s: ext_us_amp_gpio isn't configured\n",
-				__func__);
-			return -EINVAL;
-		}
-		if (SND_SOC_DAPM_EVENT_ON(event))
-			msm8996_ext_us_amp_enable(1);
-		else
-			msm8996_ext_us_amp_enable(0);
-	} else {
-		pr_err("%s() Invalid Widget = %s\n",
-				__func__, w->name);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
-					int enable, bool dapm)
-{
-	int ret = 0;
-
-	if (!strcmp(dev_name(codec->dev), "tasha_codec")) {
-		ret = tasha_cdc_mclk_enable(codec, enable, dapm);
-	} else {
-		dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
-			__func__);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int msm8996_mclk_event(struct snd_soc_dapm_widget *w,
-				 struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	pr_debug("%s: event = %d\n", __func__, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		return msm_snd_enable_codec_ext_clk(codec, 1, true);
-	case SND_SOC_DAPM_POST_PMD:
-		return msm_snd_enable_codec_ext_clk(codec, 0, true);
-	}
-	return 0;
-}
-
-static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
-					   int enable, bool dapm)
-{
-	int ret = 0;
-
-	if (!strcmp(dev_name(codec->dev), "tasha_codec"))
-		ret = tasha_cdc_mclk_tx_enable(codec, enable, dapm);
-	else {
-		dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
-			__func__);
-		ret = -EINVAL;
-	}
-	return ret;
-}
-
-static int msm8996_mclk_tx_event(struct snd_soc_dapm_widget *w,
-				 struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	pr_debug("%s: event = %d\n", __func__, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
-	case SND_SOC_DAPM_POST_PMD:
-		return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
-	}
-	return 0;
-}
-
-static int msm_hifi_ctrl_event(struct snd_soc_dapm_widget *w,
-				    struct snd_kcontrol *k, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-	struct snd_soc_card *card = codec->component.card;
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(card);
-	int ret = 0;
-
-	pr_debug("%s: msm_hifi_control = %d", __func__,
-		 msm_hifi_control);
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		if (msm_hifi_control == MSM8996_HIFI_ON) {
-			if (pdata->hph_en0_gpio < 0) {
-				pr_err("%s: hph_en0_gpio is invalid\n",
-					__func__);
-				ret = -EINVAL;
-				goto err;
-			}
-			gpio_direction_output(pdata->hph_en0_gpio, 1);
-		}
-		break;
-	case SND_SOC_DAPM_PRE_PMD:
-		if (msm_hifi_control == MSM8996_HIFI_ON) {
-			if (pdata->hph_en0_gpio < 0) {
-				pr_err("%s: hph_en0_gpio is invalid\n",
-					__func__);
-				ret = -EINVAL;
-				goto err;
-			}
-			gpio_direction_output(pdata->hph_en0_gpio, 0);
-		}
-		break;
-	}
-err:
-	return ret;
-}
-
-static const struct snd_soc_dapm_widget msm8996_dapm_widgets[] = {
-
-	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
-	msm8996_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_SUPPLY("MCLK TX",  SND_SOC_NOPM, 0, 0,
-	msm8996_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
-	SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
-	SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
-	SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
-	SND_SOC_DAPM_SPK("ultrasound amp", msm_ext_ultrasound_event),
-	SND_SOC_DAPM_SPK("hifi amp", msm_hifi_ctrl_event),
-	SND_SOC_DAPM_MIC("Handset Mic", NULL),
-	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-	SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
-	SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
-	SND_SOC_DAPM_MIC("Analog Mic4", NULL),
-	SND_SOC_DAPM_MIC("Analog Mic6", NULL),
-	SND_SOC_DAPM_MIC("Analog Mic7", NULL),
-	SND_SOC_DAPM_MIC("Analog Mic8", NULL),
-
-	SND_SOC_DAPM_MIC("Digital Mic0", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic1", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic2", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic3", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic4", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic5", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic6", NULL),
-};
-
-static struct snd_soc_dapm_route wcd9335_audio_paths[] = {
-	{"MIC BIAS1", NULL, "MCLK TX"},
-	{"MIC BIAS2", NULL, "MCLK TX"},
-	{"MIC BIAS3", NULL, "MCLK TX"},
-	{"MIC BIAS4", NULL, "MCLK TX"},
-};
-
-static int slim5_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	int sample_rate_val = 0;
-
-	switch (slim5_rx_sample_rate) {
-	case SAMPLING_RATE_44P1KHZ:
-		sample_rate_val = 3;
-		break;
-
-	case SAMPLING_RATE_192KHZ:
-		sample_rate_val = 2;
-		break;
-
-	case SAMPLING_RATE_96KHZ:
-		sample_rate_val = 1;
-		break;
-
-	case SAMPLING_RATE_48KHZ:
-	default:
-		sample_rate_val = 0;
-		break;
-	}
-
-	ucontrol->value.integer.value[0] = sample_rate_val;
-	pr_debug("%s: slim5_rx_sample_rate = %d\n", __func__,
-		 slim5_rx_sample_rate);
-
-	return 0;
-}
-
-static int slim5_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: ucontrol value = %ld\n", __func__,
-		 ucontrol->value.integer.value[0]);
-
-	switch (ucontrol->value.integer.value[0]) {
-	case 3:
-		slim5_rx_sample_rate = SAMPLING_RATE_44P1KHZ;
-		break;
-	case 2:
-		slim5_rx_sample_rate = SAMPLING_RATE_192KHZ;
-		break;
-	case 1:
-		slim5_rx_sample_rate = SAMPLING_RATE_96KHZ;
-		break;
-	case 0:
-	default:
-		slim5_rx_sample_rate = SAMPLING_RATE_48KHZ;
-	}
-
-	pr_debug("%s: slim5_rx_sample_rate = %d\n", __func__,
-		 slim5_rx_sample_rate);
-
-	return 0;
-}
-
-static int slim6_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
-{
-	int sample_rate_val = 0;
-
-	switch (slim6_rx_sample_rate) {
-	case SAMPLING_RATE_44P1KHZ:
-		sample_rate_val = 3;
-		break;
-
-	case SAMPLING_RATE_192KHZ:
-		sample_rate_val = 2;
-		break;
-
-	case SAMPLING_RATE_96KHZ:
-		sample_rate_val = 1;
-		break;
-
-	case SAMPLING_RATE_48KHZ:
-	default:
-		sample_rate_val = 0;
-		break;
-	}
-
-	ucontrol->value.integer.value[0] = sample_rate_val;
-	pr_debug("%s: slim6_rx_sample_rate = %d\n", __func__,
-		 slim6_rx_sample_rate);
-
-	return 0;
-}
-
-static int slim6_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	switch (ucontrol->value.integer.value[0]) {
-	case 3:
-		slim6_rx_sample_rate = SAMPLING_RATE_44P1KHZ;
-		break;
-	case 2:
-		slim6_rx_sample_rate = SAMPLING_RATE_192KHZ;
-		break;
-	case 1:
-		slim6_rx_sample_rate = SAMPLING_RATE_96KHZ;
-		break;
-	case 0:
-	default:
-		slim6_rx_sample_rate = SAMPLING_RATE_48KHZ;
-		break;
-	}
-
-	pr_debug("%s: ucontrol value = %ld, slim6_rx_sample_rate = %d\n",
-		 __func__, ucontrol->value.integer.value[0],
-		 slim6_rx_sample_rate);
-
-	return 0;
-}
-
-static int slim0_tx_bit_format_get(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	switch (slim0_tx_bit_format) {
-	case SNDRV_PCM_FORMAT_S24_3LE:
-		ucontrol->value.integer.value[0] = 2;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-		ucontrol->value.integer.value[0] = 1;
-		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	default:
-		ucontrol->value.integer.value[0] = 0;
-		break;
-	}
-
-	pr_debug("%s: slim0_tx_bit_format = %d, ucontrol value = %ld\n",
-			 __func__, slim0_tx_bit_format,
-			ucontrol->value.integer.value[0]);
-	return 0;
-}
-
-static int slim0_tx_bit_format_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	int rc = 0;
-
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		slim0_tx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
-		break;
-	case 1:
-		slim0_tx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
-		break;
-	case 0:
-		slim0_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-		break;
-	default:
-		pr_err("%s: invalid value %ld\n", __func__,
-		       ucontrol->value.integer.value[0]);
-		rc = -EINVAL;
-		break;
-	}
-
-	pr_debug("%s: ucontrol value = %ld, slim0_tx_bit_format = %d\n",
-		 __func__, ucontrol->value.integer.value[0],
-		 slim0_tx_bit_format);
-
-	return rc;
-}
-
-static int slim0_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	int sample_rate_val = 0;
-
-	switch (slim0_rx_sample_rate) {
-	case SAMPLING_RATE_32KHZ:
-		sample_rate_val = 6;
-		break;
-
-	case SAMPLING_RATE_16KHZ:
-		sample_rate_val = 5;
-		break;
-
-	case SAMPLING_RATE_8KHZ:
-		sample_rate_val = 4;
-		break;
-
-	case SAMPLING_RATE_44P1KHZ:
-		sample_rate_val = 3;
-		break;
-
-	case SAMPLING_RATE_192KHZ:
-		sample_rate_val = 2;
-		break;
-
-	case SAMPLING_RATE_96KHZ:
-		sample_rate_val = 1;
-		break;
-
-	case SAMPLING_RATE_48KHZ:
-	default:
-		sample_rate_val = 0;
-		break;
-	}
-
-	ucontrol->value.integer.value[0] = sample_rate_val;
-	pr_debug("%s: slim0_rx_sample_rate = %d\n", __func__,
-		 slim0_rx_sample_rate);
-
-	return 0;
-}
-
-static int slim0_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: ucontrol value = %ld\n", __func__,
-		 ucontrol->value.integer.value[0]);
-
-	switch (ucontrol->value.integer.value[0]) {
-	case 6:
-		slim0_rx_sample_rate = SAMPLING_RATE_32KHZ;
-		break;
-	case 5:
-		slim0_rx_sample_rate = SAMPLING_RATE_16KHZ;
-		break;
-	case 4:
-		slim0_rx_sample_rate = SAMPLING_RATE_8KHZ;
-		break;
-	case 3:
-		slim0_rx_sample_rate = SAMPLING_RATE_44P1KHZ;
-		break;
-	case 2:
-		slim0_rx_sample_rate = SAMPLING_RATE_192KHZ;
-		break;
-	case 1:
-		slim0_rx_sample_rate = SAMPLING_RATE_96KHZ;
-		break;
-	case 0:
-	default:
-		slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
-	}
-
-	pr_debug("%s: slim0_rx_sample_rate = %d\n", __func__,
-		 slim0_rx_sample_rate);
-
-	return 0;
-}
-
-static int slim0_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	int sample_rate_val = 0;
-
-	switch (slim0_tx_sample_rate) {
-	case SAMPLING_RATE_192KHZ:
-		sample_rate_val = 2;
-		break;
-	case SAMPLING_RATE_96KHZ:
-		sample_rate_val = 1;
-		break;
-	case SAMPLING_RATE_48KHZ:
-	default:
-		sample_rate_val = 0;
-		break;
-	}
-
-	ucontrol->value.integer.value[0] = sample_rate_val;
-	pr_debug("%s: slim0_tx_sample_rate = %d\n", __func__,
-				slim0_tx_sample_rate);
-	return 0;
-}
-
-static int slim0_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	int rc = 0;
-
-	pr_debug("%s: ucontrol value = %ld\n", __func__,
-			ucontrol->value.integer.value[0]);
-
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		slim0_tx_sample_rate = SAMPLING_RATE_192KHZ;
-		break;
-	case 1:
-		slim0_tx_sample_rate = SAMPLING_RATE_96KHZ;
-		break;
-	case 0:
-		slim0_tx_sample_rate = SAMPLING_RATE_48KHZ;
-		break;
-	default:
-		rc = -EINVAL;
-		pr_err("%s: invalid sample rate being passed\n", __func__);
-		break;
-	}
-
-	pr_debug("%s: slim0_tx_sample_rate = %d\n", __func__,
-			slim0_tx_sample_rate);
-	return rc;
-}
-
-static int slim5_rx_bit_format_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-
-	switch (slim5_rx_bit_format) {
-	case SNDRV_PCM_FORMAT_S24_3LE:
-		ucontrol->value.integer.value[0] = 2;
-		break;
-
-	case SNDRV_PCM_FORMAT_S24_LE:
-		ucontrol->value.integer.value[0] = 1;
-		break;
-
-	case SNDRV_PCM_FORMAT_S16_LE:
-	default:
-		ucontrol->value.integer.value[0] = 0;
-		break;
-	}
-
-	pr_debug("%s: slim5_rx_bit_format = %d, ucontrol value = %ld\n",
-		 __func__, slim5_rx_bit_format,
-			ucontrol->value.integer.value[0]);
-
-	return 0;
-}
-
-static int slim5_rx_bit_format_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		slim5_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
-		break;
-	case 1:
-		slim5_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
-		break;
-	case 0:
-	default:
-		slim5_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-		break;
-	}
-	return 0;
-}
-
-static int slim6_rx_bit_format_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-
-	switch (slim6_rx_bit_format) {
-	case SNDRV_PCM_FORMAT_S24_3LE:
-		ucontrol->value.integer.value[0] = 2;
-		break;
-
-	case SNDRV_PCM_FORMAT_S24_LE:
-		ucontrol->value.integer.value[0] = 1;
-		break;
-
-	case SNDRV_PCM_FORMAT_S16_LE:
-	default:
-		ucontrol->value.integer.value[0] = 0;
-		break;
-	}
-
-	pr_debug("%s: slim6_rx_bit_format = %d, ucontrol value = %ld\n",
-		 __func__, slim6_rx_bit_format,
-		 ucontrol->value.integer.value[0]);
-
-	return 0;
-}
-
-static int slim6_rx_bit_format_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		slim6_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
-		break;
-	case 1:
-		slim6_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
-		break;
-	case 0:
-	default:
-		slim6_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-		break;
-	}
-	return 0;
-}
-
-static int slim0_rx_bit_format_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-
-	switch (slim0_rx_bit_format) {
-	case SNDRV_PCM_FORMAT_S24_3LE:
-		ucontrol->value.integer.value[0] = 2;
-		break;
-
-	case SNDRV_PCM_FORMAT_S24_LE:
-		ucontrol->value.integer.value[0] = 1;
-		break;
-
-	case SNDRV_PCM_FORMAT_S16_LE:
-	default:
-		ucontrol->value.integer.value[0] = 0;
-		break;
-	}
-
-	pr_debug("%s: slim0_rx_bit_format = %d, ucontrol value = %ld\n",
-		 __func__, slim0_rx_bit_format,
-			ucontrol->value.integer.value[0]);
-
-	return 0;
-}
-
-static int slim0_rx_bit_format_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		slim0_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
-		break;
-	case 1:
-		slim0_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
-		break;
-	case 0:
-	default:
-		slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-		break;
-	}
-	return 0;
-}
-
-static int msm_slim_5_rx_ch_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_slim_5_rx_ch  = %d\n", __func__,
-		 msm_slim_5_rx_ch);
-	ucontrol->value.integer.value[0] = msm_slim_5_rx_ch - 1;
-	return 0;
-}
-
-static int msm_slim_5_rx_ch_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	msm_slim_5_rx_ch = ucontrol->value.integer.value[0] + 1;
-	pr_debug("%s: msm_slim_5_rx_ch = %d\n", __func__,
-		 msm_slim_5_rx_ch);
-	return 1;
-}
-
-static int msm_slim_6_rx_ch_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_slim_6_rx_ch  = %d\n", __func__,
-		 msm_slim_6_rx_ch);
-	ucontrol->value.integer.value[0] = msm_slim_6_rx_ch - 1;
-	return 0;
-}
-
-static int msm_slim_6_rx_ch_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	msm_slim_6_rx_ch = ucontrol->value.integer.value[0] + 1;
-	pr_debug("%s: msm_slim_6_rx_ch = %d\n", __func__,
-		 msm_slim_6_rx_ch);
-	return 1;
-}
-
-static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_slim_0_rx_ch  = %d\n", __func__,
-		 msm_slim_0_rx_ch);
-	ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
-	return 0;
-}
-
-static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
-	pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
-		 msm_slim_0_rx_ch);
-	return 1;
-}
-
-static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_slim_0_tx_ch  = %d\n", __func__,
-		 msm_slim_0_tx_ch);
-	ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
-	return 0;
-}
-
-static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
-	pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__, msm_slim_0_tx_ch);
-	return 1;
-}
-
-static int msm_slim_1_tx_ch_get(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_slim_1_tx_ch  = %d\n", __func__,
-		 msm_slim_1_tx_ch);
-	ucontrol->value.integer.value[0] = msm_slim_1_tx_ch - 1;
-	return 0;
-}
-
-static int msm_slim_1_tx_ch_put(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	msm_slim_1_tx_ch = ucontrol->value.integer.value[0] + 1;
-
-	pr_debug("%s: msm_slim_1_tx_ch = %d\n", __func__, msm_slim_1_tx_ch);
-	return 1;
-}
-
-static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
-	pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
-		 ucontrol->value.integer.value[0]);
-	return 0;
-}
-
-static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
-
-	pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
-	return 1;
-}
-
-static int hdmi_rx_bit_format_get(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-
-	switch (hdmi_rx_bit_format) {
-	case SNDRV_PCM_FORMAT_S24_3LE:
-		ucontrol->value.integer.value[0] = 2;
-		break;
-
-	case SNDRV_PCM_FORMAT_S24_LE:
-		ucontrol->value.integer.value[0] = 1;
-		break;
-
-	case SNDRV_PCM_FORMAT_S16_LE:
-	default:
-		ucontrol->value.integer.value[0] = 0;
-		break;
-	}
-
-	pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
-		 __func__, hdmi_rx_bit_format,
-			ucontrol->value.integer.value[0]);
-
-	return 0;
-}
-
-static int hdmi_rx_bit_format_put(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
-		break;
-	case 1:
-		hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
-		break;
-	case 0:
-	default:
-		hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
-		break;
-	}
-	pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
-		 __func__, hdmi_rx_bit_format,
-			ucontrol->value.integer.value[0]);
-	return 0;
-}
-
-static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_hdmi_rx_ch  = %d\n", __func__,
-		 msm_hdmi_rx_ch);
-	ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
-
-	return 0;
-}
-
-static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
-	if (msm_hdmi_rx_ch > 8) {
-		pr_err("%s: channels %d exceeded 8.Limiting to max chs-8\n",
-			__func__, msm_hdmi_rx_ch);
-		msm_hdmi_rx_ch = 8;
-	}
-	pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__, msm_hdmi_rx_ch);
-
-	return 1;
-}
-
-static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	int sample_rate_val = 0;
-
-	switch (hdmi_rx_sample_rate) {
-	case SAMPLING_RATE_192KHZ:
-		sample_rate_val = 2;
-		break;
-
-	case SAMPLING_RATE_96KHZ:
-		sample_rate_val = 1;
-		break;
-
-	case SAMPLING_RATE_48KHZ:
-	default:
-		sample_rate_val = 0;
-		break;
-	}
-
-	ucontrol->value.integer.value[0] = sample_rate_val;
-	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
-		 hdmi_rx_sample_rate);
-
-	return 0;
-}
-
-static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: ucontrol value = %ld\n", __func__,
-		 ucontrol->value.integer.value[0]);
-
-	switch (ucontrol->value.integer.value[0]) {
-	case 2:
-		hdmi_rx_sample_rate = SAMPLING_RATE_192KHZ;
-		break;
-	case 1:
-		hdmi_rx_sample_rate = SAMPLING_RATE_96KHZ;
-		break;
-	case 0:
-	default:
-		hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
-	}
-
-	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
-		 hdmi_rx_sample_rate);
-
-	return 0;
-}
-
-static int msm8996_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
-				      struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = msm8996_auxpcm_rate;
-	return 0;
-}
-
-static int msm8996_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
-				      struct snd_ctl_elem_value *ucontrol)
-{
-	switch (ucontrol->value.integer.value[0]) {
-	case 0:
-		msm8996_auxpcm_rate = SAMPLING_RATE_8KHZ;
-		break;
-	case 1:
-		msm8996_auxpcm_rate = SAMPLING_RATE_16KHZ;
-		break;
-	default:
-		msm8996_auxpcm_rate = SAMPLING_RATE_8KHZ;
-		break;
-	}
-	return 0;
-}
-
-static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__, msm_proxy_rx_ch);
-	ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
-	return 0;
-}
-
-static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
-	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__, msm_proxy_rx_ch);
-	return 1;
-}
-
-static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
-				      struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate =
-	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
-
-	struct snd_interval *channels =
-	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	rate->min = rate->max = msm8996_auxpcm_rate;
-	channels->min = channels->max = 1;
-
-	return 0;
-}
-
-static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					   struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
-
-	if (channels->max < 2)
-		channels->min = channels->max = 2;
-	channels->min = channels->max = msm_proxy_rx_ch;
-	rate->min = rate->max = SAMPLING_RATE_48KHZ;
-	return 0;
-}
-
-static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					   struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-
-	rate->min = rate->max = SAMPLING_RATE_48KHZ;
-	return 0;
-}
-
-static int msm8996_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					      struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
-		 channels->min, channels->max);
-
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				hdmi_rx_bit_format);
-	if (channels->max < 2)
-		channels->min = channels->max = 2;
-	rate->min = rate->max = hdmi_rx_sample_rate;
-	channels->min = channels->max = msm_hdmi_rx_ch;
-
-	return 0;
-}
-
-static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-				     struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s: channel:%d\n", __func__, msm_tert_mi2s_tx_ch);
-	rate->min = rate->max = SAMPLING_RATE_48KHZ;
-	channels->min = channels->max = msm_tert_mi2s_tx_ch;
-	return 0;
-}
-
-static int msm8996_mi2s_snd_startup(struct snd_pcm_substream *substream)
-{
-	int ret = 0;
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
-	pr_debug("%s: substream = %s  stream = %d\n", __func__,
-		 substream->name, substream->stream);
-
-	mi2s_tx_clk.enable = 1;
-	ret = afe_set_lpass_clock_v2(AFE_PORT_ID_TERTIARY_MI2S_TX,
-				&mi2s_tx_clk);
-	if (ret < 0) {
-		pr_err("%s: afe lpass clock failed, err:%d\n", __func__, ret);
-		goto err;
-	}
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
-	if (ret < 0)
-		pr_err("%s: set fmt cpu dai failed, err:%d\n", __func__, ret);
-err:
-	return ret;
-}
-
-static void msm8996_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
-{
-	int ret = 0;
-
-	pr_debug("%s: substream = %s  stream = %d\n", __func__,
-		substream->name, substream->stream);
-
-	mi2s_tx_clk.enable = 0;
-	ret = afe_set_lpass_clock_v2(AFE_PORT_ID_TERTIARY_MI2S_TX,
-				&mi2s_tx_clk);
-	if (ret < 0)
-		pr_err("%s: afe lpass clock failed, err:%d\n", __func__, ret);
-}
-
-static struct snd_soc_ops msm8996_mi2s_be_ops = {
-	.startup = msm8996_mi2s_snd_startup,
-	.shutdown = msm8996_mi2s_snd_shutdown,
-};
-
-static int msm_slim_5_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				   slim5_rx_bit_format);
-	rate->min = rate->max = slim5_rx_sample_rate;
-	channels->min = channels->max = msm_slim_5_rx_ch;
-
-	 pr_debug("%s: format = %d, rate = %d, channels = %d\n",
-		  __func__, params_format(params), params_rate(params),
-		  msm_slim_5_rx_ch);
-
-	return 0;
-}
-
-static int msm_slim_6_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				   slim6_rx_bit_format);
-	rate->min = rate->max = slim6_rx_sample_rate;
-	channels->min = channels->max = msm_slim_6_rx_ch;
-
-	pr_debug("%s: format = %d, rate = %d, channels = %d\n",
-		 __func__, params_format(params), params_rate(params),
-		 msm_slim_6_rx_ch);
-
-	return 0;
-}
-
-static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				   slim0_rx_bit_format);
-	rate->min = rate->max = slim0_rx_sample_rate;
-	channels->min = channels->max = msm_slim_0_rx_ch;
-
-	 pr_debug("%s: format = %d, rate = %d, channels = %d\n",
-		  __func__, params_format(params), params_rate(params),
-		  msm_slim_0_rx_ch);
-
-	return 0;
-}
-
-static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s()\n", __func__);
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, slim0_tx_bit_format);
-	rate->min = rate->max = slim0_tx_sample_rate;
-	channels->min = channels->max = msm_slim_0_tx_ch;
-
-	return 0;
-}
-
-static int msm_slim_1_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s()\n", __func__);
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, slim1_tx_bit_format);
-	rate->min = rate->max = slim1_tx_sample_rate;
-	channels->min = channels->max = msm_slim_1_tx_ch;
-
-	return 0;
-}
-
-static int msm_slim_4_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-		       SNDRV_PCM_FORMAT_S32_LE);
-
-	rate->min = rate->max = SAMPLING_RATE_8KHZ;
-	channels->min = channels->max = msm_vi_feed_tx_ch;
-	pr_debug("%s: msm_vi_feed_tx_ch: %d\n", __func__, msm_vi_feed_tx_ch);
-
-	return 0;
-}
-
-static int msm_slim_5_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					    struct snd_pcm_hw_params *params)
-{
-	int rc = 0;
-	void *config = NULL;
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s: enter\n", __func__);
-	rate->min = rate->max = SAMPLING_RATE_16KHZ;
-	channels->min = channels->max = 1;
-
-	config = msm8996_codec_fn.get_afe_config_fn(codec,
-				AFE_SLIMBUS_SLAVE_PORT_CONFIG);
-	if (config) {
-		rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG, config,
-				    SLIMBUS_5_TX);
-		if (rc) {
-			pr_err("%s: Failed to set slimbus slave port config %d\n",
-				__func__, rc);
-		}
-	}
-
-	return rc;
-}
-
-static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-				  struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-
-	pr_debug("%s:\n", __func__);
-	rate->min = rate->max = SAMPLING_RATE_48KHZ;
-	return 0;
-}
-
-static const struct soc_enum msm_snd_enum[] = {
-	SOC_ENUM_SINGLE_EXT(2, spk_function),
-	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
-	SOC_ENUM_SINGLE_EXT(8, slim0_tx_ch_text),
-	SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text),
-			    rx_bit_format_text),
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim0_rx_sample_rate_text),
-			    slim0_rx_sample_rate_text),
-	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
-	SOC_ENUM_SINGLE_EXT(3, hdmi_rx_sample_rate_text),
-	SOC_ENUM_SINGLE_EXT(4, slim5_rx_sample_rate_text),
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim5_rx_bit_format_text),
-			    slim5_rx_bit_format_text),
-	SOC_ENUM_SINGLE_EXT(2, slim5_rx_ch_text),
-	SOC_ENUM_SINGLE_EXT(2, hifi_function),
-	SOC_ENUM_SINGLE_EXT(2, vi_feed_ch_text),
-	SOC_ENUM_SINGLE_EXT(4, slim6_rx_sample_rate_text),
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim6_rx_bit_format_text),
-			    slim6_rx_bit_format_text),
-	SOC_ENUM_SINGLE_EXT(2, slim6_rx_ch_text),
-};
-
-static const struct snd_kcontrol_new msm_snd_controls[] = {
-	SOC_ENUM_EXT("Speaker Function", msm_snd_enum[0], msm8996_get_spk,
-			msm8996_set_spk),
-	SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[1],
-			msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
-	SOC_ENUM_EXT("SLIM_5_RX Channels", msm_snd_enum[10],
-			msm_slim_5_rx_ch_get, msm_slim_5_rx_ch_put),
-	SOC_ENUM_EXT("SLIM_6_RX Channels", msm_snd_enum[15],
-			msm_slim_6_rx_ch_get, msm_slim_6_rx_ch_put),
-	SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[2],
-			msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
-	SOC_ENUM_EXT("SLIM_1_TX Channels", msm_snd_enum[2],
-			msm_slim_1_tx_ch_get, msm_slim_1_tx_ch_put),
-	SOC_ENUM_EXT("AUX PCM SampleRate", msm8996_auxpcm_enum[0],
-			msm8996_auxpcm_rate_get,
-			msm8996_auxpcm_rate_put),
-	SOC_ENUM_EXT("HDMI_RX Channels", msm_snd_enum[3],
-			msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
-	SOC_ENUM_EXT("SLIM_0_RX Format", msm_snd_enum[4],
-			slim0_rx_bit_format_get, slim0_rx_bit_format_put),
-	SOC_ENUM_EXT("SLIM_5_RX Format", msm_snd_enum[9],
-			slim5_rx_bit_format_get, slim5_rx_bit_format_put),
-	SOC_ENUM_EXT("SLIM_6_RX Format", msm_snd_enum[14],
-			slim6_rx_bit_format_get, slim6_rx_bit_format_put),
-	SOC_ENUM_EXT("SLIM_0_RX SampleRate", msm_snd_enum[5],
-			slim0_rx_sample_rate_get, slim0_rx_sample_rate_put),
-	SOC_ENUM_EXT("SLIM_5_RX SampleRate", msm_snd_enum[8],
-			slim5_rx_sample_rate_get, slim5_rx_sample_rate_put),
-	SOC_ENUM_EXT("SLIM_6_RX SampleRate", msm_snd_enum[13],
-			slim6_rx_sample_rate_get, slim6_rx_sample_rate_put),
-	SOC_ENUM_EXT("HDMI_RX Bit Format", msm_snd_enum[4],
-			hdmi_rx_bit_format_get, hdmi_rx_bit_format_put),
-	SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[6],
-			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
-	SOC_ENUM_EXT("HDMI_RX SampleRate", msm_snd_enum[7],
-			hdmi_rx_sample_rate_get, hdmi_rx_sample_rate_put),
-	SOC_ENUM_EXT("SLIM_0_TX SampleRate", msm_snd_enum[5],
-			slim0_tx_sample_rate_get, slim0_tx_sample_rate_put),
-	SOC_ENUM_EXT("SLIM_0_TX Format", msm_snd_enum[4],
-			slim0_tx_bit_format_get, slim0_tx_bit_format_put),
-	SOC_ENUM_EXT("HiFi Function", msm_snd_enum[11], msm8996_hifi_get,
-			msm8996_hifi_put),
-	SOC_ENUM_EXT("VI_FEED_TX Channels", msm_snd_enum[12],
-			msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
-};
-
-static bool msm8996_swap_gnd_mic(struct snd_soc_codec *codec)
-{
-	struct snd_soc_card *card = codec->component.card;
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(card);
-	int value = gpio_get_value_cansleep(pdata->us_euro_gpio);
-
-	pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
-	gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
-	return true;
-}
-
-static int msm_afe_set_config(struct snd_soc_codec *codec)
-{
-	int rc;
-	void *config_data = NULL;
-
-	pr_debug("%s: enter\n", __func__);
-
-	if (!msm8996_codec_fn.get_afe_config_fn) {
-		dev_err(codec->dev, "%s: codec get afe config not init'ed\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	config_data = msm8996_codec_fn.get_afe_config_fn(codec,
-			AFE_CDC_REGISTERS_CONFIG);
-	if (config_data) {
-		rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
-		if (rc) {
-			pr_err("%s: Failed to set codec registers config %d\n",
-					__func__, rc);
-			return rc;
-		}
-	}
-
-	config_data = msm8996_codec_fn.get_afe_config_fn(codec,
-			AFE_CDC_REGISTER_PAGE_CONFIG);
-	if (config_data) {
-		rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
-				    0);
-		if (rc)
-			pr_err("%s: Failed to set cdc register page config\n",
-				__func__);
-	}
-
-	config_data = msm8996_codec_fn.get_afe_config_fn(codec,
-			AFE_SLIMBUS_SLAVE_CONFIG);
-	if (config_data) {
-		rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
-		if (rc) {
-			pr_err("%s: Failed to set slimbus slave config %d\n",
-					__func__, rc);
-			return rc;
-		}
-	}
-
-	return 0;
-}
-
-static void msm_afe_clear_config(void)
-{
-	afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
-	afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
-}
-
-static int  msm8996_adsp_state_callback(struct notifier_block *nb,
-					   unsigned long value, void *priv)
-{
-	if (value == SUBSYS_BEFORE_SHUTDOWN) {
-		pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
-			 __func__);
-		msm_afe_clear_config();
-	} else if (value == SUBSYS_AFTER_POWERUP) {
-		pr_debug("%s: ADSP is up\n", __func__);
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block adsp_state_notifier_block = {
-	.notifier_call = msm8996_adsp_state_callback,
-	.priority = -INT_MAX,
-};
-
-static int msm8996_wcd93xx_codec_up(struct snd_soc_codec *codec)
-{
-	int err;
-	unsigned long timeout;
-	int adsp_ready = 0;
-
-	timeout = jiffies +
-		msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
-
-	do {
-		if (!q6core_is_adsp_ready()) {
-			pr_err_ratelimited("%s: ADSP Audio isn't ready\n",
-					   __func__);
-			/*
-			 * ADSP will be coming up after subsystem restart and
-			 * it might not be fully up when the control reaches
-			 * here. So, wait for 50msec before checking ADSP state
-			 */
-			msleep(50);
-		} else {
-			pr_debug("%s: ADSP Audio is ready\n", __func__);
-			adsp_ready = 1;
-			break;
-		}
-	} while (time_after(timeout, jiffies));
-
-	if (!adsp_ready) {
-		pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
-		return -ETIMEDOUT;
-	}
-
-	err = msm_afe_set_config(codec);
-	if (err)
-		pr_err("%s: Failed to set AFE config. err %d\n",
-			__func__, err);
-	return err;
-}
-
-static int msm8996_tasha_codec_event_cb(struct snd_soc_codec *codec,
-					enum wcd9335_codec_event codec_event)
-{
-	switch (codec_event) {
-	case WCD9335_CODEC_EVENT_CODEC_UP:
-		return msm8996_wcd93xx_codec_up(codec);
-	default:
-		pr_err("%s: UnSupported codec event %d\n",
-			__func__, codec_event);
-		return -EINVAL;
-	}
-}
-
-static int msm8996_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high)
-{
-	struct snd_soc_card *card = codec->component.card;
-	struct msm8996_asoc_mach_data *pdata;
-	int val;
-
-	if (!card)
-		return 0;
-
-	pdata = snd_soc_card_get_drvdata(card);
-	if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
-		return 0;
-
-	val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
-	if ((!!val) == high)
-		return 0;
-
-	gpio_direction_output(pdata->hph_en0_gpio, (int)high);
-
-	return 1;
-}
-
-static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
-{
-	int err;
-	void *config_data;
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_component *aux_comp;
-	void *mbhc_calibration;
-	struct snd_card *card;
-	struct snd_info_entry *entry;
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(rtd->card);
-
-	/* Codec SLIMBUS configuration
-	 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
-	 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
-	 * TX14, TX15, TX16
-	 */
-	unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
-					    151, 152, 153, 154, 155, 156};
-	unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
-					    134, 135, 136, 137, 138, 139,
-					    140, 141, 142, 143};
-
-	pr_info("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
-
-	rtd->pmdown_time = 0;
-
-	err = snd_soc_add_codec_controls(codec, msm_snd_controls,
-					 ARRAY_SIZE(msm_snd_controls));
-	if (err < 0) {
-		pr_err("%s: add_codec_controls failed, err %d\n",
-			__func__, err);
-		return err;
-	}
-
-	err = msm8996_liquid_init_docking();
-	if (err) {
-		pr_err("%s: 8996 init Docking stat IRQ failed (%d)\n",
-			__func__, err);
-		return err;
-	}
-
-	err = msm8996_ext_us_amp_init();
-	if (err) {
-		pr_err("%s: 8996 US Emitter GPIO init failed (%d)\n",
-			__func__, err);
-		return err;
-	}
-
-	snd_soc_dapm_new_controls(dapm, msm8996_dapm_widgets,
-				ARRAY_SIZE(msm8996_dapm_widgets));
-
-	snd_soc_dapm_add_routes(dapm, wcd9335_audio_paths,
-				ARRAY_SIZE(wcd9335_audio_paths));
-	snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
-	snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
-	snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
-	snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
-
-	snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp");
-	snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp");
-	snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp");
-	snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp");
-	snd_soc_dapm_ignore_suspend(dapm, "ultrasound amp");
-	snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
-	snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
-	snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
-	snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
-	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
-	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
-	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
-	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
-	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
-	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
-	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
-	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7");
-	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8");
-	snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
-	snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
-	snd_soc_dapm_ignore_suspend(dapm, "EAR");
-	snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
-	snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
-	snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
-	snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
-	snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
-	snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
-	snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
-	snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
-	snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
-	snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
-	snd_soc_dapm_ignore_suspend(dapm, "AMIC6");
-	snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
-	snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
-	snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
-	snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
-	snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
-	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
-	snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
-	snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
-	snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
-	snd_soc_dapm_ignore_suspend(dapm, "HPHL");
-	snd_soc_dapm_ignore_suspend(dapm, "HPHR");
-	snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
-	snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
-	snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
-	snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
-	snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
-	snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
-
-	snd_soc_dapm_sync(dapm);
-
-	snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
-				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
-
-	msm8996_codec_fn.get_afe_config_fn = tasha_get_afe_config;
-	msm8996_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit;
-
-	err = msm_afe_set_config(codec);
-	if (err) {
-		pr_err("%s: Failed to set AFE config %d\n", __func__, err);
-		goto out;
-	}
-
-	config_data = msm8996_codec_fn.get_afe_config_fn(codec,
-						AFE_AANC_VERSION);
-	if (config_data) {
-		err = afe_set_config(AFE_AANC_VERSION, config_data, 0);
-		if (err) {
-			pr_err("%s: Failed to set aanc version %d\n",
-				__func__, err);
-			goto out;
-		}
-	}
-	config_data = msm8996_codec_fn.get_afe_config_fn(codec,
-					    AFE_CDC_CLIP_REGISTERS_CONFIG);
-	if (config_data) {
-		err = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
-				     config_data, 0);
-		if (err) {
-			pr_err("%s: Failed to set clip registers %d\n",
-				__func__, err);
-			goto out;
-		}
-	}
-	config_data = msm8996_codec_fn.get_afe_config_fn(codec,
-			AFE_CLIP_BANK_SEL);
-	if (config_data) {
-		err = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
-		if (err) {
-			pr_err("%s: Failed to set AFE bank selection %d\n",
-				__func__, err);
-			goto out;
-		}
-	}
-	/* Start mbhc */
-	tasha_mbhc_zdet_gpio_ctrl(msm8996_config_hph_en0_gpio, rtd->codec);
-	mbhc_calibration = def_tasha_mbhc_cal();
-	if (mbhc_calibration) {
-		wcd_mbhc_cfg.calibration = mbhc_calibration;
-		err = tasha_mbhc_hs_detect(codec, &wcd_mbhc_cfg);
-		if (err) {
-			pr_err("%s: mbhc hs detect failed, err:%d\n",
-				__func__, err);
-			goto out;
-		}
-	} else {
-		pr_err("%s: mbhc_cfg calibration is NULL\n", __func__);
-		err = -ENOMEM;
-		goto out;
-	}
-	adsp_state_notifier = subsys_notif_register_notifier("adsp",
-						&adsp_state_notifier_block);
-	if (!adsp_state_notifier) {
-		pr_err("%s: Failed to register adsp state notifier\n",
-		       __func__);
-		err = -EFAULT;
-		msm8996_codec_fn.mbhc_hs_detect_exit(codec);
-		goto out;
-	}
-
-	tasha_event_register(msm8996_tasha_codec_event_cb, rtd->codec);
-
-	/*
-	 * Send speaker configuration only for WSA8810.
-	 * Defalut configuration is for WSA8815.
-	 */
-	if (!list_empty(&rtd->card->aux_comp_list)) {
-		aux_comp = list_first_entry(&rtd->card->aux_comp_list,
-				struct snd_soc_component, list_aux);
-		if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
-		    !strcmp(aux_comp->name, WSA8810_NAME_2)) {
-			tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
-			tasha_set_spkr_gain_offset(rtd->codec,
-						   RX_GAIN_OFFSET_M1P5_DB);
-		}
-	}
-	codec_reg_done = true;
-
-	card = rtd->card->snd_card;
-	entry = snd_info_create_subdir(card->module, "codecs",
-					 card->proc_root);
-	if (!entry) {
-		pr_debug("%s: Cannot create codecs module entry\n",
-			 __func__);
-		err = 0;
-		goto out;
-	}
-	pdata->codec_root = entry;
-	tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
-
-	return 0;
-out:
-	return err;
-}
-
-static void *def_tasha_mbhc_cal(void)
-{
-	void *tasha_wcd_cal;
-	struct wcd_mbhc_btn_detect_cfg *btn_cfg;
-	u16 *btn_high;
-
-	tasha_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
-				WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
-	if (!tasha_wcd_cal)
-		return NULL;
-
-#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tasha_wcd_cal)->X) = (Y))
-	S(v_hs_max, 1500);
-#undef S
-#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal)->X) = (Y))
-	S(num_btn, WCD_MBHC_DEF_BUTTONS);
-#undef S
-
-	btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal);
-	btn_high = ((void *)&btn_cfg->_v_btn_low) +
-		(sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
-
-	btn_high[0] = 75;
-	btn_high[1] = 150;
-	btn_high[2] = 237;
-	btn_high[3] = 500;
-	btn_high[4] = 500;
-	btn_high[5] = 500;
-	btn_high[6] = 500;
-	btn_high[7] = 500;
-
-	return tasha_wcd_cal;
-}
-
-static int msm_snd_hw_params(struct snd_pcm_substream *substream,
-			     struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai_link *dai_link = rtd->dai_link;
-
-	int ret = 0;
-	u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
-	u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
-	u32 user_set_tx_ch = 0;
-	u32 rx_ch_count;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		ret = snd_soc_dai_get_channel_map(codec_dai,
-					&tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
-		if (ret < 0) {
-			pr_err("%s: failed to get codec chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-		if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
-			pr_debug("%s: rx_5_ch=%d\n", __func__,
-				  msm_slim_5_rx_ch);
-			rx_ch_count = msm_slim_5_rx_ch;
-		} else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
-			pr_debug("%s: rx_6_ch=%d\n", __func__,
-				  msm_slim_6_rx_ch);
-			rx_ch_count = msm_slim_6_rx_ch;
-		} else {
-			pr_debug("%s: rx_0_ch=%d\n", __func__,
-				  msm_slim_0_rx_ch);
-			rx_ch_count = msm_slim_0_rx_ch;
-		}
-		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
-						  rx_ch_count, rx_ch);
-		if (ret < 0) {
-			pr_err("%s: failed to set cpu chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-	} else {
-
-		pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
-			 codec_dai->name, codec_dai->id, user_set_tx_ch);
-		ret = snd_soc_dai_get_channel_map(codec_dai,
-					 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
-		if (ret < 0) {
-			pr_err("%s: failed to get codec chan map\n, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-		/* For <codec>_tx1 case */
-		if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
-			user_set_tx_ch = msm_slim_0_tx_ch;
-		/* For <codec>_tx3 case */
-		else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
-			user_set_tx_ch = msm_slim_1_tx_ch;
-		else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_3_TX)
-			/* DAI 5 is used for external EC reference from codec.
-			 * Since Rx is fed as reference for EC, the config of
-			 * this DAI is based on that of the Rx path.
-			 */
-			user_set_tx_ch = msm_slim_0_rx_ch;
-		else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
-			user_set_tx_ch = msm_vi_feed_tx_ch;
-		else
-			user_set_tx_ch = tx_ch_cnt;
-
-		pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), BE id (%d)\n",
-			 __func__, msm_slim_0_tx_ch, user_set_tx_ch,
-			 tx_ch_cnt, dai_link->id);
-
-		ret = snd_soc_dai_set_channel_map(cpu_dai,
-						  user_set_tx_ch, tx_ch, 0, 0);
-		if (ret < 0) {
-			pr_err("%s: failed to set cpu chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-	}
-end:
-	return ret;
-}
-
-static int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai_link *dai_link = rtd->dai_link;
-
-	int ret = 0;
-	u32 tx_ch[SLIM_MAX_TX_PORTS];
-	u32 tx_ch_cnt = 0;
-	u32 user_set_tx_ch = 0;
-
-	if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
-		pr_err("%s: Invalid stream type %d\n",
-			__func__, substream->stream);
-		ret = -EINVAL;
-		goto end;
-	}
-
-	pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
-		 codec_dai->name, codec_dai->id);
-	ret = snd_soc_dai_get_channel_map(codec_dai,
-				 &tx_ch_cnt, tx_ch, NULL, NULL);
-	if (ret < 0) {
-		pr_err("%s: failed to get codec chan map\n, err:%d\n",
-			__func__, ret);
-		goto end;
-	}
-
-	user_set_tx_ch = tx_ch_cnt;
-
-	pr_debug("%s: tx_ch_cnt(%d) BE id %d\n",
-		 __func__, tx_ch_cnt, dai_link->id);
-
-	ret = snd_soc_dai_set_channel_map(cpu_dai,
-					  user_set_tx_ch, tx_ch, 0, 0);
-	if (ret < 0)
-		pr_err("%s: failed to set cpu chan map, err:%d\n",
-			__func__, ret);
-end:
-	return ret;
-}
-
-static struct snd_soc_ops msm8996_be_ops = {
-	.hw_params = msm_snd_hw_params,
-};
-
-static struct snd_soc_ops msm8996_cpe_ops = {
-	.hw_params = msm_snd_cpe_hw_params,
-};
-
-static int msm8996_slimbus_2_hw_params(struct snd_pcm_substream *substream,
-					  struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	int ret = 0;
-	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
-	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
-	unsigned int num_tx_ch = 0;
-	unsigned int num_rx_ch = 0;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		num_rx_ch =  params_channels(params);
-		pr_debug("%s: %s rx_dai_id = %d  num_ch = %d\n", __func__,
-			codec_dai->name, codec_dai->id, num_rx_ch);
-		ret = snd_soc_dai_get_channel_map(codec_dai,
-				&tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
-		if (ret < 0) {
-			pr_err("%s: failed to get codec chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
-				num_rx_ch, rx_ch);
-		if (ret < 0) {
-			pr_err("%s: failed to set cpu chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-	} else {
-		num_tx_ch =  params_channels(params);
-		pr_debug("%s: %s  tx_dai_id = %d  num_ch = %d\n", __func__,
-			codec_dai->name, codec_dai->id, num_tx_ch);
-		ret = snd_soc_dai_get_channel_map(codec_dai,
-				&tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
-		if (ret < 0) {
-			pr_err("%s: failed to get codec chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-		ret = snd_soc_dai_set_channel_map(cpu_dai,
-				num_tx_ch, tx_ch, 0, 0);
-		if (ret < 0) {
-			pr_err("%s: failed to set cpu chan map, err:%d\n",
-				__func__, ret);
-			goto end;
-		}
-	}
-end:
-	return ret;
-}
-
-static struct snd_soc_ops msm8996_slimbus_2_be_ops = {
-	.hw_params = msm8996_slimbus_2_hw_params,
-};
-
-static int msm8996_get_ll_qos_val(struct snd_pcm_runtime *runtime)
-{
-	int usecs;
-
-	/* take 10% of period time as the deadline */
-	usecs = (100000 / runtime->rate) * runtime->period_size;
-	usecs += ((100000 % runtime->rate) * runtime->period_size) /
-		runtime->rate;
-
-	return usecs;
-}
-
-static int msm8996_mm5_prepare(struct snd_pcm_substream *substream)
-{
-	if (pm_qos_request_active(&substream->latency_pm_qos_req))
-		pm_qos_remove_request(&substream->latency_pm_qos_req);
-	pm_qos_add_request(&substream->latency_pm_qos_req,
-			   PM_QOS_CPU_DMA_LATENCY,
-			   msm8996_get_ll_qos_val(substream->runtime));
-	return 0;
-}
-
-static struct snd_soc_ops msm8996_mm5_ops = {
-	.prepare = msm8996_mm5_prepare,
-};
-
-/* Digital audio interface glue - connects codec <---> CPU */
-static struct snd_soc_dai_link msm8996_common_dai_links[] = {
-	/* FrontEnd DAI Links */
-	{
-		.name = "MSM8996 Media1",
-		.stream_name = "MultiMedia1",
-		.cpu_dai_name = "MultiMedia1",
-		.platform_name = "msm-pcm-dsp.0",
-		.dynamic = 1,
-		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA1
-	},
-	{
-		.name = "MSM8996 Media2",
-		.stream_name = "MultiMedia2",
-		.cpu_dai_name = "MultiMedia2",
-		.platform_name = "msm-pcm-dsp.0",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA2,
-	},
-	{
-		.name = "VoiceMMode1",
-		.stream_name = "VoiceMMode1",
-		.cpu_dai_name = "VoiceMMode1",
-		.platform_name = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_VOICEMMODE1,
-	},
-	{
-		.name = "MSM VoIP",
-		.stream_name = "VoIP",
-		.cpu_dai_name = "VoIP",
-		.platform_name = "msm-voip-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_VOIP,
-	},
-	{
-		.name = "MSM8996 ULL",
-		.stream_name = "MultiMedia3",
-		.cpu_dai_name = "MultiMedia3",
-		.platform_name = "msm-pcm-dsp.2",
-		.dynamic = 1,
-		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA3,
-	},
-	/* Hostless PCM purpose */
-	{
-		.name = "SLIMBUS_0 Hostless",
-		.stream_name = "SLIMBUS_0 Hostless",
-		.cpu_dai_name = "SLIMBUS0_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		 /* this dailink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "Tertiary MI2S TX_Hostless",
-		.stream_name = "Tertiary MI2S_TX Hostless Capture",
-		.cpu_dai_name = "TERT_MI2S_TX_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "MSM AFE-PCM RX",
-		.stream_name = "AFE-PROXY RX",
-		.cpu_dai_name = "msm-dai-q6-dev.241",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.platform_name = "msm-pcm-afe",
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-	},
-	{
-		.name = "MSM AFE-PCM TX",
-		.stream_name = "AFE-PROXY TX",
-		.cpu_dai_name = "msm-dai-q6-dev.240",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.platform_name  = "msm-pcm-afe",
-		.ignore_suspend = 1,
-	},
-	{
-		.name = "MSM8996 Compress1",
-		.stream_name = "Compress1",
-		.cpu_dai_name = "MultiMedia4",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA4,
-	},
-	{
-		.name = "AUXPCM Hostless",
-		.stream_name = "AUXPCM Hostless",
-		.cpu_dai_name = "AUXPCM_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "SLIMBUS_1 Hostless",
-		.stream_name = "SLIMBUS_1 Hostless",
-		.cpu_dai_name = "SLIMBUS1_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		 /* this dailink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "SLIMBUS_3 Hostless",
-		.stream_name = "SLIMBUS_3 Hostless",
-		.cpu_dai_name = "SLIMBUS3_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		 /* this dailink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "SLIMBUS_4 Hostless",
-		.stream_name = "SLIMBUS_4 Hostless",
-		.cpu_dai_name = "SLIMBUS4_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		 /* this dailink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "VoLTE",
-		.stream_name = "VoLTE",
-		.cpu_dai_name = "VoLTE",
-		.platform_name = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_VOLTE,
-	},
-	{
-		.name = "MSM8996 LowLatency",
-		.stream_name = "MultiMedia5",
-		.cpu_dai_name = "MultiMedia5",
-		.platform_name = "msm-pcm-dsp.1",
-		.dynamic = 1,
-		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-				SND_SOC_DPCM_TRIGGER_POST},
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA5,
-		.ops = &msm8996_mm5_ops,
-	},
-	{
-		.name = "Listen 1 Audio Service",
-		.stream_name = "Listen 1 Audio Service",
-		.cpu_dai_name = "LSM1",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-			     SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM1,
-	},
-	/* Multiple Tunnel instances */
-	{
-		.name = "MSM8996 Compress2",
-		.stream_name = "Compress2",
-		.cpu_dai_name = "MultiMedia7",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
-	},
-	{
-		.name = "MSM8996 Compress3",
-		.stream_name = "Compress3",
-		.cpu_dai_name = "MultiMedia10",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA10,
-	},
-	{
-		.name = "MSM8996 ULL NOIRQ",
-		.stream_name = "MM_NOIRQ",
-		.cpu_dai_name = "MultiMedia8",
-		.platform_name = "msm-pcm-dsp-noirq",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA8,
-	},
-	{
-		.name = "QCHAT",
-		.stream_name = "QCHAT",
-		.cpu_dai_name = "QCHAT",
-		.platform_name = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_QCHAT,
-	},
-	/* HDMI Hostless */
-	{
-		.name = "HDMI_RX_HOSTLESS",
-		.stream_name = "HDMI_RX_HOSTLESS",
-		.cpu_dai_name = "HDMI_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "VoiceMMode2",
-		.stream_name = "VoiceMMode2",
-		.cpu_dai_name = "VoiceMMode2",
-		.platform_name = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_VOICEMMODE2,
-	},
-	{
-		.name = "INT_HFP_BT Hostless",
-		.stream_name = "INT_HFP_BT Hostless",
-		.cpu_dai_name = "INT_HFP_BT_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	{
-		.name = "MSM8996 HFP TX",
-		.stream_name = "MultiMedia6",
-		.cpu_dai_name = "MultiMedia6",
-		.platform_name = "msm-pcm-loopback",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.ignore_suspend = 1,
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA6,
-	},
-	/* LSM FE */
-	{
-		.name = "Listen 2 Audio Service",
-		.stream_name = "Listen 2 Audio Service",
-		.cpu_dai_name = "LSM2",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM2,
-	},
-	{
-		.name = "Listen 3 Audio Service",
-		.stream_name = "Listen 3 Audio Service",
-		.cpu_dai_name = "LSM3",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM3,
-	},
-	{
-		.name = "Listen 4 Audio Service",
-		.stream_name = "Listen 4 Audio Service",
-		.cpu_dai_name = "LSM4",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM4,
-	},
-	{
-		.name = "Listen 5 Audio Service",
-		.stream_name = "Listen 5 Audio Service",
-		.cpu_dai_name = "LSM5",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM5,
-	},
-	{
-		.name = "Listen 6 Audio Service",
-		.stream_name = "Listen 6 Audio Service",
-		.cpu_dai_name = "LSM6",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM6,
-	},
-	{
-		.name = "Listen 7 Audio Service",
-		.stream_name = "Listen 7 Audio Service",
-		.cpu_dai_name = "LSM7",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM7,
-	},
-	{
-		.name = "Listen 8 Audio Service",
-		.stream_name = "Listen 8 Audio Service",
-		.cpu_dai_name = "LSM8",
-		.platform_name = "msm-lsm-client",
-		.dynamic = 1,
-		.dpcm_capture = 1,
-		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
-				 SND_SOC_DPCM_TRIGGER_POST },
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_LSM8,
-	},
-	{
-		.name = "MSM8996 Media9",
-		.stream_name = "MultiMedia9",
-		.cpu_dai_name = "MultiMedia9",
-		.platform_name = "msm-pcm-dsp.0",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-				SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA9,
-	},
-	{
-		.name = "VoWLAN",
-		.stream_name = "VoWLAN",
-		.cpu_dai_name = "VoWLAN",
-		.platform_name = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_VOWLAN,
-	},
-	{
-		.name = "MSM8996 Compress4",
-		.stream_name = "Compress4",
-		.cpu_dai_name = "MultiMedia11",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA11,
-	},
-	{
-		.name = "MSM8996 Compress5",
-		.stream_name = "Compress5",
-		.cpu_dai_name = "MultiMedia12",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA12,
-	},
-	{
-		.name = "MSM8996 Compress6",
-		.stream_name = "Compress6",
-		.cpu_dai_name = "MultiMedia13",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA13,
-	},
-	{
-		.name = "MSM8996 Compress7",
-		.stream_name = "Compress7",
-		.cpu_dai_name = "MultiMedia14",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA14,
-	},
-	{
-		.name = "MSM8996 Compress8",
-		.stream_name = "Compress8",
-		.cpu_dai_name = "MultiMedia15",
-		.platform_name = "msm-compress-dsp",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA15,
-	},
-	{
-		.name = "MSM8996 ULL NOIRQ_2",
-		.stream_name = "MM_NOIRQ_2",
-		.cpu_dai_name = "MultiMedia16",
-		.platform_name = "msm-pcm-dsp-noirq",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			 SND_SOC_DPCM_TRIGGER_POST},
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		 /* this dainlink has playback support */
-		.id = MSM_FRONTEND_DAI_MULTIMEDIA16,
-	},
-	{
-		.name = "Circuit-Switch Voice",
-		.stream_name = "CS-Voice",
-		.cpu_dai_name   = "CS-VOICE",
-		.platform_name  = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.id = MSM_FRONTEND_DAI_CS_VOICE,
-	},
-	{
-		.name = "Voice2",
-		.stream_name = "Voice2",
-		.cpu_dai_name = "Voice2",
-		.platform_name = "msm-pcm-voice",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-		.id = MSM_FRONTEND_DAI_VOICE2,
-	},
-};
-
-static struct snd_soc_dai_link msm8996_tasha_fe_dai_links[] = {
-	{
-		.name = LPASS_BE_SLIMBUS_4_TX,
-		.stream_name = "Slimbus4 Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.16393",
-		.platform_name = "msm-pcm-hostless",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_vifeedback",
-		.id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
-		.be_hw_params_fixup = msm_slim_4_tx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-	},
-	/* Ultrasound RX DAI Link */
-	{
-		.name = "SLIMBUS_2 Hostless Playback",
-		.stream_name = "SLIMBUS_2 Hostless Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16388",
-		.platform_name = "msm-pcm-hostless",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_rx2",
-		.ignore_suspend = 1,
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ops = &msm8996_slimbus_2_be_ops,
-	},
-	/* Ultrasound TX DAI Link */
-	{
-		.name = "SLIMBUS_2 Hostless Capture",
-		.stream_name = "SLIMBUS_2 Hostless Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.16389",
-		.platform_name = "msm-pcm-hostless",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_tx2",
-		.ignore_suspend = 1,
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ops = &msm8996_slimbus_2_be_ops,
-	},
-	/* CPE LSM direct dai-link */
-	{
-		.name = "CPE Listen service",
-		.stream_name = "CPE Listen Audio Service",
-		.cpu_dai_name = "msm-dai-slim",
-		.platform_name = "msm-cpe-lsm",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "tasha_mad1",
-		.codec_name = "tasha_codec",
-		.ops = &msm8996_cpe_ops,
-	},
-	/* slimbus rx 6 hostless */
-	{
-		.name = "SLIMBUS_6 Hostless Playback",
-		.stream_name = "SLIMBUS_6 Hostless",
-		.cpu_dai_name = "SLIMBUS6_HOSTLESS",
-		.platform_name = "msm-pcm-hostless",
-		.dynamic = 1,
-		.dpcm_playback = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		 /* this dailink has playback support */
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.codec_name = "snd-soc-dummy",
-	},
-	/* CPE LSM EC PP direct dai-link */
-	{
-		.name = "CPE Listen service ECPP",
-		.stream_name = "CPE Listen Audio Service ECPP",
-		.cpu_dai_name = "CPE_LSM_NOHOST",
-		.platform_name = "msm-cpe-lsm.3",
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
-			    SND_SOC_DPCM_TRIGGER_POST},
-		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.codec_dai_name = "tasha_cpe",
-		.codec_name = "tasha_codec",
-	},
-};
-
-static struct snd_soc_dai_link msm8996_common_be_dai_links[] = {
-	/* Backend AFE DAI Links */
-	{
-		.name = LPASS_BE_AFE_PCM_RX,
-		.stream_name = "AFE Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.224",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_AFE_PCM_RX,
-		.be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_AFE_PCM_TX,
-		.stream_name = "AFE Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.225",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_AFE_PCM_TX,
-		.be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Primary AUX PCM Backend DAI Links */
-	{
-		.name = LPASS_BE_AUXPCM_RX,
-		.stream_name = "AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_AUXPCM_RX,
-		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-		/* this dainlink has playback support */
-	},
-	{
-		.name = LPASS_BE_AUXPCM_TX,
-		.stream_name = "AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_AUXPCM_TX,
-		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Incall Record Uplink BACK END DAI Link */
-	{
-		.name = LPASS_BE_INCALL_RECORD_TX,
-		.stream_name = "Voice Uplink Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.32772",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Incall Record Downlink BACK END DAI Link */
-	{
-		.name = LPASS_BE_INCALL_RECORD_RX,
-		.stream_name = "Voice Downlink Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.32771",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Incall Music BACK END DAI Link */
-	{
-		.name = LPASS_BE_VOICE_PLAYBACK_TX,
-		.stream_name = "Voice Farend Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.32773",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Incall Music 2 BACK END DAI Link */
-	{
-		.name = LPASS_BE_VOICE2_PLAYBACK_TX,
-		.stream_name = "Voice2 Farend Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.32770",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_TERT_MI2S_TX,
-		.stream_name = "Tertiary MI2S Capture",
-		.cpu_dai_name = "msm-dai-q6-mi2s.2",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
-		.be_hw_params_fixup = msm_tx_be_hw_params_fixup,
-		.ops = &msm8996_mi2s_be_ops,
-		.ignore_suspend = 1,
-	}
-};
-
-static struct snd_soc_dai_link msm8996_tasha_be_dai_links[] = {
-	/* Backend DAI Links */
-	{
-		.name = LPASS_BE_SLIMBUS_0_RX,
-		.stream_name = "Slimbus Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16384",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_mix_rx1",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
-		.init = &msm_audrx_init,
-		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
-		/* this dainlink has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-		.ops = &msm8996_be_ops,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_0_TX,
-		.stream_name = "Slimbus Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.16385",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_tx1",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
-		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
-		.ignore_suspend = 1,
-		.ops = &msm8996_be_ops,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_1_RX,
-		.stream_name = "Slimbus1 Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16386",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_mix_rx1",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
-		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		/* dai link has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_1_TX,
-		.stream_name = "Slimbus1 Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.16387",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_tx3",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
-		.be_hw_params_fixup = msm_slim_1_tx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_3_RX,
-		.stream_name = "Slimbus3 Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16390",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_mix_rx1",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
-		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		/* dai link has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_3_TX,
-		.stream_name = "Slimbus3 Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.16391",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_tx1",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
-		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_4_RX,
-		.stream_name = "Slimbus4 Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16392",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_mix_rx1",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
-		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		/* dai link has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_5_RX,
-		.stream_name = "Slimbus5 Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16394",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_rx3",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
-		.be_hw_params_fixup = msm_slim_5_rx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		/* dai link has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-	/* MAD BE */
-	{
-		.name = LPASS_BE_SLIMBUS_5_TX,
-		.stream_name = "Slimbus5 Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.16395",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_mad1",
-		.no_pcm = 1,
-		.dpcm_capture = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
-		.be_hw_params_fixup = msm_slim_5_tx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		.ignore_suspend = 1,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_6_RX,
-		.stream_name = "Slimbus6 Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.16396",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "tasha_codec",
-		.codec_dai_name = "tasha_rx4",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
-		.be_hw_params_fixup = msm_slim_6_rx_be_hw_params_fixup,
-		.ops = &msm8996_be_ops,
-		/* dai link has playback support */
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-};
-
-static struct snd_soc_dai_link msm8996_hdmi_dai_link[] = {
-	/* HDMI BACK END DAI Link */
-	{
-		.name = LPASS_BE_HDMI,
-		.stream_name = "HDMI Playback",
-		.cpu_dai_name = "msm-dai-q6-hdmi.8",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-hdmi-audio-codec-rx",
-		.codec_dai_name = "msm_hdmi_audio_codec_rx_dai",
-		.no_pcm = 1,
-		.dpcm_playback = 1,
-		.id = MSM_BACKEND_DAI_HDMI_RX,
-		.be_hw_params_fixup = msm8996_hdmi_be_hw_params_fixup,
-		.ignore_pmdown_time = 1,
-		.ignore_suspend = 1,
-	},
-};
-
-static struct snd_soc_dai_link msm8996_tasha_dai_links[
-			 ARRAY_SIZE(msm8996_common_dai_links) +
-			 ARRAY_SIZE(msm8996_tasha_fe_dai_links) +
-			 ARRAY_SIZE(msm8996_common_be_dai_links) +
-			 ARRAY_SIZE(msm8996_tasha_be_dai_links) +
-			 ARRAY_SIZE(msm8996_hdmi_dai_link)];
-
-static int msm8996_wsa881x_init(struct snd_soc_component *component)
-{
-	u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106};
-	u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107};
-	unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200};
-	unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3};
-	struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
-	struct msm8996_asoc_mach_data *pdata;
-	struct snd_soc_dapm_context *dapm;
-
-	if (!codec) {
-		pr_err("%s codec is NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	dapm = snd_soc_codec_get_dapm(codec);
-
-	if (!strcmp(component->name_prefix, "SpkrLeft")) {
-		dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n",
-			__func__, codec->component.name);
-		wsa881x_set_channel_map(codec, &spkleft_ports[0],
-				WSA881X_MAX_SWR_PORTS, &ch_mask[0],
-				&ch_rate[0]);
-		if (dapm->component) {
-			snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
-			snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
-		}
-	} else if (!strcmp(component->name_prefix, "SpkrRight")) {
-		dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n",
-			__func__, codec->component.name);
-		wsa881x_set_channel_map(codec, &spkright_ports[0],
-				WSA881X_MAX_SWR_PORTS, &ch_mask[0],
-				&ch_rate[0]);
-		if (dapm->component) {
-			snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
-			snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
-		}
-	} else {
-		dev_err(codec->dev, "%s: wrong codec name %s\n", __func__,
-			codec->component.name);
-		return -EINVAL;
-	}
-	pdata = snd_soc_card_get_drvdata(component->card);
-	if (pdata && pdata->codec_root)
-		wsa881x_codec_info_create_codec_entry(pdata->codec_root,
-						      codec);
-
-	return 0;
-}
-
-struct snd_soc_card snd_soc_card_tasha_msm8996 = {
-	.name		= "msm8996-tasha-snd-card",
-};
-
-static int msm8996_populate_dai_link_component_of_node(
-					struct snd_soc_card *card)
-{
-	int i, index, ret = 0;
-	struct device *cdev = card->dev;
-	struct snd_soc_dai_link *dai_link = card->dai_link;
-	struct device_node *np;
-
-	if (!cdev) {
-		pr_err("%s: Sound card device memory NULL\n", __func__);
-		return -ENODEV;
-	}
-
-	for (i = 0; i < card->num_links; i++) {
-		if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
-			continue;
-
-		/* populate platform_of_node for snd card dai links */
-		if (dai_link[i].platform_name &&
-		    !dai_link[i].platform_of_node) {
-			index = of_property_match_string(cdev->of_node,
-						"asoc-platform-names",
-						dai_link[i].platform_name);
-			if (index < 0) {
-				pr_err("%s: No match found for platform name: %s\n",
-					__func__, dai_link[i].platform_name);
-				ret = index;
-				goto err;
-			}
-			np = of_parse_phandle(cdev->of_node, "asoc-platform",
-					      index);
-			if (!np) {
-				pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
-					__func__, dai_link[i].platform_name,
-					index);
-				ret = -ENODEV;
-				goto err;
-			}
-			dai_link[i].platform_of_node = np;
-			dai_link[i].platform_name = NULL;
-		}
-
-		/* populate cpu_of_node for snd card dai links */
-		if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
-			index = of_property_match_string(cdev->of_node,
-						 "asoc-cpu-names",
-						 dai_link[i].cpu_dai_name);
-			if (index >= 0) {
-				np = of_parse_phandle(cdev->of_node, "asoc-cpu",
-						index);
-				if (!np) {
-					pr_err("%s: retrieving phandle for cpu dai %s failed\n",
-						__func__,
-						dai_link[i].cpu_dai_name);
-					ret = -ENODEV;
-					goto err;
-				}
-				dai_link[i].cpu_of_node = np;
-				dai_link[i].cpu_dai_name = NULL;
-			}
-		}
-
-		/* populate codec_of_node for snd card dai links */
-		if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
-			index = of_property_match_string(cdev->of_node,
-						 "asoc-codec-names",
-						 dai_link[i].codec_name);
-			if (index < 0)
-				continue;
-			np = of_parse_phandle(cdev->of_node, "asoc-codec",
-					      index);
-			if (!np) {
-				pr_err("%s: retrieving phandle for codec %s failed\n",
-					__func__, dai_link[i].codec_name);
-				ret = -ENODEV;
-				goto err;
-			}
-			dai_link[i].codec_of_node = np;
-			dai_link[i].codec_name = NULL;
-		}
-	}
-
-err:
-	return ret;
-}
-
-static int msm8996_prepare_us_euro(struct snd_soc_card *card)
-{
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(card);
-	int ret;
-
-	if (pdata->us_euro_gpio >= 0) {
-		dev_dbg(card->dev, "%s: us_euro gpio request %d", __func__,
-			pdata->us_euro_gpio);
-		ret = gpio_request(pdata->us_euro_gpio, "TASHA_CODEC_US_EURO");
-		if (ret) {
-			dev_err(card->dev,
-				"%s: Failed to request codec US/EURO gpio %d error %d\n",
-				__func__, pdata->us_euro_gpio, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static int msm8996_prepare_hifi(struct snd_soc_card *card)
-{
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(card);
-	int ret;
-
-	if (gpio_is_valid(pdata->hph_en1_gpio)) {
-		dev_dbg(card->dev, "%s: hph_en1_gpio request %d\n", __func__,
-			pdata->hph_en1_gpio);
-		ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
-		if (ret) {
-			dev_err(card->dev,
-				"%s: hph_en1_gpio request failed, ret:%d\n",
-				__func__, ret);
-			return ret;
-		}
-	}
-	if (gpio_is_valid(pdata->hph_en0_gpio)) {
-		dev_dbg(card->dev, "%s: hph_en0_gpio request %d\n", __func__,
-			pdata->hph_en0_gpio);
-		ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
-		if (ret) {
-			dev_err(card->dev,
-				"%s: hph_en0_gpio request failed, ret:%d\n",
-				__func__, ret);
-			return ret;
-		}
-	}
-	return 0;
-}
-
-static const struct of_device_id msm8996_asoc_machine_of_match[]  = {
-	{ .compatible = "qcom,msm8996-asoc-snd-tasha",
-	  .data = "tasha_codec"},
-	{},
-};
-
-static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
-{
-	struct snd_soc_card *card = NULL;
-	struct snd_soc_dai_link *dailink;
-	int len_1, len_2, len_3, len_4;
-	const struct of_device_id *match;
-
-	match = of_match_node(msm8996_asoc_machine_of_match, dev->of_node);
-	if (!match) {
-		dev_err(dev, "%s: No DT match found for sound card\n",
-			__func__);
-		return NULL;
-	}
-
-	if (!strcmp(match->data, "tasha_codec")) {
-		card = &snd_soc_card_tasha_msm8996;
-		len_1 = ARRAY_SIZE(msm8996_common_dai_links);
-		len_2 = len_1 + ARRAY_SIZE(msm8996_tasha_fe_dai_links);
-		len_3 = len_2 + ARRAY_SIZE(msm8996_common_be_dai_links);
-
-		memcpy(msm8996_tasha_dai_links,
-		       msm8996_common_dai_links,
-		       sizeof(msm8996_common_dai_links));
-		memcpy(msm8996_tasha_dai_links + len_1,
-		       msm8996_tasha_fe_dai_links,
-		       sizeof(msm8996_tasha_fe_dai_links));
-		memcpy(msm8996_tasha_dai_links + len_2,
-		       msm8996_common_be_dai_links,
-		       sizeof(msm8996_common_be_dai_links));
-		memcpy(msm8996_tasha_dai_links + len_3,
-		       msm8996_tasha_be_dai_links,
-		       sizeof(msm8996_tasha_be_dai_links));
-
-		dailink = msm8996_tasha_dai_links;
-		len_4 = len_3 + ARRAY_SIZE(msm8996_tasha_be_dai_links);
-	}
-
-	if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) {
-		dev_dbg(dev, "%s(): hdmi audio support present\n",
-				__func__);
-		memcpy(dailink + len_4, msm8996_hdmi_dai_link,
-			sizeof(msm8996_hdmi_dai_link));
-		len_4 += ARRAY_SIZE(msm8996_hdmi_dai_link);
-	} else {
-		dev_dbg(dev, "%s(): No hdmi audio support\n", __func__);
-	}
-
-	if (card) {
-		card->dai_link = dailink;
-		card->num_links = len_4;
-	}
-
-	return card;
-}
-
-static int msm8996_init_wsa_dev(struct platform_device *pdev,
-				struct snd_soc_card *card)
-{
-	struct device_node *wsa_of_node;
-	u32 wsa_max_devs;
-	u32 wsa_dev_cnt;
-	char *dev_name_str = NULL;
-	struct msm8996_wsa881x_dev_info *wsa881x_dev_info;
-	const char *wsa_auxdev_name_prefix[1];
-	int found = 0;
-	int i;
-	int ret;
-
-	/* Get maximum WSA device count for this platform */
-	ret = of_property_read_u32(pdev->dev.of_node,
-				   "qcom,wsa-max-devs", &wsa_max_devs);
-	if (ret) {
-		dev_dbg(&pdev->dev,
-			 "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
-			 __func__, pdev->dev.of_node->full_name, ret);
-		return 0;
-	}
-	if (wsa_max_devs == 0) {
-		dev_warn(&pdev->dev,
-			 "%s: Max WSA devices is 0 for this target?\n",
-			 __func__);
-		return 0;
-	}
-
-	/* Get count of WSA device phandles for this platform */
-	wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
-						 "qcom,wsa-devs", NULL);
-	if (wsa_dev_cnt == -ENOENT) {
-		dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n",
-			 __func__);
-		return 0;
-	} else if (wsa_dev_cnt <= 0) {
-		dev_err(&pdev->dev,
-			"%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n",
-			__func__, wsa_dev_cnt);
-		return -EINVAL;
-	}
-
-	/*
-	 * Expect total phandles count to be NOT less than maximum possible
-	 * WSA count. However, if it is less, then assign same value to
-	 * max count as well.
-	 */
-	if (wsa_dev_cnt < wsa_max_devs) {
-		dev_dbg(&pdev->dev,
-			"%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n",
-			__func__, wsa_max_devs, wsa_dev_cnt);
-		wsa_max_devs = wsa_dev_cnt;
-	}
-
-	/* Make sure prefix string passed for each WSA device */
-	ret = of_property_count_strings(pdev->dev.of_node,
-					"qcom,wsa-aux-dev-prefix");
-	if (ret != wsa_dev_cnt) {
-		dev_err(&pdev->dev,
-			"%s: expecting %d wsa prefix. Defined only %d in DT\n",
-			__func__, wsa_dev_cnt, ret);
-		return -EINVAL;
-	}
-
-	/*
-	 * Alloc mem to store phandle and index info of WSA device, if already
-	 * registered with ALSA core
-	 */
-	wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs,
-					sizeof(struct msm8996_wsa881x_dev_info),
-					GFP_KERNEL);
-	if (!wsa881x_dev_info)
-		return -ENOMEM;
-
-	/*
-	 * search and check whether all WSA devices are already
-	 * registered with ALSA core or not. If found a node, store
-	 * the node and the index in a local array of struct for later
-	 * use.
-	 */
-	for (i = 0; i < wsa_dev_cnt; i++) {
-		wsa_of_node = of_parse_phandle(pdev->dev.of_node,
-					    "qcom,wsa-devs", i);
-		if (unlikely(!wsa_of_node)) {
-			/* we should not be here */
-			dev_err(&pdev->dev,
-				"%s: wsa dev node is not present\n",
-				__func__);
-			return -EINVAL;
-		}
-		if (soc_find_component(wsa_of_node, NULL)) {
-			/* WSA device registered with ALSA core */
-			wsa881x_dev_info[found].of_node = wsa_of_node;
-			wsa881x_dev_info[found].index = i;
-			found++;
-			if (found == wsa_max_devs)
-				break;
-		}
-	}
-
-	if (found < wsa_max_devs) {
-		dev_dbg(&pdev->dev,
-			"%s: failed to find %d components. Found only %d\n",
-			__func__, wsa_max_devs, found);
-		return -EPROBE_DEFER;
-	}
-	dev_info(&pdev->dev,
-		"%s: found %d wsa881x devices registered with ALSA core\n",
-		__func__, found);
-
-	card->num_aux_devs = wsa_max_devs;
-	card->num_configs = wsa_max_devs;
-
-	/* Alloc array of AUX devs struct */
-	msm8996_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
-				       sizeof(struct snd_soc_aux_dev),
-				       GFP_KERNEL);
-	if (!msm8996_aux_dev)
-		return -ENOMEM;
-
-	/* Alloc array of codec conf struct */
-	msm8996_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs,
-					  sizeof(struct snd_soc_codec_conf),
-					  GFP_KERNEL);
-	if (!msm8996_codec_conf)
-		return -ENOMEM;
-
-	for (i = 0; i < card->num_aux_devs; i++) {
-		dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
-					    GFP_KERNEL);
-		if (!dev_name_str)
-			return -ENOMEM;
-
-		ret = of_property_read_string_index(pdev->dev.of_node,
-						    "qcom,wsa-aux-dev-prefix",
-						    wsa881x_dev_info[i].index,
-						    wsa_auxdev_name_prefix);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"%s: failed to read wsa aux dev prefix, ret = %d\n",
-				__func__, ret);
-			return -EINVAL;
-		}
-
-		snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i);
-		msm8996_aux_dev[i].name = dev_name_str;
-		msm8996_aux_dev[i].codec_name = NULL;
-		msm8996_aux_dev[i].codec_of_node =
-					wsa881x_dev_info[i].of_node;
-		msm8996_aux_dev[i].init = msm8996_wsa881x_init;
-		msm8996_codec_conf[i].dev_name = NULL;
-		msm8996_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0];
-		msm8996_codec_conf[i].of_node =
-					wsa881x_dev_info[i].of_node;
-	}
-	card->codec_conf = msm8996_codec_conf;
-	card->aux_dev = msm8996_aux_dev;
-
-	return 0;
-}
-
-static int msm8996_asoc_machine_probe(struct platform_device *pdev)
-{
-	struct snd_soc_card *card;
-	struct msm8996_asoc_mach_data *pdata;
-	const char *mbhc_audio_jack_type = NULL;
-	char *mclk_freq_prop_name;
-	const struct of_device_id *match;
-	int ret;
-
-	if (!pdev->dev.of_node) {
-		dev_err(&pdev->dev, "No platform supplied from device tree\n");
-		return -EINVAL;
-	}
-
-	pdata = devm_kzalloc(&pdev->dev,
-			sizeof(struct msm8996_asoc_mach_data), GFP_KERNEL);
-	if (!pdata)
-		return -ENOMEM;
-
-	card = populate_snd_card_dailinks(&pdev->dev);
-	if (!card) {
-		dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
-		ret = -EINVAL;
-		goto err;
-	}
-	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
-	snd_soc_card_set_drvdata(card, pdata);
-
-	ret = snd_soc_of_parse_card_name(card, "qcom,model");
-	if (ret) {
-		dev_err(&pdev->dev, "parse card name failed, err:%d\n",
-			ret);
-		goto err;
-	}
-
-	ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
-	if (ret) {
-		dev_err(&pdev->dev, "parse audio routing failed, err:%d\n",
-			ret);
-		goto err;
-	}
-
-	match = of_match_node(msm8996_asoc_machine_of_match,
-			pdev->dev.of_node);
-	if (!match) {
-		dev_err(&pdev->dev, "%s: no matched codec is found.\n",
-			__func__);
-		goto err;
-	}
-
-	mclk_freq_prop_name = "qcom,tasha-mclk-clk-freq";
-
-	ret = of_property_read_u32(pdev->dev.of_node,
-			mclk_freq_prop_name, &pdata->mclk_freq);
-	if (ret) {
-		dev_err(&pdev->dev,
-			"Looking up %s property in node %s failed, err%d\n",
-			mclk_freq_prop_name,
-			pdev->dev.of_node->full_name, ret);
-		goto err;
-	}
-
-	if (pdata->mclk_freq != CODEC_EXT_CLK_RATE) {
-		dev_err(&pdev->dev, "unsupported mclk freq %u\n",
-			pdata->mclk_freq);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	spdev = pdev;
-
-	ret = msm8996_populate_dai_link_component_of_node(card);
-	if (ret) {
-		ret = -EPROBE_DEFER;
-		goto err;
-	}
-
-	ret = msm8996_init_wsa_dev(pdev, card);
-	if (ret)
-		goto err;
-
-	pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
-						"qcom,hph-en1-gpio", 0);
-	if (pdata->hph_en1_gpio < 0) {
-		dev_dbg(&pdev->dev, "%s: %s property not found %d\n",
-			__func__, "qcom,hph-en1-gpio", pdata->hph_en1_gpio);
-	}
-
-	pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
-						"qcom,hph-en0-gpio", 0);
-	if (pdata->hph_en0_gpio < 0) {
-		dev_dbg(&pdev->dev, "%s: %s property not found %d\n",
-			__func__, "qcom,hph-en0-gpio", pdata->hph_en0_gpio);
-	}
-	ret = msm8996_prepare_hifi(card);
-	if (ret)
-		dev_dbg(&pdev->dev, "msm8996_prepare_hifi failed (%d)\n",
-			ret);
-
-	ret = snd_soc_register_card(card);
-	if (ret == -EPROBE_DEFER) {
-		if (codec_reg_done)
-			ret = -EINVAL;
-		goto err;
-	} else if (ret) {
-		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
-			ret);
-		goto err;
-	}
-	dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
-
-	ret = of_property_read_string(pdev->dev.of_node,
-		"qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
-	if (ret) {
-		dev_dbg(&pdev->dev, "Looking up %s property in node %s failed",
-			"qcom,mbhc-audio-jack-type",
-			pdev->dev.of_node->full_name);
-		dev_dbg(&pdev->dev, "Jack type properties set to default");
-	} else {
-		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack"))
-			dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
-		else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack"))
-			dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
-		else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack"))
-			dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
-		else
-			dev_dbg(&pdev->dev, "Unknown value, set to default");
-	}
-	/*
-	 * Parse US-Euro gpio info from DT. Report no error if us-euro
-	 * entry is not found in DT file as some targets do not support
-	 * US-Euro detection
-	 */
-	pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
-				"qcom,us-euro-gpios", 0);
-	if (pdata->us_euro_gpio < 0) {
-		dev_info(&pdev->dev, "property %s not detected in node %s",
-			"qcom,us-euro-gpios",
-			pdev->dev.of_node->full_name);
-	} else {
-		dev_dbg(&pdev->dev, "%s detected %d",
-			"qcom,us-euro-gpios", pdata->us_euro_gpio);
-		wcd_mbhc_cfg.swap_gnd_mic = msm8996_swap_gnd_mic;
-	}
-
-	ret = msm8996_prepare_us_euro(card);
-	if (ret)
-		dev_info(&pdev->dev, "msm8996_prepare_us_euro failed (%d)\n",
-			ret);
-	return 0;
-err:
-	if (pdata->us_euro_gpio > 0) {
-		dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n",
-			__func__, pdata->us_euro_gpio);
-		gpio_free(pdata->us_euro_gpio);
-		pdata->us_euro_gpio = 0;
-	}
-	if (pdata->hph_en1_gpio > 0) {
-		dev_dbg(&pdev->dev, "%s free hph_en1_gpio %d\n",
-			__func__, pdata->hph_en1_gpio);
-		gpio_free(pdata->hph_en1_gpio);
-		pdata->hph_en1_gpio = 0;
-	}
-	if (pdata->hph_en0_gpio > 0) {
-		dev_dbg(&pdev->dev, "%s free hph_en0_gpio %d\n",
-			__func__, pdata->hph_en0_gpio);
-		gpio_free(pdata->hph_en0_gpio);
-		pdata->hph_en0_gpio = 0;
-	}
-	devm_kfree(&pdev->dev, pdata);
-	return ret;
-}
-
-static int msm8996_asoc_machine_remove(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
-	struct msm8996_asoc_mach_data *pdata =
-				snd_soc_card_get_drvdata(card);
-
-	if (gpio_is_valid(ext_us_amp_gpio))
-		gpio_free(ext_us_amp_gpio);
-
-	gpio_free(pdata->us_euro_gpio);
-	gpio_free(pdata->hph_en1_gpio);
-	gpio_free(pdata->hph_en0_gpio);
-
-	if (msm8996_liquid_dock_dev != NULL) {
-		switch_dev_unregister(&msm8996_liquid_dock_dev->audio_sdev);
-
-		if (msm8996_liquid_dock_dev->dock_plug_irq)
-			free_irq(msm8996_liquid_dock_dev->dock_plug_irq,
-				 msm8996_liquid_dock_dev);
-
-		if (msm8996_liquid_dock_dev->dock_plug_gpio)
-			gpio_free(msm8996_liquid_dock_dev->dock_plug_gpio);
-
-		kfree(msm8996_liquid_dock_dev);
-		msm8996_liquid_dock_dev = NULL;
-	}
-	snd_soc_unregister_card(card);
-
-	return 0;
-}
-
-static struct platform_driver msm8996_asoc_machine_driver = {
-	.driver = {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
-		.pm = &snd_soc_pm_ops,
-		.of_match_table = msm8996_asoc_machine_of_match,
-	},
-	.probe = msm8996_asoc_machine_probe,
-	.remove = msm8996_asoc_machine_remove,
-};
-module_platform_driver(msm8996_asoc_machine_driver);
-
-MODULE_DESCRIPTION("ALSA SoC msm");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, msm8996_asoc_machine_of_match);
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 174db28..05b7d30 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -5036,12 +5036,13 @@
 		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
 	},
 	{
-		.name = MSM_DAILINK_NAME(Compress3),
-		.stream_name = "Compress3",
+		.name = MSM_DAILINK_NAME(MultiMedia10),
+		.stream_name = "MultiMedia10",
 		.cpu_dai_name = "MultiMedia10",
-		.platform_name = "msm-compress-dsp",
+		.platform_name = "msm-pcm-dsp.1",
 		.dynamic = 1,
 		.dpcm_playback = 1,
+		.dpcm_capture = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			 SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
index 9f08222..9b845ee 100644
--- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
@@ -154,7 +154,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"VIRT ENABLE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 				AUDPROC_MODULE_ID_VIRTUALIZER;
 				*updt_params++ =
@@ -182,7 +182,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"VIRT STRENGTH", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_VIRTUALIZER;
 				*updt_params++ =
@@ -210,7 +210,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"VIRT OUT_TYPE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_VIRTUALIZER;
 				*updt_params++ =
@@ -238,7 +238,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"VIRT GAIN_ADJUST", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 				AUDPROC_MODULE_ID_VIRTUALIZER;
 				*updt_params++ =
@@ -316,7 +316,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_ENABLE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -344,7 +344,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_MODE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -372,7 +372,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_PRESET", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -400,7 +400,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_WET_MIX", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -428,7 +428,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_GAIN_ADJUST", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -456,7 +456,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_ROOM_LEVEL", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -484,7 +484,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_ROOM_HF_LEVEL", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -512,7 +512,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_DECAY_TIME", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -540,7 +540,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_DECAY_HF_RATIO", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -568,7 +568,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_REFLECTIONS_LEVEL", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 				AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -596,7 +596,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_REFLECTIONS_DELAY", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 				AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -624,7 +624,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_LEVEL", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -652,7 +652,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_DELAY", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -680,7 +680,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_DIFFUSION", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -708,7 +708,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"REVERB_DENSITY", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_REVERB;
 				*updt_params++ =
@@ -787,7 +787,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"BASS_BOOST_ENABLE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_BASS_BOOST;
 				*updt_params++ =
@@ -815,7 +815,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"BASS_BOOST_MODE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_BASS_BOOST;
 				*updt_params++ =
@@ -843,7 +843,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"BASS_BOOST_STRENGTH", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_BASS_BOOST;
 				*updt_params++ =
@@ -920,7 +920,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"PBE_ENABLE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_PBE;
 				*updt_params++ =
@@ -946,7 +946,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"PBE_PARAM", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_PBE;
 				*updt_params++ =
@@ -1031,7 +1031,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"EQ_ENABLE", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
 				*updt_params++ =
@@ -1099,7 +1099,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"EQ_CONFIG", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
 				*updt_params++ =
@@ -1150,7 +1150,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"EQ_BAND_INDEX", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
 				*updt_params++ =
@@ -1182,7 +1182,7 @@
 						MAX_INBAND_PARAM_SZ,
 						"EQ_SINGLE_BAND_FREQ", rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				*updt_params++ =
 					AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
 				*updt_params++ =
@@ -1271,7 +1271,7 @@
 						"VOLUME/VOLUME2_GAIN_2CH",
 						rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				if (instance == SOFT_VOLUME_INSTANCE_2)
 					*updt_params++ =
 						ASM_MODULE_ID_VOL_CTRL2;
@@ -1320,7 +1320,7 @@
 						"VOLUME/VOLUME2_GAIN_MASTER",
 						rc);
 				if (rc != 0)
-					break;
+					goto invalid_config;
 				if (instance == SOFT_VOLUME_INSTANCE_2)
 					*updt_params++ =
 						ASM_MODULE_ID_VOL_CTRL2;
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 3a6cbe6..ef3475c 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -1682,7 +1682,7 @@
 			dev_err(rtd->dev,
 				"%s REG_SND_MODEL failed err %d\n",
 				__func__, err);
-		return err;
+		goto done;
 		}
 		break;
 	case SNDRV_LSM_SET_PARAMS: {
@@ -1852,13 +1852,15 @@
 			dev_err(rtd->dev,
 				"%s: Invalid params event_status_v3\n",
 				__func__);
-			return -EINVAL;
+			err = -EINVAL;
+			goto done;
 		}
 		if (copy_from_user(&userarg, arg, sizeof(userarg))) {
 			dev_err(rtd->dev,
 				"%s: err copyuser event_status_v3\n",
 				__func__);
-			return -EFAULT;
+			err = -EFAULT;
+			goto done;
 		}
 
 		if (userarg.payload_size >
@@ -1866,7 +1868,8 @@
 			pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
 				__func__, userarg.payload_size,
 				LISTEN_MAX_STATUS_PAYLOAD_SIZE);
-			return -EINVAL;
+			err = -EINVAL;
+			goto done;
 		}
 
 		size = sizeof(struct snd_lsm_event_status_v3) +
@@ -1876,7 +1879,8 @@
 			dev_err(rtd->dev,
 				"%s: Allocation failed event status size %d\n",
 				__func__, size);
-			return -EFAULT;
+			err = -EFAULT;
+			goto done;
 		}
 		user->payload_size = userarg.payload_size;
 		err = msm_lsm_ioctl_shared(substream, cmd, user);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index ef50d92..16f82ce 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -1093,7 +1093,7 @@
 		port_type = MSM_AFE_PORT_TYPE_RX;
 	} else if (stream_type == SNDRV_PCM_STREAM_CAPTURE) {
 		session_type = SESSION_TYPE_TX;
-		if (passthr_mode != LEGACY_PCM)
+		if ((passthr_mode != LEGACY_PCM) && (passthr_mode != LISTEN))
 			path_type = ADM_PATH_COMPRESSED_TX;
 		else
 			path_type = ADM_PATH_LIVE_REC;
@@ -3645,6 +3645,11 @@
 		msm_route_ec_ref_rx_enum[0],
 		msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
 
+static const struct snd_kcontrol_new ext_ec_ref_mux_ul10 =
+	SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL10 MUX Mux",
+		msm_route_ec_ref_rx_enum[0],
+		msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+
 static const struct snd_kcontrol_new ext_ec_ref_mux_ul17 =
 	SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL17 MUX Mux",
 		msm_route_ec_ref_rx_enum[0],
@@ -7251,6 +7256,59 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new mmul10_mixer_controls[] = {
+	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 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_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("TERT_TDM_TX_1", MSM_BACKEND_DAI_TERT_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("TERT_TDM_TX_2", MSM_BACKEND_DAI_TERT_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("TERT_TDM_TX_3", MSM_BACKEND_DAI_TERT_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_TX_0,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("USB_AUDIO_TX", MSM_BACKEND_DAI_USB_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
 static const struct snd_kcontrol_new mmul17_mixer_controls[] = {
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
@@ -11489,6 +11547,7 @@
 	SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL9", "MultiMedia9 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL10", "MultiMedia10 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL16", "MultiMedia16 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL17", "MultiMedia17 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL18", "MultiMedia18 Capture", 0, 0, 0, 0),
@@ -12225,6 +12284,8 @@
 	mmul8_mixer_controls, ARRAY_SIZE(mmul8_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia9 Mixer", SND_SOC_NOPM, 0, 0,
 	mmul9_mixer_controls, ARRAY_SIZE(mmul9_mixer_controls)),
+	SND_SOC_DAPM_MIXER("MultiMedia10 Mixer", SND_SOC_NOPM, 0, 0,
+	mmul10_mixer_controls, ARRAY_SIZE(mmul10_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia16 Mixer", SND_SOC_NOPM, 0, 0,
 	mmul16_mixer_controls, ARRAY_SIZE(mmul16_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia17 Mixer", SND_SOC_NOPM, 0, 0,
@@ -12557,6 +12618,8 @@
 		&ext_ec_ref_mux_ul8),
 	SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL9 MUX", SND_SOC_NOPM, 0, 0,
 		&ext_ec_ref_mux_ul9),
+	SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL10 MUX", SND_SOC_NOPM, 0, 0,
+		&ext_ec_ref_mux_ul10),
 	SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL16 MUX", SND_SOC_NOPM, 0, 0,
 		&ext_ec_ref_mux_ul16),
 	SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL17 MUX", SND_SOC_NOPM, 0, 0,
@@ -12810,9 +12873,11 @@
 	{"MultiMedia8 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
 	{"MultiMedia3 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia5 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"MultiMedia10 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia16 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia5 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
 	{"MultiMedia5 Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
+	{"MultiMedia10 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
 	{"MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
@@ -13379,6 +13444,7 @@
 	{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia3 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia5 Mixer", "MI2S_TX", "MI2S_TX"},
+	{"MultiMedia10 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia16 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
 	{"MultiMedia2 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
@@ -13395,17 +13461,21 @@
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"MultiMedia3 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
 	{"MultiMedia5 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+	{"MultiMedia10 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
 	{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
 	{"MultiMedia3 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
 	{"MultiMedia5 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
+	{"MultiMedia10 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
 	{"MultiMedia16 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
 	{"MultiMedia16 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
 	{"MultiMedia1 Mixer", "TERT_AUXPCM_UL_TX", "TERT_AUX_PCM_TX"},
 	{"MultiMedia3 Mixer", "TERT_AUX_PCM_TX", "TERT_AUX_PCM_TX"},
 	{"MultiMedia5 Mixer", "TERT_AUX_PCM_TX", "TERT_AUX_PCM_TX"},
+	{"MultiMedia10 Mixer", "TERT_AUX_PCM_TX", "TERT_AUX_PCM_TX"},
 	{"MultiMedia1 Mixer", "QUAT_AUXPCM_UL_TX", "QUAT_AUX_PCM_TX"},
 	{"MultiMedia3 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
 	{"MultiMedia5 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
+	{"MultiMedia10 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
 	{"MultiMedia16 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
 	{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia2 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
@@ -13418,13 +13488,16 @@
 	{"MultiMedia6 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
 	{"MultiMedia3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
 	{"MultiMedia5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+	{"MultiMedia10 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
 	{"MultiMedia6 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
 	{"MultiMedia3 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
 	{"MultiMedia5 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
+	{"MultiMedia10 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
 	{"MultiMedia16 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
 	{"MultiMedia6 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
 	{"MultiMedia3 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
 	{"MultiMedia5 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
+	{"MultiMedia10 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
 	{"MultiMedia16 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
 	{"MultiMedia6 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"MultiMedia6 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
@@ -13559,6 +13632,14 @@
 	{"MultiMedia9 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"},
 	{"MultiMedia9 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"},
 
+	{"MultiMedia10 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
+	{"MultiMedia10 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"},
+	{"MultiMedia10 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"},
+	{"MultiMedia10 Mixer", "TERT_TDM_TX_3", "TERT_TDM_TX_3"},
+	{"MultiMedia10 Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"},
+	{"MultiMedia10 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"},
+	{"MultiMedia10 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"},
+	{"MultiMedia10 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"},
 	{"MultiMedia20 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"MultiMedia20 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 	{"MultiMedia20 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
@@ -13586,6 +13667,7 @@
 	{"MultiMedia5 Mixer", "USB_AUDIO_TX", "USB_AUDIO_TX"},
 	{"MultiMedia6 Mixer", "USB_AUDIO_TX", "USB_AUDIO_TX"},
 	{"MultiMedia8 Mixer", "USB_AUDIO_TX", "USB_AUDIO_TX"},
+	{"MultiMedia10 Mixer", "USB_AUDIO_TX", "USB_AUDIO_TX"},
 
 	{"MultiMedia16 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"},
 	{"MultiMedia16 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"},
@@ -13682,6 +13764,7 @@
 	{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia3 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia4 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+	{"MultiMedia10 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia17 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia18 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia19 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -13701,6 +13784,7 @@
 	{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia3 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia4 Mixer", "AFE_PCM_TX", "PCM_TX"},
+	{"MultiMedia10 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia17 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia18 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia19 Mixer", "AFE_PCM_TX", "PCM_TX"},
@@ -13716,6 +13800,7 @@
 	{"MM_UL6", NULL, "MultiMedia6 Mixer"},
 	{"MM_UL8", NULL, "MultiMedia8 Mixer"},
 	{"MM_UL9", NULL, "MultiMedia9 Mixer"},
+	{"MM_UL10", NULL, "MultiMedia10 Mixer"},
 	{"MM_UL16", NULL, "MultiMedia16 Mixer"},
 	{"MM_UL17", NULL, "MultiMedia17 Mixer"},
 	{"MM_UL18", NULL, "MultiMedia18 Mixer"},
@@ -14104,6 +14189,16 @@
 	{"AUDIO_REF_EC_UL9 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
 	{"AUDIO_REF_EC_UL9 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
 
+	{"AUDIO_REF_EC_UL10 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+	{"AUDIO_REF_EC_UL10 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+	{"AUDIO_REF_EC_UL10 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+	{"AUDIO_REF_EC_UL10 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
+	{"AUDIO_REF_EC_UL10 MUX", "SLIM_1_TX", "SLIMBUS_1_TX"},
+	{"AUDIO_REF_EC_UL10 MUX", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"},
+	{"AUDIO_REF_EC_UL10 MUX", "QUAT_TDM_RX_0", "QUAT_TDM_RX_0"},
+	{"AUDIO_REF_EC_UL10 MUX", "QUAT_TDM_RX_1", "QUAT_TDM_RX_1"},
+	{"AUDIO_REF_EC_UL10 MUX", "QUAT_TDM_RX_2", "QUAT_TDM_RX_2"},
+	{"AUDIO_REF_EC_UL10 MUX", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"AUDIO_REF_EC_UL17 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"AUDIO_REF_EC_UL17 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 	{"AUDIO_REF_EC_UL17 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
@@ -14127,6 +14222,7 @@
 	{"MM_UL6", NULL, "AUDIO_REF_EC_UL6 MUX"},
 	{"MM_UL8", NULL, "AUDIO_REF_EC_UL8 MUX"},
 	{"MM_UL9", NULL, "AUDIO_REF_EC_UL9 MUX"},
+	{"MM_UL10", NULL, "AUDIO_REF_EC_UL10 MUX"},
 	{"MM_UL16", NULL, "AUDIO_REF_EC_UL16 MUX"},
 	{"MM_UL17", NULL, "AUDIO_REF_EC_UL17 MUX"},
 	{"MM_UL18", NULL, "AUDIO_REF_EC_UL18 MUX"},
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 1590605..46bc540 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -2388,7 +2388,8 @@
 	struct adm_cmd_device_open_v5	open;
 	struct adm_cmd_device_open_v6	open_v6;
 	int ret = 0;
-	int port_idx, copp_idx, flags;
+	int port_idx, flags;
+	int copp_idx = -1;
 	int tmp_port = q6audio_get_port_id(port_id);
 
 	pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
@@ -2442,8 +2443,17 @@
 	    (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY))
 		rate = 16000;
 
-	copp_idx = adm_get_idx_if_copp_exists(port_idx, topology, perf_mode,
-						rate, bit_width, app_type);
+	/*
+	 * Routing driver reuses the same adm for streams with the same
+	 * app_type, sample_rate etc.
+	 * This isn't allowed for ULL streams as per the DSP interface
+	 */
+	if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE)
+		copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
+						      perf_mode,
+						      rate, bit_width,
+						      app_type);
+
 	if (copp_idx < 0) {
 		copp_idx = adm_get_next_available_copp(port_idx);
 		if (copp_idx >= MAX_COPPS_PER_PORT) {
diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c
index 3aaaa35..4c3a3a1 100644
--- a/sound/soc/msm/qdsp6v2/q6core.c
+++ b/sound/soc/msm/qdsp6v2/q6core.c
@@ -21,6 +21,8 @@
 #include <linux/qdsp6v2/apr.h>
 #include <sound/q6core.h>
 #include <sound/audio_cal_utils.h>
+#include <sound/adsp_err.h>
+#include <sound/apr_audio-v2.h>
 
 #define TIMEOUT_MS 1000
 /*
@@ -36,16 +38,30 @@
 	CORE_MAX_CAL
 };
 
+enum ver_query_status {
+	VER_QUERY_UNATTEMPTED,
+	VER_QUERY_UNSUPPORTED,
+	VER_QUERY_SUPPORTED
+};
+
+struct q6core_avcs_ver_info {
+	enum ver_query_status status;
+	struct avcs_fwk_ver_info ver_info;
+};
+
 struct q6core_str {
 	struct apr_svc *core_handle_q;
 	wait_queue_head_t bus_bw_req_wait;
 	wait_queue_head_t cmd_req_wait;
+	wait_queue_head_t avcs_fwk_ver_req_wait;
 	u32 bus_bw_resp_received;
 	enum cmd_flags {
 		FLAG_NONE,
 		FLAG_CMDRSP_LICENSE_RESULT
 	} cmd_resp_received_flag;
+	u32 avcs_fwk_ver_resp_received;
 	struct mutex cmd_lock;
+	struct mutex ver_lock;
 	union {
 		struct avcs_cmdrsp_get_license_validation_result
 						cmdrsp_license_result;
@@ -54,6 +70,7 @@
 	struct cal_type_data *cal_data[CORE_MAX_CAL];
 	uint32_t mem_map_cal_handle;
 	int32_t adsp_status;
+	struct q6core_avcs_ver_info q6core_avcs_ver_info;
 };
 
 static struct q6core_str q6core_lcl;
@@ -65,9 +82,61 @@
 };
 static struct generic_get_data_ *generic_get_data;
 
+static int parse_fwk_version_info(uint32_t *payload)
+{
+	size_t fwk_ver_size;
+	size_t svc_size;
+	int num_services;
+	int ret = 0;
+
+	pr_debug("%s: Payload info num services %d\n",
+		 __func__, payload[4]);
+	/*
+	 * payload1[4] is the number of services running on DSP
+	 * Based on this info, we copy the payload into core
+	 * avcs version info structure.
+	 */
+	num_services = payload[4];
+	q6core_lcl.q6core_avcs_ver_info.ver_info.avcs_fwk_version.
+			num_services = num_services;
+	if (num_services > VSS_MAX_AVCS_NUM_SERVICES) {
+		pr_err("%s: num_services: %d greater than max services: %d\n",
+		       __func__, num_services, VSS_MAX_AVCS_NUM_SERVICES);
+		ret = -EINVAL;
+		goto done;
+	}
+	fwk_ver_size = sizeof(struct avcs_get_fwk_version);
+	svc_size = num_services * sizeof(struct avs_svc_api_info);
+	/*
+	 * Dynamically allocate memory for all
+	 * the services based on num_services
+	 */
+	q6core_lcl.q6core_avcs_ver_info.ver_info.services = NULL;
+	q6core_lcl.q6core_avcs_ver_info.ver_info.services =
+				kzalloc(svc_size, GFP_ATOMIC);
+	if (q6core_lcl.q6core_avcs_ver_info.ver_info.services == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	/*
+	 * memcpy is done twice because the memory allocated for
+	 * q6core_lcl.q6core_avcs_ver_info.ver_info is not
+	 * contiguous.
+	 */
+	memcpy(&q6core_lcl.q6core_avcs_ver_info.ver_info,
+	       (uint8_t *)payload, fwk_ver_size);
+	memcpy(q6core_lcl.q6core_avcs_ver_info.ver_info.services,
+	       (uint8_t *)&payload[sizeof(struct avcs_get_fwk_version)/
+				   sizeof(uint32_t)], svc_size);
+	ret = 0;
+done:
+	return ret;
+}
+
 static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
 {
 	uint32_t *payload1;
+	int ret = 0;
 
 	if (data == NULL) {
 		pr_err("%s: data argument is null\n", __func__);
@@ -118,6 +187,17 @@
 			q6core_lcl.bus_bw_resp_received = 1;
 			wake_up(&q6core_lcl.bus_bw_req_wait);
 			break;
+		case AVCS_CMD_GET_FWK_VERSION:
+			pr_debug("%s: Cmd = AVCS_CMD_GET_FWK_VERSION status[%s]\n",
+				__func__, adsp_err_get_err_str(payload1[1]));
+			/* ADSP status to match Linux error standard */
+			q6core_lcl.adsp_status = -payload1[1];
+			if (payload1[1] == ADSP_EUNSUPPORTED)
+				q6core_lcl.q6core_avcs_ver_info.status =
+					VER_QUERY_UNSUPPORTED;
+			q6core_lcl.avcs_fwk_ver_resp_received = 1;
+			wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
+			break;
 		default:
 			pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n",
 					__func__,
@@ -130,7 +210,7 @@
 	case RESET_EVENTS:{
 		pr_debug("%s: Reset event received in Core service\n",
 			__func__);
-		apr_reset(q6core_lcl.core_handle_q);
+		/* no reset done as the data will not change after SSR*/
 		q6core_lcl.core_handle_q = NULL;
 		break;
 	}
@@ -161,6 +241,18 @@
 		q6core_lcl.cmd_resp_received_flag = FLAG_CMDRSP_LICENSE_RESULT;
 		wake_up(&q6core_lcl.cmd_req_wait);
 		break;
+	case AVCS_CMDRSP_GET_FWK_VERSION:
+		pr_debug("%s: Received AVCS_CMDRSP_GET_FWK_VERSION\n",
+			 __func__);
+		payload1 = data->payload;
+		q6core_lcl.q6core_avcs_ver_info.status = VER_QUERY_SUPPORTED;
+		q6core_lcl.avcs_fwk_ver_resp_received = 1;
+		ret = parse_fwk_version_info(payload1);
+		if (ret < 0)
+			pr_err("%s: Failed to parse payload:%d\n",
+			       __func__, ret);
+		wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
+		break;
 	default:
 		pr_err("%s: Message id from adsp core svc: 0x%x\n",
 			__func__, data->opcode);
@@ -217,6 +309,157 @@
 	return NULL;
 }
 
+static int q6core_send_get_avcs_fwk_ver_cmd(void)
+{
+	struct apr_hdr avcs_ver_cmd;
+	int ret;
+
+	avcs_ver_cmd.hdr_field =
+		APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
+			      APR_PKT_VER);
+	avcs_ver_cmd.pkt_size = sizeof(struct apr_hdr);
+	avcs_ver_cmd.src_port = 0;
+	avcs_ver_cmd.dest_port = 0;
+	avcs_ver_cmd.token = 0;
+	avcs_ver_cmd.opcode = AVCS_CMD_GET_FWK_VERSION;
+
+	q6core_lcl.adsp_status = 0;
+	q6core_lcl.avcs_fwk_ver_resp_received = 0;
+
+	ret = apr_send_pkt(q6core_lcl.core_handle_q,
+			   (uint32_t *) &avcs_ver_cmd);
+	if (ret < 0) {
+		pr_err("%s: failed to send apr packet, ret=%d\n", __func__,
+		       ret);
+		goto done;
+	}
+
+	ret = wait_event_timeout(q6core_lcl.avcs_fwk_ver_req_wait,
+				 (q6core_lcl.avcs_fwk_ver_resp_received == 1),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout for AVCS fwk version info\n",
+		       __func__);
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+
+	if (q6core_lcl.adsp_status < 0) {
+		/*
+		 * adsp_err_get_err_str expects a positive value but we store
+		 * the DSP error as negative to match the Linux error standard.
+		 * Pass in the negated value so adsp_err_get_err_str returns
+		 * the correct string.
+		 */
+		pr_err("%s: DSP returned error[%s]\n", __func__,
+		       adsp_err_get_err_str(-q6core_lcl.adsp_status));
+		ret = adsp_err_get_lnx_err_code(q6core_lcl.adsp_status);
+		goto done;
+	}
+
+	ret = 0;
+
+done:
+	return ret;
+}
+
+int q6core_get_service_version(uint32_t service_id,
+			       struct avcs_fwk_ver_info *ver_info,
+			       size_t size)
+{
+	int i;
+	uint32_t num_services;
+	size_t svc_size;
+
+	svc_size = q6core_get_avcs_service_size(service_id);
+	if (svc_size != size) {
+		pr_err("%s: Expected size: %ld, Provided size: %ld",
+		       __func__, svc_size, size);
+		return -EINVAL;
+	}
+
+	num_services =
+		q6core_lcl.q6core_avcs_ver_info.ver_info.
+		avcs_fwk_version.num_services;
+
+	if (ver_info == NULL) {
+		pr_err("%s: NULL parameter ver_info\n", __func__);
+		return -EINVAL;
+	}
+
+	memcpy(ver_info, &q6core_lcl.q6core_avcs_ver_info.
+	       ver_info.avcs_fwk_version, sizeof(struct avcs_get_fwk_version));
+
+	if (service_id == AVCS_SERVICE_ID_ALL) {
+		memcpy(&ver_info->services[0], &q6core_lcl.
+		       q6core_avcs_ver_info.ver_info.services[0],
+		       (num_services * sizeof(struct avs_svc_api_info)));
+	} else {
+		for (i = 0; i < num_services; i++) {
+			if (q6core_lcl.q6core_avcs_ver_info.
+			    ver_info.services[i].service_id == service_id) {
+				memcpy(&ver_info->services[0],
+				       &q6core_lcl.q6core_avcs_ver_info.
+				       ver_info.services[i], size);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(q6core_get_service_version);
+
+size_t q6core_get_avcs_service_size(uint32_t service_id)
+{
+	int ret = 0;
+	uint32_t num_services;
+
+	num_services =
+		q6core_lcl.q6core_avcs_ver_info.ver_info.
+		avcs_fwk_version.num_services;
+
+	mutex_lock(&(q6core_lcl.ver_lock));
+	pr_debug("%s: q6core_avcs_ver_info.status(%d)\n", __func__,
+		 q6core_lcl.q6core_avcs_ver_info.status);
+
+	switch (q6core_lcl.q6core_avcs_ver_info.status) {
+	case VER_QUERY_SUPPORTED:
+		pr_debug("%s: AVCS FWK version query already attempted\n",
+			 __func__);
+		ret = num_services * sizeof(struct avs_svc_api_info);
+		break;
+	case VER_QUERY_UNSUPPORTED:
+		ret = -EOPNOTSUPP;
+		break;
+	case VER_QUERY_UNATTEMPTED:
+		pr_debug("%s: Attempting AVCS FWK version query\n", __func__);
+		if (q6core_is_adsp_ready()) {
+			ret = q6core_send_get_avcs_fwk_ver_cmd();
+			if (ret == 0)
+				ret = num_services *
+				      sizeof(struct avs_svc_api_info);
+		} else {
+			pr_err("%s: ADSP is not ready to query version\n",
+			       __func__);
+			ret = -ENODEV;
+		}
+		break;
+	default:
+		pr_err("%s: Invalid version query status %d\n", __func__,
+		       q6core_lcl.q6core_avcs_ver_info.status);
+		ret = -EINVAL;
+		break;
+	}
+	mutex_unlock(&(q6core_lcl.ver_lock));
+
+	if (service_id != AVCS_SERVICE_ID_ALL)
+		return sizeof(struct avs_svc_api_info);
+
+	return ret;
+}
+EXPORT_SYMBOL(q6core_get_avcs_service_size);
+
 int32_t core_set_license(uint32_t key, uint32_t module_id)
 {
 	struct avcs_cmd_set_license *cmd_setl = NULL;
@@ -827,18 +1070,16 @@
 
 static int __init core_init(void)
 {
+	memset(&q6core_lcl, 0, sizeof(struct q6core_str));
 	init_waitqueue_head(&q6core_lcl.bus_bw_req_wait);
-	q6core_lcl.bus_bw_resp_received = 0;
-
-	q6core_lcl.core_handle_q = NULL;
-
 	init_waitqueue_head(&q6core_lcl.cmd_req_wait);
+	init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait);
 	q6core_lcl.cmd_resp_received_flag = FLAG_NONE;
 	mutex_init(&q6core_lcl.cmd_lock);
-	q6core_lcl.mem_map_cal_handle = 0;
-	q6core_lcl.adsp_status = 0;
+	mutex_init(&q6core_lcl.ver_lock);
 
 	q6core_init_cal_data();
+
 	return 0;
 }
 module_init(core_init);
@@ -846,6 +1087,7 @@
 static void __exit core_exit(void)
 {
 	mutex_destroy(&q6core_lcl.cmd_lock);
+	mutex_destroy(&q6core_lcl.ver_lock);
 	q6core_delete_cal_data();
 }
 module_exit(core_exit);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 15c9e13..0d444d0 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -21,6 +21,7 @@
 #include <soc/qcom/socinfo.h>
 #include <linux/qdsp6v2/apr_tal.h>
 
+#include "sound/q6core.h"
 #include "sound/q6audio-v2.h"
 #include "sound/apr_audio-v2.h"
 #include "sound/q6afe-v2.h"
@@ -33,6 +34,9 @@
 
 #define CMD_STATUS_SUCCESS 0
 #define CMD_STATUS_FAIL 1
+#define NUM_CHANNELS_MONO 1
+#define NUM_CHANNELS_STEREO 2
+#define CVP_VERSION_2 2
 
 enum {
 	VOC_TOKEN_NONE,
@@ -83,6 +87,11 @@
 static int voice_send_cvp_media_format_cmd(struct voice_data *v,
 					   uint32_t param_type);
 static int voice_send_cvp_topology_commit_cmd(struct voice_data *v);
+static int voice_send_cvp_channel_info_cmd(struct voice_data *v);
+static int voice_send_cvp_channel_info_v2(struct voice_data *v,
+					  uint32_t param_type);
+static int voice_get_avcs_version_per_service(uint32_t service_id);
+
 
 static int voice_cvs_stop_playback(struct voice_data *v);
 static int voice_cvs_start_playback(struct voice_data *v);
@@ -3793,6 +3802,295 @@
 	return result;
 }
 
+static int voice_send_cvp_channel_info_v2(struct voice_data *v,
+					  uint32_t param_type)
+{
+	int ret;
+	struct cvp_set_channel_info_cmd_v2 cvp_set_channel_info_cmd;
+	void *apr_cvp;
+	u16 cvp_handle;
+	struct vss_icommon_param_data_channel_info_v2_t
+		*channel_info_param_data =
+			&cvp_set_channel_info_cmd.
+			cvp_set_ch_info_param_v2.param_data;
+	struct vss_param_vocproc_dev_channel_info_t *channel_info =
+			&channel_info_param_data->channel_info;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	apr_cvp = common.apr_q6_cvp;
+	if (!apr_cvp) {
+		pr_err("%s: apr_cvp is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cvp_handle = voice_get_cvp_handle(v);
+	memset(&cvp_set_channel_info_cmd, 0, sizeof(cvp_set_channel_info_cmd));
+
+	cvp_set_channel_info_cmd.hdr.hdr_field =
+		APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
+			      APR_PKT_VER);
+	cvp_set_channel_info_cmd.hdr.pkt_size =
+		APR_PKT_SIZE(APR_HDR_SIZE,
+		sizeof(cvp_set_channel_info_cmd) - APR_HDR_SIZE);
+	cvp_set_channel_info_cmd.hdr.src_svc = 0;
+	cvp_set_channel_info_cmd.hdr.src_domain = APR_DOMAIN_APPS;
+	cvp_set_channel_info_cmd.hdr.src_port =
+		voice_get_idx_for_session(v->session_id);
+	cvp_set_channel_info_cmd.hdr.dest_svc = 0;
+	cvp_set_channel_info_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+	cvp_set_channel_info_cmd.hdr.dest_port = cvp_handle;
+	cvp_set_channel_info_cmd.hdr.token = 0;
+	cvp_set_channel_info_cmd.hdr.opcode =  VSS_ICOMMON_CMD_SET_PARAM_V2;
+
+	cvp_set_channel_info_cmd.cvp_set_ch_info_param_v2.mem_size =
+			sizeof(struct vss_icommon_param_data_channel_info_v2_t);
+
+	channel_info_param_data->module_id = VSS_MODULE_CVD_GENERIC;
+	channel_info_param_data->param_size =
+		sizeof(struct vss_param_vocproc_dev_channel_info_t);
+
+	 /* Device specific data */
+	switch (param_type) {
+	case RX_PATH:
+		channel_info_param_data->param_id =
+			VSS_PARAM_VOCPROC_RX_CHANNEL_INFO;
+		channel_info->num_channels = v->dev_rx.no_of_channels;
+		channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
+		break;
+
+	case TX_PATH:
+		channel_info_param_data->param_id =
+			VSS_PARAM_VOCPROC_TX_CHANNEL_INFO;
+		channel_info->num_channels = v->dev_tx.no_of_channels;
+		channel_info->bits_per_sample = v->dev_tx.bits_per_sample;
+		break;
+
+	case EC_REF_PATH:
+		channel_info_param_data->param_id =
+			VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO;
+		channel_info->num_channels = v->dev_rx.no_of_channels;
+		channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
+		break;
+	default:
+		pr_err("%s: Invalid param type\n",
+		       __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (channel_info->num_channels == NUM_CHANNELS_MONO) {
+		channel_info->channel_mapping[0] = PCM_CHANNEL_FC;
+	} else if (channel_info->num_channels == NUM_CHANNELS_STEREO) {
+		channel_info->channel_mapping[0] = PCM_CHANNEL_FL;
+		channel_info->channel_mapping[1] = PCM_CHANNEL_FR;
+	} else {
+		pr_err("%s: Unsupported num channels: %d\n",
+		       __func__, channel_info->num_channels);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	v->cvp_state = CMD_STATUS_FAIL;
+	v->async_err = 0;
+	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_channel_info_cmd);
+	if (ret < 0) {
+		pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2\n",
+		       __func__);
+		goto done;
+	}
+
+	ret = wait_event_timeout(v->cvp_wait,
+				(v->cvp_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+
+	if (v->async_err > 0) {
+		pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
+		       adsp_err_get_err_str(v->async_err), cvp_handle);
+		ret = adsp_err_get_lnx_err_code(v->async_err);
+		goto done;
+	}
+	ret = 0;
+done:
+	return ret;
+}
+
+static int voice_send_cvp_channel_info_cmd(struct voice_data *v)
+{
+	int ret = 0;
+
+	ret = voice_send_cvp_channel_info_v2(v, RX_PATH);
+	if (ret < 0) {
+		pr_err("%s: Error in sending cvp_channel_info RX: %d\n",
+		       __func__, ret);
+		goto done;
+	}
+
+	ret = voice_send_cvp_channel_info_v2(v, TX_PATH);
+	if (ret < 0) {
+		pr_err("%s: Error in sending cvp_channel_info TX: %d\n",
+		       __func__, ret);
+		goto done;
+	}
+
+	ret = voice_send_cvp_channel_info_v2(v, EC_REF_PATH);
+	if (ret < 0) {
+		pr_err("%s: Error in sending cvp_channel_info EC Ref: %d\n",
+		       __func__, ret);
+		goto done;
+	}
+done:
+	return ret;
+}
+
+static int voice_send_cvp_mfc_config_v2(struct voice_data *v)
+{
+	int ret;
+	struct cvp_set_mfc_config_cmd_v2 cvp_set_mfc_config_cmd;
+	void *apr_cvp;
+	u16 cvp_handle;
+	struct vss_icommon_param_data_mfc_config_v2_t *cvp_config_param_data =
+		&cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.param_data;
+	struct vss_param_mfc_config_info_t *mfc_config_info =
+		&cvp_config_param_data->mfc_config_info;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	apr_cvp  = common.apr_q6_cvp;
+	if (!apr_cvp) {
+		pr_err("%s: apr_cvp is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cvp_handle = voice_get_cvp_handle(v);
+	memset(&cvp_set_mfc_config_cmd, 0, sizeof(cvp_set_mfc_config_cmd));
+
+	cvp_set_mfc_config_cmd.hdr.hdr_field =
+		APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
+			      APR_PKT_VER);
+	cvp_set_mfc_config_cmd.hdr.pkt_size =
+		APR_PKT_SIZE(APR_HDR_SIZE,
+		sizeof(cvp_set_mfc_config_cmd) - APR_HDR_SIZE);
+	cvp_set_mfc_config_cmd.hdr.src_svc = 0;
+	cvp_set_mfc_config_cmd.hdr.src_domain = APR_DOMAIN_APPS;
+	cvp_set_mfc_config_cmd.hdr.src_port =
+		voice_get_idx_for_session(v->session_id);
+	cvp_set_mfc_config_cmd.hdr.dest_svc = 0;
+	cvp_set_mfc_config_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+	cvp_set_mfc_config_cmd.hdr.dest_port = cvp_handle;
+	cvp_set_mfc_config_cmd.hdr.token = 0;
+	cvp_set_mfc_config_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
+	cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.mem_size =
+		sizeof(struct vss_icommon_param_data_mfc_config_v2_t);
+
+	cvp_config_param_data->module_id = AUDPROC_MODULE_ID_MFC;
+	cvp_config_param_data->param_id =
+		AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
+	cvp_config_param_data->param_size =
+		sizeof(struct vss_param_mfc_config_info_t);
+
+	mfc_config_info->num_channels = v->dev_rx.no_of_channels;
+	mfc_config_info->bits_per_sample = 16;
+	mfc_config_info->sample_rate = v->dev_rx.sample_rate;
+
+	if (mfc_config_info->num_channels == NUM_CHANNELS_MONO) {
+		mfc_config_info->channel_type[0] = PCM_CHANNEL_FC;
+	} else if (mfc_config_info->num_channels == NUM_CHANNELS_STEREO) {
+		mfc_config_info->channel_type[0] = PCM_CHANNEL_FL;
+		mfc_config_info->channel_type[1] = PCM_CHANNEL_FR;
+	} else {
+		pr_err("%s: Unsupported num channels: %d\n",
+		       __func__, mfc_config_info->num_channels);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	v->cvp_state = CMD_STATUS_FAIL;
+	v->async_err = 0;
+	ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_mfc_config_cmd);
+	if (ret < 0) {
+		pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
+		       __func__, ret);
+		goto done;
+	}
+	ret = wait_event_timeout(v->cvp_wait,
+				(v->cvp_state == CMD_STATUS_SUCCESS),
+				msecs_to_jiffies(TIMEOUT_MS));
+
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+
+	if (v->async_err > 0) {
+		pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
+		       adsp_err_get_err_str(v->async_err), cvp_handle);
+		ret = adsp_err_get_lnx_err_code(v->async_err);
+		goto done;
+	}
+	ret = 0;
+done:
+	return ret;
+}
+
+static int voice_send_cvp_mfc_config_cmd(struct voice_data *v)
+{
+	int ret = 0;
+
+	if (common.cvp_version >= CVP_VERSION_2) {
+		ret = voice_send_cvp_mfc_config_v2(v);
+	} else {
+		pr_warn("%s: CVP Version not supported\n", __func__);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int voice_get_avcs_version_per_service(uint32_t service_id)
+{
+	int ret = 0;
+	size_t svc_size;
+	struct avcs_fwk_ver_info ver_info = {{0}, NULL};
+
+	if (service_id == AVCS_SERVICE_ID_ALL) {
+		pr_err("%s: Invalid service id: %d", __func__,
+		       AVCS_SERVICE_ID_ALL);
+		return -EINVAL;
+	}
+
+	svc_size = sizeof(struct avs_svc_api_info);
+	ver_info.services = kzalloc(svc_size, GFP_KERNEL);
+	if (ver_info.services == NULL)
+		return -ENOMEM;
+
+	ret = q6core_get_service_version(service_id, &ver_info, svc_size);
+	if (ret < 0)
+		goto done;
+
+	ret = ver_info.services[0].api_version;
+	common.is_avcs_version_queried = true;
+done:
+	kfree(ver_info.services);
+	return ret;
+}
+
 static int voice_setup_vocproc(struct voice_data *v)
 {
 	int ret = 0;
@@ -3803,6 +4101,18 @@
 		goto fail;
 	}
 
+	if (common.is_avcs_version_queried == false)
+		common.cvp_version = voice_get_avcs_version_per_service(
+				     APRV2_IDS_SERVICE_ID_ADSP_CVP_V);
+
+	if (common.cvp_version < 0) {
+		pr_err("%s: Invalid CVP version %d\n",
+		       __func__, common.cvp_version);
+		ret = -EINVAL;
+		goto fail;
+	}
+	pr_debug("%s: CVP Version %d\n", __func__, common.cvp_version);
+
 	ret = voice_send_cvp_media_fmt_info_cmd(v);
 	if (ret < 0) {
 		pr_err("%s: Set media format info failed err:%d\n", __func__,
@@ -3817,6 +4127,15 @@
 		goto fail;
 	}
 
+	/* Send MFC config only when the no of channels are more than 1 */
+	if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
+		ret = voice_send_cvp_mfc_config_cmd(v);
+		if (ret < 0) {
+			pr_warn("%s: Set mfc config failed err:%d\n",
+				__func__, ret);
+		}
+	}
+
 	voice_send_cvs_register_cal_cmd(v);
 	voice_send_cvp_register_dev_cfg_cmd(v);
 	voice_send_cvp_register_cal_cmd(v);
@@ -3962,11 +4281,18 @@
 
 static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v)
 {
-	int ret;
+	int ret = 0;
 
-	ret = voice_send_cvp_device_channels_cmd(v);
-	if (ret < 0)
+	if (common.cvp_version < CVP_VERSION_2)
+		ret = voice_send_cvp_device_channels_cmd(v);
+	else
+		ret = voice_send_cvp_channel_info_cmd(v);
+
+	if (ret < 0) {
+		pr_err("%s: Set channel info failed err: %d\n", __func__,
+		       ret);
 		goto done;
+	}
 
 	if (voice_get_cvd_int_version(common.cvd_version) >=
 	    CVD_INT_VERSION_2_3) {
@@ -3994,7 +4320,7 @@
 	void *apr_cvp;
 	u16 cvp_handle;
 	struct vss_icommon_param_data_t *media_fmt_param_data =
-		&cvp_set_media_format_cmd.cvp_set_param_v2.param_data;
+		&cvp_set_media_format_cmd.cvp_set_media_param_v2.param_data;
 	struct vss_param_endpoint_media_format_info_t *media_fmt_info =
 		&media_fmt_param_data->media_format_info;
 
@@ -4032,7 +4358,7 @@
 	cvp_set_media_format_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
 
 	/* Fill param data */
-	cvp_set_media_format_cmd.cvp_set_param_v2.mem_size =
+	cvp_set_media_format_cmd.cvp_set_media_param_v2.mem_size =
 		sizeof(struct vss_icommon_param_data_t);
 	media_fmt_param_data->module_id = VSS_MODULE_CVD_GENERIC;
 	media_fmt_param_data->param_size =
@@ -6197,6 +6523,15 @@
 			goto done;
 		}
 
+		/* Send MFC config only when the no of channels are > 1 */
+		if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
+			ret = voice_send_cvp_mfc_config_cmd(v);
+			if (ret < 0) {
+				pr_warn("%s: Set mfc config failed err: %d\n",
+					__func__, ret);
+			}
+		}
+
 		voice_send_cvp_register_dev_cfg_cmd(v);
 		voice_send_cvp_register_cal_cmd(v);
 		voice_send_cvp_register_vol_cal_cmd(v);
@@ -7054,7 +7389,8 @@
 			case VSS_ICOMMON_CMD_SET_PARAM_V2:
 				switch (data->token) {
 				case VOC_SET_MEDIA_FORMAT_PARAM_TOKEN:
-					pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by voice_send_cvp_media_format_cmd\n",
+				case VOC_GENERIC_SET_PARAM_TOKEN:
+					pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called\n",
 						__func__);
 					v->cvp_state = CMD_STATUS_SUCCESS;
 					v->async_err = ptr[1];
@@ -8566,7 +8902,8 @@
 	common.default_vol_step_val = 0;
 	common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
 	common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
-
+	common.cvp_version = 0;
+	common.is_avcs_version_queried = false;
 	/* Initialize EC Ref media format info */
 	common.ec_ref_ext = false;
 	common.ec_media_fmt_info.port_id = AFE_PORT_INVALID;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 74d80be..db48091 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -124,7 +124,7 @@
 };
 
 enum {
-	VOC_NO_SET_PARAM_TOKEN = 0,
+	VOC_GENERIC_SET_PARAM_TOKEN = 0,
 	VOC_RTAC_SET_PARAM_TOKEN,
 	VOC_SET_MEDIA_FORMAT_PARAM_TOKEN,
 	VOC_SET_PARAM_TOKEN_MAX
@@ -239,6 +239,19 @@
 	uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX];
 } __packed;
 
+struct vss_param_vocproc_dev_channel_info_t {
+	uint32_t num_channels;
+	uint32_t bits_per_sample;
+	uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX];
+} __packed;
+
+struct vss_param_mfc_config_info_t {
+	uint32_t sample_rate;
+	uint16_t bits_per_sample;
+	uint16_t num_channels;
+	uint16_t channel_type[VSS_NUM_CHANNELS_MAX];
+} __packed;
+
 struct vss_icommon_param_data_t {
 	/* Valid ID of the module. */
 	uint32_t module_id;
@@ -260,6 +273,88 @@
 	};
 } __packed;
 
+struct vss_icommon_param_data_channel_info_v2_t {
+	/* Valid ID of the module. */
+	uint32_t module_id;
+	/* Valid ID of the parameter. */
+	uint32_t param_id;
+	/*
+	 * Data size of the structure relating to the param_id/module_id
+	 * combination in uint8_t bytes.
+	 */
+	uint16_t param_size;
+	/* This field must be set to zero. */
+	uint16_t reserved;
+	struct vss_param_vocproc_dev_channel_info_t channel_info;
+} __packed;
+
+struct vss_icommon_cmd_set_param_channel_info_v2_t {
+	/*
+	 * Pointer to the unique identifier for an address (physical/virtual).
+	 *
+	 * If the parameter data payload is within the message payload
+	 * (in-band), set this field to 0. The parameter data begins at the
+	 * specified data payload address.
+	 *
+	 * If the parameter data is out-of-band, this field is the handle to
+	 * the physical address in the shared memory that holds the parameter
+	 * data.
+	 */
+	uint32_t mem_handle;
+	/*
+	 * Location of the parameter data payload.
+	 *
+	 * The payload is an array of vss_icommon_param_data_t. If the
+	 * mem_handle is 0, this field is ignored.
+	 */
+	uint64_t mem_address;
+	/* Size of the parameter data payload in bytes. */
+	uint32_t mem_size;
+	struct vss_icommon_param_data_channel_info_v2_t param_data;
+} __packed;
+
+struct vss_icommon_param_data_mfc_config_v2_t {
+	/* Valid ID of the module. */
+	uint32_t module_id;
+	/* Valid ID of the parameter. */
+	uint32_t param_id;
+	/*
+	 * Data size of the structure relating to the param_id/module_id
+	 * combination in uint8_t bytes.
+	 */
+	uint16_t param_size;
+	/* This field must be set to zero. */
+	uint16_t reserved;
+	struct vss_param_mfc_config_info_t mfc_config_info;
+} __packed;
+
+struct vss_icommon_cmd_set_param_mfc_config_v2_t {
+	/*
+	 * Pointer to the unique identifier for an address (physical/virtual).
+	 *
+	 * If the parameter data payload is within the message payload
+	 * (in-band), set this field to 0. The parameter data begins at the
+	 * specified data payload address.
+	 *
+	 * If the parameter data is out-of-band, this field is the handle to
+	 * the physical address in the shared memory that holds the parameter
+	 * data.
+	 */
+
+	uint32_t mem_handle;
+	/*
+	 * Location of the parameter data payload.
+	 *
+	 * The payload is an array of vss_icommon_param_data_t. If the
+	 * mem_handle is 0, this field is ignored.
+	 */
+	uint64_t mem_address;
+	/* Size of the parameter data payload in bytes. */
+	uint32_t mem_size;
+
+	struct vss_icommon_param_data_mfc_config_v2_t param_data;
+} __packed;
+
 /* Payload structure for the VSS_ICOMMON_CMD_SET_PARAM_V2 command. */
 struct vss_icommon_cmd_set_param_v2_t {
 	/*
@@ -674,6 +769,12 @@
 #define VSS_IRECORD_MODE_TX_RX_MIXING			0x00010F7B
 /* Select mixed Tx and Rx paths. */
 
+#define VSS_PARAM_VOCPROC_TX_CHANNEL_INFO              0x0001328E
+
+#define VSS_PARAM_VOCPROC_RX_CHANNEL_INFO              0x0001328F
+
+#define VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO          0x00013290
+
 #define VSS_PARAM_TX_PORT_ENDPOINT_MEDIA_INFO		0x00013253
 
 #define VSS_PARAM_RX_PORT_ENDPOINT_MEDIA_INFO		0x00013254
@@ -1485,7 +1586,18 @@
 
 struct cvp_set_media_format_cmd {
 	struct apr_hdr hdr;
-	struct vss_icommon_cmd_set_param_v2_t cvp_set_param_v2;
+	struct vss_icommon_cmd_set_param_v2_t cvp_set_media_param_v2;
+} __packed;
+
+struct cvp_set_channel_info_cmd_v2 {
+	struct apr_hdr hdr;
+	struct vss_icommon_cmd_set_param_channel_info_v2_t
+					cvp_set_ch_info_param_v2;
+} __packed;
+
+struct cvp_set_mfc_config_cmd_v2 {
+	struct apr_hdr hdr;
+	struct vss_icommon_cmd_set_param_mfc_config_v2_t cvp_set_mfc_param_v2;
 } __packed;
 
 struct cvp_set_vp3_data_cmd {
@@ -1756,6 +1868,8 @@
 	bool srvcc_rec_flag;
 	bool is_destroy_cvd;
 	char cvd_version[CVD_VERSION_STRING_MAX_SIZE];
+	int cvp_version;
+	bool is_avcs_version_queried;
 	bool is_per_vocoder_cal_enabled;
 	bool is_sound_focus_resp_success;
 	bool is_source_tracking_resp_success;
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c
index b34b04b..43df772 100644
--- a/sound/soc/msm/sdm660-common.c
+++ b/sound/soc/msm/sdm660-common.c
@@ -44,6 +44,8 @@
 	EXT_DISP_RX_IDX_MAX,
 };
 
+bool codec_reg_done;
+
 /* TDM default config */
 static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
 	{ /* PRI TDM */
@@ -2016,6 +2018,12 @@
 }
 EXPORT_SYMBOL(msm_common_snd_controls_size);
 
+void msm_set_codec_reg_done(bool done)
+{
+	codec_reg_done = done;
+}
+EXPORT_SYMBOL(msm_set_codec_reg_done);
+
 static inline int param_is_mask(int p)
 {
 	return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
@@ -3027,6 +3035,12 @@
 	  .data = "tasha_codec"},
 	{ .compatible = "qcom,sdm660-asoc-snd-tavil",
 	  .data = "tavil_codec"},
+	{ .compatible = "qcom,sdm670-asoc-snd",
+	  .data = "internal_codec"},
+	{ .compatible = "qcom,sdm670-asoc-snd-tasha",
+	  .data = "tasha_codec"},
+	{ .compatible = "qcom,sdm670-asoc-snd-tavil",
+	  .data = "tavil_codec"},
 	{},
 };
 
@@ -3044,6 +3058,7 @@
 	if (!pdata)
 		return -ENOMEM;
 
+	msm_set_codec_reg_done(false);
 	match = of_match_node(sdm660_asoc_machine_of_match,
 			      pdev->dev.of_node);
 	if (!match)
diff --git a/sound/soc/msm/sdm660-common.h b/sound/soc/msm/sdm660-common.h
index bca8cd7..ffe77bc 100644
--- a/sound/soc/msm/sdm660-common.h
+++ b/sound/soc/msm/sdm660-common.h
@@ -122,4 +122,5 @@
 int msm_mi2s_snd_startup(struct snd_pcm_substream *substream);
 void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream);
 int msm_common_snd_controls_size(void);
+void msm_set_codec_reg_done(bool done);
 #endif
diff --git a/sound/soc/msm/sdm660-ext-dai-links.c b/sound/soc/msm/sdm660-ext-dai-links.c
index 6ff29c9..68a0f37 100644
--- a/sound/soc/msm/sdm660-ext-dai-links.c
+++ b/sound/soc/msm/sdm660-ext-dai-links.c
@@ -29,8 +29,15 @@
 #define WCN_CDC_SLIM_RX_CH_MAX 2
 #define WCN_CDC_SLIM_TX_CH_MAX 3
 
-static struct snd_soc_card snd_soc_card_msm_card_tavil;
-static struct snd_soc_card snd_soc_card_msm_card_tasha;
+static struct snd_soc_card snd_soc_card_msm_card_tavil = {
+	.name = "sdm670-tavil-snd-card",
+	.late_probe = msm_snd_card_tavil_late_probe,
+};
+
+static struct snd_soc_card snd_soc_card_msm_card_tasha = {
+	.name = "sdm670-tasha-snd-card",
+	.late_probe = msm_snd_card_tasha_late_probe,
+};
 
 static struct snd_soc_ops msm_ext_slimbus_be_ops = {
 	.hw_params = msm_snd_hw_params,
@@ -990,13 +997,14 @@
 		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
 	},
 	{/* hw:x,16 */
-		.name = MSM_DAILINK_NAME(Compress3),
-		.stream_name = "Compress3",
+		.name = MSM_DAILINK_NAME(MultiMedia10),
+		.stream_name = "MultiMedia10",
 		.cpu_dai_name	= "MultiMedia10",
-		.platform_name  = "msm-compress-dsp",
+		.platform_name  = "msm-pcm-dsp.1",
 		.dynamic = 1,
 		.dpcm_capture = 1,
 		.dpcm_playback = 1,
+		.dpcm_capture = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			 SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
diff --git a/sound/soc/msm/sdm660-external.c b/sound/soc/msm/sdm660-external.c
index 426c150..4224289 100644
--- a/sound/soc/msm/sdm660-external.c
+++ b/sound/soc/msm/sdm660-external.c
@@ -55,7 +55,6 @@
 
 static int msm_ext_spk_control = 1;
 static struct wcd_mbhc_config *wcd_mbhc_cfg_ptr;
-bool codec_reg_done;
 
 struct msm_asoc_wcd93xx_codec {
 	void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
@@ -603,23 +602,23 @@
 
 static void *def_ext_mbhc_cal(void)
 {
-	void *tavil_wcd_cal;
+	void *wcd_mbhc_cal;
 	struct wcd_mbhc_btn_detect_cfg *btn_cfg;
 	u16 *btn_high;
 
-	tavil_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+	wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
 				WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
-	if (!tavil_wcd_cal)
+	if (!wcd_mbhc_cal)
 		return NULL;
 
-#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tavil_wcd_cal)->X) = (Y))
+#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->X) = (Y))
 	S(v_hs_max, 1600);
 #undef S
-#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tavil_wcd_cal)->X) = (Y))
+#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->X) = (Y))
 	S(num_btn, WCD_MBHC_DEF_BUTTONS);
 #undef S
 
-	btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tavil_wcd_cal);
+	btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
 	btn_high = ((void *)&btn_cfg->_v_btn_low) +
 		(sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
 
@@ -632,7 +631,7 @@
 	btn_high[6] = 500;
 	btn_high[7] = 500;
 
-	return tavil_wcd_cal;
+	return wcd_mbhc_cal;
 }
 
 static inline int param_is_mask(int p)
@@ -1478,6 +1477,79 @@
 	{"MIC BIAS4", NULL, "MCLK"},
 };
 
+int msm_snd_card_tasha_late_probe(struct snd_soc_card *card)
+{
+	const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
+	struct snd_soc_pcm_runtime *rtd;
+	int ret = 0;
+	void *mbhc_calibration;
+
+	rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+	if (!rtd) {
+		dev_err(card->dev,
+			"%s: snd_soc_get_pcm_runtime for %s failed!\n",
+			__func__, be_dl_name);
+		ret = -EINVAL;
+		goto err_pcm_runtime;
+	}
+
+	mbhc_calibration = def_ext_mbhc_cal();
+	if (!mbhc_calibration) {
+		ret = -ENOMEM;
+		goto err_mbhc_cal;
+	}
+	wcd_mbhc_cfg_ptr->calibration = mbhc_calibration;
+	ret = tasha_mbhc_hs_detect(rtd->codec, wcd_mbhc_cfg_ptr);
+	if (ret) {
+		dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
+			__func__, ret);
+		goto err_hs_detect;
+	}
+	return 0;
+
+err_hs_detect:
+	kfree(mbhc_calibration);
+err_mbhc_cal:
+err_pcm_runtime:
+	return ret;
+}
+
+int msm_snd_card_tavil_late_probe(struct snd_soc_card *card)
+{
+	const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
+	struct snd_soc_pcm_runtime *rtd;
+	int ret = 0;
+	void *mbhc_calibration;
+
+	rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+	if (!rtd) {
+		dev_err(card->dev,
+			"%s: snd_soc_get_pcm_runtime for %s failed!\n",
+			__func__, be_dl_name);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	mbhc_calibration = def_ext_mbhc_cal();
+	if (!mbhc_calibration) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	wcd_mbhc_cfg_ptr->calibration = mbhc_calibration;
+	ret = tavil_mbhc_hs_detect(rtd->codec, wcd_mbhc_cfg_ptr);
+	if (ret) {
+		dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
+			__func__, ret);
+		goto err_free_mbhc_cal;
+	}
+	return 0;
+
+err_free_mbhc_cal:
+	kfree(mbhc_calibration);
+err:
+	return ret;
+}
+
 /**
  * msm_audrx_init - Audio init function of sound card instantiate.
  *
@@ -1698,7 +1770,6 @@
 		if (!entry) {
 			pr_debug("%s: Cannot create codecs module entry\n",
 				 __func__);
-			pdata->codec_root = NULL;
 			goto done;
 		}
 		pdata->codec_root = entry;
@@ -1721,50 +1792,17 @@
 		if (!entry) {
 			pr_debug("%s: Cannot create codecs module entry\n",
 				 __func__);
-			ret = 0;
-			goto err_snd_module;
+			goto done;
 		}
 		pdata->codec_root = entry;
 		tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
 		tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec);
 	}
-
-	wcd_mbhc_cfg_ptr->calibration = def_ext_mbhc_cal();
-	if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
-		if (wcd_mbhc_cfg_ptr->calibration) {
-			pdata->codec = codec;
-			ret = tavil_mbhc_hs_detect(codec, wcd_mbhc_cfg_ptr);
-			if (ret < 0)
-				pr_err("%s: Failed to intialise mbhc %d\n",
-						__func__, ret);
-		} else {
-			pr_err("%s: wcd_mbhc_cfg calibration is NULL\n",
-					__func__);
-			ret = -ENOMEM;
-			goto err_mbhc_cal;
-		}
-	} else {
-		if (wcd_mbhc_cfg_ptr->calibration) {
-			pdata->codec = codec;
-			ret = tasha_mbhc_hs_detect(codec, wcd_mbhc_cfg_ptr);
-			if (ret < 0)
-				pr_err("%s: Failed to intialise mbhc %d\n",
-						__func__, ret);
-		} else {
-			pr_err("%s: wcd_mbhc_cfg calibration is NULL\n",
-					__func__);
-			ret = -ENOMEM;
-			goto err_mbhc_cal;
-		}
-
-	}
-	codec_reg_done = true;
 done:
+	msm_set_codec_reg_done(true);
 	return 0;
 
-err_snd_module:
 err_afe_cfg:
-err_mbhc_cal:
 	return ret;
 }
 EXPORT_SYMBOL(msm_audrx_init);
diff --git a/sound/soc/msm/sdm660-external.h b/sound/soc/msm/sdm660-external.h
index acf5735..d53e7c7 100644
--- a/sound/soc/msm/sdm660-external.h
+++ b/sound/soc/msm/sdm660-external.h
@@ -30,6 +30,8 @@
 						int snd_card_val);
 int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			       struct snd_pcm_hw_params *params);
+int msm_snd_card_tavil_late_probe(struct snd_soc_card *card);
+int msm_snd_card_tasha_late_probe(struct snd_soc_card *card);
 #ifdef CONFIG_SND_SOC_EXT_CODEC
 int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *,
 		     struct snd_soc_card **, struct wcd_mbhc_config *);
diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c
index 4b9334b..14e7308 100644
--- a/sound/soc/msm/sdm660-internal.c
+++ b/sound/soc/msm/sdm660-internal.c
@@ -1314,6 +1314,7 @@
 	msm_dig_codec_info_create_codec_entry(codec_root, dig_cdc);
 	msm_anlg_codec_info_create_codec_entry(codec_root, ana_cdc);
 done:
+	msm_set_codec_reg_done(true);
 	return 0;
 }
 
@@ -1914,13 +1915,14 @@
 		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
 	},
 	{/* hw:x,16 */
-		.name = MSM_DAILINK_NAME(Compress3),
-		.stream_name = "Compress3",
+		.name = MSM_DAILINK_NAME(MultiMedia10),
+		.stream_name = "MultiMedia10",
 		.cpu_dai_name	= "MultiMedia10",
-		.platform_name  = "msm-compress-dsp",
+		.platform_name  = "msm-pcm-dsp.1",
 		.dynamic = 1,
 		.dpcm_capture = 1,
 		.dpcm_playback = 1,
+		.dpcm_capture = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			 SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
diff --git a/sound/soc/msm/sdm845.c b/sound/soc/msm/sdm845.c
index 03a4938..7a5ccd8 100644
--- a/sound/soc/msm/sdm845.c
+++ b/sound/soc/msm/sdm845.c
@@ -134,6 +134,13 @@
 	u32 msm_is_mi2s_master;
 };
 
+static u32 mi2s_ebit_clk[MI2S_MAX] = {
+	Q6AFE_LPASS_CLK_ID_PRI_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_QUAD_MI2S_EBIT
+};
+
 struct auxpcm_conf {
 	struct mutex lock;
 	u32 ref_cnt;
@@ -434,6 +441,7 @@
 					   "Five", "Six", "Seven",
 					   "Eight"};
 static const char *const hifi_text[] = {"Off", "On"};
+static const char *const qos_text[] = {"Disable", "Enable"};
 
 static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text);
@@ -498,9 +506,11 @@
 static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
 static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text);
 static SOC_ENUM_SINGLE_EXT_DECL(hifi_function, hifi_text);
+static SOC_ENUM_SINGLE_EXT_DECL(qos_vote, qos_text);
 
 static struct platform_device *spdev;
 static int msm_hifi_control;
+static int qos_vote_status;
 
 static bool is_initial_boot;
 static bool codec_reg_done;
@@ -2628,6 +2638,72 @@
 	return 0;
 }
 
+static s32 msm_qos_value(struct snd_pcm_runtime *runtime)
+{
+	s32 usecs;
+
+	if (!runtime->rate)
+		return -EINVAL;
+
+	/* take 75% of period time as the deadline */
+	usecs = (750000 / runtime->rate) * runtime->period_size;
+	usecs += ((750000 % runtime->rate) * runtime->period_size) /
+		 runtime->rate;
+
+	return usecs;
+}
+
+static int msm_qos_ctl_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.enumerated.item[0] = qos_vote_status;
+
+	return 0;
+}
+
+static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct snd_soc_card *card = codec->component.card;
+	const char *be_name = MSM_DAILINK_NAME(LowLatency);
+	struct snd_soc_pcm_runtime *rtd;
+	struct snd_pcm_substream *substream;
+	s32 usecs;
+
+	rtd = snd_soc_get_pcm_runtime(card, be_name);
+	if (!rtd) {
+		pr_err("%s: fail to get pcm runtime for %s\n",
+			__func__, be_name);
+		return -EINVAL;
+	}
+
+	substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	if (!substream) {
+		pr_err("%s: substream is null\n", __func__);
+		return -EINVAL;
+	}
+
+	qos_vote_status = ucontrol->value.enumerated.item[0];
+	if (qos_vote_status) {
+		if (pm_qos_request_active(&substream->latency_pm_qos_req))
+			pm_qos_remove_request(&substream->latency_pm_qos_req);
+		if (!substream->runtime) {
+			pr_err("%s: runtime is null\n", __func__);
+			return -EINVAL;
+		}
+		usecs = msm_qos_value(substream->runtime);
+		if (usecs >= 0)
+			pm_qos_add_request(&substream->latency_pm_qos_req,
+					PM_QOS_CPU_DMA_LATENCY, usecs);
+	} else {
+		if (pm_qos_request_active(&substream->latency_pm_qos_req))
+			pm_qos_remove_request(&substream->latency_pm_qos_req);
+	}
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new msm_snd_controls[] = {
 	SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs,
 			msm_slim_rx_ch_get, msm_slim_rx_ch_put),
@@ -2857,6 +2933,8 @@
 			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
 	SOC_ENUM_EXT("HiFi Function", hifi_function, msm_hifi_get,
 			msm_hifi_put),
+	SOC_ENUM_EXT("MultiMedia5_RX QOS Vote", qos_vote, msm_qos_ctl_get,
+			msm_qos_ctl_put),
 };
 
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
@@ -4176,9 +4254,6 @@
 		mi2s_clk[dai_id].clk_freq_in_hz =
 		    mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
 	}
-
-	if (!mi2s_intf_conf[dai_id].msm_is_mi2s_master)
-		mi2s_clk[dai_id].clk_freq_in_hz = 0;
 }
 
 static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
@@ -4529,6 +4604,11 @@
 	 */
 	mutex_lock(&mi2s_intf_conf[index].lock);
 	if (++mi2s_intf_conf[index].ref_cnt == 1) {
+		/* Check if msm needs to provide the clock to the interface */
+		if (!mi2s_intf_conf[index].msm_is_mi2s_master) {
+			mi2s_clk[index].clk_id = mi2s_ebit_clk[index];
+			fmt = SND_SOC_DAIFMT_CBM_CFM;
+		}
 		ret = msm_mi2s_set_sclk(substream, true);
 		if (ret < 0) {
 			dev_err(rtd->card->dev,
@@ -4548,9 +4628,6 @@
 			ret = -EINVAL;
 			goto clk_off;
 		}
-		/* Check if msm needs to provide the clock to the interface */
-		if (!mi2s_intf_conf[index].msm_is_mi2s_master)
-			fmt = SND_SOC_DAIFMT_CBM_CFM;
 		ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
 		if (ret < 0) {
 			pr_err("%s: set fmt cpu dai failed for MI2S (%d), err:%d\n",
@@ -5049,12 +5126,13 @@
 		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
 	},
 	{
-		.name = MSM_DAILINK_NAME(Compress3),
-		.stream_name = "Compress3",
+		.name = MSM_DAILINK_NAME(MultiMedia10),
+		.stream_name = "MultiMedia10",
 		.cpu_dai_name = "MultiMedia10",
-		.platform_name = "msm-compress-dsp",
+		.platform_name = "msm-pcm-dsp.1",
 		.dynamic = 1,
 		.dpcm_playback = 1,
+		.dpcm_capture = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			 SND_SOC_DPCM_TRIGGER_POST},
 		.codec_dai_name = "snd-soc-dummy-dai",
@@ -6619,16 +6697,18 @@
 	ret = of_property_read_u32(pdev->dev.of_node,
 				   "qcom,wsa-max-devs", &wsa_max_devs);
 	if (ret) {
-		dev_dbg(&pdev->dev,
+		dev_info(&pdev->dev,
 			 "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
 			 __func__, pdev->dev.of_node->full_name, ret);
-		goto err;
+		card->num_aux_devs = 0;
+		return 0;
 	}
 	if (wsa_max_devs == 0) {
 		dev_warn(&pdev->dev,
 			 "%s: Max WSA devices is 0 for this target?\n",
 			 __func__);
-		goto err;
+		card->num_aux_devs = 0;
+		return 0;
 	}
 
 	/* Get count of WSA device phandles for this platform */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 6b23bf5..4f6c777 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3326,7 +3326,8 @@
  */
 void snd_soc_card_change_online_state(struct snd_soc_card *soc_card, int online)
 {
-	snd_card_change_online_state(soc_card->snd_card, online);
+	if (soc_card && soc_card->snd_card)
+		snd_card_change_online_state(soc_card->snd_card, online);
 }
 EXPORT_SYMBOL(snd_soc_card_change_online_state);
 
diff --git a/sound/usb/card.c b/sound/usb/card.c
index eaf18aa..a87a526 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -619,7 +619,7 @@
 	assoc = intf->intf_assoc;
 	if (assoc && assoc->bFunctionClass == USB_CLASS_AUDIO &&
 	    assoc->bFunctionProtocol == UAC_VERSION_3 &&
-	    assoc->bFunctionSubClass == FULL_ADC_PROFILE) {
+	    assoc->bFunctionSubClass == FULL_ADC_3_0) {
 		dev_info(&dev->dev, "No support for full-fledged ADC 3.0 yet!!\n");
 		return -EINVAL;
 	}
diff --git a/techpack/.gitignore b/techpack/.gitignore
new file mode 100644
index 0000000..58da0b8
--- /dev/null
+++ b/techpack/.gitignore
@@ -0,0 +1,2 @@
+# ignore all subdirs except stub
+!/stub/
diff --git a/techpack/Kbuild b/techpack/Kbuild
new file mode 100644
index 0000000..3c7c8e6
--- /dev/null
+++ b/techpack/Kbuild
@@ -0,0 +1,5 @@
+techpack-dirs := $(shell find $(srctree)/$(src) -maxdepth 1 -mindepth 1 -type d -not -name ".*")
+obj-y += stub/ $(addsuffix /,$(subst $(srctree)/$(src)/,,$(techpack-dirs)))
+
+techpack-header-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*")
+header-y += $(addsuffix /include/uapi/,$(subst $(srctree)/techpack/,,$(techpack-header-dirs)))
diff --git a/techpack/stub/Makefile b/techpack/stub/Makefile
new file mode 100644
index 0000000..184b5c7
--- /dev/null
+++ b/techpack/stub/Makefile
@@ -0,0 +1,2 @@
+ccflags-y := -Wno-unused-function
+obj-y := stub.o
diff --git a/techpack/stub/include/uapi/Kbuild b/techpack/stub/include/uapi/Kbuild
new file mode 100644
index 0000000..87bfa65
--- /dev/null
+++ b/techpack/stub/include/uapi/Kbuild
@@ -0,0 +1 @@
+#Stub place holder
diff --git a/techpack/stub/stub.c b/techpack/stub/stub.c
new file mode 100644
index 0000000..6024341
--- /dev/null
+++ b/techpack/stub/stub.c
@@ -0,0 +1,3 @@
+static void _techpack_stub(void)
+{
+}
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
index c808c7d..d302142 100644
--- a/tools/lib/lockdep/uinclude/linux/lockdep.h
+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
@@ -8,7 +8,7 @@
 #include <linux/utsname.h>
 #include <linux/compiler.h>
 
-#define MAX_LOCK_DEPTH 2000UL
+#define MAX_LOCK_DEPTH 63UL
 
 #define asmlinkage
 #define __visible
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 3eb3edb..a130901 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -702,7 +702,7 @@
 		ui_browser__gotorc(browser, row, column + 1);
 		SLsmg_draw_hline(2);
 
-		if (row++ == 0)
+		if (++row == 0)
 			goto out;
 	} else
 		row = 0;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 04387ab..7e27207 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -64,6 +64,25 @@
 	INTEL_PT_STATE_FUP_NO_TIP,
 };
 
+static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)
+{
+	switch (pkt_state) {
+	case INTEL_PT_STATE_NO_PSB:
+	case INTEL_PT_STATE_NO_IP:
+	case INTEL_PT_STATE_ERR_RESYNC:
+	case INTEL_PT_STATE_IN_SYNC:
+	case INTEL_PT_STATE_TNT:
+		return true;
+	case INTEL_PT_STATE_TIP:
+	case INTEL_PT_STATE_TIP_PGD:
+	case INTEL_PT_STATE_FUP:
+	case INTEL_PT_STATE_FUP_NO_TIP:
+		return false;
+	default:
+		return true;
+	};
+}
+
 #ifdef INTEL_PT_STRICT
 #define INTEL_PT_STATE_ERR1	INTEL_PT_STATE_NO_PSB
 #define INTEL_PT_STATE_ERR2	INTEL_PT_STATE_NO_PSB
@@ -92,6 +111,7 @@
 	bool have_tma;
 	bool have_cyc;
 	bool fixup_last_mtc;
+	bool have_last_ip;
 	uint64_t pos;
 	uint64_t last_ip;
 	uint64_t ip;
@@ -99,6 +119,7 @@
 	uint64_t timestamp;
 	uint64_t tsc_timestamp;
 	uint64_t ref_timestamp;
+	uint64_t sample_timestamp;
 	uint64_t ret_addr;
 	uint64_t ctc_timestamp;
 	uint64_t ctc_delta;
@@ -139,6 +160,7 @@
 	unsigned int fup_tx_flags;
 	unsigned int tx_flags;
 	uint64_t timestamp_insn_cnt;
+	uint64_t sample_insn_cnt;
 	uint64_t stuck_ip;
 	int no_progress;
 	int stuck_ip_prd;
@@ -398,6 +420,7 @@
 static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
 {
 	decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
+	decoder->have_last_ip = true;
 }
 
 static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
@@ -898,6 +921,7 @@
 
 	decoder->tot_insn_cnt += insn_cnt;
 	decoder->timestamp_insn_cnt += insn_cnt;
+	decoder->sample_insn_cnt += insn_cnt;
 	decoder->period_insn_cnt += insn_cnt;
 
 	if (err) {
@@ -1444,7 +1468,8 @@
 
 		case INTEL_PT_FUP:
 			decoder->pge = true;
-			intel_pt_set_last_ip(decoder);
+			if (decoder->packet.count)
+				intel_pt_set_last_ip(decoder);
 			break;
 
 		case INTEL_PT_MODE_TSX:
@@ -1648,6 +1673,8 @@
 			break;
 
 		case INTEL_PT_PSB:
+			decoder->last_ip = 0;
+			decoder->have_last_ip = true;
 			intel_pt_clear_stack(&decoder->stack);
 			err = intel_pt_walk_psbend(decoder);
 			if (err == -EAGAIN)
@@ -1728,8 +1755,9 @@
 
 static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
 {
-	return decoder->last_ip || decoder->packet.count == 0 ||
-	       decoder->packet.count == 3 || decoder->packet.count == 6;
+	return decoder->packet.count &&
+	       (decoder->have_last_ip || decoder->packet.count == 3 ||
+		decoder->packet.count == 6);
 }
 
 /* Walk PSB+ packets to get in sync. */
@@ -1852,14 +1880,10 @@
 			break;
 
 		case INTEL_PT_FUP:
-			if (decoder->overflow) {
-				if (intel_pt_have_ip(decoder))
-					intel_pt_set_ip(decoder);
-				if (decoder->ip)
-					return 0;
-			}
-			if (decoder->packet.count)
-				intel_pt_set_last_ip(decoder);
+			if (intel_pt_have_ip(decoder))
+				intel_pt_set_ip(decoder);
+			if (decoder->ip)
+				return 0;
 			break;
 
 		case INTEL_PT_MTC:
@@ -1908,6 +1932,9 @@
 			break;
 
 		case INTEL_PT_PSB:
+			decoder->last_ip = 0;
+			decoder->have_last_ip = true;
+			intel_pt_clear_stack(&decoder->stack);
 			err = intel_pt_walk_psb(decoder);
 			if (err)
 				return err;
@@ -1933,6 +1960,8 @@
 {
 	int err;
 
+	decoder->set_fup_tx_flags = false;
+
 	intel_pt_log("Scanning for full IP\n");
 	err = intel_pt_walk_to_ip(decoder);
 	if (err)
@@ -2041,6 +2070,7 @@
 
 	decoder->pge = false;
 	decoder->continuous_period = false;
+	decoder->have_last_ip = false;
 	decoder->last_ip = 0;
 	decoder->ip = 0;
 	intel_pt_clear_stack(&decoder->stack);
@@ -2049,6 +2079,7 @@
 	if (err)
 		return err;
 
+	decoder->have_last_ip = true;
 	decoder->pkt_state = INTEL_PT_STATE_NO_IP;
 
 	err = intel_pt_walk_psb(decoder);
@@ -2067,7 +2098,7 @@
 
 static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
 {
-	uint64_t est = decoder->timestamp_insn_cnt << 1;
+	uint64_t est = decoder->sample_insn_cnt << 1;
 
 	if (!decoder->cbr || !decoder->max_non_turbo_ratio)
 		goto out;
@@ -2075,7 +2106,7 @@
 	est *= decoder->max_non_turbo_ratio;
 	est /= decoder->cbr;
 out:
-	return decoder->timestamp + est;
+	return decoder->sample_timestamp + est;
 }
 
 const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
@@ -2091,7 +2122,9 @@
 			err = intel_pt_sync(decoder);
 			break;
 		case INTEL_PT_STATE_NO_IP:
+			decoder->have_last_ip = false;
 			decoder->last_ip = 0;
+			decoder->ip = 0;
 			/* Fall through */
 		case INTEL_PT_STATE_ERR_RESYNC:
 			err = intel_pt_sync_ip(decoder);
@@ -2128,15 +2161,24 @@
 		}
 	} while (err == -ENOLINK);
 
-	decoder->state.err = err ? intel_pt_ext_err(err) : 0;
-	decoder->state.timestamp = decoder->timestamp;
+	if (err) {
+		decoder->state.err = intel_pt_ext_err(err);
+		decoder->state.from_ip = decoder->ip;
+		decoder->sample_timestamp = decoder->timestamp;
+		decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
+	} else {
+		decoder->state.err = 0;
+		if (intel_pt_sample_time(decoder->pkt_state)) {
+			decoder->sample_timestamp = decoder->timestamp;
+			decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
+		}
+	}
+
+	decoder->state.timestamp = decoder->sample_timestamp;
 	decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
 	decoder->state.cr3 = decoder->cr3;
 	decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
 
-	if (err)
-		decoder->state.from_ip = decoder->ip;
-
 	return &decoder->state;
 }
 
diff --git a/tools/testing/selftests/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c
index 10a21a9..763f37f 100644
--- a/tools/testing/selftests/capabilities/test_execve.c
+++ b/tools/testing/selftests/capabilities/test_execve.c
@@ -138,9 +138,6 @@
 
 	if (chdir(cwd) != 0)
 		err(1, "chdir to private tmpfs");
-
-	if (umount2(".", MNT_DETACH) != 0)
-		err(1, "detach private tmpfs");
 }
 
 static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
@@ -248,7 +245,7 @@
 			err(1, "chown");
 		if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
 			err(1, "chmod");
-}
+	}
 
 	capng_get_caps_process();
 
@@ -384,7 +381,7 @@
 	} else {
 		printf("[RUN]\tNon-root +ia, sgidnonroot => i\n");
 		exec_other_validate_cap("./validate_cap_sgidnonroot",
-						false, false, true, false);
+					false, false, true, false);
 
 		if (fork_wait()) {
 			printf("[RUN]\tNon-root +ia, sgidroot => i\n");
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 1dd087d..111e09c 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -47,6 +47,22 @@
 	return vfio_group;
 }
 
+static bool kvm_vfio_external_group_match_file(struct vfio_group *group,
+					       struct file *filep)
+{
+	bool ret, (*fn)(struct vfio_group *, struct file *);
+
+	fn = symbol_get(vfio_external_group_match_file);
+	if (!fn)
+		return false;
+
+	ret = fn(group, filep);
+
+	symbol_put(vfio_external_group_match_file);
+
+	return ret;
+}
+
 static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group)
 {
 	void (*fn)(struct vfio_group *);
@@ -171,18 +187,13 @@
 		if (!f.file)
 			return -EBADF;
 
-		vfio_group = kvm_vfio_group_get_external_user(f.file);
-		fdput(f);
-
-		if (IS_ERR(vfio_group))
-			return PTR_ERR(vfio_group);
-
 		ret = -ENOENT;
 
 		mutex_lock(&kv->lock);
 
 		list_for_each_entry(kvg, &kv->group_list, node) {
-			if (kvg->vfio_group != vfio_group)
+			if (!kvm_vfio_external_group_match_file(kvg->vfio_group,
+								f.file))
 				continue;
 
 			list_del(&kvg->node);
@@ -196,7 +207,7 @@
 
 		mutex_unlock(&kv->lock);
 
-		kvm_vfio_group_put_external_user(vfio_group);
+		fdput(f);
 
 		kvm_vfio_update_coherency(dev);