xref: /openbsd-src/sys/dev/pci/drm/i915/display/intel_hdcp_gsc.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
1*f005ef32Sjsg // SPDX-License-Identifier: MIT
2*f005ef32Sjsg /*
3*f005ef32Sjsg  * Copyright 2023, Intel Corporation.
4*f005ef32Sjsg  */
5*f005ef32Sjsg 
6*f005ef32Sjsg #include <drm/i915_hdcp_interface.h>
7*f005ef32Sjsg 
8*f005ef32Sjsg #include "gem/i915_gem_region.h"
9*f005ef32Sjsg #include "gt/intel_gt.h"
10*f005ef32Sjsg #include "gt/uc/intel_gsc_uc_heci_cmd_submit.h"
11*f005ef32Sjsg #include "i915_drv.h"
12*f005ef32Sjsg #include "i915_utils.h"
13*f005ef32Sjsg #include "intel_hdcp_gsc.h"
14*f005ef32Sjsg 
intel_hdcp_gsc_cs_required(struct drm_i915_private * i915)15*f005ef32Sjsg bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915)
16*f005ef32Sjsg {
17*f005ef32Sjsg 	return DISPLAY_VER(i915) >= 14;
18*f005ef32Sjsg }
19*f005ef32Sjsg 
20*f005ef32Sjsg static int
gsc_hdcp_initiate_session(struct device * dev,struct hdcp_port_data * data,struct hdcp2_ake_init * ake_data)21*f005ef32Sjsg gsc_hdcp_initiate_session(struct device *dev, struct hdcp_port_data *data,
22*f005ef32Sjsg 			  struct hdcp2_ake_init *ake_data)
23*f005ef32Sjsg {
24*f005ef32Sjsg 	STUB();
25*f005ef32Sjsg 	return -ENOSYS;
26*f005ef32Sjsg #ifdef notyet
27*f005ef32Sjsg 	struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };
28*f005ef32Sjsg 	struct wired_cmd_initiate_hdcp2_session_out
29*f005ef32Sjsg 						session_init_out = { { 0 } };
30*f005ef32Sjsg 	struct drm_i915_private *i915;
31*f005ef32Sjsg 	ssize_t byte;
32*f005ef32Sjsg 
33*f005ef32Sjsg 	if (!dev || !data || !ake_data)
34*f005ef32Sjsg 		return -EINVAL;
35*f005ef32Sjsg 
36*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
37*f005ef32Sjsg 	if (!i915) {
38*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
39*f005ef32Sjsg 		return -ENODEV;
40*f005ef32Sjsg 	}
41*f005ef32Sjsg 
42*f005ef32Sjsg 	session_init_in.header.api_version = HDCP_API_VERSION;
43*f005ef32Sjsg 	session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
44*f005ef32Sjsg 	session_init_in.header.status = FW_HDCP_STATUS_SUCCESS;
45*f005ef32Sjsg 	session_init_in.header.buffer_len =
46*f005ef32Sjsg 				WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
47*f005ef32Sjsg 
48*f005ef32Sjsg 	session_init_in.port.integrated_port_type = data->port_type;
49*f005ef32Sjsg 	session_init_in.port.physical_port = (u8)data->hdcp_ddi;
50*f005ef32Sjsg 	session_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
51*f005ef32Sjsg 	session_init_in.protocol = data->protocol;
52*f005ef32Sjsg 
53*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_init_in,
54*f005ef32Sjsg 				       sizeof(session_init_in),
55*f005ef32Sjsg 				       (u8 *)&session_init_out,
56*f005ef32Sjsg 				       sizeof(session_init_out));
57*f005ef32Sjsg 	if (byte < 0) {
58*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
59*f005ef32Sjsg 		return byte;
60*f005ef32Sjsg 	}
61*f005ef32Sjsg 
62*f005ef32Sjsg 	if (session_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
63*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
64*f005ef32Sjsg 			    WIRED_INITIATE_HDCP2_SESSION,
65*f005ef32Sjsg 			    session_init_out.header.status);
66*f005ef32Sjsg 		return -EIO;
67*f005ef32Sjsg 	}
68*f005ef32Sjsg 
69*f005ef32Sjsg 	ake_data->msg_id = HDCP_2_2_AKE_INIT;
70*f005ef32Sjsg 	ake_data->tx_caps = session_init_out.tx_caps;
71*f005ef32Sjsg 	memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN);
72*f005ef32Sjsg 
73*f005ef32Sjsg 	return 0;
74*f005ef32Sjsg #endif
75*f005ef32Sjsg }
76*f005ef32Sjsg 
77*f005ef32Sjsg static int
gsc_hdcp_verify_receiver_cert_prepare_km(struct device * dev,struct hdcp_port_data * data,struct hdcp2_ake_send_cert * rx_cert,bool * km_stored,struct hdcp2_ake_no_stored_km * ek_pub_km,size_t * msg_sz)78*f005ef32Sjsg gsc_hdcp_verify_receiver_cert_prepare_km(struct device *dev,
79*f005ef32Sjsg 					 struct hdcp_port_data *data,
80*f005ef32Sjsg 					 struct hdcp2_ake_send_cert *rx_cert,
81*f005ef32Sjsg 					 bool *km_stored,
82*f005ef32Sjsg 					 struct hdcp2_ake_no_stored_km
83*f005ef32Sjsg 								*ek_pub_km,
84*f005ef32Sjsg 					 size_t *msg_sz)
85*f005ef32Sjsg {
86*f005ef32Sjsg 	STUB();
87*f005ef32Sjsg 	return -ENOSYS;
88*f005ef32Sjsg #ifdef notyet
89*f005ef32Sjsg 	struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };
90*f005ef32Sjsg 	struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };
91*f005ef32Sjsg 	struct drm_i915_private *i915;
92*f005ef32Sjsg 	ssize_t byte;
93*f005ef32Sjsg 
94*f005ef32Sjsg 	if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
95*f005ef32Sjsg 		return -EINVAL;
96*f005ef32Sjsg 
97*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
98*f005ef32Sjsg 	if (!i915) {
99*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
100*f005ef32Sjsg 		return -ENODEV;
101*f005ef32Sjsg 	}
102*f005ef32Sjsg 
103*f005ef32Sjsg 	verify_rxcert_in.header.api_version = HDCP_API_VERSION;
104*f005ef32Sjsg 	verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
105*f005ef32Sjsg 	verify_rxcert_in.header.status = FW_HDCP_STATUS_SUCCESS;
106*f005ef32Sjsg 	verify_rxcert_in.header.buffer_len =
107*f005ef32Sjsg 				WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
108*f005ef32Sjsg 
109*f005ef32Sjsg 	verify_rxcert_in.port.integrated_port_type = data->port_type;
110*f005ef32Sjsg 	verify_rxcert_in.port.physical_port = (u8)data->hdcp_ddi;
111*f005ef32Sjsg 	verify_rxcert_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
112*f005ef32Sjsg 
113*f005ef32Sjsg 	verify_rxcert_in.cert_rx = rx_cert->cert_rx;
114*f005ef32Sjsg 	memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
115*f005ef32Sjsg 	memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
116*f005ef32Sjsg 
117*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_rxcert_in,
118*f005ef32Sjsg 				       sizeof(verify_rxcert_in),
119*f005ef32Sjsg 				       (u8 *)&verify_rxcert_out,
120*f005ef32Sjsg 				       sizeof(verify_rxcert_out));
121*f005ef32Sjsg 	if (byte < 0) {
122*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
123*f005ef32Sjsg 		return byte;
124*f005ef32Sjsg 	}
125*f005ef32Sjsg 
126*f005ef32Sjsg 	if (verify_rxcert_out.header.status != FW_HDCP_STATUS_SUCCESS) {
127*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
128*f005ef32Sjsg 			    WIRED_VERIFY_RECEIVER_CERT,
129*f005ef32Sjsg 			    verify_rxcert_out.header.status);
130*f005ef32Sjsg 		return -EIO;
131*f005ef32Sjsg 	}
132*f005ef32Sjsg 
133*f005ef32Sjsg 	*km_stored = !!verify_rxcert_out.km_stored;
134*f005ef32Sjsg 	if (verify_rxcert_out.km_stored) {
135*f005ef32Sjsg 		ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
136*f005ef32Sjsg 		*msg_sz = sizeof(struct hdcp2_ake_stored_km);
137*f005ef32Sjsg 	} else {
138*f005ef32Sjsg 		ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
139*f005ef32Sjsg 		*msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
140*f005ef32Sjsg 	}
141*f005ef32Sjsg 
142*f005ef32Sjsg 	memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
143*f005ef32Sjsg 	       sizeof(verify_rxcert_out.ekm_buff));
144*f005ef32Sjsg 
145*f005ef32Sjsg 	return 0;
146*f005ef32Sjsg #endif
147*f005ef32Sjsg }
148*f005ef32Sjsg 
149*f005ef32Sjsg static int
gsc_hdcp_verify_hprime(struct device * dev,struct hdcp_port_data * data,struct hdcp2_ake_send_hprime * rx_hprime)150*f005ef32Sjsg gsc_hdcp_verify_hprime(struct device *dev, struct hdcp_port_data *data,
151*f005ef32Sjsg 		       struct hdcp2_ake_send_hprime *rx_hprime)
152*f005ef32Sjsg {
153*f005ef32Sjsg 	STUB();
154*f005ef32Sjsg 	return -ENOSYS;
155*f005ef32Sjsg #ifdef notyet
156*f005ef32Sjsg 	struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };
157*f005ef32Sjsg 	struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };
158*f005ef32Sjsg 	struct drm_i915_private *i915;
159*f005ef32Sjsg 	ssize_t byte;
160*f005ef32Sjsg 
161*f005ef32Sjsg 	if (!dev || !data || !rx_hprime)
162*f005ef32Sjsg 		return -EINVAL;
163*f005ef32Sjsg 
164*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
165*f005ef32Sjsg 	if (!i915) {
166*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
167*f005ef32Sjsg 		return -ENODEV;
168*f005ef32Sjsg 	}
169*f005ef32Sjsg 
170*f005ef32Sjsg 	send_hprime_in.header.api_version = HDCP_API_VERSION;
171*f005ef32Sjsg 	send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
172*f005ef32Sjsg 	send_hprime_in.header.status = FW_HDCP_STATUS_SUCCESS;
173*f005ef32Sjsg 	send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
174*f005ef32Sjsg 
175*f005ef32Sjsg 	send_hprime_in.port.integrated_port_type = data->port_type;
176*f005ef32Sjsg 	send_hprime_in.port.physical_port = (u8)data->hdcp_ddi;
177*f005ef32Sjsg 	send_hprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
178*f005ef32Sjsg 
179*f005ef32Sjsg 	memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
180*f005ef32Sjsg 	       HDCP_2_2_H_PRIME_LEN);
181*f005ef32Sjsg 
182*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&send_hprime_in,
183*f005ef32Sjsg 				       sizeof(send_hprime_in),
184*f005ef32Sjsg 				       (u8 *)&send_hprime_out,
185*f005ef32Sjsg 				       sizeof(send_hprime_out));
186*f005ef32Sjsg 	if (byte < 0) {
187*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
188*f005ef32Sjsg 		return byte;
189*f005ef32Sjsg 	}
190*f005ef32Sjsg 
191*f005ef32Sjsg 	if (send_hprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
192*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
193*f005ef32Sjsg 			    WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
194*f005ef32Sjsg 		return -EIO;
195*f005ef32Sjsg 	}
196*f005ef32Sjsg 
197*f005ef32Sjsg 	return 0;
198*f005ef32Sjsg #endif
199*f005ef32Sjsg }
200*f005ef32Sjsg 
201*f005ef32Sjsg static int
gsc_hdcp_store_pairing_info(struct device * dev,struct hdcp_port_data * data,struct hdcp2_ake_send_pairing_info * pairing_info)202*f005ef32Sjsg gsc_hdcp_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
203*f005ef32Sjsg 			    struct hdcp2_ake_send_pairing_info *pairing_info)
204*f005ef32Sjsg {
205*f005ef32Sjsg 	STUB();
206*f005ef32Sjsg 	return -ENOSYS;
207*f005ef32Sjsg #ifdef notyet
208*f005ef32Sjsg 	struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };
209*f005ef32Sjsg 	struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };
210*f005ef32Sjsg 	struct drm_i915_private *i915;
211*f005ef32Sjsg 	ssize_t byte;
212*f005ef32Sjsg 
213*f005ef32Sjsg 	if (!dev || !data || !pairing_info)
214*f005ef32Sjsg 		return -EINVAL;
215*f005ef32Sjsg 
216*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
217*f005ef32Sjsg 	if (!i915) {
218*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
219*f005ef32Sjsg 		return -ENODEV;
220*f005ef32Sjsg 	}
221*f005ef32Sjsg 
222*f005ef32Sjsg 	pairing_info_in.header.api_version = HDCP_API_VERSION;
223*f005ef32Sjsg 	pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
224*f005ef32Sjsg 	pairing_info_in.header.status = FW_HDCP_STATUS_SUCCESS;
225*f005ef32Sjsg 	pairing_info_in.header.buffer_len =
226*f005ef32Sjsg 					WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
227*f005ef32Sjsg 
228*f005ef32Sjsg 	pairing_info_in.port.integrated_port_type = data->port_type;
229*f005ef32Sjsg 	pairing_info_in.port.physical_port = (u8)data->hdcp_ddi;
230*f005ef32Sjsg 	pairing_info_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
231*f005ef32Sjsg 
232*f005ef32Sjsg 	memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
233*f005ef32Sjsg 	       HDCP_2_2_E_KH_KM_LEN);
234*f005ef32Sjsg 
235*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&pairing_info_in,
236*f005ef32Sjsg 				       sizeof(pairing_info_in),
237*f005ef32Sjsg 				       (u8 *)&pairing_info_out,
238*f005ef32Sjsg 				       sizeof(pairing_info_out));
239*f005ef32Sjsg 	if (byte < 0) {
240*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
241*f005ef32Sjsg 		return byte;
242*f005ef32Sjsg 	}
243*f005ef32Sjsg 
244*f005ef32Sjsg 	if (pairing_info_out.header.status != FW_HDCP_STATUS_SUCCESS) {
245*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. Status: 0x%X\n",
246*f005ef32Sjsg 			    WIRED_AKE_SEND_PAIRING_INFO,
247*f005ef32Sjsg 			    pairing_info_out.header.status);
248*f005ef32Sjsg 		return -EIO;
249*f005ef32Sjsg 	}
250*f005ef32Sjsg 
251*f005ef32Sjsg 	return 0;
252*f005ef32Sjsg #endif
253*f005ef32Sjsg }
254*f005ef32Sjsg 
255*f005ef32Sjsg static int
gsc_hdcp_initiate_locality_check(struct device * dev,struct hdcp_port_data * data,struct hdcp2_lc_init * lc_init_data)256*f005ef32Sjsg gsc_hdcp_initiate_locality_check(struct device *dev,
257*f005ef32Sjsg 				 struct hdcp_port_data *data,
258*f005ef32Sjsg 				 struct hdcp2_lc_init *lc_init_data)
259*f005ef32Sjsg {
260*f005ef32Sjsg 	STUB();
261*f005ef32Sjsg 	return -ENOSYS;
262*f005ef32Sjsg #ifdef notyet
263*f005ef32Sjsg 	struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } };
264*f005ef32Sjsg 	struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } };
265*f005ef32Sjsg 	struct drm_i915_private *i915;
266*f005ef32Sjsg 	ssize_t byte;
267*f005ef32Sjsg 
268*f005ef32Sjsg 	if (!dev || !data || !lc_init_data)
269*f005ef32Sjsg 		return -EINVAL;
270*f005ef32Sjsg 
271*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
272*f005ef32Sjsg 	if (!i915) {
273*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
274*f005ef32Sjsg 		return -ENODEV;
275*f005ef32Sjsg 	}
276*f005ef32Sjsg 
277*f005ef32Sjsg 	lc_init_in.header.api_version = HDCP_API_VERSION;
278*f005ef32Sjsg 	lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
279*f005ef32Sjsg 	lc_init_in.header.status = FW_HDCP_STATUS_SUCCESS;
280*f005ef32Sjsg 	lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;
281*f005ef32Sjsg 
282*f005ef32Sjsg 	lc_init_in.port.integrated_port_type = data->port_type;
283*f005ef32Sjsg 	lc_init_in.port.physical_port = (u8)data->hdcp_ddi;
284*f005ef32Sjsg 	lc_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
285*f005ef32Sjsg 
286*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&lc_init_in, sizeof(lc_init_in),
287*f005ef32Sjsg 				       (u8 *)&lc_init_out, sizeof(lc_init_out));
288*f005ef32Sjsg 	if (byte < 0) {
289*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
290*f005ef32Sjsg 		return byte;
291*f005ef32Sjsg 	}
292*f005ef32Sjsg 
293*f005ef32Sjsg 	if (lc_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
294*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. status: 0x%X\n",
295*f005ef32Sjsg 			    WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
296*f005ef32Sjsg 		return -EIO;
297*f005ef32Sjsg 	}
298*f005ef32Sjsg 
299*f005ef32Sjsg 	lc_init_data->msg_id = HDCP_2_2_LC_INIT;
300*f005ef32Sjsg 	memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);
301*f005ef32Sjsg 
302*f005ef32Sjsg 	return 0;
303*f005ef32Sjsg #endif
304*f005ef32Sjsg }
305*f005ef32Sjsg 
306*f005ef32Sjsg static int
gsc_hdcp_verify_lprime(struct device * dev,struct hdcp_port_data * data,struct hdcp2_lc_send_lprime * rx_lprime)307*f005ef32Sjsg gsc_hdcp_verify_lprime(struct device *dev, struct hdcp_port_data *data,
308*f005ef32Sjsg 		       struct hdcp2_lc_send_lprime *rx_lprime)
309*f005ef32Sjsg {
310*f005ef32Sjsg 	STUB();
311*f005ef32Sjsg 	return -ENOSYS;
312*f005ef32Sjsg #ifdef notyet
313*f005ef32Sjsg 	struct wired_cmd_validate_locality_in verify_lprime_in = { { 0 } };
314*f005ef32Sjsg 	struct wired_cmd_validate_locality_out verify_lprime_out = { { 0 } };
315*f005ef32Sjsg 	struct drm_i915_private *i915;
316*f005ef32Sjsg 	ssize_t byte;
317*f005ef32Sjsg 
318*f005ef32Sjsg 	if (!dev || !data || !rx_lprime)
319*f005ef32Sjsg 		return -EINVAL;
320*f005ef32Sjsg 
321*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
322*f005ef32Sjsg 	if (!i915) {
323*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
324*f005ef32Sjsg 		return -ENODEV;
325*f005ef32Sjsg 	}
326*f005ef32Sjsg 
327*f005ef32Sjsg 	verify_lprime_in.header.api_version = HDCP_API_VERSION;
328*f005ef32Sjsg 	verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;
329*f005ef32Sjsg 	verify_lprime_in.header.status = FW_HDCP_STATUS_SUCCESS;
330*f005ef32Sjsg 	verify_lprime_in.header.buffer_len =
331*f005ef32Sjsg 					WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN;
332*f005ef32Sjsg 
333*f005ef32Sjsg 	verify_lprime_in.port.integrated_port_type = data->port_type;
334*f005ef32Sjsg 	verify_lprime_in.port.physical_port = (u8)data->hdcp_ddi;
335*f005ef32Sjsg 	verify_lprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
336*f005ef32Sjsg 
337*f005ef32Sjsg 	memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
338*f005ef32Sjsg 	       HDCP_2_2_L_PRIME_LEN);
339*f005ef32Sjsg 
340*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_lprime_in,
341*f005ef32Sjsg 				       sizeof(verify_lprime_in),
342*f005ef32Sjsg 				       (u8 *)&verify_lprime_out,
343*f005ef32Sjsg 				       sizeof(verify_lprime_out));
344*f005ef32Sjsg 	if (byte < 0) {
345*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
346*f005ef32Sjsg 		return byte;
347*f005ef32Sjsg 	}
348*f005ef32Sjsg 
349*f005ef32Sjsg 	if (verify_lprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
350*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
351*f005ef32Sjsg 			    WIRED_VALIDATE_LOCALITY,
352*f005ef32Sjsg 			    verify_lprime_out.header.status);
353*f005ef32Sjsg 		return -EIO;
354*f005ef32Sjsg 	}
355*f005ef32Sjsg 
356*f005ef32Sjsg 	return 0;
357*f005ef32Sjsg #endif
358*f005ef32Sjsg }
359*f005ef32Sjsg 
gsc_hdcp_get_session_key(struct device * dev,struct hdcp_port_data * data,struct hdcp2_ske_send_eks * ske_data)360*f005ef32Sjsg static int gsc_hdcp_get_session_key(struct device *dev,
361*f005ef32Sjsg 				    struct hdcp_port_data *data,
362*f005ef32Sjsg 				    struct hdcp2_ske_send_eks *ske_data)
363*f005ef32Sjsg {
364*f005ef32Sjsg 	STUB();
365*f005ef32Sjsg 	return -ENOSYS;
366*f005ef32Sjsg #ifdef notyet
367*f005ef32Sjsg 	struct wired_cmd_get_session_key_in get_skey_in = { { 0 } };
368*f005ef32Sjsg 	struct wired_cmd_get_session_key_out get_skey_out = { { 0 } };
369*f005ef32Sjsg 	struct drm_i915_private *i915;
370*f005ef32Sjsg 	ssize_t byte;
371*f005ef32Sjsg 
372*f005ef32Sjsg 	if (!dev || !data || !ske_data)
373*f005ef32Sjsg 		return -EINVAL;
374*f005ef32Sjsg 
375*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
376*f005ef32Sjsg 	if (!i915) {
377*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
378*f005ef32Sjsg 		return -ENODEV;
379*f005ef32Sjsg 	}
380*f005ef32Sjsg 
381*f005ef32Sjsg 	get_skey_in.header.api_version = HDCP_API_VERSION;
382*f005ef32Sjsg 	get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;
383*f005ef32Sjsg 	get_skey_in.header.status = FW_HDCP_STATUS_SUCCESS;
384*f005ef32Sjsg 	get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN;
385*f005ef32Sjsg 
386*f005ef32Sjsg 	get_skey_in.port.integrated_port_type = data->port_type;
387*f005ef32Sjsg 	get_skey_in.port.physical_port = (u8)data->hdcp_ddi;
388*f005ef32Sjsg 	get_skey_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
389*f005ef32Sjsg 
390*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&get_skey_in, sizeof(get_skey_in),
391*f005ef32Sjsg 				       (u8 *)&get_skey_out, sizeof(get_skey_out));
392*f005ef32Sjsg 	if (byte < 0) {
393*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
394*f005ef32Sjsg 		return byte;
395*f005ef32Sjsg 	}
396*f005ef32Sjsg 
397*f005ef32Sjsg 	if (get_skey_out.header.status != FW_HDCP_STATUS_SUCCESS) {
398*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
399*f005ef32Sjsg 			    WIRED_GET_SESSION_KEY, get_skey_out.header.status);
400*f005ef32Sjsg 		return -EIO;
401*f005ef32Sjsg 	}
402*f005ef32Sjsg 
403*f005ef32Sjsg 	ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
404*f005ef32Sjsg 	memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
405*f005ef32Sjsg 	       HDCP_2_2_E_DKEY_KS_LEN);
406*f005ef32Sjsg 	memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
407*f005ef32Sjsg 
408*f005ef32Sjsg 	return 0;
409*f005ef32Sjsg #endif
410*f005ef32Sjsg }
411*f005ef32Sjsg 
412*f005ef32Sjsg static int
gsc_hdcp_repeater_check_flow_prepare_ack(struct device * dev,struct hdcp_port_data * data,struct hdcp2_rep_send_receiverid_list * rep_topology,struct hdcp2_rep_send_ack * rep_send_ack)413*f005ef32Sjsg gsc_hdcp_repeater_check_flow_prepare_ack(struct device *dev,
414*f005ef32Sjsg 					 struct hdcp_port_data *data,
415*f005ef32Sjsg 					 struct hdcp2_rep_send_receiverid_list
416*f005ef32Sjsg 							*rep_topology,
417*f005ef32Sjsg 					 struct hdcp2_rep_send_ack
418*f005ef32Sjsg 							*rep_send_ack)
419*f005ef32Sjsg {
420*f005ef32Sjsg 	STUB();
421*f005ef32Sjsg 	return -ENOSYS;
422*f005ef32Sjsg #ifdef notyet
423*f005ef32Sjsg 	struct wired_cmd_verify_repeater_in verify_repeater_in = { { 0 } };
424*f005ef32Sjsg 	struct wired_cmd_verify_repeater_out verify_repeater_out = { { 0 } };
425*f005ef32Sjsg 	struct drm_i915_private *i915;
426*f005ef32Sjsg 	ssize_t byte;
427*f005ef32Sjsg 
428*f005ef32Sjsg 	if (!dev || !rep_topology || !rep_send_ack || !data)
429*f005ef32Sjsg 		return -EINVAL;
430*f005ef32Sjsg 
431*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
432*f005ef32Sjsg 	if (!i915) {
433*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
434*f005ef32Sjsg 		return -ENODEV;
435*f005ef32Sjsg 	}
436*f005ef32Sjsg 
437*f005ef32Sjsg 	verify_repeater_in.header.api_version = HDCP_API_VERSION;
438*f005ef32Sjsg 	verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;
439*f005ef32Sjsg 	verify_repeater_in.header.status = FW_HDCP_STATUS_SUCCESS;
440*f005ef32Sjsg 	verify_repeater_in.header.buffer_len =
441*f005ef32Sjsg 					WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN;
442*f005ef32Sjsg 
443*f005ef32Sjsg 	verify_repeater_in.port.integrated_port_type = data->port_type;
444*f005ef32Sjsg 	verify_repeater_in.port.physical_port = (u8)data->hdcp_ddi;
445*f005ef32Sjsg 	verify_repeater_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
446*f005ef32Sjsg 
447*f005ef32Sjsg 	memcpy(verify_repeater_in.rx_info, rep_topology->rx_info,
448*f005ef32Sjsg 	       HDCP_2_2_RXINFO_LEN);
449*f005ef32Sjsg 	memcpy(verify_repeater_in.seq_num_v, rep_topology->seq_num_v,
450*f005ef32Sjsg 	       HDCP_2_2_SEQ_NUM_LEN);
451*f005ef32Sjsg 	memcpy(verify_repeater_in.v_prime, rep_topology->v_prime,
452*f005ef32Sjsg 	       HDCP_2_2_V_PRIME_HALF_LEN);
453*f005ef32Sjsg 	memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
454*f005ef32Sjsg 	       HDCP_2_2_RECEIVER_IDS_MAX_LEN);
455*f005ef32Sjsg 
456*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_repeater_in,
457*f005ef32Sjsg 				       sizeof(verify_repeater_in),
458*f005ef32Sjsg 				       (u8 *)&verify_repeater_out,
459*f005ef32Sjsg 				       sizeof(verify_repeater_out));
460*f005ef32Sjsg 	if (byte < 0) {
461*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
462*f005ef32Sjsg 		return byte;
463*f005ef32Sjsg 	}
464*f005ef32Sjsg 
465*f005ef32Sjsg 	if (verify_repeater_out.header.status != FW_HDCP_STATUS_SUCCESS) {
466*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
467*f005ef32Sjsg 			    WIRED_VERIFY_REPEATER,
468*f005ef32Sjsg 			    verify_repeater_out.header.status);
469*f005ef32Sjsg 		return -EIO;
470*f005ef32Sjsg 	}
471*f005ef32Sjsg 
472*f005ef32Sjsg 	memcpy(rep_send_ack->v, verify_repeater_out.v,
473*f005ef32Sjsg 	       HDCP_2_2_V_PRIME_HALF_LEN);
474*f005ef32Sjsg 	rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
475*f005ef32Sjsg 
476*f005ef32Sjsg 	return 0;
477*f005ef32Sjsg #endif
478*f005ef32Sjsg }
479*f005ef32Sjsg 
gsc_hdcp_verify_mprime(struct device * dev,struct hdcp_port_data * data,struct hdcp2_rep_stream_ready * stream_ready)480*f005ef32Sjsg static int gsc_hdcp_verify_mprime(struct device *dev,
481*f005ef32Sjsg 				  struct hdcp_port_data *data,
482*f005ef32Sjsg 				  struct hdcp2_rep_stream_ready *stream_ready)
483*f005ef32Sjsg {
484*f005ef32Sjsg 	STUB();
485*f005ef32Sjsg 	return -ENOSYS;
486*f005ef32Sjsg #ifdef notyet
487*f005ef32Sjsg 	struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
488*f005ef32Sjsg 	struct wired_cmd_repeater_auth_stream_req_out
489*f005ef32Sjsg 					verify_mprime_out = { { 0 } };
490*f005ef32Sjsg 	struct drm_i915_private *i915;
491*f005ef32Sjsg 	ssize_t byte;
492*f005ef32Sjsg 	size_t cmd_size;
493*f005ef32Sjsg 
494*f005ef32Sjsg 	if (!dev || !stream_ready || !data)
495*f005ef32Sjsg 		return -EINVAL;
496*f005ef32Sjsg 
497*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
498*f005ef32Sjsg 	if (!i915) {
499*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
500*f005ef32Sjsg 		return -ENODEV;
501*f005ef32Sjsg 	}
502*f005ef32Sjsg 
503*f005ef32Sjsg 	cmd_size = struct_size(verify_mprime_in, streams, data->k);
504*f005ef32Sjsg 	if (cmd_size == SIZE_MAX)
505*f005ef32Sjsg 		return -EINVAL;
506*f005ef32Sjsg 
507*f005ef32Sjsg 	verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
508*f005ef32Sjsg 	if (!verify_mprime_in)
509*f005ef32Sjsg 		return -ENOMEM;
510*f005ef32Sjsg 
511*f005ef32Sjsg 	verify_mprime_in->header.api_version = HDCP_API_VERSION;
512*f005ef32Sjsg 	verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
513*f005ef32Sjsg 	verify_mprime_in->header.status = FW_HDCP_STATUS_SUCCESS;
514*f005ef32Sjsg 	verify_mprime_in->header.buffer_len = cmd_size  - sizeof(verify_mprime_in->header);
515*f005ef32Sjsg 
516*f005ef32Sjsg 	verify_mprime_in->port.integrated_port_type = data->port_type;
517*f005ef32Sjsg 	verify_mprime_in->port.physical_port = (u8)data->hdcp_ddi;
518*f005ef32Sjsg 	verify_mprime_in->port.attached_transcoder = (u8)data->hdcp_transcoder;
519*f005ef32Sjsg 
520*f005ef32Sjsg 	memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, HDCP_2_2_MPRIME_LEN);
521*f005ef32Sjsg 	drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
522*f005ef32Sjsg 
523*f005ef32Sjsg 	memcpy(verify_mprime_in->streams, data->streams,
524*f005ef32Sjsg 	       array_size(data->k, sizeof(*data->streams)));
525*f005ef32Sjsg 
526*f005ef32Sjsg 	verify_mprime_in->k = cpu_to_be16(data->k);
527*f005ef32Sjsg 
528*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)verify_mprime_in, cmd_size,
529*f005ef32Sjsg 				       (u8 *)&verify_mprime_out,
530*f005ef32Sjsg 				       sizeof(verify_mprime_out));
531*f005ef32Sjsg 	kfree(verify_mprime_in);
532*f005ef32Sjsg 	if (byte < 0) {
533*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
534*f005ef32Sjsg 		return byte;
535*f005ef32Sjsg 	}
536*f005ef32Sjsg 
537*f005ef32Sjsg 	if (verify_mprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
538*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
539*f005ef32Sjsg 			    WIRED_REPEATER_AUTH_STREAM_REQ,
540*f005ef32Sjsg 			    verify_mprime_out.header.status);
541*f005ef32Sjsg 		return -EIO;
542*f005ef32Sjsg 	}
543*f005ef32Sjsg 
544*f005ef32Sjsg 	return 0;
545*f005ef32Sjsg #endif
546*f005ef32Sjsg }
547*f005ef32Sjsg 
gsc_hdcp_enable_authentication(struct device * dev,struct hdcp_port_data * data)548*f005ef32Sjsg static int gsc_hdcp_enable_authentication(struct device *dev,
549*f005ef32Sjsg 					  struct hdcp_port_data *data)
550*f005ef32Sjsg {
551*f005ef32Sjsg 	STUB();
552*f005ef32Sjsg 	return -ENOSYS;
553*f005ef32Sjsg #ifdef notyet
554*f005ef32Sjsg 	struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
555*f005ef32Sjsg 	struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
556*f005ef32Sjsg 	struct drm_i915_private *i915;
557*f005ef32Sjsg 	ssize_t byte;
558*f005ef32Sjsg 
559*f005ef32Sjsg 	if (!dev || !data)
560*f005ef32Sjsg 		return -EINVAL;
561*f005ef32Sjsg 
562*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
563*f005ef32Sjsg 	if (!i915) {
564*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
565*f005ef32Sjsg 		return -ENODEV;
566*f005ef32Sjsg 	}
567*f005ef32Sjsg 
568*f005ef32Sjsg 	enable_auth_in.header.api_version = HDCP_API_VERSION;
569*f005ef32Sjsg 	enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;
570*f005ef32Sjsg 	enable_auth_in.header.status = FW_HDCP_STATUS_SUCCESS;
571*f005ef32Sjsg 	enable_auth_in.header.buffer_len = WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN;
572*f005ef32Sjsg 
573*f005ef32Sjsg 	enable_auth_in.port.integrated_port_type = data->port_type;
574*f005ef32Sjsg 	enable_auth_in.port.physical_port = (u8)data->hdcp_ddi;
575*f005ef32Sjsg 	enable_auth_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
576*f005ef32Sjsg 	enable_auth_in.stream_type = data->streams[0].stream_type;
577*f005ef32Sjsg 
578*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&enable_auth_in,
579*f005ef32Sjsg 				       sizeof(enable_auth_in),
580*f005ef32Sjsg 				       (u8 *)&enable_auth_out,
581*f005ef32Sjsg 				       sizeof(enable_auth_out));
582*f005ef32Sjsg 	if (byte < 0) {
583*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
584*f005ef32Sjsg 		return byte;
585*f005ef32Sjsg 	}
586*f005ef32Sjsg 
587*f005ef32Sjsg 	if (enable_auth_out.header.status != FW_HDCP_STATUS_SUCCESS) {
588*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
589*f005ef32Sjsg 			    WIRED_ENABLE_AUTH, enable_auth_out.header.status);
590*f005ef32Sjsg 		return -EIO;
591*f005ef32Sjsg 	}
592*f005ef32Sjsg 
593*f005ef32Sjsg 	return 0;
594*f005ef32Sjsg #endif
595*f005ef32Sjsg }
596*f005ef32Sjsg 
597*f005ef32Sjsg static int
gsc_hdcp_close_session(struct device * dev,struct hdcp_port_data * data)598*f005ef32Sjsg gsc_hdcp_close_session(struct device *dev, struct hdcp_port_data *data)
599*f005ef32Sjsg {
600*f005ef32Sjsg 	STUB();
601*f005ef32Sjsg 	return -ENOSYS;
602*f005ef32Sjsg #ifdef notyet
603*f005ef32Sjsg 	struct wired_cmd_close_session_in session_close_in = { { 0 } };
604*f005ef32Sjsg 	struct wired_cmd_close_session_out session_close_out = { { 0 } };
605*f005ef32Sjsg 	struct drm_i915_private *i915;
606*f005ef32Sjsg 	ssize_t byte;
607*f005ef32Sjsg 
608*f005ef32Sjsg 	if (!dev || !data)
609*f005ef32Sjsg 		return -EINVAL;
610*f005ef32Sjsg 
611*f005ef32Sjsg 	i915 = kdev_to_i915(dev);
612*f005ef32Sjsg 	if (!i915) {
613*f005ef32Sjsg 		dev_err(dev, "DRM not initialized, aborting HDCP.\n");
614*f005ef32Sjsg 		return -ENODEV;
615*f005ef32Sjsg 	}
616*f005ef32Sjsg 
617*f005ef32Sjsg 	session_close_in.header.api_version = HDCP_API_VERSION;
618*f005ef32Sjsg 	session_close_in.header.command_id = WIRED_CLOSE_SESSION;
619*f005ef32Sjsg 	session_close_in.header.status = FW_HDCP_STATUS_SUCCESS;
620*f005ef32Sjsg 	session_close_in.header.buffer_len =
621*f005ef32Sjsg 				WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN;
622*f005ef32Sjsg 
623*f005ef32Sjsg 	session_close_in.port.integrated_port_type = data->port_type;
624*f005ef32Sjsg 	session_close_in.port.physical_port = (u8)data->hdcp_ddi;
625*f005ef32Sjsg 	session_close_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
626*f005ef32Sjsg 
627*f005ef32Sjsg 	byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_close_in,
628*f005ef32Sjsg 				       sizeof(session_close_in),
629*f005ef32Sjsg 				       (u8 *)&session_close_out,
630*f005ef32Sjsg 				       sizeof(session_close_out));
631*f005ef32Sjsg 	if (byte < 0) {
632*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
633*f005ef32Sjsg 		return byte;
634*f005ef32Sjsg 	}
635*f005ef32Sjsg 
636*f005ef32Sjsg 	if (session_close_out.header.status != FW_HDCP_STATUS_SUCCESS) {
637*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "Session Close Failed. status: 0x%X\n",
638*f005ef32Sjsg 			    session_close_out.header.status);
639*f005ef32Sjsg 		return -EIO;
640*f005ef32Sjsg 	}
641*f005ef32Sjsg 
642*f005ef32Sjsg 	return 0;
643*f005ef32Sjsg #endif
644*f005ef32Sjsg }
645*f005ef32Sjsg 
646*f005ef32Sjsg static const struct i915_hdcp_ops gsc_hdcp_ops = {
647*f005ef32Sjsg 	.initiate_hdcp2_session = gsc_hdcp_initiate_session,
648*f005ef32Sjsg 	.verify_receiver_cert_prepare_km =
649*f005ef32Sjsg 				gsc_hdcp_verify_receiver_cert_prepare_km,
650*f005ef32Sjsg 	.verify_hprime = gsc_hdcp_verify_hprime,
651*f005ef32Sjsg 	.store_pairing_info = gsc_hdcp_store_pairing_info,
652*f005ef32Sjsg 	.initiate_locality_check = gsc_hdcp_initiate_locality_check,
653*f005ef32Sjsg 	.verify_lprime = gsc_hdcp_verify_lprime,
654*f005ef32Sjsg 	.get_session_key = gsc_hdcp_get_session_key,
655*f005ef32Sjsg 	.repeater_check_flow_prepare_ack =
656*f005ef32Sjsg 				gsc_hdcp_repeater_check_flow_prepare_ack,
657*f005ef32Sjsg 	.verify_mprime = gsc_hdcp_verify_mprime,
658*f005ef32Sjsg 	.enable_hdcp_authentication = gsc_hdcp_enable_authentication,
659*f005ef32Sjsg 	.close_hdcp_session = gsc_hdcp_close_session,
660*f005ef32Sjsg };
661*f005ef32Sjsg 
662*f005ef32Sjsg /*This function helps allocate memory for the command that we will send to gsc cs */
intel_hdcp_gsc_initialize_message(struct drm_i915_private * i915,struct intel_hdcp_gsc_message * hdcp_message)663*f005ef32Sjsg static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915,
664*f005ef32Sjsg 					     struct intel_hdcp_gsc_message *hdcp_message)
665*f005ef32Sjsg {
666*f005ef32Sjsg 	struct intel_gt *gt = i915->media_gt;
667*f005ef32Sjsg 	struct drm_i915_gem_object *obj = NULL;
668*f005ef32Sjsg 	struct i915_vma *vma = NULL;
669*f005ef32Sjsg 	void *cmd_in, *cmd_out;
670*f005ef32Sjsg 	int err;
671*f005ef32Sjsg 
672*f005ef32Sjsg 	/* allocate object of two page for HDCP command memory and store it */
673*f005ef32Sjsg 	obj = i915_gem_object_create_shmem(i915, 2 * PAGE_SIZE);
674*f005ef32Sjsg 
675*f005ef32Sjsg 	if (IS_ERR(obj)) {
676*f005ef32Sjsg 		drm_err(&i915->drm, "Failed to allocate HDCP streaming command!\n");
677*f005ef32Sjsg 		return PTR_ERR(obj);
678*f005ef32Sjsg 	}
679*f005ef32Sjsg 
680*f005ef32Sjsg 	cmd_in = i915_gem_object_pin_map_unlocked(obj, intel_gt_coherent_map_type(gt, obj, true));
681*f005ef32Sjsg 	if (IS_ERR(cmd_in)) {
682*f005ef32Sjsg 		drm_err(&i915->drm, "Failed to map gsc message page!\n");
683*f005ef32Sjsg 		err = PTR_ERR(cmd_in);
684*f005ef32Sjsg 		goto out_unpin;
685*f005ef32Sjsg 	}
686*f005ef32Sjsg 
687*f005ef32Sjsg 	cmd_out = cmd_in + PAGE_SIZE;
688*f005ef32Sjsg 
689*f005ef32Sjsg 	vma = i915_vma_instance(obj, &gt->ggtt->vm, NULL);
690*f005ef32Sjsg 	if (IS_ERR(vma)) {
691*f005ef32Sjsg 		err = PTR_ERR(vma);
692*f005ef32Sjsg 		goto out_unmap;
693*f005ef32Sjsg 	}
694*f005ef32Sjsg 
695*f005ef32Sjsg 	err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
696*f005ef32Sjsg 	if (err)
697*f005ef32Sjsg 		goto out_unmap;
698*f005ef32Sjsg 
699*f005ef32Sjsg 	memset(cmd_in, 0, obj->base.size);
700*f005ef32Sjsg 
701*f005ef32Sjsg 	hdcp_message->hdcp_cmd_in = cmd_in;
702*f005ef32Sjsg 	hdcp_message->hdcp_cmd_out = cmd_out;
703*f005ef32Sjsg 	hdcp_message->vma = vma;
704*f005ef32Sjsg 
705*f005ef32Sjsg 	return 0;
706*f005ef32Sjsg 
707*f005ef32Sjsg out_unmap:
708*f005ef32Sjsg 	i915_gem_object_unpin_map(obj);
709*f005ef32Sjsg out_unpin:
710*f005ef32Sjsg 	i915_gem_object_put(obj);
711*f005ef32Sjsg 	return err;
712*f005ef32Sjsg }
713*f005ef32Sjsg 
intel_hdcp_gsc_hdcp2_init(struct drm_i915_private * i915)714*f005ef32Sjsg static int intel_hdcp_gsc_hdcp2_init(struct drm_i915_private *i915)
715*f005ef32Sjsg {
716*f005ef32Sjsg 	struct intel_hdcp_gsc_message *hdcp_message;
717*f005ef32Sjsg 	int ret;
718*f005ef32Sjsg 
719*f005ef32Sjsg 	hdcp_message = kzalloc(sizeof(*hdcp_message), GFP_KERNEL);
720*f005ef32Sjsg 
721*f005ef32Sjsg 	if (!hdcp_message)
722*f005ef32Sjsg 		return -ENOMEM;
723*f005ef32Sjsg 
724*f005ef32Sjsg 	/*
725*f005ef32Sjsg 	 * NOTE: No need to lock the comp mutex here as it is already
726*f005ef32Sjsg 	 * going to be taken before this function called
727*f005ef32Sjsg 	 */
728*f005ef32Sjsg 	i915->display.hdcp.hdcp_message = hdcp_message;
729*f005ef32Sjsg 	ret = intel_hdcp_gsc_initialize_message(i915, hdcp_message);
730*f005ef32Sjsg 
731*f005ef32Sjsg 	if (ret)
732*f005ef32Sjsg 		drm_err(&i915->drm, "Could not initialize hdcp_message\n");
733*f005ef32Sjsg 
734*f005ef32Sjsg 	return ret;
735*f005ef32Sjsg }
736*f005ef32Sjsg 
intel_hdcp_gsc_free_message(struct drm_i915_private * i915)737*f005ef32Sjsg static void intel_hdcp_gsc_free_message(struct drm_i915_private *i915)
738*f005ef32Sjsg {
739*f005ef32Sjsg 	struct intel_hdcp_gsc_message *hdcp_message =
740*f005ef32Sjsg 					i915->display.hdcp.hdcp_message;
741*f005ef32Sjsg 
742*f005ef32Sjsg 	hdcp_message->hdcp_cmd_in = NULL;
743*f005ef32Sjsg 	hdcp_message->hdcp_cmd_out = NULL;
744*f005ef32Sjsg 	i915_vma_unpin_and_release(&hdcp_message->vma, I915_VMA_RELEASE_MAP);
745*f005ef32Sjsg 	kfree(hdcp_message);
746*f005ef32Sjsg }
747*f005ef32Sjsg 
intel_hdcp_gsc_init(struct drm_i915_private * i915)748*f005ef32Sjsg int intel_hdcp_gsc_init(struct drm_i915_private *i915)
749*f005ef32Sjsg {
750*f005ef32Sjsg 	struct i915_hdcp_arbiter *data;
751*f005ef32Sjsg 	int ret;
752*f005ef32Sjsg 
753*f005ef32Sjsg 	data = kzalloc(sizeof(struct i915_hdcp_arbiter), GFP_KERNEL);
754*f005ef32Sjsg 	if (!data)
755*f005ef32Sjsg 		return -ENOMEM;
756*f005ef32Sjsg 
757*f005ef32Sjsg 	mutex_lock(&i915->display.hdcp.hdcp_mutex);
758*f005ef32Sjsg 	i915->display.hdcp.arbiter = data;
759*f005ef32Sjsg 	i915->display.hdcp.arbiter->hdcp_dev = i915->drm.dev;
760*f005ef32Sjsg 	i915->display.hdcp.arbiter->ops = &gsc_hdcp_ops;
761*f005ef32Sjsg 	ret = intel_hdcp_gsc_hdcp2_init(i915);
762*f005ef32Sjsg 	mutex_unlock(&i915->display.hdcp.hdcp_mutex);
763*f005ef32Sjsg 
764*f005ef32Sjsg 	return ret;
765*f005ef32Sjsg }
766*f005ef32Sjsg 
intel_hdcp_gsc_fini(struct drm_i915_private * i915)767*f005ef32Sjsg void intel_hdcp_gsc_fini(struct drm_i915_private *i915)
768*f005ef32Sjsg {
769*f005ef32Sjsg 	intel_hdcp_gsc_free_message(i915);
770*f005ef32Sjsg 	kfree(i915->display.hdcp.arbiter);
771*f005ef32Sjsg }
772*f005ef32Sjsg 
intel_gsc_send_sync(struct drm_i915_private * i915,struct intel_gsc_mtl_header * header_in,struct intel_gsc_mtl_header * header_out,u64 addr_in,u64 addr_out,size_t msg_out_len)773*f005ef32Sjsg static int intel_gsc_send_sync(struct drm_i915_private *i915,
774*f005ef32Sjsg 			       struct intel_gsc_mtl_header *header_in,
775*f005ef32Sjsg 			       struct intel_gsc_mtl_header *header_out,
776*f005ef32Sjsg 			       u64 addr_in, u64 addr_out,
777*f005ef32Sjsg 			       size_t msg_out_len)
778*f005ef32Sjsg {
779*f005ef32Sjsg 	struct intel_gt *gt = i915->media_gt;
780*f005ef32Sjsg 	int ret;
781*f005ef32Sjsg 
782*f005ef32Sjsg 	ret = intel_gsc_uc_heci_cmd_submit_packet(&gt->uc.gsc, addr_in,
783*f005ef32Sjsg 						  header_in->message_size,
784*f005ef32Sjsg 						  addr_out,
785*f005ef32Sjsg 						  msg_out_len + sizeof(*header_out));
786*f005ef32Sjsg 	if (ret) {
787*f005ef32Sjsg 		drm_err(&i915->drm, "failed to send gsc HDCP msg (%d)\n", ret);
788*f005ef32Sjsg 		return ret;
789*f005ef32Sjsg 	}
790*f005ef32Sjsg 
791*f005ef32Sjsg 	/*
792*f005ef32Sjsg 	 * Checking validity marker and header status to see if some error has
793*f005ef32Sjsg 	 * blocked us from sending message to gsc cs
794*f005ef32Sjsg 	 */
795*f005ef32Sjsg 	if (header_out->validity_marker != GSC_HECI_VALIDITY_MARKER) {
796*f005ef32Sjsg 		drm_err(&i915->drm, "invalid validity marker\n");
797*f005ef32Sjsg 		return -EINVAL;
798*f005ef32Sjsg 	}
799*f005ef32Sjsg 
800*f005ef32Sjsg 	if (header_out->status != 0) {
801*f005ef32Sjsg 		drm_err(&i915->drm, "header status indicates error %d\n",
802*f005ef32Sjsg 			header_out->status);
803*f005ef32Sjsg 		return -EINVAL;
804*f005ef32Sjsg 	}
805*f005ef32Sjsg 
806*f005ef32Sjsg 	if (header_out->flags & GSC_OUTFLAG_MSG_PENDING) {
807*f005ef32Sjsg 		header_in->gsc_message_handle = header_out->gsc_message_handle;
808*f005ef32Sjsg 		return -EAGAIN;
809*f005ef32Sjsg 	}
810*f005ef32Sjsg 
811*f005ef32Sjsg 	return 0;
812*f005ef32Sjsg }
813*f005ef32Sjsg 
814*f005ef32Sjsg /*
815*f005ef32Sjsg  * This function can now be used for sending requests and will also handle
816*f005ef32Sjsg  * receipt of reply messages hence no different function of message retrieval
817*f005ef32Sjsg  * is required. We will initialize intel_hdcp_gsc_message structure then add
818*f005ef32Sjsg  * gsc cs memory header as stated in specs after which the normal HDCP payload
819*f005ef32Sjsg  * will follow
820*f005ef32Sjsg  */
intel_hdcp_gsc_msg_send(struct drm_i915_private * i915,u8 * msg_in,size_t msg_in_len,u8 * msg_out,size_t msg_out_len)821*f005ef32Sjsg ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
822*f005ef32Sjsg 				size_t msg_in_len, u8 *msg_out,
823*f005ef32Sjsg 				size_t msg_out_len)
824*f005ef32Sjsg {
825*f005ef32Sjsg 	struct intel_gt *gt = i915->media_gt;
826*f005ef32Sjsg 	struct intel_gsc_mtl_header *header_in, *header_out;
827*f005ef32Sjsg 	const size_t max_msg_size = PAGE_SIZE - sizeof(*header_in);
828*f005ef32Sjsg 	struct intel_hdcp_gsc_message *hdcp_message;
829*f005ef32Sjsg 	u64 addr_in, addr_out, host_session_id;
830*f005ef32Sjsg 	u32 reply_size, msg_size_in, msg_size_out;
831*f005ef32Sjsg 	int ret, tries = 0;
832*f005ef32Sjsg 
833*f005ef32Sjsg 	if (!intel_uc_uses_gsc_uc(&gt->uc))
834*f005ef32Sjsg 		return -ENODEV;
835*f005ef32Sjsg 
836*f005ef32Sjsg 	if (msg_in_len > max_msg_size || msg_out_len > max_msg_size)
837*f005ef32Sjsg 		return -ENOSPC;
838*f005ef32Sjsg 
839*f005ef32Sjsg 	msg_size_in = msg_in_len + sizeof(*header_in);
840*f005ef32Sjsg 	msg_size_out = msg_out_len + sizeof(*header_out);
841*f005ef32Sjsg 	hdcp_message = i915->display.hdcp.hdcp_message;
842*f005ef32Sjsg 	header_in = hdcp_message->hdcp_cmd_in;
843*f005ef32Sjsg 	header_out = hdcp_message->hdcp_cmd_out;
844*f005ef32Sjsg 	addr_in = i915_ggtt_offset(hdcp_message->vma);
845*f005ef32Sjsg 	addr_out = addr_in + PAGE_SIZE;
846*f005ef32Sjsg 
847*f005ef32Sjsg 	memset(header_in, 0, msg_size_in);
848*f005ef32Sjsg 	memset(header_out, 0, msg_size_out);
849*f005ef32Sjsg 	get_random_bytes(&host_session_id, sizeof(u64));
850*f005ef32Sjsg 	intel_gsc_uc_heci_cmd_emit_mtl_header(header_in, HECI_MEADDRESS_HDCP,
851*f005ef32Sjsg 					      msg_size_in, host_session_id);
852*f005ef32Sjsg 	memcpy(hdcp_message->hdcp_cmd_in + sizeof(*header_in), msg_in, msg_in_len);
853*f005ef32Sjsg 
854*f005ef32Sjsg 	/*
855*f005ef32Sjsg 	 * Keep sending request in case the pending bit is set no need to add
856*f005ef32Sjsg 	 * message handle as we are using same address hence loc. of header is
857*f005ef32Sjsg 	 * same and it will contain the message handle. we will send the message
858*f005ef32Sjsg 	 * 20 times each message 50 ms apart
859*f005ef32Sjsg 	 */
860*f005ef32Sjsg 	do {
861*f005ef32Sjsg 		ret = intel_gsc_send_sync(i915, header_in, header_out, addr_in,
862*f005ef32Sjsg 					  addr_out, msg_out_len);
863*f005ef32Sjsg 
864*f005ef32Sjsg 		/* Only try again if gsc says so */
865*f005ef32Sjsg 		if (ret != -EAGAIN)
866*f005ef32Sjsg 			break;
867*f005ef32Sjsg 
868*f005ef32Sjsg 		drm_msleep(50);
869*f005ef32Sjsg 
870*f005ef32Sjsg 	} while (++tries < 20);
871*f005ef32Sjsg 
872*f005ef32Sjsg 	if (ret)
873*f005ef32Sjsg 		goto err;
874*f005ef32Sjsg 
875*f005ef32Sjsg 	/* we use the same mem for the reply, so header is in the same loc */
876*f005ef32Sjsg 	reply_size = header_out->message_size - sizeof(*header_out);
877*f005ef32Sjsg 	if (reply_size > msg_out_len) {
878*f005ef32Sjsg 		drm_warn(&i915->drm, "caller with insufficient HDCP reply size %u (%d)\n",
879*f005ef32Sjsg 			 reply_size, (u32)msg_out_len);
880*f005ef32Sjsg 		reply_size = msg_out_len;
881*f005ef32Sjsg 	} else if (reply_size != msg_out_len) {
882*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "caller unexpected HCDP reply size %u (%d)\n",
883*f005ef32Sjsg 			    reply_size, (u32)msg_out_len);
884*f005ef32Sjsg 	}
885*f005ef32Sjsg 
886*f005ef32Sjsg 	memcpy(msg_out, hdcp_message->hdcp_cmd_out + sizeof(*header_out), msg_out_len);
887*f005ef32Sjsg 
888*f005ef32Sjsg err:
889*f005ef32Sjsg 	return ret;
890*f005ef32Sjsg }
891