Merge pull request #5862 from jernejsk/spdif

Allwinner: Sort out SPDIF support
This commit is contained in:
knaerzche 2021-11-09 21:33:41 +01:00 committed by GitHub
commit abfe01743d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 191 additions and 9 deletions

View File

@ -22,7 +22,7 @@ simple-card.pcm.hdmi."allwinner-hdmi" {
type ctl_elems type ctl_elems
hook_args [ hook_args [
{ {
interface MIXER interface PCM
name "IEC958 Playback Default" name "IEC958 Playback Default"
lock true lock true
preserve true preserve true
@ -71,6 +71,8 @@ simple-card.pcm.hdmi.0 {
<confdir:pcm/iec958.conf> <confdir:pcm/iec958.conf>
simple-card.pcm.iec958."On-board SPDIF" "cards.simple-card.pcm.iec958.sun50i-h6-spdif"
simple-card.pcm.iec958."sun50i-h6-spdif" { simple-card.pcm.iec958."sun50i-h6-spdif" {
@args [ CARD DEVICE AES0 AES1 AES2 AES3 ] @args [ CARD DEVICE AES0 AES1 AES2 AES3 ]
@args.CARD { type string } @args.CARD { type string }
@ -89,7 +91,7 @@ simple-card.pcm.iec958."sun50i-h6-spdif" {
type ctl_elems type ctl_elems
hook_args [ hook_args [
{ {
interface MIXER interface PCM
name "IEC958 Playback Default" name "IEC958 Playback Default"
lock true lock true
preserve true preserve true

View File

@ -20,12 +20,6 @@
<default>ALSA:hdmi:CARD=allwinnerhdmi,DEV=0</default> <default>ALSA:hdmi:CARD=allwinnerhdmi,DEV=0</default>
</setting> </setting>
</group> </group>
<group id="3">
<visible>false</visible>
<setting id="audiooutput.passthrough">
<default>false</default>
</setting>
</group>
</category> </category>
</section> </section>

View File

@ -4309,7 +4309,7 @@ CONFIG_SND_SOC_HDMI_CODEC=y
# CONFIG_SND_SOC_SGTL5000 is not set # CONFIG_SND_SOC_SGTL5000 is not set
# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set # CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set
# CONFIG_SND_SOC_SIMPLE_MUX is not set # CONFIG_SND_SOC_SIMPLE_MUX is not set
# CONFIG_SND_SOC_SPDIF is not set CONFIG_SND_SOC_SPDIF=y
# CONFIG_SND_SOC_SSM2305 is not set # CONFIG_SND_SOC_SSM2305 is not set
# CONFIG_SND_SOC_SSM2518 is not set # CONFIG_SND_SOC_SSM2518 is not set
# CONFIG_SND_SOC_SSM2602_SPI is not set # CONFIG_SND_SOC_SSM2602_SPI is not set

View File

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Mon, 8 Nov 2021 20:48:17 +0100
Subject: [PATCH] arm64: dts: allwinner: h6: tanix-tx6: Add SPDIF
Tanix TX6 board has SPDIF connector in form of 3.5 mm jack.
Add support for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
.../dts/allwinner/sun50i-h6-tanix-tx6.dts | 22 +++++++++++++++++++
1 file changed, 22 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 8f2a80f128de..6c10ff7f4b1c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
@@ -52,6 +52,24 @@ reg_vdd_cpu_gpu: regulator-vdd-cpu-gpu {
regulator-min-microvolt = <1135000>;
regulator-max-microvolt = <1135000>;
};
+
+ sound-spdif {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "sun50i-h6-spdif";
+
+ simple-audio-card,cpu {
+ sound-dai = <&spdif>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&spdif_out>;
+ };
+ };
+
+ spdif_out: spdif-out {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ };
};
&cpu0 {
@@ -127,6 +145,10 @@ &r_ir {
status = "okay";
};
+&spdif {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_ph_pins>;

View File

@ -0,0 +1,132 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Tue, 9 Nov 2021 18:52:37 +0100
Subject: [PATCH] ASoC: sunxi: sun4i-spdif: Implement IEC958 control
SPDIF core is capable of sending custom status.
Implement IEC958 control handling.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
sound/soc/sunxi/sun4i-spdif.c | 95 +++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index a10949bf0ca1..e80982b229ff 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <sound/asoundef.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -385,11 +386,105 @@ static int sun4i_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
+static int sun4i_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int sun4i_spdif_get_status_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 *status = ucontrol->value.iec958.status;
+
+ status[0] = 0xff;
+ status[1] = 0xff;
+ status[2] = 0xff;
+ status[3] = 0xff;
+ status[4] = 0xff;
+
+ return 0;
+}
+
+static int sun4i_spdif_get_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
+ u8 *status = ucontrol->value.iec958.status;
+ unsigned int reg;
+
+ regmap_read(host->regmap, SUN4I_SPDIF_TXCHSTA0, &reg);
+
+ status[0] = reg & 0xff;
+ status[1] = (reg >> 8) & 0xff;
+ status[2] = (reg >> 16) & 0xff;
+ status[3] = (reg >> 24) & 0xff;
+
+ regmap_read(host->regmap, SUN4I_SPDIF_TXCHSTA1, &reg);
+
+ status[4] = reg & 0xff;
+
+ return 0;
+}
+
+static int sun4i_spdif_set_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
+ u8 *status = ucontrol->value.iec958.status;
+ unsigned int reg;
+
+ reg = ((u32)status[3] << 24);
+ reg |= ((u32)status[2] << 16);
+ reg |= ((u32)status[1] << 8);
+ reg |= (u32)status[0];
+
+ regmap_write(host->regmap, SUN4I_SPDIF_TXCHSTA0, reg);
+
+ reg = status[4];
+ regmap_write(host->regmap, SUN4I_SPDIF_TXCHSTA1, reg);
+
+ reg = SUN4I_SPDIF_TXCFG_CHSTMODE;
+ if (status[0] & IEC958_AES0_NONAUDIO)
+ reg |= SUN4I_SPDIF_TXCFG_NONAUDIO;
+
+ regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG,
+ SUN4I_SPDIF_TXCFG_CHSTMODE |
+ SUN4I_SPDIF_TXCFG_NONAUDIO, reg);
+
+ return 0;
+}
+
+static struct snd_kcontrol_new sun4i_spdif_controls[] = {
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
+ .info = sun4i_spdif_info,
+ .get = sun4i_spdif_get_status_mask
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+ .info = sun4i_spdif_info,
+ .get = sun4i_spdif_get_status,
+ .put = sun4i_spdif_set_status
+ }
+};
+
static int sun4i_spdif_soc_dai_probe(struct snd_soc_dai *dai)
{
struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &host->dma_params_tx, NULL);
+ snd_soc_add_dai_controls(dai, sun4i_spdif_controls,
+ ARRAY_SIZE(sun4i_spdif_controls));
+
return 0;
}