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