[Intel-gfx] [PATCH v3] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier
Kahola, Mika
mika.kahola at intel.com
Mon Nov 6 09:09:09 UTC 2023
> -----Original Message-----
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Sent: Monday, November 6, 2023 10:54 AM
> To: Hogander, Jouni <jouni.hogander at intel.com>
> Cc: Kahola, Mika <mika.kahola at intel.com>; intel-gfx at lists.freedesktop.org
> Subject: Re: [PATCH v3] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier
>
> On Mon, Nov 06, 2023 at 08:40:52AM +0000, Hogander, Jouni wrote:
> > On Fri, 2023-11-03 at 11:32 +0200, 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)
> > >
> > > v2: Write frames before su entry to correct register (Ville, Jouni)
> > > Move frames before su entry calculation to it's
> > > own function (Ville, Jouni)
> > > Rename PSR Entry Setup Frames register to indicate
> > > Lunarlake specificity (Jouni)
> > > v3: Modify setup entry frames calculation function to
> > > return the actual frames (Ville)
> > > Match comment with actual implementation (Jouni)
> > >
> > > 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 | 82
> > > +++++++++++++++--
> > > --
> > > drivers/gpu/drm/i915/display/intel_psr_regs.h | 2 +
> > > 3 files changed, 71 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> > > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > > index 047fe3f8905a..92f06d67fd1e 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > > @@ -1708,6 +1708,7 @@ struct intel_psr {
> > > u32 dc3co_exitline;
> > > u32 dc3co_exit_delay;
> > > struct delayed_work dc3co_work;
> > > + u8 entry_setup_frames;
> > > };
> > >
> > > struct intel_dp {
> > > diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> > > b/drivers/gpu/drm/i915/display/intel_psr.c
> > > index ecd24a0b86cb..497e4c26f4a6 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 (DISPLAY_VER(dev_priv) >= 20)
> > > + val |= LNL_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);
> > > }
> > > @@ -727,11 +733,27 @@ static int psr2_block_count(struct intel_dp
> > > *intel_dp)
> > > return psr2_block_count_lines(intel_dp) / 4;
> > > }
> > >
> > > +static u8 get_frames_before_su_entry(struct intel_dp *intel_dp) {
> > > + u8 frames_before_su_entry;
> > > +
> > > + frames_before_su_entry = max_t(u8,
> > > + intel_dp-
> > > >psr.sink_sync_latency + 1,
> > > + 2);
> > > +
> > > + /* Entry setup frames must be at least 1 less than frames
> > > before SU entry */
> > > + if (intel_dp->psr.entry_setup_frames >=
> > > frames_before_su_entry)
> > > + frames_before_su_entry = intel_dp-
> > > >psr.entry_setup_frames + 1;
> > > +
> > > + return frames_before_su_entry; }
> > > +
> > > 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;
> > > u32 val = EDP_PSR2_ENABLE;
> > > + u32 psr_val = 0;
> > >
> > > val |=
> > > EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
> > >
> > > @@ -741,7 +763,8 @@ 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));
> > > + val |=
> > > EDP_PSR2_FRAME_BEFORE_SU(get_frames_before_su_entry(intel_dp));
> > > +
> > > val |= intel_psr2_get_tp_time(intel_dp);
> > >
> > > if (DISPLAY_VER(dev_priv) >= 12) { @@ -785,6 +808,9 @@
> > > 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;
> > >
> > > + if (DISPLAY_VER(dev_priv) >= 20)
> > > + psr_val |= LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp-
> > > >psr.entry_setup_frames);
> > > +
> > > if (intel_dp->psr.psr2_sel_fetch_enabled) {
> > > u32 tmp;
> > >
> > > @@ -798,7 +824,7 @@ static void hsw_activate_psr2(struct intel_dp
> > > *intel_dp)
> > > * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and
> > > BSpec is
> > > * recommending keep this bit unset while PSR2 is enabled.
> > > */
> > > - intel_de_write(dev_priv, psr_ctl_reg(dev_priv,
> > > cpu_transcoder), 0);
> > > + intel_de_write(dev_priv, psr_ctl_reg(dev_priv,
> > > cpu_transcoder), psr_val);
> > >
> > > intel_de_write(dev_priv, EDP_PSR2_CTL(cpu_transcoder), val);
> > > }
> > > @@ -1066,6 +1092,40 @@ static bool _compute_psr2_wake_times(struct
> > > intel_dp *intel_dp,
> > > return true;
> > > }
> > >
> > > +static u8 intel_psr_set_entry_setup_frames(struct intel_dp
> > > *intel_dp,
> > > + const struct
> > > drm_display_mode *adjusted_mode)
> >
> > I think "set" is not correct here. intel_psr_get_entry_setup_frames is
> > more appropriate.
>
> I don't really like either.
>
> We don't generally say eg. get_sin(x) either, it's just sin(x).
>
> So IMO the correct name would be just intel_psr_entry_setup_frames(), or perhaps intel_psr_num_entry_setup_frames(). That
> will make the code more like proper English when you read it outloud.
I was thinking while writing this that we set the register with this value but since we don't actually set the register here the naming would be better phrased.
>
> >
> > > +{
> > > + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> >
> > You should use name i915 here.
> >
> > > + int psr_setup_time = drm_dp_psr_setup_time(intel_dp-
> > > >psr_dpcd);
> > > + u8 entry_setup_frames = 0;
> > > +
> > > + if (psr_setup_time < 0) {
> > > + drm_dbg_kms(&dev_priv->drm,
> > > + "PSR condition failed: Invalid PSR setup
> > > time (0x%02x)\n",
> > > + intel_dp->psr_dpcd[1]);
> > > + return -ETIME;
> > > + }
> > > +
> > > +
> > > + if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time)
> > > +>
> > > + adjusted_mode->crtc_vtotal -
> > > +adjusted_mode->crtc_vdisplay
> > > - 1) {
> > > + if (DISPLAY_VER(dev_priv) >= 20) {
> > > + /* setup entry frames can be set up to 3
> > > frames */
> > > + entry_setup_frames = 1;
> > > + drm_dbg_kms(&dev_priv->drm,
> > > + "PSR setup entry frames set to
> > > %d\n",
> > > + entry_setup_frames);
> >
> > Don't refer "setting" here as this is just returning the value. Not
> > setting it.
>
> This kind of stuff should really all be moved to the crtc state proper, and then just dumped alongside everything else.
Probably this is not the optimal place for this and could be moved out. Maybe update to this patch?
Thanks!
-Mika-
>
> >
> > BR,
> >
> > Jouni Högander
> >
> > > + } else {
> > > + drm_dbg_kms(&dev_priv->drm,
> > > + "PSR condition failed: PSR setup
> > > time (%d us) too long\n",
> > > + psr_setup_time);
> > > + return -ETIME;
> > > + }
> > > + }
> > > +
> > > + return entry_setup_frames;
> > > +}
> > > +
> > > static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
> > > struct intel_crtc_state
> > > *crtc_state)
> > > {
> > > @@ -1213,7 +1273,7 @@ void intel_psr_compute_config(struct intel_dp
> > > *intel_dp,
> > > struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> > > const struct drm_display_mode *adjusted_mode =
> > > &crtc_state->hw.adjusted_mode;
> > > - int psr_setup_time;
> > > + u8 entry_setup_frames;
> > >
> > > /*
> > > * Current PSR panels don't work reliably with VRR enabled
> > > @@ -1242,19 +1302,13 @@ void intel_psr_compute_config(struct
> > > intel_dp *intel_dp,
> > > return;
> > > }
> > >
> > > - psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
> > > - if (psr_setup_time < 0) {
> > > - drm_dbg_kms(&dev_priv->drm,
> > > - "PSR condition failed: Invalid PSR setup
> > > time (0x%02x)\n",
> > > - intel_dp->psr_dpcd[1]);
> > > - return;
> > > - }
> > > + entry_setup_frames =
> > > intel_psr_set_entry_setup_frames(intel_dp, adjusted_mode);
> > >
> > > - if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time)
> > > >
> > > - adjusted_mode->crtc_vtotal -
> > > adjusted_mode->crtc_vdisplay
> > > - 1) {
> > > + if (entry_setup_frames >= 0) {
> > > + intel_dp->psr.entry_setup_frames =
> > > entry_setup_frames;
> > > + } else {
> > > drm_dbg_kms(&dev_priv->drm,
> > > - "PSR condition failed: PSR setup time
> > > (%d
> > > us) too long\n",
> > > - psr_setup_time);
> > > + "PSR condition failed: PSR setup timing
> > > not met\n");
> > > return;
> > > }
> > >
> > > diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h
> > > b/drivers/gpu/drm/i915/display/intel_psr_regs.h
> > > index d39951383c92..efe4306b37e0 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 LNL_EDP_PSR_ENTRY_SETUP_FRAMES_MASK REG_GENMASK(17, 16)
> > > +#define
> > > LNL_EDP_PSR_ENTRY_SETUP_FRAMES(x)
> > > REG_FIELD_PREP(LNL_EDP_PSR_ENTRY _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)
> >
>
> --
> Ville Syrjälä
> Intel
More information about the Intel-gfx
mailing list