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

📄 soc-core.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		return -ENODEV;	}	codec->card->dev = socdev->dev;	codec->card->private_data = codec;	strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));	/* create the pcms */	for(i = 0; i < machine->num_links; i++) {		ret = soc_new_pcm(socdev, &machine->dai_link[i], i);		if (ret < 0) {			printk(KERN_ERR "asoc: can't create pcm %s\n",				machine->dai_link[i].stream_name);			mutex_unlock(&codec->mutex);			return ret;		}	}	mutex_unlock(&codec->mutex);	return ret;}EXPORT_SYMBOL_GPL(snd_soc_new_pcms);/** * snd_soc_register_card - register sound card * @socdev: the SoC audio device * * Register a SoC sound card. Also registers an AC97 device if the * codec is AC97 for ad hoc devices. * * Returns 0 for success, else error. */int snd_soc_register_card(struct snd_soc_device *socdev){	struct snd_soc_codec *codec = socdev->codec;	struct snd_soc_machine *machine = socdev->machine;	int ret = 0, i, ac97 = 0, err = 0;	mutex_lock(&codec->mutex);	for(i = 0; i < machine->num_links; i++) {		if (socdev->machine->dai_link[i].init) {			err = socdev->machine->dai_link[i].init(codec);			if (err < 0) {				printk(KERN_ERR "asoc: failed to init %s\n",					socdev->machine->dai_link[i].stream_name);				continue;			}		}		if (socdev->machine->dai_link[i].codec_dai->type == 			SND_SOC_DAI_AC97_BUS)			ac97 = 1;	}	snprintf(codec->card->shortname, sizeof(codec->card->shortname),		 "%s", machine->name);	snprintf(codec->card->longname, sizeof(codec->card->longname),		 "%s (%s)", machine->name, codec->name);	ret = snd_card_register(codec->card);	if (ret < 0) {		printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n",				codec->name);		goto out;	}#ifdef CONFIG_SND_SOC_AC97_BUS	if (ac97) {		ret = soc_ac97_dev_register(codec);		if (ret < 0) {			printk(KERN_ERR "asoc: AC97 device register failed\n");			snd_card_free(codec->card);			goto out;		}	}#endif	err = snd_soc_dapm_sys_add(socdev->dev);	if (err < 0)		printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");	err = device_create_file(socdev->dev, &dev_attr_codec_reg);	if (err < 0)		printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n");out:	mutex_unlock(&codec->mutex);	return ret;}EXPORT_SYMBOL_GPL(snd_soc_register_card);/** * snd_soc_free_pcms - free sound card and pcms * @socdev: the SoC audio device * * Frees sound card and pcms associated with the socdev. * Also unregister the codec if it is an AC97 device. */void snd_soc_free_pcms(struct snd_soc_device *socdev){	struct snd_soc_codec *codec = socdev->codec;#ifdef CONFIG_SND_SOC_AC97_BUS	struct snd_soc_codec_dai *codec_dai;	int i;#endif	mutex_lock(&codec->mutex);#ifdef CONFIG_SND_SOC_AC97_BUS	for(i = 0; i < codec->num_dai; i++) {		codec_dai = &codec->dai[i];		if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {			soc_ac97_dev_unregister(codec);			goto free_card;		}	}free_card:#endif	if (codec->card)		snd_card_free(codec->card);	device_remove_file(socdev->dev, &dev_attr_codec_reg);	mutex_unlock(&codec->mutex);}EXPORT_SYMBOL_GPL(snd_soc_free_pcms);/** * snd_soc_set_runtime_hwparams - set the runtime hardware parameters * @substream: the pcm substream * @hw: the hardware parameters * * Sets the substream runtime hardware parameters. */int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,	const struct snd_pcm_hardware *hw){	struct snd_pcm_runtime *runtime = substream->runtime;	runtime->hw.info = hw->info;	runtime->hw.formats = hw->formats;	runtime->hw.period_bytes_min = hw->period_bytes_min;	runtime->hw.period_bytes_max = hw->period_bytes_max;	runtime->hw.periods_min = hw->periods_min;	runtime->hw.periods_max = hw->periods_max;	runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;	runtime->hw.fifo_size = hw->fifo_size;	return 0;}EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);/** * snd_soc_cnew - create new control * @_template: control template * @data: control private data * @lnng_name: control long name * * Create a new mixer control from a template control. * * Returns 0 for success, else error. */struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,	void *data, char *long_name){	struct snd_kcontrol_new template;	memcpy(&template, _template, sizeof(template));	if (long_name)		template.name = long_name;	template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;	template.index = 0;	return snd_ctl_new1(&template, data);}EXPORT_SYMBOL_GPL(snd_soc_cnew);/** * snd_soc_info_enum_double - enumerated double mixer info callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about a double enumerated * mixer control. * * Returns 0 for success. */int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_info *uinfo){	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = e->shift_l == e->shift_r ? 1 : 2;	uinfo->value.enumerated.items = e->mask;	if (uinfo->value.enumerated.item > e->mask - 1)		uinfo->value.enumerated.item = e->mask - 1;	strcpy(uinfo->value.enumerated.name,		e->texts[uinfo->value.enumerated.item]);	return 0;}EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);/** * snd_soc_get_enum_double - enumerated double mixer get callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to get the value of a double enumerated mixer. * * Returns 0 for success. */int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = 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(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_get_enum_double);/** * snd_soc_put_enum_double - enumerated double mixer put callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to set the value of a double enumerated mixer. * * Returns 0 for success. */int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;	unsigned short val;	unsigned short mask, bitmask;	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)		;	if (ucontrol->value.enumerated.item[0] > e->mask - 1)		return -EINVAL;	val = ucontrol->value.enumerated.item[0] << 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;	}	return snd_soc_update_bits(codec, e->reg, mask, val);}EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);/** * snd_soc_info_enum_ext - external enumerated single mixer info callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about an external enumerated * single mixer. * * Returns 0 for success. */int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_info *uinfo){	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = e->mask;	if (uinfo->value.enumerated.item > e->mask - 1)		uinfo->value.enumerated.item = e->mask - 1;	strcpy(uinfo->value.enumerated.name,		e->texts[uinfo->value.enumerated.item]);	return 0;}EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);/** * snd_soc_info_volsw_ext - external single mixer info callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about a single external mixer control. * * Returns 0 for success. */int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_info *uinfo){	int mask = kcontrol->private_value;	uinfo->type =		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);/** * snd_soc_info_volsw - single mixer info callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about a single mixer control. * * Returns 0 for success. */int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_info *uinfo){	int mask = (kcontrol->private_value >> 16) & 0xff;	int shift = (kcontrol->private_value >> 8) & 0x0f;	int rshift = (kcontrol->private_value >> 12) & 0x0f;	uinfo->type =		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = shift == rshift ? 1 : 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}EXPORT_SYMBOL_GPL(snd_soc_info_volsw);/** * snd_soc_get_volsw - single mixer get callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to get the value of a single mixer control. * * Returns 0 for success. */int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = 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;	ucontrol->value.integer.value[0] =		(snd_soc_read(codec, reg) >> shift) & mask;	if (shift != rshift)		ucontrol->value.integer.value[1] =			(snd_soc_read(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_get_volsw);/** * snd_soc_put_volsw - single mixer put callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to set the value of a single mixer control. * * Returns 0 for success. */int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = 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;	int err;	unsigned short val, val2, val_mask;	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;	}	err = snd_soc_update_bits(codec, reg, val_mask, val);	return err;}EXPORT_SYMBOL_GPL(snd_soc_put_volsw);/** * snd_soc_info_volsw_2r - double mixer info callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about a double mixer control that * spans 2 codec registers. * * Returns 0 for success. */int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_info *uinfo){	int mask = (kcontrol->private_value >> 12) & 0xff;	uinfo->type =		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);/** * snd_soc_get_volsw_2r - double mixer get callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to get the value of a double mixer control that spans 2 registers. * * Returns 0 for success. */int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int reg2 = (kcontrol->private_value >> 24) & 0xff;	int shift = (kcontrol->private_value >> 8) & 0x0f;	int mask = (kcontrol->private_value >> 12) & 0xff;	int invert = (kcontrol->private_value >> 20) & 0x01;	ucontrol->value.integer.value[0] =		(snd_soc_read(codec, reg) >> shift) & mask;	ucontrol->value.integer.value[1] =		(snd_soc_read(codec, reg2) >> shift) & mask;	if (invert) {		ucontrol->value.integer.value[0] =			mask - ucontrol->value.integer.value[0];		ucontrol->value.integer.value[1] =			mask - ucontrol->value.integer.value[1];	}	return 0;}EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);/** * snd_soc_put_volsw_2r - double mixer set callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to set the value of a double mixer control that spans 2 registers. * * Returns 0 for success. */int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int reg2 = (kcontrol->private_value >> 24) & 0xff;	int shift = (kcontrol->private_value >> 8) & 0x0f;	int mask = (kcontrol->private_value >> 12) & 0xff;	int invert = (kcontrol->private_value >> 20) & 0x01;	int err;	unsigned short val, val2, val_mask;	val_mask = mask << shift;	val = (ucontrol->value.integer.value[0] & mask);	val2 = (ucontrol->value.integer.value[1] & mask);	if (invert) {		val = mask - val;		val2 = mask - val2;	}	val = val << shift;	val2 = val2 << shift;	if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0)		return err;	err = snd_soc_update_bits(codec, reg2, val_mask, val2);	return err;}EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);static int __devinit snd_soc_init(void){	printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);	return platform_driver_register(&soc_driver);}static void snd_soc_exit(void){ 	platform_driver_unregister(&soc_driver);}module_init(snd_soc_init);module_exit(snd_soc_exit);/* Module information */MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");MODULE_DESCRIPTION("ALSA SoC Core");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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