aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2018-03-03 04:53:24 -0500
committerLukas Wunner <lukas@wunner.de>2018-03-13 17:58:09 -0400
commit07f4f97d7b4bf325d9f558c5b58230387e4e57e0 (patch)
treeb297cfbe775326e8874e0e160624c508c432223e
parent8948ca1a12c9a039361bbc3e4627064153971d57 (diff)
vga_switcheroo: Use device link for HDA controller
Back in 2013, runtime PM for GPUs with integrated HDA controller was introduced with commits 0d69704ae348 ("gpu/vga_switcheroo: add driver control power feature. (v3)") and 246efa4a072f ("snd/hda: add runtime suspend/resume on optimus support (v4)"). Briefly, the idea was that the HDA controller is forced on and off in unison with the GPU. The original code is mostly still in place even though it was never a 100% perfect solution: E.g. on access to the HDA controller, the GPU is powered up via vga_switcheroo_runtime_resume_hdmi_audio() but there are no provisions to keep it resumed until access to the HDA controller has ceased: The GPU autosuspends after 5 seconds, rendering the HDA controller inaccessible. Additionally, a kludge is required when hda_intel.c probes: It has to check whether the GPU is powered down (check_hdmi_disabled()) and defer probing if so. However in the meantime (in v4.10) the driver core has gained a feature called device links which promises to solve such issues in a clean way: It allows us to declare a dependency from the HDA controller (consumer) to the GPU (supplier). The PM core then automagically ensures that the GPU is runtime resumed as long as the HDA controller's ->probe hook is executed and whenever the HDA controller is accessed. By default, the HDA controller has a dependency on its parent, a PCIe Root Port. Adding a device link creates another dependency on its sibling: PCIe Root Port ^ ^ | | | | HDA ===> GPU The device link is not only used for runtime PM, it also guarantees that on system sleep, the HDA controller suspends before the GPU and resumes after the GPU, and on system shutdown the HDA controller's ->shutdown hook is executed before the one of the GPU. It is a complete solution. Using this functionality is as simple as calling device_link_add(), which results in a dmesg entry like this: pci 0000:01:00.1: Linked as a consumer to 0000:01:00.0 The code for the GPU-governed audio power management can thus be removed (except where it's still needed for legacy manual power control). The device link is added in a PCI quirk rather than in hda_intel.c. It is therefore legal for the GPU to runtime suspend to D3cold even if the HDA controller is not bound to a driver or if CONFIG_SND_HDA_INTEL is not enabled, for accesses to the HDA controller will cause the GPU to wake up regardless if they're occurring outside of hda_intel.c (think config space readout via sysfs). Contrary to the previous implementation, the HDA controller's power state is now self-governed, rather than GPU-governed, whereas the GPU's power state is no longer fully self-governed. (The HDA controller needs to runtime suspend before the GPU can.) It is thus crucial that runtime PM is always activated on the HDA controller even if CONFIG_SND_HDA_POWER_SAVE_DEFAULT is set to 0 (which is the default), lest the GPU stays awake. This is achieved by setting the auto_runtime_pm flag on every codec and the AZX_DCAPS_PM_RUNTIME flag on the HDA controller. A side effect is that power consumption might be reduced if the GPU is in use but the HDA controller is not, because the HDA controller is now allowed to go to D3hot. Before, it was forced to stay in D0 as long as the GPU was in use. (There is no reduction in power consumption on my Nvidia GK107, but there might be on other chips.) The code paths for legacy manual power control are adjusted such that runtime PM is disabled during power off, thereby preventing the PM core from resuming the HDA controller. Note that the device link is not only added on vga_switcheroo capable systems, but for *any* GPU with integrated HDA controller. The idea is that the HDA controller streams audio via connectors located on the GPU, so the GPU needs to be on for the HDA controller to do anything useful. This commit implicitly fixes an unbalanced runtime PM ref upon unbind of hda_intel.c: On ->probe, a runtime PM ref was previously released under the condition "azx_has_pm_runtime(chip) || hda->use_vga_switcheroo", but on ->remove a runtime PM ref was only acquired under the first of those conditions. Thus, binding and unbinding the driver twice on a vga_switcheroo capable system caused the runtime PM refcount to drop below zero. The issue is resolved because the AZX_DCAPS_PM_RUNTIME flag is now always set if use_vga_switcheroo is true. For more information on device links please refer to: https://www.kernel.org/doc/html/latest/driver-api/device_link.html Documentation/driver-api/device_link.rst Cc: Dave Airlie <airlied@redhat.com> Cc: Ben Skeggs <bskeggs@redhat.com> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Reviewed-by: Peter Wu <peter@lekensteyn.nl> Tested-by: Kai Heng Feng <kai.heng.feng@canonical.com> # AMD PowerXpress Tested-by: Mike Lothian <mike@fireburn.co.uk> # AMD PowerXpress Tested-by: Denis Lisov <dennis.lissov@gmail.com> # Nvidia Optimus Tested-by: Peter Wu <peter@lekensteyn.nl> # Nvidia Optimus Tested-by: Lukas Wunner <lukas@wunner.de> # MacBook Pro Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: https://patchwork.freedesktop.org/patch/msgid/51bd38360ff502a8c42b1ebf4405ee1d3f27118d.1520068884.git.lukas@wunner.de
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c2
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c115
-rw-r--r--drivers/pci/quirks.c39
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/vga_switcheroo.h6
-rw-r--r--include/sound/hdaudio.h3
-rw-r--r--sound/pci/hda/hda_intel.c36
-rw-r--r--sound/pci/hda/hda_intel.h3
10 files changed, 73 insertions, 136 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 50afcf65181a..ba4335fd4f65 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -720,7 +720,6 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
720 720
721 drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 721 drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
722 drm_kms_helper_poll_disable(drm_dev); 722 drm_kms_helper_poll_disable(drm_dev);
723 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
724 723
725 ret = amdgpu_device_suspend(drm_dev, false, false); 724 ret = amdgpu_device_suspend(drm_dev, false, false);
726 pci_save_state(pdev); 725 pci_save_state(pdev);
@@ -757,7 +756,6 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
757 756
758 ret = amdgpu_device_resume(drm_dev, false, false); 757 ret = amdgpu_device_resume(drm_dev, false, false);
759 drm_kms_helper_poll_enable(drm_dev); 758 drm_kms_helper_poll_enable(drm_dev);
760 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
761 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; 759 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
762 return 0; 760 return 0;
763} 761}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 3e293029e3a6..6959951d45d6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -856,7 +856,6 @@ nouveau_pmops_runtime_suspend(struct device *dev)
856 } 856 }
857 857
858 drm_kms_helper_poll_disable(drm_dev); 858 drm_kms_helper_poll_disable(drm_dev);
859 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
860 nouveau_switcheroo_optimus_dsm(); 859 nouveau_switcheroo_optimus_dsm();
861 ret = nouveau_do_suspend(drm_dev, true); 860 ret = nouveau_do_suspend(drm_dev, true);
862 pci_save_state(pdev); 861 pci_save_state(pdev);
@@ -891,7 +890,6 @@ nouveau_pmops_runtime_resume(struct device *dev)
891 890
892 /* do magic */ 891 /* do magic */
893 nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25)); 892 nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
894 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
895 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; 893 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
896 894
897 /* Monitors may have been connected / disconnected during suspend */ 895 /* Monitors may have been connected / disconnected during suspend */
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 31dd04f6baa1..b28288a781ef 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -415,7 +415,6 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
415 415
416 drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 416 drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
417 drm_kms_helper_poll_disable(drm_dev); 417 drm_kms_helper_poll_disable(drm_dev);
418 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
419 418
420 ret = radeon_suspend_kms(drm_dev, false, false, false); 419 ret = radeon_suspend_kms(drm_dev, false, false, false);
421 pci_save_state(pdev); 420 pci_save_state(pdev);
@@ -452,7 +451,6 @@ static int radeon_pmops_runtime_resume(struct device *dev)
452 451
453 ret = radeon_resume_kms(drm_dev, false, false); 452 ret = radeon_resume_kms(drm_dev, false, false);
454 drm_kms_helper_poll_enable(drm_dev); 453 drm_kms_helper_poll_enable(drm_dev);
455 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
456 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; 454 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
457 return 0; 455 return 0;
458} 456}
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 2488af797020..4ee0ed642386 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -105,8 +105,7 @@
105 * @list: client list 105 * @list: client list
106 * 106 *
107 * Registered client. A client can be either a GPU or an audio device on a GPU. 107 * Registered client. A client can be either a GPU or an audio device on a GPU.
108 * For audio clients, the @fb_info, @active and @driver_power_control members 108 * For audio clients, the @fb_info and @active members are bogus.
109 * are bogus.
110 */ 109 */
111struct vga_switcheroo_client { 110struct vga_switcheroo_client {
112 struct pci_dev *pdev; 111 struct pci_dev *pdev;
@@ -332,8 +331,8 @@ EXPORT_SYMBOL(vga_switcheroo_register_client);
332 * @ops: client callbacks 331 * @ops: client callbacks
333 * @id: client identifier 332 * @id: client identifier
334 * 333 *
335 * Register audio client (audio device on a GPU). The power state of the 334 * Register audio client (audio device on a GPU). The client is assumed
336 * client is assumed to be ON. Beforehand, vga_switcheroo_client_probe_defer() 335 * to use runtime PM. Beforehand, vga_switcheroo_client_probe_defer()
337 * shall be called to ensure that all prerequisites are met. 336 * shall be called to ensure that all prerequisites are met.
338 * 337 *
339 * Return: 0 on success, -ENOMEM on memory allocation error. 338 * Return: 0 on success, -ENOMEM on memory allocation error.
@@ -342,7 +341,7 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
342 const struct vga_switcheroo_client_ops *ops, 341 const struct vga_switcheroo_client_ops *ops,
343 enum vga_switcheroo_client_id id) 342 enum vga_switcheroo_client_id id)
344{ 343{
345 return register_client(pdev, ops, id | ID_BIT_AUDIO, false, false); 344 return register_client(pdev, ops, id | ID_BIT_AUDIO, false, true);
346} 345}
347EXPORT_SYMBOL(vga_switcheroo_register_audio_client); 346EXPORT_SYMBOL(vga_switcheroo_register_audio_client);
348 347
@@ -655,10 +654,8 @@ static void set_audio_state(enum vga_switcheroo_client_id id,
655 struct vga_switcheroo_client *client; 654 struct vga_switcheroo_client *client;
656 655
657 client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO); 656 client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO);
658 if (client) { 657 if (client)
659 client->ops->set_gpu_state(client->pdev, state); 658 client->ops->set_gpu_state(client->pdev, state);
660 client->pwr_state = state;
661 }
662} 659}
663 660
664/* stage one happens before delay */ 661/* stage one happens before delay */
@@ -953,10 +950,6 @@ EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
953 * Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel 950 * Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel
954 * command line disables it. 951 * command line disables it.
955 * 952 *
956 * When the driver decides to power up or down, it notifies vga_switcheroo
957 * thereof so that it can power the audio device on the GPU up or down.
958 * This is achieved by vga_switcheroo_set_dynamic_switch().
959 *
960 * After the GPU has been suspended, the handler needs to be called to cut 953 * After the GPU has been suspended, the handler needs to be called to cut
961 * power to the GPU. Likewise it needs to reinstate power before the GPU 954 * power to the GPU. Likewise it needs to reinstate power before the GPU
962 * can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(), 955 * can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(),
@@ -964,8 +957,9 @@ EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
964 * calls to the handler. 957 * calls to the handler.
965 * 958 *
966 * When the audio device resumes, the GPU needs to be woken. This is achieved 959 * When the audio device resumes, the GPU needs to be woken. This is achieved
967 * by vga_switcheroo_init_domain_pm_optimus_hdmi_audio(), which augments the 960 * by a PCI quirk which calls device_link_add() to declare a dependency on the
968 * audio device's resume function. 961 * GPU. That way, the GPU is kept awake whenever and as long as the audio
962 * device is in use.
969 * 963 *
970 * On muxed machines, if the mux is initially switched to the discrete GPU, 964 * On muxed machines, if the mux is initially switched to the discrete GPU,
971 * the user ends up with a black screen when the GPU powers down after boot. 965 * the user ends up with a black screen when the GPU powers down after boot.
@@ -991,33 +985,6 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev,
991 vgasr_priv.handler->power_state(client->id, state); 985 vgasr_priv.handler->power_state(client->id, state);
992} 986}
993 987
994/**
995 * vga_switcheroo_set_dynamic_switch() - helper for driver power control
996 * @pdev: client pci device
997 * @dynamic: new power state
998 *
999 * Helper for GPUs whose power state is controlled by the driver's runtime pm.
1000 * When the driver decides to power up or down, it notifies vga_switcheroo
1001 * thereof using this helper so that it can power the audio device on the GPU
1002 * up or down.
1003 */
1004void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
1005 enum vga_switcheroo_state dynamic)
1006{
1007 struct vga_switcheroo_client *client;
1008
1009 mutex_lock(&vgasr_mutex);
1010 client = find_client_from_pci(&vgasr_priv.clients, pdev);
1011 if (!client || !client->driver_power_control) {
1012 mutex_unlock(&vgasr_mutex);
1013 return;
1014 }
1015
1016 set_audio_state(client->id, dynamic);
1017 mutex_unlock(&vgasr_mutex);
1018}
1019EXPORT_SYMBOL(vga_switcheroo_set_dynamic_switch);
1020
1021/* switcheroo power domain */ 988/* switcheroo power domain */
1022static int vga_switcheroo_runtime_suspend(struct device *dev) 989static int vga_switcheroo_runtime_suspend(struct device *dev)
1023{ 990{
@@ -1089,69 +1056,3 @@ void vga_switcheroo_fini_domain_pm_ops(struct device *dev)
1089 dev_pm_domain_set(dev, NULL); 1056 dev_pm_domain_set(dev, NULL);
1090} 1057}
1091EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); 1058EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
1092
1093static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
1094{
1095 struct pci_dev *pdev = to_pci_dev(dev);
1096 struct vga_switcheroo_client *client;
1097 struct device *video_dev = NULL;
1098 int ret;
1099
1100 /* we need to check if we have to switch back on the video
1101 * device so the audio device can come back
1102 */
1103 mutex_lock(&vgasr_mutex);
1104 list_for_each_entry(client, &vgasr_priv.clients, list) {
1105 if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
1106 client_is_vga(client)) {
1107 video_dev = &client->pdev->dev;
1108 break;
1109 }
1110 }
1111 mutex_unlock(&vgasr_mutex);
1112
1113 if (video_dev) {
1114 ret = pm_runtime_get_sync(video_dev);
1115 if (ret && ret != 1)
1116 return ret;
1117 }
1118 ret = dev->bus->pm->runtime_resume(dev);
1119
1120 /* put the reference for the gpu */
1121 if (video_dev) {
1122 pm_runtime_mark_last_busy(video_dev);
1123 pm_runtime_put_autosuspend(video_dev);
1124 }
1125 return ret;
1126}
1127
1128/**
1129 * vga_switcheroo_init_domain_pm_optimus_hdmi_audio() - helper for driver
1130 * power control
1131 * @dev: audio client device
1132 * @domain: power domain
1133 *
1134 * Helper for GPUs whose power state is controlled by the driver's runtime pm.
1135 * When the audio device resumes, the GPU needs to be woken. This helper
1136 * augments the audio device's resume function to do that.
1137 *
1138 * Return: 0 on success, -EINVAL if no power management operations are
1139 * defined for this device.
1140 */
1141int
1142vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev,
1143 struct dev_pm_domain *domain)
1144{
1145 /* copy over all the bus versions */
1146 if (dev->bus && dev->bus->pm) {
1147 domain->ops = *dev->bus->pm;
1148 domain->ops.runtime_resume =
1149 vga_switcheroo_runtime_resume_hdmi_audio;
1150
1151 dev_pm_domain_set(dev, domain);
1152 return 0;
1153 }
1154 dev_pm_domain_set(dev, NULL);
1155 return -EINVAL;
1156}
1157EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index fc734014206f..ec582d37c189 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -26,6 +26,7 @@
26#include <linux/ktime.h> 26#include <linux/ktime.h>
27#include <linux/mm.h> 27#include <linux/mm.h>
28#include <linux/platform_data/x86/apple.h> 28#include <linux/platform_data/x86/apple.h>
29#include <linux/pm_runtime.h>
29#include <asm/dma.h> /* isa_dma_bridge_buggy */ 30#include <asm/dma.h> /* isa_dma_bridge_buggy */
30#include "pci.h" 31#include "pci.h"
31 32
@@ -4832,3 +4833,41 @@ static void quirk_fsl_no_msi(struct pci_dev *pdev)
4832 pdev->no_msi = 1; 4833 pdev->no_msi = 1;
4833} 4834}
4834DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi); 4835DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi);
4836
4837/*
4838 * GPUs with integrated HDA controller for streaming audio to attached displays
4839 * need a device link from the HDA controller (consumer) to the GPU (supplier)
4840 * so that the GPU is powered up whenever the HDA controller is accessed.
4841 * The GPU and HDA controller are functions 0 and 1 of the same PCI device.
4842 * The device link stays in place until shutdown (or removal of the PCI device
4843 * if it's hotplugged). Runtime PM is allowed by default on the HDA controller
4844 * to prevent it from permanently keeping the GPU awake.
4845 */
4846static void quirk_gpu_hda(struct pci_dev *hda)
4847{
4848 struct pci_dev *gpu;
4849
4850 if (PCI_FUNC(hda->devfn) != 1)
4851 return;
4852
4853 gpu = pci_get_domain_bus_and_slot(pci_domain_nr(hda->bus),
4854 hda->bus->number,
4855 PCI_DEVFN(PCI_SLOT(hda->devfn), 0));
4856 if (!gpu || (gpu->class >> 16) != PCI_BASE_CLASS_DISPLAY) {
4857 pci_dev_put(gpu);
4858 return;
4859 }
4860
4861 if (!device_link_add(&hda->dev, &gpu->dev,
4862 DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME))
4863 pci_err(hda, "cannot link HDA to GPU %s\n", pci_name(gpu));
4864
4865 pm_runtime_allow(&hda->dev);
4866 pci_dev_put(gpu);
4867}
4868DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
4869 PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda);
4870DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_AMD, PCI_ANY_ID,
4871 PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda);
4872DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
4873 PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index a6b30667a331..a637a7d8ce5b 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -45,6 +45,7 @@
45#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400 45#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
46#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401 46#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
47#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402 47#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402
48#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
48#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480 49#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
49 50
50#define PCI_BASE_CLASS_MEMORY 0x05 51#define PCI_BASE_CLASS_MEMORY 0x05
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 960bedbdec87..77f0f0af3a71 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -168,11 +168,8 @@ int vga_switcheroo_process_delayed_switch(void);
168bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev); 168bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev);
169enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev); 169enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev);
170 170
171void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic);
172
173int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain); 171int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain);
174void vga_switcheroo_fini_domain_pm_ops(struct device *dev); 172void vga_switcheroo_fini_domain_pm_ops(struct device *dev);
175int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain);
176#else 173#else
177 174
178static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} 175static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
@@ -192,11 +189,8 @@ static inline int vga_switcheroo_process_delayed_switch(void) { return 0; }
192static inline bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) { return false; } 189static inline bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) { return false; }
193static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } 190static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; }
194 191
195static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) {}
196
197static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; } 192static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
198static inline void vga_switcheroo_fini_domain_pm_ops(struct device *dev) {} 193static inline void vga_switcheroo_fini_domain_pm_ops(struct device *dev) {}
199static inline int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
200 194
201#endif 195#endif
202#endif /* _LINUX_VGA_SWITCHEROO_H_ */ 196#endif /* _LINUX_VGA_SWITCHEROO_H_ */
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 68169e3749de..5b2ed12f58ce 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -227,9 +227,6 @@ struct hdac_io_ops {
227#define HDA_UNSOL_QUEUE_SIZE 64 227#define HDA_UNSOL_QUEUE_SIZE 64
228#define HDA_MAX_CODECS 8 /* limit by controller side */ 228#define HDA_MAX_CODECS 8 /* limit by controller side */
229 229
230/* HD Audio class code */
231#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
232
233/* 230/*
234 * CORB/RIRB 231 * CORB/RIRB
235 * 232 *
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c71dcacea807..ec4e6b829ee2 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1227,6 +1227,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
1227 struct snd_card *card = pci_get_drvdata(pci); 1227 struct snd_card *card = pci_get_drvdata(pci);
1228 struct azx *chip = card->private_data; 1228 struct azx *chip = card->private_data;
1229 struct hda_intel *hda = container_of(chip, struct hda_intel, chip); 1229 struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
1230 struct hda_codec *codec;
1230 bool disabled; 1231 bool disabled;
1231 1232
1232 wait_for_completion(&hda->probe_wait); 1233 wait_for_completion(&hda->probe_wait);
@@ -1251,8 +1252,12 @@ static void azx_vs_set_state(struct pci_dev *pci,
1251 dev_info(chip->card->dev, "%s via vga_switcheroo\n", 1252 dev_info(chip->card->dev, "%s via vga_switcheroo\n",
1252 disabled ? "Disabling" : "Enabling"); 1253 disabled ? "Disabling" : "Enabling");
1253 if (disabled) { 1254 if (disabled) {
1254 pm_runtime_put_sync_suspend(card->dev); 1255 list_for_each_codec(codec, &chip->bus) {
1255 azx_suspend(card->dev); 1256 pm_runtime_suspend(hda_codec_dev(codec));
1257 pm_runtime_disable(hda_codec_dev(codec));
1258 }
1259 pm_runtime_suspend(card->dev);
1260 pm_runtime_disable(card->dev);
1256 /* when we get suspended by vga_switcheroo we end up in D3cold, 1261 /* when we get suspended by vga_switcheroo we end up in D3cold,
1257 * however we have no ACPI handle, so pci/acpi can't put us there, 1262 * however we have no ACPI handle, so pci/acpi can't put us there,
1258 * put ourselves there */ 1263 * put ourselves there */
@@ -1263,9 +1268,12 @@ static void azx_vs_set_state(struct pci_dev *pci,
1263 "Cannot lock devices!\n"); 1268 "Cannot lock devices!\n");
1264 } else { 1269 } else {
1265 snd_hda_unlock_devices(&chip->bus); 1270 snd_hda_unlock_devices(&chip->bus);
1266 pm_runtime_get_noresume(card->dev);
1267 chip->disabled = false; 1271 chip->disabled = false;
1268 azx_resume(card->dev); 1272 pm_runtime_enable(card->dev);
1273 list_for_each_codec(codec, &chip->bus) {
1274 pm_runtime_enable(hda_codec_dev(codec));
1275 pm_runtime_resume(hda_codec_dev(codec));
1276 }
1269 } 1277 }
1270 } 1278 }
1271} 1279}
@@ -1295,6 +1303,7 @@ static void init_vga_switcheroo(struct azx *chip)
1295 dev_info(chip->card->dev, 1303 dev_info(chip->card->dev,
1296 "Handle vga_switcheroo audio client\n"); 1304 "Handle vga_switcheroo audio client\n");
1297 hda->use_vga_switcheroo = 1; 1305 hda->use_vga_switcheroo = 1;
1306 chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
1298 pci_dev_put(p); 1307 pci_dev_put(p);
1299 } 1308 }
1300} 1309}
@@ -1320,9 +1329,6 @@ static int register_vga_switcheroo(struct azx *chip)
1320 return err; 1329 return err;
1321 hda->vga_switcheroo_registered = 1; 1330 hda->vga_switcheroo_registered = 1;
1322 1331
1323 /* register as an optimus hdmi audio power domain */
1324 vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
1325 &hda->hdmi_pm_domain);
1326 return 0; 1332 return 0;
1327} 1333}
1328#else 1334#else
@@ -1351,10 +1357,8 @@ static int azx_free(struct azx *chip)
1351 if (use_vga_switcheroo(hda)) { 1357 if (use_vga_switcheroo(hda)) {
1352 if (chip->disabled && hda->probe_continued) 1358 if (chip->disabled && hda->probe_continued)
1353 snd_hda_unlock_devices(&chip->bus); 1359 snd_hda_unlock_devices(&chip->bus);
1354 if (hda->vga_switcheroo_registered) { 1360 if (hda->vga_switcheroo_registered)
1355 vga_switcheroo_unregister_client(chip->pci); 1361 vga_switcheroo_unregister_client(chip->pci);
1356 vga_switcheroo_fini_domain_pm_ops(chip->card->dev);
1357 }
1358 } 1362 }
1359 1363
1360 if (bus->chip_init) { 1364 if (bus->chip_init) {
@@ -2197,6 +2201,7 @@ static int azx_probe_continue(struct azx *chip)
2197 struct hda_intel *hda = container_of(chip, struct hda_intel, chip); 2201 struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
2198 struct hdac_bus *bus = azx_bus(chip); 2202 struct hdac_bus *bus = azx_bus(chip);
2199 struct pci_dev *pci = chip->pci; 2203 struct pci_dev *pci = chip->pci;
2204 struct hda_codec *codec;
2200 int dev = chip->dev_index; 2205 int dev = chip->dev_index;
2201 int err; 2206 int err;
2202 2207
@@ -2278,8 +2283,17 @@ static int azx_probe_continue(struct azx *chip)
2278 2283
2279 chip->running = 1; 2284 chip->running = 1;
2280 azx_add_card_list(chip); 2285 azx_add_card_list(chip);
2286
2287 /*
2288 * The discrete GPU cannot power down unless the HDA controller runtime
2289 * suspends, so activate runtime PM on codecs even if power_save == 0.
2290 */
2291 if (use_vga_switcheroo(hda))
2292 list_for_each_codec(codec, &chip->bus)
2293 codec->auto_runtime_pm = 1;
2294
2281 snd_hda_set_power_save(&chip->bus, power_save * 1000); 2295 snd_hda_set_power_save(&chip->bus, power_save * 1000);
2282 if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo) 2296 if (azx_has_pm_runtime(chip))
2283 pm_runtime_put_autosuspend(&pci->dev); 2297 pm_runtime_put_autosuspend(&pci->dev);
2284 2298
2285out_free: 2299out_free:
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h
index ff0c4d617bc1..e3a3d318d2e5 100644
--- a/sound/pci/hda/hda_intel.h
+++ b/sound/pci/hda/hda_intel.h
@@ -40,9 +40,6 @@ struct hda_intel {
40 unsigned int vga_switcheroo_registered:1; 40 unsigned int vga_switcheroo_registered:1;
41 unsigned int init_failed:1; /* delayed init failed */ 41 unsigned int init_failed:1; /* delayed init failed */
42 42
43 /* secondary power domain for hdmi audio under vga device */
44 struct dev_pm_domain hdmi_pm_domain;
45
46 bool need_i915_power:1; /* the hda controller needs i915 power */ 43 bool need_i915_power:1; /* the hda controller needs i915 power */
47}; 44};
48 45