blob: 5df2da7b038c6bcff3747df30e611de5b3eff9df [file] [log] [blame]
Chris Wilsone7d26df2015-03-19 15:24:52 +00001/*
2 * Copyright © 2015 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
24/** @file kms_vblank.c
25 *
26 * This is a test of performance of drmWaitVblank.
27 */
28
Thomas Wood804e11f2015-08-17 17:57:43 +010029#include "igt.h"
Chris Wilsone7d26df2015-03-19 15:24:52 +000030#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <fcntl.h>
34#include <inttypes.h>
35#include <errno.h>
36#include <time.h>
Chris Wilson0aef4862017-03-19 15:47:42 +000037#include <sys/poll.h>
Chris Wilsone7d26df2015-03-19 15:24:52 +000038#include <sys/stat.h>
39#include <sys/time.h>
40#include <sys/wait.h>
41
42#include <drm.h>
43
Chris Wilsone7d26df2015-03-19 15:24:52 +000044#include "intel_bufmgr.h"
Chris Wilsone7d26df2015-03-19 15:24:52 +000045
46IGT_TEST_DESCRIPTION("Test speed of WaitVblank.");
47
Robert Fossba865142016-05-18 20:07:07 -040048typedef struct {
49 igt_display_t display;
50 struct igt_fb primary_fb;
51 igt_output_t *output;
52 enum pipe pipe;
Chris Wilson0aef4862017-03-19 15:47:42 +000053 unsigned int flags;
Maarten Lankhorst1d405fb2018-01-03 11:04:29 +010054#define IDLE 0x1
55#define BUSY 0x2
56#define FORKED 0x4
57#define NOHANG 0x8
58#define MODESET 0x10
59#define DPMS 0x20
60#define SUSPEND 0x40
61#define RPM 0x80
Robert Fossba865142016-05-18 20:07:07 -040062} data_t;
63
Chris Wilsone7d26df2015-03-19 15:24:52 +000064static double elapsed(const struct timespec *start,
65 const struct timespec *end,
66 int loop)
67{
68 return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000)/loop;
69}
70
Maarten Lankhorst9c459332017-01-05 14:02:46 +010071static void prepare_crtc(data_t *data, int fd, igt_output_t *output)
Chris Wilsone7d26df2015-03-19 15:24:52 +000072{
Robert Fossba865142016-05-18 20:07:07 -040073 drmModeModeInfo *mode;
74 igt_display_t *display = &data->display;
75 igt_plane_t *primary;
Chris Wilsone7d26df2015-03-19 15:24:52 +000076
Maarten Lankhorst63f7ef02018-01-04 12:50:19 +010077 igt_display_reset(display);
78
Robert Fossba865142016-05-18 20:07:07 -040079 /* select the pipe we want to use */
80 igt_output_set_pipe(output, data->pipe);
Robert Fossba865142016-05-18 20:07:07 -040081
82 /* create and set the primary plane fb */
83 mode = igt_output_get_mode(output);
84 igt_create_color_fb(fd, mode->hdisplay, mode->vdisplay,
85 DRM_FORMAT_XRGB8888,
86 LOCAL_DRM_FORMAT_MOD_NONE,
87 0.0, 0.0, 0.0,
88 &data->primary_fb);
89
Robert Fossa27f8312017-01-10 20:21:26 -050090 primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
Robert Fossba865142016-05-18 20:07:07 -040091 igt_plane_set_fb(primary, &data->primary_fb);
92
93 igt_display_commit(display);
94
95 igt_wait_for_vblank(fd, data->pipe);
Chris Wilsone7d26df2015-03-19 15:24:52 +000096}
97
Robert Fossba865142016-05-18 20:07:07 -040098static void cleanup_crtc(data_t *data, int fd, igt_output_t *output)
99{
Robert Fossba865142016-05-18 20:07:07 -0400100 igt_remove_fb(fd, &data->primary_fb);
Robert Fossba865142016-05-18 20:07:07 -0400101}
102
Chris Wilson0aef4862017-03-19 15:47:42 +0000103static int wait_vblank(int fd, union drm_wait_vblank *vbl)
Robert Fossba865142016-05-18 20:07:07 -0400104{
Chris Wilson0aef4862017-03-19 15:47:42 +0000105 int err;
106
107 err = 0;
108 if (igt_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl))
109 err = -errno;
110
111 return err;
112}
113
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100114static void run_test(data_t *data, void (*testfunc)(data_t *, int, int))
Chris Wilson0aef4862017-03-19 15:47:42 +0000115{
116 int nchildren =
117 data->flags & FORKED ? sysconf(_SC_NPROCESSORS_ONLN) : 1;
Robert Fossba865142016-05-18 20:07:07 -0400118 igt_display_t *display = &data->display;
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100119 igt_output_t *output = data->output;
120 int fd = display->drm_fd;
Maarten Lankhorst4405f392017-11-01 14:20:45 +0100121 igt_hang_t hang;
Robert Fossba865142016-05-18 20:07:07 -0400122
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100123 prepare_crtc(data, fd, output);
Robert Fossba865142016-05-18 20:07:07 -0400124
Maarten Lankhorst1d405fb2018-01-03 11:04:29 +0100125 if (data->flags & RPM)
126 igt_require(igt_setup_runtime_pm());
127
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100128 igt_info("Beginning %s on pipe %s, connector %s (%d threads)\n",
129 igt_subtest_name(), kmstest_pipe_name(data->pipe),
130 igt_output_name(output), nchildren);
Robert Fossba865142016-05-18 20:07:07 -0400131
Maarten Lankhorst4405f392017-11-01 14:20:45 +0100132 if (!(data->flags & NOHANG))
133 hang = igt_hang_ring(fd, I915_EXEC_DEFAULT);
134
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100135 if (data->flags & BUSY) {
136 union drm_wait_vblank vbl;
Robert Fossba865142016-05-18 20:07:07 -0400137
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100138 memset(&vbl, 0, sizeof(vbl));
139 vbl.request.type =
140 DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
141 vbl.request.type |= kmstest_get_vbl_flag(data->pipe);
142 vbl.request.sequence = 120 + 12;
143 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Robert Fossba865142016-05-18 20:07:07 -0400144 }
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100145
146 igt_fork(child, nchildren)
147 testfunc(data, fd, nchildren);
148 igt_waitchildren();
149
150 if (data->flags & BUSY) {
151 struct drm_event_vblank buf;
152 igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
153 }
154
155 igt_assert(poll(&(struct pollfd){fd, POLLIN}, 1, 0) == 0);
156
Maarten Lankhorst4405f392017-11-01 14:20:45 +0100157 if (!(data->flags & NOHANG))
158 igt_post_hang_ring(fd, hang);
159
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100160 igt_info("\n%s on pipe %s, connector %s: PASSED\n\n",
161 igt_subtest_name(), kmstest_pipe_name(data->pipe), igt_output_name(output));
162
163 /* cleanup what prepare_crtc() has done */
164 cleanup_crtc(data, fd, output);
Maarten Lankhorst4919d1f2017-11-22 14:10:54 +0100165}
Robert Fossba865142016-05-18 20:07:07 -0400166
Maarten Lankhorst4919d1f2017-11-22 14:10:54 +0100167static void crtc_id_subtest(data_t *data, int fd)
168{
169 igt_display_t *display = &data->display;
170 igt_output_t *output;
171 enum pipe p;
172
173 for_each_pipe_with_valid_output(display, p, output) {
174 struct drm_event_vblank buf;
175 const uint32_t pipe_id_flag = kmstest_get_vbl_flag(p);
176 unsigned crtc_id, expected_crtc_id;
177 uint64_t val;
178 union drm_wait_vblank vbl;
179
180 crtc_id = display->pipes[p].crtc_id;
181 if (drmGetCap(display->drm_fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &val) == 0)
182 expected_crtc_id = crtc_id;
183 else
184 expected_crtc_id = 0;
185
186 data->pipe = p;
187 prepare_crtc(data, fd, output);
188
189 memset(&vbl, 0, sizeof(vbl));
190 vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
191 vbl.request.type |= pipe_id_flag;
192 vbl.request.sequence = 1;
193 igt_assert_eq(wait_vblank(fd, &vbl), 0);
194
195 igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
196 igt_assert_eq(buf.crtc_id, expected_crtc_id);
197
198 do_or_die(drmModePageFlip(fd, crtc_id,
199 data->primary_fb.fb_id,
200 DRM_MODE_PAGE_FLIP_EVENT, NULL));
201
202 igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
203 igt_assert_eq(buf.crtc_id, expected_crtc_id);
204
205 if (display->is_atomic) {
206 igt_plane_t *primary = igt_output_get_plane(output, 0);
207
208 igt_plane_set_fb(primary, &data->primary_fb);
209 igt_display_commit_atomic(display, DRM_MODE_PAGE_FLIP_EVENT, NULL);
210
211 igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
212 igt_assert_eq(buf.crtc_id, expected_crtc_id);
213 }
214
215 cleanup_crtc(data, fd, output);
216 return;
217 }
Robert Fossba865142016-05-18 20:07:07 -0400218}
219
Chris Wilson0aef4862017-03-19 15:47:42 +0000220static void accuracy(data_t *data, int fd, int nchildren)
Chris Wilsona6c3b322015-04-06 10:37:41 +0100221{
Chris Wilson0aef4862017-03-19 15:47:42 +0000222 const uint32_t pipe_id_flag = kmstest_get_vbl_flag(data->pipe);
Chris Wilsona6c3b322015-04-06 10:37:41 +0100223 union drm_wait_vblank vbl;
224 unsigned long target;
Chris Wilson0aef4862017-03-19 15:47:42 +0000225 int total = 120 / nchildren;
Chris Wilsona6c3b322015-04-06 10:37:41 +0100226 int n;
227
228 memset(&vbl, 0, sizeof(vbl));
Chris Wilsona6c3b322015-04-06 10:37:41 +0100229 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400230 vbl.request.type |= pipe_id_flag;
Chris Wilsona6c3b322015-04-06 10:37:41 +0100231 vbl.request.sequence = 1;
Chris Wilson0aef4862017-03-19 15:47:42 +0000232 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilsona6c3b322015-04-06 10:37:41 +0100233
Chris Wilson0aef4862017-03-19 15:47:42 +0000234 target = vbl.reply.sequence + total;
235 for (n = 0; n < total; n++) {
Chris Wilsona6c3b322015-04-06 10:37:41 +0100236 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400237 vbl.request.type |= pipe_id_flag;
Chris Wilsona6c3b322015-04-06 10:37:41 +0100238 vbl.request.sequence = 1;
Chris Wilson0aef4862017-03-19 15:47:42 +0000239 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilsona6c3b322015-04-06 10:37:41 +0100240
241 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
Robert Fossba865142016-05-18 20:07:07 -0400242 vbl.request.type |= pipe_id_flag;
Chris Wilsona6c3b322015-04-06 10:37:41 +0100243 vbl.request.sequence = target;
Chris Wilson0aef4862017-03-19 15:47:42 +0000244 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilsona6c3b322015-04-06 10:37:41 +0100245 }
246 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400247 vbl.request.type |= pipe_id_flag;
Chris Wilsona6c3b322015-04-06 10:37:41 +0100248 vbl.request.sequence = 0;
Chris Wilson0aef4862017-03-19 15:47:42 +0000249 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilsona6c3b322015-04-06 10:37:41 +0100250 igt_assert_eq(vbl.reply.sequence, target);
251
Chris Wilson0aef4862017-03-19 15:47:42 +0000252 for (n = 0; n < total; n++) {
Chris Wilsona6c3b322015-04-06 10:37:41 +0100253 struct drm_event_vblank ev;
254 igt_assert_eq(read(fd, &ev, sizeof(ev)), sizeof(ev));
255 igt_assert_eq(ev.sequence, target);
256 }
257}
258
Chris Wilson0aef4862017-03-19 15:47:42 +0000259static void vblank_query(data_t *data, int fd, int nchildren)
Chris Wilsone7d26df2015-03-19 15:24:52 +0000260{
Chris Wilson0aef4862017-03-19 15:47:42 +0000261 const uint32_t pipe_id_flag = kmstest_get_vbl_flag(data->pipe);
Chris Wilsone7d26df2015-03-19 15:24:52 +0000262 union drm_wait_vblank vbl;
263 struct timespec start, end;
264 unsigned long sq, count = 0;
Chris Wilsone7d26df2015-03-19 15:24:52 +0000265
266 memset(&vbl, 0, sizeof(vbl));
Chris Wilsone7d26df2015-03-19 15:24:52 +0000267 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400268 vbl.request.type |= pipe_id_flag;
Chris Wilsone7d26df2015-03-19 15:24:52 +0000269 vbl.request.sequence = 0;
Chris Wilson0aef4862017-03-19 15:47:42 +0000270 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilsone7d26df2015-03-19 15:24:52 +0000271
272 sq = vbl.reply.sequence;
273
274 clock_gettime(CLOCK_MONOTONIC, &start);
275 do {
276 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400277 vbl.request.type |= pipe_id_flag;
Chris Wilsone7d26df2015-03-19 15:24:52 +0000278 vbl.request.sequence = 0;
Chris Wilson0aef4862017-03-19 15:47:42 +0000279 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilsone7d26df2015-03-19 15:24:52 +0000280 count++;
Chris Wilson0aef4862017-03-19 15:47:42 +0000281 } while ((vbl.reply.sequence - sq) <= 120);
Chris Wilsone7d26df2015-03-19 15:24:52 +0000282 clock_gettime(CLOCK_MONOTONIC, &end);
283
284 igt_info("Time to query current counter (%s): %7.3fµs\n",
Chris Wilson0aef4862017-03-19 15:47:42 +0000285 data->flags & BUSY ? "busy" : "idle", elapsed(&start, &end, count));
Chris Wilson590e47c2015-04-02 11:37:23 +0100286}
287
Chris Wilson0aef4862017-03-19 15:47:42 +0000288static void vblank_wait(data_t *data, int fd, int nchildren)
Chris Wilson590e47c2015-04-02 11:37:23 +0100289{
Chris Wilson0aef4862017-03-19 15:47:42 +0000290 const uint32_t pipe_id_flag = kmstest_get_vbl_flag(data->pipe);
Chris Wilson590e47c2015-04-02 11:37:23 +0100291 union drm_wait_vblank vbl;
292 struct timespec start, end;
293 unsigned long sq, count = 0;
Chris Wilson590e47c2015-04-02 11:37:23 +0100294
295 memset(&vbl, 0, sizeof(vbl));
Chris Wilson590e47c2015-04-02 11:37:23 +0100296 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400297 vbl.request.type |= pipe_id_flag;
Chris Wilson590e47c2015-04-02 11:37:23 +0100298 vbl.request.sequence = 0;
Chris Wilson0aef4862017-03-19 15:47:42 +0000299 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilson590e47c2015-04-02 11:37:23 +0100300
301 sq = vbl.reply.sequence;
302
303 clock_gettime(CLOCK_MONOTONIC, &start);
304 do {
305 vbl.request.type = DRM_VBLANK_RELATIVE;
Robert Fossba865142016-05-18 20:07:07 -0400306 vbl.request.type |= pipe_id_flag;
Chris Wilson590e47c2015-04-02 11:37:23 +0100307 vbl.request.sequence = 1;
Chris Wilson0aef4862017-03-19 15:47:42 +0000308 igt_assert_eq(wait_vblank(fd, &vbl), 0);
Chris Wilson590e47c2015-04-02 11:37:23 +0100309 count++;
Chris Wilson0aef4862017-03-19 15:47:42 +0000310 } while ((vbl.reply.sequence - sq) <= 120);
Chris Wilson590e47c2015-04-02 11:37:23 +0100311 clock_gettime(CLOCK_MONOTONIC, &end);
312
313 igt_info("Time to wait for %ld/%d vblanks (%s): %7.3fµs\n",
314 count, (int)(vbl.reply.sequence - sq),
Chris Wilson0aef4862017-03-19 15:47:42 +0000315 data->flags & BUSY ? "busy" : "idle",
Chris Wilson590e47c2015-04-02 11:37:23 +0100316 elapsed(&start, &end, count));
Chris Wilsone7d26df2015-03-19 15:24:52 +0000317}
318
Maarten Lankhorst1d405fb2018-01-03 11:04:29 +0100319static int get_vblank(int fd, enum pipe pipe, unsigned flags)
320{
321 union drm_wait_vblank vbl;
322
323 memset(&vbl, 0, sizeof(vbl));
324 vbl.request.type = DRM_VBLANK_RELATIVE | kmstest_get_vbl_flag(pipe) | flags;
325 do_or_die(igt_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl));
326
327 return vbl.reply.sequence;
328}
329
330static void vblank_ts_cont(data_t *data, int fd, int nchildren)
331{
332 igt_display_t *display = &data->display;
333 igt_output_t *output = data->output;
334 int seq1, seq2;
335 union drm_wait_vblank vbl;
336
337 seq1 = get_vblank(fd, data->pipe, 0);
338
339 if (data->flags & DPMS) {
340 igt_output_set_prop_value(output, IGT_CONNECTOR_DPMS, DRM_MODE_DPMS_OFF);
341 igt_display_commit(display);
342 }
343
344 if (data->flags & MODESET) {
345 igt_output_set_pipe(output, PIPE_NONE);
346 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
347 }
348
349 if (data->flags & RPM)
350 igt_assert(igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED));
351
352 if (data->flags & SUSPEND)
353 igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
354 SUSPEND_TEST_NONE);
355
356 if (data->flags & (MODESET | DPMS)) {
357 /* Attempting to do a vblank while disabled should return -EINVAL */
358 memset(&vbl, 0, sizeof(vbl));
359 vbl.request.type = DRM_VBLANK_RELATIVE;
360 vbl.request.type |= kmstest_get_vbl_flag(data->pipe);
361 igt_assert_eq(wait_vblank(fd, &vbl), -EINVAL);
362 }
363
364 if (data->flags & DPMS) {
365 igt_output_set_prop_value(output, IGT_CONNECTOR_DPMS, DRM_MODE_DPMS_ON);
366 igt_display_commit(display);
367 }
368
369 if (data->flags & MODESET) {
370 igt_output_set_pipe(output, data->pipe);
371 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
372 }
373
374 seq2 = get_vblank(fd, data->pipe, 0);
375
376 igt_debug("testing ts continuity: Current frame %u, old frame %u\n", seq2, seq1);
377
378 igt_assert_f(seq2 - seq1 >= 0, "unexpected vblank seq %u, should be >= %u\n", seq2, seq1);
379 igt_assert_f(seq2 - seq1 <= 150, "unexpected vblank seq %u, should be < %u\n", seq2, seq1 + 150);
380}
381
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100382static void run_subtests_for_pipe(data_t *data)
Chris Wilsone7d26df2015-03-19 15:24:52 +0000383{
Chris Wilson0aef4862017-03-19 15:47:42 +0000384 const struct {
385 const char *name;
386 void (*func)(data_t *, int, int);
387 unsigned int valid;
388 } funcs[] = {
Maarten Lankhorst4405f392017-11-01 14:20:45 +0100389 /*
390 * GPU reset recovery may disable irqs or reset display, so
391 * accuracy tests will fail in the hang case, disable this test.
392 */
393 { "accuracy", accuracy, IDLE | NOHANG },
Chris Wilson0aef4862017-03-19 15:47:42 +0000394 { "query", vblank_query, IDLE | FORKED | BUSY },
395 { "wait", vblank_wait, IDLE | FORKED | BUSY },
Maarten Lankhorst1d405fb2018-01-03 11:04:29 +0100396 { "ts-continuation", vblank_ts_cont, IDLE | SUSPEND | MODESET | DPMS | RPM },
Chris Wilson0aef4862017-03-19 15:47:42 +0000397 { }
398 }, *f;
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100399
Chris Wilson0aef4862017-03-19 15:47:42 +0000400 const struct {
401 const char *name;
402 unsigned int flags;
403 } modes[] = {
404 { "idle", IDLE },
405 { "forked", IDLE | FORKED },
406 { "busy", BUSY },
407 { "forked-busy", BUSY | FORKED },
Maarten Lankhorst1d405fb2018-01-03 11:04:29 +0100408 { "dpms-rpm", DPMS | RPM | NOHANG },
409 { "dpms-suspend", DPMS | SUSPEND | NOHANG},
410 { "suspend", SUSPEND | NOHANG },
411 { "modeset", MODESET },
412 { "modeset-rpm", MODESET | RPM | NOHANG},
Chris Wilson0aef4862017-03-19 15:47:42 +0000413 { }
414 }, *m;
Chris Wilsone7d26df2015-03-19 15:24:52 +0000415
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100416 igt_fixture
417 igt_display_require_output_on_pipe(&data->display, data->pipe);
418
419 for (f = funcs; f->name; f++) {
420 for (m = modes; m->name; m++) {
Maarten Lankhorst4405f392017-11-01 14:20:45 +0100421 if (m->flags & ~(f->valid | NOHANG))
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100422 continue;
423
424 igt_subtest_f("pipe-%s-%s-%s",
425 kmstest_pipe_name(data->pipe),
426 f->name, m->name) {
427 for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) {
Maarten Lankhorst4405f392017-11-01 14:20:45 +0100428 data->flags = m->flags | NOHANG;
429 run_test(data, f->func);
430 }
431 }
432
433 /* Skip the -hang version if NOHANG flag is set */
434 if (f->valid & NOHANG || m->flags & NOHANG)
435 continue;
436
437 igt_subtest_f("pipe-%s-%s-%s-hang",
438 kmstest_pipe_name(data->pipe),
439 f->name, m->name) {
440 for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) {
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100441 data->flags = m->flags;
442 run_test(data, f->func);
443 }
444 }
445 }
446 }
447}
448
449igt_main
450{
451 int fd;
452 data_t data;
453
Chris Wilsone7d26df2015-03-19 15:24:52 +0000454 igt_skip_on_simulation();
455
456 igt_fixture {
Chris Wilsond0f996c2017-12-11 09:03:41 +0000457 fd = drm_open_driver_master(DRIVER_ANY);
Robert Fossba865142016-05-18 20:07:07 -0400458 kmstest_set_vt_graphics_mode();
459 igt_display_init(&data.display, fd);
Maarten Lankhorst4919d1f2017-11-22 14:10:54 +0100460 igt_display_require_output(&data.display);
Chris Wilsone7d26df2015-03-19 15:24:52 +0000461 }
462
Maarten Lankhorst4919d1f2017-11-22 14:10:54 +0100463 igt_subtest("crtc-id")
464 crtc_id_subtest(&data, fd);
465
Maarten Lankhorst8d7e9412018-01-03 11:18:01 +0100466 for_each_pipe_static(data.pipe)
467 igt_subtest_group
468 run_subtests_for_pipe(&data);
Chris Wilsone7d26df2015-03-19 15:24:52 +0000469}