diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-04-26 06:13:25 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-05-14 08:49:17 -0400 |
commit | 9121947d696df7ea259c0102e449da9621b9cf92 (patch) | |
tree | d9924ab48c80ba91649c2e4bae8adc1b44ad11b2 /sound/pci/hda/hda_intel.c | |
parent | d9bbb4756dbc05764cebd0e3e2f49a56c9504e4d (diff) |
ALSA: hda - Check the dead HDMI audio controller by vga-switcheroo
When a discrete-GPU is disabled by the VGA switcheroo, the
corresponding HD-audio controller for HDMI output is also disabled.
Such a dead controller still appears in the PCI device list, but you
can't access properly any longer (even calling pci_read_config_*()
triggers Oops!) which leads the stall of the whole communication of
the driver.
This patch adds a check of graphics controller at the probe time to
see whether it's disabled by vga-switcheroo. If disabled, skip the
whole initialization of this controller.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43155
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a70d7e5443aa..06a4ad3e5cd2 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #endif | 53 | #endif |
54 | #include <sound/core.h> | 54 | #include <sound/core.h> |
55 | #include <sound/initval.h> | 55 | #include <sound/initval.h> |
56 | #include <linux/vgaarb.h> | ||
56 | #include "hda_codec.h" | 57 | #include "hda_codec.h" |
57 | 58 | ||
58 | 59 | ||
@@ -2494,6 +2495,45 @@ static int azx_dev_free(struct snd_device *device) | |||
2494 | } | 2495 | } |
2495 | 2496 | ||
2496 | /* | 2497 | /* |
2498 | * Check of disabled HDMI controller by vga-switcheroo | ||
2499 | */ | ||
2500 | static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci) | ||
2501 | { | ||
2502 | struct pci_dev *p; | ||
2503 | |||
2504 | /* check only discrete GPU */ | ||
2505 | switch (pci->vendor) { | ||
2506 | case PCI_VENDOR_ID_ATI: | ||
2507 | case PCI_VENDOR_ID_AMD: | ||
2508 | case PCI_VENDOR_ID_NVIDIA: | ||
2509 | if (pci->devfn == 1) { | ||
2510 | p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus), | ||
2511 | pci->bus->number, 0); | ||
2512 | if (p) { | ||
2513 | if ((p->class >> 8) == PCI_CLASS_DISPLAY_VGA) | ||
2514 | return p; | ||
2515 | pci_dev_put(p); | ||
2516 | } | ||
2517 | } | ||
2518 | break; | ||
2519 | } | ||
2520 | return NULL; | ||
2521 | } | ||
2522 | |||
2523 | static bool __devinit check_hdmi_disabled(struct pci_dev *pci) | ||
2524 | { | ||
2525 | bool vga_inactive = false; | ||
2526 | struct pci_dev *p = get_bound_vga(pci); | ||
2527 | |||
2528 | if (p) { | ||
2529 | if (vga_default_device() && p != vga_default_device()) | ||
2530 | vga_inactive = true; | ||
2531 | pci_dev_put(p); | ||
2532 | } | ||
2533 | return vga_inactive; | ||
2534 | } | ||
2535 | |||
2536 | /* | ||
2497 | * white/black-listing for position_fix | 2537 | * white/black-listing for position_fix |
2498 | */ | 2538 | */ |
2499 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { | 2539 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
@@ -2928,6 +2968,12 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2928 | return -ENOENT; | 2968 | return -ENOENT; |
2929 | } | 2969 | } |
2930 | 2970 | ||
2971 | if (check_hdmi_disabled(pci)) { | ||
2972 | snd_printk(KERN_INFO SFX | ||
2973 | "Inactive VGA controller; disabled audio, too\n"); | ||
2974 | goto out; | ||
2975 | } | ||
2976 | |||
2931 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); | 2977 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2932 | if (err < 0) { | 2978 | if (err < 0) { |
2933 | snd_printk(KERN_ERR SFX "Error creating card!\n"); | 2979 | snd_printk(KERN_ERR SFX "Error creating card!\n"); |
@@ -2984,8 +3030,10 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2984 | power_down_all_codecs(chip); | 3030 | power_down_all_codecs(chip); |
2985 | azx_notifier_register(chip); | 3031 | azx_notifier_register(chip); |
2986 | 3032 | ||
3033 | out: | ||
2987 | dev++; | 3034 | dev++; |
2988 | return err; | 3035 | return 0; |
3036 | |||
2989 | out_free: | 3037 | out_free: |
2990 | snd_card_free(card); | 3038 | snd_card_free(card); |
2991 | return err; | 3039 | return err; |
@@ -2993,7 +3041,9 @@ out_free: | |||
2993 | 3041 | ||
2994 | static void __devexit azx_remove(struct pci_dev *pci) | 3042 | static void __devexit azx_remove(struct pci_dev *pci) |
2995 | { | 3043 | { |
2996 | snd_card_free(pci_get_drvdata(pci)); | 3044 | struct snd_card *card = pci_get_drvdata(pci); |
3045 | if (card) | ||
3046 | snd_card_free(card); | ||
2997 | pci_set_drvdata(pci, NULL); | 3047 | pci_set_drvdata(pci, NULL); |
2998 | } | 3048 | } |
2999 | 3049 | ||