[alsa-devel] [PATCH V3] ASoC: omap-mcbsp - add support for upto 16 channels.
This time we use wlen * channels when CODEC masters BCLK and FRAME, otherwise same as V2.
From: Graeme Gregory gg@slimlogic.co.uk
This patch increases the number of supported audio channels from 4 to 16 and has been sponsored by Shotspotter Inc. It also fixes a FSYNC rate calculation bug when McBSP is FSYNC master.
Signed-off-by: Graeme Gregory gg@slimlogic.co.uk Signed-off-by: Liam Girdwood lrg@slimlogic.co.uk --- sound/soc/omap/omap-mcbsp.c | 63 +++++++++++++++++++++++++----------------- 1 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 3341f49..45be942 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -49,6 +49,8 @@ struct omap_mcbsp_data { */ int active; int configured; + unsigned int in_freq; + int clk_div; };
#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) @@ -257,7 +259,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; unsigned long port; - unsigned int format; + unsigned int format, div, framesize, master;
if (cpu_class_is_omap1()) { dma = omap1_dma_reqs[bus_id][substream->stream]; @@ -294,28 +296,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels = params_channels(params); - switch (channels) { - case 2: - if (format == SND_SOC_DAIFMT_I2S) { - /* Use dual-phase frames */ - regs->rcr2 |= RPHASE; - regs->xcr2 |= XPHASE; - /* Set 1 word per (McBSP) frame for phase1 and phase2 */ - wpf--; - regs->rcr2 |= RFRLEN2(wpf - 1); - regs->xcr2 |= XFRLEN2(wpf - 1); - } - case 1: - case 4: - /* Set word per (McBSP) frame for phase1 */ - regs->rcr1 |= RFRLEN1(wpf - 1); - regs->xcr1 |= XFRLEN1(wpf - 1); - break; - default: - /* Unsupported number of channels */ - return -EINVAL; + if (channels == 2 && format == SND_SOC_DAIFMT_I2S) { + /* Use dual-phase frames */ + regs->rcr2 |= RPHASE; + regs->xcr2 |= XPHASE; + /* Set 1 word per (McBSP) frame for phase1 and phase2 */ + wpf--; + regs->rcr2 |= RFRLEN2(wpf - 1); + regs->xcr2 |= XFRLEN2(wpf - 1); }
+ regs->rcr1 |= RFRLEN1(wpf - 1); + regs->xcr1 |= XFRLEN1(wpf - 1); + switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ @@ -330,15 +323,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; }
+ /* In McBSP master modes, FRAME (i.e. sample rate) is generated + * by _counting_ BCLKs. Calculate frame size in BCLKs */ + master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK; + if (master == SND_SOC_DAIFMT_CBS_CFS) { + div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1; + framesize = (mcbsp_data->in_freq / div) / params_rate(params); + + if (framesize < wlen * channels) { + printk(KERN_ERR "%s: not enough bandwidth for desired rate and " + "channels\n", __func__); + return -EINVAL; + } + } else + framesize = wlen * channels; + /* Set FS period and length in terms of bit clock periods */ switch (format) { case SND_SOC_DAIFMT_I2S: - regs->srgr2 |= FPER(wlen * channels - 1); - regs->srgr1 |= FWID(wlen - 1); + regs->srgr2 |= FPER(framesize - 1); + regs->srgr1 |= FWID((framesize >> 1) - 1); break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: - regs->srgr2 |= FPER(wlen * channels - 1); + regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID(0); break; } @@ -454,6 +462,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, if (div_id != OMAP_MCBSP_CLKGDV) return -ENODEV;
+ mcbsp_data->clk_div = div; regs->srgr1 |= CLKGDV(div - 1);
return 0; @@ -554,6 +563,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int err = 0;
+ mcbsp_data->in_freq = freq; + switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: regs->srgr2 |= CLKSM; @@ -598,13 +609,13 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { .id = (link_id), \ .playback = { \ .channels_min = 1, \ - .channels_max = 4, \ + .channels_max = 16, \ .rates = OMAP_MCBSP_RATES, \ .formats = SNDRV_PCM_FMTBIT_S16_LE, \ }, \ .capture = { \ .channels_min = 1, \ - .channels_max = 4, \ + .channels_max = 16, \ .rates = OMAP_MCBSP_RATES, \ .formats = SNDRV_PCM_FMTBIT_S16_LE, \ }, \
On Monday 09 November 2009 21:02:15 ext Liam Girdwood wrote:
This time we use wlen * channels when CODEC masters BCLK and FRAME, otherwise same as V2.
From: Graeme Gregory gg@slimlogic.co.uk
This patch increases the number of supported audio channels from 4 to 16 and has been sponsored by Shotspotter Inc. It also fixes a FSYNC rate calculation bug when McBSP is FSYNC master.
Signed-off-by: Graeme Gregory gg@slimlogic.co.uk Signed-off-by: Liam Girdwood lrg@slimlogic.co.uk
Looks good, and works when OMAP McBSP is slave. Thank you!
I'm not sure, if both acked and tested can be added... Mark, please pick the relevant:
Acked-by: Peter Ujfalusi peter.ujfalusi@nokia.com Tested-by: Peter Ujfalusi peter.ujfalusi@nokia.com
On Tue, 10 Nov 2009 08:25:27 +0200 Peter Ujfalusi peter.ujfalusi@nokia.com wrote:
Looks good, and works when OMAP McBSP is slave. Thank you!
I'm not sure, if both acked and tested can be added... Mark, please pick the relevant:
Acked-by: Peter Ujfalusi peter.ujfalusi@nokia.com Tested-by: Peter Ujfalusi peter.ujfalusi@nokia.com
Acked-by: Jarkko Nikula jhnikula@gmail.com
On Mon, Nov 09, 2009 at 07:02:15PM +0000, Liam Girdwood wrote:
This time we use wlen * channels when CODEC masters BCLK and FRAME, otherwise same as V2.
Applied, thanks.
From: Graeme Gregory gg@slimlogic.co.uk
git am doesn't appear to notice From lines that aren't the very first line of the body.
participants (4)
-
Jarkko Nikula
-
Liam Girdwood
-
Mark Brown
-
Peter Ujfalusi