Moves the PCI-specific portions of nouveau_pmops to NVKM, leaving the DRM pieces where they are. The NVKM functions are called through the the nvkm_device_pci_driver struct from DRM for now, but will be fully separated once the DRM driver is implemented on an auxiliary device. Signed-off-by: Ben Skeggs <bskeggs@xxxxxxxxxx> --- drivers/gpu/drm/nouveau/nouveau_acpi.h | 3 - drivers/gpu/drm/nouveau/nouveau_drm.c | 24 ++----- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 76 +++++++++++++++++++++++ 3 files changed, 80 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index be1b218cb921..b4c7ae78cedc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -5,13 +5,10 @@ #define ROM_BIOS_PAGE 4096 #if defined(CONFIG_ACPI) && defined(CONFIG_X86) -#include <device/acpi.h> -static inline void nouveau_switcheroo_optimus_dsm(void) { nvkm_acpi_switcheroo_set_powerdown(); } void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else -static inline void nouveau_switcheroo_optimus_dsm(void) {} static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } static inline void nouveau_acpi_video_register_backlight(void) {} diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 76eddf172bb5..aa54aee23814 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -901,11 +901,7 @@ nouveau_pmops_suspend(struct device *dev) if (ret) return ret; - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - udelay(200); - return 0; + return nvkm_device_pci_driver.driver.pm->suspend(dev); } int @@ -919,12 +915,9 @@ nouveau_pmops_resume(struct device *dev) drm->dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); + ret = nvkm_device_pci_driver.driver.pm->resume(dev); if (ret) return ret; - pci_set_master(pdev); ret = nouveau_do_resume(drm, false); @@ -973,12 +966,8 @@ nouveau_pmops_runtime_suspend(struct device *dev) return -EBUSY; } - nouveau_switcheroo_optimus_dsm(); ret = nouveau_do_suspend(drm, true); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_ignore_hotplug(pdev); - pci_set_power_state(pdev, PCI_D3cold); + ret = nvkm_device_pci_driver.driver.pm->runtime_suspend(dev); drm->dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; return ret; } @@ -995,12 +984,9 @@ nouveau_pmops_runtime_resume(struct device *dev) return -EBUSY; } - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); + ret = nvkm_device_pci_driver.driver.pm->runtime_resume(dev); if (ret) return ret; - pci_set_master(pdev); ret = nouveau_do_resume(drm, true); if (ret) { @@ -1008,8 +994,6 @@ nouveau_pmops_runtime_resume(struct device *dev) return ret; } - /* do magic */ - nvif_mask(&drm->device, 0x088488, (1 << 25), (1 << 25)); drm->dev->switch_power_state = DRM_SWITCH_POWER_ON; /* Monitors may have been connected / disconnected during suspend */ diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index d454d56a7909..a66cb9d474d5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1620,6 +1620,81 @@ nvkm_device_pci_func = { #include "nouveau_drv.h" +static int +nvkm_device_pci_pm_runtime_resume(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + + /* do magic */ + nvkm_mask(device, 0x088488, (1 << 25), (1 << 25)); + return 0; +} + +static int +nvkm_device_pci_pm_runtime_suspend(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + + nvkm_acpi_switcheroo_set_powerdown(); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_ignore_hotplug(pdev); + pci_set_power_state(pdev, PCI_D3cold); + return 0; +} + +static int +nvkm_device_pci_pm_resume(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + return 0; +} + +static int +nvkm_device_pci_pm_suspend(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + udelay(200); + return 0; +} + +static const struct dev_pm_ops +nvkm_device_pci_pm = { + .suspend = nvkm_device_pci_pm_suspend, + .resume = nvkm_device_pci_pm_resume, + .runtime_suspend = nvkm_device_pci_pm_runtime_suspend, + .runtime_resume = nvkm_device_pci_pm_runtime_resume, +}; + static void nvkm_device_pci_remove(struct pci_dev *dev) { @@ -1787,4 +1862,5 @@ struct pci_driver nvkm_device_pci_driver = { .probe = nvkm_device_pci_probe, .remove = nvkm_device_pci_remove, + .driver.pm = &nvkm_device_pci_pm, }; -- 2.44.0