aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c117
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 */
768static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) 772u32 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 */
1023void 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 */
1040struct 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 */
1051int 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 */
1016int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, 1081int 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],