[PATCH] mode: Retrieve only the current information for a Connector
Chris Wilson
chris at chris-wilson.co.uk
Wed Mar 4 02:30:30 PST 2015
Add a new API that allows the caller to skip any forced probing, which
may require slow i2c to a remote display, and only report the currently
active mode and encoder for a Connector. This is often the information
of interest and is much, much faster than re-retrieving the link status
and EDIDs, e.g. if the caller only wishes to count the number of active
outputs.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter at ffwll.com>
Cc: Damien Lespiau <damien.lespiau at intel.com>
C: David Herrmann <dh.herrmann at googlemail.com>
---
tests/modeprint/modeprint.c | 18 ++++++++-
xf86drmMode.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
xf86drmMode.h | 17 +++++++-
3 files changed, 129 insertions(+), 4 deletions(-)
diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c
index 6f0d039..514d3ba 100644
--- a/tests/modeprint/modeprint.c
+++ b/tests/modeprint/modeprint.c
@@ -43,6 +43,7 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+int current;
int connectors;
int full_props;
int edid;
@@ -272,7 +273,7 @@ int printRes(int fd, drmModeResPtr res)
if (connectors) {
for (i = 0; i < res->count_connectors; i++) {
- connector = drmModeGetConnector(fd, res->connectors[i]);
+ connector = (current ? drmModeGetConnectorCurrent : drmModeGetConnector) (fd, res->connectors[i]);
if (!connector)
printf("Could not get connector %i\n", res->connectors[i]);
@@ -331,6 +332,7 @@ int printRes(int fd, drmModeResPtr res)
void args(int argc, char **argv)
{
+ int defaults = 1;
int i;
fbs = 0;
@@ -341,32 +343,41 @@ void args(int argc, char **argv)
full_modes = 0;
full_props = 0;
connectors = 0;
+ current = 0;
module_name = argv[1];
for (i = 2; i < argc; i++) {
if (strcmp(argv[i], "-fb") == 0) {
fbs = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-crtcs") == 0) {
crtcs = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-cons") == 0) {
connectors = 1;
modes = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-modes") == 0) {
connectors = 1;
modes = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-full") == 0) {
connectors = 1;
modes = 1;
full_modes = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-props") == 0) {
connectors = 1;
full_props = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-edids") == 0) {
connectors = 1;
edid = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-encoders") == 0) {
encoders = 1;
+ defaults = 0;
} else if (strcmp(argv[i], "-v") == 0) {
fbs = 1;
edid = 1;
@@ -376,10 +387,13 @@ void args(int argc, char **argv)
full_modes = 1;
full_props = 1;
connectors = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-current") == 0) {
+ current = 1;
}
}
- if (argc == 2) {
+ if (defaults) {
fbs = 1;
edid = 1;
crtcs = 1;
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 9ea8fe7..5544e5b 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -572,6 +572,104 @@ err_allocs:
return r;
}
+drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id)
+{
+ struct drm_mode_modeinfo mode;
+ struct drm_mode_get_encoder enc;
+ struct drm_mode_get_connector conn;
+ unsigned int num_props = 0;
+ drmModeConnectorPtr r;
+
+ memclear(conn);
+ conn.connector_id = connector_id;
+ do {
+ if (conn.count_props) {
+ drmFree(U642VOID(conn.props_ptr));
+ drmFree(U642VOID(conn.prop_values_ptr));
+
+ conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
+ if (!conn.props_ptr)
+ goto err;
+
+ conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
+ if (!conn.prop_values_ptr)
+ goto err;
+
+ num_props = conn.count_props;
+ }
+
+ conn.count_modes = 1; /* skip detect */
+ conn.modes_ptr = (uintptr_t)&mode;
+ conn.count_encoders = 0;
+
+ if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
+ goto err;
+ } while (conn.count_props != num_props);
+
+ /* Retrieve the current mode */
+ memclear(mode);
+ memclear(enc);
+ if (conn.encoder_id) {
+ struct drm_mode_crtc crtc;
+
+ enc.encoder_id = conn.encoder_id;
+ if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
+ goto err;
+
+ memclear(crtc);
+ crtc.crtc_id = enc.crtc_id;
+ if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
+ goto err;
+
+ if (crtc.mode_valid)
+ mode = crtc.mode;
+ }
+
+ if(!(r = drmMalloc(sizeof(*r))))
+ goto err;
+
+ memset(r, 0, sizeof(*r));
+ r->connector_id = conn.connector_id;
+ r->encoder_id = conn.encoder_id;
+ r->connection = conn.connection;
+ r->mmWidth = conn.mm_width;
+ r->mmHeight = conn.mm_height;
+ /* convert subpixel from kernel to userspace */
+ r->subpixel = conn.subpixel + 1;
+
+ if (mode.clock) {
+ r->count_modes = 1;
+ r->modes = drmAllocCpy(&mode, 1, sizeof(mode));
+ if (!r->modes)
+ goto err_copy;
+ }
+
+ if (conn.encoder_id) {
+ r->count_encoders = 1;
+ r->encoders = drmAllocCpy(&enc, 1, sizeof(enc));
+ if (!r->encoders)
+ goto err_copy;
+ }
+
+ r->count_props = conn.count_props;
+ r->props = U642VOID(conn.props_ptr);
+ r->prop_values = U642VOID(conn.prop_values_ptr);
+
+ r->connector_type = conn.connector_type;
+ r->connector_type_id = conn.connector_type_id;
+
+ return r;
+
+err_copy:
+ drmFree(r->modes);
+ drmFree(r->encoders);
+ drmFree(r);
+err:
+ drmFree(U642VOID(conn.props_ptr));
+ drmFree(U642VOID(conn.prop_values_ptr));
+ return 0;
+}
+
int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
{
struct drm_mode_mode_cmd res;
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 856a6bb..278da48 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -422,10 +422,23 @@ drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id);
*/
/**
- * Retrive information about the connector connectorId.
+ * Retrieve all information about the connector connectorId. This will do a
+ * forced probe on the connector to retrieve remote information such as EDIDs
+ * from the display device.
*/
extern drmModeConnectorPtr drmModeGetConnector(int fd,
- uint32_t connectorId);
+ uint32_t connectorId);
+
+/**
+ * Retrieve current information, i.e the currently active mode and encoder,
+ * about the connector connectorId. This will not do any probing on the
+ * connector or remote device, and only reports what is currently known.
+ * For the complete set of modes and encoders associated with the connector
+ * use drmModeGetConnector() which will do a probe to determine any display
+ * link changes first.
+ */
+extern drmModeConnectorPtr drmModeGetConnectorCurrent(int fd,
+ uint32_t connector_id);
/**
* Attaches the given mode to an connector.
--
2.1.4
More information about the dri-devel
mailing list