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