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