Linux Audio

Check our new training course

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