Commit 4268d081 authored by Ahmad Othman's avatar Ahmad Othman Committed by Alex Deucher
Browse files

drm/amd/display: Fix HDCP SEND AKI INIT error



[why]
HDCP sends AKI INIT error in case of multiple display on dock

[how]
Add new checks and method to handle display adjustment
for multiple display cases

Reviewed-by: default avatarWenjing Liu <Wenjing.Liu@amd.com>
Acked-by: default avatarAlex Hung <alex.hung@amd.com>
Signed-off-by: default avatarAhmad Othman <ahmad.othman@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f3fa4909
Loading
Loading
Loading
Loading
+37 −1
Original line number Diff line number Diff line
@@ -251,6 +251,33 @@ static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp,
	return status;
}

static enum mod_hdcp_status update_display_adjustments(struct mod_hdcp *hdcp,
		struct mod_hdcp_display *display,
		struct mod_hdcp_display_adjustment *adj)
{
	enum mod_hdcp_status status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;

	if (is_in_authenticated_states(hdcp) &&
			is_dp_mst_hdcp(hdcp) &&
			display->adjust.disable == true &&
			adj->disable == false) {
		display->adjust.disable = false;
		if (is_hdcp1(hdcp))
			status = mod_hdcp_hdcp1_enable_dp_stream_encryption(hdcp);
		else if (is_hdcp2(hdcp))
			status = mod_hdcp_hdcp2_enable_dp_stream_encryption(hdcp);

		if (status != MOD_HDCP_STATUS_SUCCESS)
			display->adjust.disable = true;
	}

	if (status == MOD_HDCP_STATUS_SUCCESS &&
		memcmp(adj, &display->adjust,
		sizeof(struct mod_hdcp_display_adjustment)) != 0)
		status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;

	return status;
}
/*
 * Implementation of functions in mod_hdcp.h
 */
@@ -391,7 +418,7 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
	return status;
}

enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp,
		uint8_t index,
		struct mod_hdcp_link_adjustment *link_adjust,
		struct mod_hdcp_display_adjustment *display_adjust,
@@ -419,6 +446,15 @@ enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
		goto out;
	}

	if (memcmp(link_adjust, &hdcp->connection.link.adjust,
			sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
			memcmp(display_adjust, &display->adjust,
					sizeof(struct mod_hdcp_display_adjustment)) != 0) {
		status = update_display_adjustments(hdcp, display, display_adjust);
		if (status != MOD_HDCP_STATUS_NOT_IMPLEMENTED)
			goto out;
	}

	/* stop current authentication */
	status = reset_authentication(hdcp, output);
	if (status != MOD_HDCP_STATUS_SUCCESS)
+8 −0
Original line number Diff line number Diff line
@@ -445,6 +445,14 @@ static inline uint8_t is_in_hdcp2_dp_states(struct mod_hdcp *hdcp)
			current_state(hdcp) <= HDCP2_DP_STATE_END);
}

static inline uint8_t is_in_authenticated_states(struct mod_hdcp *hdcp)
{
	return (current_state(hdcp) == D1_A4_AUTHENTICATED ||
	current_state(hdcp) == H1_A45_AUTHENTICATED ||
	current_state(hdcp) == D2_A5_AUTHENTICATED ||
	current_state(hdcp) == H2_A5_AUTHENTICATED);
}

static inline uint8_t is_hdcp1(struct mod_hdcp *hdcp)
{
	return (is_in_hdcp1_states(hdcp) || is_in_hdcp1_dp_states(hdcp));
+1 −1
Original line number Diff line number Diff line
@@ -294,7 +294,7 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
		uint8_t index, struct mod_hdcp_output *output);

/* called per display to apply new authentication adjustment */
enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp,
		uint8_t index,
		struct mod_hdcp_link_adjustment *link_adjust,
		struct mod_hdcp_display_adjustment *display_adjust,