DAPM-widget

 widget控件

所谓widget,其实可以理解为是kcontrol的进一步升级和封装,它同样是指音频系统中的某个部件,比如mixer,mux,输入输出引脚,电源供应器等等,甚至,我们可以定义虚拟的widget,例如playback stream widget。widget把kcontrol和动态电源管理进行了有机的结合,同时还具备音频路径的连结功能,一个widget可以与它相邻的widget有某种动态的连结关系。在DAPM框架中,widget用结构体snd_soc_dapm_widget来描述(部分):

struct snd_soc_dapm_widget {
        enum snd_soc_dapm_type id;
        const char *name;               /* widget name */
 
        ......
        /* dapm control */
        int reg;                        /* negative reg = no direct dapm */
        unsigned char shift;            /* bits to shift */
        unsigned int value;             /* widget current value */
        unsigned int mask;              /* non-shifted mask */
        ......
 
        int (*power_check)(struct snd_soc_dapm_widget *w);
 
        int (*event)(struct snd_soc_dapm_widget*, struct snd_kcontrol *, int);
 
        /* kcontrols that relate to this widget */
        int num_kcontrols;
        const struct snd_kcontrol_new *kcontrol_news;
        struct snd_kcontrol **kcontrols;
 
        /* widget input and outputs */
        struct list_head sources;
        struct list_head sinks;
        ......
};

下面介绍各成员:

.id:该widget的类型值,比如snd_soc_dapm_output,snd_soc_dapm_mixer等等
.name:该widget的名字
.sname:代表该widget所在stream的名字,比如对于snd_soc_dapm_dai_in类型的widget,会使用该字段
.codec .platform:指向该widget所属的codec和platform
.list:所有注册到系统中的widget都会通过该list,链接到代表声卡的snd_soc_card结构的widgets链表头字段中
.dapm:snd_soc_dapm_context结构指针,ASoC把系统划分为多个dapm域,每个widget属于某个dapm域,同一个域代表着同样的偏置电压供电策略比如,同一个codec中的widget通常位于同一个dapm域,而平台上的widget可能又会位于另外一个dapm域中
.priv:有些widget可能需要一些专有的数据,可以使用该字段来保存,像snd_soc_dapm_dai_in类型的widget,会使用该字段来记住与之相关联的snd_soc_dai结构指针
.regulator:对于snd_soc_dapm_regulator_supply类型的widget,该字段指向与之相关的regulator结构指针
.params:目前对于snd_soc_dapm_dai_link类型的widget,指向该dai的配置信息的 snd_soc_pcm_stream结构
.reg .shift .mask:这3个字段用来控制该widget的电源状态,分别对应控制信息所在的寄存器地址,位移值和屏蔽值
.value .on_val .off_val:电源状态的当前值,开启时和关闭时所对应的值
.power .invert:用于指示该widget当前是否处于上电状态,invert则用于表明power字段是否需要逻辑反转
.active .connected:分别表示该widget是否处于激活状态和连接状态,当和相邻的widget有连接关系时,connected位会被置1,否则置0
.new:我们定义好的widget(snd_soc_dapm_widget结构),在注册到声卡中时需要进行实例化,该字段用来表示该widget是否已经被实例化
.ext:表示该widget当前是否有外部连接,比如连接mic,耳机,喇叭等等
.force:该位被设置后,将会不管widget当前的状态,强制更新至新的电源状态
.ignore_suspend new_power .power_checked:这些电源管理相关的字段
.subseq:该widget目前在上电或下电队列中的排序编号,为了防止在上下电的过程中出现pop-pop声,DAPM会给每个widget分配合理的上下电顺序
.power_check:用于检查该widget是否应该上电或下电的回调函数指针
.event_flags:该字段是一个位或字段,每个位代表该widget会关注某个DAPM事件通知。只有被关注的通知事件会被发送到widget的事件处理回调函数中
.event:DAPM事件处理回调函数指针
.num_kcontrols .kcontrol_news .kcontrols:这3个字段用来描述与该widget所包含的kcontrol控件,例如一个mixer控件或者是一个mux控件
.sources sinks:两个链表字段,两个widget如果有连接关系,会通过一个snd_soc_dapm_path结构进行连接,sources链表用于链接所有的输入path,sinks链表用于链接所有的输出path
.power_list:每次更新整个dapm的电源状态时,会根据一定的算法扫描所有的widget,然后把需要变更电源状态的widget利用该字段链接到一个上电或下电的链表中,扫描完毕后,dapm系统会遍历这两个链表执行相应的上电或下电操作
.dirty:链表字段,widget的状态变更后,dapm系统会利用该字段,把该widget加入到一个dirty链表中,稍后会对dirty链表进行扫描,以执行整个路径的更新
.inputs:该widget的所有有效路径中,连接到输入端的路径数量
.outputs:该widget的所有有效路径中,连接到输出端的路径数量
.clk:对于snd_soc_dapm_clock_supply类型的widget,指向相关联的clk结构体(指针)

widget的种类

在DAPM框架中,把各种不同的widget划分为不同的种类,可选的种类都定义在一个枚举中:

/* dapm widget types */
enum snd_soc_dapm_type {......}

下面我们逐个解释一下这些widget的种类:

snd_soc_dapm_input 该widget对应一个输入引脚。
snd_soc_dapm_output 该widget对应一个输出引脚。
snd_soc_dapm_mux 该widget对应一个mux控件。
snd_soc_dapm_virt_mux 该widget对应一个虚拟的mux控件。
snd_soc_dapm_value_mux 该widget对应一个value类型的mux控件。
snd_soc_dapm_mixer 该widget对应一个mixer控件。
snd_soc_dapm_mixer_named_ctl 该widget对应一个mixer控件,但是对应的kcontrol的名字不会加入widget的名字作为前缀。
snd_soc_dapm_pga 该widget对应一个pga控件(可编程增益控件)。
snd_soc_dapm_out_drv 该widget对应一个输出驱动控件
snd_soc_dapm_adc 该widget对应一个ADC
snd_soc_dapm_dac 该widget对应一个DAC
snd_soc_dapm_micbias 该widget对应一个麦克风偏置电压控件
snd_soc_dapm_mic 该widget对应一个麦克风
snd_soc_dapm_hp 该widget对应一个耳机
snd_soc_dapm_spk 该widget对应一个扬声器
snd_soc_dapm_line 该widget对应一个线路输入
snd_soc_dapm_switch 该widget对应一个模拟开关
snd_soc_dapm_vmid 该widget对应一个codec的vmid偏置电压
snd_soc_dapm_pre machine级别的专用widget,会先于其它widget执行检查操作 snd_soc_dapm_post machine级别的专用widget,会后于其它widget执行检查操作 snd_soc_dapm_supply 对应一个电源或是时钟源
snd_soc_dapm_regulator_supply 对应一个外部regulator稳压器
snd_soc_dapm_clock_supply 对应一个外部时钟源
snd_soc_dapm_aif_in 对应一个数字音频输入接口,比如I2S接口的输入端 snd_soc_dapm_aif_out 对应一个数字音频输出接口,比如I2S接口的输出端 snd_soc_dapm_siggen 对应一个信号发生器
snd_soc_dapm_dai_in 对应一个platform或codec域的输入DAI结构
snd_soc_dapm_dai_out 对应一个platform或codec域的输出DAI结构
snd_soc_dapm_dai_link 用于链接一对输入/输出DAI结构

widget的定义

和普通的kcontrol一样,DAPM框架为我们提供了大量的辅助宏用来定义各种各样的widget控件,这些宏定义根据widget的类型,按照它们的电源所在的域,被分为了几个域,他们分别是:

codec域 比如VREF和VMID等提供参考电压的widget,这些widget通常在codec的probe/remove回调中进行控制,当然,在工作中如果没有音频流时,也可以适当地进行控制它们的开启与关闭。

platform域 位于该域上的widget通常是针对平台或板子的一些需要物理连接的输入/输出接口,例如耳机、扬声器、麦克风,因为这些接口在每块板子上都可能不一样,所以通常它们是在machine驱动中进行定义和控制,并且也可以由用户空间的应用程序通过某种方式来控制它们的打开和关闭。

音频路径域 一般是指codec内部的mixer、mux等控制音频路径的widget,这些widget可以根据用户空间的设定连接关系,自动设定他们的电源状态。

音频数据流域 是指那些需要处理音频数据流的widget,例如ADC、DAC等等。

举个例子

#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
         wcontrols, wncontrols)\
{       .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
        .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}

可以发现这个widget的reg和shift字段是需要赋值的,说明这个widget是有相应的电源控制寄存器的,DAPM框架在扫描和更新音频路径时,会利用这些寄存器来控制widget的电源状态,使得它们的供电状态是按需分配的,需要的时候(在有效的音频路径上)上电,不需要的时候(不再有效的音频路径上)下电。这些widget需要完成和之前介绍的mixer、mux等控件同样的功能,实际上,这是通过它们包含的kcontrol控件来完成的,这些kcontrol我们需要在定义widget前先定义好,然后通过wcontrols和num_kcontrols参数传递给这些辅助定义宏。 如果需要自定义这些widget的dapm事件处理回调函数,也可以使用下面这些带“_E”后缀的版本:

  • SND_SOC_DAPM_PGA_E

  • SND_SOC_DAPM_OUT_DRV_E

  • SND_SOC_DAPM_MIXER_E

  • SND_SOC_DAPM_MIXER_NAMED_CTL_E

  • SND_SOC_DAPM_SWITCH_E

  • SND_SOC_DAPM_MUX_E

  • SND_SOC_DAPM_VIRT_MUX_E

还有另外三种widget没有提供显式的定义方法,它们的种类id分别是:

  • snd_soc_dapm_dai_in

  • snd_soc_dapm_dai_out

  • snd_soc_dapm_dai_link

每个codec有多个dai,而cpu(通常就是指某个soc cpu芯片)也会有多个dai,dai注册时,dapm系统会为每个dai创建一个snd_soc_dapm_dai_in或snd_soc_dapm_dai_out类型的widget,通常,这两种widget会和codec中具有相同的stream name的widget进行连接。另外一种情况,当系统中具有多个音频处理器(比如多个codec)时,他们之间可能会通过某两个dai进行连接,当machine驱动确认有这种配置时(通过判断dai_links结构中的param字段),会为他们建立一个dai link把他们绑定在一起,因为有连接关系,两个音频处理器之间的widget的电源状态就可以互相传递。

猜你喜欢

转载自blog.csdn.net/hhx123456798/article/details/123302990