Jetson AGX uses the WM8904 codec

I want to implement recording and speaker functions with WM8904. I refer to the documentationhttps://docs.nvidia.com/jetson/archives/r35.1/DeveloperGuide/text/SD/Communications/AudioSetupAndDevelopment.html#device-tree-configuration-for-a-custom-audio-card

The clock and drivers are already configured, but DMESG also shows some problems

➜  ~ sudo dmesg|grep i2s   
[   34.532388] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for capture
[   34.532806] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 TX event failed: -110
[   34.792675] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[   34.792937] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110
[   35.054850] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[   35.055074] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110
[  113.324039] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for capture
[  113.324246] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 TX event failed: -110
[  113.560518] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[  113.560779] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110
[  113.636378] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[  113.636575] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110
[ 1764.007422] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[ 1764.007649] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110

What is the reason for this I2S1 error

failed to reset I2S for playback

Hi,
The above error occurs if tegra I2S is slave and not getting the clocks from codec.

Audio Setup and Development — Jetson Linux
Developer Guide 34.1 documentation (nvidia.com)

Please confirm the codec is connected to I2S1 interface?

@Sheetal.G ,Dear Sheetal.G,hi,I see https://docs.nvidia.com/jetson/archives/r35.1/DeveloperGuide/text/SD/Communications/AudioSetupAndDevelopment.html?highlight=audio#add-support-for-runtime-configuration-of-codec-parameters The corresponding instructions are related to the link you just sent, the activation of bit clock.So I’m adding the tegra_codecs_runtime_setup function as follows?

    rtd = get_pcm_runtime(card, "wm8904-playback");
	if (rtd) {
		err = set_pll_sysclk(card->dev, rtd, RT5659_PLL1_S_BCLK1,
				     RT5659_SCLK_S_PLL1, srate, channels);
		if (err < 0) {
			dev_err(card->dev, "failed to set pll clk\n");
			return err;
		}
	}

[ 14.870498] wm8904 7-001a: ASoC: error at snd_soc_component_update_bits on wm8904.7-001a: -16
[ 15.141817] wm8904 7-001a: ASoC: error at snd_soc_dai_hw_params on wm8904-hifi: -22
[ 15.142030] tegra-asoc: sound: ASoC: PRE_PMU: wm8904-playback-playback event failed: -22
[ 15.153961] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[ 15.154121] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110

Please share all the changes done along with dmesg logs.

dmesg.txt (82.6 KB)

OK, thank you very much.
tegra_codecs.c (8.7 KB)
tegra194-audio-p2822-0000.dtsi (9.9 KB)
wm8904.c (65.1 KB)

Add the following to the tegra_codecs.c file:

static int tegra_machine_wm8904_init(struct snd_soc_pcm_runtime *rtd)
{
	struct device *dev = rtd->card->dev;
	int err;
	// dev_info(dev, "set to wm8904 sysclk .\n");
	err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], WM8904_CLK_MCLK,
				     12288000, SND_SOC_CLOCK_IN);
	if (err) {
		dev_err(dev, " failed to set wm8904 sysclk!\n");
		return err;
	}

	return tegra_audio_dai_init(rtd);
}

int tegra_codecs_init(struct snd_soc_card *card)
{
	struct snd_soc_dai_link *dai_links = card->dai_link;
	int i;

	if (!dai_links || !card->num_links)
		return -EINVAL;

	for (i = 0; i < card->num_links; i++) {
		if (strstr(dai_links[i].name, "rt565x-playback") ||
		    strstr(dai_links[i].name, "rt5640-playback") ||
		    strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1") ||
		    strstr(dai_links[i].name, "rt5640-codec-sysclk-bclk1"))
			dai_links[i].init = tegra_machine_rt56xx_init;
		else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2"))
			dai_links[i].init = tegra_machine_fepi_init;
		else if (strstr(dai_links[i].name, "respeaker-4-mic-array"))
			dai_links[i].init = tegra_machine_respeaker_init;
		else if (strstr(dai_links[i].name, "wm8904-playback"))
			dai_links[i].init = tegra_machine_wm8904_init;
	}

	return 0;
}
  rtd = get_pcm_runtime(card, "wm8904-playback");
	if (rtd) {
		err = set_pll_sysclk(card->dev, rtd, RT5659_PLL1_S_BCLK1,
				     RT5659_SCLK_S_PLL1, srate, channels);
		if (err < 0) {
			dev_err(card->dev, "failed to set pll clk\n");
			return err;
		}
	}

The dmesg log error is not same as mentioned here.

I am observing error log like

[   17.316325] wm8904 7-001a: ASoC: error at snd_soc_component_update_bits on wm8904.7-001a: -16
[   18.263867] wm8904 7-001a: ASoC: error at snd_soc_dai_hw_params on wm8904-hifi: -22
[   18.264110] tegra-asoc: sound: ASoC: PRE_PMU: rt565x-playback-playback event failed: -22
[   18.276292] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[   18.276496] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110

Also, the logs are not matching with the query description.

Please provide details on what is changed between these 3 logs.

The difference is because I just put link-name = “wm8904-playback”; change to link-name = “rt565x-playback”;
dmesg.txt (86.0 KB)

As mentioned in the document, it is not a mandatory step to perform for all the codecs.
Please check codec datasheet to know if this change is required for wm8904.

You’re saying that the WM8904 codec doesn’t mean that bit clock

I am not saying it is not required for WM8904. You need to confirm from WM8904 datasheet whether this change is required or not.
Also, please confirm Tegra I2S is slave and codec is master in the setup?

Dear Sheetal.G,hello,WM8904 has one last error, the error is as follows

The WM8904 data sheet is described below,The error occurs with the register address c6h

The key codes in WM8904.c are as follows

	SOC_SINGLE_EXT("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0,
		       snd_soc_get_volsw, wm8904_adc_osr_put),
};
static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component =
		snd_soc_kcontrol_component(kcontrol);
	unsigned int val;
	int ret;

	ret = snd_soc_put_volsw(kcontrol, ucontrol);
	if (ret < 0)
		return ret;

	if (ucontrol->value.integer.value[0])
		val = 0;
	else
		val = WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5;

	snd_soc_component_update_bits(
		component, WM8904_ADC_TEST_0,
		WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5, val);
	// printk("wm8904 adc reg val is %d \n ",val);

	return ret;
}

How does this solve this problem? Thank you so much

Hi,
Sorry for the late response.

Please let me know who is master here, codec or tegra I2S?

You are still getting the below error or just error from wm8904 codec?

[   17.316325] wm8904 7-001a: ASoC: error at snd_soc_component_update_bits on wm8904.7-001a: -16
[   18.263867] wm8904 7-001a: ASoC: error at snd_soc_dai_hw_params on wm8904-hifi: -22
[   18.264110] tegra-asoc: sound: ASoC: PRE_PMU: rt565x-playback-playback event failed: -22
[   18.276292] tegra210-i2s 2901000.i2s: timeout: failed to reset I2S for playback
[   18.276496] tegra210-i2s 2901000.i2s: ASoC: PRE_PMU: I2S1 RX event failed: -110

Hello, the custom board mainly uses WM8904 as a speaker, this situation should Tegra i2S be the master.

Yes, the above error still appears, thanks for your help.

Could you please provide the info, which header you are using for I2S?
For example, If it is 40pin header, then you need to use I2S2 and perform required pinmux settings.
For reference, Audio Setup and Development — Jetson Linux
Developer Guide 34.1 documentation (nvidia.com)

On top of that,
Ideally if Tegra I2S is Master then above error won’t come as mentioned in comment #2. I will suggest either
check if codec is master and it is giving clock to Tegra I2S
or make codec as slave and Tegra I2S as Master.

Also please note above macros in set_pll_sysclk are related to RT5659, you need to replace them with WM8904 specific macros, if you want to add this.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.