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

Reply via email to