diff options
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dm_cp_psp.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 135 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h | 23 |
6 files changed, 214 insertions, 4 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 666796a0067c..10c0406778b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -454,6 +454,13 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) display->dig_fe = config->dig_fe; link->dig_be = config->dig_be; link->ddc_line = aconnector->dc_link->ddc_hw_inst + 1; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + display->stream_enc_idx = config->stream_enc_idx; + link->link_enc_idx = config->link_enc_idx; + link->phy_idx = config->phy_idx; + link->hdcp_supported_informational = dc_link_is_hdcp14(aconnector->dc_link, + aconnector->dc_sink->sink_signal) ? 1 : 0; +#endif link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw; link->dp.assr_enabled = config->assr_enabled; link->dp.mst_enabled = config->mst_enabled; @@ -637,6 +644,12 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate); hdcp_work[i].hdcp.config.psp.handle = &adev->psp; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + if (dc->ctx->dce_version == DCN_VERSION_3_1) { + hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1; + hdcp_work[i].hdcp.config.psp.caps.opm_state_query_supported = false; + } +#endif hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i); hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c; hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c; diff --git a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h index cac0b2c0d31b..8381c8f9ddb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h +++ b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h @@ -32,6 +32,11 @@ struct cp_psp_stream_config { uint8_t otg_inst; uint8_t dig_be; uint8_t dig_fe; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + uint8_t link_enc_idx; + uint8_t stream_enc_idx; + uint8_t phy_idx; +#endif uint8_t assr_enabled; uint8_t mst_enabled; void *dm_stream_ctx; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c index ee5230ccf3c4..62dd89cf70bb 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c @@ -172,6 +172,10 @@ char *mod_hdcp_status_to_str(int32_t status) return "MOD_HDCP_STATUS_HDCP2_REAUTH_LINK_INTEGRITY_FAILURE"; case MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE: return "MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE"; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + case MOD_HDCP_STATUS_UNSUPPORTED_PSP_VER_FAILURE: + return "MOD_HDCP_STATUS_UNSUPPORTED_PSP_VER_FAILURE"; +#endif default: return "MOD_HDCP_STATUS_UNKNOWN"; } diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index 06910d2fd57a..fc88fe249a50 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -44,11 +44,16 @@ static void hdcp2_message_init(struct mod_hdcp *hdcp, in->process.msg3_desc.msg_id = TA_HDCP_HDCP2_MSG_ID__NULL_MESSAGE; in->process.msg3_desc.msg_size = 0; } +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v2( + struct mod_hdcp *hdcp, uint8_t index) +#else enum mod_hdcp_status mod_hdcp_remove_display_from_topology( struct mod_hdcp *hdcp, uint8_t index) - { - struct psp_context *psp = hdcp->config.psp.handle; - struct ta_dtm_shared_memory *dtm_cmd; +#endif +{ + struct psp_context *psp = hdcp->config.psp.handle; + struct ta_dtm_shared_memory *dtm_cmd; struct mod_hdcp_display *display = get_active_display_at_index(hdcp, index); enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; @@ -79,8 +84,66 @@ enum mod_hdcp_status mod_hdcp_remove_display_from_topology( mutex_unlock(&psp->dtm_context.mutex); return status; } +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3( + struct mod_hdcp *hdcp, uint8_t index) +{ + struct psp_context *psp = hdcp->config.psp.handle; + struct ta_dtm_shared_memory *dtm_cmd; + struct mod_hdcp_display *display = + get_active_display_at_index(hdcp, index); + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; + + dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; + + if (!display || !is_display_active(display)) + return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; + + mutex_lock(&psp->dtm_context.mutex); + + memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); + + dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V3; + dtm_cmd->dtm_in_message.topology_update_v3.display_handle = display->index; + dtm_cmd->dtm_in_message.topology_update_v3.is_active = 0; + dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; + + psp_dtm_invoke(psp, dtm_cmd->cmd_id); + + if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) { + status = mod_hdcp_remove_display_from_topology_v2(hdcp, index); + if (status != MOD_HDCP_STATUS_SUCCESS) + display->state = MOD_HDCP_DISPLAY_INACTIVE; + } else { + display->state = MOD_HDCP_DISPLAY_ACTIVE; + HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index); + } + + mutex_unlock(&psp->dtm_context.mutex); + + return status; +} + +enum mod_hdcp_status mod_hdcp_remove_display_from_topology( + struct mod_hdcp *hdcp, uint8_t index) +{ + enum mod_hdcp_status status = MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; + + if (hdcp->config.psp.caps.dtm_v3_supported) + status = mod_hdcp_remove_display_from_topology_v3(hdcp, index); + else + status = mod_hdcp_remove_display_from_topology_v2(hdcp, index); + + return status; +} +#endif +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v2( + struct mod_hdcp *hdcp, struct mod_hdcp_display *display) +#else enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp, struct mod_hdcp_display *display) +#endif { struct psp_context *psp = hdcp->config.psp.handle; struct ta_dtm_shared_memory *dtm_cmd; @@ -126,6 +189,72 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp, return status; } +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3( + struct mod_hdcp *hdcp, struct mod_hdcp_display *display) +{ + struct psp_context *psp = hdcp->config.psp.handle; + struct ta_dtm_shared_memory *dtm_cmd; + struct mod_hdcp_link *link = &hdcp->connection.link; + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; + + if (!psp->dtm_context.dtm_initialized) { + DRM_INFO("Failed to add display topology, DTM TA is not initialized."); + display->state = MOD_HDCP_DISPLAY_INACTIVE; + return MOD_HDCP_STATUS_FAILURE; + } + + dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; + + mutex_lock(&psp->dtm_context.mutex); + memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); + + dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V3; + dtm_cmd->dtm_in_message.topology_update_v3.display_handle = display->index; + dtm_cmd->dtm_in_message.topology_update_v3.is_active = 1; + dtm_cmd->dtm_in_message.topology_update_v3.controller = display->controller; + dtm_cmd->dtm_in_message.topology_update_v3.ddc_line = link->ddc_line; + dtm_cmd->dtm_in_message.topology_update_v3.link_enc = link->link_enc_idx; + dtm_cmd->dtm_in_message.topology_update_v3.stream_enc = display->stream_enc_idx; + if (is_dp_hdcp(hdcp)) + dtm_cmd->dtm_in_message.topology_update_v3.is_assr = link->dp.assr_enabled; + + dtm_cmd->dtm_in_message.topology_update_v3.dp_mst_vcid = display->vc_id; + dtm_cmd->dtm_in_message.topology_update_v3.max_hdcp_supported_version = + TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_3; + dtm_cmd->dtm_in_message.topology_update_v3.encoder_type = TA_DTM_ENCODER_TYPE__DIG; + dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; + dtm_cmd->dtm_in_message.topology_update_v3.phy_id = link->phy_idx; + dtm_cmd->dtm_in_message.topology_update_v3.link_hdcp_cap = link->hdcp_supported_informational; + + psp_dtm_invoke(psp, dtm_cmd->cmd_id); + + if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) { + status = mod_hdcp_add_display_to_topology_v2(hdcp, display); + if (status != MOD_HDCP_STATUS_SUCCESS) + display->state = MOD_HDCP_DISPLAY_INACTIVE; + } else { + HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index); + } + + mutex_unlock(&psp->dtm_context.mutex); + + return status; +} + +enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp, + struct mod_hdcp_display *display) +{ + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; + + if (hdcp->config.psp.caps.dtm_v3_supported) + status = mod_hdcp_add_display_to_topology_v3(hdcp, display); + else + status = mod_hdcp_add_display_to_topology_v2(hdcp, display); + + return status; +} +#endif enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp) { diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h index 1a663dbbf810..b0b2544eaa9d 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h @@ -44,7 +44,12 @@ enum bgd_security_hdcp2_content_type { enum ta_dtm_command { TA_DTM_COMMAND__UNUSED_1 = 1, TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2, +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + TA_DTM_COMMAND__TOPOLOGY_ASSR_ENABLE, + TA_DTM_COMMAND__TOPOLOGY_UPDATE_V3 +#else TA_DTM_COMMAND__TOPOLOGY_ASSR_ENABLE +#endif }; /* DTM related enumerations */ @@ -86,6 +91,33 @@ struct ta_dtm_topology_update_input_v2 { uint32_t max_hdcp_supported_version; }; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +/* For security reason/HW may change value, these encoder type enum values are not HW register values */ +/* Security code will check real HW register values and these SW enum values */ +enum ta_dtm_encoder_type { + TA_DTM_ENCODER_TYPE__INVALID = 0, + TA_DTM_ENCODER_TYPE__DIG = 0x10 +}; + +struct ta_dtm_topology_update_input_v3 { + /* display handle is unique across the driver and is used to identify a display */ + /* for all security interfaces which reference displays such as HDCP */ + /* link_hdcp_cap means link is HDCP-capable for audio HDCP capable property(informational), not for other logic(e.g. Crossbar) */ + uint32_t display_handle; + uint32_t is_active; + uint32_t is_miracast; + uint32_t controller; + uint32_t ddc_line; + uint32_t link_enc; + uint32_t stream_enc; + uint32_t dp_mst_vcid; + uint32_t is_assr; + uint32_t max_hdcp_supported_version; + enum ta_dtm_encoder_type encoder_type; + uint32_t phy_id; + uint32_t link_hdcp_cap; +}; +#endif struct ta_dtm_topology_assr_enable { uint32_t display_topology_dig_be_index; }; @@ -99,6 +131,9 @@ struct ta_dtm_topology_assr_enable { union ta_dtm_cmd_input { struct ta_dtm_topology_update_input_v2 topology_update_v2; struct ta_dtm_topology_assr_enable topology_assr_enable; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + struct ta_dtm_topology_update_input_v3 topology_update_v3; +#endif }; union ta_dtm_cmd_output { @@ -278,6 +313,9 @@ enum ta_hdcp2_version { TA_HDCP2_VERSION_UNKNOWN = 0, TA_HDCP2_VERSION_2_0 = 20, TA_HDCP2_VERSION_2_1 = 21, +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + TA_HDCP2_VERSION_2_3 = 23, +#endif TA_HDCP2_VERSION_2_2 = 22 }; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h index acbeada5215b..2197c269e0a7 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright 2018 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -97,6 +97,9 @@ enum mod_hdcp_status { MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST, MOD_HDCP_STATUS_HDCP2_REAUTH_LINK_INTEGRITY_FAILURE, MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE, +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + MOD_HDCP_STATUS_UNSUPPORTED_PSP_VER_FAILURE, +#endif }; struct mod_hdcp_displayport { @@ -120,6 +123,13 @@ enum mod_hdcp_display_state { MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED }; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +struct mod_hdcp_psp_caps { + uint8_t dtm_v3_supported; + uint8_t opm_state_query_supported; +}; + +#endif enum mod_hdcp_display_disable_option { MOD_HDCP_DISPLAY_NOT_DISABLE = 0, MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION, @@ -152,6 +162,9 @@ struct mod_hdcp_ddc { struct mod_hdcp_psp { void *handle; void *funcs; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + struct mod_hdcp_psp_caps caps; +#endif }; struct mod_hdcp_display_adjustment { @@ -227,6 +240,9 @@ struct mod_hdcp_display { uint8_t index; uint8_t controller; uint8_t dig_fe; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + uint8_t stream_enc_idx; +#endif union { uint8_t vc_id; }; @@ -239,6 +255,11 @@ struct mod_hdcp_link { enum mod_hdcp_operation_mode mode; uint8_t dig_be; uint8_t ddc_line; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + uint8_t link_enc_idx; + uint8_t phy_idx; + uint8_t hdcp_supported_informational; +#endif union { struct mod_hdcp_displayport dp; struct mod_hdcp_hdmi hdmi; |