File Index
Files and directories
Sign in
FILE

alc662.c

File preview with syntax highlighting.

linux-6.19.14/sound/hda/codecs/realtek/alc662.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2//
   3// Realtek ALC662 and compatible codecs
   4//
   5
   6#include <linux/init.h>
   7#include <linux/module.h>
   8#include "realtek.h"
   9
  10/*
  11 * ALC662 support
  12 *
  13 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
  14 * configuration.  Each pin widget can choose any input DACs and a mixer.
  15 * Each ADC is connected from a mixer of all inputs.  This makes possible
  16 * 6-channel independent captures.
  17 *
  18 * In addition, an independent DAC for the multi-playback (not used in this
  19 * driver yet).
  20 */
  21
  22/*
  23 * BIOS auto configuration
  24 */
  25
  26static int alc662_parse_auto_config(struct hda_codec *codec)
  27{
  28	static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
  29	static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
  30	static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
  31	const hda_nid_t *ssids;
  32
  33	if (codec->core.vendor_id == 0x10ec0272 || codec->core.vendor_id == 0x10ec0663 ||
  34	    codec->core.vendor_id == 0x10ec0665 || codec->core.vendor_id == 0x10ec0670 ||
  35	    codec->core.vendor_id == 0x10ec0671)
  36		ssids = alc663_ssids;
  37	else
  38		ssids = alc662_ssids;
  39	return alc_parse_auto_config(codec, alc662_ignore, ssids);
  40}
  41
  42static void alc272_fixup_mario(struct hda_codec *codec,
  43			       const struct hda_fixup *fix, int action)
  44{
  45	if (action != HDA_FIXUP_ACT_PRE_PROBE)
  46		return;
  47	if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
  48				      (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
  49				      (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
  50				      (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
  51				      (0 << AC_AMPCAP_MUTE_SHIFT)))
  52		codec_warn(codec, "failed to override amp caps for NID 0x2\n");
  53}
  54
  55/* avoid D3 for keeping GPIO up */
  56static unsigned int gpio_led_power_filter(struct hda_codec *codec,
  57					  hda_nid_t nid,
  58					  unsigned int power_state)
  59{
  60	struct alc_spec *spec = codec->spec;
  61	if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_data)
  62		return AC_PWRST_D0;
  63	return power_state;
  64}
  65
  66static void alc662_fixup_led_gpio1(struct hda_codec *codec,
  67				   const struct hda_fixup *fix, int action)
  68{
  69	struct alc_spec *spec = codec->spec;
  70
  71	alc_fixup_hp_gpio_led(codec, action, 0x01, 0);
  72	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
  73		spec->mute_led_polarity = 1;
  74		codec->power_filter = gpio_led_power_filter;
  75	}
  76}
  77
  78static void alc662_usi_automute_hook(struct hda_codec *codec,
  79					 struct hda_jack_callback *jack)
  80{
  81	struct alc_spec *spec = codec->spec;
  82	int vref;
  83	msleep(200);
  84	snd_hda_gen_hp_automute(codec, jack);
  85
  86	vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
  87	msleep(100);
  88	snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
  89			    vref);
  90}
  91
  92static void alc662_fixup_usi_headset_mic(struct hda_codec *codec,
  93				     const struct hda_fixup *fix, int action)
  94{
  95	struct alc_spec *spec = codec->spec;
  96	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
  97		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
  98		spec->gen.hp_automute_hook = alc662_usi_automute_hook;
  99	}
 100}
 101
 102static void alc662_aspire_ethos_mute_speakers(struct hda_codec *codec,
 103					struct hda_jack_callback *cb)
 104{
 105	/* surround speakers at 0x1b already get muted automatically when
 106	 * headphones are plugged in, but we have to mute/unmute the remaining
 107	 * channels manually:
 108	 * 0x15 - front left/front right
 109	 * 0x18 - front center/ LFE
 110	 */
 111	if (snd_hda_jack_detect_state(codec, 0x1b) == HDA_JACK_PRESENT) {
 112		snd_hda_set_pin_ctl_cache(codec, 0x15, 0);
 113		snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
 114	} else {
 115		snd_hda_set_pin_ctl_cache(codec, 0x15, PIN_OUT);
 116		snd_hda_set_pin_ctl_cache(codec, 0x18, PIN_OUT);
 117	}
 118}
 119
 120static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec,
 121					const struct hda_fixup *fix, int action)
 122{
 123    /* Pin 0x1b: shared headphones jack and surround speakers */
 124	if (!is_jack_detectable(codec, 0x1b))
 125		return;
 126
 127	switch (action) {
 128	case HDA_FIXUP_ACT_PRE_PROBE:
 129		snd_hda_jack_detect_enable_callback(codec, 0x1b,
 130				alc662_aspire_ethos_mute_speakers);
 131		/* subwoofer needs an extra GPIO setting to become audible */
 132		alc_setup_gpio(codec, 0x02);
 133		break;
 134	case HDA_FIXUP_ACT_INIT:
 135		/* Make sure to start in a correct state, i.e. if
 136		 * headphones have been plugged in before powering up the system
 137		 */
 138		alc662_aspire_ethos_mute_speakers(codec, NULL);
 139		break;
 140	}
 141}
 142
 143static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
 144					     const struct hda_fixup *fix, int action)
 145{
 146	struct alc_spec *spec = codec->spec;
 147
 148	static const struct hda_pintbl pincfgs[] = {
 149		{ 0x19, 0x02a11040 }, /* use as headset mic, with its own jack detect */
 150		{ 0x1b, 0x0181304f },
 151		{ }
 152	};
 153
 154	switch (action) {
 155	case HDA_FIXUP_ACT_PRE_PROBE:
 156		spec->gen.mixer_nid = 0;
 157		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
 158		snd_hda_apply_pincfgs(codec, pincfgs);
 159		break;
 160	case HDA_FIXUP_ACT_INIT:
 161		alc_write_coef_idx(codec, 0x19, 0xa054);
 162		break;
 163	}
 164}
 165
 166static void alc897_hp_automute_hook(struct hda_codec *codec,
 167					 struct hda_jack_callback *jack)
 168{
 169	struct alc_spec *spec = codec->spec;
 170	int vref;
 171
 172	snd_hda_gen_hp_automute(codec, jack);
 173	vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP;
 174	snd_hda_set_pin_ctl(codec, 0x1b, vref);
 175}
 176
 177static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec,
 178				     const struct hda_fixup *fix, int action)
 179{
 180	struct alc_spec *spec = codec->spec;
 181	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 182		spec->gen.hp_automute_hook = alc897_hp_automute_hook;
 183		spec->no_shutup_pins = 1;
 184	}
 185	if (action == HDA_FIXUP_ACT_PROBE) {
 186		snd_hda_set_pin_ctl_cache(codec, 0x1a, PIN_IN | AC_PINCTL_VREF_100);
 187	}
 188}
 189
 190static void alc897_fixup_lenovo_headset_mode(struct hda_codec *codec,
 191				     const struct hda_fixup *fix, int action)
 192{
 193	struct alc_spec *spec = codec->spec;
 194
 195	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 196		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
 197		spec->gen.hp_automute_hook = alc897_hp_automute_hook;
 198	}
 199}
 200
 201static const struct coef_fw alc668_coefs[] = {
 202	WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03,    0x0),
 203	WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06,    0x0), WRITE_COEF(0x07, 0x0f80),
 204	WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b,    0x0),
 205	WRITE_COEF(0x0c, 0x7cf7), WRITE_COEF(0x0d, 0x1080), WRITE_COEF(0x0e, 0x7f7f),
 206	WRITE_COEF(0x0f, 0xcccc), WRITE_COEF(0x10, 0xddcc), WRITE_COEF(0x11, 0x0001),
 207	WRITE_COEF(0x13,    0x0), WRITE_COEF(0x14, 0x2aa0), WRITE_COEF(0x17, 0xa940),
 208	WRITE_COEF(0x19,    0x0), WRITE_COEF(0x1a,    0x0), WRITE_COEF(0x1b,    0x0),
 209	WRITE_COEF(0x1c,    0x0), WRITE_COEF(0x1d,    0x0), WRITE_COEF(0x1e, 0x7418),
 210	WRITE_COEF(0x1f, 0x0804), WRITE_COEF(0x20, 0x4200), WRITE_COEF(0x21, 0x0468),
 211	WRITE_COEF(0x22, 0x8ccc), WRITE_COEF(0x23, 0x0250), WRITE_COEF(0x24, 0x7418),
 212	WRITE_COEF(0x27,    0x0), WRITE_COEF(0x28, 0x8ccc), WRITE_COEF(0x2a, 0xff00),
 213	WRITE_COEF(0x2b, 0x8000), WRITE_COEF(0xa7, 0xff00), WRITE_COEF(0xa8, 0x8000),
 214	WRITE_COEF(0xaa, 0x2e17), WRITE_COEF(0xab, 0xa0c0), WRITE_COEF(0xac,    0x0),
 215	WRITE_COEF(0xad,    0x0), WRITE_COEF(0xae, 0x2ac6), WRITE_COEF(0xaf, 0xa480),
 216	WRITE_COEF(0xb0,    0x0), WRITE_COEF(0xb1,    0x0), WRITE_COEF(0xb2,    0x0),
 217	WRITE_COEF(0xb3,    0x0), WRITE_COEF(0xb4,    0x0), WRITE_COEF(0xb5, 0x1040),
 218	WRITE_COEF(0xb6, 0xd697), WRITE_COEF(0xb7, 0x902b), WRITE_COEF(0xb8, 0xd697),
 219	WRITE_COEF(0xb9, 0x902b), WRITE_COEF(0xba, 0xb8ba), WRITE_COEF(0xbb, 0xaaab),
 220	WRITE_COEF(0xbc, 0xaaaf), WRITE_COEF(0xbd, 0x6aaa), WRITE_COEF(0xbe, 0x1c02),
 221	WRITE_COEF(0xc0, 0x00ff), WRITE_COEF(0xc1, 0x0fa6),
 222	{}
 223};
 224
 225static void alc668_restore_default_value(struct hda_codec *codec)
 226{
 227	alc_process_coef_fw(codec, alc668_coefs);
 228}
 229
 230static void alc_fixup_headset_mode_alc662(struct hda_codec *codec,
 231				const struct hda_fixup *fix, int action)
 232{
 233	struct alc_spec *spec = codec->spec;
 234
 235	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 236		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
 237		spec->gen.hp_mic = 1; /* Mic-in is same pin as headphone */
 238
 239		/* Disable boost for mic-in permanently. (This code is only called
 240		   from quirks that guarantee that the headphone is at NID 0x1b.) */
 241		snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000);
 242		snd_hda_override_wcaps(codec, 0x1b, get_wcaps(codec, 0x1b) & ~AC_WCAP_IN_AMP);
 243	} else
 244		alc_fixup_headset_mode(codec, fix, action);
 245}
 246
 247static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
 248				const struct hda_fixup *fix, int action)
 249{
 250	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 251		alc_write_coef_idx(codec, 0xc4, 0x8000);
 252		alc_update_coef_idx(codec, 0xc2, ~0xfe, 0);
 253		snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
 254	}
 255	alc_fixup_headset_mode(codec, fix, action);
 256}
 257
 258enum {
 259	ALC662_FIXUP_ASPIRE,
 260	ALC662_FIXUP_LED_GPIO1,
 261	ALC662_FIXUP_IDEAPAD,
 262	ALC272_FIXUP_MARIO,
 263	ALC662_FIXUP_CZC_ET26,
 264	ALC662_FIXUP_CZC_P10T,
 265	ALC662_FIXUP_SKU_IGNORE,
 266	ALC662_FIXUP_HP_RP5800,
 267	ALC662_FIXUP_ASUS_MODE1,
 268	ALC662_FIXUP_ASUS_MODE2,
 269	ALC662_FIXUP_ASUS_MODE3,
 270	ALC662_FIXUP_ASUS_MODE4,
 271	ALC662_FIXUP_ASUS_MODE5,
 272	ALC662_FIXUP_ASUS_MODE6,
 273	ALC662_FIXUP_ASUS_MODE7,
 274	ALC662_FIXUP_ASUS_MODE8,
 275	ALC662_FIXUP_NO_JACK_DETECT,
 276	ALC662_FIXUP_ZOTAC_Z68,
 277	ALC662_FIXUP_INV_DMIC,
 278	ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
 279	ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
 280	ALC662_FIXUP_HEADSET_MODE,
 281	ALC668_FIXUP_HEADSET_MODE,
 282	ALC662_FIXUP_BASS_MODE4_CHMAP,
 283	ALC662_FIXUP_BASS_16,
 284	ALC662_FIXUP_BASS_1A,
 285	ALC662_FIXUP_BASS_CHMAP,
 286	ALC668_FIXUP_AUTO_MUTE,
 287	ALC668_FIXUP_DELL_DISABLE_AAMIX,
 288	ALC668_FIXUP_DELL_XPS13,
 289	ALC662_FIXUP_ASUS_Nx50,
 290	ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
 291	ALC668_FIXUP_ASUS_Nx51,
 292	ALC668_FIXUP_MIC_COEF,
 293	ALC668_FIXUP_ASUS_G751,
 294	ALC891_FIXUP_HEADSET_MODE,
 295	ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
 296	ALC662_FIXUP_ACER_VERITON,
 297	ALC892_FIXUP_ASROCK_MOBO,
 298	ALC662_FIXUP_USI_FUNC,
 299	ALC662_FIXUP_USI_HEADSET_MODE,
 300	ALC662_FIXUP_LENOVO_MULTI_CODECS,
 301	ALC669_FIXUP_ACER_ASPIRE_ETHOS,
 302	ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET,
 303	ALC671_FIXUP_HP_HEADSET_MIC2,
 304	ALC662_FIXUP_ACER_X2660G_HEADSET_MODE,
 305	ALC662_FIXUP_ACER_NITRO_HEADSET_MODE,
 306	ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
 307	ALC668_FIXUP_HEADSET_MIC,
 308	ALC668_FIXUP_MIC_DET_COEF,
 309	ALC897_FIXUP_LENOVO_HEADSET_MIC,
 310	ALC897_FIXUP_HEADSET_MIC_PIN,
 311	ALC897_FIXUP_HP_HSMIC_VERB,
 312	ALC897_FIXUP_LENOVO_HEADSET_MODE,
 313	ALC897_FIXUP_HEADSET_MIC_PIN2,
 314	ALC897_FIXUP_UNIS_H3C_X500S,
 315	ALC897_FIXUP_HEADSET_MIC_PIN3,
 316};
 317
 318static const struct hda_fixup alc662_fixups[] = {
 319	[ALC662_FIXUP_ASPIRE] = {
 320		.type = HDA_FIXUP_PINS,
 321		.v.pins = (const struct hda_pintbl[]) {
 322			{ 0x15, 0x99130112 }, /* subwoofer */
 323			{ }
 324		}
 325	},
 326	[ALC662_FIXUP_LED_GPIO1] = {
 327		.type = HDA_FIXUP_FUNC,
 328		.v.func = alc662_fixup_led_gpio1,
 329	},
 330	[ALC662_FIXUP_IDEAPAD] = {
 331		.type = HDA_FIXUP_PINS,
 332		.v.pins = (const struct hda_pintbl[]) {
 333			{ 0x17, 0x99130112 }, /* subwoofer */
 334			{ }
 335		},
 336		.chained = true,
 337		.chain_id = ALC662_FIXUP_LED_GPIO1,
 338	},
 339	[ALC272_FIXUP_MARIO] = {
 340		.type = HDA_FIXUP_FUNC,
 341		.v.func = alc272_fixup_mario,
 342	},
 343	[ALC662_FIXUP_CZC_ET26] = {
 344		.type = HDA_FIXUP_PINS,
 345		.v.pins = (const struct hda_pintbl[]) {
 346			{0x12, 0x403cc000},
 347			{0x14, 0x90170110}, /* speaker */
 348			{0x15, 0x411111f0},
 349			{0x16, 0x411111f0},
 350			{0x18, 0x01a19030}, /* mic */
 351			{0x19, 0x90a7013f}, /* int-mic */
 352			{0x1a, 0x01014020},
 353			{0x1b, 0x0121401f},
 354			{0x1c, 0x411111f0},
 355			{0x1d, 0x411111f0},
 356			{0x1e, 0x40478e35},
 357			{}
 358		},
 359		.chained = true,
 360		.chain_id = ALC662_FIXUP_SKU_IGNORE
 361	},
 362	[ALC662_FIXUP_CZC_P10T] = {
 363		.type = HDA_FIXUP_VERBS,
 364		.v.verbs = (const struct hda_verb[]) {
 365			{0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
 366			{}
 367		}
 368	},
 369	[ALC662_FIXUP_SKU_IGNORE] = {
 370		.type = HDA_FIXUP_FUNC,
 371		.v.func = alc_fixup_sku_ignore,
 372	},
 373	[ALC662_FIXUP_HP_RP5800] = {
 374		.type = HDA_FIXUP_PINS,
 375		.v.pins = (const struct hda_pintbl[]) {
 376			{ 0x14, 0x0221201f }, /* HP out */
 377			{ }
 378		},
 379		.chained = true,
 380		.chain_id = ALC662_FIXUP_SKU_IGNORE
 381	},
 382	[ALC662_FIXUP_ASUS_MODE1] = {
 383		.type = HDA_FIXUP_PINS,
 384		.v.pins = (const struct hda_pintbl[]) {
 385			{ 0x14, 0x99130110 }, /* speaker */
 386			{ 0x18, 0x01a19c20 }, /* mic */
 387			{ 0x19, 0x99a3092f }, /* int-mic */
 388			{ 0x21, 0x0121401f }, /* HP out */
 389			{ }
 390		},
 391		.chained = true,
 392		.chain_id = ALC662_FIXUP_SKU_IGNORE
 393	},
 394	[ALC662_FIXUP_ASUS_MODE2] = {
 395		.type = HDA_FIXUP_PINS,
 396		.v.pins = (const struct hda_pintbl[]) {
 397			{ 0x14, 0x99130110 }, /* speaker */
 398			{ 0x18, 0x01a19820 }, /* mic */
 399			{ 0x19, 0x99a3092f }, /* int-mic */
 400			{ 0x1b, 0x0121401f }, /* HP out */
 401			{ }
 402		},
 403		.chained = true,
 404		.chain_id = ALC662_FIXUP_SKU_IGNORE
 405	},
 406	[ALC662_FIXUP_ASUS_MODE3] = {
 407		.type = HDA_FIXUP_PINS,
 408		.v.pins = (const struct hda_pintbl[]) {
 409			{ 0x14, 0x99130110 }, /* speaker */
 410			{ 0x15, 0x0121441f }, /* HP */
 411			{ 0x18, 0x01a19840 }, /* mic */
 412			{ 0x19, 0x99a3094f }, /* int-mic */
 413			{ 0x21, 0x01211420 }, /* HP2 */
 414			{ }
 415		},
 416		.chained = true,
 417		.chain_id = ALC662_FIXUP_SKU_IGNORE
 418	},
 419	[ALC662_FIXUP_ASUS_MODE4] = {
 420		.type = HDA_FIXUP_PINS,
 421		.v.pins = (const struct hda_pintbl[]) {
 422			{ 0x14, 0x99130110 }, /* speaker */
 423			{ 0x16, 0x99130111 }, /* speaker */
 424			{ 0x18, 0x01a19840 }, /* mic */
 425			{ 0x19, 0x99a3094f }, /* int-mic */
 426			{ 0x21, 0x0121441f }, /* HP */
 427			{ }
 428		},
 429		.chained = true,
 430		.chain_id = ALC662_FIXUP_SKU_IGNORE
 431	},
 432	[ALC662_FIXUP_ASUS_MODE5] = {
 433		.type = HDA_FIXUP_PINS,
 434		.v.pins = (const struct hda_pintbl[]) {
 435			{ 0x14, 0x99130110 }, /* speaker */
 436			{ 0x15, 0x0121441f }, /* HP */
 437			{ 0x16, 0x99130111 }, /* speaker */
 438			{ 0x18, 0x01a19840 }, /* mic */
 439			{ 0x19, 0x99a3094f }, /* int-mic */
 440			{ }
 441		},
 442		.chained = true,
 443		.chain_id = ALC662_FIXUP_SKU_IGNORE
 444	},
 445	[ALC662_FIXUP_ASUS_MODE6] = {
 446		.type = HDA_FIXUP_PINS,
 447		.v.pins = (const struct hda_pintbl[]) {
 448			{ 0x14, 0x99130110 }, /* speaker */
 449			{ 0x15, 0x01211420 }, /* HP2 */
 450			{ 0x18, 0x01a19840 }, /* mic */
 451			{ 0x19, 0x99a3094f }, /* int-mic */
 452			{ 0x1b, 0x0121441f }, /* HP */
 453			{ }
 454		},
 455		.chained = true,
 456		.chain_id = ALC662_FIXUP_SKU_IGNORE
 457	},
 458	[ALC662_FIXUP_ASUS_MODE7] = {
 459		.type = HDA_FIXUP_PINS,
 460		.v.pins = (const struct hda_pintbl[]) {
 461			{ 0x14, 0x99130110 }, /* speaker */
 462			{ 0x17, 0x99130111 }, /* speaker */
 463			{ 0x18, 0x01a19840 }, /* mic */
 464			{ 0x19, 0x99a3094f }, /* int-mic */
 465			{ 0x1b, 0x01214020 }, /* HP */
 466			{ 0x21, 0x0121401f }, /* HP */
 467			{ }
 468		},
 469		.chained = true,
 470		.chain_id = ALC662_FIXUP_SKU_IGNORE
 471	},
 472	[ALC662_FIXUP_ASUS_MODE8] = {
 473		.type = HDA_FIXUP_PINS,
 474		.v.pins = (const struct hda_pintbl[]) {
 475			{ 0x14, 0x99130110 }, /* speaker */
 476			{ 0x12, 0x99a30970 }, /* int-mic */
 477			{ 0x15, 0x01214020 }, /* HP */
 478			{ 0x17, 0x99130111 }, /* speaker */
 479			{ 0x18, 0x01a19840 }, /* mic */
 480			{ 0x21, 0x0121401f }, /* HP */
 481			{ }
 482		},
 483		.chained = true,
 484		.chain_id = ALC662_FIXUP_SKU_IGNORE
 485	},
 486	[ALC662_FIXUP_NO_JACK_DETECT] = {
 487		.type = HDA_FIXUP_FUNC,
 488		.v.func = alc_fixup_no_jack_detect,
 489	},
 490	[ALC662_FIXUP_ZOTAC_Z68] = {
 491		.type = HDA_FIXUP_PINS,
 492		.v.pins = (const struct hda_pintbl[]) {
 493			{ 0x1b, 0x02214020 }, /* Front HP */
 494			{ }
 495		}
 496	},
 497	[ALC662_FIXUP_INV_DMIC] = {
 498		.type = HDA_FIXUP_FUNC,
 499		.v.func = alc_fixup_inv_dmic,
 500	},
 501	[ALC668_FIXUP_DELL_XPS13] = {
 502		.type = HDA_FIXUP_FUNC,
 503		.v.func = alc_fixup_dell_xps13,
 504		.chained = true,
 505		.chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX
 506	},
 507	[ALC668_FIXUP_DELL_DISABLE_AAMIX] = {
 508		.type = HDA_FIXUP_FUNC,
 509		.v.func = alc_fixup_disable_aamix,
 510		.chained = true,
 511		.chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
 512	},
 513	[ALC668_FIXUP_AUTO_MUTE] = {
 514		.type = HDA_FIXUP_FUNC,
 515		.v.func = alc_fixup_auto_mute_via_amp,
 516		.chained = true,
 517		.chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
 518	},
 519	[ALC662_FIXUP_DELL_MIC_NO_PRESENCE] = {
 520		.type = HDA_FIXUP_PINS,
 521		.v.pins = (const struct hda_pintbl[]) {
 522			{ 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */
 523			/* headphone mic by setting pin control of 0x1b (headphone out) to in + vref_50 */
 524			{ }
 525		},
 526		.chained = true,
 527		.chain_id = ALC662_FIXUP_HEADSET_MODE
 528	},
 529	[ALC662_FIXUP_HEADSET_MODE] = {
 530		.type = HDA_FIXUP_FUNC,
 531		.v.func = alc_fixup_headset_mode_alc662,
 532	},
 533	[ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
 534		.type = HDA_FIXUP_PINS,
 535		.v.pins = (const struct hda_pintbl[]) {
 536			{ 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
 537			{ 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
 538			{ }
 539		},
 540		.chained = true,
 541		.chain_id = ALC668_FIXUP_HEADSET_MODE
 542	},
 543	[ALC668_FIXUP_HEADSET_MODE] = {
 544		.type = HDA_FIXUP_FUNC,
 545		.v.func = alc_fixup_headset_mode_alc668,
 546	},
 547	[ALC662_FIXUP_BASS_MODE4_CHMAP] = {
 548		.type = HDA_FIXUP_FUNC,
 549		.v.func = alc_fixup_bass_chmap,
 550		.chained = true,
 551		.chain_id = ALC662_FIXUP_ASUS_MODE4
 552	},
 553	[ALC662_FIXUP_BASS_16] = {
 554		.type = HDA_FIXUP_PINS,
 555		.v.pins = (const struct hda_pintbl[]) {
 556			{0x16, 0x80106111}, /* bass speaker */
 557			{}
 558		},
 559		.chained = true,
 560		.chain_id = ALC662_FIXUP_BASS_CHMAP,
 561	},
 562	[ALC662_FIXUP_BASS_1A] = {
 563		.type = HDA_FIXUP_PINS,
 564		.v.pins = (const struct hda_pintbl[]) {
 565			{0x1a, 0x80106111}, /* bass speaker */
 566			{}
 567		},
 568		.chained = true,
 569		.chain_id = ALC662_FIXUP_BASS_CHMAP,
 570	},
 571	[ALC662_FIXUP_BASS_CHMAP] = {
 572		.type = HDA_FIXUP_FUNC,
 573		.v.func = alc_fixup_bass_chmap,
 574	},
 575	[ALC662_FIXUP_ASUS_Nx50] = {
 576		.type = HDA_FIXUP_FUNC,
 577		.v.func = alc_fixup_auto_mute_via_amp,
 578		.chained = true,
 579		.chain_id = ALC662_FIXUP_BASS_1A
 580	},
 581	[ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE] = {
 582		.type = HDA_FIXUP_FUNC,
 583		.v.func = alc_fixup_headset_mode_alc668,
 584		.chain_id = ALC662_FIXUP_BASS_CHMAP
 585	},
 586	[ALC668_FIXUP_ASUS_Nx51] = {
 587		.type = HDA_FIXUP_PINS,
 588		.v.pins = (const struct hda_pintbl[]) {
 589			{ 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
 590			{ 0x1a, 0x90170151 }, /* bass speaker */
 591			{ 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
 592			{}
 593		},
 594		.chained = true,
 595		.chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
 596	},
 597	[ALC668_FIXUP_MIC_COEF] = {
 598		.type = HDA_FIXUP_VERBS,
 599		.v.verbs = (const struct hda_verb[]) {
 600			{ 0x20, AC_VERB_SET_COEF_INDEX, 0xc3 },
 601			{ 0x20, AC_VERB_SET_PROC_COEF, 0x4000 },
 602			{}
 603		},
 604	},
 605	[ALC668_FIXUP_ASUS_G751] = {
 606		.type = HDA_FIXUP_PINS,
 607		.v.pins = (const struct hda_pintbl[]) {
 608			{ 0x16, 0x0421101f }, /* HP */
 609			{}
 610		},
 611		.chained = true,
 612		.chain_id = ALC668_FIXUP_MIC_COEF
 613	},
 614	[ALC891_FIXUP_HEADSET_MODE] = {
 615		.type = HDA_FIXUP_FUNC,
 616		.v.func = alc_fixup_headset_mode,
 617	},
 618	[ALC891_FIXUP_DELL_MIC_NO_PRESENCE] = {
 619		.type = HDA_FIXUP_PINS,
 620		.v.pins = (const struct hda_pintbl[]) {
 621			{ 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
 622			{ 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
 623			{ }
 624		},
 625		.chained = true,
 626		.chain_id = ALC891_FIXUP_HEADSET_MODE
 627	},
 628	[ALC662_FIXUP_ACER_VERITON] = {
 629		.type = HDA_FIXUP_PINS,
 630		.v.pins = (const struct hda_pintbl[]) {
 631			{ 0x15, 0x50170120 }, /* no internal speaker */
 632			{ }
 633		}
 634	},
 635	[ALC892_FIXUP_ASROCK_MOBO] = {
 636		.type = HDA_FIXUP_PINS,
 637		.v.pins = (const struct hda_pintbl[]) {
 638			{ 0x15, 0x40f000f0 }, /* disabled */
 639			{ 0x16, 0x40f000f0 }, /* disabled */
 640			{ }
 641		}
 642	},
 643	[ALC662_FIXUP_USI_FUNC] = {
 644		.type = HDA_FIXUP_FUNC,
 645		.v.func = alc662_fixup_usi_headset_mic,
 646	},
 647	[ALC662_FIXUP_USI_HEADSET_MODE] = {
 648		.type = HDA_FIXUP_PINS,
 649		.v.pins = (const struct hda_pintbl[]) {
 650			{ 0x19, 0x02a1913c }, /* use as headset mic, without its own jack detect */
 651			{ 0x18, 0x01a1903d },
 652			{ }
 653		},
 654		.chained = true,
 655		.chain_id = ALC662_FIXUP_USI_FUNC
 656	},
 657	[ALC662_FIXUP_LENOVO_MULTI_CODECS] = {
 658		.type = HDA_FIXUP_FUNC,
 659		.v.func = alc233_alc662_fixup_lenovo_dual_codecs,
 660	},
 661	[ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET] = {
 662		.type = HDA_FIXUP_FUNC,
 663		.v.func = alc662_fixup_aspire_ethos_hp,
 664	},
 665	[ALC669_FIXUP_ACER_ASPIRE_ETHOS] = {
 666		.type = HDA_FIXUP_PINS,
 667		.v.pins = (const struct hda_pintbl[]) {
 668			{ 0x15, 0x92130110 }, /* front speakers */
 669			{ 0x18, 0x99130111 }, /* center/subwoofer */
 670			{ 0x1b, 0x11130012 }, /* surround plus jack for HP */
 671			{ }
 672		},
 673		.chained = true,
 674		.chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET
 675	},
 676	[ALC671_FIXUP_HP_HEADSET_MIC2] = {
 677		.type = HDA_FIXUP_FUNC,
 678		.v.func = alc671_fixup_hp_headset_mic2,
 679	},
 680	[ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = {
 681		.type = HDA_FIXUP_PINS,
 682		.v.pins = (const struct hda_pintbl[]) {
 683			{ 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */
 684			{ }
 685		},
 686		.chained = true,
 687		.chain_id = ALC662_FIXUP_USI_FUNC
 688	},
 689	[ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = {
 690		.type = HDA_FIXUP_PINS,
 691		.v.pins = (const struct hda_pintbl[]) {
 692			{ 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
 693			{ 0x1b, 0x0221144f },
 694			{ }
 695		},
 696		.chained = true,
 697		.chain_id = ALC662_FIXUP_USI_FUNC
 698	},
 699	[ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = {
 700		.type = HDA_FIXUP_PINS,
 701		.v.pins = (const struct hda_pintbl[]) {
 702			{ 0x1b, 0x04a1112c },
 703			{ }
 704		},
 705		.chained = true,
 706		.chain_id = ALC668_FIXUP_HEADSET_MIC
 707	},
 708	[ALC668_FIXUP_HEADSET_MIC] = {
 709		.type = HDA_FIXUP_FUNC,
 710		.v.func = alc_fixup_headset_mic,
 711		.chained = true,
 712		.chain_id = ALC668_FIXUP_MIC_DET_COEF
 713	},
 714	[ALC668_FIXUP_MIC_DET_COEF] = {
 715		.type = HDA_FIXUP_VERBS,
 716		.v.verbs = (const struct hda_verb[]) {
 717			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x15 },
 718			{ 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 },
 719			{}
 720		},
 721	},
 722	[ALC897_FIXUP_LENOVO_HEADSET_MIC] = {
 723		.type = HDA_FIXUP_FUNC,
 724		.v.func = alc897_fixup_lenovo_headset_mic,
 725	},
 726	[ALC897_FIXUP_HEADSET_MIC_PIN] = {
 727		.type = HDA_FIXUP_PINS,
 728		.v.pins = (const struct hda_pintbl[]) {
 729			{ 0x1a, 0x03a11050 },
 730			{ }
 731		},
 732		.chained = true,
 733		.chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
 734	},
 735	[ALC897_FIXUP_HP_HSMIC_VERB] = {
 736		.type = HDA_FIXUP_PINS,
 737		.v.pins = (const struct hda_pintbl[]) {
 738			{ 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
 739			{ }
 740		},
 741	},
 742	[ALC897_FIXUP_LENOVO_HEADSET_MODE] = {
 743		.type = HDA_FIXUP_FUNC,
 744		.v.func = alc897_fixup_lenovo_headset_mode,
 745	},
 746	[ALC897_FIXUP_HEADSET_MIC_PIN2] = {
 747		.type = HDA_FIXUP_PINS,
 748		.v.pins = (const struct hda_pintbl[]) {
 749			{ 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
 750			{ }
 751		},
 752		.chained = true,
 753		.chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE
 754	},
 755	[ALC897_FIXUP_UNIS_H3C_X500S] = {
 756		.type = HDA_FIXUP_VERBS,
 757		.v.verbs = (const struct hda_verb[]) {
 758			{ 0x14, AC_VERB_SET_EAPD_BTLENABLE, 0 },
 759			{}
 760		},
 761	},
 762	[ALC897_FIXUP_HEADSET_MIC_PIN3] = {
 763		.type = HDA_FIXUP_PINS,
 764		.v.pins = (const struct hda_pintbl[]) {
 765			{ 0x19, 0x03a11050 }, /* use as headset mic */
 766			{ }
 767		},
 768	},
 769};
 770
 771static const struct hda_quirk alc662_fixup_tbl[] = {
 772	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
 773	SND_PCI_QUIRK(0x1019, 0x9859, "JP-IK LEAP W502", ALC897_FIXUP_HEADSET_MIC_PIN3),
 774	SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
 775	SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
 776	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
 777	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
 778	SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
 779	SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
 780	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 781	SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
 782	SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE),
 783	SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE),
 784	SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 785	SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 786	SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
 787	SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
 788	SND_PCI_QUIRK(0x1028, 0x060d, "Dell M3800", ALC668_FIXUP_DELL_XPS13),
 789	SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 790	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 791	SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 792	SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 793	SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 794	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
 795	SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
 796	SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
 797	SND_PCI_QUIRK(0x103c, 0x872b, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
 798	SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
 799	SND_PCI_QUIRK(0x103c, 0x8768, "HP Slim Desktop S01", ALC671_FIXUP_HP_HEADSET_MIC2),
 800	SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2),
 801	SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
 802	SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
 803	SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
 804	SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
 805	SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751),
 806	SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
 807	SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
 808	SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
 809	SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
 810	SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
 811	SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC),
 812	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
 813	SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
 814	SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
 815	SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
 816	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
 817	SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
 818	SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
 819	SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
 820	SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
 821	SND_PCI_QUIRK(0x17aa, 0x1064, "Lenovo P3 Tower", ALC897_FIXUP_HEADSET_MIC_PIN),
 822	SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
 823	SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
 824	SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
 825	SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
 826	SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
 827	SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
 828	SND_PCI_QUIRK(0x17aa, 0x3364, "Lenovo ThinkCentre M90 Gen5", ALC897_FIXUP_HEADSET_MIC_PIN),
 829	SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
 830	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
 831	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
 832	SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
 833	SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
 834	SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
 835	SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
 836	SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
 837	SND_PCI_QUIRK(0x1c6c, 0x1239, "Compaq N14JP6-V2", ALC897_FIXUP_HP_HSMIC_VERB),
 838
 839#if 0
 840	/* Below is a quirk table taken from the old code.
 841	 * Basically the device should work as is without the fixup table.
 842	 * If BIOS doesn't give a proper info, enable the corresponding
 843	 * fixup entry.
 844	 */
 845	SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
 846	SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
 847	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
 848	SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
 849	SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
 850	SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 851	SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
 852	SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
 853	SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
 854	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 855	SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
 856	SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
 857	SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
 858	SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
 859	SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
 860	SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 861	SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
 862	SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
 863	SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 864	SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
 865	SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
 866	SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 867	SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
 868	SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
 869	SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
 870	SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 871	SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
 872	SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
 873	SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 874	SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
 875	SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 876	SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 877	SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
 878	SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
 879	SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
 880	SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
 881	SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
 882	SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
 883	SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
 884	SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
 885	SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
 886	SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
 887	SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
 888	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
 889	SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
 890	SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
 891	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
 892	SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
 893	SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
 894	SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
 895#endif
 896	{}
 897};
 898
 899static const struct hda_model_fixup alc662_fixup_models[] = {
 900	{.id = ALC662_FIXUP_ASPIRE, .name = "aspire"},
 901	{.id = ALC662_FIXUP_IDEAPAD, .name = "ideapad"},
 902	{.id = ALC272_FIXUP_MARIO, .name = "mario"},
 903	{.id = ALC662_FIXUP_HP_RP5800, .name = "hp-rp5800"},
 904	{.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
 905	{.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
 906	{.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
 907	{.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
 908	{.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
 909	{.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
 910	{.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
 911	{.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
 912	{.id = ALC662_FIXUP_ZOTAC_Z68, .name = "zotac-z68"},
 913	{.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
 914	{.id = ALC662_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc662-headset-multi"},
 915	{.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
 916	{.id = ALC662_FIXUP_HEADSET_MODE, .name = "alc662-headset"},
 917	{.id = ALC668_FIXUP_HEADSET_MODE, .name = "alc668-headset"},
 918	{.id = ALC662_FIXUP_BASS_16, .name = "bass16"},
 919	{.id = ALC662_FIXUP_BASS_1A, .name = "bass1a"},
 920	{.id = ALC668_FIXUP_AUTO_MUTE, .name = "automute"},
 921	{.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"},
 922	{.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"},
 923	{.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"},
 924	{.id = ALC668_FIXUP_ASUS_G751, .name = "asus-g751"},
 925	{.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"},
 926	{.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"},
 927	{.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"},
 928	{.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"},
 929	{.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"},
 930	{.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
 931	{.id = ALC669_FIXUP_ACER_ASPIRE_ETHOS, .name = "aspire-ethos"},
 932	{.id = ALC897_FIXUP_UNIS_H3C_X500S, .name = "unis-h3c-x500s"},
 933	{}
 934};
 935
 936static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
 937	SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
 938		{0x17, 0x02211010},
 939		{0x18, 0x01a19030},
 940		{0x1a, 0x01813040},
 941		{0x21, 0x01014020}),
 942	SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
 943		{0x16, 0x01813030},
 944		{0x17, 0x02211010},
 945		{0x18, 0x01a19040},
 946		{0x21, 0x01014020}),
 947	SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
 948		{0x14, 0x01014010},
 949		{0x18, 0x01a19020},
 950		{0x1a, 0x0181302f},
 951		{0x1b, 0x0221401f}),
 952	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
 953		{0x12, 0x99a30130},
 954		{0x14, 0x90170110},
 955		{0x15, 0x0321101f},
 956		{0x16, 0x03011020}),
 957	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
 958		{0x12, 0x99a30140},
 959		{0x14, 0x90170110},
 960		{0x15, 0x0321101f},
 961		{0x16, 0x03011020}),
 962	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
 963		{0x12, 0x99a30150},
 964		{0x14, 0x90170110},
 965		{0x15, 0x0321101f},
 966		{0x16, 0x03011020}),
 967	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
 968		{0x14, 0x90170110},
 969		{0x15, 0x0321101f},
 970		{0x16, 0x03011020}),
 971	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE,
 972		{0x12, 0x90a60130},
 973		{0x14, 0x90170110},
 974		{0x15, 0x0321101f}),
 975	SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
 976		{0x14, 0x01014010},
 977		{0x17, 0x90170150},
 978		{0x19, 0x02a11060},
 979		{0x1b, 0x01813030},
 980		{0x21, 0x02211020}),
 981	SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
 982		{0x14, 0x01014010},
 983		{0x18, 0x01a19040},
 984		{0x1b, 0x01813030},
 985		{0x21, 0x02211020}),
 986	SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
 987		{0x14, 0x01014020},
 988		{0x17, 0x90170110},
 989		{0x18, 0x01a19050},
 990		{0x1b, 0x01813040},
 991		{0x21, 0x02211030}),
 992	{}
 993};
 994
 995/*
 996 */
 997static int alc662_probe(struct hda_codec *codec, const struct hda_device_id *id)
 998{
 999	struct alc_spec *spec;
1000	int err;
1001
1002	err = alc_alloc_spec(codec, 0x0b);
1003	if (err < 0)
1004		return err;
1005
1006	spec = codec->spec;
1007
1008	spec->shutup = alc_eapd_shutup;
1009
1010	/* handle multiple HPs as is */
1011	spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
1012
1013	alc_fix_pll_init(codec, 0x20, 0x04, 15);
1014
1015	switch (codec->core.vendor_id) {
1016	case 0x10ec0668:
1017		spec->init_hook = alc668_restore_default_value;
1018		break;
1019	}
1020
1021	alc_pre_init(codec);
1022
1023	snd_hda_pick_fixup(codec, alc662_fixup_models,
1024		       alc662_fixup_tbl, alc662_fixups);
1025	snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups, true);
1026	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1027
1028	alc_auto_parse_customize_define(codec);
1029
1030	if (has_cdefine_beep(codec))
1031		spec->gen.beep_nid = 0x01;
1032
1033	if ((alc_get_coef0(codec) & (1 << 14)) &&
1034	    codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 &&
1035	    spec->cdefine.platform_type == 1) {
1036		err = alc_codec_rename(codec, "ALC272X");
1037		if (err < 0)
1038			goto error;
1039	}
1040
1041	/* automatic parse from the BIOS config */
1042	err = alc662_parse_auto_config(codec);
1043	if (err < 0)
1044		goto error;
1045
1046	if (!spec->gen.no_analog && spec->gen.beep_nid) {
1047		switch (codec->core.vendor_id) {
1048		case 0x10ec0662:
1049			err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
1050			break;
1051		case 0x10ec0272:
1052		case 0x10ec0663:
1053		case 0x10ec0665:
1054		case 0x10ec0668:
1055			err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
1056			break;
1057		case 0x10ec0273:
1058			err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
1059			break;
1060		}
1061		if (err < 0)
1062			goto error;
1063	}
1064
1065	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1066
1067	return 0;
1068
1069 error:
1070	snd_hda_gen_remove(codec);
1071	return err;
1072}
1073
1074static const struct hda_codec_ops alc662_codec_ops = {
1075	.probe = alc662_probe,
1076	.remove = snd_hda_gen_remove,
1077	.build_controls = alc_build_controls,
1078	.build_pcms = snd_hda_gen_build_pcms,
1079	.init = alc_init,
1080	.unsol_event = snd_hda_jack_unsol_event,
1081	.resume = alc_resume,
1082	.suspend = alc_suspend,
1083	.check_power_status = snd_hda_gen_check_power_status,
1084	.stream_pm = snd_hda_gen_stream_pm,
1085};
1086
1087/*
1088 * driver entries
1089 */
1090static const struct hda_device_id snd_hda_id_alc662[] = {
1091	HDA_CODEC_ID(0x10ec0272, "ALC272"),
1092	HDA_CODEC_ID_REV(0x10ec0662, 0x100101, "ALC662 rev1"),
1093	HDA_CODEC_ID_REV(0x10ec0662, 0x100300, "ALC662 rev3"),
1094	HDA_CODEC_ID(0x10ec0663, "ALC663"),
1095	HDA_CODEC_ID(0x10ec0665, "ALC665"),
1096	HDA_CODEC_ID(0x10ec0667, "ALC667"),
1097	HDA_CODEC_ID(0x10ec0668, "ALC668"),
1098	HDA_CODEC_ID(0x10ec0670, "ALC670"),
1099	HDA_CODEC_ID(0x10ec0671, "ALC671"),
1100	HDA_CODEC_ID(0x10ec0867, "ALC891"),
1101	HDA_CODEC_ID(0x10ec0892, "ALC892"),
1102	HDA_CODEC_ID(0x10ec0897, "ALC897"),
1103	{} /* terminator */
1104};
1105MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc662);
1106
1107MODULE_LICENSE("GPL");
1108MODULE_DESCRIPTION("Realtek ALC662 and compatible HD-audio codec");
1109MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
1110
1111static struct hda_codec_driver alc662_driver = {
1112	.id = snd_hda_id_alc662,
1113	.ops = &alc662_codec_ops,
1114};
1115
1116module_hda_codec_driver(alc662_driver);
~/ Read-only file preview.