summaryrefslogtreecommitdiffstats
path: root/sound/soc/davinci/davinci-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/davinci/davinci-pcm.c')
-rw-r--r--sound/soc/davinci/davinci-pcm.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 7af3b5b..a059965 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -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);
OpenPOWER on IntegriCloud