drm/amd/display: Move periodic interrupt calculations to HWSS

[why]
Periodic interrupt line calculations depends on stream and pipe state, not
ASIC-specific register programming. Keeping it in the DCN10 implementation
also prevents block-sequence callers from carrying fully resolved
parameters.
We want HWSS block parameters to not include complex structures like
pipe_ctx.

[how]
- Move the vertical interrupt line calculation into common HWSS code.
- Update the periodic interrupt callback.
- Calculate the values before direct or block-sequence execution.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Tomasz Siemek <tomasz.siemek@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Tomasz Siemek 2026-08-04 16:47:10 +02:00 committed by Alex Deucher
parent 5ea44e1347
commit d24695f377
5 changed files with 83 additions and 55 deletions

View File

@ -4367,8 +4367,8 @@ static void commit_planes_do_stream_update(struct dc *dc,
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && pipe_ctx->stream == stream) {
if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt)
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
if (stream_update->periodic_interrupt)
hwss_setup_periodic_interrupt(dc, pipe_ctx);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
stream_update->vrr_infopacket ||

View File

@ -754,6 +754,38 @@ static bool get_update_dchubp_dpp_flags_status(struct pipe_ctx *pipe)
return false;
}
static void calc_vline_position(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
uint32_t *start_line,
uint32_t *end_line)
{
if (!dc->hwss.get_vupdate_offset_from_vsync)
return;
const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
int vline_pos = pipe_ctx->stream->periodic_interrupt.lines_offset;
if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_UPDATE) {
if (vline_pos > 0)
vline_pos--;
else if (vline_pos < 0)
vline_pos++;
vline_pos += dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
if (vline_pos >= 0)
*start_line = vline_pos - ((vline_pos / timing->v_total) * timing->v_total);
else
*start_line = vline_pos + ((-vline_pos / timing->v_total) + 1) * timing->v_total - 1;
*end_line = (*start_line + 2) % timing->v_total;
} else if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_SYNC) {
// vsync is line 0 so start_line is just the requested line offset
*start_line = vline_pos;
*end_line = (*start_line + 2) % timing->v_total;
} else
ASSERT(0);
}
// Function to check if any update flags are set
static bool get_pipe_update_bits_status(struct pipe_ctx *pipe, struct dc_plane_state *plane, struct dc_stream_state *stream)
{
@ -1182,8 +1214,16 @@ void hwss_build_fast_sequence(struct dc *dc,
}
if (dc->hwss.setup_periodic_interrupt && stream->update_flags.bits.periodic_interrupt) {
block_sequence[*num_steps].params.setup_periodic_interrupt_params.dc = dc;
block_sequence[*num_steps].params.setup_periodic_interrupt_params.pipe_ctx = pipe_ctx;
uint32_t start_line = 0;
uint32_t end_line = 0;
calc_vline_position(dc, pipe_ctx, &start_line, &end_line);
block_sequence[*num_steps].params.setup_periodic_interrupt_params.tg =
pipe_ctx->stream_res.tg;
block_sequence[*num_steps].params.setup_periodic_interrupt_params.start_line =
start_line;
block_sequence[*num_steps].params.setup_periodic_interrupt_params.end_line =
end_line;
block_sequence[*num_steps].func = HWSS_SETUP_PERIODIC_INTERRUPT;
(*num_steps)++;
}
@ -1677,7 +1717,11 @@ void hwss_execute_sequence(struct dc *dc,
hwss_tg_setup_vertical_interrupt0(params);
break;
case HWSS_SETUP_PERIODIC_INTERRUPT:
hwss_setup_periodic_interrupt(dc, params);
if (dc->hwss.setup_periodic_interrupt)
dc->hwss.setup_periodic_interrupt(
params->setup_periodic_interrupt_params.tg,
params->setup_periodic_interrupt_params.start_line,
params->setup_periodic_interrupt_params.end_line);
break;
case HWSS_UPDATE_INFO_FRAME:
hwss_update_info_frame(dc, params);
@ -3331,12 +3375,18 @@ void hwss_update_info_frame(struct dc *dc, union block_sequence_params *params)
dc->hwss.update_info_frame(pipe_ctx);
}
void hwss_setup_periodic_interrupt(struct dc *dc, union block_sequence_params *params)
void hwss_setup_periodic_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct pipe_ctx *pipe_ctx = params->setup_periodic_interrupt_params.pipe_ctx;
uint32_t start_line = 0;
uint32_t end_line = 0;
if (dc->hwss.setup_periodic_interrupt)
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
if (dc->hwss.setup_periodic_interrupt) {
calc_vline_position(dc, pipe_ctx, &start_line, &end_line);
dc->hwss.setup_periodic_interrupt(
pipe_ctx->stream_res.tg,
start_line,
end_line);
}
}
void hwss_tg_setup_vertical_interrupt0(union block_sequence_params *params)
@ -5943,9 +5993,17 @@ void hwss_add_setup_periodic_interrupt(struct block_sequence_state *seq_state,
struct pipe_ctx *pipe_ctx)
{
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
uint32_t start_line = 0;
uint32_t end_line = 0;
calc_vline_position(dc, pipe_ctx, &start_line, &end_line);
seq_state->steps[*seq_state->num_steps].func = HWSS_SETUP_PERIODIC_INTERRUPT;
seq_state->steps[*seq_state->num_steps].params.setup_periodic_interrupt_params.dc = dc;
seq_state->steps[*seq_state->num_steps].params.setup_periodic_interrupt_params.pipe_ctx = pipe_ctx;
seq_state->steps[*seq_state->num_steps].params.setup_periodic_interrupt_params.tg =
pipe_ctx->stream_res.tg;
seq_state->steps[*seq_state->num_steps].params.setup_periodic_interrupt_params.start_line =
start_line;
seq_state->steps[*seq_state->num_steps].params.setup_periodic_interrupt_params.end_line =
end_line;
(*seq_state->num_steps)++;
}
}

View File

@ -4026,45 +4026,12 @@ void dcn10_calc_vupdate_position(
*end_line = (*start_line + 2) % timing->v_total;
}
static void dcn10_cal_vline_position(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
uint32_t *start_line,
uint32_t *end_line)
{
const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
int vline_pos = pipe_ctx->stream->periodic_interrupt.lines_offset;
if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_UPDATE) {
if (vline_pos > 0)
vline_pos--;
else if (vline_pos < 0)
vline_pos++;
vline_pos += dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
if (vline_pos >= 0)
*start_line = vline_pos - ((vline_pos / timing->v_total) * timing->v_total);
else
*start_line = vline_pos + ((-vline_pos / timing->v_total) + 1) * timing->v_total - 1;
*end_line = (*start_line + 2) % timing->v_total;
} else if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_SYNC) {
// vsync is line 0 so start_line is just the requested line offset
*start_line = vline_pos;
*end_line = (*start_line + 2) % timing->v_total;
} else
ASSERT(0);
}
void dcn10_setup_periodic_interrupt(
struct dc *dc,
struct pipe_ctx *pipe_ctx)
struct timing_generator *tg,
uint32_t start_line,
uint32_t end_line
)
{
struct timing_generator *tg = pipe_ctx->stream_res.tg;
uint32_t start_line = 0;
uint32_t end_line = 0;
dcn10_cal_vline_position(dc, pipe_ctx, &start_line, &end_line);
tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line);
}

View File

@ -183,8 +183,9 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx);
void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx);
void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx);
void dcn10_setup_periodic_interrupt(
struct dc *dc,
struct pipe_ctx *pipe_ctx);
struct timing_generator *tg,
uint32_t start_line,
uint32_t end_line);
enum dc_status dcn10_set_clock(struct dc *dc,
enum dc_clock_type clock_type,
uint32_t clk_khz,

View File

@ -819,8 +819,9 @@ struct cursor_lock_params {
};
struct setup_periodic_interrupt_params {
struct dc *dc;
struct pipe_ctx *pipe_ctx;
struct timing_generator *tg;
uint32_t start_line;
uint32_t end_line;
};
struct send_cursor_info_to_dmu_params {
@ -1452,8 +1453,9 @@ struct hw_sequencer_funcs {
void (*enable_vblanks_synchronization)(struct dc *dc,
int group_index, int group_size,
struct pipe_ctx *grouped_pipes[]);
void (*setup_periodic_interrupt)(struct dc *dc,
struct pipe_ctx *pipe_ctx);
void (*setup_periodic_interrupt)(struct timing_generator *tg,
uint32_t start_line,
uint32_t end_line);
void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes,
struct dc_crtc_timing_adjust adjust);
void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,
@ -2113,7 +2115,7 @@ void hwss_commit_cursor_offload_update(union block_sequence_params *params);
void hwss_update_cursor_offload_pipe(union block_sequence_params *params);
void hwss_setup_periodic_interrupt(struct dc *dc, union block_sequence_params *params);
void hwss_setup_periodic_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx);
void hwss_disable_audio_stream(struct dc *dc, union block_sequence_params *params);