ASoC: DaVinci: McASP FIFO related updates
[pandora-kernel.git] / sound / soc / davinci / davinci-pcm.c
index a059965..1152d8b 100644 (file)
@@ -66,36 +66,53 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
        dma_addr_t dma_pos;
        dma_addr_t src, dst;
        unsigned short src_bidx, dst_bidx;
+       unsigned short src_cidx, dst_cidx;
        unsigned int data_type;
+       unsigned short acnt;
        unsigned int count;
+       unsigned int fifo_level;
 
        period_size = snd_pcm_lib_period_bytes(substream);
        dma_offset = prtd->period * period_size;
        dma_pos = runtime->dma_addr + dma_offset;
+       fifo_level = prtd->params->fifo_level;
 
        pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
                "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);
 
        data_type = prtd->params->data_type;
        count = period_size / data_type;
+       if (fifo_level)
+               count /= fifo_level;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                src = dma_pos;
                dst = prtd->params->dma_addr;
                src_bidx = data_type;
                dst_bidx = 0;
+               src_cidx = data_type * fifo_level;
+               dst_cidx = 0;
        } else {
                src = prtd->params->dma_addr;
                dst = dma_pos;
                src_bidx = 0;
                dst_bidx = data_type;
+               src_cidx = 0;
+               dst_cidx = data_type * fifo_level;
        }
 
+       acnt = prtd->params->acnt;
        edma_set_src(lch, src, INCR, W8BIT);
        edma_set_dest(lch, dst, INCR, W8BIT);
-       edma_set_src_index(lch, src_bidx, 0);
-       edma_set_dest_index(lch, dst_bidx, 0);
-       edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);
+
+       edma_set_src_index(lch, src_bidx, src_cidx);
+       edma_set_dest_index(lch, dst_bidx, dst_cidx);
+
+       if (!fifo_level)
+               edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC);
+       else
+               edma_set_transfer_params(lch, acnt, fifo_level, count,
+                                                       fifo_level, ABSYNC);
 
        prtd->period++;
        if (unlikely(prtd->period >= runtime->periods))
@@ -124,16 +141,9 @@ static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data)
 static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
 {
        struct davinci_runtime_data *prtd = substream->runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
        struct edmacc_param p_ram;
        int ret;
 
-       if (!dma_data)
-               return -ENODEV;
-
-       prtd->params = dma_data;
-
        /* Request master DMA channel */
        ret = edma_alloc_channel(prtd->params->channel,
                                  davinci_pcm_dma_irq, substream,
@@ -206,6 +216,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
        /* Copy self-linked parameter RAM entry into master channel */
        edma_read_slot(prtd->slave_lch, &temp);
        edma_write_slot(prtd->master_lch, &temp);
+       davinci_pcm_enqueue_dma(substream);
 
        return 0;
 }
@@ -241,14 +252,25 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct davinci_runtime_data *prtd;
        int ret = 0;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->private_data;
+       struct davinci_pcm_dma_params *params = &pa[substream->stream];
+       if (!params)
+               return -ENODEV;
 
        snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
+       /* ensure that buffer size is a multiple of period size */
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               return ret;
 
        prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
        if (prtd == NULL)
                return -ENOMEM;
 
        spin_lock_init(&prtd->lock);
+       prtd->params = params;
 
        runtime->private_data = prtd;