Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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.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
 40static 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
 76static 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
111struct protection_properties {
112	bool supported;
113	bool (*process_transaction)(
114		struct dc_link *link,
115		struct hdcp_protection_message *message_info);
116};
117
118static const struct protection_properties non_supported_protection = {
119	.supported = false
120};
121
122static 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	result = dm_helpers_submit_i2c(
181			link->ctx,
182			link,
183			&i2c_command);
184	kfree(buff);
185
186	return result;
187}
188
189static const struct protection_properties hdmi_14_protection = {
190	.supported = true,
191	.process_transaction = hdmi_14_process_transaction
192};
193
194static const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {
195	[HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
196	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
197	[HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
198	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
199	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
200	[HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
201	[HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
202	[HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
203	[HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
204	[HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
205	[HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
206	[HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
207	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
208	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
209	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
210	[HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
211	[HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
212	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
213	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
214	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
215	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
216	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
217	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
218	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
219	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
220	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
221	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
222	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
223	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
224	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
225	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
226	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
227};
228
229static bool dpcd_access_helper(
230	struct dc_link *link,
231	uint32_t length,
232	uint8_t *data,
233	uint32_t dpcd_addr,
234	bool is_read)
235{
236	enum dc_status status;
237	uint32_t cur_length = 0;
238	uint32_t offset = 0;
239	uint32_t ksv_read_size = 0x6803b - 0x6802c;
240
241	/* Read KSV, need repeatedly handle */
242	if (dpcd_addr == 0x6802c) {
243		if (length % HDCP14_KSV_SIZE) {
244			DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",
245				__func__,
246				length,
247				HDCP14_KSV_SIZE);
248		}
249		if (length > HDCP14_MAX_KSV_FIFO_SIZE) {
250			DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",
251				__func__,
252				length,
253				HDCP14_MAX_KSV_FIFO_SIZE);
254		}
255
256		DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",
257			__func__,
258			length / HDCP14_KSV_SIZE);
259
260		while (length > 0) {
261			if (length > ksv_read_size) {
262				status = core_link_read_dpcd(
263					link,
264					dpcd_addr + offset,
265					data + offset,
266					ksv_read_size);
267
268				data += ksv_read_size;
269				length -= ksv_read_size;
270			} else {
271				status = core_link_read_dpcd(
272					link,
273					dpcd_addr + offset,
274					data + offset,
275					length);
276
277				data += length;
278				length = 0;
279			}
280
281			if (status != DC_OK)
282				return false;
283		}
284	} else {
285		while (length > 0) {
286			if (length > DEFAULT_AUX_MAX_DATA_SIZE)
287				cur_length = DEFAULT_AUX_MAX_DATA_SIZE;
288			else
289				cur_length = length;
290
291			if (is_read) {
292				status = core_link_read_dpcd(
293					link,
294					dpcd_addr + offset,
295					data + offset,
296					cur_length);
297			} else {
298				status = core_link_write_dpcd(
299					link,
300					dpcd_addr + offset,
301					data + offset,
302					cur_length);
303			}
304
305			if (status != DC_OK)
306				return false;
307
308			length -= cur_length;
309			offset += cur_length;
310		}
311	}
312	return true;
313}
314
315static bool dp_11_process_transaction(
316	struct dc_link *link,
317	struct hdcp_protection_message *message_info)
318{
319	if (message_info->msg_id == HDCP_MESSAGE_ID_INVALID) {
320		DC_LOG_ERROR("%s: Invalid message_info msg_id - %d\n", __func__, message_info->msg_id);
321		return false;
322	}
323
324	return dpcd_access_helper(
325		link,
326		message_info->length,
327		message_info->data,
328		hdcp_dpcd_addrs[message_info->msg_id],
329		hdcp_cmd_is_read[message_info->msg_id]);
330}
331
332static const struct protection_properties dp_11_protection = {
333	.supported = true,
334	.process_transaction = dp_11_process_transaction
335};
336
337static const struct protection_properties *get_protection_properties_by_signal(
338	struct dc_link *link,
339	enum signal_type st,
340	enum hdcp_version version)
341{
342	switch (version) {
343	case HDCP_VERSION_14:
344		switch (st) {
345		case SIGNAL_TYPE_DVI_SINGLE_LINK:
346		case SIGNAL_TYPE_DVI_DUAL_LINK:
347		case SIGNAL_TYPE_HDMI_TYPE_A:
348			return &hdmi_14_protection;
349		case SIGNAL_TYPE_DISPLAY_PORT:
350			if (link &&
351				(link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
352				link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) {
353				return &non_supported_protection;
354			}
355			return &dp_11_protection;
356		case SIGNAL_TYPE_DISPLAY_PORT_MST:
357		case SIGNAL_TYPE_EDP:
358			return &dp_11_protection;
359		default:
360			return &non_supported_protection;
361		}
362		break;
363	case HDCP_VERSION_22:
364		switch (st) {
365		case SIGNAL_TYPE_DVI_SINGLE_LINK:
366		case SIGNAL_TYPE_DVI_DUAL_LINK:
367		case SIGNAL_TYPE_HDMI_TYPE_A:
368			return &hdmi_14_protection; //todo version2.2
369		case SIGNAL_TYPE_DISPLAY_PORT:
370		case SIGNAL_TYPE_DISPLAY_PORT_MST:
371		case SIGNAL_TYPE_EDP:
372			return &dp_11_protection;  //todo version2.2
373		default:
374			return &non_supported_protection;
375		}
376		break;
377	default:
378		return &non_supported_protection;
379	}
380}
381
382enum hdcp_message_status dc_process_hdcp_msg(
383	enum signal_type signal,
384	struct dc_link *link,
385	struct hdcp_protection_message *message_info)
386{
387	enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;
388	uint32_t i = 0;
389
390	const struct protection_properties *protection_props;
391
392	if (!message_info)
393		return HDCP_MESSAGE_UNSUPPORTED;
394
395	if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||
396		message_info->msg_id >= HDCP_MESSAGE_ID_MAX)
397		return HDCP_MESSAGE_UNSUPPORTED;
398
399	protection_props =
400		get_protection_properties_by_signal(
401			link,
402			signal,
403			message_info->version);
404
405	if (!protection_props->supported)
406		return HDCP_MESSAGE_UNSUPPORTED;
407
408	if (protection_props->process_transaction(
409		link,
410		message_info)) {
411		status = HDCP_MESSAGE_SUCCESS;
412	} else {
413		for (i = 0; i < message_info->max_retries; i++) {
414			if (protection_props->process_transaction(
415						link,
416						message_info)) {
417				status = HDCP_MESSAGE_SUCCESS;
418				break;
419			}
420		}
421	}
422
423	return status;
424}
425