文档详情

Linux ALSA声卡驱动原理分析 设备打开过程和数据流程.ppt

发布:2017-06-14约2.91万字共40页下载文档
文本预览下载声明
v. 数据写入流程图 hardward interrupt 流程图 kernel user aplay alsa-lib alsa-driver device-driver hardward interrupt snd_audiopci_interrupt() sctrl = ~ES_P1_INT_EN snd_pcm_period_elapsed() alsa-driver snd_pcm_period_elapsed() snd_pcm_update_hw_ptr_interrupt() substream-ops -pointer(substream) snd_ensoniq_playback1_pointer() inl(DAC1_SIZE) snd_pcm_update_hw_ptr_post() avail = runtime-control-avail_min wake_up(runtime-sleep) device-driver 左图上半部alsa-driver对应的是”数据写入流程图”的(4)(5)(6)(7)(8)(9)(10)(11)(12) 硬件会周期性的发生中断,触发snd_audiopci_interrupt()函数,snd_audiopci_interrupt()清楚硬件中断位后,调用snd_pcm_period_elapsed()函数进入alsa-driver的处理。snd_pcm_period_elapsed()回调snd_ensoniq_playback1_pointer()函数获取硬件为处理的数据size,并计算出硬件的读指针位置,再通过snd_pcm_update_hw_ptr_post()判断如果有效区(读写指针间的空闲区)大于设定的最小值,就调wake_up()唤醒runtime-sleep队列,也就唤醒了poll。使alsa-lib的写入进程继续执行。 主要函数位置: 1. snd_pcm_period_elapsed() ? linux-source-2.6.26/sound/core/ pcm_lib.c : 1464 2. snd_pcm_period_elapsed() ? linux-source-2.6.26/sound/core/ pcm_lib.c : 184 3. snd_pcm_period_elapsed() ? linux-source-2.6.26/sound/core/ pcm_lib.c : 161 四、设备打开过程和数据流程 唤醒runtime-sleep队列的进程 v. 数据写入流程图 alsa-lib snd_pcm_write_areas()流程图 kernel user aplay alsa-lib alsa-driver device-driver snd_pcm_mmap_write_areas() snd_pcm_mmap_begin() snd_pcm_areas_copy() 左图上半部alsa-driver对应的是”数据写入流程图”的(13)(14) snd_pcm_mmap_write_areas()函数循环写入数据,直到数据没有,首先将找到映射内存pcm-running_areas的地址,然后调用snd_pcm_areas_copy()进行数据转换,如采样率,分辨率等,如果源数据和硬件格式一致,就简单地通过memcpy拷贝数据,转换成硬件对应的数据后,调用snd_pcm_mmap_commit()将转换后的数据写入映射内存。写入由snd_pcm_dmix_mmap_commit()完成,在对数据进行混音(do_mix_areas)同时,写入映射内存。 do_mix_areas()是通过软件进行混音的,如上图,将sum_buffer的数据和源数据进行叠加后,写入sum_buffer,同时写入dst。dst就是 pcm-running_areas,也就是pci内存的用户层映射。至此,向硬件中写入的流程就全部完成了,硬件会从pci内存中读取出数据进行DA转换后播放出声音。 在这里,多个进程同时对sum_buffer进行写访问,是通过使用信号量函数semop()进行互斥访问的。 主要函数位置: 1. snd_pcm_mmap_areas() ? alsa-lib-1.0.16/src/pcm/pcm_local.h : 458 2. snd_pcm_area_copy() ? alsa-lib-1.0.16/src/pcm/pcm.c : 2527 3. snd_pcm_dmix_mmap_commit() ? a
显示全部
相似文档