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