164e9bbddSRamalingam C // SPDX-License-Identifier: (GPL-2.0) 264e9bbddSRamalingam C /* 364e9bbddSRamalingam C * Copyright © 2019 Intel Corporation 464e9bbddSRamalingam C * 564e9bbddSRamalingam C * Mei_hdcp.c: HDCP client driver for mei bus 664e9bbddSRamalingam C * 764e9bbddSRamalingam C * Author: 864e9bbddSRamalingam C * Ramalingam C <ramalingam.c@intel.com> 964e9bbddSRamalingam C */ 1064e9bbddSRamalingam C 1164e9bbddSRamalingam C /** 1264e9bbddSRamalingam C * DOC: MEI_HDCP Client Driver 1364e9bbddSRamalingam C * 1464e9bbddSRamalingam C * This is a client driver to the mei_bus to make the HDCP2.2 services of 1564e9bbddSRamalingam C * ME FW available for the interested consumers like I915. 1664e9bbddSRamalingam C * 1764e9bbddSRamalingam C * This module will act as a translation layer between HDCP protocol 1864e9bbddSRamalingam C * implementor(I915) and ME FW by translating HDCP2.2 authentication 1964e9bbddSRamalingam C * messages to ME FW command payloads and vice versa. 2064e9bbddSRamalingam C */ 2164e9bbddSRamalingam C 2264e9bbddSRamalingam C #include <linux/module.h> 2364e9bbddSRamalingam C #include <linux/slab.h> 2464e9bbddSRamalingam C #include <linux/uuid.h> 2564e9bbddSRamalingam C #include <linux/mei_cl_bus.h> 26a37fb1e4SRamalingam C #include <drm/drm_connector.h> 27a37fb1e4SRamalingam C #include <drm/i915_component.h> 28a37fb1e4SRamalingam C #include <drm/i915_mei_hdcp_interface.h> 29a37fb1e4SRamalingam C 30a37fb1e4SRamalingam C #include "mei_hdcp.h" 31a37fb1e4SRamalingam C 32a37fb1e4SRamalingam C static inline u8 mei_get_ddi_index(enum port port) 33a37fb1e4SRamalingam C { 34a37fb1e4SRamalingam C switch (port) { 35a37fb1e4SRamalingam C case PORT_A: 36a37fb1e4SRamalingam C return MEI_DDI_A; 37a37fb1e4SRamalingam C case PORT_B ... PORT_F: 38a37fb1e4SRamalingam C return (u8)port; 39a37fb1e4SRamalingam C default: 40a37fb1e4SRamalingam C return MEI_DDI_INVALID_PORT; 41a37fb1e4SRamalingam C } 42a37fb1e4SRamalingam C } 43a37fb1e4SRamalingam C 44a37fb1e4SRamalingam C /** 45a37fb1e4SRamalingam C * mei_hdcp_initiate_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW 46a37fb1e4SRamalingam C * @dev: device corresponding to the mei_cl_device 47a37fb1e4SRamalingam C * @data: Intel HW specific hdcp data 48a37fb1e4SRamalingam C * @ake_data: AKE_Init msg output. 49a37fb1e4SRamalingam C * 50a37fb1e4SRamalingam C * Return: 0 on Success, <0 on Failure. 51a37fb1e4SRamalingam C */ 52a37fb1e4SRamalingam C static int 53a37fb1e4SRamalingam C mei_hdcp_initiate_session(struct device *dev, struct hdcp_port_data *data, 54a37fb1e4SRamalingam C struct hdcp2_ake_init *ake_data) 55a37fb1e4SRamalingam C { 56a37fb1e4SRamalingam C struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } }; 57a37fb1e4SRamalingam C struct wired_cmd_initiate_hdcp2_session_out 58a37fb1e4SRamalingam C session_init_out = { { 0 } }; 59a37fb1e4SRamalingam C struct mei_cl_device *cldev; 60a37fb1e4SRamalingam C ssize_t byte; 61a37fb1e4SRamalingam C 62a37fb1e4SRamalingam C if (!dev || !data || !ake_data) 63a37fb1e4SRamalingam C return -EINVAL; 64a37fb1e4SRamalingam C 65a37fb1e4SRamalingam C cldev = to_mei_cl_device(dev); 66a37fb1e4SRamalingam C 67a37fb1e4SRamalingam C session_init_in.header.api_version = HDCP_API_VERSION; 68a37fb1e4SRamalingam C session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION; 69a37fb1e4SRamalingam C session_init_in.header.status = ME_HDCP_STATUS_SUCCESS; 70a37fb1e4SRamalingam C session_init_in.header.buffer_len = 71a37fb1e4SRamalingam C WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN; 72a37fb1e4SRamalingam C 73a37fb1e4SRamalingam C session_init_in.port.integrated_port_type = data->port_type; 74a37fb1e4SRamalingam C session_init_in.port.physical_port = mei_get_ddi_index(data->port); 75a37fb1e4SRamalingam C session_init_in.protocol = data->protocol; 76a37fb1e4SRamalingam C 77a37fb1e4SRamalingam C byte = mei_cldev_send(cldev, (u8 *)&session_init_in, 78a37fb1e4SRamalingam C sizeof(session_init_in)); 79a37fb1e4SRamalingam C if (byte < 0) { 80a37fb1e4SRamalingam C dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); 81a37fb1e4SRamalingam C return byte; 82a37fb1e4SRamalingam C } 83a37fb1e4SRamalingam C 84a37fb1e4SRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&session_init_out, 85a37fb1e4SRamalingam C sizeof(session_init_out)); 86a37fb1e4SRamalingam C if (byte < 0) { 87a37fb1e4SRamalingam C dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); 88a37fb1e4SRamalingam C return byte; 89a37fb1e4SRamalingam C } 90a37fb1e4SRamalingam C 91a37fb1e4SRamalingam C if (session_init_out.header.status != ME_HDCP_STATUS_SUCCESS) { 92a37fb1e4SRamalingam C dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n", 93a37fb1e4SRamalingam C WIRED_INITIATE_HDCP2_SESSION, 94a37fb1e4SRamalingam C session_init_out.header.status); 95a37fb1e4SRamalingam C return -EIO; 96a37fb1e4SRamalingam C } 97a37fb1e4SRamalingam C 98a37fb1e4SRamalingam C ake_data->msg_id = HDCP_2_2_AKE_INIT; 99a37fb1e4SRamalingam C ake_data->tx_caps = session_init_out.tx_caps; 100a37fb1e4SRamalingam C memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN); 101a37fb1e4SRamalingam C 102a37fb1e4SRamalingam C return 0; 103a37fb1e4SRamalingam C } 104a37fb1e4SRamalingam C 10539b71c2bSRamalingam C /** 10639b71c2bSRamalingam C * mei_hdcp_verify_receiver_cert_prepare_km() - Verify the Receiver Certificate 10739b71c2bSRamalingam C * AKE_Send_Cert and prepare AKE_Stored_Km/AKE_No_Stored_Km 10839b71c2bSRamalingam C * @dev: device corresponding to the mei_cl_device 10939b71c2bSRamalingam C * @data: Intel HW specific hdcp data 11039b71c2bSRamalingam C * @rx_cert: AKE_Send_Cert for verification 11139b71c2bSRamalingam C * @km_stored: Pairing status flag output 11239b71c2bSRamalingam C * @ek_pub_km: AKE_Stored_Km/AKE_No_Stored_Km output msg 11339b71c2bSRamalingam C * @msg_sz : size of AKE_XXXXX_Km output msg 11439b71c2bSRamalingam C * 11539b71c2bSRamalingam C * Return: 0 on Success, <0 on Failure 11639b71c2bSRamalingam C */ 11739b71c2bSRamalingam C static int 11839b71c2bSRamalingam C mei_hdcp_verify_receiver_cert_prepare_km(struct device *dev, 11939b71c2bSRamalingam C struct hdcp_port_data *data, 12039b71c2bSRamalingam C struct hdcp2_ake_send_cert *rx_cert, 12139b71c2bSRamalingam C bool *km_stored, 12239b71c2bSRamalingam C struct hdcp2_ake_no_stored_km 12339b71c2bSRamalingam C *ek_pub_km, 12439b71c2bSRamalingam C size_t *msg_sz) 12539b71c2bSRamalingam C { 12639b71c2bSRamalingam C struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } }; 12739b71c2bSRamalingam C struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } }; 12839b71c2bSRamalingam C struct mei_cl_device *cldev; 12939b71c2bSRamalingam C ssize_t byte; 13039b71c2bSRamalingam C 13139b71c2bSRamalingam C if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz) 13239b71c2bSRamalingam C return -EINVAL; 13339b71c2bSRamalingam C 13439b71c2bSRamalingam C cldev = to_mei_cl_device(dev); 13539b71c2bSRamalingam C 13639b71c2bSRamalingam C verify_rxcert_in.header.api_version = HDCP_API_VERSION; 13739b71c2bSRamalingam C verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT; 13839b71c2bSRamalingam C verify_rxcert_in.header.status = ME_HDCP_STATUS_SUCCESS; 13939b71c2bSRamalingam C verify_rxcert_in.header.buffer_len = 14039b71c2bSRamalingam C WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN; 14139b71c2bSRamalingam C 14239b71c2bSRamalingam C verify_rxcert_in.port.integrated_port_type = data->port_type; 14339b71c2bSRamalingam C verify_rxcert_in.port.physical_port = mei_get_ddi_index(data->port); 14439b71c2bSRamalingam C 14539b71c2bSRamalingam C verify_rxcert_in.cert_rx = rx_cert->cert_rx; 14639b71c2bSRamalingam C memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN); 14739b71c2bSRamalingam C memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN); 14839b71c2bSRamalingam C 14939b71c2bSRamalingam C byte = mei_cldev_send(cldev, (u8 *)&verify_rxcert_in, 15039b71c2bSRamalingam C sizeof(verify_rxcert_in)); 15139b71c2bSRamalingam C if (byte < 0) { 15239b71c2bSRamalingam C dev_dbg(dev, "mei_cldev_send failed: %zd\n", byte); 15339b71c2bSRamalingam C return byte; 15439b71c2bSRamalingam C } 15539b71c2bSRamalingam C 15639b71c2bSRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&verify_rxcert_out, 15739b71c2bSRamalingam C sizeof(verify_rxcert_out)); 15839b71c2bSRamalingam C if (byte < 0) { 15939b71c2bSRamalingam C dev_dbg(dev, "mei_cldev_recv failed: %zd\n", byte); 16039b71c2bSRamalingam C return byte; 16139b71c2bSRamalingam C } 16239b71c2bSRamalingam C 16339b71c2bSRamalingam C if (verify_rxcert_out.header.status != ME_HDCP_STATUS_SUCCESS) { 16439b71c2bSRamalingam C dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n", 16539b71c2bSRamalingam C WIRED_VERIFY_RECEIVER_CERT, 16639b71c2bSRamalingam C verify_rxcert_out.header.status); 16739b71c2bSRamalingam C return -EIO; 16839b71c2bSRamalingam C } 16939b71c2bSRamalingam C 17039b71c2bSRamalingam C *km_stored = !!verify_rxcert_out.km_stored; 17139b71c2bSRamalingam C if (verify_rxcert_out.km_stored) { 17239b71c2bSRamalingam C ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM; 17339b71c2bSRamalingam C *msg_sz = sizeof(struct hdcp2_ake_stored_km); 17439b71c2bSRamalingam C } else { 17539b71c2bSRamalingam C ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM; 17639b71c2bSRamalingam C *msg_sz = sizeof(struct hdcp2_ake_no_stored_km); 17739b71c2bSRamalingam C } 17839b71c2bSRamalingam C 17939b71c2bSRamalingam C memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff, 18039b71c2bSRamalingam C sizeof(verify_rxcert_out.ekm_buff)); 18139b71c2bSRamalingam C 18239b71c2bSRamalingam C return 0; 18339b71c2bSRamalingam C } 18439b71c2bSRamalingam C 185a7dcbed2SRamalingam C /** 186a7dcbed2SRamalingam C * mei_hdcp_verify_hprime() - Verify AKE_Send_H_prime at ME FW. 187a7dcbed2SRamalingam C * @dev: device corresponding to the mei_cl_device 188a7dcbed2SRamalingam C * @data: Intel HW specific hdcp data 189a7dcbed2SRamalingam C * @rx_hprime: AKE_Send_H_prime msg for ME FW verification 190a7dcbed2SRamalingam C * 191a7dcbed2SRamalingam C * Return: 0 on Success, <0 on Failure 192a7dcbed2SRamalingam C */ 193a7dcbed2SRamalingam C static int 194a7dcbed2SRamalingam C mei_hdcp_verify_hprime(struct device *dev, struct hdcp_port_data *data, 195a7dcbed2SRamalingam C struct hdcp2_ake_send_hprime *rx_hprime) 196a7dcbed2SRamalingam C { 197a7dcbed2SRamalingam C struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } }; 198a7dcbed2SRamalingam C struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } }; 199a7dcbed2SRamalingam C struct mei_cl_device *cldev; 200a7dcbed2SRamalingam C ssize_t byte; 201a7dcbed2SRamalingam C 202a7dcbed2SRamalingam C if (!dev || !data || !rx_hprime) 203a7dcbed2SRamalingam C return -EINVAL; 204a7dcbed2SRamalingam C 205a7dcbed2SRamalingam C cldev = to_mei_cl_device(dev); 206a7dcbed2SRamalingam C 207a7dcbed2SRamalingam C send_hprime_in.header.api_version = HDCP_API_VERSION; 208a7dcbed2SRamalingam C send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME; 209a7dcbed2SRamalingam C send_hprime_in.header.status = ME_HDCP_STATUS_SUCCESS; 210a7dcbed2SRamalingam C send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN; 211a7dcbed2SRamalingam C 212a7dcbed2SRamalingam C send_hprime_in.port.integrated_port_type = data->port_type; 213a7dcbed2SRamalingam C send_hprime_in.port.physical_port = mei_get_ddi_index(data->port); 214a7dcbed2SRamalingam C 215a7dcbed2SRamalingam C memcpy(send_hprime_in.h_prime, rx_hprime->h_prime, 216a7dcbed2SRamalingam C HDCP_2_2_H_PRIME_LEN); 217a7dcbed2SRamalingam C 218a7dcbed2SRamalingam C byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in, 219a7dcbed2SRamalingam C sizeof(send_hprime_in)); 220a7dcbed2SRamalingam C if (byte < 0) { 221a7dcbed2SRamalingam C dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); 222a7dcbed2SRamalingam C return byte; 223a7dcbed2SRamalingam C } 224a7dcbed2SRamalingam C 225a7dcbed2SRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&send_hprime_out, 226a7dcbed2SRamalingam C sizeof(send_hprime_out)); 227a7dcbed2SRamalingam C if (byte < 0) { 228a7dcbed2SRamalingam C dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); 229a7dcbed2SRamalingam C return byte; 230a7dcbed2SRamalingam C } 231a7dcbed2SRamalingam C 232a7dcbed2SRamalingam C if (send_hprime_out.header.status != ME_HDCP_STATUS_SUCCESS) { 233a7dcbed2SRamalingam C dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n", 234a7dcbed2SRamalingam C WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status); 235a7dcbed2SRamalingam C return -EIO; 236a7dcbed2SRamalingam C } 237a7dcbed2SRamalingam C 238a7dcbed2SRamalingam C return 0; 239a7dcbed2SRamalingam C } 240a7dcbed2SRamalingam C 2416a1a00a3SRamalingam C /** 2426a1a00a3SRamalingam C * mei_hdcp_store_pairing_info() - Store pairing info received at ME FW 2436a1a00a3SRamalingam C * @dev: device corresponding to the mei_cl_device 2446a1a00a3SRamalingam C * @data: Intel HW specific hdcp data 2456a1a00a3SRamalingam C * @pairing_info: AKE_Send_Pairing_Info msg input to ME FW 2466a1a00a3SRamalingam C * 2476a1a00a3SRamalingam C * Return: 0 on Success, <0 on Failure 2486a1a00a3SRamalingam C */ 2496a1a00a3SRamalingam C static int 2506a1a00a3SRamalingam C mei_hdcp_store_pairing_info(struct device *dev, struct hdcp_port_data *data, 2516a1a00a3SRamalingam C struct hdcp2_ake_send_pairing_info *pairing_info) 2526a1a00a3SRamalingam C { 2536a1a00a3SRamalingam C struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } }; 2546a1a00a3SRamalingam C struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } }; 2556a1a00a3SRamalingam C struct mei_cl_device *cldev; 2566a1a00a3SRamalingam C ssize_t byte; 2576a1a00a3SRamalingam C 2586a1a00a3SRamalingam C if (!dev || !data || !pairing_info) 2596a1a00a3SRamalingam C return -EINVAL; 2606a1a00a3SRamalingam C 2616a1a00a3SRamalingam C cldev = to_mei_cl_device(dev); 2626a1a00a3SRamalingam C 2636a1a00a3SRamalingam C pairing_info_in.header.api_version = HDCP_API_VERSION; 2646a1a00a3SRamalingam C pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO; 2656a1a00a3SRamalingam C pairing_info_in.header.status = ME_HDCP_STATUS_SUCCESS; 2666a1a00a3SRamalingam C pairing_info_in.header.buffer_len = 2676a1a00a3SRamalingam C WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN; 2686a1a00a3SRamalingam C 2696a1a00a3SRamalingam C pairing_info_in.port.integrated_port_type = data->port_type; 2706a1a00a3SRamalingam C pairing_info_in.port.physical_port = mei_get_ddi_index(data->port); 2716a1a00a3SRamalingam C 2726a1a00a3SRamalingam C memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km, 2736a1a00a3SRamalingam C HDCP_2_2_E_KH_KM_LEN); 2746a1a00a3SRamalingam C 2756a1a00a3SRamalingam C byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in, 2766a1a00a3SRamalingam C sizeof(pairing_info_in)); 2776a1a00a3SRamalingam C if (byte < 0) { 2786a1a00a3SRamalingam C dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); 2796a1a00a3SRamalingam C return byte; 2806a1a00a3SRamalingam C } 2816a1a00a3SRamalingam C 2826a1a00a3SRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&pairing_info_out, 2836a1a00a3SRamalingam C sizeof(pairing_info_out)); 2846a1a00a3SRamalingam C if (byte < 0) { 2856a1a00a3SRamalingam C dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); 2866a1a00a3SRamalingam C return byte; 2876a1a00a3SRamalingam C } 2886a1a00a3SRamalingam C 2896a1a00a3SRamalingam C if (pairing_info_out.header.status != ME_HDCP_STATUS_SUCCESS) { 2906a1a00a3SRamalingam C dev_dbg(dev, "ME cmd 0x%08X failed. Status: 0x%X\n", 2916a1a00a3SRamalingam C WIRED_AKE_SEND_PAIRING_INFO, 2926a1a00a3SRamalingam C pairing_info_out.header.status); 2936a1a00a3SRamalingam C return -EIO; 2946a1a00a3SRamalingam C } 2956a1a00a3SRamalingam C 2966a1a00a3SRamalingam C return 0; 2976a1a00a3SRamalingam C } 2986a1a00a3SRamalingam C 299682932f3SRamalingam C /** 300682932f3SRamalingam C * mei_hdcp_initiate_locality_check() - Prepare LC_Init 301682932f3SRamalingam C * @dev: device corresponding to the mei_cl_device 302682932f3SRamalingam C * @data: Intel HW specific hdcp data 303682932f3SRamalingam C * @lc_init_data: LC_Init msg output 304682932f3SRamalingam C * 305682932f3SRamalingam C * Return: 0 on Success, <0 on Failure 306682932f3SRamalingam C */ 307682932f3SRamalingam C static int 308682932f3SRamalingam C mei_hdcp_initiate_locality_check(struct device *dev, 309682932f3SRamalingam C struct hdcp_port_data *data, 310682932f3SRamalingam C struct hdcp2_lc_init *lc_init_data) 311682932f3SRamalingam C { 312682932f3SRamalingam C struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } }; 313682932f3SRamalingam C struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } }; 314682932f3SRamalingam C struct mei_cl_device *cldev; 315682932f3SRamalingam C ssize_t byte; 316682932f3SRamalingam C 317682932f3SRamalingam C if (!dev || !data || !lc_init_data) 318682932f3SRamalingam C return -EINVAL; 319682932f3SRamalingam C 320682932f3SRamalingam C cldev = to_mei_cl_device(dev); 321682932f3SRamalingam C 322682932f3SRamalingam C lc_init_in.header.api_version = HDCP_API_VERSION; 323682932f3SRamalingam C lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK; 324682932f3SRamalingam C lc_init_in.header.status = ME_HDCP_STATUS_SUCCESS; 325682932f3SRamalingam C lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN; 326682932f3SRamalingam C 327682932f3SRamalingam C lc_init_in.port.integrated_port_type = data->port_type; 328682932f3SRamalingam C lc_init_in.port.physical_port = mei_get_ddi_index(data->port); 329682932f3SRamalingam C 330682932f3SRamalingam C byte = mei_cldev_send(cldev, (u8 *)&lc_init_in, sizeof(lc_init_in)); 331682932f3SRamalingam C if (byte < 0) { 332682932f3SRamalingam C dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); 333682932f3SRamalingam C return byte; 334682932f3SRamalingam C } 335682932f3SRamalingam C 336682932f3SRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&lc_init_out, sizeof(lc_init_out)); 337682932f3SRamalingam C if (byte < 0) { 338682932f3SRamalingam C dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); 339682932f3SRamalingam C return byte; 340682932f3SRamalingam C } 341682932f3SRamalingam C 342682932f3SRamalingam C if (lc_init_out.header.status != ME_HDCP_STATUS_SUCCESS) { 343682932f3SRamalingam C dev_dbg(dev, "ME cmd 0x%08X Failed. status: 0x%X\n", 344682932f3SRamalingam C WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status); 345682932f3SRamalingam C return -EIO; 346682932f3SRamalingam C } 347682932f3SRamalingam C 348682932f3SRamalingam C lc_init_data->msg_id = HDCP_2_2_LC_INIT; 349682932f3SRamalingam C memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN); 350682932f3SRamalingam C 351682932f3SRamalingam C return 0; 352682932f3SRamalingam C } 353682932f3SRamalingam C 35445479b67SRamalingam C /** 35545479b67SRamalingam C * mei_hdcp_verify_lprime() - Verify lprime. 35645479b67SRamalingam C * @dev: device corresponding to the mei_cl_device 35745479b67SRamalingam C * @data: Intel HW specific hdcp data 35845479b67SRamalingam C * @rx_lprime: LC_Send_L_prime msg for ME FW verification 35945479b67SRamalingam C * 36045479b67SRamalingam C * Return: 0 on Success, <0 on Failure 36145479b67SRamalingam C */ 36245479b67SRamalingam C static int 36345479b67SRamalingam C mei_hdcp_verify_lprime(struct device *dev, struct hdcp_port_data *data, 36445479b67SRamalingam C struct hdcp2_lc_send_lprime *rx_lprime) 36545479b67SRamalingam C { 36645479b67SRamalingam C struct wired_cmd_validate_locality_in verify_lprime_in = { { 0 } }; 36745479b67SRamalingam C struct wired_cmd_validate_locality_out verify_lprime_out = { { 0 } }; 36845479b67SRamalingam C struct mei_cl_device *cldev; 36945479b67SRamalingam C ssize_t byte; 37045479b67SRamalingam C 37145479b67SRamalingam C if (!dev || !data || !rx_lprime) 37245479b67SRamalingam C return -EINVAL; 37345479b67SRamalingam C 37445479b67SRamalingam C cldev = to_mei_cl_device(dev); 37545479b67SRamalingam C 37645479b67SRamalingam C verify_lprime_in.header.api_version = HDCP_API_VERSION; 37745479b67SRamalingam C verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY; 37845479b67SRamalingam C verify_lprime_in.header.status = ME_HDCP_STATUS_SUCCESS; 37945479b67SRamalingam C verify_lprime_in.header.buffer_len = 38045479b67SRamalingam C WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN; 38145479b67SRamalingam C 38245479b67SRamalingam C verify_lprime_in.port.integrated_port_type = data->port_type; 38345479b67SRamalingam C verify_lprime_in.port.physical_port = mei_get_ddi_index(data->port); 38445479b67SRamalingam C 38545479b67SRamalingam C memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime, 38645479b67SRamalingam C HDCP_2_2_L_PRIME_LEN); 38745479b67SRamalingam C 38845479b67SRamalingam C byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in, 38945479b67SRamalingam C sizeof(verify_lprime_in)); 39045479b67SRamalingam C if (byte < 0) { 39145479b67SRamalingam C dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); 39245479b67SRamalingam C return byte; 39345479b67SRamalingam C } 39445479b67SRamalingam C 39545479b67SRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&verify_lprime_out, 39645479b67SRamalingam C sizeof(verify_lprime_out)); 39745479b67SRamalingam C if (byte < 0) { 39845479b67SRamalingam C dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); 39945479b67SRamalingam C return byte; 40045479b67SRamalingam C } 40145479b67SRamalingam C 40245479b67SRamalingam C if (verify_lprime_out.header.status != ME_HDCP_STATUS_SUCCESS) { 40345479b67SRamalingam C dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n", 40445479b67SRamalingam C WIRED_VALIDATE_LOCALITY, 40545479b67SRamalingam C verify_lprime_out.header.status); 40645479b67SRamalingam C return -EIO; 40745479b67SRamalingam C } 40845479b67SRamalingam C 40945479b67SRamalingam C return 0; 41045479b67SRamalingam C } 41145479b67SRamalingam C 412*b491264fSRamalingam C /** 413*b491264fSRamalingam C * mei_hdcp_get_session_key() - Prepare SKE_Send_Eks. 414*b491264fSRamalingam C * @dev: device corresponding to the mei_cl_device 415*b491264fSRamalingam C * @data: Intel HW specific hdcp data 416*b491264fSRamalingam C * @ske_data: SKE_Send_Eks msg output from ME FW. 417*b491264fSRamalingam C * 418*b491264fSRamalingam C * Return: 0 on Success, <0 on Failure 419*b491264fSRamalingam C */ 420*b491264fSRamalingam C static int mei_hdcp_get_session_key(struct device *dev, 421*b491264fSRamalingam C struct hdcp_port_data *data, 422*b491264fSRamalingam C struct hdcp2_ske_send_eks *ske_data) 423*b491264fSRamalingam C { 424*b491264fSRamalingam C struct wired_cmd_get_session_key_in get_skey_in = { { 0 } }; 425*b491264fSRamalingam C struct wired_cmd_get_session_key_out get_skey_out = { { 0 } }; 426*b491264fSRamalingam C struct mei_cl_device *cldev; 427*b491264fSRamalingam C ssize_t byte; 428*b491264fSRamalingam C 429*b491264fSRamalingam C if (!dev || !data || !ske_data) 430*b491264fSRamalingam C return -EINVAL; 431*b491264fSRamalingam C 432*b491264fSRamalingam C cldev = to_mei_cl_device(dev); 433*b491264fSRamalingam C 434*b491264fSRamalingam C get_skey_in.header.api_version = HDCP_API_VERSION; 435*b491264fSRamalingam C get_skey_in.header.command_id = WIRED_GET_SESSION_KEY; 436*b491264fSRamalingam C get_skey_in.header.status = ME_HDCP_STATUS_SUCCESS; 437*b491264fSRamalingam C get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN; 438*b491264fSRamalingam C 439*b491264fSRamalingam C get_skey_in.port.integrated_port_type = data->port_type; 440*b491264fSRamalingam C get_skey_in.port.physical_port = mei_get_ddi_index(data->port); 441*b491264fSRamalingam C 442*b491264fSRamalingam C byte = mei_cldev_send(cldev, (u8 *)&get_skey_in, sizeof(get_skey_in)); 443*b491264fSRamalingam C if (byte < 0) { 444*b491264fSRamalingam C dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); 445*b491264fSRamalingam C return byte; 446*b491264fSRamalingam C } 447*b491264fSRamalingam C 448*b491264fSRamalingam C byte = mei_cldev_recv(cldev, (u8 *)&get_skey_out, sizeof(get_skey_out)); 449*b491264fSRamalingam C 450*b491264fSRamalingam C if (byte < 0) { 451*b491264fSRamalingam C dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); 452*b491264fSRamalingam C return byte; 453*b491264fSRamalingam C } 454*b491264fSRamalingam C 455*b491264fSRamalingam C if (get_skey_out.header.status != ME_HDCP_STATUS_SUCCESS) { 456*b491264fSRamalingam C dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n", 457*b491264fSRamalingam C WIRED_GET_SESSION_KEY, get_skey_out.header.status); 458*b491264fSRamalingam C return -EIO; 459*b491264fSRamalingam C } 460*b491264fSRamalingam C 461*b491264fSRamalingam C ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS; 462*b491264fSRamalingam C memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks, 463*b491264fSRamalingam C HDCP_2_2_E_DKEY_KS_LEN); 464*b491264fSRamalingam C memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN); 465*b491264fSRamalingam C 466*b491264fSRamalingam C return 0; 467*b491264fSRamalingam C } 468*b491264fSRamalingam C 469a37fb1e4SRamalingam C static const __attribute__((unused)) 470a37fb1e4SRamalingam C struct i915_hdcp_component_ops mei_hdcp_ops = { 471a37fb1e4SRamalingam C .owner = THIS_MODULE, 472a37fb1e4SRamalingam C .initiate_hdcp2_session = mei_hdcp_initiate_session, 47339b71c2bSRamalingam C .verify_receiver_cert_prepare_km = 47439b71c2bSRamalingam C mei_hdcp_verify_receiver_cert_prepare_km, 475a7dcbed2SRamalingam C .verify_hprime = mei_hdcp_verify_hprime, 4766a1a00a3SRamalingam C .store_pairing_info = mei_hdcp_store_pairing_info, 477682932f3SRamalingam C .initiate_locality_check = mei_hdcp_initiate_locality_check, 47845479b67SRamalingam C .verify_lprime = mei_hdcp_verify_lprime, 479*b491264fSRamalingam C .get_session_key = mei_hdcp_get_session_key, 480a37fb1e4SRamalingam C .repeater_check_flow_prepare_ack = NULL, 481a37fb1e4SRamalingam C .verify_mprime = NULL, 482a37fb1e4SRamalingam C .enable_hdcp_authentication = NULL, 483a37fb1e4SRamalingam C .close_hdcp_session = NULL, 484a37fb1e4SRamalingam C }; 48564e9bbddSRamalingam C 48664e9bbddSRamalingam C static int mei_hdcp_probe(struct mei_cl_device *cldev, 48764e9bbddSRamalingam C const struct mei_cl_device_id *id) 48864e9bbddSRamalingam C { 48964e9bbddSRamalingam C int ret; 49064e9bbddSRamalingam C 49164e9bbddSRamalingam C ret = mei_cldev_enable(cldev); 49264e9bbddSRamalingam C if (ret < 0) 49364e9bbddSRamalingam C dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret); 49464e9bbddSRamalingam C 49564e9bbddSRamalingam C return ret; 49664e9bbddSRamalingam C } 49764e9bbddSRamalingam C 49864e9bbddSRamalingam C static int mei_hdcp_remove(struct mei_cl_device *cldev) 49964e9bbddSRamalingam C { 50064e9bbddSRamalingam C return mei_cldev_disable(cldev); 50164e9bbddSRamalingam C } 50264e9bbddSRamalingam C 50364e9bbddSRamalingam C #define MEI_UUID_HDCP GUID_INIT(0xB638AB7E, 0x94E2, 0x4EA2, 0xA5, \ 50464e9bbddSRamalingam C 0x52, 0xD1, 0xC5, 0x4B, 0x62, 0x7F, 0x04) 50564e9bbddSRamalingam C 50664e9bbddSRamalingam C static struct mei_cl_device_id mei_hdcp_tbl[] = { 50764e9bbddSRamalingam C { .uuid = MEI_UUID_HDCP, .version = MEI_CL_VERSION_ANY }, 50864e9bbddSRamalingam C { } 50964e9bbddSRamalingam C }; 51064e9bbddSRamalingam C MODULE_DEVICE_TABLE(mei, mei_hdcp_tbl); 51164e9bbddSRamalingam C 51264e9bbddSRamalingam C static struct mei_cl_driver mei_hdcp_driver = { 51364e9bbddSRamalingam C .id_table = mei_hdcp_tbl, 51464e9bbddSRamalingam C .name = KBUILD_MODNAME, 51564e9bbddSRamalingam C .probe = mei_hdcp_probe, 51664e9bbddSRamalingam C .remove = mei_hdcp_remove, 51764e9bbddSRamalingam C }; 51864e9bbddSRamalingam C 51964e9bbddSRamalingam C module_mei_cl_driver(mei_hdcp_driver); 52064e9bbddSRamalingam C 52164e9bbddSRamalingam C MODULE_AUTHOR("Intel Corporation"); 52264e9bbddSRamalingam C MODULE_LICENSE("GPL"); 52364e9bbddSRamalingam C MODULE_DESCRIPTION("MEI HDCP"); 524