diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 135 |
1 files changed, 132 insertions, 3 deletions
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) { |