Commit a69dcaf9 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/dsb: Account for VRR properly in DSB scanline stuff

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: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240624191032.27333-8-ville.syrjala@linux.intel.comReviewed-by: default avatarAnimesh Manna <animesh.manna@intel.com>
parent eb4556f2
...@@ -1032,8 +1032,8 @@ static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state, ...@@ -1032,8 +1032,8 @@ static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state,
vrr_params_changed(old_crtc_state, new_crtc_state))); vrr_params_changed(old_crtc_state, new_crtc_state)));
} }
static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
struct intel_crtc *crtc) struct intel_crtc *crtc)
{ {
const struct intel_crtc_state *old_crtc_state = const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc); intel_atomic_get_old_crtc_state(state, crtc);
......
...@@ -532,6 +532,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state); ...@@ -532,6 +532,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
void intel_update_watermarks(struct drm_i915_private *i915); void intel_update_watermarks(struct drm_i915_private *i915);
bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
struct intel_crtc *crtc);
/* modesetting */ /* modesetting */
int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
const char *reason, u8 pipe_mask); const char *reason, u8 pipe_mask);
......
...@@ -83,15 +83,72 @@ struct intel_dsb { ...@@ -83,15 +83,72 @@ struct intel_dsb {
#define DSB_OPCODE_POLL 0xA #define DSB_OPCODE_POLL 0xA
/* see DSB_REG_VALUE_MASK */ /* 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); unsigned int latency = skl_watermark_max_latency(i915, 0);
return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode) - return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode) -
intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, latency); 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) static u32 dsb_chicken(struct intel_crtc *crtc)
{ {
if (crtc->mode_flags & I915_MODE_FLAG_VRR) if (crtc->mode_flags & I915_MODE_FLAG_VRR)
...@@ -487,8 +544,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, ...@@ -487,8 +544,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
unsigned int max_cmds) unsigned int max_cmds)
{ {
struct drm_i915_private *i915 = to_i915(state->base.dev); 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; intel_wakeref_t wakeref;
struct intel_dsb *dsb; struct intel_dsb *dsb;
unsigned int size; unsigned int size;
...@@ -524,7 +579,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, ...@@ -524,7 +579,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
dsb->ins_start_offset = 0; dsb->ins_start_offset = 0;
dsb->hw_dewake_scanline = 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; return dsb;
......
...@@ -190,7 +190,7 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) ...@@ -190,7 +190,7 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc)
return scanline; 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 intel_display *display = to_intel_display(crtc_state); struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 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) ...@@ -284,14 +284,6 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
return (position + vtotal + crtc->scanline_offset) % vtotal; 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 * 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 * whether we need to lock the uncore lock or not. This is only
......
...@@ -40,7 +40,6 @@ void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc); ...@@ -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_wait_for_pipe_scanline_moving(struct intel_crtc *crtc);
void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
bool vrr_enable); bool vrr_enable);
int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state, int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state);
int scanline);
#endif /* __INTEL_VBLANK_H__ */ #endif /* __INTEL_VBLANK_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment