Commit e2c8b870 authored by Maarten Lankhorst's avatar Maarten Lankhorst

drm/i915: Use atomic helpers for suspend, v2.

Instead of duplicating the functionality now that we no longer need
to preserve dpll state we can move to using the upstream suspend helper.

Changes since v1:
- Call hw readout with all mutexes held.
- Rework intel_display_suspend to only assign modeset_restore_state
  on success.
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/56C2E686.5060803@linux.intel.comReviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
parent 1db6e2e7
...@@ -603,13 +603,7 @@ static int i915_drm_suspend(struct drm_device *dev) ...@@ -603,13 +603,7 @@ static int i915_drm_suspend(struct drm_device *dev)
intel_suspend_gt_powersave(dev); intel_suspend_gt_powersave(dev);
/*
* Disable CRTCs directly since we want to preserve sw state
* for _thaw. Also, power gate the CRTC power wells.
*/
drm_modeset_lock_all(dev);
intel_display_suspend(dev); intel_display_suspend(dev);
drm_modeset_unlock_all(dev);
intel_dp_mst_suspend(dev); intel_dp_mst_suspend(dev);
...@@ -764,9 +758,7 @@ static int i915_drm_resume(struct drm_device *dev) ...@@ -764,9 +758,7 @@ static int i915_drm_resume(struct drm_device *dev)
dev_priv->display.hpd_irq_setup(dev); dev_priv->display.hpd_irq_setup(dev);
spin_unlock_irq(&dev_priv->irq_lock); spin_unlock_irq(&dev_priv->irq_lock);
drm_modeset_lock_all(dev);
intel_display_resume(dev); intel_display_resume(dev);
drm_modeset_unlock_all(dev);
intel_dp_mst_resume(dev); intel_dp_mst_resume(dev);
......
...@@ -1848,6 +1848,7 @@ struct drm_i915_private { ...@@ -1848,6 +1848,7 @@ struct drm_i915_private {
enum modeset_restore modeset_restore; enum modeset_restore modeset_restore;
struct mutex modeset_restore_lock; struct mutex modeset_restore_lock;
struct drm_atomic_state *modeset_restore_state;
struct list_head vm_list; /* Global list of all address spaces */ struct list_head vm_list; /* Global list of all address spaces */
struct i915_gtt gtt; /* VM representing the global address space */ struct i915_gtt gtt; /* VM representing the global address space */
......
...@@ -6397,55 +6397,16 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) ...@@ -6397,55 +6397,16 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
*/ */
int 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_i915_private *dev_priv = to_i915(dev);
struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
struct drm_atomic_state *state; struct drm_atomic_state *state;
struct drm_crtc *crtc; int ret;
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);
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 = drm_atomic_commit(state);
if (!ret) {
for_each_crtc(dev, crtc)
if (crtc_mask & (1 << drm_crtc_index(crtc)))
crtc->state->active = true;
return ret;
}
}
free: state = drm_atomic_helper_suspend(dev);
ret = PTR_ERR_OR_ZERO(state);
if (ret) if (ret)
DRM_ERROR("Suspending crtc's failed with %i\n", ret); DRM_ERROR("Suspending crtc's failed with %i\n", ret);
drm_atomic_state_free(state); else
dev_priv->modeset_restore_state = state;
return ret; return ret;
} }
...@@ -15918,51 +15879,57 @@ intel_modeset_setup_hw_state(struct drm_device *dev) ...@@ -15918,51 +15879,57 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
void intel_display_resume(struct drm_device *dev) void intel_display_resume(struct drm_device *dev)
{ {
struct drm_atomic_state *state = drm_atomic_state_alloc(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_connector *conn; struct drm_atomic_state *state = dev_priv->modeset_restore_state;
struct intel_plane *plane; struct drm_modeset_acquire_ctx ctx;
struct drm_crtc *crtc;
int ret; int ret;
bool setup = false;
if (!state) dev_priv->modeset_restore_state = NULL;
return;
state->acquire_ctx = dev->mode_config.acquire_ctx; drm_modeset_acquire_init(&ctx, 0);
for_each_crtc(dev, crtc) { retry:
struct drm_crtc_state *crtc_state = ret = drm_modeset_lock_all_ctx(dev, &ctx);
drm_atomic_get_crtc_state(state, crtc);
ret = PTR_ERR_OR_ZERO(crtc_state); if (ret == 0 && !setup) {
if (ret) setup = true;
goto err;
/* force a restore */ intel_modeset_setup_hw_state(dev);
crtc_state->mode_changed = true; i915_redisable_vga(dev);
} }
for_each_intel_plane(dev, plane) { if (ret == 0 && state) {
ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(state, &plane->base)); struct drm_crtc_state *crtc_state;
if (ret) struct drm_crtc *crtc;
goto err; int i;
state->acquire_ctx = &ctx;
for_each_crtc_in_state(state, crtc, crtc_state, i) {
/*
* Force recalculation even if we restore
* current state. With fast modeset this may not result
* in a modeset when the state is compatible.
*/
crtc_state->mode_changed = true;
} }
for_each_intel_connector(dev, conn) { ret = drm_atomic_commit(state);
ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(state, &conn->base));
if (ret)
goto err;
} }
intel_modeset_setup_hw_state(dev); if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx);
goto retry;
}
i915_redisable_vga(dev); drm_modeset_drop_locks(&ctx);
ret = drm_atomic_commit(state); drm_modeset_acquire_fini(&ctx);
if (!ret)
return;
err: if (ret) {
DRM_ERROR("Restoring old state failed with %i\n", ret); DRM_ERROR("Restoring old state failed with %i\n", ret);
drm_atomic_state_free(state); drm_atomic_state_free(state);
}
} }
void intel_modeset_gem_init(struct drm_device *dev) void intel_modeset_gem_init(struct drm_device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment