您当前的位置: 首页 >  linux
  • 5浏览

    0关注

    417博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

08.音频系统:第003课_Linux音频驱动程序:第007节_route_path添加过程分析

江南才尽,年少无知! 发布时间:2019-04-18 14:05:19 ,浏览量:5

该小节我们讲解route与path添加过程分析。会使用一些例子,把这个过程讲解清楚。

打开源码文件rt5651.c,根据之前的分析我们知道:

static const struct snd_soc_dapm_route rt5651_dapm_routes[] = {
	......
	{"IN1P", NULL, "LDO"},
	{"RECMIXL", "BST1 Switch", "BST1"},
	{"Stereo1 ADC L1 Mux", "DD MIX", "DD MIXL"},
	......
}
static struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
	.dapm_routes = rt5651_dapm_routes,
}
snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,rt5651_dai, ARRAY_SIZE(rt5651_dai));
	/*machin之后最终导致该函数被调用*/
	static int snd_soc_instantiate_card(struct snd_soc_card *card)
		soc_probe_link_components(card, i, order);
			soc_probe_component(card, component);
				snd_soc_dapm_add_routes(dapm, component->dapm_routes,component->num_dapm_routes);
					snd_soc_dapm_add_route(dapm, route);	

在继续分析snd_soc_dapm_add_route函数之前,我们先猜测一下。 大家肯定注意到了很多的snd_soc_dapm_route,都使用了NULL,如:

	{"IN1P", NULL, "LDO"},

如果不是为NULL的

	{"RECMIXR", "INR1 Switch", "INR1 VOL"},//MIX类型
	{"Stereo1 ADC L1 Mux", "DD MIX", "DD MIXL"},//MUX类型

实际只有两种类型,及MIX类型与MUX类型(从命名我们可以看出)。左边的为sink widget,中间为kcontrol(如果不为NULL),右边为soure widget。

其中,通过上小节的学习我们知道kcontrol分为3种: 1.sink,NULL,soure:其表示他们肯定是连接在一起的,由他们构造出来的path,其成员connect一直为1。 2.sink widget为mixer,如:

	{"RECMIXR", "INR1 Switch", "INR1 VOL"},
	{"RECMIXR", "BST3 Switch", "BST3"},
	{"RECMIXR", "BST2 Switch", "BST2"},
	{"RECMIXR", "BST1 Switch", "BST1"},//MIX类型

其描述如下 在这里插入图片描述 可以看到这四个ptch他们的source是不一样的,但是他们的sink是一样的,都为RECMIL。从上我们知道一共需要4个kcontrol,四个为通道选择的kcontrol,分别对应寄存器MXC的3,2,1,5,位。并且这些kcontrol还会对RECMXL的寄存器MX3B进行设定。他们共同组成一个mixer widger。

3.sink widget为为MUX,即如sink为mux widget类型:

在这里插入图片描述 其中MUX widget包含了MUX本身信息,以及一个snd_kcontrol,我们设置snd_kcontrol为不同的值时,其导通不同的ptch。

从上面我们总结出了3中route,那么他是怎么转换真path的呢?

情景分析

我们现在继续分析snd_soc_dapm_add_route(dapm, route);函数:

static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,const struct snd_soc_dapm_route *route)
	/*通过名字寻找card->widgets链表中的所有的widgets,如果名字相同,代表找到了对应的widgets*/
	list_for_each_entry(w, &dapm->card->widgets, list) {
		widgets[SND_SOC_DAPM_DIR_IN] = wsource;
		widgets[SND_SOC_DAPM_DIR_OUT] = wsink;
		/*如果control=null*/
		if (control == NULL) {
			/*设置connect为1*/
			path->connect = 1;		

我们先做个简单的总结:

route{"sink","kcontrol","source"}

转化为path的过程: 1.找到sink,kcontrol,source 2.构造path。 3.如果需要设置connect则设置connect。 我们称kcontrol为NULL的path称为static path。如果kcontrol不为NULL则称为动态path。对于动态路径:

static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,const char *control,int (*connected)(struct snd_soc_dapm_widget *source,struct snd_soc_dapm_widget *sink))
	if (control == NULL) { //静态路径
		path->connect = 1;
	}
	else
	{
		//根据不同的id去设置相应的状态,通过读取寄存器,再设置connect的状态
		switch (wsource->id) {
			case snd_soc_dapm_demux:
				ret = dapm_connect_mux(dapm, path, control, wsource);
				if (ret)
					goto err;
				break;
			default:
				break;
			}
	
			switch (wsink->id) {
			case snd_soc_dapm_mux:
				ret = dapm_connect_mux(dapm, path, control, wsink);
				if (ret != 0)
					goto err;
				break;
			case snd_soc_dapm_switch:
			case snd_soc_dapm_mixer:
			case snd_soc_dapm_mixer_named_ctl:
				ret = dapm_connect_mixer(dapm, path, control);
				if (ret != 0)
					goto err;
				break;
			default:
				break;
			}
	}

其会根据寄存器实际的值,然后设置connect的值,如dapm_connect_mixer函数:

/* connect mixer widget to its interconnecting audio paths */
static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,struct snd_soc_dapm_path *path, const char *control_name)
	dapm_set_mixer_path_status(path, i);
		soc_dapm_read(p->sink->dapm, reg, &val);
			p->connect = !!val;

我们再次回到snd_soc_dapm_add_path函数:

static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,const char *control,int (*connected)(struct snd_soc_dapm_widget *source,struct snd_soc_dapm_widget *sink))
	/*把path放入链表*/
	list_add(&path->list, &dapm->card->paths);
	list_add(&path->list_node[dir], &widgets[dir]->edges[dir]);

添加到里面去,就可以通过dapm->card->paths查询所有的path了,其最终会形成多条complite path,这个在后续为大家讲解。

从上面的分析,我们知道snd_soc_dapm_add_route其没有设置kcontrol,其设置是在snd_soc_dapm_new_control_unlocked函数中,把widget添加到dapm->card->widgets,然后在通过dapm_create_or_share_kcontrol把widget中的kcontrol添加到card->controls之中,

关注
打赏
1592542134
查看更多评论
立即登录/注册

微信扫码登录

0.2010s