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