diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
16 files changed, 267 insertions, 230 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index b9992ebf77a6..4e542826cd26 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -524,12 +524,12 @@ static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr, infopacket->sb[6] |= 0x04; /* PB7 = FreeSync Minimum refresh rate (Hz) */ - infopacket->sb[7] = (unsigned char)(vrr->min_refresh_in_uhz / 1000000); + infopacket->sb[7] = (unsigned char)((vrr->min_refresh_in_uhz + 500000) / 1000000); /* PB8 = FreeSync Maximum refresh rate (Hz) * Note: We should never go above the field rate of the mode timing set. */ - infopacket->sb[8] = (unsigned char)(vrr->max_refresh_in_uhz / 1000000); + infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); //FreeSync HDR @@ -747,10 +747,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, nominal_field_rate_in_uhz = mod_freesync_calc_nominal_field_rate(stream); - /* Rounded to the nearest Hz */ - nominal_field_rate_in_uhz = 1000000ULL * - div_u64(nominal_field_rate_in_uhz + 500000, 1000000); - min_refresh_in_uhz = in_config->min_refresh_in_uhz; max_refresh_in_uhz = in_config->max_refresh_in_uhz; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 8aa528e874c4..e9fbd94f8635 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -52,8 +52,8 @@ static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp) * hdcp is not desired */ for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && - !hdcp->connection.displays[i].adjust.disable) { + if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && + !hdcp->displays[i].adjust.disable) { is_auth_needed = 1; break; } @@ -61,7 +61,8 @@ static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp) return (hdcp->connection.hdcp1_retry_count < MAX_NUM_OF_ATTEMPTS) && is_auth_needed && - !hdcp->connection.link.adjust.hdcp1.disable; + !hdcp->connection.link.adjust.hdcp1.disable && + !hdcp->connection.is_hdcp1_revoked; } static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp) @@ -72,8 +73,8 @@ static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp) * hdcp is not desired */ for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && - !hdcp->connection.displays[i].adjust.disable) { + if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && + !hdcp->displays[i].adjust.disable) { is_auth_needed = 1; break; } @@ -103,8 +104,6 @@ static enum mod_hdcp_status execution(struct mod_hdcp *hdcp, event_ctx->unexpected_event = 1; goto out; } - /* update topology event if hdcp is not desired */ - status = mod_hdcp_add_display_topology(hdcp); } else if (is_in_hdcp1_states(hdcp)) { status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1); } else if (is_in_hdcp1_dp_states(hdcp)) { @@ -115,6 +114,9 @@ static enum mod_hdcp_status execution(struct mod_hdcp *hdcp, } else if (is_in_hdcp2_dp_states(hdcp)) { status = mod_hdcp_hdcp2_dp_execution(hdcp, event_ctx, &input->hdcp2); + } else { + event_ctx->unexpected_event = 1; + goto out; } out: return status; @@ -191,14 +193,7 @@ static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp, mod_hdcp_hdcp1_destroy_session(hdcp); } - if (hdcp->auth.trans_input.hdcp1.add_topology == PASS) { - status = mod_hdcp_remove_display_topology(hdcp); - if (status != MOD_HDCP_STATUS_SUCCESS) { - output->callback_needed = 0; - output->watchdog_timer_needed = 0; - goto out; - } - } + HDCP_TOP_RESET_AUTH_TRACE(hdcp); memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); @@ -212,25 +207,12 @@ static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp, goto out; } } - if (hdcp->auth.trans_input.hdcp2.add_topology == PASS) { - status = mod_hdcp_remove_display_topology(hdcp); - if (status != MOD_HDCP_STATUS_SUCCESS) { - output->callback_needed = 0; - output->watchdog_timer_needed = 0; - goto out; - } - } + HDCP_TOP_RESET_AUTH_TRACE(hdcp); memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); set_state_id(hdcp, output, HDCP_INITIALIZED); } else if (is_in_cp_not_desired_state(hdcp)) { - status = mod_hdcp_remove_display_topology(hdcp); - if (status != MOD_HDCP_STATUS_SUCCESS) { - output->callback_needed = 0; - output->watchdog_timer_needed = 0; - goto out; - } HDCP_TOP_RESET_AUTH_TRACE(hdcp); memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); @@ -337,16 +319,20 @@ enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp, if (status != MOD_HDCP_STATUS_SUCCESS) goto out; - /* add display to connection */ - hdcp->connection.link = *link; - *display_container = *display; - /* reset retry counters */ reset_retry_counts(hdcp); /* reset error trace */ memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); + /* add display to connection */ + hdcp->connection.link = *link; + *display_container = *display; + status = mod_hdcp_add_display_to_topology(hdcp, display_container); + + if (status != MOD_HDCP_STATUS_SUCCESS) + goto out; + /* request authentication */ if (current_state(hdcp) != HDCP_INITIALIZED) set_state_id(hdcp, output, HDCP_INITIALIZED); @@ -379,17 +365,20 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp, if (status != MOD_HDCP_STATUS_SUCCESS) goto out; - /* remove display */ - display->state = MOD_HDCP_DISPLAY_INACTIVE; - /* clear retry counters */ reset_retry_counts(hdcp); /* reset error trace */ memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); - /* request authentication for remaining displays*/ - if (get_active_display_count(hdcp) > 0) + /* remove display */ + status = mod_hdcp_remove_display_from_topology(hdcp, index); + if (status != MOD_HDCP_STATUS_SUCCESS) + goto out; + memset(display, 0, sizeof(struct mod_hdcp_display)); + + /* request authentication when connection is not reset */ + if (current_state(hdcp) != HDCP_UNINITIALIZED) callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output); out: @@ -496,10 +485,8 @@ enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode( break; case SIGNAL_TYPE_EDP: case SIGNAL_TYPE_DISPLAY_PORT: - mode = MOD_HDCP_MODE_DP; - break; case SIGNAL_TYPE_DISPLAY_PORT_MST: - mode = MOD_HDCP_MODE_DP_MST; + mode = MOD_HDCP_MODE_DP; break; default: break; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index af78e4f1be68..60ff1a0028ac 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -41,7 +41,6 @@ enum mod_hdcp_trans_input_result { struct mod_hdcp_transition_input_hdcp1 { uint8_t bksv_read; uint8_t bksv_validation; - uint8_t add_topology; uint8_t create_session; uint8_t an_write; uint8_t aksv_write; @@ -71,7 +70,6 @@ struct mod_hdcp_transition_input_hdcp1 { struct mod_hdcp_transition_input_hdcp2 { uint8_t hdcp2version_read; uint8_t hdcp2_capable_check; - uint8_t add_topology; uint8_t create_session; uint8_t ake_init_prepare; uint8_t ake_init_write; @@ -167,9 +165,9 @@ struct mod_hdcp_auth_counters { /* contains values per connection */ struct mod_hdcp_connection { struct mod_hdcp_link link; - struct mod_hdcp_display displays[MAX_NUM_OF_DISPLAYS]; uint8_t is_repeater; uint8_t is_km_stored; + uint8_t is_hdcp1_revoked; uint8_t is_hdcp2_revoked; struct mod_hdcp_trace trace; uint8_t hdcp1_retry_count; @@ -202,6 +200,8 @@ struct mod_hdcp { struct mod_hdcp_config config; /* per connection */ struct mod_hdcp_connection connection; + /* per displays */ + struct mod_hdcp_display displays[MAX_NUM_OF_DISPLAYS]; /* per authentication attempt */ struct mod_hdcp_authentication auth; /* per state in an authentication */ @@ -327,10 +327,10 @@ void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size, /* TODO: add adjustment log */ /* psp functions */ -enum mod_hdcp_status mod_hdcp_add_display_topology( - struct mod_hdcp *hdcp); -enum mod_hdcp_status mod_hdcp_remove_display_topology( - struct mod_hdcp *hdcp); +enum mod_hdcp_status mod_hdcp_add_display_to_topology( + struct mod_hdcp *hdcp, struct mod_hdcp_display *display); +enum mod_hdcp_status mod_hdcp_remove_display_from_topology( + struct mod_hdcp *hdcp, uint8_t index); enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp); @@ -392,13 +392,13 @@ enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp); /* hdcp version helpers */ static inline uint8_t is_dp_hdcp(struct mod_hdcp *hdcp) { - return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP || - hdcp->connection.link.mode == MOD_HDCP_MODE_DP_MST); + return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP); } static inline uint8_t is_dp_mst_hdcp(struct mod_hdcp *hdcp) { - return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP_MST); + return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP && + hdcp->connection.link.dp.mst_supported); } static inline uint8_t is_hdmi_dvi_sl_hdcp(struct mod_hdcp *hdcp) @@ -503,11 +503,6 @@ static inline uint8_t is_display_active(struct mod_hdcp_display *display) return display->state >= MOD_HDCP_DISPLAY_ACTIVE; } -static inline uint8_t is_display_added(struct mod_hdcp_display *display) -{ - return display->state >= MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; -} - static inline uint8_t is_display_encryption_enabled(struct mod_hdcp_display *display) { return display->state >= MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; @@ -515,35 +510,24 @@ static inline uint8_t is_display_encryption_enabled(struct mod_hdcp_display *dis static inline uint8_t get_active_display_count(struct mod_hdcp *hdcp) { - uint8_t added_count = 0; - uint8_t i; - - for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) - if (is_display_active(&hdcp->connection.displays[i])) - added_count++; - return added_count; -} - -static inline uint8_t get_added_display_count(struct mod_hdcp *hdcp) -{ - uint8_t added_count = 0; + uint8_t active_count = 0; uint8_t i; for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) - if (is_display_added(&hdcp->connection.displays[i])) - added_count++; - return added_count; + if (is_display_active(&hdcp->displays[i])) + active_count++; + return active_count; } -static inline struct mod_hdcp_display *get_first_added_display( +static inline struct mod_hdcp_display *get_first_active_display( struct mod_hdcp *hdcp) { uint8_t i; struct mod_hdcp_display *display = NULL; for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) - if (is_display_added(&hdcp->connection.displays[i])) { - display = &hdcp->connection.displays[i]; + if (is_display_active(&hdcp->displays[i])) { + display = &hdcp->displays[i]; break; } return display; @@ -556,9 +540,9 @@ static inline struct mod_hdcp_display *get_active_display_at_index( struct mod_hdcp_display *display = NULL; for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) - if (hdcp->connection.displays[i].index == index && - is_display_active(&hdcp->connection.displays[i])) { - display = &hdcp->connection.displays[i]; + if (hdcp->displays[i].index == index && + is_display_active(&hdcp->displays[i])) { + display = &hdcp->displays[i]; break; } return display; @@ -571,8 +555,8 @@ static inline struct mod_hdcp_display *get_empty_display_container( struct mod_hdcp_display *display = NULL; for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) - if (!is_display_active(&hdcp->connection.displays[i])) { - display = &hdcp->connection.displays[i]; + if (!is_display_active(&hdcp->displays[i])) { + display = &hdcp->displays[i]; break; } return display; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index 37670db64855..f244b72e74e0 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -129,7 +129,7 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp) static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) { /* device count must be greater than or equal to tracked hdcp displays */ - return (get_device_count(hdcp) < get_added_display_count(hdcp)) ? + return (get_device_count(hdcp) < get_active_display_count(hdcp)) ? MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE : MOD_HDCP_STATUS_SUCCESS; } @@ -168,10 +168,6 @@ static enum mod_hdcp_status exchange_ksvs(struct mod_hdcp *hdcp, goto out; } - if (!mod_hdcp_execute_and_set(mod_hdcp_add_display_topology, - &input->add_topology, &status, - hdcp, "add_topology")) - goto out; if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_create_session, &input->create_session, &status, hdcp, "create_session")) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c index 76edcbe51f71..f3711914364e 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c @@ -46,8 +46,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp, set_state_id(hdcp, output, H1_A1_EXCHANGE_KSVS); break; case H1_A1_EXCHANGE_KSVS: - if (input->add_topology != PASS || - input->create_session != PASS) { + if (input->create_session != PASS) { /* out of sync with psp state */ adjust->hdcp1.disable = 1; fail_and_restart_in_ms(0, &status, output); @@ -173,8 +172,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, set_state_id(hdcp, output, D1_A1_EXCHANGE_KSVS); break; case D1_A1_EXCHANGE_KSVS: - if (input->add_topology != PASS || - input->create_session != PASS) { + if (input->create_session != PASS) { /* out of sync with psp state */ adjust->hdcp1.disable = 1; fail_and_restart_in_ms(0, &status, output); @@ -210,7 +208,8 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, fail_and_restart_in_ms(0, &status, output); break; } else if (input->rx_validation != PASS) { - if (hdcp->state.stay_count < 2) { + if (hdcp->state.stay_count < 2 && + !hdcp->connection.is_hdcp1_revoked) { /* allow 2 additional retries */ callback_in_ms(0, output); increment_stay_counter(hdcp); @@ -231,6 +230,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, (!conn->is_repeater && is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) { fail_and_restart_in_ms(0, &status, output); break; + } else if (conn->hdcp1_retry_count < conn->link.adjust.hdcp1.min_auth_retries_wa) { + fail_and_restart_in_ms(0, &status, output); + break; } if (conn->is_repeater) { set_watchdog_in_ms(hdcp, 5000, output); @@ -290,7 +292,8 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, fail_and_restart_in_ms(0, &status, output); break; } else if (input->ksvlist_vp_validation != PASS) { - if (hdcp->state.stay_count < 2) { + if (hdcp->state.stay_count < 2 && + !hdcp->connection.is_hdcp1_revoked) { /* allow 2 additional retries */ callback_in_ms(0, output); increment_stay_counter(hdcp); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c index 55246711700b..549c113abcf7 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c @@ -34,7 +34,7 @@ static inline enum mod_hdcp_status check_receiver_id_list_ready(struct mod_hdcp if (is_dp_hdcp(hdcp)) is_ready = HDCP_2_2_DP_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus_dp) ? 1 : 0; else - is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[0]) && + is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[1]) && (HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 | hdcp->auth.msg.hdcp2.rxstatus[0])) ? 1 : 0; return is_ready ? MOD_HDCP_STATUS_SUCCESS : @@ -67,7 +67,7 @@ static inline enum mod_hdcp_status check_reauthentication_request( MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST : MOD_HDCP_STATUS_SUCCESS; else - ret = HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus[0]) ? + ret = HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus[1]) ? MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST : MOD_HDCP_STATUS_SUCCESS; return ret; @@ -208,7 +208,7 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp) static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) { /* device count must be greater than or equal to tracked hdcp displays */ - return (get_device_count(hdcp) < get_added_display_count(hdcp)) ? + return (get_device_count(hdcp) < get_active_display_count(hdcp)) ? MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE : MOD_HDCP_STATUS_SUCCESS; } @@ -259,6 +259,7 @@ static enum mod_hdcp_status known_hdcp2_capable_rx(struct mod_hdcp *hdcp, event_ctx->unexpected_event = 1; goto out; } + if (!mod_hdcp_execute_and_set(mod_hdcp_read_hdcp2version, &input->hdcp2version_read, &status, hdcp, "hdcp2version_read")) @@ -281,10 +282,7 @@ static enum mod_hdcp_status send_ake_init(struct mod_hdcp *hdcp, event_ctx->unexpected_event = 1; goto out; } - if (!mod_hdcp_execute_and_set(mod_hdcp_add_display_topology, - &input->add_topology, &status, - hdcp, "add_topology")) - goto out; + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_create_session, &input->create_session, &status, hdcp, "create_session")) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c index 8cae3e3aacd5..e738c7ae66ec 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c @@ -47,8 +47,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_transition(struct mod_hdcp *hdcp, } break; case H2_A1_SEND_AKE_INIT: - if (input->add_topology != PASS || - input->create_session != PASS || + if (input->create_session != PASS || input->ake_init_prepare != PASS) { /* out of sync with psp state */ adjust->hdcp2.disable = 1; @@ -389,8 +388,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp, } break; case D2_A1_SEND_AKE_INIT: - if (input->add_topology != PASS || - input->create_session != PASS || + if (input->create_session != PASS || input->ake_init_prepare != PASS) { /* out of sync with psp state */ adjust->hdcp2.disable = 1; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index ff9d54812e62..bb5130f4228d 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -65,6 +65,7 @@ enum mod_hdcp_ddc_message_id { MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, + MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, @@ -101,6 +102,7 @@ static const uint8_t hdcp_i2c_offsets[] = { [MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80, [MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60, [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80, + [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x80, [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60, [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60, [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80, @@ -135,6 +137,7 @@ static const uint32_t hdcp_dpcd_addrs[] = { [MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8, [MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318, [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330, + [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x69340, [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0, [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0, [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473, @@ -405,7 +408,7 @@ enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp) enum mod_hdcp_status status; if (is_dp_hdcp(hdcp)) { - hdcp->auth.msg.hdcp2.ake_cert[0] = 3; + hdcp->auth.msg.hdcp2.ake_cert[0] = HDCP_2_2_AKE_SEND_CERT; status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT, hdcp->auth.msg.hdcp2.ake_cert+1, sizeof(hdcp->auth.msg.hdcp2.ake_cert)-1); @@ -423,7 +426,7 @@ enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp) enum mod_hdcp_status status; if (is_dp_hdcp(hdcp)) { - hdcp->auth.msg.hdcp2.ake_h_prime[0] = 7; + hdcp->auth.msg.hdcp2.ake_h_prime[0] = HDCP_2_2_AKE_SEND_HPRIME; status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME, hdcp->auth.msg.hdcp2.ake_h_prime+1, sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)-1); @@ -441,7 +444,7 @@ enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp) enum mod_hdcp_status status; if (is_dp_hdcp(hdcp)) { - hdcp->auth.msg.hdcp2.ake_pairing_info[0] = 8; + hdcp->auth.msg.hdcp2.ake_pairing_info[0] = HDCP_2_2_AKE_SEND_PAIRING_INFO; status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO, hdcp->auth.msg.hdcp2.ake_pairing_info+1, sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)-1); @@ -459,7 +462,7 @@ enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp) enum mod_hdcp_status status; if (is_dp_hdcp(hdcp)) { - hdcp->auth.msg.hdcp2.lc_l_prime[0] = 10; + hdcp->auth.msg.hdcp2.lc_l_prime[0] = HDCP_2_2_LC_SEND_LPRIME; status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, hdcp->auth.msg.hdcp2.lc_l_prime+1, sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)-1); @@ -474,14 +477,27 @@ enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp) enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp) { - enum mod_hdcp_status status; + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; if (is_dp_hdcp(hdcp)) { - hdcp->auth.msg.hdcp2.rx_id_list[0] = 12; - status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, - hdcp->auth.msg.hdcp2.rx_id_list+1, - sizeof(hdcp->auth.msg.hdcp2.rx_id_list)-1); + uint32_t device_count = 0; + uint32_t rx_id_list_size = 0; + uint32_t bytes_read = 0; + hdcp->auth.msg.hdcp2.rx_id_list[0] = HDCP_2_2_REP_SEND_RECVID_LIST; + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, + hdcp->auth.msg.hdcp2.rx_id_list+1, + HDCP_MAX_AUX_TRANSACTION_SIZE); + if (status == MOD_HDCP_STATUS_SUCCESS) { + bytes_read = HDCP_MAX_AUX_TRANSACTION_SIZE; + device_count = HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) + + (HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4); + rx_id_list_size = MIN((21 + 5 * device_count), + (sizeof(hdcp->auth.msg.hdcp2.rx_id_list) - 1)); + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2, + hdcp->auth.msg.hdcp2.rx_id_list + 1 + bytes_read, + (rx_id_list_size - 1) / HDCP_MAX_AUX_TRANSACTION_SIZE * HDCP_MAX_AUX_TRANSACTION_SIZE); + } } else { status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, hdcp->auth.msg.hdcp2.rx_id_list, @@ -495,7 +511,7 @@ enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp) enum mod_hdcp_status status; if (is_dp_hdcp(hdcp)) { - hdcp->auth.msg.hdcp2.repeater_auth_stream_ready[0] = 17; + hdcp->auth.msg.hdcp2.repeater_auth_stream_ready[0] = HDCP_2_2_REP_STREAM_READY; status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, hdcp->auth.msg.hdcp2.repeater_auth_stream_ready+1, sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)-1); 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 724ebcee9a19..44956f9ba178 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c @@ -90,10 +90,14 @@ char *mod_hdcp_status_to_str(int32_t status) return "MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING"; case MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE: return "MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE"; + case MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED: + return "MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED"; case MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY: return "MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY"; case MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE: return "MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE"; + case MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED: + return "MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED"; case MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION: return "MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION"; case MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE: diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h index ff91373ebada..d3192b9d0c3d 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h @@ -37,10 +37,11 @@ /* default logs */ #define HDCP_ERROR_TRACE(hdcp, status) \ HDCP_LOG_ERR(hdcp, \ - "[Link %d] WARNING %s IN STATE %s", \ + "[Link %d] WARNING %s IN STATE %s STAY COUNT %d", \ hdcp->config.index, \ mod_hdcp_status_to_str(status), \ - mod_hdcp_state_id_to_str(hdcp->state.id)) + mod_hdcp_state_id_to_str(hdcp->state.id), \ + hdcp->state.stay_count) #define HDCP_HDCP1_ENABLED_TRACE(hdcp, displayIndex) \ HDCP_LOG_VER(hdcp, \ "[Link %d] HDCP 1.4 enabled on display %d", \ @@ -49,6 +50,15 @@ HDCP_LOG_VER(hdcp, \ "[Link %d] HDCP 2.2 enabled on display %d", \ hdcp->config.index, displayIndex) +#define HDCP_HDCP1_DISABLED_TRACE(hdcp, displayIndex) \ + HDCP_LOG_VER(hdcp, \ + "[Link %d] HDCP 1.4 disabled on display %d", \ + hdcp->config.index, displayIndex) +#define HDCP_HDCP2_DISABLED_TRACE(hdcp, displayIndex) \ + HDCP_LOG_VER(hdcp, \ + "[Link %d] HDCP 2.2 disabled on display %d", \ + hdcp->config.index, displayIndex) + /* state machine logs */ #define HDCP_REMOVE_DISPLAY_TRACE(hdcp, displayIndex) \ HDCP_LOG_FSM(hdcp, \ @@ -102,6 +112,9 @@ sizeof(hdcp->auth.msg.hdcp1.bksv)); \ HDCP_DDC_READ_TRACE(hdcp, "BCAPS", &hdcp->auth.msg.hdcp1.bcaps, \ sizeof(hdcp->auth.msg.hdcp1.bcaps)); \ + HDCP_DDC_READ_TRACE(hdcp, "BSTATUS", \ + (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus, \ + sizeof(hdcp->auth.msg.hdcp1.bstatus)); \ HDCP_DDC_WRITE_TRACE(hdcp, "AN", hdcp->auth.msg.hdcp1.an, \ sizeof(hdcp->auth.msg.hdcp1.an)); \ HDCP_DDC_WRITE_TRACE(hdcp, "AKSV", hdcp->auth.msg.hdcp1.aksv, \ 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 7911dc157d5a..836e47954938 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -44,84 +44,78 @@ 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; } -enum mod_hdcp_status mod_hdcp_remove_display_topology(struct mod_hdcp *hdcp) -{ - - struct psp_context *psp = hdcp->config.psp.handle; - struct ta_dtm_shared_memory *dtm_cmd; - struct mod_hdcp_display *display = NULL; - uint8_t i; +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; + struct mod_hdcp_display *display = + get_active_display_at_index(hdcp, index); dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; - for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (is_display_added(&(hdcp->connection.displays[i]))) { + if (!display || !is_display_active(display)) + return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; - memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); + memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); - display = &hdcp->connection.displays[i]; + dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; + dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; + dtm_cmd->dtm_in_message.topology_update_v2.is_active = 0; + dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; - dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; - dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; - dtm_cmd->dtm_in_message.topology_update_v2.is_active = 0; - dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE; + psp_dtm_invoke(psp, dtm_cmd->cmd_id); - psp_dtm_invoke(psp, dtm_cmd->cmd_id); + if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) + return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; - if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) - return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; + display->state = MOD_HDCP_DISPLAY_ACTIVE; + HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index); + + return MOD_HDCP_STATUS_SUCCESS; + } - display->state = MOD_HDCP_DISPLAY_ACTIVE; - HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index); - } - } - - return MOD_HDCP_STATUS_SUCCESS; -} - -enum mod_hdcp_status mod_hdcp_add_display_topology(struct mod_hdcp *hdcp) +enum mod_hdcp_status mod_hdcp_add_display_to_topology( + 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_display *display = NULL; struct mod_hdcp_link *link = &hdcp->connection.link; - uint8_t i; if (!psp->dtm_context.dtm_initialized) { DRM_ERROR("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; - for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (hdcp->connection.displays[i].state == MOD_HDCP_DISPLAY_ACTIVE) { - display = &hdcp->connection.displays[i]; - - memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); - - dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; - dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; - dtm_cmd->dtm_in_message.topology_update_v2.is_active = 1; - dtm_cmd->dtm_in_message.topology_update_v2.controller = display->controller; - dtm_cmd->dtm_in_message.topology_update_v2.ddc_line = link->ddc_line; - dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be; - dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe; - dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id; - dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version = - TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_2; - 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) - return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; - - display->state = MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; - HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index); - } + memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); + + dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2; + dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index; + dtm_cmd->dtm_in_message.topology_update_v2.is_active = 1; + dtm_cmd->dtm_in_message.topology_update_v2.controller = display->controller; + dtm_cmd->dtm_in_message.topology_update_v2.ddc_line = link->ddc_line; + dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be; + dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe; + if (is_dp_hdcp(hdcp)) + dtm_cmd->dtm_in_message.topology_update_v2.is_assr = link->dp.assr_supported; + + dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id; + dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version = + TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_2; + 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) { + display->state = MOD_HDCP_DISPLAY_INACTIVE; + return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE; } + HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index); + return MOD_HDCP_STATUS_SUCCESS; } @@ -129,7 +123,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; - struct mod_hdcp_display *display = get_first_added_display(hdcp); + struct mod_hdcp_display *display = get_first_active_display(hdcp); struct ta_hdcp_shared_memory *hdcp_cmd; if (!psp->hdcp_context.hdcp_initialized) { @@ -164,6 +158,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp) struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; + uint8_t i = 0; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -177,6 +172,14 @@ enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp) return MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE; HDCP_TOP_HDCP1_DESTROY_SESSION_TRACE(hdcp); + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) + if (is_display_encryption_enabled( + &hdcp->displays[i])) { + hdcp->displays[i].state = + MOD_HDCP_DISPLAY_ACTIVE; + HDCP_HDCP1_DISABLED_TRACE(hdcp, + hdcp->displays[i].index); + } return MOD_HDCP_STATUS_SUCCESS; } @@ -210,6 +213,10 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp) } else if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status == TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED) { hdcp->connection.is_repeater = 0; + } else if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status == + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_REVOKED) { + hdcp->connection.is_hdcp1_revoked = 1; + return MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED; } else return MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE; @@ -221,7 +228,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; - struct mod_hdcp_display *display = get_first_added_display(hdcp); + struct mod_hdcp_display *display = get_first_active_display(hdcp); hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -245,6 +252,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -264,10 +272,19 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp) psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); - if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) - return MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE; + if (hdcp_cmd->hdcp_status == TA_HDCP_STATUS__SUCCESS && + hdcp_cmd->out_msg.hdcp1_second_part_authentication.authentication_status == + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED) { + status = MOD_HDCP_STATUS_SUCCESS; + } else if (hdcp_cmd->out_msg.hdcp1_second_part_authentication.authentication_status == + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_REVOKED) { + hdcp->connection.is_hdcp1_revoked = 1; + status = MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED; + } else { + status = MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE; + } - return MOD_HDCP_STATUS_SUCCESS; + return status; } enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp *hdcp) @@ -281,14 +298,13 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED || - hdcp->connection.displays[i].adjust.disable) + if (hdcp->displays[i].adjust.disable) continue; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.session_handle = hdcp->auth.id; - hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.display_handle = hdcp->connection.displays[i].index; + hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.display_handle = hdcp->displays[i].index; hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_ENABLE_DP_STREAM_ENCRYPTION; psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); @@ -296,8 +312,8 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) return MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE; - hdcp->connection.displays[i].state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; - HDCP_HDCP1_ENABLED_TRACE(hdcp, hdcp->connection.displays[i].index); + hdcp->displays[i].state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; + HDCP_HDCP1_ENABLED_TRACE(hdcp, hdcp->displays[i].index); } return MOD_HDCP_STATUS_SUCCESS; @@ -344,7 +360,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; - struct mod_hdcp_display *display = get_first_added_display(hdcp); + struct mod_hdcp_display *display = get_first_active_display(hdcp); if (!psp->hdcp_context.hdcp_initialized) { DRM_ERROR("Failed to create hdcp session, HDCP TA is not initialized"); @@ -385,6 +401,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_destroy_session(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; + uint8_t i = 0; hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); @@ -398,6 +415,14 @@ enum mod_hdcp_status mod_hdcp_hdcp2_destroy_session(struct mod_hdcp *hdcp) return MOD_HDCP_STATUS_HDCP2_DESTROY_SESSION_FAILURE; HDCP_TOP_HDCP2_DESTROY_SESSION_TRACE(hdcp); + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) + if (is_display_encryption_enabled( + &hdcp->displays[i])) { + hdcp->displays[i].state = + MOD_HDCP_DISPLAY_ACTIVE; + HDCP_HDCP2_DISABLED_TRACE(hdcp, + hdcp->displays[i].index); + } return MOD_HDCP_STATUS_SUCCESS; } @@ -473,9 +498,12 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_ake_cert(struct mod_hdcp *hdcp) hdcp->connection.is_km_stored = msg_out->process.is_km_stored ? 1 : 0; hdcp->connection.is_repeater = msg_out->process.is_repeater ? 1 : 0; return MOD_HDCP_STATUS_SUCCESS; + } else if (msg_out->process.msg1_status == TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) { + hdcp->connection.is_hdcp2_revoked = 1; + return MOD_HDCP_STATUS_HDCP2_AKE_CERT_REVOKED; } - return MOD_HDCP_STATUS_FAILURE; + return MOD_HDCP_STATUS_HDCP2_VALIDATE_AKE_CERT_FAILURE; } enum mod_hdcp_status mod_hdcp_hdcp2_validate_h_prime(struct mod_hdcp *hdcp) @@ -630,20 +658,15 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_encryption(struct mod_hdcp *hdcp) { struct psp_context *psp = hdcp->config.psp.handle; struct ta_hdcp_shared_memory *hdcp_cmd; - struct ta_hdcp_cmd_hdcp2_process_prepare_authentication_message_input_v2 *msg_in; - struct mod_hdcp_display *display = get_first_added_display(hdcp); + struct mod_hdcp_display *display = get_first_active_display(hdcp); hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); - msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2; - - hdcp2_message_init(hdcp, msg_in); - if (!display) return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; - hdcp_cmd->in_msg.hdcp1_enable_encryption.session_handle = hdcp->auth.id; + hdcp_cmd->in_msg.hdcp2_set_encryption.session_handle = hdcp->auth.id; hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP2_SET_ENCRYPTION; psp_hdcp_invoke(psp, hdcp_cmd->cmd_id); @@ -695,6 +718,9 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_rx_id_list(struct mod_hdcp *hdcp) hdcp->connection.is_km_stored = msg_out->process.is_km_stored ? 1 : 0; hdcp->connection.is_repeater = msg_out->process.is_repeater ? 1 : 0; return MOD_HDCP_STATUS_SUCCESS; + } else if (msg_out->process.msg1_status == TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) { + hdcp->connection.is_hdcp2_revoked = 1; + return MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_REVOKED; } @@ -717,10 +743,9 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_dp_stream_encryption(struct mod_hdcp for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { - if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED || - hdcp->connection.displays[i].adjust.disable) + if (hdcp->displays[i].adjust.disable) continue; - hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.display_handle = hdcp->connection.displays[i].index; + hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.display_handle = hdcp->displays[i].index; hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.session_handle = hdcp->auth.id; hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP2_ENABLE_DP_STREAM_ENCRYPTION; @@ -729,8 +754,8 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_dp_stream_encryption(struct mod_hdcp if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS) break; - hdcp->connection.displays[i].state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; - HDCP_HDCP2_ENABLED_TRACE(hdcp, hdcp->connection.displays[i].index); + hdcp->displays[i].state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; + HDCP_HDCP2_ENABLED_TRACE(hdcp, hdcp->displays[i].index); } return (hdcp_cmd->hdcp_status == TA_HDCP_STATUS__SUCCESS) ? MOD_HDCP_STATUS_SUCCESS 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 82a5e997d573..1a663dbbf810 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h @@ -117,6 +117,8 @@ struct ta_dtm_shared_memory { int psp_cmd_submit_buf(struct psp_context *psp, struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr); +enum { PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE = 5120 }; + enum ta_hdcp_command { TA_HDCP_COMMAND__INITIALIZE, TA_HDCP_COMMAND__HDCP1_CREATE_SESSION, @@ -134,7 +136,10 @@ enum ta_hdcp_command { TA_HDCP_COMMAND__UNUSED_3, TA_HDCP_COMMAND__HDCP2_CREATE_SESSION_V2, TA_HDCP_COMMAND__HDCP2_PREPARE_PROCESS_AUTHENTICATION_MSG_V2, - TA_HDCP_COMMAND__HDCP2_ENABLE_DP_STREAM_ENCRYPTION + TA_HDCP_COMMAND__HDCP2_ENABLE_DP_STREAM_ENCRYPTION, + TA_HDCP_COMMAND__HDCP_DESTROY_ALL_SESSIONS, + TA_HDCP_COMMAND__HDCP_SET_SRM, + TA_HDCP_COMMAND__HDCP_GET_SRM }; enum ta_hdcp2_msg_id { @@ -235,7 +240,8 @@ enum ta_hdcp_authentication_status { TA_HDCP_AUTHENTICATION_STATUS__HDCP22_AUTHENTICATION_PENDING = 0x06, TA_HDCP_AUTHENTICATION_STATUS__HDCP22_AUTHENTICATION_FAILED = 0x07, TA_HDCP_AUTHENTICATION_STATUS__HDCP22_AUTHENTICATED = 0x08, - TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_VALIDATION_FAILED = 0x09 + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_VALIDATION_FAILED = 0x09, + TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_REVOKED = 0x0A }; enum ta_hdcp2_msg_authentication_status { @@ -253,7 +259,8 @@ enum ta_hdcp2_msg_authentication_status { TA_HDCP2_MSG_AUTHENTICATION_STATUS__INVALID_SEQ_NUM, TA_HDCP2_MSG_AUTHENTICATION_STATUS__INVALID_SIZE, TA_HDCP2_MSG_AUTHENTICATION_STATUS__INVALID_LENGTH, - TA_HDCP2_MSG_AUTHENTICATION_STATUS__REAUTH_REQUEST + TA_HDCP2_MSG_AUTHENTICATION_STATUS__REAUTH_REQUEST, + TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED }; enum ta_hdcp_content_type { @@ -415,6 +422,22 @@ struct ta_hdcp_cmd_hdcp2_enable_dp_stream_encryption_input { uint32_t display_handle; }; +struct ta_hdcp_cmd_set_srm_input { + uint32_t srm_buf_size; + uint8_t srm_buf[PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE]; +}; + +struct ta_hdcp_cmd_set_srm_output { + uint8_t valid_signature; + uint32_t srm_version; +}; + +struct ta_hdcp_cmd_get_srm_output { + uint32_t srm_version; + uint32_t srm_buf_size; + uint8_t srm_buf[PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE]; +}; + /**********************************************************/ /* Common input structure for HDCP callbacks */ union ta_hdcp_cmd_input { @@ -432,6 +455,7 @@ union ta_hdcp_cmd_input { struct ta_hdcp_cmd_hdcp2_process_prepare_authentication_message_input_v2 hdcp2_prepare_process_authentication_message_v2; struct ta_hdcp_cmd_hdcp2_enable_dp_stream_encryption_input hdcp2_enable_dp_stream_encryption; + struct ta_hdcp_cmd_set_srm_input hdcp_set_srm; }; /* Common output structure for HDCP callbacks */ @@ -444,6 +468,8 @@ union ta_hdcp_cmd_output { struct ta_hdcp_cmd_hdcp2_create_session_output_v2 hdcp2_create_session_v2; struct ta_hdcp_cmd_hdcp2_process_prepare_authentication_message_output_v2 hdcp2_prepare_process_authentication_message_v2; + struct ta_hdcp_cmd_set_srm_output hdcp_set_srm; + struct ta_hdcp_cmd_get_srm_output hdcp_get_srm; }; /**********************************************************/ 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 f2a0e1a064da..eae9309cfb24 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h @@ -56,8 +56,10 @@ enum mod_hdcp_status { MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE, MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING, MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE, + MOD_HDCP_STATUS_HDCP1_BKSV_REVOKED, MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY, MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE, + MOD_HDCP_STATUS_HDCP1_KSV_LIST_REVOKED, MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION, MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE, MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE, @@ -100,6 +102,7 @@ enum mod_hdcp_status { struct mod_hdcp_displayport { uint8_t rev; uint8_t assr_supported; + uint8_t mst_supported; }; struct mod_hdcp_hdmi { @@ -108,14 +111,12 @@ struct mod_hdcp_hdmi { enum mod_hdcp_operation_mode { MOD_HDCP_MODE_OFF, MOD_HDCP_MODE_DEFAULT, - MOD_HDCP_MODE_DP, - MOD_HDCP_MODE_DP_MST + MOD_HDCP_MODE_DP }; enum mod_hdcp_display_state { MOD_HDCP_DISPLAY_INACTIVE = 0, MOD_HDCP_DISPLAY_ACTIVE, - MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED, MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED }; @@ -155,7 +156,8 @@ struct mod_hdcp_display_adjustment { struct mod_hdcp_link_adjustment_hdcp1 { uint8_t disable : 1; uint8_t postpone_encryption : 1; - uint8_t reserved : 6; + uint8_t min_auth_retries_wa : 1; + uint8_t reserved : 5; }; enum mod_hdcp_force_hdcp_type { diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index 42cbeffac640..13c57ff2abdc 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -34,8 +34,7 @@ struct dc_info_packet; struct mod_vrr_params; void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, - bool *use_vsc_sdp_for_colorimetry); + struct dc_info_packet *info_packet); void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue); diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 6a8a056424b8..cff3ab15fc0c 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -130,8 +130,7 @@ enum ColorimetryYCCDP { }; void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, - bool *use_vsc_sdp_for_colorimetry) + struct dc_info_packet *info_packet) { unsigned int vsc_packet_revision = vsc_packet_undefined; unsigned int i; @@ -139,11 +138,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, unsigned int colorimetryFormat = 0; bool stereo3dSupport = false; - /* Initialize first, later if infopacket is valid determine if VSC SDP - * should be used to signal colorimetry format and pixel encoding. - */ - *use_vsc_sdp_for_colorimetry = false; - if (stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE && stream->view_format != VIEW_3D_FORMAT_NONE) { vsc_packet_revision = vsc_packet_rev1; stereo3dSupport = true; @@ -153,9 +147,8 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, if (stream->psr_version != 0) vsc_packet_revision = vsc_packet_rev2; - /* Update to revision 5 for extended colorimetry support for DPCD 1.4+ */ - if (stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && - stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) + /* Update to revision 5 for extended colorimetry support */ + if (stream->use_vsc_sdp_for_colorimetry) vsc_packet_revision = vsc_packet_rev5; /* VSC packet not needed based on the features @@ -269,13 +262,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, info_packet->valid = true; - /* If we are using VSC SDP revision 05h, use this to signal for - * colorimetry format and pixel encoding. HW should later be - * programmed to set MSA MISC1 bit 6 to indicate ignore - * colorimetry format and pixel encoding in the MSA. - */ - *use_vsc_sdp_for_colorimetry = true; - /* Set VSC SDP fields for pixel encoding and colorimetry format from DP 1.3 specs * Data Bytes DB 18~16 * Bits 3:0 (Colorimetry Format) | Bits 7:4 (Pixel Encoding) diff --git a/drivers/gpu/drm/amd/display/modules/vmid/vmid.c b/drivers/gpu/drm/amd/display/modules/vmid/vmid.c index f0a153704f6e..00f132f8ad55 100644 --- a/drivers/gpu/drm/amd/display/modules/vmid/vmid.c +++ b/drivers/gpu/drm/amd/display/modules/vmid/vmid.c @@ -40,14 +40,18 @@ struct core_vmid { static void add_ptb_to_table(struct core_vmid *core_vmid, unsigned int vmid, uint64_t ptb) { - core_vmid->ptb_assigned_to_vmid[vmid] = ptb; - core_vmid->num_vmids_available--; + if (vmid < MAX_VMID) { + core_vmid->ptb_assigned_to_vmid[vmid] = ptb; + core_vmid->num_vmids_available--; + } } static void clear_entry_from_vmid_table(struct core_vmid *core_vmid, unsigned int vmid) { - core_vmid->ptb_assigned_to_vmid[vmid] = 0; - core_vmid->num_vmids_available++; + if (vmid < MAX_VMID) { + core_vmid->ptb_assigned_to_vmid[vmid] = 0; + core_vmid->num_vmids_available++; + } } static void evict_vmids(struct core_vmid *core_vmid) @@ -57,7 +61,7 @@ static void evict_vmids(struct core_vmid *core_vmid) // At this point any positions with value 0 are unused vmids, evict them for (i = 1; i < core_vmid->num_vmid; i++) { - if (ord & (1u << i)) + if (!(ord & (1u << i))) clear_entry_from_vmid_table(core_vmid, i); } } @@ -91,7 +95,7 @@ static int get_next_available_vmid(struct core_vmid *core_vmid) uint8_t mod_vmid_get_for_ptb(struct mod_vmid *mod_vmid, uint64_t ptb) { struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid); - unsigned int vmid = 0; + int vmid = 0; // Physical address gets vmid 0 if (ptb == 0) |