drm/i915: Turn on panel power before doing aux transfers
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index 83d2f76cf3e2eb44ea49c93f146033c0c4db0346..8935c5113ea71f7841a2ba0fb29ec8b1c4a50f35 100644 (file)
@@ -375,9 +375,31 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
        return intel_dp->pps_pipe;
 }
 
+typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
+                              enum pipe pipe);
+
+static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
+                              enum pipe pipe)
+{
+       return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
+}
+
+static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
+                               enum pipe pipe)
+{
+       return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
+}
+
+static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
+                        enum pipe pipe)
+{
+       return true;
+}
+
 static enum pipe
-vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
-                                enum port port)
+vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
+                    enum port port,
+                    vlv_pipe_check pipe_check)
 {
        enum pipe pipe;
 
@@ -388,6 +410,9 @@ vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
                if (port_sel != PANEL_PORT_SELECT_VLV(port))
                        continue;
 
+               if (!pipe_check(dev_priv, pipe))
+                       continue;
+
                return pipe;
        }
 
@@ -406,7 +431,17 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
        lockdep_assert_held(&dev_priv->pps_mutex);
 
        /* try to find a pipe with this port selected */
-       intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
+       /* first pick one where the panel is on */
+       intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+                                                 vlv_pipe_has_pp_on);
+       /* didn't find one? pick one where vdd is on */
+       if (intel_dp->pps_pipe == INVALID_PIPE)
+               intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+                                                         vlv_pipe_has_vdd_on);
+       /* didn't find one? pick one with just the correct port */
+       if (intel_dp->pps_pipe == INVALID_PIPE)
+               intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+                                                         vlv_pipe_any);
 
        /* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
        if (intel_dp->pps_pipe == INVALID_PIPE) {
@@ -2339,10 +2374,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
                return;
 
        intel_edp_panel_vdd_on(intel_dp);
-       intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-       intel_dp_start_link_train(intel_dp);
        intel_edp_panel_on(intel_dp);
        intel_edp_panel_vdd_off(intel_dp, true);
+       intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+       intel_dp_start_link_train(intel_dp);
        intel_dp_complete_link_train(intel_dp);
        intel_dp_stop_link_train(intel_dp);
 }
This page took 0.028709 seconds and 5 git commands to generate.