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