[Feature]Merge MP1_MR1 from MTK

Change-Id: I3fc364555acf14f1c308b6be7b05f21f92757fd0
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb-ivt-emmc.dts b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb-ivt-emmc.dts
old mode 100644
new mode 100755
index a383d58..442f46d
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb-ivt-emmc.dts
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb-ivt-emmc.dts
@@ -39,8 +39,10 @@
 		atag,videolfb-vramSize= <0x1be0000>;
 		atag,videolfb-lcmname=
 			"nt35595_fhd_dsi_cmd_truly_nt50358_drv";
+#if defined(CONFIG_MTK_AEE_FEATURE)
 		aee,enable = "mini";
 		mrdump,cblock = <0x12e000 0x2000>;
+#endif
 		atag,boot = <0x03000000 0x02080041 0x0>;
 	};
 
@@ -65,43 +67,17 @@
 };
 
 &snps_mac {
-	phy-mode ="rgmii-rxid";
-	phy-handle = <&eth_phy0>;
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&eth_default>;
-	pinctrl-1 = <&eth_sleep>;
-	mediatek,tx-delay-ps = <560>;
-	mediatek,rx-delay-ps = <1440>;
-	snps,reset-gpio = <&pio 24 GPIO_ACTIVE_LOW>;
-	snps,reset-active-low;
-	snps,reset-delays-us = <0 1000 0>;
 	status = "okay";
-
-	mdio {
+	phy-mode ="sgmii";
+	fixed-link {
+		speed = <1000>;
+		pause;
+		full-duplex;
+	};
+	snps_mdio: mdio-bus {
 		compatible = "snps,dwmac-mdio";
 		#address-cells = <1>;
 		#size-cells = <0>;
-		eth_phy0: eth_phy0@0 {
-			compatible = "ethernet-phy-id0022.1640";
-			phy-intr-gpio = <&pio 25 0>;
-			reg = <0x0>;
-			rxc-skew-psec = <4294967096>;
-			txc-skew-psec = <4294966596>;
-			txd0-skew-psec = <600>;
-			txd1-skew-psec = <600>;
-			txd2-skew-psec = <600>;
-			txd3-skew-psec = <600>;
-			txen-skew-psec = <600>;
-		};
-		eth_phy1: eth_phy1@7 {
-			compatible = "ethernet-phy-ieee802.3-c45";
-			marvell,88q2110 = <1000 0>;
-			reg = <0x7>;
-		};
-		eth_phy2: eth_phy2@4 {
-			compatible = "ethernet-phy-id0180.DD00";
-			reg = <0x4>;
-		};
 	};
 };
 
@@ -114,16 +90,6 @@
 	pinctrl-1 = <&eth_smi_mdio_pinctl>;
 	pinctrl-2 = <&eth_smi_mdc_pinctl>;
 	status = "okay";
-	gmac0: mac@0 {
-		compatible = "mediatek,eth-mac";
-		reg = <0>;
-		phy-mode = "sgmii";
-		fixed-link {
-			speed = <1000>;
-			full-duplex;
-			pause;
-		};
-	};
 	gmac1: mac@1 {
 		compatible = "mediatek,eth-mac";
 		reg = <1>;
@@ -861,7 +827,7 @@
 		mdio_pins {
 			pinmux = <PINMUX_GPIO12__FUNC_GBE_MDC>,
 				 <PINMUX_GPIO13__FUNC_GBE_MDIO>;
-			drive-strength = <4>;
+			drive-strength = <3>;
 			bias-disable;
 		};
 	};
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts
old mode 100644
new mode 100755
index 85f7d53..cb2b193
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts
@@ -35,8 +35,9 @@
 
 	chosen {
 		bootargs = "console=tty0 console=ttyS0,921600n1 ubi.mtd=14 \
-		root=ubi0_0 ubi.mtd=38,0,2 ubi.mtd=5,0,1 \
-		ubi.mtd=9,0,1 ubi.mtd=10,0,1 ubi.mtd=11,0,1 ubi.mtd=40,0,1 ubi.mtd=27,0,1\
+		ubi.mtd=38,0,2 ubi.mtd=5,0,1 \
+		ubi.mtd=9,0,1 ubi.mtd=10,0,1 ubi.mtd=11,0,1 ubi.mtd=40,0,1 \
+		ubi.mtd=27,0,1 ubi.mtd=20,0,1 ubi.mtd=22,0,1 \
 		rootwait \
 		androidboot.selinux=permissive androidboot.hardware=mt6890 \
 		initcall_debug=1 page_owner=on";
@@ -49,8 +50,10 @@
 		atag,videolfb-vramSize= <0x1be0000>;
 		atag,videolfb-lcmname=
 			"nt35595_fhd_dsi_cmd_truly_nt50358_drv";
+#if defined(CONFIG_MTK_AEE_FEATURE)
 		aee,enable = "mini";
 		mrdump,cblock = <0x12e000 0x2000>;
+#endif
 		atag,boot = <0x03000000 0x02080041 0x0>;
 	};
 
@@ -136,6 +139,7 @@
 	gmac0: mac@0 {
 		compatible = "mediatek,eth-mac";
 		reg = <0>;
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 		phy-mode = "sgmii";
 		phy-handle = <&eth_phy1>;
                 /*modify by chencheng 0817*/
@@ -146,22 +150,22 @@
 			pause;
 		};
 		*/
+#endif
 	};
-
+	
 	gmac1: mac@1 {
 		compatible = "mediatek,eth-mac";
 		reg = <1>;
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 		phy-mode = "sgmii";
-		//phy-handle = <&eth_phy2>;
-		
 		fixed-link {
 			speed = <1000>;
 			full-duplex;
 			pause;
 		};
-		
+#endif
 	};
-
+	
 	mdio: mdio-bus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -170,11 +174,6 @@
 			compatible = "ethernet-phy-ieee802.3-c22";
 			reg = <0x1>;
 		};
-		eth_phy2: eth_phy2@7 {   /*modify by chencheng 0817*/
-		    phy-mode = "sgmii";
-			compatible = "ethernet-phy-ieee802.3-c45";
-			reg = <0x7>;
-		};
 	};
 };
 
@@ -664,7 +663,7 @@
 		mdio_pins {
 			pinmux = <PINMUX_GPIO12__FUNC_GBE_MDC>,
 				 <PINMUX_GPIO13__FUNC_GBE_MDIO>;
-			drive-strength = <4>;
+			drive-strength = <3>;
 			bias-disable;
 
 		};
@@ -1343,6 +1342,7 @@
 /*zhengzhou 0316 ++++*/
 	compatible = "linux,extcon-usb-gpio";
 	vbus-voltage = <5000000>;
+	vbus-supply = <&otg_vbus>;
 	vbus-current = <1800000>;
 	/*zhengzhou 0316 ----*/
 };
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
old mode 100644
new mode 100755
index 013eb87..8d89be9
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
@@ -437,17 +437,14 @@
 			ftrace-size = <0x1000>;
 			pmsg-size = <0x10000>;
 		};
-
-		reserved-memory-aee {
-			reg = <0x0 0x4340a000 0x0 0x100000>;
-			compatible = "mediatek,aee-lk";
-		};
 		
+#if defined(CONFIG_MTK_AEE_FEATURE)
 		reserve-memory-emi_isu_buf {
 			compatible = "mediatek,emi_isu_buf";
 			no-map;
 			reg = <0 0x60800000 0 0x800000>;
 		};
+#endif
 
 		wocpu0_emi: wocpu0_emi@50000000 {
                         compatible = "mediatek,wocpu0_emi";
@@ -470,11 +467,13 @@
                         shared = <1>;
                 };
 
+#if defined(CONFIG_OPTEE)
 		reserve-memory-tee {
 			compatible = "mediatek,reserve-memory-tee";
 			no-map;
 			reg = <0 0x4e9a0000 0 0xb00000>;
 		};
+#endif
 	};
 
 	gic: interrupt-controller {
@@ -580,7 +579,8 @@
 			<&topckgen_clk CLK_TOP_SNPS_ETH_62P4M_PTP_SEL>,
 			<&topckgen_clk CLK_TOP_SNPS_ETH_50M_RMII_SEL>,
 			<&topckgen_clk CLK_TOP_EIP97_SEL>,
-			<&infracfg_ao_clk CLK_IFRAO_AUDIO_26M_BCLK>;
+			<&infracfg_ao_clk CLK_IFRAO_AUDIO_26M_BCLK>,
+			<&topckgen_clk CLK_TOP_HSM_ARC_SEL>;
 		clock-names = "mm",
 			"mfg",
 			"snps_eth_312p5m_sel",
@@ -588,7 +588,8 @@
 			"snps_ptp_sel",
 			"snps_rmii_sel",
 			"eip97_sel",
-			"audio";
+			"audio",
+			"hsm_sel";
 		/*status="disabled";*/
 	};
 
@@ -2442,6 +2443,7 @@
 			"pwm7";
 	};
 
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 	sgmii0@10060000 {
 		compatible = "mediatek,sgmii0";
 		reg = <0 0x10060000 0 0x8000>;
@@ -2453,6 +2455,7 @@
 		reg = <0 0x10070000 0 0x8000>;
 		interrupts = <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>;
 	};
+#endif
 
 	sys_cirq@10204000 {
 		compatible = "mediatek,sys_cirq";
@@ -3006,7 +3009,7 @@
 			  <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
 			  <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,/*zhengzhou uart*/
 			  <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;/*zhengzhou uart*/
-		dma-requests = <8>;
+		dma-requests = <6>;
 		dma-bits = <34>;
 		clocks = <&clk26m>;
 		#dma-cells = <1>;
@@ -3104,6 +3107,7 @@
 		status = "ok";
 	};
 
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 	pd-sgmii_0_phy {
 		compatible = "mediatek,sgmii-bring-up";
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_SGMII_0_PHY>;
@@ -3157,6 +3161,7 @@
         /*modify by CLK SW Pei-hsuan Cheng */
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_SGMII_1_PHY>;
 	};
+#endif
 
 	ethsys: ethsys@15000000 {
 		#address-cells = <1>;
@@ -3181,7 +3186,11 @@
         };
 
 	eth: ethernet@15100000 {
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 		compatible = "mediatek,mt6890-eth",
+#else
+		compatible = "mediatek,mt2735-eth",
+#endif
 			     "syscon";
 		reg = <0 0x15100000 0 0x20000>;
 		interrupts-extended = <&gic GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>,
@@ -3193,6 +3202,7 @@
 				<&gic GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>,
 				<&gic GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>,
 				<&pio 63 IRQ_TYPE_LEVEL_LOW>;
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 		clocks = <&topckgen_clk CLK_TOP_NETSYS_SEL>,
 			 <&topckgen_clk CLK_TOP_MEDSYS_SEL>,
 			 <&topckgen_clk CLK_TOP_NETSYS_500M_SEL>,
@@ -3204,17 +3214,31 @@
 		clock-names = "net_sel", "med_sel", "net_500_sel",
 			      "med_mcu_sel", "wed_mcu_sel",
 			      "net_2x_sel", "sgmii_sel", "sgmii_sbus_sel";
+#else
+		clocks = <&topckgen_clk CLK_TOP_NETSYS_SEL>,
+			 <&topckgen_clk CLK_TOP_MEDSYS_SEL>,
+			 <&topckgen_clk CLK_TOP_NETSYS_500M_SEL>,
+			 <&topckgen_clk CLK_TOP_NETSYS_MED_MCU_SEL>,
+			 <&topckgen_clk CLK_TOP_NETSYS_WED_MCU_SEL>,
+			 <&topckgen_clk CLK_TOP_NETSYS_2X_SEL>;
+		clock-names = "net_sel", "med_sel", "net_500_sel",
+			      "med_mcu_sel", "wed_mcu_sel",
+			      "net_2x_sel";
+#endif
         /*modify by CLK SW Pei-hsuan Cheng
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_NETSYS>;*/
 		mediatek,ethsys = <&ethsys>;
 		mediatek,wo = <&wo>;
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 		mediatek,sgmiisys = <&sgmiisys_0>,<&sgmiisys_1>;
 		mediatek,sgmiisys_phy = <&sgmiisys_phy_0>,<&sgmiisys_phy_1>;
+#endif
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "okay";
 	};
 
+#if defined(CONFIG_MTK_SGMII_NETSYS)
 	snps-pdsgmii_0_phy {
 		compatible = "mediatek,sgmii-up";
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_SGMII_0_PHY>;
@@ -3224,6 +3248,7 @@
 		compatible = "mediatek,sgmii-up";
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_SGMII_0_TOP>;
 	};
+#endif
 
 	stmmac_axi_setup: stmmac-axi-config {
 		snps,wr_osr_lmt = <0x7>;
@@ -3281,6 +3306,20 @@
 		interrupts = <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "macirq";
 		mac-address = [00 55 7b b5 7d f7];
+#if defined(CONFIG_MTK_SGMII_SNPS)
+		clock-names = "mac_main",
+			      "ptp_ref",
+			      "eth_cg",
+			      "eth_rmii",
+			      "sgmii_sel",
+			      "sgmii_sbus_sel";
+		clocks = <&topckgen_clk CLK_TOP_SNPS_ETH_312P5M_SEL>,
+			 <&topckgen_clk CLK_TOP_SNPS_ETH_62P4M_PTP_SEL>,
+			 <&topckgen_clk CLK_TOP_SNPS_ETH_250M_SEL>,
+			 <&topckgen_clk CLK_TOP_SNPS_ETH_50M_RMII_SEL>,
+			 <&topckgen_clk CLK_TOP_SGMII_SEL>,
+			 <&topckgen_clk CLK_TOP_SGMII_SBUS_SEL>;
+#else
 		clock-names = "mac_main",
 			      "ptp_ref",
 			      "eth_cg",
@@ -3289,12 +3328,17 @@
 			 <&topckgen_clk CLK_TOP_SNPS_ETH_62P4M_PTP_SEL>,
 			 <&topckgen_clk CLK_TOP_SNPS_ETH_250M_SEL>,
 			 <&topckgen_clk CLK_TOP_SNPS_ETH_50M_RMII_SEL>;
+#endif
 		mediatek,pericfg = <&infracfg_ao>;
 		snps,axi-config = <&stmmac_axi_setup>;
 		snps,mtl-rx-config = <&mtl_rx_setup>;
 		snps,mtl-tx-config = <&mtl_tx_setup>;
 		/*modify by CLK SW Pei-hsuan Cheng */
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_ETH>;
+#if defined(CONFIG_MTK_SGMII_SNPS)
+		mediatek,sgmiisys = <&sgmiisys_0>;
+		mediatek,sgmiisys_phy = <&sgmiisys_phy_0>;
+#endif
 		snps,txpbl = <16>;
 		snps,rxpbl = <16>;
 		clk_csr = <0>;
@@ -4386,7 +4430,7 @@
 	/*zhengzhou 0316 +++*/
 	    compatible = "linux,extcon-usb-gpio";
         id-gpio = <&pio 40 GPIO_ACTIVE_HIGH>;
-		//vbus-gpio = <&pio 42 GPIO_ACTIVE_HIGH>;//tianyan@2021.11.29 modify for usb otg
+		vbus-gpio = <&pio 42 GPIO_ACTIVE_HIGH>;//tianyan@2021.11.29 modify for usb otg
 		/*compatible = "mediatek,extcon-usb";*/
 	/*	dev-conn = <&ssusb>;*/
 	/*	 id-gpio = <&pio 12 GPIO_ACTIVE_HIGH>;*/
diff --git a/src/kernel/linux/v4.19/drivers/char/rpmb/drrpmb_gp/public/dci.h b/src/kernel/linux/v4.19/drivers/char/rpmb/drrpmb_gp/public/dci.h
old mode 100644
new mode 100755
index cd8ba4b..5dafab5
--- a/src/kernel/linux/v4.19/drivers/char/rpmb/drrpmb_gp/public/dci.h
+++ b/src/kernel/linux/v4.19/drivers/char/rpmb/drrpmb_gp/public/dci.h
@@ -1,15 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (c) 2013-2016 TRUSTONIC LIMITED
- * 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 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.
+ * Copyright (c) 2021 Mediatek Inc.
  */
 
 /**
diff --git a/src/kernel/linux/v4.19/drivers/clk/mediatek/clk-mt6890.c b/src/kernel/linux/v4.19/drivers/clk/mediatek/clk-mt6890.c
index de820bc..897d0ef 100755
--- a/src/kernel/linux/v4.19/drivers/clk/mediatek/clk-mt6890.c
+++ b/src/kernel/linux/v4.19/drivers/clk/mediatek/clk-mt6890.c
@@ -522,7 +522,9 @@
 			"netsys_sel", 1, 1),
 	FACTOR(CLK_TOP_MEDSYS, "medsys_ck",
 			"medsys_sel", 1, 1),
-	/* HSM isn't in kernel */
+	/* HSM CRYPTO isn't in kernel */
+	FACTOR(CLK_TOP_HSM_ARC, "hsm_arc_ck",
+			"hsm_arc_sel", 1, 1),
 	FACTOR(CLK_TOP_EIP97, "eip97_ck",
 			"eip97_sel", 1, 1),
 	FACTOR(CLK_TOP_SNPS_ETH_312P5M, "snps_eth_312p5m_ck",
@@ -857,6 +859,13 @@
 	"univpll_d7"
 };
 
+static const char * const hsm_arc_parents[] = {
+	"tck_26m_mx9_ck",
+	"mainpll_d4_d8",
+	"mainpll_d4_d4",
+	"mainpll_d6_d2"
+};
+
 static const char * const eip97_parents[] = {
 	"tck_26m_mx9_ck",
 	"net2pll_ck",
@@ -1174,9 +1183,13 @@
 		CLK_CFG_9_CLR/* set parent */, 16/* lsb */, 3/* width */,
 		INV_BIT/* pdn bit */, CLK_CFG_UPDATE1/* upd ofs */,
 		TOP_MUX_MEDSYS_SHIFT/* upd shift */),
-	/* HSM isn't in kernel */
+	/* HSM crypto isn't in kernel */
 	/* CLK_CFG_10 */
-	/* HSM isn't in kernel */
+	MUX_CLR_SET_UPD(CLK_TOP_HSM_ARC_SEL/* dts */, "hsm_arc_sel",
+		hsm_arc_parents/* parent */, CLK_CFG_10, CLK_CFG_10_SET,
+		CLK_CFG_10_CLR/* set parent */, 0/* lsb */, 2/* width */,
+		INV_BIT/* pdn bit */, CLK_CFG_UPDATE1/* upd ofs */,
+		TOP_MUX_HSM_ARC_SHIFT/* upd shift */),
 	MUX_CLR_SET_UPD(CLK_TOP_EIP97_SEL/* dts */, "eip97_sel",
 		eip97_parents/* parent */, CLK_CFG_10, CLK_CFG_10_SET,
 		CLK_CFG_10_CLR/* set parent */, 8/* lsb */, 3/* width */,
@@ -1445,8 +1458,13 @@
 		CLK_CFG_9_CLR/* set parent */, 16/* lsb */, 3/* width */,
 		23/* pdn */, CLK_CFG_UPDATE1/* upd ofs */,
 		TOP_MUX_MEDSYS_SHIFT/* upd shift */),
-	/* HSM isn't in kernel. */
+	/* HSM crypto isn't in kernel. */
 	/* CLK_CFG_10 */
+	MUX_CLR_SET_UPD(CLK_TOP_HSM_ARC_SEL/* dts */, "hsm_arc_sel",
+		hsm_arc_parents/* parent */, CLK_CFG_10, CLK_CFG_10_SET,
+		CLK_CFG_10_CLR/* set parent */, 0/* lsb */, 2/* width */,
+		7/* pdn */, CLK_CFG_UPDATE1/* upd ofs */,
+		TOP_MUX_HSM_ARC_SHIFT/* upd shift */),
 	MUX_CLR_SET_UPD(CLK_TOP_EIP97_SEL/* dts */, "eip97_sel",
 		eip97_parents/* parent */, CLK_CFG_10, CLK_CFG_10_SET,
 		CLK_CFG_10_CLR/* set parent */, 8/* lsb */, 3/* width */,
diff --git a/src/kernel/linux/v4.19/drivers/extcon/extcon-usb-gpio.c b/src/kernel/linux/v4.19/drivers/extcon/extcon-usb-gpio.c
old mode 100644
new mode 100755
index 5376286..aad7637
--- a/src/kernel/linux/v4.19/drivers/extcon/extcon-usb-gpio.c
+++ b/src/kernel/linux/v4.19/drivers/extcon/extcon-usb-gpio.c
@@ -76,8 +76,11 @@
 	/* check ID and VBUS and update cable state */
 	id = info->id_gpiod ?
 		gpiod_get_value_cansleep(info->id_gpiod) : 1;
+	//vbus = info->vbus_gpiod ?
+		//gpiod_get_value_cansleep(info->vbus_gpiod) : id;//tianyan@2021.11.29 modify for usb otg
+		
 	vbus = info->vbus_gpiod ?
-		gpiod_get_value_cansleep(info->vbus_gpiod) : id;
+		gpiod_get_value_cansleep(info->vbus_gpiod) : 0;//tianyan@2021.11.29 modify for usb otg
 
 	/* at first we clean states which are no longer active */
 	if (id)
@@ -217,6 +220,12 @@
 {
 	struct usb_extcon_info *info = dev_get_drvdata(dev);
 	int ret = 0;
+	
+	if (info->vbus_gpiod) {//tianyan@2021.11.29 modify for usb otg
+		ret = enable_irq_wake(info->vbus_irq);
+		if (ret) 
+			return ret;
+	}
 
 	if (device_may_wakeup(dev)) {
 		if (info->id_gpiod) {
@@ -256,6 +265,12 @@
 	struct usb_extcon_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (info->vbus_gpiod) {//tianyan@2021.11.29 modify for usb otg
+		ret = disable_irq_wake(info->vbus_irq);
+		if (ret) 
+			return ret;
+	}
+
 	if (!device_may_wakeup(dev))
 		pinctrl_pm_select_default_state(dev);
 
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/Makefile b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/Makefile
old mode 100644
new mode 100755
index 584b459..37b94b5
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/Makefile
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/Makefile
@@ -2,54 +2,28 @@
 
 obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 				       mtk-vcodec-enc.o \
-				       mtk-vcodec-common.o \
+				       mtk-vcodec-common.o
 
-mtk-vcodec-dec-y := mtk_vcodec_dec_drv.o \
-		vdec_drv_if.o \
-		mtk_vcodec_dec.o \
-		mtk_vcodec_dec_stateful.o \
-		mtk_vcodec_dec_stateless.o \
-		mtk_vcodec_dec_pm.o \
-		mtk_vcodec_fw.o \
-		vcodec_dvfs.o \
-
-ifdef CONFIG_VIDEO_MEDIATEK_VCU
-	mtk-vcodec-dec-y += vdec/vdec_common_if.o \
-		vdec_vcu_if.o
-endif
-ifdef CONFIG_VIDEO_MEDIATEK_VPU
-	mtk-vcodec-dec-y += vdec/vdec_h264_if.o \
-		vdec/vdec_h264_req_if.o \
+mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
 		vdec/vdec_vp8_if.o \
 		vdec/vdec_vp9_if.o \
-		vdec_vpu_if.o
-endif
+		mtk_vcodec_dec_drv.o \
+		vdec_drv_if.o \
+		vdec_vpu_if.o \
+		mtk_vcodec_dec.o \
+		mtk_vcodec_dec_pm.o \
 
-mtk-vcodec-enc-y := mtk_vcodec_enc.o \
+
+mtk-vcodec-enc-y := venc/venc_vp8_if.o \
+		venc/venc_h264_if.o \
+		mtk_vcodec_enc.o \
 		mtk_vcodec_enc_drv.o \
 		mtk_vcodec_enc_pm.o \
 		venc_drv_if.o \
-
-ifdef CONFIG_VIDEO_MEDIATEK_VCU
-	mtk-vcodec-enc-y += venc/venc_common_if.o \
-		venc_vcu_if.o
-endif
-ifdef CONFIG_VIDEO_MEDIATEK_VPU
-	mtk-vcodec-enc-y += venc/venc_vp8_if.o \
-		venc/venc_h264_if.o \
-		venc_vpu_if.o
-endif
+		venc_vpu_if.o \
 
 
 mtk-vcodec-common-y := mtk_vcodec_intr.o \
 		mtk_vcodec_util.o\
 
-ifdef CONFIG_VIDEO_MEDIATEK_VCU
-	ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vcu
-endif
-ifdef CONFIG_VIDEO_MEDIATEK_VPU
-	ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vpu
-endif
-ifdef CONFIG_VB2_MEDIATEK_DMA
-	ccflags-y += -I$(srctree)/drivers/media/platform/mtk-videobuf
-endif
+ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vpu
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
old mode 100644
new mode 100755
index 44480be..0c8a8b4
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -16,7 +16,6 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-dma-contig.h>
-#include <linux/delay.h>
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_dec.h"
@@ -25,122 +24,72 @@
 #include "vdec_drv_if.h"
 #include "mtk_vcodec_dec_pm.h"
 
+#define OUT_FMT_IDX	0
+#define CAP_FMT_IDX	3
+
+#define MTK_VDEC_MIN_W	64U
+#define MTK_VDEC_MIN_H	64U
 #define DFT_CFG_WIDTH	MTK_VDEC_MIN_W
 #define DFT_CFG_HEIGHT	MTK_VDEC_MIN_H
 
-static struct mtk_video_fmt
-	mtk_video_formats[MTK_MAX_DEC_CODECS_SUPPORT] = { {0} };
-static struct mtk_codec_framesizes
-	mtk_vdec_framesizes[MTK_MAX_DEC_CODECS_SUPPORT] = { {0} };
-static struct mtk_video_fmt *default_out_fmt;
-static struct mtk_video_fmt *default_cap_fmt;
+static struct mtk_video_fmt mtk_video_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MT21C,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+};
+
+static const struct mtk_codec_framesizes mtk_vdec_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc	= V4L2_PIX_FMT_VP8,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+};
 
 #define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_vdec_framesizes)
 #define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
 
-static void get_supported_format(struct mtk_vcodec_ctx *ctx)
-{
-	unsigned int i;
-	const struct mtk_video_fmt *fmt = NULL;
-	const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
-
-	memcpy(mtk_video_formats, dec_pdata->vdec_formats,
-		sizeof(struct mtk_video_fmt) * dec_pdata->num_formats);
-	for (i = 0; i < dec_pdata->num_formats; i++) {
-		fmt = &dec_pdata->vdec_formats[i];
-		if (dec_pdata->default_out_fmt == fmt)
-			default_out_fmt = &mtk_video_formats[i];
-
-		if (dec_pdata->default_cap_fmt == fmt)
-			default_cap_fmt = &mtk_video_formats[i];
-	}
-
-	if (vdec_if_get_param(ctx,
-		GET_PARAM_CAPABILITY_SUPPORTED_FORMATS,
-		&mtk_video_formats)  != 0) {
-		mtk_v4l2_debug(1, "warning!! Cannot get supported format");
-		return;
-	}
-
-	for (i = 0; i < MTK_MAX_DEC_CODECS_SUPPORT; i++) {
-		if (mtk_video_formats[i].fourcc != 0)
-			mtk_v4l2_debug(1,
-			  "fmt[%d] fourcc %d type %d planes %d",
-			  i, mtk_video_formats[i].fourcc,
-			  mtk_video_formats[i].type,
-			  mtk_video_formats[i].num_planes);
-	}
-	for (i = 0; i < MTK_MAX_DEC_CODECS_SUPPORT; i++) {
-		if (mtk_video_formats[i].fourcc != 0 &&
-			mtk_video_formats[i].type == MTK_FMT_DEC) {
-			default_out_fmt = &mtk_video_formats[i];
-			break;
-		}
-	}
-	for (i = 0; i < MTK_MAX_DEC_CODECS_SUPPORT; i++) {
-		if (mtk_video_formats[i].fourcc != 0 &&
-			mtk_video_formats[i].type == MTK_FMT_FRAME) {
-			default_cap_fmt = &mtk_video_formats[i];
-			break;
-		}
-	}
-}
-
-static struct mtk_video_fmt *mtk_vdec_find_format(struct mtk_vcodec_ctx *ctx,
-	struct v4l2_format *f, unsigned int t)
+static struct mtk_video_fmt *mtk_vdec_find_format(struct v4l2_format *f)
 {
 	struct mtk_video_fmt *fmt;
 	unsigned int k;
 
-	mtk_v4l2_debug(3, "[%d] fourcc %d", ctx->id, f->fmt.pix_mp.pixelformat);
-	for (k = 0; k < MTK_MAX_DEC_CODECS_SUPPORT &&
-		 mtk_video_formats[k].fourcc != 0; k++) {
+	for (k = 0; k < NUM_FORMATS; k++) {
 		fmt = &mtk_video_formats[k];
-		if (fmt->fourcc == f->fmt.pix_mp.pixelformat &&
-			mtk_video_formats[k].type == t)
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
 			return fmt;
 	}
 
 	return NULL;
 }
 
-void mtk_vdec_update_fmt(struct mtk_vcodec_ctx *ctx,
-				unsigned int pixelformat)
-{
-	const struct mtk_video_fmt *fmt;
-	struct mtk_q_data *dst_q_data;
-	unsigned int k;
-
-	dst_q_data = &ctx->q_data[MTK_Q_DATA_DST];
-	for (k = 0; k < MTK_MAX_DEC_CODECS_SUPPORT; k++) {
-		fmt = &mtk_video_formats[k];
-		if (fmt->fourcc == pixelformat) {
-			mtk_v4l2_debug(1, "Update cap fourcc(%d -> %d)",
-				dst_q_data->fmt->fourcc, pixelformat);
-			dst_q_data->fmt = fmt;
-			return;
-		}
-	}
-
-	mtk_v4l2_err("Cannot get fourcc(%d), using init value", pixelformat);
-}
-
-struct mtk_video_fmt *mtk_find_fmt_by_pixel(unsigned int pixelformat)
-{
-	struct mtk_video_fmt *fmt;
-	unsigned int k;
-
-	for (k = 0; k < MTK_MAX_DEC_CODECS_SUPPORT; k++) {
-		fmt = &mtk_video_formats[k];
-		if (fmt->fourcc == pixelformat)
-			return fmt;
-	}
-	mtk_v4l2_err("Error!! Cannot find fourcc: %d use default", pixelformat);
-
-	return default_out_fmt;
-}
-
-
 static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
 					      enum v4l2_buf_type type)
 {
@@ -150,6 +99,369 @@
 	return &ctx->q_data[MTK_Q_DATA_DST];
 }
 
+/*
+ * This function tries to clean all display buffers, the buffers will return
+ * in display order.
+ * Note the buffers returned from codec driver may still be in driver's
+ * reference list.
+ */
+static struct vb2_buffer *get_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vdec_fb *disp_frame_buffer = NULL;
+	struct mtk_video_dec_buf *dstbuf;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	if (vdec_if_get_param(ctx,
+			GET_PARAM_DISP_FRAME_BUFFER,
+			&disp_frame_buffer)) {
+		mtk_v4l2_err("[%d]Cannot get param : GET_PARAM_DISP_FRAME_BUFFER",
+			ctx->id);
+		return NULL;
+	}
+
+	if (disp_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, "No display frame buffer");
+		return NULL;
+	}
+
+	dstbuf = container_of(disp_frame_buffer, struct mtk_video_dec_buf,
+				frame_buffer);
+	mutex_lock(&ctx->lock);
+	if (dstbuf->used) {
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0,
+					ctx->picinfo.y_bs_sz);
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1,
+					ctx->picinfo.c_bs_sz);
+
+		dstbuf->ready_to_display = true;
+
+		mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to done_list %d",
+				ctx->id, disp_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+
+		v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
+		ctx->decoded_frame_cnt++;
+	}
+	mutex_unlock(&ctx->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+/*
+ * This function tries to clean all capture buffers that are not used as
+ * reference buffers by codec driver any more
+ * In this case, we need re-queue buffer to vb2 buffer if user space
+ * already returns this buffer to v4l2 or this buffer is just the output of
+ * previous sps/pps/resolution change decode, or do nothing if user
+ * space still owns this buffer
+ */
+static struct vb2_buffer *get_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_video_dec_buf *dstbuf;
+	struct vdec_fb *free_frame_buffer = NULL;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_FREE_FRAME_BUFFER,
+				&free_frame_buffer)) {
+		mtk_v4l2_err("[%d] Error!! Cannot get param", ctx->id);
+		return NULL;
+	}
+	if (free_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, " No free frame buffer");
+		return NULL;
+	}
+
+	mtk_v4l2_debug(3, "[%d] tmp_frame_addr = 0x%p",
+			ctx->id, free_frame_buffer);
+
+	dstbuf = container_of(free_frame_buffer, struct mtk_video_dec_buf,
+				frame_buffer);
+
+	mutex_lock(&ctx->lock);
+	if (dstbuf->used) {
+		if ((dstbuf->queued_in_vb2) &&
+		    (dstbuf->queued_in_v4l2) &&
+		    (free_frame_buffer->status == FB_ST_FREE)) {
+			/*
+			 * After decode sps/pps or non-display buffer, we don't
+			 * need to return capture buffer to user space, but
+			 * just re-queue this capture buffer to vb2 queue.
+			 * This reduce overheads that dq/q unused capture
+			 * buffer. In this case, queued_in_vb2 = true.
+			 */
+			mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to rdy_queue %d",
+				ctx->id, free_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+		} else if ((dstbuf->queued_in_vb2 == false) &&
+			   (dstbuf->queued_in_v4l2 == true)) {
+			/*
+			 * If buffer in v4l2 driver but not in vb2 queue yet,
+			 * and we get this buffer from free_list, it means
+			 * that codec driver do not use this buffer as
+			 * reference buffer anymore. We should q buffer to vb2
+			 * queue, so later work thread could get this buffer
+			 * for decode. In this case, queued_in_vb2 = false
+			 * means this buffer is not from previous decode
+			 * output.
+			 */
+			mtk_v4l2_debug(2,
+					"[%d]status=%x queue id=%d to rdy_queue",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+			dstbuf->queued_in_vb2 = true;
+		} else {
+			/*
+			 * Codec driver do not need to reference this capture
+			 * buffer and this buffer is not in v4l2 driver.
+			 * Then we don't need to do any thing, just add log when
+			 * we need to debug buffer flow.
+			 * When this buffer q from user space, it could
+			 * directly q to vb2 buffer
+			 */
+			mtk_v4l2_debug(3, "[%d]status=%x err queue id=%d %d %d",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index,
+					dstbuf->queued_in_vb2,
+					dstbuf->queued_in_v4l2);
+		}
+		dstbuf->used = false;
+	}
+	mutex_unlock(&ctx->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+static void clean_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_display_buffer(ctx);
+	} while (framptr);
+}
+
+static void clean_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_free_buffer(ctx);
+	} while (framptr);
+}
+
+static void mtk_vdec_queue_res_chg_event(struct mtk_vcodec_ctx *ctx)
+{
+	static const struct v4l2_event ev_src_ch = {
+		.type = V4L2_EVENT_SOURCE_CHANGE,
+		.u.src_change.changes =
+		V4L2_EVENT_SRC_CH_RESOLUTION,
+	};
+
+	mtk_v4l2_debug(1, "[%d]", ctx->id);
+	v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+}
+
+static void mtk_vdec_flush_decoder(struct mtk_vcodec_ctx *ctx)
+{
+	bool res_chg;
+	int ret = 0;
+
+	ret = vdec_if_decode(ctx, NULL, NULL, &res_chg);
+	if (ret)
+		mtk_v4l2_err("DecodeFinal failed, ret=%d", ret);
+
+	clean_display_buffer(ctx);
+	clean_free_buffer(ctx);
+}
+
+static int mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx)
+{
+	unsigned int dpbsize = 0;
+	int ret;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_PIC_INFO,
+				&ctx->last_decoded_picinfo)) {
+		mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+				ctx->id);
+		return -EINVAL;
+	}
+
+	if (ctx->last_decoded_picinfo.pic_w == 0 ||
+		ctx->last_decoded_picinfo.pic_h == 0 ||
+		ctx->last_decoded_picinfo.buf_w == 0 ||
+		ctx->last_decoded_picinfo.buf_h == 0) {
+		mtk_v4l2_err("Cannot get correct pic info");
+		return -EINVAL;
+	}
+
+	if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h))
+		return 0;
+
+	mtk_v4l2_debug(1,
+			"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
+			ctx->id, ctx->last_decoded_picinfo.pic_w,
+			ctx->last_decoded_picinfo.pic_h,
+			ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+			ctx->last_decoded_picinfo.buf_w,
+			ctx->last_decoded_picinfo.buf_h);
+
+	ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+	if (dpbsize == 0)
+		mtk_v4l2_err("Incorrect dpb size, ret=%d", ret);
+
+	ctx->dpb_size = dpbsize;
+
+	return ret;
+}
+
+static void mtk_vdec_worker(struct work_struct *work)
+{
+	struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx,
+				decode_work);
+	struct mtk_vcodec_dev *dev = ctx->dev;
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct mtk_vcodec_mem buf;
+	struct vdec_fb *pfb;
+	bool res_chg = false;
+	int ret;
+	struct mtk_video_dec_buf *dst_buf_info, *src_buf_info;
+	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (src_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] src_buf empty!!", ctx->id);
+		return;
+	}
+
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	if (dst_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] dst_buf empty!!", ctx->id);
+		return;
+	}
+
+	src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
+	src_buf_info = container_of(src_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
+	dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	pfb = &dst_buf_info->frame_buffer;
+	pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+	pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz;
+
+	pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
+	pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+	pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz;
+	pfb->status = 0;
+	mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id);
+
+	mtk_v4l2_debug(3,
+			"id=%d Framebuf  pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad Size=%zx",
+			dst_buf->index, pfb,
+			pfb->base_y.va, &pfb->base_y.dma_addr,
+			&pfb->base_c.dma_addr, pfb->base_y.size);
+
+	if (src_buf_info->lastframe) {
+		mtk_v4l2_debug(1, "Got empty flush input buffer.");
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+		/* update dst buf status */
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		mutex_lock(&ctx->lock);
+		dst_buf_info->used = false;
+		mutex_unlock(&ctx->lock);
+
+		vdec_if_decode(ctx, NULL, NULL, &res_chg);
+		clean_display_buffer(ctx);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 0, 0);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 1, 0);
+		dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST;
+		v4l2_m2m_buf_done(&dst_buf_info->vb, VB2_BUF_STATE_DONE);
+		clean_free_buffer(ctx);
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		return;
+	}
+	buf.va = vb2_plane_vaddr(src_buf, 0);
+	buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	buf.size = (size_t)src_buf->planes[0].bytesused;
+	if (!buf.va) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_err("[%d] id=%d src_addr is NULL!!",
+				ctx->id, src_buf->index);
+		return;
+	}
+	mtk_v4l2_debug(3, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p",
+			ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf);
+	dst_buf_info->vb.vb2_buf.timestamp
+			= src_buf_info->vb.vb2_buf.timestamp;
+	dst_buf_info->vb.timecode
+			= src_buf_info->vb.timecode;
+	mutex_lock(&ctx->lock);
+	dst_buf_info->used = true;
+	mutex_unlock(&ctx->lock);
+	src_buf_info->used = true;
+
+	ret = vdec_if_decode(ctx, &buf, pfb, &res_chg);
+
+	if (ret) {
+		mtk_v4l2_err(
+			" <===[%d], src_buf[%d] sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>",
+			ctx->id,
+			src_buf->index,
+			buf.size,
+			src_buf_info->vb.vb2_buf.timestamp,
+			dst_buf->index,
+			ret, res_chg);
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		if (ret == -EIO) {
+			mutex_lock(&ctx->lock);
+			src_buf_info->error = true;
+			mutex_unlock(&ctx->lock);
+		}
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
+	} else if (res_chg == false) {
+		/*
+		 * we only return src buffer with VB2_BUF_STATE_DONE
+		 * when decode success without resolution change
+		 */
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
+	}
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	clean_display_buffer(ctx);
+	clean_free_buffer(ctx);
+
+	if (!ret && res_chg) {
+		mtk_vdec_pic_info_update(ctx);
+		/*
+		 * On encountering a resolution change in the stream.
+		 * The driver must first process and decode all
+		 * remaining buffers from before the resolution change
+		 * point, so call flush decode here
+		 */
+		mtk_vdec_flush_decoder(ctx);
+		/*
+		 * After all buffers containing decoded frames from
+		 * before the resolution change point ready to be
+		 * dequeued on the CAPTURE queue, the driver sends a
+		 * V4L2_EVENT_SOURCE_CHANGE event for source change
+		 * type V4L2_EVENT_SRC_CH_RESOLUTION
+		 */
+		mtk_vdec_queue_res_chg_event(ctx);
+	}
+	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+}
+
 static int vidioc_try_decoder_cmd(struct file *file, void *priv,
 				struct v4l2_decoder_cmd *cmd)
 {
@@ -157,7 +469,8 @@
 	case V4L2_DEC_CMD_STOP:
 	case V4L2_DEC_CMD_START:
 		if (cmd->flags != 0) {
-			mtk_v4l2_debug(1, "cmd->flags=%u", cmd->flags);
+			mtk_v4l2_err("cmd->flags=%u", cmd->flags);
+			return -EINVAL;
 		}
 		break;
 	default:
@@ -173,13 +486,12 @@
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
 	struct vb2_queue *src_vq, *dst_vq;
 	int ret;
-	const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
 
 	ret = vidioc_try_decoder_cmd(file, priv, cmd);
 	if (ret)
 		return ret;
 
-	mtk_v4l2_debug(1, "decoder cmd=%u, flag=%u", cmd->cmd, cmd->flags);
+	mtk_v4l2_debug(1, "decoder cmd=%u", cmd->cmd);
 	dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
 				V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 	switch (cmd->cmd) {
@@ -190,12 +502,9 @@
 			mtk_v4l2_debug(1, "Output stream is off. No need to flush.");
 			return 0;
 		}
-		if (!dec_pdata->uses_stateless_api) {
-			ctx->empty_flush_buf->lastframe = true;
-			if (cmd->flags & V4L2_BUF_FLAG_EARLY_EOS)
-				ctx->empty_flush_buf->isEarlyEos = true;
-			else
-				ctx->empty_flush_buf->isEarlyEos = false;
+		if (!vb2_is_streaming(dst_vq)) {
+			mtk_v4l2_debug(1, "Capture stream is off. No need to flush.");
+			return 0;
 		}
 		v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb);
 		v4l2_m2m_try_schedule(ctx->m2m_ctx);
@@ -214,52 +523,17 @@
 
 void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx)
 {
-	mtk_v4l2_debug(4, "ctx %p [%d]", ctx, ctx->id);
 	mutex_unlock(&ctx->dev->dec_mutex);
 }
 
 void mtk_vdec_lock(struct mtk_vcodec_ctx *ctx)
 {
-	unsigned int suspend_block_cnt = 0;
-
-	while (ctx->dev->is_codec_suspending == 1) {
-		suspend_block_cnt++;
-		if (suspend_block_cnt > SUSPEND_TIMEOUT_CNT) {
-			mtk_v4l2_debug(4, "VDEC blocked by suspend\n");
-			suspend_block_cnt = 0;
-		}
-		usleep_range(10000, 20000);
-	}
-
-	mtk_v4l2_debug(4, "ctx %p [%d]", ctx, ctx->id);
 	mutex_lock(&ctx->dev->dec_mutex);
 }
 
-void mtk_vcodec_dec_empty_queues(struct mtk_vcodec_ctx *ctx)
-{
-	struct vb2_v4l2_buffer *src_buf = NULL, *dst_buf = NULL;
-	struct vb2_v4l2_buffer *last_buf = NULL;
-	int i = 0;
-
-	last_buf = &ctx->empty_flush_buf->vb;
-	while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) {
-		if (last_buf != src_buf)
-			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
-	}
-
-	while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
-		for (i = 0; i < dst_buf->vb2_buf.num_planes; i++)
-			vb2_set_plane_payload(&dst_buf->vb2_buf, i, 0);
-		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
-	}
-
-	ctx->state = MTK_STATE_FREE;
-}
-
 void mtk_vcodec_dec_release(struct mtk_vcodec_ctx *ctx)
 {
 	vdec_if_deinit(ctx);
-	memset(mtk_vdec_framesizes, 0, sizeof(mtk_vdec_framesizes));
 	ctx->state = MTK_STATE_FREE;
 }
 
@@ -267,23 +541,20 @@
 {
 	struct mtk_q_data *q_data;
 
-	ctx->dev->vdec_pdata->init_vdec_params(ctx);
-
 	ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
 	ctx->fh.m2m_ctx = ctx->m2m_ctx;
 	ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
-	INIT_WORK(&ctx->decode_work, ctx->dev->vdec_pdata->worker);
+	INIT_WORK(&ctx->decode_work, mtk_vdec_worker);
 	ctx->colorspace = V4L2_COLORSPACE_REC709;
 	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
 	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
-	get_supported_format(ctx);
 
 	q_data = &ctx->q_data[MTK_Q_DATA_SRC];
 	memset(q_data, 0, sizeof(struct mtk_q_data));
 	q_data->visible_width = DFT_CFG_WIDTH;
 	q_data->visible_height = DFT_CFG_HEIGHT;
-	q_data->fmt = default_out_fmt;
+	q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
 	q_data->field = V4L2_FIELD_NONE;
 
 	q_data->sizeimage[0] = DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
@@ -295,7 +566,7 @@
 	q_data->visible_height = DFT_CFG_HEIGHT;
 	q_data->coded_width = DFT_CFG_WIDTH;
 	q_data->coded_height = DFT_CFG_HEIGHT;
-	q_data->fmt = default_cap_fmt;
+	q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
 	q_data->field = V4L2_FIELD_NONE;
 
 	v4l_bound_align_image(&q_data->coded_width,
@@ -311,126 +582,10 @@
 	q_data->bytesperline[1] = q_data->coded_width;
 }
 
-int mtk_vdec_set_param(struct mtk_vcodec_ctx *ctx)
-{
-	unsigned long in[8] = {0};
-
-	mtk_v4l2_debug(4,
-		"[%d] param change %d decode mode %d frame width %d frame height %d max width %d max height %d",
-		ctx->id, ctx->dec_param_change,
-		ctx->dec_params.decode_mode,
-		ctx->dec_params.frame_size_width,
-		ctx->dec_params.frame_size_height,
-		ctx->dec_params.fixed_max_frame_size_width,
-		ctx->dec_params.fixed_max_frame_size_height);
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_DECODE_MODE) {
-		in[0] = ctx->dec_params.decode_mode;
-		if (vdec_if_set_param(ctx, SET_PARAM_DECODE_MODE, in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_DECODE_MODE);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_FRAME_SIZE) {
-		in[0] = ctx->dec_params.frame_size_width;
-		in[1] = ctx->dec_params.frame_size_height;
-		if (in[0] != 0 && in[1] != 0) {
-			if (vdec_if_set_param(ctx,
-				SET_PARAM_FRAME_SIZE, in) != 0) {
-				mtk_v4l2_err("[%d] Error!! Cannot set param",
-					ctx->id);
-				return -EINVAL;
-			}
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_FRAME_SIZE);
-	}
-
-	if (ctx->dec_param_change &
-		MTK_DEC_PARAM_FIXED_MAX_FRAME_SIZE) {
-		in[0] = ctx->dec_params.fixed_max_frame_size_width;
-		in[1] = ctx->dec_params.fixed_max_frame_size_height;
-		if (in[0] != 0 && in[1] != 0) {
-			if (vdec_if_set_param(ctx,
-				SET_PARAM_SET_FIXED_MAX_OUTPUT_BUFFER,
-				in) != 0) {
-				mtk_v4l2_err("[%d] Error!! Cannot set param",
-					ctx->id);
-				return -EINVAL;
-			}
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_FIXED_MAX_FRAME_SIZE);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_CRC_PATH) {
-		in[0] = (unsigned long)ctx->dec_params.crc_path;
-		if (vdec_if_set_param(ctx, SET_PARAM_CRC_PATH, in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_CRC_PATH);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_GOLDEN_PATH) {
-		in[0] = (unsigned long)ctx->dec_params.golden_path;
-		if (vdec_if_set_param(ctx, SET_PARAM_GOLDEN_PATH, in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_GOLDEN_PATH);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_WAIT_KEY_FRAME) {
-		in[0] = (unsigned long)ctx->dec_params.wait_key_frame;
-		if (vdec_if_set_param(ctx, SET_PARAM_WAIT_KEY_FRAME, in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_WAIT_KEY_FRAME);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_NAL_SIZE_LENGTH) {
-		in[0] = (unsigned long)ctx->dec_params.wait_key_frame;
-		if (vdec_if_set_param(ctx, SET_PARAM_NAL_SIZE_LENGTH,
-					in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_NAL_SIZE_LENGTH);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_OPERATING_RATE) {
-		in[0] = (unsigned long)ctx->dec_params.operating_rate;
-		if (vdec_if_set_param(ctx, SET_PARAM_OPERATING_RATE, in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &= (~MTK_DEC_PARAM_OPERATING_RATE);
-	}
-
-	if (ctx->dec_param_change & MTK_DEC_PARAM_TOTAL_FRAME_BUFQ_COUNT) {
-		in[0] = (unsigned long)ctx->dec_params.total_frame_bufq_count;
-		if (vdec_if_set_param
-			(ctx, SET_PARAM_TOTAL_FRAME_BUFQ_COUNT, in) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot set param", ctx->id);
-			return -EINVAL;
-		}
-		ctx->dec_param_change &=
-			(~MTK_DEC_PARAM_TOTAL_FRAME_BUFQ_COUNT);
-	}
-
-	return 0;
-}
-
 static int vidioc_vdec_qbuf(struct file *file, void *priv,
 			    struct v4l2_buffer *buf)
 {
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
-	struct vb2_queue *vq;
-	struct vb2_buffer *vb;
-	struct mtk_video_dec_buf *mtkbuf;
-	struct vb2_v4l2_buffer  *vb2_v4l2;
 
 	if (ctx->state == MTK_STATE_ABORT) {
 		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
@@ -438,56 +593,13 @@
 		return -EIO;
 	}
 
-	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
-	vb = vq->bufs[buf->index];
-	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-	mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
-
-	if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		ctx->input_max_ts =
-			(timeval_to_ns(&buf->timestamp) > ctx->input_max_ts) ?
-			timeval_to_ns(&buf->timestamp) : ctx->input_max_ts;
-
-		mtkbuf->lastframe = false;
-		mtkbuf->isEarlyEos = false;
-		if (buf->flags & V4L2_BUF_FLAG_LAST)
-			mtkbuf->isEarlyEos = true;
-		mtk_v4l2_debug(1, "[%d] id=%d getdata BS(%d,%d) vb=%p pts=%llu %llu %d",
-			ctx->id, buf->index,
-			buf->m.planes[0].bytesused,
-			buf->length, vb,
-			timeval_to_ns(&buf->timestamp),
-			ctx->input_max_ts,
-			mtkbuf->isEarlyEos);
-	} else
-		mtk_v4l2_debug(1, "[%d] id=%d FB (%d) vb=%p",
-				ctx->id, buf->index,
-				buf->length, mtkbuf);
-
-	if (buf->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN) {
-		mtk_v4l2_debug(4, "[%d] No need for Cache clean, buf->index:%d. mtkbuf:%p",
-			ctx->id, buf->index, mtkbuf);
-		mtkbuf->flags |= NO_CAHCE_CLEAN;
-	}
-
-	if (buf->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE) {
-		mtk_v4l2_debug(4, "[%d] No need for Cache invalidate, buf->index:%d. mtkbuf:%p",
-			ctx->id, buf->index, mtkbuf);
-		mtkbuf->flags |= NO_CAHCE_INVALIDATE;
-	}
-
 	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
 }
 
 static int vidioc_vdec_dqbuf(struct file *file, void *priv,
 			     struct v4l2_buffer *buf)
 {
-	int ret = 0;
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
-	struct vb2_queue *vq;
-	struct vb2_buffer *vb;
-	struct mtk_video_dec_buf *mtkbuf;
-	struct vb2_v4l2_buffer  *vb2_v4l2;
 
 	if (ctx->state == MTK_STATE_ABORT) {
 		mtk_v4l2_err("[%d] Call on DQBUF after unrecoverable error",
@@ -495,34 +607,16 @@
 		return -EIO;
 	}
 
-	ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-	buf->reserved = ctx->errormap_info[buf->index % VB2_MAX_FRAME];
-
-	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
-		ret == 0) {
-		vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
-		vb = vq->bufs[buf->index];
-		vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-		mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
-
-		if (mtkbuf->flags & CROP_CHANGED)
-			buf->flags |= V4L2_BUF_FLAG_CROP_CHANGED;
-		if (mtkbuf->flags & REF_FREED)
-			buf->flags |= V4L2_BUF_FLAG_REF_FREED;
-	}
-
-	return ret;
+	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 }
 
 static int vidioc_vdec_querycap(struct file *file, void *priv,
 				struct v4l2_capability *cap)
 {
-	strscpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
-	strscpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
-	strscpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+	strlcpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
 
-	cap->device_caps  = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -534,17 +628,12 @@
 		return v4l2_event_subscribe(fh, sub, 2, NULL);
 	case V4L2_EVENT_SOURCE_CHANGE:
 		return v4l2_src_change_event_subscribe(fh, sub);
-	case V4L2_EVENT_VDEC_ERROR:
-		return v4l2_event_subscribe(fh, sub, 0, NULL);
-	case V4L2_EVENT_MTK_VDEC_NOHEADER:
-		return v4l2_event_subscribe(fh, sub, 0, NULL);
 	default:
 		return v4l2_ctrl_subscribe_event(fh, sub);
 	}
 }
 
-static int vidioc_try_fmt(struct v4l2_format *f,
-			  const struct mtk_video_fmt *fmt)
+static int vidioc_try_fmt(struct v4l2_format *f, struct mtk_video_fmt *fmt)
 {
 	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
 	int i;
@@ -617,14 +706,12 @@
 static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	const struct mtk_video_fmt *fmt;
-	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct mtk_video_fmt *fmt;
 
-	fmt = mtk_vdec_find_format(ctx, f, MTK_FMT_FRAME);
+	fmt = mtk_vdec_find_format(f);
 	if (!fmt) {
-		f->fmt.pix.pixelformat =
-			ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc;
-		fmt = mtk_vdec_find_format(ctx, f, MTK_FMT_FRAME);
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
 	}
 
 	return vidioc_try_fmt(f, fmt);
@@ -634,14 +721,12 @@
 				struct v4l2_format *f)
 {
 	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-	const struct mtk_video_fmt *fmt;
-	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct mtk_video_fmt *fmt;
 
-	fmt = mtk_vdec_find_format(ctx, f, MTK_FMT_DEC);
+	fmt = mtk_vdec_find_format(f);
 	if (!fmt) {
-		f->fmt.pix.pixelformat =
-			ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc;
-		fmt = mtk_vdec_find_format(ctx, f, MTK_FMT_DEC);
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
 	}
 
 	if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
@@ -665,21 +750,18 @@
 
 	switch (s->target) {
 	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-	case V4L2_SEL_TGT_CROP_DEFAULT:
 		s->r.left = 0;
 		s->r.top = 0;
 		s->r.width = ctx->picinfo.pic_w;
 		s->r.height = ctx->picinfo.pic_h;
 		break;
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-	case V4L2_SEL_TGT_CROP_BOUNDS:
 		s->r.left = 0;
 		s->r.top = 0;
 		s->r.width = ctx->picinfo.buf_w;
 		s->r.height = ctx->picinfo.buf_h;
 		break;
 	case V4L2_SEL_TGT_COMPOSE:
-	case V4L2_SEL_TGT_CROP:
 		if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) {
 			/* set to default value if header info not ready yet*/
 			s->r.left = 0;
@@ -714,7 +796,6 @@
 
 	switch (s->target) {
 	case V4L2_SEL_TGT_COMPOSE:
-	case V4L2_SEL_TGT_CROP:
 		s->r.left = 0;
 		s->r.top = 0;
 		s->r.width = ctx->picinfo.pic_w;
@@ -732,13 +813,10 @@
 {
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
 	struct v4l2_pix_format_mplane *pix_mp;
-	struct mtk_q_data *q_data, *out_q_data;
-	int ret = 0, width = 0, height = 0;
+	struct mtk_q_data *q_data;
+	int ret = 0;
 	struct mtk_video_fmt *fmt;
 
-	const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
-	uint64_t size[2];
-
 	mtk_v4l2_debug(3, "[%d]", ctx->id);
 
 	q_data = mtk_vdec_get_q_data(ctx, f->type);
@@ -746,8 +824,7 @@
 		return -EINVAL;
 
 	pix_mp = &f->fmt.pix_mp;
-	if (!dec_pdata->uses_stateless_api &&
-	    (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
 	    vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) {
 		mtk_v4l2_err("out_q_ctx buffers already requested");
 		ret = -EBUSY;
@@ -759,28 +836,18 @@
 		ret = -EBUSY;
 	}
 
-	fmt = mtk_vdec_find_format(ctx, f,
-		(f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
-		MTK_FMT_DEC : MTK_FMT_FRAME);
+	fmt = mtk_vdec_find_format(f);
 	if (fmt == NULL) {
 		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 			f->fmt.pix.pixelformat =
-				default_out_fmt->fourcc;
-			fmt = mtk_vdec_find_format(ctx, f, MTK_FMT_DEC);
+				mtk_video_formats[OUT_FMT_IDX].fourcc;
+			fmt = mtk_vdec_find_format(f);
 		} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 			f->fmt.pix.pixelformat =
-				default_cap_fmt->fourcc;
-			fmt = mtk_vdec_find_format(ctx, f, MTK_FMT_FRAME);
+				mtk_video_formats[CAP_FMT_IDX].fourcc;
+			fmt = mtk_vdec_find_format(f);
 		}
 	}
-	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		width = pix_mp->width;
-		height = pix_mp->height;
-		out_q_data = mtk_vdec_get_q_data(ctx, f->type);
-		if (!out_q_data)
-			return -EINVAL;
-	}
-
 
 	q_data->fmt = fmt;
 	vidioc_try_fmt(f, q_data->fmt);
@@ -788,15 +855,12 @@
 		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
 		q_data->coded_width = pix_mp->width;
 		q_data->coded_height = pix_mp->height;
-		size[0] = pix_mp->width;
-		size[1] = pix_mp->height;
 
 		ctx->colorspace = f->fmt.pix_mp.colorspace;
 		ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
 		ctx->quantization = f->fmt.pix_mp.quantization;
 		ctx->xfer_func = f->fmt.pix_mp.xfer_func;
 
-		ctx->current_codec = fmt->fourcc;
 		if (ctx->state == MTK_STATE_FREE) {
 			ret = vdec_if_init(ctx, q_data->fmt->fourcc);
 			if (ret) {
@@ -804,55 +868,10 @@
 					ctx->id, ret);
 				return -EINVAL;
 			}
-			vdec_if_set_param(ctx, SET_PARAM_FRAME_SIZE,
-					(void *)size);
-
 			ctx->state = MTK_STATE_INIT;
 		}
 	}
-	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-		vdec_if_set_param(ctx, SET_PARAM_FB_NUM_PLANES,
-			(void *) &q_data->fmt->num_planes);
 
-	/* Tolerate both OUTPUT and CAPTURE queues for compatibility reasons */
-	if (dec_pdata->uses_stateless_api) {
-		ctx->picinfo.pic_w = pix_mp->width;
-		ctx->picinfo.pic_h = pix_mp->height;
-
-		ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo);
-		if (ret) {
-			mtk_v4l2_err("[%d]Error!! Get GET_PARAM_PICTURE_INFO Fail",
-				ctx->id);
-			return -EINVAL;
-		}
-
-		ctx->last_decoded_picinfo = ctx->picinfo;
-		if (pix_mp->num_planes == 1) {
-			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
-				ctx->picinfo.fb_sz[0] +
-				ctx->picinfo.fb_sz[1];
-			ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
-				ctx->picinfo.buf_w;
-		} else {
-			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
-				ctx->picinfo.fb_sz[0];
-			ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
-				ctx->picinfo.buf_w;
-			ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] =
-				ctx->picinfo.fb_sz[1];
-			ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] =
-				ctx->picinfo.buf_w;
-		}
-
-		ctx->q_data[MTK_Q_DATA_DST].coded_width = ctx->picinfo.buf_w;
-		ctx->q_data[MTK_Q_DATA_DST].coded_height = ctx->picinfo.buf_h;
-		mtk_v4l2_debug(2, "[%d] vdec_if_init() num_plane = %d wxh=%dx%d pic wxh=%dx%d sz[0]=0x%x sz[1]=0x%x",
-			ctx->id, pix_mp->num_planes,
-			ctx->picinfo.buf_w, ctx->picinfo.buf_h,
-			ctx->picinfo.pic_w, ctx->picinfo.pic_h,
-			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0],
-			ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]);
-	}
 	return 0;
 }
 
@@ -861,83 +880,45 @@
 {
 	int i = 0;
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
-	const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
 
 	if (fsize->index != 0)
 		return -EINVAL;
-	if (mtk_vdec_framesizes[0].fourcc == 0) {
-		memcpy(mtk_vdec_framesizes, dec_pdata->vdec_framesizes,
-			sizeof(struct mtk_codec_framesizes) *
-			dec_pdata->num_framesizes);
 
-		if (vdec_if_get_param(ctx, GET_PARAM_CAPABILITY_FRAME_SIZES,
-			&mtk_vdec_framesizes) != 0) {
-			mtk_v4l2_debug(1, "[%d] Error!! Cannot get frame size",
-				ctx->id);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < MTK_MAX_DEC_CODECS_SUPPORT; i++) {
-			if (mtk_vdec_framesizes[i].fourcc != 0) {
-				mtk_v4l2_debug(1,
-				"vdec_fs[%d] fourcc %d, profile %d, level %d, s %d %d %d %d %d %d\n",
-				i, mtk_vdec_framesizes[i].fourcc,
-				mtk_vdec_framesizes[i].profile,
-				mtk_vdec_framesizes[i].level,
-				mtk_vdec_framesizes[i].stepwise.min_width,
-				mtk_vdec_framesizes[i].stepwise.max_width,
-				mtk_vdec_framesizes[i].stepwise.step_width,
-				mtk_vdec_framesizes[i].stepwise.min_height,
-				mtk_vdec_framesizes[i].stepwise.max_height,
-				mtk_vdec_framesizes[i].stepwise.step_height);
-			}
-		}
-	}
-
-	for (i = 0; i < MTK_MAX_DEC_CODECS_SUPPORT &&
-		 mtk_vdec_framesizes[i].fourcc != 0; ++i) {
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
 		if (fsize->pixel_format != mtk_vdec_framesizes[i].fourcc)
 			continue;
 
 		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
-		fsize->reserved[0] = mtk_vdec_framesizes[i].profile;
-		fsize->reserved[1] = mtk_vdec_framesizes[i].level;
 		fsize->stepwise = mtk_vdec_framesizes[i].stepwise;
 		if (!(ctx->dev->dec_capability &
-			  VCODEC_CAPABILITY_4K_DISABLED)) {
-			mtk_v4l2_debug(1, "4K is enabled");
+				VCODEC_CAPABILITY_4K_DISABLED)) {
+			mtk_v4l2_debug(3, "4K is enabled");
 			fsize->stepwise.max_width =
 					VCODEC_DEC_4K_CODED_WIDTH;
 			fsize->stepwise.max_height =
 					VCODEC_DEC_4K_CODED_HEIGHT;
 		}
-		mtk_v4l2_debug(4, "%x, %d %d %d %d %d %d %d %d %d %d",
-					   ctx->dev->dec_capability,
-					   fsize->reserved[0],
-					   fsize->reserved[1],
-					   fsize->stepwise.min_width,
-					   fsize->stepwise.max_width,
-					   fsize->stepwise.step_width,
-					   fsize->stepwise.min_height,
-					   fsize->stepwise.max_height,
-					   fsize->stepwise.step_height,
-					   fsize->reserved[0],
-					   fsize->reserved[1]);
+		mtk_v4l2_debug(1, "%x, %d %d %d %d %d %d",
+				ctx->dev->dec_capability,
+				fsize->stepwise.min_width,
+				fsize->stepwise.max_width,
+				fsize->stepwise.step_width,
+				fsize->stepwise.min_height,
+				fsize->stepwise.max_height,
+				fsize->stepwise.step_height);
 		return 0;
 	}
 
 	return -EINVAL;
 }
 
-static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv,
-				bool output_queue)
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
 {
 	struct mtk_video_fmt *fmt;
 	int i, j = 0;
 
-	for (i = 0; i < MTK_MAX_DEC_CODECS_SUPPORT; i++) {
-		if (output_queue &&
-			(mtk_video_formats[i].type != MTK_FMT_DEC))
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (output_queue && (mtk_video_formats[i].type != MTK_FMT_DEC))
 			continue;
 		if (!output_queue &&
 			(mtk_video_formats[i].type != MTK_FMT_FRAME))
@@ -948,28 +929,25 @@
 		++j;
 	}
 
-	if (i == MTK_MAX_DEC_CODECS_SUPPORT ||
-		mtk_video_formats[i].fourcc == 0)
+	if (i == NUM_FORMATS)
 		return -EINVAL;
 
 	fmt = &mtk_video_formats[i];
 	f->pixelformat = fmt->fourcc;
-	f->flags = 0;
-	memset(f->reserved, 0, sizeof(f->reserved));
 
 	return 0;
 }
 
-static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
+static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
 					       struct v4l2_fmtdesc *f)
 {
-	return vidioc_enum_fmt(f, priv, false);
+	return vidioc_enum_fmt(f, false);
 }
 
 static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv,
 					       struct v4l2_fmtdesc *f)
 {
-	return vidioc_enum_fmt(f, priv, true);
+	return vidioc_enum_fmt(f, true);
 }
 
 static int vidioc_vdec_g_fmt(struct file *file, void *priv,
@@ -979,8 +957,6 @@
 	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
 	struct vb2_queue *vq;
 	struct mtk_q_data *q_data;
-	unsigned int fourcc;
-	unsigned int i = 0;
 
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 	if (!vq) {
@@ -1004,13 +980,14 @@
 		 * So we just return picinfo yet, and update picinfo in
 		 * stop_streaming hook function
 		 */
-		q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
-		q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
+		q_data->sizeimage[0] = ctx->picinfo.y_bs_sz +
+					ctx->picinfo.y_len_sz;
+		q_data->sizeimage[1] = ctx->picinfo.c_bs_sz +
+					ctx->picinfo.c_len_sz;
 		q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
 		q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
 		q_data->coded_width = ctx->picinfo.buf_w;
 		q_data->coded_height = ctx->picinfo.buf_h;
-		ctx->last_decoded_picinfo.cap_fourcc = q_data->fmt->fourcc;
 
 		/*
 		 * Width and height are set to the dimensions
@@ -1018,15 +995,8 @@
 		 * further processing stages should crop to this
 		 * rectangle.
 		 */
-		fourcc = ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc;
-		if (fourcc == V4L2_PIX_FMT_RV30 ||
-			fourcc == V4L2_PIX_FMT_RV40) {
-			pix_mp->width = 1920;
-			pix_mp->height = 1088;
-		} else {
-			pix_mp->width = q_data->coded_width;
-			pix_mp->height = q_data->coded_height;
-		}
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
 
 		/*
 		 * Set pixelformat to the format in which mt vcodec
@@ -1034,28 +1004,11 @@
 		 */
 		pix_mp->num_planes = q_data->fmt->num_planes;
 		pix_mp->pixelformat = q_data->fmt->fourcc;
-		if (fourcc == V4L2_PIX_FMT_RV30 ||
-			fourcc == V4L2_PIX_FMT_RV40) {
-			for (i = 0; i < pix_mp->num_planes; i++) {
-				pix_mp->plane_fmt[i].bytesperline = 1920;
-				pix_mp->plane_fmt[i].sizeimage =
-					q_data->sizeimage[i];
-			}
-		} else {
-			for (i = 0; i < pix_mp->num_planes; i++) {
-				pix_mp->plane_fmt[i].bytesperline =
-					q_data->bytesperline[i];
-				pix_mp->plane_fmt[i].sizeimage =
-					q_data->sizeimage[i];
-			}
-		}
-		mtk_v4l2_debug(1, "fourcc:(%d %d),bytesperline:%d,sizeimage:%d,%d,%d\n",
-			ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc,
-			q_data->fmt->fourcc,
-			pix_mp->plane_fmt[0].bytesperline,
-			pix_mp->plane_fmt[0].sizeimage,
-			pix_mp->plane_fmt[1].bytesperline,
-			pix_mp->plane_fmt[1].sizeimage);
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		/*
 		 * This is run on OUTPUT
@@ -1070,29 +1023,14 @@
 		pix_mp->pixelformat = q_data->fmt->fourcc;
 		pix_mp->num_planes = q_data->fmt->num_planes;
 	} else {
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
 		pix_mp->num_planes = q_data->fmt->num_planes;
 		pix_mp->pixelformat = q_data->fmt->fourcc;
-		fourcc = ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc;
-
-		if (fourcc == V4L2_PIX_FMT_RV30 ||
-			fourcc == V4L2_PIX_FMT_RV40) {
-			for (i = 0; i < pix_mp->num_planes; i++) {
-				pix_mp->width = 1920;
-				pix_mp->height = 1088;
-				pix_mp->plane_fmt[i].bytesperline = 1920;
-				pix_mp->plane_fmt[i].sizeimage =
-					q_data->sizeimage[i];
-			}
-		} else {
-			pix_mp->width = q_data->coded_width;
-			pix_mp->height = q_data->coded_height;
-			for (i = 0; i < pix_mp->num_planes; i++) {
-				pix_mp->plane_fmt[i].bytesperline =
-					q_data->bytesperline[i];
-				pix_mp->plane_fmt[i].sizeimage =
-					q_data->sizeimage[i];
-			}
-		}
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
 
 		mtk_v4l2_debug(1, "[%d] type=%d state=%d Format information could not be read, not ready yet!",
 				ctx->id, f->type, ctx->state);
@@ -1101,7 +1039,7 @@
 	return 0;
 }
 
-int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
+static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
 				unsigned int *nbuffers,
 				unsigned int *nplanes,
 				unsigned int sizes[],
@@ -1125,7 +1063,7 @@
 		}
 	} else {
 		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-			*nplanes = q_data->fmt->num_planes;
+			*nplanes = 2;
 		else
 			*nplanes = 1;
 
@@ -1141,14 +1079,11 @@
 	return 0;
 }
 
-int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
+static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
 {
 	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct mtk_q_data *q_data;
 	int i;
-	struct mtk_video_dec_buf *mtkbuf;
-	struct vb2_v4l2_buffer *vb2_v4l2;
-	unsigned int plane = 0;
 
 	mtk_v4l2_debug(3, "[%d] (%d) id=%d",
 			ctx->id, vb->vb2_queue->type, vb->index);
@@ -1163,56 +1098,142 @@
 		}
 	}
 
-	// Check if need to proceed cache operations
-	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-	mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
-
-	if (!(mtkbuf->flags & NO_CAHCE_CLEAN) &&
-		!(ctx->dec_params.svp_mode) &&
-		(vb->vb2_queue->memory == VB2_MEMORY_DMABUF)) {
-		struct vdec_fb fb_param;
-
-		for (plane = 0; plane < vb->num_planes; plane++) {
-			struct vb2_dc_buf *dc_buf = vb->planes[plane].mem_priv;
-
-			mtk_v4l2_debug(4, "[%d] Cache sync+", ctx->id);
-			dma_sync_sg_for_device(&ctx->dev->plat_dev->dev,
-				dc_buf->dma_sgt->sgl,
-				dc_buf->dma_sgt->orig_nents,
-				DMA_TO_DEVICE);
-			fb_param.fb_base[plane].dma_addr =
-				vb2_dma_contig_plane_dma_addr(vb,
-				plane);
-			if (vb->vb2_queue->type ==
-					V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-				fb_param.fb_base[plane].size =
-					(size_t)vb->planes[0].bytesused;
-			else
-				fb_param.fb_base[plane].size =
-					ctx->picinfo.fb_sz[plane];
-
-			mtk_v4l2_debug(4,
-			  "[%d] [%d] [%d]Cache sync- TD for %p sz=%d dev %p",
-			  ctx->id,
-			  vb->vb2_queue->type,
-			  plane,
-			  (void *)fb_param.fb_base[plane].dma_addr,
-			  (unsigned int)fb_param.fb_base[plane].size,
-			  &ctx->dev->plat_dev->dev);
-		}
-	}
-
 	return 0;
 }
 
-void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
+static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_buffer *src_buf;
+	struct mtk_vcodec_mem src_mem;
+	bool res_chg = false;
+	int ret = 0;
+	unsigned int dpbsize = 1;
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+	struct mtk_video_dec_buf *buf = NULL;
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p",
+			ctx->id, vb->vb2_queue->type,
+			vb->index, vb);
+	/*
+	 * check if this buffer is ready to be used after decode
+	 */
+	if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		vb2_v4l2 = to_vb2_v4l2_buffer(vb);
+		buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+		mutex_lock(&ctx->lock);
+		if (buf->used == false) {
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
+			buf->queued_in_vb2 = true;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		} else {
+			buf->queued_in_vb2 = false;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		}
+		mutex_unlock(&ctx->lock);
+		return;
+	}
+
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb));
+
+	if (ctx->state != MTK_STATE_INIT) {
+		mtk_v4l2_debug(3, "[%d] already init driver %d",
+				ctx->id, ctx->state);
+		return;
+	}
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (!src_buf) {
+		mtk_v4l2_err("No src buffer");
+		return;
+	}
+	vb2_v4l2 = to_vb2_v4l2_buffer(src_buf);
+	buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+	if (buf->lastframe) {
+		/* This shouldn't happen. Just in case. */
+		mtk_v4l2_err("Invalid flush buffer.");
+		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		return;
+	}
+
+	src_mem.va = vb2_plane_vaddr(src_buf, 0);
+	src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	src_mem.size = (size_t)src_buf->planes[0].bytesused;
+	mtk_v4l2_debug(2,
+			"[%d] buf id=%d va=%p dma=%pad size=%zx",
+			ctx->id, src_buf->index,
+			src_mem.va, &src_mem.dma_addr,
+			src_mem.size);
+
+	ret = vdec_if_decode(ctx, &src_mem, NULL, &res_chg);
+	if (ret || !res_chg) {
+		/*
+		 * fb == NULL menas to parse SPS/PPS header or
+		 * resolution info in src_mem. Decode can fail
+		 * if there is no SPS header or picture info
+		 * in bs
+		 */
+
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		if (ret == -EIO) {
+			mtk_v4l2_err("[%d] Unrecoverable error in vdec_if_decode.",
+					ctx->id);
+			ctx->state = MTK_STATE_ABORT;
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+						VB2_BUF_STATE_ERROR);
+		} else {
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+						VB2_BUF_STATE_DONE);
+		}
+		mtk_v4l2_debug(ret ? 0 : 1,
+			       "[%d] vdec_if_decode() src_buf=%d, size=%zu, fail=%d, res_chg=%d",
+			       ctx->id, src_buf->index,
+			       src_mem.size, ret, res_chg);
+		return;
+	}
+
+	if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) {
+		mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+				ctx->id);
+		return;
+	}
+
+	ctx->last_decoded_picinfo = ctx->picinfo;
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+						ctx->picinfo.y_bs_sz +
+						ctx->picinfo.y_len_sz;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
+						ctx->picinfo.buf_w;
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] =
+						ctx->picinfo.c_bs_sz +
+						ctx->picinfo.c_len_sz;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] = ctx->picinfo.buf_w;
+	mtk_v4l2_debug(2, "[%d] vdec_if_init() OK wxh=%dx%d pic wxh=%dx%d sz[0]=0x%x sz[1]=0x%x",
+			ctx->id,
+			ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+			ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0],
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]);
+
+	ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+	if (dpbsize == 0)
+		mtk_v4l2_err("[%d] GET_PARAM_DPB_SIZE fail=%d", ctx->id, ret);
+
+	ctx->dpb_size = dpbsize;
+	ctx->state = MTK_STATE_HEADER;
+	mtk_v4l2_debug(1, "[%d] dpbsize=%d", ctx->id, ctx->dpb_size);
+
+	mtk_vdec_queue_res_chg_event(ctx);
+}
+
+static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
 {
 	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct vb2_v4l2_buffer *vb2_v4l2;
 	struct mtk_video_dec_buf *buf;
 	bool buf_error;
-	unsigned int plane = 0;
-	struct mtk_video_dec_buf *mtkbuf;
 
 	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
 	buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
@@ -1228,43 +1249,9 @@
 		mtk_v4l2_err("Unrecoverable error on buffer.");
 		ctx->state = MTK_STATE_ABORT;
 	}
-
-	if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-		return;
-
-	// Check if need to proceed cache operations for Capture Queue
-	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-	mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
-
-	if (!(mtkbuf->flags & NO_CAHCE_INVALIDATE) &&
-		!(ctx->dec_params.svp_mode) &&
-		(vb->vb2_queue->memory == VB2_MEMORY_DMABUF)) {
-		for (plane = 0; plane < buf->frame_buffer.num_planes; plane++) {
-			struct vdec_fb dst_mem;
-			struct vb2_dc_buf *dc_buf = vb->planes[plane].mem_priv;
-
-			mtk_v4l2_debug(4, "[%d] Cache sync+", ctx->id);
-			dma_sync_sg_for_cpu(&ctx->dev->plat_dev->dev,
-				dc_buf->dma_sgt->sgl,
-				dc_buf->dma_sgt->orig_nents, DMA_FROM_DEVICE);
-
-			dst_mem.fb_base[plane].dma_addr =
-				vb2_dma_contig_plane_dma_addr(vb, plane);
-			dst_mem.fb_base[plane].size = ctx->picinfo.fb_sz[plane];
-
-			mtk_v4l2_debug(4,
-				"[%d] Cache sync- FD for %p sz=%d dev %p pfb %p",
-				ctx->id,
-				(void *)dst_mem.fb_base[plane].dma_addr,
-				(unsigned int)dst_mem.fb_base[plane].size,
-				&ctx->dev->plat_dev->dev,
-				&buf->frame_buffer);
-		}
-	}
-
 }
 
-int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
+static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
 {
 	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
 					struct vb2_v4l2_buffer, vb2_buf);
@@ -1272,61 +1259,43 @@
 					struct mtk_video_dec_buf, vb);
 
 	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		/* User could use different struct dma_buf*
-		 * with the same index & enter this buf_init.
-		 * once this buffer buf->used == true will reset in mistake
-		 * VB2 use kzalloc for struct mtk_video_dec_buf,
-		 * so init could be no need
-		 */
-		if (buf->used == false)
-			buf->queued_in_v4l2 = false;
-	} else	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		/* Do not reset EOS for 1st buffer with Early EOS*/
-		//buf->lastframe = NON_EOS;
+		buf->used = false;
+		buf->ready_to_display = false;
+		buf->queued_in_v4l2 = false;
 	} else {
-		mtk_v4l2_err("%s: unknown queue type", __func__);
-		return -EINVAL;
+		buf->lastframe = false;
 	}
 
 	return 0;
 }
 
-int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
 
 	if (ctx->state == MTK_STATE_FLUSH)
 		ctx->state = MTK_STATE_HEADER;
 
-	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		mtk_v4l2_debug(4, "V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE q->num_buffers = %d",
-			q->num_buffers);
-		ctx->dec_params.total_frame_bufq_count = q->num_buffers;
-		ctx->dec_param_change |= MTK_DEC_PARAM_TOTAL_FRAME_BUFQ_COUNT;
-	}
-
-	mtk_vdec_set_param(ctx);
 	return 0;
 }
 
-void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
+static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
 {
-	struct vb2_v4l2_buffer *src_buf = NULL, *dst_buf = NULL;
-	struct vb2_v4l2_buffer *last_buf = NULL;
+	struct vb2_buffer *src_buf = NULL, *dst_buf = NULL;
 	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
-	int i = 0;
-	int ret;
 
 	mtk_v4l2_debug(3, "[%d] (%d) state=(%x) ctx->decoded_frame_cnt=%d",
 			ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt);
 
-	last_buf = &ctx->empty_flush_buf->vb;
 	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		if (ctx->state >= MTK_STATE_HEADER)
-			ctx->dev->vdec_pdata->flush_decoder(ctx);
 		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) {
-			if (last_buf != src_buf)
-				v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+			struct vb2_v4l2_buffer *vb2_v4l2 =
+					to_vb2_v4l2_buffer(src_buf);
+			struct mtk_video_dec_buf *buf_info = container_of(
+					vb2_v4l2, struct mtk_video_dec_buf, vb);
+			if (!buf_info->lastframe)
+				v4l2_m2m_buf_done(vb2_v4l2,
+						VB2_BUF_STATE_ERROR);
 		}
 		return;
 	}
@@ -1339,28 +1308,25 @@
 		 * VIDIOC_G_FMT< etc. return previous resolution.
 		 * So we update picinfo here
 		 */
+		ctx->picinfo = ctx->last_decoded_picinfo;
 
 		mtk_v4l2_debug(2,
-				"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d), DPB(%d,%d)",
+				"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
 				ctx->id, ctx->last_decoded_picinfo.pic_w,
 				ctx->last_decoded_picinfo.pic_h,
 				ctx->picinfo.pic_w, ctx->picinfo.pic_h,
 				ctx->last_decoded_picinfo.buf_w,
-				ctx->last_decoded_picinfo.buf_h,
-				ctx->dpb_size, ctx->last_dpb_size);
-		ctx->picinfo = ctx->last_decoded_picinfo;
-		ctx->dpb_size = ctx->last_dpb_size;
+				ctx->last_decoded_picinfo.buf_h);
 
-		ret = ctx->dev->vdec_pdata->flush_decoder(ctx);
-		if (ret)
-			mtk_v4l2_err("DecodeFinal failed, ret=%d", ret);
+		mtk_vdec_flush_decoder(ctx);
 	}
 	ctx->state = MTK_STATE_FLUSH;
 
 	while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
-		for (i = 0; i < dst_buf->vb2_buf.num_planes; i++)
-			vb2_set_plane_payload(&dst_buf->vb2_buf, i, 0);
-		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+		vb2_set_plane_payload(dst_buf, 0, 0);
+		vb2_set_plane_payload(dst_buf, 1, 0);
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+					VB2_BUF_STATE_ERROR);
 	}
 
 }
@@ -1383,8 +1349,7 @@
 		return 0;
 
 	if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) ||
-	    (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h)	||
-	    (ctx->last_dpb_size != ctx->dpb_size))
+	    (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h))
 		return 0;
 
 	if (ctx->state != MTK_STATE_HEADER)
@@ -1393,12 +1358,17 @@
 	return 1;
 }
 
-int mtk_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+static void m2mops_vdec_job_abort(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+
+	ctx->state = MTK_STATE_ABORT;
+}
+
+static int mtk_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct mtk_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
 	int ret = 0;
-	static unsigned int value;
-	struct mtk_color_desc *color_desc;
 
 	switch (ctrl->id) {
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
@@ -1409,77 +1379,59 @@
 			ctrl->val = 0;
 		}
 		break;
-	case V4L2_CID_MPEG_MTK_FRAME_INTERVAL:
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_FRAME_INTERVAL, &value) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-		ctrl->p_new.p_u32 = &value;
-		mtk_v4l2_debug(2, "V4L2_CID_MPEG_MTK_FRAME_INTERVAL val = %u",
-			*(ctrl->p_new.p_u32));
-		break;
-	case V4L2_CID_MPEG_MTK_COLOR_DESC:
-		color_desc = (struct mtk_color_desc *)ctrl->p_new.p_u32;
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_COLOR_DESC, color_desc) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-	break;
-	case V4L2_CID_MPEG_MTK_ASPECT_RATIO:
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_ASPECT_RATIO, &ctrl->val) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-	break;
-	case V4L2_CID_MPEG_MTK_FIX_BUFFERS:
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_PLATFORM_SUPPORTED_FIX_BUFFERS,
-				&ctrl->val) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-	break;
-	case V4L2_CID_MPEG_MTK_FIX_BUFFERS_SVP:
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_PLATFORM_SUPPORTED_FIX_BUFFERS_SVP,
-				&ctrl->val) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-	break;
-	case V4L2_CID_MPEG_MTK_INTERLACING:
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_INTERLACING, &ctrl->val) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-	break;
-	case V4L2_CID_MPEG_MTK_CODEC_TYPE:
-		if (vdec_if_get_param(ctx,
-				GET_PARAM_CODEC_TYPE, &ctrl->val) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get param",
-				ctx->id);
-			ret = -EINVAL;
-		}
-	break;
 	default:
 		ret = -EINVAL;
 	}
 	return ret;
 }
 
+static const struct v4l2_ctrl_ops mtk_vcodec_dec_ctrl_ops = {
+	.g_volatile_ctrl = mtk_vdec_g_v_ctrl,
+};
+
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
+{
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1);
+
+	ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+				&mtk_vcodec_dec_ctrl_ops,
+				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+				0, 32, 1, 1);
+	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	v4l2_ctrl_new_std_menu(&ctx->ctrl_hdl,
+				&mtk_vcodec_dec_ctrl_ops,
+				V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
+				V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+				0, V4L2_MPEG_VIDEO_VP9_PROFILE_0);
+
+	if (ctx->ctrl_hdl.error) {
+		mtk_v4l2_err("Adding control failed %d",
+				ctx->ctrl_hdl.error);
+		return ctx->ctrl_hdl.error;
+	}
+
+	v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+	return 0;
+}
+
 const struct v4l2_m2m_ops mtk_vdec_m2m_ops = {
 	.device_run	= m2mops_vdec_device_run,
 	.job_ready	= m2mops_vdec_job_ready,
+	.job_abort	= m2mops_vdec_job_abort,
+};
+
+static const struct vb2_ops mtk_vdec_vb2_ops = {
+	.queue_setup	= vb2ops_vdec_queue_setup,
+	.buf_prepare	= vb2ops_vdec_buf_prepare,
+	.buf_queue	= vb2ops_vdec_buf_queue,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+	.buf_init	= vb2ops_vdec_buf_init,
+	.buf_finish	= vb2ops_vdec_buf_finish,
+	.start_streaming	= vb2ops_vdec_start_streaming,
+	.stop_streaming	= vb2ops_vdec_stop_streaming,
 };
 
 const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops = {
@@ -1528,15 +1480,8 @@
 	src_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
 	src_vq->drv_priv	= ctx;
 	src_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
-	src_vq->allow_zero_bytesused = 1;
-	src_vq->ops		= ctx->dev->vdec_pdata->vdec_vb2_ops;
-#ifdef CONFIG_VB2_MEDIATEK_DMA
-	src_vq->mem_ops         = &mtk_dma_contig_memops;
-	mtk_v4l2_debug(4, "src_vq use mtk_dma_contig_memops");
-#else
-	src_vq->mem_ops         = &vb2_dma_contig_memops;
-	mtk_v4l2_debug(4, "src_vq use vb2_dma_contig_memops");
-#endif
+	src_vq->ops		= &mtk_vdec_vb2_ops;
+	src_vq->mem_ops		= &vb2_dma_contig_memops;
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	src_vq->lock		= &ctx->dev->dev_mutex;
 	src_vq->dev             = &ctx->dev->plat_dev->dev;
@@ -1550,15 +1495,8 @@
 	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
 	dst_vq->drv_priv	= ctx;
 	dst_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
-	dst_vq->allow_zero_bytesused = 1;
-	dst_vq->ops		= ctx->dev->vdec_pdata->vdec_vb2_ops;
-#ifdef CONFIG_VB2_MEDIATEK_DMA
-	dst_vq->mem_ops         = &mtk_dma_contig_memops;
-	mtk_v4l2_debug(4, "dst_vq use mtk_dma_contig_memops");
-#else
-	dst_vq->mem_ops         = &vb2_dma_contig_memops;
-	mtk_v4l2_debug(4, "dst_vq use vb2_dma_contig_memops");
-#endif
+	dst_vq->ops		= &mtk_vdec_vb2_ops;
+	dst_vq->mem_ops		= &vb2_dma_contig_memops;
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	dst_vq->lock		= &ctx->dev->dev_mutex;
 	dst_vq->dev             = &ctx->dev->plat_dev->dev;
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
old mode 100644
new mode 100755
index 2466db3..dc4fc1d
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
@@ -24,38 +24,34 @@
 #define VCODEC_DEC_4K_CODED_HEIGHT	2304U
 #define MTK_VDEC_MAX_W	2048U
 #define MTK_VDEC_MAX_H	1088U
-#define MTK_VDEC_MIN_W	64U
-#define MTK_VDEC_MIN_H	64U
 
 #define MTK_VDEC_IRQ_STATUS_DEC_SUCCESS        0x10000
 
 /**
  * struct vdec_fb  - decoder frame buffer
- * @fb_base	: planes memory info
+ * @base_y	: Y plane memory info
+ * @base_c	: C plane memory info
  * @status      : frame buffer status (vdec_fb_status)
- * @num_planes		:frame buffer plane number
- * @index		:frame buffer index in vb2 queue
  */
 struct vdec_fb {
-	struct mtk_vcodec_mem fb_base[VIDEO_MAX_PLANES];
+	struct mtk_vcodec_mem	base_y;
+	struct mtk_vcodec_mem	base_c;
 	unsigned int	status;
-	unsigned int    num_planes;
-	unsigned int    index;
 };
 
 /**
  * struct mtk_video_dec_buf - Private data related to each VB2 buffer.
- * @vb:	VB2 buffer
+ * @b:		VB2 buffer
  * @list:	link list
  * @used:	Capture buffer contain decoded frame data and keep in
  *			codec data structure
+ * @ready_to_display:	Capture buffer not display yet
  * @queued_in_vb2:	Capture buffer is queue in vb2
  * @queued_in_v4l2:	Capture buffer is in v4l2 driver, but not in vb2
  *			queue yet
  * @lastframe:		Intput buffer is last buffer - EOS
  * @error:		An unrecoverable error occurs on this buffer.
  * @frame_buffer:	Decode status, and buffer information of Capture buffer
- * @bs_buffer:	Output buffer info
  *
  * Note : These status information help us track and debug buffer state
  */
@@ -64,25 +60,17 @@
 	struct list_head	list;
 
 	bool	used;
+	bool	ready_to_display;
 	bool	queued_in_vb2;
 	bool	queued_in_v4l2;
-	bool lastframe;
-	bool isEarlyEos;
+	bool	lastframe;
 	bool	error;
-
-	union {
-		struct vdec_fb	frame_buffer;
-		struct mtk_vcodec_mem	bs_buffer;
-	};
-	int flags;
+	struct vdec_fb	frame_buffer;
 };
 
 extern const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops;
 extern const struct v4l2_m2m_ops mtk_vdec_m2m_ops;
-extern const struct media_device_ops mtk_vcodec_media_ops;
 
-extern const struct mtk_vcodec_dec_pdata	mtk_frame_pdata;
-extern const struct mtk_vcodec_dec_pdata	mtk_req_8183_pdata;
 
 /*
  * mtk_vdec_lock/mtk_vdec_unlock are for ctx instance to
@@ -95,28 +83,8 @@
 int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
 			   struct vb2_queue *dst_vq);
 void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx);
-void mtk_vcodec_dec_empty_queues(struct mtk_vcodec_ctx *ctx);
 void mtk_vcodec_dec_release(struct mtk_vcodec_ctx *ctx);
-int mtk_vdec_set_param(struct mtk_vcodec_ctx *ctx);
-void mtk_vdec_update_fmt(struct mtk_vcodec_ctx *ctx,
-		unsigned int pixelformat);
-struct mtk_video_fmt *mtk_find_fmt_by_pixel(unsigned int pixelformat);
-
-int mtk_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl);
-
-/*
- * VB2 ops
- */
-int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
-				unsigned int *nbuffers,
-				unsigned int *nplanes,
-				unsigned int sizes[],
-				struct device *alloc_devs[]);
-int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb);
-void vb2ops_vdec_buf_finish(struct vb2_buffer *vb);
-int vb2ops_vdec_buf_init(struct vb2_buffer *vb);
-int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count);
-void vb2ops_vdec_stop_streaming(struct vb2_queue *q);
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx);
 
 
 #endif /* _MTK_VCODEC_DEC_H_ */
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
old mode 100644
new mode 100755
index c620a0e..4334b73
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -22,18 +22,13 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-dma-contig.h>
-#include <media/v4l2-device.h>
-#include <linux/iommu.h>
-#include <linux/pm_wakeup.h>
-#include <linux/delay.h>
-#include <linux/suspend.h>
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_dec.h"
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_intr.h"
 #include "mtk_vcodec_util.h"
-#include "mtk_vcodec_fw.h"
+#include "mtk_vpu.h"
 
 #define VDEC_HW_ACTIVE	0x10
 #define VDEC_IRQ_CFG	0x11
@@ -42,7 +37,6 @@
 
 module_param(mtk_v4l2_dbg_level, int, 0644);
 module_param(mtk_vcodec_dbg, bool, 0644);
-struct mtk_vcodec_dev *vdec_dev;
 
 /* Wake up context wait_queue */
 static void wake_up_ctx(struct mtk_vcodec_ctx *ctx)
@@ -91,6 +85,22 @@
 	return IRQ_HANDLED;
 }
 
+static void mtk_vcodec_dec_reset_handler(void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+
+	mtk_v4l2_err("Watchdog timeout!!");
+
+	mutex_lock(&dev->dev_mutex);
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ERROR",
+				ctx->id);
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
 static int fops_vcodec_open(struct file *file)
 {
 	struct mtk_vcodec_dev *dev = video_drvdata(file);
@@ -120,7 +130,7 @@
 	mutex_init(&ctx->lock);
 
 	ctx->type = MTK_INST_DECODER;
-	ret = dev->vdec_pdata->ctrls_setup(ctx);
+	ret = mtk_vcodec_dec_ctrls_setup(ctx);
 	if (ret) {
 		mtk_v4l2_err("Failed to setup mt vcodec controls");
 		goto err_ctrls_setup;
@@ -137,26 +147,26 @@
 				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 	ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
 	ctx->empty_flush_buf->lastframe = true;
-	ctx->empty_flush_buf->isEarlyEos = false;
 	mtk_vcodec_dec_set_default_params(ctx);
 
 	if (v4l2_fh_is_singular(&ctx->fh)) {
 		mtk_vcodec_dec_pw_on(&dev->pm);
 		/*
-		 * load fireware to checks if it was loaded already and
+		 * vpu_load_firmware checks if it was loaded already and
 		 * does nothing in that case
 		 */
-		ret = mtk_vcodec_fw_load_firmware(dev->ipi_msg_handle);
+		ret = vpu_load_firmware(dev->vpu_plat_dev);
 		if (ret < 0) {
 			/*
 			 * Return 0 if downloading firmware successfully,
 			 * otherwise it is failed
 			 */
-			mtk_v4l2_err("failed to load firmware!");
+			mtk_v4l2_err("vpu_load_firmware failed!");
 			goto err_load_fw;
 		}
 
-		dev->dec_capability = mtk_vcodec_fw_get_vdec_capa(dev->ipi_msg_handle);
+		dev->dec_capability =
+			vpu_get_vdec_hw_capa(dev->vpu_plat_dev);
 		mtk_v4l2_debug(0, "decoder capability %x", dev->dec_capability);
 	}
 
@@ -196,7 +206,6 @@
 	 * Second, the decoder will be flushed and all the buffers will be
 	 * returned in stop_streaming.
 	 */
-	mtk_vcodec_dec_empty_queues(ctx);
 	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 	mtk_vcodec_dec_release(ctx);
 
@@ -222,66 +231,11 @@
 	.mmap		= v4l2_m2m_fop_mmap,
 };
 
-/**
- * Suspend callbacks after user space processes are frozen
- * Since user space processes are frozen, there is no need and cannot hold same
- * mutex that protects lock owner while checking status.
- * If video codec hardware is still active now, must not to enter suspend.
- **/
-static int mtk_vcodec_dec_suspend(struct device *pDev)
-{
-	if (mutex_is_locked(&vdec_dev->dec_mutex)) {
-		mtk_v4l2_debug(0, "fail due to videocodec activity");
-		return -EBUSY;
-	}
-	mtk_v4l2_debug(1, "done");
-	return 0;
-}
-
-static int mtk_vcodec_dec_resume(struct device *pDev)
-{
-	mtk_v4l2_debug(1, "done");
-	return 0;
-}
-
-static int mtk_vcodec_dec_suspend_notifier(struct notifier_block *nb,
-					unsigned long action, void *data)
-{
-	int wait_cnt = 0;
-
-	mtk_v4l2_debug(1, "action = %ld", action);
-	switch (action) {
-	case PM_SUSPEND_PREPARE:
-		vdec_dev->is_codec_suspending = 1;
-		do {
-			usleep_range(10000, 20000);
-			wait_cnt++;
-			if (wait_cnt > 5) {
-				mtk_v4l2_err("waiting fail");
-				/* Current task is still not finished, don't
-				 * care, will check again in real suspend
-				 */
-				return NOTIFY_DONE;
-			}
-		} while (mutex_is_locked(&vdec_dev->dec_mutex));
-
-		return NOTIFY_OK;
-	case PM_POST_SUSPEND:
-		vdec_dev->is_codec_suspending = 0;
-		return NOTIFY_OK;
-	default:
-		return NOTIFY_DONE;
-	}
-	return NOTIFY_DONE;
-}
-
 static int mtk_vcodec_probe(struct platform_device *pdev)
 {
 	struct mtk_vcodec_dev *dev;
 	struct video_device *vfd_dec;
 	struct resource *res;
-	phandle rproc_phandle;
-	enum mtk_vcodec_fw_type fw_type;
 	int i, ret;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -291,24 +245,14 @@
 	INIT_LIST_HEAD(&dev->ctx_list);
 	dev->plat_dev = pdev;
 
-	dev->vdec_pdata = of_device_get_match_data(&pdev->dev);
-	if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vpu",
-				  &rproc_phandle)) {
-		fw_type = VPU;
-	} else if (!of_property_read_u32(pdev->dev.of_node, "mediatek,scp",
-				  &rproc_phandle)) {
-		fw_type = SCP;
-	} else if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vcu",
-				  &rproc_phandle)) {
-		fw_type = VCU;
-	} else {
-		mtk_v4l2_err("Could not get vdec IPI device");
-		return -ENODEV;
+	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
+	if (dev->vpu_plat_dev == NULL) {
+		mtk_v4l2_err("[VPU] vpu device in not ready");
+		return -EPROBE_DEFER;
 	}
-	dev->ipi_msg_handle = mtk_vcodec_fw_select(dev, fw_type, rproc_phandle,
-						   VPU_RST_DEC);
-	if (IS_ERR(dev->ipi_msg_handle))
-		return PTR_ERR(dev->ipi_msg_handle);
+
+	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_dec_reset_handler,
+			dev, VPU_RST_DEC);
 
 	ret = mtk_vcodec_init_dec_pm(dev);
 	if (ret < 0) {
@@ -319,9 +263,9 @@
 	for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 		if (res == NULL) {
-			dev_err(&pdev->dev,
-				"get index:%d memory resource failed.", i);
-			break;
+			dev_err(&pdev->dev, "get memory resource failed.");
+			ret = -ENXIO;
+			goto err_res;
 		}
 		dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR((__force void *)dev->reg_base[i])) {
@@ -351,7 +295,6 @@
 	disable_irq(dev->dec_irq);
 	mutex_init(&dev->dec_mutex);
 	mutex_init(&dev->dev_mutex);
-	mutex_init(&dev->dec_dvfs_mutex);
 	spin_lock_init(&dev->irqlock);
 
 	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
@@ -402,32 +345,7 @@
 		goto err_event_workq;
 	}
 
-	if (dev->vdec_pdata->uses_stateless_api) {
-		dev->mdev_dec.dev = &pdev->dev;
-		strscpy(dev->mdev_dec.model, MTK_VCODEC_DEC_NAME,
-				sizeof(dev->mdev_dec.model));
-
-		media_device_init(&dev->mdev_dec);
-		dev->mdev_dec.ops = &mtk_vcodec_media_ops;
-		dev->v4l2_dev.mdev = &dev->mdev_dec;
-
-		ret = v4l2_m2m_register_media_controller(dev->m2m_dev_dec,
-			dev->vfd_dec, MEDIA_ENT_F_PROC_VIDEO_DECODER);
-		if (ret) {
-			mtk_v4l2_err("Failed to register media controller");
-			goto err_reg_cont;
-		}
-
-		ret = media_device_register(&dev->mdev_dec);
-		if (ret) {
-			mtk_v4l2_err("Failed to register media device");
-			goto err_media_reg;
-		}
-
-		mtk_v4l2_debug(0, "media registered as /dev/media%d",
-			vfd_dec->num);
-	}
-	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, -1);
+	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 0);
 	if (ret) {
 		mtk_v4l2_err("Failed to register video device");
 		goto err_dec_reg;
@@ -436,22 +354,9 @@
 	mtk_v4l2_debug(0, "decoder registered as /dev/video%d",
 		vfd_dec->num);
 
-	mtk_prepare_vdec_dvfs(dev);
-	ret = mtk_prepare_vdec_emi_bw(dev);
-	if (ret)
-		goto err_dec_reg;
-	pm_notifier(mtk_vcodec_dec_suspend_notifier, 0);
-	dev->is_codec_suspending = 0;
-	vdec_dev = dev;
 	return 0;
 
 err_dec_reg:
-	if (dev->vdec_pdata->uses_stateless_api)
-		media_device_unregister(&dev->mdev_dec);
-err_media_reg:
-	if (dev->vdec_pdata->uses_stateless_api)
-		v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
-err_reg_cont:
 	destroy_workqueue(dev->decode_workqueue);
 err_event_workq:
 	v4l2_m2m_release(dev->m2m_dev_dec);
@@ -464,13 +369,8 @@
 	return ret;
 }
 
-extern const struct mtk_vcodec_dec_pdata mtk_frame_8173_pdata;
-extern const struct mtk_vcodec_dec_pdata mtk_req_8183_pdata;
-
 static const struct of_device_id mtk_vcodec_match[] = {
-	{.compatible = "mediatek,mt8173-vcodec-dec", .data = &mtk_frame_pdata},
-	{.compatible = "mediatek,mt8183-vcodec-dec", .data = &mtk_req_8183_pdata},
-	{.compatible = "mediatek,mt6779-vcodec-dec", .data = &mtk_frame_pdata},
+	{.compatible = "mediatek,mt8173-vcodec-dec",},
 	{},
 };
 
@@ -480,18 +380,8 @@
 {
 	struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
 
-	mtk_unprepare_vdec_emi_bw();
-	mtk_unprepare_vdec_dvfs();
-
 	flush_workqueue(dev->decode_workqueue);
 	destroy_workqueue(dev->decode_workqueue);
-
-	if (media_devnode_is_registered(dev->mdev_dec.devnode)) {
-		media_device_unregister(&dev->mdev_dec);
-		v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
-		media_device_cleanup(&dev->mdev_dec);
-	}
-
 	if (dev->m2m_dev_dec)
 		v4l2_m2m_release(dev->m2m_dev_dec);
 
@@ -503,16 +393,11 @@
 	return 0;
 }
 
-static const struct dev_pm_ops mtk_vcodec_dec_pm_ops = {
-	.suspend = mtk_vcodec_dec_suspend,
-	.resume = mtk_vcodec_dec_resume,
-};
 static struct platform_driver mtk_vcodec_dec_driver = {
 	.probe	= mtk_vcodec_probe,
 	.remove	= mtk_vcodec_dec_remove,
 	.driver	= {
 		.name	= MTK_VCODEC_DEC_NAME,
-		.pm = &mtk_vcodec_dec_pm_ops,
 		.of_match_table = mtk_vcodec_match,
 	},
 };
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
old mode 100644
new mode 100755
index 9d1f74b..79ca03a
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -16,90 +16,83 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
 
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
-
-#ifdef CONFIG_MEDIATEK_DVFS
-#include <linux/pm_opp.h>
-#include <linux/regulator/consumer.h>
-#include "vcodec_dvfs.h"
-static struct regulator *reg;
-static unsigned long vdec_freq;
-static u32 vdec_freq_step_size;
-static unsigned long *vdec_freq_steps;
-static u32 vdec_high_volt;
-static struct codec_history *vdec_hists;
-static struct codec_job *vdec_jobs;
-#endif
-
-#ifdef CONFIG_MEDIATEK_EMI_BW
-#include <linux/interconnect-provider.h>
-#define STD_VDEC_FREQ 312
-static unsigned int h264_frm_scale[4] = {12, 24, 40, 12};
-static unsigned int h265_frm_scale[4] = {12, 24, 40, 12};
-static unsigned int vp9_frm_scale[4] = {12, 24, 40, 12};
-static unsigned int vp8_frm_scale[4] = {12, 24, 40, 12};
-static unsigned int mp24_frm_scale[5] = {16, 20, 32, 50, 16};
-
-static struct icc_path *vdec_mc;
-static struct icc_path *vdec_ufo;
-static struct icc_path *vdec_pp;
-static struct icc_path *vdec_pred_rd;
-static struct icc_path *vdec_pred_wr;
-static struct icc_path *vdec_ppwrap;
-static struct icc_path *vdec_tile;
-static struct icc_path *vdec_vld;
-static struct icc_path *vdec_vld2;
-static struct icc_path *vdec_avc_mv;
-static struct icc_path *vdec_ufo_enc;
-static struct icc_path *vdec_rg_ctrl_dma;
-#endif
+#include "mtk_vpu.h"
 
 int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
 {
+	struct device_node *node;
 	struct platform_device *pdev;
 	struct mtk_vcodec_pm *pm;
-	struct mtk_vcodec_clk *dec_clk;
-	struct mtk_vcodec_clk_info *clk_info;
-	int i = 0, ret = 0;
+	int ret = 0;
 
 	pdev = mtkdev->plat_dev;
 	pm = &mtkdev->pm;
 	pm->mtkdev = mtkdev;
-	dec_clk = &pm->vdec_clk;
+	node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
+	if (!node) {
+		mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
+		return -1;
+	}
 
+	pdev = of_find_device_by_node(node);
+	if (WARN_ON(!pdev)) {
+		of_node_put(node);
+		return -1;
+	}
+	pm->larbvdec = &pdev->dev;
 	pdev = mtkdev->plat_dev;
 	pm->dev = &pdev->dev;
 
-	dec_clk->clk_num =
-		of_property_count_strings(pdev->dev.of_node, "clock-names");
-	if (dec_clk->clk_num > 0) {
-		dec_clk->clk_info = devm_kcalloc(&pdev->dev,
-			dec_clk->clk_num, sizeof(*clk_info),
-			GFP_KERNEL);
-		if (!dec_clk->clk_info)
-			return -ENOMEM;
-	} else {
-		mtk_v4l2_err("Failed to get vdec clock count");
-		return -EINVAL;
+	pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll");
+	if (IS_ERR(pm->vcodecpll)) {
+		mtk_v4l2_err("devm_clk_get vcodecpll fail");
+		ret = PTR_ERR(pm->vcodecpll);
 	}
 
-	for (i = 0; i < dec_clk->clk_num; i++) {
-		clk_info = &dec_clk->clk_info[i];
-		ret = of_property_read_string_index(pdev->dev.of_node,
-			"clock-names", i, &clk_info->clk_name);
-		if (ret) {
-			mtk_v4l2_err("Failed to get clock name id = %d", i);
-			return ret;
-		}
-		clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
-			clk_info->clk_name);
-		if (IS_ERR(clk_info->vcodec_clk)) {
-			mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
-				clk_info->clk_name);
-			return PTR_ERR(clk_info->vcodec_clk);
-		}
+	pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2");
+	if (IS_ERR(pm->univpll_d2)) {
+		mtk_v4l2_err("devm_clk_get univpll_d2 fail");
+		ret = PTR_ERR(pm->univpll_d2);
+	}
+
+	pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel");
+	if (IS_ERR(pm->clk_cci400_sel)) {
+		mtk_v4l2_err("devm_clk_get clk_cci400_sel fail");
+		ret = PTR_ERR(pm->clk_cci400_sel);
+	}
+
+	pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel");
+	if (IS_ERR(pm->vdec_sel)) {
+		mtk_v4l2_err("devm_clk_get vdec_sel fail");
+		ret = PTR_ERR(pm->vdec_sel);
+	}
+
+	pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll");
+	if (IS_ERR(pm->vdecpll)) {
+		mtk_v4l2_err("devm_clk_get vdecpll fail");
+		ret = PTR_ERR(pm->vdecpll);
+	}
+
+	pm->vencpll = devm_clk_get(&pdev->dev, "vencpll");
+	if (IS_ERR(pm->vencpll)) {
+		mtk_v4l2_err("devm_clk_get vencpll fail");
+		ret = PTR_ERR(pm->vencpll);
+	}
+
+	pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
+	if (IS_ERR(pm->venc_lt_sel)) {
+		mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
+		ret = PTR_ERR(pm->venc_lt_sel);
+	}
+
+	pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src");
+	if (IS_ERR(pm->vdec_bus_clk_src)) {
+		mtk_v4l2_err("devm_clk_get vdec_bus_clk_src");
+		ret = PTR_ERR(pm->vdec_bus_clk_src);
 	}
 
 	pm_runtime_enable(&pdev->dev);
@@ -132,356 +125,78 @@
 
 void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
 {
-	struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk;
-	int ret, i = 0;
+	int ret;
 
-	for (i = 0; i < dec_clk->clk_num; i++) {
-		ret = clk_prepare_enable(dec_clk->clk_info[i].vcodec_clk);
-		if (ret) {
-			mtk_v4l2_err("clk_prepare_enable %d %s fail %d", i,
-				dec_clk->clk_info[i].clk_name, ret);
-			goto error;
-		}
-	}
+	ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000);
+	if (ret)
+		mtk_v4l2_err("clk_set_rate vcodecpll fail %d", ret);
 
-	return;
+	ret = clk_set_rate(pm->vencpll, 800 * 1000000);
+	if (ret)
+		mtk_v4l2_err("clk_set_rate vencpll fail %d", ret);
 
-error:
-	for (i -= 1; i >= 0; i--)
-		clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
+	ret = clk_prepare_enable(pm->vcodecpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vencpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vencpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_bus_clk_src);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->venc_lt_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret);
+
+	ret = clk_prepare_enable(pm->clk_cci400_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->vdec_sel, pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvdec);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
+
 }
 
 void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
 {
-	struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk;
-	int i = 0;
-
-	for (i = dec_clk->clk_num - 1; i >= 0; i--)
-		clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
-}
-void mtk_prepare_vdec_dvfs(struct mtk_vcodec_dev *mtkdev)
-{
-#ifdef CONFIG_MEDIATEK_DVFS
-	unsigned long freq = 0;
-	int i = 0;
-	struct platform_device *pdev;
-	struct dev_pm_opp *opp;
-
-	pdev = mtkdev->plat_dev;
-
-	dev_pm_opp_of_add_table(&pdev->dev);
-
-	reg = devm_regulator_get(&pdev->dev, "dvfsrc-vcore");
-	if (!IS_ERR(reg)) {
-		mtk_v4l2_debug(1,
-			"devm_regulator_get success, regualtor:%p\n", reg);
-	} else {
-		mtk_v4l2_err("devm_regulator_get fail!!\n");
-		return;
-	}
-	vdec_freq_step_size = dev_pm_opp_get_opp_count(&pdev->dev);
-	vdec_freq_steps = kcalloc(
-		vdec_freq_step_size, sizeof(unsigned long), GFP_KERNEL);
-	while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &freq))) {
-		vdec_freq_steps[i] = freq;
-		mtk_v4l2_debug(3, "i:%d, freq:%lu\n", i, freq);
-		freq++;
-		i++;
-		dev_pm_opp_put(opp);
-	}
-	freq = vdec_freq_steps[vdec_freq_step_size - 1];
-	opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &freq);
-	vdec_high_volt = dev_pm_opp_get_voltage(opp);
-	dev_pm_opp_put(opp);
-	/*convert to MHZ from HZ*/
-	for (i = 0; i < vdec_freq_step_size; i++)
-		vdec_freq_steps[i] = vdec_freq_steps[i]/ONE_MHZ;
-	mtk_v4l2_debug(1, "%s, vdec_freq_step_size:%d, high_volt:%d\n",
-	    __func__, vdec_freq_step_size, vdec_high_volt);
-#endif
-}
-
-void mtk_unprepare_vdec_dvfs(void)
-{
-#ifdef CONFIG_MEDIATEK_DVFS
-	kfree(vdec_freq_steps);
-#endif
-}
-int mtk_prepare_vdec_emi_bw(struct mtk_vcodec_dev *mtkdev)
-{
-	int ret = 0;
-#ifdef CONFIG_MEDIATEK_EMI_BW
-	struct platform_device *pdev;
-
-	pdev = mtkdev->plat_dev;
-	vdec_mc = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_MC");
-	if (IS_ERR_OR_NULL(vdec_mc)) {
-		mtk_v4l2_err("of_icc_get vdec_mc fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_mc));
-		return PTR_ERR_OR_ZERO(vdec_mc);
-	}
-	vdec_ufo = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_UFO");
-	if (IS_ERR_OR_NULL(vdec_ufo)) {
-		mtk_v4l2_err("of_icc_get vdec_ufo fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_ufo));
-		return PTR_ERR_OR_ZERO(vdec_ufo);
-	}
-	vdec_pp = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_PP");
-	if (IS_ERR_OR_NULL(vdec_pp)) {
-		mtk_v4l2_err("of_icc_get vdec_pp fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_pp));
-		return PTR_ERR_OR_ZERO(vdec_pp);
-	}
-	vdec_pred_rd = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_PRED_RD");
-	if (IS_ERR_OR_NULL(vdec_pred_rd)) {
-		mtk_v4l2_err("of_icc_get vdec_pred_rd fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_pred_rd));
-		return PTR_ERR_OR_ZERO(vdec_pred_rd);
-	}
-	vdec_pred_wr = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_PRED_WR");
-	if (IS_ERR_OR_NULL(vdec_pred_wr)) {
-		mtk_v4l2_err("of_icc_get vdec_pred_wr fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_pred_wr));
-		return PTR_ERR_OR_ZERO(vdec_pred_wr);
-	}
-	vdec_ppwrap = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_PPWRAP");
-	if (IS_ERR_OR_NULL(vdec_ppwrap)) {
-		mtk_v4l2_err("of_icc_get vdec_ppwrap fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_ppwrap));
-		return PTR_ERR_OR_ZERO(vdec_ppwrap);
-	}
-	vdec_tile = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_TILE");
-	if (IS_ERR_OR_NULL(vdec_tile)) {
-		mtk_v4l2_err("of_icc_get vdec_tile fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_tile));
-		return PTR_ERR_OR_ZERO(vdec_tile);
-	}
-	vdec_vld = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_VLD");
-	if (IS_ERR_OR_NULL(vdec_vld)) {
-		mtk_v4l2_err("of_icc_get vdec_vld fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_vld));
-		return PTR_ERR_OR_ZERO(vdec_vld);
-	}
-	vdec_vld2 = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_VLD2");
-	if (IS_ERR_OR_NULL(vdec_vld2)) {
-		mtk_v4l2_err("of_icc_get vdec_vld2 fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_vld2));
-		return PTR_ERR_OR_ZERO(vdec_vld2);
-	}
-	vdec_avc_mv = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_AVC_MV");
-	if (IS_ERR_OR_NULL(vdec_avc_mv)) {
-		mtk_v4l2_err("of_icc_get vdec_avc_mv fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_avc_mv));
-		return PTR_ERR_OR_ZERO(vdec_avc_mv);
-	}
-	vdec_ufo_enc = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_UFO_ENC");
-	if (IS_ERR_OR_NULL(vdec_ufo_enc)) {
-		mtk_v4l2_err("of_icc_get vdec_ufo_enc fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_ufo_enc));
-		return PTR_ERR_OR_ZERO(vdec_ufo_enc);
-	}
-	vdec_rg_ctrl_dma = of_icc_get(&pdev->dev, "MT_MM_M4U_VDEC_RG_CTRL_DMA");
-	if (IS_ERR_OR_NULL(vdec_rg_ctrl_dma)) {
-		mtk_v4l2_err("of_icc_get vdec_rg_ctrl_dma fail:%d!!\n",
-			PTR_ERR_OR_ZERO(vdec_rg_ctrl_dma));
-		return PTR_ERR_OR_ZERO(vdec_rg_ctrl_dma);
-	}
-#endif
-	return ret;
-}
-
-void mtk_unprepare_vdec_emi_bw(void)
-{
-}
-
-void mtk_vdec_dvfs_begin(struct mtk_vcodec_ctx *ctx)
-{
-#ifdef CONFIG_MEDIATEK_DVFS
-	int freq = 0;
-	int target_freq_mhz = 0;
-	int low_volt = 0;
-	unsigned long target_freq = 0;
-	struct codec_job *vdec_cur_job = 0;
-	struct platform_device *pdev;
-	struct mtk_vcodec_pm *pm;
-	struct dev_pm_opp *opp;
-
-	pm = &ctx->dev->pm;
-	pdev = ctx->dev->plat_dev;
-
-	mutex_lock(&ctx->dev->dec_dvfs_mutex);
-	vdec_cur_job = move_job_to_head(&ctx->id, &vdec_jobs);
-	if (vdec_cur_job != 0) {
-		vdec_cur_job->start = get_time_us();
-		freq = est_freq(vdec_cur_job->handle, &vdec_jobs,
-					vdec_hists);
-		target_freq_mhz = match_freq(freq, vdec_freq_steps,
-					vdec_freq_step_size);
-		target_freq = target_freq_mhz * ONE_MHZ;
-
-		if (freq > 0) {
-			vdec_freq = freq;
-			if (vdec_freq > target_freq_mhz)
-				vdec_freq = target_freq_mhz;
-			vdec_cur_job->mhz = (int)target_freq_mhz;
-			opp = dev_pm_opp_find_freq_ceil(&pdev->dev,
-				&target_freq);
-			if (!IS_ERR(opp))
-				opp = dev_pm_opp_find_freq_floor(&pdev->dev,
-					&target_freq);
-			else {
-				mtk_v4l2_debug(1, "%s:%d, get opp fail\n",
-					__func__, __LINE__);
-				mutex_unlock(&ctx->dev->dec_dvfs_mutex);
-				return;
-			}
-			low_volt = dev_pm_opp_get_voltage(opp);
-			regulator_set_voltage(reg, low_volt, vdec_high_volt);
-		}
-	} else {
-		target_freq_mhz = match_freq(DEFAULT_MHZ, vdec_freq_steps,
-						vdec_freq_step_size);
-		target_freq = target_freq_mhz * ONE_MHZ;
-		opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &target_freq);
-		if (!IS_ERR(opp))
-			opp = dev_pm_opp_find_freq_floor(&pdev->dev,
-				&target_freq);
-		else {
-			mtk_v4l2_debug(1, "%s:%d, get opp fail\n",
-				__func__, __LINE__);
-			mutex_unlock(&ctx->dev->dec_dvfs_mutex);
-			return;
-		}
-		low_volt = dev_pm_opp_get_voltage(opp);
-		regulator_set_voltage(reg, low_volt, vdec_high_volt);
-	}
-	mutex_unlock(&ctx->dev->dec_dvfs_mutex);
-#endif
-}
-void mtk_vdec_dvfs_end(struct mtk_vcodec_ctx *ctx)
-{
-#ifdef CONFIG_MEDIATEK_DVFS
-	int low_volt = 0;
-
-	struct codec_job *vdec_cur_job = 0;
-
-	/* vdec dvfs */
-	mutex_lock(&ctx->dev->dec_dvfs_mutex);
-	vdec_cur_job = vdec_jobs;
-	if (vdec_cur_job->handle == &ctx->id) {
-		vdec_cur_job->end = get_time_us();
-		update_hist(vdec_cur_job, &vdec_hists, 0);
-		vdec_jobs = vdec_jobs->next;
-		kfree(vdec_cur_job);
-	} else {
-		/* print error log */
-	}
-	regulator_set_voltage(reg, low_volt, vdec_high_volt);
-
-	mutex_unlock(&ctx->dev->dec_dvfs_mutex);
-#endif
-}
-void mtk_vdec_emi_bw_begin(struct mtk_vcodec_ctx *ctx)
-{
-#ifdef CONFIG_MEDIATEK_EMI_BW
-	int b_freq_idx = 0;
-	int f_type = 1; /* TODO */
-	long emi_bw = 0;
-	long emi_bw_input = 0;
-	long emi_bw_output = 0;
-
-	if (vdec_freq_step_size > 1)
-		b_freq_idx = vdec_freq_step_size - 1;
-
-	emi_bw = 8L * 1920 * 1080 * 3 * 10 * vdec_freq;
-	emi_bw_input = 8 * vdec_freq / STD_VDEC_FREQ;
-	emi_bw_output = 1920 * 1088 * 3 * 30 * 10 * vdec_freq /
-			2 / 3 / STD_VDEC_FREQ / 1024 / 1024;
-
-	switch (ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc) {
-	case V4L2_PIX_FMT_H264:
-		emi_bw = emi_bw * h264_frm_scale[f_type] / (2 * STD_VDEC_FREQ);
-		break;
-	case V4L2_PIX_FMT_H265:
-		emi_bw = emi_bw * h265_frm_scale[f_type] / (2 * STD_VDEC_FREQ);
-		break;
-	case V4L2_PIX_FMT_VP8:
-		emi_bw = emi_bw * vp8_frm_scale[f_type] / (2 * STD_VDEC_FREQ);
-		break;
-	case V4L2_PIX_FMT_VP9:
-		emi_bw = emi_bw * vp9_frm_scale[f_type] / (2 * STD_VDEC_FREQ);
-		break;
-	case V4L2_PIX_FMT_MPEG4:
-	case V4L2_PIX_FMT_H263:
-	case V4L2_PIX_FMT_S263:
-	case V4L2_PIX_FMT_XVID:
-	case V4L2_PIX_FMT_DIVX3:
-	case V4L2_PIX_FMT_DIVX4:
-	case V4L2_PIX_FMT_DIVX5:
-	case V4L2_PIX_FMT_DIVX6:
-	case V4L2_PIX_FMT_MPEG1:
-	case V4L2_PIX_FMT_MPEG2:
-		emi_bw = emi_bw * mp24_frm_scale[f_type] / (2 * STD_VDEC_FREQ);
-		break;
-	}
-
-	/* bits/s to MBytes/s */
-	emi_bw = emi_bw / (1024 * 1024) / 8;
-
-	if (0) {    /* UFO */
-		emi_bw = emi_bw * 6 / 10;
-		emi_bw_output = emi_bw_output * 6 / 10;
-	}
-
-	emi_bw = emi_bw - emi_bw_output - (emi_bw_input * 2);
-	if (emi_bw < 0)
-		emi_bw = 0;
-
-	icc_set_bw(vdec_mc, MBps_to_icc(emi_bw), 0);
-	icc_set_bw(vdec_pp, MBps_to_icc(emi_bw_output), 0);
-	icc_set_bw(vdec_pred_rd, MBps_to_icc(1), 0);
-	icc_set_bw(vdec_pred_wr, MBps_to_icc(1), 0);
-	icc_set_bw(vdec_ppwrap, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_tile, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_vld, MBps_to_icc(emi_bw_input), 0);
-	icc_set_bw(vdec_vld2, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_avc_mv, MBps_to_icc(emi_bw_input * 2), 0);
-	icc_set_bw(vdec_rg_ctrl_dma, MBps_to_icc(0), 0);
-#endif
-}
-static void mtk_vdec_emi_bw_end(void)
-{
-#ifdef CONFIG_MEDIATEK_EMI_BW
-	icc_set_bw(vdec_ufo, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_ufo_enc, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_mc, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_pp, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_pred_rd, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_pred_wr, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_ppwrap, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_tile, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_vld, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_vld2, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_avc_mv, MBps_to_icc(0), 0);
-	icc_set_bw(vdec_rg_ctrl_dma, MBps_to_icc(0), 0);
-#endif
-}
-void mtk_vdec_pmqos_prelock(struct mtk_vcodec_ctx *ctx)
-{
-	mutex_lock(&ctx->dev->dec_dvfs_mutex);
-	#ifdef CONFIG_MEDIATEK_DVFS
-	add_job(&ctx->id, &vdec_jobs);
-	#endif
-	mutex_unlock(&ctx->dev->dec_dvfs_mutex);
-}
-void mtk_vdec_pmqos_begin_frame(struct mtk_vcodec_ctx *ctx)
-{
-	mtk_vdec_dvfs_begin(ctx);
-	mtk_vdec_emi_bw_begin(ctx);
-}
-
-void mtk_vdec_pmqos_end_frame(struct mtk_vcodec_ctx *ctx)
-{
-	mtk_vdec_dvfs_end(ctx);
-	mtk_vdec_emi_bw_end();
+	mtk_smi_larb_put(pm->larbvdec);
+	clk_disable_unprepare(pm->vdec_sel);
+	clk_disable_unprepare(pm->vdecpll);
+	clk_disable_unprepare(pm->univpll_d2);
+	clk_disable_unprepare(pm->clk_cci400_sel);
+	clk_disable_unprepare(pm->venc_lt_sel);
+	clk_disable_unprepare(pm->vdec_bus_clk_src);
+	clk_disable_unprepare(pm->vencpll);
+	clk_disable_unprepare(pm->vcodecpll);
 }
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
old mode 100644
new mode 100755
index 21cf9f9..86a7825
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -25,12 +25,4 @@
 void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm);
 
-void mtk_prepare_vdec_dvfs(struct mtk_vcodec_dev *dev);
-void mtk_unprepare_vdec_dvfs(void);
-int mtk_prepare_vdec_emi_bw(struct mtk_vcodec_dev *dev);
-void mtk_unprepare_vdec_emi_bw(void);
-
-void mtk_vdec_pmqos_prelock(struct mtk_vcodec_ctx *ctx);
-void mtk_vdec_pmqos_begin_frame(struct mtk_vcodec_ctx *ctx);
-void mtk_vdec_pmqos_end_frame(struct mtk_vcodec_ctx *ctx);
 #endif /* _MTK_VCODEC_DEC_PM_H_ */
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
old mode 100644
new mode 100755
index 97b4b82..3cffb38
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -1,17 +1,17 @@
 /*
- * Copyright (c) 2016 MediaTek Inc.
- * Author: PC Chen <pc.chen@mediatek.com>
- *         Tiffany Lin <tiffany.lin@mediatek.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen@mediatek.com>
+*         Tiffany Lin <tiffany.lin@mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License 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 _MTK_VCODEC_DRV_H_
 #define _MTK_VCODEC_DRV_H_
@@ -23,20 +23,15 @@
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf2-core.h>
 #include "mtk_vcodec_util.h"
-#ifdef CONFIG_VB2_MEDIATEK_DMA
-#include "mtk-dma-contig.h"
-#endif
 
 #define MTK_VCODEC_DRV_NAME	"mtk_vcodec_drv"
 #define MTK_VCODEC_DEC_NAME	"mtk-vcodec-dec"
 #define MTK_VCODEC_ENC_NAME	"mtk-vcodec-enc"
 #define MTK_PLATFORM_STR	"platform:mt8173"
 
-#define MTK_SLOWMOTION_GCE_TH   120
 #define MTK_VCODEC_MAX_PLANES	3
 #define MTK_V4L2_BENCHMARK	0
 #define WAIT_INTR_TIMEOUT_MS	1000
-#define SUSPEND_TIMEOUT_CNT     5000
 
 /**
  * enum mtk_hw_reg_idx - MTK hw register base index
@@ -54,16 +49,14 @@
 	VDEC_HWQ,
 	VDEC_HWB,
 	VDEC_HWG,
-	NUM_MAX_VDEC_REG_BASE
-};
-
-enum mtk_enc_dtsi_reg_idx {
+	NUM_MAX_VDEC_REG_BASE,
+	/* h264 encoder */
+	VENC_SYS = NUM_MAX_VDEC_REG_BASE,
+	/* vp8 encoder */
 	VENC_LT_SYS,
-	VENC_SYS,
-	NUM_MAX_VENC_REG_BASE
+	NUM_MAX_VCODEC_REG_BASE
 };
 
-
 /**
  * enum mtk_instance_type - The type of an MTK Vcodec instance.
  */
@@ -99,34 +92,6 @@
 	MTK_ENCODE_PARAM_INTRA_PERIOD = (1 << 2),
 	MTK_ENCODE_PARAM_FORCE_INTRA = (1 << 3),
 	MTK_ENCODE_PARAM_GOP_SIZE = (1 << 4),
-	MTK_ENCODE_PARAM_SCENARIO = (1 << 5),
-	MTK_ENCODE_PARAM_NONREFP = (1 << 6),
-	MTK_ENCODE_PARAM_DETECTED_FRAMERATE = (1 << 7),
-	MTK_ENCODE_PARAM_RFS_ON = (1 << 8),
-	MTK_ENCODE_PARAM_PREPEND_SPSPPS_TO_IDR = (1 << 9),
-	MTK_ENCODE_PARAM_OPERATION_RATE = (1 << 10),
-	MTK_ENCODE_PARAM_BITRATE_MODE = (1 << 11),
-
-};
-/*
- * enum venc_yuv_fmt - The type of input yuv format
- * (VCU related: If you change the order, you must also update the VCU codes.)
- * @VENC_YUV_FORMAT_I420: I420 YUV format
- * @VENC_YUV_FORMAT_YV12: YV12 YUV format
- * @VENC_YUV_FORMAT_NV12: NV12 YUV format
- * @VENC_YUV_FORMAT_NV21: NV21 YUV format
- */
-enum venc_yuv_fmt {
-	VENC_YUV_FORMAT_I420 = 3,
-	VENC_YUV_FORMAT_YV12 = 5,
-	VENC_YUV_FORMAT_NV12 = 6,
-	VENC_YUV_FORMAT_NV21 = 7,
-	VENC_YUV_FORMAT_24bitRGB888 = 11,
-	VENC_YUV_FORMAT_24bitBGR888 = 12,
-	VENC_YUV_FORMAT_32bitRGBA8888 = 13,
-	VENC_YUV_FORMAT_32bitBGRA8888 = 14,
-	VENC_YUV_FORMAT_32bitARGB8888 = 15,
-	VENC_YUV_FORMAT_32bitABGR8888 = 16,
 };
 
 enum mtk_fmt_type {
@@ -145,6 +110,15 @@
 };
 
 /**
+ * struct mtk_codec_framesizes - Structure used to store information about
+ *							framesizes
+ */
+struct mtk_codec_framesizes {
+	u32	fourcc;
+	struct	v4l2_frmsize_stepwise	stepwise;
+};
+
+/**
  * struct mtk_q_type - Type of queue
  */
 enum mtk_q_type {
@@ -163,7 +137,7 @@
 	enum v4l2_field	field;
 	unsigned int	bytesperline[MTK_VCODEC_MAX_PLANES];
 	unsigned int	sizeimage[MTK_VCODEC_MAX_PLANES];
-	const struct mtk_video_fmt	*fmt;
+	struct mtk_video_fmt	*fmt;
 };
 
 /**
@@ -177,9 +151,9 @@
  * @intra_period: I frame period
  * @gop_size: group of picture size, it's used as the intra frame period
  * @framerate_num: frame rate numerator. ex: framerate_num=30 and
- *		   framerate_denom=1 means FPS is 30
+ *		   framerate_denom=1 menas FPS is 30
  * @framerate_denom: frame rate denominator. ex: framerate_num=30 and
- *		     framerate_denom=1 means FPS is 30
+ *		     framerate_denom=1 menas FPS is 30
  * @h264_max_qp: Max value for H.264 quantization parameter
  * @h264_profile: V4L2 defined H.264 profile
  * @h264_level: V4L2 defined H.264 level
@@ -196,92 +170,32 @@
 	unsigned int	framerate_num;
 	unsigned int	framerate_denom;
 	unsigned int	h264_max_qp;
-	unsigned int	profile;
-	unsigned int	level;
-	unsigned int    force_intra;
-	unsigned int    scenario;
-	unsigned int    nonrefp;
-	unsigned int    detectframerate;
-	unsigned int    rfs;
-	unsigned int    prependheader;
-	unsigned int    operationrate;
-	unsigned int    bitratemode;
-};
-/*
- * struct venc_enc_prm - encoder settings for VENC_SET_PARAM_ENC used in
- *                                        venc_if_set_param()
- * @input_fourcc: input yuv format
- * @h264_profile: V4L2 defined H.264 profile
- * @h264_level: V4L2 defined H.264 level
- * @width: image width
- * @height: image height
- * @buf_width: buffer width
- * @buf_height: buffer height
- * @frm_rate: frame rate in fps
- * @intra_period: intra frame period
- * @bitrate: target bitrate in bps
- * @gop_size: group of picture size
- * @sizeimage: image size for each plane
- */
-struct venc_enc_param {
-	enum venc_yuv_fmt input_yuv_fmt;
-	unsigned int profile;
-	unsigned int level;
-	unsigned int width;
-	unsigned int height;
-	unsigned int buf_width;
-	unsigned int buf_height;
-	unsigned int frm_rate;
-	unsigned int intra_period;
-	unsigned int bitrate;
-	unsigned int gop_size;
-	unsigned int scenario;
-	unsigned int nonrefp;
-	unsigned int detectframerate;
-	unsigned int rfs;
-	unsigned int prependheader;
-	unsigned int operationrate;
-	unsigned int bitratemode;
-	unsigned int sizeimage[MTK_VCODEC_MAX_PLANES];
-};
-/*
- * struct venc_frm_buf - frame buffer information used in venc_if_encode()
- * @fb_addr: plane frame buffer addresses
- * @num_planes: frmae buffer plane num
- */
-struct venc_frm_buf {
-	struct mtk_vcodec_mem fb_addr[MTK_VCODEC_MAX_PLANES];
-	unsigned int num_planes;
-	unsigned long timestamp;
-};
-
-/**
- * struct mtk_vcodec_clk_info - Structure used to store clock name
- */
-struct mtk_vcodec_clk_info {
-	const char	*clk_name;
-	struct clk	*vcodec_clk;
-};
-
-/**
- * struct mtk_vcodec_clk - Structure used to store vcodec clock information
- */
-struct mtk_vcodec_clk {
-	struct mtk_vcodec_clk_info	*clk_info;
-	int	clk_num;
+	unsigned int	h264_profile;
+	unsigned int	h264_level;
+	unsigned int	force_intra;
 };
 
 /**
  * struct mtk_vcodec_pm - Power management data structure
  */
 struct mtk_vcodec_pm {
-	struct mtk_vcodec_clk	vdec_clk;
+	struct clk	*vdec_bus_clk_src;
+	struct clk	*vencpll;
 
-	struct mtk_vcodec_clk	venc_clk;
+	struct clk	*vcodecpll;
+	struct clk	*univpll_d2;
+	struct clk	*clk_cci400_sel;
+	struct clk	*vdecpll;
+	struct clk	*vdec_sel;
+	struct clk	*vencpll_d2;
+	struct clk	*venc_sel;
+	struct clk	*univpll1_d2;
+	struct clk	*venc_lt_sel;
+	struct device	*larbvdec;
+	struct device	*larbvenc;
+	struct device	*larbvenclt;
 	struct device	*dev;
 	struct mtk_vcodec_dev	*mtkdev;
-	int enc_larb_num;
-	struct device_node *chip_node;
 };
 
 /**
@@ -290,72 +204,24 @@
  * @pic_h: picture height
  * @buf_w: picture buffer width (64 aligned up from pic_w)
  * @buf_h: picture buffer heiht (64 aligned up from pic_h)
- * @fb_sz: bitstream size
+ * @y_bs_sz: Y bitstream size
+ * @c_bs_sz: CbCr bitstream size
+ * @y_len_sz: additional size required to store decompress information for y
+ *		plane
+ * @c_len_sz: additional size required to store decompress information for cbcr
+ *		plane
  * E.g. suppose picture size is 176x144,
  *      buffer size will be aligned to 176x160.
- * @cap_fourcc: fourcc number(may changed when resolution change)
- * @reserved: align struct to 64-bit in order to adjust 32-bit and 64-bit os.
  */
 struct vdec_pic_info {
-/** from yunfei upstream
 	unsigned int pic_w;
 	unsigned int pic_h;
 	unsigned int buf_w;
 	unsigned int buf_h;
-	unsigned int fb_sz[VIDEO_MAX_PLANES];
-	unsigned int cap_fourcc;
-	unsigned int reserved;
-*/
-	__u32 pic_w;
-	__u32 pic_h;
-	__u32 buf_w;
-	__u32 buf_h;
-	__u32 fb_sz[VIDEO_MAX_PLANES];
-	__u32 bitdepth;
-	__u32 layout_mode;
-	unsigned int cap_fourcc;
-};
-
-enum mtk_dec_param {
-	MTK_DEC_PARAM_NONE = 0,
-	MTK_DEC_PARAM_DECODE_MODE = (1 << 0),
-	MTK_DEC_PARAM_FRAME_SIZE = (1 << 1),
-	MTK_DEC_PARAM_FIXED_MAX_FRAME_SIZE = (1 << 2),
-	MTK_DEC_PARAM_CRC_PATH = (1 << 3),
-	MTK_DEC_PARAM_GOLDEN_PATH = (1 << 4),
-	MTK_DEC_PARAM_WAIT_KEY_FRAME = (1 << 5),
-	MTK_DEC_PARAM_NAL_SIZE_LENGTH = (1 << 6),
-	MTK_DEC_PARAM_FIXED_MAX_OUTPUT_BUFFER = (1 << 7),
-	MTK_DEC_PARAM_SEC_DECODE = (1 << 8),
-	MTK_DEC_PARAM_OPERATING_RATE = (1 << 9),
-	MTK_DEC_PARAM_TOTAL_FRAME_BUFQ_COUNT = (1 << 10)
-};
-
-struct mtk_dec_params {
-	unsigned int    decode_mode;
-	unsigned int    frame_size_width;
-	unsigned int    frame_size_height;
-	unsigned int    fixed_max_frame_size_width;
-	unsigned int    fixed_max_frame_size_height;
-	char            *crc_path;
-	char            *golden_path;
-	unsigned int    fb_num_planes;
-	unsigned int	wait_key_frame;
-	unsigned int	nal_size_length;
-	unsigned int	svp_mode;
-	unsigned int	operating_rate;
-	unsigned int	total_frame_bufq_count;
-};
-
-/**
- * struct mtk_codec_framesizes - Structure used to store information about
- *							framesizes
- */
-struct mtk_codec_framesizes {
-	__u32	fourcc;
-	__u32	profile;
-	__u32	level;
-	struct	v4l2_frmsize_stepwise	stepwise;
+	unsigned int y_bs_sz;
+	unsigned int c_bs_sz;
+	unsigned int y_len_sz;
+	unsigned int c_len_sz;
 };
 
 /**
@@ -389,9 +255,6 @@
  * @encode_work: worker for the encoding
  * @last_decoded_picinfo: pic information get from latest decode
  * @empty_flush_buf: a fake size-0 capture buffer that indicates flush
- * @ctrls: CID controls
- * @codec_type: current set input codec, in V4L2 pixel format
- * @cap_count_sem: count of available capture buffers
  *
  * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
  * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
@@ -412,18 +275,13 @@
 	enum mtk_instance_state state;
 	enum mtk_encode_param param_change;
 	struct mtk_enc_params enc_params;
-	enum mtk_dec_param dec_param_change;
-	struct mtk_dec_params dec_params;
 
 	const struct vdec_common_if *dec_if;
 	const struct venc_common_if *enc_if;
-	void *drv_handle;
+	unsigned long drv_handle;
 
 	struct vdec_pic_info picinfo;
 	int dpb_size;
-	int last_dpb_size;
-	unsigned int errormap_info[VB2_MAX_FRAME];
-	u64 input_max_ts;
 
 	int int_cond;
 	int int_type;
@@ -435,13 +293,6 @@
 	struct work_struct encode_work;
 	struct vdec_pic_info last_decoded_picinfo;
 	struct mtk_video_dec_buf *empty_flush_buf;
-	struct mtk_video_enc_buf *enc_flush_buf;
-	struct v4l2_ctrl **ctrls;
-	struct vb2_buffer *pend_src_buf;
-	int slowmotion;
-	int oal_vcodec;
-
-	int current_codec;
 
 	enum v4l2_colorspace colorspace;
 	enum v4l2_ycbcr_encoding ycbcr_enc;
@@ -450,78 +301,25 @@
 
 	int decoded_frame_cnt;
 	struct mutex lock;
-	struct mutex worker_lock;
 
 };
 
 /**
- * struct mtk_vcodec_dec_pdata - compatible data for each IC
- * @init_vdec_params: init vdec params
- * @ctrls_setup: init vcodec dec ctrls
- * @worker: worker to start a decode job
- * @flush_decoder: function that flushes the decoder
- *
- * @vdec_vb2_ops: struct vb2_ops
- *
- * @vdec_formats: supported video decoder formats
- * @num_formats: count of video decoder formats
- * @default_out_fmt: default output buffer format
- * @default_cap_fmt: default capture buffer format
- *
- * @vdec_framesizes: supported video decoder frame sizes
- * @num_framesizes: count of video decoder frame sizes
- *
- * @uses_stateless_api: whether the decoder uses the stateless API with requests
- */
-
-struct mtk_vcodec_dec_pdata {
-	void (*init_vdec_params)(struct mtk_vcodec_ctx *ctx);
-	int (*ctrls_setup)(struct mtk_vcodec_ctx *ctx);
-	void (*worker)(struct work_struct *work);
-	int (*flush_decoder)(struct mtk_vcodec_ctx *ctx);
-
-	struct vb2_ops *vdec_vb2_ops;
-
-	const struct mtk_video_fmt *vdec_formats;
-	const int num_formats;
-	const struct mtk_video_fmt *default_out_fmt;
-	const struct mtk_video_fmt *default_cap_fmt;
-
-	const struct mtk_codec_framesizes *vdec_framesizes;
-	const int num_framesizes;
-
-	bool uses_stateless_api;
-};
-
-/**
- * struct mtk_vcodec_enc_pdata - compatibler data for each IC
- *
- * @uses_ext: whether the encoder uses the extended firmware messaging format
- * @supports_vp8: whether the encoder supports VP8
- */
-struct mtk_vcodec_enc_pdata {
-	bool uses_ext;
-	bool supports_vp8;
-};
-
-/**
  * struct mtk_vcodec_dev - driver data
  * @v4l2_dev: V4L2 device to register video devices for.
  * @vfd_dec: Video device for decoder
- * @mdev_dec: Media device for decoder
  * @vfd_enc: Video device for encoder.
  *
  * @m2m_dev_dec: m2m device for decoder
  * @m2m_dev_enc: m2m device for encoder.
  * @plat_dev: platform device
+ * @vpu_plat_dev: mtk vpu platform device
  * @ctx_list: list of struct mtk_vcodec_ctx
  * @irqlock: protect data access by irq handler and work thread
  * @curr_ctx: The context that is waiting for codec hardware
  *
  * @reg_base: Mapped address of MTK Vcodec registers.
- * @vdec_pdata: Current arch private data.
  *
- * @ipi_msg_handle: Current arch ipi message handle.
  * @id_counter: used to identify current opened instance
  *
  * @encode_workqueue: encode work queue
@@ -545,22 +343,16 @@
 struct mtk_vcodec_dev {
 	struct v4l2_device v4l2_dev;
 	struct video_device *vfd_dec;
-	struct media_device mdev_dec;
 	struct video_device *vfd_enc;
 
 	struct v4l2_m2m_dev *m2m_dev_dec;
 	struct v4l2_m2m_dev *m2m_dev_enc;
 	struct platform_device *plat_dev;
-	struct platform_device *vcu_plat_dev;
+	struct platform_device *vpu_plat_dev;
 	struct list_head ctx_list;
 	spinlock_t irqlock;
 	struct mtk_vcodec_ctx *curr_ctx;
-	void __iomem *reg_base[NUM_MAX_VDEC_REG_BASE];
-	void __iomem *enc_reg_base[NUM_MAX_VENC_REG_BASE];
-	const struct mtk_vcodec_dec_pdata *vdec_pdata;
-	const struct mtk_vcodec_enc_pdata *venc_pdata;
-
-	struct mtk_vcodec_fw *ipi_msg_handle;
+	void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE];
 
 	unsigned long id_counter;
 
@@ -577,14 +369,10 @@
 
 	struct mutex dec_mutex;
 	struct mutex enc_mutex;
-	struct mutex dec_dvfs_mutex;
-	struct semaphore enc_sem;
-	struct mutex enc_dvfs_mutex;
 
 	struct mtk_vcodec_pm pm;
 	unsigned int dec_capability;
 	unsigned int enc_capability;
-	bool is_codec_suspending;
 };
 
 static inline struct mtk_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh)
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
old mode 100644
new mode 100755
index d76548d..6ad4085
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -1,25 +1,22 @@
 /*
- * Copyright (c) 2016 MediaTek Inc.
- * Author: PC Chen <pc.chen@mediatek.com>
- *         Tiffany Lin <tiffany.lin@mediatek.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen@mediatek.com>
+*         Tiffany Lin <tiffany.lin@mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License 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 <media/v4l2-event.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-dma-contig.h>
 #include <soc/mediatek/smi.h>
-#include <linux/delay.h>
-#include <linux/semaphore.h>
-#include <linux/log2.h>
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_enc.h"
@@ -39,175 +36,56 @@
 
 
 static void mtk_venc_worker(struct work_struct *work);
-static struct mtk_video_fmt
-	mtk_video_formats[MTK_MAX_ENC_CODECS_SUPPORT] = { {0} };
-static struct mtk_codec_framesizes
-	mtk_venc_framesizes[MTK_MAX_ENC_CODECS_SUPPORT] = { {0} };
-static unsigned int default_out_fmt_idx;
-static unsigned int default_cap_fmt_idx;
 
-static void get_supported_format(struct mtk_vcodec_ctx *ctx)
-{
-	unsigned int i;
+static struct mtk_video_fmt mtk_video_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YVU420M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = MTK_FMT_ENC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.type = MTK_FMT_ENC,
+		.num_planes = 1,
+	},
+};
 
-	if (mtk_video_formats[0].fourcc == 0) {
-		if (venc_if_get_param(ctx,
-			GET_PARAM_CAPABILITY_SUPPORTED_FORMATS,
-			&mtk_video_formats) != 0) {
-			mtk_v4l2_err("Error!! Cannot get supported format");
-			return;
-		}
-		for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT; i++) {
-			if (mtk_video_formats[i].fourcc != 0 &&
-			    mtk_video_formats[i].type == MTK_FMT_FRAME) {
-				default_out_fmt_idx = i;
-				break;
-			}
-		}
-		for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT; i++) {
-			if (mtk_video_formats[i].fourcc != 0 &&
-			    mtk_video_formats[i].type == MTK_FMT_ENC) {
-				default_cap_fmt_idx = i;
-				break;
-			}
-		}
-	}
-}
-static void get_supported_framesizes(struct mtk_vcodec_ctx *ctx)
-{
-	unsigned int i;
+#define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
 
-	if (mtk_venc_framesizes[0].fourcc == 0) {
-		if (venc_if_get_param(ctx, GET_PARAM_CAPABILITY_FRAME_SIZES,
-				      &mtk_venc_framesizes) != 0) {
-			mtk_v4l2_err("[%d] Error!! Cannot get frame size",
-				ctx->id);
-			return;
-		}
+static const struct mtk_codec_framesizes mtk_venc_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = { MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
+			      MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16 },
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.stepwise = { MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
+			      MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16 },
+	},
+};
 
-		for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT; i++) {
-			if (mtk_venc_framesizes[i].fourcc != 0)
-				mtk_v4l2_debug(1, "venc_fs[%d] %d s %d %d %d %d %d %d\n",
-				i, mtk_venc_framesizes[i].fourcc,
-				mtk_venc_framesizes[i].stepwise.min_width,
-				mtk_venc_framesizes[i].stepwise.max_width,
-				mtk_venc_framesizes[i].stepwise.step_width,
-				mtk_venc_framesizes[i].stepwise.min_height,
-				mtk_venc_framesizes[i].stepwise.max_height,
-				mtk_venc_framesizes[i].stepwise.step_height);
-		}
-	}
-}
-static void get_free_buffers(struct mtk_vcodec_ctx *ctx,
-				struct venc_done_result *pResult)
-{
-	venc_if_get_param(ctx, GET_PARAM_FREE_BUFFERS, pResult);
-}
-static void return_free_buffers(struct mtk_vcodec_ctx *ctx)
-{
-	struct venc_done_result rResult;
-	struct venc_frm_buf *pfrm;
-	struct mtk_vcodec_mem *pbs;
-	struct mtk_video_enc_buf *bs_info, *frm_info;
-	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
-	struct vb2_buffer *dst_buf;
-
-	do {
-		dst_vb2_v4l2 = NULL;
-		src_vb2_v4l2 = NULL;
-		pfrm = NULL;
-		pbs = NULL;
-
-		get_free_buffers(ctx, &rResult);
-
-		if (rResult.bs_va != 0) {
-			pbs = (struct mtk_vcodec_mem *)rResult.bs_va;
-			bs_info = container_of(pbs,
-				struct mtk_video_enc_buf, bs_buf);
-			dst_vb2_v4l2 = &bs_info->vb;
-		}
-
-		if (rResult.frm_va != 0) {
-			pfrm = (struct venc_frm_buf *)rResult.frm_va;
-			frm_info = container_of(pfrm,
-				struct mtk_video_enc_buf, frm_buf);
-			src_vb2_v4l2 = &frm_info->vb;
-		}
-
-		if (src_vb2_v4l2 && dst_vb2_v4l2) {
-			if (rResult.is_key_frm)
-				dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_KEYFRAME;
-
-			dst_vb2_v4l2->vb2_buf.timestamp =
-				src_vb2_v4l2->vb2_buf.timestamp;
-			dst_vb2_v4l2->timecode = src_vb2_v4l2->timecode;
-			dst_vb2_v4l2->flags |= src_vb2_v4l2->flags;
-			dst_vb2_v4l2->sequence = src_vb2_v4l2->sequence;
-			dst_buf = &dst_vb2_v4l2->vb2_buf;
-			dst_buf->planes[0].bytesused = rResult.bs_size;
-			v4l2_m2m_buf_done(src_vb2_v4l2, VB2_BUF_STATE_DONE);
-			v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_DONE);
-
-			mtk_v4l2_debug(1, "venc_if_encode bs size=%d",
-				rResult.bs_size);
-		} else if (!src_vb2_v4l2 && dst_vb2_v4l2) {
-			dst_buf = &dst_vb2_v4l2->vb2_buf;
-			dst_buf->planes[0].bytesused = rResult.bs_size;
-			dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST;
-			v4l2_m2m_buf_done(dst_vb2_v4l2,
-					VB2_BUF_STATE_DONE);
-		} else if (!src_vb2_v4l2 || !dst_vb2_v4l2) {
-			if (!src_vb2_v4l2)
-				mtk_v4l2_debug(1, "NULL enc src buffer\n");
-
-			if (!dst_vb2_v4l2)
-				mtk_v4l2_debug(1, "NULL enc dst buffer\n");
-		}
-	} while (rResult.bs_va || rResult.frm_va);
-}
-
-
-static struct mtk_video_fmt *mtk_venc_find_format(struct v4l2_format *f,
-						  unsigned int t)
-{
-	struct mtk_video_fmt *fmt;
-	unsigned int k;
-
-	mtk_v4l2_debug(3, "fourcc %d", f->fmt.pix_mp.pixelformat);
-	for (k = 0; k < MTK_MAX_ENC_CODECS_SUPPORT; k++) {
-		fmt = &mtk_video_formats[k];
-		if (fmt->fourcc == f->fmt.pix.pixelformat && fmt->type == t)
-			return fmt;
-	}
-	return NULL;
-}
-
-static int vidioc_venc_check_supported_profile_level(__u32 fourcc,
-	unsigned int pl, bool is_profile)
-{
-	struct v4l2_format f;
-	int i = 0;
-
-	f.fmt.pix.pixelformat = fourcc;
-	if (mtk_venc_find_format(&f, MTK_FMT_ENC) == NULL)
-		return false;
-	for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT; i++) {
-		if (mtk_venc_framesizes[i].fourcc == fourcc) {
-			if (is_profile) {
-				if (mtk_venc_framesizes[i].profile & (1 << pl))
-					return true;
-				else
-					return false;
-			} else {
-				if (mtk_venc_framesizes[i].level >= pl)
-					return true;
-				else
-					return false;
-			}
-		}
-	}
-	return false;
-}
+#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_venc_framesizes)
 
 static int vidioc_venc_s_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -215,10 +93,6 @@
 	struct mtk_enc_params *p = &ctx->enc_params;
 	int ret = 0;
 
-	mtk_v4l2_debug(4, "[%d] id %d val %d array[0] %d array[1] %d",
-				   ctx->id, ctrl->id, ctrl->val,
-				   ctrl->p_new.p_u32[0], ctrl->p_new.p_u32[1]);
-
 	switch (ctrl->id) {
 	case V4L2_CID_MPEG_VIDEO_BITRATE:
 		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_BITRATE val = %d",
@@ -254,54 +128,12 @@
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_PROFILE val = %d",
 			       ctrl->val);
-		if (!vidioc_venc_check_supported_profile_level(
-				V4L2_PIX_FMT_H264, ctrl->val, 1)) {
-			mtk_v4l2_err("ERROR H264_PROFILE check Error! val:%d",
-				ctrl->val);
-		}
-		p->profile = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
-		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H265_PROFILE val = %d",
-			       ctrl->val);
-		if (!vidioc_venc_check_supported_profile_level(
-				V4L2_PIX_FMT_H265, ctrl->val, 1))
-			return -EINVAL;
-		p->profile = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
-		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE val = %d",
-			       ctrl->val);
-		if (!vidioc_venc_check_supported_profile_level(
-			    V4L2_PIX_FMT_MPEG4, ctrl->val, 1))
-			return -EINVAL;
-		p->profile = ctrl->val;
+		p->h264_profile = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
 		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_LEVEL val = %d",
 			       ctrl->val);
-		if (!vidioc_venc_check_supported_profile_level(
-				V4L2_PIX_FMT_H264, ctrl->val, 0)) {
-			mtk_v4l2_err("ERROR H264_LEVEL check Error! val:%d",
-				ctrl->val);
-		}
-		p->level = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H265_TIER_LEVEL:
-		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H265_TIER_LEVEL val = %d",
-			       ctrl->val);
-		if (!vidioc_venc_check_supported_profile_level(
-				V4L2_PIX_FMT_H265, ctrl->val, 0))
-			return -EINVAL;
-		p->level = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
-		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL val = %d",
-			       ctrl->val);
-		if (!vidioc_venc_check_supported_profile_level(
-			    V4L2_PIX_FMT_MPEG4, ctrl->val, 0))
-			return -EINVAL;
-		p->level = ctrl->val;
+		p->h264_level = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
 		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_I_PERIOD val = %d",
@@ -320,57 +152,8 @@
 		p->force_intra = 1;
 		ctx->param_change |= MTK_ENCODE_PARAM_FORCE_INTRA;
 		break;
-	case V4L2_CID_MPEG_MTK_ENCODE_SCENARIO:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_MTK_ENCODE_SCENARIO: %d",
-			ctrl->val);
-		p->scenario = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_SCENARIO;
-		break;
-	case V4L2_CID_MPEG_MTK_ENCODE_NONREFP:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_MTK_ENCODE_NONREFP: %d",
-			ctrl->val);
-		p->nonrefp = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_NONREFP;
-		break;
-	case V4L2_CID_MPEG_MTK_ENCODE_DETECTED_FRAMERATE:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_MTK_ENCODE_DETECTED_FRAMERATE: %d",
-			ctrl->val);
-		p->detectframerate = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_DETECTED_FRAMERATE;
-		break;
-	case V4L2_CID_MPEG_MTK_ENCODE_RFS_ON:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_MTK_ENCODE_RFS_ON: %d",
-			ctrl->val);
-		p->rfs = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_RFS_ON;
-		break;
-	case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: %d",
-			ctrl->val);
-		p->prependheader = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_PREPEND_SPSPPS_TO_IDR;
-		break;
-	case V4L2_CID_MPEG_MTK_ENCODE_OPERATION_RATE:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_MTK_ENCODE_OPERATION_RATE: %d",
-			ctrl->val);
-		p->operationrate = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_OPERATION_RATE;
-		break;
-	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-		mtk_v4l2_debug(2,
-			"V4L2_CID_MPEG_VIDEO_BITRATE_MODE: %d",
-			ctrl->val);
-		p->bitratemode = ctrl->val;
-		ctx->param_change |= MTK_ENCODE_PARAM_BITRATE_MODE;
-		break;
 	default:
-		mtk_v4l2_err("ctrl-id=%d not support!", ctrl->id);
+		ret = -EINVAL;
 		break;
 	}
 
@@ -383,11 +166,10 @@
 
 static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
 {
-	const struct mtk_video_fmt *fmt;
+	struct mtk_video_fmt *fmt;
 	int i, j = 0;
 
-	for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT &&
-	     mtk_video_formats[i].fourcc != 0; ++i) {
+	for (i = 0; i < NUM_FORMATS; ++i) {
 		if (output_queue && mtk_video_formats[i].type != MTK_FMT_FRAME)
 			continue;
 		if (!output_queue && mtk_video_formats[i].type != MTK_FMT_ENC)
@@ -409,22 +191,16 @@
 				  struct v4l2_frmsizeenum *fsize)
 {
 	int i = 0;
-	struct mtk_vcodec_ctx *ctx = fh_to_ctx(fh);
 
 	if (fsize->index != 0)
 		return -EINVAL;
 
-	get_supported_framesizes(ctx);
-
-	for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT &&
-	     mtk_venc_framesizes[i].fourcc != 0; ++i) {
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
 		if (fsize->pixel_format != mtk_venc_framesizes[i].fourcc)
 			continue;
 
 		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 		fsize->stepwise = mtk_venc_framesizes[i].stepwise;
-		fsize->reserved[0] = mtk_venc_framesizes[i].profile;
-		fsize->reserved[1] = mtk_venc_framesizes[i].level;
 		return 0;
 	}
 
@@ -446,11 +222,9 @@
 static int vidioc_venc_querycap(struct file *file, void *priv,
 				struct v4l2_capability *cap)
 {
-	strscpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver));
-	strscpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
-	strscpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
-	cap->device_caps  = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	strlcpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
 
 	return 0;
 }
@@ -462,6 +236,7 @@
 
 	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 		return -EINVAL;
+
 	ctx->enc_params.framerate_num =
 			a->parm.output.timeperframe.denominator;
 	ctx->enc_params.framerate_denom =
@@ -480,6 +255,7 @@
 
 	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 		return -EINVAL;
+
 	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
 	a->parm.output.timeperframe.denominator =
 			ctx->enc_params.framerate_num;
@@ -498,17 +274,27 @@
 	return &ctx->q_data[MTK_Q_DATA_DST];
 }
 
+static struct mtk_video_fmt *mtk_venc_find_format(struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &mtk_video_formats[k];
+		if (fmt->fourcc == f->fmt.pix.pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
 /* V4L2 specification suggests the driver corrects the format struct if any of
  * the dimensions is unsupported
  */
-static int vidioc_try_fmt(struct v4l2_format *f,
-			const struct mtk_video_fmt *fmt,
-			struct mtk_vcodec_ctx *ctx)
+static int vidioc_try_fmt(struct v4l2_format *f, struct mtk_video_fmt *fmt)
 {
 	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-	int org_w, org_h, i;
-	__u32 bs_fourcc;
-	struct mtk_codec_framesizes *spec_size_info = NULL;
+	int i;
 
 	pix_fmt_mp->field = V4L2_FIELD_NONE;
 
@@ -516,160 +302,73 @@
 		pix_fmt_mp->num_planes = 1;
 		pix_fmt_mp->plane_fmt[0].bytesperline = 0;
 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		get_supported_framesizes(ctx);
-		if (ctx->q_data[MTK_Q_DATA_DST].fmt != NULL) {
-			bs_fourcc =
-				ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc;
-		} else {
-			bs_fourcc =
-				mtk_video_formats[default_cap_fmt_idx].fourcc;
-		}
-		for (i = 0; i < MTK_MAX_ENC_CODECS_SUPPORT; i++) {
-			if (mtk_venc_framesizes[i].fourcc == bs_fourcc)
-				spec_size_info = &mtk_venc_framesizes[i];
-		}
-		if (!spec_size_info) {
-			mtk_v4l2_err("fail to get spec_size_info");
-			return -EINVAL;
-		}
+		int tmp_w, tmp_h;
 
-		mtk_v4l2_debug(1,
-			       "pix_fmt_mp->pixelformat %d bs fmt %d min_w %d min_h %d max_w %d max_h %d\n",
-			       pix_fmt_mp->pixelformat, bs_fourcc,
-			       spec_size_info->stepwise.min_width,
-			       spec_size_info->stepwise.min_height,
-			       spec_size_info->stepwise.max_width,
-			       spec_size_info->stepwise.max_height);
+		pix_fmt_mp->height = clamp(pix_fmt_mp->height,
+					MTK_VENC_MIN_H,
+					MTK_VENC_MAX_H);
+		pix_fmt_mp->width = clamp(pix_fmt_mp->width,
+					MTK_VENC_MIN_W,
+					MTK_VENC_MAX_W);
 
-		if ((spec_size_info->stepwise.step_width &
-		     (spec_size_info->stepwise.step_width - 1)) != 0)
-			mtk_v4l2_err("Unsupport stepwise.step_width not 2^ %d\n",
-				     spec_size_info->stepwise.step_width);
-		if ((spec_size_info->stepwise.step_height &
-		     (spec_size_info->stepwise.step_height - 1)) != 0)
-			mtk_v4l2_err("Unsupport stepwise.step_height not 2^ %d\n",
-				     spec_size_info->stepwise.step_height);
-
-
-		/* find next closer width align 16, height align 16, size align
-		 * 64 rectangle without MBAFF encoder
-		 * (with MBAFF height align should be 32)
-		 * width height swappable
+		/* find next closer width align 16, heign align 32, size align
+		 * 64 rectangle
 		 */
-		if (pix_fmt_mp->height > pix_fmt_mp->width) {
-			pix_fmt_mp->height = clamp(pix_fmt_mp->height,
-				(spec_size_info->stepwise.min_height),
-				(spec_size_info->stepwise.max_width));
-			pix_fmt_mp->width = clamp(pix_fmt_mp->width,
-				(spec_size_info->stepwise.min_width),
-				(spec_size_info->stepwise.max_height));
-			org_w = pix_fmt_mp->width;
-			org_h = pix_fmt_mp->height;
-			v4l_bound_align_image(&pix_fmt_mp->width,
-				spec_size_info->stepwise.min_width,
-				spec_size_info->stepwise.max_height,
-				ilog2(spec_size_info->stepwise.step_width),
-				&pix_fmt_mp->height,
-				spec_size_info->stepwise.min_height,
-				spec_size_info->stepwise.max_width,
-				ilog2(spec_size_info->stepwise.step_height),
-				6);
+		tmp_w = pix_fmt_mp->width;
+		tmp_h = pix_fmt_mp->height;
+		v4l_bound_align_image(&pix_fmt_mp->width,
+					MTK_VENC_MIN_W,
+					MTK_VENC_MAX_W, 4,
+					&pix_fmt_mp->height,
+					MTK_VENC_MIN_H,
+					MTK_VENC_MAX_H, 5, 6);
 
-			if (pix_fmt_mp->width < org_w &&
-			    (pix_fmt_mp->width +
-			     spec_size_info->stepwise.step_width) <=
-			    spec_size_info->stepwise.max_height)
-				pix_fmt_mp->width +=
-					spec_size_info->stepwise.step_width;
-			if (pix_fmt_mp->height < org_h &&
-			    (pix_fmt_mp->height +
-			     spec_size_info->stepwise.step_height) <=
-			    spec_size_info->stepwise.max_width)
-				pix_fmt_mp->height +=
-					spec_size_info->stepwise.step_height;
-		} else {
-			pix_fmt_mp->height = clamp(pix_fmt_mp->height,
-				(spec_size_info->stepwise.min_height),
-				(spec_size_info->stepwise.max_height));
-			pix_fmt_mp->width = clamp(pix_fmt_mp->width,
-				(spec_size_info->stepwise.min_width),
-				(spec_size_info->stepwise.max_width));
-			org_w = pix_fmt_mp->width;
-			org_h = pix_fmt_mp->height;
-			v4l_bound_align_image(&pix_fmt_mp->width,
-				spec_size_info->stepwise.min_width,
-				spec_size_info->stepwise.max_width,
-				ilog2(spec_size_info->stepwise.step_width),
-				&pix_fmt_mp->height,
-				spec_size_info->stepwise.min_height,
-				spec_size_info->stepwise.max_height,
-				ilog2(spec_size_info->stepwise.step_height),
-				6);
-
-			if (pix_fmt_mp->width < org_w &&
-			    (pix_fmt_mp->width +
-			     spec_size_info->stepwise.step_width) <=
-			    spec_size_info->stepwise.max_width)
-				pix_fmt_mp->width +=
-					spec_size_info->stepwise.step_width;
-			if (pix_fmt_mp->height < org_h &&
-			    (pix_fmt_mp->height +
-			     spec_size_info->stepwise.step_height) <=
-			    spec_size_info->stepwise.max_height)
-				pix_fmt_mp->height +=
-					spec_size_info->stepwise.step_height;
-		}
-
-		pix_fmt_mp->num_planes = fmt->num_planes;
-
-		if (pix_fmt_mp->num_planes == 1U) {
-			pix_fmt_mp->plane_fmt[0].sizeimage =
-				(pix_fmt_mp->width * pix_fmt_mp->height) +
-				(pix_fmt_mp->width * pix_fmt_mp->height) / 2;
-			pix_fmt_mp->plane_fmt[0].bytesperline =
-				pix_fmt_mp->width;
-		} else if (pix_fmt_mp->num_planes == 2U) {
-			pix_fmt_mp->plane_fmt[0].sizeimage =
-				pix_fmt_mp->width * pix_fmt_mp->height;
-			pix_fmt_mp->plane_fmt[0].bytesperline =
-				pix_fmt_mp->width;
-			pix_fmt_mp->plane_fmt[1].sizeimage =
-				(pix_fmt_mp->width * pix_fmt_mp->height) / 2;
-			pix_fmt_mp->plane_fmt[1].bytesperline =
-				pix_fmt_mp->width;
-		} else if (pix_fmt_mp->num_planes == 3U) {
-			pix_fmt_mp->plane_fmt[0].sizeimage =
-				pix_fmt_mp->width * pix_fmt_mp->height;
-			pix_fmt_mp->plane_fmt[0].bytesperline =
-				pix_fmt_mp->width;
-			pix_fmt_mp->plane_fmt[1].sizeimage =
-				(pix_fmt_mp->width * pix_fmt_mp->height) / 4;
-			pix_fmt_mp->plane_fmt[1].bytesperline =
-				pix_fmt_mp->width / 2;
-			pix_fmt_mp->plane_fmt[2].sizeimage =
-				(pix_fmt_mp->width * pix_fmt_mp->height) / 4;
-			pix_fmt_mp->plane_fmt[2].bytesperline =
-				pix_fmt_mp->width / 2;
-		} else
-			mtk_v4l2_err("Unsupport num planes = %d\n",
-				     pix_fmt_mp->num_planes);
+		if (pix_fmt_mp->width < tmp_w &&
+			(pix_fmt_mp->width + 16) <= MTK_VENC_MAX_W)
+			pix_fmt_mp->width += 16;
+		if (pix_fmt_mp->height < tmp_h &&
+			(pix_fmt_mp->height + 32) <= MTK_VENC_MAX_H)
+			pix_fmt_mp->height += 32;
 
 		mtk_v4l2_debug(0,
-			       "w/h (%d, %d) -> (%d,%d), sizeimage[%d,%d,%d]",
-			       org_w, org_h,
-			       pix_fmt_mp->width, pix_fmt_mp->height,
-			       pix_fmt_mp->plane_fmt[0].sizeimage,
-			       pix_fmt_mp->plane_fmt[1].sizeimage,
-			       pix_fmt_mp->plane_fmt[2].sizeimage);
+			"before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d %d",
+			tmp_w, tmp_h, pix_fmt_mp->width,
+			pix_fmt_mp->height,
+			pix_fmt_mp->plane_fmt[0].sizeimage,
+			pix_fmt_mp->plane_fmt[1].sizeimage);
+
+		pix_fmt_mp->num_planes = fmt->num_planes;
+		pix_fmt_mp->plane_fmt[0].sizeimage =
+				pix_fmt_mp->width * pix_fmt_mp->height +
+				((ALIGN(pix_fmt_mp->width, 16) * 2) * 16);
+		pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width;
+
+		if (pix_fmt_mp->num_planes == 2) {
+			pix_fmt_mp->plane_fmt[1].sizeimage =
+				(pix_fmt_mp->width * pix_fmt_mp->height) / 2 +
+				(ALIGN(pix_fmt_mp->width, 16) * 16);
+			pix_fmt_mp->plane_fmt[2].sizeimage = 0;
+			pix_fmt_mp->plane_fmt[1].bytesperline =
+							pix_fmt_mp->width;
+			pix_fmt_mp->plane_fmt[2].bytesperline = 0;
+		} else if (pix_fmt_mp->num_planes == 3) {
+			pix_fmt_mp->plane_fmt[1].sizeimage =
+			pix_fmt_mp->plane_fmt[2].sizeimage =
+				(pix_fmt_mp->width * pix_fmt_mp->height) / 4 +
+				((ALIGN(pix_fmt_mp->width, 16) / 2) * 16);
+			pix_fmt_mp->plane_fmt[1].bytesperline =
+				pix_fmt_mp->plane_fmt[2].bytesperline =
+				pix_fmt_mp->width / 2;
+		}
 	}
 
 	for (i = 0; i < pix_fmt_mp->num_planes; i++)
 		memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0,
-		       sizeof(pix_fmt_mp->plane_fmt[0].reserved));
+			   sizeof(pix_fmt_mp->plane_fmt[0].reserved));
 
 	pix_fmt_mp->flags = 0;
 	memset(&pix_fmt_mp->reserved, 0x0,
-	       sizeof(pix_fmt_mp->reserved));
+		sizeof(pix_fmt_mp->reserved));
 
 	return 0;
 }
@@ -682,45 +381,23 @@
 
 	switch (q_data_src->fmt->fourcc) {
 	case V4L2_PIX_FMT_YUV420M:
-	case V4L2_PIX_FMT_YUV420:
 		param->input_yuv_fmt = VENC_YUV_FORMAT_I420;
 		break;
 	case V4L2_PIX_FMT_YVU420M:
-	case V4L2_PIX_FMT_YVU420:
 		param->input_yuv_fmt = VENC_YUV_FORMAT_YV12;
 		break;
 	case V4L2_PIX_FMT_NV12M:
-	case V4L2_PIX_FMT_NV12:
 		param->input_yuv_fmt = VENC_YUV_FORMAT_NV12;
 		break;
 	case V4L2_PIX_FMT_NV21M:
-	case V4L2_PIX_FMT_NV21:
 		param->input_yuv_fmt = VENC_YUV_FORMAT_NV21;
 		break;
-	case V4L2_PIX_FMT_RGB24:
-		param->input_yuv_fmt = VENC_YUV_FORMAT_24bitRGB888;
-		break;
-	case V4L2_PIX_FMT_BGR24:
-		param->input_yuv_fmt = VENC_YUV_FORMAT_24bitBGR888;
-		break;
-	case V4L2_PIX_FMT_ARGB32:
-		param->input_yuv_fmt = VENC_YUV_FORMAT_32bitRGBA8888;
-		break;
-	case V4L2_PIX_FMT_ABGR32:
-		param->input_yuv_fmt = VENC_YUV_FORMAT_32bitBGRA8888;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-		param->input_yuv_fmt = VENC_YUV_FORMAT_32bitARGB8888;
-		break;
-	case V4L2_PIX_FMT_RGB32:
-		param->input_yuv_fmt = VENC_YUV_FORMAT_32bitABGR8888;
-		break;
 	default:
 		mtk_v4l2_err("Unsupport fourcc =%d", q_data_src->fmt->fourcc);
 		break;
 	}
-	param->profile = enc_params->profile;
-	param->level = enc_params->level;
+	param->h264_profile = enc_params->h264_profile;
+	param->h264_level = enc_params->h264_level;
 
 	/* Config visible resolution */
 	param->width = q_data_src->visible_width;
@@ -733,21 +410,14 @@
 	param->intra_period = enc_params->intra_period;
 	param->gop_size = enc_params->gop_size;
 	param->bitrate = enc_params->bitrate;
-	param->operationrate = enc_params->operationrate;
-	param->scenario = enc_params->scenario;
-	param->prependheader = enc_params->prependheader;
-	param->bitratemode = enc_params->bitratemode;
-
-	ctx->slowmotion = (enc_params->operationrate >= MTK_SLOWMOTION_GCE_TH);
 
 	mtk_v4l2_debug(0,
-	"fmt 0x%x, P/L %d/%d, w/h %d/%d, buf %d/%d, fps/bps %d/%d(%d), gop %d, i_period %d opr %d smvr %d",
-	param->input_yuv_fmt, param->profile,
-	param->level, param->width, param->height,
-	param->buf_width, param->buf_height,
-	param->frm_rate, param->bitrate, param->bitratemode,
-	param->gop_size, param->intra_period,
-	param->operationrate, ctx->slowmotion);
+		"fmt 0x%x, P/L %d/%d, w/h %d/%d, buf %d/%d, fps/bps %d/%d, gop %d, i_period %d",
+		param->input_yuv_fmt, param->h264_profile,
+		param->h264_level, param->width, param->height,
+		param->buf_width, param->buf_height,
+		param->frm_rate, param->bitrate,
+		param->gop_size, param->intra_period);
 }
 
 static int vidioc_venc_s_fmt_cap(struct file *file, void *priv,
@@ -759,7 +429,6 @@
 	int i, ret;
 	struct mtk_video_fmt *fmt;
 
-	mtk_v4l2_debug(4, "[%d] type %d", ctx->id, f->type);
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 	if (!vq) {
 		mtk_v4l2_err("fail to get vq");
@@ -777,15 +446,14 @@
 		return -EINVAL;
 	}
 
-	fmt = mtk_venc_find_format(f, MTK_FMT_ENC);
+	fmt = mtk_venc_find_format(f);
 	if (!fmt) {
-		f->fmt.pix.pixelformat =
-			mtk_video_formats[default_cap_fmt_idx].fourcc;
-		fmt = mtk_venc_find_format(f, MTK_FMT_ENC);
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
 	}
 
 	q_data->fmt = fmt;
-	ret = vidioc_try_fmt(f, q_data->fmt, ctx);
+	ret = vidioc_try_fmt(f, q_data->fmt);
 	if (ret)
 		return ret;
 
@@ -822,6 +490,7 @@
 	struct mtk_q_data *q_data;
 	int ret, i;
 	struct mtk_video_fmt *fmt;
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
 
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 	if (!vq) {
@@ -840,17 +509,23 @@
 		return -EINVAL;
 	}
 
-	fmt = mtk_venc_find_format(f, MTK_FMT_FRAME);
+	fmt = mtk_venc_find_format(f);
 	if (!fmt) {
-		f->fmt.pix.pixelformat =
-			mtk_video_formats[default_out_fmt_idx].fourcc;
-		fmt = mtk_venc_find_format(f, MTK_FMT_FRAME);
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
 	}
 
+	pix_fmt_mp->height = clamp(pix_fmt_mp->height,
+				MTK_VENC_MIN_H,
+				MTK_VENC_MAX_H);
+	pix_fmt_mp->width = clamp(pix_fmt_mp->width,
+				MTK_VENC_MIN_W,
+				MTK_VENC_MAX_W);
+
 	q_data->visible_width = f->fmt.pix_mp.width;
 	q_data->visible_height = f->fmt.pix_mp.height;
 	q_data->fmt = fmt;
-	ret = vidioc_try_fmt(f, q_data->fmt, ctx);
+	ret = vidioc_try_fmt(f, q_data->fmt);
 	if (ret)
 		return ret;
 
@@ -916,31 +591,28 @@
 	struct mtk_video_fmt *fmt;
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
 
-	fmt = mtk_venc_find_format(f, MTK_FMT_ENC);
+	fmt = mtk_venc_find_format(f);
 	if (!fmt) {
-		f->fmt.pix.pixelformat =
-			mtk_video_formats[default_cap_fmt_idx].fourcc;
-		fmt = mtk_venc_find_format(f, MTK_FMT_ENC);
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
 	}
 	f->fmt.pix_mp.colorspace = ctx->colorspace;
 	f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
 	f->fmt.pix_mp.quantization = ctx->quantization;
 	f->fmt.pix_mp.xfer_func = ctx->xfer_func;
 
-	return vidioc_try_fmt(f, fmt, ctx);
+	return vidioc_try_fmt(f, fmt);
 }
 
 static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
 					 struct v4l2_format *f)
 {
 	struct mtk_video_fmt *fmt;
-	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
 
-	fmt = mtk_venc_find_format(f, MTK_FMT_FRAME);
+	fmt = mtk_venc_find_format(f);
 	if (!fmt) {
-		f->fmt.pix.pixelformat =
-			mtk_video_formats[default_out_fmt_idx].fourcc;
-		fmt = mtk_venc_find_format(f, MTK_FMT_FRAME);
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
 	}
 	if (!f->fmt.pix_mp.colorspace) {
 		f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
@@ -949,7 +621,7 @@
 		f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
 	}
 
-	return vidioc_try_fmt(f, fmt, ctx);
+	return vidioc_try_fmt(f, fmt);
 }
 
 static int vidioc_venc_g_selection(struct file *file, void *priv,
@@ -992,14 +664,12 @@
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
 	struct mtk_q_data *q_data;
 
-	if (!V4L2_TYPE_IS_OUTPUT(s->type))
+	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 		return -EINVAL;
 
 	q_data = mtk_venc_get_q_data(ctx, s->type);
-	if (!q_data) {
-		mtk_v4l2_err("[%d] q_data iS NULL\n", ctx->id);
+	if (!q_data)
 		return -EINVAL;
-	}
 
 	switch (s->target) {
 	case V4L2_SEL_TGT_CROP:
@@ -1012,7 +682,7 @@
 		q_data->visible_height = s->r.height;
 		break;
 	default:
-		mtk_v4l2_err("[Err] target is %X\n", s->target);
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -1021,58 +691,12 @@
 			    struct v4l2_buffer *buf)
 {
 	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
-	struct vb2_queue *vq;
-	struct vb2_buffer *vb;
-	struct mtk_video_enc_buf *mtkbuf;
-	struct vb2_v4l2_buffer *vb2_v4l2;
 
 	if (ctx->state == MTK_STATE_ABORT) {
 		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
-			     ctx->id);
+				ctx->id);
 		return -EIO;
 	}
-	// Check if need to proceed cache operations
-	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
-	vb = vq->bufs[buf->index];
-	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-	mtkbuf = container_of(vb2_v4l2, struct mtk_video_enc_buf, vb);
-
-	if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		if (buf->m.planes[0].bytesused == 0) {
-			mtkbuf->lastframe = EOS;
-			mtk_v4l2_debug(0, "[%d] index=%d Eos FB(%d,%d) vb=%p pts=%llu",
-				ctx->id, buf->index,
-				buf->bytesused,
-				buf->length, vb, vb->timestamp);
-		} else if (buf->flags & V4L2_BUF_FLAG_LAST) {
-			mtkbuf->lastframe = EOS_WITH_DATA;
-			mtk_v4l2_debug(0, "[%d] id=%d EarlyEos FB(%d,%d) vb=%p pts=%llu",
-				ctx->id, buf->index, buf->m.planes[0].bytesused,
-				buf->length, vb, vb->timestamp);
-		} else {
-			mtkbuf->lastframe = NON_EOS;
-			mtk_v4l2_debug(1, "[%d] id=%d getdata FB(%d,%d) vb=%p pts=%llu type:%d",
-				ctx->id, buf->index,
-				buf->m.planes[0].bytesused,
-				buf->length, mtkbuf, vb->timestamp,
-				buf->type);
-		}
-	} else
-		mtk_v4l2_debug(1, "[%d] index=%d type:%d BS (%d) vb=%p",
-				ctx->id, buf->index, buf->type,
-				buf->length, mtkbuf);
-
-	if (buf->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN) {
-		mtk_v4l2_debug(4, "[%d] No need for Cache clean, buf->index:%d. mtkbuf:%p",
-		   ctx->id, buf->index, mtkbuf);
-		mtkbuf->flags |= NO_CAHCE_CLEAN;
-	}
-
-	if (buf->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE) {
-		mtk_v4l2_debug(4, "[%d] No need for Cache invalidate, buf->index:%d. mtkbuf:%p",
-		   ctx->id, buf->index, mtkbuf);
-		mtkbuf->flags |= NO_CAHCE_INVALIDATE;
-	}
 
 	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
 }
@@ -1091,39 +715,6 @@
 	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 }
 
-static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh,
-				     const struct v4l2_event_subscription *sub)
-{
-	switch (sub->type) {
-	case V4L2_EVENT_EOS:
-		return v4l2_event_subscribe(fh, sub, 2, NULL);
-	case V4L2_EVENT_MTK_VENC_ERROR:
-		return v4l2_event_subscribe(fh, sub, 0, NULL);
-	default:
-		return v4l2_ctrl_subscribe_event(fh, sub);
-	}
-
-}
-static void mtk_vdec_queue_stop_enc_event(struct mtk_vcodec_ctx *ctx)
-{
-	static const struct v4l2_event ev_eos = {
-		.type = V4L2_EVENT_EOS,
-	};
-
-	mtk_v4l2_debug(1, "[%d]", ctx->id);
-	v4l2_event_queue_fh(&ctx->fh, &ev_eos);
-}
-
-static void mtk_venc_queue_error_event(struct mtk_vcodec_ctx *ctx)
-{
-	static const struct v4l2_event ev_error = {
-		.type = V4L2_EVENT_MTK_VENC_ERROR,
-	};
-
-	mtk_v4l2_debug(1, "[%d]", ctx->id);
-	v4l2_event_queue_fh(&ctx->fh, &ev_error);
-}
-
 const struct v4l2_ioctl_ops mtk_venc_ioctl_ops = {
 	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
 	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
@@ -1141,7 +732,7 @@
 	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_mplane,
 	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
 	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
-	.vidioc_subscribe_event		= vidioc_vdec_subscribe_evt,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 
 	.vidioc_s_parm			= vidioc_venc_s_parm,
@@ -1192,8 +783,6 @@
 	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct mtk_q_data *q_data;
 	int i;
-	struct mtk_video_enc_buf *mtkbuf;
-	struct vb2_v4l2_buffer *vb2_v4l2;
 
 	q_data = mtk_venc_get_q_data(ctx, vb->vb2_queue->type);
 
@@ -1204,78 +793,10 @@
 				q_data->sizeimage[i]);
 			return -EINVAL;
 		}
-
-		// Check if need to proceed cache operations
-		vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-		mtkbuf = container_of(vb2_v4l2, struct mtk_video_enc_buf, vb);
-
-		if (!(mtkbuf->flags & NO_CAHCE_CLEAN)) {
-			struct mtk_vcodec_mem src_mem;
-			struct dma_buf_attachment *buf_att;
-			struct sg_table *sgt;
-
-			buf_att = dma_buf_attach(vb->planes[i].dbuf,
-				&ctx->dev->plat_dev->dev);
-			sgt = dma_buf_map_attachment(buf_att, DMA_TO_DEVICE);
-			dma_sync_sg_for_device(&ctx->dev->plat_dev->dev,
-				sgt->sgl,
-				sgt->orig_nents,
-				DMA_TO_DEVICE);
-			dma_buf_unmap_attachment(buf_att, sgt, DMA_TO_DEVICE);
-
-			src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, i);
-			src_mem.size = (size_t)(vb->planes[i].bytesused -
-				vb->planes[i].data_offset);
-			dma_buf_detach(vb->planes[i].dbuf, buf_att);
-
-			mtk_v4l2_debug(4, "[%d] Cache sync TD for %p sz=%d dev %p ",
-				ctx->id,
-				(void *)src_mem.dma_addr,
-				(unsigned int)src_mem.size,
-				&ctx->dev->plat_dev->dev);
-		}
 	}
 
 	return 0;
 }
-static void vb2ops_venc_buf_finish(struct vb2_buffer *vb)
-{
-	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct mtk_video_enc_buf *mtkbuf;
-	struct vb2_v4l2_buffer *vb2_v4l2;
-
-    // Check if need to proceed cache operations
-	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
-	mtkbuf = container_of(vb2_v4l2, struct mtk_video_enc_buf, vb);
-
-	if (!(mtkbuf->flags & NO_CAHCE_INVALIDATE)) {
-		if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-			struct mtk_vcodec_mem dst_mem;
-
-			struct dma_buf_attachment *buf_att;
-			struct sg_table *sgt;
-
-			buf_att = dma_buf_attach(vb->planes[0].dbuf,
-				&ctx->dev->plat_dev->dev);
-			sgt = dma_buf_map_attachment(buf_att, DMA_FROM_DEVICE);
-			dma_sync_sg_for_cpu(&ctx->dev->plat_dev->dev, sgt->sgl,
-				sgt->orig_nents, DMA_FROM_DEVICE);
-			dma_buf_unmap_attachment(buf_att, sgt, DMA_FROM_DEVICE);
-
-			dst_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-			dst_mem.size = (size_t)vb->planes[0].bytesused;
-			dma_buf_detach(vb->planes[0].dbuf, buf_att);
-
-			mtk_v4l2_debug(4,
-				"[%d] Cache sync FD for %p sz=%d dev %p",
-				ctx->id,
-				(void *)dst_mem.dma_addr,
-				(unsigned int)dst_mem.size,
-				&ctx->dev->plat_dev->dev);
-		}
-	}
-}
-
 
 static void vb2ops_venc_buf_queue(struct vb2_buffer *vb)
 {
@@ -1307,7 +828,9 @@
 	int ret;
 	int i;
 
-	/* once state turn into MTK_STATE_ABORT clear it */
+	/* Once state turn into MTK_STATE_ABORT, we need stop_streaming
+	  * to clear it
+	  */
 	if ((ctx->state == MTK_STATE_ABORT) || (ctx->state == MTK_STATE_FREE)) {
 		ret = -EIO;
 		goto err_set_param;
@@ -1331,9 +854,7 @@
 	}
 	ctx->param_change = MTK_ENCODE_PARAM_NONE;
 
-	if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264 ||
-	     ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H265 ||
-	     ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_MPEG4) &&
+	if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264) &&
 	    (ctx->enc_params.seq_hdr_mode !=
 				V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)) {
 		ret = venc_if_set_param(ctx,
@@ -1366,19 +887,21 @@
 static void vb2ops_venc_stop_streaming(struct vb2_queue *q)
 {
 	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct vb2_buffer *src_buf, *dst_buf;
 	int ret;
 
 	mtk_v4l2_debug(2, "[%d]-> type=%d", ctx->id, q->type);
 
 	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
-			dst_buf->vb2_buf.planes[0].bytesused = 0;
-			v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+			dst_buf->planes[0].bytesused = 0;
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+					VB2_BUF_STATE_ERROR);
 		}
 	} else {
 		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
-			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+					VB2_BUF_STATE_ERROR);
 	}
 
 	if ((q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
@@ -1406,7 +929,6 @@
 	.buf_queue		= vb2ops_venc_buf_queue,
 	.wait_prepare		= vb2_ops_wait_prepare,
 	.wait_finish		= vb2_ops_wait_finish,
-	.buf_finish             = vb2ops_venc_buf_finish,
 	.start_streaming	= vb2ops_venc_start_streaming,
 	.stop_streaming		= vb2ops_venc_stop_streaming,
 };
@@ -1415,7 +937,8 @@
 {
 	struct mtk_vcodec_ctx *ctx = priv;
 	int ret;
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
 	struct mtk_vcodec_mem bs_buf;
 	struct venc_done_result enc_result;
 
@@ -1425,15 +948,14 @@
 		return -EINVAL;
 	}
 
-	bs_buf.va = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
-	bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-	bs_buf.size = (size_t)dst_buf->vb2_buf.planes[0].length;
-	bs_buf.dmabuf = dst_buf->planes[0].dbuf;
+	bs_buf.va = vb2_plane_vaddr(dst_buf, 0);
+	bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	bs_buf.size = (size_t)dst_buf->planes[0].length;
 
 	mtk_v4l2_debug(1,
 			"[%d] buf id=%d va=0x%p dma_addr=0x%llx size=%zu",
 			ctx->id,
-			dst_buf->vb2_buf.index, bs_buf.va,
+			dst_buf->index, bs_buf.va,
 			(u64)bs_buf.dma_addr,
 			bs_buf.size);
 
@@ -1441,27 +963,27 @@
 			VENC_START_OPT_ENCODE_SEQUENCE_HEADER,
 			NULL, &bs_buf, &enc_result);
 
-	get_free_buffers(ctx, &enc_result);
-
-	if (enc_result.bs_va == 0) {
-		dst_buf->vb2_buf.planes[0].bytesused = 0;
+	if (ret) {
+		dst_buf->planes[0].bytesused = 0;
 		ctx->state = MTK_STATE_ABORT;
-		mtk_venc_queue_error_event(ctx);
-		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
-		mtk_v4l2_err("failed=%d", ret);
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				  VB2_BUF_STATE_ERROR);
+		mtk_v4l2_err("venc_if_encode failed=%d", ret);
 		return -EINVAL;
 	}
 	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 	if (src_buf) {
-		dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
-		dst_buf->timecode = src_buf->timecode;
+		src_vb2_v4l2 = to_vb2_v4l2_buffer(src_buf);
+		dst_vb2_v4l2 = to_vb2_v4l2_buffer(dst_buf);
+		dst_buf->timestamp = src_buf->timestamp;
+		dst_vb2_v4l2->timecode = src_vb2_v4l2->timecode;
 	} else {
 		mtk_v4l2_err("No timestamp for the header buffer.");
 	}
 
 	ctx->state = MTK_STATE_HEADER;
-	dst_buf->vb2_buf.planes[0].bytesused = enc_result.bs_size;
-	v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+	dst_buf->planes[0].bytesused = enc_result.bs_size;
+	v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf), VB2_BUF_STATE_DONE);
 
 	return 0;
 }
@@ -1469,7 +991,9 @@
 static int mtk_venc_param_change(struct mtk_vcodec_ctx *ctx)
 {
 	struct venc_enc_param enc_prm;
-	struct vb2_v4l2_buffer *vb2_v4l2 = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	struct vb2_v4l2_buffer *vb2_v4l2 =
+			container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
 	struct mtk_video_enc_buf *mtk_buf =
 			container_of(vb2_v4l2, struct mtk_video_enc_buf, vb);
 
@@ -1519,91 +1043,6 @@
 						 NULL);
 	}
 
-	if (!ret && mtk_buf->param_change & MTK_ENCODE_PARAM_SCENARIO) {
-		enc_prm.scenario = mtk_buf->enc_params.scenario;
-		mtk_v4l2_debug(1, "[%d] idx=%d, change param scenario=%d",
-			       ctx->id,
-			       mtk_buf->vb.vb2_buf.index,
-			       mtk_buf->enc_params.scenario);
-		if (mtk_buf->enc_params.scenario)
-			ret |= venc_if_set_param(ctx,
-						 VENC_SET_PARAM_SCENARIO,
-						 &enc_prm);
-	}
-
-	if (!ret && mtk_buf->param_change & MTK_ENCODE_PARAM_NONREFP) {
-		enc_prm.nonrefp = mtk_buf->enc_params.nonrefp;
-		mtk_v4l2_debug(1, "[%d] idx=%d, change param nonref=%d",
-			       ctx->id,
-			       mtk_buf->vb.vb2_buf.index,
-			       mtk_buf->enc_params.nonrefp);
-		ret |= venc_if_set_param(ctx,
-					 VENC_SET_PARAM_NONREFP,
-					 &enc_prm);
-	}
-
-	if (!ret &&
-	mtk_buf->param_change & MTK_ENCODE_PARAM_DETECTED_FRAMERATE) {
-		enc_prm.detectframerate = mtk_buf->enc_params.detectframerate;
-		mtk_v4l2_debug(1, "[%d] idx=%d, change param detectfr=%d",
-				ctx->id,
-				mtk_buf->vb.vb2_buf.index,
-				mtk_buf->enc_params.detectframerate);
-		ret |= venc_if_set_param(ctx,
-					VENC_SET_PARAM_DETECTED_FRAMERATE,
-					&enc_prm);
-	}
-
-	if (!ret &&
-	mtk_buf->param_change & MTK_ENCODE_PARAM_RFS_ON) {
-		enc_prm.rfs = mtk_buf->enc_params.rfs;
-		mtk_v4l2_debug(1, "[%d] idx=%d, change param rfs=%d",
-				ctx->id,
-				mtk_buf->vb.vb2_buf.index,
-				mtk_buf->enc_params.rfs);
-		ret |= venc_if_set_param(ctx,
-					VENC_SET_PARAM_RFS_ON,
-					&enc_prm);
-	}
-
-	if (!ret &&
-	mtk_buf->param_change & MTK_ENCODE_PARAM_PREPEND_SPSPPS_TO_IDR) {
-		enc_prm.prependheader = mtk_buf->enc_params.prependheader;
-		mtk_v4l2_debug(1, "[%d] idx=%d, prepend spspps idr=%d",
-				ctx->id,
-				mtk_buf->vb.vb2_buf.index,
-				mtk_buf->enc_params.prependheader);
-		ret |= venc_if_set_param(ctx,
-					VENC_SET_PARAM_PREPEND_SPSPPS_TO_IDR,
-					&enc_prm);
-	}
-
-	if (!ret &&
-	mtk_buf->param_change & MTK_ENCODE_PARAM_OPERATION_RATE) {
-		enc_prm.operationrate = mtk_buf->enc_params.operationrate;
-		mtk_v4l2_debug(1, "[%d] idx=%d, operationrate=%d",
-				ctx->id,
-				mtk_buf->vb.vb2_buf.index,
-				mtk_buf->enc_params.operationrate);
-		ret |= venc_if_set_param(ctx,
-					VENC_SET_PARAM_OPERATION_RATE,
-					&enc_prm);
-		ctx->slowmotion =
-			(mtk_buf->enc_params.operationrate >=
-				MTK_SLOWMOTION_GCE_TH);
-	}
-
-	if (!ret &&
-	mtk_buf->param_change & MTK_ENCODE_PARAM_BITRATE_MODE) {
-		enc_prm.bitratemode = mtk_buf->enc_params.bitratemode;
-		mtk_v4l2_debug(1, "[%d] idx=%d, bitratemode=%d",
-				ctx->id,
-				mtk_buf->vb.vb2_buf.index,
-				mtk_buf->enc_params.bitratemode);
-		ret |= venc_if_set_param(ctx,
-					VENC_SET_PARAM_BITRATE_MODE,
-					&enc_prm);
-	}
 	mtk_buf->param_change = MTK_ENCODE_PARAM_NONE;
 
 	if (ret) {
@@ -1628,24 +1067,12 @@
 {
 	struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx,
 				    encode_work);
-	struct mtk_q_data *q_data_src = &ctx->q_data[MTK_Q_DATA_SRC];
 	struct vb2_buffer *src_buf, *dst_buf;
-	struct venc_frm_buf *pfrm_buf;
-	struct mtk_vcodec_mem *pbs_buf;
+	struct venc_frm_buf frm_buf;
+	struct mtk_vcodec_mem bs_buf;
 	struct venc_done_result enc_result;
-	int ret, i, length;
-	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2, *pend_src_vb2_v4l2;
-	struct mtk_video_enc_buf *dst_buf_info, *src_buf_info;
-	struct venc_inst *inst = NULL;
-
-	mutex_lock(&ctx->worker_lock);
-
-	if (ctx->state == MTK_STATE_ABORT) {
-		v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);
-		mtk_v4l2_debug(1, " %d", ctx->state);
-		mutex_unlock(&ctx->worker_lock);
-		return;
-	}
+	int ret, i;
+	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
 
 	/* check dst_buf, dst_buf may be removed in device_run
 	 * to stored encdoe header so we need check dst_buf and
@@ -1654,174 +1081,75 @@
 	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
 	if (!dst_buf) {
 		v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);
-		mutex_unlock(&ctx->worker_lock);
 		return;
 	}
 
 	src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	memset(&frm_buf, 0, sizeof(frm_buf));
+	for (i = 0; i < src_buf->num_planes ; i++) {
+		frm_buf.fb_addr[i].va = vb2_plane_vaddr(src_buf, i);
+		frm_buf.fb_addr[i].dma_addr =
+				vb2_dma_contig_plane_dma_addr(src_buf, i);
+		frm_buf.fb_addr[i].size =
+				(size_t)src_buf->planes[i].length;
+	}
+	bs_buf.va = vb2_plane_vaddr(dst_buf, 0);
+	bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	bs_buf.size = (size_t)dst_buf->planes[0].length;
+
+	mtk_v4l2_debug(2,
+			"Framebuf VA=%p PA=%llx Size=0x%zx;VA=%p PA=0x%llx Size=0x%zx;VA=%p PA=0x%llx Size=%zu",
+			frm_buf.fb_addr[0].va,
+			(u64)frm_buf.fb_addr[0].dma_addr,
+			frm_buf.fb_addr[0].size,
+			frm_buf.fb_addr[1].va,
+			(u64)frm_buf.fb_addr[1].dma_addr,
+			frm_buf.fb_addr[1].size,
+			frm_buf.fb_addr[2].va,
+			(u64)frm_buf.fb_addr[2].dma_addr,
+			frm_buf.fb_addr[2].size);
+
+	ret = venc_if_encode(ctx, VENC_START_OPT_ENCODE_FRAME,
+			     &frm_buf, &bs_buf, &enc_result);
+
 	src_vb2_v4l2 = to_vb2_v4l2_buffer(src_buf);
 	dst_vb2_v4l2 = to_vb2_v4l2_buffer(dst_buf);
 
-	src_buf_info = container_of(src_vb2_v4l2, struct mtk_video_enc_buf, vb);
-	dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_enc_buf, vb);
-	pbs_buf = &dst_buf_info->bs_buf;
-	pfrm_buf = &src_buf_info->frm_buf;
+	dst_buf->timestamp = src_buf->timestamp;
+	dst_vb2_v4l2->timecode = src_vb2_v4l2->timecode;
 
-	pbs_buf->va = vb2_plane_vaddr(dst_buf, 0);
-	pbs_buf->dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-	pbs_buf->size = (size_t)dst_buf->planes[0].length;
-	pbs_buf->dmabuf = dst_buf->planes[0].dbuf;
+	if (enc_result.is_key_frm)
+		dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_KEYFRAME;
 
-	if (src_buf_info->lastframe == EOS) {
-		if (ctx->oal_vcodec == 1) {
-			ret = venc_if_encode(ctx,
-					 VENC_START_OPT_ENCODE_FRAME_FINAL,
-					 NULL, pbs_buf, &enc_result);
-
-			pend_src_vb2_v4l2 =
-				to_vb2_v4l2_buffer(ctx->pend_src_buf);
-			dst_vb2_v4l2->flags |= pend_src_vb2_v4l2->flags;
-			dst_vb2_v4l2->vb2_buf.timestamp =
-				pend_src_vb2_v4l2->vb2_buf.timestamp;
-			dst_vb2_v4l2->timecode = pend_src_vb2_v4l2->timecode;
-			dst_vb2_v4l2->sequence = pend_src_vb2_v4l2->sequence;
-			dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST;
-			if (enc_result.is_key_frm)
-				dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_KEYFRAME;
-
-			if (ret) {
-				dst_buf->planes[0].bytesused = 0;
-				v4l2_m2m_buf_done(pend_src_vb2_v4l2,
-						VB2_BUF_STATE_ERROR);
-				v4l2_m2m_buf_done(dst_vb2_v4l2,
-						VB2_BUF_STATE_ERROR);
-				mtk_v4l2_err("last venc_if_encode failed=%d",
-									ret);
-				if (ret == -EIO)
-					ctx->state = MTK_STATE_ABORT;
-			} else {
-				dst_buf->planes[0].bytesused =
-							enc_result.bs_size;
-				v4l2_m2m_buf_done(pend_src_vb2_v4l2,
-							VB2_BUF_STATE_DONE);
-				v4l2_m2m_buf_done(dst_vb2_v4l2,
-							VB2_BUF_STATE_DONE);
-			}
-
-			ctx->pend_src_buf = NULL;
-		} else {
-			ret = venc_if_encode(ctx,
-					VENC_START_OPT_ENCODE_FRAME_FINAL,
-					NULL, pbs_buf, &enc_result);
-			dst_vb2_v4l2->vb2_buf.timestamp =
-				src_vb2_v4l2->vb2_buf.timestamp;
-			dst_vb2_v4l2->timecode = src_vb2_v4l2->timecode;
-			if (ret) {
-				mtk_v4l2_err("last venc_if_encode failed=%d",
-									ret);
-				v4l2_m2m_buf_done(dst_vb2_v4l2,
-							VB2_BUF_STATE_ERROR);
-				if (ret == -EIO)
-					ctx->state = MTK_STATE_ABORT;
-			} else {
-				if (ctx->drv_handle != 0) {
-					inst =
-					(struct venc_inst *)ctx->drv_handle;
-					mtk_v4l2_debug(0,
-						"enc final free cnt %d",
-						 inst->vsi->list_free.count);
-				}
-				return_free_buffers(ctx);
-			}
-		}
-		mtk_vdec_queue_stop_enc_event(ctx);
-		if (src_buf->planes[0].bytesused == 0U) {
-			src_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST;
-			vb2_set_plane_payload(&src_buf_info->vb.vb2_buf, 0, 0);
-			v4l2_m2m_buf_done(src_vb2_v4l2,
-				VB2_BUF_STATE_DONE);
-		}
-		v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);
-		mutex_unlock(&ctx->worker_lock);
-		return;
-	} else if (src_buf_info->lastframe == EOS_WITH_DATA) {
-		mtk_v4l2_debug(0, "[%d] EarlyEos: encode last frame %d",
-			ctx->id, src_buf->planes[0].bytesused);
-		src_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST;
-		dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST;
-		ctx->enc_flush_buf->lastframe = EOS;
-		v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->enc_flush_buf->vb);
-	}
-
-	memset(pfrm_buf, 0, sizeof(struct venc_frm_buf));
-	for (i = 0; i < src_buf->num_planes ; i++) {
-		pfrm_buf->fb_addr[i].va = vb2_plane_vaddr(src_buf, i) +
-			(size_t)src_buf->planes[i].data_offset;
-		pfrm_buf->fb_addr[i].dma_addr =
-			vb2_dma_contig_plane_dma_addr(src_buf, i) +
-			(size_t)src_buf->planes[i].data_offset;
-		pfrm_buf->fb_addr[i].size =
-				(size_t)(src_buf->planes[i].bytesused-
-				src_buf->planes[i].data_offset);
-		pfrm_buf->fb_addr[i].dmabuf =
-				src_buf->planes[i].dbuf;
-		pfrm_buf->fb_addr[i].data_offset =
-				src_buf->planes[i].data_offset;
-
-		mtk_v4l2_debug(2, "fb_addr[%d].va %p, offset %d, dma_addr %p, size %d\n",
-			i, pfrm_buf->fb_addr[i].va,
-			src_buf->planes[i].data_offset,
-			(void *)pfrm_buf->fb_addr[i].dma_addr,
-			(int)pfrm_buf->fb_addr[i].size);
-	}
-	pfrm_buf->num_planes = src_buf->num_planes;
-	pfrm_buf->timestamp = src_vb2_v4l2->vb2_buf.timestamp;
-	length = q_data_src->coded_width * q_data_src->coded_height;
-
-	mtk_v4l2_debug(2,
-			"Framebuf VA=%p PA=%llx Size=0x%zx Offset=%d;VA=%p PA=0x%llx Size=0x%zx Offset=%d;VA=%p PA=0x%llx Size=%zu Offset=%d",
-			pfrm_buf->fb_addr[0].va,
-			(u64)pfrm_buf->fb_addr[0].dma_addr,
-			pfrm_buf->fb_addr[0].size,
-			src_buf->planes[0].data_offset,
-			pfrm_buf->fb_addr[1].va,
-			(u64)pfrm_buf->fb_addr[1].dma_addr,
-			pfrm_buf->fb_addr[1].size,
-			src_buf->planes[1].data_offset,
-			pfrm_buf->fb_addr[2].va,
-			(u64)pfrm_buf->fb_addr[2].dma_addr,
-			pfrm_buf->fb_addr[2].size,
-			src_buf->planes[2].data_offset);
-
-	ret = venc_if_encode(ctx, VENC_START_OPT_ENCODE_FRAME,
-				 pfrm_buf, pbs_buf, &enc_result);
 	if (ret) {
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+				  VB2_BUF_STATE_ERROR);
 		dst_buf->planes[0].bytesused = 0;
-		v4l2_m2m_buf_done(src_vb2_v4l2, VB2_BUF_STATE_ERROR);
-		v4l2_m2m_buf_done(dst_vb2_v4l2, VB2_BUF_STATE_ERROR);
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				  VB2_BUF_STATE_ERROR);
 		mtk_v4l2_err("venc_if_encode failed=%d", ret);
-		if (ret == -EIO)
-			ctx->state = MTK_STATE_ABORT;
-	} else
-		return_free_buffers(ctx);
+	} else {
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+				  VB2_BUF_STATE_DONE);
+		dst_buf->planes[0].bytesused = enc_result.bs_size;
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				  VB2_BUF_STATE_DONE);
+		mtk_v4l2_debug(2, "venc_if_encode bs size=%d",
+				 enc_result.bs_size);
+	}
 
 	v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);
 
 	mtk_v4l2_debug(1, "<=== src_buf[%d] dst_buf[%d] venc_if_encode ret=%d Size=%u===>",
 			src_buf->index, dst_buf->index, ret,
 			enc_result.bs_size);
-	mutex_unlock(&ctx->worker_lock);
 }
 
 static void m2mops_venc_device_run(void *priv)
 {
 	struct mtk_vcodec_ctx *ctx = priv;
 
-	mtk_venc_param_change(ctx);
-	if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264 ||
-	     ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H265 ||
-	     ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_MPEG4 ||
-	     ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H263) &&
+	if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264) &&
 	    (ctx->state != MTK_STATE_HEADER)) {
 		/* encode h264 sps/pps header */
 		mtk_venc_encode_header(ctx);
@@ -1829,6 +1157,7 @@
 		return;
 	}
 
+	mtk_venc_param_change(ctx);
 	queue_work(ctx->dev->encode_workqueue, &ctx->encode_work);
 }
 
@@ -1872,7 +1201,6 @@
 	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
 	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
 
-	get_supported_format(ctx);
 	q_data = &ctx->q_data[MTK_Q_DATA_SRC];
 	memset(q_data, 0, sizeof(struct mtk_q_data));
 	q_data->visible_width = DFT_CFG_WIDTH;
@@ -1881,7 +1209,7 @@
 	q_data->coded_height = DFT_CFG_HEIGHT;
 	q_data->field = V4L2_FIELD_NONE;
 
-	q_data->fmt = &mtk_video_formats[default_out_fmt_idx];
+	q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
 
 	v4l_bound_align_image(&q_data->coded_width,
 				MTK_VENC_MIN_W,
@@ -1910,7 +1238,7 @@
 	memset(q_data, 0, sizeof(struct mtk_q_data));
 	q_data->coded_width = DFT_CFG_WIDTH;
 	q_data->coded_height = DFT_CFG_HEIGHT;
-	q_data->fmt = &mtk_video_formats[default_cap_fmt_idx];
+	q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
 	q_data->field = V4L2_FIELD_NONE;
 	ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
 		DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
@@ -1922,13 +1250,11 @@
 {
 	const struct v4l2_ctrl_ops *ops = &mtk_vcodec_enc_ctrl_ops;
 	struct v4l2_ctrl_handler *handler = &ctx->ctrl_hdl;
-	struct v4l2_ctrl_config cfg;
-	struct v4l2_ctrl *ctrl;
 
 	v4l2_ctrl_handler_init(handler, MTK_MAX_CTRLS_HINT);
 
 	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_BITRATE,
-			  1, 400000000, 1, 20000000);
+			1, 4000000, 1, 4000000);
 	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_B_FRAMES,
 			0, 2, 1, 0);
 	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
@@ -1949,78 +1275,10 @@
 			0, V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE);
 	v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
 			V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
-		0, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.id = V4L2_CID_MPEG_MTK_ENCODE_SCENARIO;
-	cfg.type = V4L2_CTRL_TYPE_INTEGER;
-	cfg.flags = V4L2_CTRL_FLAG_WRITE_ONLY;
-	cfg.name = "Video encode scenario";
-	cfg.min = 0;
-	cfg.max = 32;
-	cfg.step = 1;
-	cfg.def = 0;
-	cfg.ops = ops;
-	ctrl = v4l2_ctrl_new_custom(handler, &cfg, NULL);
-
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.id = V4L2_CID_MPEG_MTK_ENCODE_NONREFP;
-	cfg.type = V4L2_CTRL_TYPE_INTEGER;
-	cfg.flags = V4L2_CTRL_FLAG_WRITE_ONLY;
-	cfg.name = "Video encode nonrefp";
-	cfg.min = 0;
-	cfg.max = 32;
-	cfg.step = 1;
-	cfg.def = 0;
-	cfg.ops = ops;
-	ctrl = v4l2_ctrl_new_custom(handler, &cfg, NULL);
-
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.id = V4L2_CID_MPEG_MTK_ENCODE_DETECTED_FRAMERATE;
-	cfg.type = V4L2_CTRL_TYPE_INTEGER;
-	cfg.flags = V4L2_CTRL_FLAG_WRITE_ONLY;
-	cfg.name = "Video encode detect framerate";
-	cfg.min = 0;
-	cfg.max = 32;
-	cfg.step = 1;
-	cfg.def = 0;
-	cfg.ops = ops;
-	ctrl = v4l2_ctrl_new_custom(handler, &cfg, NULL);
-
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.id = V4L2_CID_MPEG_MTK_ENCODE_RFS_ON;
-	cfg.type = V4L2_CTRL_TYPE_INTEGER;
-	cfg.flags = V4L2_CTRL_FLAG_WRITE_ONLY;
-	cfg.name = "Video encode slice loss indication";
-	cfg.min = 0;
-	cfg.max = 1;
-	cfg.step = 1;
-	cfg.def = 0;
-	cfg.ops = ops;
-	ctrl = v4l2_ctrl_new_custom(handler, &cfg, NULL);
-
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.id = V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR;
-	cfg.type = V4L2_CTRL_TYPE_INTEGER;
-	cfg.flags = V4L2_CTRL_FLAG_WRITE_ONLY;
-	cfg.name = "Video encode slice loss indication";
-	cfg.min = 0;
-	cfg.max = 1;
-	cfg.step = 1;
-	cfg.def = 0;
-	cfg.ops = ops;
-	ctrl = v4l2_ctrl_new_custom(handler, &cfg, NULL);
-
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.id = V4L2_CID_MPEG_MTK_ENCODE_OPERATION_RATE;
-	cfg.type = V4L2_CTRL_TYPE_INTEGER;
-	cfg.flags = V4L2_CTRL_FLAG_WRITE_ONLY;
-	cfg.name = "Video encode operation rate";
-	cfg.min = 0;
-	cfg.max = 2048;
-	cfg.step = 1;
-	cfg.def = 0;
-	cfg.ops = ops;
-	ctrl = v4l2_ctrl_new_custom(handler, &cfg, NULL);
+			0, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
+	v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+			0, V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
 	if (handler->error) {
 		mtk_v4l2_err("Init control handler fail %d",
 				handler->error);
@@ -2051,7 +1309,6 @@
 	src_vq->mem_ops		= &vb2_dma_contig_memops;
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	src_vq->lock		= &ctx->dev->dev_mutex;
-	src_vq->allow_zero_bytesused = 1;
 	src_vq->dev		= &ctx->dev->plat_dev->dev;
 
 	ret = vb2_queue_init(src_vq);
@@ -2061,12 +1318,11 @@
 	dst_vq->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
 	dst_vq->drv_priv	= ctx;
-	dst_vq->buf_struct_size = sizeof(struct mtk_video_enc_buf);
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	dst_vq->ops		= &mtk_venc_vb2_ops;
 	dst_vq->mem_ops		= &vb2_dma_contig_memops;
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	dst_vq->lock		= &ctx->dev->dev_mutex;
-	dst_vq->allow_zero_bytesused = 1;
 	dst_vq->dev		= &ctx->dev->plat_dev->dev;
 
 	return vb2_queue_init(dst_vq);
@@ -2074,56 +1330,26 @@
 
 int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx)
 {
-	mtk_v4l2_debug(4, "ctx %p [%d]", ctx, ctx->id);
-	up(&ctx->dev->enc_sem);
+	struct mtk_vcodec_dev *dev = ctx->dev;
+
+	mutex_unlock(&dev->enc_mutex);
 	return 0;
 }
 
 int mtk_venc_lock(struct mtk_vcodec_ctx *ctx)
 {
-	unsigned int suspend_block_cnt = 0;
+	struct mtk_vcodec_dev *dev = ctx->dev;
 
-	while (ctx->dev->is_codec_suspending == 1) {
-		suspend_block_cnt++;
-		if (suspend_block_cnt > SUSPEND_TIMEOUT_CNT) {
-			mtk_v4l2_debug(4, "VENC blocked by suspend\n");
-			suspend_block_cnt = 0;
-		}
-		usleep_range(10000, 20000);
-	}
-
-	mtk_v4l2_debug(4, "ctx %p [%d]", ctx, ctx->id);
-	return down_interruptible(&ctx->dev->enc_sem);
+	mutex_lock(&dev->enc_mutex);
+	return 0;
 }
 
-void mtk_vcodec_enc_empty_queues(struct file *file, struct mtk_vcodec_ctx *ctx)
-{
-	struct vb2_buffer *src_buf = NULL, *dst_buf = NULL;
-	struct v4l2_fh *fh = file->private_data;
-
-	// error handle for release before stream-off
-	//  stream off both queue mannually.
-	v4l2_m2m_streamoff(file, fh->m2m_ctx,
-		V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
-	v4l2_m2m_streamoff(file, fh->m2m_ctx,
-		V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-
-	while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
-		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
-			VB2_BUF_STATE_ERROR);
-
-	while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
-		dst_buf->planes[0].bytesused = 0;
-		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
-			VB2_BUF_STATE_ERROR);
-	}
-
-	ctx->state = MTK_STATE_FREE;
-}
 void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx)
 {
 	int ret = venc_if_deinit(ctx);
 
 	if (ret)
 		mtk_v4l2_err("venc_if_deinit failed=%d", ret);
+
+	ctx->state = MTK_STATE_FREE;
 }
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
old mode 100644
new mode 100755
index 696c250..d7a154a
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
@@ -28,11 +28,6 @@
 
 #define MTK_VENC_IRQ_STATUS_OFFSET	0x05C
 #define MTK_VENC_IRQ_ACK_OFFSET	0x060
-enum eos_types {
-	NON_EOS = 0,
-	EOS_WITH_DATA,
-	EOS
-};
 
 /**
  * struct mtk_video_enc_buf - Private data related to each VB2 buffer.
@@ -47,10 +42,6 @@
 	struct list_head list;
 	u32 param_change;
 	struct mtk_enc_params enc_params;
-	enum eos_types lastframe;
-	int    flags;
-	struct mtk_vcodec_mem bs_buf;
-	struct venc_frm_buf frm_buf;
 };
 
 extern const struct v4l2_ioctl_ops mtk_venc_ioctl_ops;
@@ -60,7 +51,6 @@
 int mtk_venc_lock(struct mtk_vcodec_ctx *ctx);
 int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq,
 			      struct vb2_queue *dst_vq);
-void mtk_vcodec_enc_empty_queues(struct file *file, struct mtk_vcodec_ctx *ctx);
 void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx);
 int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx);
 void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx);
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
old mode 100644
new mode 100755
index 5b4e6a6..83f859e
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -23,22 +23,16 @@
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-dma-contig.h>
 #include <linux/pm_runtime.h>
-#include <linux/pm_wakeup.h>
-#include <linux/iommu.h>
-#include <linux/delay.h>
-#include <linux/suspend.h>
-#include <linux/semaphore.h>
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_enc.h"
 #include "mtk_vcodec_enc_pm.h"
 #include "mtk_vcodec_intr.h"
 #include "mtk_vcodec_util.h"
-#include "mtk_vcodec_fw.h"
+#include "mtk_vpu.h"
 
 module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR);
 module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR);
-struct mtk_vcodec_dev *venc_dev;
 
 /* Wake up context wait_queue */
 static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
@@ -81,9 +75,9 @@
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 
 	mtk_v4l2_debug(1, "id=%d", ctx->id);
-	addr = dev->enc_reg_base[VENC_SYS] + MTK_VENC_IRQ_ACK_OFFSET;
+	addr = dev->reg_base[VENC_SYS] + MTK_VENC_IRQ_ACK_OFFSET;
 
-	ctx->irq_status = readl(dev->enc_reg_base[VENC_SYS] +
+	ctx->irq_status = readl(dev->reg_base[VENC_SYS] +
 				(MTK_VENC_IRQ_STATUS_OFFSET));
 
 	clean_irq_status(ctx->irq_status, addr);
@@ -104,10 +98,10 @@
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 
 	mtk_v4l2_debug(1, "id=%d", ctx->id);
-	ctx->irq_status = readl(dev->enc_reg_base[VENC_LT_SYS] +
+	ctx->irq_status = readl(dev->reg_base[VENC_LT_SYS] +
 				(MTK_VENC_IRQ_STATUS_OFFSET));
 
-	addr = dev->enc_reg_base[VENC_LT_SYS] + MTK_VENC_IRQ_ACK_OFFSET;
+	addr = dev->reg_base[VENC_LT_SYS] + MTK_VENC_IRQ_ACK_OFFSET;
 
 	clean_irq_status(ctx->irq_status, addr);
 
@@ -115,29 +109,37 @@
 	return IRQ_HANDLED;
 }
 
+static void mtk_vcodec_enc_reset_handler(void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+
+	mtk_v4l2_debug(0, "Watchdog timeout!!");
+
+	mutex_lock(&dev->dev_mutex);
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
+				ctx->id);
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
 static int fops_vcodec_open(struct file *file)
 {
 	struct mtk_vcodec_dev *dev = video_drvdata(file);
 	struct mtk_vcodec_ctx *ctx = NULL;
-	struct mtk_video_enc_buf *mtk_buf = NULL;
-	struct vb2_queue *src_vq;
 	int ret = 0;
 
 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
-	mtk_buf = kzalloc(sizeof(*mtk_buf), GFP_KERNEL);
-	if (!mtk_buf) {
-		kfree(ctx);
-		return -ENOMEM;
-	}
 
 	mutex_lock(&dev->dev_mutex);
 	/*
 	 * Use simple counter to uniquely identify this context. Only
 	 * used for logging.
 	 */
-	ctx->enc_flush_buf = mtk_buf;
 	ctx->id = dev->id_counter++;
 	v4l2_fh_init(&ctx->fh, video_devdata(file));
 	file->private_data = &ctx->fh;
@@ -161,19 +163,14 @@
 				ret);
 		goto err_m2m_ctx_init;
 	}
-	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
-		V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
-	ctx->enc_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
-	ctx->enc_flush_buf->lastframe = EOS;
-	ctx->enc_flush_buf->vb.vb2_buf.planes[0].bytesused = 1;
 	mtk_vcodec_enc_set_default_params(ctx);
 
 	if (v4l2_fh_is_singular(&ctx->fh)) {
 		/*
-		 * load fireware to checks if it was loaded already and
+		 * vpu_load_firmware checks if it was loaded already and
 		 * does nothing in that case
 		 */
-		ret = mtk_vcodec_fw_load_firmware(dev->ipi_msg_handle);
+		ret = vpu_load_firmware(dev->vpu_plat_dev);
 		if (ret < 0) {
 			/*
 			 * Return 0 if downloading firmware successfully,
@@ -183,7 +180,8 @@
 			goto err_load_fw;
 		}
 
-		dev->dec_capability = mtk_vcodec_fw_get_venc_capa(dev->ipi_msg_handle);
+		dev->enc_capability =
+			vpu_get_venc_hw_capa(dev->vpu_plat_dev);
 		mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability);
 	}
 
@@ -205,7 +203,6 @@
 err_ctrls_setup:
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
-	kfree(ctx->enc_flush_buf);
 	kfree(ctx);
 	mutex_unlock(&dev->dev_mutex);
 
@@ -220,15 +217,13 @@
 	mtk_v4l2_debug(1, "[%d] encoder", ctx->id);
 	mutex_lock(&dev->dev_mutex);
 
-	mtk_vcodec_enc_empty_queues(file, ctx);
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 	mtk_vcodec_enc_release(ctx);
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 
 	list_del_init(&ctx->list);
-	kfree(ctx->enc_flush_buf);
 	kfree(ctx);
 	mutex_unlock(&dev->dev_mutex);
 	return 0;
@@ -243,62 +238,12 @@
 	.mmap		= v4l2_m2m_fop_mmap,
 };
 
-static int mtk_vcodec_enc_suspend(struct device *pDev)
-{
-	int val = 0;
-
-	val = down_trylock(&venc_dev->enc_sem);
-	if (val == 1) {
-		mtk_v4l2_err("fail due to videocodec activity");
-		return -EBUSY;
-	}
-	up(&venc_dev->enc_sem);
-	mtk_v4l2_debug(1, "done");
-	return 0;
-}
-static int mtk_vcodec_enc_resume(struct device *pDev)
-{
-	mtk_v4l2_debug(1, "done");
-	return 0;
-}
-static int mtk_vcodec_enc_suspend_notifier(struct notifier_block *nb,
-					unsigned long action, void *data)
-{
-	int wait_cnt = 0;
-	int val = 0;
-
-	mtk_v4l2_debug(1, "action = %ld", action);
-	switch (action) {
-	case PM_SUSPEND_PREPARE:
-		venc_dev->is_codec_suspending = 1;
-		do {
-			usleep_range(10000, 20000);
-			wait_cnt++;
-			if (wait_cnt > 5) {
-				mtk_v4l2_err("waiting fail");
-				return NOTIFY_DONE;
-			}
-			val = down_trylock(&venc_dev->enc_sem);
-		} while (val == 1);
-		up(&venc_dev->enc_sem);
-		return NOTIFY_OK;
-	case PM_POST_SUSPEND:
-		venc_dev->is_codec_suspending = 0;
-		return NOTIFY_OK;
-	default:
-		return NOTIFY_DONE;
-	}
-	return NOTIFY_DONE;
-}
 static int mtk_vcodec_probe(struct platform_device *pdev)
 {
 	struct mtk_vcodec_dev *dev;
 	struct video_device *vfd_enc;
 	struct resource *res;
-	phandle rproc_phandle;
-	enum mtk_vcodec_fw_type fw_type;
-	struct mtk_vcodec_pm *pm;
-	int i, ret;
+	int i, j, ret;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 	if (!dev)
@@ -307,70 +252,31 @@
 	INIT_LIST_HEAD(&dev->ctx_list);
 	dev->plat_dev = pdev;
 
-	dev->vdec_pdata = of_device_get_match_data(&pdev->dev);
-	if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vpu",
-				  &rproc_phandle)) {
-		fw_type = VPU;
-	} else if (!of_property_read_u32(pdev->dev.of_node, "mediatek,scp",
-				  &rproc_phandle)) {
-		fw_type = SCP;
-	} else if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vcu",
-				  &rproc_phandle)){
-		fw_type = VCU;
-	} else {
-		mtk_v4l2_err("Could not get vdec IPI device1");
+	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
+	if (dev->vpu_plat_dev == NULL) {
+		mtk_v4l2_err("[VPU] vpu device in not ready");
 		return -EPROBE_DEFER;
 	}
 
-	dev->ipi_msg_handle = mtk_vcodec_fw_select(dev, fw_type, rproc_phandle,
-						   VPU_RST_ENC);
-	if (dev->ipi_msg_handle == NULL)
-		return -EINVAL;
+	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_enc_reset_handler,
+				dev, VPU_RST_ENC);
 
-	dev->venc_pdata = of_device_get_match_data(&pdev->dev);
 	ret = mtk_vcodec_init_enc_pm(dev);
 	if (ret < 0) {
-		mtk_v4l2_err("Failed to get mt vcodec clock source!");
+		dev_err(&pdev->dev, "Failed to get mt vcodec clock source!");
 		return ret;
 	}
-	pm = &dev->pm;
-	pm->chip_node = of_find_compatible_node(NULL,
-		NULL, "mediatek,venc_gcon");
-	if (pm->chip_node) {
-		for (i = VENC_SYS; i < NUM_MAX_VENC_REG_BASE; i++) {
-			res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-			if (res == NULL) {
-				mtk_v4l2_err("get memory resource failed.");
-				ret = -ENXIO;
-				goto err_res;
-			}
-			dev->enc_reg_base[i] =
-				devm_ioremap_resource(&pdev->dev, res);
-			if (IS_ERR((__force void *)dev->enc_reg_base[i])) {
-				ret = PTR_ERR(
-					(__force void *)dev->enc_reg_base[i]);
-				goto err_res;
-			}
-			mtk_v4l2_debug(2, "reg[%d] base=0x%p",
-				i, dev->enc_reg_base[i]);
-		}
-	} else {
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (res == NULL) {
-			mtk_v4l2_err("get memory resource failed\n");
-			ret = -ENXIO;
+
+	for (i = VENC_SYS, j = 0; i < NUM_MAX_VCODEC_REG_BASE; i++, j++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, j);
+		dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR((__force void *)dev->reg_base[i])) {
+			ret = PTR_ERR((__force void *)dev->reg_base[i]);
 			goto err_res;
 		}
-		dev->enc_reg_base[VENC_SYS] =
-			devm_ioremap_resource(&pdev->dev, res);
-		if (IS_ERR((__force void *)dev->enc_reg_base[VENC_SYS])) {
-			ret = PTR_ERR(
-				(__force void *)dev->enc_reg_base[VENC_SYS]);
-			goto err_res;
-		}
-		mtk_v4l2_debug(2, "reg[%d] base=0x%p",
-			VENC_SYS, dev->enc_reg_base[VENC_SYS]);
+		mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[i]);
 	}
+
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "failed to get irq resource");
@@ -389,27 +295,23 @@
 		ret = -EINVAL;
 		goto err_res;
 	}
-	disable_irq(dev->enc_irq);
 
-	if (dev->venc_pdata->supports_vp8) {
-		dev->enc_lt_irq = platform_get_irq(pdev, 1);
-		ret = devm_request_irq(&pdev->dev,
-				       dev->enc_lt_irq,
-				       mtk_vcodec_enc_lt_irq_handler,
-				       0, pdev->name, dev);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Failed to install dev->enc_lt_irq %d (%d)",
-				dev->enc_lt_irq, ret);
-			ret = -EINVAL;
-			goto err_res;
-		}
-		disable_irq(dev->enc_lt_irq); /* VENC_LT */
+	dev->enc_lt_irq = platform_get_irq(pdev, 1);
+	ret = devm_request_irq(&pdev->dev,
+			       dev->enc_lt_irq, mtk_vcodec_enc_lt_irq_handler,
+			       0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Failed to install dev->enc_lt_irq %d (%d)",
+			dev->enc_lt_irq, ret);
+		ret = -EINVAL;
+		goto err_res;
 	}
 
+	disable_irq(dev->enc_irq);
+	disable_irq(dev->enc_lt_irq); /* VENC_LT */
+	mutex_init(&dev->enc_mutex);
 	mutex_init(&dev->dev_mutex);
-	sema_init(&dev->enc_sem, 1);
-	mutex_init(&dev->enc_dvfs_mutex);
 	spin_lock_init(&dev->irqlock);
 
 	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
@@ -471,9 +373,6 @@
 	mtk_v4l2_debug(0, "encoder registered as /dev/video%d",
 			vfd_enc->num);
 
-	pm_notifier(mtk_vcodec_enc_suspend_notifier, 0);
-	dev->is_codec_suspending = 0;
-	venc_dev = dev;
 	return 0;
 
 err_enc_reg:
@@ -489,26 +388,8 @@
 	return ret;
 }
 
-static const struct mtk_vcodec_enc_pdata mt8173_pdata = {
-	.supports_vp8 = true,
-};
-
-static const struct mtk_vcodec_enc_pdata mt8183_pdata = {
-	.uses_ext = true,
-};
-
-static const struct mtk_vcodec_enc_pdata mt6779_pdata = {
-	.uses_ext = false,
-};
-static const struct mtk_vcodec_enc_pdata mt2712_pdata = {
-	.uses_ext = false,
-};
-
 static const struct of_device_id mtk_vcodec_enc_match[] = {
-	{.compatible = "mediatek,mt8173-vcodec-enc", .data = &mt8173_pdata},
-	{.compatible = "mediatek,mt8183-vcodec-enc", .data = &mt8183_pdata},
-	{.compatible = "mediatek,mt2712-vcodec-enc", .data = &mt2712_pdata},
-	{.compatible = "mediatek,venc_gcon", .data = &mt6779_pdata},
+	{.compatible = "mediatek,mt8173-vcodec-enc",},
 	{},
 };
 MODULE_DEVICE_TABLE(of, mtk_vcodec_enc_match);
@@ -531,16 +412,11 @@
 	return 0;
 }
 
-static const struct dev_pm_ops mtk_vcodec_enc_pm_ops = {
-	.suspend = mtk_vcodec_enc_suspend,
-	.resume = mtk_vcodec_enc_resume,
-};
 static struct platform_driver mtk_vcodec_enc_driver = {
 	.probe	= mtk_vcodec_probe,
 	.remove	= mtk_vcodec_enc_remove,
 	.driver	= {
 		.name	= MTK_VCODEC_ENC_NAME,
-		.pm	= &mtk_vcodec_enc_pm_ops,
 		.of_match_table = mtk_vcodec_enc_match,
 	},
 };
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
old mode 100644
new mode 100755
index 6dbcfad..7c02504
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -1,33 +1,35 @@
 /*
- * Copyright (c) 2016 MediaTek Inc.
- * Author: Tiffany Lin <tiffany.lin@mediatek.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin@mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
 
 #include <linux/clk.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
 
 #include "mtk_vcodec_enc_pm.h"
 #include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
 
 int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
 {
+	struct device_node *node;
 	struct platform_device *pdev;
-	struct mtk_vcodec_pm *pm;
-	struct mtk_vcodec_clk *enc_clk;
-	struct mtk_vcodec_clk_info *clk_info;
-	int ret = 0, i = 0;
 	struct device *dev;
+	struct mtk_vcodec_pm *pm;
+	int ret = 0;
 
 	pdev = mtkdev->plat_dev;
 	pm = &mtkdev->pm;
@@ -35,84 +37,103 @@
 	pm->mtkdev = mtkdev;
 	pm->dev = &pdev->dev;
 	dev = &pdev->dev;
-	enc_clk = &pm->venc_clk;
+
+	node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
+	if (!node) {
+		mtk_v4l2_err("no mediatek,larb found");
+		return -ENODEV;
+	}
+	pdev = of_find_device_by_node(node);
+	of_node_put(node);
+	if (!pdev) {
+		mtk_v4l2_err("no mediatek,larb device found");
+		return -ENODEV;
+	}
+	pm->larbvenc = &pdev->dev;
+
+	node = of_parse_phandle(dev->of_node, "mediatek,larb", 1);
+	if (!node) {
+		mtk_v4l2_err("no mediatek,larb found");
+		return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(node);
+	of_node_put(node);
+	if (!pdev) {
+		mtk_v4l2_err("no mediatek,larb device found");
+		return -ENODEV;
+	}
+
+	pm->larbvenclt = &pdev->dev;
 	pdev = mtkdev->plat_dev;
 	pm->dev = &pdev->dev;
 
-	enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node,
-		"clock-names");
-	if (enc_clk->clk_num > 0) {
-		enc_clk->clk_info = devm_kcalloc(&pdev->dev,
-			enc_clk->clk_num, sizeof(*clk_info),
-			GFP_KERNEL);
-		if (!enc_clk->clk_info)
-			return -ENOMEM;
-	} else {
-		mtk_v4l2_err("Failed to get venc clock count");
-		return -EINVAL;
+	pm->vencpll_d2 = devm_clk_get(&pdev->dev, "venc_sel_src");
+	if (IS_ERR(pm->vencpll_d2)) {
+		mtk_v4l2_err("devm_clk_get vencpll_d2 fail");
+		ret = PTR_ERR(pm->vencpll_d2);
 	}
 
-	for (i = 0; i < enc_clk->clk_num; i++) {
-		clk_info = &enc_clk->clk_info[i];
-		ret = of_property_read_string_index(pdev->dev.of_node,
-			"clock-names", i, &clk_info->clk_name);
-		if (ret) {
-			mtk_v4l2_err("venc failed to get clk name %d", i);
-			return ret;
-		}
-		clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
-			clk_info->clk_name);
-		if (IS_ERR(clk_info->vcodec_clk)) {
-			mtk_v4l2_err("venc devm_clk_get (%d)%s fail", i,
-				clk_info->clk_name);
-			return PTR_ERR(clk_info->vcodec_clk);
-		}
+	pm->venc_sel = devm_clk_get(&pdev->dev, "venc_sel");
+	if (IS_ERR(pm->venc_sel)) {
+		mtk_v4l2_err("devm_clk_get venc_sel fail");
+		ret = PTR_ERR(pm->venc_sel);
 	}
 
-	pm_runtime_enable(&pdev->dev);
+	pm->univpll1_d2 = devm_clk_get(&pdev->dev, "venc_lt_sel_src");
+	if (IS_ERR(pm->univpll1_d2)) {
+		mtk_v4l2_err("devm_clk_get univpll1_d2 fail");
+		ret = PTR_ERR(pm->univpll1_d2);
+	}
+
+	pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
+	if (IS_ERR(pm->venc_lt_sel)) {
+		mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
+		ret = PTR_ERR(pm->venc_lt_sel);
+	}
+
 	return ret;
 }
 
-void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *dev)
+void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev)
 {
-	pm_runtime_disable(dev->pm.dev);
 }
 
 
 void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
 {
-	struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
-	int ret, i = 0;
+	int ret;
 
-	ret = pm_runtime_get_sync(pm->dev);
+	ret = clk_prepare_enable(pm->venc_sel);
 	if (ret)
-		mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
+		mtk_v4l2_err("clk_prepare_enable fail %d", ret);
 
-	for (i = 0; i < enc_clk->clk_num; i++) {
-		ret = clk_prepare_enable(enc_clk->clk_info[i].vcodec_clk);
-		if (ret) {
-			mtk_v4l2_err("venc clk_prepare_enable %d %s fail %d", i,
-				enc_clk->clk_info[i].clk_name, ret);
-			goto clkerr;
-		}
-	}
+	ret = clk_set_parent(pm->venc_sel, pm->vencpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent fail %d", ret);
 
-	return;
-clkerr:
-	for (i -= 1; i >= 0; i--)
-		clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
-	return;
+	ret = clk_prepare_enable(pm->venc_lt_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable fail %d", ret);
+
+	ret = clk_set_parent(pm->venc_lt_sel, pm->univpll1_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvenc);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvenclt);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larb4 fail %d", ret);
+
 }
 
 void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
 {
-	struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
-	int ret, i = 0;
-
-	ret = pm_runtime_put_sync(pm->dev);
-	if (ret)
-		mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
-
-	for (i = enc_clk->clk_num - 1; i >= 0; i--)
-		clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
+	mtk_smi_larb_put(pm->larbvenc);
+	mtk_smi_larb_put(pm->larbvenclt);
+	clk_disable_unprepare(pm->venc_lt_sel);
+	clk_disable_unprepare(pm->venc_sel);
 }
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
old mode 100644
new mode 100755
index 3d22167..0c28d0b
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -17,6 +17,7 @@
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
 
 /* For encoder, this will enable logs in venc/*/
 bool mtk_vcodec_dbg;
@@ -33,25 +34,13 @@
 {
 	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
 
-	if (!data || reg_idx >= NUM_MAX_VDEC_REG_BASE) {
+	if (!data || reg_idx >= NUM_MAX_VCODEC_REG_BASE) {
 		mtk_v4l2_err("Invalid arguments, reg_idx=%d", reg_idx);
 		return NULL;
 	}
 	return ctx->dev->reg_base[reg_idx];
 }
 EXPORT_SYMBOL(mtk_vcodec_get_reg_addr);
-void __iomem *mtk_vcodec_get_enc_reg_addr(struct mtk_vcodec_ctx *data,
-	unsigned int reg_idx)
-{
-	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
-
-	if (!data || reg_idx >= NUM_MAX_VENC_REG_BASE) {
-		mtk_v4l2_err("Invalid arguments, reg_idx=%d", reg_idx);
-		return NULL;
-	}
-	return ctx->dev->enc_reg_base[reg_idx];
-}
-EXPORT_SYMBOL(mtk_vcodec_get_enc_reg_addr);
 
 int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
 			struct mtk_vcodec_mem *mem)
@@ -61,12 +50,15 @@
 	struct device *dev = &ctx->dev->plat_dev->dev;
 
 	mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
+
 	if (!mem->va) {
 		mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev),
 			     size);
 		return -ENOMEM;
 	}
 
+	memset(mem->va, 0, size);
+
 	mtk_v4l2_debug(3, "[%d]  - va      = %p", ctx->id, mem->va);
 	mtk_v4l2_debug(3, "[%d]  - dma     = 0x%lx", ctx->id,
 		       (unsigned long)mem->dma_addr);
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
old mode 100644
new mode 100755
index 5e5b865..06c254f
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
@@ -20,32 +20,9 @@
 #include <linux/dma-direction.h>
 
 struct mtk_vcodec_mem {
-	size_t length;
 	size_t size;
-	size_t data_offset;
 	void *va;
 	dma_addr_t dma_addr;
-	struct dma_buf *dmabuf;
-	__u32 flags;
-	__u32 index;
-};
-
-struct mtk_vcodec_fb {
-	size_t size;
-	dma_addr_t dma_addr;
-};
-/**
- * enum flags  - decoder different operation types
- * @NO_CAHCE_FLUSH	: no need to proceed cache flush
- * @NO_CAHCE_INVALIDATE	: no need to proceed cache invalidate
- * @CROP_CHANGED	: frame buffer crop changed
- * @REF_FREED	: frame buffer is reference freed
- */
-enum mtk_vcodec_flags {
-	NO_CAHCE_CLEAN = 1,
-	NO_CAHCE_INVALIDATE = 1 << 1,
-	CROP_CHANGED = 1 << 2,
-	REF_FREED = 1 << 3
 };
 
 struct mtk_vcodec_ctx;
@@ -63,7 +40,7 @@
 	pr_err("[MTK_VCODEC][ERROR][%d]: %s() " fmt "\n",		\
 	       ((struct mtk_vcodec_ctx *)h->ctx)->id, __func__, ##args)
 
-#define DEBUG   1
+
 #if defined(DEBUG)
 
 #define mtk_v4l2_debug(level, fmt, args...)				 \
@@ -101,8 +78,6 @@
 
 void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
 				unsigned int reg_idx);
-void __iomem *mtk_vcodec_get_enc_reg_addr(struct mtk_vcodec_ctx *data,
-	unsigned int reg_idx);
 int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
 				struct mtk_vcodec_mem *mem);
 void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
old mode 100644
new mode 100755
index 0bc8b9a..aa3ce41
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
@@ -55,7 +55,7 @@
 
 /**
  * struct h264_ring_fb_list - ring frame buffer list
- * @fb_list   : frame buffer array
+ * @fb_list   : frame buffer arrary
  * @read_idx  : read index
  * @write_idx : write index
  * @count     : buffer count in list
@@ -72,7 +72,7 @@
 /**
  * struct vdec_h264_dec_info - decode information
  * @dpb_sz		: decoding picture buffer size
- * @resolution_changed  : resolution change happen
+ * @resolution_changed  : resoltion change happen
  * @realloc_mv_buf	: flag to notify driver to re-allocate mv buffer
  * @reserved		: for 8 bytes alignment
  * @bs_dma		: Input bit-stream buffer dma address
@@ -238,8 +238,7 @@
 		}
 
 		mtk_vcodec_debug(inst, "[FB] put fb into free_list @(%p, %llx)",
-				 fb->fb_base[0].va,
-				 (u64)fb->fb_base[0].dma_addr);
+				 fb->base_y.va, (u64)fb->base_y.dma_addr);
 
 		list->fb_list[list->write_idx].vdec_fb_va = (u64)(uintptr_t)fb;
 		list->write_idx = (list->write_idx == H264_MAX_FB_NUM - 1) ?
@@ -254,8 +253,8 @@
 	*pic = inst->vsi->pic;
 	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
 			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
-	mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)",
-			 pic->fb_sz[0], pic->fb_sz[1]);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
 }
 
 static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
@@ -275,7 +274,7 @@
 	mtk_vcodec_debug(inst, "sz=%d", *dpb_sz);
 }
 
-static int vdec_h264_init(struct mtk_vcodec_ctx *ctx)
+static int vdec_h264_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
 {
 	struct vdec_h264_inst *inst = NULL;
 	int err;
@@ -287,6 +286,7 @@
 	inst->ctx = ctx;
 
 	inst->vpu.id = IPI_VDEC_H264;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
 	inst->vpu.ctx = ctx;
 	inst->vpu.handler = vpu_dec_ipi_handler;
 
@@ -303,7 +303,7 @@
 
 	mtk_vcodec_debug(inst, "H264 Instance >> %p", inst);
 
-	ctx->drv_handle = inst;
+	*h_vdec = (unsigned long)inst;
 	return 0;
 
 error_deinit:
@@ -314,7 +314,7 @@
 	return err;
 }
 
-static void vdec_h264_deinit(void *h_vdec)
+static void vdec_h264_deinit(unsigned long h_vdec)
 {
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 
@@ -339,8 +339,8 @@
 	return -1;
 }
 
-static int vdec_h264_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
-			    struct vdec_fb *fb, unsigned int  *res_chg)
+static int vdec_h264_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			    struct vdec_fb *fb, bool *res_chg)
 {
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 	struct vdec_vpu_inst *vpu = &inst->vpu;
@@ -352,9 +352,8 @@
 	unsigned int buf_sz;
 	unsigned int data[2];
 	uint64_t vdec_fb_va = (u64)(uintptr_t)fb;
-	uint64_t y_fb_dma = fb ? (u64)fb->fb_base[0].dma_addr : 0;
-	uint64_t c_fb_dma = fb ? (u64)fb->fb_base[1].dma_addr : 0;
-	*res_chg = VDEC_NO_CHANGE;
+	uint64_t y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	uint64_t c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
 
 	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p",
 			 ++inst->num_nalu, y_fb_dma, c_fb_dma, fb);
@@ -394,9 +393,9 @@
 	if (err)
 		goto err_free_fb_out;
 
-	if (inst->vsi->dec.resolution_changed) {
+	*res_chg = inst->vsi->dec.resolution_changed;
+	if (*res_chg) {
 		struct vdec_pic_info pic;
-		*res_chg = VDEC_RES_CHANGE;
 
 		mtk_vcodec_debug(inst, "- resolution changed -");
 		get_pic_info(inst, &pic);
@@ -460,8 +459,8 @@
 	list->count--;
 }
 
-static int vdec_h264_get_param(void *h_vdec, enum vdec_get_param_type type,
-			       void *out)
+static int vdec_h264_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
 {
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 
@@ -494,10 +493,16 @@
 	return 0;
 }
 
-const struct vdec_common_if vdec_h264_if = {
+static struct vdec_common_if vdec_h264_if = {
 	.init		= vdec_h264_init,
 	.decode		= vdec_h264_decode,
 	.get_param	= vdec_h264_get_param,
-	.set_param	= NULL,
 	.deinit		= vdec_h264_deinit,
 };
+
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
+struct vdec_common_if *get_h264_dec_comm_if(void)
+{
+	return &vdec_h264_if;
+}
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
old mode 100644
new mode 100755
index 59a7eeb..3e84a76
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
@@ -120,7 +120,7 @@
 /**
  * struct vdec_vp8_vpu_inst - VPU instance for VP8 decode
  * @wq_hd	: Wait queue to wait VPU message ack
- * @signaled	: 1 - Host has received ack message from VPU, 0 - not receive
+ * @signaled	: 1 - Host has received ack message from VPU, 0 - not recevie
  * @failure	: VPU execution result status 0 - success, others - fail
  * @inst_addr	: VPU decoder instance address
  */
@@ -294,8 +294,8 @@
 
 	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
 			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
-	mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)",
-			 pic->fb_sz[0], pic->fb_sz[1]);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
 }
 
 static void vp8_dec_finish(struct vdec_vp8_inst *inst)
@@ -310,7 +310,7 @@
 		list_for_each_entry(node, &inst->fb_use_list, list) {
 			struct vdec_fb *fb = (struct vdec_fb *)node->fb;
 
-			if (prev_y_dma == (uint64_t)fb->fb_base[0].dma_addr) {
+			if (prev_y_dma == (uint64_t)fb->base_y.dma_addr) {
 				list_move_tail(&node->list,
 					       &inst->fb_free_list);
 				break;
@@ -396,7 +396,7 @@
 	inst->vsi->dec.working_buf_dma = 0;
 }
 
-static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx)
+static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
 {
 	struct vdec_vp8_inst *inst;
 	int err;
@@ -408,6 +408,7 @@
 	inst->ctx = ctx;
 
 	inst->vpu.id = IPI_VDEC_VP8;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
 	inst->vpu.ctx = ctx;
 	inst->vpu.handler = vpu_dec_ipi_handler;
 
@@ -426,7 +427,7 @@
 	get_hw_reg_base(inst);
 	mtk_vcodec_debug(inst, "VP8 Instance >> %p", inst);
 
-	ctx->drv_handle = inst;
+	*h_vdec = (unsigned long)inst;
 	return 0;
 
 error_deinit:
@@ -436,8 +437,8 @@
 	return err;
 }
 
-static int vdec_vp8_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
-			   struct vdec_fb *fb, unsigned int  *res_chg)
+static int vdec_vp8_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			   struct vdec_fb *fb, bool *res_chg)
 {
 	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
 	struct vdec_vp8_dec_info *dec = &inst->vsi->dec;
@@ -447,7 +448,6 @@
 	int err = 0;
 	uint64_t y_fb_dma;
 	uint64_t c_fb_dma;
-	*res_chg = VDEC_NO_CHANGE;
 
 	/* bs NULL means flush decoder */
 	if (bs == NULL) {
@@ -455,8 +455,8 @@
 		return vpu_dec_reset(vpu);
 	}
 
-	y_fb_dma = fb ? (u64)fb->fb_base[0].dma_addr : 0;
-	c_fb_dma = fb ? (u64)fb->fb_base[1].dma_addr : 0;
+	y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
 
 	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx fb=%p",
 			 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
@@ -491,7 +491,7 @@
 
 	if (dec->resolution_changed) {
 		mtk_vcodec_debug(inst, "- resolution_changed -");
-		*res_chg = VDEC_RES_CHANGE;
+		*res_chg = true;
 		add_fb_to_free_list(inst, fb);
 		return 0;
 	}
@@ -513,7 +513,7 @@
 	mtk_vcodec_debug(inst, "\n - FRAME[%d] - show=%d\n", inst->frm_cnt,
 			 dec->show_frame);
 	inst->frm_cnt++;
-	*res_chg = VDEC_NO_CHANGE;
+	*res_chg = false;
 	return 0;
 
 error:
@@ -573,8 +573,8 @@
 			 cr->left, cr->top, cr->width, cr->height);
 }
 
-static int vdec_vp8_get_param(void *h_vdec, enum vdec_get_param_type type,
-			      void *out)
+static int vdec_vp8_get_param(unsigned long h_vdec,
+			      enum vdec_get_param_type type, void *out)
 {
 	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
 
@@ -607,7 +607,7 @@
 	return 0;
 }
 
-static void vdec_vp8_deinit(void *h_vdec)
+static void vdec_vp8_deinit(unsigned long h_vdec)
 {
 	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
 
@@ -618,10 +618,16 @@
 	kfree(inst);
 }
 
-const struct vdec_common_if vdec_vp8_if = {
+static struct vdec_common_if vdec_vp8_if = {
 	.init		= vdec_vp8_init,
 	.decode		= vdec_vp8_decode,
 	.get_param	= vdec_vp8_get_param,
-	.set_param	= NULL,
 	.deinit		= vdec_vp8_deinit,
 };
+
+struct vdec_common_if *get_vp8_dec_comm_if(void);
+
+struct vdec_common_if *get_vp8_dec_comm_if(void)
+{
+	return &vdec_vp8_if;
+}
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
old mode 100644
new mode 100755
index 232cade..bc8349b
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -227,7 +227,7 @@
 
 	list_for_each_entry(node, &inst->fb_use_list, list) {
 		fb = (struct vdec_fb *)node->fb;
-		if (fb->fb_base[0].va == addr) {
+		if (fb->base_y.va == addr) {
 			list_move_tail(&node->list,
 				       &inst->available_fb_node_list);
 			break;
@@ -275,11 +275,9 @@
 			if (!vp9_is_sf_ref_fb(inst,
 					      vsi->frm_bufs[ref_idx].buf.fb)) {
 				struct vdec_fb *fb;
-				struct vdec_fb *temp_fb;
 
-				temp_fb = vsi->frm_bufs[ref_idx].buf.fb;
 				fb = vp9_rm_from_fb_use_list(inst,
-				     temp_fb->fb_base[0].va);
+				     vsi->frm_bufs[ref_idx].buf.fb->base_y.va);
 				vp9_add_to_fb_free_list(inst, fb);
 			} else
 				vp9_free_sf_ref_fb(
@@ -297,11 +295,11 @@
 	struct vdec_vp9_vsi *vsi = inst->vsi;
 
 	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
-		if (vsi->sf_ref_fb[i].fb.fb_base[0].va) {
+		if (vsi->sf_ref_fb[i].fb.base_y.va) {
 			mtk_vcodec_mem_free(inst->ctx,
-				&vsi->sf_ref_fb[i].fb.fb_base[0]);
+				&vsi->sf_ref_fb[i].fb.base_y);
 			mtk_vcodec_mem_free(inst->ctx,
-				&vsi->sf_ref_fb[i].fb.fb_base[1]);
+				&vsi->sf_ref_fb[i].fb.base_c);
 			vsi->sf_ref_fb[i].used = 0;
 		}
 	}
@@ -322,7 +320,7 @@
 	for (idx = 0;
 		idx < ARRAY_SIZE(vsi->sf_ref_fb);
 		idx++) {
-		if (vsi->sf_ref_fb[idx].fb.fb_base[0].va &&
+		if (vsi->sf_ref_fb[idx].fb.base_y.va &&
 		    vsi->sf_ref_fb[idx].used == 0) {
 			return idx;
 		}
@@ -331,7 +329,7 @@
 	for (idx = 0;
 		idx < ARRAY_SIZE(vsi->sf_ref_fb);
 		idx++) {
-		if (vsi->sf_ref_fb[idx].fb.fb_base[0].va == NULL)
+		if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL)
 			break;
 	}
 
@@ -340,7 +338,7 @@
 		return -1;
 	}
 
-	mem_basy_y = &vsi->sf_ref_fb[idx].fb.fb_base[0];
+	mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y;
 	mem_basy_y->size = vsi->buf_sz_y_bs +
 		vsi->buf_len_sz_y;
 
@@ -349,7 +347,7 @@
 		return -1;
 	}
 
-	mem_basy_c = &vsi->sf_ref_fb[idx].fb.fb_base[1];
+	mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c;
 	mem_basy_c->size = vsi->buf_sz_c_bs +
 		vsi->buf_len_sz_c;
 
@@ -482,14 +480,14 @@
 		 * buffer
 		 */
 		if ((frm_to_show->fb != NULL) &&
-			(inst->cur_fb->fb_base[0].size >=
-			frm_to_show->fb->fb_base[0].size)) {
-			memcpy((void *)inst->cur_fb->fb_base[0].va,
-				(void *)frm_to_show->fb->fb_base[0].va,
+			(inst->cur_fb->base_y.size >=
+			frm_to_show->fb->base_y.size)) {
+			memcpy((void *)inst->cur_fb->base_y.va,
+				(void *)frm_to_show->fb->base_y.va,
 				vsi->buf_w *
 				vsi->buf_h);
-			memcpy((void *)inst->cur_fb->fb_base[1].va,
-				(void *)frm_to_show->fb->fb_base[1].va,
+			memcpy((void *)inst->cur_fb->base_c.va,
+				(void *)frm_to_show->fb->base_c.va,
 				vsi->buf_w *
 				vsi->buf_h / 2);
 		} else {
@@ -499,9 +497,9 @@
 			 */
 			if (frm_to_show->fb != NULL)
 				mtk_vcodec_err(inst,
-					"inst->cur_fb->fb_base[0].size=%zu, frm_to_show->fb.fb_base[0].size=%zu",
-					inst->cur_fb->fb_base[0].size,
-					frm_to_show->fb->fb_base[0].size);
+					"inst->cur_fb->base_y.size=%zu, frm_to_show->fb.base_y.size=%zu",
+					inst->cur_fb->base_y.size,
+					frm_to_show->fb->base_y.size);
 		}
 		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
 			if (vsi->show_frame)
@@ -523,7 +521,7 @@
 			struct vdec_fb *fb;
 
 			fb = vp9_rm_from_fb_use_list(inst,
-			vsi->frm_bufs[vsi->new_fb_idx].buf.fb->fb_base[0].va);
+			vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va);
 
 			vp9_add_to_fb_free_list(inst, fb);
 		} else {
@@ -704,8 +702,10 @@
 
 static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic)
 {
-	pic->fb_sz[0] = inst->vsi->buf_sz_y_bs + inst->vsi->buf_len_sz_y;
-	pic->fb_sz[1] = inst->vsi->buf_sz_c_bs + inst->vsi->buf_len_sz_c;
+	pic->y_bs_sz = inst->vsi->buf_sz_y_bs;
+	pic->c_bs_sz = inst->vsi->buf_sz_c_bs;
+	pic->y_len_sz = inst->vsi->buf_len_sz_y;
+	pic->c_len_sz = inst->vsi->buf_len_sz_c;
 
 	pic->pic_w = inst->vsi->pic_w;
 	pic->pic_h = inst->vsi->pic_h;
@@ -714,9 +714,8 @@
 
 	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
 		 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
-	mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)",
-		pic->fb_sz[0],
-		pic->fb_sz[1]);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+		 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
 }
 
 static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
@@ -767,7 +766,7 @@
 	return 0;
 }
 
-static void vdec_vp9_deinit(void *h_vdec)
+static void vdec_vp9_deinit(unsigned long h_vdec)
 {
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 	struct mtk_vcodec_mem *mem;
@@ -789,7 +788,7 @@
 	vp9_free_inst(inst);
 }
 
-static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx)
+static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
 {
 	struct vdec_vp9_inst *inst;
 
@@ -801,6 +800,7 @@
 	inst->ctx = ctx;
 
 	inst->vpu.id = IPI_VDEC_VP9;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
 	inst->vpu.ctx = ctx;
 	inst->vpu.handler = vpu_dec_ipi_handler;
 
@@ -812,7 +812,7 @@
 	inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi;
 	init_all_fb_lists(inst);
 
-	ctx->drv_handle = inst;
+	(*h_vdec) = (unsigned long)inst;
 	return 0;
 
 err_deinit_inst:
@@ -821,8 +821,8 @@
 	return -EINVAL;
 }
 
-static int vdec_vp9_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
-		   struct vdec_fb *fb, unsigned int  *res_chg)
+static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
 {
 	int ret = 0;
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
@@ -830,7 +830,7 @@
 	u32 data[3];
 	int i;
 
-	*res_chg = VDEC_NO_CHANGE;
+	*res_chg = false;
 
 	if ((bs == NULL) && (fb == NULL)) {
 		mtk_vcodec_debug(inst, "[EOS]");
@@ -944,7 +944,7 @@
 		}
 
 		if (vsi->resolution_changed) {
-			*res_chg = VDEC_RES_CHANGE;
+			*res_chg = true;
 			mtk_vcodec_debug(inst, "VDEC_ST_RESOLUTION_CHANGED");
 
 			ret = 0;
@@ -980,8 +980,8 @@
 			 cr->left, cr->top, cr->width, cr->height);
 }
 
-static int vdec_vp9_get_param(void *h_vdec, enum vdec_get_param_type type,
-			      void *out)
+static int vdec_vp9_get_param(unsigned long h_vdec,
+		enum vdec_get_param_type type, void *out)
 {
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 	int ret = 0;
@@ -1011,10 +1011,16 @@
 	return ret;
 }
 
-const struct vdec_common_if vdec_vp9_if = {
+static struct vdec_common_if vdec_vp9_if = {
 	.init		= vdec_vp9_init,
 	.decode		= vdec_vp9_decode,
 	.get_param	= vdec_vp9_get_param,
-	.set_param  = NULL,
 	.deinit		= vdec_vp9_deinit,
 };
+
+struct vdec_common_if *get_vp9_dec_comm_if(void);
+
+struct vdec_common_if *get_vp9_dec_comm_if(void)
+{
+	return &vdec_vp9_if;
+}
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_base.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
old mode 100644
new mode 100755
index c0f921a..7e4c1a9
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
@@ -15,6 +15,8 @@
 #ifndef _VDEC_DRV_BASE_
 #define _VDEC_DRV_BASE_
 
+#include "mtk_vcodec_drv.h"
+
 #include "vdec_drv_if.h"
 
 struct vdec_common_if {
@@ -23,7 +25,7 @@
 	 * @ctx     : [in] mtk v4l2 context
 	 * @h_vdec  : [out] driver handle
 	 */
-	int (*init)(struct mtk_vcodec_ctx *ctx);
+	int (*init)(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec);
 
 	/**
 	 * (*decode)() - trigger decode
@@ -32,8 +34,8 @@
 	 * @fb      : [in] frame buffer to store decoded frame
 	 * @res_chg : [out] resolution change happen
 	 */
-	int (*decode)(void *h_vdec, struct mtk_vcodec_mem *bs,
-		      struct vdec_fb *fb, unsigned int  *res_chg);
+	int (*decode)(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		      struct vdec_fb *fb, bool *res_chg);
 
 	/**
 	 * (*get_param)() - get driver's parameter
@@ -41,23 +43,14 @@
 	 * @type   : [in] input parameter type
 	 * @out    : [out] buffer to store query result
 	 */
-	int (*get_param)(void *h_vdec, enum vdec_get_param_type type,
+	int (*get_param)(unsigned long h_vdec, enum vdec_get_param_type type,
 			 void *out);
 
 	/**
-	 * (*set_param)() - set driver's parameter
-	 * @h_vdec : [in] driver handle
-	 * @type   : [in] input parameter type
-	 * @in     : [in] buffer to store query
-	 */
-	int (*set_param)(void  *h_vdec, enum vdec_set_param_type type,
-					 void *in);
-
-	/**
 	 * (*deinit)() - deinitialize driver.
 	 * @h_vdec : [in] driver handle to be deinit
 	 */
-	void (*deinit)(void *h_vdec);
+	void (*deinit)(unsigned long h_vdec);
 };
 
 #endif
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
old mode 100644
new mode 100755
index 2b281eb..5ffc468
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -21,78 +21,33 @@
 #include "mtk_vcodec_dec.h"
 #include "vdec_drv_base.h"
 #include "mtk_vcodec_dec_pm.h"
-
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-#include "mtk_vcu.h"
-const struct vdec_common_if *get_dec_common_if(void);
-#endif
-
-#ifdef CONFIG_VIDEO_MEDIATEK_VPU
 #include "mtk_vpu.h"
-extern const struct vdec_common_if vdec_h264_if;
-extern const struct vdec_common_if vdec_vp8_if;
-extern const struct vdec_common_if vdec_vp9_if;
-extern const struct vdec_common_if vdec_h264_slice_if;
-#endif
 
+const struct vdec_common_if *get_h264_dec_comm_if(void);
+const struct vdec_common_if *get_vp8_dec_comm_if(void);
+const struct vdec_common_if *get_vp9_dec_comm_if(void);
 
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
 	int ret = 0;
 
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
 	switch (fourcc) {
 	case V4L2_PIX_FMT_H264:
-	case V4L2_PIX_FMT_H265:
-	case V4L2_PIX_FMT_HEIF:
-	case V4L2_PIX_FMT_MPEG1:
-	case V4L2_PIX_FMT_MPEG2:
-	case V4L2_PIX_FMT_MPEG4:
-	case V4L2_PIX_FMT_H263:
-	case V4L2_PIX_FMT_S263:
-	case V4L2_PIX_FMT_XVID:
-	case V4L2_PIX_FMT_DIVX:
-	case V4L2_PIX_FMT_DIVX3:
-	case V4L2_PIX_FMT_DIVX4:
-	case V4L2_PIX_FMT_DIVX5:
-	case V4L2_PIX_FMT_DIVX6:
+		ctx->dec_if = get_h264_dec_comm_if();
+		break;
 	case V4L2_PIX_FMT_VP8:
+		ctx->dec_if = get_vp8_dec_comm_if();
+		break;
 	case V4L2_PIX_FMT_VP9:
-	case V4L2_PIX_FMT_WMV1:
-	case V4L2_PIX_FMT_WMV2:
-	case V4L2_PIX_FMT_WMV3:
-	case V4L2_PIX_FMT_WVC1:
-	case V4L2_PIX_FMT_WMVA:
-	case V4L2_PIX_FMT_RV30:
-	case V4L2_PIX_FMT_RV40:
-		ctx->dec_if = get_dec_common_if();
+		ctx->dec_if = get_vp9_dec_comm_if();
 		break;
 	default:
 		return -EINVAL;
 	}
-#endif
-#ifdef CONFIG_VIDEO_MEDIATEK_VPU
-	switch (fourcc) {
-	case V4L2_PIX_FMT_H264_SLICE:
-		ctx->dec_if = &vdec_h264_slice_if;
-		break;
-	case V4L2_PIX_FMT_H264:
-		ctx->dec_if = &vdec_h264_if;
-		break;
-	case V4L2_PIX_FMT_VP8:
-		ctx->dec_if = &vdec_vp8_if;
-		break;
-	case V4L2_PIX_FMT_VP9:
-		ctx->dec_if = &vdec_vp9_if;
-		break;
-	default:
-		return -EINVAL;
-	}
-#endif
 
 	mtk_vdec_lock(ctx);
 	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
-	ret = ctx->dec_if->init(ctx);
+	ret = ctx->dec_if->init(ctx, &ctx->drv_handle);
 	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
 	mtk_vdec_unlock(ctx);
 
@@ -100,10 +55,10 @@
 }
 
 int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
-		   struct vdec_fb *fb, unsigned int  *res_chg)
+		   struct vdec_fb *fb, bool *res_chg)
 {
 	int ret = 0;
-	int i = 0;
+
 	if (bs) {
 		if ((bs->dma_addr & 63) != 0) {
 			mtk_v4l2_err("bs dma_addr should 64 byte align");
@@ -112,21 +67,17 @@
 	}
 
 	if (fb) {
-		for (i = 0; i < fb->num_planes; i++) {
-			if ((fb->fb_base[i].dma_addr & 511UL) != 0UL) {
-				mtk_v4l2_err("fb addr should 512 byte align");
-				return -EINVAL;
-			}
+		if (((fb->base_y.dma_addr & 511) != 0) ||
+		    ((fb->base_c.dma_addr & 511) != 0)) {
+			mtk_v4l2_err("frame buffer dma_addr should 512 byte align");
+			return -EINVAL;
 		}
 	}
 
-
 	if (ctx->drv_handle == 0)
 		return -EIO;
 
-	mtk_vdec_pmqos_prelock(ctx);
 	mtk_vdec_lock(ctx);
-	mtk_vdec_pmqos_begin_frame(ctx);
 
 	mtk_vcodec_set_curr_ctx(ctx->dev, ctx);
 	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
@@ -136,7 +87,6 @@
 	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
 	mtk_vcodec_set_curr_ctx(ctx->dev, NULL);
 
-	mtk_vdec_pmqos_end_frame(ctx);
 	mtk_vdec_unlock(ctx);
 
 	return ret;
@@ -146,50 +96,14 @@
 		      void *out)
 {
 	int ret = 0;
-#ifdef CONFIG_VIDEO_MEDIATEK_VPU
+
 	if (ctx->drv_handle == 0)
 		return -EIO;
-#endif
 
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-	struct vdec_inst *inst = NULL;
-	int drv_handle_exist = 1;
-
-	if (!ctx->drv_handle) {
-		inst = kzalloc(sizeof(struct vdec_inst), GFP_KERNEL);
-		inst->ctx = ctx;
-		ctx->drv_handle = (void *)(inst);
-		ctx->dec_if = get_dec_common_if();
-		drv_handle_exist = 0;
-	}
-#endif
 	mtk_vdec_lock(ctx);
 	ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
 	mtk_vdec_unlock(ctx);
 
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-	if (!drv_handle_exist) {
-		kfree(inst);
-		ctx->drv_handle = 0;
-		ctx->dec_if = NULL;
-	}
-#endif
-	return ret;
-}
-
-int vdec_if_set_param(struct mtk_vcodec_ctx *ctx, enum vdec_set_param_type type,
-					  void *in)
-{
-	int ret = 0;
-
-	if (ctx->drv_handle == 0)
-		return -EIO;
-
-	mtk_vdec_lock(ctx);
-	if (ctx->dec_if->set_param)
-		ret = ctx->dec_if->set_param(ctx->drv_handle, type, in);
-	mtk_vdec_unlock(ctx);
-
 	return ret;
 }
 
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
old mode 100644
new mode 100755
index 682f50b..ded1154
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
@@ -19,24 +19,6 @@
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_dec.h"
 #include "mtk_vcodec_util.h"
-#include "vdec_ipi_msg.h"
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-#include "vdec_vcu_if.h"
-
-/**
- * struct vdec_inst - decoder instance
- * @num_nalu : how many nalus be decoded
- * @ctx      : point to mtk_vcodec_ctx
- * @vcu      : VCU instance
- * @vsi      : VCU shared information
- */
-struct vdec_inst {
-	unsigned int num_nalu;
-	struct mtk_vcodec_ctx *ctx;
-	struct vdec_vcu_inst vcu;
-	struct vdec_vsi *vsi;
-};
-#endif
 
 
 /**
@@ -51,6 +33,24 @@
 	FB_ST_FREE		= (1 << 1)
 };
 
+/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,
+ * the caller does not own the returned buffer. The buffer will not be
+ *				released before vdec_if_deinit.
+ * GET_PARAM_DISP_FRAME_BUFFER	: get next displayable frame buffer,
+ *				struct vdec_fb**
+ * GET_PARAM_FREE_FRAME_BUFFER	: get non-referenced framebuffer, vdec_fb**
+ * GET_PARAM_PIC_INFO		: get picture info, struct vdec_pic_info*
+ * GET_PARAM_CROP_INFO		: get crop info, struct v4l2_crop*
+ * GET_PARAM_DPB_SIZE		: get dpb size, unsigned int*
+ */
+enum vdec_get_param_type {
+	GET_PARAM_DISP_FRAME_BUFFER,
+	GET_PARAM_FREE_FRAME_BUFFER,
+	GET_PARAM_PIC_INFO,
+	GET_PARAM_CROP_INFO,
+	GET_PARAM_DPB_SIZE
+};
+
 /**
  * struct vdec_fb_node  - decoder frame buffer node
  * @list	: list to hold this node
@@ -89,7 +89,7 @@
  * Return: 0 on success. -EIO on unrecoverable error.
  */
 int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
-		   struct vdec_fb *fb, unsigned int  *res_chg);
+		   struct vdec_fb *fb, bool *res_chg);
 
 /**
  * vdec_if_get_param() - get driver's parameter
@@ -100,14 +100,4 @@
 int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
 		      void *out);
 
-/*
- * vdec_if_set_param - Set parameter to driver
- * @ctx : [in] v4l2 context
- * @type        : [in] input parameter type
- * @out : [in] input parameter
- * Return: 0 if setting param successfully, otherwise it is failed.
- */
-int vdec_if_set_param(struct mtk_vcodec_ctx *ctx,
-					  enum vdec_set_param_type type,
-					  void *in);
 #endif
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
old mode 100644
new mode 100755
index 627a0e1..5a8a629
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
@@ -16,56 +16,6 @@
 #ifndef _VDEC_IPI_MSG_H_
 #define _VDEC_IPI_MSG_H_
 
-#define MTK_MAX_DEC_CODECS_SUPPORT       (128)
-#define DEC_MAX_FB_NUM              VIDEO_MAX_FRAME
-#define DEC_MAX_BS_NUM              VIDEO_MAX_FRAME
-/**
- * enum vdec_src_chg_type - decoder src change type
- * @VDEC_NO_CHANGE      : no change
- * @VDEC_RES_CHANGE     : resolution change
- * @VDEC_REALLOC_MV_BUF : realloc mv buf
- * @VDEC_HW_NOT_SUPPORT : hw not support
- * @VDEC_NEED_MORE_OUTPUT_BUF: bs need more fm buffer to decode
- *          kernel should send the same bs buffer again with new fm buffer
- * @VDEC_CROP_CHANGED: notification to update frame crop info
- */
-enum vdec_src_chg_type {
-	VDEC_NO_CHANGE              = (0 << 0),
-	VDEC_RES_CHANGE             = (1 << 0),
-	VDEC_REALLOC_MV_BUF         = (1 << 1),
-	VDEC_HW_NOT_SUPPORT         = (1 << 2),
-	VDEC_NEED_SEQ_HEADER        = (1 << 3),
-	VDEC_NEED_MORE_OUTPUT_BUF   = (1 << 4),
-	VDEC_CROP_CHANGED           = (1 << 5),
-};
-
-/*
- * enum vdec_set_param_type -
- *                  The type of set parameter used in vdec_if_set_param()
- * (VCU related: If you change the order, you must also update the VCU codes.)
- * SET_PARAM_DECODE_MODE: set decoder mode
- * SET_PARAM_FRAME_SIZE: set container frame size
- * SET_PARAM_SET_FIXED_MAX_OUTPUT_BUFFER: set fixed maximum buffer size
- * SET_PARAM_UFO_MODE: set UFO mode
- * SET_PARAM_CRC_PATH: set CRC path used for UT
- * SET_PARAM_GOLDEN_PATH: set Golden YUV path used for UT
- * SET_PARAM_FB_NUM_PLANES                      : frame buffer plane count
- */
-enum vdec_set_param_type {
-	SET_PARAM_DECODE_MODE,
-	SET_PARAM_FRAME_SIZE,
-	SET_PARAM_SET_FIXED_MAX_OUTPUT_BUFFER,
-	SET_PARAM_UFO_MODE,
-	SET_PARAM_CRC_PATH,
-	SET_PARAM_GOLDEN_PATH,
-	SET_PARAM_FB_NUM_PLANES,
-	SET_PARAM_WAIT_KEY_FRAME,
-	SET_PARAM_NAL_SIZE_LENGTH,
-	SET_PARAM_OPERATING_RATE,
-	SET_PARAM_FREE_FRAME_BUFQ_COUNT,
-	SET_PARAM_TOTAL_FRAME_BUFQ_COUNT
-};
-
 /**
  * enum vdec_ipi_msgid - message id between AP and VPU
  * @AP_IPIMSG_XXX	: AP to VPU cmd message id
@@ -77,56 +27,14 @@
 	AP_IPIMSG_DEC_END = 0xA002,
 	AP_IPIMSG_DEC_DEINIT = 0xA003,
 	AP_IPIMSG_DEC_RESET = 0xA004,
-	AP_IPIMSG_DEC_SET_PARAM = 0xA005,
-	AP_IPIMSG_DEC_QUERY_CAP = 0xA006,
 
 	VPU_IPIMSG_DEC_INIT_ACK = 0xB000,
 	VPU_IPIMSG_DEC_START_ACK = 0xB001,
 	VPU_IPIMSG_DEC_END_ACK = 0xB002,
 	VPU_IPIMSG_DEC_DEINIT_ACK = 0xB003,
 	VPU_IPIMSG_DEC_RESET_ACK = 0xB004,
-	VPU_IPIMSG_DEC_SET_PARAM_ACK = 0xB005,
-	VPU_IPIMSG_DEC_QUERY_CAP_ACK = 0xB006,
-
-	VPU_IPIMSG_DEC_WAITISR = 0xC000,
-	VPU_IPIMSG_DEC_GET_FRAME_BUFFER = 0xC001,
-	VPU_IPIMSG_DEC_CLOCK_ON = 0xC002,
-	VPU_IPIMSG_DEC_CLOCK_OFF = 0xC003
 };
 
-/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,
- * the caller does not own the returned buffer. The buffer will not be
- *                              released before vdec_if_deinit.
- * GET_PARAM_DISP_FRAME_BUFFER  : get next displayable frame buffer,
- *                              struct vdec_fb**
- * GET_PARAM_FREE_FRAME_BUFFER  : get non-referenced framebuffer, vdec_fb**
- * GET_PARAM_PIC_INFO           : get picture info, struct vdec_pic_info*
- * GET_PARAM_CROP_INFO          : get crop info, struct v4l2_crop*
- * GET_PARAM_DPB_SIZE           : get dpb size, __s32*
- * GET_PARAM_FRAME_INTERVAL     : get frame interval info*
- * GET_PARAM_ERRORMB_MAP        : get error mocroblock when decode error*
- * GET_PARAM_CAPABILITY_SUPPORTED_FORMATS: get codec supported format capability
- * GET_PARAM_CAPABILITY_FRAME_SIZES:
- *                       get codec supported frame size & alignment info
- */
-enum vdec_get_param_type {
-	GET_PARAM_DISP_FRAME_BUFFER,
-	GET_PARAM_FREE_FRAME_BUFFER,
-	GET_PARAM_FREE_BITSTREAM_BUFFER,
-	GET_PARAM_PIC_INFO,
-	GET_PARAM_CROP_INFO,
-	GET_PARAM_DPB_SIZE,
-	GET_PARAM_FRAME_INTERVAL,
-	GET_PARAM_ERRORMB_MAP,
-	GET_PARAM_CAPABILITY_SUPPORTED_FORMATS,
-	GET_PARAM_CAPABILITY_FRAME_SIZES,
-	GET_PARAM_COLOR_DESC,
-	GET_PARAM_ASPECT_RATIO,
-	GET_PARAM_PLATFORM_SUPPORTED_FIX_BUFFERS,
-	GET_PARAM_PLATFORM_SUPPORTED_FIX_BUFFERS_SVP,
-	GET_PARAM_INTERLACING,
-	GET_PARAM_CODEC_TYPE
-};
 /**
  * struct vdec_ap_ipi_cmd - generic AP to VPU ipi command format
  * @msg_id	: vdec_ipi_msgid
@@ -191,192 +99,5 @@
 	uint64_t ap_inst_addr;
 	uint32_t vpu_inst_addr;
 };
-/**
- * struct vdec_ap_ipi_set_param - for AP_IPIMSG_DEC_SET_PARAM
- * @msg_id        : AP_IPIMSG_DEC_SET_PARAM
- * @vpu_inst_addr : VPU decoder instance address
- * @id            : set param  type
- * @data          : param data
- */
-struct vdec_ap_ipi_set_param {
-	uint32_t msg_id;
-	uint32_t vpu_inst_addr;
-	uint32_t id;
-	uint32_t data[8];
-};
 
-/**
- * struct vdec_ap_ipi_query_cap - for AP_IPIMSG_DEC_QUERY_CAP
- * @msg_id        : AP_IPIMSG_DEC_QUERY_CAP
- * @id      : query capability type
- * @vdec_inst     : AP query data address
- */
-struct vdec_ap_ipi_query_cap {
-	uint32_t msg_id;
-	uint32_t id;
-#ifndef CONFIG_64BIT
-	union {
-		uint64_t ap_inst_addr_64;
-		uint32_t ap_inst_addr;
-	};
-	union {
-		uint64_t ap_data_addr_64;
-		uint32_t ap_data_addr;
-	};
-#else
-	uint64_t ap_inst_addr;
-	uint64_t ap_data_addr;
-#endif
-};
-
-/**
- * struct vdec_vpu_ipi_query_cap_ack - for VCU_IPIMSG_DEC_QUERY_CAP_ACK
- * @msg_id      : VPU_IPIMSG_DEC_QUERY_CAP_ACK
- * @status      : VPU exeuction result
- * @ap_data_addr   : AP query data address
- * @vpu_data_addr  : VCU query data address
- */
-struct vdec_vpu_ipi_query_cap_ack {
-	uint32_t msg_id;
-	int32_t status;
-#ifndef CONFIG_64BIT
-	union {
-		uint64_t ap_inst_addr_64;
-		uint32_t ap_inst_addr;
-	};
-	uint32_t id;
-	union {
-		uint64_t ap_data_addr_64;
-		uint32_t ap_data_addr;
-	};
-#else
-	uint64_t ap_inst_addr;
-	uint32_t id;
-	uint64_t ap_data_addr;
-#endif
-	uint32_t vpu_data_addr;
-};
-/*
- * struct vdec_ipi_fb - decoder frame buffer information
- * @vdec_fb_va  : virtual address of struct vdec_fb
- * @y_fb_dma    : dma address of Y frame buffer
- * @c_fb_dma    : dma address of C frame buffer
- * @poc         : picture order count of frame buffer
- * @reserved    : for 8 bytes alignment
- */
-struct vdec_ipi_fb {
-	uint64_t vdec_fb_va;
-	uint64_t y_fb_dma;
-	uint64_t c_fb_dma;
-	int32_t poc;
-	uint32_t reserved;
-};
-
-/**
- * struct ring_bs_list - ring bitstream buffer list
- * @vdec_bs_va_list   : bitstream buffer arrary
- * @read_idx  : read index
- * @write_idx : write index
- * @count	  : buffer count in list
- */
-struct ring_bs_list {
-	uint64_t vdec_bs_va_list[DEC_MAX_BS_NUM];
-	int32_t read_idx;
-	int32_t write_idx;
-	int32_t count;
-	int32_t reserved;
-};
-
-/**
- * struct ring_fb_list - ring frame buffer list
- * @fb_list   : frame buffer arrary
- * @read_idx  : read index
- * @write_idx : write index
- * @count     : buffer count in list
- */
-struct ring_fb_list {
-	struct vdec_ipi_fb fb_list[DEC_MAX_FB_NUM];
-	int32_t read_idx;
-	int32_t write_idx;
-	int32_t count;
-	int32_t reserved;
-};
-/**
- * struct vdec_dec_info - decode information
- * @dpb_sz		: decoding picture buffer size
- * @vdec_changed_info  : some changed flags
- * @bs_dma		: Input bit-stream buffer dma address
- * @bs_fd               : Input bit-stream buffer dmabuf fd
- * @fb_dma		: Y frame buffer dma address
- * @fb_fd             : Y frame buffer dmabuf fd
- * @vdec_bs_va		: VDEC bitstream buffer struct virtual address
- * @vdec_fb_va		: VDEC frame buffer struct virtual address
- * @fb_num_planes	: frame buffer plane count
- * @reserved		: reserved variable for 64bit align
- */
-struct vdec_dec_info {
-	__u32 dpb_sz;
-	__u32 vdec_changed_info;
-	__u64 bs_dma;
-	__u64 bs_fd;
-	__u64 fb_dma[VIDEO_MAX_PLANES];
-	__u64 fb_fd[VIDEO_MAX_PLANES];
-	__u64 vdec_bs_va;
-	__u64 vdec_fb_va;
-	__u32 fb_num_planes;
-	__u32 index;
-	__u32 wait_key_frame;
-	__u32 error_map;
-	__u32 timestamp;
-	__u32 queued_frame_buf_count;
-};
-
-struct mtk_color_desc {
-	__u32	full_range;
-	__u32	color_primaries;
-	__u32	transform_character;
-	__u32	matrix_coeffs;
-	__u32	display_primaries_x[3];
-	__u32	display_primaries_y[3];
-	__u32	white_point_x;
-	__u32	white_point_y;
-	__u32	max_display_mastering_luminance;
-	__u32	min_display_mastering_luminance;
-	__u32	max_content_light_level;
-	__u32	max_pic_light_level;
-	__u32	is_hdr;
-};
-/**
- * struct vdec_vsi - shared memory for decode information exchange
- *                        between VCU and Host.
- *                        The memory is allocated by VCU and mapping to Host
- *                        in vpu_dec_init()
- * @ppl_buf_dma : HW working buffer ppl dma address
- * @mv_buf_dma  : HW working buffer mv dma address
- * @list_free   : free frame buffer ring list
- * @list_disp   : display frame buffer ring list
- * @dec         : decode information
- * @pic         : picture information
- * @crop        : crop information
- * @video_formats        : codec supported format info
- * @vdec_framesizes    : codec supported resolution info
- */
-struct vdec_vsi {
-	struct ring_bs_list list_free_bs;
-	struct ring_fb_list list_free;
-	struct ring_fb_list list_disp;
-	struct vdec_dec_info dec;
-	struct vdec_pic_info pic;
-	struct mtk_color_desc color_desc;
-	struct v4l2_rect crop;
-	struct mtk_video_fmt video_formats[MTK_MAX_DEC_CODECS_SUPPORT];
-	struct mtk_codec_framesizes vdec_framesizes[MTK_MAX_DEC_CODECS_SUPPORT];
-	uint32_t aspect_ratio;
-	uint32_t fix_buffers;
-	uint32_t fix_buffers_svp;
-	uint32_t interlacing;
-	uint32_t codec_type;
-	uint8_t crc_path[256];
-	uint8_t golden_path[256];
-};
 #endif
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
old mode 100644
new mode 100755
index be226c7..1abd14e
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
@@ -16,7 +16,6 @@
 #include "mtk_vcodec_util.h"
 #include "vdec_ipi_msg.h"
 #include "vdec_vpu_if.h"
-#include "mtk_vcodec_fw.h"
 
 static void handle_init_ack_msg(struct vdec_vpu_ipi_init_ack *msg)
 {
@@ -27,7 +26,7 @@
 
 	/* mapping VPU address to kernel virtual address */
 	/* the content in vsi is initialized to 0 in VPU */
-	vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->ipi_msg_handle, msg->vpu_inst_addr);
+	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
 	vpu->inst_addr = msg->vpu_inst_addr;
 
 	mtk_vcodec_debug(vpu, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
@@ -77,7 +76,7 @@
 	vpu->failure = 0;
 	vpu->signaled = 0;
 
-	err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->ipi_msg_handle, vpu->id, msg, len, 2000);
+	err = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
 	if (err) {
 		mtk_vcodec_err(vpu, "send fail vpu_id=%d msg_id=%X status=%d",
 			       vpu->id, *(uint32_t *)msg, err);
@@ -112,8 +111,7 @@
 
 	init_waitqueue_head(&vpu->wq);
 
-	err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->ipi_msg_handle, vpu->id, vpu->handler,
-					 "vdec", NULL);
+	err = vpu_ipi_register(vpu->dev, vpu->id, vpu->handler, "vdec", NULL);
 	if (err != 0) {
 		mtk_vcodec_err(vpu, "vpu_ipi_register fail status=%d", err);
 		return err;
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
old mode 100644
new mode 100755
index 0c48003..cd37bb2
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
@@ -15,13 +15,11 @@
 #ifndef _VDEC_VPU_IF_H_
 #define _VDEC_VPU_IF_H_
 
-#include "mtk_vcodec_fw.h"
-
-struct mtk_vcodec_ctx;
+#include "mtk_vpu.h"
 
 /**
  * struct vdec_vpu_inst - VPU instance for video codec
- * @id      : ipi msg id for each decoder
+ * @ipi_id      : ipi id for each decoder
  * @vsi         : driver structure allocated by VPU side and shared to AP side
  *                for control and info share
  * @failure     : VPU execution result status, 0: success, others: fail
@@ -33,14 +31,15 @@
  * @handler     : ipi handler for each decoder
  */
 struct vdec_vpu_inst {
-	int id;
+	enum ipi_id id;
 	void *vsi;
 	int32_t failure;
 	uint32_t inst_addr;
 	unsigned int signaled;
 	struct mtk_vcodec_ctx *ctx;
+	struct platform_device *dev;
 	wait_queue_head_t wq;
-	mtk_vcodec_ipi_handler handler;
+	ipi_handler_t handler;
 };
 
 /**
@@ -63,7 +62,7 @@
 /**
  * vpu_dec_end - end decoding, basically the function will be invoked once
  *               when HW decoding done interrupt received successfully. The
- *               decoder in VPU will continue to do reference frame management
+ *               decoder in VPU will continute to do referene frame management
  *               and check if there is a new decoded frame available to display.
  *
  * @vpu : instance for vdec_vpu_inst
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
old mode 100644
new mode 100755
index c3dd18f..6cf31b3
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
@@ -27,23 +27,14 @@
 #include "../venc_drv_base.h"
 #include "../venc_ipi_msg.h"
 #include "../venc_vpu_if.h"
+#include "mtk_vpu.h"
 
 static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc};
 
 #define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker)
 #define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098
 
-/**
- * enum venc_h264_frame_type - h264 encoder output bitstream frame type
- */
-enum venc_h264_frame_type {
-	VENC_H264_IDR_FRM,
-	VENC_H264_I_FRM,
-	VENC_H264_P_FRM,
-	VENC_H264_B_FRM,
-};
-
-/**
+/*
  * enum venc_h264_vpu_work_buf - h264 encoder buffer index
  */
 enum venc_h264_vpu_work_buf {
@@ -59,7 +50,7 @@
 	VENC_H264_VPU_WORK_BUF_MAX,
 };
 
-/**
+/*
  * enum venc_h264_bs_mode - for bs_mode argument in h264_enc_vpu_encode
  */
 enum venc_h264_bs_mode {
@@ -157,7 +148,6 @@
 	struct mtk_vcodec_mem pps_buf;
 	bool work_buf_allocated;
 	unsigned int frm_cnt;
-	unsigned int skip_frm_cnt;
 	unsigned int prepend_hdr;
 	struct venc_vpu_inst vpu_inst;
 	struct venc_h264_vsi *vsi;
@@ -276,7 +266,8 @@
 		 */
 		inst->work_bufs[i].size = wb[i].size;
 		if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) {
-			inst->work_bufs[i].va = mtk_vcodec_fw_map_dm_addr(inst->vpu_inst.ctx->dev->ipi_msg_handle, wb[i].vpua);
+			inst->work_bufs[i].va = vpu_mapping_dm_addr(
+				inst->vpu_inst.dev, wb[i].vpua);
 			inst->work_bufs[i].dma_addr = 0;
 		} else {
 			ret = mtk_vcodec_mem_alloc(inst->ctx,
@@ -295,7 +286,7 @@
 			if (i == VENC_H264_VPU_WORK_BUF_RC_CODE) {
 				void *tmp_va;
 
-				tmp_va = mtk_vcodec_fw_map_dm_addr(inst->vpu_inst.ctx->dev->ipi_msg_handle,
+				tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev,
 							     wb[i].vpua);
 				memcpy(inst->work_bufs[i].va, tmp_va,
 				       wb[i].size);
@@ -341,22 +332,6 @@
 	return irq_status;
 }
 
-static int h264_frame_type(struct venc_h264_inst *inst)
-{
-	if ((inst->vsi->config.gop_size != 0 &&
-		(inst->frm_cnt % inst->vsi->config.gop_size) == 0) ||
-		(inst->frm_cnt == 0 && inst->vsi->config.gop_size == 0)) {
-		/* IDR frame */
-		return VENC_H264_IDR_FRM;
-	} else if ((inst->vsi->config.intra_period != 0 &&
-		(inst->frm_cnt % inst->vsi->config.intra_period) == 0) ||
-		(inst->frm_cnt == 0 && inst->vsi->config.intra_period == 0)) {
-		/* I frame */
-		return VENC_H264_I_FRM;
-	} else {
-		return VENC_H264_P_FRM;  //mt8183 only support I and P frame
-	}
-}
 static int h264_encode_sps(struct venc_h264_inst *inst,
 			   struct mtk_vcodec_mem *bs_buf,
 			   unsigned int *bs_size)
@@ -366,8 +341,8 @@
 
 	mtk_vcodec_debug_enter(inst);
 
-	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL, bs_buf,
-			     bs_size, NULL);
+	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL,
+			     bs_buf, bs_size);
 	if (ret)
 		return ret;
 
@@ -394,7 +369,7 @@
 	mtk_vcodec_debug_enter(inst);
 
 	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL,
-			     bs_buf, bs_size, NULL);
+			     bs_buf, bs_size);
 	if (ret)
 		return ret;
 
@@ -440,28 +415,13 @@
 {
 	int ret = 0;
 	unsigned int irq_status;
-	struct venc_frame_info frame_info;
 
 	mtk_vcodec_debug_enter(inst);
-	if (inst->frm_cnt == 0xFFFFFFFF) {
-		inst->frm_cnt = 0;
-		mtk_vcodec_debug(inst, "init frm_cnt to %d \n", inst->frm_cnt);
-	} else {
-		inst->frm_cnt++;
-		mtk_vcodec_debug(inst, "frm_cnt++ = %d \n ", inst->frm_cnt);
-	}
-	frame_info.frm_cnt = inst->frm_cnt;
-	frame_info.skip_frm_cnt = inst->skip_frm_cnt;
-	frame_info.frm_type = h264_frame_type(inst);
-	mtk_vcodec_debug(inst, "frm_cnt++ = %d,skip_frm_cnt =%d,frm_type=%d. \n",
-		frame_info.frm_cnt, frame_info.skip_frm_cnt,
-		frame_info.frm_type);
+
 	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf,
-			     bs_buf, bs_size, &frame_info);
-	if (ret) {
-		inst->frm_cnt--;
+			     bs_buf, bs_size);
+	if (ret)
 		return ret;
-	}
 
 	/*
 	 * skip frame case: The skip frame buffer is composed by vpu side only,
@@ -472,19 +432,19 @@
 		memcpy(bs_buf->va,
 		       inst->work_bufs[VENC_H264_VPU_WORK_BUF_SKIP_FRAME].va,
 		       *bs_size);
-		++inst->skip_frm_cnt;
+		++inst->frm_cnt;
 		return ret;
 	}
 
 	irq_status = h264_enc_wait_venc_done(inst);
 	if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
 		mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
-		inst->frm_cnt--;
 		return -EIO;
 	}
 
 	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
 
+	++inst->frm_cnt;
 	mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-",
 			 inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm);
 
@@ -507,7 +467,7 @@
 	memset(p, 0xff, size);
 }
 
-static int h264_enc_init(struct mtk_vcodec_ctx *ctx)
+static int h264_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle)
 {
 	int ret = 0;
 	struct venc_h264_inst *inst;
@@ -518,10 +478,9 @@
 
 	inst->ctx = ctx;
 	inst->vpu_inst.ctx = ctx;
-	inst->vpu_inst.id = SCP_IPI_VENC_H264;
+	inst->vpu_inst.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu_inst.id = IPI_VENC_H264;
 	inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS);
-	inst->frm_cnt = 0xFFFFFFFF;
-	mtk_v4l2_err("h264_enc_init =%d!!",IPI_VENC_H264);
 
 	mtk_vcodec_debug_enter(inst);
 
@@ -534,12 +493,12 @@
 	if (ret)
 		kfree(inst);
 	else
-		ctx->drv_handle = inst;
+		(*handle) = (unsigned long)inst;
 
 	return ret;
 }
 
-static int h264_enc_encode(void *handle,
+static int h264_enc_encode(unsigned long handle,
 			   enum venc_start_opt opt,
 			   struct venc_frm_buf *frm_buf,
 			   struct mtk_vcodec_mem *bs_buf,
@@ -634,13 +593,15 @@
 	return ret;
 }
 
-static int h264_enc_set_param(void *handle,
+static int h264_enc_set_param(unsigned long handle,
 			      enum venc_set_param_type type,
 			      struct venc_enc_param *enc_prm)
 {
 	int ret = 0;
 	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
 
+	mtk_vcodec_debug(inst, "->type=%d", type);
+
 	switch (type) {
 	case VENC_SET_PARAM_ENC:
 		inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
@@ -653,9 +614,9 @@
 		inst->vsi->config.framerate = enc_prm->frm_rate;
 		inst->vsi->config.intra_period = enc_prm->intra_period;
 		inst->vsi->config.profile =
-			h264_get_profile(inst, enc_prm->profile);
+			h264_get_profile(inst, enc_prm->h264_profile);
 		inst->vsi->config.level =
-			h264_get_level(inst, enc_prm->level);
+			h264_get_level(inst, enc_prm->h264_level);
 		inst->vsi->config.wfd = 0;
 		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
 		if (ret)
@@ -674,11 +635,7 @@
 		inst->prepend_hdr = 1;
 		mtk_vcodec_debug(inst, "set prepend header mode");
 		break;
-	case VENC_SET_PARAM_FORCE_INTRA:
-	case VENC_SET_PARAM_GOP_SIZE:
-	case VENC_SET_PARAM_INTRA_PERIOD:
-		inst->frm_cnt = 0xFFFFFFFF;
-		inst->skip_frm_cnt = 0;
+
 	default:
 		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
 		break;
@@ -689,7 +646,7 @@
 	return ret;
 }
 
-static int h264_enc_deinit(void *handle)
+static int h264_enc_deinit(unsigned long handle)
 {
 	int ret = 0;
 	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
old mode 100644
new mode 100755
index 1129caf..957420d
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
@@ -26,6 +26,7 @@
 #include "../venc_drv_base.h"
 #include "../venc_ipi_msg.h"
 #include "../venc_vpu_if.h"
+#include "mtk_vpu.h"
 
 #define VENC_BITSTREAM_FRAME_SIZE 0x0098
 #define VENC_BITSTREAM_HEADER_LEN 0x00e8
@@ -200,7 +201,7 @@
 		    i == VENC_VP8_VPU_WORK_BUF_RC_CODE3) {
 			void *tmp_va;
 
-			tmp_va = mtk_vcodec_fw_map_dm_addr(inst->vpu_inst.ctx->dev->ipi_msg_handle,
+			tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev,
 						     wb[i].vpua);
 			memcpy(inst->work_bufs[i].va, tmp_va, wb[i].size);
 		}
@@ -309,8 +310,7 @@
 
 	mtk_vcodec_debug(inst, "->frm_cnt=%d", inst->frm_cnt);
 
-	ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, bs_size,
-			     NULL);
+	ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, bs_size);
 	if (ret)
 		return ret;
 
@@ -332,7 +332,7 @@
 	return ret;
 }
 
-static int vp8_enc_init(struct mtk_vcodec_ctx *ctx)
+static int vp8_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle)
 {
 	int ret = 0;
 	struct venc_vp8_inst *inst;
@@ -343,6 +343,7 @@
 
 	inst->ctx = ctx;
 	inst->vpu_inst.ctx = ctx;
+	inst->vpu_inst.dev = ctx->dev->vpu_plat_dev;
 	inst->vpu_inst.id = IPI_VENC_VP8;
 	inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_LT_SYS);
 
@@ -357,12 +358,12 @@
 	if (ret)
 		kfree(inst);
 	else
-		ctx->drv_handle = inst;
+		(*handle) = (unsigned long)inst;
 
 	return ret;
 }
 
-static int vp8_enc_encode(void *handle,
+static int vp8_enc_encode(unsigned long handle,
 			  enum venc_start_opt opt,
 			  struct venc_frm_buf *frm_buf,
 			  struct mtk_vcodec_mem *bs_buf,
@@ -399,7 +400,7 @@
 	return ret;
 }
 
-static int vp8_enc_set_param(void *handle,
+static int vp8_enc_set_param(unsigned long handle,
 			     enum venc_set_param_type type,
 			     struct venc_enc_param *enc_prm)
 {
@@ -450,7 +451,7 @@
 	return ret;
 }
 
-static int vp8_enc_deinit(void *handle)
+static int vp8_enc_deinit(unsigned long handle)
 {
 	int ret = 0;
 	struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_base.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_base.h
old mode 100644
new mode 100755
index 95a1bf0..6308d44
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_base.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_base.h
@@ -28,7 +28,7 @@
 	 * @ctx:	[in] mtk v4l2 context
 	 * @handle: [out] driver handle
 	 */
-	int (*init)(struct mtk_vcodec_ctx *ctx);
+	int (*init)(struct mtk_vcodec_ctx *ctx, unsigned long *handle);
 
 	/**
 	 * (*encode)() - trigger encode
@@ -38,34 +38,25 @@
 	 * @bs_buf: [in] bitstream buffer to store output bitstream
 	 * @result: [out] encode result
 	 */
-	int (*encode)(void *handle, enum venc_start_opt opt,
+	int (*encode)(unsigned long handle, enum venc_start_opt opt,
 		      struct venc_frm_buf *frm_buf,
 		      struct mtk_vcodec_mem *bs_buf,
 		      struct venc_done_result *result);
 
 	/**
-	 * (*get_param)() - set driver's parameter
-	 * @handle: [in] driver handle
-	 * @type: [in] parameter type
-	 * @in: [in] buffer to store the parameter
-	 */
-	int (*get_param)(void *handle, enum venc_get_param_type type,
-					 void *out);
-
-	/**
 	 * (*set_param)() - set driver's parameter
 	 * @handle: [in] driver handle
 	 * @type: [in] parameter type
 	 * @in: [in] buffer to store the parameter
 	 */
-	int (*set_param)(void *handle, enum venc_set_param_type type,
+	int (*set_param)(unsigned long handle, enum venc_set_param_type type,
 			 struct venc_enc_param *in);
 
 	/**
 	 * (*deinit)() - deinitialize driver.
 	 * @handle: [in] driver handle
 	 */
-	int (*deinit)(void *handle);
+	int (*deinit)(unsigned long handle);
 };
 
 #endif
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.c
old mode 100644
new mode 100755
index b560d71..d02d5f1
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.c
@@ -1,6 +1,18 @@
-// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao@mediatek.com>
+ *	Jungchang Tsao <jungchang.tsao@mediatek.com>
+ *	Tiffany Lin <tiffany.lin@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License 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/interrupt.h>
@@ -12,38 +24,15 @@
 
 #include "mtk_vcodec_enc.h"
 #include "mtk_vcodec_enc_pm.h"
-
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-#include "mtk_vcu.h"
-const struct venc_common_if *get_enc_common_if(void);
-#endif
-
-#ifdef CONFIG_VIDEO_MEDIATEK_VPU
 #include "mtk_vpu.h"
+
 const struct venc_common_if *get_h264_enc_comm_if(void);
 const struct venc_common_if *get_vp8_enc_comm_if(void);
-#endif
 
 int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
 	int ret = 0;
 
-	ctx->oal_vcodec = 0;
-	ctx->slowmotion = 0;
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-	switch (fourcc) {
-	case V4L2_PIX_FMT_H264:
-	case V4L2_PIX_FMT_H265:
-	case V4L2_PIX_FMT_MPEG4:
-	case V4L2_PIX_FMT_H263:
-		ctx->enc_if = get_enc_common_if();
-		ctx->oal_vcodec = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-#endif
-#ifdef CONFIG_VIDEO_MEDIATEK_VPU
 	switch (fourcc) {
 	case V4L2_PIX_FMT_VP8:
 		ctx->enc_if = get_vp8_enc_comm_if();
@@ -54,45 +43,12 @@
 	default:
 		return -EINVAL;
 	}
-#endif
 
-	if (!ctx->oal_vcodec) {
-		mtk_venc_lock(ctx);
-		mtk_vcodec_enc_clock_on(&ctx->dev->pm);
-	}
-	ret = ctx->enc_if->init(ctx);
-	if (!ctx->oal_vcodec) {
-		mtk_vcodec_enc_clock_off(&ctx->dev->pm);
-		mtk_venc_unlock(ctx);
-	}
-	return ret;
-}
-int venc_if_get_param(struct mtk_vcodec_ctx *ctx, enum venc_get_param_type type,
-					  void *out)
-{
-	struct venc_inst *inst = NULL;
-	int ret = 0;
-	int drv_handle_exist = 1;
-
-	if (!ctx->drv_handle) {
-		inst = kzalloc(sizeof(struct venc_inst), GFP_KERNEL);
-		inst->ctx = ctx;
-		ctx->drv_handle = (void *)(inst);
-		#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-		ctx->enc_if = get_enc_common_if();
-		#endif
-		drv_handle_exist = 0;
-	}
-	if (!ctx->slowmotion)
-		mtk_venc_lock(ctx);
-	ret = ctx->enc_if->get_param(ctx->drv_handle, type, out);
-	if (!ctx->slowmotion)
-		mtk_venc_unlock(ctx);
-	if (!drv_handle_exist) {
-		kfree(inst);
-		ctx->drv_handle = 0;
-		ctx->enc_if = NULL;
-	}
+	mtk_venc_lock(ctx);
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
+	ret = ctx->enc_if->init(ctx, (unsigned long *)&ctx->drv_handle);
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+	mtk_venc_unlock(ctx);
 
 	return ret;
 }
@@ -102,39 +58,14 @@
 {
 	int ret = 0;
 
-	if (!ctx->oal_vcodec) {
-		mtk_venc_lock(ctx);
-		mtk_vcodec_enc_clock_on(&ctx->dev->pm);
-	}
+	mtk_venc_lock(ctx);
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
 	ret = ctx->enc_if->set_param(ctx->drv_handle, type, in);
-	if (!ctx->oal_vcodec) {
-		mtk_vcodec_enc_clock_off(&ctx->dev->pm);
-		mtk_venc_unlock(ctx);
-	}
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+	mtk_venc_unlock(ctx);
+
 	return ret;
 }
-void venc_encode_prepare(void *ctx_prepare, unsigned long *flags)
-{
-	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)ctx_prepare;
-
-	mtk_venc_lock(ctx);
-	spin_lock_irqsave(&ctx->dev->irqlock, *flags);
-	ctx->dev->curr_ctx = ctx;
-	spin_unlock_irqrestore(&ctx->dev->irqlock, *flags);
-	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
-}
-EXPORT_SYMBOL_GPL(venc_encode_prepare);
-void venc_encode_unprepare(void *ctx_unprepare, unsigned long *flags)
-{
-	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)ctx_unprepare;
-
-	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
-	spin_lock_irqsave(&ctx->dev->irqlock, *flags);
-	ctx->dev->curr_ctx = NULL;
-	spin_unlock_irqrestore(&ctx->dev->irqlock, *flags);
-	mtk_venc_unlock(ctx);
-}
-EXPORT_SYMBOL_GPL(venc_encode_unprepare);
 
 int venc_if_encode(struct mtk_vcodec_ctx *ctx,
 		   enum venc_start_opt opt, struct venc_frm_buf *frm_buf,
@@ -144,16 +75,22 @@
 	int ret = 0;
 	unsigned long flags;
 
-	if (ctx->oal_vcodec == 0 && ctx->slowmotion == 0)
+	mtk_venc_lock(ctx);
 
-		venc_encode_prepare(ctx, &flags);
+	spin_lock_irqsave(&ctx->dev->irqlock, flags);
+	ctx->dev->curr_ctx = ctx;
+	spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
 
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
 	ret = ctx->enc_if->encode(ctx->drv_handle, opt, frm_buf,
 				  bs_buf, result);
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
 
-	if (ctx->oal_vcodec == 0 && ctx->slowmotion == 0)
-		venc_encode_unprepare(ctx, &flags);
+	spin_lock_irqsave(&ctx->dev->irqlock, flags);
+	ctx->dev->curr_ctx = NULL;
+	spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
 
+	mtk_venc_unlock(ctx);
 	return ret;
 }
 
@@ -161,18 +98,15 @@
 {
 	int ret = 0;
 
-	if (!ctx->drv_handle)
+	if (ctx->drv_handle == 0)
 		return 0;
 
-	if (!ctx->oal_vcodec) {
-		mtk_venc_lock(ctx);
-		mtk_vcodec_enc_clock_on(&ctx->dev->pm);
-	}
+	mtk_venc_lock(ctx);
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
 	ret = ctx->enc_if->deinit(ctx->drv_handle);
-	if (!ctx->oal_vcodec) {
-		mtk_vcodec_enc_clock_off(&ctx->dev->pm);
-		mtk_venc_unlock(ctx);
-	}
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+	mtk_venc_unlock(ctx);
+
 	ctx->drv_handle = 0;
 
 	return ret;
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.h
old mode 100644
new mode 100755
index f6ed09b..a6e7d32
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_drv_if.h
@@ -20,10 +20,6 @@
 
 #include "mtk_vcodec_drv.h"
 #include "mtk_vcodec_util.h"
-#include "venc_ipi_msg.h"
-#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-#include "venc_vcu_if.h"
-#endif
 
 /*
  * enum venc_yuv_fmt - The type of input yuv format
@@ -33,17 +29,11 @@
  * @VENC_YUV_FORMAT_NV12: NV12 YUV format
  * @VENC_YUV_FORMAT_NV21: NV21 YUV format
  */
-struct venc_inst {
-	void __iomem *hw_base;
-	struct mtk_vcodec_mem pps_buf;
-	bool work_buf_allocated;
-	unsigned int frm_cnt;
-	unsigned int prepend_hdr;
-	#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCU)
-	struct venc_vcu_inst vcu_inst;
-	#endif
-	struct venc_vsi *vsi;
-	struct mtk_vcodec_ctx *ctx;
+enum venc_yuv_fmt {
+	VENC_YUV_FORMAT_I420 = 3,
+	VENC_YUV_FORMAT_YV12 = 5,
+	VENC_YUV_FORMAT_NV12 = 6,
+	VENC_YUV_FORMAT_NV21 = 7,
 };
 
 /*
@@ -54,6 +44,7 @@
 enum venc_start_opt {
 	VENC_START_OPT_ENCODE_SEQUENCE_HEADER,
 	VENC_START_OPT_ENCODE_FRAME,
+};
 
 /*
  * enum venc_set_param_type - The type of set parameter used in
@@ -69,7 +60,16 @@
  * @VENC_SET_PARAM_PREPEND_HEADER: set H264 prepend SPS/PPS before IDR
  * @VENC_SET_PARAM_TS_MODE: set VP8 temporal scalability mode
  */
-	VENC_START_OPT_ENCODE_FRAME_FINAL
+enum venc_set_param_type {
+	VENC_SET_PARAM_ENC,
+	VENC_SET_PARAM_FORCE_INTRA,
+	VENC_SET_PARAM_ADJUST_BITRATE,
+	VENC_SET_PARAM_ADJUST_FRAMERATE,
+	VENC_SET_PARAM_GOP_SIZE,
+	VENC_SET_PARAM_INTRA_PERIOD,
+	VENC_SET_PARAM_SKIP_FRAME,
+	VENC_SET_PARAM_PREPEND_HEADER,
+	VENC_SET_PARAM_TS_MODE,
 };
 
 /*
@@ -87,12 +87,27 @@
  * @bitrate: target bitrate in bps
  * @gop_size: group of picture size
  */
-
+struct venc_enc_param {
+	enum venc_yuv_fmt input_yuv_fmt;
+	unsigned int h264_profile;
+	unsigned int h264_level;
+	unsigned int width;
+	unsigned int height;
+	unsigned int buf_width;
+	unsigned int buf_height;
+	unsigned int frm_rate;
+	unsigned int intra_period;
+	unsigned int bitrate;
+	unsigned int gop_size;
+};
 
 /*
  * struct venc_frm_buf - frame buffer information used in venc_if_encode()
  * @fb_addr: plane frame buffer addresses
  */
+struct venc_frm_buf {
+	struct mtk_vcodec_mem fb_addr[MTK_VCODEC_MAX_PLANES];
+};
 
 /*
  * struct venc_done_result - This is return information used in venc_if_encode()
@@ -100,10 +115,8 @@
  * @is_key_frm: output is key frame or not
  */
 struct venc_done_result {
-	__u32 bs_size;
-	__u32 is_key_frm;
-	__u64 bs_va;
-	__u64 frm_va;
+	unsigned int bs_size;
+	bool is_key_frm;
 };
 
 /*
@@ -120,8 +133,6 @@
  * Return: 0 if releasing handle successfully, otherwise it is failed.
  */
 int venc_if_deinit(struct mtk_vcodec_ctx *ctx);
-int venc_if_get_param(struct mtk_vcodec_ctx *ctx, enum venc_get_param_type type,
-					  void *out);
 
 /*
  * venc_if_set_param - Set parameter to driver
@@ -149,6 +160,4 @@
 		   struct mtk_vcodec_mem *bs_buf,
 		   struct venc_done_result *result);
 
-void venc_encode_prepare(void *ctx_prepare, unsigned long *flags);
-void venc_encode_unprepare(void *ctx_unprepare, unsigned long *flags);
 #endif /* _VENC_DRV_IF_H_ */
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
old mode 100644
new mode 100755
index 272a33d..4c869cb
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
@@ -17,13 +17,9 @@
 
 #ifndef _VENC_IPI_MSG_H_
 #define _VENC_IPI_MSG_H_
-#include <linux/videodev2.h>
 
-#define MTK_MAX_ENC_CODECS_SUPPORT       (32)
 #define AP_IPIMSG_VENC_BASE 0xC000
 #define VPU_IPIMSG_VENC_BASE 0xD000
-#define VENC_MAX_FB_NUM              VIDEO_MAX_FRAME
-#define VENC_MAX_BS_NUM              VIDEO_MAX_FRAME
 
 /**
  * enum venc_ipi_msg_id - message id between AP and VPU
@@ -36,60 +32,13 @@
 	AP_IPIMSG_ENC_SET_PARAM,
 	AP_IPIMSG_ENC_ENCODE,
 	AP_IPIMSG_ENC_DEINIT,
-	AP_IPIMSG_ENC_QUERY_CAP,
 
 	VPU_IPIMSG_ENC_INIT_DONE = VPU_IPIMSG_VENC_BASE,
 	VPU_IPIMSG_ENC_SET_PARAM_DONE,
 	VPU_IPIMSG_ENC_ENCODE_DONE,
 	VPU_IPIMSG_ENC_DEINIT_DONE,
-	VPU_IPIMSG_ENC_QUERY_CAP_ACK,
-	VPU_IPIMSG_ENC_POWER_ON,
-	VPU_IPIMSG_ENC_POWER_OFF,
-	VPU_IPIMSG_ENC_WAIT_ISR,
-	VPU_IPIMSG_ENC_ENCODE_ACK
 };
 
-enum venc_get_param_type {
-	GET_PARAM_CAPABILITY_SUPPORTED_FORMATS,
-	GET_PARAM_CAPABILITY_FRAME_SIZES,
-	GET_PARAM_FREE_BUFFERS,
-	GET_PARAM_ROI_RC_QP
-};
-/*
- * enum venc_set_param_type - The type of set parameter used in
- *                                                    venc_if_set_param()
- * (VCU related: If you change the order, you must also update the VCU codes.)
- * @VENC_SET_PARAM_ENC: set encoder parameters
- * @VENC_SET_PARAM_FORCE_INTRA: force an intra frame
- * @VENC_SET_PARAM_ADJUST_BITRATE: adjust bitrate (in bps)
- * @VENC_SET_PARAM_ADJUST_FRAMERATE: set frame rate
- * @VENC_SET_PARAM_GOP_SIZE: set IDR interval
- * @VENC_SET_PARAM_INTRA_PERIOD: set I frame interval
- * @VENC_SET_PARAM_SKIP_FRAME: set H264 skip one frame
- * @VENC_SET_PARAM_PREPEND_HEADER: set H264 prepend SPS/PPS before IDR
- * @VENC_SET_PARAM_TS_MODE: set VP8 temporal scalability mode
- * @VENC_SET_PARAM_SCENARIO: set encoder scenario mode for different RC control
- * @VENC_SET_PARAM_NONREFP: set encoder non reference P period
- */
-enum venc_set_param_type {
-	VENC_SET_PARAM_ENC,
-	VENC_SET_PARAM_FORCE_INTRA,
-	VENC_SET_PARAM_ADJUST_BITRATE,
-	VENC_SET_PARAM_ADJUST_FRAMERATE,
-	VENC_SET_PARAM_GOP_SIZE,
-	VENC_SET_PARAM_INTRA_PERIOD,
-	VENC_SET_PARAM_SKIP_FRAME,
-	VENC_SET_PARAM_PREPEND_HEADER,
-	VENC_SET_PARAM_TS_MODE,
-	VENC_SET_PARAM_SCENARIO,
-	VENC_SET_PARAM_NONREFP,
-	VENC_SET_PARAM_DETECTED_FRAMERATE,
-	VENC_SET_PARAM_RFS_ON,
-	VENC_SET_PARAM_PREPEND_SPSPPS_TO_IDR,
-	VENC_SET_PARAM_OPERATION_RATE,
-	VENC_SET_PARAM_BITRATE_MODE,
-	VENC_SET_PARAM_ROI_ON
-};
 /**
  * struct venc_ap_ipi_msg_init - AP to VPU init cmd structure
  * @msg_id:	message id (AP_IPIMSG_XXX_ENC_INIT)
@@ -106,57 +55,6 @@
 };
 
 /**
- * struct venc_ap_ipi_query_cap - for AP_IPIMSG_ENC_QUERY_CAP
- * @msg_id        : AP_IPIMSG_ENC_QUERY_CAP
- * @id      : query capability type
- * @vdec_inst     : AP query data address
- */
-struct venc_ap_ipi_query_cap {
-	__u32 msg_id;
-	__u32 id;
-#ifndef CONFIG_64BIT
-	union {
-		__u64 ap_inst_addr_64;
-		__u32 ap_inst_addr;
-	};
-	union {
-		__u64 ap_data_addr_64;
-		__u32 ap_data_addr;
-	};
-#else
-	__u64 ap_inst_addr;
-	__u64 ap_data_addr;
-#endif
-};
-
-/**
- * struct venc_vcu_ipi_query_cap_ack - for VCU_IPIMSG_ENC_QUERY_CAP_ACK
- * @msg_id      : VCU_IPIMSG_ENC_QUERY_CAP_ACK
- * @status      : VCU exeuction result
- * @ap_data_addr   : AP query data address
- * @vcu_data_addr  : VCU query data address
- */
-struct venc_vcu_ipi_query_cap_ack {
-	__u32 msg_id;
-	__s32 status;
-#ifndef CONFIG_64BIT
-	union {
-		__u64 ap_inst_addr_64;
-		__u32 ap_inst_addr;
-	};
-	__u32 id;
-	union {
-		__u64 ap_data_addr_64;
-		__u32 ap_data_addr;
-	};
-#else
-	__u64 ap_inst_addr;
-	__u32 id;
-	__u64 ap_data_addr;
-#endif
-	__u32 vcu_data_addr;
-};
-/**
  * struct venc_ap_ipi_msg_set_param - AP to VPU set_param cmd structure
  * @msg_id:	message id (AP_IPIMSG_XXX_ENC_SET_PARAM)
  * @vpu_inst_addr:	VPU encoder instance addr
@@ -173,12 +71,6 @@
 	uint32_t data[8];
 };
 
-struct venc_ap_ipi_msg_set_param_ext {
-	struct venc_ap_ipi_msg_set_param base;
-	uint32_t data_ext[24];
-};
-
-
 /**
  * struct venc_ap_ipi_msg_enc - AP to VPU enc cmd structure
  * @msg_id:	message id (AP_IPIMSG_XXX_ENC_ENCODE)
@@ -193,21 +85,10 @@
 struct venc_ap_ipi_msg_enc {
 	uint32_t msg_id;
 	uint32_t vpu_inst_addr;
+	uint32_t bs_mode;
 	uint32_t input_addr[3];
-	uint32_t input_size[3];
 	uint32_t bs_addr;
 	uint32_t bs_size;
-	__u32 data_offset[3];
-	__s16 input_fd[3];
-	__s16 bs_fd;
-	__u8 fb_num_planes;
-	__u8 bs_mode;
-};
-
-struct venc_ap_ipi_msg_enc_ext {
-	struct venc_ap_ipi_msg_enc base;
-	uint32_t data_item;
-	uint32_t data[32];
 };
 
 /**
@@ -222,22 +103,6 @@
 };
 
 /**
- * struct venc_vcu_ipi_msg_waitisr - VCU ack AP wait isr cmd structure
- * @msg_id:   message id (VCU_IPIMSG_XXX_ENC_DEINIT_DONE)
- * @status:   cmd status (venc_ipi_msg_status)
- * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
- * @irq_status: encoder irq status
- * @timeout: 1 indicate encode timeout, 0 indicate no error
- */
-struct venc_vpu_ipi_msg_waitisr {
-	__u32 msg_id;
-	__s32 status;
-	__u64 venc_inst;
-	__u32 irq_status;
-	__u32 timeout;
-};
-
-/**
  * enum venc_ipi_msg_status - VPU ack AP cmd status
  */
 enum venc_ipi_msg_status {
@@ -251,7 +116,7 @@
  * @status:	cmd status (venc_ipi_msg_status)
  * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
  */
-struct venc_vcu_ipi_msg_common {
+struct venc_vpu_ipi_msg_common {
 	uint32_t msg_id;
 	uint32_t status;
 	uint64_t venc_inst;
@@ -268,7 +133,7 @@
  *		this reserved field, if kernel run in 64bit. this struct size
  *		will be different between kernel and vpu
  */
-struct venc_vcu_ipi_msg_init {
+struct venc_vpu_ipi_msg_init {
 	uint32_t msg_id;
 	uint32_t status;
 	uint64_t venc_inst;
@@ -285,7 +150,7 @@
  * @data_item:	number of items in the data array
  * @data[6]:	data array to store the return result
  */
-struct venc_vcu_ipi_msg_set_param {
+struct venc_vpu_ipi_msg_set_param {
 	uint32_t msg_id;
 	uint32_t status;
 	uint64_t venc_inst;
@@ -320,7 +185,7 @@
  *		this reserved field, if kernel run in 64bit. this struct size
  *		will be different between kernel and vpu
  */
-struct venc_vcu_ipi_msg_enc {
+struct venc_vpu_ipi_msg_enc {
 	uint32_t msg_id;
 	uint32_t status;
 	uint64_t venc_inst;
@@ -336,125 +201,10 @@
  * @status:   cmd status (venc_ipi_msg_status)
  * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
  */
-struct venc_vcu_ipi_msg_deinit {
+struct venc_vpu_ipi_msg_deinit {
 	uint32_t msg_id;
 	uint32_t status;
 	uint64_t venc_inst;
 };
 
-/*
- * struct venc_vcu_config - Structure for encoder configuration
- *                               AP-W/R : AP is writer/reader on this item
- *                               VCU-W/R: VCU is write/reader on this item
- * @input_fourcc: input fourcc
- * @bitrate: target bitrate (in bps)
- * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
- *         to be used for display purposes; must be smaller or equal to buffer
- *         size.
- * @pic_h: picture height
- * @buf_w: buffer width. Buffer size is stream resolution in pixels aligned to
- *         hardware requirements.
- * @buf_h: buffer height
- * @gop_size: group of picture size (idr frame)
- * @intra_period: intra frame period
- * @framerate: frame rate in fps
- * @profile: as specified in standard
- * @level: as specified in standard
- * @wfd: WFD mode 1:on, 0:off
- */
-struct venc_vcu_config {
-	__u32 input_fourcc;
-	__u32 bitrate;
-	__u32 pic_w;
-	__u32 pic_h;
-	__u32 buf_w;
-	__u32 buf_h;
-	__u32 gop_size;
-	__u32 intra_period;
-	__u32 framerate;
-	__u32 profile;
-	__u32 level;
-	__u32 wfd;
-	__u32 operationrate;
-	__u32 scenario;
-	__u32 prependheader;
-	__u32 bitratemode;
-	__u32 roi_rc_qp;
-	__u32 roion;
-};
-
-/**
- * enum venc_bs_mode - for bs_mode argument in venc_bs_mode
- */
-enum venc_bs_mode {
-	VENC_BS_MODE_SPS = 0,
-	VENC_BS_MODE_PPS,
-	VENC_BS_MODE_SEQ_HDR,
-	VENC_BS_MODE_FRAME,
-	VENC_BS_MODE_FRAME_FINAL,
-	VENC_BS_MODE_MAX
-};
-/**
- * struct venc_info - encode information
- * @bs_dma		: Input bit-stream buffer dma address
- * @bs_fd           : Input bit-stream buffer dmabuf fd
- * @fb_dma		    : Y frame buffer dma address
- * @fb_fd           : Y frame buffer dmabuf fd
- * @venc_bs_va		: VDEC bitstream buffer struct virtual address
- * @venc_fb_va		: VDEC frame buffer struct virtual address
- * @fb_num_planes	: frame buffer plane count
- * @reserved		: reserved variable for 64bit align
- */
-struct venc_info {
-	__u64 bs_dma;
-	__u64 bs_fd;
-	__u64 fb_dma[VIDEO_MAX_PLANES];
-	__u64 fb_fd[VIDEO_MAX_PLANES];
-	__u64 venc_bs_va;
-	__u64 venc_fb_va;
-	__u32 fb_num_planes;
-	__u32 index;
-	__u64 timestamp;
-	__u32 roimap;
-	__u32 reserved;
-};
-
-/**
- * struct ring_input_list - ring input buffer list
- * @venc_bs_va_list   : bitstream buffer arrary
- * @venc_fb_va_list   : frame buffer arrary
- * @read_idx  : read index
- * @write_idx : write index
- * @count     : buffer count in list
- */
-struct ring_input_list {
-	__u64 venc_bs_va_list[VENC_MAX_FB_NUM];
-	__u64 venc_fb_va_list[VENC_MAX_FB_NUM];
-	__u32 bs_size[VENC_MAX_FB_NUM];
-	__u32 is_key_frm[VENC_MAX_FB_NUM];
-	__s32 read_idx;
-	__s32 write_idx;
-	__s32 count;
-	__s32 reserved;
-};
-/*
- * struct venc_vsi - Structure for VCU driver control and info share
- *                        AP-W/R : AP is writer/reader on this item
- *                        VCU-W/R: VCU is write/reader on this item
- * This structure is allocated in VCU side and shared to AP side.
- * @config: h264 encoder configuration
- * @work_bufs: working buffer information in VCU side
- * The work_bufs here is for storing the 'size' info shared to AP side.
- * The similar item in struct venc_inst is for memory allocation
- * in AP side. The AP driver will copy the 'size' from here to the one in
- * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
- * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
- * register setting in VCU side.
- */
-struct venc_vsi {
-	struct venc_vcu_config config;
-	__u32  sizeimage[VIDEO_MAX_PLANES];
-	struct ring_input_list list_free;
-	struct venc_info       venc;
-};
 #endif /* _VENC_IPI_MSG_H_ */
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.c b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
old mode 100644
new mode 100755
index 8ad22f8..0d882ac
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  */
 
-#include "mtk_vcodec_fw.h"
+#include "mtk_vpu.h"
 #include "venc_ipi_msg.h"
 #include "venc_vpu_if.h"
 
@@ -22,7 +22,7 @@
 	struct venc_vpu_ipi_msg_init *msg = data;
 
 	vpu->inst_addr = msg->vpu_inst_addr;
-	vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->ipi_msg_handle, msg->vpu_inst_addr);
+	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
 }
 
 static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, void *data)
@@ -72,12 +72,12 @@
 
 	mtk_vcodec_debug_enter(vpu);
 
-	if (!vpu->ctx->dev->ipi_msg_handle) {
+	if (!vpu->dev) {
 		mtk_vcodec_err(vpu, "inst dev is NULL");
 		return -EINVAL;
 	}
 
-	status = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->ipi_msg_handle, vpu->id, msg, len, 2000);
+	status = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
 	if (status) {
 		mtk_vcodec_err(vpu, "vpu_ipi_send msg_id %x len %d fail %d",
 			       *(uint32_t *)msg, len, status);
@@ -102,9 +102,8 @@
 	vpu->signaled = 0;
 	vpu->failure = 0;
 
-	status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->ipi_msg_handle, vpu->id,
-		vpu_enc_ipi_handler, "venc", NULL);
-
+	status = vpu_ipi_register(vpu->dev, vpu->id, vpu_enc_ipi_handler,
+				  NULL, NULL);
 	if (status) {
 		mtk_vcodec_err(vpu, "vpu_ipi_register fail %d", status);
 		return -EINVAL;
@@ -123,85 +122,49 @@
 	return 0;
 }
 
-static unsigned int venc_enc_param_crop_right(struct venc_vpu_inst *vpu,
-					      struct venc_enc_param *enc_prm)
-{
-	unsigned int img_crop_right = enc_prm->buf_width - enc_prm->width;
-	if (img_crop_right > 16) {
-		img_crop_right -= 16;
-		if (img_crop_right > 16)
-			mtk_vcodec_err(vpu,  "input not supported crop %d\n",
-			enc_prm->buf_width - enc_prm->width);
-	} else if (img_crop_right == 16) {
-			img_crop_right = 0;
-	}
-
-	return img_crop_right;
-}
-
-static unsigned int venc_enc_param_crop_bottom(struct venc_enc_param *enc_prm) {
-	return (((enc_prm->height + 15) / 16) * 16) - enc_prm->height;
-}
-
-#define ROUND_16(X) (((X) + 0xF) & (~0xF))
-static unsigned int venc_enc_param_num_mb(struct venc_enc_param *enc_prm) {
-	return (ROUND_16(enc_prm->width) >> 4) * (ROUND_16(enc_prm->height) >> 4);
-}
-
 int vpu_enc_set_param(struct venc_vpu_inst *vpu,
 		      enum venc_set_param_type id,
 		      struct venc_enc_param *enc_param)
 {
-	const bool is_ext = vpu->ctx->dev->venc_pdata->uses_ext;
-	size_t msg_size = is_ext ?
-		sizeof(struct venc_ap_ipi_msg_set_param_ext) :
-		sizeof(struct venc_ap_ipi_msg_set_param);
-	struct venc_ap_ipi_msg_set_param_ext out;
+	struct venc_ap_ipi_msg_set_param out;
 
 	mtk_vcodec_debug(vpu, "id %d ->", id);
 
 	memset(&out, 0, sizeof(out));
-	out.base.msg_id = AP_IPIMSG_ENC_SET_PARAM;
-	out.base.vpu_inst_addr = vpu->inst_addr;
-	out.base.param_id = id;
+	out.msg_id = AP_IPIMSG_ENC_SET_PARAM;
+	out.vpu_inst_addr = vpu->inst_addr;
+	out.param_id = id;
 	switch (id) {
 	case VENC_SET_PARAM_ENC:
-		if (is_ext) {
-			out.base.data_item = 3;
-			out.base.data[0] = venc_enc_param_crop_right(vpu, enc_param);
-			out.base.data[1] = venc_enc_param_crop_bottom(enc_param);
-			out.base.data[2] = venc_enc_param_num_mb(enc_param);
-		} else {
-			out.base.data_item = 0;
-		}
+		out.data_item = 0;
 		break;
 	case VENC_SET_PARAM_FORCE_INTRA:
-		out.base.data_item = 0;
+		out.data_item = 0;
 		break;
 	case VENC_SET_PARAM_ADJUST_BITRATE:
-		out.base.data_item = 1;
-		out.base.data[0] = enc_param->bitrate;
+		out.data_item = 1;
+		out.data[0] = enc_param->bitrate;
 		break;
 	case VENC_SET_PARAM_ADJUST_FRAMERATE:
-		out.base.data_item = 1;
-		out.base.data[0] = enc_param->frm_rate;
+		out.data_item = 1;
+		out.data[0] = enc_param->frm_rate;
 		break;
 	case VENC_SET_PARAM_GOP_SIZE:
-		out.base.data_item = 1;
-		out.base.data[0] = enc_param->gop_size;
+		out.data_item = 1;
+		out.data[0] = enc_param->gop_size;
 		break;
 	case VENC_SET_PARAM_INTRA_PERIOD:
-		out.base.data_item = 1;
-		out.base.data[0] = enc_param->intra_period;
+		out.data_item = 1;
+		out.data[0] = enc_param->intra_period;
 		break;
 	case VENC_SET_PARAM_SKIP_FRAME:
-		out.base.data_item = 0;
+		out.data_item = 0;
 		break;
 	default:
 		mtk_vcodec_err(vpu, "id %d not supported", id);
 		return -EINVAL;
 	}
-	if (vpu_enc_send_msg(vpu, &out, msg_size)) {
+	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
 		mtk_vcodec_err(vpu,
 			       "AP_IPIMSG_ENC_SET_PARAM %d fail", id);
 		return -EINVAL;
@@ -215,45 +178,33 @@
 int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,
 		   struct venc_frm_buf *frm_buf,
 		   struct mtk_vcodec_mem *bs_buf,
-		   unsigned int *bs_size,
-		   struct venc_frame_info *frame_info)
+		   unsigned int *bs_size)
 {
-	const bool is_ext = vpu->ctx->dev->venc_pdata->uses_ext;
-	size_t msg_size = is_ext ?
-		sizeof(struct venc_ap_ipi_msg_enc_ext) :
-		sizeof(struct venc_ap_ipi_msg_enc);
-	struct venc_ap_ipi_msg_enc_ext out;
+	struct venc_ap_ipi_msg_enc out;
 
 	mtk_vcodec_debug(vpu, "bs_mode %d ->", bs_mode);
 
 	memset(&out, 0, sizeof(out));
-	out.base.msg_id = AP_IPIMSG_ENC_ENCODE;
-	out.base.vpu_inst_addr = vpu->inst_addr;
-	out.base.bs_mode = bs_mode;
+	out.msg_id = AP_IPIMSG_ENC_ENCODE;
+	out.vpu_inst_addr = vpu->inst_addr;
+	out.bs_mode = bs_mode;
 	if (frm_buf) {
 		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&
 		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&
 		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {
-			out.base.input_addr[0] = frm_buf->fb_addr[0].dma_addr;
-			out.base.input_addr[1] = frm_buf->fb_addr[1].dma_addr;
-			out.base.input_addr[2] = frm_buf->fb_addr[2].dma_addr;
+			out.input_addr[0] = frm_buf->fb_addr[0].dma_addr;
+			out.input_addr[1] = frm_buf->fb_addr[1].dma_addr;
+			out.input_addr[2] = frm_buf->fb_addr[2].dma_addr;
 		} else {
 			mtk_vcodec_err(vpu, "dma_addr not align to 16");
 			return -EINVAL;
 		}
 	}
 	if (bs_buf) {
-		out.base.bs_addr = bs_buf->dma_addr;
-		out.base.bs_size = bs_buf->size;
+		out.bs_addr = bs_buf->dma_addr;
+		out.bs_size = bs_buf->size;
 	}
-	if (is_ext && frame_info)
-	{
-		out.data_item = 3;
-		out.data[0] = frame_info->frm_cnt;
-		out.data[1] = frame_info->skip_frm_cnt;
-		out.data[2] = frame_info->frm_type;
-	}
-	if (vpu_enc_send_msg(vpu, &out, msg_size)) {
+	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
 		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_ENCODE %d fail",
 			       bs_mode);
 		return -EINVAL;
diff --git a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.h b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
old mode 100644
new mode 100755
index 638f9b1..215d1e0
--- a/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
+++ b/src/kernel/linux/v4.19/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
@@ -16,7 +16,7 @@
 #ifndef _VENC_VPU_IF_H_
 #define _VENC_VPU_IF_H_
 
-#include "mtk_vcodec_fw.h"
+#include "mtk_vpu.h"
 #include "venc_drv_if.h"
 
 /*
@@ -43,8 +43,9 @@
 	int is_key_frm;
 	unsigned int inst_addr;
 	void *vsi;
-	int id;
+	enum ipi_id id;
 	struct mtk_vcodec_ctx *ctx;
+	struct platform_device *dev;
 };
 
 int vpu_enc_init(struct venc_vpu_inst *vpu);
@@ -54,8 +55,7 @@
 int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,
 		   struct venc_frm_buf *frm_buf,
 		   struct mtk_vcodec_mem *bs_buf,
-		   unsigned int *bs_size,
-		   struct venc_frame_info *frame_info);
+		   unsigned int *bs_size);
 int vpu_enc_deinit(struct venc_vpu_inst *vpu);
 
 #endif
diff --git a/src/kernel/linux/v4.19/drivers/mfd/mt6330-irq.c b/src/kernel/linux/v4.19/drivers/mfd/mt6330-irq.c
old mode 100644
new mode 100755
index ddc045d..e223c36
--- a/src/kernel/linux/v4.19/drivers/mfd/mt6330-irq.c
+++ b/src/kernel/linux/v4.19/drivers/mfd/mt6330-irq.c
@@ -26,6 +26,7 @@
 	unsigned int sta_reg;
 	unsigned int sta_reg_shift;
 	unsigned int top_offset;
+	unsigned int top_mask_offset;
 };
 
 struct pmic_irq_data {
@@ -34,6 +35,8 @@
 	unsigned int reg_width;
 	unsigned short top_int_status_reg_l;
 	unsigned short top_int_status_reg_h;
+	unsigned short top_int_mask_set_reg;
+	unsigned short top_int_mask_clr_reg;
 	bool *enable_hwirq;
 	bool *cache_hwirq;
 	struct irq_top_t *pmic_ints;
@@ -203,8 +206,17 @@
 	if (!top_irq_status)
 		spmi_dump_spmimst_all_reg();
 	for (i = 0; i < irqd->num_top; i++) {
-		if (top_irq_status & BIT(irqd->pmic_ints[i].top_offset))
+		if (top_irq_status & BIT(irqd->pmic_ints[i].top_offset)) {
+			/* Mask top INT */
+			regmap_write(chip->regmap, irqd->top_int_mask_set_reg,
+				BIT(irqd->pmic_ints[i].top_mask_offset));
+
 			mt6330_irq_sp_handler(chip, i);
+
+			/* Umask top INT */
+			regmap_write(chip->regmap, irqd->top_int_mask_clr_reg,
+				BIT(irqd->pmic_ints[i].top_mask_offset));
+		}
 	}
 
 	return IRQ_HANDLED;
@@ -245,6 +257,8 @@
 	irqd->reg_width = MT6330_REG_WIDTH;
 	irqd->top_int_status_reg_l = MT6330_TOP_INT_STATUS0;
 	irqd->top_int_status_reg_h = MT6330_TOP_INT_STATUS1;
+	irqd->top_int_mask_set_reg = MT6330_TOP_INT_MASK_CON0_SET;
+	irqd->top_int_mask_clr_reg = MT6330_TOP_INT_MASK_CON0_CLR;
 	irqd->pmic_ints = mt6330_ints;
 
 	dev_info(chip->dev, "mt6330_irq_init +++\n");
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/Makefile b/src/kernel/linux/v4.19/drivers/misc/mediatek/Makefile
old mode 100644
new mode 100755
index 05f9404..5d0f05e
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/Makefile
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/Makefile
@@ -70,6 +70,7 @@
 obj-$(CONFIG_USB) += usb_boost/
 obj-$(CONFIG_MTK_ECCCI_C2K) += c2k_usb/
 obj-y +=eint_debug/
+obj-$(CONFIG_HSM_SUPPORT) += hsm/
 obj-y +=wakeup_gpio/
 #tianyan@2021.10.28 modify for DTR/RI gpio start
 obj-y += wakeup_dtr/
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic.c
index 0483cb7..7654c17 100755
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic.c
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic.c
@@ -242,43 +242,77 @@
 	.notifier_call = ipanic_die,
 };
 
+/********* patchback for compatible with 2735 LK *********/
+// mrdump_cb info from lk
+static unsigned long cbaddr, cbsize;
+static int __init mrdump_get_cb(char *p)
+{
+	int ret;
+
+	ret = sscanf(p, "0x%lx,0x%lx", &cbaddr, &cbsize);
+	if (ret != 2) {
+		pr_notice("%s: no mrdump_sram_cb. (ret=%d, p=%s)\n",
+				__func__, ret, p);
+	} else {
+		pr_notice("%s: mrdump_cbaddr=0x%lx, mrdump_cbsize=0x%lx\n",
+			__func__, cbaddr, cbsize);
+	}
+
+	return 0;
+}
+early_param("mrdump_cb", mrdump_get_cb);
+
+// ddr reserve flag from lk
+static char mrdump_lk_ddr_reserve_ready[4];
+
+static int __init mrdump_get_ddr_reserve_status(char *str)
+{
+	strlcpy(mrdump_lk_ddr_reserve_ready, str,
+			sizeof(mrdump_lk_ddr_reserve_ready));
+	return 0;
+}
+
+early_param("mrdump_ddrsv", mrdump_get_ddr_reserve_status);
+static bool mrdump_ddr_reserve_is_ready(void)
+{
+	if (strncmp(mrdump_lk_ddr_reserve_ready, "yes", 3) == 0)
+		return true;
+	else
+		return false;
+}
+
+static char mrdump_lk_version[12];
+static int __init mrdump_get_lk_version(char *str)
+{
+	strlcpy(mrdump_lk_version, str,
+			sizeof(mrdump_lk_version));
+	return 0;
+}
+
+early_param("mrdump.lk", mrdump_get_lk_version);
+/********* end patchback for compatible with 2735 LK *********/
+
 static __init int mrdump_parse_chosen(struct mrdump_params *mparams)
 {
-	struct device_node *node;
-	u32 reg[2];
-	const char *lkver, *ddr_rsv;
-
+	// 2735 lk pass parameters from kernel cmdline
 	memset(mparams, 0, sizeof(struct mrdump_params));
 
-	node = of_find_node_by_path("/chosen");
-	if (node) {
-		if (of_property_read_u32_array(node, "mrdump,cblock",
-					       reg, ARRAY_SIZE(reg)) == 0) {
-			mparams->cb_addr = reg[0];
-			mparams->cb_size = reg[1];
-			//pr_notice("%s: mrdump_cbaddr=%x, mrdump_cbsize=%x\n",
-			//	  __func__, mparams->cb_addr, mparams->cb_size);
-		}
+	mparams->cb_addr = (phys_addr_t)cbaddr;
+	mparams->cb_size = (phys_addr_t)cbsize;
+	pr_notice("%s: mrdump_cbaddr=0x%llx, mrdump_cbsize=0x%llx\n",
+			__func__, mparams->cb_addr, mparams->cb_size);
 
-		if (of_property_read_string(node, "mrdump,lk", &lkver) == 0) {
-			strlcpy(mparams->lk_version, lkver,
-				sizeof(mparams->lk_version));
-			pr_notice("%s: lk version %s\n", __func__, lkver);
-		}
+	strlcpy(mparams->lk_version, mrdump_lk_version,
+			sizeof(mparams->lk_version));
+	pr_notice("%s: lk version %s\n", __func__, mrdump_lk_version);
 
-		if (of_property_read_string(node, "mrdump,ddr_rsv",
-					    &ddr_rsv) == 0) {
-			if (strcmp(ddr_rsv, "yes") == 0)
-				mparams->drm_ready = true;
-			pr_notice("%s: ddr reserve mode %s\n", __func__,
-				  ddr_rsv);
-		}
-
-		return 0;
+	if (mrdump_ddr_reserve_is_ready()) {
+		mparams->drm_ready = true;
+		pr_notice("%s: ddr reserve mode %s\n", __func__,
+				mrdump_lk_ddr_reserve_ready);
 	}
-	of_node_put(node);
-	pr_notice("%s: Can't find chosen node\n", __func__);
-	return -1;
+
+	return 0;
 }
 
 static int __init mrdump_panic_init(void)
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic_wdt.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic_wdt.c
index 87c755c..a47de22 100755
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic_wdt.c
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/aee/mrdump/mrdump_panic_wdt.c
@@ -391,7 +391,7 @@
 #ifdef CONFIG_ARM64
 	int i;
 #endif
-	void *regs;
+	void *regs = NULL;
 	struct pt_regs pregs;
 	char zaplog[64] = {0};
 	int cpu = get_HW_cpuid();
@@ -430,6 +430,7 @@
 				(cpu * sizeof(struct atf_aee_regs)));
 
 #ifdef CONFIG_ARM64
+		pregs.orig_x0 = 0;
 		pregs.pstate = ((struct atf_aee_regs *)regs)->pstate;
 		pregs.pc = ((struct atf_aee_regs *)regs)->pc;
 		pregs.sp = ((struct atf_aee_regs *)regs)->sp;
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/eccci/port/port_sysmsg.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/eccci/port/port_sysmsg.c
old mode 100644
new mode 100755
index 231a543..2a11083
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/eccci/port/port_sysmsg.c
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/eccci/port/port_sysmsg.c
@@ -180,14 +180,30 @@
 	return 0;
 }
 
+#define MAX_THERMAL_MSG_NUM 15
+static int thermal_msg_count;  // log reduction
+
 static void sys_msg_handler(struct port_t *port, struct sk_buff *skb)
 {
 	struct ccci_header *ccci_h = (struct ccci_header *)skb->data;
 	int md_id = port->md_id;
 
-	CCCI_NORMAL_LOG(md_id, SYS, "system message (%x %x %x %x)\n",
-		ccci_h->data[0], ccci_h->data[1],
-		ccci_h->channel, ccci_h->reserved);
+	if (ccci_h->data[1] != MD_RF_MAX_TEMPERATURE_SUB6) {
+		CCCI_NORMAL_LOG(md_id, SYS, "system message (%x %x %x %x)\n",
+			ccci_h->data[0], ccci_h->data[1],
+			ccci_h->channel, ccci_h->reserved);
+	} else if (ccci_h->data[1] == MD_RF_MAX_TEMPERATURE_SUB6) {
+		if (thermal_msg_count < MAX_THERMAL_MSG_NUM) {
+			thermal_msg_count++;
+		} else {
+			CCCI_NORMAL_LOG(md_id, SYS,
+				"system message (%x %x %x %x) msg_count:%d\n",
+				ccci_h->data[0], ccci_h->data[1],
+				ccci_h->channel, ccci_h->reserved,
+				thermal_msg_count);
+			thermal_msg_count = 0;
+		}
+	}
 	switch (ccci_h->data[1]) {
 	case MD_WDT_MONITOR:
 		/* abandoned */
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/hsm/hsm.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/hsm/hsm.c
old mode 100644
new mode 100755
index 778112d..78857e2
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/hsm/hsm.c
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/hsm/hsm.c
@@ -74,15 +74,11 @@
 static int hsm_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
 	hsm_clock_off();
-	pm_runtime_put_sync(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
 	return 0;
 }
 
 static int hsm_resume(struct platform_device *pdev)
 {
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_sync(&pdev->dev);
 	hsm_reset();
 	hsm_clock_on();
 	return 0;
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/common/upmu.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/common/upmu.c
old mode 100644
new mode 100755
index 037d08f..51eb17d
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/common/upmu.c
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/common/upmu.c
@@ -83,7 +83,7 @@
 		pr_notice("[%s] regmap not ready\n", __func__);
 		return -ENODEV;
 	}
-	ret = regmap_update_bits(map, RegNum, (MASK << SHIFT), (val << SHIFT));
+	ret = regmap_write_bits(map, RegNum, (MASK << SHIFT), (val << SHIFT));
 	if (ret) {
 		dev_notice(chip->dev,
 			"[%s]ret=%d Reg=0x%x val=0x%x MASK=0x%x SHIFT=%d\n",
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/mt6330/v1/pmic_debugfs.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/mt6330/v1/pmic_debugfs.c
old mode 100644
new mode 100755
index 9efeda3..aa463be
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/mt6330/v1/pmic_debugfs.c
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/pmic/mt6330/v1/pmic_debugfs.c
@@ -219,21 +219,21 @@
 
 	PMICLOG("dump PMIC register\n");
 
-	for (i = 0; i < pFlag->offset; i = i + 10) {
+	for (i = 0; i < pFlag->offset; i = i + 5) {
 		pr_notice("Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x\n"
 			  , i, upmu_get_reg_value(i)
+			  , i + 1, upmu_get_reg_value(i + 1)
 			  , i + 2, upmu_get_reg_value(i + 2)
-			  , i + 4, upmu_get_reg_value(i + 4)
-			  , i + 6, upmu_get_reg_value(i + 6)
-			  , i + 8, upmu_get_reg_value(i + 8));
+			  , i + 3, upmu_get_reg_value(i + 3)
+			  , i + 4, upmu_get_reg_value(i + 4));
 		if (m != NULL) {
 			seq_printf(m,
 				"Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x\n"
 				, i, upmu_get_reg_value(i)
+				, i + 1, upmu_get_reg_value(i + 1)
 				, i + 2, upmu_get_reg_value(i + 2)
-				, i + 4, upmu_get_reg_value(i + 4)
-				, i + 6, upmu_get_reg_value(i + 6)
-				, i + 8, upmu_get_reg_value(i + 8));
+				, i + 3, upmu_get_reg_value(i + 3)
+				, i + 4, upmu_get_reg_value(i + 4));
 		}
 	}
 }
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Kconfig b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Kconfig
old mode 100644
new mode 100755
index 6bfe8d0..d0205ab
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Kconfig
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Kconfig
@@ -6,13 +6,4 @@
 	  with mediatek sensor architecture.
 	  If unsure, say N.
 
-config MTK_SENSOR_ARCHITECTURE
-	string "MTK SENSOR ARCHITECTURE"
-	default "dummy"
-	help
-	  Sensor config for sensor architecture in project.
-	  Please set 1.0/2.0/3.0 etc if you want to support sensor
-	  with mediatek sensor architecture.
-	  If unsure, set dummy.
-
-source "drivers/misc/mediatek/sensor/2.0/Kconfig"
+source "drivers/misc/mediatek/sensor/iio/Kconfig"
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Makefile b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Makefile
old mode 100644
new mode 100755
index 31c6d23..3bd9bfc
--- a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Makefile
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/Makefile
@@ -1 +1 @@
-obj-y += $(subst ",,$(CONFIG_MTK_SENSOR_ARCHITECTURE))/
+obj-y += iio/
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/Kconfig b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/Kconfig
new file mode 100755
index 0000000..5314271
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/Kconfig
@@ -0,0 +1,9 @@
+config MTK_BMP380_IIO_SUPPORT
+	bool "MTK_BMP380_IIO_SUPPORT for MediaTek package"
+	default n
+	help
+	  Enable MTK BMP380 IIO subsystem support.
+	  BMP380 is a low-power and low-noise
+	  barometric pressure sensor.
+	  If in doubt, say N here.
+
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/Makefile b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/Makefile
new file mode 100755
index 0000000..5d69b53
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_BMP380_IIO_SUPPORT) += bmp380_iio.o
diff --git a/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/bmp380_iio.c b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/bmp380_iio.c
new file mode 100755
index 0000000..28b0047
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/misc/mediatek/sensor/iio/bmp380_iio.c
@@ -0,0 +1,507 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+
+#define CHECK_CHIP_ID_TIME_MAX          0x05
+#define C_I2C_FIFO_SIZE                 0x08
+#define PRESSURE_SENSOR_NAME            "bmp380"
+#define BOSCH_BMP380_ID                 0x50
+
+#define BOSCH_BMP380_REG_RESET          0x7e
+#define BOSCH_BMP380_REG_DIG_T1         0x31
+#define BOSCH_BMP380_REG_ID             0x00
+#define BOSCH_BMP380_REG_CTRL_ODR       0x1d  //Control the Output Data Rate
+#define BOSCH_BMP380_REG_CTRL_OSR       0x1c  //Control the OverSampling
+#define BOSCH_BMP380_REG_CTRL_PWR       0x1b
+#define BOSCH_BMP380_REG_CONFIG         0x1f  //iir filter coefficents
+#define BOSCH_BMP380_REG_PRESS_LSB      0x04
+#define BOSCH_BMP380_REG_FIFO_WTM_1     0x16
+#define BOSCH_BMP380_REG_FIFO_WTM_0     0x15
+#define BOSCH_BMP380_REG_FIFO_CONFIG_1  0x17
+#define BOSCH_BMP380_REG_FIFO_CONFIG_2  0x18
+
+#define BOSCH_BMP380_GAIN_VALUE         100
+
+struct BMP380CompParams {
+	uint16_t par_t1;
+	uint16_t par_t2;
+	int8_t par_t3;
+
+	int16_t par_p1;
+	int16_t par_p2;
+	int8_t par_p3;
+	int8_t par_p4;
+	u16 par_p5;
+	u16 par_p6;
+	int8_t par_p7;
+	int8_t par_p8;
+	int16_t par_p9;
+	int8_t par_p10;
+	int8_t par_p11;
+	s64 t_lin;
+} __packed;
+
+struct bmp380_device_priv {
+	uint32_t i2c_num;
+	uint32_t i2c_addr;
+	struct i2c_client *client;
+	struct BMP380CompParams comp;
+	atomic_t raw_enable;
+};
+
+static const struct iio_chan_spec bmp380_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	},
+};
+
+
+/* I2C operation functions */
+static int bmp_i2c_read_block(struct i2c_client *client,
+				uint8_t addr, uint8_t *data, uint8_t len)
+{
+	int err = 0;
+	uint8_t beg = addr;
+	struct i2c_msg msgs[2] = {
+		{/*.addr = client->addr,*/
+		.flags = 0,
+		.len = 1,
+		.buf = &beg},
+		{
+			/*.addr = client->addr*/
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = data,
+		} };
+	if (!client)
+		return -EINVAL;
+	msgs[0].addr = client->addr;
+	msgs[1].addr = client->addr;
+
+	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (err != 2) {
+		pr_err_ratelimited("bmp380 i2c_trans err:%x %x (%d %p %d) %d\n",
+				msgs[0].addr, client->addr, addr, data, len,
+				err);
+		err = -EIO;
+	} else {
+		err = 0; /*no error*/
+	}
+	return err;
+}
+
+static int bmp_i2c_write_block(struct i2c_client *client,
+				uint8_t addr, uint8_t *data, uint8_t len)
+{
+	/* because address also occupies one byte,
+	 * the maximum length for write is 7 bytes
+	 */
+	int err = 0, idx = 0, num = 0;
+	char buf[32];
+
+	if (!client)
+		return -EINVAL;
+	else if (len > C_I2C_FIFO_SIZE) {
+		pr_err_ratelimited("bmp380 len %d fi %d\n", len,
+				   C_I2C_FIFO_SIZE);
+		return -EINVAL;
+	}
+	buf[num++] = addr;
+	for (idx = 0; idx < len; idx++)
+		buf[num++] = data[idx];
+
+	err = i2c_master_send(client, buf, num);
+	if (err < 0) {
+		pr_err_ratelimited("bmp380 send command error!!\n");
+		return -EFAULT;
+	}
+
+	return err;
+}
+
+static int bmp380_soft_reset(struct i2c_client *client)
+{
+	uint8_t data = 0xb6;
+
+	return bmp_i2c_write_block(client, BOSCH_BMP380_REG_RESET, &data, 1);
+}
+
+static int bmp380_check_chip_id(struct i2c_client *client)
+{
+	int err = -1;
+	uint8_t chip_id = 0;
+	uint8_t read_count = 0;
+
+	while (read_count++ < CHECK_CHIP_ID_TIME_MAX) {
+		bmp_i2c_read_block(client, BOSCH_BMP380_REG_ID,
+				   &chip_id, 1);
+
+		if (chip_id != BOSCH_BMP380_ID) {
+			mdelay(1);
+			pr_err("%s fail(0x%2x).\n",
+				__func__, chip_id);
+		} else {
+			err = 0;
+			pr_info("%s success(0x%2x).\n",
+				__func__, chip_id);
+			break;
+		}
+	}
+	return err;
+}
+
+static int bmp380_init_device(struct i2c_client *client,
+		struct bmp380_device_priv *priv)
+{
+	int err = -1;
+	uint8_t tx_buf[2] = {0};
+	uint8_t rx_buf[8] = {0};
+
+	err = bmp380_soft_reset(client);
+	if (err < 0) {
+		pr_err("bmp380 soft reset fail,exit probe!\n");
+		goto i2c_fail;
+	}
+
+	mdelay(2);
+
+	tx_buf[0] = BOSCH_BMP380_REG_DIG_T1;
+	err = bmp_i2c_read_block(client, tx_buf[0], rx_buf, 0x08);
+	if (err < 0) {
+		pr_err("bmp380 read block BOSCH_BMP380_REG_DIG_T1 fail\n");
+		goto i2c_fail;
+	}
+	memcpy((uint8_t *)&priv->comp, rx_buf, 8);
+
+	tx_buf[0] = BOSCH_BMP380_REG_DIG_T1 + 8;
+	err = bmp_i2c_read_block(client, tx_buf[0], rx_buf, 0x08);
+	if (err < 0) {
+		pr_err("bmp380 read block BOSCH_BMP380_REG_DIG_T1+8 fail\n");
+		goto i2c_fail;
+	}
+	memcpy((uint8_t *)((uint8_t *)&priv->comp + 8), rx_buf, 8);
+
+	tx_buf[0] = BOSCH_BMP380_REG_DIG_T1 + 16;
+	err = bmp_i2c_read_block(client, tx_buf[0], rx_buf, 0x05);
+	if (err < 0) {
+		pr_err("bmp380 read block BOSCH_BMP380_REG_DIG_T1+16 fail\n");
+		goto i2c_fail;
+	}
+	memcpy((uint8_t *)((uint8_t *)&priv->comp + 16), rx_buf, 5);
+
+	//config oversampling: baro:16x, temp:2x
+	tx_buf[0] = ((4 << 3) | (1 << 0));
+	err = bmp_i2c_write_block(client, BOSCH_BMP380_REG_CTRL_OSR,
+				  tx_buf, 0x01);
+	if (err < 0)
+		pr_err("bmp380 write block BOSCH_BMP380_REG_CTRL_OSR fail!\n");
+
+	tx_buf[0] = 4;//config standy time: 62.5ms
+	err = bmp_i2c_write_block(client, BOSCH_BMP380_REG_CTRL_ODR,
+				  tx_buf, 0x01);
+	if (err < 0) {
+		pr_err("bmp380 write block BOSCH_BMP380_REG_CTRL_ODR fail!\n");
+		goto i2c_fail;
+	}
+
+i2c_fail:
+	return err;
+}
+
+static int64_t compensate_temp(struct bmp380_device_priv *priv,
+				uint32_t uncomp_temp)
+{
+
+	uint64_t partial_data1;
+	uint64_t partial_data2;
+	uint64_t partial_data3;
+	int64_t partial_data4;
+	int64_t partial_data5;
+	int64_t partial_data6;
+	int64_t comp_temp;
+
+	partial_data1 = uncomp_temp - (256 * priv->comp.par_t1);
+	partial_data2 = priv->comp.par_t2 * partial_data1;
+	partial_data3 = partial_data1 * partial_data1;
+	partial_data4 = (int64_t)partial_data3 * priv->comp.par_t3;
+	partial_data5 = ((int64_t)(partial_data2 * 262144) + partial_data4);
+	partial_data6 = partial_data5 / 4294967296;
+	priv->comp.t_lin = partial_data6;
+	comp_temp = (int64_t)((partial_data6 * 25) / 16384);
+
+	//return the tempeature in the unit of 0.01 centigrade.
+	return comp_temp;
+}
+
+static int64_t compensate_baro(struct bmp380_device_priv *priv,
+					uint32_t uncomp_press)
+{
+	int64_t partial_data1;
+	int64_t partial_data2;
+	int64_t partial_data3;
+	int64_t partial_data4;
+	int64_t partial_data5;
+	int64_t partial_data6;
+	int64_t offset;
+	int64_t sensitivity;
+	uint64_t comp_press;
+
+	partial_data1 = priv->comp.t_lin * priv->comp.t_lin;
+	partial_data2 = partial_data1 / 64;
+	partial_data3 = (partial_data2 * priv->comp.t_lin) / 256;
+	partial_data4 = (priv->comp.par_p8 * partial_data3) / 32;
+	partial_data5 = (priv->comp.par_p7 * partial_data1) * 16;
+	partial_data6 = (priv->comp.par_p6 * priv->comp.t_lin)
+		* 4194304;
+	offset = (priv->comp.par_p5 * 140737488355328) + partial_data4
+		+ partial_data5 + partial_data6;
+
+	partial_data2 = (priv->comp.par_p4 * partial_data3) / 32;
+	partial_data4 = (priv->comp.par_p3 * partial_data1) * 4;
+	partial_data5 = (priv->comp.par_p2 - 16384)
+		* priv->comp.t_lin * 2097152;
+	sensitivity = ((priv->comp.par_p1 - 16384) * 70368744177664)
+		+ partial_data2 + partial_data4	+ partial_data5;
+
+	partial_data1 = (sensitivity / 16777216) * uncomp_press;
+	partial_data2 = priv->comp.par_p10 * priv->comp.t_lin;
+	partial_data3 = partial_data2 + (65536 * priv->comp.par_p9);
+	partial_data4 = (partial_data3 * uncomp_press) / 8192;
+	partial_data5 = (partial_data4 * uncomp_press / 10) / 512 * 10;
+	partial_data6 = (int64_t)((uint64_t)uncomp_press
+		* (uint64_t)uncomp_press);
+	partial_data2 = (priv->comp.par_p11 * partial_data6) / 65536;
+	partial_data3 = (partial_data2 * uncomp_press) / 128;
+	partial_data4 = (offset / 4) + partial_data1 + partial_data5
+		+ partial_data3;
+	comp_press = (((uint64_t)partial_data4 * 25)
+		/ (uint64_t)1099511627776);
+
+	//return the press in the unit of the 0.01 Pa.
+	return comp_press;
+}
+
+static int bmp_get_pressure(struct bmp380_device_priv *priv, s32 *p_buf)
+{
+	uint32_t press_adc;
+	uint32_t temp_adc;
+	int ret = 0;
+	uint32_t data_xlsb;
+	uint32_t data_lsb;
+	uint32_t data_msb;
+	uint8_t tx_buf[1] = {0};
+	uint8_t rx_buf[6] = {0};
+	int64_t temp = 0, press = 0;
+	struct i2c_client *client = priv->client;
+
+	tx_buf[0] = BOSCH_BMP380_REG_PRESS_LSB;
+	ret = bmp_i2c_read_block(client, tx_buf[0], rx_buf, 6);
+	if (ret < 0) {
+		pr_err("%s failed\n", __func__);
+		return ret;
+	}
+
+	data_xlsb = (uint32_t)rx_buf[0];
+	data_lsb = (uint32_t)rx_buf[1] << 8;
+	data_msb = (uint32_t)rx_buf[2] << 16;
+	press_adc  = data_msb | data_lsb | data_xlsb;
+
+	data_xlsb = (uint32_t)rx_buf[3];
+	data_lsb = (uint32_t)rx_buf[4] << 8;
+	data_msb = (uint32_t)rx_buf[5] << 16;
+	temp_adc = data_msb | data_lsb | data_xlsb;
+
+	temp = compensate_temp(priv, temp_adc);
+	press = compensate_baro(priv, press_adc);
+	*p_buf = (s32)press * BOSCH_BMP380_GAIN_VALUE / 10000;
+
+	return 0;
+}
+
+static int bmp380_sample(struct bmp380_device_priv *priv)
+{
+	s32 value = 0;
+	int err = 0;
+
+	if (!priv) {
+		pr_err("bmp380 sample failed:invalid bmp380_device_priv\n");
+		return -1;
+	}
+
+	err = bmp_get_pressure(priv, &value);
+	if (err) {
+		pr_err("bmp_get_pressure failed\n");
+		return err;
+	}
+
+	//pr_info("%s successfully get sample: %d\n", __func__, value);
+	return value;
+}
+
+static int bmp380_enable(struct bmp380_device_priv *priv, int en)
+{
+	int ret = 0;
+	struct i2c_client *client;
+	uint8_t tx_buf[1] = {0};
+	int retry = 0;
+
+	client = priv->client;
+
+	if (en)
+		tx_buf[0] = (3 << 4 | 1 << 1 | 1 << 0);
+	else
+		tx_buf[0] = (2 << 5 | 5 << 2);
+
+	for (retry = 0; retry < 3; retry++) {
+		ret = bmp_i2c_write_block(client,
+					BOSCH_BMP380_REG_CTRL_PWR,
+					tx_buf, 0x01);
+		if (ret >= 0) {
+			pr_debug("%s (%d) done(retry:%d)\n", __func__,
+				en, retry);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int bmp380_read_raw(struct iio_dev *indio_dev,
+			 struct iio_chan_spec const *chan,
+			 int *val, int *val2, long mask)
+{
+	struct bmp380_device_priv *priv = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			bmp380_enable(priv, 1);
+			*val = bmp380_sample(priv);
+			bmp380_enable(priv, 0);
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info bmp380_info = {
+	.read_raw   = &bmp380_read_raw,
+};
+
+static int bmp380_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int err = 0;
+	struct device *dev = &client->dev;
+	struct iio_dev *indio_dev;
+	struct bmp380_device_priv *priv;
+	int ret;
+
+	err = bmp380_check_chip_id(client);
+	if (err < 0) {
+		pr_err("bmp380 chip id mismatch,exit probe!\n");
+		goto findHW_fail;
+	}
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+	if (!indio_dev) {
+		err = -ENOMEM;
+		goto malloc_fail;
+	}
+
+	priv = iio_priv(indio_dev);
+	priv->client = client;
+
+	indio_dev->dev.parent = dev;
+	indio_dev->name = id->name;
+	indio_dev->channels = bmp380_channels;
+	indio_dev->num_channels = ARRAY_SIZE(bmp380_channels);
+	indio_dev->info = &bmp380_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(dev, "Failed to register IIO device\n");
+		goto init_fail;
+	}
+
+	i2c_set_clientdata(client, indio_dev);
+
+	err = bmp380_init_device(client, priv);
+	if (err < 0) {
+		pr_err("%s fail\n", __func__);
+		goto init_fail;
+	}
+
+	bmp380_enable(priv, 1);
+	ret = bmp380_sample(priv);
+	bmp380_enable(priv, 0);
+
+	pr_info("%s success! Pressure value: %d\n", __func__, ret);
+	return 0;
+
+init_fail:
+//create_manager_fail:
+	kfree(indio_dev);
+malloc_fail:
+findHW_fail:
+	pr_err("%s fail!\n", __func__);
+	return err;
+}
+
+static int bmp380_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	kfree(indio_dev);
+	return 0;
+}
+
+static const struct i2c_device_id bmp380_id[] = {
+	{PRESSURE_SENSOR_NAME, 0},
+	{},
+};
+
+static const struct of_device_id bmp380_of_match[] = {
+	{.compatible = "mediatek,barometer"},
+	{},
+};
+
+static struct i2c_driver bmp380_driver = {
+	.driver = {
+		.name = PRESSURE_SENSOR_NAME,
+		.bus = &i2c_bus_type,
+		.owner = THIS_MODULE,
+		.of_match_table = bmp380_of_match,
+	},
+	.probe = bmp380_probe,
+	.remove = bmp380_remove,
+	.id_table = bmp380_id
+};
+
+module_i2c_driver(bmp380_driver);
+
+MODULE_DESCRIPTION("bmp380 driver");
+MODULE_AUTHOR("Mediatek");
+MODULE_LICENSE("GPL");
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/Kconfig b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/Kconfig
old mode 100644
new mode 100755
index e90930a..eed09a4
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/Kconfig
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/Kconfig
@@ -26,3 +26,23 @@
 	depends on ARCH_MEDIATEK
 	---help---
 	  Customer special config for multicast ODU support
+
+config MTK_SGMII_NETSYS
+	bool "sgmii for netsys"
+	default n
+	help
+	  Set the PHY sgmii for netsys
+
+	  This selects the sgmii as Netsys ethernet driver
+	  interface. SNPS ethernet driver can only use rgmii
+	  with this configuration.
+
+config MTK_SGMII_SNPS
+	bool "sgmii for snps"
+	default n
+	help
+	  Set the PHY sgmii for snps
+
+	  This selects the sgmii as SNPS ethernet driver
+	  interface. Netsys ethernet driver can only use
+	  another sgmii with this configuration.
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c
old mode 100644
new mode 100755
index 3a3242b..10a6735
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c
@@ -661,7 +661,7 @@
 	ring->data = kcalloc(rx_dma_size, sizeof(*ring->data),
 			     GFP_KERNEL);
 	if (!ring->data) {
-		//pr_info("%s: kcalloc error\n", __func__);
+		pr_info("%s: kcalloc error\n", __func__);
 		return -ENOMEM;
 	}
 
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 2afe494..9a98183 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -31,19 +31,27 @@
 
 void mt7530_mdio_w32(struct mtk_eth *eth, u32 reg, u32 val)
 {
+	mutex_lock(&eth->mii_bus->mdio_lock);
+
 	_mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
 	_mtk_mdio_write(eth, 0x1f, (reg >> 2) & 0xf,  val & 0xffff);
 	_mtk_mdio_write(eth, 0x1f, 0x10, val >> 16);
+
+	mutex_unlock(&eth->mii_bus->mdio_lock);
 }
 
 u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
 {
 	u16 high, low;
 
+	mutex_lock(&eth->mii_bus->mdio_lock);
+
 	_mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
 	low = _mtk_mdio_read(eth, 0x1f, (reg >> 2) & 0xf);
 	high = _mtk_mdio_read(eth, 0x1f, 0x10);
 
+	mutex_unlock(&eth->mii_bus->mdio_lock);
+
 	return (high << 16) | (low & 0xffff);
 }
 
@@ -351,21 +359,27 @@
 void mii_mgr_read_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register,
 			  u32 *read_data)
 {
-	if (mt7530_exist(eth) && phy_addr == 31)
+	if (mt7530_exist(eth) && phy_addr == 31) {
 		*read_data = mt7530_mdio_r32(eth, phy_register);
 
-	else
+	} else {
+		mutex_lock(&eth->mii_bus->mdio_lock);
 		*read_data = _mtk_mdio_read(eth, phy_addr, phy_register);
+		mutex_unlock(&eth->mii_bus->mdio_lock);
+	}
 }
 
 void mii_mgr_write_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register,
 			   u32 write_data)
 {
-	if (mt7530_exist(eth) && phy_addr == 31)
+	if (mt7530_exist(eth) && phy_addr == 31) {
 		mt7530_mdio_w32(eth, phy_register, write_data);
 
-	else
+	} else {
+		mutex_lock(&eth->mii_bus->mdio_lock);
 		_mtk_mdio_write(eth, phy_addr, phy_register, write_data);
+		mutex_unlock(&eth->mii_bus->mdio_lock);
+	}
 }
 
 static void mii_mgr_read_cl45(struct mtk_eth *eth, u32 port, u32 devad, u32 reg, u32 *data)
@@ -585,10 +599,10 @@
 	u32 i, j;
 
 	seq_puts(seq, "		<<SCH CONFIG>>\n");
-	seq_printf(seq, "SCH1_SCH2:\t0x%08x\n",
+	seq_printf(seq, "SCH1 2:0x%08x\n",
 		   mtk_r32(eth, MTK_QDMA_TX_SCH1_SCH2));
-	seq_printf(seq, "SCH3_SCH4:\t0x%08x\n",
-		   mtk_r32(eth, MTK_QDMA_TX_SCH1_SCH2));
+	seq_printf(seq, "SCH3 4:0x%08x\n",
+		   mtk_r32(eth, MTK_QDMA_TX_SCH3_SCH4));
 
 	mtk_w32(eth, 0, MTK_QDMA_SEL);
 	seq_puts(seq, "		<<TXQ SCH>>\n");
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_path.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_path.c
index a5cf48d..4a3942d 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -236,7 +236,7 @@
 
 	/* Setup SGMIISYS with the determined property */
 	if (MTK_HAS_FLAGS(eth->sgmii->flags[sid], MTK_SGMII_PHYSPEED_AN))
-		err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
+		err = mtk_sgmii_setup_mode_an(eth->sgmii, sid, eth);
 	else
 		err = mtk_sgmii_setup_mode_force(eth->sgmii, sid, eth);
 
@@ -245,7 +245,6 @@
 
 	regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
 			   SYSCFG0_SGMII_MASK, 0x3 << 8);
-			   
 
 	return 0;
 }
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index e634475..cd34f12 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -65,6 +65,64 @@
 	"wed_mcu_sel", "net_2x_sel", "sgmii_sel", "sgmii_sbus_sel",
 };
 
+#if defined(CONFIG_HW_NAT)
+static struct net_device *mtk_fast_path[MAX_IF_NUM] = {0};
+
+/* The fast paths transmit skb to PPE via Netsys eth.
+ * We register them to HWNAT module only when at least one Netsys eth is up.
+ * Confirm the fast paths were hooked before Netsys eth goes up.
+ */
+
+void mtk_hook_fast_path(struct net_device *dev)
+{
+	int i = 0;
+
+	for (i = 0; i < MAX_IF_NUM; i++) {
+		if (mtk_fast_path[i] == dev) {
+			pr_notice("%s : %s fast path hooked(%d)\n",
+				  __func__, dev->name, i);
+			return;
+		}
+		if (!mtk_fast_path[i]) {
+			mtk_fast_path[i] = dev;
+			pr_notice("%s : %s fast path(%d)\n",
+				  __func__, dev->name, i);
+			return;
+		}
+	}
+}
+
+static void mtk_register_fast_path(void)
+{
+	int i = 0;
+
+	if (ppe_dev_register_hook) {
+		for (i = 0; i < MAX_IF_NUM; i++) {
+			if (mtk_fast_path[i]) {
+				ppe_dev_register_hook(mtk_fast_path[i]);
+				pr_notice("%s : %s fast path(%d)",
+					  __func__, mtk_fast_path[i]->name, i);
+			}
+		}
+	}
+}
+
+static void mtk_unregister_fast_path(void)
+{
+	int i = 0;
+
+	if (ppe_dev_register_hook) {
+		for (i = 0; i < MAX_IF_NUM; i++) {
+			if (mtk_fast_path[i]) {
+				ppe_dev_unregister_hook(mtk_fast_path[i]);
+				pr_notice("%s : %s fast path(%d)",
+					  __func__, mtk_fast_path[i]->name, i);
+			}
+		}
+	}
+}
+#endif
+
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
 {
 	__raw_writel(val, eth->base + reg);
@@ -281,12 +339,19 @@
 		return;
 
 	switch (dev->phydev->speed) {
+	case SPEED_2500:
 	case SPEED_1000:
 		mcr |= MAC_MCR_SPEED_1000;
 		break;
 	case SPEED_100:
 		mcr |= MAC_MCR_SPEED_100;
 		break;
+	case SPEED_10: // bit[3:2] is 0
+		break;
+	default:
+		netif_dbg(mac->hw, link, dev, "unsupported speed %d\n",
+			  dev->phydev->speed);
+		break;
 	};
 
 	if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
@@ -320,10 +385,13 @@
 			  flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
 			  flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
 	}
-	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
-	mtk_w32(mac->hw, 0x0104f33b, MTK_MAC_MCR(0));
-	mtk_w32(mac->hw, 0x0104e33b, MTK_MAC_MCR(1));
+	if (MTK_HAS_FLAGS(mac->hw->sgmii->flags[mac->id],
+			  MTK_SGMII_PHYSPEED_AN))
+		mcr = 0x21057300;
+
+	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+	pr_notice("mac %d MAC_MCR = %x\n", mac->id, mcr);
 
 	if (dev->phydev->link)
 		netif_carrier_on(dev);
@@ -374,6 +442,10 @@
 	if (!np && of_phy_is_fixed_link(mac->of_node))
 		if (!of_phy_register_fixed_link(mac->of_node))
 			np = of_node_get(mac->of_node);
+
+	if (!np)
+		np = of_node_get(mac->of_node);
+
 	if (!np)
 		return -ENODEV;
 
@@ -443,6 +515,15 @@
 	return -EINVAL;
 }
 
+static void mtk_phy_disconnect(struct net_device *dev)
+{
+	struct mtk_mac *mac = netdev_priv(dev);
+
+	phy_disconnect(dev->phydev);
+	if (of_phy_is_fixed_link(mac->of_node))
+		of_phy_deregister_fixed_link(mac->of_node);
+}
+
 static int mtk_mdio_init(struct mtk_eth *eth)
 {
 	struct device_node *mii_np;
@@ -642,7 +723,6 @@
 		hw_stats->tx_bytes += (stats << 32);
 	hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
 	u64_stats_update_end(&hw_stats->syncp);
-
 }
 
 static void mtk_stats_update(struct mtk_eth *eth)
@@ -818,9 +898,8 @@
 
 	itxd = ring->next_free;
 
-	if (itxd == ring->last_free) {
+	if (itxd == ring->last_free)
 		return -ENOMEM;
-	}
 
 	/* set the forward port */
 	fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
@@ -876,6 +955,7 @@
 	/* TX SG offload */
 	txd = itxd;
 	nr_frags = skb_shinfo(skb)->nr_frags;
+
 	for (i = 0; i < nr_frags; i++) {
 		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
 		unsigned int offset = 0;
@@ -1108,7 +1188,10 @@
 	struct mtk_rx_ring *ring;
 	int i;
 
-	if (eth->hwlro) {
+	if (!eth->hwlro) {
+		ring = &eth->rx_ring[0];
+		mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
+	} else {
 		for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
 			ring = &eth->rx_ring[i];
 			if (ring->calc_idx_update) {
@@ -1116,9 +1199,6 @@
 				mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
 			}
 		}
-	} else {
-		ring = &eth->rx_ring[0];
-		mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
 	}
 }
 
@@ -1156,8 +1236,9 @@
 		mac--;
 
 #if defined(CONFIG_HW_NAT)
+		/* fast path FP is QDMA. default uses mac1(eth0) */
 		if (mac > 1)
-			mac = 1;
+			mac = netif_running(eth->netdev[1]) ? 1 : 0;
 #endif
 		if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
 			     !eth->netdev[mac]))
@@ -1977,11 +2058,11 @@
 	int tx_done = 0;
 
 	mtk_handle_status_irq(eth);
-	mtk_w32(eth, MTK_TX_DONE_INT | MTK_TX_DONE_INT0, MTK_QMTK_INT_STATUS);
+	mtk_w32(eth, MTK_TX_DONE_INT | MTK_TX_DONE_INT0, MTK_QDMA_INT_STATUS);
 	tx_done = mtk_poll_tx(eth, budget);
 
 	if (unlikely(netif_msg_intr(eth))) {
-		status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
+		status = mtk_r32(eth, MTK_QDMA_INT_STATUS);
 		mask = mtk_r32(eth, MTK_QDMA_INT_MASK);
 		dev_info(eth->dev,
 			 "done tx %d, intr 0x%08x/0x%x\n",
@@ -1991,7 +2072,7 @@
 	if (tx_done == budget)
 		return budget;
 
-	status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
+	status = mtk_r32(eth, MTK_QDMA_INT_STATUS);
 	if (status & MTK_TX_DONE_INT)
 		return budget;
 
@@ -2195,9 +2276,9 @@
 		goto no_tx_mem;
 
 	ring->dma = dma_alloc_coherent(eth->dev,
-					  MTK_DMA_SIZE * sz,
-					  &ring->phys,
-					  GFP_ATOMIC | __GFP_ZERO);
+				       MTK_DMA_SIZE * sz,
+				       &ring->phys,
+				       GFP_ATOMIC | __GFP_ZERO);
 	if (!ring->dma)
 		goto no_tx_mem;
 
@@ -2288,27 +2369,21 @@
 	ring->buf_size = mtk_max_buf_size(ring->frag_size);
 	ring->data = kcalloc(rx_dma_size, sizeof(*ring->data),
 			     GFP_KERNEL);
-	if (!ring->data) {
-		//pr_notice(" data no mem\n");
+	if (!ring->data)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < rx_dma_size; i++) {
 		ring->data[i] = netdev_alloc_frag(ring->frag_size);
-		if (!ring->data[i]) {
-			//pr_notice(" data no mem 11\n");
+		if (!ring->data[i])
 			return -ENOMEM;
-		}
 	}
 
 	ring->dma = dma_alloc_coherent(eth->dev,
 				       rx_dma_size * sizeof(*ring->dma),
 				       &ring->phys,
 				       GFP_ATOMIC | __GFP_ZERO);
-	if (!ring->dma) {
-		//pr_notice(" dma no mem\n");
+	if (!ring->dma)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < rx_dma_size; i++) {
 		dma_addr_t dma_addr = dma_map_single(eth->dev,
@@ -3098,7 +3173,7 @@
 {
 	int i;
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < MTK_MAC_COUNT; i++) {
 		u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i));
 
 		/* default setup the forward port to send frame to PDMA */
@@ -3111,7 +3186,7 @@
 
 		mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i));
 	}
-	/*Reset and enable PSE*/
+	/* Reset and enable PSE */
 	mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
 	mtk_w32(eth, 0, MTK_RST_GL);
 }
@@ -3122,14 +3197,20 @@
 	struct mtk_eth *eth = mac->hw;
 	int err;
 
-	pr_info("1!!!!! RX desc = %x\n", cpu_to_le32((u32)(4200 - 1)));
+	pr_info("%s in mac[%d]\n", __func__, mac->id);
 
-	regulator_set_voltage(eth->dvfsrc_vcore_power, SGMII_VCORE_OPS, INT_MAX);
+	if (eth->soc->sgmii_pm)
+		regulator_set_voltage(eth->dvfsrc_vcore_power,
+				      SGMII_VCORE_OPS, INT_MAX);
+
 	/* we run 2 netdevs on the same dma ring so we only bring it up once */
 	if (!refcount_read(&eth->dma_refcnt)) {
 		err = mtk_start_dma(eth);
-		if (err)
+
+		if (err) {
+			dev_err(eth->dev, "%s: mtk_start_dma err\n", __func__);
 			return err;
+		}
 		mtk_gdma_config(eth, MTK_GDMA_ICS_EN | MTK_GDMA_TCS_EN | MTK_GDMA_UCS_EN);
 		napi_enable(&eth->tx_napi);
 
@@ -3156,12 +3237,18 @@
 			mtk_rx_irq_enable_edma_all(eth);
 		}
 
+#if defined(CONFIG_HW_NAT)
+		mtk_register_fast_path();
+#endif
+
 		refcount_set(&eth->dma_refcnt, 1);
 	}
 	else
 		refcount_inc(&eth->dma_refcnt);
 
-	phy_start(dev->phydev);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		phy_start(dev->phydev);
+
 	netif_start_queue(dev);
 
 	return 0;
@@ -3196,11 +3283,14 @@
 	struct mtk_eth *eth = mac->hw;
 
 	netif_tx_disable(dev);
-	phy_stop(dev->phydev);
+
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		phy_stop(dev->phydev);
 
 	/* only shutdown DMA if this is the last user */
 	if (!refcount_dec_and_test(&eth->dma_refcnt))
 		return 0;
+
 	mtk_gdma_config(eth, MTK_GDMA_DROP_ALL);
 
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
@@ -3239,7 +3329,14 @@
 	}
 
 	mtk_dma_free(eth);
-	regulator_set_voltage(eth->dvfsrc_vcore_power, SGMII_VCORE_NON_OPS, INT_MAX);
+
+	if (eth->soc->sgmii_pm)
+		regulator_set_voltage(eth->dvfsrc_vcore_power,
+				      SGMII_VCORE_NON_OPS, INT_MAX);
+
+#if defined(CONFIG_HW_NAT)
+	mtk_unregister_fast_path();
+#endif
 
 	return 0;
 }
@@ -3530,6 +3627,7 @@
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 	const char *mac_addr;
+	int ret = 0;
 
 	mac_addr = of_get_mac_address(mac->of_node);
 	if (mac_addr)
@@ -3542,7 +3640,10 @@
 			dev->dev_addr);
 	}
 
-	return mtk_phy_connect(dev);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		ret = mtk_phy_connect(dev);
+
+	return ret;
 }
 
 static void mtk_uninit(struct net_device *dev)
@@ -3550,20 +3651,25 @@
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 
-	phy_disconnect(dev->phydev);
-	if (of_phy_is_fixed_link(mac->of_node))
-		of_phy_deregister_fixed_link(mac->of_node);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		mtk_phy_disconnect(dev);
+
 	mtk_tx_irq_disable(eth, ~0);
 	mtk_rx_irq_disable(eth, ~0);
 }
 
 static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
+	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
+
 	switch (cmd) {
 	case SIOCGMIIPHY:
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
-		return phy_mii_ioctl(dev->phydev, ifr, cmd);
+		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+			return phy_mii_ioctl(dev->phydev, ifr, cmd);
+		break;
 	default:
 		/* default invoke the mtk_eth_dbg handler */
 		return mtk_do_priv_ioctl(dev, ifr, cmd);
@@ -3676,11 +3782,13 @@
 				  struct ethtool_link_ksettings *cmd)
 {
 	struct mtk_mac *mac = netdev_priv(ndev);
+	struct mtk_eth *eth = mac->hw;
 
 	if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
 		return -EBUSY;
 
-	phy_ethtool_ksettings_get(ndev->phydev, cmd);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		phy_ethtool_ksettings_get(ndev->phydev, cmd);
 
 	return 0;
 }
@@ -3689,11 +3797,16 @@
 				  const struct ethtool_link_ksettings *cmd)
 {
 	struct mtk_mac *mac = netdev_priv(ndev);
+	struct mtk_eth *eth = mac->hw;
+	int ret = 0;
 
 	if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
 		return -EBUSY;
 
-	return phy_ethtool_ksettings_set(ndev->phydev, cmd);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		ret = phy_ethtool_ksettings_set(ndev->phydev, cmd);
+
+	return ret;
 }
 
 static void mtk_get_drvinfo(struct net_device *dev,
@@ -3723,26 +3836,36 @@
 static int mtk_nway_reset(struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
+	int ret = 0;
 
 	if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
 		return -EBUSY;
 
-	return genphy_restart_aneg(dev->phydev);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+		ret = genphy_restart_aneg(dev->phydev);
+
+	return ret;
 }
 
 static u32 mtk_get_link(struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
 	int err;
 
 	if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
 		return -EBUSY;
 
-	err = genphy_update_link(dev->phydev);
-	if (err)
-		return ethtool_op_get_link(dev);
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY)) {
+		err = genphy_update_link(dev->phydev);
+		if (err)
+			return ethtool_op_get_link(dev);
 
-	return dev->phydev->link;
+		return dev->phydev->link;
+	}
+
+	return 0;
 }
 
 static void mtk_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -3867,7 +3990,7 @@
 	.get_sset_count		= mtk_get_sset_count,
 	.get_ethtool_stats	= mtk_get_ethtool_stats,
 	.get_rxnfc		= mtk_get_rxnfc,
-	.set_rxnfc              = mtk_set_rxnfc,
+	.set_rxnfc		= mtk_set_rxnfc,
 };
 
 static const struct net_device_ops mtk_netdev_ops = {
@@ -3880,7 +4003,7 @@
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= mtk_do_ioctl,
 	//.ndo_tx_timeout		= mtk_tx_timeout,
-	.ndo_get_stats64        = mtk_get_stats64,
+	.ndo_get_stats64	= mtk_get_stats64,
 	.ndo_fix_features	= mtk_fix_features,
 	.ndo_set_features	= mtk_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -4030,9 +4153,9 @@
 		eth->dvfsrc_vcore_power = regulator_get(&pdev->dev, "dvfsrc-vcore");
 		regulator_set_voltage(eth->dvfsrc_vcore_power, SGMII_VCORE_OPS, INT_MAX);
 
+		/* sgmii0 */
 		eth->sgmii_node0 = of_find_compatible_node(NULL, NULL,
 						"mediatek,colgin-sgmiisys_0");
-
 		if (IS_ERR(eth->sgmii_node0)) {
 			dev_err(&pdev->dev, "no eth->sgmii_node0 regmap found\n");
 			return PTR_ERR(eth->sgmii_node0);
@@ -4040,34 +4163,35 @@
 		sgmii_pdev = of_find_device_by_node(eth->sgmii_node0);
 		eth->sgmii_dev0 = &sgmii_pdev->dev;
 
+		/* sgmii1 */
 		eth->sgmii_node1 = of_find_compatible_node(NULL, NULL,
 						"mediatek,colgin-sgmiisys_1");
-		sgmii_pdev = of_find_device_by_node(eth->sgmii_node1);
-		eth->sgmii_dev1 = &sgmii_pdev->dev;
-
 		if (IS_ERR(eth->sgmii_node1)) {
 			dev_err(&pdev->dev, "no eth->sgmii_node1 regmap found\n");
 			return PTR_ERR(eth->sgmii_node1);
 		}
+		sgmii_pdev = of_find_device_by_node(eth->sgmii_node1);
+		eth->sgmii_dev1 = &sgmii_pdev->dev;
 
+		/* sgmii0 phy */
 		eth->sgmii_phy_node0 = of_find_compatible_node(NULL, NULL,
 						"mediatek,colgin-sgmiisys_phy_0");
-		sgmii_pdev = of_find_device_by_node(eth->sgmii_phy_node0);
-		eth->sgmii_phy_dev0 = &sgmii_pdev->dev;
 		if (IS_ERR(eth->sgmii_phy_node0)) {
 			dev_err(&pdev->dev, "no eth->sgmii_phy_node0 regmap found\n");
 			return PTR_ERR(eth->sgmii_phy_node0);
 		}
+		sgmii_pdev = of_find_device_by_node(eth->sgmii_phy_node0);
+		eth->sgmii_phy_dev0 = &sgmii_pdev->dev;
 
-
+		/* sgmii1 phy */
 		eth->sgmii_phy_node1 = of_find_compatible_node(NULL, NULL,
 						"mediatek,colgin-sgmiisys_phy_1");
-		sgmii_pdev = of_find_device_by_node(eth->sgmii_phy_node1);
-		eth->sgmii_phy_dev1 = &sgmii_pdev->dev;
 		if (IS_ERR(eth->sgmii_phy_node1)) {
 			dev_err(&pdev->dev, "no eth->sgmii_phy_node1 regmap found\n");
 			return PTR_ERR(eth->sgmii_phy_node1);
 		}
+		sgmii_pdev = of_find_device_by_node(eth->sgmii_phy_node1);
+		eth->sgmii_phy_dev1 = &sgmii_pdev->dev;
 	}
 
 	if (eth->soc->pinctrl) {
@@ -4293,7 +4417,7 @@
 	struct platform_device *pdev = to_platform_device(device);
 	struct mtk_eth *eth;
 	u32 val = 0;
-	int ret;
+	int i, ret;
 	static int enable_hw_idle = 0;
 
 	if (pdev == NULL) {
@@ -4302,10 +4426,23 @@
 	}
 
 	eth = platform_get_drvdata(pdev);
-        netif_stop_queue(eth->netdev[0]);
-        netif_stop_queue(eth->netdev[1]);
-	phy_stop(eth->netdev[0]->phydev);
-	phy_stop(eth->netdev[1]->phydev);
+
+	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		if (!eth->netdev[i])
+			continue;
+
+		netif_stop_queue(eth->netdev[i]);
+	}
+
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY)) {
+		for (i = 0; i < MTK_MAC_COUNT; i++) {
+			if (!eth->netdev[i])
+				continue;
+
+			phy_stop(eth->netdev[i]->phydev);
+		}
+	}
+
 #if 0
 	regmap_update_bits(eth->ethsys, MTK_PPE_TB_CFG,
 			   SCAN_MODE_MASK,
@@ -4316,7 +4453,11 @@
 #endif
 	mtk_w32(eth, 0x7fb5, MTK_PPE_TB_CFG);
 	mtk_w32(eth, 0x7fb5, MTK_PPE1_TB_CFG);
-	regulator_set_voltage(eth->dvfsrc_vcore_power, SGMII_VCORE_NON_OPS, INT_MAX);
+
+	if (eth->soc->sgmii_pm)
+		regulator_set_voltage(eth->dvfsrc_vcore_power,
+				      SGMII_VCORE_NON_OPS, INT_MAX);
+
 	mtk_gdma_config(eth, MTK_GDMA_DROP_ALL);
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
 	if (eth->hwrss) {
@@ -4379,7 +4520,7 @@
 	struct platform_device *pdev = to_platform_device(device);
 	struct device_node *np;
 	struct mtk_eth *eth;
-	int err;
+	int i, err;
 	const char *str;
 
 //	if (pdev == NULL) {
@@ -4400,20 +4541,37 @@
 	mtk_w32(eth, 0x27fb5, MTK_PPE_TB_CFG);
 	mtk_w32(eth, 0x27fb5, MTK_PPE1_TB_CFG);
 
-	np = of_parse_phandle(pdev->dev.of_node, "mediatek,sgmiisys", 0);
-	err = of_property_read_string(np, "mediatek,physpeed", &str);
-	if (err)
-		return err;
+	if (eth->soc->sgmii_pm) {
+		np = of_parse_phandle(pdev->dev.of_node,
+				      "mediatek,sgmiisys", 0);
 
-	if (refcount_read(&eth->dma_refcnt)) {
-		if (!strcmp(str, "auto"))
-			regulator_set_voltage(eth->dvfsrc_vcore_power, SGMII_VCORE_1G, INT_MAX);
-		 else
-			regulator_set_voltage(eth->dvfsrc_vcore_power, SGMII_VCORE_OPS, INT_MAX);
+		err = of_property_read_string(np, "mediatek,physpeed", &str);
+		if (err)
+			return err;
+
+		if (refcount_read(&eth->dma_refcnt)) {
+			if (!strcmp(str, "auto"))
+				regulator_set_voltage(eth->dvfsrc_vcore_power,
+						      SGMII_VCORE_1G, INT_MAX);
+			else
+				regulator_set_voltage(eth->dvfsrc_vcore_power,
+						      SGMII_VCORE_OPS, INT_MAX);
+		}
 	}
-	//mtk_clk_enable(eth);
-	mtk_sgmii_setup_mode_force(eth->sgmii, 0, eth);
-	mtk_sgmii_setup_mode_force(eth->sgmii, 1, eth);
+
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY)) {
+		for (i = 0; i < MTK_MAC_COUNT; i++) {
+			if (!eth->netdev[i])
+				continue;
+
+			if (MTK_HAS_FLAGS(eth->sgmii->flags[i],
+					  MTK_SGMII_PHYSPEED_AN))
+				mtk_sgmii_setup_mode_an(eth->sgmii, i, eth);
+			else
+				mtk_sgmii_setup_mode_force(eth->sgmii, i, eth);
+		}
+	}
+
 	//napi_enable(&eth->tx_napi);
 	//napi_enable(&eth->rx_napi);
 	mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
@@ -4443,10 +4601,22 @@
 	else
 		mtk_w32(eth, 0x00200081, MTK_PDMA_LRO_CTRL_DW0);
 	mtk_w32(eth, 0x80001c04, MTK_PDMA_GLO_CFG);
-	phy_start(eth->netdev[0]->phydev);
-	phy_start(eth->netdev[1]->phydev);
-	netif_start_queue(eth->netdev[0]);
-	netif_start_queue(eth->netdev[1]);
+
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY)) {
+		for (i = 0; i < MTK_MAC_COUNT; i++) {
+			if (!eth->netdev[i])
+				continue;
+
+			phy_start(eth->netdev[i]->phydev);
+		}
+	}
+
+	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		if (!eth->netdev[i])
+			continue;
+
+		netif_start_queue(eth->netdev[i]);
+	}
 	//pr_notice("netsys resume_noirq done\n");
 
 	return 0;
@@ -4503,12 +4673,27 @@
 	.sgmii_pm = true,
 };
 
+static const struct mtk_soc_data mt2735_data = {
+	.ana_rgc3 = 0x128,
+	.irq_num = 9,
+#if defined(CONFIG_EDMA_RX)
+	.caps = MT2735_CAPS | MTK_HWLRO | MTK_EDMA_RX,
+#else
+	.caps = MT2735_CAPS | MTK_HWLRO,
+#endif
+	.required_clks = MT2735_CLKS_BITMAP,
+	.required_pctl = false,
+	.pinctrl = false,
+	.sgmii_pm = false,
+};
+
 const struct of_device_id of_mtk_match[] = {
 	{ .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
 	{ .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
 	{ .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
 	{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data},
 	{ .compatible = "mediatek,mt6890-eth", .data = &mt6890_data},
+	{ .compatible = "mediatek,mt2735-eth", .data = &mt2735_data},
 	{ .compatible = "mediatek,fpga-eth", .data = &fpga_data},
 	{},
 };
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 5597e0c..4e89135 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -299,7 +299,7 @@
 #define FC_THRES_MIN		0x4444
 
 /* QDMA Interrupt Status Register */
-#define MTK_QMTK_INT_STATUS	0x1A18
+#define MTK_QDMA_INT_STATUS	0x1A18
 #define MTK_RX_DONE_DLY		BIT(30)
 #define MTK_RX_DONE_DLY3	BIT(27)
 #define MTK_RX_DONE_DLY2	BIT(26)
@@ -412,6 +412,7 @@
 
 /* Mac control registers */
 #define MTK_MAC_MCR(x)		(0x10100 + (x * 0x100))
+#define MTK_MAC_PPSC		0x10000
 
 #define MAC_MCR_MAX_RX_1536	BIT(24)
 #define MAC_MCR_IPG_CFG		BIT(18)
@@ -504,6 +505,7 @@
 /* Register to auto-negotiation restart */
 #define SGMSYS_PCS_CONTROL_1	0x0
 #define SGMII_AN_RESTART	BIT(9)
+#define SGMII_AN_ENABLE		BIT(12)
 
 /* Register to programmable link timer, the unit in 2 * 8ns */
 #define SGMSYS_PCS_LINK_TIMER	0x18
@@ -760,27 +762,35 @@
 				 BIT(MTK_CLK_SGMII_CK) | \
 				 BIT(MTK_CLK_ETH2PLL))
 #define LEOPARD_CLKS_BITMAP	(BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) |  \
-				BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
-				BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \
-				BIT(MTK_CLK_SGMII_TX_250M) | \
-				BIT(MTK_CLK_SGMII_RX_250M) | \
-				BIT(MTK_CLK_SGMII_CDR_REF) | \
-				BIT(MTK_CLK_SGMII_CDR_FB) | \
-				BIT(MTK_CLK_SGMII2_TX_250M) | \
-				BIT(MTK_CLK_SGMII2_RX_250M) | \
-				BIT(MTK_CLK_SGMII2_CDR_REF) | \
-				BIT(MTK_CLK_SGMII2_CDR_FB) | \
-				BIT(MTK_CLK_SGMII_CK) | \
-				BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP))
+				 BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
+				 BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \
+				 BIT(MTK_CLK_SGMII_TX_250M) | \
+				 BIT(MTK_CLK_SGMII_RX_250M) | \
+				 BIT(MTK_CLK_SGMII_CDR_REF) | \
+				 BIT(MTK_CLK_SGMII_CDR_FB) | \
+				 BIT(MTK_CLK_SGMII2_TX_250M) | \
+				 BIT(MTK_CLK_SGMII2_RX_250M) | \
+				 BIT(MTK_CLK_SGMII2_CDR_REF) | \
+				 BIT(MTK_CLK_SGMII2_CDR_FB) | \
+				 BIT(MTK_CLK_SGMII_CK) | \
+				 BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP))
 
 #define MT6890_CLKS_BITMAP	(BIT(MTK_CLK_NETSYS_SEL) | \
-				BIT(MTK_CLK_MEDSYS_SEL) | \
-				BIT(MTK_CLK_NETSYS_500M_SEL) | \
-				BIT(MTK_CLK_NETSYS_MED_MCU_SEL) | \
-				BIT(MTK_CLK_NETSYS_WED_MCU_SEL) | \
-				BIT(MTK_CLK_NETSYS_2X_SEL) | \
-				BIT(MTK_CLK_SGMII_SEL) | \
-				BIT(MTK_CLK_SGMII_SBUS_SEL))
+				 BIT(MTK_CLK_MEDSYS_SEL) | \
+				 BIT(MTK_CLK_NETSYS_500M_SEL) | \
+				 BIT(MTK_CLK_NETSYS_MED_MCU_SEL) | \
+				 BIT(MTK_CLK_NETSYS_WED_MCU_SEL) | \
+				 BIT(MTK_CLK_NETSYS_2X_SEL) | \
+				 BIT(MTK_CLK_SGMII_SEL) | \
+				 BIT(MTK_CLK_SGMII_SBUS_SEL))
+
+#define MT2735_CLKS_BITMAP	(BIT(MTK_CLK_NETSYS_SEL) | \
+				 BIT(MTK_CLK_MEDSYS_SEL) | \
+				 BIT(MTK_CLK_NETSYS_500M_SEL) | \
+				 BIT(MTK_CLK_NETSYS_MED_MCU_SEL) | \
+				 BIT(MTK_CLK_NETSYS_WED_MCU_SEL) | \
+				 BIT(MTK_CLK_NETSYS_2X_SEL))
+
 enum mtk_dev_state {
 	MTK_HW_INIT,
 	MTK_RESETTING
@@ -831,7 +841,6 @@
 	MTK_RX_FLAGS_QDMA,
 	MTK_RX_FLAGS_EDMA0,
 	MTK_RX_FLAGS_EDMA1,
-
 };
 
 /* struct mtk_rx_ring -	This struct holds info describing a RX ring
@@ -891,7 +900,7 @@
 #define MTK_FPGA_CLK			BIT(12)
 #define MTK_HWRSS			BIT(13)
 #define MTK_EDMA_RX			BIT(14)
-
+#define MTK_DISABLE_PHY			BIT(15)
 
 /* Capability for features on SoCs */
 #define MTK_PATH_BIT(x)         BIT((x) + 20)
@@ -960,16 +969,19 @@
 
 #define MT6890_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
 		      MTK_SGMII_PHY)
+
+#define MT2735_CAPS  (MTK_DISABLE_PHY)
+
 /* struct mtk_eth_data -	This is the structure holding all differences
-*				among various plaforms
-* @ana_rgc3:                   The offset for register ANA_RGC3 related to
-*				sgmiisys syscon
-* @caps			Flags shown the extra capability for the SoC
-* @required_clks		Flags shown the bitmap for required clocks on
-*				the target SoC
-* @required_pctl		A bool value to show whether the SoC requires
-*				the extra setup for those pins used by GMAC.
-*/
+ *				among various plaforms
+ * @ana_rgc3:                   The offset for register ANA_RGC3 related to
+ *				sgmiisys syscon
+ * @caps			Flags shown the extra capability for the SoC
+ * @required_clks		Flags shown the bitmap for required clocks on
+ *				the target SoC
+ * @required_pctl		A bool value to show whether the SoC requires
+ *				the extra setup for those pins used by GMAC.
+ */
 struct mtk_soc_data {
 	u32             ana_rgc3;
 	u32		caps;
@@ -988,9 +1000,11 @@
 };
 
 #define MTK_SGMII_PHYSPEED_AN          BIT(31)
-#define MTK_SGMII_PHYSPEED_MASK        GENMASK(2, 0)
+#define MTK_SGMII_PHYSPEED_MASK        GENMASK(3, 0)
 #define MTK_SGMII_PHYSPEED_1000        BIT(0)
 #define MTK_SGMII_PHYSPEED_2500        BIT(1)
+#define MTK_SGMII_PHYSPEED_100         BIT(2)
+#define MTK_SGMII_PHYSPEED_10          BIT(3)
 #define MTK_HAS_FLAGS(flags, _x)       (((flags) & (_x)) == (_x))
 
 /* struct mtk_sgmii -  This is the structure holding sgmii regmap and its
@@ -1140,8 +1154,8 @@
 u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
 
 int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
-			u32 ana_rgc3);
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
+		   u32 ana_rgc3);
+int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id, struct mtk_eth *eth);
 int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
 					struct mtk_eth *eth);
 int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode);
@@ -1149,6 +1163,8 @@
 #if defined(CONFIG_HW_NAT)
 extern int (*ppe_hook_rx_eth)(struct sk_buff *skb);
 extern int (*ppe_hook_tx_eth)(struct sk_buff *skb, int gmac_no);
+extern void (*ppe_dev_register_hook)(struct net_device *dev);
+extern void (*ppe_dev_unregister_hook)(struct net_device *dev);
 #endif
 
 #define MTK_EDMA0_GLO_CFG	0x3A04
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_sgmii.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_sgmii.c
index ddbacb9..5648633 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -381,6 +381,10 @@
 			ss->flags[i] |= MTK_SGMII_PHYSPEED_2500;
 		else if (!strcmp(str, "1000"))
 			ss->flags[i] |= MTK_SGMII_PHYSPEED_1000;
+		else if (!strcmp(str, "100"))
+			ss->flags[i] |= MTK_SGMII_PHYSPEED_100;
+		else if (!strcmp(str, "10"))
+			ss->flags[i] |= MTK_SGMII_PHYSPEED_10;
 		else if (!strcmp(str, "auto"))
 			ss->flags[i] |= MTK_SGMII_PHYSPEED_AN;
 		else
@@ -398,28 +402,34 @@
 	return 0;
 }
 
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id, struct mtk_eth *eth)
 {
 	unsigned int val = 0;
 
 	if (!ss->regmap[id])
 		return -EINVAL;
 
-	/* Setup the link timer and QPHY power up inside SGMIISYS */
-	regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
-		  SGMII_LINK_TIMER_DEFAULT);
+	pr_info("%s\n", __func__);
+	mtk_sgmii_setup_mode_force(ss, id, eth);
 
-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
-	val |= SGMII_REMOTE_FAULT_DIS;
-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+	regmap_update_bits(ss->regmap[id], 0x128, GENMASK(3, 2), 0x0 << 2);
+	mtk_w32(eth, 0x21057300, MTK_MAC_MCR(id));
+	regmap_update_bits(ss->regmap[id], 0x0, GENMASK(31, 0), 0x41140);
+	regmap_update_bits(ss->regmap[id], 0x20, GENMASK(31, 0), 0x3112000B);
+
+	// TODO: MTK_MAC_PPSC phy id should move to dts
+	mtk_w32(eth, 0xc5000605, MTK_MAC_PPSC);
 
 	regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
-	val |= SGMII_AN_RESTART;
-	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+	pr_info("AN PCS_control[%d] = %x\n", id, val);
 
-	regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
-	val &= ~SGMII_PHYA_PWD;
-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+	//debug info
+	regmap_read(ss->regmap[id], 0x128, &val);
+	pr_info("AN 0x128[%d] = %x\n", id, val);
+	regmap_read(ss->regmap[id], 0x20, &val);
+	pr_info("AN 0x020[%d] = %x\n", id, val);
+	regmap_read(ss->regmap[id], 0x0, &val);
+	pr_info("AN 0x000[%d] = %x\n", id, val);
 
 	return 0;
 }
@@ -432,19 +442,34 @@
 	if (!ss->regmap[id])
 		return -EINVAL;
 
+	mode = ss->flags[id] & MTK_SGMII_PHYSPEED_MASK;
+
+	/* SGMII clock */
 	regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
 	val &= ~GENMASK(3, 2);
-	mode = ss->flags[id] & MTK_SGMII_PHYSPEED_MASK;
-	val |= (mode == MTK_SGMII_PHYSPEED_1000) ? 0 : BIT(2);
+	val |= (mode == MTK_SGMII_PHYSPEED_2500) ? BIT(2) : 0;
 	regmap_write(ss->regmap[id], ss->ana_rgc3, val);
 
 	/* disable SGMII AN */
 	regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
-	val &= ~BIT(12);
+	val &= ~SGMII_AN_ENABLE;
 	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
 
 	/* SGMII force mode setting */
-	val = 0x31120009;
+	val = 0x31120001;
+	switch (mode) {
+	case MTK_SGMII_PHYSPEED_2500:
+	case MTK_SGMII_PHYSPEED_1000:
+		val |= BIT(3);
+		break;
+	case MTK_SGMII_PHYSPEED_100:
+		val |= BIT(2);
+		break;
+	case MTK_SGMII_PHYSPEED_10: // bit[3:2] is 0
+		break;
+	default:
+		pr_info("unsupported sgmii mode %d", mode);
+	};
 	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
 
 	/* Release PHYA power down state */
@@ -455,7 +480,7 @@
 	/*SET SGMII PHY parameter*/
 	pr_info("sgmii phy caps[%d] = %x \n", id, eth->soc->caps);
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII_PHY)) {
-		if(mode == MTK_SGMII_PHYSPEED_2500)
+		if (mode == MTK_SGMII_PHYSPEED_2500)
 			mtk_sgmii_phy_gen2(ss, id);
 		else
 			mtk_sgmii_phy_gen1(ss, id);
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
old mode 100644
new mode 100755
index 7d0d374..d3746da
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -104,7 +104,7 @@
 #define MTK_USE_SGMII		1
 
 /*SGMII require vcore*/
-#define SGMII_VCORE_OPS		750000
+#define SGMII_VCORE_OPS		650000
 
 struct mac_delay_struct {
 	u32 tx_delay;
@@ -158,6 +158,9 @@
 /* list of clocks required for mac */
 static const char * const mt2735_dwmac_clk_l[] = {
 	"mac_main", "ptp_ref", "eth_cg", "eth_rmii"
+#if defined(CONFIG_MTK_SGMII_SNPS)
+	, "sgmii_sel", "sgmii_sbus_sel"
+#endif
 };
 
 static int eth_smt_result = 2;
@@ -946,6 +949,8 @@
 		mac_delay->tx_delay /= 80;
 		mac_delay->rx_delay /= 80;
 		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		break;
 	default:
 		dev_err(plat->dev, "phy interface not supported\n");
 		break;
@@ -965,6 +970,8 @@
 		mac_delay->tx_delay *= 80;
 		mac_delay->rx_delay *= 80;
 		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		break;
 	default:
 		dev_err(plat->dev, "phy interface not supported\n");
 		break;
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac.h
old mode 100644
new mode 100755
index 301c01d..36d6b80
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -172,6 +172,7 @@
 	int synopsys_id;
 	u32 msg_enable;
 	int wolopts;
+	int phy_wolopts;
 	int wol_irq;
 	int clk_csr;
 	struct timer_list eee_ctrl_timer;
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
old mode 100644
new mode 100755
index a43e1e6..a57df0c
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -637,15 +637,18 @@
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
-	if (!priv->plat->pmt)
-		return phy_ethtool_get_wol(dev->phydev, wol);
+	phy_ethtool_get_wol(dev->phydev, wol);
 
-	mutex_lock(&priv->lock);
-	if (device_can_wakeup(priv->device)) {
-		wol->supported = WAKE_MAGIC | WAKE_UCAST;
-		wol->wolopts = priv->wolopts;
+	if (!!wol->supported) {
+		return;
+	} else if (priv->plat->pmt) {
+		mutex_lock(&priv->lock);
+		if (device_can_wakeup(priv->device)) {
+			wol->supported = WAKE_MAGIC | WAKE_UCAST;
+			wol->wolopts = priv->wolopts;
+		}
+		mutex_unlock(&priv->lock);
 	}
-	mutex_unlock(&priv->lock);
 }
 
 static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -653,40 +656,46 @@
 	struct stmmac_priv *priv = netdev_priv(dev);
 	u32 support = WAKE_MAGIC | WAKE_UCAST;
 
-	if (!priv->plat->pmt) {
-		int ret = phy_ethtool_set_wol(dev->phydev, wol);
+	int ret = phy_ethtool_set_wol(dev->phydev, wol);
 
-		if (!ret)
-			device_set_wakeup_enable(priv->device, !!wol->wolopts);
+	if (!ret && (wol->wolopts & WAKE_MAGIC)) {
+		device_set_wakeup_enable(priv->device, !!wol->wolopts);
+		priv->phy_wolopts = WAKE_MAGIC;
 		return ret;
-	}
-
-	/* By default almost all GMAC devices support the WoL via
-	 * magic frame but we can disable it if the HW capability
-	 * register shows no support for pmt_magic_frame. */
-	if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame))
-		wol->wolopts &= ~WAKE_MAGIC;
-
-	if (!device_can_wakeup(priv->device))
-		return -EINVAL;
-
-	if (wol->wolopts & ~support)
-		return -EINVAL;
-
-	if (wol->wolopts) {
-		pr_info("stmmac: wakeup enable\n");
-		device_set_wakeup_enable(priv->device, 1);
-		enable_irq_wake(priv->wol_irq);
 	} else {
-		device_set_wakeup_enable(priv->device, 0);
-		disable_irq_wake(priv->wol_irq);
+		priv->phy_wolopts = 0;
 	}
 
-	mutex_lock(&priv->lock);
-	priv->wolopts = wol->wolopts;
-	mutex_unlock(&priv->lock);
+	if (priv->plat->pmt) {
+		/* By default almost all GMAC devices support the WoL via
+		 * magic frame but we can disable it if the HW capability
+		 * register shows no support for pmt_magic_frame.
+		 */
+		if (priv->hw_cap_support && !priv->dma_cap.pmt_magic_frame)
+			wol->wolopts &= ~WAKE_MAGIC;
 
-	return 0;
+		if (!device_can_wakeup(priv->device))
+			return -EINVAL;
+
+		if (wol->wolopts & ~support)
+			return -EINVAL;
+
+		if (wol->wolopts) {
+			pr_info("stmmac: wakeup enable\n");
+			device_set_wakeup_enable(priv->device, 1);
+			enable_irq_wake(priv->wol_irq);
+		} else {
+			device_set_wakeup_enable(priv->device, 0);
+			disable_irq_wake(priv->wol_irq);
+		}
+
+		mutex_lock(&priv->lock);
+		priv->wolopts = wol->wolopts;
+		mutex_unlock(&priv->lock);
+		ret = 0;
+	}
+
+	return ret;
 }
 
 static int stmmac_ethtool_op_get_eee(struct net_device *dev,
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
old mode 100644
new mode 100755
index ba75fdd..b34725d
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -964,7 +964,6 @@
 	char bus_id[MII_BUS_ID_SIZE];
 	int interface = priv->plat->interface;
 	int max_speed = priv->plat->max_speed;
-	int ret;
 	priv->oldlink = false;
 	priv->speed = SPEED_UNKNOWN;
 	priv->oldduplex = DUPLEX_UNKNOWN;
@@ -1039,11 +1038,6 @@
 	if (priv->plat->phy_intr_irq > 0) {
 		phy_ethtool_get_wol(phydev, &wol);
 		device_set_wakeup_capable(priv->device, !!wol.supported);
-		wol.wolopts = WAKE_MAGIC;
-		ret = phy_ethtool_set_wol(phydev, &wol);
-
-		if (!ret)
-			device_set_wakeup_enable(priv->device, !!wol.wolopts);
 	}
 
 	return 0;
@@ -4566,6 +4560,10 @@
 		goto error_netdev_register;
 	}
 
+#if defined(CONFIG_HW_NAT)
+	mtk_hook_fast_path(ndev);
+#endif
+
 #ifdef CONFIG_DEBUG_FS
 	ret = stmmac_init_fs(ndev);
 	if (ret < 0)
@@ -4664,7 +4662,7 @@
 	stmmac_stop_all_dma(priv);
 
 	/* Enable Power down mode by programming the PMT regs */
-	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+	if (device_may_wakeup(priv->device) && priv->wolopts) {
 		stmmac_pmt(priv, priv->hw, priv->wolopts);
 		priv->irq_wake = 1;
 	} else {
@@ -4676,7 +4674,7 @@
 		clk_disable_unprepare(priv->plat->pclk);
 		clk_disable_unprepare(priv->plat->stmmac_clk);
 
-		if (priv->plat->phy_intr_irq > 0)
+		if (priv->plat->phy_intr_irq > 0 && priv->phy_wolopts)
 			enable_irq_wake(priv->plat->phy_intr_irq);
 	}
 	mutex_unlock(&priv->lock);
@@ -4745,7 +4743,7 @@
 	 * this bit because it can generate problems while resuming
 	 * from another devices (e.g. serial console).
 	 */
-	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+	if (device_may_wakeup(priv->device) && priv->wolopts) {
 		mutex_lock(&priv->lock);
 		stmmac_pmt(priv, priv->hw, 0);
 		mutex_unlock(&priv->lock);
@@ -4772,7 +4770,7 @@
 			phy_init_hw(priv->dev->phydev);
 		}
 
-		if (priv->plat->phy_intr_irq > 0) {
+		if (priv->plat->phy_intr_irq > 0 && priv->phy_wolopts) {
 			disable_irq_wake(priv->plat->phy_intr_irq);
 			err = phy_ethtool_set_wol(priv->dev->phydev, &wol);
 
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
old mode 100644
new mode 100755
index 37c0bc6..cc1895a
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -314,7 +314,12 @@
 
 		priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
 	} else if (!qopt->enable) {
-		return stmmac_dma_qmode(priv, priv->ioaddr, queue, MTL_QUEUE_DCB);
+		ret = stmmac_dma_qmode(priv, priv->ioaddr, queue,
+				       MTL_QUEUE_DCB);
+		if (ret)
+			return ret;
+
+		priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
 	}
 
 	/* Port Transmit Rate and Speed Divider */
diff --git a/src/kernel/linux/v4.19/drivers/net/phy/marvell-88q.c b/src/kernel/linux/v4.19/drivers/net/phy/marvell-88q.c
old mode 100644
new mode 100755
index 6fb740a..297a56b
--- a/src/kernel/linux/v4.19/drivers/net/phy/marvell-88q.c
+++ b/src/kernel/linux/v4.19/drivers/net/phy/marvell-88q.c
@@ -169,7 +169,6 @@
 	return 0;
 }
 
-
 static int q2110_read_status(struct phy_device *phydev)
 {
 	int val;
@@ -177,10 +176,19 @@
 	phydev->duplex = 1;
 	phydev->pause = 0;
 
+	if (!phy_polling_mode(phydev) || !phydev->link) {
+		val = phy_read(phydev, Q2110_T1_AN_STATUS);
+		if (val < 0)
+			return val;
+		else if (val & Q2110_T1_LINK_STATUS)
+			goto done;
+	}
+
 	val = phy_read(phydev, Q2110_T1_AN_STATUS);
 	if (val < 0)
 		return val;
 
+done:
 	if (val & Q2110_T1_LINK_STATUS)
 		phydev->link = 1;
 	else
diff --git a/src/kernel/linux/v4.19/drivers/net/phy/micrel.c b/src/kernel/linux/v4.19/drivers/net/phy/micrel.c
old mode 100644
new mode 100755
index 3957ada..2a367bc
--- a/src/kernel/linux/v4.19/drivers/net/phy/micrel.c
+++ b/src/kernel/linux/v4.19/drivers/net/phy/micrel.c
@@ -710,6 +710,13 @@
 	else if (ret & 0xff)
 		return 0;
 
+	ret = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+			   KSZ9131RN_WAKE_ON_LAN_CONTROL);
+	if (ret < 0)
+		return ret;
+	else if (!(ret & KSZ9131RN_WOL_ENABLE_MAGIC_PKT))
+		return 0;
+
 	ret = phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
 			     KSZ9131RN_WAKE_ON_LAN_CONTROL,
 			     KSZ9131RN_WOL_ENABLE_MAGIC_PKT, 0);
diff --git a/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c b/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c
index c4c151d..20ebc23 100755
--- a/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c
+++ b/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c
@@ -37,6 +37,7 @@
 #define MTK_SCPD_ALWAYS_ON		BIT(3)
 #define MTK_SCPD_MD_OPS			BIT(4)
 #define MTK_SCPD_NETSYS_OPS		BIT(5)
+#define MTK_SCPD_HSM_OPS		BIT(6)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -169,6 +170,10 @@
 #define MT6890_TOP_AXI_PROT_EN_INFRA_VDNR_1_MSDC	(BIT(3) | BIT(16))
 #define MT6890_TOP_AXI_PROT_EN_INFRA_VDNR_1_SSUSB	(BIT(1) | BIT(2))
 #define MT6890_TOP_AXI_PROT_EN_INFRA_VDNR_3_SSUSB	(BIT(11))
+#define MT6890_TOP_AXI_PROT_EN_2_HSM		(BIT(19) | BIT(21))
+#define MT6890_TOP_AXI_PROT_EN_HSM		(BIT(2) | BIT(3))
+#define MT6890_TOP_AXI_PROT_EN_HSM_2ND		(BIT(4))
+#define MT6890_TOP_AXI_PROT_EN_2_HSM_2ND	(BIT(16) | BIT(17))
 
 enum clk_id {
 	CLK_NONE,
@@ -186,6 +191,7 @@
 	CLK_ETH3,
 	CLK_ETH4,
 	CLK_EIP97,
+	CLK_HSM,
 	CLK_MAX,
 };
 
@@ -205,6 +211,7 @@
 	"snps_ptp_sel",
 	"snps_rmii_sel",
 	"eip97_sel",
+	"hsm_sel",
 	NULL,
 };
 
@@ -636,8 +643,18 @@
 		writel(val, ctl_addr);
 	}
 
-	val |= PWR_RST_B_BIT;
-	writel(val, ctl_addr);
+	/* HSM have two special points:
+	 * a. Request bus protect before PWR_RST_B.
+	 * b. Move the RST_B after SRAM_PDN.
+	 */
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_HSM_OPS)) {
+		ret = scpsys_bus_protect_disable(scpd);
+		if (ret < 0)
+			goto err_pwr_ack;
+	} else { /* !HSM */
+		val |= PWR_RST_B_BIT;
+		writel(val, ctl_addr);
+	}
 
 	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_STRICT_BUSP)) {
 		/*
@@ -665,9 +682,16 @@
 		if (ret < 0)
 			goto err_sram;
 
-		ret = scpsys_bus_protect_disable(scpd);
-		if (ret < 0)
-			goto err_sram;
+		/* HSM Move RST_B after SRAM_PDN to 0. */
+		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_HSM_OPS)) {
+			val = readl(ctl_addr);
+			val |= PWR_RST_B_BIT;
+			writel(val, ctl_addr);
+		} else { /* !HSM */
+			ret = scpsys_bus_protect_disable(scpd);
+			if (ret < 0)
+				goto err_sram;
+		}
 	}
 
 	return 0;
@@ -2032,6 +2056,22 @@
 		.ctl_offs = 0x344,
 		.sram_pdn_bits = GENMASK(8, 8),
 		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.caps = MTK_SCPD_HSM_OPS,
+		.clk_id = {CLK_HSM},
+		.bp_table = {
+			BUS_PROT(IFR_TYPE, 0x0714, 0x0718, 0x0710, 0x0724,
+				 MT6890_TOP_AXI_PROT_EN_2_HSM,
+				 MT6890_TOP_AXI_PROT_EN_2_HSM, 0),
+			BUS_PROT(IFR_TYPE, 0x02A0, 0x02A4, 0x0220, 0x0228,
+				 MT6890_TOP_AXI_PROT_EN_HSM,
+				 MT6890_TOP_AXI_PROT_EN_HSM, 0),
+			BUS_PROT(IFR_TYPE, 0x02A0, 0x02A4, 0x0220, 0x0228,
+				 MT6890_TOP_AXI_PROT_EN_HSM_2ND,
+				 MT6890_TOP_AXI_PROT_EN_HSM_2ND, 0),
+			BUS_PROT(IFR_TYPE, 0x0714, 0x0718, 0x0710, 0x0724,
+				 MT6890_TOP_AXI_PROT_EN_2_HSM_2ND,
+				 MT6890_TOP_AXI_PROT_EN_2_HSM_2ND, 0),
+		},
 	},
 	[MT6890_POWER_DOMAIN_SSUSB] = {
 		.name = "ssusb",
diff --git a/src/kernel/linux/v4.19/drivers/spmi/mtk-pmif.c b/src/kernel/linux/v4.19/drivers/spmi/mtk-pmif.c
old mode 100644
new mode 100755
index b254a88..062cbe4
--- a/src/kernel/linux/v4.19/drivers/spmi/mtk-pmif.c
+++ b/src/kernel/linux/v4.19/drivers/spmi/mtk-pmif.c
@@ -1608,18 +1608,20 @@
 
 	for (i = 0; i < SPMI_MAX_SLAVE_ID; i++) {
 		slv_irq_sta = mtk_spmi_readl(arb, SPMI_SLV_3_0_EINT + (i / 4));
-		slv_irq_sta >>= (((i % 4) * 8) & 0xFF);
+		// Need to use 0xFF to clear SPMI_SLV_x_x_EINT before
+		// callback to pmic, since pmic may rcs to master again in the
+		// callback function, and we also need to deal this request.
+		// If we clear after the callback,
+		// then we may miss this request.
+		mtk_spmi_writel(arb, (0xFF << ((i % 4) * 8)),
+		    SPMI_SLV_3_0_EINT + (i / 4));
+
+		slv_irq_sta = (slv_irq_sta >> ((i % 4) * 8)) & 0xFF;
 		if (arb->rcs_enable_hwirq[i] && slv_irq_sta) {
 			dev_info(&arb->spmic->dev,
 				 "hwirq=%d, sta=0x%x\n", i, slv_irq_sta);
 			handle_nested_irq(irq_find_mapping(arb->domain, i));
 		}
-		/* need to clear using 0xFF to avoid new irq happen
-		 * after read SPMI_SLV_3_0_EINT + (i/4) value then use
-		 * this value to clean
-		 */
-		mtk_spmi_writel(arb, (0xFF << ((i % 4) * 8)),
-				SPMI_SLV_3_0_EINT + (i / 4));
 	}
 	return IRQ_HANDLED;
 }
diff --git a/src/kernel/linux/v4.19/drivers/usb/gadget/function/f_ncm.c b/src/kernel/linux/v4.19/drivers/usb/gadget/function/f_ncm.c
old mode 100644
new mode 100755
index 5780fba..d2b32d1
--- a/src/kernel/linux/v4.19/drivers/usb/gadget/function/f_ncm.c
+++ b/src/kernel/linux/v4.19/drivers/usb/gadget/function/f_ncm.c
@@ -23,6 +23,7 @@
 #include "u_ether.h"
 #include "u_ether_configfs.h"
 #include "u_ncm.h"
+#include "configfs.h"
 
 /*
  * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link.
@@ -35,9 +36,7 @@
 
 /* to trigger crc/non-crc ndp signature */
 
-#define NCM_NDP_HDR_CRC_MASK	0x01000000
 #define NCM_NDP_HDR_CRC		0x01000000
-#define NCM_NDP_HDR_NOCRC	0x00000000
 
 enum ncm_notify_state {
 	NCM_NOTIFY_NONE,		/* don't notify */
@@ -54,6 +53,7 @@
 	struct usb_ep			*notify;
 	struct usb_request		*notify_req;
 	u8				notify_state;
+	atomic_t			notify_count;
 	bool				is_open;
 
 	const struct ndp_parser_opts	*parser_opts;
@@ -85,8 +85,10 @@
 /* peak (theoretical) bulk transfer rate in bits-per-second */
 static inline unsigned ncm_bitrate(struct usb_gadget *g)
 {
-	if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
-		return 13 * 1024 * 8 * 1000 * 8;
+	if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS)
+		return 4250000000U;
+	else if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
+		return 3750000000U;
 	else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 		return 13 * 512 * 8 * 1000 * 8;
 	else
@@ -526,6 +528,7 @@
 {
 	ncm->parser_opts = &ndp16_opts;
 	ncm->is_crc = false;
+	ncm->ndp_sign = ncm->parser_opts->ndp_sign;
 	ncm->port.cdc_filter = DEFAULT_FILTER;
 
 	/* doesn't make sense for ncm, fixed size used */
@@ -547,7 +550,7 @@
 	int				status;
 
 	/* notification already in flight? */
-	if (!req)
+	if (atomic_read(&ncm->notify_count))
 		return;
 
 	event = req->buf;
@@ -564,8 +567,10 @@
 		event->wLength = 0;
 		req->length = sizeof *event;
 
-		DBG(cdev, "notify connect %s\n",
-				ncm->is_open ? "true" : "false");
+		//DBG(cdev, "notify connect %s\n",
+		//		ncm->is_open ? "true" : "false");
+		LOGI("NCM_NOTIFY_CONNECT is_open %s\n",
+			ncm->is_open ? "true" : "false");
 		ncm->notify_state = NCM_NOTIFY_NONE;
 		break;
 
@@ -580,14 +585,16 @@
 		data[0] = cpu_to_le32(ncm_bitrate(cdev->gadget));
 		data[1] = data[0];
 
-		DBG(cdev, "notify speed %d\n", ncm_bitrate(cdev->gadget));
+		//DBG(cdev, "notify speed %u\n", ncm_bitrate(cdev->gadget));
+		LOGI("NCM_NOTIFY_SPEED speed %u\n", ncm_bitrate(cdev->gadget));
 		ncm->notify_state = NCM_NOTIFY_CONNECT;
 		break;
 	}
 	event->bmRequestType = 0xA1;
 	event->wIndex = cpu_to_le16(ncm->ctrl_id);
 
-	ncm->notify_req = NULL;
+	atomic_inc(&ncm->notify_count);
+
 	/*
 	 * In double buffering if there is a space in FIFO,
 	 * completion callback can be called right after the call,
@@ -597,8 +604,9 @@
 	status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC);
 	spin_lock(&ncm->lock);
 	if (status < 0) {
-		ncm->notify_req = req;
-		DBG(cdev, "notify --> %d\n", status);
+		atomic_dec(&ncm->notify_count);
+		//DBG(cdev, "notify --> %d\n", status);
+		LOGE("usb_ep_queue() fail status %d\n", status);
 	}
 }
 
@@ -632,17 +640,19 @@
 	case 0:
 		VDBG(cdev, "Notification %02x sent\n",
 		     event->bNotificationType);
+		atomic_dec(&ncm->notify_count);
 		break;
 	case -ECONNRESET:
 	case -ESHUTDOWN:
+		atomic_set(&ncm->notify_count, 0);
 		ncm->notify_state = NCM_NOTIFY_NONE;
 		break;
 	default:
 		DBG(cdev, "event %02x --> %d\n",
 			event->bNotificationType, req->status);
+		atomic_dec(&ncm->notify_count);
 		break;
 	}
-	ncm->notify_req = req;
 	ncm_do_notify(ncm);
 	spin_unlock(&ncm->lock);
 }
@@ -700,7 +710,8 @@
 		 */
 		if (w_length != 0 || w_index != ncm->ctrl_id)
 			goto invalid;
-		DBG(cdev, "packet filter %02x\n", w_value);
+		//DBG(cdev, "packet filter %02x\n", w_value);
+		LOGI("packet filter %02x\n", w_value);
 		/*
 		 * REVISIT locking of cdc_filter.  This assumes the UDC
 		 * driver won't have a concurrent packet TX irq running on
@@ -727,7 +738,8 @@
 		value = w_length > sizeof ntb_parameters ?
 			sizeof ntb_parameters : w_length;
 		memcpy(req->buf, &ntb_parameters, value);
-		VDBG(cdev, "Host asked NTB parameters\n");
+		//VDBG(cdev, "Host asked NTB parameters\n");
+		LOGI("Host asked NTB parameters\n");
 		break;
 
 	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -737,8 +749,10 @@
 			goto invalid;
 		put_unaligned_le32(ncm->port.fixed_in_len, req->buf);
 		value = 4;
-		VDBG(cdev, "Host asked INPUT SIZE, sending %d\n",
-		     ncm->port.fixed_in_len);
+		//VDBG(cdev, "Host asked INPUT SIZE, sending %d\n",
+		//     ncm->port.fixed_in_len);
+		LOGI("Host asked INPUT SIZE, sending %d\n",
+			ncm->port.fixed_in_len);
 		break;
 
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -764,7 +778,8 @@
 		format = (ncm->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
 		put_unaligned_le16(format, req->buf);
 		value = 2;
-		VDBG(cdev, "Host asked NTB FORMAT, sending %d\n", format);
+		//VDBG(cdev, "Host asked NTB FORMAT, sending %d\n", format);
+		LOGI("Host asked NTB FORMAT, sending %d\n", format);
 		break;
 	}
 
@@ -776,11 +791,13 @@
 		switch (w_value) {
 		case 0x0000:
 			ncm->parser_opts = &ndp16_opts;
-			DBG(cdev, "NCM16 selected\n");
+			//DBG(cdev, "NCM16 selected\n");
+			LOGI("NCM16 selected\n");
 			break;
 		case 0x0001:
 			ncm->parser_opts = &ndp32_opts;
-			DBG(cdev, "NCM32 selected\n");
+			//DBG(cdev, "NCM32 selected\n");
+			LOGI("NCM32 selected\n");
 			break;
 		default:
 			goto invalid;
@@ -798,32 +815,30 @@
 		is_crc = ncm->is_crc ? 0x0001 : 0x0000;
 		put_unaligned_le16(is_crc, req->buf);
 		value = 2;
-		VDBG(cdev, "Host asked CRC MODE, sending %d\n", is_crc);
+		//VDBG(cdev, "Host asked CRC MODE, sending %d\n", is_crc);
+		LOGI("Host asked CRC MODE, sending %d\n", is_crc);
 		break;
 	}
 
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
 		| USB_CDC_SET_CRC_MODE:
 	{
-		int ndp_hdr_crc = 0;
-
 		if (w_length != 0 || w_index != ncm->ctrl_id)
 			goto invalid;
 		switch (w_value) {
 		case 0x0000:
 			ncm->is_crc = false;
-			ndp_hdr_crc = NCM_NDP_HDR_NOCRC;
-			DBG(cdev, "non-CRC mode selected\n");
+			//DBG(cdev, "non-CRC mode selected\n");
+			LOGI("non-CRC mode selected\n");
 			break;
 		case 0x0001:
 			ncm->is_crc = true;
-			ndp_hdr_crc = NCM_NDP_HDR_CRC;
-			DBG(cdev, "CRC mode selected\n");
+			//DBG(cdev, "CRC mode selected\n");
+			LOGI("CRC mode selected\n");
 			break;
 		default:
 			goto invalid;
 		}
-		ncm->ndp_sign = ncm->parser_opts->ndp_sign | ndp_hdr_crc;
 		value = 0;
 		break;
 	}
@@ -836,23 +851,34 @@
 
 	default:
 invalid:
-		DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+		//DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+		//	ctrl->bRequestType, ctrl->bRequest,
+		//	w_value, w_index, w_length);
+		LOGI("invalid control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			w_value, w_index, w_length);
 	}
+	ncm->ndp_sign = ncm->parser_opts->ndp_sign |
+		(ncm->is_crc ? NCM_NDP_HDR_CRC : 0);
 
 	/* respond with data transfer or status phase? */
 	if (value >= 0) {
-		DBG(cdev, "ncm req%02x.%02x v%04x i%04x l%d\n",
+		//DBG(cdev, "ncm req%02x.%02x v%04x i%04x l%d\n",
+		//	ctrl->bRequestType, ctrl->bRequest,
+		//	w_value, w_index, w_length);
+		LOGI("ncm req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			w_value, w_index, w_length);
 		req->zero = 0;
 		req->length = value;
 		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0)
-			ERROR(cdev, "ncm req %02x.%02x response err %d\n",
-					ctrl->bRequestType, ctrl->bRequest,
-					value);
+			//ERROR(cdev, "ncm req %02x.%02x response err %d\n",
+			//		ctrl->bRequestType, ctrl->bRequest,
+			//		value);
+			LOGE("ncm req %02x.%02x response err %d\n",
+				ctrl->bRequestType, ctrl->bRequest,
+				value);
 	}
 
 	/* device either stalls (value < 0) or reports success */
@@ -865,6 +891,9 @@
 	struct f_ncm		*ncm = func_to_ncm(f);
 	struct usb_composite_dev *cdev = f->config->cdev;
 
+	LOGI("intf=%d (ctrl=%d data=%d) alt=%d\n",
+		intf, ncm->ctrl_id, ncm->data_id, alt);
+
 	/* Control interface has only altsetting 0 */
 	if (intf == ncm->ctrl_id) {
 		if (alt != 0)
@@ -922,8 +951,10 @@
 			ncm->port.cdc_filter = DEFAULT_FILTER;
 			DBG(cdev, "activate ncm\n");
 			net = gether_connect(&ncm->port);
-			if (IS_ERR(net))
+			if (IS_ERR(net)) {
+				LOGE("gether_connect fail\n");
 				return PTR_ERR(net);
+			}
 			ncm->netdev = net;
 			ncm->timer_stopping = false;
 		}
@@ -1018,6 +1049,12 @@
 	__le16		*ntb_data;
 	__le16		*ntb_ndp;
 	int		dgram_pad;
+	struct skb_shared_info	*pinfo = NULL;
+	skb_frag_t		*frag = NULL;
+	unsigned int	frag_cnt = 0;
+	unsigned int	frag_idx = 0;
+	unsigned int	frag_data_len = 0;
+	char			*frag_data_addr;
 
 	unsigned	max_size = ncm->port.fixed_in_len;
 	const struct ndp_parser_opts *opts = ncm->parser_opts;
@@ -1026,8 +1063,10 @@
 	const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
 	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
 
-	if (!skb && !ncm->skb_tx_data)
+	if (!skb && !ncm->skb_tx_data) {
+		LOGE("skb and skb_tx_data are NULL\n");
 		return NULL;
+	}
 
 	if (skb) {
 		/* Add the CRC if required up front */
@@ -1054,8 +1093,10 @@
 		    ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len))
 		    > max_size)) {
 			skb2 = package_for_tx(ncm);
-			if (!skb2)
+			if (!skb2) {
+				LOGE("skb2 is NULL\n");
 				goto err;
+			}
 		}
 
 		if (!ncm->skb_tx_data) {
@@ -1065,8 +1106,10 @@
 
 			/* Create a new skb for the NTH and datagrams. */
 			ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC);
-			if (!ncm->skb_tx_data)
+			if (!ncm->skb_tx_data) {
+				LOGE("skb_tx_data alloc fail\n");
 				goto err;
+			}
 
 			ncm->skb_tx_data->dev = ncm->netdev;
 			ntb_data = skb_put_zero(ncm->skb_tx_data, ncb_len);
@@ -1084,8 +1127,10 @@
 						    + opts->dpe_size
 						    * TX_MAX_NUM_DPE),
 						    GFP_ATOMIC);
-			if (!ncm->skb_tx_ndp)
+			if (!ncm->skb_tx_ndp) {
+				LOGE("skb_tx_ndp alloc fail\n");
 				goto err;
+			}
 
 			ncm->skb_tx_ndp->dev = ncm->netdev;
 			ntb_ndp = skb_put(ncm->skb_tx_ndp, opts->ndp_size);
@@ -1098,11 +1143,11 @@
 			ncm->ndp_dgram_count = 1;
 
 			/* Note: we skip opts->next_ndp_index */
-		}
 
-		/* Delay the timer. */
-		hrtimer_start(&ncm->task_timer, TX_TIMEOUT_NSECS,
-			      HRTIMER_MODE_REL_SOFT);
+			/* Start the timer. */
+			hrtimer_start(&ncm->task_timer, TX_TIMEOUT_NSECS,
+				      HRTIMER_MODE_REL_SOFT);
+		}
 
 		/* Add the datagram position entries */
 		ntb_ndp = skb_put_zero(ncm->skb_tx_ndp, dgram_idx_len);
@@ -1119,15 +1164,37 @@
 
 		/* Add the new data to the skb */
 		skb_put_zero(ncm->skb_tx_data, dgram_pad);
-		skb_put_data(ncm->skb_tx_data, skb->data, skb->len);
+
+		if (ncm->netdev->features & NETIF_F_GSO) {
+			pinfo = skb_shinfo(skb);
+			frag_cnt = pinfo->nr_frags;
+		}
+		if (frag_cnt == 0) {
+			skb_put_data(ncm->skb_tx_data, skb->data, skb->len);
+		} else {
+			skb_put_data(ncm->skb_tx_data, skb->data,
+				skb->len - skb->data_len);
+
+			for (frag_idx = 0; frag_idx < frag_cnt; frag_idx++) {
+				frag = pinfo->frags + frag_idx;
+				frag_data_len = skb_frag_size(frag);
+				frag_data_addr = skb_frag_address(frag);
+
+				skb_put_data(ncm->skb_tx_data, frag_data_addr,
+					frag_data_len);
+			}
+		}
+
 		dev_consume_skb_any(skb);
 		skb = NULL;
 
 	} else if (ncm->skb_tx_data && ncm->timer_force_tx) {
 		/* If the tx was requested because of a timeout then send */
 		skb2 = package_for_tx(ncm);
-		if (!skb2)
+		if (!skb2) {
+			LOGE("skb and skb2 are null\n");
 			goto err;
+		}
 	}
 
 	return skb2;
@@ -1180,9 +1247,11 @@
 	int		ndp_index;
 	unsigned	dg_len, dg_len2;
 	unsigned	ndp_len;
+	unsigned	block_len;
 	struct sk_buff	*skb2;
 	int		ret = -EINVAL;
-	unsigned	max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
+	unsigned	ntb_max = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
+	unsigned	frame_max = le16_to_cpu(ecm_desc.wMaxSegmentSize);
 	const struct ndp_parser_opts *opts = ncm->parser_opts;
 	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
 	int		dgram_counter;
@@ -1193,7 +1262,6 @@
 			skb->len);
 		print_hex_dump(KERN_INFO, "HEAD:", DUMP_PREFIX_ADDRESS, 32, 1,
 			       skb->data, 32, false);
-
 		goto err;
 	}
 	tmp += 2;
@@ -1204,8 +1272,9 @@
 	}
 	tmp++; /* skip wSequence */
 
+	block_len = get_ncm(&tmp, opts->block_length);
 	/* (d)wBlockLength */
-	if (get_ncm(&tmp, opts->block_length) > max_size) {
+	if (block_len > ntb_max) {
 		INFO(port->func.config->cdev, "OUT size exceeded\n");
 		goto err;
 	}
@@ -1214,15 +1283,23 @@
 
 	/* Run through all the NDP's in the NTB */
 	do {
-		/* NCM 3.2 */
-		if (((ndp_index % 4) != 0) &&
-				(ndp_index < opts->nth_size)) {
+		/*
+		 * NCM 3.2
+		 * dwNdpIndex
+		 */
+		if (((ndp_index % 4) != 0) ||
+				(ndp_index < opts->nth_size) ||
+				(ndp_index > (block_len -
+					      opts->ndp_size))) {
 			INFO(port->func.config->cdev, "Bad index: %#X\n",
 			     ndp_index);
 			goto err;
 		}
 
-		/* walk through NDP */
+		/*
+		 * walk through NDP
+		 * dwSignature
+		 */
 		tmp = (void *)(skb->data + ndp_index);
 		if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
 			INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
@@ -1233,14 +1310,15 @@
 		ndp_len = get_unaligned_le16(tmp++);
 		/*
 		 * NCM 3.3.1
+		 * wLength
 		 * entry is 2 items
 		 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
 		 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
 		 * Each entry is a dgram index and a dgram length.
 		 */
 		if ((ndp_len < opts->ndp_size
-				+ 2 * 2 * (opts->dgram_item_len * 2))
-				|| (ndp_len % opts->ndplen_align != 0)) {
+				+ 2 * 2 * (opts->dgram_item_len * 2)) ||
+				(ndp_len % opts->ndplen_align != 0)) {
 			INFO(port->func.config->cdev, "Bad NDP length: %#X\n",
 			     ndp_len);
 			goto err;
@@ -1257,8 +1335,21 @@
 
 		do {
 			index = index2;
+			/* wDatagramIndex[0] */
+			if ((index < opts->nth_size) ||
+					(index > block_len - opts->dpe_size)) {
+				INFO(port->func.config->cdev,
+				     "Bad index: %#X\n", index);
+				goto err;
+			}
+
 			dg_len = dg_len2;
-			if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */
+			/*
+			 * wDatagramLength[0]
+			 * ethernet hdr + crc or larger than max frame size
+			 */
+			if ((dg_len < 14 + crc_len) ||
+					(dg_len > frame_max)) {
 				INFO(port->func.config->cdev,
 				     "Bad dgram length: %#X\n", dg_len);
 				goto err;
@@ -1282,14 +1373,23 @@
 			index2 = get_ncm(&tmp, opts->dgram_item_len);
 			dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
 
+			/* wDatagramIndex[1] */
+			if (index2 > block_len - opts->dpe_size) {
+				INFO(port->func.config->cdev,
+				     "Bad index: %#X\n", index2);
+				goto err;
+			}
+
 			/*
 			 * Copy the data into a new skb.
 			 * This ensures the truesize is correct
 			 */
 			skb2 = netdev_alloc_skb_ip_align(ncm->netdev,
 							 dg_len - crc_len);
-			if (skb2 == NULL)
+			if (skb2 == NULL) {
+				LOGE("skb2 alloc fail\n");
 				goto err;
+			}
 			skb_put_data(skb2, skb->data + index,
 				     dg_len - crc_len);
 
@@ -1298,7 +1398,6 @@
 			ndp_len -= 2 * (opts->dgram_item_len * 2);
 
 			dgram_counter++;
-
 			if (index2 == 0 || dg_len2 == 0)
 				break;
 		} while (ndp_len > 2 * (opts->dgram_item_len * 2));
@@ -1318,9 +1417,10 @@
 static void ncm_disable(struct usb_function *f)
 {
 	struct f_ncm		*ncm = func_to_ncm(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
+	//struct usb_composite_dev *cdev = f->config->cdev;
 
-	DBG(cdev, "ncm deactivated\n");
+	//DBG(cdev, "ncm deactivated\n");
+	LOGI("\n");
 
 	if (ncm->port.in_ep->enabled) {
 		ncm->timer_stopping = true;
@@ -1358,7 +1458,8 @@
 {
 	struct f_ncm		*ncm = func_to_ncm(&geth->func);
 
-	DBG(ncm->port.func.config->cdev, "%s\n", __func__);
+	//DBG(ncm->port.func.config->cdev, "%s\n", __func__);
+	LOGI("\n");
 
 	spin_lock(&ncm->lock);
 	ncm->is_open = true;
@@ -1370,7 +1471,8 @@
 {
 	struct f_ncm		*ncm = func_to_ncm(&geth->func);
 
-	DBG(ncm->port.func.config->cdev, "%s\n", __func__);
+	//DBG(ncm->port.func.config->cdev, "%s\n", __func__);
+	LOGI("\n");
 
 	spin_lock(&ncm->lock);
 	ncm->is_open = false;
@@ -1391,10 +1493,22 @@
 	struct usb_ep		*ep;
 	struct f_ncm_opts	*ncm_opts;
 
+	LOGI("\n");
+
 	if (!can_support_ecm(cdev->gadget))
 		return -EINVAL;
 
 	ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst);
+
+	if (cdev->use_os_string) {
+		f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+					   GFP_KERNEL);
+		if (!f->os_desc_table)
+			return -ENOMEM;
+		f->os_desc_n = 1;
+		f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
+	}
+
 	/*
 	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
 	 * configurations are bound in sequence with list_for_each_entry,
@@ -1408,13 +1522,15 @@
 		status = gether_register_netdev(ncm_opts->net);
 		mutex_unlock(&ncm_opts->lock);
 		if (status)
-			return status;
+			goto fail;
 		ncm_opts->bound = true;
 	}
 	us = usb_gstrings_attach(cdev, ncm_strings,
 				 ARRAY_SIZE(ncm_string_defs));
-	if (IS_ERR(us))
-		return PTR_ERR(us);
+	if (IS_ERR(us)) {
+		status = PTR_ERR(us);
+		goto fail;
+	}
 	ncm_control_intf.iInterface = us[STRING_CTRL_IDX].id;
 	ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX].id;
 	ncm_data_intf.iInterface = us[STRING_DATA_IDX].id;
@@ -1431,6 +1547,10 @@
 	ncm_control_intf.bInterfaceNumber = status;
 	ncm_union_desc.bMasterInterface0 = status;
 
+	if (cdev->use_os_string)
+		f->os_desc_table[0].if_id =
+			ncm_iad_desc.bFirstInterface;
+
 	status = usb_interface_id(c, f);
 	if (status < 0)
 		goto fail;
@@ -1486,7 +1606,7 @@
 		fs_ncm_notify_desc.bEndpointAddress;
 
 	status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
-			ncm_ss_function, NULL);
+			ncm_ss_function, ncm_ss_function);
 	if (status)
 		goto fail;
 
@@ -1502,7 +1622,12 @@
 	hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
 	ncm->task_timer.function = ncm_tx_timeout;
 
-	DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+	//DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+	//		gadget_is_superspeed(c->cdev->gadget) ? "super" :
+	//		gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+	//		ncm->port.in_ep->name, ncm->port.out_ep->name,
+	//		ncm->notify->name);
+	LOGI("CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			ncm->port.in_ep->name, ncm->port.out_ep->name,
@@ -1510,12 +1635,16 @@
 	return 0;
 
 fail:
+	kfree(f->os_desc_table);
+	f->os_desc_n = 0;
+
 	if (ncm->notify_req) {
 		kfree(ncm->notify_req->buf);
 		usb_ep_free_request(ncm->notify, ncm->notify_req);
 	}
 
-	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+	//ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+	LOGE("%s: can't bind, err %d\n", f->name, status);
 
 	return status;
 }
@@ -1564,26 +1693,51 @@
 		gether_cleanup(netdev_priv(opts->net));
 	else
 		free_netdev(opts->net);
+	kfree(opts->ncm_interf_group);
 	kfree(opts);
 }
 
 static struct usb_function_instance *ncm_alloc_inst(void)
 {
 	struct f_ncm_opts *opts;
+	struct usb_os_desc *descs[1];
+	char *names[1];
+	struct config_group *ncm_interf_group;
+
+	LOGI("\n");
 
 	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
-	if (!opts)
+	if (!opts) {
+		LOGE("opts alloc fail\n");
 		return ERR_PTR(-ENOMEM);
+	}
+	opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id;
+
 	mutex_init(&opts->lock);
 	opts->func_inst.free_func_inst = ncm_free_inst;
-	opts->net = gether_setup_default();
+	//opts->net = gether_setup_default();
+	opts->net = gether_setup_name_default("ncm");
 	if (IS_ERR(opts->net)) {
 		struct net_device *net = opts->net;
 		kfree(opts);
+		LOGE("gether_setup_name_default fail\n");
 		return ERR_CAST(net);
 	}
+	INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop);
+
+	descs[0] = &opts->ncm_os_desc;
+	names[0] = "ncm";
 
 	config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type);
+	ncm_interf_group =
+		usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
+					       names, THIS_MODULE);
+	if (IS_ERR(ncm_interf_group)) {
+		LOGE("usb_os_desc_prepare_interf_dir fail\n");
+		ncm_free_inst(&opts->func_inst);
+		return ERR_CAST(ncm_interf_group);
+	}
+	opts->ncm_interf_group = ncm_interf_group;
 
 	return &opts->func_inst;
 }
@@ -1593,6 +1747,8 @@
 	struct f_ncm *ncm;
 	struct f_ncm_opts *opts;
 
+	LOGI("\n");
+
 	ncm = func_to_ncm(f);
 	opts = container_of(f->fi, struct f_ncm_opts, func_inst);
 	kfree(ncm);
@@ -1605,13 +1761,22 @@
 {
 	struct f_ncm *ncm = func_to_ncm(f);
 
-	DBG(c->cdev, "ncm unbind\n");
+	//DBG(c->cdev, "ncm unbind\n");
+	LOGI("\n");
 
 	hrtimer_cancel(&ncm->task_timer);
 
+	kfree(f->os_desc_table);
+	f->os_desc_n = 0;
+
 	ncm_string_defs[0].id = 0;
 	usb_free_all_descriptors(f);
 
+	if (atomic_read(&ncm->notify_count)) {
+		usb_ep_dequeue(ncm->notify, ncm->notify_req);
+		atomic_set(&ncm->notify_count, 0);
+	}
+
 	kfree(ncm->notify_req->buf);
 	usb_ep_free_request(ncm->notify, ncm->notify_req);
 }
@@ -1622,10 +1787,14 @@
 	struct f_ncm_opts	*opts;
 	int status;
 
+	LOGI("\n");
+
 	/* allocate and initialize one new instance */
 	ncm = kzalloc(sizeof(*ncm), GFP_KERNEL);
-	if (!ncm)
+	if (!ncm) {
+		LOGE("ncm alloc fail\n");
 		return ERR_PTR(-ENOMEM);
+	}
 
 	opts = container_of(fi, struct f_ncm_opts, func_inst);
 	mutex_lock(&opts->lock);
@@ -1635,6 +1804,7 @@
 	status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr,
 				      sizeof(ncm->ethaddr));
 	if (status < 12) { /* strlen("01234567890a") */
+		LOGE("host addr len < 12 is unexpected\n");
 		kfree(ncm);
 		mutex_unlock(&opts->lock);
 		return ERR_PTR(-EINVAL);
diff --git a/src/kernel/linux/v4.19/drivers/usb/gadget/function/rndis.c b/src/kernel/linux/v4.19/drivers/usb/gadget/function/rndis.c
old mode 100644
new mode 100755
index 8d8f528..402fc83
--- a/src/kernel/linux/v4.19/drivers/usb/gadget/function/rndis.c
+++ b/src/kernel/linux/v4.19/drivers/usb/gadget/function/rndis.c
@@ -1175,7 +1175,7 @@
 		skb_pull(skb, data_offset + 8);
 		num_pkts++;
 
-		if (msg_len == skb->len || data_len == (skb->len -1)) {
+		if (msg_len == skb->len || data_len == skb->len) {
 			skb_trim(skb, data_len);
 			break;
 		}
diff --git a/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ether.c b/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ether.c
index 184fcb9..ce6a15e 100755
--- a/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ether.c
+++ b/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ether.c
@@ -606,6 +606,9 @@
 	U_ETHER_DBG("%s: to_usb=%d, net->name=%s\n",
 			__func__, to_usb, net->name);
 
+	if (skb == NULL)
+		return 1;
+
 	skb->dev = net;
 
 	if (to_usb) {
@@ -934,7 +937,8 @@
 		return NETDEV_TX_OK;
 	}
 
-	iph = skb->encapsulation ? inner_ip_hdr(skb): ip_hdr(skb);
+	if (skb)
+		iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
 
 	if (uether_tx_rtt_profile)	{
 		rtt_tx_start_time = ktime_get();
@@ -972,7 +976,7 @@
 	}
 
 	/* apply outgoing CDC or RNDIS filters */
-	if (!is_promisc(cdc_filter)) {
+	if (skb && !is_promisc(cdc_filter)) {
 		u8		*dest = skb->data;
 
 		if (is_multicast_ether_addr(dest)) {
diff --git a/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ncm.h b/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ncm.h
old mode 100644
new mode 100755
index 67324f9..aac3082
--- a/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ncm.h
+++ b/src/kernel/linux/v4.19/drivers/usb/gadget/function/u_ncm.h
@@ -7,7 +7,7 @@
  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
  */
 
 #ifndef U_NCM_H
@@ -15,11 +15,26 @@
 
 #include <linux/usb/composite.h>
 
+#define NCM_VER "1.00"
+//1.00 initial version
+
+#define LOGD(fmt, args...) \
+	pr_emerg("%s NCM DBG, %s, " fmt, NCM_VER, __func__, ## args)
+
+#define LOGI(fmt, args...) \
+	pr_emerg("%s NCM LOG, %s, " fmt, NCM_VER, __func__, ## args)
+
+#define LOGE(fmt, args...) \
+	pr_emerg("%s NCM ERR, %s, " fmt, NCM_VER, __func__, ## args)
+
 struct f_ncm_opts {
 	struct usb_function_instance	func_inst;
 	struct net_device		*net;
 	bool				bound;
 
+	struct config_group		*ncm_interf_group;
+	struct usb_os_desc		ncm_os_desc;
+	char				ncm_ext_compat_id[16];
 	/*
 	 * Read/write access to configfs attributes is handled by configfs.
 	 *
diff --git a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3.h b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3.h
index dc334b1..9606963 100755
--- a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3.h
+++ b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3.h
@@ -508,6 +508,8 @@
 void mtu3_gadget_resume(struct mtu3 *mtu);
 void mtu3_gadget_disconnect(struct mtu3 *mtu);
 
+int mtu3_usb_vbus_detect_init(struct ssusb_mtk *ssusb);//tianyan@2021.11.29 modify for usb otg
+
 irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu);
 extern const struct usb_ep_ops mtu3_ep0_ops;
 
diff --git a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_core.c b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_core.c
index e0ce587..c45daca 100755
--- a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_core.c
+++ b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_core.c
@@ -287,8 +287,12 @@
 void mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
 {
 #ifndef CONFIG_MTU3_MD_USB_EP0_CTRL
-	if (mtu->is_u3_ip && mtu->max_speed >= USB_SPEED_SUPER)
+	if (mtu->is_u3_ip && mtu->max_speed >= USB_SPEED_SUPER){
 		mtu3_ss_func_set(mtu, is_on);
+		dev_dbg(mtu->dev, "%s\n", usb_speed_string(mtu->g.speed));
+		if (!is_on && mtu->g.speed < USB_SPEED_SUPER)
+			mtu3_hs_softconn_set(mtu, is_on);
+	}
 	else
 		mtu3_hs_softconn_set(mtu, is_on);
 #endif
@@ -368,7 +372,8 @@
 
 static irqreturn_t mtu3_vbus_detect_eint_isr(int irq, void *data)
 {
-	struct mtu3 *mtu = data;
+	struct ssusb_mtk *ssusb = data;//tianyan@2021.11.29 modify for usb otg
+	struct mtu3 *mtu = ssusb->u3d;//tianyan@2021.11.29 modify for usb otg
 
 	disable_irq_nosync(irq);
 
@@ -376,19 +381,24 @@
 		dev_info(mtu->dev, "low-level, vbus plug out\n");
 		ssusb_set_force_vbus(mtu->ssusb, false);
 		irq_set_irq_type(irq, IRQF_TRIGGER_HIGH);
+		ssusb->otg_switch.vbus_nb.notifier_call(&ssusb->otg_switch.vbus_nb,false,NULL);//tianyan@2021.11.29 modify for usb otg
 	} else {
 		dev_info(mtu->dev, "high-level, vbus plug in\n");
 		ssusb_set_force_vbus(mtu->ssusb, true);
 		irq_set_irq_type(irq, IRQF_TRIGGER_LOW);
+		ssusb->otg_switch.vbus_nb.notifier_call(&ssusb->otg_switch.vbus_nb,true,NULL);//tianyan@2021.11.29 modify for usb otg
 	}
 	enable_irq(irq);
 	return IRQ_HANDLED;
 }
 
-static int mtu3_usb_vbus_detect_init(struct mtu3 *mtu)
+int mtu3_usb_vbus_detect_init(struct ssusb_mtk *ssusb)//tianyan@2021.11.29 modify for usb otg
 {
 	struct device_node *node;
 	int ret;
+	struct mtu3 *mtu = ssusb->u3d;//tianyan@2021.11.29 modify for usb otg
+	
+	return 0;//tianyan@2021.11.29 modify for usb otg
 
 	node = of_find_compatible_node(NULL, NULL,
 					"mediatek,mtu3");
@@ -435,7 +445,7 @@
 	}
 
 	ret = request_irq(mtu->detect_irq, mtu3_vbus_detect_eint_isr,
-				   IRQF_TRIGGER_LOW, "mtu_detect_eint", mtu);
+				   IRQF_TRIGGER_HIGH, "mtu_detect_eint", ssusb);//tianyan@2021.11.29 modify for usb otg
 	if (ret) {
 		dev_err(mtu->dev, "request eint(%d) fail (%d)\n",
 				   mtu->detect_irq, ret);
@@ -1109,7 +1119,7 @@
 		dev_err(dev, "mtu3 gadget init failed:%d\n", ret);
 		goto gadget_err;
 	}
-	mtu3_usb_vbus_detect_init(mtu);
+	
 	/* init as host mode, power down device IP for power saving */
 	if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG)
 		mtu3_stop(mtu);
diff --git a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_dr.c b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_dr.c
index 3a3ef38..6fb327d 100755
--- a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_dr.c
+++ b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_dr.c
@@ -42,12 +42,10 @@
 
 static void toggle_opstate(struct ssusb_mtk *ssusb)
 {
-	dev_info(ssusb->dev, "%s\n", __func__);
+     dev_info(ssusb->dev, "%s\n", __func__);
 	//if (!ssusb->otg_switch.is_u3_drd) {//zhengzhou 0318 usb otg */
-	if (!ssusb->otg_switch.is_u3_drd) {
 		mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION);
 		mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN);
-	}
 	//}
 }
 
@@ -257,7 +255,7 @@
 
 	if (otg_sx->id_event){
 		mdelay(500);
-		pm_stay_awake(ssusb->dev);
+		pm_stay_awake(ssusb->dev);//tianyan@2021.11.29 modify for usb otg
 		switch_port_to_on(ssusb, true);
 		ssusb_host_enable(ssusb);
 		/* register host driver */
@@ -273,7 +271,7 @@
 		of_platform_depopulate(ssusb->dev);
 		ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
 		switch_port_to_on(ssusb, false);
-		pm_relax(ssusb->dev);
+		pm_relax(ssusb->dev);//tianyan@2021.11.29 modify for usb otg
 		}
 		//zhengzhou 0318 usb otg end*/
 }
diff --git a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_plat.c b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_plat.c
index b3e4b08..3005550 100755
--- a/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_plat.c
+++ b/src/kernel/linux/v4.19/drivers/usb/mtu3/mtu3_plat.c
@@ -755,6 +755,7 @@
 			dev_err(dev, "failed to initialize switch\n");
 			goto host_exit;
 		}
+		mtu3_usb_vbus_detect_init(ssusb);//tianyan@2021.11.29 modify for usb otg
 		break;
 	default:
 		dev_err(dev, "unsupported mode: %d\n", ssusb->dr_mode);
@@ -836,9 +837,13 @@
 
 	dev_info(dev, "%s\n", __func__);
 
+	//enable_irq_wake(ssusb->u3d->detect_irq);//tianyan@2021.11.29 modify for usb otg
 	/* REVISIT: disconnect it for only device mode? */
-	if (!ssusb->is_host)
+	if (!ssusb->is_host){//tianyan@2021.11.29 modify for usb otg
+		ssusb_phy_power_off(ssusb);
+		ssusb_clks_disable(ssusb);
 		return 0;
+	}
 
 	ssusb_host_disable(ssusb, true);
 	ssusb_phy_power_off(ssusb);
@@ -854,9 +859,17 @@
 	int ret;
 
 	dev_info(dev, "%s\n", __func__);
-
-	if (!ssusb->is_host)
+	//disable_irq_wake(ssusb->u3d->detect_irq);//tianyan@2021.11.29 modify for usb otg
+	
+	if (!ssusb->is_host){//tianyan@2021.11.29 modify for usb otg
+		ret = ssusb_clks_enable(ssusb);
+		if (ret)
+			goto clks_err;
+		ret = ssusb_phy_power_on(ssusb);
+		if (ret)
+			goto phy_err;
 		return 0;
+	}
 
 	ssusb_wakeup_set(ssusb, false);
 	ret = ssusb_clks_enable(ssusb);
diff --git a/src/kernel/linux/v4.19/include/dt-bindings/clock/mt6890-clk.h b/src/kernel/linux/v4.19/include/dt-bindings/clock/mt6890-clk.h
index b55fac6..b345ae8 100755
--- a/src/kernel/linux/v4.19/include/dt-bindings/clock/mt6890-clk.h
+++ b/src/kernel/linux/v4.19/include/dt-bindings/clock/mt6890-clk.h
@@ -215,7 +215,7 @@
 #define CLK_TOP_NETSYS_SEL		202
 #define CLK_TOP_MEDSYS_SEL		203
 #define CLK_TOP_HSM_CRYPTO_SEL		204 /* no use */
-#define CLK_TOP_HSM_ARC_SEL		205 /* no use */
+#define CLK_TOP_HSM_ARC_SEL		205
 #define CLK_TOP_EIP97_SEL		206
 #define CLK_TOP_SNPS_ETH_312P5M_SEL	207
 #define CLK_TOP_SNPS_ETH_250M_SEL	208
diff --git a/src/kernel/linux/v4.19/include/linux/mfd/mt6330/core.h b/src/kernel/linux/v4.19/include/linux/mfd/mt6330/core.h
old mode 100644
new mode 100755
index aebf8c6..a2596a6
--- a/src/kernel/linux/v4.19/include/linux/mfd/mt6330/core.h
+++ b/src/kernel/linux/v4.19/include/linux/mfd/mt6330/core.h
@@ -29,6 +29,14 @@
 	MT6330_SCK_TOP = 13,
 };
 
+enum mt6330_irq_top_mask_shift {
+	MT6330_BUCK_TOP_MASK = 0,
+	MT6330_LDO_TOP_MASK = 1,
+	MT6330_PSC_TOP_MASK = 2,
+	MT6330_MISC_TOP_MASK = 3,
+	MT6330_SCK_TOP_MASK = 5,
+};
+
 enum mt6330_irq_numbers {
 	MT6330_IRQ_VCORE_OC = 0,
 	MT6330_IRQ_VMD11_OC = 1,
@@ -115,6 +123,7 @@
 	.sta_reg = MT6330_##sp##_TOP_INT_STATUS0,		\
 	.sta_reg_shift = 0x1,	\
 	.top_offset = MT6330_##sp##_TOP,	\
+	.top_mask_offset = MT6330_##sp##_TOP_MASK,	\
 }
 
 struct mt6330_chip {
diff --git a/src/kernel/linux/v4.19/include/net/ra_nat.h b/src/kernel/linux/v4.19/include/net/ra_nat.h
old mode 100644
new mode 100755
index 5963011..189e119
--- a/src/kernel/linux/v4.19/include/net/ra_nat.h
+++ b/src/kernel/linux/v4.19/include/net/ra_nat.h
@@ -544,5 +544,8 @@
 #define QDMA_RX		5
 #define PDMA_RX		0
 
+#if defined(CONFIG_HW_NAT)
+void mtk_hook_fast_path(struct net_device *dev);
+#endif
 
 #endif
diff --git a/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_RATEEST.h b/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_RATEEST.h
old mode 100644
new mode 100755
index 2b87a71..52a37bd
--- a/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_RATEEST.h
+++ b/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_RATEEST.h
@@ -1,17 +1,39 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _XT_RATEEST_TARGET_H
-#define _XT_RATEEST_TARGET_H
+#ifndef _XT_RATEEST_MATCH_H
+#define _XT_RATEEST_MATCH_H
 
 #include <linux/types.h>
 #include <linux/if.h>
 
-struct xt_rateest_target_info {
-	char			name[IFNAMSIZ];
-	__s8			interval;
-	__u8		ewma_log;
-
-	/* Used internally by the kernel */
-	struct xt_rateest	*est __attribute__((aligned(8)));
+enum xt_rateest_match_flags {
+	XT_RATEEST_MATCH_INVERT	= 1<<0,
+	XT_RATEEST_MATCH_ABS	= 1<<1,
+	XT_RATEEST_MATCH_REL	= 1<<2,
+	XT_RATEEST_MATCH_DELTA	= 1<<3,
+	XT_RATEEST_MATCH_BPS	= 1<<4,
+	XT_RATEEST_MATCH_PPS	= 1<<5,
 };
 
-#endif /* _XT_RATEEST_TARGET_H */
+enum xt_rateest_match_mode {
+	XT_RATEEST_MATCH_NONE,
+	XT_RATEEST_MATCH_EQ,
+	XT_RATEEST_MATCH_LT,
+	XT_RATEEST_MATCH_GT,
+};
+
+struct xt_rateest_match_info {
+	char			name1[IFNAMSIZ];
+	char			name2[IFNAMSIZ];
+	__u16		flags;
+	__u16		mode;
+	__u32		bps1;
+	__u32		pps1;
+	__u32		bps2;
+	__u32		pps2;
+
+	/* Used internally by the kernel */
+	struct xt_rateest	*est1 __attribute__((aligned(8)));
+	struct xt_rateest	*est2 __attribute__((aligned(8)));
+};
+
+#endif /* _XT_RATEEST_MATCH_H */
diff --git a/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_TCPMSS.h b/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_TCPMSS.h
old mode 100644
new mode 100755
index 65ea6c9..2268f58
--- a/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_TCPMSS.h
+++ b/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_TCPMSS.h
@@ -1,13 +1,12 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _XT_TCPMSS_H
-#define _XT_TCPMSS_H
+#ifndef _XT_TCPMSS_MATCH_H
+#define _XT_TCPMSS_MATCH_H
 
 #include <linux/types.h>
 
-struct xt_tcpmss_info {
-	__u16 mss;
+struct xt_tcpmss_match_info {
+    __u16 mss_min, mss_max;
+    __u8 invert;
 };
 
-#define XT_TCPMSS_CLAMP_PMTU 0xffff
-
-#endif /* _XT_TCPMSS_H */
+#endif /*_XT_TCPMSS_MATCH_H*/
diff --git a/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_dscp.h b/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_dscp.h
old mode 100644
new mode 100755
index 7594e4d..223d635
--- a/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_dscp.h
+++ b/src/kernel/linux/v4.19/include/uapi/linux/netfilter/xt_dscp.h
@@ -1,32 +1,27 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* x_tables module for matching the IPv4/IPv6 DSCP field
+/* x_tables module for setting the IPv4/IPv6 DSCP field
  *
  * (C) 2002 Harald Welte <laforge@gnumonks.org>
+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
  * This software is distributed under GNU GPL v2, 1991
  *
  * See RFC2474 for a description of the DSCP field within the IP Header.
  *
- * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp
+ * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp
 */
-#ifndef _XT_DSCP_H
-#define _XT_DSCP_H
-
+#ifndef _XT_DSCP_TARGET_H
+#define _XT_DSCP_TARGET_H
+#include <linux/netfilter/xt_dscp.h>
 #include <linux/types.h>
 
-#define XT_DSCP_MASK	0xfc	/* 11111100 */
-#define XT_DSCP_SHIFT	2
-#define XT_DSCP_MAX	0x3f	/* 00111111 */
-
-/* match info */
-struct xt_dscp_info {
+/* target info */
+struct xt_DSCP_info {
 	__u8 dscp;
-	__u8 invert;
 };
 
-struct xt_tos_match_info {
-	__u8 tos_mask;
+struct xt_tos_target_info {
 	__u8 tos_value;
-	__u8 invert;
+	__u8 tos_mask;
 };
 
-#endif /* _XT_DSCP_H */
+#endif /* _XT_DSCP_TARGET_H */
diff --git a/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_TTL.h b/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_TTL.h
old mode 100644
new mode 100755
index 57d2fc6..ad0226a
--- a/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_TTL.h
+++ b/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_TTL.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* TTL modification module for IP tables
- * (C) 2000 by Harald Welte <laforge@netfilter.org> */
+/* IP tables module for matching the value of the TTL
+ * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
 
 #ifndef _IPT_TTL_H
 #define _IPT_TTL_H
@@ -8,14 +8,14 @@
 #include <linux/types.h>
 
 enum {
-	IPT_TTL_SET = 0,
-	IPT_TTL_INC,
-	IPT_TTL_DEC
+	IPT_TTL_EQ = 0,		/* equals */
+	IPT_TTL_NE,		/* not equals */
+	IPT_TTL_LT,		/* less than */
+	IPT_TTL_GT,		/* greater than */
 };
 
-#define IPT_TTL_MAXMODE	IPT_TTL_DEC
 
-struct ipt_TTL_info {
+struct ipt_ttl_info {
 	__u8	mode;
 	__u8	ttl;
 };
diff --git a/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_ecn.h b/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_ecn.h
old mode 100644
new mode 100755
index 8121bec..e3630fd
--- a/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_ecn.h
+++ b/src/kernel/linux/v4.19/include/uapi/linux/netfilter_ipv4/ipt_ecn.h
@@ -1,16 +1,34 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _IPT_ECN_H
-#define _IPT_ECN_H
+/* Header file for iptables ipt_ECN target
+ *
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ * 
+ * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp
+*/
+#ifndef _IPT_ECN_TARGET_H
+#define _IPT_ECN_TARGET_H
 
-#include <linux/netfilter/xt_ecn.h>
-#define ipt_ecn_info xt_ecn_info
+#include <linux/types.h>
+#include <linux/netfilter/xt_DSCP.h>
 
-enum {
-	IPT_ECN_IP_MASK       = XT_ECN_IP_MASK,
-	IPT_ECN_OP_MATCH_IP   = XT_ECN_OP_MATCH_IP,
-	IPT_ECN_OP_MATCH_ECE  = XT_ECN_OP_MATCH_ECE,
-	IPT_ECN_OP_MATCH_CWR  = XT_ECN_OP_MATCH_CWR,
-	IPT_ECN_OP_MATCH_MASK = XT_ECN_OP_MATCH_MASK,
+#define IPT_ECN_IP_MASK	(~XT_DSCP_MASK)
+
+#define IPT_ECN_OP_SET_IP	0x01	/* set ECN bits of IPv4 header */
+#define IPT_ECN_OP_SET_ECE	0x10	/* set ECE bit of TCP header */
+#define IPT_ECN_OP_SET_CWR	0x20	/* set CWR bit of TCP header */
+
+#define IPT_ECN_OP_MASK		0xce
+
+struct ipt_ECN_info {
+	__u8 operation;	/* bitset of operations */
+	__u8 ip_ect;	/* ECT codepoint of IPv4 header, pre-shifted */
+	union {
+		struct {
+			__u8 ece:1, cwr:1; /* TCP ECT bits */
+		} tcp;
+	} proto;
 };
 
-#endif /* IPT_ECN_H */
+#endif /* _IPT_ECN_TARGET_H */
diff --git a/src/kernel/linux/v4.19/net/netfilter/xt_TCPMSS.c b/src/kernel/linux/v4.19/net/netfilter/xt_TCPMSS.c
old mode 100644
new mode 100755
index 98efb20..c53d4d1
--- a/src/kernel/linux/v4.19/net/netfilter/xt_TCPMSS.c
+++ b/src/kernel/linux/v4.19/net/netfilter/xt_TCPMSS.c
@@ -1,348 +1,110 @@
-/*
- * This is a module which is used for setting the MSS option in TCP packets.
- *
- * Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
- * Copyright (C) 2007 Patrick McHardy <kaber@trash.net>
+/* Kernel module to match TCP MSS values. */
+
+/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
+ * Portions (C) 2005 by Harald Welte <laforge@netfilter.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/gfp.h>
-#include <linux/ipv6.h>
-#include <linux/tcp.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/ipv6.h>
-#include <net/route.h>
 #include <net/tcp.h>
 
+#include <linux/netfilter/xt_tcpmss.h>
+#include <linux/netfilter/x_tables.h>
+
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter/xt_tcpudp.h>
-#include <linux/netfilter/xt_TCPMSS.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment");
-MODULE_ALIAS("ipt_TCPMSS");
-MODULE_ALIAS("ip6t_TCPMSS");
+MODULE_DESCRIPTION("Xtables: TCP MSS match");
+MODULE_ALIAS("ipt_tcpmss");
+MODULE_ALIAS("ip6t_tcpmss");
 
-static inline unsigned int
-optlen(const u_int8_t *opt, unsigned int offset)
+static bool
+tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
-	/* Beware zero-length options: make finite progress */
-	if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
-		return 1;
-	else
-		return opt[offset+1];
-}
+	const struct xt_tcpmss_match_info *info = par->matchinfo;
+	const struct tcphdr *th;
+	struct tcphdr _tcph;
+	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+	const u_int8_t *op;
+	u8 _opt[15 * 4 - sizeof(_tcph)];
+	unsigned int i, optlen;
 
-static u_int32_t tcpmss_reverse_mtu(struct net *net,
-				    const struct sk_buff *skb,
-				    unsigned int family)
-{
-	struct flowi fl;
-	struct rtable *rt = NULL;
-	u_int32_t mtu     = ~0U;
+	/* If we don't have the whole header, drop packet. */
+	th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
+	if (th == NULL)
+		goto dropit;
 
-	if (family == PF_INET) {
-		struct flowi4 *fl4 = &fl.u.ip4;
-		memset(fl4, 0, sizeof(*fl4));
-		fl4->daddr = ip_hdr(skb)->saddr;
-	} else {
-		struct flowi6 *fl6 = &fl.u.ip6;
+	/* Malformed. */
+	if (th->doff*4 < sizeof(*th))
+		goto dropit;
 
-		memset(fl6, 0, sizeof(*fl6));
-		fl6->daddr = ipv6_hdr(skb)->saddr;
-	}
+	optlen = th->doff*4 - sizeof(*th);
+	if (!optlen)
+		goto out;
 
-	nf_route(net, (struct dst_entry **)&rt, &fl, false, family);
-	if (rt != NULL) {
-		mtu = dst_mtu(&rt->dst);
-		dst_release(&rt->dst);
-	}
-	return mtu;
-}
+	/* Truncated options. */
+	op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt);
+	if (op == NULL)
+		goto dropit;
 
-static int
-tcpmss_mangle_packet(struct sk_buff *skb,
-		     const struct xt_action_param *par,
-		     unsigned int family,
-		     unsigned int tcphoff,
-		     unsigned int minlen)
-{
-	const struct xt_tcpmss_info *info = par->targinfo;
-	struct tcphdr *tcph;
-	int len, tcp_hdrlen;
-	unsigned int i;
-	__be16 oldval;
-	u16 newmss;
-	u8 *opt;
+	for (i = 0; i < optlen; ) {
+		if (op[i] == TCPOPT_MSS
+		    && (optlen - i) >= TCPOLEN_MSS
+		    && op[i+1] == TCPOLEN_MSS) {
+			u_int16_t mssval;
 
-	/* This is a fragment, no TCP header is available */
-	if (par->fragoff != 0)
-		return 0;
+			mssval = (op[i+2] << 8) | op[i+3];
 
-	if (!skb_make_writable(skb, skb->len))
-		return -1;
-
-	len = skb->len - tcphoff;
-	if (len < (int)sizeof(struct tcphdr))
-		return -1;
-
-	tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
-	tcp_hdrlen = tcph->doff * 4;
-
-	if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr))
-		return -1;
-
-	if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
-		struct net *net = xt_net(par);
-		unsigned int in_mtu = tcpmss_reverse_mtu(net, skb, family);
-		unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu);
-
-		if (min_mtu <= minlen) {
-			net_err_ratelimited("unknown or invalid path-MTU (%u)\n",
-					    min_mtu);
-			return -1;
+			return (mssval >= info->mss_min &&
+				mssval <= info->mss_max) ^ info->invert;
 		}
-		newmss = min_mtu - minlen;
-	} else
-		newmss = info->mss;
-
-	opt = (u_int8_t *)tcph;
-	for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) {
-		if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) {
-			u_int16_t oldmss;
-
-			oldmss = (opt[i+2] << 8) | opt[i+3];
-
-			/* Never increase MSS, even when setting it, as
-			 * doing so results in problems for hosts that rely
-			 * on MSS being set correctly.
-			 */
-			if (oldmss <= newmss)
-				return 0;
-
-			opt[i+2] = (newmss & 0xff00) >> 8;
-			opt[i+3] = newmss & 0x00ff;
-
-			inet_proto_csum_replace2(&tcph->check, skb,
-						 htons(oldmss), htons(newmss),
-						 false);
-			return 0;
-		}
+		if (op[i] < 2)
+			i++;
+		else
+			i += op[i+1] ? : 1;
 	}
+out:
+	return info->invert;
 
-	/* There is data after the header so the option can't be added
-	 * without moving it, and doing so may make the SYN packet
-	 * itself too large. Accept the packet unmodified instead.
-	 */
-	if (len > tcp_hdrlen)
-		return 0;
-
-	/* tcph->doff has 4 bits, do not wrap it to 0 */
-	if (tcp_hdrlen >= 15 * 4)
-		return 0;
-
-	/*
-	 * MSS Option not found ?! add it..
-	 */
-	if (skb_tailroom(skb) < TCPOLEN_MSS) {
-		if (pskb_expand_head(skb, 0,
-				     TCPOLEN_MSS - skb_tailroom(skb),
-				     GFP_ATOMIC))
-			return -1;
-		tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
-	}
-
-	skb_put(skb, TCPOLEN_MSS);
-
-	/*
-	 * IPv4: RFC 1122 states "If an MSS option is not received at
-	 * connection setup, TCP MUST assume a default send MSS of 536".
-	 * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum
-	 * length IPv6 header of 60, ergo the default MSS value is 1220
-	 * Since no MSS was provided, we must use the default values
-	 */
-	if (xt_family(par) == NFPROTO_IPV4)
-		newmss = min(newmss, (u16)536);
-	else
-		newmss = min(newmss, (u16)1220);
-
-	opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
-	memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr));
-
-	inet_proto_csum_replace2(&tcph->check, skb,
-				 htons(len), htons(len + TCPOLEN_MSS), true);
-	opt[0] = TCPOPT_MSS;
-	opt[1] = TCPOLEN_MSS;
-	opt[2] = (newmss & 0xff00) >> 8;
-	opt[3] = newmss & 0x00ff;
-
-	inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), false);
-
-	oldval = ((__be16 *)tcph)[6];
-	tcph->doff += TCPOLEN_MSS/4;
-	inet_proto_csum_replace2(&tcph->check, skb,
-				 oldval, ((__be16 *)tcph)[6], false);
-	return TCPOLEN_MSS;
-}
-
-static unsigned int
-tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
-{
-	struct iphdr *iph = ip_hdr(skb);
-	__be16 newlen;
-	int ret;
-
-	ret = tcpmss_mangle_packet(skb, par,
-				   PF_INET,
-				   iph->ihl * 4,
-				   sizeof(*iph) + sizeof(struct tcphdr));
-	if (ret < 0)
-		return NF_DROP;
-	if (ret > 0) {
-		iph = ip_hdr(skb);
-		newlen = htons(ntohs(iph->tot_len) + ret);
-		csum_replace2(&iph->check, iph->tot_len, newlen);
-		iph->tot_len = newlen;
-	}
-	return XT_CONTINUE;
-}
-
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-static unsigned int
-tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
-{
-	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
-	u8 nexthdr;
-	__be16 frag_off, oldlen, newlen;
-	int tcphoff;
-	int ret;
-
-	nexthdr = ipv6h->nexthdr;
-	tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
-	if (tcphoff < 0)
-		return NF_DROP;
-	ret = tcpmss_mangle_packet(skb, par,
-				   PF_INET6,
-				   tcphoff,
-				   sizeof(*ipv6h) + sizeof(struct tcphdr));
-	if (ret < 0)
-		return NF_DROP;
-	if (ret > 0) {
-		ipv6h = ipv6_hdr(skb);
-		oldlen = ipv6h->payload_len;
-		newlen = htons(ntohs(oldlen) + ret);
-		if (skb->ip_summed == CHECKSUM_COMPLETE)
-			skb->csum = csum_add(csum_sub(skb->csum, oldlen),
-					     newlen);
-		ipv6h->payload_len = newlen;
-	}
-	return XT_CONTINUE;
-}
-#endif
-
-/* Must specify -p tcp --syn */
-static inline bool find_syn_match(const struct xt_entry_match *m)
-{
-	const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data;
-
-	if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
-	    tcpinfo->flg_cmp & TCPHDR_SYN &&
-	    !(tcpinfo->invflags & XT_TCP_INV_FLAGS))
-		return true;
-
+dropit:
+	par->hotdrop = true;
 	return false;
 }
 
-static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
-{
-	const struct xt_tcpmss_info *info = par->targinfo;
-	const struct ipt_entry *e = par->entryinfo;
-	const struct xt_entry_match *ematch;
-
-	if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
-	    (par->hook_mask & ~((1 << NF_INET_FORWARD) |
-			   (1 << NF_INET_LOCAL_OUT) |
-			   (1 << NF_INET_POST_ROUTING))) != 0) {
-		pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return -EINVAL;
-	}
-	if (par->nft_compat)
-		return 0;
-
-	xt_ematch_foreach(ematch, e)
-		if (find_syn_match(ematch))
-			return 0;
-	pr_info_ratelimited("Only works on TCP SYN packets\n");
-	return -EINVAL;
-}
-
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
-{
-	const struct xt_tcpmss_info *info = par->targinfo;
-	const struct ip6t_entry *e = par->entryinfo;
-	const struct xt_entry_match *ematch;
-
-	if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
-	    (par->hook_mask & ~((1 << NF_INET_FORWARD) |
-			   (1 << NF_INET_LOCAL_OUT) |
-			   (1 << NF_INET_POST_ROUTING))) != 0) {
-		pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return -EINVAL;
-	}
-	if (par->nft_compat)
-		return 0;
-
-	xt_ematch_foreach(ematch, e)
-		if (find_syn_match(ematch))
-			return 0;
-	pr_info_ratelimited("Only works on TCP SYN packets\n");
-	return -EINVAL;
-}
-#endif
-
-static struct xt_target tcpmss_tg_reg[] __read_mostly = {
+static struct xt_match tcpmss_mt_reg[] __read_mostly = {
 	{
+		.name		= "tcpmss",
 		.family		= NFPROTO_IPV4,
-		.name		= "TCPMSS",
-		.checkentry	= tcpmss_tg4_check,
-		.target		= tcpmss_tg4,
-		.targetsize	= sizeof(struct xt_tcpmss_info),
+		.match		= tcpmss_mt,
+		.matchsize	= sizeof(struct xt_tcpmss_match_info),
 		.proto		= IPPROTO_TCP,
 		.me		= THIS_MODULE,
 	},
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 	{
+		.name		= "tcpmss",
 		.family		= NFPROTO_IPV6,
-		.name		= "TCPMSS",
-		.checkentry	= tcpmss_tg6_check,
-		.target		= tcpmss_tg6,
-		.targetsize	= sizeof(struct xt_tcpmss_info),
+		.match		= tcpmss_mt,
+		.matchsize	= sizeof(struct xt_tcpmss_match_info),
 		.proto		= IPPROTO_TCP,
 		.me		= THIS_MODULE,
 	},
-#endif
 };
 
-static int __init tcpmss_tg_init(void)
+static int __init tcpmss_mt_init(void)
 {
-	return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg));
+	return xt_register_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg));
 }
 
-static void __exit tcpmss_tg_exit(void)
+static void __exit tcpmss_mt_exit(void)
 {
-	xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg));
+	xt_unregister_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg));
 }
 
-module_init(tcpmss_tg_init);
-module_exit(tcpmss_tg_exit);
+module_init(tcpmss_mt_init);
+module_exit(tcpmss_mt_exit);
diff --git a/src/kernel/linux/v4.19/net/netfilter/xt_rateest.c b/src/kernel/linux/v4.19/net/netfilter/xt_rateest.c
old mode 100644
new mode 100755
index bf77326..9e05c86
--- a/src/kernel/linux/v4.19/net/netfilter/xt_rateest.c
+++ b/src/kernel/linux/v4.19/net/netfilter/xt_rateest.c
@@ -8,149 +8,225 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/gen_stats.h>
+#include <linux/jhash.h>
+#include <linux/rtnetlink.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <net/gen_stats.h>
+#include <net/netlink.h>
+#include <net/netns/generic.h>
 
 #include <linux/netfilter/x_tables.h>
-#include <linux/netfilter/xt_rateest.h>
+#include <linux/netfilter/xt_RATEEST.h>
 #include <net/netfilter/xt_rateest.h>
 
+#define RATEEST_HSIZE	16
 
-static bool
-xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par)
+struct xt_rateest_net {
+	struct mutex hash_lock;
+	struct hlist_head hash[RATEEST_HSIZE];
+};
+
+static unsigned int xt_rateest_id;
+
+static unsigned int jhash_rnd __read_mostly;
+
+static unsigned int xt_rateest_hash(const char *name)
 {
-	const struct xt_rateest_match_info *info = par->matchinfo;
-	struct gnet_stats_rate_est64 sample = {0};
-	u_int32_t bps1, bps2, pps1, pps2;
-	bool ret = true;
+	return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) &
+	       (RATEEST_HSIZE - 1);
+}
 
-	gen_estimator_read(&info->est1->rate_est, &sample);
+static void xt_rateest_hash_insert(struct xt_rateest_net *xn,
+				   struct xt_rateest *est)
+{
+	unsigned int h;
 
-	if (info->flags & XT_RATEEST_MATCH_DELTA) {
-		bps1 = info->bps1 >= sample.bps ? info->bps1 - sample.bps : 0;
-		pps1 = info->pps1 >= sample.pps ? info->pps1 - sample.pps : 0;
-	} else {
-		bps1 = sample.bps;
-		pps1 = sample.pps;
-	}
+	h = xt_rateest_hash(est->name);
+	hlist_add_head(&est->list, &xn->hash[h]);
+}
 
-	if (info->flags & XT_RATEEST_MATCH_ABS) {
-		bps2 = info->bps2;
-		pps2 = info->pps2;
-	} else {
-		gen_estimator_read(&info->est2->rate_est, &sample);
+static struct xt_rateest *__xt_rateest_lookup(struct xt_rateest_net *xn,
+					      const char *name)
+{
+	struct xt_rateest *est;
+	unsigned int h;
 
-		if (info->flags & XT_RATEEST_MATCH_DELTA) {
-			bps2 = info->bps2 >= sample.bps ? info->bps2 - sample.bps : 0;
-			pps2 = info->pps2 >= sample.pps ? info->pps2 - sample.pps : 0;
-		} else {
-			bps2 = sample.bps;
-			pps2 = sample.pps;
+	h = xt_rateest_hash(name);
+	hlist_for_each_entry(est, &xn->hash[h], list) {
+		if (strcmp(est->name, name) == 0) {
+			est->refcnt++;
+			return est;
 		}
 	}
 
-	switch (info->mode) {
-	case XT_RATEEST_MATCH_LT:
-		if (info->flags & XT_RATEEST_MATCH_BPS)
-			ret &= bps1 < bps2;
-		if (info->flags & XT_RATEEST_MATCH_PPS)
-			ret &= pps1 < pps2;
-		break;
-	case XT_RATEEST_MATCH_GT:
-		if (info->flags & XT_RATEEST_MATCH_BPS)
-			ret &= bps1 > bps2;
-		if (info->flags & XT_RATEEST_MATCH_PPS)
-			ret &= pps1 > pps2;
-		break;
-	case XT_RATEEST_MATCH_EQ:
-		if (info->flags & XT_RATEEST_MATCH_BPS)
-			ret &= bps1 == bps2;
-		if (info->flags & XT_RATEEST_MATCH_PPS)
-			ret &= pps1 == pps2;
-		break;
-	}
-
-	ret ^= info->flags & XT_RATEEST_MATCH_INVERT ? true : false;
-	return ret;
+	return NULL;
 }
 
-static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
+struct xt_rateest *xt_rateest_lookup(struct net *net, const char *name)
 {
-	struct xt_rateest_match_info *info = par->matchinfo;
-	struct xt_rateest *est1, *est2;
-	int ret = -EINVAL;
+	struct xt_rateest_net *xn = net_generic(net, xt_rateest_id);
+	struct xt_rateest *est;
 
-	if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
-				     XT_RATEEST_MATCH_REL)) != 1)
-		goto err1;
+	mutex_lock(&xn->hash_lock);
+	est = __xt_rateest_lookup(xn, name);
+	mutex_unlock(&xn->hash_lock);
+	return est;
+}
+EXPORT_SYMBOL_GPL(xt_rateest_lookup);
 
-	if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS)))
-		goto err1;
+void xt_rateest_put(struct net *net, struct xt_rateest *est)
+{
+	struct xt_rateest_net *xn = net_generic(net, xt_rateest_id);
 
-	switch (info->mode) {
-	case XT_RATEEST_MATCH_EQ:
-	case XT_RATEEST_MATCH_LT:
-	case XT_RATEEST_MATCH_GT:
-		break;
-	default:
-		goto err1;
+	mutex_lock(&xn->hash_lock);
+	if (--est->refcnt == 0) {
+		hlist_del(&est->list);
+		gen_kill_estimator(&est->rate_est);
+		/*
+		 * gen_estimator est_timer() might access est->lock or bstats,
+		 * wait a RCU grace period before freeing 'est'
+		 */
+		kfree_rcu(est, rcu);
+	}
+	mutex_unlock(&xn->hash_lock);
+}
+EXPORT_SYMBOL_GPL(xt_rateest_put);
+
+static unsigned int
+xt_rateest_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_rateest_target_info *info = par->targinfo;
+	struct gnet_stats_basic_packed *stats = &info->est->bstats;
+
+	spin_lock_bh(&info->est->lock);
+	stats->bytes += skb->len;
+	stats->packets++;
+	spin_unlock_bh(&info->est->lock);
+
+	return XT_CONTINUE;
+}
+
+static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
+{
+	struct xt_rateest_net *xn = net_generic(par->net, xt_rateest_id);
+	struct xt_rateest_target_info *info = par->targinfo;
+	struct xt_rateest *est;
+	struct {
+		struct nlattr		opt;
+		struct gnet_estimator	est;
+	} cfg;
+	int ret;
+
+	net_get_random_once(&jhash_rnd, sizeof(jhash_rnd));
+
+	mutex_lock(&xn->hash_lock);
+	est = __xt_rateest_lookup(xn, info->name);
+	if (est) {
+		mutex_unlock(&xn->hash_lock);
+		/*
+		 * If estimator parameters are specified, they must match the
+		 * existing estimator.
+		 */
+		if ((!info->interval && !info->ewma_log) ||
+		    (info->interval != est->params.interval ||
+		     info->ewma_log != est->params.ewma_log)) {
+			xt_rateest_put(par->net, est);
+			return -EINVAL;
+		}
+		info->est = est;
+		return 0;
 	}
 
-	ret  = -ENOENT;
-	est1 = xt_rateest_lookup(par->net, info->name1);
-	if (!est1)
+	ret = -ENOMEM;
+	est = kzalloc(sizeof(*est), GFP_KERNEL);
+	if (!est)
 		goto err1;
 
-	est2 = NULL;
-	if (info->flags & XT_RATEEST_MATCH_REL) {
-		est2 = xt_rateest_lookup(par->net, info->name2);
-		if (!est2)
-			goto err2;
-	}
+	strlcpy(est->name, info->name, sizeof(est->name));
+	spin_lock_init(&est->lock);
+	est->refcnt		= 1;
+	est->params.interval	= info->interval;
+	est->params.ewma_log	= info->ewma_log;
 
-	info->est1 = est1;
-	info->est2 = est2;
+	cfg.opt.nla_len		= nla_attr_size(sizeof(cfg.est));
+	cfg.opt.nla_type	= TCA_STATS_RATE_EST;
+	cfg.est.interval	= info->interval;
+	cfg.est.ewma_log	= info->ewma_log;
+
+	ret = gen_new_estimator(&est->bstats, NULL, &est->rate_est,
+				&est->lock, NULL, &cfg.opt);
+	if (ret < 0)
+		goto err2;
+
+	info->est = est;
+	xt_rateest_hash_insert(xn, est);
+	mutex_unlock(&xn->hash_lock);
 	return 0;
 
 err2:
-	xt_rateest_put(par->net, est1);
+	kfree(est);
 err1:
+	mutex_unlock(&xn->hash_lock);
 	return ret;
 }
 
-static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par)
+static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
 {
-	struct xt_rateest_match_info *info = par->matchinfo;
+	struct xt_rateest_target_info *info = par->targinfo;
 
-	xt_rateest_put(par->net, info->est1);
-	if (info->est2)
-		xt_rateest_put(par->net, info->est2);
+	xt_rateest_put(par->net, info->est);
 }
 
-static struct xt_match xt_rateest_mt_reg __read_mostly = {
-	.name       = "rateest",
+static struct xt_target xt_rateest_tg_reg __read_mostly = {
+	.name       = "RATEEST",
 	.revision   = 0,
 	.family     = NFPROTO_UNSPEC,
-	.match      = xt_rateest_mt,
-	.checkentry = xt_rateest_mt_checkentry,
-	.destroy    = xt_rateest_mt_destroy,
-	.matchsize  = sizeof(struct xt_rateest_match_info),
-	.usersize   = offsetof(struct xt_rateest_match_info, est1),
+	.target     = xt_rateest_tg,
+	.checkentry = xt_rateest_tg_checkentry,
+	.destroy    = xt_rateest_tg_destroy,
+	.targetsize = sizeof(struct xt_rateest_target_info),
+	.usersize   = offsetof(struct xt_rateest_target_info, est),
 	.me         = THIS_MODULE,
 };
 
-static int __init xt_rateest_mt_init(void)
+static __net_init int xt_rateest_net_init(struct net *net)
 {
-	return xt_register_match(&xt_rateest_mt_reg);
+	struct xt_rateest_net *xn = net_generic(net, xt_rateest_id);
+	int i;
+
+	mutex_init(&xn->hash_lock);
+	for (i = 0; i < ARRAY_SIZE(xn->hash); i++)
+		INIT_HLIST_HEAD(&xn->hash[i]);
+	return 0;
 }
 
-static void __exit xt_rateest_mt_fini(void)
+static struct pernet_operations xt_rateest_net_ops = {
+	.init = xt_rateest_net_init,
+	.id   = &xt_rateest_id,
+	.size = sizeof(struct xt_rateest_net),
+};
+
+static int __init xt_rateest_tg_init(void)
 {
-	xt_unregister_match(&xt_rateest_mt_reg);
+	int err = register_pernet_subsys(&xt_rateest_net_ops);
+
+	if (err)
+		return err;
+	return xt_register_target(&xt_rateest_tg_reg);
 }
 
+static void __exit xt_rateest_tg_fini(void)
+{
+	xt_unregister_target(&xt_rateest_tg_reg);
+	unregister_pernet_subsys(&xt_rateest_net_ops);
+}
+
+
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("xtables rate estimator match");
-MODULE_ALIAS("ipt_rateest");
-MODULE_ALIAS("ip6t_rateest");
-module_init(xt_rateest_mt_init);
-module_exit(xt_rateest_mt_fini);
+MODULE_DESCRIPTION("Xtables: packet rate estimator");
+MODULE_ALIAS("ipt_RATEEST");
+MODULE_ALIAS("ip6t_RATEEST");
+module_init(xt_rateest_tg_init);
+module_exit(xt_rateest_tg_fini);
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.c b/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.c
index a997bc2..708eadb 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.c
@@ -278,12 +278,12 @@
 		else
 			ppe_mib_dump_ppe1(hash_index, &pkt_cnt, &byte_cnt);
 
-		if (fport >= 0 && fport < MAX_IF_NUM) {
+		if (fport < MAX_IF_NUM) {
 			hnat_if[fport].tx_byte_cnt += byte_cnt;
 			hnat_if[fport].tx_pkt_cnt += pkt_cnt;
 		}
 
-		if (sport >= 0 && sport < MAX_IF_NUM) {
+		if (sport < MAX_IF_NUM) {
 			hnat_if[sport].rx_byte_cnt += byte_cnt;
 			hnat_if[sport].rx_pkt_cnt += pkt_cnt;
 
@@ -303,7 +303,7 @@
 		}
 
 
-		if (debug_level == 6) {
+		if (debug_level == 6 && sport < MAX_IF_NUM && fport < MAX_IF_NUM) {
 
 			if (IS_IPV4_HNAPT(entry))
 				pr_notice("%s(%d)(%d), sport(%d), fport(%d): rx_byte:%llu, rx_pkt:%llu, tx_byte=%llu, tx_pkt=%llu, mcast=%llu, entry_pkt_cnt=%llu, entry_byte_cnt=%llu\n",
@@ -432,49 +432,44 @@
 		entry = &ppe_foe_base[hash_index];
 		entry1 = &ppe1_foe_base[hash_index];
 
-		if (entry->bfib1.state == BIND) {
+		fport = get_act_dp(entry);
+		sport = get_rxif_idx(entry);
+		mcast = is_foe_mcast_entry(entry);
 
-			fport = get_act_dp(entry);
-			sport = get_rxif_idx(entry);
-			mcast = is_foe_mcast_entry(entry);
+		if (dev_idx == fport || dev_idx == sport) {
+			ppe_mib_dump_ppe0(hash_index, &pkt_cnt, &byte_cnt);
+			if (dev_idx == fport) {
+				total_tx_pkt += pkt_cnt;
+				total_tx_byte += byte_cnt;
+			}
 
-			if (dev_idx == fport || dev_idx == sport) {
-				ppe_mib_dump_ppe0(hash_index, &pkt_cnt, &byte_cnt);
-				if (dev_idx == fport) {
-					total_tx_pkt += pkt_cnt;
-					total_tx_byte += byte_cnt;
-				}
-
-				if (dev_idx == sport) {
-					total_rx_pkt += pkt_cnt;
-					total_rx_byte += byte_cnt;
-					if (mcast)
-						mcast_rx_pkt += pkt_cnt;
-				}
+			if (dev_idx == sport) {
+				total_rx_pkt += pkt_cnt;
+				total_rx_byte += byte_cnt;
+				if (mcast)
+					mcast_rx_pkt += pkt_cnt;
 			}
 		}
 
-		if (entry1->bfib1.state == BIND) {
+		fport1 = get_act_dp(entry1);
+		sport1 = get_rxif_idx(entry1);
+		mcast1 = is_foe_mcast_entry(entry1);
 
-			fport1 = get_act_dp(entry1);
-			sport1 = get_rxif_idx(entry1);
-			mcast1 = is_foe_mcast_entry(entry1);
+		if (dev_idx == fport1 || dev_idx == sport1) {
+			ppe_mib_dump_ppe1(hash_index, &pkt_cnt1, &byte_cnt1);
+			if (dev_idx == fport1) {
+				total_tx_pkt += pkt_cnt1;
+				total_tx_byte += byte_cnt1;
+			}
 
-			if (dev_idx == fport1 || dev_idx == sport1) {
-				ppe_mib_dump_ppe1(hash_index, &pkt_cnt1, &byte_cnt1);
-				if (dev_idx == fport1) {
-					total_tx_pkt += pkt_cnt1;
-					total_tx_byte += byte_cnt1;
-				}
-
-				if (dev_idx == sport1) {
-					total_rx_pkt += pkt_cnt1;
-					total_rx_byte += byte_cnt1;
-					if (mcast1)
-						mcast_rx_pkt += pkt_cnt1;
-				}
+			if (dev_idx == sport1) {
+				total_rx_pkt += pkt_cnt1;
+				total_rx_byte += byte_cnt1;
+				if (mcast1)
+					mcast_rx_pkt += pkt_cnt1;
 			}
 		}
+
 	}
 
 
@@ -1244,8 +1239,10 @@
 		     IP_FORMAT3(entry->ipv4_dslite.new_dip), IP_FORMAT2(entry->ipv4_dslite.new_dip),
 		     IP_FORMAT1(entry->ipv4_dslite.new_dip), IP_FORMAT0(entry->ipv4_dslite.new_dip),
 		     entry->ipv4_dslite.new_dport);
- 	}else if (IS_IPV4_MAPT(entry)){
+ 	}
 #if(0)
+	else if (IS_IPV4_MAPT(entry)){
+
 		NAT_PRINT("Information Block 2: %08X\n", entry->ipv4_dslite.info_blk2);
 		NAT_PRINT("Create IPv4 MAP-T entry (4 to 6)\n");
 		NAT_PRINT
@@ -1271,7 +1268,7 @@
 		     entry->ipv4_dslite.dport);
 		NAT_PRINT
 		    ("L4 New Port: %d->%d\n", entry->ipv4_dslite.new_sport, entry->ipv4_dslite.new_dport);
-#else
+		// ------------------
 		NAT_PRINT("Information Block 2: %08X\n", entry->ipv6_6rd.info_blk2);
 		NAT_PRINT("Create MAP-T (6 to 4)\n");
 		if (IS_IPV6_FLAB_EBL()) {
@@ -1294,8 +1291,10 @@
 			     entry->ipv6_6rd.ipv6_dip3, entry->ipv6_6rd.dport);
 			NAT_PRINT ("L4 New Port: %d->%d\n", entry->ipv6_6rd.new_sport, entry->ipv6_6rd.new_dport);
 		}
-#endif	     		
-	} else if (IS_IPV6_3T_ROUTE(entry)) {
+
+	}
+#endif
+	else if (IS_IPV6_3T_ROUTE(entry)) {
 		NAT_PRINT("Information Block 2: %08X\n", entry->ipv6_3t_route.info_blk2);
 		NAT_PRINT("Create IPv6 3-Tuple entry\n");
 		NAT_PRINT
@@ -1412,7 +1411,7 @@
 		NAT_PRINT(" Remove tunnel = %u\n", entry->bfib1.rmt);
 		NAT_PRINT("=========================================\n\n");
 	}
-	
+
 }
 
 int foe_get_ppe_entries(struct hwnat_args *opt1, int count, struct foe_entry *foe_base)
@@ -1429,14 +1428,14 @@
 			/* Extra info */
 			opt1->entries[count].fport = opt1->entries[count].fqos = opt1->entries[count].qid = 0;
 			if (IS_IPV4_GRP(entry)) {
-				opt1->entries[count].fport = entry->ipv4_hnapt.iblk2.acnt;
-				opt1->entries[count].fqos =  ppe_force_port(entry);
+				opt1->entries[count].fport = ppe_force_port(entry);
+				opt1->entries[count].fqos = entry->ipv4_hnapt.iblk2.fqos;
 				opt1->entries[count].qid = ppe_qid(entry);
 			}
 			if (fe_feature & HNAT_IPV6) {
 				if (IS_IPV6_GRP(entry)) {
-					opt1->entries[count].fport = entry->ipv6_5t_route.iblk2.acnt;
-					opt1->entries[count].fqos = ppe_force_port(entry);
+					opt1->entries[count].fport = ppe_force_port(entry);
+					opt1->entries[count].fqos = entry->ipv6_3t_route.iblk2.fqos;
 					opt1->entries[count].qid =  ppe_qid(entry);
 				}
 			}
@@ -1538,7 +1537,7 @@
 
 int foe_get_all_entries(struct hwnat_args *opt1)
 {
-	int ppe_count, ppe1_count;		/* valid entry count */
+	int ppe_count, ppe1_count = 0;		/* valid entry count */
 
 	ppe_count = foe_get_ppe_entries(opt1, 0, ppe_foe_base);
 	if (ppe_count < 16 * 1024) {
@@ -1661,7 +1660,7 @@
 
 void hw_nat_l2_info(struct foe_entry *entry, struct hwnat_tuple *opt)
 {
-	if ((opt->pkt_type) == IPV4_NAPT) {
+	if (opt->pkt_type == IPV4_NAPT || opt->pkt_type == IPV4_NAT) {
 		foe_set_mac_hi_info(entry->ipv4_hnapt.dmac_hi, opt->dmac);
 		foe_set_mac_lo_info(entry->ipv4_hnapt.dmac_lo, opt->dmac);
 		foe_set_mac_hi_info(entry->ipv4_hnapt.smac_hi, opt->smac);
@@ -1719,7 +1718,7 @@
 	test.flow_lbl[1] = 0x12;
 	test.flow_lbl[2] = 0xab;
 
-	if ((opt->pkt_type) == IPV4_NAPT) {
+	if (opt->pkt_type == IPV4_NAPT || opt->pkt_type == IPV4_NAT) {
 		entry->ipv4_hnapt.sip = opt->ing_sipv4;
 		entry->ipv4_hnapt.dip = opt->ing_dipv4;
 		entry->ipv4_hnapt.new_sip = opt->eg_sipv4;
@@ -1812,8 +1811,8 @@
 
 	entry->ipv4_hnapt.bfib1.cah = 1;
 
-	if ((opt->pkt_type) == IPV4_NAPT) {
-		entry->ipv4_hnapt.bfib1.pkt_type = IPV4_NAPT;
+	if (opt->pkt_type == IPV4_NAPT || opt->pkt_type == IPV4_NAT) {
+		entry->ipv4_hnapt.bfib1.pkt_type = opt->pkt_type;
 		entry->ipv4_hnapt.bfib1.sta = 1;
 		entry->ipv4_hnapt.bfib1.udp = opt->is_udp; /* tcp/udp */
 		entry->ipv4_hnapt.bfib1.state = BIND;
@@ -1866,25 +1865,25 @@
 
 void hw_nat_ib2_info(struct foe_entry *entry, struct hwnat_tuple *opt)
 {
-	if ((opt->pkt_type) == IPV4_NAPT) {
+	if (opt->pkt_type == IPV4_NAPT || opt->pkt_type == IPV4_NAT) {
 		entry->ipv4_hnapt.iblk2.dp = (opt->dst_port) & 0x7; /* 0:cpu, 1:GE1 */
 		entry->ipv4_hnapt.iblk2.dscp = opt->dscp;
 
-#if defined(CONFIG_HNAT_V1)
-	if ((opt->dst_port) >= 8) {
-	    entry->ipv4_hnapt.iblk2.dp1 = 1;
-	} else {
-	    entry->ipv4_hnapt.iblk2.dp1 = 0;
-	}
-	entry->ipv4_hnapt.iblk2.qid1 = 0;
+	#if defined(CONFIG_HNAT_V1)
+		if ((opt->dst_port) >= 8) {
+		    entry->ipv4_hnapt.iblk2.dp1 = 1;
+		} else {
+		    entry->ipv4_hnapt.iblk2.dp1 = 0;
+		}
+		entry->ipv4_hnapt.iblk2.qid1 = 0;
 
-#endif /* CONFIG_HNAT_V1 */
-	entry->ipv4_hnapt.iblk2.qid = 0;	
-	entry->ipv4_hnapt.iblk2.fqos = 0;
+	#endif /* CONFIG_HNAT_V1 */
+		entry->ipv4_hnapt.iblk2.qid = 0;
+		entry->ipv4_hnapt.iblk2.fqos = 0;
 
-	entry->ipv4_hnapt.iblk2.acnt = opt->dst_port;
-	entry->ipv4_hnapt.iblk2.mcast = 0;
-	entry->ipv4_hnapt.iblk2.mibf = 1;
+		entry->ipv4_hnapt.iblk2.acnt = opt->dst_port;
+		entry->ipv4_hnapt.iblk2.mcast = 0;
+		entry->ipv4_hnapt.iblk2.mibf = 1;
 
 	} else if ((opt->pkt_type) == IPV6_ROUTING) {
 		if (fe_feature & HNAT_IPV6) {
@@ -2418,7 +2417,7 @@
 
 void set_qid(struct sk_buff *skb)
 {
-	struct foe_pri_key key;
+	struct foe_pri_key key = {0};
 	s32 hash_index;
 	struct foe_entry *entry = NULL;
 
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.h b/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.h
index 1b5aef7..cf5a01f 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/foe_fdb.h
@@ -125,6 +125,7 @@
 	struct udphdr uh;
 
 	u32 pkt_type;
+	u16 gre_call_id;
 	u8 is_mcast;
 
 };
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
index 2ecd8fa..e246473 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
@@ -65,6 +65,8 @@
 #include <linux/inetdevice.h>
 #include <net/rtnetlink.h>
 #include <net/netevent.h>
+#include <net/gre.h>
+#include <net/pptp.h>
 #include <linux/platform_device.h>
 #include "ra_nat.h"
 #include "foe_fdb.h"
@@ -91,13 +93,15 @@
 u32 ppe_hw_fast;
 u8 set_fqos = 0;
 u8 xlat_enable = 1;
+u8 pptp_enable = 0;
 u32 rndis_bind_count = 0;
 u32 rndis_mod = 2;
+u8 second_path = 0;
 
 static const char *const mtk_hnat_feature_name[] = {
 	"GE2_SUPPORT", "HNAT_IPV6", "HNAT_VLAN_TX", "HNAT_MCAST", "HNAT_QDMA", "WARP_WHNAT", "WIFI_HNAT", "HNAT_WAN_P4", "WAN_TO_WLAN_QOS", "HNAT_SP_TAG",
 	"QDMA_TX_RX", "PPE_MIB", "PACKET_SAMPLING", "HNAT_OPENWRT", "HNAT_WLAN_QOS", "WLAN_OPTIMIZE", "UDP_FRAG", "AUTO_MODE", "SEMI_AUTO_MODE", "MANUAL_MODE",
-	"PRE_BIND", "HNAT_IPI", "DBG_IPV6_SIP", "DBG_IPV4_SIP", "DBG_SP", "ETH_QOS"
+	"PRE_BIND", "HNAT_IPI", "DBG_IPV6_SIP", "DBG_IPV4_SIP", "DBG_SP", "ETH_QOS", "SW_DVFS"
 };
 
 u8 USE_3T_UDP_FRAG;
@@ -304,7 +308,8 @@
 		hwnat_info_region = USE_HEAD_ROOM;
 
 		return USE_HEAD_ROOM;	/* use headroom */
-	} else if (IS_MAGIC_TAG_PROTECT_VALID_TAIL(skb) && IS_SPACE_AVAILABLE_TAIL(skb)) {
+	} else if (IS_MAGIC_TAG_PROTECT_VALID_TAIL(skb) && IS_SPACE_AVAILABLE_TAIL(skb) &&
+		   IS_SPACE_AVAILABLE_HEAD(skb)) {
 		FOE_INFO_START_ADDR(skb);
 		alg_tmp = FOE_ALG_TAIL(skb);;
 		sp_tmp = FOE_SP_TAIL(skb);
@@ -380,6 +385,7 @@
 	skb->protocol = eth->h_proto;
 	return vir_if_idx;
 }
+
 #ifdef CONFIG_MTK_TINYSYS_MEDMCU_SUPPORT
 extern void __iomem *medmcu_hnat_info_host_base_virt;
 void hnat_info_init(struct device *dev)
@@ -400,6 +406,7 @@
 
 }
 #endif
+
 static int foe_alloc_tbl(u32 num_of_entry, struct device *dev)
 {
 	u32 foe_tbl_size;
@@ -897,32 +904,31 @@
 	int i = 0;
 	int dev_match = 0;
 	struct ethhdr *eth = (struct ethhdr *)skb_mac_header(skb);
+	struct net_device *dst_dev;
 
-	if (debug_level >= 10)
-		pr_notice("%s, name = %s\n", __func__, skb->dev->name);
-
-		/* PPE can only handle IPv4/IPv6/PPP packets */
+	/* PPE can only handle IPv4/IPv6/PPP packets */
 	if (((skb->protocol != htons(ETH_P_8021Q)) &&
 	    (skb->protocol != htons(ETH_P_IP)) && (skb->protocol != htons(ETH_P_IPV6)) &&
 	    (skb->protocol != htons(ETH_P_PPP_SES)) && (skb->protocol != htons(ETH_P_PPP_DISC))) ||
-			is_multicast_ether_addr(&eth->h_dest[0])) {
+		is_multicast_ether_addr(&eth->h_dest[0])) {
 
-			if (debug_level >= 10)
-				pr_notice("%s not support, skb->protocol = 0x%x, multicase:%d\n", __func__, skb->protocol, is_multicast_ether_addr(&eth->h_dest[0]));
-			return 1;
+		if (debug_level >= 10)
+			pr_notice("%s not support, skb->protocol = 0x%x, multicast:%d\n", __func__, skb->protocol, is_multicast_ether_addr(&eth->h_dest[0]));
+		return 1;
 	}
 
 	if (debug_level >= 10)
-		pr_notice("%s enter, name = %s, protocol = 0x%x, skb-headroom=%d\n", __func__,
+		pr_notice("%s, name = %s, protocol = 0x%x, skb-headroom=%d\n", __func__,
 			skb->dev->name, skb->protocol, skb_headroom(skb));
 
 	skb_set_network_header(skb, 0);
 
 #ifdef CONFIG_SUPPORT_WLAN_OPTIMIZE
-		if (bridge_short_cut_rx(skb))
-			return 1;	/* Bridge ==> sw path (rps) */
+	if (bridge_short_cut_rx(skb))
+		return 1;	/* Bridge ==> sw path (rps) */
 #endif
 
+	/* Check the source interface is registered */
 	for (i = 0; i < MAX_IF_NUM; i++) {
 		if (dst_port[i] == skb->dev) {
 			vir_if_idx = i;
@@ -933,53 +939,58 @@
 		}
 	}
 
-#ifdef CONFIG_RAETH_EDMA
-	for (i = 1; i < MAX_IF_NUM; i++) {
-		if(dst_port[i]->name == NULL) {
-			pr_err("[HS-ethernet/HWNAT/RX] %s : dst_port[%d] name is NULL\n", __func__, i);
-			return 1;
-		}
-
-		if ((strcmp(dst_port[i]->name, DEV_NAME) == 0 && strcmp(skb->dev->name, AQR_DEV_NAME) == 0) ||
-		    (strcmp(dst_port[i]->name, DEV2_NAME) == 0 && strcmp(skb->dev->name, AQR_DEV2_NAME) == 0)) {
-			vir_if_idx = i;
-			dev_match = 1;
-			if (debug_level >= 7)
-				pr_notice("[HS-ethernet/HWNAT/RX] %s : dev_match ok Interfacess=%s, vir_if_idx=%x\n", __func__, skb->dev->name, vir_if_idx);
-			break;
-		}
-	}
-#endif
-
 	if (dev_match == 0) {
 		if (debug_level >= 1)
 			pr_notice("%s UnKnown Interface, vir_if_idx=%x\n", __func__, vir_if_idx);
 		return 1;
 	}
 
+	/* Check the destination interface is running */
+	if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA0)
+		dst_dev = dst_port[DP_EDMA0];
+	else if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA1)
+		dst_dev = dst_port[DP_EDMA1];
+	else
+		dst_dev = (second_path && !netif_running(dst_port[DP_GMAC1]))?
+			  dst_port[DP_GMAC2] : dst_port[DP_GMAC1];
+
+	if (!dst_dev || !netif_running(dst_dev)) {
+		if (debug_level >= 1)
+			pr_notice("%s Interface %s is Down\n", __func__, dst_dev->name);
+		return 1;
+	}
+
+	/* currently, skb->data points to layer 3 */
+	if (skb_headroom(skb) < FOE_INFO_LEN + ETH_HLEN + VLAN_HLEN) {
+		if (debug_level >= 3)
+			pr_notice("%s headroom isn't enough\n", __func__);
+		return 1;
+	}
+
 	/* push vlan tag to stand for actual incoming interface, */
 	/* so HNAT module can know the actual incoming interface from vlan id. */
 	skb_push(skb, ETH_HLEN);/* pointer to layer2 header before calling hard_start_xmit */
-
-#ifdef CONFIG_RAETH_EDMA
-		if (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_EDMA0)
-			skb->dev = dst_port[DP_EDMA0];
-		else if (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_EDMA1)
-			skb->dev = dst_port[DP_EDMA1];
-		else
-			skb->dev = dst_port[DP_GMAC1];	/* we use GMAC1 to send the packet to PPE */
-#else
-		if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA0)
-			skb->dev = dst_port[DP_EDMA0];
-		else if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA1)
-			skb->dev = dst_port[DP_EDMA1];
-		else
-			skb->dev = dst_port[DP_GMAC1];	/* we use GMAC1 to send the packet to PPE */
-#endif
+	skb->dev = dst_dev;
 
 #ifdef CONFIG_SUPPORT_WLAN_QOS
-		set_qid(skb);
+	set_qid(skb);
+	if ((!skb->dev) || ((skb->dev != dst_port[DP_GMAC2]) &&
+	    (skb->dev != dst_port[DP_GMAC1])))
+		skb->dev = dst_port[DP_GMAC1];	/* we use GMAC1 to send the packet to PPE */
 #endif
+
+	/* push the poped vlan back */
+	if (skb_vlan_tag_present(skb)) {
+		skb = vlan_insert_tag(skb, skb->vlan_proto, skb_vlan_tag_get(skb));
+		if (skb == NULL) {
+			if (debug_level >= 3)
+				pr_notice("%s, vlan_insert_tag() frees the skb\n", __func__);
+			return 0;
+		}
+		skb->vlan_tci = 0;
+	}
+
+	/* push the source interface */
 	skb->vlan_proto = htons(ETH_P_8021Q);
 #ifdef	CONFIG_RAETH_HW_VLAN_TX
 	skb->vlan_tci |= VLAN_TAG_PRESENT;
@@ -992,52 +1003,42 @@
 		return 0;
 	}
 #endif
-	if (IS_SPACE_AVAILABLE_HEAD(skb) && IS_SPACE_AVAILABLE_TAIL(skb)) {
-		/* redirect to PPE */
-#ifdef CONFIG_RAETH_EDMA
-		FOE_AI_TAIL(skb) = UN_HIT;
-		FOE_TAG_PROTECT_TAIL(skb) = TAG_PROTECT;
 
-		if (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_EDMA0) {
-			FOE_MAGIC_TAG_TAIL(skb) = FOE_MAGIC_PPE0;
-		} else if (FOE_MAGIC_TAG_TAIL(skb) == FOE_MAGIC_EDMA1) {
-			FOE_MAGIC_TAG_TAIL(skb) = FOE_MAGIC_PPE1;
-		} else {
-			FOE_MAGIC_TAG_TAIL(skb) = FOE_MAGIC_PPE;
-		}
-#else
+	/* redirect to PPE */
+	if (IS_SPACE_AVAILABLE_HEAD(skb)) {
+
 		FOE_AI(skb) = UN_HIT;
-		FOE_AI_TAIL(skb) = UN_HIT;
 		FOE_TAG_PROTECT(skb) = TAG_PROTECT;
+
+		if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA0)
+			FOE_MAGIC_TAG(skb) = FOE_MAGIC_PPE0;
+		else if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA1)
+			FOE_MAGIC_TAG(skb) = FOE_MAGIC_PPE1;
+		else
+			FOE_MAGIC_TAG(skb) = FOE_MAGIC_PPE;
+
+	} else if (IS_SPACE_AVAILABLE_TAIL(skb)) {
+
+		FOE_AI_TAIL(skb) = UN_HIT;
 		FOE_TAG_PROTECT_TAIL(skb) = TAG_PROTECT;
 
-		if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA0) {
-			FOE_MAGIC_TAG(skb) = FOE_MAGIC_PPE0;
+		if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA0)
 			FOE_MAGIC_TAG_TAIL(skb) = FOE_MAGIC_PPE0;
-		} else if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA1) {
-			FOE_MAGIC_TAG(skb) = FOE_MAGIC_PPE1;
+		else if (FOE_MAGIC_TAG(skb) == FOE_MAGIC_EDMA1)
 			FOE_MAGIC_TAG_TAIL(skb) = FOE_MAGIC_PPE1;
-		} else {
-			FOE_MAGIC_TAG(skb) = FOE_MAGIC_PPE;
+		else
 			FOE_MAGIC_TAG_TAIL(skb) = FOE_MAGIC_PPE;
-		}
-#endif
+
 	} else {
 		if (debug_level >= 3)
-			pr_notice("%s, can't fill FOE!\n",
-				__func__);
+			pr_notice("%s, check why! skb with vlan return to caller, headroom:%d, tailroom:%d\n",
+				__func__, skb_headroom(skb), skb_tailroom(skb));
 		return 1;
 	}
 
-#ifdef CONFIG_SUPPORT_WLAN_QOS
-		/*if (debug_level >= 2)*/
-			/*pr_notice("skb->dev = %s\n", skb->dev);*/
-		if ((!skb->dev) || ((skb->dev != dst_port[DP_GMAC2]) &&
-		    (skb->dev != dst_port[DP_GMAC1])))
-			skb->dev = dst_port[DP_GMAC1];	/* we use GMAC1 to send the packet to PPE */
-#endif
 	if (debug_level >= 10)
 		pr_notice("%s, send to ppe via ETH tx\n", __func__);
+
 	dev_queue_xmit(skb);
 
 	return 0;
@@ -1068,43 +1069,12 @@
   		pr_notice("%s, vir_if_idx is 65535\n", __func__);
   		return 1;
   	}
-#ifdef CONFIG_RAETH_EDMA
-	if (dst_port[vir_if_idx] != NULL) {
-		if (strcmp(dst_port[vir_if_idx]-> name, DEV_NAME) == 0) {
-			if (aqr_dev1 != NULL) {
-				aqr_dev = aqr_dev1;
-			} else {
-				aqr_dev1 = ra_dev_get_by_name(AQR_DEV_NAME);
-				aqr_dev = aqr_dev1;
-			}
-		} else if (strcmp(dst_port[vir_if_idx]-> name, DEV2_NAME) == 0) {
-			if (aqr_dev2 != NULL) {
-				aqr_dev = aqr_dev2;
-			} else {
-				aqr_dev2 = ra_dev_get_by_name(AQR_DEV2_NAME);
-				aqr_dev = aqr_dev2;
-			}
-		}
-	}
-#endif
+
 	/* recover to right incoming interface */
 	if (vir_if_idx < MAX_IF_NUM && dst_port[vir_if_idx]) {
-#ifdef CONFIG_RAETH_EDMA
-		if (aqr_dev != NULL) {
-			skb->dev = aqr_dev;
-			if (debug_level >= 7) {
-				pr_notice("[HS-ethernet/HWNAT/RX-pingpong] set the interface id back= %s (AQR)\n", aqr_dev->name);
-                        }
-		} else {
-			skb->dev = dst_port[vir_if_idx];
-			if (debug_level >= 7) {
-				pr_notice("[HS-ethernet/HWNAT/RX-pingpong] set the interface id back= %s \n", skb->dev->name);
-			}
-		}
-#else
+
 		if (dst_port[vir_if_idx] != NULL)
 			skb->dev = dst_port[vir_if_idx];
-#endif
 
 	} else {
 		if (debug_level >= 1)
@@ -1122,39 +1092,6 @@
 	} else {
 		skb->pkt_type = PACKET_OTHERHOST;
 
-#ifdef CONFIG_RAETH_EDMA
-		for (idx = 1; idx < MAX_IF_NUM; idx++) {
-			dev = dst_port[idx];
-			if (strcmp(dev-> name, DEV_NAME) == 0) {
-				if (aqr_dev1 != NULL) {
-					aqr_dev = aqr_dev1;
-				} else {
-					aqr_dev1 = ra_dev_get_by_name(AQR_DEV_NAME);
-					aqr_dev = aqr_dev1;
-				}
-
-				if (aqr_dev && ether_addr_equal(eth->h_dest, aqr_dev->dev_addr) == 0) {
-					//pr_notice("aqr0_dev_addr=%x:%x:%x:%x:%x:%x\n",aqr_dev->dev_addr[0],aqr_dev->dev_addr[1],aqr_dev->dev_addr[2],aqr_dev->dev_addr[3],aqr_dev->dev_addr[4],aqr_dev->dev_addr[5]);
-					skb->pkt_type = PACKET_HOST;
-					break;
-				}
-
-			} else if (strcmp(dev-> name, DEV2_NAME) == 0) {
-				if (aqr_dev2 != NULL) {
-					aqr_dev = aqr_dev2;
-				} else {
-					aqr_dev2 = ra_dev_get_by_name(AQR_DEV2_NAME);
-					aqr_dev = aqr_dev2;
-				}
-
-				if (aqr_dev && ether_addr_equal(eth->h_dest, aqr_dev->dev_addr) == 0) {
-					//pr_notice("aqr1_dev_addr=%x:%x:%x:%x:%x:%x\n",aqr_dev->dev_addr[0],aqr_dev->dev_addr[1],aqr_dev->dev_addr[2],aqr_dev->dev_addr[3],aqr_dev->dev_addr[4],aqr_dev->dev_addr[5]);
-					skb->pkt_type = PACKET_HOST;
-					break;
-				}
-			}
-		}
-#else
 		for (idx = 0; idx < MAX_IF_NUM; idx++) {
 			dev = dst_port[idx];
 			if (dev && ether_addr_equal(eth->h_dest, dev->dev_addr) == 0) {
@@ -1162,10 +1099,8 @@
 				break;
 			}
 		}
-#endif
 	}
 
-
 	if (debug_level >= 7)
 		pr_notice("%s, name = %s, vir_if_idx =%d, pkt_type:%d\n",
 			__func__, skb->dev->name, vir_if_idx, skb->pkt_type);
@@ -1308,7 +1243,6 @@
         if (debug_level >= 10)
 		pr_notice("%s, FOE_AI(skb):0x%x, FOE_SP(skb):%d\n", __func__, FOE_AI(skb), FOE_SP(skb));
 
-
 	if (skb == NULL) {
 		if (debug_level >= 7)
 			pr_notice("%s, skb == NULL\n", __func__);
@@ -1368,20 +1302,18 @@
 	/* interface is unknown */
 	if (!skb->dev) {
 		if (debug_level >= 1)
-			pr_notice("%s, interface is unknown\n", __func__);
+			pr_notice("%s, interface is unknown, act_dp = %d\n", __func__, act_dp);
 		kfree_skb(skb);
 		return 0;
 	}
 	skb_set_network_header(skb, 0);
 	skb_push(skb, ETH_HLEN);	/* pointer to layer2 header */
 
-
 	if (debug_level >= 7)
 		pr_notice("%s, bind to cpu done if name = %s\n",  __func__, skb->dev->name);
 
-
-
 	dev_queue_xmit(skb);
+
 	return 0;
 }
 
@@ -1502,6 +1434,11 @@
 #endif
 }
 
+bool is_same_subnet(uint32_t src_ip, uint32_t dst_ip) {
+
+	return ((src_ip & 0xFFFFFF) == (dst_ip & 0xFFFFFF));
+}
+
 int32_t ppe_parse_layer_med(struct sk_buff *skb, struct foe_entry *entry, struct pkt_parse_result *ppe_parse_result)
 {
 
@@ -1509,11 +1446,9 @@
 	struct ipv6hdr *ip6h = NULL;
 	struct tcphdr *th = NULL;
 	struct udphdr *uh = NULL;
+	struct pptp_gre_header *gh = NULL;
 	u8 ipv6_head_len = 0;
 
-	// dvt use
-	USE_3T_UDP_FRAG = 1;
-
 	memset(ppe_parse_result, 0, sizeof(*ppe_parse_result));
 	//hwnat_memcpy(ppe_parse_result->dmac, eth->h_dest, ETH_ALEN);
 	//hwnat_memcpy(ppe_parse_result->smac, eth->h_source, ETH_ALEN);
@@ -1563,11 +1498,14 @@
 			else
 				ppe_parse_result->pkt_type = IPV4_HNAPT;
 
-			if (iph->frag_off & htons(IP_MF | IP_OFFSET)) {
-		if (debug_level >= 6)
-			DD;
-				return 1;
-			}
+			/* L4 header checksum is wrong if bind */
+			if (iph != NULL && (iph->frag_off & htons(IP_MF | IP_OFFSET)))
+				if (!is_same_subnet(iph->saddr, iph->daddr)){
+					if (debug_level >= 7)
+						pr_notice("%s, 3T link on different subnet is not allowed to HWNAT !!\n", __func__);
+					return 1;
+				}
+
 		} else if (iph->protocol == IPPROTO_UDP) {
 			if (debug_level >= 6)
 				pr_notice("MD TX UDP!!!!!\n");
@@ -1580,15 +1518,29 @@
 			else
 				ppe_parse_result->pkt_type = IPV4_HNAPT;
 
-			if (iph->frag_off & htons(IP_MF | IP_OFFSET))
-				if (USE_3T_UDP_FRAG == 0) {
+			/* L4 header checksum is wrong if bind */
+			if (iph != NULL && (iph->frag_off & htons(IP_MF | IP_OFFSET)))
+				if (!is_same_subnet(iph->saddr, iph->daddr)){
+					if (debug_level >= 7)
+						pr_notice("%s, 3T link on different subnet is not allowed to HWNAT !!\n", __func__);
 					return 1;
 				}
+
 		} else if (iph->protocol == IPPROTO_GRE) {
-			/* do nothing */
-		if (debug_level >= 6)
-			DD;
-			return 1;
+			if (pptp_enable == 0)
+				return 1;
+			ppe_parse_result->pkt_type = IPV4_NAT;
+
+
+			skb_set_transport_header(skb, (iph->ihl * 4));
+			gh = (struct pptp_gre_header *)skb_transport_header(skb);
+
+			ppe_parse_result->gre_call_id = gh->call_id;
+
+			if (debug_level >= 7)
+				pr_notice("%s, gre call id:%d\n", __func__,
+					ppe_parse_result->gre_call_id);
+
 		}
 	} else {
 		ip6h = (struct ipv6hdr *)skb_network_header(skb);
@@ -1640,7 +1592,7 @@
 		}
 	}
 
-	if (debug_level >= 6) {
+	if (debug_level >= 11) {
 		pr_notice("--------------\n");
 		pr_notice("DMAC:%02X:%02X:%02X:%02X:%02X:%02X\n",
 			ppe_parse_result->dmac[0], ppe_parse_result->dmac[1],
@@ -1720,14 +1672,13 @@
 	struct ipv6hdr *ip6h = NULL;
 	struct tcphdr *th = NULL;
 	struct udphdr *uh = NULL;
+	struct pptp_gre_header *gh = NULL;
 	u8 ipv6_head_len = 0;
 #ifdef	CONFIG_RAETH_HW_VLAN_TX
 	struct vlan_hdr pseudo_vhdr;
 #endif
 	ppe_parse_result->vlan_layer = 0;
 	ppe_parse_result->vlan_tag = 0;
-	// dvt use
-	USE_3T_UDP_FRAG = 1;
 
 	memset(ppe_parse_result, 0, sizeof(*ppe_parse_result));
 	eth = (struct ethhdr *)skb->data;
@@ -1853,11 +1804,14 @@
 			else
 				ppe_parse_result->pkt_type = IPV4_HNAPT;
 
-			if (iph->frag_off & htons(IP_MF | IP_OFFSET)) {
-		if (debug_level >= 6)
-			DD;
-				return 1;
-			}
+			/* L4 header checksum is wrong if bind */
+			if (iph != NULL && (iph->frag_off & htons(IP_MF | IP_OFFSET)))
+				if (!is_same_subnet(iph->saddr, iph->daddr)){
+					if (debug_level >= 7)
+						pr_notice("%s, 3T link on different subnet is not allowed to HWNAT !!\n", __func__);
+					return 1;
+				}
+
 		} else if (iph->protocol == IPPROTO_UDP) {
 			skb_set_transport_header(skb, ETH_HLEN + ppe_parse_result->vlan1_gap +
 						 ppe_parse_result->vlan2_gap +
@@ -1870,17 +1824,29 @@
 			else
 				ppe_parse_result->pkt_type = IPV4_HNAPT;
 
-			if (iph->frag_off & htons(IP_MF | IP_OFFSET))
-				if (USE_3T_UDP_FRAG == 0) {
-		if (debug_level >= 6)
-			DD;
-				return 1;
+			/* L4 header checksum is wrong if bind */
+			if (iph != NULL && (iph->frag_off & htons(IP_MF | IP_OFFSET)))
+				if (!is_same_subnet(iph->saddr, iph->daddr)){
+					if (debug_level >= 7)
+						pr_notice("%s, 3T link on different subnet is not allowed to HWNAT !!\n", __func__);
+					return 1;
 				}
+
 		} else if (iph->protocol == IPPROTO_GRE) {
-			/* do nothing */
-		if (debug_level >= 6)
-			DD;
-			return 1;
+			if (pptp_enable == 0)
+				return 1;
+			ppe_parse_result->pkt_type = IPV4_NAT;
+
+			skb_set_transport_header(skb, ETH_HLEN + ppe_parse_result->vlan1_gap +
+						 ppe_parse_result->vlan2_gap +
+						 ppe_parse_result->pppoe_gap + (iph->ihl * 4));
+			gh = (struct pptp_gre_header *)skb_transport_header(skb);
+
+			ppe_parse_result->gre_call_id = gh->call_id;
+
+			if (debug_level >= 7)
+				pr_notice("%s, gre call id:%04x\n", __func__,
+					ppe_parse_result->gre_call_id);
 		}
 		if (fe_feature & HNAT_IPV6) {
 			if (iph->protocol == IPPROTO_IPV6) {
@@ -1960,7 +1926,7 @@
 				ppe_parse_result->pkt_type = IPV6_5T_ROUTE;
 
 		} else if (ip6h->nexthdr == NEXTHDR_IPIP) {
-			
+
 			skb_set_transport_header(skb, ETH_HLEN + ppe_parse_result->vlan1_gap +
 						 ppe_parse_result->vlan2_gap +
 						 ppe_parse_result->pppoe_gap +
@@ -1971,18 +1937,32 @@
 			       sizeof(struct iphdr));
 
 			if(SwitchDslMape == 1) {
-				if (ppe_parse_result->iph.protocol == IPPROTO_TCP) {	
+				if (ppe_parse_result->iph.protocol == IPPROTO_TCP) {
 					th = (struct tcphdr *)skb_transport_header(skb);
 					memcpy(&ppe_parse_result->th, th, sizeof(struct tcphdr));
-					if(ppe_parse_result->iph.frag_off & htons(IP_MF | IP_OFFSET)) {
-						return 1;
-					}
+
+					iph = (struct iphdr *)&ppe_parse_result->iph;
+					/* L4 header checksum is wrong if bind */
+					if (iph != NULL && (iph->frag_off & htons(IP_MF | IP_OFFSET)))
+						if (!is_same_subnet(iph->saddr, iph->daddr)){
+							if (debug_level >= 7)
+								pr_notice("%s, 3T link on different subnet is not allowed to HWNAT !!\n", __func__);
+							return 1;
+						}
+
 				} else if (ppe_parse_result->iph.protocol == IPPROTO_UDP) {
 					uh = (struct udphdr *)skb_transport_header(skb);
 					memcpy(&ppe_parse_result->uh, uh, sizeof(struct udphdr));
-					if(ppe_parse_result->iph.frag_off & htons(IP_MF|IP_OFFSET)) {
-						return 1;
-					}
+
+					iph = (struct iphdr *)&ppe_parse_result->iph;
+					/* L4 header checksum is wrong if bind */
+					if (iph != NULL && (iph->frag_off & htons(IP_MF | IP_OFFSET)))
+						if (!is_same_subnet(iph->saddr, iph->daddr)){
+							if (debug_level >= 7)
+								pr_notice("%s, 3T link on different subnet is not allowed to HWNAT !!\n", __func__);
+							return 1;
+						}
+
 				}
 				ppe_parse_result->pkt_type = IPV4_MAP_E;
 			} else {
@@ -1999,7 +1979,7 @@
 		return 1;
 	}
 
-	if (debug_level >= 6) {
+	if (debug_level >= 11) {
 		pr_notice("--------------\n");
 		pr_notice("DMAC:%02X:%02X:%02X:%02X:%02X:%02X\n",
 			ppe_parse_result->dmac[0], ppe_parse_result->dmac[1],
@@ -2080,7 +2060,7 @@
 	/* Set VLAN Info - VLAN1/VLAN2 */
 	/* Set Layer2 Info - DMAC, SMAC */
 	if ((ppe_parse_result->pkt_type == IPV4_HNAT) || (ppe_parse_result->pkt_type == IPV4_HNAPT)) {
-		if (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_DSLITE || 
+		if (entry->ipv4_hnapt.bfib1.pkt_type == IPV4_DSLITE ||
 		    entry->ipv4_hnapt.bfib1.pkt_type == IPV4_MAP_E) {/* DS-Lite WAN->LAN */
 			if (fe_feature & HNAT_IPV6) {
 				foe_set_mac_hi_info(entry->ipv4_dslite.dmac_hi, ppe_parse_result->dmac);
@@ -2457,10 +2437,20 @@
 			entry->ipv4_hnapt.new_dport = ntohs(ppe_parse_result->uh.dest);
 			entry->ipv4_hnapt.bfib1.udp = UDP;
 		}
+	} else if (ppe_parse_result->pkt_type == IPV4_HNAT) {
+
+		if (ppe_parse_result->iph.protocol == IPPROTO_GRE) {
+
+			/* Keep the same GRE caller ID field */
+			entry->ipv4_hnapt.new_sport = ntohs(ppe_parse_result->gre_call_id);
+
+			if (debug_level >= 7)
+				pr_notice("%s, sport:%04x, gre call id:%04x\n",
+					__func__, entry->ipv4_hnapt.sport, entry->ipv4_hnapt.new_sport);
+		}
+
 	}
 
-	/*else if (ppe_parse_result.pkt_type == IPV4_HNAT)*/
-		/* do nothing */
 	/*else if (ppe_parse_result.pkt_type == IPV6_1T_ROUTE)*/
 		/* do nothing */
 	/*else if (ppe_parse_result.pkt_type == IPV6_3T_ROUTE)*/
@@ -2508,7 +2498,7 @@
 		iblk2->mcast = 0;
 	}
 #endif
-	
+
 #if defined(CONFIG_HNAT_V2)
 	iblk2->dp = fpidx & 0xf;
 #endif
@@ -2560,7 +2550,7 @@
 		entry->ipv6_3t_route.iblk2.qid = (qidx & 0x0f);
 #endif
 	}
-	
+
 }
 
 void set_warp_wifi_dp(struct sk_buff *skb, struct foe_entry *entry, struct pkt_parse_result *ppe_parse_result, int gmac_no)
@@ -2608,7 +2598,6 @@
 		if (FOE_SP(skb) == 5)
 			entry->ipv6_3t_route.iblk2.fqos = 0;	/* wifi to wifi not go to pse port6 */
 		else
-
 			entry->ipv6_3t_route.iblk2.fqos = set_fqos;
 	}
 }
@@ -2672,7 +2661,9 @@
 
 #endif /* CONFIG_EDMA_RX */
 
-	pr_info("%s, FOE_AI(skb):0x%x, FOE_SP(skb):%d, pse_port:%d\n", __func__, FOE_AI(skb), FOE_SP(skb), pse_port);
+	if (debug_level >= 1)
+		pr_info("%s, FOE_AI(skb):0x%x, FOE_SP(skb):%d, pse_port:%d\n",
+			__func__, FOE_AI(skb), FOE_SP(skb), pse_port);
 
 	if (fe_feature & HNAT_QDMA) {
 		set_ppe_qid(skb, entry);
@@ -2717,7 +2708,8 @@
 	}
         pse_port = ADMA_PSE_PORT;
 
-	pr_info("set_wifi_info, gmac_no:%d, pse_port:%d, sw_fast_path:%d\n", gmac_no, pse_port, sw_fast_path);
+	if (debug_level >= 1)
+		pr_info("set_wifi_info, gmac_no:%d, pse_port:%d, sw_fast_path:%d\n", gmac_no, pse_port, sw_fast_path);
 
 	if (fe_feature & WARP_WHNAT) {
 		if (!sw_fast_path) {
@@ -2851,7 +2843,6 @@
 		if ((entry->ipv4_hnapt.vlan1 & VLAN_VID_MASK) == 1) {
 			if ((bind_dir == UPSTREAM_ONLY) || (bind_dir == BIDIRECTION))
 				ppe_set_infoblk2(&entry->ipv6_5t_route.iblk2, 1, NO_USE, ETH1_ACG, ppe_parse_result);
-
 			else
 				return 1;
 		}
@@ -2883,7 +2874,6 @@
 				if ((bind_dir == UPSTREAM_ONLY) || (bind_dir == BIDIRECTION))
 					ppe_set_infoblk2(&entry->ipv4_hnapt.iblk2, 1, NO_USE, ETH1_ACG,
 							 ppe_parse_result);
-
 				else
 					return 1;
 			} else {/* one-arm */
@@ -2904,23 +2894,22 @@
 		}
 #else
 		if ((entry->ipv4_hnapt.vlan1 & VLAN_VID_MASK) == lan_vid) {
-				if ((bind_dir == DOWNSTREAM_ONLY) || (bind_dir == BIDIRECTION))
-					ppe_set_infoblk2(&entry->ipv4_hnapt.iblk2, 1, NO_USE, ETH0_ACG,
-							 ppe_parse_result);
-				else
-					return 1;
+			if ((bind_dir == DOWNSTREAM_ONLY) || (bind_dir == BIDIRECTION))
+				ppe_set_infoblk2(&entry->ipv4_hnapt.iblk2, 1, NO_USE, ETH0_ACG,
+						 ppe_parse_result);
+			else
+				return 1;
 		} else if ((entry->ipv4_hnapt.vlan1 & VLAN_VID_MASK) == wan_vid) {
 			if ((bind_dir == UPSTREAM_ONLY) || (bind_dir == BIDIRECTION))
 				ppe_set_infoblk2(&entry->ipv4_hnapt.iblk2, 1, NO_USE, ETH1_ACG,
-						ppe_parse_result);
-
+						 ppe_parse_result);
 			else
 				return 1;
 		} else/* one-arm */
 				ppe_set_infoblk2(&entry->ipv4_hnapt.iblk2, 1, NO_USE, ETH0_ACG,
-						ppe_parse_result);
+						 ppe_parse_result);
 	}
-	
+
 #endif
 	return 0;
 }
@@ -2928,11 +2917,10 @@
 int set_eth_dp_gmac2(struct foe_entry *entry, int gmac_no,
 		     struct pkt_parse_result *ppe_parse_result)
 {
-		/* RT3883/MT7621 with 2xGMAC - Assuming GMAC2=WAN  and GMAC1=LAN */
+	/* RT3883/MT7621 with 2xGMAC - Assuming GMAC2=WAN  and GMAC1=LAN */
 	if (gmac_no == 1) {
 		if ((bind_dir == DOWNSTREAM_ONLY) || (bind_dir == BIDIRECTION))
 			set_dst_port(entry, 1, 1, ppe_parse_result); /*pse port1,goup1*/
-
 		else
 			return 1;
 	} else if (gmac_no == 2) {
@@ -2947,34 +2935,22 @@
 void set_eth_fqos(struct sk_buff *skb, struct foe_entry *entry)
 {
 	if (IS_IPV4_GRP(entry)) {
-
-			if (FOE_SP(skb) == 5) {
+			if (fe_feature & ETH_QOS)
+				entry->ipv4_hnapt.iblk2.fqos = set_fqos;
+			else
 				entry->ipv4_hnapt.iblk2.fqos = 0;
-			} else {
-				if (fe_feature & ETH_QOS)
-					entry->ipv4_hnapt.iblk2.fqos = set_fqos;
-				else
-					entry->ipv4_hnapt.iblk2.fqos = 0;
-			}
 	}
 
 	if (fe_feature & HNAT_IPV6) {
 		if (IS_IPV6_GRP(entry)) {
-
-			if (FOE_SP(skb) == 5) {
+			if (fe_feature & ETH_QOS)
+				entry->ipv6_5t_route.iblk2.fqos = set_fqos;
+			else
 				entry->ipv6_5t_route.iblk2.fqos = 0;
-			} else{
-				if (fe_feature & ETH_QOS)
-					entry->ipv6_5t_route.iblk2.fqos = set_fqos;
-				else
-					entry->ipv6_5t_route.iblk2.fqos = 0;
-			}
-
 		}
 	}
 }
 
-
 uint32_t ppe_set_ext_if_num(struct sk_buff *skb, struct foe_entry *entry)
 {
 	u32 offset = 0;
@@ -3198,7 +3174,7 @@
 		}
 	}
 	if (i < MAX_IF_NUM)
-		pr_notice("%s : ineterface %s register (%d), accel. type(%d)\n", __func__, dev->name, i, dst_port_type[i]);
+		pr_notice("%s : interface %s register (%d), accel. type(%d)\n", __func__, dev->name, i, dst_port_type[i]);
 }
 
 void ppe_dev_unreg_handler(struct net_device *dev)
@@ -3207,6 +3183,7 @@
 
 	if (dev == NULL)
 		return;
+
 	if (strncmp(dev->name, "ccmni0", 6) == 0) {
 		if (dst_port[8] != NULL) {
 			dst_port[8] = NULL;
@@ -3273,6 +3250,7 @@
 	if (i < MAX_IF_NUM)
 		pr_notice("%s : ineterface %s set null (%d)\n", __func__, dev->name, i);
 }
+
 #ifdef CONFIG_HW_NAT_SEMI_AUTO_MODE
 int get_done_bit(struct sk_buff *skb, struct foe_entry *entry)
 {
@@ -3352,17 +3330,17 @@
 		ppe_flow_set |= (BIT_IPV4_NAPT_EN | BIT_IPV4_NAT_EN);
 		ppe_flow_set |= (BIT_IPV4_NAT_FRAG_EN | BIT_UDP_IP4F_NAT_EN);	/* ip fragment */
 		ppe_flow_set |= (BIT_IPV4_HASH_GREK);
-		
+
 		ppe_flow_set |= BIT_IPV6_6RD_EN | BIT_IPV6_3T_ROUTE_EN | BIT_IPV6_5T_ROUTE_EN;
 			/* ppe_flow_set |= (BIT_IPV6_HASH_FLAB); // flow label */
-		
+
 		ppe_flow_set |= (BIT_IPV6_HASH_GREK);
 		ppe_flow_set |= (BIT_IPV4_464XLAT_EN);
 #if defined(CONFIG_HNAT_V2)
 		ppe_flow_set |= (BIT_IPV4_MAPE_EN);
 #else
 		ppe_flow_set |= (BIT_IPV4_DSL_EN);
-#endif		
+#endif
 	} else {
 		ppe_flow_set &= ~(BIT_IPV4_NAPT_EN | BIT_IPV4_NAT_EN);
 		ppe_flow_set &= ~(BIT_IPV4_NAT_FRAG_EN);
@@ -3373,7 +3351,7 @@
 		ppe_flow_set &= ~(BIT_IPV4_MAPE_EN);
 #else
 		ppe_flow_set &= ~(BIT_IPV4_DSL_EN);
-#endif	
+#endif
 			/* ppe_flow_set &= ~(BIT_IPV6_HASH_FLAB); */
 
 		ppe_flow_set &= ~(BIT_IPV6_HASH_GREK);
@@ -3383,7 +3361,7 @@
 
 	if (ppe_flow_set & BIT_IPV4_MAPE_EN)
 		SwitchDslMape = 1;
-	else 
+	else
 		SwitchDslMape = 0;
 
 	reg_write(PPE_FLOW_SET, ppe_flow_set);
@@ -3809,6 +3787,12 @@
 	return dev_get_by_name(&init_net, name);
 }
 
+#define IS_FAST_PATH_UP \
+	(dst_port[DP_EDMA0] && netif_running(dst_port[DP_EDMA0])) || \
+	(dst_port[DP_EDMA1] && netif_running(dst_port[DP_EDMA1])) || \
+	(dst_port[DP_GMAC1] && netif_running(dst_port[DP_GMAC1])) || \
+	(second_path && dst_port[DP_GMAC2] && netif_running(dst_port[DP_GMAC2]))? 1 : 0
+
 void eth_register(void)
 {
 	struct net_device *dev;
@@ -3824,7 +3808,12 @@
 			break;
 		}
 	}
-	if (fe_feature & GE2_SUPPORT) {
+
+#ifndef CONFIG_MTK_SGMII_SNPS
+	second_path = (fe_feature & GE2_SUPPORT)? 1 : 0;
+#endif
+
+	if (second_path) {
 		dev = ra_dev_get_by_name(DEV_NAME_HNAT_WAN);
 		ppe_dev_reg_handler(dev);
 		for (i = 0; i < MAX_IF_NUM; i++) {
@@ -3836,12 +3825,11 @@
 			}
 		}
 	}
-
-
 }
-#if(0)
+
 void modem_if_register(void)
 {
+#if(0)
 	struct net_device *dev;
 
 	dev = ra_dev_get_by_name(DEV_NAME_HNAT_CCCI0);
@@ -3867,8 +3855,9 @@
 
 	dev = ra_dev_get_by_name(DEV_NAME_HNAT_CCCI7);
 	ppe_dev_reg_handler(dev);
-}
 #endif
+}
+
 void rndis_if_register(void)
 {
 	struct net_device *dev;
@@ -3919,15 +3908,16 @@
 			break;
 		}
 	}
-
 }
 
 void snps_if_register(void)
 {
 	struct net_device *dev;
 
-	dev = ra_dev_get_by_name(DEV_NAME_HNAT_SNPS);
-	ppe_dev_reg_handler(dev);
+	if (IS_FAST_PATH_UP) {
+		dev = ra_dev_get_by_name(DEV_NAME_HNAT_SNPS);
+		ppe_dev_reg_handler(dev);
+	}
 }
 
 void ppe_set_dst_port(uint32_t ebl)
@@ -3943,17 +3933,18 @@
 		eth_register();
 #endif
 		ext_if_register();
-		//modem_if_register();
+		modem_if_register();
 		wifi_if_register();
 		rndis_if_register();
 		snps_if_register();
 	} else {
-		 /* disable */
-		if(dst_port[DP_GMAC1] != NULL)
+		/* disable */
+		if (dst_port[DP_GMAC1] != NULL)
 			dev_put(dst_port[DP_GMAC1]);
 
-		if(dst_port[DP_GMAC2] != NULL)
-			dev_put(dst_port[DP_GMAC2]);
+		if (second_path)
+			if(dst_port[DP_GMAC2] != NULL)
+				dev_put(dst_port[DP_GMAC2]);
 
 		for (j = 0; j < MAX_IF_NUM; j++) {
 			if (dst_port[j])
@@ -4054,7 +4045,10 @@
 	 */
 	/* FIXME: enable it to support IP fragement */
 	reg_write(PPE_IP_PROT_CHK, 0xFFFFFFFF);	/* IPV4_NXTH_CHK and IPV6_NXTH_CHK */
-	/* reg_modify_bits(PPE_IP_PROT_0, IPPROTO_GRE, 0, 8); */
+
+	if (pptp_enable == 1)
+		reg_modify_bits(PPE_IP_PROT_0, IPPROTO_GRE, 0, 8);
+
 	/* reg_modify_bits(PPE_IP_PROT_0, IPPROTO_TCP, 8, 8); */
 	/* reg_modify_bits(PPE_IP_PROT_0, IPPROTO_UDP, 16, 8); */
 	/* reg_modify_bits(PPE_IP_PROT_0, IPPROTO_IPV6, 24, 8); */
@@ -4151,7 +4145,7 @@
 		//pr_notice(" which_region = %d\n", which_region);
 
 	if (which_region == ALL_INFO_ERROR) {
-		if (pr_debug_ratelimited())
+		if (debug_level >= 7)
 			pr_notice("ppe_tx_handler : ALL_INFO_ERROR\n");
 		return 1;
 	}
@@ -4324,9 +4318,9 @@
 	ppe_set_entry_bind(skb, entry); /* Enter binding state */
 
 #ifdef CONFIG_HW_NAT_SEMI_AUTO_MODE
-		set_ppe_table_done(entry);
-		/*make sure data write to dram*/
-		wmb();
+	set_ppe_table_done(entry);
+	/*make sure data write to dram*/
+	wmb();
 #endif
 }
 
@@ -4336,7 +4330,6 @@
 	int ret;
 
 	ret = ppe_common_part(skb, entry, gmac_no, ppe_parse_result);
-
 	if (ret)
 		return ret;
 
@@ -4352,6 +4345,7 @@
 
 	if (ret)
 		return ret;
+
 	/* For force to cpu handler, record if name */
 	if (ppe_set_ext_if_num(skb, entry)) {
 		memset(FOE_INFO_START_ADDR(skb), 0, FOE_INFO_LEN);
@@ -4368,7 +4362,6 @@
 	int ret;
 
 	ret = ppe_common_part(skb, entry, gmac_no, ppe_parse_result);
-
 	if (ret)
 		return ret;
 
@@ -4391,7 +4384,6 @@
 	int ret;
 
 	ret = ppe_common_part_med(skb, entry, gmac_no, ppe_parse_result);
-
 	if (ret)
 		return ret;
 
@@ -4413,7 +4405,6 @@
 	int ret;
 
 	ret = ppe_common_part(skb, entry, gmac_no, ppe_parse_result);
-
 	if (ret)
 		return ret;
 
@@ -4437,7 +4428,6 @@
 	int ret;
 
 	ret = ppe_common_part(skb, entry, gmac_no, ppe_parse_result);
-
 	if (ret)
 		return ret;
 
@@ -4504,7 +4494,7 @@
 			/*this is duplicate packet in keepalive new header mode*/
 			/*just drop it */
 		if (debug_level >= 3)
-			pr_notice("Wifi TxGot HITBIND_KEEPALIVE_DUP_OLD packe (%s,%d)\n", skb->dev->name,
+			pr_notice("USB TxGot HITBIND_KEEPALIVE_DUP_OLD packe (%s,%d)\n", skb->dev->name,
 				FOE_ENTRY_NUM(skb));
 		memset(FOE_INFO_START_ADDR(skb), 0, FOE_INFO_LEN);
 		return 0;
@@ -4588,6 +4578,7 @@
 	}
 	return 1;
 }
+
 int tx_cpu_handler_eth(struct sk_buff *skb, struct foe_entry *entry, int gmac_no)
 {
 	int ret;
@@ -4636,7 +4627,7 @@
 	struct pkt_parse_result ppe_parse_result;
 
 	if (debug_level >= 7) {
-	    pr_notice("[HS-ethernet/HWNAT/TX] tx_cpu_handler_ext enter! \n");
+	    pr_notice("%s enter!\n", __func__);
 	}
 
 	if (debug_level >= 7) {
@@ -4711,7 +4702,8 @@
 	entry = decide_which_ppe(skb);
 
 
-	if (FOE_AI(skb) == HIT_BIND_FORCE_TO_CPU) {
+	if (FOE_AI(skb) == HIT_BIND_FORCE_TO_CPU ||
+	    FOE_AI(skb) == PACKET_FORWARD_PATH_WITHOUT_PPE) {
 
 		return hitbind_force_to_cpu_handler(skb, entry);
 		/* handle the incoming packet which came back from PPE */
@@ -4759,7 +4751,7 @@
 	}
 
 	if((FOE_MAGIC_TAG(skb) == FOE_MAGIC_WED0) ||
-		(FOE_MAGIC_TAG(skb) == FOE_MAGIC_WED1))
+	   (FOE_MAGIC_TAG(skb) == FOE_MAGIC_WED1))
 		return 1;
 
 	/* the incoming packet is from PCI or WiFi interface */
@@ -4951,12 +4943,16 @@
 		entry = &ppe1_foe_base[FOE_ENTRY_NUM(skb)];
 	} else if(FOE_SP(skb) == MDMA_PSE_PORT) {
 		entry = &ppe1_foe_base[FOE_ENTRY_NUM(skb)];
-	} else if((FOE_SP(skb) == EDMA0_PSE_PORT)) {
+	} else if(FOE_SP(skb) == EDMA0_PSE_PORT) {
 		entry = &ppe_foe_base[FOE_ENTRY_NUM(skb)];
-	} else if((FOE_SP(skb) == EDMA1_PSE_PORT) ) {
+	} else if(FOE_SP(skb) == EDMA1_PSE_PORT) {
 		entry = &ppe1_foe_base[FOE_ENTRY_NUM(skb)];
- 	} else if((FOE_SP(skb) == ADMA_PSE_PORT) || (FOE_SP(skb) == QDMA_PSE_PORT)) {
+	} else if(FOE_SP(skb) == ADMA_PSE_PORT) {
 		entry = &ppe_foe_base[FOE_ENTRY_NUM(skb)];
+	} else if(FOE_SP(skb) == QDMA_PSE_PORT) { // QoS
+		entry = (FOE_AI(skb) == PACKET_FORWARD_PATH_WITHOUT_PPE)?
+			&ppe1_foe_base[FOE_ENTRY_NUM(skb)] : // MDMA
+			&ppe_foe_base[FOE_ENTRY_NUM(skb)];
 	} else {
 		entry = &ppe_foe_base[FOE_ENTRY_NUM(skb)];
 		if (debug_level >= 3) {
@@ -4980,7 +4976,7 @@
 	hnat_chip_name |= MT7623_HWNAT;
 	hnat_chip_name |= LEOPARD_HWNAT;
 
-	pr_notice("hnat_chip_name = %x\n", hnat_chip_name);
+	pr_notice("hnat_chip_name = 0x%x\n", hnat_chip_name);
 }
 
 void fe_feature_setting(void)
@@ -5015,7 +5011,7 @@
 	fe_feature |= ETH_QOS;
 	fe_feature |= SW_DVFS;
 
-	pr_notice("fe_feature = %x\n", fe_feature);
+	pr_notice("fe_feature = 0x%x\n", fe_feature);
 	for (i = 0; i < ARRAY_SIZE(mtk_hnat_feature_name); i++) {
 		if (fe_feature & BIT(i))
 			pr_notice("!! hwnat feature :%s\n", mtk_hnat_feature_name[i]);
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_config.h b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_config.h
index 222ccc3..5a2643e 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_config.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_config.h
@@ -69,12 +69,13 @@
 #define USE_UDP_FRAG
 #endif
 
+/* hnat_chip_name */
+
 #ifdef CONFIG_RALINK_MT7620
 #define MT7620_HWNAT	BIT(0)
 #else
 #define MT7620_HWNAT	(0)
 #endif
-
 #ifdef CONFIG_RALINK_MT7621
 #define MT7621_HWNAT	BIT(1)
 #else
@@ -96,8 +97,10 @@
 #define LEOPARD_HWNAT	(0)
 #endif
 
+/* fe_feature */
+
 #ifdef	CONFIG_RAETH_GMAC2
-#define GE2_SUPPORT	(1)
+#define GE2_SUPPORT	BIT(0)
 #else
 #define GE2_SUPPORT	(0)
 #endif
@@ -114,7 +117,7 @@
 #define HNAT_VLAN_TX	(0)
 #endif
 
-#ifdef	CONFIG_PPE_MCAST
+#if 0 /*def	CONFIG_PPE_MCAST */
 #define HNAT_MCAST	BIT(3)
 #else
 #define HNAT_MCAST	(0)
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h
old mode 100644
new mode 100755
index feb84dc..b69017b
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_define.h
@@ -127,14 +127,12 @@
 /*extern struct pkt_parse_result ppe_parse_result;*/
 extern int dbg_cpu_reason;
 
-#ifdef CONFIG_SUPPORT_OPENWRT
 #define DEV_NAME_HNAT_LAN	"eth0"
 #define DEV_NAME_HNAT_WAN	"eth1"
-#define DEV_NAME_HNAT_SNPS	"eth2"
+#ifdef CONFIG_MTK_SGMII_SNPS
+#define DEV_NAME_HNAT_SNPS	"eth1"
 #else
-#define DEV_NAME_HNAT_LAN	"eth2"
-#define DEV_NAME_HNAT_WAN	"eth3"
-#define DEV_NAME_HNAT_SNPS	"eth4"
+#define DEV_NAME_HNAT_SNPS	"eth2"
 #endif
 
 #define DEV_NAME_HNAT_EDMA0	"edma0"
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hwnat_config.h b/src/kernel/modules/netsys_driver/nat/hw_nat/hwnat_config.h
old mode 100644
new mode 100755
index 5f72f3e..5a92292
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hwnat_config.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hwnat_config.h
@@ -103,7 +103,8 @@
 #define HNAT_VLAN_TX	(0)
 #endif
 
-#ifdef	CONFIG_PPE_MCAST
+/* disable mucast */
+#if 0 /*def	CONFIG_PPE_MCAST */
 #define HNAT_MCAST	BIT(3)
 #else
 #define HNAT_MCAST	(0)
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
index 9466dc5..4f05d42 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
@@ -427,10 +427,11 @@
 int32_t ppe_rx_eth_handler(struct sk_buff *skb)
 {
 	int ret;
+
+	foe_format_create(skb);
 	if (debug_level >= 10)
 		pr_info("%s, FOE_AI(skb):0x%x, FOE_SP(skb):%d\n", __func__, FOE_AI(skb), FOE_SP(skb));
 
-	foe_format_create(skb);
 	//FOE_INFO_DUMP(skb);
 	FOE_ALG(skb) = 0;
 	rx_debug_log(skb);
@@ -658,9 +659,8 @@
 		/* EDIA TX fast path is not ready */
 		ppe_hook_tx_ext = NULL;
 
-		/* Default off */
-		ppe_hook_rx_snps = NULL;
-		ppe_hook_tx_snps = NULL;
+		ppe_hook_rx_snps = ppe_rx_snps_handler;
+		ppe_hook_tx_snps = ppe_tx_snps_handler;
 
 		ppe_get_dev_stats = ppe_get_dev_stats_handler;
 
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h
index 0bed4d3..056f403 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.h
@@ -140,7 +140,8 @@
 	HIT_BIND_MULTICAST_TO_CPU = 0x18,
 	/*  Switch clone multicast packet to GMAC1 & CPU */
 	HIT_BIND_MULTICAST_TO_GMAC_CPU = 0x19,
-	HIT_PRE_BIND = 0x1A	/*  Pre-bind */
+	HIT_PRE_BIND = 0x1A,	/*  Pre-bind */
+	PACKET_FORWARD_PATH_WITHOUT_PPE = 0x1E
 };