I2S audio in left-justified mode

Hello everyone,

On a Jetson Nano board I’m struggling with capturing audio over i2s when switching operating mode from i2s to left-justified.

The setup is a Jetson Nano board connected to a ADC through the 40 Pin headers I2S4. The ADC is Master and the Jetson board is slave using the audio master clock from the jetson board. The audio format of the ADC is two’s complement, MSB first, left-justified mode, 24 bit PCM, 96 kHz.

When the dai-link operates in i2s mode samples are captured as expected. However as the ADC audio is left-justified one bit of each sample is lost.
When I change the mode of the dai-link to left-justified (setting format = ‘left_j’ in the device tree) no data is captured resulting in 0 valued samples (i2s communication on the input side is ongoing).

Am i missing something with the configuration when switching from i2s to left-justified mode (is it enough just changing the format property)?

Are there any hints on how to debug this issue?

And has the Jetson Nano board been tested in this particular configuration?

The board is running L4T: # R32 (release), REVISION: 4.3, GCID: 21589087, BOARD: t210ref, EABI: aarch64, DATE: Fri Jun 26 04:38:25 UTC 2020

More details can be provided if needed.

Thanks,
Jonas

Hello!

I don’t believe that there is anything else that needs to change given that the ADC is the master. Obviously, we are missing something, but we have tested this, so I don’t see why it would not work.

How many channels are you capturing? Is there a single channel or multiple? If there are multiple channels, are the 24-bits outputted back to back without any spacing?

What command are you using the capture the audio both in I2S mode and left-j mode?

With regard to the bit being lost in I2S mode, is this the MSB? The I2S mode does use a 1-bit delay, where as left-j uses 0-bit delay by delay. This is configured in the I2S driver.

Also just so that you are aware you can change the format between I2S and left-j using the following userspace command …

$ amixer -c tegrasndt210ref sget "I2S4 codec frame mode"
$ amixer -c tegrasndt210ref sset "I2S4 codec frame mode" i2s
$ amixer -c tegrasndt210ref sset "I2S4 codec frame mode" left-j

Regards,
Jon

Hi Jon

Thanks for the answer.

I’m capturing one channel but the input signal contains two. One with data, the other zero padded. I’m using the ‘Capture stereo to mono conv’ option (but have also done testing omitting this option capturing stereo):

amixer -c tegrasndt210ref cset name='I2S4 Capture stereo to mono conv' CH1

and capturing both modes with arecord:

arecord -vv -D hw:tegrasndt210ref,0 -r 96000 -f S32_LE -t raw -c 1 -d 5 capture.raw

The frame width is 32 bits and the last 8 bits are zero-padding. This is followed by a 32 bit zero padded frame (the other channel).

I want to clarify on the ‘one bit is lost’ statement. What I observe is that the value of each sample is doubled (left-shifted) when operating in i2s mode. I’m not exactly sure where this happens but it has the effect that 1 bit of the input signal resolution is lost.

EDIT:
After taking a closer look at my input signal I’ve noticed that every input sample has the 2 MSB equal. So the left-shift is caused by the offset 1 in i2s mode and no sudden jump from positive to negative (and vice versa) are observed because of this.

Thanks for the commands.

Best regards,
Jonas

After looking in through the driver code. I notice that the offset is not the only difference. The LRCK polarity is inverted compared to i2s mode (Set to high instead of low).

I can’t see how this would cause any issues. But maybe I’m missing something.

Best regards,
Jonas

Yes the LRCK is a different polarity. Per the I2S spec, in I2S mode the start of frame is when the LRCK transitions from high to low where the left channel is sent during the low period of the LRCK and the right channel is sent during the high period.

For left-j mode, just like the dsp-a/b mode, the start of frame is indicated by the LRCK transitioning high. Most devices will transition the LRCK high for 1 bit clock, but I don’t think it matters how long the pulse is, but just that the frame starts on the rising edge of the LRCK.

The polarity of the LRCK can be changed in device-tree via the frame-inversion property.

Regards,
Jon