xref: /aosp_15_r20/external/igt-gpu-tools/tests/kms_content_protection.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
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