Linux声卡驱动(3)——DAPM
一、DAPM简介 DAPM是Dynamic Audio Power Management的缩写,直译过来就是动态音频电源管理的意思,DAPM是为了使基于linux的移动设备上的音频子系统,在任何时候都工作在最小功耗状态下。DAPM对用户空间的应用程序来说是透明的,所有与电源相关的开关都在ASoc core中完成。DAPM根据当前激活的音频流(playback/capture)和声卡中的mixer等的配置来决定那些音频控件的电源开关被打开或关闭。
1. kcontrol 定义控件使用的宏举例: SOC_SINGLE_EXT 像这样的后面带_EXT的可以指定自己的put和get成员回调函数而不是默认的。 这些宏中使用soc_mixer_control结构来描述mixer控件的寄存器信息,soc_enum结构来描述mux控件的寄存器信息。 用户空间对kcontrol的修改,最终都会调用到kcontrol的put回调函数。 2. widget 音频控件单元抽象为kcontrol,DAPM的基本单元是widget,使用snd_soc_dapm_widget结构表示,它是对kcontrol进一步的封装,是kcontrol和开关(有的是组件前面的Switch和组件组成一个widget,有的是后面的)的组合体。 一个widget用snd_soc_dapm_widget结构体来描述,通常,会根据音频硬件的组成,分别在声卡的codec驱动、platform驱动和machine驱动中定义一组widget,这些widget用数组进行组织,我们一般会使用dapm框架提供的大量的辅助宏来定义这些widget数组。 widget把kcontrol和动态电源管理进行了有机的结合,同时还具备音频路径的连结功能,一个widget可以与它相邻的widget有某种动态的连结关系。 widget所包含的kcontrol与普通的kcontrol有所不同,它们的定义方法与标准的kcontrol也有所不同。普通snd_kcontrol_new结构可以使用宏例如SOC_SINGLE("ALC Max Gain",WM8960_ALC1,4,7,0)进行初始化,而widget的snd_kcontrol_new结构使用SOC_DAPM_SINGLE("LINPUT2 Switch",WM8960_LINPATH,6,1,0)初始化,区别是初始化回调函数不同。 SoC动态音频电源管理,最多可以拥有4个电源域的宏来初始化snd_kcontrol_new结构 一个电源域对应一个dapm context,使用snd_soc_dapm_context结构表示。属于codec中的widget位于一个dapm context中;属于platform的widget位于一个dapm context中;属于整个声卡的widget位于一个dapm context中。 定义麦克风,耳机,扬声器,线路输入接口这几种widget,还可以定义一个dapm事件回调函数wevent,因为其是外接设备,提供回调用于事件通知。 /* platform domain */ 如果需要自定义这些widget的dapm事件处理回调函数,也可以使用下面这些带“_E”后缀的版本,eg: SND_SOC_DAPM_PGA_E,这类的宏可以指定event_flag用于表示对哪些事件感兴趣。 为了防止pop-pop声,需要用户程序关注各个widget上电和下电的顺序。各个widget的上下电次序表示在两个全局数组dapm_up_seq/dapm_down_seq 中。消pop音延时的时长导出到debugfs了,文件名为dapm_pop_time
dai widget和stream widget是通过stream name进行匹配的 用struct snd_soc_pcm_stream表示,Codec驱动中的struct snd_soc_dai_driver结构中动态指定playback/capture两个stream widget。 把dai widget和stream widget连接在一起,就是为了能把ASoc中的pcm处理部分和dapm进行关联,pcm的处理过程中,会通过发出stream event来通知dapm系统,重新扫描并调整音频路径上各个widget的电源状态。 因为dai widget和codec上的stream widget是相连的,所以,dai widget的激活状态改变,会沿着音频路径传递到路径上的所有widget,等dapm_power_widgets返回后,如果发出的是SND_SOC_DAPM_STREAM_START事件,路径上的所有widget会处于上电状态,保证音频数据流的顺利播放,如果发出的是SND_SOC_DAPM_STREAM_STOP事件,路径上的所有widget会处于下电状态,保证最小的功耗水平。 ? 3. route route用于指定两个widget之间的连接关系,使用snd_soc_dapm_route结构表示,通常,所有的路径信息会用一个snd_soc_dapm_route结构数组来定义。和widget一样,路径信息也分别存在与codec驱动,machine驱动和platform驱动中。 snd_soc_dapm_route在定义的时候若是两个widget之间是直连的,没有经过开关Switch,那么kcontrol字符串就初始化为NULL。 ? 4. path route注册后被解析成path,使用snd_soc_dapm_path结构表示。kcontrol和widget都可以通过静态定义。但是path只能通过route解析而来。 一个path表示一段连接,至少包含:source widget,跳线path,sink widget。在DAPM中,用snd_soc_dapm_route结构来描述这样一个连接关系。
dapm要给一个widget上电的其中一个前提条件是:这个widget位于一条完整的音频路径上,而一条完整的音频路径的两头,必须是输入/输出端,或者是一个外部音频设备,又或者是一个处于激活状态的音频流widget。分别用is_connected_output_ep()和is_connected_input_ep()得到该widget是否有同时连接到一个输入端和一个输出端,如果是,返回1来表示该widget需要上电。 在扫描dapm_dirty链表时,dapm使用两个链表来分别保存需要上电和需要下电的widget,扫描完毕后按照上电次序,统一对各个widget上电。 ? 三、参考 ALSA声卡驱动中的DAPM详解之一:kcontrol (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |