⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soc-dapm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			path->walked = 1;			con += is_connected_input_ep(path->source);		}	}	return con;}/* * Scan each dapm widget for complete audio path. * A complete path is a route that has valid endpoints i.e.:- * *  o DAC to output pin. *  o Input Pin to ADC. *  o Input pin to Output pin (bypass, sidetone) *  o DAC to ADC (loopback). */static int dapm_power_widgets(struct snd_soc_codec *codec, int event){	struct snd_soc_dapm_widget *w;	int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;	/* do we have a sequenced stream event */	if (event == SND_SOC_DAPM_STREAM_START) {		c = ARRAY_SIZE(dapm_up_seq);		seq = dapm_up_seq;	} else if (event == SND_SOC_DAPM_STREAM_STOP) {		c = ARRAY_SIZE(dapm_down_seq);		seq = dapm_down_seq;	}	for(i = 0; i < c; i++) {		list_for_each_entry(w, &codec->dapm_widgets, list) {			/* is widget in stream order */			if (seq && seq[i] && w->id != seq[i])				continue;			/* vmid - no action */			if (w->id == snd_soc_dapm_vmid)				continue;			/* active ADC */			if (w->id == snd_soc_dapm_adc && w->active) {				in = is_connected_input_ep(w);				dapm_clear_walk(w->codec);				w->power = (in != 0) ? 1 : 0;				dapm_update_bits(w);				continue;			}			/* active DAC */			if (w->id == snd_soc_dapm_dac && w->active) {				out = is_connected_output_ep(w);				dapm_clear_walk(w->codec);				w->power = (out != 0) ? 1 : 0;				dapm_update_bits(w);				continue;			}			/* programmable gain/attenuation */			if (w->id == snd_soc_dapm_pga) {				int on;				in = is_connected_input_ep(w);				dapm_clear_walk(w->codec);				out = is_connected_output_ep(w);				dapm_clear_walk(w->codec);				w->power = on = (out != 0 && in != 0) ? 1 : 0;				if (!on)					dapm_set_pga(w, on); /* lower volume to reduce pops */				dapm_update_bits(w);				if (on)					dapm_set_pga(w, on); /* restore volume from zero */				continue;			}			/* pre and post event widgets */			if (w->id == snd_soc_dapm_pre) {				if (!w->event)					continue;				if (event == SND_SOC_DAPM_STREAM_START) {					ret = w->event(w, SND_SOC_DAPM_PRE_PMU);					if (ret < 0)						return ret;				} else if (event == SND_SOC_DAPM_STREAM_STOP) {					ret = w->event(w, SND_SOC_DAPM_PRE_PMD);					if (ret < 0)						return ret;				}				continue;			}			if (w->id == snd_soc_dapm_post) {				if (!w->event)					continue;				if (event == SND_SOC_DAPM_STREAM_START) {					ret = w->event(w, SND_SOC_DAPM_POST_PMU);					if (ret < 0)						return ret;				} else if (event == SND_SOC_DAPM_STREAM_STOP) {					ret = w->event(w, SND_SOC_DAPM_POST_PMD);					if (ret < 0)						return ret;				}				continue;			}			/* all other widgets */			in = is_connected_input_ep(w);			dapm_clear_walk(w->codec);			out = is_connected_output_ep(w);			dapm_clear_walk(w->codec);			power = (out != 0 && in != 0) ? 1 : 0;			power_change = (w->power == power) ? 0: 1;			w->power = power;			/* call any power change event handlers */			if (power_change) {				if (w->event) {					dbg("power %s event for %s flags %x\n",						w->power ? "on" : "off", w->name, w->event_flags);					if (power) {						/* power up event */						if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {							ret = w->event(w, SND_SOC_DAPM_PRE_PMU);							if (ret < 0)								return ret;						}						dapm_update_bits(w);						if (w->event_flags & SND_SOC_DAPM_POST_PMU){							ret = w->event(w, SND_SOC_DAPM_POST_PMU);							if (ret < 0)								return ret;						}					} else {						/* power down event */						if (w->event_flags & SND_SOC_DAPM_PRE_PMD) {							ret = w->event(w, SND_SOC_DAPM_PRE_PMD);							if (ret < 0)								return ret;						}						dapm_update_bits(w);						if (w->event_flags & SND_SOC_DAPM_POST_PMD) {							ret = w->event(w, SND_SOC_DAPM_POST_PMD);							if (ret < 0)								return ret;						}					}				} else					/* no event handler */					dapm_update_bits(w);			}		}	}	return ret;}#if DAPM_DEBUGstatic void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action){	struct snd_soc_dapm_widget *w;	struct snd_soc_dapm_path *p = NULL;	int in, out;	printk("DAPM %s %s\n", codec->name, action);	list_for_each_entry(w, &codec->dapm_widgets, list) {		/* only display widgets that effect routing */		switch (w->id) {		case snd_soc_dapm_pre:		case snd_soc_dapm_post:		case snd_soc_dapm_vmid:			continue;		case snd_soc_dapm_mux:		case snd_soc_dapm_output:		case snd_soc_dapm_input:		case snd_soc_dapm_switch:		case snd_soc_dapm_hp:		case snd_soc_dapm_mic:		case snd_soc_dapm_spk:		case snd_soc_dapm_line:		case snd_soc_dapm_micbias:		case snd_soc_dapm_dac:		case snd_soc_dapm_adc:		case snd_soc_dapm_pga:		case snd_soc_dapm_mixer:			if (w->name) {				in = is_connected_input_ep(w);				dapm_clear_walk(w->codec);				out = is_connected_output_ep(w);				dapm_clear_walk(w->codec);				printk("%s: %s  in %d out %d\n", w->name,					w->power ? "On":"Off",in, out);				list_for_each_entry(p, &w->sources, list_sink) {					if (p->connect)						printk(" in  %s %s\n", p->name ? p->name : "static",							p->source->name);				}				list_for_each_entry(p, &w->sinks, list_source) {					if (p->connect)						printk(" out %s %s\n", p->name ? p->name : "static",							p->sink->name);				}			}		break;		}	}}#endif/* test and update the power status of a mux widget */static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,				 struct snd_kcontrol *kcontrol, int mask,				 int val, struct soc_enum* e){	struct snd_soc_dapm_path *path;	int found = 0;	if (widget->id != snd_soc_dapm_mux)		return -ENODEV;	if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))		return 0;	/* find dapm widget path assoc with kcontrol */	list_for_each_entry(path, &widget->codec->dapm_paths, list) {		if (path->kcontrol != kcontrol)			continue;		if (!path->name || ! e->texts[val])			continue;		found = 1;		/* we now need to match the string in the enum to the path */		if (!(strcmp(path->name, e->texts[val])))			path->connect = 1; /* new connection */		else			path->connect = 0; /* old connection must be powered down */	}	if (found)		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);	return 0;}/* test and update the power status of a mixer widget */static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,				   struct snd_kcontrol *kcontrol, int reg,				   int val_mask, int val, int invert){	struct snd_soc_dapm_path *path;	int found = 0;	if (widget->id != snd_soc_dapm_mixer)		return -ENODEV;	if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))		return 0;	/* find dapm widget path assoc with kcontrol */	list_for_each_entry(path, &widget->codec->dapm_paths, list) {		if (path->kcontrol != kcontrol)			continue;		/* found, now check type */		found = 1;		if (val)			/* new connection */			path->connect = invert ? 0:1;		else			/* old connection must be powered down */			path->connect = invert ? 1:0;		break;	}	if (found)		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);	return 0;}/* show dapm widget status in sys fs */static ssize_t dapm_widget_show(struct device *dev,	struct device_attribute *attr, char *buf){	struct snd_soc_device *devdata = dev_get_drvdata(dev);	struct snd_soc_codec *codec = devdata->codec;	struct snd_soc_dapm_widget *w;	int count = 0;	char *state = "not set";	list_for_each_entry(w, &codec->dapm_widgets, list) {		/* only display widgets that burnm power */		switch (w->id) {		case snd_soc_dapm_hp:		case snd_soc_dapm_mic:		case snd_soc_dapm_spk:		case snd_soc_dapm_line:		case snd_soc_dapm_micbias:		case snd_soc_dapm_dac:		case snd_soc_dapm_adc:		case snd_soc_dapm_pga:		case snd_soc_dapm_mixer:			if (w->name)				count += sprintf(buf + count, "%s: %s\n",					w->name, w->power ? "On":"Off");		break;		default:		break;		}	}	switch(codec->dapm_state){	case SNDRV_CTL_POWER_D0:		state = "D0";		break;	case SNDRV_CTL_POWER_D1:		state = "D1";		break;	case SNDRV_CTL_POWER_D2:		state = "D2";		break;	case SNDRV_CTL_POWER_D3hot:		state = "D3hot";		break;	case SNDRV_CTL_POWER_D3cold:		state = "D3cold";		break;	}	count += sprintf(buf + count, "PM State: %s\n", state);	return count;}static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);int snd_soc_dapm_sys_add(struct device *dev){	int ret = 0;	if (dapm_status)		ret = device_create_file(dev, &dev_attr_dapm_widget);	return ret;}static void snd_soc_dapm_sys_remove(struct device *dev){	if (dapm_status)		device_remove_file(dev, &dev_attr_dapm_widget);}/* free all dapm widgets and resources */static void dapm_free_widgets(struct snd_soc_codec *codec){	struct snd_soc_dapm_widget *w, *next_w;	struct snd_soc_dapm_path *p, *next_p;	list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {		list_del(&w->list);		kfree(w);	}	list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {		list_del(&p->list);		kfree(p->long_name);		kfree(p);	}}/** * snd_soc_dapm_sync_endpoints - scan and power dapm paths * @codec: audio codec * * Walks all dapm audio paths and powers widgets according to their * stream or path usage. * * Returns 0 for success. */int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec){	return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);}EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints);/** * snd_soc_dapm_connect_input - connect dapm widgets * @codec: audio codec * @sink: name of target widget * @control: mixer control name * @source: name of source name * * Connects 2 dapm widgets together via a named audio path. The sink is * the widget receiving the audio signal, whilst the source is the sender * of the audio signal. * * Returns 0 for success else error. */int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,	const char * control, const char *source){	struct snd_soc_dapm_path *path;	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;	int ret = 0;	/* find src and dest widgets */	list_for_each_entry(w, &codec->dapm_widgets, list) {		if (!wsink && !(strcmp(w->name, sink))) {			wsink = w;			continue;		}		if (!wsource && !(strcmp(w->name, source))) {			wsource = w;		}	}	if (wsource == NULL || wsink == NULL)		return -ENODEV;	path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);	if (!path)		return -ENOMEM;	path->source = wsource;	path->sink = wsink;	INIT_LIST_HEAD(&path->list);	INIT_LIST_HEAD(&path->list_source);	INIT_LIST_HEAD(&path->list_sink);	/* check for external widgets */	if (wsink->id == snd_soc_dapm_input) {		if (wsource->id == snd_soc_dapm_micbias ||			wsource->id == snd_soc_dapm_mic ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -