Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Tom Chung <chiahsuan.chung@amd.com>
To: <igt-dev@lists.freedesktop.org>
Cc: <Rodrigo.Siqueira@amd.com>, <alex.hung@amd.com>,
	<sunpeng.li@amd.com>, <chiahsuan.chung@amd.com>
Subject: [PATCH i-g-t] tests/amdgpu/amd_vrr_range: Fix panel cannot light up after test
Date: Thu, 2 Jan 2025 18:37:26 +0800	[thread overview]
Message-ID: <20250102103741.2105-1-chiahsuan.chung@amd.com> (raw)

[Why]
If the sink side support VRR, override the EDID may cause sink
side cannot light up.

[How]
Just parsing the VRR range from sink side EDID without override it
if the sink side support VRR.

Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
---
 tests/amdgpu/amd_vrr_range.c | 125 ++++++++++++++++++++++++++++-------
 1 file changed, 102 insertions(+), 23 deletions(-)

diff --git a/tests/amdgpu/amd_vrr_range.c b/tests/amdgpu/amd_vrr_range.c
index 79db6f9c4..15bebbfa7 100644
--- a/tests/amdgpu/amd_vrr_range.c
+++ b/tests/amdgpu/amd_vrr_range.c
@@ -29,20 +29,23 @@ IGT_TEST_DESCRIPTION("Test EDID parsing and debugfs reporting on Freesync displa
 
 /* Maximumm pipes on any AMD ASIC. */
 #define MAX_PIPES 6
+#define EDID_SIZE 256
+#define EDID_PATH "/sys/class/drm/card0-%s/edid"
 
 /* Common test data. */
+struct vrr_range {
+	unsigned int min;
+	unsigned int max;
+};
+
 typedef struct data {
 	igt_display_t display;
 	igt_plane_t *primary;
 	igt_output_t *output[MAX_PIPES];
 	int fd;
+	struct vrr_range expected_range;
 } data_t;
 
-typedef struct range {
-	unsigned int min;
-	unsigned int max;
-} range_t;
-
 /* Test flags. */
 enum {
 	TEST_NONE = 1 << 0,
@@ -53,7 +56,7 @@ struct {
 	const char *name;
 	uint32_t connector_type;
 	const unsigned char edid[256];
-	const range_t range;
+	const struct vrr_range range;
 } edid_database[] = {
 	{
 		/* EDID Version 1.4. Timing requires 2 DP lanes. */
@@ -212,12 +215,12 @@ static int find_test_edid_index(uint32_t connector_type)
 }
 
 /* Returns the min and max vrr range from the connector debugfs. */
-static range_t get_freesync_range(data_t *data, igt_output_t *output)
+static struct vrr_range get_freesync_range(data_t *data, igt_output_t *output)
 {
 	char buf[256];
 	char *start_loc;
 	int fd, res;
-	range_t range;
+	struct vrr_range range;
 
 	fd = igt_debugfs_connector_dir(data->fd, output->name, O_RDONLY);
 	igt_assert(fd >= 0);
@@ -249,13 +252,84 @@ static void trigger_edid_parse(data_t *data, igt_output_t *output, uint32_t test
 	usleep(1500000);
 }
 
+/* Returns true if an output supports VRR. */
+static bool has_vrr(igt_output_t *output)
+{
+	return igt_output_has_prop(output, IGT_CONNECTOR_VRR_CAPABLE) &&
+	       igt_output_get_prop(output, IGT_CONNECTOR_VRR_CAPABLE);
+}
+
+static void parse_vrr_gange_from_edid(data_t *data, uint8_t *edid, int index)
+{
+	bool max_rate_offset = false;
+	bool min_rate_offset = false;
+
+	/* Check Bytes 4 Vertical rate offsets
+	 * Vertical rate offsets:
+	 * 00 = none;
+	 * 10 = +255 Hz for max. rate;
+	 * 11 = +255 Hz for max. and min. rates.
+	 */
+	if ((edid[index + 4] & 0b10) == 0b10)
+		max_rate_offset = true;
+	else if ((edid[index + 4] & 0b11) == 0b11) {
+		max_rate_offset = true;
+		min_rate_offset = true;
+	}
+
+	/* Bytes 5 Min vertical field rate (1–255 Hz; 256–510 Hz, if offset).*/
+	data->expected_range.min =
+		min_rate_offset ? edid[index + 5] + 255 : edid[index + 5];
+	/* Bytes 6 Max vertical field rate (1–255 Hz; 256–510 Hz, if offset).*/
+	data->expected_range.max =
+		max_rate_offset ? edid[index + 6] + 255 : edid[index + 6];
+}
+
+static bool find_vrr_range_from_edid(data_t *data, igt_output_t *output)
+{
+	char edid_path[PATH_MAX] = "\0";
+	uint8_t sink_edid[EDID_SIZE] = "\0";
+	const uint8_t range_limits_head[4] = {0x00, 0x00, 0x00, 0xFD};
+	const unsigned int range_head_size = sizeof(range_limits_head);
+	int fd, i, read_size, index = 0;
+
+	/* Get EDID */
+	igt_assert(snprintf(edid_path, PATH_MAX, EDID_PATH,
+			   output->name) < PATH_MAX);
+
+	fd = open(edid_path, O_RDONLY);
+	if (fd == -1)
+		return false;
+
+	read_size = read(fd, sink_edid, EDID_SIZE);
+	close(fd);
+	if (read_size < 0)
+		return false;
+
+	/* Find Display Range Limits Descriptor block */
+	while (index < EDID_SIZE - range_head_size) {
+		for (i = 0; i < range_head_size; i++) {
+			if (sink_edid[index+i] != range_limits_head[i])
+				break;
+			else if (i == range_head_size-1) {
+				/* Found Display Range Limits Descriptor block */
+				parse_vrr_gange_from_edid(data, sink_edid, index);
+				return true;
+			}
+		}
+		index++;
+	}
+
+	return false;
+}
+
 /* Check if EDID parsing is correctly reporting Freesync capability
  * by overriding EDID with ones from golden sample.
  */
 static void test_freesync_parsing_base(data_t *data, uint32_t test_flags)
 {
 	const struct edid *edid;
-	range_t range, expected_range;
+	struct vrr_range range, expected_range;
 	igt_output_t *output;
 	int j, test_conn_cnt = 0;
 	igt_display_t *display = &data->display;
@@ -277,15 +351,27 @@ static void test_freesync_parsing_base(data_t *data, uint32_t test_flags)
 		if (output->config.connector->connector_type == DRM_MODE_CONNECTOR_eDP)
 			igt_amd_allow_edp_hotplug_detect(data->fd, output->name, true);
 
-		/* force to use hard coded VRR EDID */
-		kmstest_force_edid(data->fd, output->config.connector, edid);
+		if (has_vrr(output)) {
+			/* A VRR sink, just parsing range from EDID directly */
+			trigger_edid_parse(data, output, test_flags);
 
-		trigger_edid_parse(data, output, test_flags);
+			igt_assert_f(find_vrr_range_from_edid(data, output),
+				"Cannot parsing VRR range from EDID\n");
 
-		range = get_freesync_range(data, output);
+			expected_range.min = data->expected_range.min;
+			expected_range.max = data->expected_range.max;
+			range = get_freesync_range(data, output);
+		} else {
+			/* force to use hard coded VRR EDID */
+			kmstest_force_edid(data->fd, output->config.connector, edid);
 
-		/* undo EDID override. re-parse EDID of display */
-		kmstest_force_edid(data->fd, output->config.connector, NULL);
+			trigger_edid_parse(data, output, test_flags);
+
+			range = get_freesync_range(data, output);
+
+			/* undo EDID override. re-parse EDID of display */
+			kmstest_force_edid(data->fd, output->config.connector, NULL);
+		}
 
 		igt_amd_trigger_hotplug(data->fd, output->name);
 
@@ -317,20 +403,13 @@ static inline void test_freesync_parsing_suspend(data_t *data)
 	test_freesync_parsing_base(data, TEST_SUSPEND);
 }
 
-/* Returns true if an output supports VRR. */
-static bool has_vrr(igt_output_t *output)
-{
-	return igt_output_has_prop(output, IGT_CONNECTOR_VRR_CAPABLE) &&
-	       igt_output_get_prop(output, IGT_CONNECTOR_VRR_CAPABLE);
-}
-
 /* More relaxed checking on Freesync capability.
  * Only checks if frame rate range is within legal range.
  * Display under test MUST be VRR capable.
  */
 static void test_freesync_range_base(data_t *data, uint32_t test_flags)
 {
-	range_t range;
+	struct vrr_range range;
 	igt_output_t *output;
 	int test_conn_cnt = 0;
 	igt_display_t *display = &data->display;
-- 
2.43.0


             reply	other threads:[~2025-01-02 10:38 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-02 10:37 Tom Chung [this message]
2025-01-02 11:51 ` ✓ Xe.CI.BAT: success for tests/amdgpu/amd_vrr_range: Fix panel cannot light up after test Patchwork
2025-01-02 13:54 ` ✗ Xe.CI.Full: failure " 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=20250102103741.2105-1-chiahsuan.chung@amd.com \
    --to=chiahsuan.chung@amd.com \
    --cc=Rodrigo.Siqueira@amd.com \
    --cc=alex.hung@amd.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=sunpeng.li@amd.com \
    /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