alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
From: Liam Girdwood <lrg@slimlogic.co.uk>
To: Raffaele Recalcati <lamiaposta71@gmail.com>
Cc: davinci-linux-open-source@linux.davincidsp.com,
	sudhakar.raj@ti.com, Takashi Iwai <tiwai@suse.de>,
	linux-kernel@vger.kernel.org,
	Mark Brown <broonie@opensource.wolfsonmicro.com>,
	alsa-devel@alsa-project.org,
	Davide Bonfanti <davide.bonfanti@bticino.it>,
	Raffaele Recalcati <raffaele.recalcati@bticino.it>,
	Troy Kisky <troy.kisky@boundarydevices.com>
Subject: Re: [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
Date: Tue, 06 Jul 2010 10:45:59 +0100	[thread overview]
Message-ID: <1278409559.3103.136.camel@odin> (raw)
In-Reply-To: <1278405544-3852-2-git-send-email-lamiaposta71@gmail.com>

On Tue, 2010-07-06 at 10:39 +0200, Raffaele Recalcati wrote:
> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> 
>     Added two clocking options for dm365 McBSP peripheral when used
>     with I2S timings, that are SND_SOC_DAIFMT_CBS_CFS (the cpu generates
>     clock and frame sync) and SND_SOC_DAIFMT_CBS_CFM (the cpu gets clock
>     from external pin and generates frame sync).
>     A slave clock management can be important when the external codec needs
>     the system clock and the bit clock synchronized (tested with uda1345).
>     This patch has been developed against the:
>         http://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci.git
>     git tree and has been tested on bmx board (similar to dm365 evm, but using
>     uda1345 as external audio codec).
> 
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> Signed-off-by: Davide Bonfanti <davide.bonfanti@bticino.it>

All

Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>

But lets get some feedback from the DaVinci folks on this too.

> ---
>  sound/soc/davinci/davinci-i2s.c |  110 +++++++++++++++++++++++++++++++++++---
>  sound/soc/davinci/davinci-i2s.h |    5 ++
>  2 files changed, 106 insertions(+), 9 deletions(-)
> 
> diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
> index adadcd3..c8f038c 100644
> --- a/sound/soc/davinci/davinci-i2s.c
> +++ b/sound/soc/davinci/davinci-i2s.c
> @@ -26,6 +26,7 @@
>  #include <mach/asp.h>
>  
>  #include "davinci-pcm.h"
> +#include "davinci-i2s.h"
>  
> 
>  /*
> @@ -68,16 +69,21 @@
>  #define DAVINCI_MCBSP_RCR_RDATDLY(v)	((v) << 16)
>  #define DAVINCI_MCBSP_RCR_RFIG		(1 << 18)
>  #define DAVINCI_MCBSP_RCR_RWDLEN2(v)	((v) << 21)
> +#define DAVINCI_MCBSP_RCR_RFRLEN2(v)	((v) << 24)
> +#define DAVINCI_MCBSP_RCR_RPHASE	BIT(31)
>  
>  #define DAVINCI_MCBSP_XCR_XWDLEN1(v)	((v) << 5)
>  #define DAVINCI_MCBSP_XCR_XFRLEN1(v)	((v) << 8)
>  #define DAVINCI_MCBSP_XCR_XDATDLY(v)	((v) << 16)
>  #define DAVINCI_MCBSP_XCR_XFIG		(1 << 18)
>  #define DAVINCI_MCBSP_XCR_XWDLEN2(v)	((v) << 21)
> +#define DAVINCI_MCBSP_XCR_XFRLEN2(v)	((v) << 24)
> +#define DAVINCI_MCBSP_XCR_XPHASE	BIT(31)
>  
>  #define DAVINCI_MCBSP_SRGR_FWID(v)	((v) << 8)
>  #define DAVINCI_MCBSP_SRGR_FPER(v)	((v) << 16)
>  #define DAVINCI_MCBSP_SRGR_FSGM		(1 << 28)
> +#define DAVINCI_MCBSP_SRGR_CLKSM	BIT(29)
>  
>  #define DAVINCI_MCBSP_PCR_CLKRP		(1 << 0)
>  #define DAVINCI_MCBSP_PCR_CLKXP		(1 << 1)
> @@ -144,6 +150,9 @@ struct davinci_mcbsp_dev {
>  	 * won't end up being swapped because of the underrun.
>  	 */
>  	unsigned enable_channel_combine:1;
> +
> +	unsigned int fmt;
> +	int clk_div;
>  };
>  
>  static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
> @@ -254,10 +263,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
>  	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
>  	unsigned int pcr;
>  	unsigned int srgr;
> +	/* Attention srgr is updated by hw_params! */
>  	srgr = DAVINCI_MCBSP_SRGR_FSGM |
>  		DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
>  		DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
>  
> +	dev->fmt = fmt;
>  	/* set master/slave audio interface */
>  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
>  	case SND_SOC_DAIFMT_CBS_CFS:
> @@ -372,6 +383,18 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
>  	return 0;
>  }
>  
> +static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
> +				int div_id, int div)
> +{
> +	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
> +
> +	if (div_id != DAVINCI_MCBSP_CLKGDV)
> +		return -ENODEV;
> +
> +	dev->clk_div = div;
> +	return 0;
> +}
> +
>  static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  				 struct snd_pcm_hw_params *params,
>  				 struct snd_soc_dai *dai)
> @@ -380,8 +403,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  	struct davinci_pcm_dma_params *dma_params =
>  					&dev->dma_params[substream->stream];
>  	struct snd_interval *i = NULL;
> -	int mcbsp_word_length;
> -	unsigned int rcr, xcr, srgr;
> +	int mcbsp_word_length, master;
> +	unsigned int rcr, xcr, srgr, clk_div, freq, framesize;
>  	u32 spcr;
>  	snd_pcm_format_t fmt;
>  	unsigned element_cnt = 1;
> @@ -396,12 +419,47 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
>  	}
>  
> -	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
> -	srgr = DAVINCI_MCBSP_SRGR_FSGM;
> -	srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
> +	master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
> +	fmt = params_format(params);
> +	mcbsp_word_length = asp_word_length[fmt];
>  
> -	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
> -	srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
> +	switch (master) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		freq = clk_get_rate(dev->clk);
> +		srgr = DAVINCI_MCBSP_SRGR_FSGM |
> +		       DAVINCI_MCBSP_SRGR_CLKSM;
> +		srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *
> +						8 - 1);
> +		/* symmetric waveforms */
> +		clk_div = freq / (mcbsp_word_length * 16) /
> +			  params->rate_num * params->rate_den;
> +		srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
> +						16 - 1);
> +		clk_div &= 0xFF;
> +		srgr |= clk_div;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFS:
> +		srgr = DAVINCI_MCBSP_SRGR_FSGM;
> +		clk_div = dev->clk_div - 1;
> +		srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);
> +		srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);
> +		clk_div &= 0xFF;
> +		srgr |= clk_div;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		/* Clock and frame sync given from external sources */
> +		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
> +		srgr = DAVINCI_MCBSP_SRGR_FSGM;
> +		srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
> +		pr_debug("%s - %d  FWID set: re-read srgr = %X\n",
> +			__func__, __LINE__, snd_interval_value(i) - 1);
> +
> +		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
> +		srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
>  
>  	rcr = DAVINCI_MCBSP_RCR_RFIG;
> @@ -426,12 +484,41 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  			element_cnt = 1;
>  			fmt = double_fmt[fmt];
>  		}
> +		switch (master) {
> +		case SND_SOC_DAIFMT_CBS_CFS:
> +		case SND_SOC_DAIFMT_CBS_CFM:
> +			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0);
> +			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0);
> +			rcr |= DAVINCI_MCBSP_RCR_RPHASE;
> +			xcr |= DAVINCI_MCBSP_XCR_XPHASE;
> +			break;
> +		case SND_SOC_DAIFMT_CBM_CFM:
> +		case SND_SOC_DAIFMT_CBM_CFS:
> +			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);
> +			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
>  	}
>  	dma_params->acnt = dma_params->data_type = data_type[fmt];
>  	dma_params->fifo_level = 0;
>  	mcbsp_word_length = asp_word_length[fmt];
> -	rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
> -	xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
> +
> +	switch (master) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +	case SND_SOC_DAIFMT_CBS_CFM:
> +		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);
> +		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +	case SND_SOC_DAIFMT_CBM_CFS:
> +		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
> +		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  
>  	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
>  		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
> @@ -442,6 +529,10 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
>  		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
>  	else
>  		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
> +
> +	pr_debug("%s - %d  srgr=%X\n", __func__, __LINE__, srgr);
> +	pr_debug("%s - %d  xcr=%X\n", __func__, __LINE__, xcr);
> +	pr_debug("%s - %d  rcr=%X\n", __func__, __LINE__, rcr);
>  	return 0;
>  }
>  
> @@ -500,6 +591,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
>  	.trigger	= davinci_i2s_trigger,
>  	.hw_params	= davinci_i2s_hw_params,
>  	.set_fmt	= davinci_i2s_set_dai_fmt,
> +	.set_clkdiv	= davinci_i2s_dai_set_clkdiv,
>  
>  };
>  
> diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
> index 241648c..0b1e77b 100644
> --- a/sound/soc/davinci/davinci-i2s.h
> +++ b/sound/soc/davinci/davinci-i2s.h
> @@ -12,6 +12,11 @@
>  #ifndef _DAVINCI_I2S_H
>  #define _DAVINCI_I2S_H
>  
> +/* McBSP dividers */
> +enum davinci_mcbsp_div {
> +	DAVINCI_MCBSP_CLKGDV,              /* Sample rate generator divider */
> +};
> +
>  extern struct snd_soc_dai davinci_i2s_dai;
>  
>  #endif

-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk

  reply	other threads:[~2010-07-06  9:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1278405544-3852-1-git-send-email-lamiaposta71@gmail.com>
2010-07-06  8:39 ` [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S) Raffaele Recalcati
2010-07-06  9:45   ` Liam Girdwood [this message]
2010-07-06 11:30     ` Sudhakar Rajashekhara
2010-07-06 11:30     ` Sudhakar Rajashekhara
     [not found]     ` <003001cb1cfe$a043a610$e0caf230$@raj@ti.com>
2010-07-06 14:54       ` Mark Brown
2010-07-06  8:39 ` [PATCH 2/3] ASoC: DaVinci: Added selection of clk input pin for McBSP Raffaele Recalcati
2010-07-06  8:39 ` [PATCH 3/3] ASoC: DaVinci: More accurate continuous serial clock for McBSP (I2S) Raffaele Recalcati
     [not found] <1277905678-4695-1-git-send-email-lamiaposta71@gmail.com>
2010-06-30 13:47 ` [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to " Raffaele Recalcati
2010-07-01 14:35   ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1278409559.3103.136.camel@odin \
    --to=lrg@slimlogic.co.uk \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@opensource.wolfsonmicro.com \
    --cc=davide.bonfanti@bticino.it \
    --cc=davinci-linux-open-source@linux.davincidsp.com \
    --cc=lamiaposta71@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=raffaele.recalcati@bticino.it \
    --cc=sudhakar.raj@ti.com \
    --cc=tiwai@suse.de \
    --cc=troy.kisky@boundarydevices.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).