Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Kunal Joshi <kunal1.joshi@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Kunal Joshi <kunal1.joshi@intel.com>
Subject: [PATCH i-g-t 07/13] lib/i915/i915_dp: Add a Type-C port mode query
Date: Wed, 16 Sep 2026 10:17:55 +0530	[thread overview]
Message-ID: <20260916044801.1279102-8-kunal1.joshi@intel.com> (raw)
In-Reply-To: <20260916044801.1279102-1-kunal1.joshi@intel.com>

Whether a DP link is tunneled over USB4/Thunderbolt decides where its
link clock comes from: a tbt-alt link is clocked by the Thunderbolt
PLL, every other mode by the PHY PLL. A test that wants to cover the
tunneled path has to be able to tell them apart, and nothing in IGT
can today.

The driver already reports it. For every connected Type-C connector
intel_connector_info() prints

	TC Port TC1: mode: tbt-alt, pin assignment: D, max lanes: 4

in the i915_display_info debugfs file, with the mode being one of
disconnected, tbt-alt, dp-alt or legacy. A connector with no TC Port
line is on a combo or native PHY.

Add i915_dp_get_tc_mode() returning that mode as an enum, optionally
along with the pin assignment and the Type-C max lane count, which are
worth having in a log line, and i915_dp_tc_mode_name() to get the
driver's spelling back for the same purpose.

i915_display_info is a per-device file listing the CRTCs first and the
connectors after them, so find the [CONNECTOR:<id>: block belonging to
the output and terminate it at the next [CONNECTOR: marker. Without
that second step a connector on a combo PHY picks up the TC Port line
of whichever connector comes after it.

Start the search at the "Connector info" heading. The CRTC section
names the connectors of every active output, so for an active output
the first [CONNECTOR:<id>: match is intel_encoder_info()'s reference to
it, not its own block. Parsing would then stop before ever reaching the
TC Port line and report a tbt-alt connector as having no Type-C port at
all.

Read the file with igt_sysfs_get(), which sizes the buffer from the
file, rather than the fixed 16 KiB and 8 KiB stack buffers the existing
readers in lib/igt_kms.c use without checking for truncation.

Note that MST stream connectors do report the TC line, since both
branches of intel_connector_info() resolve the digital port with
intel_attached_dp(), so an MST topology can be classified from any of
its streams without finding the root. Disconnected connectors return
early and print no TC line at all, which is why the root connector of
an active MST topology has none.

Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 lib/i915/i915_dp.c | 111 +++++++++++++++++++++++++++++++++++++++++++++
 lib/i915/i915_dp.h |  24 ++++++++++
 2 files changed, 135 insertions(+)

diff --git a/lib/i915/i915_dp.c b/lib/i915/i915_dp.c
index aba6aa8d5..89d1dbd4d 100644
--- a/lib/i915/i915_dp.c
+++ b/lib/i915/i915_dp.c
@@ -35,7 +35,9 @@
 
 #include "i915_dp.h"
 #include "igt_core.h"
+#include "igt_debugfs.h"
 #include "igt_kms.h"
+#include "igt_sysfs.h"
 
 /*
  * The driver allows at most 10 link rates over 3 lane counts, i.e. 30 entries
@@ -527,3 +529,112 @@ int i915_dp_get_next_lower_rate(int drm_fd, igt_output_t *output, int rate)
 
 	return next;
 }
+
+/**
+ * i915_dp_tc_mode_name:
+ * @mode: Connector mode
+ *
+ * Returns: The driver's name for @mode, for use in a log line
+ */
+const char *i915_dp_tc_mode_name(enum i915_dp_tc_mode mode)
+{
+	switch (mode) {
+	case I915_DP_TC_DISCONNECTED:
+		return "disconnected";
+	case I915_DP_TC_LEGACY:
+		return "legacy";
+	case I915_DP_TC_DP_ALT:
+		return "dp-alt";
+	case I915_DP_TC_TBT_ALT:
+		return "tbt-alt";
+	default:
+		return "native";
+	}
+}
+
+/**
+ * i915_dp_get_tc_mode:
+ * @drm_fd: A drm file descriptor
+ * @output: Target output
+ * @pin_assignment: Where to store the Type-C pin assignment, or NULL
+ * @max_lanes: Where to store the Type-C max lane count, or NULL
+ *
+ * Read the connector mode of @output out of the TC Port line the driver
+ * prints for every connected Type-C connector in the i915_display_info
+ * debugfs file:
+ *
+ *	TC Port TC1: mode: tbt-alt, pin assignment: D, max lanes: 4
+ *
+ * @pin_assignment and @max_lanes are only written when the line is present.
+ *
+ * Returns: The connector mode, or I915_DP_TC_NONE when @output has no TC Port
+ * line, i.e. it is on a combo or native PHY
+ */
+enum i915_dp_tc_mode i915_dp_get_tc_mode(int drm_fd, igt_output_t *output,
+					 char *pin_assignment, int *max_lanes)
+{
+	enum i915_dp_tc_mode mode = I915_DP_TC_NONE;
+	char marker[32];
+	char mode_str[32];
+	char *info, *block, *next_block, *line;
+	char pin;
+	int lanes;
+	int dir;
+
+	dir = igt_debugfs_dir(drm_fd);
+	igt_assert_fd(dir);
+	info = igt_sysfs_get(dir, "i915_display_info");
+	close(dir);
+	igt_assert_f(info, "Unable to read i915_display_info\n");
+
+	/*
+	 * i915_display_info is a per-device file that lists the CRTCs first
+	 * and the connectors after them. The CRTC section names the connectors
+	 * of every active output, so the search has to start at the connector
+	 * section, or an active output's first match is that reference rather
+	 * than the connector's own block and the TC Port line is never
+	 * reached. The block ends where the next connector's begins.
+	 */
+	snprintf(marker, sizeof(marker), "[CONNECTOR:%d:",
+		 output->config.connector->connector_id);
+
+	block = strstr(info, "Connector info");
+	if (!block)
+		goto out;
+
+	block = strstr(block, marker);
+	if (!block)
+		goto out;
+
+	next_block = strstr(block + strlen(marker), "[CONNECTOR:");
+	if (next_block)
+		*next_block = '\0';
+
+	line = strstr(block, "TC Port ");
+	if (!line)
+		goto out;
+
+	if (sscanf(line,
+		   "TC Port %*[^:]: mode: %31[^,], pin assignment: %c, max lanes: %d",
+		   mode_str, &pin, &lanes) != 3)
+		goto out;
+
+	if (!strcmp(mode_str, "tbt-alt"))
+		mode = I915_DP_TC_TBT_ALT;
+	else if (!strcmp(mode_str, "dp-alt"))
+		mode = I915_DP_TC_DP_ALT;
+	else if (!strcmp(mode_str, "legacy"))
+		mode = I915_DP_TC_LEGACY;
+	else
+		mode = I915_DP_TC_DISCONNECTED;
+
+	if (pin_assignment)
+		*pin_assignment = pin;
+	if (max_lanes)
+		*max_lanes = lanes;
+
+out:
+	free(info);
+
+	return mode;
+}
diff --git a/lib/i915/i915_dp.h b/lib/i915/i915_dp.h
index c818b3937..883ac346d 100644
--- a/lib/i915/i915_dp.h
+++ b/lib/i915/i915_dp.h
@@ -23,6 +23,27 @@ struct i915_dp_link_config {
 	int link_rate;
 };
 
+/**
+ * enum i915_dp_tc_mode:
+ * @I915_DP_TC_NONE: not a Type-C port, i.e. a combo or native PHY
+ * @I915_DP_TC_DISCONNECTED: Type-C port with nothing connected
+ * @I915_DP_TC_LEGACY: fixed DP connection on a Type-C port
+ * @I915_DP_TC_DP_ALT: USB-C DP alt mode, driven by the PHY PLL
+ * @I915_DP_TC_TBT_ALT: DP tunneled over USB4/Thunderbolt, driven by the
+ *			Thunderbolt PLL
+ *
+ * The connector mode of a DP output, as reported by the i915_display_info
+ * debugfs file. Only I915_DP_TC_TBT_ALT takes its link clock from the
+ * Thunderbolt PLL; every other value uses the PHY PLL.
+ */
+enum i915_dp_tc_mode {
+	I915_DP_TC_NONE,
+	I915_DP_TC_DISCONNECTED,
+	I915_DP_TC_LEGACY,
+	I915_DP_TC_DP_ALT,
+	I915_DP_TC_TBT_ALT,
+};
+
 /**
  * i915_dp_is_uhbr_rate:
  * @link_rate: DP link rate in 10 kbit/s units, as reported by the
@@ -58,5 +79,8 @@ int i915_dp_get_allowed_link_configs(int drm_fd, igt_output_t *output,
 				     struct i915_dp_link_config *configs,
 				     int max_configs);
 int i915_dp_get_next_lower_rate(int drm_fd, igt_output_t *output, int rate);
+enum i915_dp_tc_mode i915_dp_get_tc_mode(int drm_fd, igt_output_t *output,
+					 char *pin_assignment, int *max_lanes);
+const char *i915_dp_tc_mode_name(enum i915_dp_tc_mode mode);
 
 #endif
-- 
2.25.1


  parent reply	other threads:[~2026-09-16  4:34 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16  4:47 [PATCH i-g-t 00/13] Expand kms_dp_link_training coverage Kunal Joshi
2026-09-16  4:47 ` [PATCH i-g-t 01/13] lib/i915/i915_dp: Add helpers for the allowed link configs debugfs Kunal Joshi
2026-09-21  8:37   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 02/13] tests/intel/kms_dp_link_training: Use the UHBR helpers from lib Kunal Joshi
2026-09-21  8:38   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 03/13] tests/intel/kms_dp_link_training: Extract train_link_config() Kunal Joshi
2026-09-22 11:51   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 04/13] tests/intel/kms_dp_link_training: Check the config survived training Kunal Joshi
2026-09-22  5:25   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 05/13] tests/intel/kms_dp_link_training: Drive the smallest mode the sink offers Kunal Joshi
2026-09-22 11:59   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 06/13] tests/intel/kms_dp_link_training: Train every allowed link config Kunal Joshi
2026-09-22 13:51   ` S, Sowmiya
2026-09-16  4:47 ` Kunal Joshi [this message]
2026-09-22 14:55   ` [PATCH i-g-t 07/13] lib/i915/i915_dp: Add a Type-C port mode query S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 08/13] tests/intel/kms_dp_link_training: Log the DP link inventory in the fixture Kunal Joshi
2026-09-23 12:46   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 09/13] tests/intel/kms_dp_link_training: Group the outputs into links Kunal Joshi
2026-09-23 13:10   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 10/13] tests/intel/kms_dp_link_training: Add per connector mode subtests Kunal Joshi
2026-09-23 13:29   ` S, Sowmiya
2026-09-16  4:47 ` [PATCH i-g-t 11/13] lib/igt_dp: Add DPCD read helpers Kunal Joshi
2026-09-23 13:34   ` S, Sowmiya
2026-09-16  4:48 ` [PATCH i-g-t 12/13] lib/igt_dp: Add link status predicates for both channel codings Kunal Joshi
2026-09-23 13:55   ` S, Sowmiya
2026-09-16  4:48 ` [PATCH i-g-t 13/13] tests/intel/kms_dp_link_training: Verify the trained link from the sink side Kunal Joshi
2026-09-23 14:00   ` S, Sowmiya
2026-09-16  5:08 ` ✓ Xe.CI.BAT: success for Expand kms_dp_link_training coverage Patchwork
2026-09-16  5:25 ` ✓ i915.CI.BAT: " Patchwork
2026-09-16  6:15 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-09-16 11:59 ` ✗ i915.CI.Full: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260916044801.1279102-8-kunal1.joshi@intel.com \
    --to=kunal1.joshi@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox