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

Hello @jbruno ,

Were you able to test the solution from @rafael.tx ?

Best regards,
Josep

Hi @josep.tx,
To test this solution we must first migrate our image to version 5.7.0 of your BSP and we are having some compatibility problems with our libraries. As soon as we have resolved it, we will inform you of the results of our tests.
Have you already made this modification in any of your BSPs?
Best regards,
Julián

Hi @jbruno, as I mentioned before, this change is already merged into the kernels for both BSP 5 and BSP 6. It will be a part of the next release versions of both BSP’s.
Please keep in mind that we don’t have plans to release a new BSP 5 version at the moment.

Hi @rafael.tx ,
Your issue tracker does not indicate this change for any quarterly BSP. Could you tell me in which versions of your BSP it has been implemented.

Best regards,

It’s going to be a part of BSP 6.1 release. It’s also already merged on our kernel branches for BSP 5. There’s no BSP 5 release planned at the moment, and because of that, you’ll need to update the SRCREV of the kernel manually to get a BSP 5 build with this change included.

Hi @rafael.tx ,
We have installed your multimedia reference image with BSP 6.1 and when trying to play audio again we ran into the problem that the sound card is not configured for the WM8904. I have repeated the steps that you have indicated here and it does not work.

Could you tell me how I should configure the system so that it works with the WM8904 codec?

Best regards,

On the Verdins we have an automatic sound configuration procedure that runs the first time you boot a freshly installed image. This procedure checks what device tree is running (dahlia vs dev board) and copies the correct asound.conf file to /etc. After this is done, there’s no check anymore so the configuration stays like this.
In order to get a properly working audio on the dahlia (wm8904 codec), the boot procedure needs to be stopped in u-boot right after installing the image and then setting the correct device tree to be used:

setenv fdtfile imx8mp-verdin-wifi-dahlia.dtb

If this is done on the first boot the system will be properly setup.

I would guess that this is the reason you don’t have the codecs available. To fix it, you can setup the correct device tree in u-boot:

setenv fdtfile imx8mp-verdin-wifi-dahlia.dtb

And you will also need to replace the asound.conf file with the one from dahlia. The correct configuration file can be downloaded from here:
https://git.toradex.cn/cgit/meta-toradex-nxp.git/tree/recipes-bsp/alsa-state/alsa-state/verdin-imx8mp/asound-dahlia.conf

You can copy this file to your module, overwriting /etc/asound.conf. After a reboot, your audio codec should be available.

We’re working on a better solution for this selection of the correct audio codec configuration depending on which of our carrier boards is being used.

Regards,
Rafael

Hi @rafael.tx,
We have already correctly configured the sound card, thanks for the information. We have done sound tests, using different sampling frequencies, and we have not observed any type of distortion in the waveforms. Also the failure to change volume after suspension has disappeared. Therefore I can confirm that this bug is resolved in your BSP 6.1 and therefore I close the case.
Thank you very much for all the time and effort you have put into it and congratulations to the team!
Best regards,
Julián