Skip to content

Commit b2a7b0c

Browse files
AMD-aricalexdeucher
authored andcommitted
drm/amd/display: Use cursor locking to prevent flip delays
[Why] Current locking scheme for cursor can result in a flip missing its vsync, deferring it for one or more vsyncs. Result is a potential for stuttering when cursor is moved. [How] Use cursor update lock so that flips are not blocked while cursor is being programmed. Signed-off-by: Aric Cyr <[email protected]> Reviewed-by: Nicholas Kazlauskas <[email protected]> Acked-by: Aurabindo Pillai <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 668a674 commit b2a7b0c

File tree

16 files changed

+88
-45
lines changed

16 files changed

+88
-45
lines changed

drivers/gpu/drm/amd/display/dc/core/dc_stream.c

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -231,34 +231,6 @@ struct dc_stream_status *dc_stream_get_status(
231231
return dc_stream_get_status_from_state(dc->current_state, stream);
232232
}
233233

234-
static void delay_cursor_until_vupdate(struct pipe_ctx *pipe_ctx, struct dc *dc)
235-
{
236-
#if defined(CONFIG_DRM_AMD_DC_DCN)
237-
unsigned int vupdate_line;
238-
unsigned int lines_to_vupdate, us_to_vupdate, vpos, nvpos;
239-
struct dc_stream_state *stream = pipe_ctx->stream;
240-
unsigned int us_per_line;
241-
242-
if (!dc->hwss.get_vupdate_offset_from_vsync)
243-
return;
244-
245-
vupdate_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
246-
if (!dc_stream_get_crtc_position(dc, &stream, 1, &vpos, &nvpos))
247-
return;
248-
249-
if (vpos >= vupdate_line)
250-
return;
251-
252-
us_per_line =
253-
stream->timing.h_total * 10000 / stream->timing.pix_clk_100hz;
254-
lines_to_vupdate = vupdate_line - vpos;
255-
us_to_vupdate = lines_to_vupdate * us_per_line;
256-
257-
/* 70 us is a conservative estimate of cursor update time*/
258-
if (us_to_vupdate < 70)
259-
udelay(us_to_vupdate);
260-
#endif
261-
}
262234

263235
/**
264236
* dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
@@ -298,9 +270,7 @@ bool dc_stream_set_cursor_attributes(
298270

299271
if (!pipe_to_program) {
300272
pipe_to_program = pipe_ctx;
301-
302-
delay_cursor_until_vupdate(pipe_ctx, dc);
303-
dc->hwss.pipe_control_lock(dc, pipe_to_program, true);
273+
dc->hwss.cursor_lock(dc, pipe_to_program, true);
304274
}
305275

306276
dc->hwss.set_cursor_attribute(pipe_ctx);
@@ -309,7 +279,7 @@ bool dc_stream_set_cursor_attributes(
309279
}
310280

311281
if (pipe_to_program)
312-
dc->hwss.pipe_control_lock(dc, pipe_to_program, false);
282+
dc->hwss.cursor_lock(dc, pipe_to_program, false);
313283

314284
return true;
315285
}
@@ -349,16 +319,14 @@ bool dc_stream_set_cursor_position(
349319

350320
if (!pipe_to_program) {
351321
pipe_to_program = pipe_ctx;
352-
353-
delay_cursor_until_vupdate(pipe_ctx, dc);
354-
dc->hwss.pipe_control_lock(dc, pipe_to_program, true);
322+
dc->hwss.cursor_lock(dc, pipe_to_program, true);
355323
}
356324

357325
dc->hwss.set_cursor_position(pipe_ctx);
358326
}
359327

360328
if (pipe_to_program)
361-
dc->hwss.pipe_control_lock(dc, pipe_to_program, false);
329+
dc->hwss.cursor_lock(dc, pipe_to_program, false);
362330

363331
return true;
364332
}

drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,6 +2757,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
27572757
.disable_plane = dce110_power_down_fe,
27582758
.pipe_control_lock = dce_pipe_control_lock,
27592759
.interdependent_update_lock = NULL,
2760+
.cursor_lock = dce_pipe_control_lock,
27602761
.prepare_bandwidth = dce110_prepare_bandwidth,
27612762
.optimize_bandwidth = dce110_optimize_bandwidth,
27622763
.set_drr = set_drr,

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,16 @@ void dcn10_pipe_control_lock(
16251625
hws->funcs.verify_allow_pstate_change_high(dc);
16261626
}
16271627

1628+
void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock)
1629+
{
1630+
/* cursor lock is per MPCC tree, so only need to lock one pipe per stream */
1631+
if (!pipe || pipe->top_pipe)
1632+
return;
1633+
1634+
dc->res_pool->mpc->funcs->cursor_lock(dc->res_pool->mpc,
1635+
pipe->stream_res.opp->inst, lock);
1636+
}
1637+
16281638
static bool wait_for_reset_trigger_to_occur(
16291639
struct dc_context *dc_ctx,
16301640
struct timing_generator *tg)

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void dcn10_pipe_control_lock(
4949
struct dc *dc,
5050
struct pipe_ctx *pipe,
5151
bool lock);
52+
void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock);
5253
void dcn10_blank_pixel_data(
5354
struct dc *dc,
5455
struct pipe_ctx *pipe_ctx,

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
5050
.disable_audio_stream = dce110_disable_audio_stream,
5151
.disable_plane = dcn10_disable_plane,
5252
.pipe_control_lock = dcn10_pipe_control_lock,
53+
.cursor_lock = dcn10_cursor_lock,
5354
.interdependent_update_lock = dcn10_lock_all_pipes,
5455
.prepare_bandwidth = dcn10_prepare_bandwidth,
5556
.optimize_bandwidth = dcn10_optimize_bandwidth,

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ struct mpcc *mpc1_insert_plane(
223223
REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id);
224224
REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id);
225225

226+
/* Configure VUPDATE lock set for this MPCC to map to the OPP */
227+
REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, tree->opp_id);
228+
226229
/* update mpc tree mux setting */
227230
if (tree->opp_list == insert_above_mpcc) {
228231
/* insert the toppest mpcc */
@@ -318,6 +321,7 @@ void mpc1_remove_mpcc(
318321
REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
319322
REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
320323
REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf);
324+
REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
321325

322326
/* mark this mpcc as not in use */
323327
mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id);
@@ -328,6 +332,7 @@ void mpc1_remove_mpcc(
328332
REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
329333
REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
330334
REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf);
335+
REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
331336
}
332337
}
333338

@@ -361,6 +366,7 @@ void mpc1_mpc_init(struct mpc *mpc)
361366
REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
362367
REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
363368
REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf);
369+
REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
364370

365371
mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
366372
}
@@ -381,6 +387,7 @@ void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
381387
REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
382388
REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
383389
REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf);
390+
REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
384391

385392
mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
386393

@@ -453,6 +460,13 @@ void mpc1_read_mpcc_state(
453460
MPCC_BUSY, &s->busy);
454461
}
455462

463+
void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock)
464+
{
465+
struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
466+
467+
REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0);
468+
}
469+
456470
static const struct mpc_funcs dcn10_mpc_funcs = {
457471
.read_mpcc_state = mpc1_read_mpcc_state,
458472
.insert_plane = mpc1_insert_plane,
@@ -464,6 +478,7 @@ static const struct mpc_funcs dcn10_mpc_funcs = {
464478
.assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect,
465479
.init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
466480
.update_blending = mpc1_update_blending,
481+
.cursor_lock = mpc1_cursor_lock,
467482
.set_denorm = NULL,
468483
.set_denorm_clamp = NULL,
469484
.set_output_csc = NULL,

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@
3939
SRII(MPCC_BG_G_Y, MPCC, inst),\
4040
SRII(MPCC_BG_R_CR, MPCC, inst),\
4141
SRII(MPCC_BG_B_CB, MPCC, inst),\
42-
SRII(MPCC_BG_B_CB, MPCC, inst),\
43-
SRII(MPCC_SM_CONTROL, MPCC, inst)
42+
SRII(MPCC_SM_CONTROL, MPCC, inst),\
43+
SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst)
4444

4545
#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \
46-
SRII(MUX, MPC_OUT, inst)
46+
SRII(MUX, MPC_OUT, inst),\
47+
VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst)
4748

4849
#define MPC_COMMON_REG_VARIABLE_LIST \
4950
uint32_t MPCC_TOP_SEL[MAX_MPCC]; \
@@ -55,7 +56,9 @@
5556
uint32_t MPCC_BG_R_CR[MAX_MPCC]; \
5657
uint32_t MPCC_BG_B_CB[MAX_MPCC]; \
5758
uint32_t MPCC_SM_CONTROL[MAX_MPCC]; \
58-
uint32_t MUX[MAX_OPP];
59+
uint32_t MUX[MAX_OPP]; \
60+
uint32_t MPCC_UPDATE_LOCK_SEL[MAX_MPCC]; \
61+
uint32_t CUR[MAX_OPP];
5962

6063
#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
6164
SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\
@@ -78,7 +81,8 @@
7881
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\
7982
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\
8083
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\
81-
SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh)
84+
SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\
85+
SF(MPCC0_MPCC_UPDATE_LOCK_SEL, MPCC_UPDATE_LOCK_SEL, mask_sh)
8286

8387
#define MPC_REG_FIELD_LIST(type) \
8488
type MPCC_TOP_SEL;\
@@ -101,7 +105,9 @@
101105
type MPCC_SM_FIELD_ALT;\
102106
type MPCC_SM_FORCE_NEXT_FRAME_POL;\
103107
type MPCC_SM_FORCE_NEXT_TOP_POL;\
104-
type MPC_OUT_MUX;
108+
type MPC_OUT_MUX;\
109+
type MPCC_UPDATE_LOCK_SEL;\
110+
type CUR_VUPDATE_LOCK_SET;
105111

106112
struct dcn_mpc_registers {
107113
MPC_COMMON_REG_VARIABLE_LIST
@@ -192,4 +198,6 @@ void mpc1_read_mpcc_state(
192198
int mpcc_inst,
193199
struct mpcc_state *s);
194200

201+
void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock);
202+
195203
#endif

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ enum dcn10_clk_src_array_id {
181181
.reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
182182
mm ## block ## id ## _ ## reg_name
183183

184+
#define VUPDATE_SRII(reg_name, block, id)\
185+
.reg_name[id] = BASE(mm ## reg_name ## 0 ## _ ## block ## id ## _BASE_IDX) + \
186+
mm ## reg_name ## 0 ## _ ## block ## id
187+
188+
/* set field/register/bitfield name */
189+
#define SFRB(field_name, reg_name, bitfield, post_fix)\
190+
.field_name = reg_name ## __ ## bitfield ## post_fix
191+
184192
/* NBIO */
185193
#define NBIO_BASE_INNER(seg) \
186194
NBIF_BASE__INST0_SEG ## seg
@@ -419,11 +427,13 @@ static const struct dcn_mpc_registers mpc_regs = {
419427
};
420428

421429
static const struct dcn_mpc_shift mpc_shift = {
422-
MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT)
430+
MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT),\
431+
SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, __SHIFT)
423432
};
424433

425434
static const struct dcn_mpc_mask mpc_mask = {
426-
MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),
435+
MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),\
436+
SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, _MASK)
427437
};
428438

429439
#define tg_regs(id)\

drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
5252
.disable_plane = dcn20_disable_plane,
5353
.pipe_control_lock = dcn20_pipe_control_lock,
5454
.interdependent_update_lock = dcn10_lock_all_pipes,
55+
.cursor_lock = dcn10_cursor_lock,
5556
.prepare_bandwidth = dcn20_prepare_bandwidth,
5657
.optimize_bandwidth = dcn20_optimize_bandwidth,
5758
.update_bandwidth = dcn20_update_bandwidth,

drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ const struct mpc_funcs dcn20_mpc_funcs = {
545545
.mpc_init = mpc1_mpc_init,
546546
.mpc_init_single_inst = mpc1_mpc_init_single_inst,
547547
.update_blending = mpc2_update_blending,
548+
.cursor_lock = mpc1_cursor_lock,
548549
.get_mpcc_for_dpp = mpc2_get_mpcc_for_dpp,
549550
.wait_for_idle = mpc2_assert_idle_mpcc,
550551
.assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,

0 commit comments

Comments
 (0)