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(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, 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(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(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
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					    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
153err_get_hdcp_status:
154	mutex_unlock(&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					    HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
178					    1, &valid);
179	mutex_unlock(&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					    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
211err_rx_id_valid:
212	mutex_unlock(&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					    HDCP2X_TX_RESPOND_KM, size, km);
225	mutex_unlock(&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					    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);
248err_is_km_stored:
249	mutex_unlock(&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					    HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg);
262	mutex_unlock(&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);
283	if (ret || cdns_mhdp_hdcp_handle_status(mhdp, 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);
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
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, &hdcp_num_rec, (u8 *)hdcp_rec_id);
327	cdns_mhdp_hdcp_rx_id_valid_response(mhdp, 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);
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
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, 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, 0, 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_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
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);
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	}
462out:
463	mutex_unlock(&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(&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(&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
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					    HDCP_GENERAL_SET_LC_128,
510					    16, val);
511	mutex_unlock(&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					    HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
525					    sizeof(*val), (u8 *)val);
526	mutex_unlock(&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(&mhdp->hdcp.prop_work);
543	schedule_delayed_work(&mhdp->hdcp.check_work,
544			      DRM_HDCP_CHECK_PERIOD_MS);
545out:
546	mutex_unlock(&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(&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
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