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