[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