diff options
Diffstat (limited to 'sound/soc/davinci/davinci-pcm.c')
| -rw-r--r-- | sound/soc/davinci/davinci-pcm.c | 69 | 
1 files changed, 41 insertions, 28 deletions
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 7af3b5b3a53..a0599658848 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;  	} +	prtd->slave_lch = ret; -	/* Link slave DMA channel in loopback */ -	davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch); +	/* 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);  |