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 
mod_hdcp_hdcp2_transition(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input,struct mod_hdcp_output * output)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 		if (hdcp->state.stay_count > 10 ||
189 				input->lc_init_prepare != PASS ||
190 				input->lc_init_write != PASS ||
191 				input->l_prime_available_poll != PASS ||
192 				input->l_prime_read != PASS) {
193 			/*
194 			 * 1A-05: consider disconnection after LC init a failure
195 			 * 1A-13-1: consider invalid l' a failure
196 			 * 1A-13-2: consider l' timeout a failure
197 			 */
198 			fail_and_restart_in_ms(0, &status, output);
199 			break;
200 		} else if (input->l_prime_validation != PASS) {
201 			callback_in_ms(0, output);
202 			increment_stay_counter(hdcp);
203 			break;
204 		}
205 		callback_in_ms(0, output);
206 		set_state_id(hdcp, output, H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER);
207 		break;
208 	case H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
209 		if (input->eks_prepare != PASS ||
210 				input->eks_write != PASS) {
211 			fail_and_restart_in_ms(0, &status, output);
212 			break;
213 		}
214 		if (conn->is_repeater) {
215 			set_watchdog_in_ms(hdcp, 3000, output);
216 			callback_in_ms(0, output);
217 			set_state_id(hdcp, output, H2_A6_WAIT_FOR_RX_ID_LIST);
218 		} else {
219 			/* some CTS equipment requires a delay GREATER than
220 			 * 200 ms, so delay 210 ms instead of 200 ms
221 			 */
222 			callback_in_ms(210, output);
223 			set_state_id(hdcp, output, H2_ENABLE_ENCRYPTION);
224 		}
225 		break;
226 	case H2_ENABLE_ENCRYPTION:
227 		if (input->rxstatus_read != PASS ||
228 				input->reauth_request_check != PASS) {
229 			/*
230 			 * 1A-07: restart hdcp on REAUTH_REQ
231 			 * 1B-08: restart hdcp on REAUTH_REQ
232 			 */
233 			fail_and_restart_in_ms(0, &status, output);
234 			break;
235 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
236 			callback_in_ms(0, output);
237 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
238 			break;
239 		} else if (input->enable_encryption != PASS) {
240 			fail_and_restart_in_ms(0, &status, output);
241 			break;
242 		}
243 		callback_in_ms(0, output);
244 		set_state_id(hdcp, output, H2_A5_AUTHENTICATED);
245 		set_auth_complete(hdcp, output);
246 		break;
247 	case H2_A5_AUTHENTICATED:
248 		if (input->rxstatus_read == FAIL ||
249 				input->reauth_request_check == FAIL) {
250 			fail_and_restart_in_ms(0, &status, output);
251 			break;
252 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
253 			callback_in_ms(0, output);
254 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
255 			break;
256 		}
257 		callback_in_ms(500, output);
258 		increment_stay_counter(hdcp);
259 		break;
260 	case H2_A6_WAIT_FOR_RX_ID_LIST:
261 		if (input->rxstatus_read != PASS ||
262 				input->reauth_request_check != PASS) {
263 			fail_and_restart_in_ms(0, &status, output);
264 			break;
265 		} else if (!event_ctx->rx_id_list_ready) {
266 			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
267 				/* 1B-02: consider rx id list timeout a failure */
268 				/* some CTS equipment's actual timeout
269 				 * measurement is slightly greater than 3000 ms.
270 				 * Delay 100 ms to ensure it is fully timeout
271 				 * before re-authentication.
272 				 */
273 				fail_and_restart_in_ms(100, &status, output);
274 			} else {
275 				callback_in_ms(300, output);
276 				increment_stay_counter(hdcp);
277 			}
278 			break;
279 		}
280 		callback_in_ms(0, output);
281 		set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
282 		break;
283 	case H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
284 		if (input->rxstatus_read != PASS ||
285 				input->reauth_request_check != PASS ||
286 				input->rx_id_list_read != PASS ||
287 				input->device_count_check != PASS ||
288 				input->rx_id_list_validation != PASS ||
289 				input->repeater_auth_ack_write != PASS) {
290 			/* 1B-03: consider invalid v' a failure
291 			 * 1B-04: consider MAX_DEVS_EXCEEDED a failure
292 			 * 1B-05: consider MAX_CASCADE_EXCEEDED a failure
293 			 * 1B-06: consider invalid seq_num_V a failure
294 			 * 1B-09: consider seq_num_V rollover a failure
295 			 */
296 			fail_and_restart_in_ms(0, &status, output);
297 			break;
298 		}
299 		callback_in_ms(0, output);
300 		set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
301 		break;
302 	case H2_A9_SEND_STREAM_MANAGEMENT:
303 		if (input->rxstatus_read != PASS ||
304 				input->reauth_request_check != PASS) {
305 			fail_and_restart_in_ms(0, &status, output);
306 			break;
307 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
308 			callback_in_ms(0, output);
309 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
310 			break;
311 		} else if (input->prepare_stream_manage != PASS ||
312 				input->stream_manage_write != PASS) {
313 			fail_and_restart_in_ms(0, &status, output);
314 			break;
315 		}
316 		set_watchdog_in_ms(hdcp, 100, output);
317 		callback_in_ms(0, output);
318 		set_state_id(hdcp, output, H2_A9_VALIDATE_STREAM_READY);
319 		break;
320 	case H2_A9_VALIDATE_STREAM_READY:
321 		if (input->rxstatus_read != PASS ||
322 				input->reauth_request_check != PASS) {
323 			fail_and_restart_in_ms(0, &status, output);
324 			break;
325 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
326 			callback_in_ms(0, output);
327 			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
328 			break;
329 		} else if (input->stream_ready_available != PASS) {
330 			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
331 				/* 1B-10-2: restart content stream management on
332 				 * stream ready timeout
333 				 */
334 				hdcp->auth.count.stream_management_retry_count++;
335 				callback_in_ms(0, output);
336 				set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
337 			} else {
338 				callback_in_ms(10, output);
339 				increment_stay_counter(hdcp);
340 			}
341 			break;
342 		} else if (input->stream_ready_read != PASS ||
343 				input->stream_ready_validation != PASS) {
344 			/*
345 			 * 1B-10-1: restart content stream management
346 			 * on invalid M'
347 			 */
348 			if (hdcp->auth.count.stream_management_retry_count > 10) {
349 				fail_and_restart_in_ms(0, &status, output);
350 			} else {
351 				hdcp->auth.count.stream_management_retry_count++;
352 				callback_in_ms(0, output);
353 				set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
354 			}
355 			break;
356 		}
357 		callback_in_ms(200, output);
358 		set_state_id(hdcp, output, H2_ENABLE_ENCRYPTION);
359 		break;
360 	default:
361 		status = MOD_HDCP_STATUS_INVALID_STATE;
362 		fail_and_restart_in_ms(0, &status, output);
363 		break;
364 	}
365 
366 	return status;
367 }
368 
mod_hdcp_hdcp2_dp_transition(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input,struct mod_hdcp_output * output)369 enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp,
370 		struct mod_hdcp_event_context *event_ctx,
371 		struct mod_hdcp_transition_input_hdcp2 *input,
372 		struct mod_hdcp_output *output)
373 {
374 	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
375 	struct mod_hdcp_connection *conn = &hdcp->connection;
376 	struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
377 
378 	switch (current_state(hdcp)) {
379 	case D2_A0_DETERMINE_RX_HDCP_CAPABLE:
380 		if (input->rx_caps_read_dp != PASS ||
381 				input->hdcp2_capable_check != PASS) {
382 			adjust->hdcp2.disable = 1;
383 			callback_in_ms(0, output);
384 			set_state_id(hdcp, output, HDCP_INITIALIZED);
385 		} else {
386 			callback_in_ms(0, output);
387 			set_state_id(hdcp, output, D2_A1_SEND_AKE_INIT);
388 		}
389 		break;
390 	case D2_A1_SEND_AKE_INIT:
391 		if (input->create_session != PASS ||
392 				input->ake_init_prepare != PASS) {
393 			/* out of sync with psp state */
394 			adjust->hdcp2.disable = 1;
395 			fail_and_restart_in_ms(0, &status, output);
396 			break;
397 		} else if (input->ake_init_write != PASS) {
398 			/* possibly display not ready */
399 			fail_and_restart_in_ms(0, &status, output);
400 			break;
401 		}
402 		callback_in_ms(100, output);
403 		set_state_id(hdcp, output, D2_A1_VALIDATE_AKE_CERT);
404 		break;
405 	case D2_A1_VALIDATE_AKE_CERT:
406 		if (input->ake_cert_read != PASS ||
407 				input->ake_cert_validation != PASS) {
408 			/*
409 			 * 1A-08: consider invalid ake cert a failure
410 			 * 1A-09: consider receiver id listed in SRM a failure
411 			 */
412 			fail_and_restart_in_ms(0, &status, output);
413 			break;
414 		}
415 		if (conn->is_km_stored &&
416 				!adjust->hdcp2.force_no_stored_km) {
417 			callback_in_ms(0, output);
418 			set_state_id(hdcp, output, D2_A1_SEND_STORED_KM);
419 		} else {
420 			callback_in_ms(0, output);
421 			set_state_id(hdcp, output, D2_A1_SEND_NO_STORED_KM);
422 		}
423 		break;
424 	case D2_A1_SEND_NO_STORED_KM:
425 		if (input->no_stored_km_write != PASS) {
426 			fail_and_restart_in_ms(0, &status, output);
427 			break;
428 		}
429 		if (adjust->hdcp2.increase_h_prime_timeout)
430 			set_watchdog_in_ms(hdcp, 2000, output);
431 		else
432 			set_watchdog_in_ms(hdcp, 1000, output);
433 		set_state_id(hdcp, output, D2_A1_READ_H_PRIME);
434 		break;
435 	case D2_A1_READ_H_PRIME:
436 		if (input->h_prime_available != PASS) {
437 			if (event_ctx->event ==
438 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
439 				/* 1A-10-3: consider h' timeout a failure */
440 				fail_and_restart_in_ms(1000, &status, output);
441 			else
442 				increment_stay_counter(hdcp);
443 			break;
444 		} else if (input->h_prime_read != PASS) {
445 			fail_and_restart_in_ms(0, &status, output);
446 			break;
447 		}
448 		set_watchdog_in_ms(hdcp, 200, output);
449 		set_state_id(hdcp, output, D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME);
450 		break;
451 	case D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
452 		if (input->pairing_available != PASS) {
453 			if (event_ctx->event ==
454 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
455 				/*
456 				 * 1A-11: consider pairing info timeout
457 				 * a failure
458 				 */
459 				fail_and_restart_in_ms(0, &status, output);
460 			else
461 				increment_stay_counter(hdcp);
462 			break;
463 		} else if (input->pairing_info_read != PASS ||
464 				input->h_prime_validation != PASS) {
465 			/* 1A-10-1: consider invalid h' a failure */
466 			fail_and_restart_in_ms(0, &status, output);
467 			break;
468 		}
469 		callback_in_ms(0, output);
470 		set_state_id(hdcp, output, D2_A2_LOCALITY_CHECK);
471 		break;
472 	case D2_A1_SEND_STORED_KM:
473 		if (input->stored_km_write != PASS) {
474 			fail_and_restart_in_ms(0, &status, output);
475 			break;
476 		}
477 		set_watchdog_in_ms(hdcp, 200, output);
478 		set_state_id(hdcp, output, D2_A1_VALIDATE_H_PRIME);
479 		break;
480 	case D2_A1_VALIDATE_H_PRIME:
481 		if (input->h_prime_available != PASS) {
482 			if (event_ctx->event ==
483 					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
484 				/* 1A-10-2: consider h' timeout a failure */
485 				fail_and_restart_in_ms(1000, &status, output);
486 			else
487 				increment_stay_counter(hdcp);
488 			break;
489 		} else if (input->h_prime_read != PASS) {
490 			fail_and_restart_in_ms(0, &status, output);
491 			break;
492 		} else if (input->h_prime_validation != PASS) {
493 			/* 1A-10-1: consider invalid h' a failure */
494 			adjust->hdcp2.force_no_stored_km = 1;
495 			fail_and_restart_in_ms(0, &status, output);
496 			break;
497 		}
498 		callback_in_ms(0, output);
499 		set_state_id(hdcp, output, D2_A2_LOCALITY_CHECK);
500 		break;
501 	case D2_A2_LOCALITY_CHECK:
502 		if (hdcp->state.stay_count > 10 ||
503 				input->lc_init_prepare != PASS ||
504 				input->lc_init_write != PASS ||
505 				input->l_prime_read != PASS) {
506 			/* 1A-12: consider invalid l' a failure */
507 			fail_and_restart_in_ms(0, &status, output);
508 			break;
509 		} else if (input->l_prime_validation != PASS) {
510 			callback_in_ms(0, output);
511 			increment_stay_counter(hdcp);
512 			break;
513 		}
514 		callback_in_ms(0, output);
515 		set_state_id(hdcp, output, D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER);
516 		break;
517 	case D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
518 		if (input->eks_prepare != PASS ||
519 				input->eks_write != PASS) {
520 			fail_and_restart_in_ms(0, &status, output);
521 			break;
522 		}
523 		if (conn->is_repeater) {
524 			set_watchdog_in_ms(hdcp, 3000, output);
525 			set_state_id(hdcp, output, D2_A6_WAIT_FOR_RX_ID_LIST);
526 		} else {
527 			callback_in_ms(1, output);
528 			set_state_id(hdcp, output, D2_SEND_CONTENT_STREAM_TYPE);
529 		}
530 		break;
531 	case D2_SEND_CONTENT_STREAM_TYPE:
532 		if (input->rxstatus_read != PASS ||
533 				input->reauth_request_check != PASS ||
534 				input->link_integrity_check_dp != PASS ||
535 				input->content_stream_type_write != PASS) {
536 			fail_and_restart_in_ms(0, &status, output);
537 			break;
538 		}
539 		callback_in_ms(210, output);
540 		set_state_id(hdcp, output, D2_ENABLE_ENCRYPTION);
541 		break;
542 	case D2_ENABLE_ENCRYPTION:
543 		if (input->rxstatus_read != PASS ||
544 				input->reauth_request_check != PASS ||
545 				input->link_integrity_check_dp != PASS) {
546 			/*
547 			 * 1A-07: restart hdcp on REAUTH_REQ
548 			 * 1B-08: restart hdcp on REAUTH_REQ
549 			 */
550 			fail_and_restart_in_ms(0, &status, output);
551 			break;
552 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
553 			callback_in_ms(0, output);
554 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
555 			break;
556 		} else if (input->enable_encryption != PASS ||
557 				(is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
558 			fail_and_restart_in_ms(0, &status, output);
559 			break;
560 		}
561 		set_state_id(hdcp, output, D2_A5_AUTHENTICATED);
562 		set_auth_complete(hdcp, output);
563 		break;
564 	case D2_A5_AUTHENTICATED:
565 		if (input->rxstatus_read == FAIL ||
566 				input->reauth_request_check == FAIL) {
567 			fail_and_restart_in_ms(100, &status, output);
568 			break;
569 		} else if (input->link_integrity_check_dp == FAIL) {
570 			if (hdcp->connection.hdcp2_retry_count >= 1)
571 				adjust->hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0;
572 			fail_and_restart_in_ms(0, &status, output);
573 			break;
574 		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
575 			callback_in_ms(0, output);
576 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
577 			break;
578 		}
579 		increment_stay_counter(hdcp);
580 		break;
581 	case D2_A6_WAIT_FOR_RX_ID_LIST:
582 		if (input->rxstatus_read != PASS ||
583 				input->reauth_request_check != PASS ||
584 				input->link_integrity_check_dp != PASS) {
585 			fail_and_restart_in_ms(0, &status, output);
586 			break;
587 		} else if (!event_ctx->rx_id_list_ready) {
588 			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
589 				/* 1B-02: consider rx id list timeout a failure */
590 				fail_and_restart_in_ms(0, &status, output);
591 			else
592 				increment_stay_counter(hdcp);
593 			break;
594 		}
595 		callback_in_ms(0, output);
596 		set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
597 		break;
598 	case D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
599 		if (input->rxstatus_read != PASS ||
600 				input->reauth_request_check != PASS ||
601 				input->link_integrity_check_dp != PASS ||
602 				input->rx_id_list_read != PASS ||
603 				input->device_count_check != PASS ||
604 				input->rx_id_list_validation != PASS ||
605 				input->repeater_auth_ack_write != PASS) {
606 			/*
607 			 * 1B-03: consider invalid v' a failure
608 			 * 1B-04: consider MAX_DEVS_EXCEEDED a failure
609 			 * 1B-05: consider MAX_CASCADE_EXCEEDED a failure
610 			 * 1B-06: consider invalid seq_num_V a failure
611 			 * 1B-09: consider seq_num_V rollover a failure
612 			 */
613 			fail_and_restart_in_ms(0, &status, output);
614 			break;
615 		}
616 		callback_in_ms(0, output);
617 		set_state_id(hdcp, output, D2_A9_SEND_STREAM_MANAGEMENT);
618 		break;
619 	case D2_A9_SEND_STREAM_MANAGEMENT:
620 		if (input->rxstatus_read != PASS ||
621 				input->reauth_request_check != PASS ||
622 				input->link_integrity_check_dp != PASS) {
623 			fail_and_restart_in_ms(0, &status, output);
624 			break;
625 		} else if (event_ctx->rx_id_list_ready) {
626 			callback_in_ms(0, output);
627 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
628 			break;
629 		} else if (input->prepare_stream_manage != PASS ||
630 				input->stream_manage_write != PASS) {
631 			if (event_ctx->event == MOD_HDCP_EVENT_CALLBACK)
632 				fail_and_restart_in_ms(0, &status, output);
633 			else
634 				increment_stay_counter(hdcp);
635 			break;
636 		}
637 		callback_in_ms(100, output);
638 		set_state_id(hdcp, output, D2_A9_VALIDATE_STREAM_READY);
639 		break;
640 	case D2_A9_VALIDATE_STREAM_READY:
641 		if (input->rxstatus_read != PASS ||
642 				input->reauth_request_check != PASS ||
643 				input->link_integrity_check_dp != PASS) {
644 			fail_and_restart_in_ms(0, &status, output);
645 			break;
646 		} else if (event_ctx->rx_id_list_ready) {
647 			callback_in_ms(0, output);
648 			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
649 			break;
650 		} else if (input->stream_ready_read != PASS ||
651 				input->stream_ready_validation != PASS) {
652 			/*
653 			 * 1B-10-1: restart content stream management
654 			 * on invalid M'
655 			 * 1B-10-2: consider stream ready timeout a failure
656 			 */
657 			if (hdcp->auth.count.stream_management_retry_count > 10) {
658 				fail_and_restart_in_ms(0, &status, output);
659 			} else if (event_ctx->event == MOD_HDCP_EVENT_CALLBACK) {
660 				hdcp->auth.count.stream_management_retry_count++;
661 				callback_in_ms(0, output);
662 				set_state_id(hdcp, output, D2_A9_SEND_STREAM_MANAGEMENT);
663 			} else {
664 				increment_stay_counter(hdcp);
665 			}
666 			break;
667 		}
668 		callback_in_ms(200, output);
669 		set_state_id(hdcp, output, D2_ENABLE_ENCRYPTION);
670 		break;
671 	default:
672 		status = MOD_HDCP_STATUS_INVALID_STATE;
673 		fail_and_restart_in_ms(0, &status, output);
674 		break;
675 	}
676 	return status;
677 }
678