return crtc->config->cpu_transcoder;
 }
 
-static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
+static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv,
+                                   enum pipe pipe)
 {
        i915_reg_t reg = PIPEDSL(pipe);
        u32 line1, line2;
        msleep(5);
        line2 = I915_READ(reg) & line_mask;
 
-       return line1 == line2;
+       return line1 != line2;
+}
+
+static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
+
+       /* Wait for the display line to settle/start moving */
+       if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100))
+               DRM_ERROR("pipe %c scanline %s wait timed out\n",
+                         pipe_name(pipe), onoff(state));
+}
+
+static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc)
+{
+       wait_for_pipe_scanline_moving(crtc, false);
+}
+
+static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc)
+{
+       wait_for_pipe_scanline_moving(crtc, true);
 }
 
 /*
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
-       enum pipe pipe = crtc->pipe;
 
        if (INTEL_GEN(dev_priv) >= 4) {
                i915_reg_t reg = PIPECONF(cpu_transcoder);
                                            100))
                        WARN(1, "pipe_off wait timed out\n");
        } else {
-               /* Wait for the display line to settle */
-               if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
-                       WARN(1, "pipe_off wait timed out\n");
+               intel_wait_for_pipe_scanline_stopped(crtc);
        }
 }
 
        POSTING_READ(reg);
 
        /*
-        * Until the pipe starts DSL will read as 0, which would cause
-        * an apparent vblank timestamp jump, which messes up also the
-        * frame count when it's derived from the timestamps. So let's
-        * wait for the pipe to start properly before we call
-        * drm_crtc_vblank_on()
+        * Until the pipe starts PIPEDSL reads will return a stale value,
+        * which causes an apparent vblank timestamp jump when PIPEDSL
+        * resets to its proper value. That also messes up the frame count
+        * when it's derived from the timestamps. So let's wait for the
+        * pipe to start properly before we call drm_crtc_vblank_on()
         */
-       if (dev->max_vblank_count == 0 &&
-           wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
-               DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
+       if (dev->max_vblank_count == 0)
+               intel_wait_for_pipe_scanline_moving(crtc);
 }
 
 /**
 
 void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
+       struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+
        DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n",
                      pipe_name(pipe));
 
        I915_WRITE(PIPECONF(pipe), 0);
        POSTING_READ(PIPECONF(pipe));
 
-       if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
-               DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe));
+       intel_wait_for_pipe_scanline_stopped(crtc);
 
        I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS);
        POSTING_READ(DPLL(pipe));