Failure of eDMA for Some SAI Configurations

cancel
Showing results for 
Search instead for 
Did you mean: 

Failure of eDMA for Some SAI Configurations

Jump to solution
731 Views
paul_katarzis
Contributor III

I am working with an i.MX 8 QXP processor on a custom board. I am creating an ALSA SoC machine driver that connects an SAI to an external codec. For the SAI, we are using the freescale driver implemented in fsl_sai.c, imx-pcm-dma-v2.c, and fsl-edma-v3.c. To test the driver, I am simply using aplay and /dev/urandom to generate noise. All configurations for sample size, number of channels, and sample rates work except for when the number of channels is set to 32. The SAI and codec should be able to support 32 channels.

When I start aplay with 32 channels, there is no audio for exactly 10 seconds and aplay closes with the following error: "aplay: pcm_write:2051: write error: Input/output error". These symptoms indicate that the function snd_pcm_period_elapsed is not being called. This function should be called periodically in the callback function imx_pcm_dma_v2_complete. I added some debug statements into imx_pcm_dma_v2_complete and was able to see that this callback was never being called only when the number of channels is set to 32. Furthermore, I found that the interrupt handler fsl_edma3_tx_handler never executes when the number of channels is set to 32.

Has anyone else seen a similar issue? Does anyone know what causes it? Does anyone know how to fix it?

Tags (3)
0 Kudos
1 Solution
423 Views
paul_katarzis
Contributor III

I discovered the cause of this issue. The eDMA hardware and driver seems to be working fine. The problem is within the SAI driver. The file fsl_sai.c contains the following line in the fsl_sai_hw_params function:

regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << min(channels, slots)) - 1));

The expression ~0UL - ((1 << min(channels, slots)) - 1) does not evaluate to the expected value. When min(channels, slots) evaluates to 32, the rest of the expression evaluates to 0xFFFFFFFF instead of the expected value of 0x00000000. When the Transmit Mask Register is set to 0xFFFFFFFF, the SAI will not transmit data for any channel. Because of this, there is never an eDMA request to transfer data to the transmit FIFO. Since no data is transferred, the interrupt handler fsl_edma3_tx_handler is never called. Since this interrupt handler is never called, the function imx_pcm_dma_v2_complete is never called which is responsible for calling snd_pcm_period_elapsed. When snd_pcm_period_elapsed is not called within 10 seconds, ALSA will report an error.

The main issue is that the expression 1 << min(channels, slots) does not appear to be portable. If min(channels, slots) evaluates to 32, then the expression 1 << 32 must be calculated. However, this expression has undefined behavior if the integer literal 1 is stored in a 32 bit value. In my case, 1 << 32 evaluates to 1. The issue can be fixed by using the string literal 1UL (to be consistent with the 0UL string literal) instead of the string literal 1 within the expression.

View solution in original post

0 Kudos
4 Replies
424 Views
paul_katarzis
Contributor III

I discovered the cause of this issue. The eDMA hardware and driver seems to be working fine. The problem is within the SAI driver. The file fsl_sai.c contains the following line in the fsl_sai_hw_params function:

regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << min(channels, slots)) - 1));

The expression ~0UL - ((1 << min(channels, slots)) - 1) does not evaluate to the expected value. When min(channels, slots) evaluates to 32, the rest of the expression evaluates to 0xFFFFFFFF instead of the expected value of 0x00000000. When the Transmit Mask Register is set to 0xFFFFFFFF, the SAI will not transmit data for any channel. Because of this, there is never an eDMA request to transfer data to the transmit FIFO. Since no data is transferred, the interrupt handler fsl_edma3_tx_handler is never called. Since this interrupt handler is never called, the function imx_pcm_dma_v2_complete is never called which is responsible for calling snd_pcm_period_elapsed. When snd_pcm_period_elapsed is not called within 10 seconds, ALSA will report an error.

The main issue is that the expression 1 << min(channels, slots) does not appear to be portable. If min(channels, slots) evaluates to 32, then the expression 1 << 32 must be calculated. However, this expression has undefined behavior if the integer literal 1 is stored in a 32 bit value. In my case, 1 << 32 evaluates to 1. The issue can be fixed by using the string literal 1UL (to be consistent with the 0UL string literal) instead of the string literal 1 within the expression.

View solution in original post

0 Kudos
423 Views
nxf46838
NXP TechSupport
NXP TechSupport

Hello,

 

Unfortunately as you may know the i.MX8X family it is not released yet, so there is no support for it, please contact your sales/distributor regarding this.

 

Sorry for the inconvenience and for any problem this may cause.

Thank you for your understanding,

Best regards,

Aldo

0 Kudos
423 Views
j_lambrecht
Contributor I

On imx6 (I use imx6ul) it is the sdma driver drivers/dma/imx-sdma.c you need for SAI. Then you also need a binary blob (see sdma-imx6q.bin firmware ) but the driver is not stable with SLOB allocator (see https://community.nxp.com/thread/502088 ).

And then you also need to add sdma in your dts, see imx6ul.dtsi.

You say 32 channels. Do you mean channels or bits? Because 32 channels is challenging. What is your codec type, I only know max. 8-channel (I am also working on audio and am curious.)

0 Kudos
423 Views
paul_katarzis
Contributor III

Hello Juergen,

The i.MX 8 QXP uses eDMA instead of SDMA. I have had a similar problem in the past with SDMA on the i.MX 6 Quad. The interrupt signal from SDMA to the processor seemed to never be asserted when the period and buffer size for a PCM stream were small (valid values). The "fix" was to just avoid using those small values whenever possible.

I do indeed mean 32 channels. The codec supports 32 channels where each channel is 32 bits wide. Although we may never use that many channels of that width, it should still work.

I am still investigating if I have maybe incorrectly setup my device tree or am failing to understand the limitations of the eDMA.

0 Kudos