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