ALSA: hda/hdmi - fix vgaswitcheroo detection for AMD
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 22 Nov 2019 21:43:50 +0000 (16:43 -0500)
committerTakashi Iwai <tiwai@suse.de>
Tue, 26 Nov 2019 15:53:51 +0000 (16:53 +0100)
Only enable the vga_switcheroo logic on systems with the
ATPX ACPI method.  This logic is not needed for asics
that are not part of a PX (PowerXpress)/HG (Hybrid Graphics)
platform.

Reviewed-by: Takashi Iwai <tiwai@suse.de>
Acked-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://lore.kernel.org/r/20191122214353.582899-2-alexander.deucher@amd.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_intel.c

index e76a0bb6d3cfb611dd37aa4a955f49e539835288..ff098957e30fd053e7c3640d326ecf81a2694269 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/clocksource.h>
 #include <linux/time.h>
 #include <linux/completion.h>
+#include <linux/acpi.h>
 
 #ifdef CONFIG_X86
 /* for snoop control */
@@ -1401,6 +1402,34 @@ static int azx_dev_free(struct snd_device *device)
 }
 
 #ifdef SUPPORT_VGA_SWITCHEROO
+#ifdef CONFIG_ACPI
+/* ATPX is in the integrated GPU's namespace */
+static bool atpx_present(void)
+{
+       struct pci_dev *pdev = NULL;
+       acpi_handle dhandle, atpx_handle;
+       acpi_status status;
+
+       while ((pdev = pci_get_class(PCI_BASE_CLASS_DISPLAY << 16, pdev)) != NULL) {
+               dhandle = ACPI_HANDLE(&pdev->dev);
+               if (dhandle) {
+                       status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+                       if (!ACPI_FAILURE(status)) {
+                               pci_dev_put(pdev);
+                               return true;
+                       }
+               }
+               pci_dev_put(pdev);
+       }
+       return false;
+}
+#else
+static bool atpx_present(void)
+{
+       return false;
+}
+#endif
+
 /*
  * Check of disabled HDMI controller by vga_switcheroo
  */
@@ -1412,6 +1441,22 @@ static struct pci_dev *get_bound_vga(struct pci_dev *pci)
        switch (pci->vendor) {
        case PCI_VENDOR_ID_ATI:
        case PCI_VENDOR_ID_AMD:
+               if (pci->devfn == 1) {
+                       p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
+                                                       pci->bus->number, 0);
+                       if (p) {
+                               /* ATPX is in the integrated GPU's ACPI namespace
+                                * rather than the dGPU's namespace. However,
+                                * the dGPU is the one who is involved in
+                                * vgaswitcheroo.
+                                */
+                               if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
+                                   atpx_present())
+                                       return p;
+                               pci_dev_put(p);
+                       }
+               }
+               break;
        case PCI_VENDOR_ID_NVIDIA:
                if (pci->devfn == 1) {
                        p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),