[PATCH 10/13] dmaengine:audio:mmp audio use generic dma engine APIs

zhaoy zhaoy at marvell.com
Tue Feb 28 02:27:42 EST 2012


	1.change mmp audio to use dma engine

Change-Id: I7be32501b87927a6d05ed34f1c73242e1c60517a
Signed-off-by: zhaoy <zhaoy at marvell.com>
---
 sound/soc/pxa/mmp-pcm.c  |  223 ++++++++++++++++++++++++----------------------
 sound/soc/pxa/mmp-pcm.h  |    4 +-
 sound/soc/pxa/mmp2-squ.c |  182 ++++++++++++++++++--------------------
 sound/soc/pxa/mmp2-squ.h |    8 ++-
 4 files changed, 210 insertions(+), 207 deletions(-)

diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 7469e19..0e322a2 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -137,7 +137,7 @@ static void mmp2_pcm_sync_sram_with_ddr(struct snd_pcm_substream *substream)
 	char *src, *dst;
 	u32 point, rest;
 	int num, i;
-	u32 base;
+
 	pr_debug("%s: copy begin, sram_blk_idx = %d rbuf_blk_idx = %d "
 		 "sync_blk = %d", __func__,
 		 prtd->sram_blk_idx,  prtd->rbuf_blk_idx,
@@ -146,13 +146,12 @@ static void mmp2_pcm_sync_sram_with_ddr(struct snd_pcm_substream *substream)
 	if (!prtd->sync_blk)
 		return;
 
-	base = mmp_get_dma_reg_base(prtd->adma_ch);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		/*
 		 * adjust sram index if dma has run ahead
 		 * rather than memory copy speed
 		 */
-		point = TDSAR(base) - prtd->sram_phys;
+		point = mmp_tdma_chan_get_ptr(prtd->dma_chan) - prtd->sram_phys;
 		rest = mmp2_pcm_point_is_in_region(prtd->sram_size,
 				prtd->sram_blk_idx * prtd->blk_size,
 				prtd->sync_blk * prtd->blk_size,
@@ -173,7 +172,7 @@ static void mmp2_pcm_sync_sram_with_ddr(struct snd_pcm_substream *substream)
 		 * by dma polluted, will copy these periods data
 		 * as possible.
 		 */
-		point = TDSAR(base) - prtd->sram_phys;
+		point = mmp_tdma_chan_get_ptr(prtd->dma_chan) - prtd->sram_phys;
 		rest = mmp2_pcm_point_is_in_region(prtd->sram_size,
 				prtd->sram_blk_idx * prtd->blk_size,
 				prtd->sync_blk * prtd->blk_size,
@@ -193,7 +192,6 @@ static void mmp2_pcm_sync_sram_with_ddr(struct snd_pcm_substream *substream)
 
 	num = prtd->sync_blk;
 	for (i = 0; i < num; i++) {
-
 		mmp2_pcm_copy_data((int *)dst, (int *)src,
 			prtd->blk_size);
 
@@ -216,18 +214,24 @@ static void mmp2_pcm_sync_sram_with_ddr(struct snd_pcm_substream *substream)
 	return;
 }
 
-static void mmp2_pcm_adma_irq(int dma_ch, void *data)
+static bool filter(struct dma_chan *chan, void *param)
+{
+	struct mmp2_runtime_data *prtd = param;
+
+	if (!mmp_adma_is_this_type(chan))
+		return false;
+
+	if (!mmp_tdma_is_specific_chan(chan, prtd->dma_ch))
+		return false;
+
+	chan->private = &prtd->tdma_data;
+	return true;
+}
+
+static void mmp2_pcm_adma_irq(void *data)
 {
 	struct snd_pcm_substream *substream = data;
 	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
-	u32 base = mmp_get_dma_reg_base(prtd->adma_ch);
-	if (!base)
-		return;
-
-	if (!(TDISR(base) & 0x1))
-		return;
-	/* clear adma irq status */
-	TDISR(base) = 0;
 
 	/* sync sram with ring buf */
 	prtd->sync_blk = min(prtd->sync_blk + 1, prtd->sram_blk_num);
@@ -247,11 +251,12 @@ static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
 	size_t totsize = params_buffer_bytes(params);
 	size_t period = params_period_bytes(params);
 	struct mmp_tdma_desc *adma_desc;
-	dma_addr_t dma_buff_phys, next_desc_phys;
+	dma_addr_t adma_buff_phys, next_desc_phys;
 	int ret;
+	dma_cap_mask_t mask;
+
+	dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
-	dma = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-	    rtd->cpu_dai->playback_dma_data : rtd->cpu_dai->capture_dma_data;
 	/* return if this is a bufferless transfer e.g.
 	 * codec <--> BT codec or GSM modem -- lg FIXME */
 	if (!dma)
@@ -261,27 +266,66 @@ static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
 	 * this may get called several times by oss
 	 * emulation with different params
 	 */
-	if (prtd->params == NULL) {
-		prtd->params = dma;
-		ret = mmp_request_dma(prtd->params->name, dma->dma_ch,
-					 mmp2_pcm_adma_irq, substream);
-		if (ret < 0)
-			return ret;
-
-		prtd->adma_ch = ret;
-	} else if (prtd->params != dma) {
-		mmp_free_dma(prtd->adma_ch);
-		prtd->params = dma;
-		ret = mmp_request_dma(prtd->params->name, dma->dma_ch,
-					 mmp2_pcm_adma_irq, substream);
-		if (ret < 0)
-			return ret;
-
-		prtd->adma_ch = ret;
+	prtd->dma_ch = dma->dma_ch;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		prtd->tdma_data.bus_size = TDCR_SSZ_8_BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		prtd->tdma_data.bus_size = TDCR_SSZ_16_BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		prtd->tdma_data.bus_size = TDCR_SSZ_24_BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		prtd->tdma_data.bus_size = TDCR_SSZ_32_BITS;
+		break;
+	default:
+		return -EINVAL;
 	}
+	prtd->tdma_data.pack_mod = true;
+
+	/* Try to grab a DMA channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+	prtd->dma_chan = dma_request_channel(mask, filter, prtd);
+	if (!prtd->dma_chan)
+		return -EINVAL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		prtd->slave_config.direction    = DMA_TO_DEVICE;
+		prtd->slave_config.dst_addr     = dma->dev_addr;
+		prtd->slave_config.dst_maxburst = TDCR_BURSTSZ_4B;
+	} else {
+		prtd->slave_config.direction	  = DMA_FROM_DEVICE;
+		prtd->slave_config.src_addr	  = dma->dev_addr;
+		prtd->slave_config.src_maxburst = TDCR_BURSTSZ_4B;
+	}
+
+	ret = dmaengine_slave_config(prtd->dma_chan, &(prtd->slave_config));
+	if (ret) {
+		printk(KERN_ERR "%s: dmaengine slave config err.\n", __func__);
+		return ret;
+	}
+
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = totsize;
 
+	/*
+	 * init prtd value.
+	 * the driver has alloc from sram for dma transfer,
+	 * size = MMP2_ADMA_BUF_SIZE (now is equal to PAGE_SIZE).
+	 * and driver has alloc ddr buffer for mmapping to userspace,
+	 * and the size = MMP2_DDR_BUF_SIZE, now is 64KB.
+	 *
+	 * but should note the used buffer size is specified
+	 * by userspace's app, which is calculated by the
+	 * periold_size and buffer_size. The buffer size
+	 * is even less than the buffer size which allocated
+	 * from the sram.
+	 * So at this point should adjust the parameters
+	 * according to user's setting.
+	 */
 	prtd->blk_size     = period;
 	prtd->rbuf_virt    = (u32)runtime->dma_area;
 	prtd->rbuf_phys    = (u32)runtime->dma_addr;
@@ -294,31 +338,22 @@ static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
 	prtd->sync_blk     = 0;
 
 	totsize        = prtd->sram_size;
-	dma_buff_phys  = prtd->sram_phys;
+	adma_buff_phys = prtd->sram_phys;
 	next_desc_phys = prtd->adma_desc_array_phys;
 	adma_desc      = prtd->adma_desc_array;
 
-	do {
-		next_desc_phys += sizeof(struct mmp_tdma_desc);
-
-		adma_desc->nxt_desc = next_desc_phys;
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			adma_desc->src_addr = dma_buff_phys;
-			adma_desc->dst_addr = prtd->params->dev_addr;
-		} else {
-			adma_desc->src_addr = prtd->params->dev_addr;
-			adma_desc->dst_addr = dma_buff_phys;
-		}
-		if (period > totsize)
-			period = totsize;
-		adma_desc->byte_cnt = period;
-		adma_desc++;
-		dma_buff_phys += period;
-
-	} while (totsize -= period);
-	adma_desc[-1].nxt_desc = prtd->adma_desc_array_phys;
+	prtd->desc = prtd->dma_chan->device->device_prep_dma_cyclic(
+			prtd->dma_chan, adma_buff_phys, totsize, period,
+			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+			DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	if (!prtd->desc) {
+		dev_err(&prtd->dma_chan->dev->device,
+			"cannot prepare slave dma\n");
+		return -EINVAL;
+	}
 
-	mmp2_pcm_dump_adma_list(prtd);
+	prtd->desc->callback = mmp2_pcm_adma_irq;
+	prtd->desc->callback_param = substream;
 
 	return 0;
 }
@@ -327,10 +362,9 @@ static int mmp2_pcm_hw_free(struct snd_pcm_substream *substream)
 {
 	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
 
-	if (prtd->adma_ch != -1) {
-		snd_pcm_set_runtime_buffer(substream, NULL);
-		mmp_free_dma(prtd->adma_ch);
-		prtd->adma_ch = -1;
+	if (prtd->dma_chan) {
+		dma_release_channel(prtd->dma_chan);
+		prtd->dma_chan = NULL;
 	}
 
 	return 0;
@@ -338,16 +372,6 @@ static int mmp2_pcm_hw_free(struct snd_pcm_substream *substream)
 
 static int mmp2_pcm_prepare(struct snd_pcm_substream *substream)
 {
-	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
-	u32 base;
-
-	base = mmp_get_dma_reg_base(prtd->adma_ch);
-	if (!base)
-		return -EINVAL;
-
-	TDCR(base)  = (prtd->params->dcmd) & (~TDCR_CHANEN);
-	TDIMR(base) = TDIMR_COMP;
-
 	return 0;
 }
 
@@ -356,11 +380,6 @@ static int mmp2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
 	unsigned long flags;
 	int ret = 0;
-	u32 base_register;
-
-	base_register = mmp_get_dma_reg_base(prtd->adma_ch);
-	if (!base_register)
-		return -EINVAL;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -378,24 +397,21 @@ static int mmp2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		mmp2_pcm_sync_sram_with_ddr(substream);
 		spin_unlock_irqrestore(&prtd->lock, flags);
 
-		TDNDPR(base_register) = prtd->adma_desc_array_phys;
-		TDCR(base_register) = prtd->params->dcmd | TDCR_CHANEN;
+		dmaengine_submit(prtd->desc);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		TDCR(base_register) = prtd->params->dcmd;
-		wake_up(&dma_wq);
+		dmaengine_terminate_all(prtd->dma_chan);
 		break;
 
 	case SNDRV_PCM_TRIGGER_RESUME:
-		TDCR(base_register) = prtd->params->dcmd | TDCR_CHANEN;
+		dmaengine_submit(prtd->desc);
 		break;
 
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		TDNDPR(base_register) = prtd->adma_desc_array_phys;
-		TDCR(base_register) = prtd->params->dcmd | TDCR_CHANEN;
+		dmaengine_submit(prtd->desc);
 		break;
 
 	default:
@@ -460,7 +476,7 @@ static int mmp2_pcm_open(struct snd_pcm_substream *substream)
 
 	prtd->substream = substream;
 	runtime->private_data = prtd;
-	prtd->adma_ch = -1;
+	prtd->dma_ch = -1;
 
 	/*
 	 * avoid sram fragment, allocate dma buffer and
@@ -471,6 +487,11 @@ static int mmp2_pcm_open(struct snd_pcm_substream *substream)
 			MMP2_ADMA_BUF_SIZE + MMP2_ADMA_DESC_SIZE,
 			(dma_addr_t *)&prtd->sram_phys);
 
+	if (!prtd->sram_virt) {
+		printk(KERN_ERR "failed to map audio sram\n");
+		goto alloc_sram_err;
+	}
+
 	prtd->adma_desc_array = (void *)(prtd->sram_virt + MMP2_ADMA_BUF_SIZE);
 	prtd->adma_desc_array_phys = (dma_addr_t)(prtd->sram_phys
 					+ MMP2_ADMA_BUF_SIZE);
@@ -492,7 +513,7 @@ static int mmp2_pcm_suspend(struct snd_soc_dai *dai)
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime *runtime;
 	struct mmp2_runtime_data *prtd;
-	u32 base, ch;
+	u32 ch;
 	int stream;
 
 	for (stream = 0; stream < 2; stream++) {
@@ -504,22 +525,10 @@ static int mmp2_pcm_suspend(struct snd_soc_dai *dai)
 			continue;
 
 		prtd = runtime->private_data;
-		ch = prtd->adma_ch;
+		ch = prtd->dma_ch;
 
 		pr_debug("%s: dai name %s stream %d dma ch %d prtd %p\n",
-			__func__, dai->name, stream, prtd->adma_ch, prtd);
-
-		/* mmp2 only uses chain mode */
-		base = mmp_get_dma_reg_base(ch);
-
-		prtd->adma_saved.src_addr  = TDSAR(base);
-		prtd->adma_saved.dest_addr = TDDAR(base);
-		prtd->adma_saved.next_desc_ptr = TDNDPR(base);
-		prtd->adma_saved.ctrl = TDCR(base) & ~TDCR_CHANEN;
-		prtd->adma_saved.chan_pri = TDCP(base);
-		prtd->adma_saved.curr_desc_ptr = TDCDPR(base);
-		prtd->adma_saved.intr_mask = TDIMR(base);
-		prtd->adma_saved.intr_status = TDISR(base);
+			__func__, dai->name, stream, prtd->dma_ch, prtd);
 
 		memcpy(prtd->sram_saved, (void *)prtd->sram_virt,
 			MMP2_ADMA_BUF_SIZE + MMP2_ADMA_DESC_SIZE);
@@ -534,7 +543,7 @@ static int mmp2_pcm_resume(struct snd_soc_dai *dai)
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime *runtime;
 	struct mmp2_runtime_data *prtd;
-	u32 base, ch;
+	u32 ch;
 	int stream;
 
 	for (stream = 0; stream < 2; stream++) {
@@ -545,18 +554,18 @@ static int mmp2_pcm_resume(struct snd_soc_dai *dai)
 			continue;
 
 		prtd = runtime->private_data;
-		ch = prtd->adma_ch;
+		ch = prtd->dma_ch;
 
 		pr_debug("%s: dai name %s stream %d dma ch %d prtd %p\n",
-			__func__, dai->name, stream, prtd->adma_ch, prtd);
+			__func__, dai->name, stream, prtd->dma_ch, prtd);
 
-		base = mmp_get_dma_reg_base(ch);
+		dmaengine_slave_config(prtd->dma_chan, &(prtd->slave_config));
 
-		/* MMP2 only uses chain mode */
-		TDNDPR(base) = prtd->adma_saved.next_desc_ptr;
-		TDCP(base)   = prtd->adma_saved.chan_pri;
-		TDIMR(base)  = prtd->adma_saved.intr_mask;
-		TDCR(base)   = prtd->adma_saved.ctrl;
+		prtd->dma_chan->device->device_prep_dma_cyclic(
+			prtd->dma_chan, prtd->sram_phys,
+			prtd->sram_size, prtd->blk_size,
+			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+			DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 		memcpy((void *)prtd->sram_virt, prtd->sram_saved,
 			MMP2_ADMA_BUF_SIZE + MMP2_ADMA_DESC_SIZE);
diff --git a/sound/soc/pxa/mmp-pcm.h b/sound/soc/pxa/mmp-pcm.h
index ab03e9d..909d61a 100644
--- a/sound/soc/pxa/mmp-pcm.h
+++ b/sound/soc/pxa/mmp-pcm.h
@@ -44,7 +44,8 @@ struct mmp2_adma_registers {
 };
 
 struct mmp2_runtime_data {
-	int adma_ch;
+	int dma_ch;
+	struct mmp_tdma_data tdma_data;
 	struct mmp2_adma_params *params;
 	void *adma_desc_array;
 	dma_addr_t adma_desc_array_phys;
@@ -75,6 +76,7 @@ struct mmp2_runtime_data {
 
 	struct mmp2_adma_registers adma_saved;
 	char sram_saved[MMP2_ADMA_TOTAL_SIZE];
+	struct dma_slave_config slave_config;
 };
 
 extern struct snd_soc_platform_driver mmp2_soc_platform;
diff --git a/sound/soc/pxa/mmp2-squ.c b/sound/soc/pxa/mmp2-squ.c
index 6d3cc10..4b9bb3b 100644
--- a/sound/soc/pxa/mmp2-squ.c
+++ b/sound/soc/pxa/mmp2-squ.c
@@ -27,6 +27,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -131,21 +132,25 @@ static int mmp2_sram_mmap_noncached(struct vm_area_struct *vma,
 	return ret;
 }
 
-static void mmp2_adma_irq(int dma_ch, void *dev_id)
+static void mmp2_adma_irq(void *data)
 {
-	struct snd_pcm_substream *substream = dev_id;
-	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
+	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
 
-	u32 base_register = mmp_get_dma_reg_base(dma_ch);
-	if (base_register) {
-		if (TDISR(base_register) & 0x1)
-			snd_pcm_period_elapsed(substream);
-		else {
-			printk(KERN_ERR "%s: SQU error on channel %d\n",
-			       prtd->params->name, dma_ch);
-		}
-		TDISR(base_register) = 0;
-	}
+	snd_pcm_period_elapsed(substream);
+}
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+	struct mmp2_runtime_data *prtd = param;
+
+	if (!mmp_adma_is_this_type(chan))
+		return false;
+
+	if (!mmp_tdma_is_specific_chan(chan, prtd->dma_ch))
+		return false;
+
+	chan->private = &prtd->tdma_data;
+	return true;
 }
 
 static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -159,6 +164,9 @@ static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
 	size_t period = params_period_bytes(params);
 	struct mmp_tdma_desc *adma_desc;
 	dma_addr_t dma_buff_phys, next_desc_phys;
+	struct dma_slave_config slave_config;
+	dma_cap_mask_t mask;
+	enum dma_slave_buswidth buswidth;
 	int ret;
 
 	dma = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
@@ -168,25 +176,47 @@ static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (!dma)
 		return 0;
 
-	/* this may get called several times by oss emulation
-	 * with different params */
-	if (prtd->params == NULL) {
-		prtd->params = dma;
-		ret = mmp_request_dma(prtd->params->name, dma->dma_ch,
-					 mmp2_adma_irq, substream);
-		if (ret < 0)
-			return ret;
-
-		prtd->adma_ch = ret;
-	} else if (prtd->params != dma) {
-		mmp_free_dma(prtd->adma_ch);
-		prtd->params = dma;
-		ret = mmp_request_dma(prtd->params->name, dma->dma_ch,
-					 mmp2_adma_irq, substream);
-		if (ret < 0)
-			return ret;
-
-		prtd->adma_ch = ret;
+	prtd->dma_ch = dma->dma_ch;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		prtd->tdma_data.bus_size = TDCR_SSZ_8_BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		prtd->tdma_data.bus_size = TDCR_SSZ_16_BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		prtd->tdma_data.bus_size = TDCR_SSZ_24_BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		prtd->tdma_data.bus_size = TDCR_SSZ_32_BITS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	prtd->tdma_data.pack_mod = true;
+
+	/* Try to grab a DMA channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+	prtd->dma_chan = dma_request_channel(mask, filter, prtd);
+	if (!prtd->dma_chan)
+		return -EINVAL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		slave_config.direction    = DMA_TO_DEVICE;
+		slave_config.dst_addr     = dma->dev_addr;
+		slave_config.dst_maxburst = TDCR_BURSTSZ_4B;
+	} else {
+		slave_config.direction	  = DMA_FROM_DEVICE;
+		slave_config.src_addr	  = dma->dev_addr;
+		slave_config.src_maxburst = TDCR_BURSTSZ_4B;
+	}
+
+	ret = dmaengine_slave_config(prtd->dma_chan, &slave_config);
+	if (ret) {
+		printk(KERN_ERR "%s: dmaengine slave config err.\n", __func__);
+		return ret;
 	}
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
@@ -196,25 +226,19 @@ static int mmp2_pcm_hw_params(struct snd_pcm_substream *substream,
 	dma_buff_phys = runtime->dma_addr;
 
 	adma_desc = prtd->adma_desc_array;
-	do {
-		next_desc_phys += sizeof(struct mmp_tdma_desc);
-
-		adma_desc->nxt_desc = next_desc_phys;
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			adma_desc->src_addr = dma_buff_phys;
-			adma_desc->dst_addr = prtd->params->dev_addr;
-		} else {
-			adma_desc->src_addr = prtd->params->dev_addr;
-			adma_desc->dst_addr = dma_buff_phys;
-		}
-		if (period > totsize)
-			period = totsize;
-		adma_desc->byte_cnt = period;
-		adma_desc++;
-		dma_buff_phys += period;
-
-	} while (totsize -= period);
-	adma_desc[-1].nxt_desc = prtd->adma_desc_array_phys;
+
+	prtd->desc = prtd->dma_chan->device->device_prep_dma_cyclic(
+			prtd->dma_chan, dma_buff_phys, totsize, period,
+			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+			DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	if (!prtd->desc) {
+		dev_err(&prtd->dma_chan->dev->device,
+				"cannot prepare slave dma\n");
+		return -EINVAL;
+	}
+
+	prtd->desc->callback = mmp2_adma_irq;
+	prtd->desc->callback_param = substream;
 
 	return 0;
 }
@@ -223,10 +247,9 @@ static int mmp2_pcm_hw_free(struct snd_pcm_substream *substream)
 {
 	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
 
-	if (prtd->adma_ch != -1) {
-		snd_pcm_set_runtime_buffer(substream, NULL);
-		mmp_free_dma(prtd->adma_ch);
-		prtd->adma_ch = -1;
+	if (prtd->dma_chan) {
+		dma_release_channel(prtd->dma_chan);
+		prtd->dma_chan = NULL;
 	}
 
 	return 0;
@@ -234,50 +257,31 @@ static int mmp2_pcm_hw_free(struct snd_pcm_substream *substream)
 
 static int mmp2_pcm_prepare(struct snd_pcm_substream *substream)
 {
-	int ret = 0;
-	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
-
-	u32 base_register = mmp_get_dma_reg_base(prtd->adma_ch);
-	if (base_register) {
-		TDCR(base_register) = (prtd->params->dcmd)
-		    & (~TDCR_CHANEN);
-		TDIMR(base_register) = TDIMR_COMP;
-	} else
-		ret = -EINVAL;
-
-	return ret;
+	return 0;
 }
 
 static int mmp2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct mmp2_runtime_data *prtd = substream->runtime->private_data;
 	int ret = 0;
-	u32 base_register;
-
-	base_register = mmp_get_dma_reg_base(prtd->adma_ch);
-	if (!base_register)
-		return -EINVAL;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		TDNDPR(base_register) = prtd->adma_desc_array_phys;
-		TDCR(base_register) = prtd->params->dcmd | TDCR_CHANEN;
+		dmaengine_submit(prtd->desc);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		TDCR(base_register) = prtd->params->dcmd;
-		wake_up(&dma_wq);
+		dmaengine_terminate_all(prtd->dma_chan);
 		break;
 
 	case SNDRV_PCM_TRIGGER_RESUME:
-		TDCR(base_register) = prtd->params->dcmd | TDCR_CHANEN;
+		dmaengine_submit(prtd->desc);
 		break;
 
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		TDNDPR(base_register) = prtd->adma_desc_array_phys;
-		TDCR(base_register) = prtd->params->dcmd | TDCR_CHANEN;
+		dmaengine_submit(prtd->desc);
 		break;
 
 	default:
@@ -294,9 +298,7 @@ static snd_pcm_uframes_t mmp2_pcm_pointer(struct snd_pcm_substream *substream)
 	dma_addr_t ptr;
 	snd_pcm_uframes_t x;
 
-	u32 base_register = mmp_get_dma_reg_base(prtd->adma_ch);
-	ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-	    TDSAR(base_register) : TDDAR(base_register);
+	ptr = mmp_tdma_chan_get_ptr(prtd->dma_chan);
 
 	x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
 
@@ -344,23 +346,11 @@ static int mmp2_pcm_open(struct snd_pcm_substream *substream)
 		goto out;
 	}
 
-	/*
-	 * avoid sram fragment, allocate dma buffer and
-	 * dma desc list at the same time.
-	 */
-	prtd->adma_desc_array = sram_alloc("audio sram", PAGE_SIZE,
-				    (dma_addr_t *)&prtd->adma_desc_array_phys);
-	if (!prtd->adma_desc_array) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
 	runtime->private_data = prtd;
+	prtd->dma_ch = -1;
 
 	return 0;
 
-err1:
-	kfree(prtd);
 out:
 	return ret;
 }
@@ -370,8 +360,6 @@ static int mmp2_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct mmp2_runtime_data *prtd = runtime->private_data;
 
-	sram_free("audio sram", (void *)prtd->adma_desc_array, PAGE_SIZE);
-
 	kfree(prtd);
 	runtime->private_data = NULL;
 	return 0;
diff --git a/sound/soc/pxa/mmp2-squ.h b/sound/soc/pxa/mmp2-squ.h
index 4f03bb4..ff8a832 100644
--- a/sound/soc/pxa/mmp2-squ.h
+++ b/sound/soc/pxa/mmp2-squ.h
@@ -15,6 +15,8 @@
 #ifndef _MMP2_SQU_H
 #define _MMP2_SQU_H
 
+#include <mach/mmp_dma.h>
+
 #define MMP2_ADMA_BUF_SIZE		(PAGE_SIZE)
 #define MMP2_ADMA_DESC_SIZE		(1024)
 #define MMP2_DDR_BUF_SIZE		(MMP2_ADMA_BUF_SIZE << 4)
@@ -42,8 +44,8 @@ struct mmp2_adma_registers {
 };
 
 struct mmp2_runtime_data {
-	int adma_ch;
-	struct mmp2_adma_params *params;
+	int dma_ch;
+	struct mmp_tdma_data tdma_data;
 	void *adma_desc_array;
 	dma_addr_t adma_desc_array_phys;
 
@@ -69,6 +71,8 @@ struct mmp2_runtime_data {
 	u32 blk_size;
 
 	struct snd_pcm_substream *substream;
+	struct dma_chan *dma_chan;
+	struct dma_async_tx_descriptor *desc;
 
 	struct mmp2_adma_registers adma_saved;
 	char sram_saved[MMP2_ADMA_TOTAL_SIZE];
-- 
1.7.0.4




More information about the linux-arm-kernel mailing list