Signal distortion on the audio codec's headphone out

Hi @rafael.tx,
We have updated to BSP 5.7.0+build.20. Then we have checked if it took the codec of the Dhalia board by default and we have seen that it still uses the one of the Verdin Development board. We have modified the fdt_board variable in the u-boot as we did here:

and the alsamixer no longer recognizes the device. Could you tell me how to modify the image so that it takes the Dahlia codec.

Best regards,
Julián

I noticed this as well and I don’t know yet why this happens. In any case, you can play audio by setting the device manually on the command line:

# pass audio card to alsamixer
alsamixer -c imx8mmwm8904

# play with this audio card
aplay -c 2 -Dsysdefault:CARD=imx8mmwm8904 440_hz_10min.wav

Hi @rafael.tx,
I have tested with both sample rates (44.1 kHz and 48 kHz) and indeed the error disappears when the 48 kHz sample rate is used.

root@verdin-imx8mm-06902245:~# aplay -c 2 -Dsysdefault:CARD=imx8mmwm8904 ./sound/sine_440Hz_44kHz.wav
root@verdin-imx8mm-06902245:~# dmesg|tail
[10654.269144] wm8904 3-001a: CLK_SYS is 12288000Hz
[10654.269148] wm8904 3-001a: Selected CLK_SYS_RATIO of 256
[10654.269152] wm8904 3-001a: Selected SAMPLE_RATE of 44100Hz
[10654.269156] wm8904 3-001a: Selected BCLK_DIV of 80 for 1536000Hz BCLK
[10654.269161] wm8904 3-001a: LRCLK_RATE is 34
[10654.269167] wm8904 3-001a: Set deemphasis 0
[10654.290749] wm8904 3-001a: Restoring DC servo state
[10654.301121] wm8904 3-001a: DC servo ready
[10654.302651] wm8904 3-001a: Restoring DC servo state
[10654.313125] wm8904 3-001a: DC servo ready
root@verdin-imx8mm-06902245:~# aplay -c 2 -Dsysdefault:CARD=imx8mmwm8904 ./sound/sine_440Hz_48kHz.wav
root@verdin-imx8mm-06902245:~# dmesg|tail
[10672.292231] wm8904 3-001a: CLK_SYS is 12288000Hz
[10672.292235] wm8904 3-001a: Selected CLK_SYS_RATIO of 256
[10672.292239] wm8904 3-001a: Selected SAMPLE_RATE of 48000Hz
[10672.292242] wm8904 3-001a: Selected BCLK_DIV of 80 for 1536000Hz BCLK
[10672.292247] wm8904 3-001a: LRCLK_RATE is 32
[10672.292256] wm8904 3-001a: Set deemphasis 0
[10672.308665] wm8904 3-001a: Restoring DC servo state
[10672.323003] wm8904 3-001a: DC servo ready
[10672.324576] wm8904 3-001a: Restoring DC servo state
[10672.339025] wm8904 3-001a: DC servo ready

Now, if we do the same test with BSP 5.6 or earlier versions, the sine of one of the channels is distorted for any of the sampling frequencies. How is this explained? What has changed from BSP5.6 to BSP 5.7 regarding the audio codec?

It is true that if the clock divider is not adequate, a shift in frequency of the audio signal spectrum would occur. It would be like reproducing a signal at a different sample rate than the one at which it was synthesized. But this would not explain the distortion of the electrical signal as shown above.

I await your news.
Best regards,
Julián

I will try to explain again why the distortion occurs if the sampling rate has not been properly configured. I2S will change the polarity of the LRCK line one bit before the LSB of the current word is transmitted.
Please consider this picture, taken from the I2S on the dahlia while playing a file sampled at 44.1KHz:

44khz_bad

And now compare it to the same dahlia playing a file sampled at 48KHz:

As you can see, if we skip the LSB of the last word and then count 16 bits, we end up aligning the end of the 16th bit with the toggle of the LRCK on the bad example. The receiver doesn’t expect this: it wants to receive the MSB of the next word only on the next bit. Because of that, all the bits of the right channel are shifted when read by the receiver, and this is what causes the distortion. If you look at the file that was sampled at 48KHz, the same process works as expected.

Here’s another example of the dahlia playing a 44.1KHz sampled file with the clock properly configured:

You can see that in this case the bits are also aligned the way they are supposed to, and the distortion doesn’t happen. We’re in the process of evaluating a solution for the sample rate clock configuration and if we don’t find any negative side effects it will be merged into our kernel.

Hi @rafael.tx,
I understand your point of view but I find it difficult to understand how the i2s interface stops working correctly when the transmission clock frequency varies. It is a great mystery to me.
What is clear to me is that with BSP 5.6 the i2s transmission failed at both 44.1 kHz and 48 kHz. What have you changed about the BSP so that it stops failing at 48 kHz?
I don’t know if you’re aware, but we also found another problem with this codec: the amplitude of the sound changes after the SOM returns from sleep.
Please keep me aware of this situation since the audio codec is a fundamental piece of our product.
Best regards,

It doesn’t fail because the sample rate varies, it fails because we cannot get a clock sufficiently close to 44.1Khz. Because of that, the data sampled on the line and the LRCK are not properly aligned and this causes the shifts I already described.

I didn’t test 48KHz with older BSP versions so I cannot say why it would work there. But I also looked for changes in the relevant code between the two versions and could not find anything that changed.

I don’t know if you’re aware, but we also found another problem with this codec: the amplitude of the sound changes after the SOM returns from sleep.

Yes, I’m aware of that and we will try to work on that at some point.

Hello @jbruno, we merged a fix to this issue into our kernel. You can see the change here:
https://git.toradex.cn/cgit/linux-toradex.git/commit/?h=toradex_5.4-2.3.x-imx&id=36bbfb9f706b23cdf1bd203389fc39b2d8cd2f64

This works because now the MCLK is properly set to an integer multiple of the FS when audio is going to be played, instead of being fixed like it was before. You can apply the change and test it yourself. This modification will be available on the next BSP 5 (unplanned now) and BSP 6 releases.

Regards,
Rafael