* [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
* 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-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) 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
[parent not found: <003001cb1cfe$a043a610$e0caf230$@raj@ti.com>]
* 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
* [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
[parent not found: <1277905678-4695-1-git-send-email-lamiaposta71@gmail.com>]
* [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
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).