lib/igt_kms: Clean up the other _name functions/macros
[platform/upstream/intel-gpu-tools.git] / lib / igt_kms.c
1 /*
2  * Copyright © 2013 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *      Daniel Vetter <daniel.vetter@ffwll.ch>
25  *      Damien Lespiau <damien.lespiau@intel.com>
26  */
27
28 #define _GNU_SOURCE
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <fcntl.h>
33 #include <sys/stat.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <linux/kd.h>
37 #include <errno.h>
38
39 #include <i915_drm.h>
40
41 #include "drmtest.h"
42 #include "igt_kms.h"
43 #include "igt_aux.h"
44
45 /*
46  * There hasn't been a release of libdrm containing these #define's yet, so
47  * copy them here to allow compilation to succeed in the mean time.
48  *
49  * We can drop these #define's and just make i-g-t depend on the proper libdrm
50  * version in the future.
51  */
52 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
53 #define DRM_PLANE_TYPE_OVERLAY 0
54 #define DRM_PLANE_TYPE_PRIMARY 1
55 #define DRM_PLANE_TYPE_CURSOR  2
56
57
58
59 /**
60  * SECTION:igt_kms
61  * @short_description: Kernel modesetting support library
62  * @title: i-g-t kms
63  * @include: igt_kms.h
64  *
65  * This library provides support to enumerate and set modeset configurations.
66  *
67  * Since this library is very much still a work-in-progress and the interfaces
68  * still in-flux detailed api documentation is currently still missing.
69  *
70  * Note that this library's header pulls in the [i-g-t framebuffer](intel-gpu-tools-i-g-t-framebuffer.html)
71  * library as a dependency.
72  */
73
74 /**
75  * kmstest_pipe_name:
76  * @pipe: display pipe
77  *
78  * Returns: String represnting @pipe, e.g. "A".
79  */
80 const char *kmstest_pipe_name(enum pipe pipe)
81 {
82         const char *str[] = { "A", "B", "C" };
83
84         if (pipe > 2)
85                 return "invalid";
86
87         return str[pipe];
88 }
89
90 /**
91  * kmstest_plane_name:
92  * @plane: display plane
93  *
94  * Returns: String represnting @pipe, e.g. "plane1".
95  */
96 const char *kmstest_plane_name(enum igt_plane plane)
97 {
98         static const char *names[] = {
99                 [IGT_PLANE_1] = "plane1",
100                 [IGT_PLANE_2] = "plane2",
101                 [IGT_PLANE_3] = "plane3",
102                 [IGT_PLANE_CURSOR] = "cursor",
103         };
104
105         igt_assert(plane < ARRAY_SIZE(names) && names[plane]);
106
107         return names[plane];
108 }
109
110 struct type_name {
111         int type;
112         const char *name;
113 };
114
115 #define type_name_fn(res) \
116 const char * kmstest_##res##_str(int type) {            \
117         unsigned int i;                                 \
118         for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
119                 if (res##_names[i].type == type)        \
120                         return res##_names[i].name;     \
121         }                                               \
122         return "(invalid)";                             \
123 }
124
125 struct type_name encoder_type_names[] = {
126         { DRM_MODE_ENCODER_NONE, "none" },
127         { DRM_MODE_ENCODER_DAC, "DAC" },
128         { DRM_MODE_ENCODER_TMDS, "TMDS" },
129         { DRM_MODE_ENCODER_LVDS, "LVDS" },
130         { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
131 };
132
133 type_name_fn(encoder_type)
134
135 struct type_name connector_status_names[] = {
136         { DRM_MODE_CONNECTED, "connected" },
137         { DRM_MODE_DISCONNECTED, "disconnected" },
138         { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
139 };
140
141 type_name_fn(connector_status)
142
143 struct type_name connector_type_names[] = {
144         { DRM_MODE_CONNECTOR_Unknown, "unknown" },
145         { DRM_MODE_CONNECTOR_VGA, "VGA" },
146         { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
147         { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
148         { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
149         { DRM_MODE_CONNECTOR_Composite, "composite" },
150         { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
151         { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
152         { DRM_MODE_CONNECTOR_Component, "component" },
153         { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
154         { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
155         { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
156         { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
157         { DRM_MODE_CONNECTOR_TV, "TV" },
158         { DRM_MODE_CONNECTOR_eDP, "eDP" },
159 };
160
161 type_name_fn(connector_type)
162
163 static const char *mode_stereo_name(const drmModeModeInfo *mode)
164 {
165         switch (mode->flags & DRM_MODE_FLAG_3D_MASK) {
166         case DRM_MODE_FLAG_3D_FRAME_PACKING:
167                 return "FP";
168         case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
169                 return "FA";
170         case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
171                 return "LA";
172         case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
173                 return "SBSF";
174         case DRM_MODE_FLAG_3D_L_DEPTH:
175                 return "LD";
176         case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
177                 return "LDGFX";
178         case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
179                 return "TB";
180         case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
181                 return "SBSH";
182         default:
183                 return NULL;
184         }
185 }
186
187 /**
188  * kmstest_dump_mode:
189  * @mode: libdrm mode structure
190  *
191  * Prints @mode to stdout in a huma-readable form.
192  */
193 void kmstest_dump_mode(drmModeModeInfo *mode)
194 {
195         const char *stereo = mode_stereo_name(mode);
196
197         printf("  %s %d %d %d %d %d %d %d %d %d 0x%x 0x%x %d%s%s%s\n",
198                mode->name,
199                mode->vrefresh,
200                mode->hdisplay,
201                mode->hsync_start,
202                mode->hsync_end,
203                mode->htotal,
204                mode->vdisplay,
205                mode->vsync_start,
206                mode->vsync_end,
207                mode->vtotal,
208                mode->flags,
209                mode->type,
210                mode->clock,
211                stereo ? " (3D:" : "",
212                stereo ? stereo : "",
213                stereo ? ")" : "");
214         fflush(stdout);
215 }
216
217 int kmstest_get_pipe_from_crtc_id(int fd, int crtc_id)
218 {
219         struct drm_i915_get_pipe_from_crtc_id pfci;
220         int ret;
221
222         memset(&pfci, 0, sizeof(pfci));
223         pfci.crtc_id = crtc_id;
224         ret = drmIoctl(fd, DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID, &pfci);
225         igt_assert(ret == 0);
226
227         return pfci.pipe;
228 }
229
230 void kmstest_set_connector_dpms(int fd, drmModeConnector *connector, int mode)
231 {
232         int i, dpms = 0;
233         bool found_it = false;
234
235         for (i = 0; i < connector->count_props; i++) {
236                 struct drm_mode_get_property prop;
237
238                 prop.prop_id = connector->props[i];
239                 prop.count_values = 0;
240                 prop.count_enum_blobs = 0;
241                 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
242                         continue;
243
244                 if (strcmp(prop.name, "DPMS"))
245                         continue;
246
247                 dpms = prop.prop_id;
248                 found_it = true;
249                 break;
250         }
251         igt_assert_f(found_it, "DPMS property not found on %d\n",
252                      connector->connector_id);
253
254         igt_assert(drmModeConnectorSetProperty(fd, connector->connector_id,
255                                                dpms, mode) == 0);
256 }
257
258 static signed long set_vt_mode(unsigned long mode)
259 {
260         int fd;
261         unsigned long prev_mode;
262
263         fd = open("/dev/tty0", O_RDONLY);
264         if (fd < 0)
265                 return -errno;
266
267         prev_mode = 0;
268         if (drmIoctl(fd, KDGETMODE, &prev_mode))
269                 goto err;
270         if (drmIoctl(fd, KDSETMODE, (void *)mode))
271                 goto err;
272
273         close(fd);
274
275         return prev_mode;
276 err:
277         close(fd);
278
279         return -errno;
280 }
281
282 static unsigned long orig_vt_mode = -1UL;
283
284 static void restore_vt_mode_at_exit(int sig)
285 {
286         if (orig_vt_mode != -1UL)
287                 set_vt_mode(orig_vt_mode);
288 }
289
290 /*
291  * Set the VT to graphics mode and install an exit handler to restore the
292  * original mode.
293  */
294
295 void igt_set_vt_graphics_mode(void)
296 {
297         long ret;
298
299         igt_install_exit_handler(restore_vt_mode_at_exit);
300
301         igt_disable_exit_handler();
302         ret = set_vt_mode(KD_GRAPHICS);
303         igt_enable_exit_handler();
304
305         igt_assert(ret >= 0);
306         orig_vt_mode = ret;
307 }
308
309 int kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
310                                       drmModeModeInfo *mode)
311 {
312         int i;
313
314         if (!connector->count_modes) {
315                 fprintf(stderr, "no modes for connector %d\n",
316                         connector->connector_id);
317                 return -1;
318         }
319
320         for (i = 0; i < connector->count_modes; i++) {
321                 if (i == 0 ||
322                     connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
323                         *mode = connector->modes[i];
324                         if (mode->type & DRM_MODE_TYPE_PREFERRED)
325                                 break;
326                 }
327         }
328
329         return 0;
330 }
331
332 int kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
333                                  unsigned long crtc_idx_mask,
334                                  struct kmstest_connector_config *config)
335 {
336         drmModeRes *resources;
337         drmModeConnector *connector;
338         drmModeEncoder *encoder;
339         int i, j;
340
341         resources = drmModeGetResources(drm_fd);
342         if (!resources) {
343                 perror("drmModeGetResources failed");
344                 goto err1;
345         }
346
347         /* First, find the connector & mode */
348         connector = drmModeGetConnector(drm_fd, connector_id);
349         if (!connector)
350                 goto err2;
351
352         if (connector->connection != DRM_MODE_CONNECTED)
353                 goto err3;
354
355         if (!connector->count_modes) {
356                 fprintf(stderr, "connector %d has no modes\n", connector_id);
357                 goto err3;
358         }
359
360         if (connector->connector_id != connector_id) {
361                 fprintf(stderr, "connector id doesn't match (%d != %d)\n",
362                         connector->connector_id, connector_id);
363                 goto err3;
364         }
365
366         /*
367          * Find given CRTC if crtc_id != 0 or else the first CRTC not in use.
368          * In both cases find the first compatible encoder and skip the CRTC
369          * if there is non such.
370          */
371         encoder = NULL;         /* suppress GCC warning */
372         for (i = 0; i < resources->count_crtcs; i++) {
373                 if (!resources->crtcs[i] || !(crtc_idx_mask & (1 << i)))
374                         continue;
375
376                 /* Now get a compatible encoder */
377                 for (j = 0; j < connector->count_encoders; j++) {
378                         encoder = drmModeGetEncoder(drm_fd,
379                                                     connector->encoders[j]);
380
381                         if (!encoder) {
382                                 fprintf(stderr, "could not get encoder %d: %s\n",
383                                         resources->encoders[j], strerror(errno));
384
385                                 continue;
386                         }
387
388                         if (encoder->possible_crtcs & (1 << i))
389                                 goto found;
390
391                         drmModeFreeEncoder(encoder);
392                 }
393         }
394
395         goto err3;
396
397 found:
398         if (kmstest_get_connector_default_mode(drm_fd, connector,
399                                        &config->default_mode) < 0)
400                 goto err4;
401
402         config->connector = connector;
403         config->encoder = encoder;
404         config->crtc = drmModeGetCrtc(drm_fd, resources->crtcs[i]);
405         config->crtc_idx = i;
406         config->pipe = kmstest_get_pipe_from_crtc_id(drm_fd,
407                                                      config->crtc->crtc_id);
408
409         drmModeFreeResources(resources);
410
411         return 0;
412 err4:
413         drmModeFreeEncoder(encoder);
414 err3:
415         drmModeFreeConnector(connector);
416 err2:
417         drmModeFreeResources(resources);
418 err1:
419         return -1;
420 }
421
422 static int get_card_number(int fd)
423 {
424         struct stat buf;
425
426         /* find the minor number of the device */
427         fstat(fd, &buf);
428
429         return minor(buf.st_rdev) & 0x3f;
430 }
431
432 static char* get_debugfs_connector_path(int drm_fd, drmModeConnector *connector,
433                                         const char *file)
434 {
435         char *path;
436
437         asprintf(&path, "/sys/kernel/debug/dri/%d/%s-%d/%s",
438                  get_card_number(drm_fd),
439                  kmstest_connector_type_str(connector->connector_type),
440                  connector->connector_type_id,
441                  file);
442
443         return path;
444 }
445
446 /**
447  * kmstest_force_connector:
448  * @fd: drm file descriptor
449  * @connector: connector
450  * @state: state to force on @connector
451  *
452  * Force the specified state on the specified connector.
453  *
454  * Returns: true on success
455  */
456 bool kmstest_force_connector(int drm_fd, drmModeConnector *connector,
457                              enum kmstest_force_connector_state state)
458 {
459         char *path;
460         const char *value;
461         int debugfs_fd, ret;
462
463         switch (state) {
464         case FORCE_CONNECTOR_ON:
465                 value = "on";
466                 break;
467         case FORCE_CONNECTOR_DIGITAL:
468                 value = "digital";
469                 break;
470         case FORCE_CONNECTOR_OFF:
471                 value = "off";
472                 break;
473
474         default:
475         case FORCE_CONNECTOR_UNSPECIFIED:
476                 value = "unspecified";
477                 break;
478         }
479
480         path = get_debugfs_connector_path(drm_fd, connector, "force");
481         debugfs_fd = open(path, O_WRONLY | O_TRUNC);
482         free(path);
483
484         if (debugfs_fd == -1) {
485                 return false;
486         }
487
488         ret = write(debugfs_fd, value, strlen(value));
489         close(debugfs_fd);
490
491         igt_assert(ret != -1);
492         return (ret == -1) ? false : true;
493 }
494
495 /**
496  * kmstest_force_edid:
497  * @drm_fd: drm file descriptor
498  * @connector: connector to set @edid on
499  * @edid: An EDID data block
500  * @length: length of the EDID data. #EDID_LENGTH defines the standard EDID
501  * length
502  *
503  * Set the EDID data on @connector to @edid. See #generic_edid and
504  * #kmstest_generic_edid for a set of generic EDID data blocks.
505  *
506  * If @length is zero, the forced EDID will be removed.
507  */
508 void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
509                         const unsigned char *edid, size_t length)
510 {
511         char *path;
512         int debugfs_fd, ret;
513
514         path = get_debugfs_connector_path(drm_fd, connector, "edid_override");
515
516         debugfs_fd = open(path, O_WRONLY | O_TRUNC);
517
518         free(path);
519
520         igt_assert(debugfs_fd != -1);
521
522         if (length == 0)
523                 ret = write(debugfs_fd, "reset", 5);
524         else
525                 ret = write(debugfs_fd, edid, length);
526         close(debugfs_fd);
527
528         igt_assert(ret != -1);
529 }
530
531 void kmstest_free_connector_config(struct kmstest_connector_config *config)
532 {
533         drmModeFreeCrtc(config->crtc);
534         drmModeFreeEncoder(config->encoder);
535         drmModeFreeConnector(config->connector);
536 }
537
538 /*
539  * A small modeset API
540  */
541
542 #define LOG_SPACES              "    "
543 #define LOG_N_SPACES            (sizeof(LOG_SPACES) - 1)
544
545 #define LOG_INDENT(d, section)                          \
546         do {                                            \
547                 igt_display_log(d, "%s {\n", section);  \
548                 igt_display_log_shift(d, 1);            \
549         } while (0)
550 #define LOG_UNINDENT(d)                                 \
551         do {                                            \
552                 igt_display_log_shift(d, -1);           \
553                 igt_display_log(d, "}\n");              \
554         } while (0)
555 #define LOG(d, fmt, ...)        igt_display_log(d, fmt, ## __VA_ARGS__)
556
557 static void  __attribute__((format(printf, 2, 3)))
558 igt_display_log(igt_display_t *display, const char *fmt, ...)
559 {
560         va_list args;
561         int i;
562
563         va_start(args, fmt);
564         igt_debug("display: ");
565         for (i = 0; i < display->log_shift; i++)
566                 igt_debug("%s", LOG_SPACES);
567         igt_vlog(IGT_LOG_DEBUG, fmt, args);
568         va_end(args);
569 }
570
571 static void igt_display_log_shift(igt_display_t *display, int shift)
572 {
573         display->log_shift += shift;
574         igt_assert(display->log_shift >= 0);
575 }
576
577 static void igt_output_refresh(igt_output_t *output)
578 {
579         igt_display_t *display = output->display;
580         int ret;
581         unsigned long crtc_idx_mask;
582
583         /* we mask out the pipes already in use */
584         crtc_idx_mask = output->pending_crtc_idx_mask & ~display->pipes_in_use;
585
586         if (output->valid)
587                 kmstest_free_connector_config(&output->config);
588         ret = kmstest_get_connector_config(display->drm_fd,
589                                            output->id,
590                                            crtc_idx_mask,
591                                            &output->config);
592         if (ret == 0)
593                 output->valid = true;
594         else
595                 output->valid = false;
596
597         if (!output->valid)
598                 return;
599
600         if (!output->name) {
601                 drmModeConnector *c = output->config.connector;
602
603                 asprintf(&output->name, "%s-%d",
604                          kmstest_connector_type_str(c->connector_type),
605                          c->connector_type_id);
606         }
607
608         LOG(display, "%s: Selecting pipe %s\n", output->name,
609             kmstest_pipe_name(output->config.pipe));
610
611         display->pipes_in_use |= 1 << output->config.pipe;
612 }
613
614 /**
615  * kmstest_get_property:
616  * @drm_fd: drm file descriptor
617  * @object_id: object whose properties we're going to get
618  * @object_type: type of obj_id (DRM_MODE_OBJECT_*)
619  * @name: name of the property we're going to get
620  * @prop_id: if not NULL, returns the property id
621  * @value: if not NULL, returns the property value
622  * @prop: if not NULL, returns the property, and the caller will have to free
623  *        it manually.
624  *
625  * Finds a property with the given name on the given object.
626  *
627  * Returns: true in case we found something.
628  */
629 bool
630 kmstest_get_property(int drm_fd, uint32_t object_id, uint32_t object_type,
631                      const char *name, uint32_t *prop_id /* out */,
632                      uint64_t *value /* out */,
633                      drmModePropertyPtr *prop /* out */)
634 {
635         drmModeObjectPropertiesPtr proplist;
636         drmModePropertyPtr _prop;
637         bool found = false;
638         int i;
639
640         proplist = drmModeObjectGetProperties(drm_fd, object_id, object_type);
641         for (i = 0; i < proplist->count_props; i++) {
642                 _prop = drmModeGetProperty(drm_fd, proplist->props[i]);
643                 if (!_prop)
644                         continue;
645
646                 if (strcmp(_prop->name, name) == 0) {
647                         found = true;
648                         if (prop_id)
649                                 *prop_id = proplist->props[i];
650                         if (value)
651                                 *value = proplist->prop_values[i];
652                         if (prop)
653                                 *prop = _prop;
654                         else
655                                 drmModeFreeProperty(_prop);
656
657                         break;
658                 }
659                 drmModeFreeProperty(_prop);
660         }
661
662         drmModeFreeObjectProperties(proplist);
663         return found;
664 }
665
666 static bool
667 get_plane_property(int drm_fd, uint32_t plane_id, const char *name,
668                    uint32_t *prop_id /* out */, uint64_t *value /* out */,
669                    drmModePropertyPtr *prop /* out */)
670 {
671         return kmstest_get_property(drm_fd, plane_id, DRM_MODE_OBJECT_PLANE,
672                                     name, prop_id, value, prop);
673 }
674
675 static void
676 igt_plane_set_property(igt_plane_t *plane, uint32_t prop_id, uint64_t value)
677 {
678         igt_pipe_t *pipe = plane->pipe;
679         igt_display_t *display = pipe->display;
680
681         drmModeObjectSetProperty(display->drm_fd, plane->drm_plane->plane_id,
682                                  DRM_MODE_OBJECT_PLANE, prop_id, value);
683 }
684
685 /*
686  * Walk a plane's property list to determine its type.  If we don't
687  * find a type property, then the kernel doesn't support universal
688  * planes and we know the plane is an overlay/sprite.
689  */
690 static int get_drm_plane_type(int drm_fd, uint32_t plane_id)
691 {
692         uint64_t value;
693         bool has_prop;
694
695         has_prop = get_plane_property(drm_fd, plane_id, "type",
696                                       NULL /* prop_id */, &value, NULL);
697         if (has_prop)
698                 return (int)value;
699
700         return DRM_PLANE_TYPE_OVERLAY;
701 }
702
703 void igt_display_init(igt_display_t *display, int drm_fd)
704 {
705         drmModeRes *resources;
706         drmModePlaneRes *plane_resources;
707         int i;
708
709         memset(display, 0, sizeof(igt_display_t));
710
711         LOG_INDENT(display, "init");
712
713         display->drm_fd = drm_fd;
714
715         resources = drmModeGetResources(display->drm_fd);
716         igt_assert(resources);
717
718         /*
719          * We cache the number of pipes, that number is a physical limit of the
720          * hardware and cannot change of time (for now, at least).
721          */
722         display->n_pipes = resources->count_crtcs;
723
724         drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
725         plane_resources = drmModeGetPlaneResources(display->drm_fd);
726         igt_assert(plane_resources);
727
728         for (i = 0; i < display->n_pipes; i++) {
729                 igt_pipe_t *pipe = &display->pipes[i];
730                 igt_plane_t *plane;
731                 int p = IGT_PLANE_2;
732                 int j, type;
733
734                 pipe->display = display;
735                 pipe->pipe = i;
736
737                 /* add the planes that can be used with that pipe */
738                 for (j = 0; j < plane_resources->count_planes; j++) {
739                         drmModePlane *drm_plane;
740                         uint64_t prop_value;
741
742                         drm_plane = drmModeGetPlane(display->drm_fd,
743                                                     plane_resources->planes[j]);
744                         igt_assert(drm_plane);
745
746                         if (!(drm_plane->possible_crtcs & (1 << i))) {
747                                 drmModeFreePlane(drm_plane);
748                                 continue;
749                         }
750
751                         type = get_drm_plane_type(display->drm_fd,
752                                                   plane_resources->planes[j]);
753                         switch (type) {
754                         case DRM_PLANE_TYPE_PRIMARY:
755                                 plane = &pipe->planes[IGT_PLANE_PRIMARY];
756                                 plane->is_primary = 1;
757                                 plane->index = IGT_PLANE_PRIMARY;
758                                 display->has_universal_planes = 1;
759                                 break;
760                         case DRM_PLANE_TYPE_CURSOR:
761                                 /*
762                                  * Cursor should be the highest index in our
763                                  * internal list, but we don't know what that
764                                  * is yet.  Just stick it in the last slot
765                                  * for now and we'll move it later, if
766                                  * necessary.
767                                  */
768                                 plane = &pipe->planes[IGT_PLANE_CURSOR];
769                                 plane->is_cursor = 1;
770                                 plane->index = IGT_PLANE_CURSOR;
771                                 display->has_universal_planes = 1;
772                                 break;
773                         default:
774                                 plane = &pipe->planes[p];
775                                 plane->index = p++;
776                                 break;
777                         }
778
779                         plane->pipe = pipe;
780                         plane->drm_plane = drm_plane;
781
782                         get_plane_property(display->drm_fd, drm_plane->plane_id,
783                                            "rotation",
784                                            &plane->rotation_property,
785                                            &prop_value,
786                                            NULL);
787                         plane->rotation = (igt_rotation_t)prop_value;
788                 }
789
790                 if (display->has_universal_planes) {
791                         /*
792                          * If we have universal planes, we should have both
793                          * primary and cursor planes setup now.
794                          */
795                         igt_assert(pipe->planes[IGT_PLANE_PRIMARY].drm_plane &&
796                                    pipe->planes[IGT_PLANE_CURSOR].drm_plane);
797
798                         /*
799                          * Cursor was put in the last slot.  If we have 0 or
800                          * only 1 sprite, that's the wrong slot and we need to
801                          * move it down.
802                          */
803                         if (p != IGT_PLANE_CURSOR) {
804                                 pipe->planes[p] = pipe->planes[IGT_PLANE_CURSOR];
805                                 pipe->planes[p].index = p;
806                                 memset(&pipe->planes[IGT_PLANE_CURSOR], 0,
807                                        sizeof *plane);
808                         }
809                 } else {
810                         /*
811                          * No universal plane support.  Add drm_plane-less
812                          * primary and cursor planes.
813                          */
814                         plane = &pipe->planes[IGT_PLANE_PRIMARY];
815                         plane->pipe = pipe;
816                         plane->index = IGT_PLANE_PRIMARY;
817                         plane->is_primary = true;
818
819                         plane = &pipe->planes[p];
820                         plane->pipe = pipe;
821                         plane->index = p;
822                         plane->is_cursor = true;
823                 }
824
825                 /* planes = 1 primary, (p-1) sprites, 1 cursor */
826                 pipe->n_planes = p + 1;
827
828                 /* make sure we don't overflow the plane array */
829                 igt_assert(pipe->n_planes <= IGT_MAX_PLANES);
830         }
831
832         /*
833          * The number of connectors is set, so we just initialize the outputs
834          * array in _init(). This may change when we need dynamic connectors
835          * (say DisplayPort MST).
836          */
837         display->n_outputs = resources->count_connectors;
838         display->outputs = calloc(display->n_outputs, sizeof(igt_output_t));
839         igt_assert(display->outputs);
840
841         for (i = 0; i < display->n_outputs; i++) {
842                 igt_output_t *output = &display->outputs[i];
843
844                 /*
845                  * We're free to select any pipe to drive that output until
846                  * a constraint is set with igt_output_set_pipe().
847                  */
848                 output->pending_crtc_idx_mask = -1UL;
849                 output->id = resources->connectors[i];
850                 output->display = display;
851
852                 igt_output_refresh(output);
853         }
854
855         drmModeFreePlaneResources(plane_resources);
856         drmModeFreeResources(resources);
857
858         LOG_UNINDENT(display);
859 }
860
861 int igt_display_get_n_pipes(igt_display_t *display)
862 {
863         return display->n_pipes;
864 }
865
866 static void igt_pipe_fini(igt_pipe_t *pipe)
867 {
868         int i;
869
870         for (i = 0; i < pipe->n_planes; i++) {
871                 igt_plane_t *plane = &pipe->planes[i];
872
873                 if (plane->drm_plane) {
874                         drmModeFreePlane(plane->drm_plane);
875                         plane->drm_plane = NULL;
876                 }
877         }
878 }
879
880 static void igt_output_fini(igt_output_t *output)
881 {
882         if (output->valid)
883                 kmstest_free_connector_config(&output->config);
884         free(output->name);
885 }
886
887 void igt_display_fini(igt_display_t *display)
888 {
889         int i;
890
891         for (i = 0; i < display->n_pipes; i++)
892                 igt_pipe_fini(&display->pipes[i]);
893
894         for (i = 0; i < display->n_outputs; i++)
895                 igt_output_fini(&display->outputs[i]);
896         free(display->outputs);
897         display->outputs = NULL;
898 }
899
900 static void igt_display_refresh(igt_display_t *display)
901 {
902         int i, j;
903
904         display->pipes_in_use = 0;
905
906        /* Check that two outputs aren't trying to use the same pipe */
907         for (i = 0; i < display->n_outputs; i++) {
908                 igt_output_t *a = &display->outputs[i];
909
910                 if (a->pending_crtc_idx_mask == -1UL)
911                         continue;
912
913                 for (j = 0; j < display->n_outputs; j++) {
914                         igt_output_t *b = &display->outputs[j];
915
916                         if (i == j)
917                                 continue;
918
919                         if (b->pending_crtc_idx_mask == -1UL)
920                                 continue;
921
922                         igt_assert_f(a->pending_crtc_idx_mask !=
923                                      b->pending_crtc_idx_mask,
924                                      "%s and %s are both trying to use pipe %s\n",
925                                      igt_output_name(a), igt_output_name(b),
926                                      kmstest_pipe_name(ffs(a->pending_crtc_idx_mask) - 1));
927                 }
928         }
929
930         /*
931          * The pipe allocation has to be done in two phases:
932          *   - first, try to satisfy the outputs where a pipe has been specified
933          *   - then, allocate the outputs with PIPE_ANY
934          */
935         for (i = 0; i < display->n_outputs; i++) {
936                 igt_output_t *output = &display->outputs[i];
937
938                 if (output->pending_crtc_idx_mask == -1UL)
939                         continue;
940
941                 igt_output_refresh(output);
942         }
943         for (i = 0; i < display->n_outputs; i++) {
944                 igt_output_t *output = &display->outputs[i];
945
946                 if (output->pending_crtc_idx_mask != -1UL)
947                         continue;
948
949                 igt_output_refresh(output);
950         }
951 }
952
953 static igt_pipe_t *igt_output_get_driving_pipe(igt_output_t *output)
954 {
955         igt_display_t *display = output->display;
956         enum pipe pipe;
957
958         if (output->pending_crtc_idx_mask == -1UL) {
959                 /*
960                  * The user hasn't specified a pipe to use, take the one
961                  * configured by the last refresh()
962                  */
963                 pipe = output->config.pipe;
964         } else {
965                 /*
966                  * Otherwise, return the pending pipe (ie the pipe that should
967                  * drive this output after the commit()
968                  */
969                 pipe = ffs(output->pending_crtc_idx_mask) - 1;
970         }
971
972         igt_assert(pipe >= 0 && pipe < display->n_pipes);
973
974         return &display->pipes[pipe];
975 }
976
977 static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, enum igt_plane plane)
978 {
979         int idx;
980
981         /* Cursor plane is always the highest index */
982         if (plane == IGT_PLANE_CURSOR)
983                 idx = pipe->n_planes - 1;
984         else {
985                 igt_assert_f(plane >= 0 && plane < (pipe->n_planes),
986                              "plane=%d\n", plane);
987                 idx = plane;
988         }
989
990         return &pipe->planes[idx];
991 }
992
993 static uint32_t igt_plane_get_fb_id(igt_plane_t *plane)
994 {
995         if (plane->fb)
996                 return plane->fb->fb_id;
997         else
998                 return 0;
999 }
1000
1001 static uint32_t igt_plane_get_fb_gem_handle(igt_plane_t *plane)
1002 {
1003         if (plane->fb)
1004                 return plane->fb->gem_handle;
1005         else
1006                 return 0;
1007 }
1008
1009 #define CHECK_RETURN(r, fail) { \
1010         if (r && !fail)         \
1011                 return r;       \
1012         igt_assert(r == 0);     \
1013 }
1014
1015 /*
1016  * Commit position and fb changes to a DRM plane via the SetPlane ioctl; if the
1017  * DRM call to program the plane fails, we'll either fail immediately (for
1018  * tests that expect the commit to succeed) or return the failure code (for
1019  * tests that expect a specific error code).
1020  */
1021 static int igt_drm_plane_commit(igt_plane_t *plane,
1022                                 igt_output_t *output,
1023                                 bool fail_on_error)
1024 {
1025         igt_display_t *display = output->display;
1026         uint32_t fb_id, crtc_id;
1027         int ret;
1028
1029         igt_assert(plane->drm_plane);
1030
1031         /* it's an error to try an unsupported feature */
1032         igt_assert(igt_plane_supports_rotation(plane) ||
1033                    !plane->rotation_changed);
1034
1035         fb_id = igt_plane_get_fb_id(plane);
1036         crtc_id = output->config.crtc->crtc_id;
1037
1038         if (plane->fb_changed && fb_id == 0) {
1039                 LOG(display,
1040                     "%s: SetPlane pipe %s, plane %d, disabling\n",
1041                     igt_output_name(output),
1042                     kmstest_pipe_name(output->config.pipe),
1043                     plane->index);
1044
1045                 ret = drmModeSetPlane(display->drm_fd,
1046                                       plane->drm_plane->plane_id,
1047                                       crtc_id,
1048                                       fb_id,
1049                                       0,    /* flags */
1050                                       0, 0, /* crtc_x, crtc_y */
1051                                       0, 0, /* crtc_w, crtc_h */
1052                                       IGT_FIXED(0,0), /* src_x */
1053                                       IGT_FIXED(0,0), /* src_y */
1054                                       IGT_FIXED(0,0), /* src_w */
1055                                       IGT_FIXED(0,0) /* src_h */);
1056
1057                 CHECK_RETURN(ret, fail_on_error);
1058         } else if (plane->fb_changed || plane->position_changed) {
1059                 LOG(display,
1060                     "%s: SetPlane %s.%d, fb %u, position (%d, %d)\n",
1061                     igt_output_name(output),
1062                     kmstest_pipe_name(output->config.pipe),
1063                     plane->index,
1064                     fb_id,
1065                     plane->crtc_x, plane->crtc_y);
1066
1067                 ret = drmModeSetPlane(display->drm_fd,
1068                                       plane->drm_plane->plane_id,
1069                                       crtc_id,
1070                                       fb_id,
1071                                       0,    /* flags */
1072                                       plane->crtc_x, plane->crtc_y,
1073                                       plane->fb->width, plane->fb->height,
1074                                       IGT_FIXED(0,0), /* src_x */
1075                                       IGT_FIXED(0,0), /* src_y */
1076                                       IGT_FIXED(plane->fb->width,0), /* src_w */
1077                                       IGT_FIXED(plane->fb->height,0) /* src_h */);
1078
1079                 CHECK_RETURN(ret, fail_on_error);
1080         }
1081
1082         plane->fb_changed = false;
1083         plane->position_changed = false;
1084
1085         if (plane->rotation_changed) {
1086                 igt_plane_set_property(plane, plane->rotation_property,
1087                                        plane->rotation);
1088
1089                 plane->rotation_changed = false;
1090         }
1091
1092         return 0;
1093 }
1094
1095 /*
1096  * Commit position and fb changes to a cursor via legacy ioctl's.  If commit
1097  * fails, we'll either fail immediately (for tests that expect the commit to
1098  * succeed) or return the failure code (for tests that expect a specific error
1099  * code).
1100  */
1101 static int igt_cursor_commit_legacy(igt_plane_t *cursor,
1102                                     igt_output_t *output,
1103                                     bool fail_on_error)
1104 {
1105         igt_display_t *display = output->display;
1106         uint32_t crtc_id = output->config.crtc->crtc_id;
1107         int ret;
1108
1109         if (cursor->fb_changed) {
1110                 uint32_t gem_handle = igt_plane_get_fb_gem_handle(cursor);
1111
1112                 if (gem_handle) {
1113                         LOG(display,
1114                             "%s: SetCursor pipe %s, fb %u %dx%d\n",
1115                             igt_output_name(output),
1116                             kmstest_pipe_name(output->config.pipe),
1117                             gem_handle,
1118                             cursor->fb->width, cursor->fb->height);
1119
1120                         ret = drmModeSetCursor(display->drm_fd, crtc_id,
1121                                                gem_handle,
1122                                                cursor->fb->width,
1123                                                cursor->fb->height);
1124                 } else {
1125                         LOG(display,
1126                             "%s: SetCursor pipe %s, disabling\n",
1127                             igt_output_name(output),
1128                             kmstest_pipe_name(output->config.pipe));
1129
1130                         ret = drmModeSetCursor(display->drm_fd, crtc_id,
1131                                                0, 0, 0);
1132                 }
1133
1134                 CHECK_RETURN(ret, fail_on_error);
1135
1136                 cursor->fb_changed = false;
1137         }
1138
1139         if (cursor->position_changed) {
1140                 int x = cursor->crtc_x;
1141                 int y = cursor->crtc_y;
1142
1143                 LOG(display,
1144                     "%s: MoveCursor pipe %s, (%d, %d)\n",
1145                     igt_output_name(output),
1146                     kmstest_pipe_name(output->config.pipe),
1147                     x, y);
1148
1149                 ret = drmModeMoveCursor(display->drm_fd, crtc_id, x, y);
1150                 CHECK_RETURN(ret, fail_on_error);
1151
1152                 cursor->position_changed = false;
1153         }
1154
1155         return 0;
1156 }
1157
1158 /*
1159  * Commit position and fb changes to a primary plane via the legacy interface
1160  * (setmode).
1161  */
1162 static int igt_primary_plane_commit_legacy(igt_plane_t *primary,
1163                                            igt_output_t *output,
1164                                            bool fail_on_error)
1165 {
1166         struct igt_display *display = primary->pipe->display;
1167         drmModeModeInfo *mode;
1168         uint32_t fb_id, crtc_id;
1169         int ret;
1170
1171         /* Primary planes can't be windowed when using a legacy commit */
1172         igt_assert((primary->crtc_x == 0 && primary->crtc_y == 0));
1173
1174         /* nor rotated */
1175         igt_assert(!primary->rotation_changed);
1176
1177         if (!primary->fb_changed && !primary->position_changed &&
1178             !primary->panning_changed)
1179                 return 0;
1180
1181         crtc_id = output->config.crtc->crtc_id;
1182         fb_id = igt_plane_get_fb_id(primary);
1183         if (fb_id)
1184                 mode = igt_output_get_mode(output);
1185         else
1186                 mode = NULL;
1187
1188         if (fb_id) {
1189                 LOG(display,
1190                     "%s: SetCrtc pipe %s, fb %u, panning (%d, %d), "
1191                     "mode %dx%d\n",
1192                     igt_output_name(output),
1193                     kmstest_pipe_name(output->config.pipe),
1194                     fb_id,
1195                     primary->pan_x, primary->pan_y,
1196                     mode->hdisplay, mode->vdisplay);
1197
1198                 ret = drmModeSetCrtc(display->drm_fd,
1199                                      crtc_id,
1200                                      fb_id,
1201                                      primary->pan_x, primary->pan_y,
1202                                      &output->id,
1203                                      1,
1204                                      mode);
1205         } else {
1206                 LOG(display,
1207                     "%s: SetCrtc pipe %s, disabling\n",
1208                     igt_output_name(output),
1209                     kmstest_pipe_name(output->config.pipe));
1210
1211                 ret = drmModeSetCrtc(display->drm_fd,
1212                                      crtc_id,
1213                                      fb_id,
1214                                      0, 0, /* x, y */
1215                                      NULL, /* connectors */
1216                                      0,    /* n_connectors */
1217                                      NULL  /* mode */);
1218         }
1219
1220         CHECK_RETURN(ret, fail_on_error);
1221
1222         primary->pipe->enabled = (fb_id != 0);
1223         primary->fb_changed = false;
1224         primary->position_changed = false;
1225         primary->panning_changed = false;
1226
1227         return 0;
1228 }
1229
1230
1231 /*
1232  * Commit position and fb changes to a plane.  The value of @s will determine
1233  * which API is used to do the programming.
1234  */
1235 static int igt_plane_commit(igt_plane_t *plane,
1236                             igt_output_t *output,
1237                             enum igt_commit_style s,
1238                             bool fail_on_error)
1239 {
1240         if (plane->is_cursor && s == COMMIT_LEGACY) {
1241                 return igt_cursor_commit_legacy(plane, output, fail_on_error);
1242         } else if (plane->is_primary && s == COMMIT_LEGACY) {
1243                 return igt_primary_plane_commit_legacy(plane, output,
1244                                                        fail_on_error);
1245         } else {
1246                 return igt_drm_plane_commit(plane, output, fail_on_error);
1247         }
1248 }
1249
1250 /*
1251  * Commit all plane changes to an output.  Note that if @s is COMMIT_LEGACY,
1252  * enabling/disabling the primary plane will also enable/disable the CRTC.
1253  *
1254  * If @fail_on_error is true, any failure to commit plane state will lead
1255  * to subtest failure in the specific function where the failure occurs.
1256  * Otherwise, the first error code encountered will be returned and no
1257  * further programming will take place, which may result in some changes
1258  * taking effect and others not taking effect.
1259  */
1260 static int igt_output_commit(igt_output_t *output,
1261                              enum igt_commit_style s,
1262                              bool fail_on_error)
1263 {
1264         igt_display_t *display = output->display;
1265         igt_pipe_t *pipe;
1266         int i;
1267         int ret;
1268         bool need_wait_for_vblank = false;
1269
1270         pipe = igt_output_get_driving_pipe(output);
1271
1272         for (i = 0; i < pipe->n_planes; i++) {
1273                 igt_plane_t *plane = &pipe->planes[i];
1274
1275                 if (plane->fb_changed || plane->position_changed)
1276                         need_wait_for_vblank = true;
1277
1278                 ret = igt_plane_commit(plane, output, s, fail_on_error);
1279                 CHECK_RETURN(ret, fail_on_error);
1280         }
1281
1282         /*
1283          * If the crtc is enabled, wait until the next vblank before returning
1284          * if we made changes to any of the planes.
1285          */
1286         if (need_wait_for_vblank && pipe->enabled) {
1287                 igt_wait_for_vblank(display->drm_fd, pipe->pipe);
1288         }
1289
1290         return 0;
1291 }
1292
1293 /*
1294  * Commit all plane changes across all outputs of the display.
1295  *
1296  * If @fail_on_error is true, any failure to commit plane state will lead
1297  * to subtest failure in the specific function where the failure occurs.
1298  * Otherwise, the first error code encountered will be returned and no
1299  * further programming will take place, which may result in some changes
1300  * taking effect and others not taking effect.
1301  */
1302 static int do_display_commit(igt_display_t *display,
1303                              enum igt_commit_style s,
1304                              bool fail_on_error)
1305 {
1306         int i, ret;
1307
1308         LOG_INDENT(display, "commit");
1309
1310         igt_display_refresh(display);
1311
1312         for (i = 0; i < display->n_outputs; i++) {
1313                 igt_output_t *output = &display->outputs[i];
1314
1315                 if (!output->valid)
1316                         continue;
1317
1318                 ret = igt_output_commit(output, s, fail_on_error);
1319                 CHECK_RETURN(ret, fail_on_error);
1320         }
1321
1322         LOG_UNINDENT(display);
1323
1324         if (getenv("IGT_DISPLAY_WAIT_AT_COMMIT"))
1325                 igt_wait_for_keypress();
1326
1327         return 0;
1328 }
1329
1330 /**
1331  * igt_display_commit2:
1332  * @display: DRM device handle
1333  * @s: Commit style
1334  *
1335  * Commits framebuffer and positioning changes to all planes of each display
1336  * pipe, using a specific API to perform the programming.  This function should
1337  * be used to exercise a specific driver programming API; igt_display_commit
1338  * should be used instead if the API used is unimportant to the test being run.
1339  *
1340  * This function should only be used to commit changes that are expected to
1341  * succeed, since any failure during the commit process will cause the IGT
1342  * subtest to fail.  To commit changes that are expected to fail, use
1343  * @igt_try_display_commit2 instead.
1344  *
1345  * Returns: 0 upon success.  This function will never return upon failure
1346  * since igt_fail() at lower levels will longjmp out of it.
1347  */
1348 int igt_display_commit2(igt_display_t *display,
1349                        enum igt_commit_style s)
1350 {
1351         do_display_commit(display, s, true);
1352
1353         return 0;
1354 }
1355
1356 /**
1357  * igt_display_try_commit2:
1358  * @display: DRM device handle
1359  * @s: Commit style
1360  *
1361  * Attempts to commit framebuffer and positioning changes to all planes of each
1362  * display pipe.  This function should be used to commit changes that are
1363  * expected to fail, so that the error code can be checked for correctness.
1364  * For changes that are expected to succeed, use @igt_display_commit instead.
1365  *
1366  * Note that in non-atomic commit styles, no display programming will be
1367  * performed after the first failure is encountered, so only some of the
1368  * operations requested by a test may have been completed.  Tests that catch
1369  * errors returned by this function should take care to restore the display to
1370  * a sane state after a failure is detected.
1371  *
1372  * Returns: 0 upon success, otherwise the error code of the first error
1373  * encountered.
1374  */
1375 int igt_display_try_commit2(igt_display_t *display, enum igt_commit_style s)
1376 {
1377         return do_display_commit(display, s, false);
1378 }
1379
1380 /**
1381  * igt_display_commit:
1382  * @display: DRM device handle
1383  *
1384  * Commits framebuffer and positioning changes to all planes of each display
1385  * pipe.
1386  *
1387  * Returns: 0 upon success.  This function will never return upon failure
1388  * since igt_fail() at lower levels will longjmp out of it.
1389  */
1390 int igt_display_commit(igt_display_t *display)
1391 {
1392         return igt_display_commit2(display, COMMIT_LEGACY);
1393 }
1394
1395 const char *igt_output_name(igt_output_t *output)
1396 {
1397         return output->name;
1398 }
1399
1400 drmModeModeInfo *igt_output_get_mode(igt_output_t *output)
1401 {
1402         return &output->config.default_mode;
1403 }
1404
1405 void igt_output_set_pipe(igt_output_t *output, enum pipe pipe)
1406 {
1407         igt_display_t *display = output->display;
1408
1409         if (pipe == PIPE_ANY) {
1410                 LOG(display, "%s: set_pipe(any)\n", igt_output_name(output));
1411                 output->pending_crtc_idx_mask = -1UL;
1412         } else {
1413                 LOG(display, "%s: set_pipe(%s)\n", igt_output_name(output),
1414                     kmstest_pipe_name(pipe));
1415                 output->pending_crtc_idx_mask = 1 << pipe;
1416         }
1417 }
1418
1419 igt_plane_t *igt_output_get_plane(igt_output_t *output, enum igt_plane plane)
1420 {
1421         igt_pipe_t *pipe;
1422
1423         pipe = igt_output_get_driving_pipe(output);
1424         return igt_pipe_get_plane(pipe, plane);
1425 }
1426
1427 void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb)
1428 {
1429         igt_pipe_t *pipe = plane->pipe;
1430         igt_display_t *display = pipe->display;
1431
1432         LOG(display, "%s.%d: plane_set_fb(%d)\n", kmstest_pipe_name(pipe->pipe),
1433             plane->index, fb ? fb->fb_id : 0);
1434
1435         plane->fb = fb;
1436
1437         plane->fb_changed = true;
1438 }
1439
1440 void igt_plane_set_position(igt_plane_t *plane, int x, int y)
1441 {
1442         igt_pipe_t *pipe = plane->pipe;
1443         igt_display_t *display = pipe->display;
1444
1445         LOG(display, "%s.%d: plane_set_position(%d,%d)\n",
1446             kmstest_pipe_name(pipe->pipe), plane->index, x, y);
1447
1448         plane->crtc_x = x;
1449         plane->crtc_y = y;
1450
1451         plane->position_changed = true;
1452 }
1453
1454 void igt_plane_set_panning(igt_plane_t *plane, int x, int y)
1455 {
1456         igt_pipe_t *pipe = plane->pipe;
1457         igt_display_t *display = pipe->display;
1458
1459         LOG(display, "%s.%d: plane_set_panning(%d,%d)\n",
1460             kmstest_pipe_name(pipe->pipe),
1461             plane->index, x, y);
1462
1463         plane->pan_x = x;
1464         plane->pan_y = y;
1465
1466         plane->panning_changed = true;
1467 }
1468
1469 static const char *rotation_name(igt_rotation_t rotation)
1470 {
1471         switch (rotation) {
1472         case IGT_ROTATION_0:
1473                 return "0°";
1474         case IGT_ROTATION_90:
1475                 return "90°";
1476         case IGT_ROTATION_180:
1477                 return "180°";
1478         case IGT_ROTATION_270:
1479                 return "270°";
1480         default:
1481                 igt_assert(0);
1482         }
1483 }
1484
1485 void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation)
1486 {
1487         igt_pipe_t *pipe = plane->pipe;
1488         igt_display_t *display = pipe->display;
1489
1490         LOG(display, "%s.%d: plane_set_rotation(%s)\n",
1491             kmstest_pipe_name(pipe->pipe),
1492             plane->index, rotation_name(rotation));
1493
1494         plane->rotation = rotation;
1495
1496         plane->rotation_changed = true;
1497 }
1498
1499 void igt_wait_for_vblank(int drm_fd, enum pipe pipe)
1500 {
1501         drmVBlank wait_vbl;
1502
1503         memset(&wait_vbl, 0, sizeof(wait_vbl));
1504
1505         wait_vbl.request.type = pipe << DRM_VBLANK_HIGH_CRTC_SHIFT |
1506                                 DRM_VBLANK_RELATIVE;
1507         wait_vbl.request.sequence = 1;
1508
1509         igt_assert(drmWaitVBlank(drm_fd, &wait_vbl) == 0);
1510 }
1511
1512 static void reset_connectors_at_exit(int sig)
1513 {
1514         igt_reset_connectors();
1515 }
1516
1517 /**
1518  * igt_enable_connectors:
1519  *
1520  * Force connectors to be enabled where this is known to work well. Use
1521  * #igt_reset_connectors to revert the changes.
1522  *
1523  * An exit handler is installed to ensure connectors are reset when the test
1524  * exits.
1525  */
1526 void igt_enable_connectors(void)
1527 {
1528         drmModeRes *res;
1529         drmModeConnector *c;
1530         int drm_fd;
1531
1532         drm_fd = drm_open_any();
1533
1534         res = drmModeGetResources(drm_fd);
1535
1536         for (int i = 0; i < res->count_connectors; i++) {
1537
1538                 c = drmModeGetConnector(drm_fd, res->connectors[i]);
1539
1540                 /* don't attempt to force connectors that are already connected
1541                  */
1542                 if (c->connection == DRM_MODE_CONNECTED)
1543                         continue;
1544
1545                 /* just enable VGA for now */
1546                 if (c->connector_type == DRM_MODE_CONNECTOR_VGA) {
1547                         if (!kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_ON))
1548                                 igt_info("Unable to force state on %s-%d\n",
1549                                          kmstest_connector_type_str(c->connector_type),
1550                                          c->connector_type_id);
1551                 }
1552
1553                 drmModeFreeConnector(c);
1554         }
1555         close(drm_fd);
1556
1557         igt_install_exit_handler(reset_connectors_at_exit);
1558 }
1559
1560 /**
1561  * igt_reset_connectors:
1562  *
1563  * Remove any forced state from the connectors.
1564  */
1565 void igt_reset_connectors(void)
1566 {
1567         drmModeRes *res;
1568         drmModeConnector *c;
1569         int drm_fd;
1570
1571         drm_fd = drm_open_any();
1572         res = drmModeGetResources(drm_fd);
1573
1574         for (int i = 0; i < res->count_connectors; i++) {
1575
1576                 c = drmModeGetConnector(drm_fd, res->connectors[i]);
1577
1578                 kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_UNSPECIFIED);
1579
1580                 drmModeFreeConnector(c);
1581         }
1582
1583         close(drm_fd);
1584 }
1585
1586 /**
1587  * kmstest_unset_all_crtcs:
1588  * @drm_fd: the DRM fd
1589  * @resources: libdrm resources pointer
1590  *
1591  * Disables all the screens.
1592  */
1593 void kmstest_unset_all_crtcs(int drm_fd, drmModeResPtr resources)
1594 {
1595         int i, rc;
1596
1597         for (i = 0; i < resources->count_crtcs; i++) {
1598                 rc = drmModeSetCrtc(drm_fd, resources->crtcs[i], -1, 0, 0, NULL,
1599                                     0, NULL);
1600                 igt_assert(rc == 0);
1601         }
1602 }