Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
26516 views
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 <linux/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_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
504
{
505
int ret;
506
507
mutex_lock(&mhdp->hdcp.mutex);
508
ret = _cdns_mhdp_hdcp_enable(mhdp, content_type);
509
if (ret)
510
goto out;
511
512
mhdp->hdcp.hdcp_content_type = content_type;
513
mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
514
schedule_work(&mhdp->hdcp.prop_work);
515
schedule_delayed_work(&mhdp->hdcp.check_work,
516
DRM_HDCP_CHECK_PERIOD_MS);
517
out:
518
mutex_unlock(&mhdp->hdcp.mutex);
519
return ret;
520
}
521
522
int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
523
{
524
int ret = 0;
525
526
mutex_lock(&mhdp->hdcp.mutex);
527
if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
528
mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
529
schedule_work(&mhdp->hdcp.prop_work);
530
ret = _cdns_mhdp_hdcp_disable(mhdp);
531
}
532
mutex_unlock(&mhdp->hdcp.mutex);
533
cancel_delayed_work_sync(&mhdp->hdcp.check_work);
534
535
return ret;
536
}
537
538
void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp)
539
{
540
INIT_DELAYED_WORK(&mhdp->hdcp.check_work, cdns_mhdp_hdcp_check_work);
541
INIT_WORK(&mhdp->hdcp.prop_work, cdns_mhdp_hdcp_prop_work);
542
mutex_init(&mhdp->hdcp.mutex);
543
}
544
545