From 6a99099fe1d6c46cbcd74298eeb386c4b9048f77 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 21 Apr 2022 09:31:06 +0200 Subject: drm/display: Move HDCP helpers into display-helper module Move DRM's HDCP helper library into the display/ subdirectory and add it to DRM's display helpers. Split the header file into core and helpers. Update all affected drivers. No functional changes. v3: * fix Kconfig dependencies v2: * fix include statements (Jani, Javier) * update Kconfig symbols Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220421073108.19226-7-tzimmermann@suse.de --- Documentation/gpu/drm-kms-helpers.rst | 2 +- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/amd/display/Kconfig | 1 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 2 +- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h | 2 +- drivers/gpu/drm/bridge/Kconfig | 1 + drivers/gpu/drm/bridge/analogix/Kconfig | 1 + drivers/gpu/drm/bridge/analogix/anx7625.c | 2 +- drivers/gpu/drm/bridge/cadence/Kconfig | 1 + .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 2 +- .../gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c | 2 +- drivers/gpu/drm/bridge/ite-it6505.c | 2 +- drivers/gpu/drm/display/Kconfig | 6 + drivers/gpu/drm/display/Makefile | 1 + drivers/gpu/drm/display/drm_hdcp_helper.c | 421 ++++++++++++++++++++ drivers/gpu/drm/drm_hdcp.c | 423 --------------------- drivers/gpu/drm/i915/Kconfig | 1 + drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 2 +- drivers/gpu/drm/i915/display/intel_gmbus.c | 2 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- drivers/misc/mei/hdcp/mei_hdcp.h | 2 +- include/drm/display/drm_hdcp.h | 298 +++++++++++++++ include/drm/display/drm_hdcp_helper.h | 22 ++ include/drm/drm_hdcp.h | 308 --------------- include/drm/i915_mei_hdcp_interface.h | 2 +- 27 files changed, 768 insertions(+), 746 deletions(-) create mode 100644 drivers/gpu/drm/display/drm_hdcp_helper.c delete mode 100644 drivers/gpu/drm/drm_hdcp.c create mode 100644 include/drm/display/drm_hdcp.h create mode 100644 include/drm/display/drm_hdcp_helper.h delete mode 100644 include/drm/drm_hdcp.h diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 7af55fb4072c..cfda5a092a48 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -226,7 +226,7 @@ Panel Self Refresh Helper Reference HDCP Helper Functions Reference =============================== -.. kernel-doc:: drivers/gpu/drm/drm_hdcp.c +.. kernel-doc:: drivers/gpu/drm/display/drm_hdcp_helper.c :export: Display Port Helper Functions Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index b8353af70152..746a3a4953f3 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -58,7 +58,7 @@ obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o # drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o \ - drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \ + drm_encoder_slave.o drm_flip_work.o \ drm_probe_helper.o \ drm_plane_helper.o drm_atomic_helper.o \ drm_kms_helper_common.o \ diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 127667e549c1..b4029c0d5d8c 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -20,6 +20,7 @@ config DRM_AMD_DC_DCN config DRM_AMD_DC_HDCP bool "Enable HDCP support in DC" depends on DRM_AMD_DC + select DRM_DISPLAY_HDCP_HELPER help Choose this option if you want to support HDCP authentication. 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 7ef20da6c18f..e3130b4af540 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -48,7 +48,7 @@ #include "amdgpu_dm.h" #ifdef CONFIG_DRM_AMD_DC_HDCP #include "amdgpu_dm_hdcp.h" -#include +#include #endif #include "amdgpu_pm.h" #include "amdgpu_atombios.h" 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 bf0d50277f8f..15c0e3f2a9c3 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,7 +27,7 @@ #include "amdgpu.h" #include "amdgpu_dm.h" #include "dm_helpers.h" -#include +#include #include "hdcp_psp.h" /* diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index 6e88705e22f7..392c0c03365a 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -30,7 +30,7 @@ #include "hdcp_log.h" #include -#include +#include enum mod_hdcp_trans_input_result { UNKNOWN = 0, diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 73ea668babbf..ef9f1b0d91bf 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -79,6 +79,7 @@ config DRM_ITE_IT6505 tristate "ITE IT6505 DisplayPort bridge" depends on OF select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_DP_AUX_BUS select DRM_KMS_HELPER diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index 5570322dc528..173dada218ec 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -35,6 +35,7 @@ config DRM_ANALOGIX_ANX7625 depends on DRM depends on OF select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_DP_AUX_BUS select DRM_MIPI_DSI diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index be2c096374aa..53a5da6c49dd 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -23,11 +23,11 @@ #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig index 0f9e46c6de9b..1d06182bea71 100644 --- a/drivers/gpu/drm/bridge/cadence/Kconfig +++ b/drivers/gpu/drm/bridge/cadence/Kconfig @@ -2,6 +2,7 @@ config DRM_CDNS_MHDP8546 tristate "Cadence DPI/DP bridge" select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index dec93a6d14c7..67f0f444b4e8 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -36,13 +36,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include #include diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c index fccd6fbcc257..946212a95598 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c @@ -11,7 +11,7 @@ #include -#include +#include #include "cdns-mhdp8546-hdcp.h" diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 85cffc108278..8fed30df08b0 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -22,12 +22,12 @@ #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index fcd9ffd39f26..4406af5cc8bb 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -17,6 +17,12 @@ config DRM_DISPLAY_DP_HELPER help DRM display helpers for DisplayPort. +config DRM_DISPLAY_HDCP_HELPER + bool + depends on DRM_DISPLAY_HELPER + help + DRM display helpers for HDCP. + config DRM_DP_AUX_CHARDEV bool "DRM DP AUX Interface" depends on DRM diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile index 4f4e35034960..abeb5ad8c351 100644 --- a/drivers/gpu/drm/display/Makefile +++ b/drivers/gpu/drm/display/Makefile @@ -7,6 +7,7 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += drm_dp_dual_mode_helper.o drm_dp_helper.o \ drm_dp_mst_topology.o \ drm_dsc_helper.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c new file mode 100644 index 000000000000..e78999c72bd7 --- /dev/null +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Intel Corporation. + * + * Authors: + * Ramalingam C + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static inline void drm_hdcp_print_ksv(const u8 *ksv) +{ + DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n", + ksv[0], ksv[1], ksv[2], ksv[3], ksv[4]); +} + +static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length) +{ + u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz; + + while (parsed_bytes < vrls_length) { + vrl_ksv_cnt = *buf; + ksv_count += vrl_ksv_cnt; + + vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1; + buf += vrl_sz; + parsed_bytes += vrl_sz; + } + + /* + * When vrls are not valid, ksvs are not considered. + * Hence SRM will be discarded. + */ + if (parsed_bytes != vrls_length) + ksv_count = 0; + + return ksv_count; +} + +static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 **revoked_ksv_list, + u32 vrls_length) +{ + u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0; + u32 parsed_bytes = 0, ksv_count = 0; + + do { + vrl_ksv_cnt = *buf; + vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN; + + buf++; + + DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++, + vrl_ksv_cnt); + memcpy((*revoked_ksv_list) + (ksv_count * DRM_HDCP_KSV_LEN), + buf, vrl_ksv_sz); + + ksv_count += vrl_ksv_cnt; + buf += vrl_ksv_sz; + + parsed_bytes += (vrl_ksv_sz + 1); + } while (parsed_bytes < vrls_length); + + return ksv_count; +} + +static inline u32 get_vrl_length(const u8 *buf) +{ + return drm_hdcp_be24_to_cpu(buf); +} + +static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count, + u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) +{ + struct hdcp_srm_header *header; + u32 vrl_length, ksv_count; + + if (count < (sizeof(struct hdcp_srm_header) + + DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) { + DRM_ERROR("Invalid blob length\n"); + return -EINVAL; + } + + header = (struct hdcp_srm_header *)buf; + DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n", + header->srm_id, + be16_to_cpu(header->srm_version), header->srm_gen_no); + + WARN_ON(header->reserved); + + buf = buf + sizeof(*header); + vrl_length = get_vrl_length(buf); + if (count < (sizeof(struct hdcp_srm_header) + vrl_length) || + vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE + + DRM_HDCP_1_4_DCP_SIG_SIZE)) { + DRM_ERROR("Invalid blob length or vrl length\n"); + return -EINVAL; + } + + /* Length of the all vrls combined */ + vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE + + DRM_HDCP_1_4_DCP_SIG_SIZE); + + if (!vrl_length) { + DRM_ERROR("No vrl found\n"); + return -EINVAL; + } + + buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE; + ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length); + if (!ksv_count) { + DRM_DEBUG("Revoked KSV count is 0\n"); + return 0; + } + + *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL); + if (!*revoked_ksv_list) { + DRM_ERROR("Out of Memory\n"); + return -ENOMEM; + } + + if (drm_hdcp_get_revoked_ksvs(buf, revoked_ksv_list, + vrl_length) != ksv_count) { + *revoked_ksv_cnt = 0; + kfree(*revoked_ksv_list); + return -EINVAL; + } + + *revoked_ksv_cnt = ksv_count; + return 0; +} + +static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count, + u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) +{ + struct hdcp_srm_header *header; + u32 vrl_length, ksv_count, ksv_sz; + + if (count < (sizeof(struct hdcp_srm_header) + + DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) { + DRM_ERROR("Invalid blob length\n"); + return -EINVAL; + } + + header = (struct hdcp_srm_header *)buf; + DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n", + header->srm_id & DRM_HDCP_SRM_ID_MASK, + be16_to_cpu(header->srm_version), header->srm_gen_no); + + if (header->reserved) + return -EINVAL; + + buf = buf + sizeof(*header); + vrl_length = get_vrl_length(buf); + + if (count < (sizeof(struct hdcp_srm_header) + vrl_length) || + vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE + + DRM_HDCP_2_DCP_SIG_SIZE)) { + DRM_ERROR("Invalid blob length or vrl length\n"); + return -EINVAL; + } + + /* Length of the all vrls combined */ + vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE + + DRM_HDCP_2_DCP_SIG_SIZE); + + if (!vrl_length) { + DRM_ERROR("No vrl found\n"); + return -EINVAL; + } + + buf += DRM_HDCP_2_VRL_LENGTH_SIZE; + ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1)); + if (!ksv_count) { + DRM_DEBUG("Revoked KSV count is 0\n"); + return 0; + } + + *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL); + if (!*revoked_ksv_list) { + DRM_ERROR("Out of Memory\n"); + return -ENOMEM; + } + + ksv_sz = ksv_count * DRM_HDCP_KSV_LEN; + buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ; + + DRM_DEBUG("Revoked KSVs: %d\n", ksv_count); + memcpy(*revoked_ksv_list, buf, ksv_sz); + + *revoked_ksv_cnt = ksv_count; + return 0; +} + +static inline bool is_srm_version_hdcp1(const u8 *buf) +{ + return *buf == (u8)(DRM_HDCP_1_4_SRM_ID << 4); +} + +static inline bool is_srm_version_hdcp2(const u8 *buf) +{ + return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR); +} + +static int drm_hdcp_srm_update(const u8 *buf, size_t count, + u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) +{ + if (count < sizeof(struct hdcp_srm_header)) + return -EINVAL; + + if (is_srm_version_hdcp1(buf)) + return drm_hdcp_parse_hdcp1_srm(buf, count, revoked_ksv_list, + revoked_ksv_cnt); + else if (is_srm_version_hdcp2(buf)) + return drm_hdcp_parse_hdcp2_srm(buf, count, revoked_ksv_list, + revoked_ksv_cnt); + else + return -EINVAL; +} + +static int drm_hdcp_request_srm(struct drm_device *drm_dev, + u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) +{ + char fw_name[36] = "display_hdcp_srm.bin"; + const struct firmware *fw; + int ret; + + ret = request_firmware_direct(&fw, (const char *)fw_name, + drm_dev->dev); + if (ret < 0) { + *revoked_ksv_cnt = 0; + *revoked_ksv_list = NULL; + ret = 0; + goto exit; + } + + if (fw->size && fw->data) + ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list, + revoked_ksv_cnt); + +exit: + release_firmware(fw); + return ret; +} + +/** + * drm_hdcp_check_ksvs_revoked - Check the revoked status of the IDs + * + * @drm_dev: drm_device for which HDCP revocation check is requested + * @ksvs: List of KSVs (HDCP receiver IDs) + * @ksv_count: KSV count passed in through @ksvs + * + * This function reads the HDCP System renewability Message(SRM Table) + * from userspace as a firmware and parses it for the revoked HDCP + * KSVs(Receiver IDs) detected by DCP LLC. Once the revoked KSVs are known, + * revoked state of the KSVs in the list passed in by display drivers are + * decided and response is sent. + * + * SRM should be presented in the name of "display_hdcp_srm.bin". + * + * Format of the SRM table, that userspace needs to write into the binary file, + * is defined at: + * 1. Renewability chapter on 55th page of HDCP 1.4 specification + * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20Specification%20Rev1_4_Secure.pdf + * 2. Renewability chapter on 63rd page of HDCP 2.2 specification + * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf + * + * Returns: + * Count of the revoked KSVs or -ve error number in case of the failure. + */ +int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs, + u32 ksv_count) +{ + u32 revoked_ksv_cnt = 0, i, j; + u8 *revoked_ksv_list = NULL; + int ret = 0; + + ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list, + &revoked_ksv_cnt); + if (ret) + return ret; + + /* revoked_ksv_cnt will be zero when above function failed */ + for (i = 0; i < revoked_ksv_cnt; i++) + for (j = 0; j < ksv_count; j++) + if (!memcmp(&ksvs[j * DRM_HDCP_KSV_LEN], + &revoked_ksv_list[i * DRM_HDCP_KSV_LEN], + DRM_HDCP_KSV_LEN)) { + DRM_DEBUG("Revoked KSV is "); + drm_hdcp_print_ksv(&ksvs[j * DRM_HDCP_KSV_LEN]); + ret++; + } + + kfree(revoked_ksv_list); + return ret; +} +EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked); + +static struct drm_prop_enum_list drm_cp_enum_list[] = { + { DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" }, + { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" }, + { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" }, +}; +DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) + +static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = { + { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" }, + { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" }, +}; +DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name, + drm_hdcp_content_type_enum_list) + +/** + * drm_connector_attach_content_protection_property - attach content protection + * property + * + * @connector: connector to attach CP property on. + * @hdcp_content_type: is HDCP Content Type property needed for connector + * + * This is used to add support for content protection on select connectors. + * Content Protection is intentionally vague to allow for different underlying + * technologies, however it is most implemented by HDCP. + * + * When hdcp_content_type is true enum property called HDCP Content Type is + * created (if it is not already) and attached to the connector. + * + * This property is used for sending the protected content's stream type + * from userspace to kernel on selected connectors. Protected content provider + * will decide their type of their content and declare the same to kernel. + * + * Content type will be used during the HDCP 2.2 authentication. + * Content type will be set to &drm_connector_state.hdcp_content_type. + * + * The content protection will be set to &drm_connector_state.content_protection + * + * When kernel triggered content protection state change like DESIRED->ENABLED + * and ENABLED->DESIRED, will use drm_hdcp_update_content_protection() to update + * the content protection state of a connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_content_protection_property( + struct drm_connector *connector, bool hdcp_content_type) +{ + struct drm_device *dev = connector->dev; + struct drm_property *prop = + dev->mode_config.content_protection_property; + + if (!prop) + prop = drm_property_create_enum(dev, 0, "Content Protection", + drm_cp_enum_list, + ARRAY_SIZE(drm_cp_enum_list)); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&connector->base, prop, + DRM_MODE_CONTENT_PROTECTION_UNDESIRED); + dev->mode_config.content_protection_property = prop; + + if (!hdcp_content_type) + return 0; + + prop = dev->mode_config.hdcp_content_type_property; + if (!prop) + prop = drm_property_create_enum(dev, 0, "HDCP Content Type", + drm_hdcp_content_type_enum_list, + ARRAY_SIZE( + drm_hdcp_content_type_enum_list)); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&connector->base, prop, + DRM_MODE_HDCP_CONTENT_TYPE0); + dev->mode_config.hdcp_content_type_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_content_protection_property); + +/** + * drm_hdcp_update_content_protection - Updates the content protection state + * of a connector + * + * @connector: drm_connector on which content protection state needs an update + * @val: New state of the content protection property + * + * This function can be used by display drivers, to update the kernel triggered + * content protection state changes of a drm_connector such as DESIRED->ENABLED + * and ENABLED->DESIRED. No uevent for DESIRED->UNDESIRED or ENABLED->UNDESIRED, + * as userspace is triggering such state change and kernel performs it without + * fail.This function update the new state of the property into the connector's + * state and generate an uevent to notify the userspace. + */ +void drm_hdcp_update_content_protection(struct drm_connector *connector, + u64 val) +{ + struct drm_device *dev = connector->dev; + struct drm_connector_state *state = connector->state; + + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + if (state->content_protection == val) + return; + + state->content_protection = val; + drm_sysfs_connector_status_event(connector, + dev->mode_config.content_protection_property); +} +EXPORT_SYMBOL(drm_hdcp_update_content_protection); diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c deleted file mode 100644 index ca9b8f697202..000000000000 --- a/drivers/gpu/drm/drm_hdcp.c +++ /dev/null @@ -1,423 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2019 Intel Corporation. - * - * Authors: - * Ramalingam C - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "drm_internal.h" - -static inline void drm_hdcp_print_ksv(const u8 *ksv) -{ - DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n", - ksv[0], ksv[1], ksv[2], ksv[3], ksv[4]); -} - -static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length) -{ - u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz; - - while (parsed_bytes < vrls_length) { - vrl_ksv_cnt = *buf; - ksv_count += vrl_ksv_cnt; - - vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1; - buf += vrl_sz; - parsed_bytes += vrl_sz; - } - - /* - * When vrls are not valid, ksvs are not considered. - * Hence SRM will be discarded. - */ - if (parsed_bytes != vrls_length) - ksv_count = 0; - - return ksv_count; -} - -static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 **revoked_ksv_list, - u32 vrls_length) -{ - u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0; - u32 parsed_bytes = 0, ksv_count = 0; - - do { - vrl_ksv_cnt = *buf; - vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN; - - buf++; - - DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++, - vrl_ksv_cnt); - memcpy((*revoked_ksv_list) + (ksv_count * DRM_HDCP_KSV_LEN), - buf, vrl_ksv_sz); - - ksv_count += vrl_ksv_cnt; - buf += vrl_ksv_sz; - - parsed_bytes += (vrl_ksv_sz + 1); - } while (parsed_bytes < vrls_length); - - return ksv_count; -} - -static inline u32 get_vrl_length(const u8 *buf) -{ - return drm_hdcp_be24_to_cpu(buf); -} - -static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count, - u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) -{ - struct hdcp_srm_header *header; - u32 vrl_length, ksv_count; - - if (count < (sizeof(struct hdcp_srm_header) + - DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) { - DRM_ERROR("Invalid blob length\n"); - return -EINVAL; - } - - header = (struct hdcp_srm_header *)buf; - DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n", - header->srm_id, - be16_to_cpu(header->srm_version), header->srm_gen_no); - - WARN_ON(header->reserved); - - buf = buf + sizeof(*header); - vrl_length = get_vrl_length(buf); - if (count < (sizeof(struct hdcp_srm_header) + vrl_length) || - vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE + - DRM_HDCP_1_4_DCP_SIG_SIZE)) { - DRM_ERROR("Invalid blob length or vrl length\n"); - return -EINVAL; - } - - /* Length of the all vrls combined */ - vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE + - DRM_HDCP_1_4_DCP_SIG_SIZE); - - if (!vrl_length) { - DRM_ERROR("No vrl found\n"); - return -EINVAL; - } - - buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE; - ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length); - if (!ksv_count) { - DRM_DEBUG("Revoked KSV count is 0\n"); - return 0; - } - - *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL); - if (!*revoked_ksv_list) { - DRM_ERROR("Out of Memory\n"); - return -ENOMEM; - } - - if (drm_hdcp_get_revoked_ksvs(buf, revoked_ksv_list, - vrl_length) != ksv_count) { - *revoked_ksv_cnt = 0; - kfree(*revoked_ksv_list); - return -EINVAL; - } - - *revoked_ksv_cnt = ksv_count; - return 0; -} - -static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count, - u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) -{ - struct hdcp_srm_header *header; - u32 vrl_length, ksv_count, ksv_sz; - - if (count < (sizeof(struct hdcp_srm_header) + - DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) { - DRM_ERROR("Invalid blob length\n"); - return -EINVAL; - } - - header = (struct hdcp_srm_header *)buf; - DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n", - header->srm_id & DRM_HDCP_SRM_ID_MASK, - be16_to_cpu(header->srm_version), header->srm_gen_no); - - if (header->reserved) - return -EINVAL; - - buf = buf + sizeof(*header); - vrl_length = get_vrl_length(buf); - - if (count < (sizeof(struct hdcp_srm_header) + vrl_length) || - vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE + - DRM_HDCP_2_DCP_SIG_SIZE)) { - DRM_ERROR("Invalid blob length or vrl length\n"); - return -EINVAL; - } - - /* Length of the all vrls combined */ - vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE + - DRM_HDCP_2_DCP_SIG_SIZE); - - if (!vrl_length) { - DRM_ERROR("No vrl found\n"); - return -EINVAL; - } - - buf += DRM_HDCP_2_VRL_LENGTH_SIZE; - ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1)); - if (!ksv_count) { - DRM_DEBUG("Revoked KSV count is 0\n"); - return 0; - } - - *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL); - if (!*revoked_ksv_list) { - DRM_ERROR("Out of Memory\n"); - return -ENOMEM; - } - - ksv_sz = ksv_count * DRM_HDCP_KSV_LEN; - buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ; - - DRM_DEBUG("Revoked KSVs: %d\n", ksv_count); - memcpy(*revoked_ksv_list, buf, ksv_sz); - - *revoked_ksv_cnt = ksv_count; - return 0; -} - -static inline bool is_srm_version_hdcp1(const u8 *buf) -{ - return *buf == (u8)(DRM_HDCP_1_4_SRM_ID << 4); -} - -static inline bool is_srm_version_hdcp2(const u8 *buf) -{ - return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR); -} - -static int drm_hdcp_srm_update(const u8 *buf, size_t count, - u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) -{ - if (count < sizeof(struct hdcp_srm_header)) - return -EINVAL; - - if (is_srm_version_hdcp1(buf)) - return drm_hdcp_parse_hdcp1_srm(buf, count, revoked_ksv_list, - revoked_ksv_cnt); - else if (is_srm_version_hdcp2(buf)) - return drm_hdcp_parse_hdcp2_srm(buf, count, revoked_ksv_list, - revoked_ksv_cnt); - else - return -EINVAL; -} - -static int drm_hdcp_request_srm(struct drm_device *drm_dev, - u8 **revoked_ksv_list, u32 *revoked_ksv_cnt) -{ - char fw_name[36] = "display_hdcp_srm.bin"; - const struct firmware *fw; - int ret; - - ret = request_firmware_direct(&fw, (const char *)fw_name, - drm_dev->dev); - if (ret < 0) { - *revoked_ksv_cnt = 0; - *revoked_ksv_list = NULL; - ret = 0; - goto exit; - } - - if (fw->size && fw->data) - ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list, - revoked_ksv_cnt); - -exit: - release_firmware(fw); - return ret; -} - -/** - * drm_hdcp_check_ksvs_revoked - Check the revoked status of the IDs - * - * @drm_dev: drm_device for which HDCP revocation check is requested - * @ksvs: List of KSVs (HDCP receiver IDs) - * @ksv_count: KSV count passed in through @ksvs - * - * This function reads the HDCP System renewability Message(SRM Table) - * from userspace as a firmware and parses it for the revoked HDCP - * KSVs(Receiver IDs) detected by DCP LLC. Once the revoked KSVs are known, - * revoked state of the KSVs in the list passed in by display drivers are - * decided and response is sent. - * - * SRM should be presented in the name of "display_hdcp_srm.bin". - * - * Format of the SRM table, that userspace needs to write into the binary file, - * is defined at: - * 1. Renewability chapter on 55th page of HDCP 1.4 specification - * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20Specification%20Rev1_4_Secure.pdf - * 2. Renewability chapter on 63rd page of HDCP 2.2 specification - * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf - * - * Returns: - * Count of the revoked KSVs or -ve error number in case of the failure. - */ -int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs, - u32 ksv_count) -{ - u32 revoked_ksv_cnt = 0, i, j; - u8 *revoked_ksv_list = NULL; - int ret = 0; - - ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list, - &revoked_ksv_cnt); - if (ret) - return ret; - - /* revoked_ksv_cnt will be zero when above function failed */ - for (i = 0; i < revoked_ksv_cnt; i++) - for (j = 0; j < ksv_count; j++) - if (!memcmp(&ksvs[j * DRM_HDCP_KSV_LEN], - &revoked_ksv_list[i * DRM_HDCP_KSV_LEN], - DRM_HDCP_KSV_LEN)) { - DRM_DEBUG("Revoked KSV is "); - drm_hdcp_print_ksv(&ksvs[j * DRM_HDCP_KSV_LEN]); - ret++; - } - - kfree(revoked_ksv_list); - return ret; -} -EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked); - -static struct drm_prop_enum_list drm_cp_enum_list[] = { - { DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" }, - { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" }, - { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" }, -}; -DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) - -static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = { - { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" }, - { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" }, -}; -DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name, - drm_hdcp_content_type_enum_list) - -/** - * drm_connector_attach_content_protection_property - attach content protection - * property - * - * @connector: connector to attach CP property on. - * @hdcp_content_type: is HDCP Content Type property needed for connector - * - * This is used to add support for content protection on select connectors. - * Content Protection is intentionally vague to allow for different underlying - * technologies, however it is most implemented by HDCP. - * - * When hdcp_content_type is true enum property called HDCP Content Type is - * created (if it is not already) and attached to the connector. - * - * This property is used for sending the protected content's stream type - * from userspace to kernel on selected connectors. Protected content provider - * will decide their type of their content and declare the same to kernel. - * - * Content type will be used during the HDCP 2.2 authentication. - * Content type will be set to &drm_connector_state.hdcp_content_type. - * - * The content protection will be set to &drm_connector_state.content_protection - * - * When kernel triggered content protection state change like DESIRED->ENABLED - * and ENABLED->DESIRED, will use drm_hdcp_update_content_protection() to update - * the content protection state of a connector. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int drm_connector_attach_content_protection_property( - struct drm_connector *connector, bool hdcp_content_type) -{ - struct drm_device *dev = connector->dev; - struct drm_property *prop = - dev->mode_config.content_protection_property; - - if (!prop) - prop = drm_property_create_enum(dev, 0, "Content Protection", - drm_cp_enum_list, - ARRAY_SIZE(drm_cp_enum_list)); - if (!prop) - return -ENOMEM; - - drm_object_attach_property(&connector->base, prop, - DRM_MODE_CONTENT_PROTECTION_UNDESIRED); - dev->mode_config.content_protection_property = prop; - - if (!hdcp_content_type) - return 0; - - prop = dev->mode_config.hdcp_content_type_property; - if (!prop) - prop = drm_property_create_enum(dev, 0, "HDCP Content Type", - drm_hdcp_content_type_enum_list, - ARRAY_SIZE( - drm_hdcp_content_type_enum_list)); - if (!prop) - return -ENOMEM; - - drm_object_attach_property(&connector->base, prop, - DRM_MODE_HDCP_CONTENT_TYPE0); - dev->mode_config.hdcp_content_type_property = prop; - - return 0; -} -EXPORT_SYMBOL(drm_connector_attach_content_protection_property); - -/** - * drm_hdcp_update_content_protection - Updates the content protection state - * of a connector - * - * @connector: drm_connector on which content protection state needs an update - * @val: New state of the content protection property - * - * This function can be used by display drivers, to update the kernel triggered - * content protection state changes of a drm_connector such as DESIRED->ENABLED - * and ENABLED->DESIRED. No uevent for DESIRED->UNDESIRED or ENABLED->UNDESIRED, - * as userspace is triggering such state change and kernel performs it without - * fail.This function update the new state of the property into the connector's - * state and generate an uevent to notify the userspace. - */ -void drm_hdcp_update_content_protection(struct drm_connector *connector, - u64 val) -{ - struct drm_device *dev = connector->dev; - struct drm_connector_state *state = connector->state; - - WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - if (state->content_protection == val) - return; - - state->content_protection = val; - drm_sysfs_connector_status_event(connector, - dev->mode_config.content_protection_property); -} -EXPORT_SYMBOL(drm_hdcp_update_content_protection); diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 883284ca0a29..a78d82cccbff 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -11,6 +11,7 @@ config DRM_I915 select SHMEM select TMPFS select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 598cad09d499..a7640dbcf00e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "intel_ddi.h" diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 21281a7bdc17..a6ba7fb72339 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include "i915_drv.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 4de4c174a987..44ac0cee8b77 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index a4a6f8bd2841..c713cebc63fe 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -32,10 +32,10 @@ #include #include +#include #include #include #include -#include #include #include diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h index 834757f5e072..ca09c8f83d6b 100644 --- a/drivers/misc/mei/hdcp/mei_hdcp.h +++ b/drivers/misc/mei/hdcp/mei_hdcp.h @@ -9,7 +9,7 @@ #ifndef __MEI_HDCP_H__ #define __MEI_HDCP_H__ -#include +#include /* me_hdcp_status: Enumeration of all HDCP Status Codes */ enum me_hdcp_status { diff --git a/include/drm/display/drm_hdcp.h b/include/drm/display/drm_hdcp.h new file mode 100644 index 000000000000..96a99b1377c0 --- /dev/null +++ b/include/drm/display/drm_hdcp.h @@ -0,0 +1,298 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2017 Google, Inc. + * + * Authors: + * Sean Paul + */ + +#ifndef _DRM_HDCP_H_ +#define _DRM_HDCP_H_ + +#include + +/* Period of hdcp checks (to ensure we're still authenticated) */ +#define DRM_HDCP_CHECK_PERIOD_MS (128 * 16) +#define DRM_HDCP2_CHECK_PERIOD_MS 500 + +/* Shared lengths/masks between HDMI/DVI/DisplayPort */ +#define DRM_HDCP_AN_LEN 8 +#define DRM_HDCP_BSTATUS_LEN 2 +#define DRM_HDCP_KSV_LEN 5 +#define DRM_HDCP_RI_LEN 2 +#define DRM_HDCP_V_PRIME_PART_LEN 4 +#define DRM_HDCP_V_PRIME_NUM_PARTS 5 +#define DRM_HDCP_NUM_DOWNSTREAM(x) (x & 0x7f) +#define DRM_HDCP_MAX_CASCADE_EXCEEDED(x) (x & BIT(3)) +#define DRM_HDCP_MAX_DEVICE_EXCEEDED(x) (x & BIT(7)) + +/* Slave address for the HDCP registers in the receiver */ +#define DRM_HDCP_DDC_ADDR 0x3A + +/* Value to use at the end of the SHA-1 bytestream used for repeaters */ +#define DRM_HDCP_SHA1_TERMINATOR 0x80 + +/* HDCP register offsets for HDMI/DVI devices */ +#define DRM_HDCP_DDC_BKSV 0x00 +#define DRM_HDCP_DDC_RI_PRIME 0x08 +#define DRM_HDCP_DDC_AKSV 0x10 +#define DRM_HDCP_DDC_AN 0x18 +#define DRM_HDCP_DDC_V_PRIME(h) (0x20 + h * 4) +#define DRM_HDCP_DDC_BCAPS 0x40 +#define DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT BIT(6) +#define DRM_HDCP_DDC_BCAPS_KSV_FIFO_READY BIT(5) +#define DRM_HDCP_DDC_BSTATUS 0x41 +#define DRM_HDCP_DDC_KSV_FIFO 0x43 + +#define DRM_HDCP_1_4_SRM_ID 0x8 +#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3 +#define DRM_HDCP_1_4_DCP_SIG_SIZE 40 + +/* Protocol message definition for HDCP2.2 specification */ +/* + * Protected content streams are classified into 2 types: + * - Type0: Can be transmitted with HDCP 1.4+ + * - Type1: Can be transmitted with HDCP 2.2+ + */ +#define HDCP_STREAM_TYPE0 0x00 +#define HDCP_STREAM_TYPE1 0x01 + +/* HDCP2.2 Msg IDs */ +#define HDCP_2_2_NULL_MSG 1 +#define HDCP_2_2_AKE_INIT 2 +#define HDCP_2_2_AKE_SEND_CERT 3 +#define HDCP_2_2_AKE_NO_STORED_KM 4 +#define HDCP_2_2_AKE_STORED_KM 5 +#define HDCP_2_2_AKE_SEND_HPRIME 7 +#define HDCP_2_2_AKE_SEND_PAIRING_INFO 8 +#define HDCP_2_2_LC_INIT 9 +#define HDCP_2_2_LC_SEND_LPRIME 10 +#define HDCP_2_2_SKE_SEND_EKS 11 +#define HDCP_2_2_REP_SEND_RECVID_LIST 12 +#define HDCP_2_2_REP_SEND_ACK 15 +#define HDCP_2_2_REP_STREAM_MANAGE 16 +#define HDCP_2_2_REP_STREAM_READY 17 + +#define HDCP_2_2_RTX_LEN 8 +#define HDCP_2_2_RRX_LEN 8 + +#define HDCP_2_2_K_PUB_RX_MOD_N_LEN 128 +#define HDCP_2_2_K_PUB_RX_EXP_E_LEN 3 +#define HDCP_2_2_K_PUB_RX_LEN (HDCP_2_2_K_PUB_RX_MOD_N_LEN + \ + HDCP_2_2_K_PUB_RX_EXP_E_LEN) + +#define HDCP_2_2_DCP_LLC_SIG_LEN 384 + +#define HDCP_2_2_E_KPUB_KM_LEN 128 +#define HDCP_2_2_E_KH_KM_M_LEN (16 + 16) +#define HDCP_2_2_H_PRIME_LEN 32 +#define HDCP_2_2_E_KH_KM_LEN 16 +#define HDCP_2_2_RN_LEN 8 +#define HDCP_2_2_L_PRIME_LEN 32 +#define HDCP_2_2_E_DKEY_KS_LEN 16 +#define HDCP_2_2_RIV_LEN 8 +#define HDCP_2_2_SEQ_NUM_LEN 3 +#define HDCP_2_2_V_PRIME_HALF_LEN (HDCP_2_2_L_PRIME_LEN / 2) +#define HDCP_2_2_RECEIVER_ID_LEN DRM_HDCP_KSV_LEN +#define HDCP_2_2_MAX_DEVICE_COUNT 31 +#define HDCP_2_2_RECEIVER_IDS_MAX_LEN (HDCP_2_2_RECEIVER_ID_LEN * \ + HDCP_2_2_MAX_DEVICE_COUNT) +#define HDCP_2_2_MPRIME_LEN 32 + +/* Following Macros take a byte at a time for bit(s) masking */ +/* + * TODO: HDCP_2_2_MAX_CONTENT_STREAMS_CNT is based upon actual + * H/W MST streams capacity. + * This required to be moved out to platform specific header. + */ +#define HDCP_2_2_MAX_CONTENT_STREAMS_CNT 4 +#define HDCP_2_2_TXCAP_MASK_LEN 2 +#define HDCP_2_2_RXCAPS_LEN 3 +#define HDCP_2_2_RX_REPEATER(x) ((x) & BIT(0)) +#define HDCP_2_2_DP_HDCP_CAPABLE(x) ((x) & BIT(1)) +#define HDCP_2_2_RXINFO_LEN 2 + +/* HDCP1.x compliant device in downstream */ +#define HDCP_2_2_HDCP1_DEVICE_CONNECTED(x) ((x) & BIT(0)) + +/* HDCP2.0 Compliant repeater in downstream */ +#define HDCP_2_2_HDCP_2_0_REP_CONNECTED(x) ((x) & BIT(1)) +#define HDCP_2_2_MAX_CASCADE_EXCEEDED(x) ((x) & BIT(2)) +#define HDCP_2_2_MAX_DEVS_EXCEEDED(x) ((x) & BIT(3)) +#define HDCP_2_2_DEV_COUNT_LO(x) (((x) & (0xF << 4)) >> 4) +#define HDCP_2_2_DEV_COUNT_HI(x) ((x) & BIT(0)) +#define HDCP_2_2_DEPTH(x) (((x) & (0x7 << 1)) >> 1) + +struct hdcp2_cert_rx { + u8 receiver_id[HDCP_2_2_RECEIVER_ID_LEN]; + u8 kpub_rx[HDCP_2_2_K_PUB_RX_LEN]; + u8 reserved[2]; + u8 dcp_signature[HDCP_2_2_DCP_LLC_SIG_LEN]; +} __packed; + +struct hdcp2_streamid_type { + u8 stream_id; + u8 stream_type; +} __packed; + +/* + * The TxCaps field specified in the HDCP HDMI, DP specs + * This field is big endian as specified in the errata. + */ +struct hdcp2_tx_caps { + /* Transmitter must set this to 0x2 */ + u8 version; + + /* Reserved for HDCP and DP Spec. Read as Zero */ + u8 tx_cap_mask[HDCP_2_2_TXCAP_MASK_LEN]; +} __packed; + +/* Main structures for HDCP2.2 protocol communication */ +struct hdcp2_ake_init { + u8 msg_id; + u8 r_tx[HDCP_2_2_RTX_LEN]; + struct hdcp2_tx_caps tx_caps; +} __packed; + +struct hdcp2_ake_send_cert { + u8 msg_id; + struct hdcp2_cert_rx cert_rx; + u8 r_rx[HDCP_2_2_RRX_LEN]; + u8 rx_caps[HDCP_2_2_RXCAPS_LEN]; +} __packed; + +struct hdcp2_ake_no_stored_km { + u8 msg_id; + u8 e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN]; +} __packed; + +struct hdcp2_ake_stored_km { + u8 msg_id; + u8 e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN]; +} __packed; + +struct hdcp2_ake_send_hprime { + u8 msg_id; + u8 h_prime[HDCP_2_2_H_PRIME_LEN]; +} __packed; + +struct hdcp2_ake_send_pairing_info { + u8 msg_id; + u8 e_kh_km[HDCP_2_2_E_KH_KM_LEN]; +} __packed; + +struct hdcp2_lc_init { + u8 msg_id; + u8 r_n[HDCP_2_2_RN_LEN]; +} __packed; + +struct hdcp2_lc_send_lprime { + u8 msg_id; + u8 l_prime[HDCP_2_2_L_PRIME_LEN]; +} __packed; + +struct hdcp2_ske_send_eks { + u8 msg_id; + u8 e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN]; + u8 riv[HDCP_2_2_RIV_LEN]; +} __packed; + +struct hdcp2_rep_send_receiverid_list { + u8 msg_id; + u8 rx_info[HDCP_2_2_RXINFO_LEN]; + u8 seq_num_v[HDCP_2_2_SEQ_NUM_LEN]; + u8 v_prime[HDCP_2_2_V_PRIME_HALF_LEN]; + u8 receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN]; +} __packed; + +struct hdcp2_rep_send_ack { + u8 msg_id; + u8 v[HDCP_2_2_V_PRIME_HALF_LEN]; +} __packed; + +struct hdcp2_rep_stream_manage { + u8 msg_id; + u8 seq_num_m[HDCP_2_2_SEQ_NUM_LEN]; + __be16 k; + struct hdcp2_streamid_type streams[HDCP_2_2_MAX_CONTENT_STREAMS_CNT]; +} __packed; + +struct hdcp2_rep_stream_ready { + u8 msg_id; + u8 m_prime[HDCP_2_2_MPRIME_LEN]; +} __packed; + +/* HDCP2.2 TIMEOUTs in mSec */ +#define HDCP_2_2_CERT_TIMEOUT_MS 100 +#define HDCP_2_2_DP_CERT_READ_TIMEOUT_MS 110 +#define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS 1000 +#define HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS 200 +#define HDCP_2_2_DP_HPRIME_READ_TIMEOUT_MS 7 +#define HDCP_2_2_PAIRING_TIMEOUT_MS 200 +#define HDCP_2_2_DP_PAIRING_READ_TIMEOUT_MS 5 +#define HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS 20 +#define HDCP_2_2_DP_LPRIME_TIMEOUT_MS 16 +#define HDCP_2_2_RECVID_LIST_TIMEOUT_MS 3000 +#define HDCP_2_2_STREAM_READY_TIMEOUT_MS 100 + +/* HDMI HDCP2.2 Register Offsets */ +#define HDCP_2_2_HDMI_REG_VER_OFFSET 0x50 +#define HDCP_2_2_HDMI_REG_WR_MSG_OFFSET 0x60 +#define HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET 0x70 +#define HDCP_2_2_HDMI_REG_RD_MSG_OFFSET 0x80 +#define HDCP_2_2_HDMI_REG_DBG_OFFSET 0xC0 + +#define HDCP_2_2_HDMI_SUPPORT_MASK BIT(2) +#define HDCP_2_2_RX_CAPS_VERSION_VAL 0x02 +#define HDCP_2_2_SEQ_NUM_MAX 0xFFFFFF +#define HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN 200 + +/* Below macros take a byte at a time and mask the bit(s) */ +#define HDCP_2_2_HDMI_RXSTATUS_LEN 2 +#define HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(x) ((x) & 0x3) +#define HDCP_2_2_HDMI_RXSTATUS_READY(x) ((x) & BIT(2)) +#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) ((x) & BIT(3)) + +/* + * Helper functions to convert 24bit big endian hdcp sequence number to + * host format and back + */ +static inline +u32 drm_hdcp_be24_to_cpu(const u8 seq_num[HDCP_2_2_SEQ_NUM_LEN]) +{ + return (u32)(seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16); +} + +static inline +void drm_hdcp_cpu_to_be24(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val) +{ + seq_num[0] = val >> 16; + seq_num[1] = val >> 8; + seq_num[2] = val; +} + +#define DRM_HDCP_SRM_GEN1_MAX_BYTES (5 * 1024) +#define DRM_HDCP_1_4_SRM_ID 0x8 +#define DRM_HDCP_SRM_ID_MASK (0xF << 4) +#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3 +#define DRM_HDCP_1_4_DCP_SIG_SIZE 40 +#define DRM_HDCP_2_SRM_ID 0x9 +#define DRM_HDCP_2_INDICATOR 0x1 +#define DRM_HDCP_2_INDICATOR_MASK 0xF +#define DRM_HDCP_2_VRL_LENGTH_SIZE 3 +#define DRM_HDCP_2_DCP_SIG_SIZE 384 +#define DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ 4 +#define DRM_HDCP_2_KSV_COUNT_2_LSBITS(byte) (((byte) & 0xC0) >> 6) + +struct hdcp_srm_header { + u8 srm_id; + u8 reserved; + __be16 srm_version; + u8 srm_gen_no; +} __packed; + +/* Content Type classification for HDCP2.2 vs others */ +#define DRM_MODE_HDCP_CONTENT_TYPE0 0 +#define DRM_MODE_HDCP_CONTENT_TYPE1 1 + +#endif diff --git a/include/drm/display/drm_hdcp_helper.h b/include/drm/display/drm_hdcp_helper.h new file mode 100644 index 000000000000..8aaf87bf2735 --- /dev/null +++ b/include/drm/display/drm_hdcp_helper.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2017 Google, Inc. + * + * Authors: + * Sean Paul + */ + +#ifndef _DRM_HDCP_HELPER_H_INCLUDED_ +#define _DRM_HDCP_HELPER_H_INCLUDED_ + +#include + +struct drm_device; +struct drm_connector; + +int drm_hdcp_check_ksvs_revoked(struct drm_device *dev, u8 *ksvs, u32 ksv_count); +int drm_connector_attach_content_protection_property(struct drm_connector *connector, + bool hdcp_content_type); +void drm_hdcp_update_content_protection(struct drm_connector *connector, u64 val); + +#endif diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h deleted file mode 100644 index 0b1111e3228e..000000000000 --- a/include/drm/drm_hdcp.h +++ /dev/null @@ -1,308 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright (C) 2017 Google, Inc. - * - * Authors: - * Sean Paul - */ - -#ifndef _DRM_HDCP_H_INCLUDED_ -#define _DRM_HDCP_H_INCLUDED_ - -#include - -/* Period of hdcp checks (to ensure we're still authenticated) */ -#define DRM_HDCP_CHECK_PERIOD_MS (128 * 16) -#define DRM_HDCP2_CHECK_PERIOD_MS 500 - -/* Shared lengths/masks between HDMI/DVI/DisplayPort */ -#define DRM_HDCP_AN_LEN 8 -#define DRM_HDCP_BSTATUS_LEN 2 -#define DRM_HDCP_KSV_LEN 5 -#define DRM_HDCP_RI_LEN 2 -#define DRM_HDCP_V_PRIME_PART_LEN 4 -#define DRM_HDCP_V_PRIME_NUM_PARTS 5 -#define DRM_HDCP_NUM_DOWNSTREAM(x) (x & 0x7f) -#define DRM_HDCP_MAX_CASCADE_EXCEEDED(x) (x & BIT(3)) -#define DRM_HDCP_MAX_DEVICE_EXCEEDED(x) (x & BIT(7)) - -/* Slave address for the HDCP registers in the receiver */ -#define DRM_HDCP_DDC_ADDR 0x3A - -/* Value to use at the end of the SHA-1 bytestream used for repeaters */ -#define DRM_HDCP_SHA1_TERMINATOR 0x80 - -/* HDCP register offsets for HDMI/DVI devices */ -#define DRM_HDCP_DDC_BKSV 0x00 -#define DRM_HDCP_DDC_RI_PRIME 0x08 -#define DRM_HDCP_DDC_AKSV 0x10 -#define DRM_HDCP_DDC_AN 0x18 -#define DRM_HDCP_DDC_V_PRIME(h) (0x20 + h * 4) -#define DRM_HDCP_DDC_BCAPS 0x40 -#define DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT BIT(6) -#define DRM_HDCP_DDC_BCAPS_KSV_FIFO_READY BIT(5) -#define DRM_HDCP_DDC_BSTATUS 0x41 -#define DRM_HDCP_DDC_KSV_FIFO 0x43 - -#define DRM_HDCP_1_4_SRM_ID 0x8 -#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3 -#define DRM_HDCP_1_4_DCP_SIG_SIZE 40 - -/* Protocol message definition for HDCP2.2 specification */ -/* - * Protected content streams are classified into 2 types: - * - Type0: Can be transmitted with HDCP 1.4+ - * - Type1: Can be transmitted with HDCP 2.2+ - */ -#define HDCP_STREAM_TYPE0 0x00 -#define HDCP_STREAM_TYPE1 0x01 - -/* HDCP2.2 Msg IDs */ -#define HDCP_2_2_NULL_MSG 1 -#define HDCP_2_2_AKE_INIT 2 -#define HDCP_2_2_AKE_SEND_CERT 3 -#define HDCP_2_2_AKE_NO_STORED_KM 4 -#define HDCP_2_2_AKE_STORED_KM 5 -#define HDCP_2_2_AKE_SEND_HPRIME 7 -#define HDCP_2_2_AKE_SEND_PAIRING_INFO 8 -#define HDCP_2_2_LC_INIT 9 -#define HDCP_2_2_LC_SEND_LPRIME 10 -#define HDCP_2_2_SKE_SEND_EKS 11 -#define HDCP_2_2_REP_SEND_RECVID_LIST 12 -#define HDCP_2_2_REP_SEND_ACK 15 -#define HDCP_2_2_REP_STREAM_MANAGE 16 -#define HDCP_2_2_REP_STREAM_READY 17 - -#define HDCP_2_2_RTX_LEN 8 -#define HDCP_2_2_RRX_LEN 8 - -#define HDCP_2_2_K_PUB_RX_MOD_N_LEN 128 -#define HDCP_2_2_K_PUB_RX_EXP_E_LEN 3 -#define HDCP_2_2_K_PUB_RX_LEN (HDCP_2_2_K_PUB_RX_MOD_N_LEN + \ - HDCP_2_2_K_PUB_RX_EXP_E_LEN) - -#define HDCP_2_2_DCP_LLC_SIG_LEN 384 - -#define HDCP_2_2_E_KPUB_KM_LEN 128 -#define HDCP_2_2_E_KH_KM_M_LEN (16 + 16) -#define HDCP_2_2_H_PRIME_LEN 32 -#define HDCP_2_2_E_KH_KM_LEN 16 -#define HDCP_2_2_RN_LEN 8 -#define HDCP_2_2_L_PRIME_LEN 32 -#define HDCP_2_2_E_DKEY_KS_LEN 16 -#define HDCP_2_2_RIV_LEN 8 -#define HDCP_2_2_SEQ_NUM_LEN 3 -#define HDCP_2_2_V_PRIME_HALF_LEN (HDCP_2_2_L_PRIME_LEN / 2) -#define HDCP_2_2_RECEIVER_ID_LEN DRM_HDCP_KSV_LEN -#define HDCP_2_2_MAX_DEVICE_COUNT 31 -#define HDCP_2_2_RECEIVER_IDS_MAX_LEN (HDCP_2_2_RECEIVER_ID_LEN * \ - HDCP_2_2_MAX_DEVICE_COUNT) -#define HDCP_2_2_MPRIME_LEN 32 - -/* Following Macros take a byte at a time for bit(s) masking */ -/* - * TODO: HDCP_2_2_MAX_CONTENT_STREAMS_CNT is based upon actual - * H/W MST streams capacity. - * This required to be moved out to platform specific header. - */ -#define HDCP_2_2_MAX_CONTENT_STREAMS_CNT 4 -#define HDCP_2_2_TXCAP_MASK_LEN 2 -#define HDCP_2_2_RXCAPS_LEN 3 -#define HDCP_2_2_RX_REPEATER(x) ((x) & BIT(0)) -#define HDCP_2_2_DP_HDCP_CAPABLE(x) ((x) & BIT(1)) -#define HDCP_2_2_RXINFO_LEN 2 - -/* HDCP1.x compliant device in downstream */ -#define HDCP_2_2_HDCP1_DEVICE_CONNECTED(x) ((x) & BIT(0)) - -/* HDCP2.0 Compliant repeater in downstream */ -#define HDCP_2_2_HDCP_2_0_REP_CONNECTED(x) ((x) & BIT(1)) -#define HDCP_2_2_MAX_CASCADE_EXCEEDED(x) ((x) & BIT(2)) -#define HDCP_2_2_MAX_DEVS_EXCEEDED(x) ((x) & BIT(3)) -#define HDCP_2_2_DEV_COUNT_LO(x) (((x) & (0xF << 4)) >> 4) -#define HDCP_2_2_DEV_COUNT_HI(x) ((x) & BIT(0)) -#define HDCP_2_2_DEPTH(x) (((x) & (0x7 << 1)) >> 1) - -struct hdcp2_cert_rx { - u8 receiver_id[HDCP_2_2_RECEIVER_ID_LEN]; - u8 kpub_rx[HDCP_2_2_K_PUB_RX_LEN]; - u8 reserved[2]; - u8 dcp_signature[HDCP_2_2_DCP_LLC_SIG_LEN]; -} __packed; - -struct hdcp2_streamid_type { - u8 stream_id; - u8 stream_type; -} __packed; - -/* - * The TxCaps field specified in the HDCP HDMI, DP specs - * This field is big endian as specified in the errata. - */ -struct hdcp2_tx_caps { - /* Transmitter must set this to 0x2 */ - u8 version; - - /* Reserved for HDCP and DP Spec. Read as Zero */ - u8 tx_cap_mask[HDCP_2_2_TXCAP_MASK_LEN]; -} __packed; - -/* Main structures for HDCP2.2 protocol communication */ -struct hdcp2_ake_init { - u8 msg_id; - u8 r_tx[HDCP_2_2_RTX_LEN]; - struct hdcp2_tx_caps tx_caps; -} __packed; - -struct hdcp2_ake_send_cert { - u8 msg_id; - struct hdcp2_cert_rx cert_rx; - u8 r_rx[HDCP_2_2_RRX_LEN]; - u8 rx_caps[HDCP_2_2_RXCAPS_LEN]; -} __packed; - -struct hdcp2_ake_no_stored_km { - u8 msg_id; - u8 e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN]; -} __packed; - -struct hdcp2_ake_stored_km { - u8 msg_id; - u8 e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN]; -} __packed; - -struct hdcp2_ake_send_hprime { - u8 msg_id; - u8 h_prime[HDCP_2_2_H_PRIME_LEN]; -} __packed; - -struct hdcp2_ake_send_pairing_info { - u8 msg_id; - u8 e_kh_km[HDCP_2_2_E_KH_KM_LEN]; -} __packed; - -struct hdcp2_lc_init { - u8 msg_id; - u8 r_n[HDCP_2_2_RN_LEN]; -} __packed; - -struct hdcp2_lc_send_lprime { - u8 msg_id; - u8 l_prime[HDCP_2_2_L_PRIME_LEN]; -} __packed; - -struct hdcp2_ske_send_eks { - u8 msg_id; - u8 e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN]; - u8 riv[HDCP_2_2_RIV_LEN]; -} __packed; - -struct hdcp2_rep_send_receiverid_list { - u8 msg_id; - u8 rx_info[HDCP_2_2_RXINFO_LEN]; - u8 seq_num_v[HDCP_2_2_SEQ_NUM_LEN]; - u8 v_prime[HDCP_2_2_V_PRIME_HALF_LEN]; - u8 receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN]; -} __packed; - -struct hdcp2_rep_send_ack { - u8 msg_id; - u8 v[HDCP_2_2_V_PRIME_HALF_LEN]; -} __packed; - -struct hdcp2_rep_stream_manage { - u8 msg_id; - u8 seq_num_m[HDCP_2_2_SEQ_NUM_LEN]; - __be16 k; - struct hdcp2_streamid_type streams[HDCP_2_2_MAX_CONTENT_STREAMS_CNT]; -} __packed; - -struct hdcp2_rep_stream_ready { - u8 msg_id; - u8 m_prime[HDCP_2_2_MPRIME_LEN]; -} __packed; - -/* HDCP2.2 TIMEOUTs in mSec */ -#define HDCP_2_2_CERT_TIMEOUT_MS 100 -#define HDCP_2_2_DP_CERT_READ_TIMEOUT_MS 110 -#define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS 1000 -#define HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS 200 -#define HDCP_2_2_DP_HPRIME_READ_TIMEOUT_MS 7 -#define HDCP_2_2_PAIRING_TIMEOUT_MS 200 -#define HDCP_2_2_DP_PAIRING_READ_TIMEOUT_MS 5 -#define HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS 20 -#define HDCP_2_2_DP_LPRIME_TIMEOUT_MS 16 -#define HDCP_2_2_RECVID_LIST_TIMEOUT_MS 3000 -#define HDCP_2_2_STREAM_READY_TIMEOUT_MS 100 - -/* HDMI HDCP2.2 Register Offsets */ -#define HDCP_2_2_HDMI_REG_VER_OFFSET 0x50 -#define HDCP_2_2_HDMI_REG_WR_MSG_OFFSET 0x60 -#define HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET 0x70 -#define HDCP_2_2_HDMI_REG_RD_MSG_OFFSET 0x80 -#define HDCP_2_2_HDMI_REG_DBG_OFFSET 0xC0 - -#define HDCP_2_2_HDMI_SUPPORT_MASK BIT(2) -#define HDCP_2_2_RX_CAPS_VERSION_VAL 0x02 -#define HDCP_2_2_SEQ_NUM_MAX 0xFFFFFF -#define HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN 200 - -/* Below macros take a byte at a time and mask the bit(s) */ -#define HDCP_2_2_HDMI_RXSTATUS_LEN 2 -#define HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(x) ((x) & 0x3) -#define HDCP_2_2_HDMI_RXSTATUS_READY(x) ((x) & BIT(2)) -#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) ((x) & BIT(3)) - -/* - * Helper functions to convert 24bit big endian hdcp sequence number to - * host format and back - */ -static inline -u32 drm_hdcp_be24_to_cpu(const u8 seq_num[HDCP_2_2_SEQ_NUM_LEN]) -{ - return (u32)(seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16); -} - -static inline -void drm_hdcp_cpu_to_be24(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val) -{ - seq_num[0] = val >> 16; - seq_num[1] = val >> 8; - seq_num[2] = val; -} - -#define DRM_HDCP_SRM_GEN1_MAX_BYTES (5 * 1024) -#define DRM_HDCP_1_4_SRM_ID 0x8 -#define DRM_HDCP_SRM_ID_MASK (0xF << 4) -#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3 -#define DRM_HDCP_1_4_DCP_SIG_SIZE 40 -#define DRM_HDCP_2_SRM_ID 0x9 -#define DRM_HDCP_2_INDICATOR 0x1 -#define DRM_HDCP_2_INDICATOR_MASK 0xF -#define DRM_HDCP_2_VRL_LENGTH_SIZE 3 -#define DRM_HDCP_2_DCP_SIG_SIZE 384 -#define DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ 4 -#define DRM_HDCP_2_KSV_COUNT_2_LSBITS(byte) (((byte) & 0xC0) >> 6) - -struct hdcp_srm_header { - u8 srm_id; - u8 reserved; - __be16 srm_version; - u8 srm_gen_no; -} __packed; - -struct drm_device; -struct drm_connector; - -int drm_hdcp_check_ksvs_revoked(struct drm_device *dev, - u8 *ksvs, u32 ksv_count); -int drm_connector_attach_content_protection_property( - struct drm_connector *connector, bool hdcp_content_type); -void drm_hdcp_update_content_protection(struct drm_connector *connector, - u64 val); - -/* Content Type classification for HDCP2.2 vs others */ -#define DRM_MODE_HDCP_CONTENT_TYPE0 0 -#define DRM_MODE_HDCP_CONTENT_TYPE1 1 - -#endif diff --git a/include/drm/i915_mei_hdcp_interface.h b/include/drm/i915_mei_hdcp_interface.h index 702f613243bb..f441cbcd95a4 100644 --- a/include/drm/i915_mei_hdcp_interface.h +++ b/include/drm/i915_mei_hdcp_interface.h @@ -11,7 +11,7 @@ #include #include -#include +#include /** * enum hdcp_port_type - HDCP port implementation type defined by ME FW -- cgit v1.2.3