From b8ae84ce753b1bc8639398f17e9f72434d0d4423 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 8 Nov 2021 20:51:28 +0100 Subject: [PATCH] Allwinner: linux: Add SPDIF patches --- ...dts-allwinner-h6-tanix-tx6-Add-SPDIF.patch | 54 +++++++ ...sun4i-spdif-Implement-IEC958-control.patch | 132 ++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-h6-tanix-tx6-Add-SPDIF.patch create mode 100644 projects/Allwinner/patches/linux/0062-ASoC-sunxi-sun4i-spdif-Implement-IEC958-control.patch diff --git a/projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-h6-tanix-tx6-Add-SPDIF.patch b/projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-h6-tanix-tx6-Add-SPDIF.patch new file mode 100644 index 0000000000..4a3fb2aeb1 --- /dev/null +++ b/projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-h6-tanix-tx6-Add-SPDIF.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +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 +--- + .../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>; diff --git a/projects/Allwinner/patches/linux/0062-ASoC-sunxi-sun4i-spdif-Implement-IEC958-control.patch b/projects/Allwinner/patches/linux/0062-ASoC-sunxi-sun4i-spdif-Implement-IEC958-control.patch new file mode 100644 index 0000000000..9026016d48 --- /dev/null +++ b/projects/Allwinner/patches/linux/0062-ASoC-sunxi-sun4i-spdif-Implement-IEC958-control.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +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 +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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, ®); ++ ++ 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, ®); ++ ++ 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; + } +