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

Manna, Animesh animesh.manna at intel.com
Thu Nov 10 13:56:46 UTC 2022



> -----Original Message-----
> From: Ville Syrjala <ville.syrjala at linux.intel.com>
> Sent: Wednesday, November 9, 2022 4:47 PM
> To: intel-gfx at lists.freedesktop.org
> Cc: Manna, Animesh <animesh.manna at intel.com>
> Subject: [PATCH 4/6] 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.
> 
> TODO: Deal with all the modern platforms too
>       Maybe add checks to make sure the same power
>       sequencer doesn't get assigned to multiple ports?
> 
> Cc: Animesh Manna <animesh.manna at intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  8 +-
>  drivers/gpu/drm/i915/display/intel_panel.c    |  1 +
>  drivers/gpu/drm/i915/display/intel_pps.c      | 78 +++++++++++++++++--
>  3 files changed, 80 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index aec06cb24e23..25165110142b 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;
> 
> @@ -1571,9 +1571,13 @@ 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;
> +	/*
> +	 * Power sequencer index. Only relevant on BXT+.
> +	 */
> +	s8 pps_idx;
>  	struct edp_power_seq pps_delays;
>  	struct edp_power_seq bios_pps_delays;
>  };
> diff --git a/drivers/gpu/drm/i915/display/intel_panel.c
> b/drivers/gpu/drm/i915/display/intel_panel.c
> index 918b3b9d9ebe..1794e5eecf90 100644
> --- a/drivers/gpu/drm/i915/display/intel_panel.c
> +++ b/drivers/gpu/drm/i915/display/intel_panel.c
> @@ -665,6 +665,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 84265096f751..ff4f1def59d2 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -211,8 +211,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);
> 
> @@ -220,7 +219,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;
> 
> @@ -230,7 +229,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); @@
> -310,6 +309,54 @@ 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
> +bxt_initial_power_sequencer_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);
> +
> +	/* first ask the VBT */
> +	intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller;
> +  
> +	/* 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);

Always we will get 0 here even if bios enabled correctly two pps instance for dual EDP.
Can pps be mapped with port number, like pps1 for portA and pps2 for portB?
 
> +	/* 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);

Same as above for vdd.

> +	/* 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);

pps_any() is returning bool, any specific reason? Can we return 0 from it. 

Regards,
Animesh 

> +
> +		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;
> @@ -1431,7 +1478,9 @@ 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))
> +		if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
> +			bxt_initial_power_sequencer_setup(intel_dp);
> +		else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
>  			vlv_initial_power_sequencer_setup(intel_dp);
> 
>  		pps_init_delays(intel_dp);
> @@ -1440,12 +1489,31 @@ void intel_pps_init(struct intel_dp *intel_dp)
>  	}
>  }
> 
> +static void bxt_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;
> +
> +	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)  {
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>  	intel_wakeref_t wakeref;
> 
>  	with_intel_pps_lock(intel_dp, wakeref) {
>  		/* Reinit delays after per-panel info has been parsed from VBT
> */
> +		if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
> +			bxt_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