[PATCH i-g-t v7 41/48] lib/igt_dp: Create generic helpers for DP information

Louis Chauvet
2026-02-23T12:09:30Z

With the introduction of unigraf tests, there is no reason to limit the
implementation to intel. Create easly extendable generic functions to
help supporting multiple GPU.

Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
lib/igt_dp.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/igt_dp.h | 30 ++++++++++
lib/meson.build | 1 +
3 files changed, 208 insertions(+)

diff --git a/lib/igt_dp.c b/lib/igt_dp.c
new file mode 100644
index 000000000000..0920a43af5e9
--- /dev/null
+++ b/lib/igt_dp.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Google
+ *
+ * Authors:
+ * Louis Chauvet <louis.chauvet@bootlin.com>
+ */
+
+#include "drmtest.h"
+#include "i915/i915_dp.h"
+#include "igt_amd.h"
+#include "igt_core.h"
+#include "igt_kms.h"
+#include <stdint.h>
+#include "igt_dp.h"
+
+/**
+ * igt_dp_get_current_link_rate: Get current link rate on a display port
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * Returns:
+ * The current link rate in kb/s, or a negative error code on failure.
+ */
+int igt_dp_get_current_link_rate(int drm_fd, igt_output_t *output)
+{
+ if (is_intel_device(drm_fd))
+ /*
+ * i915_dp_get_current_link_rate returns the value in tens of kb/s because
+ * that what the kernel uses. Convert it to kb/s to have a sane unit...
+ */
+ return i915_dp_get_current_link_rate(drm_fd, output) * 10;
+
+ igt_assert_f(false, "Current drm device is not able to report used link rate\n");
+ return -EINVAL;
+}
+
+/**
+ * igt_dp_get_current_lane_count: Get current lane count on a display port
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * Returns:
+ * The number of active lanes, or a negative error code on failure.
+ */
+int igt_dp_get_current_lane_count(int drm_fd, igt_output_t *output)
+{
+ if (is_intel_device(drm_fd))
+ return i915_dp_get_current_lane_count(drm_fd, output);
+
+ igt_assert_f(false, "Current drm device is not able to report used lane count\n");
+ return -EINVAL;
+}
+
+/**
+ * igt_dp_get_max_link_rate: Get maximum link rate on a display port
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * Returns:
+ * The maximum link rate in kb/s, or a negative error code on failure.
+ */
+int igt_dp_get_max_link_rate(int drm_fd, igt_output_t *output)
+{
+ if (is_intel_device(drm_fd))
+ /*
+ * i915_dp_get_max_link_rate returns the value in tens of kb/s because
+ * that what the kernel uses. Convert it to kb/s to have a sane unit...
+ */
+ return i915_dp_get_max_link_rate(drm_fd, output) * 10;
+
+ igt_assert_f(false, "Current drm device is not able to report max link rate\n");
+ return -EINVAL;
+}
+
+/**
+ * igt_dp_get_max_supported_rate: Get maximum supported link rate on a display port
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * Returns:
+ * The maximum supported link rate in kb/s, or a negative error code on failure.
+ */
+int igt_dp_get_max_supported_rate(int drm_fd, igt_output_t *output)
+{
+ if (is_intel_device(drm_fd))
+ /*
+ * i915_dp_get_max_supported_rate returns the value in tens of kb/s because
+ * that what the kernel uses. Convert it to kb/s to have a sane unit...
+ */
+ return i915_dp_get_max_supported_rate(drm_fd, output) * 10;
+
+ igt_assert_f(false, "Current drm device is not able to report max link rate\n");
+ return -EINVAL;
+}
+
+/**
+ * igt_dp_get_max_lane_count: Get maximum lane count on a display port
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * Returns:
+ * The maximum number of lanes, or a negative error code on failure.
+ */
+int igt_dp_get_max_lane_count(int drm_fd, igt_output_t *output)
+{
+ if (is_intel_device(drm_fd))
+ return i915_dp_get_max_lane_count(drm_fd, output);
+
+ igt_assert_f(false, "Current drm device is not able to report max lane count\n");
+ return -EINVAL;
+}
+
+/**
+ * igt_dp_force_link_retrain: Force link retraining on a display port
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ * @retrain_count: Number of times to retrain the link
+ */
+void igt_dp_force_link_retrain(int drm_fd, igt_output_t *output, int retrain_count)
+{
+ if (is_intel_device(drm_fd)) {
+ i915_dp_force_link_retrain(drm_fd, output, retrain_count);
+ return;
+ }
+
+ igt_assert_f(false, "Current drm device does not support link retraining\n");
+}
+
+/**
+ * igt_dp_get_pending_retrain: Get pending link retrain count
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * Returns:
+ * The number of pending retrain operations, or a negative error code on failure.
+ */
+int igt_dp_get_pending_retrain(int drm_fd, igt_output_t *output)
+{
+ if (is_intel_device(drm_fd))
+ return i915_dp_get_pending_retrain(drm_fd, output);
+
+ igt_assert_f(false, "Current drm device does not support pending retrain count checking\n");
+ return -EINVAL;
+}
+
+/**
+ * igt_dp_wait_pending_retrain: Wait for pending link retrain operations to complete
+ * @drm_fd: DRM file descriptor
+ * @output: igt_output_t object representing the display port
+ *
+ * This function waits for any pending link retrain operations to complete on the
+ * specified display port. It polls the debugfs interface for the pending retrain
+ * count until it reaches zero, indicating all retrain operations have completed.
+ */
+void igt_dp_wait_pending_retrain(int drm_fd, igt_output_t *output)
+{
+ double timeout = igt_default_display_detect_timeout();
+ struct timespec start, now;
+ double elapsed;
+
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ while (1) {
+ if (!igt_dp_get_pending_retrain(drm_fd, output))
+ return;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ elapsed = (now.tv_sec - start.tv_sec) +
+ (now.tv_nsec - start.tv_nsec) / 1e9;
+
+ if (elapsed >= timeout)
+ break;
+ usleep(10);
+ }
+ igt_assert_f(false, "Timeout waiting for pending retrain to complete\n");
+}
diff --git a/lib/igt_dp.h b/lib/igt_dp.h
new file mode 100644
index 000000000000..0c56ad2ec8b1
--- /dev/null
+++ b/lib/igt_dp.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Google
+ *
+ * Authors:
+ * Louis Chauvet <louis.chauvet@bootlin.com>
+ */
+
+#ifndef _IGT_DP_H_
+#define _IGT_DP_H_
+
+#include "igt_kms.h"
+
+int igt_dp_get_current_link_rate(int drm_fd, igt_output_t *output);
+
+int igt_dp_get_current_lane_count(int drm_fd, igt_output_t *output);
+
+int igt_dp_get_max_link_rate(int drm_fd, igt_output_t *output);
+
+int igt_dp_get_max_supported_rate(int drm_fd, igt_output_t *output);
+
+int igt_dp_get_max_lane_count(int drm_fd, igt_output_t *output);
+
+void igt_dp_force_link_retrain(int drm_fd, igt_output_t *output, int retrain_count);
+
+int igt_dp_get_pending_retrain(int drm_fd, igt_output_t *output);
+
+void igt_dp_wait_pending_retrain(int drm_fd, igt_output_t *output);
+
+#endif
diff --git a/lib/meson.build b/lib/meson.build
index e7f2d3a77799..98074685afda 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -29,6 +29,7 @@ lib_sources = [
'igt_drm_fdinfo.c',
'igt_fs.c',
'igt_aux.c',
+ 'igt_dp.c',
'igt_gt.c',
'igt_halffloat.c',
'igt_hwmon.c',

--
2.52.0