]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/amd/display: save restore hdcp state when display is unplugged from mst hub
authorhersen wu <hersenxs.wu@amd.com>
Tue, 15 Nov 2022 15:39:55 +0000 (10:39 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Aug 2023 15:52:27 +0000 (17:52 +0200)
[ Upstream commit 82986fd631fa04bcedaefe11a6b3767601cbe84f ]

[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>
Stable-dep-of: cdff36a0217a ("drm/amd/display: fix access hdcp_workqueue assert")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c

index 9f718b98da1f7b87bcbbc22297e8d6cc6d947848..bdc6f90b3adb555e8930717836894c2ef62e7863 100644 (file)
@@ -8350,11 +8350,33 @@ 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
 
index 09294ff122fead72611bf7cf909ee5504f311e3c..bbbf7d0eff82f5fbb7ae815a61e83e5275658e51 100644 (file)
@@ -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;
index d07e1053b36b3820f6aa7bd64d2c0aa673c0d329..9884dd78c652c088ff6a381c4e0f1042893db881 100644 (file)
 #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"
 
@@ -363,6 +367,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);