66c7f9cd3b2d1c7a657ee256674ea3268b5f8020
[platform/upstream/libdrm.git] / tests / modetest / modetest.c
1 /*
2  * DRM based mode setting test program
3  * Copyright 2008 Tungsten Graphics
4  *   Jakob Bornecrantz <jakob@tungstengraphics.com>
5  * Copyright 2008 Intel Corporation
6  *   Jesse Barnes <jesse.barnes@intel.com>
7  */
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15
16 #include "xf86drm.h"
17 #include "xf86drmMode.h"
18 #include "intel_bufmgr.h"
19
20 drmModeRes *resources;
21 int fd, modes;
22
23 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
24
25 struct type_name {
26         int type;
27         char *name;
28 };
29
30 #define type_name_fn(res) \
31 char * res##_str(int type) {                    \
32         int i;                                          \
33         for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
34                 if (res##_names[i].type == type)        \
35                         return res##_names[i].name;     \
36         }                                               \
37         return "(invalid)";                             \
38 }
39
40 struct type_name encoder_type_names[] = {
41         { DRM_MODE_ENCODER_NONE, "none" },
42         { DRM_MODE_ENCODER_DAC, "DAC" },
43         { DRM_MODE_ENCODER_TMDS, "TMDS" },
44         { DRM_MODE_ENCODER_LVDS, "LVDS" },
45         { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
46 };
47
48 type_name_fn(encoder_type)
49
50 struct type_name connector_status_names[] = {
51         { DRM_MODE_CONNECTED, "connected" },
52         { DRM_MODE_DISCONNECTED, "disconnected" },
53         { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
54 };
55
56 type_name_fn(connector_status)
57
58 struct type_name connector_type_names[] = {
59         { DRM_MODE_CONNECTOR_Unknown, "unknown" },
60         { DRM_MODE_CONNECTOR_VGA, "VGA" },
61         { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
62         { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
63         { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
64         { DRM_MODE_CONNECTOR_Composite, "composite" },
65         { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
66         { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
67         { DRM_MODE_CONNECTOR_Component, "component" },
68         { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
69         { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
70         { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
71         { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
72 };
73
74 type_name_fn(connector_type)
75
76 void dump_encoders(void)
77 {
78         drmModeEncoder *encoder;
79         int i;
80
81         printf("Encoders:\n");
82         printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
83         for (i = 0; i < resources->count_encoders; i++) {
84                 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
85
86                 if (!encoder) {
87                         fprintf(stderr, "could not get encoder %i: %s\n",
88                                 resources->encoders[i], strerror(errno));
89                         continue;
90                 }
91                 printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
92                        encoder->encoder_id,
93                        encoder->crtc_id,
94                        encoder_type_str(encoder->encoder_type),
95                        encoder->possible_crtcs,
96                        encoder->possible_clones);
97                 drmModeFreeEncoder(encoder);
98         }
99 }
100
101 void dump_connectors(void)
102 {
103         drmModeConnector *connector;
104         int i, j;
105
106         printf("Connectors:\n");
107         printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
108         for (i = 0; i < resources->count_connectors; i++) {
109                 connector = drmModeGetConnector(fd, resources->connectors[i]);
110
111                 if (!connector) {
112                         fprintf(stderr, "could not get connector %i: %s\n",
113                                 resources->connectors[i], strerror(errno));
114                         continue;
115                 }
116
117                 printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
118                        connector->connector_id,
119                        connector->encoder_id,
120                        connector_status_str(connector->connection),
121                        connector_type_str(connector->connector_type),
122                        connector->mmWidth, connector->mmHeight,
123                        connector->count_modes);
124
125                 if (!connector->count_modes)
126                         continue;
127
128                 printf("  modes:\n");
129                 printf("  name refresh (Hz) hdisp hss hse htot vdisp "
130                        "vss vse vtot)\n");
131                 for (j = 0; j < connector->count_modes; j++) {
132                         struct drm_mode_modeinfo *mode;
133
134                         mode = &connector->modes[j];
135                         printf("  %s %.02f %d %d %d %d %d %d %d %d\n",
136                                mode->name,
137                                (float)mode->vrefresh / 1000,
138                                mode->hdisplay,
139                                mode->hsync_start,
140                                mode->hsync_end,
141                                mode->htotal,
142                                mode->vdisplay,
143                                mode->vsync_start,
144                                mode->vsync_end,
145                                mode->vtotal);
146                 }
147                 drmModeFreeConnector(connector);
148         }
149 }
150
151 void dump_crtcs(void)
152 {
153         drmModeCrtc *crtc;
154         int i;
155
156         for (i = 0; i < resources->count_crtcs; i++) {
157                 crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
158
159                 if (!crtc) {
160                         fprintf(stderr, "could not get crtc %i: %s\n",
161                                 resources->crtcs[i], strerror(errno));
162                         continue;
163                 }
164                 drmModeFreeCrtc(crtc);
165         }
166 }
167
168 void dump_framebuffers(void)
169 {
170         drmModeFB *fb;
171         int i;
172
173         for (i = 0; i < resources->count_fbs; i++) {
174                 fb = drmModeGetFB(fd, resources->fbs[i]);
175
176                 if (!fb) {
177                         fprintf(stderr, "could not get fb %i: %s\n",
178                                 resources->fbs[i], strerror(errno));
179                         continue;
180                 }
181                 drmModeFreeFB(fb);
182         }
183 }
184
185 void set_mode(int connector_id, char *mode_str)
186 {
187         drmModeConnector *connector;
188         drmModeEncoder *encoder = NULL;
189         struct drm_mode_modeinfo *mode = NULL;
190         drm_intel_bufmgr *bufmgr;
191         drm_intel_bo *bo;
192         unsigned int fb_id, *fb_ptr;
193         int i, j, size, ret, width, height;
194
195         /* First, find the connector & mode */
196         for (i = 0; i < resources->count_connectors; i++) {
197                 connector = drmModeGetConnector(fd, resources->connectors[i]);
198
199                 if (!connector) {
200                         fprintf(stderr, "could not get connector %i: %s\n",
201                                 resources->connectors[i], strerror(errno));
202                         drmModeFreeConnector(connector);
203                         continue;
204                 }
205
206                 if (!connector->count_modes) {
207                         drmModeFreeConnector(connector);
208                         continue;
209                 }
210
211                 if (connector->connector_id != connector_id) {
212                         drmModeFreeConnector(connector);
213                         continue;
214                 }
215
216                 for (j = 0; j < connector->count_modes; j++) {
217                         mode = &connector->modes[j];
218                         if (!strcmp(mode->name, mode_str))
219                                 break;
220                 }
221
222                 /* Found it, break out */
223                 if (mode)
224                         break;
225
226                 drmModeFreeConnector(connector);
227         }
228
229         if (!mode) {
230                 fprintf(stderr, "failed to find mode \"%s\"\n", mode_str);
231                 return;
232         }
233
234         width = mode->hdisplay;
235         height = mode->vdisplay;
236
237         /* Now get the encoder */
238         for (i = 0; i < resources->count_encoders; i++) {
239                 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
240
241                 if (!encoder) {
242                         fprintf(stderr, "could not get encoder %i: %s\n",
243                                 resources->encoders[i], strerror(errno));
244                         drmModeFreeEncoder(encoder);
245                         continue;
246                 }
247
248                 if (encoder->encoder_id  == connector->encoder_id)
249                         break;
250
251                 drmModeFreeEncoder(encoder);
252         }
253
254         bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
255         if (!bufmgr) {
256                 fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
257                 return;
258         }
259
260         /* Mode size at 32 bpp */
261         size = width * height * 4;
262
263         bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096);
264         if (!bo) {
265                 fprintf(stderr, "failed to alloc buffer: %s\n",
266                         strerror(errno));
267                 return;
268         }
269
270         ret = drm_intel_bo_pin(bo, 4096);
271         if (ret) {
272                 fprintf(stderr, "failed to pin buffer: %s\n", strerror(errno));
273                 return;
274         }
275
276         ret = drm_intel_gem_bo_map_gtt(bo);
277         if (ret) {
278                 fprintf(stderr, "failed to GTT map buffer: %s\n",
279                         strerror(errno));
280                 return;
281         }
282
283         fb_ptr = bo->virtual;
284
285         /* paint the buffer blue */
286         for (i = 0; i < width * height; i++)
287                 fb_ptr[i] = 0xff;
288
289         ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, bo->handle,
290                            &fb_id);
291         if (ret) {
292                 fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
293                 return;
294         }
295
296         ret = drmModeSetCrtc(fd, encoder->crtc_id, fb_id, 0, 0,
297                              &connector->connector_id, 1, mode);
298         if (ret) {
299                 fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
300                 return;
301         }
302 }
303
304 extern char *optarg;
305 extern int optind, opterr, optopt;
306 static char optstr[] = "ecpmfs:";
307
308 void usage(char *name)
309 {
310         fprintf(stderr, "usage: %s [-ecpmf]\n", name);
311         fprintf(stderr, "\t-e\tlist encoders\n");
312         fprintf(stderr, "\t-c\tlist connectors\n");
313         fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
314         fprintf(stderr, "\t-m\tlist modes\n");
315         fprintf(stderr, "\t-f\tlist framebuffers\n");
316         fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
317         fprintf(stderr, "\n\tDefault is to dump all info.\n");
318         exit(0);
319 }
320
321 #define dump_resource(res) if (res) dump_##res()
322
323 int main(int argc, char **argv)
324 {
325         int c;
326         int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
327         char *modules[] = { "i915", "radeon" };
328         char *modeset = NULL, *mode, *connector;
329         int i, connector_id;
330
331         opterr = 0;
332         while ((c = getopt(argc, argv, optstr)) != -1) {
333                 switch (c) {
334                 case 'e':
335                         encoders = 1;
336                         break;
337                 case 'c':
338                         connectors = 1;
339                         break;
340                 case 'p':
341                         crtcs = 1;
342                         break;
343                 case 'm':
344                         modes = 1;
345                         break;
346                 case 'f':
347                         framebuffers = 1;
348                         break;
349                 case 's':
350                         modeset = strdup(optarg);
351                         break;
352                 default:
353                         usage(argv[0]);
354                         break;
355                 }
356         }
357
358         if (argc == 1)
359                 encoders = connectors = crtcs = modes = framebuffers = 1;
360
361         for (i = 0; i < ARRAY_SIZE(modules); i++) {
362                 printf("trying to load module %s...", modules[i]);
363                 fd = drmOpen(modules[i], NULL);
364                 if (fd < 0) {
365                         printf("failed.\n");
366                 } else {
367                         printf("success.\n");
368                         break;
369                 }
370         }
371
372         if (i == ARRAY_SIZE(modules)) {
373                 fprintf(stderr, "failed to load any modules, aborting.\n");
374                 return -1;
375         }
376
377         resources = drmModeGetResources(fd);
378         if (!resources) {
379                 fprintf(stderr, "drmModeGetResources failed: %s\n",
380                         strerror(errno));
381                 drmClose(fd);
382                 return 1;
383         }
384
385         dump_resource(encoders);
386         dump_resource(connectors);
387         dump_resource(crtcs);
388         dump_resource(framebuffers);
389
390         if (modeset) {
391                 connector = strtok(modeset, ":");
392                 if (!connector)
393                         usage(argv[0]);
394                 connector_id = atoi(connector);
395
396                 mode = strtok(NULL, ":");
397                 if (!mode)
398                         usage(argv[0]);
399                 printf("setting connector %d to mode %s\n", connector_id,
400                        mode);
401                 set_mode(connector_id, mode);
402                 sleep(3);
403         }
404
405         sleep(3);
406
407         drmModeFreeResources(resources);
408
409         return 0;
410 }