fsl_ssi.c: Getting channel slips with fsl_ssi.c in TDM (network) mode.
diff mbox

Message ID CAG5mAdxM_p2TWKhZne7AVGnhVfhVWA3gFe3pu6QQ8djb7TtjEA@mail.gmail.com
State New
Headers show

Commit Message

Caleb Crome Oct. 19, 2015, 3:55 p.m. UTC
Hello Arnaud, all,

I'm trying to get the i.MX6 SSI working in 16-channel TDM mode.  FYI, I'm
working with the stock 4.3 kernel at https://github.com/torvalds/linux.

When I apply the patch below, the SSI does all configure properly and even
starts streaming properly with all the bits in the right place on the SSI
pins.  However, given a little bit of time and/or IO to the SD card, the
bit-stream slips by 1 slot, causing all of the channels to be misaligned.

My changes to the SSI driver are very minimal (shown below), and amount to
forcing it into network (TDM) mode, and changing the maximum channels, and
setting the STCCR DC mask.

There is no indication from user space that anything has slipped, so the
data stream just continues on shifted by 1 slot.

You (Arnaud) mentioned in a previous thread ("Multiple codecs on one sound
card for multi-channel sound card"), that I should just have to set
channels_max (and presumably the other changes I mentioned), and it'll work
mostly.  However, it's very unreliable at the moment.

Any thoughts to how I can diagnose this problem would be greatly
appreciated!

So, what happens is this:

The SSI Starts sending data like this:
SLOT 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
DATA 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15

But then after time, something slips and without warning it goes to:
SLOT 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
DATA 15 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14

     ssi_private->dma_params_tx.addr = ssi_private->ssi_phys +
CCSR_SSI_STX0;
     ssi_private->dma_params_rx.addr = ssi_private->ssi_phys +
CCSR_SSI_SRX0;


Thanks,
  -Caleb

Comments

Arnaud Mouiche Oct. 20, 2015, 7:36 a.m. UTC | #1
Hello Caleb,

I go through all [few] patchs we apply to the 4.0 linux tree (didn't 
jump to 4.2 yet).
There is one concerning the DMA firmware you can find in the freescale 
tree, available at git://git.freescale.com/imx/linux-2.6-imx.git

commit 619bfca89908b90cd6606ed894c180df0c481508
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Tue Jul 16 22:53:18 2013 +0800

     ENGR00269945: firwmare: imx: add imx6q sdma script

     Add imx6q sdma script which will be used by all i.MX6 series.

     Signed-off-by: Shawn Guo <shawn.guo@freescale.com>

  firmware/Makefile                     |   1 +
  firmware/imx/sdma/sdma-imx6q.bin.ihex | 116 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 117 insertions(+)


I don't know how 4.3rcN catch some of the freescale patch. but you may 
check if you need to apply this one.
I know there are some other SDMA firmware available all around in this 
freescale tree. I didn't find proper release note or documentation. May 
be you can test them also.

Arnaud

Le 19/10/2015 17:55, Caleb Crome a écrit :
> Hello Arnaud, all,
>
> I'm trying to get the i.MX6 SSI working in 16-channel TDM mode.  FYI, 
> I'm working with the stock 4.3 kernel at 
> https://github.com/torvalds/linux.
>
> When I apply the patch below, the SSI does all configure properly and 
> even starts streaming properly with all the bits in the right place on 
> the SSI pins.  However, given a little bit of time and/or IO to the SD 
> card, the bit-stream slips by 1 slot, causing all of the channels to 
> be misaligned.
>
> My changes to the SSI driver are very minimal (shown below), and 
> amount to forcing it into network (TDM) mode, and changing the maximum 
> channels, and setting the STCCR DC mask.
>
> There is no indication from user space that anything has slipped, so 
> the data stream just continues on shifted by 1 slot.
>
> You (Arnaud) mentioned in a previous thread ("Multiple codecs on one 
> sound card for multi-channel sound card"), that I should just have to 
> set channels_max (and presumably the other changes I mentioned), and 
> it'll work mostly. However, it's very unreliable at the moment.
>
> Any thoughts to how I can diagnose this problem would be greatly 
> appreciated!
>
> So, what happens is this:
>
> The SSI Starts sending data like this:
> SLOT 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
> DATA 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
>
> But then after time, something slips and without warning it goes to:
> SLOT 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
> DATA 15 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14
>
> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> index 37c5cd4..73778c2 100644
> --- a/sound/soc/fsl/fsl_ssi.c
> +++ b/sound/soc/fsl/fsl_ssi.c
> @@ -749,7 +749,10 @@ static int fsl_ssi_hw_params(struct 
> snd_pcm_substream *substream,
>                  CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
>                  channels == 1 ? 0 : i2smode);
>      }
> -
> +    ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | 
> CCSR_SSI_SCR_NET;
> +    regmap_update_bits(regs, CCSR_SSI_SCR,
> +               CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
> +               ssi_private->i2s_mode);
>      /*
>       * FIXME: The documentation says that SxCCR[WL] should not be
>       * modified while the SSI is enabled.  The only time this can
> @@ -863,6 +866,15 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
>          return -EINVAL;
>      }
>      scr |= ssi_private->i2s_mode;
> +    // Set to 16 slots/frame
> +    regmap_update_bits(regs, CCSR_SSI_STCCR,
> +               CCSR_SSI_SxCCR_DC_MASK,
> +               CCSR_SSI_SxCCR_DC(16));
> +
> +    regmap_update_bits(regs, CCSR_SSI_SRCCR,
> +               CCSR_SSI_SxCCR_DC_MASK,
> +               CCSR_SSI_SxCCR_DC(16));
> +
>
>      /* DAI clock inversion */
>      switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> @@ -1084,14 +1099,14 @@ static struct snd_soc_dai_driver 
> fsl_ssi_dai_template = {
>      .playback = {
>          .stream_name = "CPU-Playback",
>          .channels_min = 1,
> -        .channels_max = 2,
> +        .channels_max = 16,
>          .rates = FSLSSI_I2S_RATES,
>          .formats = FSLSSI_I2S_FORMATS,
>      },
>      .capture = {
>          .stream_name = "CPU-Capture",
>          .channels_min = 1,
> -        .channels_max = 2,
> +        .channels_max = 16,
>          .rates = FSLSSI_I2S_RATES,
>          .formats = FSLSSI_I2S_FORMATS,
>      },
>
> Another thing I have tried is changing the watermark level for the 
> fifo to give the DMA interrupt some extra time. The problem still 
> happens, but seems to be a bit better.
>
> The fifo watermark change is this:
> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> index 73778c2..7c2e4b0 100644
> --- a/sound/soc/fsl/fsl_ssi.c
> +++ b/sound/soc/fsl/fsl_ssi.c
> @@ -54,6 +54,8 @@
>  #include "fsl_ssi.h"
>  #include "imx-pcm.h"
>
> +#define WATERMARK 8
> +
>  /**
>   * FSLSSI_I2S_RATES: sample rates supported by the I2S
>   *
> @@ -943,7 +950,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
>       * size.
>       */
>      if (ssi_private->use_dma)
> -        wm = ssi_private->fifo_depth - 2;
> +        wm = ssi_private->fifo_depth - WATERMARK;
>      else
>          wm = ssi_private->fifo_depth;
>
> @@ -1260,8 +1267,8 @@ static int fsl_ssi_imx_probe(struct 
> platform_device *pdev,
>       * We have burstsize be "fifo_depth - 2" to match the SSI
>       * watermark setting in fsl_ssi_startup().
>       */
> -    ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
> -    ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
> +    ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 
> WATERMARK;
> +    ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 
> WATERMARK;
>      ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + 
> CCSR_SSI_STX0;
>      ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + 
> CCSR_SSI_SRX0;
>
>
> Thanks,
>   -Caleb
>
Caleb Crome Oct. 20, 2015, 5:43 p.m. UTC | #2
On Tue, Oct 20, 2015 at 12:36 AM, arnaud.mouiche@invoxia.com
<arnaud.mouiche@invoxia.com> wrote:
> Hello Caleb,
>
> I go through all [few] patchs we apply to the 4.0 linux tree (didn't jump to
> 4.2 yet).
> There is one concerning the DMA firmware you can find in the freescale tree,
> available at git://git.freescale.com/imx/linux-2.6-imx.git
>
> commit 619bfca89908b90cd6606ed894c180df0c481508
> Author: Shawn Guo <shawn.guo@freescale.com>
> Date:   Tue Jul 16 22:53:18 2013 +0800
>
>     ENGR00269945: firwmare: imx: add imx6q sdma script
>
>     Add imx6q sdma script which will be used by all i.MX6 series.
>
>     Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
>
>  firmware/Makefile                     |   1 +
>  firmware/imx/sdma/sdma-imx6q.bin.ihex | 116
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 117 insertions(+)
>
>
> I don't know how 4.3rcN catch some of the freescale patch. but you may check
> if you need to apply this one.
> I know there are some other SDMA firmware available all around in this
> freescale tree. I didn't find proper release note or documentation. May be
> you can test them also.
>
> Arnaud

Hi Arnaud,
  My root filesystem already had that firmware in it (the kernel
didn't have the kernel patch, but when I applied that patch, the
generated sdma script was identical.

So, unfortunately, that's not the problem with the channel slipping.
Any other thoughts on why the channel would slip?  Or pointers on how
to diagnose?  I have an oscilloscope & know how to use it :-)  Also, I
can flip a GPIO to watch for timing of interrupts, etc (although I
haven't done that yet).


Thanks,
  -Caleb




>
>
> Le 19/10/2015 17:55, Caleb Crome a écrit :
>>
>> Hello Arnaud, all,
>>
>> I'm trying to get the i.MX6 SSI working in 16-channel TDM mode.  FYI, I'm
>> working with the stock 4.3 kernel at https://github.com/torvalds/linux.
>>
>> When I apply the patch below, the SSI does all configure properly and even
>> starts streaming properly with all the bits in the right place on the SSI
>> pins.  However, given a little bit of time and/or IO to the SD card, the
>> bit-stream slips by 1 slot, causing all of the channels to be misaligned.
>>
>> My changes to the SSI driver are very minimal (shown below), and amount to
>> forcing it into network (TDM) mode, and changing the maximum channels, and
>> setting the STCCR DC mask.
>>
>> There is no indication from user space that anything has slipped, so the
>> data stream just continues on shifted by 1 slot.
>>
>> You (Arnaud) mentioned in a previous thread ("Multiple codecs on one sound
>> card for multi-channel sound card"), that I should just have to set
>> channels_max (and presumably the other changes I mentioned), and it'll work
>> mostly. However, it's very unreliable at the moment.
>>
>> Any thoughts to how I can diagnose this problem would be greatly
>> appreciated!
>>
>> So, what happens is this:
>>
>> The SSI Starts sending data like this:
>> SLOT 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
>> DATA 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
>>
>> But then after time, something slips and without warning it goes to:
>> SLOT 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
>> DATA 15 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14
>>
>> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
>> index 37c5cd4..73778c2 100644
>> --- a/sound/soc/fsl/fsl_ssi.c
>> +++ b/sound/soc/fsl/fsl_ssi.c
>> @@ -749,7 +749,10 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream
>> *substream,
>>                  CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
>>                  channels == 1 ? 0 : i2smode);
>>      }
>> -
>> +    ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL |
>> CCSR_SSI_SCR_NET;
>> +    regmap_update_bits(regs, CCSR_SSI_SCR,
>> +               CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
>> +               ssi_private->i2s_mode);
>>      /*
>>       * FIXME: The documentation says that SxCCR[WL] should not be
>>       * modified while the SSI is enabled.  The only time this can
>> @@ -863,6 +866,15 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
>>          return -EINVAL;
>>      }
>>      scr |= ssi_private->i2s_mode;
>> +    // Set to 16 slots/frame
>> +    regmap_update_bits(regs, CCSR_SSI_STCCR,
>> +               CCSR_SSI_SxCCR_DC_MASK,
>> +               CCSR_SSI_SxCCR_DC(16));
>> +
>> +    regmap_update_bits(regs, CCSR_SSI_SRCCR,
>> +               CCSR_SSI_SxCCR_DC_MASK,
>> +               CCSR_SSI_SxCCR_DC(16));
>> +
>>
>>      /* DAI clock inversion */
>>      switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
>> @@ -1084,14 +1099,14 @@ static struct snd_soc_dai_driver
>> fsl_ssi_dai_template = {
>>      .playback = {
>>          .stream_name = "CPU-Playback",
>>          .channels_min = 1,
>> -        .channels_max = 2,
>> +        .channels_max = 16,
>>          .rates = FSLSSI_I2S_RATES,
>>          .formats = FSLSSI_I2S_FORMATS,
>>      },
>>      .capture = {
>>          .stream_name = "CPU-Capture",
>>          .channels_min = 1,
>> -        .channels_max = 2,
>> +        .channels_max = 16,
>>          .rates = FSLSSI_I2S_RATES,
>>          .formats = FSLSSI_I2S_FORMATS,
>>      },
>>
>> Another thing I have tried is changing the watermark level for the fifo to
>> give the DMA interrupt some extra time. The problem still happens, but seems
>> to be a bit better.
>>
>> The fifo watermark change is this:
>> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
>> index 73778c2..7c2e4b0 100644
>> --- a/sound/soc/fsl/fsl_ssi.c
>> +++ b/sound/soc/fsl/fsl_ssi.c
>> @@ -54,6 +54,8 @@
>>  #include "fsl_ssi.h"
>>  #include "imx-pcm.h"
>>
>> +#define WATERMARK 8
>> +
>>  /**
>>   * FSLSSI_I2S_RATES: sample rates supported by the I2S
>>   *
>> @@ -943,7 +950,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
>>       * size.
>>       */
>>      if (ssi_private->use_dma)
>> -        wm = ssi_private->fifo_depth - 2;
>> +        wm = ssi_private->fifo_depth - WATERMARK;
>>      else
>>          wm = ssi_private->fifo_depth;
>>
>> @@ -1260,8 +1267,8 @@ static int fsl_ssi_imx_probe(struct platform_device
>> *pdev,
>>       * We have burstsize be "fifo_depth - 2" to match the SSI
>>       * watermark setting in fsl_ssi_startup().
>>       */
>> -    ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
>> -    ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
>> +    ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth -
>> WATERMARK;
>> +    ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth -
>> WATERMARK;
>>      ssi_private->dma_params_tx.addr = ssi_private->ssi_phys +
>> CCSR_SSI_STX0;
>>      ssi_private->dma_params_rx.addr = ssi_private->ssi_phys +
>> CCSR_SSI_SRX0;
>>
>>
>> Thanks,
>>   -Caleb
>>
>
Arnaud Mouiche Oct. 21, 2015, 7:32 a.m. UTC | #3
Le 20/10/2015 19:43, Caleb Crome a écrit :
> On Tue, Oct 20, 2015 at 12:36 AM, arnaud.mouiche@invoxia.com
> <arnaud.mouiche@invoxia.com> wrote:
>> Hello Caleb,
>>
>> I go through all [few] patchs we apply to the 4.0 linux tree (didn't jump to
>> 4.2 yet).
>> There is one concerning the DMA firmware you can find in the freescale tree,
>> available at git://git.freescale.com/imx/linux-2.6-imx.git
>>
>> commit 619bfca89908b90cd6606ed894c180df0c481508
>> Author: Shawn Guo <shawn.guo@freescale.com>
>> Date:   Tue Jul 16 22:53:18 2013 +0800
>>
>>      ENGR00269945: firwmare: imx: add imx6q sdma script
>>
>>      Add imx6q sdma script which will be used by all i.MX6 series.
>>
>>      Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
>>
>>   firmware/Makefile                     |   1 +
>>   firmware/imx/sdma/sdma-imx6q.bin.ihex | 116
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 117 insertions(+)
>>
>>
>> I don't know how 4.3rcN catch some of the freescale patch. but you may check
>> if you need to apply this one.
>> I know there are some other SDMA firmware available all around in this
>> freescale tree. I didn't find proper release note or documentation. May be
>> you can test them also.
>>
>> Arnaud
> Hi Arnaud,
>    My root filesystem already had that firmware in it (the kernel
> didn't have the kernel patch, but when I applied that patch, the
> generated sdma script was identical.
>
> So, unfortunately, that's not the problem with the channel slipping.
> Any other thoughts on why the channel would slip?  Or pointers on how
> to diagnose?  I have an oscilloscope & know how to use it :-)  Also, I
> can flip a GPIO to watch for timing of interrupts, etc (although I
> haven't done that yet).
>
>
> Thanks,
>    -Caleb

Hello Caleb,

In your situation, I would:
- check if TUE0/1 flag never rise (Transmitter Underrun) by activating 
the TUE0/1IE bit to generate related interrupts. It looks like already 
enabled in 4.0 by collecting statistics with fsl_ssi_dbg_isr(). Despite 
there is no printk message on underrun, stats can be read from 
/sys/kernel/debug/xxxx.ssi/stats.

- I suspect the dma is not fast enough to fill the FIFO. may be you 
should dig to check how SDMA priority are configured amongs the 
differents DMA channels.
Not something I already look at before. A quick look suggest that 
DMA_PRIO_HIGH is _NOT_ configured by the fsl_ssi.c driver (wheras the 
imx-ssi.c did)

Regards,
Arnaud
Caleb Crome Oct. 21, 2015, 7:37 p.m. UTC | #4
On Wed, Oct 21, 2015 at 12:32 AM, arnaud.mouiche@invoxia.com
<arnaud.mouiche@invoxia.com> wrote:
>
>
> Le 20/10/2015 19:43, Caleb Crome a écrit :
>> Hi Arnaud,
>>    My root filesystem already had that firmware in it (the kernel
>> didn't have the kernel patch, but when I applied that patch, the
>> generated sdma script was identical.
>>
>> So, unfortunately, that's not the problem with the channel slipping.
>> Any other thoughts on why the channel would slip?  Or pointers on how
>> to diagnose?  I have an oscilloscope & know how to use it :-)  Also, I
>> can flip a GPIO to watch for timing of interrupts, etc (although I
>> haven't done that yet).
>>
>>
>> Thanks,
>>    -Caleb
>
>
> Hello Caleb,
>
> In your situation, I would:
> - check if TUE0/1 flag never rise (Transmitter Underrun) by activating the
> TUE0/1IE bit to generate related interrupts. It looks like already enabled
> in 4.0 by collecting statistics with fsl_ssi_dbg_isr(). Despite there is no
> printk message on underrun, stats can be read from
> /sys/kernel/debug/xxxx.ssi/stats.

Heh, I checked that and I couldn't get the fsl_ssi_dbg_isr to trigger
ever, for any reason.  Somehow interrupts seem to be disabled in the
SSI driver, and I can't figure out how to enable them.  It appears
that the only interrupt required is the DMA interrupt, and SSI
interrupts are not checked.    The /sys/kernel/debug/xxxx.ssi/stats
file reads all zeros no matter what, even during playing, and even
after the user space detects underruns.

>
> - I suspect the dma is not fast enough to fill the FIFO. may be you should
> dig to check how SDMA priority are configured amongs the differents DMA
> channels.
> Not something I already look at before. A quick look suggest that
> DMA_PRIO_HIGH is _NOT_ configured by the fsl_ssi.c driver (wheras the
> imx-ssi.c did)


Ah ha!  Perhaps that's it.  I will check into that.  Maybe that's the
root cause.  Thanks so much.

-Caleb


>
> Regards,
> Arnaud
>
>
Caleb Crome Oct. 26, 2015, 5:31 p.m. UTC | #5
On Wed, Oct 21, 2015 at 12:37 PM, Caleb Crome <caleb@crome.org> wrote:
> On Wed, Oct 21, 2015 at 12:32 AM, arnaud.mouiche@invoxia.com
> <arnaud.mouiche@invoxia.com> wrote:
>>
>>
>> Le 20/10/2015 19:43, Caleb Crome a écrit :
>>> Hi Arnaud,
>>>    My root filesystem already had that firmware in it (the kernel
>>> didn't have the kernel patch, but when I applied that patch, the
>>> generated sdma script was identical.
>>>
>>> So, unfortunately, that's not the problem with the channel slipping.
>>> Any other thoughts on why the channel would slip?  Or pointers on how
>>> to diagnose?  I have an oscilloscope & know how to use it :-)  Also, I
>>> can flip a GPIO to watch for timing of interrupts, etc (although I
>>> haven't done that yet).
>>>
>>>
>>> Thanks,
>>>    -Caleb
>>
>>
>> Hello Caleb,
>>
>> In your situation, I would:
>> - check if TUE0/1 flag never rise (Transmitter Underrun) by activating the
>> TUE0/1IE bit to generate related interrupts. It looks like already enabled
>> in 4.0 by collecting statistics with fsl_ssi_dbg_isr(). Despite there is no
>> printk message on underrun, stats can be read from
>> /sys/kernel/debug/xxxx.ssi/stats.
>
> Heh, I checked that and I couldn't get the fsl_ssi_dbg_isr to trigger
> ever, for any reason.  Somehow interrupts seem to be disabled in the
> SSI driver, and I can't figure out how to enable them.  It appears
> that the only interrupt required is the DMA interrupt, and SSI
> interrupts are not checked.    The /sys/kernel/debug/xxxx.ssi/stats
> file reads all zeros no matter what, even during playing, and even
> after the user space detects underruns.
>
>>
>> - I suspect the dma is not fast enough to fill the FIFO. may be you should
>> dig to check how SDMA priority are configured amongs the differents DMA
>> channels.
>> Not something I already look at before. A quick look suggest that
>> DMA_PRIO_HIGH is _NOT_ configured by the fsl_ssi.c driver (wheras the
>> imx-ssi.c did)
>
>
> Ah ha!  Perhaps that's it.  I will check into that.  Maybe that's the
> root cause.  Thanks so much.

So, the dma priority doesn't seem to be the issue.  It's now set in
the device tree, and strangely it's set to priority 0 (the highest)
along with the UARTS.  priority 0 is just the highest in the device
tree -- it gets remapped to priority 3 in the sdma driver.  the DT
exposes only 3 levels of DMA priority, low, medium, and high.  I
created a new level that maps to DMA priroity 7 (the highest in the
hardware), but still got the problem.

So, still something unknown causing dma to miss samples.  must be in
the dma ISR I would assume.  I guess it's time to look into that.

-Caleb
Markus Pargmann Oct. 27, 2015, 7:13 a.m. UTC | #6
Hi,

On Mon, Oct 26, 2015 at 10:31:08AM -0700, Caleb Crome wrote:
> On Wed, Oct 21, 2015 at 12:37 PM, Caleb Crome <caleb@crome.org> wrote:
> > On Wed, Oct 21, 2015 at 12:32 AM, arnaud.mouiche@invoxia.com
> > <arnaud.mouiche@invoxia.com> wrote:
> >>
> >>
> >> Le 20/10/2015 19:43, Caleb Crome a écrit :
> >>> Hi Arnaud,
> >>>    My root filesystem already had that firmware in it (the kernel
> >>> didn't have the kernel patch, but when I applied that patch, the
> >>> generated sdma script was identical.
> >>>
> >>> So, unfortunately, that's not the problem with the channel slipping.
> >>> Any other thoughts on why the channel would slip?  Or pointers on how
> >>> to diagnose?  I have an oscilloscope & know how to use it :-)  Also, I
> >>> can flip a GPIO to watch for timing of interrupts, etc (although I
> >>> haven't done that yet).
> >>>
> >>>
> >>> Thanks,
> >>>    -Caleb
> >>
> >>
> >> Hello Caleb,
> >>
> >> In your situation, I would:
> >> - check if TUE0/1 flag never rise (Transmitter Underrun) by activating the
> >> TUE0/1IE bit to generate related interrupts. It looks like already enabled
> >> in 4.0 by collecting statistics with fsl_ssi_dbg_isr(). Despite there is no
> >> printk message on underrun, stats can be read from
> >> /sys/kernel/debug/xxxx.ssi/stats.
> >
> > Heh, I checked that and I couldn't get the fsl_ssi_dbg_isr to trigger
> > ever, for any reason.  Somehow interrupts seem to be disabled in the
> > SSI driver, and I can't figure out how to enable them.  It appears
> > that the only interrupt required is the DMA interrupt, and SSI
> > interrupts are not checked.    The /sys/kernel/debug/xxxx.ssi/stats
> > file reads all zeros no matter what, even during playing, and even
> > after the user space detects underruns.
> >
> >>
> >> - I suspect the dma is not fast enough to fill the FIFO. may be you should
> >> dig to check how SDMA priority are configured amongs the differents DMA
> >> channels.
> >> Not something I already look at before. A quick look suggest that
> >> DMA_PRIO_HIGH is _NOT_ configured by the fsl_ssi.c driver (wheras the
> >> imx-ssi.c did)
> >
> >
> > Ah ha!  Perhaps that's it.  I will check into that.  Maybe that's the
> > root cause.  Thanks so much.
> 
> So, the dma priority doesn't seem to be the issue.  It's now set in
> the device tree, and strangely it's set to priority 0 (the highest)
> along with the UARTS.  priority 0 is just the highest in the device
> tree -- it gets remapped to priority 3 in the sdma driver.  the DT
> exposes only 3 levels of DMA priority, low, medium, and high.  I
> created a new level that maps to DMA priroity 7 (the highest in the
> hardware), but still got the problem.
> 
> So, still something unknown causing dma to miss samples.  must be in
> the dma ISR I would assume.  I guess it's time to look into that.

Cc Nicolin, Fabio, Shawn

Perhaps you have an idea about this?

Regards,

Markus

> 
> -Caleb
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Fabio Estevam Oct. 27, 2015, 9:41 a.m. UTC | #7
Hi Markus/Caleb,

On Tue, Oct 27, 2015 at 5:13 AM, Markus Pargmann <mpa@pengutronix.de> wrote:
> Hi,

> Cc Nicolin, Fabio, Shawn
>
> Perhaps you have an idea about this?

Could you please try it without using the external SDMA firmware?

Regards,

Fabio Estevam
Caleb Crome Oct. 27, 2015, 4:02 p.m. UTC | #8
On Tue, Oct 27, 2015 at 2:41 AM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Markus/Caleb,
>
> On Tue, Oct 27, 2015 at 5:13 AM, Markus Pargmann <mpa@pengutronix.de> wrote:
>> Hi,
>
>> Cc Nicolin, Fabio, Shawn
>>
>> Perhaps you have an idea about this?
>
> Could you please try it without using the external SDMA firmware?

I do need *some* SDMA firmware, correct?  The firmware that I'm using
ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
5d4584134cc4cba62e1be2f382cd6f3a.

It's the exact same file that came on the root filesystem as is
generated from the freescale kernel tree, literally the same MD5SUM.

Or, should I simply remove that file?  I haven't looked into how the
kernel driver and the .bin file interact, but I do see that the
imx6qdl.dtsi references the imx/sdma/sdma-imx6q.bin file.

Thanks,
  -Caleb

>
> Regards,
>
> Fabio Estevam
Fabio Estevam Oct. 27, 2015, 4:10 p.m. UTC | #9
On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:

>> Could you please try it without using the external SDMA firmware?
>
> I do need *some* SDMA firmware, correct?  The firmware that I'm using
> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
> 5d4584134cc4cba62e1be2f382cd6f3a.

SSI can operate with the ROM SDMA firmware.

I would like to know if this issue also happens if you don't pass the
external firmware and use the internal ROM SDMA firmware instead.

Also, could you try bumping the SSI and SDMA clock rates at the maximum?

Adding Shengjiu in case he has any thoughts on getting TDM support in
the SSI driver.

Regards,

Fabio Estevam
Caleb Crome Oct. 27, 2015, 4:42 p.m. UTC | #10
On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>
>>> Could you please try it without using the external SDMA firmware?
>>
>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>> 5d4584134cc4cba62e1be2f382cd6f3a.
>
> SSI can operate with the ROM SDMA firmware.
>
> I would like to know if this issue also happens if you don't pass the
> external firmware and use the internal ROM SDMA firmware instead.

Ah, good to know.  Do I just remove reference in the .dtsi file?
Remove the file from the filesystem?  I'll do both to be doubly sure
:-)


>
> Also, could you try bumping the SSI and SDMA clock rates at the maximum?

Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
poke around.

Thanks so much for your help.  We've got several systems where we'd
really like to use the MX6, but this issues is blocking us.

  -caleb


>
> Adding Shengjiu in case he has any thoughts on getting TDM support in
> the SSI driver.
>
> Regards,
>
> Fabio Estevam
Fabio Estevam Oct. 27, 2015, 4:45 p.m. UTC | #11
On Tue, Oct 27, 2015 at 2:42 PM, Caleb Crome <caleb@crome.org> wrote:
> On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
>> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>>
>>>> Could you please try it without using the external SDMA firmware?
>>>
>>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>>> 5d4584134cc4cba62e1be2f382cd6f3a.
>>
>> SSI can operate with the ROM SDMA firmware.
>>
>> I would like to know if this issue also happens if you don't pass the
>> external firmware and use the internal ROM SDMA firmware instead.
>
> Ah, good to know.  Do I just remove reference in the .dtsi file?
> Remove the file from the filesystem?  I'll do both to be doubly sure
> :-)

Just remove it from the rootfs. Then you will see a message from the
kernel saying that no external SDMA firmware could be found and that
the internal one is going to be used.

>> Also, could you try bumping the SSI and SDMA clock rates at the maximum?
>
> Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
> poke around.

You can try to call clk_set_rate() with the maximum allowed frequency
inside the ssi driver. I don't recall on top of my head what is this
value though.

Regards,

Fabio Estevam
Fabio Estevam Oct. 27, 2015, 6:57 p.m. UTC | #12
[Adding Roberto in the thread as he is also trying to get SSI TDM support/

On Tue, Oct 27, 2015 at 2:45 PM, Fabio Estevam <festevam@gmail.com> wrote:
> On Tue, Oct 27, 2015 at 2:42 PM, Caleb Crome <caleb@crome.org> wrote:
>> On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
>>> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>>>
>>>>> Could you please try it without using the external SDMA firmware?
>>>>
>>>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>>>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>>>> 5d4584134cc4cba62e1be2f382cd6f3a.
>>>
>>> SSI can operate with the ROM SDMA firmware.
>>>
>>> I would like to know if this issue also happens if you don't pass the
>>> external firmware and use the internal ROM SDMA firmware instead.
>>
>> Ah, good to know.  Do I just remove reference in the .dtsi file?
>> Remove the file from the filesystem?  I'll do both to be doubly sure
>> :-)
>
> Just remove it from the rootfs. Then you will see a message from the
> kernel saying that no external SDMA firmware could be found and that
> the internal one is going to be used.
>
>>> Also, could you try bumping the SSI and SDMA clock rates at the maximum?
>>
>> Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
>> poke around.
>
> You can try to call clk_set_rate() with the maximum allowed frequency
> inside the ssi driver. I don't recall on top of my head what is this
> value though.
>
> Regards,
>
> Fabio Estevam
Nicolin Chen Oct. 27, 2015, 8:11 p.m. UTC | #13
On Tue, Oct 27, 2015 at 08:13:44AM +0100, Markus Pargmann wrote:

> > So, the dma priority doesn't seem to be the issue.  It's now set in
> > the device tree, and strangely it's set to priority 0 (the highest)
> > along with the UARTS.  priority 0 is just the highest in the device
> > tree -- it gets remapped to priority 3 in the sdma driver.  the DT
> > exposes only 3 levels of DMA priority, low, medium, and high.  I
> > created a new level that maps to DMA priroity 7 (the highest in the
> > hardware), but still got the problem.
> > 
> > So, still something unknown causing dma to miss samples.  must be in
> > the dma ISR I would assume.  I guess it's time to look into that.

> Cc Nicolin, Fabio, Shawn
> 
> Perhaps you have an idea about this?

Off the top of my head:

1) Enable TUE0, TUE1, ROE0, ROE1 to see if there is any IRQ trigged.

2) Set the watermarks for both TX and RX to 8 while using burst sizes
   of 6. It'd be nicer to provisionally set these numbers using hard
   code than your current change depending on fifo_depth as it might
   be an odd value.

3) Try to enlarge the ALSA period size in the asound.conf or passing
   parameters when you do the playback/capture so that the number of
   interrupts from SDMA may reduce.

You may also see if the reproducibility is somehow reduced or not.

Nicolin
Roberto Fichera Oct. 28, 2015, 8:11 a.m. UTC | #14
On 10/27/2015 07:57 PM, Fabio Estevam wrote:
> [Adding Roberto in the thread as he is also trying to get SSI TDM support/

Thanks Fabio,

I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
this since when in master mode) but valid data set to be 8bits in the SSI register.

My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
without any apparent reason.


>
> On Tue, Oct 27, 2015 at 2:45 PM, Fabio Estevam <festevam@gmail.com> wrote:
>> On Tue, Oct 27, 2015 at 2:42 PM, Caleb Crome <caleb@crome.org> wrote:
>>> On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
>>>> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>>>>
>>>>>> Could you please try it without using the external SDMA firmware?
>>>>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>>>>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>>>>> 5d4584134cc4cba62e1be2f382cd6f3a.
>>>> SSI can operate with the ROM SDMA firmware.
>>>>
>>>> I would like to know if this issue also happens if you don't pass the
>>>> external firmware and use the internal ROM SDMA firmware instead.
>>> Ah, good to know.  Do I just remove reference in the .dtsi file?
>>> Remove the file from the filesystem?  I'll do both to be doubly sure
>>> :-)
>> Just remove it from the rootfs. Then you will see a message from the
>> kernel saying that no external SDMA firmware could be found and that
>> the internal one is going to be used.
>>
>>>> Also, could you try bumping the SSI and SDMA clock rates at the maximum?
>>> Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
>>> poke around.
>> You can try to call clk_set_rate() with the maximum allowed frequency
>> inside the ssi driver. I don't recall on top of my head what is this
>> value though.
>>
>> Regards,
>>
>> Fabio Estevam
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
Roberto Fichera Oct. 28, 2015, 8:23 a.m. UTC | #15
On 10/27/2015 09:11 PM, Nicolin Chen wrote:
> On Tue, Oct 27, 2015 at 08:13:44AM +0100, Markus Pargmann wrote:
>
>>> So, the dma priority doesn't seem to be the issue.  It's now set in
>>> the device tree, and strangely it's set to priority 0 (the highest)
>>> along with the UARTS.  priority 0 is just the highest in the device
>>> tree -- it gets remapped to priority 3 in the sdma driver.  the DT
>>> exposes only 3 levels of DMA priority, low, medium, and high.  I
>>> created a new level that maps to DMA priroity 7 (the highest in the
>>> hardware), but still got the problem.
>>>
>>> So, still something unknown causing dma to miss samples.  must be in
>>> the dma ISR I would assume.  I guess it's time to look into that.
>> Cc Nicolin, Fabio, Shawn
>>
>> Perhaps you have an idea about this?
> Off the top of my head:
>
> 1) Enable TUE0, TUE1, ROE0, ROE1 to see if there is any IRQ trigged.

I'm my case I was never able to see an interrupt triggered when setting both RDMAE and TDMAE
bits in the SIER register.

> 2) Set the watermarks for both TX and RX to 8 while using burst sizes
>    of 6. It'd be nicer to provisionally set these numbers using hard
>    code than your current change depending on fifo_depth as it might
>    be an odd value.
>
> 3) Try to enlarge the ALSA period size in the asound.conf or passing
>    parameters when you do the playback/capture so that the number of
>    interrupts from SDMA may reduce.
>
> You may also see if the reproducibility is somehow reduced or not.
>
> Nicolin
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
Caleb Crome Oct. 28, 2015, 1:53 p.m. UTC | #16
On Tue, Oct 27, 2015 at 9:45 AM, Fabio Estevam <festevam@gmail.com> wrote:
> On Tue, Oct 27, 2015 at 2:42 PM, Caleb Crome <caleb@crome.org> wrote:
>> On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
>>> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>>>
>>>>> Could you please try it without using the external SDMA firmware?
>>>>
>>>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>>>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>>>> 5d4584134cc4cba62e1be2f382cd6f3a.
>>>
>>> SSI can operate with the ROM SDMA firmware.
>>>
>>> I would like to know if this issue also happens if you don't pass the
>>> external firmware and use the internal ROM SDMA firmware instead.
>>
>> Ah, good to know.  Do I just remove reference in the .dtsi file?
>> Remove the file from the filesystem?  I'll do both to be doubly sure
>> :-)
>
> Just remove it from the rootfs. Then you will see a message from the
> kernel saying that no external SDMA firmware could be found and that
> the internal one is going to be used.

I gave it a try.  No noticeable  change in behavior.

>
>>> Also, could you try bumping the SSI and SDMA clock rates at the maximum?
>>
>> Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
>> poke around.
>
> You can try to call clk_set_rate() with the maximum allowed frequency
> inside the ssi driver. I don't recall on top of my head what is this
> value though.

I don't know what to use as a parameter to clk_set_rate().  The 2
clocks that I see in the SDMA configuration are clk_ipg, and clk_ahb.
The IMX6SDLRM syas, "configurable clock options for the SDMA core and
the ARM platform DMA units.  1:2 ratio with maximum of SDMA core
running at ARM platform peripheral bus speed and DMS running at max
DMA frequency.  1:1 ratio when both SDMA core and ARM platform DMA
clocks are set to the ARM platform peripheral bus speed"

But, I have a hard time reconsiling that statement with the code in
sdma_init, which references only the ipg and ahb clocks.  I put in a
printk, and found the clk_ipg and clk_ahb to be 132 MHz.

The IMX6SDLRM.pdf, page 4717 says: "...but the SDMA core is physically
limited to a maximum 104 MHz frequency...".

So, I just don't know what clock to set to 104 MHz, or if the 104MHz
really is the right limit.  Any ideas?


This made me think that possibly the problem is with cpufreq
dynamically scaling the core frequency. So I tried:
echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo performance > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor

To ensure that the clocks don't dynamically switch on me, but I still
get channel slips.  Unfortunately,  it's hard to get statistical
measures with my eyeballs (watching a scope with TDM decode).  It
might be a little better, but still fails.

Thanks,
  -Caleb


>
> Regards,
>
> Fabio Estevam
Caleb Crome Oct. 28, 2015, 1:59 p.m. UTC | #17
On Wed, Oct 28, 2015 at 1:11 AM, Roberto Fichera <kernel@tekno-soft.it> wrote:
> On 10/27/2015 07:57 PM, Fabio Estevam wrote:
>> [Adding Roberto in the thread as he is also trying to get SSI TDM support/
>
> Thanks Fabio,
>
> I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
> using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
> this since when in master mode) but valid data set to be 8bits in the SSI register.
>
> My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
> both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
> such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
> Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
> without any apparent reason.

My problem is that the channels randomly slip a slot and all words end
up in the wrong slot.  I suspect this is a DMA issue, but I really
haven't diagnosed it yet.  I don't get a full stop on the data.

FYI, I'm using a very recent 4.3 kernel from linus's repo, but 4.2
behaved the same.

-Caleb

>
>>
>> On Tue, Oct 27, 2015 at 2:45 PM, Fabio Estevam <festevam@gmail.com> wrote:
>>> On Tue, Oct 27, 2015 at 2:42 PM, Caleb Crome <caleb@crome.org> wrote:
>>>> On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
>>>>> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>>>>>
>>>>>>> Could you please try it without using the external SDMA firmware?
>>>>>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>>>>>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>>>>>> 5d4584134cc4cba62e1be2f382cd6f3a.
>>>>> SSI can operate with the ROM SDMA firmware.
>>>>>
>>>>> I would like to know if this issue also happens if you don't pass the
>>>>> external firmware and use the internal ROM SDMA firmware instead.
>>>> Ah, good to know.  Do I just remove reference in the .dtsi file?
>>>> Remove the file from the filesystem?  I'll do both to be doubly sure
>>>> :-)
>>> Just remove it from the rootfs. Then you will see a message from the
>>> kernel saying that no external SDMA firmware could be found and that
>>> the internal one is going to be used.
>>>
>>>>> Also, could you try bumping the SSI and SDMA clock rates at the maximum?
>>>> Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
>>>> poke around.
>>> You can try to call clk_set_rate() with the maximum allowed frequency
>>> inside the ssi driver. I don't recall on top of my head what is this
>>> value though.
>>>
>>> Regards,
>>>
>>> Fabio Estevam
>> _______________________________________________
>> Alsa-devel mailing list
>> Alsa-devel@alsa-project.org
>> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>>
>
Roberto Fichera Oct. 28, 2015, 2:05 p.m. UTC | #18
On 10/28/2015 02:59 PM, Caleb Crome wrote:
> On Wed, Oct 28, 2015 at 1:11 AM, Roberto Fichera <kernel@tekno-soft.it> wrote:
>> On 10/27/2015 07:57 PM, Fabio Estevam wrote:
>>> [Adding Roberto in the thread as he is also trying to get SSI TDM support/
>> Thanks Fabio,
>>
>> I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
>> using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
>> this since when in master mode) but valid data set to be 8bits in the SSI register.
>>
>> My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
>> both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
>> such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
>> Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
>> without any apparent reason.
> My problem is that the channels randomly slip a slot and all words end
> up in the wrong slot.  I suspect this is a DMA issue, but I really
> haven't diagnosed it yet.  I don't get a full stop on the data.

Ah! Ok!

> FYI, I'm using a very recent 4.3 kernel from linus's repo, but 4.2
> behaved the same.

Can you please post the code you are using to setup the SSI, what PCLK and FSYNC rates?
Did you have your own DMA handling?

>
> -Caleb
>
>>> On Tue, Oct 27, 2015 at 2:45 PM, Fabio Estevam <festevam@gmail.com> wrote:
>>>> On Tue, Oct 27, 2015 at 2:42 PM, Caleb Crome <caleb@crome.org> wrote:
>>>>> On Tue, Oct 27, 2015 at 9:10 AM, Fabio Estevam <festevam@gmail.com> wrote:
>>>>>> On Tue, Oct 27, 2015 at 2:02 PM, Caleb Crome <caleb@crome.org> wrote:
>>>>>>
>>>>>>>> Could you please try it without using the external SDMA firmware?
>>>>>>> I do need *some* SDMA firmware, correct?  The firmware that I'm using
>>>>>>> ends up in /lib/firmware/imx/sdma/sdma-imx6q.bin and is md5sum
>>>>>>> 5d4584134cc4cba62e1be2f382cd6f3a.
>>>>>> SSI can operate with the ROM SDMA firmware.
>>>>>>
>>>>>> I would like to know if this issue also happens if you don't pass the
>>>>>> external firmware and use the internal ROM SDMA firmware instead.
>>>>> Ah, good to know.  Do I just remove reference in the .dtsi file?
>>>>> Remove the file from the filesystem?  I'll do both to be doubly sure
>>>>> :-)
>>>> Just remove it from the rootfs. Then you will see a message from the
>>>> kernel saying that no external SDMA firmware could be found and that
>>>> the internal one is going to be used.
>>>>
>>>>>> Also, could you try bumping the SSI and SDMA clock rates at the maximum?
>>>>> Any idea how I do that?  I guess it's in the .dtsi file perhaps?  I'll
>>>>> poke around.
>>>> You can try to call clk_set_rate() with the maximum allowed frequency
>>>> inside the ssi driver. I don't recall on top of my head what is this
>>>> value though.
>>>>
>>>> Regards,
>>>>
>>>> Fabio Estevam
>>> _______________________________________________
>>> Alsa-devel mailing list
>>> Alsa-devel@alsa-project.org
>>> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>>>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
Caleb Crome Oct. 28, 2015, 10:09 p.m. UTC | #19
On Wed, Oct 28, 2015 at 6:59 AM, Caleb Crome <caleb@crome.org> wrote:
> On Wed, Oct 28, 2015 at 1:11 AM, Roberto Fichera <kernel@tekno-soft.it> wrote:
>> On 10/27/2015 07:57 PM, Fabio Estevam wrote:
>>> [Adding Roberto in the thread as he is also trying to get SSI TDM support/
>>
>> Thanks Fabio,
>>
>> I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
>> using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
>> this since when in master mode) but valid data set to be 8bits in the SSI register.
>>
>> My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
>> both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
>> such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
>> Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
>> without any apparent reason.
>
> My problem is that the channels randomly slip a slot and all words end
> up in the wrong slot.  I suspect this is a DMA issue, but I really
> haven't diagnosed it yet.  I don't get a full stop on the data.
>
> FYI, I'm using a very recent 4.3 kernel from linus's repo, but 4.2
> behaved the same.
>

Now I'm recalling when I tried the patches on 4.1, everything
definitely froze.  What kernel are you using?.  I'm basically using
the 4.3-rc7

-Caleb
Roberto Fichera Oct. 29, 2015, 8:04 a.m. UTC | #20
On 10/28/2015 11:09 PM, Caleb Crome wrote:
> On Wed, Oct 28, 2015 at 6:59 AM, Caleb Crome <caleb@crome.org> wrote:
>> On Wed, Oct 28, 2015 at 1:11 AM, Roberto Fichera <kernel@tekno-soft.it> wrote:
>>> On 10/27/2015 07:57 PM, Fabio Estevam wrote:
>>>> [Adding Roberto in the thread as he is also trying to get SSI TDM support/
>>> Thanks Fabio,
>>>
>>> I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
>>> using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
>>> this since when in master mode) but valid data set to be 8bits in the SSI register.
>>>
>>> My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
>>> both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
>>> such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
>>> Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
>>> without any apparent reason.
>> My problem is that the channels randomly slip a slot and all words end
>> up in the wrong slot.  I suspect this is a DMA issue, but I really
>> haven't diagnosed it yet.  I don't get a full stop on the data.
>>
>> FYI, I'm using a very recent 4.3 kernel from linus's repo, but 4.2
>> behaved the same.
>>
> Now I'm recalling when I tried the patches on 4.1, everything
> definitely froze.  What kernel are you using?.  I'm basically using
> the 4.3-rc7

Currently the Freescale offical v3.14.28_ga_1.0.0 coming with Yocto Fido.

>
> -Caleb
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
Nicolin Chen Oct. 29, 2015, 11:04 p.m. UTC | #21
On Wed, Oct 28, 2015 at 09:11:39AM +0100, Roberto Fichera wrote:
 
> I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
> using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
> this since when in master mode) but valid data set to be 8bits in the SSI register.

> My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
> both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
> such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
> Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
> without any apparent reason.

I will start to help you to figure out your problem. But it seems that
you are having a different issue here with clock generation. I don't
get why you said *same issue*. For double confirm, the the "everything
stops" mentioned, does it mean that clock from SSI stops?
Nicolin Chen Oct. 29, 2015, 11:05 p.m. UTC | #22
On Wed, Oct 28, 2015 at 09:23:01AM +0100, Roberto Fichera wrote:
> On 10/27/2015 09:11 PM, Nicolin Chen wrote:
> > On Tue, Oct 27, 2015 at 08:13:44AM +0100, Markus Pargmann wrote:
> >
> >>> So, the dma priority doesn't seem to be the issue.  It's now set in
> >>> the device tree, and strangely it's set to priority 0 (the highest)
> >>> along with the UARTS.  priority 0 is just the highest in the device
> >>> tree -- it gets remapped to priority 3 in the sdma driver.  the DT
> >>> exposes only 3 levels of DMA priority, low, medium, and high.  I
> >>> created a new level that maps to DMA priroity 7 (the highest in the
> >>> hardware), but still got the problem.
> >>>
> >>> So, still something unknown causing dma to miss samples.  must be in
> >>> the dma ISR I would assume.  I guess it's time to look into that.
> >> Cc Nicolin, Fabio, Shawn
> >>
> >> Perhaps you have an idea about this?
> > Off the top of my head:
> >
> > 1) Enable TUE0, TUE1, ROE0, ROE1 to see if there is any IRQ trigged.
> 
> I'm my case I was never able to see an interrupt triggered when setting both RDMAE and TDMAE
> bits in the SIER register.

Your problem may not involve with hardware FIFO underrun at all
so it's quite normal for you to have no IRQ in my opinion.
Roberto Fichera Oct. 30, 2015, 11:42 a.m. UTC | #23
On 10/30/2015 12:04 AM, Nicolin Chen wrote:
> On Wed, Oct 28, 2015 at 09:11:39AM +0100, Roberto Fichera wrote:
>  
>> I'm also having the same issue but employing SSI in TDM master mode against a SLIC Si32178
>> using its PCM mode. PCLK is at 2048KHz, FSYNC is 8KHz slot length is 32 bits (SSI wants
>> this since when in master mode) but valid data set to be 8bits in the SSI register.
>> My Current situation is that I've a custom fsl_ssi.c driver to control the SSI in TDM master mode
>> both PCLK and FSYNC works perfectly fine, the SLIC has a register that I can check via SPI for
>> such purpose, I can see the clocking status from its side. The main problem I've is exactly the same
>> Caleb is having, after a certain amount of SDMA transfers, roughly 1000 or so, everything stops
>> without any apparent reason.
> I will start to help you to figure out your problem. But it seems that
> you are having a different issue here with clock generation. I don't
> get why you said *same issue*. For double confirm, the the "everything
> stops" mentioned, does it mean that clock from SSI stops?
>

Definitively yes! My problem is different than Caleb's one. Just to summarize the things.
I've the SSI1 connected to a SiLabs SLIC Si32178 via AUDMUX6 padmux is below:

        pinctrl_audmux_1: audmuxgrp-3 {
            fsl,pins = <
                MX6SX_PAD_SD3_DATA1__AUDMUX_AUD6_TXC    0x130b0    /* PCLK */
                MX6SX_PAD_SD3_DATA2__AUDMUX_AUD6_TXFS   0x130b0    /* FSYNC */
                MX6SX_PAD_SD3_DATA0__AUDMUX_AUD6_RXD    0x130b0    /* DTX */
                MX6SX_PAD_SD3_DATA3__AUDMUX_AUD6_TXD    0x120b0    /* DRX */
            >;
        };

The Si32178 is slave device so the SSI1 has to generate both BCLK and FSYNC. I've configured
the AUDMUX as:

int si3217x_audmux_config(unsigned int master, unsigned int slave)
{
  unsigned int ptcr, pdcr;
 
  ptcr = IMX_AUDMUX_V2_PTCR_SYN |
         IMX_AUDMUX_V2_PTCR_TFSDIR |
         IMX_AUDMUX_V2_PTCR_TFSEL(master) |
         IMX_AUDMUX_V2_PTCR_TCLKDIR |
         IMX_AUDMUX_V2_PTCR_TCSEL(master);
  pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);
  si3217x_audmux_v2_configure_port(slave, ptcr, pdcr); /* configure internal port */
 
  ptcr = IMX_AUDMUX_V2_PTCR_SYN;
  pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);
  si3217x_audmux_v2_configure_port(master, ptcr, pdcr); /* configure external port */
 
  return 0;
}

BCLK is 2048KHz, FSYNC@8KHz, frame is 32 slots at 8bits each. Looking at TXC and TXFS
with a logical analyzer everything looks ok.

The SSI is setup at beginning as:

        unsigned long flags;
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
        u32 srcr;
        u8 wm;

        clk_prepare_enable(ssi_private->clk);

        /*
         * Section 16.5 of the MPC8610 reference manual says that the
         * SSI needs to be disabled before updating the registers we set
         * here.
         */
        write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);

        /*
         * Program the SSI into I2S Master Network Synchronous mode.
         * Also enable the transmit and receive FIFO.
         */
        write_ssi_mask(&ssi->scr,
            CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
            CCSR_SSI_SCR_I2S_MODE_NORMAL
            | CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_NET
            | CCSR_SSI_SCR_SYS_CLK_EN);

        /*
         * TX falling edge PCLK is mandatory because the RX SLIC side works in this way
         */
        writel( CCSR_SSI_STCR_TXBIT0 /* LSB Aligned */
              | CCSR_SSI_STCR_TFEN0  /* Enable TX FIFO0 */
              | CCSR_SSI_STCR_TSCKP  /* Transmit Clock Polarity - Data Clocked out on falling edge */
              | CCSR_SSI_STCR_TFDIR  /* Transmit Frame Direction Internal - generated internally */
              | CCSR_SSI_STCR_TXDIR, /* Transmit Clock Direction Internal - generated internally */
            &ssi->stcr);

    srcr = readl(&ssi->srcr);

        /*
         * clear out RFDIR and RXDIR because the clock is synchronous
         */
    srcr &= ~(CCSR_SSI_SRCR_RFDIR | CCSR_SSI_SRCR_RXDIR);

        srcr |= CCSR_SSI_SRCR_RXBIT0 /* LSB Aligned */
             |  CCSR_SSI_SRCR_RFEN0  /* Enable RX FIFO0 */
             |  CCSR_SSI_SRCR_RSCKP  /* Receive Clock Polarity - Data latched on rising edge */
            ;

    writel(srcr, &ssi->srcr);

        /* do not service the isr yet */
        writel(0, &ssi->sier);

        /*
         * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
         * don't use FIFO 1.  We program the transmit water to signal a
         * DMA transfer if there are only two (or fewer) elements left
         * in the FIFO. 
         */

       /*
        * tdm_real_slots is 2 because mask all except first 2 slots
        * our buffer is 2 slots * 8 bytes each, so set watermarks to a multiple of it
        * 8 words in our case
        */

        wm = ssi_private->tdm_real_slots * 4; //ssi_private->use_dma ? ssi_private->fifo_depth - 2 :
ssi_private->fifo_depth;

        writel(CCSR_SSI_SFCSR_TFWM0(wm) |
               CCSR_SSI_SFCSR_RFWM0(wm) |
               CCSR_SSI_SFCSR_TFWM1(wm) |
               CCSR_SSI_SFCSR_RFWM1(wm),
               &ssi->sfcsr);

        /* enable one FIFO */
        write_ssi_mask(&ssi->srcr, CCSR_SSI_SRCR_RFEN1, 0);
        write_ssi_mask(&ssi->stcr, CCSR_SSI_STCR_TFEN1, 0);

        /* disable SSI two-channel mode operation */
        write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TCH_EN, 0);

        /*
         * We keep the SSI disabled because if we enable it, then the
         * DMA controller will start.  It's not supposed to start until
         * the SCR.TE (or SCR.RE) bit is set, but it does anyway.  The
         * DMA controller will transfer one "BWC" of data (i.e. the
         * amount of data that the MR.BWC bits are set to).  The reason
         * this is bad is because at this point, the PCM driver has not
         * finished initializing the DMA controller.
         */

        /* Set default slot number -- 32 in our case */
        write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
            CCSR_SSI_SxCCR_DC(ssi_private->tdm_slots));
        write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
            CCSR_SSI_SxCCR_DC(ssi_private->tdm_slots));

        /* Set default word length -- 8 bits */
        write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK,
            CCSR_SSI_SxCCR_WL(ssi_private->tdm_word_size));
        write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK,
            CCSR_SSI_SxCCR_WL(ssi_private->tdm_word_size));

        /* enable the SSI */
        write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, CCSR_SSI_SCR_SSIEN);

        /*
         * we are interested only at first 2 slots
         */
        writel(~ssi_private->tdm_slots_enabled, &ssi->stmsk);
        writel(~ssi_private->tdm_slots_enabled, &ssi->srmsk);

       return 0;
}

SSI clock calculated and then enabled. Both TX and RX DMA channel are requested in the probe() function as below.
and the corresponding TX and RX SDMA event in DTS are using the default from imx6sx.dtsi:

            slave_config.direction = DMA_MEM_TO_DEV;
            slave_config.dst_addr = ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
            slave_config.dst_addr_width = width;
            slave_config.dst_maxburst = ssi_private->tdm_real_slots * 4;
            ret = dmaengine_slave_config(ssi_private->tx_chan, &slave_config);

            ssi_private->rx_chan = dma_request_slave_channel_reason(&pdev->dev, "rx");
            slave_config.direction = DMA_DEV_TO_MEM;
            slave_config.src_addr = ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
            slave_config.src_addr_width = width;
            slave_config.src_maxburst = ssi_private->tdm_real_slots * 4;
            ret = dmaengine_slave_config(ssi_private->rx_chan, &slave_config);

and setup before RDMAE and TDMAE bits, like this:

        ssi_private->tx_buf = dma_alloc_coherent(NULL, buffer_len,
                                        &ssi_private->tx_dmaaddr, GFP_KERNEL);
        desc = dmaengine_prep_dma_cyclic(ssi_private->tx_chan, ssi_private->tx_dmaaddr,
                buffer_len, ssi_private->tdm_real_slots*4,
                DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);

        desc->callback = dma_tx_callback;
        desc->callback_param = ssi_private;

        printk("TX: prepare for the DMA.\n");
        dmaengine_submit(desc);
        dma_async_issue_pending(ssi_private->tx_chan);

        ssi_private->rx_buf = dma_alloc_coherent(NULL, buffer_len,
                                        &ssi_private->rx_dmaaddr, GFP_KERNEL);

        desc = dmaengine_prep_dma_cyclic(ssi_private->rx_chan, ssi_private->rx_dmaaddr,
                buffer_len, ssi_private->tdm_real_slots*4,
                DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);

        desc->callback = dma_rx_callback;
        desc->callback_param = ssi_private;

        printk("RX: prepare for the DMA.\n");
        dmaengine_submit(desc);
        dma_async_issue_pending(ssi_private->rx_chan);

Finally, the SSI's TX and RX parts are now enabled

    scr = readl(&ssi->scr);

    scr |= CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE;   /* enable both TX and RX SSI sections */

    writel(scr, &ssi->scr);

Finally the SIER si programmed as:

   struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
    u32 sier = CCSR_SSI_SIER_RFF0_EN | CCSR_SSI_SIER_TFE0_EN;

    /*
     * if DMA is enabled than allow SSI request for DMA transfers
     * otherwise normal interrupt requests
     */

    if (ssi_private->use_dma>0)
    {
      sier |= CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_TDMAE;
    }
   
    if (ssi_private->use_dma>1 || !ssi_private->use_dma)
    {
      sier |= CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_TIE;
    }

    sier &= ~(CCSR_SSI_SIER_TDE1_EN | CCSR_SSI_SIER_TFE1_EN |
              CCSR_SSI_SIER_TFE0_EN | CCSR_SSI_SIER_TDE0_EN);

    writel(sier, &ssi->sier);

At this time I should see the DMA callbacks called every burst_size words. This behaviour
doesn't really happen as I wish because I can see from a proc file that such callbacks
are called from 1 to 20000 times and then anymore. This is also confirmed by the fact that
the interrupt 34 (sdma) doesn't increase anymore but matches my internal counters collected
within my callbacks. Here is what I can inspect from the data I have collected:

root@voneus-domus-imx6sx:~# cat /proc/domus_ssi_stats
SSI TDM Info:
        PLL clk=66000000
        SSI baudclk=49152000
        ssi_phy=0x02028000
        irq=78
        fifo_depth=15 <---- this is what is read from DTS but not as watermark
        tdm_frame_rate=8000
        tdm_slots=32 (real 2)
        tdm_word_size=8
        tdm_slots_enabled=00000000000000000000000000000011
        clk_frequency=2048000
        clock_running=yes
        DMA=yes
        Dual FIFO=no
        RX DMA frame count=17121
        RX DMA addr=0x9c692000
        RX DMA buffer len=16
        TX DMA frame count=17121
        TX DMA addr=0x9c4aa000
        TX DMA buffer len=16

SSI Registers:
        ssi_scr=0x0000009f
        ssi_sier=0x00500004
        ssi_stcr=0x000002e8
        ssi_srcr=0x00000288
        ssi_stccr=0x00007f0b
        ssi_srccr=0x00007f0b
        ssi_sfcsr=0x0088f088
        ssi_stmsk=0xfffffffc
        ssi_srmsk=0xfffffffc

Cheers,
Roberto Fichera.
Nicolin Chen Oct. 30, 2015, 5:21 p.m. UTC | #24
On Fri, Oct 30, 2015 at 12:42:53PM +0100, Roberto Fichera wrote:


>         /*
>          * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
>          * don't use FIFO 1.  We program the transmit water to signal a
>          * DMA transfer if there are only two (or fewer) elements left
>          * in the FIFO. 
>          */

> SSI clock calculated and then enabled. Both TX and RX DMA channel are requested in the probe() function as below.
> and the corresponding TX and RX SDMA event in DTS are using the default from imx6sx.dtsi:

Since you are using single FIFO configuration, which SDMA script
are you using? This should reflects in the Device Tree. As far as
I learned, FSL 3.14 is using number 22 for SSIs which is the one
for Dual FIFO Mode.

> At this time I should see the DMA callbacks called every burst_size words. This behaviour
> doesn't really happen as I wish because I can see from a proc file that such callbacks
> are called from 1 to 20000 times and then anymore. This is also confirmed by the fact that
> the interrupt 34 (sdma) doesn't increase anymore but matches my internal counters collected
> within my callbacks. Here is what I can inspect from the data I have collected:

Just for clarification, the behaviour doesn't happen as you wish
is just the DMA stopped? I remember you also mentioned bit clock
has stopped as you can check the clock status from the Codec chip.

> SSI Registers:
>         ssi_sfcsr=0x0088f088

At this point you have data in RxFIFO and get empty in TxFIFO, so
the DMA requests from both side should be issued. If the DMA stops
as you described, you must check those two channels from the SDMA
side by dumping SDMAARM_STOP_STAT, SDMAARM_HSTART, SDMAARM_EVTOVR,
SDMAARM_EVTPEND, SDMAARM_EVTERR, SDMAARM_DSPOVR and SDMAARM_HOSTOVR
registers.

Overall, I don't see an obvious defect from you SSI side, but you
may also try to toggle TDMAE and RDMAE at the point that callback
stops -- re-raise the DMA requests by disabling and enabling TDMAE
and RDMAE again and see if it works. I think either something did
intervene register controls of SDMA or SSI, or SDMA have missed the
request signals from SSI.

Patch
diff mbox

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 37c5cd4..73778c2 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -749,7 +749,10 @@  static int fsl_ssi_hw_params(struct snd_pcm_substream
*substream,
                 CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
                 channels == 1 ? 0 : i2smode);
     }
-
+    ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL |
CCSR_SSI_SCR_NET;
+    regmap_update_bits(regs, CCSR_SSI_SCR,
+               CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
+               ssi_private->i2s_mode);
     /*
      * FIXME: The documentation says that SxCCR[WL] should not be
      * modified while the SSI is enabled.  The only time this can
@@ -863,6 +866,15 @@  static int _fsl_ssi_set_dai_fmt(struct device *dev,
         return -EINVAL;
     }
     scr |= ssi_private->i2s_mode;
+    // Set to 16 slots/frame
+    regmap_update_bits(regs, CCSR_SSI_STCCR,
+               CCSR_SSI_SxCCR_DC_MASK,
+               CCSR_SSI_SxCCR_DC(16));
+
+    regmap_update_bits(regs, CCSR_SSI_SRCCR,
+               CCSR_SSI_SxCCR_DC_MASK,
+               CCSR_SSI_SxCCR_DC(16));
+

     /* DAI clock inversion */
     switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -1084,14 +1099,14 @@  static struct snd_soc_dai_driver
fsl_ssi_dai_template = {
     .playback = {
         .stream_name = "CPU-Playback",
         .channels_min = 1,
-        .channels_max = 2,
+        .channels_max = 16,
         .rates = FSLSSI_I2S_RATES,
         .formats = FSLSSI_I2S_FORMATS,
     },
     .capture = {
         .stream_name = "CPU-Capture",
         .channels_min = 1,
-        .channels_max = 2,
+        .channels_max = 16,
         .rates = FSLSSI_I2S_RATES,
         .formats = FSLSSI_I2S_FORMATS,
     },

Another thing I have tried is changing the watermark level for the fifo to
give the DMA interrupt some extra time.  The problem still happens, but
seems to be a bit better.

The fifo watermark change is this:
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 73778c2..7c2e4b0 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -54,6 +54,8 @@ 
 #include "fsl_ssi.h"
 #include "imx-pcm.h"

+#define WATERMARK 8
+
 /**
  * FSLSSI_I2S_RATES: sample rates supported by the I2S
  *
@@ -943,7 +950,7 @@  static int _fsl_ssi_set_dai_fmt(struct device *dev,
      * size.
      */
     if (ssi_private->use_dma)
-        wm = ssi_private->fifo_depth - 2;
+        wm = ssi_private->fifo_depth - WATERMARK;
     else
         wm = ssi_private->fifo_depth;

@@ -1260,8 +1267,8 @@  static int fsl_ssi_imx_probe(struct platform_device
*pdev,
      * We have burstsize be "fifo_depth - 2" to match the SSI
      * watermark setting in fsl_ssi_startup().
      */
-    ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
-    ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
+    ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth -
WATERMARK;
+    ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth -
WATERMARK;