]> git.karo-electronics.de Git - linux-beck.git/commitdiff
drm/i915: Clear PPS port select when giving up the power sequencer
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 16 Oct 2014 18:29:51 +0000 (21:29 +0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 4 Nov 2014 22:22:03 +0000 (23:22 +0100)
VLV gets confused if two power sequencers have the same port selected.
It would seem the port doesn't start up properly in the is case and
vlv_wait_port_ready() will fail as will the link training. Clearing the
port select in the PP_ON_DELAYS register fixes this problem.

CHV doesn't seem to need this, but it doesn't seem to hurt either so
let's just do it for both to keep the code between the platforms as
uniform as possible.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_dp.c

index 451dd253b5d61cdd8ae2e3258bcd4ec5d2729737..04d7bc730995ee232a17def716ded4ae7e4cc56c 100644 (file)
@@ -2657,6 +2657,32 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder)
        }
 }
 
+static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
+{
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private;
+       enum pipe pipe = intel_dp->pps_pipe;
+       int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
+
+       edp_panel_vdd_off_sync(intel_dp);
+
+       /*
+        * VLV seems to get confused when multiple power seqeuencers
+        * have the same port selected (even if only one has power/vdd
+        * enabled). The failure manifests as vlv_wait_port_ready() failing
+        * CHV on the other hand doesn't seem to mind having the same port
+        * selected in multiple power seqeuencers, but let's clear the
+        * port select always when logically disconnecting a power sequencer
+        * from a port.
+        */
+       DRM_DEBUG_KMS("detaching pipe %c power sequencer from port %c\n",
+                     pipe_name(pipe), port_name(intel_dig_port->port));
+       I915_WRITE(pp_on_reg, 0);
+       POSTING_READ(pp_on_reg);
+
+       intel_dp->pps_pipe = INVALID_PIPE;
+}
+
 static void vlv_steal_power_sequencer(struct drm_device *dev,
                                      enum pipe pipe)
 {
@@ -2683,9 +2709,7 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
                              pipe_name(pipe), port_name(port));
 
                /* make sure vdd is off before we steal it */
-               edp_panel_vdd_off_sync(intel_dp);
-
-               intel_dp->pps_pipe = INVALID_PIPE;
+               vlv_detach_power_sequencer(intel_dp);
        }
 }
 
@@ -2711,7 +2735,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
         * we still have control of it.
         */
        if (intel_dp->pps_pipe != INVALID_PIPE)
-               edp_panel_vdd_off_sync(intel_dp);
+               vlv_detach_power_sequencer(intel_dp);
 
        /*
         * We may be stealing the power