]> bbs.cooldavid.org Git - net-next-2.6.git/blame - sound/pci/hda/patch_analog.c
Merge branch 'topic/hda' into for-linus
[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 1278 codec->no_trigger_sense = 1;
0e7adbe2 1279 codec->no_sticky_stream = 1;
729d55ba 1280
1da177e4
LT
1281 return 0;
1282}
1283
1284/*
4a3fdf3d 1285 * AD1983 specific
1da177e4 1286 */
1da177e4 1287
4a3fdf3d
TI
1288#define AD1983_SPDIF_OUT 0x02
1289#define AD1983_DAC 0x03
1290#define AD1983_ADC 0x04
1da177e4 1291
4a3fdf3d 1292static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
985be54b 1293static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
18a815d7 1294static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
4a3fdf3d
TI
1295
1296static struct hda_input_mux ad1983_capture_source = {
1297 .num_items = 4,
1298 .items = {
1299 { "Mic", 0x0 },
1300 { "Line", 0x1 },
1301 { "Mix", 0x2 },
1302 { "Mix Mono", 0x3 },
1303 },
1304};
1da177e4
LT
1305
1306/*
4a3fdf3d 1307 * SPDIF playback route
1da177e4 1308 */
c8b6bf9b 1309static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 1310{
4a3fdf3d
TI
1311 static char *texts[] = { "PCM", "ADC" };
1312
1313 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1314 uinfo->count = 1;
1315 uinfo->value.enumerated.items = 2;
1316 if (uinfo->value.enumerated.item > 1)
1317 uinfo->value.enumerated.item = 1;
1318 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1319 return 0;
1da177e4
LT
1320}
1321
c8b6bf9b 1322static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1323{
4a3fdf3d
TI
1324 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1325 struct ad198x_spec *spec = codec->spec;
1da177e4 1326
4a3fdf3d 1327 ucontrol->value.enumerated.item[0] = spec->spdif_route;
1da177e4
LT
1328 return 0;
1329}
1330
c8b6bf9b 1331static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1332{
4a3fdf3d
TI
1333 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1334 struct ad198x_spec *spec = codec->spec;
1335
68ea7b2f
TI
1336 if (ucontrol->value.enumerated.item[0] > 1)
1337 return -EINVAL;
4a3fdf3d
TI
1338 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1339 spec->spdif_route = ucontrol->value.enumerated.item[0];
82beb8fd
TI
1340 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1341 AC_VERB_SET_CONNECT_SEL,
1342 spec->spdif_route);
4a3fdf3d
TI
1343 return 1;
1344 }
1da177e4
LT
1345 return 0;
1346}
1347
c8b6bf9b 1348static struct snd_kcontrol_new ad1983_mixers[] = {
4a3fdf3d
TI
1349 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1350 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1351 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1352 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1353 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1354 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1355 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1356 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1357 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1358 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1359 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1360 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
4a3fdf3d
TI
1361 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
1362 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1363 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1364 {
1365 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1366 .name = "Capture Source",
1367 .info = ad198x_mux_enum_info,
1368 .get = ad198x_mux_enum_get,
1369 .put = ad198x_mux_enum_put,
1da177e4 1370 },
4a3fdf3d
TI
1371 {
1372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6540dffa 1373 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4a3fdf3d
TI
1374 .info = ad1983_spdif_route_info,
1375 .get = ad1983_spdif_route_get,
1376 .put = ad1983_spdif_route_put,
1da177e4 1377 },
4a3fdf3d 1378 { } /* end */
1da177e4
LT
1379};
1380
4a3fdf3d
TI
1381static struct hda_verb ad1983_init_verbs[] = {
1382 /* Front, HP, Mono; mute as default */
1383 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1384 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1385 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1386 /* Beep, PCM, Mic, Line-In: mute */
1387 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1388 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1389 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1390 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1391 /* Front, HP selectors; from Mix */
1392 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1393 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1394 /* Mono selector; from Mix */
1395 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1396 /* Mic selector; Mic */
1397 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1398 /* Line-in selector: Line-in */
1399 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1400 /* Mic boost: 0dB */
1401 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1402 /* Record selector: mic */
1403 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1404 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1405 /* SPDIF route: PCM */
1406 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1407 /* Front Pin */
1408 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1409 /* HP Pin */
1410 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1411 /* Mono Pin */
1412 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1413 /* Mic Pin */
1414 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1415 /* Line Pin */
1416 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1417 { } /* end */
1da177e4
LT
1418};
1419
cb53c626
TI
1420#ifdef CONFIG_SND_HDA_POWER_SAVE
1421static struct hda_amp_list ad1983_loopbacks[] = {
1422 { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1423 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1424 { } /* end */
1425};
1426#endif
985be54b 1427
4a3fdf3d 1428static int patch_ad1983(struct hda_codec *codec)
1da177e4 1429{
4a3fdf3d 1430 struct ad198x_spec *spec;
c5a4bcd0 1431 int err;
1da177e4 1432
e560d8d8 1433 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4a3fdf3d
TI
1434 if (spec == NULL)
1435 return -ENOMEM;
1da177e4 1436
4a3fdf3d
TI
1437 codec->spec = spec;
1438
c5a4bcd0
TI
1439 err = snd_hda_attach_beep_device(codec, 0x10);
1440 if (err < 0) {
1441 ad198x_free(codec);
1442 return err;
1443 }
1444 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1445
4a3fdf3d
TI
1446 spec->multiout.max_channels = 2;
1447 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1448 spec->multiout.dac_nids = ad1983_dac_nids;
1449 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
985be54b
TI
1450 spec->num_adc_nids = 1;
1451 spec->adc_nids = ad1983_adc_nids;
18a815d7 1452 spec->capsrc_nids = ad1983_capsrc_nids;
4a3fdf3d 1453 spec->input_mux = &ad1983_capture_source;
985be54b
TI
1454 spec->num_mixers = 1;
1455 spec->mixers[0] = ad1983_mixers;
1456 spec->num_init_verbs = 1;
1457 spec->init_verbs[0] = ad1983_init_verbs;
4a3fdf3d 1458 spec->spdif_route = 0;
cb53c626
TI
1459#ifdef CONFIG_SND_HDA_POWER_SAVE
1460 spec->loopback.amplist = ad1983_loopbacks;
1461#endif
2134ea4f 1462 spec->vmaster_nid = 0x05;
1da177e4 1463
4a3fdf3d 1464 codec->patch_ops = ad198x_patch_ops;
1da177e4 1465
729d55ba 1466 codec->no_trigger_sense = 1;
0e7adbe2 1467 codec->no_sticky_stream = 1;
729d55ba 1468
1da177e4
LT
1469 return 0;
1470}
1471
1da177e4 1472
4a3fdf3d
TI
1473/*
1474 * AD1981 HD specific
1475 */
1da177e4 1476
4a3fdf3d
TI
1477#define AD1981_SPDIF_OUT 0x02
1478#define AD1981_DAC 0x03
1479#define AD1981_ADC 0x04
1480
1481static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
985be54b 1482static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
18a815d7 1483static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
4a3fdf3d
TI
1484
1485/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1486static struct hda_input_mux ad1981_capture_source = {
1487 .num_items = 7,
1488 .items = {
1489 { "Front Mic", 0x0 },
1490 { "Line", 0x1 },
1491 { "Mix", 0x2 },
1492 { "Mix Mono", 0x3 },
1493 { "CD", 0x4 },
1494 { "Mic", 0x6 },
1495 { "Aux", 0x7 },
1496 },
1da177e4
LT
1497};
1498
c8b6bf9b 1499static struct snd_kcontrol_new ad1981_mixers[] = {
4a3fdf3d
TI
1500 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1501 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1502 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1503 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1504 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1505 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1506 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1507 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1508 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1509 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1510 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1511 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1512 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1513 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1514 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1515 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1516 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1517 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
4a3fdf3d
TI
1518 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
1519 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
1520 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1521 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1522 {
1523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1524 .name = "Capture Source",
1525 .info = ad198x_mux_enum_info,
1526 .get = ad198x_mux_enum_get,
1527 .put = ad198x_mux_enum_put,
1528 },
1529 /* identical with AD1983 */
1530 {
1531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6540dffa 1532 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4a3fdf3d
TI
1533 .info = ad1983_spdif_route_info,
1534 .get = ad1983_spdif_route_get,
1535 .put = ad1983_spdif_route_put,
1536 },
1537 { } /* end */
1538};
1539
1540static struct hda_verb ad1981_init_verbs[] = {
1541 /* Front, HP, Mono; mute as default */
1542 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1543 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1544 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1545 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1546 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1547 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1548 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1549 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1550 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1551 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1552 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1553 /* Front, HP selectors; from Mix */
1554 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1555 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1556 /* Mono selector; from Mix */
1557 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1558 /* Mic Mixer; select Front Mic */
1559 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1560 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1561 /* Mic boost: 0dB */
6d6e17de
TI
1562 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1563 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4a3fdf3d
TI
1564 /* Record selector: Front mic */
1565 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1566 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1567 /* SPDIF route: PCM */
1568 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1569 /* Front Pin */
1570 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1571 /* HP Pin */
1572 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1573 /* Mono Pin */
1574 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1575 /* Front & Rear Mic Pins */
1576 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1577 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1578 /* Line Pin */
1579 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1580 /* Digital Beep */
1581 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1582 /* Line-Out as Input: disabled */
1583 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1584 { } /* end */
1585};
1586
cb53c626
TI
1587#ifdef CONFIG_SND_HDA_POWER_SAVE
1588static struct hda_amp_list ad1981_loopbacks[] = {
1589 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1590 { 0x13, HDA_OUTPUT, 0 }, /* Line */
1591 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1592 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1593 { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1594 { } /* end */
1595};
1596#endif
1597
18a815d7
TI
1598/*
1599 * Patch for HP nx6320
1600 *
18768991 1601 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
18a815d7
TI
1602 * speaker output enabled _and_ mute-LED off.
1603 */
1604
1605#define AD1981_HP_EVENT 0x37
1606#define AD1981_MIC_EVENT 0x38
1607
1608static struct hda_verb ad1981_hp_init_verbs[] = {
1609 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1610 /* pin sensing on HP and Mic jacks */
1611 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1612 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1613 {}
1614};
1615
1616/* turn on/off EAPD (+ mute HP) as a master switch */
1617static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1618 struct snd_ctl_elem_value *ucontrol)
1619{
1620 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1621 struct ad198x_spec *spec = codec->spec;
1622
1623 if (! ad198x_eapd_put(kcontrol, ucontrol))
1624 return 0;
f0824812
TI
1625 /* change speaker pin appropriately */
1626 snd_hda_codec_write(codec, 0x05, 0,
1627 AC_VERB_SET_PIN_WIDGET_CONTROL,
1628 spec->cur_eapd ? PIN_OUT : 0);
18a815d7 1629 /* toggle HP mute appropriately */
47fd830a
TI
1630 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1631 HDA_AMP_MUTE,
1632 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
18a815d7
TI
1633 return 1;
1634}
1635
1636/* bind volumes of both NID 0x05 and 0x06 */
cca3b371
TI
1637static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1638 .ops = &snd_hda_bind_vol,
1639 .values = {
1640 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1641 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1642 0
1643 },
1644};
18a815d7
TI
1645
1646/* mute internal speaker if HP is plugged */
1647static void ad1981_hp_automute(struct hda_codec *codec)
1648{
1649 unsigned int present;
1650
d56757ab 1651 present = snd_hda_jack_detect(codec, 0x06);
47fd830a
TI
1652 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1653 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
18a815d7
TI
1654}
1655
1656/* toggle input of built-in and mic jack appropriately */
1657static void ad1981_hp_automic(struct hda_codec *codec)
1658{
1659 static struct hda_verb mic_jack_on[] = {
1660 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1661 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1662 {}
1663 };
1664 static struct hda_verb mic_jack_off[] = {
1665 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1666 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1667 {}
1668 };
1669 unsigned int present;
1670
d56757ab 1671 present = snd_hda_jack_detect(codec, 0x08);
18a815d7
TI
1672 if (present)
1673 snd_hda_sequence_write(codec, mic_jack_on);
1674 else
1675 snd_hda_sequence_write(codec, mic_jack_off);
1676}
1677
1678/* unsolicited event for HP jack sensing */
1679static void ad1981_hp_unsol_event(struct hda_codec *codec,
1680 unsigned int res)
1681{
1682 res >>= 26;
1683 switch (res) {
1684 case AD1981_HP_EVENT:
1685 ad1981_hp_automute(codec);
1686 break;
1687 case AD1981_MIC_EVENT:
1688 ad1981_hp_automic(codec);
1689 break;
1690 }
1691}
1692
1693static struct hda_input_mux ad1981_hp_capture_source = {
1694 .num_items = 3,
1695 .items = {
1696 { "Mic", 0x0 },
1697 { "Docking-Station", 0x1 },
1698 { "Mix", 0x2 },
1699 },
1700};
1701
1702static struct snd_kcontrol_new ad1981_hp_mixers[] = {
cca3b371 1703 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
18a815d7
TI
1704 {
1705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5b0cb1d8 1706 .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
18a815d7
TI
1707 .name = "Master Playback Switch",
1708 .info = ad198x_eapd_info,
1709 .get = ad198x_eapd_get,
1710 .put = ad1981_hp_master_sw_put,
1711 .private_value = 0x05,
1712 },
1713 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1714 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1715#if 0
1716 /* FIXME: analog mic/line loopback doesn't work with my tests...
1717 * (although recording is OK)
1718 */
1719 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1720 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1721 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1722 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1723 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1724 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1725 /* FIXME: does this laptop have analog CD connection? */
1726 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1727 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1728#endif
1729 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1730 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1731 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1732 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1733 {
1734 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1735 .name = "Capture Source",
1736 .info = ad198x_mux_enum_info,
1737 .get = ad198x_mux_enum_get,
1738 .put = ad198x_mux_enum_put,
1739 },
1740 { } /* end */
1741};
1742
1743/* initialize jack-sensing, too */
1744static int ad1981_hp_init(struct hda_codec *codec)
1745{
1746 ad198x_init(codec);
1747 ad1981_hp_automute(codec);
1748 ad1981_hp_automic(codec);
1749 return 0;
1750}
1751
18768991
TD
1752/* configuration for Toshiba Laptops */
1753static struct hda_verb ad1981_toshiba_init_verbs[] = {
1754 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
1755 /* pin sensing on HP and Mic jacks */
1756 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1757 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1758 {}
1759};
1760
1761static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
1762 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
1763 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
1764 { }
1765};
1766
01686c5f
TI
1767/* configuration for Lenovo Thinkpad T60 */
1768static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
1769 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1770 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1771 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1772 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1773 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1774 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1775 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1776 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1777 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1778 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1779 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1780 {
1781 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1782 .name = "Capture Source",
1783 .info = ad198x_mux_enum_info,
1784 .get = ad198x_mux_enum_get,
1785 .put = ad198x_mux_enum_put,
1786 },
6540dffa
TI
1787 /* identical with AD1983 */
1788 {
1789 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1790 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1791 .info = ad1983_spdif_route_info,
1792 .get = ad1983_spdif_route_get,
1793 .put = ad1983_spdif_route_put,
1794 },
01686c5f
TI
1795 { } /* end */
1796};
1797
1798static struct hda_input_mux ad1981_thinkpad_capture_source = {
1799 .num_items = 3,
1800 .items = {
1801 { "Mic", 0x0 },
1802 { "Mix", 0x2 },
1803 { "CD", 0x4 },
1804 },
1805};
1806
18a815d7 1807/* models */
f5fcc13c
TI
1808enum {
1809 AD1981_BASIC,
1810 AD1981_HP,
1811 AD1981_THINKPAD,
18768991 1812 AD1981_TOSHIBA,
f5fcc13c
TI
1813 AD1981_MODELS
1814};
18a815d7 1815
f5fcc13c
TI
1816static const char *ad1981_models[AD1981_MODELS] = {
1817 [AD1981_HP] = "hp",
1818 [AD1981_THINKPAD] = "thinkpad",
1819 [AD1981_BASIC] = "basic",
18768991 1820 [AD1981_TOSHIBA] = "toshiba"
f5fcc13c
TI
1821};
1822
1823static struct snd_pci_quirk ad1981_cfg_tbl[] = {
ac3e3741 1824 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
470eaf6b 1825 SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
8970ccda 1826 /* All HP models */
dea0a509 1827 SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
ac3e3741 1828 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
01686c5f 1829 /* Lenovo Thinkpad T60/X60/Z6xx */
dea0a509 1830 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
ac3e3741
TI
1831 /* HP nx6320 (reversed SSID, H/W bug) */
1832 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
18a815d7
TI
1833 {}
1834};
1835
4a3fdf3d 1836static int patch_ad1981(struct hda_codec *codec)
1da177e4 1837{
4a3fdf3d 1838 struct ad198x_spec *spec;
c5a4bcd0 1839 int err, board_config;
1da177e4 1840
e560d8d8 1841 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1da177e4
LT
1842 if (spec == NULL)
1843 return -ENOMEM;
1844
1da177e4
LT
1845 codec->spec = spec;
1846
c5a4bcd0
TI
1847 err = snd_hda_attach_beep_device(codec, 0x10);
1848 if (err < 0) {
1849 ad198x_free(codec);
1850 return err;
1851 }
1852 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1853
4a3fdf3d
TI
1854 spec->multiout.max_channels = 2;
1855 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
1856 spec->multiout.dac_nids = ad1981_dac_nids;
1857 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
985be54b
TI
1858 spec->num_adc_nids = 1;
1859 spec->adc_nids = ad1981_adc_nids;
18a815d7 1860 spec->capsrc_nids = ad1981_capsrc_nids;
4a3fdf3d 1861 spec->input_mux = &ad1981_capture_source;
985be54b
TI
1862 spec->num_mixers = 1;
1863 spec->mixers[0] = ad1981_mixers;
1864 spec->num_init_verbs = 1;
1865 spec->init_verbs[0] = ad1981_init_verbs;
4a3fdf3d 1866 spec->spdif_route = 0;
cb53c626
TI
1867#ifdef CONFIG_SND_HDA_POWER_SAVE
1868 spec->loopback.amplist = ad1981_loopbacks;
1869#endif
2134ea4f 1870 spec->vmaster_nid = 0x05;
1da177e4 1871
4a3fdf3d 1872 codec->patch_ops = ad198x_patch_ops;
1da177e4 1873
18a815d7 1874 /* override some parameters */
f5fcc13c
TI
1875 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1876 ad1981_models,
1877 ad1981_cfg_tbl);
18a815d7
TI
1878 switch (board_config) {
1879 case AD1981_HP:
1880 spec->mixers[0] = ad1981_hp_mixers;
1881 spec->num_init_verbs = 2;
1882 spec->init_verbs[1] = ad1981_hp_init_verbs;
1883 spec->multiout.dig_out_nid = 0;
1884 spec->input_mux = &ad1981_hp_capture_source;
1885
1886 codec->patch_ops.init = ad1981_hp_init;
1887 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
01f5966d
DC
1888 /* set the upper-limit for mixer amp to 0dB for avoiding the
1889 * possible damage by overloading
1890 */
1891 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1892 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1893 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1894 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1895 (1 << AC_AMPCAP_MUTE_SHIFT));
18a815d7 1896 break;
01686c5f
TI
1897 case AD1981_THINKPAD:
1898 spec->mixers[0] = ad1981_thinkpad_mixers;
01686c5f 1899 spec->input_mux = &ad1981_thinkpad_capture_source;
b8e80cf3
DC
1900 /* set the upper-limit for mixer amp to 0dB for avoiding the
1901 * possible damage by overloading
1902 */
1903 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
1904 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1905 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1906 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1907 (1 << AC_AMPCAP_MUTE_SHIFT));
01686c5f 1908 break;
18768991
TD
1909 case AD1981_TOSHIBA:
1910 spec->mixers[0] = ad1981_hp_mixers;
1911 spec->mixers[1] = ad1981_toshiba_mixers;
1912 spec->num_init_verbs = 2;
1913 spec->init_verbs[1] = ad1981_toshiba_init_verbs;
1914 spec->multiout.dig_out_nid = 0;
1915 spec->input_mux = &ad1981_hp_capture_source;
1916 codec->patch_ops.init = ad1981_hp_init;
1917 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1918 break;
18a815d7 1919 }
729d55ba
TI
1920
1921 codec->no_trigger_sense = 1;
0e7adbe2 1922 codec->no_sticky_stream = 1;
729d55ba 1923
1da177e4
LT
1924 return 0;
1925}
1926
4a3fdf3d 1927
fd66e0d0
TI
1928/*
1929 * AD1988
1930 *
1931 * Output pins and routes
1932 *
d32410b1 1933 * Pin Mix Sel DAC (*)
fd66e0d0
TI
1934 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
1935 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
1936 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
1937 * port-D 0x12 (mute/hp) <- 0x29 <- 04
1938 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
1939 * port-F 0x16 (mute) <- 0x2a <- 06
1940 * port-G 0x24 (mute) <- 0x27 <- 05
1941 * port-H 0x25 (mute) <- 0x28 <- 0a
1942 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
1943 *
d32410b1
TI
1944 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
1945 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
fd66e0d0
TI
1946 *
1947 * Input pins and routes
1948 *
1949 * pin boost mix input # / adc input #
1950 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
1951 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
1952 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
1953 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
1954 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
1955 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
1956 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
1957 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
1958 *
1959 *
1960 * DAC assignment
d32410b1 1961 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
f8c7c7b8 1962 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
fd66e0d0
TI
1963 *
1964 * Inputs of Analog Mix (0x20)
1965 * 0:Port-B (front mic)
1966 * 1:Port-C/G/H (line-in)
1967 * 2:Port-A
1968 * 3:Port-D (line-in/2)
1969 * 4:Port-E/G/H (mic-in)
1970 * 5:Port-F (mic2-in)
1971 * 6:CD
1972 * 7:Beep
1973 *
1974 * ADC selection
1975 * 0:Port-A
1976 * 1:Port-B (front mic-in)
1977 * 2:Port-C (line-in)
1978 * 3:Port-F (mic2-in)
1979 * 4:Port-E (mic-in)
1980 * 5:CD
1981 * 6:Port-G
1982 * 7:Port-H
1983 * 8:Port-D (line-in/2)
1984 * 9:Mix
1985 *
1986 * Proposed pin assignments by the datasheet
1987 *
1988 * 6-stack
1989 * Port-A front headphone
1990 * B front mic-in
1991 * C rear line-in
1992 * D rear front-out
1993 * E rear mic-in
1994 * F rear surround
1995 * G rear CLFE
1996 * H rear side
1997 *
1998 * 3-stack
1999 * Port-A front headphone
2000 * B front mic
2001 * C rear line-in/surround
2002 * D rear front-out
2003 * E rear mic-in/CLFE
2004 *
2005 * laptop
2006 * Port-A headphone
2007 * B mic-in
2008 * C docking station
2009 * D internal speaker (with EAPD)
2010 * E/F quad mic array
2011 */
2012
2013
2014/* models */
2015enum {
2016 AD1988_6STACK,
2017 AD1988_6STACK_DIG,
2018 AD1988_3STACK,
2019 AD1988_3STACK_DIG,
2020 AD1988_LAPTOP,
2021 AD1988_LAPTOP_DIG,
d32410b1 2022 AD1988_AUTO,
fd66e0d0
TI
2023 AD1988_MODEL_LAST,
2024};
2025
d32410b1
TI
2026/* reivision id to check workarounds */
2027#define AD1988A_REV2 0x100200
2028
1a806f48
TI
2029#define is_rev2(codec) \
2030 ((codec)->vendor_id == 0x11d41988 && \
2031 (codec)->revision_id == AD1988A_REV2)
fd66e0d0
TI
2032
2033/*
2034 * mixers
2035 */
2036
d32410b1 2037static hda_nid_t ad1988_6stack_dac_nids[4] = {
fd66e0d0
TI
2038 0x04, 0x06, 0x05, 0x0a
2039};
2040
d32410b1 2041static hda_nid_t ad1988_3stack_dac_nids[3] = {
f8c7c7b8 2042 0x04, 0x05, 0x0a
d32410b1
TI
2043};
2044
2045/* for AD1988A revision-2, DAC2-4 are swapped */
2046static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2047 0x04, 0x05, 0x0a, 0x06
2048};
2049
2050static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
f8c7c7b8 2051 0x04, 0x0a, 0x06
d32410b1
TI
2052};
2053
fd66e0d0
TI
2054static hda_nid_t ad1988_adc_nids[3] = {
2055 0x08, 0x09, 0x0f
2056};
2057
2e5b9567
TI
2058static hda_nid_t ad1988_capsrc_nids[3] = {
2059 0x0c, 0x0d, 0x0e
2060};
2061
9cae0c63
RJ
2062#define AD1988_SPDIF_OUT 0x02
2063#define AD1988_SPDIF_OUT_HDMI 0x0b
fd66e0d0
TI
2064#define AD1988_SPDIF_IN 0x07
2065
3a08e30d
TI
2066static hda_nid_t ad1989b_slave_dig_outs[] = {
2067 AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
9cae0c63
RJ
2068};
2069
fd66e0d0
TI
2070static struct hda_input_mux ad1988_6stack_capture_source = {
2071 .num_items = 5,
2072 .items = {
fb304ce5
TI
2073 { "Front Mic", 0x1 }, /* port-B */
2074 { "Line", 0x2 }, /* port-C */
2075 { "Mic", 0x4 }, /* port-E */
fd66e0d0
TI
2076 { "CD", 0x5 },
2077 { "Mix", 0x9 },
2078 },
2079};
2080
2081static struct hda_input_mux ad1988_laptop_capture_source = {
2082 .num_items = 3,
2083 .items = {
fb304ce5 2084 { "Mic/Line", 0x1 }, /* port-B */
fd66e0d0
TI
2085 { "CD", 0x5 },
2086 { "Mix", 0x9 },
2087 },
2088};
2089
2090/*
2091 */
2092static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2093 struct snd_ctl_elem_info *uinfo)
2094{
2095 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2096 struct ad198x_spec *spec = codec->spec;
2097 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2098 spec->num_channel_mode);
2099}
2100
2101static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2102 struct snd_ctl_elem_value *ucontrol)
2103{
2104 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2105 struct ad198x_spec *spec = codec->spec;
2106 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2107 spec->num_channel_mode, spec->multiout.max_channels);
2108}
2109
2110static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2111 struct snd_ctl_elem_value *ucontrol)
2112{
2113 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2114 struct ad198x_spec *spec = codec->spec;
4e195a7b
TI
2115 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2116 spec->num_channel_mode,
2117 &spec->multiout.max_channels);
bd2033f2 2118 if (err >= 0 && spec->need_dac_fix)
2125cad2 2119 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
4e195a7b 2120 return err;
fd66e0d0
TI
2121}
2122
fd66e0d0 2123/* 6-stack mode */
d32410b1 2124static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
fd66e0d0
TI
2125 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2126 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2127 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2128 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2129 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2ece5f42 2130 { } /* end */
d32410b1
TI
2131};
2132
2133static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2134 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2135 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2136 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2137 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2138 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2ece5f42 2139 { } /* end */
d32410b1 2140};
fd66e0d0 2141
d32410b1 2142static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
fd66e0d0
TI
2143 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2144 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2145 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2146 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2147 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2148 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2149 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2150
2151 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2152 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2153 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2154 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2155 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2156 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2157 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2158 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2159
2e5b9567 2160 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
2161 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2162
2163 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2164 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2165
2166 { } /* end */
2167};
2168
2169/* 3-stack mode */
d32410b1 2170static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
fd66e0d0 2171 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
d32410b1 2172 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
fd66e0d0
TI
2173 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2174 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2ece5f42 2175 { } /* end */
d32410b1
TI
2176};
2177
2178static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2179 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
f8c7c7b8
TI
2180 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2181 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2182 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2ece5f42 2183 { } /* end */
d32410b1 2184};
fd66e0d0 2185
d32410b1 2186static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
fd66e0d0 2187 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
d32410b1
TI
2188 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2189 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2190 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
fd66e0d0
TI
2191 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2192 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2193
2194 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2195 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2196 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2197 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2198 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2199 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2200 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2201 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2202
2e5b9567 2203 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
2204 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2205
2206 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2207 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
2208 {
2209 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2210 .name = "Channel Mode",
2211 .info = ad198x_ch_mode_info,
2212 .get = ad198x_ch_mode_get,
2213 .put = ad198x_ch_mode_put,
2214 },
2215
2216 { } /* end */
2217};
2218
2219/* laptop mode */
2220static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2221 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2222 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2223 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2224
2225 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2226 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2227 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2228 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2229 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2230 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2231
2e5b9567 2232 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
fd66e0d0
TI
2233 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2234
2235 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
2236
2237 {
2238 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2239 .name = "External Amplifier",
5b0cb1d8 2240 .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
18a815d7
TI
2241 .info = ad198x_eapd_info,
2242 .get = ad198x_eapd_get,
2243 .put = ad198x_eapd_put,
ee6e365e 2244 .private_value = 0x12, /* port-D */
fd66e0d0
TI
2245 },
2246
2247 { } /* end */
2248};
2249
2250/* capture */
2251static struct snd_kcontrol_new ad1988_capture_mixers[] = {
2252 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2253 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2254 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2255 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2256 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2257 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2258 {
2259 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2260 /* The multiple "Capture Source" controls confuse alsamixer
2261 * So call somewhat different..
fd66e0d0
TI
2262 */
2263 /* .name = "Capture Source", */
2264 .name = "Input Source",
2265 .count = 3,
2266 .info = ad198x_mux_enum_info,
2267 .get = ad198x_mux_enum_get,
2268 .put = ad198x_mux_enum_put,
2269 },
2270 { } /* end */
2271};
2272
2273static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2274 struct snd_ctl_elem_info *uinfo)
2275{
2276 static char *texts[] = {
2277 "PCM", "ADC1", "ADC2", "ADC3"
2278 };
2279 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2280 uinfo->count = 1;
2281 uinfo->value.enumerated.items = 4;
2282 if (uinfo->value.enumerated.item >= 4)
2283 uinfo->value.enumerated.item = 3;
2284 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2285 return 0;
2286}
2287
2288static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2289 struct snd_ctl_elem_value *ucontrol)
2290{
2291 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2292 unsigned int sel;
2293
bddcf541
TI
2294 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2295 AC_AMP_GET_INPUT);
2296 if (!(sel & 0x80))
2297 ucontrol->value.enumerated.item[0] = 0;
2298 else {
35b26722
TI
2299 sel = snd_hda_codec_read(codec, 0x0b, 0,
2300 AC_VERB_GET_CONNECT_SEL, 0);
2301 if (sel < 3)
fd66e0d0
TI
2302 sel++;
2303 else
2304 sel = 0;
bddcf541 2305 ucontrol->value.enumerated.item[0] = sel;
fd66e0d0 2306 }
fd66e0d0
TI
2307 return 0;
2308}
2309
2310static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2311 struct snd_ctl_elem_value *ucontrol)
2312{
2313 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
35b26722 2314 unsigned int val, sel;
fd66e0d0
TI
2315 int change;
2316
35b26722 2317 val = ucontrol->value.enumerated.item[0];
68ea7b2f
TI
2318 if (val > 3)
2319 return -EINVAL;
35b26722 2320 if (!val) {
bddcf541
TI
2321 sel = snd_hda_codec_read(codec, 0x1d, 0,
2322 AC_VERB_GET_AMP_GAIN_MUTE,
2323 AC_AMP_GET_INPUT);
2324 change = sel & 0x80;
82beb8fd
TI
2325 if (change) {
2326 snd_hda_codec_write_cache(codec, 0x1d, 0,
2327 AC_VERB_SET_AMP_GAIN_MUTE,
2328 AMP_IN_UNMUTE(0));
2329 snd_hda_codec_write_cache(codec, 0x1d, 0,
2330 AC_VERB_SET_AMP_GAIN_MUTE,
2331 AMP_IN_MUTE(1));
bddcf541 2332 }
fd66e0d0 2333 } else {
bddcf541
TI
2334 sel = snd_hda_codec_read(codec, 0x1d, 0,
2335 AC_VERB_GET_AMP_GAIN_MUTE,
2336 AC_AMP_GET_INPUT | 0x01);
2337 change = sel & 0x80;
82beb8fd
TI
2338 if (change) {
2339 snd_hda_codec_write_cache(codec, 0x1d, 0,
2340 AC_VERB_SET_AMP_GAIN_MUTE,
2341 AMP_IN_MUTE(0));
2342 snd_hda_codec_write_cache(codec, 0x1d, 0,
2343 AC_VERB_SET_AMP_GAIN_MUTE,
2344 AMP_IN_UNMUTE(1));
bddcf541 2345 }
35b26722
TI
2346 sel = snd_hda_codec_read(codec, 0x0b, 0,
2347 AC_VERB_GET_CONNECT_SEL, 0) + 1;
2348 change |= sel != val;
82beb8fd
TI
2349 if (change)
2350 snd_hda_codec_write_cache(codec, 0x0b, 0,
2351 AC_VERB_SET_CONNECT_SEL,
2352 val - 1);
fd66e0d0
TI
2353 }
2354 return change;
2355}
2356
2357static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2358 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2359 {
2360 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2361 .name = "IEC958 Playback Source",
5b0cb1d8 2362 .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
fd66e0d0
TI
2363 .info = ad1988_spdif_playback_source_info,
2364 .get = ad1988_spdif_playback_source_get,
2365 .put = ad1988_spdif_playback_source_put,
2366 },
2367 { } /* end */
2368};
2369
2370static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2371 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2372 { } /* end */
2373};
2374
3adb8abc
TI
2375static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2376 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
9cae0c63 2377 HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
3adb8abc
TI
2378 { } /* end */
2379};
fd66e0d0
TI
2380
2381/*
2382 * initialization verbs
2383 */
2384
2385/*
2386 * for 6-stack (+dig)
2387 */
2388static struct hda_verb ad1988_6stack_init_verbs[] = {
2e5b9567
TI
2389 /* Front, Surround, CLFE, side DAC; unmute as default */
2390 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2391 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2392 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2393 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2394 /* Port-A front headphon path */
2395 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2396 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2397 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2398 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2399 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2400 /* Port-D line-out path */
2401 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2402 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2403 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2404 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2405 /* Port-F surround path */
2406 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2407 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2408 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2409 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2410 /* Port-G CLFE path */
2411 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2412 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2413 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2414 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2415 /* Port-H side path */
2416 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2417 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2418 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2419 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2420 /* Mono out path */
2421 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2422 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2423 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2424 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2425 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2426 /* Port-B front mic-in path */
2427 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2428 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2429 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2430 /* Port-C line-in path */
2431 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2432 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2433 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2434 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2435 /* Port-E mic-in path */
2436 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2437 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2438 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2439 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
695005cf
JS
2440 /* Analog CD Input */
2441 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
db3da6c1
TI
2442 /* Analog Mix output amp */
2443 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2444
2445 { }
2446};
2447
2448static struct hda_verb ad1988_capture_init_verbs[] = {
2449 /* mute analog mix */
2450 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2451 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2452 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2453 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2454 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2455 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2456 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2457 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2458 /* select ADCs - front-mic */
2459 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2460 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2461 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
fd66e0d0
TI
2462
2463 { }
2464};
2465
2466static struct hda_verb ad1988_spdif_init_verbs[] = {
2467 /* SPDIF out sel */
2468 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2469 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2470 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
bddcf541 2471 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
fd66e0d0
TI
2472 /* SPDIF out pin */
2473 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
fd66e0d0
TI
2474
2475 { }
2476};
2477
fd0b092a
JK
2478static struct hda_verb ad1988_spdif_in_init_verbs[] = {
2479 /* unmute SPDIF input pin */
2480 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2481 { }
2482};
2483
3adb8abc
TI
2484/* AD1989 has no ADC -> SPDIF route */
2485static struct hda_verb ad1989_spdif_init_verbs[] = {
e8bfc6c1
RJ
2486 /* SPDIF-1 out pin */
2487 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3adb8abc 2488 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
e8bfc6c1
RJ
2489 /* SPDIF-2/HDMI out pin */
2490 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2491 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3adb8abc
TI
2492 { }
2493};
2494
fd66e0d0
TI
2495/*
2496 * verbs for 3stack (+dig)
2497 */
2498static struct hda_verb ad1988_3stack_ch2_init[] = {
2499 /* set port-C to line-in */
2500 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2501 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2502 /* set port-E to mic-in */
2503 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2504 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2505 { } /* end */
2506};
2507
2508static struct hda_verb ad1988_3stack_ch6_init[] = {
2509 /* set port-C to surround out */
fd66e0d0 2510 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 2511 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0 2512 /* set port-E to CLFE out */
fd66e0d0 2513 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
d32410b1 2514 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
fd66e0d0
TI
2515 { } /* end */
2516};
2517
2518static struct hda_channel_mode ad1988_3stack_modes[2] = {
2519 { 2, ad1988_3stack_ch2_init },
2520 { 6, ad1988_3stack_ch6_init },
2521};
2522
2523static struct hda_verb ad1988_3stack_init_verbs[] = {
2e5b9567
TI
2524 /* Front, Surround, CLFE, side DAC; unmute as default */
2525 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2526 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2527 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2528 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2529 /* Port-A front headphon path */
2530 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2531 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2532 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2533 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2534 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2535 /* Port-D line-out path */
2536 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2537 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2538 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2539 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2540 /* Mono out path */
2541 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2542 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2543 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2544 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2545 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2546 /* Port-B front mic-in path */
2547 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2548 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2549 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1
TI
2550 /* Port-C line-in/surround path - 6ch mode as default */
2551 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2552 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 2553 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
d32410b1 2554 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
fd66e0d0 2555 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
d32410b1
TI
2556 /* Port-E mic-in/CLFE path - 6ch mode as default */
2557 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2558 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0 2559 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
f8c7c7b8 2560 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
fd66e0d0
TI
2561 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2562 /* mute analog mix */
2563 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2564 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2565 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2566 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2567 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2568 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2569 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2570 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2571 /* select ADCs - front-mic */
2572 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2573 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2574 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
db3da6c1
TI
2575 /* Analog Mix output amp */
2576 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2577 { }
2578};
2579
2580/*
2581 * verbs for laptop mode (+dig)
2582 */
2583static struct hda_verb ad1988_laptop_hp_on[] = {
2584 /* unmute port-A and mute port-D */
2585 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2586 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2587 { } /* end */
2588};
2589static struct hda_verb ad1988_laptop_hp_off[] = {
2590 /* mute port-A and unmute port-D */
2591 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2592 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2593 { } /* end */
2594};
2595
2596#define AD1988_HP_EVENT 0x01
2597
2598static struct hda_verb ad1988_laptop_init_verbs[] = {
2e5b9567
TI
2599 /* Front, Surround, CLFE, side DAC; unmute as default */
2600 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2601 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2602 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2603 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
fd66e0d0
TI
2604 /* Port-A front headphon path */
2605 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
2606 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2607 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2608 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2609 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2610 /* unsolicited event for pin-sense */
2611 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
2612 /* Port-D line-out path + EAPD */
2613 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2614 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2615 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2616 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2617 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
2618 /* Mono out path */
2619 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2620 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2621 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2622 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2623 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2624 /* Port-B mic-in path */
2625 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2626 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2627 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2628 /* Port-C docking station - try to output */
2629 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2630 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2631 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2632 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2633 /* mute analog mix */
2634 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2635 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2636 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2637 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2638 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2639 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2640 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2641 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2642 /* select ADCs - mic */
2643 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2644 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2645 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
db3da6c1
TI
2646 /* Analog Mix output amp */
2647 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
fd66e0d0
TI
2648 { }
2649};
2650
2651static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
2652{
2653 if ((res >> 26) != AD1988_HP_EVENT)
2654 return;
d56757ab 2655 if (snd_hda_jack_detect(codec, 0x11))
fd66e0d0
TI
2656 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
2657 else
2658 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
2659}
2660
cb53c626
TI
2661#ifdef CONFIG_SND_HDA_POWER_SAVE
2662static struct hda_amp_list ad1988_loopbacks[] = {
2663 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
2664 { 0x20, HDA_INPUT, 1 }, /* Line */
2665 { 0x20, HDA_INPUT, 4 }, /* Mic */
2666 { 0x20, HDA_INPUT, 6 }, /* CD */
2667 { } /* end */
2668};
2669#endif
fd66e0d0 2670
d32410b1
TI
2671/*
2672 * Automatic parse of I/O pins from the BIOS configuration
2673 */
2674
d32410b1
TI
2675enum {
2676 AD_CTL_WIDGET_VOL,
2677 AD_CTL_WIDGET_MUTE,
2678 AD_CTL_BIND_MUTE,
2679};
2680static struct snd_kcontrol_new ad1988_control_templates[] = {
2681 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2682 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2683 HDA_BIND_MUTE(NULL, 0, 0, 0),
2684};
2685
2686/* add dynamic controls */
2687static int add_control(struct ad198x_spec *spec, int type, const char *name,
2688 unsigned long val)
2689{
2690 struct snd_kcontrol_new *knew;
2691
603c4019
TI
2692 snd_array_init(&spec->kctls, sizeof(*knew), 32);
2693 knew = snd_array_new(&spec->kctls);
2694 if (!knew)
2695 return -ENOMEM;
d32410b1
TI
2696 *knew = ad1988_control_templates[type];
2697 knew->name = kstrdup(name, GFP_KERNEL);
2698 if (! knew->name)
2699 return -ENOMEM;
4d02d1b6 2700 if (get_amp_nid_(val))
5e26dfd0 2701 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
d32410b1 2702 knew->private_value = val;
d32410b1
TI
2703 return 0;
2704}
2705
2706#define AD1988_PIN_CD_NID 0x18
2707#define AD1988_PIN_BEEP_NID 0x10
2708
2709static hda_nid_t ad1988_mixer_nids[8] = {
2710 /* A B C D E F G H */
2711 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2712};
2713
2714static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2715{
2716 static hda_nid_t idx_to_dac[8] = {
2717 /* A B C D E F G H */
f8c7c7b8 2718 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
d32410b1
TI
2719 };
2720 static hda_nid_t idx_to_dac_rev2[8] = {
2721 /* A B C D E F G H */
f8c7c7b8 2722 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
d32410b1 2723 };
1a806f48 2724 if (is_rev2(codec))
d32410b1
TI
2725 return idx_to_dac_rev2[idx];
2726 else
2727 return idx_to_dac[idx];
2728}
2729
2730static hda_nid_t ad1988_boost_nids[8] = {
2731 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2732};
2733
2734static int ad1988_pin_idx(hda_nid_t nid)
2735{
2736 static hda_nid_t ad1988_io_pins[8] = {
2737 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2738 };
2739 int i;
2740 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2741 if (ad1988_io_pins[i] == nid)
2742 return i;
2743 return 0; /* should be -1 */
2744}
2745
2746static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2747{
2748 static int loopback_idx[8] = {
2749 2, 0, 1, 3, 4, 5, 1, 4
2750 };
2751 switch (nid) {
2752 case AD1988_PIN_CD_NID:
2753 return 6;
2754 default:
2755 return loopback_idx[ad1988_pin_idx(nid)];
2756 }
2757}
2758
2759static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2760{
2761 static int adc_idx[8] = {
2762 0, 1, 2, 8, 4, 3, 6, 7
2763 };
2764 switch (nid) {
2765 case AD1988_PIN_CD_NID:
2766 return 5;
2767 default:
2768 return adc_idx[ad1988_pin_idx(nid)];
2769 }
2770}
2771
2772/* fill in the dac_nids table from the parsed pin configuration */
2773static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2774 const struct auto_pin_cfg *cfg)
2775{
2776 struct ad198x_spec *spec = codec->spec;
2777 int i, idx;
2778
2779 spec->multiout.dac_nids = spec->private_dac_nids;
2780
2781 /* check the pins hardwired to audio widget */
2782 for (i = 0; i < cfg->line_outs; i++) {
2783 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2784 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2785 }
2786 spec->multiout.num_dacs = cfg->line_outs;
2787 return 0;
2788}
2789
2790/* add playback controls from the parsed DAC table */
2791static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2792 const struct auto_pin_cfg *cfg)
2793{
2794 char name[32];
2795 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
2796 hda_nid_t nid;
2797 int i, err;
2798
2799 for (i = 0; i < cfg->line_outs; i++) {
2800 hda_nid_t dac = spec->multiout.dac_nids[i];
2801 if (! dac)
2802 continue;
2803 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2804 if (i == 2) {
2805 /* Center/LFE */
2806 err = add_control(spec, AD_CTL_WIDGET_VOL,
2807 "Center Playback Volume",
2808 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2809 if (err < 0)
2810 return err;
2811 err = add_control(spec, AD_CTL_WIDGET_VOL,
2812 "LFE Playback Volume",
2813 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2814 if (err < 0)
2815 return err;
2816 err = add_control(spec, AD_CTL_BIND_MUTE,
2817 "Center Playback Switch",
2818 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2819 if (err < 0)
2820 return err;
2821 err = add_control(spec, AD_CTL_BIND_MUTE,
2822 "LFE Playback Switch",
2823 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2824 if (err < 0)
2825 return err;
2826 } else {
2827 sprintf(name, "%s Playback Volume", chname[i]);
2828 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2829 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2830 if (err < 0)
2831 return err;
2832 sprintf(name, "%s Playback Switch", chname[i]);
2833 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2834 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2835 if (err < 0)
2836 return err;
2837 }
2838 }
2839 return 0;
2840}
2841
2842/* add playback controls for speaker and HP outputs */
2843static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2844 const char *pfx)
2845{
2846 struct ad198x_spec *spec = codec->spec;
2847 hda_nid_t nid;
43785eae 2848 int i, idx, err;
d32410b1
TI
2849 char name[32];
2850
2851 if (! pin)
2852 return 0;
2853
2854 idx = ad1988_pin_idx(pin);
2855 nid = ad1988_idx_to_dac(codec, idx);
43785eae
TI
2856 /* check whether the corresponding DAC was already taken */
2857 for (i = 0; i < spec->autocfg.line_outs; i++) {
2858 hda_nid_t pin = spec->autocfg.line_out_pins[i];
2859 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
2860 if (dac == nid)
2861 break;
2862 }
2863 if (i >= spec->autocfg.line_outs) {
2864 /* specify the DAC as the extra output */
2865 if (!spec->multiout.hp_nid)
2866 spec->multiout.hp_nid = nid;
2867 else
2868 spec->multiout.extra_out_nid[0] = nid;
2869 /* control HP volume/switch on the output mixer amp */
2870 sprintf(name, "%s Playback Volume", pfx);
2871 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2872 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
2873 if (err < 0)
2874 return err;
2875 }
d32410b1
TI
2876 nid = ad1988_mixer_nids[idx];
2877 sprintf(name, "%s Playback Switch", pfx);
2878 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
2879 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
2880 return err;
2881 return 0;
2882}
2883
2884/* create input playback/capture controls for the given pin */
2885static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
9e042e71 2886 const char *ctlname, int ctlidx, int boost)
d32410b1
TI
2887{
2888 char name[32];
2889 int err, idx;
2890
2891 sprintf(name, "%s Playback Volume", ctlname);
2892 idx = ad1988_pin_to_loopback_idx(pin);
2893 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2894 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2895 return err;
2896 sprintf(name, "%s Playback Switch", ctlname);
2897 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
2898 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
2899 return err;
2900 if (boost) {
2901 hda_nid_t bnid;
2902 idx = ad1988_pin_idx(pin);
2903 bnid = ad1988_boost_nids[idx];
2904 if (bnid) {
2905 sprintf(name, "%s Boost", ctlname);
2906 return add_control(spec, AD_CTL_WIDGET_VOL, name,
2907 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
2908
2909 }
2910 }
2911 return 0;
2912}
2913
2914/* create playback/capture controls for input pins */
10a20af7 2915static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
d32410b1
TI
2916 const struct auto_pin_cfg *cfg)
2917{
10a20af7 2918 struct ad198x_spec *spec = codec->spec;
d32410b1 2919 struct hda_input_mux *imux = &spec->private_imux;
10a20af7 2920 int i, err, type, type_idx;
d32410b1 2921
9e042e71 2922 for (i = 0; i < cfg->num_inputs; i++) {
10a20af7 2923 const char *label;
9e042e71 2924 type = cfg->inputs[i].type;
10a20af7
TI
2925 label = hda_get_autocfg_input_label(codec, cfg, i);
2926 snd_hda_add_imux_item(imux, label,
2927 ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
2928 &type_idx);
9e042e71 2929 err = new_analog_input(spec, cfg->inputs[i].pin,
10a20af7 2930 label, type_idx,
86e2959a 2931 type == AUTO_PIN_MIC);
d32410b1
TI
2932 if (err < 0)
2933 return err;
d32410b1 2934 }
10a20af7 2935 snd_hda_add_imux_item(imux, "Mix", 9, NULL);
d32410b1
TI
2936
2937 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2938 "Analog Mix Playback Volume",
2939 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2940 return err;
2941 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
2942 "Analog Mix Playback Switch",
2943 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
2944 return err;
2945
2946 return 0;
2947}
2948
2949static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
2950 hda_nid_t nid, int pin_type,
2951 int dac_idx)
2952{
2953 /* set as output */
2954 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2955 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2956 switch (nid) {
2957 case 0x11: /* port-A - DAC 04 */
2958 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2959 break;
2960 case 0x14: /* port-B - DAC 06 */
2961 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
2962 break;
2963 case 0x15: /* port-C - DAC 05 */
2964 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
2965 break;
f8c7c7b8 2966 case 0x17: /* port-E - DAC 0a */
d32410b1
TI
2967 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2968 break;
2969 case 0x13: /* mono - DAC 04 */
2970 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
2971 break;
2972 }
2973}
2974
2975static void ad1988_auto_init_multi_out(struct hda_codec *codec)
2976{
2977 struct ad198x_spec *spec = codec->spec;
2978 int i;
2979
2980 for (i = 0; i < spec->autocfg.line_outs; i++) {
2981 hda_nid_t nid = spec->autocfg.line_out_pins[i];
2982 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
2983 }
2984}
2985
2986static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2987{
2988 struct ad198x_spec *spec = codec->spec;
2989 hda_nid_t pin;
2990
82bc955f 2991 pin = spec->autocfg.speaker_pins[0];
d32410b1
TI
2992 if (pin) /* connect to front */
2993 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
eb06ed8f 2994 pin = spec->autocfg.hp_pins[0];
d32410b1
TI
2995 if (pin) /* connect to front */
2996 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2997}
2998
2999static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3000{
3001 struct ad198x_spec *spec = codec->spec;
9e042e71 3002 const struct auto_pin_cfg *cfg = &spec->autocfg;
d32410b1
TI
3003 int i, idx;
3004
9e042e71
TI
3005 for (i = 0; i < cfg->num_inputs; i++) {
3006 hda_nid_t nid = cfg->inputs[i].pin;
d32410b1
TI
3007 switch (nid) {
3008 case 0x15: /* port-C */
3009 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3010 break;
3011 case 0x17: /* port-E */
3012 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3013 break;
3014 }
3015 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
86e2959a 3016 i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
d32410b1
TI
3017 if (nid != AD1988_PIN_CD_NID)
3018 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3019 AMP_OUT_MUTE);
3020 idx = ad1988_pin_idx(nid);
3021 if (ad1988_boost_nids[idx])
3022 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3023 AC_VERB_SET_AMP_GAIN_MUTE,
3024 AMP_OUT_ZERO);
3025 }
3026}
3027
3028/* parse the BIOS configuration and set up the alc_spec */
3029/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3030static int ad1988_parse_auto_config(struct hda_codec *codec)
3031{
3032 struct ad198x_spec *spec = codec->spec;
3033 int err;
3034
df694daa 3035 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
d32410b1
TI
3036 return err;
3037 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3038 return err;
82bc955f 3039 if (! spec->autocfg.line_outs)
d32410b1
TI
3040 return 0; /* can't find valid BIOS pin config */
3041 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
82bc955f
TI
3042 (err = ad1988_auto_create_extra_out(codec,
3043 spec->autocfg.speaker_pins[0],
d32410b1 3044 "Speaker")) < 0 ||
eb06ed8f 3045 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
d32410b1 3046 "Headphone")) < 0 ||
10a20af7 3047 (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
d32410b1
TI
3048 return err;
3049
3050 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3051
0852d7a6 3052 if (spec->autocfg.dig_outs)
d32410b1
TI
3053 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3054 if (spec->autocfg.dig_in_pin)
3055 spec->dig_in_nid = AD1988_SPDIF_IN;
3056
603c4019
TI
3057 if (spec->kctls.list)
3058 spec->mixers[spec->num_mixers++] = spec->kctls.list;
d32410b1
TI
3059
3060 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3061
3062 spec->input_mux = &spec->private_imux;
3063
3064 return 1;
3065}
3066
3067/* init callback for auto-configuration model -- overriding the default init */
3068static int ad1988_auto_init(struct hda_codec *codec)
3069{
3070 ad198x_init(codec);
3071 ad1988_auto_init_multi_out(codec);
3072 ad1988_auto_init_extra_out(codec);
3073 ad1988_auto_init_analog_input(codec);
3074 return 0;
3075}
3076
3077
fd66e0d0
TI
3078/*
3079 */
3080
f5fcc13c
TI
3081static const char *ad1988_models[AD1988_MODEL_LAST] = {
3082 [AD1988_6STACK] = "6stack",
3083 [AD1988_6STACK_DIG] = "6stack-dig",
3084 [AD1988_3STACK] = "3stack",
3085 [AD1988_3STACK_DIG] = "3stack-dig",
3086 [AD1988_LAPTOP] = "laptop",
3087 [AD1988_LAPTOP_DIG] = "laptop-dig",
3088 [AD1988_AUTO] = "auto",
fd66e0d0
TI
3089};
3090
a64c8cd6 3091static struct snd_pci_quirk ad1988_cfg_tbl[] = {
18768991 3092 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
ac3e3741 3093 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
b9e16bc5 3094 SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
f51ff993 3095 SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
a64c8cd6
TD
3096 {}
3097};
3098
fd66e0d0
TI
3099static int patch_ad1988(struct hda_codec *codec)
3100{
3101 struct ad198x_spec *spec;
c5a4bcd0 3102 int err, board_config;
fd66e0d0
TI
3103
3104 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3105 if (spec == NULL)
3106 return -ENOMEM;
3107
fd66e0d0
TI
3108 codec->spec = spec;
3109
1a806f48 3110 if (is_rev2(codec))
f8c7c7b8
TI
3111 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3112
f5fcc13c 3113 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
a64c8cd6 3114 ad1988_models, ad1988_cfg_tbl);
f5fcc13c 3115 if (board_config < 0) {
9a11f1aa
TI
3116 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3117 codec->chip_name);
d32410b1
TI
3118 board_config = AD1988_AUTO;
3119 }
3120
3121 if (board_config == AD1988_AUTO) {
3122 /* automatic parse from the BIOS config */
c5a4bcd0 3123 err = ad1988_parse_auto_config(codec);
d32410b1
TI
3124 if (err < 0) {
3125 ad198x_free(codec);
3126 return err;
3127 } else if (! err) {
3128 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3129 board_config = AD1988_6STACK;
3130 }
fd66e0d0
TI
3131 }
3132
c5a4bcd0
TI
3133 err = snd_hda_attach_beep_device(codec, 0x10);
3134 if (err < 0) {
3135 ad198x_free(codec);
3136 return err;
3137 }
3138 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3139
fd66e0d0
TI
3140 switch (board_config) {
3141 case AD1988_6STACK:
3142 case AD1988_6STACK_DIG:
3143 spec->multiout.max_channels = 8;
3144 spec->multiout.num_dacs = 4;
1a806f48 3145 if (is_rev2(codec))
d32410b1
TI
3146 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3147 else
3148 spec->multiout.dac_nids = ad1988_6stack_dac_nids;
fd66e0d0 3149 spec->input_mux = &ad1988_6stack_capture_source;
d32410b1 3150 spec->num_mixers = 2;
1a806f48 3151 if (is_rev2(codec))
d32410b1
TI
3152 spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3153 else
3154 spec->mixers[0] = ad1988_6stack_mixers1;
3155 spec->mixers[1] = ad1988_6stack_mixers2;
fd66e0d0
TI
3156 spec->num_init_verbs = 1;
3157 spec->init_verbs[0] = ad1988_6stack_init_verbs;
3158 if (board_config == AD1988_6STACK_DIG) {
3159 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3160 spec->dig_in_nid = AD1988_SPDIF_IN;
3161 }
3162 break;
3163 case AD1988_3STACK:
3164 case AD1988_3STACK_DIG:
3165 spec->multiout.max_channels = 6;
3166 spec->multiout.num_dacs = 3;
1a806f48 3167 if (is_rev2(codec))
d32410b1
TI
3168 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3169 else
3170 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
3171 spec->input_mux = &ad1988_6stack_capture_source;
3172 spec->channel_mode = ad1988_3stack_modes;
3173 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
d32410b1 3174 spec->num_mixers = 2;
1a806f48 3175 if (is_rev2(codec))
d32410b1
TI
3176 spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3177 else
3178 spec->mixers[0] = ad1988_3stack_mixers1;
3179 spec->mixers[1] = ad1988_3stack_mixers2;
fd66e0d0
TI
3180 spec->num_init_verbs = 1;
3181 spec->init_verbs[0] = ad1988_3stack_init_verbs;
3182 if (board_config == AD1988_3STACK_DIG)
3183 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3184 break;
3185 case AD1988_LAPTOP:
3186 case AD1988_LAPTOP_DIG:
3187 spec->multiout.max_channels = 2;
3188 spec->multiout.num_dacs = 1;
d32410b1 3189 spec->multiout.dac_nids = ad1988_3stack_dac_nids;
fd66e0d0
TI
3190 spec->input_mux = &ad1988_laptop_capture_source;
3191 spec->num_mixers = 1;
3192 spec->mixers[0] = ad1988_laptop_mixers;
ee6e365e 3193 spec->inv_eapd = 1; /* inverted EAPD */
fd66e0d0
TI
3194 spec->num_init_verbs = 1;
3195 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3196 if (board_config == AD1988_LAPTOP_DIG)
3197 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3198 break;
3199 }
3200
d32410b1
TI
3201 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3202 spec->adc_nids = ad1988_adc_nids;
3203 spec->capsrc_nids = ad1988_capsrc_nids;
fd66e0d0
TI
3204 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3205 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3206 if (spec->multiout.dig_out_nid) {
3adb8abc
TI
3207 if (codec->vendor_id >= 0x11d4989a) {
3208 spec->mixers[spec->num_mixers++] =
3209 ad1989_spdif_out_mixers;
3210 spec->init_verbs[spec->num_init_verbs++] =
3211 ad1989_spdif_init_verbs;
9cae0c63 3212 codec->slave_dig_outs = ad1989b_slave_dig_outs;
3adb8abc
TI
3213 } else {
3214 spec->mixers[spec->num_mixers++] =
3215 ad1988_spdif_out_mixers;
3216 spec->init_verbs[spec->num_init_verbs++] =
3217 ad1988_spdif_init_verbs;
3218 }
fd66e0d0 3219 }
fd0b092a 3220 if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
fd66e0d0 3221 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
fd0b092a
JK
3222 spec->init_verbs[spec->num_init_verbs++] =
3223 ad1988_spdif_in_init_verbs;
3224 }
fd66e0d0
TI
3225
3226 codec->patch_ops = ad198x_patch_ops;
3227 switch (board_config) {
d32410b1
TI
3228 case AD1988_AUTO:
3229 codec->patch_ops.init = ad1988_auto_init;
3230 break;
fd66e0d0
TI
3231 case AD1988_LAPTOP:
3232 case AD1988_LAPTOP_DIG:
3233 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3234 break;
3235 }
cb53c626
TI
3236#ifdef CONFIG_SND_HDA_POWER_SAVE
3237 spec->loopback.amplist = ad1988_loopbacks;
3238#endif
2134ea4f 3239 spec->vmaster_nid = 0x04;
fd66e0d0 3240
729d55ba 3241 codec->no_trigger_sense = 1;
0e7adbe2 3242 codec->no_sticky_stream = 1;
729d55ba 3243
fd66e0d0
TI
3244 return 0;
3245}
3246
3247
2bac647c
TI
3248/*
3249 * AD1884 / AD1984
3250 *
3251 * port-B - front line/mic-in
3252 * port-E - aux in/out
3253 * port-F - aux in/out
3254 * port-C - rear line/mic-in
3255 * port-D - rear line/hp-out
3256 * port-A - front line/hp-out
3257 *
3258 * AD1984 = AD1884 + two digital mic-ins
3259 *
3260 * FIXME:
3261 * For simplicity, we share the single DAC for both HP and line-outs
3262 * right now. The inidividual playbacks could be easily implemented,
3263 * but no build-up framework is given, so far.
3264 */
3265
3266static hda_nid_t ad1884_dac_nids[1] = {
3267 0x04,
3268};
3269
3270static hda_nid_t ad1884_adc_nids[2] = {
3271 0x08, 0x09,
3272};
3273
3274static hda_nid_t ad1884_capsrc_nids[2] = {
3275 0x0c, 0x0d,
3276};
3277
3278#define AD1884_SPDIF_OUT 0x02
3279
3280static struct hda_input_mux ad1884_capture_source = {
3281 .num_items = 4,
3282 .items = {
3283 { "Front Mic", 0x0 },
3284 { "Mic", 0x1 },
3285 { "CD", 0x2 },
3286 { "Mix", 0x3 },
3287 },
3288};
3289
3290static struct snd_kcontrol_new ad1884_base_mixers[] = {
3291 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3292 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3293 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3294 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3295 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3296 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3297 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3298 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3299 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3300 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3301 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3302 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
2bac647c
TI
3303 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
3304 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3305 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3306 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3307 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3308 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3309 {
3310 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3311 /* The multiple "Capture Source" controls confuse alsamixer
3312 * So call somewhat different..
2bac647c
TI
3313 */
3314 /* .name = "Capture Source", */
3315 .name = "Input Source",
3316 .count = 2,
3317 .info = ad198x_mux_enum_info,
3318 .get = ad198x_mux_enum_get,
3319 .put = ad198x_mux_enum_put,
3320 },
3321 /* SPDIF controls */
3322 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3323 {
3324 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3325 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3326 /* identical with ad1983 */
3327 .info = ad1983_spdif_route_info,
3328 .get = ad1983_spdif_route_get,
3329 .put = ad1983_spdif_route_put,
3330 },
3331 { } /* end */
3332};
3333
3334static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3335 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3336 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3337 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
538c49c4 3338 HDA_INPUT),
2bac647c 3339 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
538c49c4 3340 HDA_INPUT),
2bac647c
TI
3341 { } /* end */
3342};
3343
3344/*
3345 * initialization verbs
3346 */
3347static struct hda_verb ad1884_init_verbs[] = {
3348 /* DACs; mute as default */
3b194401
TI
3349 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3350 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2bac647c
TI
3351 /* Port-A (HP) mixer */
3352 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3353 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3354 /* Port-A pin */
3355 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3356 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3357 /* HP selector - select DAC2 */
3358 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3359 /* Port-D (Line-out) mixer */
3360 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3361 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3362 /* Port-D pin */
3363 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3364 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3365 /* Mono-out mixer */
3366 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3367 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3368 /* Mono-out pin */
3369 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3370 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3371 /* Mono selector */
3372 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3373 /* Port-B (front mic) pin */
3374 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
60e388e8 3375 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2bac647c
TI
3376 /* Port-C (rear mic) pin */
3377 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
60e388e8 3378 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2bac647c
TI
3379 /* Analog mixer; mute as default */
3380 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3381 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3382 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3383 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3384 /* Analog Mix output amp */
3385 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3386 /* SPDIF output selector */
3387 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3388 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3389 { } /* end */
3390};
3391
cb53c626
TI
3392#ifdef CONFIG_SND_HDA_POWER_SAVE
3393static struct hda_amp_list ad1884_loopbacks[] = {
3394 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3395 { 0x20, HDA_INPUT, 1 }, /* Mic */
3396 { 0x20, HDA_INPUT, 2 }, /* CD */
3397 { 0x20, HDA_INPUT, 4 }, /* Docking */
3398 { } /* end */
3399};
3400#endif
3401
2134ea4f
TI
3402static const char *ad1884_slave_vols[] = {
3403 "PCM Playback Volume",
3404 "Mic Playback Volume",
3405 "Mono Playback Volume",
3406 "Front Mic Playback Volume",
3407 "Mic Playback Volume",
3408 "CD Playback Volume",
3409 "Internal Mic Playback Volume",
bca68467 3410 "Docking Mic Playback Volume",
c5a4bcd0 3411 /* "Beep Playback Volume", */
4806ef0c 3412 "IEC958 Playback Volume",
2134ea4f
TI
3413 NULL
3414};
3415
2bac647c
TI
3416static int patch_ad1884(struct hda_codec *codec)
3417{
3418 struct ad198x_spec *spec;
c5a4bcd0 3419 int err;
2bac647c
TI
3420
3421 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3422 if (spec == NULL)
3423 return -ENOMEM;
3424
2bac647c
TI
3425 codec->spec = spec;
3426
c5a4bcd0
TI
3427 err = snd_hda_attach_beep_device(codec, 0x10);
3428 if (err < 0) {
3429 ad198x_free(codec);
3430 return err;
3431 }
3432 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3433
2bac647c
TI
3434 spec->multiout.max_channels = 2;
3435 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3436 spec->multiout.dac_nids = ad1884_dac_nids;
3437 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3438 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3439 spec->adc_nids = ad1884_adc_nids;
3440 spec->capsrc_nids = ad1884_capsrc_nids;
3441 spec->input_mux = &ad1884_capture_source;
3442 spec->num_mixers = 1;
3443 spec->mixers[0] = ad1884_base_mixers;
3444 spec->num_init_verbs = 1;
3445 spec->init_verbs[0] = ad1884_init_verbs;
3446 spec->spdif_route = 0;
cb53c626
TI
3447#ifdef CONFIG_SND_HDA_POWER_SAVE
3448 spec->loopback.amplist = ad1884_loopbacks;
3449#endif
2134ea4f
TI
3450 spec->vmaster_nid = 0x04;
3451 /* we need to cover all playback volumes */
3452 spec->slave_vols = ad1884_slave_vols;
2bac647c
TI
3453
3454 codec->patch_ops = ad198x_patch_ops;
3455
729d55ba 3456 codec->no_trigger_sense = 1;
0e7adbe2 3457 codec->no_sticky_stream = 1;
729d55ba 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),
0f9f1ee9 3650 SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
2bac647c
TI
3651 {}
3652};
3653
3654static int patch_ad1984(struct hda_codec *codec)
3655{
3656 struct ad198x_spec *spec;
3657 int board_config, err;
3658
3659 err = patch_ad1884(codec);
3660 if (err < 0)
3661 return err;
3662 spec = codec->spec;
3663 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3664 ad1984_models, ad1984_cfg_tbl);
3665 switch (board_config) {
3666 case AD1984_BASIC:
3667 /* additional digital mics */
3668 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3669 codec->patch_ops.build_pcms = ad1984_build_pcms;
3670 break;
3671 case AD1984_THINKPAD:
68c18697
JY
3672 if (codec->subsystem_id == 0x17aa20fb) {
3673 /* Thinpad X300 does not have the ability to do SPDIF,
3674 or attach to docking station to use SPDIF */
3675 spec->multiout.dig_out_nid = 0;
3676 } else
3677 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
2bac647c
TI
3678 spec->input_mux = &ad1984_thinkpad_capture_source;
3679 spec->mixers[0] = ad1984_thinkpad_mixers;
3680 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
0bf0e5a6 3681 spec->analog_beep = 1;
2bac647c 3682 break;
0aaa22e5
DK
3683 case AD1984_DELL_DESKTOP:
3684 spec->multiout.dig_out_nid = 0;
3685 spec->input_mux = &ad1984_dell_desktop_capture_source;
3686 spec->mixers[0] = ad1984_dell_desktop_mixers;
3687 break;
2bac647c
TI
3688 }
3689 return 0;
3690}
3691
3692
c5059259
TI
3693/*
3694 * AD1883 / AD1884A / AD1984A / AD1984B
3695 *
3696 * port-B (0x14) - front mic-in
3697 * port-E (0x1c) - rear mic-in
3698 * port-F (0x16) - CD / ext out
3699 * port-C (0x15) - rear line-in
3700 * port-D (0x12) - rear line-out
3701 * port-A (0x11) - front hp-out
3702 *
3703 * AD1984A = AD1884A + digital-mic
3704 * AD1883 = equivalent with AD1984A
3705 * AD1984B = AD1984A + extra SPDIF-out
3706 *
3707 * FIXME:
3708 * We share the single DAC for both HP and line-outs (see AD1884/1984).
3709 */
3710
3711static hda_nid_t ad1884a_dac_nids[1] = {
3712 0x03,
3713};
3714
3715#define ad1884a_adc_nids ad1884_adc_nids
3716#define ad1884a_capsrc_nids ad1884_capsrc_nids
3717
3718#define AD1884A_SPDIF_OUT 0x02
3719
3720static struct hda_input_mux ad1884a_capture_source = {
3721 .num_items = 5,
3722 .items = {
3723 { "Front Mic", 0x0 },
3724 { "Mic", 0x4 },
3725 { "Line", 0x1 },
3726 { "CD", 0x2 },
3727 { "Mix", 0x3 },
3728 },
3729};
3730
3731static struct snd_kcontrol_new ad1884a_base_mixers[] = {
3732 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
3733 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
3734 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3735 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3736 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3737 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3738 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3739 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3740 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3741 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3742 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
3743 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
3744 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3745 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3746 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3747 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
c5059259
TI
3748 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
3749 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
3750 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3751 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3752 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3753 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3754 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3755 {
3756 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3757 /* The multiple "Capture Source" controls confuse alsamixer
3758 * So call somewhat different..
3759 */
3760 /* .name = "Capture Source", */
3761 .name = "Input Source",
3762 .count = 2,
3763 .info = ad198x_mux_enum_info,
3764 .get = ad198x_mux_enum_get,
3765 .put = ad198x_mux_enum_put,
3766 },
3767 /* SPDIF controls */
3768 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3769 {
3770 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3771 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3772 /* identical with ad1983 */
3773 .info = ad1983_spdif_route_info,
3774 .get = ad1983_spdif_route_get,
3775 .put = ad1983_spdif_route_put,
3776 },
3777 { } /* end */
3778};
3779
3780/*
3781 * initialization verbs
3782 */
3783static struct hda_verb ad1884a_init_verbs[] = {
3784 /* DACs; unmute as default */
3785 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3786 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
3787 /* Port-A (HP) mixer - route only from analog mixer */
3788 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3789 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3790 /* Port-A pin */
3791 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3792 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3793 /* Port-D (Line-out) mixer - route only from analog mixer */
3794 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3795 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3796 /* Port-D pin */
3797 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3798 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3799 /* Mono-out mixer - route only from analog mixer */
3800 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3801 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3802 /* Mono-out pin */
3803 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3804 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3805 /* Port-B (front mic) pin */
3806 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
60e388e8 3807 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
c5059259
TI
3808 /* Port-C (rear line-in) pin */
3809 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
60e388e8 3810 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
c5059259
TI
3811 /* Port-E (rear mic) pin */
3812 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3813 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3814 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
3815 /* Port-F (CD) pin */
3816 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3817 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3818 /* Analog mixer; mute as default */
3819 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3820 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3821 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3822 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3823 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
3824 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3825 /* Analog Mix output amp */
3826 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3827 /* capture sources */
3828 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
3829 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3830 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
3831 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3832 /* SPDIF output amp */
3833 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3834 { } /* end */
3835};
3836
3837#ifdef CONFIG_SND_HDA_POWER_SAVE
3838static struct hda_amp_list ad1884a_loopbacks[] = {
3839 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3840 { 0x20, HDA_INPUT, 1 }, /* Mic */
3841 { 0x20, HDA_INPUT, 2 }, /* CD */
3842 { 0x20, HDA_INPUT, 4 }, /* Docking */
3843 { } /* end */
3844};
3845#endif
3846
3847/*
3848 * Laptop model
3849 *
3850 * Port A: Headphone jack
3851 * Port B: MIC jack
3852 * Port C: Internal MIC
3853 * Port D: Dock Line Out (if enabled)
3854 * Port E: Dock Line In (if enabled)
3855 * Port F: Internal speakers
3856 */
3857
17bbaa6f
TI
3858static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
3859 struct snd_ctl_elem_value *ucontrol)
3860{
3861 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3862 int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3863 int mute = (!ucontrol->value.integer.value[0] &&
3864 !ucontrol->value.integer.value[1]);
3865 /* toggle GPIO1 according to the mute state */
3866 snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3867 mute ? 0x02 : 0x0);
3868 return ret;
3869}
c5059259
TI
3870
3871static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
3872 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
17bbaa6f
TI
3873 {
3874 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3875 .name = "Master Playback Switch",
5e26dfd0 3876 .subdevice = HDA_SUBDEV_AMP_FLAG,
17bbaa6f
TI
3877 .info = snd_hda_mixer_amp_switch_info,
3878 .get = snd_hda_mixer_amp_switch_get,
3879 .put = ad1884a_mobile_master_sw_put,
3880 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3881 },
c5059259
TI
3882 HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3883 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3884 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
3885 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3886 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3887 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3888 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3889 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3890 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
c5059259
TI
3891 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
3892 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
3893 HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
3894 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3895 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
c5059259
TI
3896 { } /* end */
3897};
3898
b40b04ad
TI
3899static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
3900 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
099db17e
TI
3901 /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
3902 {
3903 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3904 .name = "Master Playback Switch",
5e26dfd0 3905 .subdevice = HDA_SUBDEV_AMP_FLAG,
099db17e
TI
3906 .info = snd_hda_mixer_amp_switch_info,
3907 .get = snd_hda_mixer_amp_switch_get,
3908 .put = ad1884a_mobile_master_sw_put,
3909 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
3910 },
b40b04ad
TI
3911 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
3912 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
269ef19c
TI
3913 HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
3914 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
b40b04ad
TI
3915 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3916 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
b40b04ad
TI
3917 { } /* end */
3918};
3919
c5059259
TI
3920/* mute internal speaker if HP is plugged */
3921static void ad1884a_hp_automute(struct hda_codec *codec)
3922{
3923 unsigned int present;
3924
d56757ab 3925 present = snd_hda_jack_detect(codec, 0x11);
c5059259
TI
3926 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3927 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3928 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3929 present ? 0x00 : 0x02);
3930}
3931
269ef19c
TI
3932/* switch to external mic if plugged */
3933static void ad1884a_hp_automic(struct hda_codec *codec)
3934{
3935 unsigned int present;
3936
d56757ab 3937 present = snd_hda_jack_detect(codec, 0x14);
269ef19c
TI
3938 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
3939 present ? 0 : 1);
3940}
3941
c5059259 3942#define AD1884A_HP_EVENT 0x37
269ef19c 3943#define AD1884A_MIC_EVENT 0x36
c5059259
TI
3944
3945/* unsolicited event for HP jack sensing */
3946static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
3947{
269ef19c
TI
3948 switch (res >> 26) {
3949 case AD1884A_HP_EVENT:
3950 ad1884a_hp_automute(codec);
3951 break;
3952 case AD1884A_MIC_EVENT:
3953 ad1884a_hp_automic(codec);
3954 break;
3955 }
c5059259
TI
3956}
3957
3958/* initialize jack-sensing, too */
3959static int ad1884a_hp_init(struct hda_codec *codec)
3960{
3961 ad198x_init(codec);
3962 ad1884a_hp_automute(codec);
269ef19c 3963 ad1884a_hp_automic(codec);
c5059259
TI
3964 return 0;
3965}
3966
17bbaa6f
TI
3967/* mute internal speaker if HP or docking HP is plugged */
3968static void ad1884a_laptop_automute(struct hda_codec *codec)
3969{
3970 unsigned int present;
3971
d56757ab
TI
3972 present = snd_hda_jack_detect(codec, 0x11);
3973 if (!present)
3974 present = snd_hda_jack_detect(codec, 0x12);
17bbaa6f
TI
3975 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
3976 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
3977 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
3978 present ? 0x00 : 0x02);
3979}
3980
3981/* switch to external mic if plugged */
3982static void ad1884a_laptop_automic(struct hda_codec *codec)
3983{
3984 unsigned int idx;
3985
d56757ab 3986 if (snd_hda_jack_detect(codec, 0x14))
17bbaa6f 3987 idx = 0;
d56757ab 3988 else if (snd_hda_jack_detect(codec, 0x1c))
17bbaa6f
TI
3989 idx = 4;
3990 else
3991 idx = 1;
3992 snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
3993}
3994
3995/* unsolicited event for HP jack sensing */
3996static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
3997 unsigned int res)
3998{
3999 switch (res >> 26) {
4000 case AD1884A_HP_EVENT:
4001 ad1884a_laptop_automute(codec);
4002 break;
4003 case AD1884A_MIC_EVENT:
4004 ad1884a_laptop_automic(codec);
4005 break;
4006 }
4007}
4008
4009/* initialize jack-sensing, too */
4010static int ad1884a_laptop_init(struct hda_codec *codec)
4011{
4012 ad198x_init(codec);
4013 ad1884a_laptop_automute(codec);
4014 ad1884a_laptop_automic(codec);
4015 return 0;
4016}
4017
c5059259
TI
4018/* additional verbs for laptop model */
4019static struct hda_verb ad1884a_laptop_verbs[] = {
4020 /* Port-A (HP) pin - always unmuted */
4021 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4022 /* Port-F (int speaker) mixer - route only from analog mixer */
4023 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4024 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
150fe14c
WF
4025 /* Port-F (int speaker) pin */
4026 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
c5059259 4027 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
150fe14c
WF
4028 /* required for compaq 6530s/6531s speaker output */
4029 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
269ef19c
TI
4030 /* Port-C pin - internal mic-in */
4031 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4032 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4033 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
2ad81ba0
TI
4034 /* Port-D (docking line-out) pin - default unmuted */
4035 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
c5059259
TI
4036 /* analog mix */
4037 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4038 /* unsolicited event for pin-sense */
4039 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
17bbaa6f 4040 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
269ef19c 4041 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
17bbaa6f 4042 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
fe7e5681
TI
4043 /* allow to touch GPIO1 (for mute control) */
4044 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4045 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4046 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
c5059259
TI
4047 { } /* end */
4048};
4049
7315613f
TI
4050static struct hda_verb ad1884a_mobile_verbs[] = {
4051 /* DACs; unmute as default */
4052 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4053 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4054 /* Port-A (HP) mixer - route only from analog mixer */
4055 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4056 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4057 /* Port-A pin */
4058 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4059 /* Port-A (HP) pin - always unmuted */
4060 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4061 /* Port-B (mic jack) pin */
4062 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4063 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4064 /* Port-C (int mic) pin */
4065 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4066 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4067 /* Port-F (int speaker) mixer - route only from analog mixer */
4068 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4069 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4070 /* Port-F pin */
4071 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4072 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4073 /* Analog mixer; mute as default */
4074 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4075 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4076 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4077 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4078 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4079 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4080 /* Analog Mix output amp */
4081 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4082 /* capture sources */
4083 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4084 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4085 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4086 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4087 /* unsolicited event for pin-sense */
4088 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4089 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
099db17e
TI
4090 /* allow to touch GPIO1 (for mute control) */
4091 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4092 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4093 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
7315613f
TI
4094 { } /* end */
4095};
4096
f081374b
TI
4097/*
4098 * Thinkpad X300
4099 * 0x11 - HP
4100 * 0x12 - speaker
4101 * 0x14 - mic-in
4102 * 0x17 - built-in mic
4103 */
4104
4105static struct hda_verb ad1984a_thinkpad_verbs[] = {
4106 /* HP unmute */
4107 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4108 /* analog mix */
4109 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4110 /* turn on EAPD */
4111 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4112 /* unsolicited event for pin-sense */
4113 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4114 /* internal mic - dmic */
4115 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
05808ecc
TI
4116 /* set magic COEFs for dmic */
4117 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4118 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
f081374b
TI
4119 { } /* end */
4120};
4121
4122static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4123 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4124 HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4125 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4126 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4127 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4128 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
f081374b
TI
4129 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
4130 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4131 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4132 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4133 {
4134 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4135 .name = "Capture Source",
4136 .info = ad198x_mux_enum_info,
4137 .get = ad198x_mux_enum_get,
4138 .put = ad198x_mux_enum_put,
4139 },
4140 { } /* end */
4141};
4142
4143static struct hda_input_mux ad1984a_thinkpad_capture_source = {
4144 .num_items = 3,
4145 .items = {
4146 { "Mic", 0x0 },
4147 { "Internal Mic", 0x5 },
4148 { "Mix", 0x3 },
4149 },
4150};
4151
4152/* mute internal speaker if HP is plugged */
4153static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4154{
4155 unsigned int present;
4156
d56757ab 4157 present = snd_hda_jack_detect(codec, 0x11);
f081374b
TI
4158 snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4159 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4160}
4161
4162/* unsolicited event for HP jack sensing */
4163static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4164 unsigned int res)
4165{
4166 if ((res >> 26) != AD1884A_HP_EVENT)
4167 return;
4168 ad1984a_thinkpad_automute(codec);
4169}
4170
4171/* initialize jack-sensing, too */
4172static int ad1984a_thinkpad_init(struct hda_codec *codec)
4173{
4174 ad198x_init(codec);
4175 ad1984a_thinkpad_automute(codec);
4176 return 0;
4177}
4178
a72cb4bc
MB
4179/*
4180 * HP Touchsmart
4181 * port-A (0x11) - front hp-out
4182 * port-B (0x14) - unused
4183 * port-C (0x15) - unused
4184 * port-D (0x12) - rear line out
4185 * port-E (0x1c) - front mic-in
4186 * port-F (0x16) - Internal speakers
4187 * digital-mic (0x17) - Internal mic
4188 */
4189
4190static struct hda_verb ad1984a_touchsmart_verbs[] = {
4191 /* DACs; unmute as default */
4192 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4193 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4194 /* Port-A (HP) mixer - route only from analog mixer */
4195 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4196 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4197 /* Port-A pin */
4198 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4199 /* Port-A (HP) pin - always unmuted */
4200 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4201 /* Port-E (int speaker) mixer - route only from analog mixer */
4202 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4203 /* Port-E pin */
4204 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4205 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4206 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4207 /* Port-F (int speaker) mixer - route only from analog mixer */
4208 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4209 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4210 /* Port-F pin */
4211 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4212 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4213 /* Analog mixer; mute as default */
4214 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4215 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4216 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4217 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4218 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4219 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4220 /* Analog Mix output amp */
4221 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4222 /* capture sources */
4223 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4224 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4225 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4226 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4227 /* unsolicited event for pin-sense */
4228 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4229 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4230 /* allow to touch GPIO1 (for mute control) */
4231 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4232 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4233 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4234 /* internal mic - dmic */
4235 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4236 /* set magic COEFs for dmic */
4237 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4238 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4239 { } /* end */
4240};
4241
4242static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4243 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4244/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4245 {
4246 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5e26dfd0 4247 .subdevice = HDA_SUBDEV_AMP_FLAG,
a72cb4bc
MB
4248 .name = "Master Playback Switch",
4249 .info = snd_hda_mixer_amp_switch_info,
4250 .get = snd_hda_mixer_amp_switch_get,
4251 .put = ad1884a_mobile_master_sw_put,
4252 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4253 },
4254 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4255 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4256 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4257 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4258 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4259 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4260 { } /* end */
4261};
4262
4263/* switch to external mic if plugged */
4264static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4265{
d56757ab 4266 if (snd_hda_jack_detect(codec, 0x1c))
a72cb4bc
MB
4267 snd_hda_codec_write(codec, 0x0c, 0,
4268 AC_VERB_SET_CONNECT_SEL, 0x4);
d56757ab 4269 else
a72cb4bc
MB
4270 snd_hda_codec_write(codec, 0x0c, 0,
4271 AC_VERB_SET_CONNECT_SEL, 0x5);
a72cb4bc
MB
4272}
4273
4274
4275/* unsolicited event for HP jack sensing */
4276static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4277 unsigned int res)
4278{
4279 switch (res >> 26) {
4280 case AD1884A_HP_EVENT:
4281 ad1884a_hp_automute(codec);
4282 break;
4283 case AD1884A_MIC_EVENT:
4284 ad1984a_touchsmart_automic(codec);
4285 break;
4286 }
4287}
4288
4289/* initialize jack-sensing, too */
4290static int ad1984a_touchsmart_init(struct hda_codec *codec)
4291{
4292 ad198x_init(codec);
4293 ad1884a_hp_automute(codec);
4294 ad1984a_touchsmart_automic(codec);
4295 return 0;
4296}
4297
4298
c5059259
TI
4299/*
4300 */
4301
4302enum {
4303 AD1884A_DESKTOP,
4304 AD1884A_LAPTOP,
b40b04ad 4305 AD1884A_MOBILE,
f081374b 4306 AD1884A_THINKPAD,
a72cb4bc 4307 AD1984A_TOUCHSMART,
c5059259
TI
4308 AD1884A_MODELS
4309};
4310
4311static const char *ad1884a_models[AD1884A_MODELS] = {
4312 [AD1884A_DESKTOP] = "desktop",
4313 [AD1884A_LAPTOP] = "laptop",
b40b04ad 4314 [AD1884A_MOBILE] = "mobile",
f081374b 4315 [AD1884A_THINKPAD] = "thinkpad",
a72cb4bc 4316 [AD1984A_TOUCHSMART] = "touchsmart",
b40b04ad
TI
4317};
4318
4319static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4320 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
d5337deb 4321 SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
5695ff44 4322 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
c2312756 4323 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
ff848471 4324 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
873dc78a
TI
4325 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4326 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
286f5875 4327 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
f081374b 4328 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
a72cb4bc 4329 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
b40b04ad 4330 {}
c5059259
TI
4331};
4332
4333static int patch_ad1884a(struct hda_codec *codec)
4334{
4335 struct ad198x_spec *spec;
c5a4bcd0 4336 int err, board_config;
c5059259
TI
4337
4338 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4339 if (spec == NULL)
4340 return -ENOMEM;
4341
c5059259
TI
4342 codec->spec = spec;
4343
c5a4bcd0
TI
4344 err = snd_hda_attach_beep_device(codec, 0x10);
4345 if (err < 0) {
4346 ad198x_free(codec);
4347 return err;
4348 }
4349 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4350
c5059259
TI
4351 spec->multiout.max_channels = 2;
4352 spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4353 spec->multiout.dac_nids = ad1884a_dac_nids;
4354 spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4355 spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4356 spec->adc_nids = ad1884a_adc_nids;
4357 spec->capsrc_nids = ad1884a_capsrc_nids;
4358 spec->input_mux = &ad1884a_capture_source;
4359 spec->num_mixers = 1;
4360 spec->mixers[0] = ad1884a_base_mixers;
4361 spec->num_init_verbs = 1;
4362 spec->init_verbs[0] = ad1884a_init_verbs;
4363 spec->spdif_route = 0;
4364#ifdef CONFIG_SND_HDA_POWER_SAVE
4365 spec->loopback.amplist = ad1884a_loopbacks;
4366#endif
4367 codec->patch_ops = ad198x_patch_ops;
4368
4369 /* override some parameters */
4370 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
b40b04ad
TI
4371 ad1884a_models,
4372 ad1884a_cfg_tbl);
c5059259
TI
4373 switch (board_config) {
4374 case AD1884A_LAPTOP:
4375 spec->mixers[0] = ad1884a_laptop_mixers;
4376 spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4377 spec->multiout.dig_out_nid = 0;
17bbaa6f
TI
4378 codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4379 codec->patch_ops.init = ad1884a_laptop_init;
4dc1f87f
TI
4380 /* set the upper-limit for mixer amp to 0dB for avoiding the
4381 * possible damage by overloading
4382 */
4383 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4384 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4385 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4386 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4387 (1 << AC_AMPCAP_MUTE_SHIFT));
c5059259 4388 break;
b40b04ad
TI
4389 case AD1884A_MOBILE:
4390 spec->mixers[0] = ad1884a_mobile_mixers;
7315613f 4391 spec->init_verbs[0] = ad1884a_mobile_verbs;
b40b04ad 4392 spec->multiout.dig_out_nid = 0;
b40b04ad
TI
4393 codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4394 codec->patch_ops.init = ad1884a_hp_init;
13c989be
TI
4395 /* set the upper-limit for mixer amp to 0dB for avoiding the
4396 * possible damage by overloading
4397 */
4398 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4399 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4400 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4401 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4402 (1 << AC_AMPCAP_MUTE_SHIFT));
b40b04ad 4403 break;
f081374b
TI
4404 case AD1884A_THINKPAD:
4405 spec->mixers[0] = ad1984a_thinkpad_mixers;
4406 spec->init_verbs[spec->num_init_verbs++] =
4407 ad1984a_thinkpad_verbs;
4408 spec->multiout.dig_out_nid = 0;
4409 spec->input_mux = &ad1984a_thinkpad_capture_source;
4410 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4411 codec->patch_ops.init = ad1984a_thinkpad_init;
4412 break;
a72cb4bc
MB
4413 case AD1984A_TOUCHSMART:
4414 spec->mixers[0] = ad1984a_touchsmart_mixers;
4415 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4416 spec->multiout.dig_out_nid = 0;
4417 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4418 codec->patch_ops.init = ad1984a_touchsmart_init;
4419 /* set the upper-limit for mixer amp to 0dB for avoiding the
4420 * possible damage by overloading
4421 */
4422 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4423 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4424 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4425 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4426 (1 << AC_AMPCAP_MUTE_SHIFT));
4427 break;
c5059259
TI
4428 }
4429
729d55ba 4430 codec->no_trigger_sense = 1;
0e7adbe2 4431 codec->no_sticky_stream = 1;
729d55ba 4432
c5059259
TI
4433 return 0;
4434}
4435
4436
0ac8551e 4437/*
9e44c6e4 4438 * AD1882 / AD1882A
0ac8551e
TI
4439 *
4440 * port-A - front hp-out
4441 * port-B - front mic-in
4442 * port-C - rear line-in, shared surr-out (3stack)
4443 * port-D - rear line-out
4444 * port-E - rear mic-in, shared clfe-out (3stack)
4445 * port-F - rear surr-out (6stack)
4446 * port-G - rear clfe-out (6stack)
4447 */
4448
4449static hda_nid_t ad1882_dac_nids[3] = {
4450 0x04, 0x03, 0x05
4451};
4452
4453static hda_nid_t ad1882_adc_nids[2] = {
4454 0x08, 0x09,
4455};
4456
4457static hda_nid_t ad1882_capsrc_nids[2] = {
4458 0x0c, 0x0d,
4459};
4460
4461#define AD1882_SPDIF_OUT 0x02
4462
4463/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4464static struct hda_input_mux ad1882_capture_source = {
4465 .num_items = 5,
4466 .items = {
4467 { "Front Mic", 0x1 },
4468 { "Mic", 0x4 },
4469 { "Line", 0x2 },
4470 { "CD", 0x3 },
4471 { "Mix", 0x7 },
4472 },
4473};
4474
9e44c6e4
TI
4475/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4476static struct hda_input_mux ad1882a_capture_source = {
4477 .num_items = 5,
4478 .items = {
4479 { "Front Mic", 0x1 },
4480 { "Mic", 0x4},
4481 { "Line", 0x2 },
4482 { "Digital Mic", 0x06 },
4483 { "Mix", 0x7 },
4484 },
4485};
4486
0ac8551e
TI
4487static struct snd_kcontrol_new ad1882_base_mixers[] = {
4488 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4489 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4490 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4491 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4492 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4493 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4494 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4495 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
9e44c6e4 4496
0ac8551e
TI
4497 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
4498 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
4499 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT),
4500 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4501 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4502 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4503 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4504 {
4505 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4506 /* The multiple "Capture Source" controls confuse alsamixer
4507 * So call somewhat different..
0ac8551e
TI
4508 */
4509 /* .name = "Capture Source", */
4510 .name = "Input Source",
4511 .count = 2,
4512 .info = ad198x_mux_enum_info,
4513 .get = ad198x_mux_enum_get,
4514 .put = ad198x_mux_enum_put,
4515 },
4516 /* SPDIF controls */
4517 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4518 {
4519 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4520 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4521 /* identical with ad1983 */
4522 .info = ad1983_spdif_route_info,
4523 .get = ad1983_spdif_route_get,
4524 .put = ad1983_spdif_route_put,
4525 },
4526 { } /* end */
4527};
4528
9e44c6e4
TI
4529static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4530 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4531 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4532 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4533 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4534 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4535 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4536 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4537 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
9e44c6e4
TI
4538 { } /* end */
4539};
4540
4541static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4542 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4543 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4544 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4545 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4546 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4547 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4548 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4549 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
9e44c6e4
TI
4550 HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
4551 { } /* end */
4552};
4553
0ac8551e
TI
4554static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4555 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4556 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4557 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4558 {
4559 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4560 .name = "Channel Mode",
4561 .info = ad198x_ch_mode_info,
4562 .get = ad198x_ch_mode_get,
4563 .put = ad198x_ch_mode_put,
4564 },
4565 { } /* end */
4566};
4567
4568static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4569 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4570 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4571 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4572 { } /* end */
4573};
4574
4575static struct hda_verb ad1882_ch2_init[] = {
4576 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4577 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4578 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4579 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4580 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4581 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4582 { } /* end */
4583};
4584
4585static struct hda_verb ad1882_ch4_init[] = {
4586 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4587 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4588 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4589 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4590 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4591 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4592 { } /* end */
4593};
4594
4595static struct hda_verb ad1882_ch6_init[] = {
4596 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4597 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4598 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4599 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4600 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4601 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4602 { } /* end */
4603};
4604
4605static struct hda_channel_mode ad1882_modes[3] = {
4606 { 2, ad1882_ch2_init },
4607 { 4, ad1882_ch4_init },
4608 { 6, ad1882_ch6_init },
4609};
4610
4611/*
4612 * initialization verbs
4613 */
4614static struct hda_verb ad1882_init_verbs[] = {
4615 /* DACs; mute as default */
4616 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4617 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4618 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4619 /* Port-A (HP) mixer */
4620 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4621 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4622 /* Port-A pin */
4623 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4624 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4625 /* HP selector - select DAC2 */
4626 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
4627 /* Port-D (Line-out) mixer */
4628 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4629 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4630 /* Port-D pin */
4631 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4632 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4633 /* Mono-out mixer */
4634 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4635 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4636 /* Mono-out pin */
4637 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4638 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4639 /* Port-B (front mic) pin */
4640 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4641 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4642 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4643 /* Port-C (line-in) pin */
4644 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4645 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4646 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4647 /* Port-C mixer - mute as input */
4648 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4649 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4650 /* Port-E (mic-in) pin */
4651 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4652 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4653 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
4654 /* Port-E mixer - mute as input */
4655 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4656 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4657 /* Port-F (surround) */
4658 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4659 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4660 /* Port-G (CLFE) */
4661 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4662 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4663 /* Analog mixer; mute as default */
4664 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
4665 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4666 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4667 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4668 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4669 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4670 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4671 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
4672 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
4673 /* Analog Mix output amp */
4674 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
4675 /* SPDIF output selector */
4676 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4677 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
4678 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4679 { } /* end */
4680};
4681
cb53c626
TI
4682#ifdef CONFIG_SND_HDA_POWER_SAVE
4683static struct hda_amp_list ad1882_loopbacks[] = {
4684 { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4685 { 0x20, HDA_INPUT, 1 }, /* Mic */
4686 { 0x20, HDA_INPUT, 4 }, /* Line */
4687 { 0x20, HDA_INPUT, 6 }, /* CD */
4688 { } /* end */
4689};
4690#endif
4691
0ac8551e
TI
4692/* models */
4693enum {
4694 AD1882_3STACK,
4695 AD1882_6STACK,
4696 AD1882_MODELS
4697};
4698
4699static const char *ad1882_models[AD1986A_MODELS] = {
4700 [AD1882_3STACK] = "3stack",
4701 [AD1882_6STACK] = "6stack",
4702};
4703
4704
4705static int patch_ad1882(struct hda_codec *codec)
4706{
4707 struct ad198x_spec *spec;
c5a4bcd0 4708 int err, board_config;
0ac8551e
TI
4709
4710 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4711 if (spec == NULL)
4712 return -ENOMEM;
4713
0ac8551e
TI
4714 codec->spec = spec;
4715
c5a4bcd0
TI
4716 err = snd_hda_attach_beep_device(codec, 0x10);
4717 if (err < 0) {
4718 ad198x_free(codec);
4719 return err;
4720 }
4721 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4722
0ac8551e
TI
4723 spec->multiout.max_channels = 6;
4724 spec->multiout.num_dacs = 3;
4725 spec->multiout.dac_nids = ad1882_dac_nids;
4726 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
4727 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
4728 spec->adc_nids = ad1882_adc_nids;
4729 spec->capsrc_nids = ad1882_capsrc_nids;
c247ed6f 4730 if (codec->vendor_id == 0x11d41882)
9e44c6e4
TI
4731 spec->input_mux = &ad1882_capture_source;
4732 else
4733 spec->input_mux = &ad1882a_capture_source;
4734 spec->num_mixers = 2;
0ac8551e 4735 spec->mixers[0] = ad1882_base_mixers;
c247ed6f 4736 if (codec->vendor_id == 0x11d41882)
9e44c6e4
TI
4737 spec->mixers[1] = ad1882_loopback_mixers;
4738 else
4739 spec->mixers[1] = ad1882a_loopback_mixers;
0ac8551e
TI
4740 spec->num_init_verbs = 1;
4741 spec->init_verbs[0] = ad1882_init_verbs;
4742 spec->spdif_route = 0;
cb53c626
TI
4743#ifdef CONFIG_SND_HDA_POWER_SAVE
4744 spec->loopback.amplist = ad1882_loopbacks;
4745#endif
2134ea4f 4746 spec->vmaster_nid = 0x04;
0ac8551e
TI
4747
4748 codec->patch_ops = ad198x_patch_ops;
4749
4750 /* override some parameters */
4751 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4752 ad1882_models, NULL);
4753 switch (board_config) {
4754 default:
4755 case AD1882_3STACK:
9e44c6e4
TI
4756 spec->num_mixers = 3;
4757 spec->mixers[2] = ad1882_3stack_mixers;
0ac8551e
TI
4758 spec->channel_mode = ad1882_modes;
4759 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
4760 spec->need_dac_fix = 1;
4761 spec->multiout.max_channels = 2;
4762 spec->multiout.num_dacs = 1;
4763 break;
4764 case AD1882_6STACK:
9e44c6e4
TI
4765 spec->num_mixers = 3;
4766 spec->mixers[2] = ad1882_6stack_mixers;
0ac8551e
TI
4767 break;
4768 }
729d55ba
TI
4769
4770 codec->no_trigger_sense = 1;
0e7adbe2 4771 codec->no_sticky_stream = 1;
729d55ba 4772
0ac8551e
TI
4773 return 0;
4774}
4775
4776
1da177e4
LT
4777/*
4778 * patch entries
4779 */
1289e9e8 4780static struct hda_codec_preset snd_hda_preset_analog[] = {
c5059259 4781 { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
0ac8551e 4782 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
c5059259 4783 { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
2bac647c 4784 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
c5059259
TI
4785 { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
4786 { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
4a3fdf3d
TI
4787 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
4788 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
2bac647c 4789 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
1da177e4 4790 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
fd66e0d0 4791 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
71b2ccc3 4792 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
9e44c6e4 4793 { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
3adb8abc
TI
4794 { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
4795 { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
1da177e4
LT
4796 {} /* terminator */
4797};
1289e9e8
TI
4798
4799MODULE_ALIAS("snd-hda-codec-id:11d4*");
4800
4801MODULE_LICENSE("GPL");
4802MODULE_DESCRIPTION("Analog Devices HD-audio codec");
4803
4804static struct hda_codec_preset_list analog_list = {
4805 .preset = snd_hda_preset_analog,
4806 .owner = THIS_MODULE,
4807};
4808
4809static int __init patch_analog_init(void)
4810{
4811 return snd_hda_add_codec_preset(&analog_list);
4812}
4813
4814static void __exit patch_analog_exit(void)
4815{
4816 snd_hda_delete_codec_preset(&analog_list);
4817}
4818
4819module_init(patch_analog_init)
4820module_exit(patch_analog_exit)