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
18static 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(addr: mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff;
31}
32
33static 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, addr: mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA);
47
48 return 0;
49}
50
51static 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(p: 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
82static 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
99static 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(val: size, p: header + 2);
112
113 for (i = 0; i < sizeof(header); i++) {
114 ret = cdns_mhdp_secure_mailbox_write(mhdp, val: 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, val: message[i]);
121 if (ret)
122 return ret;
123 }
124
125 return 0;
126}
127
128static 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 opcode: HDCP_TRAN_STATUS_CHANGE, size: 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 opcode: HDCP_TRAN_STATUS_CHANGE,
142 req_size: sizeof(hdcp_status));
143 if (ret)
144 goto err_get_hdcp_status;
145
146 ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, buff: hdcp_status,
147 buff_size: 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
153err_get_hdcp_status:
154 mutex_unlock(lock: &mhdp->mbox_mutex);
155
156 return ret;
157}
158
159static 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
170static 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 opcode: HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
178 size: 1, message: &valid);
179 mutex_unlock(lock: &mhdp->mbox_mutex);
180
181 return ret;
182}
183
184static 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 opcode: HDCP_TRAN_IS_REC_ID_VALID, size: 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 opcode: HDCP_TRAN_IS_REC_ID_VALID,
199 req_size: sizeof(status));
200 if (ret)
201 goto err_rx_id_valid;
202
203 ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, buff: rec_id_hdr, buff_size: 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, buff: hdcp_rx_id, buff_size: 5 * *recv_num);
210
211err_rx_id_valid:
212 mutex_unlock(lock: &mhdp->mbox_mutex);
213
214 return ret;
215}
216
217static 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 opcode: HDCP2X_TX_RESPOND_KM, size, message: km);
225 mutex_unlock(lock: &mhdp->mbox_mutex);
226
227 return ret;
228}
229
230static 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 opcode: HDCP2X_TX_IS_KM_STORED, size: 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 opcode: HDCP2X_TX_IS_KM_STORED,
243 req_size: size);
244 if (ret)
245 goto err_is_km_stored;
246
247 ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, buff: resp, buff_size: size);
248err_is_km_stored:
249 mutex_unlock(lock: &mhdp->mbox_mutex);
250
251 return ret;
252}
253
254static 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 opcode: HDCP_TRAN_CONFIGURATION, size: 1, message: &hdcp_cfg);
262 mutex_unlock(lock: &mhdp->mbox_mutex);
263
264 return ret;
265}
266
267static 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: &hdcp_port_status);
283 if (ret || cdns_mhdp_hdcp_handle_status(mhdp, status: hdcp_port_status))
284 return -1;
285
286 return 0;
287}
288
289static 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: &hdcp_port_status);
300 if (ret || cdns_mhdp_hdcp_handle_status(mhdp, status: 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
313static 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, recv_num: &hdcp_num_rec, hdcp_rx_id: (u8 *)hdcp_rec_id);
327 cdns_mhdp_hdcp_rx_id_valid_response(mhdp, valid: 1);
328
329 return 0;
330}
331
332static 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: &hdcp_port_status);
348 if (ret || cdns_mhdp_hdcp_handle_status(mhdp, status: hdcp_port_status))
349 return -1;
350 }
351
352 cdns_mhdp_hdcp_tx_is_km_stored(mhdp, resp, size: sizeof(resp));
353 cdns_mhdp_hdcp_km_stored_resp(mhdp, size: 0, NULL);
354
355 if (cdns_mhdp_hdcp_check_receviers(mhdp))
356 return -1;
357
358 return 0;
359}
360
361static 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
367static 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, enable: 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
388auth_failed:
389 return ret;
390}
391
392static 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, hdcp_config: 0, enable: false);
400
401 return ret;
402}
403
404static 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_config: 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_config: 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
433static 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: &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(work: &mhdp->hdcp.prop_work);
454 goto out;
455 }
456
457 ret = _cdns_mhdp_hdcp_enable(mhdp, content_type: mhdp->hdcp.hdcp_content_type);
458 if (ret) {
459 mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
460 schedule_work(work: &mhdp->hdcp.prop_work);
461 }
462out:
463 mutex_unlock(lock: &mhdp->hdcp.mutex);
464 return ret;
465}
466
467static 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(dwork: &hdcp->check_work,
479 DRM_HDCP_CHECK_PERIOD_MS);
480}
481
482static 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(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(lock: &mhdp->hdcp.mutex);
500 drm_modeset_unlock(lock: &dev->mode_config.connection_mutex);
501}
502
503int 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 opcode: HDCP_GENERAL_SET_LC_128,
510 size: 16, message: val);
511 mutex_unlock(lock: &mhdp->mbox_mutex);
512
513 return ret;
514}
515
516int
517cdns_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 opcode: HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
525 size: sizeof(*val), message: (u8 *)val);
526 mutex_unlock(lock: &mhdp->mbox_mutex);
527
528 return ret;
529}
530
531int 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(work: &mhdp->hdcp.prop_work);
543 schedule_delayed_work(dwork: &mhdp->hdcp.check_work,
544 DRM_HDCP_CHECK_PERIOD_MS);
545out:
546 mutex_unlock(lock: &mhdp->hdcp.mutex);
547 return ret;
548}
549
550int 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(work: &mhdp->hdcp.prop_work);
558 ret = _cdns_mhdp_hdcp_disable(mhdp);
559 }
560 mutex_unlock(lock: &mhdp->hdcp.mutex);
561 cancel_delayed_work_sync(dwork: &mhdp->hdcp.check_work);
562
563 return ret;
564}
565
566void 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}
572

source code of linux/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c