1 /* 2 * Copyright 2018 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #define MAX_NUM_DISPLAYS 24 27 28 29 #include "hdcp.h" 30 31 #include "amdgpu.h" 32 #include "hdcp_psp.h" 33 34 enum mod_hdcp_status mod_hdcp_remove_display_topology(struct mod_hdcp *hdcp) 35 { 36 37 struct psp_context *psp = hdcp->config.psp.handle; 38 struct ta_dtm_shared_memory *dtm_cmd; 39 struct mod_hdcp_display *display = NULL; 40 uint8_t i; 41 42 dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; 43 44 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 45 if (hdcp->connection.displays[i].state == MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED) { 46 47 memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); 48 49 display = &hdcp->connection.displays[i]; 50 51 dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; 52 dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; 53 dtm_cmd->dtm_in_message.topology_update_v2.is_active = 0; 54 dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; 55 56 psp_dtm_invoke(psp, dtm_cmd->cmd_id); 57 58 if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) 59 return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; 60 61 display->state = MOD_HDCP_DISPLAY_ACTIVE; 62 HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index); 63 } 64 } 65 66 return MOD_HDCP_STATUS_SUCCESS; 67 } 68 69 enum mod_hdcp_status mod_hdcp_add_display_topology(struct mod_hdcp *hdcp) 70 { 71 struct psp_context *psp = hdcp->config.psp.handle; 72 struct ta_dtm_shared_memory *dtm_cmd; 73 struct mod_hdcp_display *display = NULL; 74 struct mod_hdcp_link *link = &hdcp->connection.link; 75 uint8_t i; 76 77 if (!psp->dtm_context.dtm_initialized) { 78 DRM_ERROR("Failed to add display topology, DTM TA is not initialized."); 79 return MOD_HDCP_STATUS_FAILURE; 80 } 81 82 dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; 83 84 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 85 if (hdcp->connection.displays[i].state == MOD_HDCP_DISPLAY_ACTIVE) { 86 display = &hdcp->connection.displays[i]; 87 88 memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); 89 90 dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; 91 dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; 92 dtm_cmd->dtm_in_message.topology_update_v2.is_active = 1; 93 dtm_cmd->dtm_in_message.topology_update_v2.controller = display->controller; 94 dtm_cmd->dtm_in_message.topology_update_v2.ddc_line = link->ddc_line; 95 dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be; 96 dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe; 97 dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id; 98 dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version = 99 TA_DTM_HDCP_VERSION_MAX_SUPPORTED__1_x; 100 dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; 101 102 psp_dtm_invoke(psp, dtm_cmd->cmd_id); 103 104 if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) 105 return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; 106 107 display->state = MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; 108 HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index); 109 } 110 } 111 112 return MOD_HDCP_STATUS_SUCCESS; 113 } 114 115 enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp) 116 { 117 118 struct psp_context *psp = hdcp->config.psp.handle; 119 struct mod_hdcp_display *display = get_first_added_display(hdcp); 120 struct ta_hdcp_shared_memory *hdcp_cmd; 121 122 if (!psp->hdcp_context.hdcp_initialized) { 123 DRM_ERROR("Failed to create hdcp session. HDCP TA is not initialized."); 124 return MOD_HDCP_STATUS_FAILURE; 125 } 126 127 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 128 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 129 130 hdcp_cmd->in_msg.hdcp1_create_session.display_handle = display->index; 131 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_CREATE_SESSION; 132 133 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 134 135 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 136 return MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE; 137 138 hdcp->auth.id = hdcp_cmd->out_msg.hdcp1_create_session.session_handle; 139 hdcp->auth.msg.hdcp1.ainfo = hdcp_cmd->out_msg.hdcp1_create_session.ainfo_primary; 140 memcpy(hdcp->auth.msg.hdcp1.aksv, hdcp_cmd->out_msg.hdcp1_create_session.aksv_primary, 141 sizeof(hdcp->auth.msg.hdcp1.aksv)); 142 memcpy(hdcp->auth.msg.hdcp1.an, hdcp_cmd->out_msg.hdcp1_create_session.an_primary, 143 sizeof(hdcp->auth.msg.hdcp1.an)); 144 145 return MOD_HDCP_STATUS_SUCCESS; 146 } 147 148 enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp) 149 { 150 151 struct psp_context *psp = hdcp->config.psp.handle; 152 struct ta_hdcp_shared_memory *hdcp_cmd; 153 154 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 155 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 156 157 hdcp_cmd->in_msg.hdcp1_destroy_session.session_handle = hdcp->auth.id; 158 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_DESTROY_SESSION; 159 160 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 161 162 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 163 return MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE; 164 165 HDCP_TOP_HDCP1_DESTROY_SESSION_TRACE(hdcp); 166 167 return MOD_HDCP_STATUS_SUCCESS; 168 } 169 170 enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp) 171 { 172 struct psp_context *psp = hdcp->config.psp.handle; 173 struct ta_hdcp_shared_memory *hdcp_cmd; 174 175 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 176 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 177 178 hdcp_cmd->in_msg.hdcp1_first_part_authentication.session_handle = hdcp->auth.id; 179 180 memcpy(hdcp_cmd->in_msg.hdcp1_first_part_authentication.bksv_primary, hdcp->auth.msg.hdcp1.bksv, 181 TA_HDCP__HDCP1_KSV_SIZE); 182 183 hdcp_cmd->in_msg.hdcp1_first_part_authentication.r0_prime_primary = hdcp->auth.msg.hdcp1.r0p; 184 hdcp_cmd->in_msg.hdcp1_first_part_authentication.bcaps = hdcp->auth.msg.hdcp1.bcaps; 185 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_FIRST_PART_AUTHENTICATION; 186 187 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 188 189 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 190 return MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE; 191 192 if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status == 193 TA_HDCP_AUTHENTICATION_STATUS__HDCP1_FIRST_PART_COMPLETE) { 194 /* needs second part of authentication */ 195 hdcp->connection.is_repeater = 1; 196 } else if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status == 197 TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED) { 198 hdcp->connection.is_repeater = 0; 199 } else 200 return MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE; 201 202 203 return MOD_HDCP_STATUS_SUCCESS; 204 } 205 206 enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp) 207 { 208 struct psp_context *psp = hdcp->config.psp.handle; 209 struct ta_hdcp_shared_memory *hdcp_cmd; 210 struct mod_hdcp_display *display = get_first_added_display(hdcp); 211 212 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 213 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 214 215 hdcp_cmd->in_msg.hdcp1_enable_encryption.session_handle = hdcp->auth.id; 216 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_ENABLE_ENCRYPTION; 217 218 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 219 220 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 221 return MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION; 222 223 if (!is_dp_mst_hdcp(hdcp)) { 224 display->state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; 225 HDCP_HDCP1_ENABLED_TRACE(hdcp, display->index); 226 } 227 return MOD_HDCP_STATUS_SUCCESS; 228 } 229 230 enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp) 231 { 232 struct psp_context *psp = hdcp->config.psp.handle; 233 struct ta_hdcp_shared_memory *hdcp_cmd; 234 235 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 236 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 237 238 hdcp_cmd->in_msg.hdcp1_second_part_authentication.session_handle = hdcp->auth.id; 239 240 hdcp_cmd->in_msg.hdcp1_second_part_authentication.ksv_list_size = hdcp->auth.msg.hdcp1.ksvlist_size; 241 memcpy(hdcp_cmd->in_msg.hdcp1_second_part_authentication.ksv_list, hdcp->auth.msg.hdcp1.ksvlist, 242 hdcp->auth.msg.hdcp1.ksvlist_size); 243 244 memcpy(hdcp_cmd->in_msg.hdcp1_second_part_authentication.v_prime, hdcp->auth.msg.hdcp1.vp, 245 sizeof(hdcp->auth.msg.hdcp1.vp)); 246 247 hdcp_cmd->in_msg.hdcp1_second_part_authentication.bstatus_binfo = 248 is_dp_hdcp(hdcp) ? hdcp->auth.msg.hdcp1.binfo_dp : hdcp->auth.msg.hdcp1.bstatus; 249 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_SECOND_PART_AUTHENTICATION; 250 251 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 252 253 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 254 return MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE; 255 256 return MOD_HDCP_STATUS_SUCCESS; 257 } 258 259 enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp *hdcp) 260 { 261 262 struct psp_context *psp = hdcp->config.psp.handle; 263 struct ta_hdcp_shared_memory *hdcp_cmd; 264 int i = 0; 265 266 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 267 268 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 269 270 if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED || 271 hdcp->connection.displays[i].adjust.disable) 272 continue; 273 274 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 275 276 hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.session_handle = hdcp->auth.id; 277 hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.display_handle = hdcp->connection.displays[i].index; 278 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_ENABLE_DP_STREAM_ENCRYPTION; 279 280 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 281 282 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 283 return MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE; 284 285 hdcp->connection.displays[i].state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; 286 HDCP_HDCP1_ENABLED_TRACE(hdcp, hdcp->connection.displays[i].index); 287 } 288 289 return MOD_HDCP_STATUS_SUCCESS; 290 } 291 292 enum mod_hdcp_status mod_hdcp_hdcp1_link_maintenance(struct mod_hdcp *hdcp) 293 { 294 struct psp_context *psp = hdcp->config.psp.handle; 295 struct ta_hdcp_shared_memory *hdcp_cmd; 296 297 hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; 298 299 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 300 301 hdcp_cmd->in_msg.hdcp1_get_encryption_status.session_handle = hdcp->auth.id; 302 303 hdcp_cmd->out_msg.hdcp1_get_encryption_status.protection_level = 0; 304 hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_GET_ENCRYPTION_STATUS; 305 306 psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); 307 308 if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) 309 return MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE; 310 311 return (hdcp_cmd->out_msg.hdcp1_get_encryption_status.protection_level == 1) 312 ? MOD_HDCP_STATUS_SUCCESS 313 : MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE; 314 } 315 316 enum mod_hdcp_status mod_hdcp_hdcp1_get_link_encryption_status(struct mod_hdcp *hdcp, 317 enum mod_hdcp_encryption_status *encryption_status) 318 { 319 *encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; 320 321 if (mod_hdcp_hdcp1_link_maintenance(hdcp) != MOD_HDCP_STATUS_SUCCESS) 322 return MOD_HDCP_STATUS_FAILURE; 323 324 *encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON; 325 326 return MOD_HDCP_STATUS_SUCCESS; 327 } 328 329