Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: Add HDCP module

This module manages HDCP for amdgpu driver. The module behaves as a
state machine which handles the different authentication states of HDCP

The module is divided into 3 major components
+--------+
| Hdcp.c |
+--------+
Manages the state machine, sends the events to be executed and communicates
with the dm

+-----------+
|Execution.c|
+-----------+
This executes events based on the current state. Also generates
execution results as transition inputs

+------------+
|Transition.c|
+------------+
Decides the next state based on the input and makes requests to
hdcp.c to handle.
+-------------+
------> | Execution.c | ------
| +-------------+ |
| V
+----+ +--------+ +--------------+
| DM | -----> | Hdcp.c | <------------ | Transition.c |
+----+ <----- +--------+ +--------------+

v2: Drop unused function definitions

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Wenjing Liu <Wenjing.Liu@amd.com>
Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Bhawanpreet Lakha and committed by
Alex Deucher
4c283fda 143f2305

+3095
+7
drivers/gpu/drm/amd/display/Makefile
··· 34 34 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color 35 35 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet 36 36 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power 37 + ifdef CONFIG_DRM_AMD_DC_HDCP 38 + subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp 39 + endif 37 40 38 41 #TODO: remove when Timing Sync feature is complete 39 42 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 40 43 41 44 DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet modules/power 45 + 46 + ifdef CONFIG_DRM_AMD_DC_HDCP 47 + DAL_LIBS += modules/hdcp 48 + endif 42 49 43 50 AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS))) 44 51
+4
drivers/gpu/drm/amd/display/dc/Makefile
··· 48 48 DC_LIBS += dce100 49 49 DC_LIBS += dce80 50 50 51 + ifdef CONFIG_DRM_AMD_DC_HDCP 52 + DC_LIBS += hdcp 53 + endif 54 + 51 55 AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS))) 52 56 53 57 include $(AMD_DC)
+28
drivers/gpu/drm/amd/display/dc/hdcp/Makefile
··· 1 + # Copyright 2019 Advanced Micro Devices, Inc. 2 + # 3 + # Permission is hereby granted, free of charge, to any person obtaining a 4 + # copy of this software and associated documentation files (the "Software"), 5 + # to deal in the Software without restriction, including without limitation 6 + # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 + # and/or sell copies of the Software, and to permit persons to whom the 8 + # Software is furnished to do so, subject to the following conditions: 9 + # 10 + # The above copyright notice and this permission notice shall be included in 11 + # all copies or substantial portions of the Software. 12 + # 13 + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 + # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 + # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 + # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 + # OTHER DEALINGS IN THE SOFTWARE. 20 + # 21 + # Makefile for the 'hdcp' sub-component of DAL. 22 + # 23 + 24 + HDCP_MSG = hdcp_msg.o 25 + 26 + AMD_DAL_HDCP_MSG = $(addprefix $(AMDDALPATH)/dc/hdcp/,$(HDCP_MSG)) 27 + 28 + AMD_DISPLAY_FILES += $(AMD_DAL_HDCP_MSG)
+326
drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
··· 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 + 37 + #define DC_LOGGER \ 38 + link->ctx->logger 39 + #define HDCP14_KSV_SIZE 5 40 + #define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE 41 + 42 + static const bool hdcp_cmd_is_read[] = { 43 + [HDCP_MESSAGE_ID_READ_BKSV] = true, 44 + [HDCP_MESSAGE_ID_READ_RI_R0] = true, 45 + [HDCP_MESSAGE_ID_READ_PJ] = true, 46 + [HDCP_MESSAGE_ID_WRITE_AKSV] = false, 47 + [HDCP_MESSAGE_ID_WRITE_AINFO] = false, 48 + [HDCP_MESSAGE_ID_WRITE_AN] = false, 49 + [HDCP_MESSAGE_ID_READ_VH_X] = true, 50 + [HDCP_MESSAGE_ID_READ_VH_0] = true, 51 + [HDCP_MESSAGE_ID_READ_VH_1] = true, 52 + [HDCP_MESSAGE_ID_READ_VH_2] = true, 53 + [HDCP_MESSAGE_ID_READ_VH_3] = true, 54 + [HDCP_MESSAGE_ID_READ_VH_4] = true, 55 + [HDCP_MESSAGE_ID_READ_BCAPS] = true, 56 + [HDCP_MESSAGE_ID_READ_BSTATUS] = true, 57 + [HDCP_MESSAGE_ID_READ_KSV_FIFO] = true, 58 + [HDCP_MESSAGE_ID_READ_BINFO] = true, 59 + [HDCP_MESSAGE_ID_HDCP2VERSION] = true, 60 + [HDCP_MESSAGE_ID_RX_CAPS] = true, 61 + [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false, 62 + [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true, 63 + [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false, 64 + [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false, 65 + [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true, 66 + [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true, 67 + [HDCP_MESSAGE_ID_WRITE_LC_INIT] = false, 68 + [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true, 69 + [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false, 70 + [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true, 71 + [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false, 72 + [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false, 73 + [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true, 74 + [HDCP_MESSAGE_ID_READ_RXSTATUS] = true, 75 + [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false 76 + }; 77 + 78 + static const uint8_t hdcp_i2c_offsets[] = { 79 + [HDCP_MESSAGE_ID_READ_BKSV] = 0x0, 80 + [HDCP_MESSAGE_ID_READ_RI_R0] = 0x8, 81 + [HDCP_MESSAGE_ID_READ_PJ] = 0xA, 82 + [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10, 83 + [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15, 84 + [HDCP_MESSAGE_ID_WRITE_AN] = 0x18, 85 + [HDCP_MESSAGE_ID_READ_VH_X] = 0x20, 86 + [HDCP_MESSAGE_ID_READ_VH_0] = 0x20, 87 + [HDCP_MESSAGE_ID_READ_VH_1] = 0x24, 88 + [HDCP_MESSAGE_ID_READ_VH_2] = 0x28, 89 + [HDCP_MESSAGE_ID_READ_VH_3] = 0x2C, 90 + [HDCP_MESSAGE_ID_READ_VH_4] = 0x30, 91 + [HDCP_MESSAGE_ID_READ_BCAPS] = 0x40, 92 + [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41, 93 + [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43, 94 + [HDCP_MESSAGE_ID_READ_BINFO] = 0xFF, 95 + [HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50, 96 + [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60, 97 + [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80, 98 + [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60, 99 + [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60, 100 + [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80, 101 + [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80, 102 + [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60, 103 + [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80, 104 + [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60, 105 + [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80, 106 + [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60, 107 + [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60, 108 + [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80, 109 + [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70 110 + }; 111 + 112 + struct protection_properties { 113 + bool supported; 114 + bool (*process_transaction)( 115 + struct dc_link *link, 116 + struct hdcp_protection_message *message_info); 117 + }; 118 + 119 + static const struct protection_properties non_supported_protection = { 120 + .supported = false 121 + }; 122 + 123 + static bool hdmi_14_process_transaction( 124 + struct dc_link *link, 125 + struct hdcp_protection_message *message_info) 126 + { 127 + uint8_t *buff = NULL; 128 + bool result; 129 + const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/ 130 + const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/ 131 + struct i2c_command i2c_command; 132 + uint8_t offset = hdcp_i2c_offsets[message_info->msg_id]; 133 + struct i2c_payload i2c_payloads[] = { 134 + { true, 0, 1, &offset }, 135 + /* actual hdcp payload, will be filled later, zeroed for now*/ 136 + { 0 } 137 + }; 138 + 139 + switch (message_info->link) { 140 + case HDCP_LINK_SECONDARY: 141 + i2c_payloads[0].address = hdcp_i2c_addr_link_secondary; 142 + i2c_payloads[1].address = hdcp_i2c_addr_link_secondary; 143 + break; 144 + case HDCP_LINK_PRIMARY: 145 + default: 146 + i2c_payloads[0].address = hdcp_i2c_addr_link_primary; 147 + i2c_payloads[1].address = hdcp_i2c_addr_link_primary; 148 + break; 149 + } 150 + 151 + if (hdcp_cmd_is_read[message_info->msg_id]) { 152 + i2c_payloads[1].write = false; 153 + i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads); 154 + i2c_payloads[1].length = message_info->length; 155 + i2c_payloads[1].data = message_info->data; 156 + } else { 157 + i2c_command.number_of_payloads = 1; 158 + buff = kzalloc(message_info->length + 1, GFP_KERNEL); 159 + 160 + if (!buff) 161 + return false; 162 + 163 + buff[0] = offset; 164 + memmove(&buff[1], message_info->data, message_info->length); 165 + i2c_payloads[0].length = message_info->length + 1; 166 + i2c_payloads[0].data = buff; 167 + } 168 + 169 + i2c_command.payloads = i2c_payloads; 170 + i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW 171 + i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz; 172 + 173 + result = dm_helpers_submit_i2c( 174 + link->ctx, 175 + link, 176 + &i2c_command); 177 + 178 + if (buff) 179 + kfree(buff); 180 + 181 + return result; 182 + } 183 + 184 + static const struct protection_properties hdmi_14_protection = { 185 + .supported = true, 186 + .process_transaction = hdmi_14_process_transaction 187 + }; 188 + 189 + static const uint32_t hdcp_dpcd_addrs[] = { 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 + 224 + static 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 + 310 + static 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 + 322 + static const struct protection_properties dp_11_protection = { 323 + .supported = true, 324 + .process_transaction = dp_11_process_transaction 325 + }; 326 +
+96
drivers/gpu/drm/amd/display/include/hdcp_types.h
··· 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 + #ifndef __DC_HDCP_TYPES_H__ 27 + #define __DC_HDCP_TYPES_H__ 28 + 29 + enum hdcp_message_id { 30 + HDCP_MESSAGE_ID_INVALID = -1, 31 + 32 + /* HDCP 1.4 */ 33 + 34 + HDCP_MESSAGE_ID_READ_BKSV = 0, 35 + /* HDMI is called Ri', DP is called R0' */ 36 + HDCP_MESSAGE_ID_READ_RI_R0, 37 + HDCP_MESSAGE_ID_READ_PJ, 38 + HDCP_MESSAGE_ID_WRITE_AKSV, 39 + HDCP_MESSAGE_ID_WRITE_AINFO, 40 + HDCP_MESSAGE_ID_WRITE_AN, 41 + HDCP_MESSAGE_ID_READ_VH_X, 42 + HDCP_MESSAGE_ID_READ_VH_0, 43 + HDCP_MESSAGE_ID_READ_VH_1, 44 + HDCP_MESSAGE_ID_READ_VH_2, 45 + HDCP_MESSAGE_ID_READ_VH_3, 46 + HDCP_MESSAGE_ID_READ_VH_4, 47 + HDCP_MESSAGE_ID_READ_BCAPS, 48 + HDCP_MESSAGE_ID_READ_BSTATUS, 49 + HDCP_MESSAGE_ID_READ_KSV_FIFO, 50 + HDCP_MESSAGE_ID_READ_BINFO, 51 + 52 + /* HDCP 2.2 */ 53 + 54 + HDCP_MESSAGE_ID_HDCP2VERSION, 55 + HDCP_MESSAGE_ID_RX_CAPS, 56 + HDCP_MESSAGE_ID_WRITE_AKE_INIT, 57 + HDCP_MESSAGE_ID_READ_AKE_SEND_CERT, 58 + HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM, 59 + HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM, 60 + HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME, 61 + HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO, 62 + HDCP_MESSAGE_ID_WRITE_LC_INIT, 63 + HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, 64 + HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS, 65 + HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, 66 + HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK, 67 + HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE, 68 + HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, 69 + HDCP_MESSAGE_ID_READ_RXSTATUS, 70 + HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE, 71 + 72 + HDCP_MESSAGE_ID_MAX 73 + }; 74 + 75 + enum hdcp_version { 76 + HDCP_Unknown = 0, 77 + HDCP_VERSION_14, 78 + HDCP_VERSION_22, 79 + }; 80 + 81 + enum hdcp_link { 82 + HDCP_LINK_PRIMARY, 83 + HDCP_LINK_SECONDARY 84 + }; 85 + 86 + struct hdcp_protection_message { 87 + enum hdcp_version version; 88 + /* relevant only for DVI */ 89 + enum hdcp_link link; 90 + enum hdcp_message_id msg_id; 91 + uint32_t length; 92 + uint8_t max_retries; 93 + uint8_t *data; 94 + }; 95 + 96 + #endif
+32
drivers/gpu/drm/amd/display/modules/hdcp/Makefile
··· 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 + # 23 + # Makefile for the 'hdcp' sub-module of DAL. 24 + # 25 + 26 + HDCP = hdcp_ddc.o hdcp_log.o hdcp_psp.o hdcp.o \ 27 + hdcp1_execution.o hdcp1_transition.o 28 + 29 + AMD_DAL_HDCP = $(addprefix $(AMDDALPATH)/modules/hdcp/,$(HDCP)) 30 + #$(info ************ DAL-HDCP_MAKEFILE ************) 31 + 32 + AMD_DISPLAY_FILES += $(AMD_DAL_HDCP)
+426
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
··· 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 + static void push_error_status(struct mod_hdcp *hdcp, 29 + enum mod_hdcp_status status) 30 + { 31 + struct mod_hdcp_trace *trace = &hdcp->connection.trace; 32 + 33 + if (trace->error_count < MAX_NUM_OF_ERROR_TRACE) { 34 + trace->errors[trace->error_count].status = status; 35 + trace->errors[trace->error_count].state_id = hdcp->state.id; 36 + trace->error_count++; 37 + HDCP_ERROR_TRACE(hdcp, status); 38 + } 39 + 40 + hdcp->connection.hdcp1_retry_count++; 41 + } 42 + 43 + static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp) 44 + { 45 + int i, display_enabled = 0; 46 + 47 + /* if all displays on the link are disabled, hdcp is not desired */ 48 + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 49 + if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_INACTIVE && 50 + !hdcp->connection.displays[i].adjust.disable) { 51 + display_enabled = 1; 52 + break; 53 + } 54 + } 55 + 56 + return (hdcp->connection.hdcp1_retry_count < MAX_NUM_OF_ATTEMPTS) && 57 + display_enabled && !hdcp->connection.link.adjust.hdcp1.disable; 58 + } 59 + 60 + static enum mod_hdcp_status execution(struct mod_hdcp *hdcp, 61 + struct mod_hdcp_event_context *event_ctx, 62 + union mod_hdcp_transition_input *input) 63 + { 64 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 65 + 66 + if (is_in_initialized_state(hdcp)) { 67 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 68 + event_ctx->unexpected_event = 1; 69 + goto out; 70 + } 71 + /* initialize transition input */ 72 + memset(input, 0, sizeof(union mod_hdcp_transition_input)); 73 + } else if (is_in_cp_not_desired_state(hdcp)) { 74 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 75 + event_ctx->unexpected_event = 1; 76 + goto out; 77 + } 78 + /* update topology event if hdcp is not desired */ 79 + status = mod_hdcp_add_display_topology(hdcp); 80 + } else if (is_in_hdcp1_states(hdcp)) { 81 + status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1); 82 + } else if (is_in_hdcp1_dp_states(hdcp)) { 83 + status = mod_hdcp_hdcp1_dp_execution(hdcp, 84 + event_ctx, &input->hdcp1); 85 + } 86 + out: 87 + return status; 88 + } 89 + 90 + static enum mod_hdcp_status transition(struct mod_hdcp *hdcp, 91 + struct mod_hdcp_event_context *event_ctx, 92 + union mod_hdcp_transition_input *input, 93 + struct mod_hdcp_output *output) 94 + { 95 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 96 + 97 + if (event_ctx->unexpected_event) 98 + goto out; 99 + 100 + if (is_in_initialized_state(hdcp)) { 101 + if (is_dp_hdcp(hdcp)) 102 + if (is_cp_desired_hdcp1(hdcp)) { 103 + callback_in_ms(0, output); 104 + set_state_id(hdcp, output, D1_A0_DETERMINE_RX_HDCP_CAPABLE); 105 + } else { 106 + callback_in_ms(0, output); 107 + set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED); 108 + } 109 + else if (is_hdmi_dvi_sl_hdcp(hdcp)) 110 + if (is_cp_desired_hdcp1(hdcp)) { 111 + callback_in_ms(0, output); 112 + set_state_id(hdcp, output, H1_A0_WAIT_FOR_ACTIVE_RX); 113 + } else { 114 + callback_in_ms(0, output); 115 + set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED); 116 + } 117 + else { 118 + callback_in_ms(0, output); 119 + set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED); 120 + } 121 + } else if (is_in_cp_not_desired_state(hdcp)) { 122 + increment_stay_counter(hdcp); 123 + } else if (is_in_hdcp1_states(hdcp)) { 124 + status = mod_hdcp_hdcp1_transition(hdcp, 125 + event_ctx, &input->hdcp1, output); 126 + } else if (is_in_hdcp1_dp_states(hdcp)) { 127 + status = mod_hdcp_hdcp1_dp_transition(hdcp, 128 + event_ctx, &input->hdcp1, output); 129 + } else { 130 + status = MOD_HDCP_STATUS_INVALID_STATE; 131 + } 132 + out: 133 + return status; 134 + } 135 + 136 + static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp, 137 + struct mod_hdcp_output *output) 138 + { 139 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 140 + 141 + if (is_hdcp1(hdcp)) { 142 + if (hdcp->auth.trans_input.hdcp1.create_session != UNKNOWN) 143 + mod_hdcp_hdcp1_destroy_session(hdcp); 144 + 145 + if (hdcp->auth.trans_input.hdcp1.add_topology == PASS) { 146 + status = mod_hdcp_remove_display_topology(hdcp); 147 + if (status != MOD_HDCP_STATUS_SUCCESS) { 148 + output->callback_needed = 0; 149 + output->watchdog_timer_needed = 0; 150 + goto out; 151 + } 152 + } 153 + HDCP_TOP_RESET_AUTH_TRACE(hdcp); 154 + memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); 155 + memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); 156 + set_state_id(hdcp, output, HDCP_INITIALIZED); 157 + } else if (is_in_cp_not_desired_state(hdcp)) { 158 + status = mod_hdcp_remove_display_topology(hdcp); 159 + if (status != MOD_HDCP_STATUS_SUCCESS) { 160 + output->callback_needed = 0; 161 + output->watchdog_timer_needed = 0; 162 + goto out; 163 + } 164 + HDCP_TOP_RESET_AUTH_TRACE(hdcp); 165 + memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication)); 166 + memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state)); 167 + set_state_id(hdcp, output, HDCP_INITIALIZED); 168 + } 169 + 170 + out: 171 + /* stop callback and watchdog requests from previous authentication*/ 172 + output->watchdog_timer_stop = 1; 173 + output->callback_stop = 1; 174 + return status; 175 + } 176 + 177 + static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp, 178 + struct mod_hdcp_output *output) 179 + { 180 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 181 + 182 + memset(output, 0, sizeof(struct mod_hdcp_output)); 183 + 184 + status = reset_authentication(hdcp, output); 185 + if (status != MOD_HDCP_STATUS_SUCCESS) 186 + goto out; 187 + 188 + if (current_state(hdcp) != HDCP_UNINITIALIZED) { 189 + HDCP_TOP_RESET_CONN_TRACE(hdcp); 190 + set_state_id(hdcp, output, HDCP_UNINITIALIZED); 191 + } 192 + memset(&hdcp->connection, 0, sizeof(hdcp->connection)); 193 + out: 194 + return status; 195 + } 196 + 197 + /* 198 + * Implementation of functions in mod_hdcp.h 199 + */ 200 + size_t mod_hdcp_get_memory_size(void) 201 + { 202 + return sizeof(struct mod_hdcp); 203 + } 204 + 205 + enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp, 206 + struct mod_hdcp_config *config) 207 + { 208 + struct mod_hdcp_output output; 209 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 210 + 211 + memset(hdcp, 0, sizeof(struct mod_hdcp)); 212 + memset(&output, 0, sizeof(output)); 213 + hdcp->config = *config; 214 + HDCP_TOP_INTERFACE_TRACE(hdcp); 215 + status = reset_connection(hdcp, &output); 216 + if (status != MOD_HDCP_STATUS_SUCCESS) 217 + push_error_status(hdcp, status); 218 + return status; 219 + } 220 + 221 + enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp) 222 + { 223 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 224 + struct mod_hdcp_output output; 225 + 226 + HDCP_TOP_INTERFACE_TRACE(hdcp); 227 + memset(&output, 0, sizeof(output)); 228 + status = reset_connection(hdcp, &output); 229 + if (status == MOD_HDCP_STATUS_SUCCESS) 230 + memset(hdcp, 0, sizeof(struct mod_hdcp)); 231 + else 232 + push_error_status(hdcp, status); 233 + return status; 234 + } 235 + 236 + enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp, 237 + struct mod_hdcp_link *link, struct mod_hdcp_display *display, 238 + struct mod_hdcp_output *output) 239 + { 240 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 241 + struct mod_hdcp_display *display_container = NULL; 242 + 243 + HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, display->index); 244 + memset(output, 0, sizeof(struct mod_hdcp_output)); 245 + 246 + /* skip inactive display */ 247 + if (display->state != MOD_HDCP_DISPLAY_ACTIVE) { 248 + status = MOD_HDCP_STATUS_SUCCESS; 249 + goto out; 250 + } 251 + 252 + /* check existing display container */ 253 + if (get_active_display_at_index(hdcp, display->index)) { 254 + status = MOD_HDCP_STATUS_SUCCESS; 255 + goto out; 256 + } 257 + 258 + /* find an empty display container */ 259 + display_container = get_empty_display_container(hdcp); 260 + if (!display_container) { 261 + status = MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND; 262 + goto out; 263 + } 264 + 265 + /* reset existing authentication status */ 266 + status = reset_authentication(hdcp, output); 267 + if (status != MOD_HDCP_STATUS_SUCCESS) 268 + goto out; 269 + 270 + /* add display to connection */ 271 + hdcp->connection.link = *link; 272 + *display_container = *display; 273 + 274 + /* reset retry counters */ 275 + reset_retry_counts(hdcp); 276 + 277 + /* reset error trace */ 278 + memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); 279 + 280 + /* request authentication */ 281 + if (current_state(hdcp) != HDCP_INITIALIZED) 282 + set_state_id(hdcp, output, HDCP_INITIALIZED); 283 + callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output); 284 + out: 285 + if (status != MOD_HDCP_STATUS_SUCCESS) 286 + push_error_status(hdcp, status); 287 + 288 + return status; 289 + } 290 + 291 + enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp, 292 + uint8_t index, struct mod_hdcp_output *output) 293 + { 294 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 295 + struct mod_hdcp_display *display = NULL; 296 + 297 + HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index); 298 + memset(output, 0, sizeof(struct mod_hdcp_output)); 299 + 300 + /* find display in connection */ 301 + display = get_active_display_at_index(hdcp, index); 302 + if (!display) { 303 + status = MOD_HDCP_STATUS_SUCCESS; 304 + goto out; 305 + } 306 + 307 + /* stop current authentication */ 308 + status = reset_authentication(hdcp, output); 309 + if (status != MOD_HDCP_STATUS_SUCCESS) 310 + goto out; 311 + 312 + /* remove display */ 313 + display->state = MOD_HDCP_DISPLAY_INACTIVE; 314 + 315 + /* clear retry counters */ 316 + reset_retry_counts(hdcp); 317 + 318 + /* reset error trace */ 319 + memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace)); 320 + 321 + /* request authentication for remaining displays*/ 322 + if (get_active_display_count(hdcp) > 0) 323 + callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, 324 + output); 325 + out: 326 + if (status != MOD_HDCP_STATUS_SUCCESS) 327 + push_error_status(hdcp, status); 328 + return status; 329 + } 330 + 331 + enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp, 332 + uint8_t index, struct mod_hdcp_display_query *query) 333 + { 334 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 335 + struct mod_hdcp_display *display = NULL; 336 + 337 + /* find display in connection */ 338 + display = get_active_display_at_index(hdcp, index); 339 + if (!display) { 340 + status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; 341 + goto out; 342 + } 343 + 344 + /* populate query */ 345 + query->link = &hdcp->connection.link; 346 + query->display = display; 347 + query->trace = &hdcp->connection.trace; 348 + query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; 349 + 350 + mod_hdcp_hdcp1_get_link_encryption_status(hdcp, &query->encryption_status); 351 + 352 + out: 353 + return status; 354 + } 355 + 356 + enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp, 357 + struct mod_hdcp_output *output) 358 + { 359 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 360 + 361 + HDCP_TOP_INTERFACE_TRACE(hdcp); 362 + status = reset_connection(hdcp, output); 363 + if (status != MOD_HDCP_STATUS_SUCCESS) 364 + push_error_status(hdcp, status); 365 + 366 + return status; 367 + } 368 + 369 + enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp, 370 + enum mod_hdcp_event event, struct mod_hdcp_output *output) 371 + { 372 + enum mod_hdcp_status exec_status, trans_status, reset_status, status; 373 + struct mod_hdcp_event_context event_ctx; 374 + 375 + HDCP_EVENT_TRACE(hdcp, event); 376 + memset(output, 0, sizeof(struct mod_hdcp_output)); 377 + memset(&event_ctx, 0, sizeof(struct mod_hdcp_event_context)); 378 + event_ctx.event = event; 379 + 380 + /* execute and transition */ 381 + exec_status = execution(hdcp, &event_ctx, &hdcp->auth.trans_input); 382 + trans_status = transition( 383 + hdcp, &event_ctx, &hdcp->auth.trans_input, output); 384 + if (trans_status == MOD_HDCP_STATUS_SUCCESS) { 385 + status = MOD_HDCP_STATUS_SUCCESS; 386 + } else if (exec_status == MOD_HDCP_STATUS_SUCCESS) { 387 + status = MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE; 388 + push_error_status(hdcp, status); 389 + } else { 390 + status = exec_status; 391 + push_error_status(hdcp, status); 392 + } 393 + 394 + /* reset authentication if needed */ 395 + if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) { 396 + HDCP_FULL_DDC_TRACE(hdcp); 397 + reset_status = reset_authentication(hdcp, output); 398 + if (reset_status != MOD_HDCP_STATUS_SUCCESS) 399 + push_error_status(hdcp, reset_status); 400 + } 401 + return status; 402 + } 403 + 404 + enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode( 405 + enum signal_type signal) 406 + { 407 + enum mod_hdcp_operation_mode mode = MOD_HDCP_MODE_OFF; 408 + 409 + switch (signal) { 410 + case SIGNAL_TYPE_DVI_SINGLE_LINK: 411 + case SIGNAL_TYPE_HDMI_TYPE_A: 412 + mode = MOD_HDCP_MODE_DEFAULT; 413 + break; 414 + case SIGNAL_TYPE_EDP: 415 + case SIGNAL_TYPE_DISPLAY_PORT: 416 + mode = MOD_HDCP_MODE_DP; 417 + break; 418 + case SIGNAL_TYPE_DISPLAY_PORT_MST: 419 + mode = MOD_HDCP_MODE_DP_MST; 420 + break; 421 + default: 422 + break; 423 + }; 424 + 425 + return mode; 426 + }
+442
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
··· 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 + #ifndef HDCP_H_ 27 + #define HDCP_H_ 28 + 29 + #include "mod_hdcp.h" 30 + #include "hdcp_log.h" 31 + 32 + #define BCAPS_READY_MASK 0x20 33 + #define BCAPS_REPEATER_MASK 0x40 34 + #define BSTATUS_DEVICE_COUNT_MASK 0X007F 35 + #define BSTATUS_MAX_DEVS_EXCEEDED_MASK 0x0080 36 + #define BSTATUS_MAX_CASCADE_EXCEEDED_MASK 0x0800 37 + #define BCAPS_HDCP_CAPABLE_MASK_DP 0x01 38 + #define BCAPS_REPEATER_MASK_DP 0x02 39 + #define BSTATUS_READY_MASK_DP 0x01 40 + #define BSTATUS_R0_P_AVAILABLE_MASK_DP 0x02 41 + #define BSTATUS_LINK_INTEGRITY_FAILURE_MASK_DP 0x04 42 + #define BSTATUS_REAUTH_REQUEST_MASK_DP 0x08 43 + #define BINFO_DEVICE_COUNT_MASK_DP 0X007F 44 + #define BINFO_MAX_DEVS_EXCEEDED_MASK_DP 0x0080 45 + #define BINFO_MAX_CASCADE_EXCEEDED_MASK_DP 0x0800 46 + 47 + #define RXSTATUS_MSG_SIZE_MASK 0x03FF 48 + #define RXSTATUS_READY_MASK 0x0400 49 + #define RXSTATUS_REAUTH_REQUEST_MASK 0x0800 50 + #define RXIDLIST_DEVICE_COUNT_LOWER_MASK 0xf0 51 + #define RXIDLIST_DEVICE_COUNT_UPPER_MASK 0x01 52 + #define RXCAPS_BYTE0_HDCP_CAPABLE_MASK_DP 0x02 53 + #define RXSTATUS_READY_MASK_DP 0x0001 54 + #define RXSTATUS_H_P_AVAILABLE_MASK_DP 0x0002 55 + #define RXSTATUS_PAIRING_AVAILABLE_MASK_DP 0x0004 56 + #define RXSTATUS_REAUTH_REQUEST_MASK_DP 0x0008 57 + #define RXSTATUS_LINK_INTEGRITY_FAILURE_MASK_DP 0x0010 58 + 59 + enum mod_hdcp_trans_input_result { 60 + UNKNOWN = 0, 61 + PASS, 62 + FAIL 63 + }; 64 + 65 + struct mod_hdcp_transition_input_hdcp1 { 66 + uint8_t bksv_read; 67 + uint8_t bksv_validation; 68 + uint8_t add_topology; 69 + uint8_t create_session; 70 + uint8_t an_write; 71 + uint8_t aksv_write; 72 + uint8_t ainfo_write; 73 + uint8_t bcaps_read; 74 + uint8_t r0p_read; 75 + uint8_t rx_validation; 76 + uint8_t encryption; 77 + uint8_t link_maintenance; 78 + uint8_t ready_check; 79 + uint8_t bstatus_read; 80 + uint8_t max_cascade_check; 81 + uint8_t max_devs_check; 82 + uint8_t device_count_check; 83 + uint8_t ksvlist_read; 84 + uint8_t vp_read; 85 + uint8_t ksvlist_vp_validation; 86 + 87 + uint8_t hdcp_capable_dp; 88 + uint8_t binfo_read_dp; 89 + uint8_t r0p_available_dp; 90 + uint8_t link_integiry_check; 91 + uint8_t reauth_request_check; 92 + uint8_t stream_encryption_dp; 93 + }; 94 + 95 + union mod_hdcp_transition_input { 96 + struct mod_hdcp_transition_input_hdcp1 hdcp1; 97 + }; 98 + 99 + struct mod_hdcp_message_hdcp1 { 100 + uint8_t an[8]; 101 + uint8_t aksv[5]; 102 + uint8_t ainfo; 103 + uint8_t bksv[5]; 104 + uint16_t r0p; 105 + uint8_t bcaps; 106 + uint16_t bstatus; 107 + uint8_t ksvlist[635]; 108 + uint16_t ksvlist_size; 109 + uint8_t vp[20]; 110 + 111 + uint16_t binfo_dp; 112 + }; 113 + 114 + union mod_hdcp_message { 115 + struct mod_hdcp_message_hdcp1 hdcp1; 116 + }; 117 + 118 + struct mod_hdcp_auth_counters { 119 + uint8_t stream_management_retry_count; 120 + }; 121 + 122 + /* contains values per connection */ 123 + struct mod_hdcp_connection { 124 + struct mod_hdcp_link link; 125 + struct mod_hdcp_display displays[MAX_NUM_OF_DISPLAYS]; 126 + uint8_t is_repeater; 127 + uint8_t is_km_stored; 128 + struct mod_hdcp_trace trace; 129 + uint8_t hdcp1_retry_count; 130 + }; 131 + 132 + /* contains values per authentication cycle */ 133 + struct mod_hdcp_authentication { 134 + uint32_t id; 135 + union mod_hdcp_message msg; 136 + union mod_hdcp_transition_input trans_input; 137 + struct mod_hdcp_auth_counters count; 138 + }; 139 + 140 + /* contains values per state change */ 141 + struct mod_hdcp_state { 142 + uint8_t id; 143 + uint32_t stay_count; 144 + }; 145 + 146 + /* per event in a state */ 147 + struct mod_hdcp_event_context { 148 + enum mod_hdcp_event event; 149 + uint8_t rx_id_list_ready; 150 + uint8_t unexpected_event; 151 + }; 152 + 153 + struct mod_hdcp { 154 + /* per link */ 155 + struct mod_hdcp_config config; 156 + /* per connection */ 157 + struct mod_hdcp_connection connection; 158 + /* per authentication attempt */ 159 + struct mod_hdcp_authentication auth; 160 + /* per state in an authentication */ 161 + struct mod_hdcp_state state; 162 + /* reserved memory buffer */ 163 + uint8_t buf[2025]; 164 + }; 165 + 166 + enum mod_hdcp_initial_state_id { 167 + HDCP_UNINITIALIZED = 0x0, 168 + HDCP_INITIAL_STATE_START = HDCP_UNINITIALIZED, 169 + HDCP_INITIALIZED, 170 + HDCP_CP_NOT_DESIRED, 171 + HDCP_INITIAL_STATE_END = HDCP_CP_NOT_DESIRED 172 + }; 173 + 174 + enum mod_hdcp_hdcp1_state_id { 175 + HDCP1_STATE_START = HDCP_INITIAL_STATE_END, 176 + H1_A0_WAIT_FOR_ACTIVE_RX, 177 + H1_A1_EXCHANGE_KSVS, 178 + H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER, 179 + H1_A45_AUTHENICATED, 180 + H1_A8_WAIT_FOR_READY, 181 + H1_A9_READ_KSV_LIST, 182 + HDCP1_STATE_END = H1_A9_READ_KSV_LIST 183 + }; 184 + 185 + enum mod_hdcp_hdcp1_dp_state_id { 186 + HDCP1_DP_STATE_START = HDCP1_STATE_END, 187 + D1_A0_DETERMINE_RX_HDCP_CAPABLE, 188 + D1_A1_EXCHANGE_KSVS, 189 + D1_A23_WAIT_FOR_R0_PRIME, 190 + D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER, 191 + D1_A4_AUTHENICATED, 192 + D1_A6_WAIT_FOR_READY, 193 + D1_A7_READ_KSV_LIST, 194 + HDCP1_DP_STATE_END = D1_A7_READ_KSV_LIST, 195 + }; 196 + 197 + /* hdcp1 executions and transitions */ 198 + typedef enum mod_hdcp_status (*mod_hdcp_action)(struct mod_hdcp *hdcp); 199 + uint8_t mod_hdcp_execute_and_set( 200 + mod_hdcp_action func, uint8_t *flag, 201 + enum mod_hdcp_status *status, struct mod_hdcp *hdcp, char *str); 202 + enum mod_hdcp_status mod_hdcp_hdcp1_execution(struct mod_hdcp *hdcp, 203 + struct mod_hdcp_event_context *event_ctx, 204 + struct mod_hdcp_transition_input_hdcp1 *input); 205 + enum mod_hdcp_status mod_hdcp_hdcp1_dp_execution(struct mod_hdcp *hdcp, 206 + struct mod_hdcp_event_context *event_ctx, 207 + struct mod_hdcp_transition_input_hdcp1 *input); 208 + enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp, 209 + struct mod_hdcp_event_context *event_ctx, 210 + struct mod_hdcp_transition_input_hdcp1 *input, 211 + struct mod_hdcp_output *output); 212 + enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, 213 + struct mod_hdcp_event_context *event_ctx, 214 + struct mod_hdcp_transition_input_hdcp1 *input, 215 + struct mod_hdcp_output *output); 216 + 217 + /* log functions */ 218 + void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size, 219 + uint8_t *buf, uint32_t buf_size); 220 + /* TODO: add adjustment log */ 221 + 222 + /* psp functions */ 223 + enum mod_hdcp_status mod_hdcp_add_display_topology( 224 + struct mod_hdcp *hdcp); 225 + enum mod_hdcp_status mod_hdcp_remove_display_topology( 226 + struct mod_hdcp *hdcp); 227 + enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp); 228 + enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp); 229 + enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp); 230 + enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp); 231 + enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp); 232 + enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption( 233 + struct mod_hdcp *hdcp); 234 + enum mod_hdcp_status mod_hdcp_hdcp1_link_maintenance(struct mod_hdcp *hdcp); 235 + enum mod_hdcp_status mod_hdcp_hdcp1_get_link_encryption_status(struct mod_hdcp *hdcp, 236 + enum mod_hdcp_encryption_status *encryption_status); 237 + /* ddc functions */ 238 + enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp); 239 + enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp); 240 + enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp); 241 + enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp); 242 + enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp); 243 + enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp); 244 + enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp); 245 + enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp); 246 + enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp); 247 + enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp); 248 + enum mod_hdcp_status mod_hdcp_read_rxcaps(struct mod_hdcp *hdcp); 249 + enum mod_hdcp_status mod_hdcp_read_rxstatus(struct mod_hdcp *hdcp); 250 + enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp); 251 + enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp); 252 + enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp); 253 + enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp); 254 + enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp); 255 + enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp); 256 + enum mod_hdcp_status mod_hdcp_write_ake_init(struct mod_hdcp *hdcp); 257 + enum mod_hdcp_status mod_hdcp_write_no_stored_km(struct mod_hdcp *hdcp); 258 + enum mod_hdcp_status mod_hdcp_write_stored_km(struct mod_hdcp *hdcp); 259 + enum mod_hdcp_status mod_hdcp_write_lc_init(struct mod_hdcp *hdcp); 260 + enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp); 261 + enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp); 262 + enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp); 263 + enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp); 264 + 265 + /* hdcp version helpers */ 266 + static inline uint8_t is_dp_hdcp(struct mod_hdcp *hdcp) 267 + { 268 + return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP || 269 + hdcp->connection.link.mode == MOD_HDCP_MODE_DP_MST); 270 + } 271 + 272 + static inline uint8_t is_dp_mst_hdcp(struct mod_hdcp *hdcp) 273 + { 274 + return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP_MST); 275 + } 276 + 277 + static inline uint8_t is_hdmi_dvi_sl_hdcp(struct mod_hdcp *hdcp) 278 + { 279 + return (hdcp->connection.link.mode == MOD_HDCP_MODE_DEFAULT); 280 + } 281 + 282 + /* hdcp state helpers */ 283 + static inline uint8_t current_state(struct mod_hdcp *hdcp) 284 + { 285 + return hdcp->state.id; 286 + } 287 + 288 + static inline void set_state_id(struct mod_hdcp *hdcp, 289 + struct mod_hdcp_output *output, uint8_t id) 290 + { 291 + memset(&hdcp->state, 0, sizeof(hdcp->state)); 292 + hdcp->state.id = id; 293 + /* callback timer should be reset per state */ 294 + output->callback_stop = 1; 295 + output->watchdog_timer_stop = 1; 296 + HDCP_NEXT_STATE_TRACE(hdcp, id, output); 297 + } 298 + 299 + static inline uint8_t is_in_hdcp1_states(struct mod_hdcp *hdcp) 300 + { 301 + return (current_state(hdcp) > HDCP1_STATE_START && 302 + current_state(hdcp) <= HDCP1_STATE_END); 303 + } 304 + 305 + static inline uint8_t is_in_hdcp1_dp_states(struct mod_hdcp *hdcp) 306 + { 307 + return (current_state(hdcp) > HDCP1_DP_STATE_START && 308 + current_state(hdcp) <= HDCP1_DP_STATE_END); 309 + } 310 + 311 + static inline uint8_t is_hdcp1(struct mod_hdcp *hdcp) 312 + { 313 + return (is_in_hdcp1_states(hdcp) || is_in_hdcp1_dp_states(hdcp)); 314 + } 315 + 316 + static inline uint8_t is_in_cp_not_desired_state(struct mod_hdcp *hdcp) 317 + { 318 + return current_state(hdcp) == HDCP_CP_NOT_DESIRED; 319 + } 320 + 321 + static inline uint8_t is_in_initialized_state(struct mod_hdcp *hdcp) 322 + { 323 + return current_state(hdcp) == HDCP_INITIALIZED; 324 + } 325 + 326 + /* transition operation helpers */ 327 + static inline void increment_stay_counter(struct mod_hdcp *hdcp) 328 + { 329 + hdcp->state.stay_count++; 330 + } 331 + 332 + static inline void fail_and_restart_in_ms(uint16_t time, 333 + enum mod_hdcp_status *status, 334 + struct mod_hdcp_output *output) 335 + { 336 + output->callback_needed = 1; 337 + output->callback_delay = time; 338 + output->watchdog_timer_needed = 0; 339 + output->watchdog_timer_delay = 0; 340 + *status = MOD_HDCP_STATUS_RESET_NEEDED; 341 + } 342 + 343 + static inline void callback_in_ms(uint16_t time, struct mod_hdcp_output *output) 344 + { 345 + output->callback_needed = 1; 346 + output->callback_delay = time; 347 + } 348 + 349 + static inline void set_watchdog_in_ms(struct mod_hdcp *hdcp, uint16_t time, 350 + struct mod_hdcp_output *output) 351 + { 352 + output->watchdog_timer_needed = 1; 353 + output->watchdog_timer_delay = time; 354 + } 355 + 356 + /* connection topology helpers */ 357 + static inline uint8_t is_display_active(struct mod_hdcp_display *display) 358 + { 359 + return display->state >= MOD_HDCP_DISPLAY_ACTIVE; 360 + } 361 + 362 + static inline uint8_t is_display_added(struct mod_hdcp_display *display) 363 + { 364 + return display->state >= MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED; 365 + } 366 + 367 + static inline uint8_t is_display_encryption_enabled(struct mod_hdcp_display *display) 368 + { 369 + return display->state >= MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED; 370 + } 371 + 372 + static inline uint8_t get_active_display_count(struct mod_hdcp *hdcp) 373 + { 374 + uint8_t added_count = 0; 375 + uint8_t i; 376 + 377 + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) 378 + if (is_display_active(&hdcp->connection.displays[i])) 379 + added_count++; 380 + return added_count; 381 + } 382 + 383 + static inline uint8_t get_added_display_count(struct mod_hdcp *hdcp) 384 + { 385 + uint8_t added_count = 0; 386 + uint8_t i; 387 + 388 + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) 389 + if (is_display_added(&hdcp->connection.displays[i])) 390 + added_count++; 391 + return added_count; 392 + } 393 + 394 + static inline struct mod_hdcp_display *get_first_added_display( 395 + struct mod_hdcp *hdcp) 396 + { 397 + uint8_t i; 398 + struct mod_hdcp_display *display = NULL; 399 + 400 + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) 401 + if (is_display_added(&hdcp->connection.displays[i])) { 402 + display = &hdcp->connection.displays[i]; 403 + break; 404 + } 405 + return display; 406 + } 407 + 408 + static inline struct mod_hdcp_display *get_active_display_at_index( 409 + struct mod_hdcp *hdcp, uint8_t index) 410 + { 411 + uint8_t i; 412 + struct mod_hdcp_display *display = NULL; 413 + 414 + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) 415 + if (hdcp->connection.displays[i].index == index && 416 + is_display_active(&hdcp->connection.displays[i])) { 417 + display = &hdcp->connection.displays[i]; 418 + break; 419 + } 420 + return display; 421 + } 422 + 423 + static inline struct mod_hdcp_display *get_empty_display_container( 424 + struct mod_hdcp *hdcp) 425 + { 426 + uint8_t i; 427 + struct mod_hdcp_display *display = NULL; 428 + 429 + for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) 430 + if (!is_display_active(&hdcp->connection.displays[i])) { 431 + display = &hdcp->connection.displays[i]; 432 + break; 433 + } 434 + return display; 435 + } 436 + 437 + static inline void reset_retry_counts(struct mod_hdcp *hdcp) 438 + { 439 + hdcp->connection.hdcp1_retry_count = 0; 440 + } 441 + 442 + #endif /* HDCP_H_ */
+531
drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
··· 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 + static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp) 29 + { 30 + uint64_t n = *(uint64_t *)hdcp->auth.msg.hdcp1.bksv; 31 + uint8_t count = 0; 32 + 33 + while (n) { 34 + count++; 35 + n &= (n - 1); 36 + } 37 + return (count == 20) ? MOD_HDCP_STATUS_SUCCESS : 38 + MOD_HDCP_STATUS_HDCP1_INVALID_BKSV; 39 + } 40 + 41 + static inline enum mod_hdcp_status check_ksv_ready(struct mod_hdcp *hdcp) 42 + { 43 + if (is_dp_hdcp(hdcp)) 44 + return (hdcp->auth.msg.hdcp1.bstatus & BSTATUS_READY_MASK_DP) ? 45 + MOD_HDCP_STATUS_SUCCESS : 46 + MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY; 47 + return (hdcp->auth.msg.hdcp1.bcaps & BCAPS_READY_MASK) ? 48 + MOD_HDCP_STATUS_SUCCESS : 49 + MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY; 50 + } 51 + 52 + static inline enum mod_hdcp_status check_hdcp_capable_dp(struct mod_hdcp *hdcp) 53 + { 54 + return (hdcp->auth.msg.hdcp1.bcaps & BCAPS_HDCP_CAPABLE_MASK_DP) ? 55 + MOD_HDCP_STATUS_SUCCESS : 56 + MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE; 57 + } 58 + 59 + static inline enum mod_hdcp_status check_r0p_available_dp(struct mod_hdcp *hdcp) 60 + { 61 + enum mod_hdcp_status status; 62 + if (is_dp_hdcp(hdcp)) { 63 + status = (hdcp->auth.msg.hdcp1.bstatus & 64 + BSTATUS_R0_P_AVAILABLE_MASK_DP) ? 65 + MOD_HDCP_STATUS_SUCCESS : 66 + MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING; 67 + } else { 68 + status = MOD_HDCP_STATUS_INVALID_OPERATION; 69 + } 70 + return status; 71 + } 72 + 73 + static inline enum mod_hdcp_status check_link_integrity_dp( 74 + struct mod_hdcp *hdcp) 75 + { 76 + return (hdcp->auth.msg.hdcp1.bstatus & 77 + BSTATUS_LINK_INTEGRITY_FAILURE_MASK_DP) ? 78 + MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE : 79 + MOD_HDCP_STATUS_SUCCESS; 80 + } 81 + 82 + static inline enum mod_hdcp_status check_no_reauthentication_request_dp( 83 + struct mod_hdcp *hdcp) 84 + { 85 + return (hdcp->auth.msg.hdcp1.bstatus & BSTATUS_REAUTH_REQUEST_MASK_DP) ? 86 + MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED : 87 + MOD_HDCP_STATUS_SUCCESS; 88 + } 89 + 90 + static inline enum mod_hdcp_status check_no_max_cascade(struct mod_hdcp *hdcp) 91 + { 92 + enum mod_hdcp_status status; 93 + 94 + if (is_dp_hdcp(hdcp)) 95 + status = (hdcp->auth.msg.hdcp1.binfo_dp & 96 + BINFO_MAX_CASCADE_EXCEEDED_MASK_DP) ? 97 + MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE : 98 + MOD_HDCP_STATUS_SUCCESS; 99 + else 100 + status = (hdcp->auth.msg.hdcp1.bstatus & 101 + BSTATUS_MAX_CASCADE_EXCEEDED_MASK) ? 102 + MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE : 103 + MOD_HDCP_STATUS_SUCCESS; 104 + return status; 105 + } 106 + 107 + static inline enum mod_hdcp_status check_no_max_devs(struct mod_hdcp *hdcp) 108 + { 109 + enum mod_hdcp_status status; 110 + 111 + if (is_dp_hdcp(hdcp)) 112 + status = (hdcp->auth.msg.hdcp1.binfo_dp & 113 + BINFO_MAX_DEVS_EXCEEDED_MASK_DP) ? 114 + MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE : 115 + MOD_HDCP_STATUS_SUCCESS; 116 + else 117 + status = (hdcp->auth.msg.hdcp1.bstatus & 118 + BSTATUS_MAX_DEVS_EXCEEDED_MASK) ? 119 + MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE : 120 + MOD_HDCP_STATUS_SUCCESS; 121 + return status; 122 + } 123 + 124 + static inline uint8_t get_device_count(struct mod_hdcp *hdcp) 125 + { 126 + return is_dp_hdcp(hdcp) ? 127 + (hdcp->auth.msg.hdcp1.binfo_dp & BINFO_DEVICE_COUNT_MASK_DP) : 128 + (hdcp->auth.msg.hdcp1.bstatus & BSTATUS_DEVICE_COUNT_MASK); 129 + } 130 + 131 + static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) 132 + { 133 + /* device count must be greater than or equal to tracked hdcp displays */ 134 + return (get_device_count(hdcp) < get_added_display_count(hdcp)) ? 135 + MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE : 136 + MOD_HDCP_STATUS_SUCCESS; 137 + } 138 + 139 + static enum mod_hdcp_status wait_for_active_rx(struct mod_hdcp *hdcp, 140 + struct mod_hdcp_event_context *event_ctx, 141 + struct mod_hdcp_transition_input_hdcp1 *input) 142 + { 143 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 144 + 145 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 146 + event_ctx->unexpected_event = 1; 147 + goto out; 148 + } 149 + 150 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv, 151 + &input->bksv_read, &status, 152 + hdcp, "bksv_read")) 153 + goto out; 154 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 155 + &input->bcaps_read, &status, 156 + hdcp, "bcaps_read")) 157 + goto out; 158 + out: 159 + return status; 160 + } 161 + 162 + static enum mod_hdcp_status exchange_ksvs(struct mod_hdcp *hdcp, 163 + struct mod_hdcp_event_context *event_ctx, 164 + struct mod_hdcp_transition_input_hdcp1 *input) 165 + { 166 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 167 + 168 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 169 + event_ctx->unexpected_event = 1; 170 + goto out; 171 + } 172 + 173 + if (!mod_hdcp_execute_and_set(mod_hdcp_add_display_topology, 174 + &input->add_topology, &status, 175 + hdcp, "add_topology")) 176 + goto out; 177 + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_create_session, 178 + &input->create_session, &status, 179 + hdcp, "create_session")) 180 + goto out; 181 + if (!mod_hdcp_execute_and_set(mod_hdcp_write_an, 182 + &input->an_write, &status, 183 + hdcp, "an_write")) 184 + goto out; 185 + if (!mod_hdcp_execute_and_set(mod_hdcp_write_aksv, 186 + &input->aksv_write, &status, 187 + hdcp, "aksv_write")) 188 + goto out; 189 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv, 190 + &input->bksv_read, &status, 191 + hdcp, "bksv_read")) 192 + goto out; 193 + if (!mod_hdcp_execute_and_set(validate_bksv, 194 + &input->bksv_validation, &status, 195 + hdcp, "bksv_validation")) 196 + goto out; 197 + if (hdcp->auth.msg.hdcp1.ainfo) { 198 + if (!mod_hdcp_execute_and_set(mod_hdcp_write_ainfo, 199 + &input->ainfo_write, &status, 200 + hdcp, "ainfo_write")) 201 + goto out; 202 + } 203 + out: 204 + return status; 205 + } 206 + 207 + static enum mod_hdcp_status computations_validate_rx_test_for_repeater( 208 + struct mod_hdcp *hdcp, 209 + struct mod_hdcp_event_context *event_ctx, 210 + struct mod_hdcp_transition_input_hdcp1 *input) 211 + { 212 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 213 + 214 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 215 + event_ctx->unexpected_event = 1; 216 + goto out; 217 + } 218 + 219 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_r0p, 220 + &input->r0p_read, &status, 221 + hdcp, "r0p_read")) 222 + goto out; 223 + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_rx, 224 + &input->rx_validation, &status, 225 + hdcp, "rx_validation")) 226 + goto out; 227 + if (hdcp->connection.is_repeater) { 228 + if (!hdcp->connection.link.adjust.hdcp1.postpone_encryption) 229 + if (!mod_hdcp_execute_and_set( 230 + mod_hdcp_hdcp1_enable_encryption, 231 + &input->encryption, &status, 232 + hdcp, "encryption")) 233 + goto out; 234 + } else { 235 + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption, 236 + &input->encryption, &status, 237 + hdcp, "encryption")) 238 + goto out; 239 + if (is_dp_mst_hdcp(hdcp)) 240 + if (!mod_hdcp_execute_and_set( 241 + mod_hdcp_hdcp1_enable_dp_stream_encryption, 242 + &input->stream_encryption_dp, &status, 243 + hdcp, "stream_encryption_dp")) 244 + goto out; 245 + } 246 + out: 247 + return status; 248 + } 249 + 250 + static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp, 251 + struct mod_hdcp_event_context *event_ctx, 252 + struct mod_hdcp_transition_input_hdcp1 *input) 253 + { 254 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 255 + 256 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 257 + event_ctx->unexpected_event = 1; 258 + goto out; 259 + } 260 + 261 + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_link_maintenance, 262 + &input->link_maintenance, &status, 263 + hdcp, "link_maintenance")) 264 + goto out; 265 + out: 266 + return status; 267 + } 268 + 269 + static enum mod_hdcp_status wait_for_ready(struct mod_hdcp *hdcp, 270 + struct mod_hdcp_event_context *event_ctx, 271 + struct mod_hdcp_transition_input_hdcp1 *input) 272 + { 273 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 274 + 275 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK && 276 + event_ctx->event != MOD_HDCP_EVENT_CPIRQ && 277 + event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 278 + event_ctx->unexpected_event = 1; 279 + goto out; 280 + } 281 + 282 + if (is_dp_hdcp(hdcp)) { 283 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 284 + &input->bstatus_read, &status, 285 + hdcp, "bstatus_read")) 286 + goto out; 287 + if (!mod_hdcp_execute_and_set(check_link_integrity_dp, 288 + &input->link_integiry_check, &status, 289 + hdcp, "link_integiry_check")) 290 + goto out; 291 + if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, 292 + &input->reauth_request_check, &status, 293 + hdcp, "reauth_request_check")) 294 + goto out; 295 + } else { 296 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 297 + &input->bcaps_read, &status, 298 + hdcp, "bcaps_read")) 299 + goto out; 300 + } 301 + if (!mod_hdcp_execute_and_set(check_ksv_ready, 302 + &input->ready_check, &status, 303 + hdcp, "ready_check")) 304 + goto out; 305 + out: 306 + return status; 307 + } 308 + 309 + static enum mod_hdcp_status read_ksv_list(struct mod_hdcp *hdcp, 310 + struct mod_hdcp_event_context *event_ctx, 311 + struct mod_hdcp_transition_input_hdcp1 *input) 312 + { 313 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 314 + uint8_t device_count; 315 + 316 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 317 + event_ctx->unexpected_event = 1; 318 + goto out; 319 + } 320 + 321 + if (is_dp_hdcp(hdcp)) { 322 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_binfo, 323 + &input->binfo_read_dp, &status, 324 + hdcp, "binfo_read_dp")) 325 + goto out; 326 + } else { 327 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 328 + &input->bstatus_read, &status, 329 + hdcp, "bstatus_read")) 330 + goto out; 331 + } 332 + if (!mod_hdcp_execute_and_set(check_no_max_cascade, 333 + &input->max_cascade_check, &status, 334 + hdcp, "max_cascade_check")) 335 + goto out; 336 + if (!mod_hdcp_execute_and_set(check_no_max_devs, 337 + &input->max_devs_check, &status, 338 + hdcp, "max_devs_check")) 339 + goto out; 340 + if (!mod_hdcp_execute_and_set(check_device_count, 341 + &input->device_count_check, &status, 342 + hdcp, "device_count_check")) 343 + goto out; 344 + device_count = get_device_count(hdcp); 345 + hdcp->auth.msg.hdcp1.ksvlist_size = device_count*5; 346 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_ksvlist, 347 + &input->ksvlist_read, &status, 348 + hdcp, "ksvlist_read")) 349 + goto out; 350 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_vp, 351 + &input->vp_read, &status, 352 + hdcp, "vp_read")) 353 + goto out; 354 + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_ksvlist_vp, 355 + &input->ksvlist_vp_validation, &status, 356 + hdcp, "ksvlist_vp_validation")) 357 + goto out; 358 + if (input->encryption != PASS) 359 + if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption, 360 + &input->encryption, &status, 361 + hdcp, "encryption")) 362 + goto out; 363 + if (is_dp_mst_hdcp(hdcp)) 364 + if (!mod_hdcp_execute_and_set( 365 + mod_hdcp_hdcp1_enable_dp_stream_encryption, 366 + &input->stream_encryption_dp, &status, 367 + hdcp, "stream_encryption_dp")) 368 + goto out; 369 + out: 370 + return status; 371 + } 372 + 373 + static enum mod_hdcp_status determine_rx_hdcp_capable_dp(struct mod_hdcp *hdcp, 374 + struct mod_hdcp_event_context *event_ctx, 375 + struct mod_hdcp_transition_input_hdcp1 *input) 376 + { 377 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 378 + 379 + if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 380 + event_ctx->unexpected_event = 1; 381 + goto out; 382 + } 383 + 384 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 385 + &input->bcaps_read, &status, 386 + hdcp, "bcaps_read")) 387 + goto out; 388 + if (!mod_hdcp_execute_and_set(check_hdcp_capable_dp, 389 + &input->hdcp_capable_dp, &status, 390 + hdcp, "hdcp_capable_dp")) 391 + goto out; 392 + out: 393 + return status; 394 + } 395 + 396 + static enum mod_hdcp_status wait_for_r0_prime_dp(struct mod_hdcp *hdcp, 397 + struct mod_hdcp_event_context *event_ctx, 398 + struct mod_hdcp_transition_input_hdcp1 *input) 399 + { 400 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 401 + 402 + if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ && 403 + event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 404 + event_ctx->unexpected_event = 1; 405 + goto out; 406 + } 407 + 408 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 409 + &input->bstatus_read, &status, 410 + hdcp, "bstatus_read")) 411 + goto out; 412 + if (!mod_hdcp_execute_and_set(check_r0p_available_dp, 413 + &input->r0p_available_dp, &status, 414 + hdcp, "r0p_available_dp")) 415 + goto out; 416 + out: 417 + return status; 418 + } 419 + 420 + static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp, 421 + struct mod_hdcp_event_context *event_ctx, 422 + struct mod_hdcp_transition_input_hdcp1 *input) 423 + { 424 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 425 + 426 + if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ) { 427 + event_ctx->unexpected_event = 1; 428 + goto out; 429 + } 430 + 431 + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 432 + &input->bstatus_read, &status, 433 + hdcp, "bstatus_read")) 434 + goto out; 435 + if (!mod_hdcp_execute_and_set(check_link_integrity_dp, 436 + &input->link_integiry_check, &status, 437 + hdcp, "link_integiry_check")) 438 + goto out; 439 + if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, 440 + &input->reauth_request_check, &status, 441 + hdcp, "reauth_request_check")) 442 + goto out; 443 + out: 444 + return status; 445 + } 446 + 447 + uint8_t mod_hdcp_execute_and_set( 448 + mod_hdcp_action func, uint8_t *flag, 449 + enum mod_hdcp_status *status, struct mod_hdcp *hdcp, char *str) 450 + { 451 + *status = func(hdcp); 452 + if (*status == MOD_HDCP_STATUS_SUCCESS && *flag != PASS) { 453 + HDCP_INPUT_PASS_TRACE(hdcp, str); 454 + *flag = PASS; 455 + } else if (*status != MOD_HDCP_STATUS_SUCCESS && *flag != FAIL) { 456 + HDCP_INPUT_FAIL_TRACE(hdcp, str); 457 + *flag = FAIL; 458 + } 459 + return (*status == MOD_HDCP_STATUS_SUCCESS); 460 + } 461 + 462 + enum mod_hdcp_status mod_hdcp_hdcp1_execution(struct mod_hdcp *hdcp, 463 + struct mod_hdcp_event_context *event_ctx, 464 + struct mod_hdcp_transition_input_hdcp1 *input) 465 + { 466 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 467 + 468 + switch (current_state(hdcp)) { 469 + case H1_A0_WAIT_FOR_ACTIVE_RX: 470 + status = wait_for_active_rx(hdcp, event_ctx, input); 471 + break; 472 + case H1_A1_EXCHANGE_KSVS: 473 + status = exchange_ksvs(hdcp, event_ctx, input); 474 + break; 475 + case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER: 476 + status = computations_validate_rx_test_for_repeater(hdcp, 477 + event_ctx, input); 478 + break; 479 + case H1_A45_AUTHENICATED: 480 + status = authenticated(hdcp, event_ctx, input); 481 + break; 482 + case H1_A8_WAIT_FOR_READY: 483 + status = wait_for_ready(hdcp, event_ctx, input); 484 + break; 485 + case H1_A9_READ_KSV_LIST: 486 + status = read_ksv_list(hdcp, event_ctx, input); 487 + break; 488 + default: 489 + status = MOD_HDCP_STATUS_INVALID_STATE; 490 + break; 491 + } 492 + 493 + return status; 494 + } 495 + 496 + extern enum mod_hdcp_status mod_hdcp_hdcp1_dp_execution(struct mod_hdcp *hdcp, 497 + struct mod_hdcp_event_context *event_ctx, 498 + struct mod_hdcp_transition_input_hdcp1 *input) 499 + { 500 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 501 + 502 + switch (current_state(hdcp)) { 503 + case D1_A0_DETERMINE_RX_HDCP_CAPABLE: 504 + status = determine_rx_hdcp_capable_dp(hdcp, event_ctx, input); 505 + break; 506 + case D1_A1_EXCHANGE_KSVS: 507 + status = exchange_ksvs(hdcp, event_ctx, input); 508 + break; 509 + case D1_A23_WAIT_FOR_R0_PRIME: 510 + status = wait_for_r0_prime_dp(hdcp, event_ctx, input); 511 + break; 512 + case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER: 513 + status = computations_validate_rx_test_for_repeater( 514 + hdcp, event_ctx, input); 515 + break; 516 + case D1_A4_AUTHENICATED: 517 + status = authenticated_dp(hdcp, event_ctx, input); 518 + break; 519 + case D1_A6_WAIT_FOR_READY: 520 + status = wait_for_ready(hdcp, event_ctx, input); 521 + break; 522 + case D1_A7_READ_KSV_LIST: 523 + status = read_ksv_list(hdcp, event_ctx, input); 524 + break; 525 + default: 526 + status = MOD_HDCP_STATUS_INVALID_STATE; 527 + break; 528 + } 529 + 530 + return status; 531 + }
+307
drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c
··· 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 + enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp, 29 + struct mod_hdcp_event_context *event_ctx, 30 + struct mod_hdcp_transition_input_hdcp1 *input, 31 + struct mod_hdcp_output *output) 32 + { 33 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 34 + struct mod_hdcp_connection *conn = &hdcp->connection; 35 + struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust; 36 + 37 + switch (current_state(hdcp)) { 38 + case H1_A0_WAIT_FOR_ACTIVE_RX: 39 + if (input->bksv_read != PASS || input->bcaps_read != PASS) { 40 + /* 1A-04: repeatedly attempts on port access failure */ 41 + callback_in_ms(500, output); 42 + increment_stay_counter(hdcp); 43 + break; 44 + } 45 + callback_in_ms(0, output); 46 + set_state_id(hdcp, output, H1_A1_EXCHANGE_KSVS); 47 + break; 48 + case H1_A1_EXCHANGE_KSVS: 49 + if (input->add_topology != PASS || 50 + input->create_session != PASS) { 51 + /* out of sync with psp state */ 52 + adjust->hdcp1.disable = 1; 53 + fail_and_restart_in_ms(0, &status, output); 54 + break; 55 + } else if (input->an_write != PASS || 56 + input->aksv_write != PASS || 57 + input->bksv_read != PASS || 58 + input->bksv_validation != PASS || 59 + input->ainfo_write == FAIL) { 60 + /* 1A-05: consider invalid bksv a failure */ 61 + fail_and_restart_in_ms(0, &status, output); 62 + break; 63 + } 64 + callback_in_ms(300, output); 65 + set_state_id(hdcp, output, 66 + H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER); 67 + break; 68 + case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER: 69 + if (input->bcaps_read != PASS || 70 + input->r0p_read != PASS || 71 + input->rx_validation != PASS || 72 + (!conn->is_repeater && input->encryption != PASS)) { 73 + /* 1A-06: consider invalid r0' a failure */ 74 + /* 1A-08: consider bksv listed in SRM a failure */ 75 + fail_and_restart_in_ms(0, &status, output); 76 + break; 77 + } 78 + if (conn->is_repeater) { 79 + callback_in_ms(0, output); 80 + set_watchdog_in_ms(hdcp, 5000, output); 81 + set_state_id(hdcp, output, H1_A8_WAIT_FOR_READY); 82 + } else { 83 + callback_in_ms(0, output); 84 + set_state_id(hdcp, output, H1_A45_AUTHENICATED); 85 + HDCP_FULL_DDC_TRACE(hdcp); 86 + } 87 + break; 88 + case H1_A45_AUTHENICATED: 89 + if (input->link_maintenance != PASS) { 90 + /* 1A-07: consider invalid ri' a failure */ 91 + /* 1A-07a: consider read ri' not returned a failure */ 92 + fail_and_restart_in_ms(0, &status, output); 93 + break; 94 + } 95 + callback_in_ms(500, output); 96 + increment_stay_counter(hdcp); 97 + break; 98 + case H1_A8_WAIT_FOR_READY: 99 + if (input->ready_check != PASS) { 100 + if (event_ctx->event == 101 + MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 102 + /* 1B-03: fail hdcp on ksv list READY timeout */ 103 + /* prevent black screen in next attempt */ 104 + adjust->hdcp1.postpone_encryption = 1; 105 + fail_and_restart_in_ms(0, &status, output); 106 + } else { 107 + /* continue ksv list READY polling*/ 108 + callback_in_ms(500, output); 109 + increment_stay_counter(hdcp); 110 + } 111 + break; 112 + } 113 + callback_in_ms(0, output); 114 + set_state_id(hdcp, output, H1_A9_READ_KSV_LIST); 115 + break; 116 + case H1_A9_READ_KSV_LIST: 117 + if (input->bstatus_read != PASS || 118 + input->max_cascade_check != PASS || 119 + input->max_devs_check != PASS || 120 + input->device_count_check != PASS || 121 + input->ksvlist_read != PASS || 122 + input->vp_read != PASS || 123 + input->ksvlist_vp_validation != PASS || 124 + input->encryption != PASS) { 125 + /* 1B-06: consider MAX_CASCADE_EXCEEDED a failure */ 126 + /* 1B-05: consider MAX_DEVS_EXCEEDED a failure */ 127 + /* 1B-04: consider invalid v' a failure */ 128 + fail_and_restart_in_ms(0, &status, output); 129 + break; 130 + } 131 + callback_in_ms(0, output); 132 + set_state_id(hdcp, output, H1_A45_AUTHENICATED); 133 + HDCP_FULL_DDC_TRACE(hdcp); 134 + break; 135 + default: 136 + status = MOD_HDCP_STATUS_INVALID_STATE; 137 + fail_and_restart_in_ms(0, &status, output); 138 + break; 139 + } 140 + 141 + return status; 142 + } 143 + 144 + enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, 145 + struct mod_hdcp_event_context *event_ctx, 146 + struct mod_hdcp_transition_input_hdcp1 *input, 147 + struct mod_hdcp_output *output) 148 + { 149 + enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 150 + struct mod_hdcp_connection *conn = &hdcp->connection; 151 + struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust; 152 + 153 + switch (current_state(hdcp)) { 154 + case D1_A0_DETERMINE_RX_HDCP_CAPABLE: 155 + if (input->bcaps_read != PASS) { 156 + /* 1A-04: no authentication on bcaps read failure */ 157 + fail_and_restart_in_ms(0, &status, output); 158 + break; 159 + } else if (input->hdcp_capable_dp != PASS) { 160 + adjust->hdcp1.disable = 1; 161 + fail_and_restart_in_ms(0, &status, output); 162 + break; 163 + } 164 + callback_in_ms(0, output); 165 + set_state_id(hdcp, output, D1_A1_EXCHANGE_KSVS); 166 + break; 167 + case D1_A1_EXCHANGE_KSVS: 168 + if (input->add_topology != PASS || 169 + input->create_session != PASS) { 170 + /* out of sync with psp state */ 171 + adjust->hdcp1.disable = 1; 172 + fail_and_restart_in_ms(0, &status, output); 173 + break; 174 + } else if (input->an_write != PASS || 175 + input->aksv_write != PASS || 176 + input->bksv_read != PASS || 177 + input->bksv_validation != PASS || 178 + input->ainfo_write == FAIL) { 179 + /* 1A-05: consider invalid bksv a failure */ 180 + fail_and_restart_in_ms(0, &status, output); 181 + break; 182 + } 183 + set_watchdog_in_ms(hdcp, 100, output); 184 + set_state_id(hdcp, output, D1_A23_WAIT_FOR_R0_PRIME); 185 + break; 186 + case D1_A23_WAIT_FOR_R0_PRIME: 187 + if (input->bstatus_read != PASS) { 188 + fail_and_restart_in_ms(0, &status, output); 189 + break; 190 + } else if (input->r0p_available_dp != PASS) { 191 + if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) 192 + fail_and_restart_in_ms(0, &status, output); 193 + else 194 + increment_stay_counter(hdcp); 195 + break; 196 + } 197 + callback_in_ms(0, output); 198 + set_state_id(hdcp, output, D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER); 199 + break; 200 + case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER: 201 + if (input->r0p_read != PASS) { 202 + fail_and_restart_in_ms(0, &status, output); 203 + break; 204 + } else if (input->rx_validation != PASS) { 205 + if (hdcp->state.stay_count < 2) { 206 + /* allow 2 additional retries */ 207 + callback_in_ms(0, output); 208 + increment_stay_counter(hdcp); 209 + } else { 210 + /* 211 + * 1A-06: consider invalid r0' a failure 212 + * after 3 attempts. 213 + * 1A-08: consider bksv listed in SRM a failure 214 + */ 215 + fail_and_restart_in_ms(0, &status, output); 216 + } 217 + break; 218 + } else if ((!conn->is_repeater && input->encryption != PASS) || 219 + (!conn->is_repeater && is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) { 220 + fail_and_restart_in_ms(0, &status, output); 221 + break; 222 + } 223 + if (conn->is_repeater) { 224 + set_watchdog_in_ms(hdcp, 5000, output); 225 + set_state_id(hdcp, output, D1_A6_WAIT_FOR_READY); 226 + } else { 227 + set_state_id(hdcp, output, D1_A4_AUTHENICATED); 228 + HDCP_FULL_DDC_TRACE(hdcp); 229 + } 230 + break; 231 + case D1_A4_AUTHENICATED: 232 + if (input->link_integiry_check != PASS || 233 + input->reauth_request_check != PASS) { 234 + /* 1A-07: restart hdcp on a link integrity failure */ 235 + fail_and_restart_in_ms(0, &status, output); 236 + break; 237 + } 238 + break; 239 + case D1_A6_WAIT_FOR_READY: 240 + if (input->link_integiry_check == FAIL || 241 + input->reauth_request_check == FAIL) { 242 + fail_and_restart_in_ms(0, &status, output); 243 + break; 244 + } else if (input->ready_check != PASS) { 245 + if (event_ctx->event == 246 + MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 247 + /* 1B-04: fail hdcp on ksv list READY timeout */ 248 + /* prevent black screen in next attempt */ 249 + adjust->hdcp1.postpone_encryption = 1; 250 + fail_and_restart_in_ms(0, &status, output); 251 + } else { 252 + increment_stay_counter(hdcp); 253 + } 254 + break; 255 + } 256 + callback_in_ms(0, output); 257 + set_state_id(hdcp, output, D1_A7_READ_KSV_LIST); 258 + break; 259 + case D1_A7_READ_KSV_LIST: 260 + if (input->binfo_read_dp != PASS || 261 + input->max_cascade_check != PASS || 262 + input->max_devs_check != PASS) { 263 + /* 1B-06: consider MAX_DEVS_EXCEEDED a failure */ 264 + /* 1B-07: consider MAX_CASCADE_EXCEEDED a failure */ 265 + fail_and_restart_in_ms(0, &status, output); 266 + break; 267 + } else if (input->device_count_check != PASS) { 268 + /* 269 + * some slow dongle doesn't update 270 + * device count as soon as downstream is connected. 271 + * give it more time to react. 272 + */ 273 + adjust->hdcp1.postpone_encryption = 1; 274 + fail_and_restart_in_ms(1000, &status, output); 275 + break; 276 + } else if (input->ksvlist_read != PASS || 277 + input->vp_read != PASS) { 278 + fail_and_restart_in_ms(0, &status, output); 279 + break; 280 + } else if (input->ksvlist_vp_validation != PASS) { 281 + if (hdcp->state.stay_count < 2) { 282 + /* allow 2 additional retries */ 283 + callback_in_ms(0, output); 284 + increment_stay_counter(hdcp); 285 + } else { 286 + /* 287 + * 1B-05: consider invalid v' a failure 288 + * after 3 attempts. 289 + */ 290 + fail_and_restart_in_ms(0, &status, output); 291 + } 292 + break; 293 + } else if (input->encryption != PASS || 294 + (is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) { 295 + fail_and_restart_in_ms(0, &status, output); 296 + break; 297 + } 298 + set_state_id(hdcp, output, D1_A4_AUTHENICATED); 299 + HDCP_FULL_DDC_TRACE(hdcp); 300 + break; 301 + default: 302 + fail_and_restart_in_ms(0, &status, output); 303 + break; 304 + } 305 + 306 + return status; 307 + }
+305
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
··· 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 + enum mod_hdcp_ddc_message_id { 34 + MOD_HDCP_MESSAGE_ID_INVALID = -1, 35 + 36 + /* HDCP 1.4 */ 37 + 38 + MOD_HDCP_MESSAGE_ID_READ_BKSV = 0, 39 + MOD_HDCP_MESSAGE_ID_READ_RI_R0, 40 + MOD_HDCP_MESSAGE_ID_WRITE_AKSV, 41 + MOD_HDCP_MESSAGE_ID_WRITE_AINFO, 42 + MOD_HDCP_MESSAGE_ID_WRITE_AN, 43 + MOD_HDCP_MESSAGE_ID_READ_VH_X, 44 + MOD_HDCP_MESSAGE_ID_READ_VH_0, 45 + MOD_HDCP_MESSAGE_ID_READ_VH_1, 46 + MOD_HDCP_MESSAGE_ID_READ_VH_2, 47 + MOD_HDCP_MESSAGE_ID_READ_VH_3, 48 + MOD_HDCP_MESSAGE_ID_READ_VH_4, 49 + MOD_HDCP_MESSAGE_ID_READ_BCAPS, 50 + MOD_HDCP_MESSAGE_ID_READ_BSTATUS, 51 + MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO, 52 + MOD_HDCP_MESSAGE_ID_READ_BINFO, 53 + 54 + MOD_HDCP_MESSAGE_ID_MAX 55 + }; 56 + 57 + static const uint8_t hdcp_i2c_offsets[] = { 58 + [MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x0, 59 + [MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x8, 60 + [MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10, 61 + [MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15, 62 + [MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x18, 63 + [MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x20, 64 + [MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x20, 65 + [MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x24, 66 + [MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x28, 67 + [MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x2C, 68 + [MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x30, 69 + [MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x40, 70 + [MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41, 71 + [MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43, 72 + [MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0xFF, 73 + }; 74 + 75 + static const uint32_t hdcp_dpcd_addrs[] = { 76 + [MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x68000, 77 + [MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005, 78 + [MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007, 79 + [MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B, 80 + [MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c, 81 + [MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x68014, 82 + [MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x68014, 83 + [MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x68018, 84 + [MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c, 85 + [MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x68020, 86 + [MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x68024, 87 + [MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028, 88 + [MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029, 89 + [MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c, 90 + [MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a, 91 + }; 92 + 93 + static enum mod_hdcp_status read(struct mod_hdcp *hdcp, 94 + enum mod_hdcp_ddc_message_id msg_id, 95 + uint8_t *buf, 96 + uint32_t buf_len) 97 + { 98 + bool success = true; 99 + uint32_t cur_size = 0; 100 + uint32_t data_offset = 0; 101 + 102 + if (is_dp_hdcp(hdcp)) { 103 + while (buf_len > 0) { 104 + cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE); 105 + success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle, 106 + hdcp_dpcd_addrs[msg_id] + data_offset, 107 + buf + data_offset, 108 + cur_size); 109 + 110 + if (!success) 111 + break; 112 + 113 + buf_len -= cur_size; 114 + data_offset += cur_size; 115 + } 116 + } else { 117 + success = hdcp->config.ddc.funcs.read_i2c( 118 + hdcp->config.ddc.handle, 119 + HDCP_I2C_ADDR, 120 + hdcp_i2c_offsets[msg_id], 121 + buf, 122 + (uint32_t)buf_len); 123 + } 124 + 125 + return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; 126 + } 127 + 128 + static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp, 129 + enum mod_hdcp_ddc_message_id msg_id, 130 + uint8_t *buf, 131 + uint32_t buf_len, 132 + uint8_t read_size) 133 + { 134 + enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE; 135 + uint32_t cur_size = 0; 136 + uint32_t data_offset = 0; 137 + 138 + while (buf_len > 0) { 139 + cur_size = MIN(buf_len, read_size); 140 + status = read(hdcp, msg_id, buf + data_offset, cur_size); 141 + 142 + if (status != MOD_HDCP_STATUS_SUCCESS) 143 + break; 144 + 145 + buf_len -= cur_size; 146 + data_offset += cur_size; 147 + } 148 + 149 + return status; 150 + } 151 + 152 + static enum mod_hdcp_status write(struct mod_hdcp *hdcp, 153 + enum mod_hdcp_ddc_message_id msg_id, 154 + uint8_t *buf, 155 + uint32_t buf_len) 156 + { 157 + bool success = true; 158 + uint32_t cur_size = 0; 159 + uint32_t data_offset = 0; 160 + 161 + if (is_dp_hdcp(hdcp)) { 162 + while (buf_len > 0) { 163 + cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE); 164 + success = hdcp->config.ddc.funcs.write_dpcd( 165 + hdcp->config.ddc.handle, 166 + hdcp_dpcd_addrs[msg_id] + data_offset, 167 + buf + data_offset, 168 + cur_size); 169 + 170 + if (!success) 171 + break; 172 + 173 + buf_len -= cur_size; 174 + data_offset += cur_size; 175 + } 176 + } else { 177 + hdcp->buf[0] = hdcp_i2c_offsets[msg_id]; 178 + memmove(&hdcp->buf[1], buf, buf_len); 179 + success = hdcp->config.ddc.funcs.write_i2c( 180 + hdcp->config.ddc.handle, 181 + HDCP_I2C_ADDR, 182 + hdcp->buf, 183 + (uint32_t)(buf_len+1)); 184 + } 185 + 186 + return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; 187 + } 188 + 189 + enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp) 190 + { 191 + return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV, 192 + hdcp->auth.msg.hdcp1.bksv, 193 + sizeof(hdcp->auth.msg.hdcp1.bksv)); 194 + } 195 + 196 + enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp) 197 + { 198 + return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS, 199 + &hdcp->auth.msg.hdcp1.bcaps, 200 + sizeof(hdcp->auth.msg.hdcp1.bcaps)); 201 + } 202 + 203 + enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp) 204 + { 205 + enum mod_hdcp_status status; 206 + 207 + if (is_dp_hdcp(hdcp)) 208 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS, 209 + (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus, 210 + 1); 211 + else 212 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS, 213 + (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus, 214 + sizeof(hdcp->auth.msg.hdcp1.bstatus)); 215 + return status; 216 + } 217 + 218 + enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp) 219 + { 220 + return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0, 221 + (uint8_t *)&hdcp->auth.msg.hdcp1.r0p, 222 + sizeof(hdcp->auth.msg.hdcp1.r0p)); 223 + } 224 + 225 + /* special case, reading repeatedly at the same address, don't use read() */ 226 + enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp) 227 + { 228 + enum mod_hdcp_status status; 229 + 230 + if (is_dp_hdcp(hdcp)) 231 + status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO, 232 + hdcp->auth.msg.hdcp1.ksvlist, 233 + hdcp->auth.msg.hdcp1.ksvlist_size, 234 + KSV_READ_SIZE); 235 + else 236 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO, 237 + (uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist, 238 + hdcp->auth.msg.hdcp1.ksvlist_size); 239 + return status; 240 + } 241 + 242 + enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp) 243 + { 244 + enum mod_hdcp_status status; 245 + 246 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0, 247 + &hdcp->auth.msg.hdcp1.vp[0], 4); 248 + if (status != MOD_HDCP_STATUS_SUCCESS) 249 + goto out; 250 + 251 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1, 252 + &hdcp->auth.msg.hdcp1.vp[4], 4); 253 + if (status != MOD_HDCP_STATUS_SUCCESS) 254 + goto out; 255 + 256 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2, 257 + &hdcp->auth.msg.hdcp1.vp[8], 4); 258 + if (status != MOD_HDCP_STATUS_SUCCESS) 259 + goto out; 260 + 261 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3, 262 + &hdcp->auth.msg.hdcp1.vp[12], 4); 263 + if (status != MOD_HDCP_STATUS_SUCCESS) 264 + goto out; 265 + 266 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4, 267 + &hdcp->auth.msg.hdcp1.vp[16], 4); 268 + out: 269 + return status; 270 + } 271 + 272 + enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp) 273 + { 274 + enum mod_hdcp_status status; 275 + 276 + if (is_dp_hdcp(hdcp)) 277 + status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO, 278 + (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp, 279 + sizeof(hdcp->auth.msg.hdcp1.binfo_dp)); 280 + else 281 + status = MOD_HDCP_STATUS_INVALID_OPERATION; 282 + 283 + return status; 284 + } 285 + 286 + enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp) 287 + { 288 + return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV, 289 + hdcp->auth.msg.hdcp1.aksv, 290 + sizeof(hdcp->auth.msg.hdcp1.aksv)); 291 + } 292 + 293 + enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp) 294 + { 295 + return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO, 296 + &hdcp->auth.msg.hdcp1.ainfo, 297 + sizeof(hdcp->auth.msg.hdcp1.ainfo)); 298 + } 299 + 300 + enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp) 301 + { 302 + return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN, 303 + hdcp->auth.msg.hdcp1.an, 304 + sizeof(hdcp->auth.msg.hdcp1.an)); 305 + }
+163
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c
··· 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 + 27 + #include "hdcp.h" 28 + 29 + void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size, 30 + uint8_t *buf, uint32_t buf_size) 31 + { 32 + const uint8_t bytes_per_line = 16, 33 + byte_size = 3, 34 + newline_size = 1, 35 + terminator_size = 1; 36 + uint32_t line_count = msg_size / bytes_per_line, 37 + trailing_bytes = msg_size % bytes_per_line; 38 + uint32_t target_size = (byte_size * bytes_per_line + newline_size) * line_count + 39 + byte_size * trailing_bytes + newline_size + terminator_size; 40 + uint32_t buf_pos = 0; 41 + uint32_t i = 0; 42 + 43 + if (buf_size >= target_size) { 44 + for (i = 0; i < msg_size; i++) { 45 + if (i % bytes_per_line == 0) 46 + buf[buf_pos++] = '\n'; 47 + sprintf(&buf[buf_pos], "%02X ", msg[i]); 48 + buf_pos += byte_size; 49 + } 50 + buf[buf_pos++] = '\0'; 51 + } 52 + } 53 + 54 + char *mod_hdcp_status_to_str(int32_t status) 55 + { 56 + switch (status) { 57 + case MOD_HDCP_STATUS_SUCCESS: 58 + return "MOD_HDCP_STATUS_SUCCESS"; 59 + case MOD_HDCP_STATUS_FAILURE: 60 + return "MOD_HDCP_STATUS_FAILURE"; 61 + case MOD_HDCP_STATUS_RESET_NEEDED: 62 + return "MOD_HDCP_STATUS_RESET_NEEDED"; 63 + case MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND: 64 + return "MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND"; 65 + case MOD_HDCP_STATUS_DISPLAY_NOT_FOUND: 66 + return "MOD_HDCP_STATUS_DISPLAY_NOT_FOUND"; 67 + case MOD_HDCP_STATUS_INVALID_STATE: 68 + return "MOD_HDCP_STATUS_INVALID_STATE"; 69 + case MOD_HDCP_STATUS_NOT_IMPLEMENTED: 70 + return "MOD_HDCP_STATUS_NOT_IMPLEMENTED"; 71 + case MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE: 72 + return "MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE"; 73 + case MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE: 74 + return "MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE"; 75 + case MOD_HDCP_STATUS_CREATE_PSP_SERVICE_FAILURE: 76 + return "MOD_HDCP_STATUS_CREATE_PSP_SERVICE_FAILURE"; 77 + case MOD_HDCP_STATUS_DESTROY_PSP_SERVICE_FAILURE: 78 + return "MOD_HDCP_STATUS_DESTROY_PSP_SERVICE_FAILURE"; 79 + case MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE: 80 + return "MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE"; 81 + case MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE: 82 + return "MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE"; 83 + case MOD_HDCP_STATUS_HDCP1_VALIDATE_ENCRYPTION_FAILURE: 84 + return "MOD_HDCP_STATUS_HDCP1_VALIDATE_ENCRYPTION_FAILURE"; 85 + case MOD_HDCP_STATUS_HDCP1_NOT_HDCP_REPEATER: 86 + return "MOD_HDCP_STATUS_HDCP1_NOT_HDCP_REPEATER"; 87 + case MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE: 88 + return "MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE"; 89 + case MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING: 90 + return "MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING"; 91 + case MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE: 92 + return "MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE"; 93 + case MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY: 94 + return "MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY"; 95 + case MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE: 96 + return "MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE"; 97 + case MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION: 98 + return "MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION"; 99 + case MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE: 100 + return "MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE"; 101 + case MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE: 102 + return "MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE"; 103 + case MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE: 104 + return "MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE"; 105 + case MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE: 106 + return "MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE"; 107 + case MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE: 108 + return "MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE"; 109 + case MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED: 110 + return "MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED"; 111 + case MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE: 112 + return "MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE"; 113 + case MOD_HDCP_STATUS_HDCP1_INVALID_BKSV: 114 + return "MOD_HDCP_STATUS_HDCP1_INVALID_BKSV"; 115 + case MOD_HDCP_STATUS_DDC_FAILURE: 116 + return "MOD_HDCP_STATUS_DDC_FAILURE"; 117 + case MOD_HDCP_STATUS_INVALID_OPERATION: 118 + return "MOD_HDCP_STATUS_INVALID_OPERATION"; 119 + default: 120 + return "MOD_HDCP_STATUS_UNKNOWN"; 121 + } 122 + } 123 + 124 + char *mod_hdcp_state_id_to_str(int32_t id) 125 + { 126 + switch (id) { 127 + case HDCP_UNINITIALIZED: 128 + return "HDCP_UNINITIALIZED"; 129 + case HDCP_INITIALIZED: 130 + return "HDCP_INITIALIZED"; 131 + case HDCP_CP_NOT_DESIRED: 132 + return "HDCP_CP_NOT_DESIRED"; 133 + case H1_A0_WAIT_FOR_ACTIVE_RX: 134 + return "H1_A0_WAIT_FOR_ACTIVE_RX"; 135 + case H1_A1_EXCHANGE_KSVS: 136 + return "H1_A1_EXCHANGE_KSVS"; 137 + case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER: 138 + return "H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER"; 139 + case H1_A45_AUTHENICATED: 140 + return "H1_A45_AUTHENICATED"; 141 + case H1_A8_WAIT_FOR_READY: 142 + return "H1_A8_WAIT_FOR_READY"; 143 + case H1_A9_READ_KSV_LIST: 144 + return "H1_A9_READ_KSV_LIST"; 145 + case D1_A0_DETERMINE_RX_HDCP_CAPABLE: 146 + return "D1_A0_DETERMINE_RX_HDCP_CAPABLE"; 147 + case D1_A1_EXCHANGE_KSVS: 148 + return "D1_A1_EXCHANGE_KSVS"; 149 + case D1_A23_WAIT_FOR_R0_PRIME: 150 + return "D1_A23_WAIT_FOR_R0_PRIME"; 151 + case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER: 152 + return "D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER"; 153 + case D1_A4_AUTHENICATED: 154 + return "D1_A4_AUTHENICATED"; 155 + case D1_A6_WAIT_FOR_READY: 156 + return "D1_A6_WAIT_FOR_READY"; 157 + case D1_A7_READ_KSV_LIST: 158 + return "D1_A7_READ_KSV_LIST"; 159 + default: 160 + return "UNKNOWN_STATE_ID"; 161 + }; 162 + } 163 +
+139
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
··· 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 + #ifndef MOD_HDCP_LOG_H_ 27 + #define MOD_HDCP_LOG_H_ 28 + 29 + #ifdef CONFIG_DRM_AMD_DC_HDCP 30 + #define HDCP_LOG_ERR(hdcp, ...) DRM_ERROR(__VA_ARGS__) 31 + #define HDCP_LOG_VER(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) 32 + #define HDCP_LOG_FSM(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) 33 + #define HDCP_LOG_TOP(hdcp, ...) pr_debug("[HDCP_TOP]:"__VA_ARGS__) 34 + #define HDCP_LOG_DDC(hdcp, ...) pr_debug("[HDCP_DDC]:"__VA_ARGS__) 35 + #endif 36 + 37 + /* default logs */ 38 + #define HDCP_ERROR_TRACE(hdcp, status) \ 39 + HDCP_LOG_ERR(hdcp, \ 40 + "[Link %d] ERROR %s IN STATE %s", \ 41 + hdcp->config.index, \ 42 + mod_hdcp_status_to_str(status), \ 43 + mod_hdcp_state_id_to_str(hdcp->state.id)) 44 + #define HDCP_HDCP1_ENABLED_TRACE(hdcp, displayIndex) \ 45 + HDCP_LOG_VER(hdcp, \ 46 + "[Link %d] HDCP 1.4 enabled on display %d", \ 47 + hdcp->config.index, displayIndex) 48 + /* state machine logs */ 49 + #define HDCP_REMOVE_DISPLAY_TRACE(hdcp, displayIndex) \ 50 + HDCP_LOG_FSM(hdcp, \ 51 + "[Link %d] HDCP_REMOVE_DISPLAY index %d", \ 52 + hdcp->config.index, displayIndex) 53 + #define HDCP_INPUT_PASS_TRACE(hdcp, str) \ 54 + HDCP_LOG_FSM(hdcp, \ 55 + "[Link %d]\tPASS %s", \ 56 + hdcp->config.index, str) 57 + #define HDCP_INPUT_FAIL_TRACE(hdcp, str) \ 58 + HDCP_LOG_FSM(hdcp, \ 59 + "[Link %d]\tFAIL %s", \ 60 + hdcp->config.index, str) 61 + #define HDCP_NEXT_STATE_TRACE(hdcp, id, output) do { \ 62 + if (output->watchdog_timer_needed) \ 63 + HDCP_LOG_FSM(hdcp, \ 64 + "[Link %d] > %s with %d ms watchdog", \ 65 + hdcp->config.index, \ 66 + mod_hdcp_state_id_to_str(id), output->watchdog_timer_delay); \ 67 + else \ 68 + HDCP_LOG_FSM(hdcp, \ 69 + "[Link %d] > %s", hdcp->config.index, \ 70 + mod_hdcp_state_id_to_str(id)); \ 71 + } while (0) 72 + #define HDCP_TIMEOUT_TRACE(hdcp) \ 73 + HDCP_LOG_FSM(hdcp, "[Link %d] --> TIMEOUT", hdcp->config.index) 74 + #define HDCP_CPIRQ_TRACE(hdcp) \ 75 + HDCP_LOG_FSM(hdcp, "[Link %d] --> CPIRQ", hdcp->config.index) 76 + #define HDCP_EVENT_TRACE(hdcp, event) \ 77 + if (event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) \ 78 + HDCP_TIMEOUT_TRACE(hdcp); \ 79 + else if (event == MOD_HDCP_EVENT_CPIRQ) \ 80 + HDCP_CPIRQ_TRACE(hdcp) 81 + /* TODO: find some way to tell if logging is off to save time */ 82 + #define HDCP_DDC_READ_TRACE(hdcp, msg_name, msg, msg_size) do { \ 83 + mod_hdcp_dump_binary_message(msg, msg_size, hdcp->buf, \ 84 + sizeof(hdcp->buf)); \ 85 + HDCP_LOG_DDC(hdcp, "[Link %d] Read %s%s", hdcp->config.index, \ 86 + msg_name, hdcp->buf); \ 87 + } while (0) 88 + #define HDCP_DDC_WRITE_TRACE(hdcp, msg_name, msg, msg_size) do { \ 89 + mod_hdcp_dump_binary_message(msg, msg_size, hdcp->buf, \ 90 + sizeof(hdcp->buf)); \ 91 + HDCP_LOG_DDC(hdcp, "[Link %d] Write %s%s", \ 92 + hdcp->config.index, msg_name,\ 93 + hdcp->buf); \ 94 + } while (0) 95 + #define HDCP_FULL_DDC_TRACE(hdcp) do { \ 96 + HDCP_DDC_READ_TRACE(hdcp, "BKSV", hdcp->auth.msg.hdcp1.bksv, \ 97 + sizeof(hdcp->auth.msg.hdcp1.bksv)); \ 98 + HDCP_DDC_READ_TRACE(hdcp, "BCAPS", &hdcp->auth.msg.hdcp1.bcaps, \ 99 + sizeof(hdcp->auth.msg.hdcp1.bcaps)); \ 100 + HDCP_DDC_WRITE_TRACE(hdcp, "AN", hdcp->auth.msg.hdcp1.an, \ 101 + sizeof(hdcp->auth.msg.hdcp1.an)); \ 102 + HDCP_DDC_WRITE_TRACE(hdcp, "AKSV", hdcp->auth.msg.hdcp1.aksv, \ 103 + sizeof(hdcp->auth.msg.hdcp1.aksv)); \ 104 + HDCP_DDC_WRITE_TRACE(hdcp, "AINFO", &hdcp->auth.msg.hdcp1.ainfo, \ 105 + sizeof(hdcp->auth.msg.hdcp1.ainfo)); \ 106 + HDCP_DDC_READ_TRACE(hdcp, "RI' / R0'", \ 107 + (uint8_t *)&hdcp->auth.msg.hdcp1.r0p, \ 108 + sizeof(hdcp->auth.msg.hdcp1.r0p)); \ 109 + HDCP_DDC_READ_TRACE(hdcp, "BINFO", \ 110 + (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp, \ 111 + sizeof(hdcp->auth.msg.hdcp1.binfo_dp)); \ 112 + HDCP_DDC_READ_TRACE(hdcp, "KSVLIST", hdcp->auth.msg.hdcp1.ksvlist, \ 113 + hdcp->auth.msg.hdcp1.ksvlist_size); \ 114 + HDCP_DDC_READ_TRACE(hdcp, "V'", hdcp->auth.msg.hdcp1.vp, \ 115 + sizeof(hdcp->auth.msg.hdcp1.vp)); \ 116 + } while (0) 117 + #define HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, i) \ 118 + HDCP_LOG_TOP(hdcp, "[Link %d]\tadd display %d", \ 119 + hdcp->config.index, i) 120 + #define HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, i) \ 121 + HDCP_LOG_TOP(hdcp, "[Link %d]\tremove display %d", \ 122 + hdcp->config.index, i) 123 + #define HDCP_TOP_HDCP1_DESTROY_SESSION_TRACE(hdcp) \ 124 + HDCP_LOG_TOP(hdcp, "[Link %d]\tdestroy hdcp1 session", \ 125 + hdcp->config.index) 126 + #define HDCP_TOP_RESET_AUTH_TRACE(hdcp) \ 127 + HDCP_LOG_TOP(hdcp, "[Link %d]\treset authentication", hdcp->config.index) 128 + #define HDCP_TOP_RESET_CONN_TRACE(hdcp) \ 129 + HDCP_LOG_TOP(hdcp, "[Link %d]\treset connection", hdcp->config.index) 130 + #define HDCP_TOP_INTERFACE_TRACE(hdcp) do { \ 131 + HDCP_LOG_TOP(hdcp, "\n"); \ 132 + HDCP_LOG_TOP(hdcp, "[Link %d] %s", hdcp->config.index, __func__); \ 133 + } while (0) 134 + #define HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, i) do { \ 135 + HDCP_LOG_TOP(hdcp, "\n"); \ 136 + HDCP_LOG_TOP(hdcp, "[Link %d] %s display %d", hdcp->config.index, __func__, i); \ 137 + } while (0) 138 + 139 + #endif // MOD_HDCP_LOG_H_
+289
drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
··· 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 + #ifndef MOD_HDCP_H_ 27 + #define MOD_HDCP_H_ 28 + 29 + #include "os_types.h" 30 + #include "signal_types.h" 31 + 32 + /* Forward Declarations */ 33 + struct mod_hdcp; 34 + 35 + #define MAX_NUM_OF_DISPLAYS 6 36 + #define MAX_NUM_OF_ATTEMPTS 4 37 + #define MAX_NUM_OF_ERROR_TRACE 10 38 + 39 + /* detailed return status */ 40 + enum mod_hdcp_status { 41 + MOD_HDCP_STATUS_SUCCESS = 0, 42 + MOD_HDCP_STATUS_FAILURE, 43 + MOD_HDCP_STATUS_RESET_NEEDED, 44 + MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND, 45 + MOD_HDCP_STATUS_DISPLAY_NOT_FOUND, 46 + MOD_HDCP_STATUS_INVALID_STATE, 47 + MOD_HDCP_STATUS_NOT_IMPLEMENTED, 48 + MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE, 49 + MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE, 50 + MOD_HDCP_STATUS_CREATE_PSP_SERVICE_FAILURE, 51 + MOD_HDCP_STATUS_DESTROY_PSP_SERVICE_FAILURE, 52 + MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE, 53 + MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE, 54 + MOD_HDCP_STATUS_HDCP1_VALIDATE_ENCRYPTION_FAILURE, 55 + MOD_HDCP_STATUS_HDCP1_NOT_HDCP_REPEATER, 56 + MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE, 57 + MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING, 58 + MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE, 59 + MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY, 60 + MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE, 61 + MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION, 62 + MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE, 63 + MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE, 64 + MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE, 65 + MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE, 66 + MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE, 67 + MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED, 68 + MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE, 69 + MOD_HDCP_STATUS_HDCP1_INVALID_BKSV, 70 + MOD_HDCP_STATUS_DDC_FAILURE, /* TODO: specific errors */ 71 + MOD_HDCP_STATUS_INVALID_OPERATION, 72 + MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE, 73 + MOD_HDCP_STATUS_HDCP2_CREATE_SESSION_FAILURE, 74 + MOD_HDCP_STATUS_HDCP2_DESTROY_SESSION_FAILURE, 75 + MOD_HDCP_STATUS_HDCP2_PREP_AKE_INIT_FAILURE, 76 + MOD_HDCP_STATUS_HDCP2_AKE_CERT_PENDING, 77 + MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING, 78 + MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING, 79 + MOD_HDCP_STATUS_HDCP2_VALIDATE_AKE_CERT_FAILURE, 80 + MOD_HDCP_STATUS_HDCP2_VALIDATE_H_PRIME_FAILURE, 81 + MOD_HDCP_STATUS_HDCP2_VALIDATE_PAIRING_INFO_FAILURE, 82 + MOD_HDCP_STATUS_HDCP2_PREP_LC_INIT_FAILURE, 83 + MOD_HDCP_STATUS_HDCP2_L_PRIME_PENDING, 84 + MOD_HDCP_STATUS_HDCP2_VALIDATE_L_PRIME_FAILURE, 85 + MOD_HDCP_STATUS_HDCP2_PREP_EKS_FAILURE, 86 + MOD_HDCP_STATUS_HDCP2_ENABLE_ENCRYPTION_FAILURE, 87 + MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY, 88 + MOD_HDCP_STATUS_HDCP2_VALIDATE_RX_ID_LIST_FAILURE, 89 + MOD_HDCP_STATUS_HDCP2_ENABLE_STREAM_ENCRYPTION, 90 + MOD_HDCP_STATUS_HDCP2_STREAM_READY_PENDING, 91 + MOD_HDCP_STATUS_HDCP2_VALIDATE_STREAM_READY_FAILURE, 92 + MOD_HDCP_STATUS_HDCP2_PREPARE_STREAM_MANAGEMENT_FAILURE, 93 + MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST, 94 + MOD_HDCP_STATUS_HDCP2_REAUTH_LINK_INTEGRITY_FAILURE, 95 + MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE, 96 + }; 97 + 98 + struct mod_hdcp_displayport { 99 + uint8_t rev; 100 + uint8_t assr_supported; 101 + }; 102 + 103 + struct mod_hdcp_hdmi { 104 + uint8_t reserved; 105 + }; 106 + enum mod_hdcp_operation_mode { 107 + MOD_HDCP_MODE_OFF, 108 + MOD_HDCP_MODE_DEFAULT, 109 + MOD_HDCP_MODE_DP, 110 + MOD_HDCP_MODE_DP_MST 111 + }; 112 + 113 + enum mod_hdcp_display_state { 114 + MOD_HDCP_DISPLAY_INACTIVE = 0, 115 + MOD_HDCP_DISPLAY_ACTIVE, 116 + MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED, 117 + MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED 118 + }; 119 + 120 + struct mod_hdcp_ddc { 121 + void *handle; 122 + struct { 123 + bool (*read_i2c)(void *handle, 124 + uint32_t address, 125 + uint8_t offset, 126 + uint8_t *data, 127 + uint32_t size); 128 + bool (*write_i2c)(void *handle, 129 + uint32_t address, 130 + const uint8_t *data, 131 + uint32_t size); 132 + bool (*read_dpcd)(void *handle, 133 + uint32_t address, 134 + uint8_t *data, 135 + uint32_t size); 136 + bool (*write_dpcd)(void *handle, 137 + uint32_t address, 138 + const uint8_t *data, 139 + uint32_t size); 140 + } funcs; 141 + }; 142 + 143 + struct mod_hdcp_psp { 144 + void *handle; 145 + void *funcs; 146 + }; 147 + 148 + struct mod_hdcp_display_adjustment { 149 + uint8_t disable : 1; 150 + uint8_t reserved : 7; 151 + }; 152 + 153 + struct mod_hdcp_link_adjustment_hdcp1 { 154 + uint8_t disable : 1; 155 + uint8_t postpone_encryption : 1; 156 + uint8_t reserved : 6; 157 + }; 158 + 159 + struct mod_hdcp_link_adjustment_hdcp2 { 160 + uint8_t disable : 1; 161 + uint8_t disable_type1 : 1; 162 + uint8_t force_no_stored_km : 1; 163 + uint8_t increase_h_prime_timeout: 1; 164 + uint8_t reserved : 4; 165 + }; 166 + 167 + struct mod_hdcp_link_adjustment { 168 + uint8_t auth_delay; 169 + struct mod_hdcp_link_adjustment_hdcp1 hdcp1; 170 + struct mod_hdcp_link_adjustment_hdcp2 hdcp2; 171 + }; 172 + 173 + struct mod_hdcp_error { 174 + enum mod_hdcp_status status; 175 + uint8_t state_id; 176 + }; 177 + 178 + struct mod_hdcp_trace { 179 + struct mod_hdcp_error errors[MAX_NUM_OF_ERROR_TRACE]; 180 + uint8_t error_count; 181 + }; 182 + 183 + enum mod_hdcp_encryption_status { 184 + MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF = 0, 185 + MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON, 186 + MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON, 187 + MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON 188 + }; 189 + 190 + /* per link events dm has to notify to hdcp module */ 191 + enum mod_hdcp_event { 192 + MOD_HDCP_EVENT_CALLBACK = 0, 193 + MOD_HDCP_EVENT_WATCHDOG_TIMEOUT, 194 + MOD_HDCP_EVENT_CPIRQ 195 + }; 196 + 197 + /* output flags from module requesting timer operations */ 198 + struct mod_hdcp_output { 199 + uint8_t callback_needed; 200 + uint8_t callback_stop; 201 + uint8_t watchdog_timer_needed; 202 + uint8_t watchdog_timer_stop; 203 + uint16_t callback_delay; 204 + uint16_t watchdog_timer_delay; 205 + }; 206 + 207 + /* used to represent per display info */ 208 + struct mod_hdcp_display { 209 + enum mod_hdcp_display_state state; 210 + uint8_t index; 211 + uint8_t controller; 212 + uint8_t dig_fe; 213 + union { 214 + uint8_t vc_id; 215 + }; 216 + struct mod_hdcp_display_adjustment adjust; 217 + }; 218 + 219 + /* used to represent per link info */ 220 + /* in case a link has multiple displays, they share the same link info */ 221 + struct mod_hdcp_link { 222 + enum mod_hdcp_operation_mode mode; 223 + uint8_t dig_be; 224 + uint8_t ddc_line; 225 + union { 226 + struct mod_hdcp_displayport dp; 227 + struct mod_hdcp_hdmi hdmi; 228 + }; 229 + struct mod_hdcp_link_adjustment adjust; 230 + }; 231 + 232 + /* a query structure for a display's hdcp information */ 233 + struct mod_hdcp_display_query { 234 + const struct mod_hdcp_display *display; 235 + const struct mod_hdcp_link *link; 236 + const struct mod_hdcp_trace *trace; 237 + enum mod_hdcp_encryption_status encryption_status; 238 + }; 239 + 240 + /* contains values per on external display configuration change */ 241 + struct mod_hdcp_config { 242 + struct mod_hdcp_psp psp; 243 + struct mod_hdcp_ddc ddc; 244 + uint8_t index; 245 + }; 246 + 247 + struct mod_hdcp; 248 + 249 + /* dm allocates memory of mod_hdcp per dc_link on dm init based on memory size*/ 250 + size_t mod_hdcp_get_memory_size(void); 251 + 252 + /* called per link on link creation */ 253 + enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp, 254 + struct mod_hdcp_config *config); 255 + 256 + /* called per link on link destroy */ 257 + enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp); 258 + 259 + /* called per display on cp_desired set to true */ 260 + enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp, 261 + struct mod_hdcp_link *link, struct mod_hdcp_display *display, 262 + struct mod_hdcp_output *output); 263 + 264 + /* called per display on cp_desired set to false */ 265 + enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp, 266 + uint8_t index, struct mod_hdcp_output *output); 267 + 268 + /* called to query hdcp information on a specific index */ 269 + enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp, 270 + uint8_t index, struct mod_hdcp_display_query *query); 271 + 272 + /* called per link on connectivity change */ 273 + enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp, 274 + struct mod_hdcp_output *output); 275 + 276 + /* called per link on events (i.e. callback, watchdog, CP_IRQ) */ 277 + enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp, 278 + enum mod_hdcp_event event, struct mod_hdcp_output *output); 279 + 280 + /* called to convert enum mod_hdcp_status to c string */ 281 + char *mod_hdcp_status_to_str(int32_t status); 282 + 283 + /* called to convert state id to c string */ 284 + char *mod_hdcp_state_id_to_str(int32_t id); 285 + 286 + /* called to convert signal type to operation mode */ 287 + enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode( 288 + enum signal_type signal); 289 + #endif /* MOD_HDCP_H_ */