aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChaithrika U S <chaithrika@ti.com>2009-08-11 16:58:52 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-13 17:19:35 -0400
commit6a99fb5fb85f267d075310fd30c4bf6f0ae63062 (patch)
tree2a25a4b586058b48b386771ee1522d3f1a037b88
parenta2342ae325bb1f65d90a9f38baab4c9762018a5e (diff)
ASoC: DaVinci: McASP driver enhacements
On DA830/OMAP-L137 and DA850/OMAP-L138 SoCs, the McASP peripheral has FIFO support. This FIFO provides additional data buffering. It also provides tolerance to variation in host/DMA controller response times. The read and write FIFO sizes are 256 bytes each. If FIFO is enabled, the DMA events from McASP are sent to the FIFO which in turn sends DMA requests to the host CPU according to the thresholds programmed. More details of the FIFO operation can be found at http://focus.ti.com/general/docs/lit/getliterature.tsp?literatureNumber= sprufm1&fileType=pdf This patch adds support for FIFO configuration. The platform data has a version field which differentiates the McASP on different SoCs. Signed-off-by: Chaithrika U S <chaithrika@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/davinci/davinci-i2s.c1
-rw-r--r--sound/soc/davinci/davinci-mcasp.c105
-rw-r--r--sound/soc/davinci/davinci-mcasp.h5
-rw-r--r--sound/soc/davinci/davinci-pcm.c4
-rw-r--r--sound/soc/davinci/davinci-pcm.h1
5 files changed, 107 insertions, 9 deletions
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 2a56fb78f67..12a6c549ee6 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -406,6 +406,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
406 return -EINVAL; 406 return -EINVAL;
407 } 407 }
408 408
409 dma_params->acnt = dma_params->data_type;
409 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1); 410 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
410 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1); 411 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
411 412
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index f0c03477106..e672f431323 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
281static inline void mcasp_set_bits(void __iomem *reg, u32 val) 293static 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
346static void mcasp_start_tx(struct davinci_audio_dev *dev) 358static 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
367static void mcasp_stop_rx(struct davinci_audio_dev *dev) 402static 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
387static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, 429static 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,
505static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) 546static 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
828static int davinci_mcasp_remove(struct platform_device *pdev) 916static 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;
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 36b71047a06..554354c1cc2 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -50,6 +50,11 @@ struct davinci_audio_dev {
50 u8 op_mode; 50 u8 op_mode;
51 u8 num_serializer; 51 u8 num_serializer;
52 u8 *serial_dir; 52 u8 *serial_dir;
53 u8 version;
54
55 /* McASP FIFO related */
56 u8 txnumevt;
57 u8 rxnumevt;
53}; 58};
54 59
55#endif /* DAVINCI_MCASP_H */ 60#endif /* DAVINCI_MCASP_H */
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index ab43a539c11..091dacb78b4 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -67,6 +67,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
67 dma_addr_t src, dst; 67 dma_addr_t src, dst;
68 unsigned short src_bidx, dst_bidx; 68 unsigned short src_bidx, dst_bidx;
69 unsigned int data_type; 69 unsigned int data_type;
70 unsigned short acnt;
70 unsigned int count; 71 unsigned int count;
71 72
72 period_size = snd_pcm_lib_period_bytes(substream); 73 period_size = snd_pcm_lib_period_bytes(substream);
@@ -91,11 +92,12 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
91 dst_bidx = data_type; 92 dst_bidx = data_type;
92 } 93 }
93 94
95 acnt = prtd->params->acnt;
94 edma_set_src(lch, src, INCR, W8BIT); 96 edma_set_src(lch, src, INCR, W8BIT);
95 edma_set_dest(lch, dst, INCR, W8BIT); 97 edma_set_dest(lch, dst, INCR, W8BIT);
96 edma_set_src_index(lch, src_bidx, 0); 98 edma_set_src_index(lch, src_bidx, 0);
97 edma_set_dest_index(lch, dst_bidx, 0); 99 edma_set_dest_index(lch, dst_bidx, 0);
98 edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC); 100 edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC);
99 101
100 prtd->period++; 102 prtd->period++;
101 if (unlikely(prtd->period >= runtime->periods)) 103 if (unlikely(prtd->period >= runtime->periods))
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index eb4287faa3d..63d96253c73 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -19,6 +19,7 @@
19struct davinci_pcm_dma_params { 19struct davinci_pcm_dma_params {
20 char *name; /* stream identifier */ 20 char *name; /* stream identifier */
21 int channel; /* sync dma channel ID */ 21 int channel; /* sync dma channel ID */
22 unsigned short acnt;
22 dma_addr_t dma_addr; /* device physical address for DMA */ 23 dma_addr_t dma_addr; /* device physical address for DMA */
23 enum dma_event_q eventq_no; /* event queue number */ 24 enum dma_event_q eventq_no; /* event queue number */
24 unsigned char data_type; /* xfer data type */ 25 unsigned char data_type; /* xfer data type */