aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3863-drm-amd-display-Create-amdgpu_dm_hdcp.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3863-drm-amd-display-Create-amdgpu_dm_hdcp.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3863-drm-amd-display-Create-amdgpu_dm_hdcp.patch359
1 files changed, 359 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3863-drm-amd-display-Create-amdgpu_dm_hdcp.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3863-drm-amd-display-Create-amdgpu_dm_hdcp.patch
new file mode 100644
index 00000000..94079b51
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3863-drm-amd-display-Create-amdgpu_dm_hdcp.patch
@@ -0,0 +1,359 @@
+From cfa8cb5aa5404c3bdc360563d245d755c6fac9f8 Mon Sep 17 00:00:00 2001
+From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Date: Tue, 14 May 2019 13:20:19 -0400
+Subject: [PATCH 3863/4256] drm/amd/display: Create amdgpu_dm_hdcp
+
+[Why]
+We need to interact with the hdcp module from the DM, the module
+has to be interacted with in terms of events
+
+[How]
+Create the files needed for linux hdcp. These files manage the events
+needed for the dm to interact with the hdcp module.
+
+We use the kernel work queue to process the events needed for
+the module
+
+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/Makefile | 4 +
+ .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 241 ++++++++++++++++++
+ .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 61 +++++
+ 3 files changed, 306 insertions(+)
+ create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+ create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+index 94911871eb9b..9a3b7bf8ab0b 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+@@ -31,6 +31,10 @@ ifneq ($(CONFIG_DRM_AMD_DC),)
+ AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o
+ endif
+
++ifdef CONFIG_DRM_AMD_DC_HDCP
++AMDGPUDM += amdgpu_dm_hdcp.o
++endif
++
+ ifneq ($(CONFIG_DEBUG_FS),)
+ AMDGPUDM += amdgpu_dm_crc.o amdgpu_dm_debugfs.o
+ endif
+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
+new file mode 100644
+index 000000000000..004b6e8e9ed5
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+@@ -0,0 +1,241 @@
++/*
++ * Copyright 2019 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++
++#include "amdgpu_dm_hdcp.h"
++#include "amdgpu.h"
++#include "amdgpu_dm.h"
++
++static void process_output(struct hdcp_workqueue *hdcp_work)
++{
++ struct mod_hdcp_output output = hdcp_work->output;
++
++ if (output.callback_stop)
++ cancel_delayed_work(&hdcp_work->callback_dwork);
++
++ if (output.callback_needed)
++ schedule_delayed_work(&hdcp_work->callback_dwork,
++ msecs_to_jiffies(output.callback_delay));
++
++ if (output.watchdog_timer_stop)
++ cancel_delayed_work(&hdcp_work->watchdog_timer_dwork);
++
++ if (output.watchdog_timer_needed)
++ schedule_delayed_work(&hdcp_work->watchdog_timer_dwork,
++ msecs_to_jiffies(output.watchdog_timer_delay));
++
++}
++
++void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index)
++{
++ 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);
++
++ mod_hdcp_add_display(&hdcp_w->hdcp, link, display, &hdcp_w->output);
++
++ process_output(hdcp_w);
++
++ mutex_unlock(&hdcp_w->mutex);
++
++}
++
++void hdcp_remove_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index, unsigned int display_index)
++{
++ struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
++
++ mutex_lock(&hdcp_w->mutex);
++
++ mod_hdcp_remove_display(&hdcp_w->hdcp, display_index, &hdcp_w->output);
++
++ process_output(hdcp_w);
++
++ mutex_unlock(&hdcp_w->mutex);
++
++}
++
++void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index)
++{
++ struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
++
++ mutex_lock(&hdcp_w->mutex);
++
++ mod_hdcp_reset_connection(&hdcp_w->hdcp, &hdcp_w->output);
++
++ process_output(hdcp_w);
++
++ mutex_unlock(&hdcp_w->mutex);
++}
++
++void hdcp_handle_cpirq(struct hdcp_workqueue *hdcp_work, unsigned int link_index)
++{
++ struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
++
++ schedule_work(&hdcp_w->cpirq_work);
++}
++
++
++
++
++static void event_callback(struct work_struct *work)
++{
++ struct hdcp_workqueue *hdcp_work;
++
++ hdcp_work = container_of(to_delayed_work(work), struct hdcp_workqueue,
++ callback_dwork);
++
++ mutex_lock(&hdcp_work->mutex);
++
++ cancel_delayed_work(&hdcp_work->watchdog_timer_dwork);
++
++ mod_hdcp_process_event(&hdcp_work->hdcp, MOD_HDCP_EVENT_CALLBACK,
++ &hdcp_work->output);
++
++ process_output(hdcp_work);
++
++ mutex_unlock(&hdcp_work->mutex);
++
++
++}
++
++
++static void event_watchdog_timer(struct work_struct *work)
++{
++ struct hdcp_workqueue *hdcp_work;
++
++ hdcp_work = container_of(to_delayed_work(work),
++ struct hdcp_workqueue,
++ watchdog_timer_dwork);
++
++ mutex_lock(&hdcp_work->mutex);
++
++ mod_hdcp_process_event(&hdcp_work->hdcp,
++ MOD_HDCP_EVENT_WATCHDOG_TIMEOUT,
++ &hdcp_work->output);
++
++ process_output(hdcp_work);
++
++ mutex_unlock(&hdcp_work->mutex);
++
++}
++
++static void event_cpirq(struct work_struct *work)
++{
++ struct hdcp_workqueue *hdcp_work;
++
++ hdcp_work = container_of(work, struct hdcp_workqueue, cpirq_work);
++
++ mutex_lock(&hdcp_work->mutex);
++
++ mod_hdcp_process_event(&hdcp_work->hdcp, MOD_HDCP_EVENT_CPIRQ, &hdcp_work->output);
++
++ process_output(hdcp_work);
++
++ mutex_unlock(&hdcp_work->mutex);
++
++}
++
++
++void hdcp_destroy(struct hdcp_workqueue *hdcp_work)
++{
++ int i = 0;
++
++ for (i = 0; i < hdcp_work->max_link; i++) {
++ cancel_delayed_work_sync(&hdcp_work[i].callback_dwork);
++ cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork);
++ }
++
++ kfree(hdcp_work);
++
++}
++
++static void update_config(void *handle, struct cp_psp_stream_config *config)
++{
++ struct hdcp_workqueue *hdcp_work = handle;
++ struct amdgpu_dm_connector *aconnector = config->dm_stream_ctx;
++ int link_index = aconnector->dc_link->link_index;
++ struct mod_hdcp_display *display = &hdcp_work[link_index].display;
++ struct mod_hdcp_link *link = &hdcp_work[link_index].link;
++
++ memset(display, 0, sizeof(*display));
++ memset(link, 0, sizeof(*link));
++
++ display->index = aconnector->base.index;
++ display->state = MOD_HDCP_DISPLAY_ACTIVE;
++
++ if (aconnector->dc_sink != NULL)
++ link->mode = mod_hdcp_signal_type_to_operation_mode(aconnector->dc_sink->sink_signal);
++
++ display->controller = CONTROLLER_ID_D0 + config->otg_inst;
++ display->dig_fe = config->stream_enc_inst;
++ link->dig_be = config->link_enc_inst;
++ link->ddc_line = aconnector->dc_link->ddc_hw_inst + 1;
++ link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw;
++ link->adjust.hdcp2.disable = 1;
++
++}
++
++struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *cp_psp, struct dc *dc)
++{
++
++ int max_caps = dc->caps.max_links;
++ struct hdcp_workqueue *hdcp_work = kzalloc(max_caps*sizeof(*hdcp_work), GFP_KERNEL);
++ int i = 0;
++
++ if (hdcp_work == NULL)
++ goto fail_alloc_context;
++
++ hdcp_work->max_link = max_caps;
++
++ for (i = 0; i < max_caps; i++) {
++
++ mutex_init(&hdcp_work[i].mutex);
++
++ INIT_WORK(&hdcp_work[i].cpirq_work, event_cpirq);
++ INIT_DELAYED_WORK(&hdcp_work[i].callback_dwork, event_callback);
++ INIT_DELAYED_WORK(&hdcp_work[i].watchdog_timer_dwork, event_watchdog_timer);
++
++ hdcp_work[i].hdcp.config.psp.handle = psp_context;
++ hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);
++
++ }
++
++ cp_psp->funcs.update_stream_config = update_config;
++ cp_psp->handle = hdcp_work;
++
++ return hdcp_work;
++
++fail_alloc_context:
++ kfree(hdcp_work);
++
++ return NULL;
++
++
++
++}
++
++
++
+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
+new file mode 100644
+index 000000000000..cb6c6fbd74f6
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
+@@ -0,0 +1,61 @@
++/*
++ * Copyright 2019 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++
++#ifndef AMDGPU_DM_AMDGPU_DM_HDCP_H_
++#define AMDGPU_DM_AMDGPU_DM_HDCP_H_
++
++#include "mod_hdcp.h"
++#include "hdcp.h"
++#include "dc.h"
++#include "dm_cp_psp.h"
++
++struct mod_hdcp;
++struct mod_hdcp_link;
++struct mod_hdcp_display;
++struct cp_psp;
++
++struct hdcp_workqueue {
++ struct work_struct cpirq_work;
++ struct delayed_work callback_dwork;
++ struct delayed_work watchdog_timer_dwork;
++ struct mutex mutex;
++
++ struct mod_hdcp hdcp;
++ struct mod_hdcp_output output;
++ struct mod_hdcp_display display;
++ struct mod_hdcp_link link;
++
++ uint8_t max_link;
++};
++
++void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index);
++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);
++void hdcp_destroy(struct hdcp_workqueue *work);
++
++struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *cp_psp, struct dc *dc);
++
++#endif /* AMDGPU_DM_AMDGPU_DM_HDCP_H_ */
+--
+2.17.1
+