I cannot set I2S slave mode at JetPack 4.x (both TX2 and Xavier)

Hello,

In the previous project using TX2 (last year), I changed well I2S mode from default master to slave for our application purpose.
At now project doing the similar work using Xavier, however, I cannot change the mode.

My method for changing the mode and validating the result is like this.

  1. modify sound node in the dts file to change into slave mode
  2. compile dts file to dtb file.
  3. flash the dtb file to TX2/Xavier developer kit
  4. play a wav file using alsa aplay util in the developer kit and check if clock/fs signal is quiet (because of no master ic connected)

Then, with TX2 developer kit I have repeated the same experiment over the several versions of JetPack (of course including L4T version associated).

JetPack of TX2 with no problem was old version, but this Xavier JetPack is latest.
So I suspected JetPack version is related with the problem.

The result is as follows:

TX2 JetPack 4.2.2 (+ L4T r32.2.1) => NG
TX2 JetPack 4.2 (+ L4T r32.1) => NG
TX2 JetPack 3.3 (+ L4T r28.2.1) => OK
TX2 JetPack 3.2.1 (+ L4T r28.2.1) => OK

As you know, because Xavier JetPack is supported from v4.2, I could not check JetPack 3.x of Xavier.

Please help me solve the problem in the latest JetPack of both TX2 and Xavier.

For your reference I attach DTS Sound node portion I modified (TX2 case) and the test script for playing wav file in developer kit.

<tegra186-quill-common.dtsi>
rt565x_dai_link: nvidia,dai-link-1 {
link-name = “rt565x-playback”;
cpu-dai = <&tegra_i2s1>;
codec-dai = <&spdif_dit0>;
cpu-dai-name = “I2S1”;
codec-dai-name = “dit-hifi”;
format = “dsp_a”; /org: “i2s”;/
bitclock-master; /org: none/
frame-master; /org: none/
bitclock-inversion; /org: none/
frame-noninversion; /org: none/
bit-format = “s32_le”; /org: “s16_le”;/
bclk_ratio = <1>; /org: <0>;/
srate = <48000>;
num-channel = <16>; /org: <2>;/
tx-mask=<0xFFFF>; /org: none/
rx-mask=<0xFFFF>; /org: none/
ignore_suspend;
name-prefix = “x”;
status = “okay”;
};
nvidia,dai-link-2 {
link-name = “spdif-dit-1”;
cpu-dai = <&tegra_i2s2>;
codec-dai = <&spdif_dit1>;
cpu-dai-name = “I2S2”;
codec-dai-name = “dit-hifi”;
format = “dsp_a”; /org: “i2s”;/
bitclock-master; /org: none/
frame-master; /org: none/
bitclock-inversion; /org: none/
frame-noninversion; /org: none/
bit-format = “s32_le”; /org: “s16_le”;/
bclk_ratio = <1>;
srate = <48000>;
num-channel = <16>; /org: <2>;/
tx-mask=<0xFFFF>; /org: none/
rx-mask=<0xFFFF>; /org: none/
ignore_suspend;
name-prefix = “y”;
status = “okay”;
};
nvidia,dai-link-3 {
link-name = “spdif-dit-2”;
cpu-dai = <&tegra_i2s3>;
codec-dai = <&spdif_dit2>;
cpu-dai-name = “I2S3”;
codec-dai-name = “dit-hifi”;
format = “dsp_a”; /org: “i2s”;/
bitclock-master; /org: none/
frame-master; /org: none/
bitclock-inversion; /org: none/
frame-noninversion; /org: none/
bit-format = “s32_le”; /org: “s16_le”;/
bclk_ratio = <1>;
srate = <48000>;
num-channel = <16>; /org: <2>;/
tx-mask=<0xFFFF>; /org: none/
rx-mask=<0xFFFF>; /org: none/
ignore_suspend;
name-prefix = “z”;
status = “okay”;
};
nvidia,dai-link-4 {
link-name = “spdif-dit-3”;
cpu-dai = <&tegra_i2s4>;
codec-dai = <&spdif_dit3>;
cpu-dai-name = “I2S4”;
codec-dai-name = “dit-hifi”;
format = “dsp_a”; /org: “i2s”;/
bitclock-master; /org: none/
frame-master; /org: none/
bitclock-inversion; /org: none/
frame-noninversion; /org: none/
bit-format = “s32_le”; /org: “s16_le”;/
bclk_ratio = <1>;
srate = <48000>;
num-channel = <16>; /org: <2>;/
tx-mask=<0xFFFF>; /org: none/
rx-mask=<0xFFFF>; /org: none/
ignore_suspend;
name-prefix = “m”;
status = “okay”;
};

<test.sh>

amixer -c tegrasndt186ref cset name=“I2S1 Channels” “16”
amixer -c tegrasndt186ref cset name=“I2S1 Mux” “ADMAIF1”
aplay -D hw:tegrasndt186ref,0 test.wav

Hello!

Yes I believe that this could be a bug. Can you …

$ amixer -c tegrasndt186ref cget name="I2S1 codec master mode"

If this should ‘cbs-cfs’ indicating the I2S is the master, then set …

$ amixer -c tegrasndt186ref cset name="I2S1 codec master mode" "cbm-cfm"

The above mixer control was introduced in a recent releases to allow us to quickly change the mode for testing. However, there is a bug where you do not reflash the entire system, ALSA restore will always restore the previous setting regardless of what is set in device-tree. This will be fixed in the next release.

Regards,
Jon

1 Like

Dear Jon

Thank you for answer.
I’m not at office now so I cannot take an experiment as you informed, but I have a question.

Is the bug in ALSA Mixer utility only?
If I used ALSA api’s in my c program, then would it work based on device tree settings?

So far I have been using ALSA Mixer utility in a script to assign each I2S channel to each ADMAIF, which must be run before executing my audio application.
If the bug you mentioned is related with ALSA utility program only, if I will move the pre-setting using script into my audio program using ALSA’s corresponding api’s, could I avoid this problem before next update of JetPack?

I cannot wait for next update because of urgent schedule of this project.

Regards,
lunalovre

Hello!

The bug I am referring too is not in the ALSA mixer utility but the Tegra machine driver that creates this particular mixer control.

Please note that once you have configured the mixer controls the way you need them, then on reboot the systemd alsa-restore service will save the current settings and restore them on boot.

Regards,
Jon

Dear Jon,

Sorry but I cannot still understand the bug.

Roughly speaking as I understand,
Do you mean that even if I configure a setting at device tree it has no effect because of some reason?
And instead if I configure it through ALSA mixer control, it will remains after next reboots. Is it right?

If so, as for changing master/slave mode, are there properties or options for changing format(dsp_a), bitclock-inversion, bit-format(s32_le), and num-channel(16) in amixer command line.

In fact, I need to change I2S mode to TDM16 slave mode with dsp_a type, bit clock inversion and 32 bit width.

I need even temporary remedy before the next jetpack release. Do you have any idea? or should I wait only?

Regard,
lunalovre

Hello!

The bug is only observed if say you only flash the device-tree blob (DTB). If you flash the entire system this bug will not be seen. The reason being, when you reflash the entire system the file that stores context for restoring the ALSA mixer settings is not present and so the device-tree settings will be used.

Yes there is another mixer control for setting the format …

$ amixer -c tegrasndt186ref cget name="I2S1 codec frame mode"

This bug only impacts the master mode and frame format. Other settings such as bit format and number of channels are fine.

So really, there are two options …

  1. Configure the master mode and frame format via mixer controls.
  2. Reflash the entire system so that the settings are read from device-tree on first boot.

It should be easy to workaround this.

Regards,
Jon

Dear Jon,

Thank you for help.
Both methods you guided have effect!

Continuing my work further, if any other problem is met (probably) I will open the new issue.

Regards,
Lunalovre