[Intel-gfx] [PATCH 2/4] drm/i915/psr: Store VBT TP wakeup times into a enum

Jani Nikula jani.nikula at linux.intel.com
Tue Jan 22 12:09:36 UTC 2019


On Wed, 16 Jan 2019, José Roberto de Souza <jose.souza at intel.com> wrote:
> Newer VBTs and the PSR registers uses a enum to set the TPs wakeup
> time, so lets use this format to store wakeup times and avoid
> conversions every time that PSR is activated.

The VBT is a messy blob of data, and intel_bios.c in many places tries
very hard to abstract and hide all the quirks in there from the
driver. Observe how intel_vbt_defs.h has extra safeguards to try to keep
it private to intel_bios.c. We don't want the VBT implementation details
to leak into the driver.

This patch goes against that abstraction. Please don't do it.

> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
> Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h   | 12 +++++-
>  drivers/gpu/drm/i915/i915_reg.h   | 16 ++------
>  drivers/gpu/drm/i915/intel_bios.c | 65 +++++++++++++++----------------
>  drivers/gpu/drm/i915/intel_psr.c  | 29 ++------------
>  4 files changed, 47 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index e717c3132692..d9893d35f0e2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -959,6 +959,14 @@ enum psr_lines_to_wait {
>  	PSR_8_LINES_TO_WAIT
>  };
>  
> +enum psr_tp_wakeup_time {
> +	PSR_TP_WAKEUP_TIME_500USEC = 0,
> +	PSR_TP_WAKEUP_TIME_100USEC,
> +	PSR_TP_WAKEUP_TIME_2500USEC,
> +	PSR_TP_WAKEUP_TIME_NONE,
> +	PSR_TP_WAKEUP_TIME_LAST
> +};

Here's the problem. This enum now describes both the VBT internals as
well as the hardware register contents. Imagine either the VBT or the
hardware changing to a different bit layout. You'll be in trouble
decoupling them again. (Yeah, they'll say neither will change. They've
said things like that before.)

Moreover, this looks like an innocent enumeration here, separated from
both the VBT parsing and the hardware.

The VBT needs to be described in intel_vbt_defs.h and intel_bios.c, and
the register needs to be desribed in i915_regs.h.

> +
>  struct intel_vbt_data {
>  	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
>  	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
> @@ -995,8 +1003,8 @@ struct intel_vbt_data {
>  		bool require_aux_wakeup;
>  		int idle_frames;
>  		enum psr_lines_to_wait lines_to_wait;
> -		int tp1_wakeup_time_us;
> -		int tp2_tp3_tp4_wakeup_time_us;
> +		enum psr_tp_wakeup_time tp1_wakeup_time;
> +		enum psr_tp_wakeup_time tp2_tp3_tp4_wakeup_time;
>  	} psr;
>  
>  	struct {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index fad5a9e8b44d..5faca634ee70 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4161,14 +4161,8 @@ enum {
>  #define   EDP_PSR_TP1_TP2_SEL			(0 << 11)
>  #define   EDP_PSR_TP1_TP3_SEL			(1 << 11)
>  #define   EDP_PSR_CRC_ENABLE			(1 << 10) /* BDW+ */
> -#define   EDP_PSR_TP2_TP3_TIME_500us		(0 << 8)
> -#define   EDP_PSR_TP2_TP3_TIME_100us		(1 << 8)
> -#define   EDP_PSR_TP2_TP3_TIME_2500us		(2 << 8)
> -#define   EDP_PSR_TP2_TP3_TIME_0us		(3 << 8)
> -#define   EDP_PSR_TP1_TIME_500us		(0 << 4)
> -#define   EDP_PSR_TP1_TIME_100us		(1 << 4)
> -#define   EDP_PSR_TP1_TIME_2500us		(2 << 4)
> -#define   EDP_PSR_TP1_TIME_0us			(3 << 4)
> +#define   EDP_PSR_TP2_TP3_TIME_SHIFT		(8)
> +#define   EDP_PSR_TP1_TIME_SHIFT		(4)

Please do not remove these. They describe the register contents as we
understand them, and not everyone has access or cares to dig up bspec
every time they need to figure things out.

Side note, parens are superfluous for plain values.

>  #define   EDP_PSR_IDLE_FRAME_SHIFT		0
>  
>  /* Bspec claims those aren't shifted but stay at 0x64800 */
> @@ -4234,11 +4228,7 @@ enum {
>  #define   EDP_Y_COORDINATE_ENABLE	(1 << 25) /* GLK and CNL+ */
>  #define   EDP_MAX_SU_DISABLE_TIME(t)	((t) << 20)
>  #define   EDP_MAX_SU_DISABLE_TIME_MASK	(0x1f << 20)
> -#define   EDP_PSR2_TP2_TIME_500us	(0 << 8)
> -#define   EDP_PSR2_TP2_TIME_100us	(1 << 8)
> -#define   EDP_PSR2_TP2_TIME_2500us	(2 << 8)
> -#define   EDP_PSR2_TP2_TIME_50us	(3 << 8)
> -#define   EDP_PSR2_TP2_TIME_MASK	(3 << 8)
> +#define   EDP_PSR2_TP2_TP3_TIME_SHIFT	(8)

Ditto.

>  #define   EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4
>  #define   EDP_PSR2_FRAME_BEFORE_SU_MASK	(0xf << 4)
>  #define   EDP_PSR2_FRAME_BEFORE_SU(a)	((a) << 4)
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index cd99bf88bf6c..6de6f6f1deec 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -719,46 +719,43 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
>  	if (bdb->version >= 205 &&
>  	    (IS_GEN9_BC(dev_priv) || IS_GEMINILAKE(dev_priv) ||
>  	     INTEL_GEN(dev_priv) >= 10)) {
> -		switch (psr_table->tp1_wakeup_time) {
> -		case 0:
> -			dev_priv->vbt.psr.tp1_wakeup_time_us = 500;
> -			break;
> -		case 1:
> -			dev_priv->vbt.psr.tp1_wakeup_time_us = 100;
> -			break;
> -		case 3:
> -			dev_priv->vbt.psr.tp1_wakeup_time_us = 0;
> -			break;
> -		default:
> +		dev_priv->vbt.psr.tp1_wakeup_time = psr_table->tp1_wakeup_time;
> +		if (dev_priv->vbt.psr.tp1_wakeup_time >= PSR_TP_WAKEUP_TIME_LAST) {
>  			DRM_DEBUG_KMS("VBT tp1 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n",
> -					psr_table->tp1_wakeup_time);
> -			/* fallthrough */
> -		case 2:
> -			dev_priv->vbt.psr.tp1_wakeup_time_us = 2500;
> -			break;
> +				      dev_priv->vbt.psr.tp1_wakeup_time);
> +			dev_priv->vbt.psr.tp1_wakeup_time = PSR_TP_WAKEUP_TIME_2500USEC;
>  		}
>  
> -		switch (psr_table->tp2_tp3_tp4_wakeup_time) {
> -		case 0:
> -			dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us = 500;
> -			break;
> -		case 1:
> -			dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us = 100;
> -			break;
> -		case 3:
> -			dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us = 0;
> -			break;
> -		default:
> +		dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time = psr_table->tp2_tp3_tp4_wakeup_time;
> +		if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time >= PSR_TP_WAKEUP_TIME_LAST) {
>  			DRM_DEBUG_KMS("VBT tp2_tp3_tp4 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n",
> -				      psr_table->tp2_tp3_tp4_wakeup_time);
> -			/* fallthrough */
> -		case 2:
> -			dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us = 2500;
> -		break;
> +				      dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time);
> +			dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time = PSR_TP_WAKEUP_TIME_2500USEC;
>  		}
>  	} else {
> -		dev_priv->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100;
> -		dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us = psr_table->tp2_tp3_tp4_wakeup_time * 100;
> +		enum psr_tp_wakeup_time wakeup_time;
> +
> +		if (psr_table->tp1_wakeup_time == 0)
> +			wakeup_time = PSR_TP_WAKEUP_TIME_NONE;
> +		else if (psr_table->tp1_wakeup_time == 1)
> +			wakeup_time = PSR_TP_WAKEUP_TIME_100USEC;
> +		else if (psr_table->tp1_wakeup_time <= 5)
> +			wakeup_time = PSR_TP_WAKEUP_TIME_500USEC;
> +		else
> +			wakeup_time = PSR_TP_WAKEUP_TIME_2500USEC;
> +
> +		dev_priv->vbt.psr.tp1_wakeup_time = wakeup_time;
> +
> +		if (psr_table->tp2_tp3_tp4_wakeup_time == 0)
> +			wakeup_time = PSR_TP_WAKEUP_TIME_NONE;
> +		else if (psr_table->tp2_tp3_tp4_wakeup_time == 1)
> +			wakeup_time = PSR_TP_WAKEUP_TIME_100USEC;
> +		else if (psr_table->tp2_tp3_tp4_wakeup_time <= 5)
> +			wakeup_time = PSR_TP_WAKEUP_TIME_500USEC;
> +		else
> +			wakeup_time = PSR_TP_WAKEUP_TIME_2500USEC;
> +
> +		dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time = wakeup_time;
>  	}
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
> index 49b4b3371bef..5daf0b9e2b42 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -459,23 +459,8 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
>  	if (dev_priv->psr.link_standby)
>  		val |= EDP_PSR_LINK_STANDBY;
>  
> -	if (dev_priv->vbt.psr.tp1_wakeup_time_us == 0)
> -		val |=  EDP_PSR_TP1_TIME_0us;
> -	else if (dev_priv->vbt.psr.tp1_wakeup_time_us <= 100)
> -		val |= EDP_PSR_TP1_TIME_100us;
> -	else if (dev_priv->vbt.psr.tp1_wakeup_time_us <= 500)
> -		val |= EDP_PSR_TP1_TIME_500us;
> -	else
> -		val |= EDP_PSR_TP1_TIME_2500us;
> -
> -	if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us == 0)
> -		val |=  EDP_PSR_TP2_TP3_TIME_0us;
> -	else if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us <= 100)
> -		val |= EDP_PSR_TP2_TP3_TIME_100us;
> -	else if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us <= 500)
> -		val |= EDP_PSR_TP2_TP3_TIME_500us;
> -	else
> -		val |= EDP_PSR_TP2_TP3_TIME_2500us;
> +	val |= dev_priv->vbt.psr.tp1_wakeup_time << EDP_PSR_TP1_TIME_SHIFT;
> +	val |= dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time << EDP_PSR_TP2_TP3_TIME_SHIFT;
>  
>  	if (intel_dp_source_supports_hbr2(intel_dp) &&
>  	    drm_dp_tps3_supported(intel_dp->dpcd))
> @@ -509,15 +494,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
>  
>  	val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1);
>  
> -	if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us >= 0 &&
> -	    dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us <= 50)
> -		val |= EDP_PSR2_TP2_TIME_50us;
> -	else if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us <= 100)
> -		val |= EDP_PSR2_TP2_TIME_100us;
> -	else if (dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time_us <= 500)
> -		val |= EDP_PSR2_TP2_TIME_500us;
> -	else
> -		val |= EDP_PSR2_TP2_TIME_2500us;
> +	val |= dev_priv->vbt.psr.tp2_tp3_tp4_wakeup_time << EDP_PSR2_TP2_TP3_TIME_SHIFT;

IMO usecs is the perfect abstraction between VBT and the driver for
describing timeouts. I'd prefer us not to go towards just blindly
writing hardware registers from the VBT.

BR,
Jani.


>  
>  	I915_WRITE(EDP_PSR2_CTL, val);
>  }

-- 
Jani Nikula, Intel Open Source Graphics Center


More information about the Intel-gfx mailing list