aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/davinci/davinci-mcasp.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 818732de0f75..0aba39e7468d 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -304,6 +304,12 @@
304 304
305#define DAVINCI_MCASP_NUM_SERIALIZER 16 305#define DAVINCI_MCASP_NUM_SERIALIZER 16
306 306
307/*
308 * Timeout value of 1 ms was chosen experimentally to account for the initial
309 * latency to have the first audio sample transferred to AFIFO by DMA
310 */
311#define MCASP_FIFO_FILL_TIMEOUT 1000
312
307static inline void mcasp_set_bits(void __iomem *reg, u32 val) 313static inline void mcasp_set_bits(void __iomem *reg, u32 val)
308{ 314{
309 __raw_writel(__raw_readl(reg) | val, reg); 315 __raw_writel(__raw_readl(reg) | val, reg);
@@ -410,8 +416,11 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)
410 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); 416 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
411} 417}
412 418
413static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) 419static int davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
414{ 420{
421 int i = 0;
422 u32 val;
423
415 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 424 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
416 if (dev->txnumevt) { /* enable FIFO */ 425 if (dev->txnumevt) { /* enable FIFO */
417 switch (dev->version) { 426 switch (dev->version) {
@@ -427,6 +436,24 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
427 mcasp_set_bits(dev->base + 436 mcasp_set_bits(dev->base +
428 DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); 437 DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
429 } 438 }
439
440 /*
441 * Wait until DMA has loaded at least one sample into
442 * AFIFO to ensure XRUN is not immediately hit
443 * Implementation has to use udelay since it's executed
444 * in atomic context (trigger() callback)
445 */
446 while (++i) {
447 val = mcasp_get_reg(dev->base +
448 MCASP_VER3_WFIFOSTS);
449 if (val > 0)
450 break;
451
452 if (i > MCASP_FIFO_FILL_TIMEOUT)
453 return -ETIMEDOUT;
454
455 udelay(1);
456 }
430 } 457 }
431 mcasp_start_tx(dev); 458 mcasp_start_tx(dev);
432 } else { 459 } else {
@@ -447,6 +474,8 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
447 } 474 }
448 mcasp_start_rx(dev); 475 mcasp_start_rx(dev);
449 } 476 }
477
478 return 0;
450} 479}
451 480
452static void mcasp_stop_rx(struct davinci_audio_dev *dev) 481static void mcasp_stop_rx(struct davinci_audio_dev *dev)
@@ -967,7 +996,7 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
967 case SNDRV_PCM_TRIGGER_RESUME: 996 case SNDRV_PCM_TRIGGER_RESUME:
968 case SNDRV_PCM_TRIGGER_START: 997 case SNDRV_PCM_TRIGGER_START:
969 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 998 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
970 davinci_mcasp_start(dev, substream->stream); 999 ret = davinci_mcasp_start(dev, substream->stream);
971 break; 1000 break;
972 1001
973 case SNDRV_PCM_TRIGGER_SUSPEND: 1002 case SNDRV_PCM_TRIGGER_SUSPEND: