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

📄 soc-dapm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			wsink->id == snd_soc_dapm_line ||			wsink->id == snd_soc_dapm_output)			wsink->ext = 1;	}	if (wsource->id == snd_soc_dapm_output) {		if (wsink->id == snd_soc_dapm_spk ||			wsink->id == snd_soc_dapm_hp ||			wsink->id == snd_soc_dapm_line ||			wsink->id == snd_soc_dapm_input)			wsource->ext = 1;	}	/* connect static paths */	if (control == NULL) {		list_add(&path->list, &codec->dapm_paths);		list_add(&path->list_sink, &wsink->sources);		list_add(&path->list_source, &wsource->sinks);		path->connect = 1;		return 0;	}	/* connect dynamic paths */	switch(wsink->id) {	case snd_soc_dapm_adc:	case snd_soc_dapm_dac:	case snd_soc_dapm_pga:	case snd_soc_dapm_input:	case snd_soc_dapm_output:	case snd_soc_dapm_micbias:	case snd_soc_dapm_vmid:	case snd_soc_dapm_pre:	case snd_soc_dapm_post:		list_add(&path->list, &codec->dapm_paths);		list_add(&path->list_sink, &wsink->sources);		list_add(&path->list_source, &wsource->sinks);		path->connect = 1;		return 0;	case snd_soc_dapm_mux:		ret = dapm_connect_mux(codec, wsource, wsink, path, control,			&wsink->kcontrols[0]);		if (ret != 0)			goto err;		break;	case snd_soc_dapm_switch:	case snd_soc_dapm_mixer:		ret = dapm_connect_mixer(codec, wsource, wsink, path, control);		if (ret != 0)			goto err;		break;	case snd_soc_dapm_hp:	case snd_soc_dapm_mic:	case snd_soc_dapm_line:	case snd_soc_dapm_spk:		list_add(&path->list, &codec->dapm_paths);		list_add(&path->list_sink, &wsink->sources);		list_add(&path->list_source, &wsource->sinks);		path->connect = 0;		return 0;	}	return 0;err:	printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,		control, sink);	kfree(path);	return ret;}EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);/** * snd_soc_dapm_new_widgets - add new dapm widgets * @codec: audio codec * * Checks the codec for any new dapm widgets and creates them if found. * * Returns 0 for success. */int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec){	struct snd_soc_dapm_widget *w;	mutex_lock(&codec->mutex);	list_for_each_entry(w, &codec->dapm_widgets, list)	{		if (w->new)			continue;		switch(w->id) {		case snd_soc_dapm_switch:		case snd_soc_dapm_mixer:			dapm_new_mixer(codec, w);			break;		case snd_soc_dapm_mux:			dapm_new_mux(codec, w);			break;		case snd_soc_dapm_adc:		case snd_soc_dapm_dac:		case snd_soc_dapm_pga:			dapm_new_pga(codec, w);			break;		case snd_soc_dapm_input:		case snd_soc_dapm_output:		case snd_soc_dapm_micbias:		case snd_soc_dapm_spk:		case snd_soc_dapm_hp:		case snd_soc_dapm_mic:		case snd_soc_dapm_line:		case snd_soc_dapm_vmid:		case snd_soc_dapm_pre:		case snd_soc_dapm_post:			break;		}		w->new = 1;	}	dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);	mutex_unlock(&codec->mutex);	return 0;}EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);/** * snd_soc_dapm_get_volsw - dapm mixer get callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to get the value of a dapm mixer control. * * Returns 0 for success. */int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0x0f;	int rshift = (kcontrol->private_value >> 12) & 0x0f;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0x01;	/* return the saved value if we are powered down */	if (widget->id == snd_soc_dapm_pga && !widget->power) {		ucontrol->value.integer.value[0] = widget->saved_value;		return 0;	}	ucontrol->value.integer.value[0] =		(snd_soc_read(widget->codec, reg) >> shift) & mask;	if (shift != rshift)		ucontrol->value.integer.value[1] =			(snd_soc_read(widget->codec, reg) >> rshift) & mask;	if (invert) {		ucontrol->value.integer.value[0] =			mask - ucontrol->value.integer.value[0];		if (shift != rshift)			ucontrol->value.integer.value[1] =				mask - ucontrol->value.integer.value[1];	}	return 0;}EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);/** * snd_soc_dapm_put_volsw - dapm mixer set callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to set the value of a dapm mixer control. * * Returns 0 for success. */int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0x0f;	int rshift = (kcontrol->private_value >> 12) & 0x0f;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0x01;	unsigned short val, val2, val_mask;	int ret;	val = (ucontrol->value.integer.value[0] & mask);	if (invert)		val = mask - val;	val_mask = mask << shift;	val = val << shift;	if (shift != rshift) {		val2 = (ucontrol->value.integer.value[1] & mask);		if (invert)			val2 = mask - val2;		val_mask |= mask << rshift;		val |= val2 << rshift;	}	mutex_lock(&widget->codec->mutex);	widget->value = val;	/* save volume value if the widget is powered down */	if (widget->id == snd_soc_dapm_pga && !widget->power) {		widget->saved_value = val;		mutex_unlock(&widget->codec->mutex);		return 1;	}	dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);	if (widget->event) {		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {			ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);			if (ret < 0)				goto out;		}		ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);		if (widget->event_flags & SND_SOC_DAPM_POST_REG)			ret = widget->event(widget, SND_SOC_DAPM_POST_REG);	} else		ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);out:	mutex_unlock(&widget->codec->mutex);	return ret;}EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);/** * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to get the value of a dapm enumerated double mixer control. * * Returns 0 for success. */int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;	unsigned short val, bitmask;	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)		;	val = snd_soc_read(widget->codec, e->reg);	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);	if (e->shift_l != e->shift_r)		ucontrol->value.enumerated.item[1] =			(val >> e->shift_r) & (bitmask - 1);	return 0;}EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);/** * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to set the value of a dapm enumerated double mixer control. * * Returns 0 for success. */int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;	unsigned short val, mux;	unsigned short mask, bitmask;	int ret = 0;	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)		;	if (ucontrol->value.enumerated.item[0] > e->mask - 1)		return -EINVAL;	mux = ucontrol->value.enumerated.item[0];	val = mux << e->shift_l;	mask = (bitmask - 1) << e->shift_l;	if (e->shift_l != e->shift_r) {		if (ucontrol->value.enumerated.item[1] > e->mask - 1)			return -EINVAL;		val |= ucontrol->value.enumerated.item[1] << e->shift_r;		mask |= (bitmask - 1) << e->shift_r;	}	mutex_lock(&widget->codec->mutex);	widget->value = val;	dapm_mux_update_power(widget, kcontrol, mask, mux, e);	if (widget->event) {		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {			ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);			if (ret < 0)				goto out;		}		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);		if (widget->event_flags & SND_SOC_DAPM_POST_REG)			ret = widget->event(widget, SND_SOC_DAPM_POST_REG);	} else		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);out:	mutex_unlock(&widget->codec->mutex);	return ret;}EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);/** * snd_soc_dapm_new_control - create new dapm control * @codec: audio codec * @widget: widget template * * Creates a new dapm control based upon the template. * * Returns 0 for success else error. */int snd_soc_dapm_new_control(struct snd_soc_codec *codec,	const struct snd_soc_dapm_widget *widget){	struct snd_soc_dapm_widget *w;	if ((w = dapm_cnew_widget(widget)) == NULL)		return -ENOMEM;	w->codec = codec;	INIT_LIST_HEAD(&w->sources);	INIT_LIST_HEAD(&w->sinks);	INIT_LIST_HEAD(&w->list);	list_add(&w->list, &codec->dapm_widgets);	/* machine layer set ups unconnected pins and insertions */	w->connected = 1;	return 0;}EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);/** * snd_soc_dapm_stream_event - send a stream event to the dapm core * @codec: audio codec * @stream: stream name * @event: stream event * * Sends a stream event to the dapm core. The core then makes any * necessary widget power changes. * * Returns 0 for success else error. */int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,	char *stream, int event){	struct snd_soc_dapm_widget *w;	if (stream == NULL)		return 0;	mutex_lock(&codec->mutex);	list_for_each_entry(w, &codec->dapm_widgets, list)	{		if (!w->sname)			continue;		dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname,			stream, event);		if (strstr(w->sname, stream)) {			switch(event) {			case SND_SOC_DAPM_STREAM_START:				w->active = 1;				break;			case SND_SOC_DAPM_STREAM_STOP:				w->active = 0;				break;			case SND_SOC_DAPM_STREAM_SUSPEND:				if (w->active)					w->suspend = 1;				w->active = 0;				break;			case SND_SOC_DAPM_STREAM_RESUME:				if (w->suspend) {					w->active = 1;					w->suspend = 0;				}				break;			case SND_SOC_DAPM_STREAM_PAUSE_PUSH:				break;			case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:				break;			}		}	}	mutex_unlock(&codec->mutex);	dapm_power_widgets(codec, event);	dump_dapm(codec, __FUNCTION__);	return 0;}EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);/** * snd_soc_dapm_set_endpoint - set audio endpoint status * @codec: audio codec * @endpoint: audio signal endpoint (or start point) * @status: point status * * Set audio endpoint status - connected or disconnected. * * Returns 0 for success else error. */int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,	char *endpoint, int status){	struct snd_soc_dapm_widget *w;	list_for_each_entry(w, &codec->dapm_widgets, list) {		if (!strcmp(w->name, endpoint)) {			w->connected = status;		}	}	return 0;}EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);/** * snd_soc_dapm_free - free dapm resources * @socdev: SoC device * * Free all dapm widgets and resources. */void snd_soc_dapm_free(struct snd_soc_device *socdev){	struct snd_soc_codec *codec = socdev->codec;	snd_soc_dapm_sys_remove(socdev->dev);	dapm_free_widgets(codec);}EXPORT_SYMBOL_GPL(snd_soc_dapm_free);/* Module information */MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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