[Intel-gfx] [PATCH v3 1/2] drm/i915: Initial implementation of PSR2 selective fetch

Mun, Gwan-gyeong gwan-gyeong.mun at intel.com
Mon Aug 10 14:52:52 UTC 2020


On Mon, 2020-07-06 at 16:43 -0700, José Roberto de Souza wrote:
> All GEN12 platforms supports PSR2 selective fetch but not all GEN12
> platforms supports PSR2 hardware tracking(aka RKL).
> 
> This feature consists in software programming registers with the
> damaged area of each plane this way hardware will only fetch from
> memory those areas and sent the PSR2 selective update blocks to
> panel,
> saving even more power.
> 
> But as initial step it is only enabling the full frame fetch at
> every flip, the actual selective fetch part will come in a future
> patch.
> 
> Also this is only handling the page flip side, it is still completely
> missing frontbuffer modifications, that is why the
> enable_psr2_sel_fetch parameter was added.
> 
> v3:
> - calling intel_psr2_sel_fetch_update() during the atomic check phase
> (Ville)
> 
> BSpec: 55229
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Cc: Imre Deak <imre.deak at intel.com>
> Cc: Gwan-gyeong Mun <gwan-gyeong.mun at intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi at intel.com>
> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
> Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  |  5 +
>  .../drm/i915/display/intel_display_debugfs.c  |  3 +
>  .../drm/i915/display/intel_display_types.h    |  3 +
>  drivers/gpu/drm/i915/display/intel_psr.c      | 95 ++++++++++++++++-
> --
>  drivers/gpu/drm/i915/display/intel_psr.h      |  5 +
>  drivers/gpu/drm/i915/i915_drv.h               |  2 +
>  drivers/gpu/drm/i915/i915_params.c            |  5 +
>  drivers/gpu/drm/i915/i915_params.h            |  1 +
>  8 files changed, 105 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index dff7c17f3d2b..eb64e2ac773a 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -12759,6 +12759,9 @@ static int intel_crtc_atomic_check(struct
> intel_atomic_state *state,
>  
>  	}
>  
> +	if (!mode_changed)
> +		intel_psr2_sel_fetch_update(state, crtc);
> +
>  	return 0;
>  }
>  
> @@ -15135,6 +15138,8 @@ static void commit_pipe_config(struct
> intel_atomic_state *state,
>  
>  		if (new_crtc_state->update_pipe)
>  			intel_pipe_fastset(old_crtc_state,
> new_crtc_state);
> +
> +		intel_psr2_program_trans_man_trk_ctl(new_crtc_state);
>  	}
>  
>  	if (dev_priv->display.atomic_update_watermarks)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index 3644752cc5ec..15d963183bcf 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -417,6 +417,9 @@ static int i915_edp_psr_status(struct seq_file
> *m, void *data)
>  			su_blocks = su_blocks >>
> PSR2_SU_STATUS_SHIFT(frame);
>  			seq_printf(m, "%d\t%d\n", frame, su_blocks);
>  		}
> +
> +		seq_printf(m, "PSR2 selective fetch: %s\n",
> +			   enableddisabled(psr-
> >psr2_sel_fetch_enabled));
>  	}
>  
>  unlock:
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index e8f809161c75..403a76214e71 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -931,6 +931,7 @@ struct intel_crtc_state {
>  
>  	bool has_psr;
>  	bool has_psr2;
> +	bool enable_psr2_sel_fetch;
>  	u32 dc3co_exitline;
>  
>  	/*
> @@ -1073,6 +1074,8 @@ struct intel_crtc_state {
>  
>  	/* For DSB related info */
>  	struct intel_dsb *dsb;
> +
> +	u32 psr2_man_track_ctl;
>  };
>  
>  enum intel_pipe_crc_source {
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> b/drivers/gpu/drm/i915/display/intel_psr.c
> index bf9e320c547d..d30a3560b794 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -553,6 +553,14 @@ static void hsw_activate_psr2(struct intel_dp
> *intel_dp)
>  		val |= EDP_PSR2_FAST_WAKE(7);
>  	}
>  
> +	if (dev_priv->psr.psr2_sel_fetch_enabled)
> +		intel_de_write(dev_priv,
> +			       PSR2_MAN_TRK_CTL(dev_priv-
> >psr.transcoder),
> +			       PSR2_MAN_TRK_CTL_ENABLE);
> +	else if (HAS_PSR2_SEL_FETCH(dev_priv))
> +		intel_de_write(dev_priv,
> +			       PSR2_MAN_TRK_CTL(dev_priv-
> >psr.transcoder), 0);
> +
>  	/*
>  	 * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec
> is
>  	 * recommending keep this bit unset while PSR2 is enabled.
> @@ -663,6 +671,38 @@ tgl_dc3co_exitline_compute_config(struct
> intel_dp *intel_dp,
>  	crtc_state->dc3co_exitline = crtc_vdisplay - exit_scanlines;
>  }
>  
> +static bool intel_psr2_sel_fetch_config_valid(struct intel_dp
> *intel_dp,
> +					      struct intel_crtc_state
> *crtc_state)
> +{
> +	struct intel_atomic_state *state =
> to_intel_atomic_state(crtc_state->uapi.state);
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_plane_state *plane_state;
> +	struct intel_plane *plane;
> +	int i;
> +
> +	if (!dev_priv->params.enable_psr2_sel_fetch) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "PSR2 sel fetch not enabled, disabled by
> parameter\n");
> +		return false;
> +	}
> +
> +	if (crtc_state->uapi.async_flip) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "PSR2 sel fetch not enabled, async flip
> enabled\n");
> +		return false;
> +	}
> +
> +	for_each_new_intel_plane_in_state(state, plane, plane_state, i)
> {
> +		if (plane_state->uapi.rotation != DRM_MODE_ROTATE_0) {
> +			drm_dbg_kms(&dev_priv->drm,
> +				    "PSR2 sel fetch not enabled, plane
> rotated\n");
> +			return false;
> +		}
> +	}
> +
> +	return crtc_state->enable_psr2_sel_fetch = true;
> +}
> +
>  static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
>  				    struct intel_crtc_state
> *crtc_state)
>  {
> @@ -732,22 +772,17 @@ static bool intel_psr2_config_valid(struct
> intel_dp *intel_dp,
>  		return false;
>  	}
>  
> -	/*
> -	 * Some platforms lack PSR2 HW tracking and instead require
> manual
> -	 * tracking by software.  In this case, the driver is required
> to track
> -	 * the areas that need updates and program hardware to send
> selective
> -	 * updates.
> -	 *
> -	 * So until the software tracking is implemented, PSR2 needs to
> be
> -	 * disabled for platforms without PSR2 HW tracking.
> -	 */
> -	if (!HAS_PSR_HW_TRACKING(dev_priv)) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "No PSR2 HW tracking in the platform\n");
> -		return false;
> +	if (HAS_PSR2_SEL_FETCH(dev_priv)) {
> +		if (!intel_psr2_sel_fetch_config_valid(intel_dp,
> crtc_state) &&
> +		    !HAS_PSR_HW_TRACKING(dev_priv)) {
> +			drm_dbg_kms(&dev_priv->drm,
> +				    "PSR2 not enabled, selective fetch
> not valid and no HW tracking available\n");
> +			return false;
> +		}
>  	}
>  
> -	if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) {
> +	if (!crtc_state->enable_psr2_sel_fetch &&
> +	    (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v)) {
>  		drm_dbg_kms(&dev_priv->drm,
>  			    "PSR2 not enabled, resolution %dx%d > max
> supported %dx%d\n",
>  			    crtc_hdisplay, crtc_vdisplay,
> @@ -898,6 +933,11 @@ static void intel_psr_enable_source(struct
> intel_dp *intel_dp,
>  		val |= EXITLINE_ENABLE;
>  		intel_de_write(dev_priv, EXITLINE(cpu_transcoder),
> val);
>  	}
> +
> +	if (HAS_PSR_HW_TRACKING(dev_priv))
> +		intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
> IGNORE_PSR2_HW_TRACKING,
> +			     dev_priv->psr.psr2_sel_fetch_enabled ?
> +			     IGNORE_PSR2_HW_TRACKING : 0);
>  }
>  
>  static void intel_psr_enable_locked(struct drm_i915_private
> *dev_priv,
> @@ -919,6 +959,7 @@ static void intel_psr_enable_locked(struct
> drm_i915_private *dev_priv,
>  	/* DC5/DC6 requires at least 6 idle frames */
>  	val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) *
> 6);
>  	dev_priv->psr.dc3co_exit_delay = val;
> +	dev_priv->psr.psr2_sel_fetch_enabled = crtc_state-
> >enable_psr2_sel_fetch;
>  
>  	/*
>  	 * If a PSR error happened and the driver is reloaded, the
> EDP_PSR_IIR
> @@ -1115,6 +1156,32 @@ static void psr_force_hw_tracking_exit(struct
> drm_i915_private *dev_priv)
>  		intel_psr_exit(dev_priv);
>  }
>  
> +void intel_psr2_program_trans_man_trk_ctl(const struct
> intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	struct i915_psr *psr = &dev_priv->psr;
> +
> +	if (!HAS_PSR2_SEL_FETCH(dev_priv) ||
> +	    !crtc_state->enable_psr2_sel_fetch)
> +		return;
> +
> +	intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(psr->transcoder),
> +		       crtc_state->psr2_man_track_ctl);
> +}
> +
> +void intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
> +				 struct intel_crtc *crtc)
> +{
> +	struct intel_crtc_state *crtc_state =
> intel_atomic_get_new_crtc_state(state, crtc);
> +
> +	if (!crtc_state->enable_psr2_sel_fetch)
> +		return;
> +
> +	crtc_state->psr2_man_track_ctl = PSR2_MAN_TRK_CTL_ENABLE |
> +					 PSR2_MAN_TRK_CTL_SF_SINGLE_FUL
> L_FRAME;
> +}
> +
>  /**
>   * intel_psr_update - Update PSR state
>   * @intel_dp: Intel DP
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.h
> b/drivers/gpu/drm/i915/display/intel_psr.h
> index b4515186d5f4..6a83c8e682e6 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.h
> +++ b/drivers/gpu/drm/i915/display/intel_psr.h
> @@ -13,6 +13,8 @@ struct drm_connector_state;
>  struct drm_i915_private;
>  struct intel_crtc_state;
>  struct intel_dp;
> +struct intel_crtc;
> +struct intel_atomic_state;
>  
>  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv-
> >psr.sink_support)
>  void intel_psr_init_dpcd(struct intel_dp *intel_dp);
> @@ -43,5 +45,8 @@ void intel_psr_atomic_check(struct drm_connector
> *connector,
>  			    struct drm_connector_state *old_state,
>  			    struct drm_connector_state *new_state);
>  void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp);
> +void intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
> +				 struct intel_crtc *crtc);
> +void intel_psr2_program_trans_man_trk_ctl(const struct
> intel_crtc_state *crtc_state);
>  
>  #endif /* __INTEL_PSR_H__ */
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h
> index 2c2e88d49f3e..1f3fbec2f228 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -505,6 +505,7 @@ struct i915_psr {
>  	bool link_standby;
>  	bool colorimetry_support;
>  	bool psr2_enabled;
> +	bool psr2_sel_fetch_enabled;
>  	u8 sink_sync_latency;
>  	ktime_t last_entry_attempt;
>  	ktime_t last_exit;
> @@ -1653,6 +1654,7 @@ IS_SUBPLATFORM(const struct drm_i915_private
> *i915,
>  #define HAS_PSR(dev_priv)		 (INTEL_INFO(dev_priv)-
> >display.has_psr)
>  #define HAS_PSR_HW_TRACKING(dev_priv) \
>  	(INTEL_INFO(dev_priv)->display.has_psr_hw_tracking)
> +#define HAS_PSR2_SEL_FETCH(dev_priv)	 (INTEL_GEN(dev_priv) >= 12)
>  #define HAS_TRANSCODER(dev_priv, trans)	 ((INTEL_INFO(dev_priv)
> ->cpu_transcoder_mask & BIT(trans)) != 0)
>  
>  #define HAS_RC6(dev_priv)		 (INTEL_INFO(dev_priv)-
> >has_rc6)
> diff --git a/drivers/gpu/drm/i915/i915_params.c
> b/drivers/gpu/drm/i915/i915_params.c
> index 8d8db9ff0a48..7f139ea4a90b 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -102,6 +102,11 @@ i915_param_named(psr_safest_params, bool, 0400,
>  	"is helpful to detect if PSR issues are related to bad values
> set in "
>  	" VBT. (0=use VBT parameters, 1=use safest parameters)");
>  
> +i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400,
> +	"Enable PSR2 selective fetch "
> +	"(0=disabled, 1=enabled) "
> +	"Default: 0");
> +
>  i915_param_named_unsafe(force_probe, charp, 0400,
>  	"Force probe the driver for specified devices. "
>  	"See CONFIG_DRM_I915_FORCE_PROBE for details.");
> diff --git a/drivers/gpu/drm/i915/i915_params.h
> b/drivers/gpu/drm/i915/i915_params.h
> index 53fb5ba8fbed..330c03e2b4f7 100644
> --- a/drivers/gpu/drm/i915/i915_params.h
> +++ b/drivers/gpu/drm/i915/i915_params.h
> @@ -54,6 +54,7 @@ struct drm_printer;
>  	param(int, enable_fbc, -1, 0600) \
>  	param(int, enable_psr, -1, 0600) \
>  	param(bool, psr_safest_params, false, 0600) \
> +	param(bool, enable_psr2_sel_fetch, false, 0600) \
>  	param(int, disable_power_well, -1, 0400) \
>  	param(int, enable_ips, 1, 0600) \
>  	param(int, invert_brightness, 0, 0600) \
As per the base implementation point of view, it looks good to me.
But while the mouse pointer moves on the screen, the mouse pointer
movement showed stuttering motion. 
( gdm, weston and gnome-mutter on TGL).
When the PSR2 selective update is coming, we should fix this.
For now, it is not enabled by default (it can be enabled by boot
parameter (i915.enable_psr2_sel_fetch=1)),
Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun at intel.com>


More information about the Intel-gfx mailing list