diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_beep.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 437 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 19 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 255 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 166 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 35 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 210 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 12 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 368 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 61 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1197 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 1353 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 17 |
16 files changed, 2645 insertions, 1513 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 960fd7970384..4de5bacd3929 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
@@ -138,6 +138,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) | |||
138 | 138 | ||
139 | input_unregister_device(beep->dev); | 139 | input_unregister_device(beep->dev); |
140 | kfree(beep); | 140 | kfree(beep); |
141 | codec->beep = NULL; | ||
141 | } | 142 | } |
142 | } | 143 | } |
143 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); | 144 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); |
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index b9679f081cae..51bf6a5daf39 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h | |||
@@ -39,7 +39,7 @@ struct hda_beep { | |||
39 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); | 39 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); |
40 | void snd_hda_detach_beep_device(struct hda_codec *codec); | 40 | void snd_hda_detach_beep_device(struct hda_codec *codec); |
41 | #else | 41 | #else |
42 | #define snd_hda_attach_beep_device(...) | 42 | #define snd_hda_attach_beep_device(...) 0 |
43 | #define snd_hda_detach_beep_device(...) | 43 | #define snd_hda_detach_beep_device(...) |
44 | #endif | 44 | #endif |
45 | #endif | 45 | #endif |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0b708134d12f..a4e5e5952115 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -647,9 +647,9 @@ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec) | |||
647 | 647 | ||
648 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); | 648 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); |
649 | for (i = 0; i < total_nodes; i++, nid++) { | 649 | for (i = 0; i < total_nodes; i++, nid++) { |
650 | unsigned int func; | 650 | codec->function_id = snd_hda_param_read(codec, nid, |
651 | func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE); | 651 | AC_PAR_FUNCTION_TYPE) & 0xff; |
652 | switch (func & 0xff) { | 652 | switch (codec->function_id) { |
653 | case AC_GRP_AUDIO_FUNCTION: | 653 | case AC_GRP_AUDIO_FUNCTION: |
654 | codec->afg = nid; | 654 | codec->afg = nid; |
655 | break; | 655 | break; |
@@ -682,11 +682,140 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
682 | return 0; | 682 | return 0; |
683 | } | 683 | } |
684 | 684 | ||
685 | /* read all pin default configurations and save codec->init_pins */ | ||
686 | static int read_pin_defaults(struct hda_codec *codec) | ||
687 | { | ||
688 | int i; | ||
689 | hda_nid_t nid = codec->start_nid; | ||
690 | |||
691 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
692 | struct hda_pincfg *pin; | ||
693 | unsigned int wcaps = get_wcaps(codec, nid); | ||
694 | unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >> | ||
695 | AC_WCAP_TYPE_SHIFT; | ||
696 | if (wid_type != AC_WID_PIN) | ||
697 | continue; | ||
698 | pin = snd_array_new(&codec->init_pins); | ||
699 | if (!pin) | ||
700 | return -ENOMEM; | ||
701 | pin->nid = nid; | ||
702 | pin->cfg = snd_hda_codec_read(codec, nid, 0, | ||
703 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
704 | } | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | /* look up the given pin config list and return the item matching with NID */ | ||
709 | static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec, | ||
710 | struct snd_array *array, | ||
711 | hda_nid_t nid) | ||
712 | { | ||
713 | int i; | ||
714 | for (i = 0; i < array->used; i++) { | ||
715 | struct hda_pincfg *pin = snd_array_elem(array, i); | ||
716 | if (pin->nid == nid) | ||
717 | return pin; | ||
718 | } | ||
719 | return NULL; | ||
720 | } | ||
721 | |||
722 | /* write a config value for the given NID */ | ||
723 | static void set_pincfg(struct hda_codec *codec, hda_nid_t nid, | ||
724 | unsigned int cfg) | ||
725 | { | ||
726 | int i; | ||
727 | for (i = 0; i < 4; i++) { | ||
728 | snd_hda_codec_write(codec, nid, 0, | ||
729 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, | ||
730 | cfg & 0xff); | ||
731 | cfg >>= 8; | ||
732 | } | ||
733 | } | ||
734 | |||
735 | /* set the current pin config value for the given NID. | ||
736 | * the value is cached, and read via snd_hda_codec_get_pincfg() | ||
737 | */ | ||
738 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | ||
739 | hda_nid_t nid, unsigned int cfg) | ||
740 | { | ||
741 | struct hda_pincfg *pin; | ||
742 | unsigned int oldcfg; | ||
743 | |||
744 | oldcfg = snd_hda_codec_get_pincfg(codec, nid); | ||
745 | pin = look_up_pincfg(codec, list, nid); | ||
746 | if (!pin) { | ||
747 | pin = snd_array_new(list); | ||
748 | if (!pin) | ||
749 | return -ENOMEM; | ||
750 | pin->nid = nid; | ||
751 | } | ||
752 | pin->cfg = cfg; | ||
753 | |||
754 | /* change only when needed; e.g. if the pincfg is already present | ||
755 | * in user_pins[], don't write it | ||
756 | */ | ||
757 | cfg = snd_hda_codec_get_pincfg(codec, nid); | ||
758 | if (oldcfg != cfg) | ||
759 | set_pincfg(codec, nid, cfg); | ||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | int snd_hda_codec_set_pincfg(struct hda_codec *codec, | ||
764 | hda_nid_t nid, unsigned int cfg) | ||
765 | { | ||
766 | return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg); | ||
767 | } | ||
768 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg); | ||
769 | |||
770 | /* get the current pin config value of the given pin NID */ | ||
771 | unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) | ||
772 | { | ||
773 | struct hda_pincfg *pin; | ||
774 | |||
775 | #ifdef CONFIG_SND_HDA_HWDEP | ||
776 | pin = look_up_pincfg(codec, &codec->user_pins, nid); | ||
777 | if (pin) | ||
778 | return pin->cfg; | ||
779 | #endif | ||
780 | pin = look_up_pincfg(codec, &codec->driver_pins, nid); | ||
781 | if (pin) | ||
782 | return pin->cfg; | ||
783 | pin = look_up_pincfg(codec, &codec->init_pins, nid); | ||
784 | if (pin) | ||
785 | return pin->cfg; | ||
786 | return 0; | ||
787 | } | ||
788 | EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg); | ||
789 | |||
790 | /* restore all current pin configs */ | ||
791 | static void restore_pincfgs(struct hda_codec *codec) | ||
792 | { | ||
793 | int i; | ||
794 | for (i = 0; i < codec->init_pins.used; i++) { | ||
795 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
796 | set_pincfg(codec, pin->nid, | ||
797 | snd_hda_codec_get_pincfg(codec, pin->nid)); | ||
798 | } | ||
799 | } | ||
685 | 800 | ||
686 | static void init_hda_cache(struct hda_cache_rec *cache, | 801 | static void init_hda_cache(struct hda_cache_rec *cache, |
687 | unsigned int record_size); | 802 | unsigned int record_size); |
688 | static void free_hda_cache(struct hda_cache_rec *cache); | 803 | static void free_hda_cache(struct hda_cache_rec *cache); |
689 | 804 | ||
805 | /* restore the initial pin cfgs and release all pincfg lists */ | ||
806 | static void restore_init_pincfgs(struct hda_codec *codec) | ||
807 | { | ||
808 | /* first free driver_pins and user_pins, then call restore_pincfg | ||
809 | * so that only the values in init_pins are restored | ||
810 | */ | ||
811 | snd_array_free(&codec->driver_pins); | ||
812 | #ifdef CONFIG_SND_HDA_HWDEP | ||
813 | snd_array_free(&codec->user_pins); | ||
814 | #endif | ||
815 | restore_pincfgs(codec); | ||
816 | snd_array_free(&codec->init_pins); | ||
817 | } | ||
818 | |||
690 | /* | 819 | /* |
691 | * codec destructor | 820 | * codec destructor |
692 | */ | 821 | */ |
@@ -694,6 +823,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
694 | { | 823 | { |
695 | if (!codec) | 824 | if (!codec) |
696 | return; | 825 | return; |
826 | restore_init_pincfgs(codec); | ||
697 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 827 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
698 | cancel_delayed_work(&codec->power_work); | 828 | cancel_delayed_work(&codec->power_work); |
699 | flush_workqueue(codec->bus->workq); | 829 | flush_workqueue(codec->bus->workq); |
@@ -712,6 +842,9 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
712 | kfree(codec); | 842 | kfree(codec); |
713 | } | 843 | } |
714 | 844 | ||
845 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
846 | unsigned int power_state); | ||
847 | |||
715 | /** | 848 | /** |
716 | * snd_hda_codec_new - create a HDA codec | 849 | * snd_hda_codec_new - create a HDA codec |
717 | * @bus: the bus to assign | 850 | * @bus: the bus to assign |
@@ -751,6 +884,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
751 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 884 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
752 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 885 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
753 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | 886 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); |
887 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | ||
888 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | ||
754 | if (codec->bus->modelname) { | 889 | if (codec->bus->modelname) { |
755 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | 890 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); |
756 | if (!codec->modelname) { | 891 | if (!codec->modelname) { |
@@ -787,15 +922,18 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
787 | setup_fg_nodes(codec); | 922 | setup_fg_nodes(codec); |
788 | if (!codec->afg && !codec->mfg) { | 923 | if (!codec->afg && !codec->mfg) { |
789 | snd_printdd("hda_codec: no AFG or MFG node found\n"); | 924 | snd_printdd("hda_codec: no AFG or MFG node found\n"); |
790 | snd_hda_codec_free(codec); | 925 | err = -ENODEV; |
791 | return -ENODEV; | 926 | goto error; |
792 | } | 927 | } |
793 | 928 | ||
794 | if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) { | 929 | err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg); |
930 | if (err < 0) { | ||
795 | snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); | 931 | snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); |
796 | snd_hda_codec_free(codec); | 932 | goto error; |
797 | return -ENOMEM; | ||
798 | } | 933 | } |
934 | err = read_pin_defaults(codec); | ||
935 | if (err < 0) | ||
936 | goto error; | ||
799 | 937 | ||
800 | if (!codec->subsystem_id) { | 938 | if (!codec->subsystem_id) { |
801 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; | 939 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; |
@@ -806,12 +944,15 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
806 | if (bus->modelname) | 944 | if (bus->modelname) |
807 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | 945 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); |
808 | 946 | ||
947 | /* power-up all before initialization */ | ||
948 | hda_set_power_state(codec, | ||
949 | codec->afg ? codec->afg : codec->mfg, | ||
950 | AC_PWRST_D0); | ||
951 | |||
809 | if (do_init) { | 952 | if (do_init) { |
810 | err = snd_hda_codec_configure(codec); | 953 | err = snd_hda_codec_configure(codec); |
811 | if (err < 0) { | 954 | if (err < 0) |
812 | snd_hda_codec_free(codec); | 955 | goto error; |
813 | return err; | ||
814 | } | ||
815 | } | 956 | } |
816 | snd_hda_codec_proc_new(codec); | 957 | snd_hda_codec_proc_new(codec); |
817 | 958 | ||
@@ -824,6 +965,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
824 | if (codecp) | 965 | if (codecp) |
825 | *codecp = codec; | 966 | *codecp = codec; |
826 | return 0; | 967 | return 0; |
968 | |||
969 | error: | ||
970 | snd_hda_codec_free(codec); | ||
971 | return err; | ||
827 | } | 972 | } |
828 | EXPORT_SYMBOL_HDA(snd_hda_codec_new); | 973 | EXPORT_SYMBOL_HDA(snd_hda_codec_new); |
829 | 974 | ||
@@ -907,6 +1052,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | |||
907 | 1052 | ||
908 | /* FIXME: more better hash key? */ | 1053 | /* FIXME: more better hash key? */ |
909 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | 1054 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) |
1055 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | ||
910 | #define INFO_AMP_CAPS (1<<0) | 1056 | #define INFO_AMP_CAPS (1<<0) |
911 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | 1057 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
912 | 1058 | ||
@@ -997,6 +1143,21 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
997 | } | 1143 | } |
998 | EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); | 1144 | EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); |
999 | 1145 | ||
1146 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | ||
1147 | { | ||
1148 | struct hda_amp_info *info; | ||
1149 | |||
1150 | info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid)); | ||
1151 | if (!info) | ||
1152 | return 0; | ||
1153 | if (!info->head.val) { | ||
1154 | info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1155 | info->head.val |= INFO_AMP_CAPS; | ||
1156 | } | ||
1157 | return info->amp_caps; | ||
1158 | } | ||
1159 | EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); | ||
1160 | |||
1000 | /* | 1161 | /* |
1001 | * read the current volume to info | 1162 | * read the current volume to info |
1002 | * if the cache exists, read the cache value. | 1163 | * if the cache exists, read the cache value. |
@@ -1120,6 +1281,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1120 | u16 nid = get_amp_nid(kcontrol); | 1281 | u16 nid = get_amp_nid(kcontrol); |
1121 | u8 chs = get_amp_channels(kcontrol); | 1282 | u8 chs = get_amp_channels(kcontrol); |
1122 | int dir = get_amp_direction(kcontrol); | 1283 | int dir = get_amp_direction(kcontrol); |
1284 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1123 | u32 caps; | 1285 | u32 caps; |
1124 | 1286 | ||
1125 | caps = query_amp_caps(codec, nid, dir); | 1287 | caps = query_amp_caps(codec, nid, dir); |
@@ -1131,6 +1293,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1131 | kcontrol->id.name); | 1293 | kcontrol->id.name); |
1132 | return -EINVAL; | 1294 | return -EINVAL; |
1133 | } | 1295 | } |
1296 | if (ofs < caps) | ||
1297 | caps -= ofs; | ||
1134 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1298 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1135 | uinfo->count = chs == 3 ? 2 : 1; | 1299 | uinfo->count = chs == 3 ? 2 : 1; |
1136 | uinfo->value.integer.min = 0; | 1300 | uinfo->value.integer.min = 0; |
@@ -1139,6 +1303,32 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1139 | } | 1303 | } |
1140 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); | 1304 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); |
1141 | 1305 | ||
1306 | |||
1307 | static inline unsigned int | ||
1308 | read_amp_value(struct hda_codec *codec, hda_nid_t nid, | ||
1309 | int ch, int dir, int idx, unsigned int ofs) | ||
1310 | { | ||
1311 | unsigned int val; | ||
1312 | val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx); | ||
1313 | val &= HDA_AMP_VOLMASK; | ||
1314 | if (val >= ofs) | ||
1315 | val -= ofs; | ||
1316 | else | ||
1317 | val = 0; | ||
1318 | return val; | ||
1319 | } | ||
1320 | |||
1321 | static inline int | ||
1322 | update_amp_value(struct hda_codec *codec, hda_nid_t nid, | ||
1323 | int ch, int dir, int idx, unsigned int ofs, | ||
1324 | unsigned int val) | ||
1325 | { | ||
1326 | if (val > 0) | ||
1327 | val += ofs; | ||
1328 | return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, | ||
1329 | HDA_AMP_VOLMASK, val); | ||
1330 | } | ||
1331 | |||
1142 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | 1332 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, |
1143 | struct snd_ctl_elem_value *ucontrol) | 1333 | struct snd_ctl_elem_value *ucontrol) |
1144 | { | 1334 | { |
@@ -1147,14 +1337,13 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | |||
1147 | int chs = get_amp_channels(kcontrol); | 1337 | int chs = get_amp_channels(kcontrol); |
1148 | int dir = get_amp_direction(kcontrol); | 1338 | int dir = get_amp_direction(kcontrol); |
1149 | int idx = get_amp_index(kcontrol); | 1339 | int idx = get_amp_index(kcontrol); |
1340 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1150 | long *valp = ucontrol->value.integer.value; | 1341 | long *valp = ucontrol->value.integer.value; |
1151 | 1342 | ||
1152 | if (chs & 1) | 1343 | if (chs & 1) |
1153 | *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) | 1344 | *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs); |
1154 | & HDA_AMP_VOLMASK; | ||
1155 | if (chs & 2) | 1345 | if (chs & 2) |
1156 | *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) | 1346 | *valp = read_amp_value(codec, nid, 1, dir, idx, ofs); |
1157 | & HDA_AMP_VOLMASK; | ||
1158 | return 0; | 1347 | return 0; |
1159 | } | 1348 | } |
1160 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); | 1349 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); |
@@ -1167,18 +1356,17 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
1167 | int chs = get_amp_channels(kcontrol); | 1356 | int chs = get_amp_channels(kcontrol); |
1168 | int dir = get_amp_direction(kcontrol); | 1357 | int dir = get_amp_direction(kcontrol); |
1169 | int idx = get_amp_index(kcontrol); | 1358 | int idx = get_amp_index(kcontrol); |
1359 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1170 | long *valp = ucontrol->value.integer.value; | 1360 | long *valp = ucontrol->value.integer.value; |
1171 | int change = 0; | 1361 | int change = 0; |
1172 | 1362 | ||
1173 | snd_hda_power_up(codec); | 1363 | snd_hda_power_up(codec); |
1174 | if (chs & 1) { | 1364 | if (chs & 1) { |
1175 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 1365 | change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); |
1176 | 0x7f, *valp); | ||
1177 | valp++; | 1366 | valp++; |
1178 | } | 1367 | } |
1179 | if (chs & 2) | 1368 | if (chs & 2) |
1180 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 1369 | change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); |
1181 | 0x7f, *valp); | ||
1182 | snd_hda_power_down(codec); | 1370 | snd_hda_power_down(codec); |
1183 | return change; | 1371 | return change; |
1184 | } | 1372 | } |
@@ -1190,6 +1378,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1190 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1378 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1191 | hda_nid_t nid = get_amp_nid(kcontrol); | 1379 | hda_nid_t nid = get_amp_nid(kcontrol); |
1192 | int dir = get_amp_direction(kcontrol); | 1380 | int dir = get_amp_direction(kcontrol); |
1381 | unsigned int ofs = get_amp_offset(kcontrol); | ||
1193 | u32 caps, val1, val2; | 1382 | u32 caps, val1, val2; |
1194 | 1383 | ||
1195 | if (size < 4 * sizeof(unsigned int)) | 1384 | if (size < 4 * sizeof(unsigned int)) |
@@ -1198,6 +1387,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1198 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; | 1387 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; |
1199 | val2 = (val2 + 1) * 25; | 1388 | val2 = (val2 + 1) * 25; |
1200 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 1389 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
1390 | val1 += ofs; | ||
1201 | val1 = ((int)val1) * ((int)val2); | 1391 | val1 = ((int)val1) * ((int)val2); |
1202 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 1392 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
1203 | return -EFAULT; | 1393 | return -EFAULT; |
@@ -1268,7 +1458,6 @@ int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | |||
1268 | } | 1458 | } |
1269 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); | 1459 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); |
1270 | 1460 | ||
1271 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
1272 | /* Clear all controls assigned to the given codec */ | 1461 | /* Clear all controls assigned to the given codec */ |
1273 | void snd_hda_ctls_clear(struct hda_codec *codec) | 1462 | void snd_hda_ctls_clear(struct hda_codec *codec) |
1274 | { | 1463 | { |
@@ -1279,9 +1468,52 @@ void snd_hda_ctls_clear(struct hda_codec *codec) | |||
1279 | snd_array_free(&codec->mixers); | 1468 | snd_array_free(&codec->mixers); |
1280 | } | 1469 | } |
1281 | 1470 | ||
1282 | void snd_hda_codec_reset(struct hda_codec *codec) | 1471 | /* pseudo device locking |
1472 | * toggle card->shutdown to allow/disallow the device access (as a hack) | ||
1473 | */ | ||
1474 | static int hda_lock_devices(struct snd_card *card) | ||
1283 | { | 1475 | { |
1284 | int i; | 1476 | spin_lock(&card->files_lock); |
1477 | if (card->shutdown) { | ||
1478 | spin_unlock(&card->files_lock); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | card->shutdown = 1; | ||
1482 | spin_unlock(&card->files_lock); | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | static void hda_unlock_devices(struct snd_card *card) | ||
1487 | { | ||
1488 | spin_lock(&card->files_lock); | ||
1489 | card->shutdown = 0; | ||
1490 | spin_unlock(&card->files_lock); | ||
1491 | } | ||
1492 | |||
1493 | int snd_hda_codec_reset(struct hda_codec *codec) | ||
1494 | { | ||
1495 | struct snd_card *card = codec->bus->card; | ||
1496 | int i, pcm; | ||
1497 | |||
1498 | if (hda_lock_devices(card) < 0) | ||
1499 | return -EBUSY; | ||
1500 | /* check whether the codec isn't used by any mixer or PCM streams */ | ||
1501 | if (!list_empty(&card->ctl_files)) { | ||
1502 | hda_unlock_devices(card); | ||
1503 | return -EBUSY; | ||
1504 | } | ||
1505 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | ||
1506 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; | ||
1507 | if (!cpcm->pcm) | ||
1508 | continue; | ||
1509 | if (cpcm->pcm->streams[0].substream_opened || | ||
1510 | cpcm->pcm->streams[1].substream_opened) { | ||
1511 | hda_unlock_devices(card); | ||
1512 | return -EBUSY; | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | /* OK, let it free */ | ||
1285 | 1517 | ||
1286 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1518 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1287 | cancel_delayed_work(&codec->power_work); | 1519 | cancel_delayed_work(&codec->power_work); |
@@ -1291,8 +1523,7 @@ void snd_hda_codec_reset(struct hda_codec *codec) | |||
1291 | /* relase PCMs */ | 1523 | /* relase PCMs */ |
1292 | for (i = 0; i < codec->num_pcms; i++) { | 1524 | for (i = 0; i < codec->num_pcms; i++) { |
1293 | if (codec->pcm_info[i].pcm) { | 1525 | if (codec->pcm_info[i].pcm) { |
1294 | snd_device_free(codec->bus->card, | 1526 | snd_device_free(card, codec->pcm_info[i].pcm); |
1295 | codec->pcm_info[i].pcm); | ||
1296 | clear_bit(codec->pcm_info[i].device, | 1527 | clear_bit(codec->pcm_info[i].device, |
1297 | codec->bus->pcm_dev_bits); | 1528 | codec->bus->pcm_dev_bits); |
1298 | } | 1529 | } |
@@ -1305,13 +1536,22 @@ void snd_hda_codec_reset(struct hda_codec *codec) | |||
1305 | free_hda_cache(&codec->cmd_cache); | 1536 | free_hda_cache(&codec->cmd_cache); |
1306 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 1537 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
1307 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1538 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
1539 | /* free only driver_pins so that init_pins + user_pins are restored */ | ||
1540 | snd_array_free(&codec->driver_pins); | ||
1541 | restore_pincfgs(codec); | ||
1308 | codec->num_pcms = 0; | 1542 | codec->num_pcms = 0; |
1309 | codec->pcm_info = NULL; | 1543 | codec->pcm_info = NULL; |
1310 | codec->preset = NULL; | 1544 | codec->preset = NULL; |
1545 | memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); | ||
1546 | codec->slave_dig_outs = NULL; | ||
1547 | codec->spdif_status_reset = 0; | ||
1311 | module_put(codec->owner); | 1548 | module_put(codec->owner); |
1312 | codec->owner = NULL; | 1549 | codec->owner = NULL; |
1550 | |||
1551 | /* allow device access again */ | ||
1552 | hda_unlock_devices(card); | ||
1553 | return 0; | ||
1313 | } | 1554 | } |
1314 | #endif /* CONFIG_SND_HDA_RECONFIG */ | ||
1315 | 1555 | ||
1316 | /* create a virtual master control and add slaves */ | 1556 | /* create a virtual master control and add slaves */ |
1317 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1557 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
@@ -1336,15 +1576,20 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1336 | 1576 | ||
1337 | for (s = slaves; *s; s++) { | 1577 | for (s = slaves; *s; s++) { |
1338 | struct snd_kcontrol *sctl; | 1578 | struct snd_kcontrol *sctl; |
1339 | 1579 | int i = 0; | |
1340 | sctl = snd_hda_find_mixer_ctl(codec, *s); | 1580 | for (;;) { |
1341 | if (!sctl) { | 1581 | sctl = _snd_hda_find_mixer_ctl(codec, *s, i); |
1342 | snd_printdd("Cannot find slave %s, skipped\n", *s); | 1582 | if (!sctl) { |
1343 | continue; | 1583 | if (!i) |
1584 | snd_printdd("Cannot find slave %s, " | ||
1585 | "skipped\n", *s); | ||
1586 | break; | ||
1587 | } | ||
1588 | err = snd_ctl_add_slave(kctl, sctl); | ||
1589 | if (err < 0) | ||
1590 | return err; | ||
1591 | i++; | ||
1344 | } | 1592 | } |
1345 | err = snd_ctl_add_slave(kctl, sctl); | ||
1346 | if (err < 0) | ||
1347 | return err; | ||
1348 | } | 1593 | } |
1349 | return 0; | 1594 | return 0; |
1350 | } | 1595 | } |
@@ -1955,6 +2200,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1955 | } | 2200 | } |
1956 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 2201 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1957 | kctl = snd_ctl_new1(dig_mix, codec); | 2202 | kctl = snd_ctl_new1(dig_mix, codec); |
2203 | if (!kctl) | ||
2204 | return -ENOMEM; | ||
1958 | kctl->private_value = nid; | 2205 | kctl->private_value = nid; |
1959 | err = snd_hda_ctl_add(codec, kctl); | 2206 | err = snd_hda_ctl_add(codec, kctl); |
1960 | if (err < 0) | 2207 | if (err < 0) |
@@ -2074,8 +2321,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
2074 | * don't power down the widget if it controls | 2321 | * don't power down the widget if it controls |
2075 | * eapd and EAPD_BTLENABLE is set. | 2322 | * eapd and EAPD_BTLENABLE is set. |
2076 | */ | 2323 | */ |
2077 | pincap = snd_hda_param_read(codec, nid, | 2324 | pincap = snd_hda_query_pin_caps(codec, nid); |
2078 | AC_PAR_PIN_CAP); | ||
2079 | if (pincap & AC_PINCAP_EAPD) { | 2325 | if (pincap & AC_PINCAP_EAPD) { |
2080 | int eapd = snd_hda_codec_read(codec, | 2326 | int eapd = snd_hda_codec_read(codec, |
2081 | nid, 0, | 2327 | nid, 0, |
@@ -2144,6 +2390,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
2144 | hda_set_power_state(codec, | 2390 | hda_set_power_state(codec, |
2145 | codec->afg ? codec->afg : codec->mfg, | 2391 | codec->afg ? codec->afg : codec->mfg, |
2146 | AC_PWRST_D0); | 2392 | AC_PWRST_D0); |
2393 | restore_pincfgs(codec); /* restore all current pin configs */ | ||
2147 | hda_exec_init_verbs(codec); | 2394 | hda_exec_init_verbs(codec); |
2148 | if (codec->patch_ops.resume) | 2395 | if (codec->patch_ops.resume) |
2149 | codec->patch_ops.resume(codec); | 2396 | codec->patch_ops.resume(codec); |
@@ -2171,8 +2418,16 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
2171 | 2418 | ||
2172 | list_for_each_entry(codec, &bus->codec_list, list) { | 2419 | list_for_each_entry(codec, &bus->codec_list, list) { |
2173 | int err = snd_hda_codec_build_controls(codec); | 2420 | int err = snd_hda_codec_build_controls(codec); |
2174 | if (err < 0) | 2421 | if (err < 0) { |
2175 | return err; | 2422 | printk(KERN_ERR "hda_codec: cannot build controls" |
2423 | "for #%d (error %d)\n", codec->addr, err); | ||
2424 | err = snd_hda_codec_reset(codec); | ||
2425 | if (err < 0) { | ||
2426 | printk(KERN_ERR | ||
2427 | "hda_codec: cannot revert codec\n"); | ||
2428 | return err; | ||
2429 | } | ||
2430 | } | ||
2176 | } | 2431 | } |
2177 | return 0; | 2432 | return 0; |
2178 | } | 2433 | } |
@@ -2181,19 +2436,12 @@ EXPORT_SYMBOL_HDA(snd_hda_build_controls); | |||
2181 | int snd_hda_codec_build_controls(struct hda_codec *codec) | 2436 | int snd_hda_codec_build_controls(struct hda_codec *codec) |
2182 | { | 2437 | { |
2183 | int err = 0; | 2438 | int err = 0; |
2184 | /* fake as if already powered-on */ | ||
2185 | hda_keep_power_on(codec); | ||
2186 | /* then fire up */ | ||
2187 | hda_set_power_state(codec, | ||
2188 | codec->afg ? codec->afg : codec->mfg, | ||
2189 | AC_PWRST_D0); | ||
2190 | hda_exec_init_verbs(codec); | 2439 | hda_exec_init_verbs(codec); |
2191 | /* continue to initialize... */ | 2440 | /* continue to initialize... */ |
2192 | if (codec->patch_ops.init) | 2441 | if (codec->patch_ops.init) |
2193 | err = codec->patch_ops.init(codec); | 2442 | err = codec->patch_ops.init(codec); |
2194 | if (!err && codec->patch_ops.build_controls) | 2443 | if (!err && codec->patch_ops.build_controls) |
2195 | err = codec->patch_ops.build_controls(codec); | 2444 | err = codec->patch_ops.build_controls(codec); |
2196 | snd_hda_power_down(codec); | ||
2197 | if (err < 0) | 2445 | if (err < 0) |
2198 | return err; | 2446 | return err; |
2199 | return 0; | 2447 | return 0; |
@@ -2306,12 +2554,11 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); | |||
2306 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 2554 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
2307 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) | 2555 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) |
2308 | { | 2556 | { |
2309 | int i; | 2557 | unsigned int i, val, wcaps; |
2310 | unsigned int val, streams; | ||
2311 | 2558 | ||
2312 | val = 0; | 2559 | val = 0; |
2313 | if (nid != codec->afg && | 2560 | wcaps = get_wcaps(codec, nid); |
2314 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { | 2561 | if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) { |
2315 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | 2562 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); |
2316 | if (val == -1) | 2563 | if (val == -1) |
2317 | return -EIO; | 2564 | return -EIO; |
@@ -2325,15 +2572,20 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2325 | if (val & (1 << i)) | 2572 | if (val & (1 << i)) |
2326 | rates |= rate_bits[i].alsa_bits; | 2573 | rates |= rate_bits[i].alsa_bits; |
2327 | } | 2574 | } |
2575 | if (rates == 0) { | ||
2576 | snd_printk(KERN_ERR "hda_codec: rates == 0 " | ||
2577 | "(nid=0x%x, val=0x%x, ovrd=%i)\n", | ||
2578 | nid, val, | ||
2579 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); | ||
2580 | return -EIO; | ||
2581 | } | ||
2328 | *ratesp = rates; | 2582 | *ratesp = rates; |
2329 | } | 2583 | } |
2330 | 2584 | ||
2331 | if (formatsp || bpsp) { | 2585 | if (formatsp || bpsp) { |
2332 | u64 formats = 0; | 2586 | u64 formats = 0; |
2333 | unsigned int bps; | 2587 | unsigned int streams, bps; |
2334 | unsigned int wcaps; | ||
2335 | 2588 | ||
2336 | wcaps = get_wcaps(codec, nid); | ||
2337 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 2589 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
2338 | if (streams == -1) | 2590 | if (streams == -1) |
2339 | return -EIO; | 2591 | return -EIO; |
@@ -2386,6 +2638,15 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2386 | formats |= SNDRV_PCM_FMTBIT_U8; | 2638 | formats |= SNDRV_PCM_FMTBIT_U8; |
2387 | bps = 8; | 2639 | bps = 8; |
2388 | } | 2640 | } |
2641 | if (formats == 0) { | ||
2642 | snd_printk(KERN_ERR "hda_codec: formats == 0 " | ||
2643 | "(nid=0x%x, val=0x%x, ovrd=%i, " | ||
2644 | "streams=0x%x)\n", | ||
2645 | nid, val, | ||
2646 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, | ||
2647 | streams); | ||
2648 | return -EIO; | ||
2649 | } | ||
2389 | if (formatsp) | 2650 | if (formatsp) |
2390 | *formatsp = formats; | 2651 | *formatsp = formats; |
2391 | if (bpsp) | 2652 | if (bpsp) |
@@ -2501,12 +2762,16 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2501 | static int set_pcm_default_values(struct hda_codec *codec, | 2762 | static int set_pcm_default_values(struct hda_codec *codec, |
2502 | struct hda_pcm_stream *info) | 2763 | struct hda_pcm_stream *info) |
2503 | { | 2764 | { |
2765 | int err; | ||
2766 | |||
2504 | /* query support PCM information from the given NID */ | 2767 | /* query support PCM information from the given NID */ |
2505 | if (info->nid && (!info->rates || !info->formats)) { | 2768 | if (info->nid && (!info->rates || !info->formats)) { |
2506 | snd_hda_query_supported_pcm(codec, info->nid, | 2769 | err = snd_hda_query_supported_pcm(codec, info->nid, |
2507 | info->rates ? NULL : &info->rates, | 2770 | info->rates ? NULL : &info->rates, |
2508 | info->formats ? NULL : &info->formats, | 2771 | info->formats ? NULL : &info->formats, |
2509 | info->maxbps ? NULL : &info->maxbps); | 2772 | info->maxbps ? NULL : &info->maxbps); |
2773 | if (err < 0) | ||
2774 | return err; | ||
2510 | } | 2775 | } |
2511 | if (info->ops.open == NULL) | 2776 | if (info->ops.open == NULL) |
2512 | info->ops.open = hda_pcm_default_open_close; | 2777 | info->ops.open = hda_pcm_default_open_close; |
@@ -2549,13 +2814,10 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
2549 | for (i = 0; i < ARRAY_SIZE(audio_idx); i++) { | 2814 | for (i = 0; i < ARRAY_SIZE(audio_idx); i++) { |
2550 | dev = audio_idx[i]; | 2815 | dev = audio_idx[i]; |
2551 | if (!test_bit(dev, bus->pcm_dev_bits)) | 2816 | if (!test_bit(dev, bus->pcm_dev_bits)) |
2552 | break; | 2817 | goto ok; |
2553 | } | ||
2554 | if (i >= ARRAY_SIZE(audio_idx)) { | ||
2555 | snd_printk(KERN_WARNING "Too many audio devices\n"); | ||
2556 | return -EAGAIN; | ||
2557 | } | 2818 | } |
2558 | break; | 2819 | snd_printk(KERN_WARNING "Too many audio devices\n"); |
2820 | return -EAGAIN; | ||
2559 | case HDA_PCM_TYPE_SPDIF: | 2821 | case HDA_PCM_TYPE_SPDIF: |
2560 | case HDA_PCM_TYPE_HDMI: | 2822 | case HDA_PCM_TYPE_HDMI: |
2561 | case HDA_PCM_TYPE_MODEM: | 2823 | case HDA_PCM_TYPE_MODEM: |
@@ -2570,6 +2832,7 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
2570 | snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); | 2832 | snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); |
2571 | return -EINVAL; | 2833 | return -EINVAL; |
2572 | } | 2834 | } |
2835 | ok: | ||
2573 | set_bit(dev, bus->pcm_dev_bits); | 2836 | set_bit(dev, bus->pcm_dev_bits); |
2574 | return dev; | 2837 | return dev; |
2575 | } | 2838 | } |
@@ -2606,24 +2869,36 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
2606 | if (!codec->patch_ops.build_pcms) | 2869 | if (!codec->patch_ops.build_pcms) |
2607 | return 0; | 2870 | return 0; |
2608 | err = codec->patch_ops.build_pcms(codec); | 2871 | err = codec->patch_ops.build_pcms(codec); |
2609 | if (err < 0) | 2872 | if (err < 0) { |
2610 | return err; | 2873 | printk(KERN_ERR "hda_codec: cannot build PCMs" |
2874 | "for #%d (error %d)\n", codec->addr, err); | ||
2875 | err = snd_hda_codec_reset(codec); | ||
2876 | if (err < 0) { | ||
2877 | printk(KERN_ERR | ||
2878 | "hda_codec: cannot revert codec\n"); | ||
2879 | return err; | ||
2880 | } | ||
2881 | } | ||
2611 | } | 2882 | } |
2612 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2883 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2613 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; | 2884 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2614 | int dev; | 2885 | int dev; |
2615 | 2886 | ||
2616 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | 2887 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) |
2617 | return 0; /* no substreams assigned */ | 2888 | continue; /* no substreams assigned */ |
2618 | 2889 | ||
2619 | if (!cpcm->pcm) { | 2890 | if (!cpcm->pcm) { |
2620 | dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); | 2891 | dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); |
2621 | if (dev < 0) | 2892 | if (dev < 0) |
2622 | return 0; | 2893 | continue; /* no fatal error */ |
2623 | cpcm->device = dev; | 2894 | cpcm->device = dev; |
2624 | err = snd_hda_attach_pcm(codec, cpcm); | 2895 | err = snd_hda_attach_pcm(codec, cpcm); |
2625 | if (err < 0) | 2896 | if (err < 0) { |
2626 | return err; | 2897 | printk(KERN_ERR "hda_codec: cannot attach " |
2898 | "PCM stream %d for codec #%d\n", | ||
2899 | dev, codec->addr); | ||
2900 | continue; /* no fatal error */ | ||
2901 | } | ||
2627 | } | 2902 | } |
2628 | } | 2903 | } |
2629 | return 0; | 2904 | return 0; |
@@ -3088,6 +3363,16 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | |||
3088 | } | 3363 | } |
3089 | EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare); | 3364 | EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare); |
3090 | 3365 | ||
3366 | int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec, | ||
3367 | struct hda_multi_out *mout) | ||
3368 | { | ||
3369 | mutex_lock(&codec->spdif_mutex); | ||
3370 | cleanup_dig_out_stream(codec, mout->dig_out_nid); | ||
3371 | mutex_unlock(&codec->spdif_mutex); | ||
3372 | return 0; | ||
3373 | } | ||
3374 | EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup); | ||
3375 | |||
3091 | /* | 3376 | /* |
3092 | * release the digital out | 3377 | * release the digital out |
3093 | */ | 3378 | */ |
@@ -3314,8 +3599,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3314 | if (ignore_nids && is_in_nid_list(nid, ignore_nids)) | 3599 | if (ignore_nids && is_in_nid_list(nid, ignore_nids)) |
3315 | continue; | 3600 | continue; |
3316 | 3601 | ||
3317 | def_conf = snd_hda_codec_read(codec, nid, 0, | 3602 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
3318 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3319 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 3603 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
3320 | continue; | 3604 | continue; |
3321 | loc = get_defcfg_location(def_conf); | 3605 | loc = get_defcfg_location(def_conf); |
@@ -3391,10 +3675,22 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3391 | cfg->input_pins[AUTO_PIN_AUX] = nid; | 3675 | cfg->input_pins[AUTO_PIN_AUX] = nid; |
3392 | break; | 3676 | break; |
3393 | case AC_JACK_SPDIF_OUT: | 3677 | case AC_JACK_SPDIF_OUT: |
3394 | cfg->dig_out_pin = nid; | 3678 | case AC_JACK_DIG_OTHER_OUT: |
3679 | if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) | ||
3680 | continue; | ||
3681 | cfg->dig_out_pins[cfg->dig_outs] = nid; | ||
3682 | cfg->dig_out_type[cfg->dig_outs] = | ||
3683 | (loc == AC_JACK_LOC_HDMI) ? | ||
3684 | HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF; | ||
3685 | cfg->dig_outs++; | ||
3395 | break; | 3686 | break; |
3396 | case AC_JACK_SPDIF_IN: | 3687 | case AC_JACK_SPDIF_IN: |
3688 | case AC_JACK_DIG_OTHER_IN: | ||
3397 | cfg->dig_in_pin = nid; | 3689 | cfg->dig_in_pin = nid; |
3690 | if (loc == AC_JACK_LOC_HDMI) | ||
3691 | cfg->dig_in_type = HDA_PCM_TYPE_HDMI; | ||
3692 | else | ||
3693 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; | ||
3398 | break; | 3694 | break; |
3399 | } | 3695 | } |
3400 | } | 3696 | } |
@@ -3500,6 +3796,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3500 | cfg->hp_pins[1], cfg->hp_pins[2], | 3796 | cfg->hp_pins[1], cfg->hp_pins[2], |
3501 | cfg->hp_pins[3], cfg->hp_pins[4]); | 3797 | cfg->hp_pins[3], cfg->hp_pins[4]); |
3502 | snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); | 3798 | snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); |
3799 | if (cfg->dig_outs) | ||
3800 | snd_printd(" dig-out=0x%x/0x%x\n", | ||
3801 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); | ||
3503 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 3802 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
3504 | " cd=0x%x, aux=0x%x\n", | 3803 | " cd=0x%x, aux=0x%x\n", |
3505 | cfg->input_pins[AUTO_PIN_MIC], | 3804 | cfg->input_pins[AUTO_PIN_MIC], |
@@ -3508,6 +3807,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3508 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | 3807 | cfg->input_pins[AUTO_PIN_FRONT_LINE], |
3509 | cfg->input_pins[AUTO_PIN_CD], | 3808 | cfg->input_pins[AUTO_PIN_CD], |
3510 | cfg->input_pins[AUTO_PIN_AUX]); | 3809 | cfg->input_pins[AUTO_PIN_AUX]); |
3810 | if (cfg->dig_in_pin) | ||
3811 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); | ||
3511 | 3812 | ||
3512 | return 0; | 3813 | return 0; |
3513 | } | 3814 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 09a332ada0c6..2fdecf4b0eb6 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -739,6 +739,7 @@ struct hda_codec { | |||
739 | hda_nid_t mfg; /* MFG node id */ | 739 | hda_nid_t mfg; /* MFG node id */ |
740 | 740 | ||
741 | /* ids */ | 741 | /* ids */ |
742 | u32 function_id; | ||
742 | u32 vendor_id; | 743 | u32 vendor_id; |
743 | u32 subsystem_id; | 744 | u32 subsystem_id; |
744 | u32 revision_id; | 745 | u32 revision_id; |
@@ -778,11 +779,14 @@ struct hda_codec { | |||
778 | unsigned short spdif_ctls; /* SPDIF control bits */ | 779 | unsigned short spdif_ctls; /* SPDIF control bits */ |
779 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 780 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
780 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 781 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
782 | struct snd_array init_pins; /* initial (BIOS) pin configurations */ | ||
783 | struct snd_array driver_pins; /* pin configs set by codec parser */ | ||
781 | 784 | ||
782 | #ifdef CONFIG_SND_HDA_HWDEP | 785 | #ifdef CONFIG_SND_HDA_HWDEP |
783 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 786 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
784 | struct snd_array init_verbs; /* additional init verbs */ | 787 | struct snd_array init_verbs; /* additional init verbs */ |
785 | struct snd_array hints; /* additional hints */ | 788 | struct snd_array hints; /* additional hints */ |
789 | struct snd_array user_pins; /* default pin configs to override */ | ||
786 | #endif | 790 | #endif |
787 | 791 | ||
788 | /* misc flags */ | 792 | /* misc flags */ |
@@ -790,6 +794,9 @@ struct hda_codec { | |||
790 | * status change | 794 | * status change |
791 | * (e.g. Realtek codecs) | 795 | * (e.g. Realtek codecs) |
792 | */ | 796 | */ |
797 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index | ||
798 | * (e.g. Conexant codecs) | ||
799 | */ | ||
793 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 800 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
794 | unsigned int power_on :1; /* current (global) power-state */ | 801 | unsigned int power_on :1; /* current (global) power-state */ |
795 | unsigned int power_transition :1; /* power-state in transition */ | 802 | unsigned int power_transition :1; /* power-state in transition */ |
@@ -855,6 +862,18 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); | |||
855 | #define snd_hda_sequence_write_cache snd_hda_sequence_write | 862 | #define snd_hda_sequence_write_cache snd_hda_sequence_write |
856 | #endif | 863 | #endif |
857 | 864 | ||
865 | /* the struct for codec->pin_configs */ | ||
866 | struct hda_pincfg { | ||
867 | hda_nid_t nid; | ||
868 | unsigned int cfg; | ||
869 | }; | ||
870 | |||
871 | unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid); | ||
872 | int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid, | ||
873 | unsigned int cfg); | ||
874 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | ||
875 | hda_nid_t nid, unsigned int cfg); /* for hwdep */ | ||
876 | |||
858 | /* | 877 | /* |
859 | * Mixer | 878 | * Mixer |
860 | */ | 879 | */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 65745e96dc70..1d5797a96682 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -144,9 +144,9 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid | |||
144 | node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 144 | node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
145 | 145 | ||
146 | if (node->type == AC_WID_PIN) { | 146 | if (node->type == AC_WID_PIN) { |
147 | node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP); | 147 | node->pin_caps = snd_hda_query_pin_caps(codec, node->nid); |
148 | node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 148 | node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
149 | node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 149 | node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid); |
150 | } | 150 | } |
151 | 151 | ||
152 | if (node->wid_caps & AC_WCAP_OUT_AMP) { | 152 | if (node->wid_caps & AC_WCAP_OUT_AMP) { |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 300ab407cf42..1c57505c2874 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -30,6 +30,12 @@ | |||
30 | #include <sound/hda_hwdep.h> | 30 | #include <sound/hda_hwdep.h> |
31 | #include <sound/minors.h> | 31 | #include <sound/minors.h> |
32 | 32 | ||
33 | /* hint string pair */ | ||
34 | struct hda_hint { | ||
35 | const char *key; | ||
36 | const char *val; /* contained in the same alloc as key */ | ||
37 | }; | ||
38 | |||
33 | /* | 39 | /* |
34 | * write/read an out-of-bound verb | 40 | * write/read an out-of-bound verb |
35 | */ | 41 | */ |
@@ -99,16 +105,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
99 | 105 | ||
100 | static void clear_hwdep_elements(struct hda_codec *codec) | 106 | static void clear_hwdep_elements(struct hda_codec *codec) |
101 | { | 107 | { |
102 | char **head; | ||
103 | int i; | 108 | int i; |
104 | 109 | ||
105 | /* clear init verbs */ | 110 | /* clear init verbs */ |
106 | snd_array_free(&codec->init_verbs); | 111 | snd_array_free(&codec->init_verbs); |
107 | /* clear hints */ | 112 | /* clear hints */ |
108 | head = codec->hints.list; | 113 | for (i = 0; i < codec->hints.used; i++) { |
109 | for (i = 0; i < codec->hints.used; i++, head++) | 114 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); |
110 | kfree(*head); | 115 | kfree(hint->key); /* we don't need to free hint->val */ |
116 | } | ||
111 | snd_array_free(&codec->hints); | 117 | snd_array_free(&codec->hints); |
118 | snd_array_free(&codec->user_pins); | ||
112 | } | 119 | } |
113 | 120 | ||
114 | static void hwdep_free(struct snd_hwdep *hwdep) | 121 | static void hwdep_free(struct snd_hwdep *hwdep) |
@@ -140,7 +147,8 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) | |||
140 | #endif | 147 | #endif |
141 | 148 | ||
142 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | 149 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); |
143 | snd_array_init(&codec->hints, sizeof(char *), 32); | 150 | snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); |
151 | snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); | ||
144 | 152 | ||
145 | return 0; | 153 | return 0; |
146 | } | 154 | } |
@@ -153,7 +161,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) | |||
153 | 161 | ||
154 | static int clear_codec(struct hda_codec *codec) | 162 | static int clear_codec(struct hda_codec *codec) |
155 | { | 163 | { |
156 | snd_hda_codec_reset(codec); | 164 | int err; |
165 | |||
166 | err = snd_hda_codec_reset(codec); | ||
167 | if (err < 0) { | ||
168 | snd_printk(KERN_ERR "The codec is being used, can't free.\n"); | ||
169 | return err; | ||
170 | } | ||
157 | clear_hwdep_elements(codec); | 171 | clear_hwdep_elements(codec); |
158 | return 0; | 172 | return 0; |
159 | } | 173 | } |
@@ -162,20 +176,29 @@ static int reconfig_codec(struct hda_codec *codec) | |||
162 | { | 176 | { |
163 | int err; | 177 | int err; |
164 | 178 | ||
179 | snd_hda_power_up(codec); | ||
165 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); | 180 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); |
166 | snd_hda_codec_reset(codec); | 181 | err = snd_hda_codec_reset(codec); |
182 | if (err < 0) { | ||
183 | snd_printk(KERN_ERR | ||
184 | "The codec is being used, can't reconfigure.\n"); | ||
185 | goto error; | ||
186 | } | ||
167 | err = snd_hda_codec_configure(codec); | 187 | err = snd_hda_codec_configure(codec); |
168 | if (err < 0) | 188 | if (err < 0) |
169 | return err; | 189 | goto error; |
170 | /* rebuild PCMs */ | 190 | /* rebuild PCMs */ |
171 | err = snd_hda_codec_build_pcms(codec); | 191 | err = snd_hda_codec_build_pcms(codec); |
172 | if (err < 0) | 192 | if (err < 0) |
173 | return err; | 193 | goto error; |
174 | /* rebuild mixers */ | 194 | /* rebuild mixers */ |
175 | err = snd_hda_codec_build_controls(codec); | 195 | err = snd_hda_codec_build_controls(codec); |
176 | if (err < 0) | 196 | if (err < 0) |
177 | return err; | 197 | goto error; |
178 | return 0; | 198 | err = snd_card_register(codec->bus->card); |
199 | error: | ||
200 | snd_hda_power_down(codec); | ||
201 | return err; | ||
179 | } | 202 | } |
180 | 203 | ||
181 | /* | 204 | /* |
@@ -271,47 +294,195 @@ static ssize_t type##_store(struct device *dev, \ | |||
271 | CODEC_ACTION_STORE(reconfig); | 294 | CODEC_ACTION_STORE(reconfig); |
272 | CODEC_ACTION_STORE(clear); | 295 | CODEC_ACTION_STORE(clear); |
273 | 296 | ||
297 | static ssize_t init_verbs_show(struct device *dev, | ||
298 | struct device_attribute *attr, | ||
299 | char *buf) | ||
300 | { | ||
301 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
302 | struct hda_codec *codec = hwdep->private_data; | ||
303 | int i, len = 0; | ||
304 | for (i = 0; i < codec->init_verbs.used; i++) { | ||
305 | struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); | ||
306 | len += snprintf(buf + len, PAGE_SIZE - len, | ||
307 | "0x%02x 0x%03x 0x%04x\n", | ||
308 | v->nid, v->verb, v->param); | ||
309 | } | ||
310 | return len; | ||
311 | } | ||
312 | |||
274 | static ssize_t init_verbs_store(struct device *dev, | 313 | static ssize_t init_verbs_store(struct device *dev, |
275 | struct device_attribute *attr, | 314 | struct device_attribute *attr, |
276 | const char *buf, size_t count) | 315 | const char *buf, size_t count) |
277 | { | 316 | { |
278 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | 317 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); |
279 | struct hda_codec *codec = hwdep->private_data; | 318 | struct hda_codec *codec = hwdep->private_data; |
280 | char *p; | 319 | struct hda_verb *v; |
281 | struct hda_verb verb, *v; | 320 | int nid, verb, param; |
282 | 321 | ||
283 | verb.nid = simple_strtoul(buf, &p, 0); | 322 | if (sscanf(buf, "%i %i %i", &nid, &verb, ¶m) != 3) |
284 | verb.verb = simple_strtoul(p, &p, 0); | 323 | return -EINVAL; |
285 | verb.param = simple_strtoul(p, &p, 0); | 324 | if (!nid || !verb) |
286 | if (!verb.nid || !verb.verb || !verb.param) | ||
287 | return -EINVAL; | 325 | return -EINVAL; |
288 | v = snd_array_new(&codec->init_verbs); | 326 | v = snd_array_new(&codec->init_verbs); |
289 | if (!v) | 327 | if (!v) |
290 | return -ENOMEM; | 328 | return -ENOMEM; |
291 | *v = verb; | 329 | v->nid = nid; |
330 | v->verb = verb; | ||
331 | v->param = param; | ||
292 | return count; | 332 | return count; |
293 | } | 333 | } |
294 | 334 | ||
335 | static ssize_t hints_show(struct device *dev, | ||
336 | struct device_attribute *attr, | ||
337 | char *buf) | ||
338 | { | ||
339 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
340 | struct hda_codec *codec = hwdep->private_data; | ||
341 | int i, len = 0; | ||
342 | for (i = 0; i < codec->hints.used; i++) { | ||
343 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); | ||
344 | len += snprintf(buf + len, PAGE_SIZE - len, | ||
345 | "%s = %s\n", hint->key, hint->val); | ||
346 | } | ||
347 | return len; | ||
348 | } | ||
349 | |||
350 | static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) | ||
351 | { | ||
352 | int i; | ||
353 | |||
354 | for (i = 0; i < codec->hints.used; i++) { | ||
355 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); | ||
356 | if (!strcmp(hint->key, key)) | ||
357 | return hint; | ||
358 | } | ||
359 | return NULL; | ||
360 | } | ||
361 | |||
362 | static void remove_trail_spaces(char *str) | ||
363 | { | ||
364 | char *p; | ||
365 | if (!*str) | ||
366 | return; | ||
367 | p = str + strlen(str) - 1; | ||
368 | for (; isspace(*p); p--) { | ||
369 | *p = 0; | ||
370 | if (p == str) | ||
371 | return; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | #define MAX_HINTS 1024 | ||
376 | |||
295 | static ssize_t hints_store(struct device *dev, | 377 | static ssize_t hints_store(struct device *dev, |
296 | struct device_attribute *attr, | 378 | struct device_attribute *attr, |
297 | const char *buf, size_t count) | 379 | const char *buf, size_t count) |
298 | { | 380 | { |
299 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | 381 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); |
300 | struct hda_codec *codec = hwdep->private_data; | 382 | struct hda_codec *codec = hwdep->private_data; |
301 | char *p; | 383 | char *key, *val; |
302 | char **hint; | 384 | struct hda_hint *hint; |
303 | 385 | ||
304 | if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') | 386 | while (isspace(*buf)) |
387 | buf++; | ||
388 | if (!*buf || *buf == '#' || *buf == '\n') | ||
305 | return count; | 389 | return count; |
306 | p = kstrndup_noeol(buf, 1024); | 390 | if (*buf == '=') |
307 | if (!p) | 391 | return -EINVAL; |
392 | key = kstrndup_noeol(buf, 1024); | ||
393 | if (!key) | ||
308 | return -ENOMEM; | 394 | return -ENOMEM; |
309 | hint = snd_array_new(&codec->hints); | 395 | /* extract key and val */ |
396 | val = strchr(key, '='); | ||
397 | if (!val) { | ||
398 | kfree(key); | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | *val++ = 0; | ||
402 | while (isspace(*val)) | ||
403 | val++; | ||
404 | remove_trail_spaces(key); | ||
405 | remove_trail_spaces(val); | ||
406 | hint = get_hint(codec, key); | ||
407 | if (hint) { | ||
408 | /* replace */ | ||
409 | kfree(hint->key); | ||
410 | hint->key = key; | ||
411 | hint->val = val; | ||
412 | return count; | ||
413 | } | ||
414 | /* allocate a new hint entry */ | ||
415 | if (codec->hints.used >= MAX_HINTS) | ||
416 | hint = NULL; | ||
417 | else | ||
418 | hint = snd_array_new(&codec->hints); | ||
310 | if (!hint) { | 419 | if (!hint) { |
311 | kfree(p); | 420 | kfree(key); |
312 | return -ENOMEM; | 421 | return -ENOMEM; |
313 | } | 422 | } |
314 | *hint = p; | 423 | hint->key = key; |
424 | hint->val = val; | ||
425 | return count; | ||
426 | } | ||
427 | |||
428 | static ssize_t pin_configs_show(struct hda_codec *codec, | ||
429 | struct snd_array *list, | ||
430 | char *buf) | ||
431 | { | ||
432 | int i, len = 0; | ||
433 | for (i = 0; i < list->used; i++) { | ||
434 | struct hda_pincfg *pin = snd_array_elem(list, i); | ||
435 | len += sprintf(buf + len, "0x%02x 0x%08x\n", | ||
436 | pin->nid, pin->cfg); | ||
437 | } | ||
438 | return len; | ||
439 | } | ||
440 | |||
441 | static ssize_t init_pin_configs_show(struct device *dev, | ||
442 | struct device_attribute *attr, | ||
443 | char *buf) | ||
444 | { | ||
445 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
446 | struct hda_codec *codec = hwdep->private_data; | ||
447 | return pin_configs_show(codec, &codec->init_pins, buf); | ||
448 | } | ||
449 | |||
450 | static ssize_t user_pin_configs_show(struct device *dev, | ||
451 | struct device_attribute *attr, | ||
452 | char *buf) | ||
453 | { | ||
454 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
455 | struct hda_codec *codec = hwdep->private_data; | ||
456 | return pin_configs_show(codec, &codec->user_pins, buf); | ||
457 | } | ||
458 | |||
459 | static ssize_t driver_pin_configs_show(struct device *dev, | ||
460 | struct device_attribute *attr, | ||
461 | char *buf) | ||
462 | { | ||
463 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
464 | struct hda_codec *codec = hwdep->private_data; | ||
465 | return pin_configs_show(codec, &codec->driver_pins, buf); | ||
466 | } | ||
467 | |||
468 | #define MAX_PIN_CONFIGS 32 | ||
469 | |||
470 | static ssize_t user_pin_configs_store(struct device *dev, | ||
471 | struct device_attribute *attr, | ||
472 | const char *buf, size_t count) | ||
473 | { | ||
474 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
475 | struct hda_codec *codec = hwdep->private_data; | ||
476 | int nid, cfg; | ||
477 | int err; | ||
478 | |||
479 | if (sscanf(buf, "%i %i", &nid, &cfg) != 2) | ||
480 | return -EINVAL; | ||
481 | if (!nid) | ||
482 | return -EINVAL; | ||
483 | err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); | ||
484 | if (err < 0) | ||
485 | return err; | ||
315 | return count; | 486 | return count; |
316 | } | 487 | } |
317 | 488 | ||
@@ -330,8 +501,11 @@ static struct device_attribute codec_attrs[] = { | |||
330 | CODEC_ATTR_RO(mfg), | 501 | CODEC_ATTR_RO(mfg), |
331 | CODEC_ATTR_RW(name), | 502 | CODEC_ATTR_RW(name), |
332 | CODEC_ATTR_RW(modelname), | 503 | CODEC_ATTR_RW(modelname), |
333 | CODEC_ATTR_WO(init_verbs), | 504 | CODEC_ATTR_RW(init_verbs), |
334 | CODEC_ATTR_WO(hints), | 505 | CODEC_ATTR_RW(hints), |
506 | CODEC_ATTR_RO(init_pin_configs), | ||
507 | CODEC_ATTR_RW(user_pin_configs), | ||
508 | CODEC_ATTR_RO(driver_pin_configs), | ||
335 | CODEC_ATTR_WO(reconfig), | 509 | CODEC_ATTR_WO(reconfig), |
336 | CODEC_ATTR_WO(clear), | 510 | CODEC_ATTR_WO(clear), |
337 | }; | 511 | }; |
@@ -350,4 +524,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | |||
350 | return 0; | 524 | return 0; |
351 | } | 525 | } |
352 | 526 | ||
527 | /* | ||
528 | * Look for hint string | ||
529 | */ | ||
530 | const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) | ||
531 | { | ||
532 | struct hda_hint *hint = get_hint(codec, key); | ||
533 | return hint ? hint->val : NULL; | ||
534 | } | ||
535 | EXPORT_SYMBOL_HDA(snd_hda_get_hint); | ||
536 | |||
537 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) | ||
538 | { | ||
539 | const char *p = snd_hda_get_hint(codec, key); | ||
540 | if (!p || !*p) | ||
541 | return -ENOENT; | ||
542 | switch (toupper(*p)) { | ||
543 | case 'T': /* true */ | ||
544 | case 'Y': /* yes */ | ||
545 | case '1': | ||
546 | return 1; | ||
547 | } | ||
548 | return 0; | ||
549 | } | ||
550 | EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); | ||
551 | |||
353 | #endif /* CONFIG_SND_HDA_RECONFIG */ | 552 | #endif /* CONFIG_SND_HDA_RECONFIG */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 11e791b965f6..30829ee920c3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -381,6 +381,7 @@ struct azx { | |||
381 | 381 | ||
382 | /* HD codec */ | 382 | /* HD codec */ |
383 | unsigned short codec_mask; | 383 | unsigned short codec_mask; |
384 | int codec_probe_mask; /* copied from probe_mask option */ | ||
384 | struct hda_bus *bus; | 385 | struct hda_bus *bus; |
385 | 386 | ||
386 | /* CORB/RIRB */ | 387 | /* CORB/RIRB */ |
@@ -858,13 +859,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | |||
858 | SD_CTL_DMA_START | SD_INT_MASK); | 859 | SD_CTL_DMA_START | SD_INT_MASK); |
859 | } | 860 | } |
860 | 861 | ||
861 | /* stop a stream */ | 862 | /* stop DMA */ |
862 | static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | 863 | static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) |
863 | { | 864 | { |
864 | /* stop DMA */ | ||
865 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & | 865 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & |
866 | ~(SD_CTL_DMA_START | SD_INT_MASK)); | 866 | ~(SD_CTL_DMA_START | SD_INT_MASK)); |
867 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ | 867 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ |
868 | } | ||
869 | |||
870 | /* stop a stream */ | ||
871 | static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | ||
872 | { | ||
873 | azx_stream_clear(chip, azx_dev); | ||
868 | /* disable SIE */ | 874 | /* disable SIE */ |
869 | azx_writeb(chip, INTCTL, | 875 | azx_writeb(chip, INTCTL, |
870 | azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); | 876 | azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); |
@@ -1075,8 +1081,7 @@ static int azx_setup_periods(struct azx *chip, | |||
1075 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 1081 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
1076 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 1082 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
1077 | 1083 | ||
1078 | period_bytes = snd_pcm_lib_period_bytes(substream); | 1084 | period_bytes = azx_dev->period_bytes; |
1079 | azx_dev->period_bytes = period_bytes; | ||
1080 | periods = azx_dev->bufsize / period_bytes; | 1085 | periods = azx_dev->bufsize / period_bytes; |
1081 | 1086 | ||
1082 | /* program the initial BDL entries */ | 1087 | /* program the initial BDL entries */ |
@@ -1123,24 +1128,17 @@ static int azx_setup_periods(struct azx *chip, | |||
1123 | error: | 1128 | error: |
1124 | snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", | 1129 | snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", |
1125 | azx_dev->bufsize, period_bytes); | 1130 | azx_dev->bufsize, period_bytes); |
1126 | /* reset */ | ||
1127 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | ||
1128 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | ||
1129 | return -EINVAL; | 1131 | return -EINVAL; |
1130 | } | 1132 | } |
1131 | 1133 | ||
1132 | /* | 1134 | /* reset stream */ |
1133 | * set up the SD for streaming | 1135 | static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) |
1134 | */ | ||
1135 | static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | ||
1136 | { | 1136 | { |
1137 | unsigned char val; | 1137 | unsigned char val; |
1138 | int timeout; | 1138 | int timeout; |
1139 | 1139 | ||
1140 | /* make sure the run bit is zero for SD */ | 1140 | azx_stream_clear(chip, azx_dev); |
1141 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & | 1141 | |
1142 | ~SD_CTL_DMA_START); | ||
1143 | /* reset stream */ | ||
1144 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | | 1142 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | |
1145 | SD_CTL_STREAM_RESET); | 1143 | SD_CTL_STREAM_RESET); |
1146 | udelay(3); | 1144 | udelay(3); |
@@ -1157,7 +1155,15 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1157 | while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && | 1155 | while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && |
1158 | --timeout) | 1156 | --timeout) |
1159 | ; | 1157 | ; |
1158 | } | ||
1160 | 1159 | ||
1160 | /* | ||
1161 | * set up the SD for streaming | ||
1162 | */ | ||
1163 | static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | ||
1164 | { | ||
1165 | /* make sure the run bit is zero for SD */ | ||
1166 | azx_stream_clear(chip, azx_dev); | ||
1161 | /* program the stream_tag */ | 1167 | /* program the stream_tag */ |
1162 | azx_sd_writel(azx_dev, SD_CTL, | 1168 | azx_sd_writel(azx_dev, SD_CTL, |
1163 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| | 1169 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| |
@@ -1228,7 +1234,6 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | |||
1228 | }; | 1234 | }; |
1229 | 1235 | ||
1230 | static int __devinit azx_codec_create(struct azx *chip, const char *model, | 1236 | static int __devinit azx_codec_create(struct azx *chip, const char *model, |
1231 | unsigned int codec_probe_mask, | ||
1232 | int no_init) | 1237 | int no_init) |
1233 | { | 1238 | { |
1234 | struct hda_bus_template bus_temp; | 1239 | struct hda_bus_template bus_temp; |
@@ -1261,7 +1266,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1261 | 1266 | ||
1262 | /* First try to probe all given codec slots */ | 1267 | /* First try to probe all given codec slots */ |
1263 | for (c = 0; c < max_slots; c++) { | 1268 | for (c = 0; c < max_slots; c++) { |
1264 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1269 | if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { |
1265 | if (probe_codec(chip, c) < 0) { | 1270 | if (probe_codec(chip, c) < 0) { |
1266 | /* Some BIOSen give you wrong codec addresses | 1271 | /* Some BIOSen give you wrong codec addresses |
1267 | * that don't exist | 1272 | * that don't exist |
@@ -1285,7 +1290,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1285 | 1290 | ||
1286 | /* Then create codec instances */ | 1291 | /* Then create codec instances */ |
1287 | for (c = 0; c < max_slots; c++) { | 1292 | for (c = 0; c < max_slots; c++) { |
1288 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1293 | if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { |
1289 | struct hda_codec *codec; | 1294 | struct hda_codec *codec; |
1290 | err = snd_hda_codec_new(chip->bus, c, !no_init, &codec); | 1295 | err = snd_hda_codec_new(chip->bus, c, !no_init, &codec); |
1291 | if (err < 0) | 1296 | if (err < 0) |
@@ -1403,6 +1408,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1403 | runtime->private_data = azx_dev; | 1408 | runtime->private_data = azx_dev; |
1404 | snd_pcm_set_sync(substream); | 1409 | snd_pcm_set_sync(substream); |
1405 | mutex_unlock(&chip->open_mutex); | 1410 | mutex_unlock(&chip->open_mutex); |
1411 | |||
1412 | azx_stream_reset(chip, azx_dev); | ||
1406 | return 0; | 1413 | return 0; |
1407 | } | 1414 | } |
1408 | 1415 | ||
@@ -1429,6 +1436,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1429 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | 1436 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, |
1430 | struct snd_pcm_hw_params *hw_params) | 1437 | struct snd_pcm_hw_params *hw_params) |
1431 | { | 1438 | { |
1439 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
1440 | |||
1441 | azx_dev->bufsize = 0; | ||
1442 | azx_dev->period_bytes = 0; | ||
1443 | azx_dev->format_val = 0; | ||
1432 | return snd_pcm_lib_malloc_pages(substream, | 1444 | return snd_pcm_lib_malloc_pages(substream, |
1433 | params_buffer_bytes(hw_params)); | 1445 | params_buffer_bytes(hw_params)); |
1434 | } | 1446 | } |
@@ -1443,6 +1455,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1443 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 1455 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
1444 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 1456 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
1445 | azx_sd_writel(azx_dev, SD_CTL, 0); | 1457 | azx_sd_writel(azx_dev, SD_CTL, 0); |
1458 | azx_dev->bufsize = 0; | ||
1459 | azx_dev->period_bytes = 0; | ||
1460 | azx_dev->format_val = 0; | ||
1446 | 1461 | ||
1447 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); | 1462 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); |
1448 | 1463 | ||
@@ -1456,23 +1471,37 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1456 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1471 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1457 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 1472 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
1458 | struct snd_pcm_runtime *runtime = substream->runtime; | 1473 | struct snd_pcm_runtime *runtime = substream->runtime; |
1474 | unsigned int bufsize, period_bytes, format_val; | ||
1475 | int err; | ||
1459 | 1476 | ||
1460 | azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); | 1477 | format_val = snd_hda_calc_stream_format(runtime->rate, |
1461 | azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, | 1478 | runtime->channels, |
1462 | runtime->channels, | 1479 | runtime->format, |
1463 | runtime->format, | 1480 | hinfo->maxbps); |
1464 | hinfo->maxbps); | 1481 | if (!format_val) { |
1465 | if (!azx_dev->format_val) { | ||
1466 | snd_printk(KERN_ERR SFX | 1482 | snd_printk(KERN_ERR SFX |
1467 | "invalid format_val, rate=%d, ch=%d, format=%d\n", | 1483 | "invalid format_val, rate=%d, ch=%d, format=%d\n", |
1468 | runtime->rate, runtime->channels, runtime->format); | 1484 | runtime->rate, runtime->channels, runtime->format); |
1469 | return -EINVAL; | 1485 | return -EINVAL; |
1470 | } | 1486 | } |
1471 | 1487 | ||
1488 | bufsize = snd_pcm_lib_buffer_bytes(substream); | ||
1489 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
1490 | |||
1472 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", | 1491 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", |
1473 | azx_dev->bufsize, azx_dev->format_val); | 1492 | bufsize, format_val); |
1474 | if (azx_setup_periods(chip, substream, azx_dev) < 0) | 1493 | |
1475 | return -EINVAL; | 1494 | if (bufsize != azx_dev->bufsize || |
1495 | period_bytes != azx_dev->period_bytes || | ||
1496 | format_val != azx_dev->format_val) { | ||
1497 | azx_dev->bufsize = bufsize; | ||
1498 | azx_dev->period_bytes = period_bytes; | ||
1499 | azx_dev->format_val = format_val; | ||
1500 | err = azx_setup_periods(chip, substream, azx_dev); | ||
1501 | if (err < 0) | ||
1502 | return err; | ||
1503 | } | ||
1504 | |||
1476 | azx_setup_controller(chip, azx_dev); | 1505 | azx_setup_controller(chip, azx_dev); |
1477 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1506 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1478 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; | 1507 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; |
@@ -1947,16 +1976,13 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1947 | return 0; | 1976 | return 0; |
1948 | } | 1977 | } |
1949 | 1978 | ||
1950 | static int azx_resume_early(struct pci_dev *pci) | ||
1951 | { | ||
1952 | return pci_restore_state(pci); | ||
1953 | } | ||
1954 | |||
1955 | static int azx_resume(struct pci_dev *pci) | 1979 | static int azx_resume(struct pci_dev *pci) |
1956 | { | 1980 | { |
1957 | struct snd_card *card = pci_get_drvdata(pci); | 1981 | struct snd_card *card = pci_get_drvdata(pci); |
1958 | struct azx *chip = card->private_data; | 1982 | struct azx *chip = card->private_data; |
1959 | 1983 | ||
1984 | pci_set_power_state(pci, PCI_D0); | ||
1985 | pci_restore_state(pci); | ||
1960 | if (pci_enable_device(pci) < 0) { | 1986 | if (pci_enable_device(pci) < 0) { |
1961 | printk(KERN_ERR "hda-intel: pci_enable_device failed, " | 1987 | printk(KERN_ERR "hda-intel: pci_enable_device failed, " |
1962 | "disabling device\n"); | 1988 | "disabling device\n"); |
@@ -2062,26 +2088,31 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2062 | { | 2088 | { |
2063 | const struct snd_pci_quirk *q; | 2089 | const struct snd_pci_quirk *q; |
2064 | 2090 | ||
2065 | /* Check VIA HD Audio Controller exist */ | 2091 | switch (fix) { |
2066 | if (chip->pci->vendor == PCI_VENDOR_ID_VIA && | 2092 | case POS_FIX_LPIB: |
2067 | chip->pci->device == VIA_HDAC_DEVICE_ID) { | 2093 | case POS_FIX_POSBUF: |
2094 | return fix; | ||
2095 | } | ||
2096 | |||
2097 | /* Check VIA/ATI HD Audio Controller exist */ | ||
2098 | switch (chip->driver_type) { | ||
2099 | case AZX_DRIVER_VIA: | ||
2100 | case AZX_DRIVER_ATI: | ||
2068 | chip->via_dmapos_patch = 1; | 2101 | chip->via_dmapos_patch = 1; |
2069 | /* Use link position directly, avoid any transfer problem. */ | 2102 | /* Use link position directly, avoid any transfer problem. */ |
2070 | return POS_FIX_LPIB; | 2103 | return POS_FIX_LPIB; |
2071 | } | 2104 | } |
2072 | chip->via_dmapos_patch = 0; | 2105 | chip->via_dmapos_patch = 0; |
2073 | 2106 | ||
2074 | if (fix == POS_FIX_AUTO) { | 2107 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); |
2075 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); | 2108 | if (q) { |
2076 | if (q) { | 2109 | printk(KERN_INFO |
2077 | printk(KERN_INFO | 2110 | "hda_intel: position_fix set to %d " |
2078 | "hda_intel: position_fix set to %d " | 2111 | "for device %04x:%04x\n", |
2079 | "for device %04x:%04x\n", | 2112 | q->value, q->subvendor, q->subdevice); |
2080 | q->value, q->subvendor, q->subdevice); | 2113 | return q->value; |
2081 | return q->value; | ||
2082 | } | ||
2083 | } | 2114 | } |
2084 | return fix; | 2115 | return POS_FIX_AUTO; |
2085 | } | 2116 | } |
2086 | 2117 | ||
2087 | /* | 2118 | /* |
@@ -2098,23 +2129,36 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { | |||
2098 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), | 2129 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), |
2099 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ | 2130 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ |
2100 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), | 2131 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), |
2132 | /* forced codec slots */ | ||
2133 | SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103), | ||
2101 | {} | 2134 | {} |
2102 | }; | 2135 | }; |
2103 | 2136 | ||
2137 | #define AZX_FORCE_CODEC_MASK 0x100 | ||
2138 | |||
2104 | static void __devinit check_probe_mask(struct azx *chip, int dev) | 2139 | static void __devinit check_probe_mask(struct azx *chip, int dev) |
2105 | { | 2140 | { |
2106 | const struct snd_pci_quirk *q; | 2141 | const struct snd_pci_quirk *q; |
2107 | 2142 | ||
2108 | if (probe_mask[dev] == -1) { | 2143 | chip->codec_probe_mask = probe_mask[dev]; |
2144 | if (chip->codec_probe_mask == -1) { | ||
2109 | q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); | 2145 | q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); |
2110 | if (q) { | 2146 | if (q) { |
2111 | printk(KERN_INFO | 2147 | printk(KERN_INFO |
2112 | "hda_intel: probe_mask set to 0x%x " | 2148 | "hda_intel: probe_mask set to 0x%x " |
2113 | "for device %04x:%04x\n", | 2149 | "for device %04x:%04x\n", |
2114 | q->value, q->subvendor, q->subdevice); | 2150 | q->value, q->subvendor, q->subdevice); |
2115 | probe_mask[dev] = q->value; | 2151 | chip->codec_probe_mask = q->value; |
2116 | } | 2152 | } |
2117 | } | 2153 | } |
2154 | |||
2155 | /* check forced option */ | ||
2156 | if (chip->codec_probe_mask != -1 && | ||
2157 | (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { | ||
2158 | chip->codec_mask = chip->codec_probe_mask & 0xff; | ||
2159 | printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n", | ||
2160 | chip->codec_mask); | ||
2161 | } | ||
2118 | } | 2162 | } |
2119 | 2163 | ||
2120 | 2164 | ||
@@ -2211,9 +2255,17 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2211 | gcap = azx_readw(chip, GCAP); | 2255 | gcap = azx_readw(chip, GCAP); |
2212 | snd_printdd("chipset global capabilities = 0x%x\n", gcap); | 2256 | snd_printdd("chipset global capabilities = 0x%x\n", gcap); |
2213 | 2257 | ||
2258 | /* ATI chips seems buggy about 64bit DMA addresses */ | ||
2259 | if (chip->driver_type == AZX_DRIVER_ATI) | ||
2260 | gcap &= ~0x01; | ||
2261 | |||
2214 | /* allow 64bit DMA address if supported by H/W */ | 2262 | /* allow 64bit DMA address if supported by H/W */ |
2215 | if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK)) | 2263 | if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK)) |
2216 | pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK); | 2264 | pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK); |
2265 | else { | ||
2266 | pci_set_dma_mask(pci, DMA_32BIT_MASK); | ||
2267 | pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK); | ||
2268 | } | ||
2217 | 2269 | ||
2218 | /* read number of streams from GCAP register instead of using | 2270 | /* read number of streams from GCAP register instead of using |
2219 | * hardcoded value | 2271 | * hardcoded value |
@@ -2335,10 +2387,10 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2335 | return -ENOENT; | 2387 | return -ENOENT; |
2336 | } | 2388 | } |
2337 | 2389 | ||
2338 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 2390 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2339 | if (!card) { | 2391 | if (err < 0) { |
2340 | snd_printk(KERN_ERR SFX "Error creating card!\n"); | 2392 | snd_printk(KERN_ERR SFX "Error creating card!\n"); |
2341 | return -ENOMEM; | 2393 | return err; |
2342 | } | 2394 | } |
2343 | 2395 | ||
2344 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); | 2396 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); |
@@ -2347,8 +2399,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2347 | card->private_data = chip; | 2399 | card->private_data = chip; |
2348 | 2400 | ||
2349 | /* create codec instances */ | 2401 | /* create codec instances */ |
2350 | err = azx_codec_create(chip, model[dev], probe_mask[dev], | 2402 | err = azx_codec_create(chip, model[dev], probe_only[dev]); |
2351 | probe_only[dev]); | ||
2352 | if (err < 0) | 2403 | if (err < 0) |
2353 | goto out_free; | 2404 | goto out_free; |
2354 | 2405 | ||
@@ -2445,10 +2496,10 @@ static struct pci_device_id azx_ids[] = { | |||
2445 | { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, | 2496 | { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, |
2446 | { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, | 2497 | { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, |
2447 | { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, | 2498 | { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, |
2448 | { PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA }, | 2499 | { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA }, |
2449 | { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA }, | 2500 | { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA }, |
2450 | { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA }, | 2501 | { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA }, |
2451 | { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA }, | 2502 | { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA }, |
2452 | /* Teradici */ | 2503 | /* Teradici */ |
2453 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, | 2504 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, |
2454 | /* AMD Generic, PCI class code and Vendor ID for HD Audio */ | 2505 | /* AMD Generic, PCI class code and Vendor ID for HD Audio */ |
@@ -2468,7 +2519,6 @@ static struct pci_driver driver = { | |||
2468 | .remove = __devexit_p(azx_remove), | 2519 | .remove = __devexit_p(azx_remove), |
2469 | #ifdef CONFIG_PM | 2520 | #ifdef CONFIG_PM |
2470 | .suspend = azx_suspend, | 2521 | .suspend = azx_suspend, |
2471 | .resume_early = azx_resume_early, | ||
2472 | .resume = azx_resume, | 2522 | .resume = azx_resume, |
2473 | #endif | 2523 | #endif |
2474 | }; | 2524 | }; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 1dd8716c387f..83349013b4df 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -26,8 +26,10 @@ | |||
26 | /* | 26 | /* |
27 | * for mixer controls | 27 | * for mixer controls |
28 | */ | 28 | */ |
29 | #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ | ||
30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) | ||
29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ | 31 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ |
30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | 32 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) |
31 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 33 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
32 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 34 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
33 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 35 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
@@ -96,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
96 | const char *name); | 98 | const char *name); |
97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 99 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
98 | unsigned int *tlv, const char **slaves); | 100 | unsigned int *tlv, const char **slaves); |
99 | void snd_hda_codec_reset(struct hda_codec *codec); | 101 | int snd_hda_codec_reset(struct hda_codec *codec); |
100 | int snd_hda_codec_configure(struct hda_codec *codec); | 102 | int snd_hda_codec_configure(struct hda_codec *codec); |
101 | 103 | ||
102 | /* amp value bits */ | 104 | /* amp value bits */ |
@@ -134,7 +136,7 @@ extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ | |||
134 | 136 | ||
135 | struct hda_bind_ctls { | 137 | struct hda_bind_ctls { |
136 | struct hda_ctl_ops *ops; | 138 | struct hda_ctl_ops *ops; |
137 | long values[]; | 139 | unsigned long values[]; |
138 | }; | 140 | }; |
139 | 141 | ||
140 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | 142 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, |
@@ -227,6 +229,7 @@ struct hda_multi_out { | |||
227 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ | 229 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ |
228 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ | 230 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ |
229 | hda_nid_t dig_out_nid; /* digital out audio widget */ | 231 | hda_nid_t dig_out_nid; /* digital out audio widget */ |
232 | hda_nid_t *slave_dig_outs; | ||
230 | int max_channels; /* currently supported analog channels */ | 233 | int max_channels; /* currently supported analog channels */ |
231 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | 234 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ |
232 | int no_share_stream; /* don't share a stream with multiple pins */ | 235 | int no_share_stream; /* don't share a stream with multiple pins */ |
@@ -251,6 +254,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | |||
251 | unsigned int stream_tag, | 254 | unsigned int stream_tag, |
252 | unsigned int format, | 255 | unsigned int format, |
253 | struct snd_pcm_substream *substream); | 256 | struct snd_pcm_substream *substream); |
257 | int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec, | ||
258 | struct hda_multi_out *mout); | ||
254 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, | 259 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, |
255 | struct hda_multi_out *mout, | 260 | struct hda_multi_out *mout, |
256 | struct snd_pcm_substream *substream, | 261 | struct snd_pcm_substream *substream, |
@@ -352,9 +357,12 @@ struct auto_pin_cfg { | |||
352 | int line_out_type; /* AUTO_PIN_XXX_OUT */ | 357 | int line_out_type; /* AUTO_PIN_XXX_OUT */ |
353 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; | 358 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; |
354 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 359 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
355 | hda_nid_t dig_out_pin; | 360 | int dig_outs; |
361 | hda_nid_t dig_out_pins[2]; | ||
356 | hda_nid_t dig_in_pin; | 362 | hda_nid_t dig_in_pin; |
357 | hda_nid_t mono_out_pin; | 363 | hda_nid_t mono_out_pin; |
364 | int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */ | ||
365 | int dig_in_type; /* HDA_PCM_TYPE_XXX */ | ||
358 | }; | 366 | }; |
359 | 367 | ||
360 | #define get_defcfg_connect(cfg) \ | 368 | #define get_defcfg_connect(cfg) \ |
@@ -403,6 +411,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) | |||
403 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | 411 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); |
404 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 412 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
405 | unsigned int caps); | 413 | unsigned int caps); |
414 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); | ||
406 | 415 | ||
407 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | 416 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); |
408 | void snd_hda_ctls_clear(struct hda_codec *codec); | 417 | void snd_hda_ctls_clear(struct hda_codec *codec); |
@@ -425,6 +434,23 @@ static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | |||
425 | } | 434 | } |
426 | #endif | 435 | #endif |
427 | 436 | ||
437 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
438 | const char *snd_hda_get_hint(struct hda_codec *codec, const char *key); | ||
439 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key); | ||
440 | #else | ||
441 | static inline | ||
442 | const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) | ||
443 | { | ||
444 | return NULL; | ||
445 | } | ||
446 | |||
447 | static inline | ||
448 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) | ||
449 | { | ||
450 | return -ENOENT; | ||
451 | } | ||
452 | #endif | ||
453 | |||
428 | /* | 454 | /* |
429 | * power-management | 455 | * power-management |
430 | */ | 456 | */ |
@@ -456,6 +482,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
456 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) | 482 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) |
457 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | 483 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) |
458 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 484 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
485 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) | ||
459 | 486 | ||
460 | /* | 487 | /* |
461 | * CEA Short Audio Descriptor data | 488 | * CEA Short Audio Descriptor data |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 144b85276d5a..93d7499350c6 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -399,8 +399,10 @@ static void print_conn_list(struct snd_info_buffer *buffer, | |||
399 | { | 399 | { |
400 | int c, curr = -1; | 400 | int c, curr = -1; |
401 | 401 | ||
402 | if (conn_len > 1 && wid_type != AC_WID_AUD_MIX && | 402 | if (conn_len > 1 && |
403 | wid_type != AC_WID_VOL_KNB) | 403 | wid_type != AC_WID_AUD_MIX && |
404 | wid_type != AC_WID_VOL_KNB && | ||
405 | wid_type != AC_WID_POWER) | ||
404 | curr = snd_hda_codec_read(codec, nid, 0, | 406 | curr = snd_hda_codec_read(codec, nid, 0, |
405 | AC_VERB_GET_CONNECT_SEL, 0); | 407 | AC_VERB_GET_CONNECT_SEL, 0); |
406 | snd_iprintf(buffer, " Connection: %d\n", conn_len); | 408 | snd_iprintf(buffer, " Connection: %d\n", conn_len); |
@@ -467,8 +469,9 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
467 | snd_iprintf(buffer, "Codec: %s\n", | 469 | snd_iprintf(buffer, "Codec: %s\n", |
468 | codec->name ? codec->name : "Not Set"); | 470 | codec->name ? codec->name : "Not Set"); |
469 | snd_iprintf(buffer, "Address: %d\n", codec->addr); | 471 | snd_iprintf(buffer, "Address: %d\n", codec->addr); |
470 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 472 | snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id); |
471 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 473 | snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id); |
474 | snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id); | ||
472 | snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); | 475 | snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); |
473 | 476 | ||
474 | if (codec->mfg) | 477 | if (codec->mfg) |
@@ -554,8 +557,14 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
554 | snd_iprintf(buffer, " Amp-Out caps: "); | 557 | snd_iprintf(buffer, " Amp-Out caps: "); |
555 | print_amp_caps(buffer, codec, nid, HDA_OUTPUT); | 558 | print_amp_caps(buffer, codec, nid, HDA_OUTPUT); |
556 | snd_iprintf(buffer, " Amp-Out vals: "); | 559 | snd_iprintf(buffer, " Amp-Out vals: "); |
557 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | 560 | if (wid_type == AC_WID_PIN && |
558 | wid_caps & AC_WCAP_STEREO, 1); | 561 | codec->pin_amp_workaround) |
562 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | ||
563 | wid_caps & AC_WCAP_STEREO, | ||
564 | conn_len); | ||
565 | else | ||
566 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | ||
567 | wid_caps & AC_WCAP_STEREO, 1); | ||
559 | } | 568 | } |
560 | 569 | ||
561 | switch (wid_type) { | 570 | switch (wid_type) { |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2e7371ec2e23..5bb48ee8b6c6 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -27,11 +27,12 @@ | |||
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include "hda_codec.h" | 28 | #include "hda_codec.h" |
29 | #include "hda_local.h" | 29 | #include "hda_local.h" |
30 | #include "hda_beep.h" | ||
30 | 31 | ||
31 | struct ad198x_spec { | 32 | struct ad198x_spec { |
32 | struct snd_kcontrol_new *mixers[5]; | 33 | struct snd_kcontrol_new *mixers[5]; |
33 | int num_mixers; | 34 | int num_mixers; |
34 | 35 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ | |
35 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 36 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
36 | * don't forget NULL termination! | 37 | * don't forget NULL termination! |
37 | */ | 38 | */ |
@@ -154,6 +155,16 @@ static const char *ad_slave_sws[] = { | |||
154 | 155 | ||
155 | static void ad198x_free_kctls(struct hda_codec *codec); | 156 | static void ad198x_free_kctls(struct hda_codec *codec); |
156 | 157 | ||
158 | /* additional beep mixers; the actual parameters are overwritten at build */ | ||
159 | static struct snd_kcontrol_new ad_beep_mixer[] = { | ||
160 | HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), | ||
161 | HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), | ||
162 | { } /* end */ | ||
163 | }; | ||
164 | |||
165 | #define set_beep_amp(spec, nid, idx, dir) \ | ||
166 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ | ||
167 | |||
157 | static int ad198x_build_controls(struct hda_codec *codec) | 168 | static int ad198x_build_controls(struct hda_codec *codec) |
158 | { | 169 | { |
159 | struct ad198x_spec *spec = codec->spec; | 170 | struct ad198x_spec *spec = codec->spec; |
@@ -181,6 +192,21 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
181 | return err; | 192 | return err; |
182 | } | 193 | } |
183 | 194 | ||
195 | /* create beep controls if needed */ | ||
196 | if (spec->beep_amp) { | ||
197 | struct snd_kcontrol_new *knew; | ||
198 | for (knew = ad_beep_mixer; knew->name; knew++) { | ||
199 | struct snd_kcontrol *kctl; | ||
200 | kctl = snd_ctl_new1(knew, codec); | ||
201 | if (!kctl) | ||
202 | return -ENOMEM; | ||
203 | kctl->private_value = spec->beep_amp; | ||
204 | err = snd_hda_ctl_add(codec, kctl); | ||
205 | if (err < 0) | ||
206 | return err; | ||
207 | } | ||
208 | } | ||
209 | |||
184 | /* if we have no master control, let's create it */ | 210 | /* if we have no master control, let's create it */ |
185 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 211 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { |
186 | unsigned int vmaster_tlv[4]; | 212 | unsigned int vmaster_tlv[4]; |
@@ -275,6 +301,14 @@ static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
275 | format, substream); | 301 | format, substream); |
276 | } | 302 | } |
277 | 303 | ||
304 | static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
305 | struct hda_codec *codec, | ||
306 | struct snd_pcm_substream *substream) | ||
307 | { | ||
308 | struct ad198x_spec *spec = codec->spec; | ||
309 | return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); | ||
310 | } | ||
311 | |||
278 | /* | 312 | /* |
279 | * Analog capture | 313 | * Analog capture |
280 | */ | 314 | */ |
@@ -333,7 +367,8 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = { | |||
333 | .ops = { | 367 | .ops = { |
334 | .open = ad198x_dig_playback_pcm_open, | 368 | .open = ad198x_dig_playback_pcm_open, |
335 | .close = ad198x_dig_playback_pcm_close, | 369 | .close = ad198x_dig_playback_pcm_close, |
336 | .prepare = ad198x_dig_playback_pcm_prepare | 370 | .prepare = ad198x_dig_playback_pcm_prepare, |
371 | .cleanup = ad198x_dig_playback_pcm_cleanup | ||
337 | }, | 372 | }, |
338 | }; | 373 | }; |
339 | 374 | ||
@@ -397,7 +432,8 @@ static void ad198x_free(struct hda_codec *codec) | |||
397 | return; | 432 | return; |
398 | 433 | ||
399 | ad198x_free_kctls(codec); | 434 | ad198x_free_kctls(codec); |
400 | kfree(codec->spec); | 435 | kfree(spec); |
436 | snd_hda_detach_beep_device(codec); | ||
401 | } | 437 | } |
402 | 438 | ||
403 | static struct hda_codec_ops ad198x_patch_ops = { | 439 | static struct hda_codec_ops ad198x_patch_ops = { |
@@ -536,8 +572,6 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
536 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 572 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
537 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 573 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
538 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 574 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
539 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
540 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
541 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | 575 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), |
542 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), | 576 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), |
543 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 577 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
@@ -601,8 +635,7 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | |||
601 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 635 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
602 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 636 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
603 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 637 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
604 | /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), | 638 | /* |
605 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
606 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | 639 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), |
607 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ | 640 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ |
608 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 641 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
@@ -800,8 +833,6 @@ static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { | |||
800 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 833 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
801 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 834 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
802 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 835 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
803 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
804 | HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
805 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 836 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
806 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | 837 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), |
807 | { | 838 | { |
@@ -993,10 +1024,8 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
993 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), | 1024 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), |
994 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), | 1025 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), |
995 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), | 1026 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), |
996 | SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG), | ||
997 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG), | ||
998 | SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG), | ||
999 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), | 1027 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), |
1028 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), | ||
1000 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), | 1029 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), |
1001 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), | 1030 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), |
1002 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), | 1031 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), |
@@ -1018,15 +1047,14 @@ static struct hda_amp_list ad1986a_loopbacks[] = { | |||
1018 | 1047 | ||
1019 | static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) | 1048 | static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) |
1020 | { | 1049 | { |
1021 | unsigned int conf = snd_hda_codec_read(codec, nid, 0, | 1050 | unsigned int conf = snd_hda_codec_get_pincfg(codec, nid); |
1022 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
1023 | return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; | 1051 | return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; |
1024 | } | 1052 | } |
1025 | 1053 | ||
1026 | static int patch_ad1986a(struct hda_codec *codec) | 1054 | static int patch_ad1986a(struct hda_codec *codec) |
1027 | { | 1055 | { |
1028 | struct ad198x_spec *spec; | 1056 | struct ad198x_spec *spec; |
1029 | int board_config; | 1057 | int err, board_config; |
1030 | 1058 | ||
1031 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1059 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1032 | if (spec == NULL) | 1060 | if (spec == NULL) |
@@ -1034,6 +1062,13 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1034 | 1062 | ||
1035 | codec->spec = spec; | 1063 | codec->spec = spec; |
1036 | 1064 | ||
1065 | err = snd_hda_attach_beep_device(codec, 0x19); | ||
1066 | if (err < 0) { | ||
1067 | ad198x_free(codec); | ||
1068 | return err; | ||
1069 | } | ||
1070 | set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); | ||
1071 | |||
1037 | spec->multiout.max_channels = 6; | 1072 | spec->multiout.max_channels = 6; |
1038 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); | 1073 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); |
1039 | spec->multiout.dac_nids = ad1986a_dac_nids; | 1074 | spec->multiout.dac_nids = ad1986a_dac_nids; |
@@ -1213,8 +1248,6 @@ static struct snd_kcontrol_new ad1983_mixers[] = { | |||
1213 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | 1248 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
1214 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 1249 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
1215 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 1250 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
1216 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), | ||
1217 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), | ||
1218 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), | 1251 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), |
1219 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1252 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
1220 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | 1253 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), |
@@ -1285,6 +1318,7 @@ static struct hda_amp_list ad1983_loopbacks[] = { | |||
1285 | static int patch_ad1983(struct hda_codec *codec) | 1318 | static int patch_ad1983(struct hda_codec *codec) |
1286 | { | 1319 | { |
1287 | struct ad198x_spec *spec; | 1320 | struct ad198x_spec *spec; |
1321 | int err; | ||
1288 | 1322 | ||
1289 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1323 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1290 | if (spec == NULL) | 1324 | if (spec == NULL) |
@@ -1292,6 +1326,13 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1292 | 1326 | ||
1293 | codec->spec = spec; | 1327 | codec->spec = spec; |
1294 | 1328 | ||
1329 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
1330 | if (err < 0) { | ||
1331 | ad198x_free(codec); | ||
1332 | return err; | ||
1333 | } | ||
1334 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
1335 | |||
1295 | spec->multiout.max_channels = 2; | 1336 | spec->multiout.max_channels = 2; |
1296 | spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); | 1337 | spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); |
1297 | spec->multiout.dac_nids = ad1983_dac_nids; | 1338 | spec->multiout.dac_nids = ad1983_dac_nids; |
@@ -1361,8 +1402,6 @@ static struct snd_kcontrol_new ad1981_mixers[] = { | |||
1361 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | 1402 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), |
1362 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | 1403 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), |
1363 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | 1404 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), |
1364 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1365 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1366 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), | 1405 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), |
1367 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), | 1406 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), |
1368 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1407 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
@@ -1407,8 +1446,8 @@ static struct hda_verb ad1981_init_verbs[] = { | |||
1407 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1446 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
1408 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 1447 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
1409 | /* Mic boost: 0dB */ | 1448 | /* Mic boost: 0dB */ |
1410 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1449 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1411 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1450 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1412 | /* Record selector: Front mic */ | 1451 | /* Record selector: Front mic */ |
1413 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, | 1452 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, |
1414 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 1453 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
@@ -1673,10 +1712,10 @@ static struct snd_pci_quirk ad1981_cfg_tbl[] = { | |||
1673 | SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), | 1712 | SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), |
1674 | SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), | 1713 | SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), |
1675 | /* All HP models */ | 1714 | /* All HP models */ |
1676 | SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP), | 1715 | SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP), |
1677 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), | 1716 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), |
1678 | /* Lenovo Thinkpad T60/X60/Z6xx */ | 1717 | /* Lenovo Thinkpad T60/X60/Z6xx */ |
1679 | SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD), | 1718 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD), |
1680 | /* HP nx6320 (reversed SSID, H/W bug) */ | 1719 | /* HP nx6320 (reversed SSID, H/W bug) */ |
1681 | SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), | 1720 | SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), |
1682 | {} | 1721 | {} |
@@ -1685,7 +1724,7 @@ static struct snd_pci_quirk ad1981_cfg_tbl[] = { | |||
1685 | static int patch_ad1981(struct hda_codec *codec) | 1724 | static int patch_ad1981(struct hda_codec *codec) |
1686 | { | 1725 | { |
1687 | struct ad198x_spec *spec; | 1726 | struct ad198x_spec *spec; |
1688 | int board_config; | 1727 | int err, board_config; |
1689 | 1728 | ||
1690 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1729 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1691 | if (spec == NULL) | 1730 | if (spec == NULL) |
@@ -1693,6 +1732,13 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1693 | 1732 | ||
1694 | codec->spec = spec; | 1733 | codec->spec = spec; |
1695 | 1734 | ||
1735 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
1736 | if (err < 0) { | ||
1737 | ad198x_free(codec); | ||
1738 | return err; | ||
1739 | } | ||
1740 | set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); | ||
1741 | |||
1696 | spec->multiout.max_channels = 2; | 1742 | spec->multiout.max_channels = 2; |
1697 | spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); | 1743 | spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); |
1698 | spec->multiout.dac_nids = ad1981_dac_nids; | 1744 | spec->multiout.dac_nids = ad1981_dac_nids; |
@@ -1885,8 +1931,8 @@ static hda_nid_t ad1988_capsrc_nids[3] = { | |||
1885 | #define AD1988_SPDIF_OUT_HDMI 0x0b | 1931 | #define AD1988_SPDIF_OUT_HDMI 0x0b |
1886 | #define AD1988_SPDIF_IN 0x07 | 1932 | #define AD1988_SPDIF_IN 0x07 |
1887 | 1933 | ||
1888 | static hda_nid_t ad1989b_slave_dig_outs[2] = { | 1934 | static hda_nid_t ad1989b_slave_dig_outs[] = { |
1889 | AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI | 1935 | AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0 |
1890 | }; | 1936 | }; |
1891 | 1937 | ||
1892 | static struct hda_input_mux ad1988_6stack_capture_source = { | 1938 | static struct hda_input_mux ad1988_6stack_capture_source = { |
@@ -1979,9 +2025,6 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { | |||
1979 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), | 2025 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), |
1980 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), | 2026 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), |
1981 | 2027 | ||
1982 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
1983 | HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
1984 | |||
1985 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2028 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
1986 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2029 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
1987 | 2030 | ||
@@ -2025,9 +2068,6 @@ static struct snd_kcontrol_new ad1988_3stack_mixers2[] = { | |||
2025 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), | 2068 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), |
2026 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), | 2069 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), |
2027 | 2070 | ||
2028 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
2029 | HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
2030 | |||
2031 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2071 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
2032 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2072 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
2033 | 2073 | ||
@@ -2057,9 +2097,6 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { | |||
2057 | HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), | 2097 | HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), |
2058 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), | 2098 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), |
2059 | 2099 | ||
2060 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
2061 | HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
2062 | |||
2063 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2100 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
2064 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2101 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
2065 | 2102 | ||
@@ -2288,10 +2325,6 @@ static struct hda_verb ad1988_capture_init_verbs[] = { | |||
2288 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2325 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2289 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2326 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2290 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2327 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2291 | /* ADCs; muted */ | ||
2292 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2293 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2294 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2295 | 2328 | ||
2296 | { } | 2329 | { } |
2297 | }; | 2330 | }; |
@@ -2399,10 +2432,6 @@ static struct hda_verb ad1988_3stack_init_verbs[] = { | |||
2399 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2432 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2400 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2433 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2401 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2434 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2402 | /* ADCs; muted */ | ||
2403 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2404 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2405 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2406 | /* Analog Mix output amp */ | 2435 | /* Analog Mix output amp */ |
2407 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | 2436 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ |
2408 | { } | 2437 | { } |
@@ -2474,10 +2503,6 @@ static struct hda_verb ad1988_laptop_init_verbs[] = { | |||
2474 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2503 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2475 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2504 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2476 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 2505 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
2477 | /* ADCs; muted */ | ||
2478 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2479 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2480 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2481 | /* Analog Mix output amp */ | 2506 | /* Analog Mix output amp */ |
2482 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | 2507 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ |
2483 | { } | 2508 | { } |
@@ -2881,7 +2906,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2881 | 2906 | ||
2882 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2907 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2883 | 2908 | ||
2884 | if (spec->autocfg.dig_out_pin) | 2909 | if (spec->autocfg.dig_outs) |
2885 | spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; | 2910 | spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; |
2886 | if (spec->autocfg.dig_in_pin) | 2911 | if (spec->autocfg.dig_in_pin) |
2887 | spec->dig_in_nid = AD1988_SPDIF_IN; | 2912 | spec->dig_in_nid = AD1988_SPDIF_IN; |
@@ -2931,7 +2956,7 @@ static struct snd_pci_quirk ad1988_cfg_tbl[] = { | |||
2931 | static int patch_ad1988(struct hda_codec *codec) | 2956 | static int patch_ad1988(struct hda_codec *codec) |
2932 | { | 2957 | { |
2933 | struct ad198x_spec *spec; | 2958 | struct ad198x_spec *spec; |
2934 | int board_config; | 2959 | int err, board_config; |
2935 | 2960 | ||
2936 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2961 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2937 | if (spec == NULL) | 2962 | if (spec == NULL) |
@@ -2951,7 +2976,7 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2951 | 2976 | ||
2952 | if (board_config == AD1988_AUTO) { | 2977 | if (board_config == AD1988_AUTO) { |
2953 | /* automatic parse from the BIOS config */ | 2978 | /* automatic parse from the BIOS config */ |
2954 | int err = ad1988_parse_auto_config(codec); | 2979 | err = ad1988_parse_auto_config(codec); |
2955 | if (err < 0) { | 2980 | if (err < 0) { |
2956 | ad198x_free(codec); | 2981 | ad198x_free(codec); |
2957 | return err; | 2982 | return err; |
@@ -2961,6 +2986,13 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2961 | } | 2986 | } |
2962 | } | 2987 | } |
2963 | 2988 | ||
2989 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
2990 | if (err < 0) { | ||
2991 | ad198x_free(codec); | ||
2992 | return err; | ||
2993 | } | ||
2994 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
2995 | |||
2964 | switch (board_config) { | 2996 | switch (board_config) { |
2965 | case AD1988_6STACK: | 2997 | case AD1988_6STACK: |
2966 | case AD1988_6STACK_DIG: | 2998 | case AD1988_6STACK_DIG: |
@@ -3117,12 +3149,6 @@ static struct snd_kcontrol_new ad1884_base_mixers[] = { | |||
3117 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3149 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
3118 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | 3150 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), |
3119 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | 3151 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), |
3120 | /* | ||
3121 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3122 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3123 | HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
3124 | HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
3125 | */ | ||
3126 | HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), | 3152 | HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), |
3127 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3153 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), |
3128 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3154 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3195,10 +3221,10 @@ static struct hda_verb ad1884_init_verbs[] = { | |||
3195 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | 3221 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, |
3196 | /* Port-B (front mic) pin */ | 3222 | /* Port-B (front mic) pin */ |
3197 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3223 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3198 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3224 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3199 | /* Port-C (rear mic) pin */ | 3225 | /* Port-C (rear mic) pin */ |
3200 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3226 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3201 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3227 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3202 | /* Analog mixer; mute as default */ | 3228 | /* Analog mixer; mute as default */ |
3203 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3229 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3204 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 3230 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
@@ -3231,7 +3257,7 @@ static const char *ad1884_slave_vols[] = { | |||
3231 | "CD Playback Volume", | 3257 | "CD Playback Volume", |
3232 | "Internal Mic Playback Volume", | 3258 | "Internal Mic Playback Volume", |
3233 | "Docking Mic Playback Volume" | 3259 | "Docking Mic Playback Volume" |
3234 | "Beep Playback Volume", | 3260 | /* "Beep Playback Volume", */ |
3235 | "IEC958 Playback Volume", | 3261 | "IEC958 Playback Volume", |
3236 | NULL | 3262 | NULL |
3237 | }; | 3263 | }; |
@@ -3239,6 +3265,7 @@ static const char *ad1884_slave_vols[] = { | |||
3239 | static int patch_ad1884(struct hda_codec *codec) | 3265 | static int patch_ad1884(struct hda_codec *codec) |
3240 | { | 3266 | { |
3241 | struct ad198x_spec *spec; | 3267 | struct ad198x_spec *spec; |
3268 | int err; | ||
3242 | 3269 | ||
3243 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3270 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
3244 | if (spec == NULL) | 3271 | if (spec == NULL) |
@@ -3246,6 +3273,13 @@ static int patch_ad1884(struct hda_codec *codec) | |||
3246 | 3273 | ||
3247 | codec->spec = spec; | 3274 | codec->spec = spec; |
3248 | 3275 | ||
3276 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
3277 | if (err < 0) { | ||
3278 | ad198x_free(codec); | ||
3279 | return err; | ||
3280 | } | ||
3281 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
3282 | |||
3249 | spec->multiout.max_channels = 2; | 3283 | spec->multiout.max_channels = 2; |
3250 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); | 3284 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); |
3251 | spec->multiout.dac_nids = ad1884_dac_nids; | 3285 | spec->multiout.dac_nids = ad1884_dac_nids; |
@@ -3312,8 +3346,6 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | |||
3312 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3346 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
3313 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | 3347 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), |
3314 | HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3348 | HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
3315 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3316 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3317 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3349 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
3318 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3350 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
3319 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 3351 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
@@ -3349,7 +3381,7 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = { | |||
3349 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3381 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3350 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3382 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3351 | /* docking mic boost */ | 3383 | /* docking mic boost */ |
3352 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3384 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
3353 | /* Analog mixer - docking mic; mute as default */ | 3385 | /* Analog mixer - docking mic; mute as default */ |
3354 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 3386 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3355 | /* enable EAPD bit */ | 3387 | /* enable EAPD bit */ |
@@ -3370,10 +3402,6 @@ static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { | |||
3370 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3402 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
3371 | HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), | 3403 | HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), |
3372 | HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), | 3404 | HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), |
3373 | /* | ||
3374 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3375 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3376 | */ | ||
3377 | HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT), | 3405 | HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT), |
3378 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3406 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), |
3379 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3407 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3459,7 +3487,7 @@ static const char *ad1984_models[AD1984_MODELS] = { | |||
3459 | 3487 | ||
3460 | static struct snd_pci_quirk ad1984_cfg_tbl[] = { | 3488 | static struct snd_pci_quirk ad1984_cfg_tbl[] = { |
3461 | /* Lenovo Thinkpad T61/X61 */ | 3489 | /* Lenovo Thinkpad T61/X61 */ |
3462 | SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD), | 3490 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), |
3463 | SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), | 3491 | SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), |
3464 | {} | 3492 | {} |
3465 | }; | 3493 | }; |
@@ -3552,8 +3580,6 @@ static struct snd_kcontrol_new ad1884a_base_mixers[] = { | |||
3552 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3580 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
3553 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | 3581 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), |
3554 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | 3582 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), |
3555 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3556 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3557 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3583 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), |
3558 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), | 3584 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), |
3559 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3585 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
@@ -3613,10 +3639,10 @@ static struct hda_verb ad1884a_init_verbs[] = { | |||
3613 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3639 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3614 | /* Port-B (front mic) pin */ | 3640 | /* Port-B (front mic) pin */ |
3615 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3641 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3616 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3642 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3617 | /* Port-C (rear line-in) pin */ | 3643 | /* Port-C (rear line-in) pin */ |
3618 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 3644 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
3619 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3645 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3620 | /* Port-E (rear mic) pin */ | 3646 | /* Port-E (rear mic) pin */ |
3621 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 3647 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
3622 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3648 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
@@ -3686,8 +3712,6 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
3686 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3712 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
3687 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3713 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
3688 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3714 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
3689 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3690 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3691 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3715 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
3692 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | 3716 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), |
3693 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3717 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), |
@@ -3715,8 +3739,6 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { | |||
3715 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 3739 | HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
3716 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | 3740 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), |
3717 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 3741 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
3718 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3719 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3720 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), | 3742 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), |
3721 | HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), | 3743 | HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), |
3722 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3744 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3827,8 +3849,6 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { | |||
3827 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 3849 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
3828 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | 3850 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), |
3829 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3851 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
3830 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3831 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3832 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3852 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
3833 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | 3853 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), |
3834 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3854 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -3902,9 +3922,9 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | |||
3902 | SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), | 3922 | SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), |
3903 | SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), | 3923 | SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), |
3904 | SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), | 3924 | SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), |
3905 | SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP), | 3925 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), |
3906 | SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP), | 3926 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), |
3907 | SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP), | 3927 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), |
3908 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), | 3928 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), |
3909 | {} | 3929 | {} |
3910 | }; | 3930 | }; |
@@ -3912,7 +3932,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | |||
3912 | static int patch_ad1884a(struct hda_codec *codec) | 3932 | static int patch_ad1884a(struct hda_codec *codec) |
3913 | { | 3933 | { |
3914 | struct ad198x_spec *spec; | 3934 | struct ad198x_spec *spec; |
3915 | int board_config; | 3935 | int err, board_config; |
3916 | 3936 | ||
3917 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3937 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
3918 | if (spec == NULL) | 3938 | if (spec == NULL) |
@@ -3920,6 +3940,13 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
3920 | 3940 | ||
3921 | codec->spec = spec; | 3941 | codec->spec = spec; |
3922 | 3942 | ||
3943 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
3944 | if (err < 0) { | ||
3945 | ad198x_free(codec); | ||
3946 | return err; | ||
3947 | } | ||
3948 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
3949 | |||
3923 | spec->multiout.max_channels = 2; | 3950 | spec->multiout.max_channels = 2; |
3924 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); | 3951 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); |
3925 | spec->multiout.dac_nids = ad1884a_dac_nids; | 3952 | spec->multiout.dac_nids = ad1884a_dac_nids; |
@@ -3957,6 +3984,14 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
3957 | spec->multiout.dig_out_nid = 0; | 3984 | spec->multiout.dig_out_nid = 0; |
3958 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; | 3985 | codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; |
3959 | codec->patch_ops.init = ad1884a_hp_init; | 3986 | codec->patch_ops.init = ad1884a_hp_init; |
3987 | /* set the upper-limit for mixer amp to 0dB for avoiding the | ||
3988 | * possible damage by overloading | ||
3989 | */ | ||
3990 | snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, | ||
3991 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
3992 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
3993 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
3994 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
3960 | break; | 3995 | break; |
3961 | case AD1884A_THINKPAD: | 3996 | case AD1884A_THINKPAD: |
3962 | spec->mixers[0] = ad1984a_thinkpad_mixers; | 3997 | spec->mixers[0] = ad1984a_thinkpad_mixers; |
@@ -4074,8 +4109,6 @@ static struct snd_kcontrol_new ad1882_loopback_mixers[] = { | |||
4074 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), | 4109 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), |
4075 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), | 4110 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), |
4076 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), | 4111 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), |
4077 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), | ||
4078 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), | ||
4079 | { } /* end */ | 4112 | { } /* end */ |
4080 | }; | 4113 | }; |
4081 | 4114 | ||
@@ -4088,8 +4121,6 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = { | |||
4088 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), | 4121 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), |
4089 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), | 4122 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), |
4090 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), | 4123 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), |
4091 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), | ||
4092 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), | ||
4093 | HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), | 4124 | HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), |
4094 | { } /* end */ | 4125 | { } /* end */ |
4095 | }; | 4126 | }; |
@@ -4248,7 +4279,7 @@ static const char *ad1882_models[AD1986A_MODELS] = { | |||
4248 | static int patch_ad1882(struct hda_codec *codec) | 4279 | static int patch_ad1882(struct hda_codec *codec) |
4249 | { | 4280 | { |
4250 | struct ad198x_spec *spec; | 4281 | struct ad198x_spec *spec; |
4251 | int board_config; | 4282 | int err, board_config; |
4252 | 4283 | ||
4253 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4284 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4254 | if (spec == NULL) | 4285 | if (spec == NULL) |
@@ -4256,6 +4287,13 @@ static int patch_ad1882(struct hda_codec *codec) | |||
4256 | 4287 | ||
4257 | codec->spec = spec; | 4288 | codec->spec = spec; |
4258 | 4289 | ||
4290 | err = snd_hda_attach_beep_device(codec, 0x10); | ||
4291 | if (err < 0) { | ||
4292 | ad198x_free(codec); | ||
4293 | return err; | ||
4294 | } | ||
4295 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | ||
4296 | |||
4259 | spec->multiout.max_channels = 6; | 4297 | spec->multiout.max_channels = 6; |
4260 | spec->multiout.num_dacs = 3; | 4298 | spec->multiout.num_dacs = 3; |
4261 | spec->multiout.dac_nids = ad1882_dac_nids; | 4299 | spec->multiout.dac_nids = ad1882_dac_nids; |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index f3ebe837f2d5..c921264bbd71 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -680,13 +680,13 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
680 | struct auto_pin_cfg cfg; | 680 | struct auto_pin_cfg cfg; |
681 | 681 | ||
682 | /* collect pin default configuration */ | 682 | /* collect pin default configuration */ |
683 | port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 683 | port_e = snd_hda_codec_get_pincfg(codec, 0x0f); |
684 | port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 684 | port_f = snd_hda_codec_get_pincfg(codec, 0x10); |
685 | spec->front_panel = 1; | 685 | spec->front_panel = 1; |
686 | if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || | 686 | if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || |
687 | get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { | 687 | get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { |
688 | port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 688 | port_g = snd_hda_codec_get_pincfg(codec, 0x1f); |
689 | port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 689 | port_h = snd_hda_codec_get_pincfg(codec, 0x20); |
690 | spec->channel_modes = cmi9880_channel_modes; | 690 | spec->channel_modes = cmi9880_channel_modes; |
691 | /* no front panel */ | 691 | /* no front panel */ |
692 | if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || | 692 | if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || |
@@ -703,8 +703,8 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
703 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | 703 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; |
704 | } else { | 704 | } else { |
705 | spec->input_mux = &cmi9880_basic_mux; | 705 | spec->input_mux = &cmi9880_basic_mux; |
706 | port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 706 | port_spdifi = snd_hda_codec_get_pincfg(codec, 0x13); |
707 | port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 707 | port_spdifo = snd_hda_codec_get_pincfg(codec, 0x12); |
708 | if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) | 708 | if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) |
709 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | 709 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; |
710 | if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) | 710 | if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 0177ef8f4c9e..1f2ad76ca94b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -58,6 +58,7 @@ struct conexant_spec { | |||
58 | 58 | ||
59 | struct snd_kcontrol_new *mixers[5]; | 59 | struct snd_kcontrol_new *mixers[5]; |
60 | int num_mixers; | 60 | int num_mixers; |
61 | hda_nid_t vmaster_nid; | ||
61 | 62 | ||
62 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 63 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
63 | * don't forget NULL | 64 | * don't forget NULL |
@@ -72,6 +73,7 @@ struct conexant_spec { | |||
72 | */ | 73 | */ |
73 | unsigned int cur_eapd; | 74 | unsigned int cur_eapd; |
74 | unsigned int hp_present; | 75 | unsigned int hp_present; |
76 | unsigned int no_auto_mic; | ||
75 | unsigned int need_dac_fix; | 77 | unsigned int need_dac_fix; |
76 | 78 | ||
77 | /* capture */ | 79 | /* capture */ |
@@ -461,6 +463,29 @@ static void conexant_free(struct hda_codec *codec) | |||
461 | kfree(codec->spec); | 463 | kfree(codec->spec); |
462 | } | 464 | } |
463 | 465 | ||
466 | static struct snd_kcontrol_new cxt_capture_mixers[] = { | ||
467 | { | ||
468 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
469 | .name = "Capture Source", | ||
470 | .info = conexant_mux_enum_info, | ||
471 | .get = conexant_mux_enum_get, | ||
472 | .put = conexant_mux_enum_put | ||
473 | }, | ||
474 | {} | ||
475 | }; | ||
476 | |||
477 | static const char *slave_vols[] = { | ||
478 | "Headphone Playback Volume", | ||
479 | "Speaker Playback Volume", | ||
480 | NULL | ||
481 | }; | ||
482 | |||
483 | static const char *slave_sws[] = { | ||
484 | "Headphone Playback Switch", | ||
485 | "Speaker Playback Switch", | ||
486 | NULL | ||
487 | }; | ||
488 | |||
464 | static int conexant_build_controls(struct hda_codec *codec) | 489 | static int conexant_build_controls(struct hda_codec *codec) |
465 | { | 490 | { |
466 | struct conexant_spec *spec = codec->spec; | 491 | struct conexant_spec *spec = codec->spec; |
@@ -488,6 +513,32 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
488 | if (err < 0) | 513 | if (err < 0) |
489 | return err; | 514 | return err; |
490 | } | 515 | } |
516 | |||
517 | /* if we have no master control, let's create it */ | ||
518 | if (spec->vmaster_nid && | ||
519 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
520 | unsigned int vmaster_tlv[4]; | ||
521 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
522 | HDA_OUTPUT, vmaster_tlv); | ||
523 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
524 | vmaster_tlv, slave_vols); | ||
525 | if (err < 0) | ||
526 | return err; | ||
527 | } | ||
528 | if (spec->vmaster_nid && | ||
529 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
530 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
531 | NULL, slave_sws); | ||
532 | if (err < 0) | ||
533 | return err; | ||
534 | } | ||
535 | |||
536 | if (spec->input_mux) { | ||
537 | err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); | ||
538 | if (err < 0) | ||
539 | return err; | ||
540 | } | ||
541 | |||
491 | return 0; | 542 | return 0; |
492 | } | 543 | } |
493 | 544 | ||
@@ -719,13 +770,6 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
719 | } | 770 | } |
720 | 771 | ||
721 | static struct snd_kcontrol_new cxt5045_mixers[] = { | 772 | static struct snd_kcontrol_new cxt5045_mixers[] = { |
722 | { | ||
723 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
724 | .name = "Capture Source", | ||
725 | .info = conexant_mux_enum_info, | ||
726 | .get = conexant_mux_enum_get, | ||
727 | .put = conexant_mux_enum_put | ||
728 | }, | ||
729 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 773 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
730 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), | 774 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), |
731 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 775 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
@@ -759,13 +803,6 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = { | |||
759 | }; | 803 | }; |
760 | 804 | ||
761 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { | 805 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { |
762 | { | ||
763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
764 | .name = "Capture Source", | ||
765 | .info = conexant_mux_enum_info, | ||
766 | .get = conexant_mux_enum_get, | ||
767 | .put = conexant_mux_enum_put | ||
768 | }, | ||
769 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 806 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
770 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), | 807 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), |
771 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 808 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
@@ -1002,15 +1039,9 @@ static const char *cxt5045_models[CXT5045_MODELS] = { | |||
1002 | }; | 1039 | }; |
1003 | 1040 | ||
1004 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 1041 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
1005 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP", CXT5045_LAPTOP_HPSENSE), | ||
1006 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP_HPSENSE), | ||
1007 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP_HPSENSE), | ||
1008 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP_HPSENSE), | ||
1009 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE), | ||
1010 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE), | ||
1011 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE), | ||
1012 | SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), | 1042 | SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), |
1013 | SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE), | 1043 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", |
1044 | CXT5045_LAPTOP_HPSENSE), | ||
1014 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), | 1045 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), |
1015 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), | 1046 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), |
1016 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), | 1047 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), |
@@ -1020,8 +1051,8 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | |||
1020 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1051 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1021 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1052 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1022 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1053 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1023 | SND_PCI_QUIRK(0x1631, 0xc106, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), | 1054 | SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", |
1024 | SND_PCI_QUIRK(0x1631, 0xc107, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), | 1055 | CXT5045_LAPTOP_HPMICSENSE), |
1025 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), | 1056 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), |
1026 | {} | 1057 | {} |
1027 | }; | 1058 | }; |
@@ -1035,6 +1066,7 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1035 | if (!spec) | 1066 | if (!spec) |
1036 | return -ENOMEM; | 1067 | return -ENOMEM; |
1037 | codec->spec = spec; | 1068 | codec->spec = spec; |
1069 | codec->pin_amp_workaround = 1; | ||
1038 | 1070 | ||
1039 | spec->multiout.max_channels = 2; | 1071 | spec->multiout.max_channels = 2; |
1040 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); | 1072 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); |
@@ -1134,7 +1166,7 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1134 | /* Conexant 5047 specific */ | 1166 | /* Conexant 5047 specific */ |
1135 | #define CXT5047_SPDIF_OUT 0x11 | 1167 | #define CXT5047_SPDIF_OUT 0x11 |
1136 | 1168 | ||
1137 | static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c }; | 1169 | static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ |
1138 | static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; | 1170 | static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; |
1139 | static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; | 1171 | static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; |
1140 | 1172 | ||
@@ -1142,20 +1174,6 @@ static struct hda_channel_mode cxt5047_modes[1] = { | |||
1142 | { 2, NULL }, | 1174 | { 2, NULL }, |
1143 | }; | 1175 | }; |
1144 | 1176 | ||
1145 | static struct hda_input_mux cxt5047_capture_source = { | ||
1146 | .num_items = 1, | ||
1147 | .items = { | ||
1148 | { "Mic", 0x2 }, | ||
1149 | } | ||
1150 | }; | ||
1151 | |||
1152 | static struct hda_input_mux cxt5047_hp_capture_source = { | ||
1153 | .num_items = 1, | ||
1154 | .items = { | ||
1155 | { "ExtMic", 0x2 }, | ||
1156 | } | ||
1157 | }; | ||
1158 | |||
1159 | static struct hda_input_mux cxt5047_toshiba_capture_source = { | 1177 | static struct hda_input_mux cxt5047_toshiba_capture_source = { |
1160 | .num_items = 2, | 1178 | .num_items = 2, |
1161 | .items = { | 1179 | .items = { |
@@ -1179,7 +1197,11 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1179 | * the headphone jack | 1197 | * the headphone jack |
1180 | */ | 1198 | */ |
1181 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | 1199 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
1182 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | 1200 | /* NOTE: Conexat codec needs the index for *OUTPUT* amp of |
1201 | * pin widgets unlike other codecs. In this case, we need to | ||
1202 | * set index 0x01 for the volume from the mixer amp 0x19. | ||
1203 | */ | ||
1204 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1183 | HDA_AMP_MUTE, bits); | 1205 | HDA_AMP_MUTE, bits); |
1184 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | 1206 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
1185 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, | 1207 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, |
@@ -1187,16 +1209,6 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1187 | return 1; | 1209 | return 1; |
1188 | } | 1210 | } |
1189 | 1211 | ||
1190 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ | ||
1191 | static struct hda_bind_ctls cxt5047_bind_master_vol = { | ||
1192 | .ops = &snd_hda_bind_vol, | ||
1193 | .values = { | ||
1194 | HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1195 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), | ||
1196 | 0 | ||
1197 | }, | ||
1198 | }; | ||
1199 | |||
1200 | /* mute internal speaker if HP is plugged */ | 1212 | /* mute internal speaker if HP is plugged */ |
1201 | static void cxt5047_hp_automute(struct hda_codec *codec) | 1213 | static void cxt5047_hp_automute(struct hda_codec *codec) |
1202 | { | 1214 | { |
@@ -1207,27 +1219,8 @@ static void cxt5047_hp_automute(struct hda_codec *codec) | |||
1207 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1219 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1208 | 1220 | ||
1209 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | 1221 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
1210 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | 1222 | /* See the note in cxt5047_hp_master_sw_put */ |
1211 | HDA_AMP_MUTE, bits); | 1223 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, |
1212 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | ||
1213 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, | ||
1214 | HDA_AMP_MUTE, bits); | ||
1215 | } | ||
1216 | |||
1217 | /* mute internal speaker if HP is plugged */ | ||
1218 | static void cxt5047_hp2_automute(struct hda_codec *codec) | ||
1219 | { | ||
1220 | struct conexant_spec *spec = codec->spec; | ||
1221 | unsigned int bits; | ||
1222 | |||
1223 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | ||
1224 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1225 | |||
1226 | bits = spec->hp_present ? HDA_AMP_MUTE : 0; | ||
1227 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | ||
1228 | HDA_AMP_MUTE, bits); | ||
1229 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | ||
1230 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, | ||
1231 | HDA_AMP_MUTE, bits); | 1224 | HDA_AMP_MUTE, bits); |
1232 | } | 1225 | } |
1233 | 1226 | ||
@@ -1268,55 +1261,14 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
1268 | } | 1261 | } |
1269 | } | 1262 | } |
1270 | 1263 | ||
1271 | /* unsolicited event for HP jack sensing - non-EAPD systems */ | 1264 | static struct snd_kcontrol_new cxt5047_base_mixers[] = { |
1272 | static void cxt5047_hp2_unsol_event(struct hda_codec *codec, | 1265 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), |
1273 | unsigned int res) | 1266 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), |
1274 | { | 1267 | HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT), |
1275 | res >>= 26; | ||
1276 | switch (res) { | ||
1277 | case CONEXANT_HP_EVENT: | ||
1278 | cxt5047_hp2_automute(codec); | ||
1279 | break; | ||
1280 | case CONEXANT_MIC_EVENT: | ||
1281 | cxt5047_hp_automic(codec); | ||
1282 | break; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | static struct snd_kcontrol_new cxt5047_mixers[] = { | ||
1287 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1288 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | ||
1289 | HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1290 | HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
1291 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 1268 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
1292 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 1269 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1293 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 1270 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1294 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 1271 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1295 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), | ||
1296 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), | ||
1297 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), | ||
1298 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), | ||
1299 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1300 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), | ||
1301 | |||
1302 | {} | ||
1303 | }; | ||
1304 | |||
1305 | static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | ||
1306 | { | ||
1307 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1308 | .name = "Capture Source", | ||
1309 | .info = conexant_mux_enum_info, | ||
1310 | .get = conexant_mux_enum_get, | ||
1311 | .put = conexant_mux_enum_put | ||
1312 | }, | ||
1313 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1314 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | ||
1315 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1316 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1317 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1318 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1319 | HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol), | ||
1320 | { | 1272 | { |
1321 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1273 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1322 | .name = "Master Playback Switch", | 1274 | .name = "Master Playback Switch", |
@@ -1329,29 +1281,15 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | |||
1329 | {} | 1281 | {} |
1330 | }; | 1282 | }; |
1331 | 1283 | ||
1332 | static struct snd_kcontrol_new cxt5047_hp_mixers[] = { | 1284 | static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { |
1333 | { | 1285 | /* See the note in cxt5047_hp_master_sw_put */ |
1334 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1286 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), |
1335 | .name = "Capture Source", | 1287 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1336 | .info = conexant_mux_enum_info, | 1288 | {} |
1337 | .get = conexant_mux_enum_get, | 1289 | }; |
1338 | .put = conexant_mux_enum_put | 1290 | |
1339 | }, | 1291 | static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { |
1340 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1341 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT), | ||
1342 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1343 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1344 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1345 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1346 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), | 1292 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1347 | { | ||
1348 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1349 | .name = "Master Playback Switch", | ||
1350 | .info = cxt_eapd_info, | ||
1351 | .get = cxt_eapd_get, | ||
1352 | .put = cxt5047_hp_master_sw_put, | ||
1353 | .private_value = 0x13, | ||
1354 | }, | ||
1355 | { } /* end */ | 1293 | { } /* end */ |
1356 | }; | 1294 | }; |
1357 | 1295 | ||
@@ -1362,8 +1300,8 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1362 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1300 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1363 | /* HP, Speaker */ | 1301 | /* HP, Speaker */ |
1364 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | 1302 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
1365 | {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, | 1303 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ |
1366 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, | 1304 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ |
1367 | /* Record selector: Mic */ | 1305 | /* Record selector: Mic */ |
1368 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1306 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1369 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1307 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -1383,30 +1321,7 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1383 | 1321 | ||
1384 | /* configuration for Toshiba Laptops */ | 1322 | /* configuration for Toshiba Laptops */ |
1385 | static struct hda_verb cxt5047_toshiba_init_verbs[] = { | 1323 | static struct hda_verb cxt5047_toshiba_init_verbs[] = { |
1386 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */ | 1324 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ |
1387 | /* pin sensing on HP and Mic jacks */ | ||
1388 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1389 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
1390 | /* Speaker routing */ | ||
1391 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
1392 | {} | ||
1393 | }; | ||
1394 | |||
1395 | /* configuration for HP Laptops */ | ||
1396 | static struct hda_verb cxt5047_hp_init_verbs[] = { | ||
1397 | /* pin sensing on HP jack */ | ||
1398 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1399 | /* 0x13 is actually shared by both HP and speaker; | ||
1400 | * setting the connection to 0 (=0x19) makes the master volume control | ||
1401 | * working mysteriouslly... | ||
1402 | */ | ||
1403 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1404 | /* Record selector: Ext Mic */ | ||
1405 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | ||
1406 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1407 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
1408 | /* Speaker routing */ | ||
1409 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
1410 | {} | 1325 | {} |
1411 | }; | 1326 | }; |
1412 | 1327 | ||
@@ -1571,11 +1486,9 @@ static const char *cxt5047_models[CXT5047_MODELS] = { | |||
1571 | }; | 1486 | }; |
1572 | 1487 | ||
1573 | static struct snd_pci_quirk cxt5047_cfg_tbl[] = { | 1488 | static struct snd_pci_quirk cxt5047_cfg_tbl[] = { |
1574 | SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP), | ||
1575 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), | 1489 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), |
1576 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP), | 1490 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", |
1577 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP), | 1491 | CXT5047_LAPTOP), |
1578 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6700", CXT5047_LAPTOP), | ||
1579 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), | 1492 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), |
1580 | {} | 1493 | {} |
1581 | }; | 1494 | }; |
@@ -1589,6 +1502,7 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1589 | if (!spec) | 1502 | if (!spec) |
1590 | return -ENOMEM; | 1503 | return -ENOMEM; |
1591 | codec->spec = spec; | 1504 | codec->spec = spec; |
1505 | codec->pin_amp_workaround = 1; | ||
1592 | 1506 | ||
1593 | spec->multiout.max_channels = 2; | 1507 | spec->multiout.max_channels = 2; |
1594 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); | 1508 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); |
@@ -1597,9 +1511,8 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1597 | spec->num_adc_nids = 1; | 1511 | spec->num_adc_nids = 1; |
1598 | spec->adc_nids = cxt5047_adc_nids; | 1512 | spec->adc_nids = cxt5047_adc_nids; |
1599 | spec->capsrc_nids = cxt5047_capsrc_nids; | 1513 | spec->capsrc_nids = cxt5047_capsrc_nids; |
1600 | spec->input_mux = &cxt5047_capture_source; | ||
1601 | spec->num_mixers = 1; | 1514 | spec->num_mixers = 1; |
1602 | spec->mixers[0] = cxt5047_mixers; | 1515 | spec->mixers[0] = cxt5047_base_mixers; |
1603 | spec->num_init_verbs = 1; | 1516 | spec->num_init_verbs = 1; |
1604 | spec->init_verbs[0] = cxt5047_init_verbs; | 1517 | spec->init_verbs[0] = cxt5047_init_verbs; |
1605 | spec->spdif_route = 0; | 1518 | spec->spdif_route = 0; |
@@ -1613,21 +1526,22 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1613 | cxt5047_cfg_tbl); | 1526 | cxt5047_cfg_tbl); |
1614 | switch (board_config) { | 1527 | switch (board_config) { |
1615 | case CXT5047_LAPTOP: | 1528 | case CXT5047_LAPTOP: |
1616 | codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event; | 1529 | spec->num_mixers = 2; |
1530 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1531 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1617 | break; | 1532 | break; |
1618 | case CXT5047_LAPTOP_HP: | 1533 | case CXT5047_LAPTOP_HP: |
1619 | spec->input_mux = &cxt5047_hp_capture_source; | 1534 | spec->num_mixers = 2; |
1620 | spec->num_init_verbs = 2; | 1535 | spec->mixers[1] = cxt5047_hp_only_mixers; |
1621 | spec->init_verbs[1] = cxt5047_hp_init_verbs; | ||
1622 | spec->mixers[0] = cxt5047_hp_mixers; | ||
1623 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1536 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1624 | codec->patch_ops.init = cxt5047_hp_init; | 1537 | codec->patch_ops.init = cxt5047_hp_init; |
1625 | break; | 1538 | break; |
1626 | case CXT5047_LAPTOP_EAPD: | 1539 | case CXT5047_LAPTOP_EAPD: |
1627 | spec->input_mux = &cxt5047_toshiba_capture_source; | 1540 | spec->input_mux = &cxt5047_toshiba_capture_source; |
1541 | spec->num_mixers = 2; | ||
1542 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1628 | spec->num_init_verbs = 2; | 1543 | spec->num_init_verbs = 2; |
1629 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; | 1544 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; |
1630 | spec->mixers[0] = cxt5047_toshiba_mixers; | ||
1631 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1545 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1632 | break; | 1546 | break; |
1633 | #ifdef CONFIG_SND_DEBUG | 1547 | #ifdef CONFIG_SND_DEBUG |
@@ -1638,6 +1552,7 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1638 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1552 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1639 | #endif | 1553 | #endif |
1640 | } | 1554 | } |
1555 | spec->vmaster_nid = 0x13; | ||
1641 | return 0; | 1556 | return 0; |
1642 | } | 1557 | } |
1643 | 1558 | ||
@@ -1673,8 +1588,11 @@ static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1673 | /* toggle input of built-in and mic jack appropriately */ | 1588 | /* toggle input of built-in and mic jack appropriately */ |
1674 | static void cxt5051_portb_automic(struct hda_codec *codec) | 1589 | static void cxt5051_portb_automic(struct hda_codec *codec) |
1675 | { | 1590 | { |
1591 | struct conexant_spec *spec = codec->spec; | ||
1676 | unsigned int present; | 1592 | unsigned int present; |
1677 | 1593 | ||
1594 | if (spec->no_auto_mic) | ||
1595 | return; | ||
1678 | present = snd_hda_codec_read(codec, 0x17, 0, | 1596 | present = snd_hda_codec_read(codec, 0x17, 0, |
1679 | AC_VERB_GET_PIN_SENSE, 0) & | 1597 | AC_VERB_GET_PIN_SENSE, 0) & |
1680 | AC_PINSENSE_PRESENCE; | 1598 | AC_PINSENSE_PRESENCE; |
@@ -1690,6 +1608,8 @@ static void cxt5051_portc_automic(struct hda_codec *codec) | |||
1690 | unsigned int present; | 1608 | unsigned int present; |
1691 | hda_nid_t new_adc; | 1609 | hda_nid_t new_adc; |
1692 | 1610 | ||
1611 | if (spec->no_auto_mic) | ||
1612 | return; | ||
1693 | present = snd_hda_codec_read(codec, 0x18, 0, | 1613 | present = snd_hda_codec_read(codec, 0x18, 0, |
1694 | AC_VERB_GET_PIN_SENSE, 0) & | 1614 | AC_VERB_GET_PIN_SENSE, 0) & |
1695 | AC_PINSENSE_PRESENCE; | 1615 | AC_PINSENSE_PRESENCE; |
@@ -1776,6 +1696,22 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = { | |||
1776 | {} | 1696 | {} |
1777 | }; | 1697 | }; |
1778 | 1698 | ||
1699 | static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | ||
1700 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1701 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1702 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1703 | { | ||
1704 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1705 | .name = "Master Playback Switch", | ||
1706 | .info = cxt_eapd_info, | ||
1707 | .get = cxt_eapd_get, | ||
1708 | .put = cxt5051_hp_master_sw_put, | ||
1709 | .private_value = 0x1a, | ||
1710 | }, | ||
1711 | |||
1712 | {} | ||
1713 | }; | ||
1714 | |||
1779 | static struct hda_verb cxt5051_init_verbs[] = { | 1715 | static struct hda_verb cxt5051_init_verbs[] = { |
1780 | /* Line in, Mic */ | 1716 | /* Line in, Mic */ |
1781 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | 1717 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, |
@@ -1806,6 +1742,66 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
1806 | { } /* end */ | 1742 | { } /* end */ |
1807 | }; | 1743 | }; |
1808 | 1744 | ||
1745 | static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | ||
1746 | /* Line in, Mic */ | ||
1747 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1748 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1749 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1750 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1751 | /* SPK */ | ||
1752 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1753 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1754 | /* HP, Amp */ | ||
1755 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1756 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1757 | /* DAC1 */ | ||
1758 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1759 | /* Record selector: Int mic */ | ||
1760 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1761 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1762 | /* SPDIF route: PCM */ | ||
1763 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1764 | /* EAPD */ | ||
1765 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1766 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1767 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1768 | { } /* end */ | ||
1769 | }; | ||
1770 | |||
1771 | static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | ||
1772 | /* Line in, Mic */ | ||
1773 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1774 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1775 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1776 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1777 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1778 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1779 | /* SPK */ | ||
1780 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1781 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1782 | /* HP, Amp */ | ||
1783 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1784 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1785 | /* Docking HP */ | ||
1786 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1787 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1788 | /* DAC1 */ | ||
1789 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1790 | /* Record selector: Int mic */ | ||
1791 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1792 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1793 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1794 | /* SPDIF route: PCM */ | ||
1795 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1796 | /* EAPD */ | ||
1797 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1798 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1799 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1800 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT}, | ||
1801 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1802 | { } /* end */ | ||
1803 | }; | ||
1804 | |||
1809 | /* initialize jack-sensing, too */ | 1805 | /* initialize jack-sensing, too */ |
1810 | static int cxt5051_init(struct hda_codec *codec) | 1806 | static int cxt5051_init(struct hda_codec *codec) |
1811 | { | 1807 | { |
@@ -1823,18 +1819,24 @@ static int cxt5051_init(struct hda_codec *codec) | |||
1823 | enum { | 1819 | enum { |
1824 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | 1820 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ |
1825 | CXT5051_HP, /* no docking */ | 1821 | CXT5051_HP, /* no docking */ |
1822 | CXT5051_HP_DV6736, /* HP without mic switch */ | ||
1823 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | ||
1826 | CXT5051_MODELS | 1824 | CXT5051_MODELS |
1827 | }; | 1825 | }; |
1828 | 1826 | ||
1829 | static const char *cxt5051_models[CXT5051_MODELS] = { | 1827 | static const char *cxt5051_models[CXT5051_MODELS] = { |
1830 | [CXT5051_LAPTOP] = "laptop", | 1828 | [CXT5051_LAPTOP] = "laptop", |
1831 | [CXT5051_HP] = "hp", | 1829 | [CXT5051_HP] = "hp", |
1830 | [CXT5051_HP_DV6736] = "hp-dv6736", | ||
1831 | [CXT5051_LENOVO_X200] = "lenovo-x200", | ||
1832 | }; | 1832 | }; |
1833 | 1833 | ||
1834 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1834 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { |
1835 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | ||
1835 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | 1836 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", |
1836 | CXT5051_LAPTOP), | 1837 | CXT5051_LAPTOP), |
1837 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | 1838 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), |
1839 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), | ||
1838 | {} | 1840 | {} |
1839 | }; | 1841 | }; |
1840 | 1842 | ||
@@ -1847,6 +1849,7 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1847 | if (!spec) | 1849 | if (!spec) |
1848 | return -ENOMEM; | 1850 | return -ENOMEM; |
1849 | codec->spec = spec; | 1851 | codec->spec = spec; |
1852 | codec->pin_amp_workaround = 1; | ||
1850 | 1853 | ||
1851 | codec->patch_ops = conexant_patch_ops; | 1854 | codec->patch_ops = conexant_patch_ops; |
1852 | codec->patch_ops.init = cxt5051_init; | 1855 | codec->patch_ops.init = cxt5051_init; |
@@ -1867,17 +1870,22 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1867 | spec->cur_adc = 0; | 1870 | spec->cur_adc = 0; |
1868 | spec->cur_adc_idx = 0; | 1871 | spec->cur_adc_idx = 0; |
1869 | 1872 | ||
1873 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1874 | |||
1870 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | 1875 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, |
1871 | cxt5051_models, | 1876 | cxt5051_models, |
1872 | cxt5051_cfg_tbl); | 1877 | cxt5051_cfg_tbl); |
1873 | switch (board_config) { | 1878 | switch (board_config) { |
1874 | case CXT5051_HP: | 1879 | case CXT5051_HP: |
1875 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1876 | spec->mixers[0] = cxt5051_hp_mixers; | 1880 | spec->mixers[0] = cxt5051_hp_mixers; |
1877 | break; | 1881 | break; |
1878 | default: | 1882 | case CXT5051_HP_DV6736: |
1879 | case CXT5051_LAPTOP: | 1883 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; |
1880 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | 1884 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; |
1885 | spec->no_auto_mic = 1; | ||
1886 | break; | ||
1887 | case CXT5051_LENOVO_X200: | ||
1888 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; | ||
1881 | break; | 1889 | break; |
1882 | } | 1890 | } |
1883 | 1891 | ||
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 3564f4e4b74c..fcc77fec4487 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c | |||
@@ -49,11 +49,6 @@ static struct hda_verb pinout_enable_verb[] = { | |||
49 | {} /* terminator */ | 49 | {} /* terminator */ |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static struct hda_verb pinout_disable_verb[] = { | ||
53 | {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00}, | ||
54 | {} | ||
55 | }; | ||
56 | |||
57 | static struct hda_verb unsolicited_response_verb[] = { | 52 | static struct hda_verb unsolicited_response_verb[] = { |
58 | {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | | 53 | {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | |
59 | INTEL_HDMI_EVENT_TAG}, | 54 | INTEL_HDMI_EVENT_TAG}, |
@@ -248,10 +243,6 @@ static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid, | |||
248 | 243 | ||
249 | static void hdmi_enable_output(struct hda_codec *codec) | 244 | static void hdmi_enable_output(struct hda_codec *codec) |
250 | { | 245 | { |
251 | /* Enable Audio InfoFrame Transmission */ | ||
252 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | ||
253 | snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
254 | AC_DIPXMIT_BEST); | ||
255 | /* Unmute */ | 246 | /* Unmute */ |
256 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | 247 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) |
257 | snd_hda_codec_write(codec, PIN_NID, 0, | 248 | snd_hda_codec_write(codec, PIN_NID, 0, |
@@ -260,17 +251,24 @@ static void hdmi_enable_output(struct hda_codec *codec) | |||
260 | snd_hda_sequence_write(codec, pinout_enable_verb); | 251 | snd_hda_sequence_write(codec, pinout_enable_verb); |
261 | } | 252 | } |
262 | 253 | ||
263 | static void hdmi_disable_output(struct hda_codec *codec) | 254 | /* |
255 | * Enable Audio InfoFrame Transmission | ||
256 | */ | ||
257 | static void hdmi_start_infoframe_trans(struct hda_codec *codec) | ||
264 | { | 258 | { |
265 | snd_hda_sequence_write(codec, pinout_disable_verb); | 259 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); |
266 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | 260 | snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT, |
267 | snd_hda_codec_write(codec, PIN_NID, 0, | 261 | AC_DIPXMIT_BEST); |
268 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 262 | } |
269 | 263 | ||
270 | /* | 264 | /* |
271 | * FIXME: noises may arise when playing music after reloading the | 265 | * Disable Audio InfoFrame Transmission |
272 | * kernel module, until the next X restart or monitor repower. | 266 | */ |
273 | */ | 267 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec) |
268 | { | ||
269 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | ||
270 | snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
271 | AC_DIPXMIT_DISABLE); | ||
274 | } | 272 | } |
275 | 273 | ||
276 | static int hdmi_get_channel_count(struct hda_codec *codec) | 274 | static int hdmi_get_channel_count(struct hda_codec *codec) |
@@ -368,11 +366,16 @@ static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | |||
368 | struct hdmi_audio_infoframe *ai) | 366 | struct hdmi_audio_infoframe *ai) |
369 | { | 367 | { |
370 | u8 *params = (u8 *)ai; | 368 | u8 *params = (u8 *)ai; |
369 | u8 sum = 0; | ||
371 | int i; | 370 | int i; |
372 | 371 | ||
373 | hdmi_debug_dip_size(codec); | 372 | hdmi_debug_dip_size(codec); |
374 | hdmi_clear_dip_buffers(codec); /* be paranoid */ | 373 | hdmi_clear_dip_buffers(codec); /* be paranoid */ |
375 | 374 | ||
375 | for (i = 0; i < sizeof(ai); i++) | ||
376 | sum += params[i]; | ||
377 | ai->checksum = - sum; | ||
378 | |||
376 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | 379 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); |
377 | for (i = 0; i < sizeof(ai); i++) | 380 | for (i = 0; i < sizeof(ai); i++) |
378 | hdmi_write_dip_byte(codec, PIN_NID, params[i]); | 381 | hdmi_write_dip_byte(codec, PIN_NID, params[i]); |
@@ -419,14 +422,18 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, | |||
419 | /* | 422 | /* |
420 | * CA defaults to 0 for basic stereo audio | 423 | * CA defaults to 0 for basic stereo audio |
421 | */ | 424 | */ |
422 | if (!eld->eld_ver) | ||
423 | return 0; | ||
424 | if (!eld->spk_alloc) | ||
425 | return 0; | ||
426 | if (channels <= 2) | 425 | if (channels <= 2) |
427 | return 0; | 426 | return 0; |
428 | 427 | ||
429 | /* | 428 | /* |
429 | * HDMI sink's ELD info cannot always be retrieved for now, e.g. | ||
430 | * in console or for audio devices. Assume the highest speakers | ||
431 | * configuration, to _not_ prohibit multi-channel audio playback. | ||
432 | */ | ||
433 | if (!eld->spk_alloc) | ||
434 | eld->spk_alloc = 0xffff; | ||
435 | |||
436 | /* | ||
430 | * expand ELD's speaker allocation mask | 437 | * expand ELD's speaker allocation mask |
431 | * | 438 | * |
432 | * ELD tells the speaker mask in a compact(paired) form, | 439 | * ELD tells the speaker mask in a compact(paired) form, |
@@ -485,6 +492,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
485 | hdmi_setup_channel_mapping(codec, &ai); | 492 | hdmi_setup_channel_mapping(codec, &ai); |
486 | 493 | ||
487 | hdmi_fill_audio_infoframe(codec, &ai); | 494 | hdmi_fill_audio_infoframe(codec, &ai); |
495 | hdmi_start_infoframe_trans(codec); | ||
488 | } | 496 | } |
489 | 497 | ||
490 | 498 | ||
@@ -562,7 +570,7 @@ static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
562 | { | 570 | { |
563 | struct intel_hdmi_spec *spec = codec->spec; | 571 | struct intel_hdmi_spec *spec = codec->spec; |
564 | 572 | ||
565 | hdmi_disable_output(codec); | 573 | hdmi_stop_infoframe_trans(codec); |
566 | 574 | ||
567 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 575 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
568 | } | 576 | } |
@@ -582,8 +590,6 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
582 | 590 | ||
583 | hdmi_setup_audio_infoframe(codec, substream); | 591 | hdmi_setup_audio_infoframe(codec, substream); |
584 | 592 | ||
585 | hdmi_enable_output(codec); | ||
586 | |||
587 | return 0; | 593 | return 0; |
588 | } | 594 | } |
589 | 595 | ||
@@ -628,8 +634,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec) | |||
628 | 634 | ||
629 | static int intel_hdmi_init(struct hda_codec *codec) | 635 | static int intel_hdmi_init(struct hda_codec *codec) |
630 | { | 636 | { |
631 | /* disable audio output as early as possible */ | 637 | hdmi_enable_output(codec); |
632 | hdmi_disable_output(codec); | ||
633 | 638 | ||
634 | snd_hda_sequence_write(codec, unsolicited_response_verb); | 639 | snd_hda_sequence_write(codec, unsolicited_response_verb); |
635 | 640 | ||
@@ -679,6 +684,7 @@ static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | |||
679 | { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, | 684 | { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, |
680 | { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, | 685 | { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, |
681 | { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, | 686 | { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, |
687 | { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi }, | ||
682 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, | 688 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, |
683 | {} /* terminator */ | 689 | {} /* terminator */ |
684 | }; | 690 | }; |
@@ -687,6 +693,7 @@ MODULE_ALIAS("snd-hda-codec-id:808629fb"); | |||
687 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | 693 | MODULE_ALIAS("snd-hda-codec-id:80862801"); |
688 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | 694 | MODULE_ALIAS("snd-hda-codec-id:80862802"); |
689 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | 695 | MODULE_ALIAS("snd-hda-codec-id:80862803"); |
696 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
690 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | 697 | MODULE_ALIAS("snd-hda-codec-id:10951392"); |
691 | 698 | ||
692 | MODULE_LICENSE("GPL"); | 699 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ae5c8a0d1479..82097790f6f3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include "hda_codec.h" | 31 | #include "hda_codec.h" |
32 | #include "hda_local.h" | 32 | #include "hda_local.h" |
33 | #include "hda_beep.h" | ||
33 | 34 | ||
34 | #define ALC880_FRONT_EVENT 0x01 | 35 | #define ALC880_FRONT_EVENT 0x01 |
35 | #define ALC880_DCVOL_EVENT 0x02 | 36 | #define ALC880_DCVOL_EVENT 0x02 |
@@ -77,6 +78,7 @@ enum { | |||
77 | ALC260_ACER, | 78 | ALC260_ACER, |
78 | ALC260_WILL, | 79 | ALC260_WILL, |
79 | ALC260_REPLACER_672V, | 80 | ALC260_REPLACER_672V, |
81 | ALC260_FAVORIT100, | ||
80 | #ifdef CONFIG_SND_DEBUG | 82 | #ifdef CONFIG_SND_DEBUG |
81 | ALC260_TEST, | 83 | ALC260_TEST, |
82 | #endif | 84 | #endif |
@@ -103,6 +105,7 @@ enum { | |||
103 | ALC262_NEC, | 105 | ALC262_NEC, |
104 | ALC262_TOSHIBA_S06, | 106 | ALC262_TOSHIBA_S06, |
105 | ALC262_TOSHIBA_RX1, | 107 | ALC262_TOSHIBA_RX1, |
108 | ALC262_TYAN, | ||
106 | ALC262_AUTO, | 109 | ALC262_AUTO, |
107 | ALC262_MODEL_LAST /* last tag */ | 110 | ALC262_MODEL_LAST /* last tag */ |
108 | }; | 111 | }; |
@@ -238,6 +241,13 @@ enum { | |||
238 | ALC883_MODEL_LAST, | 241 | ALC883_MODEL_LAST, |
239 | }; | 242 | }; |
240 | 243 | ||
244 | /* styles of capture selection */ | ||
245 | enum { | ||
246 | CAPT_MUX = 0, /* only mux based */ | ||
247 | CAPT_MIX, /* only mixer based */ | ||
248 | CAPT_1MUX_MIX, /* first mux and other mixers */ | ||
249 | }; | ||
250 | |||
241 | /* for GPIO Poll */ | 251 | /* for GPIO Poll */ |
242 | #define GPIO_MASK 0x03 | 252 | #define GPIO_MASK 0x03 |
243 | 253 | ||
@@ -246,6 +256,7 @@ struct alc_spec { | |||
246 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 256 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
247 | unsigned int num_mixers; | 257 | unsigned int num_mixers; |
248 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | 258 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ |
259 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ | ||
249 | 260 | ||
250 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 261 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
251 | * don't forget NULL | 262 | * don't forget NULL |
@@ -269,13 +280,15 @@ struct alc_spec { | |||
269 | * dig_out_nid and hp_nid are optional | 280 | * dig_out_nid and hp_nid are optional |
270 | */ | 281 | */ |
271 | hda_nid_t alt_dac_nid; | 282 | hda_nid_t alt_dac_nid; |
283 | hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */ | ||
284 | int dig_out_type; | ||
272 | 285 | ||
273 | /* capture */ | 286 | /* capture */ |
274 | unsigned int num_adc_nids; | 287 | unsigned int num_adc_nids; |
275 | hda_nid_t *adc_nids; | 288 | hda_nid_t *adc_nids; |
276 | hda_nid_t *capsrc_nids; | 289 | hda_nid_t *capsrc_nids; |
277 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 290 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
278 | unsigned char is_mix_capture; /* matrix-style capture (non-mux) */ | 291 | int capture_style; /* capture style (CAPT_*) */ |
279 | 292 | ||
280 | /* capture source */ | 293 | /* capture source */ |
281 | unsigned int num_mux_defs; | 294 | unsigned int num_mux_defs; |
@@ -293,7 +306,7 @@ struct alc_spec { | |||
293 | /* dynamic controls, init_verbs and input_mux */ | 306 | /* dynamic controls, init_verbs and input_mux */ |
294 | struct auto_pin_cfg autocfg; | 307 | struct auto_pin_cfg autocfg; |
295 | struct snd_array kctls; | 308 | struct snd_array kctls; |
296 | struct hda_input_mux private_imux; | 309 | struct hda_input_mux private_imux[3]; |
297 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 310 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
298 | 311 | ||
299 | /* hooks */ | 312 | /* hooks */ |
@@ -305,6 +318,9 @@ struct alc_spec { | |||
305 | unsigned int jack_present: 1; | 318 | unsigned int jack_present: 1; |
306 | unsigned int master_sw: 1; | 319 | unsigned int master_sw: 1; |
307 | 320 | ||
321 | /* other flags */ | ||
322 | unsigned int no_analog :1; /* digital I/O only */ | ||
323 | |||
308 | /* for virtual master */ | 324 | /* for virtual master */ |
309 | hda_nid_t vmaster_nid; | 325 | hda_nid_t vmaster_nid; |
310 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 326 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -314,13 +330,6 @@ struct alc_spec { | |||
314 | /* for PLL fix */ | 330 | /* for PLL fix */ |
315 | hda_nid_t pll_nid; | 331 | hda_nid_t pll_nid; |
316 | unsigned int pll_coef_idx, pll_coef_bit; | 332 | unsigned int pll_coef_idx, pll_coef_bit; |
317 | |||
318 | #ifdef SND_HDA_NEEDS_RESUME | ||
319 | #define ALC_MAX_PINS 16 | ||
320 | unsigned int num_pins; | ||
321 | hda_nid_t pin_nids[ALC_MAX_PINS]; | ||
322 | unsigned int pin_cfgs[ALC_MAX_PINS]; | ||
323 | #endif | ||
324 | }; | 333 | }; |
325 | 334 | ||
326 | /* | 335 | /* |
@@ -336,6 +345,7 @@ struct alc_config_preset { | |||
336 | hda_nid_t *dac_nids; | 345 | hda_nid_t *dac_nids; |
337 | hda_nid_t dig_out_nid; /* optional */ | 346 | hda_nid_t dig_out_nid; /* optional */ |
338 | hda_nid_t hp_nid; /* optional */ | 347 | hda_nid_t hp_nid; /* optional */ |
348 | hda_nid_t *slave_dig_outs; | ||
339 | unsigned int num_adc_nids; | 349 | unsigned int num_adc_nids; |
340 | hda_nid_t *adc_nids; | 350 | hda_nid_t *adc_nids; |
341 | hda_nid_t *capsrc_nids; | 351 | hda_nid_t *capsrc_nids; |
@@ -392,7 +402,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
392 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 402 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
393 | imux = &spec->input_mux[mux_idx]; | 403 | imux = &spec->input_mux[mux_idx]; |
394 | 404 | ||
395 | if (spec->is_mix_capture) { | 405 | if (spec->capture_style && |
406 | !(spec->capture_style == CAPT_1MUX_MIX && !adc_idx)) { | ||
396 | /* Matrix-mixer style (e.g. ALC882) */ | 407 | /* Matrix-mixer style (e.g. ALC882) */ |
397 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | 408 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; |
398 | unsigned int i, idx; | 409 | unsigned int i, idx; |
@@ -750,6 +761,24 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
750 | #endif /* CONFIG_SND_DEBUG */ | 761 | #endif /* CONFIG_SND_DEBUG */ |
751 | 762 | ||
752 | /* | 763 | /* |
764 | * set up the input pin config (depending on the given auto-pin type) | ||
765 | */ | ||
766 | static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | ||
767 | int auto_pin_type) | ||
768 | { | ||
769 | unsigned int val = PIN_IN; | ||
770 | |||
771 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | ||
772 | unsigned int pincap; | ||
773 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
774 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | ||
775 | if (pincap & AC_PINCAP_VREF_80) | ||
776 | val = PIN_VREF80; | ||
777 | } | ||
778 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
779 | } | ||
780 | |||
781 | /* | ||
753 | */ | 782 | */ |
754 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | 783 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) |
755 | { | 784 | { |
@@ -810,6 +839,7 @@ static void setup_preset(struct alc_spec *spec, | |||
810 | spec->multiout.num_dacs = preset->num_dacs; | 839 | spec->multiout.num_dacs = preset->num_dacs; |
811 | spec->multiout.dac_nids = preset->dac_nids; | 840 | spec->multiout.dac_nids = preset->dac_nids; |
812 | spec->multiout.dig_out_nid = preset->dig_out_nid; | 841 | spec->multiout.dig_out_nid = preset->dig_out_nid; |
842 | spec->multiout.slave_dig_outs = preset->slave_dig_outs; | ||
813 | spec->multiout.hp_nid = preset->hp_nid; | 843 | spec->multiout.hp_nid = preset->hp_nid; |
814 | 844 | ||
815 | spec->num_mux_defs = preset->num_mux_defs; | 845 | spec->num_mux_defs = preset->num_mux_defs; |
@@ -921,7 +951,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
921 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | 951 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
922 | } | 952 | } |
923 | #else | 953 | #else |
924 | #define alc_mic_automute(codec) /* NOP */ | 954 | #define alc_mic_automute(codec) do {} while(0) /* NOP */ |
925 | #endif /* disabled */ | 955 | #endif /* disabled */ |
926 | 956 | ||
927 | /* unsolicited event for HP jack sensing */ | 957 | /* unsolicited event for HP jack sensing */ |
@@ -952,7 +982,7 @@ static void alc888_coef_init(struct hda_codec *codec) | |||
952 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0); | 982 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0); |
953 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); | 983 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); |
954 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); | 984 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); |
955 | if ((tmp & 0xf0) == 2) | 985 | if ((tmp & 0xf0) == 0x20) |
956 | /* alc888S-VC */ | 986 | /* alc888S-VC */ |
957 | snd_hda_codec_read(codec, 0x20, 0, | 987 | snd_hda_codec_read(codec, 0x20, 0, |
958 | AC_VERB_SET_PROC_COEF, 0x830); | 988 | AC_VERB_SET_PROC_COEF, 0x830); |
@@ -991,8 +1021,7 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
991 | nid = 0x1d; | 1021 | nid = 0x1d; |
992 | if (codec->vendor_id == 0x10ec0260) | 1022 | if (codec->vendor_id == 0x10ec0260) |
993 | nid = 0x17; | 1023 | nid = 0x17; |
994 | ass = snd_hda_codec_read(codec, nid, 0, | 1024 | ass = snd_hda_codec_get_pincfg(codec, nid); |
995 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
996 | if (!(ass & 1) && !(ass & 0x100000)) | 1025 | if (!(ass & 1) && !(ass & 0x100000)) |
997 | return; | 1026 | return; |
998 | if ((ass >> 30) != 1) /* no physical connection */ | 1027 | if ((ass >> 30) != 1) /* no physical connection */ |
@@ -1166,16 +1195,8 @@ static void alc_fix_pincfg(struct hda_codec *codec, | |||
1166 | return; | 1195 | return; |
1167 | 1196 | ||
1168 | cfg = pinfix[quirk->value]; | 1197 | cfg = pinfix[quirk->value]; |
1169 | for (; cfg->nid; cfg++) { | 1198 | for (; cfg->nid; cfg++) |
1170 | int i; | 1199 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); |
1171 | u32 val = cfg->val; | ||
1172 | for (i = 0; i < 4; i++) { | ||
1173 | snd_hda_codec_write(codec, cfg->nid, 0, | ||
1174 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, | ||
1175 | val & 0xff); | ||
1176 | val >>= 8; | ||
1177 | } | ||
1178 | } | ||
1179 | } | 1200 | } |
1180 | 1201 | ||
1181 | /* | 1202 | /* |
@@ -1375,8 +1396,6 @@ static struct snd_kcontrol_new alc888_base_mixer[] = { | |||
1375 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 1396 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
1376 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 1397 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
1377 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1398 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1378 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1379 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1380 | { } /* end */ | 1399 | { } /* end */ |
1381 | }; | 1400 | }; |
1382 | 1401 | ||
@@ -1483,8 +1502,6 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = { | |||
1483 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1502 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1484 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | 1503 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), |
1485 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 1504 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), |
1486 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1487 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1488 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | 1505 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), |
1489 | { | 1506 | { |
1490 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1507 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1578,8 +1595,7 @@ static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, | |||
1578 | snd_hda_mixer_amp_switch_put); | 1595 | snd_hda_mixer_amp_switch_put); |
1579 | } | 1596 | } |
1580 | 1597 | ||
1581 | #define DEFINE_CAPMIX(num) \ | 1598 | #define _DEFINE_CAPMIX(num) \ |
1582 | static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | ||
1583 | { \ | 1599 | { \ |
1584 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1600 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1585 | .name = "Capture Switch", \ | 1601 | .name = "Capture Switch", \ |
@@ -1600,7 +1616,9 @@ static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | |||
1600 | .get = alc_cap_vol_get, \ | 1616 | .get = alc_cap_vol_get, \ |
1601 | .put = alc_cap_vol_put, \ | 1617 | .put = alc_cap_vol_put, \ |
1602 | .tlv = { .c = alc_cap_vol_tlv }, \ | 1618 | .tlv = { .c = alc_cap_vol_tlv }, \ |
1603 | }, \ | 1619 | } |
1620 | |||
1621 | #define _DEFINE_CAPSRC(num) \ | ||
1604 | { \ | 1622 | { \ |
1605 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1623 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1606 | /* .name = "Capture Source", */ \ | 1624 | /* .name = "Capture Source", */ \ |
@@ -1609,15 +1627,28 @@ static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | |||
1609 | .info = alc_mux_enum_info, \ | 1627 | .info = alc_mux_enum_info, \ |
1610 | .get = alc_mux_enum_get, \ | 1628 | .get = alc_mux_enum_get, \ |
1611 | .put = alc_mux_enum_put, \ | 1629 | .put = alc_mux_enum_put, \ |
1612 | }, \ | 1630 | } |
1613 | { } /* end */ \ | 1631 | |
1632 | #define DEFINE_CAPMIX(num) \ | ||
1633 | static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | ||
1634 | _DEFINE_CAPMIX(num), \ | ||
1635 | _DEFINE_CAPSRC(num), \ | ||
1636 | { } /* end */ \ | ||
1637 | } | ||
1638 | |||
1639 | #define DEFINE_CAPMIX_NOSRC(num) \ | ||
1640 | static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \ | ||
1641 | _DEFINE_CAPMIX(num), \ | ||
1642 | { } /* end */ \ | ||
1614 | } | 1643 | } |
1615 | 1644 | ||
1616 | /* up to three ADCs */ | 1645 | /* up to three ADCs */ |
1617 | DEFINE_CAPMIX(1); | 1646 | DEFINE_CAPMIX(1); |
1618 | DEFINE_CAPMIX(2); | 1647 | DEFINE_CAPMIX(2); |
1619 | DEFINE_CAPMIX(3); | 1648 | DEFINE_CAPMIX(3); |
1620 | 1649 | DEFINE_CAPMIX_NOSRC(1); | |
1650 | DEFINE_CAPMIX_NOSRC(2); | ||
1651 | DEFINE_CAPMIX_NOSRC(3); | ||
1621 | 1652 | ||
1622 | /* | 1653 | /* |
1623 | * ALC880 5-stack model | 1654 | * ALC880 5-stack model |
@@ -1706,8 +1737,6 @@ static struct snd_kcontrol_new alc880_six_stack_mixer[] = { | |||
1706 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1737 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1707 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 1738 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
1708 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 1739 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
1709 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1710 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1711 | { | 1740 | { |
1712 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1741 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1713 | .name = "Channel Mode", | 1742 | .name = "Channel Mode", |
@@ -1884,13 +1913,6 @@ static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { | |||
1884 | { } /* end */ | 1913 | { } /* end */ |
1885 | }; | 1914 | }; |
1886 | 1915 | ||
1887 | /* additional mixers to alc880_asus_mixer */ | ||
1888 | static struct snd_kcontrol_new alc880_pcbeep_mixer[] = { | ||
1889 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1890 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1891 | { } /* end */ | ||
1892 | }; | ||
1893 | |||
1894 | /* TCL S700 */ | 1916 | /* TCL S700 */ |
1895 | static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { | 1917 | static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { |
1896 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 1918 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -1923,8 +1945,6 @@ static struct snd_kcontrol_new alc880_uniwill_mixer[] = { | |||
1923 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1945 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1924 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 1946 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
1925 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 1947 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
1926 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1927 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1928 | { | 1948 | { |
1929 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1949 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1930 | .name = "Channel Mode", | 1950 | .name = "Channel Mode", |
@@ -1999,6 +2019,13 @@ static const char *alc_slave_sws[] = { | |||
1999 | 2019 | ||
2000 | static void alc_free_kctls(struct hda_codec *codec); | 2020 | static void alc_free_kctls(struct hda_codec *codec); |
2001 | 2021 | ||
2022 | /* additional beep mixers; the actual parameters are overwritten at build */ | ||
2023 | static struct snd_kcontrol_new alc_beep_mixer[] = { | ||
2024 | HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), | ||
2025 | HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_INPUT), | ||
2026 | { } /* end */ | ||
2027 | }; | ||
2028 | |||
2002 | static int alc_build_controls(struct hda_codec *codec) | 2029 | static int alc_build_controls(struct hda_codec *codec) |
2003 | { | 2030 | { |
2004 | struct alc_spec *spec = codec->spec; | 2031 | struct alc_spec *spec = codec->spec; |
@@ -2020,11 +2047,13 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2020 | spec->multiout.dig_out_nid); | 2047 | spec->multiout.dig_out_nid); |
2021 | if (err < 0) | 2048 | if (err < 0) |
2022 | return err; | 2049 | return err; |
2023 | err = snd_hda_create_spdif_share_sw(codec, | 2050 | if (!spec->no_analog) { |
2024 | &spec->multiout); | 2051 | err = snd_hda_create_spdif_share_sw(codec, |
2025 | if (err < 0) | 2052 | &spec->multiout); |
2026 | return err; | 2053 | if (err < 0) |
2027 | spec->multiout.share_spdif = 1; | 2054 | return err; |
2055 | spec->multiout.share_spdif = 1; | ||
2056 | } | ||
2028 | } | 2057 | } |
2029 | if (spec->dig_in_nid) { | 2058 | if (spec->dig_in_nid) { |
2030 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | 2059 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); |
@@ -2032,8 +2061,24 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2032 | return err; | 2061 | return err; |
2033 | } | 2062 | } |
2034 | 2063 | ||
2064 | /* create beep controls if needed */ | ||
2065 | if (spec->beep_amp) { | ||
2066 | struct snd_kcontrol_new *knew; | ||
2067 | for (knew = alc_beep_mixer; knew->name; knew++) { | ||
2068 | struct snd_kcontrol *kctl; | ||
2069 | kctl = snd_ctl_new1(knew, codec); | ||
2070 | if (!kctl) | ||
2071 | return -ENOMEM; | ||
2072 | kctl->private_value = spec->beep_amp; | ||
2073 | err = snd_hda_ctl_add(codec, kctl); | ||
2074 | if (err < 0) | ||
2075 | return err; | ||
2076 | } | ||
2077 | } | ||
2078 | |||
2035 | /* if we have no master control, let's create it */ | 2079 | /* if we have no master control, let's create it */ |
2036 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 2080 | if (!spec->no_analog && |
2081 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
2037 | unsigned int vmaster_tlv[4]; | 2082 | unsigned int vmaster_tlv[4]; |
2038 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 2083 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
2039 | HDA_OUTPUT, vmaster_tlv); | 2084 | HDA_OUTPUT, vmaster_tlv); |
@@ -2042,7 +2087,8 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2042 | if (err < 0) | 2087 | if (err < 0) |
2043 | return err; | 2088 | return err; |
2044 | } | 2089 | } |
2045 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 2090 | if (!spec->no_analog && |
2091 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
2046 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 2092 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
2047 | NULL, alc_slave_sws); | 2093 | NULL, alc_slave_sws); |
2048 | if (err < 0) | 2094 | if (err < 0) |
@@ -2951,6 +2997,14 @@ static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2951 | stream_tag, format, substream); | 2997 | stream_tag, format, substream); |
2952 | } | 2998 | } |
2953 | 2999 | ||
3000 | static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3001 | struct hda_codec *codec, | ||
3002 | struct snd_pcm_substream *substream) | ||
3003 | { | ||
3004 | struct alc_spec *spec = codec->spec; | ||
3005 | return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); | ||
3006 | } | ||
3007 | |||
2954 | static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | 3008 | static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, |
2955 | struct hda_codec *codec, | 3009 | struct hda_codec *codec, |
2956 | struct snd_pcm_substream *substream) | 3010 | struct snd_pcm_substream *substream) |
@@ -3034,7 +3088,8 @@ static struct hda_pcm_stream alc880_pcm_digital_playback = { | |||
3034 | .ops = { | 3088 | .ops = { |
3035 | .open = alc880_dig_playback_pcm_open, | 3089 | .open = alc880_dig_playback_pcm_open, |
3036 | .close = alc880_dig_playback_pcm_close, | 3090 | .close = alc880_dig_playback_pcm_close, |
3037 | .prepare = alc880_dig_playback_pcm_prepare | 3091 | .prepare = alc880_dig_playback_pcm_prepare, |
3092 | .cleanup = alc880_dig_playback_pcm_cleanup | ||
3038 | }, | 3093 | }, |
3039 | }; | 3094 | }; |
3040 | 3095 | ||
@@ -3061,6 +3116,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3061 | codec->num_pcms = 1; | 3116 | codec->num_pcms = 1; |
3062 | codec->pcm_info = info; | 3117 | codec->pcm_info = info; |
3063 | 3118 | ||
3119 | if (spec->no_analog) | ||
3120 | goto skip_analog; | ||
3121 | |||
3064 | info->name = spec->stream_name_analog; | 3122 | info->name = spec->stream_name_analog; |
3065 | if (spec->stream_analog_playback) { | 3123 | if (spec->stream_analog_playback) { |
3066 | if (snd_BUG_ON(!spec->multiout.dac_nids)) | 3124 | if (snd_BUG_ON(!spec->multiout.dac_nids)) |
@@ -3084,12 +3142,17 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3084 | } | 3142 | } |
3085 | } | 3143 | } |
3086 | 3144 | ||
3145 | skip_analog: | ||
3087 | /* SPDIF for stream index #1 */ | 3146 | /* SPDIF for stream index #1 */ |
3088 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 3147 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
3089 | codec->num_pcms = 2; | 3148 | codec->num_pcms = 2; |
3149 | codec->slave_dig_outs = spec->multiout.slave_dig_outs; | ||
3090 | info = spec->pcm_rec + 1; | 3150 | info = spec->pcm_rec + 1; |
3091 | info->name = spec->stream_name_digital; | 3151 | info->name = spec->stream_name_digital; |
3092 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 3152 | if (spec->dig_out_type) |
3153 | info->pcm_type = spec->dig_out_type; | ||
3154 | else | ||
3155 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
3093 | if (spec->multiout.dig_out_nid && | 3156 | if (spec->multiout.dig_out_nid && |
3094 | spec->stream_digital_playback) { | 3157 | spec->stream_digital_playback) { |
3095 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); | 3158 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); |
@@ -3104,6 +3167,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3104 | codec->spdif_status_reset = 1; | 3167 | codec->spdif_status_reset = 1; |
3105 | } | 3168 | } |
3106 | 3169 | ||
3170 | if (spec->no_analog) | ||
3171 | return 0; | ||
3172 | |||
3107 | /* If the use of more than one ADC is requested for the current | 3173 | /* If the use of more than one ADC is requested for the current |
3108 | * model, configure a second analog capture-only PCM. | 3174 | * model, configure a second analog capture-only PCM. |
3109 | */ | 3175 | */ |
@@ -3162,65 +3228,17 @@ static void alc_free(struct hda_codec *codec) | |||
3162 | 3228 | ||
3163 | alc_free_kctls(codec); | 3229 | alc_free_kctls(codec); |
3164 | kfree(spec); | 3230 | kfree(spec); |
3165 | codec->spec = NULL; /* to be sure */ | 3231 | snd_hda_detach_beep_device(codec); |
3166 | } | 3232 | } |
3167 | 3233 | ||
3168 | #ifdef SND_HDA_NEEDS_RESUME | 3234 | #ifdef SND_HDA_NEEDS_RESUME |
3169 | static void store_pin_configs(struct hda_codec *codec) | ||
3170 | { | ||
3171 | struct alc_spec *spec = codec->spec; | ||
3172 | hda_nid_t nid, end_nid; | ||
3173 | |||
3174 | end_nid = codec->start_nid + codec->num_nodes; | ||
3175 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
3176 | unsigned int wid_caps = get_wcaps(codec, nid); | ||
3177 | unsigned int wid_type = | ||
3178 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
3179 | if (wid_type != AC_WID_PIN) | ||
3180 | continue; | ||
3181 | if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids)) | ||
3182 | break; | ||
3183 | spec->pin_nids[spec->num_pins] = nid; | ||
3184 | spec->pin_cfgs[spec->num_pins] = | ||
3185 | snd_hda_codec_read(codec, nid, 0, | ||
3186 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3187 | spec->num_pins++; | ||
3188 | } | ||
3189 | } | ||
3190 | |||
3191 | static void resume_pin_configs(struct hda_codec *codec) | ||
3192 | { | ||
3193 | struct alc_spec *spec = codec->spec; | ||
3194 | int i; | ||
3195 | |||
3196 | for (i = 0; i < spec->num_pins; i++) { | ||
3197 | hda_nid_t pin_nid = spec->pin_nids[i]; | ||
3198 | unsigned int pin_config = spec->pin_cfgs[i]; | ||
3199 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3200 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
3201 | pin_config & 0x000000ff); | ||
3202 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3203 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
3204 | (pin_config & 0x0000ff00) >> 8); | ||
3205 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3206 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
3207 | (pin_config & 0x00ff0000) >> 16); | ||
3208 | snd_hda_codec_write(codec, pin_nid, 0, | ||
3209 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
3210 | pin_config >> 24); | ||
3211 | } | ||
3212 | } | ||
3213 | |||
3214 | static int alc_resume(struct hda_codec *codec) | 3235 | static int alc_resume(struct hda_codec *codec) |
3215 | { | 3236 | { |
3216 | resume_pin_configs(codec); | ||
3217 | codec->patch_ops.init(codec); | 3237 | codec->patch_ops.init(codec); |
3218 | snd_hda_codec_resume_amp(codec); | 3238 | snd_hda_codec_resume_amp(codec); |
3219 | snd_hda_codec_resume_cache(codec); | 3239 | snd_hda_codec_resume_cache(codec); |
3220 | return 0; | 3240 | return 0; |
3221 | } | 3241 | } |
3222 | #else | ||
3223 | #define store_pin_configs(codec) | ||
3224 | #endif | 3242 | #endif |
3225 | 3243 | ||
3226 | /* | 3244 | /* |
@@ -3559,7 +3577,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
3559 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), | 3577 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), |
3560 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), | 3578 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), |
3561 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), | 3579 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), |
3562 | SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), /* default ASUS */ | 3580 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */ |
3563 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), | 3581 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), |
3564 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), | 3582 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), |
3565 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), | 3583 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), |
@@ -3602,7 +3620,8 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
3602 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), | 3620 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), |
3603 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), | 3621 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), |
3604 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), | 3622 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), |
3605 | SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), /* default Intel */ | 3623 | /* default Intel */ |
3624 | SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST), | ||
3606 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), | 3625 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), |
3607 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), | 3626 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), |
3608 | {} | 3627 | {} |
@@ -3782,7 +3801,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
3782 | .input_mux = &alc880_capture_source, | 3801 | .input_mux = &alc880_capture_source, |
3783 | }, | 3802 | }, |
3784 | [ALC880_UNIWILL_DIG] = { | 3803 | [ALC880_UNIWILL_DIG] = { |
3785 | .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, | 3804 | .mixers = { alc880_asus_mixer }, |
3786 | .init_verbs = { alc880_volume_init_verbs, | 3805 | .init_verbs = { alc880_volume_init_verbs, |
3787 | alc880_pin_asus_init_verbs }, | 3806 | alc880_pin_asus_init_verbs }, |
3788 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 3807 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
@@ -3820,8 +3839,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
3820 | .init_hook = alc880_uniwill_p53_hp_automute, | 3839 | .init_hook = alc880_uniwill_p53_hp_automute, |
3821 | }, | 3840 | }, |
3822 | [ALC880_FUJITSU] = { | 3841 | [ALC880_FUJITSU] = { |
3823 | .mixers = { alc880_fujitsu_mixer, | 3842 | .mixers = { alc880_fujitsu_mixer }, |
3824 | alc880_pcbeep_mixer, }, | ||
3825 | .init_verbs = { alc880_volume_init_verbs, | 3843 | .init_verbs = { alc880_volume_init_verbs, |
3826 | alc880_uniwill_p53_init_verbs, | 3844 | alc880_uniwill_p53_init_verbs, |
3827 | alc880_beep_init_verbs }, | 3845 | alc880_beep_init_verbs }, |
@@ -4114,7 +4132,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | |||
4114 | static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, | 4132 | static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, |
4115 | const struct auto_pin_cfg *cfg) | 4133 | const struct auto_pin_cfg *cfg) |
4116 | { | 4134 | { |
4117 | struct hda_input_mux *imux = &spec->private_imux; | 4135 | struct hda_input_mux *imux = &spec->private_imux[0]; |
4118 | int i, err, idx; | 4136 | int i, err, idx; |
4119 | 4137 | ||
4120 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4138 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -4202,11 +4220,9 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) | |||
4202 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4220 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
4203 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 4221 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
4204 | if (alc880_is_input_pin(nid)) { | 4222 | if (alc880_is_input_pin(nid)) { |
4205 | snd_hda_codec_write(codec, nid, 0, | 4223 | alc_set_input_pin(codec, nid, i); |
4206 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 4224 | if (nid != ALC880_PIN_CD_NID && |
4207 | i <= AUTO_PIN_FRONT_MIC ? | 4225 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
4208 | PIN_VREF80 : PIN_IN); | ||
4209 | if (nid != ALC880_PIN_CD_NID) | ||
4210 | snd_hda_codec_write(codec, nid, 0, | 4226 | snd_hda_codec_write(codec, nid, 0, |
4211 | AC_VERB_SET_AMP_GAIN_MUTE, | 4227 | AC_VERB_SET_AMP_GAIN_MUTE, |
4212 | AMP_OUT_MUTE); | 4228 | AMP_OUT_MUTE); |
@@ -4221,7 +4237,7 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) | |||
4221 | static int alc880_parse_auto_config(struct hda_codec *codec) | 4237 | static int alc880_parse_auto_config(struct hda_codec *codec) |
4222 | { | 4238 | { |
4223 | struct alc_spec *spec = codec->spec; | 4239 | struct alc_spec *spec = codec->spec; |
4224 | int err; | 4240 | int i, err; |
4225 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; | 4241 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; |
4226 | 4242 | ||
4227 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 4243 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
@@ -4252,8 +4268,23 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4252 | 4268 | ||
4253 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 4269 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
4254 | 4270 | ||
4255 | if (spec->autocfg.dig_out_pin) | 4271 | /* check multiple SPDIF-out (for recent codecs) */ |
4256 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 4272 | for (i = 0; i < spec->autocfg.dig_outs; i++) { |
4273 | hda_nid_t dig_nid; | ||
4274 | err = snd_hda_get_connections(codec, | ||
4275 | spec->autocfg.dig_out_pins[i], | ||
4276 | &dig_nid, 1); | ||
4277 | if (err < 0) | ||
4278 | continue; | ||
4279 | if (!i) | ||
4280 | spec->multiout.dig_out_nid = dig_nid; | ||
4281 | else { | ||
4282 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
4283 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
4284 | if (i == ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
4285 | break; | ||
4286 | } | ||
4287 | } | ||
4257 | if (spec->autocfg.dig_in_pin) | 4288 | if (spec->autocfg.dig_in_pin) |
4258 | spec->dig_in_nid = ALC880_DIGIN_NID; | 4289 | spec->dig_in_nid = ALC880_DIGIN_NID; |
4259 | 4290 | ||
@@ -4263,9 +4294,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4263 | add_verb(spec, alc880_volume_init_verbs); | 4294 | add_verb(spec, alc880_volume_init_verbs); |
4264 | 4295 | ||
4265 | spec->num_mux_defs = 1; | 4296 | spec->num_mux_defs = 1; |
4266 | spec->input_mux = &spec->private_imux; | 4297 | spec->input_mux = &spec->private_imux[0]; |
4267 | 4298 | ||
4268 | store_pin_configs(codec); | ||
4269 | return 1; | 4299 | return 1; |
4270 | } | 4300 | } |
4271 | 4301 | ||
@@ -4280,21 +4310,33 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
4280 | alc_inithook(codec); | 4310 | alc_inithook(codec); |
4281 | } | 4311 | } |
4282 | 4312 | ||
4283 | /* | ||
4284 | * OK, here we have finally the patch for ALC880 | ||
4285 | */ | ||
4286 | |||
4287 | static void set_capture_mixer(struct alc_spec *spec) | 4313 | static void set_capture_mixer(struct alc_spec *spec) |
4288 | { | 4314 | { |
4289 | static struct snd_kcontrol_new *caps[3] = { | 4315 | static struct snd_kcontrol_new *caps[2][3] = { |
4290 | alc_capture_mixer1, | 4316 | { alc_capture_mixer_nosrc1, |
4291 | alc_capture_mixer2, | 4317 | alc_capture_mixer_nosrc2, |
4292 | alc_capture_mixer3, | 4318 | alc_capture_mixer_nosrc3 }, |
4319 | { alc_capture_mixer1, | ||
4320 | alc_capture_mixer2, | ||
4321 | alc_capture_mixer3 }, | ||
4293 | }; | 4322 | }; |
4294 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) | 4323 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { |
4295 | spec->cap_mixer = caps[spec->num_adc_nids - 1]; | 4324 | int mux; |
4325 | if (spec->input_mux && spec->input_mux->num_items > 1) | ||
4326 | mux = 1; | ||
4327 | else | ||
4328 | mux = 0; | ||
4329 | spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; | ||
4330 | } | ||
4296 | } | 4331 | } |
4297 | 4332 | ||
4333 | #define set_beep_amp(spec, nid, idx, dir) \ | ||
4334 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) | ||
4335 | |||
4336 | /* | ||
4337 | * OK, here we have finally the patch for ALC880 | ||
4338 | */ | ||
4339 | |||
4298 | static int patch_alc880(struct hda_codec *codec) | 4340 | static int patch_alc880(struct hda_codec *codec) |
4299 | { | 4341 | { |
4300 | struct alc_spec *spec; | 4342 | struct alc_spec *spec; |
@@ -4330,6 +4372,12 @@ static int patch_alc880(struct hda_codec *codec) | |||
4330 | } | 4372 | } |
4331 | } | 4373 | } |
4332 | 4374 | ||
4375 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
4376 | if (err < 0) { | ||
4377 | alc_free(codec); | ||
4378 | return err; | ||
4379 | } | ||
4380 | |||
4333 | if (board_config != ALC880_AUTO) | 4381 | if (board_config != ALC880_AUTO) |
4334 | setup_preset(spec, &alc880_presets[board_config]); | 4382 | setup_preset(spec, &alc880_presets[board_config]); |
4335 | 4383 | ||
@@ -4356,6 +4404,7 @@ static int patch_alc880(struct hda_codec *codec) | |||
4356 | } | 4404 | } |
4357 | } | 4405 | } |
4358 | set_capture_mixer(spec); | 4406 | set_capture_mixer(spec); |
4407 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
4359 | 4408 | ||
4360 | spec->vmaster_nid = 0x0c; | 4409 | spec->vmaster_nid = 0x0c; |
4361 | 4410 | ||
@@ -4463,6 +4512,26 @@ static struct hda_input_mux alc260_acer_capture_sources[2] = { | |||
4463 | }, | 4512 | }, |
4464 | }, | 4513 | }, |
4465 | }; | 4514 | }; |
4515 | |||
4516 | /* Maxdata Favorit 100XS */ | ||
4517 | static struct hda_input_mux alc260_favorit100_capture_sources[2] = { | ||
4518 | { | ||
4519 | .num_items = 2, | ||
4520 | .items = { | ||
4521 | { "Line/Mic", 0x0 }, | ||
4522 | { "CD", 0x4 }, | ||
4523 | }, | ||
4524 | }, | ||
4525 | { | ||
4526 | .num_items = 3, | ||
4527 | .items = { | ||
4528 | { "Line/Mic", 0x0 }, | ||
4529 | { "CD", 0x4 }, | ||
4530 | { "Mixer", 0x5 }, | ||
4531 | }, | ||
4532 | }, | ||
4533 | }; | ||
4534 | |||
4466 | /* | 4535 | /* |
4467 | * This is just place-holder, so there's something for alc_build_pcms to look | 4536 | * This is just place-holder, so there's something for alc_build_pcms to look |
4468 | * at when it calculates the maximum number of channels. ALC260 has no mixer | 4537 | * at when it calculates the maximum number of channels. ALC260 has no mixer |
@@ -4505,12 +4574,6 @@ static struct snd_kcontrol_new alc260_input_mixer[] = { | |||
4505 | { } /* end */ | 4574 | { } /* end */ |
4506 | }; | 4575 | }; |
4507 | 4576 | ||
4508 | static struct snd_kcontrol_new alc260_pc_beep_mixer[] = { | ||
4509 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
4510 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
4511 | { } /* end */ | ||
4512 | }; | ||
4513 | |||
4514 | /* update HP, line and mono out pins according to the master switch */ | 4577 | /* update HP, line and mono out pins according to the master switch */ |
4515 | static void alc260_hp_master_update(struct hda_codec *codec, | 4578 | static void alc260_hp_master_update(struct hda_codec *codec, |
4516 | hda_nid_t hp, hda_nid_t line, | 4579 | hda_nid_t hp, hda_nid_t line, |
@@ -4702,8 +4765,6 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | |||
4702 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), | 4765 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), |
4703 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), | 4766 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), |
4704 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), | 4767 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), |
4705 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
4706 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
4707 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), | 4768 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), |
4708 | HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), | 4769 | HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), |
4709 | { } /* end */ | 4770 | { } /* end */ |
@@ -4748,8 +4809,18 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = { | |||
4748 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | 4809 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), |
4749 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | 4810 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), |
4750 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | 4811 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), |
4751 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | 4812 | { } /* end */ |
4752 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | 4813 | }; |
4814 | |||
4815 | /* Maxdata Favorit 100XS: one output and one input (0x12) jack | ||
4816 | */ | ||
4817 | static struct snd_kcontrol_new alc260_favorit100_mixer[] = { | ||
4818 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
4819 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
4820 | ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
4821 | HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
4822 | HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
4823 | ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
4753 | { } /* end */ | 4824 | { } /* end */ |
4754 | }; | 4825 | }; |
4755 | 4826 | ||
@@ -4767,8 +4838,6 @@ static struct snd_kcontrol_new alc260_will_mixer[] = { | |||
4767 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | 4838 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), |
4768 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 4839 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
4769 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 4840 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
4770 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
4771 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
4772 | { } /* end */ | 4841 | { } /* end */ |
4773 | }; | 4842 | }; |
4774 | 4843 | ||
@@ -5126,6 +5195,89 @@ static struct hda_verb alc260_acer_init_verbs[] = { | |||
5126 | { } | 5195 | { } |
5127 | }; | 5196 | }; |
5128 | 5197 | ||
5198 | /* Initialisation sequence for Maxdata Favorit 100XS | ||
5199 | * (adapted from Acer init verbs). | ||
5200 | */ | ||
5201 | static struct hda_verb alc260_favorit100_init_verbs[] = { | ||
5202 | /* GPIO 0 enables the output jack. | ||
5203 | * Turn this on and rely on the standard mute | ||
5204 | * methods whenever the user wants to turn these outputs off. | ||
5205 | */ | ||
5206 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
5207 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
5208 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
5209 | /* Line/Mic input jack is connected to Mic1 pin */ | ||
5210 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
5211 | /* Ensure all other unused pins are disabled and muted. */ | ||
5212 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5213 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5214 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5215 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5216 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5217 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5218 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5219 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5220 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
5221 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5222 | /* Disable digital (SPDIF) pins */ | ||
5223 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
5224 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
5225 | |||
5226 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum | ||
5227 | * bus when acting as outputs. | ||
5228 | */ | ||
5229 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5230 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5231 | |||
5232 | /* Start with output sum widgets muted and their output gains at min */ | ||
5233 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5234 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5235 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5236 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5237 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5238 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5239 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5240 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5241 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5242 | |||
5243 | /* Unmute Line-out pin widget amp left and right | ||
5244 | * (no equiv mixer ctrl) | ||
5245 | */ | ||
5246 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5247 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as | ||
5248 | * inputs. If the pin mode is changed by the user the pin mode control | ||
5249 | * will take care of enabling the pin's input/output buffers as needed. | ||
5250 | * Therefore there's no need to enable the input buffer at this | ||
5251 | * stage. | ||
5252 | */ | ||
5253 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5254 | |||
5255 | /* Mute capture amp left and right */ | ||
5256 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5257 | /* Set ADC connection select to match default mixer setting - mic | ||
5258 | * (on mic1 pin) | ||
5259 | */ | ||
5260 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5261 | |||
5262 | /* Do similar with the second ADC: mute capture input amp and | ||
5263 | * set ADC connection to mic to match ALSA's default state. | ||
5264 | */ | ||
5265 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5266 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5267 | |||
5268 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
5269 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
5270 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
5271 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
5272 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
5273 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
5274 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
5275 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
5276 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
5277 | |||
5278 | { } | ||
5279 | }; | ||
5280 | |||
5129 | static struct hda_verb alc260_will_verbs[] = { | 5281 | static struct hda_verb alc260_will_verbs[] = { |
5130 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 5282 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
5131 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 5283 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -5272,8 +5424,6 @@ static struct snd_kcontrol_new alc260_test_mixer[] = { | |||
5272 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), | 5424 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), |
5273 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 5425 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
5274 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 5426 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
5275 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
5276 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
5277 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), | 5427 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), |
5278 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), | 5428 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), |
5279 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), | 5429 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), |
@@ -5471,7 +5621,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
5471 | static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, | 5621 | static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, |
5472 | const struct auto_pin_cfg *cfg) | 5622 | const struct auto_pin_cfg *cfg) |
5473 | { | 5623 | { |
5474 | struct hda_input_mux *imux = &spec->private_imux; | 5624 | struct hda_input_mux *imux = &spec->private_imux[0]; |
5475 | int i, err, idx; | 5625 | int i, err, idx; |
5476 | 5626 | ||
5477 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5627 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -5546,11 +5696,9 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) | |||
5546 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5696 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
5547 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5697 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
5548 | if (nid >= 0x12) { | 5698 | if (nid >= 0x12) { |
5549 | snd_hda_codec_write(codec, nid, 0, | 5699 | alc_set_input_pin(codec, nid, i); |
5550 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 5700 | if (nid != ALC260_PIN_CD_NID && |
5551 | i <= AUTO_PIN_FRONT_MIC ? | 5701 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
5552 | PIN_VREF80 : PIN_IN); | ||
5553 | if (nid != ALC260_PIN_CD_NID) | ||
5554 | snd_hda_codec_write(codec, nid, 0, | 5702 | snd_hda_codec_write(codec, nid, 0, |
5555 | AC_VERB_SET_AMP_GAIN_MUTE, | 5703 | AC_VERB_SET_AMP_GAIN_MUTE, |
5556 | AMP_OUT_MUTE); | 5704 | AMP_OUT_MUTE); |
@@ -5623,7 +5771,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5623 | 5771 | ||
5624 | spec->multiout.max_channels = 2; | 5772 | spec->multiout.max_channels = 2; |
5625 | 5773 | ||
5626 | if (spec->autocfg.dig_out_pin) | 5774 | if (spec->autocfg.dig_outs) |
5627 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5775 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5628 | if (spec->kctls.list) | 5776 | if (spec->kctls.list) |
5629 | add_mixer(spec, spec->kctls.list); | 5777 | add_mixer(spec, spec->kctls.list); |
@@ -5631,9 +5779,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5631 | add_verb(spec, alc260_volume_init_verbs); | 5779 | add_verb(spec, alc260_volume_init_verbs); |
5632 | 5780 | ||
5633 | spec->num_mux_defs = 1; | 5781 | spec->num_mux_defs = 1; |
5634 | spec->input_mux = &spec->private_imux; | 5782 | spec->input_mux = &spec->private_imux[0]; |
5635 | 5783 | ||
5636 | store_pin_configs(codec); | ||
5637 | return 1; | 5784 | return 1; |
5638 | } | 5785 | } |
5639 | 5786 | ||
@@ -5670,6 +5817,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { | |||
5670 | [ALC260_ACER] = "acer", | 5817 | [ALC260_ACER] = "acer", |
5671 | [ALC260_WILL] = "will", | 5818 | [ALC260_WILL] = "will", |
5672 | [ALC260_REPLACER_672V] = "replacer", | 5819 | [ALC260_REPLACER_672V] = "replacer", |
5820 | [ALC260_FAVORIT100] = "favorit100", | ||
5673 | #ifdef CONFIG_SND_DEBUG | 5821 | #ifdef CONFIG_SND_DEBUG |
5674 | [ALC260_TEST] = "test", | 5822 | [ALC260_TEST] = "test", |
5675 | #endif | 5823 | #endif |
@@ -5679,6 +5827,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { | |||
5679 | static struct snd_pci_quirk alc260_cfg_tbl[] = { | 5827 | static struct snd_pci_quirk alc260_cfg_tbl[] = { |
5680 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), | 5828 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), |
5681 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), | 5829 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), |
5830 | SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), | ||
5682 | SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), | 5831 | SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), |
5683 | SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), | 5832 | SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), |
5684 | SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), | 5833 | SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), |
@@ -5701,8 +5850,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = { | |||
5701 | static struct alc_config_preset alc260_presets[] = { | 5850 | static struct alc_config_preset alc260_presets[] = { |
5702 | [ALC260_BASIC] = { | 5851 | [ALC260_BASIC] = { |
5703 | .mixers = { alc260_base_output_mixer, | 5852 | .mixers = { alc260_base_output_mixer, |
5704 | alc260_input_mixer, | 5853 | alc260_input_mixer }, |
5705 | alc260_pc_beep_mixer }, | ||
5706 | .init_verbs = { alc260_init_verbs }, | 5854 | .init_verbs = { alc260_init_verbs }, |
5707 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5855 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5708 | .dac_nids = alc260_dac_nids, | 5856 | .dac_nids = alc260_dac_nids, |
@@ -5781,6 +5929,18 @@ static struct alc_config_preset alc260_presets[] = { | |||
5781 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), | 5929 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), |
5782 | .input_mux = alc260_acer_capture_sources, | 5930 | .input_mux = alc260_acer_capture_sources, |
5783 | }, | 5931 | }, |
5932 | [ALC260_FAVORIT100] = { | ||
5933 | .mixers = { alc260_favorit100_mixer }, | ||
5934 | .init_verbs = { alc260_favorit100_init_verbs }, | ||
5935 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
5936 | .dac_nids = alc260_dac_nids, | ||
5937 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
5938 | .adc_nids = alc260_dual_adc_nids, | ||
5939 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
5940 | .channel_mode = alc260_modes, | ||
5941 | .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), | ||
5942 | .input_mux = alc260_favorit100_capture_sources, | ||
5943 | }, | ||
5784 | [ALC260_WILL] = { | 5944 | [ALC260_WILL] = { |
5785 | .mixers = { alc260_will_mixer }, | 5945 | .mixers = { alc260_will_mixer }, |
5786 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | 5946 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, |
@@ -5857,6 +6017,12 @@ static int patch_alc260(struct hda_codec *codec) | |||
5857 | } | 6017 | } |
5858 | } | 6018 | } |
5859 | 6019 | ||
6020 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
6021 | if (err < 0) { | ||
6022 | alc_free(codec); | ||
6023 | return err; | ||
6024 | } | ||
6025 | |||
5860 | if (board_config != ALC260_AUTO) | 6026 | if (board_config != ALC260_AUTO) |
5861 | setup_preset(spec, &alc260_presets[board_config]); | 6027 | setup_preset(spec, &alc260_presets[board_config]); |
5862 | 6028 | ||
@@ -5882,6 +6048,7 @@ static int patch_alc260(struct hda_codec *codec) | |||
5882 | } | 6048 | } |
5883 | } | 6049 | } |
5884 | set_capture_mixer(spec); | 6050 | set_capture_mixer(spec); |
6051 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | ||
5885 | 6052 | ||
5886 | spec->vmaster_nid = 0x08; | 6053 | spec->vmaster_nid = 0x08; |
5887 | 6054 | ||
@@ -6053,8 +6220,6 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
6053 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 6220 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
6054 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 6221 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
6055 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 6222 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
6056 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6057 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6058 | { } /* end */ | 6223 | { } /* end */ |
6059 | }; | 6224 | }; |
6060 | 6225 | ||
@@ -6081,8 +6246,6 @@ static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | |||
6081 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 6246 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
6082 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 6247 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
6083 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 6248 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
6084 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6085 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6086 | { } /* end */ | 6249 | { } /* end */ |
6087 | }; | 6250 | }; |
6088 | 6251 | ||
@@ -6134,8 +6297,6 @@ static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = { | |||
6134 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 6297 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
6135 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 6298 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
6136 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 6299 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
6137 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6138 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6139 | { } /* end */ | 6300 | { } /* end */ |
6140 | }; | 6301 | }; |
6141 | 6302 | ||
@@ -6244,8 +6405,10 @@ static struct snd_kcontrol_new alc882_macpro_mixer[] = { | |||
6244 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), | 6405 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), |
6245 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), | 6406 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), |
6246 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), | 6407 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), |
6408 | /* FIXME: this looks suspicious... | ||
6247 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), | 6409 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), |
6248 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), | 6410 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), |
6411 | */ | ||
6249 | { } /* end */ | 6412 | { } /* end */ |
6250 | }; | 6413 | }; |
6251 | 6414 | ||
@@ -6877,19 +7040,9 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
6877 | 7040 | ||
6878 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 7041 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
6879 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 7042 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
6880 | unsigned int vref; | ||
6881 | if (!nid) | 7043 | if (!nid) |
6882 | continue; | 7044 | continue; |
6883 | vref = PIN_IN; | 7045 | alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/); |
6884 | if (1 /*i <= AUTO_PIN_FRONT_MIC*/) { | ||
6885 | unsigned int pincap; | ||
6886 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
6887 | if ((pincap >> AC_PINCAP_VREF_SHIFT) & | ||
6888 | AC_PINCAP_VREF_80) | ||
6889 | vref = PIN_VREF80; | ||
6890 | } | ||
6891 | snd_hda_codec_write(codec, nid, 0, | ||
6892 | AC_VERB_SET_PIN_WIDGET_CONTROL, vref); | ||
6893 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) | 7046 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) |
6894 | snd_hda_codec_write(codec, nid, 0, | 7047 | snd_hda_codec_write(codec, nid, 0, |
6895 | AC_VERB_SET_AMP_GAIN_MUTE, | 7048 | AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -6900,18 +7053,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
6900 | static void alc882_auto_init_input_src(struct hda_codec *codec) | 7053 | static void alc882_auto_init_input_src(struct hda_codec *codec) |
6901 | { | 7054 | { |
6902 | struct alc_spec *spec = codec->spec; | 7055 | struct alc_spec *spec = codec->spec; |
6903 | const struct hda_input_mux *imux = spec->input_mux; | ||
6904 | int c; | 7056 | int c; |
6905 | 7057 | ||
6906 | for (c = 0; c < spec->num_adc_nids; c++) { | 7058 | for (c = 0; c < spec->num_adc_nids; c++) { |
6907 | hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; | 7059 | hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; |
6908 | hda_nid_t nid = spec->capsrc_nids[c]; | 7060 | hda_nid_t nid = spec->capsrc_nids[c]; |
7061 | unsigned int mux_idx; | ||
7062 | const struct hda_input_mux *imux; | ||
6909 | int conns, mute, idx, item; | 7063 | int conns, mute, idx, item; |
6910 | 7064 | ||
6911 | conns = snd_hda_get_connections(codec, nid, conn_list, | 7065 | conns = snd_hda_get_connections(codec, nid, conn_list, |
6912 | ARRAY_SIZE(conn_list)); | 7066 | ARRAY_SIZE(conn_list)); |
6913 | if (conns < 0) | 7067 | if (conns < 0) |
6914 | continue; | 7068 | continue; |
7069 | mux_idx = c >= spec->num_mux_defs ? 0 : c; | ||
7070 | imux = &spec->input_mux[mux_idx]; | ||
6915 | for (idx = 0; idx < conns; idx++) { | 7071 | for (idx = 0; idx < conns; idx++) { |
6916 | /* if the current connection is the selected one, | 7072 | /* if the current connection is the selected one, |
6917 | * unmute it as default - otherwise mute it | 7073 | * unmute it as default - otherwise mute it |
@@ -6924,8 +7080,20 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) | |||
6924 | break; | 7080 | break; |
6925 | } | 7081 | } |
6926 | } | 7082 | } |
6927 | snd_hda_codec_write(codec, nid, 0, | 7083 | /* check if we have a selector or mixer |
6928 | AC_VERB_SET_AMP_GAIN_MUTE, mute); | 7084 | * we could check for the widget type instead, but |
7085 | * just check for Amp-In presence (in case of mixer | ||
7086 | * without amp-in there is something wrong, this | ||
7087 | * function shouldn't be used or capsrc nid is wrong) | ||
7088 | */ | ||
7089 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) | ||
7090 | snd_hda_codec_write(codec, nid, 0, | ||
7091 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
7092 | mute); | ||
7093 | else if (mute != AMP_IN_MUTE(idx)) | ||
7094 | snd_hda_codec_write(codec, nid, 0, | ||
7095 | AC_VERB_SET_CONNECT_SEL, | ||
7096 | idx); | ||
6929 | } | 7097 | } |
6930 | } | 7098 | } |
6931 | } | 7099 | } |
@@ -7017,6 +7185,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
7017 | case 0x106b3e00: /* iMac 24 Aluminium */ | 7185 | case 0x106b3e00: /* iMac 24 Aluminium */ |
7018 | board_config = ALC885_IMAC24; | 7186 | board_config = ALC885_IMAC24; |
7019 | break; | 7187 | break; |
7188 | case 0x106b00a0: /* MacBookPro3,1 - Another revision */ | ||
7020 | case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */ | 7189 | case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */ |
7021 | case 0x106b00a4: /* MacbookPro4,1 */ | 7190 | case 0x106b00a4: /* MacbookPro4,1 */ |
7022 | case 0x106b2c00: /* Macbook Pro rev3 */ | 7191 | case 0x106b2c00: /* Macbook Pro rev3 */ |
@@ -7053,6 +7222,12 @@ static int patch_alc882(struct hda_codec *codec) | |||
7053 | } | 7222 | } |
7054 | } | 7223 | } |
7055 | 7224 | ||
7225 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
7226 | if (err < 0) { | ||
7227 | alc_free(codec); | ||
7228 | return err; | ||
7229 | } | ||
7230 | |||
7056 | if (board_config != ALC882_AUTO) | 7231 | if (board_config != ALC882_AUTO) |
7057 | setup_preset(spec, &alc882_presets[board_config]); | 7232 | setup_preset(spec, &alc882_presets[board_config]); |
7058 | 7233 | ||
@@ -7073,7 +7248,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
7073 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 7248 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
7074 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 7249 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
7075 | 7250 | ||
7076 | spec->is_mix_capture = 1; /* matrix-style capture */ | 7251 | spec->capture_style = CAPT_MIX; /* matrix-style capture */ |
7077 | if (!spec->adc_nids && spec->input_mux) { | 7252 | if (!spec->adc_nids && spec->input_mux) { |
7078 | /* check whether NID 0x07 is valid */ | 7253 | /* check whether NID 0x07 is valid */ |
7079 | unsigned int wcap = get_wcaps(codec, 0x07); | 7254 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -7090,6 +7265,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
7090 | } | 7265 | } |
7091 | } | 7266 | } |
7092 | set_capture_mixer(spec); | 7267 | set_capture_mixer(spec); |
7268 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
7093 | 7269 | ||
7094 | spec->vmaster_nid = 0x0c; | 7270 | spec->vmaster_nid = 0x0c; |
7095 | 7271 | ||
@@ -7141,10 +7317,14 @@ static hda_nid_t alc883_adc_nids_rev[2] = { | |||
7141 | 0x09, 0x08 | 7317 | 0x09, 0x08 |
7142 | }; | 7318 | }; |
7143 | 7319 | ||
7320 | #define alc889_adc_nids alc880_adc_nids | ||
7321 | |||
7144 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; | 7322 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; |
7145 | 7323 | ||
7146 | static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; | 7324 | static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; |
7147 | 7325 | ||
7326 | #define alc889_capsrc_nids alc882_capsrc_nids | ||
7327 | |||
7148 | /* input MUX */ | 7328 | /* input MUX */ |
7149 | /* FIXME: should be a matrix-type input source selection */ | 7329 | /* FIXME: should be a matrix-type input source selection */ |
7150 | 7330 | ||
@@ -7362,8 +7542,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = { | |||
7362 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7542 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7363 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7543 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7364 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7544 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7365 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7366 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7367 | { } /* end */ | 7545 | { } /* end */ |
7368 | }; | 7546 | }; |
7369 | 7547 | ||
@@ -7426,8 +7604,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { | |||
7426 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7604 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7427 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7605 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7428 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7606 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7429 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7430 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7431 | { } /* end */ | 7607 | { } /* end */ |
7432 | }; | 7608 | }; |
7433 | 7609 | ||
@@ -7451,8 +7627,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | |||
7451 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7627 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7452 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7628 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7453 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7629 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7454 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7455 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7456 | { } /* end */ | 7630 | { } /* end */ |
7457 | }; | 7631 | }; |
7458 | 7632 | ||
@@ -7477,8 +7651,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { | |||
7477 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7651 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7478 | HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), | 7652 | HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), |
7479 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7653 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7480 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7481 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7482 | { } /* end */ | 7654 | { } /* end */ |
7483 | }; | 7655 | }; |
7484 | 7656 | ||
@@ -7502,8 +7674,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { | |||
7502 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7674 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7503 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7675 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7504 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7676 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7505 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
7506 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
7507 | { } /* end */ | 7677 | { } /* end */ |
7508 | }; | 7678 | }; |
7509 | 7679 | ||
@@ -7911,36 +8081,83 @@ static struct hda_verb alc888_lenovo_sky_verbs[] = { | |||
7911 | { } /* end */ | 8081 | { } /* end */ |
7912 | }; | 8082 | }; |
7913 | 8083 | ||
8084 | static struct hda_verb alc888_6st_dell_verbs[] = { | ||
8085 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8086 | { } | ||
8087 | }; | ||
8088 | |||
8089 | static void alc888_3st_hp_front_automute(struct hda_codec *codec) | ||
8090 | { | ||
8091 | unsigned int present, bits; | ||
8092 | |||
8093 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
8094 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
8095 | bits = present ? HDA_AMP_MUTE : 0; | ||
8096 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
8097 | HDA_AMP_MUTE, bits); | ||
8098 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
8099 | HDA_AMP_MUTE, bits); | ||
8100 | snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, | ||
8101 | HDA_AMP_MUTE, bits); | ||
8102 | } | ||
8103 | |||
8104 | static void alc888_3st_hp_unsol_event(struct hda_codec *codec, | ||
8105 | unsigned int res) | ||
8106 | { | ||
8107 | switch (res >> 26) { | ||
8108 | case ALC880_HP_EVENT: | ||
8109 | alc888_3st_hp_front_automute(codec); | ||
8110 | break; | ||
8111 | } | ||
8112 | } | ||
8113 | |||
7914 | static struct hda_verb alc888_3st_hp_verbs[] = { | 8114 | static struct hda_verb alc888_3st_hp_verbs[] = { |
7915 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ | 8115 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ |
7916 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ | 8116 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ |
7917 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ | 8117 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ |
7918 | { } | ||
7919 | }; | ||
7920 | |||
7921 | static struct hda_verb alc888_6st_dell_verbs[] = { | ||
7922 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | 8118 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, |
7923 | { } | 8119 | { } /* end */ |
7924 | }; | 8120 | }; |
7925 | 8121 | ||
8122 | /* | ||
8123 | * 2ch mode | ||
8124 | */ | ||
7926 | static struct hda_verb alc888_3st_hp_2ch_init[] = { | 8125 | static struct hda_verb alc888_3st_hp_2ch_init[] = { |
7927 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | 8126 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
7928 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | 8127 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, |
7929 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 8128 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
7930 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | 8129 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, |
7931 | { } | 8130 | { } /* end */ |
7932 | }; | 8131 | }; |
7933 | 8132 | ||
8133 | /* | ||
8134 | * 4ch mode | ||
8135 | */ | ||
8136 | static struct hda_verb alc888_3st_hp_4ch_init[] = { | ||
8137 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
8138 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
8139 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
8140 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
8141 | { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
8142 | { } /* end */ | ||
8143 | }; | ||
8144 | |||
8145 | /* | ||
8146 | * 6ch mode | ||
8147 | */ | ||
7934 | static struct hda_verb alc888_3st_hp_6ch_init[] = { | 8148 | static struct hda_verb alc888_3st_hp_6ch_init[] = { |
7935 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 8149 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
7936 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | 8150 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, |
8151 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
7937 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 8152 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
7938 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | 8153 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, |
7939 | { } | 8154 | { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 }, |
8155 | { } /* end */ | ||
7940 | }; | 8156 | }; |
7941 | 8157 | ||
7942 | static struct hda_channel_mode alc888_3st_hp_modes[2] = { | 8158 | static struct hda_channel_mode alc888_3st_hp_modes[3] = { |
7943 | { 2, alc888_3st_hp_2ch_init }, | 8159 | { 2, alc888_3st_hp_2ch_init }, |
8160 | { 4, alc888_3st_hp_4ch_init }, | ||
7944 | { 6, alc888_3st_hp_6ch_init }, | 8161 | { 6, alc888_3st_hp_6ch_init }, |
7945 | }; | 8162 | }; |
7946 | 8163 | ||
@@ -8201,7 +8418,7 @@ static void alc888_6st_dell_unsol_event(struct hda_codec *codec, | |||
8201 | { | 8418 | { |
8202 | switch (res >> 26) { | 8419 | switch (res >> 26) { |
8203 | case ALC880_HP_EVENT: | 8420 | case ALC880_HP_EVENT: |
8204 | printk("hp_event\n"); | 8421 | /* printk(KERN_DEBUG "hp_event\n"); */ |
8205 | alc888_6st_dell_front_automute(codec); | 8422 | alc888_6st_dell_front_automute(codec); |
8206 | break; | 8423 | break; |
8207 | } | 8424 | } |
@@ -8460,6 +8677,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8460 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), | 8677 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), |
8461 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), | 8678 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), |
8462 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), | 8679 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), |
8680 | SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE), | ||
8463 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), | 8681 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), |
8464 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), | 8682 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), |
8465 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), | 8683 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), |
@@ -8467,17 +8685,24 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8467 | ALC888_ACER_ASPIRE_4930G), | 8685 | ALC888_ACER_ASPIRE_4930G), |
8468 | SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G", | 8686 | SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G", |
8469 | ALC888_ACER_ASPIRE_4930G), | 8687 | ALC888_ACER_ASPIRE_4930G), |
8688 | SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO), | ||
8689 | SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO), | ||
8470 | SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", | 8690 | SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", |
8471 | ALC888_ACER_ASPIRE_4930G), | 8691 | ALC888_ACER_ASPIRE_4930G), |
8472 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */ | 8692 | SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", |
8693 | ALC888_ACER_ASPIRE_4930G), | ||
8694 | /* default Acer */ | ||
8695 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), | ||
8473 | SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), | 8696 | SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), |
8474 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), | 8697 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), |
8475 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), | 8698 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), |
8476 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), | 8699 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), |
8477 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), | 8700 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), |
8478 | SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), | 8701 | SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), |
8702 | SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP), | ||
8479 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), | 8703 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), |
8480 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), | 8704 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), |
8705 | SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG), | ||
8481 | SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q), | 8706 | SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q), |
8482 | SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), | 8707 | SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), |
8483 | SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), | 8708 | SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), |
@@ -8514,7 +8739,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8514 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), | 8739 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), |
8515 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), | 8740 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), |
8516 | SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), | 8741 | SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), |
8517 | SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), | 8742 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD), |
8518 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), | 8743 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), |
8519 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), | 8744 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), |
8520 | SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", | 8745 | SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", |
@@ -8539,6 +8764,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8539 | {} | 8764 | {} |
8540 | }; | 8765 | }; |
8541 | 8766 | ||
8767 | static hda_nid_t alc1200_slave_dig_outs[] = { | ||
8768 | ALC883_DIGOUT_NID, 0, | ||
8769 | }; | ||
8770 | |||
8542 | static struct alc_config_preset alc883_presets[] = { | 8771 | static struct alc_config_preset alc883_presets[] = { |
8543 | [ALC883_3ST_2ch_DIG] = { | 8772 | [ALC883_3ST_2ch_DIG] = { |
8544 | .mixers = { alc883_3ST_2ch_mixer }, | 8773 | .mixers = { alc883_3ST_2ch_mixer }, |
@@ -8774,6 +9003,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8774 | .channel_mode = alc888_3st_hp_modes, | 9003 | .channel_mode = alc888_3st_hp_modes, |
8775 | .need_dac_fix = 1, | 9004 | .need_dac_fix = 1, |
8776 | .input_mux = &alc883_capture_source, | 9005 | .input_mux = &alc883_capture_source, |
9006 | .unsol_event = alc888_3st_hp_unsol_event, | ||
9007 | .init_hook = alc888_3st_hp_front_automute, | ||
8777 | }, | 9008 | }, |
8778 | [ALC888_6ST_DELL] = { | 9009 | [ALC888_6ST_DELL] = { |
8779 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | 9010 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, |
@@ -8879,6 +9110,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
8879 | .dac_nids = alc883_dac_nids, | 9110 | .dac_nids = alc883_dac_nids, |
8880 | .dig_out_nid = ALC1200_DIGOUT_NID, | 9111 | .dig_out_nid = ALC1200_DIGOUT_NID, |
8881 | .dig_in_nid = ALC883_DIGIN_NID, | 9112 | .dig_in_nid = ALC883_DIGIN_NID, |
9113 | .slave_dig_outs = alc1200_slave_dig_outs, | ||
8882 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | 9114 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), |
8883 | .channel_mode = alc883_sixstack_modes, | 9115 | .channel_mode = alc883_sixstack_modes, |
8884 | .input_mux = &alc883_capture_source, | 9116 | .input_mux = &alc883_capture_source, |
@@ -8946,11 +9178,9 @@ static void alc883_auto_init_analog_input(struct hda_codec *codec) | |||
8946 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 9178 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
8947 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 9179 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
8948 | if (alc883_is_input_pin(nid)) { | 9180 | if (alc883_is_input_pin(nid)) { |
8949 | snd_hda_codec_write(codec, nid, 0, | 9181 | alc_set_input_pin(codec, nid, i); |
8950 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 9182 | if (nid != ALC883_PIN_CD_NID && |
8951 | (i <= AUTO_PIN_FRONT_MIC ? | 9183 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
8952 | PIN_VREF80 : PIN_IN)); | ||
8953 | if (nid != ALC883_PIN_CD_NID) | ||
8954 | snd_hda_codec_write(codec, nid, 0, | 9184 | snd_hda_codec_write(codec, nid, 0, |
8955 | AC_VERB_SET_AMP_GAIN_MUTE, | 9185 | AC_VERB_SET_AMP_GAIN_MUTE, |
8956 | AMP_OUT_MUTE); | 9186 | AMP_OUT_MUTE); |
@@ -8965,6 +9195,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
8965 | { | 9195 | { |
8966 | struct alc_spec *spec = codec->spec; | 9196 | struct alc_spec *spec = codec->spec; |
8967 | int err = alc880_parse_auto_config(codec); | 9197 | int err = alc880_parse_auto_config(codec); |
9198 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
9199 | int i; | ||
8968 | 9200 | ||
8969 | if (err < 0) | 9201 | if (err < 0) |
8970 | return err; | 9202 | return err; |
@@ -8978,6 +9210,26 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
8978 | /* hack - override the init verbs */ | 9210 | /* hack - override the init verbs */ |
8979 | spec->init_verbs[0] = alc883_auto_init_verbs; | 9211 | spec->init_verbs[0] = alc883_auto_init_verbs; |
8980 | 9212 | ||
9213 | /* setup input_mux for ALC889 */ | ||
9214 | if (codec->vendor_id == 0x10ec0889) { | ||
9215 | /* digital-mic input pin is excluded in alc880_auto_create..() | ||
9216 | * because it's under 0x18 | ||
9217 | */ | ||
9218 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || | ||
9219 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { | ||
9220 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
9221 | for (i = 1; i < 3; i++) | ||
9222 | memcpy(&spec->private_imux[i], | ||
9223 | &spec->private_imux[0], | ||
9224 | sizeof(spec->private_imux[0])); | ||
9225 | imux->items[imux->num_items].label = "Int DMic"; | ||
9226 | imux->items[imux->num_items].index = 0x0b; | ||
9227 | imux->num_items++; | ||
9228 | spec->num_mux_defs = 3; | ||
9229 | spec->input_mux = spec->private_imux; | ||
9230 | } | ||
9231 | } | ||
9232 | |||
8981 | return 1; /* config found */ | 9233 | return 1; /* config found */ |
8982 | } | 9234 | } |
8983 | 9235 | ||
@@ -9029,6 +9281,12 @@ static int patch_alc883(struct hda_codec *codec) | |||
9029 | } | 9281 | } |
9030 | } | 9282 | } |
9031 | 9283 | ||
9284 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
9285 | if (err < 0) { | ||
9286 | alc_free(codec); | ||
9287 | return err; | ||
9288 | } | ||
9289 | |||
9032 | if (board_config != ALC883_AUTO) | 9290 | if (board_config != ALC883_AUTO) |
9033 | setup_preset(spec, &alc883_presets[board_config]); | 9291 | setup_preset(spec, &alc883_presets[board_config]); |
9034 | 9292 | ||
@@ -9041,14 +9299,36 @@ static int patch_alc883(struct hda_codec *codec) | |||
9041 | spec->stream_name_analog = "ALC888 Analog"; | 9299 | spec->stream_name_analog = "ALC888 Analog"; |
9042 | spec->stream_name_digital = "ALC888 Digital"; | 9300 | spec->stream_name_digital = "ALC888 Digital"; |
9043 | } | 9301 | } |
9302 | if (!spec->num_adc_nids) { | ||
9303 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
9304 | spec->adc_nids = alc883_adc_nids; | ||
9305 | } | ||
9306 | if (!spec->capsrc_nids) | ||
9307 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9308 | spec->capture_style = CAPT_MIX; /* matrix-style capture */ | ||
9044 | break; | 9309 | break; |
9045 | case 0x10ec0889: | 9310 | case 0x10ec0889: |
9046 | spec->stream_name_analog = "ALC889 Analog"; | 9311 | spec->stream_name_analog = "ALC889 Analog"; |
9047 | spec->stream_name_digital = "ALC889 Digital"; | 9312 | spec->stream_name_digital = "ALC889 Digital"; |
9313 | if (!spec->num_adc_nids) { | ||
9314 | spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids); | ||
9315 | spec->adc_nids = alc889_adc_nids; | ||
9316 | } | ||
9317 | if (!spec->capsrc_nids) | ||
9318 | spec->capsrc_nids = alc889_capsrc_nids; | ||
9319 | spec->capture_style = CAPT_1MUX_MIX; /* 1mux/Nmix-style | ||
9320 | capture */ | ||
9048 | break; | 9321 | break; |
9049 | default: | 9322 | default: |
9050 | spec->stream_name_analog = "ALC883 Analog"; | 9323 | spec->stream_name_analog = "ALC883 Analog"; |
9051 | spec->stream_name_digital = "ALC883 Digital"; | 9324 | spec->stream_name_digital = "ALC883 Digital"; |
9325 | if (!spec->num_adc_nids) { | ||
9326 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
9327 | spec->adc_nids = alc883_adc_nids; | ||
9328 | } | ||
9329 | if (!spec->capsrc_nids) | ||
9330 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9331 | spec->capture_style = CAPT_MIX; /* matrix-style capture */ | ||
9052 | break; | 9332 | break; |
9053 | } | 9333 | } |
9054 | 9334 | ||
@@ -9059,15 +9339,9 @@ static int patch_alc883(struct hda_codec *codec) | |||
9059 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 9339 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
9060 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 9340 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
9061 | 9341 | ||
9062 | if (!spec->num_adc_nids) { | ||
9063 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
9064 | spec->adc_nids = alc883_adc_nids; | ||
9065 | } | ||
9066 | if (!spec->capsrc_nids) | ||
9067 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9068 | spec->is_mix_capture = 1; /* matrix-style capture */ | ||
9069 | if (!spec->cap_mixer) | 9342 | if (!spec->cap_mixer) |
9070 | set_capture_mixer(spec); | 9343 | set_capture_mixer(spec); |
9344 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
9071 | 9345 | ||
9072 | spec->vmaster_nid = 0x0c; | 9346 | spec->vmaster_nid = 0x0c; |
9073 | 9347 | ||
@@ -9120,8 +9394,6 @@ static struct snd_kcontrol_new alc262_base_mixer[] = { | |||
9120 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 9394 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
9121 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 9395 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
9122 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 9396 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
9123 | /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9124 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */ | ||
9125 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), | 9397 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), |
9126 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 9398 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
9127 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 9399 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
@@ -9142,8 +9414,6 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = { | |||
9142 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 9414 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
9143 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 9415 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
9144 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 9416 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
9145 | /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9146 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */ | ||
9147 | /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ | 9417 | /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ |
9148 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 9418 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
9149 | { } /* end */ | 9419 | { } /* end */ |
@@ -9252,8 +9522,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | |||
9252 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 9522 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
9253 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 9523 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
9254 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9524 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
9255 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9256 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
9257 | HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), | 9525 | HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), |
9258 | HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), | 9526 | HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), |
9259 | { } /* end */ | 9527 | { } /* end */ |
@@ -9282,8 +9550,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { | |||
9282 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), | 9550 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), |
9283 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 9551 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
9284 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9552 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
9285 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9286 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
9287 | { } /* end */ | 9553 | { } /* end */ |
9288 | }; | 9554 | }; |
9289 | 9555 | ||
@@ -9431,6 +9697,67 @@ static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { | |||
9431 | { } /* end */ | 9697 | { } /* end */ |
9432 | }; | 9698 | }; |
9433 | 9699 | ||
9700 | static struct snd_kcontrol_new alc262_tyan_mixer[] = { | ||
9701 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
9702 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), | ||
9703 | HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT), | ||
9704 | HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT), | ||
9705 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
9706 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
9707 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
9708 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
9709 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
9710 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
9711 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
9712 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
9713 | { } /* end */ | ||
9714 | }; | ||
9715 | |||
9716 | static struct hda_verb alc262_tyan_verbs[] = { | ||
9717 | /* Headphone automute */ | ||
9718 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
9719 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
9720 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
9721 | |||
9722 | /* P11 AUX_IN, white 4-pin connector */ | ||
9723 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
9724 | {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1}, | ||
9725 | {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93}, | ||
9726 | {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19}, | ||
9727 | |||
9728 | {} | ||
9729 | }; | ||
9730 | |||
9731 | /* unsolicited event for HP jack sensing */ | ||
9732 | static void alc262_tyan_automute(struct hda_codec *codec) | ||
9733 | { | ||
9734 | unsigned int mute; | ||
9735 | unsigned int present; | ||
9736 | |||
9737 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
9738 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
9739 | AC_VERB_GET_PIN_SENSE, 0); | ||
9740 | present = (present & 0x80000000) != 0; | ||
9741 | if (present) { | ||
9742 | /* mute line output on ATX panel */ | ||
9743 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
9744 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
9745 | } else { | ||
9746 | /* unmute line output if necessary */ | ||
9747 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); | ||
9748 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
9749 | HDA_AMP_MUTE, mute); | ||
9750 | } | ||
9751 | } | ||
9752 | |||
9753 | static void alc262_tyan_unsol_event(struct hda_codec *codec, | ||
9754 | unsigned int res) | ||
9755 | { | ||
9756 | if ((res >> 26) != ALC880_HP_EVENT) | ||
9757 | return; | ||
9758 | alc262_tyan_automute(codec); | ||
9759 | } | ||
9760 | |||
9434 | #define alc262_capture_mixer alc882_capture_mixer | 9761 | #define alc262_capture_mixer alc882_capture_mixer |
9435 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer | 9762 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer |
9436 | 9763 | ||
@@ -9897,8 +10224,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
9897 | }, | 10224 | }, |
9898 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 10225 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
9899 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 10226 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
9900 | HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT), | ||
9901 | HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT), | ||
9902 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 10227 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
9903 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 10228 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
9904 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 10229 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
@@ -10470,8 +10795,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10470 | alc262_ignore); | 10795 | alc262_ignore); |
10471 | if (err < 0) | 10796 | if (err < 0) |
10472 | return err; | 10797 | return err; |
10473 | if (!spec->autocfg.line_outs) | 10798 | if (!spec->autocfg.line_outs) { |
10799 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
10800 | spec->multiout.max_channels = 2; | ||
10801 | spec->no_analog = 1; | ||
10802 | goto dig_only; | ||
10803 | } | ||
10474 | return 0; /* can't find valid BIOS pin config */ | 10804 | return 0; /* can't find valid BIOS pin config */ |
10805 | } | ||
10475 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); | 10806 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); |
10476 | if (err < 0) | 10807 | if (err < 0) |
10477 | return err; | 10808 | return err; |
@@ -10481,8 +10812,11 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10481 | 10812 | ||
10482 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 10813 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
10483 | 10814 | ||
10484 | if (spec->autocfg.dig_out_pin) | 10815 | dig_only: |
10816 | if (spec->autocfg.dig_outs) { | ||
10485 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; | 10817 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; |
10818 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
10819 | } | ||
10486 | if (spec->autocfg.dig_in_pin) | 10820 | if (spec->autocfg.dig_in_pin) |
10487 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10821 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10488 | 10822 | ||
@@ -10491,13 +10825,12 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10491 | 10825 | ||
10492 | add_verb(spec, alc262_volume_init_verbs); | 10826 | add_verb(spec, alc262_volume_init_verbs); |
10493 | spec->num_mux_defs = 1; | 10827 | spec->num_mux_defs = 1; |
10494 | spec->input_mux = &spec->private_imux; | 10828 | spec->input_mux = &spec->private_imux[0]; |
10495 | 10829 | ||
10496 | err = alc_auto_add_mic_boost(codec); | 10830 | err = alc_auto_add_mic_boost(codec); |
10497 | if (err < 0) | 10831 | if (err < 0) |
10498 | return err; | 10832 | return err; |
10499 | 10833 | ||
10500 | store_pin_configs(codec); | ||
10501 | return 1; | 10834 | return 1; |
10502 | } | 10835 | } |
10503 | 10836 | ||
@@ -10539,20 +10872,19 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { | |||
10539 | [ALC262_ULTRA] = "ultra", | 10872 | [ALC262_ULTRA] = "ultra", |
10540 | [ALC262_LENOVO_3000] = "lenovo-3000", | 10873 | [ALC262_LENOVO_3000] = "lenovo-3000", |
10541 | [ALC262_NEC] = "nec", | 10874 | [ALC262_NEC] = "nec", |
10875 | [ALC262_TYAN] = "tyan", | ||
10542 | [ALC262_AUTO] = "auto", | 10876 | [ALC262_AUTO] = "auto", |
10543 | }; | 10877 | }; |
10544 | 10878 | ||
10545 | static struct snd_pci_quirk alc262_cfg_tbl[] = { | 10879 | static struct snd_pci_quirk alc262_cfg_tbl[] = { |
10546 | SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), | 10880 | SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), |
10547 | SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC), | 10881 | SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC), |
10548 | SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), | 10882 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series", |
10549 | SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), | 10883 | ALC262_HP_BPC), |
10550 | SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), | 10884 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series", |
10551 | SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), | 10885 | ALC262_HP_BPC), |
10552 | SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), | 10886 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series", |
10553 | SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC), | 10887 | ALC262_HP_BPC), |
10554 | SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC), | ||
10555 | SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC), | ||
10556 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), | 10888 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), |
10557 | SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), | 10889 | SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), |
10558 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), | 10890 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), |
@@ -10570,17 +10902,17 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
10570 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 10902 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
10571 | SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), | 10903 | SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), |
10572 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 10904 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
10573 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 10905 | SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */ |
10574 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), | 10906 | SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO", |
10575 | SND_PCI_QUIRK(0x104d, 0x9033, "Sony VAIO VGN-SR19XN", | 10907 | ALC262_SONY_ASSAMD), |
10576 | ALC262_SONY_ASSAMD), | ||
10577 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", | 10908 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", |
10578 | ALC262_TOSHIBA_RX1), | 10909 | ALC262_TOSHIBA_RX1), |
10579 | SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06), | 10910 | SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06), |
10580 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), | 10911 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), |
10581 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), | 10912 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), |
10582 | SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), | 10913 | SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN), |
10583 | SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), | 10914 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1", |
10915 | ALC262_ULTRA), | ||
10584 | SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), | 10916 | SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), |
10585 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), | 10917 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), |
10586 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 10918 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
@@ -10797,6 +11129,19 @@ static struct alc_config_preset alc262_presets[] = { | |||
10797 | .unsol_event = alc262_hippo_unsol_event, | 11129 | .unsol_event = alc262_hippo_unsol_event, |
10798 | .init_hook = alc262_hippo_automute, | 11130 | .init_hook = alc262_hippo_automute, |
10799 | }, | 11131 | }, |
11132 | [ALC262_TYAN] = { | ||
11133 | .mixers = { alc262_tyan_mixer }, | ||
11134 | .init_verbs = { alc262_init_verbs, alc262_tyan_verbs}, | ||
11135 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
11136 | .dac_nids = alc262_dac_nids, | ||
11137 | .hp_nid = 0x02, | ||
11138 | .dig_out_nid = ALC262_DIGOUT_NID, | ||
11139 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
11140 | .channel_mode = alc262_modes, | ||
11141 | .input_mux = &alc262_capture_source, | ||
11142 | .unsol_event = alc262_tyan_unsol_event, | ||
11143 | .init_hook = alc262_tyan_automute, | ||
11144 | }, | ||
10800 | }; | 11145 | }; |
10801 | 11146 | ||
10802 | static int patch_alc262(struct hda_codec *codec) | 11147 | static int patch_alc262(struct hda_codec *codec) |
@@ -10849,6 +11194,14 @@ static int patch_alc262(struct hda_codec *codec) | |||
10849 | } | 11194 | } |
10850 | } | 11195 | } |
10851 | 11196 | ||
11197 | if (!spec->no_analog) { | ||
11198 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
11199 | if (err < 0) { | ||
11200 | alc_free(codec); | ||
11201 | return err; | ||
11202 | } | ||
11203 | } | ||
11204 | |||
10852 | if (board_config != ALC262_AUTO) | 11205 | if (board_config != ALC262_AUTO) |
10853 | setup_preset(spec, &alc262_presets[board_config]); | 11206 | setup_preset(spec, &alc262_presets[board_config]); |
10854 | 11207 | ||
@@ -10860,7 +11213,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
10860 | spec->stream_digital_playback = &alc262_pcm_digital_playback; | 11213 | spec->stream_digital_playback = &alc262_pcm_digital_playback; |
10861 | spec->stream_digital_capture = &alc262_pcm_digital_capture; | 11214 | spec->stream_digital_capture = &alc262_pcm_digital_capture; |
10862 | 11215 | ||
10863 | spec->is_mix_capture = 1; | 11216 | spec->capture_style = CAPT_MIX; |
10864 | if (!spec->adc_nids && spec->input_mux) { | 11217 | if (!spec->adc_nids && spec->input_mux) { |
10865 | /* check whether NID 0x07 is valid */ | 11218 | /* check whether NID 0x07 is valid */ |
10866 | unsigned int wcap = get_wcaps(codec, 0x07); | 11219 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -10877,8 +11230,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
10877 | spec->capsrc_nids = alc262_capsrc_nids; | 11230 | spec->capsrc_nids = alc262_capsrc_nids; |
10878 | } | 11231 | } |
10879 | } | 11232 | } |
10880 | if (!spec->cap_mixer) | 11233 | if (!spec->cap_mixer && !spec->no_analog) |
10881 | set_capture_mixer(spec); | 11234 | set_capture_mixer(spec); |
11235 | if (!spec->no_analog) | ||
11236 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
10882 | 11237 | ||
10883 | spec->vmaster_nid = 0x0c; | 11238 | spec->vmaster_nid = 0x0c; |
10884 | 11239 | ||
@@ -11258,19 +11613,13 @@ static void alc267_quanta_il1_unsol_event(struct hda_codec *codec, | |||
11258 | static struct hda_verb alc268_base_init_verbs[] = { | 11613 | static struct hda_verb alc268_base_init_verbs[] = { |
11259 | /* Unmute DAC0-1 and set vol = 0 */ | 11614 | /* Unmute DAC0-1 and set vol = 0 */ |
11260 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 11615 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11261 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11262 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11263 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 11616 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11264 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11265 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11266 | 11617 | ||
11267 | /* | 11618 | /* |
11268 | * Set up output mixers (0x0c - 0x0e) | 11619 | * Set up output mixers (0x0c - 0x0e) |
11269 | */ | 11620 | */ |
11270 | /* set vol=0 to output mixers */ | 11621 | /* set vol=0 to output mixers */ |
11271 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11622 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11272 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11273 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
11274 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, | 11623 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, |
11275 | 11624 | ||
11276 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11625 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -11289,9 +11638,7 @@ static struct hda_verb alc268_base_init_verbs[] = { | |||
11289 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11638 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11290 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11639 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11291 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11640 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11292 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11293 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11641 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11294 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11295 | 11642 | ||
11296 | /* set PCBEEP vol = 0, mute connections */ | 11643 | /* set PCBEEP vol = 0, mute connections */ |
11297 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11644 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -11313,10 +11660,8 @@ static struct hda_verb alc268_base_init_verbs[] = { | |||
11313 | */ | 11660 | */ |
11314 | static struct hda_verb alc268_volume_init_verbs[] = { | 11661 | static struct hda_verb alc268_volume_init_verbs[] = { |
11315 | /* set output DAC */ | 11662 | /* set output DAC */ |
11316 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11663 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11317 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11664 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
11318 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11319 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11320 | 11665 | ||
11321 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 11666 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, |
11322 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 11667 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, |
@@ -11324,16 +11669,12 @@ static struct hda_verb alc268_volume_init_verbs[] = { | |||
11324 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 11669 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, |
11325 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 11670 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, |
11326 | 11671 | ||
11327 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
11328 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11672 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11329 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11330 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11673 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11331 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11674 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11332 | 11675 | ||
11333 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11676 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11334 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11335 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 11677 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
11336 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
11337 | 11678 | ||
11338 | /* set PCBEEP vol = 0, mute connections */ | 11679 | /* set PCBEEP vol = 0, mute connections */ |
11339 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11680 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -11532,7 +11873,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11532 | static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, | 11873 | static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, |
11533 | const struct auto_pin_cfg *cfg) | 11874 | const struct auto_pin_cfg *cfg) |
11534 | { | 11875 | { |
11535 | struct hda_input_mux *imux = &spec->private_imux; | 11876 | struct hda_input_mux *imux = &spec->private_imux[0]; |
11536 | int i, idx1; | 11877 | int i, idx1; |
11537 | 11878 | ||
11538 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 11879 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -11626,9 +11967,14 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11626 | alc268_ignore); | 11967 | alc268_ignore); |
11627 | if (err < 0) | 11968 | if (err < 0) |
11628 | return err; | 11969 | return err; |
11629 | if (!spec->autocfg.line_outs) | 11970 | if (!spec->autocfg.line_outs) { |
11971 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
11972 | spec->multiout.max_channels = 2; | ||
11973 | spec->no_analog = 1; | ||
11974 | goto dig_only; | ||
11975 | } | ||
11630 | return 0; /* can't find valid BIOS pin config */ | 11976 | return 0; /* can't find valid BIOS pin config */ |
11631 | 11977 | } | |
11632 | err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); | 11978 | err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); |
11633 | if (err < 0) | 11979 | if (err < 0) |
11634 | return err; | 11980 | return err; |
@@ -11638,25 +11984,26 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11638 | 11984 | ||
11639 | spec->multiout.max_channels = 2; | 11985 | spec->multiout.max_channels = 2; |
11640 | 11986 | ||
11987 | dig_only: | ||
11641 | /* digital only support output */ | 11988 | /* digital only support output */ |
11642 | if (spec->autocfg.dig_out_pin) | 11989 | if (spec->autocfg.dig_outs) { |
11643 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11990 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11644 | 11991 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | |
11992 | } | ||
11645 | if (spec->kctls.list) | 11993 | if (spec->kctls.list) |
11646 | add_mixer(spec, spec->kctls.list); | 11994 | add_mixer(spec, spec->kctls.list); |
11647 | 11995 | ||
11648 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11996 | if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) |
11649 | add_mixer(spec, alc268_beep_mixer); | 11997 | add_mixer(spec, alc268_beep_mixer); |
11650 | 11998 | ||
11651 | add_verb(spec, alc268_volume_init_verbs); | 11999 | add_verb(spec, alc268_volume_init_verbs); |
11652 | spec->num_mux_defs = 1; | 12000 | spec->num_mux_defs = 1; |
11653 | spec->input_mux = &spec->private_imux; | 12001 | spec->input_mux = &spec->private_imux[0]; |
11654 | 12002 | ||
11655 | err = alc_auto_add_mic_boost(codec); | 12003 | err = alc_auto_add_mic_boost(codec); |
11656 | if (err < 0) | 12004 | if (err < 0) |
11657 | return err; | 12005 | return err; |
11658 | 12006 | ||
11659 | store_pin_configs(codec); | ||
11660 | return 1; | 12007 | return 1; |
11661 | } | 12008 | } |
11662 | 12009 | ||
@@ -11718,7 +12065,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { | |||
11718 | 12065 | ||
11719 | static struct alc_config_preset alc268_presets[] = { | 12066 | static struct alc_config_preset alc268_presets[] = { |
11720 | [ALC267_QUANTA_IL1] = { | 12067 | [ALC267_QUANTA_IL1] = { |
11721 | .mixers = { alc267_quanta_il1_mixer }, | 12068 | .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer }, |
11722 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 12069 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
11723 | alc267_quanta_il1_verbs }, | 12070 | alc267_quanta_il1_verbs }, |
11724 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 12071 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -11800,7 +12147,8 @@ static struct alc_config_preset alc268_presets[] = { | |||
11800 | }, | 12147 | }, |
11801 | [ALC268_ACER_ASPIRE_ONE] = { | 12148 | [ALC268_ACER_ASPIRE_ONE] = { |
11802 | .mixers = { alc268_acer_aspire_one_mixer, | 12149 | .mixers = { alc268_acer_aspire_one_mixer, |
11803 | alc268_capture_alt_mixer }, | 12150 | alc268_beep_mixer, |
12151 | alc268_capture_alt_mixer }, | ||
11804 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 12152 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
11805 | alc268_acer_aspire_one_verbs }, | 12153 | alc268_acer_aspire_one_verbs }, |
11806 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 12154 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -11869,7 +12217,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
11869 | { | 12217 | { |
11870 | struct alc_spec *spec; | 12218 | struct alc_spec *spec; |
11871 | int board_config; | 12219 | int board_config; |
11872 | int err; | 12220 | int i, has_beep, err; |
11873 | 12221 | ||
11874 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 12222 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
11875 | if (spec == NULL) | 12223 | if (spec == NULL) |
@@ -11918,15 +12266,30 @@ static int patch_alc268(struct hda_codec *codec) | |||
11918 | 12266 | ||
11919 | spec->stream_digital_playback = &alc268_pcm_digital_playback; | 12267 | spec->stream_digital_playback = &alc268_pcm_digital_playback; |
11920 | 12268 | ||
11921 | if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) | 12269 | has_beep = 0; |
11922 | /* override the amp caps for beep generator */ | 12270 | for (i = 0; i < spec->num_mixers; i++) { |
11923 | snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, | 12271 | if (spec->mixers[i] == alc268_beep_mixer) { |
12272 | has_beep = 1; | ||
12273 | break; | ||
12274 | } | ||
12275 | } | ||
12276 | |||
12277 | if (has_beep) { | ||
12278 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
12279 | if (err < 0) { | ||
12280 | alc_free(codec); | ||
12281 | return err; | ||
12282 | } | ||
12283 | if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) | ||
12284 | /* override the amp caps for beep generator */ | ||
12285 | snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, | ||
11924 | (0x0c << AC_AMPCAP_OFFSET_SHIFT) | | 12286 | (0x0c << AC_AMPCAP_OFFSET_SHIFT) | |
11925 | (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) | | 12287 | (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) | |
11926 | (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 12288 | (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
11927 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 12289 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
12290 | } | ||
11928 | 12291 | ||
11929 | if (!spec->adc_nids && spec->input_mux) { | 12292 | if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { |
11930 | /* check whether NID 0x07 is valid */ | 12293 | /* check whether NID 0x07 is valid */ |
11931 | unsigned int wcap = get_wcaps(codec, 0x07); | 12294 | unsigned int wcap = get_wcaps(codec, 0x07); |
11932 | int i; | 12295 | int i; |
@@ -12007,8 +12370,6 @@ static struct snd_kcontrol_new alc269_base_mixer[] = { | |||
12007 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 12370 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
12008 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 12371 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
12009 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 12372 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
12010 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
12011 | HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
12012 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 12373 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
12013 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 12374 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
12014 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 12375 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
@@ -12035,8 +12396,6 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
12035 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 12396 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
12036 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 12397 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
12037 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | 12398 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), |
12038 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
12039 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
12040 | { } | 12399 | { } |
12041 | }; | 12400 | }; |
12042 | 12401 | ||
@@ -12060,8 +12419,6 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
12060 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), | 12419 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), |
12061 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), | 12420 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), |
12062 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), | 12421 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), |
12063 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
12064 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
12065 | { } | 12422 | { } |
12066 | }; | 12423 | }; |
12067 | 12424 | ||
@@ -12098,13 +12455,6 @@ static struct snd_kcontrol_new alc269_fujitsu_mixer[] = { | |||
12098 | { } /* end */ | 12455 | { } /* end */ |
12099 | }; | 12456 | }; |
12100 | 12457 | ||
12101 | /* beep control */ | ||
12102 | static struct snd_kcontrol_new alc269_beep_mixer[] = { | ||
12103 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
12104 | HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
12105 | { } /* end */ | ||
12106 | }; | ||
12107 | |||
12108 | static struct hda_verb alc269_quanta_fl1_verbs[] = { | 12458 | static struct hda_verb alc269_quanta_fl1_verbs[] = { |
12109 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 12459 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
12110 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 12460 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
@@ -12504,7 +12854,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
12504 | */ | 12854 | */ |
12505 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || | 12855 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || |
12506 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { | 12856 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { |
12507 | struct hda_input_mux *imux = &spec->private_imux; | 12857 | struct hda_input_mux *imux = &spec->private_imux[0]; |
12508 | imux->items[imux->num_items].label = "Int Mic"; | 12858 | imux->items[imux->num_items].label = "Int Mic"; |
12509 | imux->items[imux->num_items].index = 0x05; | 12859 | imux->items[imux->num_items].index = 0x05; |
12510 | imux->num_items++; | 12860 | imux->num_items++; |
@@ -12522,13 +12872,34 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
12522 | #define alc269_pcm_digital_playback alc880_pcm_digital_playback | 12872 | #define alc269_pcm_digital_playback alc880_pcm_digital_playback |
12523 | #define alc269_pcm_digital_capture alc880_pcm_digital_capture | 12873 | #define alc269_pcm_digital_capture alc880_pcm_digital_capture |
12524 | 12874 | ||
12875 | static struct hda_pcm_stream alc269_44k_pcm_analog_playback = { | ||
12876 | .substreams = 1, | ||
12877 | .channels_min = 2, | ||
12878 | .channels_max = 8, | ||
12879 | .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ | ||
12880 | /* NID is set in alc_build_pcms */ | ||
12881 | .ops = { | ||
12882 | .open = alc880_playback_pcm_open, | ||
12883 | .prepare = alc880_playback_pcm_prepare, | ||
12884 | .cleanup = alc880_playback_pcm_cleanup | ||
12885 | }, | ||
12886 | }; | ||
12887 | |||
12888 | static struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | ||
12889 | .substreams = 1, | ||
12890 | .channels_min = 2, | ||
12891 | .channels_max = 2, | ||
12892 | .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ | ||
12893 | /* NID is set in alc_build_pcms */ | ||
12894 | }; | ||
12895 | |||
12525 | /* | 12896 | /* |
12526 | * BIOS auto configuration | 12897 | * BIOS auto configuration |
12527 | */ | 12898 | */ |
12528 | static int alc269_parse_auto_config(struct hda_codec *codec) | 12899 | static int alc269_parse_auto_config(struct hda_codec *codec) |
12529 | { | 12900 | { |
12530 | struct alc_spec *spec = codec->spec; | 12901 | struct alc_spec *spec = codec->spec; |
12531 | int i, err; | 12902 | int err; |
12532 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; | 12903 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; |
12533 | 12904 | ||
12534 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 12905 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
@@ -12545,22 +12916,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12545 | 12916 | ||
12546 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 12917 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
12547 | 12918 | ||
12548 | if (spec->autocfg.dig_out_pin) | 12919 | if (spec->autocfg.dig_outs) |
12549 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12920 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12550 | 12921 | ||
12551 | if (spec->kctls.list) | 12922 | if (spec->kctls.list) |
12552 | add_mixer(spec, spec->kctls.list); | 12923 | add_mixer(spec, spec->kctls.list); |
12553 | 12924 | ||
12554 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | ||
12555 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | ||
12556 | if (spec->autocfg.input_pins[i] == 0x1d) | ||
12557 | break; | ||
12558 | if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) | ||
12559 | add_mixer(spec, alc269_beep_mixer); | ||
12560 | |||
12561 | add_verb(spec, alc269_init_verbs); | 12925 | add_verb(spec, alc269_init_verbs); |
12562 | spec->num_mux_defs = 1; | 12926 | spec->num_mux_defs = 1; |
12563 | spec->input_mux = &spec->private_imux; | 12927 | spec->input_mux = &spec->private_imux[0]; |
12564 | /* set default input source */ | 12928 | /* set default input source */ |
12565 | snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], | 12929 | snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], |
12566 | 0, AC_VERB_SET_CONNECT_SEL, | 12930 | 0, AC_VERB_SET_CONNECT_SEL, |
@@ -12570,10 +12934,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12570 | if (err < 0) | 12934 | if (err < 0) |
12571 | return err; | 12935 | return err; |
12572 | 12936 | ||
12573 | if (!spec->cap_mixer) | 12937 | if (!spec->cap_mixer && !spec->no_analog) |
12574 | set_capture_mixer(spec); | 12938 | set_capture_mixer(spec); |
12575 | 12939 | ||
12576 | store_pin_configs(codec); | ||
12577 | return 1; | 12940 | return 1; |
12578 | } | 12941 | } |
12579 | 12942 | ||
@@ -12670,7 +13033,7 @@ static struct alc_config_preset alc269_presets[] = { | |||
12670 | .init_hook = alc269_eeepc_dmic_inithook, | 13033 | .init_hook = alc269_eeepc_dmic_inithook, |
12671 | }, | 13034 | }, |
12672 | [ALC269_FUJITSU] = { | 13035 | [ALC269_FUJITSU] = { |
12673 | .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer }, | 13036 | .mixers = { alc269_fujitsu_mixer }, |
12674 | .cap_mixer = alc269_epc_capture_mixer, | 13037 | .cap_mixer = alc269_epc_capture_mixer, |
12675 | .init_verbs = { alc269_init_verbs, | 13038 | .init_verbs = { alc269_init_verbs, |
12676 | alc269_eeepc_dmic_init_verbs }, | 13039 | alc269_eeepc_dmic_init_verbs }, |
@@ -12735,13 +13098,26 @@ static int patch_alc269(struct hda_codec *codec) | |||
12735 | } | 13098 | } |
12736 | } | 13099 | } |
12737 | 13100 | ||
13101 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
13102 | if (err < 0) { | ||
13103 | alc_free(codec); | ||
13104 | return err; | ||
13105 | } | ||
13106 | |||
12738 | if (board_config != ALC269_AUTO) | 13107 | if (board_config != ALC269_AUTO) |
12739 | setup_preset(spec, &alc269_presets[board_config]); | 13108 | setup_preset(spec, &alc269_presets[board_config]); |
12740 | 13109 | ||
12741 | spec->stream_name_analog = "ALC269 Analog"; | 13110 | spec->stream_name_analog = "ALC269 Analog"; |
12742 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | 13111 | if (codec->subsystem_id == 0x17aa3bf8) { |
12743 | spec->stream_analog_capture = &alc269_pcm_analog_capture; | 13112 | /* Due to a hardware problem on Lenovo Ideadpad, we need to |
12744 | 13113 | * fix the sample rate of analog I/O to 44.1kHz | |
13114 | */ | ||
13115 | spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; | ||
13116 | spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; | ||
13117 | } else { | ||
13118 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | ||
13119 | spec->stream_analog_capture = &alc269_pcm_analog_capture; | ||
13120 | } | ||
12745 | spec->stream_name_digital = "ALC269 Digital"; | 13121 | spec->stream_name_digital = "ALC269 Digital"; |
12746 | spec->stream_digital_playback = &alc269_pcm_digital_playback; | 13122 | spec->stream_digital_playback = &alc269_pcm_digital_playback; |
12747 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 13123 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
@@ -12751,6 +13127,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
12751 | spec->capsrc_nids = alc269_capsrc_nids; | 13127 | spec->capsrc_nids = alc269_capsrc_nids; |
12752 | if (!spec->cap_mixer) | 13128 | if (!spec->cap_mixer) |
12753 | set_capture_mixer(spec); | 13129 | set_capture_mixer(spec); |
13130 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
12754 | 13131 | ||
12755 | codec->patch_ops = alc_patch_ops; | 13132 | codec->patch_ops = alc_patch_ops; |
12756 | if (board_config == ALC269_AUTO) | 13133 | if (board_config == ALC269_AUTO) |
@@ -13001,8 +13378,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { | |||
13001 | static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { | 13378 | static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { |
13002 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), | 13379 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), |
13003 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), | 13380 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), |
13004 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT), | ||
13005 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT), | ||
13006 | { } | 13381 | { } |
13007 | }; | 13382 | }; |
13008 | 13383 | ||
@@ -13476,7 +13851,7 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | |||
13476 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, | 13851 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, |
13477 | const struct auto_pin_cfg *cfg) | 13852 | const struct auto_pin_cfg *cfg) |
13478 | { | 13853 | { |
13479 | struct hda_input_mux *imux = &spec->private_imux; | 13854 | struct hda_input_mux *imux = &spec->private_imux[0]; |
13480 | int i, err, idx, idx1; | 13855 | int i, err, idx, idx1; |
13481 | 13856 | ||
13482 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 13857 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
@@ -13563,12 +13938,8 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec) | |||
13563 | 13938 | ||
13564 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 13939 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
13565 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 13940 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
13566 | if (nid >= 0x0c && nid <= 0x11) { | 13941 | if (nid >= 0x0c && nid <= 0x11) |
13567 | snd_hda_codec_write(codec, nid, 0, | 13942 | alc_set_input_pin(codec, nid, i); |
13568 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
13569 | i <= AUTO_PIN_FRONT_MIC ? | ||
13570 | PIN_VREF80 : PIN_IN); | ||
13571 | } | ||
13572 | } | 13943 | } |
13573 | } | 13944 | } |
13574 | 13945 | ||
@@ -13604,7 +13975,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13604 | 13975 | ||
13605 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 13976 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
13606 | 13977 | ||
13607 | if (spec->autocfg.dig_out_pin) | 13978 | if (spec->autocfg.dig_outs) |
13608 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13979 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13609 | 13980 | ||
13610 | if (spec->kctls.list) | 13981 | if (spec->kctls.list) |
@@ -13613,13 +13984,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13613 | add_verb(spec, alc861_auto_init_verbs); | 13984 | add_verb(spec, alc861_auto_init_verbs); |
13614 | 13985 | ||
13615 | spec->num_mux_defs = 1; | 13986 | spec->num_mux_defs = 1; |
13616 | spec->input_mux = &spec->private_imux; | 13987 | spec->input_mux = &spec->private_imux[0]; |
13617 | 13988 | ||
13618 | spec->adc_nids = alc861_adc_nids; | 13989 | spec->adc_nids = alc861_adc_nids; |
13619 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); | 13990 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); |
13620 | set_capture_mixer(spec); | 13991 | set_capture_mixer(spec); |
13621 | 13992 | ||
13622 | store_pin_configs(codec); | ||
13623 | return 1; | 13993 | return 1; |
13624 | } | 13994 | } |
13625 | 13995 | ||
@@ -13828,6 +14198,12 @@ static int patch_alc861(struct hda_codec *codec) | |||
13828 | } | 14198 | } |
13829 | } | 14199 | } |
13830 | 14200 | ||
14201 | err = snd_hda_attach_beep_device(codec, 0x23); | ||
14202 | if (err < 0) { | ||
14203 | alc_free(codec); | ||
14204 | return err; | ||
14205 | } | ||
14206 | |||
13831 | if (board_config != ALC861_AUTO) | 14207 | if (board_config != ALC861_AUTO) |
13832 | setup_preset(spec, &alc861_presets[board_config]); | 14208 | setup_preset(spec, &alc861_presets[board_config]); |
13833 | 14209 | ||
@@ -13839,6 +14215,8 @@ static int patch_alc861(struct hda_codec *codec) | |||
13839 | spec->stream_digital_playback = &alc861_pcm_digital_playback; | 14215 | spec->stream_digital_playback = &alc861_pcm_digital_playback; |
13840 | spec->stream_digital_capture = &alc861_pcm_digital_capture; | 14216 | spec->stream_digital_capture = &alc861_pcm_digital_capture; |
13841 | 14217 | ||
14218 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); | ||
14219 | |||
13842 | spec->vmaster_nid = 0x03; | 14220 | spec->vmaster_nid = 0x03; |
13843 | 14221 | ||
13844 | codec->patch_ops = alc_patch_ops; | 14222 | codec->patch_ops = alc_patch_ops; |
@@ -13995,9 +14373,6 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = { | |||
13995 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 14373 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
13996 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 14374 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
13997 | 14375 | ||
13998 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
13999 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
14000 | |||
14001 | { } /* end */ | 14376 | { } /* end */ |
14002 | }; | 14377 | }; |
14003 | 14378 | ||
@@ -14021,9 +14396,6 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { | |||
14021 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 14396 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
14022 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 14397 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
14023 | 14398 | ||
14024 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
14025 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
14026 | |||
14027 | { } /* end */ | 14399 | { } /* end */ |
14028 | }; | 14400 | }; |
14029 | 14401 | ||
@@ -14062,8 +14434,6 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { | |||
14062 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 14434 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
14063 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 14435 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
14064 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 14436 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
14065 | HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT), | ||
14066 | HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT), | ||
14067 | { } /* end */ | 14437 | { } /* end */ |
14068 | }; | 14438 | }; |
14069 | 14439 | ||
@@ -14374,9 +14744,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
14374 | SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), | 14744 | SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), |
14375 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), | 14745 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), |
14376 | SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), | 14746 | SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), |
14377 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | 14747 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO), |
14378 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), | ||
14379 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO), | ||
14380 | SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), | 14748 | SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), |
14381 | {} | 14749 | {} |
14382 | }; | 14750 | }; |
@@ -14538,11 +14906,9 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec) | |||
14538 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 14906 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
14539 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 14907 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
14540 | if (alc861vd_is_input_pin(nid)) { | 14908 | if (alc861vd_is_input_pin(nid)) { |
14541 | snd_hda_codec_write(codec, nid, 0, | 14909 | alc_set_input_pin(codec, nid, i); |
14542 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 14910 | if (nid != ALC861VD_PIN_CD_NID && |
14543 | i <= AUTO_PIN_FRONT_MIC ? | 14911 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
14544 | PIN_VREF80 : PIN_IN); | ||
14545 | if (nid != ALC861VD_PIN_CD_NID) | ||
14546 | snd_hda_codec_write(codec, nid, 0, | 14912 | snd_hda_codec_write(codec, nid, 0, |
14547 | AC_VERB_SET_AMP_GAIN_MUTE, | 14913 | AC_VERB_SET_AMP_GAIN_MUTE, |
14548 | AMP_OUT_MUTE); | 14914 | AMP_OUT_MUTE); |
@@ -14708,7 +15074,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14708 | 15074 | ||
14709 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 15075 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
14710 | 15076 | ||
14711 | if (spec->autocfg.dig_out_pin) | 15077 | if (spec->autocfg.dig_outs) |
14712 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 15078 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14713 | 15079 | ||
14714 | if (spec->kctls.list) | 15080 | if (spec->kctls.list) |
@@ -14717,13 +15083,12 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14717 | add_verb(spec, alc861vd_volume_init_verbs); | 15083 | add_verb(spec, alc861vd_volume_init_verbs); |
14718 | 15084 | ||
14719 | spec->num_mux_defs = 1; | 15085 | spec->num_mux_defs = 1; |
14720 | spec->input_mux = &spec->private_imux; | 15086 | spec->input_mux = &spec->private_imux[0]; |
14721 | 15087 | ||
14722 | err = alc_auto_add_mic_boost(codec); | 15088 | err = alc_auto_add_mic_boost(codec); |
14723 | if (err < 0) | 15089 | if (err < 0) |
14724 | return err; | 15090 | return err; |
14725 | 15091 | ||
14726 | store_pin_configs(codec); | ||
14727 | return 1; | 15092 | return 1; |
14728 | } | 15093 | } |
14729 | 15094 | ||
@@ -14774,6 +15139,12 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14774 | } | 15139 | } |
14775 | } | 15140 | } |
14776 | 15141 | ||
15142 | err = snd_hda_attach_beep_device(codec, 0x23); | ||
15143 | if (err < 0) { | ||
15144 | alc_free(codec); | ||
15145 | return err; | ||
15146 | } | ||
15147 | |||
14777 | if (board_config != ALC861VD_AUTO) | 15148 | if (board_config != ALC861VD_AUTO) |
14778 | setup_preset(spec, &alc861vd_presets[board_config]); | 15149 | setup_preset(spec, &alc861vd_presets[board_config]); |
14779 | 15150 | ||
@@ -14796,9 +15167,10 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14796 | spec->adc_nids = alc861vd_adc_nids; | 15167 | spec->adc_nids = alc861vd_adc_nids; |
14797 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); | 15168 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); |
14798 | spec->capsrc_nids = alc861vd_capsrc_nids; | 15169 | spec->capsrc_nids = alc861vd_capsrc_nids; |
14799 | spec->is_mix_capture = 1; | 15170 | spec->capture_style = CAPT_MIX; |
14800 | 15171 | ||
14801 | set_capture_mixer(spec); | 15172 | set_capture_mixer(spec); |
15173 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
14802 | 15174 | ||
14803 | spec->vmaster_nid = 0x02; | 15175 | spec->vmaster_nid = 0x02; |
14804 | 15176 | ||
@@ -14987,8 +15359,6 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { | |||
14987 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 15359 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
14988 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 15360 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
14989 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 15361 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
14990 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
14991 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
14992 | { } /* end */ | 15362 | { } /* end */ |
14993 | }; | 15363 | }; |
14994 | 15364 | ||
@@ -15010,8 +15380,6 @@ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { | |||
15010 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 15380 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
15011 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 15381 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
15012 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 15382 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
15013 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
15014 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
15015 | { } /* end */ | 15383 | { } /* end */ |
15016 | }; | 15384 | }; |
15017 | 15385 | ||
@@ -15987,56 +16355,55 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { | |||
15987 | }; | 16355 | }; |
15988 | 16356 | ||
15989 | static struct snd_pci_quirk alc662_cfg_tbl[] = { | 16357 | static struct snd_pci_quirk alc662_cfg_tbl[] = { |
15990 | SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), | 16358 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), |
15991 | SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), | ||
15992 | SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), | ||
15993 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), | ||
15994 | SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), | ||
15995 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), | ||
15996 | SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1), | ||
15997 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), | 16359 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), |
15998 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), | 16360 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), |
15999 | SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), | 16361 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), |
16000 | SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1), | ||
16001 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), | 16362 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), |
16363 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), | ||
16002 | SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), | 16364 | SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), |
16003 | SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), | ||
16004 | SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), | ||
16005 | SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), | ||
16006 | SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), | 16365 | SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), |
16007 | SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), | 16366 | SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), |
16008 | SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), | 16367 | SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), |
16368 | SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), | ||
16369 | SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), | ||
16370 | SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), | ||
16009 | SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2), | 16371 | SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2), |
16010 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), | 16372 | SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), |
16011 | SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), | 16373 | SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), |
16374 | SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), | ||
16012 | SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2), | 16375 | SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2), |
16013 | SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), | 16376 | SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), |
16014 | SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), | 16377 | SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), |
16015 | SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), | 16378 | /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/ |
16016 | SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), | ||
16017 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), | 16379 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), |
16018 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), | ||
16019 | SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), | ||
16020 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), | 16380 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), |
16021 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), | 16381 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), |
16382 | SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), | ||
16383 | SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), | ||
16384 | SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), | ||
16385 | SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), | ||
16386 | SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), | ||
16387 | SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), | ||
16388 | /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/ | ||
16389 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), | ||
16390 | SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), | ||
16391 | SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), | ||
16022 | SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4), | 16392 | SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4), |
16023 | SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), | 16393 | SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), |
16024 | SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), | 16394 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), |
16025 | SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), | 16395 | SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), |
16026 | SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), | 16396 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), |
16027 | SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", | 16397 | SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", |
16028 | ALC662_3ST_6ch_DIG), | 16398 | ALC662_3ST_6ch_DIG), |
16029 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | ||
16030 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), | ||
16031 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), | ||
16032 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", | 16399 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", |
16033 | ALC662_3ST_6ch_DIG), | 16400 | ALC662_3ST_6ch_DIG), |
16034 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), | 16401 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), |
16402 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | ||
16035 | SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", | 16403 | SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", |
16036 | ALC662_3ST_6ch_DIG), | 16404 | ALC662_3ST_6ch_DIG), |
16037 | SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13), | 16405 | SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x", |
16038 | SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13), | 16406 | ALC663_ASUS_H13), |
16039 | SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13), | ||
16040 | {} | 16407 | {} |
16041 | }; | 16408 | }; |
16042 | 16409 | ||
@@ -16356,7 +16723,7 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
16356 | 16723 | ||
16357 | if (alc880_is_fixed_pin(pin)) { | 16724 | if (alc880_is_fixed_pin(pin)) { |
16358 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 16725 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); |
16359 | /* printk("DAC nid=%x\n",nid); */ | 16726 | /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ |
16360 | /* specify the DAC as the extra output */ | 16727 | /* specify the DAC as the extra output */ |
16361 | if (!spec->multiout.hp_nid) | 16728 | if (!spec->multiout.hp_nid) |
16362 | spec->multiout.hp_nid = nid; | 16729 | spec->multiout.hp_nid = nid; |
@@ -16386,26 +16753,58 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
16386 | return 0; | 16753 | return 0; |
16387 | } | 16754 | } |
16388 | 16755 | ||
16756 | /* return the index of the src widget from the connection list of the nid. | ||
16757 | * return -1 if not found | ||
16758 | */ | ||
16759 | static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid, | ||
16760 | hda_nid_t src) | ||
16761 | { | ||
16762 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
16763 | int i, conns; | ||
16764 | |||
16765 | conns = snd_hda_get_connections(codec, nid, conn_list, | ||
16766 | ARRAY_SIZE(conn_list)); | ||
16767 | if (conns < 0) | ||
16768 | return -1; | ||
16769 | for (i = 0; i < conns; i++) | ||
16770 | if (conn_list[i] == src) | ||
16771 | return i; | ||
16772 | return -1; | ||
16773 | } | ||
16774 | |||
16775 | static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid) | ||
16776 | { | ||
16777 | unsigned int pincap = snd_hda_query_pin_caps(codec, nid); | ||
16778 | return (pincap & AC_PINCAP_IN) != 0; | ||
16779 | } | ||
16780 | |||
16389 | /* create playback/capture controls for input pins */ | 16781 | /* create playback/capture controls for input pins */ |
16390 | static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, | 16782 | static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec, |
16391 | const struct auto_pin_cfg *cfg) | 16783 | const struct auto_pin_cfg *cfg) |
16392 | { | 16784 | { |
16393 | struct hda_input_mux *imux = &spec->private_imux; | 16785 | struct alc_spec *spec = codec->spec; |
16786 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
16394 | int i, err, idx; | 16787 | int i, err, idx; |
16395 | 16788 | ||
16396 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16789 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
16397 | if (alc880_is_input_pin(cfg->input_pins[i])) { | 16790 | if (alc662_is_input_pin(codec, cfg->input_pins[i])) { |
16398 | idx = alc880_input_pin_idx(cfg->input_pins[i]); | 16791 | idx = alc662_input_pin_idx(codec, 0x0b, |
16399 | err = new_analog_input(spec, cfg->input_pins[i], | 16792 | cfg->input_pins[i]); |
16400 | auto_pin_cfg_labels[i], | 16793 | if (idx >= 0) { |
16401 | idx, 0x0b); | 16794 | err = new_analog_input(spec, cfg->input_pins[i], |
16402 | if (err < 0) | 16795 | auto_pin_cfg_labels[i], |
16403 | return err; | 16796 | idx, 0x0b); |
16404 | imux->items[imux->num_items].label = | 16797 | if (err < 0) |
16405 | auto_pin_cfg_labels[i]; | 16798 | return err; |
16406 | imux->items[imux->num_items].index = | 16799 | } |
16407 | alc880_input_pin_idx(cfg->input_pins[i]); | 16800 | idx = alc662_input_pin_idx(codec, 0x22, |
16408 | imux->num_items++; | 16801 | cfg->input_pins[i]); |
16802 | if (idx >= 0) { | ||
16803 | imux->items[imux->num_items].label = | ||
16804 | auto_pin_cfg_labels[i]; | ||
16805 | imux->items[imux->num_items].index = idx; | ||
16806 | imux->num_items++; | ||
16807 | } | ||
16409 | } | 16808 | } |
16410 | } | 16809 | } |
16411 | return 0; | 16810 | return 0; |
@@ -16455,7 +16854,6 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) | |||
16455 | alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 16854 | alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
16456 | } | 16855 | } |
16457 | 16856 | ||
16458 | #define alc662_is_input_pin(nid) alc880_is_input_pin(nid) | ||
16459 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID | 16857 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID |
16460 | 16858 | ||
16461 | static void alc662_auto_init_analog_input(struct hda_codec *codec) | 16859 | static void alc662_auto_init_analog_input(struct hda_codec *codec) |
@@ -16465,12 +16863,10 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec) | |||
16465 | 16863 | ||
16466 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16864 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
16467 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 16865 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
16468 | if (alc662_is_input_pin(nid)) { | 16866 | if (alc662_is_input_pin(codec, nid)) { |
16469 | snd_hda_codec_write(codec, nid, 0, | 16867 | alc_set_input_pin(codec, nid, i); |
16470 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 16868 | if (nid != ALC662_PIN_CD_NID && |
16471 | (i <= AUTO_PIN_FRONT_MIC ? | 16869 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
16472 | PIN_VREF80 : PIN_IN)); | ||
16473 | if (nid != ALC662_PIN_CD_NID) | ||
16474 | snd_hda_codec_write(codec, nid, 0, | 16870 | snd_hda_codec_write(codec, nid, 0, |
16475 | AC_VERB_SET_AMP_GAIN_MUTE, | 16871 | AC_VERB_SET_AMP_GAIN_MUTE, |
16476 | AMP_OUT_MUTE); | 16872 | AMP_OUT_MUTE); |
@@ -16508,20 +16904,20 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16508 | "Headphone"); | 16904 | "Headphone"); |
16509 | if (err < 0) | 16905 | if (err < 0) |
16510 | return err; | 16906 | return err; |
16511 | err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); | 16907 | err = alc662_auto_create_analog_input_ctls(codec, &spec->autocfg); |
16512 | if (err < 0) | 16908 | if (err < 0) |
16513 | return err; | 16909 | return err; |
16514 | 16910 | ||
16515 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 16911 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
16516 | 16912 | ||
16517 | if (spec->autocfg.dig_out_pin) | 16913 | if (spec->autocfg.dig_outs) |
16518 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16914 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16519 | 16915 | ||
16520 | if (spec->kctls.list) | 16916 | if (spec->kctls.list) |
16521 | add_mixer(spec, spec->kctls.list); | 16917 | add_mixer(spec, spec->kctls.list); |
16522 | 16918 | ||
16523 | spec->num_mux_defs = 1; | 16919 | spec->num_mux_defs = 1; |
16524 | spec->input_mux = &spec->private_imux; | 16920 | spec->input_mux = &spec->private_imux[0]; |
16525 | 16921 | ||
16526 | add_verb(spec, alc662_auto_init_verbs); | 16922 | add_verb(spec, alc662_auto_init_verbs); |
16527 | if (codec->vendor_id == 0x10ec0663) | 16923 | if (codec->vendor_id == 0x10ec0663) |
@@ -16531,7 +16927,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16531 | if (err < 0) | 16927 | if (err < 0) |
16532 | return err; | 16928 | return err; |
16533 | 16929 | ||
16534 | store_pin_configs(codec); | ||
16535 | return 1; | 16930 | return 1; |
16536 | } | 16931 | } |
16537 | 16932 | ||
@@ -16583,6 +16978,12 @@ static int patch_alc662(struct hda_codec *codec) | |||
16583 | } | 16978 | } |
16584 | } | 16979 | } |
16585 | 16980 | ||
16981 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
16982 | if (err < 0) { | ||
16983 | alc_free(codec); | ||
16984 | return err; | ||
16985 | } | ||
16986 | |||
16586 | if (board_config != ALC662_AUTO) | 16987 | if (board_config != ALC662_AUTO) |
16587 | setup_preset(spec, &alc662_presets[board_config]); | 16988 | setup_preset(spec, &alc662_presets[board_config]); |
16588 | 16989 | ||
@@ -16606,10 +17007,14 @@ static int patch_alc662(struct hda_codec *codec) | |||
16606 | spec->adc_nids = alc662_adc_nids; | 17007 | spec->adc_nids = alc662_adc_nids; |
16607 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); | 17008 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); |
16608 | spec->capsrc_nids = alc662_capsrc_nids; | 17009 | spec->capsrc_nids = alc662_capsrc_nids; |
16609 | spec->is_mix_capture = 1; | 17010 | spec->capture_style = CAPT_MIX; |
16610 | 17011 | ||
16611 | if (!spec->cap_mixer) | 17012 | if (!spec->cap_mixer) |
16612 | set_capture_mixer(spec); | 17013 | set_capture_mixer(spec); |
17014 | if (codec->vendor_id == 0x10ec0662) | ||
17015 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
17016 | else | ||
17017 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
16613 | 17018 | ||
16614 | spec->vmaster_nid = 0x02; | 17019 | spec->vmaster_nid = 0x02; |
16615 | 17020 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 38428e22428f..b5e108aa8f63 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -43,6 +43,7 @@ enum { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | enum { | 45 | enum { |
46 | STAC_AUTO, | ||
46 | STAC_REF, | 47 | STAC_REF, |
47 | STAC_9200_OQO, | 48 | STAC_9200_OQO, |
48 | STAC_9200_DELL_D21, | 49 | STAC_9200_DELL_D21, |
@@ -62,14 +63,17 @@ enum { | |||
62 | }; | 63 | }; |
63 | 64 | ||
64 | enum { | 65 | enum { |
66 | STAC_9205_AUTO, | ||
65 | STAC_9205_REF, | 67 | STAC_9205_REF, |
66 | STAC_9205_DELL_M42, | 68 | STAC_9205_DELL_M42, |
67 | STAC_9205_DELL_M43, | 69 | STAC_9205_DELL_M43, |
68 | STAC_9205_DELL_M44, | 70 | STAC_9205_DELL_M44, |
71 | STAC_9205_EAPD, | ||
69 | STAC_9205_MODELS | 72 | STAC_9205_MODELS |
70 | }; | 73 | }; |
71 | 74 | ||
72 | enum { | 75 | enum { |
76 | STAC_92HD73XX_AUTO, | ||
73 | STAC_92HD73XX_NO_JD, /* no jack-detection */ | 77 | STAC_92HD73XX_NO_JD, /* no jack-detection */ |
74 | STAC_92HD73XX_REF, | 78 | STAC_92HD73XX_REF, |
75 | STAC_DELL_M6_AMIC, | 79 | STAC_DELL_M6_AMIC, |
@@ -80,22 +84,27 @@ enum { | |||
80 | }; | 84 | }; |
81 | 85 | ||
82 | enum { | 86 | enum { |
87 | STAC_92HD83XXX_AUTO, | ||
83 | STAC_92HD83XXX_REF, | 88 | STAC_92HD83XXX_REF, |
84 | STAC_92HD83XXX_PWR_REF, | 89 | STAC_92HD83XXX_PWR_REF, |
90 | STAC_DELL_S14, | ||
85 | STAC_92HD83XXX_MODELS | 91 | STAC_92HD83XXX_MODELS |
86 | }; | 92 | }; |
87 | 93 | ||
88 | enum { | 94 | enum { |
95 | STAC_92HD71BXX_AUTO, | ||
89 | STAC_92HD71BXX_REF, | 96 | STAC_92HD71BXX_REF, |
90 | STAC_DELL_M4_1, | 97 | STAC_DELL_M4_1, |
91 | STAC_DELL_M4_2, | 98 | STAC_DELL_M4_2, |
92 | STAC_DELL_M4_3, | 99 | STAC_DELL_M4_3, |
93 | STAC_HP_M4, | 100 | STAC_HP_M4, |
94 | STAC_HP_DV5, | 101 | STAC_HP_DV5, |
102 | STAC_HP_HDX, | ||
95 | STAC_92HD71BXX_MODELS | 103 | STAC_92HD71BXX_MODELS |
96 | }; | 104 | }; |
97 | 105 | ||
98 | enum { | 106 | enum { |
107 | STAC_925x_AUTO, | ||
99 | STAC_925x_REF, | 108 | STAC_925x_REF, |
100 | STAC_M1, | 109 | STAC_M1, |
101 | STAC_M1_2, | 110 | STAC_M1_2, |
@@ -108,6 +117,7 @@ enum { | |||
108 | }; | 117 | }; |
109 | 118 | ||
110 | enum { | 119 | enum { |
120 | STAC_922X_AUTO, | ||
111 | STAC_D945_REF, | 121 | STAC_D945_REF, |
112 | STAC_D945GTP3, | 122 | STAC_D945GTP3, |
113 | STAC_D945GTP5, | 123 | STAC_D945GTP5, |
@@ -135,6 +145,7 @@ enum { | |||
135 | }; | 145 | }; |
136 | 146 | ||
137 | enum { | 147 | enum { |
148 | STAC_927X_AUTO, | ||
138 | STAC_D965_REF_NO_JD, /* no jack-detection */ | 149 | STAC_D965_REF_NO_JD, /* no jack-detection */ |
139 | STAC_D965_REF, | 150 | STAC_D965_REF, |
140 | STAC_D965_3ST, | 151 | STAC_D965_3ST, |
@@ -144,6 +155,12 @@ enum { | |||
144 | STAC_927X_MODELS | 155 | STAC_927X_MODELS |
145 | }; | 156 | }; |
146 | 157 | ||
158 | enum { | ||
159 | STAC_9872_AUTO, | ||
160 | STAC_9872_VAIO, | ||
161 | STAC_9872_MODELS | ||
162 | }; | ||
163 | |||
147 | struct sigmatel_event { | 164 | struct sigmatel_event { |
148 | hda_nid_t nid; | 165 | hda_nid_t nid; |
149 | unsigned char type; | 166 | unsigned char type; |
@@ -167,6 +184,7 @@ struct sigmatel_spec { | |||
167 | unsigned int alt_switch: 1; | 184 | unsigned int alt_switch: 1; |
168 | unsigned int hp_detect: 1; | 185 | unsigned int hp_detect: 1; |
169 | unsigned int spdif_mute: 1; | 186 | unsigned int spdif_mute: 1; |
187 | unsigned int check_volume_offset:1; | ||
170 | 188 | ||
171 | /* gpio lines */ | 189 | /* gpio lines */ |
172 | unsigned int eapd_mask; | 190 | unsigned int eapd_mask; |
@@ -179,6 +197,7 @@ struct sigmatel_spec { | |||
179 | unsigned int stream_delay; | 197 | unsigned int stream_delay; |
180 | 198 | ||
181 | /* analog loopback */ | 199 | /* analog loopback */ |
200 | struct snd_kcontrol_new *aloopback_ctl; | ||
182 | unsigned char aloopback_mask; | 201 | unsigned char aloopback_mask; |
183 | unsigned char aloopback_shift; | 202 | unsigned char aloopback_shift; |
184 | 203 | ||
@@ -203,6 +222,8 @@ struct sigmatel_spec { | |||
203 | hda_nid_t hp_dacs[5]; | 222 | hda_nid_t hp_dacs[5]; |
204 | hda_nid_t speaker_dacs[5]; | 223 | hda_nid_t speaker_dacs[5]; |
205 | 224 | ||
225 | int volume_offset; | ||
226 | |||
206 | /* capture */ | 227 | /* capture */ |
207 | hda_nid_t *adc_nids; | 228 | hda_nid_t *adc_nids; |
208 | unsigned int num_adcs; | 229 | unsigned int num_adcs; |
@@ -224,7 +245,6 @@ struct sigmatel_spec { | |||
224 | /* pin widgets */ | 245 | /* pin widgets */ |
225 | hda_nid_t *pin_nids; | 246 | hda_nid_t *pin_nids; |
226 | unsigned int num_pins; | 247 | unsigned int num_pins; |
227 | unsigned int *pin_configs; | ||
228 | 248 | ||
229 | /* codec specific stuff */ | 249 | /* codec specific stuff */ |
230 | struct hda_verb *init; | 250 | struct hda_verb *init; |
@@ -400,6 +420,10 @@ static hda_nid_t stac922x_mux_nids[2] = { | |||
400 | 0x12, 0x13, | 420 | 0x12, 0x13, |
401 | }; | 421 | }; |
402 | 422 | ||
423 | static hda_nid_t stac927x_slave_dig_outs[2] = { | ||
424 | 0x1f, 0, | ||
425 | }; | ||
426 | |||
403 | static hda_nid_t stac927x_adc_nids[3] = { | 427 | static hda_nid_t stac927x_adc_nids[3] = { |
404 | 0x07, 0x08, 0x09 | 428 | 0x07, 0x08, 0x09 |
405 | }; | 429 | }; |
@@ -472,15 +496,21 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = { | |||
472 | 0x14, 0x22, 0x23 | 496 | 0x14, 0x22, 0x23 |
473 | }; | 497 | }; |
474 | 498 | ||
475 | static hda_nid_t stac92hd83xxx_pin_nids[14] = { | 499 | static hda_nid_t stac92hd83xxx_pin_nids[10] = { |
476 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 500 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
477 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 501 | 0x0f, 0x10, 0x11, 0x1f, 0x20, |
478 | 0x1d, 0x1e, 0x1f, 0x20 | 502 | }; |
503 | |||
504 | #define STAC92HD71BXX_NUM_PINS 13 | ||
505 | static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { | ||
506 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, | ||
507 | 0x00, 0x14, 0x18, 0x19, 0x1e, | ||
508 | 0x1f, 0x20, 0x27 | ||
479 | }; | 509 | }; |
480 | static hda_nid_t stac92hd71bxx_pin_nids[11] = { | 510 | static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = { |
481 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 511 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
482 | 0x0f, 0x14, 0x18, 0x19, 0x1e, | 512 | 0x0f, 0x14, 0x18, 0x19, 0x1e, |
483 | 0x1f, | 513 | 0x1f, 0x20, 0x27 |
484 | }; | 514 | }; |
485 | 515 | ||
486 | static hda_nid_t stac927x_pin_nids[14] = { | 516 | static hda_nid_t stac927x_pin_nids[14] = { |
@@ -842,9 +872,9 @@ static struct hda_verb stac92hd73xx_10ch_core_init[] = { | |||
842 | }; | 872 | }; |
843 | 873 | ||
844 | static struct hda_verb stac92hd83xxx_core_init[] = { | 874 | static struct hda_verb stac92hd83xxx_core_init[] = { |
845 | { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0}, | 875 | { 0xa, AC_VERB_SET_CONNECT_SEL, 0x1}, |
846 | { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0}, | 876 | { 0xb, AC_VERB_SET_CONNECT_SEL, 0x1}, |
847 | { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1}, | 877 | { 0xd, AC_VERB_SET_CONNECT_SEL, 0x0}, |
848 | 878 | ||
849 | /* power state controls amps */ | 879 | /* power state controls amps */ |
850 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, | 880 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, |
@@ -854,26 +884,25 @@ static struct hda_verb stac92hd83xxx_core_init[] = { | |||
854 | static struct hda_verb stac92hd71bxx_core_init[] = { | 884 | static struct hda_verb stac92hd71bxx_core_init[] = { |
855 | /* set master volume and direct control */ | 885 | /* set master volume and direct control */ |
856 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 886 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
857 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | ||
858 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
859 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
860 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
861 | {} | 887 | {} |
862 | }; | 888 | }; |
863 | 889 | ||
864 | #define HD_DISABLE_PORTF 2 | 890 | #define HD_DISABLE_PORTF 1 |
865 | static struct hda_verb stac92hd71bxx_analog_core_init[] = { | 891 | static struct hda_verb stac92hd71bxx_analog_core_init[] = { |
866 | /* start of config #1 */ | 892 | /* start of config #1 */ |
867 | 893 | ||
868 | /* connect port 0f to audio mixer */ | 894 | /* connect port 0f to audio mixer */ |
869 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | 895 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, |
870 | /* unmute right and left channels for node 0x0f */ | ||
871 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
872 | /* start of config #2 */ | 896 | /* start of config #2 */ |
873 | 897 | ||
874 | /* set master volume and direct control */ | 898 | /* set master volume and direct control */ |
875 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 899 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
876 | /* unmute right and left channels for nodes 0x0a, 0xd */ | 900 | {} |
901 | }; | ||
902 | |||
903 | static struct hda_verb stac92hd71bxx_unmute_core_init[] = { | ||
904 | /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ | ||
905 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
877 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 906 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
878 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 907 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
879 | {} | 908 | {} |
@@ -954,16 +983,6 @@ static struct hda_verb stac9205_core_init[] = { | |||
954 | .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ | 983 | .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ |
955 | } | 984 | } |
956 | 985 | ||
957 | #define STAC_INPUT_SOURCE(cnt) \ | ||
958 | { \ | ||
959 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
960 | .name = "Input Source", \ | ||
961 | .count = cnt, \ | ||
962 | .info = stac92xx_mux_enum_info, \ | ||
963 | .get = stac92xx_mux_enum_get, \ | ||
964 | .put = stac92xx_mux_enum_put, \ | ||
965 | } | ||
966 | |||
967 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ | 986 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ |
968 | { \ | 987 | { \ |
969 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 988 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
@@ -978,7 +997,6 @@ static struct hda_verb stac9205_core_init[] = { | |||
978 | static struct snd_kcontrol_new stac9200_mixer[] = { | 997 | static struct snd_kcontrol_new stac9200_mixer[] = { |
979 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 998 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
980 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 999 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
981 | STAC_INPUT_SOURCE(1), | ||
982 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 1000 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
983 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 1001 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
984 | { } /* end */ | 1002 | { } /* end */ |
@@ -1003,8 +1021,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { | |||
1003 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | 1021 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), |
1004 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | 1022 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), |
1005 | 1023 | ||
1006 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | ||
1007 | |||
1008 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1024 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1009 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1025 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1010 | 1026 | ||
@@ -1014,9 +1030,22 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { | |||
1014 | { } /* end */ | 1030 | { } /* end */ |
1015 | }; | 1031 | }; |
1016 | 1032 | ||
1017 | static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | 1033 | static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = { |
1034 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | ||
1035 | {} | ||
1036 | }; | ||
1037 | |||
1038 | static struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = { | ||
1018 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), | 1039 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), |
1040 | {} | ||
1041 | }; | ||
1019 | 1042 | ||
1043 | static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = { | ||
1044 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | ||
1045 | {} | ||
1046 | }; | ||
1047 | |||
1048 | static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | ||
1020 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1049 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1021 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1050 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1022 | 1051 | ||
@@ -1041,8 +1070,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | |||
1041 | }; | 1070 | }; |
1042 | 1071 | ||
1043 | static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { | 1072 | static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { |
1044 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | ||
1045 | |||
1046 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1073 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1047 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 1074 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), |
1048 | 1075 | ||
@@ -1094,9 +1121,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { | |||
1094 | }; | 1121 | }; |
1095 | 1122 | ||
1096 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | 1123 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { |
1097 | STAC_INPUT_SOURCE(2), | ||
1098 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | ||
1099 | |||
1100 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1124 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1101 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1125 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1102 | 1126 | ||
@@ -1122,10 +1146,11 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | |||
1122 | { } /* end */ | 1146 | { } /* end */ |
1123 | }; | 1147 | }; |
1124 | 1148 | ||
1125 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | 1149 | static struct snd_kcontrol_new stac92hd71bxx_loopback[] = { |
1126 | STAC_INPUT_SOURCE(2), | 1150 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2) |
1127 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | 1151 | }; |
1128 | 1152 | ||
1153 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | ||
1129 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1154 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1130 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 1155 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
1131 | 1156 | ||
@@ -1137,16 +1162,12 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | |||
1137 | static struct snd_kcontrol_new stac925x_mixer[] = { | 1162 | static struct snd_kcontrol_new stac925x_mixer[] = { |
1138 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), | 1163 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), |
1139 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), | 1164 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), |
1140 | STAC_INPUT_SOURCE(1), | ||
1141 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), | 1165 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), |
1142 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), | 1166 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), |
1143 | { } /* end */ | 1167 | { } /* end */ |
1144 | }; | 1168 | }; |
1145 | 1169 | ||
1146 | static struct snd_kcontrol_new stac9205_mixer[] = { | 1170 | static struct snd_kcontrol_new stac9205_mixer[] = { |
1147 | STAC_INPUT_SOURCE(2), | ||
1148 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), | ||
1149 | |||
1150 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), | 1171 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), |
1151 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), | 1172 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), |
1152 | 1173 | ||
@@ -1155,9 +1176,13 @@ static struct snd_kcontrol_new stac9205_mixer[] = { | |||
1155 | { } /* end */ | 1176 | { } /* end */ |
1156 | }; | 1177 | }; |
1157 | 1178 | ||
1179 | static struct snd_kcontrol_new stac9205_loopback[] = { | ||
1180 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), | ||
1181 | {} | ||
1182 | }; | ||
1183 | |||
1158 | /* This needs to be generated dynamically based on sequence */ | 1184 | /* This needs to be generated dynamically based on sequence */ |
1159 | static struct snd_kcontrol_new stac922x_mixer[] = { | 1185 | static struct snd_kcontrol_new stac922x_mixer[] = { |
1160 | STAC_INPUT_SOURCE(2), | ||
1161 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), | 1186 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), |
1162 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), | 1187 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), |
1163 | 1188 | ||
@@ -1168,9 +1193,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = { | |||
1168 | 1193 | ||
1169 | 1194 | ||
1170 | static struct snd_kcontrol_new stac927x_mixer[] = { | 1195 | static struct snd_kcontrol_new stac927x_mixer[] = { |
1171 | STAC_INPUT_SOURCE(3), | ||
1172 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), | ||
1173 | |||
1174 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), | 1196 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), |
1175 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), | 1197 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), |
1176 | 1198 | ||
@@ -1182,6 +1204,11 @@ static struct snd_kcontrol_new stac927x_mixer[] = { | |||
1182 | { } /* end */ | 1204 | { } /* end */ |
1183 | }; | 1205 | }; |
1184 | 1206 | ||
1207 | static struct snd_kcontrol_new stac927x_loopback[] = { | ||
1208 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), | ||
1209 | {} | ||
1210 | }; | ||
1211 | |||
1185 | static struct snd_kcontrol_new stac_dmux_mixer = { | 1212 | static struct snd_kcontrol_new stac_dmux_mixer = { |
1186 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1213 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1187 | .name = "Digital Input Source", | 1214 | .name = "Digital Input Source", |
@@ -1207,10 +1234,7 @@ static const char *slave_vols[] = { | |||
1207 | "LFE Playback Volume", | 1234 | "LFE Playback Volume", |
1208 | "Side Playback Volume", | 1235 | "Side Playback Volume", |
1209 | "Headphone Playback Volume", | 1236 | "Headphone Playback Volume", |
1210 | "Headphone Playback Volume", | ||
1211 | "Speaker Playback Volume", | 1237 | "Speaker Playback Volume", |
1212 | "External Speaker Playback Volume", | ||
1213 | "Speaker2 Playback Volume", | ||
1214 | NULL | 1238 | NULL |
1215 | }; | 1239 | }; |
1216 | 1240 | ||
@@ -1221,10 +1245,7 @@ static const char *slave_sws[] = { | |||
1221 | "LFE Playback Switch", | 1245 | "LFE Playback Switch", |
1222 | "Side Playback Switch", | 1246 | "Side Playback Switch", |
1223 | "Headphone Playback Switch", | 1247 | "Headphone Playback Switch", |
1224 | "Headphone Playback Switch", | ||
1225 | "Speaker Playback Switch", | 1248 | "Speaker Playback Switch", |
1226 | "External Speaker Playback Switch", | ||
1227 | "Speaker2 Playback Switch", | ||
1228 | "IEC958 Playback Switch", | 1249 | "IEC958 Playback Switch", |
1229 | NULL | 1250 | NULL |
1230 | }; | 1251 | }; |
@@ -1294,6 +1315,8 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1294 | unsigned int vmaster_tlv[4]; | 1315 | unsigned int vmaster_tlv[4]; |
1295 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 1316 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], |
1296 | HDA_OUTPUT, vmaster_tlv); | 1317 | HDA_OUTPUT, vmaster_tlv); |
1318 | /* correct volume offset */ | ||
1319 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | ||
1297 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1320 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1298 | vmaster_tlv, slave_vols); | 1321 | vmaster_tlv, slave_vols); |
1299 | if (err < 0) | 1322 | if (err < 0) |
@@ -1306,6 +1329,13 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1306 | return err; | 1329 | return err; |
1307 | } | 1330 | } |
1308 | 1331 | ||
1332 | if (spec->aloopback_ctl && | ||
1333 | snd_hda_get_bool_hint(codec, "loopback") == 1) { | ||
1334 | err = snd_hda_add_new_ctls(codec, spec->aloopback_ctl); | ||
1335 | if (err < 0) | ||
1336 | return err; | ||
1337 | } | ||
1338 | |||
1309 | stac92xx_free_kctls(codec); /* no longer needed */ | 1339 | stac92xx_free_kctls(codec); /* no longer needed */ |
1310 | 1340 | ||
1311 | /* create jack input elements */ | 1341 | /* create jack input elements */ |
@@ -1490,6 +1520,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { | |||
1490 | }; | 1520 | }; |
1491 | 1521 | ||
1492 | static const char *stac9200_models[STAC_9200_MODELS] = { | 1522 | static const char *stac9200_models[STAC_9200_MODELS] = { |
1523 | [STAC_AUTO] = "auto", | ||
1493 | [STAC_REF] = "ref", | 1524 | [STAC_REF] = "ref", |
1494 | [STAC_9200_OQO] = "oqo", | 1525 | [STAC_9200_OQO] = "oqo", |
1495 | [STAC_9200_DELL_D21] = "dell-d21", | 1526 | [STAC_9200_DELL_D21] = "dell-d21", |
@@ -1511,6 +1542,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { | |||
1511 | /* SigmaTel reference board */ | 1542 | /* SigmaTel reference board */ |
1512 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1543 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1513 | "DFI LanParty", STAC_REF), | 1544 | "DFI LanParty", STAC_REF), |
1545 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
1546 | "DFI LanParty", STAC_REF), | ||
1514 | /* Dell laptops have BIOS problem */ | 1547 | /* Dell laptops have BIOS problem */ |
1515 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, | 1548 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, |
1516 | "unknown Dell", STAC_9200_DELL_D21), | 1549 | "unknown Dell", STAC_9200_DELL_D21), |
@@ -1633,6 +1666,7 @@ static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = { | |||
1633 | }; | 1666 | }; |
1634 | 1667 | ||
1635 | static const char *stac925x_models[STAC_925x_MODELS] = { | 1668 | static const char *stac925x_models[STAC_925x_MODELS] = { |
1669 | [STAC_925x_AUTO] = "auto", | ||
1636 | [STAC_REF] = "ref", | 1670 | [STAC_REF] = "ref", |
1637 | [STAC_M1] = "m1", | 1671 | [STAC_M1] = "m1", |
1638 | [STAC_M1_2] = "m1-2", | 1672 | [STAC_M1_2] = "m1-2", |
@@ -1660,6 +1694,7 @@ static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = { | |||
1660 | static struct snd_pci_quirk stac925x_cfg_tbl[] = { | 1694 | static struct snd_pci_quirk stac925x_cfg_tbl[] = { |
1661 | /* SigmaTel reference board */ | 1695 | /* SigmaTel reference board */ |
1662 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), | 1696 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), |
1697 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), | ||
1663 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), | 1698 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), |
1664 | 1699 | ||
1665 | /* Default table for unknown ID */ | 1700 | /* Default table for unknown ID */ |
@@ -1691,6 +1726,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | |||
1691 | }; | 1726 | }; |
1692 | 1727 | ||
1693 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | 1728 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { |
1729 | [STAC_92HD73XX_AUTO] = "auto", | ||
1694 | [STAC_92HD73XX_NO_JD] = "no-jd", | 1730 | [STAC_92HD73XX_NO_JD] = "no-jd", |
1695 | [STAC_92HD73XX_REF] = "ref", | 1731 | [STAC_92HD73XX_REF] = "ref", |
1696 | [STAC_DELL_M6_AMIC] = "dell-m6-amic", | 1732 | [STAC_DELL_M6_AMIC] = "dell-m6-amic", |
@@ -1703,6 +1739,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1703 | /* SigmaTel reference board */ | 1739 | /* SigmaTel reference board */ |
1704 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1740 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1705 | "DFI LanParty", STAC_92HD73XX_REF), | 1741 | "DFI LanParty", STAC_92HD73XX_REF), |
1742 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
1743 | "DFI LanParty", STAC_92HD73XX_REF), | ||
1706 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, | 1744 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, |
1707 | "Dell Studio 1535", STAC_DELL_M6_DMIC), | 1745 | "Dell Studio 1535", STAC_DELL_M6_DMIC), |
1708 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, | 1746 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, |
@@ -1726,52 +1764,68 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1726 | {} /* terminator */ | 1764 | {} /* terminator */ |
1727 | }; | 1765 | }; |
1728 | 1766 | ||
1729 | static unsigned int ref92hd83xxx_pin_configs[14] = { | 1767 | static unsigned int ref92hd83xxx_pin_configs[10] = { |
1730 | 0x02214030, 0x02211010, 0x02a19020, 0x02170130, | 1768 | 0x02214030, 0x02211010, 0x02a19020, 0x02170130, |
1731 | 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, | 1769 | 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, |
1732 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x40f000f0, | ||
1733 | 0x01451160, 0x98560170, | 1770 | 0x01451160, 0x98560170, |
1734 | }; | 1771 | }; |
1735 | 1772 | ||
1773 | static unsigned int dell_s14_pin_configs[10] = { | ||
1774 | 0x02214030, 0x02211010, 0x02a19020, 0x01014050, | ||
1775 | 0x40f000f0, 0x01819040, 0x40f000f0, 0x90a60160, | ||
1776 | 0x40f000f0, 0x40f000f0, | ||
1777 | }; | ||
1778 | |||
1736 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 1779 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { |
1737 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 1780 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, |
1738 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | 1781 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, |
1782 | [STAC_DELL_S14] = dell_s14_pin_configs, | ||
1739 | }; | 1783 | }; |
1740 | 1784 | ||
1741 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 1785 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { |
1786 | [STAC_92HD83XXX_AUTO] = "auto", | ||
1742 | [STAC_92HD83XXX_REF] = "ref", | 1787 | [STAC_92HD83XXX_REF] = "ref", |
1743 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", | 1788 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", |
1789 | [STAC_DELL_S14] = "dell-s14", | ||
1744 | }; | 1790 | }; |
1745 | 1791 | ||
1746 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1792 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
1747 | /* SigmaTel reference board */ | 1793 | /* SigmaTel reference board */ |
1748 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1794 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1749 | "DFI LanParty", STAC_92HD83XXX_REF), | 1795 | "DFI LanParty", STAC_92HD83XXX_REF), |
1796 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
1797 | "DFI LanParty", STAC_92HD83XXX_REF), | ||
1798 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, | ||
1799 | "unknown Dell", STAC_DELL_S14), | ||
1750 | {} /* terminator */ | 1800 | {} /* terminator */ |
1751 | }; | 1801 | }; |
1752 | 1802 | ||
1753 | static unsigned int ref92hd71bxx_pin_configs[11] = { | 1803 | static unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1754 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, | 1804 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, |
1755 | 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, | 1805 | 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, |
1756 | 0x90a000f0, 0x01452050, 0x01452050, | 1806 | 0x90a000f0, 0x01452050, 0x01452050, 0x00000000, |
1807 | 0x00000000 | ||
1757 | }; | 1808 | }; |
1758 | 1809 | ||
1759 | static unsigned int dell_m4_1_pin_configs[11] = { | 1810 | static unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1760 | 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, | 1811 | 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, |
1761 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, | 1812 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, |
1762 | 0x40f000f0, 0x4f0000f0, 0x4f0000f0, | 1813 | 0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000, |
1814 | 0x00000000 | ||
1763 | }; | 1815 | }; |
1764 | 1816 | ||
1765 | static unsigned int dell_m4_2_pin_configs[11] = { | 1817 | static unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1766 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, | 1818 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, |
1767 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, | 1819 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, |
1768 | 0x40f000f0, 0x044413b0, 0x044413b0, | 1820 | 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, |
1821 | 0x00000000 | ||
1769 | }; | 1822 | }; |
1770 | 1823 | ||
1771 | static unsigned int dell_m4_3_pin_configs[11] = { | 1824 | static unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = { |
1772 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, | 1825 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, |
1773 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0, | 1826 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0, |
1774 | 0x40f000f0, 0x044413b0, 0x044413b0, | 1827 | 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, |
1828 | 0x00000000 | ||
1775 | }; | 1829 | }; |
1776 | 1830 | ||
1777 | static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | 1831 | static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { |
@@ -1781,35 +1835,38 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | |||
1781 | [STAC_DELL_M4_3] = dell_m4_3_pin_configs, | 1835 | [STAC_DELL_M4_3] = dell_m4_3_pin_configs, |
1782 | [STAC_HP_M4] = NULL, | 1836 | [STAC_HP_M4] = NULL, |
1783 | [STAC_HP_DV5] = NULL, | 1837 | [STAC_HP_DV5] = NULL, |
1838 | [STAC_HP_HDX] = NULL, | ||
1784 | }; | 1839 | }; |
1785 | 1840 | ||
1786 | static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { | 1841 | static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { |
1842 | [STAC_92HD71BXX_AUTO] = "auto", | ||
1787 | [STAC_92HD71BXX_REF] = "ref", | 1843 | [STAC_92HD71BXX_REF] = "ref", |
1788 | [STAC_DELL_M4_1] = "dell-m4-1", | 1844 | [STAC_DELL_M4_1] = "dell-m4-1", |
1789 | [STAC_DELL_M4_2] = "dell-m4-2", | 1845 | [STAC_DELL_M4_2] = "dell-m4-2", |
1790 | [STAC_DELL_M4_3] = "dell-m4-3", | 1846 | [STAC_DELL_M4_3] = "dell-m4-3", |
1791 | [STAC_HP_M4] = "hp-m4", | 1847 | [STAC_HP_M4] = "hp-m4", |
1792 | [STAC_HP_DV5] = "hp-dv5", | 1848 | [STAC_HP_DV5] = "hp-dv5", |
1849 | [STAC_HP_HDX] = "hp-hdx", | ||
1793 | }; | 1850 | }; |
1794 | 1851 | ||
1795 | static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | 1852 | static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { |
1796 | /* SigmaTel reference board */ | 1853 | /* SigmaTel reference board */ |
1797 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1854 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1798 | "DFI LanParty", STAC_92HD71BXX_REF), | 1855 | "DFI LanParty", STAC_92HD71BXX_REF), |
1799 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2, | 1856 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
1800 | "HP dv5", STAC_HP_M4), | 1857 | "DFI LanParty", STAC_92HD71BXX_REF), |
1801 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, | 1858 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, |
1802 | "HP dv7", STAC_HP_M4), | 1859 | "HP", STAC_HP_DV5), |
1803 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f7, | 1860 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, |
1804 | "HP dv4", STAC_HP_DV5), | 1861 | "HP dv4-7", STAC_HP_DV5), |
1805 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc, | 1862 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, |
1806 | "HP dv7", STAC_HP_M4), | 1863 | "HP dv4-7", STAC_HP_DV5), |
1807 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600, | 1864 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, |
1808 | "HP dv5", STAC_HP_DV5), | 1865 | "HP HDX", STAC_HP_HDX), /* HDX18 */ |
1809 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603, | ||
1810 | "HP dv5", STAC_HP_DV5), | ||
1811 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, | 1866 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, |
1812 | "unknown HP", STAC_HP_M4), | 1867 | "HP mini 1000", STAC_HP_M4), |
1868 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, | ||
1869 | "HP HDX", STAC_HP_HDX), /* HDX16 */ | ||
1813 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, | 1870 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, |
1814 | "unknown Dell", STAC_DELL_M4_1), | 1871 | "unknown Dell", STAC_DELL_M4_1), |
1815 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, | 1872 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, |
@@ -1961,6 +2018,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | |||
1961 | }; | 2018 | }; |
1962 | 2019 | ||
1963 | static const char *stac922x_models[STAC_922X_MODELS] = { | 2020 | static const char *stac922x_models[STAC_922X_MODELS] = { |
2021 | [STAC_922X_AUTO] = "auto", | ||
1964 | [STAC_D945_REF] = "ref", | 2022 | [STAC_D945_REF] = "ref", |
1965 | [STAC_D945GTP5] = "5stack", | 2023 | [STAC_D945GTP5] = "5stack", |
1966 | [STAC_D945GTP3] = "3stack", | 2024 | [STAC_D945GTP3] = "3stack", |
@@ -1988,6 +2046,8 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
1988 | /* SigmaTel reference board */ | 2046 | /* SigmaTel reference board */ |
1989 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2047 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1990 | "DFI LanParty", STAC_D945_REF), | 2048 | "DFI LanParty", STAC_D945_REF), |
2049 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
2050 | "DFI LanParty", STAC_D945_REF), | ||
1991 | /* Intel 945G based systems */ | 2051 | /* Intel 945G based systems */ |
1992 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, | 2052 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, |
1993 | "Intel D945G", STAC_D945GTP3), | 2053 | "Intel D945G", STAC_D945GTP3), |
@@ -2041,6 +2101,9 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
2041 | "Intel D945P", STAC_D945GTP3), | 2101 | "Intel D945P", STAC_D945GTP3), |
2042 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, | 2102 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, |
2043 | "Intel D945P", STAC_D945GTP5), | 2103 | "Intel D945P", STAC_D945GTP5), |
2104 | /* other intel */ | ||
2105 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204, | ||
2106 | "Intel D945", STAC_D945_REF), | ||
2044 | /* other systems */ | 2107 | /* other systems */ |
2045 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ | 2108 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ |
2046 | SND_PCI_QUIRK(0x8384, 0x7680, | 2109 | SND_PCI_QUIRK(0x8384, 0x7680, |
@@ -2065,31 +2128,7 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
2065 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, | 2128 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, |
2066 | "Dell XPS M1210", STAC_922X_DELL_M82), | 2129 | "Dell XPS M1210", STAC_922X_DELL_M82), |
2067 | /* ECS/PC Chips boards */ | 2130 | /* ECS/PC Chips boards */ |
2068 | SND_PCI_QUIRK(0x1019, 0x2144, | 2131 | SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000, |
2069 | "ECS/PC chips", STAC_ECS_202), | ||
2070 | SND_PCI_QUIRK(0x1019, 0x2608, | ||
2071 | "ECS/PC chips", STAC_ECS_202), | ||
2072 | SND_PCI_QUIRK(0x1019, 0x2633, | ||
2073 | "ECS/PC chips P17G/1333", STAC_ECS_202), | ||
2074 | SND_PCI_QUIRK(0x1019, 0x2811, | ||
2075 | "ECS/PC chips", STAC_ECS_202), | ||
2076 | SND_PCI_QUIRK(0x1019, 0x2812, | ||
2077 | "ECS/PC chips", STAC_ECS_202), | ||
2078 | SND_PCI_QUIRK(0x1019, 0x2813, | ||
2079 | "ECS/PC chips", STAC_ECS_202), | ||
2080 | SND_PCI_QUIRK(0x1019, 0x2814, | ||
2081 | "ECS/PC chips", STAC_ECS_202), | ||
2082 | SND_PCI_QUIRK(0x1019, 0x2815, | ||
2083 | "ECS/PC chips", STAC_ECS_202), | ||
2084 | SND_PCI_QUIRK(0x1019, 0x2816, | ||
2085 | "ECS/PC chips", STAC_ECS_202), | ||
2086 | SND_PCI_QUIRK(0x1019, 0x2817, | ||
2087 | "ECS/PC chips", STAC_ECS_202), | ||
2088 | SND_PCI_QUIRK(0x1019, 0x2818, | ||
2089 | "ECS/PC chips", STAC_ECS_202), | ||
2090 | SND_PCI_QUIRK(0x1019, 0x2819, | ||
2091 | "ECS/PC chips", STAC_ECS_202), | ||
2092 | SND_PCI_QUIRK(0x1019, 0x2820, | ||
2093 | "ECS/PC chips", STAC_ECS_202), | 2132 | "ECS/PC chips", STAC_ECS_202), |
2094 | {} /* terminator */ | 2133 | {} /* terminator */ |
2095 | }; | 2134 | }; |
@@ -2132,6 +2171,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | |||
2132 | }; | 2171 | }; |
2133 | 2172 | ||
2134 | static const char *stac927x_models[STAC_927X_MODELS] = { | 2173 | static const char *stac927x_models[STAC_927X_MODELS] = { |
2174 | [STAC_927X_AUTO] = "auto", | ||
2135 | [STAC_D965_REF_NO_JD] = "ref-no-jd", | 2175 | [STAC_D965_REF_NO_JD] = "ref-no-jd", |
2136 | [STAC_D965_REF] = "ref", | 2176 | [STAC_D965_REF] = "ref", |
2137 | [STAC_D965_3ST] = "3stack", | 2177 | [STAC_D965_3ST] = "3stack", |
@@ -2144,26 +2184,16 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
2144 | /* SigmaTel reference board */ | 2184 | /* SigmaTel reference board */ |
2145 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2185 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
2146 | "DFI LanParty", STAC_D965_REF), | 2186 | "DFI LanParty", STAC_D965_REF), |
2187 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
2188 | "DFI LanParty", STAC_D965_REF), | ||
2147 | /* Intel 946 based systems */ | 2189 | /* Intel 946 based systems */ |
2148 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), | 2190 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), |
2149 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), | 2191 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), |
2150 | /* 965 based 3 stack systems */ | 2192 | /* 965 based 3 stack systems */ |
2151 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST), | 2193 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100, |
2152 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST), | 2194 | "Intel D965", STAC_D965_3ST), |
2153 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST), | 2195 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000, |
2154 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST), | 2196 | "Intel D965", STAC_D965_3ST), |
2155 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST), | ||
2156 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST), | ||
2157 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST), | ||
2158 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST), | ||
2159 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST), | ||
2160 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST), | ||
2161 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST), | ||
2162 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST), | ||
2163 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST), | ||
2164 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), | ||
2165 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), | ||
2166 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), | ||
2167 | /* Dell 3 stack systems */ | 2197 | /* Dell 3 stack systems */ |
2168 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST), | 2198 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST), |
2169 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | 2199 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), |
@@ -2179,15 +2209,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
2179 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), | 2209 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), |
2180 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), | 2210 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), |
2181 | /* 965 based 5 stack systems */ | 2211 | /* 965 based 5 stack systems */ |
2182 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), | 2212 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300, |
2183 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), | 2213 | "Intel D965", STAC_D965_5ST), |
2184 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), | 2214 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, |
2185 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST), | 2215 | "Intel D965", STAC_D965_5ST), |
2186 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST), | ||
2187 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST), | ||
2188 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST), | ||
2189 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST), | ||
2190 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST), | ||
2191 | {} /* terminator */ | 2216 | {} /* terminator */ |
2192 | }; | 2217 | }; |
2193 | 2218 | ||
@@ -2240,19 +2265,25 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { | |||
2240 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, | 2265 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, |
2241 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, | 2266 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, |
2242 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, | 2267 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, |
2268 | [STAC_9205_EAPD] = NULL, | ||
2243 | }; | 2269 | }; |
2244 | 2270 | ||
2245 | static const char *stac9205_models[STAC_9205_MODELS] = { | 2271 | static const char *stac9205_models[STAC_9205_MODELS] = { |
2272 | [STAC_9205_AUTO] = "auto", | ||
2246 | [STAC_9205_REF] = "ref", | 2273 | [STAC_9205_REF] = "ref", |
2247 | [STAC_9205_DELL_M42] = "dell-m42", | 2274 | [STAC_9205_DELL_M42] = "dell-m42", |
2248 | [STAC_9205_DELL_M43] = "dell-m43", | 2275 | [STAC_9205_DELL_M43] = "dell-m43", |
2249 | [STAC_9205_DELL_M44] = "dell-m44", | 2276 | [STAC_9205_DELL_M44] = "dell-m44", |
2277 | [STAC_9205_EAPD] = "eapd", | ||
2250 | }; | 2278 | }; |
2251 | 2279 | ||
2252 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { | 2280 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { |
2253 | /* SigmaTel reference board */ | 2281 | /* SigmaTel reference board */ |
2254 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2282 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
2255 | "DFI LanParty", STAC_9205_REF), | 2283 | "DFI LanParty", STAC_9205_REF), |
2284 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | ||
2285 | "DFI LanParty", STAC_9205_REF), | ||
2286 | /* Dell */ | ||
2256 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, | 2287 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, |
2257 | "unknown Dell", STAC_9205_DELL_M42), | 2288 | "unknown Dell", STAC_9205_DELL_M42), |
2258 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, | 2289 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, |
@@ -2283,101 +2314,24 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { | |||
2283 | "Dell Inspiron", STAC_9205_DELL_M44), | 2314 | "Dell Inspiron", STAC_9205_DELL_M44), |
2284 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, | 2315 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, |
2285 | "Dell Vostro 1500", STAC_9205_DELL_M42), | 2316 | "Dell Vostro 1500", STAC_9205_DELL_M42), |
2317 | /* Gateway */ | ||
2318 | SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), | ||
2286 | {} /* terminator */ | 2319 | {} /* terminator */ |
2287 | }; | 2320 | }; |
2288 | 2321 | ||
2289 | static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | 2322 | static void stac92xx_set_config_regs(struct hda_codec *codec, |
2290 | { | 2323 | unsigned int *pincfgs) |
2291 | int i; | ||
2292 | struct sigmatel_spec *spec = codec->spec; | ||
2293 | |||
2294 | kfree(spec->pin_configs); | ||
2295 | spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs), | ||
2296 | GFP_KERNEL); | ||
2297 | if (!spec->pin_configs) | ||
2298 | return -ENOMEM; | ||
2299 | |||
2300 | for (i = 0; i < spec->num_pins; i++) { | ||
2301 | hda_nid_t nid = spec->pin_nids[i]; | ||
2302 | unsigned int pin_cfg; | ||
2303 | |||
2304 | pin_cfg = snd_hda_codec_read(codec, nid, 0, | ||
2305 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | ||
2306 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | ||
2307 | nid, pin_cfg); | ||
2308 | spec->pin_configs[i] = pin_cfg; | ||
2309 | } | ||
2310 | |||
2311 | return 0; | ||
2312 | } | ||
2313 | |||
2314 | static void stac92xx_set_config_reg(struct hda_codec *codec, | ||
2315 | hda_nid_t pin_nid, unsigned int pin_config) | ||
2316 | { | ||
2317 | int i; | ||
2318 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2319 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
2320 | pin_config & 0x000000ff); | ||
2321 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2322 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
2323 | (pin_config & 0x0000ff00) >> 8); | ||
2324 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2325 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
2326 | (pin_config & 0x00ff0000) >> 16); | ||
2327 | snd_hda_codec_write(codec, pin_nid, 0, | ||
2328 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
2329 | pin_config >> 24); | ||
2330 | i = snd_hda_codec_read(codec, pin_nid, 0, | ||
2331 | AC_VERB_GET_CONFIG_DEFAULT, | ||
2332 | 0x00); | ||
2333 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", | ||
2334 | pin_nid, i); | ||
2335 | } | ||
2336 | |||
2337 | static void stac92xx_set_config_regs(struct hda_codec *codec) | ||
2338 | { | 2324 | { |
2339 | int i; | 2325 | int i; |
2340 | struct sigmatel_spec *spec = codec->spec; | 2326 | struct sigmatel_spec *spec = codec->spec; |
2341 | 2327 | ||
2342 | if (!spec->pin_configs) | 2328 | if (!pincfgs) |
2343 | return; | 2329 | return; |
2344 | 2330 | ||
2345 | for (i = 0; i < spec->num_pins; i++) | 2331 | for (i = 0; i < spec->num_pins; i++) |
2346 | stac92xx_set_config_reg(codec, spec->pin_nids[i], | 2332 | if (spec->pin_nids[i] && pincfgs[i]) |
2347 | spec->pin_configs[i]); | 2333 | snd_hda_codec_set_pincfg(codec, spec->pin_nids[i], |
2348 | } | 2334 | pincfgs[i]); |
2349 | |||
2350 | static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins) | ||
2351 | { | ||
2352 | struct sigmatel_spec *spec = codec->spec; | ||
2353 | |||
2354 | if (!pins) | ||
2355 | return stac92xx_save_bios_config_regs(codec); | ||
2356 | |||
2357 | kfree(spec->pin_configs); | ||
2358 | spec->pin_configs = kmemdup(pins, | ||
2359 | spec->num_pins * sizeof(*pins), | ||
2360 | GFP_KERNEL); | ||
2361 | if (!spec->pin_configs) | ||
2362 | return -ENOMEM; | ||
2363 | |||
2364 | stac92xx_set_config_regs(codec); | ||
2365 | return 0; | ||
2366 | } | ||
2367 | |||
2368 | static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid, | ||
2369 | unsigned int cfg) | ||
2370 | { | ||
2371 | struct sigmatel_spec *spec = codec->spec; | ||
2372 | int i; | ||
2373 | |||
2374 | for (i = 0; i < spec->num_pins; i++) { | ||
2375 | if (spec->pin_nids[i] == nid) { | ||
2376 | spec->pin_configs[i] = cfg; | ||
2377 | stac92xx_set_config_reg(codec, nid, cfg); | ||
2378 | break; | ||
2379 | } | ||
2380 | } | ||
2381 | } | 2335 | } |
2382 | 2336 | ||
2383 | /* | 2337 | /* |
@@ -2442,6 +2396,14 @@ static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2442 | stream_tag, format, substream); | 2396 | stream_tag, format, substream); |
2443 | } | 2397 | } |
2444 | 2398 | ||
2399 | static int stac92xx_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
2400 | struct hda_codec *codec, | ||
2401 | struct snd_pcm_substream *substream) | ||
2402 | { | ||
2403 | struct sigmatel_spec *spec = codec->spec; | ||
2404 | return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); | ||
2405 | } | ||
2406 | |||
2445 | 2407 | ||
2446 | /* | 2408 | /* |
2447 | * Analog capture callbacks | 2409 | * Analog capture callbacks |
@@ -2486,7 +2448,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = { | |||
2486 | .ops = { | 2448 | .ops = { |
2487 | .open = stac92xx_dig_playback_pcm_open, | 2449 | .open = stac92xx_dig_playback_pcm_open, |
2488 | .close = stac92xx_dig_playback_pcm_close, | 2450 | .close = stac92xx_dig_playback_pcm_close, |
2489 | .prepare = stac92xx_dig_playback_pcm_prepare | 2451 | .prepare = stac92xx_dig_playback_pcm_prepare, |
2452 | .cleanup = stac92xx_dig_playback_pcm_cleanup | ||
2490 | }, | 2453 | }, |
2491 | }; | 2454 | }; |
2492 | 2455 | ||
@@ -2558,7 +2521,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
2558 | codec->num_pcms++; | 2521 | codec->num_pcms++; |
2559 | info++; | 2522 | info++; |
2560 | info->name = "STAC92xx Digital"; | 2523 | info->name = "STAC92xx Digital"; |
2561 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 2524 | info->pcm_type = spec->autocfg.dig_out_type[0]; |
2562 | if (spec->multiout.dig_out_nid) { | 2525 | if (spec->multiout.dig_out_nid) { |
2563 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; | 2526 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; |
2564 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | 2527 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; |
@@ -2574,8 +2537,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
2574 | 2537 | ||
2575 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | 2538 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) |
2576 | { | 2539 | { |
2577 | unsigned int pincap = snd_hda_param_read(codec, nid, | 2540 | unsigned int pincap = snd_hda_query_pin_caps(codec, nid); |
2578 | AC_PAR_PIN_CAP); | ||
2579 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | 2541 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; |
2580 | if (pincap & AC_PINCAP_VREF_100) | 2542 | if (pincap & AC_PINCAP_VREF_100) |
2581 | return AC_PINCTL_VREF_100; | 2543 | return AC_PINCTL_VREF_100; |
@@ -2750,22 +2712,37 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { | |||
2750 | }; | 2712 | }; |
2751 | 2713 | ||
2752 | /* add dynamic controls */ | 2714 | /* add dynamic controls */ |
2753 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | 2715 | static struct snd_kcontrol_new * |
2754 | struct snd_kcontrol_new *ktemp, | 2716 | stac_control_new(struct sigmatel_spec *spec, |
2755 | int idx, const char *name, | 2717 | struct snd_kcontrol_new *ktemp, |
2756 | unsigned long val) | 2718 | const char *name) |
2757 | { | 2719 | { |
2758 | struct snd_kcontrol_new *knew; | 2720 | struct snd_kcontrol_new *knew; |
2759 | 2721 | ||
2760 | snd_array_init(&spec->kctls, sizeof(*knew), 32); | 2722 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2761 | knew = snd_array_new(&spec->kctls); | 2723 | knew = snd_array_new(&spec->kctls); |
2762 | if (!knew) | 2724 | if (!knew) |
2763 | return -ENOMEM; | 2725 | return NULL; |
2764 | *knew = *ktemp; | 2726 | *knew = *ktemp; |
2765 | knew->index = idx; | ||
2766 | knew->name = kstrdup(name, GFP_KERNEL); | 2727 | knew->name = kstrdup(name, GFP_KERNEL); |
2767 | if (!knew->name) | 2728 | if (!knew->name) { |
2729 | /* roolback */ | ||
2730 | memset(knew, 0, sizeof(*knew)); | ||
2731 | spec->kctls.alloced--; | ||
2732 | return NULL; | ||
2733 | } | ||
2734 | return knew; | ||
2735 | } | ||
2736 | |||
2737 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | ||
2738 | struct snd_kcontrol_new *ktemp, | ||
2739 | int idx, const char *name, | ||
2740 | unsigned long val) | ||
2741 | { | ||
2742 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name); | ||
2743 | if (!knew) | ||
2768 | return -ENOMEM; | 2744 | return -ENOMEM; |
2745 | knew->index = idx; | ||
2769 | knew->private_value = val; | 2746 | knew->private_value = val; |
2770 | return 0; | 2747 | return 0; |
2771 | } | 2748 | } |
@@ -2787,6 +2764,29 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, | |||
2787 | return stac92xx_add_control_idx(spec, type, 0, name, val); | 2764 | return stac92xx_add_control_idx(spec, type, 0, name, val); |
2788 | } | 2765 | } |
2789 | 2766 | ||
2767 | static struct snd_kcontrol_new stac_input_src_temp = { | ||
2768 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2769 | .name = "Input Source", | ||
2770 | .info = stac92xx_mux_enum_info, | ||
2771 | .get = stac92xx_mux_enum_get, | ||
2772 | .put = stac92xx_mux_enum_put, | ||
2773 | }; | ||
2774 | |||
2775 | static int stac92xx_add_input_source(struct sigmatel_spec *spec) | ||
2776 | { | ||
2777 | struct snd_kcontrol_new *knew; | ||
2778 | struct hda_input_mux *imux = &spec->private_imux; | ||
2779 | |||
2780 | if (!spec->num_adcs || imux->num_items <= 1) | ||
2781 | return 0; /* no need for input source control */ | ||
2782 | knew = stac_control_new(spec, &stac_input_src_temp, | ||
2783 | stac_input_src_temp.name); | ||
2784 | if (!knew) | ||
2785 | return -ENOMEM; | ||
2786 | knew->count = spec->num_adcs; | ||
2787 | return 0; | ||
2788 | } | ||
2789 | |||
2790 | /* check whether the line-input can be used as line-out */ | 2790 | /* check whether the line-input can be used as line-out */ |
2791 | static hda_nid_t check_line_out_switch(struct hda_codec *codec) | 2791 | static hda_nid_t check_line_out_switch(struct hda_codec *codec) |
2792 | { | 2792 | { |
@@ -2798,7 +2798,7 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) | |||
2798 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2798 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2799 | return 0; | 2799 | return 0; |
2800 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 2800 | nid = cfg->input_pins[AUTO_PIN_LINE]; |
2801 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 2801 | pincap = snd_hda_query_pin_caps(codec, nid); |
2802 | if (pincap & AC_PINCAP_OUT) | 2802 | if (pincap & AC_PINCAP_OUT) |
2803 | return nid; | 2803 | return nid; |
2804 | return 0; | 2804 | return 0; |
@@ -2817,12 +2817,11 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | |||
2817 | mic_pin = AUTO_PIN_MIC; | 2817 | mic_pin = AUTO_PIN_MIC; |
2818 | for (;;) { | 2818 | for (;;) { |
2819 | hda_nid_t nid = cfg->input_pins[mic_pin]; | 2819 | hda_nid_t nid = cfg->input_pins[mic_pin]; |
2820 | def_conf = snd_hda_codec_read(codec, nid, 0, | 2820 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
2821 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
2822 | /* some laptops have an internal analog microphone | 2821 | /* some laptops have an internal analog microphone |
2823 | * which can't be used as a output */ | 2822 | * which can't be used as a output */ |
2824 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | 2823 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { |
2825 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 2824 | pincap = snd_hda_query_pin_caps(codec, nid); |
2826 | if (pincap & AC_PINCAP_OUT) | 2825 | if (pincap & AC_PINCAP_OUT) |
2827 | return nid; | 2826 | return nid; |
2828 | } | 2827 | } |
@@ -2870,8 +2869,7 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | |||
2870 | conn_len = snd_hda_get_connections(codec, nid, conn, | 2869 | conn_len = snd_hda_get_connections(codec, nid, conn, |
2871 | HDA_MAX_CONNECTIONS); | 2870 | HDA_MAX_CONNECTIONS); |
2872 | for (j = 0; j < conn_len; j++) { | 2871 | for (j = 0; j < conn_len; j++) { |
2873 | wcaps = snd_hda_param_read(codec, conn[j], | 2872 | wcaps = get_wcaps(codec, conn[j]); |
2874 | AC_PAR_AUDIO_WIDGET_CAP); | ||
2875 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 2873 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
2876 | /* we check only analog outputs */ | 2874 | /* we check only analog outputs */ |
2877 | if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) | 2875 | if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) |
@@ -2886,6 +2884,16 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | |||
2886 | return conn[j]; | 2884 | return conn[j]; |
2887 | } | 2885 | } |
2888 | } | 2886 | } |
2887 | /* if all DACs are already assigned, connect to the primary DAC */ | ||
2888 | if (conn_len > 1) { | ||
2889 | for (j = 0; j < conn_len; j++) { | ||
2890 | if (conn[j] == spec->multiout.dac_nids[0]) { | ||
2891 | snd_hda_codec_write_cache(codec, nid, 0, | ||
2892 | AC_VERB_SET_CONNECT_SEL, j); | ||
2893 | break; | ||
2894 | } | ||
2895 | } | ||
2896 | } | ||
2889 | return 0; | 2897 | return 0; |
2890 | } | 2898 | } |
2891 | 2899 | ||
@@ -2926,6 +2934,26 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
2926 | add_spec_dacs(spec, dac); | 2934 | add_spec_dacs(spec, dac); |
2927 | } | 2935 | } |
2928 | 2936 | ||
2937 | for (i = 0; i < cfg->hp_outs; i++) { | ||
2938 | nid = cfg->hp_pins[i]; | ||
2939 | dac = get_unassigned_dac(codec, nid); | ||
2940 | if (dac) { | ||
2941 | if (!spec->multiout.hp_nid) | ||
2942 | spec->multiout.hp_nid = dac; | ||
2943 | else | ||
2944 | add_spec_extra_dacs(spec, dac); | ||
2945 | } | ||
2946 | spec->hp_dacs[i] = dac; | ||
2947 | } | ||
2948 | |||
2949 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
2950 | nid = cfg->speaker_pins[i]; | ||
2951 | dac = get_unassigned_dac(codec, nid); | ||
2952 | if (dac) | ||
2953 | add_spec_extra_dacs(spec, dac); | ||
2954 | spec->speaker_dacs[i] = dac; | ||
2955 | } | ||
2956 | |||
2929 | /* add line-in as output */ | 2957 | /* add line-in as output */ |
2930 | nid = check_line_out_switch(codec); | 2958 | nid = check_line_out_switch(codec); |
2931 | if (nid) { | 2959 | if (nid) { |
@@ -2953,26 +2981,6 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
2953 | } | 2981 | } |
2954 | } | 2982 | } |
2955 | 2983 | ||
2956 | for (i = 0; i < cfg->hp_outs; i++) { | ||
2957 | nid = cfg->hp_pins[i]; | ||
2958 | dac = get_unassigned_dac(codec, nid); | ||
2959 | if (dac) { | ||
2960 | if (!spec->multiout.hp_nid) | ||
2961 | spec->multiout.hp_nid = dac; | ||
2962 | else | ||
2963 | add_spec_extra_dacs(spec, dac); | ||
2964 | } | ||
2965 | spec->hp_dacs[i] = dac; | ||
2966 | } | ||
2967 | |||
2968 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
2969 | nid = cfg->speaker_pins[i]; | ||
2970 | dac = get_unassigned_dac(codec, nid); | ||
2971 | if (dac) | ||
2972 | add_spec_extra_dacs(spec, dac); | ||
2973 | spec->speaker_dacs[i] = dac; | ||
2974 | } | ||
2975 | |||
2976 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 2984 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2977 | spec->multiout.num_dacs, | 2985 | spec->multiout.num_dacs, |
2978 | spec->multiout.dac_nids[0], | 2986 | spec->multiout.dac_nids[0], |
@@ -2985,24 +2993,47 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
2985 | } | 2993 | } |
2986 | 2994 | ||
2987 | /* create volume control/switch for the given prefx type */ | 2995 | /* create volume control/switch for the given prefx type */ |
2988 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | 2996 | static int create_controls_idx(struct hda_codec *codec, const char *pfx, |
2997 | int idx, hda_nid_t nid, int chs) | ||
2989 | { | 2998 | { |
2999 | struct sigmatel_spec *spec = codec->spec; | ||
2990 | char name[32]; | 3000 | char name[32]; |
2991 | int err; | 3001 | int err; |
2992 | 3002 | ||
3003 | if (!spec->check_volume_offset) { | ||
3004 | unsigned int caps, step, nums, db_scale; | ||
3005 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); | ||
3006 | step = (caps & AC_AMPCAP_STEP_SIZE) >> | ||
3007 | AC_AMPCAP_STEP_SIZE_SHIFT; | ||
3008 | step = (step + 1) * 25; /* in .01dB unit */ | ||
3009 | nums = (caps & AC_AMPCAP_NUM_STEPS) >> | ||
3010 | AC_AMPCAP_NUM_STEPS_SHIFT; | ||
3011 | db_scale = nums * step; | ||
3012 | /* if dB scale is over -64dB, and finer enough, | ||
3013 | * let's reduce it to half | ||
3014 | */ | ||
3015 | if (db_scale > 6400 && nums >= 0x1f) | ||
3016 | spec->volume_offset = nums / 2; | ||
3017 | spec->check_volume_offset = 1; | ||
3018 | } | ||
3019 | |||
2993 | sprintf(name, "%s Playback Volume", pfx); | 3020 | sprintf(name, "%s Playback Volume", pfx); |
2994 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | 3021 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, idx, name, |
2995 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 3022 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT, |
3023 | spec->volume_offset)); | ||
2996 | if (err < 0) | 3024 | if (err < 0) |
2997 | return err; | 3025 | return err; |
2998 | sprintf(name, "%s Playback Switch", pfx); | 3026 | sprintf(name, "%s Playback Switch", pfx); |
2999 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | 3027 | err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_MUTE, idx, name, |
3000 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 3028 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
3001 | if (err < 0) | 3029 | if (err < 0) |
3002 | return err; | 3030 | return err; |
3003 | return 0; | 3031 | return 0; |
3004 | } | 3032 | } |
3005 | 3033 | ||
3034 | #define create_controls(codec, pfx, nid, chs) \ | ||
3035 | create_controls_idx(codec, pfx, 0, nid, chs) | ||
3036 | |||
3006 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | 3037 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
3007 | { | 3038 | { |
3008 | if (spec->multiout.num_dacs > 4) { | 3039 | if (spec->multiout.num_dacs > 4) { |
@@ -3028,40 +3059,32 @@ static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | |||
3028 | return 1; | 3059 | return 1; |
3029 | } | 3060 | } |
3030 | 3061 | ||
3031 | static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid) | 3062 | /* Create output controls |
3032 | { | 3063 | * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT) |
3033 | int i; | 3064 | */ |
3034 | 3065 | static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, | |
3035 | if (spec->autocfg.line_outs != 1) | 3066 | const hda_nid_t *pins, |
3036 | return 0; | 3067 | const hda_nid_t *dac_nids, |
3037 | if (spec->multiout.hp_nid == nid) | 3068 | int type) |
3038 | return 0; | ||
3039 | for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) | ||
3040 | if (spec->multiout.extra_out_nid[i] == nid) | ||
3041 | return 0; | ||
3042 | return 1; | ||
3043 | } | ||
3044 | |||
3045 | /* add playback controls from the parsed DAC table */ | ||
3046 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
3047 | const struct auto_pin_cfg *cfg) | ||
3048 | { | 3069 | { |
3049 | struct sigmatel_spec *spec = codec->spec; | 3070 | struct sigmatel_spec *spec = codec->spec; |
3050 | static const char *chname[4] = { | 3071 | static const char *chname[4] = { |
3051 | "Front", "Surround", NULL /*CLFE*/, "Side" | 3072 | "Front", "Surround", NULL /*CLFE*/, "Side" |
3052 | }; | 3073 | }; |
3053 | hda_nid_t nid = 0; | 3074 | hda_nid_t nid; |
3054 | int i, err; | 3075 | int i, err; |
3055 | unsigned int wid_caps; | 3076 | unsigned int wid_caps; |
3056 | 3077 | ||
3057 | for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) { | 3078 | for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) { |
3058 | nid = spec->multiout.dac_nids[i]; | 3079 | nid = dac_nids[i]; |
3059 | if (i == 2) { | 3080 | if (!nid) |
3081 | continue; | ||
3082 | if (type != AUTO_PIN_HP_OUT && i == 2) { | ||
3060 | /* Center/LFE */ | 3083 | /* Center/LFE */ |
3061 | err = create_controls(spec, "Center", nid, 1); | 3084 | err = create_controls(codec, "Center", nid, 1); |
3062 | if (err < 0) | 3085 | if (err < 0) |
3063 | return err; | 3086 | return err; |
3064 | err = create_controls(spec, "LFE", nid, 2); | 3087 | err = create_controls(codec, "LFE", nid, 2); |
3065 | if (err < 0) | 3088 | if (err < 0) |
3066 | return err; | 3089 | return err; |
3067 | 3090 | ||
@@ -3077,23 +3100,47 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3077 | } | 3100 | } |
3078 | 3101 | ||
3079 | } else { | 3102 | } else { |
3080 | const char *name = chname[i]; | 3103 | const char *name; |
3081 | /* if it's a single DAC, assign a better name */ | 3104 | int idx; |
3082 | if (!i && is_unique_dac(spec, nid)) { | 3105 | switch (type) { |
3083 | switch (cfg->line_out_type) { | 3106 | case AUTO_PIN_HP_OUT: |
3084 | case AUTO_PIN_HP_OUT: | 3107 | name = "Headphone"; |
3085 | name = "Headphone"; | 3108 | idx = i; |
3086 | break; | 3109 | break; |
3087 | case AUTO_PIN_SPEAKER_OUT: | 3110 | case AUTO_PIN_SPEAKER_OUT: |
3088 | name = "Speaker"; | 3111 | name = "Speaker"; |
3089 | break; | 3112 | idx = i; |
3090 | } | 3113 | break; |
3114 | default: | ||
3115 | name = chname[i]; | ||
3116 | idx = 0; | ||
3117 | break; | ||
3091 | } | 3118 | } |
3092 | err = create_controls(spec, name, nid, 3); | 3119 | err = create_controls_idx(codec, name, idx, nid, 3); |
3093 | if (err < 0) | 3120 | if (err < 0) |
3094 | return err; | 3121 | return err; |
3122 | if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { | ||
3123 | wid_caps = get_wcaps(codec, pins[i]); | ||
3124 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
3125 | spec->hp_detect = 1; | ||
3126 | } | ||
3095 | } | 3127 | } |
3096 | } | 3128 | } |
3129 | return 0; | ||
3130 | } | ||
3131 | |||
3132 | /* add playback controls from the parsed DAC table */ | ||
3133 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
3134 | const struct auto_pin_cfg *cfg) | ||
3135 | { | ||
3136 | struct sigmatel_spec *spec = codec->spec; | ||
3137 | int err; | ||
3138 | |||
3139 | err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins, | ||
3140 | spec->multiout.dac_nids, | ||
3141 | cfg->line_out_type); | ||
3142 | if (err < 0) | ||
3143 | return err; | ||
3097 | 3144 | ||
3098 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | 3145 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { |
3099 | err = stac92xx_add_control(spec, | 3146 | err = stac92xx_add_control(spec, |
@@ -3128,40 +3175,18 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
3128 | struct auto_pin_cfg *cfg) | 3175 | struct auto_pin_cfg *cfg) |
3129 | { | 3176 | { |
3130 | struct sigmatel_spec *spec = codec->spec; | 3177 | struct sigmatel_spec *spec = codec->spec; |
3131 | hda_nid_t nid; | 3178 | int err; |
3132 | int i, err, nums; | 3179 | |
3180 | err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins, | ||
3181 | spec->hp_dacs, AUTO_PIN_HP_OUT); | ||
3182 | if (err < 0) | ||
3183 | return err; | ||
3184 | |||
3185 | err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, | ||
3186 | spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT); | ||
3187 | if (err < 0) | ||
3188 | return err; | ||
3133 | 3189 | ||
3134 | nums = 0; | ||
3135 | for (i = 0; i < cfg->hp_outs; i++) { | ||
3136 | static const char *pfxs[] = { | ||
3137 | "Headphone", "Headphone2", "Headphone3", | ||
3138 | }; | ||
3139 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | ||
3140 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
3141 | spec->hp_detect = 1; | ||
3142 | if (nums >= ARRAY_SIZE(pfxs)) | ||
3143 | continue; | ||
3144 | nid = spec->hp_dacs[i]; | ||
3145 | if (!nid) | ||
3146 | continue; | ||
3147 | err = create_controls(spec, pfxs[nums++], nid, 3); | ||
3148 | if (err < 0) | ||
3149 | return err; | ||
3150 | } | ||
3151 | nums = 0; | ||
3152 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
3153 | static const char *pfxs[] = { | ||
3154 | "Speaker", "External Speaker", "Speaker2", | ||
3155 | }; | ||
3156 | if (nums >= ARRAY_SIZE(pfxs)) | ||
3157 | continue; | ||
3158 | nid = spec->speaker_dacs[i]; | ||
3159 | if (!nid) | ||
3160 | continue; | ||
3161 | err = create_controls(spec, pfxs[nums++], nid, 3); | ||
3162 | if (err < 0) | ||
3163 | return err; | ||
3164 | } | ||
3165 | return 0; | 3190 | return 0; |
3166 | } | 3191 | } |
3167 | 3192 | ||
@@ -3370,11 +3395,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3370 | unsigned int wcaps; | 3395 | unsigned int wcaps; |
3371 | unsigned int def_conf; | 3396 | unsigned int def_conf; |
3372 | 3397 | ||
3373 | def_conf = snd_hda_codec_read(codec, | 3398 | def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); |
3374 | spec->dmic_nids[i], | ||
3375 | 0, | ||
3376 | AC_VERB_GET_CONFIG_DEFAULT, | ||
3377 | 0); | ||
3378 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 3399 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
3379 | continue; | 3400 | continue; |
3380 | 3401 | ||
@@ -3498,6 +3519,7 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | |||
3498 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 3519 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
3499 | { | 3520 | { |
3500 | struct sigmatel_spec *spec = codec->spec; | 3521 | struct sigmatel_spec *spec = codec->spec; |
3522 | int hp_swap = 0; | ||
3501 | int err; | 3523 | int err; |
3502 | 3524 | ||
3503 | if ((err = snd_hda_parse_pin_def_config(codec, | 3525 | if ((err = snd_hda_parse_pin_def_config(codec, |
@@ -3525,6 +3547,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3525 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | 3547 | spec->autocfg.line_outs = spec->autocfg.hp_outs; |
3526 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | 3548 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; |
3527 | spec->autocfg.hp_outs = 0; | 3549 | spec->autocfg.hp_outs = 0; |
3550 | hp_swap = 1; | ||
3528 | } | 3551 | } |
3529 | if (spec->autocfg.mono_out_pin) { | 3552 | if (spec->autocfg.mono_out_pin) { |
3530 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | 3553 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & |
@@ -3618,12 +3641,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3618 | #endif | 3641 | #endif |
3619 | 3642 | ||
3620 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 3643 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); |
3621 | |||
3622 | if (err < 0) | 3644 | if (err < 0) |
3623 | return err; | 3645 | return err; |
3624 | 3646 | ||
3625 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | 3647 | /* All output parsing done, now restore the swapped hp pins */ |
3648 | if (hp_swap) { | ||
3649 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | ||
3650 | sizeof(spec->autocfg.hp_pins)); | ||
3651 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | ||
3652 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | ||
3653 | spec->autocfg.line_outs = 0; | ||
3654 | } | ||
3626 | 3655 | ||
3656 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
3627 | if (err < 0) | 3657 | if (err < 0) |
3628 | return err; | 3658 | return err; |
3629 | 3659 | ||
@@ -3652,11 +3682,15 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3652 | return err; | 3682 | return err; |
3653 | } | 3683 | } |
3654 | 3684 | ||
3685 | err = stac92xx_add_input_source(spec); | ||
3686 | if (err < 0) | ||
3687 | return err; | ||
3688 | |||
3655 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3689 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
3656 | if (spec->multiout.max_channels > 2) | 3690 | if (spec->multiout.max_channels > 2) |
3657 | spec->surr_switch = 1; | 3691 | spec->surr_switch = 1; |
3658 | 3692 | ||
3659 | if (spec->autocfg.dig_out_pin) | 3693 | if (spec->autocfg.dig_outs) |
3660 | spec->multiout.dig_out_nid = dig_out; | 3694 | spec->multiout.dig_out_nid = dig_out; |
3661 | if (dig_in && spec->autocfg.dig_in_pin) | 3695 | if (dig_in && spec->autocfg.dig_in_pin) |
3662 | spec->dig_in_nid = dig_in; | 3696 | spec->dig_in_nid = dig_in; |
@@ -3719,9 +3753,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | |||
3719 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { | 3753 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { |
3720 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; | 3754 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; |
3721 | unsigned int defcfg; | 3755 | unsigned int defcfg; |
3722 | defcfg = snd_hda_codec_read(codec, pin, 0, | 3756 | defcfg = snd_hda_codec_get_pincfg(codec, pin); |
3723 | AC_VERB_GET_CONFIG_DEFAULT, | ||
3724 | 0x00); | ||
3725 | if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { | 3757 | if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { |
3726 | unsigned int wcaps = get_wcaps(codec, pin); | 3758 | unsigned int wcaps = get_wcaps(codec, pin); |
3727 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | 3759 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); |
@@ -3734,7 +3766,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | |||
3734 | } | 3766 | } |
3735 | 3767 | ||
3736 | if (lfe_pin) { | 3768 | if (lfe_pin) { |
3737 | err = create_controls(spec, "LFE", lfe_pin, 1); | 3769 | err = create_controls(codec, "LFE", lfe_pin, 1); |
3738 | if (err < 0) | 3770 | if (err < 0) |
3739 | return err; | 3771 | return err; |
3740 | } | 3772 | } |
@@ -3765,7 +3797,11 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3765 | return err; | 3797 | return err; |
3766 | } | 3798 | } |
3767 | 3799 | ||
3768 | if (spec->autocfg.dig_out_pin) | 3800 | err = stac92xx_add_input_source(spec); |
3801 | if (err < 0) | ||
3802 | return err; | ||
3803 | |||
3804 | if (spec->autocfg.dig_outs) | ||
3769 | spec->multiout.dig_out_nid = 0x05; | 3805 | spec->multiout.dig_out_nid = 0x05; |
3770 | if (spec->autocfg.dig_in_pin) | 3806 | if (spec->autocfg.dig_in_pin) |
3771 | spec->dig_in_nid = 0x04; | 3807 | spec->dig_in_nid = 0x04; |
@@ -3821,8 +3857,7 @@ static int stac92xx_add_jack(struct hda_codec *codec, | |||
3821 | #ifdef CONFIG_SND_JACK | 3857 | #ifdef CONFIG_SND_JACK |
3822 | struct sigmatel_spec *spec = codec->spec; | 3858 | struct sigmatel_spec *spec = codec->spec; |
3823 | struct sigmatel_jack *jack; | 3859 | struct sigmatel_jack *jack; |
3824 | int def_conf = snd_hda_codec_read(codec, nid, | 3860 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
3825 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3826 | int connectivity = get_defcfg_connect(def_conf); | 3861 | int connectivity = get_defcfg_connect(def_conf); |
3827 | char name[32]; | 3862 | char name[32]; |
3828 | 3863 | ||
@@ -3937,6 +3972,36 @@ static void stac92xx_power_down(struct hda_codec *codec) | |||
3937 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | 3972 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
3938 | int enable); | 3973 | int enable); |
3939 | 3974 | ||
3975 | /* override some hints from the hwdep entry */ | ||
3976 | static void stac_store_hints(struct hda_codec *codec) | ||
3977 | { | ||
3978 | struct sigmatel_spec *spec = codec->spec; | ||
3979 | const char *p; | ||
3980 | int val; | ||
3981 | |||
3982 | val = snd_hda_get_bool_hint(codec, "hp_detect"); | ||
3983 | if (val >= 0) | ||
3984 | spec->hp_detect = val; | ||
3985 | p = snd_hda_get_hint(codec, "gpio_mask"); | ||
3986 | if (p) { | ||
3987 | spec->gpio_mask = simple_strtoul(p, NULL, 0); | ||
3988 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | ||
3989 | spec->gpio_mask; | ||
3990 | } | ||
3991 | p = snd_hda_get_hint(codec, "gpio_dir"); | ||
3992 | if (p) | ||
3993 | spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
3994 | p = snd_hda_get_hint(codec, "gpio_data"); | ||
3995 | if (p) | ||
3996 | spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
3997 | p = snd_hda_get_hint(codec, "eapd_mask"); | ||
3998 | if (p) | ||
3999 | spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
4000 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | ||
4001 | if (val >= 0) | ||
4002 | spec->eapd_switch = val; | ||
4003 | } | ||
4004 | |||
3940 | static int stac92xx_init(struct hda_codec *codec) | 4005 | static int stac92xx_init(struct hda_codec *codec) |
3941 | { | 4006 | { |
3942 | struct sigmatel_spec *spec = codec->spec; | 4007 | struct sigmatel_spec *spec = codec->spec; |
@@ -3953,6 +4018,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3953 | spec->adc_nids[i], 0, | 4018 | spec->adc_nids[i], 0, |
3954 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 4019 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
3955 | 4020 | ||
4021 | /* override some hints */ | ||
4022 | stac_store_hints(codec); | ||
4023 | |||
3956 | /* set up GPIO */ | 4024 | /* set up GPIO */ |
3957 | gpio = spec->gpio_data; | 4025 | gpio = spec->gpio_data; |
3958 | /* turn on EAPD statically when spec->eapd_switch isn't set. | 4026 | /* turn on EAPD statically when spec->eapd_switch isn't set. |
@@ -4002,8 +4070,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4002 | pinctl); | 4070 | pinctl); |
4003 | } | 4071 | } |
4004 | } | 4072 | } |
4005 | conf = snd_hda_codec_read(codec, nid, 0, | 4073 | conf = snd_hda_codec_get_pincfg(codec, nid); |
4006 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
4007 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | 4074 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { |
4008 | enable_pin_detect(codec, nid, | 4075 | enable_pin_detect(codec, nid, |
4009 | STAC_INSERT_EVENT); | 4076 | STAC_INSERT_EVENT); |
@@ -4015,8 +4082,8 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4015 | for (i = 0; i < spec->num_dmics; i++) | 4082 | for (i = 0; i < spec->num_dmics; i++) |
4016 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 4083 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], |
4017 | AC_PINCTL_IN_EN); | 4084 | AC_PINCTL_IN_EN); |
4018 | if (cfg->dig_out_pin) | 4085 | if (cfg->dig_out_pins[0]) |
4019 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | 4086 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pins[0], |
4020 | AC_PINCTL_OUT_EN); | 4087 | AC_PINCTL_OUT_EN); |
4021 | if (cfg->dig_in_pin) | 4088 | if (cfg->dig_in_pin) |
4022 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | 4089 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, |
@@ -4044,8 +4111,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4044 | stac_toggle_power_map(codec, nid, 1); | 4111 | stac_toggle_power_map(codec, nid, 1); |
4045 | continue; | 4112 | continue; |
4046 | } | 4113 | } |
4047 | def_conf = snd_hda_codec_read(codec, nid, 0, | 4114 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
4048 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
4049 | def_conf = get_defcfg_connect(def_conf); | 4115 | def_conf = get_defcfg_connect(def_conf); |
4050 | /* skip any ports that don't have jacks since presence | 4116 | /* skip any ports that don't have jacks since presence |
4051 | * detection is useless */ | 4117 | * detection is useless */ |
@@ -4099,7 +4165,6 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4099 | if (! spec) | 4165 | if (! spec) |
4100 | return; | 4166 | return; |
4101 | 4167 | ||
4102 | kfree(spec->pin_configs); | ||
4103 | stac92xx_free_jacks(codec); | 4168 | stac92xx_free_jacks(codec); |
4104 | snd_array_free(&spec->events); | 4169 | snd_array_free(&spec->events); |
4105 | 4170 | ||
@@ -4110,7 +4175,9 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4110 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | 4175 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, |
4111 | unsigned int flag) | 4176 | unsigned int flag) |
4112 | { | 4177 | { |
4113 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 4178 | unsigned int old_ctl, pin_ctl; |
4179 | |||
4180 | pin_ctl = snd_hda_codec_read(codec, nid, | ||
4114 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 4181 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
4115 | 4182 | ||
4116 | if (pin_ctl & AC_PINCTL_IN_EN) { | 4183 | if (pin_ctl & AC_PINCTL_IN_EN) { |
@@ -4124,14 +4191,17 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
4124 | return; | 4191 | return; |
4125 | } | 4192 | } |
4126 | 4193 | ||
4194 | old_ctl = pin_ctl; | ||
4127 | /* if setting pin direction bits, clear the current | 4195 | /* if setting pin direction bits, clear the current |
4128 | direction bits first */ | 4196 | direction bits first */ |
4129 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | 4197 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) |
4130 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 4198 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
4131 | 4199 | ||
4132 | snd_hda_codec_write_cache(codec, nid, 0, | 4200 | pin_ctl |= flag; |
4133 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 4201 | if (old_ctl != pin_ctl) |
4134 | pin_ctl | flag); | 4202 | snd_hda_codec_write_cache(codec, nid, 0, |
4203 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
4204 | pin_ctl); | ||
4135 | } | 4205 | } |
4136 | 4206 | ||
4137 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | 4207 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, |
@@ -4139,9 +4209,10 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
4139 | { | 4209 | { |
4140 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 4210 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
4141 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 4211 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
4142 | snd_hda_codec_write_cache(codec, nid, 0, | 4212 | if (pin_ctl & flag) |
4143 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 4213 | snd_hda_codec_write_cache(codec, nid, 0, |
4144 | pin_ctl & ~flag); | 4214 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
4215 | pin_ctl & ~flag); | ||
4145 | } | 4216 | } |
4146 | 4217 | ||
4147 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) | 4218 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
@@ -4404,7 +4475,6 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4404 | { | 4475 | { |
4405 | struct sigmatel_spec *spec = codec->spec; | 4476 | struct sigmatel_spec *spec = codec->spec; |
4406 | 4477 | ||
4407 | stac92xx_set_config_regs(codec); | ||
4408 | stac92xx_init(codec); | 4478 | stac92xx_init(codec); |
4409 | snd_hda_codec_resume_amp(codec); | 4479 | snd_hda_codec_resume_amp(codec); |
4410 | snd_hda_codec_resume_cache(codec); | 4480 | snd_hda_codec_resume_cache(codec); |
@@ -4415,6 +4485,37 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4415 | return 0; | 4485 | return 0; |
4416 | } | 4486 | } |
4417 | 4487 | ||
4488 | |||
4489 | /* | ||
4490 | * using power check for controlling mute led of HP HDX notebooks | ||
4491 | * check for mute state only on Speakers (nid = 0x10) | ||
4492 | * | ||
4493 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise | ||
4494 | * the LED is NOT working properly ! | ||
4495 | */ | ||
4496 | |||
4497 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4498 | static int stac92xx_hp_hdx_check_power_status(struct hda_codec *codec, | ||
4499 | hda_nid_t nid) | ||
4500 | { | ||
4501 | struct sigmatel_spec *spec = codec->spec; | ||
4502 | |||
4503 | if (nid == 0x10) { | ||
4504 | if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
4505 | HDA_AMP_MUTE) | ||
4506 | spec->gpio_data &= ~0x08; /* orange */ | ||
4507 | else | ||
4508 | spec->gpio_data |= 0x08; /* white */ | ||
4509 | |||
4510 | stac_gpio_set(codec, spec->gpio_mask, | ||
4511 | spec->gpio_dir, | ||
4512 | spec->gpio_data); | ||
4513 | } | ||
4514 | |||
4515 | return 0; | ||
4516 | } | ||
4517 | #endif | ||
4518 | |||
4418 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | 4519 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) |
4419 | { | 4520 | { |
4420 | struct sigmatel_spec *spec = codec->spec; | 4521 | struct sigmatel_spec *spec = codec->spec; |
@@ -4453,16 +4554,11 @@ static int patch_stac9200(struct hda_codec *codec) | |||
4453 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, | 4554 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, |
4454 | stac9200_models, | 4555 | stac9200_models, |
4455 | stac9200_cfg_tbl); | 4556 | stac9200_cfg_tbl); |
4456 | if (spec->board_config < 0) { | 4557 | if (spec->board_config < 0) |
4457 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 4558 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); |
4458 | err = stac92xx_save_bios_config_regs(codec); | 4559 | else |
4459 | } else | 4560 | stac92xx_set_config_regs(codec, |
4460 | err = stac_save_pin_cfgs(codec, | ||
4461 | stac9200_brd_tbl[spec->board_config]); | 4561 | stac9200_brd_tbl[spec->board_config]); |
4462 | if (err < 0) { | ||
4463 | stac92xx_free(codec); | ||
4464 | return err; | ||
4465 | } | ||
4466 | 4562 | ||
4467 | spec->multiout.max_channels = 2; | 4563 | spec->multiout.max_channels = 2; |
4468 | spec->multiout.num_dacs = 1; | 4564 | spec->multiout.num_dacs = 1; |
@@ -4530,17 +4626,12 @@ static int patch_stac925x(struct hda_codec *codec) | |||
4530 | stac925x_models, | 4626 | stac925x_models, |
4531 | stac925x_cfg_tbl); | 4627 | stac925x_cfg_tbl); |
4532 | again: | 4628 | again: |
4533 | if (spec->board_config < 0) { | 4629 | if (spec->board_config < 0) |
4534 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," | 4630 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," |
4535 | "using BIOS defaults\n"); | 4631 | "using BIOS defaults\n"); |
4536 | err = stac92xx_save_bios_config_regs(codec); | 4632 | else |
4537 | } else | 4633 | stac92xx_set_config_regs(codec, |
4538 | err = stac_save_pin_cfgs(codec, | ||
4539 | stac925x_brd_tbl[spec->board_config]); | 4634 | stac925x_brd_tbl[spec->board_config]); |
4540 | if (err < 0) { | ||
4541 | stac92xx_free(codec); | ||
4542 | return err; | ||
4543 | } | ||
4544 | 4635 | ||
4545 | spec->multiout.max_channels = 2; | 4636 | spec->multiout.max_channels = 2; |
4546 | spec->multiout.num_dacs = 1; | 4637 | spec->multiout.num_dacs = 1; |
@@ -4618,17 +4709,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
4618 | stac92hd73xx_models, | 4709 | stac92hd73xx_models, |
4619 | stac92hd73xx_cfg_tbl); | 4710 | stac92hd73xx_cfg_tbl); |
4620 | again: | 4711 | again: |
4621 | if (spec->board_config < 0) { | 4712 | if (spec->board_config < 0) |
4622 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4713 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4623 | " STAC92HD73XX, using BIOS defaults\n"); | 4714 | " STAC92HD73XX, using BIOS defaults\n"); |
4624 | err = stac92xx_save_bios_config_regs(codec); | 4715 | else |
4625 | } else | 4716 | stac92xx_set_config_regs(codec, |
4626 | err = stac_save_pin_cfgs(codec, | ||
4627 | stac92hd73xx_brd_tbl[spec->board_config]); | 4717 | stac92hd73xx_brd_tbl[spec->board_config]); |
4628 | if (err < 0) { | ||
4629 | stac92xx_free(codec); | ||
4630 | return err; | ||
4631 | } | ||
4632 | 4718 | ||
4633 | num_dacs = snd_hda_get_connections(codec, 0x0a, | 4719 | num_dacs = snd_hda_get_connections(codec, 0x0a, |
4634 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | 4720 | conn, STAC92HD73_DAC_COUNT + 2) - 1; |
@@ -4642,14 +4728,18 @@ again: | |||
4642 | case 0x3: /* 6 Channel */ | 4728 | case 0x3: /* 6 Channel */ |
4643 | spec->mixer = stac92hd73xx_6ch_mixer; | 4729 | spec->mixer = stac92hd73xx_6ch_mixer; |
4644 | spec->init = stac92hd73xx_6ch_core_init; | 4730 | spec->init = stac92hd73xx_6ch_core_init; |
4731 | spec->aloopback_ctl = stac92hd73xx_6ch_loopback; | ||
4645 | break; | 4732 | break; |
4646 | case 0x4: /* 8 Channel */ | 4733 | case 0x4: /* 8 Channel */ |
4647 | spec->mixer = stac92hd73xx_8ch_mixer; | 4734 | spec->mixer = stac92hd73xx_8ch_mixer; |
4648 | spec->init = stac92hd73xx_8ch_core_init; | 4735 | spec->init = stac92hd73xx_8ch_core_init; |
4736 | spec->aloopback_ctl = stac92hd73xx_8ch_loopback; | ||
4649 | break; | 4737 | break; |
4650 | case 0x5: /* 10 Channel */ | 4738 | case 0x5: /* 10 Channel */ |
4651 | spec->mixer = stac92hd73xx_10ch_mixer; | 4739 | spec->mixer = stac92hd73xx_10ch_mixer; |
4652 | spec->init = stac92hd73xx_10ch_core_init; | 4740 | spec->init = stac92hd73xx_10ch_core_init; |
4741 | spec->aloopback_ctl = stac92hd73xx_10ch_loopback; | ||
4742 | break; | ||
4653 | } | 4743 | } |
4654 | spec->multiout.dac_nids = spec->dac_nids; | 4744 | spec->multiout.dac_nids = spec->dac_nids; |
4655 | 4745 | ||
@@ -4688,18 +4778,18 @@ again: | |||
4688 | spec->init = dell_m6_core_init; | 4778 | spec->init = dell_m6_core_init; |
4689 | switch (spec->board_config) { | 4779 | switch (spec->board_config) { |
4690 | case STAC_DELL_M6_AMIC: /* Analog Mics */ | 4780 | case STAC_DELL_M6_AMIC: /* Analog Mics */ |
4691 | stac92xx_set_config_reg(codec, 0x0b, 0x90A70170); | 4781 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
4692 | spec->num_dmics = 0; | 4782 | spec->num_dmics = 0; |
4693 | spec->private_dimux.num_items = 1; | 4783 | spec->private_dimux.num_items = 1; |
4694 | break; | 4784 | break; |
4695 | case STAC_DELL_M6_DMIC: /* Digital Mics */ | 4785 | case STAC_DELL_M6_DMIC: /* Digital Mics */ |
4696 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 4786 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
4697 | spec->num_dmics = 1; | 4787 | spec->num_dmics = 1; |
4698 | spec->private_dimux.num_items = 2; | 4788 | spec->private_dimux.num_items = 2; |
4699 | break; | 4789 | break; |
4700 | case STAC_DELL_M6_BOTH: /* Both */ | 4790 | case STAC_DELL_M6_BOTH: /* Both */ |
4701 | stac92xx_set_config_reg(codec, 0x0b, 0x90A70170); | 4791 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
4702 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 4792 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
4703 | spec->num_dmics = 1; | 4793 | spec->num_dmics = 1; |
4704 | spec->private_dimux.num_items = 2; | 4794 | spec->private_dimux.num_items = 2; |
4705 | break; | 4795 | break; |
@@ -4762,6 +4852,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4762 | hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; | 4852 | hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; |
4763 | int err; | 4853 | int err; |
4764 | int num_dacs; | 4854 | int num_dacs; |
4855 | hda_nid_t nid; | ||
4765 | 4856 | ||
4766 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4857 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4767 | if (spec == NULL) | 4858 | if (spec == NULL) |
@@ -4780,15 +4871,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4780 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 4871 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
4781 | spec->multiout.dac_nids = spec->dac_nids; | 4872 | spec->multiout.dac_nids = spec->dac_nids; |
4782 | 4873 | ||
4783 | |||
4784 | /* set port 0xe to select the last DAC | ||
4785 | */ | ||
4786 | num_dacs = snd_hda_get_connections(codec, 0x0e, | ||
4787 | conn, STAC92HD83_DAC_COUNT + 1) - 1; | ||
4788 | |||
4789 | snd_hda_codec_write_cache(codec, 0xe, 0, | ||
4790 | AC_VERB_SET_CONNECT_SEL, num_dacs); | ||
4791 | |||
4792 | spec->init = stac92hd83xxx_core_init; | 4874 | spec->init = stac92hd83xxx_core_init; |
4793 | spec->mixer = stac92hd83xxx_mixer; | 4875 | spec->mixer = stac92hd83xxx_mixer; |
4794 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); | 4876 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); |
@@ -4803,17 +4885,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4803 | stac92hd83xxx_models, | 4885 | stac92hd83xxx_models, |
4804 | stac92hd83xxx_cfg_tbl); | 4886 | stac92hd83xxx_cfg_tbl); |
4805 | again: | 4887 | again: |
4806 | if (spec->board_config < 0) { | 4888 | if (spec->board_config < 0) |
4807 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4889 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4808 | " STAC92HD83XXX, using BIOS defaults\n"); | 4890 | " STAC92HD83XXX, using BIOS defaults\n"); |
4809 | err = stac92xx_save_bios_config_regs(codec); | 4891 | else |
4810 | } else | 4892 | stac92xx_set_config_regs(codec, |
4811 | err = stac_save_pin_cfgs(codec, | ||
4812 | stac92hd83xxx_brd_tbl[spec->board_config]); | 4893 | stac92hd83xxx_brd_tbl[spec->board_config]); |
4813 | if (err < 0) { | ||
4814 | stac92xx_free(codec); | ||
4815 | return err; | ||
4816 | } | ||
4817 | 4894 | ||
4818 | switch (codec->vendor_id) { | 4895 | switch (codec->vendor_id) { |
4819 | case 0x111d7604: | 4896 | case 0x111d7604: |
@@ -4840,6 +4917,23 @@ again: | |||
4840 | return err; | 4917 | return err; |
4841 | } | 4918 | } |
4842 | 4919 | ||
4920 | switch (spec->board_config) { | ||
4921 | case STAC_DELL_S14: | ||
4922 | nid = 0xf; | ||
4923 | break; | ||
4924 | default: | ||
4925 | nid = 0xe; | ||
4926 | break; | ||
4927 | } | ||
4928 | |||
4929 | num_dacs = snd_hda_get_connections(codec, nid, | ||
4930 | conn, STAC92HD83_DAC_COUNT + 1) - 1; | ||
4931 | |||
4932 | /* set port X to select the last DAC | ||
4933 | */ | ||
4934 | snd_hda_codec_write_cache(codec, nid, 0, | ||
4935 | AC_VERB_SET_CONNECT_SEL, num_dacs); | ||
4936 | |||
4843 | codec->patch_ops = stac92xx_patch_ops; | 4937 | codec->patch_ops = stac92xx_patch_ops; |
4844 | 4938 | ||
4845 | codec->proc_widget_hook = stac92hd_proc_hook; | 4939 | codec->proc_widget_hook = stac92hd_proc_hook; |
@@ -4847,7 +4941,16 @@ again: | |||
4847 | return 0; | 4941 | return 0; |
4848 | } | 4942 | } |
4849 | 4943 | ||
4850 | static struct hda_input_mux stac92hd71bxx_dmux = { | 4944 | static struct hda_input_mux stac92hd71bxx_dmux_nomixer = { |
4945 | .num_items = 3, | ||
4946 | .items = { | ||
4947 | { "Analog Inputs", 0x00 }, | ||
4948 | { "Digital Mic 1", 0x02 }, | ||
4949 | { "Digital Mic 2", 0x03 }, | ||
4950 | } | ||
4951 | }; | ||
4952 | |||
4953 | static struct hda_input_mux stac92hd71bxx_dmux_amixer = { | ||
4851 | .num_items = 4, | 4954 | .num_items = 4, |
4852 | .items = { | 4955 | .items = { |
4853 | { "Analog Inputs", 0x00 }, | 4956 | { "Analog Inputs", 0x00 }, |
@@ -4857,10 +4960,67 @@ static struct hda_input_mux stac92hd71bxx_dmux = { | |||
4857 | } | 4960 | } |
4858 | }; | 4961 | }; |
4859 | 4962 | ||
4963 | /* get the pin connection (fixed, none, etc) */ | ||
4964 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
4965 | { | ||
4966 | struct sigmatel_spec *spec = codec->spec; | ||
4967 | unsigned int cfg; | ||
4968 | |||
4969 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
4970 | return get_defcfg_connect(cfg); | ||
4971 | } | ||
4972 | |||
4973 | static int stac92hd71bxx_connected_ports(struct hda_codec *codec, | ||
4974 | hda_nid_t *nids, int num_nids) | ||
4975 | { | ||
4976 | struct sigmatel_spec *spec = codec->spec; | ||
4977 | int idx, num; | ||
4978 | unsigned int def_conf; | ||
4979 | |||
4980 | for (num = 0; num < num_nids; num++) { | ||
4981 | for (idx = 0; idx < spec->num_pins; idx++) | ||
4982 | if (spec->pin_nids[idx] == nids[num]) | ||
4983 | break; | ||
4984 | if (idx >= spec->num_pins) | ||
4985 | break; | ||
4986 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
4987 | if (def_conf == AC_JACK_PORT_NONE) | ||
4988 | break; | ||
4989 | } | ||
4990 | return num; | ||
4991 | } | ||
4992 | |||
4993 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | ||
4994 | hda_nid_t dig0pin) | ||
4995 | { | ||
4996 | struct sigmatel_spec *spec = codec->spec; | ||
4997 | int idx; | ||
4998 | |||
4999 | for (idx = 0; idx < spec->num_pins; idx++) | ||
5000 | if (spec->pin_nids[idx] == dig0pin) | ||
5001 | break; | ||
5002 | if ((idx + 2) >= spec->num_pins) | ||
5003 | return 0; | ||
5004 | |||
5005 | /* dig1pin case */ | ||
5006 | if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE) | ||
5007 | return 2; | ||
5008 | |||
5009 | /* dig0pin + dig2pin case */ | ||
5010 | if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE) | ||
5011 | return 2; | ||
5012 | if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE) | ||
5013 | return 1; | ||
5014 | else | ||
5015 | return 0; | ||
5016 | } | ||
5017 | |||
4860 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 5018 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
4861 | { | 5019 | { |
4862 | struct sigmatel_spec *spec; | 5020 | struct sigmatel_spec *spec; |
5021 | struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; | ||
4863 | int err = 0; | 5022 | int err = 0; |
5023 | unsigned int ndmic_nids = 0; | ||
4864 | 5024 | ||
4865 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5025 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4866 | if (spec == NULL) | 5026 | if (spec == NULL) |
@@ -4868,27 +5028,32 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4868 | 5028 | ||
4869 | codec->spec = spec; | 5029 | codec->spec = spec; |
4870 | codec->patch_ops = stac92xx_patch_ops; | 5030 | codec->patch_ops = stac92xx_patch_ops; |
4871 | spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); | 5031 | spec->num_pins = STAC92HD71BXX_NUM_PINS; |
5032 | switch (codec->vendor_id) { | ||
5033 | case 0x111d76b6: | ||
5034 | case 0x111d76b7: | ||
5035 | spec->pin_nids = stac92hd71bxx_pin_nids_4port; | ||
5036 | break; | ||
5037 | case 0x111d7603: | ||
5038 | case 0x111d7608: | ||
5039 | /* On 92HD75Bx 0x27 isn't a pin nid */ | ||
5040 | spec->num_pins--; | ||
5041 | /* fallthrough */ | ||
5042 | default: | ||
5043 | spec->pin_nids = stac92hd71bxx_pin_nids_6port; | ||
5044 | } | ||
4872 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | 5045 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); |
4873 | spec->pin_nids = stac92hd71bxx_pin_nids; | ||
4874 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux, | ||
4875 | sizeof(stac92hd71bxx_dmux)); | ||
4876 | spec->board_config = snd_hda_check_board_config(codec, | 5046 | spec->board_config = snd_hda_check_board_config(codec, |
4877 | STAC_92HD71BXX_MODELS, | 5047 | STAC_92HD71BXX_MODELS, |
4878 | stac92hd71bxx_models, | 5048 | stac92hd71bxx_models, |
4879 | stac92hd71bxx_cfg_tbl); | 5049 | stac92hd71bxx_cfg_tbl); |
4880 | again: | 5050 | again: |
4881 | if (spec->board_config < 0) { | 5051 | if (spec->board_config < 0) |
4882 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 5052 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4883 | " STAC92HD71BXX, using BIOS defaults\n"); | 5053 | " STAC92HD71BXX, using BIOS defaults\n"); |
4884 | err = stac92xx_save_bios_config_regs(codec); | 5054 | else |
4885 | } else | 5055 | stac92xx_set_config_regs(codec, |
4886 | err = stac_save_pin_cfgs(codec, | ||
4887 | stac92hd71bxx_brd_tbl[spec->board_config]); | 5056 | stac92hd71bxx_brd_tbl[spec->board_config]); |
4888 | if (err < 0) { | ||
4889 | stac92xx_free(codec); | ||
4890 | return err; | ||
4891 | } | ||
4892 | 5057 | ||
4893 | if (spec->board_config > STAC_92HD71BXX_REF) { | 5058 | if (spec->board_config > STAC_92HD71BXX_REF) { |
4894 | /* GPIO0 = EAPD */ | 5059 | /* GPIO0 = EAPD */ |
@@ -4897,16 +5062,34 @@ again: | |||
4897 | spec->gpio_data = 0x01; | 5062 | spec->gpio_data = 0x01; |
4898 | } | 5063 | } |
4899 | 5064 | ||
5065 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | ||
5066 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | ||
5067 | |||
4900 | switch (codec->vendor_id) { | 5068 | switch (codec->vendor_id) { |
4901 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | 5069 | case 0x111d76b6: /* 4 Port without Analog Mixer */ |
4902 | case 0x111d76b7: | 5070 | case 0x111d76b7: |
5071 | unmute_init++; | ||
5072 | /* fallthru */ | ||
4903 | case 0x111d76b4: /* 6 Port without Analog Mixer */ | 5073 | case 0x111d76b4: /* 6 Port without Analog Mixer */ |
4904 | case 0x111d76b5: | 5074 | case 0x111d76b5: |
5075 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer, | ||
5076 | sizeof(stac92hd71bxx_dmux_nomixer)); | ||
4905 | spec->mixer = stac92hd71bxx_mixer; | 5077 | spec->mixer = stac92hd71bxx_mixer; |
4906 | spec->init = stac92hd71bxx_core_init; | 5078 | spec->init = stac92hd71bxx_core_init; |
4907 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5079 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5080 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | ||
5081 | stac92hd71bxx_dmic_nids, | ||
5082 | STAC92HD71BXX_NUM_DMICS); | ||
5083 | if (spec->num_dmics) { | ||
5084 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
5085 | spec->dinput_mux = &spec->private_dimux; | ||
5086 | ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; | ||
5087 | } | ||
4908 | break; | 5088 | break; |
4909 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 5089 | case 0x111d7608: /* 5 Port with Analog Mixer */ |
5090 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, | ||
5091 | sizeof(stac92hd71bxx_dmux_amixer)); | ||
5092 | spec->private_dimux.num_items--; | ||
4910 | switch (spec->board_config) { | 5093 | switch (spec->board_config) { |
4911 | case STAC_HP_M4: | 5094 | case STAC_HP_M4: |
4912 | /* Enable VREF power saving on GPIO1 detect */ | 5095 | /* Enable VREF power saving on GPIO1 detect */ |
@@ -4933,7 +5116,15 @@ again: | |||
4933 | 5116 | ||
4934 | /* disable VSW */ | 5117 | /* disable VSW */ |
4935 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; | 5118 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; |
4936 | stac_change_pin_config(codec, 0xf, 0x40f000f0); | 5119 | unmute_init++; |
5120 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | ||
5121 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | ||
5122 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; | ||
5123 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | ||
5124 | stac92hd71bxx_dmic_nids, | ||
5125 | STAC92HD71BXX_NUM_DMICS - 1); | ||
5126 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
5127 | ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2; | ||
4937 | break; | 5128 | break; |
4938 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 5129 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
4939 | if ((codec->revision_id & 0xf) == 1) | 5130 | if ((codec->revision_id & 0xf) == 1) |
@@ -4943,12 +5134,23 @@ again: | |||
4943 | spec->num_pwrs = 0; | 5134 | spec->num_pwrs = 0; |
4944 | /* fallthru */ | 5135 | /* fallthru */ |
4945 | default: | 5136 | default: |
5137 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, | ||
5138 | sizeof(stac92hd71bxx_dmux_amixer)); | ||
4946 | spec->dinput_mux = &spec->private_dimux; | 5139 | spec->dinput_mux = &spec->private_dimux; |
4947 | spec->mixer = stac92hd71bxx_analog_mixer; | 5140 | spec->mixer = stac92hd71bxx_analog_mixer; |
4948 | spec->init = stac92hd71bxx_analog_core_init; | 5141 | spec->init = stac92hd71bxx_analog_core_init; |
4949 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5142 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5143 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | ||
5144 | stac92hd71bxx_dmic_nids, | ||
5145 | STAC92HD71BXX_NUM_DMICS); | ||
5146 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
5147 | ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; | ||
4950 | } | 5148 | } |
4951 | 5149 | ||
5150 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) | ||
5151 | snd_hda_sequence_write_cache(codec, unmute_init); | ||
5152 | |||
5153 | spec->aloopback_ctl = stac92hd71bxx_loopback; | ||
4952 | spec->aloopback_mask = 0x50; | 5154 | spec->aloopback_mask = 0x50; |
4953 | spec->aloopback_shift = 0; | 5155 | spec->aloopback_shift = 0; |
4954 | 5156 | ||
@@ -4956,18 +5158,17 @@ again: | |||
4956 | spec->digbeep_nid = 0x26; | 5158 | spec->digbeep_nid = 0x26; |
4957 | spec->mux_nids = stac92hd71bxx_mux_nids; | 5159 | spec->mux_nids = stac92hd71bxx_mux_nids; |
4958 | spec->adc_nids = stac92hd71bxx_adc_nids; | 5160 | spec->adc_nids = stac92hd71bxx_adc_nids; |
4959 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | ||
4960 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | ||
4961 | spec->smux_nids = stac92hd71bxx_smux_nids; | 5161 | spec->smux_nids = stac92hd71bxx_smux_nids; |
4962 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 5162 | spec->pwr_nids = stac92hd71bxx_pwr_nids; |
4963 | 5163 | ||
4964 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); | 5164 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); |
4965 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); | 5165 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); |
5166 | spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); | ||
4966 | 5167 | ||
4967 | switch (spec->board_config) { | 5168 | switch (spec->board_config) { |
4968 | case STAC_HP_M4: | 5169 | case STAC_HP_M4: |
4969 | /* enable internal microphone */ | 5170 | /* enable internal microphone */ |
4970 | stac_change_pin_config(codec, 0x0e, 0x01813040); | 5171 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); |
4971 | stac92xx_auto_set_pinctl(codec, 0x0e, | 5172 | stac92xx_auto_set_pinctl(codec, 0x0e, |
4972 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); | 5173 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); |
4973 | /* fallthru */ | 5174 | /* fallthru */ |
@@ -4980,21 +5181,38 @@ again: | |||
4980 | case STAC_DELL_M4_3: | 5181 | case STAC_DELL_M4_3: |
4981 | spec->num_dmics = 1; | 5182 | spec->num_dmics = 1; |
4982 | spec->num_smuxes = 0; | 5183 | spec->num_smuxes = 0; |
4983 | spec->num_dmuxes = 0; | 5184 | spec->num_dmuxes = 1; |
5185 | break; | ||
5186 | case STAC_HP_DV5: | ||
5187 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); | ||
5188 | stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); | ||
5189 | break; | ||
5190 | case STAC_HP_HDX: | ||
5191 | spec->num_dmics = 1; | ||
5192 | spec->num_dmuxes = 1; | ||
5193 | spec->num_smuxes = 1; | ||
5194 | /* | ||
5195 | * For controlling MUTE LED on HP HDX16/HDX18 notebooks, | ||
5196 | * the CONFIG_SND_HDA_POWER_SAVE is needed to be set. | ||
5197 | */ | ||
5198 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5199 | /* orange/white mute led on GPIO3, orange=0, white=1 */ | ||
5200 | spec->gpio_mask |= 0x08; | ||
5201 | spec->gpio_dir |= 0x08; | ||
5202 | spec->gpio_data |= 0x08; /* set to white */ | ||
5203 | |||
5204 | /* register check_power_status callback. */ | ||
5205 | codec->patch_ops.check_power_status = | ||
5206 | stac92xx_hp_hdx_check_power_status; | ||
5207 | #endif | ||
4984 | break; | 5208 | break; |
4985 | default: | ||
4986 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | ||
4987 | spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids); | ||
4988 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
4989 | }; | 5209 | }; |
4990 | 5210 | ||
4991 | spec->multiout.dac_nids = spec->dac_nids; | 5211 | spec->multiout.dac_nids = spec->dac_nids; |
4992 | if (spec->dinput_mux) | 5212 | if (spec->dinput_mux) |
4993 | spec->private_dimux.num_items += | 5213 | spec->private_dimux.num_items += spec->num_dmics - ndmic_nids; |
4994 | spec->num_dmics - | ||
4995 | (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1); | ||
4996 | 5214 | ||
4997 | err = stac92xx_parse_auto_config(codec, 0x21, 0x23); | 5215 | err = stac92xx_parse_auto_config(codec, 0x21, 0); |
4998 | if (!err) { | 5216 | if (!err) { |
4999 | if (spec->board_config < 0) { | 5217 | if (spec->board_config < 0) { |
5000 | printk(KERN_WARNING "hda_codec: No auto-config is " | 5218 | printk(KERN_WARNING "hda_codec: No auto-config is " |
@@ -5069,17 +5287,12 @@ static int patch_stac922x(struct hda_codec *codec) | |||
5069 | } | 5287 | } |
5070 | 5288 | ||
5071 | again: | 5289 | again: |
5072 | if (spec->board_config < 0) { | 5290 | if (spec->board_config < 0) |
5073 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 5291 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " |
5074 | "using BIOS defaults\n"); | 5292 | "using BIOS defaults\n"); |
5075 | err = stac92xx_save_bios_config_regs(codec); | 5293 | else |
5076 | } else | 5294 | stac92xx_set_config_regs(codec, |
5077 | err = stac_save_pin_cfgs(codec, | ||
5078 | stac922x_brd_tbl[spec->board_config]); | 5295 | stac922x_brd_tbl[spec->board_config]); |
5079 | if (err < 0) { | ||
5080 | stac92xx_free(codec); | ||
5081 | return err; | ||
5082 | } | ||
5083 | 5296 | ||
5084 | spec->adc_nids = stac922x_adc_nids; | 5297 | spec->adc_nids = stac922x_adc_nids; |
5085 | spec->mux_nids = stac922x_mux_nids; | 5298 | spec->mux_nids = stac922x_mux_nids; |
@@ -5130,24 +5343,19 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5130 | return -ENOMEM; | 5343 | return -ENOMEM; |
5131 | 5344 | ||
5132 | codec->spec = spec; | 5345 | codec->spec = spec; |
5346 | codec->slave_dig_outs = stac927x_slave_dig_outs; | ||
5133 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); | 5347 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); |
5134 | spec->pin_nids = stac927x_pin_nids; | 5348 | spec->pin_nids = stac927x_pin_nids; |
5135 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, | 5349 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, |
5136 | stac927x_models, | 5350 | stac927x_models, |
5137 | stac927x_cfg_tbl); | 5351 | stac927x_cfg_tbl); |
5138 | again: | 5352 | again: |
5139 | if (spec->board_config < 0 || !stac927x_brd_tbl[spec->board_config]) { | 5353 | if (spec->board_config < 0) |
5140 | if (spec->board_config < 0) | 5354 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
5141 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 5355 | "STAC927x, using BIOS defaults\n"); |
5142 | "STAC927x, using BIOS defaults\n"); | 5356 | else |
5143 | err = stac92xx_save_bios_config_regs(codec); | 5357 | stac92xx_set_config_regs(codec, |
5144 | } else | ||
5145 | err = stac_save_pin_cfgs(codec, | ||
5146 | stac927x_brd_tbl[spec->board_config]); | 5358 | stac927x_brd_tbl[spec->board_config]); |
5147 | if (err < 0) { | ||
5148 | stac92xx_free(codec); | ||
5149 | return err; | ||
5150 | } | ||
5151 | 5359 | ||
5152 | spec->digbeep_nid = 0x23; | 5360 | spec->digbeep_nid = 0x23; |
5153 | spec->adc_nids = stac927x_adc_nids; | 5361 | spec->adc_nids = stac927x_adc_nids; |
@@ -5176,15 +5384,15 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5176 | case 0x10280209: | 5384 | case 0x10280209: |
5177 | case 0x1028022e: | 5385 | case 0x1028022e: |
5178 | /* correct the device field to SPDIF out */ | 5386 | /* correct the device field to SPDIF out */ |
5179 | stac_change_pin_config(codec, 0x21, 0x01442070); | 5387 | snd_hda_codec_set_pincfg(codec, 0x21, 0x01442070); |
5180 | break; | 5388 | break; |
5181 | }; | 5389 | }; |
5182 | /* configure the analog microphone on some laptops */ | 5390 | /* configure the analog microphone on some laptops */ |
5183 | stac_change_pin_config(codec, 0x0c, 0x90a79130); | 5391 | snd_hda_codec_set_pincfg(codec, 0x0c, 0x90a79130); |
5184 | /* correct the front output jack as a hp out */ | 5392 | /* correct the front output jack as a hp out */ |
5185 | stac_change_pin_config(codec, 0x0f, 0x0227011f); | 5393 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x0227011f); |
5186 | /* correct the front input jack as a mic */ | 5394 | /* correct the front input jack as a mic */ |
5187 | stac_change_pin_config(codec, 0x0e, 0x02a79130); | 5395 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130); |
5188 | /* fallthru */ | 5396 | /* fallthru */ |
5189 | case STAC_DELL_3ST: | 5397 | case STAC_DELL_3ST: |
5190 | /* GPIO2 High = Enable EAPD */ | 5398 | /* GPIO2 High = Enable EAPD */ |
@@ -5211,6 +5419,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5211 | } | 5419 | } |
5212 | 5420 | ||
5213 | spec->num_pwrs = 0; | 5421 | spec->num_pwrs = 0; |
5422 | spec->aloopback_ctl = stac927x_loopback; | ||
5214 | spec->aloopback_mask = 0x40; | 5423 | spec->aloopback_mask = 0x40; |
5215 | spec->aloopback_shift = 0; | 5424 | spec->aloopback_shift = 0; |
5216 | spec->eapd_switch = 1; | 5425 | spec->eapd_switch = 1; |
@@ -5269,16 +5478,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5269 | stac9205_models, | 5478 | stac9205_models, |
5270 | stac9205_cfg_tbl); | 5479 | stac9205_cfg_tbl); |
5271 | again: | 5480 | again: |
5272 | if (spec->board_config < 0) { | 5481 | if (spec->board_config < 0) |
5273 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | 5482 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); |
5274 | err = stac92xx_save_bios_config_regs(codec); | 5483 | else |
5275 | } else | 5484 | stac92xx_set_config_regs(codec, |
5276 | err = stac_save_pin_cfgs(codec, | ||
5277 | stac9205_brd_tbl[spec->board_config]); | 5485 | stac9205_brd_tbl[spec->board_config]); |
5278 | if (err < 0) { | ||
5279 | stac92xx_free(codec); | ||
5280 | return err; | ||
5281 | } | ||
5282 | 5486 | ||
5283 | spec->digbeep_nid = 0x23; | 5487 | spec->digbeep_nid = 0x23; |
5284 | spec->adc_nids = stac9205_adc_nids; | 5488 | spec->adc_nids = stac9205_adc_nids; |
@@ -5295,17 +5499,20 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5295 | 5499 | ||
5296 | spec->init = stac9205_core_init; | 5500 | spec->init = stac9205_core_init; |
5297 | spec->mixer = stac9205_mixer; | 5501 | spec->mixer = stac9205_mixer; |
5502 | spec->aloopback_ctl = stac9205_loopback; | ||
5298 | 5503 | ||
5299 | spec->aloopback_mask = 0x40; | 5504 | spec->aloopback_mask = 0x40; |
5300 | spec->aloopback_shift = 0; | 5505 | spec->aloopback_shift = 0; |
5301 | spec->eapd_switch = 1; | 5506 | /* Turn on/off EAPD per HP plugging */ |
5507 | if (spec->board_config != STAC_9205_EAPD) | ||
5508 | spec->eapd_switch = 1; | ||
5302 | spec->multiout.dac_nids = spec->dac_nids; | 5509 | spec->multiout.dac_nids = spec->dac_nids; |
5303 | 5510 | ||
5304 | switch (spec->board_config){ | 5511 | switch (spec->board_config){ |
5305 | case STAC_9205_DELL_M43: | 5512 | case STAC_9205_DELL_M43: |
5306 | /* Enable SPDIF in/out */ | 5513 | /* Enable SPDIF in/out */ |
5307 | stac_change_pin_config(codec, 0x1f, 0x01441030); | 5514 | snd_hda_codec_set_pincfg(codec, 0x1f, 0x01441030); |
5308 | stac_change_pin_config(codec, 0x20, 0x1c410030); | 5515 | snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); |
5309 | 5516 | ||
5310 | /* Enable unsol response for GPIO4/Dock HP connection */ | 5517 | /* Enable unsol response for GPIO4/Dock HP connection */ |
5311 | err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); | 5518 | err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); |
@@ -5362,223 +5569,87 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5362 | * STAC9872 hack | 5569 | * STAC9872 hack |
5363 | */ | 5570 | */ |
5364 | 5571 | ||
5365 | /* static config for Sony VAIO FE550G and Sony VAIO AR */ | 5572 | static struct hda_verb stac9872_core_init[] = { |
5366 | static hda_nid_t vaio_dacs[] = { 0x2 }; | ||
5367 | #define VAIO_HP_DAC 0x5 | ||
5368 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | ||
5369 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | ||
5370 | |||
5371 | static struct hda_input_mux vaio_mux = { | ||
5372 | .num_items = 3, | ||
5373 | .items = { | ||
5374 | /* { "HP", 0x0 }, */ | ||
5375 | { "Mic Jack", 0x1 }, | ||
5376 | { "Internal Mic", 0x2 }, | ||
5377 | { "PCM", 0x3 }, | ||
5378 | } | ||
5379 | }; | ||
5380 | |||
5381 | static struct hda_verb vaio_init[] = { | ||
5382 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
5383 | {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT}, | ||
5384 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
5385 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
5386 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
5387 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
5388 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | 5573 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ |
5389 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
5390 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
5391 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
5392 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
5393 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | 5574 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ |
5394 | {} | 5575 | {} |
5395 | }; | 5576 | }; |
5396 | 5577 | ||
5397 | static struct hda_verb vaio_ar_init[] = { | 5578 | static struct snd_kcontrol_new stac9872_mixer[] = { |
5398 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
5399 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
5400 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
5401 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
5402 | /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ | ||
5403 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
5404 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | ||
5405 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
5406 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
5407 | /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ | ||
5408 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
5409 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
5410 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | ||
5411 | {} | ||
5412 | }; | ||
5413 | |||
5414 | static struct snd_kcontrol_new vaio_mixer[] = { | ||
5415 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), | ||
5416 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), | ||
5417 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5418 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5419 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
5420 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 5579 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
5421 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 5580 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
5422 | { | 5581 | { } /* end */ |
5423 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5424 | .name = "Capture Source", | ||
5425 | .count = 1, | ||
5426 | .info = stac92xx_mux_enum_info, | ||
5427 | .get = stac92xx_mux_enum_get, | ||
5428 | .put = stac92xx_mux_enum_put, | ||
5429 | }, | ||
5430 | {} | ||
5431 | }; | 5582 | }; |
5432 | 5583 | ||
5433 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 5584 | static hda_nid_t stac9872_pin_nids[] = { |
5434 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), | 5585 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
5435 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), | 5586 | 0x11, 0x13, 0x14, |
5436 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5437 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5438 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
5439 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | ||
5440 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | ||
5441 | /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), | ||
5442 | HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ | ||
5443 | { | ||
5444 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5445 | .name = "Capture Source", | ||
5446 | .count = 1, | ||
5447 | .info = stac92xx_mux_enum_info, | ||
5448 | .get = stac92xx_mux_enum_get, | ||
5449 | .put = stac92xx_mux_enum_put, | ||
5450 | }, | ||
5451 | {} | ||
5452 | }; | 5587 | }; |
5453 | 5588 | ||
5454 | static struct hda_codec_ops stac9872_patch_ops = { | 5589 | static hda_nid_t stac9872_adc_nids[] = { |
5455 | .build_controls = stac92xx_build_controls, | 5590 | 0x8 /*,0x6*/ |
5456 | .build_pcms = stac92xx_build_pcms, | ||
5457 | .init = stac92xx_init, | ||
5458 | .free = stac92xx_free, | ||
5459 | #ifdef SND_HDA_NEEDS_RESUME | ||
5460 | .resume = stac92xx_resume, | ||
5461 | #endif | ||
5462 | }; | 5591 | }; |
5463 | 5592 | ||
5464 | static int stac9872_vaio_init(struct hda_codec *codec) | 5593 | static hda_nid_t stac9872_mux_nids[] = { |
5465 | { | 5594 | 0x15 |
5466 | int err; | ||
5467 | |||
5468 | err = stac92xx_init(codec); | ||
5469 | if (err < 0) | ||
5470 | return err; | ||
5471 | if (codec->patch_ops.unsol_event) | ||
5472 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
5473 | return 0; | ||
5474 | } | ||
5475 | |||
5476 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | ||
5477 | { | ||
5478 | if (get_pin_presence(codec, 0x0a)) { | ||
5479 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
5480 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
5481 | } else { | ||
5482 | stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
5483 | stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
5484 | } | ||
5485 | } | ||
5486 | |||
5487 | static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res) | ||
5488 | { | ||
5489 | switch (res >> 26) { | ||
5490 | case STAC_HP_EVENT: | ||
5491 | stac9872_vaio_hp_detect(codec, res); | ||
5492 | break; | ||
5493 | } | ||
5494 | } | ||
5495 | |||
5496 | static struct hda_codec_ops stac9872_vaio_patch_ops = { | ||
5497 | .build_controls = stac92xx_build_controls, | ||
5498 | .build_pcms = stac92xx_build_pcms, | ||
5499 | .init = stac9872_vaio_init, | ||
5500 | .free = stac92xx_free, | ||
5501 | .unsol_event = stac9872_vaio_unsol_event, | ||
5502 | #ifdef CONFIG_PM | ||
5503 | .resume = stac92xx_resume, | ||
5504 | #endif | ||
5505 | }; | 5595 | }; |
5506 | 5596 | ||
5507 | enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ | 5597 | static unsigned int stac9872_vaio_pin_configs[9] = { |
5508 | CXD9872RD_VAIO, | 5598 | 0x03211020, 0x411111f0, 0x411111f0, 0x03a15030, |
5509 | /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ | 5599 | 0x411111f0, 0x90170110, 0x411111f0, 0x411111f0, |
5510 | STAC9872AK_VAIO, | 5600 | 0x90a7013e |
5511 | /* Unknown. id=0x83847661 and subsys=0x104D1200. */ | ||
5512 | STAC9872K_VAIO, | ||
5513 | /* AR Series. id=0x83847664 and subsys=104D1300 */ | ||
5514 | CXD9872AKD_VAIO, | ||
5515 | STAC_9872_MODELS, | ||
5516 | }; | 5601 | }; |
5517 | 5602 | ||
5518 | static const char *stac9872_models[STAC_9872_MODELS] = { | 5603 | static const char *stac9872_models[STAC_9872_MODELS] = { |
5519 | [CXD9872RD_VAIO] = "vaio", | 5604 | [STAC_9872_AUTO] = "auto", |
5520 | [CXD9872AKD_VAIO] = "vaio-ar", | 5605 | [STAC_9872_VAIO] = "vaio", |
5606 | }; | ||
5607 | |||
5608 | static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = { | ||
5609 | [STAC_9872_VAIO] = stac9872_vaio_pin_configs, | ||
5521 | }; | 5610 | }; |
5522 | 5611 | ||
5523 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { | 5612 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { |
5524 | SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), | 5613 | {} /* terminator */ |
5525 | SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), | ||
5526 | SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), | ||
5527 | SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO), | ||
5528 | {} | ||
5529 | }; | 5614 | }; |
5530 | 5615 | ||
5531 | static int patch_stac9872(struct hda_codec *codec) | 5616 | static int patch_stac9872(struct hda_codec *codec) |
5532 | { | 5617 | { |
5533 | struct sigmatel_spec *spec; | 5618 | struct sigmatel_spec *spec; |
5534 | int board_config; | 5619 | int err; |
5535 | 5620 | ||
5536 | board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, | ||
5537 | stac9872_models, | ||
5538 | stac9872_cfg_tbl); | ||
5539 | if (board_config < 0) | ||
5540 | /* unknown config, let generic-parser do its job... */ | ||
5541 | return snd_hda_parse_generic_codec(codec); | ||
5542 | |||
5543 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5621 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
5544 | if (spec == NULL) | 5622 | if (spec == NULL) |
5545 | return -ENOMEM; | 5623 | return -ENOMEM; |
5546 | |||
5547 | codec->spec = spec; | 5624 | codec->spec = spec; |
5548 | switch (board_config) { | ||
5549 | case CXD9872RD_VAIO: | ||
5550 | case STAC9872AK_VAIO: | ||
5551 | case STAC9872K_VAIO: | ||
5552 | spec->mixer = vaio_mixer; | ||
5553 | spec->init = vaio_init; | ||
5554 | spec->multiout.max_channels = 2; | ||
5555 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
5556 | spec->multiout.dac_nids = vaio_dacs; | ||
5557 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
5558 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
5559 | spec->adc_nids = vaio_adcs; | ||
5560 | spec->num_pwrs = 0; | ||
5561 | spec->input_mux = &vaio_mux; | ||
5562 | spec->mux_nids = vaio_mux_nids; | ||
5563 | codec->patch_ops = stac9872_vaio_patch_ops; | ||
5564 | break; | ||
5565 | |||
5566 | case CXD9872AKD_VAIO: | ||
5567 | spec->mixer = vaio_ar_mixer; | ||
5568 | spec->init = vaio_ar_init; | ||
5569 | spec->multiout.max_channels = 2; | ||
5570 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
5571 | spec->multiout.dac_nids = vaio_dacs; | ||
5572 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
5573 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
5574 | spec->num_pwrs = 0; | ||
5575 | spec->adc_nids = vaio_adcs; | ||
5576 | spec->input_mux = &vaio_mux; | ||
5577 | spec->mux_nids = vaio_mux_nids; | ||
5578 | codec->patch_ops = stac9872_patch_ops; | ||
5579 | break; | ||
5580 | } | ||
5581 | 5625 | ||
5626 | spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, | ||
5627 | stac9872_models, | ||
5628 | stac9872_cfg_tbl); | ||
5629 | if (spec->board_config < 0) | ||
5630 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, " | ||
5631 | "using BIOS defaults\n"); | ||
5632 | else | ||
5633 | stac92xx_set_config_regs(codec, | ||
5634 | stac9872_brd_tbl[spec->board_config]); | ||
5635 | |||
5636 | spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); | ||
5637 | spec->pin_nids = stac9872_pin_nids; | ||
5638 | spec->multiout.dac_nids = spec->dac_nids; | ||
5639 | spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); | ||
5640 | spec->adc_nids = stac9872_adc_nids; | ||
5641 | spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); | ||
5642 | spec->mux_nids = stac9872_mux_nids; | ||
5643 | spec->mixer = stac9872_mixer; | ||
5644 | spec->init = stac9872_core_init; | ||
5645 | |||
5646 | err = stac92xx_parse_auto_config(codec, 0x10, 0x12); | ||
5647 | if (err < 0) { | ||
5648 | stac92xx_free(codec); | ||
5649 | return -EINVAL; | ||
5650 | } | ||
5651 | spec->input_mux = &spec->private_imux; | ||
5652 | codec->patch_ops = stac92xx_patch_ops; | ||
5582 | return 0; | 5653 | return 0; |
5583 | } | 5654 | } |
5584 | 5655 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c761394cbe84..b25a5cc637d6 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -1308,16 +1308,13 @@ static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid) | |||
1308 | unsigned int def_conf; | 1308 | unsigned int def_conf; |
1309 | unsigned char seqassoc; | 1309 | unsigned char seqassoc; |
1310 | 1310 | ||
1311 | def_conf = snd_hda_codec_read(codec, nid, 0, | 1311 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
1312 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
1313 | seqassoc = (unsigned char) get_defcfg_association(def_conf); | 1312 | seqassoc = (unsigned char) get_defcfg_association(def_conf); |
1314 | seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); | 1313 | seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); |
1315 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) { | 1314 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) { |
1316 | if (seqassoc == 0xff) { | 1315 | if (seqassoc == 0xff) { |
1317 | def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); | 1316 | def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); |
1318 | snd_hda_codec_write(codec, nid, 0, | 1317 | snd_hda_codec_set_pincfg(codec, nid, def_conf); |
1319 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
1320 | def_conf >> 24); | ||
1321 | } | 1318 | } |
1322 | } | 1319 | } |
1323 | 1320 | ||
@@ -1354,7 +1351,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
1354 | 1351 | ||
1355 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 1352 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
1356 | 1353 | ||
1357 | if (spec->autocfg.dig_out_pin) | 1354 | if (spec->autocfg.dig_outs) |
1358 | spec->multiout.dig_out_nid = VT1708_DIGOUT_NID; | 1355 | spec->multiout.dig_out_nid = VT1708_DIGOUT_NID; |
1359 | if (spec->autocfg.dig_in_pin) | 1356 | if (spec->autocfg.dig_in_pin) |
1360 | spec->dig_in_nid = VT1708_DIGIN_NID; | 1357 | spec->dig_in_nid = VT1708_DIGIN_NID; |
@@ -1827,7 +1824,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1827 | 1824 | ||
1828 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 1825 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
1829 | 1826 | ||
1830 | if (spec->autocfg.dig_out_pin) | 1827 | if (spec->autocfg.dig_outs) |
1831 | spec->multiout.dig_out_nid = VT1709_DIGOUT_NID; | 1828 | spec->multiout.dig_out_nid = VT1709_DIGOUT_NID; |
1832 | if (spec->autocfg.dig_in_pin) | 1829 | if (spec->autocfg.dig_in_pin) |
1833 | spec->dig_in_nid = VT1709_DIGIN_NID; | 1830 | spec->dig_in_nid = VT1709_DIGIN_NID; |
@@ -2371,7 +2368,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
2371 | 2368 | ||
2372 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2369 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2373 | 2370 | ||
2374 | if (spec->autocfg.dig_out_pin) | 2371 | if (spec->autocfg.dig_outs) |
2375 | spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; | 2372 | spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; |
2376 | if (spec->autocfg.dig_in_pin) | 2373 | if (spec->autocfg.dig_in_pin) |
2377 | spec->dig_in_nid = VT1708B_DIGIN_NID; | 2374 | spec->dig_in_nid = VT1708B_DIGIN_NID; |
@@ -2836,7 +2833,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
2836 | 2833 | ||
2837 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2834 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2838 | 2835 | ||
2839 | if (spec->autocfg.dig_out_pin) | 2836 | if (spec->autocfg.dig_outs) |
2840 | spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; | 2837 | spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; |
2841 | 2838 | ||
2842 | spec->extra_dig_out_nid = 0x15; | 2839 | spec->extra_dig_out_nid = 0x15; |
@@ -3155,7 +3152,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3155 | 3152 | ||
3156 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3153 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
3157 | 3154 | ||
3158 | if (spec->autocfg.dig_out_pin) | 3155 | if (spec->autocfg.dig_outs) |
3159 | spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; | 3156 | spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; |
3160 | 3157 | ||
3161 | spec->extra_dig_out_nid = 0x1B; | 3158 | spec->extra_dig_out_nid = 0x1B; |