TLV320ADCx140 audio adc with TX2

OK Jon,

So if the SND_SOC_DAPM_INPUT widgets are:

SND_SOC_DAPM_INPUT("MIC1P"),
SND_SOC_DAPM_INPUT("MIC1M"),
SND_SOC_DAPM_INPUT("MIC2P"),
SND_SOC_DAPM_INPUT("MIC2M"),
SND_SOC_DAPM_INPUT("MIC3P"),
SND_SOC_DAPM_INPUT("MIC3M"),
SND_SOC_DAPM_INPUT("MIC4P"),
SND_SOC_DAPM_INPUT("MIC4M"),

should my routing for 4 x single-ended inputs look like:

nvidia,audio-routing =
“x Mic” “x MIC1P”,
“x Mic” “x MIC2P”,
“x Mic” “x MIC3P”,
“x Mic” “x MIC4P”;

I’m afraid my understanding of routing in ALSA is a bit shaky.

Cheers,

David.

Hi David,

Are you only using single-ended inputs for the mics? In other words, just the MICP inputs? The driver shows that each MIC input has a mux mixer control to setup if it is ‘Analog’, Line In’ and in the case of the MICPs ‘Digital’ that need to be configured …

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/sound/soc/codecs/tlv320adcx140.c#n209

The routing is close but you should have it the other way around …

nvidia,audio-routing =
    "x MIC1P”, “x Mic”,
    “x MIC2P”, “x Mic”,
     “x MIC3P”, “x Mic”,
     “x MIC4P”, “x Mic” ;

What we want to see is that when you run your capture command all the various DAPM widgets (Tegra and ADC) turn on. We can see this by tracing the DAPM widget events …

$ 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
$ arecord ...
$ sudo cat /sys/kernel/debug/tracing/trace

If the trace shows very little then this is a sign that something is not configured correct in the ADC.

Regards
Jon

Thanks very much Jon,

My understanding is that 4 x differential or single-ended inputs are supported, or 8 x digital inputs. As I only have single-ended analog inputs, I was assuming that these would be x MIC1-P to x MIC4-P.

I will change my routing and give the trace a try tomorrow and get back to you with the results.

Cheers,

David.

Hi David,

Yes then that would look correct to me for the routing just having those four.

Jon

Hello again Jon,

I quickly went ahead and changed the routing and performed that trace. Unfortunately, it seems to be empty:

tracer: nop

entries-in-buffer/entries-written: 0/0 #P:4# tracer: nop

entries-in-buffer/entries-written: 0/0 #P:4

_-----=> irqs-off

/ _----=> need-resched

| / _—=> hardirq/softirq

|| / _–=> preempt-depth

||| / delay

TASK-PID CPU# |||| TIMESTAMP FUNCTION

| | | |||| | |

Cheers,

David.

Hi Jon,

So the trace was completely blank and I am not seeing any BCLK or LRCLK when I run arecord. I do, however, see MCLK at 12.288 MHz.

As I mentioned before, I currently do not call snd_soc_dai_set_sysclk() anywhere, which makes me slightly surprised to see MCLK at all. Could the absence of the other clocks be caused by this, however?

I think this is close to working now, provided I can restore the clock signals for I2S1, but I note the TI driver has no .set_sysclk member in adcx140_dai_ops [1], so if I do need to set the sysclock, I don’t know how.

I have also had a change in thinking brought about by [1], as the TI driver is apparently written to configure the TLV320ADCx140 in slave mode (which is what I want) with auto-clock configuration, so it’s simplest to disconnect MCLK and let the device generate its own provided I can supply BCLK and LRCLK (FSYNC).

Right now, I need some help with those I2S1 clocks. I am using the same pinmux configuration as for the SGTL5000. sudo grep dap1 /sys/kernel/debug/tegra_pinctrl_reg gives:

Bank: 0 Reg: 0x02431028 Val: 0x00000440 → dap1_fs_pj3
Bank: 0 Reg: 0x02431030 Val: 0x00000458 → dap1_din_pj2
Bank: 0 Reg: 0x02431038 Val: 0x00000400 → dap1_dout_pj1
Bank: 0 Reg: 0x02431040 Val: 0x00000440 → dap1_sclk_pj0

Cheers,
David.

[1] https://lkml.org/lkml/2020/2/26/413

Hi David,

What exact arecord command are you using?

Have you mapped the I2S1 to one of the ADMAIFx interfaces?

There are some examples for I2S here:
https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Fasoc_driver.18.2.html%23wwpID0E0YJ0HA

Typically, you map the I2S1 to say ADMAIF1 …

$ amixer -c tegrasndt186ref sget "ADMAIF1 Mux" I2S1

And then record on ADMAIF1 …

$ arecord -D hw:tegrasndt186ref,0 -c 4 -r 48000 -f S16_LE cap.wav

Regards,
Jon

Hi Jon,

Out of ideas here. After running those exact commands, I’m still only seeing MCLK at 12.288 MHz, but no BCLK or LRCLK. My sound block looks like this:

	tegra_sound: sound {
		compatible = "nvidia,tegra-audio-t186ref-mobile-rt565x";
		nvidia,model = "tegra-snd-t186ref-mobile-rt565x";
		nvidia,num-codec-link = <1>;
        nvidia,num-clk = <8>;
        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 */
        clocks = <&tegra_car TEGRA186_CLK_PLLP_OUT0>,
                <&tegra_car TEGRA186_CLK_PLLA>,
                <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
                <&tegra_car TEGRA186_CLK_AHUB>,
                <&tegra_car TEGRA186_CLK_CLK_M>,
                <&tegra_car TEGRA186_CLK_AUD_MCLK>;
        clock-names = "pll_p_out1", "pll_a", "pll_a_out0", "ahub",
                        "clk_m", "extern1";
        assigned-clocks = <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
				  <&tegra_car TEGRA186_CLK_AHUB>,
				  <&tegra_car TEGRA186_CLK_AUD_MCLK>;
		assigned-clock-parents = <&tegra_car TEGRA186_CLK_PLLA>,
					 <&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
					 <&tegra_car TEGRA186_CLK_PLL_A_OUT0>;
		resets = <&tegra_car TEGRA186_RESET_AUD_MCLK>;
		reset-names = "extern1_rst";

		status = "okay";
		nvidia,audio-routing =
		    "x MIC1P",		"x Mic",
		    "x MIC2P",		"x Mic",
		    "x MIC3P",		"x Mic",
			"x MIC4P",		"x Mic";

		nvidia,xbar = <&tegra_axbar>;
		mclk-fs = <256>;

		rt565x_dai_link: nvidia,dai-link-1 {
			link-name = "tlv320adcx140-codec";
			cpu-dai = <&tegra_i2s1>;
			codec-dai = <&tlv320adcx140>;
			cpu-dai-name = "I2S1";
			codec-dai-name = "tlv320adcx140-codec";
			format = "dsp_a";
            bitclock-slave;
            frame-slave;
            bitclock-noninversion;
            frame-noninversion;
			bit-format = "s32_le";
			bclk_ratio = <0>;
			srate = <48000>;
			num-channel = <4>;
			ignore_suspend;
			name-prefix = "x";
			status = "okay";
		};

I should be getting those clocks even if I’ve totally messed up the codec configuration, right?

Cheers,
David.

Hi David,

If the audio path is not configured correctly, then it is possible that the DAPM widget for the I2S will not be turned on and so you will not see the clocks running. The pinmux looks fine and so it must be a configuration or routing issue somewhere. This is a common problem with integrating new codecs.

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}"

Thanks
Jon

Hi Jon,

I have uploaded the output of your script as tegra-audio-debug.log

Cheers,
David.

tegra-audio-debug.log (505.7 KB)

Hi David,

I took at look through the output and I can see that the ‘audio serial interface’ is disabled for the 4 ADCs. Can you try enabling these and then run the kernel ASoC tracing again to see if there is any output? Also re-run the debug script again so we can see how this changes the audio route.

$ amixer -c tegrasndt186ref sset "x CH1_ASI_EN" 1
$ amixer -c tegrasndt186ref sset "x CH2_ASI_EN" 1
$ amixer -c tegrasndt186ref sset "x CH3_ASI_EN" 1
$ amixer -c tegrasndt186ref sset "x CH4_ASI_EN" 1

Thanks
Jon

Thanks so much for taking a look at this Jon.

I did the following:

$ amixer -c tegrasndt186ref sset "x CH1_ASI_EN" on
$ amixer -c tegrasndt186ref sset "x CH2_ASI_EN" on
$ amixer -c tegrasndt186ref sset "x CH3_ASI_EN" on
$ amixer -c tegrasndt186ref sset "x CH4_ASI_EN" on

but, unfortunately, the kernel ASoC tracing was again empty after doing

$ 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
$ arecord -D hw:tegrasndt186ref,0 -c 4 -r 48000 -f S32_LE cap.wav
$ sudo cat /sys/kernel/debug/tracing/trace

I have attached the new debug output here:
tegra-audio-debug.log (505.9 KB)

Hi David,

Can you also try enabling the DRE switches? It is not clear to me if these need to be enabled or not but the block diagram of the ADC does show the ADC output going through the Digital filters and DRE.

$ amixer -c tegrasndt186ref sset 'x DRE_ENABLE' on
$ amixer -c tegrasndt186ref sset 'x CH1_DRE_EN' on
$ amixer -c tegrasndt186ref sset 'x CH2_DRE_EN' on
$ amixer -c tegrasndt186ref sset 'x CH3_DRE_EN' on
$ amixer -c tegrasndt186ref sset 'x CH4_DRE_EN' on

If you can enable those in addition to the ASI enables and while the arecord is running, execute the debug script to dump all the settings.

Thanks
Jon

Hi David,

I also noticed that you have both ADMAIF1 and ADMAIF2 connected to I2S1 …

/sys/kernel/debug/asoc/tegra-snd-t186ref-mobile-rt565x/codec:tegra210-axbar/dapm/I2S1 RX
I2S1 RX: Off  in 0 out 0
 out  "I2S1" "ADMAIF2 Mux"
 out  "I2S1" "ADMAIF1 Mux"
 in  "static" "I2S1 Receive"

If you are using ADMAIF1 then disconnect ADMIF2 …

$ amixer -c tegrasndt186ref sset "ADMAIF2 Mux" None

Regards
Jon

Hi Jon,

So currently, I am doing:

amixer -c tegrasndt186ref sset “ADMAIF1 Mux” I2S1
amixer -c tegrasndt186ref sset “ADMAIF2 Mux” None

amixer -c tegrasndt186ref sset “x CH1_ASI_EN” on
amixer -c tegrasndt186ref sset “x CH2_ASI_EN” on
amixer -c tegrasndt186ref sset “x CH3_ASI_EN” on
amixer -c tegrasndt186ref sset “x CH4_ASI_EN” on

amixer -c tegrasndt186ref sset “x DRE_ENABLE” on
amixer -c tegrasndt186ref sset “x CH1_DRE_EN” on
amixer -c tegrasndt186ref sset “x CH2_DRE_EN” on
amixer -c tegrasndt186ref sset “x CH3_DRE_EN” on
amixer -c tegrasndt186ref sset “x CH4_DRE_EN” on

and then running the debug script while recording:

arecord -D hw:tegrasndt186ref,0 -c 4 -r 48000 -f S32_LE cap.wav

Output is attached:
tegra-audio-debug.log (506.3 KB)

I have also switched devkit boards on the slim chance that my I2S1 pins may not have been functioning. Still no joy! It’s also strange that I revisited my SGTL5000 setup, which is attached to a separate devkit board. When I run arecord on that, I see all the correct clock activity - even after commenting out snd_soc_dai_set_sysclk()!

Cheers,

David.

Hi David,

It appears that there is no route between the ‘x Capture’ and the ADC. Could you try adding the following to the route …

nvidia,audio-routing =
    "x MIC1P”, “x Mic”,
    “x MIC2P”, “x Mic”,
     “x MIC3P”, “x Mic”,
     “x MIC4P”, “x Mic”,
     “x Capture”, “x CH1_OUT”,
     “x Capture”, “x CH2_OUT”,
     “x Capture”, “x CH3_OUT”,
     “x Capture”, “x CH4_OUT”;

This time when you run the trace can you also add …

$ 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_path/enable
$ echo 1 | sudo tee /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
$ arecord ...
$ sudo cat /sys/kernel/debug/tracing/trace

Thanks
Jon

Hi Jon,

OK - I did that and now I seem to get something the trace:

# tracer: nop
#
# entries-in-buffer/entries-written: 2/2   #P:4
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
         arecord-20956 [000] ....  1015.662446: snd_soc_dapm_path: *ADMAIF1 Transmit -> (direct) -> Capture 1
         arecord-20956 [000] ....  1015.662456: snd_soc_dapm_path: *ADMAIF1 Transmit -> (direct) -> ADMAIF1 Transmit-ADMAIF1 CIF Transmit

The new script output is here: tegra-audio-debug.log (506.5 KB)

Still no clocks on the scope and after a while of trying to record I get input/output errors as before (I should have mentioned that earlier perhaps). It seems to me there must be something wrong with my machine driver preventing the clocks rather than just a routing problem?

Thanks,

David.

Hi David,

Thanks. Yes that still does not look quite right, can you try …

    "x MIC1P”, “x Mic”,
    “x MIC2P”, “x Mic”,
     “x MIC3P”, “x Mic”,
     “x MIC4P”, “x Mic”,
     “x Capture”, “x CH1_ADC”,
     “x Capture”, “x CH2_ADC”,
     “x Capture”, “x CH3_ADC”,
     “x Capture”, “x CH4_ADC”;

Thanks
Jon

>  #####                                                    ###
> #     #  #    #   ####    ####   ######   ####    ####    ###
> #        #    #  #    #  #    #  #       #       #        ###
>  #####   #    #  #       #       #####    ####    ####     #
>       #  #    #  #       #       #            #       #
> #     #  #    #  #    #  #    #  #       #    #  #    #   ###
>  #####    ####    ####    ####   ######   ####    ####    ###

It works! (or at least it appears to for now). I can see FSYNC at 48kHz, BCLK at around 6.144 MHz and four channels of 32-bit data on I2S1 DIN. I don’t know what MCLK is because the device PLL is generating it internally. Here are some scope traces:


The trace file is here: trace.log (37.1 KB) and the debug script output is here: tegra-audio-debug.log (506.5 KB).

I’m going to try to have a look at the data now to see what I’m actually getting, but as the EVM only has a microphone on input 1, and the first data packet seems to have more no-zero bits than the next three, I’d say things look promising. I’ll let you know how I go shortly.

Thanks again Jon,
You’re a genius.

Hello again John,

I’m wondering what the best way of storing all that configuration is between boots.
Presumably there is a config somewhere?

Cheers,

David.