From 783bf4035cb7f2707ad760fbc06f6be01a553f0a Mon Sep 17 00:00:00 2001 From: Vladimir Stempen Date: Wed, 24 Feb 2021 14:02:32 -0500 Subject: [PATCH] drm/amd/display: Fix 64 bit divisions on 32 bit platforms by using div64 API [why] Synchronization displays with different timings feature uses division operator for 64 bit division, which is not supported by 32 bit platforms [how] Use div64 API for 64 bit division Signed-off-by: Vladimir Stempen Tested-by: Bindu Ramamurthy Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 13 +++++++------ 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0241c9d..3c91d16 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -424,7 +424,7 @@ bool resource_are_vblanks_synchronizable( uint32_t base60_refresh_rates[] = {10, 20, 5}; uint8_t i; uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]); - int64_t frame_time_diff; + uint64_t frame_time_diff; if (stream1->ctx->dc->config.vblank_alignment_dto_params && stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 && @@ -441,15 +441,15 @@ bool resource_are_vblanks_synchronizable( if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/ stream2->timing.v_total > 60) return false; - frame_time_diff = (int64_t)10000 * + frame_time_diff = (uint64_t)10000 * stream1->timing.h_total * stream1->timing.v_total * - stream2->timing.pix_clk_100hz / - stream1->timing.pix_clk_100hz / - stream2->timing.h_total / - stream2->timing.v_total; + stream2->timing.pix_clk_100hz; + frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz); + frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total); + frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total); for (i = 0; i < rr_count; i++) { - int64_t diff = (frame_time_diff * base60_refresh_rates[i]) / 10 - 10000; + int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000; if (diff < 0) diff = -diff; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 6f47f9b..2c7eb98 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1013,9 +1013,9 @@ static bool get_pixel_clk_frequency_100hz( * not be programmed equal to DPREFCLK */ modulo_hz = REG_READ(MODULO[inst]); - *pixel_clk_khz = ((uint64_t)clock_hz* - clock_source->ctx->dc->clk_mgr->dprefclk_khz*10)/ - modulo_hz; + *pixel_clk_khz = div_u64((uint64_t)clock_hz* + clock_source->ctx->dc->clk_mgr->dprefclk_khz*10, + modulo_hz); } else { /* NOTE: There is agreement with VBIOS here that MODULO is * programmed equal to DPREFCLK, in which case PHASE will be 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 bdf40ef..45f4dbd 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 @@ -1900,8 +1900,8 @@ uint64_t reduceSizeAndFraction( } while (num % prime_numbers[i] == 0 && denom % prime_numbers[i] == 0) { - num /= prime_numbers[i]; - denom /= prime_numbers[i]; + num = div_u64(num, prime_numbers[i]); + denom = div_u64(denom, prime_numbers[i]); } } *numerator = num; @@ -1987,8 +1987,8 @@ int dcn10_align_pixel_clocks( phase[i] = (uint64_t)embedded_pix_clk_100hz* hw_crtc_timing[i].h_total* - hw_crtc_timing[i].v_total/ - get_clock_divider(grouped_pipes[i], true); + hw_crtc_timing[i].v_total; + phase[i] = div_u64(phase[i], get_clock_divider(grouped_pipes[i], true)); modulo[i] = (uint64_t)dp_ref_clk_100hz* embedded_h_total* embedded_v_total; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c index ef6ee03..ea7eaf7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c @@ -323,8 +323,8 @@ void optc2_align_vblanks( uint32_t master_v_active = 0; uint32_t master_h_total = 0; uint32_t slave_h_total = 0; - uint64_t L, XY, p = 10000; - uint32_t X, Y; + uint64_t L, XY; + uint32_t X, Y, p = 10000; uint32_t master_update_lock; /* disable slave OTG */ @@ -355,11 +355,12 @@ void optc2_align_vblanks( REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &master_h_total); /* calculate when to enable slave OTG */ - L = p * slave_h_total * master_pixel_clock_100Hz / - master_h_total / slave_pixel_clock_100Hz; - XY = L / p; + L = (uint64_t)p * slave_h_total * master_pixel_clock_100Hz; + L = div_u64(L, master_h_total); + L = div_u64(L, slave_pixel_clock_100Hz); + XY = div_u64(L, p); Y = master_v_active - XY - 1; - X = ((XY + 1) * p - L) * master_h_total / master_clock_divider / p; + X = div_u64(((XY + 1) * p - L) * master_h_total, p * master_clock_divider); /* * set master OTG to unlock when V/H -- 2.7.4