Main controller: imx8mp
Kernel: Linux 5.4.70
Sound card: SGTL5000
Application: Moves data into the DMA buffer using mmap.
Fault symptom: When the application plays audio for a period of time, the kernel displays the error message: fsl-sai 30C3000.sai: isr:Transmit. The "underrun detected" message is printed on the screen and corresponds to the specific kernel file: ./kernel/kernel-5.4.70/sound/soc/fsl/fsl_sai.c.
...........
if(flags & FSL_SAI_CSR_FEF) {
dev_dbg(dev,"isr:Transmit underrun detected\n");
/* FIFO reset for safety */
xcsr |= FSL_SAI_CSR_FR;
}
...........
At the same time, use the command `cat /proc/interrupts | grep sdma` to check the DMA interrupt count for the sound card and stop it from increasing.
In the current code setup, is it true that when the FIFO goes underrun, the FIFO state becomes abnormal, which in turn causes the DMA to malfunction?
Looking at the IMX8MP specifications, there's a description like this: FCONT: IMX8MP PRM document 14.4.2.7.3. When FIFO Continue on Error is enbaled, the FIFO continues transmitting data following an underrun without software intervention. To ensure that data transmits in the correct order, the transmitter continues from the same word number in the frame that caused the FIFO to inderrun, but only after new data writes to transmit FIFO ........................................
According to this configuration in the specification, in this situation, after the DMA goes underrun, can it still work normally? As long as the DMA moves the data to the FIFO, it can continue playing the previous sound, instead of the previous DMA malfunctioning and the FIFO going underrun?
Hi @zhuliushun
1. The understanding of FCONT is basically correct, but FCONT is not a fundamental solution.
2. The root cause is that the TX FIFO feeding speed is less than the consumption speed. You can check this to see if it is the case.
3. Consider installing the following two patches:
LKML: Shengjiu Wang: [PATCH] ASoC: fsl_sai: Enable 'FIFO continue on error' FCONT bit
ASoC: fsl_sai: Remove unnecessary FIFO reset in ISR - Patchwork
Best Regards,
Zhiming
Hello @Zhiming_Liu
Yes, the reason for this problem is that the FIFO filling speed is slower than the FIFO data consumption speed. And FIFO filling is based on DMA.
1. Current debugging has revealed that when the FIFO is depleted, it undergoes an underrun, and the DMA also stops working, thus preventing the FIFO from being refilled.
2. After applying the two patches from the post, debugging revealed that the FIFO still underruns, and DMA is not working .
In the interrupt callback function fsl_sai_isr() in fsl_sai.c, the values of xcsr and tcr4 are printed. See below for details:
fsl-sai 30c30000.sai scsr :status:0xd0170c01
fsl-sai 30c30000.sai isr: transmit inderrun detected,tcr4: 0x18010f3a
When the malfunction occurred, the above-mentioned printing kept refreshing the screen.
3. Based on the findings in 2, bit[28] in tcr4 =1, FCONT is enabled .
4. Regarding my problem: audio file playback freezes (FIFO underrun, DMA not working, stuck). My desired solution is: when the FIFO underruns, preserve the hardware data and move the current state without resetting, while the DMA functions normally . When data becomes available in the buffer (filled by the application using mmap), the DMA (based on the DMA request from the FIFO) moves the data to the FIFO , allowing the audio file to continue playing. Is this feasible?