xref: /linux/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c (revision fcab107abe1ab5be9dbe874baa722372da8f4f73)
1 /*
2  * Copyright 2018 Advanced Micro Devices, Inc.
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 shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include "hdcp.h"
27 
28 enum mod_hdcp_status mod_hdcp_hdcp2_transition(struct mod_hdcp *hdcp,
29 		struct mod_hdcp_event_context *event_ctx,
30 		struct mod_hdcp_transition_input_hdcp2 *input,
31 		struct mod_hdcp_output *output)
32 {
33 	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
34 	struct mod_hdcp_connection *conn = &hdcp->connection;
35 	struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
36 
37 	switch (current_state(hdcp)) {
38 	case H2_A0_KNOWN_HDCP2_CAPABLE_RX:
39 		if (input->hdcp2version_read != PASS ||
40 				input->hdcp2_capable_check != PASS) {
41 			adjust->hdcp2.disable = 1;
42 			callback_in_ms(0, output);
43 			set_state_id(hdcp, output, HDCP_INITIALIZED);
44 		} else {
45 			callback_in_ms(0, output);
46 			set_state_id(hdcp, output, H2_A1_SEND_AKE_INIT);
47 		}
48 		break;
49 	case H2_A1_SEND_AKE_INIT:
50 		if (input->create_session != PASS ||
51 				input->ake_init_prepare != PASS) {
52 			/* out of sync with psp state */
53 			adjust->hdcp2.disable = 1;
54 			fail_and_restart_in_ms(0, &status, output);
55 			break;
56 		} else if (input->ake_init_write != PASS) {
57 			fail_and_restart_in_ms(0, &status, output);
58 			break;
59 		}
60 		set_watchdog_in_ms(hdcp, 100, output);
61 		callback_in_ms(0, output);
62 		set_state_id(hdcp, output, H2_A1_VALIDATE_AKE_CERT);
63 		break;
64 	case H2_A1_VALIDATE_AKE_CERT:
65 		if (input->ake_cert_available != PASS) {
66 			if (event_ctx->event ==
67 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
68 				/* 1A-08: consider ake timeout a failure */
69 				/* some hdmi receivers are not ready for HDCP
70 				 * immediately after video becomes active,
71 				 * delay 1s before retry on first HDCP message
72 				 * timeout.
73 				 */
74 				fail_and_restart_in_ms(1000, &status, output);
75 			} else {
76 				/* continue ake cert polling*/
77 				callback_in_ms(10, output);
78 				increment_stay_counter(hdcp);
79 			}
80 			break;
81 		} else if (input->ake_cert_read != PASS ||
82 				input->ake_cert_validation != PASS) {
83 			/*
84 			 * 1A-09: consider invalid ake cert a failure
85 			 * 1A-10: consider receiver id listed in SRM a failure
86 			 */
87 			fail_and_restart_in_ms(0, &status, output);
88 			break;
89 		}
90 		if (conn->is_km_stored &&
91 				!adjust->hdcp2.force_no_stored_km) {
92 			callback_in_ms(0, output);
93 			set_state_id(hdcp, output, H2_A1_SEND_STORED_KM);
94 		} else {
95 			callback_in_ms(0, output);
96 			set_state_id(hdcp, output, H2_A1_SEND_NO_STORED_KM);
97 		}
98 		break;
99 	case H2_A1_SEND_NO_STORED_KM:
100 		if (input->no_stored_km_write != PASS) {
101 			fail_and_restart_in_ms(0, &status, output);
102 			break;
103 		}
104 		if (adjust->hdcp2.increase_h_prime_timeout)
105 			set_watchdog_in_ms(hdcp, 2000, output);
106 		else
107 			set_watchdog_in_ms(hdcp, 1000, output);
108 		callback_in_ms(0, output);
109 		set_state_id(hdcp, output, H2_A1_READ_H_PRIME);
110 		break;
111 	case H2_A1_READ_H_PRIME:
112 		if (input->h_prime_available != PASS) {
113 			if (event_ctx->event ==
114 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
115 				/* 1A-11-3: consider h' timeout a failure */
116 				fail_and_restart_in_ms(1000, &status, output);
117 			} else {
118 				/* continue h' polling */
119 				callback_in_ms(100, output);
120 				increment_stay_counter(hdcp);
121 			}
122 			break;
123 		} else if (input->h_prime_read != PASS) {
124 			fail_and_restart_in_ms(0, &status, output);
125 			break;
126 		}
127 		set_watchdog_in_ms(hdcp, 200, output);
128 		callback_in_ms(0, output);
129 		set_state_id(hdcp, output, H2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME);
130 		break;
131 	case H2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
132 		if (input->pairing_available != PASS) {
133 			if (event_ctx->event ==
134 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
135 				/* 1A-12: consider pairing info timeout
136 				 * a failure
137 				 */
138 				fail_and_restart_in_ms(0, &status, output);
139 			} else {
140 				/* continue pairing info polling */
141 				callback_in_ms(20, output);
142 				increment_stay_counter(hdcp);
143 			}
144 			break;
145 		} else if (input->pairing_info_read != PASS ||
146 				input->h_prime_validation != PASS) {
147 			/* 1A-11-1: consider invalid h' a failure */
148 			fail_and_restart_in_ms(0, &status, output);
149 			break;
150 		}
151 		callback_in_ms(0, output);
152 		set_state_id(hdcp, output, H2_A2_LOCALITY_CHECK);
153 		break;
154 	case H2_A1_SEND_STORED_KM:
155 		if (input->stored_km_write != PASS) {
156 			fail_and_restart_in_ms(0, &status, output);
157 			break;
158 		}
159 		set_watchdog_in_ms(hdcp, 200, output);
160 		callback_in_ms(0, output);
161 		set_state_id(hdcp, output, H2_A1_VALIDATE_H_PRIME);
162 		break;
163 	case H2_A1_VALIDATE_H_PRIME:
164 		if (input->h_prime_available != PASS) {
165 			if (event_ctx->event ==
166 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
167 				/* 1A-11-2: consider h' timeout a failure */
168 				fail_and_restart_in_ms(1000, &status, output);
169 			} else {
170 				/* continue h' polling */
171 				callback_in_ms(20, output);
172 				increment_stay_counter(hdcp);
173 			}
174 			break;
175 		} else if (input->h_prime_read != PASS) {
176 			fail_and_restart_in_ms(0, &status, output);
177 			break;
178 		} else if (input->h_prime_validation != PASS) {
179 			/* 1A-11-1: consider invalid h' a failure */
180 			adjust->hdcp2.force_no_stored_km = 1;
181 			fail_and_restart_in_ms(0, &status, output);
182 			break;
183 		}
184 		callback_in_ms(0, output);
185 		set_state_id(hdcp, output, H2_A2_LOCALITY_CHECK);
186 		break;
187 	case H2_A2_LOCALITY_CHECK: {
188 		const bool use_fw = hdcp->config.ddc.funcs.atomic_write_poll_read_i2c
189 				&& !adjust->hdcp2.force_sw_locality_check;
190 
191 		/*
192 		 * 1A-05: consider disconnection after LC init a failure
193 		 * 1A-13-1: consider invalid l' a failure
194 		 * 1A-13-2: consider l' timeout a failure
195 		 */
196 		if (hdcp->state.stay_count > 10 ||
197 				input->lc_init_prepare != PASS ||
198 				(!use_fw && input->lc_init_write != PASS) ||
199 				(!use_fw && input->l_prime_available_poll != PASS)) {
200 			fail_and_restart_in_ms(0, &status, output);
201 			break;
202 		} else if (input->l_prime_read != PASS) {
203 			if (use_fw && hdcp->config.debug.lc_enable_sw_fallback) {
204 				adjust->hdcp2.force_sw_locality_check = true;
205 				callback_in_ms(0, output);
206 				break;
207 			}
208 
209 			fail_and_restart_in_ms(0, &status, output);
210 			break;
211 		} else if (input->l_prime_validation != PASS) {
212 			callback_in_ms(0, output);
213 			increment_stay_counter(hdcp);
214 			break;
215 		}
216 		callback_in_ms(0, output);
217 		set_state_id(hdcp, output, H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER);
218 		break;
219 	}
220 	case H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
221 		if (input->eks_prepare != PASS ||
222 				input->eks_write != PASS) {
223 			fail_and_restart_in_ms(0, &status, output);
224 			break;
225 		}
226 		if (conn->is_repeater) {
227 			set_watchdog_in_ms(hdcp, 3000, output);
228 			callback_in_ms(0, output);
229 			set_state_id(hdcp, output, H2_A6_WAIT_FOR_RX_ID_LIST);
230 		} else {
231 			/* some CTS equipment requires a delay GREATER than
232 			 * 200 ms, so delay 210 ms instead of 200 ms
233 			 */
234 			callback_in_ms(210, output);
235 			set_state_id(hdcp, output, H2_ENABLE_ENCRYPTION);
236 		}
237 		break;
238 	case H2_ENABLE_ENCRYPTION:
239 		if (input->rxstatus_read != PASS ||
240 				input->reauth_request_check != PASS) {
241 			/*
242 			 * 1A-07: restart hdcp on REAUTH_REQ
243 			 * 1B-08: restart hdcp on REAUTH_REQ
244 			 */
245 			fail_and_restart_in_ms(0, &status, output);
246 			break;
247 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
248 			callback_in_ms(0, output);
249 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
250 			break;
251 		} else if (input->enable_encryption != PASS) {
252 			fail_and_restart_in_ms(0, &status, output);
253 			break;
254 		}
255 		callback_in_ms(0, output);
256 		set_state_id(hdcp, output, H2_A5_AUTHENTICATED);
257 		set_auth_complete(hdcp, output);
258 		break;
259 	case H2_A5_AUTHENTICATED:
260 		if (input->rxstatus_read == FAIL ||
261 				input->reauth_request_check == FAIL) {
262 			fail_and_restart_in_ms(0, &status, output);
263 			break;
264 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
265 			callback_in_ms(0, output);
266 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
267 			break;
268 		}
269 		callback_in_ms(500, output);
270 		increment_stay_counter(hdcp);
271 		break;
272 	case H2_A6_WAIT_FOR_RX_ID_LIST:
273 		if (input->rxstatus_read != PASS ||
274 				input->reauth_request_check != PASS) {
275 			fail_and_restart_in_ms(0, &status, output);
276 			break;
277 		} else if (!event_ctx->rx_id_list_ready) {
278 			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
279 				/* 1B-02: consider rx id list timeout a failure */
280 				/* some CTS equipment's actual timeout
281 				 * measurement is slightly greater than 3000 ms.
282 				 * Delay 100 ms to ensure it is fully timeout
283 				 * before re-authentication.
284 				 */
285 				fail_and_restart_in_ms(100, &status, output);
286 			} else {
287 				callback_in_ms(300, output);
288 				increment_stay_counter(hdcp);
289 			}
290 			break;
291 		}
292 		callback_in_ms(0, output);
293 		set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
294 		break;
295 	case H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
296 		if (input->rxstatus_read != PASS ||
297 				input->reauth_request_check != PASS ||
298 				input->rx_id_list_read != PASS ||
299 				input->device_count_check != PASS ||
300 				input->rx_id_list_validation != PASS ||
301 				input->repeater_auth_ack_write != PASS) {
302 			/* 1B-03: consider invalid v' a failure
303 			 * 1B-04: consider MAX_DEVS_EXCEEDED a failure
304 			 * 1B-05: consider MAX_CASCADE_EXCEEDED a failure
305 			 * 1B-06: consider invalid seq_num_V a failure
306 			 * 1B-09: consider seq_num_V rollover a failure
307 			 */
308 			fail_and_restart_in_ms(0, &status, output);
309 			break;
310 		}
311 		callback_in_ms(0, output);
312 		set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
313 		break;
314 	case H2_A9_SEND_STREAM_MANAGEMENT:
315 		if (input->rxstatus_read != PASS ||
316 				input->reauth_request_check != PASS) {
317 			fail_and_restart_in_ms(0, &status, output);
318 			break;
319 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
320 			callback_in_ms(0, output);
321 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
322 			break;
323 		} else if (input->prepare_stream_manage != PASS ||
324 				input->stream_manage_write != PASS) {
325 			fail_and_restart_in_ms(0, &status, output);
326 			break;
327 		}
328 		set_watchdog_in_ms(hdcp, 100, output);
329 		callback_in_ms(0, output);
330 		set_state_id(hdcp, output, H2_A9_VALIDATE_STREAM_READY);
331 		break;
332 	case H2_A9_VALIDATE_STREAM_READY:
333 		if (input->rxstatus_read != PASS ||
334 				input->reauth_request_check != PASS) {
335 			fail_and_restart_in_ms(0, &status, output);
336 			break;
337 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
338 			callback_in_ms(0, output);
339 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
340 			break;
341 		} else if (input->stream_ready_available != PASS) {
342 			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
343 				/* 1B-10-2: restart content stream management on
344 				 * stream ready timeout
345 				 */
346 				hdcp->auth.count.stream_management_retry_count++;
347 				callback_in_ms(0, output);
348 				set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
349 			} else {
350 				callback_in_ms(10, output);
351 				increment_stay_counter(hdcp);
352 			}
353 			break;
354 		} else if (input->stream_ready_read != PASS ||
355 				input->stream_ready_validation != PASS) {
356 			/*
357 			 * 1B-10-1: restart content stream management
358 			 * on invalid M'
359 			 */
360 			if (hdcp->auth.count.stream_management_retry_count > 10) {
361 				fail_and_restart_in_ms(0, &status, output);
362 			} else {
363 				hdcp->auth.count.stream_management_retry_count++;
364 				callback_in_ms(0, output);
365 				set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
366 			}
367 			break;
368 		}
369 		callback_in_ms(200, output);
370 		set_state_id(hdcp, output, H2_ENABLE_ENCRYPTION);
371 		break;
372 	default:
373 		status = MOD_HDCP_STATUS_INVALID_STATE;
374 		fail_and_restart_in_ms(0, &status, output);
375 		break;
376 	}
377 
378 	return status;
379 }
380 
381 enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp,
382 		struct mod_hdcp_event_context *event_ctx,
383 		struct mod_hdcp_transition_input_hdcp2 *input,
384 		struct mod_hdcp_output *output)
385 {
386 	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
387 	struct mod_hdcp_connection *conn = &hdcp->connection;
388 	struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
389 
390 	switch (current_state(hdcp)) {
391 	case D2_A0_DETERMINE_RX_HDCP_CAPABLE:
392 		if (input->rx_caps_read_dp != PASS ||
393 				input->hdcp2_capable_check != PASS) {
394 			adjust->hdcp2.disable = 1;
395 			callback_in_ms(0, output);
396 			set_state_id(hdcp, output, HDCP_INITIALIZED);
397 		} else {
398 			callback_in_ms(0, output);
399 			set_state_id(hdcp, output, D2_A1_SEND_AKE_INIT);
400 		}
401 		break;
402 	case D2_A1_SEND_AKE_INIT:
403 		if (input->create_session != PASS ||
404 				input->ake_init_prepare != PASS) {
405 			/* out of sync with psp state */
406 			adjust->hdcp2.disable = 1;
407 			fail_and_restart_in_ms(0, &status, output);
408 			break;
409 		} else if (input->ake_init_write != PASS) {
410 			/* possibly display not ready */
411 			fail_and_restart_in_ms(0, &status, output);
412 			break;
413 		}
414 		callback_in_ms(100, output);
415 		set_state_id(hdcp, output, D2_A1_VALIDATE_AKE_CERT);
416 		break;
417 	case D2_A1_VALIDATE_AKE_CERT:
418 		if (input->ake_cert_read != PASS ||
419 				input->ake_cert_validation != PASS) {
420 			/*
421 			 * 1A-08: consider invalid ake cert a failure
422 			 * 1A-09: consider receiver id listed in SRM a failure
423 			 */
424 			fail_and_restart_in_ms(0, &status, output);
425 			break;
426 		}
427 		if (conn->is_km_stored &&
428 				!adjust->hdcp2.force_no_stored_km) {
429 			callback_in_ms(0, output);
430 			set_state_id(hdcp, output, D2_A1_SEND_STORED_KM);
431 		} else {
432 			callback_in_ms(0, output);
433 			set_state_id(hdcp, output, D2_A1_SEND_NO_STORED_KM);
434 		}
435 		break;
436 	case D2_A1_SEND_NO_STORED_KM:
437 		if (input->no_stored_km_write != PASS) {
438 			fail_and_restart_in_ms(0, &status, output);
439 			break;
440 		}
441 		if (adjust->hdcp2.increase_h_prime_timeout)
442 			set_watchdog_in_ms(hdcp, 2000, output);
443 		else
444 			set_watchdog_in_ms(hdcp, 1000, output);
445 		set_state_id(hdcp, output, D2_A1_READ_H_PRIME);
446 		break;
447 	case D2_A1_READ_H_PRIME:
448 		if (input->h_prime_available != PASS) {
449 			if (event_ctx->event ==
450 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
451 				/* 1A-10-3: consider h' timeout a failure */
452 				fail_and_restart_in_ms(1000, &status, output);
453 			else
454 				increment_stay_counter(hdcp);
455 			break;
456 		} else if (input->h_prime_read != PASS) {
457 			fail_and_restart_in_ms(0, &status, output);
458 			break;
459 		}
460 		set_watchdog_in_ms(hdcp, 200, output);
461 		set_state_id(hdcp, output, D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME);
462 		break;
463 	case D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
464 		if (input->pairing_available != PASS) {
465 			if (event_ctx->event ==
466 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
467 				/*
468 				 * 1A-11: consider pairing info timeout
469 				 * a failure
470 				 */
471 				fail_and_restart_in_ms(0, &status, output);
472 			else
473 				increment_stay_counter(hdcp);
474 			break;
475 		} else if (input->pairing_info_read != PASS ||
476 				input->h_prime_validation != PASS) {
477 			/* 1A-10-1: consider invalid h' a failure */
478 			fail_and_restart_in_ms(0, &status, output);
479 			break;
480 		}
481 		callback_in_ms(0, output);
482 		set_state_id(hdcp, output, D2_A2_LOCALITY_CHECK);
483 		break;
484 	case D2_A1_SEND_STORED_KM:
485 		if (input->stored_km_write != PASS) {
486 			fail_and_restart_in_ms(0, &status, output);
487 			break;
488 		}
489 		set_watchdog_in_ms(hdcp, 200, output);
490 		set_state_id(hdcp, output, D2_A1_VALIDATE_H_PRIME);
491 		break;
492 	case D2_A1_VALIDATE_H_PRIME:
493 		if (input->h_prime_available != PASS) {
494 			if (event_ctx->event ==
495 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
496 				/* 1A-10-2: consider h' timeout a failure */
497 				fail_and_restart_in_ms(1000, &status, output);
498 			else
499 				increment_stay_counter(hdcp);
500 			break;
501 		} else if (input->h_prime_read != PASS) {
502 			fail_and_restart_in_ms(0, &status, output);
503 			break;
504 		} else if (input->h_prime_validation != PASS) {
505 			/* 1A-10-1: consider invalid h' a failure */
506 			adjust->hdcp2.force_no_stored_km = 1;
507 			fail_and_restart_in_ms(0, &status, output);
508 			break;
509 		}
510 		callback_in_ms(0, output);
511 		set_state_id(hdcp, output, D2_A2_LOCALITY_CHECK);
512 		break;
513 	case D2_A2_LOCALITY_CHECK: {
514 		const bool use_fw = hdcp->config.ddc.funcs.atomic_write_poll_read_aux
515 				&& !adjust->hdcp2.force_sw_locality_check;
516 
517 		if (hdcp->state.stay_count > 10 ||
518 				input->lc_init_prepare != PASS ||
519 				(!use_fw && input->lc_init_write != PASS)) {
520 			/* 1A-12: consider invalid l' a failure */
521 			fail_and_restart_in_ms(0, &status, output);
522 			break;
523 		} else if (input->l_prime_read != PASS) {
524 			if (use_fw && hdcp->config.debug.lc_enable_sw_fallback) {
525 				adjust->hdcp2.force_sw_locality_check = true;
526 				callback_in_ms(0, output);
527 				break;
528 			}
529 
530 			fail_and_restart_in_ms(0, &status, output);
531 			break;
532 		} else if (input->l_prime_validation != PASS) {
533 			callback_in_ms(0, output);
534 			increment_stay_counter(hdcp);
535 			break;
536 		}
537 		callback_in_ms(0, output);
538 		set_state_id(hdcp, output, D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER);
539 		break;
540 	}
541 	case D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
542 		if (input->eks_prepare != PASS ||
543 				input->eks_write != PASS) {
544 			fail_and_restart_in_ms(0, &status, output);
545 			break;
546 		}
547 		if (conn->is_repeater) {
548 			set_watchdog_in_ms(hdcp, 3000, output);
549 			set_state_id(hdcp, output, D2_A6_WAIT_FOR_RX_ID_LIST);
550 		} else {
551 			callback_in_ms(1, output);
552 			set_state_id(hdcp, output, D2_SEND_CONTENT_STREAM_TYPE);
553 		}
554 		break;
555 	case D2_SEND_CONTENT_STREAM_TYPE:
556 		if (input->rxstatus_read != PASS ||
557 				input->reauth_request_check != PASS ||
558 				input->link_integrity_check_dp != PASS ||
559 				input->content_stream_type_write != PASS) {
560 			fail_and_restart_in_ms(0, &status, output);
561 			break;
562 		}
563 		callback_in_ms(210, output);
564 		set_state_id(hdcp, output, D2_ENABLE_ENCRYPTION);
565 		break;
566 	case D2_ENABLE_ENCRYPTION:
567 		if (input->rxstatus_read != PASS ||
568 				input->reauth_request_check != PASS ||
569 				input->link_integrity_check_dp != PASS) {
570 			/*
571 			 * 1A-07: restart hdcp on REAUTH_REQ
572 			 * 1B-08: restart hdcp on REAUTH_REQ
573 			 */
574 			fail_and_restart_in_ms(0, &status, output);
575 			break;
576 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
577 			callback_in_ms(0, output);
578 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
579 			break;
580 		} else if (input->enable_encryption != PASS ||
581 				(is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
582 			fail_and_restart_in_ms(0, &status, output);
583 			break;
584 		}
585 		set_state_id(hdcp, output, D2_A5_AUTHENTICATED);
586 		set_auth_complete(hdcp, output);
587 		break;
588 	case D2_A5_AUTHENTICATED:
589 		if (input->rxstatus_read == FAIL ||
590 				input->reauth_request_check == FAIL) {
591 			fail_and_restart_in_ms(100, &status, output);
592 			break;
593 		} else if (input->link_integrity_check_dp == FAIL) {
594 			if (hdcp->connection.hdcp2_retry_count >= 1)
595 				adjust->hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0;
596 			fail_and_restart_in_ms(0, &status, output);
597 			break;
598 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
599 			callback_in_ms(0, output);
600 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
601 			break;
602 		}
603 		increment_stay_counter(hdcp);
604 		break;
605 	case D2_A6_WAIT_FOR_RX_ID_LIST:
606 		if (input->rxstatus_read != PASS ||
607 				input->reauth_request_check != PASS ||
608 				input->link_integrity_check_dp != PASS) {
609 			fail_and_restart_in_ms(0, &status, output);
610 			break;
611 		} else if (!event_ctx->rx_id_list_ready) {
612 			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
613 				/* 1B-02: consider rx id list timeout a failure */
614 				fail_and_restart_in_ms(0, &status, output);
615 			else
616 				increment_stay_counter(hdcp);
617 			break;
618 		}
619 		callback_in_ms(0, output);
620 		set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
621 		break;
622 	case D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
623 		if (input->rxstatus_read != PASS ||
624 				input->reauth_request_check != PASS ||
625 				input->link_integrity_check_dp != PASS ||
626 				input->rx_id_list_read != PASS ||
627 				input->device_count_check != PASS ||
628 				input->rx_id_list_validation != PASS ||
629 				input->repeater_auth_ack_write != PASS) {
630 			/*
631 			 * 1B-03: consider invalid v' a failure
632 			 * 1B-04: consider MAX_DEVS_EXCEEDED a failure
633 			 * 1B-05: consider MAX_CASCADE_EXCEEDED a failure
634 			 * 1B-06: consider invalid seq_num_V a failure
635 			 * 1B-09: consider seq_num_V rollover a failure
636 			 */
637 			fail_and_restart_in_ms(0, &status, output);
638 			break;
639 		}
640 		callback_in_ms(0, output);
641 		set_state_id(hdcp, output, D2_A9_SEND_STREAM_MANAGEMENT);
642 		break;
643 	case D2_A9_SEND_STREAM_MANAGEMENT:
644 		if (input->rxstatus_read != PASS ||
645 				input->reauth_request_check != PASS ||
646 				input->link_integrity_check_dp != PASS) {
647 			fail_and_restart_in_ms(0, &status, output);
648 			break;
649 		} else if (event_ctx->rx_id_list_ready) {
650 			callback_in_ms(0, output);
651 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
652 			break;
653 		} else if (input->prepare_stream_manage != PASS ||
654 				input->stream_manage_write != PASS) {
655 			if (event_ctx->event == MOD_HDCP_EVENT_CALLBACK)
656 				fail_and_restart_in_ms(0, &status, output);
657 			else
658 				increment_stay_counter(hdcp);
659 			break;
660 		}
661 		callback_in_ms(100, output);
662 		set_state_id(hdcp, output, D2_A9_VALIDATE_STREAM_READY);
663 		break;
664 	case D2_A9_VALIDATE_STREAM_READY:
665 		if (input->rxstatus_read != PASS ||
666 				input->reauth_request_check != PASS ||
667 				input->link_integrity_check_dp != PASS) {
668 			fail_and_restart_in_ms(0, &status, output);
669 			break;
670 		} else if (event_ctx->rx_id_list_ready) {
671 			callback_in_ms(0, output);
672 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
673 			break;
674 		} else if (input->stream_ready_read != PASS ||
675 				input->stream_ready_validation != PASS) {
676 			/*
677 			 * 1B-10-1: restart content stream management
678 			 * on invalid M'
679 			 * 1B-10-2: consider stream ready timeout a failure
680 			 */
681 			if (hdcp->auth.count.stream_management_retry_count > 10) {
682 				fail_and_restart_in_ms(0, &status, output);
683 			} else if (event_ctx->event == MOD_HDCP_EVENT_CALLBACK) {
684 				hdcp->auth.count.stream_management_retry_count++;
685 				callback_in_ms(0, output);
686 				set_state_id(hdcp, output, D2_A9_SEND_STREAM_MANAGEMENT);
687 			} else {
688 				increment_stay_counter(hdcp);
689 			}
690 			break;
691 		}
692 		callback_in_ms(200, output);
693 		set_state_id(hdcp, output, D2_ENABLE_ENCRYPTION);
694 		break;
695 	default:
696 		status = MOD_HDCP_STATUS_INVALID_STATE;
697 		fail_and_restart_in_ms(0, &status, output);
698 		break;
699 	}
700 	return status;
701 }
702