From: Maarten Lankhorst Date: Mon, 1 Jun 2015 10:50:05 +0000 (+0200) Subject: drm/i915: Make intel_display_suspend atomic, v2. X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=06ea0b0897db906c5616f660a34b54d92f7d09cf;p=openwrt%2Fstaging%2Fblogic.git drm/i915: Make intel_display_suspend atomic, v2. 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. Calling intel_set_mode will cause intel_display_set_init_power to be called, make sure init_power gets set again afterwards. Changes since v1: - Fix to compile with v2 of the patch that adds intel_display_suspend. - Add intel_display_set_init_power. - Set return value to int to allow error checking. Signed-off-by: Maarten Lankhorst Reviewed-by: Matt Roper Signed-off-by: Jani Nikula --- diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 78ef0bb53c36..d3632c56fdf7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -634,6 +634,9 @@ static int i915_drm_suspend(struct drm_device *dev) intel_display_suspend(dev); drm_modeset_unlock_all(dev); + /* suspending displays will unsets init power */ + intel_display_set_init_power(dev_priv, true); + intel_dp_mst_suspend(dev); intel_runtime_pm_disable_interrupts(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 048a86857d0d..547d6db2a6ee 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6214,27 +6214,58 @@ static void i9xx_crtc_disable(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_i915_private *dev_priv = to_i915(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 intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum intel_display_power_domain domain; - unsigned long domains; + struct drm_crtc_state *crtc_state = + drm_atomic_get_crtc_state(state, crtc); - if (!intel_crtc->active) + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto free; + + if (!crtc_state->active) continue; - intel_crtc_disable_planes(crtc); - dev_priv->display.crtc_disable(crtc); + crtc_state->active = false; + crtc_mask |= 1 << drm_crtc_index(crtc); + } - domains = intel_crtc->enabled_power_domains; - for_each_power_domain(domain, domains) - intel_display_power_put(dev_priv, domain); - intel_crtc->enabled_power_domains = 0; + 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 */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7f8fa7f026aa..6d9c771747f9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -989,7 +989,7 @@ int intel_pch_rawclk(struct drm_device *dev); void intel_mark_busy(struct drm_device *dev); void intel_mark_idle(struct drm_device *dev); void intel_crtc_restore_mode(struct drm_crtc *crtc); -void intel_display_suspend(struct drm_device *dev); +int intel_display_suspend(struct drm_device *dev); int intel_crtc_control(struct drm_crtc *crtc, bool enable); void intel_crtc_update_dpms(struct drm_crtc *crtc); void intel_encoder_destroy(struct drm_encoder *encoder);