Revert "drm/i915: Make intel_display_suspend atomic, v2."
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index d4d7708b58a43979698627728bb74213b9311635..cc7fad9905b9a9a15fb485816f7f3cf6d84b37b1 100644 (file)
@@ -1698,7 +1698,7 @@ static int intel_num_dvo_pipes(struct drm_device *dev)
        int count = 0;
 
        for_each_intel_crtc(dev, crtc)
-               count += crtc->active &&
+               count += crtc->base.state->active &&
                        intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO);
 
        return count;
@@ -1779,7 +1779,7 @@ static void i9xx_disable_pll(struct intel_crtc *crtc)
        /* Disable DVO 2x clock on both PLLs if necessary */
        if (IS_I830(dev) &&
            intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO) &&
-           intel_num_dvo_pipes(dev) == 1) {
+           !intel_num_dvo_pipes(dev)) {
                I915_WRITE(DPLL(PIPE_B),
                           I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
                I915_WRITE(DPLL(PIPE_A),
@@ -4864,42 +4864,15 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
        return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
 }
 
-/*
- * This implements the workaround described in the "notes" section of the mode
- * set sequence documentation. When going from no pipes or single pipe to
- * multiple pipes, and planes are enabled after the pipe, we need to wait at
- * least 2 vblanks on the first pipe before enabling planes on the second pipe.
- */
-static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
-{
-       struct drm_device *dev = crtc->base.dev;
-       struct intel_crtc *crtc_it, *other_active_crtc = NULL;
-
-       /* We want to get the other_active_crtc only if there's only 1 other
-        * active crtc. */
-       for_each_intel_crtc(dev, crtc_it) {
-               if (!crtc_it->active || crtc_it == crtc)
-                       continue;
-
-               if (other_active_crtc)
-                       return;
-
-               other_active_crtc = crtc_it;
-       }
-       if (!other_active_crtc)
-               return;
-
-       intel_wait_for_vblank(dev, other_active_crtc->pipe);
-       intel_wait_for_vblank(dev, other_active_crtc->pipe);
-}
-
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
-       int pipe = intel_crtc->pipe;
+       int pipe = intel_crtc->pipe, hsw_workaround_pipe;
+       struct intel_crtc_state *pipe_config =
+               to_intel_crtc_state(crtc->state);
 
        if (WARN_ON(intel_crtc->active))
                return;
@@ -4976,7 +4949,11 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 
        /* If we change the relative order between pipe/planes enabling, we need
         * to change the workaround. */
-       haswell_mode_set_planes_workaround(intel_crtc);
+       hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
+       if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) {
+               intel_wait_for_vblank(dev, hsw_workaround_pipe);
+               intel_wait_for_vblank(dev, hsw_workaround_pipe);
+       }
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -6214,58 +6191,27 @@ 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.
  */
-int intel_display_suspend(struct drm_device *dev)
+void 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_i915_private *dev_priv = to_i915(dev);
        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);
-
-               ret = PTR_ERR_OR_ZERO(crtc_state);
-               if (ret)
-                       goto free;
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               enum intel_display_power_domain domain;
+               unsigned long domains;
 
-               if (!crtc_state->active)
+               if (!intel_crtc->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;
+               intel_crtc_disable_planes(crtc);
+               dev_priv->display.crtc_disable(crtc);
 
-                       return ret;
-               }
+               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;
        }
-
-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 */
@@ -12209,6 +12155,12 @@ intel_modeset_update_state(struct drm_atomic_state *state)
                WARN_ON(crtc->state->enable != intel_crtc_in_use(crtc));
 
                to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state);
+
+               /* Update hwmode for vblank functions */
+               if (crtc->state->active)
+                       crtc->hwmode = crtc->state->adjusted_mode;
+               else
+                       crtc->hwmode.crtc_clock = 0;
        }
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -12812,6 +12764,71 @@ static int intel_modeset_setup_plls(struct drm_atomic_state *state)
        return ret;
 }
 
+/*
+ * This implements the workaround described in the "notes" section of the mode
+ * set sequence documentation. When going from no pipes or single pipe to
+ * multiple pipes, and planes are enabled after the pipe, we need to wait at
+ * least 2 vblanks on the first pipe before enabling planes on the second pipe.
+ */
+static int haswell_mode_set_planes_workaround(struct drm_atomic_state *state)
+{
+       struct drm_crtc_state *crtc_state;
+       struct intel_crtc *intel_crtc;
+       struct drm_crtc *crtc;
+       struct intel_crtc_state *first_crtc_state = NULL;
+       struct intel_crtc_state *other_crtc_state = NULL;
+       enum pipe first_pipe = INVALID_PIPE, enabled_pipe = INVALID_PIPE;
+       int i;
+
+       /* look at all crtc's that are going to be enabled in during modeset */
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               intel_crtc = to_intel_crtc(crtc);
+
+               if (!crtc_state->active || !needs_modeset(crtc_state))
+                       continue;
+
+               if (first_crtc_state) {
+                       other_crtc_state = to_intel_crtc_state(crtc_state);
+                       break;
+               } else {
+                       first_crtc_state = to_intel_crtc_state(crtc_state);
+                       first_pipe = intel_crtc->pipe;
+               }
+       }
+
+       /* No workaround needed? */
+       if (!first_crtc_state)
+               return 0;
+
+       /* w/a possibly needed, check how many crtc's are already enabled. */
+       for_each_intel_crtc(state->dev, intel_crtc) {
+               struct intel_crtc_state *pipe_config;
+
+               pipe_config = intel_atomic_get_crtc_state(state, intel_crtc);
+               if (IS_ERR(pipe_config))
+                       return PTR_ERR(pipe_config);
+
+               pipe_config->hsw_workaround_pipe = INVALID_PIPE;
+
+               if (!pipe_config->base.active ||
+                   needs_modeset(&pipe_config->base))
+                       continue;
+
+               /* 2 or more enabled crtcs means no need for w/a */
+               if (enabled_pipe != INVALID_PIPE)
+                       return 0;
+
+               enabled_pipe = intel_crtc->pipe;
+       }
+
+       if (enabled_pipe != INVALID_PIPE)
+               first_crtc_state->hsw_workaround_pipe = enabled_pipe;
+       else if (other_crtc_state)
+               other_crtc_state->hsw_workaround_pipe = first_pipe;
+
+       return 0;
+}
+
 /* Code that should eventually be part of atomic_check() */
 static int intel_modeset_checks(struct drm_atomic_state *state)
 {
@@ -12835,7 +12852,14 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                        return ret;
        }
 
-       return intel_modeset_setup_plls(state);
+       ret = intel_modeset_setup_plls(state);
+       if (ret)
+               return ret;
+
+       if (IS_HASWELL(dev))
+               ret = haswell_mode_set_planes_workaround(state);
+
+       return ret;
 }
 
 static int
@@ -13603,6 +13627,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_crtc_state *crtc_state = intel_crtc->base.state;
        struct intel_plane *intel_plane;
        struct drm_plane *p;
        unsigned fb_bits = 0;
@@ -13646,7 +13671,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
        intel_runtime_pm_get(dev_priv);
 
        /* Perform vblank evasion around commit operation */
-       if (intel_crtc->active)
+       if (crtc_state->active && !needs_modeset(crtc_state))
                intel_crtc->atomic.evade =
                        intel_pipe_update_start(intel_crtc,
                                                &intel_crtc->atomic.start_vbl_count);
This page took 0.035543 seconds and 5 git commands to generate.