Esempio n. 1
0
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct davinci_runtime_data *prtd = substream->runtime->private_data;

	davinci_pcm_period_reset(substream);
	if (prtd->ram_channel >= 0) {
		int ret = ping_pong_dma_setup(substream);
		if (ret < 0)
			return ret;

		edma_write_slot(prtd->ram_channel, &prtd->ram_params);
		edma_write_slot(prtd->asp_channel, &prtd->asp_params);

		print_buf_info(prtd->ram_channel, "ram_channel");
		print_buf_info(prtd->ram_link, "ram_link");
		print_buf_info(prtd->ram_link2, "ram_link2");
		print_buf_info(prtd->asp_channel, "asp_channel");
		print_buf_info(prtd->asp_link[0], "asp_link[0]");
		print_buf_info(prtd->asp_link[1], "asp_link[1]");

		/*
		 * There is a phase offset of 2 periods between the position
		 * used by dma setup and the position reported in the pointer
		 * function.
		 *
		 * The phase offset, when not using ping-pong buffers, is due to
		 * the two consecutive calls to davinci_pcm_enqueue_dma() below.
		 *
		 * Whereas here, with ping-pong buffers, the phase is due to
		 * there being an entire buffer transfer complete before the
		 * first dma completion event triggers davinci_pcm_dma_irq().
		 */
		davinci_pcm_period_elapsed(substream);
		davinci_pcm_period_elapsed(substream);

		return 0;
	}
	davinci_pcm_enqueue_dma(substream);
	davinci_pcm_period_elapsed(substream);

	/* Copy self-linked parameter RAM entry into master channel */
	edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
	edma_write_slot(prtd->asp_channel, &prtd->asp_params);
	davinci_pcm_enqueue_dma(substream);
	davinci_pcm_period_elapsed(substream);

	return 0;
}
Esempio n. 2
0
static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
{
	struct snd_pcm_substream *substream = data;
	struct davinci_runtime_data *prtd = substream->runtime->private_data;

	print_buf_info(prtd->ram_channel, "i ram_channel");
	pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);

	if (unlikely(ch_status != DMA_COMPLETE))
		return;

	if (snd_pcm_running(substream)) {
		if (prtd->ram_channel < 0) {
			/* No ping/pong must fix up link dma data*/
			spin_lock(&prtd->lock);
			davinci_pcm_enqueue_dma(substream);
			spin_unlock(&prtd->lock);
		}
		snd_pcm_period_elapsed(substream);
	}
}
Esempio n. 3
0
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct davinci_runtime_data *prtd = substream->runtime->private_data;

	if (prtd->ram_channel >= 0) {
		int ret = ping_pong_dma_setup(substream);
		if (ret < 0)
			return ret;

		edma_write_slot(prtd->ram_channel, &prtd->ram_params);
		edma_write_slot(prtd->asp_channel, &prtd->asp_params);

		print_buf_info(prtd->ram_channel, "ram_channel");
		print_buf_info(prtd->ram_link, "ram_link");
		print_buf_info(prtd->ram_link2, "ram_link2");
		print_buf_info(prtd->asp_channel, "asp_channel");
		print_buf_info(prtd->asp_link[0], "asp_link[0]");
		print_buf_info(prtd->asp_link[1], "asp_link[1]");

		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			/* copy 1st iram buffer */
			edma_start(prtd->ram_channel);
		}
		edma_start(prtd->asp_channel);
		return 0;
	}
	prtd->period = 0;
	davinci_pcm_enqueue_dma(substream);

	/* Copy self-linked parameter RAM entry into master channel */
	edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
	edma_write_slot(prtd->asp_channel, &prtd->asp_params);
	davinci_pcm_enqueue_dma(substream);
	edma_start(prtd->asp_channel);

	return 0;
}