Direct passthrough between two I2S ports

I am attempting to send audio stripped from captured HDMI input using a Toshiba TC358840 directly to a Cirrus CS4344.
The TC358840 is I2S master while the CS4344 is I2S slave.

Copying the data using a GStreamer pipeline and alsasrc+alsasink works well, but introduces a 40ms delay.

Directly connecting via amixer has no effect
amixer sset 'I2S1 Mux' 'I2S3'

I have searched through the forum but there is no example that matches this apparently simple case.

Hi richardsearle,

How are you configuring Tegra I2S3 in Slave mode?

To configure I2S3 in Slave mode and connect to I2S1, please use below controls:

amixer sset “I2S3 codec master mode” “cbm-cfm”
amixer sset ‘I2S1 Mux’ ‘I2S3’

Kindly attach below register dumps if you still see issues (after setting above controls):

cat “/sys/kernel/debug/regmap/tegra210-i2s.0/registers” for I2S1
cat “/sys/kernel/debug/regmap/tegra210-i2s.2/registers” for I2S3

Thanks,
Sharad

I am using I2S4 (per SW numbering)

I tried setting the audio source into master mode: DT, devmem2 and amixer
sudo devmem2 0x02432030 w 0x00006440
sudo devmem2 0x02432038 w 0x00006450
sudo devmem2 0x02432040 w 0x00006440
sudo devmem2 0x02432048 w 0x00006440

amixer -c 1 cset name='I2S4 codec master mode' 1
amixer -c 1 cset name='I2S4 codec frame mode' 1

The final configuration is then:
sudo grep dap4 /sys/kernel/debug/tegra_pinctrl_reg
Bank: 0 Reg: 0x02432030 Val: 0x00006450 → dap4_fs_pcc3
Bank: 0 Reg: 0x02432038 Val: 0x00006450 → dap4_din_pcc2
Bank: 0 Reg: 0x02432040 Val: 0x00006400 → dap4_dout_pcc1
Bank: 0 Reg: 0x02432048 Val: 0x00006440 → dap4_sclk_pcc0

The commands that work are then
amixer cset -Dhw:1 name=“ADMAIF4 Mux” ‘I2S4’
gst-launch-1.0 alsasrc device=hw:CARD=tegrasndt186ref,DEV=3 ! ‘audio/x-raw, format=S16LE, rate=48000, channels=2’ ! alsasink device=hw:1,0

I tried the commands you referenced, but they fail
$ amixer sset “I2S3 codec master mode” “cbm-cfm”
amixer: Mixer attach default error: No such device

Registers are:
cat tegra210-i2s.0/registers
00: 00000000
04: XXXXXXXX
08: 00000000
0c: XXXXXXXX
10: XXXXXXXX
14: 00000003
18: 00000000
1c: 00000000
20: 03113300
24: 00000100
28: 00000000
2c: 00000000
30: 00000000
34: 00000000
38: 00000000
3c: 00000000
40: 00000000
44: XXXXXXXX
48: 00000000
4c: XXXXXXXX
50: XXXXXXXX
54: 00000003
58: 00000000
5c: 00000000
60: 00113300
64: 00000100
68: 00000000
6c: 00000000
70: 00000000
74: 00000000
78: 00000000
7c: 00000000
80: 00000001
84: 00000000
88: 00000001
8c: 00000000
90: XXXXXXXX
94: 00000000
98: 00000000
9c: 00000000
a0: 1f000403
a4: 0000000f
a8: 00000000
ac: 00000000
b0: 00000000

cat tegra210-i2s.3/registers
00: 00000000
04: XXXXXXXX
08: 00000000
0c: XXXXXXXX
10: XXXXXXXX
14: 00000003
18: 00000000
1c: 00000000
20: 00007700
24: 00000100
28: 00000000
2c: 00000000
30: 00000000
34: 00000000
38: 00000000
3c: 00000000
40: 00000000
44: XXXXXXXX
48: 00000000
4c: XXXXXXXX
50: XXXXXXXX
54: 00000003
58: 00000000
5c: 00000000
60: 00113300
64: 00000100
68: 00000000
6c: 00000000
70: 00000000
74: 00000000
78: 00000000
7c: 00000000
80: 00000001
84: 00000000
88: 00000001
8c: 00000000
90: XXXXXXXX
94: 00000000
98: 00000000
9c: 00000000
a0: 1f000003
a4: 0000000f
a8: 00000000
ac: 00000000
b0: 00000000

From register dumps looks like I2S1 and I2S4 both are not enabled. We have few further questions:

Did you get the dump after setting : amixer sset ‘I2S1 Mux’ ‘I2S4’ ?
What is the capture/playback data configuration for I2S1 and I2S4? is it 48K, 16bit, 2ch for both?

This usecase requires extra control setting/BSP change and we are in process of checking it at our end. We shall get back as soon as we have an update.

[Working on a remote setup is making things difficult. Please expect some delay.]

The dump was before the amixer setup (as memory serves).
I will reconfirm

The configuration is intended to be 48K, 16bit, 2ch for both.

Can you clarify this failure?
$ amixer sset “I2S3 codec master mode” “cbm-cfm”
amixer: Mixer attach default error: No such device

All the amixer sset commands fail.
Device is running R32.3.1

I currently have very limited access to the test hardware for the next 2-3 weeks.

Thanks for the quick response.

I explicitly set all the configurations that appear relevant on I2S1 and I2S4.
No sound is generated from I2S1

amixer -c 1 sset  'I2S1 Channels' 2
amixer -c 1 sset  'I2S1 Mux' 'I2S4'
amixer -c 1 sset  'I2S1 Sample Rate' 48000
amixer -c 1 sset  'I2S1 codec bit format' 16
amixer -c 1 sset  'I2S1 codec frame mode' 'i2s'
amixer -c 1 sset  'I2S1 codec master mode' 'cbs-cfs'
amixer -c 1 sset  'I2S1 input bit format' 16
amixer -c 1 sset  'I2S4 Channels' 2
amixer -c 1 sset  'I2S4 Sample Rate' 48000
amixer -c 1 sset  'I2S4 codec bit format' 16
amixer -c 1 sset  'I2S4 codec frame mode' 'i2s'
amixer -c 1 sset  'I2S4 codec master mode' 'cbm-cfm'
amixer -c 1 sset  'I2S4 input bit format' 16

Dumping the entire amixer configuration for those two ports

Simple mixer control 'I2S1 BCLK Ratio',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 2147483647
  Mono: 1 [0%]
Simple mixer control 'I2S1 Capture mono to stereo conv',0
  Capabilities: enum
  Items: 'None' 'ZERO' 'COPY'
  Item0: 'None'
Simple mixer control 'I2S1 Capture stereo to mono conv',0
  Capabilities: enum
  Items: 'None' 'CH0' 'CH1' 'AVG'
  Item0: 'None'
Simple mixer control 'I2S1 Channels',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 16
  Mono: 2 [12%]
Simple mixer control 'I2S1 Loopback',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'I2S1 Mux',0
  Capabilities: enum
  Items: 'None' 'ADMAIF1' 'ADMAIF2' 'ADMAIF3' 'ADMAIF4' 'ADMAIF5' 'ADMAIF6' 'ADMAIF7' 'ADMAIF8' 'ADMAIF9' 'ADMAIF10' 'ADMAIF11' 'ADMAIF12' 'ADMAIF13' 'ADMAIF14' 'ADMAIF15' 'ADMAIF16' 'I2S1' 'I2S2' 'I2S3' 'I2S4' 'I2S5' 'I2S6' 'SFC1' 'SFC2' 'SFC3' 'SFC4' 'MIXER1-1' 'MIXER1-2' 'MIXER1-3' 'MIXER1-4' 'MIXER1-5' 'AMX1' 'AMX2' 'AMX3' 'AMX4' 'ARAD1' 'AFC1' 'AFC2' 'AFC3' 'AFC4' 'AFC5' 'AFC6' 'OPE1' 'SPKPROT1' 'MVC1' 'MVC2' 'IQC1-1' 'IQC1-2' 'IQC2-1' 'IQC2-2' 'DMIC1' 'DMIC2' 'DMIC3' 'DMIC4' 'ADX1-1' 'ADX1-2' 'ADX1-3' 'ADX1-4' 'ADX2-1' 'ADX2-2' 'ADX2-3' 'ADX2-4' 'ADX3-1' 'ADX3-2' 'ADX3-3' 'ADX3-4' 'ADX4-1' 'ADX4-2' 'ADX4-3' 'ADX4-4' 'ADMAIF17' 'ADMAIF18' 'ADMAIF19' 'ADMAIF20' 'ASRC1-1' 'ASRC1-2' 'ASRC1-3' 'ASRC1-4' 'ASRC1-5' 'ASRC1-6'
  Item0: 'I2S4'
Simple mixer control 'I2S1 Playback FIFO threshold',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 270582939648 - 63
  Mono: 270582939714 [0%]
Simple mixer control 'I2S1 Playback mono to stereo conv',0
  Capabilities: enum
  Items: 'None' 'ZERO' 'COPY'
  Item0: 'None'
Simple mixer control 'I2S1 Playback stereo to mono conv',0
  Capabilities: enum
  Items: 'None' 'CH0' 'CH1' 'AVG'
  Item0: 'None'
Simple mixer control 'I2S1 Sample Rate',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 192000
  Mono: 48000 [25%]
Simple mixer control 'I2S1 codec bit format',0
  Capabilities: enum
  Items: 'None' '16' '32'
  Item0: '16'
Simple mixer control 'I2S1 codec frame mode',0
  Capabilities: enum
  Items: 'None' 'i2s' 'right-j' 'left-j' 'dsp-a' 'dsp-b'
  Item0: 'i2s'
Simple mixer control 'I2S1 codec master mode',0
  Capabilities: enum
  Items: 'None' 'cbm-cfm' 'cbs-cfs'
  Item0: 'cbs-cfs'
Simple mixer control 'I2S1 fsync width',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 255
  Mono: 31 [12%]
Simple mixer control 'I2S1 input bit format',0
  Capabilities: enum
  Items: 'None' '16' '32'
  Item0: '16'
Simple mixer control 'I2S4 BCLK Ratio',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 2147483647
  Mono: 1 [0%]
Simple mixer control 'I2S4 Capture mono to stereo conv',0
  Capabilities: enum
  Items: 'None' 'ZERO' 'COPY'
  Item0: 'None'
Simple mixer control 'I2S4 Capture stereo to mono conv',0
  Capabilities: enum
  Items: 'None' 'CH0' 'CH1' 'AVG'
  Item0: 'None'
Simple mixer control 'I2S4 Channels',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 16
  Mono: 2 [12%]
Simple mixer control 'I2S4 Loopback',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [off]
Simple mixer control 'I2S4 Mux',0
  Capabilities: enum
  Items: 'None' 'ADMAIF1' 'ADMAIF2' 'ADMAIF3' 'ADMAIF4' 'ADMAIF5' 'ADMAIF6' 'ADMAIF7' 'ADMAIF8' 'ADMAIF9' 'ADMAIF10' 'ADMAIF11' 'ADMAIF12' 'ADMAIF13' 'ADMAIF14' 'ADMAIF15' 'ADMAIF16' 'I2S1' 'I2S2' 'I2S3' 'I2S4' 'I2S5' 'I2S6' 'SFC1' 'SFC2' 'SFC3' 'SFC4' 'MIXER1-1' 'MIXER1-2' 'MIXER1-3' 'MIXER1-4' 'MIXER1-5' 'AMX1' 'AMX2' 'AMX3' 'AMX4' 'ARAD1' 'AFC1' 'AFC2' 'AFC3' 'AFC4' 'AFC5' 'AFC6' 'OPE1' 'SPKPROT1' 'MVC1' 'MVC2' 'IQC1-1' 'IQC1-2' 'IQC2-1' 'IQC2-2' 'DMIC1' 'DMIC2' 'DMIC3' 'DMIC4' 'ADX1-1' 'ADX1-2' 'ADX1-3' 'ADX1-4' 'ADX2-1' 'ADX2-2' 'ADX2-3' 'ADX2-4' 'ADX3-1' 'ADX3-2' 'ADX3-3' 'ADX3-4' 'ADX4-1' 'ADX4-2' 'ADX4-3' 'ADX4-4' 'ADMAIF17' 'ADMAIF18' 'ADMAIF19' 'ADMAIF20' 'ASRC1-1' 'ASRC1-2' 'ASRC1-3' 'ASRC1-4' 'ASRC1-5' 'ASRC1-6'
  Item0: 'None'
Simple mixer control 'I2S4 Playback FIFO threshold',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 270582939648 - 63
  Mono: 270582939714 [0%]
Simple mixer control 'I2S4 Playback mono to stereo conv',0
  Capabilities: enum
  Items: 'None' 'ZERO' 'COPY'
  Item0: 'None'
Simple mixer control 'I2S4 Playback stereo to mono conv',0
  Capabilities: enum
  Items: 'None' 'CH0' 'CH1' 'AVG'
  Item0: 'None'
Simple mixer control 'I2S4 Sample Rate',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 192000
  Mono: 48000 [25%]
Simple mixer control 'I2S4 codec bit format',0
  Capabilities: enum
  Items: 'None' '16' '32'
  Item0: '16'
Simple mixer control 'I2S4 codec frame mode',0
  Capabilities: enum
  Items: 'None' 'i2s' 'right-j' 'left-j' 'dsp-a' 'dsp-b'
  Item0: 'i2s'
Simple mixer control 'I2S4 codec master mode',0
  Capabilities: enum
  Items: 'None' 'cbm-cfm' 'cbs-cfs'
  Item0: 'cbm-cfm'
Simple mixer control 'I2S4 fsync width',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 255
  Mono: 31 [12%]
Simple mixer control 'I2S4 input bit format',0
  Capabilities: enum
  Items: 'None' '16' '32'
  Item0: '16'

The registers are then
cat /sys/kernel/debug/regmap/tegra210-i2s.0/registers
00: 00000001
04: 00000000
08: 00000000
0c: 00000005
10: 0000000c
14: 00000003
18: 00000000
1c: 00000000
20: 03113300
24: 00000100
28: 00000000
2c: 00000000
30: 00000000
34: 00000000
38: 00000000
3c: 00000000
40: 00000000
44: 00000000
48: 00000000
4c: 00000002
50: 00000000
54: 00000003
58: 00000000
5c: 00000000
60: 00007700
64: 00000100
68: 00000000
6c: 00000000
70: 00000000
74: 00000000
78: 00000000
7c: 00000000
80: 00000001
84: 00000000
88: 00000001
8c: 00000000
90: 00000c00
94: 00000000
98: 00000000
9c: 00000000
a0: 1f000403
a4: 0000000f
a8: 00000000
ac: 00000000
b0: 00000000

cat /sys/kernel/debug/regmap/tegra210-i2s.3/registers
00: 00000000
04: 00000000
08: 00000000
0c: 00000002
10: 00000000
14: 00000003
18: 00000000
1c: 00000000
20: 00007700
24: 00000100
28: 00000000
2c: 00000000
30: 00000000
34: 00000000
38: 00000000
3c: 00000000
40: 00000001
44: 00000000
48: 00000000
4c: 00000001
50: 0000000e
54: 00000003
58: 00000000
5c: 00000000
60: 00113300
64: 00000100
68: 00000000
6c: 00000000
70: 00000000
74: 00000000
78: 00000000
7c: 00000000
80: 00000001
84: 00000000
88: 00000001
8c: 00000000
90: 0000000e
94: 00000000
98: 00000000
9c: 00000000
a0: 1f000003
a4: 0000000f
a8: 00000000
ac: 00000000
b0: 00000000

This command does generate the expected sound
gst-launch-1.0 alsasrc device=hw:CARD=tegrasndt186ref,DEV=3 ! 'audio/x-raw, format=S16LE, rate=48000, channels=2' ! queue ! alsasink device=hw:1,0

The registers are unchanged from above

Hi richardsearle,

Sorry for the delay. We were testing the scenario on our setup remotely and hence the delay.

As we understand, you are trying to loopback I2S4 data to I2S1. This can be achieved by a simple DT change along with setting up the path via mixer controls as below:

  1. Please modify DT as ber below patch: Configure I2S4 as sync clock for I2S1
    tegra186-soc-base.dtsi.txt (1.7 KB)

  2. Build, Flash and Reboot

  3. Set controls to configure I2S1 and I2S4

amixer -c 1 cset name=“I2S1 codec master mode” “cbs-cfs”
amixer -c 1 cset name=“I2S1 codec frame mode” “i2s”
amixer -c 1 cset name=“I2S4 fsync width” “31”
amixer -c 1 cset name=“I2S4 BCLK Ratio” “1”
amixer -c 1 cset name=“I2S4 codec master mode” “cbm-cfm”
amixer -c 1 cset name=“I2S4 codec frame mode” “i2s”

  1. Connect I2S1 and I2S4

amixer -c 1 cset name=“I2S1 Mux” “I2S4”

This will enable I2S4 to I2S1 loopback within Tegra. Since I2S1 is using I2S4 as sync clock, no need to set anything else. Please try it at your end and share your observations.

Thanks,
Sharad

Looks like some formatting error in the given command, as copy pasting the commands on target giving below error.

amixer -c 1 cset name=“I2S1 codec master mode” “cbs-cfs”
amixer: Cannot find the given element from control hw:1

Richardsearle,
Please correct the formatting error by using double/single quote.

The amixer commands matched my requirements:

  1. is24 is audio input
  2. i2s1 is audio output
  3. i2s4 is clock master
  4. i2s1 is clock slave

However the dtsi patch has the reverse.

Considering Tegra I2S4 operating as Slave and Tegra I2S1 configured as Master

Is that simply an error in the comment?

No, There is no error.

Considering Tegra I2S4 operating as Slave and Tegra I2S1 configured as Master, this involves two different clock domains by default, which may lead to glitches incase there are drifts in clock sources (Tegra PLLA and Toshiba). And hence, it’s recommended to have single source for clocks for both I2S transactions.

Toshiba TC358840 chip is configured as master, which is connected to I2S4 (slave mode), it should drive I2S1 as well. Hence I2S1 is configured to use I2S4 as sync clock which is actually generate by Toshiba chip in your case. This clock is used by I2S1 (in master mode) for audio data transfer to Cirrus CS4344. Hope things are clear now.

Thanks,
Sharad

1 Like

Thanks for clarification. I was thinking of I2Sn as the connected device rather than the TX2i port.

amixer -c 1 cset name=“I2S1 Mux” “I2S4”
Has no effect. The sound is not heard on I2S1 output.

I confirmed the DTB was updated and noticed an oddity:

I2S1 == i2s@2901000

BEFORE PATCH
assigned-clock-parents = <0x10 0xf6>;
assigned-clocks = <0x10 0x4f>;

AFTER PATCH
assigned-clock-parents = <0x10 0xf7 0x10 0x26c>;
assigned-clocks = <0x10 0x4f 0x10 0xf7>;

i.e. there are now 4 clocks rather than 2.

I could not find any other dts entries that assign clocks to I2S1.
There are clocks specified under tegra_sound in platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-common.dtsi

I determined a gstreamer pipeline must run to output sound.
But that pipeline does not need to actually do anything
The following has a source that generates silence!

gst-launch-1.0 -e audiotestsrc wave=silence num-buffers=10000 ! 'audio/x-raw, format=S16LE, rate=48000, channels=2' ! queue ! alsasink device=hw:1,0

Obviously one clock for normal DT and two clocks for the modified DT.

gstreamer is presumably enabling the I2S1, which can then generate output directly from I2S4. That is actually quite acceptable.

I am still seeing some form of clock sync problem.
Stopping and restarting gstreamer will sometimes cause the D/A to generate a stuttering noise.

I tried replacing the TEGRA186_CLK_PLL_A_OUT0 under clocks with TEGRA186_CLK_I2S4_SYNC_INPUT, but that had no effect

Ideally I2S1 should get enabled immediately after setting “amixer -c 1 cset name=“I2S1 Mux” “I2S4””. We need your help in debugging/fixing this issue on your HW.

Can you follow the steps again as mentioned in comment above and dump below logs/registers immediately after that (please don’t run gstreamer on I2S1)?

cat /sys/kernel/debug/clk/clk_summary
cat /sys/kernel/debug/regmap/tegra210-i2s.0/registers
cat /sys/kernel/debug/regmap/tegra210-i2s.3/registers
dmesg

Now Trigger gstreamer and dump below logs again:

cat /sys/kernel/debug/clk/clk_summary
cat /sys/kernel/debug/regmap/tegra210-i2s.0/registers
cat /sys/kernel/debug/regmap/tegra210-i2s.3/registers

Kindly share all logs as per the sequence mentioned above.

Thanks,
Sharad

The attached initial.txt is after running your commands and before runing gst.
gst.txt is the state while gstreamer is running.

The gstreamer command is
gst-launch-1.0 -e audiotestsrc wave=silence ! ‘audio/x-raw, format=S16LE, rate=48000, channels=2’ ! queue ! alsasink device=hw:1,0

The difference between the two files is

177c177
initial: ape 2 2 158666650 158666650 0 0

gst ape 3 3 158666650 158666650 0 0
185c185
initial: pll_a_out0 2 2 49151992 49152000 0 0

gst pll_a_out0 3 3 49151992 49152000 0 0
187c187
initial: aud_mclk 0 0 12287998 12288000 0 0

gst aud_mclk 1 1 12287998 12288000 0 0
211c211
initial: ahub 1 1 49151992 49152000 0 0

gst ahub 2 2 49151992 49152000 0 0
361c361
initial: 0c: 00000001

gst 0c: 00000003

initial.log (33.7 KB) gst.log (33.7 KB)

Hi richardsearle,

From the logs looks like you are using AUD_MCLK in your design. Which is not enabled without running gstreamer. Could you please try enabling it through console with below command before setting controls for I2S1 and I2S4 (details in the comment) :

echo 1 > /sys/kernel/debug/bpmp/debug/clk/aud_mclk/state

This will force enable AUD_MCLK and should resolve playback issue. Rest all looks fine.

Thanks,
Sharad

That solved the problem.
It also eliminated an intermittent problem where the D/A would not cleanly synchronize when the stream started.

Thank you for the information

Turns out the DT patch: Configure I2S4 as sync clock for I2S1
Is not needed

We still recommend using the DT patch to configure I2S4 as sync clock for I2S1. There could be glitches if I2S1 and I2S4 are operating with different clock sources.