xref: /linux/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
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 "dm_services.h"
27 #include "dm_helpers.h"
28 #include "include/hdcp_msg_types.h"
29 #include "include/signal_types.h"
30 #include "core_types.h"
31 #include "link_service.h"
32 #include "link_hwss.h"
33 #include "link/protocols/link_dpcd.h"
34 
35 #define DC_LOGGER \
36 	link->ctx->logger
37 #define HDCP14_KSV_SIZE 5
38 #define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE
39 
40 static const bool hdcp_cmd_is_read[HDCP_MESSAGE_ID_MAX] = {
41 	[HDCP_MESSAGE_ID_READ_BKSV] = true,
42 	[HDCP_MESSAGE_ID_READ_RI_R0] = true,
43 	[HDCP_MESSAGE_ID_READ_PJ] = true,
44 	[HDCP_MESSAGE_ID_WRITE_AKSV] = false,
45 	[HDCP_MESSAGE_ID_WRITE_AINFO] = false,
46 	[HDCP_MESSAGE_ID_WRITE_AN] = false,
47 	[HDCP_MESSAGE_ID_READ_VH_X] = true,
48 	[HDCP_MESSAGE_ID_READ_VH_0] = true,
49 	[HDCP_MESSAGE_ID_READ_VH_1] = true,
50 	[HDCP_MESSAGE_ID_READ_VH_2] = true,
51 	[HDCP_MESSAGE_ID_READ_VH_3] = true,
52 	[HDCP_MESSAGE_ID_READ_VH_4] = true,
53 	[HDCP_MESSAGE_ID_READ_BCAPS] = true,
54 	[HDCP_MESSAGE_ID_READ_BSTATUS] = true,
55 	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,
56 	[HDCP_MESSAGE_ID_READ_BINFO] = true,
57 	[HDCP_MESSAGE_ID_HDCP2VERSION] = true,
58 	[HDCP_MESSAGE_ID_RX_CAPS] = true,
59 	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,
60 	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,
61 	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,
62 	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,
63 	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,
64 	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,
65 	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,
66 	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,
67 	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,
68 	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,
69 	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,
70 	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,
71 	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,
72 	[HDCP_MESSAGE_ID_READ_RXSTATUS] = true,
73 	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false,
74 };
75 
76 static const uint8_t hdcp_i2c_offsets[HDCP_MESSAGE_ID_MAX] = {
77 	[HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
78 	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
79 	[HDCP_MESSAGE_ID_READ_PJ] = 0xA,
80 	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
81 	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
82 	[HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
83 	[HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
84 	[HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
85 	[HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
86 	[HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
87 	[HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
88 	[HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
89 	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
90 	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
91 	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
92 	[HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
93 	[HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
94 	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
95 	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
96 	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
97 	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
98 	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
99 	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
100 	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
101 	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
102 	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
103 	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
104 	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
105 	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
106 	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
107 	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
108 	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0,
109 };
110 
111 struct protection_properties {
112 	bool supported;
113 	bool (*process_transaction)(
114 		struct dc_link *link,
115 		struct hdcp_protection_message *message_info);
116 };
117 
118 static const struct protection_properties non_supported_protection = {
119 	.supported = false
120 };
121 
122 static bool hdmi_14_process_transaction(
123 	struct dc_link *link,
124 	struct hdcp_protection_message *message_info)
125 {
126 	uint8_t *buff = NULL;
127 	bool result;
128 	const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
129 	const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
130 	struct i2c_command i2c_command;
131 	uint8_t offset;
132 	struct i2c_payload i2c_payloads[] = {
133 		{ true, 0, 1, 0 },
134 		/* actual hdcp payload, will be filled later, zeroed for now*/
135 		{ 0 }
136 	};
137 
138 	if (message_info->msg_id == HDCP_MESSAGE_ID_INVALID) {
139 		DC_LOG_ERROR("%s: Invalid message_info msg_id - %d\n", __func__, message_info->msg_id);
140 		return false;
141 	}
142 
143 	offset = hdcp_i2c_offsets[message_info->msg_id];
144 	i2c_payloads[0].data = &offset;
145 
146 	switch (message_info->link) {
147 	case HDCP_LINK_SECONDARY:
148 		i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
149 		i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
150 		break;
151 	case HDCP_LINK_PRIMARY:
152 	default:
153 		i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
154 		i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
155 		break;
156 	}
157 
158 	if (hdcp_cmd_is_read[message_info->msg_id]) {
159 		i2c_payloads[1].write = false;
160 		i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
161 		i2c_payloads[1].length = message_info->length;
162 		i2c_payloads[1].data = message_info->data;
163 	} else {
164 		i2c_command.number_of_payloads = 1;
165 		buff = kzalloc(message_info->length + 1, GFP_KERNEL);
166 
167 		if (!buff)
168 			return false;
169 
170 		buff[0] = offset;
171 		memmove(&buff[1], message_info->data, message_info->length);
172 		i2c_payloads[0].length = message_info->length + 1;
173 		i2c_payloads[0].data = buff;
174 	}
175 
176 	i2c_command.payloads = i2c_payloads;
177 	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
178 	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
179 
180 	if (link->force_to_use_aux)
181 		result = dm_helpers_submit_i2c_over_aux(
182 			link->ddc,
183 			hdcp_i2c_addr_link_primary,
184 			offset,
185 			message_info->data,
186 			message_info->length,
187 			hdcp_cmd_is_read[message_info->msg_id]);
188 	else
189 	result = dm_helpers_submit_i2c(
190 			link->ctx,
191 			link,
192 			&i2c_command);
193 	kfree(buff);
194 
195 	return result;
196 }
197 
198 static const struct protection_properties hdmi_14_protection = {
199 	.supported = true,
200 	.process_transaction = hdmi_14_process_transaction
201 };
202 
203 static const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {
204 	[HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
205 	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
206 	[HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
207 	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
208 	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
209 	[HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
210 	[HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
211 	[HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
212 	[HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
213 	[HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
214 	[HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
215 	[HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
216 	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
217 	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
218 	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
219 	[HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
220 	[HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
221 	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
222 	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
223 	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
224 	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
225 	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
226 	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
227 	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
228 	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
229 	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
230 	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
231 	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
232 	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
233 	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
234 	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
235 	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
236 };
237 
238 static bool dpcd_access_helper(
239 	struct dc_link *link,
240 	uint32_t length,
241 	uint8_t *data,
242 	uint32_t dpcd_addr,
243 	bool is_read)
244 {
245 	enum dc_status status;
246 	uint32_t cur_length = 0;
247 	uint32_t offset = 0;
248 	uint32_t ksv_read_size = 0x6803b - 0x6802c;
249 
250 	/* Read KSV, need repeatedly handle */
251 	if (dpcd_addr == 0x6802c) {
252 		if (length % HDCP14_KSV_SIZE) {
253 			DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",
254 				__func__,
255 				length,
256 				HDCP14_KSV_SIZE);
257 		}
258 		if (length > HDCP14_MAX_KSV_FIFO_SIZE) {
259 			DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",
260 				__func__,
261 				length,
262 				HDCP14_MAX_KSV_FIFO_SIZE);
263 		}
264 
265 		DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",
266 			__func__,
267 			length / HDCP14_KSV_SIZE);
268 
269 		while (length > 0) {
270 			if (length > ksv_read_size) {
271 				status = core_link_read_dpcd(
272 					link,
273 					dpcd_addr + offset,
274 					data + offset,
275 					ksv_read_size);
276 
277 				data += ksv_read_size;
278 				length -= ksv_read_size;
279 			} else {
280 				status = core_link_read_dpcd(
281 					link,
282 					dpcd_addr + offset,
283 					data + offset,
284 					length);
285 
286 				data += length;
287 				length = 0;
288 			}
289 
290 			if (status != DC_OK)
291 				return false;
292 		}
293 	} else {
294 		while (length > 0) {
295 			if (length > DEFAULT_AUX_MAX_DATA_SIZE)
296 				cur_length = DEFAULT_AUX_MAX_DATA_SIZE;
297 			else
298 				cur_length = length;
299 
300 			if (is_read) {
301 				status = core_link_read_dpcd(
302 					link,
303 					dpcd_addr + offset,
304 					data + offset,
305 					cur_length);
306 			} else {
307 				status = core_link_write_dpcd(
308 					link,
309 					dpcd_addr + offset,
310 					data + offset,
311 					cur_length);
312 			}
313 
314 			if (status != DC_OK)
315 				return false;
316 
317 			length -= cur_length;
318 			offset += cur_length;
319 		}
320 	}
321 	return true;
322 }
323 
324 static bool dp_11_process_transaction(
325 	struct dc_link *link,
326 	struct hdcp_protection_message *message_info)
327 {
328 	if (message_info->msg_id == HDCP_MESSAGE_ID_INVALID) {
329 		DC_LOG_ERROR("%s: Invalid message_info msg_id - %d\n", __func__, message_info->msg_id);
330 		return false;
331 	}
332 
333 	return dpcd_access_helper(
334 		link,
335 		message_info->length,
336 		message_info->data,
337 		hdcp_dpcd_addrs[message_info->msg_id],
338 		hdcp_cmd_is_read[message_info->msg_id]);
339 }
340 
341 static const struct protection_properties dp_11_protection = {
342 	.supported = true,
343 	.process_transaction = dp_11_process_transaction
344 };
345 
346 static const struct protection_properties *get_protection_properties_by_signal(
347 	struct dc_link *link,
348 	enum signal_type st,
349 	enum hdcp_version version)
350 {
351 	switch (version) {
352 	case HDCP_VERSION_14:
353 		switch (st) {
354 		case SIGNAL_TYPE_DVI_SINGLE_LINK:
355 		case SIGNAL_TYPE_DVI_DUAL_LINK:
356 		case SIGNAL_TYPE_HDMI_TYPE_A:
357 			return &hdmi_14_protection;
358 		case SIGNAL_TYPE_DISPLAY_PORT:
359 			if (link &&
360 				(link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
361 				link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) {
362 				return &non_supported_protection;
363 			}
364 			return &dp_11_protection;
365 		case SIGNAL_TYPE_DISPLAY_PORT_MST:
366 		case SIGNAL_TYPE_EDP:
367 			return &dp_11_protection;
368 		default:
369 			return &non_supported_protection;
370 		}
371 		break;
372 	case HDCP_VERSION_22:
373 		switch (st) {
374 		case SIGNAL_TYPE_DVI_SINGLE_LINK:
375 		case SIGNAL_TYPE_DVI_DUAL_LINK:
376 		case SIGNAL_TYPE_HDMI_TYPE_A:
377 		case SIGNAL_TYPE_HDMI_FRL:
378 			return &hdmi_14_protection; //todo version2.2
379 		case SIGNAL_TYPE_DISPLAY_PORT:
380 		case SIGNAL_TYPE_DISPLAY_PORT_MST:
381 		case SIGNAL_TYPE_EDP:
382 			return &dp_11_protection;  //todo version2.2
383 		default:
384 			return &non_supported_protection;
385 		}
386 		break;
387 	default:
388 		return &non_supported_protection;
389 	}
390 }
391 
392 enum hdcp_message_status dc_process_hdcp_msg(
393 	enum signal_type signal,
394 	struct dc_link *link,
395 	struct hdcp_protection_message *message_info)
396 {
397 	enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;
398 	uint32_t i = 0;
399 
400 	const struct protection_properties *protection_props;
401 
402 	if (!message_info)
403 		return HDCP_MESSAGE_UNSUPPORTED;
404 
405 	if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||
406 		message_info->msg_id >= HDCP_MESSAGE_ID_MAX)
407 		return HDCP_MESSAGE_UNSUPPORTED;
408 
409 	protection_props =
410 		get_protection_properties_by_signal(
411 			link,
412 			signal,
413 			message_info->version);
414 
415 	if (!protection_props->supported)
416 		return HDCP_MESSAGE_UNSUPPORTED;
417 
418 	if (protection_props->process_transaction(
419 		link,
420 		message_info)) {
421 		status = HDCP_MESSAGE_SUCCESS;
422 	} else {
423 		for (i = 0; i < message_info->max_retries; i++) {
424 			if (protection_props->process_transaction(
425 						link,
426 						message_info)) {
427 				status = HDCP_MESSAGE_SUCCESS;
428 				break;
429 			}
430 		}
431 	}
432 
433 	return status;
434 }
435 
436