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 12/13] lib/igt_dp: Add link status predicates for both channel codings
Date: Wed, 16 Sep 2026 10:18:00 +0530 [thread overview]
Message-ID: <20260916044801.1279102-13-kunal1.joshi@intel.com> (raw)
In-Reply-To: <20260916044801.1279102-1-kunal1.joshi@intel.com>
A link that is up has, for every lane in use, clock recovery done,
channel equalisation done and symbols locked, plus interlane alignment
done for the link as a whole. 128b/132b reports that differently from
8b/10b: there is no clock recovery phase and so no CR_DONE bit, and a
training failure has its own bit in DP_LANE_ALIGN_STATUS_UPDATED.
Add igt_dp_link_status_ok() covering both, mirroring
drm_dp_channel_eq_ok() and the drm_dp_128b132b_* predicates in
drm_dp_helper.c, so a caller does not have to know which set of bits
applies to the rate it forced.
Add igt_dp_channel_coding_ok() next to it, reading
MAIN_LINK_CHANNEL_CODING_SET, so that the DPCD offsets stay inside the
library and a test can ask the two questions it cares about without
handling raw registers.
Both return 1, 0 or a negative error code, so that a caller can tell a
sink which disagrees apart from a DPCD it could not read at all. That
matters because the AUX character device is not always there.
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
lib/igt_dp.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/igt_dp.h | 4 ++
2 files changed, 107 insertions(+)
diff --git a/lib/igt_dp.c b/lib/igt_dp.c
index 0b1fe73de..a7d9f1e77 100644
--- a/lib/igt_dp.c
+++ b/lib/igt_dp.c
@@ -281,3 +281,106 @@ int igt_dp_dpcd_read_byte(int aux_fd, unsigned int offset, uint8_t *val)
return ret == 1 ? 0 : -EIO;
}
+
+/*
+ * DPCD registers and bits used by the sink side link checks, mirroring the
+ * kernel's include/drm/display/drm_dp.h.
+ */
+#define DPCD_MAIN_LINK_CHANNEL_CODING_SET 0x108
+#define DPCD_SET_ANSI_8B10B (1 << 0)
+#define DPCD_SET_ANSI_128B132B (1 << 1)
+
+#define DPCD_LANE0_1_STATUS 0x202
+#define DPCD_LINK_STATUS_SIZE 6
+#define DPCD_LANE_CR_DONE (1 << 0)
+#define DPCD_LANE_CHANNEL_EQ_DONE (1 << 1)
+#define DPCD_LANE_SYMBOL_LOCKED (1 << 2)
+
+/* DP_LANE_ALIGN_STATUS_UPDATED, the third byte of the status block. */
+#define DPCD_INTERLANE_ALIGN_DONE (1 << 0)
+#define DPCD_128B132B_LT_FAILED (1 << 4)
+
+static uint8_t dpcd_lane_status(const uint8_t link_status[DPCD_LINK_STATUS_SIZE],
+ int lane)
+{
+ return (link_status[lane / 2] >> (4 * (lane % 2))) & 0xf;
+}
+
+/**
+ * igt_dp_channel_coding_ok: Check the channel coding the sink was told to use
+ * @aux_fd: AUX channel device file descriptor from igt_dp_aux_open()
+ * @uhbr: Whether 128b/132b is expected
+ *
+ * Read MAIN_LINK_CHANNEL_CODING_SET and check that it selects the encoding the
+ * link rate implies. This is the only direct evidence that the coding a UHBR
+ * rate implies is the coding that reached the wire.
+ *
+ * Returns:
+ * 1 when the expected coding is selected, 0 when it is not, or a negative
+ * error code when the DPCD could not be read.
+ */
+int igt_dp_channel_coding_ok(int aux_fd, bool uhbr)
+{
+ uint8_t coding;
+ int ret;
+
+ ret = igt_dp_dpcd_read_byte(aux_fd, DPCD_MAIN_LINK_CHANNEL_CODING_SET,
+ &coding);
+ if (ret < 0)
+ return ret;
+
+ return !!(coding & (uhbr ? DPCD_SET_ANSI_128B132B : DPCD_SET_ANSI_8B10B));
+}
+
+/**
+ * igt_dp_link_status_ok: Check the sink considers the link trained
+ * @aux_fd: AUX channel device file descriptor from igt_dp_aux_open()
+ * @lane_count: Number of lanes in use
+ * @uhbr: Whether the link runs at a UHBR rate, i.e. uses 128b/132b
+ *
+ * Read the link status block at DP_LANE0_1_STATUS and check that every lane in
+ * use is locked and the lanes are aligned.
+ *
+ * 128b/132b reports this differently from 8b/10b: there is no clock recovery
+ * bit, and a training failure has its own bit in
+ * DP_LANE_ALIGN_STATUS_UPDATED. Mirrors drm_dp_channel_eq_ok() and the
+ * drm_dp_128b132b_* predicates.
+ *
+ * Returns:
+ * 1 when the sink considers the link trained, 0 when it does not, or a
+ * negative error code when the DPCD could not be read.
+ */
+int igt_dp_link_status_ok(int aux_fd, int lane_count, bool uhbr)
+{
+ uint8_t link_status[DPCD_LINK_STATUS_SIZE];
+ uint8_t lane_mask;
+ uint8_t align;
+ int ret;
+ int lane;
+
+ ret = igt_dp_dpcd_read(aux_fd, DPCD_LANE0_1_STATUS, link_status,
+ sizeof(link_status));
+ if (ret < 0)
+ return ret;
+ if (ret != sizeof(link_status))
+ return -EIO;
+
+ align = link_status[2];
+
+ if (uhbr && (align & DPCD_128B132B_LT_FAILED))
+ return 0;
+
+ if (!(align & DPCD_INTERLANE_ALIGN_DONE))
+ return 0;
+
+ /* 128b/132b has no clock recovery phase, so no CR_DONE bit. */
+ lane_mask = DPCD_LANE_CHANNEL_EQ_DONE | DPCD_LANE_SYMBOL_LOCKED;
+ if (!uhbr)
+ lane_mask |= DPCD_LANE_CR_DONE;
+
+ for (lane = 0; lane < lane_count; lane++)
+ if ((dpcd_lane_status(link_status, lane) & lane_mask) != lane_mask)
+ return 0;
+
+ return 1;
+}
diff --git a/lib/igt_dp.h b/lib/igt_dp.h
index 44f3b11a1..332656aae 100644
--- a/lib/igt_dp.h
+++ b/lib/igt_dp.h
@@ -36,4 +36,8 @@ int igt_dp_dpcd_read(int aux_fd, unsigned int offset, void *buf, size_t size);
int igt_dp_dpcd_read_byte(int aux_fd, unsigned int offset, uint8_t *val);
+int igt_dp_channel_coding_ok(int aux_fd, bool uhbr);
+
+int igt_dp_link_status_ok(int aux_fd, int lane_count, bool uhbr);
+
#endif
--
2.25.1
next prev parent reply other threads:[~2026-09-16 4:36 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 ` [PATCH i-g-t 07/13] lib/i915/i915_dp: Add a Type-C port mode query Kunal Joshi
2026-09-22 14:55 ` 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 ` Kunal Joshi [this message]
2026-09-23 13:55 ` [PATCH i-g-t 12/13] lib/igt_dp: Add link status predicates for both channel codings 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-13-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.