Configure Tegra ASoC Driver for custom hardware with audio CODEC(wm8904)

Platform: Jetson AGX Xavier, **
Linux version: 20.04, R35.2,
** Audio codec: WM8904,

I2C Address:0x1a

➜  ~ sudo i2cdetect -y -r -a 7
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- 1a -- -- -- -- -- 

The addresses corresponding to I2C are as follows

➜  ~ sudo i2cdetect -l        

i2c-3   i2c             3190000.i2c                             I2C adapter
i2c-1   i2c             c240000.i2c                             I2C adapter
i2c-101 i2c             15210000.display                        I2C adapter
i2c-8   i2c             31e0000.i2c                             I2C adapter
i2c-6   i2c             31c0000.i2c                             I2C adapter
i2c-4   i2c             Tegra BPMP I2C adapter                  I2C adapter
i2c-2   i2c             3180000.i2c                             I2C adapter
i2c-0   i2c             3160000.i2c                             I2C adapter
i2c-102 i2c             15220000.display                        I2C adapter
i2c-7   i2c             c250000.i2c                             I2C adapter
i2c-5   i2c             31b0000.i2c                             I2C adapter

Below is the required kernel device tree information

	i2c@c250000 {
		//add
		wm8904_codec: wm8904@1a {
			compatible = "wlf,wm8904";
			status ="okay";
			reg = <0x1a>;
			// clocks = <&wm8904_mclk>;
			// clocks = <&bpmp TEGRA194_CLK_AUD_MCLK>;
			clocks = <&bpmp_clks TEGRA194_CLK_AUD_MCLK>;
			// clocks = <&pck0>;
			clock-names = "mclk";

			port {
				wm8904_ep: endpoint {
					remote-endpoint = <&i2s1_dap_ep>;
					mclk-fs = <256>;
					link-name = "wm8904-playback";
				};
			};
		};
	};

	/* Default for all I2S is long fsync width(31) */
	aconnect@2a41000 {
		compatible = "nvidia,tegra210-aconnect";
    	status = "okay";
		ahub {
			/* I2S4 in Short frame sync for BT SCO */
			i2s@2901300 {
				bclk-ratio = <4>;
				status = "okay";
			};
		};

	};

	tegra_acsl_audio: acsl_audio {
		status = "okay";
	};

	hda@3510000 {
		status = "okay";

		nvidia,model = "NVIDIA Jetson AGX Xavier HDA";
	};

	tegra_sound: sound {
		status = "okay";
		compatible = "nvidia,tegra186-ape";
		nvidia-audio-card,name = "NVIDIA Jetson AGX Xavier APE";
		nvidia,num-codec-link = <1>;
		nvidia,num-clk = <6>;
		nvidia,clk-rates = < 270950400  /* PLLA_x11025_RATE */
								11289600   /* AUD_MCLK_x11025_RATE */
								45158400   /* PLLA_OUT0_x11025_RATE */
								45158400   /* AHUB_x11025_RATE */
								245760000  /* PLLA_x8000_RATE */
								12288000   /* AUD_MCLK_x8000_RATE */
								49152000   /* PLLA_OUT0_x8000_RATE */
								49152000 >;/* AHUB_x8000_RATE */
		nvidia,xbar = <&tegra_axbar>;
		clocks = <&bpmp_clks TEGRA194_CLK_PLLA>,
			 <&bpmp_clks TEGRA194_CLK_PLLA_OUT0>,
			 <&bpmp_clks TEGRA194_CLK_AUD_MCLK>;
		clock-names = "pll_a", "pll_a_out0", "extern1";
		assigned-clocks = <&bpmp_clks TEGRA194_CLK_AUD_MCLK>;
		assigned-clock-parents = <&bpmp_clks TEGRA194_CLK_PLLA_OUT0>;

		nvidia-audio-card,widgets =
		    "Headphone",    "WM Headphone Jack",
			"Microphone",   "WM Mic",
			"Line",         "WM Line In Jack",
			"Line",         "WM Line In Jack",
			"Microphone",	"WM MICBIAS";
		//add
		nvidia-audio-card,routing =
		    "WM Headphone", "WM HP_L",
    		"WM Headphone", "WM HP_R"
			"WM Headphone Jack", "WM HPOUTL",		
			"WM Headphone Jack", "WM HPOUTR",			
			"WM IN2L", "WM Line In Jack",			
			"WM IN2R", "WM Line In Jack",		
			"WM Mic", "WM MICBIAS",			
			"WM IN1L", "WM Mic",
			"WM Headphone", "WM HPOUTL",
    		"WM Headphone", "WM HPOUTR";

		nvidia,dai-link-1 {
                    link-name = "wm8904-playback";
                    cpu-dai = <&tegra_i2s1>;
                    codec-dai = <&wm8904_codec>;
                    cpu-dai-name = "I2S1";
                    codec-dai-name = "wm8904-hifi";
                    format = "i2s";
                    bitclock-slave;
                    frame-slave;
                    bitclock-noninversion;
                    frame-noninversion;
                    bit-format = "s16_le";
                    bclk_ratio = <0>;
                    srate = <48000>;
                    num-channel = <2>;
                    ignore_suspend;
                    name-prefix = "WM";
                    status = "okay";
            };
		nvidia-audio-card,mclk-fs = <256>;

	};

	tegra_sound_graph: sound_graph {
		compatible = "nvidia,tegra186-audio-graph-card";

		/*
		 * Tegra audio graph card is based on uptream generic audio
		 * graph sound card. In future there is plan to use this
		 * as default sound card.
		 */
		status = "disabled";

		dais = /* ADMAIF (FE) Ports */
		       <&admaif1_port>, <&admaif2_port>, <&admaif3_port>,
		       <&admaif4_port>, <&admaif5_port>, <&admaif6_port>,
		       <&admaif7_port>, <&admaif8_port>, <&admaif9_port>,
		       <&admaif10_port>, <&admaif11_port>, <&admaif12_port>,
		       <&admaif13_port>, <&admaif14_port>, <&admaif15_port>,
		       <&admaif16_port>, <&admaif17_port>, <&admaif18_port>,
		       <&admaif19_port>, <&admaif20_port>,

		       /* ADSP (FE) Ports */
		       <&adsp_pcm1_port>, <&adsp_pcm2_port>,
		       <&adsp_compr1_port>, <&adsp_compr2_port>,

		       /* XBAR I/O ports */
		       <&xbar_i2s1_port>, <&xbar_i2s2_port>, <&xbar_i2s3_port>,
		       <&xbar_i2s4_port>, <&xbar_i2s5_port>, <&xbar_i2s6_port>,

		       <&xbar_dmic1_port>, <&xbar_dmic2_port>,
		       <&xbar_dmic3_port>, <&xbar_dmic4_port>,

		       <&xbar_dspk1_port>, <&xbar_dspk2_port>,

		       /* XBAR HW accelerator ports */
		       <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
		       <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,

		       <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,

		       <&xbar_afc1_in_port>, <&xbar_afc2_in_port>,
		       <&xbar_afc3_in_port>, <&xbar_afc4_in_port>,
		       <&xbar_afc5_in_port>, <&xbar_afc6_in_port>,

		       <&xbar_asrc_in1_port>, <&xbar_asrc_in2_port>,
		       <&xbar_asrc_in3_port>, <&xbar_asrc_in4_port>,
		       <&xbar_asrc_in5_port>, <&xbar_asrc_in6_port>,
		       <&xbar_asrc_in7_port>, <&xbar_arad_port>,

		       <&xbar_mixer_in1_port>, <&xbar_mixer_in2_port>,
		       <&xbar_mixer_in3_port>, <&xbar_mixer_in4_port>,
		       <&xbar_mixer_in5_port>, <&xbar_mixer_in6_port>,
		       <&xbar_mixer_in7_port>, <&xbar_mixer_in8_port>,
		       <&xbar_mixer_in9_port>, <&xbar_mixer_in10_port>,

		       <&xbar_ope1_in_port>,

		       <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
		       <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
		       <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
		       <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
		       <&xbar_amx3_in1_port>, <&xbar_amx3_in2_port>,
		       <&xbar_amx3_in3_port>, <&xbar_amx3_in4_port>,
		       <&xbar_amx4_in1_port>, <&xbar_amx4_in2_port>,
		       <&xbar_amx4_in3_port>, <&xbar_amx4_in4_port>,

		       <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
		       <&xbar_adx3_in_port>, <&xbar_adx4_in_port>,

		       /* BE I/O Ports */
		       <&i2s1_port>, <&i2s2_port>, <&i2s3_port>,
		       <&i2s4_port>, <&i2s5_port>, <&i2s6_port>,

		       <&dmic1_port>, <&dmic2_port>, <&dmic3_port>,
		       <&dmic4_port>,

		       <&dspk1_port>, <&dspk2_port>,

		       /* BE HW accelerator ports */
		       <&sfc1_out_port>, <&sfc2_out_port>,
		       <&sfc3_out_port>, <&sfc4_out_port>,

		       <&mvc1_out_port>, <&mvc2_out_port>,

		       <&afc1_out_port>, <&afc2_out_port>,
		       <&afc3_out_port>, <&afc4_out_port>,
		       <&afc5_out_port>, <&afc6_out_port>,

		       <&asrc_out1_port>, <&asrc_out2_port>,
		       <&asrc_out3_port>, <&asrc_out4_port>,
		       <&asrc_out5_port>, <&asrc_out6_port>,

		       <&mixer_out1_port>, <&mixer_out2_port>,
		       <&mixer_out3_port>, <&mixer_out4_port>,
		       <&mixer_out5_port>,

		       <&ope1_out_port>,

		       <&amx1_out_port>, <&amx2_out_port>,
		       <&amx3_out_port>, <&amx4_out_port>,

		       <&adx1_out1_port>, <&adx1_out2_port>,
		       <&adx1_out3_port>, <&adx1_out4_port>,
		       <&adx2_out1_port>, <&adx2_out2_port>,
		       <&adx2_out3_port>, <&adx2_out4_port>,
		       <&adx3_out1_port>, <&adx3_out2_port>,
		       <&adx3_out3_port>, <&adx3_out4_port>,
		       <&adx4_out1_port>, <&adx4_out2_port>,
		       <&adx4_out3_port>, <&adx4_out4_port>,

		       /* ADSP related ports */
		       <&adsp_admaif1_port>, <&adsp_admaif2_port>,
		       <&adsp_admaif3_port>, <&adsp_admaif4_port>,
		       <&adsp_admaif5_port>, <&adsp_admaif6_port>,
		       <&adsp_admaif7_port>, <&adsp_admaif8_port>,
		       <&adsp_admaif9_port>, <&adsp_admaif10_port>,
		       <&adsp_admaif11_port>, <&adsp_admaif12_port>,
		       <&adsp_admaif13_port>, <&adsp_admaif14_port>,
		       <&adsp_admaif15_port>, <&adsp_admaif16_port>,
		       <&adsp_admaif17_port>, <&adsp_admaif18_port>,
		       <&adsp_admaif19_port>, <&adsp_admaif20_port>,

		       <&admaif1_codec_port>, <&admaif2_codec_port>,
		       <&admaif3_codec_port>, <&admaif4_codec_port>,
		       <&admaif5_codec_port>, <&admaif6_codec_port>,
		       <&admaif7_codec_port>, <&admaif8_codec_port>,
		       <&admaif9_codec_port>, <&admaif10_codec_port>,
		       <&admaif11_codec_port>, <&admaif12_codec_port>,
		       <&admaif13_codec_port>, <&admaif14_codec_port>,
		       <&admaif15_codec_port>, <&admaif16_codec_port>,
		       <&admaif17_codec_port>, <&admaif18_codec_port>,
		       <&admaif19_codec_port>, <&admaif20_codec_port>;

		label = "NVIDIA Jetson AGX Xavier APE";

		clocks = <&bpmp_clks TEGRA194_CLK_PLLA>,
			 <&bpmp_clks TEGRA194_CLK_PLLA_OUT0>;
		clock-names = "pll_a", "plla_out0";
		assigned-clocks = <&bpmp_clks TEGRA194_CLK_AUD_MCLK>;
		assigned-clock-parents = <&bpmp_clks TEGRA194_CLK_PLLA_OUT0>;

		widgets = 		    "Headphone",    "WM Headphone Jack",
			"Microphone",   "WM Mic",
			"Line",         "WM Line In Jack",
			"Line",         "WM Line In Jack",
			"Microphone",	"WM MICBIAS";

		routing =			"WM Headphone Jack", "WM HPOUTL",		
			"WM Headphone Jack", "WM HPOUTR",			
			"WM IN2L", "WM Line In Jack",			
			"WM IN2R", "WM Line In Jack",		
			"WM Mic", "WM MICBIAS",			
			"WM IN1L", "WM Mic";

		/*
		 * For codec2codec based DAI link design this is required.
		 * For DPCM based design, this is optional and instead
		 * it will be picked from codec port node.
		 */
		mclk-fs = <256>;
	};
};

/*
 * Default config for all I2S dai links are
 * format = "i2s", bitclock-slave, frame-slave,
 * bitclock-noninversion, frame-noninversion,
 * Any change from default needs override on
 * platform specific files.
 */

/* Override with Codec entries */
&i2s1_to_codec {
	link-name = "wm8904-playback";
	// link-name = "rt5658-playback";
	bitclock-master;
    frame-master;
	codec {
		sound-dai = <&wm8904_codec 0>;
		prefix = "WM";
	};
};

hdr40_snd_link_i2s: &i2s2_to_codec { };

/* Override with BT SCO entries */
&i2s4_to_codec {
	format = "dsp_a";
	bitclock-inversion;
};

/* Audio graph related bindings */
&i2s1_dap_ep {
	remote-endpoint = <&wm8904_ep>;
};

&i2s4_dap_ep {
	dai-format = "dsp_a";
	bitclock-inversion;
};

hdr40_snd_i2s_dap_ep: &i2s2_dap_ep { };

The kernel configuration kconfig was modified to

config SND_SOC_WM8904
	bool "Wolfson Microelectronics WM8904 CODEC"
	default y
	depends on I2C

the original

config SND_SOC_WM8904
	tristate "Wolfson Microelectronics WM8904 CODEC"
	depends on I2C

After I compiled and updated to the board, I did not find the NVIDIA Jetson AGX Xavier APE

corresponding configuration

	tegra_sound: sound {
		status = "okay";
		compatible = "nvidia,tegra186-ape";
		nvidia-audio-card,name = "NVIDIA Jetson AGX Xavier APE";

There is no NVIDIA Jetson AGX Xavier APE corresponding to the sound card, which step is wrong? This question has been bothering me for a week now, hope for help

There are new developments, the wm8904 driver can be loaded, but the DMESG shows up

➜  ~ sudo dmesg | grep 8904
[sudo] password for nvidia: 
[    7.607438] wm8904 7-001a: supply DCVDD not found, using dummy regulator
[    7.616702] wm8904 7-001a: supply DBVDD not found, using dummy regulator
[    7.629127] wm8904 7-001a: supply AVDD not found, using dummy regulator
[    7.641637] wm8904 7-001a: supply CPVDD not found, using dummy regulator
[    7.654450] wm8904 7-001a: supply MICVDD not found, using dummy regulator
[    7.669821] wm8904 7-001a: revision A
[    7.689040] tegra-i2c 31e0000.i2c: Adding to iommu group 2

Corresponding to the definition in the driver WM8904.c:

static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {

"DCVDD",

"DBVDD",

"AVDD",

"CPVDD",

"MICVDD",

};
  1. Try with updating the routing and widget properties like mentioned here:
    How do I add the WM8904 audio driver in the jetson Device Tree? - #54 by DreamLan
  2. If point #1 doesn’t help, please modify the below sound-dai entry:
    As mentioned here How do I add the WM8904 audio driver in the jetson Device Tree? - #36 by Sheetal.G

If still issue persists, please share the dmesg logs.

Hi,

It seems similar query raised by you. How do I add the WM8904 audio driver in the jetson Device Tree? - Jetson & Embedded Systems / Jetson AGX Xavier - NVIDIA Developer Forums.
Could you please either close or move it to the above query discussion.

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