Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

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