kms_rotation_crc: Remove useless comments
[platform/upstream/intel-gpu-tools.git] / tests / kms_psr_sink_crc.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  */
24
25 #include <errno.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "drm_fourcc.h"
31
32 #include "ioctl_wrappers.h"
33 #include "drmtest.h"
34 #include "intel_bufmgr.h"
35 #include "intel_batchbuffer.h"
36 #include "intel_chipset.h"
37 #include "igt_debugfs.h"
38 #include "igt_kms.h"
39
40 enum tests {
41         TEST_PAGE_FLIP,
42         TEST_MMAP_CPU,
43         TEST_MMAP_GTT,
44         TEST_MMAP_GTT_NO_BUSY,
45         TEST_MMAP_GTT_WAITING_NO_BUSY,
46         TEST_SETDOMAIN_WAIT_WRITE_GTT,
47         TEST_SETDOMAIN_WAIT_WRITE_CPU,
48         TEST_BLT,
49         TEST_RENDER,
50         TEST_CONTEXT,
51         TEST_PAGE_FLIP_AND_MMAP_CPU,
52         TEST_PAGE_FLIP_AND_MMAP_GTT,
53         TEST_PAGE_FLIP_AND_BLT,
54         TEST_PAGE_FLIP_AND_RENDER,
55         TEST_PAGE_FLIP_AND_CONTEXT,
56         TEST_CURSOR_MOVE,
57         TEST_SPRITE,
58 };
59
60 typedef struct {
61         int drm_fd;
62         enum tests test;
63         drmModeRes *resources;
64         drm_intel_bufmgr *bufmgr;
65         drm_intel_context *ctx[2];
66         uint32_t devid;
67         uint32_t handle[2];
68         uint32_t crtc_id;
69         uint32_t crtc_idx;
70         uint32_t fb_id[3];
71         struct kmstest_connector_config config;
72         igt_display_t display;
73         struct igt_fb fb[2];
74         igt_plane_t *plane[2];
75 } data_t;
76
77 static const char *tests_str(enum tests test)
78 {
79         static const char * const testss[] = {
80                 [TEST_PAGE_FLIP] = "page_flip",
81                 [TEST_MMAP_CPU] = "mmap_cpu",
82                 [TEST_MMAP_GTT] = "mmap_gtt",
83                 [TEST_MMAP_GTT_NO_BUSY] = "mmap_gtt_no_busy",
84                 [TEST_MMAP_GTT_WAITING_NO_BUSY] = "mmap_gtt_waiting_no_busy",
85                 [TEST_SETDOMAIN_WAIT_WRITE_GTT] = "setdomain_wait_write_gtt",
86                 [TEST_SETDOMAIN_WAIT_WRITE_CPU] = "setdomain_wait_write_cpu",
87                 [TEST_BLT] = "blt",
88                 [TEST_RENDER] = "render",
89                 [TEST_CONTEXT] = "context",
90                 [TEST_PAGE_FLIP_AND_MMAP_CPU] = "page_flip_and_mmap_cpu",
91                 [TEST_PAGE_FLIP_AND_MMAP_GTT] = "page_flip_and_mmap_gtt",
92                 [TEST_PAGE_FLIP_AND_BLT] = "page_flip_and_blt",
93                 [TEST_PAGE_FLIP_AND_RENDER] = "page_flip_and_render",
94                 [TEST_PAGE_FLIP_AND_CONTEXT] = "page_flip_and_context",
95                 [TEST_CURSOR_MOVE] = "cursor_move",
96                 [TEST_SPRITE] = "sprite",
97         };
98
99         return testss[test];
100 }
101
102 static uint32_t create_fb(data_t *data,
103                           int w, int h,
104                           double r, double g, double b,
105                           struct igt_fb *fb)
106 {
107         uint32_t fb_id;
108         cairo_t *cr;
109
110         fb_id = igt_create_fb(data->drm_fd, w, h,
111                               DRM_FORMAT_XRGB8888, true, fb);
112         igt_assert(fb_id);
113
114         cr = igt_get_cairo_ctx(data->drm_fd, fb);
115         igt_paint_color(cr, 0, 0, w, h, r, g, b);
116         igt_assert(cairo_status(cr) == 0);
117         cairo_destroy(cr);
118
119         return fb_id;
120 }
121
122 static void create_cursor_fb(data_t *data, struct igt_fb *fb)
123 {
124         cairo_t *cr;
125
126         data->fb_id[2] = igt_create_fb(data->drm_fd, 64, 64,
127                                        DRM_FORMAT_ARGB8888, false,
128                                        fb);
129         igt_assert(data->fb_id[2]);
130
131         cr = igt_get_cairo_ctx(data->drm_fd, fb);
132         igt_paint_color_alpha(cr, 0, 0, 64, 64, 1.0, 1.0, 1.0, 1.0);
133         igt_assert(cairo_status(cr) == 0);
134 }
135
136 static bool
137 connector_set_mode(data_t *data, drmModeModeInfo *mode, uint32_t fb_id)
138 {
139         struct kmstest_connector_config *config = &data->config;
140         int ret;
141
142 #if 0
143         fprintf(stdout, "Using pipe %c, %dx%d\n", pipe_name(config->pipe),
144                 mode->hdisplay, mode->vdisplay);
145 #endif
146
147         ret = drmModeSetCrtc(data->drm_fd,
148                              config->crtc->crtc_id,
149                              fb_id,
150                              0, 0, /* x, y */
151                              &config->connector->connector_id,
152                              1,
153                              mode);
154         igt_assert(ret == 0);
155
156         return 0;
157 }
158
159 static void display_init(data_t *data)
160 {
161         igt_display_init(&data->display, data->drm_fd);
162         data->resources = drmModeGetResources(data->drm_fd);
163         igt_assert(data->resources);
164 }
165
166 static void display_fini(data_t *data)
167 {
168         igt_display_fini(&data->display);
169         drmModeSetCursor(data->drm_fd, data->crtc_id, 0, 0, 0);
170         drmModeFreeResources(data->resources);
171 }
172
173 static void fill_blt(data_t *data, uint32_t handle, unsigned char color)
174 {
175         drm_intel_bo *dst = gem_handle_to_libdrm_bo(data->bufmgr,
176                                                     data->drm_fd,
177                                                     "", handle);
178         struct intel_batchbuffer *batch;
179
180         batch = intel_batchbuffer_alloc(data->bufmgr, data->devid);
181         igt_assert(batch);
182
183         BEGIN_BATCH(5);
184         OUT_BATCH(COLOR_BLT_CMD);
185         OUT_BATCH((1 << 24) | (0xf0 << 16) | 0);
186         OUT_BATCH(1 << 16 | 4);
187         OUT_RELOC(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
188         OUT_BATCH(color);
189         ADVANCE_BATCH();
190
191         intel_batchbuffer_flush(batch);
192         intel_batchbuffer_free(batch);
193
194         gem_bo_busy(data->drm_fd, handle);
195 }
196
197 static void scratch_buf_init(struct igt_buf *buf, drm_intel_bo *bo)
198 {
199         buf->bo = bo;
200         buf->stride = 4096;
201         buf->tiling = I915_TILING_X;
202         buf->size = 4096;
203 }
204
205 static void exec_nop(data_t *data, uint32_t handle, drm_intel_context *context)
206 {
207         drm_intel_bo *dst;
208         struct intel_batchbuffer *batch;
209
210         dst = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle);
211         igt_assert(dst);
212
213         batch = intel_batchbuffer_alloc(data->bufmgr, data->devid);
214         igt_assert(batch);
215
216         /* add the reloc to make sure the kernel will think we write to dst */
217         BEGIN_BATCH(4);
218         OUT_BATCH(MI_BATCH_BUFFER_END);
219         OUT_BATCH(MI_NOOP);
220         OUT_RELOC(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
221         OUT_BATCH(MI_NOOP);
222         ADVANCE_BATCH();
223
224         intel_batchbuffer_flush_with_context(batch, context);
225         intel_batchbuffer_free(batch);
226 }
227
228 static void fill_render(data_t *data, uint32_t handle,
229                         drm_intel_context *context, unsigned char color)
230 {
231         drm_intel_bo *src, *dst;
232         struct intel_batchbuffer *batch;
233         struct igt_buf src_buf, dst_buf;
234         const uint8_t buf[4] = { color, color, color, color };
235         igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(data->devid);
236
237         igt_skip_on(!rendercopy);
238
239         dst = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle);
240         igt_assert(dst);
241
242         src = drm_intel_bo_alloc(data->bufmgr, "", 4096, 4096);
243         igt_assert(src);
244
245         gem_write(data->drm_fd, src->handle, 0, buf, 4);
246
247         scratch_buf_init(&src_buf, src);
248         scratch_buf_init(&dst_buf, dst);
249
250         batch = intel_batchbuffer_alloc(data->bufmgr, data->devid);
251         igt_assert(batch);
252
253         rendercopy(batch, context,
254                    &src_buf, 0, 0, 1, 1,
255                    &dst_buf, 0, 0);
256
257         intel_batchbuffer_free(batch);
258
259         gem_bo_busy(data->drm_fd, handle);
260 }
261
262 static bool psr_sink_support(data_t *data)
263 {
264         int ret;
265         FILE *file;
266         char str[4];
267
268         file = igt_debugfs_fopen("i915_edp_psr_status", "r");
269         igt_require(file);
270
271         ret = fscanf(file, "Sink_Support: %s\n", str);
272         igt_skip_on_f(ret == 0,
273                       "i915_edp_psr_status format not supported by this test case\n");
274
275         fclose(file);
276         return strcmp(str, "yes") == 0;
277 }
278
279 static bool psr_enabled(data_t *data)
280 {
281         int ret;
282         FILE *file;
283         char str[4];
284
285         file = igt_debugfs_fopen("i915_edp_psr_status", "r");
286         igt_require(file);
287
288         ret = fscanf(file, "Sink_Support: %s\n", str);
289         igt_assert(ret != 0);
290
291         ret = fscanf(file, "Source_OK: %s\n", str);
292         igt_assert(ret != 0);
293
294         ret = fscanf(file, "Enabled: %s\n", str);
295         igt_assert(ret != 0);
296
297         fclose(file);
298         return strcmp(str, "yes") == 0;
299 }
300
301 static bool wait_psr_entry(data_t *data, int timeout)
302 {
303         while (timeout--) {
304                 if (psr_enabled(data))
305                         return true;
306                 sleep(1);
307         }
308         return false;
309 }
310
311 static void get_sink_crc(data_t *data, char *crc) {
312         int ret;
313         FILE *file;
314
315         file = igt_debugfs_fopen("i915_sink_crc_eDP1", "r");
316         igt_require(file);
317
318         ret = fscanf(file, "%s\n", crc);
319         igt_require(ret > 0);
320
321         fclose(file);
322 }
323
324 static void test_crc(data_t *data)
325 {
326         uint32_t handle = data->handle[0];
327         char ref_crc[12];
328         char crc[12];
329
330         if (data->test == TEST_CURSOR_MOVE) {
331                 igt_assert(drmModeSetCursor(data->drm_fd, data->crtc_id,
332                                             handle, 64, 64) == 0);
333                 igt_assert(drmModeMoveCursor(data->drm_fd, data->crtc_id,
334                                              1, 1) == 0);
335         }
336
337         usleep(300000);
338         igt_assert(wait_psr_entry(data, 10));
339         get_sink_crc(data, ref_crc);
340
341         switch (data->test) {
342                 void *ptr;
343         case TEST_PAGE_FLIP:
344                 igt_assert(drmModePageFlip(data->drm_fd, data->crtc_id,
345                                            data->fb_id[1], 0, NULL) == 0);
346                 break;
347         case TEST_PAGE_FLIP_AND_MMAP_CPU:
348                 handle = data->handle[1];
349                 igt_assert(drmModePageFlip(data->drm_fd, data->crtc_id,
350                                            data->fb_id[1], 0, NULL) == 0);
351         case TEST_MMAP_CPU:
352                 ptr = gem_mmap__cpu(data->drm_fd, handle, 4096, PROT_WRITE);
353                 gem_set_domain(data->drm_fd, handle,
354                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
355                 sleep(1);
356                 memset(ptr, 0, 4);
357                 munmap(ptr, 4096);
358                 sleep(1);
359                 gem_sw_finish(data->drm_fd, handle);
360                 break;
361         case TEST_PAGE_FLIP_AND_MMAP_GTT:
362                 handle = data->handle[1];
363                 igt_assert(drmModePageFlip(data->drm_fd, data->crtc_id,
364                                            data->fb_id[1], 0, NULL) == 0);
365         case TEST_MMAP_GTT:
366                 ptr = gem_mmap__gtt(data->drm_fd, handle, 4096, PROT_WRITE);
367                 gem_set_domain(data->drm_fd, handle,
368                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
369                 memset(ptr, 0xff, 4);
370                 munmap(ptr, 4096);
371                 gem_bo_busy(data->drm_fd, handle);
372                 break;
373         case TEST_MMAP_GTT_NO_BUSY:
374                 ptr = gem_mmap__gtt(data->drm_fd, handle, 4096, PROT_WRITE);
375                 gem_set_domain(data->drm_fd, handle,
376                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
377                 memset(ptr, 0xff, 4);
378                 munmap(ptr, 4096);
379                 break;
380         case TEST_MMAP_GTT_WAITING_NO_BUSY:
381                 ptr = gem_mmap__gtt(data->drm_fd, handle, 4096, PROT_WRITE);
382                 gem_set_domain(data->drm_fd, handle,
383                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
384                 igt_info("Sleeping for 10 sec...\n");
385                 sleep(10);
386                 memset(ptr, 0xff, 4);
387                 munmap(ptr, 4096);
388                 break;
389         case TEST_SETDOMAIN_WAIT_WRITE_GTT:
390                 ptr = gem_mmap__gtt(data->drm_fd, handle, 4096, PROT_WRITE);
391                 fill_blt(data, handle, 0xff);
392                 igt_assert(wait_psr_entry(data, 10));
393                 get_sink_crc(data, ref_crc);
394                 gem_set_domain(data->drm_fd, handle,
395                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
396                 igt_info("Sleeping for 10 sec...\n");
397                 sleep(10);
398                 memset(ptr, 0xff, 4);
399                 munmap(ptr, 4096);
400                 break;
401         case TEST_SETDOMAIN_WAIT_WRITE_CPU:
402                 ptr = gem_mmap__cpu(data->drm_fd, handle, 4096, PROT_WRITE);
403                 fill_blt(data, handle, 0xff);
404                 igt_assert(wait_psr_entry(data, 10));
405                 get_sink_crc(data, ref_crc);
406                 gem_set_domain(data->drm_fd, handle,
407                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
408                 igt_info("Sleeping for 10 sec...\n");
409                 sleep(10);
410                 memset(ptr, 0xff, 4);
411                 munmap(ptr, 4096);
412                 gem_sw_finish(data->drm_fd, handle);
413                 break;
414         case TEST_BLT:
415         case TEST_PAGE_FLIP_AND_BLT:
416                 fill_blt(data, handle, 0xff);
417                 break;
418         case TEST_RENDER:
419         case TEST_CONTEXT:
420         case TEST_PAGE_FLIP_AND_RENDER:
421         case TEST_PAGE_FLIP_AND_CONTEXT:
422                 fill_render(data, handle,
423                             (data->test == TEST_CONTEXT ||
424                              data->test == TEST_PAGE_FLIP_AND_CONTEXT) ?
425                             data->ctx[1] : NULL, 0xff);
426                 break;
427         case TEST_CURSOR_MOVE:
428                 igt_assert(drmModeMoveCursor(data->drm_fd, data->crtc_id, 1, 2) == 0);
429                 break;
430         case TEST_SPRITE:
431                 igt_plane_set_fb(data->plane[0], &data->fb[0]);
432                 igt_display_commit(&data->display);
433                 igt_plane_set_fb(data->plane[1], &data->fb[1]);
434                 igt_display_commit(&data->display);
435                 break;
436         }
437
438         igt_wait_for_vblank(data->drm_fd, data->crtc_idx);
439
440         get_sink_crc(data, crc);
441         igt_assert(strcmp(ref_crc, crc) != 0);
442 }
443
444 static bool prepare_crtc(data_t *data, uint32_t connector_id)
445 {
446         int ret;
447
448         ret = kmstest_get_connector_config(data->drm_fd,
449                                            connector_id,
450                                            1 << data->crtc_idx,
451                                            &data->config);
452         if (ret)
453                 return false;
454
455         data->fb_id[0] = create_fb(data,
456                                    data->config.default_mode.hdisplay,
457                                    data->config.default_mode.vdisplay,
458                                    0.0, 1.0, 0.0, &data->fb[0]);
459         igt_assert(data->fb_id[0]);
460
461         if (data->test == TEST_CURSOR_MOVE)
462                 create_cursor_fb(data, &data->fb[0]);
463
464         data->fb_id[1] = create_fb(data,
465                                    data->config.default_mode.hdisplay,
466                                    data->config.default_mode.vdisplay,
467                                    1.0, 0.0, 0.0, &data->fb[1]);
468         igt_assert(data->fb_id[1]);
469
470         data->handle[0] = data->fb[0].gem_handle;
471         data->handle[1] = data->fb[1].gem_handle;
472
473         /* scanout = fb[1] */
474         connector_set_mode(data, &data->config.default_mode,
475                            data->fb_id[1]);
476
477         if (data->test == TEST_CONTEXT ||
478             data->test == TEST_PAGE_FLIP_AND_CONTEXT) {
479                 data->ctx[0] = drm_intel_gem_context_create(data->bufmgr);
480                 igt_require(data->ctx[0]);
481                 data->ctx[1] = drm_intel_gem_context_create(data->bufmgr);
482                 igt_require(data->ctx[1]);
483
484                 exec_nop(data, data->handle[0], data->ctx[1]);
485                 exec_nop(data, data->handle[0], data->ctx[0]);
486                 exec_nop(data, data->handle[0], data->ctx[1]);
487                 exec_nop(data, data->handle[0], data->ctx[0]);
488         }
489
490         /* scanout = fb[0] */
491         connector_set_mode(data, &data->config.default_mode,
492                            data->fb_id[0]);
493
494         if (data->test == TEST_CONTEXT ||
495             data->test == TEST_PAGE_FLIP_AND_CONTEXT) {
496                 exec_nop(data, data->fb[0].gem_handle, data->ctx[0]);
497         }
498
499         kmstest_free_connector_config(&data->config);
500
501         return true;
502 }
503
504 static void finish_crtc(data_t *data)
505 {
506         if (data->test == TEST_CONTEXT ||
507             data->test == TEST_PAGE_FLIP_AND_CONTEXT) {
508                 drm_intel_gem_context_destroy(data->ctx[0]);
509                 drm_intel_gem_context_destroy(data->ctx[1]);
510         }
511 }
512
513 static void test_sprite(data_t *data)
514 {
515         igt_display_t *display = &data->display;
516         igt_output_t *output;
517         drmModeModeInfo *mode;
518
519         igt_skip_on(IS_HASWELL(data->devid));
520
521         for_each_connected_output(display, output) {
522                 drmModeConnectorPtr c = output->config.connector;
523
524                 if (c->connector_type != DRM_MODE_CONNECTOR_eDP ||
525                     c->connection != DRM_MODE_CONNECTED)
526                         continue;
527
528                 igt_output_set_pipe(output, PIPE_ANY);
529
530                 mode = igt_output_get_mode(output);
531
532                 igt_create_color_fb(data->drm_fd,
533                                     mode->hdisplay, mode->vdisplay,
534                                     DRM_FORMAT_XRGB8888, true, /* tiled */
535                                     0.0, 1.0, 0.0,
536                                     &data->fb[0]);
537
538                 igt_create_color_fb(data->drm_fd,
539                                     mode->hdisplay/2, mode->vdisplay/2,
540                                     DRM_FORMAT_XRGB8888, true, /* tiled */
541                                     1.0, 0.0, 0.0,
542                                     &data->fb[1]);
543
544                 data->plane[0] = igt_output_get_plane(output, 0);
545                 data->plane[1] = igt_output_get_plane(output, 1);
546
547                 test_crc(data);
548         }
549 }
550
551 static void run_test(data_t *data)
552 {
553         int i, n;
554         drmModeConnectorPtr c;
555         /* Baytrail supports per-pipe PSR configuration, however PSR on
556          * PIPE_B isn't working properly. So let's keep it disabled for now.
557          * crtcs = IS_VALLEYVIEW(data->devid)? 2 : 1; */
558         int crtcs = 1;
559
560         if (data->test == TEST_SPRITE) {
561                 test_sprite(data);
562                 return;
563         }
564
565         for (i = 0; i < data->resources->count_connectors; i++) {
566                 uint32_t connector_id = data->resources->connectors[i];
567                 c = drmModeGetConnector(data->drm_fd, connector_id);
568
569                 if (c->connector_type != DRM_MODE_CONNECTOR_eDP ||
570                     c->connection != DRM_MODE_CONNECTED)
571                         continue;
572                 for (n = 0; n < crtcs; n++) {
573                         data->crtc_idx = n;
574                         data->crtc_id = data->resources->crtcs[n];
575
576                         if (!prepare_crtc(data, connector_id))
577                                 continue;
578
579                         test_crc(data);
580
581                         finish_crtc(data);
582                 }
583         }
584 }
585
586 data_t data = {};
587 enum tests test;
588
589 igt_main
590 {
591         igt_skip_on_simulation();
592
593         igt_fixture {
594                 data.drm_fd = drm_open_any();
595                 igt_set_vt_graphics_mode();
596
597                 data.devid = intel_get_drm_devid(data.drm_fd);
598
599                 igt_require(psr_sink_support(&data));
600
601                 data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096);
602                 igt_assert(data.bufmgr);
603                 drm_intel_bufmgr_gem_enable_reuse(data.bufmgr);
604
605                 display_init(&data);
606         }
607
608         for (test = TEST_PAGE_FLIP; test <= TEST_SPRITE; test++) {
609                 igt_subtest_f("%s", tests_str(test)) {
610                         data.test = test;
611                         run_test(&data);
612                 }
613         }
614
615         igt_fixture {
616                 drm_intel_bufmgr_destroy(data.bufmgr);
617                 display_fini(&data);
618         }
619 }