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>
This commit is contained in:
committed by
Alex Deucher
parent
1ea2b260eb
commit
fe8db3bcf2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user