]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - sound/soc/fsl/fsl_dma.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6-omap-h63xx.git] / sound / soc / fsl / fsl_dma.c
index b3eb8570cd7bf4a4073082fffdc9f3dbb71d9521..b1a3a278819fe6fa16a1a14d38b02221a05517e2 100644 (file)
@@ -300,7 +300,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = fsl_dma_dmamask;
 
-       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev,
+       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
                fsl_dma_hardware.buffer_bytes_max,
                &pcm->streams[0].substream->dma_buffer);
        if (ret) {
@@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
                return -ENOMEM;
        }
 
-       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev,
+       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
                fsl_dma_hardware.buffer_bytes_max,
                &pcm->streams[1].substream->dma_buffer);
        if (ret) {
@@ -418,7 +418,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
                return -EBUSY;
        }
 
-       dma_private = dma_alloc_coherent(substream->pcm->dev,
+       dma_private = dma_alloc_coherent(substream->pcm->card->dev,
                sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL);
        if (!dma_private) {
                dev_err(substream->pcm->card->dev,
@@ -445,7 +445,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
                dev_err(substream->pcm->card->dev,
                        "can't register ISR for IRQ %u (ret=%i)\n",
                        dma_private->irq, ret);
-               dma_free_coherent(substream->pcm->dev,
+               dma_free_coherent(substream->pcm->card->dev,
                        sizeof(struct fsl_dma_private),
                        dma_private, dma_private->ld_buf_phys);
                return ret;
@@ -697,6 +697,23 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
        else
                position = in_be32(&dma_channel->dar);
 
+       /*
+        * When capture is started, the SSI immediately starts to fill its FIFO.
+        * This means that the DMA controller is not started until the FIFO is
+        * full.  However, ALSA calls this function before that happens, when
+        * MR.DAR is still zero.  In this case, just return zero to indicate
+        * that nothing has been received yet.
+        */
+       if (!position)
+               return 0;
+
+       if ((position < dma_private->dma_buf_phys) ||
+           (position > dma_private->dma_buf_end)) {
+               dev_err(substream->pcm->card->dev,
+                       "dma pointer is out of range, halting stream\n");
+               return SNDRV_PCM_POS_XRUN;
+       }
+
        frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys);
 
        /*
@@ -761,13 +778,13 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)
                        free_irq(dma_private->irq, dma_private);
 
                if (dma_private->ld_buf_phys) {
-                       dma_unmap_single(substream->pcm->dev,
+                       dma_unmap_single(substream->pcm->card->dev,
                                dma_private->ld_buf_phys,
                                sizeof(dma_private->link), DMA_TO_DEVICE);
                }
 
                /* Deallocate the fsl_dma_private structure */
-               dma_free_coherent(substream->pcm->dev,
+               dma_free_coherent(substream->pcm->card->dev,
                        sizeof(struct fsl_dma_private),
                        dma_private, dma_private->ld_buf_phys);
                substream->runtime->private_data = NULL;