diff options
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 170 | 
1 files changed, 154 insertions, 16 deletions
| diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c7730dbb9dd..aad1627f56f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -230,6 +230,7 @@ enum {  	ALC888_ACER_ASPIRE_7730G,  	ALC883_MEDION,  	ALC883_MEDION_MD2, +	ALC883_MEDION_WIM2160,  	ALC883_LAPTOP_EAPD,  	ALC883_LENOVO_101E_2ch,  	ALC883_LENOVO_NB0763, @@ -1389,22 +1390,31 @@ struct alc_fixup {  static void alc_pick_fixup(struct hda_codec *codec,  			   const struct snd_pci_quirk *quirk, -			   const struct alc_fixup *fix) +			   const struct alc_fixup *fix, +			   int pre_init)  {  	const struct alc_pincfg *cfg;  	quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);  	if (!quirk)  		return; -  	fix += quirk->value;  	cfg = fix->pins; -	if (cfg) { +	if (pre_init && cfg) { +#ifdef CONFIG_SND_DEBUG_VERBOSE +		snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", +			    codec->chip_name, quirk->name); +#endif  		for (; cfg->nid; cfg++)  			snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);  	} -	if (fix->verbs) +	if (!pre_init && fix->verbs) { +#ifdef CONFIG_SND_DEBUG_VERBOSE +		snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n", +			    codec->chip_name, quirk->name); +#endif  		add_verb(codec->spec, fix->verbs); +	}  }  static int alc_read_coef_idx(struct hda_codec *codec, @@ -4808,6 +4818,25 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec)  	}  } +static void alc880_auto_init_input_src(struct hda_codec *codec) +{ +	struct alc_spec *spec = codec->spec; +	int c; + +	for (c = 0; c < spec->num_adc_nids; c++) { +		unsigned int mux_idx; +		const struct hda_input_mux *imux; +		mux_idx = c >= spec->num_mux_defs ? 0 : c; +		imux = &spec->input_mux[mux_idx]; +		if (!imux->num_items && mux_idx > 0) +			imux = &spec->input_mux[0]; +		if (imux) +			snd_hda_codec_write(codec, spec->adc_nids[c], 0, +					    AC_VERB_SET_CONNECT_SEL, +					    imux->items[0].index); +	} +} +  /* parse the BIOS configuration and set up the alc_spec */  /* return 1 if successful, 0 if the proper config is not found,   * or a negative error code @@ -4886,6 +4915,7 @@ static void alc880_auto_init(struct hda_codec *codec)  	alc880_auto_init_multi_out(codec);  	alc880_auto_init_extra_out(codec);  	alc880_auto_init_analog_input(codec); +	alc880_auto_init_input_src(codec);  	if (spec->unsol_event)  		alc_inithook(codec);  } @@ -6397,6 +6427,8 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec)  	}  } +#define alc260_auto_init_input_src	alc880_auto_init_input_src +  /*   * generic initialization of ADC, input mixers and output mixers   */ @@ -6483,6 +6515,7 @@ static void alc260_auto_init(struct hda_codec *codec)  	struct alc_spec *spec = codec->spec;  	alc260_auto_init_multi_out(codec);  	alc260_auto_init_analog_input(codec); +	alc260_auto_init_input_src(codec);  	if (spec->unsol_event)  		alc_inithook(codec);  } @@ -8455,6 +8488,42 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {  	{ } /* end */  }; +static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = { +	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), +	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), +	HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT), +	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), +	HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT), +	HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT), +	{ } /* end */ +}; + +static struct hda_verb alc883_medion_wim2160_verbs[] = { +	/* Unmute front mixer */ +	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, +	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + +	/* Set speaker pin to front mixer */ +	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + +	/* Init headphone pin */ +	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, +	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, +	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, +	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + +	{ } /* end */ +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc883_medion_wim2160_setup(struct hda_codec *codec) +{ +	struct alc_spec *spec = codec->spec; + +	spec->autocfg.hp_pins[0] = 0x1a; +	spec->autocfg.speaker_pins[0] = 0x15; +} +  static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {  	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),  	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), @@ -9164,6 +9233,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {  	[ALC888_ACER_ASPIRE_7730G]	= "acer-aspire-7730g",  	[ALC883_MEDION]		= "medion",  	[ALC883_MEDION_MD2]	= "medion-md2", +	[ALC883_MEDION_WIM2160]	= "medion-wim2160",  	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",  	[ALC883_LENOVO_101E_2ch] = "lenovo-101e",  	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763", @@ -9280,6 +9350,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {  	SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),  	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), +	SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),  	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),  	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),  	SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R), @@ -9818,6 +9889,21 @@ static struct alc_config_preset alc882_presets[] = {  		.setup = alc883_medion_md2_setup,  		.init_hook = alc_automute_amp,  	}, +	[ALC883_MEDION_WIM2160] = { +		.mixers = { alc883_medion_wim2160_mixer }, +		.init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs }, +		.num_dacs = ARRAY_SIZE(alc883_dac_nids), +		.dac_nids = alc883_dac_nids, +		.dig_out_nid = ALC883_DIGOUT_NID, +		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids), +		.adc_nids = alc883_adc_nids, +		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), +		.channel_mode = alc883_3ST_2ch_modes, +		.input_mux = &alc883_capture_source, +		.unsol_event = alc_automute_amp_unsol_event, +		.setup = alc883_medion_wim2160_setup, +		.init_hook = alc_automute_amp, +	},  	[ALC883_LAPTOP_EAPD] = {  		.mixers = { alc883_base_mixer },  		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, @@ -10363,7 +10449,8 @@ static int patch_alc882(struct hda_codec *codec)  		board_config = ALC882_AUTO;  	} -	alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups); +	if (board_config == ALC882_AUTO) +		alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1);  	if (board_config == ALC882_AUTO) {  		/* automatic parse from the BIOS config */ @@ -10436,6 +10523,9 @@ static int patch_alc882(struct hda_codec *codec)  	set_capture_mixer(codec);  	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); +	if (board_config == ALC882_AUTO) +		alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0); +  	spec->vmaster_nid = 0x0c;  	codec->patch_ops = alc_patch_ops; @@ -12816,6 +12906,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,  		dac = 0x02;  		break;  	case 0x15: +	case 0x21: /* ALC269vb has this pin, too */  		dac = 0x03;  		break;  	default: @@ -13735,19 +13826,19 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec,  	}  } -static void alc269_laptop_dmic_setup(struct hda_codec *codec) +static void alc269_laptop_amic_setup(struct hda_codec *codec)  {  	struct alc_spec *spec = codec->spec;  	spec->autocfg.hp_pins[0] = 0x15;  	spec->autocfg.speaker_pins[0] = 0x14;  	spec->ext_mic.pin = 0x18;  	spec->ext_mic.mux_idx = 0; -	spec->int_mic.pin = 0x12; -	spec->int_mic.mux_idx = 5; +	spec->int_mic.pin = 0x19; +	spec->int_mic.mux_idx = 1;  	spec->auto_mic = 1;  } -static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) +static void alc269_laptop_dmic_setup(struct hda_codec *codec)  {  	struct alc_spec *spec = codec->spec;  	spec->autocfg.hp_pins[0] = 0x15; @@ -13755,14 +13846,14 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)  	spec->ext_mic.pin = 0x18;  	spec->ext_mic.mux_idx = 0;  	spec->int_mic.pin = 0x12; -	spec->int_mic.mux_idx = 6; +	spec->int_mic.mux_idx = 5;  	spec->auto_mic = 1;  } -static void alc269_laptop_amic_setup(struct hda_codec *codec) +static void alc269vb_laptop_amic_setup(struct hda_codec *codec)  {  	struct alc_spec *spec = codec->spec; -	spec->autocfg.hp_pins[0] = 0x15; +	spec->autocfg.hp_pins[0] = 0x21;  	spec->autocfg.speaker_pins[0] = 0x14;  	spec->ext_mic.pin = 0x18;  	spec->ext_mic.mux_idx = 0; @@ -13771,6 +13862,18 @@ static void alc269_laptop_amic_setup(struct hda_codec *codec)  	spec->auto_mic = 1;  } +static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) +{ +	struct alc_spec *spec = codec->spec; +	spec->autocfg.hp_pins[0] = 0x21; +	spec->autocfg.speaker_pins[0] = 0x14; +	spec->ext_mic.pin = 0x18; +	spec->ext_mic.mux_idx = 0; +	spec->int_mic.pin = 0x12; +	spec->int_mic.mux_idx = 6; +	spec->auto_mic = 1; +} +  static void alc269_laptop_inithook(struct hda_codec *codec)  {  	alc269_speaker_automute(codec); @@ -13975,6 +14078,27 @@ static void alc269_auto_init(struct hda_codec *codec)  		alc_inithook(codec);  } +enum { +	ALC269_FIXUP_SONY_VAIO, +}; + +const static struct hda_verb alc269_sony_vaio_fixup_verbs[] = { +	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, +	{} +}; + +static const struct alc_fixup alc269_fixups[] = { +	[ALC269_FIXUP_SONY_VAIO] = { +		.verbs = alc269_sony_vaio_fixup_verbs +	}, +}; + +static struct snd_pci_quirk alc269_fixup_tbl[] = { +	SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), +	{} +}; + +  /*   * configuration and preset   */ @@ -14034,7 +14158,7 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = {  		      ALC269_DMIC),  	SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),  	SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), -	SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC), +	SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),  	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),  	SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),  	SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), @@ -14108,7 +14232,7 @@ static struct alc_config_preset alc269_presets[] = {  		.num_channel_mode = ARRAY_SIZE(alc269_modes),  		.channel_mode = alc269_modes,  		.unsol_event = alc269_laptop_unsol_event, -		.setup = alc269_laptop_amic_setup, +		.setup = alc269vb_laptop_amic_setup,  		.init_hook = alc269_laptop_inithook,  	},  	[ALC269VB_DMIC] = { @@ -14188,6 +14312,9 @@ static int patch_alc269(struct hda_codec *codec)  		board_config = ALC269_AUTO;  	} +	if (board_config == ALC269_AUTO) +		alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 1); +  	if (board_config == ALC269_AUTO) {  		/* automatic parse from the BIOS config */  		err = alc269_parse_auto_config(codec); @@ -14240,6 +14367,9 @@ static int patch_alc269(struct hda_codec *codec)  		set_capture_mixer(codec);  	set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); +	if (board_config == ALC269_AUTO) +		alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0); +  	spec->vmaster_nid = 0x02;  	codec->patch_ops = alc_patch_ops; @@ -15328,7 +15458,8 @@ static int patch_alc861(struct hda_codec *codec)  		board_config = ALC861_AUTO;  	} -	alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups); +	if (board_config == ALC861_AUTO) +		alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 1);  	if (board_config == ALC861_AUTO) {  		/* automatic parse from the BIOS config */ @@ -15365,6 +15496,9 @@ static int patch_alc861(struct hda_codec *codec)  	spec->vmaster_nid = 0x03; +	if (board_config == ALC861_AUTO) +		alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 0); +  	codec->patch_ops = alc_patch_ops;  	if (board_config == ALC861_AUTO) {  		spec->init_hook = alc861_auto_init; @@ -16299,7 +16433,8 @@ static int patch_alc861vd(struct hda_codec *codec)  		board_config = ALC861VD_AUTO;  	} -	alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups); +	if (board_config == ALC861VD_AUTO) +		alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 1);  	if (board_config == ALC861VD_AUTO) {  		/* automatic parse from the BIOS config */ @@ -16347,6 +16482,9 @@ static int patch_alc861vd(struct hda_codec *codec)  	spec->vmaster_nid = 0x02; +	if (board_config == ALC861VD_AUTO) +		alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 0); +  	codec->patch_ops = alc_patch_ops;  	if (board_config == ALC861VD_AUTO) | 
