brintos

brintos / linux-shallow public Read only

0
0
Text · 25.8 KiB · 323f106 Raw
890 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright © 2019 Intel Corporation4 *5 * mei_hdcp.c: HDCP client driver for mei bus6 *7 * Author:8 * Ramalingam C <ramalingam.c@intel.com>9 */10 11/**12 * DOC: MEI_HDCP Client Driver13 *14 * The mei_hdcp driver acts as a translation layer between HDCP 2.215 * protocol  implementer (I915) and ME FW by translating HDCP2.216 * negotiation messages to ME FW command payloads and vice versa.17 */18 19#include <linux/module.h>20#include <linux/pci.h>21#include <linux/slab.h>22#include <linux/mei.h>23#include <linux/mei_cl_bus.h>24#include <linux/component.h>25#include <drm/drm_connector.h>26#include <drm/intel/i915_component.h>27#include <drm/intel/i915_hdcp_interface.h>28 29#include "mei_hdcp.h"30 31/**32 * mei_hdcp_initiate_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW33 * @dev: device corresponding to the mei_cl_device34 * @data: Intel HW specific hdcp data35 * @ake_data: AKE_Init msg output.36 *37 * Return:  0 on Success, <0 on Failure.38 */39static int40mei_hdcp_initiate_session(struct device *dev, struct hdcp_port_data *data,41			  struct hdcp2_ake_init *ake_data)42{43	struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };44	struct wired_cmd_initiate_hdcp2_session_out45						session_init_out = { { 0 } };46	struct mei_cl_device *cldev;47	ssize_t byte;48 49	if (!dev || !data || !ake_data)50		return -EINVAL;51 52	cldev = to_mei_cl_device(dev);53 54	session_init_in.header.api_version = HDCP_API_VERSION;55	session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;56	session_init_in.header.status = FW_HDCP_STATUS_SUCCESS;57	session_init_in.header.buffer_len =58				WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;59 60	session_init_in.port.integrated_port_type = data->port_type;61	session_init_in.port.physical_port = (u8)data->hdcp_ddi;62	session_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;63	session_init_in.protocol = data->protocol;64 65	byte = mei_cldev_send(cldev, (u8 *)&session_init_in,66			      sizeof(session_init_in));67	if (byte < 0) {68		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);69		return byte;70	}71 72	byte = mei_cldev_recv(cldev, (u8 *)&session_init_out,73			      sizeof(session_init_out));74	if (byte < 0) {75		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);76		return byte;77	}78 79	if (session_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {80		dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",81			WIRED_INITIATE_HDCP2_SESSION,82			session_init_out.header.status);83		return -EIO;84	}85 86	ake_data->msg_id = HDCP_2_2_AKE_INIT;87	ake_data->tx_caps = session_init_out.tx_caps;88	memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN);89 90	return 0;91}92 93/**94 * mei_hdcp_verify_receiver_cert_prepare_km() - Verify the Receiver Certificate95 * AKE_Send_Cert and prepare AKE_Stored_Km/AKE_No_Stored_Km96 * @dev: device corresponding to the mei_cl_device97 * @data: Intel HW specific hdcp data98 * @rx_cert: AKE_Send_Cert for verification99 * @km_stored: Pairing status flag output100 * @ek_pub_km: AKE_Stored_Km/AKE_No_Stored_Km output msg101 * @msg_sz : size of AKE_XXXXX_Km output msg102 *103 * Return: 0 on Success, <0 on Failure104 */105static int106mei_hdcp_verify_receiver_cert_prepare_km(struct device *dev,107					 struct hdcp_port_data *data,108					 struct hdcp2_ake_send_cert *rx_cert,109					 bool *km_stored,110					 struct hdcp2_ake_no_stored_km111								*ek_pub_km,112					 size_t *msg_sz)113{114	struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };115	struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };116	struct mei_cl_device *cldev;117	ssize_t byte;118 119	if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)120		return -EINVAL;121 122	cldev = to_mei_cl_device(dev);123 124	verify_rxcert_in.header.api_version = HDCP_API_VERSION;125	verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;126	verify_rxcert_in.header.status = FW_HDCP_STATUS_SUCCESS;127	verify_rxcert_in.header.buffer_len =128				WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;129 130	verify_rxcert_in.port.integrated_port_type = data->port_type;131	verify_rxcert_in.port.physical_port = (u8)data->hdcp_ddi;132	verify_rxcert_in.port.attached_transcoder = (u8)data->hdcp_transcoder;133 134	verify_rxcert_in.cert_rx = rx_cert->cert_rx;135	memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);136	memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);137 138	byte = mei_cldev_send(cldev, (u8 *)&verify_rxcert_in,139			      sizeof(verify_rxcert_in));140	if (byte < 0) {141		dev_dbg(dev, "mei_cldev_send failed: %zd\n", byte);142		return byte;143	}144 145	byte = mei_cldev_recv(cldev, (u8 *)&verify_rxcert_out,146			      sizeof(verify_rxcert_out));147	if (byte < 0) {148		dev_dbg(dev, "mei_cldev_recv failed: %zd\n", byte);149		return byte;150	}151 152	if (verify_rxcert_out.header.status != FW_HDCP_STATUS_SUCCESS) {153		dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",154			WIRED_VERIFY_RECEIVER_CERT,155			verify_rxcert_out.header.status);156		return -EIO;157	}158 159	*km_stored = !!verify_rxcert_out.km_stored;160	if (verify_rxcert_out.km_stored) {161		ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;162		*msg_sz = sizeof(struct hdcp2_ake_stored_km);163	} else {164		ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;165		*msg_sz = sizeof(struct hdcp2_ake_no_stored_km);166	}167 168	memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,169	       sizeof(verify_rxcert_out.ekm_buff));170 171	return 0;172}173 174/**175 * mei_hdcp_verify_hprime() - Verify AKE_Send_H_prime at ME FW.176 * @dev: device corresponding to the mei_cl_device177 * @data: Intel HW specific hdcp data178 * @rx_hprime: AKE_Send_H_prime msg for ME FW verification179 *180 * Return: 0 on Success, <0 on Failure181 */182static int183mei_hdcp_verify_hprime(struct device *dev, struct hdcp_port_data *data,184		       struct hdcp2_ake_send_hprime *rx_hprime)185{186	struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };187	struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };188	struct mei_cl_device *cldev;189	ssize_t byte;190 191	if (!dev || !data || !rx_hprime)192		return -EINVAL;193 194	cldev = to_mei_cl_device(dev);195 196	send_hprime_in.header.api_version = HDCP_API_VERSION;197	send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;198	send_hprime_in.header.status = FW_HDCP_STATUS_SUCCESS;199	send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;200 201	send_hprime_in.port.integrated_port_type = data->port_type;202	send_hprime_in.port.physical_port = (u8)data->hdcp_ddi;203	send_hprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;204 205	memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,206	       HDCP_2_2_H_PRIME_LEN);207 208	byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,209			      sizeof(send_hprime_in));210	if (byte < 0) {211		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);212		return byte;213	}214 215	byte = mei_cldev_recv(cldev, (u8 *)&send_hprime_out,216			      sizeof(send_hprime_out));217	if (byte < 0) {218		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);219		return byte;220	}221 222	if (send_hprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {223		dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",224			WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);225		return -EIO;226	}227 228	return 0;229}230 231/**232 * mei_hdcp_store_pairing_info() - Store pairing info received at ME FW233 * @dev: device corresponding to the mei_cl_device234 * @data: Intel HW specific hdcp data235 * @pairing_info: AKE_Send_Pairing_Info msg input to ME FW236 *237 * Return: 0 on Success, <0 on Failure238 */239static int240mei_hdcp_store_pairing_info(struct device *dev, struct hdcp_port_data *data,241			    struct hdcp2_ake_send_pairing_info *pairing_info)242{243	struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };244	struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };245	struct mei_cl_device *cldev;246	ssize_t byte;247 248	if (!dev || !data || !pairing_info)249		return -EINVAL;250 251	cldev = to_mei_cl_device(dev);252 253	pairing_info_in.header.api_version = HDCP_API_VERSION;254	pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;255	pairing_info_in.header.status = FW_HDCP_STATUS_SUCCESS;256	pairing_info_in.header.buffer_len =257					WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;258 259	pairing_info_in.port.integrated_port_type = data->port_type;260	pairing_info_in.port.physical_port = (u8)data->hdcp_ddi;261	pairing_info_in.port.attached_transcoder = (u8)data->hdcp_transcoder;262 263	memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,264	       HDCP_2_2_E_KH_KM_LEN);265 266	byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,267			      sizeof(pairing_info_in));268	if (byte < 0) {269		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);270		return byte;271	}272 273	byte = mei_cldev_recv(cldev, (u8 *)&pairing_info_out,274			      sizeof(pairing_info_out));275	if (byte < 0) {276		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);277		return byte;278	}279 280	if (pairing_info_out.header.status != FW_HDCP_STATUS_SUCCESS) {281		dev_dbg(dev, "ME cmd 0x%08X failed. Status: 0x%X\n",282			WIRED_AKE_SEND_PAIRING_INFO,283			pairing_info_out.header.status);284		return -EIO;285	}286 287	return 0;288}289 290/**291 * mei_hdcp_initiate_locality_check() - Prepare LC_Init292 * @dev: device corresponding to the mei_cl_device293 * @data: Intel HW specific hdcp data294 * @lc_init_data: LC_Init msg output295 *296 * Return: 0 on Success, <0 on Failure297 */298static int299mei_hdcp_initiate_locality_check(struct device *dev,300				 struct hdcp_port_data *data,301				 struct hdcp2_lc_init *lc_init_data)302{303	struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } };304	struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } };305	struct mei_cl_device *cldev;306	ssize_t byte;307 308	if (!dev || !data || !lc_init_data)309		return -EINVAL;310 311	cldev = to_mei_cl_device(dev);312 313	lc_init_in.header.api_version = HDCP_API_VERSION;314	lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;315	lc_init_in.header.status = FW_HDCP_STATUS_SUCCESS;316	lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;317 318	lc_init_in.port.integrated_port_type = data->port_type;319	lc_init_in.port.physical_port = (u8)data->hdcp_ddi;320	lc_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;321 322	byte = mei_cldev_send(cldev, (u8 *)&lc_init_in, sizeof(lc_init_in));323	if (byte < 0) {324		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);325		return byte;326	}327 328	byte = mei_cldev_recv(cldev, (u8 *)&lc_init_out, sizeof(lc_init_out));329	if (byte < 0) {330		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);331		return byte;332	}333 334	if (lc_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {335		dev_dbg(dev, "ME cmd 0x%08X Failed. status: 0x%X\n",336			WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);337		return -EIO;338	}339 340	lc_init_data->msg_id = HDCP_2_2_LC_INIT;341	memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);342 343	return 0;344}345 346/**347 * mei_hdcp_verify_lprime() - Verify lprime.348 * @dev: device corresponding to the mei_cl_device349 * @data: Intel HW specific hdcp data350 * @rx_lprime: LC_Send_L_prime msg for ME FW verification351 *352 * Return: 0 on Success, <0 on Failure353 */354static int355mei_hdcp_verify_lprime(struct device *dev, struct hdcp_port_data *data,356		       struct hdcp2_lc_send_lprime *rx_lprime)357{358	struct wired_cmd_validate_locality_in verify_lprime_in = { { 0 } };359	struct wired_cmd_validate_locality_out verify_lprime_out = { { 0 } };360	struct mei_cl_device *cldev;361	ssize_t byte;362 363	if (!dev || !data || !rx_lprime)364		return -EINVAL;365 366	cldev = to_mei_cl_device(dev);367 368	verify_lprime_in.header.api_version = HDCP_API_VERSION;369	verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;370	verify_lprime_in.header.status = FW_HDCP_STATUS_SUCCESS;371	verify_lprime_in.header.buffer_len =372					WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN;373 374	verify_lprime_in.port.integrated_port_type = data->port_type;375	verify_lprime_in.port.physical_port = (u8)data->hdcp_ddi;376	verify_lprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;377 378	memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,379	       HDCP_2_2_L_PRIME_LEN);380 381	byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in,382			      sizeof(verify_lprime_in));383	if (byte < 0) {384		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);385		return byte;386	}387 388	byte = mei_cldev_recv(cldev, (u8 *)&verify_lprime_out,389			      sizeof(verify_lprime_out));390	if (byte < 0) {391		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);392		return byte;393	}394 395	if (verify_lprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {396		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",397			WIRED_VALIDATE_LOCALITY,398			verify_lprime_out.header.status);399		return -EIO;400	}401 402	return 0;403}404 405/**406 * mei_hdcp_get_session_key() - Prepare SKE_Send_Eks.407 * @dev: device corresponding to the mei_cl_device408 * @data: Intel HW specific hdcp data409 * @ske_data: SKE_Send_Eks msg output from ME FW.410 *411 * Return: 0 on Success, <0 on Failure412 */413static int mei_hdcp_get_session_key(struct device *dev,414				    struct hdcp_port_data *data,415				    struct hdcp2_ske_send_eks *ske_data)416{417	struct wired_cmd_get_session_key_in get_skey_in = { { 0 } };418	struct wired_cmd_get_session_key_out get_skey_out = { { 0 } };419	struct mei_cl_device *cldev;420	ssize_t byte;421 422	if (!dev || !data || !ske_data)423		return -EINVAL;424 425	cldev = to_mei_cl_device(dev);426 427	get_skey_in.header.api_version = HDCP_API_VERSION;428	get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;429	get_skey_in.header.status = FW_HDCP_STATUS_SUCCESS;430	get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN;431 432	get_skey_in.port.integrated_port_type = data->port_type;433	get_skey_in.port.physical_port = (u8)data->hdcp_ddi;434	get_skey_in.port.attached_transcoder = (u8)data->hdcp_transcoder;435 436	byte = mei_cldev_send(cldev, (u8 *)&get_skey_in, sizeof(get_skey_in));437	if (byte < 0) {438		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);439		return byte;440	}441 442	byte = mei_cldev_recv(cldev, (u8 *)&get_skey_out, sizeof(get_skey_out));443 444	if (byte < 0) {445		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);446		return byte;447	}448 449	if (get_skey_out.header.status != FW_HDCP_STATUS_SUCCESS) {450		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",451			WIRED_GET_SESSION_KEY, get_skey_out.header.status);452		return -EIO;453	}454 455	ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;456	memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,457	       HDCP_2_2_E_DKEY_KS_LEN);458	memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);459 460	return 0;461}462 463/**464 * mei_hdcp_repeater_check_flow_prepare_ack() - Validate the Downstream topology465 * and prepare rep_ack.466 * @dev: device corresponding to the mei_cl_device467 * @data: Intel HW specific hdcp data468 * @rep_topology: Receiver ID List to be validated469 * @rep_send_ack : repeater ack from ME FW.470 *471 * Return: 0 on Success, <0 on Failure472 */473static int474mei_hdcp_repeater_check_flow_prepare_ack(struct device *dev,475					 struct hdcp_port_data *data,476					 struct hdcp2_rep_send_receiverid_list477							*rep_topology,478					 struct hdcp2_rep_send_ack479							*rep_send_ack)480{481	struct wired_cmd_verify_repeater_in verify_repeater_in = { { 0 } };482	struct wired_cmd_verify_repeater_out verify_repeater_out = { { 0 } };483	struct mei_cl_device *cldev;484	ssize_t byte;485 486	if (!dev || !rep_topology || !rep_send_ack || !data)487		return -EINVAL;488 489	cldev = to_mei_cl_device(dev);490 491	verify_repeater_in.header.api_version = HDCP_API_VERSION;492	verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;493	verify_repeater_in.header.status = FW_HDCP_STATUS_SUCCESS;494	verify_repeater_in.header.buffer_len =495					WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN;496 497	verify_repeater_in.port.integrated_port_type = data->port_type;498	verify_repeater_in.port.physical_port = (u8)data->hdcp_ddi;499	verify_repeater_in.port.attached_transcoder = (u8)data->hdcp_transcoder;500 501	memcpy(verify_repeater_in.rx_info, rep_topology->rx_info,502	       HDCP_2_2_RXINFO_LEN);503	memcpy(verify_repeater_in.seq_num_v, rep_topology->seq_num_v,504	       HDCP_2_2_SEQ_NUM_LEN);505	memcpy(verify_repeater_in.v_prime, rep_topology->v_prime,506	       HDCP_2_2_V_PRIME_HALF_LEN);507	memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,508	       HDCP_2_2_RECEIVER_IDS_MAX_LEN);509 510	byte = mei_cldev_send(cldev, (u8 *)&verify_repeater_in,511			      sizeof(verify_repeater_in));512	if (byte < 0) {513		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);514		return byte;515	}516 517	byte = mei_cldev_recv(cldev, (u8 *)&verify_repeater_out,518			      sizeof(verify_repeater_out));519	if (byte < 0) {520		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);521		return byte;522	}523 524	if (verify_repeater_out.header.status != FW_HDCP_STATUS_SUCCESS) {525		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",526			WIRED_VERIFY_REPEATER,527			verify_repeater_out.header.status);528		return -EIO;529	}530 531	memcpy(rep_send_ack->v, verify_repeater_out.v,532	       HDCP_2_2_V_PRIME_HALF_LEN);533	rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;534 535	return 0;536}537 538/**539 * mei_hdcp_verify_mprime() - Verify mprime.540 * @dev: device corresponding to the mei_cl_device541 * @data: Intel HW specific hdcp data542 * @stream_ready: RepeaterAuth_Stream_Ready msg for ME FW verification.543 *544 * Return: 0 on Success, <0 on Failure545 */546static int mei_hdcp_verify_mprime(struct device *dev,547				  struct hdcp_port_data *data,548				  struct hdcp2_rep_stream_ready *stream_ready)549{550	struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;551	struct wired_cmd_repeater_auth_stream_req_out552					verify_mprime_out = { { 0 } };553	struct mei_cl_device *cldev;554	ssize_t byte;555	size_t cmd_size;556 557	if (!dev || !stream_ready || !data)558		return -EINVAL;559 560	cldev = to_mei_cl_device(dev);561 562	cmd_size = struct_size(verify_mprime_in, streams, data->k);563	if (cmd_size == SIZE_MAX)564		return -EINVAL;565 566	verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);567	if (!verify_mprime_in)568		return -ENOMEM;569 570	verify_mprime_in->header.api_version = HDCP_API_VERSION;571	verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;572	verify_mprime_in->header.status = FW_HDCP_STATUS_SUCCESS;573	verify_mprime_in->header.buffer_len = cmd_size  - sizeof(verify_mprime_in->header);574 575	verify_mprime_in->port.integrated_port_type = data->port_type;576	verify_mprime_in->port.physical_port = (u8)data->hdcp_ddi;577	verify_mprime_in->port.attached_transcoder = (u8)data->hdcp_transcoder;578 579	memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, HDCP_2_2_MPRIME_LEN);580	drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);581 582	memcpy(verify_mprime_in->streams, data->streams,583	       array_size(data->k, sizeof(*data->streams)));584 585	verify_mprime_in->k = cpu_to_be16(data->k);586 587	byte = mei_cldev_send(cldev, (u8 *)verify_mprime_in, cmd_size);588	kfree(verify_mprime_in);589	if (byte < 0) {590		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);591		return byte;592	}593 594	byte = mei_cldev_recv(cldev, (u8 *)&verify_mprime_out,595			      sizeof(verify_mprime_out));596	if (byte < 0) {597		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);598		return byte;599	}600 601	if (verify_mprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {602		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",603			WIRED_REPEATER_AUTH_STREAM_REQ,604			verify_mprime_out.header.status);605		return -EIO;606	}607 608	return 0;609}610 611/**612 * mei_hdcp_enable_authentication() - Mark a port as authenticated613 * through ME FW614 * @dev: device corresponding to the mei_cl_device615 * @data: Intel HW specific hdcp data616 *617 * Return: 0 on Success, <0 on Failure618 */619static int mei_hdcp_enable_authentication(struct device *dev,620					  struct hdcp_port_data *data)621{622	struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };623	struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };624	struct mei_cl_device *cldev;625	ssize_t byte;626 627	if (!dev || !data)628		return -EINVAL;629 630	cldev = to_mei_cl_device(dev);631 632	enable_auth_in.header.api_version = HDCP_API_VERSION;633	enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;634	enable_auth_in.header.status = FW_HDCP_STATUS_SUCCESS;635	enable_auth_in.header.buffer_len = WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN;636 637	enable_auth_in.port.integrated_port_type = data->port_type;638	enable_auth_in.port.physical_port = (u8)data->hdcp_ddi;639	enable_auth_in.port.attached_transcoder = (u8)data->hdcp_transcoder;640	enable_auth_in.stream_type = data->streams[0].stream_type;641 642	byte = mei_cldev_send(cldev, (u8 *)&enable_auth_in,643			      sizeof(enable_auth_in));644	if (byte < 0) {645		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);646		return byte;647	}648 649	byte = mei_cldev_recv(cldev, (u8 *)&enable_auth_out,650			      sizeof(enable_auth_out));651	if (byte < 0) {652		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);653		return byte;654	}655 656	if (enable_auth_out.header.status != FW_HDCP_STATUS_SUCCESS) {657		dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",658			WIRED_ENABLE_AUTH, enable_auth_out.header.status);659		return -EIO;660	}661 662	return 0;663}664 665/**666 * mei_hdcp_close_session() - Close the Wired HDCP Tx session of ME FW per port.667 * This also disables the authenticated state of the port.668 * @dev: device corresponding to the mei_cl_device669 * @data: Intel HW specific hdcp data670 *671 * Return: 0 on Success, <0 on Failure672 */673static int674mei_hdcp_close_session(struct device *dev, struct hdcp_port_data *data)675{676	struct wired_cmd_close_session_in session_close_in = { { 0 } };677	struct wired_cmd_close_session_out session_close_out = { { 0 } };678	struct mei_cl_device *cldev;679	ssize_t byte;680 681	if (!dev || !data)682		return -EINVAL;683 684	cldev = to_mei_cl_device(dev);685 686	session_close_in.header.api_version = HDCP_API_VERSION;687	session_close_in.header.command_id = WIRED_CLOSE_SESSION;688	session_close_in.header.status = FW_HDCP_STATUS_SUCCESS;689	session_close_in.header.buffer_len =690				WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN;691 692	session_close_in.port.integrated_port_type = data->port_type;693	session_close_in.port.physical_port = (u8)data->hdcp_ddi;694	session_close_in.port.attached_transcoder = (u8)data->hdcp_transcoder;695 696	byte = mei_cldev_send(cldev, (u8 *)&session_close_in,697			      sizeof(session_close_in));698	if (byte < 0) {699		dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);700		return byte;701	}702 703	byte = mei_cldev_recv(cldev, (u8 *)&session_close_out,704			      sizeof(session_close_out));705	if (byte < 0) {706		dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);707		return byte;708	}709 710	if (session_close_out.header.status != FW_HDCP_STATUS_SUCCESS) {711		dev_dbg(dev, "Session Close Failed. status: 0x%X\n",712			session_close_out.header.status);713		return -EIO;714	}715 716	return 0;717}718 719static const struct i915_hdcp_ops mei_hdcp_ops = {720	.owner = THIS_MODULE,721	.initiate_hdcp2_session = mei_hdcp_initiate_session,722	.verify_receiver_cert_prepare_km =723				mei_hdcp_verify_receiver_cert_prepare_km,724	.verify_hprime = mei_hdcp_verify_hprime,725	.store_pairing_info = mei_hdcp_store_pairing_info,726	.initiate_locality_check = mei_hdcp_initiate_locality_check,727	.verify_lprime = mei_hdcp_verify_lprime,728	.get_session_key = mei_hdcp_get_session_key,729	.repeater_check_flow_prepare_ack =730				mei_hdcp_repeater_check_flow_prepare_ack,731	.verify_mprime = mei_hdcp_verify_mprime,732	.enable_hdcp_authentication = mei_hdcp_enable_authentication,733	.close_hdcp_session = mei_hdcp_close_session,734};735 736static int mei_component_master_bind(struct device *dev)737{738	struct mei_cl_device *cldev = to_mei_cl_device(dev);739	struct i915_hdcp_arbiter *comp_arbiter = mei_cldev_get_drvdata(cldev);740	int ret;741 742	dev_dbg(dev, "%s\n", __func__);743	comp_arbiter->ops = &mei_hdcp_ops;744	comp_arbiter->hdcp_dev = dev;745	ret = component_bind_all(dev, comp_arbiter);746	if (ret < 0)747		return ret;748 749	return 0;750}751 752static void mei_component_master_unbind(struct device *dev)753{754	struct mei_cl_device *cldev = to_mei_cl_device(dev);755	struct i915_hdcp_arbiter *comp_arbiter = mei_cldev_get_drvdata(cldev);756 757	dev_dbg(dev, "%s\n", __func__);758	component_unbind_all(dev, comp_arbiter);759}760 761static const struct component_master_ops mei_component_master_ops = {762	.bind = mei_component_master_bind,763	.unbind = mei_component_master_unbind,764};765 766/**767 * mei_hdcp_component_match - compare function for matching mei hdcp.768 *769 *    The function checks if the driver is i915, the subcomponent is HDCP770 *    and the grand parent of hdcp and the parent of i915 are the same771 *    PCH device.772 *773 * @dev: master device774 * @subcomponent: subcomponent to match (I915_COMPONENT_HDCP)775 * @data: compare data (mei hdcp device)776 *777 * Return:778 * * 1 - if components match779 * * 0 - otherwise780 */781static int mei_hdcp_component_match(struct device *dev, int subcomponent,782				    void *data)783{784	struct device *base = data;785	struct pci_dev *pdev;786 787	if (!dev_is_pci(dev))788		return 0;789 790	pdev = to_pci_dev(dev);791 792	if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) ||793	    pdev->vendor != PCI_VENDOR_ID_INTEL)794		return 0;795 796	if (subcomponent != I915_COMPONENT_HDCP)797		return 0;798 799	base = base->parent;800	if (!base)801		return 0;802 803	base = base->parent;804	dev = dev->parent;805 806	return (base && dev && dev == base);807}808 809static int mei_hdcp_probe(struct mei_cl_device *cldev,810			  const struct mei_cl_device_id *id)811{812	struct i915_hdcp_arbiter *comp_arbiter;813	struct component_match *master_match;814	int ret;815 816	ret = mei_cldev_enable(cldev);817	if (ret < 0) {818		dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);819		goto enable_err_exit;820	}821 822	comp_arbiter = kzalloc(sizeof(*comp_arbiter), GFP_KERNEL);823	if (!comp_arbiter) {824		ret = -ENOMEM;825		goto err_exit;826	}827 828	master_match = NULL;829	component_match_add_typed(&cldev->dev, &master_match,830				  mei_hdcp_component_match, &cldev->dev);831	if (IS_ERR_OR_NULL(master_match)) {832		ret = -ENOMEM;833		goto err_exit;834	}835 836	mei_cldev_set_drvdata(cldev, comp_arbiter);837	ret = component_master_add_with_match(&cldev->dev,838					      &mei_component_master_ops,839					      master_match);840	if (ret < 0) {841		dev_err(&cldev->dev, "Master comp add failed %d\n", ret);842		goto err_exit;843	}844 845	return 0;846 847err_exit:848	mei_cldev_set_drvdata(cldev, NULL);849	kfree(comp_arbiter);850	mei_cldev_disable(cldev);851enable_err_exit:852	return ret;853}854 855static void mei_hdcp_remove(struct mei_cl_device *cldev)856{857	struct i915_hdcp_arbiter *comp_arbiter = mei_cldev_get_drvdata(cldev);858	int ret;859 860	component_master_del(&cldev->dev, &mei_component_master_ops);861	kfree(comp_arbiter);862	mei_cldev_set_drvdata(cldev, NULL);863 864	ret = mei_cldev_disable(cldev);865	if (ret)866		dev_warn(&cldev->dev, "mei_cldev_disable() failed\n");867}868 869#define MEI_UUID_HDCP UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, 0xA5, \870			      0x52, 0xD1, 0xC5, 0x4B, 0x62, 0x7F, 0x04)871 872static const struct mei_cl_device_id mei_hdcp_tbl[] = {873	{ .uuid = MEI_UUID_HDCP, .version = MEI_CL_VERSION_ANY },874	{ }875};876MODULE_DEVICE_TABLE(mei, mei_hdcp_tbl);877 878static struct mei_cl_driver mei_hdcp_driver = {879	.id_table = mei_hdcp_tbl,880	.name = KBUILD_MODNAME,881	.probe = mei_hdcp_probe,882	.remove	= mei_hdcp_remove,883};884 885module_mei_cl_driver(mei_hdcp_driver);886 887MODULE_AUTHOR("Intel Corporation");888MODULE_LICENSE("GPL");889MODULE_DESCRIPTION("MEI HDCP");890