[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 = <ð_phy0>;
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <ð_default>;
- pinctrl-1 = <ð_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 = <ð_smi_mdio_pinctl>;
pinctrl-2 = <ð_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 = <ð_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 = <ð_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 = <ðsys>;
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(ð->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(ð->mii_bus->mdio_lock);
}
u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
{
u16 high, low;
+ mutex_lock(ð->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(ð->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(ð->mii_bus->mdio_lock);
*read_data = _mtk_mdio_read(eth, phy_addr, phy_register);
+ mutex_unlock(ð->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(ð->mii_bus->mdio_lock);
_mtk_mdio_write(eth, phy_addr, phy_register, write_data);
+ mutex_unlock(ð->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 = ð->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 = ð->rx_ring[i];
if (ring->calc_idx_update) {
@@ -1116,9 +1199,6 @@
mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
}
}
- } else {
- ring = ð->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(ð->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(ð->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(ð->dma_refcnt, 1);
}
else
refcount_inc(ð->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(ð->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(ð->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(ð->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(ð->tx_napi);
//napi_enable(ð->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);