diff options
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 105 |
1 files changed, 97 insertions, 8 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f0c034771062..e672f431323d 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -102,6 +102,11 @@ | |||
102 | /* Receive Buffer for Serializer n */ | 102 | /* Receive Buffer for Serializer n */ |
103 | #define DAVINCI_MCASP_RXBUF_REG 0x280 | 103 | #define DAVINCI_MCASP_RXBUF_REG 0x280 |
104 | 104 | ||
105 | /* McASP FIFO Registers */ | ||
106 | #define DAVINCI_MCASP_WFIFOCTL (0x1010) | ||
107 | #define DAVINCI_MCASP_WFIFOSTS (0x1014) | ||
108 | #define DAVINCI_MCASP_RFIFOCTL (0x1018) | ||
109 | #define DAVINCI_MCASP_RFIFOSTS (0x101C) | ||
105 | 110 | ||
106 | /* | 111 | /* |
107 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management | 112 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management |
@@ -276,6 +281,13 @@ | |||
276 | */ | 281 | */ |
277 | #define TXDATADMADIS BIT(0) | 282 | #define TXDATADMADIS BIT(0) |
278 | 283 | ||
284 | /* | ||
285 | * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits | ||
286 | */ | ||
287 | #define FIFO_ENABLE BIT(16) | ||
288 | #define NUMEVT_MASK (0xFF << 8) | ||
289 | #define NUMDMA_MASK (0xFF) | ||
290 | |||
279 | #define DAVINCI_MCASP_NUM_SERIALIZER 16 | 291 | #define DAVINCI_MCASP_NUM_SERIALIZER 16 |
280 | 292 | ||
281 | static inline void mcasp_set_bits(void __iomem *reg, u32 val) | 293 | static inline void mcasp_set_bits(void __iomem *reg, u32 val) |
@@ -345,6 +357,9 @@ static void mcasp_start_rx(struct davinci_audio_dev *dev) | |||
345 | 357 | ||
346 | static void mcasp_start_tx(struct davinci_audio_dev *dev) | 358 | static void mcasp_start_tx(struct davinci_audio_dev *dev) |
347 | { | 359 | { |
360 | u8 offset = 0, i; | ||
361 | u32 cnt; | ||
362 | |||
348 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); | 363 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); |
349 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); | 364 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
350 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); | 365 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); |
@@ -353,6 +368,19 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev) | |||
353 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); | 368 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); |
354 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); | 369 | mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); |
355 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); | 370 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); |
371 | for (i = 0; i < dev->num_serializer; i++) { | ||
372 | if (dev->serial_dir[i] == TX_MODE) { | ||
373 | offset = i; | ||
374 | break; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /* wait for TX ready */ | ||
379 | cnt = 0; | ||
380 | while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & | ||
381 | TXSTATE) && (cnt < 100000)) | ||
382 | cnt++; | ||
383 | |||
356 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); | 384 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); |
357 | } | 385 | } |
358 | 386 | ||
@@ -362,6 +390,13 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) | |||
362 | mcasp_start_tx(dev); | 390 | mcasp_start_tx(dev); |
363 | else | 391 | else |
364 | mcasp_start_rx(dev); | 392 | mcasp_start_rx(dev); |
393 | |||
394 | /* enable FIFO */ | ||
395 | if (dev->txnumevt) | ||
396 | mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
397 | |||
398 | if (dev->rxnumevt) | ||
399 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
365 | } | 400 | } |
366 | 401 | ||
367 | static void mcasp_stop_rx(struct davinci_audio_dev *dev) | 402 | static void mcasp_stop_rx(struct davinci_audio_dev *dev) |
@@ -382,6 +417,13 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) | |||
382 | mcasp_stop_tx(dev); | 417 | mcasp_stop_tx(dev); |
383 | else | 418 | else |
384 | mcasp_stop_rx(dev); | 419 | mcasp_stop_rx(dev); |
420 | |||
421 | /* disable FIFO */ | ||
422 | if (dev->txnumevt) | ||
423 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
424 | |||
425 | if (dev->rxnumevt) | ||
426 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
385 | } | 427 | } |
386 | 428 | ||
387 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 429 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
@@ -401,7 +443,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
401 | 443 | ||
402 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26)); | 444 | mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26)); |
403 | break; | 445 | break; |
404 | |||
405 | case SND_SOC_DAIFMT_CBM_CFM: | 446 | case SND_SOC_DAIFMT_CBM_CFM: |
406 | /* codec is clock and frame master */ | 447 | /* codec is clock and frame master */ |
407 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); | 448 | mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); |
@@ -505,6 +546,8 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev, | |||
505 | static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | 546 | static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) |
506 | { | 547 | { |
507 | int i; | 548 | int i; |
549 | u8 tx_ser = 0; | ||
550 | u8 rx_ser = 0; | ||
508 | 551 | ||
509 | /* Default configuration */ | 552 | /* Default configuration */ |
510 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); | 553 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); |
@@ -525,12 +568,37 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | |||
525 | for (i = 0; i < dev->num_serializer; i++) { | 568 | for (i = 0; i < dev->num_serializer; i++) { |
526 | mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), | 569 | mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), |
527 | dev->serial_dir[i]); | 570 | dev->serial_dir[i]); |
528 | if (dev->serial_dir[i] == TX_MODE) | 571 | if (dev->serial_dir[i] == TX_MODE) { |
529 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, | 572 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, |
530 | AXR(i)); | 573 | AXR(i)); |
531 | else if (dev->serial_dir[i] == RX_MODE) | 574 | tx_ser++; |
575 | } else if (dev->serial_dir[i] == RX_MODE) { | ||
532 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, | 576 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, |
533 | AXR(i)); | 577 | AXR(i)); |
578 | rx_ser++; | ||
579 | } | ||
580 | } | ||
581 | |||
582 | if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
583 | if (dev->txnumevt * tx_ser > 64) | ||
584 | dev->txnumevt = 1; | ||
585 | |||
586 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, | ||
587 | NUMDMA_MASK); | ||
588 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
589 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | ||
590 | mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
591 | } | ||
592 | |||
593 | if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
594 | if (dev->rxnumevt * rx_ser > 64) | ||
595 | dev->rxnumevt = 1; | ||
596 | |||
597 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, | ||
598 | NUMDMA_MASK); | ||
599 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
600 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | ||
601 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
534 | } | 602 | } |
535 | } | 603 | } |
536 | 604 | ||
@@ -543,6 +611,8 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) | |||
543 | for (i = 0; i < active_slots; i++) | 611 | for (i = 0; i < active_slots; i++) |
544 | mask |= (1 << i); | 612 | mask |= (1 << i); |
545 | 613 | ||
614 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); | ||
615 | |||
546 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 616 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
547 | /* bit stream is MSB first with no delay */ | 617 | /* bit stream is MSB first with no delay */ |
548 | /* DSP_B mode */ | 618 | /* DSP_B mode */ |
@@ -622,8 +692,16 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
622 | struct davinci_pcm_dma_params *dma_params = | 692 | struct davinci_pcm_dma_params *dma_params = |
623 | dev->dma_params[substream->stream]; | 693 | dev->dma_params[substream->stream]; |
624 | int word_length; | 694 | int word_length; |
695 | u8 numevt; | ||
625 | 696 | ||
626 | davinci_hw_common_param(dev, substream->stream); | 697 | davinci_hw_common_param(dev, substream->stream); |
698 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
699 | numevt = dev->txnumevt; | ||
700 | else | ||
701 | numevt = dev->rxnumevt; | ||
702 | |||
703 | if (!numevt) | ||
704 | numevt = 1; | ||
627 | 705 | ||
628 | if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) | 706 | if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) |
629 | davinci_hw_dit_param(dev); | 707 | davinci_hw_dit_param(dev); |
@@ -650,6 +728,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
650 | printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); | 728 | printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); |
651 | return -EINVAL; | 729 | return -EINVAL; |
652 | } | 730 | } |
731 | |||
732 | if (dev->version == MCASP_VERSION_2) { | ||
733 | dma_params->data_type *= numevt; | ||
734 | dma_params->acnt = 4 * numevt; | ||
735 | } else | ||
736 | dma_params->acnt = dma_params->data_type; | ||
737 | |||
653 | davinci_config_channel_size(dev, word_length); | 738 | davinci_config_channel_size(dev, word_length); |
654 | 739 | ||
655 | return 0; | 740 | return 0; |
@@ -778,6 +863,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
778 | dev->num_serializer = pdata->num_serializer; | 863 | dev->num_serializer = pdata->num_serializer; |
779 | dev->serial_dir = pdata->serial_dir; | 864 | dev->serial_dir = pdata->serial_dir; |
780 | dev->codec_fmt = pdata->codec_fmt; | 865 | dev->codec_fmt = pdata->codec_fmt; |
866 | dev->version = pdata->version; | ||
867 | dev->txnumevt = pdata->txnumevt; | ||
868 | dev->rxnumevt = pdata->rxnumevt; | ||
781 | 869 | ||
782 | dma_data[count].name = "I2S PCM Stereo out"; | 870 | dma_data[count].name = "I2S PCM Stereo out"; |
783 | dma_data[count].eventq_no = pdata->eventq_no; | 871 | dma_data[count].eventq_no = pdata->eventq_no; |
@@ -807,9 +895,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
807 | } | 895 | } |
808 | 896 | ||
809 | dma_data[count].channel = res->start; | 897 | dma_data[count].channel = res->start; |
810 | davinci_mcasp_dai[pdev->id].private_data = dev; | 898 | davinci_mcasp_dai[pdata->op_mode].private_data = dev; |
811 | davinci_mcasp_dai[pdev->id].dev = &pdev->dev; | 899 | davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; |
812 | ret = snd_soc_register_dai(&davinci_mcasp_dai[pdev->id]); | 900 | ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); |
813 | 901 | ||
814 | if (ret != 0) | 902 | if (ret != 0) |
815 | goto err_release_region; | 903 | goto err_release_region; |
@@ -827,12 +915,13 @@ err_release_dev: | |||
827 | 915 | ||
828 | static int davinci_mcasp_remove(struct platform_device *pdev) | 916 | static int davinci_mcasp_remove(struct platform_device *pdev) |
829 | { | 917 | { |
918 | struct snd_platform_data *pdata = pdev->dev.platform_data; | ||
830 | struct davinci_pcm_dma_params *dma_data; | 919 | struct davinci_pcm_dma_params *dma_data; |
831 | struct davinci_audio_dev *dev; | 920 | struct davinci_audio_dev *dev; |
832 | struct resource *mem; | 921 | struct resource *mem; |
833 | 922 | ||
834 | snd_soc_unregister_dai(&davinci_mcasp_dai[pdev->id]); | 923 | snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]); |
835 | dev = davinci_mcasp_dai[pdev->id].private_data; | 924 | dev = davinci_mcasp_dai[pdata->op_mode].private_data; |
836 | clk_disable(dev->clk); | 925 | clk_disable(dev->clk); |
837 | clk_put(dev->clk); | 926 | clk_put(dev->clk); |
838 | dev->clk = NULL; | 927 | dev->clk = NULL; |