[i-g-t V2 1/2] tests/kms_vrr: New subtest for CMRR

Golani, Mitulkumar Ajitkumar mitulkumar.ajitkumar.golani at intel.com
Tue Jun 18 09:27:42 UTC 2024



> -----Original Message-----
> From: Modem, Bhanuprakash <bhanuprakash.modem at intel.com>
> Sent: Tuesday, June 18, 2024 1:12 PM
> To: igt-dev at lists.freedesktop.org
> Cc: Modem, Bhanuprakash <bhanuprakash.modem at intel.com>; Nautiyal,
> Ankit K <ankit.k.nautiyal at intel.com>; Golani, Mitulkumar Ajitkumar
> <mitulkumar.ajitkumar.golani at intel.com>
> Subject: [i-g-t V2 1/2] tests/kms_vrr: New subtest for CMRR
> 
> CMRR is an variation of VRR where it varies Vtotal slightly (between additional
> 0 and 1 Vtotal scanlines) to match content rate exactly without frame drops
> using the adaptive sync framework.
> 
> This patch creates a new subtest to validate the CMRR as below:
> - Request flips with the refresh_rate * 1.001
> - Flips should happen at the frequency of refresh_rate.
> 
> V2:
>  - Tweak the clock if CMRR supported mode not found (Ankit)
>  - Rebase
> V3:
>  - Read flip completion events instead of Vblank evants
> V4:
>  - Fix clock calculation
>  - Other minor improvements

With Addressed above comments,

Changes LGTM.
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani at intel.com>

> 
> Cc: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
> Cc: Mitul Golani <mitulkumar.ajitkumar.golani at intel.com>
> Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
> ---
>  tests/kms_vrr.c | 130
> +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 128 insertions(+), 2 deletions(-)
> 
> diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c index 7f64d6806..ecbea1bc7
> 100644
> --- a/tests/kms_vrr.c
> +++ b/tests/kms_vrr.c
> @@ -37,6 +37,11 @@
>  #include <signal.h>
> 
>  /**
> + * SUBTEST: cmrr
> + * Description: Test to validate the content rate to exactly match with the
> + * 		requested rate without any frame drops.
> + * Functionality: CMRR
> + *
>   * SUBTEST: flip-basic
>   * Description: Tests that VRR is enabled and that the difference between flip
>   *              timestamps converges to the requested rate
> @@ -87,6 +92,9 @@
>   */
>  #define TEST_DURATION_NS (5000000000ull)
> 
> +#define CMRR_PRECISION_TOLERANCE	10
> +#define VREFRESH_MODIFIER	0.1
> +
>  enum {
>  	TEST_BASIC = 1 << 0,
>  	TEST_DPMS = 1 << 1,
> @@ -97,7 +105,8 @@ enum {
>  	TEST_SEAMLESS_VIRTUAL_RR = 1 << 6,
>  	TEST_FASTSET = 1 << 7,
>  	TEST_MAXMIN = 1 << 8,
> -	TEST_NEGATIVE = 1 << 9,
> +	TEST_CMRR = 1 << 9,
> +	TEST_NEGATIVE = 1 << 10,
>  };
> 
>  enum {
> @@ -232,6 +241,21 @@ virtual_rr_vrr_range_mode(igt_output_t *output,
> unsigned int virtual_refresh_rat
>  	return mode;
>  }
> 
> +static bool
> +is_cmrr_mode(drmModeModeInfoPtr mode)
> +{
> +	int calculated_refresh, actual_refresh, pixel_clock_per_line;
> +
> +	actual_refresh = mode->vrefresh * 100;
> +	pixel_clock_per_line = mode->clock * 1000 / mode->htotal;
> +	calculated_refresh = pixel_clock_per_line * 100 / mode->vtotal;
> +
> +	if ((actual_refresh - calculated_refresh) <
> CMRR_PRECISION_TOLERANCE)
> +		return false;
> +
> +	return true;
> +}
> +
>  /* Read min and max vrr range from the connector debugfs. */  static range_t
> get_vrr_range(data_t *data, igt_output_t *output) @@ -496,6 +520,57 @@
> flip_and_measure(data_t *data, igt_output_t *output, enum pipe pipe,
>  	return total_flip ? ((total_pass * 100) / total_flip) : 0;  }
> 
> +static uint32_t
> +flip_and_measure_cmrr(data_t *data, igt_output_t *output, enum pipe pipe,
> +		      uint64_t duration_ns)
> +{
> +	uint64_t start_ns, last_event_ns, event_ns;
> +	uint32_t total_flip = 0, total_pass = 0;
> +	bool front = false;
> +	drmModeModeInfoPtr mode = igt_output_get_mode(output);
> +	uint64_t req_rate_ns = rate_from_refresh(mode->vrefresh +
> VREFRESH_MODIFIER);
> +	uint64_t exp_rate_ns = rate_from_refresh(mode->vrefresh);
> +	uint64_t threshold_ns = exp_rate_ns / mode->vdisplay; /* Upto 1 scan
> +line. */
> +
> +	igt_info("CMRR on: requested rate: %"PRIu64" ns (%.2f Hz) "
> +		 "expected rate: %"PRIu64" ns - %"PRIu64" ns (%.2f-%.2f
> Hz)\n",
> +		 req_rate_ns, (mode->vrefresh + VREFRESH_MODIFIER),
> +		 (exp_rate_ns - threshold_ns), (exp_rate_ns + threshold_ns),
> +		 (float)NSECS_PER_SEC / (exp_rate_ns + threshold_ns),
> +		 (float)NSECS_PER_SEC / (exp_rate_ns - threshold_ns));
> +
> +	do_flip(data, &data->fb[0]);
> +	start_ns = last_event_ns = get_kernel_event_ns(data,
> DRM_EVENT_FLIP_COMPLETE);
> +	do {
> +		int64_t target_ns, wait_ns, diff_ns = exp_rate_ns;
> +
> +		front = !front;
> +		do_flip(data, front ? &data->fb[1] : &data->fb[0]);
> +
> +		event_ns = get_kernel_event_ns(data,
> DRM_EVENT_FLIP_COMPLETE);
> +		igt_debug("event_ns - last_event_ns: %"PRIu64" ns (%.2f
> Hz)\n",
> +			  event_ns - last_event_ns, (float)NSECS_PER_SEC /
> (event_ns -
> +last_event_ns));
> +
> +		diff_ns -= event_ns - last_event_ns;
> +		if (llabs(diff_ns) <= threshold_ns)
> +			total_pass += 1;
> +
> +		last_event_ns = event_ns;
> +		total_flip += 1;
> +
> +		diff_ns = event_ns - start_ns;
> +		wait_ns = ((diff_ns + req_rate_ns - 1) / req_rate_ns) *
> req_rate_ns;
> +		wait_ns -= diff_ns;
> +		target_ns = event_ns + wait_ns;
> +		while (get_time_ns() < target_ns - 10);
> +	} while (event_ns - start_ns <= duration_ns);
> +
> +	igt_info("Completed %u flips, %u vblanks were in threshold for (%.2f
> Hz) %"PRIu64"ns.\n",
> +		 total_flip, total_pass, (mode->vrefresh +
> VREFRESH_MODIFIER),
> +req_rate_ns);
> +
> +	return total_flip ? ((total_pass * 100) / total_flip) : 0; }
> +
>  /* 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) @@ -702,6 +777,49 @@
> test_seamless_virtual_rr_basic(data_t *data, enum pipe pipe, igt_output_t
> *outpu
>  	}
>  }
> 
> +static void
> +test_cmrr(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t
> +flags) {
> +	uint32_t result;
> +	int i;
> +	bool found = false;
> +	drmModeConnectorPtr connector = output->config.connector;
> +	drmModeModeInfo mode = *igt_output_get_mode(output);
> +
> +	igt_info("CMRR test execution on %s, PIPE_%s with VRR range: (%u-
> %u) Hz\n",
> +		 output->name, kmstest_pipe_name(pipe), data->range.min,
> +data->range.max);
> +
> +	for (i = 0; i < connector->count_modes; i++) {
> +		if (is_cmrr_mode(&connector->modes[i])) {
> +			mode = connector->modes[i];
> +
> +			found = true;
> +			break;
> +		}
> +	}
> +
> +	igt_info("Selected mode: ");
> +	kmstest_dump_mode(&mode);
> +
> +	if (!found) {
> +		igt_info("No CMRR mode found on %s, try to tweak the
> clock.\n",
> +output->name);
> +
> +		mode.clock = (mode.htotal * mode.vtotal * (mode.vrefresh +
> +VREFRESH_MODIFIER)) / 1000;
> +
> +		igt_info("Tweaked mode: ");
> +		kmstest_dump_mode(&mode);
> +	}
> +
> +	igt_output_override_mode(output, &mode);
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> +	prepare_test(data, output, pipe);
> +	result = flip_and_measure_cmrr(data, output, pipe,
> TEST_DURATION_NS * 2);
> +	igt_assert_f(result > 75,
> +		     "Refresh rate (%u Hz) %"PRIu64"ns: Target CMRR on
> threshold not reached, result was %u%%\n",
> +		     mode.vrefresh, rate_from_refresh(mode.vrefresh), result);
> }
> +
>  static void test_cleanup(data_t *data, enum pipe pipe, igt_output_t *output)
> {
>  	if (vrr_capable(output))
> @@ -718,7 +836,7 @@ static void test_cleanup(data_t *data, enum pipe
> pipe, igt_output_t *output)
> 
>  static bool output_constraint(data_t *data, igt_output_t *output, uint32_t
> flags)  {
> -	if ((flags & (TEST_SEAMLESS_VRR | TEST_SEAMLESS_DRRS)) &&
> +	if ((flags & (TEST_SEAMLESS_VRR | TEST_SEAMLESS_DRRS |
> TEST_CMRR)) &&
>  	    output->config.connector->connector_type !=
> DRM_MODE_CONNECTOR_eDP)
>  		return false;
> 
> @@ -906,6 +1024,14 @@ igt_main_args("drs:", long_opts, help_str,
> opt_handler, &data)
>  		igt_describe("Test to switch to any custom virtual mode in
> VRR range without modeset.");
>  		igt_subtest_with_dynamic("seamless-rr-switch-virtual")
>  			run_vrr_test(&data, test_seamless_virtual_rr_basic,
> TEST_SEAMLESS_VIRTUAL_RR);
> +
> +		igt_describe("Test to validate the the content rate exactly
> match with the "
> +			     "requested rate without any frame drops.");
> +		igt_subtest_with_dynamic("cmrr") {
> +
> 	igt_require(intel_display_ver(intel_get_drm_devid(data.drm_fd)) >=
> +20);
> +
> +			run_vrr_test(&data, test_cmrr, TEST_CMRR);
> +		}
>  	}
> 
>  	igt_fixture {
> --
> 2.43.2



More information about the igt-dev mailing list