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