aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-12-21 09:17:06 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-12 02:45:00 -0500
commit78bb3cb0e24066f78168968de5f8e19615f1854e (patch)
treeb6eb8938ce7b8206b06426c2c34d312931862d48 /sound/pci/hda/patch_analog.c
parentbf92d1d5032d82e507cb328810cd7e1a046c1d0f (diff)
ALSA: hda - Add generic parser support to Analog Device codec driver
This patch adds the support for the generic auto-parser to AD codec driver. For AD1988, the old code is replaced simply with the new generic parser. For other codecs, new model "auto" is added and directed to use the generic parser. No fixup codes have been implemented yet as of now. Eventually we'd replace each static quirk with the generic parser + fixup. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c915
1 files changed, 291 insertions, 624 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 308a5b9e6b9d..02fe0d1da6e0 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -31,11 +31,15 @@
31#include "hda_auto_parser.h" 31#include "hda_auto_parser.h"
32#include "hda_beep.h" 32#include "hda_beep.h"
33#include "hda_jack.h" 33#include "hda_jack.h"
34#include "hda_generic.h"
34 35
35struct ad198x_spec { 36struct ad198x_spec {
37 struct hda_gen_spec gen;
38
36 const struct snd_kcontrol_new *mixers[6]; 39 const struct snd_kcontrol_new *mixers[6];
37 int num_mixers; 40 int num_mixers;
38 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ 41 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
42 hda_nid_t beep_dev_nid;
39 const struct hda_verb *init_verbs[6]; /* initialization verbs 43 const struct hda_verb *init_verbs[6]; /* initialization verbs
40 * don't forget NULL termination! 44 * don't forget NULL termination!
41 */ 45 */
@@ -49,11 +53,6 @@ struct ad198x_spec {
49 unsigned int cur_eapd; 53 unsigned int cur_eapd;
50 unsigned int need_dac_fix; 54 unsigned int need_dac_fix;
51 55
52 const hda_nid_t *alt_dac_nid;
53 const struct hda_pcm_stream *stream_analog_alt_playback;
54 int independent_hp;
55 int num_active_streams;
56
57 /* capture */ 56 /* capture */
58 unsigned int num_adc_nids; 57 unsigned int num_adc_nids;
59 const hda_nid_t *adc_nids; 58 const hda_nid_t *adc_nids;
@@ -73,15 +72,8 @@ struct ad198x_spec {
73 72
74 unsigned int spdif_route; 73 unsigned int spdif_route;
75 74
76 /* dynamic controls, init_verbs and input_mux */
77 struct auto_pin_cfg autocfg;
78 struct snd_array kctls;
79 struct hda_input_mux private_imux;
80 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
81
82 unsigned int jack_present: 1; 75 unsigned int jack_present: 1;
83 unsigned int inv_jack_detect: 1;/* inverted jack-detection */ 76 unsigned int inv_jack_detect: 1;/* inverted jack-detection */
84 unsigned int inv_eapd: 1; /* inverted EAPD implementation */
85 unsigned int analog_beep: 1; /* analog beep input present */ 77 unsigned int analog_beep: 1; /* analog beep input present */
86 unsigned int avoid_init_slave_vol:1; 78 unsigned int avoid_init_slave_vol:1;
87 79
@@ -150,8 +142,6 @@ static const char * const ad1988_6stack_fp_slave_pfxs[] = {
150 NULL 142 NULL
151}; 143};
152 144
153static void ad198x_free_kctls(struct hda_codec *codec);
154
155#ifdef CONFIG_SND_HDA_INPUT_BEEP 145#ifdef CONFIG_SND_HDA_INPUT_BEEP
156/* additional beep mixers; the actual parameters are overwritten at build */ 146/* additional beep mixers; the actual parameters are overwritten at build */
157static const struct snd_kcontrol_new ad_beep_mixer[] = { 147static const struct snd_kcontrol_new ad_beep_mixer[] = {
@@ -172,6 +162,33 @@ static const struct snd_kcontrol_new ad_beep2_mixer[] = {
172#define set_beep_amp(spec, nid, idx, dir) /* NOP */ 162#define set_beep_amp(spec, nid, idx, dir) /* NOP */
173#endif 163#endif
174 164
165#ifdef CONFIG_SND_HDA_INPUT_BEEP
166static int create_beep_ctls(struct hda_codec *codec)
167{
168 struct ad198x_spec *spec = codec->spec;
169 const struct snd_kcontrol_new *knew;
170
171 if (!spec->beep_amp)
172 return 0;
173
174 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
175 for ( ; knew->name; knew++) {
176 int err;
177 struct snd_kcontrol *kctl;
178 kctl = snd_ctl_new1(knew, codec);
179 if (!kctl)
180 return -ENOMEM;
181 kctl->private_value = spec->beep_amp;
182 err = snd_hda_ctl_add(codec, 0, kctl);
183 if (err < 0)
184 return err;
185 }
186 return 0;
187}
188#else
189#define create_beep_ctls(codec) 0
190#endif
191
175static int ad198x_build_controls(struct hda_codec *codec) 192static int ad198x_build_controls(struct hda_codec *codec)
176{ 193{
177 struct ad198x_spec *spec = codec->spec; 194 struct ad198x_spec *spec = codec->spec;
@@ -203,22 +220,9 @@ static int ad198x_build_controls(struct hda_codec *codec)
203 } 220 }
204 221
205 /* create beep controls if needed */ 222 /* create beep controls if needed */
206#ifdef CONFIG_SND_HDA_INPUT_BEEP 223 err = create_beep_ctls(codec);
207 if (spec->beep_amp) { 224 if (err < 0)
208 const struct snd_kcontrol_new *knew; 225 return err;
209 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
210 for ( ; knew->name; knew++) {
211 struct snd_kcontrol *kctl;
212 kctl = snd_ctl_new1(knew, codec);
213 if (!kctl)
214 return -ENOMEM;
215 kctl->private_value = spec->beep_amp;
216 err = snd_hda_ctl_add(codec, 0, kctl);
217 if (err < 0)
218 return err;
219 }
220 }
221#endif
222 226
223 /* if we have no master control, let's create it */ 227 /* if we have no master control, let's create it */
224 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 228 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
@@ -244,8 +248,6 @@ static int ad198x_build_controls(struct hda_codec *codec)
244 return err; 248 return err;
245 } 249 }
246 250
247 ad198x_free_kctls(codec); /* no longer needed */
248
249 /* assign Capture Source enums to NID */ 251 /* assign Capture Source enums to NID */
250 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); 252 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
251 if (!kctl) 253 if (!kctl)
@@ -277,72 +279,6 @@ static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
277} 279}
278#endif 280#endif
279 281
280static void activate_ctl(struct hda_codec *codec, const char *name, int active)
281{
282 struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name);
283 if (ctl) {
284 ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
285 ctl->vd[0].access |= active ? 0 :
286 SNDRV_CTL_ELEM_ACCESS_INACTIVE;
287 ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;
288 ctl->vd[0].access |= active ?
289 SNDRV_CTL_ELEM_ACCESS_WRITE : 0;
290 snd_ctl_notify(codec->bus->card,
291 SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
292 }
293}
294
295static void set_stream_active(struct hda_codec *codec, bool active)
296{
297 struct ad198x_spec *spec = codec->spec;
298 if (active)
299 spec->num_active_streams++;
300 else
301 spec->num_active_streams--;
302 activate_ctl(codec, "Independent HP", spec->num_active_streams == 0);
303}
304
305static int ad1988_independent_hp_info(struct snd_kcontrol *kcontrol,
306 struct snd_ctl_elem_info *uinfo)
307{
308 static const char * const texts[] = { "OFF", "ON", NULL};
309 int index;
310 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
311 uinfo->count = 1;
312 uinfo->value.enumerated.items = 2;
313 index = uinfo->value.enumerated.item;
314 if (index >= 2)
315 index = 1;
316 strcpy(uinfo->value.enumerated.name, texts[index]);
317 return 0;
318}
319
320static int ad1988_independent_hp_get(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
324 struct ad198x_spec *spec = codec->spec;
325 ucontrol->value.enumerated.item[0] = spec->independent_hp;
326 return 0;
327}
328
329static int ad1988_independent_hp_put(struct snd_kcontrol *kcontrol,
330 struct snd_ctl_elem_value *ucontrol)
331{
332 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
333 struct ad198x_spec *spec = codec->spec;
334 unsigned int select = ucontrol->value.enumerated.item[0];
335 if (spec->independent_hp != select) {
336 spec->independent_hp = select;
337 if (spec->independent_hp)
338 spec->multiout.hp_nid = 0;
339 else
340 spec->multiout.hp_nid = spec->alt_dac_nid[0];
341 return 1;
342 }
343 return 0;
344}
345
346/* 282/*
347 * Analog playback callbacks 283 * Analog playback callbacks
348 */ 284 */
@@ -351,15 +287,8 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
351 struct snd_pcm_substream *substream) 287 struct snd_pcm_substream *substream)
352{ 288{
353 struct ad198x_spec *spec = codec->spec; 289 struct ad198x_spec *spec = codec->spec;
354 int err; 290 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
355 set_stream_active(codec, true);
356 err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
357 hinfo); 291 hinfo);
358 if (err < 0) {
359 set_stream_active(codec, false);
360 return err;
361 }
362 return 0;
363} 292}
364 293
365static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 294static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -381,43 +310,6 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
381 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 310 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
382} 311}
383 312
384static int ad198x_playback_pcm_close(struct hda_pcm_stream *hinfo,
385 struct hda_codec *codec,
386 struct snd_pcm_substream *substream)
387{
388 set_stream_active(codec, false);
389 return 0;
390}
391
392static int ad1988_alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
393 struct hda_codec *codec,
394 struct snd_pcm_substream *substream)
395{
396 struct ad198x_spec *spec = codec->spec;
397 if (!spec->independent_hp)
398 return -EBUSY;
399 set_stream_active(codec, true);
400 return 0;
401}
402
403static int ad1988_alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
404 struct hda_codec *codec,
405 struct snd_pcm_substream *substream)
406{
407 set_stream_active(codec, false);
408 return 0;
409}
410
411static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
412 .substreams = 1,
413 .channels_min = 2,
414 .channels_max = 2,
415 .ops = {
416 .open = ad1988_alt_playback_pcm_open,
417 .close = ad1988_alt_playback_pcm_close
418 },
419};
420
421/* 313/*
422 * Digital out 314 * Digital out
423 */ 315 */
@@ -491,7 +383,6 @@ static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
491 .open = ad198x_playback_pcm_open, 383 .open = ad198x_playback_pcm_open,
492 .prepare = ad198x_playback_pcm_prepare, 384 .prepare = ad198x_playback_pcm_prepare,
493 .cleanup = ad198x_playback_pcm_cleanup, 385 .cleanup = ad198x_playback_pcm_cleanup,
494 .close = ad198x_playback_pcm_close
495 }, 386 },
496}; 387};
497 388
@@ -556,43 +447,18 @@ static int ad198x_build_pcms(struct hda_codec *codec)
556 } 447 }
557 } 448 }
558 449
559 if (spec->alt_dac_nid && spec->stream_analog_alt_playback) {
560 codec->num_pcms++;
561 info = spec->pcm_rec + 2;
562 info->name = "AD198x Headphone";
563 info->pcm_type = HDA_PCM_TYPE_AUDIO;
564 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
565 *spec->stream_analog_alt_playback;
566 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
567 spec->alt_dac_nid[0];
568 }
569
570 return 0; 450 return 0;
571} 451}
572 452
573static void ad198x_free_kctls(struct hda_codec *codec)
574{
575 struct ad198x_spec *spec = codec->spec;
576
577 if (spec->kctls.list) {
578 struct snd_kcontrol_new *kctl = spec->kctls.list;
579 int i;
580 for (i = 0; i < spec->kctls.used; i++)
581 kfree(kctl[i].name);
582 }
583 snd_array_free(&spec->kctls);
584}
585
586static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, 453static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
587 hda_nid_t hp) 454 hda_nid_t hp)
588{ 455{
589 struct ad198x_spec *spec = codec->spec;
590 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD) 456 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
591 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, 457 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
592 !spec->inv_eapd ? 0x00 : 0x02); 458 !codec->inv_eapd ? 0x00 : 0x02);
593 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD) 459 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
594 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, 460 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
595 !spec->inv_eapd ? 0x00 : 0x02); 461 !codec->inv_eapd ? 0x00 : 0x02);
596} 462}
597 463
598static void ad198x_power_eapd(struct hda_codec *codec) 464static void ad198x_power_eapd(struct hda_codec *codec)
@@ -636,7 +502,7 @@ static void ad198x_free(struct hda_codec *codec)
636 if (!spec) 502 if (!spec)
637 return; 503 return;
638 504
639 ad198x_free_kctls(codec); 505 snd_hda_gen_spec_free(&spec->gen);
640 kfree(spec); 506 kfree(spec);
641 snd_hda_detach_beep_device(codec); 507 snd_hda_detach_beep_device(codec);
642} 508}
@@ -673,7 +539,7 @@ static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
673{ 539{
674 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 540 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
675 struct ad198x_spec *spec = codec->spec; 541 struct ad198x_spec *spec = codec->spec;
676 if (spec->inv_eapd) 542 if (codec->inv_eapd)
677 ucontrol->value.integer.value[0] = ! spec->cur_eapd; 543 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
678 else 544 else
679 ucontrol->value.integer.value[0] = spec->cur_eapd; 545 ucontrol->value.integer.value[0] = spec->cur_eapd;
@@ -688,7 +554,7 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
688 hda_nid_t nid = kcontrol->private_value & 0xff; 554 hda_nid_t nid = kcontrol->private_value & 0xff;
689 unsigned int eapd; 555 unsigned int eapd;
690 eapd = !!ucontrol->value.integer.value[0]; 556 eapd = !!ucontrol->value.integer.value[0];
691 if (spec->inv_eapd) 557 if (codec->inv_eapd)
692 eapd = !eapd; 558 eapd = !eapd;
693 if (eapd == spec->cur_eapd) 559 if (eapd == spec->cur_eapd)
694 return 0; 560 return 0;
@@ -708,6 +574,66 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
708 574
709 575
710/* 576/*
577 * Automatic parse of I/O pins from the BIOS configuration
578 */
579
580static int ad198x_auto_build_controls(struct hda_codec *codec)
581{
582 int err;
583
584 err = snd_hda_gen_build_controls(codec);
585 if (err < 0)
586 return err;
587 err = create_beep_ctls(codec);
588 if (err < 0)
589 return err;
590 return 0;
591}
592
593static const struct hda_codec_ops ad198x_auto_patch_ops = {
594 .build_controls = ad198x_auto_build_controls,
595 .build_pcms = snd_hda_gen_build_pcms,
596 .init = snd_hda_gen_init,
597 .free = ad198x_free,
598#ifdef CONFIG_PM
599 .check_power_status = snd_hda_gen_check_power_status,
600 .suspend = ad198x_suspend,
601#endif
602 .reboot_notify = ad198x_shutup,
603};
604
605
606static int ad198x_parse_auto_config(struct hda_codec *codec)
607{
608 struct ad198x_spec *spec = codec->spec;
609 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
610 int err;
611
612 codec->spdif_status_reset = 1;
613 codec->no_trigger_sense = 1;
614 codec->no_sticky_stream = 1;
615
616 spec->gen.indep_hp = 1;
617
618 err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
619 if (err < 0)
620 return err;
621 err = snd_hda_gen_parse_auto_config(codec, cfg);
622 if (err < 0)
623 return err;
624
625 if (spec->beep_dev_nid) {
626 err = snd_hda_attach_beep_device(codec, spec->beep_dev_nid);
627 if (err < 0)
628 return err;
629 }
630
631 codec->patch_ops = ad198x_auto_patch_ops;
632
633 return 0;
634}
635
636/*
711 * AD1986A specific 637 * AD1986A specific
712 */ 638 */
713 639
@@ -1168,6 +1094,7 @@ static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1168 1094
1169/* models */ 1095/* models */
1170enum { 1096enum {
1097 AD1986A_AUTO,
1171 AD1986A_6STACK, 1098 AD1986A_6STACK,
1172 AD1986A_3STACK, 1099 AD1986A_3STACK,
1173 AD1986A_LAPTOP, 1100 AD1986A_LAPTOP,
@@ -1180,6 +1107,7 @@ enum {
1180}; 1107};
1181 1108
1182static const char * const ad1986a_models[AD1986A_MODELS] = { 1109static const char * const ad1986a_models[AD1986A_MODELS] = {
1110 [AD1986A_AUTO] = "auto",
1183 [AD1986A_6STACK] = "6stack", 1111 [AD1986A_6STACK] = "6stack",
1184 [AD1986A_3STACK] = "3stack", 1112 [AD1986A_3STACK] = "3stack",
1185 [AD1986A_LAPTOP] = "laptop", 1113 [AD1986A_LAPTOP] = "laptop",
@@ -1246,10 +1174,33 @@ static int alloc_ad_spec(struct hda_codec *codec)
1246 if (!spec) 1174 if (!spec)
1247 return -ENOMEM; 1175 return -ENOMEM;
1248 codec->spec = spec; 1176 codec->spec = spec;
1249 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); 1177 snd_hda_gen_spec_init(&spec->gen);
1250 return 0; 1178 return 0;
1251} 1179}
1252 1180
1181/*
1182 */
1183static int ad1986a_parse_auto_config(struct hda_codec *codec)
1184{
1185 struct ad198x_spec *spec = codec->spec;
1186
1187 /* AD1986A has the inverted EAPD implementation */
1188 codec->inv_eapd = 1;
1189
1190 spec->beep_dev_nid = 0x19;
1191 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1192
1193 /* AD1986A has a hardware problem that it can't share a stream
1194 * with multiple output pins. The copy of front to surrounds
1195 * causes noisy or silent outputs at a certain timing, e.g.
1196 * changing the volume.
1197 * So, let's disable the shared stream.
1198 */
1199 spec->gen.multiout.no_share_stream = 1;
1200
1201 return ad198x_parse_auto_config(codec);
1202}
1203
1253static int patch_ad1986a(struct hda_codec *codec) 1204static int patch_ad1986a(struct hda_codec *codec)
1254{ 1205{
1255 struct ad198x_spec *spec; 1206 struct ad198x_spec *spec;
@@ -1260,6 +1211,18 @@ static int patch_ad1986a(struct hda_codec *codec)
1260 return err; 1211 return err;
1261 spec = codec->spec; 1212 spec = codec->spec;
1262 1213
1214 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1215 ad1986a_models,
1216 ad1986a_cfg_tbl);
1217 if (board_config == AD1986A_AUTO) {
1218 err = ad1986a_parse_auto_config(codec);
1219 if (err < 0) {
1220 ad198x_free(codec);
1221 return err;
1222 }
1223 return 0;
1224 }
1225
1263 err = snd_hda_attach_beep_device(codec, 0x19); 1226 err = snd_hda_attach_beep_device(codec, 0x19);
1264 if (err < 0) { 1227 if (err < 0) {
1265 ad198x_free(codec); 1228 ad198x_free(codec);
@@ -1283,14 +1246,11 @@ static int patch_ad1986a(struct hda_codec *codec)
1283 spec->loopback.amplist = ad1986a_loopbacks; 1246 spec->loopback.amplist = ad1986a_loopbacks;
1284#endif 1247#endif
1285 spec->vmaster_nid = 0x1b; 1248 spec->vmaster_nid = 0x1b;
1286 spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */ 1249 codec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1287 1250
1288 codec->patch_ops = ad198x_patch_ops; 1251 codec->patch_ops = ad198x_patch_ops;
1289 1252
1290 /* override some parameters */ 1253 /* override some parameters */
1291 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1292 ad1986a_models,
1293 ad1986a_cfg_tbl);
1294 switch (board_config) { 1254 switch (board_config) {
1295 case AD1986A_3STACK: 1255 case AD1986A_3STACK:
1296 spec->num_mixers = 2; 1256 spec->num_mixers = 2;
@@ -1546,9 +1506,31 @@ static const struct hda_amp_list ad1983_loopbacks[] = {
1546}; 1506};
1547#endif 1507#endif
1548 1508
1509/* models */
1510enum {
1511 AD1983_AUTO,
1512 AD1983_BASIC,
1513 AD1983_MODELS
1514};
1515
1516static const char * const ad1983_models[AD1983_MODELS] = {
1517 [AD1983_AUTO] = "auto",
1518 [AD1983_BASIC] = "basic",
1519};
1520
1521static int ad1983_parse_auto_config(struct hda_codec *codec)
1522{
1523 struct ad198x_spec *spec = codec->spec;
1524
1525 spec->beep_dev_nid = 0x10;
1526 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1527 return ad198x_parse_auto_config(codec);
1528}
1529
1549static int patch_ad1983(struct hda_codec *codec) 1530static int patch_ad1983(struct hda_codec *codec)
1550{ 1531{
1551 struct ad198x_spec *spec; 1532 struct ad198x_spec *spec;
1533 int board_config;
1552 int err; 1534 int err;
1553 1535
1554 err = alloc_ad_spec(codec); 1536 err = alloc_ad_spec(codec);
@@ -1556,6 +1538,17 @@ static int patch_ad1983(struct hda_codec *codec)
1556 return err; 1538 return err;
1557 spec = codec->spec; 1539 spec = codec->spec;
1558 1540
1541 board_config = snd_hda_check_board_config(codec, AD1983_MODELS,
1542 ad1983_models, NULL);
1543 if (board_config == AD1983_AUTO) {
1544 err = ad1983_parse_auto_config(codec);
1545 if (err < 0) {
1546 ad198x_free(codec);
1547 return err;
1548 }
1549 return 0;
1550 }
1551
1559 err = snd_hda_attach_beep_device(codec, 0x10); 1552 err = snd_hda_attach_beep_device(codec, 0x10);
1560 if (err < 0) { 1553 if (err < 0) {
1561 ad198x_free(codec); 1554 ad198x_free(codec);
@@ -1924,6 +1917,7 @@ static const struct hda_input_mux ad1981_thinkpad_capture_source = {
1924 1917
1925/* models */ 1918/* models */
1926enum { 1919enum {
1920 AD1981_AUTO,
1927 AD1981_BASIC, 1921 AD1981_BASIC,
1928 AD1981_HP, 1922 AD1981_HP,
1929 AD1981_THINKPAD, 1923 AD1981_THINKPAD,
@@ -1932,6 +1926,7 @@ enum {
1932}; 1926};
1933 1927
1934static const char * const ad1981_models[AD1981_MODELS] = { 1928static const char * const ad1981_models[AD1981_MODELS] = {
1929 [AD1981_AUTO] = "auto",
1935 [AD1981_HP] = "hp", 1930 [AD1981_HP] = "hp",
1936 [AD1981_THINKPAD] = "thinkpad", 1931 [AD1981_THINKPAD] = "thinkpad",
1937 [AD1981_BASIC] = "basic", 1932 [AD1981_BASIC] = "basic",
@@ -1951,6 +1946,15 @@ static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
1951 {} 1946 {}
1952}; 1947};
1953 1948
1949static int ad1981_parse_auto_config(struct hda_codec *codec)
1950{
1951 struct ad198x_spec *spec = codec->spec;
1952
1953 spec->beep_dev_nid = 0x10;
1954 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1955 return ad198x_parse_auto_config(codec);
1956}
1957
1954static int patch_ad1981(struct hda_codec *codec) 1958static int patch_ad1981(struct hda_codec *codec)
1955{ 1959{
1956 struct ad198x_spec *spec; 1960 struct ad198x_spec *spec;
@@ -1961,6 +1965,18 @@ static int patch_ad1981(struct hda_codec *codec)
1961 return -ENOMEM; 1965 return -ENOMEM;
1962 spec = codec->spec; 1966 spec = codec->spec;
1963 1967
1968 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1969 ad1981_models,
1970 ad1981_cfg_tbl);
1971 if (board_config == AD1981_AUTO) {
1972 err = ad1981_parse_auto_config(codec);
1973 if (err < 0) {
1974 ad198x_free(codec);
1975 return err;
1976 }
1977 return 0;
1978 }
1979
1964 err = snd_hda_attach_beep_device(codec, 0x10); 1980 err = snd_hda_attach_beep_device(codec, 0x10);
1965 if (err < 0) { 1981 if (err < 0) {
1966 ad198x_free(codec); 1982 ad198x_free(codec);
@@ -1989,9 +2005,6 @@ static int patch_ad1981(struct hda_codec *codec)
1989 codec->patch_ops = ad198x_patch_ops; 2005 codec->patch_ops = ad198x_patch_ops;
1990 2006
1991 /* override some parameters */ 2007 /* override some parameters */
1992 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1993 ad1981_models,
1994 ad1981_cfg_tbl);
1995 switch (board_config) { 2008 switch (board_config) {
1996 case AD1981_HP: 2009 case AD1981_HP:
1997 spec->mixers[0] = ad1981_hp_mixers; 2010 spec->mixers[0] = ad1981_hp_mixers;
@@ -2131,13 +2144,13 @@ static int patch_ad1981(struct hda_codec *codec)
2131 2144
2132/* models */ 2145/* models */
2133enum { 2146enum {
2147 AD1988_AUTO,
2134 AD1988_6STACK, 2148 AD1988_6STACK,
2135 AD1988_6STACK_DIG, 2149 AD1988_6STACK_DIG,
2136 AD1988_3STACK, 2150 AD1988_3STACK,
2137 AD1988_3STACK_DIG, 2151 AD1988_3STACK_DIG,
2138 AD1988_LAPTOP, 2152 AD1988_LAPTOP,
2139 AD1988_LAPTOP_DIG, 2153 AD1988_LAPTOP_DIG,
2140 AD1988_AUTO,
2141 AD1988_MODEL_LAST, 2154 AD1988_MODEL_LAST,
2142}; 2155};
2143 2156
@@ -2242,17 +2255,6 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2242 return err; 2255 return err;
2243} 2256}
2244 2257
2245static const struct snd_kcontrol_new ad1988_hp_mixers[] = {
2246 {
2247 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2248 .name = "Independent HP",
2249 .info = ad1988_independent_hp_info,
2250 .get = ad1988_independent_hp_get,
2251 .put = ad1988_independent_hp_put,
2252 },
2253 { } /* end */
2254};
2255
2256/* 6-stack mode */ 2258/* 6-stack mode */
2257static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = { 2259static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2258 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2260 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
@@ -2817,414 +2819,15 @@ static const struct hda_amp_list ad1988_loopbacks[] = {
2817#endif 2819#endif
2818 2820
2819/* 2821/*
2820 * Automatic parse of I/O pins from the BIOS configuration
2821 */ 2822 */
2822 2823
2823enum {
2824 AD_CTL_WIDGET_VOL,
2825 AD_CTL_WIDGET_MUTE,
2826 AD_CTL_BIND_MUTE,
2827};
2828static const struct snd_kcontrol_new ad1988_control_templates[] = {
2829 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2830 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2831 HDA_BIND_MUTE(NULL, 0, 0, 0),
2832};
2833
2834/* add dynamic controls */
2835static int add_control(struct ad198x_spec *spec, int type, const char *name,
2836 unsigned long val)
2837{
2838 struct snd_kcontrol_new *knew;
2839
2840 knew = snd_array_new(&spec->kctls);
2841 if (!knew)
2842 return -ENOMEM;
2843 *knew = ad1988_control_templates[type];
2844 knew->name = kstrdup(name, GFP_KERNEL);
2845 if (! knew->name)
2846 return -ENOMEM;
2847 if (get_amp_nid_(val))
2848 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2849 knew->private_value = val;
2850 return 0;
2851}
2852
2853#define AD1988_PIN_CD_NID 0x18
2854#define AD1988_PIN_BEEP_NID 0x10
2855
2856static const hda_nid_t ad1988_mixer_nids[8] = {
2857 /* A B C D E F G H */
2858 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
2859};
2860
2861static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
2862{
2863 static const hda_nid_t idx_to_dac[8] = {
2864 /* A B C D E F G H */
2865 0x03, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
2866 };
2867 static const hda_nid_t idx_to_dac_rev2[8] = {
2868 /* A B C D E F G H */
2869 0x03, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
2870 };
2871 if (is_rev2(codec))
2872 return idx_to_dac_rev2[idx];
2873 else
2874 return idx_to_dac[idx];
2875}
2876
2877static const hda_nid_t ad1988_boost_nids[8] = {
2878 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
2879};
2880
2881static int ad1988_pin_idx(hda_nid_t nid)
2882{
2883 static const hda_nid_t ad1988_io_pins[8] = {
2884 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
2885 };
2886 int i;
2887 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
2888 if (ad1988_io_pins[i] == nid)
2889 return i;
2890 return 0; /* should be -1 */
2891}
2892
2893static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
2894{
2895 static const int loopback_idx[8] = {
2896 2, 0, 1, 3, 4, 5, 1, 4
2897 };
2898 switch (nid) {
2899 case AD1988_PIN_CD_NID:
2900 return 6;
2901 default:
2902 return loopback_idx[ad1988_pin_idx(nid)];
2903 }
2904}
2905
2906static int ad1988_pin_to_adc_idx(hda_nid_t nid)
2907{
2908 static const int adc_idx[8] = {
2909 0, 1, 2, 8, 4, 3, 6, 7
2910 };
2911 switch (nid) {
2912 case AD1988_PIN_CD_NID:
2913 return 5;
2914 default:
2915 return adc_idx[ad1988_pin_idx(nid)];
2916 }
2917}
2918
2919/* fill in the dac_nids table from the parsed pin configuration */
2920static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
2921 const struct auto_pin_cfg *cfg)
2922{
2923 struct ad198x_spec *spec = codec->spec;
2924 int i, idx;
2925
2926 spec->multiout.dac_nids = spec->private_dac_nids;
2927
2928 /* check the pins hardwired to audio widget */
2929 for (i = 0; i < cfg->line_outs; i++) {
2930 idx = ad1988_pin_idx(cfg->line_out_pins[i]);
2931 spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx);
2932 }
2933 spec->multiout.num_dacs = cfg->line_outs;
2934 return 0;
2935}
2936
2937/* add playback controls from the parsed DAC table */
2938static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
2939 const struct auto_pin_cfg *cfg)
2940{
2941 char name[32];
2942 static const char * const chname[4] = {
2943 "Front", "Surround", NULL /*CLFE*/, "Side"
2944 };
2945 hda_nid_t nid;
2946 int i, err;
2947
2948 for (i = 0; i < cfg->line_outs; i++) {
2949 hda_nid_t dac = spec->multiout.dac_nids[i];
2950 if (! dac)
2951 continue;
2952 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
2953 if (i == 2) {
2954 /* Center/LFE */
2955 err = add_control(spec, AD_CTL_WIDGET_VOL,
2956 "Center Playback Volume",
2957 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
2958 if (err < 0)
2959 return err;
2960 err = add_control(spec, AD_CTL_WIDGET_VOL,
2961 "LFE Playback Volume",
2962 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
2963 if (err < 0)
2964 return err;
2965 err = add_control(spec, AD_CTL_BIND_MUTE,
2966 "Center Playback Switch",
2967 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
2968 if (err < 0)
2969 return err;
2970 err = add_control(spec, AD_CTL_BIND_MUTE,
2971 "LFE Playback Switch",
2972 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
2973 if (err < 0)
2974 return err;
2975 } else {
2976 sprintf(name, "%s Playback Volume", chname[i]);
2977 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
2978 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
2979 if (err < 0)
2980 return err;
2981 sprintf(name, "%s Playback Switch", chname[i]);
2982 err = add_control(spec, AD_CTL_BIND_MUTE, name,
2983 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
2984 if (err < 0)
2985 return err;
2986 }
2987 }
2988 return 0;
2989}
2990
2991/* add playback controls for speaker and HP outputs */
2992static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2993 const char *pfx)
2994{
2995 struct ad198x_spec *spec = codec->spec;
2996 hda_nid_t nid;
2997 int i, idx, err;
2998 char name[32];
2999
3000 if (! pin)
3001 return 0;
3002
3003 idx = ad1988_pin_idx(pin);
3004 nid = ad1988_idx_to_dac(codec, idx);
3005 /* check whether the corresponding DAC was already taken */
3006 for (i = 0; i < spec->autocfg.line_outs; i++) {
3007 hda_nid_t pin = spec->autocfg.line_out_pins[i];
3008 hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
3009 if (dac == nid)
3010 break;
3011 }
3012 if (i >= spec->autocfg.line_outs) {
3013 /* specify the DAC as the extra output */
3014 if (!spec->multiout.hp_nid)
3015 spec->multiout.hp_nid = nid;
3016 else
3017 spec->multiout.extra_out_nid[0] = nid;
3018 /* control HP volume/switch on the output mixer amp */
3019 sprintf(name, "%s Playback Volume", pfx);
3020 err = add_control(spec, AD_CTL_WIDGET_VOL, name,
3021 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
3022 if (err < 0)
3023 return err;
3024 }
3025 nid = ad1988_mixer_nids[idx];
3026 sprintf(name, "%s Playback Switch", pfx);
3027 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
3028 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
3029 return err;
3030 return 0;
3031}
3032
3033/* create input playback/capture controls for the given pin */
3034static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
3035 const char *ctlname, int ctlidx, int boost)
3036{
3037 char name[32];
3038 int err, idx;
3039
3040 sprintf(name, "%s Playback Volume", ctlname);
3041 idx = ad1988_pin_to_loopback_idx(pin);
3042 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
3043 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
3044 return err;
3045 sprintf(name, "%s Playback Switch", ctlname);
3046 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
3047 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
3048 return err;
3049 if (boost) {
3050 hda_nid_t bnid;
3051 idx = ad1988_pin_idx(pin);
3052 bnid = ad1988_boost_nids[idx];
3053 if (bnid) {
3054 sprintf(name, "%s Boost Volume", ctlname);
3055 return add_control(spec, AD_CTL_WIDGET_VOL, name,
3056 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
3057
3058 }
3059 }
3060 return 0;
3061}
3062
3063/* create playback/capture controls for input pins */
3064static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
3065 const struct auto_pin_cfg *cfg)
3066{
3067 struct ad198x_spec *spec = codec->spec;
3068 struct hda_input_mux *imux = &spec->private_imux;
3069 int i, err, type, type_idx;
3070
3071 for (i = 0; i < cfg->num_inputs; i++) {
3072 const char *label;
3073 type = cfg->inputs[i].type;
3074 label = hda_get_autocfg_input_label(codec, cfg, i);
3075 snd_hda_add_imux_item(imux, label,
3076 ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
3077 &type_idx);
3078 err = new_analog_input(spec, cfg->inputs[i].pin,
3079 label, type_idx,
3080 type == AUTO_PIN_MIC);
3081 if (err < 0)
3082 return err;
3083 }
3084 snd_hda_add_imux_item(imux, "Mix", 9, NULL);
3085
3086 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
3087 "Analog Mix Playback Volume",
3088 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3089 return err;
3090 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
3091 "Analog Mix Playback Switch",
3092 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
3093 return err;
3094
3095 return 0;
3096}
3097
3098static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
3099 hda_nid_t nid, int pin_type,
3100 int dac_idx)
3101{
3102 /* set as output */
3103 snd_hda_set_pin_ctl(codec, nid, pin_type);
3104 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3105 switch (nid) {
3106 case 0x11: /* port-A - DAC 03 */
3107 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
3108 break;
3109 case 0x14: /* port-B - DAC 06 */
3110 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
3111 break;
3112 case 0x15: /* port-C - DAC 05 */
3113 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
3114 break;
3115 case 0x17: /* port-E - DAC 0a */
3116 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3117 break;
3118 case 0x13: /* mono - DAC 04 */
3119 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
3120 break;
3121 }
3122}
3123
3124static void ad1988_auto_init_multi_out(struct hda_codec *codec)
3125{
3126 struct ad198x_spec *spec = codec->spec;
3127 int i;
3128
3129 for (i = 0; i < spec->autocfg.line_outs; i++) {
3130 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3131 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3132 }
3133}
3134
3135static void ad1988_auto_init_extra_out(struct hda_codec *codec)
3136{
3137 struct ad198x_spec *spec = codec->spec;
3138 hda_nid_t pin;
3139
3140 pin = spec->autocfg.speaker_pins[0];
3141 if (pin) /* connect to front */
3142 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
3143 pin = spec->autocfg.hp_pins[0];
3144 if (pin) /* connect to front */
3145 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
3146}
3147
3148static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3149{
3150 struct ad198x_spec *spec = codec->spec;
3151 const struct auto_pin_cfg *cfg = &spec->autocfg;
3152 int i, idx;
3153
3154 for (i = 0; i < cfg->num_inputs; i++) {
3155 hda_nid_t nid = cfg->inputs[i].pin;
3156 int type = cfg->inputs[i].type;
3157 int val;
3158 switch (nid) {
3159 case 0x15: /* port-C */
3160 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3161 break;
3162 case 0x17: /* port-E */
3163 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
3164 break;
3165 }
3166 val = PIN_IN;
3167 if (type == AUTO_PIN_MIC)
3168 val |= snd_hda_get_default_vref(codec, nid);
3169 snd_hda_set_pin_ctl(codec, nid, val);
3170 if (nid != AD1988_PIN_CD_NID)
3171 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3172 AMP_OUT_MUTE);
3173 idx = ad1988_pin_idx(nid);
3174 if (ad1988_boost_nids[idx])
3175 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
3176 AC_VERB_SET_AMP_GAIN_MUTE,
3177 AMP_OUT_ZERO);
3178 }
3179}
3180
3181/* parse the BIOS configuration and set up the alc_spec */
3182/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
3183static int ad1988_parse_auto_config(struct hda_codec *codec) 2824static int ad1988_parse_auto_config(struct hda_codec *codec)
3184{ 2825{
3185 struct ad198x_spec *spec = codec->spec; 2826 struct ad198x_spec *spec = codec->spec;
3186 int err;
3187
3188 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
3189 return err;
3190 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
3191 return err;
3192 if (! spec->autocfg.line_outs)
3193 return 0; /* can't find valid BIOS pin config */
3194 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3195 (err = ad1988_auto_create_extra_out(codec,
3196 spec->autocfg.speaker_pins[0],
3197 "Speaker")) < 0 ||
3198 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3199 "Headphone")) < 0 ||
3200 (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
3201 return err;
3202
3203 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3204
3205 if (spec->autocfg.dig_outs)
3206 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3207 if (spec->autocfg.dig_in_pin)
3208 spec->dig_in_nid = AD1988_SPDIF_IN;
3209
3210 if (spec->kctls.list)
3211 spec->mixers[spec->num_mixers++] = spec->kctls.list;
3212
3213 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
3214
3215 spec->input_mux = &spec->private_imux;
3216 2827
3217 return 1; 2828 spec->beep_dev_nid = 0x10;
3218} 2829 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3219 2830 return ad198x_parse_auto_config(codec);
3220/* init callback for auto-configuration model -- overriding the default init */
3221static int ad1988_auto_init(struct hda_codec *codec)
3222{
3223 ad198x_init(codec);
3224 ad1988_auto_init_multi_out(codec);
3225 ad1988_auto_init_extra_out(codec);
3226 ad1988_auto_init_analog_input(codec);
3227 return 0;
3228} 2831}
3229 2832
3230/* 2833/*
@@ -3259,9 +2862,6 @@ static int patch_ad1988(struct hda_codec *codec)
3259 return err; 2862 return err;
3260 spec = codec->spec; 2863 spec = codec->spec;
3261 2864
3262 if (is_rev2(codec))
3263 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3264
3265 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, 2865 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3266 ad1988_models, ad1988_cfg_tbl); 2866 ad1988_models, ad1988_cfg_tbl);
3267 if (board_config < 0) { 2867 if (board_config < 0) {
@@ -3276,12 +2876,13 @@ static int patch_ad1988(struct hda_codec *codec)
3276 if (err < 0) { 2876 if (err < 0) {
3277 ad198x_free(codec); 2877 ad198x_free(codec);
3278 return err; 2878 return err;
3279 } else if (! err) {
3280 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
3281 board_config = AD1988_6STACK;
3282 } 2879 }
2880 return 0;
3283 } 2881 }
3284 2882
2883 if (is_rev2(codec))
2884 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2885
3285 err = snd_hda_attach_beep_device(codec, 0x10); 2886 err = snd_hda_attach_beep_device(codec, 0x10);
3286 if (err < 0) { 2887 if (err < 0) {
3287 ad198x_free(codec); 2888 ad198x_free(codec);
@@ -3344,7 +2945,7 @@ static int patch_ad1988(struct hda_codec *codec)
3344 spec->input_mux = &ad1988_laptop_capture_source; 2945 spec->input_mux = &ad1988_laptop_capture_source;
3345 spec->num_mixers = 1; 2946 spec->num_mixers = 1;
3346 spec->mixers[0] = ad1988_laptop_mixers; 2947 spec->mixers[0] = ad1988_laptop_mixers;
3347 spec->inv_eapd = 1; /* inverted EAPD */ 2948 codec->inv_eapd = 1; /* inverted EAPD */
3348 spec->num_init_verbs = 1; 2949 spec->num_init_verbs = 1;
3349 spec->init_verbs[0] = ad1988_laptop_init_verbs; 2950 spec->init_verbs[0] = ad1988_laptop_init_verbs;
3350 if (board_config == AD1988_LAPTOP_DIG) 2951 if (board_config == AD1988_LAPTOP_DIG)
@@ -3352,15 +2953,6 @@ static int patch_ad1988(struct hda_codec *codec)
3352 break; 2953 break;
3353 } 2954 }
3354 2955
3355 if (spec->autocfg.hp_pins[0]) {
3356 spec->mixers[spec->num_mixers++] = ad1988_hp_mixers;
3357 spec->slave_vols = ad1988_6stack_fp_slave_pfxs;
3358 spec->slave_sws = ad1988_6stack_fp_slave_pfxs;
3359 spec->alt_dac_nid = ad1988_alt_dac_nid;
3360 spec->stream_analog_alt_playback =
3361 &ad198x_pcm_analog_alt_playback;
3362 }
3363
3364 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids); 2956 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3365 spec->adc_nids = ad1988_adc_nids; 2957 spec->adc_nids = ad1988_adc_nids;
3366 spec->capsrc_nids = ad1988_capsrc_nids; 2958 spec->capsrc_nids = ad1988_capsrc_nids;
@@ -3388,9 +2980,6 @@ static int patch_ad1988(struct hda_codec *codec)
3388 2980
3389 codec->patch_ops = ad198x_patch_ops; 2981 codec->patch_ops = ad198x_patch_ops;
3390 switch (board_config) { 2982 switch (board_config) {
3391 case AD1988_AUTO:
3392 codec->patch_ops.init = ad1988_auto_init;
3393 break;
3394 case AD1988_LAPTOP: 2983 case AD1988_LAPTOP:
3395 case AD1988_LAPTOP_DIG: 2984 case AD1988_LAPTOP_DIG:
3396 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; 2985 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
@@ -3568,7 +3157,43 @@ static const char * const ad1884_slave_vols[] = {
3568 NULL 3157 NULL
3569}; 3158};
3570 3159
3571static int patch_ad1884(struct hda_codec *codec) 3160enum {
3161 AD1884_AUTO,
3162 AD1884_BASIC,
3163 AD1884_MODELS
3164};
3165
3166static const char * const ad1884_models[AD1884_MODELS] = {
3167 [AD1884_AUTO] = "auto",
3168 [AD1884_BASIC] = "basic",
3169};
3170
3171static int ad1884_parse_auto_config(struct hda_codec *codec)
3172{
3173 struct ad198x_spec *spec = codec->spec;
3174
3175 spec->beep_dev_nid = 0x10;
3176 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3177 return ad198x_parse_auto_config(codec);
3178}
3179
3180static int patch_ad1884_auto(struct hda_codec *codec)
3181{
3182 int err;
3183
3184 err = alloc_ad_spec(codec);
3185 if (err < 0)
3186 return err;
3187
3188 err = ad1884_parse_auto_config(codec);
3189 if (err < 0) {
3190 ad198x_free(codec);
3191 return err;
3192 }
3193 return 0;
3194}
3195
3196static int patch_ad1884_basic(struct hda_codec *codec)
3572{ 3197{
3573 struct ad198x_spec *spec; 3198 struct ad198x_spec *spec;
3574 int err; 3199 int err;
@@ -3615,6 +3240,18 @@ static int patch_ad1884(struct hda_codec *codec)
3615 return 0; 3240 return 0;
3616} 3241}
3617 3242
3243static int patch_ad1884(struct hda_codec *codec)
3244{
3245 int board_config;
3246
3247 board_config = snd_hda_check_board_config(codec, AD1884_MODELS,
3248 ad1884_models, NULL);
3249 if (board_config == AD1884_AUTO)
3250 return patch_ad1884_auto(codec);
3251 else
3252 return patch_ad1884_basic(codec);
3253}
3254
3618/* 3255/*
3619 * Lenovo Thinkpad T61/X61 3256 * Lenovo Thinkpad T61/X61
3620 */ 3257 */
@@ -3787,6 +3424,7 @@ static int ad1984_build_pcms(struct hda_codec *codec)
3787 3424
3788/* models */ 3425/* models */
3789enum { 3426enum {
3427 AD1984_AUTO,
3790 AD1984_BASIC, 3428 AD1984_BASIC,
3791 AD1984_THINKPAD, 3429 AD1984_THINKPAD,
3792 AD1984_DELL_DESKTOP, 3430 AD1984_DELL_DESKTOP,
@@ -3794,6 +3432,7 @@ enum {
3794}; 3432};
3795 3433
3796static const char * const ad1984_models[AD1984_MODELS] = { 3434static const char * const ad1984_models[AD1984_MODELS] = {
3435 [AD1984_AUTO] = "auto",
3797 [AD1984_BASIC] = "basic", 3436 [AD1984_BASIC] = "basic",
3798 [AD1984_THINKPAD] = "thinkpad", 3437 [AD1984_THINKPAD] = "thinkpad",
3799 [AD1984_DELL_DESKTOP] = "dell_desktop", 3438 [AD1984_DELL_DESKTOP] = "dell_desktop",
@@ -3812,12 +3451,16 @@ static int patch_ad1984(struct hda_codec *codec)
3812 struct ad198x_spec *spec; 3451 struct ad198x_spec *spec;
3813 int board_config, err; 3452 int board_config, err;
3814 3453
3815 err = patch_ad1884(codec); 3454 board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3455 ad1984_models, ad1984_cfg_tbl);
3456 if (board_config == AD1984_AUTO)
3457 return patch_ad1884_auto(codec);
3458
3459 err = patch_ad1884_basic(codec);
3816 if (err < 0) 3460 if (err < 0)
3817 return err; 3461 return err;
3818 spec = codec->spec; 3462 spec = codec->spec;
3819 board_config = snd_hda_check_board_config(codec, AD1984_MODELS, 3463
3820 ad1984_models, ad1984_cfg_tbl);
3821 switch (board_config) { 3464 switch (board_config) {
3822 case AD1984_BASIC: 3465 case AD1984_BASIC:
3823 /* additional digital mics */ 3466 /* additional digital mics */
@@ -4534,6 +4177,7 @@ static int ad1984a_touchsmart_init(struct hda_codec *codec)
4534 */ 4177 */
4535 4178
4536enum { 4179enum {
4180 AD1884A_AUTO,
4537 AD1884A_DESKTOP, 4181 AD1884A_DESKTOP,
4538 AD1884A_LAPTOP, 4182 AD1884A_LAPTOP,
4539 AD1884A_MOBILE, 4183 AD1884A_MOBILE,
@@ -4544,6 +4188,7 @@ enum {
4544}; 4188};
4545 4189
4546static const char * const ad1884a_models[AD1884A_MODELS] = { 4190static const char * const ad1884a_models[AD1884A_MODELS] = {
4191 [AD1884A_AUTO] = "auto",
4547 [AD1884A_DESKTOP] = "desktop", 4192 [AD1884A_DESKTOP] = "desktop",
4548 [AD1884A_LAPTOP] = "laptop", 4193 [AD1884A_LAPTOP] = "laptop",
4549 [AD1884A_MOBILE] = "mobile", 4194 [AD1884A_MOBILE] = "mobile",
@@ -4572,6 +4217,12 @@ static int patch_ad1884a(struct hda_codec *codec)
4572 struct ad198x_spec *spec; 4217 struct ad198x_spec *spec;
4573 int err, board_config; 4218 int err, board_config;
4574 4219
4220 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4221 ad1884a_models,
4222 ad1884a_cfg_tbl);
4223 if (board_config == AD1884_AUTO)
4224 return patch_ad1884_auto(codec);
4225
4575 err = alloc_ad_spec(codec); 4226 err = alloc_ad_spec(codec);
4576 if (err < 0) 4227 if (err < 0)
4577 return err; 4228 return err;
@@ -4603,9 +4254,6 @@ static int patch_ad1884a(struct hda_codec *codec)
4603 codec->patch_ops = ad198x_patch_ops; 4254 codec->patch_ops = ad198x_patch_ops;
4604 4255
4605 /* override some parameters */ 4256 /* override some parameters */
4606 board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4607 ad1884a_models,
4608 ad1884a_cfg_tbl);
4609 switch (board_config) { 4257 switch (board_config) {
4610 case AD1884A_LAPTOP: 4258 case AD1884A_LAPTOP:
4611 spec->mixers[0] = ad1884a_laptop_mixers; 4259 spec->mixers[0] = ad1884a_laptop_mixers;
@@ -4966,6 +4614,7 @@ static const struct hda_amp_list ad1882_loopbacks[] = {
4966 4614
4967/* models */ 4615/* models */
4968enum { 4616enum {
4617 AD1882_AUTO,
4969 AD1882_3STACK, 4618 AD1882_3STACK,
4970 AD1882_6STACK, 4619 AD1882_6STACK,
4971 AD1882_3STACK_AUTOMUTE, 4620 AD1882_3STACK_AUTOMUTE,
@@ -4973,11 +4622,20 @@ enum {
4973}; 4622};
4974 4623
4975static const char * const ad1882_models[AD1986A_MODELS] = { 4624static const char * const ad1882_models[AD1986A_MODELS] = {
4625 [AD1882_AUTO] = "auto",
4976 [AD1882_3STACK] = "3stack", 4626 [AD1882_3STACK] = "3stack",
4977 [AD1882_6STACK] = "6stack", 4627 [AD1882_6STACK] = "6stack",
4978 [AD1882_3STACK_AUTOMUTE] = "3stack-automute", 4628 [AD1882_3STACK_AUTOMUTE] = "3stack-automute",
4979}; 4629};
4980 4630
4631static int ad1882_parse_auto_config(struct hda_codec *codec)
4632{
4633 struct ad198x_spec *spec = codec->spec;
4634
4635 spec->beep_dev_nid = 0x10;
4636 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4637 return ad198x_parse_auto_config(codec);
4638}
4981 4639
4982static int patch_ad1882(struct hda_codec *codec) 4640static int patch_ad1882(struct hda_codec *codec)
4983{ 4641{
@@ -4989,6 +4647,17 @@ static int patch_ad1882(struct hda_codec *codec)
4989 return err; 4647 return err;
4990 spec = codec->spec; 4648 spec = codec->spec;
4991 4649
4650 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
4651 ad1882_models, NULL);
4652 if (board_config == AD1882_AUTO) {
4653 err = ad1882_parse_auto_config(codec);
4654 if (err < 0) {
4655 ad198x_free(codec);
4656 return err;
4657 }
4658 return 0;
4659 }
4660
4992 err = snd_hda_attach_beep_device(codec, 0x10); 4661 err = snd_hda_attach_beep_device(codec, 0x10);
4993 if (err < 0) { 4662 if (err < 0) {
4994 ad198x_free(codec); 4663 ad198x_free(codec);
@@ -5024,8 +4693,6 @@ static int patch_ad1882(struct hda_codec *codec)
5024 codec->patch_ops = ad198x_patch_ops; 4693 codec->patch_ops = ad198x_patch_ops;
5025 4694
5026 /* override some parameters */ 4695 /* override some parameters */
5027 board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
5028 ad1882_models, NULL);
5029 switch (board_config) { 4696 switch (board_config) {
5030 default: 4697 default:
5031 case AD1882_3STACK: 4698 case AD1882_3STACK: