From 4b0ffeba41f8331791ec152856c94d7682538c52 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 3 Mar 2018 13:05:36 +0100 Subject: [PATCH] PCI: Enable power to Nvidia HDA controllers on device enumeration The integrated HDA controller on Nvidia GPUs can be powergated with a bit in the GPU's config space. Some laptop BIOSes power it off unless an external display is attached on boot, rendering the HDA controller invisible and preventing its use if a display is attached later. Avoid by enabling power to the HDA controller on device enumeration. The GPU and HDA controller are two functions of the same PCI device (VGA class device on function 0 and audio device on function 1). The multifunction bit in the GPU's config space is cleared when the HDA controller is powergated and set if it's on, so reinitialize the bit after enabling power. According to Ilia Mirkin, the HDA controller is only present from MCP89 onward, so do not touch config space on older GPUs. Link: https://devtalk.nvidia.com/default/topic/1024022 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75985 Cc: Aaron Plattner Cc: Ilia Mirkin Cc: Karol Herbst Cc: Daniel Drake Cc: Maik Freudenberg Signed-off-by: Lukas Wunner --- drivers/pci/quirks.c | 29 +++++++++++++++++++++++++++++ include/linux/pci_ids.h | 1 + 2 files changed, 30 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2dfc60b..e91af83 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4867,3 +4867,32 @@ static void quirk_gpu_hda(struct pci_dev *hda) PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda); DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda); + +/* + * The integrated HDA controller on Nvidia GPUs can be powergated with a bit + * in the GPU's config space. Some laptop BIOSes power it off unless an + * external display is attached on boot, rendering the HDA controller + * invisible and preventing its use if a display is attached later. + * Avoid by enabling power to the HDA controller on device enumeration. + * + * https://devtalk.nvidia.com/default/topic/1024022 + */ +static void quirk_nvidia_hda(struct pci_dev *gpu) +{ + u8 hdr_type; + u32 val; + + /* no HDA controller present before MCP89 */ + if (gpu->device < PCI_DEVICE_ID_NVIDIA_GEFORCE_320M) + return; + + /* bit 25 at 0x488 powergates the HDA controller */ + pci_read_config_dword(gpu, 0x488, &val); + pci_write_config_dword(gpu, 0x488, val | BIT(25)); + + /* the GPU becomes a multifunction device when the HDA is powered on */ + pci_read_config_byte(gpu, PCI_HEADER_TYPE, &hdr_type)); + gpu->multifunction = !!(hdr_type & BIT(7)); +} +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, + PCI_BASE_CLASS_DISPLAY, 16, quirk_nvidia_hda); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index fa6af1e..2464b12 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1324,6 +1324,7 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS 0x0752 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_320M 0x08A0 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA 0x0D85 -- 2.15.1