[PATCH i-g-t v1 1/1] tests/kms_vrr: Add adaptive-dc subtest for VRR

Naladala Ramanaidu ramanaidu.naladala at intel.com
Wed Jan 29 20:11:49 UTC 2025


Add a new subtest 'adaptive-dc' to the VRR tests. This subtest
cover the Adaptive dc balance functionality.

Signed-off-by: Naladala Ramanaidu <ramanaidu.naladala at intel.com>
---
 tests/kms_vrr.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)

diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c
index e7d2ff1db..4f4649fff 100644
--- a/tests/kms_vrr.c
+++ b/tests/kms_vrr.c
@@ -86,6 +86,11 @@
  * Description: Oscillates between highest and lowest refresh each frame for
  *              manual flicker profiling
  *
+ * SUBTEST: adaptive-dc
+ * Description: Oscillates between highest and lowest refresh each frame poll
+ * 		Adaptive dc balance.
+ * Functionality: Adaptive dc balance, Adaptive_sync
+ *
  * SUBTEST: negative-basic
  * Description: Make sure that VRR should not be enabled on the Non-VRR panel.
  */
@@ -146,6 +151,12 @@ typedef struct data {
 	bool static_image;
 } data_t;
 
+typedef struct thread_data {
+	data_t *data;
+	int pipe;
+	bool poll_vb_flag;
+} thread_data_t;
+
 typedef void (*test_t)(data_t*, enum pipe, igt_output_t*, uint32_t);
 
 /* Converts a timespec structure to nanoseconds. */
@@ -172,6 +183,23 @@ static uint64_t get_kernel_event_ns(data_t *data, uint32_t event)
 	return ev.tv_sec * NSECS_PER_SEC + ev.tv_usec * 1000ull;
 }
 
+static uint64_t wait_for_vblank(data_t *data, int pipe)
+{
+	uint32_t pipe_id_flag;
+	drmVBlank vbl;
+
+	memset(&vbl, 0, sizeof(vbl));
+	pipe_id_flag = kmstest_get_vbl_flag(pipe);
+
+	vbl.request.type = DRM_VBLANK_RELATIVE | pipe_id_flag;
+	vbl.request.sequence = 1;
+
+	do_ioctl(data->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
+
+	return (vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec);
+}
+
+
 /*
  * Returns the current CLOCK_MONOTONIC time in nanoseconds.
  * The regular IGT helpers can't be used since they default to
@@ -570,6 +598,94 @@ flip_and_measure_cmrr(data_t *data, igt_output_t *output, enum pipe pipe,
 	return total_flip ? ((total_pass * 100) / total_flip) : 0;
 }
 
+static void *monitor_vblanks(void *arg)
+{
+	thread_data_t *t_data  = (thread_data_t *)arg;
+	uint64_t last_vb_event_us, vb_event_us;
+	uint64_t diff_us;
+	uint64_t frame = 0;
+	uint64_t dc_balance = 0;
+
+	last_vb_event_us = vb_event_us = wait_for_vblank(t_data->data, t_data->pipe);
+
+	while (t_data->poll_vb_flag) {
+		vb_event_us = wait_for_vblank(t_data->data, t_data->pipe);
+
+		diff_us = vb_event_us - last_vb_event_us;
+		frame = frame + 1;
+		last_vb_event_us = vb_event_us;
+
+		if ((frame % 2) == 0) {
+			dc_balance += diff_us;
+			igt_info("even frame%ld dc_balance = %ld frame time = %ld\n",
+				 frame, dc_balance, diff_us);
+		} else {
+			dc_balance -= diff_us;
+			igt_info("odd frame%ld dc_balance = %ld frame time = %ld\n",
+				 frame, dc_balance, diff_us);
+		}
+	}
+	igt_info("frames count = %ld, dc balance = %ld\n", frame, dc_balance);
+	pthread_exit((void *)dc_balance);
+}
+
+
+static void
+test_adaptive_dc_balance(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
+{
+	uint64_t result;
+	vtest_ns_t vtest_ns;
+	range_t range;
+	uint64_t rate[] = {0};
+	pthread_t vblank_thread;
+	void *thread_result;
+	thread_data_t thread_data;
+	unsigned int range_min;
+	uint64_t maxmin_rates[2];
+
+	prepare_test(data, output, pipe);
+	range = data->range;
+	vtest_ns = data->vtest_ns;
+	rate[0] = vtest_ns.rate_ns;
+
+	igt_info("VRR Test execution on %s, PIPE_%s with VRR range: (%u-%u) Hz\n",
+		 output->name, kmstest_pipe_name(pipe), range.min, range.max);
+	igt_info("Override Mode: ");
+	kmstest_dump_mode(&data->switch_modes[HIGH_RR_MODE]);
+
+	set_vrr_on_pipe(data, pipe, !(flags & TEST_FASTSET), true);
+	/*
+	 * Do a short run with VRR, but don't check the result.
+	 * This is to make sure we were actually in the middle of
+	 * active flipping before doing the DPMS/suspend steps.
+	 */
+	flip_and_measure(data, output, pipe, rate, 1, 250000000ull);
+
+	/* For Intel h/w tweak the min rate, as h/w will terminate the vblank at Vmax. */
+	range_min = is_intel_device(data->drm_fd) ? (range.min + 2) : range.min;
+
+	maxmin_rates[0] = vtest_ns.max;
+	maxmin_rates[1] = igt_kms_frame_time_from_vrefresh(range_min);
+
+	thread_data.data = data;
+	thread_data.pipe = pipe;
+
+	if (pthread_create(&vblank_thread, NULL, monitor_vblanks, &thread_data) != 0)
+		igt_assert_f(0, "Error: Failed to create vblank thread.\n");
+
+	thread_data.poll_vb_flag = true;
+	flip_and_measure(data, output, pipe, maxmin_rates, 2, data->duration_ns);
+	thread_data.poll_vb_flag = false;
+
+	pthread_join(vblank_thread, &thread_result);
+
+	result = (uint64_t)thread_result;
+
+	igt_assert_f(result == 0, "Adaptive_dc_balance %ld not adjusted\n", result);
+
+}
+
+
 /* Basic VRR flip functionality test - enable, measure, disable, measure */
 static void
 test_basic(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
@@ -1022,6 +1138,8 @@ static data_t data;
 
 igt_main_args("drs:", long_opts, help_str, opt_handler, &data)
 {
+	int display_ver;
+
 	igt_fixture {
 		data.drm_fd = drm_open_driver_master(DRIVER_ANY);
 
@@ -1060,6 +1178,14 @@ igt_main_args("drs:", long_opts, help_str, opt_handler, &data)
 	igt_subtest_with_dynamic("max-min")
 		run_vrr_test(&data, test_basic, TEST_MAXMIN);
 
+	igt_describe("Oscillates between highest and lowest refresh each frame poll "
+		      "Adaptive dc balance.");
+	igt_subtest_with_dynamic("adaptive-dc") {
+		display_ver = intel_display_ver(intel_get_drm_devid(data.drm_fd));
+		igt_require_f(display_ver >= 30, "Adaptive dc balance is not supported\n");
+		run_vrr_test(&data, test_adaptive_dc_balance, TEST_MAXMIN);
+	}
+
 	igt_subtest_group {
 		igt_fixture
 			igt_require_intel(data.drm_fd);
-- 
2.25.1



More information about the igt-dev mailing list