From 067bc412f078c89d32bcea53cfda51ebc5de19cc Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 3 Mar 2018 13:05:36 +0100 Subject: [PATCH 1/3] PCI: Expose Nvidia HDA controllers The integrated HDA controller on Nvidia GPUs can be hidden with a bit in the GPU's config space. Some laptop BIOSes hide it on boot and resume unless an external display is attached, rendering the HDA controller invisible and preventing its use if a display is attached later. Avoid by exposing it on device enumeration and resume. 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 flag in the GPU's Header Type register is cleared when the HDA controller is hidden and set if it's exposed, so reread the flag after exposing the HDA. According to Ilia Mirkin, the HDA controller is only present from MCP89 onward, so do not touch config space on older GPUs. This commit takes inspiration from an earlier patch by Daniel Drake. Link: https://devtalk.nvidia.com/default/topic/1024022 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75985 Cc: Aaron Plattner Cc: Peter Wu Cc: Ilia Mirkin Cc: Karol Herbst Cc: Daniel Drake Cc: Maik Freudenberg Signed-off-by: Lukas Wunner --- drivers/pci/quirks.c | 31 +++++++++++++++++++++++++++++++ include/linux/pci_ids.h | 1 + 2 files changed, 32 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2dfc60b51629..021456a9da3c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4867,3 +4867,34 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_AMD, PCI_ANY_ID, 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 hidden with a bit in the + * GPU's config space. Some laptop BIOSes hide it on boot and resume unless an + * external display is attached, rendering the HDA controller invisible and + * preventing its use if a display is attached later. Avoid by exposing it + * on device enumeration and resume. + * + * https://devtalk.nvidia.com/default/topic/1024022 + */ +static void quirk_nvidia_hda(struct pci_dev *gpu) +{ + u8 hdr_type; + u32 val; + + /* there was no integrated HDA controller before MCP89 */ + if (gpu->device < PCI_DEVICE_ID_NVIDIA_GEFORCE_320M) + return; + + /* bit 25 at offset 0x488 hides or exposes 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 exposed */ + 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); +DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(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 fa6af1e2b96b..2464b12f87d6 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.16.2