[alsa-devel] [PATCH] ASoC - Add support for upto 16 channels on OMAP MCBSP
Peter Ujfalusi
peter.ujfalusi at nokia.com
Thu Nov 5 09:26:39 CET 2009
On Wednesday 04 November 2009 19:53:55 ext Liam Girdwood wrote:
> From: Graeme Gregory <gg at slimlogic.co.uk>
>
> This patch increases the number of supported audio channels from 4
> to 16 and was sponsored by Shotspotter inc.
>
> Signed-off-by: Graeme Gregory <gg at slimlogic.co.uk>
> Signed-off-by: Liam Girdwood <lrg at slimlogic.co.uk>
> ---
> sound/soc/omap/omap-mcbsp.c | 71
> +++++++++++++++++++++++++++++------------- 1 files changed, 49
> insertions(+), 22 deletions(-)
>
> diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
> index 3341f49..290ef2f 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, frame_size, div;
>
> if (cpu_class_is_omap1()) {
> dma = omap1_dma_reqs[bus_id][substream->stream];
> @@ -294,27 +296,23 @@ 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:
> + 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);
> /* Set word per (McBSP) frame for phase1 */
> regs->rcr1 |= RFRLEN1(wpf - 1);
> regs->xcr1 |= XFRLEN1(wpf - 1);
> - break;
> - default:
> + } else if (channels > 0 && channels < 17) {
> + regs->rcr1 |= RFRLEN1(wpf - 1);
> + regs->xcr1 |= XFRLEN1(wpf - 1);
> + } else
> /* Unsupported number of channels */
> return -EINVAL;
> - }
I would have done this a bit differently:
...
/* Check if the number of channels are valid */
if (channels < 1 || channels > 16) {
/* Unsupported number of channels */
/* Probably would be good to have some error message about it? */
return -EINVAL;
}
format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
wpf = channels = params_channels(params);
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);
}
/* Set word per (McBSP) frame for phase1 */
regs->rcr1 |= RFRLEN1(wpf - 1);
regs->xcr1 |= XFRLEN1(wpf - 1);
>
> switch (params_format(params)) {
> case SNDRV_PCM_FORMAT_S16_LE:
> @@ -330,6 +328,34 @@ static int omap_mcbsp_dai_hw_params(struct
> snd_pcm_substream *substream, return -EINVAL;
> }
>
> + /* Default div to 1 if it wasn't set by machine driver, otherwise
> + * use set div as the maximum clock value
> + */
> + div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
> +
> + /* calc best frame size for rate and clock divider */
> + do {
> + frame_size = (mcbsp_data->in_freq / div) / params_rate(params);
I think this as it is now will not work when McBSP is a slave.
mcbsp_data->in_freq is going to be 0, since the sample rate generator is not in
use.
> + pr_debug("freq %d, rate %d, frame size %d, div %d\n",
> + mcbsp_data->in_freq, params_rate(params), frame_size, div);
> +
> + if (frame_size > 256)
> + div++;
> + } while (frame_size > 256);
> +
> + /* Check we can fit the requested number of channels into our
> + * calculated frame size
> + */
> + if ((channels * wlen) > frame_size) {
> + printk(KERN_ERR
> + "OMAP-MCBSP: cannot fit channels in frame size\n");
> + return -EINVAL;
> + }
--
Péter
More information about the Alsa-devel
mailing list