Linux Audio

Check our new training course

Loading...
v5.4
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
   4 *   AD1986A, AD1988
   5 *
   6 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
   7 */
   8
   9#include <linux/init.h>
 
  10#include <linux/slab.h>
  11#include <linux/module.h>
  12
  13#include <sound/core.h>
  14#include <sound/hda_codec.h>
  15#include "hda_local.h"
  16#include "hda_auto_parser.h"
  17#include "hda_beep.h"
  18#include "hda_jack.h"
  19#include "hda_generic.h"
  20
  21
  22struct ad198x_spec {
  23	struct hda_gen_spec gen;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  24
  25	/* for auto parser */
  26	int smux_paths[4];
  27	unsigned int cur_smux;
  28	hda_nid_t eapd_nid;
 
 
 
 
  29
  30	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  31};
  32
 
 
 
 
 
 
 
 
 
 
  33
  34#ifdef CONFIG_SND_HDA_INPUT_BEEP
  35/* additional beep mixers; the actual parameters are overwritten at build */
  36static const struct snd_kcontrol_new ad_beep_mixer[] = {
  37	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
  38	HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
  39	{ } /* end */
  40};
  41
 
 
 
 
 
 
  42#define set_beep_amp(spec, nid, idx, dir) \
  43	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
  44#else
  45#define set_beep_amp(spec, nid, idx, dir) /* NOP */
  46#endif
  47
  48#ifdef CONFIG_SND_HDA_INPUT_BEEP
  49static int create_beep_ctls(struct hda_codec *codec)
  50{
  51	struct ad198x_spec *spec = codec->spec;
  52	const struct snd_kcontrol_new *knew;
 
 
  53
  54	if (!spec->beep_amp)
  55		return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  56
  57	for (knew = ad_beep_mixer ; knew->name; knew++) {
  58		int err;
  59		struct snd_kcontrol *kctl;
  60		kctl = snd_ctl_new1(knew, codec);
  61		if (!kctl)
  62			return -ENOMEM;
  63		kctl->private_value = spec->beep_amp;
  64		err = snd_hda_ctl_add(codec, 0, kctl);
 
 
 
 
 
 
 
 
 
 
  65		if (err < 0)
  66			return err;
  67	}
 
  68	return 0;
  69}
  70#else
  71#define create_beep_ctls(codec)		0
 
 
 
 
 
  72#endif
  73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  74
  75static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
  76				hda_nid_t hp)
  77{
 
  78	if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
  79		snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
  80			    !codec->inv_eapd ? 0x00 : 0x02);
  81	if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
  82		snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
  83			    !codec->inv_eapd ? 0x00 : 0x02);
  84}
  85
  86static void ad198x_power_eapd(struct hda_codec *codec)
  87{
  88	/* We currently only handle front, HP */
  89	switch (codec->core.vendor_id) {
  90	case 0x11d41882:
  91	case 0x11d4882a:
  92	case 0x11d41884:
  93	case 0x11d41984:
  94	case 0x11d41883:
  95	case 0x11d4184a:
  96	case 0x11d4194a:
  97	case 0x11d4194b:
  98	case 0x11d41988:
  99	case 0x11d4198b:
 100	case 0x11d4989a:
 101	case 0x11d4989b:
 102		ad198x_power_eapd_write(codec, 0x12, 0x11);
 103		break;
 104	case 0x11d41981:
 105	case 0x11d41983:
 106		ad198x_power_eapd_write(codec, 0x05, 0x06);
 107		break;
 108	case 0x11d41986:
 109		ad198x_power_eapd_write(codec, 0x1b, 0x1a);
 110		break;
 111	}
 112}
 113
 114static void ad198x_shutup(struct hda_codec *codec)
 115{
 116	snd_hda_shutup_pins(codec);
 117	ad198x_power_eapd(codec);
 118}
 119
 120#ifdef CONFIG_PM
 121static int ad198x_suspend(struct hda_codec *codec)
 122{
 123	ad198x_shutup(codec);
 124	return 0;
 125}
 126#endif
 127
 128/* follow EAPD via vmaster hook */
 129static void ad_vmaster_eapd_hook(void *private_data, int enabled)
 130{
 131	struct hda_codec *codec = private_data;
 132	struct ad198x_spec *spec = codec->spec;
 133
 134	if (!spec->eapd_nid)
 135		return;
 136	if (codec->inv_eapd)
 137		enabled = !enabled;
 138	snd_hda_codec_write_cache(codec, spec->eapd_nid, 0,
 139				   AC_VERB_SET_EAPD_BTLENABLE,
 140				   enabled ? 0x02 : 0x00);
 141}
 142
 143/*
 144 * Automatic parse of I/O pins from the BIOS configuration
 145 */
 
 
 146
 147static int ad198x_auto_build_controls(struct hda_codec *codec)
 
 148{
 149	int err;
 150
 151	err = snd_hda_gen_build_controls(codec);
 152	if (err < 0)
 153		return err;
 154	err = create_beep_ctls(codec);
 155	if (err < 0)
 156		return err;
 157	return 0;
 158}
 
 159
 160static const struct hda_codec_ops ad198x_auto_patch_ops = {
 161	.build_controls = ad198x_auto_build_controls,
 162	.build_pcms = snd_hda_gen_build_pcms,
 163	.init = snd_hda_gen_init,
 164	.free = snd_hda_gen_free,
 165	.unsol_event = snd_hda_jack_unsol_event,
 
 
 166#ifdef CONFIG_PM
 167	.check_power_status = snd_hda_gen_check_power_status,
 168	.suspend = ad198x_suspend,
 169#endif
 170	.reboot_notify = ad198x_shutup,
 171};
 172
 173
 174static int ad198x_parse_auto_config(struct hda_codec *codec, bool indep_hp)
 
 
 
 
 
 
 
 175{
 
 176	struct ad198x_spec *spec = codec->spec;
 177	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
 178	int err;
 179
 180	codec->spdif_status_reset = 1;
 181	codec->no_trigger_sense = 1;
 182	codec->no_sticky_stream = 1;
 183
 184	spec->gen.indep_hp = indep_hp;
 185	if (!spec->gen.add_stereo_mix_input)
 186		spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 187
 188	err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
 189	if (err < 0)
 190		return err;
 191	err = snd_hda_gen_parse_auto_config(codec, cfg);
 192	if (err < 0)
 193		return err;
 194
 195	return 0;
 196}
 197
 198/*
 199 * AD1986A specific
 200 */
 201
 202static int alloc_ad_spec(struct hda_codec *codec)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 203{
 204	struct ad198x_spec *spec;
 
 
 
 
 
 205
 206	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 207	if (!spec)
 208		return -ENOMEM;
 209	codec->spec = spec;
 210	snd_hda_gen_spec_init(&spec->gen);
 211	codec->patch_ops = ad198x_auto_patch_ops;
 
 
 
 
 
 
 
 
 212	return 0;
 213}
 214
 215/*
 216 * AD1986A fixup codes
 217 */
 218
 219/* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
 220static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
 221				     const struct hda_fixup *fix, int action)
 222{
 223	struct ad198x_spec *spec = codec->spec;
 
 224
 225	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 226		codec->inv_jack_detect = 1;
 227		spec->gen.keep_eapd_on = 1;
 228		spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
 229		spec->eapd_nid = 0x1b;
 230	}
 
 231}
 232
 233/* Toshiba Satellite L40 implements EAPD in a standard way unlike others */
 234static void ad1986a_fixup_eapd(struct hda_codec *codec,
 235			       const struct hda_fixup *fix, int action)
 236{
 237	struct ad198x_spec *spec = codec->spec;
 238
 239	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 240		codec->inv_eapd = 0;
 241		spec->gen.keep_eapd_on = 1;
 242		spec->eapd_nid = 0x1b;
 243	}
 244}
 245
 246/* enable stereo-mix input for avoiding regression on KDE (bko#88251) */
 247static void ad1986a_fixup_eapd_mix_in(struct hda_codec *codec,
 248				      const struct hda_fixup *fix, int action)
 249{
 250	struct ad198x_spec *spec = codec->spec;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 251
 252	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 253		ad1986a_fixup_eapd(codec, fix, action);
 254		spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_ENABLE;
 
 
 
 
 
 
 
 255	}
 256}
 257
 
 
 
 
 
 
 
 
 
 
 258enum {
 259	AD1986A_FIXUP_INV_JACK_DETECT,
 260	AD1986A_FIXUP_ULTRA,
 261	AD1986A_FIXUP_SAMSUNG,
 262	AD1986A_FIXUP_3STACK,
 263	AD1986A_FIXUP_LAPTOP,
 264	AD1986A_FIXUP_LAPTOP_IMIC,
 265	AD1986A_FIXUP_EAPD,
 266	AD1986A_FIXUP_EAPD_MIX_IN,
 267	AD1986A_FIXUP_EASYNOTE,
 268};
 269
 270static const struct hda_fixup ad1986a_fixups[] = {
 271	[AD1986A_FIXUP_INV_JACK_DETECT] = {
 272		.type = HDA_FIXUP_FUNC,
 273		.v.func = ad_fixup_inv_jack_detect,
 274	},
 275	[AD1986A_FIXUP_ULTRA] = {
 276		.type = HDA_FIXUP_PINS,
 277		.v.pins = (const struct hda_pintbl[]) {
 278			{ 0x1b, 0x90170110 }, /* speaker */
 279			{ 0x1d, 0x90a7013e }, /* int mic */
 280			{}
 281		},
 282	},
 283	[AD1986A_FIXUP_SAMSUNG] = {
 284		.type = HDA_FIXUP_PINS,
 285		.v.pins = (const struct hda_pintbl[]) {
 286			{ 0x1b, 0x90170110 }, /* speaker */
 287			{ 0x1d, 0x90a7013e }, /* int mic */
 288			{ 0x20, 0x411111f0 }, /* N/A */
 289			{ 0x24, 0x411111f0 }, /* N/A */
 290			{}
 291		},
 292	},
 293	[AD1986A_FIXUP_3STACK] = {
 294		.type = HDA_FIXUP_PINS,
 295		.v.pins = (const struct hda_pintbl[]) {
 296			{ 0x1a, 0x02214021 }, /* headphone */
 297			{ 0x1b, 0x01014011 }, /* front */
 298			{ 0x1c, 0x01813030 }, /* line-in */
 299			{ 0x1d, 0x01a19020 }, /* rear mic */
 300			{ 0x1e, 0x411111f0 }, /* N/A */
 301			{ 0x1f, 0x02a190f0 }, /* mic */
 302			{ 0x20, 0x411111f0 }, /* N/A */
 303			{}
 304		},
 305	},
 306	[AD1986A_FIXUP_LAPTOP] = {
 307		.type = HDA_FIXUP_PINS,
 308		.v.pins = (const struct hda_pintbl[]) {
 309			{ 0x1a, 0x02214021 }, /* headphone */
 310			{ 0x1b, 0x90170110 }, /* speaker */
 311			{ 0x1c, 0x411111f0 }, /* N/A */
 312			{ 0x1d, 0x411111f0 }, /* N/A */
 313			{ 0x1e, 0x411111f0 }, /* N/A */
 314			{ 0x1f, 0x02a191f0 }, /* mic */
 315			{ 0x20, 0x411111f0 }, /* N/A */
 316			{}
 317		},
 318	},
 319	[AD1986A_FIXUP_LAPTOP_IMIC] = {
 320		.type = HDA_FIXUP_PINS,
 321		.v.pins = (const struct hda_pintbl[]) {
 322			{ 0x1d, 0x90a7013e }, /* int mic */
 323			{}
 324		},
 325		.chained_before = 1,
 326		.chain_id = AD1986A_FIXUP_LAPTOP,
 327	},
 328	[AD1986A_FIXUP_EAPD] = {
 329		.type = HDA_FIXUP_FUNC,
 330		.v.func = ad1986a_fixup_eapd,
 331	},
 332	[AD1986A_FIXUP_EAPD_MIX_IN] = {
 333		.type = HDA_FIXUP_FUNC,
 334		.v.func = ad1986a_fixup_eapd_mix_in,
 335	},
 336	[AD1986A_FIXUP_EASYNOTE] = {
 337		.type = HDA_FIXUP_PINS,
 338		.v.pins = (const struct hda_pintbl[]) {
 339			{ 0x1a, 0x0421402f }, /* headphone */
 340			{ 0x1b, 0x90170110 }, /* speaker */
 341			{ 0x1c, 0x411111f0 }, /* N/A */
 342			{ 0x1d, 0x90a70130 }, /* int mic */
 343			{ 0x1e, 0x411111f0 }, /* N/A */
 344			{ 0x1f, 0x04a19040 }, /* mic */
 345			{ 0x20, 0x411111f0 }, /* N/A */
 346			{ 0x21, 0x411111f0 }, /* N/A */
 347			{ 0x22, 0x411111f0 }, /* N/A */
 348			{ 0x23, 0x411111f0 }, /* N/A */
 349			{ 0x24, 0x411111f0 }, /* N/A */
 350			{ 0x25, 0x411111f0 }, /* N/A */
 351			{}
 352		},
 353		.chained = true,
 354		.chain_id = AD1986A_FIXUP_EAPD_MIX_IN,
 355	},
 356};
 357
 358static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
 359	SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
 360	SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9V", AD1986A_FIXUP_LAPTOP_IMIC),
 361	SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD),
 362	SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD),
 363	SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK),
 364	SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK),
 365	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK),
 366	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40", AD1986A_FIXUP_EAPD),
 367	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP),
 368	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG),
 369	SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA),
 370	SND_PCI_QUIRK(0x1631, 0xc022, "PackardBell EasyNote MX65", AD1986A_FIXUP_EASYNOTE),
 371	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
 372	SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_FIXUP_3STACK),
 373	SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_FIXUP_3STACK),
 374	{}
 375};
 376
 377static const struct hda_model_fixup ad1986a_fixup_models[] = {
 378	{ .id = AD1986A_FIXUP_3STACK, .name = "3stack" },
 379	{ .id = AD1986A_FIXUP_LAPTOP, .name = "laptop" },
 380	{ .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-imic" },
 381	{ .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-eapd" }, /* alias */
 382	{ .id = AD1986A_FIXUP_EAPD, .name = "eapd" },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 383	{}
 384};
 385
 386/*
 387 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 388static int patch_ad1986a(struct hda_codec *codec)
 389{
 390	int err;
 391	struct ad198x_spec *spec;
 392	static hda_nid_t preferred_pairs[] = {
 393		0x1a, 0x03,
 394		0x1b, 0x03,
 395		0x1c, 0x04,
 396		0x1d, 0x05,
 397		0x1e, 0x03,
 398		0
 399	};
 400
 401	err = alloc_ad_spec(codec);
 402	if (err < 0)
 403		return err;
 404	spec = codec->spec;
 405
 406	/* AD1986A has the inverted EAPD implementation */
 407	codec->inv_eapd = 1;
 408
 409	spec->gen.mixer_nid = 0x07;
 410	spec->gen.beep_nid = 0x19;
 
 
 
 411	set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
 412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 413	/* AD1986A has a hardware problem that it can't share a stream
 414	 * with multiple output pins.  The copy of front to surrounds
 415	 * causes noisy or silent outputs at a certain timing, e.g.
 416	 * changing the volume.
 417	 * So, let's disable the shared stream.
 418	 */
 419	spec->gen.multiout.no_share_stream = 1;
 420	/* give fixed DAC/pin pairs */
 421	spec->gen.preferred_dacs = preferred_pairs;
 422
 423	/* AD1986A can't manage the dynamic pin on/off smoothly */
 424	spec->gen.auto_mute_via_amp = 1;
 425
 426	snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
 427			   ad1986a_fixups);
 428	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 429
 430	err = ad198x_parse_auto_config(codec, false);
 431	if (err < 0) {
 432		snd_hda_gen_free(codec);
 433		return err;
 434	}
 435
 436	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 
 437
 438	return 0;
 439}
 440
 441
 442/*
 443 * AD1983 specific
 444 */
 445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 446/*
 447 * SPDIF mux control for AD1983 auto-parser
 448 */
 449static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
 450				      struct snd_ctl_elem_info *uinfo)
 451{
 452	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 453	struct ad198x_spec *spec = codec->spec;
 454	static const char * const texts2[] = { "PCM", "ADC" };
 455	static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
 456	hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
 457	int num_conns = snd_hda_get_num_conns(codec, dig_out);
 458
 459	if (num_conns == 2)
 460		return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
 461	else if (num_conns == 3)
 462		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
 463	else
 464		return -EINVAL;
 465}
 466
 467static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
 468				     struct snd_ctl_elem_value *ucontrol)
 469{
 470	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 471	struct ad198x_spec *spec = codec->spec;
 472
 473	ucontrol->value.enumerated.item[0] = spec->cur_smux;
 474	return 0;
 475}
 476
 477static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
 478				     struct snd_ctl_elem_value *ucontrol)
 479{
 480	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 481	struct ad198x_spec *spec = codec->spec;
 482	unsigned int val = ucontrol->value.enumerated.item[0];
 483	hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
 484	int num_conns = snd_hda_get_num_conns(codec, dig_out);
 485
 486	if (val >= num_conns)
 487		return -EINVAL;
 488	if (spec->cur_smux == val)
 489		return 0;
 490	spec->cur_smux = val;
 491	snd_hda_codec_write_cache(codec, dig_out, 0,
 492				  AC_VERB_SET_CONNECT_SEL, val);
 493	return 1;
 
 
 494}
 495
 496static const struct snd_kcontrol_new ad1983_auto_smux_mixer = {
 497	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 498	.name = "IEC958 Playback Source",
 499	.info = ad1983_auto_smux_enum_info,
 500	.get = ad1983_auto_smux_enum_get,
 501	.put = ad1983_auto_smux_enum_put,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 502};
 503
 504static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
 505{
 506	struct ad198x_spec *spec = codec->spec;
 507	hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
 508	int num_conns;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 509
 510	if (!dig_out)
 511		return 0;
 512	num_conns = snd_hda_get_num_conns(codec, dig_out);
 513	if (num_conns != 2 && num_conns != 3)
 514		return 0;
 515	if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
 516		return -ENOMEM;
 517	return 0;
 518}
 519
 520static int patch_ad1983(struct hda_codec *codec)
 521{
 522	struct ad198x_spec *spec;
 523	static hda_nid_t conn_0c[] = { 0x08 };
 524	static hda_nid_t conn_0d[] = { 0x09 };
 525	int err;
 526
 527	err = alloc_ad_spec(codec);
 528	if (err < 0)
 529		return err;
 530	spec = codec->spec;
 
 531
 532	spec->gen.mixer_nid = 0x0e;
 533	spec->gen.beep_nid = 0x10;
 
 
 
 534	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 535
 536	/* limit the loopback routes not to confuse the parser */
 537	snd_hda_override_conn_list(codec, 0x0c, ARRAY_SIZE(conn_0c), conn_0c);
 538	snd_hda_override_conn_list(codec, 0x0d, ARRAY_SIZE(conn_0d), conn_0d);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 539
 540	err = ad198x_parse_auto_config(codec, false);
 541	if (err < 0)
 542		goto error;
 543	err = ad1983_add_spdif_mux_ctl(codec);
 544	if (err < 0)
 545		goto error;
 546	return 0;
 547
 548 error:
 549	snd_hda_gen_free(codec);
 550	return err;
 
 551}
 552
 553
 554/*
 555 * AD1981 HD specific
 556 */
 557
 558static void ad1981_fixup_hp_eapd(struct hda_codec *codec,
 559				 const struct hda_fixup *fix, int action)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 560{
 
 561	struct ad198x_spec *spec = codec->spec;
 562
 563	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 564		spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
 565		spec->eapd_nid = 0x05;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 566	}
 567}
 568
 569/* set the upper-limit for mixer amp to 0dB for avoiding the possible
 570 * damage by overloading
 571 */
 572static void ad1981_fixup_amp_override(struct hda_codec *codec,
 573				      const struct hda_fixup *fix, int action)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 574{
 575	if (action == HDA_FIXUP_ACT_PRE_PROBE)
 576		snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
 577					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
 578					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
 579					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
 580					  (1 << AC_AMPCAP_MUTE_SHIFT));
 581}
 582
 583enum {
 584	AD1981_FIXUP_AMP_OVERRIDE,
 585	AD1981_FIXUP_HP_EAPD,
 
 
 
 
 
 
 
 
 
 
 586};
 587
 588static const struct hda_fixup ad1981_fixups[] = {
 589	[AD1981_FIXUP_AMP_OVERRIDE] = {
 590		.type = HDA_FIXUP_FUNC,
 591		.v.func = ad1981_fixup_amp_override,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 592	},
 593	[AD1981_FIXUP_HP_EAPD] = {
 594		.type = HDA_FIXUP_FUNC,
 595		.v.func = ad1981_fixup_hp_eapd,
 596		.chained = true,
 597		.chain_id = AD1981_FIXUP_AMP_OVERRIDE,
 
 
 
 
 
 
 
 
 
 
 
 
 598	},
 599};
 600
 601static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
 602	SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
 603	SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
 604	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 605	/* HP nx6320 (reversed SSID, H/W bug) */
 606	SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD),
 607	{}
 608};
 609
 610static int patch_ad1981(struct hda_codec *codec)
 611{
 612	struct ad198x_spec *spec;
 613	int err;
 614
 615	err = alloc_ad_spec(codec);
 616	if (err < 0)
 617		return -ENOMEM;
 618	spec = codec->spec;
 619
 620	spec->gen.mixer_nid = 0x0e;
 621	spec->gen.beep_nid = 0x10;
 
 
 
 
 
 622	set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
 623
 624	snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
 625	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 626
 627	err = ad198x_parse_auto_config(codec, false);
 628	if (err < 0)
 629		goto error;
 630	err = ad1983_add_spdif_mux_ctl(codec);
 631	if (err < 0)
 632		goto error;
 633
 634	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 635
 636	return 0;
 
 637
 638 error:
 639	snd_hda_gen_free(codec);
 640	return err;
 641}
 642
 643
 644/*
 645 * AD1988
 646 *
 647 * Output pins and routes
 648 *
 649 *        Pin               Mix     Sel     DAC (*)
 650 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
 651 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
 652 * port-C 0x15 (mute)    <- 0x2c <- 0x31 <- 05/0a
 653 * port-D 0x12 (mute/hp) <- 0x29         <- 04
 654 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
 655 * port-F 0x16 (mute)    <- 0x2a         <- 06
 656 * port-G 0x24 (mute)    <- 0x27         <- 05
 657 * port-H 0x25 (mute)    <- 0x28         <- 0a
 658 * mono   0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
 659 *
 660 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
 661 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
 662 *
 663 * Input pins and routes
 664 *
 665 *        pin     boost   mix input # / adc input #
 666 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
 667 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
 668 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
 669 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
 670 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
 671 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
 672 * port-G 0x24 -> N/A  -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
 673 * port-H 0x25 -> N/A  -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
 674 *
 675 *
 676 * DAC assignment
 677 *   6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
 678 *   3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
 679 *
 680 * Inputs of Analog Mix (0x20)
 681 *   0:Port-B (front mic)
 682 *   1:Port-C/G/H (line-in)
 683 *   2:Port-A
 684 *   3:Port-D (line-in/2)
 685 *   4:Port-E/G/H (mic-in)
 686 *   5:Port-F (mic2-in)
 687 *   6:CD
 688 *   7:Beep
 689 *
 690 * ADC selection
 691 *   0:Port-A
 692 *   1:Port-B (front mic-in)
 693 *   2:Port-C (line-in)
 694 *   3:Port-F (mic2-in)
 695 *   4:Port-E (mic-in)
 696 *   5:CD
 697 *   6:Port-G
 698 *   7:Port-H
 699 *   8:Port-D (line-in/2)
 700 *   9:Mix
 701 *
 702 * Proposed pin assignments by the datasheet
 703 *
 704 * 6-stack
 705 * Port-A front headphone
 706 *      B front mic-in
 707 *      C rear line-in
 708 *      D rear front-out
 709 *      E rear mic-in
 710 *      F rear surround
 711 *      G rear CLFE
 712 *      H rear side
 713 *
 714 * 3-stack
 715 * Port-A front headphone
 716 *      B front mic
 717 *      C rear line-in/surround
 718 *      D rear front-out
 719 *      E rear mic-in/CLFE
 720 *
 721 * laptop
 722 * Port-A headphone
 723 *      B mic-in
 724 *      C docking station
 725 *      D internal speaker (with EAPD)
 726 *      E/F quad mic array
 727 */
 728
 729static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
 730				      struct snd_ctl_elem_info *uinfo)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 731{
 732	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 733	static const char * const texts[] = {
 734		"PCM", "ADC1", "ADC2", "ADC3",
 735	};
 736	int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
 737	if (num_conns > 4)
 738		num_conns = 4;
 739	return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
 
 
 
 740}
 741
 742static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
 743				     struct snd_ctl_elem_value *ucontrol)
 744{
 745	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 746	struct ad198x_spec *spec = codec->spec;
 747
 748	ucontrol->value.enumerated.item[0] = spec->cur_smux;
 
 
 
 
 
 
 
 
 
 
 
 
 749	return 0;
 750}
 751
 752static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
 753				     struct snd_ctl_elem_value *ucontrol)
 754{
 755	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 756	struct ad198x_spec *spec = codec->spec;
 757	unsigned int val = ucontrol->value.enumerated.item[0];
 758	struct nid_path *path;
 759	int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
 760
 761	if (val >= num_conns)
 
 762		return -EINVAL;
 763	if (spec->cur_smux == val)
 764		return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 765
 766	mutex_lock(&codec->control_mutex);
 767	path = snd_hda_get_path_from_idx(codec,
 768					 spec->smux_paths[spec->cur_smux]);
 769	if (path)
 770		snd_hda_activate_path(codec, path, false, true);
 771	path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
 772	if (path)
 773		snd_hda_activate_path(codec, path, true, true);
 774	spec->cur_smux = val;
 775	mutex_unlock(&codec->control_mutex);
 776	return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 777}
 778
 779static const struct snd_kcontrol_new ad1988_auto_smux_mixer = {
 780	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 781	.name = "IEC958 Playback Source",
 782	.info = ad1988_auto_smux_enum_info,
 783	.get = ad1988_auto_smux_enum_get,
 784	.put = ad1988_auto_smux_enum_put,
 785};
 786
 787static int ad1988_auto_init(struct hda_codec *codec)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 788{
 789	struct ad198x_spec *spec = codec->spec;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 790	int i, err;
 791
 792	err = snd_hda_gen_init(codec);
 793	if (err < 0)
 794		return err;
 795	if (!spec->gen.autocfg.dig_outs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 796		return 0;
 797
 798	for (i = 0; i < 4; i++) {
 799		struct nid_path *path;
 800		path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]);
 801		if (path)
 802			snd_hda_activate_path(codec, path, path->active, false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 803	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 804
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 805	return 0;
 806}
 807
 808static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
 
 
 809{
 810	struct ad198x_spec *spec = codec->spec;
 811	int i, num_conns;
 812	/* we create four static faked paths, since AD codecs have odd
 813	 * widget connections regarding the SPDIF out source
 814	 */
 815	static struct nid_path fake_paths[4] = {
 816		{
 817			.depth = 3,
 818			.path = { 0x02, 0x1d, 0x1b },
 819			.idx = { 0, 0, 0 },
 820			.multi = { 0, 0, 0 },
 821		},
 822		{
 823			.depth = 4,
 824			.path = { 0x08, 0x0b, 0x1d, 0x1b },
 825			.idx = { 0, 0, 1, 0 },
 826			.multi = { 0, 1, 0, 0 },
 827		},
 828		{
 829			.depth = 4,
 830			.path = { 0x09, 0x0b, 0x1d, 0x1b },
 831			.idx = { 0, 1, 1, 0 },
 832			.multi = { 0, 1, 0, 0 },
 833		},
 834		{
 835			.depth = 4,
 836			.path = { 0x0f, 0x0b, 0x1d, 0x1b },
 837			.idx = { 0, 2, 1, 0 },
 838			.multi = { 0, 1, 0, 0 },
 839		},
 840	};
 841
 842	/* SPDIF source mux appears to be present only on AD1988A */
 843	if (!spec->gen.autocfg.dig_outs ||
 844	    get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX)
 845		return 0;
 
 
 
 
 
 
 
 
 
 
 846
 847	num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
 848	if (num_conns != 3 && num_conns != 4)
 849		return 0;
 
 
 
 
 
 850
 851	for (i = 0; i < num_conns; i++) {
 852		struct nid_path *path = snd_array_new(&spec->gen.paths);
 853		if (!path)
 854			return -ENOMEM;
 855		*path = fake_paths[i];
 856		if (!i)
 857			path->active = 1;
 858		spec->smux_paths[i] = snd_hda_get_path_idx(codec, path);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 859	}
 
 860
 861	if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer))
 862		return -ENOMEM;
 
 
 
 
 
 
 
 
 863
 864	codec->patch_ops.init = ad1988_auto_init;
 
 
 
 
 
 
 
 
 
 
 
 865
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 866	return 0;
 867}
 868
 869/*
 870 */
 871
 872enum {
 873	AD1988_FIXUP_6STACK_DIG,
 874};
 875
 876static const struct hda_fixup ad1988_fixups[] = {
 877	[AD1988_FIXUP_6STACK_DIG] = {
 878		.type = HDA_FIXUP_PINS,
 879		.v.pins = (const struct hda_pintbl[]) {
 880			{ 0x11, 0x02214130 }, /* front-hp */
 881			{ 0x12, 0x01014010 }, /* line-out */
 882			{ 0x14, 0x02a19122 }, /* front-mic */
 883			{ 0x15, 0x01813021 }, /* line-in */
 884			{ 0x16, 0x01011012 }, /* line-out */
 885			{ 0x17, 0x01a19020 }, /* mic */
 886			{ 0x1b, 0x0145f1f0 }, /* SPDIF */
 887			{ 0x24, 0x01016011 }, /* line-out */
 888			{ 0x25, 0x01012013 }, /* line-out */
 889			{ }
 890		}
 891	},
 892};
 893
 894static const struct hda_model_fixup ad1988_fixup_models[] = {
 895	{ .id = AD1988_FIXUP_6STACK_DIG, .name = "6stack-dig" },
 
 
 
 
 896	{}
 897};
 898
 899static int patch_ad1988(struct hda_codec *codec)
 900{
 901	struct ad198x_spec *spec;
 902	int err;
 903
 904	err = alloc_ad_spec(codec);
 905	if (err < 0)
 906		return err;
 907	spec = codec->spec;
 
 
 
 
 908
 909	spec->gen.mixer_nid = 0x20;
 910	spec->gen.mixer_merge_nid = 0x21;
 911	spec->gen.beep_nid = 0x10;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 912	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 913
 914	snd_hda_pick_fixup(codec, ad1988_fixup_models, NULL, ad1988_fixups);
 915	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 916
 917	err = ad198x_parse_auto_config(codec, true);
 918	if (err < 0)
 919		goto error;
 920	err = ad1988_add_spdif_mux_ctl(codec);
 921	if (err < 0)
 922		goto error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 923
 924	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 925
 926	return 0;
 
 927
 928 error:
 929	snd_hda_gen_free(codec);
 930	return err;
 931}
 932
 933
 934/*
 935 * AD1884 / AD1984
 936 *
 937 * port-B - front line/mic-in
 938 * port-E - aux in/out
 939 * port-F - aux in/out
 940 * port-C - rear line/mic-in
 941 * port-D - rear line/hp-out
 942 * port-A - front line/hp-out
 943 *
 944 * AD1984 = AD1884 + two digital mic-ins
 945 *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 946 * AD1883 / AD1884A / AD1984A / AD1984B
 947 *
 948 * port-B (0x14) - front mic-in
 949 * port-E (0x1c) - rear mic-in
 950 * port-F (0x16) - CD / ext out
 951 * port-C (0x15) - rear line-in
 952 * port-D (0x12) - rear line-out
 953 * port-A (0x11) - front hp-out
 954 *
 955 * AD1984A = AD1884A + digital-mic
 956 * AD1883 = equivalent with AD1984A
 957 * AD1984B = AD1984A + extra SPDIF-out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 958 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 959
 960/* set the upper-limit for mixer amp to 0dB for avoiding the possible
 961 * damage by overloading
 
 
 
 
 
 
 
 962 */
 963static void ad1884_fixup_amp_override(struct hda_codec *codec,
 964				      const struct hda_fixup *fix, int action)
 
 965{
 966	if (action == HDA_FIXUP_ACT_PRE_PROBE)
 967		snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
 968					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
 969					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
 970					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
 971					  (1 << AC_AMPCAP_MUTE_SHIFT));
 
 
 972}
 973
 974/* toggle GPIO1 according to the mute state */
 975static void ad1884_vmaster_hp_gpio_hook(void *private_data, int enabled)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 976{
 977	struct hda_codec *codec = private_data;
 978	struct ad198x_spec *spec = codec->spec;
 979
 980	if (spec->eapd_nid)
 981		ad_vmaster_eapd_hook(private_data, enabled);
 982	snd_hda_codec_write_cache(codec, 0x01, 0,
 983				   AC_VERB_SET_GPIO_DATA,
 984				   enabled ? 0x00 : 0x02);
 985}
 986
 987static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
 988				 const struct hda_fixup *fix, int action)
 989{
 990	struct ad198x_spec *spec = codec->spec;
 
 
 
 
 
 991
 992	switch (action) {
 993	case HDA_FIXUP_ACT_PRE_PROBE:
 994		spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
 995		spec->gen.own_eapd_ctl = 1;
 996		snd_hda_codec_write_cache(codec, 0x01, 0,
 997					  AC_VERB_SET_GPIO_MASK, 0x02);
 998		snd_hda_codec_write_cache(codec, 0x01, 0,
 999					  AC_VERB_SET_GPIO_DIRECTION, 0x02);
1000		snd_hda_codec_write_cache(codec, 0x01, 0,
1001					  AC_VERB_SET_GPIO_DATA, 0x02);
1002		break;
1003	case HDA_FIXUP_ACT_PROBE:
1004		if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
1005			spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
1006		else
1007			spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
1008		break;
1009	}
1010}
1011
1012static void ad1884_fixup_thinkpad(struct hda_codec *codec,
1013				  const struct hda_fixup *fix, int action)
1014{
1015	struct ad198x_spec *spec = codec->spec;
 
 
 
 
1016
1017	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
1018		spec->gen.keep_eapd_on = 1;
1019		spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
1020		spec->eapd_nid = 0x12;
1021		/* Analog PC Beeper - allow firmware/ACPI beeps */
1022		spec->beep_amp = HDA_COMPOSE_AMP_VAL(0x20, 3, 3, HDA_INPUT);
1023		spec->gen.beep_nid = 0; /* no digital beep */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1024	}
1025}
1026
1027/* set magic COEFs for dmic */
1028static const struct hda_verb ad1884_dmic_init_verbs[] = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1029	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
1030	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
1031	{}
1032};
1033
1034enum {
1035	AD1884_FIXUP_AMP_OVERRIDE,
1036	AD1884_FIXUP_HP_EAPD,
1037	AD1884_FIXUP_DMIC_COEF,
1038	AD1884_FIXUP_THINKPAD,
1039	AD1884_FIXUP_HP_TOUCHSMART,
1040};
1041
1042static const struct hda_fixup ad1884_fixups[] = {
1043	[AD1884_FIXUP_AMP_OVERRIDE] = {
1044		.type = HDA_FIXUP_FUNC,
1045		.v.func = ad1884_fixup_amp_override,
1046	},
1047	[AD1884_FIXUP_HP_EAPD] = {
1048		.type = HDA_FIXUP_FUNC,
1049		.v.func = ad1884_fixup_hp_eapd,
1050		.chained = true,
1051		.chain_id = AD1884_FIXUP_AMP_OVERRIDE,
1052	},
1053	[AD1884_FIXUP_DMIC_COEF] = {
1054		.type = HDA_FIXUP_VERBS,
1055		.v.verbs = ad1884_dmic_init_verbs,
1056	},
1057	[AD1884_FIXUP_THINKPAD] = {
1058		.type = HDA_FIXUP_FUNC,
1059		.v.func = ad1884_fixup_thinkpad,
1060		.chained = true,
1061		.chain_id = AD1884_FIXUP_DMIC_COEF,
1062	},
1063	[AD1884_FIXUP_HP_TOUCHSMART] = {
1064		.type = HDA_FIXUP_VERBS,
1065		.v.verbs = ad1884_dmic_init_verbs,
1066		.chained = true,
1067		.chain_id = AD1884_FIXUP_HP_EAPD,
1068	},
 
1069};
1070
1071static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
1072	SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
1073	SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
1074	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_THINKPAD),
1075	{}
 
 
1076};
1077
 
 
 
 
1078
1079static int patch_ad1884(struct hda_codec *codec)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1080{
1081	struct ad198x_spec *spec;
1082	int err;
1083
1084	err = alloc_ad_spec(codec);
1085	if (err < 0)
1086		return err;
1087	spec = codec->spec;
1088
1089	spec->gen.mixer_nid = 0x20;
1090	spec->gen.mixer_merge_nid = 0x21;
1091	spec->gen.beep_nid = 0x10;
 
 
 
 
1092	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1093
1094	snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
1095	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1096
1097	err = ad198x_parse_auto_config(codec, true);
1098	if (err < 0)
1099		goto error;
1100	err = ad1983_add_spdif_mux_ctl(codec);
1101	if (err < 0)
1102		goto error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1103
1104	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 
1105
1106	return 0;
1107
1108 error:
1109	snd_hda_gen_free(codec);
1110	return err;
1111}
1112
 
1113/*
1114 * AD1882 / AD1882A
1115 *
1116 * port-A - front hp-out
1117 * port-B - front mic-in
1118 * port-C - rear line-in, shared surr-out (3stack)
1119 * port-D - rear line-out
1120 * port-E - rear mic-in, shared clfe-out (3stack)
1121 * port-F - rear surr-out (6stack)
1122 * port-G - rear clfe-out (6stack)
1123 */
1124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1125static int patch_ad1882(struct hda_codec *codec)
1126{
1127	struct ad198x_spec *spec;
1128	int err;
1129
1130	err = alloc_ad_spec(codec);
1131	if (err < 0)
1132		return err;
1133	spec = codec->spec;
1134
1135	spec->gen.mixer_nid = 0x20;
1136	spec->gen.mixer_merge_nid = 0x21;
1137	spec->gen.beep_nid = 0x10;
 
 
 
 
1138	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1139	err = ad198x_parse_auto_config(codec, true);
1140	if (err < 0)
1141		goto error;
1142	err = ad1988_add_spdif_mux_ctl(codec);
1143	if (err < 0)
1144		goto error;
1145	return 0;
1146
1147 error:
1148	snd_hda_gen_free(codec);
1149	return err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1150}
1151
1152
1153/*
1154 * patch entries
1155 */
1156static const struct hda_device_id snd_hda_id_analog[] = {
1157	HDA_CODEC_ENTRY(0x11d4184a, "AD1884A", patch_ad1884),
1158	HDA_CODEC_ENTRY(0x11d41882, "AD1882", patch_ad1882),
1159	HDA_CODEC_ENTRY(0x11d41883, "AD1883", patch_ad1884),
1160	HDA_CODEC_ENTRY(0x11d41884, "AD1884", patch_ad1884),
1161	HDA_CODEC_ENTRY(0x11d4194a, "AD1984A", patch_ad1884),
1162	HDA_CODEC_ENTRY(0x11d4194b, "AD1984B", patch_ad1884),
1163	HDA_CODEC_ENTRY(0x11d41981, "AD1981", patch_ad1981),
1164	HDA_CODEC_ENTRY(0x11d41983, "AD1983", patch_ad1983),
1165	HDA_CODEC_ENTRY(0x11d41984, "AD1984", patch_ad1884),
1166	HDA_CODEC_ENTRY(0x11d41986, "AD1986A", patch_ad1986a),
1167	HDA_CODEC_ENTRY(0x11d41988, "AD1988", patch_ad1988),
1168	HDA_CODEC_ENTRY(0x11d4198b, "AD1988B", patch_ad1988),
1169	HDA_CODEC_ENTRY(0x11d4882a, "AD1882A", patch_ad1882),
1170	HDA_CODEC_ENTRY(0x11d4989a, "AD1989A", patch_ad1988),
1171	HDA_CODEC_ENTRY(0x11d4989b, "AD1989B", patch_ad1988),
1172	{} /* terminator */
1173};
1174MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_analog);
 
1175
1176MODULE_LICENSE("GPL");
1177MODULE_DESCRIPTION("Analog Devices HD-audio codec");
1178
1179static struct hda_codec_driver analog_driver = {
1180	.id = snd_hda_id_analog,
 
1181};
1182
1183module_hda_codec_driver(analog_driver);
 
 
 
 
 
 
 
 
 
 
 
v3.1
 
   1/*
   2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
   3 *   AD1986A, AD1988
   4 *
   5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
   6 *
   7 *  This driver is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License as published by
   9 *  the Free Software Foundation; either version 2 of the License, or
  10 *  (at your option) any later version.
  11 *
  12 *  This driver is distributed in the hope that it will be useful,
  13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 *  GNU General Public License for more details.
  16 *
  17 *  You should have received a copy of the GNU General Public License
  18 *  along with this program; if not, write to the Free Software
  19 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20 */
  21
  22#include <linux/init.h>
  23#include <linux/delay.h>
  24#include <linux/slab.h>
  25#include <linux/pci.h>
  26
  27#include <sound/core.h>
  28#include "hda_codec.h"
  29#include "hda_local.h"
 
  30#include "hda_beep.h"
 
 
 
  31
  32struct ad198x_spec {
  33	const struct snd_kcontrol_new *mixers[6];
  34	int num_mixers;
  35	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
  36	const struct hda_verb *init_verbs[6];	/* initialization verbs
  37						 * don't forget NULL termination!
  38						 */
  39	unsigned int num_init_verbs;
  40
  41	/* playback */
  42	struct hda_multi_out multiout;	/* playback set-up
  43					 * max_channels, dacs must be set
  44					 * dig_out_nid and hp_nid are optional
  45					 */
  46	unsigned int cur_eapd;
  47	unsigned int need_dac_fix;
  48
  49	const hda_nid_t *alt_dac_nid;
  50	const struct hda_pcm_stream *stream_analog_alt_playback;
  51
  52	/* capture */
  53	unsigned int num_adc_nids;
  54	const hda_nid_t *adc_nids;
  55	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
  56
  57	/* capture source */
  58	const struct hda_input_mux *input_mux;
  59	const hda_nid_t *capsrc_nids;
  60	unsigned int cur_mux[3];
  61
  62	/* channel model */
  63	const struct hda_channel_mode *channel_mode;
  64	int num_channel_mode;
  65
  66	/* PCM information */
  67	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
  68
  69	unsigned int spdif_route;
  70
  71	/* dynamic controls, init_verbs and input_mux */
  72	struct auto_pin_cfg autocfg;
  73	struct snd_array kctls;
  74	struct hda_input_mux private_imux;
  75	hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
  76
  77	unsigned int jack_present: 1;
  78	unsigned int inv_jack_detect: 1;/* inverted jack-detection */
  79	unsigned int inv_eapd: 1;	/* inverted EAPD implementation */
  80	unsigned int analog_beep: 1;	/* analog beep input present */
  81
  82#ifdef CONFIG_SND_HDA_POWER_SAVE
  83	struct hda_loopback_check loopback;
  84#endif
  85	/* for virtual master */
  86	hda_nid_t vmaster_nid;
  87	const char * const *slave_vols;
  88	const char * const *slave_sws;
  89};
  90
  91/*
  92 * input MUX handling (common part)
  93 */
  94static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  95{
  96	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  97	struct ad198x_spec *spec = codec->spec;
  98
  99	return snd_hda_input_mux_info(spec->input_mux, uinfo);
 100}
 101
 102static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 103{
 104	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 105	struct ad198x_spec *spec = codec->spec;
 106	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 107
 108	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
 109	return 0;
 110}
 111
 112static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 113{
 114	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 115	struct ad198x_spec *spec = codec->spec;
 116	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 117
 118	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 119				     spec->capsrc_nids[adc_idx],
 120				     &spec->cur_mux[adc_idx]);
 121}
 122
 123/*
 124 * initialization (common callbacks)
 125 */
 126static int ad198x_init(struct hda_codec *codec)
 127{
 128	struct ad198x_spec *spec = codec->spec;
 129	int i;
 130
 131	for (i = 0; i < spec->num_init_verbs; i++)
 132		snd_hda_sequence_write(codec, spec->init_verbs[i]);
 133	return 0;
 134}
 135
 136static const char * const ad_slave_vols[] = {
 137	"Front Playback Volume",
 138	"Surround Playback Volume",
 139	"Center Playback Volume",
 140	"LFE Playback Volume",
 141	"Side Playback Volume",
 142	"Headphone Playback Volume",
 143	"Mono Playback Volume",
 144	"Speaker Playback Volume",
 145	"IEC958 Playback Volume",
 146	NULL
 147};
 148
 149static const char * const ad_slave_sws[] = {
 150	"Front Playback Switch",
 151	"Surround Playback Switch",
 152	"Center Playback Switch",
 153	"LFE Playback Switch",
 154	"Side Playback Switch",
 155	"Headphone Playback Switch",
 156	"Mono Playback Switch",
 157	"Speaker Playback Switch",
 158	"IEC958 Playback Switch",
 159	NULL
 160};
 161
 162static const char * const ad1988_6stack_fp_slave_vols[] = {
 163	"Front Playback Volume",
 164	"Surround Playback Volume",
 165	"Center Playback Volume",
 166	"LFE Playback Volume",
 167	"Side Playback Volume",
 168	"IEC958 Playback Volume",
 169	NULL
 170};
 171
 172static const char * const ad1988_6stack_fp_slave_sws[] = {
 173	"Front Playback Switch",
 174	"Surround Playback Switch",
 175	"Center Playback Switch",
 176	"LFE Playback Switch",
 177	"Side Playback Switch",
 178	"IEC958 Playback Switch",
 179	NULL
 180};
 181static void ad198x_free_kctls(struct hda_codec *codec);
 182
 183#ifdef CONFIG_SND_HDA_INPUT_BEEP
 184/* additional beep mixers; the actual parameters are overwritten at build */
 185static const struct snd_kcontrol_new ad_beep_mixer[] = {
 186	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
 187	HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
 188	{ } /* end */
 189};
 190
 191static const struct snd_kcontrol_new ad_beep2_mixer[] = {
 192	HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
 193	HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
 194	{ } /* end */
 195};
 196
 197#define set_beep_amp(spec, nid, idx, dir) \
 198	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
 199#else
 200#define set_beep_amp(spec, nid, idx, dir) /* NOP */
 201#endif
 202
 203static int ad198x_build_controls(struct hda_codec *codec)
 
 204{
 205	struct ad198x_spec *spec = codec->spec;
 206	struct snd_kcontrol *kctl;
 207	unsigned int i;
 208	int err;
 209
 210	for (i = 0; i < spec->num_mixers; i++) {
 211		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
 212		if (err < 0)
 213			return err;
 214	}
 215	if (spec->multiout.dig_out_nid) {
 216		err = snd_hda_create_spdif_out_ctls(codec,
 217						    spec->multiout.dig_out_nid,
 218						    spec->multiout.dig_out_nid);
 219		if (err < 0)
 220			return err;
 221		err = snd_hda_create_spdif_share_sw(codec,
 222						    &spec->multiout);
 223		if (err < 0)
 224			return err;
 225		spec->multiout.share_spdif = 1;
 226	} 
 227	if (spec->dig_in_nid) {
 228		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
 229		if (err < 0)
 230			return err;
 231	}
 232
 233	/* create beep controls if needed */
 234#ifdef CONFIG_SND_HDA_INPUT_BEEP
 235	if (spec->beep_amp) {
 236		const struct snd_kcontrol_new *knew;
 237		knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
 238		for ( ; knew->name; knew++) {
 239			struct snd_kcontrol *kctl;
 240			kctl = snd_ctl_new1(knew, codec);
 241			if (!kctl)
 242				return -ENOMEM;
 243			kctl->private_value = spec->beep_amp;
 244			err = snd_hda_ctl_add(codec, 0, kctl);
 245			if (err < 0)
 246				return err;
 247		}
 248	}
 249#endif
 250
 251	/* if we have no master control, let's create it */
 252	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
 253		unsigned int vmaster_tlv[4];
 254		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
 255					HDA_OUTPUT, vmaster_tlv);
 256		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
 257					  vmaster_tlv,
 258					  (spec->slave_vols ?
 259					   spec->slave_vols : ad_slave_vols));
 260		if (err < 0)
 261			return err;
 262	}
 263	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
 264		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
 265					  NULL,
 266					  (spec->slave_sws ?
 267					   spec->slave_sws : ad_slave_sws));
 268		if (err < 0)
 269			return err;
 270	}
 271
 272	ad198x_free_kctls(codec); /* no longer needed */
 273
 274	/* assign Capture Source enums to NID */
 275	kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
 276	if (!kctl)
 277		kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 278	for (i = 0; kctl && i < kctl->count; i++) {
 279		err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
 280		if (err < 0)
 281			return err;
 282	}
 283
 284	/* assign IEC958 enums to NID */
 285	kctl = snd_hda_find_mixer_ctl(codec,
 286			SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
 287	if (kctl) {
 288		err = snd_hda_add_nid(codec, kctl, 0,
 289				      spec->multiout.dig_out_nid);
 290		if (err < 0)
 291			return err;
 292	}
 293
 294	return 0;
 295}
 296
 297#ifdef CONFIG_SND_HDA_POWER_SAVE
 298static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 299{
 300	struct ad198x_spec *spec = codec->spec;
 301	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
 302}
 303#endif
 304
 305/*
 306 * Analog playback callbacks
 307 */
 308static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
 309				    struct hda_codec *codec,
 310				    struct snd_pcm_substream *substream)
 311{
 312	struct ad198x_spec *spec = codec->spec;
 313	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
 314					     hinfo);
 315}
 316
 317static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 318				       struct hda_codec *codec,
 319				       unsigned int stream_tag,
 320				       unsigned int format,
 321				       struct snd_pcm_substream *substream)
 322{
 323	struct ad198x_spec *spec = codec->spec;
 324	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
 325						format, substream);
 326}
 327
 328static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
 329				       struct hda_codec *codec,
 330				       struct snd_pcm_substream *substream)
 331{
 332	struct ad198x_spec *spec = codec->spec;
 333	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
 334}
 335
 336static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
 337	.substreams = 1,
 338	.channels_min = 2,
 339	.channels_max = 2,
 340	/* NID is set in ad198x_build_pcms */
 341};
 342
 343/*
 344 * Digital out
 345 */
 346static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 347					struct hda_codec *codec,
 348					struct snd_pcm_substream *substream)
 349{
 350	struct ad198x_spec *spec = codec->spec;
 351	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 352}
 353
 354static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 355					 struct hda_codec *codec,
 356					 struct snd_pcm_substream *substream)
 357{
 358	struct ad198x_spec *spec = codec->spec;
 359	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 360}
 361
 362static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 363					   struct hda_codec *codec,
 364					   unsigned int stream_tag,
 365					   unsigned int format,
 366					   struct snd_pcm_substream *substream)
 367{
 368	struct ad198x_spec *spec = codec->spec;
 369	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
 370					     format, substream);
 371}
 372
 373static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
 374					   struct hda_codec *codec,
 375					   struct snd_pcm_substream *substream)
 376{
 377	struct ad198x_spec *spec = codec->spec;
 378	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
 379}
 380
 381/*
 382 * Analog capture
 383 */
 384static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
 385				      struct hda_codec *codec,
 386				      unsigned int stream_tag,
 387				      unsigned int format,
 388				      struct snd_pcm_substream *substream)
 389{
 390	struct ad198x_spec *spec = codec->spec;
 391	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
 392				   stream_tag, 0, format);
 393	return 0;
 394}
 395
 396static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 397				      struct hda_codec *codec,
 398				      struct snd_pcm_substream *substream)
 399{
 400	struct ad198x_spec *spec = codec->spec;
 401	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 402	return 0;
 403}
 404
 405
 406/*
 407 */
 408static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
 409	.substreams = 1,
 410	.channels_min = 2,
 411	.channels_max = 6, /* changed later */
 412	.nid = 0, /* fill later */
 413	.ops = {
 414		.open = ad198x_playback_pcm_open,
 415		.prepare = ad198x_playback_pcm_prepare,
 416		.cleanup = ad198x_playback_pcm_cleanup
 417	},
 418};
 419
 420static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
 421	.substreams = 1,
 422	.channels_min = 2,
 423	.channels_max = 2,
 424	.nid = 0, /* fill later */
 425	.ops = {
 426		.prepare = ad198x_capture_pcm_prepare,
 427		.cleanup = ad198x_capture_pcm_cleanup
 428	},
 429};
 430
 431static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
 432	.substreams = 1,
 433	.channels_min = 2,
 434	.channels_max = 2,
 435	.nid = 0, /* fill later */
 436	.ops = {
 437		.open = ad198x_dig_playback_pcm_open,
 438		.close = ad198x_dig_playback_pcm_close,
 439		.prepare = ad198x_dig_playback_pcm_prepare,
 440		.cleanup = ad198x_dig_playback_pcm_cleanup
 441	},
 442};
 443
 444static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
 445	.substreams = 1,
 446	.channels_min = 2,
 447	.channels_max = 2,
 448	/* NID is set in alc_build_pcms */
 449};
 450
 451static int ad198x_build_pcms(struct hda_codec *codec)
 452{
 453	struct ad198x_spec *spec = codec->spec;
 454	struct hda_pcm *info = spec->pcm_rec;
 455
 456	codec->num_pcms = 1;
 457	codec->pcm_info = info;
 458
 459	info->name = "AD198x Analog";
 460	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
 461	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
 462	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
 463	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
 464	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
 465	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
 466
 467	if (spec->multiout.dig_out_nid) {
 468		info++;
 469		codec->num_pcms++;
 470		info->name = "AD198x Digital";
 471		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 472		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
 473		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
 474		if (spec->dig_in_nid) {
 475			info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
 476			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
 477		}
 478	}
 479
 480	if (spec->alt_dac_nid && spec->stream_analog_alt_playback) {
 481		codec->num_pcms++;
 482		info = spec->pcm_rec + 2;
 483		info->name = "AD198x Headphone";
 484		info->pcm_type = HDA_PCM_TYPE_AUDIO;
 485		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
 486			*spec->stream_analog_alt_playback;
 487		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
 488			spec->alt_dac_nid[0];
 489	}
 490
 491	return 0;
 492}
 493
 494static void ad198x_free_kctls(struct hda_codec *codec)
 495{
 496	struct ad198x_spec *spec = codec->spec;
 497
 498	if (spec->kctls.list) {
 499		struct snd_kcontrol_new *kctl = spec->kctls.list;
 500		int i;
 501		for (i = 0; i < spec->kctls.used; i++)
 502			kfree(kctl[i].name);
 503	}
 504	snd_array_free(&spec->kctls);
 505}
 506
 507static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
 508				hda_nid_t hp)
 509{
 510	struct ad198x_spec *spec = codec->spec;
 511	if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
 512		snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
 513			    !spec->inv_eapd ? 0x00 : 0x02);
 514	if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
 515		snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
 516			    !spec->inv_eapd ? 0x00 : 0x02);
 517}
 518
 519static void ad198x_power_eapd(struct hda_codec *codec)
 520{
 521	/* We currently only handle front, HP */
 522	switch (codec->vendor_id) {
 523	case 0x11d41882:
 524	case 0x11d4882a:
 525	case 0x11d41884:
 526	case 0x11d41984:
 527	case 0x11d41883:
 528	case 0x11d4184a:
 529	case 0x11d4194a:
 530	case 0x11d4194b:
 531	case 0x11d41988:
 532	case 0x11d4198b:
 533	case 0x11d4989a:
 534	case 0x11d4989b:
 535		ad198x_power_eapd_write(codec, 0x12, 0x11);
 536		break;
 537	case 0x11d41981:
 538	case 0x11d41983:
 539		ad198x_power_eapd_write(codec, 0x05, 0x06);
 540		break;
 541	case 0x11d41986:
 542		ad198x_power_eapd_write(codec, 0x1b, 0x1a);
 543		break;
 544	}
 545}
 546
 547static void ad198x_shutup(struct hda_codec *codec)
 548{
 549	snd_hda_shutup_pins(codec);
 550	ad198x_power_eapd(codec);
 551}
 552
 553static void ad198x_free(struct hda_codec *codec)
 
 
 
 
 
 
 
 
 
 554{
 
 555	struct ad198x_spec *spec = codec->spec;
 556
 557	if (!spec)
 558		return;
 
 
 
 
 
 
 559
 560	ad198x_shutup(codec);
 561	ad198x_free_kctls(codec);
 562	kfree(spec);
 563	snd_hda_detach_beep_device(codec);
 564}
 565
 566#ifdef CONFIG_PM
 567static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
 568{
 569	ad198x_shutup(codec);
 
 
 
 
 
 
 
 570	return 0;
 571}
 572#endif
 573
 574static const struct hda_codec_ops ad198x_patch_ops = {
 575	.build_controls = ad198x_build_controls,
 576	.build_pcms = ad198x_build_pcms,
 577	.init = ad198x_init,
 578	.free = ad198x_free,
 579#ifdef CONFIG_SND_HDA_POWER_SAVE
 580	.check_power_status = ad198x_check_power_status,
 581#endif
 582#ifdef CONFIG_PM
 
 583	.suspend = ad198x_suspend,
 584#endif
 585	.reboot_notify = ad198x_shutup,
 586};
 587
 588
 589/*
 590 * EAPD control
 591 * the private value = nid
 592 */
 593#define ad198x_eapd_info	snd_ctl_boolean_mono_info
 594
 595static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
 596			   struct snd_ctl_elem_value *ucontrol)
 597{
 598	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 599	struct ad198x_spec *spec = codec->spec;
 600	if (spec->inv_eapd)
 601		ucontrol->value.integer.value[0] = ! spec->cur_eapd;
 602	else
 603		ucontrol->value.integer.value[0] = spec->cur_eapd;
 604	return 0;
 605}
 606
 607static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
 608			   struct snd_ctl_elem_value *ucontrol)
 609{
 610	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 611	struct ad198x_spec *spec = codec->spec;
 612	hda_nid_t nid = kcontrol->private_value & 0xff;
 613	unsigned int eapd;
 614	eapd = !!ucontrol->value.integer.value[0];
 615	if (spec->inv_eapd)
 616		eapd = !eapd;
 617	if (eapd == spec->cur_eapd)
 618		return 0;
 619	spec->cur_eapd = eapd;
 620	snd_hda_codec_write_cache(codec, nid,
 621				  0, AC_VERB_SET_EAPD_BTLENABLE,
 622				  eapd ? 0x02 : 0x00);
 623	return 1;
 624}
 625
 626static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
 627			       struct snd_ctl_elem_info *uinfo);
 628static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
 629			      struct snd_ctl_elem_value *ucontrol);
 630static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
 631			      struct snd_ctl_elem_value *ucontrol);
 632
 
 
 633
 634/*
 635 * AD1986A specific
 636 */
 637
 638#define AD1986A_SPDIF_OUT	0x02
 639#define AD1986A_FRONT_DAC	0x03
 640#define AD1986A_SURR_DAC	0x04
 641#define AD1986A_CLFE_DAC	0x05
 642#define AD1986A_ADC		0x06
 643
 644static const hda_nid_t ad1986a_dac_nids[3] = {
 645	AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
 646};
 647static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
 648static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
 649
 650static const struct hda_input_mux ad1986a_capture_source = {
 651	.num_items = 7,
 652	.items = {
 653		{ "Mic", 0x0 },
 654		{ "CD", 0x1 },
 655		{ "Aux", 0x3 },
 656		{ "Line", 0x4 },
 657		{ "Mix", 0x5 },
 658		{ "Mono", 0x6 },
 659		{ "Phone", 0x7 },
 660	},
 661};
 662
 663
 664static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
 665	.ops = &snd_hda_bind_vol,
 666	.values = {
 667		HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
 668		HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
 669		HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
 670		0
 671	},
 672};
 673
 674static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
 675	.ops = &snd_hda_bind_sw,
 676	.values = {
 677		HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
 678		HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
 679		HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
 680		0
 681	},
 682};
 683
 684/*
 685 * mixers
 686 */
 687static const struct snd_kcontrol_new ad1986a_mixers[] = {
 688	/*
 689	 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
 690	 */
 691	HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
 692	HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
 693	HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
 694	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 695	HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
 696	HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
 697	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
 698	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
 699	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
 700	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
 701	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
 702	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
 703	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
 704	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 705	HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
 706	HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
 707	HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
 708	HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
 709	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 710	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 711	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
 712	HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
 713	HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
 714	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 715	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 716	{
 717		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 718		.name = "Capture Source",
 719		.info = ad198x_mux_enum_info,
 720		.get = ad198x_mux_enum_get,
 721		.put = ad198x_mux_enum_put,
 722	},
 723	HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
 724	{ } /* end */
 725};
 726
 727/* additional mixers for 3stack mode */
 728static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
 729	{
 730		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 731		.name = "Channel Mode",
 732		.info = ad198x_ch_mode_info,
 733		.get = ad198x_ch_mode_get,
 734		.put = ad198x_ch_mode_put,
 735	},
 736	{ } /* end */
 737};
 738
 739/* laptop model - 2ch only */
 740static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
 741
 742/* master controls both pins 0x1a and 0x1b */
 743static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
 744	.ops = &snd_hda_bind_vol,
 745	.values = {
 746		HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
 747		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
 748		0,
 749	},
 750};
 751
 752static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
 753	.ops = &snd_hda_bind_sw,
 754	.values = {
 755		HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
 756		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
 757		0,
 758	},
 759};
 760
 761static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
 762	HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 763	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
 764	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 765	HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
 766	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
 767	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 768	HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
 769	HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
 770	HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
 771	HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
 772	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 773	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 774	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
 775	/* 
 776	   HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
 777	   HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
 778	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 779	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 780	{
 781		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 782		.name = "Capture Source",
 783		.info = ad198x_mux_enum_info,
 784		.get = ad198x_mux_enum_get,
 785		.put = ad198x_mux_enum_put,
 786	},
 787	{ } /* end */
 788};
 789
 790/* laptop-eapd model - 2ch only */
 791
 792static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
 793	.num_items = 3,
 794	.items = {
 795		{ "Mic", 0x0 },
 796		{ "Internal Mic", 0x4 },
 797		{ "Mix", 0x5 },
 798	},
 799};
 800
 801static const struct hda_input_mux ad1986a_automic_capture_source = {
 802	.num_items = 2,
 803	.items = {
 804		{ "Mic", 0x0 },
 805		{ "Mix", 0x5 },
 806	},
 807};
 808
 809static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
 810	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 811	HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
 812	{ } /* end */
 813};
 814
 815static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
 816	HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 817	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
 818	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 819	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 820	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
 821	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 822	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 823	{
 824		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 825		.name = "Capture Source",
 826		.info = ad198x_mux_enum_info,
 827		.get = ad198x_mux_enum_get,
 828		.put = ad198x_mux_enum_put,
 829	},
 830	{
 831		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 832		.name = "External Amplifier",
 833		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
 834		.info = ad198x_eapd_info,
 835		.get = ad198x_eapd_get,
 836		.put = ad198x_eapd_put,
 837		.private_value = 0x1b, /* port-D */
 838	},
 839	{ } /* end */
 840};
 841
 842static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
 843	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
 844	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
 845	{ } /* end */
 846};
 847
 848/* re-connect the mic boost input according to the jack sensing */
 849static void ad1986a_automic(struct hda_codec *codec)
 850{
 851	unsigned int present;
 852	present = snd_hda_jack_detect(codec, 0x1f);
 853	/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
 854	snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
 855			    present ? 0 : 2);
 856}
 857
 858#define AD1986A_MIC_EVENT		0x36
 859
 860static void ad1986a_automic_unsol_event(struct hda_codec *codec,
 861					    unsigned int res)
 862{
 863	if ((res >> 26) != AD1986A_MIC_EVENT)
 864		return;
 865	ad1986a_automic(codec);
 866}
 867
 868static int ad1986a_automic_init(struct hda_codec *codec)
 869{
 870	ad198x_init(codec);
 871	ad1986a_automic(codec);
 872	return 0;
 873}
 874
 875/* laptop-automute - 2ch only */
 
 
 876
 877static void ad1986a_update_hp(struct hda_codec *codec)
 
 
 878{
 879	struct ad198x_spec *spec = codec->spec;
 880	unsigned int mute;
 881
 882	if (spec->jack_present)
 883		mute = HDA_AMP_MUTE; /* mute internal speaker */
 884	else
 885		/* unmute internal speaker if necessary */
 886		mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
 887	snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
 888				 HDA_AMP_MUTE, mute);
 889}
 890
 891static void ad1986a_hp_automute(struct hda_codec *codec)
 
 
 892{
 893	struct ad198x_spec *spec = codec->spec;
 894
 895	spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
 896	if (spec->inv_jack_detect)
 897		spec->jack_present = !spec->jack_present;
 898	ad1986a_update_hp(codec);
 
 899}
 900
 901#define AD1986A_HP_EVENT		0x37
 902
 903static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
 904{
 905	if ((res >> 26) != AD1986A_HP_EVENT)
 906		return;
 907	ad1986a_hp_automute(codec);
 908}
 909
 910static int ad1986a_hp_init(struct hda_codec *codec)
 911{
 912	ad198x_init(codec);
 913	ad1986a_hp_automute(codec);
 914	return 0;
 915}
 916
 917/* bind hp and internal speaker mute (with plug check) */
 918static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 919				    struct snd_ctl_elem_value *ucontrol)
 920{
 921	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 922	long *valp = ucontrol->value.integer.value;
 923	int change;
 924
 925	change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
 926					  HDA_AMP_MUTE,
 927					  valp[0] ? 0 : HDA_AMP_MUTE);
 928	change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
 929					   HDA_AMP_MUTE,
 930					   valp[1] ? 0 : HDA_AMP_MUTE);
 931	if (change)
 932		ad1986a_update_hp(codec);
 933	return change;
 934}
 935
 936static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
 937	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 938	{
 939		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 940		.name = "Master Playback Switch",
 941		.subdevice = HDA_SUBDEV_AMP_FLAG,
 942		.info = snd_hda_mixer_amp_switch_info,
 943		.get = snd_hda_mixer_amp_switch_get,
 944		.put = ad1986a_hp_master_sw_put,
 945		.private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
 946	},
 947	{ } /* end */
 948};
 949
 950
 951/*
 952 * initialization verbs
 953 */
 954static const struct hda_verb ad1986a_init_verbs[] = {
 955	/* Front, Surround, CLFE DAC; mute as default */
 956	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 957	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 958	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 959	/* Downmix - off */
 960	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 961	/* HP, Line-Out, Surround, CLFE selectors */
 962	{0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
 963	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
 964	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
 965	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
 966	/* Mono selector */
 967	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
 968	/* Mic selector: Mic 1/2 pin */
 969	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
 970	/* Line-in selector: Line-in */
 971	{0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
 972	/* Mic 1/2 swap */
 973	{0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
 974	/* Record selector: mic */
 975	{0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
 976	/* Mic, Phone, CD, Aux, Line-In amp; mute as default */
 977	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 978	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 979	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 980	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 981	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 982	/* PC beep */
 983	{0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
 984	/* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
 985	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 986	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 987	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 988	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 989	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 990	/* HP Pin */
 991	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
 992	/* Front, Surround, CLFE Pins */
 993	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 994	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 995	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 996	/* Mono Pin */
 997	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 998	/* Mic Pin */
 999	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1000	/* Line, Aux, CD, Beep-In Pin */
1001	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1002	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1003	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1004	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1005	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1006	{ } /* end */
1007};
1008
1009static const struct hda_verb ad1986a_ch2_init[] = {
1010	/* Surround out -> Line In */
1011	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1012 	/* Line-in selectors */
1013	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
1014	/* CLFE -> Mic in */
1015	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1016	/* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1017	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1018	{ } /* end */
1019};
1020
1021static const struct hda_verb ad1986a_ch4_init[] = {
1022	/* Surround out -> Surround */
1023	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1024	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1025	/* CLFE -> Mic in */
1026	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1027	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1028	{ } /* end */
1029};
1030
1031static const struct hda_verb ad1986a_ch6_init[] = {
1032	/* Surround out -> Surround out */
1033	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1034	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1035	/* CLFE -> CLFE */
1036	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1037	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1038	{ } /* end */
1039};
1040
1041static const struct hda_channel_mode ad1986a_modes[3] = {
1042	{ 2, ad1986a_ch2_init },
1043	{ 4, ad1986a_ch4_init },
1044	{ 6, ad1986a_ch6_init },
1045};
1046
1047/* eapd initialization */
1048static const struct hda_verb ad1986a_eapd_init_verbs[] = {
1049	{0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1050	{}
1051};
1052
1053static const struct hda_verb ad1986a_automic_verbs[] = {
1054	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1055	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1056	/*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1057	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1058	{0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1059	{}
1060};
1061
1062/* Ultra initialization */
1063static const struct hda_verb ad1986a_ultra_init[] = {
1064	/* eapd initialization */
1065	{ 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1066	/* CLFE -> Mic in */
1067	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1068	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1069	{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1070	{ } /* end */
1071};
1072
1073/* pin sensing on HP jack */
1074static const struct hda_verb ad1986a_hp_init_verbs[] = {
1075	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1076	{}
1077};
1078
1079static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1080					    unsigned int res)
1081{
1082	switch (res >> 26) {
1083	case AD1986A_HP_EVENT:
1084		ad1986a_hp_automute(codec);
1085		break;
1086	case AD1986A_MIC_EVENT:
1087		ad1986a_automic(codec);
1088		break;
1089	}
1090}
1091
1092static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1093{
1094	ad198x_init(codec);
1095	ad1986a_hp_automute(codec);
1096	ad1986a_automic(codec);
1097	return 0;
1098}
1099
1100
1101/* models */
1102enum {
1103	AD1986A_6STACK,
1104	AD1986A_3STACK,
1105	AD1986A_LAPTOP,
1106	AD1986A_LAPTOP_EAPD,
1107	AD1986A_LAPTOP_AUTOMUTE,
1108	AD1986A_ULTRA,
1109	AD1986A_SAMSUNG,
1110	AD1986A_SAMSUNG_P50,
1111	AD1986A_MODELS
1112};
1113
1114static const char * const ad1986a_models[AD1986A_MODELS] = {
1115	[AD1986A_6STACK]	= "6stack",
1116	[AD1986A_3STACK]	= "3stack",
1117	[AD1986A_LAPTOP]	= "laptop",
1118	[AD1986A_LAPTOP_EAPD]	= "laptop-eapd",
1119	[AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1120	[AD1986A_ULTRA]		= "ultra",
1121	[AD1986A_SAMSUNG]	= "samsung",
1122	[AD1986A_SAMSUNG_P50]	= "samsung-p50",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1123};
1124
1125static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1126	SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1127	SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1128	SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1129	SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1130	SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1131	SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1132	SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1133	SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1134	SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1135	SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1136	SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1137	SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1138	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1139	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1140	SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1141	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1142	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1143	SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1144	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1145	SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1146	SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1147	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1148	SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1149	SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1150	SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1151	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1152	SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1153	{}
1154};
1155
1156#ifdef CONFIG_SND_HDA_POWER_SAVE
1157static const struct hda_amp_list ad1986a_loopbacks[] = {
1158	{ 0x13, HDA_OUTPUT, 0 }, /* Mic */
1159	{ 0x14, HDA_OUTPUT, 0 }, /* Phone */
1160	{ 0x15, HDA_OUTPUT, 0 }, /* CD */
1161	{ 0x16, HDA_OUTPUT, 0 }, /* Aux */
1162	{ 0x17, HDA_OUTPUT, 0 }, /* Line */
1163	{ } /* end */
1164};
1165#endif
1166
1167static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1168{
1169	unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1170	return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1171}
1172
1173static int patch_ad1986a(struct hda_codec *codec)
1174{
 
1175	struct ad198x_spec *spec;
1176	int err, board_config;
 
 
 
 
 
 
 
1177
1178	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1179	if (spec == NULL)
1180		return -ENOMEM;
 
1181
1182	codec->spec = spec;
 
1183
1184	err = snd_hda_attach_beep_device(codec, 0x19);
1185	if (err < 0) {
1186		ad198x_free(codec);
1187		return err;
1188	}
1189	set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1190
1191	spec->multiout.max_channels = 6;
1192	spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1193	spec->multiout.dac_nids = ad1986a_dac_nids;
1194	spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1195	spec->num_adc_nids = 1;
1196	spec->adc_nids = ad1986a_adc_nids;
1197	spec->capsrc_nids = ad1986a_capsrc_nids;
1198	spec->input_mux = &ad1986a_capture_source;
1199	spec->num_mixers = 1;
1200	spec->mixers[0] = ad1986a_mixers;
1201	spec->num_init_verbs = 1;
1202	spec->init_verbs[0] = ad1986a_init_verbs;
1203#ifdef CONFIG_SND_HDA_POWER_SAVE
1204	spec->loopback.amplist = ad1986a_loopbacks;
1205#endif
1206	spec->vmaster_nid = 0x1b;
1207	spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1208
1209	codec->patch_ops = ad198x_patch_ops;
1210
1211	/* override some parameters */
1212	board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1213						  ad1986a_models,
1214						  ad1986a_cfg_tbl);
1215	switch (board_config) {
1216	case AD1986A_3STACK:
1217		spec->num_mixers = 2;
1218		spec->mixers[1] = ad1986a_3st_mixers;
1219		spec->num_init_verbs = 2;
1220		spec->init_verbs[1] = ad1986a_ch2_init;
1221		spec->channel_mode = ad1986a_modes;
1222		spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1223		spec->need_dac_fix = 1;
1224		spec->multiout.max_channels = 2;
1225		spec->multiout.num_dacs = 1;
1226		break;
1227	case AD1986A_LAPTOP:
1228		spec->mixers[0] = ad1986a_laptop_mixers;
1229		spec->multiout.max_channels = 2;
1230		spec->multiout.num_dacs = 1;
1231		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1232		break;
1233	case AD1986A_LAPTOP_EAPD:
1234		spec->num_mixers = 3;
1235		spec->mixers[0] = ad1986a_laptop_master_mixers;
1236		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1237		spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1238		spec->num_init_verbs = 2;
1239		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1240		spec->multiout.max_channels = 2;
1241		spec->multiout.num_dacs = 1;
1242		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1243		if (!is_jack_available(codec, 0x25))
1244			spec->multiout.dig_out_nid = 0;
1245		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1246		break;
1247	case AD1986A_SAMSUNG:
1248		spec->num_mixers = 2;
1249		spec->mixers[0] = ad1986a_laptop_master_mixers;
1250		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1251		spec->num_init_verbs = 3;
1252		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1253		spec->init_verbs[2] = ad1986a_automic_verbs;
1254		spec->multiout.max_channels = 2;
1255		spec->multiout.num_dacs = 1;
1256		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1257		if (!is_jack_available(codec, 0x25))
1258			spec->multiout.dig_out_nid = 0;
1259		spec->input_mux = &ad1986a_automic_capture_source;
1260		codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1261		codec->patch_ops.init = ad1986a_automic_init;
1262		break;
1263	case AD1986A_SAMSUNG_P50:
1264		spec->num_mixers = 2;
1265		spec->mixers[0] = ad1986a_automute_master_mixers;
1266		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1267		spec->num_init_verbs = 4;
1268		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1269		spec->init_verbs[2] = ad1986a_automic_verbs;
1270		spec->init_verbs[3] = ad1986a_hp_init_verbs;
1271		spec->multiout.max_channels = 2;
1272		spec->multiout.num_dacs = 1;
1273		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1274		if (!is_jack_available(codec, 0x25))
1275			spec->multiout.dig_out_nid = 0;
1276		spec->input_mux = &ad1986a_automic_capture_source;
1277		codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1278		codec->patch_ops.init = ad1986a_samsung_p50_init;
1279		break;
1280	case AD1986A_LAPTOP_AUTOMUTE:
1281		spec->num_mixers = 3;
1282		spec->mixers[0] = ad1986a_automute_master_mixers;
1283		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1284		spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1285		spec->num_init_verbs = 3;
1286		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1287		spec->init_verbs[2] = ad1986a_hp_init_verbs;
1288		spec->multiout.max_channels = 2;
1289		spec->multiout.num_dacs = 1;
1290		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1291		if (!is_jack_available(codec, 0x25))
1292			spec->multiout.dig_out_nid = 0;
1293		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1294		codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1295		codec->patch_ops.init = ad1986a_hp_init;
1296		/* Lenovo N100 seems to report the reversed bit
1297		 * for HP jack-sensing
1298		 */
1299		spec->inv_jack_detect = 1;
1300		break;
1301	case AD1986A_ULTRA:
1302		spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1303		spec->num_init_verbs = 2;
1304		spec->init_verbs[1] = ad1986a_ultra_init;
1305		spec->multiout.max_channels = 2;
1306		spec->multiout.num_dacs = 1;
1307		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1308		spec->multiout.dig_out_nid = 0;
1309		break;
1310	}
1311
1312	/* AD1986A has a hardware problem that it can't share a stream
1313	 * with multiple output pins.  The copy of front to surrounds
1314	 * causes noisy or silent outputs at a certain timing, e.g.
1315	 * changing the volume.
1316	 * So, let's disable the shared stream.
1317	 */
1318	spec->multiout.no_share_stream = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1319
1320	codec->no_trigger_sense = 1;
1321	codec->no_sticky_stream = 1;
1322
1323	return 0;
1324}
1325
 
1326/*
1327 * AD1983 specific
1328 */
1329
1330#define AD1983_SPDIF_OUT	0x02
1331#define AD1983_DAC		0x03
1332#define AD1983_ADC		0x04
1333
1334static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1335static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1336static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1337
1338static const struct hda_input_mux ad1983_capture_source = {
1339	.num_items = 4,
1340	.items = {
1341		{ "Mic", 0x0 },
1342		{ "Line", 0x1 },
1343		{ "Mix", 0x2 },
1344		{ "Mix Mono", 0x3 },
1345	},
1346};
1347
1348/*
1349 * SPDIF playback route
1350 */
1351static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 
1352{
1353	static const char * const texts[] = { "PCM", "ADC" };
1354
1355	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1356	uinfo->count = 1;
1357	uinfo->value.enumerated.items = 2;
1358	if (uinfo->value.enumerated.item > 1)
1359		uinfo->value.enumerated.item = 1;
1360	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1361	return 0;
 
 
 
 
1362}
1363
1364static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 
1365{
1366	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1367	struct ad198x_spec *spec = codec->spec;
1368
1369	ucontrol->value.enumerated.item[0] = spec->spdif_route;
1370	return 0;
1371}
1372
1373static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 
1374{
1375	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1376	struct ad198x_spec *spec = codec->spec;
 
 
 
1377
1378	if (ucontrol->value.enumerated.item[0] > 1)
1379		return -EINVAL;
1380	if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1381		spec->spdif_route = ucontrol->value.enumerated.item[0];
1382		snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1383					  AC_VERB_SET_CONNECT_SEL,
1384					  spec->spdif_route);
1385		return 1;
1386	}
1387	return 0;
1388}
1389
1390static const struct snd_kcontrol_new ad1983_mixers[] = {
1391	HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1392	HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1393	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1394	HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1395	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1396	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1397	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1398	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1399	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1400	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1401	HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1402	HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1403	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT),
1404	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1405	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1406	{
1407		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1408		.name = "Capture Source",
1409		.info = ad198x_mux_enum_info,
1410		.get = ad198x_mux_enum_get,
1411		.put = ad198x_mux_enum_put,
1412	},
1413	{
1414		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1415		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1416		.info = ad1983_spdif_route_info,
1417		.get = ad1983_spdif_route_get,
1418		.put = ad1983_spdif_route_put,
1419	},
1420	{ } /* end */
1421};
1422
1423static const struct hda_verb ad1983_init_verbs[] = {
1424	/* Front, HP, Mono; mute as default */
1425	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1426	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1427	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1428	/* Beep, PCM, Mic, Line-In: mute */
1429	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1430	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1431	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1432	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1433	/* Front, HP selectors; from Mix */
1434	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1435	{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1436	/* Mono selector; from Mix */
1437	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1438	/* Mic selector; Mic */
1439	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1440	/* Line-in selector: Line-in */
1441	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1442	/* Mic boost: 0dB */
1443	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1444	/* Record selector: mic */
1445	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1446	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1447	/* SPDIF route: PCM */
1448	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1449	/* Front Pin */
1450	{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1451	/* HP Pin */
1452	{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1453	/* Mono Pin */
1454	{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1455	/* Mic Pin */
1456	{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1457	/* Line Pin */
1458	{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1459	{ } /* end */
1460};
1461
1462#ifdef CONFIG_SND_HDA_POWER_SAVE
1463static const struct hda_amp_list ad1983_loopbacks[] = {
1464	{ 0x12, HDA_OUTPUT, 0 }, /* Mic */
1465	{ 0x13, HDA_OUTPUT, 0 }, /* Line */
1466	{ } /* end */
1467};
1468#endif
 
 
1469
1470static int patch_ad1983(struct hda_codec *codec)
1471{
1472	struct ad198x_spec *spec;
 
 
1473	int err;
1474
1475	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1476	if (spec == NULL)
1477		return -ENOMEM;
1478
1479	codec->spec = spec;
1480
1481	err = snd_hda_attach_beep_device(codec, 0x10);
1482	if (err < 0) {
1483		ad198x_free(codec);
1484		return err;
1485	}
1486	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1487
1488	spec->multiout.max_channels = 2;
1489	spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1490	spec->multiout.dac_nids = ad1983_dac_nids;
1491	spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1492	spec->num_adc_nids = 1;
1493	spec->adc_nids = ad1983_adc_nids;
1494	spec->capsrc_nids = ad1983_capsrc_nids;
1495	spec->input_mux = &ad1983_capture_source;
1496	spec->num_mixers = 1;
1497	spec->mixers[0] = ad1983_mixers;
1498	spec->num_init_verbs = 1;
1499	spec->init_verbs[0] = ad1983_init_verbs;
1500	spec->spdif_route = 0;
1501#ifdef CONFIG_SND_HDA_POWER_SAVE
1502	spec->loopback.amplist = ad1983_loopbacks;
1503#endif
1504	spec->vmaster_nid = 0x05;
1505
1506	codec->patch_ops = ad198x_patch_ops;
 
 
 
 
 
 
1507
1508	codec->no_trigger_sense = 1;
1509	codec->no_sticky_stream = 1;
1510
1511	return 0;
1512}
1513
1514
1515/*
1516 * AD1981 HD specific
1517 */
1518
1519#define AD1981_SPDIF_OUT	0x02
1520#define AD1981_DAC		0x03
1521#define AD1981_ADC		0x04
1522
1523static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1524static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1525static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1526
1527/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1528static const struct hda_input_mux ad1981_capture_source = {
1529	.num_items = 7,
1530	.items = {
1531		{ "Front Mic", 0x0 },
1532		{ "Line", 0x1 },
1533		{ "Mix", 0x2 },
1534		{ "Mix Mono", 0x3 },
1535		{ "CD", 0x4 },
1536		{ "Mic", 0x6 },
1537		{ "Aux", 0x7 },
1538	},
1539};
1540
1541static const struct snd_kcontrol_new ad1981_mixers[] = {
1542	HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1543	HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1544	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1545	HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1546	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1547	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1548	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1549	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1550	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1551	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1552	HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1553	HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1554	HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1555	HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1556	HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1557	HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1558	HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1559	HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1560	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1561	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1562	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1563	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1564	{
1565		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1566		.name = "Capture Source",
1567		.info = ad198x_mux_enum_info,
1568		.get = ad198x_mux_enum_get,
1569		.put = ad198x_mux_enum_put,
1570	},
1571	/* identical with AD1983 */
1572	{
1573		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1574		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1575		.info = ad1983_spdif_route_info,
1576		.get = ad1983_spdif_route_get,
1577		.put = ad1983_spdif_route_put,
1578	},
1579	{ } /* end */
1580};
1581
1582static const struct hda_verb ad1981_init_verbs[] = {
1583	/* Front, HP, Mono; mute as default */
1584	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1585	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1586	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1587	/* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1588	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1589	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1590	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1591	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1592	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1593	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1594	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1595	/* Front, HP selectors; from Mix */
1596	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1597	{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1598	/* Mono selector; from Mix */
1599	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1600	/* Mic Mixer; select Front Mic */
1601	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1602	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1603	/* Mic boost: 0dB */
1604	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1605	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1606	/* Record selector: Front mic */
1607	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1608	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1609	/* SPDIF route: PCM */
1610	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1611	/* Front Pin */
1612	{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1613	/* HP Pin */
1614	{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1615	/* Mono Pin */
1616	{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1617	/* Front & Rear Mic Pins */
1618	{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1619	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1620	/* Line Pin */
1621	{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1622	/* Digital Beep */
1623	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1624	/* Line-Out as Input: disabled */
1625	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1626	{ } /* end */
1627};
1628
1629#ifdef CONFIG_SND_HDA_POWER_SAVE
1630static const struct hda_amp_list ad1981_loopbacks[] = {
1631	{ 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1632	{ 0x13, HDA_OUTPUT, 0 }, /* Line */
1633	{ 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1634	{ 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1635	{ 0x1d, HDA_OUTPUT, 0 }, /* CD */
1636	{ } /* end */
1637};
1638#endif
1639
1640/*
1641 * Patch for HP nx6320
1642 *
1643 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1644 * speaker output enabled _and_ mute-LED off.
1645 */
1646
1647#define AD1981_HP_EVENT		0x37
1648#define AD1981_MIC_EVENT	0x38
1649
1650static const struct hda_verb ad1981_hp_init_verbs[] = {
1651	{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1652	/* pin sensing on HP and Mic jacks */
1653	{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1654	{0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1655	{}
1656};
1657
1658/* turn on/off EAPD (+ mute HP) as a master switch */
1659static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1660				   struct snd_ctl_elem_value *ucontrol)
1661{
1662	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1663	struct ad198x_spec *spec = codec->spec;
1664
1665	if (! ad198x_eapd_put(kcontrol, ucontrol))
1666		return 0;
1667	/* change speaker pin appropriately */
1668	snd_hda_codec_write(codec, 0x05, 0,
1669			    AC_VERB_SET_PIN_WIDGET_CONTROL,
1670			    spec->cur_eapd ? PIN_OUT : 0);
1671	/* toggle HP mute appropriately */
1672	snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1673				 HDA_AMP_MUTE,
1674				 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1675	return 1;
1676}
1677
1678/* bind volumes of both NID 0x05 and 0x06 */
1679static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1680	.ops = &snd_hda_bind_vol,
1681	.values = {
1682		HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1683		HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1684		0
1685	},
1686};
1687
1688/* mute internal speaker if HP is plugged */
1689static void ad1981_hp_automute(struct hda_codec *codec)
1690{
1691	unsigned int present;
1692
1693	present = snd_hda_jack_detect(codec, 0x06);
1694	snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1695				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1696}
1697
1698/* toggle input of built-in and mic jack appropriately */
1699static void ad1981_hp_automic(struct hda_codec *codec)
1700{
1701	static const struct hda_verb mic_jack_on[] = {
1702		{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1703		{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1704		{}
1705	};
1706	static const struct hda_verb mic_jack_off[] = {
1707		{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1708		{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1709		{}
1710	};
1711	unsigned int present;
1712
1713	present = snd_hda_jack_detect(codec, 0x08);
1714	if (present)
1715		snd_hda_sequence_write(codec, mic_jack_on);
1716	else
1717		snd_hda_sequence_write(codec, mic_jack_off);
1718}
1719
1720/* unsolicited event for HP jack sensing */
1721static void ad1981_hp_unsol_event(struct hda_codec *codec,
1722				  unsigned int res)
1723{
1724	res >>= 26;
1725	switch (res) {
1726	case AD1981_HP_EVENT:
1727		ad1981_hp_automute(codec);
1728		break;
1729	case AD1981_MIC_EVENT:
1730		ad1981_hp_automic(codec);
1731		break;
1732	}
1733}
1734
1735static const struct hda_input_mux ad1981_hp_capture_source = {
1736	.num_items = 3,
1737	.items = {
1738		{ "Mic", 0x0 },
1739		{ "Docking-Station", 0x1 },
1740		{ "Mix", 0x2 },
1741	},
1742};
1743
1744static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
1745	HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1746	{
1747		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1748		.subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1749		.name = "Master Playback Switch",
1750		.info = ad198x_eapd_info,
1751		.get = ad198x_eapd_get,
1752		.put = ad1981_hp_master_sw_put,
1753		.private_value = 0x05,
1754	},
1755	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1756	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1757#if 0
1758	/* FIXME: analog mic/line loopback doesn't work with my tests...
1759	 *        (although recording is OK)
1760	 */
1761	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1762	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1763	HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1764	HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1765	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1766	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1767	/* FIXME: does this laptop have analog CD connection? */
1768	HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1769	HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1770#endif
1771	HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1772	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1773	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1774	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1775	{
1776		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1777		.name = "Capture Source",
1778		.info = ad198x_mux_enum_info,
1779		.get = ad198x_mux_enum_get,
1780		.put = ad198x_mux_enum_put,
1781	},
1782	{ } /* end */
1783};
1784
1785/* initialize jack-sensing, too */
1786static int ad1981_hp_init(struct hda_codec *codec)
1787{
1788	ad198x_init(codec);
1789	ad1981_hp_automute(codec);
1790	ad1981_hp_automic(codec);
1791	return 0;
 
 
1792}
1793
1794/* configuration for Toshiba Laptops */
1795static const struct hda_verb ad1981_toshiba_init_verbs[] = {
1796	{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1797	/* pin sensing on HP and Mic jacks */
1798	{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1799	{0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1800	{}
1801};
1802
1803static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1804	HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1805	HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1806	{ }
1807};
1808
1809/* configuration for Lenovo Thinkpad T60 */
1810static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1811	HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1812	HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1813	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1814	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1815	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1816	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1817	HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1818	HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1819	HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1820	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1821	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1822	{
1823		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1824		.name = "Capture Source",
1825		.info = ad198x_mux_enum_info,
1826		.get = ad198x_mux_enum_get,
1827		.put = ad198x_mux_enum_put,
1828	},
1829	/* identical with AD1983 */
1830	{
1831		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1832		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1833		.info = ad1983_spdif_route_info,
1834		.get = ad1983_spdif_route_get,
1835		.put = ad1983_spdif_route_put,
1836	},
1837	{ } /* end */
1838};
1839
1840static const struct hda_input_mux ad1981_thinkpad_capture_source = {
1841	.num_items = 3,
1842	.items = {
1843		{ "Mic", 0x0 },
1844		{ "Mix", 0x2 },
1845		{ "CD", 0x4 },
1846	},
1847};
1848
1849/* models */
1850enum {
1851	AD1981_BASIC,
1852	AD1981_HP,
1853	AD1981_THINKPAD,
1854	AD1981_TOSHIBA,
1855	AD1981_MODELS
1856};
1857
1858static const char * const ad1981_models[AD1981_MODELS] = {
1859	[AD1981_HP]		= "hp",
1860	[AD1981_THINKPAD]	= "thinkpad",
1861	[AD1981_BASIC]		= "basic",
1862	[AD1981_TOSHIBA]	= "toshiba"
1863};
1864
1865static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
1866	SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1867	SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
1868	/* All HP models */
1869	SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
1870	SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
1871	/* Lenovo Thinkpad T60/X60/Z6xx */
1872	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
1873	/* HP nx6320 (reversed SSID, H/W bug) */
1874	SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1875	{}
1876};
1877
1878static int patch_ad1981(struct hda_codec *codec)
1879{
1880	struct ad198x_spec *spec;
1881	int err, board_config;
1882
1883	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1884	if (spec == NULL)
1885		return -ENOMEM;
 
1886
1887	codec->spec = spec;
1888
1889	err = snd_hda_attach_beep_device(codec, 0x10);
1890	if (err < 0) {
1891		ad198x_free(codec);
1892		return err;
1893	}
1894	set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1895
1896	spec->multiout.max_channels = 2;
1897	spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1898	spec->multiout.dac_nids = ad1981_dac_nids;
1899	spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
1900	spec->num_adc_nids = 1;
1901	spec->adc_nids = ad1981_adc_nids;
1902	spec->capsrc_nids = ad1981_capsrc_nids;
1903	spec->input_mux = &ad1981_capture_source;
1904	spec->num_mixers = 1;
1905	spec->mixers[0] = ad1981_mixers;
1906	spec->num_init_verbs = 1;
1907	spec->init_verbs[0] = ad1981_init_verbs;
1908	spec->spdif_route = 0;
1909#ifdef CONFIG_SND_HDA_POWER_SAVE
1910	spec->loopback.amplist = ad1981_loopbacks;
1911#endif
1912	spec->vmaster_nid = 0x05;
1913
1914	codec->patch_ops = ad198x_patch_ops;
 
 
 
 
 
1915
1916	/* override some parameters */
1917	board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1918						  ad1981_models,
1919						  ad1981_cfg_tbl);
1920	switch (board_config) {
1921	case AD1981_HP:
1922		spec->mixers[0] = ad1981_hp_mixers;
1923		spec->num_init_verbs = 2;
1924		spec->init_verbs[1] = ad1981_hp_init_verbs;
1925		if (!is_jack_available(codec, 0x0a))
1926			spec->multiout.dig_out_nid = 0;
1927		spec->input_mux = &ad1981_hp_capture_source;
1928
1929		codec->patch_ops.init = ad1981_hp_init;
1930		codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1931		/* set the upper-limit for mixer amp to 0dB for avoiding the
1932		 * possible damage by overloading
1933		 */
1934		snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1935					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1936					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1937					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1938					  (1 << AC_AMPCAP_MUTE_SHIFT));
1939		break;
1940	case AD1981_THINKPAD:
1941		spec->mixers[0] = ad1981_thinkpad_mixers;
1942		spec->input_mux = &ad1981_thinkpad_capture_source;
1943		/* set the upper-limit for mixer amp to 0dB for avoiding the
1944		 * possible damage by overloading
1945		 */
1946		snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1947					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1948					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1949					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1950					  (1 << AC_AMPCAP_MUTE_SHIFT));
1951		break;
1952	case AD1981_TOSHIBA:
1953		spec->mixers[0] = ad1981_hp_mixers;
1954		spec->mixers[1] = ad1981_toshiba_mixers;
1955		spec->num_init_verbs = 2;
1956		spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1957		spec->multiout.dig_out_nid = 0;
1958		spec->input_mux = &ad1981_hp_capture_source;
1959		codec->patch_ops.init = ad1981_hp_init;
1960		codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1961		break;
1962	}
1963
1964	codec->no_trigger_sense = 1;
1965	codec->no_sticky_stream = 1;
1966
1967	return 0;
 
 
1968}
1969
1970
1971/*
1972 * AD1988
1973 *
1974 * Output pins and routes
1975 *
1976 *        Pin               Mix     Sel     DAC (*)
1977 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1978 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1979 * port-C 0x15 (mute)    <- 0x2c <- 0x31 <- 05/0a
1980 * port-D 0x12 (mute/hp) <- 0x29         <- 04
1981 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1982 * port-F 0x16 (mute)    <- 0x2a         <- 06
1983 * port-G 0x24 (mute)    <- 0x27         <- 05
1984 * port-H 0x25 (mute)    <- 0x28         <- 0a
1985 * mono   0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1986 *
1987 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1988 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
1989 *
1990 * Input pins and routes
1991 *
1992 *        pin     boost   mix input # / adc input #
1993 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1994 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1995 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1996 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1997 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1998 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1999 * port-G 0x24 -> N/A  -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
2000 * port-H 0x25 -> N/A  -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
2001 *
2002 *
2003 * DAC assignment
2004 *   6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2005 *   3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2006 *
2007 * Inputs of Analog Mix (0x20)
2008 *   0:Port-B (front mic)
2009 *   1:Port-C/G/H (line-in)
2010 *   2:Port-A
2011 *   3:Port-D (line-in/2)
2012 *   4:Port-E/G/H (mic-in)
2013 *   5:Port-F (mic2-in)
2014 *   6:CD
2015 *   7:Beep
2016 *
2017 * ADC selection
2018 *   0:Port-A
2019 *   1:Port-B (front mic-in)
2020 *   2:Port-C (line-in)
2021 *   3:Port-F (mic2-in)
2022 *   4:Port-E (mic-in)
2023 *   5:CD
2024 *   6:Port-G
2025 *   7:Port-H
2026 *   8:Port-D (line-in/2)
2027 *   9:Mix
2028 *
2029 * Proposed pin assignments by the datasheet
2030 *
2031 * 6-stack
2032 * Port-A front headphone
2033 *      B front mic-in
2034 *      C rear line-in
2035 *      D rear front-out
2036 *      E rear mic-in
2037 *      F rear surround
2038 *      G rear CLFE
2039 *      H rear side
2040 *
2041 * 3-stack
2042 * Port-A front headphone
2043 *      B front mic
2044 *      C rear line-in/surround
2045 *      D rear front-out
2046 *      E rear mic-in/CLFE
2047 *
2048 * laptop
2049 * Port-A headphone
2050 *      B mic-in
2051 *      C docking station
2052 *      D internal speaker (with EAPD)
2053 *      E/F quad mic array
2054 */
2055
2056
2057/* models */
2058enum {
2059	AD1988_6STACK,
2060	AD1988_6STACK_DIG,
2061	AD1988_6STACK_DIG_FP,
2062	AD1988_3STACK,
2063	AD1988_3STACK_DIG,
2064	AD1988_LAPTOP,
2065	AD1988_LAPTOP_DIG,
2066	AD1988_AUTO,
2067	AD1988_MODEL_LAST,
2068};
2069
2070/* reivision id to check workarounds */
2071#define AD1988A_REV2		0x100200
2072
2073#define is_rev2(codec) \
2074	((codec)->vendor_id == 0x11d41988 && \
2075	 (codec)->revision_id == AD1988A_REV2)
2076
2077/*
2078 * mixers
2079 */
2080
2081static const hda_nid_t ad1988_6stack_dac_nids[4] = {
2082	0x04, 0x06, 0x05, 0x0a
2083};
2084
2085static const hda_nid_t ad1988_3stack_dac_nids[3] = {
2086	0x04, 0x05, 0x0a
2087};
2088
2089/* for AD1988A revision-2, DAC2-4 are swapped */
2090static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2091	0x04, 0x05, 0x0a, 0x06
2092};
2093
2094static const hda_nid_t ad1988_alt_dac_nid[1] = {
2095	0x03
2096};
2097
2098static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2099	0x04, 0x0a, 0x06
2100};
2101
2102static const hda_nid_t ad1988_adc_nids[3] = {
2103	0x08, 0x09, 0x0f
2104};
2105
2106static const hda_nid_t ad1988_capsrc_nids[3] = {
2107	0x0c, 0x0d, 0x0e
2108};
2109
2110#define AD1988_SPDIF_OUT		0x02
2111#define AD1988_SPDIF_OUT_HDMI	0x0b
2112#define AD1988_SPDIF_IN		0x07
2113
2114static const hda_nid_t ad1989b_slave_dig_outs[] = {
2115	AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2116};
2117
2118static const struct hda_input_mux ad1988_6stack_capture_source = {
2119	.num_items = 5,
2120	.items = {
2121		{ "Front Mic", 0x1 },	/* port-B */
2122		{ "Line", 0x2 },	/* port-C */
2123		{ "Mic", 0x4 },		/* port-E */
2124		{ "CD", 0x5 },
2125		{ "Mix", 0x9 },
2126	},
2127};
2128
2129static const struct hda_input_mux ad1988_laptop_capture_source = {
2130	.num_items = 3,
2131	.items = {
2132		{ "Mic/Line", 0x1 },	/* port-B */
2133		{ "CD", 0x5 },
2134		{ "Mix", 0x9 },
2135	},
2136};
2137
2138/*
2139 */
2140static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2141			       struct snd_ctl_elem_info *uinfo)
2142{
2143	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2144	struct ad198x_spec *spec = codec->spec;
2145	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2146				    spec->num_channel_mode);
2147}
2148
2149static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2150			      struct snd_ctl_elem_value *ucontrol)
2151{
2152	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2153	struct ad198x_spec *spec = codec->spec;
2154	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2155				   spec->num_channel_mode, spec->multiout.max_channels);
2156}
2157
2158static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2159			      struct snd_ctl_elem_value *ucontrol)
2160{
2161	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2162	struct ad198x_spec *spec = codec->spec;
2163	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2164				      spec->num_channel_mode,
2165				      &spec->multiout.max_channels);
2166	if (err >= 0 && spec->need_dac_fix)
2167		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2168	return err;
2169}
2170
2171/* 6-stack mode */
2172static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2173	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2174	HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2175	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2176	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2177	HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2178	{ } /* end */
2179};
2180
2181static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2182	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2183	HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2184	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2185	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2186	HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2187	{ } /* end */
2188};
2189
2190static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2191	HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2192	HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2193	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2194	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2195	HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2196	HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2197	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2198
2199	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2200	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2201	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2202	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2203	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2204	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2205	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2206	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2207
2208	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2209	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2210
2211	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2212	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2213
2214	{ } /* end */
2215};
2216
2217static const struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
2218	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2219
2220	{ } /* end */
2221};
2222
2223/* 3-stack mode */
2224static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2225	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2226	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2227	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2228	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2229	{ } /* end */
2230};
2231
2232static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2233	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2234	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2235	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2236	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2237	{ } /* end */
2238};
2239
2240static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2241	HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2242	HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2243	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2244	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2245	HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2246	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2247
2248	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2249	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2250	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2251	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2252	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2253	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2254	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2255	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2256
2257	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2258	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2259
2260	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2261	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2262	{
2263		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2264		.name = "Channel Mode",
2265		.info = ad198x_ch_mode_info,
2266		.get = ad198x_ch_mode_get,
2267		.put = ad198x_ch_mode_put,
2268	},
2269
2270	{ } /* end */
2271};
2272
2273/* laptop mode */
2274static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2275	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2276	HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2277	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2278
2279	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2280	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2281	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2282	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2283	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2284	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2285
2286	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2287	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2288
2289	HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2290
2291	{
2292		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2293		.name = "External Amplifier",
2294		.subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2295		.info = ad198x_eapd_info,
2296		.get = ad198x_eapd_get,
2297		.put = ad198x_eapd_put,
2298		.private_value = 0x12, /* port-D */
2299	},
2300
2301	{ } /* end */
2302};
2303
2304/* capture */
2305static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
2306	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2307	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2308	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2309	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2310	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2311	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2312	{
2313		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2314		/* The multiple "Capture Source" controls confuse alsamixer
2315		 * So call somewhat different..
2316		 */
2317		/* .name = "Capture Source", */
2318		.name = "Input Source",
2319		.count = 3,
2320		.info = ad198x_mux_enum_info,
2321		.get = ad198x_mux_enum_get,
2322		.put = ad198x_mux_enum_put,
2323	},
2324	{ } /* end */
2325};
2326
2327static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2328					     struct snd_ctl_elem_info *uinfo)
2329{
2330	static const char * const texts[] = {
2331		"PCM", "ADC1", "ADC2", "ADC3"
2332	};
2333	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2334	uinfo->count = 1;
2335	uinfo->value.enumerated.items = 4;
2336	if (uinfo->value.enumerated.item >= 4)
2337		uinfo->value.enumerated.item = 3;
2338	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2339	return 0;
2340}
2341
2342static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2343					    struct snd_ctl_elem_value *ucontrol)
2344{
2345	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2346	unsigned int sel;
2347
2348	sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2349				 AC_AMP_GET_INPUT);
2350	if (!(sel & 0x80))
2351		ucontrol->value.enumerated.item[0] = 0;
2352	else {
2353		sel = snd_hda_codec_read(codec, 0x0b, 0,
2354					 AC_VERB_GET_CONNECT_SEL, 0);
2355		if (sel < 3)
2356			sel++;
2357		else
2358			sel = 0;
2359		ucontrol->value.enumerated.item[0] = sel;
2360	}
2361	return 0;
2362}
2363
2364static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2365					    struct snd_ctl_elem_value *ucontrol)
2366{
2367	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2368	unsigned int val, sel;
2369	int change;
 
 
2370
2371	val = ucontrol->value.enumerated.item[0];
2372	if (val > 3)
2373		return -EINVAL;
2374	if (!val) {
2375		sel = snd_hda_codec_read(codec, 0x1d, 0,
2376					 AC_VERB_GET_AMP_GAIN_MUTE,
2377					 AC_AMP_GET_INPUT);
2378		change = sel & 0x80;
2379		if (change) {
2380			snd_hda_codec_write_cache(codec, 0x1d, 0,
2381						  AC_VERB_SET_AMP_GAIN_MUTE,
2382						  AMP_IN_UNMUTE(0));
2383			snd_hda_codec_write_cache(codec, 0x1d, 0,
2384						  AC_VERB_SET_AMP_GAIN_MUTE,
2385						  AMP_IN_MUTE(1));
2386		}
2387	} else {
2388		sel = snd_hda_codec_read(codec, 0x1d, 0,
2389					 AC_VERB_GET_AMP_GAIN_MUTE,
2390					 AC_AMP_GET_INPUT | 0x01);
2391		change = sel & 0x80;
2392		if (change) {
2393			snd_hda_codec_write_cache(codec, 0x1d, 0,
2394						  AC_VERB_SET_AMP_GAIN_MUTE,
2395						  AMP_IN_MUTE(0));
2396			snd_hda_codec_write_cache(codec, 0x1d, 0,
2397						  AC_VERB_SET_AMP_GAIN_MUTE,
2398						  AMP_IN_UNMUTE(1));
2399		}
2400		sel = snd_hda_codec_read(codec, 0x0b, 0,
2401					 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2402		change |= sel != val;
2403		if (change)
2404			snd_hda_codec_write_cache(codec, 0x0b, 0,
2405						  AC_VERB_SET_CONNECT_SEL,
2406						  val - 1);
2407	}
2408	return change;
2409}
2410
2411static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2412	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2413	{
2414		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2415		.name = "IEC958 Playback Source",
2416		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2417		.info = ad1988_spdif_playback_source_info,
2418		.get = ad1988_spdif_playback_source_get,
2419		.put = ad1988_spdif_playback_source_put,
2420	},
2421	{ } /* end */
2422};
2423
2424static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2425	HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2426	{ } /* end */
2427};
2428
2429static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2430	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2431	HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2432	{ } /* end */
2433};
2434
2435/*
2436 * initialization verbs
2437 */
2438
2439/*
2440 * for 6-stack (+dig)
2441 */
2442static const struct hda_verb ad1988_6stack_init_verbs[] = {
2443	/* Front, Surround, CLFE, side DAC; unmute as default */
2444	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2445	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2446	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2447	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2448	/* Port-A front headphon path */
2449	{0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2450	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2451	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2452	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2453	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2454	/* Port-D line-out path */
2455	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2456	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2457	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2458	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2459	/* Port-F surround path */
2460	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2461	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2462	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2463	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2464	/* Port-G CLFE path */
2465	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2466	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2467	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2468	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2469	/* Port-H side path */
2470	{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2471	{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2472	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2473	{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2474	/* Mono out path */
2475	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2476	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2477	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2478	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2479	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2480	/* Port-B front mic-in path */
2481	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2482	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2483	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2484	/* Port-C line-in path */
2485	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2486	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2487	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2488	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2489	/* Port-E mic-in path */
2490	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2491	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2492	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2493	{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2494	/* Analog CD Input */
2495	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2496	/* Analog Mix output amp */
2497	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2498
2499	{ }
2500};
2501
2502static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
2503	/* Headphone; unmute as default */
2504	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2505	/* Port-A front headphon path */
2506	{0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2507	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2508	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2509	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2510	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2511
2512	{ }
2513};
2514
2515static const struct hda_verb ad1988_capture_init_verbs[] = {
2516	/* mute analog mix */
2517	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2518	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2519	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2520	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2521	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2522	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2523	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2524	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2525	/* select ADCs - front-mic */
2526	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2527	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2528	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2529
2530	{ }
2531};
2532
2533static const struct hda_verb ad1988_spdif_init_verbs[] = {
2534	/* SPDIF out sel */
2535	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2536	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2537	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2538	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2539	/* SPDIF out pin */
2540	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2541
2542	{ }
2543};
2544
2545static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
2546	/* unmute SPDIF input pin */
2547	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2548	{ }
2549};
2550
2551/* AD1989 has no ADC -> SPDIF route */
2552static const struct hda_verb ad1989_spdif_init_verbs[] = {
2553	/* SPDIF-1 out pin */
2554	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2555	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2556	/* SPDIF-2/HDMI out pin */
2557	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2558	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2559	{ }
2560};
2561
2562/*
2563 * verbs for 3stack (+dig)
2564 */
2565static const struct hda_verb ad1988_3stack_ch2_init[] = {
2566	/* set port-C to line-in */
2567	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2568	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2569	/* set port-E to mic-in */
2570	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2571	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2572	{ } /* end */
2573};
2574
2575static const struct hda_verb ad1988_3stack_ch6_init[] = {
2576	/* set port-C to surround out */
2577	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2578	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2579	/* set port-E to CLFE out */
2580	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2581	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2582	{ } /* end */
2583};
2584
2585static const struct hda_channel_mode ad1988_3stack_modes[2] = {
2586	{ 2, ad1988_3stack_ch2_init },
2587	{ 6, ad1988_3stack_ch6_init },
2588};
2589
2590static const struct hda_verb ad1988_3stack_init_verbs[] = {
2591	/* Front, Surround, CLFE, side DAC; unmute as default */
2592	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2593	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2594	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2595	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2596	/* Port-A front headphon path */
2597	{0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2598	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2599	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2600	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2601	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2602	/* Port-D line-out path */
2603	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2604	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2605	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2606	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2607	/* Mono out path */
2608	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2609	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2610	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2611	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2612	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2613	/* Port-B front mic-in path */
2614	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2615	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2616	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2617	/* Port-C line-in/surround path - 6ch mode as default */
2618	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2619	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2620	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2621	{0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2622	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2623	/* Port-E mic-in/CLFE path - 6ch mode as default */
2624	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2625	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2626	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2627	{0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2628	{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2629	/* mute analog mix */
2630	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2631	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2632	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2633	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2634	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2635	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2636	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2637	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2638	/* select ADCs - front-mic */
2639	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2640	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2641	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2642	/* Analog Mix output amp */
2643	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2644	{ }
2645};
2646
2647/*
2648 * verbs for laptop mode (+dig)
2649 */
2650static const struct hda_verb ad1988_laptop_hp_on[] = {
2651	/* unmute port-A and mute port-D */
2652	{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2653	{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2654	{ } /* end */
2655};
2656static const struct hda_verb ad1988_laptop_hp_off[] = {
2657	/* mute port-A and unmute port-D */
2658	{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2659	{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2660	{ } /* end */
2661};
2662
2663#define AD1988_HP_EVENT	0x01
2664
2665static const struct hda_verb ad1988_laptop_init_verbs[] = {
2666	/* Front, Surround, CLFE, side DAC; unmute as default */
2667	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2668	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2669	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2670	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2671	/* Port-A front headphon path */
2672	{0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2673	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2674	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2675	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2676	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2677	/* unsolicited event for pin-sense */
2678	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2679	/* Port-D line-out path + EAPD */
2680	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2681	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2682	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2683	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2684	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2685	/* Mono out path */
2686	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2687	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2688	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2689	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2690	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2691	/* Port-B mic-in path */
2692	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2693	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2694	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2695	/* Port-C docking station - try to output */
2696	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2697	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2698	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2699	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2700	/* mute analog mix */
2701	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2702	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2703	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2704	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2705	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2706	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2707	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2708	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2709	/* select ADCs - mic */
2710	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2711	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2712	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2713	/* Analog Mix output amp */
2714	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2715	{ }
2716};
2717
2718static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2719{
2720	if ((res >> 26) != AD1988_HP_EVENT)
2721		return;
2722	if (snd_hda_jack_detect(codec, 0x11))
2723		snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2724	else
2725		snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2726} 
2727
2728#ifdef CONFIG_SND_HDA_POWER_SAVE
2729static const struct hda_amp_list ad1988_loopbacks[] = {
2730	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
2731	{ 0x20, HDA_INPUT, 1 }, /* Line */
2732	{ 0x20, HDA_INPUT, 4 }, /* Mic */
2733	{ 0x20, HDA_INPUT, 6 }, /* CD */
2734	{ } /* end */
2735};
2736#endif
2737
2738/*
2739 * Automatic parse of I/O pins from the BIOS configuration
2740 */
2741
2742enum {
2743	AD_CTL_WIDGET_VOL,
2744	AD_CTL_WIDGET_MUTE,
2745	AD_CTL_BIND_MUTE,
2746};
2747static const struct snd_kcontrol_new ad1988_control_templates[] = {
2748	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2749	HDA_CODEC_MUTE(NULL, 0, 0, 0),
2750	HDA_BIND_MUTE(NULL, 0, 0, 0),
2751};
2752
2753/* add dynamic controls */
2754static int add_control(struct ad198x_spec *spec, int type, const char *name,
2755		       unsigned long val)
2756{
2757	struct snd_kcontrol_new *knew;
2758
2759	snd_array_init(&spec->kctls, sizeof(*knew), 32);
2760	knew = snd_array_new(&spec->kctls);
2761	if (!knew)
2762		return -ENOMEM;
2763	*knew = ad1988_control_templates[type];
2764	knew->name = kstrdup(name, GFP_KERNEL);
2765	if (! knew->name)
2766		return -ENOMEM;
2767	if (get_amp_nid_(val))
2768		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2769	knew->private_value = val;
2770	return 0;
2771}
2772
2773#define AD1988_PIN_CD_NID		0x18
2774#define AD1988_PIN_BEEP_NID		0x10
2775
2776static const hda_nid_t ad1988_mixer_nids[8] = {
2777	/* A     B     C     D     E     F     G     H */
2778	0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2779};
2780
2781static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2782{
2783	static const hda_nid_t idx_to_dac[8] = {
2784		/* A     B     C     D     E     F     G     H */
2785		0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2786	};
2787	static const hda_nid_t idx_to_dac_rev2[8] = {
2788		/* A     B     C     D     E     F     G     H */
2789		0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2790	};
2791	if (is_rev2(codec))
2792		return idx_to_dac_rev2[idx];
2793	else
2794		return idx_to_dac[idx];
2795}
2796
2797static const hda_nid_t ad1988_boost_nids[8] = {
2798	0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2799};
2800
2801static int ad1988_pin_idx(hda_nid_t nid)
2802{
2803	static const hda_nid_t ad1988_io_pins[8] = {
2804		0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2805	};
2806	int i;
2807	for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2808		if (ad1988_io_pins[i] == nid)
2809			return i;
2810	return 0; /* should be -1 */
2811}
2812
2813static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2814{
2815	static const int loopback_idx[8] = {
2816		2, 0, 1, 3, 4, 5, 1, 4
2817	};
2818	switch (nid) {
2819	case AD1988_PIN_CD_NID:
2820		return 6;
2821	default:
2822		return loopback_idx[ad1988_pin_idx(nid)];
2823	}
2824}
2825
2826static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2827{
2828	static const int adc_idx[8] = {
2829		0, 1, 2, 8, 4, 3, 6, 7
2830	};
2831	switch (nid) {
2832	case AD1988_PIN_CD_NID:
2833		return 5;
2834	default:
2835		return adc_idx[ad1988_pin_idx(nid)];
2836	}
2837}
2838
2839/* fill in the dac_nids table from the parsed pin configuration */
2840static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2841				     const struct auto_pin_cfg *cfg)
2842{
2843	struct ad198x_spec *spec = codec->spec;
2844	int i, idx;
2845
2846	spec->multiout.dac_nids = spec->private_dac_nids;
2847
2848	/* check the pins hardwired to audio widget */
2849	for (i = 0; i < cfg->line_outs; i++) {
2850		idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2851		spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2852	}
2853	spec->multiout.num_dacs = cfg->line_outs;
2854	return 0;
2855}
2856
2857/* add playback controls from the parsed DAC table */
2858static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2859					     const struct auto_pin_cfg *cfg)
2860{
2861	char name[32];
2862	static const char * const chname[4] = {
2863		"Front", "Surround", NULL /*CLFE*/, "Side"
2864	};
2865	hda_nid_t nid;
2866	int i, err;
2867
2868	for (i = 0; i < cfg->line_outs; i++) {
2869		hda_nid_t dac = spec->multiout.dac_nids[i];
2870		if (! dac)
2871			continue;
2872		nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2873		if (i == 2) {
2874			/* Center/LFE */
2875			err = add_control(spec, AD_CTL_WIDGET_VOL,
2876					  "Center Playback Volume",
2877					  HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2878			if (err < 0)
2879				return err;
2880			err = add_control(spec, AD_CTL_WIDGET_VOL,
2881					  "LFE Playback Volume",
2882					  HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2883			if (err < 0)
2884				return err;
2885			err = add_control(spec, AD_CTL_BIND_MUTE,
2886					  "Center Playback Switch",
2887					  HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2888			if (err < 0)
2889				return err;
2890			err = add_control(spec, AD_CTL_BIND_MUTE,
2891					  "LFE Playback Switch",
2892					  HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2893			if (err < 0)
2894				return err;
2895		} else {
2896			sprintf(name, "%s Playback Volume", chname[i]);
2897			err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2898					  HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2899			if (err < 0)
2900				return err;
2901			sprintf(name, "%s Playback Switch", chname[i]);
2902			err = add_control(spec, AD_CTL_BIND_MUTE, name,
2903					  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2904			if (err < 0)
2905				return err;
2906		}
2907	}
2908	return 0;
2909}
2910
2911/* add playback controls for speaker and HP outputs */
2912static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2913					const char *pfx)
2914{
2915	struct ad198x_spec *spec = codec->spec;
2916	hda_nid_t nid;
2917	int i, idx, err;
2918	char name[32];
2919
2920	if (! pin)
2921		return 0;
2922
2923	idx = ad1988_pin_idx(pin);
2924	nid = ad1988_idx_to_dac(codec, idx);
2925	/* check whether the corresponding DAC was already taken */
2926	for (i = 0; i < spec->autocfg.line_outs; i++) {
2927		hda_nid_t pin = spec->autocfg.line_out_pins[i];
2928		hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2929		if (dac == nid)
2930			break;
2931	}
2932	if (i >= spec->autocfg.line_outs) {
2933		/* specify the DAC as the extra output */
2934		if (!spec->multiout.hp_nid)
2935			spec->multiout.hp_nid = nid;
2936		else
2937			spec->multiout.extra_out_nid[0] = nid;
2938		/* control HP volume/switch on the output mixer amp */
2939		sprintf(name, "%s Playback Volume", pfx);
2940		err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2941				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2942		if (err < 0)
2943			return err;
2944	}
2945	nid = ad1988_mixer_nids[idx];
2946	sprintf(name, "%s Playback Switch", pfx);
2947	if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2948			       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2949		return err;
2950	return 0;
2951}
2952
2953/* create input playback/capture controls for the given pin */
2954static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2955			    const char *ctlname, int ctlidx, int boost)
2956{
2957	char name[32];
2958	int err, idx;
2959
2960	sprintf(name, "%s Playback Volume", ctlname);
2961	idx = ad1988_pin_to_loopback_idx(pin);
2962	if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2963			       HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2964		return err;
2965	sprintf(name, "%s Playback Switch", ctlname);
2966	if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2967			       HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2968		return err;
2969	if (boost) {
2970		hda_nid_t bnid;
2971		idx = ad1988_pin_idx(pin);
2972		bnid = ad1988_boost_nids[idx];
2973		if (bnid) {
2974			sprintf(name, "%s Boost Volume", ctlname);
2975			return add_control(spec, AD_CTL_WIDGET_VOL, name,
2976					   HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2977
2978		}
2979	}
2980	return 0;
2981}
2982
2983/* create playback/capture controls for input pins */
2984static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
2985						const struct auto_pin_cfg *cfg)
2986{
2987	struct ad198x_spec *spec = codec->spec;
2988	struct hda_input_mux *imux = &spec->private_imux;
2989	int i, err, type, type_idx;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2990
2991	for (i = 0; i < cfg->num_inputs; i++) {
2992		const char *label;
2993		type = cfg->inputs[i].type;
2994		label = hda_get_autocfg_input_label(codec, cfg, i);
2995		snd_hda_add_imux_item(imux, label,
2996				      ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
2997				      &type_idx);
2998		err = new_analog_input(spec, cfg->inputs[i].pin,
2999				       label, type_idx,
3000				       type == AUTO_PIN_MIC);
3001		if (err < 0)
3002			return err;
3003	}
3004	snd_hda_add_imux_item(imux, "Mix", 9, NULL);
3005
3006	if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
3007			       "Analog Mix Playback Volume",
3008			       HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3009		return err;
3010	if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
3011			       "Analog Mix Playback Switch",
3012			       HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3013		return err;
3014
3015	return 0;
3016}
3017
3018static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
3019					      hda_nid_t nid, int pin_type,
3020					      int dac_idx)
3021{
3022	/* set as output */
3023	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3024	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3025	switch (nid) {
3026	case 0x11: /* port-A - DAC 04 */
3027		snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3028		break;
3029	case 0x14: /* port-B - DAC 06 */
3030		snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
3031		break;
3032	case 0x15: /* port-C - DAC 05 */
3033		snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
3034		break;
3035	case 0x17: /* port-E - DAC 0a */
3036		snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3037		break;
3038	case 0x13: /* mono - DAC 04 */
3039		snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3040		break;
3041	}
3042}
3043
3044static void ad1988_auto_init_multi_out(struct hda_codec *codec)
3045{
3046	struct ad198x_spec *spec = codec->spec;
3047	int i;
3048
3049	for (i = 0; i < spec->autocfg.line_outs; i++) {
3050		hda_nid_t nid = spec->autocfg.line_out_pins[i];
3051		ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3052	}
3053}
3054
3055static void ad1988_auto_init_extra_out(struct hda_codec *codec)
3056{
3057	struct ad198x_spec *spec = codec->spec;
3058	hda_nid_t pin;
3059
3060	pin = spec->autocfg.speaker_pins[0];
3061	if (pin) /* connect to front */
3062		ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
3063	pin = spec->autocfg.hp_pins[0];
3064	if (pin) /* connect to front */
3065		ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3066}
3067
3068static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3069{
3070	struct ad198x_spec *spec = codec->spec;
3071	const struct auto_pin_cfg *cfg = &spec->autocfg;
3072	int i, idx;
3073
3074	for (i = 0; i < cfg->num_inputs; i++) {
3075		hda_nid_t nid = cfg->inputs[i].pin;
3076		int type = cfg->inputs[i].type;
3077		switch (nid) {
3078		case 0x15: /* port-C */
3079			snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3080			break;
3081		case 0x17: /* port-E */
3082			snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3083			break;
3084		}
3085		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3086				    type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
3087		if (nid != AD1988_PIN_CD_NID)
3088			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3089					    AMP_OUT_MUTE);
3090		idx = ad1988_pin_idx(nid);
3091		if (ad1988_boost_nids[idx])
3092			snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3093					    AC_VERB_SET_AMP_GAIN_MUTE,
3094					    AMP_OUT_ZERO);
3095	}
3096}
3097
3098/* parse the BIOS configuration and set up the alc_spec */
3099/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3100static int ad1988_parse_auto_config(struct hda_codec *codec)
3101{
3102	struct ad198x_spec *spec = codec->spec;
3103	int err;
3104
3105	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3106		return err;
3107	if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3108		return err;
3109	if (! spec->autocfg.line_outs)
3110		return 0; /* can't find valid BIOS pin config */
3111	if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3112	    (err = ad1988_auto_create_extra_out(codec,
3113						spec->autocfg.speaker_pins[0],
3114						"Speaker")) < 0 ||
3115	    (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3116						"Headphone")) < 0 ||
3117	    (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
3118		return err;
3119
3120	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3121
3122	if (spec->autocfg.dig_outs)
3123		spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3124	if (spec->autocfg.dig_in_pin)
3125		spec->dig_in_nid = AD1988_SPDIF_IN;
3126
3127	if (spec->kctls.list)
3128		spec->mixers[spec->num_mixers++] = spec->kctls.list;
3129
3130	spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3131
3132	spec->input_mux = &spec->private_imux;
3133
3134	return 1;
3135}
3136
3137/* init callback for auto-configuration model -- overriding the default init */
3138static int ad1988_auto_init(struct hda_codec *codec)
3139{
3140	ad198x_init(codec);
3141	ad1988_auto_init_multi_out(codec);
3142	ad1988_auto_init_extra_out(codec);
3143	ad1988_auto_init_analog_input(codec);
3144	return 0;
3145}
3146
3147/*
3148 */
3149
3150static const char * const ad1988_models[AD1988_MODEL_LAST] = {
3151	[AD1988_6STACK]		= "6stack",
3152	[AD1988_6STACK_DIG]	= "6stack-dig",
3153	[AD1988_6STACK_DIG_FP]	= "6stack-dig-fp",
3154	[AD1988_3STACK]		= "3stack",
3155	[AD1988_3STACK_DIG]	= "3stack-dig",
3156	[AD1988_LAPTOP]		= "laptop",
3157	[AD1988_LAPTOP_DIG]	= "laptop-dig",
3158	[AD1988_AUTO]		= "auto",
 
 
 
 
 
 
 
 
 
 
 
3159};
3160
3161static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
3162	SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3163	SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3164	SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3165	SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
3166	SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3167	{}
3168};
3169
3170static int patch_ad1988(struct hda_codec *codec)
3171{
3172	struct ad198x_spec *spec;
3173	int err, board_config;
3174
3175	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3176	if (spec == NULL)
3177		return -ENOMEM;
3178
3179	codec->spec = spec;
3180
3181	if (is_rev2(codec))
3182		snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3183
3184	board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3185						  ad1988_models, ad1988_cfg_tbl);
3186	if (board_config < 0) {
3187		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3188		       codec->chip_name);
3189		board_config = AD1988_AUTO;
3190	}
3191
3192	if (board_config == AD1988_AUTO) {
3193		/* automatic parse from the BIOS config */
3194		err = ad1988_parse_auto_config(codec);
3195		if (err < 0) {
3196			ad198x_free(codec);
3197			return err;
3198		} else if (! err) {
3199			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using 6-stack mode...\n");
3200			board_config = AD1988_6STACK;
3201		}
3202	}
3203
3204	err = snd_hda_attach_beep_device(codec, 0x10);
3205	if (err < 0) {
3206		ad198x_free(codec);
3207		return err;
3208	}
3209	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3210
3211	switch (board_config) {
3212	case AD1988_6STACK:
3213	case AD1988_6STACK_DIG:
3214	case AD1988_6STACK_DIG_FP:
3215		spec->multiout.max_channels = 8;
3216		spec->multiout.num_dacs = 4;
3217		if (is_rev2(codec))
3218			spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3219		else
3220			spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3221		spec->input_mux = &ad1988_6stack_capture_source;
3222		spec->num_mixers = 2;
3223		if (is_rev2(codec))
3224			spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3225		else
3226			spec->mixers[0] = ad1988_6stack_mixers1;
3227		spec->mixers[1] = ad1988_6stack_mixers2;
3228		spec->num_init_verbs = 1;
3229		spec->init_verbs[0] = ad1988_6stack_init_verbs;
3230		if (board_config == AD1988_6STACK_DIG_FP) {
3231			spec->num_mixers++;
3232			spec->mixers[2] = ad1988_6stack_fp_mixers;
3233			spec->num_init_verbs++;
3234			spec->init_verbs[1] = ad1988_6stack_fp_init_verbs;
3235			spec->slave_vols = ad1988_6stack_fp_slave_vols;
3236			spec->slave_sws = ad1988_6stack_fp_slave_sws;
3237			spec->alt_dac_nid = ad1988_alt_dac_nid;
3238			spec->stream_analog_alt_playback =
3239				&ad198x_pcm_analog_alt_playback;
3240		}
3241		if ((board_config == AD1988_6STACK_DIG) ||
3242			(board_config == AD1988_6STACK_DIG_FP)) {
3243			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3244			spec->dig_in_nid = AD1988_SPDIF_IN;
3245		}
3246		break;
3247	case AD1988_3STACK:
3248	case AD1988_3STACK_DIG:
3249		spec->multiout.max_channels = 6;
3250		spec->multiout.num_dacs = 3;
3251		if (is_rev2(codec))
3252			spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3253		else
3254			spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3255		spec->input_mux = &ad1988_6stack_capture_source;
3256		spec->channel_mode = ad1988_3stack_modes;
3257		spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3258		spec->num_mixers = 2;
3259		if (is_rev2(codec))
3260			spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3261		else
3262			spec->mixers[0] = ad1988_3stack_mixers1;
3263		spec->mixers[1] = ad1988_3stack_mixers2;
3264		spec->num_init_verbs = 1;
3265		spec->init_verbs[0] = ad1988_3stack_init_verbs;
3266		if (board_config == AD1988_3STACK_DIG)
3267			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3268		break;
3269	case AD1988_LAPTOP:
3270	case AD1988_LAPTOP_DIG:
3271		spec->multiout.max_channels = 2;
3272		spec->multiout.num_dacs = 1;
3273		spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3274		spec->input_mux = &ad1988_laptop_capture_source;
3275		spec->num_mixers = 1;
3276		spec->mixers[0] = ad1988_laptop_mixers;
3277		spec->inv_eapd = 1; /* inverted EAPD */
3278		spec->num_init_verbs = 1;
3279		spec->init_verbs[0] = ad1988_laptop_init_verbs;
3280		if (board_config == AD1988_LAPTOP_DIG)
3281			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3282		break;
3283	}
3284
3285	spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3286	spec->adc_nids = ad1988_adc_nids;
3287	spec->capsrc_nids = ad1988_capsrc_nids;
3288	spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3289	spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3290	if (spec->multiout.dig_out_nid) {
3291		if (codec->vendor_id >= 0x11d4989a) {
3292			spec->mixers[spec->num_mixers++] =
3293				ad1989_spdif_out_mixers;
3294			spec->init_verbs[spec->num_init_verbs++] =
3295				ad1989_spdif_init_verbs;
3296			codec->slave_dig_outs = ad1989b_slave_dig_outs;
3297		} else {
3298			spec->mixers[spec->num_mixers++] =
3299				ad1988_spdif_out_mixers;
3300			spec->init_verbs[spec->num_init_verbs++] =
3301				ad1988_spdif_init_verbs;
3302		}
3303	}
3304	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3305		spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3306		spec->init_verbs[spec->num_init_verbs++] =
3307			ad1988_spdif_in_init_verbs;
3308	}
3309
3310	codec->patch_ops = ad198x_patch_ops;
3311	switch (board_config) {
3312	case AD1988_AUTO:
3313		codec->patch_ops.init = ad1988_auto_init;
3314		break;
3315	case AD1988_LAPTOP:
3316	case AD1988_LAPTOP_DIG:
3317		codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3318		break;
3319	}
3320#ifdef CONFIG_SND_HDA_POWER_SAVE
3321	spec->loopback.amplist = ad1988_loopbacks;
3322#endif
3323	spec->vmaster_nid = 0x04;
3324
3325	codec->no_trigger_sense = 1;
3326	codec->no_sticky_stream = 1;
3327
3328	return 0;
 
 
3329}
3330
3331
3332/*
3333 * AD1884 / AD1984
3334 *
3335 * port-B - front line/mic-in
3336 * port-E - aux in/out
3337 * port-F - aux in/out
3338 * port-C - rear line/mic-in
3339 * port-D - rear line/hp-out
3340 * port-A - front line/hp-out
3341 *
3342 * AD1984 = AD1884 + two digital mic-ins
3343 *
3344 * FIXME:
3345 * For simplicity, we share the single DAC for both HP and line-outs
3346 * right now.  The inidividual playbacks could be easily implemented,
3347 * but no build-up framework is given, so far.
3348 */
3349
3350static const hda_nid_t ad1884_dac_nids[1] = {
3351	0x04,
3352};
3353
3354static const hda_nid_t ad1884_adc_nids[2] = {
3355	0x08, 0x09,
3356};
3357
3358static const hda_nid_t ad1884_capsrc_nids[2] = {
3359	0x0c, 0x0d,
3360};
3361
3362#define AD1884_SPDIF_OUT	0x02
3363
3364static const struct hda_input_mux ad1884_capture_source = {
3365	.num_items = 4,
3366	.items = {
3367		{ "Front Mic", 0x0 },
3368		{ "Mic", 0x1 },
3369		{ "CD", 0x2 },
3370		{ "Mix", 0x3 },
3371	},
3372};
3373
3374static const struct snd_kcontrol_new ad1884_base_mixers[] = {
3375	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3376	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3377	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3378	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3379	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3380	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3381	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3382	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3383	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3384	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3385	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3386	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3387	HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3388	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3389	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3390	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3391	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3392	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3393	{
3394		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3395		/* The multiple "Capture Source" controls confuse alsamixer
3396		 * So call somewhat different..
3397		 */
3398		/* .name = "Capture Source", */
3399		.name = "Input Source",
3400		.count = 2,
3401		.info = ad198x_mux_enum_info,
3402		.get = ad198x_mux_enum_get,
3403		.put = ad198x_mux_enum_put,
3404	},
3405	/* SPDIF controls */
3406	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3407	{
3408		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3409		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3410		/* identical with ad1983 */
3411		.info = ad1983_spdif_route_info,
3412		.get = ad1983_spdif_route_get,
3413		.put = ad1983_spdif_route_put,
3414	},
3415	{ } /* end */
3416};
3417
3418static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3419	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3420	HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3421	HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3422			     HDA_INPUT),
3423	HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3424			   HDA_INPUT),
3425	{ } /* end */
3426};
3427
3428/*
3429 * initialization verbs
3430 */
3431static const struct hda_verb ad1884_init_verbs[] = {
3432	/* DACs; mute as default */
3433	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3434	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3435	/* Port-A (HP) mixer */
3436	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3437	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3438	/* Port-A pin */
3439	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3440	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3441	/* HP selector - select DAC2 */
3442	{0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3443	/* Port-D (Line-out) mixer */
3444	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3445	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3446	/* Port-D pin */
3447	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3448	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3449	/* Mono-out mixer */
3450	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3451	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3452	/* Mono-out pin */
3453	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3454	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3455	/* Mono selector */
3456	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3457	/* Port-B (front mic) pin */
3458	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3459	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3460	/* Port-C (rear mic) pin */
3461	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3462	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3463	/* Analog mixer; mute as default */
3464	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3465	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3466	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3467	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3468	/* Analog Mix output amp */
3469	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3470	/* SPDIF output selector */
3471	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3472	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3473	{ } /* end */
3474};
3475
3476#ifdef CONFIG_SND_HDA_POWER_SAVE
3477static const struct hda_amp_list ad1884_loopbacks[] = {
3478	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
3479	{ 0x20, HDA_INPUT, 1 }, /* Mic */
3480	{ 0x20, HDA_INPUT, 2 }, /* CD */
3481	{ 0x20, HDA_INPUT, 4 }, /* Docking */
3482	{ } /* end */
3483};
3484#endif
3485
3486static const char * const ad1884_slave_vols[] = {
3487	"PCM Playback Volume",
3488	"Mic Playback Volume",
3489	"Mono Playback Volume",
3490	"Front Mic Playback Volume",
3491	"Mic Playback Volume",
3492	"CD Playback Volume",
3493	"Internal Mic Playback Volume",
3494	"Docking Mic Playback Volume",
3495	/* "Beep Playback Volume", */
3496	"IEC958 Playback Volume",
3497	NULL
3498};
3499
3500static int patch_ad1884(struct hda_codec *codec)
3501{
3502	struct ad198x_spec *spec;
3503	int err;
3504
3505	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3506	if (spec == NULL)
3507		return -ENOMEM;
3508
3509	codec->spec = spec;
3510
3511	err = snd_hda_attach_beep_device(codec, 0x10);
3512	if (err < 0) {
3513		ad198x_free(codec);
3514		return err;
3515	}
3516	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3517
3518	spec->multiout.max_channels = 2;
3519	spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3520	spec->multiout.dac_nids = ad1884_dac_nids;
3521	spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3522	spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3523	spec->adc_nids = ad1884_adc_nids;
3524	spec->capsrc_nids = ad1884_capsrc_nids;
3525	spec->input_mux = &ad1884_capture_source;
3526	spec->num_mixers = 1;
3527	spec->mixers[0] = ad1884_base_mixers;
3528	spec->num_init_verbs = 1;
3529	spec->init_verbs[0] = ad1884_init_verbs;
3530	spec->spdif_route = 0;
3531#ifdef CONFIG_SND_HDA_POWER_SAVE
3532	spec->loopback.amplist = ad1884_loopbacks;
3533#endif
3534	spec->vmaster_nid = 0x04;
3535	/* we need to cover all playback volumes */
3536	spec->slave_vols = ad1884_slave_vols;
3537
3538	codec->patch_ops = ad198x_patch_ops;
3539
3540	codec->no_trigger_sense = 1;
3541	codec->no_sticky_stream = 1;
3542
3543	return 0;
3544}
3545
3546/*
3547 * Lenovo Thinkpad T61/X61
3548 */
3549static const struct hda_input_mux ad1984_thinkpad_capture_source = {
3550	.num_items = 4,
3551	.items = {
3552		{ "Mic", 0x0 },
3553		{ "Internal Mic", 0x1 },
3554		{ "Mix", 0x3 },
3555		{ "Docking-Station", 0x4 },
3556	},
3557};
3558
3559
3560/*
3561 * Dell Precision T3400
3562 */
3563static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
3564	.num_items = 3,
3565	.items = {
3566		{ "Front Mic", 0x0 },
3567		{ "Line-In", 0x1 },
3568		{ "Mix", 0x3 },
3569	},
3570};
3571
3572
3573static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3574	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3575	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3576	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3577	HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3578	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3579	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3580	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3581	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3582	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3583	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3584	HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3585	HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3586	HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3587	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3588	HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3589	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3590	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3591	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3592	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3593	{
3594		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3595		/* The multiple "Capture Source" controls confuse alsamixer
3596		 * So call somewhat different..
3597		 */
3598		/* .name = "Capture Source", */
3599		.name = "Input Source",
3600		.count = 2,
3601		.info = ad198x_mux_enum_info,
3602		.get = ad198x_mux_enum_get,
3603		.put = ad198x_mux_enum_put,
3604	},
3605	/* SPDIF controls */
3606	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3607	{
3608		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3609		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3610		/* identical with ad1983 */
3611		.info = ad1983_spdif_route_info,
3612		.get = ad1983_spdif_route_get,
3613		.put = ad1983_spdif_route_put,
3614	},
3615	{ } /* end */
3616};
3617
3618/* additional verbs */
3619static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
3620	/* Port-E (docking station mic) pin */
3621	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3622	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3623	/* docking mic boost */
3624	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3625	/* Analog PC Beeper - allow firmware/ACPI beeps */
3626	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3627	/* Analog mixer - docking mic; mute as default */
3628	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3629	/* enable EAPD bit */
3630	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3631	{ } /* end */
3632};
3633
3634/*
3635 * Dell Precision T3400
3636 */
3637static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3638	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3639	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3640	HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3641	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3642	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3643	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3644	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3645	HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3646	HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3647	HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
3648	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3649	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3650	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3651	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3652	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3653	{
3654		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3655		/* The multiple "Capture Source" controls confuse alsamixer
3656		 * So call somewhat different..
3657		 */
3658		/* .name = "Capture Source", */
3659		.name = "Input Source",
3660		.count = 2,
3661		.info = ad198x_mux_enum_info,
3662		.get = ad198x_mux_enum_get,
3663		.put = ad198x_mux_enum_put,
3664	},
3665	{ } /* end */
3666};
3667
3668/* Digial MIC ADC NID 0x05 + 0x06 */
3669static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3670				   struct hda_codec *codec,
3671				   unsigned int stream_tag,
3672				   unsigned int format,
3673				   struct snd_pcm_substream *substream)
3674{
3675	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3676				   stream_tag, 0, format);
3677	return 0;
3678}
3679
3680static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3681				   struct hda_codec *codec,
3682				   struct snd_pcm_substream *substream)
3683{
3684	snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3685	return 0;
3686}
3687
3688static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3689	.substreams = 2,
3690	.channels_min = 2,
3691	.channels_max = 2,
3692	.nid = 0x05,
3693	.ops = {
3694		.prepare = ad1984_pcm_dmic_prepare,
3695		.cleanup = ad1984_pcm_dmic_cleanup
3696	},
3697};
3698
3699static int ad1984_build_pcms(struct hda_codec *codec)
3700{
3701	struct ad198x_spec *spec = codec->spec;
3702	struct hda_pcm *info;
3703	int err;
3704
3705	err = ad198x_build_pcms(codec);
3706	if (err < 0)
3707		return err;
3708
3709	info = spec->pcm_rec + codec->num_pcms;
3710	codec->num_pcms++;
3711	info->name = "AD1984 Digital Mic";
3712	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3713	return 0;
3714}
3715
3716/* models */
3717enum {
3718	AD1984_BASIC,
3719	AD1984_THINKPAD,
3720	AD1984_DELL_DESKTOP,
3721	AD1984_MODELS
3722};
3723
3724static const char * const ad1984_models[AD1984_MODELS] = {
3725	[AD1984_BASIC]		= "basic",
3726	[AD1984_THINKPAD]	= "thinkpad",
3727	[AD1984_DELL_DESKTOP]	= "dell_desktop",
3728};
3729
3730static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
3731	/* Lenovo Thinkpad T61/X61 */
3732	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3733	SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3734	SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
3735	{}
3736};
3737
3738static int patch_ad1984(struct hda_codec *codec)
3739{
3740	struct ad198x_spec *spec;
3741	int board_config, err;
3742
3743	err = patch_ad1884(codec);
3744	if (err < 0)
3745		return err;
3746	spec = codec->spec;
3747	board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3748						  ad1984_models, ad1984_cfg_tbl);
3749	switch (board_config) {
3750	case AD1984_BASIC:
3751		/* additional digital mics */
3752		spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3753		codec->patch_ops.build_pcms = ad1984_build_pcms;
3754		break;
3755	case AD1984_THINKPAD:
3756		if (codec->subsystem_id == 0x17aa20fb) {
3757			/* Thinpad X300 does not have the ability to do SPDIF,
3758			   or attach to docking station to use SPDIF */
3759			spec->multiout.dig_out_nid = 0;
3760		} else
3761			spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3762		spec->input_mux = &ad1984_thinkpad_capture_source;
3763		spec->mixers[0] = ad1984_thinkpad_mixers;
3764		spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3765		spec->analog_beep = 1;
3766		break;
3767	case AD1984_DELL_DESKTOP:
3768		spec->multiout.dig_out_nid = 0;
3769		spec->input_mux = &ad1984_dell_desktop_capture_source;
3770		spec->mixers[0] = ad1984_dell_desktop_mixers;
3771		break;
3772	}
3773	return 0;
3774}
3775
3776
3777/*
3778 * AD1883 / AD1884A / AD1984A / AD1984B
3779 *
3780 * port-B (0x14) - front mic-in
3781 * port-E (0x1c) - rear mic-in
3782 * port-F (0x16) - CD / ext out
3783 * port-C (0x15) - rear line-in
3784 * port-D (0x12) - rear line-out
3785 * port-A (0x11) - front hp-out
3786 *
3787 * AD1984A = AD1884A + digital-mic
3788 * AD1883 = equivalent with AD1984A
3789 * AD1984B = AD1984A + extra SPDIF-out
3790 *
3791 * FIXME:
3792 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3793 */
3794
3795static const hda_nid_t ad1884a_dac_nids[1] = {
3796	0x03,
3797};
3798
3799#define ad1884a_adc_nids	ad1884_adc_nids
3800#define ad1884a_capsrc_nids	ad1884_capsrc_nids
3801
3802#define AD1884A_SPDIF_OUT	0x02
3803
3804static const struct hda_input_mux ad1884a_capture_source = {
3805	.num_items = 5,
3806	.items = {
3807		{ "Front Mic", 0x0 },
3808		{ "Mic", 0x4 },
3809		{ "Line", 0x1 },
3810		{ "CD", 0x2 },
3811		{ "Mix", 0x3 },
3812	},
3813};
3814
3815static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
3816	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3817	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3818	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3819	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3820	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3821	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3822	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3823	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3824	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3825	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3826	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3827	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3828	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3829	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3830	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3831	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3832	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3833	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
3834	HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3835	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3836	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3837	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3838	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3839	{
3840		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3841		/* The multiple "Capture Source" controls confuse alsamixer
3842		 * So call somewhat different..
3843		 */
3844		/* .name = "Capture Source", */
3845		.name = "Input Source",
3846		.count = 2,
3847		.info = ad198x_mux_enum_info,
3848		.get = ad198x_mux_enum_get,
3849		.put = ad198x_mux_enum_put,
3850	},
3851	/* SPDIF controls */
3852	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3853	{
3854		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3855		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3856		/* identical with ad1983 */
3857		.info = ad1983_spdif_route_info,
3858		.get = ad1983_spdif_route_get,
3859		.put = ad1983_spdif_route_put,
3860	},
3861	{ } /* end */
3862};
3863
3864/*
3865 * initialization verbs
3866 */
3867static const struct hda_verb ad1884a_init_verbs[] = {
3868	/* DACs; unmute as default */
3869	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3870	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3871	/* Port-A (HP) mixer - route only from analog mixer */
3872	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3873	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3874	/* Port-A pin */
3875	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3876	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3877	/* Port-D (Line-out) mixer - route only from analog mixer */
3878	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3879	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3880	/* Port-D pin */
3881	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3882	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3883	/* Mono-out mixer - route only from analog mixer */
3884	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3885	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3886	/* Mono-out pin */
3887	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3888	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3889	/* Port-B (front mic) pin */
3890	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3891	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3892	/* Port-C (rear line-in) pin */
3893	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3894	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3895	/* Port-E (rear mic) pin */
3896	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3897	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3898	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3899	/* Port-F (CD) pin */
3900	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3901	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3902	/* Analog mixer; mute as default */
3903	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3904	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3905	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3906	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3907	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3908	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3909	/* Analog Mix output amp */
3910	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3911	/* capture sources */
3912	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3913	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3914	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3915	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3916	/* SPDIF output amp */
3917	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3918	{ } /* end */
3919};
3920
3921#ifdef CONFIG_SND_HDA_POWER_SAVE
3922static const struct hda_amp_list ad1884a_loopbacks[] = {
3923	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
3924	{ 0x20, HDA_INPUT, 1 }, /* Mic */
3925	{ 0x20, HDA_INPUT, 2 }, /* CD */
3926	{ 0x20, HDA_INPUT, 4 }, /* Docking */
3927	{ } /* end */
3928};
3929#endif
3930
3931/*
3932 * Laptop model
3933 *
3934 * Port A: Headphone jack
3935 * Port B: MIC jack
3936 * Port C: Internal MIC
3937 * Port D: Dock Line Out (if enabled)
3938 * Port E: Dock Line In (if enabled)
3939 * Port F: Internal speakers
3940 */
3941
3942static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3943					struct snd_ctl_elem_value *ucontrol)
3944{
3945	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3946	int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3947	int mute = (!ucontrol->value.integer.value[0] &&
3948		    !ucontrol->value.integer.value[1]);
3949	/* toggle GPIO1 according to the mute state */
3950	snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3951			    mute ? 0x02 : 0x0);
3952	return ret;
3953}
3954
3955static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3956	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3957	{
3958		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3959		.name = "Master Playback Switch",
3960		.subdevice = HDA_SUBDEV_AMP_FLAG,
3961		.info = snd_hda_mixer_amp_switch_info,
3962		.get = snd_hda_mixer_amp_switch_get,
3963		.put = ad1884a_mobile_master_sw_put,
3964		.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3965	},
3966	HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3967	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3968	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3969	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3970	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3971	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3972	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3973	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3974	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3975	HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3976	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3977	HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3978	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3979	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3980	{ } /* end */
3981};
3982
3983static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3984	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3985	/*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3986	{
3987		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3988		.name = "Master Playback Switch",
3989		.subdevice = HDA_SUBDEV_AMP_FLAG,
3990		.info = snd_hda_mixer_amp_switch_info,
3991		.get = snd_hda_mixer_amp_switch_get,
3992		.put = ad1884a_mobile_master_sw_put,
3993		.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3994	},
3995	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3996	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3997	HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3998	HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
3999	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4000	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4001	{ } /* end */
4002};
4003
4004/* mute internal speaker if HP is plugged */
4005static void ad1884a_hp_automute(struct hda_codec *codec)
4006{
4007	unsigned int present;
 
4008
4009	present = snd_hda_jack_detect(codec, 0x11);
4010	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4011				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4012	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4013			    present ? 0x00 : 0x02);
4014}
4015
4016/* switch to external mic if plugged */
4017static void ad1884a_hp_automic(struct hda_codec *codec)
4018{
4019	unsigned int present;
4020
4021	present = snd_hda_jack_detect(codec, 0x14);
4022	snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
4023			    present ? 0 : 1);
4024}
4025
4026#define AD1884A_HP_EVENT		0x37
4027#define AD1884A_MIC_EVENT		0x36
4028
4029/* unsolicited event for HP jack sensing */
4030static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4031{
4032	switch (res >> 26) {
4033	case AD1884A_HP_EVENT:
4034		ad1884a_hp_automute(codec);
 
4035		break;
4036	case AD1884A_MIC_EVENT:
4037		ad1884a_hp_automic(codec);
 
 
 
4038		break;
4039	}
4040}
4041
4042/* initialize jack-sensing, too */
4043static int ad1884a_hp_init(struct hda_codec *codec)
4044{
4045	ad198x_init(codec);
4046	ad1884a_hp_automute(codec);
4047	ad1884a_hp_automic(codec);
4048	return 0;
4049}
4050
4051/* mute internal speaker if HP or docking HP is plugged */
4052static void ad1884a_laptop_automute(struct hda_codec *codec)
4053{
4054	unsigned int present;
4055
4056	present = snd_hda_jack_detect(codec, 0x11);
4057	if (!present)
4058		present = snd_hda_jack_detect(codec, 0x12);
4059	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4060				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4061	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4062			    present ? 0x00 : 0x02);
4063}
4064
4065/* switch to external mic if plugged */
4066static void ad1884a_laptop_automic(struct hda_codec *codec)
4067{
4068	unsigned int idx;
4069
4070	if (snd_hda_jack_detect(codec, 0x14))
4071		idx = 0;
4072	else if (snd_hda_jack_detect(codec, 0x1c))
4073		idx = 4;
4074	else
4075		idx = 1;
4076	snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
4077}
4078
4079/* unsolicited event for HP jack sensing */
4080static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
4081				       unsigned int res)
4082{
4083	switch (res >> 26) {
4084	case AD1884A_HP_EVENT:
4085		ad1884a_laptop_automute(codec);
4086		break;
4087	case AD1884A_MIC_EVENT:
4088		ad1884a_laptop_automic(codec);
4089		break;
4090	}
4091}
4092
4093/* initialize jack-sensing, too */
4094static int ad1884a_laptop_init(struct hda_codec *codec)
4095{
4096	ad198x_init(codec);
4097	ad1884a_laptop_automute(codec);
4098	ad1884a_laptop_automic(codec);
4099	return 0;
4100}
4101
4102/* additional verbs for laptop model */
4103static const struct hda_verb ad1884a_laptop_verbs[] = {
4104	/* Port-A (HP) pin - always unmuted */
4105	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4106	/* Port-F (int speaker) mixer - route only from analog mixer */
4107	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4108	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4109	/* Port-F (int speaker) pin */
4110	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4111	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4112	/* required for compaq 6530s/6531s speaker output */
4113	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4114	/* Port-C pin - internal mic-in */
4115	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4116	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4117	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4118	/* Port-D (docking line-out) pin - default unmuted */
4119	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4120	/* analog mix */
4121	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4122	/* unsolicited event for pin-sense */
4123	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4124	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4125	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4126	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4127	/* allow to touch GPIO1 (for mute control) */
4128	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4129	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4130	{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4131	{ } /* end */
4132};
4133
4134static const struct hda_verb ad1884a_mobile_verbs[] = {
4135	/* DACs; unmute as default */
4136	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4137	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4138	/* Port-A (HP) mixer - route only from analog mixer */
4139	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4140	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4141	/* Port-A pin */
4142	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4143	/* Port-A (HP) pin - always unmuted */
4144	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4145	/* Port-B (mic jack) pin */
4146	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4147	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4148	/* Port-C (int mic) pin */
4149	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4150	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4151	/* Port-F (int speaker) mixer - route only from analog mixer */
4152	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4153	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4154	/* Port-F pin */
4155	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4156	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4157	/* Analog mixer; mute as default */
4158	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4159	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4160	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4161	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4162	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4163	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4164	/* Analog Mix output amp */
4165	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4166	/* capture sources */
4167	/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4168	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4169	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4170	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4171	/* unsolicited event for pin-sense */
4172	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4173	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4174	/* allow to touch GPIO1 (for mute control) */
4175	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4176	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4177	{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4178	{ } /* end */
4179};
4180
4181/*
4182 * Thinkpad X300
4183 * 0x11 - HP
4184 * 0x12 - speaker
4185 * 0x14 - mic-in
4186 * 0x17 - built-in mic
4187 */
4188
4189static const struct hda_verb ad1984a_thinkpad_verbs[] = {
4190	/* HP unmute */
4191	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4192	/* analog mix */
4193	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4194	/* turn on EAPD */
4195	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4196	/* unsolicited event for pin-sense */
4197	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4198	/* internal mic - dmic */
4199	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4200	/* set magic COEFs for dmic */
4201	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4202	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
4203	{ } /* end */
4204};
4205
4206static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4207	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4208	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4209	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4210	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4211	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4212	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4213	HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4214	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4215	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4216	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4217	{
4218		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4219		.name = "Capture Source",
4220		.info = ad198x_mux_enum_info,
4221		.get = ad198x_mux_enum_get,
4222		.put = ad198x_mux_enum_put,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4223	},
4224	{ } /* end */
4225};
4226
4227static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
4228	.num_items = 3,
4229	.items = {
4230		{ "Mic", 0x0 },
4231		{ "Internal Mic", 0x5 },
4232		{ "Mix", 0x3 },
4233	},
4234};
4235
4236/* mute internal speaker if HP is plugged */
4237static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4238{
4239	unsigned int present;
4240
4241	present = snd_hda_jack_detect(codec, 0x11);
4242	snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4243				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4244}
4245
4246/* unsolicited event for HP jack sensing */
4247static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4248					 unsigned int res)
4249{
4250	if ((res >> 26) != AD1884A_HP_EVENT)
4251		return;
4252	ad1984a_thinkpad_automute(codec);
4253}
4254
4255/* initialize jack-sensing, too */
4256static int ad1984a_thinkpad_init(struct hda_codec *codec)
4257{
4258	ad198x_init(codec);
4259	ad1984a_thinkpad_automute(codec);
4260	return 0;
4261}
4262
4263/*
4264 * Precision R5500
4265 * 0x12 - HP/line-out
4266 * 0x13 - speaker (mono)
4267 * 0x15 - mic-in
4268 */
4269
4270static const struct hda_verb ad1984a_precision_verbs[] = {
4271	/* Unmute main output path */
4272	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4273	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
4274	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4275	/* Analog mixer; mute as default */
4276	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4277	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4278	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4279	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4280	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4281	/* Select mic as input */
4282	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
4283	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
4284	/* Configure as mic */
4285	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4286	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4287	/* HP unmute */
4288	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4289	/* turn on EAPD */
4290	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4291	/* unsolicited event for pin-sense */
4292	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4293	{ } /* end */
4294};
4295
4296static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
4297	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4298	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4299	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4300	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4301	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4302	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4303	HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4304	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4305	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
4306	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4307	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4308	{ } /* end */
4309};
4310
4311
4312/* mute internal speaker if HP is plugged */
4313static void ad1984a_precision_automute(struct hda_codec *codec)
4314{
4315	unsigned int present;
4316
4317	present = snd_hda_jack_detect(codec, 0x12);
4318	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
4319				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4320}
4321
4322
4323/* unsolicited event for HP jack sensing */
4324static void ad1984a_precision_unsol_event(struct hda_codec *codec,
4325					 unsigned int res)
4326{
4327	if ((res >> 26) != AD1884A_HP_EVENT)
4328		return;
4329	ad1984a_precision_automute(codec);
4330}
4331
4332/* initialize jack-sensing, too */
4333static int ad1984a_precision_init(struct hda_codec *codec)
4334{
4335	ad198x_init(codec);
4336	ad1984a_precision_automute(codec);
4337	return 0;
4338}
4339
4340
4341/*
4342 * HP Touchsmart
4343 * port-A (0x11)      - front hp-out
4344 * port-B (0x14)      - unused
4345 * port-C (0x15)      - unused
4346 * port-D (0x12)      - rear line out
4347 * port-E (0x1c)      - front mic-in
4348 * port-F (0x16)      - Internal speakers
4349 * digital-mic (0x17) - Internal mic
4350 */
4351
4352static const struct hda_verb ad1984a_touchsmart_verbs[] = {
4353	/* DACs; unmute as default */
4354	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4355	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4356	/* Port-A (HP) mixer - route only from analog mixer */
4357	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4358	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4359	/* Port-A pin */
4360	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4361	/* Port-A (HP) pin - always unmuted */
4362	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4363	/* Port-E (int speaker) mixer - route only from analog mixer */
4364	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4365	/* Port-E pin */
4366	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4367	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4368	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4369	/* Port-F (int speaker) mixer - route only from analog mixer */
4370	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4371	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4372	/* Port-F pin */
4373	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4374	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4375	/* Analog mixer; mute as default */
4376	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4377	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4378	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4379	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4380	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4381	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4382	/* Analog Mix output amp */
4383	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4384	/* capture sources */
4385	/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4386	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4387	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4388	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4389	/* unsolicited event for pin-sense */
4390	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4391	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4392	/* allow to touch GPIO1 (for mute control) */
4393	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4394	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4395	{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4396	/* internal mic - dmic */
4397	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4398	/* set magic COEFs for dmic */
4399	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4400	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
4401	{ } /* end */
4402};
4403
4404static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4405	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4406/*	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4407	{
4408		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4409		.subdevice = HDA_SUBDEV_AMP_FLAG,
4410		.name = "Master Playback Switch",
4411		.info = snd_hda_mixer_amp_switch_info,
4412		.get = snd_hda_mixer_amp_switch_get,
4413		.put = ad1884a_mobile_master_sw_put,
4414		.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4415	},
4416	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4417	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4418	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4419	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4420	HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4421	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4422	{ } /* end */
4423};
4424
4425/* switch to external mic if plugged */
4426static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4427{
4428	if (snd_hda_jack_detect(codec, 0x1c))
4429		snd_hda_codec_write(codec, 0x0c, 0,
4430				     AC_VERB_SET_CONNECT_SEL, 0x4);
4431	else
4432		snd_hda_codec_write(codec, 0x0c, 0,
4433				     AC_VERB_SET_CONNECT_SEL, 0x5);
4434}
4435
4436
4437/* unsolicited event for HP jack sensing */
4438static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4439	unsigned int res)
4440{
4441	switch (res >> 26) {
4442	case AD1884A_HP_EVENT:
4443		ad1884a_hp_automute(codec);
4444		break;
4445	case AD1884A_MIC_EVENT:
4446		ad1984a_touchsmart_automic(codec);
4447		break;
4448	}
4449}
4450
4451/* initialize jack-sensing, too */
4452static int ad1984a_touchsmart_init(struct hda_codec *codec)
4453{
4454	ad198x_init(codec);
4455	ad1884a_hp_automute(codec);
4456	ad1984a_touchsmart_automic(codec);
4457	return 0;
4458}
4459
4460
4461/*
4462 */
4463
4464enum {
4465	AD1884A_DESKTOP,
4466	AD1884A_LAPTOP,
4467	AD1884A_MOBILE,
4468	AD1884A_THINKPAD,
4469	AD1984A_TOUCHSMART,
4470	AD1984A_PRECISION,
4471	AD1884A_MODELS
4472};
4473
4474static const char * const ad1884a_models[AD1884A_MODELS] = {
4475	[AD1884A_DESKTOP]	= "desktop",
4476	[AD1884A_LAPTOP]	= "laptop",
4477	[AD1884A_MOBILE]	= "mobile",
4478	[AD1884A_THINKPAD]	= "thinkpad",
4479	[AD1984A_TOUCHSMART]	= "touchsmart",
4480	[AD1984A_PRECISION]	= "precision",
4481};
4482
4483static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4484	SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
4485	SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4486	SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4487	SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4488	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4489	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4490	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4491	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4492	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4493	SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4494	SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4495	{}
4496};
4497
4498static int patch_ad1884a(struct hda_codec *codec)
4499{
4500	struct ad198x_spec *spec;
4501	int err, board_config;
4502
4503	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4504	if (spec == NULL)
4505		return -ENOMEM;
 
4506
4507	codec->spec = spec;
4508
4509	err = snd_hda_attach_beep_device(codec, 0x10);
4510	if (err < 0) {
4511		ad198x_free(codec);
4512		return err;
4513	}
4514	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4515
4516	spec->multiout.max_channels = 2;
4517	spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4518	spec->multiout.dac_nids = ad1884a_dac_nids;
4519	spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4520	spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4521	spec->adc_nids = ad1884a_adc_nids;
4522	spec->capsrc_nids = ad1884a_capsrc_nids;
4523	spec->input_mux = &ad1884a_capture_source;
4524	spec->num_mixers = 1;
4525	spec->mixers[0] = ad1884a_base_mixers;
4526	spec->num_init_verbs = 1;
4527	spec->init_verbs[0] = ad1884a_init_verbs;
4528	spec->spdif_route = 0;
4529#ifdef CONFIG_SND_HDA_POWER_SAVE
4530	spec->loopback.amplist = ad1884a_loopbacks;
4531#endif
4532	codec->patch_ops = ad198x_patch_ops;
4533
4534	/* override some parameters */
4535	board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4536						  ad1884a_models,
4537						  ad1884a_cfg_tbl);
4538	switch (board_config) {
4539	case AD1884A_LAPTOP:
4540		spec->mixers[0] = ad1884a_laptop_mixers;
4541		spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4542		spec->multiout.dig_out_nid = 0;
4543		codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4544		codec->patch_ops.init = ad1884a_laptop_init;
4545		/* set the upper-limit for mixer amp to 0dB for avoiding the
4546		 * possible damage by overloading
4547		 */
4548		snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4549					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4550					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4551					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4552					  (1 << AC_AMPCAP_MUTE_SHIFT));
4553		break;
4554	case AD1884A_MOBILE:
4555		spec->mixers[0] = ad1884a_mobile_mixers;
4556		spec->init_verbs[0] = ad1884a_mobile_verbs;
4557		spec->multiout.dig_out_nid = 0;
4558		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4559		codec->patch_ops.init = ad1884a_hp_init;
4560		/* set the upper-limit for mixer amp to 0dB for avoiding the
4561		 * possible damage by overloading
4562		 */
4563		snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4564					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4565					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4566					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4567					  (1 << AC_AMPCAP_MUTE_SHIFT));
4568		break;
4569	case AD1884A_THINKPAD:
4570		spec->mixers[0] = ad1984a_thinkpad_mixers;
4571		spec->init_verbs[spec->num_init_verbs++] =
4572			ad1984a_thinkpad_verbs;
4573		spec->multiout.dig_out_nid = 0;
4574		spec->input_mux = &ad1984a_thinkpad_capture_source;
4575		codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4576		codec->patch_ops.init = ad1984a_thinkpad_init;
4577		break;
4578	case AD1984A_PRECISION:
4579		spec->mixers[0] = ad1984a_precision_mixers;
4580		spec->init_verbs[spec->num_init_verbs++] =
4581			ad1984a_precision_verbs;
4582		spec->multiout.dig_out_nid = 0;
4583		codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
4584		codec->patch_ops.init = ad1984a_precision_init;
4585		break;
4586	case AD1984A_TOUCHSMART:
4587		spec->mixers[0] = ad1984a_touchsmart_mixers;
4588		spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4589		spec->multiout.dig_out_nid = 0;
4590		codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4591		codec->patch_ops.init = ad1984a_touchsmart_init;
4592		/* set the upper-limit for mixer amp to 0dB for avoiding the
4593		 * possible damage by overloading
4594		 */
4595		snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4596					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4597					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4598					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4599					  (1 << AC_AMPCAP_MUTE_SHIFT));
4600		break;
4601	}
4602
4603	codec->no_trigger_sense = 1;
4604	codec->no_sticky_stream = 1;
4605
4606	return 0;
 
 
 
 
4607}
4608
4609
4610/*
4611 * AD1882 / AD1882A
4612 *
4613 * port-A - front hp-out
4614 * port-B - front mic-in
4615 * port-C - rear line-in, shared surr-out (3stack)
4616 * port-D - rear line-out
4617 * port-E - rear mic-in, shared clfe-out (3stack)
4618 * port-F - rear surr-out (6stack)
4619 * port-G - rear clfe-out (6stack)
4620 */
4621
4622static const hda_nid_t ad1882_dac_nids[3] = {
4623	0x04, 0x03, 0x05
4624};
4625
4626static const hda_nid_t ad1882_adc_nids[2] = {
4627	0x08, 0x09,
4628};
4629
4630static const hda_nid_t ad1882_capsrc_nids[2] = {
4631	0x0c, 0x0d,
4632};
4633
4634#define AD1882_SPDIF_OUT	0x02
4635
4636/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4637static const struct hda_input_mux ad1882_capture_source = {
4638	.num_items = 5,
4639	.items = {
4640		{ "Front Mic", 0x1 },
4641		{ "Mic", 0x4 },
4642		{ "Line", 0x2 },
4643		{ "CD", 0x3 },
4644		{ "Mix", 0x7 },
4645	},
4646};
4647
4648/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4649static const struct hda_input_mux ad1882a_capture_source = {
4650	.num_items = 5,
4651	.items = {
4652		{ "Front Mic", 0x1 },
4653		{ "Mic", 0x4},
4654		{ "Line", 0x2 },
4655		{ "Digital Mic", 0x06 },
4656		{ "Mix", 0x7 },
4657	},
4658};
4659
4660static const struct snd_kcontrol_new ad1882_base_mixers[] = {
4661	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4662	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4663	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4664	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4665	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4666	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4667	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4668	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4669
4670	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
4671	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
4672	HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT),
4673	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4674	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4675	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4676	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4677	{
4678		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4679		/* The multiple "Capture Source" controls confuse alsamixer
4680		 * So call somewhat different..
4681		 */
4682		/* .name = "Capture Source", */
4683		.name = "Input Source",
4684		.count = 2,
4685		.info = ad198x_mux_enum_info,
4686		.get = ad198x_mux_enum_get,
4687		.put = ad198x_mux_enum_put,
4688	},
4689	/* SPDIF controls */
4690	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4691	{
4692		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4693		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4694		/* identical with ad1983 */
4695		.info = ad1983_spdif_route_info,
4696		.get = ad1983_spdif_route_get,
4697		.put = ad1983_spdif_route_put,
4698	},
4699	{ } /* end */
4700};
4701
4702static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4703	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4704	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4705	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4706	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4707	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4708	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4709	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4710	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4711	{ } /* end */
4712};
4713
4714static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4715	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4716	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4717	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4718	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4719	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4720	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4721	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4722	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4723	HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT),
4724	{ } /* end */
4725};
4726
4727static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4728	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4729	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4730	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4731	{
4732		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4733		.name = "Channel Mode",
4734		.info = ad198x_ch_mode_info,
4735		.get = ad198x_ch_mode_get,
4736		.put = ad198x_ch_mode_put,
4737	},
4738	{ } /* end */
4739};
4740
4741static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4742	HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4743	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4744	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4745	{ } /* end */
4746};
4747
4748static const struct hda_verb ad1882_ch2_init[] = {
4749	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4750	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4751	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4752	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4753	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4754	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4755	{ } /* end */
4756};
4757
4758static const struct hda_verb ad1882_ch4_init[] = {
4759	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4760	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4761	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4762	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4763	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4764	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4765	{ } /* end */
4766};
4767
4768static const struct hda_verb ad1882_ch6_init[] = {
4769	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4770	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4771	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4772	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4773	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4774	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4775	{ } /* end */
4776};
4777
4778static const struct hda_channel_mode ad1882_modes[3] = {
4779	{ 2, ad1882_ch2_init },
4780	{ 4, ad1882_ch4_init },
4781	{ 6, ad1882_ch6_init },
4782};
4783
4784/*
4785 * initialization verbs
4786 */
4787static const struct hda_verb ad1882_init_verbs[] = {
4788	/* DACs; mute as default */
4789	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4790	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4791	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4792	/* Port-A (HP) mixer */
4793	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4794	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4795	/* Port-A pin */
4796	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4797	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4798	/* HP selector - select DAC2 */
4799	{0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4800	/* Port-D (Line-out) mixer */
4801	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4802	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4803	/* Port-D pin */
4804	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4805	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4806	/* Mono-out mixer */
4807	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4808	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4809	/* Mono-out pin */
4810	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4811	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4812	/* Port-B (front mic) pin */
4813	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4814	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4815	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4816	/* Port-C (line-in) pin */
4817	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4818	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4819	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4820	/* Port-C mixer - mute as input */
4821	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4822	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4823	/* Port-E (mic-in) pin */
4824	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4825	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4826	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4827	/* Port-E mixer - mute as input */
4828	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4829	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4830	/* Port-F (surround) */
4831	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4832	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4833	/* Port-G (CLFE) */
4834	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4835	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4836	/* Analog mixer; mute as default */
4837	/* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4838	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4839	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4840	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4841	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4842	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4843	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4844	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4845	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4846	/* Analog Mix output amp */
4847	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4848	/* SPDIF output selector */
4849	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4850	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4851	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4852	{ } /* end */
4853};
4854
4855#ifdef CONFIG_SND_HDA_POWER_SAVE
4856static const struct hda_amp_list ad1882_loopbacks[] = {
4857	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
4858	{ 0x20, HDA_INPUT, 1 }, /* Mic */
4859	{ 0x20, HDA_INPUT, 4 }, /* Line */
4860	{ 0x20, HDA_INPUT, 6 }, /* CD */
4861	{ } /* end */
4862};
4863#endif
4864
4865/* models */
4866enum {
4867	AD1882_3STACK,
4868	AD1882_6STACK,
4869	AD1882_MODELS
4870};
4871
4872static const char * const ad1882_models[AD1986A_MODELS] = {
4873	[AD1882_3STACK]		= "3stack",
4874	[AD1882_6STACK]		= "6stack",
4875};
4876
4877
4878static int patch_ad1882(struct hda_codec *codec)
4879{
4880	struct ad198x_spec *spec;
4881	int err, board_config;
4882
4883	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4884	if (spec == NULL)
4885		return -ENOMEM;
 
4886
4887	codec->spec = spec;
4888
4889	err = snd_hda_attach_beep_device(codec, 0x10);
4890	if (err < 0) {
4891		ad198x_free(codec);
4892		return err;
4893	}
4894	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 
 
 
 
 
 
 
4895
4896	spec->multiout.max_channels = 6;
4897	spec->multiout.num_dacs = 3;
4898	spec->multiout.dac_nids = ad1882_dac_nids;
4899	spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4900	spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4901	spec->adc_nids = ad1882_adc_nids;
4902	spec->capsrc_nids = ad1882_capsrc_nids;
4903	if (codec->vendor_id == 0x11d41882)
4904		spec->input_mux = &ad1882_capture_source;
4905	else
4906		spec->input_mux = &ad1882a_capture_source;
4907	spec->num_mixers = 2;
4908	spec->mixers[0] = ad1882_base_mixers;
4909	if (codec->vendor_id == 0x11d41882)
4910		spec->mixers[1] = ad1882_loopback_mixers;
4911	else
4912		spec->mixers[1] = ad1882a_loopback_mixers;
4913	spec->num_init_verbs = 1;
4914	spec->init_verbs[0] = ad1882_init_verbs;
4915	spec->spdif_route = 0;
4916#ifdef CONFIG_SND_HDA_POWER_SAVE
4917	spec->loopback.amplist = ad1882_loopbacks;
4918#endif
4919	spec->vmaster_nid = 0x04;
4920
4921	codec->patch_ops = ad198x_patch_ops;
4922
4923	/* override some parameters */
4924	board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4925						  ad1882_models, NULL);
4926	switch (board_config) {
4927	default:
4928	case AD1882_3STACK:
4929		spec->num_mixers = 3;
4930		spec->mixers[2] = ad1882_3stack_mixers;
4931		spec->channel_mode = ad1882_modes;
4932		spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4933		spec->need_dac_fix = 1;
4934		spec->multiout.max_channels = 2;
4935		spec->multiout.num_dacs = 1;
4936		break;
4937	case AD1882_6STACK:
4938		spec->num_mixers = 3;
4939		spec->mixers[2] = ad1882_6stack_mixers;
4940		break;
4941	}
4942
4943	codec->no_trigger_sense = 1;
4944	codec->no_sticky_stream = 1;
4945
4946	return 0;
4947}
4948
4949
4950/*
4951 * patch entries
4952 */
4953static const struct hda_codec_preset snd_hda_preset_analog[] = {
4954	{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
4955	{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
4956	{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
4957	{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
4958	{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4959	{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4960	{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4961	{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
4962	{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
4963	{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
4964	{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
4965	{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
4966	{ .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
4967	{ .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4968	{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
4969	{} /* terminator */
4970};
4971
4972MODULE_ALIAS("snd-hda-codec-id:11d4*");
4973
4974MODULE_LICENSE("GPL");
4975MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4976
4977static struct hda_codec_preset_list analog_list = {
4978	.preset = snd_hda_preset_analog,
4979	.owner = THIS_MODULE,
4980};
4981
4982static int __init patch_analog_init(void)
4983{
4984	return snd_hda_add_codec_preset(&analog_list);
4985}
4986
4987static void __exit patch_analog_exit(void)
4988{
4989	snd_hda_delete_codec_preset(&analog_list);
4990}
4991
4992module_init(patch_analog_init)
4993module_exit(patch_analog_exit)