Example #1
0
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct tegra_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct tegra_pcm_dma_params * dmap;
	unsigned long flags;
	int i;

	dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
	if (!dmap)
		return 0;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		prtd->dma_pos = 0;
		prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
		prtd->period_index = 0;
		prtd->dma_req_idx = 0;
		if (prtd->disable_intr) {
			prtd->dma_req_count = 1;
			prtd->dma_req[0].complete = NULL;
		} else if (!prtd->dma_req[0].complete) {
			prtd->dma_req[0].complete = dma_complete_callback;
			prtd->dma_req_count =
				(MAX_DMA_REQ_COUNT <= runtime->periods) ?
				MAX_DMA_REQ_COUNT : runtime->periods;
		}
		/* Fall-through */
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 1;
		spin_unlock_irqrestore(&prtd->lock, flags);
		for (i = 0; i < prtd->dma_req_count; i++)
			tegra_pcm_queue_dma(prtd);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 0;
		spin_unlock_irqrestore(&prtd->lock, flags);
		tegra_dma_cancel(prtd->dma_chan);
		for (i = 0; i < prtd->dma_req_count; i++) {
			if (prtd->dma_req[i].complete &&
				(prtd->dma_req[i].status ==
				 -TEGRA_DMA_REQ_ERROR_ABORTED))
				prtd->dma_req[i].complete(&prtd->dma_req[i]);
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Example #2
0
static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct tegra_runtime_data *prtd = runtime->private_data;
	unsigned long flags;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		prtd->dma_pos = 0;
		prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
		prtd->period_index = 0;
		prtd->dma_req_idx = 0;
		/* Fall-through */
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 1;
		spin_unlock_irqrestore(&prtd->lock, flags);
		tegra_pcm_queue_dma(prtd);
		tegra_pcm_queue_dma(prtd);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 0;
		spin_unlock_irqrestore(&prtd->lock, flags);
		tegra_dma_cancel(prtd->dma_chan);
		if (prtd->dma_req[0].status == -TEGRA_DMA_REQ_ERROR_ABORTED)
			prtd->dma_req[0].complete(&prtd->dma_req[0]);
		if (prtd->dma_req[1].status == -TEGRA_DMA_REQ_ERROR_ABORTED)
			prtd->dma_req[1].complete(&prtd->dma_req[1]);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Example #3
0
void tegra_dma_flush(struct tegra_dma_channel *ch)
{
	tegra_dma_cancel(ch);
}