drm/radeon: wire up a pci shutdown callback
[cascardo/linux.git] / drivers / gpu / drm / radeon / radeon_drv.c
index a455dc7..5fdd48c 100644 (file)
  *   2.43.0 - RADEON_INFO_GPU_RESET_COUNTER
  *   2.44.0 - SET_APPEND_CNT packet3 support
  *   2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI
+ *   2.46.0 - Add PFP_SYNC_ME support on evergreen
+ *   2.47.0 - Add UVD_NO_OP register support
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       45
+#define KMS_DRIVER_MINOR       47
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -162,9 +164,13 @@ void radeon_debugfs_cleanup(struct drm_minor *minor);
 #if defined(CONFIG_VGA_SWITCHEROO)
 void radeon_register_atpx_handler(void);
 void radeon_unregister_atpx_handler(void);
+bool radeon_has_atpx_dgpu_power_cntl(void);
+bool radeon_is_atpx_hybrid(void);
 #else
 static inline void radeon_register_atpx_handler(void) {}
 static inline void radeon_unregister_atpx_handler(void) {}
+static inline bool radeon_has_atpx_dgpu_power_cntl(void) { return false; }
+static inline bool radeon_is_atpx_hybrid(void) { return false; }
 #endif
 
 int radeon_no_wb;
@@ -304,6 +310,8 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 
 static struct drm_driver kms_driver;
 
+bool radeon_device_is_virtual(void);
+
 static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
 {
        struct apertures_struct *ap;
@@ -357,6 +365,16 @@ radeon_pci_remove(struct pci_dev *pdev)
        drm_put_dev(dev);
 }
 
+static void
+radeon_pci_shutdown(struct pci_dev *pdev)
+{
+       /* if we are running in a VM, make sure the device
+        * torn down properly on reboot/shutdown
+        */
+       if (radeon_device_is_virtual())
+               radeon_pci_remove(pdev);
+}
+
 static int radeon_pmops_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -368,6 +386,14 @@ static int radeon_pmops_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+       /* GPU comes up enabled by the bios on resume */
+       if (radeon_is_px(drm_dev)) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+       }
+
        return radeon_resume_kms(drm_dev, true, true);
 }
 
@@ -404,7 +430,10 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
        pci_save_state(pdev);
        pci_disable_device(pdev);
        pci_ignore_hotplug(pdev);
-       pci_set_power_state(pdev, PCI_D3cold);
+       if (radeon_is_atpx_hybrid())
+               pci_set_power_state(pdev, PCI_D3cold);
+       else if (!radeon_has_atpx_dgpu_power_cntl())
+               pci_set_power_state(pdev, PCI_D3hot);
        drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
 
        return 0;
@@ -421,7 +450,9 @@ static int radeon_pmops_runtime_resume(struct device *dev)
 
        drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 
-       pci_set_power_state(pdev, PCI_D0);
+       if (radeon_is_atpx_hybrid() ||
+           !radeon_has_atpx_dgpu_power_cntl())
+               pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
        ret = pci_enable_device(pdev);
        if (ret)
@@ -564,6 +595,7 @@ static struct pci_driver radeon_kms_pci_driver = {
        .id_table = pciidlist,
        .probe = radeon_pci_probe,
        .remove = radeon_pci_remove,
+       .shutdown = radeon_pci_shutdown,
        .driver.pm = &radeon_pm_ops,
 };