[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