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