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