From patchwork Fri Nov 24 08:53:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "mac.shen" X-Patchwork-Id: 13467261 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 622C1C61DF4 for ; Fri, 24 Nov 2023 08:55:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:CC :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=c9ybIlrw7/5GijwEC6L0lalSvQgLCH6qxsIH8Y7f0AI=; b=KPAEewrBv83Bwa 99+ntagEPXN3Y1DWsgwYR8Jp4xnbV/+vDo1PUAxcZ7aHuZMXfYIeRgoCKGTIseLyy1AgnRYXdQQia YVQ78fCA55aSYNdlQDie6UMrckQpGC6Dkoe7QE+IolTWxbQ0eIy/MlUlwFEJ3Ok7zhWPS7rC2hgMF JOLEqJjXWFpyalmOve4t40mEwQ7lJ1v4nvWULblt5GrHhmxS11TvzXyhttpFxkofAFC7D9q2Llt+e kNkFLthQT1DX+d5ftPFVNRwhD+QImoL4btFY8IEVlS4ZYduohmvjZ2ro8tJ91CbPekf9W+usKik1X 9dO6GmO5A0714W/HNW8A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1r6Rx4-006aQe-0D; Fri, 24 Nov 2023 08:54:18 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1r6Rwx-006aPN-2c; Fri, 24 Nov 2023 08:54:16 +0000 X-UUID: ff02e2188aa611ee9b7791016c24628a-20231124 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:CC:To:From; bh=wDb7QOniywV6HjHzP9YpA989cdkc2ofjSnAMzlzZR64=; b=uOw73C1BSVDriNEcXBjujs5gWAnabvpARhaMLyxPd11z5Ds/16bGI4FmHzwYiy/5OWUSOCwz7cZmJ982cC27EvJQqStnG8/WgIR8oefmhJnxakHNkvY2DAwZDfAVzmOsf9XJdcqf5IlvS+OUnXo2tSQBGzwAI62X8HQY39eag8Q=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.33,REQID:e1068ced-ca60-4f12-98a8-9ba0ac2988a7,IP:0,U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:364b77b,CLOUDID:b1a7c495-10ce-4e4b-85c2-c9b5229ff92b,B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:0,File:nil,Bulk:nil,QS:nil,BEC:nil,COL:1,OSI:0,OSA:0,AV:0,LES:1,SPR:NO, DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 2,OSH|NGT X-CID-BAS: 2,OSH|NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: ff02e2188aa611ee9b7791016c24628a-20231124 Received: from mtkmbs11n1.mediatek.inc [(172.21.101.185)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 107601965; Fri, 24 Nov 2023 01:53:54 -0700 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs11n2.mediatek.inc (172.21.101.187) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 24 Nov 2023 16:53:17 +0800 Received: from mszsdhlt06.gcn.mediatek.inc (10.16.6.206) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 24 Nov 2023 16:53:16 +0800 From: mac.shen To: , , , , , , CC: , , , , , Subject: [PATCH] drm/mediatek/dp: Add the HDCP feature for DisplayPort Date: Fri, 24 Nov 2023 16:53:46 +0800 Message-ID: <20231124085346.26602-1-mac.shen@mediatek.com> X-Mailer: git-send-email 2.40.1 MIME-Version: 1.0 X-MTK: N X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add tee client application, HDCP 1.x and 2.x authentication for DisplayPort to support the HDCP feature. Signed-off-by: mac.shen --- drivers/gpu/drm/mediatek/Makefile | 7 +- drivers/gpu/drm/mediatek/ca/tci.h | 143 +++ drivers/gpu/drm/mediatek/ca/tlDPHdcpCMD.h | 36 + drivers/gpu/drm/mediatek/ca/tlcDpHdcp.c | 638 +++++++++++++ drivers/gpu/drm/mediatek/ca/tlcDpHdcp.h | 305 +++++++ drivers/gpu/drm/mediatek/mtk_dp.c | 159 +++- drivers/gpu/drm/mediatek/mtk_dp.h | 17 + drivers/gpu/drm/mediatek/mtk_dp_hdcp.h | 154 ++++ drivers/gpu/drm/mediatek/mtk_dp_hdcp1x.c | 646 +++++++++++++ drivers/gpu/drm/mediatek/mtk_dp_hdcp1x.h | 55 ++ drivers/gpu/drm/mediatek/mtk_dp_hdcp2.c | 1008 +++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_dp_hdcp2.h | 75 ++ drivers/gpu/drm/mediatek/mtk_dp_reg.h | 6 +- 13 files changed, 3233 insertions(+), 16 deletions(-) create mode 100644 drivers/gpu/drm/mediatek/ca/tci.h create mode 100644 drivers/gpu/drm/mediatek/ca/tlDPHdcpCMD.h create mode 100644 drivers/gpu/drm/mediatek/ca/tlcDpHdcp.c create mode 100644 drivers/gpu/drm/mediatek/ca/tlcDpHdcp.h create mode 100644 drivers/gpu/drm/mediatek/mtk_dp.h create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_hdcp.h create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_hdcp1x.c create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_hdcp1x.h create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_hdcp2.c create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_hdcp2.h diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index d4d193f60271..6839c96221e3 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -26,4 +26,9 @@ mediatek-drm-hdmi-objs := mtk_cec.o \ obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o -obj-$(CONFIG_DRM_MEDIATEK_DP) += mtk_dp.o +mtk-dp-objs := mtk_dp_hdcp1x.o \ + mtk_dp_hdcp2.o \ + ca/tlcDpHdcp.o \ + mtk_dp.o + +obj-$(CONFIG_DRM_MEDIATEK_DP) += mtk-dp.o diff --git a/drivers/gpu/drm/mediatek/ca/tci.h b/drivers/gpu/drm/mediatek/ca/tci.h new file mode 100644 index 000000000000..527f77d9308d --- /dev/null +++ b/drivers/gpu/drm/mediatek/ca/tci.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019-2023 MediaTek Inc. + */ + +#ifndef _TCI_H_ +#define _TCI_H_ + +#define RET_COMPARE_PASS 0 +#define RET_COMPARE_FAIL 1 +#define RET_NEW_DEVICE 2 +#define RET_STORED_DEVICE 3 + +#define AN_LEN 8 +#define AKSV_LEN 5 +#define BKSV_LEN 5 +#define CERT_LEN 522 +#define EKM_LEN 16 +#define M_LEN 16 +#define ENC_KM_LEN 128 +#define RXX_LEN 8 +#define CAPS_LEN 3 +#define RN_LEN 8 +#define RIV_LEN 8 + +#define TYPE_HDCP_PARAM_AN 10 +#define TYPE_HDCP_PARAM_RST_1 11 +#define TYPE_HDCP_PARAM_RST_2 12 +#define TYPE_HDCP_ENABLE_ENCRYPT 13 +#define TYPE_HDCP_DISABLE_ENCRYPT 14 + +#define TYPE_HDCP13_KEY 20 +#define TYPE_HDCP22_KEY 21 + +#define TCI_LENGTH sizeof(struct tci_t) + +struct cryptokeys_t { + u8 type; + u32 len; + u32 key; +}; + +struct cmd_hdcp_init_for_verion_t { + u32 version; + bool need_load_key; +}; + +struct cmd_hdcp_write_val_t { + u8 type; + u8 len; + u32 val; +}; + +struct cmd_hdcp_calculate_lm_t { + u8 bksv[BKSV_LEN]; +}; + +struct cmd_hdcp_get_aksv_t { + u8 aksv[AKSV_LEN]; +}; + +struct cmd_hdcp_sha1_t { + u32 message_len; + u32 message_addr; +}; + +struct cmd_hdcp_ake_certificate_t { + u8 certification[CERT_LEN]; + bool stored; + u8 m[M_LEN]; + u8 ekm[EKM_LEN]; +}; + +struct cmd_hdcp_ake_paring_t { + u8 ekm[EKM_LEN]; +}; + +struct cmd_hdcp_enc_km_t { + u8 enc_km[ENC_KM_LEN]; +}; + +struct cmd_hdcp_ake_h_prime_t { + u8 rtx[RXX_LEN]; + u8 rrx[RXX_LEN]; + u8 rx_caps[CAPS_LEN]; + u8 tx_caps[CAPS_LEN]; + u32 rx_h_len; + u32 rx_h; +}; + +struct cmd_hdcp_lc_l_prime_t { + u8 rn[RN_LEN]; + u32 rx_l_len; + u32 rx_l; +}; + +struct cmd_hdcp_ske_eks_t { + u8 riv[RIV_LEN]; + u32 eks_len; + u32 eks; +}; + +struct cmd_hdcp_compare_t { + u32 rx_val_len; + u32 rx_val; + u32 param_len; + u32 param; + u32 out_len; + u32 out; +}; + +union tci_cmd_body_t { + /* Init with special HDCP version */ + struct cmd_hdcp_init_for_verion_t cmd_hdcp_init_for_verion; + /* Write uint32 data to hw */ + struct cmd_hdcp_write_val_t cmd_hdcp_write_val; + /* Get aksv */ + struct cmd_hdcp_get_aksv_t cmd_hdcp_get_aksv; + /* Calculate r0 */ + struct cmd_hdcp_calculate_lm_t cmd_hdcp_calculate_lm; + /* Generate signature for certificate */ + struct cmd_hdcp_ake_certificate_t cmd_hdcp_ake_certificate; + /* To store ekm */ + struct cmd_hdcp_ake_paring_t cmd_hdcp_ake_paring; + /* Encrypt km for V2.2 */ + struct cmd_hdcp_enc_km_t cmd_hdcp_enc_km; + /* Compute H prime */ + struct cmd_hdcp_ake_h_prime_t cmd_hdcp_ake_h_prime; + /* Compute L prime */ + struct cmd_hdcp_lc_l_prime_t cmd_hdcp_lc_l_prime; + /* Compute eks */ + struct cmd_hdcp_ske_eks_t cmd_hdcp_ske_eks; + /* Compare */ + struct cmd_hdcp_compare_t cmd_hdcp_compare; +} __packed; + +struct tci_t { + u32 command_id; + u32 return_code; + union tci_cmd_body_t cmd_body; +}; + +#endif /* _TCI_H_ */ diff --git a/drivers/gpu/drm/mediatek/ca/tlDPHdcpCMD.h b/drivers/gpu/drm/mediatek/ca/tlDPHdcpCMD.h new file mode 100644 index 000000000000..5687aec9bdd9 --- /dev/null +++ b/drivers/gpu/drm/mediatek/ca/tlDPHdcpCMD.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019-2023 MediaTek Inc. + */ + +#ifndef _TLDPHDCP_CMD_H_ +#define _TLDPHDCP_CMD_H_ + +#define CMD_DEVICE_ADDED 1 +#define CMD_DEVICE_REMOVE 2 +#define CMD_WRITE_VAL 3 +#define CMD_DEVICE_CLEAN 4 +#define CMD_ENABLE_ENCRYPT 5 + +/* V1.3 */ +#define CMD_CALCULATE_LM 11 +#define CMD_COMPARE_R0 12 +#define CMD_COMPARE_V1 13 +#define CMD_GET_AKSV 14 + +/* V2.2 */ +#define CMD_AKE_CERTIFICATE 20 +#define CMD_ENC_KM 21 +#define CMD_AKE_H_PRIME 22 +#define CMD_AKE_PARING 23 +#define CMD_LC_L_PRIME 24 +#define CMD_COMPARE_L 25 +#define CMD_SKE_CAL_EKS 26 + +#define CMD_COMPARE_V2 27 +#define CMD_COMPARE_M 28 + +/* Need remove in furture */ +#define CMD_LOAD_KEY 50 + +#endif /* _TLDPHDCP_CMD_H_ */ diff --git a/drivers/gpu/drm/mediatek/ca/tlcDpHdcp.c b/drivers/gpu/drm/mediatek/ca/tlcDpHdcp.c new file mode 100644 index 000000000000..2979d38ee230 --- /dev/null +++ b/drivers/gpu/drm/mediatek/ca/tlcDpHdcp.c @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019-2023 MediaTek Inc. + */ + +#include +#include +#include +#include "tlcDpHdcp.h" + +#define AN_LEN 8 +#define AKSV_LEN 5 +#define DEFAULT_WRITE_VAL_LEN 1 +#define DEFAULT_WRITE_VAL 0 + +/* + * TA_FTPM_UUID: 99975014-3c7c-54ea-8487-a80d215ea92c + * + * Randomly generated, and must correspond to the GUID on the TA side. + * Defined here in the reference implementation: + * https://github.com/microsoft/ms-tpm-20-ref/blob/master/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h#L42 + */ +static const uuid_t dp_ta_uuid = + UUID_INIT(0x99975014, 0x3c7c, 0x54ea, + 0x84, 0x87, 0xa8, 0x0d, 0x21, 0x5e, 0xa9, 0x2c); + +/** + * dp_tee_op_send() - send dp commands through the TEE shared memory. + * @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h + * @buf: the buffer to send. + * @len: the number of bytes to send. + * + * Return: + * In case of success, returns 0. + * On failure, -errno + */ +static int dp_tee_op_send(struct dp_tee_private *dp_tee_priv, u8 *buf, size_t len, u32 cmd_id) +{ + int rc; + u8 *temp_buf; + struct tee_ioctl_invoke_arg transceive_args; + struct tee_param command_params[4]; + struct tee_shm *shm = dp_tee_priv->shm; + + if (len > MAX_COMMAND_SIZE) { + TLCERR("%s: len=%zd exceeds MAX_COMMAND_SIZE supported by dp TA\n", __func__, len); + return -EIO; + } + + memset(&transceive_args, 0, sizeof(transceive_args)); + memset(command_params, 0, sizeof(command_params)); + dp_tee_priv->resp_len = 0; + + /* Invoke FTPM_OPTEE_TA_SUBMIT_COMMAND function of dp TA */ + transceive_args = (struct tee_ioctl_invoke_arg) { + .func = cmd_id, + .session = dp_tee_priv->session, + .num_params = 4, + }; + + /* Fill FTPM_OPTEE_TA_SUBMIT_COMMAND parameters */ + command_params[0] = (struct tee_param) { + .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT, + .u.memref = { + .shm = shm, + .size = len, + .shm_offs = 0, + }, + }; + + temp_buf = tee_shm_get_va(shm, 0); + if (IS_ERR(temp_buf)) { + TLCERR("%s: tee_shm_get_va failed for transmit\n", __func__); + return PTR_ERR(temp_buf); + } + + memcpy(temp_buf, buf, len); + + command_params[1] = (struct tee_param) { + .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT, + .u.memref = { + .shm = shm, + .size = MAX_RESPONSE_SIZE, + .shm_offs = MAX_COMMAND_SIZE, + }, + }; + + rc = tee_client_invoke_func(dp_tee_priv->ctx, &transceive_args, + command_params); + if (rc < 0 || transceive_args.ret != 0) { + TLCERR("%s: invoke error: 0x%x\n", __func__, transceive_args.ret); + return (rc < 0) ? rc : transceive_args.ret; + } + + temp_buf = tee_shm_get_va(shm, command_params[1].u.memref.shm_offs); + if (IS_ERR(temp_buf)) { + TLCERR("%s: tee_shm_get_va failed for receive\n", __func__); + return PTR_ERR(temp_buf); + } + + /* Sanity checks look good, cache the response */ + memcpy(dp_tee_priv->resp_buf, temp_buf, MAX_RESPONSE_SIZE / 2); + dp_tee_priv->resp_len = MAX_RESPONSE_SIZE / 2; + + return 0; +} + +/* + * Check whether this driver supports the dp TA in the TEE instance + * represented by the params (ver/data) to this function. + */ +static int dp_tee_match(struct tee_ioctl_version_data *ver, const void *data) +{ + /* + * Currently this driver only support GP Complaint OPTEE based dp TA + */ + if (ver->impl_id == TEE_IMPL_ID_OPTEE && ver->gen_caps & TEE_GEN_CAP_GP) + return 1; + else + return 0; +} + +int tee_add_device(struct mtk_hdcp_info *hdcp_info, u32 version) +{ + int rc; + struct dp_tee_private *dp_tee_priv = NULL; + struct tee_ioctl_open_session_arg sess_arg; + struct tci_t *tci; + + if (hdcp_info->g_init) + tee_remove_device(hdcp_info); + + dp_tee_priv = kzalloc(sizeof(*dp_tee_priv), GFP_KERNEL); + if (!dp_tee_priv) { + kfree(dp_tee_priv); + TLCERR("%s: tee_alloc_memory failed\n", __func__); + return -ENOMEM; + } + hdcp_info->g_dp_tee_priv = dp_tee_priv; + + /* Open context with TEE driver */ + dp_tee_priv->ctx = tee_client_open_context(NULL, dp_tee_match, NULL, NULL); + if (IS_ERR(dp_tee_priv->ctx)) { + if (PTR_ERR(dp_tee_priv->ctx) == -ENOENT) { + kfree(dp_tee_priv); + return -EPROBE_DEFER; + } + kfree(dp_tee_priv); + TLCERR("%s: tee_client_open_context failed\n", __func__); + return PTR_ERR(dp_tee_priv->ctx); + } + + /* Open a session with dp TA */ + memset(&sess_arg, 0, sizeof(sess_arg)); + export_uuid(sess_arg.uuid, &dp_ta_uuid); + sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC; + sess_arg.num_params = 0; + + rc = tee_client_open_session(dp_tee_priv->ctx, &sess_arg, NULL); + if (rc < 0 || sess_arg.ret != 0) { + kfree(dp_tee_priv); + TLCERR("tee_client_open_session failed, err=%x\n", sess_arg.ret); + rc = -EINVAL; + goto out_tee_session; + } + dp_tee_priv->session = sess_arg.session; + + /* Allocate dynamic shared memory with dp TA */ + dp_tee_priv->shm = tee_shm_alloc_kernel_buf(dp_tee_priv->ctx, MAX_COMMAND_SIZE + + MAX_RESPONSE_SIZE); + if (IS_ERR(dp_tee_priv->shm)) { + kfree(dp_tee_priv); + TLCERR("%s: tee_shm_alloc_kernel_buf failed\n", __func__); + rc = -ENOMEM; + goto out_shm_alloc; + } + TLCINFO("Register 8k share memory successfully, (%p)", + dp_tee_priv->shm->kaddr); + + /* Copy parameter for add new device */ + tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_DEVICE_ADDED; + tci->cmd_body.cmd_hdcp_init_for_verion.version = version; + tci->cmd_body.cmd_hdcp_init_for_verion.need_load_key = true; + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_DEVICE_ADDED); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + tee_remove_device(hdcp_info); + return rc; + } + + hdcp_info->g_init = true; + + return rc; + +out_shm_alloc: + tee_client_close_session(dp_tee_priv->ctx, dp_tee_priv->session); +out_tee_session: + tee_client_close_context(dp_tee_priv->ctx); + + return rc; +} + +void tee_remove_device(struct mtk_hdcp_info *hdcp_info) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + if (!hdcp_info->g_init) + return; + + hdcp_info->g_init = false; + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_DEVICE_REMOVE; + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_DEVICE_REMOVE); + if (rc != 0) + TLCERR("tee_op_send failed, error=%x\n", rc); + + /* Free the shared memory pool */ + tee_shm_free(dp_tee_priv->shm); + + /* Close the existing session with fTPM TA */ + tee_client_close_session(dp_tee_priv->ctx, dp_tee_priv->session); + + /* Close the context with TEE driver */ + tee_client_close_context(dp_tee_priv->ctx); + + /* Free the memory */ + kfree(dp_tee_priv); +} + +int tee_clear_paring(struct mtk_hdcp_info *hdcp_info) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_DEVICE_CLEAN; + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_DEVICE_CLEAN); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +int tee_hdcp1x_set_tx_an(struct mtk_hdcp_info *hdcp_info, u8 *an_code) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_WRITE_VAL; + tci->cmd_body.cmd_hdcp_write_val.len = AN_LEN; + tci->cmd_body.cmd_hdcp_write_val.type = TYPE_HDCP_PARAM_AN; + memcpy(share_buffer + TCI_LENGTH, an_code, AN_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + AN_LEN, CMD_WRITE_VAL); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +int tee_hdcp_enable_encrypt(struct mtk_hdcp_info *hdcp_info, bool enable, u8 version) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_ENABLE_ENCRYPT; + if (enable) + tci->cmd_body.cmd_hdcp_write_val.type = TYPE_HDCP_ENABLE_ENCRYPT; + else + tci->cmd_body.cmd_hdcp_write_val.type = TYPE_HDCP_DISABLE_ENCRYPT; + + /* Set HDCP version supportted by device */ + tci->cmd_body.cmd_hdcp_write_val.len = 1; + memset(share_buffer + TCI_LENGTH, version, 1); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + 1, CMD_ENABLE_ENCRYPT); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +int tee_hdcp1x_soft_rst(struct mtk_hdcp_info *hdcp_info) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_WRITE_VAL; + tci->cmd_body.cmd_hdcp_write_val.type = TYPE_HDCP_PARAM_RST_1; + /* No need input. Set default value 0 for check */ + tci->cmd_body.cmd_hdcp_write_val.len = DEFAULT_WRITE_VAL_LEN; + memset(share_buffer + TCI_LENGTH, DEFAULT_WRITE_VAL, DEFAULT_WRITE_VAL_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + + DEFAULT_WRITE_VAL_LEN, CMD_WRITE_VAL); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +int tee_hdcp2_soft_rst(struct mtk_hdcp_info *hdcp_info) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_WRITE_VAL; + tci->cmd_body.cmd_hdcp_write_val.type = TYPE_HDCP_PARAM_RST_2; + /* No need input. Set default value 0 for check */ + tci->cmd_body.cmd_hdcp_write_val.len = + DEFAULT_WRITE_VAL_LEN; + memset(share_buffer + TCI_LENGTH, DEFAULT_WRITE_VAL, DEFAULT_WRITE_VAL_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + + DEFAULT_WRITE_VAL_LEN, CMD_WRITE_VAL); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +/** V1.X **/ +int tee_get_aksv(struct mtk_hdcp_info *hdcp_info, u8 *aksv) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_GET_AKSV; + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_GET_AKSV); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + tci = (struct tci_t *)dp_tee_priv->resp_buf; + memcpy(aksv, tci->cmd_body.cmd_hdcp_get_aksv.aksv, AKSV_LEN); + + return rc; +} + +int tee_calculate_lm(struct mtk_hdcp_info *hdcp_info, u8 *bksv) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_CALCULATE_LM; + memcpy(tci->cmd_body.cmd_hdcp_calculate_lm.bksv, bksv, BKSV_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_CALCULATE_LM); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +int tee_compare_r0(struct mtk_hdcp_info *hdcp_info, u8 *r0, u32 len) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_COMPARE_R0; + tci->cmd_body.cmd_hdcp_compare.rx_val_len = len; + memcpy(share_buffer + TCI_LENGTH, r0, len); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + len, CMD_COMPARE_R0); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +int tee_hdcp1x_compute_compare_v(struct mtk_hdcp_info *hdcp_info, + u8 *crypto_param, u32 param_len, u8 *rx_v) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_COMPARE_V1; + tci->cmd_body.cmd_hdcp_compare.rx_val_len = 20; + tci->cmd_body.cmd_hdcp_compare.param_len = param_len; + memcpy(share_buffer + TCI_LENGTH, rx_v, 20); + memcpy(share_buffer + TCI_LENGTH + 20, crypto_param, param_len); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + param_len + 20, CMD_COMPARE_V1); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + return rc; +} + +/** V2.X **/ +int tee_ake_certificate(struct mtk_hdcp_info *hdcp_info, + u8 *certificate, bool *stored, u8 *out_m, u8 *out_ekm) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_AKE_CERTIFICATE; + memcpy(tci->cmd_body.cmd_hdcp_ake_certificate.certification, + certificate, CERT_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_AKE_CERTIFICATE); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + TLCINFO("verify signature: result %d", rc); + tci = (struct tci_t *)dp_tee_priv->resp_buf; + *stored = tci->cmd_body.cmd_hdcp_ake_certificate.stored; + memcpy(out_m, tci->cmd_body.cmd_hdcp_ake_certificate.m, M_LEN); + memcpy(out_ekm, tci->cmd_body.cmd_hdcp_ake_certificate.ekm, EKM_LEN); + + return rc; +} + +int tee_enc_rsaes_oaep(struct mtk_hdcp_info *hdcp_info, u8 *ekm) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_ENC_KM; + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_ENC_KM); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + tci = (struct tci_t *)dp_tee_priv->resp_buf; + memcpy(ekm, tci->cmd_body.cmd_hdcp_enc_km.enc_km, ENC_KM_LEN); + + return rc; +} + +int tee_ake_h_prime(struct mtk_hdcp_info *hdcp_info, + u8 *rtx, u8 *rrx, u8 *rx_caps, u8 *tx_caps, u8 *rx_h, u32 rx_h_len) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_AKE_H_PRIME; + tci->cmd_body.cmd_hdcp_ake_h_prime.rx_h_len = rx_h_len; + + memcpy(tci->cmd_body.cmd_hdcp_ake_h_prime.rtx, rtx, RXX_LEN); + memcpy(tci->cmd_body.cmd_hdcp_ake_h_prime.rrx, rrx, RXX_LEN); + memcpy(tci->cmd_body.cmd_hdcp_ake_h_prime.rx_caps, rx_caps, CAPS_LEN); + memcpy(tci->cmd_body.cmd_hdcp_ake_h_prime.tx_caps, tx_caps, CAPS_LEN); + memcpy(share_buffer + TCI_LENGTH, rx_h, rx_h_len); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + rx_h_len, CMD_AKE_H_PRIME); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + tci = (struct tci_t *)dp_tee_priv->resp_buf; + return tci->return_code; +} + +int tee_ake_paring(struct mtk_hdcp_info *hdcp_info, u8 *rx_ekm) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_AKE_PARING; + memcpy(tci->cmd_body.cmd_hdcp_ake_paring.ekm, rx_ekm, EKM_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH, CMD_AKE_PARING); + if (rc != 0) + TLCERR("tee_op_send failed, error=%x\n", rc); + + return rc; +} + +int tee_lc_l_prime(struct mtk_hdcp_info *hdcp_info, u8 *rn, u8 *rx_l, u32 len) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_LC_L_PRIME; + memcpy(tci->cmd_body.cmd_hdcp_lc_l_prime.rn, rn, RN_LEN); + tci->cmd_body.cmd_hdcp_lc_l_prime.rx_l_len = len; + memcpy(share_buffer + TCI_LENGTH, rx_l, len); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + len, CMD_LC_L_PRIME); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + tci = (struct tci_t *)dp_tee_priv->resp_buf; + return tci->return_code; +} + +int tee_ske_enc_ks(struct mtk_hdcp_info *hdcp_info, u8 *riv, u8 *eks) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_SKE_CAL_EKS; + memcpy(tci->cmd_body.cmd_hdcp_ske_eks.riv, riv, RIV_LEN); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + 16, CMD_SKE_CAL_EKS); + if (rc != 0) + TLCERR("tee_op_send failed, error=%x\n", rc); + + share_buffer = (u8 *)dp_tee_priv->resp_buf; + memcpy(eks, share_buffer + TCI_LENGTH, 16); + + return rc; +} + +int tee_hdcp2_compute_compare_v(struct mtk_hdcp_info *hdcp_info, + u8 *crypto_param, u32 param_len, u8 *rx_v, u8 *tx_v) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_COMPARE_V2; + tci->cmd_body.cmd_hdcp_compare.rx_val_len = 16; + tci->cmd_body.cmd_hdcp_compare.param_len = param_len; + memcpy(share_buffer + TCI_LENGTH, rx_v, 16); + memcpy(share_buffer + TCI_LENGTH + 16, crypto_param, param_len); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + param_len + 16, CMD_COMPARE_V2); + if (rc != 0) { + TLCERR("tee_op_send failed, error=%x\n", rc); + return rc; + } + + share_buffer = (u8 *)dp_tee_priv->resp_buf; + memcpy(tx_v, share_buffer + TCI_LENGTH, 16); + + return rc; +} + +int tee_hdcp2_compute_compare_m(struct mtk_hdcp_info *hdcp_info, + u8 *crypto_param, u32 param_len, u8 *rx_m) +{ + int rc; + struct dp_tee_private *dp_tee_priv = hdcp_info->g_dp_tee_priv; + struct tci_t *tci = (struct tci_t *)dp_tee_priv->shm->kaddr; + u8 *share_buffer = (u8 *)dp_tee_priv->shm->kaddr; + + /* Copy parameters */ + memset(tci, 0, TCI_LENGTH); + tci->command_id = CMD_COMPARE_M; + tci->cmd_body.cmd_hdcp_compare.rx_val_len = 32; + tci->cmd_body.cmd_hdcp_compare.param_len = param_len; + memcpy(share_buffer + TCI_LENGTH, rx_m, 32); + memcpy(share_buffer + TCI_LENGTH + 32, crypto_param, param_len); + + rc = dp_tee_op_send(dp_tee_priv, (u8 *)tci, TCI_LENGTH + param_len + 32, CMD_COMPARE_M); + if (rc != 0) + TLCERR("tee_op_send failed, error=%x\n", rc); + + return rc; +} + diff --git a/drivers/gpu/drm/mediatek/ca/tlcDpHdcp.h b/drivers/gpu/drm/mediatek/ca/tlcDpHdcp.h new file mode 100644 index 000000000000..72e713dd96bf --- /dev/null +++ b/drivers/gpu/drm/mediatek/ca/tlcDpHdcp.h @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019-2023 MediaTek Inc. + */ + +#ifndef _TLCDPHDCP_H_ +#define _TLCDPHDCP_H_ + +#include +#include +#include +#include "tci.h" +#include "tlDPHdcpCMD.h" +#include "mtk_dp_hdcp.h" + +#define TLCINFO(string, args...) pr_info("[TLC_HDCP]info: "string, ##args) +#define TLCERR(string, args...) pr_info("[TLC_HDCP]line:%d,err:%s:"string,\ + __LINE__, __func__, ##args) + +#define RET_SUCCESS 0 + +/** + * hdcp version definitions + */ +#define HDCP_NONE 0x0 // No HDCP supported, no secure data path +#define HDCP_V1 0x1 // HDCP version 1.0 +#define HDCP_V2 0x2 // HDCP version 2.0 Type 1 +#define HDCP_V2_1 0x3 // HDCP version 2.1 Type 1 +#define HDCP_V2_2 0x4 // HDCP version 2.2 Type 1 +#define HDCP_V2_3 0x5 // HDCP version 2.3 Type 1 + +/* Local display only(content required version use only) */ +#define HDCP_LOCAL_DISPLAY_ONLY 0xf +#define HDCP_NO_DIGITAL_OUTPUT 0xff // No digital output +#define HDCP_DEFAULT HDCP_NO_DIGITAL_OUTPUT // Default value + +#define HDCP_VERSION_1X 1 +#define HDCP_VERSION_2X 2 + +/* max. buffer size supported by dp */ +#define MAX_COMMAND_SIZE 4096 +#define MAX_RESPONSE_SIZE 4096 + +struct dp_header { + __be16 tag; + __be32 length; + union { + __be32 ordinal; + __be32 return_code; + }; +} __packed; + +/** + * struct dp_tee_private - fTPM's private data + * @session: dp TA session identifier. + * @resp_len: cached response buffer length. + * @resp_buf: cached response buffer. + * @ctx: TEE context handler. + * @shm: Memory pool shared with fTPM TA in TEE. + */ +struct dp_tee_private { + u32 session; + size_t resp_len; + u8 resp_buf[MAX_RESPONSE_SIZE]; + struct tee_context *ctx; + struct tee_shm *shm; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + *Description: + * A device connect and do some initializations. + * + *Input: + * version: HDCP version + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_add_device(struct mtk_hdcp_info *hdcp_info, u32 version); + +/* + *Description: + * Device disconnect. + * + *Returns: + * N/A + */ +void tee_remove_device(struct mtk_hdcp_info *hdcp_info); + +/* + *Description: + * Clearing paring info. + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_clear_paring(struct mtk_hdcp_info *hdcp_info); + +/* + *Description: + * Calculate Km base on Bksv and write it to HW. + * + *Input: + * bksv[5] input + * + *Returns: + * TEEC_SUCCESS success + */ +int tee_calculate_lm(struct mtk_hdcp_info *hdcp_info, u8 *bksv); + +/* + *Description: + * Get Aksv from TEE. + * + *Output: + * aksv[5] + * + *Returns: + * TEEC_SUCCESS success + */ +int tee_get_aksv(struct mtk_hdcp_info *hdcp_info, u8 *aksv); + +/* + *Description: + * Get r0 from HW and compare to rx_r0. + * + *Parameters: + * r0[len] input + * + *Returns: + * TEEC_SUCCESS success + */ +int tee_compare_r0(struct mtk_hdcp_info *hdcp_info, u8 *r0, u32 len); + +/* + *Description: + * Compute and compare v value. + * + *Input: + * crypto_param[param_len] params used to calculate + * rx_v[20] v value from rx + * + *Returns: + * RET_COMPARE_PASS verify pass + */ +int tee_hdcp1x_compute_compare_v(struct mtk_hdcp_info *hdcp_info, + u8 *crypto_param, u32 param_len, u8 *rx_v); + +/* + *Description: + * Write An to HW. + * + *Input: + * an_code[8] + * + *Returns: + * TEEC_SUCCESS success + */ +int tee_hdcp1x_set_tx_an(struct mtk_hdcp_info *hdcp_info, u8 *an_code); + +/* + *Description: + * Write RST to HW. + * + *Returns: + * TEEC_SUCCESS success + */ +int tee_hdcp1x_soft_rst(struct mtk_hdcp_info *hdcp_info); +int tee_hdcp2_soft_rst(struct mtk_hdcp_info *hdcp_info); + +/* + *Description: + * Set enable or disable to HW. + * + *Returns: + * TEEC_SUCCESS success + */ +int tee_hdcp_enable_encrypt(struct mtk_hdcp_info *hdcp_info, bool enable, u8 version); + +/* + *Description: + * AKE cetificate verify. + * + *Input: + * certificate[522]: cert use to calculate + *output: + * stored: whether be stored before + * out_m[16] + * out_ekm[16] + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_ake_certificate(struct mtk_hdcp_info *hdcp_info, + u8 *certificate, bool *stored, u8 *out_m, u8 *out_ekm); + +/* + *Description: + * Encrypt km. + * + *Output: + * ekm[128]: encrypted km + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_enc_rsaes_oaep(struct mtk_hdcp_info *hdcp_info, u8 *ekm); + +/* + *Description: + * Calculate h prime and compare to rx_h + * + *Input: + * rtx[8] + * rrx[8] + * rx_caps[3] + * tx_caps[3] + * rx_h[rx_h_len] + * + *Returns: + * RET_COMPARE_PASS: compare pass + */ +int tee_ake_h_prime(struct mtk_hdcp_info *hdcp_info, + u8 *rtx, u8 *rrx, u8 *rx_caps, u8 *tx_caps, u8 *rx_h, u32 rx_h_len); + +/* + *Description: + * Store paring info. + * + *Input: + * rx_ekm[16] + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_ake_paring(struct mtk_hdcp_info *hdcp_info, u8 *rx_ekm); + +/* + *Description: + * Calculate l prime and compare. + * + *Input: + * rn[8] + * rx_l[len] + * + *Returns: + * RET_COMPARE_PASS compare pass + */ +int tee_lc_l_prime(struct mtk_hdcp_info *hdcp_info, u8 *rn, u8 *rx_l, u32 len); + +/* + *Description: + * Encrypt ks + * Write contentkey and riv to hw + * + *Input: + * riv[8] + *Output: + * eks[16] + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_ske_enc_ks(struct mtk_hdcp_info *hdcp_info, u8 *riv, u8 *eks); + +/* + *Description: + * Calculate and compare v prime for repeater. + * + *Input: + * crypto_param[param_len] params used to calculate + * rx_v[16] v value from rx + *Output: + * tx_v[16] + * + *Returns: + * TEEC_SUCCESS success* + */ +int tee_hdcp2_compute_compare_v(struct mtk_hdcp_info *hdcp_info, + u8 *crypto_param, u32 param_len, u8 *rx_v, u8 *tx_v); + +/* + *Description: + * Calculate and compare m prime for repeater. + * + *Input: + * crypto_param[param_len] params used to calculate + * rx_m[32] m value from rx + * + *Returns: + * RET_COMPARE_PASS verify pass + */ +int tee_hdcp2_compute_compare_m(struct mtk_hdcp_info *hdcp_info, + u8 *crypto_param, u32 param_len, u8 *rx_m); + +#ifdef __cplusplus +} +#endif + +#endif /* _TLCDPHDCP_H_ */ diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index e4c16ba9902d..a5fa682f2b3c 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2019-2022 MediaTek Inc. + * Copyright (c) 2019-2023 MediaTek Inc. * Copyright (c) 2022 BayLibre */ @@ -33,7 +33,12 @@ #include #include