1 /* 2 * Copyright 2019 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 static void push_error_status(struct mod_hdcp *hdcp, 29 enum mod_hdcp_status status) 30 { 31 struct mod_hdcp_trace *trace = &hdcp->connection.trace; 32 const uint8_t retry_limit = hdcp->connection.link.adjust.retry_limit; 33 34 if (trace->error_count < MAX_NUM_OF_ERROR_TRACE) { 35 trace->errors[trace->error_count].status = status; 36 trace->errors[trace->error_count].state_id = hdcp->state.id; 37 trace->error_count++; 38 HDCP_ERROR_TRACE(hdcp, status); 39 } 40 41 if (is_hdcp1(hdcp)) { 42 hdcp->connection.hdcp1_retry_count++; 43 if (hdcp->connection.hdcp1_retry_count == retry_limit) 44 hdcp->connection.link.adjust.hdcp1.disable = 1; 45 } else if (is_hdcp2(hdcp)) { 46 hdcp->connection.hdcp2_retry_count++; 47 if (hdcp->connection.hdcp2_retry_count == retry_limit) 48 hdcp->connection.link.adjust.hdcp2.disable = 1; 49 } 50 } 51 52 static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp) 53 { 54 int i, is_auth_needed = 0; 55 56 /* if all displays on the link don't need authentication, 57 * hdcp is not desired 58 */ 59 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 60 if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && 61 hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) { 62 is_auth_needed = 1; 63 break; 64 } 65 } 66 67 return is_auth_needed && 68 !hdcp->connection.link.adjust.hdcp1.disable && 69 !is_frl_hdcp(hdcp) && 70 !hdcp->connection.is_hdcp1_revoked; 71 } 72 73 static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp) 74 { 75 int i, is_auth_needed = 0; 76 77 /* if all displays on the link don't need authentication, 78 * hdcp is not desired 79 */ 80 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 81 if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && 82 hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) { 83 is_auth_needed = 1; 84 break; 85 } 86 } 87 88 return is_auth_needed && 89 !hdcp->connection.link.adjust.hdcp2.disable && 90 !hdcp->connection.is_hdcp2_revoked; 91 } 92 93 static enum mod_hdcp_status execution(struct mod_hdcp *hdcp, 94 struct mod_hdcp_event_context *event_ctx, 95 union mod_hdcp_transition_input *input) 96 { 97 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 98 99 if (is_in_initialized_state(hdcp)) { 100 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 101 event_ctx->unexpected_event = 1; 102 goto out; 103 } 104 /* initialize transition input */ 105 memset(input, 0, sizeof(union mod_hdcp_transition_input)); 106 } else if (is_in_cp_not_desired_state(hdcp)) { 107 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 108 event_ctx->unexpected_event = 1; 109 goto out; 110 } 111 } else if (is_in_hdcp1_states(hdcp)) { 112 status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1); 113 } else if (is_in_hdcp1_dp_states(hdcp)) { 114 status = mod_hdcp_hdcp1_dp_execution(hdcp, 115 event_ctx, &input->hdcp1); 116 } else if (is_in_hdcp2_states(hdcp)) { 117 status = mod_hdcp_hdcp2_execution(hdcp, event_ctx, &input->hdcp2); 118 } else if (is_in_hdcp2_dp_states(hdcp)) { 119 status = mod_hdcp_hdcp2_dp_execution(hdcp, 120 event_ctx, &input->hdcp2); 121 } else { 122 event_ctx->unexpected_event = 1; 123 goto out; 124 } 125 out: 126 return status; 127 } 128 129 static enum mod_hdcp_status transition(struct mod_hdcp *hdcp, 130 struct mod_hdcp_event_context *event_ctx, 131 union mod_hdcp_transition_input *input, 132 struct mod_hdcp_output *output) 133 { 134 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 135 136 if (event_ctx->unexpected_event) 137 goto out; 138 139 if (is_in_initialized_state(hdcp)) { 140 if (is_dp_hdcp(hdcp)) 141 if (is_cp_desired_hdcp2(hdcp)) { 142 callback_in_ms(0, output); 143 set_state_id(hdcp, output, D2_A0_DETERMINE_RX_HDCP_CAPABLE); 144 } else if (is_cp_desired_hdcp1(hdcp)) { 145 callback_in_ms(0, output); 146 set_state_id(hdcp, output, D1_A0_DETERMINE_RX_HDCP_CAPABLE); 147 } else { 148 callback_in_ms(0, output); 149 set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED); 150 set_auth_complete(hdcp, output); 151 } 152 else if (is_hdmi_dvi_sl_hdcp(hdcp)) 153 if (is_cp_desired_hdcp2(hdcp)) { 154 callback_in_ms(0, output); 155 set_state_id(hdcp, output, H2_A0_KNOWN_HDCP2_CAPABLE_RX); 156 } else if (is_cp_desired_hdcp1(hdcp)) { 157 callback_in_ms(0, output); 158 set_state_id(hdcp, output, H1_A0_WAIT_FOR_ACTIVE_RX); 159 } else { 160 callback_in_ms(0, output); 161 set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED); 162 set_auth_complete(hdcp, output); 163 } 164 else { 165 callback_in_ms(0, output); 166 set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED); 167 set_auth_complete(hdcp, output); 168 } 169 } else if (is_in_cp_not_desired_state(hdcp)) { 170 increment_stay_counter(hdcp); 171 } else if (is_in_hdcp1_states(hdcp)) { 172 status = mod_hdcp_hdcp1_transition(hdcp, 173 event_ctx, &input->hdcp1, output); 174 } else if (is_in_hdcp1_dp_states(hdcp)) { 175 status = mod_hdcp_hdcp1_dp_transition(hdcp, 176 event_ctx, &input->hdcp1, output); 177 } else if (is_in_hdcp2_states(hdcp)) { 178 status = mod_hdcp_hdcp2_transition(hdcp, 179 event_ctx, &input->hdcp2, output); 180 } else if (is_in_hdcp2_dp_states(hdcp)) { 181 status = mod_hdcp_hdcp2_dp_transition(hdcp, 182 event_ctx, &input->hdcp2, output); 183 } else { 184 status = MOD_HDCP_STATUS_INVALID_STATE; 185 } 186 out: 187 return status; 188 } 189 190 static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp, 191 struct mod_hdcp_output *output) 192 { 193 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 194 195 if (is_hdcp1(hdcp)) { 196 if (hdcp->auth.trans_input.hdcp1.create_session != UNKNOWN) { 197 /* TODO - update psp to unify create session failure 198 * recovery between hdcp1 and 2. 199 */ 200 mod_hdcp_hdcp1_destroy_session(hdcp); 201 202 } 203 204 HDCP_TOP_RESET_AUTH_TRACE(hdcp); 205 memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); 206 memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); 207 set_state_id(hdcp, output, HDCP_INITIALIZED); 208 } else if (is_hdcp2(hdcp)) { 209 if (hdcp->auth.trans_input.hdcp2.create_session == PASS) { 210 status = mod_hdcp_hdcp2_destroy_session(hdcp); 211 if (status != MOD_HDCP_STATUS_SUCCESS) { 212 output->callback_needed = 0; 213 output->watchdog_timer_needed = 0; 214 goto out; 215 } 216 } 217 218 HDCP_TOP_RESET_AUTH_TRACE(hdcp); 219 memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); 220 memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); 221 set_state_id(hdcp, output, HDCP_INITIALIZED); 222 } else if (is_in_cp_not_desired_state(hdcp)) { 223 HDCP_TOP_RESET_AUTH_TRACE(hdcp); 224 memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); 225 memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); 226 set_state_id(hdcp, output, HDCP_INITIALIZED); 227 } 228 229 out: 230 /* stop callback and watchdog requests from previous authentication*/ 231 output->watchdog_timer_stop = 1; 232 output->callback_stop = 1; 233 return status; 234 } 235 236 static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp, 237 struct mod_hdcp_output *output) 238 { 239 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 240 241 memset(output, 0, sizeof(struct mod_hdcp_output)); 242 243 status = reset_authentication(hdcp, output); 244 if (status != MOD_HDCP_STATUS_SUCCESS) 245 goto out; 246 247 if (current_state(hdcp) != HDCP_UNINITIALIZED) { 248 HDCP_TOP_RESET_CONN_TRACE(hdcp); 249 set_state_id(hdcp, output, HDCP_UNINITIALIZED); 250 } 251 memset(&hdcp->connection, 0, sizeof(hdcp->connection)); 252 out: 253 return status; 254 } 255 256 static enum mod_hdcp_status update_display_adjustments(struct mod_hdcp *hdcp, 257 struct mod_hdcp_display *display, 258 struct mod_hdcp_display_adjustment *adj) 259 { 260 enum mod_hdcp_status status = MOD_HDCP_STATUS_NOT_IMPLEMENTED; 261 262 if (is_in_authenticated_states(hdcp) && 263 is_dp_mst_hdcp(hdcp) && 264 display->adjust.disable == true && 265 adj->disable == false) { 266 display->adjust.disable = false; 267 if (is_hdcp1(hdcp)) 268 status = mod_hdcp_hdcp1_enable_dp_stream_encryption(hdcp); 269 else if (is_hdcp2(hdcp)) 270 status = mod_hdcp_hdcp2_enable_dp_stream_encryption(hdcp); 271 272 if (status != MOD_HDCP_STATUS_SUCCESS) 273 display->adjust.disable = true; 274 } 275 276 if (status == MOD_HDCP_STATUS_SUCCESS && 277 memcmp(adj, &display->adjust, 278 sizeof(struct mod_hdcp_display_adjustment)) != 0) 279 status = MOD_HDCP_STATUS_NOT_IMPLEMENTED; 280 281 return status; 282 } 283 /* 284 * Implementation of functions in mod_hdcp.h 285 */ 286 size_t mod_hdcp_get_memory_size(void) 287 { 288 return sizeof(struct mod_hdcp); 289 } 290 291 enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp, 292 struct mod_hdcp_config *config) 293 { 294 struct mod_hdcp_output output; 295 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 296 297 memset(&output, 0, sizeof(output)); 298 hdcp->config = *config; 299 HDCP_TOP_INTERFACE_TRACE(hdcp); 300 status = reset_connection(hdcp, &output); 301 if (status != MOD_HDCP_STATUS_SUCCESS) 302 push_error_status(hdcp, status); 303 return status; 304 } 305 306 enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp) 307 { 308 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 309 struct mod_hdcp_output output; 310 311 HDCP_TOP_INTERFACE_TRACE(hdcp); 312 memset(&output, 0, sizeof(output)); 313 status = reset_connection(hdcp, &output); 314 if (status == MOD_HDCP_STATUS_SUCCESS) 315 memset(hdcp, 0, sizeof(struct mod_hdcp)); 316 else 317 push_error_status(hdcp, status); 318 return status; 319 } 320 321 enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp, 322 struct mod_hdcp_link *link, struct mod_hdcp_display *display, 323 struct mod_hdcp_output *output) 324 { 325 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 326 struct mod_hdcp_display *display_container = NULL; 327 328 HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, display->index); 329 memset(output, 0, sizeof(struct mod_hdcp_output)); 330 331 /* skip inactive display */ 332 if (display->state != MOD_HDCP_DISPLAY_ACTIVE) { 333 status = MOD_HDCP_STATUS_SUCCESS; 334 goto out; 335 } 336 337 /* check existing display container */ 338 if (get_active_display_at_index(hdcp, display->index)) { 339 status = MOD_HDCP_STATUS_SUCCESS; 340 goto out; 341 } 342 343 /* find an empty display container */ 344 display_container = get_empty_display_container(hdcp); 345 if (!display_container) { 346 status = MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND; 347 goto out; 348 } 349 350 /* reset existing authentication status */ 351 status = reset_authentication(hdcp, output); 352 if (status != MOD_HDCP_STATUS_SUCCESS) 353 goto out; 354 355 /* reset retry counters */ 356 reset_retry_counts(hdcp); 357 358 /* reset trace */ 359 memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); 360 361 /* add display to connection */ 362 hdcp->connection.link = *link; 363 *display_container = *display; 364 status = mod_hdcp_add_display_to_topology(hdcp, display_container); 365 366 if (status != MOD_HDCP_STATUS_SUCCESS) 367 goto out; 368 369 /* request authentication */ 370 if (current_state(hdcp) != HDCP_INITIALIZED) 371 set_state_id(hdcp, output, HDCP_INITIALIZED); 372 callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output); 373 out: 374 if (status != MOD_HDCP_STATUS_SUCCESS) 375 push_error_status(hdcp, status); 376 377 return status; 378 } 379 380 enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp, 381 uint8_t index, struct mod_hdcp_output *output) 382 { 383 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 384 struct mod_hdcp_display *display = NULL; 385 386 HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index); 387 memset(output, 0, sizeof(struct mod_hdcp_output)); 388 389 /* find display in connection */ 390 display = get_active_display_at_index(hdcp, index); 391 if (!display) { 392 status = MOD_HDCP_STATUS_SUCCESS; 393 goto out; 394 } 395 396 /* stop current authentication */ 397 status = reset_authentication(hdcp, output); 398 if (status != MOD_HDCP_STATUS_SUCCESS) 399 goto out; 400 401 /* clear retry counters */ 402 reset_retry_counts(hdcp); 403 404 /* reset trace */ 405 memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); 406 407 /* remove display */ 408 status = mod_hdcp_remove_display_from_topology(hdcp, index); 409 if (status != MOD_HDCP_STATUS_SUCCESS) 410 goto out; 411 memset(display, 0, sizeof(struct mod_hdcp_display)); 412 413 /* request authentication when connection is not reset */ 414 if (current_state(hdcp) != HDCP_UNINITIALIZED) 415 callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, 416 output); 417 out: 418 if (status != MOD_HDCP_STATUS_SUCCESS) 419 push_error_status(hdcp, status); 420 return status; 421 } 422 423 enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp, 424 uint8_t index, 425 struct mod_hdcp_link_adjustment *link_adjust, 426 struct mod_hdcp_display_adjustment *display_adjust, 427 struct mod_hdcp_output *output) 428 { 429 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 430 struct mod_hdcp_display *display = NULL; 431 432 HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index); 433 memset(output, 0, sizeof(struct mod_hdcp_output)); 434 435 /* find display in connection */ 436 display = get_active_display_at_index(hdcp, index); 437 if (!display) { 438 status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; 439 goto out; 440 } 441 442 /* skip if no changes */ 443 if (memcmp(link_adjust, &hdcp->connection.link.adjust, 444 sizeof(struct mod_hdcp_link_adjustment)) == 0 && 445 memcmp(display_adjust, &display->adjust, 446 sizeof(struct mod_hdcp_display_adjustment)) == 0) { 447 status = MOD_HDCP_STATUS_SUCCESS; 448 goto out; 449 } 450 451 if (memcmp(link_adjust, &hdcp->connection.link.adjust, 452 sizeof(struct mod_hdcp_link_adjustment)) == 0 && 453 memcmp(display_adjust, &display->adjust, 454 sizeof(struct mod_hdcp_display_adjustment)) != 0) { 455 status = update_display_adjustments(hdcp, display, display_adjust); 456 if (status != MOD_HDCP_STATUS_NOT_IMPLEMENTED) 457 goto out; 458 } 459 460 /* stop current authentication */ 461 status = reset_authentication(hdcp, output); 462 if (status != MOD_HDCP_STATUS_SUCCESS) 463 goto out; 464 465 /* clear retry counters */ 466 reset_retry_counts(hdcp); 467 468 /* reset trace */ 469 memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); 470 471 /* set new adjustment */ 472 hdcp->connection.link.adjust = *link_adjust; 473 display->adjust = *display_adjust; 474 475 /* request authentication when connection is not reset */ 476 if (current_state(hdcp) != HDCP_UNINITIALIZED) 477 /* wait 100ms to debounce simultaneous updates for different indices */ 478 callback_in_ms(100, output); 479 480 out: 481 if (status != MOD_HDCP_STATUS_SUCCESS) 482 push_error_status(hdcp, status); 483 return status; 484 } 485 486 enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp, 487 uint8_t index, struct mod_hdcp_display_query *query) 488 { 489 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 490 struct mod_hdcp_display *display = NULL; 491 492 /* find display in connection */ 493 display = get_active_display_at_index(hdcp, index); 494 if (!display) { 495 status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; 496 goto out; 497 } 498 499 /* populate query */ 500 query->link = &hdcp->connection.link; 501 query->display = display; 502 query->trace = &hdcp->connection.trace; 503 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; 504 505 if (is_display_encryption_enabled(display)) { 506 if (is_hdcp1(hdcp)) { 507 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON; 508 } else if (is_hdcp2(hdcp)) { 509 if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0) 510 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON; 511 else if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_1) 512 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON; 513 else 514 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_ON; 515 } 516 } else { 517 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; 518 } 519 520 out: 521 return status; 522 } 523 524 enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp, 525 struct mod_hdcp_output *output) 526 { 527 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 528 529 HDCP_TOP_INTERFACE_TRACE(hdcp); 530 status = reset_connection(hdcp, output); 531 if (status != MOD_HDCP_STATUS_SUCCESS) 532 push_error_status(hdcp, status); 533 534 return status; 535 } 536 537 enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp, 538 enum mod_hdcp_event event, struct mod_hdcp_output *output) 539 { 540 enum mod_hdcp_status exec_status, trans_status, reset_status, status; 541 struct mod_hdcp_event_context event_ctx; 542 543 HDCP_EVENT_TRACE(hdcp, event); 544 memset(output, 0, sizeof(struct mod_hdcp_output)); 545 memset(&event_ctx, 0, sizeof(struct mod_hdcp_event_context)); 546 event_ctx.event = event; 547 548 /* execute and transition */ 549 exec_status = execution(hdcp, &event_ctx, &hdcp->auth.trans_input); 550 trans_status = transition( 551 hdcp, &event_ctx, &hdcp->auth.trans_input, output); 552 if (trans_status == MOD_HDCP_STATUS_SUCCESS) { 553 status = MOD_HDCP_STATUS_SUCCESS; 554 } else if (exec_status == MOD_HDCP_STATUS_SUCCESS) { 555 status = MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE; 556 push_error_status(hdcp, status); 557 } else { 558 status = exec_status; 559 push_error_status(hdcp, status); 560 } 561 562 /* reset authentication if needed */ 563 if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) { 564 mod_hdcp_log_ddc_trace(hdcp); 565 reset_status = reset_authentication(hdcp, output); 566 if (reset_status != MOD_HDCP_STATUS_SUCCESS) 567 push_error_status(hdcp, reset_status); 568 } 569 570 /* Clear CP_IRQ status if needed */ 571 if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ) { 572 status = mod_hdcp_clear_cp_irq_status(hdcp); 573 if (status != MOD_HDCP_STATUS_SUCCESS) 574 push_error_status(hdcp, status); 575 } 576 577 return status; 578 } 579 580 enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode( 581 enum signal_type signal) 582 { 583 enum mod_hdcp_operation_mode mode = MOD_HDCP_MODE_OFF; 584 585 switch (signal) { 586 case SIGNAL_TYPE_DVI_SINGLE_LINK: 587 case SIGNAL_TYPE_HDMI_TYPE_A: 588 case SIGNAL_TYPE_HDMI_FRL: 589 mode = MOD_HDCP_MODE_DEFAULT; 590 break; 591 case SIGNAL_TYPE_EDP: 592 case SIGNAL_TYPE_DISPLAY_PORT: 593 case SIGNAL_TYPE_DISPLAY_PORT_MST: 594 mode = MOD_HDCP_MODE_DP; 595 break; 596 default: 597 break; 598 } 599 600 return mode; 601 } 602