Commit 21bb0415 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/dsb: Convert dewake_scanline to a hw scanline number earlier

Currently we switch from out software idea of a scanline
to the hw's idea of a scanline during the commit phase in
_intel_dsb_commit(). While that is slightly easier due to
fastsets fiddling with the timings, we'll also need to
generate proper hw scanline numbers already when emitting
DSB scanline wait instructions. So this approach won't
do in the future. Switch to hw scanline numbers earlier.

Also intel_dsb_dewake_scanline() itself already makes
some assumptions about VRR that don't take into account
VRR toggling during fastsets, so technically delaying
the sw->hw conversion doesn't even help us.

The other reason for delaying the conversion was that we
are using intel_get_crtc_scanline() during intel_dsb_commit()
which gives us the current sw scanline. But this is pretty
low level stuff anyway so just using raw PIPEDSL reads seems
fine here, and that of course gives us the hw scanline
directly, reducing the need to do so many conversions.

v2: Return the non-hw scanline from intel_dsb_dewake_scanline()
Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240624191032.27333-5-ville.syrjala@linux.intel.com
parent 81a1c37c
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_irq.h" #include "i915_irq.h"
#include "i915_reg.h"
#include "intel_crtc.h" #include "intel_crtc.h"
#include "intel_de.h" #include "intel_de.h"
#include "intel_display_types.h" #include "intel_display_types.h"
...@@ -42,7 +43,7 @@ struct intel_dsb { ...@@ -42,7 +43,7 @@ struct intel_dsb {
*/ */
unsigned int ins_start_offset; unsigned int ins_start_offset;
int dewake_scanline; int hw_dewake_scanline;
}; };
/** /**
...@@ -374,7 +375,7 @@ static u32 dsb_error_int_en(struct intel_display *display) ...@@ -374,7 +375,7 @@ static u32 dsb_error_int_en(struct intel_display *display)
} }
static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
int dewake_scanline) int hw_dewake_scanline)
{ {
struct intel_crtc *crtc = dsb->crtc; struct intel_crtc *crtc = dsb->crtc;
struct intel_display *display = to_intel_display(crtc->base.dev); struct intel_display *display = to_intel_display(crtc->base.dev);
...@@ -404,10 +405,8 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, ...@@ -404,10 +405,8 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id), intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf)); intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
if (dewake_scanline >= 0) { if (hw_dewake_scanline >= 0) {
int diff, hw_dewake_scanline; int diff, position;
hw_dewake_scanline = intel_crtc_scanline_to_hw(crtc, dewake_scanline);
intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id), intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id),
DSB_ENABLE_DEWAKE | DSB_ENABLE_DEWAKE |
...@@ -417,7 +416,9 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, ...@@ -417,7 +416,9 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
* Force DEwake immediately if we're already past * Force DEwake immediately if we're already past
* or close to racing past the target scanline. * or close to racing past the target scanline.
*/ */
diff = dewake_scanline - intel_get_crtc_scanline(crtc); position = intel_de_read_fw(display, PIPEDSL(display, pipe)) & PIPEDSL_LINE_MASK;
diff = hw_dewake_scanline - position;
intel_de_write_fw(display, DSB_PMCTRL_2(pipe, dsb->id), intel_de_write_fw(display, DSB_PMCTRL_2(pipe, dsb->id),
(diff >= 0 && diff < 5 ? DSB_FORCE_DEWAKE : 0) | (diff >= 0 && diff < 5 ? DSB_FORCE_DEWAKE : 0) |
DSB_BLOCK_DEWAKE_EXTENSION); DSB_BLOCK_DEWAKE_EXTENSION);
...@@ -439,7 +440,7 @@ void intel_dsb_commit(struct intel_dsb *dsb, ...@@ -439,7 +440,7 @@ void intel_dsb_commit(struct intel_dsb *dsb,
{ {
_intel_dsb_commit(dsb, _intel_dsb_commit(dsb,
wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0, wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0,
wait_for_vblank ? dsb->dewake_scanline : -1); wait_for_vblank ? dsb->hw_dewake_scanline : -1);
} }
void intel_dsb_wait(struct intel_dsb *dsb) void intel_dsb_wait(struct intel_dsb *dsb)
...@@ -527,7 +528,9 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state, ...@@ -527,7 +528,9 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
dsb->size = size / 4; /* in dwords */ dsb->size = size / 4; /* in dwords */
dsb->free_pos = 0; dsb->free_pos = 0;
dsb->ins_start_offset = 0; dsb->ins_start_offset = 0;
dsb->dewake_scanline = intel_dsb_dewake_scanline(crtc_state);
dsb->hw_dewake_scanline =
intel_crtc_scanline_to_hw(crtc_state, intel_dsb_dewake_scanline(crtc_state));
return dsb; return dsb;
......
...@@ -284,13 +284,12 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) ...@@ -284,13 +284,12 @@ 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(struct intel_crtc *crtc, int scanline) int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state,
int scanline)
{ {
const struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); int vtotal = intel_mode_vtotal(&crtc_state->hw.adjusted_mode);
const struct drm_display_mode *mode = &vblank->hwmode;
int vtotal = intel_mode_vtotal(mode);
return (scanline + vtotal - crtc->scanline_offset) % vtotal; return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal;
} }
/* /*
......
...@@ -40,6 +40,7 @@ void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc); ...@@ -40,6 +40,7 @@ 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(struct intel_crtc *crtc, int scanline); int intel_crtc_scanline_to_hw(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