diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 117 |
1 files changed, 106 insertions, 11 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8cbe3bf1e317..26812dc2b7f2 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -19,7 +19,6 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <sound/driver.h> | ||
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
@@ -55,6 +54,7 @@ static struct hda_vendor_id hda_vendor_ids[] = { | |||
55 | { 0x10ec, "Realtek" }, | 54 | { 0x10ec, "Realtek" }, |
56 | { 0x1057, "Motorola" }, | 55 | { 0x1057, "Motorola" }, |
57 | { 0x1106, "VIA" }, | 56 | { 0x1106, "VIA" }, |
57 | { 0x111d, "IDT" }, | ||
58 | { 0x11d4, "Analog Devices" }, | 58 | { 0x11d4, "Analog Devices" }, |
59 | { 0x13f6, "C-Media" }, | 59 | { 0x13f6, "C-Media" }, |
60 | { 0x14f1, "Conexant" }, | 60 | { 0x14f1, "Conexant" }, |
@@ -429,6 +429,10 @@ find_codec_preset(struct hda_codec *codec) | |||
429 | for (tbl = hda_preset_tables; *tbl; tbl++) { | 429 | for (tbl = hda_preset_tables; *tbl; tbl++) { |
430 | for (preset = *tbl; preset->id; preset++) { | 430 | for (preset = *tbl; preset->id; preset++) { |
431 | u32 mask = preset->mask; | 431 | u32 mask = preset->mask; |
432 | if (preset->afg && preset->afg != codec->afg) | ||
433 | continue; | ||
434 | if (preset->mfg && preset->mfg != codec->mfg) | ||
435 | continue; | ||
432 | if (!mask) | 436 | if (!mask) |
433 | mask = ~0; | 437 | mask = ~0; |
434 | if (preset->id == (codec->vendor_id & mask) && | 438 | if (preset->id == (codec->vendor_id & mask) && |
@@ -765,7 +769,7 @@ get_alloc_amp_hash(struct hda_codec *codec, u32 key) | |||
765 | /* | 769 | /* |
766 | * query AMP capabilities for the given widget and direction | 770 | * query AMP capabilities for the given widget and direction |
767 | */ | 771 | */ |
768 | static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | 772 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) |
769 | { | 773 | { |
770 | struct hda_amp_info *info; | 774 | struct hda_amp_info *info; |
771 | 775 | ||
@@ -933,7 +937,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
933 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | 937 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; |
934 | if (!caps) { | 938 | if (!caps) { |
935 | printk(KERN_WARNING "hda_codec: " | 939 | printk(KERN_WARNING "hda_codec: " |
936 | "num_steps = 0 for NID=0x%x\n", nid); | 940 | "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, |
941 | kcontrol->id.name); | ||
937 | return -EINVAL; | 942 | return -EINVAL; |
938 | } | 943 | } |
939 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 944 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
@@ -1012,6 +1017,66 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1012 | return 0; | 1017 | return 0; |
1013 | } | 1018 | } |
1014 | 1019 | ||
1020 | /* | ||
1021 | * set (static) TLV for virtual master volume; recalculated as max 0dB | ||
1022 | */ | ||
1023 | void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, | ||
1024 | unsigned int *tlv) | ||
1025 | { | ||
1026 | u32 caps; | ||
1027 | int nums, step; | ||
1028 | |||
1029 | caps = query_amp_caps(codec, nid, dir); | ||
1030 | nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
1031 | step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; | ||
1032 | step = (step + 1) * 25; | ||
1033 | tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; | ||
1034 | tlv[1] = 2 * sizeof(unsigned int); | ||
1035 | tlv[2] = -nums * step; | ||
1036 | tlv[3] = step; | ||
1037 | } | ||
1038 | |||
1039 | /* find a mixer control element with the given name */ | ||
1040 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | ||
1041 | const char *name) | ||
1042 | { | ||
1043 | struct snd_ctl_elem_id id; | ||
1044 | memset(&id, 0, sizeof(id)); | ||
1045 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
1046 | strcpy(id.name, name); | ||
1047 | return snd_ctl_find_id(codec->bus->card, &id); | ||
1048 | } | ||
1049 | |||
1050 | /* create a virtual master control and add slaves */ | ||
1051 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | ||
1052 | unsigned int *tlv, const char **slaves) | ||
1053 | { | ||
1054 | struct snd_kcontrol *kctl; | ||
1055 | const char **s; | ||
1056 | int err; | ||
1057 | |||
1058 | kctl = snd_ctl_make_virtual_master(name, tlv); | ||
1059 | if (!kctl) | ||
1060 | return -ENOMEM; | ||
1061 | err = snd_ctl_add(codec->bus->card, kctl); | ||
1062 | if (err < 0) | ||
1063 | return err; | ||
1064 | |||
1065 | for (s = slaves; *s; s++) { | ||
1066 | struct snd_kcontrol *sctl; | ||
1067 | |||
1068 | sctl = snd_hda_find_mixer_ctl(codec, *s); | ||
1069 | if (!sctl) { | ||
1070 | snd_printdd("Cannot find slave %s, skipped\n", *s); | ||
1071 | continue; | ||
1072 | } | ||
1073 | err = snd_ctl_add_slave(kctl, sctl); | ||
1074 | if (err < 0) | ||
1075 | return err; | ||
1076 | } | ||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1015 | /* switch */ | 1080 | /* switch */ |
1016 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, | 1081 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, |
1017 | struct snd_ctl_elem_info *uinfo) | 1082 | struct snd_ctl_elem_info *uinfo) |
@@ -1434,7 +1499,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1434 | return err; | 1499 | return err; |
1435 | } | 1500 | } |
1436 | codec->spdif_ctls = | 1501 | codec->spdif_ctls = |
1437 | snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); | 1502 | snd_hda_codec_read(codec, nid, 0, |
1503 | AC_VERB_GET_DIGI_CONVERT_1, 0); | ||
1438 | codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); | 1504 | codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); |
1439 | return 0; | 1505 | return 0; |
1440 | } | 1506 | } |
@@ -1481,7 +1547,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, | |||
1481 | unsigned short val; | 1547 | unsigned short val; |
1482 | unsigned int sbits; | 1548 | unsigned int sbits; |
1483 | 1549 | ||
1484 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); | 1550 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0); |
1485 | sbits = convert_to_spdif_status(val); | 1551 | sbits = convert_to_spdif_status(val); |
1486 | ucontrol->value.iec958.status[0] = sbits; | 1552 | ucontrol->value.iec958.status[0] = sbits; |
1487 | ucontrol->value.iec958.status[1] = sbits >> 8; | 1553 | ucontrol->value.iec958.status[1] = sbits >> 8; |
@@ -1532,7 +1598,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1532 | return err; | 1598 | return err; |
1533 | } | 1599 | } |
1534 | codec->spdif_in_enable = | 1600 | codec->spdif_in_enable = |
1535 | snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & | 1601 | snd_hda_codec_read(codec, nid, 0, |
1602 | AC_VERB_GET_DIGI_CONVERT_1, 0) & | ||
1536 | AC_DIG1_ENABLE; | 1603 | AC_DIG1_ENABLE; |
1537 | return 0; | 1604 | return 0; |
1538 | } | 1605 | } |
@@ -1622,6 +1689,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
1622 | 1689 | ||
1623 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 1690 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, |
1624 | power_state); | 1691 | power_state); |
1692 | msleep(10); /* partial workaround for "azx_get_response timeout" */ | ||
1625 | 1693 | ||
1626 | nid = codec->start_nid; | 1694 | nid = codec->start_nid; |
1627 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 1695 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
@@ -2336,7 +2404,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, | |||
2336 | unsigned int mode; | 2404 | unsigned int mode; |
2337 | 2405 | ||
2338 | mode = ucontrol->value.enumerated.item[0]; | 2406 | mode = ucontrol->value.enumerated.item[0]; |
2339 | snd_assert(mode < num_chmodes, return -EINVAL); | 2407 | if (mode >= num_chmodes) |
2408 | return -EINVAL; | ||
2340 | if (*max_channelsp == chmode[mode].channels) | 2409 | if (*max_channelsp == chmode[mode].channels) |
2341 | return 0; | 2410 | return 0; |
2342 | /* change the current channel setting */ | 2411 | /* change the current channel setting */ |
@@ -2602,20 +2671,21 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2602 | struct auto_pin_cfg *cfg, | 2671 | struct auto_pin_cfg *cfg, |
2603 | hda_nid_t *ignore_nids) | 2672 | hda_nid_t *ignore_nids) |
2604 | { | 2673 | { |
2605 | hda_nid_t nid, nid_start; | 2674 | hda_nid_t nid, end_nid; |
2606 | int nodes; | ||
2607 | short seq, assoc_line_out, assoc_speaker; | 2675 | short seq, assoc_line_out, assoc_speaker; |
2608 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | 2676 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; |
2609 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | 2677 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; |
2678 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; | ||
2610 | 2679 | ||
2611 | memset(cfg, 0, sizeof(*cfg)); | 2680 | memset(cfg, 0, sizeof(*cfg)); |
2612 | 2681 | ||
2613 | memset(sequences_line_out, 0, sizeof(sequences_line_out)); | 2682 | memset(sequences_line_out, 0, sizeof(sequences_line_out)); |
2614 | memset(sequences_speaker, 0, sizeof(sequences_speaker)); | 2683 | memset(sequences_speaker, 0, sizeof(sequences_speaker)); |
2684 | memset(sequences_hp, 0, sizeof(sequences_hp)); | ||
2615 | assoc_line_out = assoc_speaker = 0; | 2685 | assoc_line_out = assoc_speaker = 0; |
2616 | 2686 | ||
2617 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | 2687 | end_nid = codec->start_nid + codec->num_nodes; |
2618 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | 2688 | for (nid = codec->start_nid; nid < end_nid; nid++) { |
2619 | unsigned int wid_caps = get_wcaps(codec, nid); | 2689 | unsigned int wid_caps = get_wcaps(codec, nid); |
2620 | unsigned int wid_type = | 2690 | unsigned int wid_type = |
2621 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 2691 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
@@ -2638,6 +2708,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2638 | case AC_JACK_LINE_OUT: | 2708 | case AC_JACK_LINE_OUT: |
2639 | seq = get_defcfg_sequence(def_conf); | 2709 | seq = get_defcfg_sequence(def_conf); |
2640 | assoc = get_defcfg_association(def_conf); | 2710 | assoc = get_defcfg_association(def_conf); |
2711 | |||
2712 | if (!(wid_caps & AC_WCAP_STEREO)) | ||
2713 | if (!cfg->mono_out_pin) | ||
2714 | cfg->mono_out_pin = nid; | ||
2641 | if (!assoc) | 2715 | if (!assoc) |
2642 | continue; | 2716 | continue; |
2643 | if (!assoc_line_out) | 2717 | if (!assoc_line_out) |
@@ -2666,9 +2740,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2666 | cfg->speaker_outs++; | 2740 | cfg->speaker_outs++; |
2667 | break; | 2741 | break; |
2668 | case AC_JACK_HP_OUT: | 2742 | case AC_JACK_HP_OUT: |
2743 | seq = get_defcfg_sequence(def_conf); | ||
2744 | assoc = get_defcfg_association(def_conf); | ||
2669 | if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) | 2745 | if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) |
2670 | continue; | 2746 | continue; |
2671 | cfg->hp_pins[cfg->hp_outs] = nid; | 2747 | cfg->hp_pins[cfg->hp_outs] = nid; |
2748 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; | ||
2672 | cfg->hp_outs++; | 2749 | cfg->hp_outs++; |
2673 | break; | 2750 | break; |
2674 | case AC_JACK_MIC_IN: { | 2751 | case AC_JACK_MIC_IN: { |
@@ -2712,7 +2789,24 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2712 | cfg->line_outs); | 2789 | cfg->line_outs); |
2713 | sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker, | 2790 | sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker, |
2714 | cfg->speaker_outs); | 2791 | cfg->speaker_outs); |
2792 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | ||
2793 | cfg->hp_outs); | ||
2715 | 2794 | ||
2795 | /* if we have only one mic, make it AUTO_PIN_MIC */ | ||
2796 | if (!cfg->input_pins[AUTO_PIN_MIC] && | ||
2797 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | ||
2798 | cfg->input_pins[AUTO_PIN_MIC] = | ||
2799 | cfg->input_pins[AUTO_PIN_FRONT_MIC]; | ||
2800 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0; | ||
2801 | } | ||
2802 | /* ditto for line-in */ | ||
2803 | if (!cfg->input_pins[AUTO_PIN_LINE] && | ||
2804 | cfg->input_pins[AUTO_PIN_FRONT_LINE]) { | ||
2805 | cfg->input_pins[AUTO_PIN_LINE] = | ||
2806 | cfg->input_pins[AUTO_PIN_FRONT_LINE]; | ||
2807 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0; | ||
2808 | } | ||
2809 | |||
2716 | /* | 2810 | /* |
2717 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | 2811 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
2718 | * as a primary output | 2812 | * as a primary output |
@@ -2766,6 +2860,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2766 | cfg->hp_outs, cfg->hp_pins[0], | 2860 | cfg->hp_outs, cfg->hp_pins[0], |
2767 | cfg->hp_pins[1], cfg->hp_pins[2], | 2861 | cfg->hp_pins[1], cfg->hp_pins[2], |
2768 | cfg->hp_pins[3], cfg->hp_pins[4]); | 2862 | cfg->hp_pins[3], cfg->hp_pins[4]); |
2863 | snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); | ||
2769 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 2864 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
2770 | " cd=0x%x, aux=0x%x\n", | 2865 | " cd=0x%x, aux=0x%x\n", |
2771 | cfg->input_pins[AUTO_PIN_MIC], | 2866 | cfg->input_pins[AUTO_PIN_MIC], |