@@ -103,6 +103,30 @@ static int drm_hdcp_2_2_enable(struct drm_hdcp *hdcp, uint8_t stream_type)
return 0;
}
+void hdcp_2_2_disable_work(struct work_struct *work)
+{
+ struct drm_hdcp *hdcp = container_of(work, struct drm_hdcp,
+ hdcp2_disable_work);
+
+ mutex_lock(&hdcp->mutex);
+
+ hdcp->req_state &= ~DRM_HDCP_ENABLE;
+
+ /*
+ * TODO: Implement the HDCP2.2 Disable Sequence
+ */
+
+ drm_hdcp_update_change(hdcp, false, 0, false);
+
+ mutex_unlock(&hdcp->mutex);
+}
+
+void drm_hdcp_2_2_disable(struct drm_hdcp *hdcp)
+{
+ if (!schedule_work(&hdcp->hdcp2_disable_work))
+ DRM_ERROR("Disable work is already in queue\n");
+}
+
int drm_hdcp_enable(struct drm_connector *connector, uint8_t stream_type)
{
struct drm_hdcp *hdcp = connector->hdcp;
@@ -134,9 +158,8 @@ int drm_hdcp_disable(struct drm_connector *connector)
return 0;
}
- /*
- * TODO: Invoke the Version specific hdcp_disable
- */
+ if (hdcp->spec_ver_used & HDCP_2_2_SUPPORT)
+ drm_hdcp_2_2_disable(hdcp);
return 0;
}
@@ -293,6 +316,7 @@ static inline int drm_hdcp2_init(struct drm_connector *connector,
hdcp->streams[0].stream_type = HDCP_STREAM_TYPE0_CODE;
INIT_WORK(&hdcp->hdcp2_enable_work, hdcp_2_2_enable_work);
+ INIT_WORK(&hdcp->hdcp2_disable_work, hdcp_2_2_disable_work);
return 0;
}
@@ -382,6 +382,7 @@ struct drm_hdcp {
const struct drm_hdcp2_funcs *hdcp2_funcs;
struct work_struct hdcp2_enable_work;
+ struct work_struct hdcp2_disable_work;
struct mutex mutex;
};
HDCP2.2 Disable might take some time to destroy the ongoing link integrity check thread, to disable the encryption and deauthenticate the port. So Just to unblock the caller like hotplug handler or IOCTL we are scheduling the HDCP2.2 disable as an asynchronous work. Once HDCP is disabled, DRM Property will be updated. Signed-off-by: Ramalingam C <ramalingam.c@intel.com> --- drivers/gpu/drm/drm_hdcp.c | 30 +++++++++++++++++++++++++++--- include/drm/drm_hdcp.h | 1 + 2 files changed, 28 insertions(+), 3 deletions(-)