summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2016-09-04 18:58:24 -0400
committerRob Clark <robdclark@gmail.com>2016-09-07 14:25:40 -0400
commitdca4a37f375fb22f20f58ba6fb8fb5cd446a92fa (patch)
tree661a45e5603890c375516fbe9786e0cacea07cd6
parent7b20482798d72c087e6435daa17533358ebbd010 (diff)
Make search for a crtc more robust
Running the kmscube test on qemu with "-vga virtio" fails for me with a "no encoder!" error. Fixed by searching all crtcs for one that is supported by one of the encoders in the connector. This code is only used if the existing `encoder->crtc_id` check is zero, so there should be no regression for systems where it already works. I think this should match the advice given here: https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api/
-rw-r--r--kmscube.c55
1 files changed, 51 insertions, 4 deletions
diff --git a/kmscube.c b/kmscube.c
index a5915a6..36ef8ee 100644
--- a/kmscube.c
+++ b/kmscube.c
@@ -76,6 +76,47 @@ struct drm_fb {
uint32_t fb_id;
};
+static uint32_t find_crtc_for_encoder(const drmModeRes *resources,
+ const drmModeEncoder *encoder) {
+ int i;
+
+ for (i = 0; i < resources->count_crtcs; i++) {
+ /* possible_crtcs is a bitmask as described here:
+ * https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api
+ */
+ const uint32_t crtc_mask = 1 << i;
+ const uint32_t crtc_id = resources->crtcs[i];
+ if (encoder->possible_crtcs & crtc_mask) {
+ return crtc_id;
+ }
+ }
+
+ /* no match found */
+ return -1;
+}
+
+static uint32_t find_crtc_for_connector(const drmModeRes *resources,
+ const drmModeConnector *connector) {
+ int i;
+
+ for (i = 0; i < connector->count_encoders; i++) {
+ const uint32_t encoder_id = connector->encoders[i];
+ drmModeEncoder *encoder = drmModeGetEncoder(drm.fd, encoder_id);
+
+ if (encoder) {
+ const uint32_t crtc_id = find_crtc_for_encoder(resources, encoder);
+
+ drmModeFreeEncoder(encoder);
+ if (crtc_id != 0) {
+ return crtc_id;
+ }
+ }
+ }
+
+ /* no match found */
+ return -1;
+}
+
static int init_drm(void)
{
static const char *modules[] = {
@@ -156,12 +197,18 @@ static int init_drm(void)
encoder = NULL;
}
- if (!encoder) {
- printf("no encoder!\n");
- return -1;
+ if (encoder) {
+ drm.crtc_id = encoder->crtc_id;
+ } else {
+ uint32_t crtc_id = find_crtc_for_connector(resources, connector);
+ if (crtc_id == 0) {
+ printf("no crtc found!\n");
+ return -1;
+ }
+
+ drm.crtc_id = crtc_id;
}
- drm.crtc_id = encoder->crtc_id;
drm.connector_id = connector->connector_id;
return 0;