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