diff options
author | Aric Cyr <aric.cyr@amd.com> | 2022-09-23 17:09:54 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2022-10-06 12:01:07 -0400 |
commit | 51619c671316e96d7adaf2b6ea94ce245b81b6dd (patch) | |
tree | 796cc7086ec870185562b36a8b62ce7911563dac /drivers/gpu | |
parent | baec651f4160f4c3f029edf84bbc18b4fcba9cf5 (diff) | |
download | linux-stable-51619c671316e96d7adaf2b6ea94ce245b81b6dd.tar.gz linux-stable-51619c671316e96d7adaf2b6ea94ce245b81b6dd.tar.bz2 linux-stable-51619c671316e96d7adaf2b6ea94ce245b81b6dd.zip |
drm/amd/display: Fix vupdate and vline position calculation
[how]
Large deltas for periodic interrupts could result in the interrupt not
being programmed properly and thus not firing.
[why]
Add proper wrap-around support for calculating VUPDATE and VLINE
positions.
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 60 |
1 files changed, 25 insertions, 35 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4390f6d7050f..f4b3ec32a331 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -3818,28 +3818,14 @@ void dcn10_calc_vupdate_position( uint32_t *start_line, uint32_t *end_line) { - const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing; - int vline_int_offset_from_vupdate = - pipe_ctx->stream->periodic_interrupt.lines_offset; - int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx); - int start_position; - - if (vline_int_offset_from_vupdate > 0) - vline_int_offset_from_vupdate--; - else if (vline_int_offset_from_vupdate < 0) - vline_int_offset_from_vupdate++; + const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; + int vupdate_pos = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx); - start_position = vline_int_offset_from_vupdate + vupdate_offset_from_vsync; - - if (start_position >= 0) - *start_line = start_position; + if (vupdate_pos >= 0) + *start_line = vupdate_pos - ((vupdate_pos / timing->v_total) * timing->v_total); else - *start_line = dc_crtc_timing->v_total + start_position - 1; - - *end_line = *start_line + 2; - - if (*end_line >= dc_crtc_timing->v_total) - *end_line = 2; + *start_line = vupdate_pos + ((-vupdate_pos / timing->v_total) + 1) * timing->v_total - 1; + *end_line = (*start_line + 2) % timing->v_total; } static void dcn10_cal_vline_position( @@ -3848,23 +3834,27 @@ static void dcn10_cal_vline_position( uint32_t *start_line, uint32_t *end_line) { - switch (pipe_ctx->stream->periodic_interrupt.ref_point) { - case START_V_UPDATE: - dcn10_calc_vupdate_position( - dc, - pipe_ctx, - start_line, - end_line); - break; - case START_V_SYNC: + 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 = pipe_ctx->stream->periodic_interrupt.lines_offset; - *end_line = *start_line + 2; - break; - default: + *start_line = vline_pos; + *end_line = (*start_line + 2) % timing->v_total; + } else ASSERT(0); - break; - } } void dcn10_setup_periodic_interrupt( |