> -----Original Message----- > From: Intel-gfx <intel-gfx-boun...@lists.freedesktop.org> On Behalf Of Ville > Syrjala > Sent: Monday, June 9, 2025 7:41 PM > To: intel-gfx@lists.freedesktop.org > Cc: intel...@lists.freedesktop.org > Subject: [PATCH v4 16/21] drm/i915/flipq: Implement flip queue based commit > path > > From: Ville Syrjälä <ville.syrj...@linux.intel.com> > > Support commits via the flip queue (as opposed to DSB or MMIO). > > As it's somewhat unknown if we can actually use it is currently gated behind > the > new use_flipq modparam, which defaults to disabled. > > The implementation has a bunch of limitations that would need real though to > solve: > - disabled when PSR is used > - disabled when VRR is used > - color management updates not performed via the flip queue > > v2: Don't use flip queue if there is no dmc > v3: Use intel_flipq_supported() > v3: Configure PKG_C_LATENCY appropriately > Ignore INT_VECTOR if there is a real PIPEDMC interrupt > (nothing in the hw appears to clear INT_VECTOR)
Changes Look Good to me. Reviewed-by: Uma Shankar <uma.shan...@intel.com> > Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com> > --- > drivers/gpu/drm/i915/display/intel_display.c | 44 +++++++++++++++---- > .../drm/i915/display/intel_display_params.c | 3 ++ > .../drm/i915/display/intel_display_params.h | 1 + > .../drm/i915/display/intel_display_types.h | 3 ++ > drivers/gpu/drm/i915/display/intel_dmc.c | 26 +++++++++-- > drivers/gpu/drm/i915/display/intel_flipq.c | 21 +++++---- > drivers/gpu/drm/i915/display/intel_flipq.h | 1 + > drivers/gpu/drm/i915/display/skl_watermark.c | 4 +- > 8 files changed, 80 insertions(+), 23 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c > b/drivers/gpu/drm/i915/display/intel_display.c > index 3f14f524fe17..04492cb9446a 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -94,6 +94,7 @@ > #include "intel_fbc.h" > #include "intel_fdi.h" > #include "intel_fifo_underrun.h" > +#include "intel_flipq.h" > #include "intel_frontbuffer.h" > #include "intel_hdmi.h" > #include "intel_hotplug.h" > @@ -6611,7 +6612,7 @@ static void commit_pipe_pre_planes(struct > intel_atomic_state *state, > intel_atomic_get_new_crtc_state(state, crtc); > bool modeset = intel_crtc_needs_modeset(new_crtc_state); > > - drm_WARN_ON(display->drm, new_crtc_state->use_dsb); > + drm_WARN_ON(display->drm, new_crtc_state->use_dsb || > +new_crtc_state->use_flipq); > > /* > * During modesets pipe configuration was programmed as the @@ - > 6641,7 +6642,7 @@ static void commit_pipe_post_planes(struct > intel_atomic_state *state, > intel_atomic_get_new_crtc_state(state, crtc); > bool modeset = intel_crtc_needs_modeset(new_crtc_state); > > - drm_WARN_ON(display->drm, new_crtc_state->use_dsb); > + drm_WARN_ON(display->drm, new_crtc_state->use_dsb || > +new_crtc_state->use_flipq); > > /* > * Disable the scaler(s) after the plane(s) so that we don't @@ -6730,10 > +6731,10 @@ static void intel_pre_update_crtc(struct intel_atomic_state > *state, > > if (!modeset && > intel_crtc_needs_color_update(new_crtc_state) && > - !new_crtc_state->use_dsb) > + !new_crtc_state->use_dsb && !new_crtc_state->use_flipq) > intel_color_commit_noarm(NULL, new_crtc_state); > > - if (!new_crtc_state->use_dsb) > + if (!new_crtc_state->use_dsb && !new_crtc_state->use_flipq) > intel_crtc_planes_update_noarm(NULL, state, crtc); } > > @@ -6745,7 +6746,14 @@ static void intel_update_crtc(struct intel_atomic_state > *state, > struct intel_crtc_state *new_crtc_state = > intel_atomic_get_new_crtc_state(state, crtc); > > - if (new_crtc_state->use_dsb) { > + if (new_crtc_state->use_flipq) { > + intel_flipq_enable(new_crtc_state); > + > + intel_crtc_prepare_vblank_event(new_crtc_state, &crtc- > >flipq_event); > + > + intel_flipq_add(crtc, INTEL_FLIPQ_PLANE_1, 0, INTEL_DSB_0, > + new_crtc_state->dsb_commit); > + } else if (new_crtc_state->use_dsb) { > intel_crtc_prepare_vblank_event(new_crtc_state, &crtc- > >dsb_event); > > intel_dsb_commit(new_crtc_state->dsb_commit); > @@ -7183,7 +7191,17 @@ static void intel_atomic_dsb_prepare(struct > intel_atomic_state *state, > return; > > /* FIXME deal with everything */ > + new_crtc_state->use_flipq = > + intel_flipq_supported(display) && > + !new_crtc_state->do_async_flip && > + !new_crtc_state->vrr.enable && > + !new_crtc_state->has_psr && > + !intel_crtc_needs_modeset(new_crtc_state) && > + !intel_crtc_needs_fastset(new_crtc_state) && > + !intel_crtc_needs_color_update(new_crtc_state); > + > new_crtc_state->use_dsb = > + !new_crtc_state->use_flipq && > !new_crtc_state->do_async_flip && > (DISPLAY_VER(display) >= 20 || !new_crtc_state->has_psr) && > !intel_crtc_needs_modeset(new_crtc_state) && @@ -7199,7 > +7217,9 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state > *state, > struct intel_crtc_state *new_crtc_state = > intel_atomic_get_new_crtc_state(state, crtc); > > - if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color) > + if (!new_crtc_state->use_flipq && > + !new_crtc_state->use_dsb && > + !new_crtc_state->dsb_color) > return; > > /* > @@ -7208,14 +7228,16 @@ static void intel_atomic_dsb_finish(struct > intel_atomic_state *state, > * Double that for pipe stuff and other overhead. > */ > new_crtc_state->dsb_commit = intel_dsb_prepare(state, crtc, > INTEL_DSB_0, > - new_crtc_state->use_dsb ? > 1024 : 16); > + new_crtc_state->use_dsb > || > + > new_crtc_state->use_flipq ? > 1024 : 16); > if (!new_crtc_state->dsb_commit) { > + new_crtc_state->use_flipq = false; > new_crtc_state->use_dsb = false; > intel_color_cleanup_commit(new_crtc_state); > return; > } > > - if (new_crtc_state->use_dsb) { > + if (new_crtc_state->use_flipq || new_crtc_state->use_dsb) { > if (intel_crtc_needs_color_update(new_crtc_state)) > intel_color_commit_noarm(new_crtc_state->dsb_commit, > new_crtc_state); > @@ -7230,7 +7252,8 @@ static void intel_atomic_dsb_finish(struct > intel_atomic_state *state, > intel_psr_trigger_frame_change_event(new_crtc_state- > >dsb_commit, > state, crtc); > > - intel_dsb_vblank_evade(state, new_crtc_state->dsb_commit); > + if (new_crtc_state->use_dsb) > + intel_dsb_vblank_evade(state, new_crtc_state- > >dsb_commit); > > if (intel_crtc_needs_color_update(new_crtc_state)) > intel_color_commit_arm(new_crtc_state->dsb_commit, > @@ -7409,6 +7432,9 @@ static void intel_atomic_commit_tail(struct > intel_atomic_state *state) > > if (!state->base.legacy_cursor_update && !new_crtc_state- > >use_dsb) > intel_vrr_check_push_sent(NULL, new_crtc_state); > + > + if (new_crtc_state->use_flipq) > + intel_flipq_disable(new_crtc_state); > } > > /* > diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c > b/drivers/gpu/drm/i915/display/intel_display_params.c > index c4f1ab43fc0c..75316247ee8a 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_params.c > +++ b/drivers/gpu/drm/i915/display/intel_display_params.c > @@ -62,6 +62,9 @@ intel_display_param_named_unsafe(enable_dpt, bool, 0400, > intel_display_param_named_unsafe(enable_dsb, bool, 0400, > "Enable display state buffer (DSB) (default: true)"); > > +intel_display_param_named_unsafe(enable_flipq, bool, 0400, > + "Enable DMC flip queue (default: false)"); > + > intel_display_param_named_unsafe(enable_sagv, bool, 0400, > "Enable system agent voltage/frequency scaling (SAGV) (default: true)"); > > diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h > b/drivers/gpu/drm/i915/display/intel_display_params.h > index 5317138e6044..784e6bae8615 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_params.h > +++ b/drivers/gpu/drm/i915/display/intel_display_params.h > @@ -31,6 +31,7 @@ struct drm_printer; > param(int, enable_dc, -1, 0400) \ > param(bool, enable_dpt, true, 0400) \ > param(bool, enable_dsb, true, 0600) \ > + param(bool, enable_flipq, false, 0600) \ > param(bool, enable_sagv, true, 0600) \ > param(int, disable_power_well, -1, 0400) \ > param(bool, enable_ips, true, 0600) \ > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h > b/drivers/gpu/drm/i915/display/intel_display_types.h > index 5b30b652e123..536a545cc387 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_types.h > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h > @@ -1299,6 +1299,7 @@ struct intel_crtc_state { > /* For DSB based pipe updates */ > struct intel_dsb *dsb_color, *dsb_commit; > bool use_dsb; > + bool use_flipq; > > u32 psr2_man_track_ctl; > > @@ -1406,6 +1407,8 @@ struct intel_crtc { > struct drm_pending_vblank_event *flip_done_event; > /* armed event for DSB based updates */ > struct drm_pending_vblank_event *dsb_event; > + /* armed event for flip queue based updates */ > + struct drm_pending_vblank_event *flipq_event; > > /* Access to these should be protected by display->irq.lock. */ > bool cpu_fifo_underrun_disabled; > diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c > b/drivers/gpu/drm/i915/display/intel_dmc.c > index e239e444eafe..f786666720de 100644 > --- a/drivers/gpu/drm/i915/display/intel_dmc.c > +++ b/drivers/gpu/drm/i915/display/intel_dmc.c > @@ -503,7 +503,8 @@ static u32 pipedmc_interrupt_mask(struct intel_display > *display) > * triggering it during the first DC state transition. Figure > * out what is going on... > */ > - return PIPEDMC_GTT_FAULT | > + return PIPEDMC_FLIPQ_PROG_DONE | > + PIPEDMC_GTT_FAULT | > PIPEDMC_ATS_FAULT; > } > > @@ -1518,12 +1519,29 @@ void intel_dmc_debugfs_register(struct intel_display > *display) void intel_pipedmc_irq_handler(struct intel_display *display, enum > pipe > pipe) { > struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); > - u32 tmp; > + u32 tmp = 0, int_vector; > > if (DISPLAY_VER(display) >= 20) { > tmp = intel_de_read(display, PIPEDMC_INTERRUPT(pipe)); > intel_de_write(display, PIPEDMC_INTERRUPT(pipe), tmp); > > + if (tmp & PIPEDMC_FLIPQ_PROG_DONE) { > + spin_lock(&display->drm->event_lock); > + > + if (crtc->flipq_event) { > + /* > + * Update vblank counter/timestamp in case it > + * hasn't been done yet for this frame. > + */ > + drm_crtc_accurate_vblank_count(&crtc->base); > + > + drm_crtc_send_vblank_event(&crtc->base, crtc- > >flipq_event); > + crtc->flipq_event = NULL; > + } > + > + spin_unlock(&display->drm->event_lock); > + } > + > if (tmp & PIPEDMC_ATS_FAULT) > drm_err_ratelimited(display->drm, "[CRTC:%d:%s] > PIPEDMC ATS fault\n", > crtc->base.base.id, > crtc->base.name); > @@ -1535,8 +1553,8 @@ void intel_pipedmc_irq_handler(struct intel_display > *display, enum pipe pipe) > crtc->base.base.id, crtc->base.name); > } > > - tmp = intel_de_read(display, PIPEDMC_STATUS(pipe)) & > PIPEDMC_INT_VECTOR_MASK; > - if (tmp) > + int_vector = intel_de_read(display, PIPEDMC_STATUS(pipe)) & > PIPEDMC_INT_VECTOR_MASK; > + if (tmp == 0 && int_vector != 0) > drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC interrupt > vector 0x%x\n", > crtc->base.base.id, crtc->base.name, tmp); } diff --git > a/drivers/gpu/drm/i915/display/intel_flipq.c > b/drivers/gpu/drm/i915/display/intel_flipq.c > index c9804cfe506a..2f5100c47059 100644 > --- a/drivers/gpu/drm/i915/display/intel_flipq.c > +++ b/drivers/gpu/drm/i915/display/intel_flipq.c > @@ -98,6 +98,9 @@ static void intel_flipq_crtc_init(struct intel_crtc *crtc) > > bool intel_flipq_supported(struct intel_display *display) { > + if (!display->params.enable_flipq) > + return false; > + > if (!display->dmc.dmc) > return false; > > @@ -126,13 +129,21 @@ static int cdclk_factor(struct intel_display *display) > return 280; > } > > -static int intel_flipq_exec_time_us(struct intel_display *display) > +int intel_flipq_exec_time_us(struct intel_display *display) > { > return intel_dsb_exec_time_us() + > DIV_ROUND_UP(display->cdclk.hw.cdclk * cdclk_factor(display), > 540000) + > display->sagv.block_time_us; > } > > +static int intel_flipq_exec_time_lines(const struct intel_crtc_state > +*crtc_state) { > + struct intel_display *display = to_intel_display(crtc_state); > + > + return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, > + intel_flipq_exec_time_us(display)); > +} > + > static int intel_flipq_preempt_timeout_ms(struct intel_display *display) { > return DIV_ROUND_UP(intel_flipq_exec_time_us(display), 1000); @@ - > 180,14 +191,6 @@ static void intel_flipq_sw_dmc_wake(struct intel_crtc *crtc) > intel_de_write(display, PIPEDMC_FPQ_CTL1(crtc->pipe), > PIPEDMC_SW_DMC_WAKE); } > > -static int intel_flipq_exec_time_lines(const struct intel_crtc_state > *crtc_state) -{ > - struct intel_display *display = to_intel_display(crtc_state); > - > - return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, > - intel_flipq_exec_time_us(display)); > -} > - > void intel_flipq_reset(struct intel_display *display, enum pipe pipe) { > struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); diff --git > a/drivers/gpu/drm/i915/display/intel_flipq.h > b/drivers/gpu/drm/i915/display/intel_flipq.h > index 64d3c2a5bb7b..195ff0dd83f5 100644 > --- a/drivers/gpu/drm/i915/display/intel_flipq.h > +++ b/drivers/gpu/drm/i915/display/intel_flipq.h > @@ -28,5 +28,6 @@ void intel_flipq_add(struct intel_crtc *crtc, > unsigned int pts, > enum intel_dsb_id dsb_id, > struct intel_dsb *dsb); > +int intel_flipq_exec_time_us(struct intel_display *display); > > #endif /* __INTEL_FLIPQ_H__ */ > diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c > b/drivers/gpu/drm/i915/display/skl_watermark.c > index a3a28cff3e32..f8d8a6ac0646 100644 > --- a/drivers/gpu/drm/i915/display/skl_watermark.c > +++ b/drivers/gpu/drm/i915/display/skl_watermark.c > @@ -26,6 +26,7 @@ > #include "intel_display_types.h" > #include "intel_fb.h" > #include "intel_fixed.h" > +#include "intel_flipq.h" > #include "intel_pcode.h" > #include "intel_wm.h" > #include "skl_universal_plane_regs.h" > @@ -2938,7 +2939,7 @@ void > intel_program_dpkgc_latency(struct intel_atomic_state *state) { > struct intel_display *display = to_intel_display(state); > - int max_linetime, latency, added_wake_time = 0; > + int max_linetime, latency, added_wake_time; > > if (DISPLAY_VER(display) < 20) > return; > @@ -2946,6 +2947,7 @@ intel_program_dpkgc_latency(struct intel_atomic_state > *state) > mutex_lock(&display->wm.wm_mutex); > > latency = skl_watermark_max_latency(display, 1); > + added_wake_time = intel_flipq_exec_time_us(display); > > /* > * Wa_22020432604 > -- > 2.49.0