[PATCH i-g-t v1 1/2] lib/igt_vrr:Add VRR helper library for display refresh rate testing
Naladala Ramanaidu <[email protected]> Wed, 5 Aug 2026 04:46:57 +0530
| Newsgroups | org.freedesktop.lists.igt-dev |
|---|---|
| Message-ID | <[email protected]> |
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 © 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 = snprintf(path, sizeof(path), + "crtc-%d/intel_vrr_target_refresh_rate", + crtc->pipe); + igt_assert(ret > 0 && ret < sizeof(path)); + + switch (cmrr_flag) { + case CMRR_VIDEO_MODE: + cmrr_value = vrefresh * CMRR_NUMERATOR; + len = 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 = vrefresh * CMRR_NUMERATOR; + len = snprintf(buf, sizeof(buf), + "%" PRIu64 "/%llu", + cmrr_value, + CMRR_DENOMINATOR); + igt_assert(len > 0 && len < sizeof(buf)); + break; + + default: + cmrr_value = 0 * CMRR_NUMERATOR; + len = 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 = snprintf(path, sizeof(path), + "crtc-%d/intel_vrr_target_refresh_rate", + crtc->pipe); + igt_assert(ret > 0 && ret < sizeof(path)); + + igt_debugfs_read(fd, path, buf); + + ret = sscanf(buf, "%" SCNu64 "/%" SCNu64, + &numerator, &denominator); + igt_assert(ret == 2); + + if (denominator == CMRR_VIDEO_MODE_DENOMINATOR) + return CMRR_VIDEO_MODE; + + if (denominator == CMRR_DENOMINATOR) + return CMRR_NON_VIDEO_MODE; + + if (denominator == 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)mode->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 = output->config.connector; + if (!connector) + return false; + + for (int i = 0; i < connector->count_modes; i++) { + if (connector->modes[i].vrefresh == fps) { + *matched_mode = 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 © 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[] = { + 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 = + 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 = [ 'igt_configfs.c', 'igt_facts.c', 'igt_crc.c', + 'igt_vrr.c', 'igt_debugfs.c', 'igt_device.c', 'igt_device_scan.c', -- 2.43.0