diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3868-drm-amd-display-Update-CP-property-based-on-HW-query.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3868-drm-amd-display-Update-CP-property-based-on-HW-query.patch | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3868-drm-amd-display-Update-CP-property-based-on-HW-query.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3868-drm-amd-display-Update-CP-property-based-on-HW-query.patch new file mode 100644 index 00000000..a6fc99a3 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3868-drm-amd-display-Update-CP-property-based-on-HW-query.patch @@ -0,0 +1,206 @@ +From e5313f84346649b9c45031f299ae4116d1821570 Mon Sep 17 00:00:00 2001 +From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> +Date: Mon, 10 Jun 2019 16:06:05 -0400 +Subject: [PATCH 3868/4256] drm/amd/display: Update CP property based on HW + query + +[Why] +We need to use HW state to set content protection to ENABLED. +This way we know that the link is encrypted from the HW side + +[How] +Create a workqueue that queries the HW every ~2seconds, and sets it to +ENABLED or DESIRED based on the result from the hardware + +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 | 16 +---- + .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 65 ++++++++++++++++++- + .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 7 +- + 3 files changed, 73 insertions(+), 15 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 0d017de12f12..a6c04f490c48 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5398,19 +5398,9 @@ static void update_content_protection(struct drm_connector_state *state, const s + { + 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) ++ if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) ++ hdcp_add_display(hdcp_w, aconnector->dc_link->link_index, aconnector); ++ else if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) + hdcp_remove_display(hdcp_w, aconnector->dc_link->link_index, aconnector->base.index); + + } +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +index 9d11d7695508..2443c238c188 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +@@ -27,6 +27,7 @@ + #include "amdgpu.h" + #include "amdgpu_dm.h" + #include "dm_helpers.h" ++#include <drm/drm_hdcp.h> + + bool lp_write_i2c(void *handle, uint32_t address, const uint8_t *data, uint32_t size) + { +@@ -82,16 +83,19 @@ static void process_output(struct hdcp_workqueue *hdcp_work) + + } + +-void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index) ++void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index, struct amdgpu_dm_connector *aconnector) + { + struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index]; + struct mod_hdcp_display *display = &hdcp_work[link_index].display; + struct mod_hdcp_link *link = &hdcp_work[link_index].link; + + mutex_lock(&hdcp_w->mutex); ++ hdcp_w->aconnector = aconnector; + + mod_hdcp_add_display(&hdcp_w->hdcp, link, display, &hdcp_w->output); + ++ schedule_delayed_work(&hdcp_w->property_validate_dwork, msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS)); ++ + process_output(hdcp_w); + + mutex_unlock(&hdcp_w->mutex); +@@ -106,6 +110,9 @@ void hdcp_remove_display(struct hdcp_workqueue *hdcp_work, unsigned int link_ind + + mod_hdcp_remove_display(&hdcp_w->hdcp, display_index, &hdcp_w->output); + ++ cancel_delayed_work(&hdcp_w->property_validate_dwork); ++ hdcp_w->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; ++ + process_output(hdcp_w); + + mutex_unlock(&hdcp_w->mutex); +@@ -120,6 +127,9 @@ void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_inde + + mod_hdcp_reset_connection(&hdcp_w->hdcp, &hdcp_w->output); + ++ cancel_delayed_work(&hdcp_w->property_validate_dwork); ++ hdcp_w->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; ++ + process_output(hdcp_w); + + mutex_unlock(&hdcp_w->mutex); +@@ -155,7 +165,58 @@ static void event_callback(struct work_struct *work) + + + } ++static void event_property_update(struct work_struct *work) ++{ ++ ++ struct hdcp_workqueue *hdcp_work = container_of(work, struct hdcp_workqueue, property_update_work); ++ struct amdgpu_dm_connector *aconnector = hdcp_work->aconnector; ++ struct drm_device *dev = hdcp_work->aconnector->base.dev; ++ long ret; ++ ++ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); ++ mutex_lock(&hdcp_work->mutex); ++ ++ ++ if (aconnector->base.state->commit) { ++ ret = wait_for_completion_interruptible_timeout(&aconnector->base.state->commit->hw_done, 10 * HZ); ++ ++ if (ret == 0) { ++ DRM_ERROR("HDCP state unknown! Setting it to DESIRED"); ++ hdcp_work->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; ++ } ++ } ++ ++ if (hdcp_work->encryption_status == MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON) ++ drm_hdcp_update_content_protection(&aconnector->base, DRM_MODE_CONTENT_PROTECTION_ENABLED); ++ else ++ drm_hdcp_update_content_protection(&aconnector->base, DRM_MODE_CONTENT_PROTECTION_DESIRED); ++ ++ ++ mutex_unlock(&hdcp_work->mutex); ++ drm_modeset_unlock(&dev->mode_config.connection_mutex); ++} ++ ++static void event_property_validate(struct work_struct *work) ++{ ++ struct hdcp_workqueue *hdcp_work = ++ container_of(to_delayed_work(work), struct hdcp_workqueue, property_validate_dwork); ++ struct mod_hdcp_display_query query; ++ struct amdgpu_dm_connector *aconnector = hdcp_work->aconnector; ++ ++ mutex_lock(&hdcp_work->mutex); + ++ query.encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; ++ mod_hdcp_query_display(&hdcp_work->hdcp, aconnector->base.index, &query); ++ ++ if (query.encryption_status != hdcp_work->encryption_status) { ++ hdcp_work->encryption_status = query.encryption_status; ++ schedule_work(&hdcp_work->property_update_work); ++ } ++ ++ schedule_delayed_work(&hdcp_work->property_validate_dwork, msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS)); ++ ++ mutex_unlock(&hdcp_work->mutex); ++} + + static void event_watchdog_timer(struct work_struct *work) + { +@@ -250,8 +311,10 @@ struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *c + mutex_init(&hdcp_work[i].mutex); + + INIT_WORK(&hdcp_work[i].cpirq_work, event_cpirq); ++ INIT_WORK(&hdcp_work[i].property_update_work, event_property_update); + INIT_DELAYED_WORK(&hdcp_work[i].callback_dwork, event_callback); + INIT_DELAYED_WORK(&hdcp_work[i].watchdog_timer_dwork, event_watchdog_timer); ++ INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate); + + hdcp_work[i].hdcp.config.psp.handle = psp_context; + hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i); +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 cb6c6fbd74f6..d3ba505d0696 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 +@@ -38,8 +38,11 @@ struct cp_psp; + + struct hdcp_workqueue { + struct work_struct cpirq_work; ++ struct work_struct property_update_work; + struct delayed_work callback_dwork; + struct delayed_work watchdog_timer_dwork; ++ struct delayed_work property_validate_dwork; ++ struct amdgpu_dm_connector *aconnector; + struct mutex mutex; + + struct mod_hdcp hdcp; +@@ -47,10 +50,12 @@ struct hdcp_workqueue { + struct mod_hdcp_display display; + struct mod_hdcp_link link; + ++ enum mod_hdcp_encryption_status encryption_status; + uint8_t max_link; + }; + +-void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index); ++void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index, ++ struct amdgpu_dm_connector *aconnector); + void hdcp_remove_display(struct hdcp_workqueue *work, unsigned int link_index, unsigned int display_index); + void hdcp_reset_display(struct hdcp_workqueue *work, unsigned int link_index); + void hdcp_handle_cpirq(struct hdcp_workqueue *work, unsigned int link_index); +-- +2.17.1 + |