Commit 51619c67 authored by Aric Cyr's avatar Aric Cyr Committed by Alex Deucher

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: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarHamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: default avatarAric Cyr <aric.cyr@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent baec651f
...@@ -3818,28 +3818,14 @@ void dcn10_calc_vupdate_position( ...@@ -3818,28 +3818,14 @@ void dcn10_calc_vupdate_position(
uint32_t *start_line, uint32_t *start_line,
uint32_t *end_line) uint32_t *end_line)
{ {
const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing; const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
int vline_int_offset_from_vupdate = int vupdate_pos = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
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++;
start_position = vline_int_offset_from_vupdate + vupdate_offset_from_vsync; if (vupdate_pos >= 0)
*start_line = vupdate_pos - ((vupdate_pos / timing->v_total) * timing->v_total);
if (start_position >= 0)
*start_line = start_position;
else else
*start_line = dc_crtc_timing->v_total + start_position - 1; *start_line = vupdate_pos + ((-vupdate_pos / timing->v_total) + 1) * timing->v_total - 1;
*end_line = (*start_line + 2) % timing->v_total;
*end_line = *start_line + 2;
if (*end_line >= dc_crtc_timing->v_total)
*end_line = 2;
} }
static void dcn10_cal_vline_position( static void dcn10_cal_vline_position(
...@@ -3848,23 +3834,27 @@ static void dcn10_cal_vline_position( ...@@ -3848,23 +3834,27 @@ static void dcn10_cal_vline_position(
uint32_t *start_line, uint32_t *start_line,
uint32_t *end_line) uint32_t *end_line)
{ {
switch (pipe_ctx->stream->periodic_interrupt.ref_point) { const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
case START_V_UPDATE: int vline_pos = pipe_ctx->stream->periodic_interrupt.lines_offset;
dcn10_calc_vupdate_position(
dc, if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_UPDATE) {
pipe_ctx, if (vline_pos > 0)
start_line, vline_pos--;
end_line); else if (vline_pos < 0)
break; vline_pos++;
case START_V_SYNC:
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 // vsync is line 0 so start_line is just the requested line offset
*start_line = pipe_ctx->stream->periodic_interrupt.lines_offset; *start_line = vline_pos;
*end_line = *start_line + 2; *end_line = (*start_line + 2) % timing->v_total;
break; } else
default:
ASSERT(0); ASSERT(0);
break;
}
} }
void dcn10_setup_periodic_interrupt( void dcn10_setup_periodic_interrupt(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment