cdns-mhdp8546-hdcp.c (13369B)
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}