Re: [PATCH 37/40] drm/i915: Fix eDP link training when switching pipes

Jesse Barnes
2014-06-30T21:51:31Z

On Sat, 28 Jun 2014 02:04:28 +0300
ville.syrjala@linux.intel.com wrote:

> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> When switching from one pipe to another, the power sequencer of the new
> pipe seems to need a bit of kicking to lock into the port. Even the vdd
> force bit doesn't work before the power sequencer has been sufficiently
> kicked, so this must be done even before any AUX transactions.
>
> This sequence has been found to do the trick:
> 1) enable port with idle pattern
> 2) enable the power sequencer
> 3) proceed with link training
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/intel_dp.c | 34 ++++++++++++++++++++++++++++++++--
> 1 file changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 65ab54c..07b0320 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2010,6 +2010,37 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
> mutex_unlock(&dev_priv->dpio_lock);
> }
>
> +static void intel_edp_init_train(struct intel_dp *intel_dp)
> +{
> + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> + struct drm_device *dev = intel_dig_port->base.base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (!is_edp(intel_dp))
> + return;
> +
> + /*
> + * Need to enable the port with idle pattern to allow the power
> + * sequencer to lock into the port. Otherwise the power sequencer
> + * (including vdd force bit!) doesn't work on this port.
> + */
> + if (IS_VALLEYVIEW(dev)) {
> + intel_dp->DP |= DP_PORT_EN;
> +
> + if (IS_CHERRYVIEW(dev))
> + intel_dp->DP &= ~DP_LINK_TRAIN_MASK_CHV;
> + else
> + intel_dp->DP &= ~DP_LINK_TRAIN_MASK;
> + intel_dp->DP |= DP_LINK_TRAIN_PAT_IDLE;
> +
> + I915_WRITE(intel_dp->output_reg, intel_dp->DP);
> + POSTING_READ(intel_dp->output_reg);
> + }
> +
> + intel_edp_panel_on(intel_dp);
> + edp_panel_vdd_off(intel_dp, true);
> +}
> +
> static void intel_enable_dp(struct intel_encoder *encoder)
> {
> struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -2021,10 +2052,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
> return;
>
> intel_edp_panel_vdd_on(intel_dp);
> + intel_edp_init_train(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);
> - edp_panel_vdd_off(intel_dp, true);
> intel_dp_complete_link_train(intel_dp);
> intel_dp_stop_link_train(intel_dp);
> }

Yeah I think this matches the doc too. I never pushed this change
because I could never find anything that it actually fixed.

I guess you have something now though!

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

--
Jesse Barnes, Intel Open Source Technology Center