[alsa-devel] [PATCH 1/4] ASoC: pxa-ssp: enhance I2S and add Left_J support
Daniel Ribeiro
drwyrm at gmail.com
Sat Jun 6 10:26:45 CEST 2009
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Esta =?ISO-8859-1?Q?=E9?= uma parte de mensagem
assinada digitalmente
Url : http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20090606/abbfc2cc/attachment.sig
More information about the Alsa-devel
mailing list