[Intel-gfx] [PATCH v2 4/5] drm/i915: Initial implementation of PSR2 selective fetch

Ville Syrjälä ville.syrjala at linux.intel.com
Tue Jun 30 15:33:41 UTC 2020


On Thu, Jun 25, 2020 at 06:01:50PM -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.
> 
> 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  |  3 +
>  .../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, 103 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index b66008b80589..eb3a4f317b01 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -15114,6 +15114,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)
> @@ -15155,6 +15157,7 @@ static void intel_update_crtc(struct intel_atomic_state *state,
>  			intel_color_load_luts(new_crtc_state);
>  
>  		intel_pre_plane_update(state, crtc);
> +		intel_psr2_sel_fetch_update(state, crtc);

You seem to be modifying the crtc state here. No good. Ideally the state
should be const for the whole programming step.

>  
>  		if (new_crtc_state->update_pipe)
>  			intel_encoders_update_pipe(state, crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index d1cb48b3f462..4c9591f7ed92 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 4b0aaa3081c9..44c98ae3964e 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 611cb8d74811..078987a878b0 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_FULL_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 9aad3ec979bd..038bd57e429e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -503,6 +503,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;
> @@ -1651,6 +1652,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 a7b61e6ec508..da686f8bcb09 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 helpfull to detect if PSR issues are related to bad values set in "
>  	" VBT. (0=use VBT paramters, 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) \
> -- 
> 2.27.0

-- 
Ville Syrjälä
Intel


More information about the Intel-gfx mailing list