Esempio n. 1
0
static int tegra_set_avp_device(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
	struct snd_soc_card *card = data->card;
	struct snd_soc_pcm_runtime *rtd;
	struct snd_pcm_substream *substream;
	struct tegra_runtime_data *prtd;
	int id, old_id = data->avp_device_id;

	id = ucontrol->value.integer.value[0];
	if ((id >= card->num_rtd) || (id < 0))
		id = -1;

	if (old_id >= 0) {
		rtd = &card->rtd[old_id];
		substream =
			rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
		if (substream && substream->runtime) {
			prtd = (struct tegra_runtime_data *)
				snd_dmaengine_pcm_get_data(substream);
			if (!prtd)
				return -EINVAL;
			if (prtd->running)
				return -EBUSY;
			prtd->disable_intr = false;
		}
	}

	if (id >= 0) {
		rtd = &card->rtd[id];
		substream =
			rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
		if (substream && substream->runtime) {
			prtd = (struct tegra_runtime_data *)
				snd_dmaengine_pcm_get_data(substream);
			if (!prtd)
				return -EINVAL;
			if (prtd->running)
				return -EBUSY;
			prtd->disable_intr = true;
			if (data->avp_dma_addr || prtd->avp_dma_addr)
				prtd->avp_dma_addr = data->avp_dma_addr;
		}
	}
	data->avp_device_id = id;
	return 1;
}
Esempio n. 2
0
static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
	struct snd_soc_card *card = data->card;
	struct snd_soc_pcm_runtime *rtd;
	struct snd_pcm_substream *substream;
	struct tegra_runtime_data *prtd;

	if (data->avp_device_id < 0)
		return 0;

	rtd = &card->rtd[data->avp_device_id];
	substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;

	if (!substream || !substream->runtime)
		return 0;

	prtd = (struct tegra_runtime_data *)
		snd_dmaengine_pcm_get_data(substream);

	if (!prtd)
		return 0;

	ucontrol->value.integer.value[0] = 0;
	ucontrol->value.integer.value[0] = prtd->avp_dma_addr ?
					   (long)prtd->avp_dma_addr :
					   (long)substream->runtime->dma_addr;

	return 0;
}
Esempio n. 3
0
/**
 * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC
 *
 * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to
 * check if any overrun occured.
 */
static void atmel_pcm_dma_irq(u32 ssc_sr,
	struct snd_pcm_substream *substream)
{
	struct atmel_pcm_dma_params *prtd;

	prtd = snd_dmaengine_pcm_get_data(substream);

	if (ssc_sr & prtd->mask->ssc_error) {
		if (snd_pcm_running(substream))
			pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x)\n",
				substream->stream == SNDRV_PCM_STREAM_PLAYBACK
				? "underrun" : "overrun", prtd->name,
				ssc_sr);

		/* stop RX and capture: will be enabled again at restart */
		ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable);
		snd_pcm_stream_lock(substream);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(substream);

		/* now drain RHR and read status to remove xrun condition */
		ssc_readx(prtd->ssc->regs, SSC_RHR);
		ssc_readx(prtd->ssc->regs, SSC_SR);
	}
}
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct tegra_pcm_dma_params * dmap;
	struct tegra_runtime_data *prtd;

	if (rtd->dai_link->no_pcm)
		return 0;

	dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);


	prtd = (struct tegra_runtime_data *)
	snd_dmaengine_pcm_get_data(substream);

	if (!dmap)
		return 0;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		prtd->running = 1;
		if (prtd->disable_intr) {
			substream->runtime->dma_addr = prtd->avp_dma_addr;
			substream->runtime->no_period_wakeup = 1;
		} else {
			substream->runtime->no_period_wakeup = 0;
		}

		return snd_dmaengine_pcm_trigger(substream,
					SNDRV_PCM_TRIGGER_START);

	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		prtd->running = 0;

		return snd_dmaengine_pcm_trigger(substream,
					SNDRV_PCM_TRIGGER_STOP);
	default:
		return -EINVAL;
	}
	return 0;
}
Esempio n. 5
0
static int tegra_pcm_close(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct tegra_runtime_data *tegra_prtd;

	if (rtd->dai_link->no_pcm)
		return 0;

	tegra_prtd =
		(struct tegra_runtime_data *)snd_dmaengine_pcm_get_data(
						substream);
	kfree(tegra_prtd);

	snd_dmaengine_pcm_set_data(substream, NULL);
	snd_dmaengine_pcm_close_release_chan(substream);

	return 0;
}