Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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, tries = 3;
407	u32 i;
408
409	for (i = 0; i < tries; i++) {
410		if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0 ||
411		    content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
412			ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_2);
413			if (!ret)
414				return 0;
415			_cdns_mhdp_hdcp_disable(mhdp);
416		}
417
418		if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
419			ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_1);
420			if (!ret)
421				return 0;
422			_cdns_mhdp_hdcp_disable(mhdp);
423		}
424	}
425
426	dev_err(mhdp->dev, "HDCP authentication failed (%d tries/%d)\n",
427		tries, ret);
428
429	return ret;
430}
431
432static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
433{
434	u16 hdcp_port_status;
435	int ret = 0;
436
437	mutex_lock(&mhdp->hdcp.mutex);
438	if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
439		goto out;
440
441	ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
442	if (!ret && hdcp_port_status & HDCP_PORT_STS_AUTH)
443		goto out;
444
445	dev_err(mhdp->dev,
446		"[%s:%d] HDCP link failed, retrying authentication\n",
447		mhdp->connector.name, mhdp->connector.base.id);
448
449	ret = _cdns_mhdp_hdcp_disable(mhdp);
450	if (ret) {
451		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
452		schedule_work(&mhdp->hdcp.prop_work);
453		goto out;
454	}
455
456	ret = _cdns_mhdp_hdcp_enable(mhdp, mhdp->hdcp.hdcp_content_type);
457	if (ret) {
458		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
459		schedule_work(&mhdp->hdcp.prop_work);
460	}
461out:
462	mutex_unlock(&mhdp->hdcp.mutex);
463	return ret;
464}
465
466static void cdns_mhdp_hdcp_check_work(struct work_struct *work)
467{
468	struct delayed_work *d_work = to_delayed_work(work);
469	struct cdns_mhdp_hdcp *hdcp = container_of(d_work,
470						   struct cdns_mhdp_hdcp,
471						   check_work);
472	struct cdns_mhdp_device *mhdp = container_of(hdcp,
473						     struct cdns_mhdp_device,
474						     hdcp);
475
476	if (!cdns_mhdp_hdcp_check_link(mhdp))
477		schedule_delayed_work(&hdcp->check_work,
478				      DRM_HDCP_CHECK_PERIOD_MS);
479}
480
481static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
482{
483	struct cdns_mhdp_hdcp *hdcp = container_of(work,
484						   struct cdns_mhdp_hdcp,
485						   prop_work);
486	struct cdns_mhdp_device *mhdp = container_of(hdcp,
487						     struct cdns_mhdp_device,
488						     hdcp);
489	struct drm_device *dev = mhdp->connector.dev;
490	struct drm_connector_state *state;
491
492	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
493	mutex_lock(&mhdp->hdcp.mutex);
494	if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
495		state = mhdp->connector.state;
496		state->content_protection = mhdp->hdcp.value;
497	}
498	mutex_unlock(&mhdp->hdcp.mutex);
499	drm_modeset_unlock(&dev->mode_config.connection_mutex);
500}
501
502int cdns_mhdp_hdcp_set_lc(struct cdns_mhdp_device *mhdp, u8 *val)
503{
504	int ret;
505
506	mutex_lock(&mhdp->mbox_mutex);
507	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_GENERAL,
508					    HDCP_GENERAL_SET_LC_128,
509					    16, val);
510	mutex_unlock(&mhdp->mbox_mutex);
511
512	return ret;
513}
514
515int
516cdns_mhdp_hdcp_set_public_key_param(struct cdns_mhdp_device *mhdp,
517				    struct cdns_hdcp_tx_public_key_param *val)
518{
519	int ret;
520
521	mutex_lock(&mhdp->mbox_mutex);
522	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
523					    HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
524					    sizeof(*val), (u8 *)val);
525	mutex_unlock(&mhdp->mbox_mutex);
526
527	return ret;
528}
529
530int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
531{
532	int ret;
533
534	mutex_lock(&mhdp->hdcp.mutex);
535	ret = _cdns_mhdp_hdcp_enable(mhdp, content_type);
536	if (ret)
537		goto out;
538
539	mhdp->hdcp.hdcp_content_type = content_type;
540	mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
541	schedule_work(&mhdp->hdcp.prop_work);
542	schedule_delayed_work(&mhdp->hdcp.check_work,
543			      DRM_HDCP_CHECK_PERIOD_MS);
544out:
545	mutex_unlock(&mhdp->hdcp.mutex);
546	return ret;
547}
548
549int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
550{
551	int ret = 0;
552
553	mutex_lock(&mhdp->hdcp.mutex);
554	if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
555		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
556		schedule_work(&mhdp->hdcp.prop_work);
557		ret = _cdns_mhdp_hdcp_disable(mhdp);
558	}
559	mutex_unlock(&mhdp->hdcp.mutex);
560	cancel_delayed_work_sync(&mhdp->hdcp.check_work);
561
562	return ret;
563}
564
565void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp)
566{
567	INIT_DELAYED_WORK(&mhdp->hdcp.check_work, cdns_mhdp_hdcp_check_work);
568	INIT_WORK(&mhdp->hdcp.prop_work, cdns_mhdp_hdcp_prop_work);
569	mutex_init(&mhdp->hdcp.mutex);
570}