[PATCH v4 16/21] drm/i915/flipq: Implement flip queue based commit path

Shankar, Uma uma.shankar at intel.com
Mon Jun 23 19:58:37 UTC 2025



> -----Original Message-----
> From: Intel-gfx <intel-gfx-bounces at lists.freedesktop.org> On Behalf Of Ville
> Syrjala
> Sent: Monday, June 9, 2025 7:41 PM
> To: intel-gfx at lists.freedesktop.org
> Cc: intel-xe at lists.freedesktop.org
> Subject: [PATCH v4 16/21] drm/i915/flipq: Implement flip queue based commit
> path
> 
> From: Ville Syrjälä <ville.syrjala at 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.shankar at intel.com>

> Signed-off-by: Ville Syrjälä <ville.syrjala at 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



More information about the Intel-xe mailing list