Linux Audio

Check our new training course

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