xref: /openbsd-src/sys/dev/pci/drm/amd/display/modules/hdcp/hdcp_ddc.c (revision c1a45aed656e7d5627c30c92421893a76f370ccb)
1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include "hdcp.h"
27 
28 #ifdef __linux__
29 #define MIN(a, b) ((a) < (b) ? (a) : (b))
30 #endif
31 #define HDCP_I2C_ADDR 0x3a	/* 0x74 >> 1*/
32 #define KSV_READ_SIZE 0xf	/* 0x6803b - 0x6802c */
33 #define HDCP_MAX_AUX_TRANSACTION_SIZE 16
34 
35 #define DP_CP_IRQ (1 << 2)
36 
37 enum mod_hdcp_ddc_message_id {
38 	MOD_HDCP_MESSAGE_ID_INVALID = -1,
39 
40 	/* HDCP 1.4 */
41 
42 	MOD_HDCP_MESSAGE_ID_READ_BKSV = 0,
43 	MOD_HDCP_MESSAGE_ID_READ_RI_R0,
44 	MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
45 	MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
46 	MOD_HDCP_MESSAGE_ID_WRITE_AN,
47 	MOD_HDCP_MESSAGE_ID_READ_VH_X,
48 	MOD_HDCP_MESSAGE_ID_READ_VH_0,
49 	MOD_HDCP_MESSAGE_ID_READ_VH_1,
50 	MOD_HDCP_MESSAGE_ID_READ_VH_2,
51 	MOD_HDCP_MESSAGE_ID_READ_VH_3,
52 	MOD_HDCP_MESSAGE_ID_READ_VH_4,
53 	MOD_HDCP_MESSAGE_ID_READ_BCAPS,
54 	MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
55 	MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
56 	MOD_HDCP_MESSAGE_ID_READ_BINFO,
57 
58 	/* HDCP 2.2 */
59 
60 	MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
61 	MOD_HDCP_MESSAGE_ID_RX_CAPS,
62 	MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
63 	MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
64 	MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
65 	MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
66 	MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
67 	MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
68 	MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
69 	MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
70 	MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
71 	MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
72 	MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
73 	MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
74 	MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
75 	MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
76 	MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
77 	MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
78 
79 	MOD_HDCP_MESSAGE_ID_MAX
80 };
81 
82 static const uint8_t hdcp_i2c_offsets[] = {
83 	[MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
84 	[MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
85 	[MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
86 	[MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
87 	[MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
88 	[MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
89 	[MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
90 	[MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
91 	[MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
92 	[MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
93 	[MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
94 	[MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
95 	[MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
96 	[MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
97 	[MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
98 	[MOD_HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
99 	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
100 	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
101 	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
102 	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
103 	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
104 	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
105 	[MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
106 	[MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
107 	[MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
108 	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
109 	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x80,
110 	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
111 	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
112 	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
113 	[MOD_HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
114 	[MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0
115 };
116 
117 static const uint32_t hdcp_dpcd_addrs[] = {
118 	[MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
119 	[MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
120 	[MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
121 	[MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
122 	[MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
123 	[MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
124 	[MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
125 	[MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
126 	[MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
127 	[MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
128 	[MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
129 	[MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
130 	[MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
131 	[MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
132 	[MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
133 	[MOD_HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
134 	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
135 	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
136 	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
137 	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
138 	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
139 	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
140 	[MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
141 	[MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
142 	[MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
143 	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
144 	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x69340,
145 	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
146 	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
147 	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
148 	[MOD_HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
149 	[MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
150 };
151 
152 static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
153 		enum mod_hdcp_ddc_message_id msg_id,
154 		uint8_t *buf,
155 		uint32_t buf_len)
156 {
157 	bool success = true;
158 	uint32_t cur_size = 0;
159 	uint32_t data_offset = 0;
160 
161 	if (is_dp_hdcp(hdcp)) {
162 		while (buf_len > 0) {
163 			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
164 			success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
165 					hdcp_dpcd_addrs[msg_id] + data_offset,
166 					buf + data_offset,
167 					cur_size);
168 
169 			if (!success)
170 				break;
171 
172 			buf_len -= cur_size;
173 			data_offset += cur_size;
174 		}
175 	} else {
176 		success = hdcp->config.ddc.funcs.read_i2c(
177 				hdcp->config.ddc.handle,
178 				HDCP_I2C_ADDR,
179 				hdcp_i2c_offsets[msg_id],
180 				buf,
181 				(uint32_t)buf_len);
182 	}
183 
184 	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
185 }
186 
187 static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp,
188 		enum mod_hdcp_ddc_message_id msg_id,
189 		uint8_t *buf,
190 		uint32_t buf_len,
191 		uint8_t read_size)
192 {
193 	enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE;
194 	uint32_t cur_size = 0;
195 	uint32_t data_offset = 0;
196 
197 	while (buf_len > 0) {
198 		cur_size = MIN(buf_len, read_size);
199 		status = read(hdcp, msg_id, buf + data_offset, cur_size);
200 
201 		if (status != MOD_HDCP_STATUS_SUCCESS)
202 			break;
203 
204 		buf_len -= cur_size;
205 		data_offset += cur_size;
206 	}
207 
208 	return status;
209 }
210 
211 static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
212 		enum mod_hdcp_ddc_message_id msg_id,
213 		uint8_t *buf,
214 		uint32_t buf_len)
215 {
216 	bool success = true;
217 	uint32_t cur_size = 0;
218 	uint32_t data_offset = 0;
219 
220 	if (is_dp_hdcp(hdcp)) {
221 		while (buf_len > 0) {
222 			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
223 			success = hdcp->config.ddc.funcs.write_dpcd(
224 					hdcp->config.ddc.handle,
225 					hdcp_dpcd_addrs[msg_id] + data_offset,
226 					buf + data_offset,
227 					cur_size);
228 
229 			if (!success)
230 				break;
231 
232 			buf_len -= cur_size;
233 			data_offset += cur_size;
234 		}
235 	} else {
236 		hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
237 		memmove(&hdcp->buf[1], buf, buf_len);
238 		success = hdcp->config.ddc.funcs.write_i2c(
239 				hdcp->config.ddc.handle,
240 				HDCP_I2C_ADDR,
241 				hdcp->buf,
242 				(uint32_t)(buf_len+1));
243 	}
244 
245 	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
246 }
247 
248 enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp)
249 {
250 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV,
251 			hdcp->auth.msg.hdcp1.bksv,
252 			sizeof(hdcp->auth.msg.hdcp1.bksv));
253 }
254 
255 enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp)
256 {
257 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS,
258 			&hdcp->auth.msg.hdcp1.bcaps,
259 			sizeof(hdcp->auth.msg.hdcp1.bcaps));
260 }
261 
262 enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp)
263 {
264 	enum mod_hdcp_status status;
265 
266 	if (is_dp_hdcp(hdcp))
267 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
268 					(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
269 					1);
270 	else
271 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
272 				(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
273 				sizeof(hdcp->auth.msg.hdcp1.bstatus));
274 	return status;
275 }
276 
277 enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp)
278 {
279 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0,
280 			(uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
281 			sizeof(hdcp->auth.msg.hdcp1.r0p));
282 }
283 
284 /* special case, reading repeatedly at the same address, don't use read() */
285 enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp)
286 {
287 	enum mod_hdcp_status status;
288 
289 	if (is_dp_hdcp(hdcp))
290 		status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
291 				hdcp->auth.msg.hdcp1.ksvlist,
292 				hdcp->auth.msg.hdcp1.ksvlist_size,
293 				KSV_READ_SIZE);
294 	else
295 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
296 				(uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist,
297 				hdcp->auth.msg.hdcp1.ksvlist_size);
298 	return status;
299 }
300 
301 enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp)
302 {
303 	enum mod_hdcp_status status;
304 
305 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0,
306 			&hdcp->auth.msg.hdcp1.vp[0], 4);
307 	if (status != MOD_HDCP_STATUS_SUCCESS)
308 		goto out;
309 
310 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1,
311 			&hdcp->auth.msg.hdcp1.vp[4], 4);
312 	if (status != MOD_HDCP_STATUS_SUCCESS)
313 		goto out;
314 
315 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2,
316 			&hdcp->auth.msg.hdcp1.vp[8], 4);
317 	if (status != MOD_HDCP_STATUS_SUCCESS)
318 		goto out;
319 
320 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3,
321 			&hdcp->auth.msg.hdcp1.vp[12], 4);
322 	if (status != MOD_HDCP_STATUS_SUCCESS)
323 		goto out;
324 
325 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4,
326 			&hdcp->auth.msg.hdcp1.vp[16], 4);
327 out:
328 	return status;
329 }
330 
331 enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp)
332 {
333 	enum mod_hdcp_status status;
334 
335 	if (is_dp_hdcp(hdcp))
336 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO,
337 				(uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
338 				sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
339 	else
340 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
341 
342 	return status;
343 }
344 
345 enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp)
346 {
347 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
348 			hdcp->auth.msg.hdcp1.aksv,
349 			sizeof(hdcp->auth.msg.hdcp1.aksv));
350 }
351 
352 enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp)
353 {
354 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
355 			&hdcp->auth.msg.hdcp1.ainfo,
356 			sizeof(hdcp->auth.msg.hdcp1.ainfo));
357 }
358 
359 enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp)
360 {
361 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN,
362 			hdcp->auth.msg.hdcp1.an,
363 			sizeof(hdcp->auth.msg.hdcp1.an));
364 }
365 
366 enum mod_hdcp_status mod_hdcp_read_hdcp2version(struct mod_hdcp *hdcp)
367 {
368 	enum mod_hdcp_status status;
369 
370 	if (is_dp_hdcp(hdcp))
371 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
372 	else
373 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
374 				&hdcp->auth.msg.hdcp2.hdcp2version_hdmi,
375 				sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi));
376 
377 	return status;
378 }
379 
380 enum mod_hdcp_status mod_hdcp_read_rxcaps(struct mod_hdcp *hdcp)
381 {
382 	enum mod_hdcp_status status;
383 
384 	if (!is_dp_hdcp(hdcp))
385 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
386 	else
387 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_RX_CAPS,
388 				hdcp->auth.msg.hdcp2.rxcaps_dp,
389 				sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp));
390 
391 	return status;
392 }
393 
394 enum mod_hdcp_status mod_hdcp_read_rxstatus(struct mod_hdcp *hdcp)
395 {
396 	enum mod_hdcp_status status;
397 
398 	if (is_dp_hdcp(hdcp)) {
399 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
400 				&hdcp->auth.msg.hdcp2.rxstatus_dp,
401 				1);
402 	} else {
403 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
404 					(uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus,
405 					sizeof(hdcp->auth.msg.hdcp2.rxstatus));
406 	}
407 	return status;
408 }
409 
410 enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp)
411 {
412 	enum mod_hdcp_status status;
413 
414 	if (is_dp_hdcp(hdcp)) {
415 		hdcp->auth.msg.hdcp2.ake_cert[0] = HDCP_2_2_AKE_SEND_CERT;
416 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
417 				hdcp->auth.msg.hdcp2.ake_cert+1,
418 				sizeof(hdcp->auth.msg.hdcp2.ake_cert)-1);
419 
420 	} else {
421 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
422 					hdcp->auth.msg.hdcp2.ake_cert,
423 					sizeof(hdcp->auth.msg.hdcp2.ake_cert));
424 	}
425 	return status;
426 }
427 
428 enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp)
429 {
430 	enum mod_hdcp_status status;
431 
432 	if (is_dp_hdcp(hdcp)) {
433 		hdcp->auth.msg.hdcp2.ake_h_prime[0] = HDCP_2_2_AKE_SEND_HPRIME;
434 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
435 				hdcp->auth.msg.hdcp2.ake_h_prime+1,
436 				sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)-1);
437 
438 	} else {
439 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
440 				hdcp->auth.msg.hdcp2.ake_h_prime,
441 				sizeof(hdcp->auth.msg.hdcp2.ake_h_prime));
442 	}
443 	return status;
444 }
445 
446 enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp)
447 {
448 	enum mod_hdcp_status status;
449 
450 	if (is_dp_hdcp(hdcp)) {
451 		hdcp->auth.msg.hdcp2.ake_pairing_info[0] = HDCP_2_2_AKE_SEND_PAIRING_INFO;
452 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
453 				hdcp->auth.msg.hdcp2.ake_pairing_info+1,
454 				sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)-1);
455 
456 	} else {
457 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
458 				hdcp->auth.msg.hdcp2.ake_pairing_info,
459 				sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info));
460 	}
461 	return status;
462 }
463 
464 enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp)
465 {
466 	enum mod_hdcp_status status;
467 
468 	if (is_dp_hdcp(hdcp)) {
469 		hdcp->auth.msg.hdcp2.lc_l_prime[0] = HDCP_2_2_LC_SEND_LPRIME;
470 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
471 				hdcp->auth.msg.hdcp2.lc_l_prime+1,
472 				sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)-1);
473 
474 	} else {
475 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
476 				hdcp->auth.msg.hdcp2.lc_l_prime,
477 				sizeof(hdcp->auth.msg.hdcp2.lc_l_prime));
478 	}
479 	return status;
480 }
481 
482 enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp)
483 {
484 	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
485 
486 	if (is_dp_hdcp(hdcp)) {
487 		uint32_t device_count = 0;
488 		uint32_t rx_id_list_size = 0;
489 		uint32_t bytes_read = 0;
490 
491 		hdcp->auth.msg.hdcp2.rx_id_list[0] = HDCP_2_2_REP_SEND_RECVID_LIST;
492 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
493 						hdcp->auth.msg.hdcp2.rx_id_list+1,
494 						HDCP_MAX_AUX_TRANSACTION_SIZE);
495 		if (status == MOD_HDCP_STATUS_SUCCESS) {
496 			bytes_read = HDCP_MAX_AUX_TRANSACTION_SIZE;
497 			device_count = HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) +
498 					(HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4);
499 			rx_id_list_size = MIN((21 + 5 * device_count),
500 					(sizeof(hdcp->auth.msg.hdcp2.rx_id_list) - 1));
501 			status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
502 					hdcp->auth.msg.hdcp2.rx_id_list + 1 + bytes_read,
503 					(rx_id_list_size - 1) / HDCP_MAX_AUX_TRANSACTION_SIZE * HDCP_MAX_AUX_TRANSACTION_SIZE);
504 		}
505 	} else {
506 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
507 				hdcp->auth.msg.hdcp2.rx_id_list,
508 				hdcp->auth.msg.hdcp2.rx_id_list_size);
509 	}
510 	return status;
511 }
512 
513 enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp)
514 {
515 	enum mod_hdcp_status status;
516 
517 	if (is_dp_hdcp(hdcp)) {
518 		hdcp->auth.msg.hdcp2.repeater_auth_stream_ready[0] = HDCP_2_2_REP_STREAM_READY;
519 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
520 				hdcp->auth.msg.hdcp2.repeater_auth_stream_ready+1,
521 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)-1);
522 
523 	} else {
524 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
525 				hdcp->auth.msg.hdcp2.repeater_auth_stream_ready,
526 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready));
527 	}
528 	return status;
529 }
530 
531 enum mod_hdcp_status mod_hdcp_write_ake_init(struct mod_hdcp *hdcp)
532 {
533 	enum mod_hdcp_status status;
534 
535 	if (is_dp_hdcp(hdcp))
536 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
537 				hdcp->auth.msg.hdcp2.ake_init+1,
538 				sizeof(hdcp->auth.msg.hdcp2.ake_init)-1);
539 	else
540 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
541 					hdcp->auth.msg.hdcp2.ake_init,
542 					sizeof(hdcp->auth.msg.hdcp2.ake_init));
543 	return status;
544 }
545 
546 enum mod_hdcp_status mod_hdcp_write_no_stored_km(struct mod_hdcp *hdcp)
547 {
548 	enum mod_hdcp_status status;
549 
550 	if (is_dp_hdcp(hdcp))
551 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
552 				hdcp->auth.msg.hdcp2.ake_no_stored_km+1,
553 				sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)-1);
554 	else
555 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
556 			hdcp->auth.msg.hdcp2.ake_no_stored_km,
557 			sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km));
558 	return status;
559 }
560 
561 enum mod_hdcp_status mod_hdcp_write_stored_km(struct mod_hdcp *hdcp)
562 {
563 	enum mod_hdcp_status status;
564 
565 	if (is_dp_hdcp(hdcp))
566 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
567 				hdcp->auth.msg.hdcp2.ake_stored_km+1,
568 				sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)-1);
569 	else
570 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
571 				hdcp->auth.msg.hdcp2.ake_stored_km,
572 				sizeof(hdcp->auth.msg.hdcp2.ake_stored_km));
573 	return status;
574 }
575 
576 enum mod_hdcp_status mod_hdcp_write_lc_init(struct mod_hdcp *hdcp)
577 {
578 	enum mod_hdcp_status status;
579 
580 	if (is_dp_hdcp(hdcp))
581 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
582 				hdcp->auth.msg.hdcp2.lc_init+1,
583 				sizeof(hdcp->auth.msg.hdcp2.lc_init)-1);
584 	else
585 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
586 				hdcp->auth.msg.hdcp2.lc_init,
587 				sizeof(hdcp->auth.msg.hdcp2.lc_init));
588 	return status;
589 }
590 
591 enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp)
592 {
593 	enum mod_hdcp_status status;
594 
595 	if (is_dp_hdcp(hdcp))
596 		status = write(hdcp,
597 				MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
598 				hdcp->auth.msg.hdcp2.ske_eks+1,
599 				sizeof(hdcp->auth.msg.hdcp2.ske_eks)-1);
600 	else
601 		status = write(hdcp,
602 			MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
603 			hdcp->auth.msg.hdcp2.ske_eks,
604 			sizeof(hdcp->auth.msg.hdcp2.ske_eks));
605 	return status;
606 }
607 
608 enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp)
609 {
610 	enum mod_hdcp_status status;
611 
612 	if (is_dp_hdcp(hdcp))
613 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
614 				hdcp->auth.msg.hdcp2.repeater_auth_ack+1,
615 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)-1);
616 	else
617 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
618 				hdcp->auth.msg.hdcp2.repeater_auth_ack,
619 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack));
620 	return status;
621 }
622 
623 enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp)
624 {
625 	enum mod_hdcp_status status;
626 
627 	if (is_dp_hdcp(hdcp))
628 		status = write(hdcp,
629 				MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
630 				hdcp->auth.msg.hdcp2.repeater_auth_stream_manage+1,
631 				hdcp->auth.msg.hdcp2.stream_manage_size-1);
632 	else
633 		status = write(hdcp,
634 				MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
635 				hdcp->auth.msg.hdcp2.repeater_auth_stream_manage,
636 				hdcp->auth.msg.hdcp2.stream_manage_size);
637 	return status;
638 }
639 
640 enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp)
641 {
642 	enum mod_hdcp_status status;
643 
644 	if (is_dp_hdcp(hdcp))
645 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
646 				hdcp->auth.msg.hdcp2.content_stream_type_dp+1,
647 				sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp)-1);
648 	else
649 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
650 	return status;
651 }
652 
653 enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp)
654 {
655 	uint8_t clear_cp_irq_bit = DP_CP_IRQ;
656 	uint32_t size = 1;
657 
658 	if (is_dp_hdcp(hdcp)) {
659 		uint32_t cp_irq_addrs = (hdcp->connection.link.dp.rev >= 0x14)
660 				? DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0:DP_DEVICE_SERVICE_IRQ_VECTOR;
661 		return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, cp_irq_addrs,
662 				&clear_cp_irq_bit, size) ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
663 	}
664 
665 	return MOD_HDCP_STATUS_INVALID_OPERATION;
666 }
667