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