Skip to content

Commit ec3a347

Browse files
committed
drm/i915/flipq: Implement flip queue based commit path
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) v4: Leave added_wake_time=0 when flip queue isn't used, to avoid needleslly increasing pkg_c_latency on lnl/ptl due to Wa_22020432604. This is a bit racy though... Use IS_DISPLAY_VER() Reviewed-by: Uma Shankar <[email protected]> Signed-off-by: Ville Syrjälä <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 470022b commit ec3a347

File tree

8 files changed

+75
-15
lines changed

8 files changed

+75
-15
lines changed

drivers/gpu/drm/i915/display/intel_display.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#include "intel_fbc.h"
9494
#include "intel_fdi.h"
9595
#include "intel_fifo_underrun.h"
96+
#include "intel_flipq.h"
9697
#include "intel_frontbuffer.h"
9798
#include "intel_hdmi.h"
9899
#include "intel_hotplug.h"
@@ -6619,7 +6620,7 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state,
66196620
intel_atomic_get_new_crtc_state(state, crtc);
66206621
bool modeset = intel_crtc_needs_modeset(new_crtc_state);
66216622

6622-
drm_WARN_ON(display->drm, new_crtc_state->use_dsb);
6623+
drm_WARN_ON(display->drm, new_crtc_state->use_dsb || new_crtc_state->use_flipq);
66236624

66246625
/*
66256626
* During modesets pipe configuration was programmed as the
@@ -6649,7 +6650,7 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
66496650
intel_atomic_get_new_crtc_state(state, crtc);
66506651
bool modeset = intel_crtc_needs_modeset(new_crtc_state);
66516652

6652-
drm_WARN_ON(display->drm, new_crtc_state->use_dsb);
6653+
drm_WARN_ON(display->drm, new_crtc_state->use_dsb || new_crtc_state->use_flipq);
66536654

66546655
/*
66556656
* Disable the scaler(s) after the plane(s) so that we don't
@@ -6738,10 +6739,10 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state,
67386739

67396740
if (!modeset &&
67406741
intel_crtc_needs_color_update(new_crtc_state) &&
6741-
!new_crtc_state->use_dsb)
6742+
!new_crtc_state->use_dsb && !new_crtc_state->use_flipq)
67426743
intel_color_commit_noarm(NULL, new_crtc_state);
67436744

6744-
if (!new_crtc_state->use_dsb)
6745+
if (!new_crtc_state->use_dsb && !new_crtc_state->use_flipq)
67456746
intel_crtc_planes_update_noarm(NULL, state, crtc);
67466747
}
67476748

@@ -6753,7 +6754,14 @@ static void intel_update_crtc(struct intel_atomic_state *state,
67536754
struct intel_crtc_state *new_crtc_state =
67546755
intel_atomic_get_new_crtc_state(state, crtc);
67556756

6756-
if (new_crtc_state->use_dsb) {
6757+
if (new_crtc_state->use_flipq) {
6758+
intel_flipq_enable(new_crtc_state);
6759+
6760+
intel_crtc_prepare_vblank_event(new_crtc_state, &crtc->flipq_event);
6761+
6762+
intel_flipq_add(crtc, INTEL_FLIPQ_PLANE_1, 0, INTEL_DSB_0,
6763+
new_crtc_state->dsb_commit);
6764+
} else if (new_crtc_state->use_dsb) {
67576765
intel_crtc_prepare_vblank_event(new_crtc_state, &crtc->dsb_event);
67586766

67596767
intel_dsb_commit(new_crtc_state->dsb_commit);
@@ -7191,7 +7199,17 @@ static void intel_atomic_dsb_prepare(struct intel_atomic_state *state,
71917199
return;
71927200

71937201
/* FIXME deal with everything */
7202+
new_crtc_state->use_flipq =
7203+
intel_flipq_supported(display) &&
7204+
!new_crtc_state->do_async_flip &&
7205+
!new_crtc_state->vrr.enable &&
7206+
!new_crtc_state->has_psr &&
7207+
!intel_crtc_needs_modeset(new_crtc_state) &&
7208+
!intel_crtc_needs_fastset(new_crtc_state) &&
7209+
!intel_crtc_needs_color_update(new_crtc_state);
7210+
71947211
new_crtc_state->use_dsb =
7212+
!new_crtc_state->use_flipq &&
71957213
!new_crtc_state->do_async_flip &&
71967214
(DISPLAY_VER(display) >= 20 || !new_crtc_state->has_psr) &&
71977215
!intel_crtc_needs_modeset(new_crtc_state) &&
@@ -7207,7 +7225,9 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
72077225
struct intel_crtc_state *new_crtc_state =
72087226
intel_atomic_get_new_crtc_state(state, crtc);
72097227

7210-
if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color)
7228+
if (!new_crtc_state->use_flipq &&
7229+
!new_crtc_state->use_dsb &&
7230+
!new_crtc_state->dsb_color)
72117231
return;
72127232

72137233
/*
@@ -7216,14 +7236,16 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
72167236
* Double that for pipe stuff and other overhead.
72177237
*/
72187238
new_crtc_state->dsb_commit = intel_dsb_prepare(state, crtc, INTEL_DSB_0,
7219-
new_crtc_state->use_dsb ? 1024 : 16);
7239+
new_crtc_state->use_dsb ||
7240+
new_crtc_state->use_flipq ? 1024 : 16);
72207241
if (!new_crtc_state->dsb_commit) {
7242+
new_crtc_state->use_flipq = false;
72217243
new_crtc_state->use_dsb = false;
72227244
intel_color_cleanup_commit(new_crtc_state);
72237245
return;
72247246
}
72257247

7226-
if (new_crtc_state->use_dsb) {
7248+
if (new_crtc_state->use_flipq || new_crtc_state->use_dsb) {
72277249
if (intel_crtc_needs_color_update(new_crtc_state))
72287250
intel_color_commit_noarm(new_crtc_state->dsb_commit,
72297251
new_crtc_state);
@@ -7238,7 +7260,8 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
72387260
intel_psr_trigger_frame_change_event(new_crtc_state->dsb_commit,
72397261
state, crtc);
72407262

7241-
intel_dsb_vblank_evade(state, new_crtc_state->dsb_commit);
7263+
if (new_crtc_state->use_dsb)
7264+
intel_dsb_vblank_evade(state, new_crtc_state->dsb_commit);
72427265

72437266
if (intel_crtc_needs_color_update(new_crtc_state))
72447267
intel_color_commit_arm(new_crtc_state->dsb_commit,
@@ -7417,6 +7440,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
74177440

74187441
if (!state->base.legacy_cursor_update && !new_crtc_state->use_dsb)
74197442
intel_vrr_check_push_sent(NULL, new_crtc_state);
7443+
7444+
if (new_crtc_state->use_flipq)
7445+
intel_flipq_disable(new_crtc_state);
74207446
}
74217447

74227448
/*

drivers/gpu/drm/i915/display/intel_display_params.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ intel_display_param_named_unsafe(enable_dpt, bool, 0400,
6262
intel_display_param_named_unsafe(enable_dsb, bool, 0400,
6363
"Enable display state buffer (DSB) (default: true)");
6464

65+
intel_display_param_named_unsafe(enable_flipq, bool, 0400,
66+
"Enable DMC flip queue (default: false)");
67+
6568
intel_display_param_named_unsafe(enable_sagv, bool, 0400,
6669
"Enable system agent voltage/frequency scaling (SAGV) (default: true)");
6770

drivers/gpu/drm/i915/display/intel_display_params.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct drm_printer;
3131
param(int, enable_dc, -1, 0400) \
3232
param(bool, enable_dpt, true, 0400) \
3333
param(bool, enable_dsb, true, 0600) \
34+
param(bool, enable_flipq, false, 0600) \
3435
param(bool, enable_sagv, true, 0600) \
3536
param(int, disable_power_well, -1, 0400) \
3637
param(bool, enable_ips, true, 0600) \

drivers/gpu/drm/i915/display/intel_display_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,7 @@ struct intel_crtc_state {
13051305
/* For DSB based pipe updates */
13061306
struct intel_dsb *dsb_color, *dsb_commit;
13071307
bool use_dsb;
1308+
bool use_flipq;
13081309

13091310
u32 psr2_man_track_ctl;
13101311

@@ -1412,6 +1413,8 @@ struct intel_crtc {
14121413
struct drm_pending_vblank_event *flip_done_event;
14131414
/* armed event for DSB based updates */
14141415
struct drm_pending_vblank_event *dsb_event;
1416+
/* armed event for flip queue based updates */
1417+
struct drm_pending_vblank_event *flipq_event;
14151418

14161419
/* Access to these should be protected by display->irq.lock. */
14171420
bool cpu_fifo_underrun_disabled;

drivers/gpu/drm/i915/display/intel_dmc.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,8 @@ static u32 pipedmc_interrupt_mask(struct intel_display *display)
501501
* triggering it during the first DC state transition. Figure
502502
* out what is going on...
503503
*/
504-
return PIPEDMC_GTT_FAULT |
504+
return PIPEDMC_FLIPQ_PROG_DONE |
505+
PIPEDMC_GTT_FAULT |
505506
PIPEDMC_ATS_FAULT;
506507
}
507508

@@ -1608,12 +1609,29 @@ void intel_dmc_debugfs_register(struct intel_display *display)
16081609
void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe)
16091610
{
16101611
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
1611-
u32 tmp;
1612+
u32 tmp = 0, int_vector;
16121613

16131614
if (DISPLAY_VER(display) >= 20) {
16141615
tmp = intel_de_read(display, PIPEDMC_INTERRUPT(pipe));
16151616
intel_de_write(display, PIPEDMC_INTERRUPT(pipe), tmp);
16161617

1618+
if (tmp & PIPEDMC_FLIPQ_PROG_DONE) {
1619+
spin_lock(&display->drm->event_lock);
1620+
1621+
if (crtc->flipq_event) {
1622+
/*
1623+
* Update vblank counter/timestamp in case it
1624+
* hasn't been done yet for this frame.
1625+
*/
1626+
drm_crtc_accurate_vblank_count(&crtc->base);
1627+
1628+
drm_crtc_send_vblank_event(&crtc->base, crtc->flipq_event);
1629+
crtc->flipq_event = NULL;
1630+
}
1631+
1632+
spin_unlock(&display->drm->event_lock);
1633+
}
1634+
16171635
if (tmp & PIPEDMC_ATS_FAULT)
16181636
drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC ATS fault\n",
16191637
crtc->base.base.id, crtc->base.name);
@@ -1625,8 +1643,8 @@ void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe)
16251643
crtc->base.base.id, crtc->base.name);
16261644
}
16271645

1628-
tmp = intel_de_read(display, PIPEDMC_STATUS(pipe)) & PIPEDMC_INT_VECTOR_MASK;
1629-
if (tmp)
1646+
int_vector = intel_de_read(display, PIPEDMC_STATUS(pipe)) & PIPEDMC_INT_VECTOR_MASK;
1647+
if (tmp == 0 && int_vector != 0)
16301648
drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC interrupt vector 0x%x\n",
16311649
crtc->base.base.id, crtc->base.name, tmp);
16321650
}

drivers/gpu/drm/i915/display/intel_flipq.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ static void intel_flipq_crtc_init(struct intel_crtc *crtc)
112112

113113
bool intel_flipq_supported(struct intel_display *display)
114114
{
115+
if (!display->params.enable_flipq)
116+
return false;
117+
115118
if (!display->dmc.dmc)
116119
return false;
117120

@@ -140,7 +143,7 @@ static int cdclk_factor(struct intel_display *display)
140143
return 280;
141144
}
142145

143-
static int intel_flipq_exec_time_us(struct intel_display *display)
146+
int intel_flipq_exec_time_us(struct intel_display *display)
144147
{
145148
return intel_dsb_exec_time_us() +
146149
DIV_ROUND_UP(display->cdclk.hw.cdclk * cdclk_factor(display), 540000) +

drivers/gpu/drm/i915/display/intel_flipq.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ void intel_flipq_add(struct intel_crtc *crtc,
2828
unsigned int pts,
2929
enum intel_dsb_id dsb_id,
3030
struct intel_dsb *dsb);
31+
int intel_flipq_exec_time_us(struct intel_display *display);
3132

3233
#endif /* __INTEL_FLIPQ_H__ */

drivers/gpu/drm/i915/display/skl_watermark.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "intel_display_types.h"
2727
#include "intel_fb.h"
2828
#include "intel_fixed.h"
29+
#include "intel_flipq.h"
2930
#include "intel_pcode.h"
3031
#include "intel_plane.h"
3132
#include "intel_wm.h"
@@ -2897,11 +2898,15 @@ intel_program_dpkgc_latency(struct intel_atomic_state *state)
28972898

28982899
latency = skl_watermark_max_latency(display, 1);
28992900

2901+
/* FIXME runtime changes to enable_flipq are racy */
2902+
if (display->params.enable_flipq)
2903+
added_wake_time = intel_flipq_exec_time_us(display);
2904+
29002905
/*
29012906
* Wa_22020432604
29022907
* "PKG_C_LATENCY Added Wake Time field is not working"
29032908
*/
2904-
if (latency && (DISPLAY_VER(display) == 20 || DISPLAY_VER(display) == 30)) {
2909+
if (latency && IS_DISPLAY_VER(display, 20, 30)) {
29052910
latency += added_wake_time;
29062911
added_wake_time = 0;
29072912
}

0 commit comments

Comments
 (0)