Commit fe8db3bc authored by Bhawanpreet Lakha's avatar Bhawanpreet Lakha Committed by Alex Deucher

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: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 1ea2b260
......@@ -515,6 +515,50 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
link->local_sink = prev_sink;
}
#if defined(CONFIG_DRM_AMD_DC_HDCP)
static void query_hdcp_capability(enum signal_type signal, struct dc_link *link)
{
struct hdcp_protection_message msg22;
struct hdcp_protection_message msg14;
memset(&msg22, 0, sizeof(struct hdcp_protection_message));
memset(&msg14, 0, sizeof(struct hdcp_protection_message));
memset(link->hdcp_caps.rx_caps.raw, 0,
sizeof(link->hdcp_caps.rx_caps.raw));
if ((link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
link->ddc->transaction_type ==
DDC_TRANSACTION_TYPE_I2C_OVER_AUX) ||
link->connector_signal == SIGNAL_TYPE_EDP) {
msg22.data = link->hdcp_caps.rx_caps.raw;
msg22.length = sizeof(link->hdcp_caps.rx_caps.raw);
msg22.msg_id = HDCP_MESSAGE_ID_RX_CAPS;
} else {
msg22.data = &link->hdcp_caps.rx_caps.fields.version;
msg22.length = sizeof(link->hdcp_caps.rx_caps.fields.version);
msg22.msg_id = HDCP_MESSAGE_ID_HDCP2VERSION;
}
msg22.version = HDCP_VERSION_22;
msg22.link = HDCP_LINK_PRIMARY;
msg22.max_retries = 5;
dc_process_hdcp_msg(signal, link, &msg22);
if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
enum hdcp_message_status status = HDCP_MESSAGE_UNSUPPORTED;
msg14.data = &link->hdcp_caps.bcaps.raw;
msg14.length = sizeof(link->hdcp_caps.bcaps.raw);
msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS;
msg14.version = HDCP_VERSION_14;
msg14.link = HDCP_LINK_PRIMARY;
msg14.max_retries = 5;
status = dc_process_hdcp_msg(signal, link, &msg14);
}
}
#endif
static void read_current_link_settings_on_detect(struct dc_link *link)
{
union lane_count_set lane_count_set = { {0} };
......@@ -607,6 +651,12 @@ static bool detect_dp(struct dc_link *link,
dal_ddc_service_set_transaction_type(link->ddc,
sink_caps->transaction_type);
#if defined(CONFIG_DRM_AMD_DC_HDCP)
/* In case of fallback to SST when topology discovery below fails
* HDCP caps will be querried again later by the upper layer (caller
* of this function). */
query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link);
#endif
/*
* This call will initiate MST topology discovery. Which
* will detect MST ports and add new DRM connector DRM
......@@ -976,6 +1026,9 @@ static bool dc_link_detect_helper(struct dc_link *link,
* TODO debug why Dell 2413 doesn't like
* two link trainings
*/
#if defined(CONFIG_DRM_AMD_DC_HDCP)
query_hdcp_capability(sink->sink_signal, link);
#endif
// verify link cap for SST non-seamless boot
if (!perform_dp_seamless_boot)
......@@ -989,6 +1042,9 @@ static bool dc_link_detect_helper(struct dc_link *link,
sink = prev_sink;
prev_sink = NULL;
}
#if defined(CONFIG_DRM_AMD_DC_HDCP)
query_hdcp_capability(sink->sink_signal, link);
#endif
}
/* HDMI-DVI Dongle */
......
......@@ -29,6 +29,9 @@
#include "dc_types.h"
#include "grph_object_defs.h"
#include "logger_types.h"
#if defined(CONFIG_DRM_AMD_DC_HDCP)
#include "hdcp_types.h"
#endif
#include "gpio_types.h"
#include "link_service_types.h"
#include "grph_object_ctrl_defs.h"
......@@ -1004,6 +1007,35 @@ union dpcd_sink_ext_caps {
uint8_t raw;
};
#if defined(CONFIG_DRM_AMD_DC_HDCP)
union hdcp_rx_caps {
struct {
uint8_t version;
uint8_t reserved;
struct {
uint8_t repeater : 1;
uint8_t hdcp_capable : 1;
uint8_t reserved : 6;
} byte0;
} fields;
uint8_t raw[3];
};
union hdcp_bcaps {
struct {
uint8_t HDCP_CAPABLE:1;
uint8_t REPEATER:1;
uint8_t RESERVED:6;
} bits;
uint8_t raw;
};
struct hdcp_caps {
union hdcp_rx_caps rx_caps;
union hdcp_bcaps bcaps;
};
#endif
#include "dc_link.h"
/*******************************************************************************
......@@ -1107,6 +1139,15 @@ void dc_resume(struct dc *dc);
unsigned int dc_get_current_backlight_pwm(struct dc *dc);
unsigned int dc_get_target_backlight_pwm(struct dc *dc);
#if defined(CONFIG_DRM_AMD_DC_HDCP)
/*
* HDCP Interfaces
*/
enum hdcp_message_status dc_process_hdcp_msg(
enum signal_type signal,
struct dc_link *link,
struct hdcp_protection_message *message_info);
#endif
bool dc_is_dmcu_initialized(struct dc *dc);
enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping);
......
......@@ -126,6 +126,9 @@ struct dc_link {
uint32_t dongle_max_pix_clk;
unsigned short chip_caps;
unsigned int dpcd_sink_count;
#if defined(CONFIG_DRM_AMD_DC_HDCP)
struct hdcp_caps hdcp_caps;
#endif
enum edp_revision edp_revision;
bool psr_feature_enabled;
bool psr_allow_active;
......
......@@ -322,3 +322,92 @@ static const struct protection_properties dp_11_protection = {
.process_transaction = dp_11_process_transaction
};
static const struct protection_properties *get_protection_properties_by_signal(
struct dc_link *link,
enum signal_type st,
enum hdcp_version version)
{
switch (version) {
case HDCP_VERSION_14:
switch (st) {
case SIGNAL_TYPE_DVI_SINGLE_LINK:
case SIGNAL_TYPE_DVI_DUAL_LINK:
case SIGNAL_TYPE_HDMI_TYPE_A:
return &hdmi_14_protection;
case SIGNAL_TYPE_DISPLAY_PORT:
if (link &&
(link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) {
return &non_supported_protection;
}
return &dp_11_protection;
case SIGNAL_TYPE_DISPLAY_PORT_MST:
case SIGNAL_TYPE_EDP:
return &dp_11_protection;
default:
return &non_supported_protection;
}
break;
case HDCP_VERSION_22:
switch (st) {
case SIGNAL_TYPE_DVI_SINGLE_LINK:
case SIGNAL_TYPE_DVI_DUAL_LINK:
case SIGNAL_TYPE_HDMI_TYPE_A:
return &hdmi_14_protection; //todo version2.2
case SIGNAL_TYPE_DISPLAY_PORT:
case SIGNAL_TYPE_DISPLAY_PORT_MST:
case SIGNAL_TYPE_EDP:
return &dp_11_protection; //todo version2.2
default:
return &non_supported_protection;
}
break;
default:
return &non_supported_protection;
}
}
enum hdcp_message_status dc_process_hdcp_msg(
enum signal_type signal,
struct dc_link *link,
struct hdcp_protection_message *message_info)
{
enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;
uint32_t i = 0;
const struct protection_properties *protection_props;
if (!message_info)
return HDCP_MESSAGE_UNSUPPORTED;
if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||
message_info->msg_id >= HDCP_MESSAGE_ID_MAX)
return HDCP_MESSAGE_UNSUPPORTED;
protection_props =
get_protection_properties_by_signal(
link,
signal,
message_info->version);
if (!protection_props->supported)
return HDCP_MESSAGE_UNSUPPORTED;
if (protection_props->process_transaction(
link,
message_info)) {
status = HDCP_MESSAGE_SUCCESS;
} else {
for (i = 0; i < message_info->max_retries; i++) {
if (protection_props->process_transaction(
link,
message_info)) {
status = HDCP_MESSAGE_SUCCESS;
break;
}
}
}
return status;
}
......@@ -83,6 +83,12 @@ enum hdcp_link {
HDCP_LINK_SECONDARY
};
enum hdcp_message_status {
HDCP_MESSAGE_SUCCESS,
HDCP_MESSAGE_FAILURE,
HDCP_MESSAGE_UNSUPPORTED
};
struct hdcp_protection_message {
enum hdcp_version version;
/* relevant only for DVI */
......@@ -91,6 +97,7 @@ struct hdcp_protection_message {
uint32_t length;
uint8_t max_retries;
uint8_t *data;
enum hdcp_message_status status;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment