Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f63ef99 authored by Graeme Gregory's avatar Graeme Gregory Committed by Mark Brown
Browse files

ASoC: omap-mcbsp - add support for upto 16 channels.



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: default avatarGraeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
Acked-by: default avatarPeter Ujfalusi <peter.ujfalusi@nokia.com>
Tested-by: default avatarPeter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: default avatarJarkko Nikula <jhnikula@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 9e5d86fe
Loading
Loading
Loading
Loading
+37 −26
Original line number Diff line number Diff line
@@ -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,9 +296,7 @@ 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) {
	if (channels == 2 && format == SND_SOC_DAIFMT_I2S) {
		/* Use dual-phase frames */
		regs->rcr2	|= RPHASE;
		regs->xcr2	|= XPHASE;
@@ -305,16 +305,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
		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;
	}

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
@@ -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,		\
	},							\