linux alsa笔记 widget 7-12

来源:互联网 发布:软件参数 编辑:程序博客网 时间:2024/06/06 18:48

1.
ASoc中对Codec的数据抽象 描述Codec的最主要的几个数据结构分别是:snd_soc_codec、snd_soc_codec_driver、snd_soc_dai、snd_soc_dai_driver、其中snd_soc_dai和snd_soc_dai_driver在ASoc的Platform驱动中也会使用到,Platform和Codec的DAI通过snd_soc_dai_link结构,在Machine驱动中进行绑定连接。下面我们几个结构体的定义。
2.各个widget之间是如何建立连接关系,形成一条完整的音频路径
创建widget:
SND_SOC_DAPM_NEW_CONTROLS
实际上,这个函数只是创建WIDGET的第一步,它为每个WIDGET分配内存,初始化必要的字段,然后把这些WIDGET挂在代表声卡的SND_SOC_CARD的WIDGETS链表字段中。要使WIDGET之间具备连接能力,我们还需要第二个函数:
SND_SOC_DAPM_NEW_WIDGETS
这个函数会根据WIDGET的信息,创建WIDGET所需要的DAPM KCONTROL,这些DAPM KCONTOL的状态变化,代表着音频路径的变化,从而影响着各个WIDGET的电源状态。看到函数的名称可能会迷惑一下,实际上,SND_SOC_DAPM_NEW_CONTROLS的作用更多地是创建WIDGET,而SND_SOC_DAPM_NEW_WIDGET的作用则更多地是创建WIDGET所包含的KCONTROL
创建widget:snd_soc_dapm_new_controls

int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,          const struct snd_soc_dapm_widget *widget,          int num) 

snd_soc_dapm_widget数组,snd_soc_dapm_new_control是为该widget重新分配内存,并把模板的内容拷贝过来

static struct snd_soc_dapm_widget *  snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,                           const struct snd_soc_dapm_widget *widget)  

由dapm_cnew_widget完成内存申请和拷贝模板的动作。接下来,根据widget的类型做不同的处理

 switch (w->id) {          case snd_soc_dapm_regulator_supply:  

对于snd_soc_dapm_regulator_supply类型的widget,根据widget的名称获取对应的regulator结构,对于snd_soc_dapm_clock_supply类型的widget,根据widget的名称,获取对应的clock结构。接下来,根据需要,在widget的名称前加入必要的前缀:

if (dapm->codec && dapm->codec->name_prefix)          w->name = kasprintf(GFP_KERNEL, "%s %s",                  dapm->codec->name_prefix, widget->name);  else          w->name = kasprintf(GFP_KERNEL, "%s", widget->name); 

然后,为不同类型的widget设置合适的power_check电源状态回调函数,widget类型和对应的power_check回调函数
widget的power_check回调函数
widget类型 power_check回调函数
mixer类:
snd_soc_dapm_switch
snd_soc_dapm_mixer
snd_soc_dapm_mixer_named_ctl dapm_generic_check_power
mux类:
snd_soc_dapm_mux
snd_soc_dapm_mux
snd_soc_dapm_mux dapm_generic_check_power
snd_soc_dapm_dai_out dapm_adc_check_power
snd_soc_dapm_dai_in dapm_dac_check_power
端点类:
snd_soc_dapm_adc
snd_soc_dapm_aif_out
snd_soc_dapm_dac
snd_soc_dapm_aif_in
snd_soc_dapm_pga
snd_soc_dapm_out_drv
snd_soc_dapm_input
snd_soc_dapm_output
snd_soc_dapm_micbias
snd_soc_dapm_spk
snd_soc_dapm_hp
snd_soc_dapm_mic
snd_soc_dapm_line
snd_soc_dapm_dai_link dapm_generic_check_power
电源/时钟/影子widget:
snd_soc_dapm_supply
snd_soc_dapm_regulator_supply
snd_soc_dapm_clock_supply
snd_soc_dapm_kcontrol dapm_supply_check_power
其它类型 dapm_always_on_check_power

当音频路径发生变化时,power_check回调会被调用,用于检查该widget的电源状态是否需要更新。power_check设置完成后,需要设置widget所属的codec、platform和dapm context,几个用于音频路径的链表也需要初始化,然后,把该widget加入到声卡的widgets链表中:

w->dapm = dapm;  w->codec = dapm->codec;  w->platform = dapm->platform;  INIT_LIST_HEAD(&w->sources);  INIT_LIST_HEAD(&w->sinks);  INIT_LIST_HEAD(&w->list);  INIT_LIST_HEAD(&w->dirty);  list_add(&w->list, &dapm->card->widgets); 

几个链表的作用如下:
sources 用于链接所有连接到该widget输入端的snd_soc_path结构
sinks 用于链接所有连接到该widget输出端的snd_soc_path结构
list 用于链接到声卡的widgets链表
dirty 用于链接到声卡的dapm_dirty链表
最后,把widget设置为connect状态:

/* machine layer set ups unconnected pins and insertions */  w->connected = 1;  return w;  

connected字段代表着引脚的连接状态,目前,只有以下这些widget使用connected字段:
snd_soc_dapm_output
snd_soc_dapm_input
snd_soc_dapm_hp
snd_soc_dapm_spk
snd_soc_dapm_line
snd_soc_dapm_vmid
snd_soc_dapm_mic
snd_soc_dapm_siggen

驱动程序可以使用以下这些api来设置引脚的连接状态:
snd_soc_dapm_enable_pin
snd_soc_dapm_force_enable_pin
snd_soc_dapm_disable_pin
snd_soc_dapm_nc_pin

到此,widget已经被正确地创建并初始化,而且被挂在声卡的widgets链表中,以后我们就可以通过声卡的widgets链表来遍历所有的widget,再次强调一下snd_soc_dapm_new_controls函数所完成的主要功能:
为widget分配内存,并拷贝参数中传入的在驱动中定义好的模板
设置power_check回调函数
把widget挂在声卡的widgets链表中

原创粉丝点击