Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: query hdcp capability during link detect

[Why]
Query the hdcp caps of a link, it is useful and can be reported to the user

[How]
Create a query function and call it during link detect

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Bhawanpreet Lakha and committed by
Alex Deucher
fe8db3bc 1ea2b260

+196
+56
drivers/gpu/drm/amd/display/dc/core/dc_link.c
··· 515 515 link->local_sink = prev_sink; 516 516 } 517 517 518 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 519 + static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) 520 + { 521 + struct hdcp_protection_message msg22; 522 + struct hdcp_protection_message msg14; 523 + 524 + memset(&msg22, 0, sizeof(struct hdcp_protection_message)); 525 + memset(&msg14, 0, sizeof(struct hdcp_protection_message)); 526 + memset(link->hdcp_caps.rx_caps.raw, 0, 527 + sizeof(link->hdcp_caps.rx_caps.raw)); 528 + 529 + if ((link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && 530 + link->ddc->transaction_type == 531 + DDC_TRANSACTION_TYPE_I2C_OVER_AUX) || 532 + link->connector_signal == SIGNAL_TYPE_EDP) { 533 + msg22.data = link->hdcp_caps.rx_caps.raw; 534 + msg22.length = sizeof(link->hdcp_caps.rx_caps.raw); 535 + msg22.msg_id = HDCP_MESSAGE_ID_RX_CAPS; 536 + } else { 537 + msg22.data = &link->hdcp_caps.rx_caps.fields.version; 538 + msg22.length = sizeof(link->hdcp_caps.rx_caps.fields.version); 539 + msg22.msg_id = HDCP_MESSAGE_ID_HDCP2VERSION; 540 + } 541 + msg22.version = HDCP_VERSION_22; 542 + msg22.link = HDCP_LINK_PRIMARY; 543 + msg22.max_retries = 5; 544 + dc_process_hdcp_msg(signal, link, &msg22); 545 + 546 + if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 547 + enum hdcp_message_status status = HDCP_MESSAGE_UNSUPPORTED; 548 + 549 + msg14.data = &link->hdcp_caps.bcaps.raw; 550 + msg14.length = sizeof(link->hdcp_caps.bcaps.raw); 551 + msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS; 552 + msg14.version = HDCP_VERSION_14; 553 + msg14.link = HDCP_LINK_PRIMARY; 554 + msg14.max_retries = 5; 555 + 556 + status = dc_process_hdcp_msg(signal, link, &msg14); 557 + } 558 + 559 + } 560 + #endif 561 + 518 562 static void read_current_link_settings_on_detect(struct dc_link *link) 519 563 { 520 564 union lane_count_set lane_count_set = { {0} }; ··· 651 607 dal_ddc_service_set_transaction_type(link->ddc, 652 608 sink_caps->transaction_type); 653 609 610 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 611 + /* In case of fallback to SST when topology discovery below fails 612 + * HDCP caps will be querried again later by the upper layer (caller 613 + * of this function). */ 614 + query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link); 615 + #endif 654 616 /* 655 617 * This call will initiate MST topology discovery. Which 656 618 * will detect MST ports and add new DRM connector DRM ··· 1026 976 * TODO debug why Dell 2413 doesn't like 1027 977 * two link trainings 1028 978 */ 979 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 980 + query_hdcp_capability(sink->sink_signal, link); 981 + #endif 1029 982 1030 983 // verify link cap for SST non-seamless boot 1031 984 if (!perform_dp_seamless_boot) ··· 1042 989 sink = prev_sink; 1043 990 prev_sink = NULL; 1044 991 } 992 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 993 + query_hdcp_capability(sink->sink_signal, link); 994 + #endif 1045 995 } 1046 996 1047 997 /* HDMI-DVI Dongle */
+41
drivers/gpu/drm/amd/display/dc/dc.h
··· 29 29 #include "dc_types.h" 30 30 #include "grph_object_defs.h" 31 31 #include "logger_types.h" 32 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 33 + #include "hdcp_types.h" 34 + #endif 32 35 #include "gpio_types.h" 33 36 #include "link_service_types.h" 34 37 #include "grph_object_ctrl_defs.h" ··· 1007 1004 uint8_t raw; 1008 1005 }; 1009 1006 1007 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 1008 + union hdcp_rx_caps { 1009 + struct { 1010 + uint8_t version; 1011 + uint8_t reserved; 1012 + struct { 1013 + uint8_t repeater : 1; 1014 + uint8_t hdcp_capable : 1; 1015 + uint8_t reserved : 6; 1016 + } byte0; 1017 + } fields; 1018 + uint8_t raw[3]; 1019 + }; 1020 + 1021 + union hdcp_bcaps { 1022 + struct { 1023 + uint8_t HDCP_CAPABLE:1; 1024 + uint8_t REPEATER:1; 1025 + uint8_t RESERVED:6; 1026 + } bits; 1027 + uint8_t raw; 1028 + }; 1029 + 1030 + struct hdcp_caps { 1031 + union hdcp_rx_caps rx_caps; 1032 + union hdcp_bcaps bcaps; 1033 + }; 1034 + #endif 1035 + 1010 1036 #include "dc_link.h" 1011 1037 1012 1038 /******************************************************************************* ··· 1139 1107 unsigned int dc_get_current_backlight_pwm(struct dc *dc); 1140 1108 unsigned int dc_get_target_backlight_pwm(struct dc *dc); 1141 1109 1110 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 1111 + /* 1112 + * HDCP Interfaces 1113 + */ 1114 + enum hdcp_message_status dc_process_hdcp_msg( 1115 + enum signal_type signal, 1116 + struct dc_link *link, 1117 + struct hdcp_protection_message *message_info); 1118 + #endif 1142 1119 bool dc_is_dmcu_initialized(struct dc *dc); 1143 1120 1144 1121 enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping);
+3
drivers/gpu/drm/amd/display/dc/dc_link.h
··· 126 126 uint32_t dongle_max_pix_clk; 127 127 unsigned short chip_caps; 128 128 unsigned int dpcd_sink_count; 129 + #if defined(CONFIG_DRM_AMD_DC_HDCP) 130 + struct hdcp_caps hdcp_caps; 131 + #endif 129 132 enum edp_revision edp_revision; 130 133 bool psr_feature_enabled; 131 134 bool psr_allow_active;
+89
drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
··· 322 322 .process_transaction = dp_11_process_transaction 323 323 }; 324 324 325 + static const struct protection_properties *get_protection_properties_by_signal( 326 + struct dc_link *link, 327 + enum signal_type st, 328 + enum hdcp_version version) 329 + { 330 + switch (version) { 331 + case HDCP_VERSION_14: 332 + switch (st) { 333 + case SIGNAL_TYPE_DVI_SINGLE_LINK: 334 + case SIGNAL_TYPE_DVI_DUAL_LINK: 335 + case SIGNAL_TYPE_HDMI_TYPE_A: 336 + return &hdmi_14_protection; 337 + case SIGNAL_TYPE_DISPLAY_PORT: 338 + if (link && 339 + (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER || 340 + link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) { 341 + return &non_supported_protection; 342 + } 343 + return &dp_11_protection; 344 + case SIGNAL_TYPE_DISPLAY_PORT_MST: 345 + case SIGNAL_TYPE_EDP: 346 + return &dp_11_protection; 347 + default: 348 + return &non_supported_protection; 349 + } 350 + break; 351 + case HDCP_VERSION_22: 352 + switch (st) { 353 + case SIGNAL_TYPE_DVI_SINGLE_LINK: 354 + case SIGNAL_TYPE_DVI_DUAL_LINK: 355 + case SIGNAL_TYPE_HDMI_TYPE_A: 356 + return &hdmi_14_protection; //todo version2.2 357 + case SIGNAL_TYPE_DISPLAY_PORT: 358 + case SIGNAL_TYPE_DISPLAY_PORT_MST: 359 + case SIGNAL_TYPE_EDP: 360 + return &dp_11_protection; //todo version2.2 361 + default: 362 + return &non_supported_protection; 363 + } 364 + break; 365 + default: 366 + return &non_supported_protection; 367 + } 368 + } 369 + 370 + enum hdcp_message_status dc_process_hdcp_msg( 371 + enum signal_type signal, 372 + struct dc_link *link, 373 + struct hdcp_protection_message *message_info) 374 + { 375 + enum hdcp_message_status status = HDCP_MESSAGE_FAILURE; 376 + uint32_t i = 0; 377 + 378 + const struct protection_properties *protection_props; 379 + 380 + if (!message_info) 381 + return HDCP_MESSAGE_UNSUPPORTED; 382 + 383 + if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV || 384 + message_info->msg_id >= HDCP_MESSAGE_ID_MAX) 385 + return HDCP_MESSAGE_UNSUPPORTED; 386 + 387 + protection_props = 388 + get_protection_properties_by_signal( 389 + link, 390 + signal, 391 + message_info->version); 392 + 393 + if (!protection_props->supported) 394 + return HDCP_MESSAGE_UNSUPPORTED; 395 + 396 + if (protection_props->process_transaction( 397 + link, 398 + message_info)) { 399 + status = HDCP_MESSAGE_SUCCESS; 400 + } else { 401 + for (i = 0; i < message_info->max_retries; i++) { 402 + if (protection_props->process_transaction( 403 + link, 404 + message_info)) { 405 + status = HDCP_MESSAGE_SUCCESS; 406 + break; 407 + } 408 + } 409 + } 410 + 411 + return status; 412 + } 413 +
+7
drivers/gpu/drm/amd/display/include/hdcp_types.h
··· 83 83 HDCP_LINK_SECONDARY 84 84 }; 85 85 86 + enum hdcp_message_status { 87 + HDCP_MESSAGE_SUCCESS, 88 + HDCP_MESSAGE_FAILURE, 89 + HDCP_MESSAGE_UNSUPPORTED 90 + }; 91 + 86 92 struct hdcp_protection_message { 87 93 enum hdcp_version version; 88 94 /* relevant only for DVI */ ··· 97 91 uint32_t length; 98 92 uint8_t max_retries; 99 93 uint8_t *data; 94 + enum hdcp_message_status status; 100 95 }; 101 96 102 97 #endif