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.
Acked-by: Evan Quan evan.quan@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com ---
v2: - check CONFIG_ACPI - fix pci ref logic
sound/pci/hda/hda_intel.c | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1e14d7270adf..ab6c4e7c468b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -35,6 +35,11 @@ #include <linux/clocksource.h> #include <linux/time.h> #include <linux/completion.h> +#ifdef SUPPORT_VGA_SWITCHEROO +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#endif +#endif
#ifdef CONFIG_X86 /* for snoop control */ @@ -1345,6 +1350,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 */ @@ -1356,6 +1389,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),