Commit 82986fd6 authored by hersen wu's avatar hersen wu Committed by Alex Deucher
Browse files

drm/amd/display: save restore hdcp state when display is unplugged from mst hub



[Why]
connector hdcp properties are lost after display is
unplgged from mst hub. connector is destroyed with
dm_dp_mst_connector_destroy. when display is plugged
back, hdcp is not desired and it wouldnt be enabled.

[How]
save hdcp properties into hdcp_work within
amdgpu_dm_atomic_commit_tail. If the same display is
plugged back with same display index, its hdcp
properties will be retrieved from hdcp_work within
dm_dp_mst_get_modes.

Acked-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: default avatarhersen wu <hersenxs.wu@amd.com>
Reviewed-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7f35c54c
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -8310,12 +8310,34 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
			continue;
		}

		if (is_content_protection_different(new_con_state, old_con_state, connector, adev->dm.hdcp_workqueue))
		if (is_content_protection_different(new_con_state, old_con_state, connector, adev->dm.hdcp_workqueue)) {
			/* when display is unplugged from mst hub, connctor will
			 * be destroyed within dm_dp_mst_connector_destroy. connector
			 * hdcp perperties, like type, undesired, desired, enabled,
			 * will be lost. So, save hdcp properties into hdcp_work within
			 * amdgpu_dm_atomic_commit_tail. if the same display is
			 * plugged back with same display index, its hdcp properties
			 * will be retrieved from hdcp_work within dm_dp_mst_get_modes
			 */

			if (aconnector->dc_link && aconnector->dc_sink &&
				aconnector->dc_link->type == dc_connection_mst_branch) {
				struct hdcp_workqueue *hdcp_work = adev->dm.hdcp_workqueue;
				struct hdcp_workqueue *hdcp_w =
					&hdcp_work[aconnector->dc_link->link_index];

				hdcp_w->hdcp_content_type[connector->index] =
					new_con_state->hdcp_content_type;
				hdcp_w->content_protection[connector->index] =
					new_con_state->content_protection;
			}

			hdcp_update_display(
				adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector,
				new_con_state->hdcp_content_type,
				new_con_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED);
    }
	}
#endif

	/* Handle connector state changes */
+14 −0
Original line number Diff line number Diff line
@@ -52,6 +52,20 @@ struct hdcp_workqueue {
	struct mod_hdcp_link link;

	enum mod_hdcp_encryption_status encryption_status;

	/* when display is unplugged from mst hub, connctor will be
	 * destroyed within dm_dp_mst_connector_destroy. connector
	 * hdcp perperties, like type, undesired, desired, enabled,
	 * will be lost. So, save hdcp properties into hdcp_work within
	 * amdgpu_dm_atomic_commit_tail. if the same display is
	 * plugged back with same display index, its hdcp properties
	 * will be retrieved from hdcp_work within dm_dp_mst_get_modes
	 */
	/* un-desired, desired, enabled */
	unsigned int content_protection[AMDGPU_DM_MAX_DISPLAY_INDEX];
	/* hdcp1.x, hdcp2.x */
	unsigned int hdcp_content_type[AMDGPU_DM_MAX_DISPLAY_INDEX];

	uint8_t max_link;

	uint8_t *srm;
+26 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@
#include "amdgpu_dm.h"
#include "amdgpu_dm_mst_types.h"

#ifdef CONFIG_DRM_AMD_DC_HDCP
#include "amdgpu_dm_hdcp.h"
#endif

#include "dc.h"
#include "dm_helpers.h"

@@ -344,6 +348,28 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
		/* dc_link_add_remote_sink returns a new reference */
		aconnector->dc_sink = dc_sink;

		/* when display is unplugged from mst hub, connctor will be
		 * destroyed within dm_dp_mst_connector_destroy. connector
		 * hdcp perperties, like type, undesired, desired, enabled,
		 * will be lost. So, save hdcp properties into hdcp_work within
		 * amdgpu_dm_atomic_commit_tail. if the same display is
		 * plugged back with same display index, its hdcp properties
		 * will be retrieved from hdcp_work within dm_dp_mst_get_modes
		 */
#ifdef CONFIG_DRM_AMD_DC_HDCP
		if (aconnector->dc_sink && connector->state) {
			struct drm_device *dev = connector->dev;
			struct amdgpu_device *adev = drm_to_adev(dev);
			struct hdcp_workqueue *hdcp_work = adev->dm.hdcp_workqueue;
			struct hdcp_workqueue *hdcp_w = &hdcp_work[aconnector->dc_link->link_index];

			connector->state->hdcp_content_type =
			hdcp_w->hdcp_content_type[connector->index];
			connector->state->content_protection =
			hdcp_w->content_protection[connector->index];
		}
#endif

		if (aconnector->dc_sink) {
			amdgpu_dm_update_freesync_caps(
					connector, aconnector->edid);