diff options
Diffstat (limited to 'sound/soc/fsl/fsl_ssi.c')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 8cb6bcf2c00f..b7733e6be192 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -464,28 +464,33 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
464 | 464 | ||
465 | switch (cmd) { | 465 | switch (cmd) { |
466 | case SNDRV_PCM_TRIGGER_START: | 466 | case SNDRV_PCM_TRIGGER_START: |
467 | case SNDRV_PCM_TRIGGER_RESUME: | 467 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); |
468 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 468 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
469 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 469 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
470 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | ||
471 | setbits32(&ssi->scr, | 470 | setbits32(&ssi->scr, |
472 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); | 471 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); |
473 | } else { | 472 | } else { |
474 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | 473 | long timeout = jiffies + 10; |
474 | |||
475 | setbits32(&ssi->scr, | 475 | setbits32(&ssi->scr, |
476 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); | 476 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); |
477 | 477 | ||
478 | /* | 478 | /* Wait until the SSI has filled its FIFO. Without this |
479 | * I think we need this delay to allow time for the SSI | 479 | * delay, ALSA complains about overruns. When the FIFO |
480 | * to put data into its FIFO. Without it, ALSA starts | 480 | * is full, the DMA controller initiates its first |
481 | * to complain about overruns. | 481 | * transfer. Until then, however, the DMA's DAR |
482 | * register is zero, which translates to an | ||
483 | * out-of-bounds pointer. This makes ALSA think an | ||
484 | * overrun has occurred. | ||
482 | */ | 485 | */ |
483 | mdelay(1); | 486 | while (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0) && |
487 | (jiffies < timeout)); | ||
488 | if (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0)) | ||
489 | return -EIO; | ||
484 | } | 490 | } |
485 | break; | 491 | break; |
486 | 492 | ||
487 | case SNDRV_PCM_TRIGGER_STOP: | 493 | case SNDRV_PCM_TRIGGER_STOP: |
488 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
489 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 494 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
490 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 495 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
491 | clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); | 496 | clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); |