aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMisael Lopez Cruz2013-07-05 17:10:38 -0500
committerMisael Lopez Cruz2013-07-22 14:43:25 -0500
commit99a1e07f426e010404b6bdadfbdb9286641a6602 (patch)
tree6794bbbb1882ab2e4945a209766b8f684fd925a4
parent29485e4cd6b4adac3816c5e1809f7998afe633e5 (diff)
downloadkernel-audio-99a1e07f426e010404b6bdadfbdb9286641a6602.tar.gz
kernel-audio-99a1e07f426e010404b6bdadfbdb9286641a6602.tar.xz
kernel-audio-99a1e07f426e010404b6bdadfbdb9286641a6602.zip
ASoC: davinci-mcasp: Wait until TX AFIFO is not empty
Wait until TX AFIFO has at least one audio sample before TXBUF starts consuming data, otherwise XRUN can be hit immediately at the start of the stream. Change-Id: Ie94dcd16f7a00046eb043aec1ceee21ce6009fbc Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
-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: