[alsa-devel] [PATCH 1/4] ASoC: pxa-ssp: enhance I2S and add Left_J support

Paul Shen boshen9 at gmail.com
Tue Jun 9 11:39:53 CEST 2009


Hi Daniel,

Would you please give some informations about your platform ?
Thus I can test the patches with your method.

2009/6/6 Daniel Ribeiro <drwyrm at gmail.com>:
> Em Qua, 2009-06-03 às 20:33 +0800, Eric Miao escreveu:
>> Make the pxa I2S configuration generic, add support for Left_J, add
>> support for variable frame width like 32fs, 48fs, 64fs and 96fs
>>
>> Signed-off-by: Paul Shen <bshen9 at marvell.com>
>> Signed-off-by: Eric Miao <eric.miao at marvell.com>
>> Cc: Daniel Mack <daniel at caiaq.de>
>> ---
>>  arch/arm/mach-pxa/include/mach/regs-ssp.h |   14 +++---
>>  sound/soc/pxa/pxa-ssp.c                   |   62 ++++++++++++++--------------
>>  sound/soc/pxa/pxa-ssp.h                   |    9 ++++
>>  3 files changed, 47 insertions(+), 38 deletions(-)
>>
>> diff --git a/arch/arm/mach-pxa/include/mach/regs-ssp.h
>> b/arch/arm/mach-pxa/include/mach/regs-ssp.h
>> index 6a2ed35..27f0cd4 100644
>> --- a/arch/arm/mach-pxa/include/mach/regs-ssp.h
>> +++ b/arch/arm/mach-pxa/include/mach/regs-ssp.h
>> @@ -108,21 +108,21 @@
>>  #define SSSR_TINT            (1 << 19)       /* Receiver Time-out Interrupt */
>>  #define SSSR_PINT            (1 << 18)       /* Peripheral Trailing Byte Interrupt */
>>
>> -#if defined(CONFIG_PXA3xx)
>> -#define SSPSP_EDMYSTOP(x)    ((x) << 28)     /* Extended Dummy Stop */
>> -#define SSPSP_EDMYSTRT(x)    ((x) << 26)     /* Extended Dummy Start */
>> -#endif
>> -
>>  #define SSPSP_FSRT           (1 << 25)       /* Frame Sync Relative Timing */
>> -#define SSPSP_DMYSTOP(x)     ((x) << 23)     /* Dummy Stop */
>>  #define SSPSP_SFRMWDTH(x)    ((x) << 16)     /* Serial Frame Width */
>>  #define SSPSP_SFRMDLY(x)     ((x) << 9)      /* Serial Frame Delay */
>> -#define SSPSP_DMYSTRT(x)     ((x) << 7)      /* Dummy Start */
>>  #define SSPSP_STRTDLY(x)     ((x) << 4)      /* Start Delay */
>>  #define SSPSP_ETDS           (1 << 3)        /* End of Transfer data State */
>>  #define SSPSP_SFRMP          (1 << 2)        /* Serial Frame Polarity */
>>  #define SSPSP_SCMODE(x)              ((x) << 0)      /* Serial Bit Rate Clock Mode */
>>
>> +/* NOTE: PXA3xx extends the bit number of dummy start and stop, the macros
>> + * below are compatible with PXA25x/27x as long as the parameter is within
>> + * the correct limits, driver code has to take care of this.
>> + */
>> +#define SSPSP_DMYSTRT(x)     ((((x) & 3) << 7)  | ((((x) >> 2) & 3) << 26))
>> +#define SSPSP_DMYSTOP(x)     ((((x) & 3) << 23) | ((((x) >> 2) & 7) << 28))
>> +
>>  #define SSACD_SCDB           (1 << 3)        /* SSPSYSCLK Divider Bypass */
>>  #define SSACD_ACPS(x)                ((x) << 4)      /* Audio clock PLL select */
>>  #define SSACD_ACDS(x)                ((x) << 0)      /* Audio clock divider select */
>> diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
>> index 6fc7876..2831c16 100644
>> --- a/sound/soc/pxa/pxa-ssp.c
>> +++ b/sound/soc/pxa/pxa-ssp.c
>> @@ -463,7 +463,8 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
>>
>>       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
>>       case SND_SOC_DAIFMT_I2S:
>> -             sscr0 |= SSCR0_PSP;
>> +     case SND_SOC_DAIFMT_LEFT_J:
>> +             sscr0 |= SSCR0_PSP | SSCR0_MOD;
>
> Why do you enforce network mode here?
>
>>               sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
>>
>>               /* See hw_params() */
>> @@ -541,6 +542,7 @@ static int pxa_ssp_hw_params(struct
>> snd_pcm_substream *substream,
>>       int chn = params_channels(params);
>>       u32 sscr0;
>>       u32 sspsp;
>> +     int frame_width;
>>       int width = snd_pcm_format_physical_width(params_format(params));
>>       int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
>>
>> @@ -585,40 +587,38 @@ static int pxa_ssp_hw_params(struct
>> snd_pcm_substream *substream,
>>
>>       switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
>>       case SND_SOC_DAIFMT_I2S:
>> -            sspsp = ssp_read_reg(ssp, SSPSP);
>> -
>> -             if ((ssp_get_scr(ssp) == 4) && (width == 16)) {
>> -                     /* This is a special case where the bitclk is 64fs
>> -                     * and we're not dealing with 2*32 bits of audio
>> -                     * samples.
>> -                     *
>> -                     * The SSP values used for that are all found out by
>> -                     * trying and failing a lot; some of the registers
>> -                     * needed for that mode are only available on PXA3xx.
>> -                     */
>> +             sspsp = ssp_read_reg(ssp, SSPSP);
>> +             frame_width = PXA_SSP_FRM_WIDTH(priv->dai_fmt);
>
> I would expect FRM_WIDTH to also change SSCR0_EDSS and SSCR0_DataSize
>
>>
>> -#ifdef CONFIG_PXA3xx
>> -                     if (!cpu_is_pxa3xx())
>> -                             return -EINVAL;
>> -
>> -                     sspsp |= SSPSP_SFRMWDTH(width * 2);
>> -                     sspsp |= SSPSP_SFRMDLY(width * 4);
>> -                     sspsp |= SSPSP_EDMYSTOP(3);
>> -                     sspsp |= SSPSP_DMYSTOP(3);
>> -                     sspsp |= SSPSP_DMYSTRT(1);
>> -#else
>> +             if (frame_width < width * 2)
>>                       return -EINVAL;
>> -#endif
>> -             } else {
>> -                     /* The frame width is the width the LRCLK is
>> -                      * asserted for; the delay is expressed in
>> -                      * half cycle units.  We need the extra cycle
>> -                      * because the data starts clocking out one BCLK
>> -                      * after LRCLK changes polarity.
>> +
>> +             if (frame_width == width * 2)
>> +                     /* frame width is exactly double of data sample width,
>> +                      * use FSRT instead
>>                        */
>> -                     sspsp |= SSPSP_SFRMWDTH(width + 1);
>> -                     sspsp |= SSPSP_SFRMDLY((width + 1) * 2);
>> +                     sspsp |= SSPSP_FSRT | SSPSP_SFRMWDTH(width);
>> +             else {
>>                       sspsp |= SSPSP_DMYSTRT(1);
>> +                     sspsp |= SSPSP_DMYSTOP((frame_width / 2 - width - 1));
>> +                     sspsp |= SSPSP_SFRMWDTH(frame_width / 2);
>> +             }
>> +
>> +             ssp_write_reg(ssp, SSPSP, sspsp);
>> +             break;
>> +
>> +     case SND_SOC_DAIFMT_LEFT_J:
>> +             sspsp = ssp_read_reg(ssp, SSPSP);
>> +             frame_width = PXA_SSP_FRM_WIDTH(priv->dai_fmt);
>> +
>> +             if (frame_width < width * 2)
>> +                     return -EINVAL;
>> +
>> +             if (frame_width == width * 2)
>> +                     sspsp |= SSPSP_SFRMWDTH(width);
>> +             else {
>> +                     sspsp |= SSPSP_DMYSTOP((frame_width / 2 - width));
>> +                     sspsp |= SSPSP_SFRMWDTH(frame_width / 2);
>>               }
>>
>>               ssp_write_reg(ssp, SSPSP, sspsp);
>> diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h
>> index 91deadd..fda51d0 100644
>> --- a/sound/soc/pxa/pxa-ssp.h
>> +++ b/sound/soc/pxa/pxa-ssp.h
>> @@ -40,6 +40,15 @@
>>  #define PXA_SSP_CLK_SCDB_1           1
>>  #define PXA_SSP_CLK_SCDB_8           2
>>
>> +/* frame size definitions for I2S and Left_J formats - default is
>> + * 32fs, other possibilities are 48fs, 64fs and 96fs
>> + */
>> +#define PXA_SSP_FRM_32FS     (0 << 16)
>> +#define PXA_SSP_FRM_48FS     (1 << 16)
>> +#define PXA_SSP_FRM_64FS     (2 << 16)
>> +#define PXA_SSP_FRM_96FS     (3 << 16)
>> +#define PXA_SSP_FRM_WIDTH(x) (((((x) >> 16) & 0x3) + 2) << 4)
>> +
>>  #define PXA_SSP_PLL_OUT  0
>>
>>  extern struct snd_soc_dai pxa_ssp_dai[4];
>
> I am testing this patch with PXA272 slave of clock and frame,
> DAIFMT_LEFT_J, tdm_slot(3,2), and it causes my audio to play with double
> speed. (with tdm_slot(1,1) it plays at half speed).
>
> Values that are known to work fine for my board are:
> SSCR0 = 0x1000bf
> SSPSP = 0x100002
>
>
> --
> Daniel Ribeiro
>


Would you please give me code extract about your SSP, codec
configurations and clock setting?

-- 
Paul Shen


More information about the Alsa-devel mailing list