diff --git a/projects/Allwinner/devices/A64/patches/linux/0001-HACK-a64-Add-HDMI-sound-card.patch b/projects/Allwinner/devices/A64/patches/linux/0001-HACK-a64-Add-HDMI-sound-card.patch new file mode 100644 index 0000000000..be4cdd7bfa --- /dev/null +++ b/projects/Allwinner/devices/A64/patches/linux/0001-HACK-a64-Add-HDMI-sound-card.patch @@ -0,0 +1,53 @@ +From ff9ed48eb584e583e20509af6cde1ba80ebd3edd Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 10:49:00 +0100 +Subject: [PATCH] HACK: a64: Add HDMI sound card + +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 20 ++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -161,6 +161,24 @@ + }; + }; + ++ sound_hdmi: sound_hdmi { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "allwinner-hdmi"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,frame-inversion; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s2>; ++ dai-tdm-slot-num = <2>; ++ dai-tdm-slot-width = <32>; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + allwinner,erratum-unknown1; +@@ -878,7 +896,6 @@ + resets = <&ccu RST_BUS_I2S2>; + dma-names = "rx", "tx"; + dmas = <&dma 27>, <&dma 27>; +- status = "disabled"; + }; + + dai: dai@1c22c00 { +@@ -1178,6 +1195,7 @@ + }; + + hdmi: hdmi@1ee0000 { ++ #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-a64-dw-hdmi", + "allwinner,sun8i-a83t-dw-hdmi"; + reg = <0x01ee0000 0x10000>; diff --git a/projects/Allwinner/devices/A64/patches/linux/05-a64-increase-mali-frequency.patch b/projects/Allwinner/devices/A64/patches/linux/0002-a64-increase-mali-frequency.patch similarity index 78% rename from projects/Allwinner/devices/A64/patches/linux/05-a64-increase-mali-frequency.patch rename to projects/Allwinner/devices/A64/patches/linux/0002-a64-increase-mali-frequency.patch index 289074d582..33a08323a5 100644 --- a/projects/Allwinner/devices/A64/patches/linux/05-a64-increase-mali-frequency.patch +++ b/projects/Allwinner/devices/A64/patches/linux/0002-a64-increase-mali-frequency.patch @@ -8,11 +8,9 @@ Signed-off-by: Jernej Skrabec arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 3 +++ 1 file changed, 3 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -index 31143fe64d91..1f22b0f6a4e0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -1055,6 +1055,9 @@ mali: gpu@1c40000 { +@@ -1101,6 +1101,9 @@ clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>; clock-names = "bus", "core"; resets = <&ccu RST_BUS_GPU>; @@ -22,6 +20,3 @@ index 31143fe64d91..1f22b0f6a4e0 100644 }; gic: interrupt-controller@1c81000 { --- -2.26.0 - diff --git a/projects/Allwinner/devices/A64/patches/linux/01_a64_hdmi_audio.patch b/projects/Allwinner/devices/A64/patches/linux/01_a64_hdmi_audio.patch deleted file mode 100644 index 6994536945..0000000000 --- a/projects/Allwinner/devices/A64/patches/linux/01_a64_hdmi_audio.patch +++ /dev/null @@ -1,48 +0,0 @@ -Date: Sun, 3 Dec 2017 11:43:08 -0800 -Subject: [PATCH] Add A64 HDMI sound node - ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 29 +++++++++++++++++++ - 2 files changed, 47 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -index 0f69f35939755..0b44018361cbf 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -727,6 +727,36 @@ - status = "disabled"; - }; - -+ i2s2: i2s@1c22800 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun8i-h3-i2s"; -+ reg = <0x01c22800 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; -+ clock-names = "apb", "mod"; -+ dmas = <&dma 27>; -+ resets = <&ccu RST_BUS_I2S2>; -+ dma-names = "tx"; -+ allwinner,playback-channels = <8>; -+ }; -+ -+ sound_hdmi: sound_hdmi { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "allwinner-hdmi"; -+ simple-audio-card,mclk-fs = <128>; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s2>; -+ dai-tdm-slot-num = <2>; -+ dai-tdm-slot-width = <32>; -+ }; -+ }; -+ - rtc: rtc@1f00000 { - compatible = "allwinner,sun6i-a31-rtc"; - reg = <0x01f00000 0x54>; diff --git a/projects/Allwinner/devices/A64/patches/linux/02_hdmi_sound_cell.patch b/projects/Allwinner/devices/A64/patches/linux/02_hdmi_sound_cell.patch deleted file mode 100644 index 5fbe486aee..0000000000 --- a/projects/Allwinner/devices/A64/patches/linux/02_hdmi_sound_cell.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -Nur a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 2018-11-17 18:26:20.000000000 +0100 -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 2018-11-17 19:29:15.132911602 +0100 -@@ -892,6 +892,7 @@ - }; - - hdmi: hdmi@1ee0000 { -+ #sound-dai-cells = <0>; - compatible = "allwinner,sun50i-a64-dw-hdmi", - "allwinner,sun8i-a83t-dw-hdmi"; - reg = <0x01ee0000 0x10000>; diff --git a/projects/Allwinner/devices/A64/patches/linux/04-Add-frame-inversion-to-correct-multi-channel-audio.patch b/projects/Allwinner/devices/A64/patches/linux/04-Add-frame-inversion-to-correct-multi-channel-audio.patch deleted file mode 100644 index 16bbbb5c80..0000000000 --- a/projects/Allwinner/devices/A64/patches/linux/04-Add-frame-inversion-to-correct-multi-channel-audio.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 08d35c5d5ce6de3453f17e6eff7375afa74173d2 Mon Sep 17 00:00:00 2001 -From: Marcus Cooper -Date: Thu, 2 Jan 2020 19:09:25 +0100 -Subject: [PATCH] Add frame inversion to correct multi-channel audio - ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -index 988e261a0ab3..4e20a0872c0c 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -1101,6 +1101,7 @@ - simple-audio-card,format = "i2s"; - simple-audio-card,name = "allwinner-hdmi"; - simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,frame-inversion; - - simple-audio-card,codec { - sound-dai = <&hdmi>; --- -2.24.1 - diff --git a/projects/Allwinner/devices/H2-plus/patches/linux/0001-ARM-dts-sun8i-h2-plus-bananapi-m2-zero-Increase-BT-U.patch b/projects/Allwinner/devices/H2-plus/patches/linux/0001-ARM-dts-sun8i-h2-plus-bananapi-m2-zero-Increase-BT-U.patch new file mode 100644 index 0000000000..21047f5b7a --- /dev/null +++ b/projects/Allwinner/devices/H2-plus/patches/linux/0001-ARM-dts-sun8i-h2-plus-bananapi-m2-zero-Increase-BT-U.patch @@ -0,0 +1,26 @@ +From 4cc652f2c660bd01bd0d8cefde272400cbe82fbe Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 11:32:04 +0100 +Subject: [PATCH 1/2] ARM: dts: sun8i: h2-plus: bananapi-m2-zero: Increase BT + UART speed + +Bluetooth module on BananaPi M2 Zero can also be used for streaming +audio. However, for that case higher UART speed is required. + +Add a max-speed property. + +Signed-off-by: Jernej Skrabec +--- + arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts ++++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts +@@ -125,6 +125,7 @@ + + bluetooth { + compatible = "brcm,bcm43438-bt"; ++ max-speed = <1500000>; + clocks = <&rtc 1>; + clock-names = "lpo"; + vbat-supply = <®_vcc3v3>; diff --git a/projects/Allwinner/devices/H2-plus/patches/linux/50-armbian-add-bananapim2-zero-z1-HDMI-out.patch b/projects/Allwinner/devices/H2-plus/patches/linux/0002-ARM-dts-sunxi-h2-plus-bananapi-m2-zero-Add-HDMI-out.patch similarity index 56% rename from projects/Allwinner/devices/H2-plus/patches/linux/50-armbian-add-bananapim2-zero-z1-HDMI-out.patch rename to projects/Allwinner/devices/H2-plus/patches/linux/0002-ARM-dts-sunxi-h2-plus-bananapi-m2-zero-Add-HDMI-out.patch index 0ef48b0586..daeef7f63f 100644 --- a/projects/Allwinner/devices/H2-plus/patches/linux/50-armbian-add-bananapim2-zero-z1-HDMI-out.patch +++ b/projects/Allwinner/devices/H2-plus/patches/linux/0002-ARM-dts-sunxi-h2-plus-bananapi-m2-zero-Add-HDMI-out.patch @@ -1,14 +1,13 @@ -commit 9702424ea23471e3bdbe6a150e28a1ecdf837d2c -Author: PJBrs -Date: Fri Feb 21 08:56:04 2020 +0100 +From aa47c3b292cb0ffcf2c00b2a12c477ec3027a729 Mon Sep 17 00:00:00 2001 +From: PJBrs +Date: Sat, 16 Jan 2021 11:39:45 +0100 +Subject: [PATCH 2/2] ARM: dts: sunxi: h2-plus-bananapi-m2-zero: Add HDMI out - ARM: dts: sunxi: h2-plus-bananapi-m2-zero: Add HDMI out - - Add HDMI out, including the display engine, to the BananaPi - M2 Zero. +Add HDMI out, including the display engine, to the BananaPi M2 Zero. +--- + .../dts/sun8i-h2-plus-bananapi-m2-zero.dts | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) -diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts -index 38e8da594e44..9051a1097258 100644 --- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts +++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts @@ -26,6 +26,17 @@ @@ -29,7 +28,7 @@ index 38e8da594e44..9051a1097258 100644 leds { compatible = "gpio-leds"; -@@ -140,6 +151,20 @@ +@@ -107,6 +118,20 @@ }; }; diff --git a/projects/Allwinner/devices/H2-plus/patches/linux/01-increase-bt-speed.patch b/projects/Allwinner/devices/H2-plus/patches/linux/01-increase-bt-speed.patch deleted file mode 100644 index 287a585d02..0000000000 --- a/projects/Allwinner/devices/H2-plus/patches/linux/01-increase-bt-speed.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts -index b4ddfaf01b45..e746abb724b4 100644 ---- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts -+++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts -@@ -125,6 +125,7 @@ &uart1 { - - bluetooth { - compatible = "brcm,bcm43438-bt"; -+ max-speed = <1500000>; - clocks = <&rtc 1>; - clock-names = "lpo"; - vbat-supply = <®_vcc3v3>; diff --git a/projects/Allwinner/devices/H2-plus/patches/linux/16-H3-add-HDMI-sound-nodes.patch b/projects/Allwinner/devices/H2-plus/patches/linux/16-H3-add-HDMI-sound-nodes.patch deleted file mode 100644 index 1515ba3355..0000000000 --- a/projects/Allwinner/devices/H2-plus/patches/linux/16-H3-add-HDMI-sound-nodes.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -index 8aa2befc..d3d70eac 100644 ---- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi -+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -53,6 +53,23 @@ - #address-cells = <1>; - #size-cells = <1>; - -+ sound_hdmi: sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "allwinner-hdmi"; -+ simple-audio-card,mclk-fs = <128>; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s2>; -+ dai-tdm-slot-num = <2>; -+ dai-tdm-slot-width = <32>; -+ }; -+ }; -+ - clocks { - #address-cells = <1>; - #size-cells = <1>; -@@ -631,6 +648,19 @@ - status = "disabled"; - }; - -+ i2s2: i2s@1c22800 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun8i-h3-i2s"; -+ reg = <0x01c22800 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; -+ clock-names = "apb", "mod"; -+ dmas = <&dma 27>; -+ resets = <&ccu RST_BUS_I2S2>; -+ dma-names = "tx"; -+ allwinner,playback-channels = <8>; -+ }; -+ - codec: codec@1c22c00 { - #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-codec"; -@@ -110,6 +126,7 @@ - }; - - hdmi: hdmi@1ee0000 { -+ #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-dw-hdmi", - "allwinner,sun8i-a83t-dw-hdmi"; - reg = <0x01ee0000 0x10000>; diff --git a/projects/Allwinner/devices/H2-plus/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch b/projects/Allwinner/devices/H2-plus/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch deleted file mode 100644 index 21e13cbfd7..0000000000 --- a/projects/Allwinner/devices/H2-plus/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 51dcda7a261bcadca0a8f5e6fe6241ec266438d0 Mon Sep 17 00:00:00 2001 -From: Marcus Cooper -Date: Thu, 2 Jan 2020 19:03:35 +0100 -Subject: [PATCH] Add frame inversion to correct multi-channel audio - ---- - arch/arm/boot/dts/sunxi-h3-h5.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -index 8644435e66d3..7375a9479e84 100644 ---- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi -+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -82,6 +82,7 @@ - simple-audio-card,format = "i2s"; - simple-audio-card,name = "allwinner-hdmi"; - simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,frame-inversion; - - simple-audio-card,codec { - sound-dai = <&hdmi>; --- -2.24.1 - diff --git a/projects/Allwinner/patches/linux/0006-wip-cec-improvements.patch b/projects/Allwinner/devices/H3/patches/linux/0001-HACK-SW-CEC-implementation-for-H3.patch similarity index 51% rename from projects/Allwinner/patches/linux/0006-wip-cec-improvements.patch rename to projects/Allwinner/devices/H3/patches/linux/0001-HACK-SW-CEC-implementation-for-H3.patch index 9cda689946..5bf122c9fd 100644 --- a/projects/Allwinner/patches/linux/0006-wip-cec-improvements.patch +++ b/projects/Allwinner/devices/H3/patches/linux/0001-HACK-SW-CEC-implementation-for-H3.patch @@ -1,85 +1,24 @@ -From bf21ad0889bdcc1dc12fe5a024fd7df7ad2c4310 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 26 Feb 2019 20:45:14 +0000 -Subject: [PATCH 1/2] WIP: dw-hdmi-cec: sleep 100ms on error - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c -index 6c323510f128..b5a1a85c8700 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c -@@ -7,6 +7,7 @@ - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -+#include - #include - #include - #include -@@ -132,8 +133,15 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) - - dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); - -- if (stat & CEC_STAT_ERROR_INIT) { -- cec->tx_status = CEC_TX_STATUS_ERROR; -+ /* Status with both done and error_initiator bits have been seen -+ * on Rockchip RK3328 devices, transmit attempt seems to have failed -+ * when this happens, report as low drive and block cec-framework -+ * 100ms before core retransmits the failed message, this seems to -+ * mitigate the issue with failed transmit attempts. -+ */ -+ if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { -+ pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); -+ cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; - cec->tx_done = true; - ret = IRQ_WAKE_THREAD; - } else if (stat & CEC_STAT_DONE) { -@@ -144,6 +152,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) - cec->tx_status = CEC_TX_STATUS_NACK; - cec->tx_done = true; - ret = IRQ_WAKE_THREAD; -+ } else if (stat & CEC_STAT_ERROR_INIT) { -+ cec->tx_status = CEC_TX_STATUS_ERROR; -+ cec->tx_done = true; -+ ret = IRQ_WAKE_THREAD; - } - - if (stat & CEC_STAT_EOM) { -@@ -176,6 +188,8 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) - - if (cec->tx_done) { - cec->tx_done = false; -+ if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) -+ msleep(100); - cec_transmit_attempt_done(adap, cec->tx_status); - } - if (cec->rx_done) { --- -2.21.0 - - -From 12f1abe2b5cee6575c6dd9cd29b17b589f044b80 Mon Sep 17 00:00:00 2001 +From 0981ac8f42983c820790b14668d59f39b0375d90 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 25 May 2019 12:03:39 +0200 -Subject: [PATCH 2/2] WIP: sun8i-hdmi CEC improvements +Subject: [PATCH] HACK: SW CEC implementation for H3 + +Many H3 boards lack 32768 Hz external oscillator, so internal RC is used +instead. However, it's too unstable for CEC. Use SW implementation +instead. That makes it usable, albeit sensitive to cpufreq changes. Signed-off-by: Jernej Skrabec --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- - drivers/gpu/drm/sun4i/Kconfig | 10 +++ - drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 11 +++ - drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 83 ++++++++++++++++++++++- + drivers/gpu/drm/sun4i/Kconfig | 2 + + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 12 ++++ + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 74 ++++++++++++++++++++++- include/drm/bridge/dw_hdmi.h | 2 + - 5 files changed, 105 insertions(+), 3 deletions(-) + 5 files changed, 89 insertions(+), 3 deletions(-) -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 09fdc9f87651..f359c4c3f1d1 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -2713,7 +2713,7 @@ __dw_hdmi_probe(struct platform_device *pdev, +@@ -3421,7 +3421,7 @@ struct dw_hdmi *dw_hdmi_probe(struct pla hdmi->audio = platform_device_register_full(&pdevinfo); } @@ -88,32 +27,20 @@ index 09fdc9f87651..f359c4c3f1d1 100644 cec.hdmi = hdmi; cec.ops = &dw_hdmi_cec_ops; cec.irq = irq; -diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig -index 1dbbc3a1b763..7149c72e44c8 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig -@@ -60,6 +60,16 @@ config DRM_SUN8I_DW_HDMI +@@ -56,6 +56,8 @@ config DRM_SUN8I_DW_HDMI + tristate "Support for Allwinner version of DesignWare HDMI" + depends on DRM_SUN4I + select DRM_DW_HDMI ++ select CEC_CORE ++ select CEC_PIN + help + Choose this option if you have an Allwinner SoC with the DesignWare HDMI controller with custom HDMI PHY. If M is - selected the module will be called sun8i_dw_hdmi. - -+config DRM_SUN8I_DW_HDMI_CEC -+ bool "Allwinner DesignWare HDMI CEC Support for 40nm SoCs" -+ depends on DRM_SUN8I_DW_HDMI -+ select CEC_CORE -+ select CEC_PIN -+ help -+ Choose this option if you have an 40nm Allwinner SoC with -+ the DesignWare HDMI controller with custom HDMI PHY and -+ you want to use CEC. -+ - config DRM_SUN8I_MIXER - tristate "Support for Allwinner Display Engine 2.0 Mixer" - default MACH_SUN8I -diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h -index 720c5aa8adc1..49ca001923e3 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h -@@ -12,6 +12,8 @@ +@@ -13,6 +13,8 @@ #include #include #include @@ -122,7 +49,7 @@ index 720c5aa8adc1..49ca001923e3 100644 #define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000 #define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0) -@@ -144,6 +145,13 @@ +@@ -145,6 +147,13 @@ #define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK GENMASK(5, 0) #define SUN8I_HDMI_PHY_CEC_REG 0x003c @@ -136,7 +63,7 @@ index 720c5aa8adc1..49ca001923e3 100644 struct sun8i_hdmi_phy; -@@ -151,6 +159,7 @@ struct sun8i_hdmi_phy_variant { +@@ -152,6 +161,7 @@ struct sun8i_hdmi_phy_variant { bool has_phy_clk; bool has_second_pll; unsigned int is_custom_phy : 1; @@ -144,7 +71,7 @@ index 720c5aa8adc1..49ca001923e3 100644 const struct dw_hdmi_curr_ctrl *cur_ctr; const struct dw_hdmi_mpll_config *mpll_cfg; const struct dw_hdmi_phy_config *phy_cfg; -@@ -163,6 +172,8 @@ struct sun8i_hdmi_phy_variant { +@@ -164,6 +174,8 @@ struct sun8i_hdmi_phy_variant { }; struct sun8i_hdmi_phy { @@ -153,11 +80,9 @@ index 720c5aa8adc1..49ca001923e3 100644 struct clk *clk_bus; struct clk *clk_mod; struct clk *clk_phy; -diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c -index 43643ad31730..d840bc07cba6 100644 --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c -@@ -504,8 +504,9 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy) +@@ -505,8 +505,9 @@ static void sun8i_hdmi_phy_init_h3(struc regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0); @@ -169,14 +94,13 @@ index 43643ad31730..d840bc07cba6 100644 /* read calibration data */ regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); -@@ -531,8 +532,49 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy, +@@ -532,8 +533,47 @@ void sun8i_hdmi_phy_set_ops(struct sun8i plat_data->cur_ctr = variant->cur_ctr; plat_data->phy_config = variant->phy_cfg; } + plat_data->is_cec_unusable = phy->variant->bit_bang_cec; } -+#ifdef CONFIG_DRM_SUN8I_DW_HDMI_CEC +static int sun8i_hdmi_phy_cec_pin_read(struct cec_adapter *adap) +{ + struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap); @@ -214,12 +138,11 @@ index 43643ad31730..d840bc07cba6 100644 + .low = sun8i_hdmi_phy_cec_pin_low, + .high = sun8i_hdmi_phy_cec_pin_high, +}; -+#endif + static const struct regmap_config sun8i_hdmi_phy_regmap_config = { .reg_bits = 32, .val_bits = 32, -@@ -549,6 +591,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = { +@@ -550,6 +590,7 @@ static const struct sun8i_hdmi_phy_varia }; static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = { @@ -227,19 +150,10 @@ index 43643ad31730..d840bc07cba6 100644 .has_phy_clk = true, .is_custom_phy = true, .phy_init = &sun8i_hdmi_phy_init_h3, -@@ -566,6 +610,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_r40_hdmi_phy = { - }; - - static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = { -+ .bit_bang_cec = true, - .has_phy_clk = true, - .is_custom_phy = true, - .phy_init = &sun8i_hdmi_phy_init_h3, -@@ -711,10 +756,38 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) +@@ -712,10 +753,36 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw clk_prepare_enable(phy->clk_phy); } -+#ifdef CONFIG_DRM_SUN8I_DW_HDMI_CEC + if (phy->variant->bit_bang_cec) { + phy->cec_adapter = + cec_pin_allocate_adapter(&sun8i_hdmi_phy_cec_pin_ops, @@ -259,7 +173,6 @@ index 43643ad31730..d840bc07cba6 100644 + if (ret < 0) + goto err_put_cec_notifier; + } -+#endif + hdmi->phy = phy; @@ -274,7 +187,7 @@ index 43643ad31730..d840bc07cba6 100644 err_disable_clk_mod: clk_disable_unprepare(phy->clk_mod); err_disable_clk_bus: -@@ -739,6 +814,9 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi) +@@ -740,6 +807,9 @@ void sun8i_hdmi_phy_remove(struct sun8i_ { struct sun8i_hdmi_phy *phy = hdmi->phy; @@ -284,19 +197,14 @@ index 43643ad31730..d840bc07cba6 100644 clk_disable_unprepare(phy->clk_mod); clk_disable_unprepare(phy->clk_bus); clk_disable_unprepare(phy->clk_phy); -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index 323febe7f102..cec73761856d 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h -@@ -144,6 +144,8 @@ struct dw_hdmi_plat_data { - int (*configure_phy)(struct dw_hdmi *hdmi, - const struct dw_hdmi_plat_data *pdata, +@@ -153,6 +153,8 @@ struct dw_hdmi_plat_data { + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, unsigned long mpixelclock); + + unsigned int is_cec_unusable : 1; }; struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, --- -2.21.0 - diff --git a/projects/Allwinner/devices/H3/patches/linux/0002-ARM-dts-sunxi-bananapi-m2-plus-Increase-BT-UART-spee.patch b/projects/Allwinner/devices/H3/patches/linux/0002-ARM-dts-sunxi-bananapi-m2-plus-Increase-BT-UART-spee.patch new file mode 100644 index 0000000000..12059e3a72 --- /dev/null +++ b/projects/Allwinner/devices/H3/patches/linux/0002-ARM-dts-sunxi-bananapi-m2-plus-Increase-BT-UART-spee.patch @@ -0,0 +1,25 @@ +From 54b5c2cb4fc87ca72daa662423d4d969f3b5edb8 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 11:49:57 +0100 +Subject: [PATCH] ARM: dts: sunxi: bananapi-m2-plus: Increase BT UART speed + +Bluetooth module on BananaPi M2 Plus can also be used for streaming +audio. However, for that case higher UART speed is required. + +Add a max-speed property. + +Signed-off-by: Jernej Skrabec +--- + arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi ++++ b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi +@@ -219,6 +219,7 @@ + + bluetooth { + compatible = "brcm,bcm43438-bt"; ++ max-speed = <1500000>; + clocks = <&rtc 1>; + clock-names = "lpo"; + vbat-supply = <®_vcc3v3>; diff --git a/projects/Allwinner/devices/H3/patches/linux/01-increase-bt-speed.patch b/projects/Allwinner/devices/H3/patches/linux/01-increase-bt-speed.patch deleted file mode 100644 index c96395e739..0000000000 --- a/projects/Allwinner/devices/H3/patches/linux/01-increase-bt-speed.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi -index 39263e74fbb5..0ec6109ec625 100644 ---- a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi -+++ b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi -@@ -219,6 +219,7 @@ - - bluetooth { - compatible = "brcm,bcm43438-bt"; -+ max-speed = <1500000>; - clocks = <&rtc 1>; - clock-names = "lpo"; - vbat-supply = <®_vcc3v3>; diff --git a/projects/Allwinner/devices/H3/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch b/projects/Allwinner/devices/H3/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch deleted file mode 100644 index 21e13cbfd7..0000000000 --- a/projects/Allwinner/devices/H3/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 51dcda7a261bcadca0a8f5e6fe6241ec266438d0 Mon Sep 17 00:00:00 2001 -From: Marcus Cooper -Date: Thu, 2 Jan 2020 19:03:35 +0100 -Subject: [PATCH] Add frame inversion to correct multi-channel audio - ---- - arch/arm/boot/dts/sunxi-h3-h5.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -index 8644435e66d3..7375a9479e84 100644 ---- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi -+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -82,6 +82,7 @@ - simple-audio-card,format = "i2s"; - simple-audio-card,name = "allwinner-hdmi"; - simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,frame-inversion; - - simple-audio-card,codec { - sound-dai = <&hdmi>; --- -2.24.1 - diff --git a/projects/Allwinner/devices/H5/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf b/projects/Allwinner/devices/H5/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf deleted file mode 100644 index 1331fd6ad4..0000000000 --- a/projects/Allwinner/devices/H5/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf +++ /dev/null @@ -1,36 +0,0 @@ -# -# Configuration for H3 analog output -# - - - -H3_Audio_Codec.pcm.front.0 { - @args [ CARD ] - @args.CARD { - type string - } - type hooks - slave.pcm { - type hw - card $CARD - } - hooks.0 { - type ctl_elems - hook_args [ - { - name "Line Out Playback Volume" - lock true - preserve true - optional false - value 31 - } - { - name "Line Out Playback Switch" - lock true - preserve true - optional false - value [ on on ] - } - ] - } -} diff --git a/projects/Allwinner/devices/H5/patches/linux/16-H3-add-HDMI-sound-nodes.patch b/projects/Allwinner/devices/H5/patches/linux/16-H3-add-HDMI-sound-nodes.patch deleted file mode 100644 index 1515ba3355..0000000000 --- a/projects/Allwinner/devices/H5/patches/linux/16-H3-add-HDMI-sound-nodes.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -index 8aa2befc..d3d70eac 100644 ---- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi -+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -53,6 +53,23 @@ - #address-cells = <1>; - #size-cells = <1>; - -+ sound_hdmi: sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "allwinner-hdmi"; -+ simple-audio-card,mclk-fs = <128>; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s2>; -+ dai-tdm-slot-num = <2>; -+ dai-tdm-slot-width = <32>; -+ }; -+ }; -+ - clocks { - #address-cells = <1>; - #size-cells = <1>; -@@ -631,6 +648,19 @@ - status = "disabled"; - }; - -+ i2s2: i2s@1c22800 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun8i-h3-i2s"; -+ reg = <0x01c22800 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; -+ clock-names = "apb", "mod"; -+ dmas = <&dma 27>; -+ resets = <&ccu RST_BUS_I2S2>; -+ dma-names = "tx"; -+ allwinner,playback-channels = <8>; -+ }; -+ - codec: codec@1c22c00 { - #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-codec"; -@@ -110,6 +126,7 @@ - }; - - hdmi: hdmi@1ee0000 { -+ #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-dw-hdmi", - "allwinner,sun8i-a83t-dw-hdmi"; - reg = <0x01ee0000 0x10000>; diff --git a/projects/Allwinner/devices/H5/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch b/projects/Allwinner/devices/H5/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch deleted file mode 100644 index 21e13cbfd7..0000000000 --- a/projects/Allwinner/devices/H5/patches/linux/17-Add-frame-inversion-to-correct-multi-channel-audio.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 51dcda7a261bcadca0a8f5e6fe6241ec266438d0 Mon Sep 17 00:00:00 2001 -From: Marcus Cooper -Date: Thu, 2 Jan 2020 19:03:35 +0100 -Subject: [PATCH] Add frame inversion to correct multi-channel audio - ---- - arch/arm/boot/dts/sunxi-h3-h5.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -index 8644435e66d3..7375a9479e84 100644 ---- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi -+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -82,6 +82,7 @@ - simple-audio-card,format = "i2s"; - simple-audio-card,name = "allwinner-hdmi"; - simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,frame-inversion; - - simple-audio-card,codec { - sound-dai = <&hdmi>; --- -2.24.1 - diff --git a/projects/Allwinner/devices/H6/patches/linux/0001-HACK-h6-Add-HDMI-sound-card.patch b/projects/Allwinner/devices/H6/patches/linux/0001-HACK-h6-Add-HDMI-sound-card.patch new file mode 100644 index 0000000000..a9e3f72ddb --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0001-HACK-h6-Add-HDMI-sound-card.patch @@ -0,0 +1,53 @@ +From da5268aa6c9a552ceebf74263acf997489368adc Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 10:58:14 +0100 +Subject: [PATCH 01/14] HACK: h6: Add HDMI sound card + +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -108,6 +108,24 @@ + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + ++ sound_hdmi: sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "allwinner-hdmi"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,frame-inversion; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ dai-tdm-slot-num = <2>; ++ dai-tdm-slot-width = <32>; ++ }; ++ }; ++ + soc { + compatible = "simple-bus"; + #address-cells = <1>; +@@ -651,7 +669,6 @@ + dmas = <&dma 4>, <&dma 4>; + resets = <&ccu RST_BUS_I2S1>; + dma-names = "rx", "tx"; +- status = "disabled"; + }; + + spdif: spdif@5093000 { +@@ -784,6 +801,7 @@ + }; + + hdmi: hdmi@6000000 { ++ #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-h6-dw-hdmi"; + reg = <0x06000000 0x10000>; + reg-io-width = <1>; diff --git a/projects/Allwinner/devices/H6/patches/linux/0002-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regu.patch b/projects/Allwinner/devices/H6/patches/linux/0002-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regu.patch new file mode 100644 index 0000000000..29ac39de4c --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0002-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regu.patch @@ -0,0 +1,70 @@ +From 7f12904df66e28c2a5fa8ea652ed9eee48a22131 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Wed, 27 Mar 2019 13:21:06 +0100 +Subject: [PATCH 02/14] net: stmmac: sun8i: Use devm_regulator_get for PHY + regulator + +Use devm_regulator_get instead of devm_regulator_get_optional and rely +on dummy supply. This avoids NULL checks before regulator_enable/disable +calls. + +This path also improves error reporting, because we now report both +use of dummy supply and error during registration with more detail, +instead of generic info level message "No regulator found" that +was reported previously on errors and lack of regulator property in DT. + +Finally, we'll be adding further optional regulators, and the overall +code will be simpler. + +Signed-off-by: Ondrej Jirman +--- + .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++----------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -544,12 +544,10 @@ static int sun8i_dwmac_init(struct platf + struct sunxi_priv_data *gmac = priv; + int ret; + +- if (gmac->regulator) { +- ret = regulator_enable(gmac->regulator); +- if (ret) { +- dev_err(&pdev->dev, "Fail to enable regulator\n"); +- return ret; +- } ++ ret = regulator_enable(gmac->regulator); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to enable regulator\n"); ++ return ret; + } + + ret = clk_prepare_enable(gmac->tx_clk); +@@ -1017,8 +1015,7 @@ static void sun8i_dwmac_exit(struct plat + + clk_disable_unprepare(gmac->tx_clk); + +- if (gmac->regulator) +- regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1155,12 +1152,12 @@ static int sun8i_dwmac_probe(struct plat + } + + /* Optional regulator for PHY */ +- gmac->regulator = devm_regulator_get_optional(dev, "phy"); ++ gmac->regulator = devm_regulator_get(dev, "phy"); + if (IS_ERR(gmac->regulator)) { +- if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- dev_info(dev, "No regulator found\n"); +- gmac->regulator = NULL; ++ ret = PTR_ERR(gmac->regulator); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); ++ return ret; + } + + /* The "GMAC clock control" register might be located in the diff --git a/projects/Allwinner/devices/H6/patches/linux/0003-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-re.patch b/projects/Allwinner/devices/H6/patches/linux/0003-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-re.patch new file mode 100644 index 0000000000..cbab1f8232 --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0003-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-re.patch @@ -0,0 +1,81 @@ +From 455e29ad5f37b40532b9cf56781dab3c3eb275b5 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:29:29 +0200 +Subject: [PATCH 03/14] net: stmmac: sun8i: Rename PHY regulator variable to + regulator_phy + +We'll be adding further optional regulators, and this makes it clearer +what the regulator is for. + +Signed-off-by: Ondrej Jirman +--- + .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 32 ++++++++++--------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -57,19 +57,21 @@ struct emac_variant { + }; + + /* struct sunxi_priv_data - hold all sunxi private data +- * @tx_clk: reference to MAC TX clock +- * @ephy_clk: reference to the optional EPHY clock for the internal PHY +- * @regulator: reference to the optional regulator +- * @rst_ephy: reference to the optional EPHY reset for the internal PHY +- * @variant: reference to the current board variant +- * @regmap: regmap for using the syscon +- * @internal_phy_powered: Does the internal PHY is enabled +- * @mux_handle: Internal pointer used by mdio-mux lib ++ * @tx_clk: reference to MAC TX clock ++ * @ephy_clk: reference to the optional EPHY clock for ++ * the internal PHY ++ * @regulator_phy: reference to the optional regulator ++ * @rst_ephy: reference to the optional EPHY reset for ++ * the internal PHY ++ * @variant: reference to the current board variant ++ * @regmap: regmap for using the syscon ++ * @internal_phy_powered: Does the internal PHY is enabled ++ * @mux_handle: Internal pointer used by mdio-mux lib + */ + struct sunxi_priv_data { + struct clk *tx_clk; + struct clk *ephy_clk; +- struct regulator *regulator; ++ struct regulator *regulator_phy; + struct reset_control *rst_ephy; + const struct emac_variant *variant; + struct regmap_field *regmap_field; +@@ -544,9 +546,9 @@ static int sun8i_dwmac_init(struct platf + struct sunxi_priv_data *gmac = priv; + int ret; + +- ret = regulator_enable(gmac->regulator); ++ ret = regulator_enable(gmac->regulator_phy); + if (ret) { +- dev_err(&pdev->dev, "Fail to enable regulator\n"); ++ dev_err(&pdev->dev, "Fail to enable PHY regulator\n"); + return ret; + } + +@@ -1015,7 +1017,7 @@ static void sun8i_dwmac_exit(struct plat + + clk_disable_unprepare(gmac->tx_clk); + +- regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator_phy); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1152,9 +1154,9 @@ static int sun8i_dwmac_probe(struct plat + } + + /* Optional regulator for PHY */ +- gmac->regulator = devm_regulator_get(dev, "phy"); +- if (IS_ERR(gmac->regulator)) { +- ret = PTR_ERR(gmac->regulator); ++ gmac->regulator_phy = devm_regulator_get(dev, "phy"); ++ if (IS_ERR(gmac->regulator_phy)) { ++ ret = PTR_ERR(gmac->regulator_phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); + return ret; diff --git a/projects/Allwinner/devices/H6/patches/linux/0004-net-stmmac-sun8i-Add-support-for-enabling-a-regulato.patch b/projects/Allwinner/devices/H6/patches/linux/0004-net-stmmac-sun8i-Add-support-for-enabling-a-regulato.patch new file mode 100644 index 0000000000..8e70e4f755 --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0004-net-stmmac-sun8i-Add-support-for-enabling-a-regulato.patch @@ -0,0 +1,95 @@ +From a2903d15de86fc3ab455a665e22ad6e5c27f8c43 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:31:38 +0200 +Subject: [PATCH 04/14] net: stmmac: sun8i: Add support for enabling a + regulator for PHY I/O pins + +Orange Pi 3 has two regulators that power the Realtek RTL8211E. According +to the phy datasheet, both regulators need to be enabled at the same time. + +Add support for the second optional regulator, "phy-io", to the glue +driver. + +Signed-off-by: Ondrej Jirman +--- + .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 30 ++++++++++++++++--- + 1 file changed, 26 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -61,6 +61,8 @@ struct emac_variant { + * @ephy_clk: reference to the optional EPHY clock for + * the internal PHY + * @regulator_phy: reference to the optional regulator ++ * @regulator_phy_io: reference to the optional regulator for ++ * PHY I/O pins + * @rst_ephy: reference to the optional EPHY reset for + * the internal PHY + * @variant: reference to the current board variant +@@ -72,6 +74,7 @@ struct sunxi_priv_data { + struct clk *tx_clk; + struct clk *ephy_clk; + struct regulator *regulator_phy; ++ struct regulator *regulator_phy_io; + struct reset_control *rst_ephy; + const struct emac_variant *variant; + struct regmap_field *regmap_field; +@@ -546,21 +549,30 @@ static int sun8i_dwmac_init(struct platf + struct sunxi_priv_data *gmac = priv; + int ret; + ++ ret = regulator_enable(gmac->regulator_phy_io); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to enable PHY I/O regulator\n"); ++ return ret; ++ } ++ + ret = regulator_enable(gmac->regulator_phy); + if (ret) { + dev_err(&pdev->dev, "Fail to enable PHY regulator\n"); +- return ret; ++ goto err_disable_regulator_phy_io; + } + + ret = clk_prepare_enable(gmac->tx_clk); + if (ret) { +- if (gmac->regulator) +- regulator_disable(gmac->regulator); + dev_err(&pdev->dev, "Could not enable AHB clock\n"); +- return ret; ++ goto err_disable_regulator_phy; + } + + return 0; ++err_disable_regulator_phy: ++ regulator_disable(gmac->regulator_phy); ++err_disable_regulator_phy_io: ++ regulator_disable(gmac->regulator_phy_io); ++ return ret; + } + + static void sun8i_dwmac_core_init(struct mac_device_info *hw, +@@ -1018,6 +1030,7 @@ static void sun8i_dwmac_exit(struct plat + clk_disable_unprepare(gmac->tx_clk); + + regulator_disable(gmac->regulator_phy); ++ regulator_disable(gmac->regulator_phy_io); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1162,6 +1175,15 @@ static int sun8i_dwmac_probe(struct plat + return ret; + } + ++ /* Optional regulator for PHY I/O pins */ ++ gmac->regulator_phy_io = devm_regulator_get(dev, "phy-io"); ++ if (IS_ERR(gmac->regulator_phy_io)) { ++ ret = PTR_ERR(gmac->regulator_phy_io); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get PHY I/O regulator (%d)\n", ret); ++ return ret; ++ } ++ + /* The "GMAC clock control" register might be located in the + * CCU address range (on the R40), or the system control address + * range (on most other sun8i and later SoCs). diff --git a/projects/Allwinner/devices/H6/patches/linux/0005-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch b/projects/Allwinner/devices/H6/patches/linux/0005-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch new file mode 100644 index 0000000000..f33067038d --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0005-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch @@ -0,0 +1,100 @@ +From 3a078af461185f3ed34c182616365da3a60c6b77 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:54:48 +0200 +Subject: [PATCH 05/14] arm64: dts: allwinner: orange-pi-3: Enable ethernet + +Orange Pi 3 has two regulators that power the Realtek RTL8211E +PHY. According to the datasheet, both regulators need to be enabled +at the same time, or that "phy-io" should be enabled slightly earlier +than "phy" regulator. + +RTL8211E/RTL8211EG datasheet says: + + Note 4: 2.5V (or 1.8/1.5V) RGMII power should be risen simultaneously + or slightly earlier than 3.3V power. Rising 2.5V (or 1.8/1.5V) power + later than 3.3V power may lead to errors. + +The driver ensures the regulator enable ordering. The timing is set +in DT via startup-delay-us. + +We also need to wait at least 30ms after power-up/reset, before +accessing the PHY registers. + +All values of RX/TX delay were tested exhaustively and a middle one +of the range of working values was chosen. + +Signed-off-by: Ondrej Jirman +--- + .../dts/allwinner/sun50i-h6-orangepi-3.dts | 40 +++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -15,6 +15,7 @@ + aliases { + serial0 = &uart0; + serial1 = &uart1; ++ ethernet0 = &emac; + }; + + chosen { +@@ -64,6 +65,15 @@ + regulator-always-on; + }; + ++ reg_gmac_2v5: gmac-2v5 { ++ compatible = "regulator-fixed"; ++ regulator-name = "gmac-2v5"; ++ regulator-min-microvolt = <2500000>; ++ regulator-max-microvolt = <2500000>; ++ enable-active-high; ++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ ++ }; ++ + reg_vcc33_wifi: vcc33-wifi { + /* Always on 3.3V regulator for WiFi and BT */ + compatible = "regulator-fixed"; +@@ -128,6 +138,35 @@ + }; + }; + ++&emac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ext_rgmii_pins>; ++ phy-mode = "rgmii-txid"; ++ phy-handle = <&ext_rgmii_phy>; ++ /* ++ * The board uses 2.5V RGMII signalling. Power sequence to enable ++ * the phy is to enable GMAC-2V5 and GMAC-3V (aldo2) power rails ++ * at the same time and to wait 100ms. The driver enables phy-io ++ * first. Delay is achieved with enable-ramp-delay on reg_aldo2. ++ */ ++ phy-supply = <®_aldo2>; ++ phy-io-supply = <®_gmac_2v5>; ++ allwinner,rx-delay-ps = <1500>; ++ allwinner,tx-delay-ps = <700>; ++ status = "okay"; ++}; ++ ++&mdio { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ ++ reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ ++ reset-assert-us = <15000>; ++ reset-deassert-us = <40000>; ++ }; ++}; ++ + &mmc0 { + vmmc-supply = <®_cldo1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ +@@ -207,6 +246,7 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33-audio-tv-ephy-mac"; ++ regulator-enable-ramp-delay = <100000>; + }; + + /* ALDO3 is shorted to CLDO1 */ diff --git a/projects/Allwinner/devices/H6/patches/linux/0006-net-stmmac-sun8i-Fix-reboot-issue-with-ethernet-on-O.patch b/projects/Allwinner/devices/H6/patches/linux/0006-net-stmmac-sun8i-Fix-reboot-issue-with-ethernet-on-O.patch new file mode 100644 index 0000000000..45673784cb --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0006-net-stmmac-sun8i-Fix-reboot-issue-with-ethernet-on-O.patch @@ -0,0 +1,67 @@ +From e58355ab59c95b3ce708d3fdb417e3893170cfde Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:34:57 +0200 +Subject: [PATCH 06/14] net: stmmac: sun8i: Fix reboot issue with ethernet on + Orange Pi 3 + +We disable both phy regulators before reboot, so that they are in a +known state on the next boot. This should be done in u-boot, but +it doesn't support AXP806 yet, thus this workaround. + +Signed-off-by: Ondrej Jirman +--- + .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 22 +++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -80,6 +81,7 @@ struct sunxi_priv_data { + struct regmap_field *regmap_field; + bool internal_phy_powered; + void *mux_handle; ++ struct notifier_block reboot_nb; + }; + + /* EMAC clock register @ 0x30 in the "system control" address range */ +@@ -1130,6 +1132,19 @@ out_put_node: + return regmap; + } + ++ ++static int sun8i_dwmac_reboot_notifier(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ struct sunxi_priv_data *gmac = container_of(nb, struct sunxi_priv_data, ++ reboot_nb); ++ ++ regulator_disable(gmac->regulator_phy); ++ regulator_disable(gmac->regulator_phy_io); ++ ++ return NOTIFY_DONE; ++} ++ + static int sun8i_dwmac_probe(struct platform_device *pdev) + { + struct plat_stmmacenet_data *plat_dat; +@@ -1184,6 +1199,13 @@ static int sun8i_dwmac_probe(struct plat + return ret; + } + ++ gmac->reboot_nb.notifier_call = sun8i_dwmac_reboot_notifier; ++ ret = devm_register_reboot_notifier(dev, &gmac->reboot_nb); ++ if (ret) { ++ dev_err(dev, "Failed to register reboot notifier (%d)\n", ret); ++ return ret; ++ } ++ + /* The "GMAC clock control" register might be located in the + * CCU address range (on the R40), or the system control address + * range (on most other sun8i and later SoCs). diff --git a/projects/Allwinner/devices/H6/patches/linux/09-pineh64-enable-usb3.patch b/projects/Allwinner/devices/H6/patches/linux/0007-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch similarity index 71% rename from projects/Allwinner/devices/H6/patches/linux/09-pineh64-enable-usb3.patch rename to projects/Allwinner/devices/H6/patches/linux/0007-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch index ccf92c5c09..7bbe863e45 100644 --- a/projects/Allwinner/devices/H6/patches/linux/09-pineh64-enable-usb3.patch +++ b/projects/Allwinner/devices/H6/patches/linux/0007-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch @@ -1,7 +1,7 @@ -From b5554a30a6486e6e769130718d285902e6705bf8 Mon Sep 17 00:00:00 2001 +From df7cfa735a251371d3bbee07994fc5e8af55e508 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Mon, 25 Dec 2017 12:10:59 +0800 -Subject: [PATCH] arm64: allwinner: dts: h6: enable USB3 port on Pine H64 +Subject: [PATCH 07/14] arm64: allwinner: dts: h6: enable USB3 port on Pine H64 Pine H64 board have a USB3 port, which is connected to the USB3 pins of the H6 SoC, and the 5V power supply is controlled via GPIO (shared with @@ -15,11 +15,9 @@ Reviewed-by: Chen-Yu Tsai arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 9 +++++++++ 1 file changed, 9 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts -index f01fdf622756f..f2d04cfeec900 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts -@@ -71,6 +71,10 @@ +@@ -97,6 +97,10 @@ status = "okay"; }; @@ -30,7 +28,7 @@ index f01fdf622756f..f2d04cfeec900 100644 &emac { pinctrl-names = "default"; pinctrl-0 = <&ext_rgmii_pins>; -@@ -279,3 +283,8 @@ +@@ -331,3 +335,8 @@ usb3_vbus-supply = <®_usb_vbus>; status = "okay"; }; diff --git a/projects/Allwinner/devices/H6/patches/linux/12-ac200-nodes.patch b/projects/Allwinner/devices/H6/patches/linux/0008-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch similarity index 70% rename from projects/Allwinner/devices/H6/patches/linux/12-ac200-nodes.patch rename to projects/Allwinner/devices/H6/patches/linux/0008-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch index 8b8b5c4e4d..78d3f24a58 100644 --- a/projects/Allwinner/devices/H6/patches/linux/12-ac200-nodes.patch +++ b/projects/Allwinner/devices/H6/patches/linux/0008-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch @@ -1,18 +1,16 @@ -From fa11b2ef7b8359f70d010d3b76b7dfd90250dc5c Mon Sep 17 00:00:00 2001 +From 8d6daa429e4b4c97131b16a69cd34ab486b2c248 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Fri, 16 Aug 2019 16:40:20 +0200 -Subject: [PATCH] arm64: dts: allwinner: h6: Add AC200 EPHY related nodes +Subject: [PATCH 08/14] arm64: dts: allwinner: h6: Add AC200 EPHY related nodes Signed-off-by: Jernej Skrabec --- - arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 51 ++++++++++++++++++++ - 1 file changed, 51 insertions(+) + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 56 ++++++++++++++++++++ + 1 file changed, 56 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index 8eec8685a50b..5eeb7da7a0ab 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -17,6 +17,16 @@ +@@ -16,6 +16,16 @@ #address-cells = <1>; #size-cells = <1>; @@ -29,7 +27,7 @@ index 8eec8685a50b..5eeb7da7a0ab 100644 cpus { #address-cells = <1>; #size-cells = <0>; -@@ -218,6 +228,10 @@ +@@ -319,6 +329,10 @@ cpu_speed_grade: cpu-speed-grade@1c { reg = <0x1c 0x4>; }; @@ -40,19 +38,33 @@ index 8eec8685a50b..5eeb7da7a0ab 100644 }; watchdog: watchdog@30090a0 { -@@ -268,6 +284,11 @@ +@@ -363,6 +377,13 @@ drive-strength = <40>; }; ++ ext_rmii_pins: rmii_pins { ++ pins = "PA0", "PA1", "PA2", "PA3", "PA4", ++ "PA5", "PA6", "PA7", "PA8", "PA9"; ++ function = "emac"; ++ drive-strength = <40>; ++ }; ++ + hdmi_pins: hdmi-pins { + pins = "PH8", "PH9", "PH10"; + function = "hdmi"; +@@ -383,6 +404,11 @@ + function = "i2c2"; + }; + + i2c3_pins: i2c3-pins { + pins = "PB17", "PB18"; + function = "i2c3"; + }; + - hdmi_pins: hdmi-pins { - pins = "PH8", "PH9", "PH10"; - function = "hdmi"; -@@ -290,6 +311,11 @@ + mmc0_pins: mmc0-pins { + pins = "PF0", "PF1", "PF2", "PF3", + "PF4", "PF5"; +@@ -409,6 +435,11 @@ bias-pull-up; }; @@ -61,11 +73,11 @@ index 8eec8685a50b..5eeb7da7a0ab 100644 + function = "pwm1"; + }; + - mmc2_pins: mmc2-pins { - pins = "PC1", "PC4", "PC5", "PC6", - "PC7", "PC8", "PC9", "PC10", -@@ -408,6 +434,31 @@ - status = "disabled"; + /omit-if-no-ref/ + spi0_pins: spi0-pins { + pins = "PC0", "PC2", "PC3"; +@@ -639,6 +670,31 @@ + #size-cells = <0>; }; + i2c3: i2c@5002c00 { @@ -96,6 +108,3 @@ index 8eec8685a50b..5eeb7da7a0ab 100644 emac: ethernet@5020000 { compatible = "allwinner,sun50i-h6-emac", "allwinner,sun50i-a64-emac"; --- -2.22.1 - diff --git a/projects/Allwinner/devices/H6/patches/linux/0009-arm64-dts-allwinner-h6-tanix-tx6-enable-emmc.patch b/projects/Allwinner/devices/H6/patches/linux/0009-arm64-dts-allwinner-h6-tanix-tx6-enable-emmc.patch new file mode 100644 index 0000000000..8586dccd69 --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0009-arm64-dts-allwinner-h6-tanix-tx6-enable-emmc.patch @@ -0,0 +1,55 @@ +From b6b784bac19b9ee68b7f7ee5855216b76ac118cd Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 15 Jan 2020 18:39:17 +0100 +Subject: [PATCH 09/14] arm64: dts: allwinner: h6: tanix-tx6: enable emmc + +Tanix TX6 has 32 GiB eMMC. Add a node for it. + +Signed-off-by: Jernej Skrabec +--- + .../dts/allwinner/sun50i-h6-tanix-tx6.dts | 20 +++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts +@@ -32,6 +32,13 @@ + }; + }; + ++ reg_vcc1v8: vcc1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; +@@ -91,6 +98,15 @@ + status = "okay"; + }; + ++&mmc2 { ++ vmmc-supply = <®_vcc3v3>; ++ vqmmc-supply = <®_vcc1v8>; ++ non-removable; ++ cap-mmc-hw-reset; ++ bus-width = <8>; ++ status = "okay"; ++}; ++ + &ohci0 { + status = "okay"; + }; +@@ -99,6 +115,10 @@ + status = "okay"; + }; + ++&pio { ++ vcc-pc-supply = <®_vcc1v8>; ++}; ++ + &r_ir { + linux,rc-map-name = "rc-tanix-tx5max"; + status = "okay"; diff --git a/projects/Allwinner/devices/H6/patches/linux/0010-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch b/projects/Allwinner/devices/H6/patches/linux/0010-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch new file mode 100644 index 0000000000..56281eca89 --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0010-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch @@ -0,0 +1,75 @@ +From ff190627e3986569a2516f36e218adcde02fc78b Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 24 Aug 2019 01:03:05 +0200 +Subject: [PATCH 10/14] arm64: dts: allwinner: h6: tanix-tx6: enable ethernet + +Signed-off-by: Jernej Skrabec +--- + .../dts/allwinner/sun50i-h6-tanix-tx6.dts | 28 +++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts +@@ -13,6 +13,7 @@ + compatible = "oranth,tanix-tx6", "allwinner,sun50i-h6"; + + aliases { ++ ethernet0 = &emac; + serial0 = &uart0; + }; + +@@ -54,6 +55,10 @@ + }; + }; + ++&ac200_pwm_clk { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_vdd_cpu_gpu>; + }; +@@ -74,6 +79,14 @@ + status = "okay"; + }; + ++&emac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ext_rmii_pins>; ++ phy-mode = "rmii"; ++ phy-handle = <&ext_rmii_phy>; ++ status = "okay"; ++}; ++ + &gpu { + mali-supply = <®_vdd_cpu_gpu>; + status = "okay"; +@@ -89,6 +102,17 @@ + }; + }; + ++&i2c3 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ext_rmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ }; ++}; ++ + &mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; +@@ -119,6 +143,10 @@ + vcc-pc-supply = <®_vcc1v8>; + }; + ++&pwm { ++ status = "okay"; ++}; ++ + &r_ir { + linux,rc-map-name = "rc-tanix-tx5max"; + status = "okay"; diff --git a/projects/Allwinner/devices/H6/patches/linux/18-OrangePi-Lite2-support.patch b/projects/Allwinner/devices/H6/patches/linux/0011-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch similarity index 70% rename from projects/Allwinner/devices/H6/patches/linux/18-OrangePi-Lite2-support.patch rename to projects/Allwinner/devices/H6/patches/linux/0011-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch index e3e3c95a51..ae5f8fefbd 100644 --- a/projects/Allwinner/devices/H6/patches/linux/18-OrangePi-Lite2-support.patch +++ b/projects/Allwinner/devices/H6/patches/linux/0011-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch @@ -1,18 +1,16 @@ -From e087c727b23ed0665136973e24a0292c14522723 Mon Sep 17 00:00:00 2001 +From 483a90d0500c528b2faeed662c3209f779d43103 Mon Sep 17 00:00:00 2001 From: Sebastian Meyer Date: Mon, 3 Feb 2020 21:27:47 +0100 -Subject: [PATCH 4/4] arm64: allwinner: h6: Enable USB3 for OrangePi Lite2 +Subject: [PATCH 11/14] arm64: allwinner: h6: Enable USB3 for OrangePi Lite2 Signed-off-by: Sebastian Meyer --- .../allwinner/sun50i-h6-orangepi-lite2.dts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts -index e8770858b5d0..6ca46b1cabb9 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts -@@ -11,6 +11,16 @@ aliases { +@@ -11,6 +11,16 @@ serial1 = &uart1; /* BT-UART */ }; @@ -29,7 +27,7 @@ index e8770858b5d0..6ca46b1cabb9 100644 wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; clocks = <&rtc 1>; -@@ -20,6 +30,10 @@ wifi_pwrseq: wifi_pwrseq { +@@ -20,6 +30,10 @@ }; }; @@ -40,7 +38,7 @@ index e8770858b5d0..6ca46b1cabb9 100644 &mmc1 { vmmc-supply = <®_cldo2>; vqmmc-supply = <®_bldo3>; -@@ -72,3 +86,8 @@ bluetooth { +@@ -72,3 +86,8 @@ max-speed = <1500000>; }; }; @@ -49,6 +47,3 @@ index e8770858b5d0..6ca46b1cabb9 100644 + phy-supply = <®_usb_vbus>; + status = "okay"; +}; --- -2.26.0 - diff --git a/projects/Allwinner/devices/H6/patches/linux/20-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-disabling-DDR.patch b/projects/Allwinner/devices/H6/patches/linux/0012-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch similarity index 83% rename from projects/Allwinner/devices/H6/patches/linux/20-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-disabling-DDR.patch rename to projects/Allwinner/devices/H6/patches/linux/0012-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch index 101a9bd946..1e83ad44d2 100644 --- a/projects/Allwinner/devices/H6/patches/linux/20-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-disabling-DDR.patch +++ b/projects/Allwinner/devices/H6/patches/linux/0012-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch @@ -1,3 +1,12 @@ +From 4b723d23c444ae9dc85ecea51a1ae4de092ddf54 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= + +Date: Sun, 25 Aug 2019 17:05:58 +0200 +Subject: [PATCH 12/14] mmc: sunxi: fix unusuable eMMC on some H6 boards by + disabling DDR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Some Allwinner H6 boards have timing problems when dealing with DDR-capable eMMC cards. These boards include the Pine H64 and Tanix TX6. @@ -26,11 +35,9 @@ Signed-off-by: Alejandro González drivers/mmc/host/sunxi-mmc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) -diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c -index d577a6b0ceae..dac57d76d009 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c -@@ -1395,14 +1395,17 @@ static int sunxi_mmc_probe(struct platform_device *pdev) +@@ -1398,14 +1398,17 @@ static int sunxi_mmc_probe(struct platfo /* * Some H5 devices do not have signal traces precise enough to diff --git a/projects/Allwinner/devices/H6/patches/linux/0013-pineh64-model-b-bluetooth-wip.patch b/projects/Allwinner/devices/H6/patches/linux/0013-pineh64-model-b-bluetooth-wip.patch new file mode 100644 index 0000000000..d7a1748f8c --- /dev/null +++ b/projects/Allwinner/devices/H6/patches/linux/0013-pineh64-model-b-bluetooth-wip.patch @@ -0,0 +1,45 @@ +From 083e09f834e58cad72671e4df2136cf36c10aaa7 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 29 Oct 2020 21:04:24 +0100 +Subject: [PATCH 13/14] pineh64 model b - bluetooth wip + +Signed-off-by: Jernej Skrabec +--- + .../dts/allwinner/sun50i-h6-pine-h64-model-b.dts | 16 ++++++++++++++++ + drivers/bluetooth/hci_h5.c | 3 +++ + 2 files changed, 19 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts +@@ -34,3 +34,19 @@ + non-removable; + status = "okay"; + }; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "realtek,rtl8723bs-bt"; ++ device-wakeup-gpios = <&r_pio 1 2 GPIO_ACTIVE_HIGH>; /* PM2 */ ++ host-wakeup-gpios = <&r_pio 1 1 GPIO_ACTIVE_HIGH>; /* PM1 */ ++ enable-gpios = <&r_pio 1 4 GPIO_ACTIVE_HIGH>; /* PM4 */ ++ firmware-postfix = "OBDA8723"; ++ max-speed = <1500000>; ++ }; ++}; +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -820,6 +820,9 @@ static int h5_serdev_probe(struct serdev + if (!data) + return -ENODEV; + ++ of_property_read_string(dev->of_node, ++ "firmware-postfix", &h5->id); ++ + h5->vnd = (const struct h5_vnd *)data; + } + diff --git a/projects/Allwinner/devices/H6/patches/linux/22-opi3-crust-eth-workaround.patch b/projects/Allwinner/devices/H6/patches/linux/0014-hack-to-fix-sun8i_dwmac.patch similarity index 67% rename from projects/Allwinner/devices/H6/patches/linux/22-opi3-crust-eth-workaround.patch rename to projects/Allwinner/devices/H6/patches/linux/0014-hack-to-fix-sun8i_dwmac.patch index 0f41f0709c..52ffe5a219 100644 --- a/projects/Allwinner/devices/H6/patches/linux/22-opi3-crust-eth-workaround.patch +++ b/projects/Allwinner/devices/H6/patches/linux/0014-hack-to-fix-sun8i_dwmac.patch @@ -1,17 +1,15 @@ -From 8515bba5b33addcf87c4da5ab67cd7ffc052a87d Mon Sep 17 00:00:00 2001 +From 64954a507d442da5c2615897e6d35154c9c2f593 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 8 Dec 2020 19:48:39 -0600 -Subject: [PATCH] hack to fix sun8i_dwmac +Subject: [PATCH 14/14] hack to fix sun8i_dwmac --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -index d1a47145fe4e0..54f8ee992f560 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -1299,12 +1299,14 @@ static const struct of_device_id sun8i_dwmac_match[] = { +@@ -1310,12 +1310,14 @@ static const struct of_device_id sun8i_d }; MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); diff --git a/projects/Allwinner/devices/H6/patches/linux/05-sound-hack.patch b/projects/Allwinner/devices/H6/patches/linux/05-sound-hack.patch deleted file mode 100644 index a5654489a5..0000000000 --- a/projects/Allwinner/devices/H6/patches/linux/05-sound-hack.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 026ec1598d98a0bd45785a44a74ddb7063d2f776 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Tue, 22 Jan 2019 20:16:58 +0100 -Subject: [PATCH] AW H6 I2S WIP - -Signed-off-by: Jernej Skrabec ---- - arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 31 ++++++++++++++++++++ - 3 files changed, 41 insertions(+), 10 deletions(-) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index 62a0eae77639..f1c53aec6523 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -95,6 +95,23 @@ - (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; - }; - -+ sound_hdmi: sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "allwinner-hdmi"; -+ simple-audio-card,mclk-fs = <128>; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s1>; -+ dai-tdm-slot-num = <2>; -+ dai-tdm-slot-width = <32>; -+ }; -+ }; -+ - soc { - compatible = "simple-bus"; - #address-cells = <1>; -@@ -357,6 +374,19 @@ - }; - }; - -+ i2s1: i2s@5091000 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun50i-h6-i2s"; -+ reg = <0x05091000 0x1000>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>; -+ clock-names = "apb", "mod"; -+ dmas = <&dma 4>; -+ resets = <&ccu RST_BUS_I2S1>; -+ dma-names = "tx"; -+ allwinner,playback-channels = <8>; -+ }; -+ - usb2otg: usb@5100000 { - compatible = "allwinner,sun50i-h6-musb", - "allwinner,sun8i-a33-musb"; -@@ -440,6 +470,7 @@ - }; - - hdmi: hdmi@6000000 { -+ #sound-dai-cells = <0>; - compatible = "allwinner,sun50i-h6-dw-hdmi"; - reg = <0x06000000 0x10000>; - reg-io-width = <1>; --- -2.21.0 diff --git a/projects/Allwinner/devices/H6/patches/linux/07-opi3.patch b/projects/Allwinner/devices/H6/patches/linux/07-opi3.patch deleted file mode 100644 index 9bc168d747..0000000000 --- a/projects/Allwinner/devices/H6/patches/linux/07-opi3.patch +++ /dev/null @@ -1,442 +0,0 @@ -From 0b2bbc6708ef986e2f8d281f65e0c1ca3ff14562 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Wed, 27 Mar 2019 13:21:06 +0100 -Subject: [PATCH 1/5] net: stmmac: sun8i: Use devm_regulator_get for PHY - regulator - -Use devm_regulator_get instead of devm_regulator_get_optional and rely -on dummy supply. This avoids NULL checks before regulator_enable/disable -calls. - -This path also improves error reporting, because we now report both -use of dummy supply and error during registration with more detail, -instead of generic info level message "No regulator found" that -was reported previously on errors and lack of regulator property in DT. - -Finally, we'll be adding further optional regulators, and the overall -code will be simpler. - -Signed-off-by: Ondrej Jirman ---- - .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++----------- - 1 file changed, 10 insertions(+), 13 deletions(-) - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -index ddcc191febdb..906d46e2d166 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -528,12 +528,10 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) - struct sunxi_priv_data *gmac = priv; - int ret; - -- if (gmac->regulator) { -- ret = regulator_enable(gmac->regulator); -- if (ret) { -- dev_err(&pdev->dev, "Fail to enable regulator\n"); -- return ret; -- } -+ ret = regulator_enable(gmac->regulator); -+ if (ret) { -+ dev_err(&pdev->dev, "Fail to enable regulator\n"); -+ return ret; - } - - ret = clk_prepare_enable(gmac->tx_clk); -@@ -998,8 +996,7 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) - - clk_disable_unprepare(gmac->tx_clk); - -- if (gmac->regulator) -- regulator_disable(gmac->regulator); -+ regulator_disable(gmac->regulator); - } - - static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) -@@ -1135,12 +1132,12 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) - } - - /* Optional regulator for PHY */ -- gmac->regulator = devm_regulator_get_optional(dev, "phy"); -+ gmac->regulator = devm_regulator_get(dev, "phy"); - if (IS_ERR(gmac->regulator)) { -- if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) -- return -EPROBE_DEFER; -- dev_info(dev, "No regulator found\n"); -- gmac->regulator = NULL; -+ ret = PTR_ERR(gmac->regulator); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); -+ return ret; - } - - /* The "GMAC clock control" register might be located in the --- -2.24.0 - - -From 4335e41db5678cf2a766c19e4fa79ffa5e4dca81 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Tue, 20 Aug 2019 14:29:29 +0200 -Subject: [PATCH 2/5] net: stmmac: sun8i: Rename PHY regulator variable to - regulator_phy - -We'll be adding further optional regulators, and this makes it clearer -what the regulator is for. - -Signed-off-by: Ondrej Jirman ---- - .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 32 ++++++++++--------- - 1 file changed, 17 insertions(+), 15 deletions(-) - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -index 906d46e2d166..5d4ee99ca80e 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -57,19 +57,21 @@ struct emac_variant { - }; - - /* struct sunxi_priv_data - hold all sunxi private data -- * @tx_clk: reference to MAC TX clock -- * @ephy_clk: reference to the optional EPHY clock for the internal PHY -- * @regulator: reference to the optional regulator -- * @rst_ephy: reference to the optional EPHY reset for the internal PHY -- * @variant: reference to the current board variant -- * @regmap: regmap for using the syscon -- * @internal_phy_powered: Does the internal PHY is enabled -- * @mux_handle: Internal pointer used by mdio-mux lib -+ * @tx_clk: reference to MAC TX clock -+ * @ephy_clk: reference to the optional EPHY clock for -+ * the internal PHY -+ * @regulator_phy: reference to the optional regulator -+ * @rst_ephy: reference to the optional EPHY reset for -+ * the internal PHY -+ * @variant: reference to the current board variant -+ * @regmap: regmap for using the syscon -+ * @internal_phy_powered: Does the internal PHY is enabled -+ * @mux_handle: Internal pointer used by mdio-mux lib - */ - struct sunxi_priv_data { - struct clk *tx_clk; - struct clk *ephy_clk; -- struct regulator *regulator; -+ struct regulator *regulator_phy; - struct reset_control *rst_ephy; - const struct emac_variant *variant; - struct regmap_field *regmap_field; -@@ -528,9 +530,9 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) - struct sunxi_priv_data *gmac = priv; - int ret; - -- ret = regulator_enable(gmac->regulator); -+ ret = regulator_enable(gmac->regulator_phy); - if (ret) { -- dev_err(&pdev->dev, "Fail to enable regulator\n"); -+ dev_err(&pdev->dev, "Fail to enable PHY regulator\n"); - return ret; - } - -@@ -996,7 +998,7 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) - - clk_disable_unprepare(gmac->tx_clk); - -- regulator_disable(gmac->regulator); -+ regulator_disable(gmac->regulator_phy); - } - - static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) -@@ -1132,9 +1134,9 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) - } - - /* Optional regulator for PHY */ -- gmac->regulator = devm_regulator_get(dev, "phy"); -- if (IS_ERR(gmac->regulator)) { -- ret = PTR_ERR(gmac->regulator); -+ gmac->regulator_phy = devm_regulator_get(dev, "phy"); -+ if (IS_ERR(gmac->regulator_phy)) { -+ ret = PTR_ERR(gmac->regulator_phy); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); - return ret; --- -2.24.0 - - -From 5f2f079f8bec44f9a5d07767b12d3eb7ad247012 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Tue, 20 Aug 2019 14:31:38 +0200 -Subject: [PATCH 3/5] net: stmmac: sun8i: Add support for enabling a regulator - for PHY I/O pins - -Orange Pi 3 has two regulators that power the Realtek RTL8211E. According -to the phy datasheet, both regulators need to be enabled at the same time. - -Add support for the second optional regulator, "phy-io", to the glue -driver. - -Signed-off-by: Ondrej Jirman ---- - .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 30 ++++++++++++++++--- - 1 file changed, 26 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -index 5d4ee99ca80e..a7ffee494488 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -61,6 +61,8 @@ struct emac_variant { - * @ephy_clk: reference to the optional EPHY clock for - * the internal PHY - * @regulator_phy: reference to the optional regulator -+ * @regulator_phy_io: reference to the optional regulator for -+ * PHY I/O pins - * @rst_ephy: reference to the optional EPHY reset for - * the internal PHY - * @variant: reference to the current board variant -@@ -72,6 +74,7 @@ struct sunxi_priv_data { - struct clk *tx_clk; - struct clk *ephy_clk; - struct regulator *regulator_phy; -+ struct regulator *regulator_phy_io; - struct reset_control *rst_ephy; - const struct emac_variant *variant; - struct regmap_field *regmap_field; -@@ -530,21 +533,30 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) - struct sunxi_priv_data *gmac = priv; - int ret; - -+ ret = regulator_enable(gmac->regulator_phy_io); -+ if (ret) { -+ dev_err(&pdev->dev, "Fail to enable PHY I/O regulator\n"); -+ return ret; -+ } -+ - ret = regulator_enable(gmac->regulator_phy); - if (ret) { - dev_err(&pdev->dev, "Fail to enable PHY regulator\n"); -- return ret; -+ goto err_disable_regulator_phy_io; - } - - ret = clk_prepare_enable(gmac->tx_clk); - if (ret) { -- if (gmac->regulator) -- regulator_disable(gmac->regulator); - dev_err(&pdev->dev, "Could not enable AHB clock\n"); -- return ret; -+ goto err_disable_regulator_phy; - } - - return 0; -+err_disable_regulator_phy: -+ regulator_disable(gmac->regulator_phy); -+err_disable_regulator_phy_io: -+ regulator_disable(gmac->regulator_phy_io); -+ return ret; - } - - static void sun8i_dwmac_core_init(struct mac_device_info *hw, -@@ -999,6 +1011,7 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) - clk_disable_unprepare(gmac->tx_clk); - - regulator_disable(gmac->regulator_phy); -+ regulator_disable(gmac->regulator_phy_io); - } - - static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) -@@ -1142,6 +1155,15 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) - return ret; - } - -+ /* Optional regulator for PHY I/O pins */ -+ gmac->regulator_phy_io = devm_regulator_get(dev, "phy-io"); -+ if (IS_ERR(gmac->regulator_phy_io)) { -+ ret = PTR_ERR(gmac->regulator_phy_io); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get PHY I/O regulator (%d)\n", ret); -+ return ret; -+ } -+ - /* The "GMAC clock control" register might be located in the - * CCU address range (on the R40), or the system control address - * range (on most other sun8i and later SoCs). --- -2.24.0 - - -From 1bb9d9c95dc6fdb5cc7f9f39166274cd47365f9a Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Tue, 20 Aug 2019 14:54:48 +0200 -Subject: [PATCH 4/5] arm64: dts: allwinner: orange-pi-3: Enable ethernet - -Orange Pi 3 has two regulators that power the Realtek RTL8211E -PHY. According to the datasheet, both regulators need to be enabled -at the same time, or that "phy-io" should be enabled slightly earlier -than "phy" regulator. - -RTL8211E/RTL8211EG datasheet says: - - Note 4: 2.5V (or 1.8/1.5V) RGMII power should be risen simultaneously - or slightly earlier than 3.3V power. Rising 2.5V (or 1.8/1.5V) power - later than 3.3V power may lead to errors. - -The driver ensures the regulator enable ordering. The timing is set -in DT via startup-delay-us. - -We also need to wait at least 30ms after power-up/reset, before -accessing the PHY registers. - -All values of RX/TX delay were tested exhaustively and a middle one -of the range of working values was chosen. - -Signed-off-by: Ondrej Jirman ---- - .../dts/allwinner/sun50i-h6-orangepi-3.dts | 40 +++++++++++++++++++ - 1 file changed, 40 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts -index eb379cd402ac..b5dc419d92de 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts -@@ -15,6 +15,7 @@ / { - aliases { - serial0 = &uart0; - serial1 = &uart1; -+ ethernet0 = &emac; - }; - - chosen { -@@ -57,6 +58,15 @@ reg_vcc5v: vcc5v { - regulator-always-on; - }; - -+ reg_gmac_2v5: gmac-2v5 { -+ compatible = "regulator-fixed"; -+ regulator-name = "gmac-2v5"; -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ enable-active-high; -+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ -+ }; -+ - reg_vcc33_wifi: vcc33-wifi { - /* Always on 3.3V regulator for WiFi and BT */ - compatible = "regulator-fixed"; -@@ -112,6 +122,35 @@ hdmi_out_con: endpoint { - }; - }; - -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ext_rgmii_pins>; -+ phy-mode = "rgmii-txid"; -+ phy-handle = <&ext_rgmii_phy>; -+ /* -+ * The board uses 2.5V RGMII signalling. Power sequence to enable -+ * the phy is to enable GMAC-2V5 and GMAC-3V (aldo2) power rails -+ * at the same time and to wait 100ms. The driver enables phy-io -+ * first. Delay is achieved with enable-ramp-delay on reg_aldo2. -+ */ -+ phy-supply = <®_aldo2>; -+ phy-io-supply = <®_gmac_2v5>; -+ allwinner,rx-delay-ps = <1500>; -+ allwinner,tx-delay-ps = <700>; -+ status = "okay"; -+}; -+ -+&mdio { -+ ext_rgmii_phy: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ -+ reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ -+ reset-assert-us = <15000>; -+ reset-deassert-us = <40000>; -+ }; -+}; -+ - &mmc0 { - vmmc-supply = <®_cldo1>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ -@@ -182,6 +221,7 @@ reg_aldo2: aldo2 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc33-audio-tv-ephy-mac"; -+ regulator-enable-ramp-delay = <100000>; - }; - - /* ALDO3 is shorted to CLDO1 */ --- -2.24.0 - - -From e6700b102c319f31165de2361830c24f182f69b6 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Tue, 20 Aug 2019 14:34:57 +0200 -Subject: [PATCH 5/5] net: stmmac: sun8i: Fix reboot issue with ethernet on - Orange Pi 3 - -We disable both phy regulators before reboot, so that they are in a -known state on the next boot. This should be done in u-boot, but -it doesn't support AXP806 yet, thus this workaround. - -Signed-off-by: Ondrej Jirman ---- - .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 22 +++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -index a7ffee494488..f7c7d89da7f8 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -80,6 +81,7 @@ struct sunxi_priv_data { - struct regmap_field *regmap_field; - bool internal_phy_powered; - void *mux_handle; -+ struct notifier_block reboot_nb; - }; - - /* EMAC clock register @ 0x30 in the "system control" address range */ -@@ -1111,6 +1113,19 @@ static struct regmap *sun8i_dwmac_get_syscon_from_dev(struct device_node *node) - return regmap; - } - -+ -+static int sun8i_dwmac_reboot_notifier(struct notifier_block *nb, -+ unsigned long action, void *data) -+{ -+ struct sunxi_priv_data *gmac = container_of(nb, struct sunxi_priv_data, -+ reboot_nb); -+ -+ regulator_disable(gmac->regulator_phy); -+ regulator_disable(gmac->regulator_phy_io); -+ -+ return NOTIFY_DONE; -+} -+ - static int sun8i_dwmac_probe(struct platform_device *pdev) - { - struct plat_stmmacenet_data *plat_dat; -@@ -1164,6 +1179,13 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) - return ret; - } - -+ gmac->reboot_nb.notifier_call = sun8i_dwmac_reboot_notifier; -+ ret = devm_register_reboot_notifier(dev, &gmac->reboot_nb); -+ if (ret) { -+ dev_err(dev, "Failed to register reboot notifier (%d)\n", ret); -+ return ret; -+ } -+ - /* The "GMAC clock control" register might be located in the - * CCU address range (on the R40), or the system control address - * range (on most other sun8i and later SoCs). --- -2.24.0 - diff --git a/projects/Allwinner/devices/H6/patches/linux/13-Tanix-TX6.patch b/projects/Allwinner/devices/H6/patches/linux/13-Tanix-TX6.patch deleted file mode 100644 index a5ae658f3d..0000000000 --- a/projects/Allwinner/devices/H6/patches/linux/13-Tanix-TX6.patch +++ /dev/null @@ -1,159 +0,0 @@ -From e6cdedb22a9b012366d07276dace02c2c98fffc4 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Wed, 15 Jan 2020 18:39:17 +0100 -Subject: [PATCH 1/3] arm64: dts: allwinner: h6: tanix-tx6: enable emmc - -Tanix TX6 has 32 GiB eMMC. Add a node for it. - -Signed-off-by: Jernej Skrabec ---- - .../dts/allwinner/sun50i-h6-tanix-tx6.dts | 20 +++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts -index 83e6cb0e59ce..8cbf4e4a761e 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts -@@ -31,6 +31,13 @@ hdmi_con_in: endpoint { - }; - }; - -+ reg_vcc1v8: vcc1v8 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ - reg_vcc3v3: vcc3v3 { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3"; -@@ -78,6 +85,15 @@ &mmc0 { - status = "okay"; - }; - -+&mmc2 { -+ vmmc-supply = <®_vcc3v3>; -+ vqmmc-supply = <®_vcc1v8>; -+ non-removable; -+ cap-mmc-hw-reset; -+ bus-width = <8>; -+ status = "okay"; -+}; -+ - &ohci0 { - status = "okay"; - }; -@@ -86,6 +102,10 @@ &ohci3 { - status = "okay"; - }; - -+&pio { -+ vcc-pc-supply = <®_vcc1v8>; -+}; -+ - &r_ir { - linux,rc-map-name = "rc-tanix-tx5max"; - status = "okay"; --- -2.24.1 - -From cbf6129cdb69f006f66e22b854d5d544c940fd49 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 24 Aug 2019 01:03:05 +0200 -Subject: [PATCH] Tanix TX6 improvements - -Signed-off-by: Jernej Skrabec ---- - .../dts/allwinner/sun50i-h6-tanix-tx6.dts | 44 +++++++++++++++++++ - arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +++ - 2 files changed, 51 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts -index 7e7cb10e3d96..3de430b631f2 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts -@@ -14,6 +14,7 @@ - compatible = "oranth,tanix-tx6", "allwinner,sun50i-h6"; - - aliases { -+ ethernet0 = &emac; - serial0 = &uart0; - }; - -@@ -41,14 +42,26 @@ - }; - }; - -+&ac200_pwm_clk { -+ status = "okay"; -+}; -+ - &de { - status = "okay"; - }; - - &dwc3 { - status = "okay"; - }; - -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ext_rmii_pins>; -+ phy-mode = "rmii"; -+ phy-handle = <&ext_rmii_phy>; -+ status = "okay"; -+}; -+ - &ehci0 { - status = "okay"; - }; -@@ -63,6 +80,17 @@ - }; - }; - -+&i2c3 { -+ status = "okay"; -+}; -+ -+&mdio { -+ ext_rmii_phy: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ }; -+}; -+ - &mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins>; -@@ -80,6 +116,10 @@ - status = "okay"; - }; - -+&pwm { -+ status = "okay"; -+}; -+ - &r_ir { - status = "okay"; - }; -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index 67b732e34091..e436fc78ac71 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -251,6 +251,13 @@ - drive-strength = <40>; - }; - -+ ext_rmii_pins: rmii_pins { -+ pins = "PA0", "PA1", "PA2", "PA3", "PA4", -+ "PA5", "PA6", "PA7", "PA8", "PA9"; -+ function = "emac"; -+ drive-strength = <40>; -+ }; -+ - hdmi_pins: hdmi-pins { - pins = "PH8", "PH9", "PH10"; - function = "hdmi"; --- -2.23.0 diff --git a/projects/Allwinner/devices/H6/patches/linux/16-Add-frame-inversion-to-correct-multi-channel-audio.patch b/projects/Allwinner/devices/H6/patches/linux/16-Add-frame-inversion-to-correct-multi-channel-audio.patch deleted file mode 100644 index 18f7f63656..0000000000 --- a/projects/Allwinner/devices/H6/patches/linux/16-Add-frame-inversion-to-correct-multi-channel-audio.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 3e9d104275c44ab1711a3564ce67cabe850afe75 Mon Sep 17 00:00:00 2001 -From: Marcus Cooper -Date: Thu, 2 Jan 2020 19:07:29 +0100 -Subject: [PATCH] Add frame inversion to correct multi-channel audio - ---- - arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index 132ef9c2d348..43ed134b49f7 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -103,6 +103,7 @@ - simple-audio-card,format = "i2s"; - simple-audio-card,name = "allwinner-hdmi"; - simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,frame-inversion; - - simple-audio-card,codec { - sound-dai = <&hdmi>; --- -2.24.1 - diff --git a/projects/Allwinner/devices/H6/patches/linux/21-pineh64-model-b-wifi-bt.patch b/projects/Allwinner/devices/H6/patches/linux/21-pineh64-model-b-wifi-bt.patch deleted file mode 100644 index 410ddb647b..0000000000 --- a/projects/Allwinner/devices/H6/patches/linux/21-pineh64-model-b-wifi-bt.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 23fa74407f0c71e06e10cb55ca64722b97d924f0 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Thu, 29 Oct 2020 20:58:55 +0100 -Subject: [PATCH] arm64: dts: allwinner: h6: PineH64 model B: Add wifi - -PineH64 model B contains RTL8723CS wifi+bt combo module. - -Since bluetooth support is not yet squared away, only wifi is enabled -for now. - -Acked-by: Chen-Yu Tsai -Signed-off-by: Jernej Skrabec ---- - .../dts/allwinner/sun50i-h6-pine-h64-model-b.dts | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts -index f4c8966a6497..7fea1e4e2d49 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts -@@ -10,6 +10,12 @@ / { - compatible = "pine64,pine-h64-model-b", "allwinner,sun50i-h6"; - - /delete-node/ reg_gmac_3v3; -+ -+ wifi_pwrseq: wifi_pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ -+ post-power-on-delay-ms = <200>; -+ }; - }; - - &hdmi_connector { -@@ -19,3 +25,12 @@ &hdmi_connector { - &emac { - phy-supply = <®_aldo2>; - }; -+ -+&mmc1 { -+ vmmc-supply = <®_cldo3>; -+ vqmmc-supply = <®_aldo1>; -+ mmc-pwrseq = <&wifi_pwrseq>; -+ bus-width = <4>; -+ non-removable; -+ status = "okay"; -+}; --- -2.29.1 - -From 1f08c8dbef8c4f9590e1de0169e1d004a23ed721 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Thu, 29 Oct 2020 21:04:24 +0100 -Subject: [PATCH 2/2] pineh64 model b - bluetooth wip - -Signed-off-by: Jernej Skrabec ---- - .../dts/allwinner/sun50i-h6-pine-h64-model-b.dts | 16 ++++++++++++++++ - drivers/bluetooth/hci_h5.c | 3 +++ - 2 files changed, 19 insertions(+) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts -index 3f42b8b29b0f..99732e5850c2 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts -@@ -33,3 +33,19 @@ &mmc1 { - non-removable; - status = "okay"; - }; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; -+ uart-has-rtscts; -+ status = "okay"; -+ -+ bluetooth { -+ compatible = "realtek,rtl8723bs-bt"; -+ device-wakeup-gpios = <&r_pio 1 2 GPIO_ACTIVE_HIGH>; /* PM2 */ -+ host-wakeup-gpios = <&r_pio 1 1 GPIO_ACTIVE_HIGH>; /* PM1 */ -+ enable-gpios = <&r_pio 1 4 GPIO_ACTIVE_HIGH>; /* PM4 */ -+ firmware-postfix = "OBDA8723"; -+ max-speed = <1500000>; -+ }; -+}; -diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c -index a10d710fc3f1..c2fcb3429277 100644 ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -821,6 +821,9 @@ static int h5_serdev_probe(struct serdev_device *serdev) - if (!data) - return -ENODEV; - -+ of_property_read_string(dev->of_node, -+ "firmware-postfix", &h5->id); -+ - h5->vnd = (const struct h5_vnd *)data; - } - --- -2.29.1 - diff --git a/projects/Allwinner/devices/R40/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf b/projects/Allwinner/devices/R40/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf deleted file mode 100644 index 1331fd6ad4..0000000000 --- a/projects/Allwinner/devices/R40/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf +++ /dev/null @@ -1,36 +0,0 @@ -# -# Configuration for H3 analog output -# - - - -H3_Audio_Codec.pcm.front.0 { - @args [ CARD ] - @args.CARD { - type string - } - type hooks - slave.pcm { - type hw - card $CARD - } - hooks.0 { - type ctl_elems - hook_args [ - { - name "Line Out Playback Volume" - lock true - preserve true - optional false - value 31 - } - { - name "Line Out Playback Switch" - lock true - preserve true - optional false - value [ on on ] - } - ] - } -} diff --git a/projects/Allwinner/devices/R40/patches/linux/0001-ARM-dts-sun8i-r40-Add-timer-node.patch b/projects/Allwinner/devices/R40/patches/linux/0001-ARM-dts-sun8i-r40-Add-timer-node.patch new file mode 100644 index 0000000000..58fd3e7398 --- /dev/null +++ b/projects/Allwinner/devices/R40/patches/linux/0001-ARM-dts-sun8i-r40-Add-timer-node.patch @@ -0,0 +1,35 @@ +From 8e2b67acc77a0c7704b2001dd4bf8646f286e4be Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 13:09:00 +0100 +Subject: [PATCH] ARM: dts: sun8i: r40: Add timer node + +Allwinner R40 has a timer. + +Add a node for it. + +Signed-off-by: Jernej Skrabec +--- + arch/arm/boot/dts/sun8i-r40.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm/boot/dts/sun8i-r40.dtsi ++++ b/arch/arm/boot/dts/sun8i-r40.dtsi +@@ -647,6 +647,18 @@ + }; + }; + ++ timer@1c20c00 { ++ compatible = "allwinner,sun4i-a10-timer"; ++ reg = <0x01c20c00 0x90>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&osc24M>; ++ }; ++ + wdt: watchdog@1c20c90 { + compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; diff --git a/projects/Allwinner/devices/R40/patches/linux/0002-bpi-m2u-analog-codec.patch b/projects/Allwinner/devices/R40/patches/linux/0002-bpi-m2u-analog-codec.patch new file mode 100644 index 0000000000..7b19556c09 --- /dev/null +++ b/projects/Allwinner/devices/R40/patches/linux/0002-bpi-m2u-analog-codec.patch @@ -0,0 +1,57 @@ +From 958ad802878443a2f5f06f5f3c796d163fd03ca9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Mon, 24 Aug 2020 16:35:54 +0200 +Subject: [PATCH 16/17] dts: enable analog codec + +Signed-off-by: Jernej Skrabec +--- + .../boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 9 ++++ + arch/arm/boot/dts/sun8i-r40.dtsi | 42 +++++++++++++++++++ + 2 files changed, 51 insertions(+) + +--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts ++++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts +@@ -113,6 +113,15 @@ + status = "okay"; + }; + ++&codec { ++ allwinner,audio-routing = ++ "Headphone", "HP", ++ "Headphone", "HPCOM", ++ "MIC1", "Mic", ++ "Mic", "MBIAS"; ++ status = "okay"; ++}; ++ + &de { + status = "okay"; + }; +--- a/arch/arm/boot/dts/sun8i-r40.dtsi ++++ b/arch/arm/boot/dts/sun8i-r40.dtsi +@@ -692,6 +692,25 @@ + status = "disabled"; + }; + ++ codec: codec@01c22c00 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun8i-h3-codec"; ++ reg = <0x01c22c00 0x300>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_CODEC>; ++ clock-names = "apb", "codec"; ++ resets = <&ccu RST_BUS_CODEC>; ++ dmas = <&dma 19>, <&dma 19>; ++ dma-names = "rx", "tx"; ++ allwinner,codec-analog-controls = <&codec_analog>; ++ status = "disabled"; ++ }; ++ ++ codec_analog: codec-analog@01c22f00 { ++ compatible = "allwinner,sun8i-a23-codec-analog"; ++ reg = <0x01c22f00 0x4>; ++ }; ++ + ths: thermal-sensor@1c24c00 { + compatible = "allwinner,sun8i-r40-ths"; + reg = <0x01c24c00 0x100>; diff --git a/projects/Allwinner/devices/R40/patches/linux/0017-r40-hdmi-audio-wip.patch b/projects/Allwinner/devices/R40/patches/linux/0003-r40-hdmi-audio-wip.patch similarity index 85% rename from projects/Allwinner/devices/R40/patches/linux/0017-r40-hdmi-audio-wip.patch rename to projects/Allwinner/devices/R40/patches/linux/0003-r40-hdmi-audio-wip.patch index 281d52669e..76fcb9d50d 100644 --- a/projects/Allwinner/devices/R40/patches/linux/0017-r40-hdmi-audio-wip.patch +++ b/projects/Allwinner/devices/R40/patches/linux/0003-r40-hdmi-audio-wip.patch @@ -8,11 +8,9 @@ Signed-off-by: Jernej Skrabec arch/arm/boot/dts/sun8i-r40.dtsi | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) -diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi -index 6dc075de94ae..bd8f4495ad7a 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi -@@ -111,6 +111,24 @@ de: display-engine { +@@ -111,6 +111,24 @@ status = "disabled"; }; @@ -37,7 +35,7 @@ index 6dc075de94ae..bd8f4495ad7a 100644 thermal-zones { cpu_thermal: cpu0-thermal { /* milliseconds */ -@@ -647,6 +665,19 @@ wdt: watchdog@1c20c90 { +@@ -666,6 +684,19 @@ clocks = <&osc24M>; }; @@ -57,7 +55,7 @@ index 6dc075de94ae..bd8f4495ad7a 100644 ir0: ir@1c21800 { compatible = "allwinner,sun8i-r40-ir", "allwinner,sun6i-a31-ir"; -@@ -1134,6 +1165,7 @@ gic: interrupt-controller@1c81000 { +@@ -1142,6 +1173,7 @@ }; hdmi: hdmi@1ee0000 { @@ -65,6 +63,3 @@ index 6dc075de94ae..bd8f4495ad7a 100644 compatible = "allwinner,sun8i-r40-dw-hdmi", "allwinner,sun8i-a83t-dw-hdmi"; reg = <0x01ee0000 0x10000>; --- -2.28.0 - diff --git a/projects/Allwinner/devices/R40/patches/linux/0015-clk-r40-initialize-clocks-earlier.patch b/projects/Allwinner/devices/R40/patches/linux/0015-clk-r40-initialize-clocks-earlier.patch deleted file mode 100644 index b6ee5a403d..0000000000 --- a/projects/Allwinner/devices/R40/patches/linux/0015-clk-r40-initialize-clocks-earlier.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 7ace610aa8c87a4854c974299f880f168a8b075d Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Mon, 24 Aug 2020 16:35:00 +0200 -Subject: [PATCH 15/17] clk: r40: initialize clocks earlier - -Signed-off-by: Jernej Skrabec ---- - drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 63 +++++++++++++++++----------- - 1 file changed, 38 insertions(+), 25 deletions(-) - -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c -index 84153418453f..5c82fed4b4b9 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c -@@ -5,6 +5,7 @@ - - #include - #include -+#include - #include - #include - -@@ -1310,14 +1311,46 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) - struct resource *res; - struct regmap *regmap; - void __iomem *reg; -- u32 val; -- int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(reg)) - return PTR_ERR(reg); - -+ regmap = devm_regmap_init_mmio(&pdev->dev, reg, -+ &sun8i_r40_ccu_regmap_config); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ return 0; -+} -+ -+static const struct of_device_id sun8i_r40_ccu_ids[] = { -+ { .compatible = "allwinner,sun8i-r40-ccu" }, -+ { } -+}; -+ -+static struct platform_driver sun8i_r40_ccu_driver = { -+ .probe = sun8i_r40_ccu_probe, -+ .driver = { -+ .name = "sun8i-r40-ccu", -+ .of_match_table = sun8i_r40_ccu_ids, -+ }, -+}; -+builtin_platform_driver(sun8i_r40_ccu_driver); -+ -+static void __init sun8i_r40_ccu_setup(struct device_node *node) -+{ -+ void __iomem *reg; -+ u32 val; -+ int ret; -+ -+ reg = of_iomap(node, 0); -+ if (IS_ERR(reg)) { -+ pr_err("%pOF: Could not map the clock registers\n", node); -+ return; -+ } -+ - /* Force the PLL-Audio-1x divider to 1 */ - val = readl(reg + SUN8I_R40_PLL_AUDIO_REG); - val &= ~GENMASK(19, 16); -@@ -1341,14 +1374,7 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) - writel(SUN8I_R40_SYS_32K_CLK_KEY | BIT(8), - reg + SUN8I_R40_SYS_32K_CLK_REG); - -- regmap = devm_regmap_init_mmio(&pdev->dev, reg, -- &sun8i_r40_ccu_regmap_config); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc); -- if (ret) -- return ret; -+ sunxi_ccu_probe(node, reg, &sun8i_r40_ccu_desc); - - /* Gate then ungate PLL CPU after any rate changes */ - ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb); -@@ -1357,19 +1383,6 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) - ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, - &sun8i_r40_cpu_nb); - -- return 0; - } -- --static const struct of_device_id sun8i_r40_ccu_ids[] = { -- { .compatible = "allwinner,sun8i-r40-ccu" }, -- { } --}; -- --static struct platform_driver sun8i_r40_ccu_driver = { -- .probe = sun8i_r40_ccu_probe, -- .driver = { -- .name = "sun8i-r40-ccu", -- .of_match_table = sun8i_r40_ccu_ids, -- }, --}; --builtin_platform_driver(sun8i_r40_ccu_driver); -+CLK_OF_DECLARE_DRIVER(sun8i_r40_ccu, "allwinner,sun8i-r40-ccu", -+ sun8i_r40_ccu_setup); --- -2.28.0 - diff --git a/projects/Allwinner/devices/R40/patches/linux/0016-dts-enable-various-devices.patch b/projects/Allwinner/devices/R40/patches/linux/0016-dts-enable-various-devices.patch deleted file mode 100644 index a35c2ba201..0000000000 --- a/projects/Allwinner/devices/R40/patches/linux/0016-dts-enable-various-devices.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 958ad802878443a2f5f06f5f3c796d163fd03ca9 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Mon, 24 Aug 2020 16:35:54 +0200 -Subject: [PATCH 16/17] dts: enable various devices - -Signed-off-by: Jernej Skrabec ---- - .../boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 9 ++++ - arch/arm/boot/dts/sun8i-r40.dtsi | 42 +++++++++++++++++++ - 2 files changed, 51 insertions(+) - -diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts -index 2fc62ef0cb3e..dc673826109f 100644 ---- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts -+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts -@@ -113,6 +113,15 @@ &ahci { - status = "okay"; - }; - -+&codec { -+ allwinner,audio-routing = -+ "Headphone", "HP", -+ "Headphone", "HPCOM", -+ "MIC1", "Mic", -+ "Mic", "MBIAS"; -+ status = "okay"; -+}; -+ - &de { - status = "okay"; - }; -diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi -index 7907569e7b5c..6dc075de94ae 100644 ---- a/arch/arm/boot/dts/sun8i-r40.dtsi -+++ b/arch/arm/boot/dts/sun8i-r40.dtsi -@@ -628,6 +628,18 @@ uart3_rts_cts_pg_pins: uart3-rts-cts-pg-pins { - }; - }; - -+ timer@1c20c00 { -+ compatible = "allwinner,sun4i-a10-timer"; -+ reg = <0x01c20c00 0x90>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ ; -+ clocks = <&osc24M>; -+ }; -+ - wdt: watchdog@1c20c90 { - compatible = "allwinner,sun4i-a10-wdt"; - reg = <0x01c20c90 0x10>; -@@ -661,6 +673,25 @@ ir1: ir@1c21c00 { - status = "disabled"; - }; - -+ codec: codec@01c22c00 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun8i-h3-codec"; -+ reg = <0x01c22c00 0x300>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_CODEC>; -+ clock-names = "apb", "codec"; -+ resets = <&ccu RST_BUS_CODEC>; -+ dmas = <&dma 19>, <&dma 19>; -+ dma-names = "rx", "tx"; -+ allwinner,codec-analog-controls = <&codec_analog>; -+ status = "disabled"; -+ }; -+ -+ codec_analog: codec-analog@01c22f00 { -+ compatible = "allwinner,sun8i-a23-codec-analog"; -+ reg = <0x01c22f00 0x4>; -+ }; -+ - ths: thermal-sensor@1c24c00 { - compatible = "allwinner,sun8i-r40-ths"; - reg = <0x01c24c00 0x100>; -@@ -866,6 +897,17 @@ gmac_mdio: mdio { - }; - }; - -+ hstimer@1c60000 { -+ compatible = "allwinner,sun7i-a20-hstimer"; -+ reg = <0x01c60000 0x1000>; -+ interrupts = , -+ , -+ , -+ ; -+ clocks = <&ccu CLK_BUS_HSTIMER>; -+ resets = <&ccu RST_BUS_HSTIMER>; -+ }; -+ - mbus: dram-controller@1c62000 { - compatible = "allwinner,sun8i-r40-mbus"; - reg = <0x01c62000 0x1000>; --- -2.28.0 - diff --git a/projects/Allwinner/devices/H3/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf b/projects/Allwinner/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf similarity index 100% rename from projects/Allwinner/devices/H3/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf rename to projects/Allwinner/filesystem/usr/share/alsa/cards/H3_Audio_Codec.conf diff --git a/projects/Allwinner/devices/A64/filesystem/usr/share/alsa/cards/sun50i-a64-audi.conf b/projects/Allwinner/filesystem/usr/share/alsa/cards/sun50i-a64-audi.conf similarity index 100% rename from projects/Allwinner/devices/A64/filesystem/usr/share/alsa/cards/sun50i-a64-audi.conf rename to projects/Allwinner/filesystem/usr/share/alsa/cards/sun50i-a64-audi.conf diff --git a/projects/Allwinner/linux/linux.aarch64.conf b/projects/Allwinner/linux/linux.aarch64.conf index aa77b96ca7..5367813bd6 100644 --- a/projects/Allwinner/linux/linux.aarch64.conf +++ b/projects/Allwinner/linux/linux.aarch64.conf @@ -3686,7 +3686,6 @@ CONFIG_DRM_SUN4I=y # CONFIG_DRM_SUN4I_BACKEND is not set # CONFIG_DRM_SUN6I_DSI is not set CONFIG_DRM_SUN8I_DW_HDMI=y -CONFIG_DRM_SUN8I_DW_HDMI_CEC=y CONFIG_DRM_SUN8I_MIXER=y CONFIG_DRM_SUN8I_TCON_TOP=y CONFIG_DRM_PANEL=y diff --git a/projects/Allwinner/linux/linux.arm.conf b/projects/Allwinner/linux/linux.arm.conf index 5a244c1c83..a03a6eb784 100644 --- a/projects/Allwinner/linux/linux.arm.conf +++ b/projects/Allwinner/linux/linux.arm.conf @@ -3613,7 +3613,6 @@ CONFIG_DRM_SUN4I_HDMI_CEC=y CONFIG_DRM_SUN4I_BACKEND=y CONFIG_DRM_SUN6I_DSI=y CONFIG_DRM_SUN8I_DW_HDMI=y -CONFIG_DRM_SUN8I_DW_HDMI_CEC=y CONFIG_DRM_SUN8I_MIXER=y CONFIG_DRM_SUN8I_TCON_TOP=y # CONFIG_DRM_OMAP is not set diff --git a/projects/Allwinner/patches/linux/0001-backport-from-5.11.patch b/projects/Allwinner/patches/linux/0001-media-cedrus-Add-support-for-R40.patch similarity index 70% rename from projects/Allwinner/patches/linux/0001-backport-from-5.11.patch rename to projects/Allwinner/patches/linux/0001-media-cedrus-Add-support-for-R40.patch index 49bb7c2a9c..37665933e4 100644 --- a/projects/Allwinner/patches/linux/0001-backport-from-5.11.patch +++ b/projects/Allwinner/patches/linux/0001-media-cedrus-Add-support-for-R40.patch @@ -1,7 +1,7 @@ -From 343bbfd1652964fb52520c4cc232c5a2c679cb21 Mon Sep 17 00:00:00 2001 +From 9a7e6c2d8a18a24b013c1ad165ed04bb7d2c7716 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 25 Aug 2020 19:35:22 +0200 -Subject: [PATCH] media: cedrus: Add support for R40 +Subject: [PATCH 01/44] media: cedrus: Add support for R40 Video engine in R40 is very similar to that in A33 but it runs on lower speed, at least according to OS images released by board designer. @@ -13,11 +13,9 @@ Link: https://lore.kernel.org/r/20200825173523.1289379-5-jernej.skrabec@siol.net drivers/staging/media/sunxi/cedrus/cedrus.c | 9 +++++++++ 1 file changed, 9 insertions(+) -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index bc27f9430eeb..83a654a618be 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -496,6 +496,11 @@ static const struct cedrus_variant sun8i_h3_cedrus_variant = { +@@ -508,6 +508,11 @@ static const struct cedrus_variant sun8i .mod_rate = 402000000, }; @@ -29,17 +27,14 @@ index bc27f9430eeb..83a654a618be 100644 static const struct cedrus_variant sun50i_a64_cedrus_variant = { .capabilities = CEDRUS_CAPABILITY_UNTILED | CEDRUS_CAPABILITY_H265_DEC, -@@ -536,6 +541,10 @@ static const struct of_device_id cedrus_dt_match[] = { - .compatible = "allwinner,sun8i-h3-video-engine", +@@ -549,6 +554,10 @@ static const struct of_device_id cedrus_ .data = &sun8i_h3_cedrus_variant, }, -+ { + { + .compatible = "allwinner,sun8i-r40-video-engine", + .data = &sun8i_r40_cedrus_variant, + }, - { ++ { .compatible = "allwinner,sun50i-a64-video-engine", .data = &sun50i_a64_cedrus_variant, --- -2.28.0 - + }, diff --git a/projects/Allwinner/patches/linux/0008-media-sunxi-cir-allow-timeout-to-be-set-at-runtime.patch b/projects/Allwinner/patches/linux/0002-media-sunxi-cir-allow-timeout-to-be-set-at-runtime.patch similarity index 86% rename from projects/Allwinner/patches/linux/0008-media-sunxi-cir-allow-timeout-to-be-set-at-runtime.patch rename to projects/Allwinner/patches/linux/0002-media-sunxi-cir-allow-timeout-to-be-set-at-runtime.patch index c161c9a81c..602c26a462 100644 --- a/projects/Allwinner/patches/linux/0008-media-sunxi-cir-allow-timeout-to-be-set-at-runtime.patch +++ b/projects/Allwinner/patches/linux/0002-media-sunxi-cir-allow-timeout-to-be-set-at-runtime.patch @@ -1,7 +1,7 @@ -From 371443de3c991f7b025d5203754a3497b7ea7c32 Mon Sep 17 00:00:00 2001 +From f710d6403b7716d7a5319e51c4cb3c217ec85b73 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 10 Nov 2020 09:30:38 +0100 -Subject: [PATCH] media: sunxi-cir: allow timeout to be set at runtime +Subject: [PATCH 02/44] media: sunxi-cir: allow timeout to be set at runtime This allows the timeout to be set with the LIRC_SET_REC_TIMEOUT ioctl. @@ -18,8 +18,6 @@ Signed-off-by: Mauro Carvalho Chehab drivers/media/rc/sunxi-cir.c | 48 ++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 8 deletions(-) -diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c -index 4afc5895bee7..8555c7798706 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -73,10 +73,6 @@ @@ -33,7 +31,7 @@ index 4afc5895bee7..8555c7798706 100644 /** * struct sunxi_ir_quirks - Differences between SoC variants. -@@ -146,6 +142,41 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) +@@ -146,6 +142,41 @@ static irqreturn_t sunxi_ir_irq(int irqn return IRQ_HANDLED; } @@ -75,7 +73,7 @@ index 4afc5895bee7..8555c7798706 100644 static int sunxi_ir_probe(struct platform_device *pdev) { int ret = 0; -@@ -242,9 +273,11 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -242,9 +273,11 @@ static int sunxi_ir_probe(struct platfor ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY; ir->rc->dev.parent = dev; ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; @@ -89,7 +87,7 @@ index 4afc5895bee7..8555c7798706 100644 ir->rc->driver_name = SUNXI_IR_DEV; ret = rc_register_device(ir->rc); -@@ -272,8 +305,7 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -272,8 +305,7 @@ static int sunxi_ir_probe(struct platfor writel(REG_CTL_MD, ir->base+SUNXI_IR_CTL_REG); /* Set noise threshold and idle threshold */ @@ -99,6 +97,3 @@ index 4afc5895bee7..8555c7798706 100644 /* Invert Input Signal */ writel(REG_RXCTL_RPPI, ir->base + SUNXI_IR_RXCTL_REG); --- -2.30.0 - diff --git a/projects/Allwinner/patches/linux/0003-ASoC-sun4i-i2s-Change-set_chan_cfg-params.patch b/projects/Allwinner/patches/linux/0003-ASoC-sun4i-i2s-Change-set_chan_cfg-params.patch new file mode 100644 index 0000000000..5cb7c89a06 --- /dev/null +++ b/projects/Allwinner/patches/linux/0003-ASoC-sun4i-i2s-Change-set_chan_cfg-params.patch @@ -0,0 +1,118 @@ +From a8bdfe3893f9b226492dac4b4e0d37a27dbee201 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 30 Oct 2020 15:46:35 +0100 +Subject: [PATCH 03/44] ASoC: sun4i-i2s: Change set_chan_cfg() params +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As slots and slot_width can be set manually using set_tdm(). +These values are then kept in sun4i_i2s struct. +So we need to check if these values are set or not. + +This is not done actually and will trigger a bug. +For example, if we set to the simple soundcard in the device-tree +dai-tdm-slot-width = <32> and then start a stream using S16_LE, +currently we would calculate BCLK for 32-bit slots, but program +lrck_period for 16-bit slots, making the sample rate double what we +expected. + +To fix this, we need to check if these values are set or not but as +this logic is already done by the caller. Avoid duplicating this +logic and just pass the required values as params to set_chan_cfg(). + +Suggested-by: Samuel Holland +Acked-by: Maxime Ripard +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-3-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -162,8 +162,15 @@ struct sun4i_i2s_quirks { + unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *); + s8 (*get_sr)(const struct sun4i_i2s *, int); + s8 (*get_wss)(const struct sun4i_i2s *, int); +- int (*set_chan_cfg)(const struct sun4i_i2s *, +- const struct snd_pcm_hw_params *); ++ ++ /* ++ * In the set_chan_cfg() function pointer: ++ * @slots: channels per frame + padding slots, regardless of format ++ * @slot_width: bits per sample + padding bits, regardless of format ++ */ ++ int (*set_chan_cfg)(const struct sun4i_i2s *i2s, ++ unsigned int channels, unsigned int slots, ++ unsigned int slot_width); + int (*set_fmt)(const struct sun4i_i2s *, unsigned int); + }; + +@@ -399,10 +406,9 @@ static s8 sun8i_i2s_get_sr_wss(const str + } + + static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, +- const struct snd_pcm_hw_params *params) ++ unsigned int channels, unsigned int slots, ++ unsigned int slot_width) + { +- unsigned int channels = params_channels(params); +- + /* Map the channels for playback and capture */ + regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210); + regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210); +@@ -419,15 +425,11 @@ static int sun4i_i2s_set_chan_cfg(const + } + + static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, +- const struct snd_pcm_hw_params *params) ++ unsigned int channels, unsigned int slots, ++ unsigned int slot_width) + { +- unsigned int channels = params_channels(params); +- unsigned int slots = channels; + unsigned int lrck_period; + +- if (i2s->slots) +- slots = i2s->slots; +- + /* Map the channels for playback and capture */ + regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210); + regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210); +@@ -450,13 +452,13 @@ static int sun8i_i2s_set_chan_cfg(const + switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: +- lrck_period = params_physical_width(params) * slots; ++ lrck_period = slot_width * slots; + break; + + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_I2S: +- lrck_period = params_physical_width(params); ++ lrck_period = slot_width; + break; + + default: +@@ -482,7 +484,9 @@ static int sun4i_i2s_hw_params(struct sn + unsigned int word_size = params_width(params); + unsigned int slot_width = params_physical_width(params); + unsigned int channels = params_channels(params); ++ + unsigned int slots = channels; ++ + int ret, sr, wss; + u32 width; + +@@ -492,7 +496,7 @@ static int sun4i_i2s_hw_params(struct sn + if (i2s->slot_width) + slot_width = i2s->slot_width; + +- ret = i2s->variant->set_chan_cfg(i2s, params); ++ ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width); + if (ret < 0) { + dev_err(dai->dev, "Invalid channel configuration\n"); + return ret; diff --git a/projects/Allwinner/patches/linux/0004-ASoC-sun4i-i2s-Add-support-for-H6-I2S.patch b/projects/Allwinner/patches/linux/0004-ASoC-sun4i-i2s-Add-support-for-H6-I2S.patch new file mode 100644 index 0000000000..a1c67052ce --- /dev/null +++ b/projects/Allwinner/patches/linux/0004-ASoC-sun4i-i2s-Add-support-for-H6-I2S.patch @@ -0,0 +1,295 @@ +From 8ff0df5dffe58a2d1595a6e59ccd5ce63d6bf0e5 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 30 Oct 2020 15:46:36 +0100 +Subject: [PATCH 04/44] ASoC: sun4i-i2s: Add support for H6 I2S +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +H6 I2S is very similar to that in H3, except it supports up to 16 +channels. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Marcus Cooper +Reviewed-by: Chen-Yu Tsai +Acked-by: Maxime Ripard +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-4-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 222 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 222 insertions(+) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -124,6 +124,21 @@ + #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 + #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 + ++/* Defines required for sun50i-h6 support */ ++#define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK GENMASK(21, 20) ++#define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset) ((offset) << 20) ++#define SUN50I_H6_I2S_TX_CHAN_SEL_MASK GENMASK(19, 16) ++#define SUN50I_H6_I2S_TX_CHAN_SEL(chan) ((chan - 1) << 16) ++#define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) ++#define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1)) ++ ++#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 ++#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 ++ ++#define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 ++#define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 ++#define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6C ++ + struct sun4i_i2s; + + /** +@@ -476,6 +491,60 @@ static int sun8i_i2s_set_chan_cfg(const + return 0; + } + ++static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, ++ unsigned int channels, unsigned int slots, ++ unsigned int slot_width) ++{ ++ unsigned int lrck_period; ++ ++ /* Map the channels for playback and capture */ ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); ++ ++ /* Configure the channels */ ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, ++ SUN50I_H6_I2S_TX_CHAN_SEL_MASK, ++ SUN50I_H6_I2S_TX_CHAN_SEL(channels)); ++ regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, ++ SUN50I_H6_I2S_TX_CHAN_SEL_MASK, ++ SUN50I_H6_I2S_TX_CHAN_SEL(channels)); ++ ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, ++ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, ++ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, ++ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, ++ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); ++ ++ switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_DSP_A: ++ case SND_SOC_DAIFMT_DSP_B: ++ lrck_period = slot_width * slots; ++ break; ++ ++ case SND_SOC_DAIFMT_LEFT_J: ++ case SND_SOC_DAIFMT_RIGHT_J: ++ case SND_SOC_DAIFMT_I2S: ++ lrck_period = slot_width; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, ++ SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, ++ SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); ++ ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, ++ SUN50I_H6_I2S_TX_CHAN_EN_MASK, ++ SUN50I_H6_I2S_TX_CHAN_EN(channels)); ++ ++ return 0; ++} ++ + static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +@@ -703,6 +772,108 @@ static int sun8i_i2s_set_soc_fmt(const s + return 0; + } + ++static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, ++ unsigned int fmt) ++{ ++ u32 mode, val; ++ u8 offset; ++ ++ /* ++ * DAI clock polarity ++ * ++ * The setup for LRCK contradicts the datasheet, but under a ++ * scope it's clear that the LRCK polarity is reversed ++ * compared to the expected polarity on the bus. ++ */ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_IB_IF: ++ /* Invert both clocks */ ++ val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ /* Invert bit clock */ ++ val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED | ++ SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ /* Invert frame clock */ ++ val = 0; ++ break; ++ case SND_SOC_DAIFMT_NB_NF: ++ val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, ++ SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | ++ SUN8I_I2S_FMT0_BCLK_POLARITY_MASK, ++ val); ++ ++ /* DAI Mode */ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_DSP_A: ++ mode = SUN8I_I2S_CTRL_MODE_PCM; ++ offset = 1; ++ break; ++ ++ case SND_SOC_DAIFMT_DSP_B: ++ mode = SUN8I_I2S_CTRL_MODE_PCM; ++ offset = 0; ++ break; ++ ++ case SND_SOC_DAIFMT_I2S: ++ mode = SUN8I_I2S_CTRL_MODE_LEFT; ++ offset = 1; ++ break; ++ ++ case SND_SOC_DAIFMT_LEFT_J: ++ mode = SUN8I_I2S_CTRL_MODE_LEFT; ++ offset = 0; ++ break; ++ ++ case SND_SOC_DAIFMT_RIGHT_J: ++ mode = SUN8I_I2S_CTRL_MODE_RIGHT; ++ offset = 0; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN8I_I2S_CTRL_MODE_MASK, mode); ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, ++ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, ++ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); ++ regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, ++ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, ++ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); ++ ++ /* DAI clock master masks */ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ /* BCLK and LRCLK master */ ++ val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; ++ break; ++ ++ case SND_SOC_DAIFMT_CBM_CFM: ++ /* BCLK and LRCLK slave */ ++ val = 0; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT, ++ val); ++ ++ return 0; ++} ++ + static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) + { + struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); +@@ -983,6 +1154,22 @@ static const struct reg_default sun8i_i2 + { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 }, + }; + ++static const struct reg_default sun50i_h6_i2s_reg_defaults[] = { ++ { SUN4I_I2S_CTRL_REG, 0x00060000 }, ++ { SUN4I_I2S_FMT0_REG, 0x00000033 }, ++ { SUN4I_I2S_FMT1_REG, 0x00000030 }, ++ { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, ++ { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, ++ { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, ++ { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 }, ++ { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 }, ++ { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 }, ++ { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 }, ++}; ++ + static const struct regmap_config sun4i_i2s_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, +@@ -1010,6 +1197,19 @@ static const struct regmap_config sun8i_ + .volatile_reg = sun8i_i2s_volatile_reg, + }; + ++static const struct regmap_config sun50i_h6_i2s_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = SUN50I_H6_I2S_RX_CHAN_MAP1_REG, ++ .cache_type = REGCACHE_FLAT, ++ .reg_defaults = sun50i_h6_i2s_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(sun50i_h6_i2s_reg_defaults), ++ .writeable_reg = sun4i_i2s_wr_reg, ++ .readable_reg = sun8i_i2s_rd_reg, ++ .volatile_reg = sun8i_i2s_volatile_reg, ++}; ++ + static int sun4i_i2s_runtime_resume(struct device *dev) + { + struct sun4i_i2s *i2s = dev_get_drvdata(dev); +@@ -1168,6 +1368,24 @@ static const struct sun4i_i2s_quirks sun + .set_fmt = sun4i_i2s_set_soc_fmt, + }; + ++static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = { ++ .has_reset = true, ++ .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, ++ .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config, ++ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), ++ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), ++ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), ++ .bclk_dividers = sun8i_i2s_clk_div, ++ .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), ++ .mclk_dividers = sun8i_i2s_clk_div, ++ .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), ++ .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, ++ .get_sr = sun8i_i2s_get_sr_wss, ++ .get_wss = sun8i_i2s_get_sr_wss, ++ .set_chan_cfg = sun50i_h6_i2s_set_chan_cfg, ++ .set_fmt = sun50i_h6_i2s_set_soc_fmt, ++}; ++ + static int sun4i_i2s_init_regmap_fields(struct device *dev, + struct sun4i_i2s *i2s) + { +@@ -1337,6 +1555,10 @@ static const struct of_device_id sun4i_i + .compatible = "allwinner,sun50i-a64-codec-i2s", + .data = &sun50i_a64_codec_i2s_quirks, + }, ++ { ++ .compatible = "allwinner,sun50i-h6-i2s", ++ .data = &sun50i_h6_i2s_quirks, ++ }, + {} + }; + MODULE_DEVICE_TABLE(of, sun4i_i2s_match); diff --git a/projects/Allwinner/patches/linux/0004-sun4i-i2s-improvements.patch b/projects/Allwinner/patches/linux/0004-sun4i-i2s-improvements.patch deleted file mode 100644 index 20fbec916e..0000000000 --- a/projects/Allwinner/patches/linux/0004-sun4i-i2s-improvements.patch +++ /dev/null @@ -1,752 +0,0 @@ -From b5cb1681a065bd03b0eb84ca243bc50ab0fa54c1 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Tue, 17 Sep 2019 17:55:07 +0200 -Subject: [PATCH] WIP: I2S improvements (to be mainlined) - -Work done by Marcus Cooper (codekipper) ---- - sound/soc/sunxi/sun4i-i2s.c | 454 ++++++++++++++++++++++++++++++++---- - 1 file changed, 412 insertions(+), 42 deletions(-) - -diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c -index d0a8d5810c0a..9a715a6bdbf9 100644 ---- a/sound/soc/sunxi/sun4i-i2s.c -+++ b/sound/soc/sunxi/sun4i-i2s.c -@@ -23,7 +23,7 @@ - - #define SUN4I_I2S_CTRL_REG 0x00 - #define SUN4I_I2S_CTRL_SDO_EN_MASK GENMASK(11, 8) --#define SUN4I_I2S_CTRL_SDO_EN(sdo) BIT(8 + (sdo)) -+#define SUN4I_I2S_CTRL_SDO_EN(lines) (((1 << (lines)) - 1) << 8) - #define SUN4I_I2S_CTRL_MODE_MASK BIT(5) - #define SUN4I_I2S_CTRL_MODE_SLAVE (1 << 5) - #define SUN4I_I2S_CTRL_MODE_MASTER (0 << 5) -@@ -48,6 +48,9 @@ - #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) - - #define SUN4I_I2S_FMT1_REG 0x08 -+#define SUN4I_I2S_FMT1_REG_SEXT_MASK BIT(8) -+#define SUN4I_I2S_FMT1_REG_SEXT(sext) ((sext) << 8) -+ - #define SUN4I_I2S_FIFO_TX_REG 0x0c - #define SUN4I_I2S_FIFO_RX_REG 0x10 - -@@ -97,33 +100,53 @@ - #define SUN8I_I2S_CTRL_MODE_PCM (0 << 4) - - #define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(19) --#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19) --#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19) -+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19) -+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19) - #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8) - #define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8) - #define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK BIT(7) --#define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7) --#define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7) -+#define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7) -+#define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7) -+ -+#define SUN8I_I2S_FMT1_REG_SEXT_MASK GENMASK(5, 4) -+#define SUN8I_I2S_FMT1_REG_SEXT(sext) ((sext) << 4) - - #define SUN8I_I2S_INT_STA_REG 0x0c - #define SUN8I_I2S_FIFO_TX_REG 0x20 - - #define SUN8I_I2S_CHAN_CFG_REG 0x30 - #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) --#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4) -+#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (((chan) - 1) << 4) - #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) --#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) -+#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) ((chan) - 1) - - #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 - #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 - #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12) --#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) -+#define SUN8I_I2S_TX_CHAN_OFFSET(offset) ((offset) << 12) - #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) - #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) -+#define SUN8I_I2S_TX_CHAN_SEL_MASK GENMASK(2, 0) -+#define SUN8I_I2S_TX_CHAN_SEL(chan) ((chan) - 1) - - #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 - #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 - -+/* Defines required for sun50i-h6 support */ -+#define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK GENMASK(21, 20) -+#define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset) ((offset) << 20) -+#define SUN50I_H6_I2S_TX_CHAN_SEL_MASK GENMASK(19, 16) -+#define SUN50I_H6_I2S_TX_CHAN_SEL(chan) (((chan) - 1) << 16) -+#define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) -+#define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << (num_chan)) - 1)) -+ -+#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 -+#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 -+ -+#define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 -+#define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 -+#define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6C -+ - struct sun4i_i2s; - - /** -@@ -156,7 +179,16 @@ struct sun4i_i2s_quirks { - s8 (*get_wss)(const struct sun4i_i2s *, int); - int (*set_chan_cfg)(const struct sun4i_i2s *, - const struct snd_pcm_hw_params *); -- int (*set_fmt)(const struct sun4i_i2s *, unsigned int); -+ int (*set_fmt)(struct sun4i_i2s *, unsigned int); -+ void (*set_fmt_sext)(const struct sun4i_i2s *, unsigned int); -+ void (*set_txchanoffset)(const struct sun4i_i2s *, int); -+ void (*set_rxchanoffset)(const struct sun4i_i2s *); -+ void (*set_txchanen)(const struct sun4i_i2s *, int, int); -+ void (*set_rxchanen)(const struct sun4i_i2s *, int); -+ void (*set_txchansel)(const struct sun4i_i2s *, int, int); -+ void (*set_rxchansel)(const struct sun4i_i2s *, int); -+ void (*set_txchanmap)(const struct sun4i_i2s *, int, int); -+ void (*set_rxchanmap)(const struct sun4i_i2s *, int); - }; - - struct sun4i_i2s { -@@ -169,6 +201,7 @@ struct sun4i_i2s { - unsigned int mclk_freq; - unsigned int slots; - unsigned int slot_width; -+ unsigned int offset; - - struct snd_dmaengine_dai_dma_data capture_dma_data; - struct snd_dmaengine_dai_dma_data playback_dma_data; -@@ -354,6 +387,9 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, - - regmap_field_write(i2s->field_clkdiv_mclk_en, 1); - -+ /* Set sign extension to pad out LSB with 0 */ -+ i2s->variant->set_fmt_sext(i2s, 0); -+ - return 0; - } - -@@ -396,8 +432,8 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, - unsigned int channels = params_channels(params); - - /* Map the channels for playback and capture */ -- regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210); -- regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210); -+ i2s->variant->set_txchanmap(i2s, 0, 0x76543210); -+ i2s->variant->set_rxchanmap(i2s, 0x3210); - - /* Configure the channels */ - regmap_update_bits(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG, -@@ -421,16 +457,12 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, - slots = i2s->slots; - - /* Map the channels for playback and capture */ -- regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210); -- regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210); -+ i2s->variant->set_txchanmap(i2s, 0, 0x76543210); -+ i2s->variant->set_rxchanmap(i2s, 0x3210); - - /* Configure the channels */ -- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, -- SUN4I_I2S_CHAN_SEL_MASK, -- SUN4I_I2S_CHAN_SEL(channels)); -- regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, -- SUN4I_I2S_CHAN_SEL_MASK, -- SUN4I_I2S_CHAN_SEL(channels)); -+ i2s->variant->set_txchansel(i2s, 0, channels); -+ i2s->variant->set_rxchansel(i2s, channels); - - regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, - SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, -@@ -448,7 +480,10 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, - break; - - case SND_SOC_DAIFMT_I2S: -- lrck_period = params_physical_width(params); -+ if (i2s->slot_width) -+ lrck_period = i2s->slot_width; -+ else -+ lrck_period = params_physical_width(params); - break; - - default: -@@ -466,6 +501,166 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, - return 0; - } - -+static void sun8i_i2s_set_txchanoffset(const struct sun4i_i2s *i2s, int output) -+{ -+ if (output >= 0 && output < 4) -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), -+ SUN8I_I2S_TX_CHAN_OFFSET_MASK, -+ SUN8I_I2S_TX_CHAN_OFFSET(i2s->offset)); -+} -+ -+static void sun8i_i2s_set_rxchanoffset(const struct sun4i_i2s *i2s) -+{ -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_RX_CHAN_SEL_REG, -+ SUN8I_I2S_TX_CHAN_OFFSET_MASK, -+ SUN8I_I2S_TX_CHAN_OFFSET(i2s->offset)); -+} -+ -+static void sun50i_h6_i2s_set_txchanoffset(const struct sun4i_i2s *i2s, int output) -+{ -+ if (output >= 0 && output < 4) -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), -+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, -+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(i2s->offset)); -+} -+ -+static void sun50i_h6_i2s_set_rxchanoffset(const struct sun4i_i2s *i2s) -+{ -+ regmap_update_bits(i2s->regmap, -+ SUN50I_H6_I2S_RX_CHAN_SEL_REG, -+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, -+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(i2s->offset)); -+} -+ -+static void sun8i_i2s_set_txchanen(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ if (output >= 0 && output < 4) -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), -+ SUN8I_I2S_TX_CHAN_EN_MASK, -+ SUN8I_I2S_TX_CHAN_EN(channel)); -+} -+ -+static void sun8i_i2s_set_rxchanen(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_RX_CHAN_SEL_REG, -+ SUN8I_I2S_TX_CHAN_EN_MASK, -+ SUN8I_I2S_TX_CHAN_EN(channel)); -+} -+ -+static void sun50i_h6_i2s_set_txchanen(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ if (output >= 0 && output < 4) -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), -+ SUN50I_H6_I2S_TX_CHAN_EN_MASK, -+ SUN50I_H6_I2S_TX_CHAN_EN(channel)); -+} -+ -+static void sun50i_h6_i2s_set_rxchanen(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_update_bits(i2s->regmap, -+ SUN50I_H6_I2S_RX_CHAN_SEL_REG, -+ SUN50I_H6_I2S_TX_CHAN_EN_MASK, -+ SUN50I_H6_I2S_TX_CHAN_EN(channel)); -+} -+ -+static void sun4i_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ /* Configure the channels */ -+ regmap_write(i2s->regmap, -+ SUN4I_I2S_TX_CHAN_SEL_REG, -+ SUN4I_I2S_CHAN_SEL(channel)); -+} -+ -+static void sun8i_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ if (output >= 0 && output < 4) -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), -+ SUN8I_I2S_TX_CHAN_SEL_MASK, -+ SUN8I_I2S_TX_CHAN_SEL(channel)); -+} -+ -+static void sun4i_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel) -+{ -+ /* Configure the channels */ -+ regmap_write(i2s->regmap, -+ SUN4I_I2S_RX_CHAN_SEL_REG, -+ SUN4I_I2S_CHAN_SEL(channel)); -+} -+ -+static void sun8i_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_RX_CHAN_SEL_REG, -+ SUN8I_I2S_TX_CHAN_SEL_MASK, -+ SUN8I_I2S_TX_CHAN_SEL(channel)); -+} -+ -+static void sun50i_h6_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ if (output >= 0 && output < 4) -+ regmap_update_bits(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), -+ SUN50I_H6_I2S_TX_CHAN_SEL_MASK, -+ SUN50I_H6_I2S_TX_CHAN_SEL(channel)); -+} -+ -+static void sun50i_h6_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_update_bits(i2s->regmap, -+ SUN50I_H6_I2S_RX_CHAN_SEL_REG, -+ SUN50I_H6_I2S_TX_CHAN_SEL_MASK, -+ SUN50I_H6_I2S_TX_CHAN_SEL(channel)); -+} -+ -+static void sun4i_i2s_set_txchanmap(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, channel); -+} -+ -+static void sun8i_i2s_set_txchanmap(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ if (output >= 0 && output < 4) -+ regmap_write(i2s->regmap, -+ SUN8I_I2S_TX_CHAN_MAP_REG + (output * 4), channel); -+} -+ -+static void sun4i_i2s_set_rxchanmap(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, channel); -+} -+ -+static void sun8i_i2s_set_rxchanmap(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, channel); -+} -+ -+static void sun50i_h6_i2s_set_txchanmap(const struct sun4i_i2s *i2s, int output, -+ int channel) -+{ -+ if (output >= 0 && output < 4) -+ regmap_write(i2s->regmap, -+ SUN50I_H6_I2S_TX_CHAN_MAP1_REG + (output * 8), channel); -+} -+ -+static void sun50i_h6_i2s_set_rxchanmap(const struct sun4i_i2s *i2s, int channel) -+{ -+ regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, channel); -+} -+ - static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -@@ -477,6 +672,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, - unsigned int slots = channels; - int ret, sr, wss; - u32 width; -+ int lines; - - if (i2s->slots) - slots = i2s->slots; -@@ -490,10 +686,82 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, - return ret; - } - -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ if (channels > dai->driver->playback.channels_max || -+ channels < dai->driver->playback.channels_min) { -+ dev_err(dai->dev, "Unsupported number of channels: %d\n", -+ channels); -+ return -EINVAL; -+ } -+ -+ lines = (channels + 1) / 2; -+ -+ /* Enable the required output lines */ -+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, -+ SUN4I_I2S_CTRL_SDO_EN_MASK, -+ SUN4I_I2S_CTRL_SDO_EN(lines)); -+ -+ i2s->variant->set_txchanmap(i2s, 0, 0x10); -+ i2s->variant->set_txchansel(i2s, 0, channels > 1 ? 2 : 1); -+ -+ if (i2s->variant->set_txchanen) -+ i2s->variant->set_txchanen(i2s, 0, 2); -+ -+ if (i2s->variant->set_txchanoffset) { -+ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, -+ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, -+ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); -+ -+ if (channels > 2) { -+ i2s->variant->set_txchanmap(i2s, 1, 0x32); -+ i2s->variant->set_txchanoffset(i2s, 1); -+ i2s->variant->set_txchansel(i2s, 1, -+ channels > 3 ? 2 : 1); -+ i2s->variant->set_txchanen(i2s, 1, 2); -+ } -+ if (channels > 4) { -+ i2s->variant->set_txchanmap(i2s, 2, 0x54); -+ i2s->variant->set_txchanoffset(i2s, 2); -+ i2s->variant->set_txchansel(i2s, 2, -+ channels > 5 ? 2 : 1); -+ i2s->variant->set_txchanen(i2s, 2, 2); -+ } -+ if (channels > 6) { -+ i2s->variant->set_txchanmap(i2s, 3, 0x76); -+ i2s->variant->set_txchanoffset(i2s, 3); -+ i2s->variant->set_txchansel(i2s, 3, -+ channels > 6 ? 2 : 1); -+ i2s->variant->set_txchanen(i2s, 3, 2); -+ } -+ } -+ } else { -+ if (channels > dai->driver->capture.channels_max || -+ channels < dai->driver->capture.channels_min) { -+ dev_err(dai->dev, "Unsupported number of channels: %d\n", -+ channels); -+ return -EINVAL; -+ } -+ -+ /* Map the channels for capture */ -+ i2s->variant->set_rxchanmap(i2s, 0x10); -+ i2s->variant->set_rxchansel(i2s, channels); -+ -+ if (i2s->variant->set_rxchanen) -+ i2s->variant->set_rxchanen(i2s, channels); -+ -+ if (i2s->variant->set_rxchanoffset) -+ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, -+ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, -+ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); -+ } -+ - switch (params_physical_width(params)) { - case 16: - width = DMA_SLAVE_BUSWIDTH_2_BYTES; - break; -+ case 32: -+ width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ break; - default: - dev_err(dai->dev, "Unsupported physical sample width: %d\n", - params_physical_width(params)); -@@ -516,7 +784,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, - slots, slot_width); - } - --static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, -+static int sun4i_i2s_set_soc_fmt(struct sun4i_i2s *i2s, - unsigned int fmt) - { - u32 val; -@@ -589,11 +857,10 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, - return 0; - } - --static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, -+static int sun8i_i2s_set_soc_fmt(struct sun4i_i2s *i2s, - unsigned int fmt) - { - u32 mode, val; -- u8 offset; - - /* - * DAI clock polarity -@@ -632,27 +899,27 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - mode = SUN8I_I2S_CTRL_MODE_PCM; -- offset = 1; -+ i2s->offset = 1; - break; - - case SND_SOC_DAIFMT_DSP_B: - mode = SUN8I_I2S_CTRL_MODE_PCM; -- offset = 0; -+ i2s->offset = 0; - break; - - case SND_SOC_DAIFMT_I2S: - mode = SUN8I_I2S_CTRL_MODE_LEFT; -- offset = 1; -+ i2s->offset = 1; - break; - - case SND_SOC_DAIFMT_LEFT_J: - mode = SUN8I_I2S_CTRL_MODE_LEFT; -- offset = 0; -+ i2s->offset = 0; - break; - - case SND_SOC_DAIFMT_RIGHT_J: - mode = SUN8I_I2S_CTRL_MODE_RIGHT; -- offset = 0; -+ i2s->offset = 0; - break; - - default: -@@ -661,12 +928,8 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, - - regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, - SUN8I_I2S_CTRL_MODE_MASK, mode); -- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, -- SUN8I_I2S_TX_CHAN_OFFSET_MASK, -- SUN8I_I2S_TX_CHAN_OFFSET(offset)); -- regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, -- SUN8I_I2S_TX_CHAN_OFFSET_MASK, -- SUN8I_I2S_TX_CHAN_OFFSET(offset)); -+ i2s->variant->set_txchanoffset(i2s, 0); -+ i2s->variant->set_rxchanoffset(i2s); - - /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -@@ -691,6 +954,22 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, - return 0; - } - -+static void sun4i_i2s_set_fmt_sext(const struct sun4i_i2s *i2s, -+ unsigned int sext) -+{ -+ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG, -+ SUN4I_I2S_FMT1_REG_SEXT_MASK, -+ SUN4I_I2S_FMT1_REG_SEXT(sext)); -+} -+ -+static void sun8i_i2s_set_fmt_sext(const struct sun4i_i2s *i2s, -+ unsigned int sext) -+{ -+ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG, -+ SUN8I_I2S_FMT1_REG_SEXT_MASK, -+ SUN8I_I2S_FMT1_REG_SEXT(sext)); -+} -+ - static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) - { - struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); -@@ -717,9 +996,9 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) - static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s) - { - /* Flush RX FIFO */ -- regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, -- SUN4I_I2S_FIFO_CTRL_FLUSH_RX, -- SUN4I_I2S_FIFO_CTRL_FLUSH_RX); -+ regmap_write_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, -+ SUN4I_I2S_FIFO_CTRL_FLUSH_RX, -+ SUN4I_I2S_FIFO_CTRL_FLUSH_RX); - - /* Clear RX counter */ - regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0); -@@ -738,9 +1017,9 @@ static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s) - static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s) - { - /* Flush TX FIFO */ -- regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, -- SUN4I_I2S_FIFO_CTRL_FLUSH_TX, -- SUN4I_I2S_FIFO_CTRL_FLUSH_TX); -+ regmap_write_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, -+ SUN4I_I2S_FIFO_CTRL_FLUSH_TX, -+ SUN4I_I2S_FIFO_CTRL_FLUSH_TX); - - /* Clear TX counter */ - regmap_write(i2s->regmap, SUN4I_I2S_TX_CNT_REG, 0); -@@ -862,6 +1141,10 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai) - return 0; - } - -+#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ -+ SNDRV_PCM_FMTBIT_S20_LE | \ -+ SNDRV_PCM_FMTBIT_S24_LE) -+ - static struct snd_soc_dai_driver sun4i_i2s_dai = { - .probe = sun4i_i2s_dai_probe, - .capture = { -@@ -869,14 +1152,14 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { - .channels_min = 1, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_8000_192000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ .formats = SUN4I_FORMATS, - }, - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_8000_192000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ .formats = SUN4I_FORMATS, - }, - .ops = &sun4i_i2s_dai_ops, - .symmetric_rates = 1, -@@ -971,6 +1254,22 @@ static const struct reg_default sun8i_i2s_reg_defaults[] = { - { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 }, - }; - -+static const struct reg_default sun50i_i2s_reg_defaults[] = { -+ { SUN4I_I2S_CTRL_REG, 0x00060000 }, -+ { SUN4I_I2S_FMT0_REG, 0x00000033 }, -+ { SUN4I_I2S_FMT1_REG, 0x00000030 }, -+ { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, -+ { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, -+ { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, -+ { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, -+ { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, -+ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 }, -+ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 }, -+ { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 }, -+ { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 }, -+ { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 }, -+}; -+ - static const struct regmap_config sun4i_i2s_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, -@@ -998,6 +1297,19 @@ static const struct regmap_config sun8i_i2s_regmap_config = { - .volatile_reg = sun8i_i2s_volatile_reg, - }; - -+static const struct regmap_config sun50i_i2s_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = SUN50I_H6_I2S_RX_CHAN_MAP1_REG, -+ .cache_type = REGCACHE_FLAT, -+ .reg_defaults = sun50i_i2s_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(sun50i_i2s_reg_defaults), -+ .writeable_reg = sun4i_i2s_wr_reg, -+ .readable_reg = sun8i_i2s_rd_reg, -+ .volatile_reg = sun8i_i2s_volatile_reg, -+}; -+ - static int sun4i_i2s_runtime_resume(struct device *dev) - { - struct sun4i_i2s *i2s = dev_get_drvdata(dev); -@@ -1077,6 +1389,11 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { - .get_wss = sun4i_i2s_get_wss, - .set_chan_cfg = sun4i_i2s_set_chan_cfg, - .set_fmt = sun4i_i2s_set_soc_fmt, -+ .set_fmt_sext = sun4i_i2s_set_fmt_sext, -+ .set_txchansel = sun4i_i2s_set_txchansel, -+ .set_rxchansel = sun4i_i2s_set_rxchansel, -+ .set_txchanmap = sun4i_i2s_set_txchanmap, -+ .set_rxchanmap = sun4i_i2s_set_rxchanmap, - }; - - static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { -@@ -1095,6 +1412,11 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { - .get_wss = sun4i_i2s_get_wss, - .set_chan_cfg = sun4i_i2s_set_chan_cfg, - .set_fmt = sun4i_i2s_set_soc_fmt, -+ .set_fmt_sext = sun4i_i2s_set_fmt_sext, -+ .set_txchansel = sun4i_i2s_set_txchansel, -+ .set_rxchansel = sun4i_i2s_set_rxchansel, -+ .set_txchanmap = sun4i_i2s_set_txchanmap, -+ .set_rxchanmap = sun4i_i2s_set_rxchanmap, - }; - - /* -@@ -1118,6 +1440,9 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { - .get_wss = sun4i_i2s_get_wss, - .set_chan_cfg = sun4i_i2s_set_chan_cfg, - .set_fmt = sun4i_i2s_set_soc_fmt, -+ .set_fmt_sext = sun4i_i2s_set_fmt_sext, -+ .set_txchansel = sun4i_i2s_set_txchansel, -+ .set_rxchansel = sun4i_i2s_set_rxchansel, - }; - - static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { -@@ -1136,6 +1461,15 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { - .get_wss = sun8i_i2s_get_sr_wss, - .set_chan_cfg = sun8i_i2s_set_chan_cfg, - .set_fmt = sun8i_i2s_set_soc_fmt, -+ .set_fmt_sext = sun8i_i2s_set_fmt_sext, -+ .set_txchanoffset = sun8i_i2s_set_txchanoffset, -+ .set_rxchanoffset = sun8i_i2s_set_rxchanoffset, -+ .set_txchanen = sun8i_i2s_set_txchanen, -+ .set_rxchanen = sun8i_i2s_set_rxchanen, -+ .set_txchansel = sun8i_i2s_set_txchansel, -+ .set_rxchansel = sun8i_i2s_set_rxchansel, -+ .set_txchanmap = sun8i_i2s_set_txchanmap, -+ .set_rxchanmap = sun8i_i2s_set_rxchanmap, - }; - - static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { -@@ -1154,6 +1488,38 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { - .get_wss = sun4i_i2s_get_wss, - .set_chan_cfg = sun4i_i2s_set_chan_cfg, - .set_fmt = sun4i_i2s_set_soc_fmt, -+ .set_fmt_sext = sun4i_i2s_set_fmt_sext, -+ .set_txchansel = sun4i_i2s_set_txchansel, -+ .set_rxchansel = sun4i_i2s_set_rxchansel, -+ .set_txchanmap = sun4i_i2s_set_txchanmap, -+ .set_rxchanmap = sun4i_i2s_set_rxchanmap, -+}; -+ -+static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = { -+ .has_reset = true, -+ .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, -+ .sun4i_i2s_regmap = &sun50i_i2s_regmap_config, -+ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), -+ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), -+ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), -+ .bclk_dividers = sun8i_i2s_clk_div, -+ .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), -+ .mclk_dividers = sun8i_i2s_clk_div, -+ .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), -+ .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, -+ .get_sr = sun8i_i2s_get_sr_wss, -+ .get_wss = sun8i_i2s_get_sr_wss, -+ .set_chan_cfg = sun8i_i2s_set_chan_cfg, -+ .set_fmt = sun8i_i2s_set_soc_fmt, -+ .set_fmt_sext = sun8i_i2s_set_fmt_sext, -+ .set_txchanoffset = sun50i_h6_i2s_set_txchanoffset, -+ .set_rxchanoffset = sun50i_h6_i2s_set_rxchanoffset, -+ .set_txchanen = sun50i_h6_i2s_set_txchanen, -+ .set_rxchanen = sun50i_h6_i2s_set_rxchanen, -+ .set_txchansel = sun50i_h6_i2s_set_txchansel, -+ .set_rxchansel = sun50i_h6_i2s_set_rxchansel, -+ .set_txchanmap = sun50i_h6_i2s_set_txchanmap, -+ .set_rxchanmap = sun50i_h6_i2s_set_rxchanmap, - }; - - static int sun4i_i2s_init_regmap_fields(struct device *dev, -@@ -1325,6 +1691,10 @@ static const struct of_device_id sun4i_i2s_match[] = { - .compatible = "allwinner,sun50i-a64-codec-i2s", - .data = &sun50i_a64_codec_i2s_quirks, - }, -+ { -+ .compatible = "allwinner,sun50i-h6-i2s", -+ .data = &sun50i_h6_i2s_quirks, -+ }, - {} - }; - MODULE_DEVICE_TABLE(of, sun4i_i2s_match); --- -2.23.0 - -From 2da43795f6191505b2dd6e30938c3af4c90bf745 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Thu, 7 Nov 2019 07:36:11 +0100 -Subject: [PATCH] sound: soc: sun4i-i2s: Fix rate calculation - -Signed-off-by: Jernej Skrabec ---- - sound/soc/sunxi/sun4i-i2s.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c -index d0a8d5810c0a..6c4241cb6509 100644 ---- a/sound/soc/sunxi/sun4i-i2s.c -+++ b/sound/soc/sunxi/sun4i-i2s.c -@@ -334,6 +334,9 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, - return -EINVAL; - } - -+ if (i2s->slot_width) -+ slot_width = i2s->slot_width; -+ - bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s); - bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate, - rate, slots, slot_width); --- -2.24.0 - diff --git a/projects/Allwinner/patches/linux/0005-ASoC-sun4i-i2s-Change-get_sr-and-get_wss-to-be-more-.patch b/projects/Allwinner/patches/linux/0005-ASoC-sun4i-i2s-Change-get_sr-and-get_wss-to-be-more-.patch new file mode 100644 index 0000000000..731610a0f7 --- /dev/null +++ b/projects/Allwinner/patches/linux/0005-ASoC-sun4i-i2s-Change-get_sr-and-get_wss-to-be-more-.patch @@ -0,0 +1,134 @@ +From aec30a56043a890b75440bb8c9673a07166cf104 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 30 Oct 2020 15:46:37 +0100 +Subject: [PATCH 05/44] ASoC: sun4i-i2s: Change get_sr() and get_wss() to be + more explicit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We are actually using a complex formula to just return a bunch of +simple values. Also this formula is wrong for sun4i when calling +get_wss() the function return 4 instead of 3. + +Replace this with a simpler switch case. + +Also drop the i2s params which is unused and return a simple int as +returning an error code could be out of range for an s8 and there is +no optim to return a s8 here. + +Fixes: 619c15f7fac9 ("ASoC: sun4i-i2s: Change SR and WSS computation") +Reviewed-by: Chen-Yu Tsai +Acked-by: Maxime Ripard +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-5-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 75 +++++++++++++++++++++++-------------- + 1 file changed, 47 insertions(+), 28 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -175,8 +175,8 @@ struct sun4i_i2s_quirks { + unsigned int num_mclk_dividers; + + unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *); +- s8 (*get_sr)(const struct sun4i_i2s *, int); +- s8 (*get_wss)(const struct sun4i_i2s *, int); ++ int (*get_sr)(unsigned int width); ++ int (*get_wss)(unsigned int width); + + /* + * In the set_chan_cfg() function pointer: +@@ -387,37 +387,56 @@ static int sun4i_i2s_set_clk_rate(struct + return 0; + } + +-static s8 sun4i_i2s_get_sr(const struct sun4i_i2s *i2s, int width) ++static int sun4i_i2s_get_sr(unsigned int width) + { +- if (width < 16 || width > 24) +- return -EINVAL; +- +- if (width % 4) +- return -EINVAL; ++ switch (width) { ++ case 16: ++ return 0; ++ case 20: ++ return 1; ++ case 24: ++ return 2; ++ } + +- return (width - 16) / 4; ++ return -EINVAL; + } + +-static s8 sun4i_i2s_get_wss(const struct sun4i_i2s *i2s, int width) ++static int sun4i_i2s_get_wss(unsigned int width) + { +- if (width < 16 || width > 32) +- return -EINVAL; +- +- if (width % 4) +- return -EINVAL; ++ switch (width) { ++ case 16: ++ return 0; ++ case 20: ++ return 1; ++ case 24: ++ return 2; ++ case 32: ++ return 3; ++ } + +- return (width - 16) / 4; ++ return -EINVAL; + } + +-static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width) ++static int sun8i_i2s_get_sr_wss(unsigned int width) + { +- if (width % 4) +- return -EINVAL; +- +- if (width < 8 || width > 32) +- return -EINVAL; ++ switch (width) { ++ case 8: ++ return 1; ++ case 12: ++ return 2; ++ case 16: ++ return 3; ++ case 20: ++ return 4; ++ case 24: ++ return 5; ++ case 28: ++ return 6; ++ case 32: ++ return 7; ++ } + +- return (width - 8) / 4 + 1; ++ return -EINVAL; + } + + static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, +@@ -582,11 +601,11 @@ static int sun4i_i2s_hw_params(struct sn + } + i2s->playback_dma_data.addr_width = width; + +- sr = i2s->variant->get_sr(i2s, word_size); ++ sr = i2s->variant->get_sr(word_size); + if (sr < 0) + return -EINVAL; + +- wss = i2s->variant->get_wss(i2s, slot_width); ++ wss = i2s->variant->get_wss(slot_width); + if (wss < 0) + return -EINVAL; + diff --git a/projects/Allwinner/patches/linux/0005-cedrus-improvements.patch b/projects/Allwinner/patches/linux/0005-cedrus-improvements.patch deleted file mode 100644 index 80994340a5..0000000000 --- a/projects/Allwinner/patches/linux/0005-cedrus-improvements.patch +++ /dev/null @@ -1,2440 +0,0 @@ -From 51af8e7381275e9b047857bb1269544fa4751ba7 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 13:55:15 +0200 -Subject: [PATCH 02/11] media: uapi: hevc: Add scaling matrix control - -HEVC has a scaling matrix concept. Add support for it. - -Signed-off-by: Jernej Skrabec ---- - .../media/uapi/v4l/ext-ctrls-codec.rst | 41 +++++++++++++++++++ - .../media/uapi/v4l/pixfmt-compressed.rst | 1 + - drivers/media/v4l2-core/v4l2-ctrls.c | 10 +++++ - include/media/hevc-ctrls.h | 11 +++++ - 4 files changed, 63 insertions(+) - -diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c -index 93d33d1db4e8..94c3e64ffb8b 100644 ---- a/drivers/media/v4l2-core/v4l2-ctrls.c -+++ b/drivers/media/v4l2-core/v4l2-ctrls.c -@@ -975,6 +975,7 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; - case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; - case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; - case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; - case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; - -@@ -1407,6 +1408,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, - case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: - *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; - break; -+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: -+ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; -+ break; - case V4L2_CID_UNIT_CELL_SIZE: - *type = V4L2_CTRL_TYPE_AREA; - *flags |= V4L2_CTRL_FLAG_READ_ONLY; -@@ -1857,6 +1861,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, - zero_padding(*p_hevc_slice_params); - break; - -+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: -+ break; -+ - case V4L2_CTRL_TYPE_AREA: - area = p; - if (!area->width || !area->height) -@@ -2546,6 +2553,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, - case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: - elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); - break; -+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: -+ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); -+ break; - case V4L2_CTRL_TYPE_AREA: - elem_size = sizeof(struct v4l2_area); - break; -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 1009cf0891cc..1592e52c3614 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -19,6 +19,7 @@ - #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) - #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) - #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) -+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) - #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) - #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) - -@@ -26,6 +27,7 @@ - #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 - #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 - #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 -+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 - - enum v4l2_mpeg_video_hevc_decode_mode { - V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, -@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { - __u64 flags; - }; - -+struct v4l2_ctrl_hevc_scaling_matrix { -+ __u8 scaling_list_4x4[6][16]; -+ __u8 scaling_list_8x8[6][64]; -+ __u8 scaling_list_16x16[6][64]; -+ __u8 scaling_list_32x32[2][64]; -+ __u8 scaling_list_dc_coef_16x16[6]; -+ __u8 scaling_list_dc_coef_32x32[2]; -+}; -+ - #endif --- -2.25.1 - - -From ba9500a50714666da11622d44f42a5512b5002d1 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 13:58:49 +0200 -Subject: [PATCH 03/11] media: cedrus: hevc: Add support for scaling matrix - -HEVC frames may use scaling list feature. Add support for it. - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.c | 7 ++ - drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + - .../staging/media/sunxi/cedrus/cedrus_dec.c | 2 + - .../staging/media/sunxi/cedrus/cedrus_h265.c | 70 ++++++++++++++++++- - .../staging/media/sunxi/cedrus/cedrus_regs.h | 2 + - 5 files changed, 81 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index 05a85517ff60..d813d32a6755 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -116,6 +116,13 @@ static const struct cedrus_control cedrus_controls[] = { - .codec = CEDRUS_CODEC_H265, - .required = true, - }, -+ { -+ .cfg = { -+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, -+ }, -+ .codec = CEDRUS_CODEC_H265, -+ .required = true, -+ }, - { - .cfg = { - .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index 96765555ab8a..d945f4f0ff2d 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -73,6 +73,7 @@ struct cedrus_h265_run { - const struct v4l2_ctrl_hevc_sps *sps; - const struct v4l2_ctrl_hevc_pps *pps; - const struct v4l2_ctrl_hevc_slice_params *slice_params; -+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; - }; - - struct cedrus_run { -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -index 4a2fc33a1d79..327ed6c264dc 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -@@ -66,6 +66,8 @@ void cedrus_device_run(void *priv) - V4L2_CID_MPEG_VIDEO_HEVC_PPS); - run.h265.slice_params = cedrus_find_control_data(ctx, - V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); -+ run.h265.scaling_matrix = cedrus_find_control_data(ctx, -+ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); - break; - - default: -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index ce497d0197df..0031b7517f6e 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -238,6 +238,69 @@ static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) - } - } - -+static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, -+ struct cedrus_run *run) -+{ -+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling; -+ struct cedrus_dev *dev = ctx->dev; -+ u32 i, j, k, val; -+ -+ scaling = run->h265.scaling_matrix; -+ -+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0, -+ (scaling->scaling_list_dc_coef_32x32[1] << 24) | -+ (scaling->scaling_list_dc_coef_32x32[0] << 16) | -+ (scaling->scaling_list_dc_coef_16x16[1] << 8) | -+ (scaling->scaling_list_dc_coef_16x16[0] << 0)); -+ -+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1, -+ (scaling->scaling_list_dc_coef_16x16[5] << 24) | -+ (scaling->scaling_list_dc_coef_16x16[4] << 16) | -+ (scaling->scaling_list_dc_coef_16x16[3] << 8) | -+ (scaling->scaling_list_dc_coef_16x16[2] << 0)); -+ -+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS); -+ -+ for (i = 0; i < 6; i++) -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 8; k += 4) { -+ val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) | -+ ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) | -+ ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) | -+ scaling->scaling_list_8x8[i][j + k * 8]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 8; k += 4) { -+ val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) | -+ ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) | -+ ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) | -+ scaling->scaling_list_32x32[i][j + k * 8]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+ -+ for (i = 0; i < 6; i++) -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 8; k += 4) { -+ val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) | -+ ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) | -+ ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) | -+ scaling->scaling_list_16x16[i][j + k * 8]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+ -+ for (i = 0; i < 6; i++) -+ for (j = 0; j < 4; j++) { -+ val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) | -+ ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) | -+ ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) | -+ scaling->scaling_list_4x4[i][j]; -+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); -+ } -+} -+ - static void cedrus_h265_setup(struct cedrus_ctx *ctx, - struct cedrus_run *run) - { -@@ -519,7 +582,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - - /* Scaling list. */ - -- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; -+ if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) { -+ cedrus_h265_write_scaling_list(ctx, run); -+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED; -+ } else { -+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; -+ } - cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); - - /* Neightbor information address. */ -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index 66b152f18d17..df1cceef8d93 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -493,6 +493,8 @@ - #define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64) - #define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) - #define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) -+#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78) -+#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c) - - #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) - --- -2.25.1 - - -From 6aef32eebe853485da686ae866cf43a45627476b Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 15:42:28 +0200 -Subject: [PATCH 04/11] media: uapi: hevc: Add segment address field - -If HEVC frame consists of multiple slices, segment address has to be -known in order to properly decode it. - -Add segment address field to slice parameters. - -Signed-off-by: Jernej Skrabec ---- - Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 5 ++++- - include/media/hevc-ctrls.h | 5 ++++- - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 1592e52c3614..3e2e32098312 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { - __u32 bit_size; - __u32 data_bit_offset; - -+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ -+ __u32 slice_segment_addr; -+ - /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ - __u8 nal_unit_type; - __u8 nuh_temporal_id_plus1; -@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { - __u8 num_rps_poc_st_curr_after; - __u8 num_rps_poc_lt_curr; - -- __u8 padding; -+ __u8 padding[5]; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; --- -2.25.1 - - -From e1fcee0fecc71d23b14daa1a5c89d2d6d8274d8e Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 15:44:15 +0200 -Subject: [PATCH 05/11] media: cedrus: hevc: Add support for multiple slices - -Now that segment address is available, support for multi-slice frames -can be easily added. - -Signed-off-by: Jernej Skrabec ---- - .../staging/media/sunxi/cedrus/cedrus_h265.c | 26 ++++++++++++------- - .../staging/media/sunxi/cedrus/cedrus_video.c | 1 + - 2 files changed, 17 insertions(+), 10 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index 0031b7517f6e..ff590d4e871a 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -309,6 +309,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - const struct v4l2_ctrl_hevc_pps *pps; - const struct v4l2_ctrl_hevc_slice_params *slice_params; - const struct v4l2_hevc_pred_weight_table *pred_weight_table; -+ unsigned int width_in_ctb_luma, ctb_size_luma; -+ unsigned int log2_max_luma_coding_block_size; - dma_addr_t src_buf_addr; - dma_addr_t src_buf_end_addr; - u32 chroma_log2_weight_denom; -@@ -321,15 +323,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - slice_params = run->h265.slice_params; - pred_weight_table = &slice_params->pred_weight_table; - -+ log2_max_luma_coding_block_size = -+ sps->log2_min_luma_coding_block_size_minus3 + 3 + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ ctb_size_luma = 1UL << log2_max_luma_coding_block_size; -+ width_in_ctb_luma = -+ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); -+ - /* MV column buffer size and allocation. */ - if (!ctx->codec.h265.mv_col_buf_size) { - unsigned int num_buffers = - run->dst->vb2_buf.vb2_queue->num_buffers; -- unsigned int log2_max_luma_coding_block_size = -- sps->log2_min_luma_coding_block_size_minus3 + 3 + -- sps->log2_diff_max_min_luma_coding_block_size; -- unsigned int ctb_size_luma = -- 1UL << log2_max_luma_coding_block_size; - - /* - * Each CTB requires a MV col buffer with a specific unit size. -@@ -383,15 +387,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); - cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); - -- /* Coding tree block address: start at the beginning. */ -- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); -+ /* Coding tree block address */ -+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); -+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); - cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); - - cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); - cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); - - /* Clear the number of correctly-decoded coding tree blocks. */ -- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); -+ if (ctx->fh.m2m_ctx->new_frame) -+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); - - /* Initialize bitstream access. */ - cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); -@@ -543,8 +549,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT, - pps->flags); - -- /* FIXME: For multi-slice support. */ -- reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; -+ if (ctx->fh.m2m_ctx->new_frame) -+ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; - - cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index 15cf1f10221b..497b1199d3fe 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -311,6 +311,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv, - - switch (ctx->src_fmt.pixelformat) { - case V4L2_PIX_FMT_H264_SLICE: -+ case V4L2_PIX_FMT_HEVC_SLICE: - vq->subsystem_flags |= - VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; - break; --- -2.25.1 - - -From e75f9802ba0fc3d7a000b9a159961ac8a4dbc07e Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 26 Oct 2019 21:23:55 +0200 -Subject: [PATCH 06/11] media: cedrus: hevc: tiles hack - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.h | 2 + - .../staging/media/sunxi/cedrus/cedrus_h265.c | 93 +++++++++++++++++-- - include/media/hevc-ctrls.h | 5 +- - 3 files changed, 93 insertions(+), 7 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index d945f4f0ff2d..1204e32d83bc 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -134,6 +134,8 @@ struct cedrus_ctx { - ssize_t mv_col_buf_unit_size; - void *neighbor_info_buf; - dma_addr_t neighbor_info_buf_addr; -+ void *entry_points_buf; -+ dma_addr_t entry_points_buf_addr; - } h265; - } codec; - }; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index ff590d4e871a..bc56130d2f17 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -301,6 +301,61 @@ static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, - } - } - -+static void write_entry_point_list(struct cedrus_ctx *ctx, -+ struct cedrus_run *run, -+ unsigned int ctb_addr_x, -+ unsigned int ctb_addr_y) -+{ -+ const struct v4l2_ctrl_hevc_slice_params *slice_params; -+ const struct v4l2_ctrl_hevc_pps *pps; -+ struct cedrus_dev *dev = ctx->dev; -+ int i, x, tx, y, ty; -+ u32 *entry_points; -+ -+ pps = run->h265.pps; -+ slice_params = run->h265.slice_params; -+ -+ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) { -+ if (x + pps->column_width_minus1[tx] + 1 > ctb_addr_x) -+ break; -+ -+ x += pps->column_width_minus1[tx] + 1; -+ } -+ -+ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) { -+ if (y + pps->row_height_minus1[ty] + 1 > ctb_addr_y) -+ break; -+ -+ y += pps->row_height_minus1[ty] + 1; -+ } -+ -+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0)); -+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, -+ ((y + pps->row_height_minus1[ty]) << 16) | -+ ((x + pps->column_width_minus1[tx]) << 0)); -+ -+ entry_points = ctx->codec.h265.entry_points_buf; -+ if (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) { -+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) -+ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1; -+ } else { -+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) { -+ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) { -+ x = 0; -+ tx = 0; -+ y += pps->row_height_minus1[ty++] + 1; -+ } else { -+ x += pps->column_width_minus1[tx++] + 1; -+ } -+ -+ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1; -+ entry_points[i * 4 + 1] = 0x0; -+ entry_points[i * 4 + 2] = (y << 16) | (x << 0); -+ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0); -+ } -+ } -+} -+ - static void cedrus_h265_setup(struct cedrus_ctx *ctx, - struct cedrus_run *run) - { -@@ -311,6 +366,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - const struct v4l2_hevc_pred_weight_table *pred_weight_table; - unsigned int width_in_ctb_luma, ctb_size_luma; - unsigned int log2_max_luma_coding_block_size; -+ unsigned int ctb_addr_x, ctb_addr_y; - dma_addr_t src_buf_addr; - dma_addr_t src_buf_end_addr; - u32 chroma_log2_weight_denom; -@@ -388,12 +444,19 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); - - /* Coding tree block address */ -- reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); -- reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); -+ ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma; -+ ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma; -+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x); -+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y); - cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); - -- cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); -- cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); -+ if ((pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) || -+ (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) { -+ write_entry_point_list(ctx, run, ctb_addr_x, ctb_addr_y); -+ } else { -+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); -+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); -+ } - - /* Clear the number of correctly-decoded coding tree blocks. */ - if (ctx->fh.m2m_ctx->new_frame) -@@ -497,7 +560,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED, - pps->flags); - -- /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */ -+ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED, -+ V4L2_HEVC_PPS_FLAG_TILES_ENABLED, -+ pps->flags); - - reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED, - V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED, -@@ -573,12 +638,14 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - - chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + - pred_weight_table->delta_chroma_log2_weight_denom; -- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) | -+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) | - VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) | - VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom); - - cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg); - -+ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8); -+ - /* Decoded picture size. */ - - reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) | -@@ -672,6 +739,17 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) - if (!ctx->codec.h265.neighbor_info_buf) - return -ENOMEM; - -+ ctx->codec.h265.entry_points_buf = -+ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, -+ &ctx->codec.h265.entry_points_buf_addr, -+ GFP_KERNEL); -+ if (!ctx->codec.h265.entry_points_buf) { -+ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, -+ ctx->codec.h265.neighbor_info_buf, -+ ctx->codec.h265.neighbor_info_buf_addr); -+ return -ENOMEM; -+ } -+ - return 0; - } - -@@ -690,6 +768,9 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) - dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h265.neighbor_info_buf, - ctx->codec.h265.neighbor_info_buf_addr); -+ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, -+ ctx->codec.h265.entry_points_buf, -+ ctx->codec.h265.entry_points_buf_addr); - } - - static void cedrus_h265_trigger(struct cedrus_ctx *ctx) -diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h -index 3e2e32098312..d1b094c8aaeb 100644 ---- a/include/media/hevc-ctrls.h -+++ b/include/media/hevc-ctrls.h -@@ -169,6 +169,7 @@ struct v4l2_ctrl_hevc_slice_params { - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - __u32 slice_segment_addr; -+ __u32 num_entry_point_offsets; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ - __u8 nal_unit_type; -@@ -203,7 +204,9 @@ struct v4l2_ctrl_hevc_slice_params { - __u8 num_rps_poc_st_curr_after; - __u8 num_rps_poc_lt_curr; - -- __u8 padding[5]; -+ __u8 padding; -+ -+ __u32 entry_point_offset_minus1[256]; - - /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ - struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; --- -2.25.1 - - -From 464ef73deba86cb59d14a5094604f4bb30ac1ce7 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 9 Nov 2019 13:06:15 +0100 -Subject: [PATCH 08/11] media: cedrus: Add callback for buffer cleanup - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + - drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++++ - 2 files changed, 14 insertions(+) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index 1204e32d83bc..9298aa5f229d 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -148,6 +148,7 @@ struct cedrus_dec_ops { - int (*start)(struct cedrus_ctx *ctx); - void (*stop)(struct cedrus_ctx *ctx); - void (*trigger)(struct cedrus_ctx *ctx); -+ void (*buf_cleanup)(struct cedrus_ctx *ctx, struct cedrus_buffer *buf); - }; - - struct cedrus_variant { -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index 497b1199d3fe..7f95216a552e 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -431,6 +431,18 @@ static int cedrus_buf_prepare(struct vb2_buffer *vb) - return 0; - } - -+static void cedrus_buf_cleanup(struct vb2_buffer *vb) -+{ -+ struct vb2_queue *vq = vb->vb2_queue; -+ struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); -+ struct cedrus_dev *dev = ctx->dev; -+ struct cedrus_dec_ops *ops = dev->dec_ops[ctx->current_codec]; -+ -+ if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ops->buf_cleanup) -+ ops->buf_cleanup(ctx, -+ vb2_to_cedrus_buffer(vq->bufs[vb->index])); -+} -+ - static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) - { - struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); -@@ -494,6 +506,7 @@ static void cedrus_buf_request_complete(struct vb2_buffer *vb) - static struct vb2_ops cedrus_qops = { - .queue_setup = cedrus_queue_setup, - .buf_prepare = cedrus_buf_prepare, -+ .buf_cleanup = cedrus_buf_cleanup, - .buf_queue = cedrus_buf_queue, - .buf_out_validate = cedrus_buf_out_validate, - .buf_request_complete = cedrus_buf_request_complete, --- -2.25.1 - - -From 9840ecff1bba7863e848ac47ac162091560b6d9f Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 9 Nov 2019 13:22:05 +0100 -Subject: [PATCH 09/11] media: cedrus: hevc: Improve buffer management - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +- - .../staging/media/sunxi/cedrus/cedrus_h265.c | 117 ++++++++++-------- - 2 files changed, 69 insertions(+), 57 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index 9298aa5f229d..d8a4f8e83f94 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -95,6 +95,11 @@ struct cedrus_buffer { - unsigned int position; - enum cedrus_h264_pic_type pic_type; - } h264; -+ struct { -+ void *mv_col_buf; -+ dma_addr_t mv_col_buf_dma; -+ ssize_t mv_col_buf_size; -+ } h265; - } codec; - }; - -@@ -128,10 +133,6 @@ struct cedrus_ctx { - ssize_t intra_pred_buf_size; - } h264; - struct { -- void *mv_col_buf; -- dma_addr_t mv_col_buf_addr; -- ssize_t mv_col_buf_size; -- ssize_t mv_col_buf_unit_size; - void *neighbor_info_buf; - dma_addr_t neighbor_info_buf_addr; - void *entry_points_buf; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index bc56130d2f17..4569d906979c 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, - - static inline dma_addr_t - cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, -- unsigned int index, unsigned int field) -+ unsigned int index, -+ const struct v4l2_ctrl_hevc_sps *sps) - { -- return ctx->codec.h265.mv_col_buf_addr + index * -- ctx->codec.h265.mv_col_buf_unit_size + -- field * ctx->codec.h265.mv_col_buf_unit_size / 2; -+ struct cedrus_buffer *cedrus_buf = NULL; -+ struct vb2_buffer *buf = NULL; -+ struct vb2_queue *vq; -+ -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); -+ if (vq) -+ buf = vb2_get_buffer(vq, index); -+ -+ if (buf) -+ cedrus_buf = vb2_to_cedrus_buffer(buf); -+ -+ if (!cedrus_buf) -+ return 0; -+ -+ if (!cedrus_buf->codec.h265.mv_col_buf_size) { -+ unsigned int ctb_size_luma, width_in_ctb_luma; -+ unsigned int log2_max_luma_coding_block_size; -+ -+ log2_max_luma_coding_block_size = -+ sps->log2_min_luma_coding_block_size_minus3 + 3 + -+ sps->log2_diff_max_min_luma_coding_block_size; -+ ctb_size_luma = 1 << log2_max_luma_coding_block_size; -+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, -+ ctb_size_luma); -+ -+ cedrus_buf->codec.h265.mv_col_buf_size = ALIGN(width_in_ctb_luma * -+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) * -+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024); -+ -+ cedrus_buf->codec.h265.mv_col_buf = -+ dma_alloc_coherent(ctx->dev->dev, -+ cedrus_buf->codec.h265.mv_col_buf_size, -+ &cedrus_buf->codec.h265.mv_col_buf_dma, -+ GFP_KERNEL); -+ -+ if (!cedrus_buf->codec.h265.mv_col_buf) { -+ cedrus_buf->codec.h265.mv_col_buf_size = 0; -+ cedrus_buf->codec.h265.mv_col_buf_dma = 0; -+ } -+ } -+ -+ return cedrus_buf->codec.h265.mv_col_buf_dma; - } - - static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, - unsigned int index, - bool field_pic, - u32 pic_order_cnt[], -- int buffer_index) -+ int buffer_index, -+ const struct v4l2_ctrl_hevc_sps *sps) - { - struct cedrus_dev *dev = ctx->dev; - dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); - dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); - dma_addr_t mv_col_buf_addr[2] = { -- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), -- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, -- field_pic ? 1 : 0) -+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps), -+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps) - }; - u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + - VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; -@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, - - static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, - const struct v4l2_hevc_dpb_entry *dpb, -- u8 num_active_dpb_entries) -+ u8 num_active_dpb_entries, -+ const struct v4l2_ctrl_hevc_sps *sps) - { - struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, - V4L2_BUF_TYPE_VIDEO_CAPTURE); -@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, - - cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, - pic_order_cnt, -- buffer_index); -+ buffer_index, sps); - } - } - -@@ -386,36 +427,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - width_in_ctb_luma = - DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); - -- /* MV column buffer size and allocation. */ -- if (!ctx->codec.h265.mv_col_buf_size) { -- unsigned int num_buffers = -- run->dst->vb2_buf.vb2_queue->num_buffers; -- -- /* -- * Each CTB requires a MV col buffer with a specific unit size. -- * Since the address is given with missing lsb bits, 1 KiB is -- * added to each buffer to ensure proper alignment. -- */ -- ctx->codec.h265.mv_col_buf_unit_size = -- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * -- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * -- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; -- -- ctx->codec.h265.mv_col_buf_size = num_buffers * -- ctx->codec.h265.mv_col_buf_unit_size; -- -- ctx->codec.h265.mv_col_buf = -- dma_alloc_coherent(dev->dev, -- ctx->codec.h265.mv_col_buf_size, -- &ctx->codec.h265.mv_col_buf_addr, -- GFP_KERNEL); -- if (!ctx->codec.h265.mv_col_buf) { -- ctx->codec.h265.mv_col_buf_size = 0; -- // TODO: Abort the process here. -- return; -- } -- } -- - /* Activate H265 engine. */ - cedrus_engine_enable(ctx, CEDRUS_CODEC_H265); - -@@ -669,7 +680,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - - /* Write decoded picture buffer in pic list. */ - cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb, -- slice_params->num_active_dpb_entries); -+ slice_params->num_active_dpb_entries, sps); - - /* Output frame. */ - -@@ -680,7 +691,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, - slice_params->pic_struct != 0, - pic_order_cnt, -- run->dst->vb2_buf.index); -+ run->dst->vb2_buf.index, sps); - - cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); - -@@ -729,9 +740,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - -- /* The buffer size is calculated at setup time. */ -- ctx->codec.h265.mv_col_buf_size = 0; -- - ctx->codec.h265.neighbor_info_buf = - dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - &ctx->codec.h265.neighbor_info_buf_addr, -@@ -757,14 +765,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - -- if (ctx->codec.h265.mv_col_buf_size > 0) { -- dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, -- ctx->codec.h265.mv_col_buf, -- ctx->codec.h265.mv_col_buf_addr); -- -- ctx->codec.h265.mv_col_buf_size = 0; -- } -- - dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h265.neighbor_info_buf, - ctx->codec.h265.neighbor_info_buf_addr); -@@ -780,6 +780,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx) - cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); - } - -+static void cedrus_h265_buf_cleanup(struct cedrus_ctx *ctx, -+ struct cedrus_buffer *buf) -+{ -+ if (buf->codec.h265.mv_col_buf_size) -+ dma_free_coherent(ctx->dev->dev, -+ buf->codec.h265.mv_col_buf_size, -+ buf->codec.h265.mv_col_buf, -+ buf->codec.h265.mv_col_buf_dma); -+} -+ - struct cedrus_dec_ops cedrus_dec_ops_h265 = { - .irq_clear = cedrus_h265_irq_clear, - .irq_disable = cedrus_h265_irq_disable, -@@ -788,4 +798,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = { - .start = cedrus_h265_start, - .stop = cedrus_h265_stop, - .trigger = cedrus_h265_trigger, -+ .buf_cleanup = cedrus_h265_buf_cleanup, - }; --- -2.25.1 - - -From 3c39cc9b8c5605419f7fe5385b77129d860b5a2b Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sat, 9 Nov 2019 14:12:42 +0100 -Subject: [PATCH 10/11] media: cedrus: h264: Improve buffer management - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.h | 3 + - .../staging/media/sunxi/cedrus/cedrus_h264.c | 93 ++++++++----------- - 2 files changed, 44 insertions(+), 52 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index d8a4f8e83f94..f8264953dd04 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -94,6 +94,9 @@ struct cedrus_buffer { - struct { - unsigned int position; - enum cedrus_h264_pic_type pic_type; -+ void *mv_col_buf; -+ dma_addr_t mv_col_buf_dma; -+ ssize_t mv_col_buf_size; - } h264; - struct { - void *mv_col_buf; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -index ba723d5af35c..c336366f6e19 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struct cedrus_dev *dev, - } - - static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx, -- unsigned int position, -+ struct cedrus_buffer *buf, - unsigned int field) - { -- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma; -+ dma_addr_t addr = buf->codec.h264.mv_col_buf_dma; - -- /* Adjust for the position */ -- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2; -- -- /* Adjust for the field */ -- addr += field * ctx->codec.h264.mv_col_buf_field_size; -+ /* Adjust for the field */ -+ if (field) -+ addr += buf->codec.h264.mv_col_buf_size / 2; - - return addr; - } -@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx, - struct cedrus_h264_sram_ref_pic *pic) - { - struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf; -- unsigned int position = buf->codec.h264.position; - - pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt); - pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt); -@@ -85,9 +82,9 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx, - pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0)); - pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1)); - pic->mv_col_top_ptr = -- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0)); -+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 0)); - pic->mv_col_bot_ptr = -- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1)); -+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 1)); - } - - static void cedrus_write_frame_list(struct cedrus_ctx *ctx, -@@ -147,6 +144,28 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx, - output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); - output_buf->codec.h264.position = position; - -+ if (!output_buf->codec.h264.mv_col_buf_size) { -+ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; -+ unsigned int field_size; -+ -+ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * -+ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; -+ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) -+ field_size = field_size * 2; -+ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) -+ field_size = field_size * 2; -+ -+ output_buf->codec.h264.mv_col_buf_size = field_size * 2; -+ output_buf->codec.h264.mv_col_buf = -+ dma_alloc_coherent(dev->dev, -+ output_buf->codec.h264.mv_col_buf_size, -+ &output_buf->codec.h264.mv_col_buf_dma, -+ GFP_KERNEL); -+ -+ if (!output_buf->codec.h264.mv_col_buf) -+ output_buf->codec.h264.mv_col_buf_size = 0; -+ } -+ - if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) - output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD; - else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) -@@ -525,8 +544,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - unsigned int pic_info_size; -- unsigned int field_size; -- unsigned int mv_col_size; - int ret; - - /* Formula for picture buffer size is taken from CedarX source. */ -@@ -569,37 +586,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) - goto err_pic_buf; - } - -- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * -- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; -- -- /* -- * FIXME: This is actually conditional to -- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we -- * might have to rework this if memory efficiency ever is -- * something we need to work on. -- */ -- field_size = field_size * 2; -- -- /* -- * FIXME: This is actually conditional to -- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might -- * have to rework this if memory efficiency ever is something -- * we need to work on. -- */ -- field_size = field_size * 2; -- ctx->codec.h264.mv_col_buf_field_size = field_size; -- -- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM; -- ctx->codec.h264.mv_col_buf_size = mv_col_size; -- ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev, -- ctx->codec.h264.mv_col_buf_size, -- &ctx->codec.h264.mv_col_buf_dma, -- GFP_KERNEL); -- if (!ctx->codec.h264.mv_col_buf) { -- ret = -ENOMEM; -- goto err_neighbor_buf; -- } -- - if (ctx->src_fmt.width > 2048) { - /* - * Formulas for deblock and intra prediction buffer sizes -@@ -615,7 +601,7 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) - GFP_KERNEL); - if (!ctx->codec.h264.deblk_buf) { - ret = -ENOMEM; -- goto err_mv_col_buf; -+ goto err_neighbor_buf; - } - - /* -@@ -642,11 +628,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx) - ctx->codec.h264.deblk_buf, - ctx->codec.h264.deblk_buf_dma); - --err_mv_col_buf: -- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, -- ctx->codec.h264.mv_col_buf, -- ctx->codec.h264.mv_col_buf_dma); -- - err_neighbor_buf: - dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h264.neighbor_info_buf, -@@ -663,9 +644,6 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx) - { - struct cedrus_dev *dev = ctx->dev; - -- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, -- ctx->codec.h264.mv_col_buf, -- ctx->codec.h264.mv_col_buf_dma); - dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, - ctx->codec.h264.neighbor_info_buf, - ctx->codec.h264.neighbor_info_buf_dma); -@@ -690,6 +668,16 @@ static void cedrus_h264_trigger(struct cedrus_ctx *ctx) - VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE); - } - -+static void cedrus_h264_buf_cleanup(struct cedrus_ctx *ctx, -+ struct cedrus_buffer *buf) -+{ -+ if (buf->codec.h264.mv_col_buf_size) -+ dma_free_coherent(ctx->dev->dev, -+ buf->codec.h264.mv_col_buf_size, -+ buf->codec.h264.mv_col_buf, -+ buf->codec.h264.mv_col_buf_dma); -+} -+ - struct cedrus_dec_ops cedrus_dec_ops_h264 = { - .irq_clear = cedrus_h264_irq_clear, - .irq_disable = cedrus_h264_irq_disable, -@@ -698,4 +686,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h264 = { - .start = cedrus_h264_start, - .stop = cedrus_h264_stop, - .trigger = cedrus_h264_trigger, -+ .buf_cleanup = cedrus_h264_buf_cleanup, - }; --- -2.25.1 - - -From c3dd710398e6d0697bb2583c1ebc76a40a8e8c79 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sun, 15 Mar 2020 21:35:39 +0100 -Subject: [PATCH 11/11] WIp: 10-bit HEVC support - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.c | 4 +-- - .../staging/media/sunxi/cedrus/cedrus_h265.c | 12 ++++++++ - .../staging/media/sunxi/cedrus/cedrus_regs.h | 4 +++ - .../staging/media/sunxi/cedrus/cedrus_video.c | 28 ++++++++++++++++--- - .../staging/media/sunxi/cedrus/cedrus_video.h | 2 +- - 5 files changed, 43 insertions(+), 7 deletions(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index d813d32a6755..e92d55331d08 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -288,7 +288,7 @@ static int cedrus_open(struct file *file) - goto err_ctrls; - } - ctx->dst_fmt.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12; -- cedrus_prepare_format(&ctx->dst_fmt); -+ cedrus_prepare_format(&ctx->dst_fmt, 0); - ctx->src_fmt.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; - /* - * TILED_NV12 has more strict requirements, so copy the width and -@@ -296,7 +296,7 @@ static int cedrus_open(struct file *file) - */ - ctx->src_fmt.width = ctx->dst_fmt.width; - ctx->src_fmt.height = ctx->dst_fmt.height; -- cedrus_prepare_format(&ctx->src_fmt); -+ cedrus_prepare_format(&ctx->src_fmt, 0); - - v4l2_fh_add(&ctx->fh); - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index 4569d906979c..8861e1535886 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -532,6 +532,18 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, - - cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg); - -+ if (sps->bit_depth_luma_minus8 == 2) { -+ unsigned int size; -+ -+ size = ALIGN(ctx->src_fmt.width, 16) * ALIGN(ctx->src_fmt.height, 16); -+ -+ reg = (size * 3) / 2; -+ cedrus_write(dev, VE_DEC_H265_OFFSET_ADDR_FIRST_OUT, reg); -+ -+ reg = DIV_ROUND_UP(ctx->src_fmt.width, 4); -+ cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, ALIGN(reg, 32)); -+ } -+ - /* PPS. */ - - reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) | -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index df1cceef8d93..150eae2d92d2 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -498,6 +498,10 @@ - - #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) - -+#define VE_DEC_H265_OFFSET_ADDR_FIRST_OUT (VE_ENGINE_DEC_H265 + 0x84) -+#define VE_DEC_H265_OFFSET_ADDR_SECOND_OUT (VE_ENGINE_DEC_H265 + 0x88) -+#define VE_DEC_H265_10BIT_CONFIGURE (VE_ENGINE_DEC_H265 + 0x8c) -+ - #define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \ - SHIFT_AND_MASK_BITS(a, 31, 24) - #define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \ -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index 7f95216a552e..daff14d0a1ae 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -91,7 +91,7 @@ static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions, - return &cedrus_formats[i]; - } - --void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) -+void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended) - { - unsigned int width = pix_fmt->width; - unsigned int height = pix_fmt->height; -@@ -145,6 +145,17 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) - break; - } - -+ if (extended) { -+ unsigned int extra_size; -+ -+ extra_size = DIV_ROUND_UP(pix_fmt->width, 4); -+ extra_size = ALIGN(extra_size, 32); -+ extra_size *= ALIGN(pix_fmt->height, 16) * 3; -+ extra_size /= 2; -+ -+ sizeimage += extra_size; -+ } -+ - pix_fmt->width = width; - pix_fmt->height = height; - -@@ -237,17 +248,27 @@ static int cedrus_try_fmt_vid_cap(struct file *file, void *priv, - struct cedrus_ctx *ctx = cedrus_file2ctx(file); - struct cedrus_dev *dev = ctx->dev; - struct v4l2_pix_format *pix_fmt = &f->fmt.pix; -+ const struct v4l2_ctrl_hevc_sps *sps; - struct cedrus_format *fmt = - cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST, - dev->capabilities); -+ int extended; - - if (!fmt) - return -EINVAL; - -+ sps = cedrus_find_control_data(ctx, V4L2_CID_MPEG_VIDEO_HEVC_SPS); -+ -+ /* The 10-bitHEVC decoder needs extra size on the output buffer. */ -+ extended = ctx->src_fmt.pixelformat == V4L2_PIX_FMT_HEVC_SLICE && -+ sps->bit_depth_luma_minus8 == 2; -+ - pix_fmt->pixelformat = fmt->pixelformat; - pix_fmt->width = ctx->src_fmt.width; - pix_fmt->height = ctx->src_fmt.height; -- cedrus_prepare_format(pix_fmt); -+ -+ pix_fmt->pixelformat = fmt->pixelformat; -+ cedrus_prepare_format(pix_fmt, extended); - - return 0; - } -@@ -263,8 +284,7 @@ static int cedrus_try_fmt_vid_out(struct file *file, void *priv, - if (!fmt) - return -EINVAL; - -- pix_fmt->pixelformat = fmt->pixelformat; -- cedrus_prepare_format(pix_fmt); -+ cedrus_prepare_format(pix_fmt, 0); - - return 0; - } -@@ -348,7 +348,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv, - ctx->dst_fmt.quantization = f->fmt.pix.quantization; - ctx->dst_fmt.width = ctx->src_fmt.width; - ctx->dst_fmt.height = ctx->src_fmt.height; -- cedrus_prepare_format(&ctx->dst_fmt); -+ cedrus_prepare_format(&ctx->dst_fmt, 0); - - return 0; - } -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.h b/drivers/staging/media/sunxi/cedrus/cedrus_video.h -index 05050c0a0921..d42e4ebf6cad 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h -@@ -26,6 +26,6 @@ extern const struct v4l2_ioctl_ops cedrus_ioctl_ops; - - int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq); --void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt); -+void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended); - - #endif --- -2.25.1 - -From 19c227cb73d6cd040341987d25cf1ad23e1454a2 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Tue, 21 Jul 2020 21:53:27 +0200 -Subject: [PATCH] media: cedrus: add check for H264 and HEVC limitations - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/cedrus.c | 49 ++++++++++++++++++++- - drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + - 2 files changed, 49 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index e6b864f05364..c3101c0225d6 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -28,6 +28,50 @@ - #include "cedrus_dec.h" - #include "cedrus_hw.h" - -+static int cedrus_try_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { -+ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; -+ -+ if (sps->chroma_format_idc != 1) -+ /* Only 4:2:0 is supported */ -+ return -EINVAL; -+ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) -+ /* Luma and chroma bit depth mismatch */ -+ return -EINVAL; -+ if (sps->bit_depth_luma_minus8 != 0) -+ /* Only 8-bit is supported */ -+ return -EINVAL; -+ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) { -+ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; -+ struct cedrus_ctx *ctx = container_of(ctrl->handler, struct cedrus_ctx, hdl); -+ -+ if (sps->chroma_format_idc != 1) -+ /* Only 4:2:0 is supported */ -+ return -EINVAL; -+ -+ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) -+ /* Luma and chroma bit depth mismatch */ -+ return -EINVAL; -+ -+ if (ctx->dev->capabilities & CEDRUS_CAPABILITY_H265_10_DEC) { -+ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) -+ /* Only 8-bit and 10-bit are supported */ -+ return -EINVAL; -+ } else { -+ if (sps->bit_depth_luma_minus8 != 0) -+ /* Only 8-bit is supported */ -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+static const struct v4l2_ctrl_ops cedrus_ctrl_ops = { -+ .try_ctrl = cedrus_try_ctrl, -+}; -+ - static const struct cedrus_control cedrus_controls[] = { - { - .cfg = { -@@ -60,6 +104,7 @@ static const struct cedrus_control cedrus_controls[] = { - { - .cfg = { - .id = V4L2_CID_MPEG_VIDEO_H264_SPS, -+ .ops = &cedrus_ctrl_ops, - }, - .codec = CEDRUS_CODEC_H264, - .required = true, -@@ -99,6 +144,7 @@ static const struct cedrus_control cedrus_controls[] = { - { - .cfg = { - .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, -+ .ops = &cedrus_ctrl_ops, - }, - .codec = CEDRUS_CODEC_H265, - .required = true, -@@ -525,7 +571,8 @@ static const struct cedrus_variant sun50i_h5_cedrus_variant = { - - static const struct cedrus_variant sun50i_h6_cedrus_variant = { - .capabilities = CEDRUS_CAPABILITY_UNTILED | -- CEDRUS_CAPABILITY_H265_DEC, -+ CEDRUS_CAPABILITY_H265_DEC | -+ CEDRUS_CAPABILITY_H265_10_DEC, - .quirks = CEDRUS_QUIRK_NO_DMA_OFFSET, - .mod_rate = 600000000, - }; -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index 353cb04b4ce5..b8d3a685b549 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -28,6 +28,7 @@ - - #define CEDRUS_CAPABILITY_UNTILED BIT(0) - #define CEDRUS_CAPABILITY_H265_DEC BIT(1) -+#define CEDRUS_CAPABILITY_H265_10_DEC BIT(2) - - #define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0) - --- -2.27.0 - -From patchwork Wed May 20 21:01:29 2020 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: =?utf-8?q?Jernej_=C5=A0krabec?= - -X-Patchwork-Id: 63962 -X-Patchwork-Delegate: hverkuil@xs4all.nl -Received: from vger.kernel.org ([23.128.96.18]) - by www.linuxtv.org with esmtp (Exim 4.92) - (envelope-from ) - id 1jbVkU-00Fo0H-K2; Wed, 20 May 2020 20:55:37 +0000 -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1728023AbgETU7E (ORCPT + 1 other); - Wed, 20 May 2020 16:59:04 -0400 -Received: from mailoutvs56.siol.net ([185.57.226.247]:55962 "EHLO - mail.siol.net" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org - with ESMTP id S1727018AbgETU7E (ORCPT - ); - Wed, 20 May 2020 16:59:04 -0400 -Received: from localhost (localhost [127.0.0.1]) - by mail.siol.net (Zimbra) with ESMTP id DD7C25215C3; - Wed, 20 May 2020 22:58:53 +0200 (CEST) -X-Virus-Scanned: amavisd-new at psrvmta12.zcs-production.pri -Received: from mail.siol.net ([127.0.0.1]) - by localhost (psrvmta12.zcs-production.pri [127.0.0.1]) (amavisd-new, - port 10032) - with ESMTP id uLlvVeda4tVC; Wed, 20 May 2020 22:58:51 +0200 (CEST) -Received: from mail.siol.net (localhost [127.0.0.1]) - by mail.siol.net (Zimbra) with ESMTPS id 52A0C521527; - Wed, 20 May 2020 22:58:51 +0200 (CEST) -Received: from kista.localdomain (cpe-194-152-20-232.static.triera.net - [194.152.20.232]) - (Authenticated sender: 031275009) - by mail.siol.net (Zimbra) with ESMTPSA id B6B3452140A; - Wed, 20 May 2020 22:58:50 +0200 (CEST) -From: Jernej Skrabec -To: mripard@kernel.org, paul.kocialkowski@bootlin.com -Cc: mchehab@kernel.org, gregkh@linuxfoundation.org, wens@csie.org, - hverkuil-cisco@xs4all.nl, linux-kernel@vger.kernel.org, - linux-media@vger.kernel.org, devel@driverdev.osuosl.org, - linux-arm-kernel@lists.infradead.org -Subject: [PATCH] media: cedrus: Add support for VP8 decoding -Date: Wed, 20 May 2020 23:01:29 +0200 -Message-Id: <20200520210129.132816-1-jernej.skrabec@siol.net> -X-Mailer: git-send-email 2.26.2 -MIME-Version: 1.0 -Sender: linux-media-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-media@vger.kernel.org -X-LSpam-Score: -2.4 (--) -X-LSpam-Report: No, - score=-2.4 required=5.0 - tests=BAYES_00=-1.9,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 - autolearn=ham autolearn_force=no - -VP8 in Cedrus shares same engine as H264. - -Note that it seems necessary to call bitstream parsing functions, -to parse frame header, otherwise decoded image is garbage. This is -contrary to what is driver supposed to do. However, values are not -really used, so this might be acceptable. It's possible that bitstream -parsing functions set some internal VPU state, which is later necessary -for proper decoding. Biggest suspect is "VP8 probs update" trigger. - -Signed-off-by: Jernej Skrabec ---- - drivers/staging/media/sunxi/cedrus/Makefile | 3 +- - drivers/staging/media/sunxi/cedrus/cedrus.c | 8 + - drivers/staging/media/sunxi/cedrus/cedrus.h | 15 + - .../staging/media/sunxi/cedrus/cedrus_dec.c | 5 + - .../staging/media/sunxi/cedrus/cedrus_hw.c | 1 + - .../staging/media/sunxi/cedrus/cedrus_regs.h | 80 ++ - .../staging/media/sunxi/cedrus/cedrus_video.c | 9 + - .../staging/media/sunxi/cedrus/cedrus_vp8.c | 699 ++++++++++++++++++ - 8 files changed, 819 insertions(+), 1 deletion(-) - create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_vp8.c - -diff --git a/drivers/staging/media/sunxi/cedrus/Makefile b/drivers/staging/media/sunxi/cedrus/Makefile -index 1bce49d3e7e2..a647b3690bf8 100644 ---- a/drivers/staging/media/sunxi/cedrus/Makefile -+++ b/drivers/staging/media/sunxi/cedrus/Makefile -@@ -2,4 +2,5 @@ - obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o - - sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \ -- cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o -+ cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \ -+ cedrus_vp8.o -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c -index b320aa058f74..e6b864f05364 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c -@@ -142,6 +142,13 @@ static const struct cedrus_control cedrus_controls[] = { - .codec = CEDRUS_CODEC_H265, - .required = false, - }, -+ { -+ .cfg = { -+ .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, -+ }, -+ .codec = CEDRUS_CODEC_VP8, -+ .required = true, -+ }, - }; - - #define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls) -@@ -388,6 +395,7 @@ static int cedrus_probe(struct platform_device *pdev) - dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2; - dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264; - dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265; -+ dev->dec_ops[CEDRUS_CODEC_VP8] = &cedrus_dec_ops_vp8; - - mutex_init(&dev->dev_mutex); - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h -index f8264953dd04..353cb04b4ce5 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h -@@ -35,6 +35,7 @@ enum cedrus_codec { - CEDRUS_CODEC_MPEG2, - CEDRUS_CODEC_H264, - CEDRUS_CODEC_H265, -+ CEDRUS_CODEC_VP8, - CEDRUS_CODEC_LAST, - }; - -@@ -76,6 +77,10 @@ struct cedrus_h265_run { - const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; - }; - -+struct cedrus_vp8_run { -+ const struct v4l2_ctrl_vp8_frame_header *slice_params; -+}; -+ - struct cedrus_run { - struct vb2_v4l2_buffer *src; - struct vb2_v4l2_buffer *dst; -@@ -84,6 +89,7 @@ struct cedrus_run { - struct cedrus_h264_run h264; - struct cedrus_mpeg2_run mpeg2; - struct cedrus_h265_run h265; -+ struct cedrus_vp8_run vp8; - }; - }; - -@@ -141,6 +147,14 @@ struct cedrus_ctx { - void *entry_points_buf; - dma_addr_t entry_points_buf_addr; - } h265; -+ struct { -+ unsigned int last_frame_p_type; -+ unsigned int last_filter_type; -+ unsigned int last_sharpness_level; -+ -+ u8 *entropy_probs_buf; -+ dma_addr_t entropy_probs_buf_dma; -+ } vp8; - } codec; - }; - -@@ -188,6 +202,7 @@ struct cedrus_dev { - extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; - extern struct cedrus_dec_ops cedrus_dec_ops_h264; - extern struct cedrus_dec_ops cedrus_dec_ops_h265; -+extern struct cedrus_dec_ops cedrus_dec_ops_vp8; - - static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val) - { -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -index 38c0bd7cf672..740b738fdde6 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c -@@ -70,6 +70,11 @@ void cedrus_device_run(void *priv) - V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); - break; - -+ case V4L2_PIX_FMT_VP8_FRAME: -+ run.vp8.slice_params = cedrus_find_control_data(ctx, -+ V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER); -+ break; -+ - default: - break; - } -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -index fb0cf8adcf1e..7c0ab4015e8f 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c -@@ -48,6 +48,7 @@ int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec) - break; - - case CEDRUS_CODEC_H264: -+ case CEDRUS_CODEC_VP8: - reg |= VE_MODE_DEC_H264; - break; - -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -index 150eae2d92d2..6cb1c279790f 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h -@@ -552,6 +552,7 @@ - #define VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT BIT(24) - - #define VE_H264_CTRL 0x220 -+#define VE_H264_CTRL_VP8 BIT(29) - #define VE_H264_CTRL_VLD_DATA_REQ_INT BIT(2) - #define VE_H264_CTRL_DECODE_ERR_INT BIT(1) - #define VE_H264_CTRL_SLICE_DECODE_INT BIT(0) -@@ -561,7 +562,12 @@ - VE_H264_CTRL_SLICE_DECODE_INT) - - #define VE_H264_TRIGGER_TYPE 0x224 -+#define VE_H264_TRIGGER_TYPE_PROBABILITY(x) SHIFT_AND_MASK_BITS(x, 31, 24) -+#define VE_H264_TRIGGER_TYPE_BIN_LENS(x) SHIFT_AND_MASK_BITS((x) - 1, 18, 16) - #define VE_H264_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8) -+#define VE_H264_TRIGGER_TYPE_VP8_GET_BITS (15 << 0) -+#define VE_H264_TRIGGER_TYPE_VP8_UPDATE_COEF (14 << 0) -+#define VE_H264_TRIGGER_TYPE_VP8_SLICE_DECODE (10 << 0) - #define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE (8 << 0) - #define VE_H264_TRIGGER_TYPE_INIT_SWDEC (7 << 0) - #define VE_H264_TRIGGER_TYPE_FLUSH_BITS (3 << 0) -@@ -571,6 +577,7 @@ - #define VE_H264_STATUS_DECODE_ERR_INT VE_H264_CTRL_DECODE_ERR_INT - #define VE_H264_STATUS_SLICE_DECODE_INT VE_H264_CTRL_SLICE_DECODE_INT - #define VE_H264_STATUS_VLD_BUSY BIT(8) -+#define VE_H264_STATUS_VP8_UPPROB_BUSY BIT(17) - - #define VE_H264_STATUS_INT_MASK VE_H264_CTRL_INT_MASK - -@@ -589,10 +596,83 @@ - #define VE_H264_OUTPUT_FRAME_IDX 0x24c - #define VE_H264_EXTRA_BUFFER1 0x250 - #define VE_H264_EXTRA_BUFFER2 0x254 -+#define VE_H264_MB_ADDR 0x260 -+#define VE_H264_ERROR_CASE 0x2b8 - #define VE_H264_BASIC_BITS 0x2dc - #define VE_AVC_SRAM_PORT_OFFSET 0x2e0 - #define VE_AVC_SRAM_PORT_DATA 0x2e4 - -+#define VE_VP8_PPS 0x214 -+#define VE_VP8_PPS_PIC_TYPE_P_FRAME BIT(31) -+#define VE_VP8_PPS_LAST_SHARPNESS_LEVEL(v) SHIFT_AND_MASK_BITS(v, 30, 28) -+#define VE_VP8_PPS_LAST_PIC_TYPE_P_FRAME BIT(27) -+#define VE_VP8_PPS_ALTREF_SIGN_BIAS BIT(26) -+#define VE_VP8_PPS_GOLDEN_SIGN_BIAS BIT(25) -+#define VE_VP8_PPS_RELOAD_ENTROPY_PROBS BIT(24) -+#define VE_VP8_PPS_REFRESH_ENTROPY_PROBS BIT(23) -+#define VE_VP8_PPS_MB_NO_COEFF_SKIP BIT(22) -+#define VE_VP8_PPS_TOKEN_PARTITION(v) SHIFT_AND_MASK_BITS(v, 21, 20) -+#define VE_VP8_PPS_MODE_REF_LF_DELTA_UPDATE BIT(19) -+#define VE_VP8_PPS_MODE_REF_LF_DELTA_ENABLE BIT(18) -+#define VE_VP8_PPS_LOOP_FILTER_LEVEL(v) SHIFT_AND_MASK_BITS(v, 17, 12) -+#define VE_VP8_PPS_LOOP_FILTER_SIMPLE BIT(11) -+#define VE_VP8_PPS_SHARPNESS_LEVEL(v) SHIFT_AND_MASK_BITS(v, 10, 8) -+#define VE_VP8_PPS_LAST_LOOP_FILTER_SIMPLE BIT(7) -+#define VE_VP8_PPS_SEGMENTATION_ENABLE BIT(6) -+#define VE_VP8_PPS_MB_SEGMENT_ABS_DELTA BIT(5) -+#define VE_VP8_PPS_UPDATE_MB_SEGMENTATION_MAP BIT(4) -+#define VE_VP8_PPS_FULL_PIXEL BIT(3) -+#define VE_VP8_PPS_BILINEAR_MC_FILTER BIT(2) -+#define VE_VP8_PPS_FILTER_TYPE_SIMPLE BIT(1) -+#define VE_VP8_PPS_LPF_DISABLE BIT(0) -+ -+#define VE_VP8_QP_INDEX_DELTA 0x218 -+#define VE_VP8_QP_INDEX_DELTA_UVAC(v) SHIFT_AND_MASK_BITS(v, 31, 27) -+#define VE_VP8_QP_INDEX_DELTA_UVDC(v) SHIFT_AND_MASK_BITS(v, 26, 22) -+#define VE_VP8_QP_INDEX_DELTA_Y2AC(v) SHIFT_AND_MASK_BITS(v, 21, 17) -+#define VE_VP8_QP_INDEX_DELTA_Y2DC(v) SHIFT_AND_MASK_BITS(v, 16, 12) -+#define VE_VP8_QP_INDEX_DELTA_Y1DC(v) SHIFT_AND_MASK_BITS(v, 11, 7) -+#define VE_VP8_QP_INDEX_DELTA_BASE_QINDEX(v) SHIFT_AND_MASK_BITS(v, 6, 0) -+ -+#define VE_VP8_PART_SIZE_OFFSET 0x21c -+#define VE_VP8_ENTROPY_PROBS_ADDR 0x250 -+#define VE_VP8_FIRST_DATA_PART_LEN 0x254 -+ -+#define VE_VP8_FSIZE 0x258 -+#define VE_VP8_FSIZE_WIDTH(w) \ -+ SHIFT_AND_MASK_BITS(DIV_ROUND_UP(w, 16), 15, 8) -+#define VE_VP8_FSIZE_HEIGHT(h) \ -+ SHIFT_AND_MASK_BITS(DIV_ROUND_UP(h, 16), 7, 0) -+ -+#define VE_VP8_PICSIZE 0x25c -+#define VE_VP8_PICSIZE_WIDTH(w) SHIFT_AND_MASK_BITS(w, 27, 16) -+#define VE_VP8_PICSIZE_HEIGHT(h) SHIFT_AND_MASK_BITS(h, 11, 0) -+ -+#define VE_VP8_REC_LUMA 0x2ac -+#define VE_VP8_FWD_LUMA 0x2b0 -+#define VE_VP8_BWD_LUMA 0x2b4 -+#define VE_VP8_REC_CHROMA 0x2d0 -+#define VE_VP8_FWD_CHROMA 0x2d4 -+#define VE_VP8_BWD_CHROMA 0x2d8 -+#define VE_VP8_ALT_LUMA 0x2e8 -+#define VE_VP8_ALT_CHROMA 0x2ec -+ -+#define VE_VP8_SEGMENT_FEAT_MB_LV0 0x2f0 -+#define VE_VP8_SEGMENT_FEAT_MB_LV1 0x2f4 -+ -+#define VE_VP8_SEGMENT3(v) SHIFT_AND_MASK_BITS(v, 31, 24) -+#define VE_VP8_SEGMENT2(v) SHIFT_AND_MASK_BITS(v, 23, 16) -+#define VE_VP8_SEGMENT1(v) SHIFT_AND_MASK_BITS(v, 15, 8) -+#define VE_VP8_SEGMENT0(v) SHIFT_AND_MASK_BITS(v, 7, 0) -+ -+#define VE_VP8_REF_LF_DELTA 0x2f8 -+#define VE_VP8_MODE_LF_DELTA 0x2fc -+ -+#define VE_VP8_LF_DELTA3(v) SHIFT_AND_MASK_BITS(v, 30, 24) -+#define VE_VP8_LF_DELTA2(v) SHIFT_AND_MASK_BITS(v, 22, 16) -+#define VE_VP8_LF_DELTA1(v) SHIFT_AND_MASK_BITS(v, 14, 8) -+#define VE_VP8_LF_DELTA0(v) SHIFT_AND_MASK_BITS(v, 6, 0) -+ - #define VE_ISP_INPUT_SIZE 0xa00 - #define VE_ISP_INPUT_STRIDE 0xa04 - #define VE_ISP_CTRL 0xa08 -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -index a78d6b1a3b64..6801ffa77a6b 100644 ---- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c -@@ -48,6 +48,10 @@ static struct cedrus_format cedrus_formats[] = { - .directions = CEDRUS_DECODE_SRC, - .capabilities = CEDRUS_CAPABILITY_H265_DEC, - }, -+ { -+ .pixelformat = V4L2_PIX_FMT_VP8_FRAME, -+ .directions = CEDRUS_DECODE_SRC, -+ }, - { - .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, - .directions = CEDRUS_DECODE_DST, -@@ -125,6 +129,7 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended) - case V4L2_PIX_FMT_MPEG2_SLICE: - case V4L2_PIX_FMT_H264_SLICE: - case V4L2_PIX_FMT_HEVC_SLICE: -+ case V4L2_PIX_FMT_VP8_FRAME: - /* Zero bytes per line for encoded source. */ - bytesperline = 0; - /* Choose some minimum size since this can't be 0 */ -@@ -499,6 +504,10 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) - ctx->current_codec = CEDRUS_CODEC_H265; - break; - -+ case V4L2_PIX_FMT_VP8_FRAME: -+ ctx->current_codec = CEDRUS_CODEC_VP8; -+ break; -+ - default: - return -EINVAL; - } -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c -new file mode 100644 -index 000000000000..93beffd07c35 ---- /dev/null -+++ b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c -@@ -0,0 +1,699 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Cedrus VPU driver -+ * -+ * Copyright (c) 2019 Jernej Skrabec -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include "cedrus.h" -+#include "cedrus_hw.h" -+#include "cedrus_regs.h" -+ -+#define CEDRUS_ENTROPY_PROBS_SIZE 0x2400 -+#define VP8_PROB_HALF 128 -+ -+static const u8 prob_table_init[] = { -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xB0, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xF1, 0xFC, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xF9, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF4, 0xFC, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xEA, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xF6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xEF, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xFE, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFE, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFB, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFE, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xE1, 0xFC, 0xF1, 0xFD, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xEA, 0xFA, 0xF1, 0xFA, 0xFD, 0xFF, 0xFD, 0xFE, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFD, 0xFE, 0xFE, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xFE, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xF7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFD, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xBA, 0xFB, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0xFB, 0xF4, 0xFE, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFB, 0xFB, 0xF3, 0xFD, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFE, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xEC, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFE, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xF9, 0xFD, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFD, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFC, 0xFE, 0xFB, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFC, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xF8, 0xFE, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xF5, 0xFB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFE, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFD, 0xFE, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xF9, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x9C, 0xA3, 0x80, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x96, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x5A, 0x4F, 0x85, 0x57, 0x55, 0x50, 0x6F, -+ 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x93, 0x88, 0x12, 0x00, 0x6A, 0x91, 0x01, 0x00, 0xB3, 0x79, 0x01, 0x00, -+ 0xDF, 0x01, 0x22, 0x00, 0xD0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x01, 0x8F, -+ 0x0E, 0x12, 0x0E, 0x6B, 0x87, 0x40, 0x39, 0x44, 0x3C, 0x38, 0x80, 0x41, -+ 0x9F, 0x86, 0x80, 0x22, 0xEA, 0xBC, 0x80, 0x1C, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x84, 0x02, 0x04, 0x06, 0x80, 0x81, 0x82, 0x83, 0x80, 0x02, 0x04, 0x06, -+ 0x81, 0x82, 0x83, 0x84, 0x80, 0x02, 0x81, 0x04, 0x82, 0x83, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, -+ 0x04, 0x06, 0x80, 0x81, 0x82, 0x83, 0x0A, 0x0C, 0x84, 0x85, 0x86, 0x87, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x06, 0x80, 0x81, -+ 0x82, 0x83, 0x0A, 0x0C, 0x84, 0x85, 0x86, 0x87, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x83, 0x02, 0x82, 0x04, 0x80, 0x81, 0x00, 0x00, 0x80, 0x02, 0x81, 0x04, -+ 0x82, 0x06, 0x08, 0x0C, 0x83, 0x0A, 0x85, 0x86, 0x84, 0x0E, 0x87, 0x10, -+ 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x8A, 0x02, 0x8B, 0x04, 0x8C, 0x8D, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x87, 0x02, 0x85, 0x04, 0x86, 0x06, 0x88, 0x89, -+}; -+ -+static const u8 vp8_mv_update_prob[2][19] = { -+ { 237, 246, 253, 253, 254, 254, 254, 254, 254, -+ 254, 254, 254, 254, 254, 250, 250, 252, 254, 254 }, -+ { 231, 243, 245, 253, 254, 254, 254, 254, 254, -+ 254, 254, 254, 254, 254, 251, 251, 254, 254, 254 } -+}; -+ -+static uint8_t read_bits(struct cedrus_dev *dev, unsigned int bits_count, -+ unsigned int probability) -+{ -+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, -+ VE_H264_TRIGGER_TYPE_VP8_GET_BITS | -+ VE_H264_TRIGGER_TYPE_BIN_LENS(bits_count) | -+ VE_H264_TRIGGER_TYPE_PROBABILITY(probability)); -+ -+ while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VLD_BUSY) -+ ; -+ -+ return cedrus_read(dev, VE_H264_BASIC_BITS); -+} -+ -+static void get_delta_q(struct cedrus_dev *dev) -+{ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 4, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+ } -+} -+ -+static void process_segmentation_info(struct cedrus_dev *dev) -+{ -+ int update = read_bits(dev, 1, VP8_PROB_HALF); -+ int i; -+ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 1, VP8_PROB_HALF); -+ -+ for (i = 0; i < 4; i++) -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 7, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+ } -+ -+ for (i = 0; i < 4; i++) -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 6, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+ } -+ } -+ -+ if (update) -+ for (i = 0; i < 3; i++) -+ if (read_bits(dev, 1, VP8_PROB_HALF)) -+ read_bits(dev, 8, VP8_PROB_HALF); -+} -+ -+static void process_ref_lf_delta_info(struct cedrus_dev *dev) -+{ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ int i; -+ -+ for (i = 0; i < 4; i++) -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 6, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+ } -+ -+ for (i = 0; i < 4; i++) -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 6, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+ } -+ } -+} -+ -+static void process_ref_frame_info(struct cedrus_dev *dev) -+{ -+ u8 refresh_golden_frame = read_bits(dev, 1, VP8_PROB_HALF); -+ u8 refresh_alt_ref_frame = read_bits(dev, 1, VP8_PROB_HALF); -+ -+ if (!refresh_golden_frame) -+ read_bits(dev, 2, VP8_PROB_HALF); -+ -+ if (!refresh_alt_ref_frame) -+ read_bits(dev, 2, VP8_PROB_HALF); -+ -+ read_bits(dev, 1, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+} -+ -+static void cedrus_read_header(struct cedrus_dev *dev, -+ const struct v4l2_ctrl_vp8_frame_header *slice) -+{ -+ int i, j; -+ -+ if (VP8_FRAME_IS_KEY_FRAME(slice)) { -+ read_bits(dev, 1, VP8_PROB_HALF); -+ read_bits(dev, 1, VP8_PROB_HALF); -+ } -+ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) -+ process_segmentation_info(dev); -+ -+ read_bits(dev, 1, VP8_PROB_HALF); -+ read_bits(dev, 6, VP8_PROB_HALF); -+ read_bits(dev, 3, VP8_PROB_HALF); -+ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) -+ process_ref_lf_delta_info(dev); -+ -+ read_bits(dev, 2, VP8_PROB_HALF); -+ read_bits(dev, 7, VP8_PROB_HALF); -+ -+ get_delta_q(dev); -+ get_delta_q(dev); -+ get_delta_q(dev); -+ get_delta_q(dev); -+ get_delta_q(dev); -+ -+ if (!VP8_FRAME_IS_KEY_FRAME(slice)) -+ process_ref_frame_info(dev); -+ -+ read_bits(dev, 1, VP8_PROB_HALF); -+ -+ if (!VP8_FRAME_IS_KEY_FRAME(slice)) -+ read_bits(dev, 1, VP8_PROB_HALF); -+ -+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, VE_H264_TRIGGER_TYPE_VP8_UPDATE_COEF); -+ while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VP8_UPPROB_BUSY) -+ ; -+ -+ cedrus_write(dev, VE_H264_STATUS, VE_H264_CTRL_INT_MASK); -+ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) -+ read_bits(dev, 8, VP8_PROB_HALF); -+ -+ if (!VP8_FRAME_IS_KEY_FRAME(slice)) { -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ } -+ -+ if (read_bits(dev, 1, VP8_PROB_HALF)) { -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ read_bits(dev, 8, VP8_PROB_HALF); -+ } -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < 19; j++) -+ if (read_bits(dev, 1, vp8_mv_update_prob[i][j])) -+ read_bits(dev, 7, VP8_PROB_HALF); -+ } -+} -+ -+static void cedrus_vp8_update_probs(const struct v4l2_ctrl_vp8_frame_header *slice, -+ u8 *prob_table) -+{ -+ int i, j, k; -+ -+ memcpy(&prob_table[0x1008], slice->entropy_header.y_mode_probs, 4); -+ memcpy(&prob_table[0x1010], slice->entropy_header.uv_mode_probs, 3); -+ -+ memcpy(&prob_table[0x1018], slice->segment_header.segment_probs, 3); -+ -+ prob_table[0x101c] = slice->prob_skip_false; -+ prob_table[0x101d] = slice->prob_intra; -+ prob_table[0x101e] = slice->prob_last; -+ prob_table[0x101f] = slice->prob_gf; -+ -+ memcpy(&prob_table[0x1020], slice->entropy_header.mv_probs[0], 19); -+ memcpy(&prob_table[0x1040], slice->entropy_header.mv_probs[1], 19); -+ -+ for (i = 0; i < 4; ++i) -+ for (j = 0; j < 8; ++j) -+ for (k = 0; k < 3; ++k) -+ memcpy(&prob_table[i * 512 + j * 64 + k * 16], -+ slice->entropy_header.coeff_probs[i][j][k], 11); -+} -+ -+static enum cedrus_irq_status -+cedrus_vp8_irq_status(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ u32 reg = cedrus_read(dev, VE_H264_STATUS); -+ -+ if (reg & (VE_H264_STATUS_DECODE_ERR_INT | -+ VE_H264_STATUS_VLD_DATA_REQ_INT)) -+ return CEDRUS_IRQ_ERROR; -+ -+ if (reg & VE_H264_CTRL_SLICE_DECODE_INT) -+ return CEDRUS_IRQ_OK; -+ -+ return CEDRUS_IRQ_NONE; -+} -+ -+static void cedrus_vp8_irq_clear(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ cedrus_write(dev, VE_H264_STATUS, -+ VE_H264_STATUS_INT_MASK); -+} -+ -+static void cedrus_vp8_irq_disable(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ u32 reg = cedrus_read(dev, VE_H264_CTRL); -+ -+ cedrus_write(dev, VE_H264_CTRL, -+ reg & ~VE_H264_CTRL_INT_MASK); -+} -+ -+static void cedrus_vp8_setup(struct cedrus_ctx *ctx, -+ struct cedrus_run *run) -+{ -+ const struct v4l2_ctrl_vp8_frame_header *slice = run->vp8.slice_params; -+ struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; -+ struct vb2_buffer *src_buf = &run->src->vb2_buf; -+ struct cedrus_dev *dev = ctx->dev; -+ dma_addr_t luma_addr, chroma_addr; -+ dma_addr_t src_buf_addr; -+ int header_size; -+ int qindex; -+ u32 reg; -+ -+ cedrus_engine_enable(ctx, CEDRUS_CODEC_VP8); -+ -+ cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8); -+ -+ cedrus_vp8_update_probs(slice, ctx->codec.vp8.entropy_probs_buf); -+ -+ reg = slice->first_part_size * 8; -+ cedrus_write(dev, VE_VP8_FIRST_DATA_PART_LEN, reg); -+ -+ header_size = VP8_FRAME_IS_KEY_FRAME(slice) ? 10 : 3; -+ -+ reg = slice->first_part_size + header_size; -+ cedrus_write(dev, VE_VP8_PART_SIZE_OFFSET, reg); -+ -+ reg = vb2_plane_size(src_buf, 0) * 8; -+ cedrus_write(dev, VE_H264_VLD_LEN, reg); -+ -+ /* -+ * FIXME: There is a problem if frame header is skipped (adding -+ * first_part_header_bits to offset). It seems that functions -+ * for parsing bitstreams change internal state of VPU in some -+ * way that can't be otherwise set. Maybe this can be bypassed -+ * by somehow fixing probability table buffer? -+ */ -+ reg = header_size * 8; -+ cedrus_write(dev, VE_H264_VLD_OFFSET, reg); -+ -+ src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); -+ cedrus_write(dev, VE_H264_VLD_END, -+ src_buf_addr + vb2_get_plane_payload(src_buf, 0)); -+ cedrus_write(dev, VE_H264_VLD_ADDR, -+ VE_H264_VLD_ADDR_VAL(src_buf_addr) | -+ VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID | -+ VE_H264_VLD_ADDR_LAST); -+ -+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, -+ VE_H264_TRIGGER_TYPE_INIT_SWDEC); -+ -+ cedrus_write(dev, VE_VP8_ENTROPY_PROBS_ADDR, -+ ctx->codec.vp8.entropy_probs_buf_dma); -+ -+ reg = 0; -+ switch (slice->version) { -+ case 1: -+ reg |= VE_VP8_PPS_FILTER_TYPE_SIMPLE; -+ reg |= VE_VP8_PPS_BILINEAR_MC_FILTER; -+ break; -+ case 2: -+ reg |= VE_VP8_PPS_LPF_DISABLE; -+ reg |= VE_VP8_PPS_BILINEAR_MC_FILTER; -+ break; -+ case 3: -+ reg |= VE_VP8_PPS_LPF_DISABLE; -+ reg |= VE_VP8_PPS_FULL_PIXEL; -+ break; -+ } -+ if (slice->segment_header.flags & V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP) -+ reg |= VE_VP8_PPS_UPDATE_MB_SEGMENTATION_MAP; -+ if (!(slice->segment_header.flags & V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE)) -+ reg |= VE_VP8_PPS_MB_SEGMENT_ABS_DELTA; -+ if (slice->segment_header.flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED) -+ reg |= VE_VP8_PPS_SEGMENTATION_ENABLE; -+ if (ctx->codec.vp8.last_filter_type) -+ reg |= VE_VP8_PPS_LAST_LOOP_FILTER_SIMPLE; -+ reg |= VE_VP8_PPS_SHARPNESS_LEVEL(slice->lf_header.sharpness_level); -+ if (slice->lf_header.flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE) -+ reg |= VE_VP8_PPS_LOOP_FILTER_SIMPLE; -+ reg |= VE_VP8_PPS_LOOP_FILTER_LEVEL(slice->lf_header.level); -+ if (slice->lf_header.flags & V4L2_VP8_LF_HEADER_ADJ_ENABLE) -+ reg |= VE_VP8_PPS_MODE_REF_LF_DELTA_ENABLE; -+ if (slice->lf_header.flags & V4L2_VP8_LF_HEADER_DELTA_UPDATE) -+ reg |= VE_VP8_PPS_MODE_REF_LF_DELTA_UPDATE; -+ reg |= VE_VP8_PPS_TOKEN_PARTITION(ilog2(slice->num_dct_parts)); -+ if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF) -+ reg |= VE_VP8_PPS_MB_NO_COEFF_SKIP; -+ reg |= VE_VP8_PPS_RELOAD_ENTROPY_PROBS; -+ if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN) -+ reg |= VE_VP8_PPS_GOLDEN_SIGN_BIAS; -+ if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT) -+ reg |= VE_VP8_PPS_ALTREF_SIGN_BIAS; -+ if (ctx->codec.vp8.last_frame_p_type) -+ reg |= VE_VP8_PPS_LAST_PIC_TYPE_P_FRAME; -+ reg |= VE_VP8_PPS_LAST_SHARPNESS_LEVEL(ctx->codec.vp8.last_sharpness_level); -+ if (!(slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) -+ reg |= VE_VP8_PPS_PIC_TYPE_P_FRAME; -+ cedrus_write(dev, VE_VP8_PPS, reg); -+ -+ cedrus_read_header(dev, slice); -+ -+ /* reset registers changed by HW */ -+ cedrus_write(dev, VE_H264_CUR_MB_NUM, 0); -+ cedrus_write(dev, VE_H264_MB_ADDR, 0); -+ cedrus_write(dev, VE_H264_ERROR_CASE, 0); -+ -+ reg = 0; -+ reg |= VE_VP8_QP_INDEX_DELTA_UVAC(slice->quant_header.uv_ac_delta); -+ reg |= VE_VP8_QP_INDEX_DELTA_UVDC(slice->quant_header.uv_dc_delta); -+ reg |= VE_VP8_QP_INDEX_DELTA_Y2AC(slice->quant_header.y2_ac_delta); -+ reg |= VE_VP8_QP_INDEX_DELTA_Y2DC(slice->quant_header.y2_dc_delta); -+ reg |= VE_VP8_QP_INDEX_DELTA_Y1DC(slice->quant_header.y_dc_delta); -+ reg |= VE_VP8_QP_INDEX_DELTA_BASE_QINDEX(slice->quant_header.y_ac_qi); -+ cedrus_write(dev, VE_VP8_QP_INDEX_DELTA, reg); -+ -+ reg = 0; -+ reg |= VE_VP8_FSIZE_WIDTH(slice->width); -+ reg |= VE_VP8_FSIZE_HEIGHT(slice->height); -+ cedrus_write(dev, VE_VP8_FSIZE, reg); -+ -+ reg = 0; -+ reg |= VE_VP8_PICSIZE_WIDTH(slice->width); -+ reg |= VE_VP8_PICSIZE_HEIGHT(slice->height); -+ cedrus_write(dev, VE_VP8_PICSIZE, reg); -+ -+ reg = 0; -+ reg |= VE_VP8_SEGMENT3(slice->segment_header.quant_update[3]); -+ reg |= VE_VP8_SEGMENT2(slice->segment_header.quant_update[2]); -+ reg |= VE_VP8_SEGMENT1(slice->segment_header.quant_update[1]); -+ reg |= VE_VP8_SEGMENT0(slice->segment_header.quant_update[0]); -+ cedrus_write(dev, VE_VP8_SEGMENT_FEAT_MB_LV0, reg); -+ -+ reg = 0; -+ reg |= VE_VP8_SEGMENT3(slice->segment_header.lf_update[3]); -+ reg |= VE_VP8_SEGMENT2(slice->segment_header.lf_update[2]); -+ reg |= VE_VP8_SEGMENT1(slice->segment_header.lf_update[1]); -+ reg |= VE_VP8_SEGMENT0(slice->segment_header.lf_update[0]); -+ cedrus_write(dev, VE_VP8_SEGMENT_FEAT_MB_LV1, reg); -+ -+ reg = 0; -+ reg |= VE_VP8_LF_DELTA3(slice->lf_header.ref_frm_delta[3]); -+ reg |= VE_VP8_LF_DELTA2(slice->lf_header.ref_frm_delta[2]); -+ reg |= VE_VP8_LF_DELTA1(slice->lf_header.ref_frm_delta[1]); -+ reg |= VE_VP8_LF_DELTA0(slice->lf_header.ref_frm_delta[0]); -+ cedrus_write(dev, VE_VP8_REF_LF_DELTA, reg); -+ -+ reg = 0; -+ reg |= VE_VP8_LF_DELTA3(slice->lf_header.mb_mode_delta[3]); -+ reg |= VE_VP8_LF_DELTA2(slice->lf_header.mb_mode_delta[2]); -+ reg |= VE_VP8_LF_DELTA1(slice->lf_header.mb_mode_delta[1]); -+ reg |= VE_VP8_LF_DELTA0(slice->lf_header.mb_mode_delta[0]); -+ cedrus_write(dev, VE_VP8_MODE_LF_DELTA, reg); -+ -+ luma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 0); -+ chroma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 1); -+ cedrus_write(dev, VE_VP8_REC_LUMA, luma_addr); -+ cedrus_write(dev, VE_VP8_REC_CHROMA, chroma_addr); -+ -+ qindex = vb2_find_timestamp(cap_q, slice->last_frame_ts, 0); -+ if (qindex >= 0) { -+ luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0); -+ chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1); -+ cedrus_write(dev, VE_VP8_FWD_LUMA, luma_addr); -+ cedrus_write(dev, VE_VP8_FWD_CHROMA, chroma_addr); -+ } else { -+ cedrus_write(dev, VE_VP8_FWD_LUMA, 0); -+ cedrus_write(dev, VE_VP8_FWD_CHROMA, 0); -+ } -+ -+ qindex = vb2_find_timestamp(cap_q, slice->golden_frame_ts, 0); -+ if (qindex >= 0) { -+ luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0); -+ chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1); -+ cedrus_write(dev, VE_VP8_BWD_LUMA, luma_addr); -+ cedrus_write(dev, VE_VP8_BWD_CHROMA, chroma_addr); -+ } else { -+ cedrus_write(dev, VE_VP8_BWD_LUMA, 0); -+ cedrus_write(dev, VE_VP8_BWD_CHROMA, 0); -+ } -+ -+ qindex = vb2_find_timestamp(cap_q, slice->alt_frame_ts, 0); -+ if (qindex >= 0) { -+ luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0); -+ chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1); -+ cedrus_write(dev, VE_VP8_ALT_LUMA, luma_addr); -+ cedrus_write(dev, VE_VP8_ALT_CHROMA, chroma_addr); -+ } else { -+ cedrus_write(dev, VE_VP8_ALT_LUMA, 0); -+ cedrus_write(dev, VE_VP8_ALT_CHROMA, 0); -+ } -+ -+ cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8 | -+ VE_H264_CTRL_DECODE_ERR_INT | -+ VE_H264_CTRL_SLICE_DECODE_INT); -+ -+ if (slice->lf_header.level) { -+ ctx->codec.vp8.last_filter_type = -+ !!(slice->lf_header.flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE); -+ ctx->codec.vp8.last_frame_p_type = -+ !VP8_FRAME_IS_KEY_FRAME(slice); -+ ctx->codec.vp8.last_sharpness_level = -+ slice->lf_header.sharpness_level; -+ } -+} -+ -+static int cedrus_vp8_start(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ ctx->codec.vp8.entropy_probs_buf = -+ dma_alloc_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE, -+ &ctx->codec.vp8.entropy_probs_buf_dma, -+ GFP_KERNEL); -+ if (!ctx->codec.vp8.entropy_probs_buf) -+ return -ENOMEM; -+ -+ memcpy(&ctx->codec.vp8.entropy_probs_buf[2048], -+ prob_table_init, sizeof(prob_table_init)); -+ -+ return 0; -+} -+ -+static void cedrus_vp8_stop(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ cedrus_engine_disable(dev); -+ -+ dma_free_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE, -+ ctx->codec.vp8.entropy_probs_buf, -+ ctx->codec.vp8.entropy_probs_buf_dma); -+} -+ -+static void cedrus_vp8_trigger(struct cedrus_ctx *ctx) -+{ -+ struct cedrus_dev *dev = ctx->dev; -+ -+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, -+ VE_H264_TRIGGER_TYPE_VP8_SLICE_DECODE); -+} -+ -+struct cedrus_dec_ops cedrus_dec_ops_vp8 = { -+ .irq_clear = cedrus_vp8_irq_clear, -+ .irq_disable = cedrus_vp8_irq_disable, -+ .irq_status = cedrus_vp8_irq_status, -+ .setup = cedrus_vp8_setup, -+ .start = cedrus_vp8_start, -+ .stop = cedrus_vp8_stop, -+ .trigger = cedrus_vp8_trigger, -+}; diff --git a/projects/Allwinner/patches/linux/0006-ASoC-sun4i-i2s-Set-sign-extend-sample.patch b/projects/Allwinner/patches/linux/0006-ASoC-sun4i-i2s-Set-sign-extend-sample.patch new file mode 100644 index 0000000000..b4e6c89dec --- /dev/null +++ b/projects/Allwinner/patches/linux/0006-ASoC-sun4i-i2s-Set-sign-extend-sample.patch @@ -0,0 +1,86 @@ +From fe1ae019879d51633d8dcd705117c70b701b77e9 Mon Sep 17 00:00:00 2001 +From: Marcus Cooper +Date: Fri, 30 Oct 2020 15:46:38 +0100 +Subject: [PATCH 06/44] ASoC: sun4i-i2s: Set sign extend sample +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On the newer SoCs such as the H3 and A64 this is set by default +to transfer a 0 after each sample in each slot. However the A10 +and A20 SoCs that this driver was developed on had a default +setting where it padded the audio gain with zeros. + +This isn't a problem while we have only support for 16bit audio +but with larger sample resolution rates in the pipeline then SEXT +bits should be cleared so that they also pad at the LSB. Without +this the audio gets distorted. + +Set sign extend sample for all the sunxi generations even if they +are not affected. This will keep consistency and avoid relying on +default. + +Signed-off-by: Marcus Cooper +Reviewed-by: Chen-Yu Tsai +Acked-by: Maxime Ripard +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-6-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -48,6 +48,9 @@ + #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) + + #define SUN4I_I2S_FMT1_REG 0x08 ++#define SUN4I_I2S_FMT1_REG_SEXT_MASK BIT(8) ++#define SUN4I_I2S_FMT1_REG_SEXT(sext) ((sext) << 8) ++ + #define SUN4I_I2S_FIFO_TX_REG 0x0c + #define SUN4I_I2S_FIFO_RX_REG 0x10 + +@@ -105,6 +108,9 @@ + #define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7) + #define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7) + ++#define SUN8I_I2S_FMT1_REG_SEXT_MASK GENMASK(5, 4) ++#define SUN8I_I2S_FMT1_REG_SEXT(sext) ((sext) << 4) ++ + #define SUN8I_I2S_INT_STA_REG 0x0c + #define SUN8I_I2S_FIFO_TX_REG 0x20 + +@@ -686,6 +692,7 @@ static int sun4i_i2s_set_soc_fmt(const s + } + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, + SUN4I_I2S_CTRL_MODE_MASK, val); ++ + return 0; + } + +@@ -788,6 +795,11 @@ static int sun8i_i2s_set_soc_fmt(const s + SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT, + val); + ++ /* Set sign extension to pad out LSB with 0 */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG, ++ SUN8I_I2S_FMT1_REG_SEXT_MASK, ++ SUN8I_I2S_FMT1_REG_SEXT(0)); ++ + return 0; + } + +@@ -890,6 +902,11 @@ static int sun50i_h6_i2s_set_soc_fmt(con + SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT, + val); + ++ /* Set sign extension to pad out LSB with 0 */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG, ++ SUN8I_I2S_FMT1_REG_SEXT_MASK, ++ SUN8I_I2S_FMT1_REG_SEXT(0)); ++ + return 0; + } + diff --git a/projects/Allwinner/patches/linux/0007-ASoC-sun4i-i2s-Add-20-and-24-bit-support.patch b/projects/Allwinner/patches/linux/0007-ASoC-sun4i-i2s-Add-20-and-24-bit-support.patch new file mode 100644 index 0000000000..0205308b31 --- /dev/null +++ b/projects/Allwinner/patches/linux/0007-ASoC-sun4i-i2s-Add-20-and-24-bit-support.patch @@ -0,0 +1,61 @@ +From 9c2121fe514f12c830bceea7b33872fa67af3e97 Mon Sep 17 00:00:00 2001 +From: Marcus Cooper +Date: Fri, 30 Oct 2020 15:46:39 +0100 +Subject: [PATCH 07/44] ASoC: sun4i-i2s: Add 20 and 24 bit support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extend the functionality of the driver to include support of 20 and +24 bits per sample. + +Signed-off-by: Marcus Cooper +Acked-by: Maxime Ripard +Reviewed-by: Chen-Yu Tsai +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-7-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -600,6 +600,9 @@ static int sun4i_i2s_hw_params(struct sn + case 16: + width = DMA_SLAVE_BUSWIDTH_2_BYTES; + break; ++ case 32: ++ width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ break; + default: + dev_err(dai->dev, "Unsupported physical sample width: %d\n", + params_physical_width(params)); +@@ -1081,6 +1084,10 @@ static int sun4i_i2s_dai_probe(struct sn + return 0; + } + ++#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ ++ SNDRV_PCM_FMTBIT_S20_LE | \ ++ SNDRV_PCM_FMTBIT_S24_LE) ++ + static struct snd_soc_dai_driver sun4i_i2s_dai = { + .probe = sun4i_i2s_dai_probe, + .capture = { +@@ -1088,14 +1095,14 @@ static struct snd_soc_dai_driver sun4i_i + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, +- .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .formats = SUN4I_FORMATS, + }, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, +- .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .formats = SUN4I_FORMATS, + }, + .ops = &sun4i_i2s_dai_ops, + .symmetric_rates = 1, diff --git a/projects/Allwinner/patches/linux/0008-ASoC-sun4i-i2s-Fix-sun8i-volatile-regs.patch b/projects/Allwinner/patches/linux/0008-ASoC-sun4i-i2s-Fix-sun8i-volatile-regs.patch new file mode 100644 index 0000000000..8c4dd63320 --- /dev/null +++ b/projects/Allwinner/patches/linux/0008-ASoC-sun4i-i2s-Fix-sun8i-volatile-regs.patch @@ -0,0 +1,49 @@ +From 9f0cbed8e957216d58a2dd5c9c8e795ec39004ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 30 Oct 2020 15:46:40 +0100 +Subject: [PATCH 08/44] ASoC: sun4i-i2s: Fix sun8i volatile regs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The FIFO TX reg is volatile and sun8i i2s register +mapping is different from sun4i. + +Even if in this case it's doesn't create an issue, +Avoid setting some regs that are undefined in sun8i. + +Acked-by: Maxime Ripard +Reviewed-by: Chen-Yu Tsai +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-8-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -1162,12 +1162,19 @@ static bool sun8i_i2s_rd_reg(struct devi + + static bool sun8i_i2s_volatile_reg(struct device *dev, unsigned int reg) + { +- if (reg == SUN8I_I2S_INT_STA_REG) ++ switch (reg) { ++ case SUN4I_I2S_FIFO_CTRL_REG: ++ case SUN4I_I2S_FIFO_RX_REG: ++ case SUN4I_I2S_FIFO_STA_REG: ++ case SUN4I_I2S_RX_CNT_REG: ++ case SUN4I_I2S_TX_CNT_REG: ++ case SUN8I_I2S_FIFO_TX_REG: ++ case SUN8I_I2S_INT_STA_REG: + return true; +- if (reg == SUN8I_I2S_FIFO_TX_REG) +- return false; + +- return sun4i_i2s_volatile_reg(dev, reg); ++ default: ++ return false; ++ } + } + + static const struct reg_default sun4i_i2s_reg_defaults[] = { diff --git a/projects/Allwinner/patches/linux/0009-ASoC-sun4i-i2s-Fix-setting-of-FIFO-modes.patch b/projects/Allwinner/patches/linux/0009-ASoC-sun4i-i2s-Fix-setting-of-FIFO-modes.patch new file mode 100644 index 0000000000..14cc889b76 --- /dev/null +++ b/projects/Allwinner/patches/linux/0009-ASoC-sun4i-i2s-Fix-setting-of-FIFO-modes.patch @@ -0,0 +1,53 @@ +From de8ff7b3ac4736f5aa0c55968170bd449e46c88f Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Fri, 30 Oct 2020 15:46:41 +0100 +Subject: [PATCH 09/44] ASoC: sun4i-i2s: Fix setting of FIFO modes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Because SUN4I_I2S_FIFO_CTRL_REG is volatile, writes done while the +regmap is cache-only are ignored. To work around this, move the +configuration to a callback that runs while the ASoC core has a +runtime PM reference to the device. + +Signed-off-by: Samuel Holland +Reviewed-by: Chen-Yu Tsai +Acked-by: Maxime Ripard +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-9-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -596,6 +596,13 @@ static int sun4i_i2s_hw_params(struct sn + return ret; + } + ++ /* Set significant bits in our FIFOs */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, ++ SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK | ++ SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK, ++ SUN4I_I2S_FIFO_CTRL_TX_MODE(1) | ++ SUN4I_I2S_FIFO_CTRL_RX_MODE(1)); ++ + switch (params_physical_width(params)) { + case 16: + width = DMA_SLAVE_BUSWIDTH_2_BYTES; +@@ -924,13 +931,6 @@ static int sun4i_i2s_set_fmt(struct snd_ + return ret; + } + +- /* Set significant bits in our FIFOs */ +- regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, +- SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK | +- SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK, +- SUN4I_I2S_FIFO_CTRL_TX_MODE(1) | +- SUN4I_I2S_FIFO_CTRL_RX_MODE(1)); +- + i2s->format = fmt; + + return 0; diff --git a/projects/Allwinner/patches/linux/0010-ASoC-sun4i-i2s-fix-coding-style-for-callback-definit.patch b/projects/Allwinner/patches/linux/0010-ASoC-sun4i-i2s-fix-coding-style-for-callback-definit.patch new file mode 100644 index 0000000000..15899dd1e6 --- /dev/null +++ b/projects/Allwinner/patches/linux/0010-ASoC-sun4i-i2s-fix-coding-style-for-callback-definit.patch @@ -0,0 +1,44 @@ +From 82b0eb24d554180fdea8a254553dcce22085cc74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Fri, 30 Oct 2020 15:46:42 +0100 +Subject: [PATCH 10/44] ASoC: sun4i-i2s: fix coding-style for callback + definition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Checkpatch script produces warning: +WARNING: function definition argument 'const struct sun4i_i2s *' +should also have an identifier name. + +Let's fix this by adding identifier name to get_bclk_parent_rate() +and set_fmt() callback definition. + +Acked-by: Maxime Ripard +Signed-off-by: Clément Péron +Link: https://lore.kernel.org/r/20201030144648.397824-10-peron.clem@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/sunxi/sun4i-i2s.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -180,7 +180,7 @@ struct sun4i_i2s_quirks { + const struct sun4i_i2s_clk_div *mclk_dividers; + unsigned int num_mclk_dividers; + +- unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *); ++ unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *i2s); + int (*get_sr)(unsigned int width); + int (*get_wss)(unsigned int width); + +@@ -192,7 +192,7 @@ struct sun4i_i2s_quirks { + int (*set_chan_cfg)(const struct sun4i_i2s *i2s, + unsigned int channels, unsigned int slots, + unsigned int slot_width); +- int (*set_fmt)(const struct sun4i_i2s *, unsigned int); ++ int (*set_fmt)(const struct sun4i_i2s *i2s, unsigned int fmt); + }; + + struct sun4i_i2s { diff --git a/projects/Allwinner/devices/R40/patches/linux/0018-r40-enable-deinterlace.patch b/projects/Allwinner/patches/linux/0011-ARM-dts-sun8i-r40-Add-deinterlace-node.patch similarity index 51% rename from projects/Allwinner/devices/R40/patches/linux/0018-r40-enable-deinterlace.patch rename to projects/Allwinner/patches/linux/0011-ARM-dts-sun8i-r40-Add-deinterlace-node.patch index 332325031d..ee4b752ba2 100644 --- a/projects/Allwinner/devices/R40/patches/linux/0018-r40-enable-deinterlace.patch +++ b/projects/Allwinner/patches/linux/0011-ARM-dts-sun8i-r40-Add-deinterlace-node.patch @@ -1,8 +1,23 @@ -diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi -index 7907569e7b5c..d5ad3b9efd12 100644 +From 51ebc019df15b46d109bafe7068ebb6fe0b266b5 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 6 Jan 2021 19:19:01 +0100 +Subject: [PATCH 11/44] ARM: dts: sun8i: r40: Add deinterlace node + +R40 contains deinterlace core compatible to that in H3. One peculiarity +is that RAM gate is shared with CSI1. User manual states it's separate +but that's not true. Shared gate was verified with BSP Linux code check +and with runtime tests (CPU crashed if CSI1 gate was not ungated). + +Signed-off-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +Link: https://lore.kernel.org/r/20210106181901.1324075-3-jernej.skrabec@siol.net +--- + arch/arm/boot/dts/sun8i-r40.dtsi | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi -@@ -190,6 +190,25 @@ mixer1_out_tcon_top: endpoint { +@@ -190,6 +190,25 @@ }; }; diff --git a/projects/Allwinner/devices/H5/patches/linux/18-enable-deinterlace.patch b/projects/Allwinner/patches/linux/0012-arm64-dts-allwinner-h5-Add-deinterlace-node.patch similarity index 53% rename from projects/Allwinner/devices/H5/patches/linux/18-enable-deinterlace.patch rename to projects/Allwinner/patches/linux/0012-arm64-dts-allwinner-h5-Add-deinterlace-node.patch index a6e47d6316..5bcbc7e9c5 100644 --- a/projects/Allwinner/devices/H5/patches/linux/18-enable-deinterlace.patch +++ b/projects/Allwinner/patches/linux/0012-arm64-dts-allwinner-h5-Add-deinterlace-node.patch @@ -1,8 +1,22 @@ -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -index 10489e508695..578a63dedf46 100644 +From 7166a5b6ab1f3d9ba0f5236b738525e828138c8e Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 6 Jan 2021 19:25:23 +0100 +Subject: [PATCH 12/44] arm64: dts: allwinner: h5: Add deinterlace node + +Deinterlace core is completely compatible to H3. + +Add a node for it. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +Link: https://lore.kernel.org/r/20210106182523.1325796-1-jernej.skrabec@siol.net +--- + arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -@@ -121,6 +121,19 @@ crypto: crypto@1c15000 { +@@ -121,6 +121,19 @@ resets = <&ccu RST_BUS_CE>; }; diff --git a/projects/Allwinner/patches/linux/0013-drm-sun4i-csc-Rework-DE3-CSC-macros.patch b/projects/Allwinner/patches/linux/0013-drm-sun4i-csc-Rework-DE3-CSC-macros.patch new file mode 100644 index 0000000000..f8fdf0b2ff --- /dev/null +++ b/projects/Allwinner/patches/linux/0013-drm-sun4i-csc-Rework-DE3-CSC-macros.patch @@ -0,0 +1,40 @@ +From dcd9635dc6027b04a64e19ebb3dc15aaae082400 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 18 Feb 2020 19:24:29 +0100 +Subject: [PATCH 13/44] drm/sun4i: csc: Rework DE3 CSC macros + +Rework DE3 CSC macros to take just one coordinate instead of two. This +will make its usage easier in subsequent commit. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_csc.c | 2 +- + drivers/gpu/drm/sun4i/sun8i_mixer.h | 6 ++---- + 2 files changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -194,7 +194,7 @@ static void sun8i_de3_ccsc_set_coefficie + return; + } + +- base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0, 0); ++ base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); + regmap_bulk_write(map, base_reg, table, 12); + } + +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h +@@ -50,10 +50,8 @@ + #define SUN8I_MIXER_BLEND_CK_MIN(base, x) ((base) + 0xe0 + 0x04 * (x)) + #define SUN8I_MIXER_BLEND_OUTCTL(base) ((base) + 0xfc) + #define SUN50I_MIXER_BLEND_CSC_CTL(base) ((base) + 0x100) +-#define SUN50I_MIXER_BLEND_CSC_COEFF(base, layer, x, y) \ +- ((base) + 0x110 + (layer) * 0x30 + (x) * 0x10 + 4 * (y)) +-#define SUN50I_MIXER_BLEND_CSC_CONST(base, layer, i) \ +- ((base) + 0x110 + (layer) * 0x30 + (i) * 0x10 + 0x0c) ++#define SUN50I_MIXER_BLEND_CSC_COEFF(base, layer, x) \ ++ ((base) + 0x110 + (layer) * 0x30 + (x) * 4) + + #define SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK GENMASK(12, 8) + #define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe) BIT(8 + pipe) diff --git a/projects/Allwinner/patches/linux/0014-drm-sun4i-de2-de3-Remove-redundant-CSC-matrices.patch b/projects/Allwinner/patches/linux/0014-drm-sun4i-de2-de3-Remove-redundant-CSC-matrices.patch new file mode 100644 index 0000000000..de6c92f2bf --- /dev/null +++ b/projects/Allwinner/patches/linux/0014-drm-sun4i-de2-de3-Remove-redundant-CSC-matrices.patch @@ -0,0 +1,163 @@ +From acdfa534d3fe6759f43c1fe0bcd2fd40f31d3797 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 18 Feb 2020 19:44:33 +0100 +Subject: [PATCH 14/44] drm/sun4i: de2/de3: Remove redundant CSC matrices + +YUV to RGB matrices are almost identical to YVU to RGB matrices. They +only have second and third column reversed. Do that reversion in code in +order to lower amount of static data and redundancy. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_csc.c | 99 +++++++++++-------------------- + 1 file changed, 34 insertions(+), 65 deletions(-) + +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -46,33 +46,6 @@ static const u32 yuv2rgb[2][2][12] = { + }, + }; + +-static const u32 yvu2rgb[2][2][12] = { +- [DRM_COLOR_YCBCR_LIMITED_RANGE] = { +- [DRM_COLOR_YCBCR_BT601] = { +- 0x000004A8, 0x00000662, 0x00000000, 0xFFFC8451, +- 0x000004A8, 0xFFFFFCC0, 0xFFFFFE6F, 0x00021E4D, +- 0x000004A8, 0x00000000, 0x00000811, 0xFFFBACA9, +- }, +- [DRM_COLOR_YCBCR_BT709] = { +- 0x000004A8, 0x0000072B, 0x00000000, 0xFFFC1F99, +- 0x000004A8, 0xFFFFFDDF, 0xFFFFFF26, 0x00013383, +- 0x000004A8, 0x00000000, 0x00000873, 0xFFFB7BEF, +- } +- }, +- [DRM_COLOR_YCBCR_FULL_RANGE] = { +- [DRM_COLOR_YCBCR_BT601] = { +- 0x00000400, 0x0000059B, 0x00000000, 0xFFFD322E, +- 0x00000400, 0xFFFFFD25, 0xFFFFFEA0, 0x00021DD5, +- 0x00000400, 0x00000000, 0x00000716, 0xFFFC74BD, +- }, +- [DRM_COLOR_YCBCR_BT709] = { +- 0x00000400, 0x0000064C, 0x00000000, 0xFFFCD9B4, +- 0x00000400, 0xFFFFFE21, 0xFFFFFF41, 0x00014F96, +- 0x00000400, 0x00000000, 0x0000076C, 0xFFFC49EF, +- } +- }, +-}; +- + /* + * DE3 has a bit different CSC units. Factors are in two's complement format. + * First three factors in a row are multiplication factors which have 17 bits +@@ -123,33 +96,6 @@ static const u32 yuv2rgb_de3[2][2][12] = + }, + }; + +-static const u32 yvu2rgb_de3[2][2][12] = { +- [DRM_COLOR_YCBCR_LIMITED_RANGE] = { +- [DRM_COLOR_YCBCR_BT601] = { +- 0x0002542A, 0x0003312A, 0x00000000, 0xFFC00000, +- 0x0002542A, 0xFFFE5FC3, 0xFFFF376B, 0xFE000000, +- 0x0002542A, 0x00000000, 0x000408D2, 0xFE000000, +- }, +- [DRM_COLOR_YCBCR_BT709] = { +- 0x0002542A, 0x000395E2, 0x00000000, 0xFFC00000, +- 0x0002542A, 0xFFFEEF27, 0xFFFF92D2, 0xFE000000, +- 0x0002542A, 0x00000000, 0x0004398C, 0xFE000000, +- } +- }, +- [DRM_COLOR_YCBCR_FULL_RANGE] = { +- [DRM_COLOR_YCBCR_BT601] = { +- 0x00020000, 0x0002CDD2, 0x00000000, 0x00000000, +- 0x00020000, 0xFFFE925D, 0xFFFF4FCE, 0xFE000000, +- 0x00020000, 0x00000000, 0x00038B43, 0xFE000000, +- }, +- [DRM_COLOR_YCBCR_BT709] = { +- 0x00020000, 0x0003264C, 0x00000000, 0x00000000, +- 0x00020000, 0xFFFF1053, 0xFFFFA018, 0xFE000000, +- 0x00020000, 0x00000000, 0x0003B611, 0xFE000000, +- } +- }, +-}; +- + static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, + enum sun8i_csc_mode mode, + enum drm_color_encoding encoding, +@@ -157,21 +103,30 @@ static void sun8i_csc_set_coefficients(s + { + const u32 *table; + u32 base_reg; ++ int i; ++ ++ table = yuv2rgb[range][encoding]; + + switch (mode) { + case SUN8I_CSC_MODE_YUV2RGB: +- table = yuv2rgb[range][encoding]; ++ base_reg = SUN8I_CSC_COEFF(base, 0); ++ regmap_bulk_write(map, base_reg, table, 12); + break; + case SUN8I_CSC_MODE_YVU2RGB: +- table = yvu2rgb[range][encoding]; ++ for (i = 0; i < 12; i++) { ++ if ((i & 3) == 1) ++ base_reg = SUN8I_CSC_COEFF(base, i + 1); ++ else if ((i & 3) == 2) ++ base_reg = SUN8I_CSC_COEFF(base, i - 1); ++ else ++ base_reg = SUN8I_CSC_COEFF(base, i); ++ regmap_write(map, base_reg, table[i]); ++ } + break; + default: + DRM_WARN("Wrong CSC mode specified.\n"); + return; + } +- +- base_reg = SUN8I_CSC_COEFF(base, 0); +- regmap_bulk_write(map, base_reg, table, 12); + } + + static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, +@@ -180,22 +135,36 @@ static void sun8i_de3_ccsc_set_coefficie + enum drm_color_range range) + { + const u32 *table; +- u32 base_reg; ++ u32 addr; ++ int i; ++ ++ table = yuv2rgb_de3[range][encoding]; + + switch (mode) { + case SUN8I_CSC_MODE_YUV2RGB: +- table = yuv2rgb_de3[range][encoding]; ++ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); ++ regmap_bulk_write(map, addr, table, 12); + break; + case SUN8I_CSC_MODE_YVU2RGB: +- table = yvu2rgb_de3[range][encoding]; ++ for (i = 0; i < 12; i++) { ++ if ((i & 3) == 1) ++ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, ++ layer, ++ i + 1); ++ else if ((i & 3) == 2) ++ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, ++ layer, ++ i - 1); ++ else ++ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, ++ layer, i); ++ regmap_write(map, addr, table[i]); ++ } + break; + default: + DRM_WARN("Wrong CSC mode specified.\n"); + return; + } +- +- base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); +- regmap_bulk_write(map, base_reg, table, 12); + } + + static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable) diff --git a/projects/Allwinner/patches/linux/0015-drm-sun4i-Add-support-for-BT2020-to-DE3.patch b/projects/Allwinner/patches/linux/0015-drm-sun4i-Add-support-for-BT2020-to-DE3.patch new file mode 100644 index 0000000000..f94f13d1b8 --- /dev/null +++ b/projects/Allwinner/patches/linux/0015-drm-sun4i-Add-support-for-BT2020-to-DE3.patch @@ -0,0 +1,62 @@ +From 2c9a7a5a71d5ed6db9ee28a5ccd11f0db45f574d Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 15 Apr 2020 10:24:05 +0200 +Subject: [PATCH 15/44] drm/sun4i: Add support for BT2020 to DE3 + +DE3 supports 10-bit formats, so it's only naturally to also support +BT2020 encoding. + +Add support for it. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_csc.c | 12 +++++++++++- + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 ++ + 2 files changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -69,7 +69,7 @@ static const u32 yuv2rgb[2][2][12] = { + * c20 c21 c22 [d2 const2] + */ + +-static const u32 yuv2rgb_de3[2][2][12] = { ++static const u32 yuv2rgb_de3[2][3][12] = { + [DRM_COLOR_YCBCR_LIMITED_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0002542A, 0x00000000, 0x0003312A, 0xFFC00000, +@@ -80,6 +80,11 @@ static const u32 yuv2rgb_de3[2][2][12] = + 0x0002542A, 0x00000000, 0x000395E2, 0xFFC00000, + 0x0002542A, 0xFFFF92D2, 0xFFFEEF27, 0xFE000000, + 0x0002542A, 0x0004398C, 0x00000000, 0xFE000000, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x0002542A, 0x00000000, 0x00035B7B, 0xFFC00000, ++ 0x0002542A, 0xFFFFA017, 0xFFFEB2FC, 0xFE000000, ++ 0x0002542A, 0x00044896, 0x00000000, 0xFE000000, + } + }, + [DRM_COLOR_YCBCR_FULL_RANGE] = { +@@ -92,6 +97,11 @@ static const u32 yuv2rgb_de3[2][2][12] = + 0x00020000, 0x00000000, 0x0003264C, 0x00000000, + 0x00020000, 0xFFFFA018, 0xFFFF1053, 0xFE000000, + 0x00020000, 0x0003B611, 0x00000000, 0xFE000000, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x00020000, 0x00000000, 0x0002F2FE, 0x00000000, ++ 0x00020000, 0xFFFFABC0, 0xFFFEDB78, 0xFE000000, ++ 0x00020000, 0x0003C346, 0x00000000, 0xFE000000, + } + }, + }; +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -543,6 +543,8 @@ struct sun8i_vi_layer *sun8i_vi_layer_in + + supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) | + BIT(DRM_COLOR_YCBCR_BT709); ++ if (mixer->cfg->is_de3) ++ supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020); + + supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | + BIT(DRM_COLOR_YCBCR_FULL_RANGE); diff --git a/projects/Allwinner/patches/linux/0016-mmc-sunxi-mmc-Ensure-host-is-suspended-during-system.patch b/projects/Allwinner/patches/linux/0016-mmc-sunxi-mmc-Ensure-host-is-suspended-during-system.patch new file mode 100644 index 0000000000..1a4b75baa0 --- /dev/null +++ b/projects/Allwinner/patches/linux/0016-mmc-sunxi-mmc-Ensure-host-is-suspended-during-system.patch @@ -0,0 +1,27 @@ +From e689f3536e632e26166e66eac88728c6653a18b6 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Tue, 12 Jan 2021 23:24:21 -0600 +Subject: [PATCH 16/44] mmc: sunxi-mmc: Ensure host is suspended during system + sleep + +If the device suspend process begins before the mmc host's autosuspend +timeout, the host will continue running during system sleep. Avoid +this by forcing runtime suspend during a global suspend transition. + +Signed-off-by: Samuel Holland +Acked-by: Maxime Ripard +--- + drivers/mmc/host/sunxi-mmc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -1506,6 +1506,8 @@ static int sunxi_mmc_runtime_suspend(str + #endif + + static const struct dev_pm_ops sunxi_mmc_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, ++ pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(sunxi_mmc_runtime_suspend, + sunxi_mmc_runtime_resume, + NULL) diff --git a/projects/Allwinner/patches/linux/0017-arm64-dts-allwinner-h6-Add-I2S1-node.patch b/projects/Allwinner/patches/linux/0017-arm64-dts-allwinner-h6-Add-I2S1-node.patch new file mode 100644 index 0000000000..58c540517a --- /dev/null +++ b/projects/Allwinner/patches/linux/0017-arm64-dts-allwinner-h6-Add-I2S1-node.patch @@ -0,0 +1,42 @@ +From e019a54d084020e6acc2869da341b376700bfe4c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 30 Oct 2020 15:46:44 +0100 +Subject: [PATCH 17/44] arm64: dts: allwinner: h6: Add I2S1 node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add Allwinner H6 I2S1 node connected to HDMI interface. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Marcus Cooper +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +Acked-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20201030144648.397824-12-peron.clem@gmail.com +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -609,6 +609,19 @@ + }; + }; + ++ i2s1: i2s@5091000 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun50i-h6-i2s"; ++ reg = <0x05091000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>; ++ clock-names = "apb", "mod"; ++ dmas = <&dma 4>, <&dma 4>; ++ resets = <&ccu RST_BUS_I2S1>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ + spdif: spdif@5093000 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-h6-spdif"; diff --git a/projects/Allwinner/patches/linux/0018-arm64-dts-allwinner-a64-Add-I2S2-node.patch b/projects/Allwinner/patches/linux/0018-arm64-dts-allwinner-a64-Add-I2S2-node.patch new file mode 100644 index 0000000000..e47e95c9fb --- /dev/null +++ b/projects/Allwinner/patches/linux/0018-arm64-dts-allwinner-a64-Add-I2S2-node.patch @@ -0,0 +1,43 @@ +From 0175a3d5680924d3d64ee8181b50c8b06ee715d1 Mon Sep 17 00:00:00 2001 +From: Marcus Cooper +Date: Fri, 30 Oct 2020 15:46:45 +0100 +Subject: [PATCH 18/44] arm64: dts: allwinner: a64: Add I2S2 node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the I2S2 node connected to the HDMI interface. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Marcus Cooper +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +Acked-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20201030144648.397824-13-peron.clem@gmail.com +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -846,6 +846,20 @@ + status = "disabled"; + }; + ++ i2s2: i2s@1c22800 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun50i-a64-i2s", ++ "allwinner,sun8i-h3-i2s"; ++ reg = <0x01c22800 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; ++ clock-names = "apb", "mod"; ++ resets = <&ccu RST_BUS_I2S2>; ++ dma-names = "rx", "tx"; ++ dmas = <&dma 27>, <&dma 27>; ++ status = "disabled"; ++ }; ++ + dai: dai@1c22c00 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-a64-codec-i2s"; diff --git a/projects/Allwinner/patches/linux/0019-arm-dts-sunxi-h3-h5-Add-I2S2-node.patch b/projects/Allwinner/patches/linux/0019-arm-dts-sunxi-h3-h5-Add-I2S2-node.patch new file mode 100644 index 0000000000..dfd107a942 --- /dev/null +++ b/projects/Allwinner/patches/linux/0019-arm-dts-sunxi-h3-h5-Add-I2S2-node.patch @@ -0,0 +1,42 @@ +From fd67e65487b4e5e2a93df2868043302a99f93098 Mon Sep 17 00:00:00 2001 +From: Marcus Cooper +Date: Fri, 30 Oct 2020 15:46:48 +0100 +Subject: [PATCH 19/44] arm: dts: sunxi: h3/h5: Add I2S2 node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add H3/H5 I2S2 node connected to the HDMI interface. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Marcus Cooper +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +Acked-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20201030144648.397824-16-peron.clem@gmail.com +--- + arch/arm/boot/dts/sunxi-h3-h5.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi ++++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi +@@ -662,6 +662,19 @@ + status = "disabled"; + }; + ++ i2s2: i2s@1c22800 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun8i-h3-i2s"; ++ reg = <0x01c22800 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; ++ clock-names = "apb", "mod"; ++ dmas = <&dma 27>; ++ resets = <&ccu RST_BUS_I2S2>; ++ dma-names = "tx"; ++ status = "disabled"; ++ }; ++ + codec: codec@1c22c00 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun8i-h3-codec"; diff --git a/projects/Allwinner/patches/linux/0020-arm64-dts-allwinner-h6-PineH64-model-B-Add-wifi.patch b/projects/Allwinner/patches/linux/0020-arm64-dts-allwinner-h6-PineH64-model-B-Add-wifi.patch new file mode 100644 index 0000000000..12fd8d08a8 --- /dev/null +++ b/projects/Allwinner/patches/linux/0020-arm64-dts-allwinner-h6-PineH64-model-B-Add-wifi.patch @@ -0,0 +1,47 @@ +From 3c970c9e87e403b190407dec5c6e4745aef78e6a Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 30 Oct 2020 18:25:30 +0100 +Subject: [PATCH 20/44] arm64: dts: allwinner: h6: PineH64 model B: Add wifi + +PineH64 model B contains RTL8723CS wifi+bt combo module. + +Since bluetooth support is not yet squared away, only wifi is enabled +for now. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +Tested-by: +Acked-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20201030172530.1096394-1-jernej.skrabec@siol.net +--- + .../dts/allwinner/sun50i-h6-pine-h64-model-b.dts | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts +@@ -10,6 +10,12 @@ + compatible = "pine64,pine-h64-model-b", "allwinner,sun50i-h6"; + + /delete-node/ reg_gmac_3v3; ++ ++ wifi_pwrseq: wifi_pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ ++ post-power-on-delay-ms = <200>; ++ }; + }; + + &hdmi_connector { +@@ -19,3 +25,12 @@ + &emac { + phy-supply = <®_aldo2>; + }; ++ ++&mmc1 { ++ vmmc-supply = <®_cldo3>; ++ vqmmc-supply = <®_aldo1>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ bus-width = <4>; ++ non-removable; ++ status = "okay"; ++}; diff --git a/projects/Allwinner/patches/linux/0002-media-cedrus-Fix-H264-decoding.patch b/projects/Allwinner/patches/linux/0021-media-cedrus-Fix-H264-decoding.patch similarity index 77% rename from projects/Allwinner/patches/linux/0002-media-cedrus-Fix-H264-decoding.patch rename to projects/Allwinner/patches/linux/0021-media-cedrus-Fix-H264-decoding.patch index 7505acb480..f2af6e6cab 100644 --- a/projects/Allwinner/patches/linux/0002-media-cedrus-Fix-H264-decoding.patch +++ b/projects/Allwinner/patches/linux/0021-media-cedrus-Fix-H264-decoding.patch @@ -1,7 +1,7 @@ -From 45e6e50e3420425d1db8022aa2773dd697c6f054 Mon Sep 17 00:00:00 2001 +From 3a9d4fe5b89c783d2162c84db3cabf00c3bca983 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Wed, 23 Dec 2020 11:23:40 +0100 -Subject: [PATCH 2/2] media: cedrus: Fix H264 decoding +Subject: [PATCH 21/44] media: cedrus: Fix H264 decoding During H264 API overhaul subtle bug was introduced Cedrus driver. Progressive references have both, top and bottom reference flags set. @@ -20,11 +20,9 @@ Signed-off-by: Jernej Skrabec drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -index 781c84a9b1b7..de7442d4834d 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c -@@ -203,7 +203,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx, +@@ -203,7 +203,7 @@ static void _cedrus_write_ref_list(struc position = cedrus_buf->codec.h264.position; sram_array[i] |= position << 1; @@ -33,6 +31,3 @@ index 781c84a9b1b7..de7442d4834d 100644 sram_array[i] |= BIT(0); } --- -2.29.2 - diff --git a/projects/Allwinner/patches/linux/0003-hdmi-improvements.patch b/projects/Allwinner/patches/linux/0022-ASoC-hdmi-codec-fix-channel-allocation.patch similarity index 91% rename from projects/Allwinner/patches/linux/0003-hdmi-improvements.patch rename to projects/Allwinner/patches/linux/0022-ASoC-hdmi-codec-fix-channel-allocation.patch index a1fd260c66..b5a73b1af7 100644 --- a/projects/Allwinner/patches/linux/0003-hdmi-improvements.patch +++ b/projects/Allwinner/patches/linux/0022-ASoC-hdmi-codec-fix-channel-allocation.patch @@ -1,17 +1,15 @@ -From e7b2f400507263f12872db06f4cd69bc80f62c2f Mon Sep 17 00:00:00 2001 +From 91b69779e0875e58d8973b2938a1cc4b7a1c455b Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 25 Mar 2018 22:17:06 +0200 -Subject: [PATCH 10/15] ASoC: hdmi-codec: fix channel allocation +Subject: [PATCH 22/44] ASoC: hdmi-codec: fix channel allocation --- - sound/soc/codecs/hdmi-codec.c | 113 +++++++++++++++++++----------------------- + sound/soc/codecs/hdmi-codec.c | 113 ++++++++++++++++------------------ 1 file changed, 52 insertions(+), 61 deletions(-) -diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c -index bfb1519..47632a3 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c -@@ -202,78 +202,69 @@ static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { +@@ -195,78 +195,69 @@ static const struct snd_pcm_chmap_elem h */ static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { { .ca_id = 0x00, .n_ch = 2, @@ -142,6 +140,3 @@ index bfb1519..47632a3 100644 }; struct hdmi_codec_priv { --- -2.14.1 - diff --git a/projects/Allwinner/patches/linux/0023-media-uapi-hevc-Add-scaling-matrix-control.patch b/projects/Allwinner/patches/linux/0023-media-uapi-hevc-Add-scaling-matrix-control.patch new file mode 100644 index 0000000000..8add1ecf3a --- /dev/null +++ b/projects/Allwinner/patches/linux/0023-media-uapi-hevc-Add-scaling-matrix-control.patch @@ -0,0 +1,85 @@ +From 82a8ceccbaf9aa3d8cbc56d10e3905eec0d4ffb4 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 13:55:15 +0200 +Subject: [PATCH 23/44] media: uapi: hevc: Add scaling matrix control + +HEVC has a scaling matrix concept. Add support for it. + +Signed-off-by: Jernej Skrabec +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 10 ++++++++++ + include/media/hevc-ctrls.h | 11 +++++++++++ + 2 files changed, 21 insertions(+) + +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -1021,6 +1021,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix"; + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; + +@@ -1461,6 +1462,9 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: + *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; + break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: ++ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; ++ break; + case V4L2_CID_UNIT_CELL_SIZE: + *type = V4L2_CTRL_TYPE_AREA; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; +@@ -1934,6 +1938,9 @@ static int std_validate_compound(const s + zero_padding(*p_hevc_slice_params); + break; + ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ break; ++ + case V4L2_CTRL_TYPE_AREA: + area = p; + if (!area->width || !area->height) +@@ -2626,6 +2633,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); + break; ++ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: ++ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); ++ break; + case V4L2_CTRL_TYPE_AREA: + elem_size = sizeof(struct v4l2_area); + break; +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -19,6 +19,7 @@ + #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) + #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) + #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) + #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) + #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) + +@@ -26,6 +27,7 @@ + #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 + #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 + #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 + + enum v4l2_mpeg_video_hevc_decode_mode { + V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, +@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { + __u64 flags; + }; + ++struct v4l2_ctrl_hevc_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++ __u8 scaling_list_16x16[6][64]; ++ __u8 scaling_list_32x32[2][64]; ++ __u8 scaling_list_dc_coef_16x16[6]; ++ __u8 scaling_list_dc_coef_32x32[2]; ++}; ++ + #endif diff --git a/projects/Allwinner/patches/linux/0024-media-cedrus-hevc-Add-support-for-scaling-matrix.patch b/projects/Allwinner/patches/linux/0024-media-cedrus-hevc-Add-support-for-scaling-matrix.patch new file mode 100644 index 0000000000..ddf6ff9f6b --- /dev/null +++ b/projects/Allwinner/patches/linux/0024-media-cedrus-hevc-Add-support-for-scaling-matrix.patch @@ -0,0 +1,150 @@ +From b4b79b4eeacb63f0a72c866526e4a2021a201090 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 13:58:49 +0200 +Subject: [PATCH 24/44] media: cedrus: hevc: Add support for scaling matrix + +HEVC frames may use scaling list feature. Add support for it. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 7 ++ + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + .../staging/media/sunxi/cedrus/cedrus_dec.c | 2 + + .../staging/media/sunxi/cedrus/cedrus_h265.c | 70 ++++++++++++++++++- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 2 + + 5 files changed, 81 insertions(+), 1 deletion(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -126,6 +126,13 @@ static const struct cedrus_control cedru + }, + { + .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, ++ }, ++ .codec = CEDRUS_CODEC_H265, ++ .required = true, ++ }, ++ { ++ .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, + .max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, + .def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -74,6 +74,7 @@ struct cedrus_h265_run { + const struct v4l2_ctrl_hevc_sps *sps; + const struct v4l2_ctrl_hevc_pps *pps; + const struct v4l2_ctrl_hevc_slice_params *slice_params; ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; + }; + + struct cedrus_run { +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -68,6 +68,8 @@ void cedrus_device_run(void *priv) + V4L2_CID_MPEG_VIDEO_HEVC_PPS); + run.h265.slice_params = cedrus_find_control_data(ctx, + V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS); ++ run.h265.scaling_matrix = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); + break; + + default: +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -238,6 +238,69 @@ static void cedrus_h265_skip_bits(struct + } + } + ++static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, ++ struct cedrus_run *run) ++{ ++ const struct v4l2_ctrl_hevc_scaling_matrix *scaling; ++ struct cedrus_dev *dev = ctx->dev; ++ u32 i, j, k, val; ++ ++ scaling = run->h265.scaling_matrix; ++ ++ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0, ++ (scaling->scaling_list_dc_coef_32x32[1] << 24) | ++ (scaling->scaling_list_dc_coef_32x32[0] << 16) | ++ (scaling->scaling_list_dc_coef_16x16[1] << 8) | ++ (scaling->scaling_list_dc_coef_16x16[0] << 0)); ++ ++ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1, ++ (scaling->scaling_list_dc_coef_16x16[5] << 24) | ++ (scaling->scaling_list_dc_coef_16x16[4] << 16) | ++ (scaling->scaling_list_dc_coef_16x16[3] << 8) | ++ (scaling->scaling_list_dc_coef_16x16[2] << 0)); ++ ++ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS); ++ ++ for (i = 0; i < 6; i++) ++ for (j = 0; j < 8; j++) ++ for (k = 0; k < 8; k += 4) { ++ val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) | ++ ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) | ++ ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) | ++ scaling->scaling_list_8x8[i][j + k * 8]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < 8; j++) ++ for (k = 0; k < 8; k += 4) { ++ val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) | ++ ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) | ++ ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) | ++ scaling->scaling_list_32x32[i][j + k * 8]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++ ++ for (i = 0; i < 6; i++) ++ for (j = 0; j < 8; j++) ++ for (k = 0; k < 8; k += 4) { ++ val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) | ++ ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) | ++ ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) | ++ scaling->scaling_list_16x16[i][j + k * 8]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++ ++ for (i = 0; i < 6; i++) ++ for (j = 0; j < 4; j++) { ++ val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) | ++ ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) | ++ ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) | ++ scaling->scaling_list_4x4[i][j]; ++ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val); ++ } ++} ++ + static void cedrus_h265_setup(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -519,7 +582,12 @@ static void cedrus_h265_setup(struct ced + + /* Scaling list. */ + +- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; ++ if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) { ++ cedrus_h265_write_scaling_list(ctx, run); ++ reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED; ++ } else { ++ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT; ++ } + cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg); + + /* Neightbor information address. */ +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -493,6 +493,8 @@ + #define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64) + #define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68) + #define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c) ++#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78) ++#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c) + + #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) + diff --git a/projects/Allwinner/patches/linux/0025-media-uapi-hevc-Add-segment-address-field.patch b/projects/Allwinner/patches/linux/0025-media-uapi-hevc-Add-segment-address-field.patch new file mode 100644 index 0000000000..d2632df423 --- /dev/null +++ b/projects/Allwinner/patches/linux/0025-media-uapi-hevc-Add-segment-address-field.patch @@ -0,0 +1,36 @@ +From e61cf76fca5984dd9edcb0daf6c5cb5278f32e05 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 15:42:28 +0200 +Subject: [PATCH 25/44] media: uapi: hevc: Add segment address field + +If HEVC frame consists of multiple slices, segment address has to be +known in order to properly decode it. + +Add segment address field to slice parameters. + +Signed-off-by: Jernej Skrabec +--- + include/media/hevc-ctrls.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u32 bit_size; + __u32 data_bit_offset; + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; + __u8 nuh_temporal_id_plus1; +@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding; ++ __u8 padding[5]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; diff --git a/projects/Allwinner/patches/linux/0026-media-cedrus-hevc-Add-support-for-multiple-slices.patch b/projects/Allwinner/patches/linux/0026-media-cedrus-hevc-Add-support-for-multiple-slices.patch new file mode 100644 index 0000000000..1a49b6f12d --- /dev/null +++ b/projects/Allwinner/patches/linux/0026-media-cedrus-hevc-Add-support-for-multiple-slices.patch @@ -0,0 +1,90 @@ +From d99740197a9776b9332d21b9f3b05dab658a90eb Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 15:44:15 +0200 +Subject: [PATCH 26/44] media: cedrus: hevc: Add support for multiple slices + +Now that segment address is available, support for multi-slice frames +can be easily added. + +Signed-off-by: Jernej Skrabec +--- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 26 ++++++++++++------- + .../staging/media/sunxi/cedrus/cedrus_video.c | 1 + + 2 files changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -309,6 +309,8 @@ static void cedrus_h265_setup(struct ced + const struct v4l2_ctrl_hevc_pps *pps; + const struct v4l2_ctrl_hevc_slice_params *slice_params; + const struct v4l2_hevc_pred_weight_table *pred_weight_table; ++ unsigned int width_in_ctb_luma, ctb_size_luma; ++ unsigned int log2_max_luma_coding_block_size; + dma_addr_t src_buf_addr; + dma_addr_t src_buf_end_addr; + u32 chroma_log2_weight_denom; +@@ -321,15 +323,17 @@ static void cedrus_h265_setup(struct ced + slice_params = run->h265.slice_params; + pred_weight_table = &slice_params->pred_weight_table; + ++ log2_max_luma_coding_block_size = ++ sps->log2_min_luma_coding_block_size_minus3 + 3 + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_luma = 1UL << log2_max_luma_coding_block_size; ++ width_in_ctb_luma = ++ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); ++ + /* MV column buffer size and allocation. */ + if (!ctx->codec.h265.mv_col_buf_size) { + unsigned int num_buffers = + run->dst->vb2_buf.vb2_queue->num_buffers; +- unsigned int log2_max_luma_coding_block_size = +- sps->log2_min_luma_coding_block_size_minus3 + 3 + +- sps->log2_diff_max_min_luma_coding_block_size; +- unsigned int ctb_size_luma = +- 1UL << log2_max_luma_coding_block_size; + + /* + * Each CTB requires a MV col buffer with a specific unit size. +@@ -383,15 +387,17 @@ static void cedrus_h265_setup(struct ced + reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); + cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); + +- /* Coding tree block address: start at the beginning. */ +- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); ++ /* Coding tree block address */ ++ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); ++ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); + cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); + + cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); + cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); + + /* Clear the number of correctly-decoded coding tree blocks. */ +- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); ++ if (ctx->fh.m2m_ctx->new_frame) ++ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); + + /* Initialize bitstream access. */ + cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); +@@ -543,8 +549,8 @@ static void cedrus_h265_setup(struct ced + V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT, + pps->flags); + +- /* FIXME: For multi-slice support. */ +- reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; ++ if (ctx->fh.m2m_ctx->new_frame) ++ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; + + cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); + +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -332,6 +332,7 @@ static int cedrus_s_fmt_vid_out(struct f + + switch (ctx->src_fmt.pixelformat) { + case V4L2_PIX_FMT_H264_SLICE: ++ case V4L2_PIX_FMT_HEVC_SLICE: + vq->subsystem_flags |= + VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; + break; diff --git a/projects/Allwinner/patches/linux/0027-media-cedrus-hevc-tiles-hack.patch b/projects/Allwinner/patches/linux/0027-media-cedrus-hevc-tiles-hack.patch new file mode 100644 index 0000000000..b968361004 --- /dev/null +++ b/projects/Allwinner/patches/linux/0027-media-cedrus-hevc-tiles-hack.patch @@ -0,0 +1,195 @@ +From 9e203d78974aa445086dbe6b667e49b3f00d36d0 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 26 Oct 2019 21:23:55 +0200 +Subject: [PATCH 27/44] media: cedrus: hevc: tiles hack + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 2 + + .../staging/media/sunxi/cedrus/cedrus_h265.c | 93 +++++++++++++++++-- + include/media/hevc-ctrls.h | 5 +- + 3 files changed, 93 insertions(+), 7 deletions(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -135,6 +135,8 @@ struct cedrus_ctx { + ssize_t mv_col_buf_unit_size; + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_addr; ++ void *entry_points_buf; ++ dma_addr_t entry_points_buf_addr; + } h265; + } codec; + }; +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -301,6 +301,61 @@ static void cedrus_h265_write_scaling_li + } + } + ++static void write_entry_point_list(struct cedrus_ctx *ctx, ++ struct cedrus_run *run, ++ unsigned int ctb_addr_x, ++ unsigned int ctb_addr_y) ++{ ++ const struct v4l2_ctrl_hevc_slice_params *slice_params; ++ const struct v4l2_ctrl_hevc_pps *pps; ++ struct cedrus_dev *dev = ctx->dev; ++ int i, x, tx, y, ty; ++ u32 *entry_points; ++ ++ pps = run->h265.pps; ++ slice_params = run->h265.slice_params; ++ ++ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) { ++ if (x + pps->column_width_minus1[tx] + 1 > ctb_addr_x) ++ break; ++ ++ x += pps->column_width_minus1[tx] + 1; ++ } ++ ++ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) { ++ if (y + pps->row_height_minus1[ty] + 1 > ctb_addr_y) ++ break; ++ ++ y += pps->row_height_minus1[ty] + 1; ++ } ++ ++ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0)); ++ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, ++ ((y + pps->row_height_minus1[ty]) << 16) | ++ ((x + pps->column_width_minus1[tx]) << 0)); ++ ++ entry_points = ctx->codec.h265.entry_points_buf; ++ if (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) { ++ for (i = 0; i < slice_params->num_entry_point_offsets; i++) ++ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1; ++ } else { ++ for (i = 0; i < slice_params->num_entry_point_offsets; i++) { ++ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) { ++ x = 0; ++ tx = 0; ++ y += pps->row_height_minus1[ty++] + 1; ++ } else { ++ x += pps->column_width_minus1[tx++] + 1; ++ } ++ ++ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1; ++ entry_points[i * 4 + 1] = 0x0; ++ entry_points[i * 4 + 2] = (y << 16) | (x << 0); ++ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0); ++ } ++ } ++} ++ + static void cedrus_h265_setup(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -311,6 +366,7 @@ static void cedrus_h265_setup(struct ced + const struct v4l2_hevc_pred_weight_table *pred_weight_table; + unsigned int width_in_ctb_luma, ctb_size_luma; + unsigned int log2_max_luma_coding_block_size; ++ unsigned int ctb_addr_x, ctb_addr_y; + dma_addr_t src_buf_addr; + dma_addr_t src_buf_end_addr; + u32 chroma_log2_weight_denom; +@@ -388,12 +444,19 @@ static void cedrus_h265_setup(struct ced + cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); + + /* Coding tree block address */ +- reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); +- reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); ++ ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma; ++ ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma; ++ reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x); ++ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y); + cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); + +- cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); +- cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); ++ if ((pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) || ++ (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) { ++ write_entry_point_list(ctx, run, ctb_addr_x, ctb_addr_y); ++ } else { ++ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); ++ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); ++ } + + /* Clear the number of correctly-decoded coding tree blocks. */ + if (ctx->fh.m2m_ctx->new_frame) +@@ -497,7 +560,9 @@ static void cedrus_h265_setup(struct ced + V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED, + pps->flags); + +- /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */ ++ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED, ++ V4L2_HEVC_PPS_FLAG_TILES_ENABLED, ++ pps->flags); + + reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED, + V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED, +@@ -573,12 +638,14 @@ static void cedrus_h265_setup(struct ced + + chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + + pred_weight_table->delta_chroma_log2_weight_denom; +- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) | ++ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) | + VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) | + VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom); + + cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg); + ++ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8); ++ + /* Decoded picture size. */ + + reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) | +@@ -672,6 +739,17 @@ static int cedrus_h265_start(struct cedr + if (!ctx->codec.h265.neighbor_info_buf) + return -ENOMEM; + ++ ctx->codec.h265.entry_points_buf = ++ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, ++ &ctx->codec.h265.entry_points_buf_addr, ++ GFP_KERNEL); ++ if (!ctx->codec.h265.entry_points_buf) { ++ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, ++ ctx->codec.h265.neighbor_info_buf, ++ ctx->codec.h265.neighbor_info_buf_addr); ++ return -ENOMEM; ++ } ++ + return 0; + } + +@@ -690,6 +768,9 @@ static void cedrus_h265_stop(struct cedr + dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr); ++ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE, ++ ctx->codec.h265.entry_points_buf, ++ ctx->codec.h265.entry_points_buf_addr); + } + + static void cedrus_h265_trigger(struct cedrus_ctx *ctx) +--- a/include/media/hevc-ctrls.h ++++ b/include/media/hevc-ctrls.h +@@ -169,6 +169,7 @@ struct v4l2_ctrl_hevc_slice_params { + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; +@@ -203,7 +204,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding[5]; ++ __u8 padding; ++ ++ __u32 entry_point_offset_minus1[256]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; diff --git a/projects/Allwinner/patches/linux/0028-media-cedrus-Add-callback-for-buffer-cleanup.patch b/projects/Allwinner/patches/linux/0028-media-cedrus-Add-callback-for-buffer-cleanup.patch new file mode 100644 index 0000000000..b8006ee8a9 --- /dev/null +++ b/projects/Allwinner/patches/linux/0028-media-cedrus-Add-callback-for-buffer-cleanup.patch @@ -0,0 +1,50 @@ +From b6d288bb8823e11114297d1e406ccd977106aaf9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 13:06:15 +0100 +Subject: [PATCH 28/44] media: cedrus: Add callback for buffer cleanup + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++++ + 2 files changed, 14 insertions(+) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -149,6 +149,7 @@ struct cedrus_dec_ops { + int (*start)(struct cedrus_ctx *ctx); + void (*stop)(struct cedrus_ctx *ctx); + void (*trigger)(struct cedrus_ctx *ctx); ++ void (*buf_cleanup)(struct cedrus_ctx *ctx, struct cedrus_buffer *buf); + }; + + struct cedrus_variant { +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -455,6 +455,18 @@ static int cedrus_buf_prepare(struct vb2 + return 0; + } + ++static void cedrus_buf_cleanup(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *vq = vb->vb2_queue; ++ struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); ++ struct cedrus_dev *dev = ctx->dev; ++ struct cedrus_dec_ops *ops = dev->dec_ops[ctx->current_codec]; ++ ++ if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ops->buf_cleanup) ++ ops->buf_cleanup(ctx, ++ vb2_to_cedrus_buffer(vq->bufs[vb->index])); ++} ++ + static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) + { + struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); +@@ -535,6 +547,7 @@ static void cedrus_buf_request_complete( + static struct vb2_ops cedrus_qops = { + .queue_setup = cedrus_queue_setup, + .buf_prepare = cedrus_buf_prepare, ++ .buf_cleanup = cedrus_buf_cleanup, + .buf_queue = cedrus_buf_queue, + .buf_out_validate = cedrus_buf_out_validate, + .buf_request_complete = cedrus_buf_request_complete, diff --git a/projects/Allwinner/patches/linux/0029-media-cedrus-hevc-Improve-buffer-management.patch b/projects/Allwinner/patches/linux/0029-media-cedrus-hevc-Improve-buffer-management.patch new file mode 100644 index 0000000000..fa357267c3 --- /dev/null +++ b/projects/Allwinner/patches/linux/0029-media-cedrus-hevc-Improve-buffer-management.patch @@ -0,0 +1,235 @@ +From d4ffac11f0d8b3a844f528e963b953a6bfe540af Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 13:22:05 +0100 +Subject: [PATCH 29/44] media: cedrus: hevc: Improve buffer management + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 117 ++++++++++-------- + 2 files changed, 69 insertions(+), 57 deletions(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -96,6 +96,11 @@ struct cedrus_buffer { + unsigned int position; + enum cedrus_h264_pic_type pic_type; + } h264; ++ struct { ++ void *mv_col_buf; ++ dma_addr_t mv_col_buf_dma; ++ ssize_t mv_col_buf_size; ++ } h265; + } codec; + }; + +@@ -129,10 +134,6 @@ struct cedrus_ctx { + ssize_t intra_pred_buf_size; + } h264; + struct { +- void *mv_col_buf; +- dma_addr_t mv_col_buf_addr; +- ssize_t mv_col_buf_size; +- ssize_t mv_col_buf_unit_size; + void *neighbor_info_buf; + dma_addr_t neighbor_info_buf_addr; + void *entry_points_buf; +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data( + + static inline dma_addr_t + cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, +- unsigned int index, unsigned int field) ++ unsigned int index, ++ const struct v4l2_ctrl_hevc_sps *sps) + { +- return ctx->codec.h265.mv_col_buf_addr + index * +- ctx->codec.h265.mv_col_buf_unit_size + +- field * ctx->codec.h265.mv_col_buf_unit_size / 2; ++ struct cedrus_buffer *cedrus_buf = NULL; ++ struct vb2_buffer *buf = NULL; ++ struct vb2_queue *vq; ++ ++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if (vq) ++ buf = vb2_get_buffer(vq, index); ++ ++ if (buf) ++ cedrus_buf = vb2_to_cedrus_buffer(buf); ++ ++ if (!cedrus_buf) ++ return 0; ++ ++ if (!cedrus_buf->codec.h265.mv_col_buf_size) { ++ unsigned int ctb_size_luma, width_in_ctb_luma; ++ unsigned int log2_max_luma_coding_block_size; ++ ++ log2_max_luma_coding_block_size = ++ sps->log2_min_luma_coding_block_size_minus3 + 3 + ++ sps->log2_diff_max_min_luma_coding_block_size; ++ ctb_size_luma = 1 << log2_max_luma_coding_block_size; ++ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ++ ctb_size_luma); ++ ++ cedrus_buf->codec.h265.mv_col_buf_size = ALIGN(width_in_ctb_luma * ++ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) * ++ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024); ++ ++ cedrus_buf->codec.h265.mv_col_buf = ++ dma_alloc_coherent(ctx->dev->dev, ++ cedrus_buf->codec.h265.mv_col_buf_size, ++ &cedrus_buf->codec.h265.mv_col_buf_dma, ++ GFP_KERNEL); ++ ++ if (!cedrus_buf->codec.h265.mv_col_buf) { ++ cedrus_buf->codec.h265.mv_col_buf_size = 0; ++ cedrus_buf->codec.h265.mv_col_buf_dma = 0; ++ } ++ } ++ ++ return cedrus_buf->codec.h265.mv_col_buf_dma; + } + + static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, + unsigned int index, + bool field_pic, + u32 pic_order_cnt[], +- int buffer_index) ++ int buffer_index, ++ const struct v4l2_ctrl_hevc_sps *sps) + { + struct cedrus_dev *dev = ctx->dev; + dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0); + dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1); + dma_addr_t mv_col_buf_addr[2] = { +- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0), +- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, +- field_pic ? 1 : 0) ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps), ++ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps) + }; + u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + + VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; +@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write + + static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, + const struct v4l2_hevc_dpb_entry *dpb, +- u8 num_active_dpb_entries) ++ u8 num_active_dpb_entries, ++ const struct v4l2_ctrl_hevc_sps *sps) + { + struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); +@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write + + cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, + pic_order_cnt, +- buffer_index); ++ buffer_index, sps); + } + } + +@@ -386,36 +427,6 @@ static void cedrus_h265_setup(struct ced + width_in_ctb_luma = + DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); + +- /* MV column buffer size and allocation. */ +- if (!ctx->codec.h265.mv_col_buf_size) { +- unsigned int num_buffers = +- run->dst->vb2_buf.vb2_queue->num_buffers; +- +- /* +- * Each CTB requires a MV col buffer with a specific unit size. +- * Since the address is given with missing lsb bits, 1 KiB is +- * added to each buffer to ensure proper alignment. +- */ +- ctx->codec.h265.mv_col_buf_unit_size = +- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) * +- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) * +- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; +- +- ctx->codec.h265.mv_col_buf_size = num_buffers * +- ctx->codec.h265.mv_col_buf_unit_size; +- +- ctx->codec.h265.mv_col_buf = +- dma_alloc_coherent(dev->dev, +- ctx->codec.h265.mv_col_buf_size, +- &ctx->codec.h265.mv_col_buf_addr, +- GFP_KERNEL); +- if (!ctx->codec.h265.mv_col_buf) { +- ctx->codec.h265.mv_col_buf_size = 0; +- // TODO: Abort the process here. +- return; +- } +- } +- + /* Activate H265 engine. */ + cedrus_engine_enable(ctx, CEDRUS_CODEC_H265); + +@@ -669,7 +680,7 @@ static void cedrus_h265_setup(struct ced + + /* Write decoded picture buffer in pic list. */ + cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb, +- slice_params->num_active_dpb_entries); ++ slice_params->num_active_dpb_entries, sps); + + /* Output frame. */ + +@@ -680,7 +691,7 @@ static void cedrus_h265_setup(struct ced + cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, + slice_params->pic_struct != 0, + pic_order_cnt, +- run->dst->vb2_buf.index); ++ run->dst->vb2_buf.index, sps); + + cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); + +@@ -729,9 +740,6 @@ static int cedrus_h265_start(struct cedr + { + struct cedrus_dev *dev = ctx->dev; + +- /* The buffer size is calculated at setup time. */ +- ctx->codec.h265.mv_col_buf_size = 0; +- + ctx->codec.h265.neighbor_info_buf = + dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + &ctx->codec.h265.neighbor_info_buf_addr, +@@ -757,14 +765,6 @@ static void cedrus_h265_stop(struct cedr + { + struct cedrus_dev *dev = ctx->dev; + +- if (ctx->codec.h265.mv_col_buf_size > 0) { +- dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size, +- ctx->codec.h265.mv_col_buf, +- ctx->codec.h265.mv_col_buf_addr); +- +- ctx->codec.h265.mv_col_buf_size = 0; +- } +- + dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h265.neighbor_info_buf, + ctx->codec.h265.neighbor_info_buf_addr); +@@ -780,6 +780,16 @@ static void cedrus_h265_trigger(struct c + cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); + } + ++static void cedrus_h265_buf_cleanup(struct cedrus_ctx *ctx, ++ struct cedrus_buffer *buf) ++{ ++ if (buf->codec.h265.mv_col_buf_size) ++ dma_free_coherent(ctx->dev->dev, ++ buf->codec.h265.mv_col_buf_size, ++ buf->codec.h265.mv_col_buf, ++ buf->codec.h265.mv_col_buf_dma); ++} ++ + struct cedrus_dec_ops cedrus_dec_ops_h265 = { + .irq_clear = cedrus_h265_irq_clear, + .irq_disable = cedrus_h265_irq_disable, +@@ -788,4 +798,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h26 + .start = cedrus_h265_start, + .stop = cedrus_h265_stop, + .trigger = cedrus_h265_trigger, ++ .buf_cleanup = cedrus_h265_buf_cleanup, + }; diff --git a/projects/Allwinner/patches/linux/0030-media-cedrus-h264-Improve-buffer-management.patch b/projects/Allwinner/patches/linux/0030-media-cedrus-h264-Improve-buffer-management.patch new file mode 100644 index 0000000000..648ade8589 --- /dev/null +++ b/projects/Allwinner/patches/linux/0030-media-cedrus-h264-Improve-buffer-management.patch @@ -0,0 +1,197 @@ +From a881ce25cba8e45c6a86b5a680981c3b14b5b1e1 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 9 Nov 2019 14:12:42 +0100 +Subject: [PATCH 30/44] media: cedrus: h264: Improve buffer management + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 3 + + .../staging/media/sunxi/cedrus/cedrus_h264.c | 93 ++++++++----------- + 2 files changed, 44 insertions(+), 52 deletions(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -95,6 +95,9 @@ struct cedrus_buffer { + struct { + unsigned int position; + enum cedrus_h264_pic_type pic_type; ++ void *mv_col_buf; ++ dma_addr_t mv_col_buf_dma; ++ ssize_t mv_col_buf_size; + } h264; + struct { + void *mv_col_buf; +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struc + } + + static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx, +- unsigned int position, ++ struct cedrus_buffer *buf, + unsigned int field) + { +- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma; ++ dma_addr_t addr = buf->codec.h264.mv_col_buf_dma; + +- /* Adjust for the position */ +- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2; +- +- /* Adjust for the field */ +- addr += field * ctx->codec.h264.mv_col_buf_field_size; ++ /* Adjust for the field */ ++ if (field) ++ addr += buf->codec.h264.mv_col_buf_size / 2; + + return addr; + } +@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct c + struct cedrus_h264_sram_ref_pic *pic) + { + struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf; +- unsigned int position = buf->codec.h264.position; + + pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt); + pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt); +@@ -85,9 +82,9 @@ static void cedrus_fill_ref_pic(struct c + pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0)); + pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1)); + pic->mv_col_top_ptr = +- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0)); ++ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 0)); + pic->mv_col_bot_ptr = +- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1)); ++ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 1)); + } + + static void cedrus_write_frame_list(struct cedrus_ctx *ctx, +@@ -146,6 +143,28 @@ static void cedrus_write_frame_list(stru + output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); + output_buf->codec.h264.position = position; + ++ if (!output_buf->codec.h264.mv_col_buf_size) { ++ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps; ++ unsigned int field_size; ++ ++ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * ++ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; ++ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) ++ field_size = field_size * 2; ++ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) ++ field_size = field_size * 2; ++ ++ output_buf->codec.h264.mv_col_buf_size = field_size * 2; ++ output_buf->codec.h264.mv_col_buf = ++ dma_alloc_coherent(dev->dev, ++ output_buf->codec.h264.mv_col_buf_size, ++ &output_buf->codec.h264.mv_col_buf_dma, ++ GFP_KERNEL); ++ ++ if (!output_buf->codec.h264.mv_col_buf) ++ output_buf->codec.h264.mv_col_buf_size = 0; ++ } ++ + if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) + output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD; + else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) +@@ -516,8 +535,6 @@ static int cedrus_h264_start(struct cedr + { + struct cedrus_dev *dev = ctx->dev; + unsigned int pic_info_size; +- unsigned int field_size; +- unsigned int mv_col_size; + int ret; + + /* Formula for picture buffer size is taken from CedarX source. */ +@@ -560,37 +577,6 @@ static int cedrus_h264_start(struct cedr + goto err_pic_buf; + } + +- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) * +- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16; +- +- /* +- * FIXME: This is actually conditional to +- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we +- * might have to rework this if memory efficiency ever is +- * something we need to work on. +- */ +- field_size = field_size * 2; +- +- /* +- * FIXME: This is actually conditional to +- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might +- * have to rework this if memory efficiency ever is something +- * we need to work on. +- */ +- field_size = field_size * 2; +- ctx->codec.h264.mv_col_buf_field_size = field_size; +- +- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM; +- ctx->codec.h264.mv_col_buf_size = mv_col_size; +- ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev, +- ctx->codec.h264.mv_col_buf_size, +- &ctx->codec.h264.mv_col_buf_dma, +- GFP_KERNEL); +- if (!ctx->codec.h264.mv_col_buf) { +- ret = -ENOMEM; +- goto err_neighbor_buf; +- } +- + if (ctx->src_fmt.width > 2048) { + /* + * Formulas for deblock and intra prediction buffer sizes +@@ -606,7 +592,7 @@ static int cedrus_h264_start(struct cedr + GFP_KERNEL); + if (!ctx->codec.h264.deblk_buf) { + ret = -ENOMEM; +- goto err_mv_col_buf; ++ goto err_neighbor_buf; + } + + /* +@@ -633,11 +619,6 @@ err_deblk_buf: + ctx->codec.h264.deblk_buf, + ctx->codec.h264.deblk_buf_dma); + +-err_mv_col_buf: +- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, +- ctx->codec.h264.mv_col_buf, +- ctx->codec.h264.mv_col_buf_dma); +- + err_neighbor_buf: + dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, +@@ -654,9 +635,6 @@ static void cedrus_h264_stop(struct cedr + { + struct cedrus_dev *dev = ctx->dev; + +- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size, +- ctx->codec.h264.mv_col_buf, +- ctx->codec.h264.mv_col_buf_dma); + dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE, + ctx->codec.h264.neighbor_info_buf, + ctx->codec.h264.neighbor_info_buf_dma); +@@ -681,6 +659,16 @@ static void cedrus_h264_trigger(struct c + VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE); + } + ++static void cedrus_h264_buf_cleanup(struct cedrus_ctx *ctx, ++ struct cedrus_buffer *buf) ++{ ++ if (buf->codec.h264.mv_col_buf_size) ++ dma_free_coherent(ctx->dev->dev, ++ buf->codec.h264.mv_col_buf_size, ++ buf->codec.h264.mv_col_buf, ++ buf->codec.h264.mv_col_buf_dma); ++} ++ + struct cedrus_dec_ops cedrus_dec_ops_h264 = { + .irq_clear = cedrus_h264_irq_clear, + .irq_disable = cedrus_h264_irq_disable, +@@ -689,4 +677,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h26 + .start = cedrus_h264_start, + .stop = cedrus_h264_stop, + .trigger = cedrus_h264_trigger, ++ .buf_cleanup = cedrus_h264_buf_cleanup, + }; diff --git a/projects/Allwinner/patches/linux/0031-WIp-10-bit-HEVC-support.patch b/projects/Allwinner/patches/linux/0031-WIp-10-bit-HEVC-support.patch new file mode 100644 index 0000000000..85477ccf2b --- /dev/null +++ b/projects/Allwinner/patches/linux/0031-WIp-10-bit-HEVC-support.patch @@ -0,0 +1,155 @@ +From 54389b5956af51023b073a08eeb7a746a4a37119 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 15 Mar 2020 21:35:39 +0100 +Subject: [PATCH 31/44] WIp: 10-bit HEVC support + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 4 +-- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 12 ++++++++ + .../staging/media/sunxi/cedrus/cedrus_regs.h | 4 +++ + .../staging/media/sunxi/cedrus/cedrus_video.c | 30 +++++++++++++++---- + .../staging/media/sunxi/cedrus/cedrus_video.h | 2 +- + 5 files changed, 44 insertions(+), 8 deletions(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -301,7 +301,7 @@ static int cedrus_open(struct file *file + goto err_ctrls; + } + ctx->dst_fmt.pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12; +- cedrus_prepare_format(&ctx->dst_fmt); ++ cedrus_prepare_format(&ctx->dst_fmt, 0); + ctx->src_fmt.pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; + /* + * TILED_NV12 has more strict requirements, so copy the width and +@@ -309,7 +309,7 @@ static int cedrus_open(struct file *file + */ + ctx->src_fmt.width = ctx->dst_fmt.width; + ctx->src_fmt.height = ctx->dst_fmt.height; +- cedrus_prepare_format(&ctx->src_fmt); ++ cedrus_prepare_format(&ctx->src_fmt, 0); + + v4l2_fh_add(&ctx->fh); + +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -532,6 +532,18 @@ static void cedrus_h265_setup(struct ced + + cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg); + ++ if (sps->bit_depth_luma_minus8 == 2) { ++ unsigned int size; ++ ++ size = ALIGN(ctx->src_fmt.width, 16) * ALIGN(ctx->src_fmt.height, 16); ++ ++ reg = (size * 3) / 2; ++ cedrus_write(dev, VE_DEC_H265_OFFSET_ADDR_FIRST_OUT, reg); ++ ++ reg = DIV_ROUND_UP(ctx->src_fmt.width, 4); ++ cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, ALIGN(reg, 32)); ++ } ++ + /* PPS. */ + + reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) | +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -498,6 +498,10 @@ + + #define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80) + ++#define VE_DEC_H265_OFFSET_ADDR_FIRST_OUT (VE_ENGINE_DEC_H265 + 0x84) ++#define VE_DEC_H265_OFFSET_ADDR_SECOND_OUT (VE_ENGINE_DEC_H265 + 0x88) ++#define VE_DEC_H265_10BIT_CONFIGURE (VE_ENGINE_DEC_H265 + 0x8c) ++ + #define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \ + SHIFT_AND_MASK_BITS(a, 31, 24) + #define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \ +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -93,7 +93,7 @@ static struct cedrus_format *cedrus_find + return &cedrus_formats[i]; + } + +-void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) ++void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended) + { + unsigned int width = pix_fmt->width; + unsigned int height = pix_fmt->height; +@@ -147,6 +147,17 @@ void cedrus_prepare_format(struct v4l2_p + break; + } + ++ if (extended) { ++ unsigned int extra_size; ++ ++ extra_size = DIV_ROUND_UP(pix_fmt->width, 4); ++ extra_size = ALIGN(extra_size, 32); ++ extra_size *= ALIGN(pix_fmt->height, 16) * 3; ++ extra_size /= 2; ++ ++ sizeimage += extra_size; ++ } ++ + pix_fmt->width = width; + pix_fmt->height = height; + +@@ -239,17 +250,27 @@ static int cedrus_try_fmt_vid_cap(struct + struct cedrus_ctx *ctx = cedrus_file2ctx(file); + struct cedrus_dev *dev = ctx->dev; + struct v4l2_pix_format *pix_fmt = &f->fmt.pix; ++ const struct v4l2_ctrl_hevc_sps *sps; + struct cedrus_format *fmt = + cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST, + dev->capabilities); ++ int extended; + + if (!fmt) + return -EINVAL; + ++ sps = cedrus_find_control_data(ctx, V4L2_CID_MPEG_VIDEO_HEVC_SPS); ++ ++ /* The 10-bitHEVC decoder needs extra size on the output buffer. */ ++ extended = ctx->src_fmt.pixelformat == V4L2_PIX_FMT_HEVC_SLICE && ++ sps->bit_depth_luma_minus8 == 2; ++ + pix_fmt->pixelformat = fmt->pixelformat; + pix_fmt->width = ctx->src_fmt.width; + pix_fmt->height = ctx->src_fmt.height; +- cedrus_prepare_format(pix_fmt); ++ ++ pix_fmt->pixelformat = fmt->pixelformat; ++ cedrus_prepare_format(pix_fmt, extended); + + return 0; + } +@@ -267,8 +288,7 @@ static int cedrus_try_fmt_vid_out(struct + if (!fmt) + return -EINVAL; + +- pix_fmt->pixelformat = fmt->pixelformat; +- cedrus_prepare_format(pix_fmt); ++ cedrus_prepare_format(pix_fmt, 0); + + return 0; + } +@@ -349,7 +369,7 @@ static int cedrus_s_fmt_vid_out(struct f + ctx->dst_fmt.quantization = f->fmt.pix.quantization; + ctx->dst_fmt.width = ctx->src_fmt.width; + ctx->dst_fmt.height = ctx->src_fmt.height; +- cedrus_prepare_format(&ctx->dst_fmt); ++ cedrus_prepare_format(&ctx->dst_fmt, 0); + + return 0; + } +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h +@@ -26,6 +26,6 @@ extern const struct v4l2_ioctl_ops cedru + + int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq); +-void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt); ++void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt, int extended); + + #endif diff --git a/projects/Allwinner/patches/linux/0032-media-cedrus-add-check-for-H264-and-HEVC-limitations.patch b/projects/Allwinner/patches/linux/0032-media-cedrus-add-check-for-H264-and-HEVC-limitations.patch new file mode 100644 index 0000000000..e16c2ce89e --- /dev/null +++ b/projects/Allwinner/patches/linux/0032-media-cedrus-add-check-for-H264-and-HEVC-limitations.patch @@ -0,0 +1,100 @@ +From f26df66c4d6ea08a865a16df82af37035401254d Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 21 Jul 2020 21:53:27 +0200 +Subject: [PATCH 32/44] media: cedrus: add check for H264 and HEVC limitations + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 49 ++++++++++++++++++++- + drivers/staging/media/sunxi/cedrus/cedrus.h | 1 + + 2 files changed, 49 insertions(+), 1 deletion(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -28,6 +28,50 @@ + #include "cedrus_dec.h" + #include "cedrus_hw.h" + ++static int cedrus_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_SPS) { ++ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; ++ ++ if (sps->chroma_format_idc != 1) ++ /* Only 4:2:0 is supported */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ if (sps->bit_depth_luma_minus8 != 0) ++ /* Only 8-bit is supported */ ++ return -EINVAL; ++ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) { ++ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; ++ struct cedrus_ctx *ctx = container_of(ctrl->handler, struct cedrus_ctx, hdl); ++ ++ if (sps->chroma_format_idc != 1) ++ /* Only 4:2:0 is supported */ ++ return -EINVAL; ++ ++ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) ++ /* Luma and chroma bit depth mismatch */ ++ return -EINVAL; ++ ++ if (ctx->dev->capabilities & CEDRUS_CAPABILITY_H265_10_DEC) { ++ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) ++ /* Only 8-bit and 10-bit are supported */ ++ return -EINVAL; ++ } else { ++ if (sps->bit_depth_luma_minus8 != 0) ++ /* Only 8-bit is supported */ ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops cedrus_ctrl_ops = { ++ .try_ctrl = cedrus_try_ctrl, ++}; ++ + static const struct cedrus_control cedrus_controls[] = { + { + .cfg = { +@@ -60,6 +104,7 @@ static const struct cedrus_control cedru + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ops = &cedrus_ctrl_ops, + }, + .codec = CEDRUS_CODEC_H264, + .required = true, +@@ -106,6 +151,7 @@ static const struct cedrus_control cedru + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .ops = &cedrus_ctrl_ops, + }, + .codec = CEDRUS_CODEC_H265, + .required = true, +@@ -534,7 +580,8 @@ static const struct cedrus_variant sun50 + + static const struct cedrus_variant sun50i_h6_cedrus_variant = { + .capabilities = CEDRUS_CAPABILITY_UNTILED | +- CEDRUS_CAPABILITY_H265_DEC, ++ CEDRUS_CAPABILITY_H265_DEC | ++ CEDRUS_CAPABILITY_H265_10_DEC, + .quirks = CEDRUS_QUIRK_NO_DMA_OFFSET, + .mod_rate = 600000000, + }; +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -28,6 +28,7 @@ + + #define CEDRUS_CAPABILITY_UNTILED BIT(0) + #define CEDRUS_CAPABILITY_H265_DEC BIT(1) ++#define CEDRUS_CAPABILITY_H265_10_DEC BIT(2) + + #define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0) + diff --git a/projects/Allwinner/patches/linux/0033-media-cedrus-Add-support-for-VP8-decoding.patch b/projects/Allwinner/patches/linux/0033-media-cedrus-Add-support-for-VP8-decoding.patch new file mode 100644 index 0000000000..6c4320868b --- /dev/null +++ b/projects/Allwinner/patches/linux/0033-media-cedrus-Add-support-for-VP8-decoding.patch @@ -0,0 +1,985 @@ +From 574ba48fa87225fbf3e39ffd2b11a6fb93cb6c98 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 20 May 2020 23:01:29 +0200 +Subject: [PATCH 33/44] media: cedrus: Add support for VP8 decoding + +VP8 in Cedrus shares same engine as H264. + +Note that it seems necessary to call bitstream parsing functions, +to parse frame header, otherwise decoded image is garbage. This is +contrary to what is driver supposed to do. However, values are not +really used, so this might be acceptable. It's possible that bitstream +parsing functions set some internal VPU state, which is later necessary +for proper decoding. Biggest suspect is "VP8 probs update" trigger. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/Makefile | 3 +- + drivers/staging/media/sunxi/cedrus/cedrus.c | 8 + + drivers/staging/media/sunxi/cedrus/cedrus.h | 15 + + .../staging/media/sunxi/cedrus/cedrus_dec.c | 5 + + .../staging/media/sunxi/cedrus/cedrus_hw.c | 1 + + .../staging/media/sunxi/cedrus/cedrus_regs.h | 80 ++ + .../staging/media/sunxi/cedrus/cedrus_video.c | 9 + + .../staging/media/sunxi/cedrus/cedrus_vp8.c | 699 ++++++++++++++++++ + 8 files changed, 819 insertions(+), 1 deletion(-) + create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_vp8.c + +--- a/drivers/staging/media/sunxi/cedrus/Makefile ++++ b/drivers/staging/media/sunxi/cedrus/Makefile +@@ -2,4 +2,5 @@ + obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o + + sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \ +- cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o ++ cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \ ++ cedrus_vp8.o +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -195,6 +195,13 @@ static const struct cedrus_control cedru + .codec = CEDRUS_CODEC_H265, + .required = false, + }, ++ { ++ .cfg = { ++ .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, ++ }, ++ .codec = CEDRUS_CODEC_VP8, ++ .required = true, ++ }, + }; + + #define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls) +@@ -446,6 +453,7 @@ static int cedrus_probe(struct platform_ + dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2; + dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264; + dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265; ++ dev->dec_ops[CEDRUS_CODEC_VP8] = &cedrus_dec_ops_vp8; + + mutex_init(&dev->dev_mutex); + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -36,6 +36,7 @@ enum cedrus_codec { + CEDRUS_CODEC_MPEG2, + CEDRUS_CODEC_H264, + CEDRUS_CODEC_H265, ++ CEDRUS_CODEC_VP8, + CEDRUS_CODEC_LAST, + }; + +@@ -78,6 +79,10 @@ struct cedrus_h265_run { + const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix; + }; + ++struct cedrus_vp8_run { ++ const struct v4l2_ctrl_vp8_frame_header *slice_params; ++}; ++ + struct cedrus_run { + struct vb2_v4l2_buffer *src; + struct vb2_v4l2_buffer *dst; +@@ -86,6 +91,7 @@ struct cedrus_run { + struct cedrus_h264_run h264; + struct cedrus_mpeg2_run mpeg2; + struct cedrus_h265_run h265; ++ struct cedrus_vp8_run vp8; + }; + }; + +@@ -143,6 +149,14 @@ struct cedrus_ctx { + void *entry_points_buf; + dma_addr_t entry_points_buf_addr; + } h265; ++ struct { ++ unsigned int last_frame_p_type; ++ unsigned int last_filter_type; ++ unsigned int last_sharpness_level; ++ ++ u8 *entropy_probs_buf; ++ dma_addr_t entropy_probs_buf_dma; ++ } vp8; + } codec; + }; + +@@ -190,6 +204,7 @@ struct cedrus_dev { + extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; + extern struct cedrus_dec_ops cedrus_dec_ops_h264; + extern struct cedrus_dec_ops cedrus_dec_ops_h265; ++extern struct cedrus_dec_ops cedrus_dec_ops_vp8; + + static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val) + { +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -72,6 +72,11 @@ void cedrus_device_run(void *priv) + V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX); + break; + ++ case V4L2_PIX_FMT_VP8_FRAME: ++ run.vp8.slice_params = cedrus_find_control_data(ctx, ++ V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER); ++ break; ++ + default: + break; + } +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +@@ -48,6 +48,7 @@ int cedrus_engine_enable(struct cedrus_c + break; + + case CEDRUS_CODEC_H264: ++ case CEDRUS_CODEC_VP8: + reg |= VE_MODE_DEC_H264; + break; + +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -552,6 +552,7 @@ + #define VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT BIT(24) + + #define VE_H264_CTRL 0x220 ++#define VE_H264_CTRL_VP8 BIT(29) + #define VE_H264_CTRL_VLD_DATA_REQ_INT BIT(2) + #define VE_H264_CTRL_DECODE_ERR_INT BIT(1) + #define VE_H264_CTRL_SLICE_DECODE_INT BIT(0) +@@ -561,7 +562,12 @@ + VE_H264_CTRL_SLICE_DECODE_INT) + + #define VE_H264_TRIGGER_TYPE 0x224 ++#define VE_H264_TRIGGER_TYPE_PROBABILITY(x) SHIFT_AND_MASK_BITS(x, 31, 24) ++#define VE_H264_TRIGGER_TYPE_BIN_LENS(x) SHIFT_AND_MASK_BITS((x) - 1, 18, 16) + #define VE_H264_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8) ++#define VE_H264_TRIGGER_TYPE_VP8_GET_BITS (15 << 0) ++#define VE_H264_TRIGGER_TYPE_VP8_UPDATE_COEF (14 << 0) ++#define VE_H264_TRIGGER_TYPE_VP8_SLICE_DECODE (10 << 0) + #define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE (8 << 0) + #define VE_H264_TRIGGER_TYPE_INIT_SWDEC (7 << 0) + #define VE_H264_TRIGGER_TYPE_FLUSH_BITS (3 << 0) +@@ -571,6 +577,7 @@ + #define VE_H264_STATUS_DECODE_ERR_INT VE_H264_CTRL_DECODE_ERR_INT + #define VE_H264_STATUS_SLICE_DECODE_INT VE_H264_CTRL_SLICE_DECODE_INT + #define VE_H264_STATUS_VLD_BUSY BIT(8) ++#define VE_H264_STATUS_VP8_UPPROB_BUSY BIT(17) + + #define VE_H264_STATUS_INT_MASK VE_H264_CTRL_INT_MASK + +@@ -589,10 +596,83 @@ + #define VE_H264_OUTPUT_FRAME_IDX 0x24c + #define VE_H264_EXTRA_BUFFER1 0x250 + #define VE_H264_EXTRA_BUFFER2 0x254 ++#define VE_H264_MB_ADDR 0x260 ++#define VE_H264_ERROR_CASE 0x2b8 + #define VE_H264_BASIC_BITS 0x2dc + #define VE_AVC_SRAM_PORT_OFFSET 0x2e0 + #define VE_AVC_SRAM_PORT_DATA 0x2e4 + ++#define VE_VP8_PPS 0x214 ++#define VE_VP8_PPS_PIC_TYPE_P_FRAME BIT(31) ++#define VE_VP8_PPS_LAST_SHARPNESS_LEVEL(v) SHIFT_AND_MASK_BITS(v, 30, 28) ++#define VE_VP8_PPS_LAST_PIC_TYPE_P_FRAME BIT(27) ++#define VE_VP8_PPS_ALTREF_SIGN_BIAS BIT(26) ++#define VE_VP8_PPS_GOLDEN_SIGN_BIAS BIT(25) ++#define VE_VP8_PPS_RELOAD_ENTROPY_PROBS BIT(24) ++#define VE_VP8_PPS_REFRESH_ENTROPY_PROBS BIT(23) ++#define VE_VP8_PPS_MB_NO_COEFF_SKIP BIT(22) ++#define VE_VP8_PPS_TOKEN_PARTITION(v) SHIFT_AND_MASK_BITS(v, 21, 20) ++#define VE_VP8_PPS_MODE_REF_LF_DELTA_UPDATE BIT(19) ++#define VE_VP8_PPS_MODE_REF_LF_DELTA_ENABLE BIT(18) ++#define VE_VP8_PPS_LOOP_FILTER_LEVEL(v) SHIFT_AND_MASK_BITS(v, 17, 12) ++#define VE_VP8_PPS_LOOP_FILTER_SIMPLE BIT(11) ++#define VE_VP8_PPS_SHARPNESS_LEVEL(v) SHIFT_AND_MASK_BITS(v, 10, 8) ++#define VE_VP8_PPS_LAST_LOOP_FILTER_SIMPLE BIT(7) ++#define VE_VP8_PPS_SEGMENTATION_ENABLE BIT(6) ++#define VE_VP8_PPS_MB_SEGMENT_ABS_DELTA BIT(5) ++#define VE_VP8_PPS_UPDATE_MB_SEGMENTATION_MAP BIT(4) ++#define VE_VP8_PPS_FULL_PIXEL BIT(3) ++#define VE_VP8_PPS_BILINEAR_MC_FILTER BIT(2) ++#define VE_VP8_PPS_FILTER_TYPE_SIMPLE BIT(1) ++#define VE_VP8_PPS_LPF_DISABLE BIT(0) ++ ++#define VE_VP8_QP_INDEX_DELTA 0x218 ++#define VE_VP8_QP_INDEX_DELTA_UVAC(v) SHIFT_AND_MASK_BITS(v, 31, 27) ++#define VE_VP8_QP_INDEX_DELTA_UVDC(v) SHIFT_AND_MASK_BITS(v, 26, 22) ++#define VE_VP8_QP_INDEX_DELTA_Y2AC(v) SHIFT_AND_MASK_BITS(v, 21, 17) ++#define VE_VP8_QP_INDEX_DELTA_Y2DC(v) SHIFT_AND_MASK_BITS(v, 16, 12) ++#define VE_VP8_QP_INDEX_DELTA_Y1DC(v) SHIFT_AND_MASK_BITS(v, 11, 7) ++#define VE_VP8_QP_INDEX_DELTA_BASE_QINDEX(v) SHIFT_AND_MASK_BITS(v, 6, 0) ++ ++#define VE_VP8_PART_SIZE_OFFSET 0x21c ++#define VE_VP8_ENTROPY_PROBS_ADDR 0x250 ++#define VE_VP8_FIRST_DATA_PART_LEN 0x254 ++ ++#define VE_VP8_FSIZE 0x258 ++#define VE_VP8_FSIZE_WIDTH(w) \ ++ SHIFT_AND_MASK_BITS(DIV_ROUND_UP(w, 16), 15, 8) ++#define VE_VP8_FSIZE_HEIGHT(h) \ ++ SHIFT_AND_MASK_BITS(DIV_ROUND_UP(h, 16), 7, 0) ++ ++#define VE_VP8_PICSIZE 0x25c ++#define VE_VP8_PICSIZE_WIDTH(w) SHIFT_AND_MASK_BITS(w, 27, 16) ++#define VE_VP8_PICSIZE_HEIGHT(h) SHIFT_AND_MASK_BITS(h, 11, 0) ++ ++#define VE_VP8_REC_LUMA 0x2ac ++#define VE_VP8_FWD_LUMA 0x2b0 ++#define VE_VP8_BWD_LUMA 0x2b4 ++#define VE_VP8_REC_CHROMA 0x2d0 ++#define VE_VP8_FWD_CHROMA 0x2d4 ++#define VE_VP8_BWD_CHROMA 0x2d8 ++#define VE_VP8_ALT_LUMA 0x2e8 ++#define VE_VP8_ALT_CHROMA 0x2ec ++ ++#define VE_VP8_SEGMENT_FEAT_MB_LV0 0x2f0 ++#define VE_VP8_SEGMENT_FEAT_MB_LV1 0x2f4 ++ ++#define VE_VP8_SEGMENT3(v) SHIFT_AND_MASK_BITS(v, 31, 24) ++#define VE_VP8_SEGMENT2(v) SHIFT_AND_MASK_BITS(v, 23, 16) ++#define VE_VP8_SEGMENT1(v) SHIFT_AND_MASK_BITS(v, 15, 8) ++#define VE_VP8_SEGMENT0(v) SHIFT_AND_MASK_BITS(v, 7, 0) ++ ++#define VE_VP8_REF_LF_DELTA 0x2f8 ++#define VE_VP8_MODE_LF_DELTA 0x2fc ++ ++#define VE_VP8_LF_DELTA3(v) SHIFT_AND_MASK_BITS(v, 30, 24) ++#define VE_VP8_LF_DELTA2(v) SHIFT_AND_MASK_BITS(v, 22, 16) ++#define VE_VP8_LF_DELTA1(v) SHIFT_AND_MASK_BITS(v, 14, 8) ++#define VE_VP8_LF_DELTA0(v) SHIFT_AND_MASK_BITS(v, 6, 0) ++ + #define VE_ISP_INPUT_SIZE 0xa00 + #define VE_ISP_INPUT_STRIDE 0xa04 + #define VE_ISP_CTRL 0xa08 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -49,6 +49,10 @@ static struct cedrus_format cedrus_forma + .capabilities = CEDRUS_CAPABILITY_H265_DEC, + }, + { ++ .pixelformat = V4L2_PIX_FMT_VP8_FRAME, ++ .directions = CEDRUS_DECODE_SRC, ++ }, ++ { + .pixelformat = V4L2_PIX_FMT_SUNXI_TILED_NV12, + .directions = CEDRUS_DECODE_DST, + }, +@@ -110,6 +114,7 @@ void cedrus_prepare_format(struct v4l2_p + case V4L2_PIX_FMT_MPEG2_SLICE: + case V4L2_PIX_FMT_H264_SLICE: + case V4L2_PIX_FMT_HEVC_SLICE: ++ case V4L2_PIX_FMT_VP8_FRAME: + /* Zero bytes per line for encoded source. */ + bytesperline = 0; + /* Choose some minimum size since this can't be 0 */ +@@ -506,6 +511,10 @@ static int cedrus_start_streaming(struct + ctx->current_codec = CEDRUS_CODEC_H265; + break; + ++ case V4L2_PIX_FMT_VP8_FRAME: ++ ctx->current_codec = CEDRUS_CODEC_VP8; ++ break; ++ + default: + return -EINVAL; + } +--- /dev/null ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c +@@ -0,0 +1,699 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Cedrus VPU driver ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "cedrus.h" ++#include "cedrus_hw.h" ++#include "cedrus_regs.h" ++ ++#define CEDRUS_ENTROPY_PROBS_SIZE 0x2400 ++#define VP8_PROB_HALF 128 ++ ++static const u8 prob_table_init[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xB0, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xF1, 0xFC, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF9, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF4, 0xFC, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xEA, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xF6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xEF, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xFE, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFE, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFB, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFE, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xE1, 0xFC, 0xF1, 0xFD, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xEA, 0xFA, 0xF1, 0xFA, 0xFD, 0xFF, 0xFD, 0xFE, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFD, 0xFE, 0xFE, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xFE, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFD, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xBA, 0xFB, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0xFB, 0xF4, 0xFE, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFB, 0xFB, 0xF3, 0xFD, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFE, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xEC, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFE, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xF9, 0xFD, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFD, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFC, 0xFE, 0xFB, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFC, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF8, 0xFE, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xF5, 0xFB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFE, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFD, 0xFE, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF9, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x9C, 0xA3, 0x80, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x96, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x78, 0x5A, 0x4F, 0x85, 0x57, 0x55, 0x50, 0x6F, ++ 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x93, 0x88, 0x12, 0x00, 0x6A, 0x91, 0x01, 0x00, 0xB3, 0x79, 0x01, 0x00, ++ 0xDF, 0x01, 0x22, 0x00, 0xD0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x01, 0x8F, ++ 0x0E, 0x12, 0x0E, 0x6B, 0x87, 0x40, 0x39, 0x44, 0x3C, 0x38, 0x80, 0x41, ++ 0x9F, 0x86, 0x80, 0x22, 0xEA, 0xBC, 0x80, 0x1C, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x84, 0x02, 0x04, 0x06, 0x80, 0x81, 0x82, 0x83, 0x80, 0x02, 0x04, 0x06, ++ 0x81, 0x82, 0x83, 0x84, 0x80, 0x02, 0x81, 0x04, 0x82, 0x83, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, ++ 0x04, 0x06, 0x80, 0x81, 0x82, 0x83, 0x0A, 0x0C, 0x84, 0x85, 0x86, 0x87, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x06, 0x80, 0x81, ++ 0x82, 0x83, 0x0A, 0x0C, 0x84, 0x85, 0x86, 0x87, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x83, 0x02, 0x82, 0x04, 0x80, 0x81, 0x00, 0x00, 0x80, 0x02, 0x81, 0x04, ++ 0x82, 0x06, 0x08, 0x0C, 0x83, 0x0A, 0x85, 0x86, 0x84, 0x0E, 0x87, 0x10, ++ 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x8A, 0x02, 0x8B, 0x04, 0x8C, 0x8D, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x87, 0x02, 0x85, 0x04, 0x86, 0x06, 0x88, 0x89, ++}; ++ ++static const u8 vp8_mv_update_prob[2][19] = { ++ { 237, 246, 253, 253, 254, 254, 254, 254, 254, ++ 254, 254, 254, 254, 254, 250, 250, 252, 254, 254 }, ++ { 231, 243, 245, 253, 254, 254, 254, 254, 254, ++ 254, 254, 254, 254, 254, 251, 251, 254, 254, 254 } ++}; ++ ++static uint8_t read_bits(struct cedrus_dev *dev, unsigned int bits_count, ++ unsigned int probability) ++{ ++ cedrus_write(dev, VE_H264_TRIGGER_TYPE, ++ VE_H264_TRIGGER_TYPE_VP8_GET_BITS | ++ VE_H264_TRIGGER_TYPE_BIN_LENS(bits_count) | ++ VE_H264_TRIGGER_TYPE_PROBABILITY(probability)); ++ ++ while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VLD_BUSY) ++ ; ++ ++ return cedrus_read(dev, VE_H264_BASIC_BITS); ++} ++ ++static void get_delta_q(struct cedrus_dev *dev) ++{ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 4, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++ } ++} ++ ++static void process_segmentation_info(struct cedrus_dev *dev) ++{ ++ int update = read_bits(dev, 1, VP8_PROB_HALF); ++ int i; ++ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 1, VP8_PROB_HALF); ++ ++ for (i = 0; i < 4; i++) ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 7, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++ } ++ ++ for (i = 0; i < 4; i++) ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 6, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++ } ++ } ++ ++ if (update) ++ for (i = 0; i < 3; i++) ++ if (read_bits(dev, 1, VP8_PROB_HALF)) ++ read_bits(dev, 8, VP8_PROB_HALF); ++} ++ ++static void process_ref_lf_delta_info(struct cedrus_dev *dev) ++{ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ int i; ++ ++ for (i = 0; i < 4; i++) ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 6, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++ } ++ ++ for (i = 0; i < 4; i++) ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 6, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++ } ++ } ++} ++ ++static void process_ref_frame_info(struct cedrus_dev *dev) ++{ ++ u8 refresh_golden_frame = read_bits(dev, 1, VP8_PROB_HALF); ++ u8 refresh_alt_ref_frame = read_bits(dev, 1, VP8_PROB_HALF); ++ ++ if (!refresh_golden_frame) ++ read_bits(dev, 2, VP8_PROB_HALF); ++ ++ if (!refresh_alt_ref_frame) ++ read_bits(dev, 2, VP8_PROB_HALF); ++ ++ read_bits(dev, 1, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++} ++ ++static void cedrus_read_header(struct cedrus_dev *dev, ++ const struct v4l2_ctrl_vp8_frame_header *slice) ++{ ++ int i, j; ++ ++ if (VP8_FRAME_IS_KEY_FRAME(slice)) { ++ read_bits(dev, 1, VP8_PROB_HALF); ++ read_bits(dev, 1, VP8_PROB_HALF); ++ } ++ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) ++ process_segmentation_info(dev); ++ ++ read_bits(dev, 1, VP8_PROB_HALF); ++ read_bits(dev, 6, VP8_PROB_HALF); ++ read_bits(dev, 3, VP8_PROB_HALF); ++ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) ++ process_ref_lf_delta_info(dev); ++ ++ read_bits(dev, 2, VP8_PROB_HALF); ++ read_bits(dev, 7, VP8_PROB_HALF); ++ ++ get_delta_q(dev); ++ get_delta_q(dev); ++ get_delta_q(dev); ++ get_delta_q(dev); ++ get_delta_q(dev); ++ ++ if (!VP8_FRAME_IS_KEY_FRAME(slice)) ++ process_ref_frame_info(dev); ++ ++ read_bits(dev, 1, VP8_PROB_HALF); ++ ++ if (!VP8_FRAME_IS_KEY_FRAME(slice)) ++ read_bits(dev, 1, VP8_PROB_HALF); ++ ++ cedrus_write(dev, VE_H264_TRIGGER_TYPE, VE_H264_TRIGGER_TYPE_VP8_UPDATE_COEF); ++ while (cedrus_read(dev, VE_H264_STATUS) & VE_H264_STATUS_VP8_UPPROB_BUSY) ++ ; ++ ++ cedrus_write(dev, VE_H264_STATUS, VE_H264_CTRL_INT_MASK); ++ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) ++ read_bits(dev, 8, VP8_PROB_HALF); ++ ++ if (!VP8_FRAME_IS_KEY_FRAME(slice)) { ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ } ++ ++ if (read_bits(dev, 1, VP8_PROB_HALF)) { ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ read_bits(dev, 8, VP8_PROB_HALF); ++ } ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < 19; j++) ++ if (read_bits(dev, 1, vp8_mv_update_prob[i][j])) ++ read_bits(dev, 7, VP8_PROB_HALF); ++ } ++} ++ ++static void cedrus_vp8_update_probs(const struct v4l2_ctrl_vp8_frame_header *slice, ++ u8 *prob_table) ++{ ++ int i, j, k; ++ ++ memcpy(&prob_table[0x1008], slice->entropy_header.y_mode_probs, 4); ++ memcpy(&prob_table[0x1010], slice->entropy_header.uv_mode_probs, 3); ++ ++ memcpy(&prob_table[0x1018], slice->segment_header.segment_probs, 3); ++ ++ prob_table[0x101c] = slice->prob_skip_false; ++ prob_table[0x101d] = slice->prob_intra; ++ prob_table[0x101e] = slice->prob_last; ++ prob_table[0x101f] = slice->prob_gf; ++ ++ memcpy(&prob_table[0x1020], slice->entropy_header.mv_probs[0], 19); ++ memcpy(&prob_table[0x1040], slice->entropy_header.mv_probs[1], 19); ++ ++ for (i = 0; i < 4; ++i) ++ for (j = 0; j < 8; ++j) ++ for (k = 0; k < 3; ++k) ++ memcpy(&prob_table[i * 512 + j * 64 + k * 16], ++ slice->entropy_header.coeff_probs[i][j][k], 11); ++} ++ ++static enum cedrus_irq_status ++cedrus_vp8_irq_status(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ u32 reg = cedrus_read(dev, VE_H264_STATUS); ++ ++ if (reg & (VE_H264_STATUS_DECODE_ERR_INT | ++ VE_H264_STATUS_VLD_DATA_REQ_INT)) ++ return CEDRUS_IRQ_ERROR; ++ ++ if (reg & VE_H264_CTRL_SLICE_DECODE_INT) ++ return CEDRUS_IRQ_OK; ++ ++ return CEDRUS_IRQ_NONE; ++} ++ ++static void cedrus_vp8_irq_clear(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ cedrus_write(dev, VE_H264_STATUS, ++ VE_H264_STATUS_INT_MASK); ++} ++ ++static void cedrus_vp8_irq_disable(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ u32 reg = cedrus_read(dev, VE_H264_CTRL); ++ ++ cedrus_write(dev, VE_H264_CTRL, ++ reg & ~VE_H264_CTRL_INT_MASK); ++} ++ ++static void cedrus_vp8_setup(struct cedrus_ctx *ctx, ++ struct cedrus_run *run) ++{ ++ const struct v4l2_ctrl_vp8_frame_header *slice = run->vp8.slice_params; ++ struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; ++ struct vb2_buffer *src_buf = &run->src->vb2_buf; ++ struct cedrus_dev *dev = ctx->dev; ++ dma_addr_t luma_addr, chroma_addr; ++ dma_addr_t src_buf_addr; ++ int header_size; ++ int qindex; ++ u32 reg; ++ ++ cedrus_engine_enable(ctx, CEDRUS_CODEC_VP8); ++ ++ cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8); ++ ++ cedrus_vp8_update_probs(slice, ctx->codec.vp8.entropy_probs_buf); ++ ++ reg = slice->first_part_size * 8; ++ cedrus_write(dev, VE_VP8_FIRST_DATA_PART_LEN, reg); ++ ++ header_size = VP8_FRAME_IS_KEY_FRAME(slice) ? 10 : 3; ++ ++ reg = slice->first_part_size + header_size; ++ cedrus_write(dev, VE_VP8_PART_SIZE_OFFSET, reg); ++ ++ reg = vb2_plane_size(src_buf, 0) * 8; ++ cedrus_write(dev, VE_H264_VLD_LEN, reg); ++ ++ /* ++ * FIXME: There is a problem if frame header is skipped (adding ++ * first_part_header_bits to offset). It seems that functions ++ * for parsing bitstreams change internal state of VPU in some ++ * way that can't be otherwise set. Maybe this can be bypassed ++ * by somehow fixing probability table buffer? ++ */ ++ reg = header_size * 8; ++ cedrus_write(dev, VE_H264_VLD_OFFSET, reg); ++ ++ src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); ++ cedrus_write(dev, VE_H264_VLD_END, ++ src_buf_addr + vb2_get_plane_payload(src_buf, 0)); ++ cedrus_write(dev, VE_H264_VLD_ADDR, ++ VE_H264_VLD_ADDR_VAL(src_buf_addr) | ++ VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID | ++ VE_H264_VLD_ADDR_LAST); ++ ++ cedrus_write(dev, VE_H264_TRIGGER_TYPE, ++ VE_H264_TRIGGER_TYPE_INIT_SWDEC); ++ ++ cedrus_write(dev, VE_VP8_ENTROPY_PROBS_ADDR, ++ ctx->codec.vp8.entropy_probs_buf_dma); ++ ++ reg = 0; ++ switch (slice->version) { ++ case 1: ++ reg |= VE_VP8_PPS_FILTER_TYPE_SIMPLE; ++ reg |= VE_VP8_PPS_BILINEAR_MC_FILTER; ++ break; ++ case 2: ++ reg |= VE_VP8_PPS_LPF_DISABLE; ++ reg |= VE_VP8_PPS_BILINEAR_MC_FILTER; ++ break; ++ case 3: ++ reg |= VE_VP8_PPS_LPF_DISABLE; ++ reg |= VE_VP8_PPS_FULL_PIXEL; ++ break; ++ } ++ if (slice->segment_header.flags & V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP) ++ reg |= VE_VP8_PPS_UPDATE_MB_SEGMENTATION_MAP; ++ if (!(slice->segment_header.flags & V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE)) ++ reg |= VE_VP8_PPS_MB_SEGMENT_ABS_DELTA; ++ if (slice->segment_header.flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED) ++ reg |= VE_VP8_PPS_SEGMENTATION_ENABLE; ++ if (ctx->codec.vp8.last_filter_type) ++ reg |= VE_VP8_PPS_LAST_LOOP_FILTER_SIMPLE; ++ reg |= VE_VP8_PPS_SHARPNESS_LEVEL(slice->lf_header.sharpness_level); ++ if (slice->lf_header.flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE) ++ reg |= VE_VP8_PPS_LOOP_FILTER_SIMPLE; ++ reg |= VE_VP8_PPS_LOOP_FILTER_LEVEL(slice->lf_header.level); ++ if (slice->lf_header.flags & V4L2_VP8_LF_HEADER_ADJ_ENABLE) ++ reg |= VE_VP8_PPS_MODE_REF_LF_DELTA_ENABLE; ++ if (slice->lf_header.flags & V4L2_VP8_LF_HEADER_DELTA_UPDATE) ++ reg |= VE_VP8_PPS_MODE_REF_LF_DELTA_UPDATE; ++ reg |= VE_VP8_PPS_TOKEN_PARTITION(ilog2(slice->num_dct_parts)); ++ if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF) ++ reg |= VE_VP8_PPS_MB_NO_COEFF_SKIP; ++ reg |= VE_VP8_PPS_RELOAD_ENTROPY_PROBS; ++ if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN) ++ reg |= VE_VP8_PPS_GOLDEN_SIGN_BIAS; ++ if (slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT) ++ reg |= VE_VP8_PPS_ALTREF_SIGN_BIAS; ++ if (ctx->codec.vp8.last_frame_p_type) ++ reg |= VE_VP8_PPS_LAST_PIC_TYPE_P_FRAME; ++ reg |= VE_VP8_PPS_LAST_SHARPNESS_LEVEL(ctx->codec.vp8.last_sharpness_level); ++ if (!(slice->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) ++ reg |= VE_VP8_PPS_PIC_TYPE_P_FRAME; ++ cedrus_write(dev, VE_VP8_PPS, reg); ++ ++ cedrus_read_header(dev, slice); ++ ++ /* reset registers changed by HW */ ++ cedrus_write(dev, VE_H264_CUR_MB_NUM, 0); ++ cedrus_write(dev, VE_H264_MB_ADDR, 0); ++ cedrus_write(dev, VE_H264_ERROR_CASE, 0); ++ ++ reg = 0; ++ reg |= VE_VP8_QP_INDEX_DELTA_UVAC(slice->quant_header.uv_ac_delta); ++ reg |= VE_VP8_QP_INDEX_DELTA_UVDC(slice->quant_header.uv_dc_delta); ++ reg |= VE_VP8_QP_INDEX_DELTA_Y2AC(slice->quant_header.y2_ac_delta); ++ reg |= VE_VP8_QP_INDEX_DELTA_Y2DC(slice->quant_header.y2_dc_delta); ++ reg |= VE_VP8_QP_INDEX_DELTA_Y1DC(slice->quant_header.y_dc_delta); ++ reg |= VE_VP8_QP_INDEX_DELTA_BASE_QINDEX(slice->quant_header.y_ac_qi); ++ cedrus_write(dev, VE_VP8_QP_INDEX_DELTA, reg); ++ ++ reg = 0; ++ reg |= VE_VP8_FSIZE_WIDTH(slice->width); ++ reg |= VE_VP8_FSIZE_HEIGHT(slice->height); ++ cedrus_write(dev, VE_VP8_FSIZE, reg); ++ ++ reg = 0; ++ reg |= VE_VP8_PICSIZE_WIDTH(slice->width); ++ reg |= VE_VP8_PICSIZE_HEIGHT(slice->height); ++ cedrus_write(dev, VE_VP8_PICSIZE, reg); ++ ++ reg = 0; ++ reg |= VE_VP8_SEGMENT3(slice->segment_header.quant_update[3]); ++ reg |= VE_VP8_SEGMENT2(slice->segment_header.quant_update[2]); ++ reg |= VE_VP8_SEGMENT1(slice->segment_header.quant_update[1]); ++ reg |= VE_VP8_SEGMENT0(slice->segment_header.quant_update[0]); ++ cedrus_write(dev, VE_VP8_SEGMENT_FEAT_MB_LV0, reg); ++ ++ reg = 0; ++ reg |= VE_VP8_SEGMENT3(slice->segment_header.lf_update[3]); ++ reg |= VE_VP8_SEGMENT2(slice->segment_header.lf_update[2]); ++ reg |= VE_VP8_SEGMENT1(slice->segment_header.lf_update[1]); ++ reg |= VE_VP8_SEGMENT0(slice->segment_header.lf_update[0]); ++ cedrus_write(dev, VE_VP8_SEGMENT_FEAT_MB_LV1, reg); ++ ++ reg = 0; ++ reg |= VE_VP8_LF_DELTA3(slice->lf_header.ref_frm_delta[3]); ++ reg |= VE_VP8_LF_DELTA2(slice->lf_header.ref_frm_delta[2]); ++ reg |= VE_VP8_LF_DELTA1(slice->lf_header.ref_frm_delta[1]); ++ reg |= VE_VP8_LF_DELTA0(slice->lf_header.ref_frm_delta[0]); ++ cedrus_write(dev, VE_VP8_REF_LF_DELTA, reg); ++ ++ reg = 0; ++ reg |= VE_VP8_LF_DELTA3(slice->lf_header.mb_mode_delta[3]); ++ reg |= VE_VP8_LF_DELTA2(slice->lf_header.mb_mode_delta[2]); ++ reg |= VE_VP8_LF_DELTA1(slice->lf_header.mb_mode_delta[1]); ++ reg |= VE_VP8_LF_DELTA0(slice->lf_header.mb_mode_delta[0]); ++ cedrus_write(dev, VE_VP8_MODE_LF_DELTA, reg); ++ ++ luma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 0); ++ chroma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 1); ++ cedrus_write(dev, VE_VP8_REC_LUMA, luma_addr); ++ cedrus_write(dev, VE_VP8_REC_CHROMA, chroma_addr); ++ ++ qindex = vb2_find_timestamp(cap_q, slice->last_frame_ts, 0); ++ if (qindex >= 0) { ++ luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0); ++ chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1); ++ cedrus_write(dev, VE_VP8_FWD_LUMA, luma_addr); ++ cedrus_write(dev, VE_VP8_FWD_CHROMA, chroma_addr); ++ } else { ++ cedrus_write(dev, VE_VP8_FWD_LUMA, 0); ++ cedrus_write(dev, VE_VP8_FWD_CHROMA, 0); ++ } ++ ++ qindex = vb2_find_timestamp(cap_q, slice->golden_frame_ts, 0); ++ if (qindex >= 0) { ++ luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0); ++ chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1); ++ cedrus_write(dev, VE_VP8_BWD_LUMA, luma_addr); ++ cedrus_write(dev, VE_VP8_BWD_CHROMA, chroma_addr); ++ } else { ++ cedrus_write(dev, VE_VP8_BWD_LUMA, 0); ++ cedrus_write(dev, VE_VP8_BWD_CHROMA, 0); ++ } ++ ++ qindex = vb2_find_timestamp(cap_q, slice->alt_frame_ts, 0); ++ if (qindex >= 0) { ++ luma_addr = cedrus_dst_buf_addr(ctx, qindex, 0); ++ chroma_addr = cedrus_dst_buf_addr(ctx, qindex, 1); ++ cedrus_write(dev, VE_VP8_ALT_LUMA, luma_addr); ++ cedrus_write(dev, VE_VP8_ALT_CHROMA, chroma_addr); ++ } else { ++ cedrus_write(dev, VE_VP8_ALT_LUMA, 0); ++ cedrus_write(dev, VE_VP8_ALT_CHROMA, 0); ++ } ++ ++ cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8 | ++ VE_H264_CTRL_DECODE_ERR_INT | ++ VE_H264_CTRL_SLICE_DECODE_INT); ++ ++ if (slice->lf_header.level) { ++ ctx->codec.vp8.last_filter_type = ++ !!(slice->lf_header.flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE); ++ ctx->codec.vp8.last_frame_p_type = ++ !VP8_FRAME_IS_KEY_FRAME(slice); ++ ctx->codec.vp8.last_sharpness_level = ++ slice->lf_header.sharpness_level; ++ } ++} ++ ++static int cedrus_vp8_start(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ ctx->codec.vp8.entropy_probs_buf = ++ dma_alloc_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE, ++ &ctx->codec.vp8.entropy_probs_buf_dma, ++ GFP_KERNEL); ++ if (!ctx->codec.vp8.entropy_probs_buf) ++ return -ENOMEM; ++ ++ memcpy(&ctx->codec.vp8.entropy_probs_buf[2048], ++ prob_table_init, sizeof(prob_table_init)); ++ ++ return 0; ++} ++ ++static void cedrus_vp8_stop(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ cedrus_engine_disable(dev); ++ ++ dma_free_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE, ++ ctx->codec.vp8.entropy_probs_buf, ++ ctx->codec.vp8.entropy_probs_buf_dma); ++} ++ ++static void cedrus_vp8_trigger(struct cedrus_ctx *ctx) ++{ ++ struct cedrus_dev *dev = ctx->dev; ++ ++ cedrus_write(dev, VE_H264_TRIGGER_TYPE, ++ VE_H264_TRIGGER_TYPE_VP8_SLICE_DECODE); ++} ++ ++struct cedrus_dec_ops cedrus_dec_ops_vp8 = { ++ .irq_clear = cedrus_vp8_irq_clear, ++ .irq_disable = cedrus_vp8_irq_disable, ++ .irq_status = cedrus_vp8_irq_status, ++ .setup = cedrus_vp8_setup, ++ .start = cedrus_vp8_start, ++ .stop = cedrus_vp8_stop, ++ .trigger = cedrus_vp8_trigger, ++}; diff --git a/projects/Allwinner/patches/linux/0034-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch b/projects/Allwinner/patches/linux/0034-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch new file mode 100644 index 0000000000..1f9d4ce0ea --- /dev/null +++ b/projects/Allwinner/patches/linux/0034-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch @@ -0,0 +1,57 @@ +From f826ffb93b1ba0cfb9a5cfa3403813674331d4e0 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 26 Feb 2019 20:45:14 +0000 +Subject: [PATCH 34/44] WIP: dw-hdmi-cec: sleep 100ms on error + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c +@@ -4,6 +4,7 @@ + * + * Copyright (C) 2015-2017 Russell King. + */ ++#include + #include + #include + #include +@@ -129,8 +130,15 @@ static irqreturn_t dw_hdmi_cec_hardirq(i + + dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); + +- if (stat & CEC_STAT_ERROR_INIT) { +- cec->tx_status = CEC_TX_STATUS_ERROR; ++ /* Status with both done and error_initiator bits have been seen ++ * on Rockchip RK3328 devices, transmit attempt seems to have failed ++ * when this happens, report as low drive and block cec-framework ++ * 100ms before core retransmits the failed message, this seems to ++ * mitigate the issue with failed transmit attempts. ++ */ ++ if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) { ++ pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat); ++ cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; + } else if (stat & CEC_STAT_DONE) { +@@ -141,6 +149,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(i + cec->tx_status = CEC_TX_STATUS_NACK; + cec->tx_done = true; + ret = IRQ_WAKE_THREAD; ++ } else if (stat & CEC_STAT_ERROR_INIT) { ++ cec->tx_status = CEC_TX_STATUS_ERROR; ++ cec->tx_done = true; ++ ret = IRQ_WAKE_THREAD; + } + + if (stat & CEC_STAT_EOM) { +@@ -173,6 +185,8 @@ static irqreturn_t dw_hdmi_cec_thread(in + + if (cec->tx_done) { + cec->tx_done = false; ++ if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE) ++ msleep(100); + cec_transmit_attempt_done(adap, cec->tx_status); + } + if (cec->rx_done) { diff --git a/projects/Allwinner/patches/linux/0007-drm-fixes.patch b/projects/Allwinner/patches/linux/0035-drm-sun4i-Reimplement-plane-z-position-setting-logic.patch similarity index 60% rename from projects/Allwinner/patches/linux/0007-drm-fixes.patch rename to projects/Allwinner/patches/linux/0035-drm-sun4i-Reimplement-plane-z-position-setting-logic.patch index 65db2f9e01..1f8eab64dd 100644 --- a/projects/Allwinner/patches/linux/0007-drm-fixes.patch +++ b/projects/Allwinner/patches/linux/0035-drm-sun4i-Reimplement-plane-z-position-setting-logic.patch @@ -1,7 +1,7 @@ -From 8132877d34935f3d0a2c661f00f67f782b6bc8f8 Mon Sep 17 00:00:00 2001 +From f1c04148f8cc62bf99cb06e348f04452d307ebc8 Mon Sep 17 00:00:00 2001 From: Roman Stratiienko Date: Sat, 28 Dec 2019 22:28:17 +0200 -Subject: [PATCH 1/3] drm/sun4i: Reimplement plane z position setting logic +Subject: [PATCH 35/44] drm/sun4i: Reimplement plane z position setting logic To set blending channel order register software needs to know state and position of each channel, which impossible at plane commit stage. @@ -18,14 +18,13 @@ Signed-off-by: Jernej Skrabec drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 39 +++-------------------- 4 files changed, 57 insertions(+), 72 deletions(-) -diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c -index cc4fb916318f..1ad704b737cf 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c -@@ -250,8 +250,45 @@ int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format) +@@ -250,8 +250,45 @@ int sun8i_mixer_drm_format_to_hw(u32 for static void sun8i_mixer_commit(struct sunxi_engine *engine) { +- DRM_DEBUG_DRIVER("Committing changes\n"); + struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + int channel_by_zpos[SUN8I_MIXER_MAX_CHANNELS]; + u32 base = sun8i_blender_base(mixer); @@ -46,7 +45,7 @@ index cc4fb916318f..1ad704b737cf 100644 + if (zpos >= 0 && zpos < channel_count) + channel_by_zpos[zpos] = i; + } -+ + + j = 0; + for (i = 0; i < channel_count; i++) { + int ch = channel_by_zpos[i]; @@ -64,12 +63,11 @@ index cc4fb916318f..1ad704b737cf 100644 + regmap_write(mixer->engine.regs, + SUN8I_MIXER_BLEND_ROUTE(base), route); + - DRM_DEBUG_DRIVER("Committing changes\n"); -- ++ DRM_DEBUG_DRIVER("Committing changes\n"); regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); } -@@ -489,10 +526,12 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, +@@ -489,10 +526,12 @@ static int sun8i_mixer_bind(struct devic SUN8I_MIXER_BLEND_COLOR_BLACK); plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; @@ -83,8 +81,6 @@ index cc4fb916318f..1ad704b737cf 100644 regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); -diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h -index 7576b523fdbb..7b378d6e4dd9 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -12,6 +12,8 @@ @@ -96,7 +92,7 @@ index 7576b523fdbb..7b378d6e4dd9 100644 #define SUN8I_MIXER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1)) #define SUN8I_MIXER_COORD(x, y) ((y) << 16 | (x)) -@@ -179,6 +181,9 @@ struct sun8i_mixer { +@@ -177,6 +179,9 @@ struct sun8i_mixer { struct clk *bus_clk; struct clk *mod_clk; @@ -106,8 +102,6 @@ index 7576b523fdbb..7b378d6e4dd9 100644 }; static inline struct sun8i_mixer * -diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c -index 54f937a7d5e7..651d3bf096c6 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -24,12 +24,10 @@ @@ -125,7 +119,7 @@ index 54f937a7d5e7..651d3bf096c6 100644 ch_base = sun8i_channel_base(mixer, channel); DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n", -@@ -44,32 +42,7 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel, +@@ -44,32 +42,7 @@ static void sun8i_ui_layer_enable(struct SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val); @@ -159,7 +153,7 @@ index 54f937a7d5e7..651d3bf096c6 100644 } static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, -@@ -267,11 +240,9 @@ static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane, +@@ -267,11 +240,9 @@ static void sun8i_ui_layer_atomic_disabl struct drm_plane_state *old_state) { struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); @@ -172,7 +166,7 @@ index 54f937a7d5e7..651d3bf096c6 100644 } static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, -@@ -279,12 +250,11 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, +@@ -279,12 +250,11 @@ static void sun8i_ui_layer_atomic_update { struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); unsigned int zpos = plane->state->normalized_zpos; @@ -186,7 +180,7 @@ index 54f937a7d5e7..651d3bf096c6 100644 return; } -@@ -295,7 +265,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, +@@ -295,7 +265,7 @@ static void sun8i_ui_layer_atomic_update sun8i_ui_layer_update_buffer(mixer, layer->channel, layer->overlay, plane); sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, @@ -194,9 +188,7 @@ index 54f937a7d5e7..651d3bf096c6 100644 + true, zpos); } - static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { -diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c -index 22c8c5375d0d..bd28e76363d9 100644 + static const struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -18,8 +18,7 @@ @@ -209,7 +201,7 @@ index 22c8c5375d0d..bd28e76363d9 100644 { u32 val, bld_base, ch_base; -@@ -38,32 +37,7 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, +@@ -38,32 +37,7 @@ static void sun8i_vi_layer_enable(struct SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); @@ -243,7 +235,7 @@ index 22c8c5375d0d..bd28e76363d9 100644 } static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, -@@ -370,11 +344,9 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, +@@ -370,11 +344,9 @@ static void sun8i_vi_layer_atomic_disabl struct drm_plane_state *old_state) { struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); @@ -256,7 +248,7 @@ index 22c8c5375d0d..bd28e76363d9 100644 } static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, -@@ -382,12 +354,11 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, +@@ -382,12 +354,11 @@ static void sun8i_vi_layer_atomic_update { struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); unsigned int zpos = plane->state->normalized_zpos; @@ -270,7 +262,7 @@ index 22c8c5375d0d..bd28e76363d9 100644 return; } -@@ -398,7 +369,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, +@@ -398,7 +369,7 @@ static void sun8i_vi_layer_atomic_update sun8i_vi_layer_update_buffer(mixer, layer->channel, layer->overlay, plane); sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, @@ -278,112 +270,4 @@ index 22c8c5375d0d..bd28e76363d9 100644 + true, zpos); } - static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { --- -2.27.0 - - -From 9d11b18afdb63d60714a78c5966f674aa66ee6b9 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sun, 19 Jul 2020 11:28:49 +0200 -Subject: [PATCH 2/3] drm/sun4i: Don't use update regmap variant for blend pipe - register - -Readout might return invalid value, so always write it. - -Signed-off-by: Jernej Skrabec ---- - drivers/gpu/drm/sun4i/sun8i_mixer.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c -index 1ad704b737cf..8825518e06c8 100644 ---- a/drivers/gpu/drm/sun4i/sun8i_mixer.c -+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c -@@ -282,8 +282,14 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine) - } - } - -- regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), -- SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, pipe_ctl); -+ /* -+ * Set fill color of bottom plane to black. Generally not needed -+ * except when VI plane is at bottom (zpos = 0) and enabled. -+ */ -+ pipe_ctl |= SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0); -+ -+ regmap_write(mixer->engine.regs, -+ SUN8I_MIXER_BLEND_PIPE_CTL(base), pipe_ctl); - - regmap_write(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE(base), route); -@@ -516,12 +522,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base), - SUN8I_MIXER_BLEND_COLOR_BLACK); - -- /* -- * Set fill color of bottom plane to black. Generally not needed -- * except when VI plane is at bottom (zpos = 0) and enabled. -- */ -- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), -- SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), - SUN8I_MIXER_BLEND_COLOR_BLACK); - -@@ -533,9 +533,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, - mixer->channel_zpos[i] = -1; - } - -- regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), -- SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); -- - return 0; - - err_disable_bus_clk: --- -2.27.0 - - -From bb41e6a8620fc7c3fd91be8155ef5972ea04c0c8 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sun, 19 Jul 2020 11:37:41 +0200 -Subject: [PATCH 3/3] drm/sun4i: mixer: Add caching support - -Most registers are not safe to read out so enable cache in regmap. - -Signed-off-by: Jernej Skrabec ---- - drivers/gpu/drm/sun4i/sun8i_mixer.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c -index 8825518e06c8..006b746b0e95 100644 ---- a/drivers/gpu/drm/sun4i/sun8i_mixer.c -+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c -@@ -346,11 +346,23 @@ static const struct sunxi_engine_ops sun8i_engine_ops = { - .layers_init = sun8i_layers_init, - }; - -+static bool sun8i_mixer_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case SUN8I_MIXER_GLOBAL_STATUS: -+ case SUN8I_MIXER_GLOBAL_DBUFF: -+ return true; -+ } -+ return false; -+} -+ - static const struct regmap_config sun8i_mixer_regmap_config = { -+ .cache_type = REGCACHE_FLAT, - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0xffffc, /* guessed */ -+ .volatile_reg = sun8i_mixer_volatile_reg, - }; - - static int sun8i_mixer_of_get_id(struct device_node *node) --- -2.27.0 - + static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { diff --git a/projects/Allwinner/patches/linux/0036-drm-sun4i-Don-t-use-update-regmap-variant-for-blend-.patch b/projects/Allwinner/patches/linux/0036-drm-sun4i-Don-t-use-update-regmap-variant-for-blend-.patch new file mode 100644 index 0000000000..6dbad80533 --- /dev/null +++ b/projects/Allwinner/patches/linux/0036-drm-sun4i-Don-t-use-update-regmap-variant-for-blend-.patch @@ -0,0 +1,55 @@ +From 144ad308ded7c5617d9574e174b68cbcb622cf4c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 19 Jul 2020 11:28:49 +0200 +Subject: [PATCH 36/44] drm/sun4i: Don't use update regmap variant for blend + pipe register + +Readout might return invalid value, so always write it. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -282,8 +282,14 @@ static void sun8i_mixer_commit(struct su + } + } + +- regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), +- SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, pipe_ctl); ++ /* ++ * Set fill color of bottom plane to black. Generally not needed ++ * except when VI plane is at bottom (zpos = 0) and enabled. ++ */ ++ pipe_ctl |= SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0); ++ ++ regmap_write(mixer->engine.regs, ++ SUN8I_MIXER_BLEND_PIPE_CTL(base), pipe_ctl); + + regmap_write(mixer->engine.regs, + SUN8I_MIXER_BLEND_ROUTE(base), route); +@@ -516,12 +522,6 @@ static int sun8i_mixer_bind(struct devic + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base), + SUN8I_MIXER_BLEND_COLOR_BLACK); + +- /* +- * Set fill color of bottom plane to black. Generally not needed +- * except when VI plane is at bottom (zpos = 0) and enabled. +- */ +- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), +- SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), + SUN8I_MIXER_BLEND_COLOR_BLACK); + +@@ -533,9 +533,6 @@ static int sun8i_mixer_bind(struct devic + mixer->channel_zpos[i] = -1; + } + +- regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), +- SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); +- + return 0; + + err_disable_bus_clk: diff --git a/projects/Allwinner/patches/linux/0037-drm-sun4i-mixer-Add-caching-support.patch b/projects/Allwinner/patches/linux/0037-drm-sun4i-mixer-Add-caching-support.patch new file mode 100644 index 0000000000..fe9c05aeab --- /dev/null +++ b/projects/Allwinner/patches/linux/0037-drm-sun4i-mixer-Add-caching-support.patch @@ -0,0 +1,38 @@ +From 2e5d4ca1c07ddf06f8c3b18fd73baea7ce711169 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 19 Jul 2020 11:37:41 +0200 +Subject: [PATCH 37/44] drm/sun4i: mixer: Add caching support + +Most registers are not safe to read out so enable cache in regmap. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -346,11 +346,23 @@ static const struct sunxi_engine_ops sun + .layers_init = sun8i_layers_init, + }; + ++static bool sun8i_mixer_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case SUN8I_MIXER_GLOBAL_STATUS: ++ case SUN8I_MIXER_GLOBAL_DBUFF: ++ return true; ++ } ++ return false; ++} ++ + static const struct regmap_config sun8i_mixer_regmap_config = { ++ .cache_type = REGCACHE_FLAT, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0xffffc, /* guessed */ ++ .volatile_reg = sun8i_mixer_volatile_reg, + }; + + static int sun8i_mixer_of_get_id(struct device_node *node) diff --git a/projects/Allwinner/patches/linux/0014-AC200.patch b/projects/Allwinner/patches/linux/0038-mfd-Add-support-for-AC200.patch similarity index 58% rename from projects/Allwinner/patches/linux/0014-AC200.patch rename to projects/Allwinner/patches/linux/0038-mfd-Add-support-for-AC200.patch index 00e50ea0ab..04dd0106f8 100644 --- a/projects/Allwinner/patches/linux/0014-AC200.patch +++ b/projects/Allwinner/patches/linux/0038-mfd-Add-support-for-AC200.patch @@ -1,7 +1,7 @@ -From fe3aef9d51c82c286ff33d867b59d0fae9a6dddd Mon Sep 17 00:00:00 2001 +From 59adceb6f34521c0f1a229f20ee9961269daa539 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Fri, 16 Aug 2019 16:38:21 +0200 -Subject: [PATCH 1/2] mfd: Add support for AC200 +Subject: [PATCH 38/44] mfd: Add support for AC200 Signed-off-by: Jernej Skrabec --- @@ -13,8 +13,6 @@ Signed-off-by: Jernej Skrabec create mode 100644 drivers/mfd/ac200.c create mode 100644 include/linux/mfd/ac200.h -diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 4a07afe50b35..576db86dfa79 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -178,6 +178,15 @@ config MFD_AC100 @@ -33,11 +31,9 @@ index 4a07afe50b35..576db86dfa79 100644 config MFD_AXP20X tristate select MFD_CORE -diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 7b6a6aa4fe42..7981edcbff4a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -143,6 +143,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o +@@ -143,6 +143,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-s obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o obj-$(CONFIG_MFD_AC100) += ac100.o @@ -45,9 +41,6 @@ index 7b6a6aa4fe42..7981edcbff4a 100644 obj-$(CONFIG_MFD_AXP20X) += axp20x.o obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o -diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c -new file mode 100644 -index 000000000000..3c95be216cf0 --- /dev/null +++ b/drivers/mfd/ac200.c @@ -0,0 +1,150 @@ @@ -201,9 +194,6 @@ index 000000000000..3c95be216cf0 +MODULE_DESCRIPTION("MFD core driver for AC200"); +MODULE_AUTHOR("Jernej Skrabec "); +MODULE_LICENSE("GPL v2"); -diff --git a/include/linux/mfd/ac200.h b/include/linux/mfd/ac200.h -new file mode 100644 -index 000000000000..48a21d5c354a --- /dev/null +++ b/include/linux/mfd/ac200.h @@ -0,0 +1,209 @@ @@ -416,293 +406,3 @@ index 000000000000..48a21d5c354a +}; + +#endif /* __LINUX_MFD_AC200_H */ --- -2.22.1 - - -From d570d779f96ce5abc1f215eb11bbe0401b539f4b Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Fri, 16 Aug 2019 16:38:57 +0200 -Subject: [PATCH 2/2] net: phy: Add support for AC200 EPHY - -Signed-off-by: Jernej Skrabec ---- - drivers/net/phy/Kconfig | 7 ++ - drivers/net/phy/Makefile | 1 + - drivers/net/phy/ac200.c | 234 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 242 insertions(+) - create mode 100644 drivers/net/phy/ac200.c - -diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig -index 48ca213c0ada..37012117fc7a 100644 ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,6 +257,13 @@ config SFP - depends on HWMON || HWMON=n - select MDIO_I2C - -+config AC200_PHY -+ tristate "AC200 EPHY" -+ depends on NVMEM -+ depends on OF -+ help -+ Fast ethernet PHY as found in X-Powers AC200 multi-function device. -+ - config AMD_PHY - tristate "AMD PHYs" - ---help--- -diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile -index ba07c27e4208..8fab8dfbe94e 100644 ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -47,6 +47,7 @@ obj-$(CONFIG_SFP) += sfp.o - sfp-obj-$(CONFIG_SFP) += sfp-bus.o - obj-y += $(sfp-obj-y) $(sfp-obj-m) - -+obj-$(CONFIG_AC200_PHY) += ac200.o - obj-$(CONFIG_ADIN_PHY) += adin.o - obj-$(CONFIG_AMD_PHY) += amd.o - aquantia-objs += aquantia_main.o -diff --git a/drivers/net/phy/ac200.c b/drivers/net/phy/ac200.c -new file mode 100644 -index 000000000000..e36af123db43 ---- /dev/null -+++ b/drivers/net/phy/ac200.c -@@ -0,0 +1,234 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/** -+ * Driver for AC200 Ethernet PHY -+ * -+ * Copyright (c) 2019 Jernej Skrabec -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define AC200_EPHY_ID 0x00441400 -+#define AC200_EPHY_ID_MASK 0x0ffffff0 -+ -+/* macros for system ephy control 0 register */ -+#define AC200_EPHY_RESET_INVALID BIT(0) -+#define AC200_EPHY_SYSCLK_GATING BIT(1) -+ -+/* macros for system ephy control 1 register */ -+#define AC200_EPHY_E_EPHY_MII_IO_EN BIT(0) -+#define AC200_EPHY_E_LNK_LED_IO_EN BIT(1) -+#define AC200_EPHY_E_SPD_LED_IO_EN BIT(2) -+#define AC200_EPHY_E_DPX_LED_IO_EN BIT(3) -+ -+/* macros for ephy control register */ -+#define AC200_EPHY_SHUTDOWN BIT(0) -+#define AC200_EPHY_LED_POL BIT(1) -+#define AC200_EPHY_CLK_SEL BIT(2) -+#define AC200_EPHY_ADDR(x) (((x) & 0x1F) << 4) -+#define AC200_EPHY_XMII_SEL BIT(11) -+#define AC200_EPHY_CALIB(x) (((x) & 0xF) << 12) -+ -+struct ac200_ephy_dev { -+ struct phy_driver *ephy; -+ struct regmap *regmap; -+}; -+ -+static char *ac200_phy_name = "AC200 EPHY"; -+ -+static void disable_intelligent_ieee(struct phy_device *phydev) -+{ -+ unsigned int value; -+ -+ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ -+ value = phy_read(phydev, 0x17); -+ value &= ~BIT(3); /* disable IEEE */ -+ phy_write(phydev, 0x17, value); -+ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ -+} -+ -+static void disable_802_3az_ieee(struct phy_device *phydev) -+{ -+ unsigned int value; -+ -+ phy_write(phydev, 0xd, 0x7); -+ phy_write(phydev, 0xe, 0x3c); -+ phy_write(phydev, 0xd, BIT(14) | 0x7); -+ value = phy_read(phydev, 0xe); -+ value &= ~BIT(1); -+ phy_write(phydev, 0xd, 0x7); -+ phy_write(phydev, 0xe, 0x3c); -+ phy_write(phydev, 0xd, BIT(14) | 0x7); -+ phy_write(phydev, 0xe, value); -+ -+ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ -+ phy_write(phydev, 0x18, 0x0000); -+} -+ -+static int ac200_ephy_config_init(struct phy_device *phydev) -+{ -+ const struct ac200_ephy_dev *priv = phydev->drv->driver_data; -+ unsigned int value; -+ int ret; -+ -+ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ -+ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ -+ -+ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ -+ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ -+ -+ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ -+ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ -+ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ -+ phy_write(phydev, 0x15, 0x1530); -+ -+ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 6 */ -+ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ -+ -+ disable_intelligent_ieee(phydev); /* Disable Intelligent IEEE */ -+ disable_802_3az_ieee(phydev); /* Disable 802.3az IEEE */ -+ phy_write(phydev, 0x1f, 0x0000); /* Switch to Page 0 */ -+ -+ value = (phydev->interface == PHY_INTERFACE_MODE_RMII) ? -+ AC200_EPHY_XMII_SEL : 0; -+ ret = regmap_update_bits(priv->regmap, AC200_EPHY_CTL, -+ AC200_EPHY_XMII_SEL, value); -+ if (ret) -+ return ret; -+ -+ /* FIXME: This is probably H6 specific */ -+ value = phy_read(phydev, 0x13); -+ value |= BIT(12); -+ phy_write(phydev, 0x13, value); -+ -+ return 0; -+} -+ -+static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { -+ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); -+ -+static int ac200_ephy_probe(struct platform_device *pdev) -+{ -+ struct ac200_dev *ac200 = dev_get_drvdata(pdev->dev.parent); -+ struct device *dev = &pdev->dev; -+ struct ac200_ephy_dev *priv; -+ struct nvmem_cell *calcell; -+ struct phy_driver *ephy; -+ u16 *caldata, calib; -+ size_t callen; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL); -+ if (!ephy) -+ return -ENOMEM; -+ -+ calcell = devm_nvmem_cell_get(dev, "ephy_calib"); -+ if (IS_ERR(calcell)) { -+ dev_err(dev, "Unable to find calibration data!\n"); -+ return PTR_ERR(calcell); -+ } -+ -+ caldata = nvmem_cell_read(calcell, &callen); -+ if (IS_ERR(caldata)) { -+ dev_err(dev, "Unable to read calibration data!\n"); -+ return PTR_ERR(caldata); -+ } -+ -+ if (callen != 2) { -+ dev_err(dev, "Calibration data has wrong length: 2 != %lu\n", -+ callen); -+ kfree(caldata); -+ return -EINVAL; -+ } -+ -+ calib = *caldata + 3; -+ kfree(caldata); -+ -+ ephy->phy_id = AC200_EPHY_ID; -+ ephy->phy_id_mask = AC200_EPHY_ID_MASK; -+ ephy->name = ac200_phy_name; -+ ephy->driver_data = priv; -+ ephy->soft_reset = genphy_soft_reset; -+ ephy->config_init = ac200_ephy_config_init; -+ ephy->suspend = genphy_suspend; -+ ephy->resume = genphy_resume; -+ -+ priv->ephy = ephy; -+ priv->regmap = ac200->regmap; -+ platform_set_drvdata(pdev, priv); -+ -+ ret = regmap_write(ac200->regmap, AC200_SYS_EPHY_CTL0, -+ AC200_EPHY_RESET_INVALID | -+ AC200_EPHY_SYSCLK_GATING); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ac200->regmap, AC200_SYS_EPHY_CTL1, -+ AC200_EPHY_E_EPHY_MII_IO_EN | -+ AC200_EPHY_E_LNK_LED_IO_EN | -+ AC200_EPHY_E_SPD_LED_IO_EN | -+ AC200_EPHY_E_DPX_LED_IO_EN); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(ac200->regmap, AC200_EPHY_CTL, -+ AC200_EPHY_LED_POL | -+ AC200_EPHY_CLK_SEL | -+ AC200_EPHY_ADDR(1) | -+ AC200_EPHY_CALIB(calib)); -+ if (ret) -+ return ret; -+ -+ ret = phy_driver_register(priv->ephy, THIS_MODULE); -+ if (ret) { -+ dev_err(dev, "Unable to register phy\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int ac200_ephy_remove(struct platform_device *pdev) -+{ -+ struct ac200_ephy_dev *priv = platform_get_drvdata(pdev); -+ -+ phy_driver_unregister(priv->ephy); -+ -+ regmap_write(priv->regmap, AC200_EPHY_CTL, AC200_EPHY_SHUTDOWN); -+ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1, 0); -+ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0, 0); -+ -+ return 0; -+} -+ -+static const struct of_device_id ac200_ephy_match[] = { -+ { .compatible = "x-powers,ac200-ephy" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, ac200_ephy_match); -+ -+static struct platform_driver ac200_ephy_driver = { -+ .probe = ac200_ephy_probe, -+ .remove = ac200_ephy_remove, -+ .driver = { -+ .name = "ac200-ephy", -+ .of_match_table = ac200_ephy_match, -+ }, -+}; -+module_platform_driver(ac200_ephy_driver); -+ -+MODULE_AUTHOR("Jernej Skrabec "); -+MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); -+MODULE_LICENSE("GPL"); --- -2.22.1 - diff --git a/projects/Allwinner/patches/linux/0039-net-phy-Add-support-for-AC200-EPHY.patch b/projects/Allwinner/patches/linux/0039-net-phy-Add-support-for-AC200-EPHY.patch new file mode 100644 index 0000000000..c5814cd7c2 --- /dev/null +++ b/projects/Allwinner/patches/linux/0039-net-phy-Add-support-for-AC200-EPHY.patch @@ -0,0 +1,276 @@ +From cbf68fb141747879e2e6c43584c1e1e3b4d77683 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:57 +0200 +Subject: [PATCH 39/44] net: phy: Add support for AC200 EPHY + +Signed-off-by: Jernej Skrabec +--- + drivers/net/phy/Kconfig | 7 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/ac200.c | 234 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 242 insertions(+) + create mode 100644 drivers/net/phy/ac200.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -63,6 +63,13 @@ config SFP + + comment "MII PHY device drivers" + ++config AC200_PHY ++ tristate "AC200 EPHY" ++ depends on NVMEM ++ depends on OF ++ help ++ Fast ethernet PHY as found in X-Powers AC200 multi-function device. ++ + config AMD_PHY + tristate "AMD PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -30,6 +30,7 @@ obj-$(CONFIG_SFP) += sfp.o + sfp-obj-$(CONFIG_SFP) += sfp-bus.o + obj-y += $(sfp-obj-y) $(sfp-obj-m) + ++obj-$(CONFIG_AC200_PHY) += ac200.o + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_AMD_PHY) += amd.o + aquantia-objs += aquantia_main.o +--- /dev/null ++++ b/drivers/net/phy/ac200.c +@@ -0,0 +1,234 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/** ++ * Driver for AC200 Ethernet PHY ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AC200_EPHY_ID 0x00441400 ++#define AC200_EPHY_ID_MASK 0x0ffffff0 ++ ++/* macros for system ephy control 0 register */ ++#define AC200_EPHY_RESET_INVALID BIT(0) ++#define AC200_EPHY_SYSCLK_GATING BIT(1) ++ ++/* macros for system ephy control 1 register */ ++#define AC200_EPHY_E_EPHY_MII_IO_EN BIT(0) ++#define AC200_EPHY_E_LNK_LED_IO_EN BIT(1) ++#define AC200_EPHY_E_SPD_LED_IO_EN BIT(2) ++#define AC200_EPHY_E_DPX_LED_IO_EN BIT(3) ++ ++/* macros for ephy control register */ ++#define AC200_EPHY_SHUTDOWN BIT(0) ++#define AC200_EPHY_LED_POL BIT(1) ++#define AC200_EPHY_CLK_SEL BIT(2) ++#define AC200_EPHY_ADDR(x) (((x) & 0x1F) << 4) ++#define AC200_EPHY_XMII_SEL BIT(11) ++#define AC200_EPHY_CALIB(x) (((x) & 0xF) << 12) ++ ++struct ac200_ephy_dev { ++ struct phy_driver *ephy; ++ struct regmap *regmap; ++}; ++ ++static char *ac200_phy_name = "AC200 EPHY"; ++ ++static void disable_intelligent_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ ++ value = phy_read(phydev, 0x17); ++ value &= ~BIT(3); /* disable IEEE */ ++ phy_write(phydev, 0x17, value); ++ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ ++} ++ ++static void disable_802_3az_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, 0xd, 0x7); ++ phy_write(phydev, 0xe, 0x3c); ++ phy_write(phydev, 0xd, BIT(14) | 0x7); ++ value = phy_read(phydev, 0xe); ++ value &= ~BIT(1); ++ phy_write(phydev, 0xd, 0x7); ++ phy_write(phydev, 0xe, 0x3c); ++ phy_write(phydev, 0xd, BIT(14) | 0x7); ++ phy_write(phydev, 0xe, value); ++ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ ++ phy_write(phydev, 0x18, 0x0000); ++} ++ ++static int ac200_ephy_config_init(struct phy_device *phydev) ++{ ++ const struct ac200_ephy_dev *priv = phydev->drv->driver_data; ++ unsigned int value; ++ int ret; ++ ++ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ ++ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ ++ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ ++ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ ++ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ ++ phy_write(phydev, 0x15, 0x1530); ++ ++ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 6 */ ++ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++ ++ disable_intelligent_ieee(phydev); /* Disable Intelligent IEEE */ ++ disable_802_3az_ieee(phydev); /* Disable 802.3az IEEE */ ++ phy_write(phydev, 0x1f, 0x0000); /* Switch to Page 0 */ ++ ++ value = (phydev->interface == PHY_INTERFACE_MODE_RMII) ? ++ AC200_EPHY_XMII_SEL : 0; ++ ret = regmap_update_bits(priv->regmap, AC200_EPHY_CTL, ++ AC200_EPHY_XMII_SEL, value); ++ if (ret) ++ return ret; ++ ++ /* FIXME: This is probably H6 specific */ ++ value = phy_read(phydev, 0x13); ++ value |= BIT(12); ++ phy_write(phydev, 0x13, value); ++ ++ return 0; ++} ++ ++static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { ++ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); ++ ++static int ac200_ephy_probe(struct platform_device *pdev) ++{ ++ struct ac200_dev *ac200 = dev_get_drvdata(pdev->dev.parent); ++ struct device *dev = &pdev->dev; ++ struct ac200_ephy_dev *priv; ++ struct nvmem_cell *calcell; ++ struct phy_driver *ephy; ++ u16 *caldata, calib; ++ size_t callen; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL); ++ if (!ephy) ++ return -ENOMEM; ++ ++ calcell = devm_nvmem_cell_get(dev, "ephy_calib"); ++ if (IS_ERR(calcell)) { ++ dev_err(dev, "Unable to find calibration data!\n"); ++ return PTR_ERR(calcell); ++ } ++ ++ caldata = nvmem_cell_read(calcell, &callen); ++ if (IS_ERR(caldata)) { ++ dev_err(dev, "Unable to read calibration data!\n"); ++ return PTR_ERR(caldata); ++ } ++ ++ if (callen != 2) { ++ dev_err(dev, "Calibration data has wrong length: 2 != %lu\n", ++ callen); ++ kfree(caldata); ++ return -EINVAL; ++ } ++ ++ calib = *caldata + 3; ++ kfree(caldata); ++ ++ ephy->phy_id = AC200_EPHY_ID; ++ ephy->phy_id_mask = AC200_EPHY_ID_MASK; ++ ephy->name = ac200_phy_name; ++ ephy->driver_data = priv; ++ ephy->soft_reset = genphy_soft_reset; ++ ephy->config_init = ac200_ephy_config_init; ++ ephy->suspend = genphy_suspend; ++ ephy->resume = genphy_resume; ++ ++ priv->ephy = ephy; ++ priv->regmap = ac200->regmap; ++ platform_set_drvdata(pdev, priv); ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID | ++ AC200_EPHY_SYSCLK_GATING); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_EPHY_CTL1, ++ AC200_EPHY_E_EPHY_MII_IO_EN | ++ AC200_EPHY_E_LNK_LED_IO_EN | ++ AC200_EPHY_E_SPD_LED_IO_EN | ++ AC200_EPHY_E_DPX_LED_IO_EN); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ac200->regmap, AC200_EPHY_CTL, ++ AC200_EPHY_LED_POL | ++ AC200_EPHY_CLK_SEL | ++ AC200_EPHY_ADDR(1) | ++ AC200_EPHY_CALIB(calib)); ++ if (ret) ++ return ret; ++ ++ ret = phy_driver_register(priv->ephy, THIS_MODULE); ++ if (ret) { ++ dev_err(dev, "Unable to register phy\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ac200_ephy_remove(struct platform_device *pdev) ++{ ++ struct ac200_ephy_dev *priv = platform_get_drvdata(pdev); ++ ++ phy_driver_unregister(priv->ephy); ++ ++ regmap_write(priv->regmap, AC200_EPHY_CTL, AC200_EPHY_SHUTDOWN); ++ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1, 0); ++ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0, 0); ++ ++ return 0; ++} ++ ++static const struct of_device_id ac200_ephy_match[] = { ++ { .compatible = "x-powers,ac200-ephy" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ac200_ephy_match); ++ ++static struct platform_driver ac200_ephy_driver = { ++ .probe = ac200_ephy_probe, ++ .remove = ac200_ephy_remove, ++ .driver = { ++ .name = "ac200-ephy", ++ .of_match_table = ac200_ephy_match, ++ }, ++}; ++module_platform_driver(ac200_ephy_driver); ++ ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); ++MODULE_LICENSE("GPL"); diff --git a/projects/Allwinner/patches/linux/x0001-wip-H6-deinterlace.patch b/projects/Allwinner/patches/linux/0040-wip-H6-deinterlace.patch similarity index 97% rename from projects/Allwinner/patches/linux/x0001-wip-H6-deinterlace.patch rename to projects/Allwinner/patches/linux/0040-wip-H6-deinterlace.patch index 008929104b..b5bb79679e 100644 --- a/projects/Allwinner/patches/linux/x0001-wip-H6-deinterlace.patch +++ b/projects/Allwinner/patches/linux/0040-wip-H6-deinterlace.patch @@ -1,7 +1,7 @@ -From 70ad6a66d55ec76f7a0595b7c1bc94bca11dd289 Mon Sep 17 00:00:00 2001 +From 91c70ea17b58c9205c35cd43a3dd8266bbe035b1 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 25 May 2020 19:06:07 +0200 -Subject: [PATCH 1/2] wip: H6 deinterlace +Subject: [PATCH 40/44] wip: H6 deinterlace Signed-off-by: Jernej Skrabec --- @@ -15,11 +15,9 @@ Signed-off-by: Jernej Skrabec create mode 100644 drivers/media/platform/sunxi/sun50i-di/sun50i-di.c create mode 100644 drivers/media/platform/sunxi/sun50i-di/sun50i-di.h -diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index c57ee78fa99d..0d3b25d96b10 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig -@@ -495,6 +495,19 @@ config VIDEO_QCOM_VENUS +@@ -510,6 +510,19 @@ config VIDEO_QCOM_VENUS on various Qualcomm SoCs. To compile this driver as a module choose m here. @@ -39,8 +37,6 @@ index c57ee78fa99d..0d3b25d96b10 100644 config VIDEO_SUN8I_DEINTERLACE tristate "Allwinner Deinterlace driver" depends on VIDEO_DEV && VIDEO_V4L2 -diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile -index fc537c9f5ca9..b28f3b15329f 100644 --- a/drivers/media/platform/sunxi/Makefile +++ b/drivers/media/platform/sunxi/Makefile @@ -3,4 +3,5 @@ @@ -49,17 +45,11 @@ index fc537c9f5ca9..b28f3b15329f 100644 obj-y += sun8i-di/ +obj-y += sun50i-di/ obj-y += sun8i-rotate/ -diff --git a/drivers/media/platform/sunxi/sun50i-di/Makefile b/drivers/media/platform/sunxi/sun50i-di/Makefile -new file mode 100644 -index 000000000000..225b3b808069 --- /dev/null +++ b/drivers/media/platform/sunxi/sun50i-di/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_VIDEO_SUN50I_DEINTERLACE) += sun50i-di.o -diff --git a/drivers/media/platform/sunxi/sun50i-di/sun50i-di.c b/drivers/media/platform/sunxi/sun50i-di/sun50i-di.c -new file mode 100644 -index 000000000000..f6b706fb1a9a --- /dev/null +++ b/drivers/media/platform/sunxi/sun50i-di/sun50i-di.c @@ -0,0 +1,1134 @@ @@ -1197,9 +1187,6 @@ index 000000000000..f6b706fb1a9a +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Jernej Skrabec "); +MODULE_DESCRIPTION("Allwinner Deinterlace driver"); -diff --git a/drivers/media/platform/sunxi/sun50i-di/sun50i-di.h b/drivers/media/platform/sunxi/sun50i-di/sun50i-di.h -new file mode 100644 -index 000000000000..8cb19955ef06 --- /dev/null +++ b/drivers/media/platform/sunxi/sun50i-di/sun50i-di.h @@ -0,0 +1,172 @@ @@ -1375,6 +1362,3 @@ index 000000000000..8cb19955ef06 +}; + +#endif --- -2.27.0 - diff --git a/projects/Allwinner/patches/linux/x0002-arm64-dts-h6-deinterlace.patch b/projects/Allwinner/patches/linux/0041-arm64-dts-h6-deinterlace.patch similarity index 71% rename from projects/Allwinner/patches/linux/x0002-arm64-dts-h6-deinterlace.patch rename to projects/Allwinner/patches/linux/0041-arm64-dts-h6-deinterlace.patch index 509bbbd6b7..87ec6f74f5 100644 --- a/projects/Allwinner/patches/linux/x0002-arm64-dts-h6-deinterlace.patch +++ b/projects/Allwinner/patches/linux/0041-arm64-dts-h6-deinterlace.patch @@ -1,18 +1,16 @@ -From 559f5716ee5e45e87e3bb7f7e5ded5c6116d194b Mon Sep 17 00:00:00 2001 +From c009b3b707bbde30fa6ff49ca3075160524ea7b9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 26 May 2020 20:08:27 +0200 -Subject: [PATCH 2/2] arm64: dts: h6 deinterlace +Subject: [PATCH 41/44] arm64: dts: h6 deinterlace Signed-off-by: Jernej Skrabec --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index 78b1361dfbb9..d45893b7b7b8 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -152,6 +152,17 @@ mixer0_out_tcon_top_mixer0: endpoint { +@@ -153,6 +153,17 @@ }; }; @@ -30,6 +28,3 @@ index 78b1361dfbb9..d45893b7b7b8 100644 video-codec@1c0e000 { compatible = "allwinner,sun50i-h6-video-engine"; reg = <0x01c0e000 0x2000>; --- -2.27.0 - diff --git a/projects/Allwinner/patches/linux/0042-ASoC-sun4i-i2s-Add-parenthesis-around-macro-argument.patch b/projects/Allwinner/patches/linux/0042-ASoC-sun4i-i2s-Add-parenthesis-around-macro-argument.patch new file mode 100644 index 0000000000..8aa7fb3a2e --- /dev/null +++ b/projects/Allwinner/patches/linux/0042-ASoC-sun4i-i2s-Add-parenthesis-around-macro-argument.patch @@ -0,0 +1,50 @@ +From b10b474925447933bf1d718e6d064190b15b56d9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 14 Jan 2021 19:26:03 +0100 +Subject: [PATCH 42/44] ASoC: sun4i-i2s: Add parenthesis around macro arguments + +Several macro arguments are not put inside parenthesis, which may cause +subtle issues. + +Fix those macros. + +Signed-off-by: Jernej Skrabec +--- + sound/soc/sunxi/sun4i-i2s.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -116,16 +116,16 @@ + + #define SUN8I_I2S_CHAN_CFG_REG 0x30 + #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) +-#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4) ++#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (((chan) - 1) << 4) + #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) +-#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) ++#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) ((chan) - 1) + + #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 + #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 + #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12) +-#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) ++#define SUN8I_I2S_TX_CHAN_OFFSET(offset) ((offset) << 12) + #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) +-#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) ++#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << (num_chan)) - 1) << 4) + + #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 + #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 +@@ -134,9 +134,9 @@ + #define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK GENMASK(21, 20) + #define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset) ((offset) << 20) + #define SUN50I_H6_I2S_TX_CHAN_SEL_MASK GENMASK(19, 16) +-#define SUN50I_H6_I2S_TX_CHAN_SEL(chan) ((chan - 1) << 16) ++#define SUN50I_H6_I2S_TX_CHAN_SEL(chan) (((chan) - 1) << 16) + #define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) +-#define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1)) ++#define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << (num_chan)) - 1)) + + #define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 + #define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 diff --git a/projects/Allwinner/patches/linux/0043-WIP-I2S-multi-channel.patch b/projects/Allwinner/patches/linux/0043-WIP-I2S-multi-channel.patch new file mode 100644 index 0000000000..520eca52ee --- /dev/null +++ b/projects/Allwinner/patches/linux/0043-WIP-I2S-multi-channel.patch @@ -0,0 +1,288 @@ +From a19b428a02224e0e01fff4738bbf0632942d18a1 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 15 Jan 2021 00:13:54 +0100 +Subject: [PATCH 43/44] WIP: I2S multi channel + +Signed-off-by: Jernej Skrabec +--- + sound/soc/sunxi/sun4i-i2s.c | 137 +++++++++++++++++++++++++----------- + 1 file changed, 97 insertions(+), 40 deletions(-) + +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -23,7 +23,7 @@ + + #define SUN4I_I2S_CTRL_REG 0x00 + #define SUN4I_I2S_CTRL_SDO_EN_MASK GENMASK(11, 8) +-#define SUN4I_I2S_CTRL_SDO_EN(sdo) BIT(8 + (sdo)) ++#define SUN4I_I2S_CTRL_SDO_EN(lines) (((1 << (lines)) - 1) << 8) + #define SUN4I_I2S_CTRL_MODE_MASK BIT(5) + #define SUN4I_I2S_CTRL_MODE_SLAVE (1 << 5) + #define SUN4I_I2S_CTRL_MODE_MASTER (0 << 5) +@@ -120,8 +120,8 @@ + #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) + #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) ((chan) - 1) + +-#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 +-#define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 ++#define SUN8I_I2S_TX_CHAN_MAP_REG(i) (0x44 + 4 * (i)) ++#define SUN8I_I2S_TX_CHAN_SEL_REG(i) (0x34 + 4 * (i)) + #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12) + #define SUN8I_I2S_TX_CHAN_OFFSET(offset) ((offset) << 12) + #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) +@@ -138,8 +138,8 @@ + #define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) + #define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << (num_chan)) - 1)) + +-#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 +-#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 ++#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG(i) (0x44 + 8 * (i)) ++#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG(i) (0x48 + 8 * (i)) + + #define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 + #define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 +@@ -189,7 +189,7 @@ struct sun4i_i2s_quirks { + * @slots: channels per frame + padding slots, regardless of format + * @slot_width: bits per sample + padding bits, regardless of format + */ +- int (*set_chan_cfg)(const struct sun4i_i2s *i2s, ++ int (*set_chan_cfg)(struct sun4i_i2s *i2s, + unsigned int channels, unsigned int slots, + unsigned int slot_width); + int (*set_fmt)(const struct sun4i_i2s *i2s, unsigned int fmt); +@@ -205,6 +205,7 @@ struct sun4i_i2s { + unsigned int mclk_freq; + unsigned int slots; + unsigned int slot_width; ++ unsigned int lines; + + struct snd_dmaengine_dai_dma_data capture_dma_data; + struct snd_dmaengine_dai_dma_data playback_dma_data; +@@ -445,7 +446,7 @@ static int sun8i_i2s_get_sr_wss(unsigned + return -EINVAL; + } + +-static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, ++static int sun4i_i2s_set_chan_cfg(struct sun4i_i2s *i2s, + unsigned int channels, unsigned int slots, + unsigned int slot_width) + { +@@ -464,20 +465,42 @@ static int sun4i_i2s_set_chan_cfg(const + return 0; + } + +-static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, ++static int sun8i_i2s_set_chan_cfg(struct sun4i_i2s *i2s, + unsigned int channels, unsigned int slots, + unsigned int slot_width) + { +- unsigned int lrck_period; ++ unsigned int lrck_period, val; ++ int i; ++ ++ i2s->lines = (channels + 1) / 2; ++ ++ /* Enable the required output lines */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN4I_I2S_CTRL_SDO_EN_MASK, ++ SUN4I_I2S_CTRL_SDO_EN(i2s->lines)); + + /* Map the channels for playback and capture */ +- regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210); ++ regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG(0), 0x76543210); ++ regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG(1), 0x32); ++ regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG(2), 0x54); ++ regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG(3), 0x76); + regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210); + + /* Configure the channels */ +- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, +- SUN4I_I2S_CHAN_SEL_MASK, +- SUN4I_I2S_CHAN_SEL(channels)); ++ for (i = 0; i < 4; i++) { ++ if (channels <= i * 2) ++ val = 0; ++ else if (channels == i * 2 + 1) ++ val = 1; ++ else ++ val = 2; ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG(i), ++ SUN4I_I2S_CHAN_SEL_MASK | ++ SUN8I_I2S_TX_CHAN_EN_MASK, ++ SUN4I_I2S_CHAN_SEL(val) | ++ SUN8I_I2S_TX_CHAN_EN(val)); ++ } ++ + regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, + SUN4I_I2S_CHAN_SEL_MASK, + SUN4I_I2S_CHAN_SEL(channels)); +@@ -509,29 +532,47 @@ static int sun8i_i2s_set_chan_cfg(const + SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, + SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); + +- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, +- SUN8I_I2S_TX_CHAN_EN_MASK, +- SUN8I_I2S_TX_CHAN_EN(channels)); +- + return 0; + } + +-static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, ++static int sun50i_h6_i2s_set_chan_cfg(struct sun4i_i2s *i2s, + unsigned int channels, unsigned int slots, + unsigned int slot_width) + { +- unsigned int lrck_period; ++ unsigned int lrck_period, val; ++ int i; ++ ++ i2s->lines = (channels + 1) / 2; ++ ++ /* Enable the required output lines */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN4I_I2S_CTRL_SDO_EN_MASK, ++ SUN4I_I2S_CTRL_SDO_EN(i2s->lines)); + + /* Map the channels for playback and capture */ +- regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98); +- regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0xFEDCBA98); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x76543210); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(1), 0x32); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(2), 0x54); ++ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(3), 0x76); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); + + /* Configure the channels */ +- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, +- SUN50I_H6_I2S_TX_CHAN_SEL_MASK, +- SUN50I_H6_I2S_TX_CHAN_SEL(channels)); ++ for (i = 0; i < 4; i++) { ++ if (channels <= i * 2) ++ val = 0; ++ else if (channels == i * 2 + 1) ++ val = 1; ++ else ++ val = 2; ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG(i), ++ SUN50I_H6_I2S_TX_CHAN_SEL_MASK | ++ SUN50I_H6_I2S_TX_CHAN_EN_MASK, ++ SUN50I_H6_I2S_TX_CHAN_SEL(val) | ++ SUN50I_H6_I2S_TX_CHAN_EN(val)); ++ } ++ + regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, + SUN50I_H6_I2S_TX_CHAN_SEL_MASK, + SUN50I_H6_I2S_TX_CHAN_SEL(channels)); +@@ -563,10 +604,6 @@ static int sun50i_h6_i2s_set_chan_cfg(co + SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, + SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); + +- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, +- SUN50I_H6_I2S_TX_CHAN_EN_MASK, +- SUN50I_H6_I2S_TX_CHAN_EN(channels)); +- + return 0; + } + +@@ -711,6 +748,7 @@ static int sun8i_i2s_set_soc_fmt(const s + { + u32 mode, val; + u8 offset; ++ int i; + + /* + * DAI clock polarity +@@ -778,9 +816,10 @@ static int sun8i_i2s_set_soc_fmt(const s + + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, + SUN8I_I2S_CTRL_MODE_MASK, mode); +- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, +- SUN8I_I2S_TX_CHAN_OFFSET_MASK, +- SUN8I_I2S_TX_CHAN_OFFSET(offset)); ++ for (i = 0; i < 4; i++) ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG(i), ++ SUN8I_I2S_TX_CHAN_OFFSET_MASK, ++ SUN8I_I2S_TX_CHAN_OFFSET(offset)); + regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, + SUN8I_I2S_TX_CHAN_OFFSET_MASK, + SUN8I_I2S_TX_CHAN_OFFSET(offset)); +@@ -818,6 +857,7 @@ static int sun50i_h6_i2s_set_soc_fmt(con + { + u32 mode, val; + u8 offset; ++ int i; + + /* + * DAI clock polarity +@@ -885,9 +925,10 @@ static int sun50i_h6_i2s_set_soc_fmt(con + + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, + SUN8I_I2S_CTRL_MODE_MASK, mode); +- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, +- SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, +- SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); ++ for (i = 0; i < 4; i++) ++ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG(i), ++ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, ++ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); + regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, + SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, + SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); +@@ -1198,8 +1239,14 @@ static const struct reg_default sun8i_i2 + { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, + { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, + { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, +- { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, +- { SUN8I_I2S_TX_CHAN_MAP_REG, 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(0), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(1), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(2), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(3), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_MAP_REG(0), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_MAP_REG(1), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_MAP_REG(2), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_MAP_REG(3), 0x00000000 }, + { SUN8I_I2S_RX_CHAN_SEL_REG, 0x00000000 }, + { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 }, + }; +@@ -1212,9 +1259,18 @@ static const struct reg_default sun50i_h + { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, + { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, + { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, +- { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, +- { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 }, +- { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(0), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(1), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(2), 0x00000000 }, ++ { SUN8I_I2S_TX_CHAN_SEL_REG(3), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG(1), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG(1), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG(2), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG(2), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG(3), 0x00000000 }, ++ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG(3), 0x00000000 }, + { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 }, + { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 }, + { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 }, +@@ -1287,7 +1343,7 @@ static int sun4i_i2s_runtime_resume(stru + /* Enable the first output line */ + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, + SUN4I_I2S_CTRL_SDO_EN_MASK, +- SUN4I_I2S_CTRL_SDO_EN(0)); ++ SUN4I_I2S_CTRL_SDO_EN(i2s->lines)); + + ret = clk_prepare_enable(i2s->mod_clk); + if (ret) { +@@ -1529,6 +1585,7 @@ static int sun4i_i2s_probe(struct platfo + + i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; + i2s->capture_dma_data.maxburst = 8; ++ i2s->lines = 1; + + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { diff --git a/projects/Allwinner/devices/H3/patches/linux/16-H3-add-HDMI-sound-nodes.patch b/projects/Allwinner/patches/linux/0044-HACK-h3-h5-Add-HDMI-sound-card.patch similarity index 50% rename from projects/Allwinner/devices/H3/patches/linux/16-H3-add-HDMI-sound-nodes.patch rename to projects/Allwinner/patches/linux/0044-HACK-h3-h5-Add-HDMI-sound-card.patch index 1515ba3355..8f44848145 100644 --- a/projects/Allwinner/devices/H3/patches/linux/16-H3-add-HDMI-sound-nodes.patch +++ b/projects/Allwinner/patches/linux/0044-HACK-h3-h5-Add-HDMI-sound-card.patch @@ -1,16 +1,25 @@ -diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -index 8aa2befc..d3d70eac 100644 +From d0428e1d4b2a1a3d640f6052646e0f8ca7fc2d53 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 10:57:58 +0100 +Subject: [PATCH 44/44] HACK: h3/h5: Add HDMI sound card + +Signed-off-by: Jernej Skrabec +--- + arch/arm/boot/dts/sunxi-h3-h5.dtsi | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -53,6 +53,23 @@ - #address-cells = <1>; - #size-cells = <1>; +@@ -77,6 +77,24 @@ + }; + }; + sound_hdmi: sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "allwinner-hdmi"; + simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,frame-inversion; + + simple-audio-card,codec { + sound-dai = <&hdmi>; @@ -26,27 +35,15 @@ index 8aa2befc..d3d70eac 100644 clocks { #address-cells = <1>; #size-cells = <1>; -@@ -631,6 +648,19 @@ - status = "disabled"; +@@ -672,7 +690,6 @@ + dmas = <&dma 27>; + resets = <&ccu RST_BUS_I2S2>; + dma-names = "tx"; +- status = "disabled"; }; -+ i2s2: i2s@1c22800 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun8i-h3-i2s"; -+ reg = <0x01c22800 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; -+ clock-names = "apb", "mod"; -+ dmas = <&dma 27>; -+ resets = <&ccu RST_BUS_I2S2>; -+ dma-names = "tx"; -+ allwinner,playback-channels = <8>; -+ }; -+ codec: codec@1c22c00 { - #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-codec"; -@@ -110,6 +126,7 @@ +@@ -806,6 +823,7 @@ }; hdmi: hdmi@1ee0000 { diff --git a/projects/Allwinner/patches/linux/crust/0005-DO-NOT-MERGE-ARM-dts-sunxi-h3-h5-Protect-SCP-clocks.patch b/projects/Allwinner/patches/linux/crust/0005-DO-NOT-MERGE-ARM-dts-sunxi-h3-h5-Protect-SCP-clocks.patch index 03b5922896..be188b157b 100644 --- a/projects/Allwinner/patches/linux/crust/0005-DO-NOT-MERGE-ARM-dts-sunxi-h3-h5-Protect-SCP-clocks.patch +++ b/projects/Allwinner/patches/linux/crust/0005-DO-NOT-MERGE-ARM-dts-sunxi-h3-h5-Protect-SCP-clocks.patch @@ -11,7 +11,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -388,6 +388,7 @@ +@@ -406,6 +406,7 @@ reg = <0x01c20000 0x400>; clocks = <&osc24M>, <&rtc 0>; clock-names = "hosc", "losc"; @@ -19,7 +19,7 @@ Signed-off-by: Samuel Holland #clock-cells = <1>; #reset-cells = <1>; }; -@@ -852,6 +853,7 @@ +@@ -883,6 +884,7 @@ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, <&ccu CLK_PLL_PERIPH0>; clock-names = "hosc", "losc", "iosc", "pll-periph"; diff --git a/projects/Allwinner/patches/linux/crust/0006-DO-NOT-MERGE-arm64-dts-allwinner-a64-Protect-SCP-clo.patch b/projects/Allwinner/patches/linux/crust/0006-DO-NOT-MERGE-arm64-dts-allwinner-a64-Protect-SCP-clo.patch index aa28404f93..eabfec7096 100644 --- a/projects/Allwinner/patches/linux/crust/0006-DO-NOT-MERGE-arm64-dts-allwinner-a64-Protect-SCP-clo.patch +++ b/projects/Allwinner/patches/linux/crust/0006-DO-NOT-MERGE-arm64-dts-allwinner-a64-Protect-SCP-clo.patch @@ -19,7 +19,7 @@ Signed-off-by: Samuel Holland #clock-cells = <1>; #reset-cells = <1>; }; -@@ -1212,6 +1213,7 @@ +@@ -1226,6 +1227,7 @@ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, <&ccu CLK_PLL_PERIPH0>; clock-names = "hosc", "losc", "iosc", "pll-periph"; diff --git a/projects/Allwinner/patches/linux/crust/0007-DO-NOT-MERGE-arm64-dts-allwinner-h6-Protect-SCP-cloc.patch b/projects/Allwinner/patches/linux/crust/0007-DO-NOT-MERGE-arm64-dts-allwinner-h6-Protect-SCP-cloc.patch index 6f58990457..b9dd0d60e9 100644 --- a/projects/Allwinner/patches/linux/crust/0007-DO-NOT-MERGE-arm64-dts-allwinner-h6-Protect-SCP-cloc.patch +++ b/projects/Allwinner/patches/linux/crust/0007-DO-NOT-MERGE-arm64-dts-allwinner-h6-Protect-SCP-cloc.patch @@ -11,7 +11,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -230,6 +230,7 @@ +@@ -241,6 +241,7 @@ reg = <0x03001000 0x1000>; clocks = <&osc24M>, <&rtc 0>, <&rtc 2>; clock-names = "hosc", "losc", "iosc"; @@ -19,7 +19,7 @@ Signed-off-by: Samuel Holland #clock-cells = <1>; #reset-cells = <1>; }; -@@ -894,6 +895,7 @@ +@@ -918,6 +919,7 @@ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, <&ccu CLK_PLL_PERIPH0>; clock-names = "hosc", "losc", "iosc", "pll-periph"; diff --git a/projects/Allwinner/patches/linux/crust/0019-ARM-dts-sunxi-h3-h5-Add-r_intc-node.patch b/projects/Allwinner/patches/linux/crust/0019-ARM-dts-sunxi-h3-h5-Add-r_intc-node.patch index 887fc39996..6acb0d8ea9 100644 --- a/projects/Allwinner/patches/linux/crust/0019-ARM-dts-sunxi-h3-h5-Add-r_intc-node.patch +++ b/projects/Allwinner/patches/linux/crust/0019-ARM-dts-sunxi-h3-h5-Add-r_intc-node.patch @@ -15,7 +15,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -847,6 +847,15 @@ +@@ -878,6 +878,15 @@ #clock-cells = <1>; }; diff --git a/projects/Allwinner/patches/linux/crust/0020-ARM-dts-sunxi-h3-h5-Move-wakeup-capable-IRQs-to-r_in.patch b/projects/Allwinner/patches/linux/crust/0020-ARM-dts-sunxi-h3-h5-Move-wakeup-capable-IRQs-to-r_in.patch index dcddcc10f2..d55dfb84c3 100644 --- a/projects/Allwinner/patches/linux/crust/0020-ARM-dts-sunxi-h3-h5-Move-wakeup-capable-IRQs-to-r_in.patch +++ b/projects/Allwinner/patches/linux/crust/0020-ARM-dts-sunxi-h3-h5-Move-wakeup-capable-IRQs-to-r_in.patch @@ -17,7 +17,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -840,8 +840,9 @@ +@@ -871,8 +871,9 @@ rtc: rtc@1f00000 { /* compatible is in per SoC .dtsi file */ reg = <0x01f00000 0x400>; @@ -29,7 +29,7 @@ Signed-off-by: Samuel Holland clock-output-names = "osc32k", "osc32k-out", "iosc"; clocks = <&osc32k>; #clock-cells = <1>; -@@ -877,7 +878,8 @@ +@@ -908,7 +909,8 @@ clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>; clock-names = "apb", "ir"; resets = <&r_ccu RST_APB0_IR>; @@ -39,7 +39,7 @@ Signed-off-by: Samuel Holland reg = <0x01f02000 0x400>; status = "disabled"; }; -@@ -898,7 +900,8 @@ +@@ -929,7 +931,8 @@ r_pio: pinctrl@1f02c00 { compatible = "allwinner,sun8i-h3-r-pinctrl"; reg = <0x01f02c00 0x400>; diff --git a/projects/Allwinner/patches/linux/crust/0022-arm64-dts-allwinner-a64-Move-wakeup-capable-IRQs-to-.patch b/projects/Allwinner/patches/linux/crust/0022-arm64-dts-allwinner-a64-Move-wakeup-capable-IRQs-to-.patch index d6040de8d7..ffd59ef69c 100644 --- a/projects/Allwinner/patches/linux/crust/0022-arm64-dts-allwinner-a64-Move-wakeup-capable-IRQs-to-.patch +++ b/projects/Allwinner/patches/linux/crust/0022-arm64-dts-allwinner-a64-Move-wakeup-capable-IRQs-to-.patch @@ -17,7 +17,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -1191,8 +1191,9 @@ +@@ -1205,8 +1205,9 @@ compatible = "allwinner,sun50i-a64-rtc", "allwinner,sun8i-h3-rtc"; reg = <0x01f00000 0x400>; @@ -29,7 +29,7 @@ Signed-off-by: Samuel Holland clock-output-names = "osc32k", "osc32k-out", "iosc"; clocks = <&osc32k>; #clock-cells = <1>; -@@ -1243,7 +1244,8 @@ +@@ -1257,7 +1258,8 @@ clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>; clock-names = "apb", "ir"; resets = <&r_ccu RST_APB0_IR>; @@ -39,7 +39,7 @@ Signed-off-by: Samuel Holland pinctrl-names = "default"; pinctrl-0 = <&r_ir_rx_pin>; status = "disabled"; -@@ -1263,7 +1265,8 @@ +@@ -1277,7 +1279,8 @@ r_pio: pinctrl@1f02c00 { compatible = "allwinner,sun50i-a64-r-pinctrl"; reg = <0x01f02c00 0x400>; diff --git a/projects/Allwinner/patches/linux/crust/0023-arm64-dts-allwinner-h6-Fix-indentation-of-IR-node.patch b/projects/Allwinner/patches/linux/crust/0023-arm64-dts-allwinner-h6-Fix-indentation-of-IR-node.patch index 4e096a9185..2fbff96df9 100644 --- a/projects/Allwinner/patches/linux/crust/0023-arm64-dts-allwinner-h6-Fix-indentation-of-IR-node.patch +++ b/projects/Allwinner/patches/linux/crust/0023-arm64-dts-allwinner-h6-Fix-indentation-of-IR-node.patch @@ -13,7 +13,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -941,17 +941,17 @@ +@@ -965,17 +965,17 @@ }; r_ir: ir@7040000 { diff --git a/projects/Allwinner/patches/linux/crust/0024-arm64-dts-allwinner-h6-Move-wakeup-capable-IRQs-to-r.patch b/projects/Allwinner/patches/linux/crust/0024-arm64-dts-allwinner-h6-Move-wakeup-capable-IRQs-to-r.patch index 25ce155229..2fd8882f56 100644 --- a/projects/Allwinner/patches/linux/crust/0024-arm64-dts-allwinner-h6-Move-wakeup-capable-IRQs-to-r.patch +++ b/projects/Allwinner/patches/linux/crust/0024-arm64-dts-allwinner-h6-Move-wakeup-capable-IRQs-to-r.patch @@ -17,7 +17,7 @@ Signed-off-by: Samuel Holland --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -883,8 +883,9 @@ +@@ -907,8 +907,9 @@ rtc: rtc@7000000 { compatible = "allwinner,sun50i-h6-rtc"; reg = <0x07000000 0x400>; @@ -29,7 +29,7 @@ Signed-off-by: Samuel Holland clock-output-names = "osc32k", "osc32k-out", "iosc"; #clock-cells = <1>; }; -@@ -920,8 +921,9 @@ +@@ -944,8 +945,9 @@ r_pio: pinctrl@7022000 { compatible = "allwinner,sun50i-h6-r-pinctrl"; reg = <0x07022000 0x400>; @@ -41,7 +41,7 @@ Signed-off-by: Samuel Holland clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>; clock-names = "apb", "hosc", "losc"; gpio-controller; -@@ -944,7 +946,8 @@ +@@ -968,7 +970,8 @@ compatible = "allwinner,sun50i-h6-ir", "allwinner,sun6i-a31-ir"; reg = <0x07040000 0x400>; diff --git a/projects/Allwinner/patches/linux/crust/0029-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch b/projects/Allwinner/patches/linux/crust/0029-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch index 0a1ecb226e..3c52919f75 100644 --- a/projects/Allwinner/patches/linux/crust/0029-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch +++ b/projects/Allwinner/patches/linux/crust/0029-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch @@ -34,7 +34,7 @@ Signed-off-by: Samuel Holland reg = <0x01d00000 0x80000>; --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi -@@ -105,6 +105,13 @@ +@@ -123,6 +123,13 @@ status = "disabled"; }; diff --git a/projects/Allwinner/patches/linux/crust/0031-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch b/projects/Allwinner/patches/linux/crust/0031-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch index 08ea5eda64..6e42cac1ad 100644 --- a/projects/Allwinner/patches/linux/crust/0031-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch +++ b/projects/Allwinner/patches/linux/crust/0031-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch @@ -24,7 +24,7 @@ Signed-off-by: Samuel Holland timer { compatible = "arm,armv8-timer"; arm,no-tick-in-suspend; -@@ -196,6 +203,19 @@ +@@ -207,6 +214,19 @@ #size-cells = <1>; ranges; diff --git a/projects/Allwinner/patches/linux/crust/0032-media-sunxi-cir-Skip-register-writes-during-remove.patch b/projects/Allwinner/patches/linux/crust/0032-media-sunxi-cir-Skip-register-writes-during-remove.patch index a868045460..5e09bcc285 100644 --- a/projects/Allwinner/patches/linux/crust/0032-media-sunxi-cir-Skip-register-writes-during-remove.patch +++ b/projects/Allwinner/patches/linux/crust/0032-media-sunxi-cir-Skip-register-writes-during-remove.patch @@ -11,11 +11,9 @@ Signed-off-by: Samuel Holland drivers/media/rc/sunxi-cir.c | 10 ---------- 1 file changed, 10 deletions(-) -diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c -index 8555c7798706..0a7f7eab3cc3 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c -@@ -342,22 +342,12 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -342,22 +342,12 @@ exit_reset_assert: static int sunxi_ir_remove(struct platform_device *pdev) { @@ -38,6 +36,3 @@ index 8555c7798706..0a7f7eab3cc3 100644 rc_unregister_device(ir->rc); return 0; } --- -2.30.0 - diff --git a/projects/Allwinner/patches/linux/crust/0033-media-sunxi-cir-Remove-unnecessary-spinlock.patch b/projects/Allwinner/patches/linux/crust/0033-media-sunxi-cir-Remove-unnecessary-spinlock.patch index bf7513703a..86d19a09b3 100644 --- a/projects/Allwinner/patches/linux/crust/0033-media-sunxi-cir-Remove-unnecessary-spinlock.patch +++ b/projects/Allwinner/patches/linux/crust/0033-media-sunxi-cir-Remove-unnecessary-spinlock.patch @@ -12,8 +12,6 @@ Signed-off-by: Samuel Holland drivers/media/rc/sunxi-cir.c | 10 ---------- 1 file changed, 10 deletions(-) -diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c -index 0a7f7eab3cc3..48be400421cd 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -86,7 +86,6 @@ struct sunxi_ir_quirks { @@ -24,7 +22,7 @@ index 0a7f7eab3cc3..48be400421cd 100644 struct rc_dev *rc; void __iomem *base; int irq; -@@ -105,8 +104,6 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) +@@ -105,8 +104,6 @@ static irqreturn_t sunxi_ir_irq(int irqn struct sunxi_ir *ir = dev_id; struct ir_raw_event rawir = {}; @@ -33,7 +31,7 @@ index 0a7f7eab3cc3..48be400421cd 100644 status = readl(ir->base + SUNXI_IR_RXSTA_REG); /* clean all pending statuses */ -@@ -137,8 +134,6 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) +@@ -137,8 +134,6 @@ static irqreturn_t sunxi_ir_irq(int irqn ir_raw_event_handle(ir->rc); } @@ -42,7 +40,7 @@ index 0a7f7eab3cc3..48be400421cd 100644 return IRQ_HANDLED; } -@@ -160,17 +155,14 @@ static int sunxi_ir_set_timeout(struct rc_dev *rc_dev, unsigned int timeout) +@@ -160,17 +155,14 @@ static int sunxi_ir_set_timeout(struct r { struct sunxi_ir *ir = rc_dev->priv; unsigned int base_clk = clk_get_rate(ir->clk); @@ -60,7 +58,7 @@ index 0a7f7eab3cc3..48be400421cd 100644 rc_dev->timeout = sunxi_ithr_to_usec(base_clk, ithr); -@@ -199,8 +191,6 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -199,8 +191,6 @@ static int sunxi_ir_probe(struct platfor return -ENODEV; } @@ -69,6 +67,3 @@ index 0a7f7eab3cc3..48be400421cd 100644 ir->fifo_size = quirks->fifo_size; /* Clock */ --- -2.30.0 - diff --git a/projects/Allwinner/patches/linux/crust/0034-media-sunxi-cir-Factor-out-hardware-initialization.patch b/projects/Allwinner/patches/linux/crust/0034-media-sunxi-cir-Factor-out-hardware-initialization.patch index 5241b44254..0cf08d829d 100644 --- a/projects/Allwinner/patches/linux/crust/0034-media-sunxi-cir-Factor-out-hardware-initialization.patch +++ b/projects/Allwinner/patches/linux/crust/0034-media-sunxi-cir-Factor-out-hardware-initialization.patch @@ -8,8 +8,6 @@ Signed-off-by: Samuel Holland drivers/media/rc/sunxi-cir.c | 142 ++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 60 deletions(-) -diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c -index 48be400421cd..1047654e601b 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -90,6 +90,7 @@ struct sunxi_ir { @@ -20,7 +18,7 @@ index 48be400421cd..1047654e601b 100644 struct clk *clk; struct clk *apb_clk; struct reset_control *rst; -@@ -169,10 +170,81 @@ static int sunxi_ir_set_timeout(struct rc_dev *rc_dev, unsigned int timeout) +@@ -169,10 +170,81 @@ static int sunxi_ir_set_timeout(struct r return 0; } @@ -103,7 +101,7 @@ index 48be400421cd..1047654e601b 100644 struct device *dev = &pdev->dev; struct device_node *dn = dev->of_node; -@@ -207,49 +279,26 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -207,49 +279,26 @@ static int sunxi_ir_probe(struct platfor /* Base clock frequency (optional) */ of_property_read_u32(dn, "clock-frequency", &b_clk_freq); @@ -156,7 +154,7 @@ index 48be400421cd..1047654e601b 100644 } ir->rc->priv = ir; -@@ -265,6 +314,7 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -265,6 +314,7 @@ static int sunxi_ir_probe(struct platfor ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; /* Frequency after IR internal divider with sample period in us */ ir->rc->rx_resolution = (USEC_PER_SEC / (b_clk_freq / 64)); @@ -164,7 +162,7 @@ index 48be400421cd..1047654e601b 100644 ir->rc->min_timeout = sunxi_ithr_to_usec(b_clk_freq, 0); ir->rc->max_timeout = sunxi_ithr_to_usec(b_clk_freq, 255); ir->rc->s_timeout = sunxi_ir_set_timeout; -@@ -291,41 +341,15 @@ static int sunxi_ir_probe(struct platform_device *pdev) +@@ -291,41 +341,15 @@ static int sunxi_ir_probe(struct platfor goto exit_free_dev; } @@ -209,7 +207,7 @@ index 48be400421cd..1047654e601b 100644 return ret; } -@@ -334,11 +358,9 @@ static int sunxi_ir_remove(struct platform_device *pdev) +@@ -334,11 +358,9 @@ static int sunxi_ir_remove(struct platfo { struct sunxi_ir *ir = platform_get_drvdata(pdev); @@ -223,6 +221,3 @@ index 48be400421cd..1047654e601b 100644 return 0; } --- -2.30.0 - diff --git a/projects/Allwinner/patches/linux/crust/0035-media-sunxi-cir-Implement-suspend-resume-shutdown-ca.patch b/projects/Allwinner/patches/linux/crust/0035-media-sunxi-cir-Implement-suspend-resume-shutdown-ca.patch index b747b772c7..200b7e373e 100644 --- a/projects/Allwinner/patches/linux/crust/0035-media-sunxi-cir-Implement-suspend-resume-shutdown-ca.patch +++ b/projects/Allwinner/patches/linux/crust/0035-media-sunxi-cir-Implement-suspend-resume-shutdown-ca.patch @@ -9,11 +9,9 @@ Signed-off-by: Samuel Holland drivers/media/rc/sunxi-cir.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) -diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c -index 1047654e601b..4e025f3980f4 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c -@@ -242,6 +242,18 @@ static void sunxi_ir_hw_exit(struct device *dev) +@@ -242,6 +242,18 @@ static void sunxi_ir_hw_exit(struct devi reset_control_assert(ir->rst); } @@ -32,7 +30,7 @@ index 1047654e601b..4e025f3980f4 100644 static int sunxi_ir_probe(struct platform_device *pdev) { int ret = 0; -@@ -364,6 +376,11 @@ static int sunxi_ir_remove(struct platform_device *pdev) +@@ -364,6 +376,11 @@ static int sunxi_ir_remove(struct platfo return 0; } @@ -44,7 +42,7 @@ index 1047654e601b..4e025f3980f4 100644 static const struct sunxi_ir_quirks sun4i_a10_ir_quirks = { .has_reset = false, .fifo_size = 16, -@@ -396,12 +413,16 @@ static const struct of_device_id sunxi_ir_match[] = { +@@ -396,12 +413,16 @@ static const struct of_device_id sunxi_i }; MODULE_DEVICE_TABLE(of, sunxi_ir_match); @@ -61,6 +59,3 @@ index 1047654e601b..4e025f3980f4 100644 }, }; --- -2.30.0 -