diff options
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 33 |
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 | |||
307 | static inline void mcasp_set_bits(void __iomem *reg, u32 val) | 313 | static 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 | ||
413 | static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) | 419 | static 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 | ||
452 | static void mcasp_stop_rx(struct davinci_audio_dev *dev) | 481 | static 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: |