From: "Borah, Chaitanya Kumar" <chaitanya.kumar.borah@intel.com>
To: Naladala Ramanaidu <ramanaidu.naladala@intel.com>,
<igt-dev@lists.freedesktop.org>
Cc: <mitulkumar.ajitkumar.golani@intel.com>
Subject: Re: [PATCH i-g-t v4 2/2] tests/kms_vrr: add CMRR fixed and video mode subtests
Date: Thu, 20 Aug 2026 16:40:26 +0530 [thread overview]
Message-ID: <cbc88cef-1008-409b-aa54-3d9fd4ae5696@intel.com> (raw)
In-Reply-To: <20260812130738.1242659-3-ramanaidu.naladala@intel.com>
On 8/12/2026 6:37 PM, Naladala Ramanaidu wrote:
> Add test coverage to validate Content Match Refresh Rate (CMRR)
> behavior across both fixed and video timing display modes.
>
> This introduces a shared helper library to support refresh-rate
> mode selection and parsing,
Does it?
along with two new test cases covering
> fixed-mode and video-mode scenarios.
>
Let's call it desktop mode (here and everywhere else). Refresh rates are
fixed here anyway.
> The new tests measure actual display refresh timing during CMRR
> operation and compare it against the expected target rate to
> verify correctness. Video mode coverage validates behavior across
> standard video timing rates, while fixed mode coverage targets
> display modes that fall outside the standard video timing set.
>
> Each test cycles through the relevant refresh configurations,
> applying and resetting the appropriate settings between
> measurement passes to ensure consistent and isolated test results.
>
> v2: Fix test issue.
> v3: Address review comments. (Mitul)
> v4: Fix test issue.
>
> Signed-off-by: Naladala Ramanaidu <ramanaidu.naladala@intel.com>
> ---
> tests/kms_vrr.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 204 insertions(+)
>
> diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c
> index 27f18e8d0..ab6bc66d9 100644
> --- a/tests/kms_vrr.c
> +++ b/tests/kms_vrr.c
> @@ -32,6 +32,7 @@
> #include "igt_pm.h"
> #include "igt_psr.h"
> #include "i915/intel_drrs.h"
> +#include "igt_vrr.h"
> #include "sw_sync.h"
> #include <fcntl.h>
> #include <signal.h>
> @@ -80,6 +81,14 @@
> *
> * SUBTEST: lobf-dc3co
> * Description: Test DC3CO entry during LOBF.
> + *
> + * SUBTEST: cmrr-fixed-mode
> + * Description: Test to set a fixed CMRR target refresh rate and verify it
> + * is correctly applied.
> + *
> + * SUBTEST: cmrr-video-mode
> + * Description: Test to set standard video timing refresh rates via CMRR
> + * and verify each target rate is correctly applied.
> */
>
> #define NSECS_PER_SEC (1000000000ull)
> @@ -103,6 +112,8 @@ enum {
> TEST_LINK_OFF = 1 << 10,
> TEST_NEGATIVE = 1 << 11,
> TEST_FORCE_RR = 1 << 12,
> + TEST_CMRR_FIXED_MODE = 1 << 13,
> + TEST_CMRR_VIDEO_MODE = 1 << 14,
> };
>
> enum {
> @@ -580,6 +591,184 @@ flip_and_measure(data_t *data, igt_output_t *output,
> return 0;
> }
>
> +static
> +uint64_t wait_next_vblank_ts_ns(data_t *data, igt_crtc_t *crtc)
> +{
> + union drm_wait_vblank vbl = {};
> +
> + vbl.request.type = DRM_VBLANK_RELATIVE | igt_crtc_get_vbl_flag(crtc);
> + vbl.request.sequence = 1;
> + do_or_die(igt_ioctl(data->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl));
> +
> + return vbl.reply.tval_sec * NSECS_PER_SEC + vbl.reply.tval_usec * 1000ull;
> +}
> +
Time to create a helper for this. See wait_for_vblank() in kms_async_flips.c
> +static void
> +flip_and_measure_target_rr(data_t *data, igt_crtc_t *crtc,
> + double vrefresh, uint32_t cmrr_mode)
> +{
> + uint32_t i;
> + bool front = false;
> + uint64_t last_vblank_ns, vblank_ns;
> + uint32_t err_frames = 0;
> + uint64_t frame_times_ns[TARGET_RR_SAMP_COUNT];
> + uint64_t exp_time_ns;
> + uint64_t total_frame_time_ns = 0;
> + uint64_t avg_frame_time_ns;
> + double avg_refresh_rate;
> + double expected_rr;
> + uint32_t valid_frames = 0;
> +
> + exp_time_ns = igt_kms_frame_time_from_vrefresh(vrefresh);
> +
> + do_flip(data, &data->fb[0]);
> + (void)get_kernel_event_ns(data, DRM_EVENT_FLIP_COMPLETE);
> + last_vblank_ns = wait_next_vblank_ts_ns(data, crtc);
> +
> + for (i = 0; i < TARGET_RR_SAMP_COUNT; i++) {
> + front = !front;
> +
> + do_flip(data, front ? &data->fb[1] : &data->fb[0]);
> + vblank_ns = wait_next_vblank_ts_ns(data, crtc);
> + (void)get_kernel_event_ns(data, DRM_EVENT_FLIP_COMPLETE);
> +
> + frame_times_ns[i] = vblank_ns - last_vblank_ns;
> +
> + if (frame_times_ns[i] > (exp_time_ns + (exp_time_ns / 2))) {
> + err_frames++;
> + last_vblank_ns = vblank_ns;
> + continue;
> + }
> +
> + last_vblank_ns = vblank_ns;
> + total_frame_time_ns += frame_times_ns[i];
> + }
> +
> + valid_frames = TARGET_RR_SAMP_COUNT - err_frames;
> + igt_assert_f(valid_frames > 0,
> + "No valid frame samples collected\n");
We should hold valid frames to a higher standard than > 0
> +
> + avg_frame_time_ns = total_frame_time_ns / valid_frames;
> + avg_refresh_rate = (double)NSECS_PER_SEC / (double)avg_frame_time_ns;
> +
> + if (cmrr_mode == CMRR_VIDEO_MODE) {
> + expected_rr = (double)(vrefresh * CMRR_NUMERATOR) /
> + (double)CMRR_VIDEO_MODE_DENOMINATOR;
> + igt_assert_f(fabs(avg_refresh_rate - expected_rr) <= 0.02,
> + "CMRR refresh rate mismatch: "
> + "measured avg_rr = %.3f Hz, "
> + "expected_rr = %.3f Hz\n",
> + avg_refresh_rate, expected_rr);
> + }
> +
> + if (cmrr_mode == CMRR_NON_VIDEO_MODE) {
> + expected_rr = (double)(vrefresh * CMRR_NUMERATOR) /
> + (double)CMRR_DENOMINATOR;
> + igt_assert_f(fabs(avg_refresh_rate - expected_rr) <= 0.02,
> + "CMRR refresh rate mismatch: "
> + "measured avg_rr = %.3f Hz, "
> + "expected_rr = %.3f Hz\n",
> + avg_refresh_rate, expected_rr);
> + }
> +
> + if (cmrr_mode == CMRR_DISABLE) {
> + expected_rr = vrefresh;
> + igt_assert_f(fabs(avg_refresh_rate - expected_rr) <= 0.02,
> + "CMRR refresh rate mismatch: "
> + "measured avg_rr = %.3f Hz, "
> + "expected_rr = %.3f Hz\n",
> + avg_refresh_rate, expected_rr);
> + }
> +
> + igt_info("Average RR (Hz): %.2f , Expected RR (Hz): %.2f, error frames = %d\n",
> + avg_refresh_rate, expected_rr, err_frames);
> +}
> +
> +static
> +void test_cmrr(data_t *data, igt_crtc_t *crtc,
> + igt_output_t *output, uint32_t flags)
> +{
> + uint32_t found;
> + double rr_from_mode;
> + drmModeModeInfo mode;
> + drmModeConnectorPtr connector;
> + int j;
> +
> + igt_require_f(cmrr_supported(data->drm_fd, crtc->crtc_index),
> + "CMRR not supported\n");
> + prepare_test(data, output, crtc);
> + set_vrr_on_crtc(data, crtc, true, false);
> +
> + if (flags & TEST_CMRR_VIDEO_MODE) {
> + for (j = 0; j < igt_vrr_standard_video_timing_fps_count; j++) {
> + found = igt_vrr_get_mode_with_video_timing(output,
> + igt_vrr_standard_video_timing_fps[j],
> + &mode);
> + if (found) {
> + rr_from_mode = igt_vrr_mode_line_refresh_hz(&mode);
> + igt_output_override_mode(output, &mode);
> + igt_info("Override mode:");
> + kmstest_dump_mode(&mode);
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> + igt_target_rr_debugfs_write(data->drm_fd,
> + crtc->crtc_index,
> + mode.vrefresh,
> + CMRR_NUMERATOR,
> + CMRR_VIDEO_MODE_DENOMINATOR);
> +
> + flip_and_measure_target_rr(data, crtc,
> + mode.vrefresh,
> + CMRR_VIDEO_MODE);
> +
> + igt_target_rr_debugfs_write(data->drm_fd,
> + crtc->crtc_index,
> + mode.vrefresh,
> + 0, 0);
> +
> + flip_and_measure_target_rr(data, crtc,
> + rr_from_mode,
> + CMRR_DISABLE);
> + }
> + }
> + }
> +
> + if (flags & TEST_CMRR_FIXED_MODE) {
> + found = 0;
> + connector = output->config.connector;
> + for (j = 0; j < connector->count_modes; j++) {
> + mode = connector->modes[j];
> + rr_from_mode = igt_vrr_mode_line_refresh_hz(&mode);
> +
> + if (rr_from_mode - mode.vrefresh > 0.04) {
> + found = 1;
> + igt_output_override_mode(output, &mode);
> + igt_info("Override mode:");
> + kmstest_dump_mode(&mode);
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> + igt_target_rr_debugfs_write(data->drm_fd,
> + crtc->crtc_index,
> + mode.vrefresh,
> + CMRR_NUMERATOR,
> + CMRR_DENOMINATOR);
> +
> + flip_and_measure_target_rr(data, crtc,
> + mode.vrefresh,
> + CMRR_NON_VIDEO_MODE);
> +
> + igt_target_rr_debugfs_write(data->drm_fd,
> + crtc->crtc_index,
> + mode.vrefresh,
> + 0, 0);
> +
> + flip_and_measure_target_rr(data, crtc,
> + rr_from_mode,
> + CMRR_DISABLE);
> + }
> + }
> + igt_require_f(found, "No non-video-timing mode found.\n");
Should this be a skip?
> + }
> +}
> +
> /* Basic VRR flip functionality test - enable, measure, disable, measure */
> static void
> test_basic(data_t *data, igt_crtc_t *crtc, igt_output_t *output,
> @@ -591,6 +780,7 @@ test_basic(data_t *data, igt_crtc_t *crtc, igt_output_t *output,
> uint64_t rate[] = {0};
>
> prepare_test(data, output, crtc);
> +
> range = data->range;
> vtest_ns = data->vtest_ns;
> rate[0] = vtest_ns.rate_ns;
> @@ -1147,6 +1337,20 @@ int igt_main_args("drs:", long_opts, help_str, opt_handler, &data)
> }
> }
>
> + igt_subtest_group() {
> + igt_fixture()
> + igt_require_intel(data.drm_fd);
> +
There was some recent discussion regarding intel specific tests in tests
folder [1].
But this change is just following a pre-existing pattern so this should
not be a blocker but may be this warrants a broader discussion.
==
Chaitanya
[1]
https://lore.kernel.org/igt-dev/210afacb-8486-43a5-865c-f52befda3231@intel.com/
> + igt_describe("Test to validate CMRR in fixed mode.");
> + igt_subtest_with_dynamic("cmrr-fixed-mode") {
> + run_vrr_test(&data, test_cmrr, TEST_CMRR_FIXED_MODE);
> + }
> +
> + igt_describe("Test to validate CMRR in video mode.");
> + igt_subtest_with_dynamic("cmrr-video-mode") {
> + run_vrr_test(&data, test_cmrr, TEST_CMRR_VIDEO_MODE);
> + }
> + }
> igt_fixture() {
> close(data.debugfs_fd);
> igt_display_fini(&data.display);
next prev parent reply other threads:[~2026-08-20 11:11 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 13:07 [PATCH i-g-t v4 0/2] Add CMRR subtests Naladala Ramanaidu
2026-08-12 13:07 ` [PATCH i-g-t v4 1/2] lib/igt_vrr:Add VRR helper library for display refresh rate testing Naladala Ramanaidu
2026-08-19 16:03 ` Golani, Mitulkumar Ajitkumar
2026-08-20 11:08 ` Borah, Chaitanya Kumar
2026-08-12 13:07 ` [PATCH i-g-t v4 2/2] tests/kms_vrr: add CMRR fixed and video mode subtests Naladala Ramanaidu
2026-08-19 17:00 ` Golani, Mitulkumar Ajitkumar
2026-08-20 11:10 ` Borah, Chaitanya Kumar
2026-08-20 11:10 ` Borah, Chaitanya Kumar [this message]
2026-08-12 14:12 ` ✓ i915.CI.BAT: success for Add CMRR subtests (rev4) Patchwork
2026-08-12 14:14 ` ✓ Xe.CI.BAT: " Patchwork
2026-08-12 17:49 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-08-12 18:01 ` ✗ i915.CI.Full: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cbc88cef-1008-409b-aa54-3d9fd4ae5696@intel.com \
--to=chaitanya.kumar.borah@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=mitulkumar.ajitkumar.golani@intel.com \
--cc=ramanaidu.naladala@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.