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

📄 patch_realtek.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))		item_num = alc_pin_mode_min(dir);	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);	return 0;}static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,			    struct snd_ctl_elem_value *ucontrol){	unsigned int i;	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);	hda_nid_t nid = kcontrol->private_value & 0xffff;	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;	long *valp = ucontrol->value.integer.value;	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,						 AC_VERB_GET_PIN_WIDGET_CONTROL,						 0x00);	/* Find enumerated value for current pinctl setting */	i = alc_pin_mode_min(dir);	while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))		i++;	*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);	return 0;}static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,			    struct snd_ctl_elem_value *ucontrol){	signed int change;	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);	hda_nid_t nid = kcontrol->private_value & 0xffff;	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;	long val = *ucontrol->value.integer.value;	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,						 AC_VERB_GET_PIN_WIDGET_CONTROL,						 0x00);	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))		val = alc_pin_mode_min(dir);	change = pinctl != alc_pin_mode_values[val];	if (change) {		/* Set pin mode to that requested */		snd_hda_codec_write_cache(codec, nid, 0,					  AC_VERB_SET_PIN_WIDGET_CONTROL,					  alc_pin_mode_values[val]);		/* Also enable the retasking pin's input/output as required 		 * for the requested pin mode.  Enum values of 2 or less are		 * input modes.		 *		 * Dynamically switching the input/output buffers probably		 * reduces noise slightly (particularly on input) so we'll		 * do it.  However, having both input and output buffers		 * enabled simultaneously doesn't seem to be problematic if		 * this turns out to be necessary in the future.		 */		if (val <= 2) {			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,						 HDA_AMP_MUTE, HDA_AMP_MUTE);			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,						 HDA_AMP_MUTE, 0);		} else {			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,						 HDA_AMP_MUTE, HDA_AMP_MUTE);			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,						 HDA_AMP_MUTE, 0);		}	}	return change;}#define ALC_PIN_MODE(xname, nid, dir) \	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \	  .info = alc_pin_mode_info, \	  .get = alc_pin_mode_get, \	  .put = alc_pin_mode_put, \	  .private_value = nid | (dir<<16) }/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged * together using a mask with more than one bit set.  This control is * currently used only by the ALC260 test model.  At this stage they are not * needed for any "production" models. */#ifdef CONFIG_SND_DEBUG#define alc_gpio_data_info	snd_ctl_boolean_mono_infostatic int alc_gpio_data_get(struct snd_kcontrol *kcontrol,			     struct snd_ctl_elem_value *ucontrol){	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);	hda_nid_t nid = kcontrol->private_value & 0xffff;	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;	long *valp = ucontrol->value.integer.value;	unsigned int val = snd_hda_codec_read(codec, nid, 0,					      AC_VERB_GET_GPIO_DATA, 0x00);	*valp = (val & mask) != 0;	return 0;}static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,			     struct snd_ctl_elem_value *ucontrol){	signed int change;	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);	hda_nid_t nid = kcontrol->private_value & 0xffff;	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;	long val = *ucontrol->value.integer.value;	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,						    AC_VERB_GET_GPIO_DATA,						    0x00);	/* Set/unset the masked GPIO bit(s) as needed */	change = (val == 0 ? 0 : mask) != (gpio_data & mask);	if (val == 0)		gpio_data &= ~mask;	else		gpio_data |= mask;	snd_hda_codec_write_cache(codec, nid, 0,				  AC_VERB_SET_GPIO_DATA, gpio_data);	return change;}#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \	  .info = alc_gpio_data_info, \	  .get = alc_gpio_data_get, \	  .put = alc_gpio_data_put, \	  .private_value = nid | (mask<<16) }#endif   /* CONFIG_SND_DEBUG *//* A switch control to allow the enabling of the digital IO pins on the * ALC260.  This is incredibly simplistic; the intention of this control is * to provide something in the test model allowing digital outputs to be * identified if present.  If models are found which can utilise these * outputs a more complete mixer control can be devised for those models if * necessary. */#ifdef CONFIG_SND_DEBUG#define alc_spdif_ctrl_info	snd_ctl_boolean_mono_infostatic int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,			      struct snd_ctl_elem_value *ucontrol){	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);	hda_nid_t nid = kcontrol->private_value & 0xffff;	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;	long *valp = ucontrol->value.integer.value;	unsigned int val = snd_hda_codec_read(codec, nid, 0,					      AC_VERB_GET_DIGI_CONVERT, 0x00);	*valp = (val & mask) != 0;	return 0;}static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,			      struct snd_ctl_elem_value *ucontrol){	signed int change;	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);	hda_nid_t nid = kcontrol->private_value & 0xffff;	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;	long val = *ucontrol->value.integer.value;	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,						    AC_VERB_GET_DIGI_CONVERT,						    0x00);	/* Set/unset the masked control bit(s) as needed */	change = (val == 0 ? 0 : mask) != (ctrl_data & mask);	if (val==0)		ctrl_data &= ~mask;	else		ctrl_data |= mask;	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,				  ctrl_data);	return change;}#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \	  .info = alc_spdif_ctrl_info, \	  .get = alc_spdif_ctrl_get, \	  .put = alc_spdif_ctrl_put, \	  .private_value = nid | (mask<<16) }#endif   /* CONFIG_SND_DEBUG *//* * set up from the preset table */static void setup_preset(struct alc_spec *spec,			 const struct alc_config_preset *preset){	int i;	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)		spec->mixers[spec->num_mixers++] = preset->mixers[i];	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];	     i++)		spec->init_verbs[spec->num_init_verbs++] =			preset->init_verbs[i];		spec->channel_mode = preset->channel_mode;	spec->num_channel_mode = preset->num_channel_mode;	spec->need_dac_fix = preset->need_dac_fix;	spec->multiout.max_channels = spec->channel_mode[0].channels;	spec->multiout.num_dacs = preset->num_dacs;	spec->multiout.dac_nids = preset->dac_nids;	spec->multiout.dig_out_nid = preset->dig_out_nid;	spec->multiout.hp_nid = preset->hp_nid;		spec->num_mux_defs = preset->num_mux_defs;	if (!spec->num_mux_defs)		spec->num_mux_defs = 1;	spec->input_mux = preset->input_mux;	spec->num_adc_nids = preset->num_adc_nids;	spec->adc_nids = preset->adc_nids;	spec->dig_in_nid = preset->dig_in_nid;	spec->unsol_event = preset->unsol_event;	spec->init_hook = preset->init_hook;#ifdef CONFIG_SND_HDA_POWER_SAVE	spec->loopback.amplist = preset->loopbacks;#endif}/* Enable GPIO mask and set output */static struct hda_verb alc_gpio1_init_verbs[] = {	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},	{ }};static struct hda_verb alc_gpio2_init_verbs[] = {	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},	{ }};static struct hda_verb alc_gpio3_init_verbs[] = {	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},	{ }};static void alc_sku_automute(struct hda_codec *codec){	struct alc_spec *spec = codec->spec;	unsigned int mute;	unsigned int present;	unsigned int hp_nid = spec->autocfg.hp_pins[0];	unsigned int sp_nid = spec->autocfg.speaker_pins[0];	/* need to execute and sync at first */	snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0);	present = snd_hda_codec_read(codec, hp_nid, 0,				     AC_VERB_GET_PIN_SENSE, 0);	spec->jack_present = (present & 0x80000000) != 0;	if (spec->jack_present) {		/* mute internal speaker */		snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,					 HDA_AMP_MUTE, HDA_AMP_MUTE);	} else {		/* unmute internal speaker if necessary */		mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0);		snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,					 HDA_AMP_MUTE, mute);	}}/* unsolicited event for HP jack sensing */static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res){	if (codec->vendor_id == 0x10ec0880)		res >>= 28;	else		res >>= 26;	if (res != ALC880_HP_EVENT)		return;	alc_sku_automute(codec);}/* 32-bit subsystem ID for BIOS loading in HD Audio codec. *	31 ~ 16 :	Manufacture ID *	15 ~ 8	:	SKU ID *	7  ~ 0	:	Assembly ID *	port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 */static void alc_subsystem_id(struct hda_codec *codec,			     unsigned int porta, unsigned int porte,			     unsigned int portd){	unsigned int ass, tmp, i;	unsigned nid;	struct alc_spec *spec = codec->spec;	ass = codec->subsystem_id & 0xffff;	if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))		goto do_sku;	/*		 * 31~30	: port conetcivity	 * 29~21	: reserve	 * 20		: PCBEEP input	 * 19~16	: Check sum (15:1)	 * 15~1		: Custom	 * 0		: override	*/	nid = 0x1d;	if (codec->vendor_id == 0x10ec0260)		nid = 0x17;	ass = snd_hda_codec_read(codec, nid, 0,				 AC_VERB_GET_CONFIG_DEFAULT, 0);	if (!(ass & 1) && !(ass & 0x100000))		return;	if ((ass >> 30) != 1)	/* no physical connection */		return;	/* check sum */	tmp = 0;	for (i = 1; i < 16; i++) {		if ((ass >> i) && 1)			tmp++;	}	if (((ass >> 16) & 0xf) != tmp)		return;do_sku:	/*	 * 0 : override	 * 1 :	Swap Jack	 * 2 : 0 --> Desktop, 1 --> Laptop	 * 3~5 : External Amplifier control	 * 7~6 : Reserved	*/	tmp = (ass & 0x38) >> 3;	/* external Amp control */	switch (tmp) {	case 1:		snd_hda_sequence_write(codec, alc_gpio1_init_verbs);		break;	case 3:		snd_hda_sequence_write(codec, alc_gpio2_init_verbs);		break;	case 7:		snd_hda_sequence_write(codec, alc_gpio3_init_verbs);		break;	case 5:	/* set EAPD output high */		switch (codec->vendor_id) {		case 0x10ec0260:			snd_hda_codec_write(codec, 0x0f, 0,					    AC_VERB_SET_EAPD_BTLENABLE, 2);			snd_hda_codec_write(codec, 0x10, 0,					    AC_VERB_SET_EAPD_BTLENABLE, 2);			break;		case 0x10ec0262:		case 0x10ec0267:		case 0x10ec0268:		case 0x10ec0269:		case 0x10ec0862:		case 0x10ec0662:				snd_hda_codec_write(codec, 0x14, 0,					    AC_VERB_SET_EAPD_BTLENABLE, 2);			snd_hda_codec_write(codec, 0x15, 0,					    AC_VERB_SET_EAPD_BTLENABLE, 2);			break;		}		switch (codec->vendor_id) {		case 0x10ec0260:			snd_hda_codec_write(codec, 0x1a, 0,					    AC_VERB_SET_COEF_INDEX, 7);			tmp = snd_hda_codec_read(codec, 0x1a, 0,						 AC_VERB_GET_PROC_COEF, 0);			snd_hda_codec_write(codec, 0x1a, 0,					    AC_VERB_SET_COEF_INDEX, 7);			snd_hda_codec_write(codec, 0x1a, 0,					    AC_VERB_SET_PROC_COEF,					    tmp | 0x2010);			break;		case 0x10ec0262:		case 0x10ec0880:		case 0x10ec0882:		case 0x10ec0883:		case 0x10ec0885:		case 0x10ec0888:			snd_hda_codec_write(codec, 0x20, 0,					    AC_VERB_SET_COEF_INDEX, 7);			tmp = snd_hda_codec_read(codec, 0x20, 0,						 AC_VERB_GET_PROC_COEF, 0);			snd_hda_codec_write(codec, 0x20, 0,					    AC_VERB_SET_COEF_INDEX, 7);				snd_hda_codec_write(codec, 0x20, 0,					    AC_VERB_SET_PROC_COEF,					    tmp | 0x2010);			break;		case 0x10ec0267:		case 0x10ec0268:			snd_hda_codec_write(codec, 0x20, 0,					    AC_VERB_SET_COEF_INDEX, 7);			tmp = snd_hda_codec_read(codec, 0x20, 0,						 AC_VERB_GET_PROC_COEF, 0);			snd_hda_codec_write(codec, 0x20, 0,					    AC_VERB_SET_COEF_INDEX, 7);				snd_hda_codec_write(codec, 0x20, 0,					    AC_VERB_SET_PROC_COEF,					    tmp | 0x3000);			break;		}	default:		break;

⌨️ 快捷键说明

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