Enable i2s3 on Tegra X2

We want to use i2s3 on our Jetson TX2.
We already - and successfully - use I2S1, I2S2 and I2S4 as input and output masters, they are turned on in the pinmux, they are enabled in the device tree, we also set the audio data paths with amixer.

From the four i2s (i2s1,i2s2,i2s3,i2s4) three is OK(1,2 and 4), however there is no signal whatsoever on i2s3 when we capture it with a logic analyzator or oscilloscope during playback or record (Tegra X2 is the master).

We see a difference, that i2s3 can also be used as DMIC1, but as far as we see in the device tree, DMIC1 is disabled (status=“disabled”).

What do we miss?

Hello,

When you say I2S3, I want to check if this is the I2S available via the camera expansion header or the M.2 key E header?

The reason being that the schematics for the CVB (main p2597 board) and CVM (Tegra module board) label these differently. For example

CVM → CVB
DAP1 → I2S0 (header J21)
DAP2 → I2S1 (header J26
DAP3 → I2S2 (M.2 Key E header J18)
DAP4 → I2S3 (Camera header J22)

I assume that you are referring to DAP3 as this can be muxed with DMIC1/2.

You can check the pinmux for the dmic pins by …

$ sudo grep dmic /sys/kernel/debug/tegra_pinctrl_reg
Bank: 0 Reg: 0x02432000 Val: 0x00006401 -> dmic1_clk_pm1
Bank: 0 Reg: 0x02432008 Val: 0x00006459 -> dmic1_dat_pm0
Bank: 0 Reg: 0x02432010 Val: 0x00006401 -> dmic2_dat_pm2
Bank: 0 Reg: 0x02432018 Val: 0x00006401 -> dmic2_clk_pm3

The bits[1:0] indicate the current mux setting and a ‘1’ means that I2S3/DAP3 is selected. Bit 10 indicates if the pin is a GPIO or SFIO. We want bit 10 to be set so the pin is an SFIO and not GPIO (which for me it is). If you have the same, then the pinmux is good.

I assume that you have mapped the I2S3/DAP3 interface to one of the ADMAIF and then tried to play …

amixer -c tegrasndt186ref cset name="I2S3 Mux" "ADMAIF3"
aplay -D hw:tegrasndt186ref,2 <wavfile>

Regards,
Jon

Hi jonathanh,

We have a custom carrier board for the SOM, so we found I2S interface numbers from the pinmux excel. According to this, DMIC1_CLK, DMIC1_DAT, DMIC2_CLK and DMIC2_DAT pins (pins H5, G6, H6, G5) of the SOM are connected to I2S3 interface.

In the meantime we modified our system so that the Tegra is an I2S slave, all I2S clocks are generated by an external FPGA. So this is why the pinmux registers show the clocks as inputs.
Pinmux registers for all 4 I2S interfaces (with TRM chapter number and expected bit setting):

# I2S1 (8.31.7 -> [1:0]=0)
DIN:  Bank: 0 Reg: 0x02431030 Val: 0x00000458 -> dap1_din_pj2
DOUT: Bank: 0 Reg: 0x02431038 Val: 0x00000400 -> dap1_dout_pj1
LRCK: Bank: 0 Reg: 0x02431028 Val: 0x00000454 -> dap1_fs_pj3
SCLK: Bank: 0 Reg: 0x02431040 Val: 0x00000454 -> dap1_sclk_pj0

# I2S3 (8.31.5 -> [1:0]=1)
DIN:  Bank: 0 Reg: 0x02432008 Val: 0x00006451 -> dmic1_dat_pm0
DOUT: Bank: 0 Reg: 0x02432018 Val: 0x00006401 -> dmic2_clk_pm3
LRCK: Bank: 0 Reg: 0x02432000 Val: 0x00006455 -> dmic1_clk_pm1
SCLK: Bank: 0 Reg: 0x02432010 Val: 0x00006455 -> dmic2_dat_pm2

# I2S4 (8.31.5 -> [1:0]=0)
DIN:  Bank: 0 Reg: 0x02432038 Val: 0x00006458 -> dap4_din_pcc2
DOUT: Bank: 0 Reg: 0x02432040 Val: 0x00006400 -> dap4_dout_pcc1
LRCK: Bank: 0 Reg: 0x02432030 Val: 0x00006454 -> dap4_fs_pcc3
SCLK: Bank: 0 Reg: 0x02432048 Val: 0x00006454 -> dap4_sclk_pcc0

#I2S2 (8.31.11 -> [1:0]=0)
DIN:  Bank: 0 Reg: 0x02434000 Val: 0x00000458 -> dap2_din_pc3
DOUT: Bank: 0 Reg: 0x02434008 Val: 0x00000400 -> dap2_dout_pc2
LRCK: Bank: 0 Reg: 0x02434010 Val: 0x00000454 -> dap2_fs_pc4
SCLK: Bank: 0 Reg: 0x02434018 Val: 0x00000454 -> dap2_sclk_pc1

According to the Parker TRM they seem to be fine: bit[10] is 1 and bit[1:0] settings correspond with the register documentation (PULLUP on the DIN pins is my fault, but it should not matter).

amixer setting:

amixer -c 0 sset 'I2S1 Mux' 'ADMAIF1'
amixer -c 0 sset 'ADMAIF1 Mux' 'I2S1'
amixer -c 0 cset name='I2S1 codec bit format' 32
amixer -c 0 cset name='I2S1 input bit format' 32

amixer -c 0 sset 'I2S2 Mux' 'ADMAIF2'
amixer -c 0 sset 'ADMAIF2 Mux' 'I2S2'
amixer -c 0 cset name='I2S2 codec bit format' 32
amixer -c 0 cset name='I2S2 input bit format' 32

amixer -c 0 sset 'I2S3 Mux' 'ADMAIF3'
amixer -c 0 sset 'ADMAIF3 Mux' 'I2S3'
amixer -c 0 cset name='I2S3 codec bit format' 32
amixer -c 0 cset name='I2S3 input bit format' 32

amixer -c 0 sset 'I2S4 Mux' 'ADMAIF4'
amixer -c 0 sset 'ADMAIF4 Mux' 'I2S4'
amixer -c 0 cset name='I2S4 codec bit format' 32
amixer -c 0 cset name='I2S4 input bit format' 32

When I try to record something with

arecord -D hw:0,X -r 48000 -c 2 -f S32_LE rec.wav

(X is changed from 0 to 3), I get the correct data sent by the test I2S source for all channels except I2S3, where there is no data recorded at all (the wav file only contains the header).

When a play an 1 minute, 48kHz file with

aplay -D hw:0,X sawtooth.wav

it takes ~30 sec on the other channels (the sampling frequency generated by the FPGA is 96 kHz, so this is ok) and the serial I2S output of the Tegra changes correctly (verified with a logic analyzer). When I2S3 is used, playback takes ~2 sec and there is no change on the output.
I would guess that this is the maximum performance of ADMA, so the output of the DMA is not limited by any read handshake?

Regards,

Peter

Hi Peter,

It sounds like the I2S3 interface is not even turning on which would imply an software audio routing problem. Can you …

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

<start playback/capture>

sudo cat /sys/kernel/debug/tracing/trace

Otherwise what you have looks fine. Please note that you should not need to set either ‘I2Sx codec bit format’ or ‘I2Sx input bit format’ mixer controls as this should be directly handled by the format you are passing with aplay/arecord.

Regards,
Jon

Hi Jon,

This is the log when I use I2S3:

/ # echo 1 /sys/kernel/debug/tracing/tracing_on
1 /sys/kernel/debug/tracing/tracing_on
/ # echo 1 /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
1 /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
/ #
/ # time aplay -D hw:0,2 sawtooth.wav
Playing WAVE 'sawtooth.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
real    0m 1.89s
user    0m 0.00s
sys     0m 0.04s
/ #
/ # cat /sys/kernel/debug/tracing/trace
# 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
#              | |       |   ||||       |         |
/ #

The same debug trace for I2S1:

echo 1 /sys/kernel/debug/tracing/tracing_on
1 /sys/kernel/debug/tracing/tracing_on
/ # echo 1 /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
1 /sys/kernel/debug/tracing/events/asoc/snd_soc_dapm_widget_power/enable
/ #
/ # time aplay -D hw:0,0 sawtooth.wav
Playing WAVE 'sawtooth.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
real    0m 29.52s
user    0m 0.00s
sys     0m 0.04s
/ #
/ # cat /sys/kernel/debug/tracing/trace
# tracer: nop
#
# entries-in-buffer/entries-written: 30/30   #P:4
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
           aplay-371   [004] ...1 10579.944442: snd_soc_dapm_widget_power: widget=Playback 1 val=1
           aplay-371   [004] ...1 10579.944446: snd_soc_dapm_widget_power: widget=ADMAIF1 Receive val=1
           aplay-371   [004] ...1 10579.944447: snd_soc_dapm_widget_power: widget=ADMAIF1 RX val=1
           aplay-371   [004] ...1 10579.944452: snd_soc_dapm_widget_power: widget=I2S1 Mux val=1
           aplay-371   [004] ...1 10579.944453: snd_soc_dapm_widget_power: widget=I2S1 TX val=1
           aplay-371   [004] ...1 10579.944454: snd_soc_dapm_widget_power: widget=I2S1 Transmit val=1
           aplay-371   [004] ...1 10579.944454: snd_soc_dapm_widget_power: widget=I2S1 Transmit-I2S1 CIF Receive val=1
           aplay-371   [004] ...1 10579.944455: snd_soc_dapm_widget_power: widget=I2S1 CIF Receive val=1
           aplay-371   [004] ...1 10579.944456: snd_soc_dapm_widget_power: widget=I2S1 CIF RX val=1
           aplay-371   [004] ...1 10579.944456: snd_soc_dapm_widget_power: widget=I2S1 DAP TX val=1
           aplay-371   [004] ...1 10579.944457: snd_soc_dapm_widget_power: widget=I2S1 DAP Transmit val=1
           aplay-371   [004] ...1 10579.944458: snd_soc_dapm_widget_power: widget=I2S1 DAP Transmit-x Playback val=1
           aplay-371   [004] ...1 10579.944459: snd_soc_dapm_widget_power: widget=x Playback val=1
           aplay-371   [004] ...1 10579.944459: snd_soc_dapm_widget_power: widget=x OUT val=1
           aplay-371   [004] ...1 10579.944460: snd_soc_dapm_widget_power: widget=x Headphone val=1
           aplay-371   [000] ...1 10609.452396: snd_soc_dapm_widget_power: widget=Playback 1 val=0
           aplay-371   [000] ...1 10609.452400: snd_soc_dapm_widget_power: widget=ADMAIF1 Receive val=0
           aplay-371   [000] ...1 10609.452401: snd_soc_dapm_widget_power: widget=ADMAIF1 RX val=0
           aplay-371   [000] ...1 10609.452405: snd_soc_dapm_widget_power: widget=I2S1 Mux val=0
           aplay-371   [000] ...1 10609.452407: snd_soc_dapm_widget_power: widget=I2S1 TX val=0
           aplay-371   [000] ...1 10609.452407: snd_soc_dapm_widget_power: widget=I2S1 Transmit val=0
           aplay-371   [000] ...1 10609.452408: snd_soc_dapm_widget_power: widget=I2S1 Transmit-I2S1 CIF Receive val=0
           aplay-371   [000] ...1 10609.452409: snd_soc_dapm_widget_power: widget=I2S1 CIF Receive val=0
           aplay-371   [000] ...1 10609.452409: snd_soc_dapm_widget_power: widget=I2S1 CIF RX val=0
           aplay-371   [000] ...1 10609.452410: snd_soc_dapm_widget_power: widget=I2S1 DAP TX val=0
           aplay-371   [000] ...1 10609.452411: snd_soc_dapm_widget_power: widget=I2S1 DAP Transmit val=0
           aplay-371   [000] ...1 10609.452412: snd_soc_dapm_widget_power: widget=I2S1 DAP Transmit-x Playback val=0
           aplay-371   [000] ...1 10609.452412: snd_soc_dapm_widget_power: widget=x Playback val=0
           aplay-371   [000] ...1 10609.452413: snd_soc_dapm_widget_power: widget=x OUT val=0
           aplay-371   [000] ...1 10609.452414: snd_soc_dapm_widget_power: widget=x Headphone val=0
/ #

So I think your first assumption is right, I2S3 does not run at all.
Do you have any suggestion we can try?

Regards,

Peter

Hi Peter,

Have you made any changes to device-tree with regard to the ‘sound’ node?

Can you tell me the output from …

cat /proc/device-tree/sound/nvidia,audio-routing
links=$(find /proc/device-tree/sound -type d -name nvidia,dai-link-*)
for link in ${links}; do cat ${link}/link-name; echo -n " " ; cat ${link}/cpu-dai-name ; echo -n " " ; cat ${link}/name-prefix ; echo; done

Can you also dump the alsa settings and attach …

$ alsactl -f alsa-settings.txt store

Regards,
Jon

Hi Jon,

Output:

cat /proc/device-tree/sound/nvidia,audio-routing
x Headphonex OUTx INx Micy Headphoney OUTy INy Micz INz OUTm Headphonem OUTm INm Micn Headphonen OUTn INn Mico Headphoneo OUTo INo Mica INa Micb INb Micc INc Micd INd Mice Headphonee OUTe INe Micd1 Headphoned1 OUTd2 Headphoned2 OUT/ # links=$(find /proc/device-tree/sound -type d -name nvidia,dai-link-*)
/ # for link in ${links}; do cat ${link}/link-name; echo -n " " ; cat ${link}/cpu-dai-name ; echo -n " " ; cat ${link}/name-
prefix ; echo; done
spdif-dit-10 DMIC4 d
spdif-playback SPDIF1-1 e
dspk-playback-r DSPK1 d1
dspk-playback-l DSPK2 d2
rt565x-playback I2S1 x
spdif-dit-1 I2S2 y
spdif-dit-2 I2S3 z
spdif-dit-3 I2S4 m
spdif-dit-4 I2S5 n
spdif-dit-6 I2S6 o
spdif-dit-7 DMIC1 a
spdif-dit-8 DMIC2 b
spdif-dit-9 DMIC3 c

Alsa settings: http://home.mit.bme.hu/~szanto/tegra/alsa-settings.txt

Regards,

Peter

Hi Peter,

Thanks. The audio route for I2S3 does not look correct. This was fixed in L4T rel28.2. I do recommend upgrading to rel28.2 as there were several audio related fixes in this release. However, the exact fix you need is …

https://nv-tegra.nvidia.com/gitweb/?p=device/hardware/nvidia/platform/t18x/common.git;a=commit;h=6dd204863d8c6c1c5bf8791694b7cdce8f5d739a

Regards,
Jon

Hi Jon,

This fix solved our problem.
Thank you for your support.

Regards,

Peter

Hi, i am trying to activate i2s3 (DAP4) connector j22 on my tx2 but i can’t see nothing on oscilloscope.

What i need to do this?

Thank you very much!

Can you tell me …

  1. What L4T release are you using?
  2. Can you check the pinmuxing as described in comment #2?

Jon

Hi:

I am using version r28.2.

This is my pinmux.dtsi:

include <dt-bindings/pinctrl/pinctrl-tegra.h>

/ {
pinmux@2430000 {
pinctrl-names = “default”, “drive”, “unused”;
pinctrl-0 = <&pinmux_default>;
pinctrl-1 = <&drive_default>;
pinctrl-2 = <&pinmux_unused_lowpower>;

	pinmux_default: common {
		/* SFIO Pin Configuration */
		uart4_tx_pb0 {
			nvidia,pins = "uart4_tx_pb0";
			nvidia,function = "uartd";
			nvidia,pull = <TEGRA_PIN_PULL_NONE>;
			nvidia,tristate = <TEGRA_PIN_DISABLE>;
			nvidia,enable-input = <TEGRA_PIN_DISABLE>;
			nvidia,lpdr = <TEGRA_PIN_DISABLE>;
		};

.
.
.

                    dap4_sclk_pcc0 {
			nvidia,pins = "dap4_sclk_pcc0";
			nvidia,function = "i2s4";
			nvidia,pull = <TEGRA_PIN_PULL_NONE>;
			nvidia,tristate = <TEGRA_PIN_DISABLE>;
			nvidia,enable-input = <TEGRA_PIN_DISABLE>;
		};

		dap4_dout_pcc1 {
			nvidia,pins = "dap4_dout_pcc1";
			nvidia,function = "i2s4";
			nvidia,pull = <TEGRA_PIN_PULL_NONE>;
			nvidia,tristate = <TEGRA_PIN_DISABLE>;
			nvidia,enable-input = <TEGRA_PIN_DISABLE>;
		};

		dap4_din_pcc2 {
			nvidia,pins = "dap4_din_pcc2";
			nvidia,function = "i2s4";
			nvidia,pull = <TEGRA_PIN_PULL_UP>;
			nvidia,tristate = <TEGRA_PIN_ENABLE>;
			nvidia,enable-input = <TEGRA_PIN_ENABLE>;
		};

		dap4_fs_pcc3 {
			nvidia,pins = "dap4_fs_pcc3";
			nvidia,function = "i2s4";
			nvidia,pull = <TEGRA_PIN_PULL_NONE>;
			nvidia,tristate = <TEGRA_PIN_DISABLE>;
			nvidia,enable-input = <TEGRA_PIN_DISABLE>;
		};

.
.
.

Best Regards,
Antonio

Hi Antonio,

Per comment #2, please send the output from …

$ sudo grep dmic /sys/kernel/debug/tegra_pinctrl_reg

Regards,
Jon

sudo grep dmic /sys/kernel/debug/tegra_pinctrl_reg[/code]
Bank: 0 Reg: 0x02432000 Val: 0x00006001 → dmic1_clk_pm1
Bank: 0 Reg: 0x02432008 Val: 0x00006049 → dmic1_dat_pm0
Bank: 0 Reg: 0x02432010 Val: 0x00006401 → dmic2_dat_pm2
Bank: 0 Reg: 0x02432018 Val: 0x00006001 → dmic2_clk_pm3
Bank: 0 Reg: 0x02432020 Val: 0x00006002 → dmic4_dat_pm4
Bank: 0 Reg: 0x02432028 Val: 0x0000605a → dmic4_clk_pm5
Bank: 0 Reg: 0x02432004 Val: 0xf0000000 → drive_dmic1_clk
Bank: 0 Reg: 0x0243200c Val: 0xf0000000 → drive_dmic1_dat
Bank: 0 Reg: 0x02432014 Val: 0xf0000000 → drive_dmic2_dat
Bank: 0 Reg: 0x0243201c Val: 0xf0000000 → drive_dmic2_clk
Bank: 0 Reg: 0x02432024 Val: 0xf0000000 → drive_dmic4_dat
Bank: 0 Reg: 0x0243202c Val: 0xf0000000 → drive_dmic4_clk

Sorry, I confused myself because originally, I was unsure if the initial thread was discussing DAP3 or DAP4. For DAP4, can you dump the following …

$ sudo grep dap4 /sys/kernel/debug/tegra_pinctrl_reg
Bank: 0 Reg: 0x02432030 Val: 0x00006400 -> dap4_fs_pcc3
Bank: 0 Reg: 0x02432038 Val: 0x00006458 -> dap4_din_pcc2
Bank: 0 Reg: 0x02432040 Val: 0x00006400 -> dap4_dout_pcc1
Bank: 0 Reg: 0x02432048 Val: 0x00006400 -> dap4_sclk_pcc0

Jon

Hi:

Bank: 0 Reg: 0x02432030 Val: 0x00006400 → dap4_fs_pcc3
Bank: 0 Reg: 0x02432038 Val: 0x00006458 → dap4_din_pcc2
Bank: 0 Reg: 0x02432040 Val: 0x00006400 → dap4_dout_pcc1
Bank: 0 Reg: 0x02432048 Val: 0x00006400 → dap4_sclk_pcc0
Bank: 0 Reg: 0x02432034 Val: 0xf0000000 → drive_dap4_fs
Bank: 0 Reg: 0x0243203c Val: 0xf0000000 → drive_dap4_din
Bank: 0 Reg: 0x02432044 Val: 0xf0000000 → drive_dap4_dout
Bank: 0 Reg: 0x0243204c Val: 0xf0000000 → drive_dap4_sclk

OK, so the pinmux looks fine. To play a WAV file to I2S3, can you try …

amixer -c tegrasndt186ref cset name="I2S4 Mux" "ADMAIF4"
aplay -D hw:tegrasndt186ref,3 <wavfile>

Jon

Ok, but i only want to use these four lines of i2s3 like GPIOs.

That was not clear from what you are asking before. Given that this seems unrelated to $subject matter, I would suggest that you create a new thread on the forum and explicitly state what you are trying to accomplish.

Jon