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