struct snd_soc_dapm_path
概要
struct snd_soc_dapm_path结构体用于连接两个widgets,生成path实例的入口函数是snd_soc_dapm_add_path()。
字段解释
struct snd_soc_dapm_path {
const char *name;
/* source (input) and sink (output) widgets */
struct snd_soc_dapm_widget *source; // 指向源部件
struct snd_soc_dapm_widget *sink; // 指向目的部件
/* status */
u32 connect:1; /* source and sink widgets are connected */
u32 walked:1; /* path has been walked */
u32 walking:1; /* path is in the process of being walked */
u32 weak:1; /* path ignored for power management */
struct list_head list_source; // 链表元素,挂在wsource->sinks
struct list_head list_sink; // 链表元素,挂在wsink->sources
struct list_head list_kcontrol; // 链表元素,挂在struct snd_kcontrol的字段(struct dapm_kcontrol_data)private_data->paths
struct list_head list; // 链表元素,挂在struct snd_soc_card paths字段
};
path实例connect状态
path数据结构里connect字段保存path实例的连接状态,除了用户态通过amix kcontrol设置相应path实例connect状态外,在snd_soc_dapm_add_path()函数里有以下情况可以设置path实例的connect状态:
- 当源和目的部件之间的control为NULL时,path->connect = 1
- 当目的部件是下面类型时,path->connect = 1
- 当目的部件是下面类型时,path->connect = 0
- 当目的部件是MUX类型时,函数入口dapm_connect_mux。读取寄存器值,把寄存器值相应的kcontrol所在的path设置为 path->connect=1,mux部件其它path设置为0。
- 当目的部件是下面类型时,入口函数是dapm_connect_mixer。如果dapm kcontrol寄存器是 SND_SOC_NOPM,则 path->connect=0。否则 见下面代码:
dapm_connect_mux()函数解析
static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
struct snd_soc_dapm_path *path, const char *control_name,
const struct snd_kcontrol_new *kcontrol)
{
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, item;
int i;
if (e->reg != SND_SOC_NOPM) {
// 读取寄存器值
soc_dapm_read(dapm, e->reg, &val);
val = (val >> e->shift_l) & e->mask;
// 如果soc_enum的values字段是NULL,那寄存器值就是数组index。
// 如果texts字符串数组index能够反应寄存器值,那就不需要定义values字段,如果没有这种规律,就定义values寄存器值数组
item = snd_soc_enum_val_to_item(e, val);
} else {
/* since a virtual mux has no backing registers to
* decide which path to connect, it will try to match
* with the first enumeration. This is to ensure
* that the default mux choice (the first) will be
* correctly powered up during initialization.
*/
// 默认texts[0]所在的path实例path->connect = 1;,其它path->connect = 0.
item = 0;
}
for (i = 0; i < e->items; i++) {
if (!(strcmp(control_name, e->texts[i]))) {
// MUX类型widget在路由表作为目的部件时,其control名称就是texts数组定义的字符串
// 源和目的部件之间的control在字符串数组texts找到,说明path实例合法
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &dest->sources);
list_add(&path->list_source, &src->sinks);
path->name = (char*)e->texts[i];
if (i == item)
path->connect = 1; // 寄存器值和control匹配
else
path->connect = 0; // 寄存器值和control 不匹配
return 0;
}
}
return -ENODEV;
}
amix kcontrol设置path connect状态
amix kcontrol PUT回调函数有:snd_soc_dapm_put_volsw 和 snd_soc_dapm_put_enum_double。
snd_soc_dapm_put_volsw
-->soc_dapm_mixer_update_power(card, kcontrol, connect); // 用户态传下来非0值 connect为 1,传下来0 connect为0。
-->把kcontrol在路由表里相关的所有path实例设置为 connect状态
-->dapm_power_widgets // 触发DAPM机制
snd_soc_dapm_put_enum_double
soc_dapm_mux_update_power(card, kcontrol, item[0], e); // 用户态给mux kontrol设置字符串,alsa lib库会把字符串转化为struct soc_enum里字符串数组texts的index,item[0]就是index。
-->循环遍历kcontrol所有的path实例,如果path->name等于 texts[index],则path->connect = 1;其它path实例设置为path->connect = 0。
-->dapm_power_widgets // 触发DAPM机制