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; }
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; }
void tegra_dma_flush(struct tegra_dma_channel *ch) { tegra_dma_cancel(ch); }