aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaffaele Recalcati <raffaele.recalcati@bticino.it>2010-07-06 04:39:02 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-07-06 10:54:06 -0400
commita4c8ea2ddaed2f461606c2828b19786524b551ac (patch)
tree0b6b890a47554a276bbb836883f7cf1e2ab8799e
parent088fbab406e264a60fb06d3ea8d32a3e802a00b8 (diff)
ASoC: DaVinci: Added two clocking possibilities to McBSP (I2S)
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> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Acked-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/davinci/davinci-i2s.c110
-rw-r--r--sound/soc/davinci/davinci-i2s.h5
2 files changed, 106 insertions, 9 deletions
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index adadcd3aa1b1..c8f038cb4c5e 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -26,6 +26,7 @@
26#include <mach/asp.h> 26#include <mach/asp.h>
27 27
28#include "davinci-pcm.h" 28#include "davinci-pcm.h"
29#include "davinci-i2s.h"
29 30
30 31
31/* 32/*
@@ -68,16 +69,21 @@
68#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) 69#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16)
69#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) 70#define DAVINCI_MCBSP_RCR_RFIG (1 << 18)
70#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) 71#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21)
72#define DAVINCI_MCBSP_RCR_RFRLEN2(v) ((v) << 24)
73#define DAVINCI_MCBSP_RCR_RPHASE BIT(31)
71 74
72#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) 75#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5)
73#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8) 76#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8)
74#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16) 77#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16)
75#define DAVINCI_MCBSP_XCR_XFIG (1 << 18) 78#define DAVINCI_MCBSP_XCR_XFIG (1 << 18)
76#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21) 79#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21)
80#define DAVINCI_MCBSP_XCR_XFRLEN2(v) ((v) << 24)
81#define DAVINCI_MCBSP_XCR_XPHASE BIT(31)
77 82
78#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8) 83#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8)
79#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16) 84#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16)
80#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28) 85#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28)
86#define DAVINCI_MCBSP_SRGR_CLKSM BIT(29)
81 87
82#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0) 88#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0)
83#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) 89#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
@@ -144,6 +150,9 @@ struct davinci_mcbsp_dev {
144 * won't end up being swapped because of the underrun. 150 * won't end up being swapped because of the underrun.
145 */ 151 */
146 unsigned enable_channel_combine:1; 152 unsigned enable_channel_combine:1;
153
154 unsigned int fmt;
155 int clk_div;
147}; 156};
148 157
149static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, 158static 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,
254 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 263 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
255 unsigned int pcr; 264 unsigned int pcr;
256 unsigned int srgr; 265 unsigned int srgr;
266 /* Attention srgr is updated by hw_params! */
257 srgr = DAVINCI_MCBSP_SRGR_FSGM | 267 srgr = DAVINCI_MCBSP_SRGR_FSGM |
258 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | 268 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
259 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); 269 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
260 270
271 dev->fmt = fmt;
261 /* set master/slave audio interface */ 272 /* set master/slave audio interface */
262 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 273 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
263 case SND_SOC_DAIFMT_CBS_CFS: 274 case SND_SOC_DAIFMT_CBS_CFS:
@@ -372,6 +383,18 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
372 return 0; 383 return 0;
373} 384}
374 385
386static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
387 int div_id, int div)
388{
389 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
390
391 if (div_id != DAVINCI_MCBSP_CLKGDV)
392 return -ENODEV;
393
394 dev->clk_div = div;
395 return 0;
396}
397
375static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, 398static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
376 struct snd_pcm_hw_params *params, 399 struct snd_pcm_hw_params *params,
377 struct snd_soc_dai *dai) 400 struct snd_soc_dai *dai)
@@ -380,8 +403,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
380 struct davinci_pcm_dma_params *dma_params = 403 struct davinci_pcm_dma_params *dma_params =
381 &dev->dma_params[substream->stream]; 404 &dev->dma_params[substream->stream];
382 struct snd_interval *i = NULL; 405 struct snd_interval *i = NULL;
383 int mcbsp_word_length; 406 int mcbsp_word_length, master;
384 unsigned int rcr, xcr, srgr; 407 unsigned int rcr, xcr, srgr, clk_div, freq, framesize;
385 u32 spcr; 408 u32 spcr;
386 snd_pcm_format_t fmt; 409 snd_pcm_format_t fmt;
387 unsigned element_cnt = 1; 410 unsigned element_cnt = 1;
@@ -396,12 +419,47 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
396 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); 419 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
397 } 420 }
398 421
399 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 422 master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
400 srgr = DAVINCI_MCBSP_SRGR_FSGM; 423 fmt = params_format(params);
401 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); 424 mcbsp_word_length = asp_word_length[fmt];
402 425
403 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); 426 switch (master) {
404 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); 427 case SND_SOC_DAIFMT_CBS_CFS:
428 freq = clk_get_rate(dev->clk);
429 srgr = DAVINCI_MCBSP_SRGR_FSGM |
430 DAVINCI_MCBSP_SRGR_CLKSM;
431 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *
432 8 - 1);
433 /* symmetric waveforms */
434 clk_div = freq / (mcbsp_word_length * 16) /
435 params->rate_num * params->rate_den;
436 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
437 16 - 1);
438 clk_div &= 0xFF;
439 srgr |= clk_div;
440 break;
441 case SND_SOC_DAIFMT_CBM_CFS:
442 srgr = DAVINCI_MCBSP_SRGR_FSGM;
443 clk_div = dev->clk_div - 1;
444 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);
445 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);
446 clk_div &= 0xFF;
447 srgr |= clk_div;
448 break;
449 case SND_SOC_DAIFMT_CBM_CFM:
450 /* Clock and frame sync given from external sources */
451 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
452 srgr = DAVINCI_MCBSP_SRGR_FSGM;
453 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
454 pr_debug("%s - %d FWID set: re-read srgr = %X\n",
455 __func__, __LINE__, snd_interval_value(i) - 1);
456
457 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
458 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
459 break;
460 default:
461 return -EINVAL;
462 }
405 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); 463 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
406 464
407 rcr = DAVINCI_MCBSP_RCR_RFIG; 465 rcr = DAVINCI_MCBSP_RCR_RFIG;
@@ -426,12 +484,41 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
426 element_cnt = 1; 484 element_cnt = 1;
427 fmt = double_fmt[fmt]; 485 fmt = double_fmt[fmt];
428 } 486 }
487 switch (master) {
488 case SND_SOC_DAIFMT_CBS_CFS:
489 case SND_SOC_DAIFMT_CBS_CFM:
490 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0);
491 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0);
492 rcr |= DAVINCI_MCBSP_RCR_RPHASE;
493 xcr |= DAVINCI_MCBSP_XCR_XPHASE;
494 break;
495 case SND_SOC_DAIFMT_CBM_CFM:
496 case SND_SOC_DAIFMT_CBM_CFS:
497 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);
498 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);
499 break;
500 default:
501 return -EINVAL;
502 }
429 } 503 }
430 dma_params->acnt = dma_params->data_type = data_type[fmt]; 504 dma_params->acnt = dma_params->data_type = data_type[fmt];
431 dma_params->fifo_level = 0; 505 dma_params->fifo_level = 0;
432 mcbsp_word_length = asp_word_length[fmt]; 506 mcbsp_word_length = asp_word_length[fmt];
433 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); 507
434 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); 508 switch (master) {
509 case SND_SOC_DAIFMT_CBS_CFS:
510 case SND_SOC_DAIFMT_CBS_CFM:
511 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);
512 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);
513 break;
514 case SND_SOC_DAIFMT_CBM_CFM:
515 case SND_SOC_DAIFMT_CBM_CFS:
516 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
517 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
518 break;
519 default:
520 return -EINVAL;
521 }
435 522
436 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | 523 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
437 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); 524 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
@@ -442,6 +529,10 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
442 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); 529 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
443 else 530 else
444 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); 531 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
532
533 pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr);
534 pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr);
535 pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr);
445 return 0; 536 return 0;
446} 537}
447 538
@@ -500,6 +591,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
500 .trigger = davinci_i2s_trigger, 591 .trigger = davinci_i2s_trigger,
501 .hw_params = davinci_i2s_hw_params, 592 .hw_params = davinci_i2s_hw_params,
502 .set_fmt = davinci_i2s_set_dai_fmt, 593 .set_fmt = davinci_i2s_set_dai_fmt,
594 .set_clkdiv = davinci_i2s_dai_set_clkdiv,
503 595
504}; 596};
505 597
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
index 241648ce8873..0b1e77b8c279 100644
--- a/sound/soc/davinci/davinci-i2s.h
+++ b/sound/soc/davinci/davinci-i2s.h
@@ -12,6 +12,11 @@
12#ifndef _DAVINCI_I2S_H 12#ifndef _DAVINCI_I2S_H
13#define _DAVINCI_I2S_H 13#define _DAVINCI_I2S_H
14 14
15/* McBSP dividers */
16enum davinci_mcbsp_div {
17 DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */
18};
19
15extern struct snd_soc_dai davinci_i2s_dai; 20extern struct snd_soc_dai davinci_i2s_dai;
16 21
17#endif 22#endif