linux/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.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 <linux/slab.h>
  27
  28#include "dm_services.h"
  29#include "dm_helpers.h"
  30#include "include/hdcp_types.h"
  31#include "include/i2caux_interface.h"
  32#include "include/signal_types.h"
  33#include "core_types.h"
  34#include "dc_link_ddc.h"
  35#include "link_hwss.h"
  36#include "inc/link_dpcd.h"
  37
  38#define DC_LOGGER \
  39        link->ctx->logger
  40#define HDCP14_KSV_SIZE 5
  41#define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE
  42
  43static const bool hdcp_cmd_is_read[HDCP_MESSAGE_ID_MAX] = {
  44        [HDCP_MESSAGE_ID_READ_BKSV] = true,
  45        [HDCP_MESSAGE_ID_READ_RI_R0] = true,
  46        [HDCP_MESSAGE_ID_READ_PJ] = true,
  47        [HDCP_MESSAGE_ID_WRITE_AKSV] = false,
  48        [HDCP_MESSAGE_ID_WRITE_AINFO] = false,
  49        [HDCP_MESSAGE_ID_WRITE_AN] = false,
  50        [HDCP_MESSAGE_ID_READ_VH_X] = true,
  51        [HDCP_MESSAGE_ID_READ_VH_0] = true,
  52        [HDCP_MESSAGE_ID_READ_VH_1] = true,
  53        [HDCP_MESSAGE_ID_READ_VH_2] = true,
  54        [HDCP_MESSAGE_ID_READ_VH_3] = true,
  55        [HDCP_MESSAGE_ID_READ_VH_4] = true,
  56        [HDCP_MESSAGE_ID_READ_BCAPS] = true,
  57        [HDCP_MESSAGE_ID_READ_BSTATUS] = true,
  58        [HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,
  59        [HDCP_MESSAGE_ID_READ_BINFO] = true,
  60        [HDCP_MESSAGE_ID_HDCP2VERSION] = true,
  61        [HDCP_MESSAGE_ID_RX_CAPS] = true,
  62        [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,
  63        [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,
  64        [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,
  65        [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,
  66        [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,
  67        [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,
  68        [HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,
  69        [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,
  70        [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,
  71        [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,
  72        [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,
  73        [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,
  74        [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,
  75        [HDCP_MESSAGE_ID_READ_RXSTATUS] = true,
  76        [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false
  77};
  78
  79static const uint8_t hdcp_i2c_offsets[HDCP_MESSAGE_ID_MAX] = {
  80        [HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
  81        [HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
  82        [HDCP_MESSAGE_ID_READ_PJ] = 0xA,
  83        [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
  84        [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
  85        [HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
  86        [HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
  87        [HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
  88        [HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
  89        [HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
  90        [HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
  91        [HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
  92        [HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
  93        [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
  94        [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
  95        [HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
  96        [HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
  97        [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
  98        [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
  99        [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
 100        [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
 101        [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
 102        [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
 103        [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
 104        [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
 105        [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
 106        [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
 107        [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
 108        [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
 109        [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
 110        [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
 111        [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0,
 112};
 113
 114struct protection_properties {
 115        bool supported;
 116        bool (*process_transaction)(
 117                struct dc_link *link,
 118                struct hdcp_protection_message *message_info);
 119};
 120
 121static const struct protection_properties non_supported_protection = {
 122        .supported = false
 123};
 124
 125static bool hdmi_14_process_transaction(
 126        struct dc_link *link,
 127        struct hdcp_protection_message *message_info)
 128{
 129        uint8_t *buff = NULL;
 130        bool result;
 131        const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
 132        const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
 133        struct i2c_command i2c_command;
 134        uint8_t offset = hdcp_i2c_offsets[message_info->msg_id];
 135        struct i2c_payload i2c_payloads[] = {
 136                { true, 0, 1, &offset },
 137                /* actual hdcp payload, will be filled later, zeroed for now*/
 138                { 0 }
 139        };
 140
 141        switch (message_info->link) {
 142        case HDCP_LINK_SECONDARY:
 143                i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
 144                i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
 145                break;
 146        case HDCP_LINK_PRIMARY:
 147        default:
 148                i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
 149                i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
 150                break;
 151        }
 152
 153        if (hdcp_cmd_is_read[message_info->msg_id]) {
 154                i2c_payloads[1].write = false;
 155                i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
 156                i2c_payloads[1].length = message_info->length;
 157                i2c_payloads[1].data = message_info->data;
 158        } else {
 159                i2c_command.number_of_payloads = 1;
 160                buff = kzalloc(message_info->length + 1, GFP_KERNEL);
 161
 162                if (!buff)
 163                        return false;
 164
 165                buff[0] = offset;
 166                memmove(&buff[1], message_info->data, message_info->length);
 167                i2c_payloads[0].length = message_info->length + 1;
 168                i2c_payloads[0].data = buff;
 169        }
 170
 171        i2c_command.payloads = i2c_payloads;
 172        i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
 173        i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
 174
 175        result = dm_helpers_submit_i2c(
 176                        link->ctx,
 177                        link,
 178                        &i2c_command);
 179        kfree(buff);
 180
 181        return result;
 182}
 183
 184static const struct protection_properties hdmi_14_protection = {
 185        .supported = true,
 186        .process_transaction = hdmi_14_process_transaction
 187};
 188
 189static const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {
 190        [HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
 191        [HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
 192        [HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
 193        [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
 194        [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
 195        [HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
 196        [HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
 197        [HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
 198        [HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
 199        [HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
 200        [HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
 201        [HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
 202        [HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
 203        [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
 204        [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
 205        [HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
 206        [HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
 207        [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
 208        [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
 209        [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
 210        [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
 211        [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
 212        [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
 213        [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
 214        [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
 215        [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
 216        [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
 217        [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
 218        [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
 219        [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
 220        [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
 221        [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
 222};
 223
 224static bool dpcd_access_helper(
 225        struct dc_link *link,
 226        uint32_t length,
 227        uint8_t *data,
 228        uint32_t dpcd_addr,
 229        bool is_read)
 230{
 231        enum dc_status status;
 232        uint32_t cur_length = 0;
 233        uint32_t offset = 0;
 234        uint32_t ksv_read_size = 0x6803b - 0x6802c;
 235
 236        /* Read KSV, need repeatedly handle */
 237        if (dpcd_addr == 0x6802c) {
 238                if (length % HDCP14_KSV_SIZE) {
 239                        DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",
 240                                __func__,
 241                                length,
 242                                HDCP14_KSV_SIZE);
 243                }
 244                if (length > HDCP14_MAX_KSV_FIFO_SIZE) {
 245                        DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",
 246                                __func__,
 247                                length,
 248                                HDCP14_MAX_KSV_FIFO_SIZE);
 249                }
 250
 251                DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",
 252                        __func__,
 253                        length / HDCP14_KSV_SIZE);
 254
 255                while (length > 0) {
 256                        if (length > ksv_read_size) {
 257                                status = core_link_read_dpcd(
 258                                        link,
 259                                        dpcd_addr + offset,
 260                                        data + offset,
 261                                        ksv_read_size);
 262
 263                                data += ksv_read_size;
 264                                length -= ksv_read_size;
 265                        } else {
 266                                status = core_link_read_dpcd(
 267                                        link,
 268                                        dpcd_addr + offset,
 269                                        data + offset,
 270                                        length);
 271
 272                                data += length;
 273                                length = 0;
 274                        }
 275
 276                        if (status != DC_OK)
 277                                return false;
 278                }
 279        } else {
 280                while (length > 0) {
 281                        if (length > DEFAULT_AUX_MAX_DATA_SIZE)
 282                                cur_length = DEFAULT_AUX_MAX_DATA_SIZE;
 283                        else
 284                                cur_length = length;
 285
 286                        if (is_read) {
 287                                status = core_link_read_dpcd(
 288                                        link,
 289                                        dpcd_addr + offset,
 290                                        data + offset,
 291                                        cur_length);
 292                        } else {
 293                                status = core_link_write_dpcd(
 294                                        link,
 295                                        dpcd_addr + offset,
 296                                        data + offset,
 297                                        cur_length);
 298                        }
 299
 300                        if (status != DC_OK)
 301                                return false;
 302
 303                        length -= cur_length;
 304                        offset += cur_length;
 305                }
 306        }
 307        return true;
 308}
 309
 310static bool dp_11_process_transaction(
 311        struct dc_link *link,
 312        struct hdcp_protection_message *message_info)
 313{
 314        return dpcd_access_helper(
 315                link,
 316                message_info->length,
 317                message_info->data,
 318                hdcp_dpcd_addrs[message_info->msg_id],
 319                hdcp_cmd_is_read[message_info->msg_id]);
 320}
 321
 322static const struct protection_properties dp_11_protection = {
 323        .supported = true,
 324        .process_transaction = dp_11_process_transaction
 325};
 326
 327static const struct protection_properties *get_protection_properties_by_signal(
 328        struct dc_link *link,
 329        enum signal_type st,
 330        enum hdcp_version version)
 331{
 332        switch (version) {
 333        case HDCP_VERSION_14:
 334                switch (st) {
 335                case SIGNAL_TYPE_DVI_SINGLE_LINK:
 336                case SIGNAL_TYPE_DVI_DUAL_LINK:
 337                case SIGNAL_TYPE_HDMI_TYPE_A:
 338                        return &hdmi_14_protection;
 339                case SIGNAL_TYPE_DISPLAY_PORT:
 340                        if (link &&
 341                                (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
 342                                link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) {
 343                                return &non_supported_protection;
 344                        }
 345                        return &dp_11_protection;
 346                case SIGNAL_TYPE_DISPLAY_PORT_MST:
 347                case SIGNAL_TYPE_EDP:
 348                        return &dp_11_protection;
 349                default:
 350                        return &non_supported_protection;
 351                }
 352                break;
 353        case HDCP_VERSION_22:
 354                switch (st) {
 355                case SIGNAL_TYPE_DVI_SINGLE_LINK:
 356                case SIGNAL_TYPE_DVI_DUAL_LINK:
 357                case SIGNAL_TYPE_HDMI_TYPE_A:
 358                        return &hdmi_14_protection; //todo version2.2
 359                case SIGNAL_TYPE_DISPLAY_PORT:
 360                case SIGNAL_TYPE_DISPLAY_PORT_MST:
 361                case SIGNAL_TYPE_EDP:
 362                        return &dp_11_protection;  //todo version2.2
 363                default:
 364                        return &non_supported_protection;
 365                }
 366                break;
 367        default:
 368                return &non_supported_protection;
 369        }
 370}
 371
 372enum hdcp_message_status dc_process_hdcp_msg(
 373        enum signal_type signal,
 374        struct dc_link *link,
 375        struct hdcp_protection_message *message_info)
 376{
 377        enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;
 378        uint32_t i = 0;
 379
 380        const struct protection_properties *protection_props;
 381
 382        if (!message_info)
 383                return HDCP_MESSAGE_UNSUPPORTED;
 384
 385        if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||
 386                message_info->msg_id >= HDCP_MESSAGE_ID_MAX)
 387                return HDCP_MESSAGE_UNSUPPORTED;
 388
 389        protection_props =
 390                get_protection_properties_by_signal(
 391                        link,
 392                        signal,
 393                        message_info->version);
 394
 395        if (!protection_props->supported)
 396                return HDCP_MESSAGE_UNSUPPORTED;
 397
 398        if (protection_props->process_transaction(
 399                link,
 400                message_info)) {
 401                status = HDCP_MESSAGE_SUCCESS;
 402        } else {
 403                for (i = 0; i < message_info->max_retries; i++) {
 404                        if (protection_props->process_transaction(
 405                                                link,
 406                                                message_info)) {
 407                                status = HDCP_MESSAGE_SUCCESS;
 408                                break;
 409                        }
 410                }
 411        }
 412
 413        return status;
 414}
 415
 416