1c349dbc7Sjsg /* 2c349dbc7Sjsg * Copyright 2019 Advanced Micro Devices, Inc. 3c349dbc7Sjsg * 4c349dbc7Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 5c349dbc7Sjsg * copy of this software and associated documentation files (the "Software"), 6c349dbc7Sjsg * to deal in the Software without restriction, including without limitation 7c349dbc7Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c349dbc7Sjsg * and/or sell copies of the Software, and to permit persons to whom the 9c349dbc7Sjsg * Software is furnished to do so, subject to the following conditions: 10c349dbc7Sjsg * 11c349dbc7Sjsg * The above copyright notice and this permission notice shall be included in 12c349dbc7Sjsg * all copies or substantial portions of the Software. 13c349dbc7Sjsg * 14c349dbc7Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15c349dbc7Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16c349dbc7Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17c349dbc7Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18c349dbc7Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19c349dbc7Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20c349dbc7Sjsg * OTHER DEALINGS IN THE SOFTWARE. 21c349dbc7Sjsg * 22c349dbc7Sjsg * Authors: AMD 23c349dbc7Sjsg * 24c349dbc7Sjsg */ 25c349dbc7Sjsg 26c349dbc7Sjsg #include "hdcp.h" 27c349dbc7Sjsg 28c349dbc7Sjsg static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp) 29c349dbc7Sjsg { 30c349dbc7Sjsg uint64_t n = 0; 31c349dbc7Sjsg uint8_t count = 0; 32560c8523Sjsg u8 bksv[sizeof(n)] = { }; 33c349dbc7Sjsg 34560c8523Sjsg memcpy(bksv, hdcp->auth.msg.hdcp1.bksv, sizeof(hdcp->auth.msg.hdcp1.bksv)); 35560c8523Sjsg n = *(uint64_t *)bksv; 36c349dbc7Sjsg 37c349dbc7Sjsg while (n) { 38c349dbc7Sjsg count++; 39c349dbc7Sjsg n &= (n - 1); 40c349dbc7Sjsg } 41c349dbc7Sjsg return (count == 20) ? MOD_HDCP_STATUS_SUCCESS : 42c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_INVALID_BKSV; 43c349dbc7Sjsg } 44c349dbc7Sjsg 45c349dbc7Sjsg static inline enum mod_hdcp_status check_ksv_ready(struct mod_hdcp *hdcp) 46c349dbc7Sjsg { 47c349dbc7Sjsg if (is_dp_hdcp(hdcp)) 48c349dbc7Sjsg return (hdcp->auth.msg.hdcp1.bstatus & DP_BSTATUS_READY) ? 49c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS : 50c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY; 51c349dbc7Sjsg return (hdcp->auth.msg.hdcp1.bcaps & DRM_HDCP_DDC_BCAPS_KSV_FIFO_READY) ? 52c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS : 53c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY; 54c349dbc7Sjsg } 55c349dbc7Sjsg 56c349dbc7Sjsg static inline enum mod_hdcp_status check_hdcp_capable_dp(struct mod_hdcp *hdcp) 57c349dbc7Sjsg { 58c349dbc7Sjsg return (hdcp->auth.msg.hdcp1.bcaps & DP_BCAPS_HDCP_CAPABLE) ? 59c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS : 60c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE; 61c349dbc7Sjsg } 62c349dbc7Sjsg 63c349dbc7Sjsg static inline enum mod_hdcp_status check_r0p_available_dp(struct mod_hdcp *hdcp) 64c349dbc7Sjsg { 65c349dbc7Sjsg enum mod_hdcp_status status; 66c349dbc7Sjsg if (is_dp_hdcp(hdcp)) { 67c349dbc7Sjsg status = (hdcp->auth.msg.hdcp1.bstatus & 68c349dbc7Sjsg DP_BSTATUS_R0_PRIME_READY) ? 69c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS : 70c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING; 71c349dbc7Sjsg } else { 72c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_OPERATION; 73c349dbc7Sjsg } 74c349dbc7Sjsg return status; 75c349dbc7Sjsg } 76c349dbc7Sjsg 77c349dbc7Sjsg static inline enum mod_hdcp_status check_link_integrity_dp( 78c349dbc7Sjsg struct mod_hdcp *hdcp) 79c349dbc7Sjsg { 80c349dbc7Sjsg return (hdcp->auth.msg.hdcp1.bstatus & 81c349dbc7Sjsg DP_BSTATUS_LINK_FAILURE) ? 82c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE : 83c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS; 84c349dbc7Sjsg } 85c349dbc7Sjsg 86c349dbc7Sjsg static inline enum mod_hdcp_status check_no_reauthentication_request_dp( 87c349dbc7Sjsg struct mod_hdcp *hdcp) 88c349dbc7Sjsg { 89c349dbc7Sjsg return (hdcp->auth.msg.hdcp1.bstatus & DP_BSTATUS_REAUTH_REQ) ? 90c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED : 91c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS; 92c349dbc7Sjsg } 93c349dbc7Sjsg 94c349dbc7Sjsg static inline enum mod_hdcp_status check_no_max_cascade(struct mod_hdcp *hdcp) 95c349dbc7Sjsg { 96c349dbc7Sjsg enum mod_hdcp_status status; 97c349dbc7Sjsg 98c349dbc7Sjsg if (is_dp_hdcp(hdcp)) 99c349dbc7Sjsg status = DRM_HDCP_MAX_CASCADE_EXCEEDED(hdcp->auth.msg.hdcp1.binfo_dp >> 8) 100c349dbc7Sjsg ? MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE 101c349dbc7Sjsg : MOD_HDCP_STATUS_SUCCESS; 102c349dbc7Sjsg else 103c349dbc7Sjsg status = DRM_HDCP_MAX_CASCADE_EXCEEDED(hdcp->auth.msg.hdcp1.bstatus >> 8) 104c349dbc7Sjsg ? MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE 105c349dbc7Sjsg : MOD_HDCP_STATUS_SUCCESS; 106c349dbc7Sjsg return status; 107c349dbc7Sjsg } 108c349dbc7Sjsg 109c349dbc7Sjsg static inline enum mod_hdcp_status check_no_max_devs(struct mod_hdcp *hdcp) 110c349dbc7Sjsg { 111c349dbc7Sjsg enum mod_hdcp_status status; 112c349dbc7Sjsg 113c349dbc7Sjsg if (is_dp_hdcp(hdcp)) 114c349dbc7Sjsg status = DRM_HDCP_MAX_DEVICE_EXCEEDED(hdcp->auth.msg.hdcp1.binfo_dp) ? 115c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE : 116c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS; 117c349dbc7Sjsg else 118c349dbc7Sjsg status = DRM_HDCP_MAX_DEVICE_EXCEEDED(hdcp->auth.msg.hdcp1.bstatus) ? 119c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE : 120c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS; 121c349dbc7Sjsg return status; 122c349dbc7Sjsg } 123c349dbc7Sjsg 124c349dbc7Sjsg static inline uint8_t get_device_count(struct mod_hdcp *hdcp) 125c349dbc7Sjsg { 126c349dbc7Sjsg return is_dp_hdcp(hdcp) ? 127c349dbc7Sjsg DRM_HDCP_NUM_DOWNSTREAM(hdcp->auth.msg.hdcp1.binfo_dp) : 128c349dbc7Sjsg DRM_HDCP_NUM_DOWNSTREAM(hdcp->auth.msg.hdcp1.bstatus); 129c349dbc7Sjsg } 130c349dbc7Sjsg 131c349dbc7Sjsg static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) 132c349dbc7Sjsg { 1335ca02815Sjsg /* Avoid device count == 0 to do authentication */ 1345ca02815Sjsg if (0 == get_device_count(hdcp)) { 1355ca02815Sjsg return MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE; 1365ca02815Sjsg } 1375ca02815Sjsg 1385ca02815Sjsg /* Some MST display may choose to report the internal panel as an HDCP RX. 1395ca02815Sjsg * To update this condition with 1(because the immediate repeater's internal 1405ca02815Sjsg * panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). 1415ca02815Sjsg * Device count must be greater than or equal to tracked hdcp displays. 1425ca02815Sjsg */ 1435ca02815Sjsg return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ? 144c349dbc7Sjsg MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE : 145c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS; 146c349dbc7Sjsg } 147c349dbc7Sjsg 148c349dbc7Sjsg static enum mod_hdcp_status wait_for_active_rx(struct mod_hdcp *hdcp, 149c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 150c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 151c349dbc7Sjsg { 152c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 153c349dbc7Sjsg 154c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 155c349dbc7Sjsg event_ctx->unexpected_event = 1; 156c349dbc7Sjsg goto out; 157c349dbc7Sjsg } 158c349dbc7Sjsg 159c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv, 160c349dbc7Sjsg &input->bksv_read, &status, 161c349dbc7Sjsg hdcp, "bksv_read")) 162c349dbc7Sjsg goto out; 163c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 164c349dbc7Sjsg &input->bcaps_read, &status, 165c349dbc7Sjsg hdcp, "bcaps_read")) 166c349dbc7Sjsg goto out; 167c349dbc7Sjsg out: 168c349dbc7Sjsg return status; 169c349dbc7Sjsg } 170c349dbc7Sjsg 171c349dbc7Sjsg static enum mod_hdcp_status exchange_ksvs(struct mod_hdcp *hdcp, 172c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 173c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 174c349dbc7Sjsg { 175c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 176c349dbc7Sjsg 177c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 178c349dbc7Sjsg event_ctx->unexpected_event = 1; 179c349dbc7Sjsg goto out; 180c349dbc7Sjsg } 181c349dbc7Sjsg 182c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_create_session, 183c349dbc7Sjsg &input->create_session, &status, 184c349dbc7Sjsg hdcp, "create_session")) 185c349dbc7Sjsg goto out; 186c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_an, 187c349dbc7Sjsg &input->an_write, &status, 188c349dbc7Sjsg hdcp, "an_write")) 189c349dbc7Sjsg goto out; 190c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_aksv, 191c349dbc7Sjsg &input->aksv_write, &status, 192c349dbc7Sjsg hdcp, "aksv_write")) 193c349dbc7Sjsg goto out; 194c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv, 195c349dbc7Sjsg &input->bksv_read, &status, 196c349dbc7Sjsg hdcp, "bksv_read")) 197c349dbc7Sjsg goto out; 198c349dbc7Sjsg if (!mod_hdcp_execute_and_set(validate_bksv, 199c349dbc7Sjsg &input->bksv_validation, &status, 200c349dbc7Sjsg hdcp, "bksv_validation")) 201c349dbc7Sjsg goto out; 202c349dbc7Sjsg if (hdcp->auth.msg.hdcp1.ainfo) { 203c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_ainfo, 204c349dbc7Sjsg &input->ainfo_write, &status, 205c349dbc7Sjsg hdcp, "ainfo_write")) 206c349dbc7Sjsg goto out; 207c349dbc7Sjsg } 208c349dbc7Sjsg out: 209c349dbc7Sjsg return status; 210c349dbc7Sjsg } 211c349dbc7Sjsg 212c349dbc7Sjsg static enum mod_hdcp_status computations_validate_rx_test_for_repeater( 213c349dbc7Sjsg struct mod_hdcp *hdcp, 214c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 215c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 216c349dbc7Sjsg { 217c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 218c349dbc7Sjsg 219c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 220c349dbc7Sjsg event_ctx->unexpected_event = 1; 221c349dbc7Sjsg goto out; 222c349dbc7Sjsg } 223c349dbc7Sjsg 224c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_r0p, 225c349dbc7Sjsg &input->r0p_read, &status, 226c349dbc7Sjsg hdcp, "r0p_read")) 227c349dbc7Sjsg goto out; 228c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_rx, 229c349dbc7Sjsg &input->rx_validation, &status, 230c349dbc7Sjsg hdcp, "rx_validation")) 231c349dbc7Sjsg goto out; 232c349dbc7Sjsg if (hdcp->connection.is_repeater) { 233c349dbc7Sjsg if (!hdcp->connection.link.adjust.hdcp1.postpone_encryption) 234c349dbc7Sjsg if (!mod_hdcp_execute_and_set( 235c349dbc7Sjsg mod_hdcp_hdcp1_enable_encryption, 236c349dbc7Sjsg &input->encryption, &status, 237c349dbc7Sjsg hdcp, "encryption")) 238c349dbc7Sjsg goto out; 239c349dbc7Sjsg } else { 240c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption, 241c349dbc7Sjsg &input->encryption, &status, 242c349dbc7Sjsg hdcp, "encryption")) 243c349dbc7Sjsg goto out; 244c349dbc7Sjsg if (is_dp_mst_hdcp(hdcp)) 245c349dbc7Sjsg if (!mod_hdcp_execute_and_set( 246c349dbc7Sjsg mod_hdcp_hdcp1_enable_dp_stream_encryption, 247c349dbc7Sjsg &input->stream_encryption_dp, &status, 248c349dbc7Sjsg hdcp, "stream_encryption_dp")) 249c349dbc7Sjsg goto out; 250c349dbc7Sjsg } 251c349dbc7Sjsg out: 252c349dbc7Sjsg return status; 253c349dbc7Sjsg } 254c349dbc7Sjsg 255c349dbc7Sjsg static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp, 256c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 257c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 258c349dbc7Sjsg { 259c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 260c349dbc7Sjsg 261c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 262c349dbc7Sjsg event_ctx->unexpected_event = 1; 263c349dbc7Sjsg goto out; 264c349dbc7Sjsg } 265c349dbc7Sjsg 2665ca02815Sjsg mod_hdcp_execute_and_set(mod_hdcp_hdcp1_link_maintenance, 267c349dbc7Sjsg &input->link_maintenance, &status, 2685ca02815Sjsg hdcp, "link_maintenance"); 269c349dbc7Sjsg out: 270c349dbc7Sjsg return status; 271c349dbc7Sjsg } 272c349dbc7Sjsg 273c349dbc7Sjsg static enum mod_hdcp_status wait_for_ready(struct mod_hdcp *hdcp, 274c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 275c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 276c349dbc7Sjsg { 277c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 278c349dbc7Sjsg 279c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK && 280c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ && 281c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 282c349dbc7Sjsg event_ctx->unexpected_event = 1; 283c349dbc7Sjsg goto out; 284c349dbc7Sjsg } 285c349dbc7Sjsg 286c349dbc7Sjsg if (is_dp_hdcp(hdcp)) { 287c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 288c349dbc7Sjsg &input->bstatus_read, &status, 289c349dbc7Sjsg hdcp, "bstatus_read")) 290c349dbc7Sjsg goto out; 291c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_link_integrity_dp, 292c349dbc7Sjsg &input->link_integrity_check, &status, 293c349dbc7Sjsg hdcp, "link_integrity_check")) 294c349dbc7Sjsg goto out; 295c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, 296c349dbc7Sjsg &input->reauth_request_check, &status, 297c349dbc7Sjsg hdcp, "reauth_request_check")) 298c349dbc7Sjsg goto out; 299c349dbc7Sjsg } else { 300c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 301c349dbc7Sjsg &input->bcaps_read, &status, 302c349dbc7Sjsg hdcp, "bcaps_read")) 303c349dbc7Sjsg goto out; 304c349dbc7Sjsg } 305c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_ksv_ready, 306c349dbc7Sjsg &input->ready_check, &status, 307c349dbc7Sjsg hdcp, "ready_check")) 308c349dbc7Sjsg goto out; 309c349dbc7Sjsg out: 310c349dbc7Sjsg return status; 311c349dbc7Sjsg } 312c349dbc7Sjsg 313c349dbc7Sjsg static enum mod_hdcp_status read_ksv_list(struct mod_hdcp *hdcp, 314c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 315c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 316c349dbc7Sjsg { 317c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 318c349dbc7Sjsg uint8_t device_count; 319c349dbc7Sjsg 320c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 321c349dbc7Sjsg event_ctx->unexpected_event = 1; 322c349dbc7Sjsg goto out; 323c349dbc7Sjsg } 324c349dbc7Sjsg 325c349dbc7Sjsg if (is_dp_hdcp(hdcp)) { 326c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_binfo, 327c349dbc7Sjsg &input->binfo_read_dp, &status, 328c349dbc7Sjsg hdcp, "binfo_read_dp")) 329c349dbc7Sjsg goto out; 330c349dbc7Sjsg } else { 331c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 332c349dbc7Sjsg &input->bstatus_read, &status, 333c349dbc7Sjsg hdcp, "bstatus_read")) 334c349dbc7Sjsg goto out; 335c349dbc7Sjsg } 336c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_no_max_cascade, 337c349dbc7Sjsg &input->max_cascade_check, &status, 338c349dbc7Sjsg hdcp, "max_cascade_check")) 339c349dbc7Sjsg goto out; 340c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_no_max_devs, 341c349dbc7Sjsg &input->max_devs_check, &status, 342c349dbc7Sjsg hdcp, "max_devs_check")) 343c349dbc7Sjsg goto out; 344c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_device_count, 345c349dbc7Sjsg &input->device_count_check, &status, 346c349dbc7Sjsg hdcp, "device_count_check")) 347c349dbc7Sjsg goto out; 348c349dbc7Sjsg device_count = get_device_count(hdcp); 349c349dbc7Sjsg hdcp->auth.msg.hdcp1.ksvlist_size = device_count*5; 350c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_ksvlist, 351c349dbc7Sjsg &input->ksvlist_read, &status, 352c349dbc7Sjsg hdcp, "ksvlist_read")) 353c349dbc7Sjsg goto out; 354c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_vp, 355c349dbc7Sjsg &input->vp_read, &status, 356c349dbc7Sjsg hdcp, "vp_read")) 357c349dbc7Sjsg goto out; 358c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_ksvlist_vp, 359c349dbc7Sjsg &input->ksvlist_vp_validation, &status, 360c349dbc7Sjsg hdcp, "ksvlist_vp_validation")) 361c349dbc7Sjsg goto out; 362c349dbc7Sjsg if (input->encryption != PASS) 363c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption, 364c349dbc7Sjsg &input->encryption, &status, 365c349dbc7Sjsg hdcp, "encryption")) 366c349dbc7Sjsg goto out; 367c349dbc7Sjsg if (is_dp_mst_hdcp(hdcp)) 368c349dbc7Sjsg if (!mod_hdcp_execute_and_set( 369c349dbc7Sjsg mod_hdcp_hdcp1_enable_dp_stream_encryption, 370c349dbc7Sjsg &input->stream_encryption_dp, &status, 371c349dbc7Sjsg hdcp, "stream_encryption_dp")) 372c349dbc7Sjsg goto out; 373c349dbc7Sjsg out: 374c349dbc7Sjsg return status; 375c349dbc7Sjsg } 376c349dbc7Sjsg 377c349dbc7Sjsg static enum mod_hdcp_status determine_rx_hdcp_capable_dp(struct mod_hdcp *hdcp, 378c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 379c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 380c349dbc7Sjsg { 381c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 382c349dbc7Sjsg 383c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 384c349dbc7Sjsg event_ctx->unexpected_event = 1; 385c349dbc7Sjsg goto out; 386c349dbc7Sjsg } 387c349dbc7Sjsg 388c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 389c349dbc7Sjsg &input->bcaps_read, &status, 390c349dbc7Sjsg hdcp, "bcaps_read")) 391c349dbc7Sjsg goto out; 392c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_hdcp_capable_dp, 393c349dbc7Sjsg &input->hdcp_capable_dp, &status, 394c349dbc7Sjsg hdcp, "hdcp_capable_dp")) 395c349dbc7Sjsg goto out; 396c349dbc7Sjsg out: 397c349dbc7Sjsg return status; 398c349dbc7Sjsg } 399c349dbc7Sjsg 400c349dbc7Sjsg static enum mod_hdcp_status wait_for_r0_prime_dp(struct mod_hdcp *hdcp, 401c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 402c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 403c349dbc7Sjsg { 404c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 405c349dbc7Sjsg 406c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ && 407c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 408c349dbc7Sjsg event_ctx->unexpected_event = 1; 409c349dbc7Sjsg goto out; 410c349dbc7Sjsg } 411c349dbc7Sjsg 412c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 413c349dbc7Sjsg &input->bstatus_read, &status, 414c349dbc7Sjsg hdcp, "bstatus_read")) 415c349dbc7Sjsg goto out; 416c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_r0p_available_dp, 417c349dbc7Sjsg &input->r0p_available_dp, &status, 418c349dbc7Sjsg hdcp, "r0p_available_dp")) 419c349dbc7Sjsg goto out; 420c349dbc7Sjsg out: 421c349dbc7Sjsg return status; 422c349dbc7Sjsg } 423c349dbc7Sjsg 424c349dbc7Sjsg static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp, 425c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 426c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 427c349dbc7Sjsg { 428c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 429c349dbc7Sjsg 430c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ) { 431c349dbc7Sjsg event_ctx->unexpected_event = 1; 432c349dbc7Sjsg goto out; 433c349dbc7Sjsg } 434c349dbc7Sjsg 435*c11f9634Sjsg mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 436c349dbc7Sjsg &input->bstatus_read, &status, 437*c11f9634Sjsg hdcp, "bstatus_read"); 438*c11f9634Sjsg 439*c11f9634Sjsg mod_hdcp_execute_and_set(check_link_integrity_dp, 440c349dbc7Sjsg &input->link_integrity_check, &status, 441*c11f9634Sjsg hdcp, "link_integrity_check"); 442*c11f9634Sjsg 443*c11f9634Sjsg mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, 444c349dbc7Sjsg &input->reauth_request_check, &status, 445*c11f9634Sjsg hdcp, "reauth_request_check"); 446*c11f9634Sjsg 447c349dbc7Sjsg out: 448c349dbc7Sjsg return status; 449c349dbc7Sjsg } 450c349dbc7Sjsg 451c349dbc7Sjsg uint8_t mod_hdcp_execute_and_set( 452c349dbc7Sjsg mod_hdcp_action func, uint8_t *flag, 453c349dbc7Sjsg enum mod_hdcp_status *status, struct mod_hdcp *hdcp, char *str) 454c349dbc7Sjsg { 455c349dbc7Sjsg *status = func(hdcp); 456c349dbc7Sjsg if (*status == MOD_HDCP_STATUS_SUCCESS && *flag != PASS) { 457c349dbc7Sjsg HDCP_INPUT_PASS_TRACE(hdcp, str); 458c349dbc7Sjsg *flag = PASS; 459c349dbc7Sjsg } else if (*status != MOD_HDCP_STATUS_SUCCESS && *flag != FAIL) { 460c349dbc7Sjsg HDCP_INPUT_FAIL_TRACE(hdcp, str); 461c349dbc7Sjsg *flag = FAIL; 462c349dbc7Sjsg } 463c349dbc7Sjsg return (*status == MOD_HDCP_STATUS_SUCCESS); 464c349dbc7Sjsg } 465c349dbc7Sjsg 466c349dbc7Sjsg enum mod_hdcp_status mod_hdcp_hdcp1_execution(struct mod_hdcp *hdcp, 467c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 468c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 469c349dbc7Sjsg { 470c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 471c349dbc7Sjsg 472c349dbc7Sjsg switch (current_state(hdcp)) { 473c349dbc7Sjsg case H1_A0_WAIT_FOR_ACTIVE_RX: 474c349dbc7Sjsg status = wait_for_active_rx(hdcp, event_ctx, input); 475c349dbc7Sjsg break; 476c349dbc7Sjsg case H1_A1_EXCHANGE_KSVS: 477c349dbc7Sjsg status = exchange_ksvs(hdcp, event_ctx, input); 478c349dbc7Sjsg break; 479c349dbc7Sjsg case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER: 480c349dbc7Sjsg status = computations_validate_rx_test_for_repeater(hdcp, 481c349dbc7Sjsg event_ctx, input); 482c349dbc7Sjsg break; 483c349dbc7Sjsg case H1_A45_AUTHENTICATED: 484c349dbc7Sjsg status = authenticated(hdcp, event_ctx, input); 485c349dbc7Sjsg break; 486c349dbc7Sjsg case H1_A8_WAIT_FOR_READY: 487c349dbc7Sjsg status = wait_for_ready(hdcp, event_ctx, input); 488c349dbc7Sjsg break; 489c349dbc7Sjsg case H1_A9_READ_KSV_LIST: 490c349dbc7Sjsg status = read_ksv_list(hdcp, event_ctx, input); 491c349dbc7Sjsg break; 492c349dbc7Sjsg default: 493c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_STATE; 494c349dbc7Sjsg break; 495c349dbc7Sjsg } 496c349dbc7Sjsg 497c349dbc7Sjsg return status; 498c349dbc7Sjsg } 499c349dbc7Sjsg 5001bb76ff1Sjsg enum mod_hdcp_status mod_hdcp_hdcp1_dp_execution(struct mod_hdcp *hdcp, 501c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx, 502c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp1 *input) 503c349dbc7Sjsg { 504c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 505c349dbc7Sjsg 506c349dbc7Sjsg switch (current_state(hdcp)) { 507c349dbc7Sjsg case D1_A0_DETERMINE_RX_HDCP_CAPABLE: 508c349dbc7Sjsg status = determine_rx_hdcp_capable_dp(hdcp, event_ctx, input); 509c349dbc7Sjsg break; 510c349dbc7Sjsg case D1_A1_EXCHANGE_KSVS: 511c349dbc7Sjsg status = exchange_ksvs(hdcp, event_ctx, input); 512c349dbc7Sjsg break; 513c349dbc7Sjsg case D1_A23_WAIT_FOR_R0_PRIME: 514c349dbc7Sjsg status = wait_for_r0_prime_dp(hdcp, event_ctx, input); 515c349dbc7Sjsg break; 516c349dbc7Sjsg case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER: 517c349dbc7Sjsg status = computations_validate_rx_test_for_repeater( 518c349dbc7Sjsg hdcp, event_ctx, input); 519c349dbc7Sjsg break; 520c349dbc7Sjsg case D1_A4_AUTHENTICATED: 521c349dbc7Sjsg status = authenticated_dp(hdcp, event_ctx, input); 522c349dbc7Sjsg break; 523c349dbc7Sjsg case D1_A6_WAIT_FOR_READY: 524c349dbc7Sjsg status = wait_for_ready(hdcp, event_ctx, input); 525c349dbc7Sjsg break; 526c349dbc7Sjsg case D1_A7_READ_KSV_LIST: 527c349dbc7Sjsg status = read_ksv_list(hdcp, event_ctx, input); 528c349dbc7Sjsg break; 529c349dbc7Sjsg default: 530c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_STATE; 531c349dbc7Sjsg break; 532c349dbc7Sjsg } 533c349dbc7Sjsg 534c349dbc7Sjsg return status; 535c349dbc7Sjsg } 536