[PATCH 1/2] SWDEV-266369 - dc: Fix 64 bit divisions on 32 bit platforms by using div64 API

Bindu Ramamurthy bindu.r at amd.com
Mon Mar 1 17:06:30 UTC 2021


From: Vladimir Stempen <vladimir.stempen at amd.com>

[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 <vladimir.stempen at amd.com>
Tested-by: Bindu Ramamurthy<bindu.r at amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c  | 14 +++++++-------
 .../gpu/drm/amd/display/dc/dce/dce_clock_source.c  |  6 +++---
 .../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 0241c9d96d7a..3c91d16c2710 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 6f47f9bab5ee..2c7eb982eabc 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 bdf40ef01607..45f4dbd886b9 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 ef6ee03175e0..ea7eaf7d755f 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.25.1



More information about the amd-gfx mailing list