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: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: hersen wu <hersenxs.wu@amd.com>
Reviewed-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
hersen wu 2022-11-15 10:39:55 -05:00 committed by Alex Deucher
parent 7f35c54cc2
commit 82986fd631
3 changed files with 63 additions and 1 deletions

View File

@ -8310,11 +8310,33 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
continue; 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( hdcp_update_display(
adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector, adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector,
new_con_state->hdcp_content_type, new_con_state->hdcp_content_type,
new_con_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED); new_con_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED);
}
} }
#endif #endif

View File

@ -52,6 +52,20 @@ struct hdcp_workqueue {
struct mod_hdcp_link link; struct mod_hdcp_link link;
enum mod_hdcp_encryption_status encryption_status; 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 max_link;
uint8_t *srm; uint8_t *srm;

View File

@ -32,6 +32,10 @@
#include "amdgpu_dm.h" #include "amdgpu_dm.h"
#include "amdgpu_dm_mst_types.h" #include "amdgpu_dm_mst_types.h"
#ifdef CONFIG_DRM_AMD_DC_HDCP
#include "amdgpu_dm_hdcp.h"
#endif
#include "dc.h" #include "dc.h"
#include "dm_helpers.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 */ /* dc_link_add_remote_sink returns a new reference */
aconnector->dc_sink = dc_sink; 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) { if (aconnector->dc_sink) {
amdgpu_dm_update_freesync_caps( amdgpu_dm_update_freesync_caps(
connector, aconnector->edid); connector, aconnector->edid);