Skip to content

Commit 45c5486

Browse files
committed
drm/i915/dsb: Use DSB for plane/color management updates
Push regular plane/color management updates to the DSB, if other constraints allow it. The first part of the sequence will go as follows: - CPU will kick off DSB0 immediately - DSB0 writes double bufferd non-arming registers - DSB0 evades the vblank - DSB0 writes double buffered arming registers If no color management updates is needed we follow that up with: - DSB0 waits for the undelayed vblank - DSB0 waits for the delayed vblank (usec wait) - DSB0 emits an interrupt which will cause the CPU to complete the commit If color management update is needed: - DSB0 will start DSB1 with wait for undelayed vblank - DSB0 will in parallel perform the force DEwake tricks - DSB1 writes single buffered LUT registers - DSB1 waits for the delayed vblank (usec wait) - DSB1 emits an interrupt which will cause the CPU to complete the commit With this sequence we don't need to increase the vblank delay to make room for register programming during vblank, which is a good thing for high refresh rate display. But I'll need to still think of some way to eliminate VRR commit completion related races under this scheme. Stuff that isn't ready for DSB yet: - modesets (potentially we could do at least the plane enabling via DSB) - fastsets - VRR - PSR - scalers - async flips Reviewed-by: Animesh Manna <[email protected]> Signed-off-by: Ville Syrjälä <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent a6d4d97 commit 45c5486

File tree

5 files changed

+128
-40
lines changed

5 files changed

+128
-40
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
276276
crtc_state->fb_bits = 0;
277277
crtc_state->update_planes = 0;
278278
crtc_state->dsb_color_vblank = NULL;
279-
crtc_state->dsb_color_commit = NULL;
279+
crtc_state->dsb_commit = NULL;
280+
crtc_state->use_dsb = false;
280281

281282
return &crtc_state->uapi;
282283
}
@@ -311,7 +312,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
311312
struct intel_crtc_state *crtc_state = to_intel_crtc_state(state);
312313

313314
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank);
314-
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_commit);
315+
drm_WARN_ON(crtc->dev, crtc_state->dsb_commit);
315316

316317
__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
317318
intel_crtc_free_hw_state(crtc_state);

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

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,9 +1913,6 @@ void intel_color_commit_arm(struct intel_dsb *dsb,
19131913
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
19141914

19151915
i915->display.funcs.color->color_commit_arm(dsb, crtc_state);
1916-
1917-
if (crtc_state->dsb_color_commit)
1918-
intel_dsb_commit(crtc_state->dsb_color_commit, false);
19191916
}
19201917

19211918
void intel_color_post_update(const struct intel_crtc_state *crtc_state)
@@ -1966,28 +1963,14 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
19661963

19671964
i915->display.funcs.color->load_luts(crtc_state);
19681965

1969-
intel_dsb_finish(crtc_state->dsb_color_vblank);
1966+
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
1967+
intel_dsb_interrupt(crtc_state->dsb_color_vblank);
19701968

1971-
crtc_state->dsb_color_commit = intel_dsb_prepare(state, crtc, INTEL_DSB_0, 16);
1972-
if (!crtc_state->dsb_color_commit) {
1973-
intel_dsb_cleanup(crtc_state->dsb_color_vblank);
1974-
crtc_state->dsb_color_vblank = NULL;
1975-
return;
1976-
}
1977-
1978-
intel_dsb_chain(state, crtc_state->dsb_color_commit,
1979-
crtc_state->dsb_color_vblank, true);
1980-
1981-
intel_dsb_finish(crtc_state->dsb_color_commit);
1969+
intel_dsb_finish(crtc_state->dsb_color_vblank);
19821970
}
19831971

19841972
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
19851973
{
1986-
if (crtc_state->dsb_color_commit) {
1987-
intel_dsb_cleanup(crtc_state->dsb_color_commit);
1988-
crtc_state->dsb_color_commit = NULL;
1989-
}
1990-
19911974
if (crtc_state->dsb_color_vblank) {
19921975
intel_dsb_cleanup(crtc_state->dsb_color_vblank);
19931976
crtc_state->dsb_color_vblank = NULL;
@@ -1996,8 +1979,6 @@ void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
19961979

19971980
void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
19981981
{
1999-
if (crtc_state->dsb_color_commit)
2000-
intel_dsb_wait(crtc_state->dsb_color_commit);
20011982
if (crtc_state->dsb_color_vblank)
20021983
intel_dsb_wait(crtc_state->dsb_color_vblank);
20031984
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,11 @@ int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
416416
static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_state)
417417
{
418418
return crtc_state->hw.active &&
419-
!intel_crtc_needs_modeset(crtc_state) &&
420419
!crtc_state->preload_luts &&
420+
!intel_crtc_needs_modeset(crtc_state) &&
421421
intel_crtc_needs_color_update(crtc_state) &&
422-
!intel_color_uses_dsb(crtc_state);
422+
!intel_color_uses_dsb(crtc_state) &&
423+
!crtc_state->use_dsb;
423424
}
424425

425426
static void intel_crtc_vblank_work(struct kthread_work *base)

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

Lines changed: 116 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7070,7 +7070,7 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state,
70707070
* During modesets pipe configuration was programmed as the
70717071
* CRTC was enabled.
70727072
*/
7073-
if (!modeset) {
7073+
if (!modeset && !new_crtc_state->use_dsb) {
70747074
if (intel_crtc_needs_color_update(new_crtc_state))
70757075
intel_color_commit_arm(NULL, new_crtc_state);
70767076

@@ -7172,10 +7172,12 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state,
71727172
drm_WARN_ON(&i915->drm, !intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF));
71737173

71747174
if (!modeset &&
7175-
intel_crtc_needs_color_update(new_crtc_state))
7175+
intel_crtc_needs_color_update(new_crtc_state) &&
7176+
!new_crtc_state->use_dsb)
71767177
intel_color_commit_noarm(NULL, new_crtc_state);
71777178

7178-
intel_crtc_planes_update_noarm(NULL, state, crtc);
7179+
if (!new_crtc_state->use_dsb)
7180+
intel_crtc_planes_update_noarm(NULL, state, crtc);
71797181
}
71807182

71817183
static void intel_update_crtc(struct intel_atomic_state *state,
@@ -7186,16 +7188,25 @@ static void intel_update_crtc(struct intel_atomic_state *state,
71867188
struct intel_crtc_state *new_crtc_state =
71877189
intel_atomic_get_new_crtc_state(state, crtc);
71887190

7189-
/* Perform vblank evasion around commit operation */
7190-
intel_pipe_update_start(state, crtc);
7191+
if (new_crtc_state->use_dsb) {
7192+
intel_crtc_prepare_vblank_event(new_crtc_state, &crtc->dsb_event);
7193+
7194+
intel_dsb_commit(new_crtc_state->dsb_commit, false);
7195+
} else {
7196+
/* Perform vblank evasion around commit operation */
7197+
intel_pipe_update_start(state, crtc);
7198+
7199+
if (new_crtc_state->dsb_commit)
7200+
intel_dsb_commit(new_crtc_state->dsb_commit, false);
71917201

7192-
commit_pipe_pre_planes(state, crtc);
7202+
commit_pipe_pre_planes(state, crtc);
71937203

7194-
intel_crtc_planes_update_arm(NULL, state, crtc);
7204+
intel_crtc_planes_update_arm(NULL, state, crtc);
71957205

7196-
commit_pipe_post_planes(state, crtc);
7206+
commit_pipe_post_planes(state, crtc);
71977207

7198-
intel_pipe_update_end(state, crtc);
7208+
intel_pipe_update_end(state, crtc);
7209+
}
71997210

72007211
/*
72017212
* VRR/Seamless M/N update may need to update frame timings.
@@ -7520,6 +7531,24 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat
75207531
}
75217532
}
75227533

7534+
static void intel_atomic_dsb_wait_commit(struct intel_crtc_state *crtc_state)
7535+
{
7536+
if (crtc_state->dsb_commit)
7537+
intel_dsb_wait(crtc_state->dsb_commit);
7538+
7539+
intel_color_wait_commit(crtc_state);
7540+
}
7541+
7542+
static void intel_atomic_dsb_cleanup(struct intel_crtc_state *crtc_state)
7543+
{
7544+
if (crtc_state->dsb_commit) {
7545+
intel_dsb_cleanup(crtc_state->dsb_commit);
7546+
crtc_state->dsb_commit = NULL;
7547+
}
7548+
7549+
intel_color_cleanup_commit(crtc_state);
7550+
}
7551+
75237552
static void intel_atomic_cleanup_work(struct work_struct *work)
75247553
{
75257554
struct intel_atomic_state *state =
@@ -7530,7 +7559,7 @@ static void intel_atomic_cleanup_work(struct work_struct *work)
75307559
int i;
75317560

75327561
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i)
7533-
intel_color_cleanup_commit(old_crtc_state);
7562+
intel_atomic_dsb_cleanup(old_crtc_state);
75347563

75357564
drm_atomic_helper_cleanup_planes(&i915->drm, &state->base);
75367565
drm_atomic_helper_commit_cleanup_done(&state->base);
@@ -7586,6 +7615,78 @@ static void intel_atomic_dsb_prepare(struct intel_atomic_state *state,
75867615
intel_color_prepare_commit(state, crtc);
75877616
}
75887617

7618+
static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
7619+
struct intel_crtc *crtc)
7620+
{
7621+
const struct intel_crtc_state *old_crtc_state =
7622+
intel_atomic_get_old_crtc_state(state, crtc);
7623+
struct intel_crtc_state *new_crtc_state =
7624+
intel_atomic_get_new_crtc_state(state, crtc);
7625+
7626+
if (!new_crtc_state->hw.active)
7627+
return;
7628+
7629+
if (state->base.legacy_cursor_update)
7630+
return;
7631+
7632+
/* FIXME deal with everything */
7633+
new_crtc_state->use_dsb =
7634+
new_crtc_state->update_planes &&
7635+
!new_crtc_state->vrr.enable &&
7636+
!new_crtc_state->do_async_flip &&
7637+
!new_crtc_state->has_psr &&
7638+
!new_crtc_state->scaler_state.scaler_users &&
7639+
!old_crtc_state->scaler_state.scaler_users &&
7640+
!intel_crtc_needs_modeset(new_crtc_state) &&
7641+
!intel_crtc_needs_fastset(new_crtc_state);
7642+
7643+
if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color_vblank)
7644+
return;
7645+
7646+
/*
7647+
* Rough estimate:
7648+
* ~64 registers per each plane * 8 planes = 512
7649+
* Double that for pipe stuff and other overhead.
7650+
*/
7651+
new_crtc_state->dsb_commit = intel_dsb_prepare(state, crtc, INTEL_DSB_0,
7652+
new_crtc_state->use_dsb ? 1024 : 16);
7653+
if (!new_crtc_state->dsb_commit) {
7654+
new_crtc_state->use_dsb = false;
7655+
intel_color_cleanup_commit(new_crtc_state);
7656+
return;
7657+
}
7658+
7659+
if (new_crtc_state->use_dsb) {
7660+
if (intel_crtc_needs_color_update(new_crtc_state))
7661+
intel_color_commit_noarm(new_crtc_state->dsb_commit,
7662+
new_crtc_state);
7663+
intel_crtc_planes_update_noarm(new_crtc_state->dsb_commit,
7664+
state, crtc);
7665+
7666+
intel_dsb_vblank_evade(state, new_crtc_state->dsb_commit);
7667+
7668+
if (intel_crtc_needs_color_update(new_crtc_state))
7669+
intel_color_commit_arm(new_crtc_state->dsb_commit,
7670+
new_crtc_state);
7671+
bdw_set_pipe_misc(new_crtc_state->dsb_commit,
7672+
new_crtc_state);
7673+
intel_crtc_planes_update_arm(new_crtc_state->dsb_commit,
7674+
state, crtc);
7675+
7676+
if (!new_crtc_state->dsb_color_vblank) {
7677+
intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
7678+
intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit);
7679+
intel_dsb_interrupt(new_crtc_state->dsb_commit);
7680+
}
7681+
}
7682+
7683+
if (new_crtc_state->dsb_color_vblank)
7684+
intel_dsb_chain(state, new_crtc_state->dsb_commit,
7685+
new_crtc_state->dsb_color_vblank, true);
7686+
7687+
intel_dsb_finish(new_crtc_state->dsb_commit);
7688+
}
7689+
75897690
static void intel_atomic_commit_tail(struct intel_atomic_state *state)
75907691
{
75917692
struct drm_device *dev = state->base.dev;
@@ -7605,6 +7706,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
76057706

76067707
intel_atomic_prepare_plane_clear_colors(state);
76077708

7709+
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
7710+
intel_atomic_dsb_finish(state, crtc);
7711+
76087712
drm_atomic_helper_wait_for_dependencies(&state->base);
76097713
drm_dp_mst_atomic_wait_for_dependencies(&state->base);
76107714
intel_atomic_global_state_wait_for_dependencies(state);
@@ -7718,7 +7822,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
77187822
if (new_crtc_state->do_async_flip)
77197823
intel_crtc_disable_flip_done(state, crtc);
77207824

7721-
intel_color_wait_commit(new_crtc_state);
7825+
intel_atomic_dsb_wait_commit(new_crtc_state);
77227826
}
77237827

77247828
/*
@@ -7763,7 +7867,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
77637867
* FIXME get rid of this funny new->old swapping
77647868
*/
77657869
old_crtc_state->dsb_color_vblank = fetch_and_zero(&new_crtc_state->dsb_color_vblank);
7766-
old_crtc_state->dsb_color_commit = fetch_and_zero(&new_crtc_state->dsb_color_commit);
7870+
old_crtc_state->dsb_commit = fetch_and_zero(&new_crtc_state->dsb_commit);
77677871
}
77687872

77697873
/* Underruns don't always raise interrupts, so check manually */

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,8 +1270,9 @@ struct intel_crtc_state {
12701270
/* Only valid on TGL+ */
12711271
enum transcoder mst_master_transcoder;
12721272

1273-
/* For DSB based color LUT updates */
1274-
struct intel_dsb *dsb_color_vblank, *dsb_color_commit;
1273+
/* For DSB based pipe updates */
1274+
struct intel_dsb *dsb_color_vblank, *dsb_commit;
1275+
bool use_dsb;
12751276

12761277
u32 psr2_man_track_ctl;
12771278

0 commit comments

Comments
 (0)