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