All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jesse Barnes <jbarnes@virtuousgeek.org>
To: ville.syrjala@linux.intel.com, intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 08/12] drm/i915: Fix the IBX transcoder B workarounds
Date: Thu, 21 May 2015 12:23:21 -0700	[thread overview]
Message-ID: <555E30A9.2040206@virtuousgeek.org> (raw)
In-Reply-To: <1430835458-11187-9-git-send-email-ville.syrjala@linux.intel.com>

On 05/05/2015 07:17 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Currently the IBX transcoder B workarounds are not working correctly.
> Well, the HDMI one seems to be working somewhat, but the DP one is
> definitely busted.
> 
> After a bit of experimentation it looks like the best way to make this
> work is first disable the port on transcoder B, and then re-enable it
> transcoder A, and immediately disable it again.
> 
> We can also clean up the code by noting that we can't be called without
> a valid crtc. And also note that port A on ILK does not need the
> workaround, so let's check for that one too.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   | 37 ++++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_hdmi.c | 50 ++++++++++++++++++---------------------
>  drivers/gpu/drm/i915/intel_sdvo.c | 41 +++++++++++++-------------------
>  3 files changed, 60 insertions(+), 68 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 17b006c..3401cde 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3821,6 +3821,7 @@ static void
>  intel_dp_link_down(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
>  	enum port port = intel_dig_port->port;
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3837,34 +3838,38 @@ intel_dp_link_down(struct intel_dp *intel_dp)
>  	if ((IS_GEN7(dev) && port == PORT_A) ||
>  	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
>  		DP &= ~DP_LINK_TRAIN_MASK_CPT;
> -		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
> +		DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
>  	} else {
>  		if (IS_CHERRYVIEW(dev))
>  			DP &= ~DP_LINK_TRAIN_MASK_CHV;
>  		else
>  			DP &= ~DP_LINK_TRAIN_MASK;
> -		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
> +		DP |= DP_LINK_TRAIN_PAT_IDLE;
>  	}
> +	I915_WRITE(intel_dp->output_reg, DP);
>  	POSTING_READ(intel_dp->output_reg);
>  
> -	if (HAS_PCH_IBX(dev) &&
> -	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
> -		/* Hardware workaround: leaving our transcoder select
> -		 * set to transcoder B while it's off will prevent the
> -		 * corresponding HDMI output on transcoder A.
> -		 *
> -		 * Combine this with another hardware workaround:
> -		 * transcoder select bit can only be cleared while the
> -		 * port is enabled.
> -		 */
> -		DP &= ~DP_PIPEB_SELECT;
> +	DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE);
> +	I915_WRITE(intel_dp->output_reg, DP);
> +	POSTING_READ(intel_dp->output_reg);
> +
> +	/*
> +	 * HW workaround for IBX, we need to move the port
> +	 * to transcoder A after disabling it to allow the
> +	 * matching HDMI port to be enabled on transcoder A.
> +	 */
> +	if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) {
> +		/* always enable with pattern 1 (as per spec) */
> +		DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK);
> +		DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1;
> +		I915_WRITE(intel_dp->output_reg, DP);
> +		POSTING_READ(intel_dp->output_reg);
> +
> +		DP &= ~DP_PORT_EN;
>  		I915_WRITE(intel_dp->output_reg, DP);
>  		POSTING_READ(intel_dp->output_reg);
>  	}
>  
> -	DP &= ~DP_AUDIO_OUTPUT_ENABLE;
> -	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
> -	POSTING_READ(intel_dp->output_reg);
>  	msleep(intel_dp->panel_power_down_delay);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 308015e..9b9a69e 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1096,39 +1096,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
>  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
>  	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
>  	u32 temp;
> -	u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE;
>  
>  	if (crtc->config->has_audio)
>  		intel_audio_codec_disable(encoder);
>  
>  	temp = I915_READ(intel_hdmi->hdmi_reg);
>  
> -	/* HW workaround for IBX, we need to move the port to transcoder A
> -	 * before disabling it. */
> -	if (HAS_PCH_IBX(dev)) {
> -		struct drm_crtc *crtc = encoder->base.crtc;
> -		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
> -
> -		if (temp & SDVO_PIPE_B_SELECT) {
> -			temp &= ~SDVO_PIPE_B_SELECT;
> -			I915_WRITE(intel_hdmi->hdmi_reg, temp);
> -			POSTING_READ(intel_hdmi->hdmi_reg);
> -
> -			/* Again we need to write this twice. */
> -			I915_WRITE(intel_hdmi->hdmi_reg, temp);
> -			POSTING_READ(intel_hdmi->hdmi_reg);
> -
> -			/* Transcoder selection bits only update
> -			 * effectively on vblank. */
> -			if (crtc)
> -				intel_wait_for_vblank(dev, pipe);
> -			else
> -				msleep(50);
> -		}
> -	}
> -
> -	temp &= ~enable_bits;
> -
> +	temp &= ~(SDVO_ENABLE | SDVO_AUDIO_ENABLE);
>  	I915_WRITE(intel_hdmi->hdmi_reg, temp);
>  	POSTING_READ(intel_hdmi->hdmi_reg);
>  
> @@ -1136,6 +1110,28 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
>  		chv_powergate_phy_lanes(encoder, 0xf);
>  
>  	intel_hdmi->set_infoframes(&encoder->base, false, NULL);
> +
> +	/*
> +	 * HW workaround for IBX, we need to move the port
> +	 * to transcoder A after disabling it to allow the
> +	 * matching DP port to be enabled on transcoder A.
> +	 */
> +	if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) {
> +		temp &= ~SDVO_PIPE_B_SELECT;
> +		temp |= SDVO_ENABLE;
> +		/*
> +		 * HW workaround, need to write this twice for issue
> +		 * that may result in first write getting masked.
> +		 */
> +		I915_WRITE(intel_hdmi->hdmi_reg, temp);
> +		POSTING_READ(intel_hdmi->hdmi_reg);
> +		I915_WRITE(intel_hdmi->hdmi_reg, temp);
> +		POSTING_READ(intel_hdmi->hdmi_reg);
> +
> +		temp &= ~SDVO_ENABLE;
> +		I915_WRITE(intel_hdmi->hdmi_reg, temp);
> +		POSTING_READ(intel_hdmi->hdmi_reg);
> +	}
>  }
>  
>  static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index e3e9c98..4a87691 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1437,6 +1437,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
>  {
>  	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
>  	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
>  	u32 temp;
>  
>  	intel_sdvo_set_active_outputs(intel_sdvo, 0);
> @@ -1445,32 +1446,22 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
>  						   DRM_MODE_DPMS_OFF);
>  
>  	temp = I915_READ(intel_sdvo->sdvo_reg);
> -	if ((temp & SDVO_ENABLE) != 0) {
> -		/* HW workaround for IBX, we need to move the port to
> -		 * transcoder A before disabling it. */
> -		if (HAS_PCH_IBX(encoder->base.dev)) {
> -			struct drm_crtc *crtc = encoder->base.crtc;
> -			int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
> -
> -			if (temp & SDVO_PIPE_B_SELECT) {
> -				temp &= ~SDVO_PIPE_B_SELECT;
> -				I915_WRITE(intel_sdvo->sdvo_reg, temp);
> -				POSTING_READ(intel_sdvo->sdvo_reg);
> -
> -				/* Again we need to write this twice. */
> -				I915_WRITE(intel_sdvo->sdvo_reg, temp);
> -				POSTING_READ(intel_sdvo->sdvo_reg);
> -
> -				/* Transcoder selection bits only update
> -				 * effectively on vblank. */
> -				if (crtc)
> -					intel_wait_for_vblank(encoder->base.dev, pipe);
> -				else
> -					msleep(50);
> -			}
> -		}
>  
> -		intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
> +	temp &= ~SDVO_ENABLE;
> +	intel_sdvo_write_sdvox(intel_sdvo, temp);
> +
> +	/*
> +	 * HW workaround for IBX, we need to move the port
> +	 * to transcoder A after disabling it to allow the
> +	 * matching DP port to be enabled on transcoder A.
> +	 */
> +	if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
> +		temp &= ~SDVO_PIPE_B_SELECT;
> +		temp |= SDVO_ENABLE;
> +		intel_sdvo_write_sdvox(intel_sdvo, temp);
> +
> +		temp &= ~SDVO_ENABLE;
> +		intel_sdvo_write_sdvox(intel_sdvo, temp);
>  	}
>  }
>  
> 

Cool, again, testing wins.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2015-05-21 19:30 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-05 14:17 [PATCH 00/12] drm/i915: PCH modeset sequence fixes ville.syrjala
2015-05-05 14:17 ` [PATCH 01/12] drm/i915: Remove a bogus 12bpc "toggle" from intel_disable_hdmi() ville.syrjala
2015-05-21 19:04   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 02/12] drm/i915: Remove the double register write " ville.syrjala
2015-05-21 19:04   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 03/12] drm/i915: Clarfify the DP code platform checks ville.syrjala
2015-05-21 19:10   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 04/12] drm/i915: Clean up the CPT DP .get_hw_state() port readout ville.syrjala
2015-05-21 19:16   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 05/12] drm/i915: Fix DP enhanced framing for CPT ville.syrjala
2015-05-21 19:19   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 06/12] drm/i915: Use POSTING_READ() in intel_sdvo_write_sdvox() ville.syrjala
2015-05-06 11:30   ` Daniel Vetter
2015-05-05 14:17 ` [PATCH 07/12] drm/i915: Write the SDVO reg twice on IBX ville.syrjala
2015-05-21 19:20   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 08/12] drm/i915: Fix the IBX transcoder B workarounds ville.syrjala
2015-05-21 19:23   ` Jesse Barnes [this message]
2015-05-05 14:17 ` [PATCH 09/12] drm/i915: Disable HDMI port after the pipe on PCH platforms ville.syrjala
2015-05-21 19:24   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 10/12] drm/i915: Disable SDVO " ville.syrjala
2015-05-21 19:26   ` Jesse Barnes
2015-05-21 21:24     ` Daniel Vetter
2015-05-05 14:17 ` [PATCH 11/12] drm/i915: Disable CRT port after " ville.syrjala
2015-05-21 19:26   ` Jesse Barnes
2015-05-05 14:17 ` [PATCH 12/12] drm/i915: Disable FDI RX/TX before the ports ville.syrjala
2015-05-21 19:27   ` Jesse Barnes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=555E30A9.2040206@virtuousgeek.org \
    --to=jbarnes@virtuousgeek.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=ville.syrjala@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.