2 * DRM based fimc test program
3 * Copyright 2012 Samsung Electronics
4 * Eunchul Kim <chulspro.kim@sasmsung.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * This fairly simple test program dumps output in a similar format to the
27 * "xrandr" tool everyone knows & loves. It's necessarily slightly different
28 * since the kernel separates outputs into encoder and connector structures,
29 * each with their own unique ID. The program also allows test testing of the
30 * memory management and mode setting APIs by allowing the user to specify a
31 * connector and mode to use for mode setting. If all works as expected, a
32 * blue background should be painted on the monitor attached to the specified
33 * connector after the selected mode is set.
52 #include "exynos_drm.h"
57 drmModeRes *resources;
60 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
67 #define type_name_fn(res) \
68 char * res##_str(int type) { \
70 for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
71 if (res##_names[i].type == type) \
72 return res##_names[i].name; \
77 struct type_name encoder_type_names[] = {
78 { DRM_MODE_ENCODER_NONE, "none" },
79 { DRM_MODE_ENCODER_DAC, "DAC" },
80 { DRM_MODE_ENCODER_TMDS, "TMDS" },
81 { DRM_MODE_ENCODER_LVDS, "LVDS" },
82 { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
85 type_name_fn(encoder_type)
87 struct type_name connector_status_names[] = {
88 { DRM_MODE_CONNECTED, "connected" },
89 { DRM_MODE_DISCONNECTED, "disconnected" },
90 { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
93 type_name_fn(connector_status)
95 struct type_name connector_type_names[] = {
96 { DRM_MODE_CONNECTOR_Unknown, "unknown" },
97 { DRM_MODE_CONNECTOR_VGA, "VGA" },
98 { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
99 { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
100 { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
101 { DRM_MODE_CONNECTOR_Composite, "composite" },
102 { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
103 { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
104 { DRM_MODE_CONNECTOR_Component, "component" },
105 { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
106 { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
107 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
108 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
109 { DRM_MODE_CONNECTOR_TV, "TV" },
110 { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
113 type_name_fn(connector_type)
115 static void dump_encoders(void)
117 drmModeEncoder *encoder;
120 printf("Encoders:\n");
121 printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
122 for (i = 0; i < resources->count_encoders; i++) {
123 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
126 fprintf(stderr, "could not get encoder %i: %s\n",
127 resources->encoders[i], strerror(errno));
130 printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
133 encoder_type_str(encoder->encoder_type),
134 encoder->possible_crtcs,
135 encoder->possible_clones);
136 drmModeFreeEncoder(encoder);
141 static void dump_mode(drmModeModeInfo *mode)
143 printf(" %s %d %d %d %d %d %d %d %d %d\n",
156 static void dump_props(drmModeConnector *connector)
158 drmModePropertyPtr props;
161 for (i = 0; i < connector->count_props; i++) {
162 props = drmModeGetProperty(fd, connector->props[i]);
163 printf("\t%s, flags %d\n", props->name, props->flags);
164 drmModeFreeProperty(props);
168 static void dump_connectors(void)
170 drmModeConnector *connector;
173 printf("Connectors:\n");
174 printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
175 for (i = 0; i < resources->count_connectors; i++) {
176 connector = drmModeGetConnector(fd, resources->connectors[i]);
179 fprintf(stderr, "could not get connector %i: %s\n",
180 resources->connectors[i], strerror(errno));
184 printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
185 connector->connector_id,
186 connector->encoder_id,
187 connector_status_str(connector->connection),
188 connector_type_str(connector->connector_type),
189 connector->mmWidth, connector->mmHeight,
190 connector->count_modes);
192 for (j = 0; j < connector->count_encoders; j++)
193 printf("%s%d", j > 0 ? ", " : "",
194 connector->encoders[j]);
197 if (!connector->count_modes)
201 printf(" name refresh (Hz) hdisp hss hse htot vdisp "
203 for (j = 0; j < connector->count_modes; j++)
204 dump_mode(&connector->modes[j]);
207 dump_props(connector);
209 drmModeFreeConnector(connector);
214 static void dump_crtcs(void)
220 printf("id\tfb\tpos\tsize\n");
221 for (i = 0; i < resources->count_crtcs; i++) {
222 crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
225 fprintf(stderr, "could not get crtc %i: %s\n",
226 resources->crtcs[i], strerror(errno));
229 printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
233 crtc->width, crtc->height);
234 dump_mode(&crtc->mode);
236 drmModeFreeCrtc(crtc);
241 static void dump_framebuffers(void)
246 printf("Frame buffers:\n");
247 printf("id\tsize\tpitch\n");
248 for (i = 0; i < resources->count_fbs; i++) {
249 fb = drmModeGetFB(fd, resources->fbs[i]);
252 fprintf(stderr, "could not get fb %i: %s\n",
253 resources->fbs[i], strerror(errno));
256 printf("%u\t(%ux%u)\t%u\n",
258 fb->width, fb->height,
267 * Mode setting with the kernel interfaces is a bit of a chore.
268 * First you have to find the connector in question and make sure the
269 * requested mode is available.
270 * Then you need to find the encoder attached to that connector so you
271 * can bind it with a free crtc.
274 void connector_find_mode(struct connector *c)
276 drmModeConnector *connector;
279 /* First, find the connector & mode */
281 for (i = 0; i < resources->count_connectors; i++) {
282 connector = drmModeGetConnector(fd, resources->connectors[i]);
285 fprintf(stderr, "could not get connector %i: %s\n",
286 resources->connectors[i], strerror(errno));
287 drmModeFreeConnector(connector);
291 if (!connector->count_modes) {
292 drmModeFreeConnector(connector);
296 if (connector->connector_id != c->id) {
297 drmModeFreeConnector(connector);
301 for (j = 0; j < connector->count_modes; j++) {
302 c->mode = &connector->modes[j];
303 if (!strcmp(c->mode->name, c->mode_str))
307 /* Found it, break out */
311 drmModeFreeConnector(connector);
315 fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
319 /* Now get the encoder */
320 for (i = 0; i < resources->count_encoders; i++) {
321 c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
324 fprintf(stderr, "could not get encoder %i: %s\n",
325 resources->encoders[i], strerror(errno));
326 drmModeFreeEncoder(c->encoder);
330 if (c->encoder->encoder_id == connector->encoder_id)
333 drmModeFreeEncoder(c->encoder);
337 c->crtc = c->encoder->crtc_id;
341 extern int optind, opterr, optopt;
342 static char optstr[] = "ecpmfo:s:v";
344 static void usage(char *name)
346 fprintf(stderr, "usage: %s [-ecpmf]\n", name);
347 fprintf(stderr, "\t-e\tlist encoders\n");
348 fprintf(stderr, "\t-c\tlist connectors\n");
349 fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
350 fprintf(stderr, "\t-m\tlist modes\n");
351 fprintf(stderr, "\t-f\tlist framebuffers\n");
352 fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
353 fprintf(stderr, "\t-o\tlist of operation id : 0: M2M, 1: Writeback, 2: Output\n");
354 fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
355 fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
356 fprintf(stderr, "\n\tDefault is to dump all info.\n");
360 #define dump_resource(res) if (res) dump_##res()
362 int main(int argc, char **argv)
365 int operations = 0, encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
367 char *modules[] = {"exynos", "i915", "radeon", "nouveau", "vmwgfx"};
368 char *modeset = NULL;
370 struct connector con_args[2];
373 while ((c = getopt(argc, argv, optstr)) != -1) {
395 sscanf(optarg, "%d", &operations);
398 modeset = strdup(optarg);
399 con_args[count].crtc = -1;
400 if (sscanf(optarg, "%d:%64s",
402 con_args[count].mode_str) != 2 &&
403 sscanf(optarg, "%d@%d:%64s",
405 &con_args[count].crtc,
406 con_args[count].mode_str) != 3)
417 encoders = connectors = crtcs = modes = framebuffers = 1;
419 for (i = 0; i < ARRAY_SIZE(modules); i++) {
420 printf("trying to load module %s...", modules[i]);
421 fd = drmOpen(modules[i], NULL);
425 printf("success.\n");
430 if (i == ARRAY_SIZE(modules)) {
431 fprintf(stderr, "failed to load any modules, aborting.\n");
435 resources = drmModeGetResources(fd);
437 fprintf(stderr, "drmModeGetResources failed: %s\n",
443 dump_resource(encoders);
444 dump_resource(connectors);
445 dump_resource(crtcs);
446 dump_resource(framebuffers);
449 long int sum = 0, usec[MAX_LOOP];
453 fimc_m2m_set_mode(con_args, count, test_vsync, usec);
456 fimc_wb_set_mode(con_args, count, test_vsync, usec);
459 fimc_output_set_mode(con_args, count, test_vsync, usec);
465 for (i = 0; i < MAX_LOOP; i++) {
466 printf("[%d] : %d\n", i + 1, usec[i]);
469 printf("fimc : cma\n");
470 printf("avg : [%d]\n", sum / MAX_LOOP);
474 drmModeFreeResources(resources);