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状态:

  1. 当源和目的部件之间的control为NULL时,path->connect = 1
  2. 当目的部件是下面类型时,path->connect = 1
  3. 当目的部件是下面类型时,path->connect = 0
  4. 当目的部件是MUX类型时,函数入口dapm_connect_mux。读取寄存器值,把寄存器值相应的kcontrol所在的path设置为 path->connect=1,mux部件其它path设置为0。
  5. 当目的部件是下面类型时,入口函数是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机制
posted @ 2020-11-17 22:38  bobfly1984  阅读(245)  评论(0编辑  收藏  举报