1 /*
2 * Copyright © 2018 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 <poll.h>
26 #include <fcntl.h>
27 #include <sys/epoll.h>
28 #include <sys/stat.h>
29 #include <libudev.h>
30 #include "igt.h"
31 #include "igt_sysfs.h"
32 #include "igt_kms.h"
33 #include "igt_kmod.h"
34
35 IGT_TEST_DESCRIPTION("Test content protection (HDCP)");
36
37 struct data {
38 int drm_fd;
39 igt_display_t display;
40 struct igt_fb red, green;
41 unsigned int cp_tests;
42 } data;
43
44 /* Test flags */
45 #define CP_DPMS (1 << 0)
46 #define CP_LIC (1 << 1)
47 #define CP_MEI_RELOAD (1 << 2)
48 #define CP_TYPE_CHANGE (1 << 3)
49 #define CP_UEVENT (1 << 4)
50
51 #define CP_UNDESIRED 0
52 #define CP_DESIRED 1
53 #define CP_ENABLED 2
54
55 /*
56 * HDCP_CONTENT_TYPE_0 can be handled on both HDCP1.4 and HDCP2.2. Where as
57 * HDCP_CONTENT_TYPE_1 can be handled only through HDCP2.2.
58 */
59 #define HDCP_CONTENT_TYPE_0 0
60 #define HDCP_CONTENT_TYPE_1 1
61
62 #define LIC_PERIOD_MSEC (4 * 1000)
63 /* Kernel retry count=3, Max time per authentication allowed = 6Sec */
64 #define KERNEL_AUTH_TIME_ALLOWED_MSEC (3 * 6 * 1000)
65 #define KERNEL_DISABLE_TIME_ALLOWED_MSEC (1 * 1000)
66 #define FLIP_EVENT_POLLING_TIMEOUT_MSEC 1000
67
68 __u8 facsimile_srm[] = {
69 0x80, 0x0, 0x0, 0x05, 0x01, 0x0, 0x0, 0x36, 0x02, 0x51, 0x1E, 0xF2,
70 0x1A, 0xCD, 0xE7, 0x26, 0x97, 0xF4, 0x01, 0x97, 0x10, 0x19, 0x92, 0x53,
71 0xE9, 0xF0, 0x59, 0x95, 0xA3, 0x7A, 0x3B, 0xFE, 0xE0, 0x9C, 0x76, 0xDD,
72 0x83, 0xAA, 0xC2, 0x5B, 0x24, 0xB3, 0x36, 0x84, 0x94, 0x75, 0x34, 0xDB,
73 0x10, 0x9E, 0x3B, 0x23, 0x13, 0xD8, 0x7A, 0xC2, 0x30, 0x79, 0x84};
74
flip_handler(int fd,unsigned int sequence,unsigned int tv_sec,unsigned int tv_usec,void * _data)75 static void flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
76 unsigned int tv_usec, void *_data)
77 {
78 igt_debug("Flip event received.\n");
79 }
80
wait_flip_event(void)81 static int wait_flip_event(void)
82 {
83 int rc;
84 drmEventContext evctx;
85 struct pollfd pfd;
86
87 evctx.version = 2;
88 evctx.vblank_handler = NULL;
89 evctx.page_flip_handler = flip_handler;
90
91 pfd.fd = data.drm_fd;
92 pfd.events = POLLIN;
93 pfd.revents = 0;
94
95 rc = poll(&pfd, 1, FLIP_EVENT_POLLING_TIMEOUT_MSEC);
96 switch (rc) {
97 case 0:
98 igt_info("Poll timeout. 1Sec.\n");
99 rc = -ETIMEDOUT;
100 break;
101 case 1:
102 rc = drmHandleEvent(data.drm_fd, &evctx);
103 igt_assert_eq(rc, 0);
104 rc = 0;
105 break;
106 default:
107 igt_info("Unexpected poll rc %d\n", rc);
108 rc = -1;
109 break;
110 }
111
112 return rc;
113 }
114
hdcp_event(struct udev_monitor * uevent_monitor,struct udev * udev,uint32_t conn_id,uint32_t prop_id)115 static bool hdcp_event(struct udev_monitor *uevent_monitor,
116 struct udev *udev, uint32_t conn_id, uint32_t prop_id)
117 {
118 struct udev_device *dev;
119 dev_t udev_devnum;
120 struct stat s;
121 const char *hotplug, *connector, *property;
122 bool ret = false;
123
124 dev = udev_monitor_receive_device(uevent_monitor);
125 if (!dev)
126 goto out;
127
128 udev_devnum = udev_device_get_devnum(dev);
129 fstat(data.display.drm_fd, &s);
130
131 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
132 if (!(memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
133 hotplug && atoi(hotplug) == 1)) {
134 igt_debug("Not a Hotplug event\n");
135 goto out_dev;
136 }
137
138 connector = udev_device_get_property_value(dev, "CONNECTOR");
139 if (!(memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
140 connector && atoi(connector) == conn_id)) {
141 igt_debug("Not for connector id: %u\n", conn_id);
142 goto out_dev;
143 }
144
145 property = udev_device_get_property_value(dev, "PROPERTY");
146 if (!(memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
147 property && atoi(property) == prop_id)) {
148 igt_debug("Not for property id: %u\n", prop_id);
149 goto out_dev;
150 }
151 ret = true;
152
153 out_dev:
154 udev_device_unref(dev);
155 out:
156 return ret;
157 }
158
hdcp_udev_fini(struct udev_monitor * uevent_monitor,struct udev * udev)159 static void hdcp_udev_fini(struct udev_monitor *uevent_monitor,
160 struct udev *udev)
161 {
162 if (uevent_monitor)
163 udev_monitor_unref(uevent_monitor);
164 if (udev)
165 udev_unref(udev);
166 }
167
hdcp_udev_init(struct udev_monitor * uevent_monitor,struct udev * udev)168 static int hdcp_udev_init(struct udev_monitor *uevent_monitor,
169 struct udev *udev)
170 {
171 int ret = -EINVAL;
172
173 udev = udev_new();
174 if (!udev) {
175 igt_info("failed to create udev object\n");
176 goto out;
177 }
178
179 uevent_monitor = udev_monitor_new_from_netlink(udev, "udev");
180 if (!uevent_monitor) {
181 igt_info("failed to create udev event monitor\n");
182 goto out;
183 }
184
185 ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor,
186 "drm",
187 "drm_minor");
188 if (ret < 0) {
189 igt_info("failed to filter for drm events\n");
190 goto out;
191 }
192
193 ret = udev_monitor_enable_receiving(uevent_monitor);
194 if (ret < 0) {
195 igt_info("failed to enable udev event reception\n");
196 goto out;
197 }
198
199 return udev_monitor_get_fd(uevent_monitor);
200
201 out:
202 hdcp_udev_fini(uevent_monitor, udev);
203 return ret;
204 }
205
206 #define MAX_EVENTS 10
wait_for_hdcp_event(uint32_t conn_id,uint32_t prop_id,uint32_t timeout_mSec)207 static bool wait_for_hdcp_event(uint32_t conn_id, uint32_t prop_id,
208 uint32_t timeout_mSec)
209 {
210
211 struct udev_monitor *uevent_monitor = NULL;
212 struct udev *udev = NULL;
213 int udev_fd, epoll_fd;
214 struct epoll_event event, events[MAX_EVENTS];
215 bool ret = false;
216
217 udev_fd = hdcp_udev_init(uevent_monitor, udev);
218 if (udev_fd < 0)
219 return false;
220
221 epoll_fd = epoll_create1(0);
222 if (epoll_fd == -1) {
223 igt_info("Failed to create epoll fd. %d\n", epoll_fd);
224 goto out_ep_create;
225 }
226
227 event.events = EPOLLIN | EPOLLERR;
228 event.data.fd = 0;
229
230 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, udev_fd, &event)) {
231 igt_info("failed to fd into epoll\n");
232 goto out_ep_ctl;
233 }
234
235 if (epoll_wait(epoll_fd, events, MAX_EVENTS, timeout_mSec))
236 ret = hdcp_event(uevent_monitor, udev, conn_id, prop_id);
237
238 out_ep_ctl:
239 if (close(epoll_fd))
240 igt_info("failed to close the epoll fd\n");
241 out_ep_create:
242 hdcp_udev_fini(uevent_monitor, udev);
243 return ret;
244 }
245
246 static bool
wait_for_prop_value(igt_output_t * output,uint64_t expected,uint32_t timeout_mSec)247 wait_for_prop_value(igt_output_t *output, uint64_t expected,
248 uint32_t timeout_mSec)
249 {
250 uint64_t val;
251 int i;
252
253 if (data.cp_tests & CP_UEVENT && expected != CP_UNDESIRED) {
254 igt_assert_f(wait_for_hdcp_event(output->id,
255 output->props[IGT_CONNECTOR_CONTENT_PROTECTION],
256 timeout_mSec), "uevent is not received");
257
258 val = igt_output_get_prop(output,
259 IGT_CONNECTOR_CONTENT_PROTECTION);
260 if (val == expected)
261 return true;
262 } else {
263 for (i = 0; i < timeout_mSec; i++) {
264 val = igt_output_get_prop(output,
265 IGT_CONNECTOR_CONTENT_PROTECTION);
266 if (val == expected)
267 return true;
268 usleep(1000);
269 }
270 }
271
272 igt_info("prop_value mismatch %" PRId64 " != %" PRId64 "\n",
273 val, expected);
274
275 return false;
276 }
277
278 static void
commit_display_and_wait_for_flip(enum igt_commit_style s)279 commit_display_and_wait_for_flip(enum igt_commit_style s)
280 {
281 int ret;
282 uint32_t flag;
283
284 if (s == COMMIT_ATOMIC) {
285 flag = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET;
286 igt_display_commit_atomic(&data.display, flag, NULL);
287
288 ret = wait_flip_event();
289 igt_assert_f(!ret, "wait_flip_event failed. %d\n", ret);
290 } else {
291 igt_display_commit2(&data.display, s);
292
293 /* Wait for 50mSec */
294 usleep(50 * 1000);
295 }
296 }
297
modeset_with_fb(const enum pipe pipe,igt_output_t * output,enum igt_commit_style s)298 static void modeset_with_fb(const enum pipe pipe, igt_output_t *output,
299 enum igt_commit_style s)
300 {
301 igt_display_t *display = &data.display;
302 drmModeModeInfo mode;
303 igt_plane_t *primary;
304
305 igt_assert(kmstest_get_connector_default_mode(
306 display->drm_fd, output->config.connector, &mode));
307
308 igt_output_override_mode(output, &mode);
309 igt_output_set_pipe(output, pipe);
310
311 igt_create_color_fb(display->drm_fd, mode.hdisplay, mode.vdisplay,
312 DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
313 1.f, 0.f, 0.f, &data.red);
314 igt_create_color_fb(display->drm_fd, mode.hdisplay, mode.vdisplay,
315 DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
316 0.f, 1.f, 0.f, &data.green);
317
318 primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
319 igt_display_commit2(display, s);
320 igt_plane_set_fb(primary, &data.red);
321
322 /* Wait for Flip completion before starting the HDCP authentication */
323 commit_display_and_wait_for_flip(s);
324 }
325
test_cp_enable(igt_output_t * output,enum igt_commit_style s,int content_type,bool type_change)326 static bool test_cp_enable(igt_output_t *output, enum igt_commit_style s,
327 int content_type, bool type_change)
328 {
329 igt_display_t *display = &data.display;
330 igt_plane_t *primary;
331 bool ret;
332
333 primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
334
335 if (!type_change)
336 igt_output_set_prop_value(output,
337 IGT_CONNECTOR_CONTENT_PROTECTION,
338 CP_DESIRED);
339
340 if (output->props[IGT_CONNECTOR_HDCP_CONTENT_TYPE])
341 igt_output_set_prop_value(output,
342 IGT_CONNECTOR_HDCP_CONTENT_TYPE,
343 content_type);
344 igt_display_commit2(display, s);
345
346 ret = wait_for_prop_value(output, CP_ENABLED,
347 KERNEL_AUTH_TIME_ALLOWED_MSEC);
348 if (ret) {
349 igt_plane_set_fb(primary, &data.green);
350 igt_display_commit2(display, s);
351 }
352
353 return ret;
354 }
355
test_cp_disable(igt_output_t * output,enum igt_commit_style s)356 static void test_cp_disable(igt_output_t *output, enum igt_commit_style s)
357 {
358 igt_display_t *display = &data.display;
359 igt_plane_t *primary;
360 bool ret;
361
362 primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
363
364 /*
365 * Even on HDCP enable failed scenario, IGT should exit leaving the
366 * "content protection" at "UNDESIRED".
367 */
368 igt_output_set_prop_value(output, IGT_CONNECTOR_CONTENT_PROTECTION,
369 CP_UNDESIRED);
370 igt_plane_set_fb(primary, &data.red);
371 igt_display_commit2(display, s);
372
373 /* Wait for HDCP to be disabled, before crtc off */
374 ret = wait_for_prop_value(output, CP_UNDESIRED,
375 KERNEL_DISABLE_TIME_ALLOWED_MSEC);
376 igt_assert_f(ret, "Content Protection not cleared\n");
377 }
378
test_cp_enable_with_retry(igt_output_t * output,enum igt_commit_style s,int retry,int content_type,bool expect_failure,bool type_change)379 static void test_cp_enable_with_retry(igt_output_t *output,
380 enum igt_commit_style s, int retry,
381 int content_type, bool expect_failure,
382 bool type_change)
383 {
384 int retry_orig = retry;
385 bool ret;
386
387 do {
388 if (!type_change || retry_orig != retry)
389 test_cp_disable(output, s);
390
391 ret = test_cp_enable(output, s, content_type, type_change);
392
393 if (!ret && --retry)
394 igt_debug("Retry (%d/2) ...\n", 3 - retry);
395 } while (retry && !ret);
396
397 if (!ret)
398 test_cp_disable(output, s);
399
400 if (expect_failure)
401 igt_assert_f(!ret,
402 "CP Enabled. Though it is expected to fail\n");
403 else
404 igt_assert_f(ret, "Content Protection not enabled\n");
405
406 }
407
igt_pipe_is_free(igt_display_t * display,enum pipe pipe)408 static bool igt_pipe_is_free(igt_display_t *display, enum pipe pipe)
409 {
410 int i;
411
412 for (i = 0; i < display->n_outputs; i++)
413 if (display->outputs[i].pending_pipe == pipe)
414 return false;
415
416 return true;
417 }
418
test_cp_lic(igt_output_t * output)419 static void test_cp_lic(igt_output_t *output)
420 {
421 bool ret;
422
423 /* Wait for 4Secs (min 2 cycles of Link Integrity Check) */
424 ret = wait_for_prop_value(output, CP_DESIRED, LIC_PERIOD_MSEC);
425 igt_assert_f(!ret, "Content Protection LIC Failed\n");
426 }
427
write_srm_as_fw(const __u8 * srm,int len)428 static bool write_srm_as_fw(const __u8 *srm, int len)
429 {
430 int fd, ret, total = 0;
431
432 fd = open("/lib/firmware/display_hdcp_srm.bin",
433 O_WRONLY | O_CREAT, S_IRWXU);
434 do {
435 ret = write(fd, srm + total, len - total);
436 if (ret < 0)
437 ret = -errno;
438 if (ret == -EINTR || ret == -EAGAIN)
439 continue;
440 if (ret <= 0)
441 break;
442 total += ret;
443 } while (total != len);
444 close(fd);
445
446 return total < len ? false : true;
447 }
448
test_content_protection_on_output(igt_output_t * output,enum igt_commit_style s,int content_type)449 static void test_content_protection_on_output(igt_output_t *output,
450 enum igt_commit_style s,
451 int content_type)
452 {
453 igt_display_t *display = &data.display;
454 igt_plane_t *primary;
455 enum pipe pipe;
456 bool ret;
457
458 for_each_pipe(display, pipe) {
459 if (!igt_pipe_connector_valid(pipe, output))
460 continue;
461
462 /*
463 * If previous subtest of connector failed, pipe
464 * attached to that connector is not released.
465 * Because of that we have to choose the non
466 * attached pipe for this subtest.
467 */
468 if (!igt_pipe_is_free(display, pipe))
469 continue;
470
471 modeset_with_fb(pipe, output, s);
472 test_cp_enable_with_retry(output, s, 3, content_type, false,
473 false);
474
475 if (data.cp_tests & CP_TYPE_CHANGE) {
476 /* Type 1 -> Type 0 */
477 test_cp_enable_with_retry(output, s, 3,
478 HDCP_CONTENT_TYPE_0, false,
479 true);
480 /* Type 0 -> Type 1 */
481 test_cp_enable_with_retry(output, s, 3,
482 content_type, false,
483 true);
484 }
485
486 if (data.cp_tests & CP_MEI_RELOAD) {
487 igt_assert_f(!igt_kmod_unload("mei_hdcp", 0),
488 "mei_hdcp unload failed");
489
490 /* Expected to fail */
491 test_cp_enable_with_retry(output, s, 3,
492 content_type, true, false);
493
494 igt_assert_f(!igt_kmod_load("mei_hdcp", NULL),
495 "mei_hdcp load failed");
496
497 /* Expected to pass */
498 test_cp_enable_with_retry(output, s, 3,
499 content_type, false, false);
500 }
501
502 if (data.cp_tests & CP_LIC)
503 test_cp_lic(output);
504
505 if (data.cp_tests & CP_DPMS) {
506 igt_pipe_set_prop_value(display, pipe,
507 IGT_CRTC_ACTIVE, 0);
508 igt_display_commit2(display, s);
509
510 igt_pipe_set_prop_value(display, pipe,
511 IGT_CRTC_ACTIVE, 1);
512 igt_display_commit2(display, s);
513
514 ret = wait_for_prop_value(output, CP_ENABLED,
515 KERNEL_AUTH_TIME_ALLOWED_MSEC);
516 if (!ret)
517 test_cp_enable_with_retry(output, s, 2,
518 content_type, false,
519 false);
520 }
521
522 test_cp_disable(output, s);
523 primary = igt_output_get_plane_type(output,
524 DRM_PLANE_TYPE_PRIMARY);
525 igt_plane_set_fb(primary, NULL);
526 igt_output_set_pipe(output, PIPE_NONE);
527
528 /*
529 * Testing a output with a pipe is enough for HDCP
530 * testing. No ROI in testing the connector with other
531 * pipes. So Break the loop on pipe.
532 */
533 break;
534 }
535 }
536
__debugfs_read(int fd,const char * param,char * buf,int len)537 static void __debugfs_read(int fd, const char *param, char *buf, int len)
538 {
539 len = igt_debugfs_simple_read(fd, param, buf, len);
540 if (len < 0)
541 igt_assert_eq(len, -ENODEV);
542 }
543
544 #define debugfs_read(fd, p, arr) __debugfs_read(fd, p, arr, sizeof(arr))
545
546 #define MAX_SINK_HDCP_CAP_BUF_LEN 5000
547
sink_hdcp_capable(igt_output_t * output)548 static bool sink_hdcp_capable(igt_output_t *output)
549 {
550 char buf[MAX_SINK_HDCP_CAP_BUF_LEN];
551 int fd;
552
553 fd = igt_debugfs_connector_dir(data.drm_fd, output->name, O_RDONLY);
554 if (fd < 0)
555 return false;
556
557 debugfs_read(fd, "i915_hdcp_sink_capability", buf);
558 close(fd);
559
560 igt_debug("Sink capability: %s\n", buf);
561
562 return strstr(buf, "HDCP1.4");
563 }
564
sink_hdcp2_capable(igt_output_t * output)565 static bool sink_hdcp2_capable(igt_output_t *output)
566 {
567 char buf[MAX_SINK_HDCP_CAP_BUF_LEN];
568 int fd;
569
570 fd = igt_debugfs_connector_dir(data.drm_fd, output->name, O_RDONLY);
571 if (fd < 0)
572 return false;
573
574 debugfs_read(fd, "i915_hdcp_sink_capability", buf);
575 close(fd);
576
577 igt_debug("Sink capability: %s\n", buf);
578
579 return strstr(buf, "HDCP2.2");
580 }
581
582 static void
test_content_protection(enum igt_commit_style s,int content_type)583 test_content_protection(enum igt_commit_style s, int content_type)
584 {
585 igt_display_t *display = &data.display;
586 igt_output_t *output;
587 int valid_tests = 0;
588
589 if (data.cp_tests & CP_MEI_RELOAD)
590 igt_require_f(igt_kmod_is_loaded("mei_hdcp"),
591 "mei_hdcp module is not loaded\n");
592
593 for_each_connected_output(display, output) {
594 if (!output->props[IGT_CONNECTOR_CONTENT_PROTECTION])
595 continue;
596
597 if (!output->props[IGT_CONNECTOR_HDCP_CONTENT_TYPE] &&
598 content_type)
599 continue;
600
601 igt_info("CP Test execution on %s\n", output->name);
602
603 if (content_type && !sink_hdcp2_capable(output)) {
604 igt_info("\tSkip %s (Sink has no HDCP2.2 support)\n",
605 output->name);
606 continue;
607 } else if (!sink_hdcp_capable(output)) {
608 igt_info("\tSkip %s (Sink has no HDCP support)\n",
609 output->name);
610 continue;
611 }
612
613 test_content_protection_on_output(output, s, content_type);
614 valid_tests++;
615 }
616
617 igt_require_f(valid_tests, "No connector found with HDCP capability\n");
618 }
619
620 igt_main
621 {
622 igt_fixture {
623 igt_skip_on_simulation();
624
625 data.drm_fd = drm_open_driver(DRIVER_ANY);
626
627 igt_display_require(&data.display, data.drm_fd);
628 }
629
630 igt_subtest("legacy") {
631 data.cp_tests = 0;
632 test_content_protection(COMMIT_LEGACY, HDCP_CONTENT_TYPE_0);
633 }
634
635 igt_subtest("atomic") {
636 igt_require(data.display.is_atomic);
637 data.cp_tests = 0;
638 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_0);
639 }
640
641 igt_subtest("atomic-dpms") {
642 igt_require(data.display.is_atomic);
643 data.cp_tests = CP_DPMS;
644 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_0);
645 }
646
647 igt_subtest("LIC") {
648 igt_require(data.display.is_atomic);
649 data.cp_tests = CP_LIC;
650 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_0);
651 }
652
653 igt_subtest("type1") {
654 igt_require(data.display.is_atomic);
655 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_1);
656 }
657
658 igt_subtest("mei_interface") {
659 igt_require(data.display.is_atomic);
660 data.cp_tests = CP_MEI_RELOAD;
661 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_1);
662 }
663
664 igt_subtest("content_type_change") {
665 igt_require(data.display.is_atomic);
666 data.cp_tests = CP_TYPE_CHANGE;
667 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_1);
668 }
669
670 igt_subtest("uevent") {
671 igt_require(data.display.is_atomic);
672 data.cp_tests = CP_UEVENT;
673 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_0);
674 }
675
676 /*
677 * Testing the revocation check through SRM needs a HDCP sink with
678 * programmable Ksvs or we need a uAPI from kernel to read the
679 * connected HDCP sink's Ksv. With that we would be able to add that
680 * Ksv into a SRM and send in for revocation check. Since we dont have
681 * either of these options, we test SRM writing from userspace and
682 * validation of the same at kernel. Something is better than nothing.
683 */
684 igt_subtest("srm") {
685 bool ret;
686
687 igt_require(data.display.is_atomic);
688 data.cp_tests = 0;
689 ret = write_srm_as_fw((const __u8 *)facsimile_srm,
690 sizeof(facsimile_srm));
691 igt_assert_f(ret, "SRM update failed");
692 test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_0);
693 }
694
695 igt_fixture
696 igt_display_fini(&data.display);
697 }
698