[Intel-gfx] [PATCH v2 4/9] drm/i915: Try to use the correct power sequencer intiially on bxt/glk

Manna, Animesh animesh.manna at intel.com
Thu Dec 8 15:28:31 UTC 2022



> -----Original Message-----
> From: Ville Syrjala <ville.syrjala at linux.intel.com>
> Sent: Friday, November 25, 2022 11:02 PM
> To: intel-gfx at lists.freedesktop.org
> Cc: Manna, Animesh <animesh.manna at intel.com>
> Subject: [PATCH v2 4/9] drm/i915: Try to use the correct power sequencer
> intiially on bxt/glk
> 
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> Currently on bxt/glk we just grab the power sequencer index from the VBT
> data even though it may not have been parsed yet. That could lead us to
> using the incorrect power sequencer during the initial panel probe.
> 
> To avoid that let's try to read out the current state of the power sequencer
> from the hardware. Unfortunately the power sequencer no longer has
> anything in its registers to associate it with the port, so the best we can do is
> just iterate through the power sequencers and pick the first one. This should
> be sufficient for single panel cases.
> 
> For the dual panel cases we probably need to go back to parsing the VBT
> before the panel probe (and hope that panel_type=0xff is never a thing in
> those cases). To that end the code always prefers the VBT panel sequencer, if
> available.
> 
> v2: Restructure a bit for upcoming icp+ dual PPS support
> 
> Cc: Animesh Manna <animesh.manna at intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

LGTM.
Reviewed-by: Animesh Manna <animesh.manna at intel.com>

> ---
>  .../drm/i915/display/intel_display_types.h    | 22 +++--
>  drivers/gpu/drm/i915/display/intel_panel.c    |  1 +
>  drivers/gpu/drm/i915/display/intel_pps.c      | 96 +++++++++++++++++--
>  3 files changed, 102 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index cc64e787e401..32e8b2fc3cc6 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -330,7 +330,7 @@ struct intel_vbt_panel_data {
>  		bool present;
>  		bool active_low_pwm;
>  		u8 min_brightness;	/* min_brightness/255 of max */
> -		u8 controller;		/* brightness controller number */
> +		s8 controller;		/* brightness controller number */
>  		enum intel_backlight_type type;
>  	} backlight;
> 
> @@ -1570,11 +1570,19 @@ struct intel_pps {
>  	ktime_t panel_power_off_time;
>  	intel_wakeref_t vdd_wakeref;
> 
> -	/*
> -	 * Pipe whose power sequencer is currently locked into
> -	 * this port. Only relevant on VLV/CHV.
> -	 */
> -	enum pipe pps_pipe;
> +	union {
> +		/*
> +		 * Pipe whose power sequencer is currently locked into
> +		 * this port. Only relevant on VLV/CHV.
> +		 */
> +		enum pipe pps_pipe;
> +
> +		/*
> +		 * Power sequencer index. Only relevant on BXT+.
> +		 */
> +		int pps_idx;
> +	};
> +
>  	/*
>  	 * Pipe currently driving the port. Used for preventing
>  	 * the use of the PPS for any pipe currentrly driving @@ -1583,7
> +1591,7 @@ struct intel_pps {
>  	enum pipe active_pipe;
>  	/*
>  	 * Set if the sequencer may be reset due to a power transition,
> -	 * requiring a reinitialization. Only relevant on BXT.
> +	 * requiring a reinitialization. Only relevant on BXT+.
>  	 */
>  	bool pps_reset;
>  	struct edp_power_seq pps_delays;
> diff --git a/drivers/gpu/drm/i915/display/intel_panel.c
> b/drivers/gpu/drm/i915/display/intel_panel.c
> index 609fcdbd7d58..3b1004b019a8 100644
> --- a/drivers/gpu/drm/i915/display/intel_panel.c
> +++ b/drivers/gpu/drm/i915/display/intel_panel.c
> @@ -666,6 +666,7 @@ void intel_panel_init_alloc(struct intel_connector
> *connector)
>  	struct intel_panel *panel = &connector->panel;
> 
>  	connector->panel.vbt.panel_type = -1;
> +	connector->panel.vbt.backlight.controller = -1;
>  	INIT_LIST_HEAD(&panel->fixed_modes);
>  }
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c
> b/drivers/gpu/drm/i915/display/intel_pps.c
> index 41ab12fcce0e..d8d2f22f3e0c 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -212,8 +212,7 @@ static int
>  bxt_power_sequencer_idx(struct intel_dp *intel_dp)  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_connector *connector = intel_dp->attached_connector;
> -	int backlight_controller = connector->panel.vbt.backlight.controller;
> +	int pps_idx = intel_dp->pps.pps_idx;
> 
>  	lockdep_assert_held(&dev_priv->display.pps.mutex);
> 
> @@ -221,7 +220,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
>  	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> 
>  	if (!intel_dp->pps.pps_reset)
> -		return backlight_controller;
> +		return pps_idx;
> 
>  	intel_dp->pps.pps_reset = false;
> 
> @@ -231,7 +230,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
>  	 */
>  	pps_init_registers(intel_dp, false);
> 
> -	return backlight_controller;
> +	return pps_idx;
>  }
> 
>  typedef bool (*pps_check)(struct drm_i915_private *dev_priv, int pps_idx);
> @@ -311,6 +310,64 @@ vlv_initial_power_sequencer_setup(struct intel_dp
> *intel_dp)
>  		    pipe_name(intel_dp->pps.pps_pipe));
>  }
> 
> +static int
> +bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check) {
> +	int pps_idx, pps_num = 2;
> +
> +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> +		if (check(i915, pps_idx))
> +			return pps_idx;
> +	}
> +
> +	return -1;
> +}
> +
> +static void
> +pps_initial_setup(struct intel_dp *intel_dp) {
> +	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +	struct intel_connector *connector = intel_dp->attached_connector;
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	lockdep_assert_held(&i915->display.pps.mutex);
> +
> +	if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
> +		vlv_initial_power_sequencer_setup(intel_dp);
> +		return;
> +	}
> +
> +	if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915))
> +		return;
> +
> +	/* first ask the VBT */
> +	intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller;
> +	if (drm_WARN_ON(&i915->drm, intel_dp->pps.pps_idx >= 2))
> +		intel_dp->pps.pps_idx = -1;
> +
> +	/* VBT wasn't parsed yet? pick one where the panel is on */
> +	if (intel_dp->pps.pps_idx < 0)
> +		intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915,
> pps_has_pp_on);
> +	/* didn't find one? pick one where vdd is on */
> +	if (intel_dp->pps.pps_idx < 0)
> +		intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915,
> pps_has_vdd_on);
> +	/* didn't find one? pick any */
> +	if (intel_dp->pps.pps_idx < 0) {
> +		intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_any);
> +
> +		drm_dbg_kms(&i915->drm,
> +			    "[ENCODER:%d:%s] no initial power sequencer,
> assuming %d\n",
> +			    encoder->base.base.id, encoder->base.name,
> +			    intel_dp->pps.pps_idx);
> +		return;
> +	}
> +
> +	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);
> +}
> +
>  void intel_pps_reset_all(struct drm_i915_private *dev_priv)  {
>  	struct intel_encoder *encoder;
> @@ -363,10 +420,10 @@ static void intel_pps_get_registers(struct intel_dp
> *intel_dp,
> 
>  	memset(regs, 0, sizeof(*regs));
> 
> -	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
> -		pps_idx = bxt_power_sequencer_idx(intel_dp);
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>  		pps_idx = vlv_power_sequencer_pipe(intel_dp);
> +	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
> +		pps_idx = bxt_power_sequencer_idx(intel_dp);
> 
>  	regs->pp_ctrl = PP_CONTROL(pps_idx);
>  	regs->pp_stat = PP_STATUS(pps_idx);
> @@ -1429,7 +1486,6 @@ void intel_pps_encoder_reset(struct intel_dp
> *intel_dp)
> 
>  void intel_pps_init(struct intel_dp *intel_dp)  {
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>  	intel_wakeref_t wakeref;
> 
>  	intel_dp->pps.initializing = true;
> @@ -1438,8 +1494,7 @@ void intel_pps_init(struct intel_dp *intel_dp)
>  	pps_init_timestamps(intel_dp);
> 
>  	with_intel_pps_lock(intel_dp, wakeref) {
> -		if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
> -			vlv_initial_power_sequencer_setup(intel_dp);
> +		pps_initial_setup(intel_dp);
> 
>  		pps_init_delays(intel_dp);
>  		pps_init_registers(intel_dp, false);
> @@ -1447,12 +1502,33 @@ void intel_pps_init(struct intel_dp *intel_dp)
>  	}
>  }
> 
> +static void pps_init_late(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +	struct intel_connector *connector = intel_dp->attached_connector;
> +
> +	if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915))
> +		return;
> +
> +	drm_WARN(&i915->drm, connector->panel.vbt.backlight.controller
> >= 0 &&
> +		 intel_dp->pps.pps_idx != connector-
> >panel.vbt.backlight.controller,
> +		 "[ENCODER:%d:%s] power sequencer mismatch: %d (initial)
> vs. %d (VBT)\n",
> +		 encoder->base.base.id, encoder->base.name,
> +		 intel_dp->pps.pps_idx, connector-
> >panel.vbt.backlight.controller);
> +
> +	if (connector->panel.vbt.backlight.controller >= 0)
> +		intel_dp->pps.pps_idx = connector-
> >panel.vbt.backlight.controller;
> +}
> +
>  void intel_pps_init_late(struct intel_dp *intel_dp)  {
>  	intel_wakeref_t wakeref;
> 
>  	with_intel_pps_lock(intel_dp, wakeref) {
>  		/* Reinit delays after per-panel info has been parsed from
> VBT */
> +		pps_init_late(intel_dp);
> +
>  		memset(&intel_dp->pps.pps_delays, 0, sizeof(intel_dp-
> >pps.pps_delays));
>  		pps_init_delays(intel_dp);
>  		pps_init_registers(intel_dp, false);
> --
> 2.37.4



More information about the Intel-gfx mailing list