[RK3288][Android6.0] ALSA的DMA buffer读写位置更新
来源:互联网 发布:如何自学软件编程 编辑:程序博客网 时间:2024/06/05 08:58
Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
刚开始我以为走的是下面的通路一,后来调试发现根本没更新,而是在后面提到的通路二中更新了,不过通路一也提一下吧!
通路一:
以录音为例:
snd_pcm_lib_read1 -> pcm_lib.csnd_pcm_update_hw_ptr ->
snd_pcm_update_hw_ptr0 -> pcm_lib.c
substream->ops->pointer -> //这个函数指针很关键! 初始化时在soc_new_pcm()中注册
soc_pcm_pointer -> soc-pcm.c
platform->driver->ops->pointer -> //snd_dmaengine_pcm_register()中注册dmaengine_no_residue_pcm_platform
snd_dmaengine_pcm_pointer_no_residue
static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, unsigned int in_interrupt){......pos = substream->ops->pointer(substream);......}snd_dmaengine_pcm_pointer_no_residue():
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream){ //pl330.c里注册 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); //可是rk在开头做了#undef CONFIG_ARCH_ROCKCHIP,所以这里不会跑到了 //也就是说通路一是不会更新pos了#ifdef CONFIG_ARCH_ROCKCHIP dma_addr_t src, dst; //pl330_probe()中注册,对应pl330_dma_getposition prtd->dma_chan->device->dma_getposition(prtd->dma_chan, &src, &dst); //dma_addr为申请dma buffer物理地址,相减之后得到当前相对 //物理地址的偏移,也就是当前播放和录音的位置了。 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) prtd->pos = dst - substream->runtime->dma_addr; else prtd->pos = src - substream->runtime->dma_addr;#endif //转成frame返回 return bytes_to_frames(substream->runtime, prtd->pos);}
通路二:
那么pos,是在哪里更新的呢?其实它是在回调函数中dmaengine_pcm_dma_complete()中完成,dma中断函数最终会调用更新它。
pl330_irq_handler -> pl330.c
pl330_update ->
_callback ->
r->xfer_cb ->
dma_pl330_rqcb ->
tasklet_schedule ->
pl330_tasklet ->
handle_cyclic_desc_list ->
callback ->
dmaengine_pcm_dma_complete ->
snd_pcm_period_elapsed ->
snd_pcm_update_hw_ptr0
static void dmaengine_pcm_dma_complete(void *arg){ struct snd_pcm_substream *substream = arg; struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);...... //以peroid_size为单位增加偏移 prtd->pos += snd_pcm_lib_period_bytes(substream); //当到达buffer_size后,会被重置 if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) prtd->pos = 0; snd_pcm_period_elapsed(substream);}
snd_pcm_lib_period_bytes():
static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substream){ struct snd_pcm_runtime *runtime = substream->runtime; //每次其实就是加上一个peroid_size return frames_to_bytes(runtime, runtime->period_size);}snd_pcm_lib_buffer_bytes():
static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substream){ struct snd_pcm_runtime *runtime = substream->runtime; //获取buffer_size大小的frame return frames_to_bytes(runtime, runtime->buffer_size);}
- [RK3288][Android6.0] ALSA的DMA buffer读写位置更新
- [RK3288][Android6.0] ALSA的buffer指针更新(hw_ptr)
- [RK3288][Android6.0] ALSA中的DMA buffer分配
- [RK3288][Android6.0] Audio的DMA调用实例流程
- [RK3288][Android6.0] WiFi之NetworkAgent对评分的更新
- RK3288][Android6.0] ALSA dapm框架中的widget/path/route
- [RK3288][Android6.0] 调试笔记 --- pmu(rk818)寄存器读写
- [RK3288][Android6.0] WiFi之网络时间定期同步更新
- [RK3288][Android6.0] AUDIO_BECOMING_NOISY作用
- [RK3288][Android6.0] USB UVC Camera 功能支持的添加
- [RK3288][Android6.0] 调试笔记 --- 普通串口的添加
- [RK3288][Android6.0] 调试笔记 --- 调试串口的更换
- [RK3288][Android6.0] Audio的ASOC驱动及数据结构
- [RK3288][Android6.0] Audio的frame/period_size/bps_rate
- [RK3288][Android6.0] 调试笔记 --- 隐藏系统状态栏的方法
- [RK3288][Android6.0] Audio的音量设置流程小结
- [RK3288][Android6.0] Audio的音量计算过程小结
- [RK3288][Android6.0] MediaCodec的configure配置过程小结
- Java实现寻找链表的中间节点
- 服务器常用端口介绍
- 剑指Offer-8
- Python三大神器之pip的安装
- 【git系列之E】git的分支操作(查看分支、切换分支、新建分支和删除分支)
- [RK3288][Android6.0] ALSA的DMA buffer读写位置更新
- codevs 3342 绿色通道(二分+dp+优先队列or单调队列)好题
- hadoop streaming (shell执行 & combiner & 数据分割)
- javascript 位置,尺寸,溢出
- 使用Apache POI生成和解析Excel文件
- Nginx 配置部分详述
- 【OpenCV】邻域滤波:方框、高斯、中值、双边滤波
- 在servlet中使用jasperreport展示报表
- 【R语言可视化】R语言画爱心图