Exemplo n.º 1
0
/*
 * Make a circular DMA descriptor list
 */
static int mxs_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxs_runtime_data *prtd = runtime->private_data;
	dma_addr_t dma_buffer_phys;
	int periods_num, playback, i;

	playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0;
	periods_num = prtd->dma_totsize / prtd->dma_period;

	dma_buffer_phys = runtime->dma_addr;

	/* Reset DMA channel, enable interrupt */
	mxs_dma_reset(prtd->dma_ch);

	/* Set up a DMA chain to sent DMA buffer */
	for (i = 0; i < periods_num; i++) {
		int ret;
		/* Link with previous command */
		prtd->dma_desc_array[i]->cmd.cmd.bits.bytes = prtd->dma_period;
		prtd->dma_desc_array[i]->cmd.cmd.bits.irq = 1;
		prtd->dma_desc_array[i]->cmd.cmd.bits.dec_sem = 0;
		prtd->dma_desc_array[i]->cmd.cmd.bits.chain = 1;
		/* Set DMA direction */
		if (playback)
			prtd->dma_desc_array[i]->cmd.cmd.bits.command = \
				DMA_READ;
		else
			prtd->dma_desc_array[i]->cmd.cmd.bits.command = \
				DMA_WRITE;

		prtd->dma_desc_array[i]->cmd.address = dma_buffer_phys;

		ret = mxs_dma_desc_append(prtd->dma_ch, \
			prtd->dma_desc_array[i]);
		if (ret) {
			printk(KERN_ERR "%s: Failed to append DMA descriptor\n",
		       __func__);
			return ret;
		}
		/* Next data chunk */
		dma_buffer_phys += prtd->dma_period;
	}

	return 0;
}
Exemplo n.º 2
0
int submit_request(struct mxs_hsadc_data* pdx, unsigned long count)
{
	unsigned long sample_count;
	memset(pdx->buf, 0, count);

	pdx->desc->cmd.cmd.bits.bytes = count;
	pdx->desc->cmd.cmd.bits.pio_words = 0;
	pdx->desc->cmd.cmd.bits.wait4end = 1;
	pdx->desc->cmd.cmd.bits.dec_sem = 1;
	pdx->desc->cmd.cmd.bits.irq = 1;
	pdx->desc->cmd.cmd.bits.command = DMA_WRITE;
	pdx->desc->cmd.address = pdx->buf_phy;
	
	if(mxs_dma_desc_append(pdx->dma_ch, pdx->desc))
	{
		return -EINVAL;
	}

	//
	// byte(s) to sample count
	//
	sample_count = 
		adc_sample_percision == 8 ? count : (count >> 1); // 10-bit & 12-bit mode a sample word is two bytes size

	writel(sample_count, pdx->hsadc_base + HSADC_SEQUENCE_SAMPLES_NUM);
	writel(1,     pdx->hsadc_base + HSADC_SEQUENCE_NUM);

	writel(1<<31 | 1<<30 | 1<<29, pdx->hsadc_base + HSADC_CTRL1); // enable irq

	mxs_dma_reset(pdx->dma_ch);
	mxs_dma_ack_irq(pdx->dma_ch);
	mxs_dma_enable_irq(pdx->dma_ch, 1);
	if(mxs_dma_enable(pdx->dma_ch))
	{
		return -EINVAL;
	}

	writel(RUN, pdx->hsadc_base + HSADC_CTRL0_SET);
	writel(SOFT_TRIGGER, pdx->hsadc_base + HSADC_CTRL0_SET);
	
	return 0;
}
Exemplo n.º 3
0
static int mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxs_runtime_data *prtd = substream->runtime->private_data;
	int ret = 0;
	switch (cmd) {

	case SNDRV_PCM_TRIGGER_START:
		if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) &&
		    (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
		    (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) &&
		    ((prtd->format == SNDRV_PCM_FORMAT_S24_LE)
		     || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) {
			prtd->appl_ptr_bytes =
			    frames_to_bytes(runtime,
					    runtime->control->appl_ptr);
			memmove(runtime->dma_area + 1, runtime->dma_area,
				prtd->appl_ptr_bytes - 1);
		}
		mxs_dma_enable(prtd->dma_ch);
		break;

	case SNDRV_PCM_TRIGGER_STOP:
		mxs_pcm_stop(substream);
		break;

	case SNDRV_PCM_TRIGGER_RESUME:
		if (mxs_pm_get_target() == PM_SUSPEND_MEM) {

			mxs_dma_reset(prtd->dma_ch);
			mxs_dma_ack_irq(prtd->dma_ch);
			mxs_dma_enable_irq(prtd->dma_ch, 1);
			mxs_pcm_prepare(substream);

			if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) &&
				  (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
				  (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) &&
				  ((prtd->format == SNDRV_PCM_FORMAT_S24_LE)
				   || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) {
				prtd->appl_ptr_bytes =
					  frames_to_bytes(runtime,
							  runtime->control->appl_ptr);
				memmove(runtime->dma_area + 1, runtime->dma_area,
					prtd->appl_ptr_bytes - 1);
			}

			mxs_dma_enable(prtd->dma_ch);
		} else
			mxs_dma_unfreeze(prtd->dma_ch);
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		mxs_dma_unfreeze(prtd->dma_ch);
		break;

	case SNDRV_PCM_TRIGGER_SUSPEND:
		if (mxs_pm_get_target() == PM_SUSPEND_MEM) {
			mxs_pcm_stop(substream);
			mdelay(30);
		}	else {
			mxs_dma_freeze(prtd->dma_ch);
			mdelay(30);
		}
		break;

	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		mxs_dma_freeze(prtd->dma_ch);
		mdelay(30);
		break;

	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}