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