Esempio n. 1
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;
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 1;
#if 0
		if( prtd->dma_chan ){
			prtd->pcm_timeout_tick = jiffies;
			del_timer(&prtd->pcm_timeout);
			prtd->pcm_timeout.function = pcm_timeout_func;
			prtd->pcm_timeout.expires = jiffies + msecs_to_jiffies((runtime->period_size/(runtime->rate/1000))*runtime->periods*2);
			prtd->pcm_timeout.data = (unsigned long)prtd;
			add_timer(&prtd->pcm_timeout);		
			prtd->callback_time = jiffies;
		}
#endif
		spin_unlock_irqrestore(&prtd->lock, flags);
		if( prtd->dma_chan ){
			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;
#if 0
		if( prtd->dma_chan ){
			del_timer(&prtd->pcm_timeout);
		}
#endif
		spin_unlock_irqrestore(&prtd->lock, flags);

		if( prtd->dma_chan ){
			tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
			tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Esempio n. 2
0
static void dma_complete_callback(struct tegra_dma_req *req)
{
	struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev;
	struct snd_pcm_substream *substream = prtd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;

	spin_lock(&prtd->lock);

	if (!prtd->running) {
		spin_unlock(&prtd->lock);
		return;
	}

	if (++prtd->period_index >= runtime->periods)
		prtd->period_index = 0;

	tegra_pcm_queue_dma(prtd);
	
#if 0
	prtd->pcm_timeout_tick = jiffies;
	del_timer(&prtd->pcm_timeout);
	prtd->pcm_timeout.function = pcm_timeout_func;
	prtd->pcm_timeout.expires = jiffies + msecs_to_jiffies((runtime->period_size/(runtime->rate/1000))*runtime->periods*2);
	prtd->pcm_timeout.data = (unsigned long)prtd;
	add_timer(&prtd->pcm_timeout);
// for error debuging.
	if( jiffies_to_msecs(jiffies - prtd->callback_time) > (runtime->period_size/(runtime->rate/1000))*2 )
		dev_err(substream->pcm->dev, "dma_complete_callback time error!!!\n");
	prtd->callback_time = jiffies;
#endif

	spin_unlock(&prtd->lock);

	snd_pcm_period_elapsed(substream);
}
Esempio n. 3
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;
}
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:
#ifdef CONFIG_HAS_WAKELOCK
	wake_lock(&prtd->tegra_wake_lock);
#endif
		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_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
		tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);

#ifdef CONFIG_HAS_WAKELOCK
		wake_unlock(&prtd->tegra_wake_lock);
#endif
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Esempio n. 5
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;
}
static void dma_complete_callback(struct tegra_dma_req *req)
{
	struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev;
	struct snd_pcm_substream *substream = prtd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;

	spin_lock(&prtd->lock);

	if (!prtd->running) {
		spin_unlock(&prtd->lock);
		return;
	}

	if (++prtd->period_index >= runtime->periods)
		prtd->period_index = 0;

	tegra_pcm_queue_dma(prtd);

	spin_unlock(&prtd->lock);

	snd_pcm_period_elapsed(substream);
}