drm/i915: Clear PPS port select when giving up the power sequencer

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>
This commit is contained in:
Ville Syrjälä 2014-10-16 21:29:51 +03:00 committed by Daniel Vetter
parent 9a42356b96
commit 83b8459756
1 changed files with 28 additions and 4 deletions

View 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, static void vlv_steal_power_sequencer(struct drm_device *dev,
enum pipe pipe) enum pipe pipe)
{ {
@ -2683,9 +2709,7 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
pipe_name(pipe), port_name(port)); pipe_name(pipe), port_name(port));
/* make sure vdd is off before we steal it */ /* make sure vdd is off before we steal it */
edp_panel_vdd_off_sync(intel_dp); vlv_detach_power_sequencer(intel_dp);
intel_dp->pps_pipe = INVALID_PIPE;
} }
} }
@ -2711,7 +2735,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
* we still have control of it. * we still have control of it.
*/ */
if (intel_dp->pps_pipe != INVALID_PIPE) 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 * We may be stealing the power