]> Git Repo - linux.git/blob - drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux.git] / drivers / gpu / drm / bridge / cadence / cdns-mhdp8546-hdcp.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Cadence MHDP8546 DP bridge driver.
4  *
5  * Copyright (C) 2020 Cadence Design Systems, Inc.
6  *
7  */
8
9 #include <linux/io.h>
10 #include <linux/iopoll.h>
11
12 #include <asm/unaligned.h>
13
14 #include <drm/display/drm_hdcp_helper.h>
15
16 #include "cdns-mhdp8546-hdcp.h"
17
18 static int cdns_mhdp_secure_mailbox_read(struct cdns_mhdp_device *mhdp)
19 {
20         int ret, empty;
21
22         WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
23
24         ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_EMPTY,
25                                  empty, !empty, MAILBOX_RETRY_US,
26                                  MAILBOX_TIMEOUT_US);
27         if (ret < 0)
28                 return ret;
29
30         return readl(mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff;
31 }
32
33 static int cdns_mhdp_secure_mailbox_write(struct cdns_mhdp_device *mhdp,
34                                           u8 val)
35 {
36         int ret, full;
37
38         WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
39
40         ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_FULL,
41                                  full, !full, MAILBOX_RETRY_US,
42                                  MAILBOX_TIMEOUT_US);
43         if (ret < 0)
44                 return ret;
45
46         writel(val, mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA);
47
48         return 0;
49 }
50
51 static int cdns_mhdp_secure_mailbox_recv_header(struct cdns_mhdp_device *mhdp,
52                                                 u8 module_id,
53                                                 u8 opcode,
54                                                 u16 req_size)
55 {
56         u32 mbox_size, i;
57         u8 header[4];
58         int ret;
59
60         /* read the header of the message */
61         for (i = 0; i < sizeof(header); i++) {
62                 ret = cdns_mhdp_secure_mailbox_read(mhdp);
63                 if (ret < 0)
64                         return ret;
65
66                 header[i] = ret;
67         }
68
69         mbox_size = get_unaligned_be16(header + 2);
70
71         if (opcode != header[0] || module_id != header[1] ||
72             (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) {
73                 for (i = 0; i < mbox_size; i++)
74                         if (cdns_mhdp_secure_mailbox_read(mhdp) < 0)
75                                 break;
76                 return -EINVAL;
77         }
78
79         return 0;
80 }
81
82 static int cdns_mhdp_secure_mailbox_recv_data(struct cdns_mhdp_device *mhdp,
83                                               u8 *buff, u16 buff_size)
84 {
85         int ret;
86         u32 i;
87
88         for (i = 0; i < buff_size; i++) {
89                 ret = cdns_mhdp_secure_mailbox_read(mhdp);
90                 if (ret < 0)
91                         return ret;
92
93                 buff[i] = ret;
94         }
95
96         return 0;
97 }
98
99 static int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_device *mhdp,
100                                          u8 module_id,
101                                          u8 opcode,
102                                          u16 size,
103                                          u8 *message)
104 {
105         u8 header[4];
106         int ret;
107         u32 i;
108
109         header[0] = opcode;
110         header[1] = module_id;
111         put_unaligned_be16(size, header + 2);
112
113         for (i = 0; i < sizeof(header); i++) {
114                 ret = cdns_mhdp_secure_mailbox_write(mhdp, header[i]);
115                 if (ret)
116                         return ret;
117         }
118
119         for (i = 0; i < size; i++) {
120                 ret = cdns_mhdp_secure_mailbox_write(mhdp, message[i]);
121                 if (ret)
122                         return ret;
123         }
124
125         return 0;
126 }
127
128 static int cdns_mhdp_hdcp_get_status(struct cdns_mhdp_device *mhdp,
129                                      u16 *hdcp_port_status)
130 {
131         u8 hdcp_status[HDCP_STATUS_SIZE];
132         int ret;
133
134         mutex_lock(&mhdp->mbox_mutex);
135         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
136                                             HDCP_TRAN_STATUS_CHANGE, 0, NULL);
137         if (ret)
138                 goto err_get_hdcp_status;
139
140         ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
141                                                    HDCP_TRAN_STATUS_CHANGE,
142                                                    sizeof(hdcp_status));
143         if (ret)
144                 goto err_get_hdcp_status;
145
146         ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_status,
147                                                  sizeof(hdcp_status));
148         if (ret)
149                 goto err_get_hdcp_status;
150
151         *hdcp_port_status = ((u16)(hdcp_status[0] << 8) | hdcp_status[1]);
152
153 err_get_hdcp_status:
154         mutex_unlock(&mhdp->mbox_mutex);
155
156         return ret;
157 }
158
159 static u8 cdns_mhdp_hdcp_handle_status(struct cdns_mhdp_device *mhdp,
160                                        u16 status)
161 {
162         u8 err = GET_HDCP_PORT_STS_LAST_ERR(status);
163
164         if (err)
165                 dev_dbg(mhdp->dev, "HDCP Error = %d", err);
166
167         return err;
168 }
169
170 static int cdns_mhdp_hdcp_rx_id_valid_response(struct cdns_mhdp_device *mhdp,
171                                                u8 valid)
172 {
173         int ret;
174
175         mutex_lock(&mhdp->mbox_mutex);
176         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
177                                             HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
178                                             1, &valid);
179         mutex_unlock(&mhdp->mbox_mutex);
180
181         return ret;
182 }
183
184 static int cdns_mhdp_hdcp_rx_id_valid(struct cdns_mhdp_device *mhdp,
185                                       u8 *recv_num, u8 *hdcp_rx_id)
186 {
187         u8 rec_id_hdr[2];
188         u8 status;
189         int ret;
190
191         mutex_lock(&mhdp->mbox_mutex);
192         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
193                                             HDCP_TRAN_IS_REC_ID_VALID, 0, NULL);
194         if (ret)
195                 goto err_rx_id_valid;
196
197         ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
198                                                    HDCP_TRAN_IS_REC_ID_VALID,
199                                                    sizeof(status));
200         if (ret)
201                 goto err_rx_id_valid;
202
203         ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, rec_id_hdr, 2);
204         if (ret)
205                 goto err_rx_id_valid;
206
207         *recv_num = rec_id_hdr[0];
208
209         ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_rx_id, 5 * *recv_num);
210
211 err_rx_id_valid:
212         mutex_unlock(&mhdp->mbox_mutex);
213
214         return ret;
215 }
216
217 static int cdns_mhdp_hdcp_km_stored_resp(struct cdns_mhdp_device *mhdp,
218                                          u32 size, u8 *km)
219 {
220         int ret;
221
222         mutex_lock(&mhdp->mbox_mutex);
223         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
224                                             HDCP2X_TX_RESPOND_KM, size, km);
225         mutex_unlock(&mhdp->mbox_mutex);
226
227         return ret;
228 }
229
230 static int cdns_mhdp_hdcp_tx_is_km_stored(struct cdns_mhdp_device *mhdp,
231                                           u8 *resp, u32 size)
232 {
233         int ret;
234
235         mutex_lock(&mhdp->mbox_mutex);
236         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
237                                             HDCP2X_TX_IS_KM_STORED, 0, NULL);
238         if (ret)
239                 goto err_is_km_stored;
240
241         ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
242                                                    HDCP2X_TX_IS_KM_STORED,
243                                                    size);
244         if (ret)
245                 goto err_is_km_stored;
246
247         ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, resp, size);
248 err_is_km_stored:
249         mutex_unlock(&mhdp->mbox_mutex);
250
251         return ret;
252 }
253
254 static int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp,
255                                     u8 hdcp_cfg)
256 {
257         int ret;
258
259         mutex_lock(&mhdp->mbox_mutex);
260         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
261                                             HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg);
262         mutex_unlock(&mhdp->mbox_mutex);
263
264         return ret;
265 }
266
267 static int cdns_mhdp_hdcp_set_config(struct cdns_mhdp_device *mhdp,
268                                      u8 hdcp_config, bool enable)
269 {
270         u16 hdcp_port_status;
271         u32 ret_event;
272         u8 hdcp_cfg;
273         int ret;
274
275         hdcp_cfg = hdcp_config | (enable ? 0x04 : 0) |
276                    (HDCP_CONTENT_TYPE_0 << 3);
277         cdns_mhdp_hdcp_tx_config(mhdp, hdcp_cfg);
278         ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS);
279         if (!ret_event)
280                 return -1;
281
282         ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
283         if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
284                 return -1;
285
286         return 0;
287 }
288
289 static int cdns_mhdp_hdcp_auth_check(struct cdns_mhdp_device *mhdp)
290 {
291         u16 hdcp_port_status;
292         u32 ret_event;
293         int ret;
294
295         ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS);
296         if (!ret_event)
297                 return -1;
298
299         ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
300         if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
301                 return -1;
302
303         if (hdcp_port_status & 1) {
304                 dev_dbg(mhdp->dev, "Authentication completed successfully!\n");
305                 return 0;
306         }
307
308         dev_dbg(mhdp->dev, "Authentication failed\n");
309
310         return -1;
311 }
312
313 static int cdns_mhdp_hdcp_check_receviers(struct cdns_mhdp_device *mhdp)
314 {
315         u8 hdcp_rec_id[HDCP_MAX_RECEIVERS][HDCP_RECEIVER_ID_SIZE_BYTES];
316         u8 hdcp_num_rec;
317         u32 ret_event;
318
319         ret_event = cdns_mhdp_wait_for_sw_event(mhdp,
320                                                 CDNS_HDCP_TX_IS_RCVR_ID_VALID);
321         if (!ret_event)
322                 return -1;
323
324         hdcp_num_rec = 0;
325         memset(&hdcp_rec_id, 0, sizeof(hdcp_rec_id));
326         cdns_mhdp_hdcp_rx_id_valid(mhdp, &hdcp_num_rec, (u8 *)hdcp_rec_id);
327         cdns_mhdp_hdcp_rx_id_valid_response(mhdp, 1);
328
329         return 0;
330 }
331
332 static int cdns_mhdp_hdcp_auth_22(struct cdns_mhdp_device *mhdp)
333 {
334         u8 resp[HDCP_STATUS_SIZE];
335         u16 hdcp_port_status;
336         u32 ret_event;
337         int ret;
338
339         dev_dbg(mhdp->dev, "HDCP: Start 2.2 Authentication\n");
340         ret_event = cdns_mhdp_wait_for_sw_event(mhdp,
341                                                 CDNS_HDCP2_TX_IS_KM_STORED);
342         if (!ret_event)
343                 return -1;
344
345         if (ret_event & CDNS_HDCP_TX_STATUS) {
346                 mhdp->sw_events &= ~CDNS_HDCP_TX_STATUS;
347                 ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
348                 if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
349                         return -1;
350         }
351
352         cdns_mhdp_hdcp_tx_is_km_stored(mhdp, resp, sizeof(resp));
353         cdns_mhdp_hdcp_km_stored_resp(mhdp, 0, NULL);
354
355         if (cdns_mhdp_hdcp_check_receviers(mhdp))
356                 return -1;
357
358         return 0;
359 }
360
361 static inline int cdns_mhdp_hdcp_auth_14(struct cdns_mhdp_device *mhdp)
362 {
363         dev_dbg(mhdp->dev, "HDCP: Starting 1.4 Authentication\n");
364         return cdns_mhdp_hdcp_check_receviers(mhdp);
365 }
366
367 static int cdns_mhdp_hdcp_auth(struct cdns_mhdp_device *mhdp,
368                                u8 hdcp_config)
369 {
370         int ret;
371
372         ret = cdns_mhdp_hdcp_set_config(mhdp, hdcp_config, true);
373         if (ret)
374                 goto auth_failed;
375
376         if (hdcp_config == HDCP_TX_1)
377                 ret = cdns_mhdp_hdcp_auth_14(mhdp);
378         else
379                 ret = cdns_mhdp_hdcp_auth_22(mhdp);
380
381         if (ret)
382                 goto auth_failed;
383
384         ret = cdns_mhdp_hdcp_auth_check(mhdp);
385         if (ret)
386                 ret = cdns_mhdp_hdcp_auth_check(mhdp);
387
388 auth_failed:
389         return ret;
390 }
391
392 static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
393 {
394         int ret;
395
396         dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n",
397                 mhdp->connector.name, mhdp->connector.base.id);
398
399         ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false);
400
401         return ret;
402 }
403
404 static int _cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
405 {
406         int ret = -EINVAL;
407         int tries = 3;
408         u32 i;
409
410         for (i = 0; i < tries; i++) {
411                 if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0 ||
412                     content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
413                         ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_2);
414                         if (!ret)
415                                 return 0;
416                         _cdns_mhdp_hdcp_disable(mhdp);
417                 }
418
419                 if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
420                         ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_1);
421                         if (!ret)
422                                 return 0;
423                         _cdns_mhdp_hdcp_disable(mhdp);
424                 }
425         }
426
427         dev_err(mhdp->dev, "HDCP authentication failed (%d tries/%d)\n",
428                 tries, ret);
429
430         return ret;
431 }
432
433 static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
434 {
435         u16 hdcp_port_status;
436         int ret = 0;
437
438         mutex_lock(&mhdp->hdcp.mutex);
439         if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
440                 goto out;
441
442         ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
443         if (!ret && hdcp_port_status & HDCP_PORT_STS_AUTH)
444                 goto out;
445
446         dev_err(mhdp->dev,
447                 "[%s:%d] HDCP link failed, retrying authentication\n",
448                 mhdp->connector.name, mhdp->connector.base.id);
449
450         ret = _cdns_mhdp_hdcp_disable(mhdp);
451         if (ret) {
452                 mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
453                 schedule_work(&mhdp->hdcp.prop_work);
454                 goto out;
455         }
456
457         ret = _cdns_mhdp_hdcp_enable(mhdp, mhdp->hdcp.hdcp_content_type);
458         if (ret) {
459                 mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
460                 schedule_work(&mhdp->hdcp.prop_work);
461         }
462 out:
463         mutex_unlock(&mhdp->hdcp.mutex);
464         return ret;
465 }
466
467 static void cdns_mhdp_hdcp_check_work(struct work_struct *work)
468 {
469         struct delayed_work *d_work = to_delayed_work(work);
470         struct cdns_mhdp_hdcp *hdcp = container_of(d_work,
471                                                    struct cdns_mhdp_hdcp,
472                                                    check_work);
473         struct cdns_mhdp_device *mhdp = container_of(hdcp,
474                                                      struct cdns_mhdp_device,
475                                                      hdcp);
476
477         if (!cdns_mhdp_hdcp_check_link(mhdp))
478                 schedule_delayed_work(&hdcp->check_work,
479                                       DRM_HDCP_CHECK_PERIOD_MS);
480 }
481
482 static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
483 {
484         struct cdns_mhdp_hdcp *hdcp = container_of(work,
485                                                    struct cdns_mhdp_hdcp,
486                                                    prop_work);
487         struct cdns_mhdp_device *mhdp = container_of(hdcp,
488                                                      struct cdns_mhdp_device,
489                                                      hdcp);
490         struct drm_device *dev = mhdp->connector.dev;
491         struct drm_connector_state *state;
492
493         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
494         mutex_lock(&mhdp->hdcp.mutex);
495         if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
496                 state = mhdp->connector.state;
497                 state->content_protection = mhdp->hdcp.value;
498         }
499         mutex_unlock(&mhdp->hdcp.mutex);
500         drm_modeset_unlock(&dev->mode_config.connection_mutex);
501 }
502
503 int cdns_mhdp_hdcp_set_lc(struct cdns_mhdp_device *mhdp, u8 *val)
504 {
505         int ret;
506
507         mutex_lock(&mhdp->mbox_mutex);
508         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_GENERAL,
509                                             HDCP_GENERAL_SET_LC_128,
510                                             16, val);
511         mutex_unlock(&mhdp->mbox_mutex);
512
513         return ret;
514 }
515
516 int
517 cdns_mhdp_hdcp_set_public_key_param(struct cdns_mhdp_device *mhdp,
518                                     struct cdns_hdcp_tx_public_key_param *val)
519 {
520         int ret;
521
522         mutex_lock(&mhdp->mbox_mutex);
523         ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
524                                             HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
525                                             sizeof(*val), (u8 *)val);
526         mutex_unlock(&mhdp->mbox_mutex);
527
528         return ret;
529 }
530
531 int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
532 {
533         int ret;
534
535         mutex_lock(&mhdp->hdcp.mutex);
536         ret = _cdns_mhdp_hdcp_enable(mhdp, content_type);
537         if (ret)
538                 goto out;
539
540         mhdp->hdcp.hdcp_content_type = content_type;
541         mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
542         schedule_work(&mhdp->hdcp.prop_work);
543         schedule_delayed_work(&mhdp->hdcp.check_work,
544                               DRM_HDCP_CHECK_PERIOD_MS);
545 out:
546         mutex_unlock(&mhdp->hdcp.mutex);
547         return ret;
548 }
549
550 int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
551 {
552         int ret = 0;
553
554         mutex_lock(&mhdp->hdcp.mutex);
555         if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
556                 mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
557                 schedule_work(&mhdp->hdcp.prop_work);
558                 ret = _cdns_mhdp_hdcp_disable(mhdp);
559         }
560         mutex_unlock(&mhdp->hdcp.mutex);
561         cancel_delayed_work_sync(&mhdp->hdcp.check_work);
562
563         return ret;
564 }
565
566 void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp)
567 {
568         INIT_DELAYED_WORK(&mhdp->hdcp.check_work, cdns_mhdp_hdcp_check_work);
569         INIT_WORK(&mhdp->hdcp.prop_work, cdns_mhdp_hdcp_prop_work);
570         mutex_init(&mhdp->hdcp.mutex);
571 }
This page took 0.073052 seconds and 4 git commands to generate.