From: Simon Ser <simon.ser@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: martin.peres@intel.com
Subject: [igt-dev] [PATCH i-g-t v2 9/9] lib/igt_chamelium: autodiscover Chamelium port mappings
Date: Wed, 19 Jun 2019 18:55:18 +0300 [thread overview]
Message-ID: <20190619155518.25129-10-simon.ser@intel.com> (raw)
In-Reply-To: <20190619155518.25129-1-simon.ser@intel.com>
This removes the need for configuring Chamelium ports in .igtrc, making it both
easier and less error-prone to setup Chamelium boards.
A new function chamelium_autodiscover sets a different EDID on each Chamelium
port and plugs them. We then walk the list of DRM connectors, read back the
EDID and infer the mapping.
The EDID serial number is used to tell each port apart. In case a mapping is
already configured in the .igtrc file, we check that it's consistent.
MST is not handled yet (requires refactoring existing tests since connector IDs
aren't stable).
Signed-off-by: Simon Ser <simon.ser@intel.com>
---
lib/igt_chamelium.c | 205 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 203 insertions(+), 2 deletions(-)
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index dcc59e9f0b04..ddea1ba47d4e 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -358,7 +358,7 @@ static xmlrpc_value *chamelium_rpc(struct chamelium *chamelium,
*/
void chamelium_plug(struct chamelium *chamelium, struct chamelium_port *port)
{
- igt_debug("Plugging %s\n", port->name);
+ igt_debug("Plugging %s (Chamelium port ID %d)\n", port->name, port->id);
xmlrpc_DECREF(chamelium_rpc(chamelium, NULL, "Plug", "(i)", port->id));
}
@@ -1828,6 +1828,204 @@ out:
return ret;
}
+/**
+ * autodiscover_ports: list of ports which can be auto-discovered
+ *
+ * See this file for a list of Chamelium ports:
+ * https://chromium.googlesource.com/chromiumos/platform/chameleon/+/master/chameleond/utils/ids.py
+ */
+static const int autodiscover_ports[] = {1, 2, 3, 4};
+
+#define AUTODISCOVER_PORTS_LEN (sizeof(autodiscover_ports) / sizeof(autodiscover_ports[0]))
+
+static int port_id_from_edid(int drm_fd, drmModeConnector *connector)
+{
+ int port_id = -1;
+ bool ok;
+ uint64_t edid_blob_id;
+ drmModePropertyBlobRes *edid_blob;
+ const struct edid *edid;
+ char mfg[3];
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ igt_debug("Skipping auto-discovery for connector %s-%d: "
+ "connector status is not connected\n",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id);
+ return -1;
+ }
+
+ ok = kmstest_get_property(drm_fd, connector->connector_id,
+ DRM_MODE_OBJECT_CONNECTOR, "EDID",
+ NULL, &edid_blob_id, NULL);
+ if (!ok) {
+ igt_debug("Skipping auto-discovery for connector %s-%d: "
+ "missing the EDID property\n",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id);
+ return -1;
+ }
+
+ edid_blob = drmModeGetPropertyBlob(drm_fd, edid_blob_id);
+ igt_assert(edid_blob);
+
+ edid = (const struct edid *) edid_blob->data;
+
+ edid_get_mfg(edid, mfg);
+ if (memcmp(mfg, "IGT", 3) != 0) {
+ igt_debug("Skipping connector %s-%d for auto-discovery: "
+ "manufacturer is %.3s, not IGT\n",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id, mfg);
+ goto out;
+ }
+
+ if (edid->prod_code[0] != 'C' || edid->prod_code[1] != 'H') {
+ igt_warn("Invalid EDID for IGT connector %s-%d: "
+ "invalid product code\n",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id);
+ goto out;
+ }
+
+ port_id = *(uint32_t *) &edid->serial;
+ igt_debug("Auto-discovery mapped connector %s-%d to Chamelium "
+ "port ID %d\n",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id, port_id);
+
+out:
+ drmModeFreePropertyBlob(edid_blob);
+ return port_id;
+}
+
+/**
+ * chamelium_autodiscover: TODO
+ */
+static bool chamelium_autodiscover(struct chamelium *chamelium, int drm_fd)
+{
+ drmModeRes *res;
+ drmModeConnector *connector;
+ struct chamelium_port *port;
+ size_t i, j, port_index;
+ int port_id;
+ uint32_t conn_id;
+ struct chamelium_edid *edid;
+ bool found;
+ uint32_t autodiscovered[AUTODISCOVER_PORTS_LEN] = {0};
+ char conn_name[64];
+
+ igt_debug("Starting Chamelium port auto-discovery\n");
+
+ edid = chamelium_new_edid(chamelium, igt_kms_get_base_edid());
+
+ /* Set EDID and plug ports we want to auto-discover */
+ port_index = chamelium->port_count;
+ for (i = 0; i < AUTODISCOVER_PORTS_LEN; i++) {
+ port_id = autodiscover_ports[i];
+
+ /* No need to auto-discover ports explicitly configured in the
+ * .igtrc file. */
+ found = false;
+ for (j = 0; j < chamelium->port_count; j++) {
+ if (chamelium->ports[j].id == port_id) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ igt_assert(port_index < CHAMELIUM_MAX_PORTS);
+ port = &chamelium->ports[port_index];
+ port_index++;
+
+ port->id = port_id;
+
+ chamelium_port_set_edid(chamelium, port, edid);
+ chamelium_plug(chamelium, port);
+ }
+
+ /* Reprobe connectors and build the mapping */
+ res = drmModeGetResources(drm_fd);
+ if (!res)
+ return false;
+
+ for (i = 0; i < res->count_connectors; i++) {
+ conn_id = res->connectors[i];
+
+ /* Read the EDID and parse the Chamelium port ID we stored
+ * there. */
+ connector = drmModeGetConnector(drm_fd, res->connectors[i]);
+ port_id = port_id_from_edid(drm_fd, connector);
+ drmModeFreeConnector(connector);
+ if (port_id < 0)
+ continue;
+
+ /* If we already have a mapping from the config file, check
+ * that it's consistent. */
+ found = false;
+ for (j = 0; j < chamelium->port_count; j++) {
+ port = &chamelium->ports[j];
+ if (port->connector_id == conn_id) {
+ found = true;
+ igt_assert_f(port->id == port_id,
+ "Inconsistency detected in .igtrc: "
+ "connector %s is configured with "
+ "Chamelium port %d, but is "
+ "connected to port %d\n",
+ port->name, port->id, port_id);
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ /* Get got a new mapping */
+ found = false;
+ for (j = 0; j < AUTODISCOVER_PORTS_LEN; j++) {
+ if (port_id == autodiscover_ports[j]) {
+ found = true;
+ autodiscovered[j] = conn_id;
+ break;
+ }
+ }
+ igt_assert_f(found, "Auto-discovered a port (%d) we haven't "
+ "setup\n", port_id);
+ }
+
+ drmModeFreeResources(res);
+
+ /* We now have a Chamelium port ID ↔ DRM connector ID mapping:
+ * autodiscover_ports contains the Chamelium port IDs and
+ * autodiscovered contains the DRM connector IDs. */
+ for (i = 0; i < AUTODISCOVER_PORTS_LEN; i++) {
+ port_id = autodiscover_ports[i];
+ conn_id = autodiscovered[i];
+ if (!conn_id) {
+ continue;
+ }
+
+ port = &chamelium->ports[chamelium->port_count];
+ chamelium->port_count++;
+
+ port->id = port_id;
+ port->type = chamelium_get_port_type(chamelium, port);
+ port->connector_id = conn_id;
+
+ connector = drmModeGetConnectorCurrent(drm_fd, conn_id);
+ snprintf(conn_name, sizeof(conn_name), "%s-%u",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id);
+ drmModeFreeConnector(connector);
+ port->name = strdup(conn_name);
+ }
+
+ chamelium_reset(chamelium);
+
+ return true;
+}
+
static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd)
{
GError *error = NULL;
@@ -1845,7 +2043,10 @@ static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd)
return false;
}
- return chamelium_read_port_mappings(chamelium, drm_fd);
+ if (!chamelium_read_port_mappings(chamelium, drm_fd)) {
+ return false;
+ }
+ return chamelium_autodiscover(chamelium, drm_fd);
}
/**
--
2.22.0
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev
next prev parent reply other threads:[~2019-06-19 15:55 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-19 15:55 [igt-dev] [PATCH i-g-t v2 0/9] Chamelium port mapping auto-discovery Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 1/9] lib/igt_edid: add edid_get_size Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 2/9] lib/igt_chamelium: fix chamelium_port_set_edid docs Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 3/9] lib/igt_chamelium: allow EDIDs to be mutated for each port Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 4/9] lib/igt_chamelium: split chmelium_new_edid Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 5/9] lib/igt_chamelium: add CHAMELIUM_MAX_PORTS Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 6/9] lib/igt_chamelium: upload one EDID per port Simon Ser
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 7/9] lib/igt_chamelium: set EDID serial Simon Ser
2019-06-24 12:16 ` Arkadiusz Hiler
2019-06-25 8:06 ` Ser, Simon
2019-06-19 15:55 ` [igt-dev] [PATCH i-g-t v2 8/9] lib/igt_edid: add edid_get_mfg Simon Ser
2019-06-19 15:55 ` Simon Ser [this message]
2019-06-20 8:40 ` [igt-dev] [PATCH i-g-t v3] lib/igt_chamelium: autodiscover Chamelium port mappings Simon Ser
2019-06-24 13:22 ` [igt-dev] [PATCH i-g-t v2 9/9] " Arkadiusz Hiler
2019-06-24 14:15 ` Ser, Simon
2019-06-25 7:03 ` Arkadiusz Hiler
2019-06-25 7:23 ` Ser, Simon
2019-06-19 17:38 ` [igt-dev] ✗ Fi.CI.BAT: failure for Chamelium port mapping auto-discovery Patchwork
2019-06-20 10:53 ` [igt-dev] ✓ Fi.CI.BAT: success for Chamelium port mapping auto-discovery (rev2) Patchwork
2019-06-24 8:58 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
2019-06-24 9:32 ` Ser, Simon
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=20190619155518.25129-10-simon.ser@intel.com \
--to=simon.ser@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=martin.peres@intel.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