diff options
Diffstat (limited to 'sound/soc/fsl/fsl_dma.c')
-rw-r--r-- | sound/soc/fsl/fsl_dma.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index b3eb8570cd7..b1a3a278819 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -300,7 +300,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
300 | if (!card->dev->coherent_dma_mask) | 300 | if (!card->dev->coherent_dma_mask) |
301 | card->dev->coherent_dma_mask = fsl_dma_dmamask; | 301 | card->dev->coherent_dma_mask = fsl_dma_dmamask; |
302 | 302 | ||
303 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, | 303 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, |
304 | fsl_dma_hardware.buffer_bytes_max, | 304 | fsl_dma_hardware.buffer_bytes_max, |
305 | &pcm->streams[0].substream->dma_buffer); | 305 | &pcm->streams[0].substream->dma_buffer); |
306 | if (ret) { | 306 | if (ret) { |
@@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
310 | return -ENOMEM; | 310 | return -ENOMEM; |
311 | } | 311 | } |
312 | 312 | ||
313 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, | 313 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, |
314 | fsl_dma_hardware.buffer_bytes_max, | 314 | fsl_dma_hardware.buffer_bytes_max, |
315 | &pcm->streams[1].substream->dma_buffer); | 315 | &pcm->streams[1].substream->dma_buffer); |
316 | if (ret) { | 316 | if (ret) { |
@@ -418,7 +418,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) | |||
418 | return -EBUSY; | 418 | return -EBUSY; |
419 | } | 419 | } |
420 | 420 | ||
421 | dma_private = dma_alloc_coherent(substream->pcm->dev, | 421 | dma_private = dma_alloc_coherent(substream->pcm->card->dev, |
422 | sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); | 422 | sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); |
423 | if (!dma_private) { | 423 | if (!dma_private) { |
424 | dev_err(substream->pcm->card->dev, | 424 | dev_err(substream->pcm->card->dev, |
@@ -445,7 +445,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) | |||
445 | dev_err(substream->pcm->card->dev, | 445 | dev_err(substream->pcm->card->dev, |
446 | "can't register ISR for IRQ %u (ret=%i)\n", | 446 | "can't register ISR for IRQ %u (ret=%i)\n", |
447 | dma_private->irq, ret); | 447 | dma_private->irq, ret); |
448 | dma_free_coherent(substream->pcm->dev, | 448 | dma_free_coherent(substream->pcm->card->dev, |
449 | sizeof(struct fsl_dma_private), | 449 | sizeof(struct fsl_dma_private), |
450 | dma_private, dma_private->ld_buf_phys); | 450 | dma_private, dma_private->ld_buf_phys); |
451 | return ret; | 451 | return ret; |
@@ -697,6 +697,23 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) | |||
697 | else | 697 | else |
698 | position = in_be32(&dma_channel->dar); | 698 | position = in_be32(&dma_channel->dar); |
699 | 699 | ||
700 | /* | ||
701 | * When capture is started, the SSI immediately starts to fill its FIFO. | ||
702 | * This means that the DMA controller is not started until the FIFO is | ||
703 | * full. However, ALSA calls this function before that happens, when | ||
704 | * MR.DAR is still zero. In this case, just return zero to indicate | ||
705 | * that nothing has been received yet. | ||
706 | */ | ||
707 | if (!position) | ||
708 | return 0; | ||
709 | |||
710 | if ((position < dma_private->dma_buf_phys) || | ||
711 | (position > dma_private->dma_buf_end)) { | ||
712 | dev_err(substream->pcm->card->dev, | ||
713 | "dma pointer is out of range, halting stream\n"); | ||
714 | return SNDRV_PCM_POS_XRUN; | ||
715 | } | ||
716 | |||
700 | frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys); | 717 | frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys); |
701 | 718 | ||
702 | /* | 719 | /* |
@@ -761,13 +778,13 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) | |||
761 | free_irq(dma_private->irq, dma_private); | 778 | free_irq(dma_private->irq, dma_private); |
762 | 779 | ||
763 | if (dma_private->ld_buf_phys) { | 780 | if (dma_private->ld_buf_phys) { |
764 | dma_unmap_single(substream->pcm->dev, | 781 | dma_unmap_single(substream->pcm->card->dev, |
765 | dma_private->ld_buf_phys, | 782 | dma_private->ld_buf_phys, |
766 | sizeof(dma_private->link), DMA_TO_DEVICE); | 783 | sizeof(dma_private->link), DMA_TO_DEVICE); |
767 | } | 784 | } |
768 | 785 | ||
769 | /* Deallocate the fsl_dma_private structure */ | 786 | /* Deallocate the fsl_dma_private structure */ |
770 | dma_free_coherent(substream->pcm->dev, | 787 | dma_free_coherent(substream->pcm->card->dev, |
771 | sizeof(struct fsl_dma_private), | 788 | sizeof(struct fsl_dma_private), |
772 | dma_private, dma_private->ld_buf_phys); | 789 | dma_private, dma_private->ld_buf_phys); |
773 | substream->runtime->private_data = NULL; | 790 | substream->runtime->private_data = NULL; |