alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
       [not found] <1277905678-4695-1-git-send-email-lamiaposta71@gmail.com>
@ 2010-06-30 13:47 ` Raffaele Recalcati
  2010-07-01 14:35   ` Mark Brown
  0 siblings, 1 reply; 9+ messages in thread
From: Raffaele Recalcati @ 2010-06-30 13:47 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: Raffaele Recalcati, Davide Bonfanti, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Troy Kisky, alsa-devel,
	linux-kernel

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>
---
 sound/soc/davinci/davinci-i2s.c |   92 +++++++++++++++++++++++++++++++++++----
 1 files changed, 83 insertions(+), 9 deletions(-)

diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index adadcd3..319e8ca 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -68,16 +68,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	(1 << 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	(1 << 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	(1 << 29)
 
 #define DAVINCI_MCBSP_PCR_CLKRP		(1 << 0)
 #define DAVINCI_MCBSP_PCR_CLKXP		(1 << 1)
@@ -144,6 +149,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 +262,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 +382,16 @@ 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;
+	int srgr;
+
+	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 +400,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 +416,44 @@ 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;
+	default:
+		/* 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);
+	}
 	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
 
 	rcr = DAVINCI_MCBSP_RCR_RFIG;
@@ -426,12 +478,29 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
 			element_cnt = 1;
 			fmt = double_fmt[fmt];
 		}
+		if (master == SND_SOC_DAIFMT_CBS_CFS ||
+				master == 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;
+		} else {
+			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);
+			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);
+		}
 	}
 	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);
+
+	if (master == SND_SOC_DAIFMT_CBS_CFS ||
+			master == SND_SOC_DAIFMT_CBS_CFM) {
+		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);
+		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);
+	} else {
+		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
+		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
+	}
 
 	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
 		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
@@ -442,6 +511,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 +573,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,
 
 };
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
  2010-06-30 13:47 ` [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to " Raffaele Recalcati
@ 2010-07-01 14:35   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2010-07-01 14:35 UTC (permalink / raw)
  To: Raffaele Recalcati
  Cc: davinci-linux-open-source, Takashi Iwai, linux-kernel, alsa-devel,
	Davide Bonfanti, Raffaele Recalcati, Troy Kisky, Liam Girdwood

On Wed, Jun 30, 2010 at 03:47:56PM +0200, Raffaele Recalcati wrote:

> +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;
> +	int srgr;
> +
> +	dev->clk_div = div;
> +	return 0;
> +}

As previously mentioned this should check the div_id argument.

> +	switch (master) {
> +	case SND_SOC_DAIFMT_CBS_CFS:

...

> +	case SND_SOC_DAIFMT_CBM_CFS:

...

> +	default:
> +		/* Clock and frame sync given from external sources */

The two remaining options (_CBM_CFM and _CBS_CFM) are different, your
description matches _CBM_CFM.

> +		if (master == SND_SOC_DAIFMT_CBS_CFS ||
> +				master == SND_SOC_DAIFMT_CBS_CFM) {

Switch statement again.

> +	if (master == SND_SOC_DAIFMT_CBS_CFS ||
> +			master == SND_SOC_DAIFMT_CBS_CFM) {
> +		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);
> +		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);
> +	} else {

...and another.  Please fix all these.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
       [not found] <1278405544-3852-1-git-send-email-lamiaposta71@gmail.com>
@ 2010-07-06  8:39 ` Raffaele Recalcati
  2010-07-06  9:45   ` Liam Girdwood
  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
  2 siblings, 1 reply; 9+ messages in thread
From: Raffaele Recalcati @ 2010-07-06  8:39 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: sudhakar.raj, Mark Brown, Raffaele Recalcati, Davide Bonfanti,
	Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Troy Kisky,
	alsa-devel, linux-kernel

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>
---
 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
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] ASoC: DaVinci: Added selection of clk input pin for McBSP
       [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  8:39 ` Raffaele Recalcati
  2010-07-06  8:39 ` [PATCH 3/3] ASoC: DaVinci: More accurate continuous serial clock for McBSP (I2S) Raffaele Recalcati
  2 siblings, 0 replies; 9+ messages in thread
From: Raffaele Recalcati @ 2010-07-06  8:39 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: alsa-devel, sudhakar.raj, Russell King, Takashi Iwai, Mark Brown,
	linux-kernel, Troy Kisky, Davide Bonfanti, Raffaele Recalcati,
	Chaithrika U S, Jaroslav Kysela, linux-arm-kernel, Liam Girdwood

From: Raffaele Recalcati <raffaele.recalcati@bticino.it>

    When McBSP peripheral gets the clock from an external pin,
    there are three possible chooses, MCBSP_CLKX, MCBSP_CLKR
    and MCBSP_CLKS.
    evm-dm365 uses MCBSP_CLKR, instead in bmx board I have a different
    hardware connection and I use MCBSP_CLKS, so I have added
    this possibility.

    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)

Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Signed-off-by: Davide Bonfanti <davide.bonfanti@bticino.it>
---
 arch/arm/mach-davinci/include/mach/asp.h |   15 +++++++++++++++
 sound/soc/davinci/davinci-i2s.c          |   29 ++++++++++++++++++++++++-----
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h
index 834725f..0847d21 100644
--- a/arch/arm/mach-davinci/include/mach/asp.h
+++ b/arch/arm/mach-davinci/include/mach/asp.h
@@ -63,6 +63,16 @@ struct snd_platform_data {
 	unsigned sram_size_playback;
 	unsigned sram_size_capture;
 
+	/*
+	 * If McBSP peripheral gets the clock from an external pin,
+	 * there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR
+	 * and MCBSP_CLKS.
+	 * Depending on different hardware connections it is possible
+	 * to use this setting to change the behaviour of McBSP
+	 * driver. The dm365_clk_input_pin enum is available for dm365
+	 */
+	int clk_input_pin;
+
 	/* McASP specific fields */
 	int tdm_slots;
 	u8 op_mode;
@@ -78,6 +88,11 @@ enum {
 	MCASP_VERSION_2,	/* DA8xx/OMAPL1x */
 };
 
+enum dm365_clk_input_pin {
+	MCBSP_CLKR = 0,		/* DM365 */
+	MCBSP_CLKS,
+};
+
 #define INACTIVE_MODE	0
 #define TX_MODE		1
 #define RX_MODE		2
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index c8f038c..ba5644b 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -122,6 +122,7 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
 };
 
 struct davinci_mcbsp_dev {
+	struct device *dev;
 	struct davinci_pcm_dma_params	dma_params[2];
 	void __iomem			*base;
 #define MOD_DSP_A	0
@@ -153,6 +154,7 @@ struct davinci_mcbsp_dev {
 
 	unsigned int fmt;
 	int clk_div;
+	int clk_input_pin;
 };
 
 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -279,11 +281,26 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 			DAVINCI_MCBSP_PCR_CLKRM;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFS:
-		/* McBSP CLKR pin is the input for the Sample Rate Generator.
-		 * McBSP FSR and FSX are driven by the Sample Rate Generator. */
-		pcr = DAVINCI_MCBSP_PCR_SCLKME |
-			DAVINCI_MCBSP_PCR_FSXM |
-			DAVINCI_MCBSP_PCR_FSRM;
+		pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;
+		/*
+		 * Selection of the clock input pin that is the
+		 * input for the Sample Rate Generator.
+		 * McBSP FSR and FSX are driven by the Sample Rate
+		 * Generator.
+		 */
+		switch (dev->clk_input_pin) {
+		case MCBSP_CLKS:
+			pcr |= DAVINCI_MCBSP_PCR_CLKXM |
+				DAVINCI_MCBSP_PCR_CLKRM;
+			break;
+		case MCBSP_CLKR:
+			pcr |= DAVINCI_MCBSP_PCR_SCLKME;
+			break;
+		default:
+			dev_err(dev->dev, "bad clk_input_pin\n");
+			return -EINVAL;
+		}
+
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
 		/* codec is master */
@@ -644,6 +661,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 			pdata->sram_size_playback;
 		dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
 			pdata->sram_size_capture;
+		dev->clk_input_pin = pdata->clk_input_pin;
 	}
 	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk)) {
@@ -676,6 +694,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 		goto err_free_mem;
 	}
 	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
+	dev->dev = &pdev->dev;
 
 	davinci_i2s_dai.private_data = dev;
 	davinci_i2s_dai.capture.dma_data = dev->dma_params;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] ASoC: DaVinci: More accurate continuous serial clock for McBSP (I2S)
       [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  8:39 ` [PATCH 2/3] ASoC: DaVinci: Added selection of clk input pin for McBSP Raffaele Recalcati
@ 2010-07-06  8:39 ` Raffaele Recalcati
  2 siblings, 0 replies; 9+ messages in thread
From: Raffaele Recalcati @ 2010-07-06  8:39 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: sudhakar.raj, Mark Brown, Raffaele Recalcati, Davide Bonfanti,
	Russell King, Chaithrika U S, Troy Kisky, Liam Girdwood,
	Jaroslav Kysela, Takashi Iwai, linux-arm-kernel, linux-kernel,
	alsa-devel

From: Raffaele Recalcati <raffaele.recalcati@bticino.it>

    i2s_accurate_sck switch can be used to have a better approximate
    sampling frequency.
    The clock is an externally visible bit clock and it is named
    i2s continuous serial clock (I2S_SCK).
    The trade off is between more accurate clock (fast clock)
    and less accurate clock (slow clock).
    The waveform will be not symmetric.
    Probably it is possible to get a better algorithm for calculating
    the divider, trying to keep a slower clock as possible.

    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>
---
 arch/arm/mach-davinci/include/mach/asp.h |   33 ++++++++++++++++++++++++++++++
 sound/soc/davinci/davinci-i2s.c          |   24 +++++++++++++++++----
 2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h
index 0847d21..b12c69e 100644
--- a/arch/arm/mach-davinci/include/mach/asp.h
+++ b/arch/arm/mach-davinci/include/mach/asp.h
@@ -73,6 +73,39 @@ struct snd_platform_data {
 	 */
 	int clk_input_pin;
 
+	/*
+	 * This flag works when both clock and FS are outputs for the cpu
+	 * and makes clock more accurate (FS is not symmetrical and the
+	 * clock is very fast.
+	 * The clock becoming faster is named
+	 * i2s continuous serial clock (I2S_SCK) and it is an externally
+	 * visible bit clock.
+	 *
+	 * first line : WordSelect
+	 * second line : ContinuousSerialClock
+	 * third line: SerialData
+	 *
+	 * SYMMETRICAL APPROACH:
+	 *   _______________________          LEFT
+	 * _|         RIGHT         |______________________|
+	 *     _   _         _   _   _   _         _   _
+	 *   _| |_| |_ x16 _| |_| |_| |_| |_ x16 _| |_| |_
+	 *     _   _         _   _   _   _         _   _
+	 *   _/ \_/ \_ ... _/ \_/ \_/ \_/ \_ ... _/ \_/ \_
+	 *    \_/ \_/       \_/ \_/ \_/ \_/       \_/ \_/
+	 *
+	 * ACCURATE CLOCK APPROACH:
+	 *   ______________          LEFT
+	 * _|     RIGHT    |_______________________________|
+	 *     _         _   _         _   _   _   _   _   _
+	 *   _| |_ x16 _| |_| |_ x16 _| |_| |_| |_| |_| |_| |
+	 *     _         _   _          _      dummy cycles
+	 *   _/ \_ ... _/ \_/ \_  ... _/ \__________________
+	 *    \_/       \_/ \_/        \_/
+	 *
+	 */
+	bool i2s_accurate_sck;
+
 	/* McASP specific fields */
 	int tdm_slots;
 	u8 op_mode;
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index ba5644b..b251bc9 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -155,6 +155,7 @@ struct davinci_mcbsp_dev {
 	unsigned int fmt;
 	int clk_div;
 	int clk_input_pin;
+	bool i2s_accurate_sck;
 };
 
 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -447,11 +448,23 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
 		       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);
+		if (dev->i2s_accurate_sck) {
+			clk_div = 256;
+			do {
+				framesize = (freq / (--clk_div)) /
+				params->rate_num *
+					params->rate_den;
+			} while (((framesize < 33) || (framesize > 4095)) &&
+				 (clk_div));
+			clk_div--;
+			srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);
+		} else {
+			/* 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;
@@ -662,6 +675,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 		dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
 			pdata->sram_size_capture;
 		dev->clk_input_pin = pdata->clk_input_pin;
+		dev->i2s_accurate_sck = pdata->i2s_accurate_sck;
 	}
 	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk)) {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
  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
  2010-07-06 11:30     ` Sudhakar Rajashekhara
                       ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Liam Girdwood @ 2010-07-06  9:45 UTC (permalink / raw)
  To: Raffaele Recalcati
  Cc: davinci-linux-open-source, sudhakar.raj, Takashi Iwai,
	linux-kernel, Mark Brown, alsa-devel, Davide Bonfanti,
	Raffaele Recalcati, Troy Kisky

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
  2010-07-06  9:45   ` Liam Girdwood
  2010-07-06 11:30     ` Sudhakar Rajashekhara
@ 2010-07-06 11:30     ` Sudhakar Rajashekhara
       [not found]     ` <003001cb1cfe$a043a610$e0caf230$@raj@ti.com>
  2 siblings, 0 replies; 9+ messages in thread
From: Sudhakar Rajashekhara @ 2010-07-06 11:30 UTC (permalink / raw)
  To: 'Liam Girdwood', 'Raffaele Recalcati'
  Cc: davinci-linux-open-source, 'Takashi Iwai', linux-kernel,
	'Mark Brown', alsa-devel, 'Davide Bonfanti',
	'Raffaele Recalcati', 'Troy Kisky'

Hi,

On Tue, Jul 06, 2010 at 15:15:59, Liam Girdwood wrote:
> 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.
> 

Acked-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Regards,
Sudhakar

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
  2010-07-06  9:45   ` Liam Girdwood
@ 2010-07-06 11:30     ` Sudhakar Rajashekhara
  2010-07-06 11:30     ` Sudhakar Rajashekhara
       [not found]     ` <003001cb1cfe$a043a610$e0caf230$@raj@ti.com>
  2 siblings, 0 replies; 9+ messages in thread
From: Sudhakar Rajashekhara @ 2010-07-06 11:30 UTC (permalink / raw)
  To: 'Liam Girdwood', 'Raffaele Recalcati'
  Cc: davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/,
	'Takashi Iwai', linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	'Mark Brown', alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	'Jaroslav Kysela', 'Raffaele Recalcati'

Hi,

On Tue, Jul 06, 2010 at 15:15:59, Liam Girdwood wrote:
> On Tue, 2010-07-06 at 10:39 +0200, Raffaele Recalcati wrote:
> > From: Raffaele Recalcati <raffaele.recalcati-nfoefbsQIRSonA0d6jMUrA@public.gmane.org>
> > 
> >     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-nfoefbsQIRSonA0d6jMUrA@public.gmane.org>
> > Signed-off-by: Davide Bonfanti <davide.bonfanti-nfoefbsQIRSonA0d6jMUrA@public.gmane.org>
> 
> All
> 
> Acked-by: Liam Girdwood <lrg-kDsPt+C1G03kYMGBc/C6ZA@public.gmane.org>
> 
> But lets get some feedback from the DaVinci folks on this too.
> 

Acked-by: Sudhakar Rajashekhara <sudhakar.raj-l0cyMroinI0@public.gmane.org>

Regards,
Sudhakar

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
       [not found]     ` <003001cb1cfe$a043a610$e0caf230$@raj@ti.com>
@ 2010-07-06 14:54       ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2010-07-06 14:54 UTC (permalink / raw)
  To: Sudhakar Rajashekhara
  Cc: davinci-linux-open-source, 'Takashi Iwai', linux-kernel,
	alsa-devel, 'Davide Bonfanti',
	'Raffaele Recalcati', 'Troy Kisky',
	'Raffaele Recalcati', 'Liam Girdwood'

On Tue, Jul 06, 2010 at 05:00:24PM +0530, Sudhakar Rajashekhara wrote:
> > Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>

> Acked-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Applied all, thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-07-06 14:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [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
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

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).