drm/amdgpu: Enter low power state if CRTC active.
authorAndrey Grodzovsky <andrey.grodzovsky@amd.com>
Thu, 12 Dec 2019 22:04:41 +0000 (17:04 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 9 Mar 2020 17:50:52 +0000 (13:50 -0400)
CRTC in DPMS state off calls for low power state entry.
Support both atomic mode setting and pre-atomic mode setting.

v2: move comment

Acked-by: Feifei Xu <Feifei.Xu@amd.com>
Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c

index f31661f8f7d3bd606c7bebc083c570fcea50673b..8ea86ffdea0d8dfbcf860c67bc1cfc08d26885a8 100644 (file)
@@ -1299,24 +1299,55 @@ static int amdgpu_pmops_runtime_idle(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = drm_dev->dev_private;
-       struct drm_crtc *crtc;
+       /* we don't want the main rpm_idle to call suspend - we want to autosuspend */
+       int ret = 1;
 
        if (!adev->runpm) {
                pm_runtime_forbid(dev);
                return -EBUSY;
        }
 
-       list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
-               if (crtc->enabled) {
-                       DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
-                       return -EBUSY;
+       if (amdgpu_device_has_dc_support(adev)) {
+               struct drm_crtc *crtc;
+
+               drm_modeset_lock_all(drm_dev);
+
+               drm_for_each_crtc(crtc, drm_dev) {
+                       if (crtc->state->active) {
+                               ret = -EBUSY;
+                               break;
+                       }
                }
+
+               drm_modeset_unlock_all(drm_dev);
+
+       } else {
+               struct drm_connector *list_connector;
+               struct drm_connector_list_iter iter;
+
+               mutex_lock(&drm_dev->mode_config.mutex);
+               drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL);
+
+               drm_connector_list_iter_begin(drm_dev, &iter);
+               drm_for_each_connector_iter(list_connector, &iter) {
+                       if (list_connector->dpms ==  DRM_MODE_DPMS_ON) {
+                               ret = -EBUSY;
+                               break;
+                       }
+               }
+
+               drm_connector_list_iter_end(&iter);
+
+               drm_modeset_unlock(&drm_dev->mode_config.connection_mutex);
+               mutex_unlock(&drm_dev->mode_config.mutex);
        }
 
+       if (ret == -EBUSY)
+               DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
+
        pm_runtime_mark_last_busy(dev);
        pm_runtime_autosuspend(dev);
-       /* we don't want the main rpm_idle to call suspend - we want to autosuspend */
-       return 1;
+       return ret;
 }
 
 long amdgpu_drm_ioctl(struct file *filp,