diff --git a/drivers/gpu/drm/nouveau/include/nvif/driverif.h b/drivers/gpu/drm/nouveau/include/nvif/driverif.h
index 638c72c1b580..e1d3ccc2128c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/driverif.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/driverif.h
@@ -538,6 +538,8 @@ struct nvif_device_impl {
 	u64 ram_size;
 	u64 ram_user;
 
+	bool runpm;
+
 	u64 (*time)(struct nvif_device_priv *);
 
 	struct {
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
index c9965934b0d5..3c11d3068ced 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
@@ -55,6 +55,12 @@ struct nvkm_device {
 		struct notifier_block nb;
 	} acpi;
 
+	enum {
+		NVKM_DEVICE_RUNPM_NONE = 0,
+		NVKM_DEVICE_RUNPM_V1,
+		NVKM_DEVICE_RUNPM_OPTIMUS,
+	} runpm;
+
 #define NVKM_LAYOUT_ONCE(type,data,ptr) data *ptr;
 #define NVKM_LAYOUT_INST(type,data,ptr,cnt) data *ptr[cnt];
 #include <core/layout.h>
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/module.h b/drivers/gpu/drm/nouveau/include/nvkm/core/module.h
index 5cf80e4deb90..fc42ace93a1c 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/module.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/module.h
@@ -5,4 +5,6 @@
 
 int __init nvkm_init(void);
 void __exit nvkm_exit(void);
+
+extern int nvkm_runpm;
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 0ac17da04819..52c4c3f58799 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -486,7 +486,7 @@ nouveau_drm_device_fini(struct nouveau_drm *drm)
 	struct drm_device *dev = drm->dev;
 	struct nouveau_cli *cli, *temp_cli;
 
-	if (nouveau_pmops_runtime()) {
+	if (nouveau_pmops_runtime(dev->dev)) {
 		pm_runtime_get_sync(dev->dev);
 		pm_runtime_forbid(dev->dev);
 	}
@@ -584,7 +584,7 @@ nouveau_drm_device_init(struct nouveau_drm *drm)
 	nouveau_dmem_init(drm);
 	nouveau_led_init(dev);
 
-	if (nouveau_pmops_runtime()) {
+	if (nouveau_pmops_runtime(dev->dev)) {
 		pm_runtime_use_autosuspend(dev->dev);
 		pm_runtime_set_autosuspend_delay(dev->dev, 5000);
 		pm_runtime_set_active(dev->dev);
@@ -1031,10 +1031,13 @@ nouveau_pmops_thaw(struct device *dev)
 }
 
 bool
-nouveau_pmops_runtime(void)
+nouveau_pmops_runtime(struct device *dev)
 {
+	struct nouveau_drm *drm = nouveau_drm(dev_get_drvdata(dev));
+
 	if (nouveau_runtime_pm == -1)
-		return nouveau_is_optimus() || nouveau_is_v1_dsm();
+		return drm->device.impl->runpm;
+
 	return nouveau_runtime_pm == 1;
 }
 
@@ -1045,7 +1048,7 @@ nouveau_pmops_runtime_suspend(struct device *dev)
 	struct nouveau_drm *drm = pci_get_drvdata(pdev);
 	int ret;
 
-	if (!nouveau_pmops_runtime()) {
+	if (!nouveau_pmops_runtime(dev)) {
 		pm_runtime_forbid(dev);
 		return -EBUSY;
 	}
@@ -1067,7 +1070,7 @@ nouveau_pmops_runtime_resume(struct device *dev)
 	struct nouveau_drm *drm = pci_get_drvdata(pdev);
 	int ret;
 
-	if (!nouveau_pmops_runtime()) {
+	if (!nouveau_pmops_runtime(dev)) {
 		pm_runtime_forbid(dev);
 		return -EBUSY;
 	}
@@ -1098,7 +1101,7 @@ nouveau_pmops_runtime_resume(struct device *dev)
 static int
 nouveau_pmops_runtime_idle(struct device *dev)
 {
-	if (!nouveau_pmops_runtime()) {
+	if (!nouveau_pmops_runtime(dev)) {
 		pm_runtime_forbid(dev);
 		return -EBUSY;
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 52589d5eab63..c2014a29891c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -324,7 +324,7 @@ nouveau_drm_use_coherent_gpu_mapping(struct nouveau_drm *drm)
 
 int nouveau_pmops_suspend(struct device *);
 int nouveau_pmops_resume(struct device *);
-bool nouveau_pmops_runtime(void);
+bool nouveau_pmops_runtime(struct device *);
 
 #include <nvkm/core/tegra.h>
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 53b332708061..1f5ccec025d7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -63,7 +63,7 @@ void
 nouveau_vga_init(struct nouveau_drm *drm)
 {
 	struct drm_device *dev = drm->dev;
-	bool runtime = nouveau_pmops_runtime();
+	bool runtime = nouveau_pmops_runtime(dev->dev);
 	struct pci_dev *pdev;
 
 	/* only relevant for PCI devices */
@@ -85,7 +85,7 @@ void
 nouveau_vga_fini(struct nouveau_drm *drm)
 {
 	struct drm_device *dev = drm->dev;
-	bool runtime = nouveau_pmops_runtime();
+	bool runtime = nouveau_pmops_runtime(dev->dev);
 	struct pci_dev *pdev;
 
 	/* only relevant for PCI devices */
diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c
index e48f3219f047..16e059866168 100644
--- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 #include <core/pci.h>
+#include <core/module.h>
+#include "acpi.h"
 #include "priv.h"
 
 struct nvkm_device_pci_device {
@@ -1704,5 +1706,15 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
 	}
 
 	*pdevice = &pdev->device;
+
+	if (nvkm_runpm) {
+		if (!nouveau_dsm_priv.optimus_detected) {
+			if (nouveau_dsm_priv.dsm_detected)
+				device->runpm = NVKM_DEVICE_RUNPM_V1;
+		} else {
+			device->runpm = NVKM_DEVICE_RUNPM_OPTIMUS;
+		}
+	}
+
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/device/user.c b/drivers/gpu/drm/nouveau/nvkm/device/user.c
index 4ffcd7c6e0b9..a510d24019f6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/device/user.c
@@ -393,6 +393,8 @@ nvkm_udevice_new(struct nvkm_device *device,
 	if (device->imem && udev->impl.ram_size > 0)
 		udev->impl.ram_user = udev->impl.ram_user - device->imem->reserved;
 
+	udev->impl.runpm = (device->runpm != NVKM_DEVICE_RUNPM_NONE);
+
 	if (device->vfn) {
 		udev->impl.usermode.oclass = device->vfn->user.base.oclass;
 		udev->impl.usermode.new = nvkm_udevice_usermode_new;
diff --git a/drivers/gpu/drm/nouveau/nvkm/module.c b/drivers/gpu/drm/nouveau/nvkm/module.c
index cf71c68af89a..7a56ef8c3b6b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/module.c
+++ b/drivers/gpu/drm/nouveau/nvkm/module.c
@@ -22,6 +22,8 @@
 #include <core/module.h>
 #include <device/acpi.h>
 
+int nvkm_runpm = -1;
+
 void __exit
 nvkm_exit(void)
 {
