Nano audio codec not detected

Hello,

We have the tlv320aic3007 audio codec on our custom carrier board connected to i2c0 and i2s0 lines on the nano. I’ve tried to update the device tree according to ASoC Driver guide but it doesn’t seem to find the device.

Here are they updates I’ve tried in tegra210-porg-p3448-common.dtsi:

ahub {
	i2s@702d1000 {
		status = "okay";
	};
        ....
}

tegra_sound: sound {
	status = "okay";
	compatible = "nvidia,tegra-audio-t210ref-mobile-rt565x";
	nvidia,model = "tegra-snd-t186ref-mobile-rt565x";
		clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
		 <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
		 <&tegra_car TEGRA210_CLK_D_AUDIO>,
		 <&tegra_car TEGRA210_CLK_EXTERN1>;
	clock-names = "pll_a", "pll_a_out0", "ahub", "extern1";
	assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>,
			  <&tegra_car TEGRA210_CLK_EXTERN1>;
	assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
				 <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
	nvidia,num-codec-link = <1>;
		nvidia,audio-routing =
		"x Headphone",	"x HPLOUT",
		"x MIC3L",		"x Mic",
		"y Headphone",	"y HPROUT",
		"y MIC3R",		"y Mic",
		"a LINE1L",		"a Line In",
		"b LINE1R",		"b Line In";
		nvidia,xbar = <&tegra_axbar>;
	mclk-fs = <256>;
		hdr40_snd_link_i2s: i2s_dai_link1: nvidia,dai-link-1 {
		link-name = "tlv320-playback";
		cpu-dai = <&tegra_i2s1>;
		codec-dai = <&tlv320aic3007>;
		cpu-dai-name = "I2S0";
		codec-dai-name = "tlv320-hifi";
		format = "i2s";
		bitclock-slave;
		frame-slave;
		bitclock-noninversion;
		frame-noninversion;
		bit-format = "s16_le";
		srate = <48000>;
		num-channel = <2>;
		ignore_suspend;
		name-prefix = "x";
		status = "okay";
	};

i2c@7000d000 {
	clock-frequency = <400000>;
	status="okay";
	tlv320aic3007: tlv320aic3007@18 {
		#sound-dai-cells = <0>;
		compatible = "ti,tlv320aic3007";
		reg = <0x18>;
		status = "okay";
		ai3x-micbias-vg = <2>;
		adc-settle-ms = <40>;
	};
};

Using i2cdetect we can see that the codec is detected on the i2c0 bus at the correct address, 0x18. I haven’t been able to find any errors pointing me in the right direction in dmesg though.

Any help would be greatly appreciated!

Thank you

1 Like

Hello!

The first thing that you need to check is if the codec driver has been probed on boot. Is the codec has been probed and registered successfully, then you should see it listed under …

$ sudo cat /sys/kernel/debug/asoc/codecs

If it is not there, then check that the codec is enabled in the kernel config …

$ zcat /proc/config.gz | grep CONFIG_SND_SOC_TLV320AIC3X

Regards,
Jon

1 Like

Hello!

By the way, are you familiar with this codec?

The reason I ask is that getting the codec to probe and register is usually fairly straight forward to get working, but knowing how to configure the codec is the tricky part. Once the codec is registered and you have configured device-tree, then the next thing is knowing now to configure and enable the audio route in the codec. If you refer to the codec driver [0], you will see that it provides a lot of mixer controls for configuring and enabling the audio route. This is far the most complex part of integrating an I2S codec and unless this is a codec we have used (which this is not), it is difficult to assist with this. So it can be a good idea to ask the codec vendor how to configure the Linux driver for the codec.

Regards
Jon

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/sound/soc/codecs/tlv320aic3x.c#n327

Howdy Jonathan,

Yes, I’ve used this codec once before on a different SoM, it was included in their dev board and already defined in their device tree. I had to modify its routing via the driver and Alsa which worked, but this is my first time really getting into the Jetson device tree and adding a device.

It is listing as added in the kernel config, but I don’t believe I see it listed when I cat /sys/kernel/debug/asoc/codecs.

Hello John,

OK great. You mentioned that you are using I2C0, can you confirm that is the I2C on pins 185 and 187 of the module? If so, then that should be the gen1_i2c controller, but this is the I2C controller at address 0x7000c000.

Regards,
Jon

You’re correct, I think I put the codec-dai under the wrong address. We are using pins 185 and 187 so I moved it into the i2c@7000c000 section, but it still does not seem to be detected:

	hdr40_i2c0: i2c@7000c000 {
		clock-frequency = <400000>;
		status="okay";

		tegra_nct72: temp-sensor@4c {
			status = "disabled";
		};

		tlv320aic3007: tlv320aic3007@18 {
			compatible = "ti,tlv320aic3007";
			reg = <0x18>;
			status = "okay";
			ai3x-micbias-vg = <2>;
			adc-settle-ms = <40>;
		};
	};

I also changed the cpu-dai from i2s1 to i2s4: cpu-dai = <&tegra_i2s4>; because the pinmux has pins 193, 195, 197, and 199 going to i2s4 correct?

Thanks again for the help with this!

Hi John,

Yes I2S4 would be correct for pins 193, 195, 197 and 199.

So next make sure that the DT was updated OK …

$ cat /proc/device-tree/i2c@7000c000/status
$ cat /proc/device-tree/i2c@7000c000/tlv320aic3007@18/status

Then check the output from ‘dmesg’ to see if there are any errors related to i2c or the codec.

Regards,
Jon

Cool, so the i2c@7000c000 shows status=okay. It gives no such file or directory when trying to check status of tlv320aic3007@18.

Dmesg is not showing any errors relating to i2c or the audio codec.

Hi John,

Is sounds like the DT was not updated as expected. I assumed that you rebuilt and flashed the updated DTB?

How did you update the DTB?

Regards,
Jon

I made the changes in tegra210-porg-p3448-common.dtsi and then ran the following command to rebuild:

make -C kernel/kernel-4.9/ ARCH=arm64 O=$TEGRA_KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${TOOLCHAIN_PREFIX} -j8 --output-sync=target dtbs

But I did not use the “sudo ./flash.sh -r -k DTB jetson-nano-emmc mmcblk0p1” command to update the Nano. I just copied the new .dtb straight to the /boot folder.

Hi John,

Yes that is the problem. Please try flashing the DTB. If you look at the /boot/extlinux/extlinux.conf it does not have an FDT entry for loading the DTB from the rootfs and so the one in the DTB partition is used. That said it is possible to update the extlinux.conf to load one from /boot.

Regards,
Jon

That’ll teach me to take shortcuts! It is now seeing my device tree changes and trying to setup the codec, but it is failing with the following in dmesg:

tegra-asoc: sound: ASoC: CODEC DAI tlv320-hifi not registered
tegra-asoc: sound: snd_soc_register_card failed (-517)

Hello John,

That error can be normal. The error code -517 means that the probing of the codec is being deferred because some dependency (clocks, resets, etc) are not available yet and will continue to retry probing it. So check the debugfs node again for the codec and see if it is there …

$ sudo cat /sys/kernel/debug/asoc/codecs

Regards,
Jon

So I had some naming mismatches between the device tree and driver .c file. Changed tlv320-hifi to tlv320aic3x-hifi and that error disappeared. Then next I had to fix my cpu-dai-name from “I2S0” to “I2S4”, and fix the audio-routing prefixes to all "x ".

Now it is loading with no errors in dmesg and it looks like I just need to setup the routing with amixer?

I’m not familiar with the ASoC machine driver and mixing it through the ADMAIF. I’ve set the following:

amixer -c 1 cset name='I2S4 Mux' 'ADMAIF1' 
amixer -c 1 cset name='ADMAIF1 Mux' 'I2S4'

Then I setup the other I2S4 field values according to the codec data sheet, as well as the 'x ’ routing, but I’m still not getting any sound when I try to playback.

Hi John,

The above mixer settings should be set by default for Nano (in /usr/share/alsa/init/postinit/00-tegra.conf). It is not necessary to set the other I2S mixer controls (for channels, sample-rate, etc) as these should be configured when capture/playback start depending on the PCM format being used. These are only to override the PCM format for some more complex use-cases.

To check if the audio path is good try …

$ echo 0 | sudo tee /sys/kernel/debug/tracing/trace
$ echo 0 | sudo tee /sys/kernel/debug/tracing/events/enable
$ echo 1 | sudo tee /sys/kernel/debug/tracing/tracing_on
$ echo 1 | sudo tee /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
$ speaker-test -D hw:tegrasndt210ref,0 -c 2 -r 48000 -F S16_LE -t sine -f 500 -l 1
$ sudo cat /sys/kernel/debug/tracing/trace

Regards,
Jon

Here are the results to the trace:

Hi John,

Looks like a problem with the configuration of the audio route. Can you try the following and verify that you see some output from the trace …

$ echo 0 | sudo tee /sys/kernel/debug/tracing/trace
$ echo 0 | sudo tee /sys/kernel/debug/tracing/events/enable
$ echo 1 | sudo tee /sys/kernel/debug/tracing/tracing_on
$ echo 1 | sudo tee /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
$ amixer -c 1 sset "ADMAIF1 Mux" ADMAIF1
$ speaker-test -D hw:1,0 -c 2 -r 48000 -F S16_LE -t sine -f 500 -l 1
$ sudo cat /sys/kernel/debug/tracing/trace

This effectively does a simple audio loopback.

Regards,
Jon

Hi Jon,

Here is the result from the audio loopback:

Hi John,

Can you revert the ADMAIF1 Mux changes so you have …

$ amixer -c 1 cset name='I2S4 Mux' 'ADMAIF1' 
$ amixer -c 1 cset name='ADMAIF1 Mux' 'I2S4'

Can you run the following script and send me the output?

#!/bin/bash

set -e
set -u

outfile="${HOME}/tegra-audio-debug.txt"

if [ -f "${outfile}" ]; then
    rm "${outfile}"
fi

alsactl store -f "${outfile}"

dapm_dirs=$(sudo find /sys/kernel/debug/asoc -type d -name dapm)

for dir in ${dapm_dirs}; do
    sudo find ${dir} -type f -exec echo {} \; -exec cat {} \; >> "${outfile}"
done

echo "Tegra audio debug info written to ${outfile}"

Please can you attach the output file because it is quite long.

Thanks
Jon