diff options
Diffstat (limited to 'sound/soc/davinci/davinci-i2s.c')
-rw-r--r-- | sound/soc/davinci/davinci-i2s.c | 163 |
1 files changed, 149 insertions, 14 deletions
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index adadcd3aa1b1..9e8932abf158 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) |
@@ -116,6 +122,7 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = { | |||
116 | }; | 122 | }; |
117 | 123 | ||
118 | struct davinci_mcbsp_dev { | 124 | struct davinci_mcbsp_dev { |
125 | struct device *dev; | ||
119 | struct davinci_pcm_dma_params dma_params[2]; | 126 | struct davinci_pcm_dma_params dma_params[2]; |
120 | void __iomem *base; | 127 | void __iomem *base; |
121 | #define MOD_DSP_A 0 | 128 | #define MOD_DSP_A 0 |
@@ -144,6 +151,11 @@ struct davinci_mcbsp_dev { | |||
144 | * won't end up being swapped because of the underrun. | 151 | * won't end up being swapped because of the underrun. |
145 | */ | 152 | */ |
146 | unsigned enable_channel_combine:1; | 153 | unsigned enable_channel_combine:1; |
154 | |||
155 | unsigned int fmt; | ||
156 | int clk_div; | ||
157 | int clk_input_pin; | ||
158 | bool i2s_accurate_sck; | ||
147 | }; | 159 | }; |
148 | 160 | ||
149 | static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, | 161 | static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, |
@@ -254,10 +266,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
254 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; | 266 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; |
255 | unsigned int pcr; | 267 | unsigned int pcr; |
256 | unsigned int srgr; | 268 | unsigned int srgr; |
269 | /* Attention srgr is updated by hw_params! */ | ||
257 | srgr = DAVINCI_MCBSP_SRGR_FSGM | | 270 | srgr = DAVINCI_MCBSP_SRGR_FSGM | |
258 | DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | | 271 | DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | |
259 | DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); | 272 | DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); |
260 | 273 | ||
274 | dev->fmt = fmt; | ||
261 | /* set master/slave audio interface */ | 275 | /* set master/slave audio interface */ |
262 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 276 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
263 | case SND_SOC_DAIFMT_CBS_CFS: | 277 | case SND_SOC_DAIFMT_CBS_CFS: |
@@ -268,11 +282,26 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
268 | DAVINCI_MCBSP_PCR_CLKRM; | 282 | DAVINCI_MCBSP_PCR_CLKRM; |
269 | break; | 283 | break; |
270 | case SND_SOC_DAIFMT_CBM_CFS: | 284 | case SND_SOC_DAIFMT_CBM_CFS: |
271 | /* McBSP CLKR pin is the input for the Sample Rate Generator. | 285 | pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; |
272 | * McBSP FSR and FSX are driven by the Sample Rate Generator. */ | 286 | /* |
273 | pcr = DAVINCI_MCBSP_PCR_SCLKME | | 287 | * Selection of the clock input pin that is the |
274 | DAVINCI_MCBSP_PCR_FSXM | | 288 | * input for the Sample Rate Generator. |
275 | DAVINCI_MCBSP_PCR_FSRM; | 289 | * McBSP FSR and FSX are driven by the Sample Rate |
290 | * Generator. | ||
291 | */ | ||
292 | switch (dev->clk_input_pin) { | ||
293 | case MCBSP_CLKS: | ||
294 | pcr |= DAVINCI_MCBSP_PCR_CLKXM | | ||
295 | DAVINCI_MCBSP_PCR_CLKRM; | ||
296 | break; | ||
297 | case MCBSP_CLKR: | ||
298 | pcr |= DAVINCI_MCBSP_PCR_SCLKME; | ||
299 | break; | ||
300 | default: | ||
301 | dev_err(dev->dev, "bad clk_input_pin\n"); | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | |||
276 | break; | 305 | break; |
277 | case SND_SOC_DAIFMT_CBM_CFM: | 306 | case SND_SOC_DAIFMT_CBM_CFM: |
278 | /* codec is master */ | 307 | /* codec is master */ |
@@ -372,6 +401,18 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
372 | return 0; | 401 | return 0; |
373 | } | 402 | } |
374 | 403 | ||
404 | static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, | ||
405 | int div_id, int div) | ||
406 | { | ||
407 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; | ||
408 | |||
409 | if (div_id != DAVINCI_MCBSP_CLKGDV) | ||
410 | return -ENODEV; | ||
411 | |||
412 | dev->clk_div = div; | ||
413 | return 0; | ||
414 | } | ||
415 | |||
375 | static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | 416 | static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, |
376 | struct snd_pcm_hw_params *params, | 417 | struct snd_pcm_hw_params *params, |
377 | struct snd_soc_dai *dai) | 418 | struct snd_soc_dai *dai) |
@@ -380,8 +421,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
380 | struct davinci_pcm_dma_params *dma_params = | 421 | struct davinci_pcm_dma_params *dma_params = |
381 | &dev->dma_params[substream->stream]; | 422 | &dev->dma_params[substream->stream]; |
382 | struct snd_interval *i = NULL; | 423 | struct snd_interval *i = NULL; |
383 | int mcbsp_word_length; | 424 | int mcbsp_word_length, master; |
384 | unsigned int rcr, xcr, srgr; | 425 | unsigned int rcr, xcr, srgr, clk_div, freq, framesize; |
385 | u32 spcr; | 426 | u32 spcr; |
386 | snd_pcm_format_t fmt; | 427 | snd_pcm_format_t fmt; |
387 | unsigned element_cnt = 1; | 428 | unsigned element_cnt = 1; |
@@ -396,12 +437,59 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
396 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); | 437 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); |
397 | } | 438 | } |
398 | 439 | ||
399 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | 440 | master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; |
400 | srgr = DAVINCI_MCBSP_SRGR_FSGM; | 441 | fmt = params_format(params); |
401 | srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); | 442 | mcbsp_word_length = asp_word_length[fmt]; |
402 | 443 | ||
403 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); | 444 | switch (master) { |
404 | srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); | 445 | case SND_SOC_DAIFMT_CBS_CFS: |
446 | freq = clk_get_rate(dev->clk); | ||
447 | srgr = DAVINCI_MCBSP_SRGR_FSGM | | ||
448 | DAVINCI_MCBSP_SRGR_CLKSM; | ||
449 | srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * | ||
450 | 8 - 1); | ||
451 | if (dev->i2s_accurate_sck) { | ||
452 | clk_div = 256; | ||
453 | do { | ||
454 | framesize = (freq / (--clk_div)) / | ||
455 | params->rate_num * | ||
456 | params->rate_den; | ||
457 | } while (((framesize < 33) || (framesize > 4095)) && | ||
458 | (clk_div)); | ||
459 | clk_div--; | ||
460 | srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1); | ||
461 | } else { | ||
462 | /* symmetric waveforms */ | ||
463 | clk_div = freq / (mcbsp_word_length * 16) / | ||
464 | params->rate_num * params->rate_den; | ||
465 | srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * | ||
466 | 16 - 1); | ||
467 | } | ||
468 | clk_div &= 0xFF; | ||
469 | srgr |= clk_div; | ||
470 | break; | ||
471 | case SND_SOC_DAIFMT_CBM_CFS: | ||
472 | srgr = DAVINCI_MCBSP_SRGR_FSGM; | ||
473 | clk_div = dev->clk_div - 1; | ||
474 | srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); | ||
475 | srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1); | ||
476 | clk_div &= 0xFF; | ||
477 | srgr |= clk_div; | ||
478 | break; | ||
479 | case SND_SOC_DAIFMT_CBM_CFM: | ||
480 | /* Clock and frame sync given from external sources */ | ||
481 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | ||
482 | srgr = DAVINCI_MCBSP_SRGR_FSGM; | ||
483 | srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); | ||
484 | pr_debug("%s - %d FWID set: re-read srgr = %X\n", | ||
485 | __func__, __LINE__, snd_interval_value(i) - 1); | ||
486 | |||
487 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); | ||
488 | srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); | ||
489 | break; | ||
490 | default: | ||
491 | return -EINVAL; | ||
492 | } | ||
405 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); | 493 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); |
406 | 494 | ||
407 | rcr = DAVINCI_MCBSP_RCR_RFIG; | 495 | rcr = DAVINCI_MCBSP_RCR_RFIG; |
@@ -426,12 +514,41 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
426 | element_cnt = 1; | 514 | element_cnt = 1; |
427 | fmt = double_fmt[fmt]; | 515 | fmt = double_fmt[fmt]; |
428 | } | 516 | } |
517 | switch (master) { | ||
518 | case SND_SOC_DAIFMT_CBS_CFS: | ||
519 | case SND_SOC_DAIFMT_CBS_CFM: | ||
520 | rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0); | ||
521 | xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0); | ||
522 | rcr |= DAVINCI_MCBSP_RCR_RPHASE; | ||
523 | xcr |= DAVINCI_MCBSP_XCR_XPHASE; | ||
524 | break; | ||
525 | case SND_SOC_DAIFMT_CBM_CFM: | ||
526 | case SND_SOC_DAIFMT_CBM_CFS: | ||
527 | rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); | ||
528 | xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); | ||
529 | break; | ||
530 | default: | ||
531 | return -EINVAL; | ||
532 | } | ||
429 | } | 533 | } |
430 | dma_params->acnt = dma_params->data_type = data_type[fmt]; | 534 | dma_params->acnt = dma_params->data_type = data_type[fmt]; |
431 | dma_params->fifo_level = 0; | 535 | dma_params->fifo_level = 0; |
432 | mcbsp_word_length = asp_word_length[fmt]; | 536 | mcbsp_word_length = asp_word_length[fmt]; |
433 | rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); | 537 | |
434 | xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); | 538 | switch (master) { |
539 | case SND_SOC_DAIFMT_CBS_CFS: | ||
540 | case SND_SOC_DAIFMT_CBS_CFM: | ||
541 | rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); | ||
542 | xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); | ||
543 | break; | ||
544 | case SND_SOC_DAIFMT_CBM_CFM: | ||
545 | case SND_SOC_DAIFMT_CBM_CFS: | ||
546 | rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); | ||
547 | xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); | ||
548 | break; | ||
549 | default: | ||
550 | return -EINVAL; | ||
551 | } | ||
435 | 552 | ||
436 | rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | | 553 | rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | |
437 | DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); | 554 | DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); |
@@ -442,6 +559,10 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
442 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); | 559 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); |
443 | else | 560 | else |
444 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); | 561 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); |
562 | |||
563 | pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr); | ||
564 | pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr); | ||
565 | pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr); | ||
445 | return 0; | 566 | return 0; |
446 | } | 567 | } |
447 | 568 | ||
@@ -500,6 +621,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = { | |||
500 | .trigger = davinci_i2s_trigger, | 621 | .trigger = davinci_i2s_trigger, |
501 | .hw_params = davinci_i2s_hw_params, | 622 | .hw_params = davinci_i2s_hw_params, |
502 | .set_fmt = davinci_i2s_set_dai_fmt, | 623 | .set_fmt = davinci_i2s_set_dai_fmt, |
624 | .set_clkdiv = davinci_i2s_dai_set_clkdiv, | ||
503 | 625 | ||
504 | }; | 626 | }; |
505 | 627 | ||
@@ -526,6 +648,8 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
526 | struct snd_platform_data *pdata = pdev->dev.platform_data; | 648 | struct snd_platform_data *pdata = pdev->dev.platform_data; |
527 | struct davinci_mcbsp_dev *dev; | 649 | struct davinci_mcbsp_dev *dev; |
528 | struct resource *mem, *ioarea, *res; | 650 | struct resource *mem, *ioarea, *res; |
651 | enum dma_event_q asp_chan_q = EVENTQ_0; | ||
652 | enum dma_event_q ram_chan_q = EVENTQ_1; | ||
529 | int ret; | 653 | int ret; |
530 | 654 | ||
531 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 655 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -552,7 +676,17 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
552 | pdata->sram_size_playback; | 676 | pdata->sram_size_playback; |
553 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size = | 677 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size = |
554 | pdata->sram_size_capture; | 678 | pdata->sram_size_capture; |
679 | dev->clk_input_pin = pdata->clk_input_pin; | ||
680 | dev->i2s_accurate_sck = pdata->i2s_accurate_sck; | ||
681 | asp_chan_q = pdata->asp_chan_q; | ||
682 | ram_chan_q = pdata->ram_chan_q; | ||
555 | } | 683 | } |
684 | |||
685 | dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q; | ||
686 | dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q; | ||
687 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q; | ||
688 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q; | ||
689 | |||
556 | dev->clk = clk_get(&pdev->dev, NULL); | 690 | dev->clk = clk_get(&pdev->dev, NULL); |
557 | if (IS_ERR(dev->clk)) { | 691 | if (IS_ERR(dev->clk)) { |
558 | ret = -ENODEV; | 692 | ret = -ENODEV; |
@@ -584,6 +718,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
584 | goto err_free_mem; | 718 | goto err_free_mem; |
585 | } | 719 | } |
586 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; | 720 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; |
721 | dev->dev = &pdev->dev; | ||
587 | 722 | ||
588 | davinci_i2s_dai.private_data = dev; | 723 | davinci_i2s_dai.private_data = dev; |
589 | davinci_i2s_dai.capture.dma_data = dev->dma_params; | 724 | davinci_i2s_dai.capture.dma_data = dev->dma_params; |