lib: add kmstest_get_connector_config
authorImre Deak <imre.deak@intel.com>
Thu, 30 May 2013 21:21:43 +0000 (00:21 +0300)
committerImre Deak <imre.deak@intel.com>
Wed, 5 Jun 2013 22:43:51 +0000 (01:43 +0300)
This is used by multiple test cases, so make it shared.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
lib/drmtest.c
lib/drmtest.h
tests/kms_flip.c
tests/testdisplay.c

index 3ad77a8..7368077 100644 (file)
@@ -1317,3 +1317,137 @@ int drmtest_set_vt_graphics_mode(void)
        return orig_vt_mode < 0 ? -1 : 0;
 }
 
+static int get_connector_default_mode(int drm_fd, drmModeConnector *connector,
+                                     drmModeModeInfo *mode)
+{
+       drmModeRes *resources;
+       int i;
+
+       resources = drmModeGetResources(drm_fd);
+       if (!resources) {
+               perror("drmModeGetResources failed");
+
+               return -1;
+       }
+
+       if (!connector->count_modes) {
+               fprintf(stderr, "no modes for connector %d\n",
+                       connector->connector_id);
+               drmModeFreeResources(resources);
+
+               return -1;
+       }
+
+       for (i = 0; i < connector->count_modes; i++) {
+               if (i == 0 ||
+                   connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
+                       *mode = connector->modes[i];
+                       if (mode->type & DRM_MODE_TYPE_PREFERRED)
+                               break;
+               }
+       }
+
+       drmModeFreeResources(resources);
+
+       return 0;
+}
+
+int kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
+                                unsigned long crtc_idx_mask,
+                                struct kmstest_connector_config *config)
+{
+       drmModeRes *resources;
+       drmModeConnector *connector;
+       drmModeEncoder *encoder;
+       int i, j;
+
+       resources = drmModeGetResources(drm_fd);
+       if (!resources) {
+               perror("drmModeGetResources failed");
+               goto err1;
+       }
+
+       /* First, find the connector & mode */
+       connector = drmModeGetConnector(drm_fd, connector_id);
+       if (!connector)
+               goto err2;
+
+       if (connector->connection != DRM_MODE_CONNECTED)
+               goto err3;
+
+       if (!connector->count_modes) {
+               fprintf(stderr, "connector %d has no modes\n", connector_id);
+               goto err3;
+       }
+
+       if (connector->connector_id != connector_id) {
+               fprintf(stderr, "connector id doesn't match (%d != %d)\n",
+                       connector->connector_id, connector_id);
+               goto err3;
+       }
+
+       /*
+        * Find given CRTC if crtc_id != 0 or else the first CRTC not in use.
+        * In both cases find the first compatible encoder and skip the CRTC
+        * if there is non such.
+        */
+       encoder = NULL;         /* suppress GCC warning */
+       for (i = 0; i < resources->count_crtcs; i++) {
+               if (!resources->crtcs[i] || !(crtc_idx_mask & (1 << i)))
+                       continue;
+
+               /* Now get a compatible encoder */
+               for (j = 0; j < connector->count_encoders; j++) {
+                       encoder = drmModeGetEncoder(drm_fd,
+                                                   connector->encoders[j]);
+
+                       if (!encoder) {
+                               fprintf(stderr, "could not get encoder %d: %s\n",
+                                       resources->encoders[j], strerror(errno));
+
+                               continue;
+                       }
+
+                       if (encoder->possible_crtcs & (1 << i))
+                               goto found;
+
+                       drmModeFreeEncoder(encoder);
+               }
+       }
+
+       fprintf(stderr,
+               "no crtc with a compatible encoder (crtc_idx_mask %08lx)\n",
+               crtc_idx_mask);
+       goto err3;
+
+found:
+       if (get_connector_default_mode(drm_fd, connector,
+                                      &config->default_mode) < 0)
+               goto err4;
+
+       config->connector = connector;
+       config->encoder = encoder;
+       config->crtc = drmModeGetCrtc(drm_fd, resources->crtcs[i]);
+       config->crtc_idx = i;
+       config->pipe = kmstest_get_pipe_from_crtc_id(drm_fd,
+                                                    config->crtc->crtc_id);
+
+       drmModeFreeResources(resources);
+
+       return 0;
+err4:
+       drmModeFreeEncoder(encoder);
+err3:
+       drmModeFreeConnector(connector);
+err2:
+       drmModeFreeResources(resources);
+err1:
+       return -1;
+}
+
+void kmstest_free_connector_config(struct kmstest_connector_config *config)
+{
+       drmModeFreeCrtc(config->crtc);
+       drmModeFreeEncoder(config->encoder);
+       drmModeFreeConnector(config->connector);
+}
index 3c1368d..89ded11 100644 (file)
@@ -101,6 +101,20 @@ void drmtest_init_aperture_trashers(drm_intel_bufmgr *bufmgr);
 void drmtest_trash_aperture(void);
 void drmtest_cleanup_aperture_trashers(void);
 
+struct kmstest_connector_config {
+       drmModeCrtc *crtc;
+       drmModeConnector *connector;
+       drmModeEncoder *encoder;
+       drmModeModeInfo default_mode;
+       int crtc_idx;
+       int pipe;
+};
+
+int kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
+                                unsigned long crtc_idx_mask,
+                                struct kmstest_connector_config *config);
+void kmstest_free_connector_config(struct kmstest_connector_config *config);
+
 /* helpers to create nice-looking framebuffers */
 struct kmstest_fb {
        uint32_t fb_id;
index 735b4dd..c9b3d8a 100644 (file)
@@ -825,97 +825,23 @@ static void update_all_state(struct test_output *o,
                update_state(&o->vblank_state);
 }
 
-static void connector_find_preferred_mode(struct test_output *o, int crtc_id)
+static void connector_find_preferred_mode(uint32_t connector_id, int crtc_idx,
+                                         struct test_output *o)
 {
-       drmModeConnector *connector;
-       drmModeEncoder *encoder = NULL;
-       int i, j;
-
-       /* First, find the connector & mode */
-       o->mode_valid = 0;
-       o->crtc = 0;
-       connector = drmModeGetConnector(drm_fd, o->id);
-       assert(connector);
-
-       if (connector->connection != DRM_MODE_CONNECTED) {
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       if (!connector->count_modes) {
-               fprintf(stderr, "connector %d has no modes\n", o->id);
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       if (connector->connector_id != o->id) {
-               fprintf(stderr, "connector id doesn't match (%d != %d)\n",
-                       connector->connector_id, o->id);
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       for (j = 0; j < connector->count_modes; j++) {
-               o->mode = connector->modes[j];
-               if (o->mode.type & DRM_MODE_TYPE_PREFERRED) {
-                       o->mode_valid = 1;
-                       break;
-               }
-       }
-
-       if (!o->mode_valid) {
-               if (connector->count_modes > 0) {
-                       /* use the first mode as test mode */
-                       o->mode = connector->modes[0];
-                       o->mode_valid = 1;
-               }
-               else {
-                       fprintf(stderr, "failed to find any modes on connector %d\n",
-                               o->id);
-                       return;
-               }
-       }
+       struct kmstest_connector_config config;
 
-       /* Now get the encoder */
-       for (i = 0; i < connector->count_encoders; i++) {
-               encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]);
-
-               if (!encoder) {
-                       fprintf(stderr, "could not get encoder %i: %s\n",
-                               resources->encoders[i], strerror(errno));
-                       drmModeFreeEncoder(encoder);
-                       continue;
-               }
-
-               break;
-       }
-
-       o->encoder = encoder;
-
-       if (i == resources->count_encoders) {
-               fprintf(stderr, "failed to find encoder\n");
-               o->mode_valid = 0;
-               return;
-       }
-
-       /* Find first CRTC not in use */
-       for (i = 0; i < resources->count_crtcs; i++) {
-               if (resources->crtcs[i] != crtc_id)
-                       continue;
-               if (resources->crtcs[i] &&
-                   (o->encoder->possible_crtcs & (1<<i))) {
-                       o->crtc = resources->crtcs[i];
-                       break;
-               }
-       }
-
-       if (!o->crtc) {
-               fprintf(stderr, "could not find requested crtc %d\n", crtc_id);
+       if (kmstest_get_connector_config(drm_fd, connector_id, 1 << crtc_idx,
+                                        &config) < 0) {
                o->mode_valid = 0;
                return;
        }
 
-       o->connector = connector;
+       o->connector = config.connector;
+       o->encoder = config.encoder;
+       o->crtc = config.crtc->crtc_id;
+       o->pipe = config.pipe;
+       o->mode = config.default_mode;
+       o->mode_valid = 1;
 }
 
 static void
@@ -1042,21 +968,21 @@ static unsigned event_loop(struct test_output *o, unsigned duration_sec)
        return end - start;
 }
 
-static void run_test_on_crtc(struct test_output *o, int crtc, int duration)
+static void run_test_on_crtc(struct test_output *o, int crtc_idx, int duration)
 {
        unsigned ellapsed;
 
        o->bpp = 32;
        o->depth = 24;
 
-       connector_find_preferred_mode(o, crtc);
+       connector_find_preferred_mode(o->id, crtc_idx, o);
        if (!o->mode_valid)
                return;
 
        last_connector = o->connector;
 
        fprintf(stdout, "Beginning %s on crtc %d, connector %d\n",
-               o->test_name, crtc, o->id);
+               o->test_name, o->crtc, o->id);
 
        o->fb_width = o->mode.hdisplay;
        o->fb_height = o->mode.vdisplay;
@@ -1116,7 +1042,7 @@ static void run_test_on_crtc(struct test_output *o, int crtc, int duration)
                check_final_state(o, &o->vblank_state, ellapsed);
 
        fprintf(stdout, "\n%s on crtc %d, connector %d: PASSED\n\n",
-               o->test_name, crtc, o->id);
+               o->test_name, o->crtc, o->id);
 
        kmstest_remove_fb(drm_fd, o->fb_ids[2]);
        kmstest_remove_fb(drm_fd, o->fb_ids[1]);
@@ -1131,7 +1057,8 @@ static void run_test_on_crtc(struct test_output *o, int crtc, int duration)
 static int run_test(int duration, int flags, const char *test_name)
 {
        struct test_output o;
-       int c, i;
+       int c;
+       int crtc_idx;
 
        resources = drmModeGetResources(drm_fd);
        if (!resources) {
@@ -1142,19 +1069,15 @@ static int run_test(int duration, int flags, const char *test_name)
 
        /* Find any connected displays */
        for (c = 0; c < resources->count_connectors; c++) {
-               for (i = 0; i < resources->count_crtcs; i++) {
-                       int crtc;
-
+               for (crtc_idx = 0; crtc_idx < resources->count_crtcs; crtc_idx++) {
                        memset(&o, 0, sizeof(o));
                        o.test_name = test_name;
                        o.id = resources->connectors[c];
                        o.flags = flags;
                        o.flip_state.name = "flip";
                        o.vblank_state.name = "vblank";
-                       crtc = resources->crtcs[i];
-                       o.pipe = kmstest_get_pipe_from_crtc_id(drm_fd, crtc);
 
-                       run_test_on_crtc(&o, crtc, duration);
+                       run_test_on_crtc(&o, crtc_idx, duration);
                }
        }
 
index 67b7031..30474af 100644 (file)
@@ -102,6 +102,7 @@ struct connector {
        drmModeEncoder *encoder;
        drmModeConnector *connector;
        int crtc;
+       int crtc_idx;
        int pipe;
 };
 
@@ -185,101 +186,31 @@ static void dump_crtcs_fd(int drmfd)
        drmModeFreeResources(mode_resources);
 }
 
-static void connector_find_preferred_mode(struct connector *c)
+static void connector_find_preferred_mode(uint32_t connector_id,
+                                         unsigned long crtc_idx_mask,
+                                         int mode_num, struct connector *c)
 {
-       drmModeConnector *connector;
-       drmModeEncoder *encoder = NULL;
-       int i, j;
-
-       /* First, find the connector & mode */
-       c->mode_valid = 0;
-       connector = drmModeGetConnector(drm_fd, c->id);
-       if (!connector) {
-               fprintf(stderr, "could not get connector %d: %s\n",
-                       c->id, strerror(errno));
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       if (connector->connection != DRM_MODE_CONNECTED) {
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       if (!connector->count_modes) {
-               fprintf(stderr, "connector %d has no modes\n", c->id);
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       if (connector->connector_id != c->id) {
-               fprintf(stderr, "connector id doesn't match (%d != %d)\n",
-                       connector->connector_id, c->id);
-               drmModeFreeConnector(connector);
-               return;
-       }
-
-       for (j = 0; j < connector->count_modes; j++) {
-               c->mode = connector->modes[j];
-               if (c->mode.type & DRM_MODE_TYPE_PREFERRED) {
-                       c->mode_valid = 1;
-                       break;
-               }
-       }
-
-       if ( specified_mode_num != -1 ){
-               c->mode = connector->modes[specified_mode_num];
-               if (c->mode.type & DRM_MODE_TYPE_PREFERRED)
-                       c->mode_valid = 1;
-       }
-
-       if (!c->mode_valid) {
-               if (connector->count_modes > 0) {
-                       /* use the first mode as test mode */
-                       c->mode = connector->modes[0];
-                       c->mode_valid = 1;
-               }
-               else {
-                       fprintf(stderr, "failed to find any modes on connector %d\n",
-                               c->id);
-                       return;
-               }
-       }
-
-       /* Now get the encoder */
-       for (i = 0; i < connector->count_encoders; i++) {
-               encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]);
-
-               if (!encoder) {
-                       fprintf(stderr, "could not get encoder %i: %s\n",
-                               resources->encoders[i], strerror(errno));
-                       drmModeFreeEncoder(encoder);
-                       continue;
-               }
-
-               break;
-       }
-
-       c->encoder = encoder;
+       struct kmstest_connector_config config;
 
-       if (i == resources->count_encoders) {
-               fprintf(stderr, "failed to find encoder\n");
+       if (kmstest_get_connector_config(drm_fd, connector_id, crtc_idx_mask,
+                                        &config) < 0) {
                c->mode_valid = 0;
                return;
        }
 
-       /* Find first CRTC not in use */
-       for (i = 0; i < resources->count_crtcs; i++) {
-               if (resources->crtcs[i] && (c->encoder->possible_crtcs & (1<<i)))
-                       break;
+       c->connector = config.connector;
+       c->encoder = config.encoder;
+       c->crtc = config.crtc->crtc_id;
+       c->crtc_idx = config.crtc_idx;
+       c->pipe = config.pipe;
+
+       if (mode_num != -1) {
+               assert(mode_num < config.connector->count_modes);
+               c->mode = config.connector->modes[mode_num];
+       } else {
+               c->mode = config.default_mode;
        }
-       c->crtc = resources->crtcs[i];
-       c->pipe = i;
-
-       if(test_preferred_mode || force_mode || specified_mode_num != -1)
-               resources->crtcs[i] = 0;
-
-       c->connector = connector;
+       c->mode_valid = 1;
 }
 
 static void
@@ -409,10 +340,6 @@ set_mode(struct connector *c)
        else if (depth > 16 && depth <= 32)
                bpp = 32;
 
-       connector_find_preferred_mode(c);
-       if (!c->mode_valid)
-               return;
-
        test_mode_num = 1;
        if (force_mode){
                memcpy( &c->mode, &force_timing, sizeof(force_timing));
@@ -506,13 +433,30 @@ int update_display(void)
        }
 
        if (test_preferred_mode || test_all_modes || force_mode || specified_disp_id != -1) {
+               unsigned long crtc_idx_mask = -1UL;
+
                /* Find any connected displays */
                for (c = 0; c < resources->count_connectors; c++) {
-                       connectors[c].id = resources->connectors[c];
-                       if ( specified_disp_id != -1 && connectors[c].id != specified_disp_id )
+                       struct connector *connector = &connectors[c];
+
+                       connector->id = resources->connectors[c];
+                       if (specified_disp_id != -1 &&
+                           connector->id != specified_disp_id)
+                               continue;
+
+                       connector_find_preferred_mode(connector->id,
+                                                     crtc_idx_mask,
+                                                     specified_mode_num,
+                                                     connector);
+                       if (!connector->mode_valid)
                                continue;
 
-                       set_mode(&connectors[c]);
+                       set_mode(connector);
+
+                       if (test_preferred_mode || force_mode ||
+                           specified_mode_num != -1)
+                               crtc_idx_mask &= ~(1 << connector->crtc_idx);
+
                }
        }
        drmModeFreeResources(resources);