[RFC PATCH v1 0/1] ASoC: meson: aiu: HDMI codec control questions and issues

Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
On Amlogic Meson GXBB/GXL/GXM SoCs a DesignWare HDMI TX controller is used. This has an SPDIF input but there's currently not driver for it. On Meson8/8b/8m2 SoCs I am working on a HDMI driver for the TransSwitch HDMI controller which - just like DesignWare HDMI TX - supports SPDIF and I2S inputs. I decided to add SPDIF support to the latter since the code from the vendor driver is much easier.
It took me a while to figure out why I would not get any audio output from AIU SPDIF to the HDMI controller - or from there to the sink. The "fix" for this issue is the RFC patch which is part of this series. Any feedback would be great as I am still new to the ASoC subsystem.
Another part I am still struggling with is the audio "routing" (due to lack of a better term - please correct me if this is not the right word to use for this case). I have the following description in my .dts: sound { compatible = "amlogic,gx-sound-card"; model = "M8B-ODROID-C1";
assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; assigned-clock-rates = <294912000>, <270950400>; dai-link-0 { sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; };
dai-link-1 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; };
dai-link-2 { sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; dai-format = "i2s"; mclk-fs = <256>;
codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_I2S>; }; };
dai-link-3 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_PCM>; }; };
dai-link-4 { sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
codec-0 { sound-dai = <&hdmi_tx>; }; }; }; The driver for &hdmi_tx defines: struct hdmi_codec_pdata pdata = { .ops = &txc_48352_hdmi_codec_ops, .i2s = 1, .spdif = 1, .max_i2s_channels = 8, .data = priv, }; In hdmi_codec_ops.hw_params I always get fmt->fmt HDMI_I2S unless I remove all I2S references from the .dts snipped above (only then HDMI_SPDIF is detected). Based on the selection of the "HDMI Source" enum in aiu-codec-ctrl I was expecting the format to update as well. That unfortunately doesn't happen and I don't know how that can be achieved.
Best regards, Martin
Martin Blumenstingl (1): ASoC: meson: aiu: Fix HDMI codec control selection
sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++-------- sound/soc/meson/aiu-encoder-i2s.c | 6 -- 2 files changed, 80 insertions(+), 34 deletions(-)

The HDMI controllers on Amlogic Meson SoCs which use the AIU audio-controller have two different audio format inputs: - I2S which is also the only configuration supported on GXBB, GXL and GXM SoCs since there's no SPDIF support in the DesignWare HDMI controller driver (at the time of writing this) - SPDIF can be used optionally, including pass-through formats
Switching between these requires us to set different registers: AIU_HDMI_CLK_DATA_CTRL[1:0] "HDMI_DATA_CLK_SEL": - 0x0 disables the HDMI output clock - 0x1 selects the PCM clock - 0x2 selects the AIU clock - 0x3 is reserved
AIU_HDMI_CLK_DATA_CTRL[5:4] "HDMI_DATA_SEL": - 0x0 outputs constant zero, disables HDMI data - 0x1 selects PCM data - 0x2 selects AIU I2S data - 0x3 is reserved
AIU_CLK_CTRL_MORE[6] "HDMITX_SEL_AOCLKX2": - 0x0 selects cts_i958 as AIU clk to hdmi_tx_audio_master_clk - 0x1 selects cts_aoclkx2_int as AIU clk to hdmi_tx_audio_master_clk
The Meson8/8b/8m2 vendor driver uses the following settings: SPDIF output to the HDMI controller: - 0x2 (AIU clock) in AIU_HDMI_CLK_DATA_CTRL[1:0] - 0x0 (no HDMI data) in AIU_HDMI_CLK_DATA_CTRL[5:4] - 0x0 (using cts_i958 as AIU clk) in AIU_CLK_CTRL_MORE[6] I2S output to the HDMI controller: - 0x2 (AIU clock) in AIU_HDMI_CLK_DATA_CTRL[1:0] - 0x2 (I2S data) in AIU_HDMI_CLK_DATA_CTRL[5:4] - 0x0 (using cts_aoclkx2_int as AIU clk) in AIU_CLK_CTRL_MORE[6]
The GXBB/GXL/GXM vendor driver uses the following settings: SPDIF output to the HDMI controller: - not setting AIU_HDMI_CLK_DATA_CTRL at all - 0x0 (using cts_i958 as AIU clk) in AIU_CLK_CTRL_MORE[6] I2S output to the HDMI controller: - 0x2 (AIU clock) in AIU_HDMI_CLK_DATA_CTRL[1:0] - 0x2 (I2S data) in AIU_HDMI_CLK_DATA_CTRL[5:4] - 0x0 (using cts_aoclkx2_int as AIU clk) in AIU_CLK_CTRL_MORE[6]
Set the three registers at the same time following what the vendor driver does on Meson8/8b/8m2 SoCs. This makes the SPDIF output to the HDMI controller work. The entries and order of the entries in the enum is not changed on purpose to not break old configurations.
Fixes: b82b734c0e9a7 ("ASoC: meson: aiu: add hdmi codec control support") Signed-off-by: Martin Blumenstingl martin.blumenstingl@googlemail.com --- sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++-------- sound/soc/meson/aiu-encoder-i2s.c | 6 -- 2 files changed, 80 insertions(+), 34 deletions(-)
diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c index c3ea733fce91..2b8575491aeb 100644 --- a/sound/soc/meson/aiu-codec-ctrl.c +++ b/sound/soc/meson/aiu-codec-ctrl.c @@ -12,14 +12,60 @@ #include "aiu.h" #include "meson-codec-glue.h"
-#define CTRL_CLK_SEL GENMASK(1, 0) -#define CTRL_DATA_SEL_SHIFT 4 -#define CTRL_DATA_SEL (0x3 << CTRL_DATA_SEL_SHIFT) - -static const char * const aiu_codec_ctrl_mux_texts[] = { - "DISABLED", "PCM", "I2S", +#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL GENMASK(1, 0) +#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_DISABLE 0x0 +#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_PCM 0x1 +#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_AIU 0x2 +#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL GENMASK(5, 4) +#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_OUTPUT_ZERO 0x0 +#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_PCM_DATA 0x1 +#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_I2S_DATA 0x2 + +#define AIU_CLK_CTRL_MORE_AMCLK BIT(6) + +#define AIU_HDMI_CTRL_MUX_DISABLED 0 +#define AIU_HDMI_CTRL_MUX_PCM 1 +#define AIU_HDMI_CTRL_MUX_I2S 2 + +static const char * const aiu_codec_hdmi_ctrl_mux_texts[] = { + [AIU_HDMI_CTRL_MUX_DISABLED] = "DISABLED", + [AIU_HDMI_CTRL_MUX_PCM] = "PCM", + [AIU_HDMI_CTRL_MUX_I2S] = "I2S", };
+static int aiu_codec_ctrl_mux_get_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + unsigned int ctrl, more, mux = AIU_HDMI_CTRL_MUX_DISABLED; + + ctrl = snd_soc_component_read(component, AIU_HDMI_CLK_DATA_CTRL); + if (FIELD_GET(AIU_HDMI_CLK_DATA_CTRL_CLK_SEL, ctrl) != + AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_AIU) { + goto out; + } + + more = snd_soc_component_read(component, AIU_CLK_CTRL_MORE); + if (FIELD_GET(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, ctrl) == + AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_I2S_DATA && + !!(more & AIU_CLK_CTRL_MORE_AMCLK)) { + mux = AIU_HDMI_CTRL_MUX_I2S; + goto out; + } + + if (FIELD_GET(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, ctrl) == + AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_OUTPUT_ZERO && + !(more & AIU_CLK_CTRL_MORE_AMCLK)) { + mux = AIU_HDMI_CTRL_MUX_PCM; + goto out; + } + +out: + ucontrol->value.enumerated.item[0] = mux; + return 0; +} + static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -28,45 +74,51 @@ static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int mux, changed; + unsigned int mux, ctrl, more;
mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); - changed = snd_soc_component_test_bits(component, e->reg, - CTRL_DATA_SEL, - FIELD_PREP(CTRL_DATA_SEL, mux));
- if (!changed) - return 0; + if (mux == AIU_HDMI_CTRL_MUX_I2S) { + ctrl = FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, + AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_I2S_DATA); + more = AIU_CLK_CTRL_MORE_AMCLK; + } else { + ctrl = FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, + AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_OUTPUT_ZERO); + more = 0; + } + + if (mux == AIU_HDMI_CTRL_MUX_DISABLED) { + ctrl |= FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_CLK_SEL, + AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_DISABLE); + } else { + ctrl |= FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_CLK_SEL, + AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_AIU); + }
/* Force disconnect of the mux while updating */ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
- /* Reset the source first */ - snd_soc_component_update_bits(component, e->reg, - CTRL_CLK_SEL | - CTRL_DATA_SEL, - FIELD_PREP(CTRL_CLK_SEL, 0) | - FIELD_PREP(CTRL_DATA_SEL, 0)); + snd_soc_component_update_bits(component, AIU_HDMI_CLK_DATA_CTRL, + AIU_HDMI_CLK_DATA_CTRL_CLK_SEL | + AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, + ctrl);
- /* Set the appropriate source */ - snd_soc_component_update_bits(component, e->reg, - CTRL_CLK_SEL | - CTRL_DATA_SEL, - FIELD_PREP(CTRL_CLK_SEL, mux) | - FIELD_PREP(CTRL_DATA_SEL, mux)); + snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, + AIU_CLK_CTRL_MORE_AMCLK, + more);
snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
return 0; }
-static SOC_ENUM_SINGLE_DECL(aiu_hdmi_ctrl_mux_enum, AIU_HDMI_CLK_DATA_CTRL, - CTRL_DATA_SEL_SHIFT, - aiu_codec_ctrl_mux_texts); +static SOC_ENUM_SINGLE_VIRT_DECL(aiu_hdmi_ctrl_mux_enum, + aiu_codec_hdmi_ctrl_mux_texts);
static const struct snd_kcontrol_new aiu_hdmi_ctrl_mux = SOC_DAPM_ENUM_EXT("HDMI Source", aiu_hdmi_ctrl_mux_enum, - snd_soc_dapm_get_enum_double, + aiu_codec_ctrl_mux_get_enum, aiu_codec_ctrl_mux_put_enum);
static const struct snd_soc_dapm_widget aiu_hdmi_ctrl_widgets[] = { diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index d6aea7797641..ba3dac987112 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -24,7 +24,6 @@ #define AIU_CLK_CTRL_AOCLK_INVERT BIT(6) #define AIU_CLK_CTRL_LRCLK_INVERT BIT(7) #define AIU_CLK_CTRL_LRCLK_SKEW GENMASK(9, 8) -#define AIU_CLK_CTRL_MORE_HDMI_AMCLK BIT(6) #define AIU_CLK_CTRL_MORE_I2S_DIV GENMASK(5, 0) #define AIU_CODEC_DAC_LRCLK_CTRL_DIV GENMASK(11, 0)
@@ -210,11 +209,6 @@ static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component, if (ret) return ret;
- /* Make sure amclk is used for HDMI i2s as well */ - snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, - AIU_CLK_CTRL_MORE_HDMI_AMCLK, - AIU_CLK_CTRL_MORE_HDMI_AMCLK); - return 0; }

On Sun, Oct 03, 2021 at 01:43:12AM +0200, Martin Blumenstingl wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Hi, Martin,
The MGN issue surely must be that one when using ALSA directly (no dmix, no JACK, no Pulseaudio, no Pipewire, no nothing) and when the track changes or we pause it, when it resumes we get noise instead of sound, correct?
If so, thanks for trying to track this down!
I bring it up because Googling it seems to head straight to a Neil Armstrong post to linux-amlogic about what works and what doesn't on linux-meson currently, and only if you dig deeper you find a couple of reports apparently by the same person about the "machine gun noise" thing.
It doesn't sound like a machine gun noise to me :)
More like brown noise, but anyway what I'd like to note to everyone involved is that this one is a major dealbreaker. Unless using JACK, Pulseaudio, Pipewire (?) or at least dmix audio will degrade at the second song or when the user first pauses and then resumes a stream, completely ruining the experience.
On Amlogic Meson GXBB/GXL/GXM SoCs a DesignWare HDMI TX controller is used. This has an SPDIF input but there's currently not driver for it. On Meson8/8b/8m2 SoCs I am working on a HDMI driver for the TransSwitch HDMI controller which - just like DesignWare HDMI TX - supports SPDIF and I2S inputs. I decided to add SPDIF support to the latter since the code from the vendor driver is much easier.
It took me a while to figure out why I would not get any audio output from AIU SPDIF to the HDMI controller - or from there to the sink. The "fix" for this issue is the RFC patch which is part of this series. Any feedback would be great as I am still new to the ASoC subsystem.
Another part I am still struggling with is the audio "routing" (due to lack of a better term - please correct me if this is not the right word to use for this case). I have the following description in my .dts: sound { compatible = "amlogic,gx-sound-card"; model = "M8B-ODROID-C1";
assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; assigned-clock-rates = <294912000>, <270950400>; dai-link-0 { sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; }; dai-link-1 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; }; dai-link-2 { sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; dai-format = "i2s"; mclk-fs = <256>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_I2S>; }; }; dai-link-3 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_PCM>; }; }; dai-link-4 { sound-dai = <&aiu AIU_HDMI CTRL_OUT>; codec-0 { sound-dai = <&hdmi_tx>; }; };
}; The driver for &hdmi_tx defines: struct hdmi_codec_pdata pdata = { .ops = &txc_48352_hdmi_codec_ops, .i2s = 1, .spdif = 1, .max_i2s_channels = 8, .data = priv, }; In hdmi_codec_ops.hw_params I always get fmt->fmt HDMI_I2S unless I remove all I2S references from the .dts snipped above (only then HDMI_SPDIF is detected). Based on the selection of the "HDMI Source" enum in aiu-codec-ctrl I was expecting the format to update as well. That unfortunately doesn't happen and I don't know how that can be achieved.
Hm, that sounds weird. I hope you get the answers you are looking for.
Thanks, Geraldo Nascimento
Best regards, Martin
Martin Blumenstingl (1): ASoC: meson: aiu: Fix HDMI codec control selection
sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++-------- sound/soc/meson/aiu-encoder-i2s.c | 6 -- 2 files changed, 80 insertions(+), 34 deletions(-)
-- 2.33.0

On 3 Oct 2021, at 9:13 am, Geraldo Nascimento geraldogabriel@gmail.com wrote:
On Sun, Oct 03, 2021 at 01:43:12AM +0200, Martin Blumenstingl wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Hi, Martin,
The MGN issue surely must be that one when using ALSA directly (no dmix, no JACK, no Pulseaudio, no Pipewire, no nothing) and when the track changes or we pause it, when it resumes we get noise instead of sound, correct?
If so, thanks for trying to track this down!
I bring it up because Googling it seems to head straight to a Neil Armstrong post to linux-amlogic about what works and what doesn't on linux-meson currently, and only if you dig deeper you find a couple of reports apparently by the same person about the "machine gun noise" thing.
It doesn't sound like a machine gun noise to me :)
More like brown noise, but anyway what I'd like to note to everyone involved is that this one is a major dealbreaker. Unless using JACK, Pulseaudio, Pipewire (?) or at least dmix audio will degrade at the second song or when the user first pauses and then resumes a stream, completely ruining the experience.
I’m the origin of most reports that Google will eventually discover. I was told elsewhere that this is known as MGN so I’ve described it as such, but that could be wrong. For clarity this is the noise (triggered, and with AVR volume deliberately right down) followed by some navigation in the Kodi GUI to change output:
https://chewitt.libreelec.tv/testing/wp2_audio_noise.mov
In the LibreELEC images I work on where this occurs it’s not something I associate with play/pause (although I can’t definitively rule it out) or second or third songs (not something that happens that often or predictably) but more when there’s a hard transition like starting or stopping playback. I hit it most with simple scrolling around in the Kodi GUI, although that could be because (due to this issue) I limit media playback testing on AIU devices. It’s particularly simple to trigger from the Kodi Settings > System > Audio page, just scroll around it for 10-30 seconds, which is handy because the only way to stop the noise is switching audio source (from anything to anything) on the same page.
CH.
On Amlogic Meson GXBB/GXL/GXM SoCs a DesignWare HDMI TX controller is used. This has an SPDIF input but there's currently not driver for it. On Meson8/8b/8m2 SoCs I am working on a HDMI driver for the TransSwitch HDMI controller which - just like DesignWare HDMI TX - supports SPDIF and I2S inputs. I decided to add SPDIF support to the latter since the code from the vendor driver is much easier.
It took me a while to figure out why I would not get any audio output from AIU SPDIF to the HDMI controller - or from there to the sink. The "fix" for this issue is the RFC patch which is part of this series. Any feedback would be great as I am still new to the ASoC subsystem.
Another part I am still struggling with is the audio "routing" (due to lack of a better term - please correct me if this is not the right word to use for this case). I have the following description in my .dts: sound { compatible = "amlogic,gx-sound-card"; model = "M8B-ODROID-C1";
assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; assigned-clock-rates = <294912000>, <270950400>; dai-link-0 { sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; }; dai-link-1 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; }; dai-link-2 { sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; dai-format = "i2s"; mclk-fs = <256>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_I2S>; }; }; dai-link-3 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_PCM>; }; }; dai-link-4 { sound-dai = <&aiu AIU_HDMI CTRL_OUT>; codec-0 { sound-dai = <&hdmi_tx>; }; };
}; The driver for &hdmi_tx defines: struct hdmi_codec_pdata pdata = { .ops = &txc_48352_hdmi_codec_ops, .i2s = 1, .spdif = 1, .max_i2s_channels = 8, .data = priv, }; In hdmi_codec_ops.hw_params I always get fmt->fmt HDMI_I2S unless I remove all I2S references from the .dts snipped above (only then HDMI_SPDIF is detected). Based on the selection of the "HDMI Source" enum in aiu-codec-ctrl I was expecting the format to update as well. That unfortunately doesn't happen and I don't know how that can be achieved.
Hm, that sounds weird. I hope you get the answers you are looking for.
Thanks, Geraldo Nascimento
Best regards, Martin
Martin Blumenstingl (1): ASoC: meson: aiu: Fix HDMI codec control selection
sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++-------- sound/soc/meson/aiu-encoder-i2s.c | 6 -- 2 files changed, 80 insertions(+), 34 deletions(-)
-- 2.33.0

On Sun, Oct 03, 2021 at 11:00:15AM +0400, Christian Hewitt wrote:
On 3 Oct 2021, at 9:13 am, Geraldo Nascimento geraldogabriel@gmail.com wrote:
On Sun, Oct 03, 2021 at 01:43:12AM +0200, Martin Blumenstingl wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Hi, Martin,
The MGN issue surely must be that one when using ALSA directly (no dmix, no JACK, no Pulseaudio, no Pipewire, no nothing) and when the track changes or we pause it, when it resumes we get noise instead of sound, correct?
If so, thanks for trying to track this down!
I bring it up because Googling it seems to head straight to a Neil Armstrong post to linux-amlogic about what works and what doesn't on linux-meson currently, and only if you dig deeper you find a couple of reports apparently by the same person about the "machine gun noise" thing.
It doesn't sound like a machine gun noise to me :)
More like brown noise, but anyway what I'd like to note to everyone involved is that this one is a major dealbreaker. Unless using JACK, Pulseaudio, Pipewire (?) or at least dmix audio will degrade at the second song or when the user first pauses and then resumes a stream, completely ruining the experience.
I’m the origin of most reports that Google will eventually discover. I was told elsewhere that this is known as MGN so I’ve described it as such, but that could be wrong. For clarity this is the noise (triggered, and with AVR volume deliberately right down) followed by some navigation in the Kodi GUI to change output:
Hi, Christian,
Thanks for the video.
In the LibreELEC images I work on where this occurs it’s not something I associate with play/pause (although I can’t definitively rule it out) or second or third songs (not something that happens that often or predictably) but more when there’s a hard transition like starting or stopping playback. I hit it most with simple scrolling around in the Kodi GUI, although that could be because (due to this issue) I limit media playback testing on AIU devices. It’s particularly simple to trigger from the Kodi Settings > System > Audio page, just scroll around it for 10-30 seconds, which is handy because the only way to stop the noise is switching audio source (from anything to anything) on the same page.
CH.
I wasn't able to reproduce the bug by simply scrolling around. On the other hand, once I flipped the Send Low Volume Noise switch to off, all hell broke loose!
This is one show-stopper bug, and I empathize to how particularly nasty this must be for a "Just enough Linux for Kodi" approach.
But I also see Jerome Brunet has already clarified the subject in response to Martin Blumenstingl's original post.
Thank you, Geraldo Nascimento
On Amlogic Meson GXBB/GXL/GXM SoCs a DesignWare HDMI TX controller is used. This has an SPDIF input but there's currently not driver for it. On Meson8/8b/8m2 SoCs I am working on a HDMI driver for the TransSwitch HDMI controller which - just like DesignWare HDMI TX - supports SPDIF and I2S inputs. I decided to add SPDIF support to the latter since the code from the vendor driver is much easier.
It took me a while to figure out why I would not get any audio output from AIU SPDIF to the HDMI controller - or from there to the sink. The "fix" for this issue is the RFC patch which is part of this series. Any feedback would be great as I am still new to the ASoC subsystem.
Another part I am still struggling with is the audio "routing" (due to lack of a better term - please correct me if this is not the right word to use for this case). I have the following description in my .dts: sound { compatible = "amlogic,gx-sound-card"; model = "M8B-ODROID-C1";
assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; assigned-clock-rates = <294912000>, <270950400>; dai-link-0 { sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; }; dai-link-1 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; }; dai-link-2 { sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; dai-format = "i2s"; mclk-fs = <256>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_I2S>; }; }; dai-link-3 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_PCM>; }; }; dai-link-4 { sound-dai = <&aiu AIU_HDMI CTRL_OUT>; codec-0 { sound-dai = <&hdmi_tx>; }; };
}; The driver for &hdmi_tx defines: struct hdmi_codec_pdata pdata = { .ops = &txc_48352_hdmi_codec_ops, .i2s = 1, .spdif = 1, .max_i2s_channels = 8, .data = priv, }; In hdmi_codec_ops.hw_params I always get fmt->fmt HDMI_I2S unless I remove all I2S references from the .dts snipped above (only then HDMI_SPDIF is detected). Based on the selection of the "HDMI Source" enum in aiu-codec-ctrl I was expecting the format to update as well. That unfortunately doesn't happen and I don't know how that can be achieved.
Hm, that sounds weird. I hope you get the answers you are looking for.
Thanks, Geraldo Nascimento
Best regards, Martin
Martin Blumenstingl (1): ASoC: meson: aiu: Fix HDMI codec control selection
sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++-------- sound/soc/meson/aiu-encoder-i2s.c | 6 -- 2 files changed, 80 insertions(+), 34 deletions(-)
-- 2.33.0

On Sun, Oct 03, 2021 at 11:00:15AM +0400, Christian Hewitt wrote:
On 3 Oct 2021, at 9:13 am, Geraldo Nascimento geraldogabriel@gmail.com wrote:
It doesn't sound like a machine gun noise to me :)
More like brown noise, but anyway what I'd like to note to everyone involved is that this one is a major dealbreaker.
I’m the origin of most reports that Google will eventually discover. I was told elsewhere that this is known as MGN so I’ve described it as such, but that could be wrong. For clarity this is the noise (triggered, and with AVR volume deliberately right down) followed by some navigation in the Kodi GUI to change output:
Right, I would just call that static.
Please fix your mail client to word wrap within paragraphs at something substantially less than 80 columns. Doing this makes your messages much easier to read and reply to.

On Sun 03 Oct 2021 at 01:43, Martin Blumenstingl martin.blumenstingl@googlemail.com wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Ok, I'll clarify (again) about this issue.
This issue is on AIU only (not the AXG series), on the i2s encoder regardless of the output (HDMI, internal and external codec)
This encoder support either 2ch or 8ch mode, nothing else. As long as only 2ch was supported, there was no problem. In order to switch between 2ch and 8ch mode. AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC shall be "poked" (check iu-fifo-i2s.c and aiu-encoder-i2c.c). Without this, the switch is not done.
What these do, how and when it should be done is unclear. I tried several combination. At the time I found something stable-ish but it was not perfect.
At the time, It was completely new driver. Even if was not rock solid, it was still progress and I opted to upstream it with an imperfect 8ch support so people could help debug it. This was mentioned in the original submission.
The other solution is to restrict to 2ch mode and remove AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC pokes. There will be no noise anymore.
On Amlogic Meson GXBB/GXL/GXM SoCs a DesignWare HDMI TX controller is used. This has an SPDIF input but there's currently not driver for it. On Meson8/8b/8m2 SoCs I am working on a HDMI driver for the TransSwitch HDMI controller which - just like DesignWare HDMI TX - supports SPDIF and I2S inputs. I decided to add SPDIF support to the latter since the code from the vendor driver is much easier.
It took me a while to figure out why I would not get any audio output from AIU SPDIF to the HDMI controller - or from there to the sink. The "fix" for this issue is the RFC patch which is part of this series. Any feedback would be great as I am still new to the ASoC subsystem.
Another part I am still struggling with is the audio "routing" (due to lack of a better term - please correct me if this is not the right word to use for this case). I have the following description in my .dts: sound { compatible = "amlogic,gx-sound-card"; model = "M8B-ODROID-C1";
assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; assigned-clock-rates = <294912000>, <270950400>; dai-link-0 { sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; }; dai-link-1 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; }; dai-link-2 { sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; dai-format = "i2s"; mclk-fs = <256>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_I2S>; }; }; dai-link-3 { sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; codec-0 { sound-dai = <&aiu AIU_HDMI CTRL_PCM>;
Ok, the obove sums up the problem around this RFC.
Here you describe a DAI link (think of it as wires) between the SPDIF encoder (output) and AIU_HDMI input PCM. This is not what the HW is and it is not possible.
Let's start from the HDMI controller. The designware (on amlogic SoC) has 2 interface for audio input. 1) PCM/I2S: a classic interface 2 clocks and N data line 2) SPDIF: The Sony Philips 1 wire interface
Whatever comes up on 1) has to be some sort of i2s signal. So SPDIF won't fly there.
AIU_HDMI output is Hardwired to 1). It is just just a digital mux, implemented as an ASoC codec which allows to seleted one of 2 audio sources: A) the i2s output implemented as part of the AIU B) the PCM output, part the AUDIN (yes, an output in AUDIN) block. This is not implemented ATM.
So trying to handle SPDIF through AIU_HDMI is wrong.
}; }; dai-link-4 { sound-dai = <&aiu AIU_HDMI CTRL_OUT>; codec-0 { sound-dai = <&hdmi_tx>;
your HDMI controller should have an argument to the phandle if it supported both I2S and SPDIF inputs
}; };
}; The driver for &hdmi_tx defines: struct hdmi_codec_pdata pdata = { .ops = &txc_48352_hdmi_codec_ops, .i2s = 1, .spdif = 1, .max_i2s_channels = 8, .data = priv, }; In hdmi_codec_ops.hw_params I always get fmt->fmt HDMI_I2S unless I remove all I2S references from the .dts snipped above (only then HDMI_SPDIF is detected). Based on the selection of the "HDMI Source" enum in aiu-codec-ctrl I was expecting the format to update as well. That unfortunately doesn't happen and I don't know how that can be achieved.
It is not meant to. The dai_link and the endpoint are i2s. Your HDMI controller should have 2 inputs and should have a way to select one or the other. The format at each of the (internal) input does not change
Best regards, Martin
Martin Blumenstingl (1): ASoC: meson: aiu: Fix HDMI codec control selection
sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++-------- sound/soc/meson/aiu-encoder-i2s.c | 6 -- 2 files changed, 80 insertions(+), 34 deletions(-)

Hi Jerome,
first of all: thanks for taking the time to go through all of this!
On Sun, Oct 3, 2021 at 6:34 PM Jerome Brunet jbrunet@baylibre.com wrote:
On Sun 03 Oct 2021 at 01:43, Martin Blumenstingl martin.blumenstingl@googlemail.com wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Ok, I'll clarify (again) about this issue.
This issue is on AIU only (not the AXG series), on the i2s encoder regardless of the output (HDMI, internal and external codec)
Thanks for repeating this. It was clear to me that only AIU is affected but I didn't know that it only affects I2S
This encoder support either 2ch or 8ch mode, nothing else. As long as only 2ch was supported, there was no problem. In order to switch between 2ch and 8ch mode. AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC shall be "poked" (check iu-fifo-i2s.c and aiu-encoder-i2c.c). Without this, the switch is not done.
What these do, how and when it should be done is unclear. I tried several combination. At the time I found something stable-ish but it was not perfect.
old 32-bit u-boot sources from the Endless Mini do have some documentation on AIU_I2S_SYNC [0]: // 8'b0_000_1_1_10 // A write to this register will cause the interface to repeat the current // sample. Can be used to regain synchronization. // A read from this register indicates that the next sample to be sent // out of the interface should go into the _left_ channel of the dac.
There's also a note about AIU_I2S_MISC stating: // Bit 4 if true, force each audio data to left or right according to the bit attached with the audio data // This bit should be used with Register AIU_i2s_sync(0x511) together
To be honest: to me this is not helpful since I don't understand how/why the left channel is of importance.
At the time, It was completely new driver. Even if was not rock solid, it was still progress and I opted to upstream it with an imperfect 8ch support so people could help debug it. This was mentioned in the original submission.
The other solution is to restrict to 2ch mode and remove AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC pokes. There will be no noise anymore.
I think Christian (Hewitt) agrees on this point as he mentioned that your earlier versions of the AIU code (before it got upstream) were not affected by the "machine gun noise" issue. Does the documentation from above give you any new ideas (assuming that it's correct since it's the best we have)? Should I try playing with AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC to see if I can make a difference?
[...]
Here you describe a DAI link (think of it as wires) between the SPDIF encoder (output) and AIU_HDMI input PCM. This is not what the HW is and it is not possible.
Let's start from the HDMI controller. The designware (on amlogic SoC) has 2 interface for audio input.
- PCM/I2S: a classic interface 2 clocks and N data line
- SPDIF: The Sony Philips 1 wire interface
The Transwitch HDMI TX controller supports these two inputs so even though the IP is different the basic functionality (which we'll discuss below) is the same.
Whatever comes up on 1) has to be some sort of i2s signal. So SPDIF won't fly there.
I agree with this
AIU_HDMI output is Hardwired to 1). It is just just a digital mux, implemented as an ASoC codec which allows to seleted one of 2 audio sources: A) the i2s output implemented as part of the AIU B) the PCM output, part the AUDIN (yes, an output in AUDIN) block. This is not implemented ATM.
This is some interesting information, I thought that PCM was used because PCM audio can be transmitted over SPDIF.
For A) my understanding is different though: - for AIU_HDMI_CLK_DATA_CTRL[5:4] (HDMI_DATA_SEL) your description matches my understanding. For me it makes sense that SPDIF data cannot be selected with this register since it's a one-wire protocol (and doesn't have separate data/clock lines). Value 0x2 selects the I2S data interface - for AIU_HDMI_CLK_DATA_CTRL[1:0] (HDMI_DATA_CLK_SEL) however I have a different understanding: 0x0 disables the clock signal to the HDMI TX controller, 0x1 selects the PCM clock (which now I have learned is related to the AUDIN block) and 0x2 selects the "AIU clock" (see below) - my understanding is that "AIU clock" comes from AIU_CLK_CTRL_MORE[6] (HDMITX_SEL_AOCLKX2) where 0x0 selects "cts_i958 as AIU clk to hdmi_tx_audio_master_clk" (SPDIF clock) and 0x1 selects "cts_aoclkx2_int as AIU clk to hdmi_tx_audio_master_clk" (I2S clock)
So to me this means that there's three different muxes: - data mux to choose between 0x0 (all zeros), 0x1 (PCM) and 0x2 (I2S) - clock mux to choose between 0x0 (disabled), 0x1 (PCM) and 0x2 (hdmi_tx_audio_master_clk) - hdmi_tx_audio_master_clk clock mux to choose between 0x0 (cts_i958) and 0x1 (cts_aoclkx2_int)
Based on that I think that it's not possible to have AIU output the I2S and SPDIF signals at the same time to the HDMI TX controller and then letting the HDMI TX controller choose which one to use. Based on whichever signal (I2S or SPDIF) we want to use for HDMI we need to configure AIU accordingly (data and clock).
[...]
It is not meant to. The dai_link and the endpoint are i2s. Your HDMI controller should have 2 inputs and should have a way to select one or the other. The format at each of the (internal) input does not change
ah, that makes sense. Let's say AIU has some internal muxing for the HDMI output then AIU would have two outputs as well (let's call them HDMI_OUT_I2S and HDMI_OUT_SPDIF). Then I'd wire up each of these to their corresponding inputs on the HDMI TX controller.
Best regards, Martin

On Sun, Oct 3, 2021 at 9:17 PM Martin Blumenstingl martin.blumenstingl@googlemail.com wrote: [...]
documentation on AIU_I2S_SYNC [0]:
I forgot to add the link to my last email, sorry about that - adding it here to clarify where I got this info from.
[0] https://github.com/endlessm/u-boot-meson/blob/f1ee03e3f7547d03e1478cc1fc967a...

On Sun 03 Oct 2021 at 21:17, Martin Blumenstingl martin.blumenstingl@googlemail.com wrote:
Hi Jerome,
first of all: thanks for taking the time to go through all of this!
On Sun, Oct 3, 2021 at 6:34 PM Jerome Brunet jbrunet@baylibre.com wrote:
On Sun 03 Oct 2021 at 01:43, Martin Blumenstingl martin.blumenstingl@googlemail.com wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Ok, I'll clarify (again) about this issue.
This issue is on AIU only (not the AXG series), on the i2s encoder regardless of the output (HDMI, internal and external codec)
Thanks for repeating this. It was clear to me that only AIU is affected but I didn't know that it only affects I2S
This encoder support either 2ch or 8ch mode, nothing else. As long as only 2ch was supported, there was no problem. In order to switch between 2ch and 8ch mode. AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC shall be "poked" (check iu-fifo-i2s.c and aiu-encoder-i2c.c). Without this, the switch is not done.
What these do, how and when it should be done is unclear. I tried several combination. At the time I found something stable-ish but it was not perfect.
old 32-bit u-boot sources from the Endless Mini do have some documentation on AIU_I2S_SYNC [0]: // 8'b0_000_1_1_10 // A write to this register will cause the interface to repeat the current // sample. Can be used to regain synchronization. // A read from this register indicates that the next sample to be sent // out of the interface should go into the _left_ channel of the dac.
There's also a note about AIU_I2S_MISC stating: // Bit 4 if true, force each audio data to left or right according to the bit attached with the audio data // This bit should be used with Register AIU_i2s_sync(0x511) together
To be honest: to me this is not helpful since I don't understand how/why the left channel is of importance.
Same here, I already had this description and it is not really that helpful.
At the time, It was completely new driver. Even if was not rock solid, it was still progress and I opted to upstream it with an imperfect 8ch support so people could help debug it. This was mentioned in the original submission.
The other solution is to restrict to 2ch mode and remove AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC pokes. There will be no noise anymore.
I think Christian (Hewitt) agrees on this point as he mentioned that your earlier versions of the AIU code (before it got upstream) were not affected by the "machine gun noise" issue. Does the documentation from above give you any new ideas (assuming that it's correct since it's the best we have)? Should I try playing with AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC to see if I can make a difference?
Nothing new here. I suspect that the encoder restart out of sync with the FIFO, picking mis-aligned samples but I have not confirmed that yet.
[...]
Here you describe a DAI link (think of it as wires) between the SPDIF encoder (output) and AIU_HDMI input PCM. This is not what the HW is and it is not possible.
Let's start from the HDMI controller. The designware (on amlogic SoC) has 2 interface for audio input.
- PCM/I2S: a classic interface 2 clocks and N data line
- SPDIF: The Sony Philips 1 wire interface
The Transwitch HDMI TX controller supports these two inputs so even though the IP is different the basic functionality (which we'll discuss below) is the same.
Whatever comes up on 1) has to be some sort of i2s signal. So SPDIF won't fly there.
I agree with this
AIU_HDMI output is Hardwired to 1). It is just just a digital mux, implemented as an ASoC codec which allows to seleted one of 2 audio sources: A) the i2s output implemented as part of the AIU B) the PCM output, part the AUDIN (yes, an output in AUDIN) block. This is not implemented ATM.
This is some interesting information, I thought that PCM was used because PCM audio can be transmitted over SPDIF.
For A) my understanding is different though:
- for AIU_HDMI_CLK_DATA_CTRL[5:4] (HDMI_DATA_SEL) your description
matches my understanding. For me it makes sense that SPDIF data cannot be selected with this register since it's a one-wire protocol (and doesn't have separate data/clock lines). Value 0x2 selects the I2S data interface
- for AIU_HDMI_CLK_DATA_CTRL[1:0] (HDMI_DATA_CLK_SEL) however I have a
different understanding: 0x0 disables the clock signal to the HDMI TX controller, 0x1 selects the PCM clock (which now I have learned is related to the AUDIN block) and 0x2 selects the "AIU clock" (see below)
- my understanding is that "AIU clock" comes from AIU_CLK_CTRL_MORE[6]
(HDMITX_SEL_AOCLKX2) where 0x0 selects "cts_i958 as AIU clk to hdmi_tx_audio_master_clk" (SPDIF clock) and 0x1 selects "cts_aoclkx2_int as AIU clk to hdmi_tx_audio_master_clk" (I2S clock)
Not quite sure it works that way. Each FIFO (i2s and spdif) is mainly target at the related encoder BUT there is way to feed to both encoder from a single FIFO. In such case, the proper must selected for the encoder and the downstream element to keep things in sync
This at least with i2s FIFO feeding both the i2s and spdif encoders. I suspect the same is possible with the spdif FIFO. Maybe the bit is needed to also switch HDMI part to the spdif clock in this case.
This bit could also be a remain of an older design, not really connected to anything meaningful. It would not be the first time.
The AIU looks like an IP that has evolved a lot over the years, not always in a coordinated fashion. Some scenario are well supported and easy, others seem to require a magic spell.
Last (but not least), in AML vendor kernel, the only time this bit poked is around 8ch support (1 for 8ch, 0 otherwise) ... I have no idea why.
So to me this means that there's three different muxes:
- data mux to choose between 0x0 (all zeros), 0x1 (PCM) and 0x2 (I2S)
- clock mux to choose between 0x0 (disabled), 0x1 (PCM) and 0x2
(hdmi_tx_audio_master_clk)
- hdmi_tx_audio_master_clk clock mux to choose between 0x0 (cts_i958)
and 0x1 (cts_aoclkx2_int)
Based on that I think that it's not possible to have AIU output the I2S and SPDIF signals at the same time to the HDMI TX controller and then letting the HDMI TX controller choose which one to use.
i2s and spdif can be 2 independent paths (with different clock sources). I have already made them work concurrently. I believe (but have no proof) that the same should be possible with the HDMI.
Until the hdmi controller has support for both inputs, we don't need to worry about it.
Based on whichever signal (I2S or SPDIF) we want to use for HDMI we need to configure AIU accordingly (data and clock).
TBH, I'm not really sure what this bit does. From the description, it seems it allows to select an HDMI clock (not idea which one actually) for either the i2s or the spdif path.
Nothing says it is related to the HDMI_CTRL (codec), maybe it is not. Maybe (MAYBE) it defines what will become "the AIU clk" in AIU_HDMI_CLK_DATA_CTRL[1:0]. Until we can feed the i2s encoder from the spdif FIFO, I'm not sure we need to play with it.
[...]
It is not meant to. The dai_link and the endpoint are i2s. Your HDMI controller should have 2 inputs and should have a way to select one or the other. The format at each of the (internal) input does not change
ah, that makes sense. Let's say AIU has some internal muxing for the HDMI output then AIU would have two outputs as well (let's call them HDMI_OUT_I2S and HDMI_OUT_SPDIF).
I don't think there is another output the HDMI_CTRL mux block. If SPDIF to HDMITX is supported, I suspect the output of the spdif encoder is hardwired to the spdif input of the HDMI controller and it is up to the HDMI controller to take it or not.
That being said, I don't see any hard evidence that AML used SPDIF to HDMI in their tree, so maybe it does not work at all.
Then I'd wire up each of these to their corresponding inputs on the HDMI TX controller.
Best regards, Martin

Hi Jerome,
On Mon, Oct 4, 2021 at 11:02 AM Jerome Brunet jbrunet@baylibre.com wrote: [...]
old 32-bit u-boot sources from the Endless Mini do have some documentation on AIU_I2S_SYNC [0]: // 8'b0_000_1_1_10 // A write to this register will cause the interface to repeat the current // sample. Can be used to regain synchronization. // A read from this register indicates that the next sample to be sent // out of the interface should go into the _left_ channel of the dac.
There's also a note about AIU_I2S_MISC stating: // Bit 4 if true, force each audio data to left or right according to the bit attached with the audio data // This bit should be used with Register AIU_i2s_sync(0x511) together
To be honest: to me this is not helpful since I don't understand how/why the left channel is of importance.
Same here, I already had this description and it is not really that helpful.
OK, so I guess this leaves experimenting (which requires luck)... :-(
[...]
This bit could also be a remain of an older design, not really connected to anything meaningful. It would not be the first time.
The AIU looks like an IP that has evolved a lot over the years, not always in a coordinated fashion. Some scenario are well supported and easy, others seem to require a magic spell.
Last (but not least), in AML vendor kernel, the only time this bit poked is around 8ch support (1 for 8ch, 0 otherwise) ... I have no idea why.
The 32-bit SoCs use SPDIF to feed 2-channel audio to the HDMI TX controller and I2S to feed 8-channel audio to the HDMI TX controller. It seems that Amlogic stopped this for (at least some) 64-bit SoCs.
My testing results indicate that AIU_CLK_CTRL_MORE[6] is still relevant. I can do another round of testing with various combinations of AIU_CLK_CTRL_MORE[6] and AIU_HDMI_CLK_DATA_CTRL register values. If you want me to test any specific combinations then please let me know.
So to me this means that there's three different muxes:
- data mux to choose between 0x0 (all zeros), 0x1 (PCM) and 0x2 (I2S)
- clock mux to choose between 0x0 (disabled), 0x1 (PCM) and 0x2
(hdmi_tx_audio_master_clk)
- hdmi_tx_audio_master_clk clock mux to choose between 0x0 (cts_i958)
and 0x1 (cts_aoclkx2_int)
Based on that I think that it's not possible to have AIU output the I2S and SPDIF signals at the same time to the HDMI TX controller and then letting the HDMI TX controller choose which one to use.
i2s and spdif can be 2 independent paths (with different clock sources). I have already made them work concurrently. I believe (but have no proof) that the same should be possible with the HDMI.
Until the hdmi controller has support for both inputs, we don't need to worry about it.
My work-in-progress HDMI TX controller driver for the 32-bit SoCs [0] does support both (I2S and SPDIF) inputs. That's how I am able to test all of this. I wasn't aware of the fact that it's known that the "machine gun noise" (MGN) issue is related to I2S only. Since I couldn't find a workaround or fix for the MGN issue I wanted to narrow it down by adding SPDIF support to the HDMI TX path.
Based on whichever signal (I2S or SPDIF) we want to use for HDMI we need to configure AIU accordingly (data and clock).
TBH, I'm not really sure what this bit does. From the description, it seems it allows to select an HDMI clock (not idea which one actually) for either the i2s or the spdif path.
Nothing says it is related to the HDMI_CTRL (codec), maybe it is not. Maybe (MAYBE) it defines what will become "the AIU clk" in AIU_HDMI_CLK_DATA_CTRL[1:0].
This is what I am thinking
Until we can feed the i2s encoder from the spdif FIFO, I'm not sure we need to play with it.
I think it's also relevant when we feed HDMI TX from the SPDIF (FIFO + encoder) which is what I am attempting here.
[...]
It is not meant to. The dai_link and the endpoint are i2s. Your HDMI controller should have 2 inputs and should have a way to select one or the other. The format at each of the (internal) input does not change
ah, that makes sense. Let's say AIU has some internal muxing for the HDMI output then AIU would have two outputs as well (let's call them HDMI_OUT_I2S and HDMI_OUT_SPDIF).
I don't think there is another output the HDMI_CTRL mux block. If SPDIF to HDMITX is supported, I suspect the output of the spdif encoder is hardwired to the spdif input of the HDMI controller and it is up to the HDMI controller to take it or not.
I think you are correct with this. My theory is that AIU_CLK_CTRL_MORE[6] and AIU_HDMI_CLK_DATA_CTRL will enable one of the outputs (I2S or SPIDF) from AIU to the HDMI TX controller, meaning that only one signal can be active at a time. The HDMI TX controller then needs to "select" the correct input based on the selected output from AIU.
That being said, I don't see any hard evidence that AML used SPDIF to HDMI in their tree, so maybe it does not work at all.
For the 32-bit SoCs the easiest to understand code-snippet is the HDMI TX audio input configuration [1] Which basically translates to: if (more_than_two_channel_audio) { enable_audio_i2s(); } else { enable_audio_spdif(); }
The code in the AIU driver just assumes that whatever it's configuring is what the HDMI TX driver expects - without a clear link between these two.
Best regards, Martin
[0] https://github.com/xdarklight/linux/blob/meson-mx-integration-5.15-20211003/... [1] https://github.com/endlessm/linux-meson/blob/d6e13c220931110fe676ede6da69fc6...

Hi Jerome,
On Mon, Oct 4, 2021 at 11:17 PM Martin Blumenstingl martin.blumenstingl@googlemail.com wrote: [...]
This bit could also be a remain of an older design, not really connected to anything meaningful. It would not be the first time.
The AIU looks like an IP that has evolved a lot over the years, not always in a coordinated fashion. Some scenario are well supported and easy, others seem to require a magic spell.
Last (but not least), in AML vendor kernel, the only time this bit poked is around 8ch support (1 for 8ch, 0 otherwise) ... I have no idea why.
The 32-bit SoCs use SPDIF to feed 2-channel audio to the HDMI TX controller and I2S to feed 8-channel audio to the HDMI TX controller. It seems that Amlogic stopped this for (at least some) 64-bit SoCs.
My testing results indicate that AIU_CLK_CTRL_MORE[6] is still relevant. I can do another round of testing with various combinations of AIU_CLK_CTRL_MORE[6] and AIU_HDMI_CLK_DATA_CTRL register values. If you want me to test any specific combinations then please let me know.
I have tested various combinations, see the attached result file (which can be viewed with "column -t /path/to/results.txt"). The short summary is that... ...I2S output requires: AIU_HDMI_CLK_DATA_CTRL[1:0] = 0x2 AIU_HDMI_CLK_DATA_CTRL[5:4] = 0x2 AIU_CLK_CTRL_MORE[6] = 0x1
...SPDIF output requires: AIU_HDMI_CLK_DATA_CTRL[1:0] = 0x2 AIU_HDMI_CLK_DATA_CTRL[5:4] = (any) AIU_CLK_CTRL_MORE[6] = 0x1
My test consisted of running speaker-test -c2 and playing an mp3 with ffplay on an Odroid-C1.
In other words: this confirms what we have suspected before. What is your suggestion on how to model these muxes in the driver?
In the meantime I finally understood what #sound-dai-cells = <1>; does thanks to your previous hints. With that I can wire up the I2S and SPDIF inputs to the HDMI TX controller's "HDMI codec". Many thanks again for this hint!
Best regards, Martin

On Sun, Oct 03, 2021 at 09:17:39PM +0200, Martin Blumenstingl wrote:
old 32-bit u-boot sources from the Endless Mini do have some documentation on AIU_I2S_SYNC [0]: // 8'b0_000_1_1_10 // A write to this register will cause the interface to repeat the current // sample. Can be used to regain synchronization. // A read from this register indicates that the next sample to be sent // out of the interface should go into the _left_ channel of the dac.
There's also a note about AIU_I2S_MISC stating: // Bit 4 if true, force each audio data to left or right according to the bit attached with the audio data // This bit should be used with Register AIU_i2s_sync(0x511) together
To be honest: to me this is not helpful since I don't understand how/why the left channel is of importance.
The left channel is important because for most (I think all?) audio formats the first channel sent after each frame sync is the left channel, if you're trying to resync it's useful to know when a left frame is going to be sent.
At the time, It was completely new driver. Even if was not rock solid, it was still progress and I opted to upstream it with an imperfect 8ch support so people could help debug it. This was mentioned in the original submission.
The other solution is to restrict to 2ch mode and remove AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC pokes. There will be no noise anymore.
I think Christian (Hewitt) agrees on this point as he mentioned that your earlier versions of the AIU code (before it got upstream) were not affected by the "machine gun noise" issue. Does the documentation from above give you any new ideas (assuming that it's correct since it's the best we have)? Should I try playing with AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC to see if I can make a difference?
[...]
Here you describe a DAI link (think of it as wires) between the SPDIF encoder (output) and AIU_HDMI input PCM. This is not what the HW is and it is not possible.
Let's start from the HDMI controller. The designware (on amlogic SoC) has 2 interface for audio input.
- PCM/I2S: a classic interface 2 clocks and N data line
- SPDIF: The Sony Philips 1 wire interface
The Transwitch HDMI TX controller supports these two inputs so even though the IP is different the basic functionality (which we'll discuss below) is the same.
Whatever comes up on 1) has to be some sort of i2s signal. So SPDIF won't fly there.
I agree with this
AIU_HDMI output is Hardwired to 1). It is just just a digital mux, implemented as an ASoC codec which allows to seleted one of 2 audio sources: A) the i2s output implemented as part of the AIU B) the PCM output, part the AUDIN (yes, an output in AUDIN) block. This is not implemented ATM.
This is some interesting information, I thought that PCM was used because PCM audio can be transmitted over SPDIF.
For A) my understanding is different though:
- for AIU_HDMI_CLK_DATA_CTRL[5:4] (HDMI_DATA_SEL) your description
matches my understanding. For me it makes sense that SPDIF data cannot be selected with this register since it's a one-wire protocol (and doesn't have separate data/clock lines). Value 0x2 selects the I2S data interface
- for AIU_HDMI_CLK_DATA_CTRL[1:0] (HDMI_DATA_CLK_SEL) however I have a
different understanding: 0x0 disables the clock signal to the HDMI TX controller, 0x1 selects the PCM clock (which now I have learned is related to the AUDIN block) and 0x2 selects the "AIU clock" (see below)
- my understanding is that "AIU clock" comes from AIU_CLK_CTRL_MORE[6]
(HDMITX_SEL_AOCLKX2) where 0x0 selects "cts_i958 as AIU clk to hdmi_tx_audio_master_clk" (SPDIF clock) and 0x1 selects "cts_aoclkx2_int as AIU clk to hdmi_tx_audio_master_clk" (I2S clock)
So to me this means that there's three different muxes:
- data mux to choose between 0x0 (all zeros), 0x1 (PCM) and 0x2 (I2S)
- clock mux to choose between 0x0 (disabled), 0x1 (PCM) and 0x2
(hdmi_tx_audio_master_clk)
- hdmi_tx_audio_master_clk clock mux to choose between 0x0 (cts_i958)
and 0x1 (cts_aoclkx2_int)
Based on that I think that it's not possible to have AIU output the I2S and SPDIF signals at the same time to the HDMI TX controller and then letting the HDMI TX controller choose which one to use. Based on whichever signal (I2S or SPDIF) we want to use for HDMI we need to configure AIU accordingly (data and clock).
[...]
It is not meant to. The dai_link and the endpoint are i2s. Your HDMI controller should have 2 inputs and should have a way to select one or the other. The format at each of the (internal) input does not change
ah, that makes sense. Let's say AIU has some internal muxing for the HDMI output then AIU would have two outputs as well (let's call them HDMI_OUT_I2S and HDMI_OUT_SPDIF). Then I'd wire up each of these to their corresponding inputs on the HDMI TX controller.
Best regards, Martin

On Sun, Oct 03, 2021 at 05:57:34PM +0200, Jerome Brunet wrote:
On Sun 03 Oct 2021 at 01:43, Martin Blumenstingl martin.blumenstingl@googlemail.com wrote:
Hello Jerome et al.,
on Amlogic Meson SoCs which use the AIU audio controller we have the so-called "machine gun noise" (MGN) issue, reproducible for example in Kodi. So far nobody was able to identify the cause of this issue. My idea was to at least narrow down the issue so we can categorize it. For that I wanted to get the SPDIF output from AIU to the HDMI controller working.
Ok, I'll clarify (again) about this issue.
This issue is on AIU only (not the AXG series), on the i2s encoder regardless of the output (HDMI, internal and external codec)
This encoder support either 2ch or 8ch mode, nothing else. As long as only 2ch was supported, there was no problem. In order to switch between 2ch and 8ch mode. AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC shall be "poked" (check iu-fifo-i2s.c and aiu-encoder-i2c.c). Without this, the switch is not done.
What these do, how and when it should be done is unclear. I tried several combination. At the time I found something stable-ish but it was not perfect.
At the time, It was completely new driver. Even if was not rock solid, it was still progress and I opted to upstream it with an imperfect 8ch support so people could help debug it. This was mentioned in the original submission.
The other solution is to restrict to 2ch mode and remove AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC pokes. There will be no noise anymore.
Hi, Jerome,
Thanks for the extensive clarification. I have compiled 5.15-rc3 commenting out the pokes for 8ch as you have suggested, both for AIU_RST_SOFT_I2S_FAST and AIU_I2S_SYNC in both aiu-fifo-i2s.c and aiu-encoder-i2c.c.
It works, the bug is gone just like you said it would be.
My suggestion is that, for the time being, until someone can solve this properly, you restrict enablement of 8ch configuration under an EXPERIMENTAL kernel option, with a big fat warning in the help description, saying it will break 2ch.
Last but no least, thanks for helping Martin out.
Thank you, Geraldo Nascimento
participants (5)
-
Christian Hewitt
-
Geraldo Nascimento
-
Jerome Brunet
-
Mark Brown
-
Martin Blumenstingl