Capturing i2s audio from tc358743

Greetings,

I have a HDMI to CSI bridge board with a Toshiba tc358743. I’ve been able to capture video now I’m working on capturing audio. The chip sends the audio out via i2s over 4 pins sck (bit clock) , wfs (word clock), sd (data), osck ( oversampling).

I’ve read you can configure the pins on the 40 pin header for this by modifying the dtb.

I’ve tried using the jetson-io.py tool but the problem is that it rebuilds the dtb from scratch. Since I’m using a custom dtb which has the configuration for the tc358743 compiled into it, that method doesn’t work.

I’ve modified the tegra194-p3668-all-p3509-0000-hdr40.dts in the source code as it seemed to have the configuration for he 40 pin header. Pins 12, 35, 38, 40 I modified like this.

pin12 {
                                        nvidia,function = "i2s5";
                                        nvidia,pins = "dap5_sclk_pt5";
                                        nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
                                        nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                        nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                                        nvidia,lpdr = <TEGRA_PIN_DISABLE>;
                                };

I recompiled the dtb and loaded it onto the Xavier NX but some questions I have now are:

  1. How do I know the pins on the 40 pin header are configured correctly?
    In other words, how do I know the changes I made in the tegra194-p3668-all-p3509-0000-hdr40.dts were applied?

  2. Since I just configured each pin for i2s5 but nothing further, how do I know which pin is the clock line versus the data line?

  3. I’ve seen some people use i2s2 and i2s3 but when I used the jetson-io tool it used i2s5. Is there a difference between all of these?

Thanks in advance for the help!

Hi edward.dow,

Preferred Solution:

https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/hw_setup_jetson_io.html#wwpID0EKHA has
clear instructions for creating custom device tree overlay.

Alternate Solution:

Generate ovelay dtbo usig below command

sudo /opt/nvidia/jetson-io/config-by-function.py -o dtbo i2s5

Apply the overlay on your current kernel dtb using command below and flash the new kernel dtb

fdtoverlay -i <current_kernel.dtb> -o <new_kernel.dtb> <overlay.dtbo>

To answer your questions in specific

How do I know the pins on the 40 pin header are configured correctly?

sudo /opt/nvidia/jetson-io/config-by-function.py -l enabled
Above command shall inform if i2s5 is enabled

Since I just configured each pin for i2s5 but nothing further, how do I know which pin is the clock line versus the data line?

Header screen of Jetson-IO tool shall reflect the function of each pin after it is configured
https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/asoc_driver.19.2.html#wwpID0E0XX0HA also has these details

I’ve seen some people use i2s2 and i2s3 but when I used the jetson-io tool it used i2s5. Is there a difference between all of these?

I2S5 is available on 40-pin header for Xavier NX.
Refer https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/asoc_driver.19.2.html#wwpID0E0XX0HA for I2S’s available
on other headers

NOTE: tegra194-p3668-all-p3509-0000-hdr40.dts is used by Jetson-IO. Do not modify manually

For more details, checking https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/hw_setup_jetson_io.html# in detail will help

Thanks

@atalambedu
Thanks for all the information about this! I did the following:

Made the i2s5 overlay using this

sudo /opt/nvidia/jetson-io/config-by-function.py -o dtbo i2s5

Applied the overlay to my custom dtb file

fdtoverlay -i <current_kernel.dtb> -o <new_kernel.dtb> <overlay.dtbo>

Moved the <new_kernel.dtb> in place of the <current_kernel.dtb> and rebooted

Once rebooted I checked it

> sudo /opt/nvidia/jetson-io/config-by-function.py -l enabled
> The following functions are enabled on the 40-pin header:
>  1. i2s5

Once I verified i2s was enabled I connected to the 40 pin header:

Bridge Board → 40 pin Header
SD → DIN pin 38
SCK → SCLK pin 12
WFS → FS pin 35

Next I got the name of the card:

# arecord -L
null
    Discard all samples (playback) or generate zero samples (capture)
pulse
    PulseAudio Sound Server
default
    Tegra APE Soundcard (jetsonxaviernxa,0)
music
demixer
voice
aux_plug
music_and_voice
sysdefault:CARD=**jetsonxaviernxa**
    jetson-xaviernx-ape, 
    Default Audio Device

Then I set up the mixer to use the card

amixer -c jetsonxaviernxa cset name="I2S2 Mux" I2S5

Last I tried to record audio:

> `arecord -D hw:jetsonxaviernxa,0 -r 48000 -c 2 -f S16_LE junk.wav`



It produced a wav file but there’s no sound when I play it back on my PC with VLC. A few thoughts:

  1. I may have not set everything up correctly?
  2. There is no audio coming from the bridge board?
  3. I’m using the wrong commands to record audio?

Hi edward.dow,

Ensure that bridge board is sending I2S data by probing with oscilloscope. Once the bridge board is confirmed to be sending data, try below mixer settings and capture the data

amixer -c jetsonxaviernxa cset name=“ADMAIF1 Mux” I2S5
arecord -D hw:jetsonxaviernxa,0 -r 48000 -c 2 -f S16_LE junk.wav

0 in “jetsonxaviernxa,0” refers to ADMAIF1. So it needs to be configured to receive data from I2S5

Encourage to refer https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/asoc_driver.19.2.html#wwpID0E06M0HA for undertstanding control settings and path setup

Thanks

@atalambedu

I probed the bridge board with an Oscope but to my surprise I’m not getting any readings for the clock, data or word clock on the i2s headers. These should all be outputs. I would assume when I am capturing video these outputs would be sending data? Toshiba data sheet does not specify how these work exactly… only that they are outputs. The chip is a ball grid array so I have to assume the traces to the headers are wired up.

What is interesting is that I do have a signals from both the FS (35) and SCLK (12) from the Xavier. I was thinking these would be input pins since the ones from the chip/bridge board are output. Am I thinking about this incorrectly?

By the way, I’m using a separate system to build kernels, drivers and the device tree. Instead of building the overlay and then applying it to the dtb, can I include the dts somewhere in the source code so it gets built into the dtb? For example…the device tree portion for the bridge board uses a dtsi file that gets pulled into the dtb when built.

Thanks for all the help with this!

Hi edward.dow,

Signals are available on FS and SCLK from Xavier as I2S operates in master mode by default.

Device tree can be modified either through overlay or override(dtsi) and you can choose whichever way is convenient and suitable for your usecase

Thanks

@atalambedu
Thanks for the info.
I took a look at the spec sheet for the chip and it says i2s “Support Master Clock mode only”. I’m thinking the chip needs to be the master and the Xavier would be the slave device on the i2s, but I’m not sure. At this point it doesn’t seem like it would make much difference as I’m not getting any signals from the i2s anyway.

Hi edward.dow,

FYI, Jetson I2S supports both master and slave mode. However, I undertsand that you are yet to get signals from bridge board. If your queries are answered for now, you can close this thread as solved

Thanks

@atalambedu

The only other question I have is how do you change the Jetson to support slave mode on i2s?

Other than that I’d say the thread is closed.

Hi edward.dow,

Use below command to configure Jetson I2S5 in slave mode

amixer -c jetsonxaviernxa cset name="I2S5 Codec Master Mode" "cbm-cfm"

Another way through DT is mentioned in “Codec as I2S Master/Slave” subsection at link

Thanks

@atalambedu
I finally found an alternate source for the I2S signal. Now I am able to verify the I2S source with an Oscope.

I was able to set the Jetson in slave mode with:

amixer -c jetsonxaviernxa cset name="I2S5 codec master mode" "cbm-cfm"

Apparently the name is case sensitive.

When I record I just get loud clicking/static noise. The device is outputting at a rate of 48000 and format of signed 24 bit big endian. When I try and use S24_BE for the format it tells me:

`arecord: set_params:1299: Sample format non available
Available formats:

Am I reading this correctly?
Is there anyway to make more formats available? Possibly different codec drivers?

Thanks again for the help!

Hi edward.dow,

There is no direct way for capturing 24 bit big endian data.

But before we try the indirect ways, could you try offline conversion of recorded S24_LE data (Note that S24_LE is signed 24-bit little-endian integer, packed into a 32-bit integer so that the 8 most significant bits are ignored) to 24 bit big endian and play once to ensure there is no other issue. apart from endian difference.

Please attach both waveforms for our reference as well

Thanks

@atalambedu

Thanks for the thoughts on this. It seems strange to me that most of the chips are sending the I2S data in a MSB/big endian format but the Jetson/arecord will only accept a LSB/little endian format. How are developers handling this?

Do you know of any tools to do this?

Hi edward.dow,

We did not receive such queries earlier.

SOX utility should help in offline conversion. Refer example command below

sox in_S24_BE.wav -L out_S24_LE.wav

Ensure your input data is S24_BE

Thanks

@atalambedu

Thanks for the suggestion of of using SOX for a conversion utility.

So, the problem that I think I’m having is that the I2S data is being transmitted as big endian but the only option with arecord or ffmpeg is to capture it as little endian.

What is produced is a .wav file that is labeled as little endian but has big endian in it.

When I used SOX to do a conversion to little endian I believe it gave me the same file. I’ve attached the two files here.


For fun I tried to convert the file to big endian format but it produces a non loading wav file. ( Just noticed after I uploaded it, the file doesn’t load in the media player)

Not sure what to do at this point.

@atalambedu

So I’ve figured out what is going on. My source audio was encoded with AC3. When I use source audio that is PCM it is working.

I’d like to understand the following:

  1. How I could use different audio encodings seamlessly e.g. it wouldn’t matter if the audio content was PCM or Dolby?

  2. When the I2S comes from the source as big endian how is it converted to little endian format for .wav?

  3. When you configure the audio settings with amixer is it persistent? This seems to be true as I’ve rebooted the Jetson and I didn’t have to make changes.

Thanks for all the help!

Hi edward.dow,

  1. How I could use different audio encodings seamlessly e.g. it wouldn’t matter if the audio content was PCM or Dolby?

I2S interface is intended for PCM playback/capture. AC3 being a compressed format, we are unable to support it over I2S

  1. When the I2S comes from the source as big endian how is it converted to little endian format for .wav?

I2S supported formats can be referred from here. AMX/ADX APE modules help alter the byte map if needed. Refer Usage and Examples section and AMX/ADX sections in link to find more information about the usage of these modules

  1. When you configure the audio settings with amixer is it persistent? This seems to be true as I’ve rebooted the Jetson and I didn’t have to make changes.

Yes it is persistent as alsa controls are stored during shutdown and restored during reboot

Please initiate new forum query if there are other queries as this is already marked as solved

Thanks

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