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.syrj...@linux.intel.com>
> Cc: Imre Deak <imre.d...@intel.com>
> Cc: Gwan-gyeong Mun <gwan-gyeong....@intel.com>
> Cc: Rodrigo Vivi <rodrigo.v...@intel.com>
> Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com>
> Signed-off-by: José Roberto de Souza <jose.so...@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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to