File Index
Files and directories
Sign in
FILE

realtek.c

File preview with syntax highlighting.

linux-6.19.14/sound/hda/codecs/realtek/realtek.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2//
   3// Realtek HD-audio codec support code
   4//
   5
   6#include <linux/init.h>
   7#include <linux/module.h>
   8#include "realtek.h"
   9
  10static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
  11				 unsigned int coef_idx)
  12{
  13	unsigned int val;
  14
  15	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
  16	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
  17	return val;
  18}
  19
  20int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
  21			unsigned int coef_idx)
  22{
  23	guard(coef_mutex)(codec);
  24	return __alc_read_coefex_idx(codec, nid, coef_idx);
  25}
  26EXPORT_SYMBOL_NS_GPL(alc_read_coefex_idx, "SND_HDA_CODEC_REALTEK");
  27
  28static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
  29				   unsigned int coef_idx, unsigned int coef_val)
  30{
  31	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
  32	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val);
  33}
  34
  35void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
  36			  unsigned int coef_idx, unsigned int coef_val)
  37{
  38	guard(coef_mutex)(codec);
  39	__alc_write_coefex_idx(codec, nid, coef_idx, coef_val);
  40}
  41EXPORT_SYMBOL_NS_GPL(alc_write_coefex_idx, "SND_HDA_CODEC_REALTEK");
  42
  43static void __alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
  44				    unsigned int coef_idx, unsigned int mask,
  45				    unsigned int bits_set)
  46{
  47	unsigned int val = __alc_read_coefex_idx(codec, nid, coef_idx);
  48
  49	if (val != -1)
  50		__alc_write_coefex_idx(codec, nid, coef_idx,
  51				       (val & ~mask) | bits_set);
  52}
  53
  54void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
  55			   unsigned int coef_idx, unsigned int mask,
  56			   unsigned int bits_set)
  57{
  58	guard(coef_mutex)(codec);
  59	__alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set);
  60}
  61EXPORT_SYMBOL_NS_GPL(alc_update_coefex_idx, "SND_HDA_CODEC_REALTEK");
  62
  63/* a special bypass for COEF 0; read the cached value at the second time */
  64unsigned int alc_get_coef0(struct hda_codec *codec)
  65{
  66	struct alc_spec *spec = codec->spec;
  67
  68	if (!spec->coef0)
  69		spec->coef0 = alc_read_coef_idx(codec, 0);
  70	return spec->coef0;
  71}
  72EXPORT_SYMBOL_NS_GPL(alc_get_coef0, "SND_HDA_CODEC_REALTEK");
  73
  74void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw)
  75{
  76	guard(coef_mutex)(codec);
  77	for (; fw->nid; fw++) {
  78		if (fw->mask == (unsigned short)-1)
  79			__alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val);
  80		else
  81			__alc_update_coefex_idx(codec, fw->nid, fw->idx,
  82						fw->mask, fw->val);
  83	}
  84}
  85EXPORT_SYMBOL_NS_GPL(alc_process_coef_fw, "SND_HDA_CODEC_REALTEK");
  86
  87/*
  88 * GPIO setup tables, used in initialization
  89 */
  90
  91/* Enable GPIO mask and set output */
  92void alc_setup_gpio(struct hda_codec *codec, unsigned int mask)
  93{
  94	struct alc_spec *spec = codec->spec;
  95
  96	spec->gpio_mask |= mask;
  97	spec->gpio_dir |= mask;
  98	spec->gpio_data |= mask;
  99}
 100EXPORT_SYMBOL_NS_GPL(alc_setup_gpio, "SND_HDA_CODEC_REALTEK");
 101
 102void alc_write_gpio_data(struct hda_codec *codec)
 103{
 104	struct alc_spec *spec = codec->spec;
 105
 106	snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
 107			    spec->gpio_data);
 108}
 109EXPORT_SYMBOL_NS_GPL(alc_write_gpio_data, "SND_HDA_CODEC_REALTEK");
 110
 111void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask,
 112			  bool on)
 113{
 114	struct alc_spec *spec = codec->spec;
 115	unsigned int oldval = spec->gpio_data;
 116
 117	if (on)
 118		spec->gpio_data |= mask;
 119	else
 120		spec->gpio_data &= ~mask;
 121	if (oldval != spec->gpio_data)
 122		alc_write_gpio_data(codec);
 123}
 124EXPORT_SYMBOL_NS_GPL(alc_update_gpio_data, "SND_HDA_CODEC_REALTEK");
 125
 126void alc_write_gpio(struct hda_codec *codec)
 127{
 128	struct alc_spec *spec = codec->spec;
 129
 130	if (!spec->gpio_mask)
 131		return;
 132
 133	snd_hda_codec_write(codec, codec->core.afg, 0,
 134			    AC_VERB_SET_GPIO_MASK, spec->gpio_mask);
 135	snd_hda_codec_write(codec, codec->core.afg, 0,
 136			    AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir);
 137	if (spec->gpio_write_delay)
 138		msleep(1);
 139	alc_write_gpio_data(codec);
 140}
 141EXPORT_SYMBOL_NS_GPL(alc_write_gpio, "SND_HDA_CODEC_REALTEK");
 142
 143void alc_fixup_gpio(struct hda_codec *codec, int action, unsigned int mask)
 144{
 145	if (action == HDA_FIXUP_ACT_PRE_PROBE)
 146		alc_setup_gpio(codec, mask);
 147}
 148EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio, "SND_HDA_CODEC_REALTEK");
 149
 150void alc_fixup_gpio1(struct hda_codec *codec,
 151		     const struct hda_fixup *fix, int action)
 152{
 153	alc_fixup_gpio(codec, action, 0x01);
 154}
 155EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio1, "SND_HDA_CODEC_REALTEK");
 156
 157void alc_fixup_gpio2(struct hda_codec *codec,
 158		     const struct hda_fixup *fix, int action)
 159{
 160	alc_fixup_gpio(codec, action, 0x02);
 161}
 162EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio2, "SND_HDA_CODEC_REALTEK");
 163
 164void alc_fixup_gpio3(struct hda_codec *codec,
 165		     const struct hda_fixup *fix, int action)
 166{
 167	alc_fixup_gpio(codec, action, 0x03);
 168}
 169EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio3, "SND_HDA_CODEC_REALTEK");
 170
 171void alc_fixup_gpio4(struct hda_codec *codec,
 172		     const struct hda_fixup *fix, int action)
 173{
 174	alc_fixup_gpio(codec, action, 0x04);
 175}
 176EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio4, "SND_HDA_CODEC_REALTEK");
 177
 178void alc_fixup_micmute_led(struct hda_codec *codec,
 179			   const struct hda_fixup *fix, int action)
 180{
 181	if (action == HDA_FIXUP_ACT_PRE_PROBE)
 182		snd_hda_gen_add_micmute_led_cdev(codec, NULL);
 183}
 184EXPORT_SYMBOL_NS_GPL(alc_fixup_micmute_led, "SND_HDA_CODEC_REALTEK");
 185
 186/*
 187 * Fix hardware PLL issue
 188 * On some codecs, the analog PLL gating control must be off while
 189 * the default value is 1.
 190 */
 191void alc_fix_pll(struct hda_codec *codec)
 192{
 193	struct alc_spec *spec = codec->spec;
 194
 195	if (spec->pll_nid)
 196		alc_update_coefex_idx(codec, spec->pll_nid, spec->pll_coef_idx,
 197				      1 << spec->pll_coef_bit, 0);
 198}
 199EXPORT_SYMBOL_NS_GPL(alc_fix_pll, "SND_HDA_CODEC_REALTEK");
 200
 201void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
 202		      unsigned int coef_idx, unsigned int coef_bit)
 203{
 204	struct alc_spec *spec = codec->spec;
 205	spec->pll_nid = nid;
 206	spec->pll_coef_idx = coef_idx;
 207	spec->pll_coef_bit = coef_bit;
 208	alc_fix_pll(codec);
 209}
 210EXPORT_SYMBOL_NS_GPL(alc_fix_pll_init, "SND_HDA_CODEC_REALTEK");
 211
 212/* update the master volume per volume-knob's unsol event */
 213void alc_update_knob_master(struct hda_codec *codec,
 214			    struct hda_jack_callback *jack)
 215{
 216	unsigned int val;
 217	struct snd_kcontrol *kctl;
 218
 219	kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
 220	if (!kctl)
 221		return;
 222
 223	struct snd_ctl_elem_value *uctl __free(kfree) =
 224		kzalloc(sizeof(*uctl), GFP_KERNEL);
 225	if (!uctl)
 226		return;
 227	val = snd_hda_codec_read(codec, jack->nid, 0,
 228				 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
 229	val &= HDA_AMP_VOLMASK;
 230	uctl->value.integer.value[0] = val;
 231	uctl->value.integer.value[1] = val;
 232	kctl->put(kctl, uctl);
 233}
 234EXPORT_SYMBOL_NS_GPL(alc_update_knob_master, "SND_HDA_CODEC_REALTEK");
 235
 236/* Change EAPD to verb control */
 237void alc_fill_eapd_coef(struct hda_codec *codec)
 238{
 239	int coef;
 240
 241	coef = alc_get_coef0(codec);
 242
 243	switch (codec->core.vendor_id) {
 244	case 0x10ec0262:
 245		alc_update_coef_idx(codec, 0x7, 0, 1<<5);
 246		break;
 247	case 0x10ec0267:
 248	case 0x10ec0268:
 249		alc_update_coef_idx(codec, 0x7, 0, 1<<13);
 250		break;
 251	case 0x10ec0269:
 252		if ((coef & 0x00f0) == 0x0010)
 253			alc_update_coef_idx(codec, 0xd, 0, 1<<14);
 254		if ((coef & 0x00f0) == 0x0020)
 255			alc_update_coef_idx(codec, 0x4, 1<<15, 0);
 256		if ((coef & 0x00f0) == 0x0030)
 257			alc_update_coef_idx(codec, 0x10, 1<<9, 0);
 258		break;
 259	case 0x10ec0280:
 260	case 0x10ec0284:
 261	case 0x10ec0290:
 262	case 0x10ec0292:
 263		alc_update_coef_idx(codec, 0x4, 1<<15, 0);
 264		break;
 265	case 0x10ec0225:
 266	case 0x10ec0295:
 267	case 0x10ec0299:
 268		alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
 269		fallthrough;
 270	case 0x10ec0215:
 271	case 0x10ec0236:
 272	case 0x10ec0245:
 273	case 0x10ec0256:
 274	case 0x10ec0257:
 275	case 0x10ec0285:
 276	case 0x10ec0289:
 277		alc_update_coef_idx(codec, 0x36, 1<<13, 0);
 278		fallthrough;
 279	case 0x10ec0230:
 280	case 0x10ec0233:
 281	case 0x10ec0235:
 282	case 0x10ec0255:
 283	case 0x19e58326:
 284	case 0x10ec0282:
 285	case 0x10ec0283:
 286	case 0x10ec0286:
 287	case 0x10ec0288:
 288	case 0x10ec0298:
 289	case 0x10ec0300:
 290		alc_update_coef_idx(codec, 0x10, 1<<9, 0);
 291		break;
 292	case 0x10ec0275:
 293		alc_update_coef_idx(codec, 0xe, 0, 1<<0);
 294		break;
 295	case 0x10ec0287:
 296		alc_update_coef_idx(codec, 0x10, 1<<9, 0);
 297		alc_write_coef_idx(codec, 0x8, 0x4ab7);
 298		break;
 299	case 0x10ec0293:
 300		alc_update_coef_idx(codec, 0xa, 1<<13, 0);
 301		break;
 302	case 0x10ec0234:
 303	case 0x10ec0274:
 304		alc_write_coef_idx(codec, 0x6e, 0x0c25);
 305		fallthrough;
 306	case 0x10ec0294:
 307	case 0x10ec0700:
 308	case 0x10ec0701:
 309	case 0x10ec0703:
 310	case 0x10ec0711:
 311		alc_update_coef_idx(codec, 0x10, 1<<15, 0);
 312		break;
 313	case 0x10ec0662:
 314		if ((coef & 0x00f0) == 0x0030)
 315			alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
 316		break;
 317	case 0x10ec0272:
 318	case 0x10ec0273:
 319	case 0x10ec0663:
 320	case 0x10ec0665:
 321	case 0x10ec0670:
 322	case 0x10ec0671:
 323	case 0x10ec0672:
 324		alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
 325		break;
 326	case 0x10ec0222:
 327	case 0x10ec0623:
 328		alc_update_coef_idx(codec, 0x19, 1<<13, 0);
 329		break;
 330	case 0x10ec0668:
 331		alc_update_coef_idx(codec, 0x7, 3<<13, 0);
 332		break;
 333	case 0x10ec0867:
 334		alc_update_coef_idx(codec, 0x4, 1<<10, 0);
 335		break;
 336	case 0x10ec0888:
 337		if ((coef & 0x00f0) == 0x0020 || (coef & 0x00f0) == 0x0030)
 338			alc_update_coef_idx(codec, 0x7, 1<<5, 0);
 339		break;
 340	case 0x10ec0892:
 341	case 0x10ec0897:
 342		alc_update_coef_idx(codec, 0x7, 1<<5, 0);
 343		break;
 344	case 0x10ec0899:
 345	case 0x10ec0900:
 346	case 0x10ec0b00:
 347	case 0x10ec1168:
 348	case 0x10ec1220:
 349		alc_update_coef_idx(codec, 0x7, 1<<1, 0);
 350		break;
 351	}
 352}
 353EXPORT_SYMBOL_NS_GPL(alc_fill_eapd_coef, "SND_HDA_CODEC_REALTEK");
 354
 355/* turn on/off EAPD control (only if available) */
 356static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
 357{
 358	if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
 359		return;
 360	if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
 361		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
 362				    on ? 2 : 0);
 363}
 364
 365/* turn on/off EAPD controls of the codec */
 366void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
 367{
 368	/* We currently only handle front, HP */
 369	static const hda_nid_t pins[] = {
 370		0x0f, 0x10, 0x14, 0x15, 0x17, 0
 371	};
 372	const hda_nid_t *p;
 373	for (p = pins; *p; p++)
 374		set_eapd(codec, *p, on);
 375}
 376EXPORT_SYMBOL_NS_GPL(alc_auto_setup_eapd, "SND_HDA_CODEC_REALTEK");
 377
 378/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
 379int alc_find_ext_mic_pin(struct hda_codec *codec)
 380{
 381	struct alc_spec *spec = codec->spec;
 382	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
 383	hda_nid_t nid;
 384	unsigned int defcfg;
 385	int i;
 386
 387	for (i = 0; i < cfg->num_inputs; i++) {
 388		if (cfg->inputs[i].type != AUTO_PIN_MIC)
 389			continue;
 390		nid = cfg->inputs[i].pin;
 391		defcfg = snd_hda_codec_get_pincfg(codec, nid);
 392		if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
 393			continue;
 394		return nid;
 395	}
 396
 397	return 0;
 398}
 399EXPORT_SYMBOL_NS_GPL(alc_find_ext_mic_pin, "SND_HDA_CODEC_REALTEK");
 400
 401void alc_headset_mic_no_shutup(struct hda_codec *codec)
 402{
 403	const struct hda_pincfg *pin;
 404	int mic_pin = alc_find_ext_mic_pin(codec);
 405	int i;
 406
 407	/* don't shut up pins when unloading the driver; otherwise it breaks
 408	 * the default pin setup at the next load of the driver
 409	 */
 410	if (codec->bus->shutdown)
 411		return;
 412
 413	snd_array_for_each(&codec->init_pins, i, pin) {
 414		/* use read here for syncing after issuing each verb */
 415		if (pin->nid != mic_pin)
 416			snd_hda_codec_read(codec, pin->nid, 0,
 417					AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
 418	}
 419
 420	codec->pins_shutup = 1;
 421}
 422EXPORT_SYMBOL_NS_GPL(alc_headset_mic_no_shutup, "SND_HDA_CODEC_REALTEK");
 423
 424void alc_shutup_pins(struct hda_codec *codec)
 425{
 426	struct alc_spec *spec = codec->spec;
 427
 428	if (spec->no_shutup_pins)
 429		return;
 430
 431	switch (codec->core.vendor_id) {
 432	case 0x10ec0236:
 433	case 0x10ec0256:
 434	case 0x10ec0257:
 435	case 0x19e58326:
 436	case 0x10ec0283:
 437	case 0x10ec0285:
 438	case 0x10ec0286:
 439	case 0x10ec0287:
 440	case 0x10ec0288:
 441	case 0x10ec0295:
 442	case 0x10ec0298:
 443		alc_headset_mic_no_shutup(codec);
 444		break;
 445	default:
 446		snd_hda_shutup_pins(codec);
 447		break;
 448	}
 449}
 450EXPORT_SYMBOL_NS_GPL(alc_shutup_pins, "SND_HDA_CODEC_REALTEK");
 451
 452/* generic shutup callback;
 453 * just turning off EAPD and a little pause for avoiding pop-noise
 454 */
 455void alc_eapd_shutup(struct hda_codec *codec)
 456{
 457	struct alc_spec *spec = codec->spec;
 458
 459	alc_auto_setup_eapd(codec, false);
 460	if (!spec->no_depop_delay)
 461		msleep(200);
 462	alc_shutup_pins(codec);
 463}
 464EXPORT_SYMBOL_NS_GPL(alc_eapd_shutup, "SND_HDA_CODEC_REALTEK");
 465
 466/* additional initialization for ALC888 variants */
 467static void alc888_coef_init(struct hda_codec *codec)
 468{
 469	switch (alc_get_coef0(codec) & 0x00f0) {
 470	/* alc888-VA */
 471	case 0x00:
 472	/* alc888-VB */
 473	case 0x10:
 474		alc_update_coef_idx(codec, 7, 0, 0x2030); /* Turn EAPD to High */
 475		break;
 476	}
 477}
 478
 479/* generic EAPD initialization */
 480void alc_auto_init_amp(struct hda_codec *codec, int type)
 481{
 482	alc_auto_setup_eapd(codec, true);
 483	alc_write_gpio(codec);
 484	switch (type) {
 485	case ALC_INIT_DEFAULT:
 486		switch (codec->core.vendor_id) {
 487		case 0x10ec0260:
 488			alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
 489			break;
 490		case 0x10ec0880:
 491		case 0x10ec0882:
 492		case 0x10ec0883:
 493		case 0x10ec0885:
 494			alc_update_coef_idx(codec, 7, 0, 0x2030);
 495			break;
 496		case 0x10ec0888:
 497			alc888_coef_init(codec);
 498			break;
 499		}
 500		break;
 501	}
 502}
 503EXPORT_SYMBOL_NS_GPL(alc_auto_init_amp, "SND_HDA_CODEC_REALTEK");
 504
 505/* get a primary headphone pin if available */
 506hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
 507{
 508	if (spec->gen.autocfg.hp_pins[0])
 509		return spec->gen.autocfg.hp_pins[0];
 510	if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
 511		return spec->gen.autocfg.line_out_pins[0];
 512	return 0;
 513}
 514EXPORT_SYMBOL_NS_GPL(alc_get_hp_pin, "SND_HDA_CODEC_REALTEK");
 515
 516/*
 517 * Realtek SSID verification
 518 */
 519
 520/* Could be any non-zero and even value. When used as fixup, tells
 521 * the driver to ignore any present sku defines.
 522 */
 523#define ALC_FIXUP_SKU_IGNORE (2)
 524
 525void alc_fixup_sku_ignore(struct hda_codec *codec,
 526			  const struct hda_fixup *fix, int action)
 527{
 528	struct alc_spec *spec = codec->spec;
 529	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 530		spec->cdefine.fixup = 1;
 531		spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
 532	}
 533}
 534EXPORT_SYMBOL_NS_GPL(alc_fixup_sku_ignore, "SND_HDA_CODEC_REALTEK");
 535
 536void alc_fixup_no_depop_delay(struct hda_codec *codec,
 537			      const struct hda_fixup *fix, int action)
 538{
 539	struct alc_spec *spec = codec->spec;
 540
 541	if (action == HDA_FIXUP_ACT_PROBE) {
 542		spec->no_depop_delay = 1;
 543		codec->depop_delay = 0;
 544	}
 545}
 546EXPORT_SYMBOL_NS_GPL(alc_fixup_no_depop_delay, "SND_HDA_CODEC_REALTEK");
 547
 548int alc_auto_parse_customize_define(struct hda_codec *codec)
 549{
 550	unsigned int ass, tmp, i;
 551	unsigned nid = 0;
 552	struct alc_spec *spec = codec->spec;
 553
 554	spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
 555
 556	if (spec->cdefine.fixup) {
 557		ass = spec->cdefine.sku_cfg;
 558		if (ass == ALC_FIXUP_SKU_IGNORE)
 559			return -1;
 560		goto do_sku;
 561	}
 562
 563	if (!codec->bus->pci)
 564		return -1;
 565	ass = codec->core.subsystem_id & 0xffff;
 566	if (ass != codec->bus->pci->subsystem_device && (ass & 1))
 567		goto do_sku;
 568
 569	nid = 0x1d;
 570	if (codec->core.vendor_id == 0x10ec0260)
 571		nid = 0x17;
 572	ass = snd_hda_codec_get_pincfg(codec, nid);
 573
 574	if (!(ass & 1)) {
 575		codec_info(codec, "%s: SKU not ready 0x%08x\n",
 576			   codec->core.chip_name, ass);
 577		return -1;
 578	}
 579
 580	/* check sum */
 581	tmp = 0;
 582	for (i = 1; i < 16; i++) {
 583		if ((ass >> i) & 1)
 584			tmp++;
 585	}
 586	if (((ass >> 16) & 0xf) != tmp)
 587		return -1;
 588
 589	spec->cdefine.port_connectivity = ass >> 30;
 590	spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
 591	spec->cdefine.check_sum = (ass >> 16) & 0xf;
 592	spec->cdefine.customization = ass >> 8;
 593do_sku:
 594	spec->cdefine.sku_cfg = ass;
 595	spec->cdefine.external_amp = (ass & 0x38) >> 3;
 596	spec->cdefine.platform_type = (ass & 0x4) >> 2;
 597	spec->cdefine.swap = (ass & 0x2) >> 1;
 598	spec->cdefine.override = ass & 0x1;
 599
 600	codec_dbg(codec, "SKU: Nid=0x%x sku_cfg=0x%08x\n",
 601		   nid, spec->cdefine.sku_cfg);
 602	codec_dbg(codec, "SKU: port_connectivity=0x%x\n",
 603		   spec->cdefine.port_connectivity);
 604	codec_dbg(codec, "SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
 605	codec_dbg(codec, "SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
 606	codec_dbg(codec, "SKU: customization=0x%08x\n", spec->cdefine.customization);
 607	codec_dbg(codec, "SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
 608	codec_dbg(codec, "SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
 609	codec_dbg(codec, "SKU: swap=0x%x\n", spec->cdefine.swap);
 610	codec_dbg(codec, "SKU: override=0x%x\n", spec->cdefine.override);
 611
 612	return 0;
 613}
 614EXPORT_SYMBOL_NS_GPL(alc_auto_parse_customize_define, "SND_HDA_CODEC_REALTEK");
 615
 616/* return the position of NID in the list, or -1 if not found */
 617static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
 618{
 619	int i;
 620	for (i = 0; i < nums; i++)
 621		if (list[i] == nid)
 622			return i;
 623	return -1;
 624}
 625/* return true if the given NID is found in the list */
 626static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
 627{
 628	return find_idx_in_nid_list(nid, list, nums) >= 0;
 629}
 630
 631/* check subsystem ID and set up device-specific initialization;
 632 * return 1 if initialized, 0 if invalid SSID
 633 */
 634/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
 635 *	31 ~ 16 :	Manufacture ID
 636 *	15 ~ 8	:	SKU ID
 637 *	7  ~ 0	:	Assembly ID
 638 *	port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
 639 */
 640int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
 641{
 642	unsigned int ass, tmp, i;
 643	unsigned nid;
 644	struct alc_spec *spec = codec->spec;
 645
 646	if (spec->cdefine.fixup) {
 647		ass = spec->cdefine.sku_cfg;
 648		if (ass == ALC_FIXUP_SKU_IGNORE)
 649			return 0;
 650		goto do_sku;
 651	}
 652
 653	ass = codec->core.subsystem_id & 0xffff;
 654	if (codec->bus->pci &&
 655	    ass != codec->bus->pci->subsystem_device && (ass & 1))
 656		goto do_sku;
 657
 658	/* invalid SSID, check the special NID pin defcfg instead */
 659	/*
 660	 * 31~30	: port connectivity
 661	 * 29~21	: reserve
 662	 * 20		: PCBEEP input
 663	 * 19~16	: Check sum (15:1)
 664	 * 15~1		: Custom
 665	 * 0		: override
 666	*/
 667	nid = 0x1d;
 668	if (codec->core.vendor_id == 0x10ec0260)
 669		nid = 0x17;
 670	ass = snd_hda_codec_get_pincfg(codec, nid);
 671	codec_dbg(codec,
 672		  "realtek: No valid SSID, checking pincfg 0x%08x for NID 0x%x\n",
 673		   ass, nid);
 674	if (!(ass & 1))
 675		return 0;
 676	if ((ass >> 30) != 1)	/* no physical connection */
 677		return 0;
 678
 679	/* check sum */
 680	tmp = 0;
 681	for (i = 1; i < 16; i++) {
 682		if ((ass >> i) & 1)
 683			tmp++;
 684	}
 685	if (((ass >> 16) & 0xf) != tmp)
 686		return 0;
 687do_sku:
 688	codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
 689		   ass & 0xffff, codec->core.vendor_id);
 690	/*
 691	 * 0 : override
 692	 * 1 :	Swap Jack
 693	 * 2 : 0 --> Desktop, 1 --> Laptop
 694	 * 3~5 : External Amplifier control
 695	 * 7~6 : Reserved
 696	*/
 697	tmp = (ass & 0x38) >> 3;	/* external Amp control */
 698	if (spec->init_amp == ALC_INIT_UNDEFINED) {
 699		switch (tmp) {
 700		case 1:
 701			alc_setup_gpio(codec, 0x01);
 702			break;
 703		case 3:
 704			alc_setup_gpio(codec, 0x02);
 705			break;
 706		case 7:
 707			alc_setup_gpio(codec, 0x04);
 708			break;
 709		case 5:
 710		default:
 711			spec->init_amp = ALC_INIT_DEFAULT;
 712			break;
 713		}
 714	}
 715
 716	/* is laptop or Desktop and enable the function "Mute internal speaker
 717	 * when the external headphone out jack is plugged"
 718	 */
 719	if (!(ass & 0x8000))
 720		return 1;
 721	/*
 722	 * 10~8 : Jack location
 723	 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
 724	 * 14~13: Resvered
 725	 * 15   : 1 --> enable the function "Mute internal speaker
 726	 *	        when the external headphone out jack is plugged"
 727	 */
 728	if (!alc_get_hp_pin(spec)) {
 729		hda_nid_t nid;
 730		tmp = (ass >> 11) & 0x3;	/* HP to chassis */
 731		nid = ports[tmp];
 732		if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
 733				      spec->gen.autocfg.line_outs))
 734			return 1;
 735		spec->gen.autocfg.hp_pins[0] = nid;
 736	}
 737	return 1;
 738}
 739EXPORT_SYMBOL_NS_GPL(alc_subsystem_id, "SND_HDA_CODEC_REALTEK");
 740
 741/* Check the validity of ALC subsystem-id
 742 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
 743void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
 744{
 745	if (!alc_subsystem_id(codec, ports)) {
 746		struct alc_spec *spec = codec->spec;
 747		if (spec->init_amp == ALC_INIT_UNDEFINED) {
 748			codec_dbg(codec,
 749				  "realtek: Enable default setup for auto mode as fallback\n");
 750			spec->init_amp = ALC_INIT_DEFAULT;
 751		}
 752	}
 753}
 754EXPORT_SYMBOL_NS_GPL(alc_ssid_check, "SND_HDA_CODEC_REALTEK");
 755
 756/* inverted digital-mic */
 757void alc_fixup_inv_dmic(struct hda_codec *codec,
 758			const struct hda_fixup *fix, int action)
 759{
 760	struct alc_spec *spec = codec->spec;
 761
 762	spec->gen.inv_dmic_split = 1;
 763}
 764EXPORT_SYMBOL_NS_GPL(alc_fixup_inv_dmic, "SND_HDA_CODEC_REALTEK");
 765
 766int alc_build_controls(struct hda_codec *codec)
 767{
 768	int err;
 769
 770	err = snd_hda_gen_build_controls(codec);
 771	if (err < 0)
 772		return err;
 773
 774	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
 775	return 0;
 776}
 777EXPORT_SYMBOL_NS_GPL(alc_build_controls, "SND_HDA_CODEC_REALTEK");
 778
 779int alc_init(struct hda_codec *codec)
 780{
 781	struct alc_spec *spec = codec->spec;
 782
 783	/* hibernation resume needs the full chip initialization */
 784	if (is_s4_resume(codec))
 785		alc_pre_init(codec);
 786
 787	if (spec->init_hook)
 788		spec->init_hook(codec);
 789
 790	spec->gen.skip_verbs = 1; /* applied in below */
 791	snd_hda_gen_init(codec);
 792	alc_fix_pll(codec);
 793	alc_auto_init_amp(codec, spec->init_amp);
 794	snd_hda_apply_verbs(codec); /* apply verbs here after own init */
 795
 796	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
 797
 798	return 0;
 799}
 800EXPORT_SYMBOL_NS_GPL(alc_init, "SND_HDA_CODEC_REALTEK");
 801
 802void alc_shutup(struct hda_codec *codec)
 803{
 804	struct alc_spec *spec = codec->spec;
 805
 806	if (!snd_hda_get_bool_hint(codec, "shutup"))
 807		return; /* disabled explicitly by hints */
 808
 809	if (spec && spec->shutup)
 810		spec->shutup(codec);
 811	else
 812		alc_shutup_pins(codec);
 813}
 814EXPORT_SYMBOL_NS_GPL(alc_shutup, "SND_HDA_CODEC_REALTEK");
 815
 816void alc_power_eapd(struct hda_codec *codec)
 817{
 818	alc_auto_setup_eapd(codec, false);
 819}
 820EXPORT_SYMBOL_NS_GPL(alc_power_eapd, "SND_HDA_CODEC_REALTEK");
 821
 822int alc_suspend(struct hda_codec *codec)
 823{
 824	struct alc_spec *spec = codec->spec;
 825	alc_shutup(codec);
 826	if (spec && spec->power_hook)
 827		spec->power_hook(codec);
 828	return 0;
 829}
 830EXPORT_SYMBOL_NS_GPL(alc_suspend, "SND_HDA_CODEC_REALTEK");
 831
 832int alc_resume(struct hda_codec *codec)
 833{
 834	struct alc_spec *spec = codec->spec;
 835
 836	if (!spec->no_depop_delay)
 837		msleep(150); /* to avoid pop noise */
 838	snd_hda_codec_init(codec);
 839	snd_hda_regmap_sync(codec);
 840	hda_call_check_power_status(codec, 0x01);
 841	return 0;
 842}
 843EXPORT_SYMBOL_NS_GPL(alc_resume, "SND_HDA_CODEC_REALTEK");
 844
 845/*
 846 * Rename codecs appropriately from COEF value or subvendor id
 847 */
 848struct alc_codec_rename_table {
 849	unsigned int vendor_id;
 850	unsigned short coef_mask;
 851	unsigned short coef_bits;
 852	const char *name;
 853};
 854
 855struct alc_codec_rename_pci_table {
 856	unsigned int codec_vendor_id;
 857	unsigned short pci_subvendor;
 858	unsigned short pci_subdevice;
 859	const char *name;
 860};
 861
 862static const struct alc_codec_rename_table rename_tbl[] = {
 863	{ 0x10ec0221, 0xf00f, 0x1003, "ALC231" },
 864	{ 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
 865	{ 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
 866	{ 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
 867	{ 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
 868	{ 0x10ec0269, 0xffff, 0xa023, "ALC259" },
 869	{ 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
 870	{ 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
 871	{ 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
 872	{ 0x10ec0662, 0xffff, 0x4020, "ALC656" },
 873	{ 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
 874	{ 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
 875	{ 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
 876	{ 0x10ec0899, 0x2000, 0x2000, "ALC899" },
 877	{ 0x10ec0892, 0xffff, 0x8020, "ALC661" },
 878	{ 0x10ec0892, 0xffff, 0x8011, "ALC661" },
 879	{ 0x10ec0892, 0xffff, 0x4011, "ALC656" },
 880	{ } /* terminator */
 881};
 882
 883static const struct alc_codec_rename_pci_table rename_pci_tbl[] = {
 884	{ 0x10ec0280, 0x1028, 0, "ALC3220" },
 885	{ 0x10ec0282, 0x1028, 0, "ALC3221" },
 886	{ 0x10ec0283, 0x1028, 0, "ALC3223" },
 887	{ 0x10ec0288, 0x1028, 0, "ALC3263" },
 888	{ 0x10ec0292, 0x1028, 0, "ALC3226" },
 889	{ 0x10ec0293, 0x1028, 0, "ALC3235" },
 890	{ 0x10ec0255, 0x1028, 0, "ALC3234" },
 891	{ 0x10ec0668, 0x1028, 0, "ALC3661" },
 892	{ 0x10ec0275, 0x1028, 0, "ALC3260" },
 893	{ 0x10ec0899, 0x1028, 0, "ALC3861" },
 894	{ 0x10ec0298, 0x1028, 0, "ALC3266" },
 895	{ 0x10ec0236, 0x1028, 0, "ALC3204" },
 896	{ 0x10ec0256, 0x1028, 0, "ALC3246" },
 897	{ 0x10ec0225, 0x1028, 0, "ALC3253" },
 898	{ 0x10ec0295, 0x1028, 0, "ALC3254" },
 899	{ 0x10ec0299, 0x1028, 0, "ALC3271" },
 900	{ 0x10ec0670, 0x1025, 0, "ALC669X" },
 901	{ 0x10ec0676, 0x1025, 0, "ALC679X" },
 902	{ 0x10ec0282, 0x1043, 0, "ALC3229" },
 903	{ 0x10ec0233, 0x1043, 0, "ALC3236" },
 904	{ 0x10ec0280, 0x103c, 0, "ALC3228" },
 905	{ 0x10ec0282, 0x103c, 0, "ALC3227" },
 906	{ 0x10ec0286, 0x103c, 0, "ALC3242" },
 907	{ 0x10ec0290, 0x103c, 0, "ALC3241" },
 908	{ 0x10ec0668, 0x103c, 0, "ALC3662" },
 909	{ 0x10ec0283, 0x17aa, 0, "ALC3239" },
 910	{ 0x10ec0292, 0x17aa, 0, "ALC3232" },
 911	{ 0x10ec0257, 0x12f0, 0, "ALC3328" },
 912	{ } /* terminator */
 913};
 914
 915static int alc_codec_rename_from_preset(struct hda_codec *codec)
 916{
 917	const struct alc_codec_rename_table *p;
 918	const struct alc_codec_rename_pci_table *q;
 919
 920	for (p = rename_tbl; p->vendor_id; p++) {
 921		if (p->vendor_id != codec->core.vendor_id)
 922			continue;
 923		if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
 924			return alc_codec_rename(codec, p->name);
 925	}
 926
 927	if (!codec->bus->pci)
 928		return 0;
 929	for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
 930		if (q->codec_vendor_id != codec->core.vendor_id)
 931			continue;
 932		if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
 933			continue;
 934		if (!q->pci_subdevice ||
 935		    q->pci_subdevice == codec->bus->pci->subsystem_device)
 936			return alc_codec_rename(codec, q->name);
 937	}
 938
 939	return 0;
 940}
 941
 942/*
 943 * Digital-beep handlers
 944 */
 945#ifdef CONFIG_SND_HDA_INPUT_BEEP
 946
 947/* additional beep mixers; private_value will be overwritten */
 948static const struct snd_kcontrol_new alc_beep_mixer[] = {
 949	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
 950	HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
 951};
 952
 953/* set up and create beep controls */
 954int alc_set_beep_amp(struct alc_spec *spec, hda_nid_t nid, int idx, int dir)
 955{
 956	struct snd_kcontrol_new *knew;
 957	unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
 958	int i;
 959
 960	for (i = 0; i < ARRAY_SIZE(alc_beep_mixer); i++) {
 961		knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
 962					    &alc_beep_mixer[i]);
 963		if (!knew)
 964			return -ENOMEM;
 965		knew->private_value = beep_amp;
 966	}
 967	return 0;
 968}
 969EXPORT_SYMBOL_NS_GPL(alc_set_beep_amp, "SND_HDA_CODEC_REALTEK");
 970
 971static const struct snd_pci_quirk beep_allow_list[] = {
 972	SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
 973	SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1),
 974	SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
 975	SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
 976	SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
 977	SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
 978	SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
 979	SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
 980	SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
 981	/* denylist -- no beep available */
 982	SND_PCI_QUIRK(0x17aa, 0x309e, "Lenovo ThinkCentre M73", 0),
 983	SND_PCI_QUIRK(0x17aa, 0x30a3, "Lenovo ThinkCentre M93", 0),
 984	{}
 985};
 986
 987int alc_has_cdefine_beep(struct hda_codec *codec)
 988{
 989	struct alc_spec *spec = codec->spec;
 990	const struct snd_pci_quirk *q;
 991	q = snd_pci_quirk_lookup(codec->bus->pci, beep_allow_list);
 992	if (q)
 993		return q->value;
 994	return spec->cdefine.enable_pcbeep;
 995}
 996EXPORT_SYMBOL_NS_GPL(alc_has_cdefine_beep, "SND_HDA_CODEC_REALTEK");
 997
 998#endif /* CONFIG_SND_HDA_INPUT_BEEP */
 999
1000/* parse the BIOS configuration and set up the alc_spec */
1001/* return 1 if successful, 0 if the proper config is not found,
1002 * or a negative error code
1003 */
1004int alc_parse_auto_config(struct hda_codec *codec,
1005			  const hda_nid_t *ignore_nids,
1006			  const hda_nid_t *ssid_nids)
1007{
1008	struct alc_spec *spec = codec->spec;
1009	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
1010	int err;
1011
1012	err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
1013				       spec->parse_flags);
1014	if (err < 0)
1015		return err;
1016
1017	if (ssid_nids)
1018		alc_ssid_check(codec, ssid_nids);
1019
1020	err = snd_hda_gen_parse_auto_config(codec, cfg);
1021	if (err < 0)
1022		return err;
1023
1024	return 1;
1025}
1026EXPORT_SYMBOL_NS_GPL(alc_parse_auto_config, "SND_HDA_CODEC_REALTEK");
1027
1028/* common preparation job for alc_spec */
1029int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
1030{
1031	struct alc_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1032	int err;
1033
1034	if (!spec)
1035		return -ENOMEM;
1036	codec->spec = spec;
1037	snd_hda_gen_spec_init(&spec->gen);
1038	spec->gen.mixer_nid = mixer_nid;
1039	spec->gen.own_eapd_ctl = 1;
1040	codec->single_adc_amp = 1;
1041	/* FIXME: do we need this for all Realtek codec models? */
1042	codec->spdif_status_reset = 1;
1043	codec->forced_resume = 1;
1044	mutex_init(&spec->coef_mutex);
1045
1046	err = alc_codec_rename_from_preset(codec);
1047	if (err < 0) {
1048		kfree(spec);
1049		return err;
1050	}
1051	return 0;
1052}
1053EXPORT_SYMBOL_NS_GPL(alc_alloc_spec, "SND_HDA_CODEC_REALTEK");
1054
1055/* For dual-codec configuration, we need to disable some features to avoid
1056 * conflicts of kctls and PCM streams
1057 */
1058void alc_fixup_dual_codecs(struct hda_codec *codec,
1059			   const struct hda_fixup *fix, int action)
1060{
1061	struct alc_spec *spec = codec->spec;
1062
1063	if (action != HDA_FIXUP_ACT_PRE_PROBE)
1064		return;
1065	/* disable vmaster */
1066	spec->gen.suppress_vmaster = 1;
1067	/* auto-mute and auto-mic switch don't work with multiple codecs */
1068	spec->gen.suppress_auto_mute = 1;
1069	spec->gen.suppress_auto_mic = 1;
1070	/* disable aamix as well */
1071	spec->gen.mixer_nid = 0;
1072	/* add location prefix to avoid conflicts */
1073	codec->force_pin_prefix = 1;
1074}
1075EXPORT_SYMBOL_NS_GPL(alc_fixup_dual_codecs, "SND_HDA_CODEC_REALTEK");
1076
1077static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
1078	{ .channels = 2,
1079	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
1080	{ .channels = 4,
1081	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
1082		   SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
1083	{ }
1084};
1085
1086/* override the 2.1 chmap */
1087void alc_fixup_bass_chmap(struct hda_codec *codec,
1088			  const struct hda_fixup *fix, int action)
1089{
1090	if (action == HDA_FIXUP_ACT_BUILD) {
1091		struct alc_spec *spec = codec->spec;
1092		spec->gen.pcm_rec[0]->stream[0].chmap = asus_pcm_2_1_chmaps;
1093	}
1094}
1095EXPORT_SYMBOL_NS_GPL(alc_fixup_bass_chmap, "SND_HDA_CODEC_REALTEK");
1096
1097/* exported as it's used by multiple codecs */
1098void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
1099				  const struct hda_fixup *fix,
1100				  int action)
1101{
1102	alc_fixup_dual_codecs(codec, fix, action);
1103	switch (action) {
1104	case HDA_FIXUP_ACT_PRE_PROBE:
1105		/* override card longname to provide a unique UCM profile */
1106		strscpy(codec->card->longname, "HDAudio-Gigabyte-ALC1220DualCodecs");
1107		break;
1108	case HDA_FIXUP_ACT_BUILD:
1109		/* rename Capture controls depending on the codec */
1110		rename_ctl(codec, "Capture Volume",
1111			   codec->addr == 0 ?
1112			   "Rear-Panel Capture Volume" :
1113			   "Front-Panel Capture Volume");
1114		rename_ctl(codec, "Capture Switch",
1115			   codec->addr == 0 ?
1116			   "Rear-Panel Capture Switch" :
1117			   "Front-Panel Capture Switch");
1118		break;
1119	}
1120}
1121EXPORT_SYMBOL_NS_GPL(alc1220_fixup_gb_dual_codecs, "SND_HDA_CODEC_REALTEK");
1122
1123void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec,
1124					    const struct hda_fixup *fix,
1125					    int action)
1126{
1127	alc_fixup_dual_codecs(codec, fix, action);
1128	switch (action) {
1129	case HDA_FIXUP_ACT_PRE_PROBE:
1130		/* override card longname to provide a unique UCM profile */
1131		strscpy(codec->card->longname, "HDAudio-Lenovo-DualCodecs");
1132		break;
1133	case HDA_FIXUP_ACT_BUILD:
1134		/* rename Capture controls depending on the codec */
1135		rename_ctl(codec, "Capture Volume",
1136			   codec->addr == 0 ?
1137			   "Rear-Panel Capture Volume" :
1138			   "Front-Panel Capture Volume");
1139		rename_ctl(codec, "Capture Switch",
1140			   codec->addr == 0 ?
1141			   "Rear-Panel Capture Switch" :
1142			   "Front-Panel Capture Switch");
1143		break;
1144	}
1145}
1146EXPORT_SYMBOL_NS_GPL(alc233_alc662_fixup_lenovo_dual_codecs, "SND_HDA_CODEC_REALTEK");
1147
1148static void alc_shutup_dell_xps13(struct hda_codec *codec)
1149{
1150	struct alc_spec *spec = codec->spec;
1151	int hp_pin = alc_get_hp_pin(spec);
1152
1153	/* Prevent pop noises when headphones are plugged in */
1154	snd_hda_codec_write(codec, hp_pin, 0,
1155			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
1156	msleep(20);
1157}
1158
1159void alc_fixup_dell_xps13(struct hda_codec *codec,
1160			  const struct hda_fixup *fix, int action)
1161{
1162	struct alc_spec *spec = codec->spec;
1163	struct hda_input_mux *imux = &spec->gen.input_mux;
1164	int i;
1165
1166	switch (action) {
1167	case HDA_FIXUP_ACT_PRE_PROBE:
1168		/* mic pin 0x19 must be initialized with Vref Hi-Z, otherwise
1169		 * it causes a click noise at start up
1170		 */
1171		snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
1172		spec->shutup = alc_shutup_dell_xps13;
1173		break;
1174	case HDA_FIXUP_ACT_PROBE:
1175		/* Make the internal mic the default input source. */
1176		for (i = 0; i < imux->num_items; i++) {
1177			if (spec->gen.imux_pins[i] == 0x12) {
1178				spec->gen.cur_mux[0] = i;
1179				break;
1180			}
1181		}
1182		break;
1183	}
1184}
1185EXPORT_SYMBOL_NS_GPL(alc_fixup_dell_xps13, "SND_HDA_CODEC_REALTEK");
1186
1187/*
1188 * headset handling
1189 */
1190
1191static void alc_hp_mute_disable(struct hda_codec *codec, unsigned int delay)
1192{
1193	if (delay <= 0)
1194		delay = 75;
1195	snd_hda_codec_write(codec, 0x21, 0,
1196		    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
1197	msleep(delay);
1198	snd_hda_codec_write(codec, 0x21, 0,
1199		    AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
1200	msleep(delay);
1201}
1202
1203static void alc_hp_enable_unmute(struct hda_codec *codec, unsigned int delay)
1204{
1205	if (delay <= 0)
1206		delay = 75;
1207	snd_hda_codec_write(codec, 0x21, 0,
1208		    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1209	msleep(delay);
1210	snd_hda_codec_write(codec, 0x21, 0,
1211		    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1212	msleep(delay);
1213}
1214
1215static const struct coef_fw alc225_pre_hsmode[] = {
1216	UPDATE_COEF(0x4a, 1<<8, 0),
1217	UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
1218	UPDATE_COEF(0x63, 3<<14, 3<<14),
1219	UPDATE_COEF(0x4a, 3<<4, 2<<4),
1220	UPDATE_COEF(0x4a, 3<<10, 3<<10),
1221	UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
1222	UPDATE_COEF(0x4a, 3<<10, 0),
1223	{}
1224};
1225
1226static void alc_headset_mode_unplugged(struct hda_codec *codec)
1227{
1228	struct alc_spec *spec = codec->spec;
1229	static const struct coef_fw coef0255[] = {
1230		WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
1231		WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
1232		UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
1233		WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
1234		WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
1235		{}
1236	};
1237	static const struct coef_fw coef0256[] = {
1238		WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
1239		WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
1240		WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
1241		WRITE_COEFEX(0x57, 0x03, 0x09a3), /* Direct Drive HP Amp control */
1242		UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
1243		{}
1244	};
1245	static const struct coef_fw coef0233[] = {
1246		WRITE_COEF(0x1b, 0x0c0b),
1247		WRITE_COEF(0x45, 0xc429),
1248		UPDATE_COEF(0x35, 0x4000, 0),
1249		WRITE_COEF(0x06, 0x2104),
1250		WRITE_COEF(0x1a, 0x0001),
1251		WRITE_COEF(0x26, 0x0004),
1252		WRITE_COEF(0x32, 0x42a3),
1253		{}
1254	};
1255	static const struct coef_fw coef0288[] = {
1256		UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
1257		UPDATE_COEF(0x50, 0x2000, 0x2000),
1258		UPDATE_COEF(0x56, 0x0006, 0x0006),
1259		UPDATE_COEF(0x66, 0x0008, 0),
1260		UPDATE_COEF(0x67, 0x2000, 0),
1261		{}
1262	};
1263	static const struct coef_fw coef0298[] = {
1264		UPDATE_COEF(0x19, 0x1300, 0x0300),
1265		{}
1266	};
1267	static const struct coef_fw coef0292[] = {
1268		WRITE_COEF(0x76, 0x000e),
1269		WRITE_COEF(0x6c, 0x2400),
1270		WRITE_COEF(0x18, 0x7308),
1271		WRITE_COEF(0x6b, 0xc429),
1272		{}
1273	};
1274	static const struct coef_fw coef0293[] = {
1275		UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */
1276		UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */
1277		UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */
1278		UPDATE_COEF(0x1a, 1<<3, 1<<3), /* Combo JD gating with LINE1-VREFO */
1279		WRITE_COEF(0x45, 0xc429), /* Set to TRS type */
1280		UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
1281		{}
1282	};
1283	static const struct coef_fw coef0668[] = {
1284		WRITE_COEF(0x15, 0x0d40),
1285		WRITE_COEF(0xb7, 0x802b),
1286		{}
1287	};
1288	static const struct coef_fw coef0225[] = {
1289		UPDATE_COEF(0x63, 3<<14, 0),
1290		{}
1291	};
1292	static const struct coef_fw coef0274[] = {
1293		UPDATE_COEF(0x4a, 0x0100, 0),
1294		UPDATE_COEFEX(0x57, 0x05, 0x4000, 0),
1295		UPDATE_COEF(0x6b, 0xf000, 0x5000),
1296		UPDATE_COEF(0x4a, 0x0010, 0),
1297		UPDATE_COEF(0x4a, 0x0c00, 0x0c00),
1298		WRITE_COEF(0x45, 0x5289),
1299		UPDATE_COEF(0x4a, 0x0c00, 0),
1300		{}
1301	};
1302
1303	if (spec->no_internal_mic_pin) {
1304		alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
1305		return;
1306	}
1307
1308	switch (codec->core.vendor_id) {
1309	case 0x10ec0255:
1310		alc_process_coef_fw(codec, coef0255);
1311		break;
1312	case 0x10ec0230:
1313	case 0x10ec0236:
1314	case 0x10ec0256:
1315	case 0x19e58326:
1316		alc_hp_mute_disable(codec, 75);
1317		alc_process_coef_fw(codec, coef0256);
1318		break;
1319	case 0x10ec0234:
1320	case 0x10ec0274:
1321	case 0x10ec0294:
1322		alc_process_coef_fw(codec, coef0274);
1323		break;
1324	case 0x10ec0233:
1325	case 0x10ec0283:
1326		alc_process_coef_fw(codec, coef0233);
1327		break;
1328	case 0x10ec0286:
1329	case 0x10ec0288:
1330		alc_process_coef_fw(codec, coef0288);
1331		break;
1332	case 0x10ec0298:
1333		alc_process_coef_fw(codec, coef0298);
1334		alc_process_coef_fw(codec, coef0288);
1335		break;
1336	case 0x10ec0292:
1337		alc_process_coef_fw(codec, coef0292);
1338		break;
1339	case 0x10ec0293:
1340		alc_process_coef_fw(codec, coef0293);
1341		break;
1342	case 0x10ec0668:
1343		alc_process_coef_fw(codec, coef0668);
1344		break;
1345	case 0x10ec0215:
1346	case 0x10ec0225:
1347	case 0x10ec0285:
1348	case 0x10ec0295:
1349	case 0x10ec0289:
1350	case 0x10ec0299:
1351		alc_hp_mute_disable(codec, 75);
1352		alc_process_coef_fw(codec, alc225_pre_hsmode);
1353		alc_process_coef_fw(codec, coef0225);
1354		break;
1355	case 0x10ec0867:
1356		alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1357		break;
1358	}
1359	codec_dbg(codec, "Headset jack set to unplugged mode.\n");
1360}
1361
1362
1363static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
1364				    hda_nid_t mic_pin)
1365{
1366	static const struct coef_fw coef0255[] = {
1367		WRITE_COEFEX(0x57, 0x03, 0x8aa6),
1368		WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
1369		{}
1370	};
1371	static const struct coef_fw coef0256[] = {
1372		UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), /* Direct Drive HP Amp control(Set to verb control)*/
1373		WRITE_COEFEX(0x57, 0x03, 0x09a3),
1374		WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
1375		{}
1376	};
1377	static const struct coef_fw coef0233[] = {
1378		UPDATE_COEF(0x35, 0, 1<<14),
1379		WRITE_COEF(0x06, 0x2100),
1380		WRITE_COEF(0x1a, 0x0021),
1381		WRITE_COEF(0x26, 0x008c),
1382		{}
1383	};
1384	static const struct coef_fw coef0288[] = {
1385		UPDATE_COEF(0x4f, 0x00c0, 0),
1386		UPDATE_COEF(0x50, 0x2000, 0),
1387		UPDATE_COEF(0x56, 0x0006, 0),
1388		UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
1389		UPDATE_COEF(0x66, 0x0008, 0x0008),
1390		UPDATE_COEF(0x67, 0x2000, 0x2000),
1391		{}
1392	};
1393	static const struct coef_fw coef0292[] = {
1394		WRITE_COEF(0x19, 0xa208),
1395		WRITE_COEF(0x2e, 0xacf0),
1396		{}
1397	};
1398	static const struct coef_fw coef0293[] = {
1399		UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */
1400		UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */
1401		UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
1402		{}
1403	};
1404	static const struct coef_fw coef0688[] = {
1405		WRITE_COEF(0xb7, 0x802b),
1406		WRITE_COEF(0xb5, 0x1040),
1407		UPDATE_COEF(0xc3, 0, 1<<12),
1408		{}
1409	};
1410	static const struct coef_fw coef0225[] = {
1411		UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14),
1412		UPDATE_COEF(0x4a, 3<<4, 2<<4),
1413		UPDATE_COEF(0x63, 3<<14, 0),
1414		{}
1415	};
1416	static const struct coef_fw coef0274[] = {
1417		UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000),
1418		UPDATE_COEF(0x4a, 0x0010, 0),
1419		UPDATE_COEF(0x6b, 0xf000, 0),
1420		{}
1421	};
1422
1423	switch (codec->core.vendor_id) {
1424	case 0x10ec0255:
1425		alc_write_coef_idx(codec, 0x45, 0xc489);
1426		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1427		alc_process_coef_fw(codec, coef0255);
1428		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1429		break;
1430	case 0x10ec0230:
1431	case 0x10ec0236:
1432	case 0x10ec0256:
1433	case 0x19e58326:
1434		alc_write_coef_idx(codec, 0x45, 0xc489);
1435		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1436		alc_process_coef_fw(codec, coef0256);
1437		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1438		break;
1439	case 0x10ec0234:
1440	case 0x10ec0274:
1441	case 0x10ec0294:
1442		alc_write_coef_idx(codec, 0x45, 0x4689);
1443		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1444		alc_process_coef_fw(codec, coef0274);
1445		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1446		break;
1447	case 0x10ec0233:
1448	case 0x10ec0283:
1449		alc_write_coef_idx(codec, 0x45, 0xc429);
1450		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1451		alc_process_coef_fw(codec, coef0233);
1452		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1453		break;
1454	case 0x10ec0286:
1455	case 0x10ec0288:
1456	case 0x10ec0298:
1457		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1458		alc_process_coef_fw(codec, coef0288);
1459		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1460		break;
1461	case 0x10ec0292:
1462		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1463		alc_process_coef_fw(codec, coef0292);
1464		break;
1465	case 0x10ec0293:
1466		/* Set to TRS mode */
1467		alc_write_coef_idx(codec, 0x45, 0xc429);
1468		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1469		alc_process_coef_fw(codec, coef0293);
1470		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1471		break;
1472	case 0x10ec0867:
1473		alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14);
1474		fallthrough;
1475	case 0x10ec0221:
1476	case 0x10ec0662:
1477		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1478		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1479		break;
1480	case 0x10ec0668:
1481		alc_write_coef_idx(codec, 0x11, 0x0001);
1482		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1483		alc_process_coef_fw(codec, coef0688);
1484		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1485		break;
1486	case 0x10ec0215:
1487	case 0x10ec0225:
1488	case 0x10ec0285:
1489	case 0x10ec0295:
1490	case 0x10ec0289:
1491	case 0x10ec0299:
1492		alc_process_coef_fw(codec, alc225_pre_hsmode);
1493		alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
1494		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1495		alc_process_coef_fw(codec, coef0225);
1496		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1497		break;
1498	}
1499	codec_dbg(codec, "Headset jack set to mic-in mode.\n");
1500}
1501
1502static void alc_headset_mode_default(struct hda_codec *codec)
1503{
1504	static const struct coef_fw coef0225[] = {
1505		UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10),
1506		UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10),
1507		UPDATE_COEF(0x49, 3<<8, 0<<8),
1508		UPDATE_COEF(0x4a, 3<<4, 3<<4),
1509		UPDATE_COEF(0x63, 3<<14, 0),
1510		UPDATE_COEF(0x67, 0xf000, 0x3000),
1511		{}
1512	};
1513	static const struct coef_fw coef0255[] = {
1514		WRITE_COEF(0x45, 0xc089),
1515		WRITE_COEF(0x45, 0xc489),
1516		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
1517		WRITE_COEF(0x49, 0x0049),
1518		{}
1519	};
1520	static const struct coef_fw coef0256[] = {
1521		WRITE_COEF(0x45, 0xc489),
1522		WRITE_COEFEX(0x57, 0x03, 0x0da3),
1523		WRITE_COEF(0x49, 0x0049),
1524		UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
1525		WRITE_COEF(0x06, 0x6100),
1526		{}
1527	};
1528	static const struct coef_fw coef0233[] = {
1529		WRITE_COEF(0x06, 0x2100),
1530		WRITE_COEF(0x32, 0x4ea3),
1531		{}
1532	};
1533	static const struct coef_fw coef0288[] = {
1534		UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */
1535		UPDATE_COEF(0x50, 0x2000, 0x2000),
1536		UPDATE_COEF(0x56, 0x0006, 0x0006),
1537		UPDATE_COEF(0x66, 0x0008, 0),
1538		UPDATE_COEF(0x67, 0x2000, 0),
1539		{}
1540	};
1541	static const struct coef_fw coef0292[] = {
1542		WRITE_COEF(0x76, 0x000e),
1543		WRITE_COEF(0x6c, 0x2400),
1544		WRITE_COEF(0x6b, 0xc429),
1545		WRITE_COEF(0x18, 0x7308),
1546		{}
1547	};
1548	static const struct coef_fw coef0293[] = {
1549		UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
1550		WRITE_COEF(0x45, 0xC429), /* Set to TRS type */
1551		UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
1552		{}
1553	};
1554	static const struct coef_fw coef0688[] = {
1555		WRITE_COEF(0x11, 0x0041),
1556		WRITE_COEF(0x15, 0x0d40),
1557		WRITE_COEF(0xb7, 0x802b),
1558		{}
1559	};
1560	static const struct coef_fw coef0274[] = {
1561		WRITE_COEF(0x45, 0x4289),
1562		UPDATE_COEF(0x4a, 0x0010, 0x0010),
1563		UPDATE_COEF(0x6b, 0x0f00, 0),
1564		UPDATE_COEF(0x49, 0x0300, 0x0300),
1565		{}
1566	};
1567
1568	switch (codec->core.vendor_id) {
1569	case 0x10ec0215:
1570	case 0x10ec0225:
1571	case 0x10ec0285:
1572	case 0x10ec0295:
1573	case 0x10ec0289:
1574	case 0x10ec0299:
1575		alc_process_coef_fw(codec, alc225_pre_hsmode);
1576		alc_process_coef_fw(codec, coef0225);
1577		alc_hp_enable_unmute(codec, 75);
1578		break;
1579	case 0x10ec0255:
1580		alc_process_coef_fw(codec, coef0255);
1581		break;
1582	case 0x10ec0230:
1583	case 0x10ec0236:
1584	case 0x10ec0256:
1585	case 0x19e58326:
1586		alc_write_coef_idx(codec, 0x1b, 0x0e4b);
1587		alc_write_coef_idx(codec, 0x45, 0xc089);
1588		msleep(50);
1589		alc_process_coef_fw(codec, coef0256);
1590		alc_hp_enable_unmute(codec, 75);
1591		break;
1592	case 0x10ec0234:
1593	case 0x10ec0274:
1594	case 0x10ec0294:
1595		alc_process_coef_fw(codec, coef0274);
1596		break;
1597	case 0x10ec0233:
1598	case 0x10ec0283:
1599		alc_process_coef_fw(codec, coef0233);
1600		break;
1601	case 0x10ec0286:
1602	case 0x10ec0288:
1603	case 0x10ec0298:
1604		alc_process_coef_fw(codec, coef0288);
1605		break;
1606	case 0x10ec0292:
1607		alc_process_coef_fw(codec, coef0292);
1608		break;
1609	case 0x10ec0293:
1610		alc_process_coef_fw(codec, coef0293);
1611		break;
1612	case 0x10ec0668:
1613		alc_process_coef_fw(codec, coef0688);
1614		break;
1615	case 0x10ec0867:
1616		alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1617		break;
1618	}
1619	codec_dbg(codec, "Headset jack set to headphone (default) mode.\n");
1620}
1621
1622/* Iphone type */
1623static void alc_headset_mode_ctia(struct hda_codec *codec)
1624{
1625	int val;
1626
1627	static const struct coef_fw coef0255[] = {
1628		WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
1629		WRITE_COEF(0x1b, 0x0c2b),
1630		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
1631		{}
1632	};
1633	static const struct coef_fw coef0256[] = {
1634		WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
1635		WRITE_COEF(0x1b, 0x0e6b),
1636		{}
1637	};
1638	static const struct coef_fw coef0233[] = {
1639		WRITE_COEF(0x45, 0xd429),
1640		WRITE_COEF(0x1b, 0x0c2b),
1641		WRITE_COEF(0x32, 0x4ea3),
1642		{}
1643	};
1644	static const struct coef_fw coef0288[] = {
1645		UPDATE_COEF(0x50, 0x2000, 0x2000),
1646		UPDATE_COEF(0x56, 0x0006, 0x0006),
1647		UPDATE_COEF(0x66, 0x0008, 0),
1648		UPDATE_COEF(0x67, 0x2000, 0),
1649		{}
1650	};
1651	static const struct coef_fw coef0292[] = {
1652		WRITE_COEF(0x6b, 0xd429),
1653		WRITE_COEF(0x76, 0x0008),
1654		WRITE_COEF(0x18, 0x7388),
1655		{}
1656	};
1657	static const struct coef_fw coef0293[] = {
1658		WRITE_COEF(0x45, 0xd429), /* Set to ctia type */
1659		UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
1660		{}
1661	};
1662	static const struct coef_fw coef0688[] = {
1663		WRITE_COEF(0x11, 0x0001),
1664		WRITE_COEF(0x15, 0x0d60),
1665		WRITE_COEF(0xc3, 0x0000),
1666		{}
1667	};
1668	static const struct coef_fw coef0225_1[] = {
1669		UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
1670		UPDATE_COEF(0x63, 3<<14, 2<<14),
1671		{}
1672	};
1673	static const struct coef_fw coef0225_2[] = {
1674		UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
1675		UPDATE_COEF(0x63, 3<<14, 1<<14),
1676		{}
1677	};
1678
1679	switch (codec->core.vendor_id) {
1680	case 0x10ec0255:
1681		alc_process_coef_fw(codec, coef0255);
1682		break;
1683	case 0x10ec0230:
1684	case 0x10ec0236:
1685	case 0x10ec0256:
1686	case 0x19e58326:
1687		alc_process_coef_fw(codec, coef0256);
1688		alc_hp_enable_unmute(codec, 75);
1689		break;
1690	case 0x10ec0234:
1691	case 0x10ec0274:
1692	case 0x10ec0294:
1693		alc_write_coef_idx(codec, 0x45, 0xd689);
1694		break;
1695	case 0x10ec0233:
1696	case 0x10ec0283:
1697		alc_process_coef_fw(codec, coef0233);
1698		break;
1699	case 0x10ec0298:
1700		val = alc_read_coef_idx(codec, 0x50);
1701		if (val & (1 << 12)) {
1702			alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);
1703			alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
1704			msleep(300);
1705		} else {
1706			alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);
1707			alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
1708			msleep(300);
1709		}
1710		break;
1711	case 0x10ec0286:
1712	case 0x10ec0288:
1713		alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
1714		msleep(300);
1715		alc_process_coef_fw(codec, coef0288);
1716		break;
1717	case 0x10ec0292:
1718		alc_process_coef_fw(codec, coef0292);
1719		break;
1720	case 0x10ec0293:
1721		alc_process_coef_fw(codec, coef0293);
1722		break;
1723	case 0x10ec0668:
1724		alc_process_coef_fw(codec, coef0688);
1725		break;
1726	case 0x10ec0215:
1727	case 0x10ec0225:
1728	case 0x10ec0285:
1729	case 0x10ec0295:
1730	case 0x10ec0289:
1731	case 0x10ec0299:
1732		val = alc_read_coef_idx(codec, 0x45);
1733		if (val & (1 << 9))
1734			alc_process_coef_fw(codec, coef0225_2);
1735		else
1736			alc_process_coef_fw(codec, coef0225_1);
1737		alc_hp_enable_unmute(codec, 75);
1738		break;
1739	case 0x10ec0867:
1740		alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1741		break;
1742	}
1743	codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
1744}
1745
1746/* Nokia type */
1747static void alc_headset_mode_omtp(struct hda_codec *codec)
1748{
1749	static const struct coef_fw coef0255[] = {
1750		WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
1751		WRITE_COEF(0x1b, 0x0c2b),
1752		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
1753		{}
1754	};
1755	static const struct coef_fw coef0256[] = {
1756		WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
1757		WRITE_COEF(0x1b, 0x0e6b),
1758		{}
1759	};
1760	static const struct coef_fw coef0233[] = {
1761		WRITE_COEF(0x45, 0xe429),
1762		WRITE_COEF(0x1b, 0x0c2b),
1763		WRITE_COEF(0x32, 0x4ea3),
1764		{}
1765	};
1766	static const struct coef_fw coef0288[] = {
1767		UPDATE_COEF(0x50, 0x2000, 0x2000),
1768		UPDATE_COEF(0x56, 0x0006, 0x0006),
1769		UPDATE_COEF(0x66, 0x0008, 0),
1770		UPDATE_COEF(0x67, 0x2000, 0),
1771		{}
1772	};
1773	static const struct coef_fw coef0292[] = {
1774		WRITE_COEF(0x6b, 0xe429),
1775		WRITE_COEF(0x76, 0x0008),
1776		WRITE_COEF(0x18, 0x7388),
1777		{}
1778	};
1779	static const struct coef_fw coef0293[] = {
1780		WRITE_COEF(0x45, 0xe429), /* Set to omtp type */
1781		UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
1782		{}
1783	};
1784	static const struct coef_fw coef0688[] = {
1785		WRITE_COEF(0x11, 0x0001),
1786		WRITE_COEF(0x15, 0x0d50),
1787		WRITE_COEF(0xc3, 0x0000),
1788		{}
1789	};
1790	static const struct coef_fw coef0225[] = {
1791		UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10),
1792		UPDATE_COEF(0x63, 3<<14, 2<<14),
1793		{}
1794	};
1795
1796	switch (codec->core.vendor_id) {
1797	case 0x10ec0255:
1798		alc_process_coef_fw(codec, coef0255);
1799		break;
1800	case 0x10ec0230:
1801	case 0x10ec0236:
1802	case 0x10ec0256:
1803	case 0x19e58326:
1804		alc_process_coef_fw(codec, coef0256);
1805		alc_hp_enable_unmute(codec, 75);
1806		break;
1807	case 0x10ec0234:
1808	case 0x10ec0274:
1809	case 0x10ec0294:
1810		alc_write_coef_idx(codec, 0x45, 0xe689);
1811		break;
1812	case 0x10ec0233:
1813	case 0x10ec0283:
1814		alc_process_coef_fw(codec, coef0233);
1815		break;
1816	case 0x10ec0298:
1817		alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);/* Headset output enable */
1818		alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
1819		msleep(300);
1820		break;
1821	case 0x10ec0286:
1822	case 0x10ec0288:
1823		alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
1824		msleep(300);
1825		alc_process_coef_fw(codec, coef0288);
1826		break;
1827	case 0x10ec0292:
1828		alc_process_coef_fw(codec, coef0292);
1829		break;
1830	case 0x10ec0293:
1831		alc_process_coef_fw(codec, coef0293);
1832		break;
1833	case 0x10ec0668:
1834		alc_process_coef_fw(codec, coef0688);
1835		break;
1836	case 0x10ec0215:
1837	case 0x10ec0225:
1838	case 0x10ec0285:
1839	case 0x10ec0295:
1840	case 0x10ec0289:
1841	case 0x10ec0299:
1842		alc_process_coef_fw(codec, coef0225);
1843		alc_hp_enable_unmute(codec, 75);
1844		break;
1845	}
1846	codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
1847}
1848
1849static void alc_determine_headset_type(struct hda_codec *codec)
1850{
1851	int val;
1852	bool is_ctia = false;
1853	struct alc_spec *spec = codec->spec;
1854	static const struct coef_fw coef0255[] = {
1855		WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/
1856		WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref
1857 conteol) */
1858		{}
1859	};
1860	static const struct coef_fw coef0288[] = {
1861		UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */
1862		{}
1863	};
1864	static const struct coef_fw coef0298[] = {
1865		UPDATE_COEF(0x50, 0x2000, 0x2000),
1866		UPDATE_COEF(0x56, 0x0006, 0x0006),
1867		UPDATE_COEF(0x66, 0x0008, 0),
1868		UPDATE_COEF(0x67, 0x2000, 0),
1869		UPDATE_COEF(0x19, 0x1300, 0x1300),
1870		{}
1871	};
1872	static const struct coef_fw coef0293[] = {
1873		UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */
1874		WRITE_COEF(0x45, 0xD429), /* Set to ctia type */
1875		{}
1876	};
1877	static const struct coef_fw coef0688[] = {
1878		WRITE_COEF(0x11, 0x0001),
1879		WRITE_COEF(0xb7, 0x802b),
1880		WRITE_COEF(0x15, 0x0d60),
1881		WRITE_COEF(0xc3, 0x0c00),
1882		{}
1883	};
1884	static const struct coef_fw coef0274[] = {
1885		UPDATE_COEF(0x4a, 0x0010, 0),
1886		UPDATE_COEF(0x4a, 0x8000, 0),
1887		WRITE_COEF(0x45, 0xd289),
1888		UPDATE_COEF(0x49, 0x0300, 0x0300),
1889		{}
1890	};
1891
1892	if (spec->no_internal_mic_pin) {
1893		alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
1894		return;
1895	}
1896
1897	switch (codec->core.vendor_id) {
1898	case 0x10ec0255:
1899		alc_process_coef_fw(codec, coef0255);
1900		msleep(300);
1901		val = alc_read_coef_idx(codec, 0x46);
1902		is_ctia = (val & 0x0070) == 0x0070;
1903		break;
1904	case 0x10ec0230:
1905	case 0x10ec0236:
1906	case 0x10ec0256:
1907	case 0x19e58326:
1908		alc_write_coef_idx(codec, 0x1b, 0x0e4b);
1909		alc_write_coef_idx(codec, 0x06, 0x6104);
1910		alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3);
1911
1912		alc_process_coef_fw(codec, coef0255);
1913		msleep(300);
1914		val = alc_read_coef_idx(codec, 0x46);
1915		is_ctia = (val & 0x0070) == 0x0070;
1916		if (!is_ctia) {
1917			alc_write_coef_idx(codec, 0x45, 0xe089);
1918			msleep(100);
1919			val = alc_read_coef_idx(codec, 0x46);
1920			if ((val & 0x0070) == 0x0070)
1921				is_ctia = false;
1922			else
1923				is_ctia = true;
1924		}
1925		alc_write_coefex_idx(codec, 0x57, 0x3, 0x0da3);
1926		alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1927		break;
1928	case 0x10ec0234:
1929	case 0x10ec0274:
1930	case 0x10ec0294:
1931		alc_process_coef_fw(codec, coef0274);
1932		msleep(850);
1933		val = alc_read_coef_idx(codec, 0x46);
1934		is_ctia = (val & 0x00f0) == 0x00f0;
1935		break;
1936	case 0x10ec0233:
1937	case 0x10ec0283:
1938		alc_write_coef_idx(codec, 0x45, 0xd029);
1939		msleep(300);
1940		val = alc_read_coef_idx(codec, 0x46);
1941		is_ctia = (val & 0x0070) == 0x0070;
1942		break;
1943	case 0x10ec0298:
1944		snd_hda_codec_write(codec, 0x21, 0,
1945			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
1946		msleep(100);
1947		snd_hda_codec_write(codec, 0x21, 0,
1948			    AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
1949		msleep(200);
1950
1951		val = alc_read_coef_idx(codec, 0x50);
1952		if (val & (1 << 12)) {
1953			alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);
1954			alc_process_coef_fw(codec, coef0288);
1955			msleep(350);
1956			val = alc_read_coef_idx(codec, 0x50);
1957			is_ctia = (val & 0x0070) == 0x0070;
1958		} else {
1959			alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);
1960			alc_process_coef_fw(codec, coef0288);
1961			msleep(350);
1962			val = alc_read_coef_idx(codec, 0x50);
1963			is_ctia = (val & 0x0070) == 0x0070;
1964		}
1965		alc_process_coef_fw(codec, coef0298);
1966		snd_hda_codec_write(codec, 0x21, 0,
1967			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
1968		msleep(75);
1969		snd_hda_codec_write(codec, 0x21, 0,
1970			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1971		break;
1972	case 0x10ec0286:
1973	case 0x10ec0288:
1974		alc_process_coef_fw(codec, coef0288);
1975		msleep(350);
1976		val = alc_read_coef_idx(codec, 0x50);
1977		is_ctia = (val & 0x0070) == 0x0070;
1978		break;
1979	case 0x10ec0292:
1980		alc_write_coef_idx(codec, 0x6b, 0xd429);
1981		msleep(300);
1982		val = alc_read_coef_idx(codec, 0x6c);
1983		is_ctia = (val & 0x001c) == 0x001c;
1984		break;
1985	case 0x10ec0293:
1986		alc_process_coef_fw(codec, coef0293);
1987		msleep(300);
1988		val = alc_read_coef_idx(codec, 0x46);
1989		is_ctia = (val & 0x0070) == 0x0070;
1990		break;
1991	case 0x10ec0668:
1992		alc_process_coef_fw(codec, coef0688);
1993		msleep(300);
1994		val = alc_read_coef_idx(codec, 0xbe);
1995		is_ctia = (val & 0x1c02) == 0x1c02;
1996		break;
1997	case 0x10ec0215:
1998	case 0x10ec0225:
1999	case 0x10ec0285:
2000	case 0x10ec0295:
2001	case 0x10ec0289:
2002	case 0x10ec0299:
2003		alc_process_coef_fw(codec, alc225_pre_hsmode);
2004		alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000);
2005		val = alc_read_coef_idx(codec, 0x45);
2006		if (val & (1 << 9)) {
2007			alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);
2008			alc_update_coef_idx(codec, 0x49, 3<<8, 2<<8);
2009			msleep(800);
2010			val = alc_read_coef_idx(codec, 0x46);
2011			is_ctia = (val & 0x00f0) == 0x00f0;
2012		} else {
2013			alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);
2014			alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
2015			msleep(800);
2016			val = alc_read_coef_idx(codec, 0x46);
2017			is_ctia = (val & 0x00f0) == 0x00f0;
2018		}
2019		if (!is_ctia) {
2020			alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x38<<10);
2021			alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
2022			msleep(100);
2023			val = alc_read_coef_idx(codec, 0x46);
2024			if ((val & 0x00f0) == 0x00f0)
2025				is_ctia = false;
2026			else
2027				is_ctia = true;
2028		}
2029		alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6);
2030		alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4);
2031		alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
2032		break;
2033	case 0x10ec0867:
2034		is_ctia = true;
2035		break;
2036	}
2037
2038	codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
2039		  str_yes_no(is_ctia));
2040	spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
2041}
2042
2043static void alc_update_headset_mode(struct hda_codec *codec)
2044{
2045	struct alc_spec *spec = codec->spec;
2046
2047	hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
2048	hda_nid_t hp_pin = alc_get_hp_pin(spec);
2049
2050	int new_headset_mode;
2051
2052	if (!snd_hda_jack_detect(codec, hp_pin))
2053		new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
2054	else if (mux_pin == spec->headset_mic_pin)
2055		new_headset_mode = ALC_HEADSET_MODE_HEADSET;
2056	else if (mux_pin == spec->headphone_mic_pin)
2057		new_headset_mode = ALC_HEADSET_MODE_MIC;
2058	else
2059		new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
2060
2061	if (new_headset_mode == spec->current_headset_mode) {
2062		snd_hda_gen_update_outputs(codec);
2063		return;
2064	}
2065
2066	switch (new_headset_mode) {
2067	case ALC_HEADSET_MODE_UNPLUGGED:
2068		alc_headset_mode_unplugged(codec);
2069		spec->current_headset_mode = ALC_HEADSET_MODE_UNKNOWN;
2070		spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
2071		spec->gen.hp_jack_present = false;
2072		break;
2073	case ALC_HEADSET_MODE_HEADSET:
2074		if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
2075			alc_determine_headset_type(codec);
2076		if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
2077			alc_headset_mode_ctia(codec);
2078		else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
2079			alc_headset_mode_omtp(codec);
2080		spec->gen.hp_jack_present = true;
2081		break;
2082	case ALC_HEADSET_MODE_MIC:
2083		alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
2084		spec->gen.hp_jack_present = false;
2085		break;
2086	case ALC_HEADSET_MODE_HEADPHONE:
2087		alc_headset_mode_default(codec);
2088		spec->gen.hp_jack_present = true;
2089		break;
2090	}
2091	if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
2092		snd_hda_set_pin_ctl_cache(codec, hp_pin,
2093					  AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
2094		if (spec->headphone_mic_pin && spec->headphone_mic_pin != hp_pin)
2095			snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
2096						  PIN_VREFHIZ);
2097	}
2098	spec->current_headset_mode = new_headset_mode;
2099
2100	snd_hda_gen_update_outputs(codec);
2101}
2102
2103static void alc_update_headset_mode_hook(struct hda_codec *codec,
2104					 struct snd_kcontrol *kcontrol,
2105					 struct snd_ctl_elem_value *ucontrol)
2106{
2107	alc_update_headset_mode(codec);
2108}
2109
2110void alc_update_headset_jack_cb(struct hda_codec *codec,
2111				struct hda_jack_callback *jack)
2112{
2113	snd_hda_gen_hp_automute(codec, jack);
2114	alc_update_headset_mode(codec);
2115}
2116EXPORT_SYMBOL_NS_GPL(alc_update_headset_jack_cb, "SND_HDA_CODEC_REALTEK");
2117
2118static void alc_probe_headset_mode(struct hda_codec *codec)
2119{
2120	int i;
2121	struct alc_spec *spec = codec->spec;
2122	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
2123
2124	/* Find mic pins */
2125	for (i = 0; i < cfg->num_inputs; i++) {
2126		if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
2127			spec->headset_mic_pin = cfg->inputs[i].pin;
2128		if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
2129			spec->headphone_mic_pin = cfg->inputs[i].pin;
2130	}
2131
2132	WARN_ON(spec->gen.cap_sync_hook);
2133	spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
2134	spec->gen.automute_hook = alc_update_headset_mode;
2135	spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
2136}
2137
2138void alc_fixup_headset_mode(struct hda_codec *codec,
2139			    const struct hda_fixup *fix, int action)
2140{
2141	struct alc_spec *spec = codec->spec;
2142
2143	switch (action) {
2144	case HDA_FIXUP_ACT_PRE_PROBE:
2145		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
2146		break;
2147	case HDA_FIXUP_ACT_PROBE:
2148		alc_probe_headset_mode(codec);
2149		break;
2150	case HDA_FIXUP_ACT_INIT:
2151		if (is_s3_resume(codec) || is_s4_resume(codec)) {
2152			spec->current_headset_mode = ALC_HEADSET_MODE_UNKNOWN;
2153			spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
2154		}
2155		alc_update_headset_mode(codec);
2156		break;
2157	}
2158}
2159EXPORT_SYMBOL_NS_GPL(alc_fixup_headset_mode, "SND_HDA_CODEC_REALTEK");
2160
2161void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
2162				      const struct hda_fixup *fix, int action)
2163{
2164	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2165		struct alc_spec *spec = codec->spec;
2166		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
2167	}
2168	else
2169		alc_fixup_headset_mode(codec, fix, action);
2170}
2171EXPORT_SYMBOL_NS_GPL(alc_fixup_headset_mode_no_hp_mic, "SND_HDA_CODEC_REALTEK");
2172
2173void alc_fixup_headset_mic(struct hda_codec *codec,
2174			   const struct hda_fixup *fix, int action)
2175{
2176	struct alc_spec *spec = codec->spec;
2177
2178	if (action == HDA_FIXUP_ACT_PRE_PROBE)
2179		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
2180}
2181EXPORT_SYMBOL_NS_GPL(alc_fixup_headset_mic, "SND_HDA_CODEC_REALTEK");
2182
2183/* update LED status via GPIO */
2184void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
2185			 int polarity, bool enabled)
2186{
2187	if (polarity)
2188		enabled = !enabled;
2189	alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */
2190}
2191EXPORT_SYMBOL_NS_GPL(alc_update_gpio_led, "SND_HDA_CODEC_REALTEK");
2192
2193/* turn on/off mic-mute LED via GPIO per capture hook */
2194static int micmute_led_set(struct led_classdev *led_cdev,
2195			   enum led_brightness brightness)
2196{
2197	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
2198	struct alc_spec *spec = codec->spec;
2199
2200	alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
2201			    spec->micmute_led_polarity, !brightness);
2202	return 0;
2203}
2204
2205/* turn on/off mute LED via GPIO per vmaster hook */
2206static int gpio_mute_led_set(struct led_classdev *led_cdev,
2207			     enum led_brightness brightness)
2208{
2209	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
2210	struct alc_spec *spec = codec->spec;
2211
2212	alc_update_gpio_led(codec, spec->gpio_mute_led_mask,
2213			    spec->mute_led_polarity, !brightness);
2214	return 0;
2215}
2216
2217/* setup mute and mic-mute GPIO bits, add hooks appropriately */
2218void alc_fixup_hp_gpio_led(struct hda_codec *codec,
2219			   int action,
2220			   unsigned int mute_mask,
2221			   unsigned int micmute_mask)
2222{
2223	struct alc_spec *spec = codec->spec;
2224
2225	alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
2226
2227	if (action != HDA_FIXUP_ACT_PRE_PROBE)
2228		return;
2229	if (mute_mask) {
2230		spec->gpio_mute_led_mask = mute_mask;
2231		snd_hda_gen_add_mute_led_cdev(codec, gpio_mute_led_set);
2232	}
2233	if (micmute_mask) {
2234		spec->gpio_mic_led_mask = micmute_mask;
2235		snd_hda_gen_add_micmute_led_cdev(codec, micmute_led_set);
2236	}
2237}
2238EXPORT_SYMBOL_NS_GPL(alc_fixup_hp_gpio_led, "SND_HDA_CODEC_REALTEK");
2239
2240/* suppress the jack-detection */
2241void alc_fixup_no_jack_detect(struct hda_codec *codec,
2242			      const struct hda_fixup *fix, int action)
2243{
2244	if (action == HDA_FIXUP_ACT_PRE_PROBE)
2245		codec->no_jack_detect = 1;
2246}
2247EXPORT_SYMBOL_NS_GPL(alc_fixup_no_jack_detect, "SND_HDA_CODEC_REALTEK");
2248
2249void alc_fixup_disable_aamix(struct hda_codec *codec,
2250			     const struct hda_fixup *fix, int action)
2251{
2252	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2253		struct alc_spec *spec = codec->spec;
2254		/* Disable AA-loopback as it causes white noise */
2255		spec->gen.mixer_nid = 0;
2256	}
2257}
2258EXPORT_SYMBOL_NS_GPL(alc_fixup_disable_aamix, "SND_HDA_CODEC_REALTEK");
2259
2260void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
2261				 const struct hda_fixup *fix, int action)
2262{
2263	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2264		struct alc_spec *spec = codec->spec;
2265		spec->gen.auto_mute_via_amp = 1;
2266	}
2267}
2268EXPORT_SYMBOL_NS_GPL(alc_fixup_auto_mute_via_amp, "SND_HDA_CODEC_REALTEK");
2269
2270MODULE_IMPORT_NS("SND_HDA_SCODEC_COMPONENT");
2271MODULE_LICENSE("GPL");
2272MODULE_DESCRIPTION("Realtek HD-audio codec helper");
~/ Read-only file preview.