mode: Retrieve only the current information for a Connector

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.

v2: Fix error path to avoid double free after a failed GETCONNECTOR
ioctl.

v3: Daniel strongly disapproved of my disjoint in behaviour between
GetConnector and GetConnectorCurrent, and considering how best to make a
drop in replacement for drmmode_output_init() convinced me keeping the
API as consistent as possible was the right approach.

v4: Avoid probing on the second calls to GETCONNECTOR for unconnected
outputs.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.com>
Cc: Damien Lespiau <damien.lespiau@intel.com>
Cc: David Herrmann <dh.herrmann@googlemail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
main
Chris Wilson 2015-03-04 10:07:19 +00:00
parent 6f90b77ea9
commit 5ed5fa1060
3 changed files with 51 additions and 7 deletions

View File

@ -43,6 +43,7 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
int current;
int connectors; int connectors;
int full_props; int full_props;
int edid; int edid;
@ -272,7 +273,7 @@ static int printRes(int fd, drmModeResPtr res)
if (connectors) { if (connectors) {
for (i = 0; i < res->count_connectors; i++) { for (i = 0; i < res->count_connectors; i++) {
connector = drmModeGetConnector(fd, res->connectors[i]); connector = (current ? drmModeGetConnectorCurrent : drmModeGetConnector) (fd, res->connectors[i]);
if (!connector) if (!connector)
printf("Could not get connector %i\n", res->connectors[i]); printf("Could not get connector %i\n", res->connectors[i]);
@ -331,6 +332,7 @@ static int printRes(int fd, drmModeResPtr res)
static void args(int argc, char **argv) static void args(int argc, char **argv)
{ {
int defaults = 1;
int i; int i;
fbs = 0; fbs = 0;
@ -341,32 +343,41 @@ static void args(int argc, char **argv)
full_modes = 0; full_modes = 0;
full_props = 0; full_props = 0;
connectors = 0; connectors = 0;
current = 0;
module_name = argv[1]; module_name = argv[1];
for (i = 2; i < argc; i++) { for (i = 2; i < argc; i++) {
if (strcmp(argv[i], "-fb") == 0) { if (strcmp(argv[i], "-fb") == 0) {
fbs = 1; fbs = 1;
defaults = 0;
} else if (strcmp(argv[i], "-crtcs") == 0) { } else if (strcmp(argv[i], "-crtcs") == 0) {
crtcs = 1; crtcs = 1;
defaults = 0;
} else if (strcmp(argv[i], "-cons") == 0) { } else if (strcmp(argv[i], "-cons") == 0) {
connectors = 1; connectors = 1;
modes = 1; modes = 1;
defaults = 0;
} else if (strcmp(argv[i], "-modes") == 0) { } else if (strcmp(argv[i], "-modes") == 0) {
connectors = 1; connectors = 1;
modes = 1; modes = 1;
defaults = 0;
} else if (strcmp(argv[i], "-full") == 0) { } else if (strcmp(argv[i], "-full") == 0) {
connectors = 1; connectors = 1;
modes = 1; modes = 1;
full_modes = 1; full_modes = 1;
defaults = 0;
} else if (strcmp(argv[i], "-props") == 0) { } else if (strcmp(argv[i], "-props") == 0) {
connectors = 1; connectors = 1;
full_props = 1; full_props = 1;
defaults = 0;
} else if (strcmp(argv[i], "-edids") == 0) { } else if (strcmp(argv[i], "-edids") == 0) {
connectors = 1; connectors = 1;
edid = 1; edid = 1;
defaults = 0;
} else if (strcmp(argv[i], "-encoders") == 0) { } else if (strcmp(argv[i], "-encoders") == 0) {
encoders = 1; encoders = 1;
defaults = 0;
} else if (strcmp(argv[i], "-v") == 0) { } else if (strcmp(argv[i], "-v") == 0) {
fbs = 1; fbs = 1;
edid = 1; edid = 1;
@ -376,10 +387,13 @@ static void args(int argc, char **argv)
full_modes = 1; full_modes = 1;
full_props = 1; full_props = 1;
connectors = 1; connectors = 1;
defaults = 0;
} else if (strcmp(argv[i], "-current") == 0) {
current = 1;
} }
} }
if (argc == 2) { if (defaults) {
fbs = 1; fbs = 1;
edid = 1; edid = 1;
crtcs = 1; crtcs = 1;

View File

@ -476,19 +476,23 @@ drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
/* /*
* Connector manipulation * Connector manipulation
*/ */
static drmModeConnectorPtr
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) _drmModeGetConnector(int fd, uint32_t connector_id, int probe)
{ {
struct drm_mode_get_connector conn, counts; struct drm_mode_get_connector conn, counts;
drmModeConnectorPtr r = NULL; drmModeConnectorPtr r = NULL;
retry:
memclear(conn); memclear(conn);
conn.connector_id = connector_id; conn.connector_id = connector_id;
if (!probe) {
conn.count_modes = 1;
conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct drm_mode_modeinfo)));
}
if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
return 0; return 0;
retry:
counts = conn; counts = conn;
if (conn.count_props) { if (conn.count_props) {
@ -504,6 +508,9 @@ retry:
conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
if (!conn.modes_ptr) if (!conn.modes_ptr)
goto err_allocs; goto err_allocs;
} else {
conn.count_modes = 1;
conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct drm_mode_modeinfo)));
} }
if (conn.count_encoders) { if (conn.count_encoders) {
@ -572,6 +579,16 @@ err_allocs:
return r; return r;
} }
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
{
return _drmModeGetConnector(fd, connector_id, 1);
}
drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id)
{
return _drmModeGetConnector(fd, connector_id, 0);
}
int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
{ {
struct drm_mode_mode_cmd res; struct drm_mode_mode_cmd res;

View File

@ -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, 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. * Attaches the given mode to an connector.