ipptest: add fimc and rotator test applications
[platform/upstream/libdrm.git] / tests / ipptest / fimctest.c
1 /*
2  * DRM based fimc test program
3  * Copyright 2012 Samsung Electronics
4  *   Eunchul Kim <chulspro.kim@sasmsung.com>
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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
22  * IN THE SOFTWARE.
23  */
24
25 /*
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.
34  *
35  */
36
37 #include "config.h"
38
39 #include <assert.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stdint.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <sys/poll.h>
47 #include <sys/time.h>
48 #include <sys/mman.h>
49
50 #include "libkms.h"
51
52 #include "exynos_drm.h"
53
54 #include "fimctest.h"
55 #include "fimc.h"
56
57 drmModeRes *resources;
58 int fd, modes;
59
60 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
61
62 struct type_name {
63         int type;
64         char *name;
65 };
66
67 #define type_name_fn(res) \
68 char * res##_str(int type) {                    \
69         int i;                                          \
70         for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
71                 if (res##_names[i].type == type)        \
72                         return res##_names[i].name;     \
73         }                                               \
74         return "(invalid)";                             \
75 }
76
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" },
83 };
84
85 type_name_fn(encoder_type)
86
87 struct type_name connector_status_names[] = {
88         { DRM_MODE_CONNECTED, "connected" },
89         { DRM_MODE_DISCONNECTED, "disconnected" },
90         { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
91 };
92
93 type_name_fn(connector_status)
94
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" },
111 };
112
113 type_name_fn(connector_type)
114
115 static void dump_encoders(void)
116 {
117         drmModeEncoder *encoder;
118         int i;
119
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]);
124
125                 if (!encoder) {
126                         fprintf(stderr, "could not get encoder %i: %s\n",
127                                 resources->encoders[i], strerror(errno));
128                         continue;
129                 }
130                 printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
131                        encoder->encoder_id,
132                        encoder->crtc_id,
133                        encoder_type_str(encoder->encoder_type),
134                        encoder->possible_crtcs,
135                        encoder->possible_clones);
136                 drmModeFreeEncoder(encoder);
137         }
138         printf("\n");
139 }
140
141 static void dump_mode(drmModeModeInfo *mode)
142 {
143         printf("  %s %d %d %d %d %d %d %d %d %d\n",
144                mode->name,
145                mode->vrefresh,
146                mode->hdisplay,
147                mode->hsync_start,
148                mode->hsync_end,
149                mode->htotal,
150                mode->vdisplay,
151                mode->vsync_start,
152                mode->vsync_end,
153                mode->vtotal);
154 }
155
156 static void dump_props(drmModeConnector *connector)
157 {
158         drmModePropertyPtr props;
159         int i;
160
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);
165         }
166 }
167
168 static void dump_connectors(void)
169 {
170         drmModeConnector *connector;
171         int i, j;
172
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]);
177
178                 if (!connector) {
179                         fprintf(stderr, "could not get connector %i: %s\n",
180                                 resources->connectors[i], strerror(errno));
181                         continue;
182                 }
183
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);
191
192                 for (j = 0; j < connector->count_encoders; j++)
193                         printf("%s%d", j > 0 ? ", " : "",
194                                                         connector->encoders[j]);
195                 printf("\n");
196
197                 if (!connector->count_modes)
198                         continue;
199
200                 printf("  modes:\n");
201                 printf("  name refresh (Hz) hdisp hss hse htot vdisp "
202                        "vss vse vtot)\n");
203                 for (j = 0; j < connector->count_modes; j++)
204                         dump_mode(&connector->modes[j]);
205
206                 printf("  props:\n");
207                 dump_props(connector);
208
209                 drmModeFreeConnector(connector);
210         }
211         printf("\n");
212 }
213
214 static void dump_crtcs(void)
215 {
216         drmModeCrtc *crtc;
217         int i;
218
219         printf("CRTCs:\n");
220         printf("id\tfb\tpos\tsize\n");
221         for (i = 0; i < resources->count_crtcs; i++) {
222                 crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
223
224                 if (!crtc) {
225                         fprintf(stderr, "could not get crtc %i: %s\n",
226                                 resources->crtcs[i], strerror(errno));
227                         continue;
228                 }
229                 printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
230                        crtc->crtc_id,
231                        crtc->buffer_id,
232                        crtc->x, crtc->y,
233                        crtc->width, crtc->height);
234                 dump_mode(&crtc->mode);
235
236                 drmModeFreeCrtc(crtc);
237         }
238         printf("\n");
239 }
240
241 static void dump_framebuffers(void)
242 {
243         drmModeFB *fb;
244         int i;
245
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]);
250
251                 if (!fb) {
252                         fprintf(stderr, "could not get fb %i: %s\n",
253                                 resources->fbs[i], strerror(errno));
254                         continue;
255                 }
256                 printf("%u\t(%ux%u)\t%u\n",
257                        fb->fb_id,
258                        fb->width, fb->height,
259                        fb->pitch);
260
261                 drmModeFreeFB(fb);
262         }
263         printf("\n");
264 }
265
266 /*
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.
272  */
273
274 void connector_find_mode(struct connector *c)
275 {
276         drmModeConnector *connector;
277         int i, j;
278
279         /* First, find the connector & mode */
280         c->mode = NULL;
281         for (i = 0; i < resources->count_connectors; i++) {
282                 connector = drmModeGetConnector(fd, resources->connectors[i]);
283
284                 if (!connector) {
285                         fprintf(stderr, "could not get connector %i: %s\n",
286                                 resources->connectors[i], strerror(errno));
287                         drmModeFreeConnector(connector);
288                         continue;
289                 }
290
291                 if (!connector->count_modes) {
292                         drmModeFreeConnector(connector);
293                         continue;
294                 }
295
296                 if (connector->connector_id != c->id) {
297                         drmModeFreeConnector(connector);
298                         continue;
299                 }
300
301                 for (j = 0; j < connector->count_modes; j++) {
302                         c->mode = &connector->modes[j];
303                         if (!strcmp(c->mode->name, c->mode_str))
304                                 break;
305                 }
306
307                 /* Found it, break out */
308                 if (c->mode)
309                         break;
310
311                 drmModeFreeConnector(connector);
312         }
313
314         if (!c->mode) {
315                 fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
316                 return;
317         }
318
319         /* Now get the encoder */
320         for (i = 0; i < resources->count_encoders; i++) {
321                 c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
322
323                 if (!c->encoder) {
324                         fprintf(stderr, "could not get encoder %i: %s\n",
325                                 resources->encoders[i], strerror(errno));
326                         drmModeFreeEncoder(c->encoder);
327                         continue;
328                 }
329
330                 if (c->encoder->encoder_id  == connector->encoder_id)
331                         break;
332
333                 drmModeFreeEncoder(c->encoder);
334         }
335
336         if (c->crtc == -1)
337                 c->crtc = c->encoder->crtc_id;
338 }
339
340 extern char *optarg;
341 extern int optind, opterr, optopt;
342 static char optstr[] = "ecpmfo:s:v";
343
344 static void usage(char *name)
345 {
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");
357         exit(0);
358 }
359
360 #define dump_resource(res) if (res) dump_##res()
361
362 int main(int argc, char **argv)
363 {
364         int c;
365         int operations = 0, encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
366         int test_vsync = 0;
367         char *modules[] = {"exynos", "i915", "radeon", "nouveau", "vmwgfx"};
368         char *modeset = NULL;
369         int i, count = 0;
370         struct connector con_args[2];
371         
372         opterr = 0;
373         while ((c = getopt(argc, argv, optstr)) != -1) {
374                 switch (c) {
375                 case 'e':
376                         encoders = 1;
377                         break;
378                 case 'c':
379                         connectors = 1;
380                         break;
381                 case 'p':
382                         crtcs = 1;
383                         break;
384                 case 'm':
385                         modes = 1;
386                         break;
387                 case 'f':
388                         framebuffers = 1;
389                         break;
390                 case 'v':
391                         test_vsync = 1;
392                         break;
393                 case 'o':
394                         if (optarg)
395                                 sscanf(optarg, "%d", &operations);
396                         break;
397                 case 's':
398                         modeset = strdup(optarg);
399                         con_args[count].crtc = -1;
400                         if (sscanf(optarg, "%d:%64s",
401                                    &con_args[count].id,
402                                    con_args[count].mode_str) != 2 &&
403                             sscanf(optarg, "%d@%d:%64s",
404                                    &con_args[count].id,
405                                    &con_args[count].crtc,
406                                    con_args[count].mode_str) != 3)
407                                 usage(argv[0]);
408                         count++;
409                         break;
410                 default:
411                         usage(argv[0]);
412                         break;
413                 }
414         }
415
416         if (argc == 1)
417                 encoders = connectors = crtcs = modes = framebuffers = 1;
418
419         for (i = 0; i < ARRAY_SIZE(modules); i++) {
420                 printf("trying to load module %s...", modules[i]);
421                 fd = drmOpen(modules[i], NULL);
422                 if (fd < 0) {
423                         printf("failed.\n");
424                 } else {
425                         printf("success.\n");
426                         break;
427                 }
428         }
429
430         if (i == ARRAY_SIZE(modules)) {
431                 fprintf(stderr, "failed to load any modules, aborting.\n");
432                 return -1;
433         }
434
435         resources = drmModeGetResources(fd);
436         if (!resources) {
437                 fprintf(stderr, "drmModeGetResources failed: %s\n",
438                         strerror(errno));
439                 drmClose(fd);
440                 return 1;
441         }
442
443         dump_resource(encoders);
444         dump_resource(connectors);
445         dump_resource(crtcs);
446         dump_resource(framebuffers);
447
448         if (count > 0) {
449                 long int sum = 0, usec[MAX_LOOP];
450
451                 switch(operations) {
452                 case 0:
453                         fimc_m2m_set_mode(con_args, count, test_vsync, usec);
454                         break;
455                 case 1:
456                         fimc_wb_set_mode(con_args, count, test_vsync, usec);
457                         break;
458                 case 2:
459                         fimc_output_set_mode(con_args, count, test_vsync, usec);
460                         break;
461                 default:
462                         break;
463                 }
464
465                 for (i = 0; i < MAX_LOOP; i++) {
466                         printf("[%d] : %d\n", i + 1, usec[i]);
467                         sum += usec[i];
468                 }
469                 printf("fimc : cma\n");
470                 printf("avg : [%d]\n", sum / MAX_LOOP);
471                 getchar();
472         }
473
474         drmModeFreeResources(resources);
475
476         return 0;
477 }