mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 13:46:49 +00:00
Merge pull request #4976 from jernejsk/aw-patch-rework
Allwinner: Complete patch reorganization
This commit is contained in:
commit
7b30b3d505
@ -0,0 +1,53 @@
|
||||
From ff9ed48eb584e583e20509af6cde1ba80ebd3edd Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 16 Jan 2021 10:49:00 +0100
|
||||
Subject: [PATCH] HACK: a64: Add HDMI sound card
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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>;
|
@ -8,11 +8,9 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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
|
||||
|
@ -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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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>;
|
@ -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>;
|
@ -1,24 +0,0 @@
|
||||
From 08d35c5d5ce6de3453f17e6eff7375afa74173d2 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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
|
||||
|
@ -0,0 +1,26 @@
|
||||
From 4cc652f2c660bd01bd0d8cefde272400cbe82fbe Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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>;
|
@ -1,14 +1,13 @@
|
||||
commit 9702424ea23471e3bdbe6a150e28a1ecdf837d2c
|
||||
Author: PJBrs <pjbrs@floorenpj.xs4all.nl>
|
||||
Date: Fri Feb 21 08:56:04 2020 +0100
|
||||
From aa47c3b292cb0ffcf2c00b2a12c477ec3027a729 Mon Sep 17 00:00:00 2001
|
||||
From: PJBrs <pjbrs@floorenpj.xs4all.nl>
|
||||
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 @@
|
||||
};
|
||||
};
|
||||
|
@ -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>;
|
@ -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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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>;
|
@ -1,24 +0,0 @@
|
||||
From 51dcda7a261bcadca0a8f5e6fe6241ec266438d0 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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
|
||||
|
@ -1,85 +1,24 @@
|
||||
From bf21ad0889bdcc1dc12fe5a024fd7df7ad2c4310 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
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 <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
@@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
@ -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
|
||||
|
@ -0,0 +1,25 @@
|
||||
From 54b5c2cb4fc87ca72daa662423d4d969f3b5edb8 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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>;
|
@ -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>;
|
@ -1,24 +0,0 @@
|
||||
From 51dcda7a261bcadca0a8f5e6fe6241ec266438d0 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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
|
||||
|
@ -1,36 +0,0 @@
|
||||
#
|
||||
# Configuration for H3 analog output
|
||||
#
|
||||
|
||||
<confdir:pcm/front.conf>
|
||||
|
||||
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 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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>;
|
@ -1,24 +0,0 @@
|
||||
From 51dcda7a261bcadca0a8f5e6fe6241ec266438d0 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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
|
||||
|
@ -0,0 +1,53 @@
|
||||
From da5268aa6c9a552ceebf74263acf997489368adc Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 16 Jan 2021 10:58:14 +0100
|
||||
Subject: [PATCH 01/14] HACK: h6: Add HDMI sound card
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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>;
|
@ -0,0 +1,70 @@
|
||||
From 7f12904df66e28c2a5fa8ea652ed9eee48a22131 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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
|
@ -0,0 +1,81 @@
|
||||
From 455e29ad5f37b40532b9cf56781dab3c3eb275b5 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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;
|
@ -0,0 +1,95 @@
|
||||
From a2903d15de86fc3ab455a665e22ad6e5c27f8c43 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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).
|
@ -0,0 +1,100 @@
|
||||
From 3a078af461185f3ed34c182616365da3a60c6b77 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 */
|
@ -0,0 +1,67 @@
|
||||
From e58355ab59c95b3ce708d3fdb417e3893170cfde Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 <linux/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
+#include <linux/reboot.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/stmmac.h>
|
||||
|
||||
@@ -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).
|
@ -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 <icenowy@aosc.io>
|
||||
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 <wens@csie.org>
|
||||
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";
|
||||
};
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,55 @@
|
||||
From b6b784bac19b9ee68b7f7ee5855216b76ac118cd Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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";
|
@ -0,0 +1,75 @@
|
||||
From ff190627e3986569a2516f36e218adcde02fc78b Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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";
|
@ -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 <git-commit@mailhell.seb7.de>
|
||||
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 <git-commit@mailhell.seb7.de>
|
||||
---
|
||||
.../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
|
||||
|
@ -1,3 +1,12 @@
|
||||
From 4b723d23c444ae9dc85ecea51a1ae4de092ddf54 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?=
|
||||
<alejandro.gonzalez.correo@gmail.com>
|
||||
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 <alejandro.gonzalez.correo@gmail.com>
|
||||
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
|
@ -0,0 +1,45 @@
|
||||
From 083e09f834e58cad72671e4df2136cf36c10aaa7 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Thu, 29 Oct 2020 21:04:24 +0100
|
||||
Subject: [PATCH 13/14] pineh64 model b - bluetooth wip
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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;
|
||||
}
|
||||
|
@ -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 <samuel@sholland.org>
|
||||
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);
|
||||
|
@ -1,68 +0,0 @@
|
||||
From 026ec1598d98a0bd45785a44a74ddb7063d2f776 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue, 22 Jan 2019 20:16:58 +0100
|
||||
Subject: [PATCH] AW H6 I2S WIP
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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
|
@ -1,442 +0,0 @@
|
||||
From 0b2bbc6708ef986e2f8d281f65e0c1ca3ff14562 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 <megous@megous.com>
|
||||
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 <megous@megous.com>
|
||||
---
|
||||
.../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 <linux/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
+#include <linux/reboot.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/stmmac.h>
|
||||
|
||||
@@ -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
|
||||
|
@ -1,159 +0,0 @@
|
||||
From e6cdedb22a9b012366d07276dace02c2c98fffc4 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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 <jernej.skrabec@siol.net>
|
||||
Date: Sat, 24 Aug 2019 01:03:05 +0200
|
||||
Subject: [PATCH] Tanix TX6 improvements
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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
|
@ -1,24 +0,0 @@
|
||||
From 3e9d104275c44ab1711a3564ce67cabe850afe75 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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
|
||||
|
@ -1,101 +0,0 @@
|
||||
From 23fa74407f0c71e06e10cb55ca64722b97d924f0 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <wens@csie.org>
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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 <jernej.skrabec@siol.net>
|
||||
Date: Thu, 29 Oct 2020 21:04:24 +0100
|
||||
Subject: [PATCH 2/2] pineh64 model b - bluetooth wip
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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
|
||||
|
@ -1,36 +0,0 @@
|
||||
#
|
||||
# Configuration for H3 analog output
|
||||
#
|
||||
|
||||
<confdir:pcm/front.conf>
|
||||
|
||||
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 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
From 8e2b67acc77a0c7704b2001dd4bf8646f286e4be Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&osc24M>;
|
||||
+ };
|
||||
+
|
||||
wdt: watchdog@1c20c90 {
|
||||
compatible = "allwinner,sun4i-a10-wdt";
|
||||
reg = <0x01c20c90 0x10>;
|
@ -0,0 +1,57 @@
|
||||
From 958ad802878443a2f5f06f5f3c796d163fd03ca9 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Mon, 24 Aug 2020 16:35:54 +0200
|
||||
Subject: [PATCH 16/17] dts: enable analog codec
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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 = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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>;
|
@ -8,11 +8,9 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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
|
||||
|
@ -1,112 +0,0 @@
|
||||
From 7ace610aa8c87a4854c974299f880f168a8b075d Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Mon, 24 Aug 2020 16:35:00 +0200
|
||||
Subject: [PATCH 15/17] clk: r40: initialize clocks earlier
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
@@ -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
|
||||
|
@ -1,101 +0,0 @@
|
||||
From 958ad802878443a2f5f06f5f3c796d163fd03ca9 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Mon, 24 Aug 2020 16:35:54 +0200
|
||||
Subject: [PATCH 16/17] dts: enable various devices
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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 = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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 = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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 = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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
|
||||
|
||||
},
|
@ -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 <sean@mess.org>
|
||||
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 <mchehab+huawei@kernel.org>
|
||||
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
|
||||
|
@ -0,0 +1,118 @@
|
||||
From a8bdfe3893f9b226492dac4b4e0d37a27dbee201 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com>
|
||||
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 <samuel@sholland.org>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-3-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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;
|
@ -0,0 +1,295 @@
|
||||
From 8ff0df5dffe58a2d1595a6e59ccd5ce63d6bf0e5 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-4-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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);
|
@ -1,752 +0,0 @@
|
||||
From b5cb1681a065bd03b0eb84ca243bc50ab0fa54c1 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Date: Thu, 7 Nov 2019 07:36:11 +0100
|
||||
Subject: [PATCH] sound: soc: sun4i-i2s: Fix rate calculation
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,134 @@
|
||||
From aec30a56043a890b75440bb8c9673a07166cf104 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com>
|
||||
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 <wens@csie.org>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-5-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,86 @@
|
||||
From fe1ae019879d51633d8dcd705117c70b701b77e9 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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 <codekipper@gmail.com>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-6-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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;
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
From 9c2121fe514f12c830bceea7b33872fa67af3e97 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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 <codekipper@gmail.com>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-7-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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,
|
@ -0,0 +1,49 @@
|
||||
From 9f0cbed8e957216d58a2dd5c9c8e795ec39004ad Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com>
|
||||
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 <mripard@kernel.org>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-8-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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[] = {
|
@ -0,0 +1,53 @@
|
||||
From de8ff7b3ac4736f5aa0c55968170bd449e46c88f Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
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 <samuel@sholland.org>
|
||||
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-9-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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;
|
@ -0,0 +1,44 @@
|
||||
From 82b0eb24d554180fdea8a254553dcce22085cc74 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com>
|
||||
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 <mripard@kernel.org>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20201030144648.397824-10-peron.clem@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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 {
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
|
||||
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 @@
|
||||
};
|
||||
};
|
||||
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
|
||||
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>;
|
||||
};
|
||||
|
@ -0,0 +1,40 @@
|
||||
From dcd9635dc6027b04a64e19ebb3dc15aaae082400 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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)
|
@ -0,0 +1,163 @@
|
||||
From acdfa534d3fe6759f43c1fe0bcd2fd40f31d3797 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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)
|
@ -0,0 +1,62 @@
|
||||
From 2c9a7a5a71d5ed6db9ee28a5ccd11f0db45f574d Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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);
|
@ -0,0 +1,27 @@
|
||||
From e689f3536e632e26166e66eac88728c6653a18b6 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
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 <samuel@sholland.org>
|
||||
Acked-by: Maxime Ripard <mripard@kernel.org>
|
||||
---
|
||||
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)
|
@ -0,0 +1,42 @@
|
||||
From e019a54d084020e6acc2869da341b376700bfe4c Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
|
||||
Acked-by: Chen-Yu Tsai <wens@csie.org>
|
||||
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 = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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";
|
@ -0,0 +1,43 @@
|
||||
From 0175a3d5680924d3d64ee8181b50c8b06ee715d1 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
|
||||
Acked-by: Chen-Yu Tsai <wens@csie.org>
|
||||
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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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";
|
@ -0,0 +1,42 @@
|
||||
From fd67e65487b4e5e2a93df2868043302a99f93098 Mon Sep 17 00:00:00 2001
|
||||
From: Marcus Cooper <codekipper@gmail.com>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
|
||||
Signed-off-by: Clément Péron <peron.clem@gmail.com>
|
||||
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
|
||||
Acked-by: Chen-Yu Tsai <wens@csie.org>
|
||||
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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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";
|
@ -0,0 +1,47 @@
|
||||
From 3c970c9e87e403b190407dec5c6e4745aef78e6a Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
|
||||
Tested-by: <clabbe.montjoie@gmail.com>
|
||||
Acked-by: Chen-Yu Tsai <wens@csie.org>
|
||||
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";
|
||||
+};
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
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
|
||||
|
@ -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 <jonas@kwiboo.se>
|
||||
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
|
||||
|
@ -0,0 +1,85 @@
|
||||
From 82a8ceccbaf9aa3d8cbc56d10e3905eec0d4ffb4 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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
|
@ -0,0 +1,150 @@
|
||||
From b4b79b4eeacb63f0a72c866526e4a2021a201090 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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)
|
||||
|
@ -0,0 +1,36 @@
|
||||
From e61cf76fca5984dd9edcb0daf6c5cb5278f32e05 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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];
|
@ -0,0 +1,90 @@
|
||||
From d99740197a9776b9332d21b9f3b05dab658a90eb Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../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;
|
@ -0,0 +1,195 @@
|
||||
From 9e203d78974aa445086dbe6b667e49b3f00d36d0 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 26 Oct 2019 21:23:55 +0200
|
||||
Subject: [PATCH 27/44] media: cedrus: hevc: tiles hack
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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];
|
@ -0,0 +1,50 @@
|
||||
From b6d288bb8823e11114297d1e406ccd977106aaf9 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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,
|
@ -0,0 +1,235 @@
|
||||
From d4ffac11f0d8b3a844f528e963b953a6bfe540af Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 9 Nov 2019 13:22:05 +0100
|
||||
Subject: [PATCH 29/44] media: cedrus: hevc: Improve buffer management
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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,
|
||||
};
|
@ -0,0 +1,197 @@
|
||||
From a881ce25cba8e45c6a86b5a680981c3b14b5b1e1 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 9 Nov 2019 14:12:42 +0100
|
||||
Subject: [PATCH 30/44] media: cedrus: h264: Improve buffer management
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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,
|
||||
};
|
@ -0,0 +1,155 @@
|
||||
From 54389b5956af51023b073a08eeb7a746a4a37119 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sun, 15 Mar 2020 21:35:39 +0100
|
||||
Subject: [PATCH 31/44] WIp: 10-bit HEVC support
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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
|
@ -0,0 +1,100 @@
|
||||
From f26df66c4d6ea08a865a16df82af37035401254d Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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)
|
||||
|
@ -0,0 +1,985 @@
|
||||
From 574ba48fa87225fbf3e39ffd2b11a6fb93cb6c98 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 <jernej.skrabec@siol.net>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#include <media/videobuf2-dma-contig.h>
|
||||
+
|
||||
+#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,
|
||||
+};
|
@ -0,0 +1,57 @@
|
||||
From f826ffb93b1ba0cfb9a5cfa3403813674331d4e0 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
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 <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
@@ -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) {
|
@ -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 <roman.stratiienko@globallogic.com>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 = {
|
@ -0,0 +1,55 @@
|
||||
From 144ad308ded7c5617d9574e174b68cbcb622cf4c Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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:
|
@ -0,0 +1,38 @@
|
||||
From 2e5d4ca1c07ddf06f8c3b18fd73baea7ce711169 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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)
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
@ -13,8 +13,6 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>");
|
||||
+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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 <jernej.skrabec@siol.net>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mfd/ac200.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/phy.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#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 <jernej.skrabec@siol.net>");
|
||||
+MODULE_DESCRIPTION("AC200 Ethernet PHY driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.22.1
|
||||
|
@ -0,0 +1,276 @@
|
||||
From cbf68fb141747879e2e6c43584c1e1e3b4d77683 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 <jernej.skrabec@siol.net>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mfd/ac200.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/phy.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#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 <jernej.skrabec@siol.net>");
|
||||
+MODULE_DESCRIPTION("AC200 Ethernet PHY driver");
|
||||
+MODULE_LICENSE("GPL");
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
@ -15,11 +15,9 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>");
|
||||
+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
|
||||
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,50 @@
|
||||
From b10b474925447933bf1d718e6d064190b15b56d9 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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
|
@ -0,0 +1,288 @@
|
||||
From a19b428a02224e0e01fff4738bbf0632942d18a1 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Fri, 15 Jan 2021 00:13:54 +0100
|
||||
Subject: [PATCH 43/44] WIP: I2S multi channel
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
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)) {
|
@ -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 <jernej.skrabec@siol.net>
|
||||
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 <jernej.skrabec@siol.net>
|
||||
---
|
||||
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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ 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 {
|
@ -11,7 +11,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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 <samuel@sholland.org>
|
||||
#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";
|
||||
|
@ -19,7 +19,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
#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";
|
||||
|
@ -11,7 +11,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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 <samuel@sholland.org>
|
||||
#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";
|
||||
|
@ -15,7 +15,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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>;
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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 <samuel@sholland.org>
|
||||
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 <samuel@sholland.org>
|
||||
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>;
|
||||
|
@ -17,7 +17,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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 <samuel@sholland.org>
|
||||
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 <samuel@sholland.org>
|
||||
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>;
|
||||
|
@ -13,7 +13,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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 {
|
||||
|
@ -17,7 +17,7 @@ Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
|
||||
--- 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 <samuel@sholland.org>
|
||||
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 <samuel@sholland.org>
|
||||
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>;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user