summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-15 08:45:33 +0100
committerTakashi Iwai <tiwai@suse.de>2013-01-15 08:49:09 +0100
commit52fd5cbc9bef6a2e20bfbdae771498ef97c67b34 (patch)
treeba12a8ae618f52bcc6f07c64e18a85cb79e1a6d2
parentae177c3fd0667df21b60bc8e031607de257e58e4 (diff)
ALSA: hda - Check pincap while parsing the configuration
Sometimes (or rather often) BIOS sets the pin default configurations obviously wrongly. Looking through these failures, one common pattern is to enable some dead pins that are usually marked as speaker pins. In such a case, we can skip them if the pins don't have the output capability. In this patch, add a check for the valid pin cap bit for each parsed pin, and filter out when it's invalid. The fix was originally suggested by Raymond Yau. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_auto_parser.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 33b3ece224c..a4810c7437b 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -97,6 +97,28 @@ static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
}
}
+/* check whether the given pin has a proper pin I/O capability bit */
+static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin,
+ unsigned int dev)
+{
+ unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
+
+ /* some old hardware don't return the proper pincaps */
+ if (!pincap)
+ return true;
+
+ switch (dev) {
+ case AC_JACK_LINE_OUT:
+ case AC_JACK_SPEAKER:
+ case AC_JACK_HP_OUT:
+ case AC_JACK_SPDIF_OUT:
+ case AC_JACK_DIG_OTHER_OUT:
+ return !!(pincap & AC_PINCAP_OUT);
+ default:
+ return !!(pincap & AC_PINCAP_IN);
+ }
+}
+
/*
* Parse all pin widgets and store the useful pin nids to cfg
*
@@ -164,6 +186,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
dev = AC_JACK_SPEAKER;
}
+ if (!check_pincap_validity(codec, nid, dev))
+ continue;
+
switch (dev) {
case AC_JACK_LINE_OUT:
seq = get_defcfg_sequence(def_conf);