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