|
@@ -22,6 +22,7 @@
|
|
|
#include <sound/soc.h>
|
|
|
|
|
|
#include <asm/dma.h>
|
|
|
+#include <mach/edma.h>
|
|
|
|
|
|
#include "davinci-pcm.h"
|
|
|
|
|
@@ -51,7 +52,7 @@ struct davinci_runtime_data {
|
|
|
spinlock_t lock;
|
|
|
int period; /* current DMA period */
|
|
|
int master_lch; /* Master DMA channel */
|
|
|
- int slave_lch; /* Slave DMA channel */
|
|
|
+ int slave_lch; /* linked parameter RAM reload slot */
|
|
|
struct davinci_pcm_dma_params *params; /* DMA params */
|
|
|
};
|
|
|
|
|
@@ -90,18 +91,18 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
|
|
|
dst_bidx = data_type;
|
|
|
}
|
|
|
|
|
|
- davinci_set_dma_src_params(lch, src, INCR, W8BIT);
|
|
|
- davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
|
|
|
- davinci_set_dma_src_index(lch, src_bidx, 0);
|
|
|
- davinci_set_dma_dest_index(lch, dst_bidx, 0);
|
|
|
- davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
|
|
|
+ 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);
|
|
|
|
|
|
prtd->period++;
|
|
|
if (unlikely(prtd->period >= runtime->periods))
|
|
|
prtd->period = 0;
|
|
|
}
|
|
|
|
|
|
-static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
|
|
|
+static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data)
|
|
|
{
|
|
|
struct snd_pcm_substream *substream = data;
|
|
|
struct davinci_runtime_data *prtd = substream->runtime->private_data;
|
|
@@ -125,7 +126,7 @@ 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;
|
|
|
- int tcc = TCC_ANY;
|
|
|
+ struct edmacc_param p_ram;
|
|
|
int ret;
|
|
|
|
|
|
if (!dma_data)
|
|
@@ -134,22 +135,34 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
|
|
|
prtd->params = dma_data;
|
|
|
|
|
|
/* Request master DMA channel */
|
|
|
- ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
|
|
|
+ ret = edma_alloc_channel(prtd->params->channel,
|
|
|
davinci_pcm_dma_irq, substream,
|
|
|
- &prtd->master_lch, &tcc, EVENTQ_0);
|
|
|
- if (ret)
|
|
|
+ EVENTQ_0);
|
|
|
+ if (ret < 0)
|
|
|
return ret;
|
|
|
+ prtd->master_lch = ret;
|
|
|
|
|
|
- /* Request slave DMA channel */
|
|
|
- ret = davinci_request_dma(PARAM_ANY, "Link",
|
|
|
- NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
|
|
|
- if (ret) {
|
|
|
- davinci_free_dma(prtd->master_lch);
|
|
|
+ /* Request parameter RAM reload slot */
|
|
|
+ ret = edma_alloc_slot(EDMA_SLOT_ANY);
|
|
|
+ if (ret < 0) {
|
|
|
+ edma_free_channel(prtd->master_lch);
|
|
|
return ret;
|
|
|
}
|
|
|
-
|
|
|
- /* Link slave DMA channel in loopback */
|
|
|
- davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
|
|
|
+ prtd->slave_lch = ret;
|
|
|
+
|
|
|
+ /* Issue transfer completion IRQ when the channel completes a
|
|
|
+ * transfer, then always reload from the same slot (by a kind
|
|
|
+ * of loopback link). The completion IRQ handler will update
|
|
|
+ * the reload slot with a new buffer.
|
|
|
+ *
|
|
|
+ * REVISIT save p_ram here after setting up everything except
|
|
|
+ * the buffer and its length (ccnt) ... use it as a template
|
|
|
+ * so davinci_pcm_enqueue_dma() takes less time in IRQ.
|
|
|
+ */
|
|
|
+ edma_read_slot(prtd->slave_lch, &p_ram);
|
|
|
+ p_ram.opt |= TCINTEN | EDMA_TCC(prtd->master_lch);
|
|
|
+ p_ram.link_bcntrld = prtd->slave_lch << 5;
|
|
|
+ edma_write_slot(prtd->slave_lch, &p_ram);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -165,12 +178,12 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
|
case SNDRV_PCM_TRIGGER_START:
|
|
|
case SNDRV_PCM_TRIGGER_RESUME:
|
|
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
|
|
- davinci_start_dma(prtd->master_lch);
|
|
|
+ edma_start(prtd->master_lch);
|
|
|
break;
|
|
|
case SNDRV_PCM_TRIGGER_STOP:
|
|
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
|
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
|
|
- davinci_stop_dma(prtd->master_lch);
|
|
|
+ edma_stop(prtd->master_lch);
|
|
|
break;
|
|
|
default:
|
|
|
ret = -EINVAL;
|
|
@@ -185,14 +198,14 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
|
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
|
|
|
{
|
|
|
struct davinci_runtime_data *prtd = substream->runtime->private_data;
|
|
|
- struct paramentry_descriptor temp;
|
|
|
+ struct edmacc_param temp;
|
|
|
|
|
|
prtd->period = 0;
|
|
|
davinci_pcm_enqueue_dma(substream);
|
|
|
|
|
|
- /* Get slave channel dma params for master channel startup */
|
|
|
- davinci_get_dma_params(prtd->slave_lch, &temp);
|
|
|
- davinci_set_dma_params(prtd->master_lch, &temp);
|
|
|
+ /* Copy self-linked parameter RAM entry into master channel */
|
|
|
+ edma_read_slot(prtd->slave_lch, &temp);
|
|
|
+ edma_write_slot(prtd->master_lch, &temp);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -208,7 +221,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
|
|
|
|
|
|
spin_lock(&prtd->lock);
|
|
|
|
|
|
- davinci_dma_getposition(prtd->master_lch, &src, &dst);
|
|
|
+ edma_get_position(prtd->master_lch, &src, &dst);
|
|
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
|
|
count = src - runtime->dma_addr;
|
|
|
else
|
|
@@ -253,10 +266,10 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
|
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
struct davinci_runtime_data *prtd = runtime->private_data;
|
|
|
|
|
|
- davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
|
|
|
+ edma_unlink(prtd->slave_lch);
|
|
|
|
|
|
- davinci_free_dma(prtd->slave_lch);
|
|
|
- davinci_free_dma(prtd->master_lch);
|
|
|
+ edma_free_slot(prtd->slave_lch);
|
|
|
+ edma_free_channel(prtd->master_lch);
|
|
|
|
|
|
kfree(prtd);
|
|
|
|