I2S Capture in Slave Mode on Orin NX

Good evening -

I have a Jetson Orin NX 16GB on a dev kit board, and am using an AES audio receiver (TI DIR9001PWR) connected to the 40pin header on the dev kit. This chip operates as an I2S master, and generates the I2S LRCLK and SCLK, and sends I2S SDATA to the Jetson.

I have verified that the DIR9001 is sending I2S data to the Jetson. Here is what it looks like probed at the Jetson Dev Kit’s pins:

I’ve verified that the sample rate is 48kHz and there are 32 bits per frame:

On the Jetson, I’ve configured the 40-pin header for I2S2 on the required pins:

jetson@ubuntu:~$ sudo /opt/nvidia/jetson-io/config-by-pin.py | grep i2s2
 12: i2s2_sclk
 35: i2s2_fs
 38: i2s2_din
 40: i2s2_dout

And here’s the audio configuration I’m using:

amixer -c APE cset name="ADMAIF1 Mux" I2S2
amixer -c APE cset name="I2S2 codec master mode" cbs-cfs

Running arecord returns no errors, but the resulting .wav file is empty:

jetson@ubuntu:~$ arecord -D hw:APE,0 -r 48000 -f S32_LE -c 2 -d 5 -v test.wav
Recording WAVE 'test.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Stereo
Hardware PCM card 1 'NVIDIA Jetson Orin NX APE' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : S32_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 4096
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 4096
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
jetson@ubuntu:~$ hexdump -C test.wav
00000000  52 49 46 46 24 4c 1d 00  57 41 56 45 66 6d 74 20  |RIFF$L..WAVEfmt |
00000010  10 00 00 00 01 00 02 00  80 bb 00 00 00 dc 05 00  |................|
00000020  08 00 20 00 64 61 74 61  00 4c 1d 00 00 00 00 00  |.. .data.L......|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
001d4c2c

Here are my mixer control settings:
settings.txt (784.0 KB)

Here’s my kernel log:
kernel_log.txt (66.9 KB)

Here’s my device tree log:
dt.log (430.3 KB)

And here’s the result of cat /sys/kernel/debug/regmap/2901100.i2s/registers > ~/reg_dump.txt:
reg_dump.txt (585 Bytes)

Hi
I am reviewing the logs and settings. Meanwhile, could you please provide the pinconf info/dap2?
Is the capture issue present only with CODEC master mode or in slave mode as well?

cat /sys/kernel/debug/pinctrl/2430000.pinmux/pinconf-groups

Hi Dramesh - thank you for the response!

Here’s my pinconf:
pinconf.txt (39.3 KB)

Is the capture issue present only with CODEC master mode or in slave mode as well?

It is only possible to operate the DIR9001 in master mode (i.e., the DIR9001 generates the LRCLK, SCLK, and data signals), so this issue is with that mode.

Thanks in advance for the help!
-Robert

Hi Robert,
Could you please set the mixer control as mentioned below? This sets Tegra I2S in slave mode, while the earlier command sets it in master mode.

amixer -c APE cset name==“I2S2 codec master mode” “cbm-cfm”

Also, could you please dump the list of functions that are currently enabled?
sudo /opt/nvidia/jetson-io/config-by-function.py -l enabled | grep i2s2

Thanks Ramesh -
I set the mixer master mode as you suggested, but this results in an Input/Output Error:

jetson@ubuntu:~$ amixer -c APE cset name="I2S2 codec master mode" "cbm-cfm"
numid=1527,iface=MIXER,name='I2S2 codec master mode'
  ; type=ENUMERATED,access=rw------,values=1,items=3
  ; Item #0 'None'
  ; Item #1 'cbm-cfm'
  ; Item #2 'cbs-cfs'
  : values=1
jetson@ubuntu:~$ arecord -D hw:APE,0 -r 48000 -f S32_LE -c 2 -d 5 -v test.wav
Recording WAVE 'test.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Stereo
Hardware PCM card 1 'NVIDIA Jetson Orin NX APE' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : S32_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 4096
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 4096
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
arecord: pcm_read:2178: read error: Input/output error

This results in an output file with only the header (i.e., no audio data, not even the all zeroes read previously):

jetson@ubuntu:~$ hexdump -C test.wav 
00000000  52 49 46 46 24 4c 1d 00  57 41 56 45 66 6d 74 20  |RIFF$L..WAVEfmt |
00000010  10 00 00 00 01 00 02 00  80 bb 00 00 00 dc 05 00  |................|
00000020  08 00 20 00 64 61 74 61  00 4c 1d 00              |.. .data.L..|
0000002c

I tried then setting the mixer master mode back to cbs-cfs, and the error goes away, and the output .wav file is all zeroes (same result as in my original post).


Also, could you please dump the list of functions that are currently enabled?

Here you go:

jetson@ubuntu:~$ sudo /opt/nvidia/jetson-io/config-by-function.py -l enabled | grep i2s2
   1. i2s2 (12,35,38,40)

Thanks, Robert, for sharing the logs.

It seems that the Tegra I2S controller (slave) has failed to receive the LRCLK and SCLK from the DIR9001 (master). To confirm this, could you please attach the kernel log with I2S2 in codec master mode as suggested? Also, please re-confirm with probes.

amixer -c APE cset name==“I2S2 codec master mode” “cbm-cfm”

Ramesh,

I won’t be able to do the hardware probes until next week, but will confirm at that point that I’m seeing the I2S data at the Jetson’s 40-pin header.

In the meantime, here are the kernel logs after setting master mode to “cbm-cfm” and attempting to record with arecord (receiving the same “input/output error” message).
kernel_log.txt (66.8 KB)

Thanks!
-Robert

Hi Robert,
Thanks. It seems kernel logs capture only the initial 20 seconds and do not capture the full logs…
In case I2S fails to receive the clock from CODEC, you will see “Failed at I2S2_RX sw reset” prints in logs

The audio configuration to use as follows for Tegra I2S in slave mode:-
amixer -c APE cset name=“ADMAIF1 Mux” I2S2
amixer -c APE cset name==“I2S2 codec master mode” “cbm-cfm”

Hi Ramesh -
That kernel log I uploaded represented the entirety of the kernel log - I had just booted the board before running the test, so there were only 20s of history in the log.

Just to double-check, I’ve performed it again, with this output (note a couple of messages about ADMAIF in the kernel log at the end):

jetson@ubuntu:~$ amixer -c APE cset name="ADMAIF1 Mux" I2S2
numid=1264,iface=MIXER,name='ADMAIF1 Mux'
  ; type=ENUMERATED,access=rw------,values=1,items=81
  ; Item #0 'None'
  ; Item #1 'ADMAIF1'
  ; Item #2 'ADMAIF2'
  ; Item #3 'ADMAIF3'
  ; Item #4 'ADMAIF4'
  ; Item #5 'ADMAIF5'
  ; Item #6 'ADMAIF6'
  ; Item #7 'ADMAIF7'
  ; Item #8 'ADMAIF8'
  ; Item #9 'ADMAIF9'
  ; Item #10 'ADMAIF10'
  ; Item #11 'ADMAIF11'
  ; Item #12 'ADMAIF12'
  ; Item #13 'ADMAIF13'
  ; Item #14 'ADMAIF14'
  ; Item #15 'ADMAIF15'
  ; Item #16 'ADMAIF16'
  ; Item #17 'I2S1'
  ; Item #18 'I2S2'
  ; Item #19 'I2S3'
  ; Item #20 'I2S4'
  ; Item #21 'I2S5'
  ; Item #22 'I2S6'
  ; Item #23 'SFC1'
  ; Item #24 'SFC2'
  ; Item #25 'SFC3'
  ; Item #26 'SFC4'
  ; Item #27 'MIXER1 TX1'
  ; Item #28 'MIXER1 TX2'
  ; Item #29 'MIXER1 TX3'
  ; Item #30 'MIXER1 TX4'
  ; Item #31 'MIXER1 TX5'
  ; Item #32 'AMX1'
  ; Item #33 'AMX2'
  ; Item #34 'AMX3'
  ; Item #35 'AMX4'
  ; Item #36 'ARAD1'
  ; Item #37 'AFC1'
  ; Item #38 'AFC2'
  ; Item #39 'AFC3'
  ; Item #40 'AFC4'
  ; Item #41 'AFC5'
  ; Item #42 'AFC6'
  ; Item #43 'OPE1'
  ; Item #44 'SPKPROT1'
  ; Item #45 'MVC1'
  ; Item #46 'MVC2'
  ; Item #47 'IQC1-1'
  ; Item #48 'IQC1-2'
  ; Item #49 'IQC2-1'
  ; Item #50 'IQC2-2'
  ; Item #51 'DMIC1'
  ; Item #52 'DMIC2'
  ; Item #53 'DMIC3'
  ; Item #54 'DMIC4'
  ; Item #55 'ADX1 TX1'
  ; Item #56 'ADX1 TX2'
  ; Item #57 'ADX1 TX3'
  ; Item #58 'ADX1 TX4'
  ; Item #59 'ADX2 TX1'
  ; Item #60 'ADX2 TX2'
  ; Item #61 'ADX2 TX3'
  ; Item #62 'ADX2 TX4'
  ; Item #63 'ADX3 TX1'
  ; Item #64 'ADX3 TX2'
  ; Item #65 'ADX3 TX3'
  ; Item #66 'ADX3 TX4'
  ; Item #67 'ADX4 TX1'
  ; Item #68 'ADX4 TX2'
  ; Item #69 'ADX4 TX3'
  ; Item #70 'ADX4 TX4'
  ; Item #71 'ADMAIF17'
  ; Item #72 'ADMAIF18'
  ; Item #73 'ADMAIF19'
  ; Item #74 'ADMAIF20'
  ; Item #75 'ASRC1 TX1'
  ; Item #76 'ASRC1 TX2'
  ; Item #77 'ASRC1 TX3'
  ; Item #78 'ASRC1 TX4'
  ; Item #79 'ASRC1 TX5'
  ; Item #80 'ASRC1 TX6'
  : values=18
jetson@ubuntu:~$ amixer -c APE cset name="I2S2 codec master mode" "cbm-cfm"
numid=1527,iface=MIXER,name='I2S2 codec master mode'
  ; type=ENUMERATED,access=rw------,values=1,items=3
  ; Item #0 'None'
  ; Item #1 'cbm-cfm'
  ; Item #2 'cbs-cfs'
  : values=1
jetson@ubuntu:~$ arecord -D hw:APE,0 -r 48000 -f S32_LE -c 2 -d 5 -v test.wav
Recording WAVE 'test.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Stereo
Hardware PCM card 1 'NVIDIA Jetson Orin NX APE' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : S32_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 4096
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 4096
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
arecord: pcm_read:2178: read error: Input/output error
jetson@ubuntu:~$ hexdump -C test.wav
00000000  52 49 46 46 24 4c 1d 00  57 41 56 45 66 6d 74 20  |RIFF$L..WAVEfmt |
00000010  10 00 00 00 01 00 02 00  80 bb 00 00 00 dc 05 00  |................|
00000020  08 00 20 00 64 61 74 61  00 4c 1d 00              |.. .data.L..|
0000002c
jetson@ubuntu:~$ sudo dmesg | tail -n 20
[sudo] password for jetson:
[   16.749093] zram1: detected capacity change from 0 to 2032029696
[   16.778978] Adding 1984400k swap on /dev/zram1.  Priority:5 extents:1 across:1984400k SS
[   16.781035] zram2: detected capacity change from 0 to 2032029696
[   16.806953] Adding 1984400k swap on /dev/zram2.  Priority:5 extents:1 across:1984400k SS
[   16.810214] zram3: detected capacity change from 0 to 2032029696
[   16.843007] Adding 1984400k swap on /dev/zram3.  Priority:5 extents:1 across:1984400k SS
[   18.275173] wlan0: authenticate with 90:ca:fa:13:e8:fc
[   18.279689] wlan0: send auth to 90:ca:fa:13:e8:fc (try 1/3)
[   18.294251] wlan0: authenticated
[   18.294879] wlan0: associate with 90:ca:fa:13:e8:fc (try 1/3)
[   18.310756] wlan0: RX AssocResp from 90:ca:fa:13:e8:fc (capab=0x1111 status=0 aid=5)
[   18.312975] wlan0: associated
[   18.347775] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[   18.384490] wlan0: Limiting TX power to 30 (30 - 0) dBm as advertised by 90:ca:fa:13:e8:fc
[   18.503803] nvidia-modeset: Loading NVIDIA UNIX Open Kernel Mode Setting Driver for aarch64  35.5.0  Release Build  (buildbrain@mobile-u64-6519-d7000)  Mon Feb 19 20:34:14 PST 2024
[   18.662797] fuse: init (API version 7.32)
[   18.802222] NVRM rpcRmApiControl_dce: NVRM_RPC_DCE: Failed RM ctrl call cmd:0x731341 result 0xffff:
[   20.183375] Bridge firewalling registered
[   24.251251] tegra210-admaif 290f000.admaif: timeout: failed to disable ADMAIF1_TX
[   42.175452] tegra210-admaif 290f000.admaif: timeout: failed to disable ADMAIF1_TX

I did also verify that the DIR9001 chip is continuing to provide SCLK, SDIN, and FS to the Jetson’s 40-pin header (probed these signals at pins 12, 38, 35 respectively):

Hi Robert,
Thanks for providing the logs. There is no issue with the ADMAIF prints. Could you please share the hw_params during capture along with the clock summary?
cat /proc/asound/card1/<pcm_device>/sub0/hw_params
cat /sys/kernel/debug/clk/clk_summary

Have you tried capturing with 16-bit? "The DIR9001 supports MSB-first PCM data output in 24-bit I2S, 24-bit left justified, 24-bit right justified, or 16-bit right justified form. "

also pinmux dump:
$ sudo busybox devmem 0x02434088 //SOC_GPIO41 - I2S2_SCLK
$ sudo busybox devmem 0x02434090 //SOC_GPIO42 - I2S2_SDATA_OUT
$ sudo busybox devmem 0x02434098 //SOC_GPIO43 - I2S2_SDATA_IN
$ sudo busybox devmem 0x024340a0 //SOC_GPIO44 - I2S2_LRCK

Hi Ramesh,
Here are the hw_params (for both pcm3c and pcm7c, as I’m not sure which corresponds to I2S2), captured while arecord is running:

jetson@ubuntu:~$ cat /proc/asound/card1/pcm3c/sub0/hw_params
closed
jetson@ubuntu:~$ cat /proc/asound/card1/pcm7c/sub0/hw_params
closed

I’m guessing that’s not good that they’re both listed as closed

And here’s the clk summary:
clk_summary.txt (77.9 KB)


Have you tried capturing with 16-bit? "The DIR9001 supports MSB-first PCM data output in 24-bit I2S, 24-bit left justified, 24-bit right justified, or 16-bit right justified form. "

My hardware configuration is for 24-bit I2S format, and you can see in my hardware probing of the I2S stream that there are actually 32 falling edges on the data clock for every LR_CLK transition:

So I think S32_LE is correct? Just for grins I tried 16-bit, and got the same Input/output error:

jetson@ubuntu:~$ arecord -D hw:APE,0 -r 48000 -f S16_LE -c 2 -d 60 -v test.wav
Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Hardware PCM card 1 'NVIDIA Jetson Orin NX APE' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 8192
  period_size  : 2048
  period_time  : 42666
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 2048
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 8192
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
arecord: pcm_read:2178: read error: Input/output error

Finally, here’s the pinmux info:

jetson@ubuntu:~$ sudo busybox devmem 0x02434088
0x00001445
jetson@ubuntu:~$ sudo busybox devmem 0x02434090
0x00000405
jetson@ubuntu:~$ sudo busybox devmem 0x02434098
0x00001455
jetson@ubuntu:~$ sudo busybox devmem 0x024340a0
0x00001445

After looking around a bit more at the /proc/asound/card1/ tree, I realized I may have been looking at the wrong device. Based on the table “Port to Device ID Map” I found here, I had assumed pcm3c or pcm7c would be the correct device. However, after examining the /proc/asound/card1/<pcm_device>/sub0/info for a few of the PCM devices, I realized these correspond to the ADMA interface.

Examining pcm0c, this looks like the one I actually want, since it corresponds to ADMAIF1:

jetson@ubuntu:~$ cat /proc/asound/card1/pcm0c/sub0/info
card: 1
device: 0
subdevice: 0
stream: CAPTURE
id: tegra-dlink-0 XBAR-ADMAIF1-0
name:
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1

Capturing hw_params while running arecord, I see:

jetson@ubuntu:~$ cat /proc/asound/card1/pcm0c/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 1024
buffer_size: 4096

Good news! I started playing around with all of the amixer controls, and I now have capture working. I had to set the FSYNC width correctly, but now I get correct stereo data from the DIR9001. The working config for me is:

amixer -c APE cset name="ADMAIF1 Mux" I2S2
amixer -c APE cset name="I2S2 codec master mode" "cbm-cfm"
amixer -c APE cset name='I2S2 FSYNC Width' 32
arecord -D hw:APE,0 -r 48000 -f S32_LE -c 2 -d 5 -v test.wav

Thanks for the help debugging this!

Glad to hear, thanks for the letting me know!