Skip to content

Commit

Permalink
drm/amd/display: Do not enable replay when vtotal update is pending.
Browse files Browse the repository at this point in the history
[Why&How]
Vtotal is not applied to HW when handling vsync interrupt.
Make sure vtotal is aligned before enable replay.

Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Reviewed-by: Robin Chen <robin.chen@amd.com>
Signed-off-by: Danny Wang <danny.wang@amd.com>
Signed-off-by: Zhongwei Zhang <Zhongwei.Zhang@amd.com>
Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Danny Wang authored and Alex Deucher committed Mar 10, 2025
1 parent 50e0bae commit bd00b29
Showing 10 changed files with 40 additions and 30 deletions.
9 changes: 7 additions & 2 deletions drivers/gpu/drm/amd/display/dc/core/dc.c
Original file line number Diff line number Diff line change
@@ -453,6 +453,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,

if (dc->caps.max_v_total != 0 &&
(adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
stream->adjust.timing_adjust_pending = false;
if (adjust->allow_otg_v_count_halt)
return set_long_vtotal(dc, stream, adjust);
else
@@ -466,7 +467,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
dc->hwss.set_drr(&pipe,
1,
*adjust);

stream->adjust.timing_adjust_pending = false;
return true;
}
}
@@ -3165,8 +3166,12 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (update->vrr_active_fixed)
stream->vrr_active_fixed = *update->vrr_active_fixed;

if (update->crtc_timing_adjust)
if (update->crtc_timing_adjust) {
if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min ||
stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max)
stream->adjust.timing_adjust_pending = true;
stream->adjust = *update->crtc_timing_adjust;
}

if (update->dpms_off)
stream->dpms_off = *update->dpms_off;
15 changes: 15 additions & 0 deletions drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
Original file line number Diff line number Diff line change
@@ -659,6 +659,21 @@ void set_p_state_switch_method(
}
}

void set_drr_and_clear_adjust_pending(
struct pipe_ctx *pipe_ctx,
struct dc_stream_state *stream,
struct drr_params *params)
{
/* params can be null.*/
if (pipe_ctx && pipe_ctx->stream_res.tg &&
pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, params);

if (stream)
stream->adjust.timing_adjust_pending = false;
}

void get_fams2_visual_confirm_color(
struct dc *dc,
struct dc_state *context,
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/display/dc/dc_hw_types.h
Original file line number Diff line number Diff line change
@@ -1017,6 +1017,7 @@ struct dc_crtc_timing_adjust {
uint32_t v_total_mid;
uint32_t v_total_mid_frame_num;
uint32_t allow_otg_v_count_halt;
uint8_t timing_adjust_pending;
};


7 changes: 2 additions & 5 deletions drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
Original file line number Diff line number Diff line change
@@ -1658,9 +1658,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(

params.vertical_total_min = stream->adjust.v_total_min;
params.vertical_total_max = stream->adjust.v_total_max;
if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, &params);
set_drr_and_clear_adjust_pending(pipe_ctx, stream, &params);

// DRR should set trigger event to monitor surface update event
if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
@@ -2109,8 +2107,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;

if ((tg != NULL) && tg->funcs) {
if (tg->funcs->set_drr)
tg->funcs->set_drr(tg, &params);
set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, &params);
if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
if (tg->funcs->set_static_screen_control)
tg->funcs->set_static_screen_control(
7 changes: 2 additions & 5 deletions drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
Original file line number Diff line number Diff line change
@@ -1113,9 +1113,7 @@ static void dcn10_reset_back_end_for_pipe(
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);

pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, NULL);
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
}
@@ -3218,8 +3216,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;

if ((tg != NULL) && tg->funcs) {
if (tg->funcs->set_drr)
tg->funcs->set_drr(tg, &params);
set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, &params);
if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
if (tg->funcs->set_static_screen_control)
tg->funcs->set_static_screen_control(
8 changes: 2 additions & 6 deletions drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
Original file line number Diff line number Diff line change
@@ -952,9 +952,7 @@ enum dc_status dcn20_enable_stream_timing(
params.vertical_total_max = stream->adjust.v_total_max;
params.vertical_total_mid = stream->adjust.v_total_mid;
params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num;
if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, &params);
set_drr_and_clear_adjust_pending(pipe_ctx, stream, &params);

// DRR should set trigger event to monitor surface update event
if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
@@ -2856,9 +2854,7 @@ void dcn20_reset_back_end_for_pipe(
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);

if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, NULL);
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
/* TODO - convert symclk_ref_cnts for otg to a bit map to solve
* the case where the same symclk is shared across multiple otg
* instances
4 changes: 1 addition & 3 deletions drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
Original file line number Diff line number Diff line change
@@ -543,9 +543,7 @@ static void dcn31_reset_back_end_for_pipe(
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;

if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, NULL);
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);

/* DPMS may already disable or */
/* dpms_off status is incorrect due to fastboot
3 changes: 1 addition & 2 deletions drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
Original file line number Diff line number Diff line change
@@ -1473,8 +1473,7 @@ void dcn35_set_drr(struct pipe_ctx **pipe_ctx,
num_frames = 2 * (frame_rate % 60);
}
}
if (tg->funcs->set_drr)
tg->funcs->set_drr(tg, &params);
set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, &params);
if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
if (tg->funcs->set_static_screen_control)
tg->funcs->set_static_screen_control(
10 changes: 3 additions & 7 deletions drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
Original file line number Diff line number Diff line change
@@ -830,10 +830,7 @@ enum dc_status dcn401_enable_stream_timing(
}

hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp);

if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, &params);
set_drr_and_clear_adjust_pending(pipe_ctx, stream, &params);

/* Event triggers and num frames initialized for DRR, but can be
* later updated for PSR use. Note DRR trigger events are generated
@@ -1820,9 +1817,8 @@ void dcn401_reset_back_end_for_pipe(
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);

if (pipe_ctx->stream_res.tg->funcs->set_drr)
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, NULL);
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);

/* TODO - convert symclk_ref_cnts for otg to a bit map to solve
* the case where the same symclk is shared across multiple otg
* instances
6 changes: 6 additions & 0 deletions drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@ struct dce_hwseq;
struct link_resource;
struct dc_dmub_cmd;
struct pg_block_update;
struct drr_params;

struct subvp_pipe_control_lock_fast_params {
struct dc *dc;
@@ -527,6 +528,11 @@ void set_p_state_switch_method(
struct dc_state *context,
struct pipe_ctx *pipe_ctx);

void set_drr_and_clear_adjust_pending(
struct pipe_ctx *pipe_ctx,
struct dc_stream_state *stream,
struct drr_params *params);

void hwss_execute_sequence(struct dc *dc,
struct block_sequence block_sequence[],
int num_steps);

0 comments on commit bd00b29

Please sign in to comment.