Em Seg, 2009-06-08 às 17:53 +0100, Mark Brown escreveu: > I'd like to see all these details handled within the driver - knowing if > and when network mode are to be set up is the sort of thing that users > ought to be able to rely on the driver for. Untested, RFC only version of patch. (plus some minor copynpaste and whitespace fixes) Am I on the right direction? :) include/sound/soc-dai.h | 3 + sound/soc/pxa/pxa-ssp.c | 86 +++++++++++++++++++++++++++++------------------- sound/soc/soc-core.c | 13 ++++--- 3 files changed, 62 insertions(+), 40 deletions(-) -- diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1367647..0bf9502 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,7 +154,8 @@ struct snd_soc_dai_ops { */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); int (*set_tdm_slot)(struct snd_soc_dai *dai, - unsigned int mask, int slots); + unsigned int tx_mask, unsigned int rx_mask, + int slots, int frame_width); int (*set_tristate)(struct snd_soc_dai *dai, int tristate); /* diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 92838af..a0b7bad 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -490,21 +490,31 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, * Set the active slots in TDM/Network mode */ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, - unsigned int mask, int slots) + unsigned int tx_mask, unsigned int rx_mask, int slots, int frame_width) { struct ssp_priv *priv = cpu_dai->private_data; struct ssp_device *ssp = priv->dev.ssp; u32 sscr0; - sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7); + sscr0 = ssp_read_reg(ssp, SSCR0); + sscr0 &= ~(SSCR0_SlotsPerFrm(7) | SSCR0_EDSS | SSCR0_DSS); + + /* enable network mode */ + sscr0 |= SSCR0_MOD; + + /* set frame width */ + if (frame_width > 16) + sscr0 |= SSCR0_EDSS | SSCR0_DataSize(frame_width - 16); + else + sscr0 |= SSCR0_DataSize(frame_width); /* set number of active slots */ sscr0 |= SSCR0_SlotsPerFrm(slots); ssp_write_reg(ssp, SSCR0, sscr0); /* set active slot mask */ - ssp_write_reg(ssp, SSTSA, mask); - ssp_write_reg(ssp, SSRSA, mask); + ssp_write_reg(ssp, SSTSA, tx_mask); + ssp_write_reg(ssp, SSRSA, rx_mask); return 0; } @@ -555,7 +565,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* reset port settings */ sscr0 = ssp_read_reg(ssp, SSCR0) & - (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); + (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); sspsp = 0; @@ -602,7 +612,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_DSP_A: sspsp |= SSPSP_FSRT; case SND_SOC_DAIFMT_DSP_B: - sscr0 |= SSCR0_MOD | SSCR0_PSP; + sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -652,10 +662,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, struct ssp_priv *priv = cpu_dai->private_data; struct ssp_device *ssp = priv->dev.ssp; int dma = 0, chn = params_channels(params); - u32 sscr0; + u32 sscr0, sscr1; u32 sspsp; int width = snd_pcm_format_physical_width(params_format(params)); - int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; + int frame_width = width * chn; /* select correct DMA params */ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) @@ -664,7 +674,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, * to force 16-bit frame width on the wire (for S16_LE), even * with two channels. Use 16-bit DMA transfers for this case. */ - if (((chn == 2) && (ttsa != 1)) || (width == 32)) + if (frame_width >= 32) dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */ cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma]; @@ -675,32 +685,48 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) return 0; - /* clear selected SSP bits */ - sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); - ssp_write_reg(ssp, SSCR0, sscr0); + /* frame width */ + sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_EDSS | SSCR0_DSS); - /* bit size */ - sscr0 = ssp_read_reg(ssp, SSCR0); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: + /* FIXME: Is this needed? */ #ifdef CONFIG_PXA3xx - if (cpu_is_pxa3xx()) - sscr0 |= SSCR0_FPCKE; + if (width == 16 && cpu_is_pxa3xx()) + sscr0 |= SSCR0_FPCKE; #endif + + if (!(sscr0 & SSCR0_MOD)) { + + /* Not on network mode, setup the frame width */ sscr0 |= SSCR0_DataSize(16); - break; - case SNDRV_PCM_FORMAT_S24_LE: - sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); - break; - case SNDRV_PCM_FORMAT_S32_LE: - sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); - break; + if (frame_width >= 32) + sscr0 |= SSCR0_EDSS; + + if (frame_width > 32) { + /* + * Network mode is needed to support this frame_width + * We assume that the wire is not networked and setup + * a "fake" network mode here. + */ + int slots = frame_width / 32; + + sscr0 |= SSCR0_MOD; + sscr0 |= SSCR0_SlotsPerFrm(slots); + ssp_write_reg(ssp, SSTSA, slots - 1); + ssp_write_reg(ssp, SSRSA, slots - 1); + } + } + + /* If SSCR0_MOD is set we can't use SSCR1_RWOT */ + if (sscr0 & SSCR0_MOD) { + sscr1 = ssp_read_reg(ssp, SSCR1); + ssp_write_reg(ssp, SSCR1, sscr1 & ~SSCR1_RWOT); } + ssp_write_reg(ssp, SSCR0, sscr0); switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sspsp = ssp_read_reg(ssp, SSPSP); + sspsp = ssp_read_reg(ssp, SSPSP); if ((ssp_get_scr(ssp) == 4) && (width == 16)) { /* This is a special case where the bitclk is 64fs @@ -742,14 +768,6 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, break; } - /* When we use a network mode, we always require TDM slots - * - complain loudly and fail if they've not been set up yet. - */ - if ((sscr0 & SSCR0_MOD) && !ttsa) { - dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); - return -EINVAL; - } - dump_registers(ssp); return 0; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c9f19d0..ce13b6d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2130,17 +2130,20 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); /** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI - * @mask: DAI specific mask representing used slots. + * @tx_mask: DAI specific mask representing TX slots. + * @rx_mask: DAI specific mask representing RX slots. * @slots: Number of slots in use. + * @frame_width: Width in bits for each slot. * * Configures a DAI for TDM operation. Both mask and slots are codec and DAI * specific. */ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int mask, int slots) + unsigned int tx_mask, unsigned int rx_mask, int slots, int frame_width) { - if (dai->ops->set_sysclk) - return dai->ops->set_tdm_slot(dai, mask, slots); + if (dai->ops->set_tdm_slot) + return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, + slots, frame_width); else return -EINVAL; } @@ -2155,7 +2158,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); */ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) { - if (dai->ops->set_sysclk) + if (dai->ops->set_tristate) return dai->ops->set_tristate(dai, tristate); else return -EINVAL; -- Daniel Ribeiro
Attachment:
signature.asc
Description: Esta =?ISO-8859-1?Q?=E9?= uma parte de mensagem assinada digitalmente
_______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel