linux/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2019 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "hdcp.h"
  27
  28#define MIN(a, b) ((a) < (b) ? (a) : (b))
  29#define HDCP_I2C_ADDR 0x3a      /* 0x74 >> 1*/
  30#define KSV_READ_SIZE 0xf       /* 0x6803b - 0x6802c */
  31#define HDCP_MAX_AUX_TRANSACTION_SIZE 16
  32
  33#define DP_CP_IRQ (1 << 2)
  34
  35enum mod_hdcp_ddc_message_id {
  36        MOD_HDCP_MESSAGE_ID_INVALID = -1,
  37
  38        /* HDCP 1.4 */
  39
  40        MOD_HDCP_MESSAGE_ID_READ_BKSV = 0,
  41        MOD_HDCP_MESSAGE_ID_READ_RI_R0,
  42        MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
  43        MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
  44        MOD_HDCP_MESSAGE_ID_WRITE_AN,
  45        MOD_HDCP_MESSAGE_ID_READ_VH_X,
  46        MOD_HDCP_MESSAGE_ID_READ_VH_0,
  47        MOD_HDCP_MESSAGE_ID_READ_VH_1,
  48        MOD_HDCP_MESSAGE_ID_READ_VH_2,
  49        MOD_HDCP_MESSAGE_ID_READ_VH_3,
  50        MOD_HDCP_MESSAGE_ID_READ_VH_4,
  51        MOD_HDCP_MESSAGE_ID_READ_BCAPS,
  52        MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
  53        MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
  54        MOD_HDCP_MESSAGE_ID_READ_BINFO,
  55
  56        /* HDCP 2.2 */
  57
  58        MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
  59        MOD_HDCP_MESSAGE_ID_RX_CAPS,
  60        MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
  61        MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
  62        MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
  63        MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
  64        MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
  65        MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
  66        MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
  67        MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
  68        MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
  69        MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
  70        MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
  71        MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
  72        MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
  73        MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
  74        MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
  75        MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
  76
  77        MOD_HDCP_MESSAGE_ID_MAX
  78};
  79
  80static const uint8_t hdcp_i2c_offsets[] = {
  81        [MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
  82        [MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
  83        [MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
  84        [MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
  85        [MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
  86        [MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
  87        [MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
  88        [MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
  89        [MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
  90        [MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
  91        [MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
  92        [MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
  93        [MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
  94        [MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
  95        [MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
  96        [MOD_HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
  97        [MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
  98        [MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
  99        [MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
 100        [MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
 101        [MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
 102        [MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
 103        [MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
 104        [MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
 105        [MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
 106        [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
 107        [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x80,
 108        [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
 109        [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
 110        [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
 111        [MOD_HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
 112        [MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0
 113};
 114
 115static const uint32_t hdcp_dpcd_addrs[] = {
 116        [MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
 117        [MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
 118        [MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
 119        [MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
 120        [MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
 121        [MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
 122        [MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
 123        [MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
 124        [MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
 125        [MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
 126        [MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
 127        [MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
 128        [MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
 129        [MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
 130        [MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
 131        [MOD_HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
 132        [MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
 133        [MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
 134        [MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
 135        [MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
 136        [MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
 137        [MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
 138        [MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
 139        [MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
 140        [MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
 141        [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
 142        [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x69340,
 143        [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
 144        [MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
 145        [MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
 146        [MOD_HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
 147        [MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
 148};
 149
 150static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
 151                enum mod_hdcp_ddc_message_id msg_id,
 152                uint8_t *buf,
 153                uint32_t buf_len)
 154{
 155        bool success = true;
 156        uint32_t cur_size = 0;
 157        uint32_t data_offset = 0;
 158
 159        if (is_dp_hdcp(hdcp)) {
 160                while (buf_len > 0) {
 161                        cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
 162                        success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
 163                                        hdcp_dpcd_addrs[msg_id] + data_offset,
 164                                        buf + data_offset,
 165                                        cur_size);
 166
 167                        if (!success)
 168                                break;
 169
 170                        buf_len -= cur_size;
 171                        data_offset += cur_size;
 172                }
 173        } else {
 174                success = hdcp->config.ddc.funcs.read_i2c(
 175                                hdcp->config.ddc.handle,
 176                                HDCP_I2C_ADDR,
 177                                hdcp_i2c_offsets[msg_id],
 178                                buf,
 179                                (uint32_t)buf_len);
 180        }
 181
 182        return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
 183}
 184
 185static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp,
 186                enum mod_hdcp_ddc_message_id msg_id,
 187                uint8_t *buf,
 188                uint32_t buf_len,
 189                uint8_t read_size)
 190{
 191        enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE;
 192        uint32_t cur_size = 0;
 193        uint32_t data_offset = 0;
 194
 195        while (buf_len > 0) {
 196                cur_size = MIN(buf_len, read_size);
 197                status = read(hdcp, msg_id, buf + data_offset, cur_size);
 198
 199                if (status != MOD_HDCP_STATUS_SUCCESS)
 200                        break;
 201
 202                buf_len -= cur_size;
 203                data_offset += cur_size;
 204        }
 205
 206        return status;
 207}
 208
 209static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
 210                enum mod_hdcp_ddc_message_id msg_id,
 211                uint8_t *buf,
 212                uint32_t buf_len)
 213{
 214        bool success = true;
 215        uint32_t cur_size = 0;
 216        uint32_t data_offset = 0;
 217
 218        if (is_dp_hdcp(hdcp)) {
 219                while (buf_len > 0) {
 220                        cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
 221                        success = hdcp->config.ddc.funcs.write_dpcd(
 222                                        hdcp->config.ddc.handle,
 223                                        hdcp_dpcd_addrs[msg_id] + data_offset,
 224                                        buf + data_offset,
 225                                        cur_size);
 226
 227                        if (!success)
 228                                break;
 229
 230                        buf_len -= cur_size;
 231                        data_offset += cur_size;
 232                }
 233        } else {
 234                hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
 235                memmove(&hdcp->buf[1], buf, buf_len);
 236                success = hdcp->config.ddc.funcs.write_i2c(
 237                                hdcp->config.ddc.handle,
 238                                HDCP_I2C_ADDR,
 239                                hdcp->buf,
 240                                (uint32_t)(buf_len+1));
 241        }
 242
 243        return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
 244}
 245
 246enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp)
 247{
 248        return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV,
 249                        hdcp->auth.msg.hdcp1.bksv,
 250                        sizeof(hdcp->auth.msg.hdcp1.bksv));
 251}
 252
 253enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp)
 254{
 255        return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS,
 256                        &hdcp->auth.msg.hdcp1.bcaps,
 257                        sizeof(hdcp->auth.msg.hdcp1.bcaps));
 258}
 259
 260enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp)
 261{
 262        enum mod_hdcp_status status;
 263
 264        if (is_dp_hdcp(hdcp))
 265                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
 266                                        (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
 267                                        1);
 268        else
 269                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
 270                                (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
 271                                sizeof(hdcp->auth.msg.hdcp1.bstatus));
 272        return status;
 273}
 274
 275enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp)
 276{
 277        return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0,
 278                        (uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
 279                        sizeof(hdcp->auth.msg.hdcp1.r0p));
 280}
 281
 282/* special case, reading repeatedly at the same address, don't use read() */
 283enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp)
 284{
 285        enum mod_hdcp_status status;
 286
 287        if (is_dp_hdcp(hdcp))
 288                status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
 289                                hdcp->auth.msg.hdcp1.ksvlist,
 290                                hdcp->auth.msg.hdcp1.ksvlist_size,
 291                                KSV_READ_SIZE);
 292        else
 293                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
 294                                (uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist,
 295                                hdcp->auth.msg.hdcp1.ksvlist_size);
 296        return status;
 297}
 298
 299enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp)
 300{
 301        enum mod_hdcp_status status;
 302
 303        status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0,
 304                        &hdcp->auth.msg.hdcp1.vp[0], 4);
 305        if (status != MOD_HDCP_STATUS_SUCCESS)
 306                goto out;
 307
 308        status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1,
 309                        &hdcp->auth.msg.hdcp1.vp[4], 4);
 310        if (status != MOD_HDCP_STATUS_SUCCESS)
 311                goto out;
 312
 313        status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2,
 314                        &hdcp->auth.msg.hdcp1.vp[8], 4);
 315        if (status != MOD_HDCP_STATUS_SUCCESS)
 316                goto out;
 317
 318        status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3,
 319                        &hdcp->auth.msg.hdcp1.vp[12], 4);
 320        if (status != MOD_HDCP_STATUS_SUCCESS)
 321                goto out;
 322
 323        status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4,
 324                        &hdcp->auth.msg.hdcp1.vp[16], 4);
 325out:
 326        return status;
 327}
 328
 329enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp)
 330{
 331        enum mod_hdcp_status status;
 332
 333        if (is_dp_hdcp(hdcp))
 334                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO,
 335                                (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
 336                                sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
 337        else
 338                status = MOD_HDCP_STATUS_INVALID_OPERATION;
 339
 340        return status;
 341}
 342
 343enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp)
 344{
 345        return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
 346                        hdcp->auth.msg.hdcp1.aksv,
 347                        sizeof(hdcp->auth.msg.hdcp1.aksv));
 348}
 349
 350enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp)
 351{
 352        return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
 353                        &hdcp->auth.msg.hdcp1.ainfo,
 354                        sizeof(hdcp->auth.msg.hdcp1.ainfo));
 355}
 356
 357enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp)
 358{
 359        return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN,
 360                        hdcp->auth.msg.hdcp1.an,
 361                        sizeof(hdcp->auth.msg.hdcp1.an));
 362}
 363
 364enum mod_hdcp_status mod_hdcp_read_hdcp2version(struct mod_hdcp *hdcp)
 365{
 366        enum mod_hdcp_status status;
 367
 368        if (is_dp_hdcp(hdcp))
 369                status = MOD_HDCP_STATUS_INVALID_OPERATION;
 370        else
 371                status = read(hdcp, MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
 372                                &hdcp->auth.msg.hdcp2.hdcp2version_hdmi,
 373                                sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi));
 374
 375        return status;
 376}
 377
 378enum mod_hdcp_status mod_hdcp_read_rxcaps(struct mod_hdcp *hdcp)
 379{
 380        enum mod_hdcp_status status;
 381
 382        if (!is_dp_hdcp(hdcp))
 383                status = MOD_HDCP_STATUS_INVALID_OPERATION;
 384        else
 385                status = read(hdcp, MOD_HDCP_MESSAGE_ID_RX_CAPS,
 386                                hdcp->auth.msg.hdcp2.rxcaps_dp,
 387                                sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp));
 388
 389        return status;
 390}
 391
 392enum mod_hdcp_status mod_hdcp_read_rxstatus(struct mod_hdcp *hdcp)
 393{
 394        enum mod_hdcp_status status;
 395
 396        if (is_dp_hdcp(hdcp)) {
 397                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
 398                                &hdcp->auth.msg.hdcp2.rxstatus_dp,
 399                                1);
 400        } else {
 401                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
 402                                        (uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus,
 403                                        sizeof(hdcp->auth.msg.hdcp2.rxstatus));
 404        }
 405        return status;
 406}
 407
 408enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp)
 409{
 410        enum mod_hdcp_status status;
 411
 412        if (is_dp_hdcp(hdcp)) {
 413                hdcp->auth.msg.hdcp2.ake_cert[0] = HDCP_2_2_AKE_SEND_CERT;
 414                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
 415                                hdcp->auth.msg.hdcp2.ake_cert+1,
 416                                sizeof(hdcp->auth.msg.hdcp2.ake_cert)-1);
 417
 418        } else {
 419                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
 420                                        hdcp->auth.msg.hdcp2.ake_cert,
 421                                        sizeof(hdcp->auth.msg.hdcp2.ake_cert));
 422        }
 423        return status;
 424}
 425
 426enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp)
 427{
 428        enum mod_hdcp_status status;
 429
 430        if (is_dp_hdcp(hdcp)) {
 431                hdcp->auth.msg.hdcp2.ake_h_prime[0] = HDCP_2_2_AKE_SEND_HPRIME;
 432                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
 433                                hdcp->auth.msg.hdcp2.ake_h_prime+1,
 434                                sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)-1);
 435
 436        } else {
 437                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
 438                                hdcp->auth.msg.hdcp2.ake_h_prime,
 439                                sizeof(hdcp->auth.msg.hdcp2.ake_h_prime));
 440        }
 441        return status;
 442}
 443
 444enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp)
 445{
 446        enum mod_hdcp_status status;
 447
 448        if (is_dp_hdcp(hdcp)) {
 449                hdcp->auth.msg.hdcp2.ake_pairing_info[0] = HDCP_2_2_AKE_SEND_PAIRING_INFO;
 450                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
 451                                hdcp->auth.msg.hdcp2.ake_pairing_info+1,
 452                                sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)-1);
 453
 454        } else {
 455                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
 456                                hdcp->auth.msg.hdcp2.ake_pairing_info,
 457                                sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info));
 458        }
 459        return status;
 460}
 461
 462enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp)
 463{
 464        enum mod_hdcp_status status;
 465
 466        if (is_dp_hdcp(hdcp)) {
 467                hdcp->auth.msg.hdcp2.lc_l_prime[0] = HDCP_2_2_LC_SEND_LPRIME;
 468                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
 469                                hdcp->auth.msg.hdcp2.lc_l_prime+1,
 470                                sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)-1);
 471
 472        } else {
 473                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
 474                                hdcp->auth.msg.hdcp2.lc_l_prime,
 475                                sizeof(hdcp->auth.msg.hdcp2.lc_l_prime));
 476        }
 477        return status;
 478}
 479
 480enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp)
 481{
 482        enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
 483
 484        if (is_dp_hdcp(hdcp)) {
 485                uint32_t device_count = 0;
 486                uint32_t rx_id_list_size = 0;
 487                uint32_t bytes_read = 0;
 488
 489                hdcp->auth.msg.hdcp2.rx_id_list[0] = HDCP_2_2_REP_SEND_RECVID_LIST;
 490                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
 491                                                hdcp->auth.msg.hdcp2.rx_id_list+1,
 492                                                HDCP_MAX_AUX_TRANSACTION_SIZE);
 493                if (status == MOD_HDCP_STATUS_SUCCESS) {
 494                        bytes_read = HDCP_MAX_AUX_TRANSACTION_SIZE;
 495                        device_count = HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) +
 496                                        (HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4);
 497                        rx_id_list_size = MIN((21 + 5 * device_count),
 498                                        (sizeof(hdcp->auth.msg.hdcp2.rx_id_list) - 1));
 499                        status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
 500                                        hdcp->auth.msg.hdcp2.rx_id_list + 1 + bytes_read,
 501                                        (rx_id_list_size - 1) / HDCP_MAX_AUX_TRANSACTION_SIZE * HDCP_MAX_AUX_TRANSACTION_SIZE);
 502                }
 503        } else {
 504                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
 505                                hdcp->auth.msg.hdcp2.rx_id_list,
 506                                hdcp->auth.msg.hdcp2.rx_id_list_size);
 507        }
 508        return status;
 509}
 510
 511enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp)
 512{
 513        enum mod_hdcp_status status;
 514
 515        if (is_dp_hdcp(hdcp)) {
 516                hdcp->auth.msg.hdcp2.repeater_auth_stream_ready[0] = HDCP_2_2_REP_STREAM_READY;
 517                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
 518                                hdcp->auth.msg.hdcp2.repeater_auth_stream_ready+1,
 519                                sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)-1);
 520
 521        } else {
 522                status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
 523                                hdcp->auth.msg.hdcp2.repeater_auth_stream_ready,
 524                                sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready));
 525        }
 526        return status;
 527}
 528
 529enum mod_hdcp_status mod_hdcp_write_ake_init(struct mod_hdcp *hdcp)
 530{
 531        enum mod_hdcp_status status;
 532
 533        if (is_dp_hdcp(hdcp))
 534                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
 535                                hdcp->auth.msg.hdcp2.ake_init+1,
 536                                sizeof(hdcp->auth.msg.hdcp2.ake_init)-1);
 537        else
 538                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
 539                                        hdcp->auth.msg.hdcp2.ake_init,
 540                                        sizeof(hdcp->auth.msg.hdcp2.ake_init));
 541        return status;
 542}
 543
 544enum mod_hdcp_status mod_hdcp_write_no_stored_km(struct mod_hdcp *hdcp)
 545{
 546        enum mod_hdcp_status status;
 547
 548        if (is_dp_hdcp(hdcp))
 549                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
 550                                hdcp->auth.msg.hdcp2.ake_no_stored_km+1,
 551                                sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)-1);
 552        else
 553                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
 554                        hdcp->auth.msg.hdcp2.ake_no_stored_km,
 555                        sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km));
 556        return status;
 557}
 558
 559enum mod_hdcp_status mod_hdcp_write_stored_km(struct mod_hdcp *hdcp)
 560{
 561        enum mod_hdcp_status status;
 562
 563        if (is_dp_hdcp(hdcp))
 564                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
 565                                hdcp->auth.msg.hdcp2.ake_stored_km+1,
 566                                sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)-1);
 567        else
 568                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
 569                                hdcp->auth.msg.hdcp2.ake_stored_km,
 570                                sizeof(hdcp->auth.msg.hdcp2.ake_stored_km));
 571        return status;
 572}
 573
 574enum mod_hdcp_status mod_hdcp_write_lc_init(struct mod_hdcp *hdcp)
 575{
 576        enum mod_hdcp_status status;
 577
 578        if (is_dp_hdcp(hdcp))
 579                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
 580                                hdcp->auth.msg.hdcp2.lc_init+1,
 581                                sizeof(hdcp->auth.msg.hdcp2.lc_init)-1);
 582        else
 583                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
 584                                hdcp->auth.msg.hdcp2.lc_init,
 585                                sizeof(hdcp->auth.msg.hdcp2.lc_init));
 586        return status;
 587}
 588
 589enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp)
 590{
 591        enum mod_hdcp_status status;
 592
 593        if (is_dp_hdcp(hdcp))
 594                status = write(hdcp,
 595                                MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
 596                                hdcp->auth.msg.hdcp2.ske_eks+1,
 597                                sizeof(hdcp->auth.msg.hdcp2.ske_eks)-1);
 598        else
 599                status = write(hdcp,
 600                        MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
 601                        hdcp->auth.msg.hdcp2.ske_eks,
 602                        sizeof(hdcp->auth.msg.hdcp2.ske_eks));
 603        return status;
 604}
 605
 606enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp)
 607{
 608        enum mod_hdcp_status status;
 609
 610        if (is_dp_hdcp(hdcp))
 611                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
 612                                hdcp->auth.msg.hdcp2.repeater_auth_ack+1,
 613                                sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)-1);
 614        else
 615                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
 616                                hdcp->auth.msg.hdcp2.repeater_auth_ack,
 617                                sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack));
 618        return status;
 619}
 620
 621enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp)
 622{
 623        enum mod_hdcp_status status;
 624
 625        if (is_dp_hdcp(hdcp))
 626                status = write(hdcp,
 627                                MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
 628                                hdcp->auth.msg.hdcp2.repeater_auth_stream_manage+1,
 629                                hdcp->auth.msg.hdcp2.stream_manage_size-1);
 630        else
 631                status = write(hdcp,
 632                                MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
 633                                hdcp->auth.msg.hdcp2.repeater_auth_stream_manage,
 634                                hdcp->auth.msg.hdcp2.stream_manage_size);
 635        return status;
 636}
 637
 638enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp)
 639{
 640        enum mod_hdcp_status status;
 641
 642        if (is_dp_hdcp(hdcp))
 643                status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
 644                                hdcp->auth.msg.hdcp2.content_stream_type_dp+1,
 645                                sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp)-1);
 646        else
 647                status = MOD_HDCP_STATUS_INVALID_OPERATION;
 648        return status;
 649}
 650
 651enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp)
 652{
 653        uint8_t clear_cp_irq_bit = DP_CP_IRQ;
 654        uint32_t size = 1;
 655
 656        if (is_dp_hdcp(hdcp)) {
 657                uint32_t cp_irq_addrs = (hdcp->connection.link.dp.rev >= 0x14)
 658                                ? DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0:DP_DEVICE_SERVICE_IRQ_VECTOR;
 659                return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, cp_irq_addrs,
 660                                &clear_cp_irq_bit, size) ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
 661        }
 662
 663        return MOD_HDCP_STATUS_INVALID_OPERATION;
 664}
 665