[i-g-t V3 1/4] lib/igt_kms: Add infra to handle crtc arbitrary attributes
Bhanuprakash Modem
bhanuprakash.modem at intel.com
Mon Nov 18 09:59:45 UTC 2024
We may want to poke at various other crtc attributes
via sysfs/debugfs. Add a mechamisn to handle crtc
arbitrary attributes.
V2:
- Fix derefering of NULL pointer (Kamil)
- Other minor cleanups (Kamil)
Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
---
lib/igt_kms.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/igt_kms.h | 6 ++
2 files changed, 177 insertions(+)
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 5d8096a17..f88c7d6c0 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -93,6 +93,7 @@
#define DISPLAY_TILE_BLOCK 0x12
typedef bool (*igt_connector_attr_set)(int dir, const char *attr, const char *value);
+typedef bool (*igt_crtc_attr_set)(int dir, const char *attr, const char *value);
struct igt_connector_attr {
uint32_t connector_type;
@@ -103,7 +104,16 @@ struct igt_connector_attr {
const char *attr, *value, *reset_value;
};
+struct igt_crtc_attr {
+ int pipe;
+ int idx;
+ int dir;
+ igt_crtc_attr_set set;
+ const char *attr, *value, *reset_value;
+};
+
static struct igt_connector_attr connector_attrs[MAX_CONNECTORS];
+static struct igt_crtc_attr crtc_attrs[IGT_MAX_PIPES];
/**
* igt_kms_get_base_edid:
@@ -1827,6 +1837,146 @@ void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
igt_assert(ret != -1);
}
+static struct igt_crtc_attr *crtc_attr_find(int idx, enum pipe pipe,
+ igt_crtc_attr_set set,
+ const char *attr)
+{
+ igt_assert(pipe > PIPE_NONE && pipe < IGT_MAX_PIPES);
+
+ for (int i = 0; i < ARRAY_SIZE(crtc_attrs); i++) {
+ struct igt_crtc_attr *c = &crtc_attrs[i];
+
+ if (c->idx == idx &&
+ c->pipe == pipe &&
+ c->set == set && !strcmp(c->attr, attr))
+ return c;
+ }
+
+ return NULL;
+}
+
+static struct igt_crtc_attr *crtc_attr_find_free(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(crtc_attrs); i++) {
+ struct igt_crtc_attr *c = &crtc_attrs[i];
+
+ if (!c->attr)
+ return c;
+ }
+
+ return NULL;
+}
+
+static struct igt_crtc_attr *crtc_attr_alloc(int idx, enum pipe pipe,
+ int dir, igt_crtc_attr_set set,
+ const char *attr, const char *reset_value)
+{
+ struct igt_crtc_attr *c = crtc_attr_find_free();
+
+ igt_assert(c);
+
+ c->idx = idx;
+ c->pipe = pipe;
+
+ c->dir = dir;
+ c->set = set;
+ c->attr = attr;
+ c->reset_value = reset_value;
+
+ return c;
+}
+
+static void crtc_attr_free(struct igt_crtc_attr *c)
+{
+ memset(c, 0, sizeof(*c));
+}
+
+static bool crtc_attr_set(int idx, enum pipe pipe,
+ int dir, igt_crtc_attr_set set,
+ const char *attr, const char *value,
+ const char *reset_value)
+{
+ struct igt_crtc_attr *c;
+
+ c = crtc_attr_find(idx, pipe, set, attr);
+ if (!c)
+ c = crtc_attr_alloc(idx, pipe, dir, set, attr, reset_value);
+
+ c->value = value;
+
+ if (!c->set(c->dir, c->attr, c->value)) {
+ crtc_attr_free(c);
+ return false;
+ }
+
+ if (!strcmp(c->value, c->reset_value))
+ crtc_attr_free(c);
+
+ return true;
+}
+
+static bool crtc_attr_set_debugfs(int drm_fd, enum pipe pipe,
+ const char *attr, const char *value,
+ const char *reset_value)
+{
+ int idx, dir;
+
+ idx = igt_device_get_card_index(drm_fd);
+ if (idx < 0 || idx > 63)
+ return false;
+
+ dir = igt_debugfs_pipe_dir(drm_fd, pipe, O_DIRECTORY);
+ if (dir < 0)
+ return false;
+
+ if (!crtc_attr_set(idx, pipe, dir,
+ igt_sysfs_set, attr,
+ value, reset_value))
+ return false;
+
+ igt_info("Crtc-%d/%s is now %s\n", pipe, attr, value);
+
+ return true;
+}
+
+/**
+ * igt_set_crtc_attrs:
+ * @drm_fd: drm file descriptor
+ * @pipe: pipe
+ * @attr: attribute to set
+ * @value: value to set
+ * @reset_value: value to reset to
+ *
+ * Set the attribute @attr to @value on the crtc- at pipe.
+ *
+ * @return: true on success
+ */
+bool igt_set_crtc_attrs(int drm_fd, enum pipe pipe,
+ const char *attr, const char *value,
+ const char *reset_value)
+{
+ return crtc_attr_set_debugfs(drm_fd, pipe, attr, value, reset_value);
+}
+
+/**
+ * kmstest_set_connector_dpms:
+ *
+ * Dump all attr state on all crtcs.
+ */
+void dump_crtc_attrs(void)
+{
+ igt_debug("Current crtc attrs:\n");
+
+ for (int i = 0; i < ARRAY_SIZE(crtc_attrs); i++) {
+ struct igt_crtc_attr *c = &crtc_attrs[i];
+
+ if (!c->attr)
+ continue;
+
+ igt_debug("\tcrtc-%d/%s: %s\n", c->pipe, c->attr, c->value);
+ }
+}
+
/**
* sort_drm_modes_by_clk_dsc:
* @a: first element
@@ -5484,6 +5634,27 @@ void igt_reset_connectors(void)
}
}
+/**
+ * igt_reset_crtcs:
+ *
+ * Remove any forced state from the crtcs.
+ */
+void igt_reset_crtcs(void)
+{
+ /*
+ * Reset the crtcs stored in crtc_attrs, avoiding any
+ * functions that are not safe to call in signal handlers
+ */
+ for (int i = 0; i < ARRAY_SIZE(crtc_attrs); i++) {
+ struct igt_crtc_attr *c = &crtc_attrs[i];
+
+ if (!c->attr)
+ continue;
+
+ c->set(c->dir, c->attr, c->reset_value);
+ }
+}
+
/**
* igt_watch_uevents:
*
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index bd154d1c1..51eba3c69 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -1110,6 +1110,12 @@ void igt_pipe_refresh(igt_display_t *display, enum pipe pipe, bool force);
void igt_enable_connectors(int drm_fd);
void igt_reset_connectors(void);
+bool igt_set_crtc_attrs(int drm_fd, enum pipe pipe,
+ const char *attr, const char *value,
+ const char *reset_value);
+void igt_reset_crtcs(void);
+void dump_crtc_attrs(void);
+
uint32_t kmstest_get_vbl_flag(int crtc_offset);
const struct edid *igt_kms_get_base_edid(void);
--
2.43.0
More information about the igt-dev
mailing list