diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3866-drm-amd-display-Handle-Content-protection-property-c.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3866-drm-amd-display-Handle-Content-protection-property-c.patch | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3866-drm-amd-display-Handle-Content-protection-property-c.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3866-drm-amd-display-Handle-Content-protection-property-c.patch new file mode 100644 index 00000000..213393fc --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3866-drm-amd-display-Handle-Content-protection-property-c.patch @@ -0,0 +1,185 @@ +From b0606e6d078d670cfca992383f5b886cf64d69a2 Mon Sep 17 00:00:00 2001 +From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> +Date: Mon, 16 Sep 2019 15:52:58 -0500 +Subject: [PATCH 3866/4256] drm/amd/display: Handle Content protection property + changes + +[Why] +We need to manage the content protection property changes for +different usecase, once cp is DESIRED we need to maintain the +ENABLED/DESIRED status for different cases. + +[How] +1. Attach the content_protection property + +2. HDCP enable (UNDESIRED -> DESIRED) + call into the module with the correct parameters to start + hdcp. Set cp to ENABLED + +3. HDCP disable (ENABLED -> UNDESIRED) + Call the module to disable hdcp. + +3. Handle Special cases (Hotplug, S3, headless S3, DPMS) + If already ENABLED: set to DESIRED on unplug/suspend/dpms, + and disable hdcp + + Then on plugin/resume/dpms: enable HDCP + +Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> +Reviewed-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 96 +++++++++++++++++++ + 1 file changed, 96 insertions(+) + +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 f04b5798ce2c..af7f326c56bd 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -78,6 +78,7 @@ + + #include "soc15_common.h" + #endif ++#include <drm/drm_hdcp.h> + + #include "modules/inc/mod_freesync.h" + #include "modules/power/power_helpers.h" +@@ -1459,6 +1460,11 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) + dc_sink_release(aconnector->dc_sink); + aconnector->dc_sink = NULL; + aconnector->edid = NULL; ++#ifdef CONFIG_DRM_AMD_DC_HDCP ++ /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */ ++ if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) ++ connector->state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; ++#endif + } + + mutex_unlock(&dev->mode_config.mutex); +@@ -1473,12 +1479,18 @@ static void handle_hpd_irq(void *param) + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + enum dc_connection_type new_connection_type = dc_connection_none; ++#ifdef CONFIG_DRM_AMD_DC_HDCP ++ struct amdgpu_device *adev = dev->dev_private; ++#endif + + /* In case of failure or MST no need to update connector status or notify the OS + * since (for MST case) MST does this in it's own context. + */ + mutex_lock(&aconnector->hpd_lock); + ++#ifdef CONFIG_DRM_AMD_DC_HDCP ++ hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index); ++#endif + if (aconnector->fake_enable) + aconnector->fake_enable = false; + +@@ -5086,6 +5098,9 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + adev->mode_info.freesync_property, 0); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.freesync_capable_property, 0); ++#ifdef CONFIG_DRM_AMD_DC_HDCP ++ drm_connector_attach_content_protection_property(&aconnector->base, false); ++#endif + } + } + +@@ -5328,6 +5343,63 @@ is_scaling_state_different(const struct dm_connector_state *dm_state, + return false; + } + ++#ifdef CONFIG_DRM_AMD_DC_HDCP ++static bool is_content_protection_different(struct drm_connector_state *state, ++ const struct drm_connector_state *old_state, ++ const struct drm_connector *connector, struct hdcp_workqueue *hdcp_w) ++{ ++ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); ++ ++ /* CP is being re enabled, ignore this */ ++ if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED && ++ state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) { ++ state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; ++ return false; ++ } ++ ++ /* S3 resume case, since old state will always be 0 (UNDESIRED) and the restored state will be ENABLED */ ++ if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED && ++ state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) ++ state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; ++ ++ /* Check if something is connected/enabled, otherwise we start hdcp but nothing is connected/enabled ++ * hot-plug, headless s3, dpms ++ */ ++ if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED && connector->dpms == DRM_MODE_DPMS_ON && ++ aconnector->dc_sink != NULL) ++ return true; ++ ++ if (old_state->content_protection == state->content_protection) ++ return false; ++ ++ if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) ++ return true; ++ ++ return false; ++} ++ ++static void update_content_protection(struct drm_connector_state *state, const struct drm_connector *connector, ++ struct hdcp_workqueue *hdcp_w) ++{ ++ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); ++ ++ if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) { ++ hdcp_add_display(hdcp_w, aconnector->dc_link->link_index); ++ ++ /* ++ * TODO: ENABLED should be verified using psp, it is planned later. ++ * Just set this to ENABLED for now ++ */ ++ state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; ++ ++ return; ++ } ++ ++ if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) ++ hdcp_remove_display(hdcp_w, aconnector->dc_link->link_index, aconnector->base.index); ++ ++} ++#endif + static void remove_stream(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + struct dc_stream_state *stream) +@@ -6247,6 +6319,30 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + acrtc->otg_inst = status->primary_otg_inst; + } + } ++#ifdef CONFIG_DRM_AMD_DC_HDCP ++ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { ++ struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); ++ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); ++ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); ++ ++ new_crtc_state = NULL; ++ ++ if (acrtc) ++ new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); ++ ++ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); ++ ++ if (dm_new_crtc_state && dm_new_crtc_state->stream == NULL && ++ connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) { ++ hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index); ++ new_con_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; ++ continue; ++ } ++ ++ if (is_content_protection_different(new_con_state, old_con_state, connector, adev->dm.hdcp_workqueue)) ++ update_content_protection(new_con_state, connector, adev->dm.hdcp_workqueue); ++ } ++#endif + + /* Handle connector state changes */ + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { +-- +2.17.1 + |