[PATCH i-g-t v1 1/2] lib/igt_kms: Add platform-specific joiner exception mode handling

Sowmiya S <[email protected]> Thu, 23 Jul 2026 19:13:53 +0530
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <[email protected]>
On NVL (display_ver=35), a higher max_dotclock causes modes like
6144x3456@60 to pass the standard igt_bigjoiner_possible() checks,
yet the kernel still enables joiner for them. Introduce per-platform
exception mode lists (e.g. nvl_joiner_exception_modes[]) dispatched
via IS_NOVALAKE() in a new mode_needs_joiner_exception() helper, and
wire it into igt_bigjoiner_possible(). Also add IS_NOVALAKE() to
intel_chipset.h as a combined IS_NOVALAKE_S() || IS_NOVALAKE_P() macro.

Signed-off-by: Sowmiya S <[email protected]>
---
 lib/igt_kms.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 2eefb773b..bfa6dfc0e 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -7058,6 +7058,52 @@ int intel_get_max_pipe_hdisplay(int drm_fd)
 						   HDISPLAY_5K_PER_PIPE;
 }
 
+struct joiner_mode_exception {
+	uint16_t hdisplay, vdisplay;
+	uint32_t clock;
+};
+
+static bool match_joiner_exception(drmModeModeInfo *mode,
+				   const struct joiner_mode_exception *list,
+				   int count)
+{
+	for (int i = 0; i < count; i++) {
+		if (mode->hdisplay == list[i].hdisplay &&
+		    mode->vdisplay == list[i].vdisplay &&
+		    mode->clock == list[i].clock)
+			return true;
+	}
+
+	return false;
+}
+
+/* NVL: higher max_dotclock allows clocks that still need joiner */
+static const struct joiner_mode_exception nvl_joiner_exception_modes[] = {
+	{ 6144, 3456, 1413390 }, /* 6144x3456@60Hz */
+};
+
+/*
+ * mode_needs_joiner_exception - check if a mode requires joiner via explicit exception
+ * @drm_fd: drm file descriptor
+ * @mode: libdrm mode
+ *
+ * On some platforms, a higher max_dotclock means certain modes won't trigger
+ * the standard clock or hdisplay checks even though the kernel enables joiner
+ * for them. Each platform has its own exception list.
+ *
+ * Returns: True if the mode is a known joiner exception, else False.
+ */
+static bool mode_needs_joiner_exception(int drm_fd, drmModeModeInfo *mode)
+{
+	uint16_t dev_id = intel_get_drm_devid(drm_fd);
+
+	if (IS_NOVALAKE_P(dev_id) || IS_NOVALAKE_S(dev_id))
+		return match_joiner_exception(mode, nvl_joiner_exception_modes,
+					      ARRAY_SIZE(nvl_joiner_exception_modes));
+
+	return false;
+}
+
 /**
  * igt_bigjoiner_possible:
  * @drm_fd: drm file descriptor
@@ -7066,13 +7112,15 @@ int intel_get_max_pipe_hdisplay(int drm_fd)
  *
  * Bigjoiner is required when the requested mode exceeds single-pipe
  * platform limits, i.e. hdisplay is above the platform threshold or
- * clock is above @max_dotclock.
+ * clock is above @max_dotclock. On NVL, the higher max_dotclock means
+ * some modes (e.g. 6144x3456@60) need an explicit exception check.
  *
  * Returns: True if mode requires Bigjoiner, else False.
  */
 bool igt_bigjoiner_possible(int drm_fd, drmModeModeInfo *mode, int max_dotclock)
 {
-	return (mode->hdisplay > intel_get_max_pipe_hdisplay(drm_fd) ||
+	return (mode_needs_joiner_exception(drm_fd, mode) ||
+		mode->hdisplay > intel_get_max_pipe_hdisplay(drm_fd) ||
 		mode->clock > max_dotclock);
 }
 
-- 
2.43.0