DMA在ASOC声卡驱动中的使用

Linux 中DMA 的使用方法:

  1. dma_request_channel 申请一个chan
  2. tx = dma_prep_xxxx 准备,tx结构体
  3. tx->callback = tx_callback; 设置回调
  4. dma_cookie = dmaengine_submit(tx); 提交
  5. dma_async_issue_pending(chan); 启动硬件开始传输

注:dmaengine_slave_config 接口有时也要调用

下面看一下DMS 在ASOC 代码中的使用。
从I2S 驱动看起,因为ASOC 中主要是用到 I2S 接口来传输数据,DMA 是内存与 I2S 交换数据的工具。

static int sun4i_i2s_probe(struct platform_device *pdev)
{
	...
	/* 设置物理地址*/
	i2s->playback_dma_data.addr = res->start +
					i2s->variant->reg_offset_txdata;
	i2s->playback_dma_data.maxburst = 8;

	i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
	i2s->capture_dma_data.maxburst = 8;
	
	/*注册PCM*/
	ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
	if (ret) {
		dev_err(&pdev->dev, "Could not register PCM\n");
		goto err_suspend;
	}
}

带着问题看代码,既然是用到DMA 那第一步肯定是要 dma_request_channel ,
问题1:ASOC 中何时调用了 dma_request_channel ?

snd_dmaengine_pcm_register
  dmaengine_pcm_request_chan_of
    for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
	     i++) {
		...
		chan = dma_request_slave_channel_reason(dev, name);   // 这里面调用了dma_request_chan
		...
		pcm->chan[i] = chan;
		...
	}
#define dma_request_slave_channel_reason(dev, name) dma_request_chan(dev, name)
struct dma_chan *dma_request_chan(struct device *dev, const char *name)
{
	struct dma_device *d, *_d;
	struct dma_chan *chan = NULL;

	/* If device-tree is present get slave info from here */
	if (dev->of_node)
		chan = of_dma_request_slave_channel(dev->of_node, name);   //这里往下就稍复杂了,先不跟吧,总之chan 在这就request 到手了
	
	if (chan) {
		/* Valid channel found or requester need to be deferred */
		if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
			return chan;
	}
	...

问题2:dma_prep_xxxx 什么地方调用?
问题3:dmaengine_submit 什么地方调用?

static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
{
	...
	if (!substream->runtime->no_period_wakeup)
		flags |= DMA_PREP_INTERRUPT;

	prtd->pos = 0;
	desc = dmaengine_prep_dma_cyclic(chan,
		substream->runtime->dma_addr,
		snd_pcm_lib_buffer_bytes(substream),
		snd_pcm_lib_period_bytes(substream), direction, flags);
	
	desc->callback = dmaengine_pcm_dma_complete;
	desc->callback_param = substream;
	prtd->cookie = dmaengine_submit(desc);

	return 0;
}

问题4:dma_async_issue_pending 在哪调用?

int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	...	
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		ret = dmaengine_pcm_prepare_and_submit(substream);
		if (ret)
			return ret;
		dma_async_issue_pending(prtd->dma_chan);  //在这里调用
		break;
	...
}

ASOC 框架虽然复杂,但DMA 的用法还是遵循基本法则的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值