[Intel-gfx] [PATCH] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier
Kahola, Mika
mika.kahola at intel.com
Thu Oct 26 10:42:40 UTC 2023
> -----Original Message-----
> From: Hogander, Jouni <jouni.hogander at intel.com>
> Sent: Wednesday, October 25, 2023 4:05 PM
> To: Kahola, Mika <mika.kahola at intel.com>; intel-gfx at lists.freedesktop.org
> Subject: Re: [PATCH] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier
>
> On Wed, 2023-10-25 at 12:46 +0300, Mika Kahola wrote:
> > Display driver shall read DPCD 00071h[3:1] during configuration to get
> > PSR setup time. This register provides the setup time requirement on
> > the VSC SDP entry packet. If setup time cannot be met with the current
> > timings (e.g., PSR setup time + other blanking requirements > blanking
> > time), driver should enable sending VSC SDP one frame earlier before
> > sending the capture frame.
> >
> > BSpec: 69895 (PSR Entry Setup Frames 17:16)
> >
> > Signed-off-by: Mika Kahola <mika.kahola at intel.com>
> > ---
> > .../drm/i915/display/intel_display_types.h | 1 +
> > drivers/gpu/drm/i915/display/intel_psr.c | 35 ++++++++++++++++-
> > --
> > drivers/gpu/drm/i915/display/intel_psr_regs.h | 2 ++
> > 3 files changed, 33 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 65ea37fe8cff..a0bcab6f2bec 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1710,6 +1710,7 @@ struct intel_psr {
> > u32 dc3co_exitline;
> > u32 dc3co_exit_delay;
> > struct delayed_work dc3co_work;
> > + u8 entry_setup_frames;
>
> eDP spec is speaking about 1 frame. Our HW seem to have possibility to have several.
That's true. The bitfield is two bits wide so anything from zero to three frames are, in theory, allowed.
Since the description talks only having one frame earlier, I sticked to this idea.
>
> > };
> >
> > struct intel_dp {
> > diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> > b/drivers/gpu/drm/i915/display/intel_psr.c
> > index 4f1f31fc9529..0acb4edae128 100644
> > --- a/drivers/gpu/drm/i915/display/intel_psr.c
> > +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> > @@ -592,6 +592,9 @@ static void intel_psr_enable_sink(struct intel_dp
> > *intel_dp)
> > if (intel_dp->psr.req_psr2_sdp_prior_scanline)
> > dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE;
> >
> > + if (intel_dp->psr.entry_setup_frames > 0)
> > + dpcd_val |= DP_PSR_FRAME_CAPTURE;
> > +
> > drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, dpcd_val);
> >
> > drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
> > DP_SET_POWER_D0); @@ -690,6 +693,9 @@ static void
> > hsw_activate_psr1(struct intel_dp
> > *intel_dp)
> > if (DISPLAY_VER(dev_priv) >= 8)
> > val |= EDP_PSR_CRC_ENABLE;
> >
> > + if (intel_dp->psr.entry_setup_frames > 0)
> > + val |= EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp-
> > >psr.entry_setup_frames);
> > +
> > intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder),
> > ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
> > }
> > @@ -731,6 +737,7 @@ static void hsw_activate_psr2(struct intel_dp
> > *intel_dp)
> > {
> > struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> > enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
> > + u8 frames_before_su_entry;
> > u32 val = EDP_PSR2_ENABLE;
> >
> > val |=
> > EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
> > @@ -741,7 +748,10 @@ static void hsw_activate_psr2(struct intel_dp
> > *intel_dp)
> > if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <=
> > 12)
> > val |= EDP_Y_COORDINATE_ENABLE;
> >
> > - val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, intel_dp-
> > >psr.sink_sync_latency + 1, 2));
> > + frames_before_su_entry = max_t(u8,
> > + intel_dp-
> > >psr.sink_sync_latency + 1,
> > + 2);
> > + val |= EDP_PSR2_FRAME_BEFORE_SU(frames_before_su_entry);
>
> I think you want to do this only once. Below or here.
This might end up as a separate function so I will program this value only once there.
>
> > val |= intel_psr2_get_tp_time(intel_dp);
> >
> > if (DISPLAY_VER(dev_priv) >= 12) { @@ -785,6 +795,14 @@ static
> > void hsw_activate_psr2(struct intel_dp
> > *intel_dp)
> > if (intel_dp->psr.req_psr2_sdp_prior_scanline)
> > val |= EDP_PSR2_SU_SDP_SCANLINE;
> >
> > + /* Entry setup frames must be at least 1 less than frames
> > before SU entry */
> > + if (intel_dp->psr.entry_setup_frames > 0) {
> > + val |= EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp-
> > >psr.entry_setup_frames);
>
> This is not the correct register. You want to have this in PSR_CTL (not PSR2_CTL).
Yes, this ends up in the wrong place. I'll fix this.
>
> > +
> > + if (intel_dp->psr.entry_setup_frames >=
> > frames_before_su_entry)
> > + val |=
> > EDP_PSR2_FRAME_BEFORE_SU(frames_before_su_entry + 1);
> > + }
> > +
>
> Here you are ORing second time. Please do it only once.
I will rewrite this so that this is done only once.
>
> > if (intel_dp->psr.psr2_sel_fetch_enabled) {
> > u32 tmp;
> >
> > @@ -1252,10 +1270,17 @@ void intel_psr_compute_config(struct intel_dp
> > *intel_dp,
> >
> > if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
> > adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay
> > - 1) {
> > - drm_dbg_kms(&dev_priv->drm,
> > - "PSR condition failed: PSR setup time (%d
> > us) too long\n",
> > - psr_setup_time);
> > - return;
> > + if (DISPLAY_VER(dev_priv) >= 20) {
> > + intel_dp->psr.entry_setup_frames = 1;
> > + drm_dbg_kms(&dev_priv->drm,
> > + "PSR setup entry frames: %d\n",
> > + intel_dp-
> > >psr.entry_setup_frames);
> > + } else {
> > + drm_dbg_kms(&dev_priv->drm,
> > + "PSR condition failed: PSR setup
> > time (%d us) too long\n",
> > + psr_setup_time);
> > + return;
> > + }
>
> Maybe you could add separate helper for this. E.g.
> _compute_psr_setup_frames().
Yes. That might be cleaner solution.
>
> > }
> >
> > crtc_state->has_psr = true;
> > diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h
> > b/drivers/gpu/drm/i915/display/intel_psr_regs.h
> > index d39951383c92..9414c4de5f6e 100644
> > --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
> > +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
> > @@ -35,6 +35,8 @@
> > #define
> > EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES REG_FIELD_PREP(EDP_PSR_MIN_LINK_
> > ENTRY_TIME_MASK, 3)
> > #define EDP_PSR_MAX_SLEEP_TIME_MASK REG_GENMASK(24, 20)
> > #define
> > EDP_PSR_MAX_SLEEP_TIME(x) REG_FIELD_PREP(EDP_PSR_MAX_SLEEP
> > _TIME_MASK, (x))
> > +#define EDP_PSR_ENTRY_SETUP_FRAMES_MASK REG_GENMASK(17, 16)
> > +#define
> > EDP_PSR_ENTRY_SETUP_FRAMES(x) REG_FIELD_PREP(EDP_PSR_E
>
> Maybe LNL prefix here could clarify that this is only in LNL and
> beyond.
Yes, this bitfield is only for LNL+. I will rename these so this will be more clearly indicated.
Thanks for review & comments!
Mika
>
> BR,
>
> Jouni Högander
>
> > NTRY_SETUP_FRAMES_MASK, (x))
> > #define EDP_PSR_SKIP_AUX_EXIT REG_BIT(12)
> > #define EDP_PSR_TP_MASK REG_BIT(11)
> > #define
> > EDP_PSR_TP_TP1_TP2 REG_FIELD_PREP(EDP_PSR_TP_MASK,
> > 0)
More information about the Intel-gfx
mailing list