Stange behavior of TX2 Audio Processing Engine

Hi,

We connected a DSP (dirana3) as audio inputs to I2S3 and I2S4 of TX2 and connect a speaker as audio output to I2S1. Shown as below. See the attached device tree related to sound.

dirana3 -----------> (i2s3)
   |                         TX2  (i2s1) -----------> speaker (A2B)
   ----------------> (i2s4)

Here i2s3/4 are configured as masters and i2s1 as slave.

I want to configure the audio processing such that the output of dirana3 goes to TX2 and I am able to hear it on the speaker. The input to I2s3 and I2S4 may be muxed. I have so far not had much luck in doing so.

Can you suggest a workable configuration using amixer.

As a starter, I tried this scenario:

#Configure speaker
amixer sset "MIXER1-1 Mux" "ADMAIF1"
amixer sset "AMX1-1 Mux" "MIXER1-1"
amixer sset "I2S1 Mux" "AMX1"
amixer sset "Adder1 RX1" on
amixer sset "Adder1 RX2" on
amixer sset "Mixer Enable" on

#play a wav file

aplay -D hw:0,0 -c 6 -f S32_LE /root/n51441.wav

I can not hear the sound, and the scope shows no fsync on I2S1 bus. Some debugging shows the audio driver complains the following (I put some lines in kernel/sound/soc/soc/soc-dapm.c …)

root@nvidia:~# aplay -D hw:0,8 -c 6 -f S32_LE /root/n51441.wav
Warning: format is changed to S16_LE
aying WAVE '/root/n51441.wav' :
Signed 16 bit Little Endian, Rate 44100 Hz, Channels 6
[  111.130498]  tegra210_i2s_runtime_resume ============>
[  111.146679] snd_soc_dai_link_event source_p name (null). sink name (null)
[  111.156272] source_p->source name I2S1 DAP Transmit. sname I2S1 DAP Transmit
[  111.165447] source_p->sink name I2S1 DAP Transmit-d Playback. sname (null)
[  111.172396] sink_p->source name I2S1 DAP Transmit-d Playback. sname (null)
[  111.179367] sink_p->sink name d Playback. sname d Playback     <----------------------  # 1
[  111.184950]  tegra210_i2s_hw_params ============> DAP, 8
[  111.190251]  ===> tegra210_i2s_hw_params format SNDRV_PCM_FORMAT_S32_LE
[  111.196964]  ===> tegra210_i2s_hw_params srate 0
[  111.201659]  ===>  frame_format TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE
[  111.208455] tegra210_i2s_set_slot_ctrl =====> 8, ff, ff
[  111.213707] tegra210_i2s_hw_params ============> -1, 1023, 0, 0, 32, 8
[  111.220225] tegra210-i2s tegra210-i2s.0: Can't set channel bit count
[  111.226589] tegra210-i2s tegra210-i2s.0: ASoC: can't set DAP hw params: -22
[  111.233539] tegra186-snd-p2382 sound_ref: ASoC: PRE_PMU: I2S1 DAP Transmit-d Playback event failed: -22
[  111.242938] snd_soc_dai_link_event source_p name (null). sink name (null)
[  111.249818] source_p->source name I2S3 DAP Transmit. sname I2S3 DAP Transmit
[  111.256960] source_p->sink name I2S3 DAP Transmit-x Playback. sname (null)
[  111.263942] sink_p->source name I2S3 DAP Transmit-x Playback. sname (null)
[  111.270889] sink_p->sink name x Playback. sname x Playback    <--------------------- # 2
[  111.276472]  tegra210_i2s_hw_params ============> DAP, 8
[  111.281771]  ===> tegra210_i2s_hw_params format SNDRV_PCM_FORMAT_S32_LE
[  111.288486]  ===> tegra210_i2s_hw_params srate 48000
[  111.293525]  ===>  frame_format TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE
[  111.300323] tegra210_i2s_set_slot_ctrl =====> 8, ff, ff
[  111.305562] tegra210_i2s_hw_params ============> 255, 1023, 12288000, 48000, 32, 8
[  111.313115] tegra210_i2s_set_slot_rate =====> 12288000
.....
aplay: pcm_write:1939: write error: Input/output error

I don’t understand why there are two “routes” (#1 and #2), one having the wrong setting (srate = 0).

For an experiment, I removed I2S3/4/6 from the dts (see the attached) and left only I2S1, then configure the same way and play the same file. Everything is fine then:

root@nvidia:~# aplay -D hw:0,8 -c 6 -f S32_LE /root/n51441.wav
Warning: format is changed to S16_LE
aying WAVE '/root/n51441.wav' :
Signed 16 bit Little Endian, Rate 44100 Hz, Channels 6
[  566.997855] snd_soc_dai_link_event source_p name (null). sink name (null) 
{  567.010028] source_p->source name I2S1 DAP Transmit. sname I2S1 DAP Transmit 
[  567.022560] source_p->sink name I2S1 DAP Transmit-d Playback. sname (null) 
[  567.034156] sink_p->source name I2S1 DAP Transmit-d Playback. sname (null) 
[  567.043726] sink_p->sink name d Playback. sname d Playback 
[  567.051916]  tegra210_i2s_hw_params ============> DAP, 8
[  567.057243]  ===> tegra210_i2s_hw_params format SNDRV_PCM_FORMAT_S32_LE 
[  567.063933]  ===> tegra210_i2s_hw_params srate 44100 
[  567.068991]  ===>  frame_format TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE
[  567.075783] tegra210_i2s_set_slot_ctrl =====> 8, ff, ff
[  567.081003] tegra210_i2s_hw_params ============> 255, 1023, 11289600, 44100, 32, 8
[  567.088577] tegra210_i2s_set_slot_rate =====> 11289600

Looks like I2S3/4 are interfering with I2S. Any insight and recommendations?

Thanks a lot.

Jin

tegra186-sound.dts.txt (16.3 KB)
tegra186-sound-one-i2s.dts.txt (15.1 KB)

Hello Jin,

Just so that I understand, do you intended to mix both I2S3 and I2S4 inputs and send to the I2S1 or do you just need to mux either I2S3 or I2S4 to I2S1? In other words, are I2S3/4 active at the same time?

To begin with to simplify matters, if you want play to I2S1 then you should just …

amixer sset 'I2S1 Mux' 'ADMAIF1'
aplay -D hw:0,0 -c 6 -f S32_LE /root/n51441.wav

If you want to route the audio captured from I2S3 to I2S1 then you can try …

amixer sset 'ADMAIF1 Mux' 'I2S3'
amixer sset 'I2S1 Mux' 'I2S3'
arecord -D hw:tegrasndt186ref,0 -c 6 -r 44100 -f S32_LE cap.wav

I don’t think that you need to involve the MIXER or AMX unless you specifically need to mix or multiplex the audio. However, the AMX will require more configuration if you need to use it. I would need to check on if the MIXER is configured correctly. However, you should be able to test the audio paths using the above.

Regards,
Jon

Jon,

Thanks so much. Yes, we may need to mux I2S3/4. I do have a related question. In the sound_ref section of the dts file, there is this routing config shown below. I never figured out what is means; how this relates to audio routing in terms of input/out. In my case, I2S3/I2S4 ->demux->mix->mux-> I2S1, etc. Can you shed some light to it.

nvidia,audio-routing = "Headphone-x", "x OUT", "x IN", "LineIn-x", 
"Headphone-y", "y OUT", "y IN", "LineIn-y", 
"Headphone-d", "d OUT", "d IN", "LineIn-d", 
"BT-out", "b OUT", "b IN", "BT-in", 
"EAVB-out", "ADSP EAVB Transmit", "ADSP EAVB Receive", "EAVB-in";

And also, I see the slot maps for adx and amx shown below. How to read them? Are they related to the routing above.

nvidia,amx1-slot-map = <0x100 0x101 0x200 0x201 0x10100 0x10101 0x10200 0x10201 0x20100 0x20101 0x20200 0x20201 0x30100 0x30101 0x30200 0x30201 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0>;
nvidia,adx1-slot-map = <0x100 0x101 0x200 0x201 0x10100 0x10101 0x10200 0x10201 0x20100 0x20101 0x20200 0x20201 0x30100 0x30101 0x30200 0x30201 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0>;

Thanks again, Jon. You have been very helpful.

Jin

Hi Jin,

This routing describes how the audio jacks are connected to the different audio components. So in the above you will see that the board has a few different 'Headphone’jacks, ‘LineIn’ jacks, etc that are connected to the various codec outputs/inputs. This is necessary to complete the audio routing for the board.

These are used for programming the AMX/ADX to map their inputs to outputs. Programming the AMX via device-tree is not necessary and can be completely configured from userspace and therefore I do not recommend configuring the AMX via DT. For an example on how to use/configure the AMX please see …

https://devtalk.nvidia.com/default/topic/1044333/jetson-tx2/microphone-array-using-i2s-on-tx2/post/5304848/#5304848

Currently, we have to configure the ADX via DT, however, I have plans to add similar controls for the ADX so we can program from userspace and avoid using DT for configuring it. There is another thread here about using the ADX …

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

Regards,
Jon