DAPM-3 damp的kcontrol注册过程
- 普通kcontrol
- DAMP kcontrol
- 第一步 codec驱动add widget
- 第二步 Mechine驱动add kcontrol
- damp的注册过程
普通kcontrol
定义:
static const struct snd_kcontrol_new wm8960_snd_controls[] = {
SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
0, 63, 0, adc_tlv),
Trace 普通的kcontrol是如何添加到内核中去的,其实在Linux Audio (4) DAPM-1 Kcontrol 中有分析过(uda1341为例),下面以wm8960为例:
wm8960_probe(struct snd_soc_codec *codec)
snd_soc_add_codec_controls(codec, wm8960_snd_controls, ARRAY_SIZE(wm8960_snd_controls));
snd_soc_add_controls(card, codec->dev, controls, num_controls, codec->name_prefix, codec);
snd_ctl_add(card, snd_soc_cnew(control, data, control->name, prefix));
list_add_tail(&kcontrol->list, &card->controls);
// snd_soc_cnew() 将snd_kcontrol_new转化为kcontrol
将数组中的每个snd_kcontrol_new
转化为kcontrol
并且挂到card->controls
链表中。
DAMP kcontrol
以Left Boost Mixer
为例,该widget包含一个Mixer和三个kcontrol;而Muxer则只包含有一个kcontrol;
-
第一步
调用snd_soc_dapm_new_controls
把widget放入dapm->card->widgets
链表中 -
第二步
在注册machine驱动时,导致如下调用:
soc_probe_dai_link --> soc_post_component_init --> snd_soc_dapm_new_widgets在 snd_soc_dapm_new_widgets 中:
- 对于每一个widget,设置power_check函数(判断是否应该上电)
- 对于mixer widget,取出其中的kcontrol_new构造出snd_kcontrol, 放入card->controls链表
- 对于mixer widget,只有一个kcontrol_new,构造出snd_kcontrol, 放入card->controls链表
第一步 codec驱动add widget
将Mixer widget放入声卡链表中:
wm8960_probe(struct snd_soc_codec *codec)
wm8960_add_widgets(codec);
snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets,ARRAY_SIZE(wm8960_dapm_widgets));
snd_soc_dapm_new_control(dapm, widget);
list_add(&w->list, &dapm->card->widgets); //添加到声卡中的widgets链表中
snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
snd_soc_dapm_add_route(dapm, route); // for (i = 0; i < num; i++) {
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
第二步 Mechine驱动add kcontrol
三个kcontrol的注册过程
snd_smdk_probe(struct platform_device *pdev) // Mechine驱动的probe()函数
snd_soc_register_card(struct snd_soc_card *card)
snd_soc_instantiate_card(struct snd_soc_card *card)
soc_probe_dai_link()
soc_post_component_init(card, codec, num, 0);
snd_soc_dapm_new_widgets(&codec->dapm); //Make sure all DAPM widgets are instantiated
对于Mixer 和 Muxer有不同的处理
- Mixer
snd_soc_dapm_new_widgets(&codec->dapm); //Make sure all DAPM widgets are instantiated
dapm_new_mixer(w); //create new dapm mixer control
for (i = 0; i < w->num_kcontrols; i++) {
path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],wlist, path->long_name,prefix);
snd_ctl_add(card, path->kcontrol);
list_add_tail(&kcontrol->list, &card->controls);
path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],wlist, path->long_name,prefix);
创建kcontrol的命名规则是:
add dapm control with long name for dapm_mixer this is the concatenation of the mixer and kcontrol name for dapm_mixer_named_ctl this is simply the kcontrol name.
- Muxer
snd_soc_dapm_new_widgets(&codec->dapm); //Make sure all DAPM widgets are instantiated
dapm_new_mux(struct snd_soc_dapm_widget *w)
kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist,name + prefix_len, prefix);
snd_ctl_add(card, kcontrol);
list_add_tail(&kcontrol->list, &card->controls);
list_for_each_entry(path, &w->sources, list_sink)
path->kcontrol = kcontrol;
创建kcontrol的命名规则是:
The control will get a prefix from the control creation process but we’re also using the same prefix for widgets so cut the prefix off the front of the widget name.