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.c599
1 files changed, 529 insertions, 70 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 1ada1b075c9a..32401bd8c229 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -23,6 +23,8 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/pci.h> 25#include <linux/pci.h>
26#include <linux/mutex.h>
27
26#include <sound/core.h> 28#include <sound/core.h>
27#include "hda_codec.h" 29#include "hda_codec.h"
28#include "hda_local.h" 30#include "hda_local.h"
@@ -60,7 +62,7 @@ struct ad198x_spec {
60 /* PCM information */ 62 /* PCM information */
61 struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ 63 struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */
62 64
63 struct semaphore amp_mutex; /* PCM volume/mute control mutex */ 65 struct mutex amp_mutex; /* PCM volume/mute control mutex */
64 unsigned int spdif_route; 66 unsigned int spdif_route;
65 67
66 /* dynamic controls, init_verbs and input_mux */ 68 /* dynamic controls, init_verbs and input_mux */
@@ -308,7 +310,7 @@ static int ad198x_resume(struct hda_codec *codec)
308 struct ad198x_spec *spec = codec->spec; 310 struct ad198x_spec *spec = codec->spec;
309 int i; 311 int i;
310 312
311 ad198x_init(codec); 313 codec->patch_ops.init(codec);
312 for (i = 0; i < spec->num_mixers; i++) 314 for (i = 0; i < spec->num_mixers; i++)
313 snd_hda_resume_ctls(codec, spec->mixers[i]); 315 snd_hda_resume_ctls(codec, spec->mixers[i]);
314 if (spec->multiout.dig_out_nid) 316 if (spec->multiout.dig_out_nid)
@@ -331,6 +333,61 @@ static struct hda_codec_ops ad198x_patch_ops = {
331 333
332 334
333/* 335/*
336 * EAPD control
337 * the private value = nid | (invert << 8)
338 */
339static int ad198x_eapd_info(struct snd_kcontrol *kcontrol,
340 struct snd_ctl_elem_info *uinfo)
341{
342 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
343 uinfo->count = 1;
344 uinfo->value.integer.min = 0;
345 uinfo->value.integer.max = 1;
346 return 0;
347}
348
349static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
350 struct snd_ctl_elem_value *ucontrol)
351{
352 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
353 struct ad198x_spec *spec = codec->spec;
354 int invert = (kcontrol->private_value >> 8) & 1;
355 if (invert)
356 ucontrol->value.integer.value[0] = ! spec->cur_eapd;
357 else
358 ucontrol->value.integer.value[0] = spec->cur_eapd;
359 return 0;
360}
361
362static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
363 struct snd_ctl_elem_value *ucontrol)
364{
365 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
366 struct ad198x_spec *spec = codec->spec;
367 int invert = (kcontrol->private_value >> 8) & 1;
368 hda_nid_t nid = kcontrol->private_value & 0xff;
369 unsigned int eapd;
370 eapd = ucontrol->value.integer.value[0];
371 if (invert)
372 eapd = !eapd;
373 if (eapd == spec->cur_eapd && ! codec->in_resume)
374 return 0;
375 spec->cur_eapd = eapd;
376 snd_hda_codec_write(codec, nid,
377 0, AC_VERB_SET_EAPD_BTLENABLE,
378 eapd ? 0x02 : 0x00);
379 return 1;
380}
381
382static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
383 struct snd_ctl_elem_info *uinfo);
384static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
385 struct snd_ctl_elem_value *ucontrol);
386static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
387 struct snd_ctl_elem_value *ucontrol);
388
389
390/*
334 * AD1986A specific 391 * AD1986A specific
335 */ 392 */
336 393
@@ -344,6 +401,7 @@ static hda_nid_t ad1986a_dac_nids[3] = {
344 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC 401 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
345}; 402};
346static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; 403static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
404static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
347 405
348static struct hda_input_mux ad1986a_capture_source = { 406static struct hda_input_mux ad1986a_capture_source = {
349 .num_items = 7, 407 .num_items = 7,
@@ -371,9 +429,9 @@ static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl
371 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 429 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
372 struct ad198x_spec *ad = codec->spec; 430 struct ad198x_spec *ad = codec->spec;
373 431
374 down(&ad->amp_mutex); 432 mutex_lock(&ad->amp_mutex);
375 snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); 433 snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
376 up(&ad->amp_mutex); 434 mutex_unlock(&ad->amp_mutex);
377 return 0; 435 return 0;
378} 436}
379 437
@@ -383,13 +441,13 @@ static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl
383 struct ad198x_spec *ad = codec->spec; 441 struct ad198x_spec *ad = codec->spec;
384 int i, change = 0; 442 int i, change = 0;
385 443
386 down(&ad->amp_mutex); 444 mutex_lock(&ad->amp_mutex);
387 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { 445 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
388 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); 446 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
389 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); 447 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
390 } 448 }
391 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); 449 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
392 up(&ad->amp_mutex); 450 mutex_unlock(&ad->amp_mutex);
393 return change; 451 return change;
394} 452}
395 453
@@ -400,9 +458,9 @@ static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
400 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 458 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
401 struct ad198x_spec *ad = codec->spec; 459 struct ad198x_spec *ad = codec->spec;
402 460
403 down(&ad->amp_mutex); 461 mutex_lock(&ad->amp_mutex);
404 snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); 462 snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
405 up(&ad->amp_mutex); 463 mutex_unlock(&ad->amp_mutex);
406 return 0; 464 return 0;
407} 465}
408 466
@@ -412,13 +470,13 @@ static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
412 struct ad198x_spec *ad = codec->spec; 470 struct ad198x_spec *ad = codec->spec;
413 int i, change = 0; 471 int i, change = 0;
414 472
415 down(&ad->amp_mutex); 473 mutex_lock(&ad->amp_mutex);
416 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { 474 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
417 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); 475 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
418 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 476 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
419 } 477 }
420 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); 478 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
421 up(&ad->amp_mutex); 479 mutex_unlock(&ad->amp_mutex);
422 return change; 480 return change;
423} 481}
424 482
@@ -477,6 +535,143 @@ static struct snd_kcontrol_new ad1986a_mixers[] = {
477 { } /* end */ 535 { } /* end */
478}; 536};
479 537
538/* additional mixers for 3stack mode */
539static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
540 {
541 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
542 .name = "Channel Mode",
543 .info = ad198x_ch_mode_info,
544 .get = ad198x_ch_mode_get,
545 .put = ad198x_ch_mode_put,
546 },
547 { } /* end */
548};
549
550/* laptop model - 2ch only */
551static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
552
553static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
554 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
555 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
556 HDA_CODEC_VOLUME("Master Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
557 HDA_CODEC_MUTE("Master Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
558 /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
559 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), */
560 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
561 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
562 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
563 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
564 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
565 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
566 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
567 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
568 /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
569 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
570 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
571 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
572 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
573 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
574 {
575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
576 .name = "Capture Source",
577 .info = ad198x_mux_enum_info,
578 .get = ad198x_mux_enum_get,
579 .put = ad198x_mux_enum_put,
580 },
581 { } /* end */
582};
583
584/* laptop-eapd model - 2ch only */
585
586/* master controls both pins 0x1a and 0x1b */
587static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol,
588 struct snd_ctl_elem_value *ucontrol)
589{
590 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
591 long *valp = ucontrol->value.integer.value;
592 int change;
593
594 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
595 0x7f, valp[0] & 0x7f);
596 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
597 0x7f, valp[1] & 0x7f);
598 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
599 0x7f, valp[0] & 0x7f);
600 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
601 0x7f, valp[1] & 0x7f);
602 return change;
603}
604
605static int ad1986a_laptop_master_sw_put(struct snd_kcontrol *kcontrol,
606 struct snd_ctl_elem_value *ucontrol)
607{
608 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
609 long *valp = ucontrol->value.integer.value;
610 int change;
611
612 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
613 0x80, valp[0] ? 0 : 0x80);
614 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
615 0x80, valp[1] ? 0 : 0x80);
616 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
617 0x80, valp[0] ? 0 : 0x80);
618 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
619 0x80, valp[1] ? 0 : 0x80);
620 return change;
621}
622
623static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
624 .num_items = 3,
625 .items = {
626 { "Mic", 0x0 },
627 { "Internal Mic", 0x4 },
628 { "Mix", 0x5 },
629 },
630};
631
632static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
633 {
634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
635 .name = "Master Playback Volume",
636 .info = snd_hda_mixer_amp_volume_info,
637 .get = snd_hda_mixer_amp_volume_get,
638 .put = ad1986a_laptop_master_vol_put,
639 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
640 },
641 {
642 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
643 .name = "Master Playback Switch",
644 .info = snd_hda_mixer_amp_switch_info,
645 .get = snd_hda_mixer_amp_switch_get,
646 .put = ad1986a_laptop_master_sw_put,
647 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
648 },
649 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
650 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
651 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
652 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
653 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
654 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
655 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
656 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
657 {
658 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
659 .name = "Capture Source",
660 .info = ad198x_mux_enum_info,
661 .get = ad198x_mux_enum_get,
662 .put = ad198x_mux_enum_put,
663 },
664 {
665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
666 .name = "External Amplifier",
667 .info = ad198x_eapd_info,
668 .get = ad198x_eapd_get,
669 .put = ad198x_eapd_put,
670 .private_value = 0x1b | (1 << 8), /* port-D, inversed */
671 },
672 { } /* end */
673};
674
480/* 675/*
481 * initialization verbs 676 * initialization verbs
482 */ 677 */
@@ -535,16 +730,89 @@ static struct hda_verb ad1986a_init_verbs[] = {
535 { } /* end */ 730 { } /* end */
536}; 731};
537 732
733/* additional verbs for 3-stack model */
734static struct hda_verb ad1986a_3st_init_verbs[] = {
735 /* Mic and line-in selectors */
736 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
737 {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
738 { } /* end */
739};
740
741static struct hda_verb ad1986a_ch2_init[] = {
742 /* Surround out -> Line In */
743 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
744 { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
745 /* CLFE -> Mic in */
746 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
747 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
748 { } /* end */
749};
750
751static struct hda_verb ad1986a_ch4_init[] = {
752 /* Surround out -> Surround */
753 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
754 { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
755 /* CLFE -> Mic in */
756 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
757 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
758 { } /* end */
759};
760
761static struct hda_verb ad1986a_ch6_init[] = {
762 /* Surround out -> Surround out */
763 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
764 { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
765 /* CLFE -> CLFE */
766 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
767 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
768 { } /* end */
769};
770
771static struct hda_channel_mode ad1986a_modes[3] = {
772 { 2, ad1986a_ch2_init },
773 { 4, ad1986a_ch4_init },
774 { 6, ad1986a_ch6_init },
775};
776
777/* eapd initialization */
778static struct hda_verb ad1986a_eapd_init_verbs[] = {
779 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00},
780 {}
781};
782
783/* models */
784enum { AD1986A_6STACK, AD1986A_3STACK, AD1986A_LAPTOP, AD1986A_LAPTOP_EAPD };
785
786static struct hda_board_config ad1986a_cfg_tbl[] = {
787 { .modelname = "6stack", .config = AD1986A_6STACK },
788 { .modelname = "3stack", .config = AD1986A_3STACK },
789 { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84,
790 .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */
791 { .modelname = "laptop", .config = AD1986A_LAPTOP },
792 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e,
793 .config = AD1986A_LAPTOP }, /* FSC V2060 */
794 { .pci_subvendor = 0x17c0, .pci_subdevice = 0x2017,
795 .config = AD1986A_LAPTOP }, /* Samsung M50 */
796 { .pci_subvendor = 0x1043, .pci_subdevice = 0x818f,
797 .config = AD1986A_LAPTOP }, /* ASUS P5GV-MX */
798 { .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD },
799 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024,
800 .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
801 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213,
802 .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */
803 {}
804};
538 805
539static int patch_ad1986a(struct hda_codec *codec) 806static int patch_ad1986a(struct hda_codec *codec)
540{ 807{
541 struct ad198x_spec *spec; 808 struct ad198x_spec *spec;
809 int board_config;
542 810
543 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 811 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
544 if (spec == NULL) 812 if (spec == NULL)
545 return -ENOMEM; 813 return -ENOMEM;
546 814
547 init_MUTEX(&spec->amp_mutex); 815 mutex_init(&spec->amp_mutex);
548 codec->spec = spec; 816 codec->spec = spec;
549 817
550 spec->multiout.max_channels = 6; 818 spec->multiout.max_channels = 6;
@@ -553,7 +821,7 @@ static int patch_ad1986a(struct hda_codec *codec)
553 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; 821 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
554 spec->num_adc_nids = 1; 822 spec->num_adc_nids = 1;
555 spec->adc_nids = ad1986a_adc_nids; 823 spec->adc_nids = ad1986a_adc_nids;
556 spec->capsrc_nids = ad1986a_adc_nids; 824 spec->capsrc_nids = ad1986a_capsrc_nids;
557 spec->input_mux = &ad1986a_capture_source; 825 spec->input_mux = &ad1986a_capture_source;
558 spec->num_mixers = 1; 826 spec->num_mixers = 1;
559 spec->mixers[0] = ad1986a_mixers; 827 spec->mixers[0] = ad1986a_mixers;
@@ -562,6 +830,35 @@ static int patch_ad1986a(struct hda_codec *codec)
562 830
563 codec->patch_ops = ad198x_patch_ops; 831 codec->patch_ops = ad198x_patch_ops;
564 832
833 /* override some parameters */
834 board_config = snd_hda_check_board_config(codec, ad1986a_cfg_tbl);
835 switch (board_config) {
836 case AD1986A_3STACK:
837 spec->num_mixers = 2;
838 spec->mixers[1] = ad1986a_3st_mixers;
839 spec->num_init_verbs = 2;
840 spec->init_verbs[1] = ad1986a_3st_init_verbs;
841 spec->channel_mode = ad1986a_modes;
842 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
843 break;
844 case AD1986A_LAPTOP:
845 spec->mixers[0] = ad1986a_laptop_mixers;
846 spec->multiout.max_channels = 2;
847 spec->multiout.num_dacs = 1;
848 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
849 break;
850 case AD1986A_LAPTOP_EAPD:
851 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
852 spec->num_init_verbs = 2;
853 spec->init_verbs[1] = ad1986a_eapd_init_verbs;
854 spec->multiout.max_channels = 2;
855 spec->multiout.num_dacs = 1;
856 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
857 spec->multiout.dig_out_nid = 0;
858 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
859 break;
860 }
861
565 return 0; 862 return 0;
566} 863}
567 864
@@ -575,6 +872,7 @@ static int patch_ad1986a(struct hda_codec *codec)
575 872
576static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; 873static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
577static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; 874static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
875static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
578 876
579static struct hda_input_mux ad1983_capture_source = { 877static struct hda_input_mux ad1983_capture_source = {
580 .num_items = 4, 878 .num_items = 4,
@@ -708,7 +1006,7 @@ static int patch_ad1983(struct hda_codec *codec)
708 if (spec == NULL) 1006 if (spec == NULL)
709 return -ENOMEM; 1007 return -ENOMEM;
710 1008
711 init_MUTEX(&spec->amp_mutex); 1009 mutex_init(&spec->amp_mutex);
712 codec->spec = spec; 1010 codec->spec = spec;
713 1011
714 spec->multiout.max_channels = 2; 1012 spec->multiout.max_channels = 2;
@@ -717,7 +1015,7 @@ static int patch_ad1983(struct hda_codec *codec)
717 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; 1015 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
718 spec->num_adc_nids = 1; 1016 spec->num_adc_nids = 1;
719 spec->adc_nids = ad1983_adc_nids; 1017 spec->adc_nids = ad1983_adc_nids;
720 spec->capsrc_nids = ad1983_adc_nids; 1018 spec->capsrc_nids = ad1983_capsrc_nids;
721 spec->input_mux = &ad1983_capture_source; 1019 spec->input_mux = &ad1983_capture_source;
722 spec->num_mixers = 1; 1020 spec->num_mixers = 1;
723 spec->mixers[0] = ad1983_mixers; 1021 spec->mixers[0] = ad1983_mixers;
@@ -741,6 +1039,7 @@ static int patch_ad1983(struct hda_codec *codec)
741 1039
742static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; 1040static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
743static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; 1041static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1042static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
744 1043
745/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ 1044/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
746static struct hda_input_mux ad1981_capture_source = { 1045static struct hda_input_mux ad1981_capture_source = {
@@ -846,15 +1145,200 @@ static struct hda_verb ad1981_init_verbs[] = {
846 { } /* end */ 1145 { } /* end */
847}; 1146};
848 1147
1148/*
1149 * Patch for HP nx6320
1150 *
1151 * nx6320 uses EAPD in the reserve way - EAPD-on means the internal
1152 * speaker output enabled _and_ mute-LED off.
1153 */
1154
1155#define AD1981_HP_EVENT 0x37
1156#define AD1981_MIC_EVENT 0x38
1157
1158static struct hda_verb ad1981_hp_init_verbs[] = {
1159 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1160 /* pin sensing on HP and Mic jacks */
1161 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1162 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1163 {}
1164};
1165
1166/* turn on/off EAPD (+ mute HP) as a master switch */
1167static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1168 struct snd_ctl_elem_value *ucontrol)
1169{
1170 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1171 struct ad198x_spec *spec = codec->spec;
1172
1173 if (! ad198x_eapd_put(kcontrol, ucontrol))
1174 return 0;
1175
1176 /* toggle HP mute appropriately */
1177 snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0,
1178 0x80, spec->cur_eapd ? 0 : 0x80);
1179 snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0,
1180 0x80, spec->cur_eapd ? 0 : 0x80);
1181 return 1;
1182}
1183
1184/* bind volumes of both NID 0x05 and 0x06 */
1185static int ad1981_hp_master_vol_put(struct snd_kcontrol *kcontrol,
1186 struct snd_ctl_elem_value *ucontrol)
1187{
1188 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1189 long *valp = ucontrol->value.integer.value;
1190 int change;
1191
1192 change = snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
1193 0x7f, valp[0] & 0x7f);
1194 change |= snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
1195 0x7f, valp[1] & 0x7f);
1196 snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0,
1197 0x7f, valp[0] & 0x7f);
1198 snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0,
1199 0x7f, valp[1] & 0x7f);
1200 return change;
1201}
1202
1203/* mute internal speaker if HP is plugged */
1204static void ad1981_hp_automute(struct hda_codec *codec)
1205{
1206 unsigned int present;
1207
1208 present = snd_hda_codec_read(codec, 0x06, 0,
1209 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1210 snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
1211 0x80, present ? 0x80 : 0);
1212 snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
1213 0x80, present ? 0x80 : 0);
1214}
1215
1216/* toggle input of built-in and mic jack appropriately */
1217static void ad1981_hp_automic(struct hda_codec *codec)
1218{
1219 static struct hda_verb mic_jack_on[] = {
1220 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1221 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1222 {}
1223 };
1224 static struct hda_verb mic_jack_off[] = {
1225 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1226 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1227 {}
1228 };
1229 unsigned int present;
1230
1231 present = snd_hda_codec_read(codec, 0x08, 0,
1232 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1233 if (present)
1234 snd_hda_sequence_write(codec, mic_jack_on);
1235 else
1236 snd_hda_sequence_write(codec, mic_jack_off);
1237}
1238
1239/* unsolicited event for HP jack sensing */
1240static void ad1981_hp_unsol_event(struct hda_codec *codec,
1241 unsigned int res)
1242{
1243 res >>= 26;
1244 switch (res) {
1245 case AD1981_HP_EVENT:
1246 ad1981_hp_automute(codec);
1247 break;
1248 case AD1981_MIC_EVENT:
1249 ad1981_hp_automic(codec);
1250 break;
1251 }
1252}
1253
1254static struct hda_input_mux ad1981_hp_capture_source = {
1255 .num_items = 3,
1256 .items = {
1257 { "Mic", 0x0 },
1258 { "Docking-Station", 0x1 },
1259 { "Mix", 0x2 },
1260 },
1261};
1262
1263static struct snd_kcontrol_new ad1981_hp_mixers[] = {
1264 {
1265 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1266 .name = "Master Playback Volume",
1267 .info = snd_hda_mixer_amp_volume_info,
1268 .get = snd_hda_mixer_amp_volume_get,
1269 .put = ad1981_hp_master_vol_put,
1270 .private_value = HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1271 },
1272 {
1273 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1274 .name = "Master Playback Switch",
1275 .info = ad198x_eapd_info,
1276 .get = ad198x_eapd_get,
1277 .put = ad1981_hp_master_sw_put,
1278 .private_value = 0x05,
1279 },
1280 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1281 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1282#if 0
1283 /* FIXME: analog mic/line loopback doesn't work with my tests...
1284 * (although recording is OK)
1285 */
1286 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1287 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1288 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1289 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1290 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1291 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1292 /* FIXME: does this laptop have analog CD connection? */
1293 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1294 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1295#endif
1296 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
1297 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT),
1298 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1299 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1300 {
1301 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1302 .name = "Capture Source",
1303 .info = ad198x_mux_enum_info,
1304 .get = ad198x_mux_enum_get,
1305 .put = ad198x_mux_enum_put,
1306 },
1307 { } /* end */
1308};
1309
1310/* initialize jack-sensing, too */
1311static int ad1981_hp_init(struct hda_codec *codec)
1312{
1313 ad198x_init(codec);
1314 ad1981_hp_automute(codec);
1315 ad1981_hp_automic(codec);
1316 return 0;
1317}
1318
1319/* models */
1320enum { AD1981_BASIC, AD1981_HP };
1321
1322static struct hda_board_config ad1981_cfg_tbl[] = {
1323 { .modelname = "hp", .config = AD1981_HP },
1324 { .pci_subvendor = 0x103c, .pci_subdevice = 0x30aa,
1325 .config = AD1981_HP }, /* HP nx6320 */
1326 { .pci_subvendor = 0x103c, .pci_subdevice = 0x309f,
1327 .config = AD1981_HP }, /* HP nx9420 AngelFire */
1328 { .modelname = "basic", .config = AD1981_BASIC },
1329 {}
1330};
1331
849static int patch_ad1981(struct hda_codec *codec) 1332static int patch_ad1981(struct hda_codec *codec)
850{ 1333{
851 struct ad198x_spec *spec; 1334 struct ad198x_spec *spec;
1335 int board_config;
852 1336
853 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1337 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
854 if (spec == NULL) 1338 if (spec == NULL)
855 return -ENOMEM; 1339 return -ENOMEM;
856 1340
857 init_MUTEX(&spec->amp_mutex); 1341 mutex_init(&spec->amp_mutex);
858 codec->spec = spec; 1342 codec->spec = spec;
859 1343
860 spec->multiout.max_channels = 2; 1344 spec->multiout.max_channels = 2;
@@ -863,7 +1347,7 @@ static int patch_ad1981(struct hda_codec *codec)
863 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; 1347 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
864 spec->num_adc_nids = 1; 1348 spec->num_adc_nids = 1;
865 spec->adc_nids = ad1981_adc_nids; 1349 spec->adc_nids = ad1981_adc_nids;
866 spec->capsrc_nids = ad1981_adc_nids; 1350 spec->capsrc_nids = ad1981_capsrc_nids;
867 spec->input_mux = &ad1981_capture_source; 1351 spec->input_mux = &ad1981_capture_source;
868 spec->num_mixers = 1; 1352 spec->num_mixers = 1;
869 spec->mixers[0] = ad1981_mixers; 1353 spec->mixers[0] = ad1981_mixers;
@@ -873,6 +1357,21 @@ static int patch_ad1981(struct hda_codec *codec)
873 1357
874 codec->patch_ops = ad198x_patch_ops; 1358 codec->patch_ops = ad198x_patch_ops;
875 1359
1360 /* override some parameters */
1361 board_config = snd_hda_check_board_config(codec, ad1981_cfg_tbl);
1362 switch (board_config) {
1363 case AD1981_HP:
1364 spec->mixers[0] = ad1981_hp_mixers;
1365 spec->num_init_verbs = 2;
1366 spec->init_verbs[1] = ad1981_hp_init_verbs;
1367 spec->multiout.dig_out_nid = 0;
1368 spec->input_mux = &ad1981_hp_capture_source;
1369
1370 codec->patch_ops.init = ad1981_hp_init;
1371 codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
1372 break;
1373 }
1374
876 return 0; 1375 return 0;
877} 1376}
878 1377
@@ -1060,44 +1559,6 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1060 spec->num_channel_mode, &spec->multiout.max_channels); 1559 spec->num_channel_mode, &spec->multiout.max_channels);
1061} 1560}
1062 1561
1063/*
1064 * EAPD control
1065 */
1066static int ad1988_eapd_info(struct snd_kcontrol *kcontrol,
1067 struct snd_ctl_elem_info *uinfo)
1068{
1069 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1070 uinfo->count = 1;
1071 uinfo->value.integer.min = 0;
1072 uinfo->value.integer.max = 1;
1073 return 0;
1074}
1075
1076static int ad1988_eapd_get(struct snd_kcontrol *kcontrol,
1077 struct snd_ctl_elem_value *ucontrol)
1078{
1079 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1080 struct ad198x_spec *spec = codec->spec;
1081 ucontrol->value.enumerated.item[0] = ! spec->cur_eapd;
1082 return 0;
1083}
1084
1085static int ad1988_eapd_put(struct snd_kcontrol *kcontrol,
1086 struct snd_ctl_elem_value *ucontrol)
1087{
1088 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1089 struct ad198x_spec *spec = codec->spec;
1090 unsigned int eapd;
1091 eapd = ! ucontrol->value.enumerated.item[0];
1092 if (eapd == spec->cur_eapd && ! codec->in_resume)
1093 return 0;
1094 spec->cur_eapd = eapd;
1095 snd_hda_codec_write(codec, 0x12 /* port-D */,
1096 0, AC_VERB_SET_EAPD_BTLENABLE,
1097 eapd ? 0x02 : 0x00);
1098 return 0;
1099}
1100
1101/* 6-stack mode */ 1562/* 6-stack mode */
1102static struct snd_kcontrol_new ad1988_6stack_mixers1[] = { 1563static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
1103 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 1564 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
@@ -1220,9 +1681,10 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1220 { 1681 {
1221 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1682 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1222 .name = "External Amplifier", 1683 .name = "External Amplifier",
1223 .info = ad1988_eapd_info, 1684 .info = ad198x_eapd_info,
1224 .get = ad1988_eapd_get, 1685 .get = ad198x_eapd_get,
1225 .put = ad1988_eapd_put, 1686 .put = ad198x_eapd_put,
1687 .private_value = 0x12 | (1 << 8), /* port-D, inversed */
1226 }, 1688 },
1227 1689
1228 { } /* end */ 1690 { } /* end */
@@ -1795,14 +2257,11 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
1795 2257
1796 idx = ad1988_pin_idx(pin); 2258 idx = ad1988_pin_idx(pin);
1797 nid = ad1988_idx_to_dac(codec, idx); 2259 nid = ad1988_idx_to_dac(codec, idx);
1798 if (! spec->multiout.dac_nids[0]) { 2260 /* specify the DAC as the extra output */
1799 /* use this as the primary output */ 2261 if (! spec->multiout.hp_nid)
1800 spec->multiout.dac_nids[0] = nid;
1801 if (! spec->multiout.num_dacs)
1802 spec->multiout.num_dacs = 1;
1803 } else
1804 /* specify the DAC as the extra output */
1805 spec->multiout.hp_nid = nid; 2262 spec->multiout.hp_nid = nid;
2263 else
2264 spec->multiout.extra_out_nid[0] = nid;
1806 /* control HP volume/switch on the output mixer amp */ 2265 /* control HP volume/switch on the output mixer amp */
1807 sprintf(name, "%s Playback Volume", pfx); 2266 sprintf(name, "%s Playback Volume", pfx);
1808 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, 2267 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
@@ -1921,7 +2380,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec)
1921 struct ad198x_spec *spec = codec->spec; 2380 struct ad198x_spec *spec = codec->spec;
1922 hda_nid_t pin; 2381 hda_nid_t pin;
1923 2382
1924 pin = spec->autocfg.speaker_pin; 2383 pin = spec->autocfg.speaker_pins[0];
1925 if (pin) /* connect to front */ 2384 if (pin) /* connect to front */
1926 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 2385 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
1927 pin = spec->autocfg.hp_pin; 2386 pin = spec->autocfg.hp_pin;
@@ -1970,13 +2429,13 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
1970 return err; 2429 return err;
1971 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) 2430 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
1972 return err; 2431 return err;
1973 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && 2432 if (! spec->autocfg.line_outs)
1974 ! spec->autocfg.hp_pin)
1975 return 0; /* can't find valid BIOS pin config */ 2433 return 0; /* can't find valid BIOS pin config */
1976 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || 2434 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
1977 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, 2435 (err = ad1988_auto_create_extra_out(codec,
2436 spec->autocfg.speaker_pins[0],
1978 "Speaker")) < 0 || 2437 "Speaker")) < 0 ||
1979 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, 2438 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin,
1980 "Headphone")) < 0 || 2439 "Headphone")) < 0 ||
1981 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 2440 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
1982 return err; 2441 return err;
@@ -2032,7 +2491,7 @@ static int patch_ad1988(struct hda_codec *codec)
2032 if (spec == NULL) 2491 if (spec == NULL)
2033 return -ENOMEM; 2492 return -ENOMEM;
2034 2493
2035 init_MUTEX(&spec->amp_mutex); 2494 mutex_init(&spec->amp_mutex);
2036 codec->spec = spec; 2495 codec->spec = spec;
2037 2496
2038 if (codec->revision_id == AD1988A_REV2) 2497 if (codec->revision_id == AD1988A_REV2)