IMX8 SAI TDM16 Issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IMX8 SAI TDM16 Issue

Jump to solution
643 Views
millark
Contributor III

We are using an IMX8Nano kernel 5.15 custom board and have an issue with TDM16 on SAI5

The issue is that  for a TDM 16 stream, we randomly get channels switching out of step by 8 channels. We have added kernel trace and see the following debug from the fsl_sai driver

if (flags & FSL_SAI_CSR_FEF) {
dev_dbg(dev, "isr: Transmit underrun detected\n");

The driver should perform a FIFO reset in this condition, however this either doesn't happen or has no effect.

The next time the underrun occurs, the channels realign as the step in always 8 channels out in a 16 channel config.

The SAI is in slave mode with only transmit lines activated:

&sai5 {
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai5>;
fsl,dataline = <0 0x00 0xff>;
dmas = <&sdma2 8 24 0>, <&sdma2 9 24 0>;
fsl,txmasterflag = <1>;
status = "okay";
};
 
using the simpl-audio-card f
 
   output1 {
 
        compatible = "simple-audio-card";
        simple-audio-card,name = "SAI51";
simple-audio-card,status="okay";
simple-audio-card,bitclock-master = <&spdif_codec1>;
        simple-audio-card,frame-master = <&spdif_codec1>;
        simple-audio-card,format = "left_j";
               
        cpu1:  simple-audio-card,cpu {
                sound-dai = <&sai5>;
                dai-tdm-slot-num = <16>;
                dai-tdm-slot-width = <32>;
        };
 
        spdif_codec1:  simple-audio-card,codec {
                sound-dai = <&codec_out1>;
        };
        
 
    };
    
   
    codec_out1: 1output_txcodec {
        #sound-dai-cells = <0>;
        #address-cells = <0>;
        #size-cells = <0>;
        compatible = "linux,spdif-dit";
        sound-name-prefix = "spdif_codec1";  
        status = "okay";
    };
 
We have tried a few fixes for this from various posts on line, with no success. 
 
Has anyone else seen such an issue? We assume that this underrun is due the interupt being fired to early hence there is not enough data in the DMA for all channels.

We have no errors in our also playback logs and no errors in TDM8 mode.
 
Any help appreciated.,

 

0 Kudos
Reply
1 Solution
473 Views
millark
Contributor III

We have pushed the problem aside. But there are some important lessons learnt here to share with other from a dts perspective:

fsl,dataline = <0 0x00 0xff>;

Be careful with this config if you have specified multiple data lines in the pin mappings. With this config combined with:

  cpu1:  simple-audio-card,cpu {
                sound-dai = <&sai5>;
                dai-tdm-slot-num = <16>;
                dai-tdm-slot-width = <32>;
        };
 
This will create a 32 channel interface as the slot num should reference the number of channels needed per data line not the total number of channels for the SAI interface.
 
Hence we were seeing dma of 64 bit as this was essentially a 32 channel operation and we only needed 16.
 
We switched to a 4 X TDM4 config like below:

4 DATA LINES 

pinctrl_sai5: sai5grp {
fsl,pins = <
MX8MN_IOMUXC_SAI2_MCLK_SAI5_MCLK        0xd6
MX8MN_IOMUXC_SAI2_RXC_SAI5_TX_BCLK 0xd6
MX8MN_IOMUXC_SAI2_RXFS_SAI5_TX_SYNC 0xd6
MX8MN_IOMUXC_SAI2_RXD0_SAI5_TX_DATA0 0xd6
MX8MN_IOMUXC_SAI2_TXFS_SAI5_TX_DATA1 0xd6
MX8MN_IOMUXC_SAI2_TXC_SAI5_TX_DATA2 0xd6
MX8MN_IOMUXC_SAI2_TXD0_SAI5_TX_DATA3 0xd6
>;
};

 

SAI5


&sai5 {

#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai5>;
fsl,dataline = <0 0x00 0xff>;
dmas = <&sdma2 8 24 0>, <&sdma2 9 24 0>;
fsl,txmasterflag = <1>; 
/delete-property/ fsl,shared-interrupt;
status = "okay";
};

 
Card and Codec
 
output1 {
 
        compatible = "simple-audio-card";
        simple-audio-card,name = "SAI51";
simple-audio-card,status="okay";
simple-audio-card,bitclock-master = <&spdif_codec1>;
        simple-audio-card,frame-master = <&spdif_codec1>;
        simple-audio-card,format = "left_j";
               
        cpu1:  simple-audio-card,cpu {
                sound-dai = <&sai5>;
                dai-tdm-slot-num = <4>;
                dai-tdm-slot-width = <32>;
        };
 
        spdif_codec1:  simple-audio-card,codec {
                sound-dai = <&codec_out1>;
        };
        
    };
    
   
    codec_out1: 1output_txcodec {
        #sound-dai-cells = <0>;
        #address-cells = <0>;
        #size-cells = <0>;
        compatible = "linux,spdif-dit";
        sound-name-prefix = "spdif_codec1";  
        status = "okay";
    };

 

Note the slo-num of 4. Each dataline now has 4 channels of data. You will need to use ALSA to map these as we have. We use a dmix to create 8 stereos, the mappings were :

C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15
0    4   8    12  1     5    9    13   2   6    10    14   3     7     11     15

The channel count is like this because we didn't enable the fls,multi-lane and disabled shared interrupt

 

Hope this helps someone else.

 

View solution in original post

Tags (1)
0 Kudos
Reply
7 Replies
474 Views
millark
Contributor III

We have pushed the problem aside. But there are some important lessons learnt here to share with other from a dts perspective:

fsl,dataline = <0 0x00 0xff>;

Be careful with this config if you have specified multiple data lines in the pin mappings. With this config combined with:

  cpu1:  simple-audio-card,cpu {
                sound-dai = <&sai5>;
                dai-tdm-slot-num = <16>;
                dai-tdm-slot-width = <32>;
        };
 
This will create a 32 channel interface as the slot num should reference the number of channels needed per data line not the total number of channels for the SAI interface.
 
Hence we were seeing dma of 64 bit as this was essentially a 32 channel operation and we only needed 16.
 
We switched to a 4 X TDM4 config like below:

4 DATA LINES 

pinctrl_sai5: sai5grp {
fsl,pins = <
MX8MN_IOMUXC_SAI2_MCLK_SAI5_MCLK        0xd6
MX8MN_IOMUXC_SAI2_RXC_SAI5_TX_BCLK 0xd6
MX8MN_IOMUXC_SAI2_RXFS_SAI5_TX_SYNC 0xd6
MX8MN_IOMUXC_SAI2_RXD0_SAI5_TX_DATA0 0xd6
MX8MN_IOMUXC_SAI2_TXFS_SAI5_TX_DATA1 0xd6
MX8MN_IOMUXC_SAI2_TXC_SAI5_TX_DATA2 0xd6
MX8MN_IOMUXC_SAI2_TXD0_SAI5_TX_DATA3 0xd6
>;
};

 

SAI5


&sai5 {

#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai5>;
fsl,dataline = <0 0x00 0xff>;
dmas = <&sdma2 8 24 0>, <&sdma2 9 24 0>;
fsl,txmasterflag = <1>; 
/delete-property/ fsl,shared-interrupt;
status = "okay";
};

 
Card and Codec
 
output1 {
 
        compatible = "simple-audio-card";
        simple-audio-card,name = "SAI51";
simple-audio-card,status="okay";
simple-audio-card,bitclock-master = <&spdif_codec1>;
        simple-audio-card,frame-master = <&spdif_codec1>;
        simple-audio-card,format = "left_j";
               
        cpu1:  simple-audio-card,cpu {
                sound-dai = <&sai5>;
                dai-tdm-slot-num = <4>;
                dai-tdm-slot-width = <32>;
        };
 
        spdif_codec1:  simple-audio-card,codec {
                sound-dai = <&codec_out1>;
        };
        
    };
    
   
    codec_out1: 1output_txcodec {
        #sound-dai-cells = <0>;
        #address-cells = <0>;
        #size-cells = <0>;
        compatible = "linux,spdif-dit";
        sound-name-prefix = "spdif_codec1";  
        status = "okay";
    };

 

Note the slo-num of 4. Each dataline now has 4 channels of data. You will need to use ALSA to map these as we have. We use a dmix to create 8 stereos, the mappings were :

C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15
0    4   8    12  1     5    9    13   2   6    10    14   3     7     11     15

The channel count is like this because we didn't enable the fls,multi-lane and disabled shared interrupt

 

Hope this helps someone else.

 

Tags (1)
0 Kudos
Reply
588 Views
JorgeCas
NXP TechSupport
NXP TechSupport

Hello,

If you reduce the bit rate, does the error happen?

Best regards.

0 Kudos
Reply
512 Views
millark
Contributor III

So we have tested with 16bit audio and so far no errors. We will keep the test running on soak as it has only been a few hours. We can't use this in production, but an interesting test,

I guess this makes sense as the DMA controller is 32bit so for 32bit audio data at 16ch we are talking about 64bits of audio per sample, which will use two DMA slots, for an underrun the fifo gets out of sync by 1, representing half the data hence the 8 channel switch. 

We need to understand now about the fifo reset in 32bit mode when an underrun occurs and why this has no affect, I assume as it only clears 32bits of data and not the 64bits relating to a full sample.  Also as to why these underruns occur and why the dma interrupts can't keep up with the system.

0 Kudos
Reply
495 Views
JorgeCas
NXP TechSupport
NXP TechSupport

Hello,

Thank you for the update.

Just to confirm, please verify that the Transmit Channel Enable bit of SAI Transmit Configuration 3 Register (TCR3) is enabled for your design.

Best regards.

0 Kudos
Reply
572 Views
millark
Contributor III

I am not able to reduce the bit rate in this current test environment, as the audio being piped via alsa is fixed and the receiving end codec (clck src) is also fixed. I will try and test another way.

As an update, we set the clocks in master mode thinking it may have been related to clock stability when in slave mode, this had no affect.

We are running a dmix plugin in alsa that mixes the 16ch to 8 X 2ch and are now investigating there.

0 Kudos
Reply
570 Views
millark
Contributor III

We have ruled out DMIX itself as it also happens with other Alsa plugins like DSHARE

0 Kudos
Reply
640 Views
millark
Contributor III
We have no errors in our alsa playback logs and no errors in TDM8 mode.
0 Kudos
Reply