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