Re: [PATCH i-g-t v1 1/2] lib/igt_vrr:Add VRR helper library for display refresh rate testing

Jani Nikula <[email protected]> Wed, 05 Aug 2026 10:15:11 +0300
Newsgroups org.freedesktop.lists.igt-dev
Organization Intel Finland Oy - BIC 0357606-4 - c/o Alberga Business Park, 6 krs Bertel Jungin Aukio 5, 02600 Espoo, Finland
Message-ID <[email protected]>
On Wed, 05 Aug 2026, Naladala Ramanaidu <[email protected]> wrot=
e:
> Introduce a new helper library for Variable Refresh Rate (VRR).
>
> Add helpers to validate targeted refresh-rate testing.
>
> Signed-off-by: Naladala Ramanaidu <[email protected]>
> ---
>  lib/igt_vrr.c   | 150 ++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/igt_vrr.h   |  45 +++++++++++++++
>  lib/meson.build |   1 +
>  3 files changed, 196 insertions(+)
>  create mode 100644 lib/igt_vrr.c
>  create mode 100644 lib/igt_vrr.h
>
> diff --git a/lib/igt_vrr.c b/lib/igt_vrr.c
> new file mode 100644
> index 000000000..a11cc8adc
> --- /dev/null
> +++ b/lib/igt_vrr.c
> @@ -0,0 +1,150 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright =C2=A9 2026 Intel Corporation
> + */
> +
> +#include <inttypes.h>
> +
> +#include "igt_vrr.h"
> +
> +/**
> + * igt_cmrr_debugfs_write:
> + * @fd: DRM file descriptor.
> + * @crtc: CRTC whose VRR debugfs node is to be updated.
> + * @vrefresh: Target refresh rate to program.
> + * @cmrr_flag: CMRR mode to configure (video, non-video, or disable).
> + *
> + * Write the target CMRR refresh rate configuration to the per-CRTC
> + * VRR debugfs interface.
> + *
> + * Returns:
> + * None.
> + */
> +void
> +igt_target_rr_debugfs_write(int fd, igt_crtc_t *crtc,
> +			    uint32_t vrefresh,
> +			    uint32_t cmrr_flag)
> +{
> +	char buf[32];
> +	char path[64];
> +	uint32_t len, ret;
> +	uint64_t cmrr_value;
> +
> +	ret =3D snprintf(path, sizeof(path),
> +		       "crtc-%d/intel_vrr_target_refresh_rate",
> +		       crtc->pipe);

crtc->pipe usage here is plain wrong.

Besides, aren't there already helpers for debugfs read/write? If not,
there should be generic helpers.

> +	igt_assert(ret > 0 && ret < sizeof(path));
> +
> +	switch (cmrr_flag) {
> +	case CMRR_VIDEO_MODE:
> +		cmrr_value =3D vrefresh * CMRR_NUMERATOR;
> +		len =3D snprintf(buf, sizeof(buf),
> +			       "%" PRIu64 "/%llu",
> +			       cmrr_value,
> +			       CMRR_VIDEO_MODE_DENOMINATOR);
> +		igt_assert(len > 0 && len < sizeof(buf));
> +		break;
> +
> +	case CMRR_NON_VIDEO_MODE:
> +		cmrr_value =3D vrefresh * CMRR_NUMERATOR;
> +		len =3D snprintf(buf, sizeof(buf),
> +			       "%" PRIu64 "/%llu",
> +			       cmrr_value,
> +			       CMRR_DENOMINATOR);
> +		igt_assert(len > 0 && len < sizeof(buf));
> +		break;
> +
> +	default:
> +		cmrr_value =3D 0 * CMRR_NUMERATOR;
> +		len =3D snprintf(buf, sizeof(buf),
> +			       "%" PRIu64 "/0", cmrr_value);
> +		igt_assert(len > 0 && len < sizeof(buf));
> +		break;
> +	}
> +
> +	__igt_debugfs_write(fd, path, buf, len);
> +}
> +
> +/**
> + * igt_cmrr_debugfs_read:
> + * @fd: DRM file descriptor.
> + * @crtc: CRTC whose VRR debugfs node is to be read.
> + *
> + * Read the configured CMRR mode from the per-CRTC VRR debugfs node.
> + *
> + * Return: The configured CMRR mode (video, non-video, or disabled).
> + */
> +uint32_t
> +igt_target_rr_debugfs_read(int fd, igt_crtc_t *crtc)
> +{
> +	char buf[32];
> +	char path[64];
> +	uint32_t ret;
> +	uint64_t numerator, denominator;
> +
> +	ret =3D snprintf(path, sizeof(path),
> +		       "crtc-%d/intel_vrr_target_refresh_rate",
> +		       crtc->pipe);

Ditto.

BR,
Jani.


> +	igt_assert(ret > 0 && ret < sizeof(path));
> +
> +	igt_debugfs_read(fd, path, buf);
> +
> +	ret =3D sscanf(buf, "%" SCNu64 "/%" SCNu64,
> +		     &numerator, &denominator);
> +	igt_assert(ret =3D=3D 2);
> +
> +	if (denominator =3D=3D CMRR_VIDEO_MODE_DENOMINATOR)
> +		return CMRR_VIDEO_MODE;
> +
> +	if (denominator =3D=3D CMRR_DENOMINATOR)
> +		return CMRR_NON_VIDEO_MODE;
> +
> +	if (denominator =3D=3D 0)
> +		return CMRR_DISABLE;
> +
> +	return CMRR_DISABLE;
> +}
> +
> +/**
> + * igt_vrr_mode_line_refresh_hz:
> + * @mode: DRM display mode used for the calculation
> + *
> + * Compute the refresh rate directly from the mode timing parameters.
> + *
> + * Returns: Refresh rate in Hz as a floating-point value.
> + */
> +double igt_vrr_mode_line_refresh_hz(const drmModeModeInfo *mode)
> +{
> +	return (double)mode->clock * 1000.0 / ((double)mode->htotal * (double)m=
ode->vtotal);
> +}
> +
> +/**
> + * igt_vrr_get_mode_with_video_timeing:
> + * @output: Display output containing connector mode list
> + * @fps: Requested integer refresh rate in Hz
> + * @matched_mode: Returned mode that matches @fps
> + *
> + * Find and return a connector mode that matches the requested
> + * video timing refresh rate in Hz.
> + *
> + * Returns: true when a mode is found, false otherwise
> + */
> +
> +bool igt_vrr_get_mode_with_video_timeing(igt_output_t *output,
> +					 uint32_t fps,
> +					 drmModeModeInfo *matched_mode)
> +{
> +	drmModeConnectorPtr connector;
> +
> +	connector =3D output->config.connector;
> +	if (!connector)
> +		return false;
> +
> +	for (int i =3D 0; i < connector->count_modes; i++) {
> +		if (connector->modes[i].vrefresh =3D=3D fps) {
> +			*matched_mode =3D connector->modes[i];
> +			return true;
> +		}
> +	}
> +	return false;
> +}
> diff --git a/lib/igt_vrr.h b/lib/igt_vrr.h
> new file mode 100644
> index 000000000..7724f60a1
> --- /dev/null
> +++ b/lib/igt_vrr.h
> @@ -0,0 +1,45 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright =C2=A9 2026 Intel Corporation
> + */
> +
> +#ifndef IGT_VRR_H
> +#define IGT_VRR_H
> +
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include "igt.h"
> +#include "igt_kms.h"
> +
> +#define CMRR_NUMERATOR 1000ULL
> +#define CMRR_DENOMINATOR 1000ULL
> +#define CMRR_VIDEO_MODE_DENOMINATOR 1001ULL
> +#define TARGET_RR_SAMP_COUNT 100
> +
> +enum {
> +	CMRR_VIDEO_MODE,
> +	CMRR_NON_VIDEO_MODE,
> +	CMRR_DISABLE,
> +};
> +
> +const uint32_t igt_vrr_standard_video_timing_fps[] =3D {
> +	24, 25, 30, 48, 50, 60, 75, 90, 96, 100, 120, 144, 165, 180, 200, 240,
> +};
> +
> +const uint32_t igt_vrr_standard_video_timing_fps_count =3D
> +	ARRAY_SIZE(igt_vrr_standard_video_timing_fps);
> +
> +void
> +igt_target_rr_debugfs_write(int fd, igt_crtc_t *crtc,
> +			    uint32_t vrefresh,
> +			    uint32_t cmrr_flag);
> +uint32_t
> +igt_target_rr_debugfs_read(int fd, igt_crtc_t *crtc);
> +
> +double igt_vrr_mode_line_refresh_hz(const drmModeModeInfo *mode);
> +
> +bool igt_vrr_get_mode_with_video_timeing(igt_output_t *output,
> +					 uint32_t fps,
> +					 drmModeModeInfo *matched_mode);
> +
> +#endif
> diff --git a/lib/meson.build b/lib/meson.build
> index 3001b473e..8675bd4a6 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -22,6 +22,7 @@ lib_sources =3D [
>  	'igt_configfs.c',
>  	'igt_facts.c',
>  	'igt_crc.c',
> +        'igt_vrr.c',
>  	'igt_debugfs.c',
>  	'igt_device.c',
>  	'igt_device_scan.c',

--=20
Jani Nikula, Intel