When a display is unplugged from a MST hub, the connector will be destroyed in dm_dp_mst_connector_destroy(). The connector's HDCP properties, like HDCP state will be lost. So, save the connector's HDCP properties into hdcp_work in amdgpu_dm_atomic_commit_tail(). Also, if the same display is plugged back in with the same display index, restore its HDCP properties from hdcp_work in dm_dp_mst_get_modes(). Signed-off-by: Hamza Mahfooz <hamza.mahfooz@xxxxxxx> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 56 +++++++++++++++++-- .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 13 +++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 33 +++++++++++ 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ece2003a74cc..8d8788792f7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7990,6 +7990,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; +#ifdef CONFIG_DRM_AMD_DC_HDCP + struct dc_edid_caps *edid_caps; + struct hdcp_workqueue *hdcp_work, *hdcp_w; + unsigned int index; + bool enable_encryption = false; +#endif int crtc_disable_count = 0; bool mode_set_reset_required = false; @@ -8165,11 +8171,51 @@ 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)) - 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); + if (is_content_protection_different(new_con_state, + old_con_state, + connector, + adev->dm.hdcp_workqueue)) { + + if (new_con_state->content_protection == + DRM_MODE_CONTENT_PROTECTION_DESIRED) + enable_encryption = true; + + if (aconnector->dc_link && aconnector->dc_sink && + aconnector->dc_link->type == + dc_connection_mst_branch) { + hdcp_work = adev->dm.hdcp_workqueue; + hdcp_w = &hdcp_work[ + aconnector->dc_link->link_index]; + edid_caps = &aconnector->dc_sink->edid_caps; + index = connector->index; + + hdcp_w->sink_edid_id[index].manufacturer_id = + edid_caps->manufacturer_id; + hdcp_w->sink_edid_id[index].product_id = + edid_caps->product_id; + hdcp_w->sink_edid_id[index].serial_number = + edid_caps->serial_number; + hdcp_w->sink_edid_id[index].manufacture_week = + edid_caps->manufacture_week; + hdcp_w->sink_edid_id[index].manufacture_year = + edid_caps->manufacture_year; + + hdcp_w->hdcp_content_type[index] = + new_con_state->hdcp_content_type; + hdcp_w->content_protection[index] = + new_con_state->content_protection; + + if (new_crtc_state && + new_crtc_state->mode_changed) + enable_encryption = true; + } + + hdcp_update_display(adev->dm.hdcp_workqueue, + aconnector->dc_link->link_index, + aconnector, + new_con_state->hdcp_content_type, + enable_encryption); + } } #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h index b2dbc0719472..31a81ee5ab69 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h @@ -37,6 +37,14 @@ struct mod_hdcp_link; struct mod_hdcp_display; struct cp_psp; +struct sink_identification { + uint16_t manufacturer_id; + uint16_t product_id; + uint32_t serial_number; + uint8_t manufacture_week; + uint8_t manufacture_year; +}; + struct hdcp_workqueue { struct work_struct cpirq_work; struct work_struct property_update_work; @@ -53,6 +61,11 @@ struct hdcp_workqueue { enum mod_hdcp_encryption_status encryption_status[ AMDGPU_DM_MAX_DISPLAY_INDEX]; + + struct sink_identification sink_edid_id[AMDGPU_DM_MAX_DISPLAY_INDEX]; + unsigned int hdcp_content_type[AMDGPU_DM_MAX_DISPLAY_INDEX]; + unsigned int content_protection[AMDGPU_DM_MAX_DISPLAY_INDEX]; + uint8_t max_link; uint8_t *srm; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ce6929224a6e..872c83e61a13 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -31,6 +31,9 @@ #include "amdgpu.h" #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" @@ -272,6 +275,10 @@ static bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnect static int dm_dp_mst_get_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); +#ifdef CONFIG_DRM_AMD_DC_HDCP + struct hdcp_workqueue *hdcp_work, *hdcp_w; + unsigned int index; +#endif int ret = 0; if (!aconnector) @@ -344,6 +351,32 @@ 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; +#ifdef CONFIG_DRM_AMD_DC_HDCP + if (aconnector->dc_sink && connector->state) { + hdcp_work = + drm_to_adev(connector->dev)->dm.hdcp_workqueue; + hdcp_w = &hdcp_work[aconnector->dc_link->link_index]; + index = connector->index; + + if (hdcp_w->sink_edid_id[index].manufacturer_id == + aconnector->dc_sink->edid_caps.manufacturer_id && + hdcp_w->sink_edid_id[index].product_id == + aconnector->dc_sink->edid_caps.product_id && + hdcp_w->sink_edid_id[index].serial_number == + aconnector->dc_sink->edid_caps.serial_number && + hdcp_w->sink_edid_id[index].manufacture_week == + aconnector->dc_sink->edid_caps.manufacture_week && + hdcp_w->sink_edid_id[index].manufacture_year == + aconnector->dc_sink->edid_caps.manufacture_year) { + + connector->state->hdcp_content_type = + hdcp_w->hdcp_content_type[index]; + connector->state->content_protection = + hdcp_w->content_protection[index]; + } + } +#endif + if (aconnector->dc_sink) { amdgpu_dm_update_freesync_caps( connector, aconnector->edid); -- 2.37.2