xref: /linux/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c (revision d40981350844c2cfa437abfc80596e10ea8f1149)
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 		msg_id >= MOD_HDCP_MESSAGE_ID_MAX)
161 		return MOD_HDCP_STATUS_DDC_FAILURE;
162 
163 	if (is_dp_hdcp(hdcp)) {
164 		int num_dpcd_addrs = ARRAY_SIZE(hdcp_dpcd_addrs);
165 		if (msg_id >= num_dpcd_addrs)
166 			return MOD_HDCP_STATUS_DDC_FAILURE;
167 
168 		while (buf_len > 0) {
169 			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
170 			success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
171 					hdcp_dpcd_addrs[msg_id] + data_offset,
172 					buf + data_offset,
173 					cur_size);
174 
175 			if (!success)
176 				break;
177 
178 			buf_len -= cur_size;
179 			data_offset += cur_size;
180 		}
181 	} else {
182 		int num_i2c_offsets = ARRAY_SIZE(hdcp_i2c_offsets);
183 		if (msg_id >= num_i2c_offsets)
184 			return MOD_HDCP_STATUS_DDC_FAILURE;
185 
186 		success = hdcp->config.ddc.funcs.read_i2c(
187 				hdcp->config.ddc.handle,
188 				HDCP_I2C_ADDR,
189 				hdcp_i2c_offsets[msg_id],
190 				buf,
191 				(uint32_t)buf_len);
192 	}
193 
194 	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
195 }
196 
197 static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp,
198 		enum mod_hdcp_ddc_message_id msg_id,
199 		uint8_t *buf,
200 		uint32_t buf_len,
201 		uint8_t read_size)
202 {
203 	enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE;
204 	uint32_t cur_size = 0;
205 	uint32_t data_offset = 0;
206 
207 	while (buf_len > 0) {
208 		cur_size = MIN(buf_len, read_size);
209 		status = read(hdcp, msg_id, buf + data_offset, cur_size);
210 
211 		if (status != MOD_HDCP_STATUS_SUCCESS)
212 			break;
213 
214 		buf_len -= cur_size;
215 		data_offset += cur_size;
216 	}
217 
218 	return status;
219 }
220 
221 static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
222 		enum mod_hdcp_ddc_message_id msg_id,
223 		uint8_t *buf,
224 		uint32_t buf_len)
225 {
226 	bool success = true;
227 	uint32_t cur_size = 0;
228 	uint32_t data_offset = 0;
229 
230 	if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID ||
231 		msg_id >= MOD_HDCP_MESSAGE_ID_MAX)
232 		return MOD_HDCP_STATUS_DDC_FAILURE;
233 
234 	if (is_dp_hdcp(hdcp)) {
235 		int num_dpcd_addrs = ARRAY_SIZE(hdcp_dpcd_addrs);
236 		if (msg_id >= num_dpcd_addrs)
237 			return MOD_HDCP_STATUS_DDC_FAILURE;
238 
239 		while (buf_len > 0) {
240 			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
241 			success = hdcp->config.ddc.funcs.write_dpcd(
242 					hdcp->config.ddc.handle,
243 					hdcp_dpcd_addrs[msg_id] + data_offset,
244 					buf + data_offset,
245 					cur_size);
246 
247 			if (!success)
248 				break;
249 
250 			buf_len -= cur_size;
251 			data_offset += cur_size;
252 		}
253 	} else {
254 		int num_i2c_offsets = ARRAY_SIZE(hdcp_i2c_offsets);
255 		if (msg_id >= num_i2c_offsets)
256 			return MOD_HDCP_STATUS_DDC_FAILURE;
257 
258 		hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
259 		memmove(&hdcp->buf[1], buf, buf_len);
260 		success = hdcp->config.ddc.funcs.write_i2c(
261 				hdcp->config.ddc.handle,
262 				HDCP_I2C_ADDR,
263 				hdcp->buf,
264 				(uint32_t)(buf_len+1));
265 	}
266 
267 	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
268 }
269 
270 enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp)
271 {
272 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV,
273 			hdcp->auth.msg.hdcp1.bksv,
274 			sizeof(hdcp->auth.msg.hdcp1.bksv));
275 }
276 
277 enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp)
278 {
279 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS,
280 			&hdcp->auth.msg.hdcp1.bcaps,
281 			sizeof(hdcp->auth.msg.hdcp1.bcaps));
282 }
283 
284 enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp)
285 {
286 	enum mod_hdcp_status status;
287 
288 	if (is_dp_hdcp(hdcp))
289 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
290 					(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
291 					1);
292 	else
293 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
294 				(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
295 				sizeof(hdcp->auth.msg.hdcp1.bstatus));
296 	return status;
297 }
298 
299 enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp)
300 {
301 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0,
302 			(uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
303 			sizeof(hdcp->auth.msg.hdcp1.r0p));
304 }
305 
306 /* special case, reading repeatedly at the same address, don't use read() */
307 enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp)
308 {
309 	enum mod_hdcp_status status;
310 
311 	if (is_dp_hdcp(hdcp))
312 		status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
313 				hdcp->auth.msg.hdcp1.ksvlist,
314 				hdcp->auth.msg.hdcp1.ksvlist_size,
315 				KSV_READ_SIZE);
316 	else
317 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
318 				(uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist,
319 				hdcp->auth.msg.hdcp1.ksvlist_size);
320 	return status;
321 }
322 
323 enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp)
324 {
325 	enum mod_hdcp_status status;
326 
327 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0,
328 			&hdcp->auth.msg.hdcp1.vp[0], 4);
329 	if (status != MOD_HDCP_STATUS_SUCCESS)
330 		goto out;
331 
332 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1,
333 			&hdcp->auth.msg.hdcp1.vp[4], 4);
334 	if (status != MOD_HDCP_STATUS_SUCCESS)
335 		goto out;
336 
337 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2,
338 			&hdcp->auth.msg.hdcp1.vp[8], 4);
339 	if (status != MOD_HDCP_STATUS_SUCCESS)
340 		goto out;
341 
342 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3,
343 			&hdcp->auth.msg.hdcp1.vp[12], 4);
344 	if (status != MOD_HDCP_STATUS_SUCCESS)
345 		goto out;
346 
347 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4,
348 			&hdcp->auth.msg.hdcp1.vp[16], 4);
349 out:
350 	return status;
351 }
352 
353 enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp)
354 {
355 	enum mod_hdcp_status status;
356 
357 	if (is_dp_hdcp(hdcp))
358 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO,
359 				(uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
360 				sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
361 	else
362 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
363 
364 	return status;
365 }
366 
367 enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp)
368 {
369 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
370 			hdcp->auth.msg.hdcp1.aksv,
371 			sizeof(hdcp->auth.msg.hdcp1.aksv));
372 }
373 
374 enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp)
375 {
376 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
377 			&hdcp->auth.msg.hdcp1.ainfo,
378 			sizeof(hdcp->auth.msg.hdcp1.ainfo));
379 }
380 
381 enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp)
382 {
383 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN,
384 			hdcp->auth.msg.hdcp1.an,
385 			sizeof(hdcp->auth.msg.hdcp1.an));
386 }
387 
388 enum mod_hdcp_status mod_hdcp_read_hdcp2version(struct mod_hdcp *hdcp)
389 {
390 	enum mod_hdcp_status status;
391 
392 	if (is_dp_hdcp(hdcp))
393 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
394 	else
395 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
396 				&hdcp->auth.msg.hdcp2.hdcp2version_hdmi,
397 				sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi));
398 
399 	return status;
400 }
401 
402 enum mod_hdcp_status mod_hdcp_read_rxcaps(struct mod_hdcp *hdcp)
403 {
404 	enum mod_hdcp_status status;
405 
406 	if (!is_dp_hdcp(hdcp))
407 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
408 	else
409 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_RX_CAPS,
410 				hdcp->auth.msg.hdcp2.rxcaps_dp,
411 				sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp));
412 
413 	return status;
414 }
415 
416 enum mod_hdcp_status mod_hdcp_read_rxstatus(struct mod_hdcp *hdcp)
417 {
418 	enum mod_hdcp_status status;
419 
420 	if (is_dp_hdcp(hdcp)) {
421 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
422 				&hdcp->auth.msg.hdcp2.rxstatus_dp,
423 				1);
424 	} else {
425 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
426 					(uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus,
427 					sizeof(hdcp->auth.msg.hdcp2.rxstatus));
428 	}
429 	return status;
430 }
431 
432 enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp)
433 {
434 	enum mod_hdcp_status status;
435 
436 	if (is_dp_hdcp(hdcp)) {
437 		hdcp->auth.msg.hdcp2.ake_cert[0] = HDCP_2_2_AKE_SEND_CERT;
438 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
439 				hdcp->auth.msg.hdcp2.ake_cert+1,
440 				sizeof(hdcp->auth.msg.hdcp2.ake_cert)-1);
441 
442 	} else {
443 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
444 					hdcp->auth.msg.hdcp2.ake_cert,
445 					sizeof(hdcp->auth.msg.hdcp2.ake_cert));
446 	}
447 	return status;
448 }
449 
450 enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp)
451 {
452 	enum mod_hdcp_status status;
453 
454 	if (is_dp_hdcp(hdcp)) {
455 		hdcp->auth.msg.hdcp2.ake_h_prime[0] = HDCP_2_2_AKE_SEND_HPRIME;
456 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
457 				hdcp->auth.msg.hdcp2.ake_h_prime+1,
458 				sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)-1);
459 
460 	} else {
461 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
462 				hdcp->auth.msg.hdcp2.ake_h_prime,
463 				sizeof(hdcp->auth.msg.hdcp2.ake_h_prime));
464 	}
465 	return status;
466 }
467 
468 enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp)
469 {
470 	enum mod_hdcp_status status;
471 
472 	if (is_dp_hdcp(hdcp)) {
473 		hdcp->auth.msg.hdcp2.ake_pairing_info[0] = HDCP_2_2_AKE_SEND_PAIRING_INFO;
474 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
475 				hdcp->auth.msg.hdcp2.ake_pairing_info+1,
476 				sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)-1);
477 
478 	} else {
479 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
480 				hdcp->auth.msg.hdcp2.ake_pairing_info,
481 				sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info));
482 	}
483 	return status;
484 }
485 
486 enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp)
487 {
488 	enum mod_hdcp_status status;
489 
490 	if (is_dp_hdcp(hdcp)) {
491 		hdcp->auth.msg.hdcp2.lc_l_prime[0] = HDCP_2_2_LC_SEND_LPRIME;
492 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
493 				hdcp->auth.msg.hdcp2.lc_l_prime+1,
494 				sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)-1);
495 
496 	} else {
497 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
498 				hdcp->auth.msg.hdcp2.lc_l_prime,
499 				sizeof(hdcp->auth.msg.hdcp2.lc_l_prime));
500 	}
501 	return status;
502 }
503 
504 enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp)
505 {
506 	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
507 
508 	if (is_dp_hdcp(hdcp)) {
509 		uint32_t device_count = 0;
510 		uint32_t rx_id_list_size = 0;
511 		uint32_t bytes_read = 0;
512 
513 		hdcp->auth.msg.hdcp2.rx_id_list[0] = HDCP_2_2_REP_SEND_RECVID_LIST;
514 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
515 						hdcp->auth.msg.hdcp2.rx_id_list+1,
516 						HDCP_MAX_AUX_TRANSACTION_SIZE);
517 		if (status == MOD_HDCP_STATUS_SUCCESS) {
518 			bytes_read = HDCP_MAX_AUX_TRANSACTION_SIZE;
519 			device_count = HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) +
520 					(HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4);
521 			rx_id_list_size = MIN((21 + 5 * device_count),
522 					(sizeof(hdcp->auth.msg.hdcp2.rx_id_list) - 1));
523 			status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
524 					hdcp->auth.msg.hdcp2.rx_id_list + 1 + bytes_read,
525 					(rx_id_list_size - 1) / HDCP_MAX_AUX_TRANSACTION_SIZE * HDCP_MAX_AUX_TRANSACTION_SIZE);
526 		}
527 	} else {
528 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
529 				hdcp->auth.msg.hdcp2.rx_id_list,
530 				hdcp->auth.msg.hdcp2.rx_id_list_size);
531 	}
532 	return status;
533 }
534 
535 enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp)
536 {
537 	enum mod_hdcp_status status;
538 
539 	if (is_dp_hdcp(hdcp)) {
540 		hdcp->auth.msg.hdcp2.repeater_auth_stream_ready[0] = HDCP_2_2_REP_STREAM_READY;
541 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
542 				hdcp->auth.msg.hdcp2.repeater_auth_stream_ready+1,
543 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)-1);
544 
545 	} else {
546 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
547 				hdcp->auth.msg.hdcp2.repeater_auth_stream_ready,
548 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready));
549 	}
550 	return status;
551 }
552 
553 enum mod_hdcp_status mod_hdcp_write_ake_init(struct mod_hdcp *hdcp)
554 {
555 	enum mod_hdcp_status status;
556 
557 	if (is_dp_hdcp(hdcp))
558 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
559 				hdcp->auth.msg.hdcp2.ake_init+1,
560 				sizeof(hdcp->auth.msg.hdcp2.ake_init)-1);
561 	else
562 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
563 					hdcp->auth.msg.hdcp2.ake_init,
564 					sizeof(hdcp->auth.msg.hdcp2.ake_init));
565 	return status;
566 }
567 
568 enum mod_hdcp_status mod_hdcp_write_no_stored_km(struct mod_hdcp *hdcp)
569 {
570 	enum mod_hdcp_status status;
571 
572 	if (is_dp_hdcp(hdcp))
573 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
574 				hdcp->auth.msg.hdcp2.ake_no_stored_km+1,
575 				sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)-1);
576 	else
577 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
578 			hdcp->auth.msg.hdcp2.ake_no_stored_km,
579 			sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km));
580 	return status;
581 }
582 
583 enum mod_hdcp_status mod_hdcp_write_stored_km(struct mod_hdcp *hdcp)
584 {
585 	enum mod_hdcp_status status;
586 
587 	if (is_dp_hdcp(hdcp))
588 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
589 				hdcp->auth.msg.hdcp2.ake_stored_km+1,
590 				sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)-1);
591 	else
592 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
593 				hdcp->auth.msg.hdcp2.ake_stored_km,
594 				sizeof(hdcp->auth.msg.hdcp2.ake_stored_km));
595 	return status;
596 }
597 
598 enum mod_hdcp_status mod_hdcp_write_lc_init(struct mod_hdcp *hdcp)
599 {
600 	enum mod_hdcp_status status;
601 
602 	if (is_dp_hdcp(hdcp))
603 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
604 				hdcp->auth.msg.hdcp2.lc_init+1,
605 				sizeof(hdcp->auth.msg.hdcp2.lc_init)-1);
606 	else
607 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
608 				hdcp->auth.msg.hdcp2.lc_init,
609 				sizeof(hdcp->auth.msg.hdcp2.lc_init));
610 	return status;
611 }
612 
613 enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp)
614 {
615 	enum mod_hdcp_status status;
616 
617 	if (is_dp_hdcp(hdcp))
618 		status = write(hdcp,
619 				MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
620 				hdcp->auth.msg.hdcp2.ske_eks+1,
621 				sizeof(hdcp->auth.msg.hdcp2.ske_eks)-1);
622 	else
623 		status = write(hdcp,
624 			MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
625 			hdcp->auth.msg.hdcp2.ske_eks,
626 			sizeof(hdcp->auth.msg.hdcp2.ske_eks));
627 	return status;
628 }
629 
630 enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp)
631 {
632 	enum mod_hdcp_status status;
633 
634 	if (is_dp_hdcp(hdcp))
635 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
636 				hdcp->auth.msg.hdcp2.repeater_auth_ack+1,
637 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)-1);
638 	else
639 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
640 				hdcp->auth.msg.hdcp2.repeater_auth_ack,
641 				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack));
642 	return status;
643 }
644 
645 enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp)
646 {
647 	enum mod_hdcp_status status;
648 
649 	if (is_dp_hdcp(hdcp))
650 		status = write(hdcp,
651 				MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
652 				hdcp->auth.msg.hdcp2.repeater_auth_stream_manage+1,
653 				hdcp->auth.msg.hdcp2.stream_manage_size-1);
654 	else
655 		status = write(hdcp,
656 				MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
657 				hdcp->auth.msg.hdcp2.repeater_auth_stream_manage,
658 				hdcp->auth.msg.hdcp2.stream_manage_size);
659 	return status;
660 }
661 
662 enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp)
663 {
664 	enum mod_hdcp_status status;
665 
666 	if (is_dp_hdcp(hdcp))
667 		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
668 				hdcp->auth.msg.hdcp2.content_stream_type_dp+1,
669 				sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp)-1);
670 	else
671 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
672 	return status;
673 }
674 
675 enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp)
676 {
677 	uint8_t clear_cp_irq_bit = DP_CP_IRQ;
678 	uint32_t size = 1;
679 
680 	if (is_dp_hdcp(hdcp)) {
681 		uint32_t cp_irq_addrs = (hdcp->connection.link.dp.rev >= 0x14)
682 				? DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0:DP_DEVICE_SERVICE_IRQ_VECTOR;
683 		return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, cp_irq_addrs,
684 				&clear_cp_irq_bit, size) ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
685 	}
686 
687 	return MOD_HDCP_STATUS_INVALID_OPERATION;
688 }
689