Message ID | 20240624191032.27333-8-ville.syrjala@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/i915/dsb: Use chained DSBs for LUT programming | expand |
> -----Original Message----- > From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf Of Ville > Syrjala > Sent: Tuesday, June 25, 2024 12:40 AM > To: intel-gfx@lists.freedesktop.org > Subject: [PATCH 07/14] drm/i915/dsb: Account for VRR properly in DSB > scanline stuff > > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > When determining various scanlines for DSB use we should take into account > whether VRR is active at the time when the DSB uses said scanline > information. For now all DSB scanline usage occurs prior to the actual > commit, so we only need to care about the state of VRR at that time. > > I've decided to move intel_crtc_scanline_to_hw() in its entirety to the DSB > code as it will also need to know the actual state of VRR in order to do its job > 100% correctly. > > TODO: figure out how much of this could be moved to some > more generic place and perhaps be shared with the CPU > vblank evasion code/etc... > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Animesh Manna <animesh.manna@intel.com> > --- > drivers/gpu/drm/i915/display/intel_display.c | 4 +- > drivers/gpu/drm/i915/display/intel_display.h | 3 + > drivers/gpu/drm/i915/display/intel_dsb.c | 65 ++++++++++++++++++-- > drivers/gpu/drm/i915/display/intel_vblank.c | 10 +-- > drivers/gpu/drm/i915/display/intel_vblank.h | 3 +- > 5 files changed, 67 insertions(+), 18 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c > b/drivers/gpu/drm/i915/display/intel_display.c > index 01a5faa3fea5..592483651b3c 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -1031,8 +1031,8 @@ static bool intel_crtc_vrr_enabling(struct > intel_atomic_state *state, > vrr_params_changed(old_crtc_state, new_crtc_state))); } > > -static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, > - struct intel_crtc *crtc) > +bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, > + struct intel_crtc *crtc) > { > const struct intel_crtc_state *old_crtc_state = > intel_atomic_get_old_crtc_state(state, crtc); diff --git > a/drivers/gpu/drm/i915/display/intel_display.h > b/drivers/gpu/drm/i915/display/intel_display.h > index b0cf6ca70952..b21d9578d5db 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.h > +++ b/drivers/gpu/drm/i915/display/intel_display.h > @@ -532,6 +532,9 @@ void intel_plane_fixup_bitmasks(struct > intel_crtc_state *crtc_state); > > void intel_update_watermarks(struct drm_i915_private *i915); > > +bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, > + struct intel_crtc *crtc); > + > /* modesetting */ > int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, > const char *reason, u8 pipe_mask); diff -- > git a/drivers/gpu/drm/i915/display/intel_dsb.c > b/drivers/gpu/drm/i915/display/intel_dsb.c > index e871af5517b5..b362a3050c7f 100644 > --- a/drivers/gpu/drm/i915/display/intel_dsb.c > +++ b/drivers/gpu/drm/i915/display/intel_dsb.c > @@ -83,15 +83,72 @@ struct intel_dsb { > #define DSB_OPCODE_POLL 0xA > /* see DSB_REG_VALUE_MASK */ > > -static int dsb_dewake_scanline(const struct intel_crtc_state *crtc_state) > +static bool pre_commit_is_vrr_active(struct intel_atomic_state *state, > + struct intel_crtc *crtc) > { > - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); > + const struct intel_crtc_state *old_crtc_state = > + intel_atomic_get_old_crtc_state(state, crtc); > + const struct intel_crtc_state *new_crtc_state = > + intel_atomic_get_new_crtc_state(state, crtc); > + > + /* VRR will be enabled afterwards, if necessary */ > + if (intel_crtc_needs_modeset(new_crtc_state)) > + return false; > + > + /* VRR will have been disabled during intel_pre_plane_update() */ > + return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, > +crtc); } > + > +static const struct intel_crtc_state * > +pre_commit_crtc_state(struct intel_atomic_state *state, > + struct intel_crtc *crtc) > +{ > + const struct intel_crtc_state *old_crtc_state = > + intel_atomic_get_old_crtc_state(state, crtc); > + const struct intel_crtc_state *new_crtc_state = > + intel_atomic_get_new_crtc_state(state, crtc); > + > + /* > + * During fastsets/etc. the transcoder is still > + * running with the old timings at this point. > + */ > + if (intel_crtc_needs_modeset(new_crtc_state)) > + return new_crtc_state; > + else > + return old_crtc_state; > +} > + > +static int dsb_vtotal(struct intel_atomic_state *state, > + struct intel_crtc *crtc) > +{ > + const struct intel_crtc_state *crtc_state = > +pre_commit_crtc_state(state, crtc); > + > + if (pre_commit_is_vrr_active(state, crtc)) > + return crtc_state->vrr.vmax; > + else > + return intel_mode_vtotal(&crtc_state->hw.adjusted_mode); > +} > + > +static int dsb_dewake_scanline(struct intel_atomic_state *state, > + struct intel_crtc *crtc) > +{ > + const struct intel_crtc_state *crtc_state = > pre_commit_crtc_state(state, crtc); > + struct drm_i915_private *i915 = to_i915(state->base.dev); > unsigned int latency = skl_watermark_max_latency(i915, 0); > > return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode) - > intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, > latency); } > > +static int dsb_scanline_to_hw(struct intel_atomic_state *state, > + struct intel_crtc *crtc, int scanline) { > + const struct intel_crtc_state *crtc_state = > pre_commit_crtc_state(state, crtc); > + int vtotal = dsb_vtotal(state, crtc); > + > + return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % > +vtotal; } > + > static u32 dsb_chicken(struct intel_crtc *crtc) { > if (crtc->mode_flags & I915_MODE_FLAG_VRR) @@ -489,8 +546,6 > @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, > unsigned int max_cmds) > { > struct drm_i915_private *i915 = to_i915(state->base.dev); > - const struct intel_crtc_state *crtc_state = > - intel_atomic_get_new_crtc_state(state, crtc); > intel_wakeref_t wakeref; > struct intel_dsb *dsb; > unsigned int size; > @@ -526,7 +581,7 @@ struct intel_dsb *intel_dsb_prepare(struct > intel_atomic_state *state, > dsb->ins_start_offset = 0; > > dsb->hw_dewake_scanline = > - intel_crtc_scanline_to_hw(crtc_state, > dsb_dewake_scanline(crtc_state)); > + dsb_scanline_to_hw(state, crtc, dsb_dewake_scanline(state, > crtc)); > > return dsb; > > diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c > b/drivers/gpu/drm/i915/display/intel_vblank.c > index 56c8033eec4c..71abc7354c3b 100644 > --- a/drivers/gpu/drm/i915/display/intel_vblank.c > +++ b/drivers/gpu/drm/i915/display/intel_vblank.c > @@ -190,7 +190,7 @@ static u32 > __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) > return scanline; > } > > -static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) > +int intel_crtc_scanline_offset(const struct intel_crtc_state > +*crtc_state) > { > struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); > > @@ -284,14 +284,6 @@ static int __intel_get_crtc_scanline(struct intel_crtc > *crtc) > return (position + vtotal + crtc->scanline_offset) % vtotal; } > > -int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state, > - int scanline) > -{ > - int vtotal = intel_mode_vtotal(&crtc_state->hw.adjusted_mode); > - > - return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % > vtotal; > -} > - > /* > * The uncore version of the spin lock functions is used to decide > * whether we need to lock the uncore lock or not. This is only diff --git > a/drivers/gpu/drm/i915/display/intel_vblank.h > b/drivers/gpu/drm/i915/display/intel_vblank.h > index 45a4a961aaab..6d7336256982 100644 > --- a/drivers/gpu/drm/i915/display/intel_vblank.h > +++ b/drivers/gpu/drm/i915/display/intel_vblank.h > @@ -40,7 +40,6 @@ void intel_wait_for_pipe_scanline_stopped(struct > intel_crtc *crtc); void intel_wait_for_pipe_scanline_moving(struct intel_crtc > *crtc); void intel_crtc_update_active_timings(const struct intel_crtc_state > *crtc_state, > bool vrr_enable); > -int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state, > - int scanline); > +int intel_crtc_scanline_offset(const struct intel_crtc_state > +*crtc_state); > > #endif /* __INTEL_VBLANK_H__ */ > -- > 2.44.2
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 01a5faa3fea5..592483651b3c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1031,8 +1031,8 @@ static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state, vrr_params_changed(old_crtc_state, new_crtc_state))); } -static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, - struct intel_crtc *crtc) +bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, + struct intel_crtc *crtc) { const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index b0cf6ca70952..b21d9578d5db 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -532,6 +532,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state); void intel_update_watermarks(struct drm_i915_private *i915); +bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, + struct intel_crtc *crtc); + /* modesetting */ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, const char *reason, u8 pipe_mask); diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index e871af5517b5..b362a3050c7f 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -83,15 +83,72 @@ struct intel_dsb { #define DSB_OPCODE_POLL 0xA /* see DSB_REG_VALUE_MASK */ -static int dsb_dewake_scanline(const struct intel_crtc_state *crtc_state) +static bool pre_commit_is_vrr_active(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + /* VRR will be enabled afterwards, if necessary */ + if (intel_crtc_needs_modeset(new_crtc_state)) + return false; + + /* VRR will have been disabled during intel_pre_plane_update() */ + return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, crtc); +} + +static const struct intel_crtc_state * +pre_commit_crtc_state(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + /* + * During fastsets/etc. the transcoder is still + * running with the old timings at this point. + */ + if (intel_crtc_needs_modeset(new_crtc_state)) + return new_crtc_state; + else + return old_crtc_state; +} + +static int dsb_vtotal(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + + if (pre_commit_is_vrr_active(state, crtc)) + return crtc_state->vrr.vmax; + else + return intel_mode_vtotal(&crtc_state->hw.adjusted_mode); +} + +static int dsb_dewake_scanline(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + struct drm_i915_private *i915 = to_i915(state->base.dev); unsigned int latency = skl_watermark_max_latency(i915, 0); return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode) - intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, latency); } +static int dsb_scanline_to_hw(struct intel_atomic_state *state, + struct intel_crtc *crtc, int scanline) +{ + const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + int vtotal = dsb_vtotal(state, crtc); + + return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal; +} + static u32 dsb_chicken(struct intel_crtc *crtc) { if (crtc->mode_flags & I915_MODE_FLAG_VRR) @@ -489,8 +546,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, unsigned int max_cmds) { struct drm_i915_private *i915 = to_i915(state->base.dev); - const struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); intel_wakeref_t wakeref; struct intel_dsb *dsb; unsigned int size; @@ -526,7 +581,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, dsb->ins_start_offset = 0; dsb->hw_dewake_scanline = - intel_crtc_scanline_to_hw(crtc_state, dsb_dewake_scanline(crtc_state)); + dsb_scanline_to_hw(state, crtc, dsb_dewake_scanline(state, crtc)); return dsb; diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 56c8033eec4c..71abc7354c3b 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -190,7 +190,7 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) return scanline; } -static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) +int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -284,14 +284,6 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) return (position + vtotal + crtc->scanline_offset) % vtotal; } -int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state, - int scanline) -{ - int vtotal = intel_mode_vtotal(&crtc_state->hw.adjusted_mode); - - return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal; -} - /* * The uncore version of the spin lock functions is used to decide * whether we need to lock the uncore lock or not. This is only diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h index 45a4a961aaab..6d7336256982 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.h +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -40,7 +40,6 @@ void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc); void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc); void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, bool vrr_enable); -int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state, - int scanline); +int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_VBLANK_H__ */