Using the I2S Interfaces for Audio Output

I have connected I2S-0 to an external audio codec (Freescale SGTL5000). This also includes the audio master clock and I2C_GP0. The codec has an internal reset therefore I did not connect GPIO19_AUD_RST.

The codec does not show up as a device once the system is booted. I’ve tried the following commands to find the codec but it is not present:

cat /proc/asound/car*/co* | grep Codec
cat /proc/asound/car*/co*/* | head

I’ve also tried alsamixer with no luck.

When I monitor the I2S and master clock lines using an oscilloscope I notice there is no activity on these lines at all (not during boot, reset, or once the system has booted into Ubuntu).

How does the Jetson TX1 module discover audio codecs over I2S? Should this be automatic or do I need to make software changes?

I wish I could give you an answer, but I have no way to test anything at the moment (no oscilloscope, no i2s chip). At some future time I plan to create a surround sound audio breakout, but can’t do so right now…I imagine when that time comes I’ll have exactly this question. I’d personally like to see more information on the topic.

I suspect a comparison with USB and HDMI audio might at least partly clarify things. If you look at HDMI audio channels, this is hardware which is always there and likely set up with some other driver to generate an “I’m here” event, e.g., video driver load triggers audio codec detect event associated with video session owner; on the other hand, USB audio triggers an event which causes another driver to load if the driver thinks it can handle the audio device. In both cases, an event from another driver triggers audio driver load, and associates the audio with an X11 user session. I’m guessing that piggy-backing off of the HDMI audio start event is what you need (assuming your i2s is otherwise complete, e.g., 3.3V I/O, clocks correct, so on).

Hi tronpopcans,

From HW perspective, for TX1, GPIO19_AUD_RST is for codec reset and GPIO20_AUD_INT is for audio codec detection. Generally TX1 generate a reset signal to codec, then codec feedback an INT when it’s ready. Not sure the power up sequence of the codec you chose, but there should be interrupt signal output too.

Does anyone know if NVIDIA has its own I2S audio test board that it uses to verify the J21 audio connector on the dev kit motherboard? How does NVIDIA verify the J21 header when boards are manufactured? Is it strictly has JTAG type test to verify connectivity or do they functionally test (I2S) as well?

This ties into what linuxdev was saying with the “I’m here” event.

Unfortunately the codec I am using does not have an external reset input pin or an interrupt output pin.

As for GPIO20_AUD_INT operation, will pulling this pin LOW be enough to tell the JTX1 module that the codec “is here” or do I need a falling edge event on this pin after the reset (GPIO19_AUD_RST) has been de-asserted?

If you have no hardware to generate an interrupt, you might find the location in the kernel source where audio CODEC reset is generated, and essentially code a surrogate software interrupt to do the same thing (perhaps only enabled when a firmware dts Boolean setting exists and is true).

Hi guys

I have a similiar question.

I need audio 5.1 in the Jetson TX2, and according with the specs, the TX2 has I2S Outputs. By the moment I only have stereo though a codec PCM1690 (the other two connectors dont work). As a next step, I want to confirm an I2S signal output with an osciloscope.

In the forum, I ride about modify the Data Tree, but I don’t know how to modify the audio lines in the document. On the other hand, I also read that I only have to modify the configuration of the audio mixer .Can you give me some suggestions?

Thanks in advance

I don’t use any codec. I hope to see the signal on MCLK when I am playing. But I saw the signal on MCLK is constant about 1.8V。 What’s wrong with the signal?

Hi,
Have you checked [System Configuration] -> [Tegra ASoC Driver for Jetson TX1 and TX2] in document?
https://developer.nvidia.com/embedded/dlc/l4t-documentation-28-2-ga

You should need to make modification in device tree.

I use the sources which version is R24.2. I changed gpio as you said.

hi,
We support I2S connecting to audio codec. What is the purpose that no audio codec is connected?

Hi DaneLLL
I connect a ADC to tx1. The ADC is simple. I hope to see right signals on MCLK, SCLK and LRCK when I play music. I modify GPIO to sfio. The signal on LRCK is true, but the signals are flase on MCLK and SCLK. I think there are wrong in gpiolib-of.c. I can’t find gpiod_hog. Can you help me?

Hi DaneLLL

Finally I tried with a simple stereo decoder as an Adafruit UDA1334A and I have stereo audio by the I2S port in the J21 Header (Devkit). My first test was in a costume board with the PCM1690.

In this test, I only hoped two audio streams (L and R) during an 5.1 audio playback, but I am listening all the channels combined like stereo.

My idea was to test 5.1 audio with a stereo DAC (First front L and F channels, next Rear L and F channels and later Center and SW), but as I said, I have all the channels by the unique I2S port.

Is there any way to configure 2 channels though each I2S port like

I2S0 -> Front Left and Front Right
I2S1 -> Read Left and Rear Right
I2S2 -> Center ans SW

I dont know if this is the best way to achieve 5.1 audio in the Jetson.

Please can you help me?

Thanks!

Hello!

Ideally you would use a 5.1 codec and then send all 6 channels in a TDM stream from a single I2S interface to the codec. Each I2S interface can support upto 16 channels in TDM mode (ie. dsp-a/b modes).

However, it is also possible to do what you are asking using the ADX module (audio demultiplexer). The ADX can take a input stream of N channels (where N is between 1 and 16) and split into up to 4 output streams of M channels (where M is between 1 and 16). So you could have …

ADMAIF --> ADX --> |
----------------------| --> ADX Out1 --> I2S0
----------------------| --> ADX Out2 --> I2S1
----------------------| --> ADX Out3 --> I2S2

(sorry if the digram is not clear this editor is not brilliant!)

Unfortunately, examples/documentation for using the ADX is very lacking and it is a bit of a pain to configure (requires both driver and device-tree changes). The best example, I can point you to right now is the following …

https://devtalk.nvidia.com/default/topic/1031552/jetson-tx2/i2s-tdm-adx-demux/1

The above thread is using the ADX to do the reverse of what you are asking, but there is no reason why it cannot be used the other way around.

In future L4T releases we are looking to simplify how the ADX is configured as well as provide better documentation/examples.

Hope this helps.

Regards,
Jon

Hi jonathanh, thanks for your answer

I decided to try with audio 5.1 from the Jetson using TDM through I2S0.

Actually we have two boards (a devkit to test and a costume board with others peripherals).

In the costume board we have a FPGA between a Jetson and a codec PCM1690. At this moment, physically all the I2S pins are connected to a codec trough the FPGA, and we have stereo output from the codec already.

If we play a 5.1 audio via vlc or youtube, all the channels (6) are played in one of the three outputs board (stereo L/R).

I was viewing the Device Tree maybe we have to modify some lines as ‘num-channel’

nvidia,dai-link-1 {
			link-name = "rt565x-playback";
			cpu-dai = <0xce>;
			codec-dai = <0xcf>;
			cpu-dai-name = "I2S1";
			codec-dai-name = "dit-hifi";
			format = "i2s";
			bitclock-slave;
			frame-slave;
			bitclock-noninversion;
			frame-noninversion;
			bit-format = "s16_le";
			bclk_ratio = <0x0>;
			srate = <0xbb80>;
			num-channel = <0x2>;
			ignore_suspend;
			name-prefix = [78 00];
			status = "okay";
			linux,phandle = <0x120>;
			phandle = <0x120>;
		};

In addition, if we use an Ubuntu audio configuration tool, only have two channels

https://drive.google.com/open?id=1GdD3XMRK9H9urr86eHQZtHYWlr1OE1gE

I am reviewing the documentation but I don’t find the process to modify the audio configuration.

Thanks in advance!

By the way, as well as using a hardware module, such as the ADX in Tegra, to demux the stream, it should also be possible for pulseaudio/alsa to do this as well. The ALSA ‘multi’ plugin can be used to do this, for example see the section ‘Plugin: Multiple streams to One’ in …

https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html

If you want to play all 5.1 channels via a single I2S interface, then instead of using the ‘multi’ plugin we can use the ‘plug’ plugin to define the ‘surround51’ profile for the ‘Analog Output’ soundcard. To do this add the following file to the root file-system and reboot the board …

$ cat /usr/share/alsa/cards/tegra-snd-t186r.conf 
#
#  ALSA configuration for the Tegra186 APE soundcard
#

<confdir:pcm/surround51.conf>

tegra-snd-t186r.pcm.surround51.0 {
        @args [ CARD ]
        @args.CARD { type string }
        type plug
        slave.pcm {
                type hw
                card $CARD
                device 1
                channels 6
        }
}

After the board reboots, you should be able to select the ‘surround51’ profile for the ‘Analog Output’ soundcard under the ‘Sound’ settings in the desktop manager.

These plugins tell pulseaudio/ALSA what profiles are supported by the card and so to support certain configurations it maybe necessary to add more plugins for the card.

Unfortunately, I don’t have a 5.1 audio codec to test this and so the above is not fully validated but will hopefully provide some guidance.

For further reading on configuring ALSA please see …

http://www.volkerschatz.com/noise/alsa.html

Regards,
Jon

Hi Jonathanh, I appreciate your help

I’ve tested this plugin configuration and it works. Now, the Surround 5.1 option is avalible in the Ubuntu audio configuration tool. The problem is that I dont have audio when I choose this option, only works if I choose stereo output (with stereo option, the pcm1690 works perfectly). I measured the data pins with an oscilocope before the PCM1690 and confirm that no output have a signal, only in the clock pins.

According to the last answer, to have 5.1 audio, if I use the Pulse Audio is not necessary configure the TDM option or do I need to make other additional configuration?

Thanks ind advance.

https://drive.google.com/open?id=1yHq-ffqkqV8zGh3hwq3yZO8Df_EEJVeZ

Hello!

So to use the I2S interface in TDM mode will require you to update the DT file. You will need to set the ‘format’ under the ‘nvidia,dai-link-1’ node to ‘dsp_a’ or ‘dsp_b’ (which ever your codec supports). You should be able to test the I2S interface in TDM mode by executing to play a tone on each channel …

$ speaker-test -D hw:tegrasndt186ref,0 -c 6 -r 48000 -F S16_LE -t sine -f 500

If you were going to use the ‘multi’ plugin as opposed to use TDM, then it would not be necessary to configure the I2S interfaces for TDM just regular I2S (with 2 channels per interface) is fine.

Regards,
Jon

Hi Jon

I got it, then if I use multi plugin, multiples I2S will be used to stream 5.1 audio (2 channels per I2S). I misunderstood, I thought that all the channels were still going to be sent by a unique I2S port (as TDM).

Firstly, I wil try using a pulse plugin but TDM is also interesting.

I my costume board I am using 4 I2S (from 1 to 4). Then, if I choose 5.1 audio in the configuration tool, how can indicate to the Jetson this configuration

I2S1 -> L / R
I2S2 -> FL / FR
I2S3 -> C / LFE

I saw that the amixer tool can configure the I2S port with commands as :

amixer -c tegrasndt186ref sset 'I2S1 Mux' 'ADMAIF1'

But in my case, how can I link each 2 audio channels of ADMAIF1 source with each I2S port. Would this allow me to listen to 5.1 audio from youtube or VLC?

Thanks in advance!

Hi again Jon,

I tried with a TDM way now and have other questions lol

I was reading the forum and made the next process (5.1 audio still doesnt work)

Modify the device tree (tegra186-quill-p3310-1000-c03-00-base.dtb), format and fsync-width

nvidia,dai-link-1 {
			link-name = "rt565x-playback";
			cpu-dai = <0xce>;
			codec-dai = <0xcf>;
			cpu-dai-name = "I2S1";
			codec-dai-name = "dit-hifi";
			format = "dsp_a";
			bitclock-slave;
			frame-slave;
			bitclock-noninversion;
			frame-noninversion;
			bit-format = "s16_le";
			bclk_ratio = <0x0>;
			srate = <0xbb80>;
			num-channel = <0x6>;
			ignore_suspend;
			name-prefix = [78 00];
			status = "okay";
			linux,phandle = <0x120>;
			phandle = <0x120>;
		};
i2s@2901000 {
			compatible = "nvidia,tegra210-i2s";
			reg = <0x2901000 0x100>;
			nvidia,ahub-i2s-id = <0x0>;
			clocks = <0xd 0x4f 0xd 0xf6 0xd 0x269 0xd 0xf7>;
			clock-names = "i2s1", "pll_a_out0", "ext_audio_sync", "audio_sync";
			pinctrl-names = "dap_active", "dap_inactive";
			pinctrl-0;
			pinctrl-1;
			fsync-width = <0x0>;
			status = "okay";
			linux,phandle = <0xce>;
			phandle = <0xce>;
		};

Later, I used the amixer tool

amixer -c tegrasndt186ref cset name="I2S1 Mux" "ADMAIF1"

Finally, I used speaker-test

speaker-test -D hw:tegrasndt186ref,0 -c 6 -r 48000 -F S16_LE -t sine -f 500

Is the process correct?

Thanks!