From: Louis Chauvet <louis.chauvet@bootlin.com>
To: igt-dev@lists.freedesktop.org
Cc: thomas.petazzoni@bootlin.com, luca.ceresoli@bootlin.com,
kory.maincent@bootlin.com, markyacoub@google.com,
khaled.almahallawy@intel.com,
Louis Chauvet <louis.chauvet@bootlin.com>
Subject: [PATCH i-g-t v9 20/49] lib/unigraf: Initial Unigraf support
Date: Mon, 16 Mar 2026 17:17:41 +0100 [thread overview]
Message-ID: <20260316-unigraf-integration-v9-20-a01dffc3b0cb@bootlin.com> (raw)
In-Reply-To: <20260316-unigraf-integration-v9-0-a01dffc3b0cb@bootlin.com>
This introduce the basic boilerplate to connect to a unigraf device.
This integration currently only supports one device opened to simplify
its usage and cleanup.
The functions unigraf_open_device and unigraf_require_device will register
a handler to do proper cleanup on IGT exit.
Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
lib/meson.build | 10 +++++
lib/unigraf/unigraf.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/unigraf/unigraf.h | 43 ++++++++++++++++++
meson.build | 14 ++++++
4 files changed, 187 insertions(+)
diff --git a/lib/meson.build b/lib/meson.build
index cd03e8f634e4..268f3238cbfa 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -151,6 +151,13 @@ lib_deps = [
zlib
]
+if libtsi.found()
+ lib_deps += libtsi
+ lib_sources += [
+ 'unigraf/unigraf.c'
+ ]
+endif
+
if libdrm_nouveau.found()
lib_deps += libdrm_nouveau
lib_sources += [
@@ -232,6 +239,9 @@ endif
if chamelium.found()
lib_deps += chamelium
lib_sources += [ 'igt_chamelium.c', 'igt_chamelium_stream.c' ]
+endif
+
+if chamelium.found() or libtsi.found()
lib_sources += 'monitor_edids/monitor_edids_helper.c'
endif
diff --git a/lib/unigraf/unigraf.c b/lib/unigraf/unigraf.c
new file mode 100644
index 000000000000..df18ab178e16
--- /dev/null
+++ b/lib/unigraf/unigraf.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Google
+ *
+ * Authors:
+ * Louis Chauvet <louis.chauvet@bootlin.com>
+ */
+
+#include "igt_core.h"
+#include <stdint.h>
+
+#include "unigraf.h"
+#include "TSI.h"
+#include "TSI_types.h"
+
+#define unigraf_debug(fmt, ...) igt_debug("TSI:%p: " fmt, unigraf_device, ##__VA_ARGS__)
+
+static TSI_HANDLE unigraf_device;
+static char *unigraf_default_edid;
+static char *unigraf_connector_name;
+
+static void unigraf_close_device(void)
+{
+ if (!unigraf_device)
+ return;
+
+ unigraf_debug("Closing...\n");
+ unigraf_assert(TSIX_DEV_CloseDevice(unigraf_device));
+ TSI_Clean();
+ unigraf_device = NULL;
+ free(unigraf_default_edid);
+ free(unigraf_connector_name);
+}
+
+/**
+ * unigraf_exit_handler - Handle the exit signal and clean up unigraf resources.
+ * @sig: The signal number received.
+ *
+ * This function is called when the program receives an exit signal. It ensures
+ * that all unigraf resources are properly cleaned up by calling unigraf_deinit
+ * for each open instance.
+ */
+static void unigraf_exit_handler(int sig)
+{
+ unigraf_close_device();
+}
+
+static void unigraf_init(void)
+{
+ int ret;
+
+ unigraf_debug("Initialize unigraf...\n");
+ ret = TSI_Init(TSI_CURRENT_VERSION);
+ unigraf_assert(ret);
+ igt_install_exit_handler(unigraf_exit_handler);
+}
+
+/**
+ * unigraf_device_count() - Return the number of scanned devices
+ *
+ * Must be called after a unigraf_rescan_devices().
+ */
+static unsigned int unigraf_device_count(void)
+{
+ return unigraf_assert(TSIX_DEV_GetDeviceCount());
+}
+
+/**
+ * unigraf_open_device() - Search and open a device.
+ * @drm_fd: File descriptor of the currently used drm device
+ *
+ * Returns: true if a device was found and initialized, otherwise false.
+ *
+ * This function searches for a compatible device and opens it.
+ */
+bool unigraf_open_device(int drm_fd)
+{
+ TSI_RESULT r;
+ int device_count;
+ int chosen_device = 0;
+ int chosen_role = 0;
+ int chosen_input = 0;
+
+ assert(igt_can_fail());
+
+ if (unigraf_device)
+ return true;
+
+ unigraf_init();
+
+ unigraf_assert(TSIX_DEV_RescanDevices(0, TSI_DEVCAP_VIDEO_CAPTURE, 0));
+
+ device_count = unigraf_device_count();
+ if (device_count < 1) {
+ unigraf_debug("No device found.\n");
+ return false;
+ }
+
+ unigraf_device = TSIX_DEV_OpenDevice(chosen_device, &r);
+ unigraf_assert(r);
+ igt_assert(unigraf_device);
+ unigraf_debug("Successfully opened the unigraf device %d.\n", chosen_device);
+
+ unigraf_assert(TSIX_DEV_SelectRole(unigraf_device, chosen_role));
+ unigraf_assert(TSIX_VIN_Select(unigraf_device, chosen_input));
+ unigraf_assert(TSIX_VIN_Enable(unigraf_device, chosen_input));
+
+ return true;
+}
+
+/**
+ * unigraf_require_device() - Search and open a device.
+ * @drm_fd: File descriptor of the currently used drm device
+ *
+ * This is a shorthand to reduce test boilerplate when a unigraf device must be present.
+ */
+void unigraf_require_device(int drm_fd)
+{
+ igt_require(unigraf_open_device(drm_fd));
+}
diff --git a/lib/unigraf/unigraf.h b/lib/unigraf/unigraf.h
new file mode 100644
index 000000000000..c08ce62894c5
--- /dev/null
+++ b/lib/unigraf/unigraf.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Google
+ *
+ * Authors:
+ * Louis Chauvet <louis.chauvet@bootlin.com>
+ */
+
+#ifndef UNIGRAF_H
+#define UNIGRAF_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * unigraf_assert: Helper macro to assert a TSI return value and retrieve a detailed error message.
+ * @result: libTSI return value to check
+ *
+ * This macro checks the return value of a libTSI function call. If the return value indicates an
+ * error, it retrieves a detailed error message and asserts with that message.
+ * If retrieving the error description fails, it asserts with a generic error message.
+ */
+#define unigraf_assert(result) \
+({ \
+ char msg[256]; \
+ TSI_RESULT __r = (result); \
+ if (__r < TSI_SUCCESS) { \
+ TSI_RESULT __r2 = TSI_MISC_GetErrorDescription(__r, msg, sizeof(msg)); \
+ if (__r2 < TSI_SUCCESS) \
+ igt_assert_f(false, \
+ "unigraf error: %d (get error description failed: %d)\n", \
+ __r, __r2); \
+ else \
+ igt_assert_f(false, "unigraf error: %d (%s)\n", __r, msg); \
+ } \
+ (__r); \
+})
+
+bool unigraf_open_device(int drm_fd);
+
+void unigraf_require_device(int drm_fd);
+
+#endif // UNIGRAF_H
diff --git a/meson.build b/meson.build
index 57849648a377..127abbf62024 100644
--- a/meson.build
+++ b/meson.build
@@ -166,6 +166,12 @@ libpci = dependency('libpci', required : true)
libudev = dependency('libudev', required : true)
glib = dependency('glib-2.0', required : true)
+libtsi = cc.find_library('TSI', required : false)
+
+if libtsi.found()
+ config.set('HAVE_UNIGRAF', 1)
+endif
+
xmlrpc = dependency('xmlrpc', required : false)
xmlrpc_util = dependency('xmlrpc_util', required : false)
xmlrpc_client = dependency('xmlrpc_client', required : false)
@@ -290,6 +296,7 @@ amdgpudir = join_paths(libexecdir, 'amdgpu')
msmdir = join_paths(libexecdir, 'msm')
panfrostdir = join_paths(libexecdir, 'panfrost')
panthordir = join_paths(libexecdir, 'panthor')
+unigrafdir = join_paths(libexecdir, 'unigraf')
v3ddir = join_paths(libexecdir, 'v3d')
vc4dir = join_paths(libexecdir, 'vc4')
vkmsdir = join_paths(libexecdir, 'vkms')
@@ -372,6 +379,12 @@ if get_option('use_rpath')
vmwgfx_rpathdir = join_paths(vmwgfx_rpathdir, '..')
endforeach
vmwgfx_rpathdir = join_paths(vmwgfx_rpathdir, libdir)
+
+ unigraf_rpathdir = '$ORIGIN'
+ foreach p : unigrafdir.split('/')
+ unigraf_rpathdir = join_paths(unigraf_rpathdir, '..')
+ endforeach
+ unigraf_rpathdir = join_paths(unigraf_rpathdir, libdir)
else
bindir_rpathdir = ''
libexecdir_rpathdir = ''
@@ -383,6 +396,7 @@ else
vc4_rpathdir = ''
vkms_rpathdir = ''
vmwgfx_rpathdir = ''
+ unigraf_rpathdir = ''
endif
build_testplan = get_option('testplan')
--
2.52.0
next prev parent reply other threads:[~2026-03-16 16:25 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-16 16:17 [PATCH i-g-t v9 00/49] Unigraf integration Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 01/49] lib/igt_kms: Add a detect timeout value Louis Chauvet
2026-03-16 18:50 ` Kamil Konieczny
2026-03-16 16:17 ` [PATCH i-g-t v9 02/49] lib/igt_kms: Add helper to wait for a specific status on a connector Louis Chauvet
2026-03-24 10:22 ` Kamil Konieczny
2026-03-16 16:17 ` [PATCH i-g-t v9 03/49] lib/igt_kms: Add function to list connected connectors Louis Chauvet
2026-03-24 10:34 ` Kamil Konieczny
2026-03-24 13:56 ` Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 04/49] lib/igt_kms: Add helper to obtain a connector by its name or MST path Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 05/49] lib/igt_kms: Add helper to wait for new connectors Louis Chauvet
2026-03-17 14:56 ` Kory Maincent
2026-03-23 14:40 ` Louis Chauvet
2026-03-24 10:11 ` Kamil Konieczny
2026-03-16 16:17 ` [PATCH i-g-t v9 06/49] lib/tests: Add tests for array manipulations Louis Chauvet
2026-03-17 15:00 ` Kory Maincent
2026-03-16 16:17 ` [PATCH i-g-t v9 07/49] lib/igt_kms: Add helper to get a pipe from a connector Louis Chauvet
2026-03-24 7:58 ` Jani Nikula
2026-03-24 10:02 ` Kamil Konieczny
2026-03-16 16:17 ` [PATCH i-g-t v9 08/49] lib/igt_kms: Expose dump_connector_attrs Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 09/49] lib/igt_kms: Expose reset_connectors_at_exit Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 10/49] lib/igt_kms: Expose connector_attr_set and igt_connector_attr_set Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 11/49] lib/igt_debugfs: Move debugfs helpers to the proper location Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 12/49] lib/igt_debugfs: Add const when make sense Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 13/49] lib/igt_amd: " Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 14/49] lib/igt_kms: " Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 15/49] lib/monitor_edids: Add helper functions for using monitor_edid objects Louis Chauvet
2026-03-17 15:09 ` Kory Maincent
2026-03-24 10:15 ` Kamil Konieczny
2026-03-24 14:09 ` Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 16/49] lib/monitor_edids: Add helper to get an EDID by its name Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 17/49] lib/monitor_edids: Add helper to print all available EDID names Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 18/49] lib/unigraf: Add used defines for TSI_Types Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 19/49] lib/unigraf: Add TSI.h Louis Chauvet
2026-03-16 16:17 ` Louis Chauvet [this message]
2026-03-24 8:19 ` [PATCH i-g-t v9 20/49] lib/unigraf: Initial Unigraf support Naladala, Ramanaidu
2026-03-24 9:37 ` Louis Chauvet
2026-03-26 9:59 ` Louis Chauvet
2026-03-24 9:58 ` Kamil Konieczny
2026-03-16 16:17 ` [PATCH i-g-t v9 21/49] lib/igt_kms: Automatically connect unigraf on display require Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 22/49] lib/unigraf: Introduce device configuration Louis Chauvet
2026-03-17 15:16 ` Kory Maincent
2026-03-16 16:17 ` [PATCH i-g-t v9 23/49] lib/unigraf: Introduce role configuration Louis Chauvet
2026-03-17 15:19 ` Kory Maincent
2026-03-16 16:17 ` [PATCH i-g-t v9 24/49] lib/unigraf: Introduce input configuration Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 25/49] lib/unigraf: Add reset function Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 26/49] lib/unigraf: Add unigraf assert and deassert helpers Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 27/49] lib/unigraf: Add plug/unplug helpers Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 28/49] lib/unigraf: Allows sst/mst configuration Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 29/49] lib/unigraf: Add helpers to read and write edid Louis Chauvet
2026-03-17 15:32 ` Kory Maincent
2026-03-23 14:46 ` Louis Chauvet
2026-03-23 16:26 ` Kamil Konieczny
2026-03-23 17:34 ` Louis Chauvet
2026-03-24 9:35 ` Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 30/49] lib/unigraf: Add connector and EDID configuration Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 31/49] tests/unigraf: Add basic unigraf tests Louis Chauvet
2026-03-17 15:46 ` Kory Maincent
2026-03-23 14:49 ` Louis Chauvet
2026-03-24 19:25 ` Naladala, Ramanaidu
2026-03-16 16:17 ` [PATCH i-g-t v9 32/49] lib/unigraf: Add unigraf CRC capture Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 33/49] lib/unigraf: Add configuration for CRC usage Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 34/49] lib/unigraf: add unigraf_get_connector_by_stream Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 35/49] lib/unigraf: Add helper to check timings received by unigraf Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 36/49] lib/igt_pipe_crc: Add unigraf crc calculation Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 37/49] lib/i915/dp: Move DP-related function for i915 to proper folder Louis Chauvet
2026-03-16 16:17 ` [PATCH i-g-t v9 38/49] lib/i915/dp: Rename functions to avoid confusion Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 39/49] lib/i915/dp: Add helper to get maximum supported rate Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 40/49] lib/i915/dp: Properly check sscanf results Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 41/49] lib/i915/dp: Use igt_output_name instead of private field Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 42/49] lib/igt_dp: Create generic helpers for DP information Louis Chauvet
2026-03-17 15:55 ` Kory Maincent
2026-03-23 14:52 ` Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 43/49] lib/igt_kms: Add asserts to avoid null pointer dereference Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 44/49] lib/igt_kms: Add helper to get a CRTC from an output Louis Chauvet
2026-03-17 15:56 ` Kory Maincent
2026-03-16 16:18 ` [PATCH i-g-t v9 45/49] lib/unigraf: Add lane count configuration Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 46/49] docs/unigraf: Add unigraf documentation Louis Chauvet
2026-03-17 15:58 ` Kory Maincent
2026-03-24 8:07 ` Naladala, Ramanaidu
2026-03-16 16:18 ` [PATCH i-g-t v9 47/49] lib/unigraf: Add helpers to set maximum link rate Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 48/49] lib/unigraf: Add helpers to get the current LT status Louis Chauvet
2026-03-16 16:18 ` [PATCH i-g-t v9 49/49] tests/unigraf/unigraf_lt: Add test for link training Louis Chauvet
2026-03-17 12:02 ` ✗ Fi.CI.BUILD: failure for Unigraf integration (rev8) 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=20260316-unigraf-integration-v9-20-a01dffc3b0cb@bootlin.com \
--to=louis.chauvet@bootlin.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=khaled.almahallawy@intel.com \
--cc=kory.maincent@bootlin.com \
--cc=luca.ceresoli@bootlin.com \
--cc=markyacoub@google.com \
--cc=thomas.petazzoni@bootlin.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