summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorMaarten Lankhorst2015-07-13 16:30:29 +0200
committerDaniel Vetter2015-07-14 18:09:56 +0200
commit70e0bd74b9a22ecaa25793bf4f461cf84a1f348a (patch)
tree93409c42e3cb3b8948b3b557a2fa62f2040e0775 /drivers/gpu/drm/i915/intel_display.c
parentdrm/i915: Always force a modeset in intel_crtc_restore_mode, v2. (diff)
downloadkernel-qcow2-linux-70e0bd74b9a22ecaa25793bf4f461cf84a1f348a.tar.gz
kernel-qcow2-linux-70e0bd74b9a22ecaa25793bf4f461cf84a1f348a.tar.xz
kernel-qcow2-linux-70e0bd74b9a22ecaa25793bf4f461cf84a1f348a.zip
drm/i915: Make intel_display_suspend atomic, try 2.
Calculate all state using a normal transition, but afterwards fudge crtc->state->active back to its old value. This should still allow state restore in setup_hw_state to work properly. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Stone <daniels@collabora.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f9ed3732f95f..4e64dae78360 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6225,12 +6225,58 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
* turn all crtc's off, but do not adjust state
* This has to be paired with a call to intel_modeset_setup_hw_state.
*/
-void intel_display_suspend(struct drm_device *dev)
+int intel_display_suspend(struct drm_device *dev)
{
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
+ struct drm_atomic_state *state;
struct drm_crtc *crtc;
+ unsigned crtc_mask = 0;
+ int ret = 0;
+
+ if (WARN_ON(!ctx))
+ return 0;
+
+ lockdep_assert_held(&ctx->ww_ctx);
+ state = drm_atomic_state_alloc(dev);
+ if (WARN_ON(!state))
+ return -ENOMEM;
+
+ state->acquire_ctx = ctx;
+ state->allow_modeset = true;
+
+ for_each_crtc(dev, crtc) {
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_crtc_state(state, crtc);
- for_each_crtc(dev, crtc)
- intel_crtc_disable_noatomic(crtc);
+ ret = PTR_ERR_OR_ZERO(crtc_state);
+ if (ret)
+ goto free;
+
+ if (!crtc_state->active)
+ continue;
+
+ crtc_state->active = false;
+ crtc_mask |= 1 << drm_crtc_index(crtc);
+ }
+
+ if (crtc_mask) {
+ ret = intel_set_mode(state);
+
+ if (!ret) {
+ for_each_crtc(dev, crtc)
+ if (crtc_mask & (1 << drm_crtc_index(crtc)))
+ crtc->state->active = true;
+
+ return ret;
+ }
+ }
+
+free:
+ if (ret)
+ DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+ drm_atomic_state_free(state);
+ return ret;
}
/* Master function to enable/disable CRTC and corresponding power wells */