linux/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
<<
>>
Prefs
   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/drm_hdcp.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}
 571