With this change we can (finally!) rip out a few of the temporary hacks
and clean up a few other things:
- Kill intel_crtc_prepare_encoders, now unused.
- Kill the hacks in the crtc_disable/enable functions to always call the
  encoder callbacks, we now always call the crtc functions with the right
  encoder -> crtc links.
- Also push down the crtc->enable, encoder and connector dpms state
  updates. Unfortunately we can't add a WARN in the crtc_disable
  callbacks to ensure that the crtc is always still enabled when
  disabling an output pipe - the crtc sanitizer of the hw readout path
  can hit this when it needs to disable an active pipe without any
  enabled outputs.
- Only call crtc->disable if the pipe is already enabled - again avoids
  running afoul of the new WARN.

v2: Copy&paste our own version of crtc_in_use, too.

v3: We need to update the dpms an encoder->connectors_active states,
too.

v4: I've forgotten to kill the unconditional encoder->disable calls in
the crtc_disable functions.

v5: Rip out leftover debug printk.

Signed-off-by: Daniel Vetter <daniel.vet...@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c |   85 +++++++++++++++++++---------------
 1 file changed, 47 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 6166708..99f4e55 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3220,10 +3220,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
        WARN_ON(!crtc->enabled);
 
-       /* XXX: For compatability with the crtc helper code, call the encoder's
-        * enable function unconditionally for now. */
        if (intel_crtc->active)
-               goto encoders;
+               return;
 
        intel_crtc->active = true;
        intel_update_watermarks(dev);
@@ -3271,7 +3269,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
        intel_crtc_update_cursor(crtc, true);
 
-encoders:
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
 
@@ -3289,14 +3286,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
        int plane = intel_crtc->plane;
        u32 reg, temp;
 
-       /* XXX: For compatability with the crtc helper code, call the encoder's
-        * disable function unconditionally for now. */
-       for_each_encoder_on_crtc(dev, crtc, encoder)
-               encoder->disable(encoder);
 
        if (!intel_crtc->active)
                return;
 
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               encoder->disable(encoder);
+
        intel_crtc_wait_for_pending_flips(crtc);
        drm_vblank_off(dev, pipe);
        intel_crtc_update_cursor(crtc, false);
@@ -3398,10 +3394,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
        WARN_ON(!crtc->enabled);
 
-       /* XXX: For compatability with the crtc helper code, call the encoder's
-        * enable function unconditionally for now. */
        if (intel_crtc->active)
-               goto encoders;
+               return;
 
        intel_crtc->active = true;
        intel_update_watermarks(dev);
@@ -3417,7 +3411,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_dpms_overlay(intel_crtc, true);
        intel_crtc_update_cursor(crtc, true);
 
-encoders:
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
 }
@@ -3431,14 +3424,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
 
-       /* XXX: For compatability with the crtc helper code, call the encoder's
-        * disable function unconditionally for now. */
-       for_each_encoder_on_crtc(dev, crtc, encoder)
-               encoder->disable(encoder);
 
        if (!intel_crtc->active)
                return;
 
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               encoder->disable(encoder);
+
        /* Give the overlay scaler a chance to disable if it's on this pipe */
        intel_crtc_wait_for_pending_flips(crtc);
        drm_vblank_off(dev, pipe);
@@ -6558,18 +6550,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder 
*encoder,
        return false;
 }
 
-static void
-intel_crtc_prepare_encoders(struct drm_device *dev)
-{
-       struct intel_encoder *encoder;
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) 
{
-               /* Disable unused encoders */
-               if (encoder->base.crtc == NULL)
-                       encoder->disable(encoder);
-       }
-}
-
 /**
  * intel_modeset_update_staged_output_state
  *
@@ -6742,6 +6722,18 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, 
unsigned *modeset_pipes,
        *prepare_pipes &= ~(*disable_pipes);
 }
 
+static bool intel_crtc_in_use(struct drm_crtc *crtc)
+{
+       struct drm_encoder *encoder;
+       struct drm_device *dev = crtc->dev;
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+               if (encoder->crtc == crtc)
+                       return true;
+
+       return false;
+}
+
 #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
        list_for_each_entry((intel_crtc), \
                            &(dev)->mode_config.crtc_list, \
@@ -6758,6 +6750,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
        struct drm_encoder_helper_funcs *encoder_funcs;
        struct drm_encoder *encoder;
        struct intel_crtc *intel_crtc;
+       struct drm_connector *connector;
        unsigned disable_pipes, prepare_pipes, modeset_pipes;
        bool ret = true;
 
@@ -6770,12 +6763,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
                intel_crtc_disable(&intel_crtc->base);
 
-       intel_modeset_commit_output_state(dev);
-
-       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
-                           base.head)
-               intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
-
        saved_hwmode = crtc->hwmode;
        saved_mode = crtc->mode;
 
@@ -6790,12 +6777,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
                if (IS_ERR(adjusted_mode)) {
                        return false;
                }
-
-               intel_crtc_prepare_encoders(dev);
        }
 
-       for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
-               dev_priv->display.crtc_disable(&intel_crtc->base);
+       for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
+               if (intel_crtc->base.enabled)
+                       dev_priv->display.crtc_disable(&intel_crtc->base);
+       }
 
        if (modeset_pipes) {
                crtc->mode = *mode;
@@ -6803,6 +6790,28 @@ bool intel_set_mode(struct drm_crtc *crtc,
                crtc->y = y;
        }
 
+       /* Only after disabling all output pipelines that will be changed can we
+        * update the the output configuration. */
+       intel_modeset_commit_output_state(dev);
+
+       /* Update computed state. */
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head) {
+               intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
+       }
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               if (!connector->encoder || !connector->encoder->crtc)
+                       continue;
+
+               intel_crtc = to_intel_crtc(connector->encoder->crtc);
+
+               if (prepare_pipes & (1 << intel_crtc->pipe))
+                       connector->dpms = DRM_MODE_DPMS_ON;
+
+               to_intel_encoder(connector->encoder)->connectors_active = true;
+       }
+
        /* Set up the DPLL and any encoders state that needs to adjust or depend
         * on the DPLL.
         */
-- 
1.7.10.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to