[alsa-devel] fsl_ssi.c: Getting channel slips with fsl_ssi.c in TDM (network) mode.

Caleb Crome caleb at crome.org
Tue Oct 20 19:43:14 CEST 2015


On Tue, Oct 20, 2015 at 12:36 AM, arnaud.mouiche at invoxia.com
<arnaud.mouiche at 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 at 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 at 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
>>
>


More information about the Alsa-devel mailing list