Linux 中DMA 的使用方法:
注: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 PCMn");goto err_suspend;}
}
带着问题看代码,既然是用到DMA 那第一步肯定是要 dma_request_channel ,
问题1:ASOC 中何时调用了 dma_request_channel ?
snd_dmaengine_pcm_registerdmaengine_pcm_request_chan_offor (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;i++) {...chan = dma_request_slave_channel_reason(dev, name); // 这里面调用了dma_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 的用法还是遵循基本法则的。
本文发布于:2024-02-02 04:37:12,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170681984641400.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |