Esempio n. 1
0
/*
 * Stop circular DMA descriptor list
 * We should not stop DMA in a middle of current transaction once we receive
 * stop request from ALSA core. This function finds the next DMA descriptor
 * and set it up to decrement DMA channel semaphore. So the current transaction
 * is the last data transfer.
 */
static void mxs_pcm_stop(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxs_runtime_data *prtd = runtime->private_data;
	struct mxs_dma_info dma_info;
	int desc;

	int periods_num = prtd->dma_totsize / prtd->dma_period;
	/* Freez DMA channel for a moment */
	mxs_dma_freeze(prtd->dma_ch);
	mxs_dma_get_info(prtd->dma_ch, &dma_info);

	desc = (dma_info.buf_addr - runtime->dma_addr) / prtd->dma_period;

	if (desc >= periods_num)
		desc = 0;
	else if (desc < 0)
		desc = 0;

	/* Set up the next descriptor to decrement DMA channel sempahore */
	prtd->dma_desc_array[(desc + 1)%periods_num]->cmd.cmd.bits.bytes = 0;
	prtd->dma_desc_array[(desc + 1)%periods_num]->cmd.cmd.bits.pio_words = \
		0;
	prtd->dma_desc_array[(desc + 1)%periods_num]->cmd.cmd.bits.dec_sem = 1;
	prtd->dma_desc_array[(desc + 1)%periods_num]->cmd.cmd.bits.irq = 0;
	prtd->dma_desc_array[(desc + 1)%periods_num]->cmd.cmd.bits.command = \
		NO_DMA_XFER;

	mxs_dma_unfreeze(prtd->dma_ch);

	mxs_dma_disable(prtd->dma_ch);
}
Esempio n. 2
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:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		mxs_dma_unfreeze(prtd->dma_ch);
		break;

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

	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}