Merge "msm: kgsl: Do not return error if there is no GMU" into msm-4.9
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt b/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt
deleted file mode 100644
index 84a8765..0000000
--- a/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-* Qualcomm Technologies Inc MSM VIDC VMEM
-
-Required properties:
-- compatible : "qcom,msm-vmem".
-- interrupts : Contains the interrupt that maps to the VMEM module.
-- reg : A set of 2 start address and size pairs that describe the hardware
-register address space and mappable memory address space.
-- reg-names : Strings that describe the pairs in "reg".  The register address
-space should be called "reg-base" and the memory space should be called "mem-base".
-- clocks : A set of clocks that correspond to the AHB and MAXI clocks that the
-hardware uses.
-- clock-names : A string that describes the "clocks" property.  The AHB clock
-should be named "ahb" and the MAXI clock should be named "maxi".
-- qcom,bank-size : The size of each memory bank, in bytes.
-- vdd-supply: phandle to a regulator that is considered to be the footswitch for vmem.
-- qcom,msm-bus,(name|num-cases,num-paths,vectors-KBps) - Bus to be voted for prior to
-  issuing any IO transactions to vmem.  Refer to Documentation/devicetree/bindings/arm/\
-  msm/msm_bus_adhoc.txt for further details.
-
-Example:
-
-qcom,vmem@880000 {
-	compatible = "qcom,msm-vmem";
-	interrupts = <0 429 0>;
-	reg = <0x880000 0x800>,
-	    <0x6800000 0x100000>;
-	reg-names = "reg-base", "mem-base";
-
-	vdd-supply = <&gdsc_mmagic_video>;
-	clocks = <&clock_mmss clk_vmem_ahb_clk>,
-	       <&clock_mmss clk_vmem_maxi_clk>;
-	clock-names = "ahb", "maxi";
-
-	qcom,bank-size = <131072>;
-
-	qcom,msm-bus,name = "vmem";
-	qcom,msm-bus,num-cases = <2>;
-	qcom,msm-bus,num-paths = <1>;
-	qcom,msm-bus,vectors-KBps =
-	        <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_VMEM_CFG   0   0>,
-	        <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_VMEM_CFG 500 800>;
-};
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index bdc0eba..53f419c 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -104,6 +104,9 @@
   memory, performance etc.
 - qcom,debug-timeout = A bool indicating that FW errors such as SYS_ERROR,
   SESSION_ERROR and timeouts will be treated as Fatal.
+- cache-slice-names = An array of supported cache slice names by llcc
+- cache-slices = An array of supported cache slice ids corresponding
+  to cache-slice-names by llcc
 
 [Second level nodes]
 Context Banks
@@ -149,7 +152,7 @@
 Optional properties:
 - qcom,bus-governor : governor to use when scaling bus, generally any commonly
   found devfreq governor might be used.  In addition to those governors, the
-  custom Venus governors, "msm-vidc-ddr" or "msm-vidc-vmem" are also
+  custom Venus governors, "msm-vidc-ddr" or "msm-vidc-llcc" are also
   acceptable values.
   In the absence of this property the "performance" governor is used.
 - qcom,bus-rage-kbps : an array of two items (<min max>) that indicate the
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 5d0499c..803df6f 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -59,6 +59,8 @@
  - qcom,poll-cfg-gdscr:	Poll the CFG register of the GDSC to determine if the
 			GDSC is enabled/disabled. This flag should not be set
 			in conjunction with "hw-ctrl-addr".
+ - qcom,toggle-sw-collapse-in-disable: If set, SW_COLLAPSE bit is toggled
+			in disable call.
 
 Example:
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
index 84a6a84..2194a42 100644
--- a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
@@ -217,6 +217,7 @@
 		sw-reset = <&gpu_gx_sw_reset>;
 		qcom,reset-aon-logic;
 		qcom,poll-cfg-gdscr;
+		qcom,toggle-sw-collapse-in-disable;
 		status = "disabled";
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index f6493ac..9b7865f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -767,6 +767,15 @@
 					    <&tpdm_lpass_out_funnel_lpass>;
 				};
 			};
+
+			port@2 {
+				reg = <1>;
+				funnel_lpass_in_audio_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+					    <&audio_etm0_out_funnel_lpass>;
+				};
+			};
 		};
 	};
 
@@ -1731,7 +1740,7 @@
 		compatible = "qcom,coresight-remote-etm";
 
 		coresight-name = "coresight-turing-etm0";
-		qcom,inst-id = <1>;
+		qcom,inst-id = <13>;
 
 		port{
 			turing_etm0_out_funnel_turing: endpoint {
@@ -1770,6 +1779,19 @@
 		};
 	};
 
+	audio_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-name = "coresight-audio-etm0";
+		qcom,inst-id = <5>;
+
+		port {
+			audio_etm0_out_funnel_lpass: endpoint {
+				remote-endpoint = <&funnel_lpass_in_audio_etm0>;
+			};
+		};
+	};
+
 	funnel_apss_merg: funnel@7810000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 9056569..b51996d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -142,6 +142,7 @@
 	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 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index df2e0c7..6d9e321 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -14,9 +14,11 @@
 	mdss_mdp: qcom,mdss_mdp@ae00000 {
 		compatible = "qcom,sde-kms";
 		reg = <0x0ae00000 0x81d40>,
-		      <0x0aeb0000 0x2008>;
+		      <0x0aeb0000 0x2008>,
+		      <0x0aeac000 0xf0>;
 		reg-names = "mdp_phys",
-			"vbif_phys";
+			"vbif_phys",
+			"regdma_phys";
 
 		clocks =
 			<&clock_gcc GCC_DISP_AHB_CLK>,
@@ -56,7 +58,7 @@
 		qcom,sde-mixer-size = <0x320>;
 
 		qcom,sde-dspp-off = <0x55000 0x57000 0x59000 0x5b000>;
-		qcom,sde-dspp-size = <0x4>;
+		qcom,sde-dspp-size = <0x17e0>;
 
 		qcom,sde-wb-off = <0x66000>;
 		qcom,sde-wb-size = <0x2c8>;
@@ -97,6 +99,8 @@
 					1 5 9 13>;
 		qcom,sde-sspp-excl-rect = <1 1 1 1
 						1 1 1 1>;
+		qcom,sde-sspp-smart-dma-priority = <5 6 7 8 1 2 3 4>;
+		qcom,sde-smart-dma-rev = "smart_dma_v2";
 
 		qcom,sde-mixer-pair-mask = <2 1 6 0 0 3>;
 
@@ -133,12 +137,22 @@
 
 		qcom,sde-inline-rotator = <&mdss_rotator 0>;
 
+		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>;
 			qcom,sde-vig-qseed-off = <0xa00>;
 			qcom,sde-vig-qseed-size = <0xa0>;
 		};
 
+		qcom,sde-dspp-blocks {
+			qcom,sde-dspp-vlut = <0xa00 0x00010008>;
+			qcom,sde-dspp-gamut = <0x1000 0x00040000>;
+			qcom,sde-dspp-gc = <0x17c0 0x00010008>;
+		};
+
 		qcom,platform-supply-entries {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index dddd241..6038b6e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -69,11 +69,14 @@
 			};
 			L1_I_0: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_0: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_0: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -97,11 +100,14 @@
 			};
 			L1_I_100: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_100: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_100: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -125,11 +131,14 @@
 			};
 			L1_I_200: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_200: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_200: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -153,11 +162,14 @@
 			};
 			L1_I_300: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_300: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_300: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -181,11 +193,14 @@
 			};
 			L1_I_400: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_400: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_400: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -209,11 +224,14 @@
 			};
 			L1_I_500: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_500: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_500: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -237,11 +255,14 @@
 			};
 			L1_I_600: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_600: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_600: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -265,11 +286,14 @@
 			};
 			L1_I_700: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_700: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_700: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -428,6 +452,13 @@
 
 	soc: soc { };
 
+	vendor: vendor {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+		compatible = "simple-bus";
+	};
+
 	reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -2036,6 +2067,38 @@
 			qcom,dump-node = <&LLCC_4>;
 			qcom,dump-id = <0x124>;
 		};
+		qcom,l1_tlb_dump0 {
+			qcom,dump-node = <&L1_TLB_0>;
+			qcom,dump-id = <0x20>;
+		};
+		qcom,l1_tlb_dump100 {
+			qcom,dump-node = <&L1_TLB_100>;
+			qcom,dump-id = <0x21>;
+		};
+		qcom,l1_tlb_dump200 {
+			qcom,dump-node = <&L1_TLB_200>;
+			qcom,dump-id = <0x22>;
+		};
+		qcom,l1_tlb_dump300 {
+			qcom,dump-node = <&L1_TLB_300>;
+			qcom,dump-id = <0x23>;
+		};
+		qcom,l1_tlb_dump400 {
+			qcom,dump-node = <&L1_TLB_400>;
+			qcom,dump-id = <0x24>;
+		};
+		qcom,l1_tlb_dump500 {
+			qcom,dump-node = <&L1_TLB_500>;
+			qcom,dump-id = <0x25>;
+		};
+		qcom,l1_tlb_dump600 {
+			qcom,dump-node = <&L1_TLB_600>;
+			qcom,dump-id = <0x26>;
+		};
+		qcom,l1_tlb_dump700 {
+			qcom,dump-node = <&L1_TLB_700>;
+			qcom,dump-id = <0x27>;
+		};
 	};
 
 	kryo3xx-erp {
@@ -2797,7 +2860,7 @@
 			thermal-sensors = <&tsens0 0>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2811,7 +2874,7 @@
 			thermal-sensors = <&tsens0 1>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2825,7 +2888,7 @@
 			thermal-sensors = <&tsens0 2>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2839,7 +2902,7 @@
 			thermal-sensors = <&tsens0 3>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2853,7 +2916,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2867,7 +2930,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2881,7 +2944,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2895,7 +2958,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2909,7 +2972,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2923,7 +2986,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2937,7 +3000,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2951,7 +3014,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2965,7 +3028,7 @@
 			thermal-sensors = <&tsens0 12>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2979,7 +3042,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2993,7 +3056,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3009,7 +3072,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3023,7 +3086,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3037,7 +3100,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3051,7 +3114,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3065,7 +3128,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3079,7 +3142,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3811,6 +3874,38 @@
 		interrupt-names = "tsens-upper-lower", "tsens-critical";
 		#thermal-sensor-cells = <1>;
 	};
+
+	gpi_dma0: qcom,gpi-dma@0x800000 {
+		#dma-cells = <6>;
+		compatible = "qcom,gpi-dma";
+		reg = <0x800000 0x60000>;
+		reg-names = "gpi-top";
+		interrupts = <0 244 0>, <0 245 0>, <0 246 0>, <0 247 0>,
+			     <0 248 0>, <0 249 0>, <0 250 0>, <0 251 0>,
+			     <0 252 0>, <0 253 0>, <0 254 0>, <0 255 0>,
+			     <0 256 0>;
+		qcom,max-num-gpii = <13>;
+		qcom,gpii-mask = <0xfa>;
+		qcom,ev-factor = <2>;
+		iommus = <&apps_smmu 0x0016 0x0>;
+		status = "ok";
+	};
+
+	gpi_dma1: qcom,gpi-dma@0xa00000 {
+		#dma-cells = <6>;
+		compatible = "qcom,gpi-dma";
+		reg = <0xa00000 0x60000>;
+		reg-names = "gpi-top";
+		interrupts = <0 279 0>, <0 280 0>, <0 281 0>, <0 282 0>,
+			     <0 283 0>, <0 284 0>, <0 293 0>, <0 294 0>,
+			     <0 295 0>, <0 296 0>, <0 297 0>, <0 298 0>,
+			     <0 299 0>;
+		qcom,max-num-gpii = <13>;
+		qcom,gpii-mask = <0xfa>;
+		qcom,ev-factor = <2>;
+		iommus = <&apps_smmu 0x06d6 0x0>;
+		status = "ok";
+	};
 };
 
 &clock_cpucc {
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 837bbab..75088c00 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -943,6 +943,8 @@
 	.sync_single_for_device = __iommu_sync_single_for_device,
 	.sync_sg_for_cpu = __iommu_sync_sg_for_cpu,
 	.sync_sg_for_device = __iommu_sync_sg_for_device,
+	.map_resource = iommu_dma_map_resource,
+	.unmap_resource = iommu_dma_unmap_resource,
 	.dma_supported = iommu_dma_supported,
 	.mapping_error = iommu_dma_mapping_error,
 };
@@ -1847,6 +1849,45 @@
 		__dma_page_cpu_to_dev(page, offset, size, dir);
 }
 
+static dma_addr_t arm_iommu_dma_map_resource(
+			struct device *dev, phys_addr_t phys_addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+	size_t offset = phys_addr & ~PAGE_MASK;
+	size_t len = PAGE_ALIGN(size + offset);
+	dma_addr_t dma_addr;
+	int prot;
+
+	dma_addr = __alloc_iova(mapping, len);
+	if (dma_addr == DMA_ERROR_CODE)
+		return dma_addr;
+
+	prot = __dma_direction_to_prot(dir);
+	prot |= IOMMU_MMIO;
+
+	if (iommu_map(mapping->domain, dma_addr, phys_addr - offset,
+			len, prot)) {
+		__free_iova(mapping, dma_addr, len);
+		return DMA_ERROR_CODE;
+	}
+	return dma_addr + offset;
+}
+
+static void arm_iommu_dma_unmap_resource(
+			struct device *dev, dma_addr_t addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+	size_t offset = addr & ~PAGE_MASK;
+	size_t len = PAGE_ALIGN(size + offset);
+
+	iommu_unmap(mapping->domain, addr - offset, len);
+	__free_iova(mapping, addr - offset, len);
+}
+
 static int arm_iommu_mapping_error(struct device *dev,
 				   dma_addr_t dma_addr)
 {
@@ -1869,6 +1910,9 @@
 	.sync_sg_for_cpu	= arm_iommu_sync_sg_for_cpu,
 	.sync_sg_for_device	= arm_iommu_sync_sg_for_device,
 
+	.map_resource		= arm_iommu_dma_map_resource,
+	.unmap_resource		= arm_iommu_dma_unmap_resource,
+
 	.set_dma_mask		= arm_dma_set_mask,
 	.mapping_error		= arm_iommu_mapping_error,
 };
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ee847d9f..3f2ce31 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -2470,7 +2470,7 @@
 			int srcVM[1] = {VMID_HLOS};
 			int destVM[4] = {VMID_HLOS, VMID_MSS_MSA, VMID_SSC_Q6,
 						VMID_ADSP_Q6};
-			int destVMperm[4] = {PERM_READ | PERM_WRITE,
+			int destVMperm[4] = {PERM_READ | PERM_WRITE | PERM_EXEC,
 				PERM_READ | PERM_WRITE | PERM_EXEC,
 				PERM_READ | PERM_WRITE | PERM_EXEC,
 				PERM_READ | PERM_WRITE | PERM_EXEC,
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index 3bb7c04..90c76e6 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -54,6 +54,9 @@
 /* Timeout Delay */
 #define TIMEOUT_US		100
 
+/* TOGGLE SW COLLAPSE */
+#define TOGGLE_SW_COLLAPSE_IN_DISABLE	BIT(0)
+
 struct gdsc {
 	struct regulator_dev	*rdev;
 	struct regulator_desc	rdesc;
@@ -79,6 +82,7 @@
 	int			reset_count;
 	int			root_clk_idx;
 	u32			gds_timeout;
+	u32			flags;
 };
 
 enum gdscr_status {
@@ -378,6 +382,13 @@
 		regval |= SW_COLLAPSE_MASK;
 		regmap_write(sc->regmap, REG_OFFSET, regval);
 
+		if (sc->flags & TOGGLE_SW_COLLAPSE_IN_DISABLE) {
+			regval &= ~SW_COLLAPSE_MASK;
+			regmap_write(sc->regmap, REG_OFFSET, regval);
+			regval |= SW_COLLAPSE_MASK;
+			regmap_write(sc->regmap, REG_OFFSET, regval);
+		}
+
 		/* Wait for 8 XO cycles before polling the status bit. */
 		mb();
 		udelay(1);
@@ -522,7 +533,7 @@
 	struct resource *res;
 	struct gdsc *sc;
 	uint32_t regval, clk_dis_wait_val = 0;
-	bool retain_mem, retain_periph, support_hw_trigger;
+	bool retain_mem, retain_periph, support_hw_trigger, prop_val;
 	int i, ret;
 	u32 timeout;
 
@@ -613,6 +624,11 @@
 	sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
 						"qcom,force-enable-root-clk");
 
+	prop_val = of_property_read_bool(pdev->dev.of_node,
+						"qcom,toggle-sw-collapse-in-disable");
+	if (prop_val)
+		sc->flags |= TOGGLE_SW_COLLAPSE_IN_DISABLE;
+
 	for (i = 0; i < sc->clock_count; i++) {
 		const char *clock_name;
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 53f0098..37ed411 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -357,6 +357,10 @@
 	case DSI_PANEL_ROTATE_V_FLIP:
 		sde_kms_info_add_keystr(info, "panel orientation", "vert flip");
 		break;
+	case DSI_PANEL_ROTATE_HV_FLIP:
+		sde_kms_info_add_keystr(info, "panel orientation",
+							"horz & vert flip");
+		break;
 	default:
 		pr_debug("invalid panel rotation:%d\n",
 						panel->phy_props.rotation);
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 79b39bd..d5207b9 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -1164,7 +1164,7 @@
 		sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_AD_CFG,
 			sizeof(struct drm_msm_ad4_cfg));
 		sde_cp_crtc_install_range_property(crtc,
-			"SDE_DSPP_AD_V4_ASSERTIVNESS",
+			"SDE_DSPP_AD_V4_ASSERTIVENESS",
 			SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS, 0, (BIT(8) - 1), 0);
 		sde_cp_crtc_install_range_property(crtc, "SDE_DSPP_AD_V4_INPUT",
 			SDE_CP_CRTC_DSPP_AD_INPUT, 0, U16_MAX, 0);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 02d6009..dcf3c08 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -731,7 +731,6 @@
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_state *crtc_state;
 	struct sde_rect *crtc_roi;
-	struct drm_clip_rect crtc_clip, *user_rect;
 	int i, num_attached_conns = 0;
 
 	if (!crtc || !state)
@@ -741,12 +740,6 @@
 	crtc_state = to_sde_crtc_state(state);
 	crtc_roi = &crtc_state->crtc_roi;
 
-	/* init to invalid range maxes */
-	crtc_clip.x1 = ~0;
-	crtc_clip.y1 = ~0;
-	crtc_clip.x2 = 0;
-	crtc_clip.y2 = 0;
-
 	for_each_connector_in_state(state->state, conn, conn_state, i) {
 		struct sde_connector_state *sde_conn_state;
 
@@ -771,36 +764,7 @@
 		}
 	}
 
-	/* aggregate all clipping rectangles together for overall crtc roi */
-	for (i = 0; i < crtc_state->user_roi_list.num_rects; i++) {
-		user_rect = &crtc_state->user_roi_list.roi[i];
-
-		crtc_clip.x1 = min(crtc_clip.x1, user_rect->x1);
-		crtc_clip.y1 = min(crtc_clip.y1, user_rect->y1);
-		crtc_clip.x2 = max(crtc_clip.x2, user_rect->x2);
-		crtc_clip.y2 = max(crtc_clip.y2, user_rect->y2);
-
-		SDE_DEBUG(
-			"%s: conn%d roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n",
-				sde_crtc->name, DRMID(crtc), i,
-				user_rect->x1, user_rect->y1,
-				user_rect->x2, user_rect->y2,
-				crtc_clip.x1, crtc_clip.y1,
-				crtc_clip.x2, crtc_clip.y2);
-
-	}
-
-	if (crtc_clip.x2  && crtc_clip.y2) {
-		crtc_roi->x = crtc_clip.x1;
-		crtc_roi->y = crtc_clip.y1;
-		crtc_roi->w = crtc_clip.x2 - crtc_clip.x1;
-		crtc_roi->h = crtc_clip.y2 - crtc_clip.y1;
-	} else {
-		crtc_roi->x = 0;
-		crtc_roi->y = 0;
-		crtc_roi->w = 0;
-		crtc_roi->h = 0;
-	}
+	sde_kms_rect_merge_rectangles(&crtc_state->user_roi_list, crtc_roi);
 
 	SDE_DEBUG("%s: crtc roi (%d,%d,%d,%d)\n", sde_crtc->name,
 			crtc_roi->x, crtc_roi->y, crtc_roi->w, crtc_roi->h);
@@ -1066,6 +1030,10 @@
 		if (sde_kms_rect_is_null(lm_roi))
 			continue;
 
+		hw_lm->cfg.out_width = lm_roi->w;
+		hw_lm->cfg.out_height = lm_roi->h;
+		hw_lm->cfg.right_mixer = lm_horiz_position;
+
 		cfg.out_width = lm_roi->w;
 		cfg.out_height = lm_roi->h;
 		cfg.right_mixer = lm_horiz_position++;
@@ -2563,11 +2531,14 @@
 	}
 
 	for (i = 1; i < SSPP_MAX; i++) {
-		if (pipe_staged[i] &&
-			is_sde_plane_virtual(pipe_staged[i]->plane)) {
-			SDE_ERROR("invalid use of virtual plane: %d\n",
+		if (pipe_staged[i]) {
+			sde_plane_clear_multirect(pipe_staged[i]);
+
+			if (is_sde_plane_virtual(pipe_staged[i]->plane)) {
+				SDE_ERROR("invalid use of virtual plane: %d\n",
 					pipe_staged[i]->plane->base.id);
-			goto end;
+				goto end;
+			}
 		}
 	}
 
@@ -3081,6 +3052,8 @@
 		seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n",
 			state->crtc_x, state->crtc_y, state->crtc_w,
 			state->crtc_h);
+		seq_printf(s, "\tmultirect: mode: %d index: %d\n",
+			pstate->multirect_mode, pstate->multirect_index);
 		seq_puts(s, "\n");
 	}
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ad4.c b/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
index 7d2f67d..b02cc06 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
@@ -17,8 +17,8 @@
 #include "sde_ad4.h"
 
 #define IDLE_2_RUN(x) ((x) == (ad4_init | ad4_cfg | ad4_mode | ad4_input))
-#define MERGE_WIDTH_RIGHT 4
-#define MERGE_WIDTH_LEFT 3
+#define MERGE_WIDTH_RIGHT 6
+#define MERGE_WIDTH_LEFT 5
 
 enum ad4_ops_bitmask {
 	ad4_init = BIT(AD_INIT),
@@ -179,7 +179,7 @@
 			cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
 		return -EINVAL;
 	} else if (hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
-		    hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 2)) {
+		    hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 1)) {
 		DRM_ERROR("dual_lm lmh %d lmw %d displayh %d displayw %d\n",
 			hw_lm->cfg.out_height, hw_lm->cfg.out_width,
 			cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
@@ -250,6 +250,7 @@
 				MERGE_WIDTH_LEFT;
 			proc_start = 0;
 			proc_end = (cfg->hw_cfg->displayh >> 1) - 1;
+			tile_ctl |= 0x10;
 		}
 	}
 
@@ -769,7 +770,8 @@
 					(cfg->hw_cfg->payload));
 	info[dspp->idx].completed_ops_mask |= ad4_mode;
 
-	if (IDLE_2_RUN(info[dspp->idx].completed_ops_mask))
+	if (IDLE_2_RUN(info[dspp->idx].completed_ops_mask) ||
+					info[dspp->idx].cached_mode == AD4_OFF)
 		ad4_mode_setup(dspp, info[dspp->idx].cached_mode);
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index c33e520..5719c51 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -529,16 +529,36 @@
 		REG_DMA_SETUP_OPS(dma_write_cfg,
 			ctx->cap->sblk->gc.base + GC_C0_OFF +
 			(i * sizeof(u32) * 2),
-			lut_cfg->c0 + ARRAY_SIZE(lut_cfg->c0),
+			lut_cfg->c0 + (ARRAY_SIZE(lut_cfg->c0) * i),
 			PGC_TBL_LEN * sizeof(u32),
 			REG_BLK_WRITE_INC, 0, 0);
 		rc = dma_ops->setup_payload(&dma_write_cfg);
 		if (rc) {
-			DRM_ERROR("index init failed ret %d\n", rc);
+			DRM_ERROR("lut write failed ret %d\n", rc);
 			return;
 		}
 	}
 
+	reg = BIT(0);
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("setting swap offset failed ret %d\n", rc);
+		return;
+	}
+
+	reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0);
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->gc.base,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("enabling gamma correction failed ret %d\n", rc);
+		return;
+	}
+
 	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[GC][ctx->idx],
 			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
 	kick_off.last_command = hw_cfg->last_feature;
@@ -547,11 +567,6 @@
 		DRM_ERROR("failed to kick off ret %d\n", rc);
 		return;
 	}
-
-	reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0);
-	SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF,
-			BIT(0));
-	SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, reg);
 }
 
 int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx)
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index c045067..a1f5cee 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -299,7 +299,7 @@
 {
 	struct sde_hw_blk_reg_map *c;
 	u32 chroma_samp, unpack, src_format;
-	u32 secure = 0;
+	u32 secure = 0, secure_bit_mask;
 	u32 opmode = 0;
 	u32 op_mode_off, unpack_pat_off, format_off;
 	u32 idx;
@@ -311,10 +311,12 @@
 		op_mode_off = SSPP_SRC_OP_MODE;
 		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
 		format_off = SSPP_SRC_FORMAT;
+		secure_bit_mask = (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
 	} else {
 		op_mode_off = SSPP_SRC_OP_MODE_REC1;
 		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN_REC1;
 		format_off = SSPP_SRC_FORMAT_REC1;
+		secure_bit_mask = 0xA;
 	}
 
 	c = &ctx->hw;
@@ -322,16 +324,11 @@
 	opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
 			MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
 
-	if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION) {
-		secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
-
-		if (rect_mode == SDE_SSPP_RECT_SOLO)
-			secure |= 0xF;
-		else if (rect_mode == SDE_SSPP_RECT_0)
-			secure |= 0x5;
-		else if (rect_mode == SDE_SSPP_RECT_1)
-			secure |= 0xA;
-	}
+	secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+	if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION)
+		secure |= secure_bit_mask;
+	else
+		secure &= ~secure_bit_mask;
 
 	if (flags & SDE_SSPP_FLIP_LR)
 		opmode |= MDSS_MDP_OP_FLIP_LR;
@@ -803,11 +800,17 @@
 		ystride1 = SDE_REG_READ(c, SSPP_SRC_YSTRIDE1 + idx);
 
 		if (rect_index == SDE_SSPP_RECT_0) {
-			ystride0 |= cfg->layout.plane_pitch[0];
-			ystride1 |= cfg->layout.plane_pitch[2];
-		}  else {
-			ystride0 |= cfg->layout.plane_pitch[0] << 16;
-			ystride1 |= cfg->layout.plane_pitch[2] << 16;
+			ystride0 = (ystride0 & 0xFFFF0000) |
+				(cfg->layout.plane_pitch[0] & 0x0000FFFF);
+			ystride1 = (ystride1 & 0xFFFF0000)|
+				(cfg->layout.plane_pitch[2] & 0x0000FFFF);
+		} else {
+			ystride0 = (ystride0 & 0x0000FFFF) |
+				((cfg->layout.plane_pitch[0] << 16) &
+				 0xFFFF0000);
+			ystride1 = (ystride1 & 0x0000FFFF) |
+				((cfg->layout.plane_pitch[2] << 16) &
+				 0xFFFF0000);
 		}
 	}
 
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 01a5535..1f56d73 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -407,6 +407,14 @@
 		struct sde_rect *result);
 
 /**
+ * sde_kms_rect_merge_rectangles - merge a rectangle list into one rect
+ * @rois: pointer to the list of rois
+ * @result: output rectangle, all 0 on error
+ */
+void sde_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
+		struct sde_rect *result);
+
+/**
  * sde_kms_rect_is_equal - compares two rects
  * @r1: rect value to compare
  * @r2: rect value to compare
diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
index b956be5..dcc0bd5 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
@@ -175,3 +175,46 @@
 		result->h = b - t;
 	}
 }
+
+void sde_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
+		struct sde_rect *result)
+{
+	struct drm_clip_rect clip;
+	const struct drm_clip_rect *roi_rect;
+	int i;
+
+	if (!rois || !result)
+		return;
+
+	memset(result, 0, sizeof(*result));
+
+	/* init to invalid range maxes */
+	clip.x1 = ~0;
+	clip.y1 = ~0;
+	clip.x2 = 0;
+	clip.y2 = 0;
+
+	/* aggregate all clipping rectangles together for overall roi */
+	for (i = 0; i < rois->num_rects; i++) {
+		roi_rect = &rois->roi[i];
+
+		clip.x1 = min(clip.x1, roi_rect->x1);
+		clip.y1 = min(clip.y1, roi_rect->y1);
+		clip.x2 = max(clip.x2, roi_rect->x2);
+		clip.y2 = max(clip.y2, roi_rect->y2);
+
+		SDE_DEBUG("roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n", i,
+				roi_rect->x1, roi_rect->y1,
+				roi_rect->x2, roi_rect->y2,
+				clip.x1, clip.y1,
+				clip.x2, clip.y2);
+	}
+
+	if (clip.x2  && clip.y2) {
+		result->x = clip.x1;
+		result->y = clip.y1;
+		result->w = clip.x2 - clip.x1;
+		result->h = clip.y2 - clip.y1;
+	}
+}
+
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index deca83e..3a6de75 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -2208,274 +2208,17 @@
 		DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
 }
 
-static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
-				struct drm_plane_state *state)
+void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
 {
-	uint32_t nplanes, src_flags;
-	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
-	struct sde_plane_rot_state *rstate;
-	const struct sde_format *fmt;
-	struct drm_crtc *crtc;
-	struct drm_framebuffer *fb;
-	struct sde_rect src, dst;
-	const struct sde_rect *crtc_roi;
-	bool q16_data = true;
-	int idx;
 
-	if (!plane) {
-		SDE_ERROR("invalid plane\n");
-		return -EINVAL;
-	} else if (!plane->state) {
-		SDE_ERROR("invalid plane state\n");
-		return -EINVAL;
-	}
+	if (!drm_state)
+		return;
 
-	psde = to_sde_plane(plane);
-	pstate = to_sde_plane_state(plane->state);
-	rstate = &pstate->rot;
+	pstate = to_sde_plane_state(drm_state);
 
-	crtc = state->crtc;
-	fb = rstate->out_fb;
-	if (!crtc || !fb) {
-		SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
-				crtc != 0, fb != 0);
-		return -EINVAL;
-	}
-	fmt = to_sde_format(msm_framebuffer_format(fb));
-	nplanes = fmt->num_planes;
-
-	SDE_DEBUG(
-		"plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
-			plane->base.id, rstate->sequence_id,
-			rstate->out_fb_width, rstate->out_fb_height,
-			(char *) &rstate->out_fb_pixel_format,
-			rstate->out_fb_modifier[0],
-			rstate->out_src_w >> 16, rstate->out_src_h >> 16,
-			rstate->out_src_x >> 16, rstate->out_src_y >> 16,
-			rstate->out_rotation,
-			state->crtc_w, state->crtc_h,
-			state->crtc_x, state->crtc_y);
-
-	/* force reprogramming of all the parameters, if the flag is set */
-	if (psde->revalidate) {
-		SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
-				plane->base.id);
-		pstate->dirty = SDE_PLANE_DIRTY_ALL;
-		psde->revalidate = false;
-	}
-
-	/* determine what needs to be refreshed */
-	while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
-		switch (idx) {
-		case PLANE_PROP_SCALER_V1:
-		case PLANE_PROP_SCALER_V2:
-		case PLANE_PROP_H_DECIMATE:
-		case PLANE_PROP_V_DECIMATE:
-		case PLANE_PROP_SRC_CONFIG:
-		case PLANE_PROP_ZPOS:
-		case PLANE_PROP_EXCL_RECT_V1:
-			pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-			break;
-		case PLANE_PROP_CSC_V1:
-			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
-			break;
-		case PLANE_PROP_COLOR_FILL:
-			/* potentially need to refresh everything */
-			pstate->dirty = SDE_PLANE_DIRTY_ALL;
-			break;
-		case PLANE_PROP_ROTATION:
-			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
-			break;
-		case PLANE_PROP_INFO:
-		case PLANE_PROP_ALPHA:
-		case PLANE_PROP_INPUT_FENCE:
-		case PLANE_PROP_BLEND_OP:
-			/* no special action required */
-			break;
-		case PLANE_PROP_ROT_DST_X:
-		case PLANE_PROP_ROT_DST_Y:
-		case PLANE_PROP_ROT_DST_W:
-		case PLANE_PROP_ROT_DST_H:
-			/* handled by rotator atomic update */
-			break;
-		default:
-			/* unknown property, refresh everything */
-			pstate->dirty |= SDE_PLANE_DIRTY_ALL;
-			SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
-			break;
-		}
-	}
-
-	/* re-program the output rects always in the case of partial update */
-	sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
-	if (!sde_kms_rect_is_null(crtc_roi))
-		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-
-	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
-		memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
-
-	_sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
-
-	/* early out if nothing dirty */
-	if (!pstate->dirty)
-		return 0;
-	pstate->pending = true;
-
-	psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
-	_sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
-
-	/* update roi config */
-	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
-		POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
-			rstate->out_src_w, rstate->out_src_h, q16_data);
-		POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
-			state->crtc_w, state->crtc_h, !q16_data);
-
-		SDE_DEBUG_PLANE(psde,
-			"FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
-				fb->base.id, src.x, src.y, src.w, src.h,
-				crtc->base.id, dst.x, dst.y, dst.w, dst.h,
-				(char *)&fmt->base.pixel_format,
-				SDE_FORMAT_IS_UBWC(fmt));
-
-		if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
-			BIT(SDE_DRM_DEINTERLACE)) {
-			SDE_DEBUG_PLANE(psde, "deinterlace\n");
-			for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
-				psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
-			src.h /= 2;
-			src.y  = DIV_ROUND_UP(src.y, 2);
-			src.y &= ~0x1;
-		}
-
-		/*
-		 * adjust layer mixer position of the sspp in the presence
-		 * of a partial update to the active lm origin
-		 */
-		dst.x -= crtc_roi->x;
-		dst.y -= crtc_roi->y;
-
-		psde->pipe_cfg.src_rect = src;
-		psde->pipe_cfg.dst_rect = dst;
-
-		_sde_plane_setup_scaler(psde, fmt, pstate);
-
-		/* check for color fill */
-		psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
-				PLANE_PROP_COLOR_FILL);
-		if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
-			/* skip remaining processing on color fill */
-			pstate->dirty = 0x0;
-		} else if (psde->pipe_hw->ops.setup_rects) {
-			psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
-					&psde->pipe_cfg,
-					pstate->multirect_index);
-		}
-
-		if (psde->pipe_hw->ops.setup_pe)
-			psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
-					&psde->pixel_ext);
-
-		if (psde->pipe_hw->ops.setup_scaler)
-			psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
-					&psde->pipe_cfg, &psde->pixel_ext,
-					psde->scaler3_cfg);
-
-		/* update excl rect */
-		if (psde->pipe_hw->ops.setup_excl_rect)
-			psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
-					&pstate->excl_rect,
-					pstate->multirect_index);
-
-		if (psde->pipe_hw->ops.setup_multirect)
-			psde->pipe_hw->ops.setup_multirect(
-					psde->pipe_hw,
-					pstate->multirect_index,
-					pstate->multirect_mode);
-	}
-
-	if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
-			psde->pipe_hw->ops.setup_format) {
-		src_flags = 0x0;
-		SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
-		if (rstate->out_rotation & DRM_REFLECT_X)
-			src_flags |= SDE_SSPP_FLIP_LR;
-		if (rstate->out_rotation & DRM_REFLECT_Y)
-			src_flags |= SDE_SSPP_FLIP_UD;
-
-		/* update format */
-		psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
-				pstate->multirect_index);
-
-		if (psde->pipe_hw->ops.setup_sys_cache) {
-			if (rstate->out_sbuf) {
-				if (rstate->nplane < 2)
-					pstate->sc_cfg.op_mode =
-					SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
-				else if (rstate->out_xpos == 0)
-					pstate->sc_cfg.op_mode =
-						SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
-				else
-					pstate->sc_cfg.op_mode =
-					SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
-
-				pstate->sc_cfg.rd_en = true;
-				pstate->sc_cfg.rd_scid =
-						rstate->rot_hw->caps->scid;
-				pstate->sc_cfg.rd_noallocate = true;
-				pstate->sc_cfg.rd_op_type =
-					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
-			} else {
-				pstate->sc_cfg.op_mode =
-						SDE_PIPE_SC_OP_MODE_OFFLINE;
-				pstate->sc_cfg.rd_en = false;
-				pstate->sc_cfg.rd_scid = 0;
-				pstate->sc_cfg.rd_noallocate = false;
-				pstate->sc_cfg.rd_op_type =
-					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
-			}
-
-			psde->pipe_hw->ops.setup_sys_cache(
-					psde->pipe_hw, &pstate->sc_cfg);
-		}
-
-		/* update csc */
-		if (SDE_FORMAT_IS_YUV(fmt))
-			_sde_plane_setup_csc(psde);
-		else
-			psde->csc_ptr = 0;
-	}
-
-	sde_color_process_plane_setup(plane);
-
-	/* update sharpening */
-	if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
-		psde->pipe_hw->ops.setup_sharpening) {
-		psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
-		psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
-		psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
-		psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
-
-		psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
-				&psde->sharp_cfg);
-	}
-
-	_sde_plane_set_qos_lut(plane, fb);
-	_sde_plane_set_danger_lut(plane, fb);
-
-	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
-		_sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
-		_sde_plane_set_ot_limit(plane, crtc);
-	}
-
-	/* clear dirty */
-	pstate->dirty = 0x0;
-
-	/* clear multirect mode*/
 	pstate->multirect_index = SDE_SSPP_RECT_SOLO;
 	pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
-	return 0;
 }
 
 int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
@@ -2486,11 +2229,12 @@
 	struct sde_plane *sde_plane[R_MAX];
 	const struct sde_format *fmt[R_MAX];
 	bool q16_data = true;
-	int i, max_sspp_linewidth;
-	int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
+	int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
+	bool parallel_fetch_qualified = true;
 
 	for (i = 0; i < R_MAX; i++) {
 		const struct msm_format *msm_fmt;
+		int width_threshold;
 
 		drm_state[i] = i ? plane->r1 : plane->r0;
 		pstate[i] = to_sde_plane_state(drm_state[i]);
@@ -2521,15 +2265,27 @@
 				"Unsupported format for multirect mode\n");
 			return -EINVAL;
 		}
-	}
 
-	max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
+		/**
+		 * SSPP PD_MEM is split half - one for each RECT.
+		 * Tiled formats need 5 lines of buffering while fetching
+		 * whereas linear formats need only 2 lines.
+		 * So we cannot support more than half of the supported SSPP
+		 * width for tiled formats.
+		 */
+		width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
+		if (SDE_FORMAT_IS_UBWC(fmt[i]))
+			width_threshold /= 2;
+
+		if (parallel_fetch_qualified && src[i].w > width_threshold)
+			parallel_fetch_qualified = false;
+
+	}
 
 	/* Validate RECT's and set the mode */
 
 	/* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
-	if (src[R0].w <= max_sspp_linewidth/2 &&
-			src[R1].w <= max_sspp_linewidth/2) {
+	if (parallel_fetch_qualified) {
 		if (dst[R0].x <= dst[R1].x) {
 			pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
 			pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
@@ -2564,6 +2320,10 @@
 	pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
 	pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
 done:
+	SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
+		pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
+	SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
+		pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
 	return 0;
 }
 
@@ -2667,6 +2427,10 @@
 	} else if (to_sde_plane_state(old_state)->pending) {
 		SDE_DEBUG_PLANE(psde, "still pending\n");
 		pstate->dirty |= SDE_PLANE_DIRTY_ALL;
+	} else if (pstate->multirect_index != old_pstate->multirect_index ||
+			pstate->multirect_mode != old_pstate->multirect_mode) {
+		SDE_DEBUG_PLANE(psde, "multirect config updated\n");
+		pstate->dirty |= SDE_PLANE_DIRTY_ALL;
 	} else if (rstate->out_src_w != old_rstate->out_src_w ||
 		   rstate->out_src_h != old_rstate->out_src_h ||
 		   rstate->out_src_x != old_rstate->out_src_x ||
@@ -2685,10 +2449,6 @@
 		   pstate->excl_rect.y != old_pstate->excl_rect.y) {
 		SDE_DEBUG_PLANE(psde, "excl rect updated\n");
 		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-	} else if (pstate->multirect_index != old_pstate->multirect_index ||
-			pstate->multirect_mode != old_pstate->multirect_mode) {
-		SDE_DEBUG_PLANE(psde, "multirect config updated\n");
-		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
 	}
 
 	fb = rstate->out_fb;
@@ -2976,6 +2736,299 @@
 		to_sde_plane_state(plane->state)->pending = false;
 }
 
+static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
+				struct drm_plane_state *old_state)
+{
+	uint32_t nplanes, src_flags;
+	struct sde_plane *psde;
+	struct drm_plane_state *state;
+	struct sde_plane_state *pstate;
+	struct sde_plane_state *old_pstate;
+	struct sde_plane_rot_state *rstate;
+	const struct sde_format *fmt;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	struct sde_rect src, dst;
+	const struct sde_rect *crtc_roi;
+	bool q16_data = true;
+	int idx;
+
+	if (!plane) {
+		SDE_ERROR("invalid plane\n");
+		return -EINVAL;
+	} else if (!plane->state) {
+		SDE_ERROR("invalid plane state\n");
+		return -EINVAL;
+	} else if (!old_state) {
+		SDE_ERROR("invalid old state\n");
+		return -EINVAL;
+	}
+
+	psde = to_sde_plane(plane);
+	state = plane->state;
+
+	pstate = to_sde_plane_state(state);
+	rstate = &pstate->rot;
+
+	old_pstate = to_sde_plane_state(old_state);
+
+	crtc = state->crtc;
+	fb = rstate->out_fb;
+	if (!crtc || !fb) {
+		SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
+				crtc != 0, fb != 0);
+		return -EINVAL;
+	}
+	fmt = to_sde_format(msm_framebuffer_format(fb));
+	nplanes = fmt->num_planes;
+
+	SDE_DEBUG(
+		"plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
+			plane->base.id, rstate->sequence_id,
+			rstate->out_fb_width, rstate->out_fb_height,
+			(char *) &rstate->out_fb_pixel_format,
+			rstate->out_fb_modifier[0],
+			rstate->out_src_w >> 16, rstate->out_src_h >> 16,
+			rstate->out_src_x >> 16, rstate->out_src_y >> 16,
+			rstate->out_rotation,
+			state->crtc_w, state->crtc_h,
+			state->crtc_x, state->crtc_y);
+
+	/* force reprogramming of all the parameters, if the flag is set */
+	if (psde->revalidate) {
+		SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
+				plane->base.id);
+		pstate->dirty = SDE_PLANE_DIRTY_ALL;
+		psde->revalidate = false;
+	}
+
+	/* determine what needs to be refreshed */
+	while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
+		switch (idx) {
+		case PLANE_PROP_SCALER_V1:
+		case PLANE_PROP_SCALER_V2:
+		case PLANE_PROP_H_DECIMATE:
+		case PLANE_PROP_V_DECIMATE:
+		case PLANE_PROP_SRC_CONFIG:
+		case PLANE_PROP_ZPOS:
+		case PLANE_PROP_EXCL_RECT_V1:
+			pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+			break;
+		case PLANE_PROP_CSC_V1:
+			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
+			break;
+		case PLANE_PROP_COLOR_FILL:
+			/* potentially need to refresh everything */
+			pstate->dirty = SDE_PLANE_DIRTY_ALL;
+			break;
+		case PLANE_PROP_ROTATION:
+			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
+			break;
+		case PLANE_PROP_INFO:
+		case PLANE_PROP_ALPHA:
+		case PLANE_PROP_INPUT_FENCE:
+		case PLANE_PROP_BLEND_OP:
+			/* no special action required */
+			break;
+		case PLANE_PROP_ROT_DST_X:
+		case PLANE_PROP_ROT_DST_Y:
+		case PLANE_PROP_ROT_DST_W:
+		case PLANE_PROP_ROT_DST_H:
+			/* handled by rotator atomic update */
+			break;
+		default:
+			/* unknown property, refresh everything */
+			pstate->dirty |= SDE_PLANE_DIRTY_ALL;
+			SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
+			break;
+		}
+	}
+
+	/**
+	 * since plane_atomic_check is invoked before crtc_atomic_check
+	 * in the commit sequence, all the parameters for updating the
+	 * plane dirty flag will not be available during
+	 * plane_atomic_check as some features params are updated
+	 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
+	 * before sspp update.
+	 */
+	_sde_plane_sspp_atomic_check_mode_changed(psde, state,
+								old_state);
+
+	/* re-program the output rects always in the case of partial update */
+	sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
+	if (!sde_kms_rect_is_null(crtc_roi))
+		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+
+	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
+		memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
+
+	_sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
+
+	/* early out if nothing dirty */
+	if (!pstate->dirty)
+		return 0;
+	pstate->pending = true;
+
+	psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
+	_sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
+
+	/* update roi config */
+	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
+		POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
+			rstate->out_src_w, rstate->out_src_h, q16_data);
+		POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
+			state->crtc_w, state->crtc_h, !q16_data);
+
+		SDE_DEBUG_PLANE(psde,
+			"FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
+				fb->base.id, src.x, src.y, src.w, src.h,
+				crtc->base.id, dst.x, dst.y, dst.w, dst.h,
+				(char *)&fmt->base.pixel_format,
+				SDE_FORMAT_IS_UBWC(fmt));
+
+		if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
+			BIT(SDE_DRM_DEINTERLACE)) {
+			SDE_DEBUG_PLANE(psde, "deinterlace\n");
+			for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
+				psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
+			src.h /= 2;
+			src.y  = DIV_ROUND_UP(src.y, 2);
+			src.y &= ~0x1;
+		}
+
+		/*
+		 * adjust layer mixer position of the sspp in the presence
+		 * of a partial update to the active lm origin
+		 */
+		dst.x -= crtc_roi->x;
+		dst.y -= crtc_roi->y;
+
+		psde->pipe_cfg.src_rect = src;
+		psde->pipe_cfg.dst_rect = dst;
+
+		_sde_plane_setup_scaler(psde, fmt, pstate);
+
+		/* check for color fill */
+		psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
+				PLANE_PROP_COLOR_FILL);
+		if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
+			/* skip remaining processing on color fill */
+			pstate->dirty = 0x0;
+		} else if (psde->pipe_hw->ops.setup_rects) {
+			psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
+					&psde->pipe_cfg,
+					pstate->multirect_index);
+		}
+
+		if (psde->pipe_hw->ops.setup_pe)
+			psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
+					&psde->pixel_ext);
+
+		/**
+		 * when programmed in multirect mode, scalar block will be
+		 * bypassed. Still we need to update alpha and bitwidth
+		 * ONLY for RECT0
+		 */
+		if (psde->pipe_hw->ops.setup_scaler &&
+				pstate->multirect_index != SDE_SSPP_RECT_1)
+			psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
+					&psde->pipe_cfg, &psde->pixel_ext,
+					psde->scaler3_cfg);
+
+		/* update excl rect */
+		if (psde->pipe_hw->ops.setup_excl_rect)
+			psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
+					&pstate->excl_rect,
+					pstate->multirect_index);
+
+		if (psde->pipe_hw->ops.setup_multirect)
+			psde->pipe_hw->ops.setup_multirect(
+					psde->pipe_hw,
+					pstate->multirect_index,
+					pstate->multirect_mode);
+	}
+
+	if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
+			psde->pipe_hw->ops.setup_format) {
+		src_flags = 0x0;
+		SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
+		if (rstate->out_rotation & DRM_REFLECT_X)
+			src_flags |= SDE_SSPP_FLIP_LR;
+		if (rstate->out_rotation & DRM_REFLECT_Y)
+			src_flags |= SDE_SSPP_FLIP_UD;
+
+		/* update format */
+		psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
+				pstate->multirect_index);
+
+		if (psde->pipe_hw->ops.setup_sys_cache) {
+			if (rstate->out_sbuf) {
+				if (rstate->nplane < 2)
+					pstate->sc_cfg.op_mode =
+					SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
+				else if (rstate->out_xpos == 0)
+					pstate->sc_cfg.op_mode =
+						SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
+				else
+					pstate->sc_cfg.op_mode =
+					SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
+
+				pstate->sc_cfg.rd_en = true;
+				pstate->sc_cfg.rd_scid =
+						rstate->rot_hw->caps->scid;
+				pstate->sc_cfg.rd_noallocate = true;
+				pstate->sc_cfg.rd_op_type =
+					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
+			} else {
+				pstate->sc_cfg.op_mode =
+						SDE_PIPE_SC_OP_MODE_OFFLINE;
+				pstate->sc_cfg.rd_en = false;
+				pstate->sc_cfg.rd_scid = 0;
+				pstate->sc_cfg.rd_noallocate = false;
+				pstate->sc_cfg.rd_op_type =
+					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
+			}
+
+			psde->pipe_hw->ops.setup_sys_cache(
+					psde->pipe_hw, &pstate->sc_cfg);
+		}
+
+		/* update csc */
+		if (SDE_FORMAT_IS_YUV(fmt))
+			_sde_plane_setup_csc(psde);
+		else
+			psde->csc_ptr = 0;
+	}
+
+	sde_color_process_plane_setup(plane);
+
+	/* update sharpening */
+	if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
+		psde->pipe_hw->ops.setup_sharpening) {
+		psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
+		psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
+		psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
+		psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
+
+		psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
+				&psde->sharp_cfg);
+	}
+
+	_sde_plane_set_qos_lut(plane, fb);
+	_sde_plane_set_danger_lut(plane, fb);
+
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		_sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
+		_sde_plane_set_ot_limit(plane, crtc);
+	}
+
+	/* clear dirty */
+	pstate->dirty = 0x0;
+
+	return 0;
+}
+
 static void sde_plane_atomic_update(struct drm_plane *plane,
 				struct drm_plane_state *old_state)
 {
@@ -3007,7 +3060,7 @@
 	} else {
 		int ret;
 
-		ret = sde_plane_sspp_atomic_update(plane, state);
+		ret = sde_plane_sspp_atomic_update(plane, old_state);
 		/* atomic_check should have ensured that this doesn't fail */
 		WARN_ON(ret < 0);
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index ac70542..2056a70 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -207,10 +207,15 @@
  *				      against hw limitations
  * @plane: drm plate states of the multirect pair
  */
-
 int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane);
 
 /**
+ * sde_plane_clear_multirect - clear multirect bits for the given pipe
+ * @drm_state: Pointer to DRM plane state
+ */
+void sde_plane_clear_multirect(const struct drm_plane_state *drm_state);
+
+/**
  * sde_plane_wait_input_fence - wait for input fence object
  * @plane:   Pointer to DRM plane object
  * @wait_ms: Wait timeout value
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index da68139..38bf21f 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -16,9 +16,9 @@
 
 #define MAX_CLIENT_NAME_LEN 128
 
-#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA	2000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA	6000000000
 #define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA	0
-#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA	2000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA	6000000000
 #define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA	0
 
 #include <linux/sde_io_util.h>
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 3413ee7..50710cd 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -416,6 +416,11 @@
 	if (config)
 		sde_rsc_timer_calculate(rsc, config);
 
+	if (rsc->current_state == SDE_RSC_CMD_STATE) {
+		rc = 0;
+		goto vsync_wait;
+	}
+
 	/* any one client in video state blocks the cmd state switch */
 	list_for_each_entry(client, &rsc->client_list, list)
 		if (client->current_state == SDE_RSC_VID_STATE)
@@ -427,8 +432,10 @@
 			rpmh_mode_solver_set(rsc->disp_rsc, true);
 	}
 
-	/* wait for vsync for vid to cmd state switch */
-	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
+vsync_wait:
+	/* wait for vsync for vid to cmd state switch and config update */
+	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
+			rsc->current_state == SDE_RSC_CMD_STATE))
 		drm_wait_one_vblank(rsc->master_drm,
 						rsc->primary_client->crtc_id);
 end:
@@ -470,6 +477,10 @@
 	if (config && (caller_client == rsc->primary_client))
 		sde_rsc_timer_calculate(rsc, config);
 
+	/* early exit without vsync wait for vid state */
+	if (rsc->current_state == SDE_RSC_VID_STATE)
+		goto end;
+
 	/* video state switch should be done immediately */
 	if (rsc->hw_ops.state_update) {
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
@@ -482,6 +493,8 @@
 			(rsc->current_state == SDE_RSC_CMD_STATE))
 		drm_wait_one_vblank(rsc->master_drm,
 						rsc->primary_client->crtc_id);
+
+end:
 	return rc;
 }
 
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 6db0111..e5cfd69 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -381,6 +381,7 @@
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_1             0x508
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_2             0x509
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_3             0x50A
+#define A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED        0x50B
 
 #define A6XX_RBBM_ISDB_CNT                       0x533
 
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 98ca77f..24b5faa 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -385,6 +385,10 @@
 
 	adreno_vbif_start(adreno_dev, a6xx_vbif_platforms,
 			ARRAY_SIZE(a6xx_vbif_platforms));
+
+	/* Make all blocks contribute to the GPU BUSY perf counter */
+	kgsl_regwrite(device, A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
 	/*
 	 * Set UCHE_WRITE_THRU_BASE to the UCHE_TRAP_BASE effectively
 	 * disabling L2 bypass
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 63dbde0..17ee6e6 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -640,6 +640,9 @@
 	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
 	int i, j;
 
+	if (!device->snapshot_legacy)
+		return 0;
+
 	if (remain < sizeof(*header)) {
 		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
 		return 0;
@@ -748,6 +751,9 @@
 	unsigned int read_sel;
 	int i, j;
 
+	if (!device->snapshot_legacy)
+		return 0;
+
 	/* Figure out how many registers we are going to dump */
 	for (i = 0; i < regs->num_sets; i++) {
 		int start = regs->regs[i * 2];
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 876b668..be379e3 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -291,6 +291,8 @@
 
 	/* Use CP Crash dumper to get GPU snapshot*/
 	bool snapshot_crashdumper;
+	/* Use HOST side register reads to get GPU snapshot*/
+	bool snapshot_legacy;
 
 	struct kobject snapshot_kobj;
 
diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c
index 30e1d7c..b05e18d 100644
--- a/drivers/gpu/msm/kgsl_hfi.c
+++ b/drivers/gpu/msm/kgsl_hfi.c
@@ -573,44 +573,41 @@
 	if (result)
 		return result;
 
-	if (boot_state == GMU_COLD_BOOT) {
-		major = adreno_dev->gpucore->gpmu_major;
-		minor = adreno_dev->gpucore->gpmu_minor;
+	major = adreno_dev->gpucore->gpmu_major;
+	minor = adreno_dev->gpucore->gpmu_minor;
+	result = hfi_get_fw_version(gmu,
+			FW_VERSION(major, minor), &ver);
+	if (result)
+		dev_err(dev, "Failed to get FW version via HFI\n");
 
-		result = hfi_get_fw_version(gmu,
-				FW_VERSION(major, minor), &ver);
-		if (result)
-			dev_err(dev, "Failed to get FW version via HFI\n");
+	gmu->ver = ver;
+	if (major != FW_VER_MAJOR(ver))
+		dev_err(dev, "FW version major %d error (expect %d)\n",
+				FW_VER_MAJOR(ver),
+				adreno_dev->gpucore->gpmu_major);
 
-		gmu->ver = ver;
-		if (major != FW_VER_MAJOR(ver))
-			dev_err(dev, "FW version major %d error (expect %d)\n",
-					FW_VER_MAJOR(ver),
-					adreno_dev->gpucore->gpmu_major);
+	if (minor > FW_VER_MINOR(ver))
+		dev_err(dev, "FW version minor %d error (expect %d)\n",
+				FW_VER_MINOR(ver),
+				adreno_dev->gpucore->gpmu_minor);
 
-		if (minor > FW_VER_MINOR(ver))
-			dev_err(dev, "FW version minor %d error (expect %d)\n",
-					FW_VER_MINOR(ver),
-					adreno_dev->gpucore->gpmu_minor);
+	result = hfi_send_perftbl(gmu);
+	if (result)
+		return result;
 
-		result = hfi_send_perftbl(gmu);
-		if (result)
-			return result;
+	result = hfi_send_bwtbl(gmu);
+	if (result)
+		return result;
 
-		result = hfi_send_bwtbl(gmu);
-		if (result)
-			return result;
-
-		/*
-		 * FW is not ready for LM configuration
-		 * without powering on GPU.
-		 */
-		/*
-		 * result = hfi_send_lmconfig(gmu);
-		 * if (result)
-		 * return result;
-		 */
-	}
+	/*
+	 * FW is not ready for LM configuration
+	 * without powering on GPU.
+	 */
+	/*
+	 * result = hfi_send_lmconfig(gmu);
+	 * if (result)
+	 * return result;
+	 */
 
 	set_bit(GMU_HFI_ON, &gmu->flags);
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 40d239c..7cbda72 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -875,6 +875,25 @@
 	return snprintf(buf, PAGE_SIZE, "%lu\n", timestamp);
 }
 
+static ssize_t snapshot_legacy_show(struct kgsl_device *device, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_legacy);
+}
+
+static ssize_t snapshot_legacy_store(struct kgsl_device *device,
+	const char *buf, size_t count)
+{
+	unsigned int val = 0;
+	int ret;
+
+	ret = kgsl_sysfs_store(buf, &val);
+
+	if (!ret && device)
+		device->snapshot_legacy = (bool)val;
+
+	return (ssize_t) ret < 0 ? ret : count;
+}
+
 static struct bin_attribute snapshot_attr = {
 	.attr.name = "dump",
 	.attr.mode = 0444,
@@ -894,6 +913,8 @@
 static SNAPSHOT_ATTR(force_panic, 0644, force_panic_show, force_panic_store);
 static SNAPSHOT_ATTR(snapshot_crashdumper, 0644, snapshot_crashdumper_show,
 	snapshot_crashdumper_store);
+static SNAPSHOT_ATTR(snapshot_legacy, 0644, snapshot_legacy_show,
+	snapshot_legacy_store);
 
 static ssize_t snapshot_sysfs_show(struct kobject *kobj,
 	struct attribute *attr, char *buf)
@@ -975,6 +996,7 @@
 	device->snapshot_faultcount = 0;
 	device->force_panic = 0;
 	device->snapshot_crashdumper = 1;
+	device->snapshot_legacy = 0;
 
 	ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
 		&device->dev->kobj, "snapshot");
@@ -1000,6 +1022,12 @@
 
 	ret  = sysfs_create_file(&device->snapshot_kobj,
 			&attr_snapshot_crashdumper.attr);
+	if (ret)
+		goto done;
+
+	ret  = sysfs_create_file(&device->snapshot_kobj,
+			&attr_snapshot_legacy.attr);
+
 done:
 	return ret;
 }
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index c5ab866..2db0d64 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -432,13 +432,12 @@
 	return ret;
 }
 
-dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
-		unsigned long offset, size_t size, int prot)
+static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
+		size_t size, int prot)
 {
 	dma_addr_t dma_addr;
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 	struct iova_domain *iovad = cookie_iovad(domain);
-	phys_addr_t phys = page_to_phys(page) + offset;
 	size_t iova_off = iova_offset(iovad, phys);
 	size_t len = iova_align(iovad, size + iova_off);
 	struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
@@ -454,6 +453,12 @@
 	return dma_addr + iova_off;
 }
 
+dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
+		unsigned long offset, size_t size, int prot)
+{
+	return __iommu_dma_map(dev, page_to_phys(page) + offset, size, prot);
+}
+
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
 		enum dma_data_direction dir, unsigned long attrs)
 {
@@ -624,6 +629,19 @@
 	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
 }
 
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+	return __iommu_dma_map(dev, phys, size,
+			dma_direction_to_prot(dir, false) | IOMMU_MMIO);
+}
+
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+}
+
 int iommu_dma_supported(struct device *dev, u64 mask)
 {
 	/*
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index 8ba6da4..ac3059d 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -611,6 +611,55 @@
 	return ret;
 }
 
+static dma_addr_t fast_smmu_dma_map_resource(
+			struct device *dev, phys_addr_t phys_addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast;
+	size_t offset = phys_addr & ~FAST_PAGE_MASK;
+	size_t len = round_up(size + offset, FAST_PAGE_SIZE);
+	dma_addr_t dma_addr;
+	int prot;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mapping->lock, flags);
+	dma_addr = __fast_smmu_alloc_iova(mapping, attrs, len);
+	spin_unlock_irqrestore(&mapping->lock, flags);
+
+	if (dma_addr == DMA_ERROR_CODE)
+		return dma_addr;
+
+	prot = __fast_dma_direction_to_prot(dir);
+	prot |= IOMMU_MMIO;
+
+	if (iommu_map(mapping->domain, dma_addr, phys_addr - offset,
+			len, prot)) {
+		spin_lock_irqsave(&mapping->lock, flags);
+		__fast_smmu_free_iova(mapping, dma_addr, len);
+		spin_unlock_irqrestore(&mapping->lock, flags);
+		return DMA_ERROR_CODE;
+	}
+	return dma_addr + offset;
+}
+
+static void fast_smmu_dma_unmap_resource(
+			struct device *dev, dma_addr_t addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast;
+	size_t offset = addr & ~FAST_PAGE_MASK;
+	size_t len = round_up(size + offset, FAST_PAGE_SIZE);
+	unsigned long flags;
+
+	iommu_unmap(mapping->domain, addr - offset, len);
+	spin_lock_irqsave(&mapping->lock, flags);
+	__fast_smmu_free_iova(mapping, addr, len);
+	spin_unlock_irqrestore(&mapping->lock, flags);
+}
+
+
 static int fast_smmu_dma_supported(struct device *dev, u64 mask)
 {
 	return mask <= 0xffffffff;
@@ -667,6 +716,8 @@
 	.unmap_sg = fast_smmu_unmap_sg,
 	.sync_sg_for_cpu = fast_smmu_sync_sg_for_cpu,
 	.sync_sg_for_device = fast_smmu_sync_sg_for_device,
+	.map_resource = fast_smmu_dma_map_resource,
+	.unmap_resource = fast_smmu_dma_unmap_resource,
 	.dma_supported = fast_smmu_dma_supported,
 	.mapping_error = fast_smmu_mapping_error,
 };
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 7a03bdc..c837232 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
@@ -974,7 +974,7 @@
 						del_req_id, rc);
 			}
 		} else {
-			pr_err("%s:%d Invalid/NOP request to apply: %lld\n",
+			CDBG("%s:%d Invalid/NOP request to apply: %lld\n",
 				__func__, __LINE__, req_id);
 		}
 	}
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 1709fd3..40a69ef 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
@@ -146,11 +146,9 @@
 	for (i = 0; i < delay_ms; i++) {
 		rc = cam_cci_i2c_compare(client,
 			addr, data, data_mask, data_type, addr_type);
-		if (!rc) {
-			pr_err("%s:%d Fail in comparing the data in poll\n",
-				__func__, __LINE__);
+		if (!rc)
 			return rc;
-		}
+
 		usleep_range(1000, 1010);
 	}
 
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
index db12cae..d6297d4 100644
--- a/drivers/media/platform/msm/vidc/Kconfig
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -7,5 +7,4 @@
 		depends on ARCH_QCOM && VIDEO_V4L2
 		select VIDEOBUF2_CORE
 
-source "drivers/media/platform/msm/vidc/vmem/Kconfig"
 source "drivers/media/platform/msm/vidc/governors/Kconfig"
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 12b5b04..f7ce757 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
@@ -22,8 +22,7 @@
 
 enum governor_mode {
 	GOVERNOR_DDR,
-	GOVERNOR_VMEM,
-	GOVERNOR_VMEM_PLUS,
+	GOVERNOR_LLCC,
 };
 
 struct governor {
@@ -275,38 +274,6 @@
 	}
 }
 
-static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
-{
-	unsigned long i = 0, vmem_plus = 0;
-
-	if (!d->imem_ab_tbl || !d->imem_ab_tbl_size) {
-		vmem_plus = 1; /* Vote for the min ab value */
-		goto exit;
-	}
-
-	/* Pick up vmem frequency based on venus core frequency */
-	for (i = 0; i < d->imem_ab_tbl_size; i++) {
-		if (d->imem_ab_tbl[i].core_freq == d->core_freq) {
-			vmem_plus = d->imem_ab_tbl[i].imem_ab;
-			break;
-		}
-	}
-
-	/*
-	 * Incase we get an unsupported freq throw a warning
-	 * and set ab to the minimum value.
-	 */
-	if (!vmem_plus) {
-		vmem_plus = 1;
-		dprintk(VIDC_WARN,
-			"could not calculate vmem ab value due to core freq mismatch\n");
-		WARN_ON(1);
-	}
-
-exit:
-	return vmem_plus;
-}
-
 static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
 		enum governor_mode gm) {
 	/*
@@ -611,12 +578,9 @@
 	case GOVERNOR_DDR:
 		ret = kbps(fp_round(ddr.total));
 		break;
-	case GOVERNOR_VMEM:
+	case GOVERNOR_LLCC:
 		ret = kbps(fp_round(vmem.total));
 		break;
-	case GOVERNOR_VMEM_PLUS:
-		ret = __calculate_vmem_plus_ab(d);
-		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
 	}
@@ -1016,12 +980,9 @@
 	case GOVERNOR_DDR:
 		ret = kbps(fp_round(ddr.total));
 		break;
-	case GOVERNOR_VMEM:
+	case GOVERNOR_LLCC:
 		ret = kbps(fp_round(vmem.total));
 		break;
-	case GOVERNOR_VMEM_PLUS:
-		ret = __calculate_vmem_plus_ab(d);
-		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
 	}
@@ -1107,17 +1068,9 @@
 		},
 	},
 	{
-		.mode = GOVERNOR_VMEM,
+		.mode = GOVERNOR_LLCC,
 		.devfreq_gov = {
-			.name = "msm-vidc-vmem",
-			.get_target_freq = __get_target_freq,
-			.event_handler = __event_handler,
-		},
-	},
-	{
-		.mode = GOVERNOR_VMEM_PLUS,
-		.devfreq_gov = {
-			.name = "msm-vidc-vmem+",
+			.name = "msm-vidc-llcc",
 			.get_target_freq = __get_target_freq,
 			.event_handler = __event_handler,
 		},
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 9331c94..a477340 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -332,37 +332,56 @@
 
 int create_pkt_cmd_sys_set_resource(
 		struct hfi_cmd_sys_set_resource_packet *pkt,
-		struct vidc_resource_hdr *resource_hdr,
-		void *resource_value)
+		struct vidc_resource_hdr *res_hdr,
+		void *res_value)
 {
 	int rc = 0;
+	u32 i = 0;
 
-	if (!pkt || !resource_hdr || !resource_value)
+	if (!pkt || !res_hdr || !res_value) {
+		dprintk(VIDC_ERR,
+			"Invalid paramas pkt %pK res_hdr %pK res_value %pK\n",
+				pkt, res_hdr, res_value);
 		return -EINVAL;
+	}
 
 	pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
 	pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
-	pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+	pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
 
-	switch (resource_hdr->resource_id) {
-	case VIDC_RESOURCE_OCMEM:
-	case VIDC_RESOURCE_VMEM:
+	switch (res_hdr->resource_id) {
+	case VIDC_RESOURCE_SYSCACHE:
 	{
-		struct hfi_resource_ocmem *hfioc_mem =
-			(struct hfi_resource_ocmem *)
-			&pkt->rg_resource_data[0];
+		struct hfi_resource_syscache_info_type *res_sc_info =
+			(struct hfi_resource_syscache_info_type *) res_value;
+		struct hfi_resource_subcache_type *res_sc =
+			(struct hfi_resource_subcache_type *)
+				&(res_sc_info->rg_subcache_entries[0]);
 
-		phys_addr_t imem_addr = (phys_addr_t)resource_value;
+		struct hfi_resource_syscache_info_type *hfi_sc_info =
+			(struct hfi_resource_syscache_info_type *)
+				&pkt->rg_resource_data[0];
 
-		pkt->resource_type = HFI_RESOURCE_OCMEM;
-		pkt->size += sizeof(struct hfi_resource_ocmem) - sizeof(u32);
-		hfioc_mem->size = (u32)resource_hdr->size;
-		hfioc_mem->mem = imem_addr;
+		struct hfi_resource_subcache_type *hfi_sc =
+			(struct hfi_resource_subcache_type *)
+			&(hfi_sc_info->rg_subcache_entries[0]);
+
+		pkt->resource_type = HFI_RESOURCE_SYSCACHE;
+		hfi_sc_info->num_entries = res_sc_info->num_entries;
+
+		pkt->size += (sizeof(struct hfi_resource_subcache_type))
+				 * hfi_sc_info->num_entries;
+
+		for (i = 0; i < hfi_sc_info->num_entries; i++) {
+			hfi_sc[i] = res_sc[i];
+		dprintk(VIDC_DBG, "entry hfi#%d, sc_id %d, size %d\n",
+				 i, hfi_sc[i].sc_id, hfi_sc[i].size);
+		}
 		break;
 	}
 	default:
-		dprintk(VIDC_ERR, "Invalid resource_id %d\n",
-					resource_hdr->resource_id);
+		dprintk(VIDC_ERR,
+			"Invalid resource_id %d\n", res_hdr->resource_id);
 		rc = -ENOTSUPP;
 	}
 
@@ -371,28 +390,35 @@
 
 int create_pkt_cmd_sys_release_resource(
 		struct hfi_cmd_sys_release_resource_packet *pkt,
-		struct vidc_resource_hdr *resource_hdr)
+		struct vidc_resource_hdr *res_hdr)
 {
 	int rc = 0;
 
-	if (!pkt)
+	if (!pkt || !res_hdr) {
+		dprintk(VIDC_ERR,
+			"Invalid paramas pkt %pK res_hdr %pK\n",
+				pkt, res_hdr);
 		return -EINVAL;
+	}
 
 	pkt->size = sizeof(struct hfi_cmd_sys_release_resource_packet);
 	pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
-	pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+	pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
 
-	switch (resource_hdr->resource_id) {
-	case VIDC_RESOURCE_OCMEM:
-	case VIDC_RESOURCE_VMEM:
-		pkt->resource_type = HFI_RESOURCE_OCMEM;
+	switch (res_hdr->resource_id) {
+	case VIDC_RESOURCE_SYSCACHE:
+		pkt->resource_type = HFI_RESOURCE_SYSCACHE;
 		break;
 	default:
-		dprintk(VIDC_ERR, "Invalid resource_id %d\n",
-					resource_hdr->resource_id);
+		dprintk(VIDC_ERR,
+			 "Invalid resource_id %d\n", res_hdr->resource_id);
 		rc = -ENOTSUPP;
 	}
 
+	dprintk(VIDC_DBG,
+		"rel_res: pkt_type 0x%x res_type 0x%x prepared\n",
+		pkt->packet_type, pkt->resource_type);
+
 	return rc;
 }
 
@@ -1837,6 +1863,14 @@
 		pkt->size += sizeof(u32) + sizeof(*work_mode);
 		break;
 	}
+	case HAL_PARAM_USE_SYS_CACHE:
+	{
+		create_pkt_enable(pkt->rg_property_data,
+			HFI_PROPERTY_PARAM_USE_SYS_CACHE,
+			(((struct hal_enable *) pdata)->enable));
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
 	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
 	case HAL_CONFIG_BUFFER_REQUIREMENTS:
 	case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 19a1e3f..3d3d567 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -94,9 +94,11 @@
 		trace_msm_smem_buffer_iommu_op_start("MAP", 0, 0,
 			align, *iova, *buffer_size);
 
-		/* Map a scatterlist into an SMMU */
-		rc = msm_dma_map_sg_lazy(cb->dev, table->sgl, table->nents,
-				DMA_BIDIRECTIONAL, buf);
+		/* Map a scatterlist into an SMMU with system cacheability */
+		rc = msm_dma_map_sg_attrs(cb->dev, table->sgl,
+			table->nents, DMA_BIDIRECTIONAL,
+			buf, DMA_ATTR_IOMMU_USE_UPSTREAM_HINT);
+
 		if (rc != table->nents) {
 			dprintk(VIDC_ERR,
 				"Mapping failed with rc(%d), expected rc(%d)\n",
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 89da0a1..2289b23 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1449,6 +1449,8 @@
 		}
 	}
 
+	msm_comm_set_use_sys_cache(inst);
+
 	/*
 	 * For seq_changed_insufficient, driver should set session_continue
 	 * to firmware after the following sequence
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 25cc1e4..a52fe05 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -968,6 +968,8 @@
 
 decision_done:
 	core_info.video_core_enable_mask = inst->clk_data.core_id;
+	dprintk(VIDC_DBG,
+		"Core Enable Mask %d\n", core_info.video_core_enable_mask);
 
 	rc = call_hfi_op(hdev, session_set_property,
 			(void *)inst->session,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 7b75d70..c0bbfbb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -5553,3 +5553,41 @@
 {
 	return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
 }
+
+void msm_comm_set_use_sys_cache(struct msm_vidc_inst *inst)
+{
+	struct hal_enable syscache_use;
+	int rc = 0;
+
+
+	if (!inst->core->resources.sys_cache_enabled)
+		goto exit;
+
+	syscache_use.enable = false;
+	inst->clk_data.use_sys_cache = false;
+
+	if (inst->flags & VIDC_REALTIME)
+		syscache_use.enable = true;
+
+	if (inst->flags & VIDC_THUMBNAIL)
+		syscache_use.enable = false;
+
+	dprintk(VIDC_DBG,
+		"set_use_sys_cache: enable = %d inst = %pK flags =%d\n",
+		syscache_use.enable, inst, inst->flags);
+	rc = msm_comm_try_set_prop(inst, HAL_PARAM_USE_SYS_CACHE,
+		&syscache_use);
+	if (rc) {
+		dprintk(VIDC_ERR, "set_use_sys_cache: failed!!\n");
+			inst->clk_data.use_sys_cache = false;
+		goto exit;
+	}
+
+	inst->clk_data.use_sys_cache = syscache_use.enable;
+
+	return;
+
+exit:
+	return;
+}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 61df652..7534593 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -103,4 +103,5 @@
 u32 get_frame_size_rgba(int plane, u32 height, u32 width);
 u32 get_frame_size_nv21(int plane, u32 height, u32 width);
 u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width);
+void msm_comm_set_use_sys_cache(struct msm_vidc_inst *inst);
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 37bccbd..17c3045 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -224,6 +224,7 @@
 	u32 core_id;
 	enum hal_work_mode work_mode;
 	bool low_latency_mode;
+	bool use_sys_cache;
 };
 
 struct profile_data {
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 0a6de41..5cf4628 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -59,19 +59,6 @@
 	return 0;
 }
 
-static inline enum imem_type read_imem_type(struct platform_device *pdev)
-{
-	bool is_compatible(char *compat)
-	{
-		return !!of_find_compatible_node(NULL, NULL, compat);
-	}
-
-	return is_compatible("qcom,msm-ocmem") ? IMEM_OCMEM :
-		is_compatible("qcom,msm-vmem") ? IMEM_VMEM :
-						IMEM_NONE;
-
-}
-
 static inline void msm_vidc_free_allowed_clocks_table(
 		struct msm_vidc_platform_resources *res)
 {
@@ -90,12 +77,6 @@
 	res->pf_ver_tbl = NULL;
 }
 
-static inline void msm_vidc_free_imem_ab_table(
-		struct msm_vidc_platform_resources *res)
-{
-	res->imem_ab_tbl = NULL;
-}
-
 static inline void msm_vidc_free_reg_table(
 			struct msm_vidc_platform_resources *res)
 {
@@ -262,43 +243,48 @@
 	return rc;
 }
 
-static int msm_vidc_load_imem_ab_table(struct msm_vidc_platform_resources *res)
+static int msm_vidc_load_subcache_info(struct msm_vidc_platform_resources *res)
 {
-	int num_elements = 0;
+	int rc = 0, num_subcaches = 0, c;
 	struct platform_device *pdev = res->pdev;
+	struct subcache_set *subcaches = &res->subcache_set;
 
-	if (!of_find_property(pdev->dev.of_node, "qcom,imem-ab-tbl", NULL)) {
-		/* optional property */
-		dprintk(VIDC_DBG, "qcom,imem-freq-tbl not found\n");
-		return 0;
+	num_subcaches = of_property_count_strings(pdev->dev.of_node,
+		"cache-slice-names");
+	if (num_subcaches <= 0) {
+		dprintk(VIDC_DBG, "No subcaches found\n");
+		goto err_load_subcache_table_fail;
 	}
 
-	num_elements = get_u32_array_num_elements(pdev->dev.of_node,
-			"qcom,imem-ab-tbl");
-	num_elements /= (sizeof(*res->imem_ab_tbl) / sizeof(u32));
-	if (!num_elements) {
-		dprintk(VIDC_ERR, "no elements in imem ab table\n");
-		return -EINVAL;
+	subcaches->subcache_tbl = devm_kzalloc(&pdev->dev,
+		sizeof(*subcaches->subcache_tbl) * num_subcaches, GFP_KERNEL);
+	if (!subcaches->subcache_tbl) {
+		dprintk(VIDC_ERR,
+			"Failed to allocate memory for subcache tbl\n");
+		rc = -ENOMEM;
+		goto err_load_subcache_table_fail;
 	}
 
-	res->imem_ab_tbl = devm_kzalloc(&pdev->dev, num_elements *
-			sizeof(*res->imem_ab_tbl), GFP_KERNEL);
-	if (!res->imem_ab_tbl) {
-		dprintk(VIDC_ERR, "Failed to alloc imem_ab_tbl\n");
-		return -ENOMEM;
+	subcaches->count = num_subcaches;
+	dprintk(VIDC_DBG, "Found %d subcaches\n", num_subcaches);
+
+	for (c = 0; c < num_subcaches; ++c) {
+		struct subcache_info *vsc = &res->subcache_set.subcache_tbl[c];
+
+		of_property_read_string_index(pdev->dev.of_node,
+			"cache-slice-names", c, &vsc->name);
 	}
 
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,imem-ab-tbl", (u32 *)res->imem_ab_tbl,
-		num_elements * sizeof(*res->imem_ab_tbl) / sizeof(u32))) {
-		dprintk(VIDC_ERR, "Failed to read imem_ab_tbl\n");
-		msm_vidc_free_imem_ab_table(res);
-		return -EINVAL;
-	}
-
-	res->imem_ab_tbl_size = num_elements;
+	res->sys_cache_enabled = true;
 
 	return 0;
+
+err_load_subcache_table_fail:
+	res->sys_cache_enabled = false;
+	subcaches->count = 0;
+	subcaches->subcache_tbl = NULL;
+
+	return rc;
 }
 
 /**
@@ -856,10 +842,6 @@
 	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	res->irq = kres ? kres->start : -1;
 
-	of_property_read_u32(pdev->dev.of_node,
-			"qcom,imem-size", &res->imem_size);
-	res->imem_type = read_imem_type(pdev);
-
 	res->sys_idle_indicator = of_property_read_bool(pdev->dev.of_node,
 			"qcom,enable-idle-indicator");
 
@@ -884,9 +866,9 @@
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to load pf version table: %d\n", rc);
 
-	rc = msm_vidc_load_imem_ab_table(res);
+	rc = msm_vidc_load_subcache_info(res);
 	if (rc)
-		dprintk(VIDC_WARN, "Failed to load freq table: %d\n", rc);
+		dprintk(VIDC_WARN, "Failed to load subcache info: %d\n", rc);
 
 	rc = msm_vidc_load_qdss_table(res);
 	if (rc)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 20b0ffc..d76985e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -17,6 +17,8 @@
 #include <linux/devfreq.h>
 #include <linux/platform_device.h>
 #include <media/msm_vidc.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
 #define MAX_BUFFER_TYPES 32
 
 struct platform_version_table {
@@ -36,11 +38,6 @@
 	u32 fps;
 };
 
-struct imem_ab_table {
-	u32 core_freq;
-	u32 imem_ab;
-};
-
 struct reg_value_pair {
 	u32 reg;
 	u32 value;
@@ -122,13 +119,6 @@
 	u32 count;
 };
 
-enum imem_type {
-	IMEM_NONE,
-	IMEM_OCMEM,
-	IMEM_VMEM,
-	IMEM_MAX,
-};
-
 struct allowed_clock_rates_table {
 	u32 clock_rate;
 };
@@ -145,6 +135,18 @@
 	u32 count;
 };
 
+struct subcache_info {
+	const char *name;
+	bool isactive;
+	bool isset;
+	struct llcc_slice_desc *subcache;
+};
+
+struct subcache_set {
+	struct subcache_info *subcache_tbl;
+	u32 count;
+};
+
 struct msm_vidc_platform_resources {
 	phys_addr_t firmware_base;
 	phys_addr_t register_base;
@@ -157,13 +159,11 @@
 	struct dcvs_table *dcvs_tbl;
 	uint32_t dcvs_tbl_size;
 	struct dcvs_limit *dcvs_limit;
-	struct imem_ab_table *imem_ab_tbl;
-	u32 imem_ab_tbl_size;
+	bool sys_cache_enabled;
+	struct subcache_set subcache_set;
 	struct reg_set reg_set;
 	struct addr_set qdss_addr_set;
 	struct buffer_usage_set buffer_usage_set;
-	uint32_t imem_size;
-	enum imem_type imem_type;
 	uint32_t max_load;
 	uint32_t max_hq_mbs_per_frame;
 	uint32_t max_hq_fps;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 1a1078d..5a8dd26 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -27,6 +27,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
 #include <soc/qcom/scm.h>
 #include <soc/qcom/smem.h>
 #include <soc/qcom/subsystem_restart.h>
@@ -72,7 +74,6 @@
 const struct msm_vidc_gov_data DEFAULT_BUS_VOTE = {
 	.data = NULL,
 	.data_count = 0,
-	.imem_size = 0,
 };
 
 const int max_packets = 1000;
@@ -95,6 +96,8 @@
 static int __load_fw(struct venus_hfi_device *device);
 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 __disable_subcaches(struct venus_hfi_device *device);
 
 
 /**
@@ -875,7 +878,6 @@
 	kfree(device->bus_vote.data);
 	device->bus_vote.data = new_data;
 	device->bus_vote.data_count = num_data;
-	device->bus_vote.imem_size = device->res->imem_size;
 
 	venus_hfi_for_each_bus(device, bus) {
 		if (bus && bus->devfreq) {
@@ -939,140 +941,33 @@
 	return rc;
 }
 
-static int __alloc_imem(struct venus_hfi_device *device, unsigned long size)
+static int __core_release_resource(struct venus_hfi_device *device,
+		struct vidc_resource_hdr *resource_hdr)
 {
-	struct imem *imem = NULL;
+	struct hfi_cmd_sys_release_resource_packet *pkt;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
 	int rc = 0;
 
-	if (!device)
-		return -EINVAL;
-
-	imem = &device->resources.imem;
-	if (imem->type) {
-		dprintk(VIDC_ERR, "IMEM of type %d already allocated\n",
-				imem->type);
-		return -ENOMEM;
-	}
-
-	switch (device->res->imem_type) {
-	case IMEM_VMEM:
-	{
-		phys_addr_t vmem_buffer = 0;
-
-		rc = vmem_allocate(size, &vmem_buffer);
-		if (rc) {
-			if (rc == -ENOTSUPP) {
-				dprintk(VIDC_DBG,
-					"Target does not support vmem\n");
-				rc = 0;
-			}
-			goto imem_alloc_failed;
-		} else if (!vmem_buffer) {
-			rc = -ENOMEM;
-			goto imem_alloc_failed;
-		}
-
-		imem->vmem = vmem_buffer;
-		break;
-	}
-	case IMEM_NONE:
-		rc = 0;
-		break;
-
-	default:
-		rc = -ENOTSUPP;
-		goto imem_alloc_failed;
-	}
-
-	imem->type = device->res->imem_type;
-	dprintk(VIDC_DBG, "Allocated %ld bytes of IMEM of type %d\n", size,
-			imem->type);
-	return 0;
-imem_alloc_failed:
-	imem->type = IMEM_NONE;
-	return rc;
-}
-
-static int __free_imem(struct venus_hfi_device *device)
-{
-	struct imem *imem = NULL;
-	int rc = 0;
-
-	if (!device)
-		return -EINVAL;
-
-	imem = &device->resources.imem;
-	switch (imem->type) {
-	case IMEM_NONE:
-		/* Follow the semantics of free(NULL), which is a no-op. */
-		break;
-	case IMEM_VMEM:
-		vmem_free(imem->vmem);
-		break;
-	default:
-		rc = -ENOTSUPP;
-		goto imem_free_failed;
-	}
-
-	imem->type = IMEM_NONE;
-	return 0;
-
-imem_free_failed:
-	return rc;
-}
-
-static int __set_imem(struct venus_hfi_device *device, struct imem *imem)
-{
-	struct vidc_resource_hdr rhdr;
-	phys_addr_t addr = 0;
-	int rc = 0;
-
-	if (!device || !device->res || !imem) {
-		dprintk(VIDC_ERR, "Invalid params, core: %pK, imem: %pK\n",
-			device, imem);
+	if (!device || !resource_hdr) {
+		dprintk(VIDC_ERR, "release_res: Invalid Params\n");
 		return -EINVAL;
 	}
 
-	rhdr.resource_handle = imem; /* cookie */
-	rhdr.size = device->res->imem_size;
-	rhdr.resource_id = VIDC_RESOURCE_NONE;
+	pkt = (struct hfi_cmd_sys_release_resource_packet *) packet;
 
-	switch (imem->type) {
-	case IMEM_VMEM:
-		rhdr.resource_id = VIDC_RESOURCE_VMEM;
-		addr = imem->vmem;
-		break;
-	case IMEM_NONE:
-		dprintk(VIDC_DBG, "%s Target does not support IMEM", __func__);
-		rc = 0;
-		goto imem_set_failed;
-	default:
-		dprintk(VIDC_ERR, "IMEM of type %d unsupported\n", imem->type);
-		rc = -ENOTSUPP;
-		goto imem_set_failed;
-	}
+	rc = call_hfi_pkt_op(device, sys_release_resource,
+			pkt, resource_hdr);
 
-	MSM_VIDC_ERROR(!addr);
-
-	rc = __core_set_resource(device, &rhdr, (void *)addr);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to set IMEM on driver\n");
-		goto imem_set_failed;
+		dprintk(VIDC_ERR, "release_res: failed to create packet\n");
+		goto err_create_pkt;
 	}
 
-	dprintk(VIDC_DBG,
-			"Managed to set IMEM buffer of type %d sized %d bytes at %pa\n",
-			rhdr.resource_id, rhdr.size, &addr);
+	rc = __iface_cmdq_write(device, pkt);
+	if (rc)
+		rc = -ENOTEMPTY;
 
-	rc = __vote_buses(device, device->bus_vote.data,
-			device->bus_vote.data_count);
-	if (rc) {
-		dprintk(VIDC_ERR,
-				"Failed to vote for buses after setting imem: %d\n",
-				rc);
-	}
-
-imem_set_failed:
+err_create_pkt:
 	return rc;
 }
 
@@ -1931,6 +1826,12 @@
 	if (rc || __iface_cmdq_write(dev, &version_pkt))
 		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 (dev->res->pm_qos_latency_us) {
 #ifdef CONFIG_SMP
 		dev->qos.type = PM_QOS_REQ_AFFINE_IRQ;
@@ -2848,6 +2749,8 @@
 		return;
 	}
 
+	dprintk(VIDC_PROF,
+		"Entering venus_hfi_pm_handler\n");
 	/*
 	 * It is ok to check this variable outside the lock since
 	 * it is being updated in this context only
@@ -3094,12 +2997,7 @@
 			break;
 		case HAL_SYS_INIT_DONE:
 			dprintk(VIDC_DBG, "Received SYS_INIT_DONE\n");
-			/* Video driver intentionally does not unset
-			 * IMEM on venus to simplify power collapse.
-			 */
-			if (__set_imem(device, &device->resources.imem))
-				dprintk(VIDC_WARN,
-				"Failed to set IMEM. Performance will be impacted\n");
+
 			sys_init_done.capabilities =
 				device->sys_init_capabilities;
 			hfi_process_sys_init_done_prop_read(
@@ -3584,6 +3482,68 @@
 	return rc;
 }
 
+static void __deinit_subcaches(struct venus_hfi_device *device)
+{
+	struct subcache_info *sinfo = NULL;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "deinit_subcaches: invalid device %pK\n",
+			device);
+		goto exit;
+	}
+
+	if (!device->res->sys_cache_enabled)
+		goto exit;
+
+	venus_hfi_for_each_subcache_reverse(device, sinfo) {
+		if (sinfo->subcache) {
+			dprintk(VIDC_DBG, "deinit_subcaches: %s\n",
+				sinfo->name);
+			llcc_slice_putd(sinfo->subcache);
+			sinfo->subcache = NULL;
+		}
+	}
+
+exit:
+	return;
+}
+
+static int __init_subcaches(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	struct subcache_info *sinfo = NULL;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "init_subcaches: invalid device %pK\n",
+			device);
+		return -EINVAL;
+	}
+
+	if (!device->res->sys_cache_enabled)
+		return 0;
+
+	venus_hfi_for_each_subcache(device, sinfo) {
+		sinfo->subcache = llcc_slice_getd(&device->res->pdev->dev,
+			sinfo->name);
+		if (IS_ERR_OR_NULL(sinfo->subcache)) {
+			rc = PTR_ERR(sinfo->subcache) ? : -EBADHANDLE;
+			dprintk(VIDC_ERR,
+				 "init_subcaches: invalid subcache: %s rc %d\n",
+				sinfo->name, rc);
+			sinfo->subcache = NULL;
+			goto err_subcache_get;
+		}
+		dprintk(VIDC_DBG, "init_subcaches: %s\n",
+			sinfo->name);
+	}
+
+	return 0;
+
+err_subcache_get:
+	__deinit_subcaches(device);
+	return rc;
+}
+
 static int __init_resources(struct venus_hfi_device *device,
 				struct msm_vidc_platform_resources *res)
 {
@@ -3608,6 +3568,10 @@
 		goto err_init_bus;
 	}
 
+	rc = __init_subcaches(device);
+	if (rc)
+		dprintk(VIDC_WARN, "Failed to init subcaches: %d\n", rc);
+
 	device->sys_init_capabilities =
 		kzalloc(sizeof(struct msm_vidc_capability)
 		* VIDC_MAX_SESSIONS, GFP_TEMPORARY);
@@ -3623,6 +3587,7 @@
 
 static void __deinit_resources(struct venus_hfi_device *device)
 {
+	__deinit_subcaches(device);
 	__deinit_bus(device);
 	__deinit_clocks(device);
 	__deinit_regulators(device);
@@ -3789,6 +3754,132 @@
 	return rc;
 }
 
+static int __enable_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_enabled)
+		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;
+		}
+		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);
+		c++;
+	}
+
+	/* Set resource to Venus for activated subcaches */
+	if (c) {
+		dprintk(VIDC_DBG, "Setting Subcaches\n");
+
+		rhdr.resource_handle = sc_res_info; /* cookie */
+		rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
+
+		sc_res_info->num_entries = c;
+
+		rc = __core_set_resource(device, &rhdr, (void *)sc_res_info);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to set subcaches %d\n", rc);
+			goto err_fail_set_subacaches;
+		}
+	}
+
+	venus_hfi_for_each_subcache(device, sinfo) {
+		if (sinfo->isactive == true)
+			sinfo->isset = true;
+	}
+
+	dprintk(VIDC_DBG, "Activated & Set Subcaches to Venus\n");
+
+	return 0;
+
+err_fail_set_subacaches:
+	__disable_subcaches(device);
+
+	return rc;
+}
+
+static int __disable_subcaches(struct venus_hfi_device *device)
+{
+	struct subcache_info *sinfo;
+	int rc = 0;
+	u32 c = 0;
+	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_enabled)
+		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;
+	sc_res = &(sc_res_info->rg_subcache_entries[0]);
+
+	/* Release resource command to Venus */
+	venus_hfi_for_each_subcache_reverse(device, sinfo) {
+		if (sinfo->isset == true) {
+			/* Update the entry */
+			sc_res[c].size = sinfo->subcache->llcc_slice_size;
+			sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
+			c++;
+			sinfo->isset = false;
+		}
+	}
+
+	if (c > 0) {
+		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);
+	}
+
+	/* De-activate subcaches */
+	venus_hfi_for_each_subcache_reverse(device, sinfo) {
+		if (sinfo->isactive == true) {
+			dprintk(VIDC_DBG, "De-activate subcache %s\n",
+				sinfo->name);
+			rc = llcc_slice_deactivate(sinfo->subcache);
+			if (rc) {
+				dprintk(VIDC_ERR,
+					"Failed to de-activate %s: %d\n",
+					sinfo->name, rc);
+			}
+			sinfo->isactive = false;
+		}
+	}
+
+	return rc;
+}
+
 static int __venus_power_on(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -3805,12 +3896,6 @@
 		goto fail_vote_buses;
 	}
 
-	rc = __alloc_imem(device, device->res->imem_size);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to allocate IMEM\n");
-		goto fail_alloc_imem;
-	}
-
 	rc = __enable_regulators(device);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to enable GDSC, err = %d\n", rc);
@@ -3855,8 +3940,6 @@
 fail_enable_clks:
 	__disable_regulators(device);
 fail_enable_gdsc:
-	__free_imem(device);
-fail_alloc_imem:
 	__unvote_buses(device);
 fail_vote_buses:
 	device->power_enabled = false;
@@ -3876,8 +3959,6 @@
 	if (__disable_regulators(device))
 		dprintk(VIDC_WARN, "Failed to disable regulators\n");
 
-	__free_imem(device);
-
 	if (__unvote_buses(device))
 		dprintk(VIDC_WARN, "Failed to unvote for buses\n");
 	device->power_enabled = false;
@@ -3897,6 +3978,9 @@
 
 	dprintk(VIDC_PROF, "Entering power collapse\n");
 
+	if (__disable_subcaches(device))
+		dprintk(VIDC_ERR, "Failed to disable subcaches\n");
+
 	if (device->res->pm_qos_latency_us &&
 		pm_qos_request_active(&device->qos))
 		pm_qos_remove_request(&device->qos);
@@ -3966,6 +4050,15 @@
 		pm_qos_add_request(&device->qos, PM_QOS_CPU_DMA_LATENCY,
 				device->res->pm_qos_latency_us);
 	}
+
+	__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);
+	}
+
 	dprintk(VIDC_PROF, "Resumed from power collapse\n");
 exit:
 	device->skip_pc_count = 0;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 76ede70..925918c 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -19,7 +19,6 @@
 #include <linux/platform_device.h>
 #include <linux/pm_qos.h>
 #include <linux/spinlock.h>
-#include "vmem/vmem.h"
 #include "vidc_hfi_api.h"
 #include "vidc_hfi_helper.h"
 #include "vidc_hfi_api.h"
@@ -48,6 +47,9 @@
 
 #define VIDC_MAX_NAME_LENGTH 64
 #define VIDC_MAX_PC_SKIP_COUNT 10
+#define VIDC_MAX_SUBCACHES 4
+#define VIDC_MAX_SUBCACHE_SIZE 52
+
 struct hfi_queue_table_header {
 	u32 qtbl_version;
 	u32 qtbl_size;
@@ -198,6 +200,11 @@
 #define venus_hfi_for_each_bus_reverse(__device, __binfo) \
 	venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
 
+/* Subcache set helpers */
+#define venus_hfi_for_each_subcache(__device, __sinfo) \
+	venus_hfi_for_each_thing(__device, __sinfo, subcache)
+#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
+	venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
 
 /* Internal data used in vidc_hal not exposed to msm_vidc*/
 struct hal_data {
@@ -207,16 +214,8 @@
 	u32 register_size;
 };
 
-struct imem {
-	enum imem_type type;
-	union {
-		phys_addr_t vmem;
-	};
-};
-
 struct venus_resources {
 	struct msm_vidc_fw fw;
-	struct imem imem;
 };
 
 enum venus_hfi_state {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 537a1c6..bcc29c0 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -224,6 +224,7 @@
 	HAL_PARAM_VIDEO_CORES_USAGE,
 	HAL_PARAM_VIDEO_WORK_MODE,
 	HAL_PARAM_SECURE,
+	HAL_PARAM_USE_SYS_CACHE,
 };
 
 enum hal_domain {
@@ -870,15 +871,13 @@
 
 enum vidc_resource_id {
 	VIDC_RESOURCE_NONE,
-	VIDC_RESOURCE_OCMEM,
-	VIDC_RESOURCE_VMEM,
+	VIDC_RESOURCE_SYSCACHE,
 	VIDC_UNUSED_RESOURCE = 0x10000000,
 };
 
 struct vidc_resource_hdr {
 	enum vidc_resource_id resource_id;
 	void *resource_handle;
-	u32 size;
 };
 
 struct vidc_buffer_addr_info {
@@ -1293,7 +1292,6 @@
 struct msm_vidc_gov_data {
 	struct vidc_bus_vote_data *data;
 	u32 data_count;
-	int imem_size;
 };
 
 enum msm_vidc_power_mode {
@@ -1309,9 +1307,6 @@
 	int num_formats; /* 1 = DPB-OPB unified; 2 = split */
 	int height, width, fps;
 	enum msm_vidc_power_mode power_mode;
-	struct imem_ab_table *imem_ab_tbl;
-	u32 imem_ab_tbl_size;
-	unsigned long core_freq;
 };
 
 struct vidc_clk_scale_data {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index eaba920..fc638f0 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -220,6 +220,8 @@
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x010)
 #define  HFI_PROPERTY_PARAM_SECURE_SESSION		\
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x011)
+#define  HFI_PROPERTY_PARAM_USE_SYS_CACHE				\
+	(HFI_PROPERTY_PARAM_COMMON_START + 0x012)
 #define  HFI_PROPERTY_PARAM_WORK_MODE                       \
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x015)
 
@@ -718,23 +720,16 @@
 	u32 flip;
 };
 
-#define HFI_RESOURCE_OCMEM 0x00000001
+#define HFI_RESOURCE_SYSCACHE 0x00000002
 
-struct hfi_resource_ocmem {
+struct hfi_resource_subcache_type {
 	u32 size;
-	u32 mem;
+	u32 sc_id;
 };
 
-struct hfi_resource_ocmem_requirement {
-	u32 session_domain;
-	u32 width;
-	u32 height;
-	u32 size;
-};
-
-struct hfi_resource_ocmem_requirement_info {
+struct hfi_resource_syscache_info_type {
 	u32 num_entries;
-	struct hfi_resource_ocmem_requirement rg_requirements[1];
+	struct hfi_resource_subcache_type rg_subcache_entries[1];
 };
 
 struct hfi_property_sys_image_version_info_type {
diff --git a/drivers/media/platform/msm/vidc/vmem/Kconfig b/drivers/media/platform/msm/vidc/vmem/Kconfig
deleted file mode 100644
index 99260a9..0000000
--- a/drivers/media/platform/msm/vidc/vmem/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-menuconfig MSM_VIDC_VMEM
-	tristate "Qualcomm Technologies, Inc. MSM VMEM driver"
-	depends on ARCH_QCOM && MSM_VIDC_V4L2
diff --git a/drivers/media/platform/msm/vidc/vmem/Makefile b/drivers/media/platform/msm/vidc/vmem/Makefile
deleted file mode 100644
index a56ad95..0000000
--- a/drivers/media/platform/msm/vidc/vmem/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/
-ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/vmem/
-
-msm-vidc-vmem-objs := vmem.o \
-                      vmem_debugfs.o
-
-obj-$(CONFIG_MSM_VIDC_VMEM) := msm-vidc-vmem.o
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c
deleted file mode 100644
index c75f02d..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem.c
+++ /dev/null
@@ -1,738 +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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/bitops.h>
-#include <linux/clk.h>
-#include <linux/clk/qcom.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/msm-bus.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include "vmem.h"
-#include "vmem_debugfs.h"
-
-/* Registers */
-#define OCIMEM_BASE(v)               ((uint8_t *)(v)->reg.base)
-#define OCIMEM_HW_VERSION(v)         (OCIMEM_BASE(v) + 0x00)
-#define OCIMEM_HW_PROFILE(v)         (OCIMEM_BASE(v) + 0x04)
-#define OCIMEM_GEN_CTL(v)            (OCIMEM_BASE(v) + 0x08)
-#define OCIMEM_GEN_STAT(v)           (OCIMEM_BASE(v) + 0x0C)
-#define OCIMEM_INTC_CLR(v)           (OCIMEM_BASE(v) + 0x10)
-#define OCIMEM_INTC_MASK(v)          (OCIMEM_BASE(v) + 0x14)
-#define OCIMEM_INTC_STAT(v)          (OCIMEM_BASE(v) + 0x18)
-#define OCIMEM_OSW_STATUS(v)         (OCIMEM_BASE(v) + 0x1C)
-#define OCIMEM_PSCGC_TIMERS(v)       (OCIMEM_BASE(v) + 0x34)
-#define OCIMEM_PSCGC_STAT(v)         (OCIMEM_BASE(v) + 0x38)
-#define OCIMEM_PSCGC_M0_M7_CTL(v)    (OCIMEM_BASE(v) + 0x3C)
-#define OCIMEM_ERR_ADDRESS(v)        (OCIMEM_BASE(v) + 0x60)
-#define OCIMEM_AXI_ERR_SYNDROME(v)   (OCIMEM_BASE(v) + 0x64)
-#define OCIMEM_DEBUG_CTL(v)          (OCIMEM_BASE(v) + 0x68)
-
-/*
- * Helper macro to help out with masks and shifts for values packed into
- * registers.
- */
-#define DECLARE_TYPE(__type, __end, __start)                                   \
-	static const unsigned int __type##_BITS = (__end) - (__start) + 1;     \
-	static const unsigned int __type##_SHIFT = (__start);                  \
-	static const unsigned int __type##_MASK = GENMASK((__end), (__start)); \
-	static inline unsigned int __type(uint32_t val)                        \
-	{                                                                      \
-		return (val & __type##_MASK) >> __type##_SHIFT;                \
-	}                                                                      \
-	static inline uint32_t __type##_UPDATE(unsigned int val)               \
-	{                                                                      \
-		return (val << __type##_SHIFT) & __type##_MASK;                \
-	}
-
-/* Register masks */
-/* OCIMEM_PSCGC_M0_M7_CTL */
-DECLARE_TYPE(BANK0_STATE, 3, 0);
-DECLARE_TYPE(BANK1_STATE, 7, 4);
-DECLARE_TYPE(BANK2_STATE, 11, 8);
-DECLARE_TYPE(BANK3_STATE, 15, 12);
-/* OCIMEM_PSCGC_TIMERS */
-DECLARE_TYPE(TIMERS_WAKEUP, 3, 0);
-DECLARE_TYPE(TIMERS_SLEEP, 11, 8);
-/* OCIMEM_HW_VERSION */
-DECLARE_TYPE(VERSION_STEP, 15, 0);
-DECLARE_TYPE(VERSION_MINOR, 27, 16);
-DECLARE_TYPE(VERSION_MAJOR, 31, 28);
-/* OCIMEM_HW_PROFILE */
-DECLARE_TYPE(PROFILE_BANKS, 16, 12);
-/* OCIMEM_AXI_ERR_SYNDROME */
-DECLARE_TYPE(ERR_SYN_ATID, 14, 8);
-DECLARE_TYPE(ERR_SYN_AMID, 23, 16);
-DECLARE_TYPE(ERR_SYN_APID, 28, 24);
-DECLARE_TYPE(ERR_SYN_ABID, 31, 29);
-/* OCIMEM_INTC_MASK */
-DECLARE_TYPE(AXI_ERR_INT, 0, 0);
-
-/* Internal stuff */
-#define MAX_BANKS 4
-
-enum bank_state {
-	BANK_STATE_NORM_PASSTHRU = 0x000,
-	BANK_STATE_NORM_FORCE_CORE_ON = 0x002,
-	BANK_STATE_NORM_FORCE_PERIPH_ON = 0x001,
-	BANK_STATE_NORM_FORCE_ALL_ON = 0x03,
-	BANK_STATE_SLEEP_RET = 0x6,
-	BANK_STATE_SLEEP_RET_PERIPH_ON = 0x7,
-	BANK_STATE_SLEEP_NO_RET = 0x4,
-};
-
-struct vmem {
-	int irq;
-	int num_banks;
-	int bank_size;
-	struct {
-		struct resource *resource;
-		void __iomem *base;
-	} reg, mem;
-	struct regulator *vdd;
-	struct {
-		const char *name;
-		struct clk *clk;
-		bool has_mem_retention;
-	} *clocks;
-	int num_clocks;
-	struct {
-		struct msm_bus_scale_pdata *pdata;
-		uint32_t priv;
-	} bus;
-	atomic_t alloc_count;
-	struct dentry *debugfs_root;
-};
-
-static struct vmem *vmem;
-
-static inline u32 __readl(void * __iomem addr)
-{
-	u32 value = 0;
-
-	pr_debug("read %pK ", addr);
-	value = readl_relaxed(addr);
-	pr_debug("-> %08x\n", value);
-
-	return value;
-}
-
-static inline void __writel(u32 val, void * __iomem addr)
-{
-	pr_debug("write %08x -> %pK\n", val, addr);
-	writel_relaxed(val, addr);
-	/*
-	 * Commit all writes via a mem barrier, as subsequent __readl()
-	 * will depend on the state that's set via __writel().
-	 */
-	mb();
-}
-
-static inline void __wait_timer(struct vmem *v, bool wakeup)
-{
-	uint32_t ticks = 0;
-	unsigned int (*timer)(uint32_t) = wakeup ?
-		TIMERS_WAKEUP : TIMERS_SLEEP;
-
-	ticks = timer(__readl(OCIMEM_PSCGC_TIMERS(v)));
-
-	/* Sleep for `ticks` nanoseconds as per h/w spec */
-	ndelay(ticks);
-}
-
-static inline void __wait_wakeup(struct vmem *v)
-{
-	return __wait_timer(v, true);
-}
-
-static inline void __wait_sleep(struct vmem *v)
-{
-	return __wait_timer(v, false);
-}
-
-static inline int __power_on(struct vmem *v)
-{
-	int rc = 0, c = 0;
-
-	rc = msm_bus_scale_client_update_request(v->bus.priv, 1);
-	if (rc) {
-		pr_err("Failed to vote for buses (%d)\n", rc);
-		goto exit;
-	}
-	pr_debug("Voted for buses\n");
-
-	rc = regulator_enable(v->vdd);
-	if (rc) {
-		pr_err("Failed to power on gdsc (%d)", rc);
-		goto unvote_bus;
-	}
-	pr_debug("Enabled regulator vdd\n");
-
-	for (c = 0; c < v->num_clocks; ++c) {
-		if (v->clocks[c].has_mem_retention) {
-			rc = clk_set_flags(v->clocks[c].clk,
-				       CLKFLAG_NORETAIN_PERIPH);
-			if (rc) {
-				pr_warn("Failed set flag NORETAIN_PERIPH %s\n",
-					v->clocks[c].name);
-			}
-			rc = clk_set_flags(v->clocks[c].clk,
-				       CLKFLAG_NORETAIN_MEM);
-			if (rc) {
-				pr_warn("Failed set flag NORETAIN_MEM %s\n",
-					v->clocks[c].name);
-			}
-		}
-
-		rc = clk_prepare_enable(v->clocks[c].clk);
-		if (rc) {
-			pr_err("Failed to enable %s clock (%d)\n",
-					v->clocks[c].name, rc);
-			goto disable_clocks;
-		}
-
-		pr_debug("Enabled clock %s\n", v->clocks[c].name);
-	}
-
-	return 0;
-disable_clocks:
-	for (--c; c >= 0; c--)
-		clk_disable_unprepare(v->clocks[c].clk);
-	regulator_disable(v->vdd);
-unvote_bus:
-	msm_bus_scale_client_update_request(v->bus.priv, 0);
-exit:
-	return rc;
-}
-
-static inline int __power_off(struct vmem *v)
-{
-	int c = v->num_clocks;
-
-	for (c--; c >= 0; --c) {
-		clk_disable_unprepare(v->clocks[c].clk);
-		pr_debug("Disabled clock %s\n", v->clocks[c].name);
-	}
-
-	regulator_disable(v->vdd);
-	pr_debug("Disabled regulator vdd\n");
-
-	msm_bus_scale_client_update_request(v->bus.priv, 0);
-	pr_debug("Unvoted for buses\n");
-
-	return 0;
-}
-
-static inline enum bank_state __bank_get_state(struct vmem *v,
-		unsigned int bank)
-{
-	unsigned int (*func[MAX_BANKS])(uint32_t) = {
-		BANK0_STATE, BANK1_STATE, BANK2_STATE, BANK3_STATE
-	};
-
-	VMEM_ERROR(bank >= ARRAY_SIZE(func));
-	return func[bank](__readl(OCIMEM_PSCGC_M0_M7_CTL(v)));
-}
-
-static inline void __bank_set_state(struct vmem *v, unsigned int bank,
-		enum bank_state state)
-{
-	uint32_t bank_state = 0;
-	struct {
-		uint32_t (*update)(unsigned int);
-		uint32_t mask;
-	} banks[MAX_BANKS] = {
-		{BANK0_STATE_UPDATE, BANK0_STATE_MASK},
-		{BANK1_STATE_UPDATE, BANK1_STATE_MASK},
-		{BANK2_STATE_UPDATE, BANK2_STATE_MASK},
-		{BANK3_STATE_UPDATE, BANK3_STATE_MASK},
-	};
-
-	VMEM_ERROR(bank >= ARRAY_SIZE(banks));
-
-	bank_state = __readl(OCIMEM_PSCGC_M0_M7_CTL(v));
-	bank_state &= ~banks[bank].mask;
-	bank_state |= banks[bank].update(state);
-
-	__writel(bank_state, OCIMEM_PSCGC_M0_M7_CTL(v));
-}
-
-static inline void __toggle_interrupts(struct vmem *v, bool enable)
-{
-	uint32_t ints = __readl(OCIMEM_INTC_MASK(v)),
-		mask = AXI_ERR_INT_MASK,
-		update = AXI_ERR_INT_UPDATE(!enable);
-
-	ints &= ~mask;
-	ints |= update;
-
-	__writel(ints, OCIMEM_INTC_MASK(v));
-}
-
-static void __enable_interrupts(struct vmem *v)
-{
-	pr_debug("Enabling interrupts\n");
-	enable_irq(v->irq);
-	__toggle_interrupts(v, true);
-}
-
-static void __disable_interrupts(struct vmem *v)
-{
-	pr_debug("Disabling interrupts\n");
-	__toggle_interrupts(v, false);
-	disable_irq_nosync(v->irq);
-}
-
-/**
- * vmem_allocate: - Allocates memory from VMEM.  Allocations have a few
- * restrictions: only allocations of the entire VMEM memory are allowed, and
- * , as a result, only single outstanding allocations are allowed.
- *
- * @size: amount of bytes to allocate
- * @addr: A pointer to phys_addr_t where the physical address of the memory
- * allocated is stored.
- *
- * Return: 0 in case of successful allocation (i.e. *addr != NULL). -ENOTSUPP,
- * if platform doesn't support VMEM. -EEXIST, if there are outstanding VMEM
- * allocations.  -ENOMEM, if platform can't support allocation of `size` bytes.
- * -EAGAIN, if `size` does not allocate the entire VMEM region.  -EIO in case of
- * internal errors.
- */
-int vmem_allocate(size_t size, phys_addr_t *addr)
-{
-	int rc = 0, c = 0;
-	resource_size_t max_size = 0;
-
-	if (!vmem) {
-		pr_err("No vmem, try rebooting your device\n");
-		rc = -ENOTSUPP;
-		goto exit;
-	}
-	if (!size) {
-		pr_err("%s Invalid size %zu\n", __func__, size);
-		rc = -EINVAL;
-		goto exit;
-	}
-
-	max_size = resource_size(vmem->mem.resource);
-
-	if (atomic_read(&vmem->alloc_count)) {
-		pr_err("Only single allocations allowed for vmem\n");
-		rc = -EEXIST;
-		goto exit;
-	} else if (size > max_size) {
-		pr_err("Out of memory, have max %pa\n", &max_size);
-		rc = -ENOMEM;
-		goto exit;
-	} else if (size != max_size) {
-		pr_err("Only support allocations of size %pa\n", &max_size);
-		rc = -EAGAIN;
-		goto exit;
-	}
-
-	rc = __power_on(vmem);
-	if (rc) {
-		pr_err("Failed power on (%d)\n", rc);
-		goto exit;
-	}
-
-	VMEM_ERROR(vmem->num_banks != DIV_ROUND_UP(size, vmem->bank_size));
-
-	/* Turn on the necessary banks */
-	for (c = 0; c < vmem->num_banks; ++c) {
-		__bank_set_state(vmem, c, BANK_STATE_NORM_FORCE_CORE_ON);
-		__wait_wakeup(vmem);
-	}
-
-	/* Enable interrupts to detect faults */
-	__enable_interrupts(vmem);
-
-	atomic_inc(&vmem->alloc_count);
-	*addr = (phys_addr_t)vmem->mem.resource->start;
-	return 0;
-exit:
-	return rc;
-}
-EXPORT_SYMBOL(vmem_allocate);
-
-/**
- * vmem_free: - Frees the memory allocated via vmem_allocate.  Undefined
- * behaviour if to_free is a not a pointer returned via vmem_allocate
- */
-void vmem_free(phys_addr_t to_free)
-{
-	int c = 0;
-
-	if (!to_free || !vmem)
-		return;
-
-	VMEM_ERROR(atomic_read(&vmem->alloc_count) == 0);
-
-	for (c = 0; c < vmem->num_banks; ++c) {
-		enum bank_state curr_state = __bank_get_state(vmem, c);
-
-		if (curr_state != BANK_STATE_NORM_FORCE_CORE_ON) {
-			pr_warn("When freeing, expected bank state to be %d, was instead %d\n",
-					BANK_STATE_NORM_FORCE_CORE_ON,
-					curr_state);
-		}
-
-		__bank_set_state(vmem, c, BANK_STATE_SLEEP_NO_RET);
-	}
-
-	__disable_interrupts(vmem);
-	__power_off(vmem);
-	atomic_dec(&vmem->alloc_count);
-}
-EXPORT_SYMBOL(vmem_free);
-
-struct vmem_interrupt_cookie {
-	struct vmem *vmem;
-	struct work_struct work;
-};
-
-static void __irq_helper(struct work_struct *work)
-{
-	struct vmem_interrupt_cookie *cookie = container_of(work,
-			struct vmem_interrupt_cookie, work);
-	struct vmem *v = cookie->vmem;
-	unsigned int stat, gen_stat, pscgc_stat, err_addr_abs,
-		err_addr_rel, err_syn;
-
-	stat = __readl(OCIMEM_INTC_STAT(v));
-	gen_stat = __readl(OCIMEM_GEN_CTL(v));
-	pscgc_stat = __readl(OCIMEM_PSCGC_STAT(v));
-
-	err_addr_abs = __readl(OCIMEM_ERR_ADDRESS(v));
-	err_addr_rel = v->mem.resource->start - err_addr_abs;
-
-	err_syn = __readl(OCIMEM_AXI_ERR_SYNDROME(v));
-
-	pr_crit("Detected a fault on VMEM:\n");
-	pr_cont("\tinterrupt status: %x\n", stat);
-	pr_cont("\tgeneral status: %x\n", gen_stat);
-	pr_cont("\tmemory status: %x\n", pscgc_stat);
-	pr_cont("\tfault address: %x (absolute), %x (relative)\n",
-			err_addr_abs, err_addr_rel);
-	pr_cont("\tfault bank: %x\n", err_addr_rel / v->bank_size);
-	pr_cont("\tfault core: %u (mid), %u (pid), %u (bid)\n",
-			ERR_SYN_AMID(err_syn), ERR_SYN_APID(err_syn),
-			ERR_SYN_ABID(err_syn));
-
-	/* Clear the interrupt */
-	__writel(0, OCIMEM_INTC_CLR(v));
-
-	__enable_interrupts(v);
-}
-
-static struct vmem_interrupt_cookie interrupt_cookie;
-
-static irqreturn_t __irq_handler(int irq, void *cookie)
-{
-	struct vmem *v = cookie;
-	irqreturn_t status = __readl(OCIMEM_INTC_STAT(vmem)) ?
-		IRQ_HANDLED : IRQ_NONE;
-
-	if (status != IRQ_NONE) {
-		/* Mask further interrupts while handling this one */
-		__disable_interrupts(v);
-
-		interrupt_cookie.vmem = v;
-		INIT_WORK(&interrupt_cookie.work, __irq_helper);
-		schedule_work(&interrupt_cookie.work);
-	}
-
-	return status;
-}
-
-static inline int __init_resources(struct vmem *v,
-		struct platform_device *pdev)
-{
-	int rc = 0, c = 0;
-	int *clock_props = NULL;
-
-	v->irq = platform_get_irq(pdev, 0);
-	if (v->irq < 0) {
-		rc = v->irq;
-		pr_err("Failed to get irq (%d)\n", rc);
-		v->irq = 0;
-		goto exit;
-	}
-
-	/* Registers and memory */
-	v->reg.resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"reg-base");
-	if (!v->reg.resource) {
-		pr_err("Failed to find register base\n");
-		rc = -ENOENT;
-		goto exit;
-	}
-
-	v->reg.base = devm_ioremap_resource(&pdev->dev, v->reg.resource);
-	if (IS_ERR_OR_NULL(v->reg.base)) {
-		rc = PTR_ERR(v->reg.base) ?: -EIO;
-		pr_err("Failed to map register base into kernel (%d)\n", rc);
-		v->reg.base = NULL;
-		goto exit;
-	}
-
-	pr_debug("Register range: %pa -> %pa\n", &v->reg.resource->start,
-			&v->reg.resource->end);
-
-	v->mem.resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"mem-base");
-	if (!v->mem.resource) {
-		pr_err("Failed to find memory base\n");
-		rc = -ENOENT;
-		goto exit;
-	}
-
-	v->mem.base = NULL;
-	pr_debug("Memory range: %pa -> %pa\n", &v->mem.resource->start,
-			&v->mem.resource->end);
-
-	/* Buses, Clocks & Regulators*/
-	v->num_clocks = of_property_count_strings(pdev->dev.of_node,
-			"clock-names");
-	if (v->num_clocks <= 0) {
-		pr_err("Can't find any clocks\n");
-		goto exit;
-	}
-
-	v->clocks = devm_kzalloc(&pdev->dev, sizeof(*v->clocks) * v->num_clocks,
-			GFP_KERNEL);
-	if (!v->clocks) {
-		rc = -ENOMEM;
-		goto exit;
-	}
-
-	clock_props = devm_kzalloc(&pdev->dev,
-					v->num_clocks * sizeof(*clock_props),
-					GFP_KERNEL);
-	if (!clock_props) {
-		pr_err("Failed to allocate clock config table\n");
-		goto exit;
-	}
-
-	rc = of_property_read_u32_array(pdev->dev.of_node, "clock-config",
-			clock_props, v->num_clocks);
-	if (rc) {
-		pr_err("Failed to read clock config\n");
-		goto exit;
-	}
-
-	for (c = 0; c < v->num_clocks; ++c) {
-		const char *name = NULL;
-		struct clk *temp = NULL;
-
-		of_property_read_string_index(pdev->dev.of_node, "clock-names",
-				c, &name);
-		temp = devm_clk_get(&pdev->dev, name);
-		if (IS_ERR_OR_NULL(temp)) {
-			rc = PTR_ERR(temp) ?: -ENOENT;
-			pr_err("Failed to find %s (%d)\n", name, rc);
-			goto exit;
-		}
-
-		v->clocks[c].clk = temp;
-		v->clocks[c].name = name;
-		v->clocks[c].has_mem_retention = clock_props[c];
-	}
-
-	v->vdd = devm_regulator_get(&pdev->dev, "vdd");
-	if (IS_ERR_OR_NULL(v->vdd)) {
-		rc = PTR_ERR(v->vdd) ?: -ENOENT;
-		pr_err("Failed to find regulator (vdd) (%d)\n", rc);
-		goto exit;
-	}
-
-	v->bus.pdata = msm_bus_cl_get_pdata(pdev);
-	if (IS_ERR_OR_NULL(v->bus.pdata)) {
-		rc = PTR_ERR(v->bus.pdata) ?: -ENOENT;
-		pr_err("Failed to find bus vectors (%d)\n", rc);
-		goto exit;
-	}
-
-	v->bus.priv = msm_bus_scale_register_client(v->bus.pdata);
-	if (!v->bus.priv) {
-		rc = -EBADHANDLE;
-		pr_err("Failed to register bus client\n");
-		goto free_pdata;
-	}
-
-	/* Misc. */
-	rc = of_property_read_u32(pdev->dev.of_node, "qcom,bank-size",
-			&v->bank_size);
-	if (rc || !v->bank_size) {
-		pr_err("Failed reading (or found invalid) qcom,bank-size in %s (%d)\n",
-				of_node_full_name(pdev->dev.of_node), rc);
-		rc = -ENOENT;
-		goto free_pdata;
-	}
-
-	v->num_banks = resource_size(v->mem.resource) / v->bank_size;
-
-	pr_debug("Found configuration with %d banks with size %d\n",
-			v->num_banks, v->bank_size);
-
-	return 0;
-free_pdata:
-	msm_bus_cl_clear_pdata(v->bus.pdata);
-exit:
-	return rc;
-}
-
-static inline void __uninit_resources(struct vmem *v,
-		struct platform_device *pdev)
-{
-	int c = 0;
-
-	msm_bus_cl_clear_pdata(v->bus.pdata);
-	v->bus.pdata = NULL;
-	v->bus.priv = 0;
-
-	for (c = 0; c < v->num_clocks; ++c) {
-		v->clocks[c].clk = NULL;
-		v->clocks[c].name = NULL;
-	}
-
-	v->vdd = NULL;
-}
-
-static int vmem_probe(struct platform_device *pdev)
-{
-	uint32_t version = 0, num_banks = 0, rc = 0;
-	struct vmem *v = NULL;
-
-	if (vmem) {
-		pr_err("Only one instance of %s allowed", pdev->name);
-		return -EEXIST;
-	}
-
-	v = devm_kzalloc(&pdev->dev, sizeof(*v), GFP_KERNEL);
-	if (!v)
-		return -ENOMEM;
-
-
-	rc = __init_resources(v, pdev);
-	if (rc) {
-		pr_err("Failed to read resources\n");
-		goto exit;
-	}
-
-	/*
-	 * For now, only support up to 4 banks. It's unrealistic that VMEM has
-	 * more banks than that (even in the future).
-	 */
-	if (v->num_banks > MAX_BANKS) {
-		pr_err("Number of banks (%d) exceeds what's supported (%d)\n",
-			v->num_banks, MAX_BANKS);
-		rc = -ENOTSUPP;
-		goto exit;
-	}
-
-	/* Cross check the platform resources with what's available on chip */
-	rc = __power_on(v);
-	if (rc) {
-		pr_err("Failed to power on (%d)\n", rc);
-		goto exit;
-	}
-
-	version = __readl(OCIMEM_HW_VERSION(v));
-	pr_debug("v%d.%d.%d\n", VERSION_MAJOR(version), VERSION_MINOR(version),
-			VERSION_STEP(version));
-
-	num_banks = PROFILE_BANKS(__readl(OCIMEM_HW_PROFILE(v)));
-	pr_debug("Found %d banks on chip\n", num_banks);
-	if (v->num_banks != num_banks) {
-		pr_err("Platform configuration of %d banks differs from what's available on chip (%d)\n",
-				v->num_banks, num_banks);
-		rc = -EINVAL;
-		goto disable_clocks;
-	}
-
-	rc = devm_request_irq(&pdev->dev, v->irq, __irq_handler,
-			IRQF_TRIGGER_HIGH, "vmem", v);
-	if (rc) {
-		pr_err("Failed to setup irq (%d)\n", rc);
-		goto disable_clocks;
-	}
-
-	__disable_interrupts(v);
-
-	/* Everything good so far, set up the global context and debug hooks */
-	pr_info("Up and running with %d banks of memory from %pR\n",
-			v->num_banks, &v->mem.resource);
-	v->debugfs_root = vmem_debugfs_init(pdev);
-	platform_set_drvdata(pdev, v);
-	vmem = v;
-
-disable_clocks:
-	__power_off(v);
-exit:
-	return rc;
-}
-
-static int vmem_remove(struct platform_device *pdev)
-{
-	struct vmem *v = platform_get_drvdata(pdev);
-
-	VMEM_ERROR(v != vmem);
-
-	__uninit_resources(v, pdev);
-	vmem_debugfs_deinit(v->debugfs_root);
-	vmem = NULL;
-
-	return 0;
-}
-
-static const struct of_device_id vmem_of_match[] = {
-	{.compatible = "qcom,msm-vmem"},
-	{}
-};
-
-MODULE_DEVICE_TABLE(of, vmem_of_match);
-
-static struct platform_driver vmem_driver = {
-	.probe = vmem_probe,
-	.remove = vmem_remove,
-	.driver = {
-		.name = "msm_vidc_vmem",
-		.owner = THIS_MODULE,
-		.of_match_table = vmem_of_match,
-	},
-};
-
-static int __init vmem_init(void)
-{
-	return platform_driver_register(&vmem_driver);
-}
-
-static void __exit vmem_exit(void)
-{
-	platform_driver_unregister(&vmem_driver);
-}
-
-module_init(vmem_init);
-module_exit(vmem_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.h b/drivers/media/platform/msm/vidc/vmem/vmem.h
deleted file mode 100644
index 0376427..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- */
-
-#ifndef __VMEM_H__
-#define __VMEM_H__
-
-#define VMEM_ERROR(value)	\
-	do {			\
-		pr_info("%s : Fatal Level = %d\n", KBUILD_MODNAME, value);\
-		BUG_ON(value);  \
-	} while (0)
-
-#if (defined CONFIG_MSM_VIDC_VMEM) || (defined CONFIG_MSM_VIDC_VMEM_MODULE)
-
-int vmem_allocate(size_t size, phys_addr_t *addr);
-void vmem_free(phys_addr_t to_free);
-
-#else
-
-static inline int vmem_allocate(size_t size, phys_addr_t *addr)
-{
-	return -ENODEV;
-}
-
-static inline void vmem_free(phys_addr_t to_free)
-{
-}
-
-#endif
-
-#endif /* __VMEM_H__ */
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c b/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c
deleted file mode 100644
index 7d2d524..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c
+++ /dev/null
@@ -1,82 +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/debugfs.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include "vmem.h"
-
-struct vmem_debugfs_cookie {
-	phys_addr_t addr;
-	size_t size;
-};
-
-static int __vmem_alloc_get(void *priv, u64 *val)
-{
-	struct vmem_debugfs_cookie *cookie = priv;
-
-	*val = cookie->size;
-	return 0;
-}
-
-static int __vmem_alloc_set(void *priv, u64 val)
-{
-	struct vmem_debugfs_cookie *cookie = priv;
-	int rc = 0;
-
-	switch (val) {
-	case 0: /* free */
-		vmem_free(cookie->addr);
-		cookie->size = 0;
-		break;
-	default:
-		rc = vmem_allocate(val, &cookie->addr);
-		cookie->size = val;
-		break;
-	}
-
-	return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_vmem_alloc, __vmem_alloc_get,
-		__vmem_alloc_set, "%llu");
-
-struct dentry *vmem_debugfs_init(struct platform_device *pdev)
-{
-	struct vmem_debugfs_cookie *alloc_cookie = NULL;
-	struct dentry *debugfs_root = NULL;
-
-	alloc_cookie = devm_kzalloc(&pdev->dev, sizeof(*alloc_cookie),
-			GFP_KERNEL);
-	if (!alloc_cookie)
-		goto exit;
-
-	debugfs_root = debugfs_create_dir("vmem", NULL);
-	if (IS_ERR_OR_NULL(debugfs_root)) {
-		pr_warn("Failed to create '<debugfs>/vmem'\n");
-		debugfs_root = NULL;
-		goto exit;
-	}
-
-	debugfs_create_file("alloc", 0600, debugfs_root,
-			alloc_cookie, &fops_vmem_alloc);
-
-exit:
-	return debugfs_root;
-}
-
-void vmem_debugfs_deinit(struct dentry *debugfs_root)
-{
-	debugfs_remove_recursive(debugfs_root);
-}
-
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h b/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h
deleted file mode 100644
index 8b716cc..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h
+++ /dev/null
@@ -1,21 +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.
- */
-#ifndef __VMEM_DEBUGFS_H__
-#define __VMEM_DEBUGFS_H__
-
-#include <linux/debugfs.h>
-
-struct dentry *vmem_debugfs_init(struct platform_device *pdev);
-void vmem_debugfs_deinit(struct dentry *debugfs_root);
-
-#endif /* __VMEM_DEBUGFS_H__ */
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index f8a7555..64e1f43 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -677,7 +677,7 @@
 		rc = smblib_get_prop_fcc_delta(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		val->intval = get_effective_result(chg->usb_icl_votable);
+		rc = smblib_get_icl_current(chg, &val->intval);
 		break;
 	default:
 		pr_debug("get prop %d is not supported in usb-main\n", psp);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index f4ae415..6eb7009 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -812,6 +812,28 @@
 	return rc;
 }
 
+static int get_sdp_current(struct smb_charger *chg, int *icl_ua)
+{
+	int rc;
+	u8 icl_options;
+	bool usb3 = false;
+
+	rc = smblib_read(chg, USBIN_ICL_OPTIONS_REG, &icl_options);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't get ICL options rc=%d\n", rc);
+		return rc;
+	}
+
+	usb3 = (icl_options & CFG_USB3P0_SEL_BIT);
+
+	if (icl_options & USB51_MODE_BIT)
+		*icl_ua = usb3 ? USBIN_900MA : USBIN_500MA;
+	else
+		*icl_ua = usb3 ? USBIN_150MA : USBIN_100MA;
+
+	return rc;
+}
+
 int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
 {
 	int rc = 0;
@@ -889,6 +911,48 @@
 	return rc;
 }
 
+int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua)
+{
+	int rc = 0;
+	u8 load_cfg;
+	bool override;
+	union power_supply_propval pval;
+
+	rc = smblib_get_prop_typec_mode(chg, &pval);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc);
+		return rc;
+	}
+
+	if ((pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+		|| chg->micro_usb_mode)
+		&& (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
+		rc = get_sdp_current(chg, icl_ua);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get SDP ICL rc=%d\n", rc);
+			return rc;
+		}
+	} else {
+		rc = smblib_read(chg, USBIN_LOAD_CFG_REG, &load_cfg);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get load cfg rc=%d\n", rc);
+			return rc;
+		}
+		override = load_cfg & ICL_OVERRIDE_AFTER_APSD_BIT;
+		if (!override)
+			return INT_MAX;
+
+		/* override is set */
+		rc = smblib_get_charge_param(chg, &chg->param.usb_icl, icl_ua);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 /*********************
  * VOTABLE CALLBACKS *
  *********************/
@@ -2822,7 +2886,7 @@
 int smblib_get_charge_current(struct smb_charger *chg,
 				int *total_current_ua)
 {
-	const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 	union power_supply_propval val = {0, };
 	int rc = 0, typec_source_rd, current_ua;
 	bool non_compliant;
@@ -3094,12 +3158,28 @@
 	}
 }
 
-static void smblib_typec_usb_plugin(struct smb_charger *chg, bool vbus_rising)
+void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg)
 {
+	int rc;
+	u8 stat;
+	bool vbus_rising;
+
+	rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+		return;
+	}
+
+	vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
+
 	if (vbus_rising)
 		smblib_cc2_sink_removal_exit(chg);
 	else
 		smblib_cc2_sink_removal_enter(chg);
+
+	power_supply_changed(chg->usb_psy);
+	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
+					vbus_rising ? "attached" : "detached");
 }
 
 #define PL_DELAY_MS			30000
@@ -3158,8 +3238,6 @@
 
 	if (chg->micro_usb_mode)
 		smblib_micro_usb_plugin(chg, vbus_rising);
-	else
-		smblib_typec_usb_plugin(chg, vbus_rising);
 
 	power_supply_changed(chg->usb_psy);
 	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
@@ -3172,7 +3250,10 @@
 	struct smb_charger *chg = irq_data->parent_data;
 
 	mutex_lock(&chg->lock);
-	smblib_usb_plugin_locked(chg);
+	if (chg->pd_hard_reset)
+		smblib_usb_plugin_hard_reset_locked(chg);
+	else
+		smblib_usb_plugin_locked(chg);
 	mutex_unlock(&chg->lock);
 	return IRQ_HANDLED;
 }
@@ -3336,7 +3417,7 @@
 static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
 					      bool rising, bool qc_charger)
 {
-	const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 
 	/* Hold off PD only until hvdcp 2.0 detection timeout */
 	if (rising) {
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 5409166..e4679f4 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -495,6 +495,7 @@
 int smblib_dp_dm(struct smb_charger *chg, int val);
 int smblib_rerun_aicl(struct smb_charger *chg);
 int smblib_set_icl_current(struct smb_charger *chg, int icl_ua);
+int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua);
 int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
 
 int smblib_init(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index a29871b..8725590 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -598,6 +598,26 @@
 	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
 };
 
+static int smb138x_get_parallel_charging(struct smb138x *chip, int *disabled)
+{
+	struct smb_charger *chg = &chip->chg;
+	int rc = 0;
+	u8 cfg2;
+
+	rc = smblib_read(chg, CHGR_CFG2_REG, &cfg2);
+	if (rc < 0) {
+		pr_err("Couldn't read en_cmg_reg rc=%d\n", rc);
+		return rc;
+	}
+
+	if (cfg2 & CHG_EN_SRC_BIT)
+		*disabled = 0;
+	else
+		*disabled = 1;
+
+	return 0;
+}
+
 static int smb138x_parallel_get_prop(struct power_supply *psy,
 				     enum power_supply_property prop,
 				     union power_supply_propval *val)
@@ -624,7 +644,7 @@
 			val->intval = !(temp & DISABLE_CHARGING_BIT);
 		break;
 	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
-		rc = smblib_get_usb_suspend(chg, &val->intval);
+		rc = smb138x_get_parallel_charging(chip, &val->intval);
 		break;
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
 		if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
@@ -694,28 +714,33 @@
 	return rc;
 }
 
-static int smb138x_set_parallel_suspend(struct smb138x *chip, bool suspend)
+static int smb138x_set_parallel_charging(struct smb138x *chip, bool disable)
 {
 	struct smb_charger *chg = &chip->chg;
 	int rc = 0;
 
 	rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT,
-				 suspend ? 0 : WDOG_TIMER_EN_BIT);
+				 disable ? 0 : WDOG_TIMER_EN_BIT);
 	if (rc < 0) {
 		pr_err("Couldn't %s watchdog rc=%d\n",
-		       suspend ? "disable" : "enable", rc);
-		suspend = true;
+		       disable ? "disable" : "enable", rc);
+		disable = true;
 	}
 
-	rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
-				 suspend ? USBIN_SUSPEND_BIT : 0);
+	/*
+	 * Configure charge enable for high polarity and
+	 * When disabling charging set it to cmd register control(cmd bit=0)
+	 * When enabling charging set it to pin control
+	 */
+	rc = smblib_masked_write(chg, CHGR_CFG2_REG,
+			CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT,
+			disable ? 0 : CHG_EN_SRC_BIT);
 	if (rc < 0) {
-		pr_err("Couldn't %s parallel charger rc=%d\n",
-		       suspend ? "suspend" : "resume", rc);
+		pr_err("Couldn't configure charge enable source rc=%d\n", rc);
 		return rc;
 	}
 
-	return rc;
+	return 0;
 }
 
 static int smb138x_parallel_set_prop(struct power_supply *psy,
@@ -728,7 +753,7 @@
 
 	switch (prop) {
 	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
-		rc = smb138x_set_parallel_suspend(chip, (bool)val->intval);
+		rc = smb138x_set_parallel_charging(chip, (bool)val->intval);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
@@ -946,10 +971,25 @@
 		return rc;
 	}
 
-	/* suspend parallel charging */
-	rc = smb138x_set_parallel_suspend(chip, true);
+	/* disable the charging path when under s/w control */
+	rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
+				 CHARGING_ENABLE_CMD_BIT, 0);
 	if (rc < 0) {
-		pr_err("Couldn't suspend parallel charging rc=%d\n", rc);
+		pr_err("Couldn't disable charging rc=%d\n", rc);
+		return rc;
+	}
+
+	/* disable parallel charging path */
+	rc = smb138x_set_parallel_charging(chip, true);
+	if (rc < 0) {
+		pr_err("Couldn't disable parallel path rc=%d\n", rc);
+		return rc;
+	}
+
+	/* unsuspend parallel charging */
+	rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, 0);
+	if (rc < 0) {
+		pr_err("Couldn't unsuspend parallel charging rc=%d\n", rc);
 		return rc;
 	}
 
@@ -960,24 +1000,6 @@
 		return rc;
 	}
 
-	/* enable the charging path */
-	rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
-				 CHARGING_ENABLE_CMD_BIT,
-				 CHARGING_ENABLE_CMD_BIT);
-	if (rc < 0) {
-		pr_err("Couldn't enable charging rc=%d\n", rc);
-		return rc;
-	}
-
-	/* configure charge enable for software control; active high */
-	rc = smblib_masked_write(chg, CHGR_CFG2_REG,
-				 CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0);
-	if (rc < 0) {
-		pr_err("Couldn't configure charge enable source rc=%d\n",
-			rc);
-		return rc;
-	}
-
 	/* enable parallel current sensing */
 	rc = smblib_masked_write(chg, CFG_REG,
 				 VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dc74484..2f6cd95 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -10054,7 +10054,8 @@
 	mb();
 
 	/* IRQ registration */
-	err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+	err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED,
+				dev_name(dev), hba);
 	if (err) {
 		dev_err(hba->dev, "request irq failed\n");
 		goto exit_gating;
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 0a28ee0..be2b7da 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -65,20 +65,15 @@
 	SCT_ENTRY("audio",       6, 6, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("modem",       8, 8, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("modemhw",     9, 9, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("compute",     10, 10, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("gpuhtw",      11, 11, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("gpu",         12, 12, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("gpuhtw",      11, 11, 515, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("gpu",         12, 12, 2560, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("mmuhwt",      13, 13, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1),
-	SCT_ENTRY("sensor",      14, 14, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("compute_dma", 15, 15, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("display",     16, 16, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("videofw",     17, 17, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("camerafw",    18, 18, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("mss_tcm",     19, 19, 1024, 0, 0, 0x0,  0xf, 1, 0, 1, 1, 0),
 	SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0xF,  0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("audiohw",     22, 22, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("audiohw",     22, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 };
 
 static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 32c5890..7f7e9a7 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -61,6 +61,10 @@
 		enum dma_data_direction dir, unsigned long attrs);
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction dir, unsigned long attrs);
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+		size_t size, enum dma_data_direction dir, unsigned long attrs);
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir, unsigned long attrs);
 int iommu_dma_supported(struct device *dev, u64 mask);
 int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 37dd31f..421769e 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -1165,28 +1165,27 @@
 		break;
 
 	case SNDRV_LSM_SET_FWK_MODE_CONFIG: {
-		u32 *mode = NULL;
+		u32 mode;
 
-		if (!arg) {
-			dev_err(rtd->dev,
-				"%s: Invalid param arg for ioctl %s session %d\n",
-				__func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG",
-				prtd->lsm_client->session);
-			rc = -EINVAL;
-			break;
+		if (copy_from_user(&mode, arg, sizeof(mode))) {
+			dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
+				__func__, "LSM_SET_FWK_MODE_CONFIG");
+			return -EFAULT;
 		}
-		mode = (u32 *)arg;
-		if (prtd->lsm_client->event_mode == *mode) {
+
+		dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n",
+			__func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG", mode);
+		if (prtd->lsm_client->event_mode == mode) {
 			dev_dbg(rtd->dev,
 				"%s: mode for %d already set to %d\n",
-				__func__, prtd->lsm_client->session, *mode);
+				__func__, prtd->lsm_client->session, mode);
 			rc = 0;
 		} else {
 			dev_dbg(rtd->dev, "%s: Event mode = %d\n",
-				 __func__, *mode);
-			rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, *mode);
+				 __func__, mode);
+			rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, mode);
 			if (!rc)
-				prtd->lsm_client->event_mode = *mode;
+				prtd->lsm_client->event_mode = mode;
 			else
 				dev_err(rtd->dev,
 					"%s: set event mode failed %d\n",