Re: [PATCH v2 6/9] drm/i915: Reject unusablee power sequencers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> -----Original Message-----
> From: Ville Syrjala <ville.syrjala@xxxxxxxxxxxxxxx>
> Sent: Friday, November 25, 2022 11:02 PM
> To: intel-gfx@xxxxxxxxxxxxxxxxxxxxx
> Cc: Manna, Animesh <animesh.manna@xxxxxxxxx>
> Subject: [PATCH v2 6/9] drm/i915: Reject unusablee power sequencers
> 
> From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> 
> On ICP-ADP the pins used by the second PPS can be alternatively muxed to
> some other function. In that case the second power sequencer is unusable.
> 
> Unfortunately (on my ADL Thinkpad T14 gen3 at least) the BIOS still likes to
> enable the VDD on the second PPS (due to the VBT declaring the second
> bogus eDP panel) even when not correctly muxed, so we need to deal with it
> somehow.
> For now let's just initialize the PPS as normal, and then use the normal eDP
> probe failure VDD off path to turn it off (and release the wakeref the PPS init
> grabbed). The alternative of just declaring that the platform has a single PPS
> doesn't really work since it would cause the second eDP probe to also try to
> use the first PPS and thus clobber the state for the first (real) eDP panel.
> 
> Cc: Animesh Manna <animesh.manna@xxxxxxxxx>
> Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>

Reviewed-by: Animesh Manna <animesh.manna@xxxxxxxxx>

> ---
>  drivers/gpu/drm/i915/display/intel_dp.c  | 12 ++++++++-
> drivers/gpu/drm/i915/display/intel_pps.c | 34 +++++++++++++++++-------
> drivers/gpu/drm/i915/display/intel_pps.h |  2 +-
>  drivers/gpu/drm/i915/i915_reg.h          |  1 +
>  4 files changed, 38 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index c1bebe77ed8e..9deaa5e3632a 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -5283,7 +5283,17 @@ static bool intel_edp_init_connector(struct
> intel_dp *intel_dp,
>  	intel_bios_init_panel_early(dev_priv, &intel_connector->panel,
>  				    encoder->devdata);
> 
> -	intel_pps_init(intel_dp);
> +	if (!intel_pps_init(intel_dp)) {
> +		drm_info(&dev_priv->drm,
> +			 "[ENCODER:%d:%s] unusable PPS, disabling eDP\n",
> +			 encoder->base.base.id, encoder->base.name);
> +		/*
> +		 * The BIOS may have still enabled VDD on the PPS even
> +		 * though it's unusable. Make sure we turn it back off
> +		 * and to release the power domain references/etc.
> +		 */
> +		goto out_vdd_off;
> +	}
> 
>  	/* Cache DPCD and EDID for edp. */
>  	has_dpcd = intel_edp_init_dpcd(intel_dp); diff --git
> a/drivers/gpu/drm/i915/display/intel_pps.c
> b/drivers/gpu/drm/i915/display/intel_pps.c
> index 77b0a4f27abc..d18c1c58dfcf 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -327,6 +327,18 @@ static int intel_num_pps(struct drm_i915_private
> *i915)
>  	return 1;
>  }
> 
> +static bool intel_pps_is_valid(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	if (intel_dp->pps.pps_idx == 1 &&
> +	    INTEL_PCH_TYPE(i915) >= PCH_ICP &&
> +	    INTEL_PCH_TYPE(i915) < PCH_MTP)
> +		return intel_de_read(i915, SOUTH_CHICKEN1) &
> +ICP_SECOND_PPS_IO_SELECT;
> +
> +	return true;
> +}
> +
>  static int
>  bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check)  { @@ -
> 340,7 +352,7 @@ bxt_initial_pps_idx(struct drm_i915_private *i915,
> pps_check check)
>  	return -1;
>  }
> 
> -static void
> +static bool
>  pps_initial_setup(struct intel_dp *intel_dp)  {
>  	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> @@ -351,7 +363,7 @@ pps_initial_setup(struct intel_dp *intel_dp)
> 
>  	if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
>  		vlv_initial_power_sequencer_setup(intel_dp);
> -		return;
> +		return true;
>  	}
> 
>  	/* first ask the VBT */
> @@ -377,13 +389,14 @@ pps_initial_setup(struct intel_dp *intel_dp)
>  			    "[ENCODER:%d:%s] no initial power sequencer,
> assuming %d\n",
>  			    encoder->base.base.id, encoder->base.name,
>  			    intel_dp->pps.pps_idx);
> -		return;
> +	} else {
> +		drm_dbg_kms(&i915->drm,
> +			    "[ENCODER:%d:%s] initial power sequencer:
> %d\n",
> +			    encoder->base.base.id, encoder->base.name,
> +			    intel_dp->pps.pps_idx);
>  	}
> 
> -	drm_dbg_kms(&i915->drm,
> -		    "[ENCODER:%d:%s] initial power sequencer: %d\n",
> -		    encoder->base.base.id, encoder->base.name,
> -		    intel_dp->pps.pps_idx);
> +	return intel_pps_is_valid(intel_dp);
>  }
> 
>  void intel_pps_reset_all(struct drm_i915_private *dev_priv) @@ -1504,9
> +1517,10 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
>  	}
>  }
> 
> -void intel_pps_init(struct intel_dp *intel_dp)
> +bool intel_pps_init(struct intel_dp *intel_dp)
>  {
>  	intel_wakeref_t wakeref;
> +	bool ret;
> 
>  	intel_dp->pps.initializing = true;
>  	INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work,
> edp_panel_vdd_work); @@ -1514,12 +1528,14 @@ void
> intel_pps_init(struct intel_dp *intel_dp)
>  	pps_init_timestamps(intel_dp);
> 
>  	with_intel_pps_lock(intel_dp, wakeref) {
> -		pps_initial_setup(intel_dp);
> +		ret = pps_initial_setup(intel_dp);
> 
>  		pps_init_delays(intel_dp);
>  		pps_init_registers(intel_dp, false);
>  		pps_vdd_init(intel_dp);
>  	}
> +
> +	return ret;
>  }
> 
>  static void pps_init_late(struct intel_dp *intel_dp) diff --git
> a/drivers/gpu/drm/i915/display/intel_pps.h
> b/drivers/gpu/drm/i915/display/intel_pps.h
> index a3a56f903f26..a2c2467e3c22 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.h
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -40,7 +40,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
> bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp);  void
> intel_pps_wait_power_cycle(struct intel_dp *intel_dp);
> 
> -void intel_pps_init(struct intel_dp *intel_dp);
> +bool intel_pps_init(struct intel_dp *intel_dp);
>  void intel_pps_init_late(struct intel_dp *intel_dp);  void
> intel_pps_encoder_reset(struct intel_dp *intel_dp);  void
> intel_pps_reset_all(struct drm_i915_private *i915); diff --git
> a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 0b90fe6a28f7..ebb45935750c 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -6242,6 +6242,7 @@
>  #define  CHASSIS_CLK_REQ_DURATION_MASK	(0xf << 8)
>  #define  CHASSIS_CLK_REQ_DURATION(x)	((x) << 8)
>  #define  SBCLK_RUN_REFCLK_DIS		(1 << 7)
> +#define  ICP_SECOND_PPS_IO_SELECT	REG_BIT(2)
>  #define  SPT_PWM_GRANULARITY		(1 << 0)
>  #define SOUTH_CHICKEN2		_MMIO(0xc2004)
>  #define  FDI_MPHY_IOSFSB_RESET_STATUS	(1 << 13)
> --
> 2.37.4





[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux