1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2026 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: AMD 24 * 25 */ 26 27 #include "dm_services_types.h" 28 #include "dc.h" 29 #include "dc/inc/core_types.h" 30 #include "dc/dc_dmub_srv.h" 31 #include "dmub/dmub_srv.h" 32 #include "dc/inc/hw/dmcu.h" 33 #include "dc/inc/hw/abm.h" 34 #include "dal_asic_id.h" 35 36 #include "amdgpu.h" 37 #include "amdgpu_display.h" 38 #include "amdgpu_ucode.h" 39 #include "amdgpu_dm.h" 40 #include "amdgpu_dm_dmub.h" 41 #include "dm_helpers.h" 42 #include <linux/component.h> 43 #include <linux/firmware.h> 44 45 static_assert(AMDGPU_DMUB_NOTIFICATION_MAX == DMUB_NOTIFICATION_MAX, "AMDGPU_DMUB_NOTIFICATION_MAX mismatch"); 46 47 MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB); 48 MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB); 49 MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER_DMUB); 50 MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE_DMUB); 51 MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB); 52 MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB); 53 MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB); 54 MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP_DMUB); 55 MODULE_FIRMWARE(FIRMWARE_DCN_314_DMUB); 56 MODULE_FIRMWARE(FIRMWARE_DCN_315_DMUB); 57 MODULE_FIRMWARE(FIRMWARE_DCN316_DMUB); 58 MODULE_FIRMWARE(FIRMWARE_DCN_V3_2_0_DMCUB); 59 MODULE_FIRMWARE(FIRMWARE_DCN_V3_2_1_DMCUB); 60 MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB); 61 MODULE_FIRMWARE(FIRMWARE_DCN_351_DMUB); 62 MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB); 63 MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB); 64 MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB); 65 MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB); 66 MODULE_FIRMWARE(FIRMWARE_DCN_60_DMUB); 67 68 /** 69 * dm_dmub_aux_setconfig_callback - Callback for AUX or SET_CONFIG command. 70 * @adev: amdgpu_device pointer 71 * @notify: dmub notification structure 72 * 73 * Dmub AUX or SET_CONFIG command completion processing callback 74 * Copies dmub notification to DM which is to be read by AUX command. 75 * issuing thread and also signals the event to wake up the thread. 76 */ 77 void dm_dmub_aux_setconfig_callback(struct amdgpu_device *adev, 78 struct dmub_notification *notify) 79 { 80 if (adev->dm.dmub_notify) 81 memcpy(adev->dm.dmub_notify, notify, sizeof(struct dmub_notification)); 82 if (notify->type == DMUB_NOTIFICATION_AUX_REPLY) 83 complete(&adev->dm.dmub_aux_transfer_done); 84 } 85 EXPORT_IF_KUNIT(dm_dmub_aux_setconfig_callback); 86 87 void dm_dmub_aux_fused_io_callback(struct amdgpu_device *adev, 88 struct dmub_notification *notify) 89 { 90 if (!adev || !notify) { 91 ASSERT(false); 92 return; 93 } 94 95 const struct dmub_cmd_fused_request *req = ¬ify->fused_request; 96 const uint8_t ddc_line = req->u.aux.ddc_line; 97 98 if (ddc_line >= ARRAY_SIZE(adev->dm.fused_io)) { 99 ASSERT(false); 100 return; 101 } 102 103 struct fused_io_sync *sync = &adev->dm.fused_io[ddc_line]; 104 105 static_assert(sizeof(*req) <= sizeof(sync->reply_data), "Size mismatch"); 106 memcpy(sync->reply_data, req, sizeof(*req)); 107 complete(&sync->replied); 108 } 109 EXPORT_IF_KUNIT(dm_dmub_aux_fused_io_callback); 110 111 /** 112 * dm_register_dmub_notify_callback - Sets callback for DMUB notify 113 * @adev: amdgpu_device pointer 114 * @type: Type of dmub notification 115 * @callback: Dmub interrupt callback function 116 * @dmub_int_thread_offload: offload indicator 117 * 118 * API to register a dmub callback handler for a dmub notification 119 * Also sets indicator whether callback processing to be offloaded. 120 * to dmub interrupt handling thread 121 * Return: true if successfully registered, false if there is existing registration 122 */ 123 bool dm_register_dmub_notify_callback(struct amdgpu_device *adev, 124 enum dmub_notification_type type, 125 dmub_notify_interrupt_callback_t callback, 126 bool dmub_int_thread_offload) 127 { 128 if (!callback || type >= ARRAY_SIZE(adev->dm.dmub_thread_offload)) 129 return false; 130 131 adev->dm.dmub_callback[type] = callback; 132 adev->dm.dmub_thread_offload[type] = dmub_int_thread_offload; 133 134 return true; 135 } 136 EXPORT_IF_KUNIT(dm_register_dmub_notify_callback); 137 138 int dm_dmub_hw_init(struct amdgpu_device *adev) 139 { 140 const struct dmcub_firmware_header_v1_0 *hdr; 141 struct dmub_srv *dmub_srv = adev->dm.dmub_srv; 142 struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info; 143 const struct firmware *dmub_fw = adev->dm.dmub_fw; 144 struct dc *dc = adev->dm.dc; 145 struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu; 146 struct abm *abm = adev->dm.dc->res_pool->abm; 147 struct dc_context *ctx = adev->dm.dc->ctx; 148 struct dmub_srv_hw_params hw_params; 149 enum dmub_status status; 150 const unsigned char *fw_inst_const, *fw_bss_data; 151 u32 fw_inst_const_size, fw_bss_data_size; 152 bool has_hw_support; 153 154 if (!dmub_srv) 155 /* DMUB isn't supported on the ASIC. */ 156 return 0; 157 158 if (!fb_info) { 159 drm_err(adev_to_drm(adev), "No framebuffer info for DMUB service.\n"); 160 return -EINVAL; 161 } 162 163 if (!dmub_fw) { 164 /* Firmware required for DMUB support. */ 165 drm_err(adev_to_drm(adev), "No firmware provided for DMUB.\n"); 166 return -EINVAL; 167 } 168 169 /* initialize register offsets for ASICs with runtime initialization available */ 170 if (dmub_srv->hw_funcs.init_reg_offsets) 171 dmub_srv->hw_funcs.init_reg_offsets(dmub_srv, ctx); 172 173 status = dmub_srv_has_hw_support(dmub_srv, &has_hw_support); 174 if (status != DMUB_STATUS_OK) { 175 drm_err(adev_to_drm(adev), "Error checking HW support for DMUB: %d\n", status); 176 return -EINVAL; 177 } 178 179 if (!has_hw_support) { 180 drm_info(adev_to_drm(adev), "DMUB unsupported on ASIC\n"); 181 return 0; 182 } 183 184 /* Reset DMCUB if it was previously running - before we overwrite its memory. */ 185 status = dmub_srv_hw_reset(dmub_srv); 186 if (status != DMUB_STATUS_OK) 187 drm_warn(adev_to_drm(adev), "Error resetting DMUB HW: %d\n", status); 188 189 hdr = (const struct dmcub_firmware_header_v1_0 *)dmub_fw->data; 190 191 fw_inst_const = dmub_fw->data + 192 le32_to_cpu(hdr->header.ucode_array_offset_bytes) + 193 PSP_HEADER_BYTES_256; 194 195 fw_bss_data = dmub_fw->data + 196 le32_to_cpu(hdr->header.ucode_array_offset_bytes) + 197 le32_to_cpu(hdr->inst_const_bytes); 198 199 /* Copy firmware and bios info into FB memory. */ 200 fw_inst_const_size = adev->dm.fw_inst_size; 201 202 fw_bss_data_size = le32_to_cpu(hdr->bss_data_bytes); 203 204 /* if adev->firmware.load_type == AMDGPU_FW_LOAD_PSP, 205 * amdgpu_ucode_init_single_fw will load dmub firmware 206 * fw_inst_const part to cw0; otherwise, the firmware back door load 207 * will be done by dm_dmub_hw_init 208 */ 209 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { 210 memcpy(fb_info->fb[DMUB_WINDOW_0_INST_CONST].cpu_addr, fw_inst_const, 211 fw_inst_const_size); 212 } 213 214 if (fw_bss_data_size) 215 memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr, 216 fw_bss_data, fw_bss_data_size); 217 218 /* Copy firmware bios info into FB memory. */ 219 memcpy(fb_info->fb[DMUB_WINDOW_3_VBIOS].cpu_addr, adev->bios, 220 adev->bios_size); 221 222 /* Reset regions that need to be reset. */ 223 memset(fb_info->fb[DMUB_WINDOW_4_MAILBOX].cpu_addr, 0, 224 fb_info->fb[DMUB_WINDOW_4_MAILBOX].size); 225 226 memset(fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].cpu_addr, 0, 227 fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size); 228 229 memset(fb_info->fb[DMUB_WINDOW_6_FW_STATE].cpu_addr, 0, 230 fb_info->fb[DMUB_WINDOW_6_FW_STATE].size); 231 232 memset(fb_info->fb[DMUB_WINDOW_SHARED_STATE].cpu_addr, 0, 233 fb_info->fb[DMUB_WINDOW_SHARED_STATE].size); 234 235 /* Initialize hardware. */ 236 memset(&hw_params, 0, sizeof(hw_params)); 237 hw_params.soc_fb_info.fb_base = adev->gmc.fb_start; 238 hw_params.soc_fb_info.fb_offset = adev->vm_manager.vram_base_offset; 239 240 /* backdoor load firmware and trigger dmub running */ 241 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) 242 hw_params.load_inst_const = true; 243 244 if (dmcu) 245 hw_params.psp_version = dmcu->psp_version; 246 247 hw_params.fb_info = fb_info; 248 249 /* Enable usb4 dpia in the FW APU */ 250 if (dc->caps.is_apu && 251 dc->res_pool->usb4_dpia_count != 0 && 252 !dc->debug.dpia_debug.bits.disable_dpia) { 253 hw_params.dpia_supported = true; 254 hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia; 255 hw_params.dpia_hpd_int_enable_supported = false; 256 hw_params.enable_non_transparent_setconfig = dc->config.consolidated_dpia_dp_lt; 257 hw_params.disable_dpia_bw_allocation = !dc->config.usb4_bw_alloc_support; 258 } 259 260 switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { 261 case IP_VERSION(3, 5, 0): 262 case IP_VERSION(3, 5, 1): 263 case IP_VERSION(3, 6, 0): 264 case IP_VERSION(4, 2, 0): 265 case IP_VERSION(4, 2, 1): 266 hw_params.ips_sequential_ono = adev->external_rev_id > 0x10; 267 hw_params.lower_hbr3_phy_ssc = true; 268 break; 269 default: 270 break; 271 } 272 273 status = dmub_srv_hw_init(dmub_srv, &hw_params); 274 if (status != DMUB_STATUS_OK) { 275 drm_err(adev_to_drm(adev), "Error initializing DMUB HW: %d\n", status); 276 return -EINVAL; 277 } 278 279 /* Wait for firmware load to finish. */ 280 status = dmub_srv_wait_for_auto_load(dmub_srv, 100000); 281 if (status != DMUB_STATUS_OK) 282 drm_warn(adev_to_drm(adev), "Wait for DMUB auto-load failed: %d\n", status); 283 284 /* Init DMCU and ABM if available. */ 285 if (dmcu && abm) { 286 dmcu->funcs->dmcu_init(dmcu); 287 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); 288 } 289 290 if (!adev->dm.dc->ctx->dmub_srv) 291 adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv); 292 if (!adev->dm.dc->ctx->dmub_srv) { 293 drm_err(adev_to_drm(adev), "Couldn't allocate DC DMUB server!\n"); 294 return -ENOMEM; 295 } 296 297 drm_info(adev_to_drm(adev), "DMUB hardware initialized: version=0x%08X\n", 298 adev->dm.dmcub_fw_version); 299 300 /* Keeping sanity checks off if 301 * DCN31 >= 4.0.59.0 302 * DCN314 >= 8.0.16.0 303 * Otherwise, turn on sanity checks 304 */ 305 switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { 306 case IP_VERSION(3, 1, 2): 307 case IP_VERSION(3, 1, 3): 308 if (adev->dm.dmcub_fw_version && 309 adev->dm.dmcub_fw_version >= DMUB_FW_VERSION(4, 0, 0) && 310 adev->dm.dmcub_fw_version < DMUB_FW_VERSION(4, 0, 59)) 311 adev->dm.dc->debug.sanity_checks = true; 312 break; 313 case IP_VERSION(3, 1, 4): 314 if (adev->dm.dmcub_fw_version && 315 adev->dm.dmcub_fw_version >= DMUB_FW_VERSION(4, 0, 0) && 316 adev->dm.dmcub_fw_version < DMUB_FW_VERSION(8, 0, 16)) 317 adev->dm.dc->debug.sanity_checks = true; 318 break; 319 default: 320 break; 321 } 322 323 return 0; 324 } 325 EXPORT_IF_KUNIT(dm_dmub_hw_init); 326 327 void dm_dmub_hw_resume(struct amdgpu_device *adev) 328 { 329 struct dmub_srv *dmub_srv = adev->dm.dmub_srv; 330 enum dmub_status status; 331 bool init; 332 int r; 333 334 if (!dmub_srv) { 335 /* DMUB isn't supported on the ASIC. */ 336 return; 337 } 338 339 status = dmub_srv_is_hw_init(dmub_srv, &init); 340 if (status != DMUB_STATUS_OK) 341 drm_warn(adev_to_drm(adev), "DMUB hardware init check failed: %d\n", status); 342 343 if (status == DMUB_STATUS_OK && init) { 344 /* Wait for firmware load to finish. */ 345 status = dmub_srv_wait_for_auto_load(dmub_srv, 100000); 346 if (status != DMUB_STATUS_OK) 347 drm_warn(adev_to_drm(adev), "Wait for DMUB auto-load failed: %d\n", status); 348 } else { 349 /* Perform the full hardware initialization. */ 350 r = dm_dmub_hw_init(adev); 351 if (r) 352 drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r); 353 } 354 } 355 EXPORT_IF_KUNIT(dm_dmub_hw_resume); 356 357 static enum dmub_status 358 dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev, 359 enum dmub_gpint_command command_code, 360 uint16_t param, 361 uint32_t timeout_us) 362 { 363 union dmub_gpint_data_register reg, test; 364 uint32_t i; 365 366 /* Assume that VBIOS DMUB is ready to take commands */ 367 368 reg.bits.status = 1; 369 reg.bits.command_code = command_code; 370 reg.bits.param = param; 371 372 cgs_write_register(adev->dm.cgs_device, 0x34c0 + 0x01f8, reg.all); 373 374 for (i = 0; i < timeout_us; ++i) { 375 udelay(1); 376 377 /* Check if our GPINT got acked */ 378 reg.bits.status = 0; 379 test = (union dmub_gpint_data_register) 380 cgs_read_register(adev->dm.cgs_device, 0x34c0 + 0x01f8); 381 382 if (test.all == reg.all) 383 return DMUB_STATUS_OK; 384 } 385 386 return DMUB_STATUS_TIMEOUT; 387 } 388 389 STATIC_IFN_KUNIT void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev) 390 { 391 void *bb; 392 long long addr; 393 unsigned int bb_size; 394 int i = 0; 395 uint16_t chunk; 396 enum dmub_gpint_command send_addrs[] = { 397 DMUB_GPINT__SET_BB_ADDR_WORD0, 398 DMUB_GPINT__SET_BB_ADDR_WORD1, 399 DMUB_GPINT__SET_BB_ADDR_WORD2, 400 DMUB_GPINT__SET_BB_ADDR_WORD3, 401 }; 402 enum dmub_status ret; 403 404 switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { 405 case IP_VERSION(4, 0, 1): 406 bb_size = sizeof(struct dml2_soc_bb); 407 break; 408 case IP_VERSION(4, 2, 0): 409 case IP_VERSION(4, 2, 1): 410 bb_size = sizeof(struct dml2_soc_bb); 411 break; 412 case IP_VERSION(6, 0, 0): 413 bb_size = sizeof(struct dmub_soc_bb_params); 414 break; 415 default: 416 return NULL; 417 } 418 419 bb = dm_allocate_gpu_mem(adev, 420 DC_MEM_ALLOC_TYPE_GART, 421 bb_size, 422 &addr); 423 if (!bb) 424 return NULL; 425 426 for (i = 0; i < 4; i++) { 427 /* Extract 16-bit chunk */ 428 chunk = ((uint64_t) addr >> (i * 16)) & 0xFFFF; 429 /* Send the chunk */ 430 ret = dm_dmub_send_vbios_gpint_command(adev, send_addrs[i], chunk, 30000); 431 if (ret != DMUB_STATUS_OK) 432 goto free_bb; 433 } 434 435 /* Now ask DMUB to copy the bb */ 436 ret = dm_dmub_send_vbios_gpint_command(adev, DMUB_GPINT__BB_COPY, 1, 200000); 437 if (ret != DMUB_STATUS_OK) 438 goto free_bb; 439 440 return bb; 441 442 free_bb: 443 dm_free_gpu_mem(adev, DC_MEM_ALLOC_TYPE_GART, (void *) bb); 444 return NULL; 445 446 } 447 EXPORT_IF_KUNIT(dm_dmub_get_vbios_bounding_box); 448 449 enum dmub_ips_disable_type dm_get_default_ips_mode( 450 struct amdgpu_device *adev) 451 { 452 enum dmub_ips_disable_type ret = DMUB_IPS_ENABLE; 453 454 switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { 455 case IP_VERSION(3, 5, 0): 456 case IP_VERSION(3, 6, 0): 457 case IP_VERSION(3, 5, 1): 458 ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; 459 break; 460 default: 461 /* ASICs older than DCN35 do not have IPSs */ 462 if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0)) 463 ret = DMUB_IPS_DISABLE_ALL; 464 break; 465 } 466 467 return ret; 468 } 469 EXPORT_IF_KUNIT(dm_get_default_ips_mode); 470 471 static uint32_t amdgpu_dm_dmub_reg_read(void *ctx, uint32_t address) 472 { 473 struct amdgpu_device *adev = ctx; 474 475 return dm_read_reg(adev->dm.dc->ctx, address); 476 } 477 478 static void amdgpu_dm_dmub_reg_write(void *ctx, uint32_t address, 479 uint32_t value) 480 { 481 struct amdgpu_device *adev = ctx; 482 483 return dm_write_reg(adev->dm.dc->ctx, address, value); 484 } 485 486 int dm_dmub_sw_init(struct amdgpu_device *adev) 487 { 488 struct dmub_srv_create_params create_params; 489 struct dmub_srv_fw_meta_info_params fw_meta_info_params; 490 struct dmub_srv_region_params region_params; 491 struct dmub_srv_region_info region_info; 492 struct dmub_srv_memory_params memory_params; 493 struct dmub_fw_meta_info fw_info; 494 struct dmub_srv_fb_info *fb_info; 495 struct dmub_srv *dmub_srv; 496 const struct dmcub_firmware_header_v1_0 *hdr; 497 enum dmub_asic dmub_asic; 498 enum dmub_status status; 499 static enum dmub_window_memory_type window_memory_type[DMUB_WINDOW_TOTAL] = { 500 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_0_INST_CONST */ 501 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_1_STACK */ 502 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_2_BSS_DATA */ 503 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_3_VBIOS */ 504 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_4_MAILBOX */ 505 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_5_TRACEBUFF */ 506 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_6_FW_STATE */ 507 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_7_SCRATCH_MEM */ 508 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_IB_MEM */ 509 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_SHARED_STATE */ 510 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_LSDMA_BUFFER */ 511 DMUB_WINDOW_MEMORY_TYPE_FB, /* DMUB_WINDOW_CURSOR_OFFLOAD */ 512 }; 513 int r; 514 int mem_domain = AMDGPU_GEM_DOMAIN_GTT; 515 516 switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { 517 case IP_VERSION(2, 1, 0): 518 dmub_asic = DMUB_ASIC_DCN21; 519 break; 520 case IP_VERSION(3, 0, 0): 521 dmub_asic = DMUB_ASIC_DCN30; 522 break; 523 case IP_VERSION(3, 0, 1): 524 dmub_asic = DMUB_ASIC_DCN301; 525 break; 526 case IP_VERSION(3, 0, 2): 527 dmub_asic = DMUB_ASIC_DCN302; 528 break; 529 case IP_VERSION(3, 0, 3): 530 dmub_asic = DMUB_ASIC_DCN303; 531 break; 532 case IP_VERSION(3, 1, 2): 533 case IP_VERSION(3, 1, 3): 534 dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31; 535 break; 536 case IP_VERSION(3, 1, 4): 537 dmub_asic = DMUB_ASIC_DCN314; 538 break; 539 case IP_VERSION(3, 1, 5): 540 dmub_asic = DMUB_ASIC_DCN315; 541 break; 542 case IP_VERSION(3, 1, 6): 543 dmub_asic = DMUB_ASIC_DCN316; 544 break; 545 case IP_VERSION(3, 2, 0): 546 dmub_asic = DMUB_ASIC_DCN32; 547 break; 548 case IP_VERSION(3, 2, 1): 549 dmub_asic = DMUB_ASIC_DCN321; 550 break; 551 case IP_VERSION(3, 5, 0): 552 case IP_VERSION(3, 5, 1): 553 dmub_asic = DMUB_ASIC_DCN35; 554 break; 555 case IP_VERSION(3, 6, 0): 556 dmub_asic = DMUB_ASIC_DCN36; 557 break; 558 case IP_VERSION(4, 0, 1): 559 dmub_asic = DMUB_ASIC_DCN401; 560 break; 561 case IP_VERSION(4, 2, 0): 562 dmub_asic = DMUB_ASIC_DCN42; 563 break; 564 case IP_VERSION(4, 2, 1): 565 dmub_asic = DMUB_ASIC_DCN42B; 566 break; 567 case IP_VERSION(6, 0, 0): 568 dmub_asic = DMUB_ASIC_DCN60; 569 break; 570 default: 571 /* ASIC doesn't support DMUB. */ 572 return 0; 573 } 574 575 hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data; 576 adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version); 577 578 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 579 adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id = 580 AMDGPU_UCODE_ID_DMCUB; 581 adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].fw = 582 adev->dm.dmub_fw; 583 adev->firmware.fw_size += 584 ALIGN(le32_to_cpu(hdr->inst_const_bytes), PAGE_SIZE); 585 586 drm_info(adev_to_drm(adev), "Loading DMUB firmware via PSP: version=0x%08X\n", 587 adev->dm.dmcub_fw_version); 588 } 589 590 591 adev->dm.dmub_srv = kzalloc_obj(*adev->dm.dmub_srv); 592 dmub_srv = adev->dm.dmub_srv; 593 594 if (!dmub_srv) { 595 drm_err(adev_to_drm(adev), "Failed to allocate DMUB service!\n"); 596 return -ENOMEM; 597 } 598 599 memset(&create_params, 0, sizeof(create_params)); 600 create_params.user_ctx = adev; 601 create_params.funcs.reg_read = amdgpu_dm_dmub_reg_read; 602 create_params.funcs.reg_write = amdgpu_dm_dmub_reg_write; 603 create_params.asic = dmub_asic; 604 605 /* Create the DMUB service. */ 606 status = dmub_srv_create(dmub_srv, &create_params); 607 if (status != DMUB_STATUS_OK) { 608 drm_err(adev_to_drm(adev), "Error creating DMUB service: %d\n", status); 609 return -EINVAL; 610 } 611 612 /* Extract the FW meta info. */ 613 memset(&fw_meta_info_params, 0, sizeof(fw_meta_info_params)); 614 615 fw_meta_info_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) - 616 PSP_HEADER_BYTES_256; 617 fw_meta_info_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes); 618 fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data + 619 le32_to_cpu(hdr->header.ucode_array_offset_bytes) + 620 PSP_HEADER_BYTES_256; 621 fw_meta_info_params.fw_bss_data = fw_meta_info_params.bss_data_size ? adev->dm.dmub_fw->data + 622 le32_to_cpu(hdr->header.ucode_array_offset_bytes) + 623 le32_to_cpu(hdr->inst_const_bytes) : NULL; 624 fw_meta_info_params.custom_psp_footer_size = 0; 625 626 status = dmub_srv_get_fw_meta_info_from_raw_fw(&fw_meta_info_params, &fw_info); 627 if (status != DMUB_STATUS_OK) { 628 /* Skip returning early, just log the error. */ 629 drm_err(adev_to_drm(adev), "Error getting DMUB FW meta info: %d\n", status); 630 } 631 632 /* Calculate the size of all the regions for the DMUB service. */ 633 memset(®ion_params, 0, sizeof(region_params)); 634 635 region_params.inst_const_size = fw_meta_info_params.inst_const_size; 636 region_params.bss_data_size = fw_meta_info_params.bss_data_size; 637 region_params.vbios_size = adev->bios_size; 638 region_params.fw_bss_data = fw_meta_info_params.fw_bss_data; 639 region_params.fw_inst_const = fw_meta_info_params.fw_inst_const; 640 region_params.window_memory_type = window_memory_type; 641 region_params.fw_info = (status == DMUB_STATUS_OK) ? &fw_info : NULL; 642 643 status = dmub_srv_calc_region_info(dmub_srv, ®ion_params, 644 ®ion_info); 645 646 if (status != DMUB_STATUS_OK) { 647 drm_err(adev_to_drm(adev), "Error calculating DMUB region info: %d\n", status); 648 return -EINVAL; 649 } 650 651 /* Limit to allocate dmub to GTT on DCN32/1 652 * TODO: Other asics with GDDR7 may have worse latency 653 */ 654 if (dmub_asic != DMUB_ASIC_DCN32 && 655 dmub_asic != DMUB_ASIC_DCN321) 656 mem_domain |= AMDGPU_GEM_DOMAIN_VRAM; 657 658 /* 659 * Allocate a framebuffer based on the total size of all the regions. 660 * TODO: Move this into GART. 661 */ 662 r = amdgpu_bo_create_kernel(adev, region_info.fb_size, PAGE_SIZE, 663 mem_domain, 664 &adev->dm.dmub_bo, 665 &adev->dm.dmub_bo_gpu_addr, 666 &adev->dm.dmub_bo_cpu_addr); 667 if (r) 668 return r; 669 670 /* Rebase the regions on the framebuffer address. */ 671 memset(&memory_params, 0, sizeof(memory_params)); 672 memory_params.cpu_fb_addr = adev->dm.dmub_bo_cpu_addr; 673 memory_params.gpu_fb_addr = adev->dm.dmub_bo_gpu_addr; 674 memory_params.region_info = ®ion_info; 675 memory_params.window_memory_type = window_memory_type; 676 677 adev->dm.dmub_fb_info = kzalloc_obj(*adev->dm.dmub_fb_info); 678 fb_info = adev->dm.dmub_fb_info; 679 680 if (!fb_info) { 681 drm_err(adev_to_drm(adev), 682 "Failed to allocate framebuffer info for DMUB service!\n"); 683 return -ENOMEM; 684 } 685 686 status = dmub_srv_calc_mem_info(dmub_srv, &memory_params, fb_info); 687 if (status != DMUB_STATUS_OK) { 688 drm_err(adev_to_drm(adev), "Error calculating DMUB FB info: %d\n", status); 689 return -EINVAL; 690 } 691 692 adev->dm.bb_from_dmub = dm_dmub_get_vbios_bounding_box(adev); 693 adev->dm.fw_inst_size = fw_meta_info_params.inst_const_size; 694 695 return 0; 696 } 697 EXPORT_IF_KUNIT(dm_dmub_sw_init); 698 699 int dm_init_microcode(struct amdgpu_device *adev) 700 { 701 char *fw_name_dmub; 702 int r; 703 704 switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { 705 case IP_VERSION(2, 1, 0): 706 fw_name_dmub = FIRMWARE_RENOIR_DMUB; 707 if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id)) 708 fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB; 709 break; 710 case IP_VERSION(3, 0, 0): 711 if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 0)) 712 fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB; 713 else 714 fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB; 715 break; 716 case IP_VERSION(3, 0, 1): 717 fw_name_dmub = FIRMWARE_VANGOGH_DMUB; 718 break; 719 case IP_VERSION(3, 0, 2): 720 fw_name_dmub = FIRMWARE_DIMGREY_CAVEFISH_DMUB; 721 break; 722 case IP_VERSION(3, 0, 3): 723 fw_name_dmub = FIRMWARE_BEIGE_GOBY_DMUB; 724 break; 725 case IP_VERSION(3, 1, 2): 726 case IP_VERSION(3, 1, 3): 727 fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB; 728 break; 729 case IP_VERSION(3, 1, 4): 730 fw_name_dmub = FIRMWARE_DCN_314_DMUB; 731 break; 732 case IP_VERSION(3, 1, 5): 733 fw_name_dmub = FIRMWARE_DCN_315_DMUB; 734 break; 735 case IP_VERSION(3, 1, 6): 736 fw_name_dmub = FIRMWARE_DCN316_DMUB; 737 break; 738 case IP_VERSION(3, 2, 0): 739 fw_name_dmub = FIRMWARE_DCN_V3_2_0_DMCUB; 740 break; 741 case IP_VERSION(3, 2, 1): 742 fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB; 743 break; 744 case IP_VERSION(3, 5, 0): 745 fw_name_dmub = FIRMWARE_DCN_35_DMUB; 746 break; 747 case IP_VERSION(3, 5, 1): 748 fw_name_dmub = FIRMWARE_DCN_351_DMUB; 749 break; 750 case IP_VERSION(3, 6, 0): 751 fw_name_dmub = FIRMWARE_DCN_36_DMUB; 752 break; 753 case IP_VERSION(4, 0, 1): 754 fw_name_dmub = FIRMWARE_DCN_401_DMUB; 755 break; 756 case IP_VERSION(4, 2, 0): 757 fw_name_dmub = FIRMWARE_DCN_42_DMUB; 758 break; 759 case IP_VERSION(4, 2, 1): 760 fw_name_dmub = FIRMWARE_DCN_42B_DMUB; 761 break; 762 case IP_VERSION(6, 0, 0): 763 fw_name_dmub = FIRMWARE_DCN_60_DMUB; 764 break; 765 default: 766 /* ASIC doesn't support DMUB. */ 767 return 0; 768 } 769 r = amdgpu_ucode_request(adev, &adev->dm.dmub_fw, AMDGPU_UCODE_REQUIRED, 770 "%s", fw_name_dmub); 771 return r; 772 } 773 EXPORT_IF_KUNIT(dm_init_microcode); 774 775 int amdgpu_dm_process_dmub_aux_transfer_sync( 776 struct dc_context *ctx, 777 unsigned int link_index, 778 struct aux_payload *payload, 779 enum aux_return_code_type *operation_result) 780 { 781 struct amdgpu_device *adev = ctx->driver_context; 782 struct dmub_notification *p_notify = adev->dm.dmub_notify; 783 int ret = -1; 784 785 mutex_lock(&adev->dm.dpia_aux_lock); 786 if (!dc_process_dmub_aux_transfer_async(ctx->dc, link_index, payload)) { 787 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 788 goto out; 789 } 790 791 if (!wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) { 792 drm_err(adev_to_drm(adev), "wait_for_completion_timeout timeout!"); 793 *operation_result = AUX_RET_ERROR_TIMEOUT; 794 goto out; 795 } 796 797 if (p_notify->result != AUX_RET_SUCCESS) { 798 /* 799 * Transient states before tunneling is enabled could 800 * lead to this error. We can ignore this for now. 801 */ 802 if (p_notify->result == AUX_RET_ERROR_PROTOCOL_ERROR) { 803 drm_warn(adev_to_drm(adev), "DPIA AUX failed on 0x%x(%d), error %d\n", 804 payload->address, payload->length, 805 p_notify->result); 806 } 807 *operation_result = p_notify->result; 808 goto out; 809 } 810 811 payload->reply[0] = adev->dm.dmub_notify->aux_reply.command & 0xF; 812 if (adev->dm.dmub_notify->aux_reply.command & 0xF0) 813 /* The reply is stored in the top nibble of the command. */ 814 payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF; 815 816 /*write req may receive a byte indicating partially written number as well*/ 817 if (p_notify->aux_reply.length && payload->data) { 818 /* Bound the reply to the scratch buffer it was read into. */ 819 ret = min_t(uint32_t, p_notify->aux_reply.length, 820 sizeof(p_notify->aux_reply.data)); 821 822 /* 823 * During a write-status-update retry the caller zeroes 824 * payload->length while still expecting the partial-write 825 * status byte in payload->data (see dce_aux_transfer_with_retries), 826 * so only clamp to payload->length for regular transfers. 827 */ 828 if (!payload->write_status_update) 829 ret = min_t(int, ret, payload->length); 830 831 memcpy(payload->data, p_notify->aux_reply.data, ret); 832 } else { 833 /* success */ 834 ret = p_notify->aux_reply.length; 835 } 836 837 *operation_result = p_notify->result; 838 out: 839 reinit_completion(&adev->dm.dmub_aux_transfer_done); 840 mutex_unlock(&adev->dm.dpia_aux_lock); 841 return ret; 842 } 843 EXPORT_IF_KUNIT(amdgpu_dm_process_dmub_aux_transfer_sync); 844 845 STATIC_IFN_KUNIT void abort_fused_io( 846 struct dc_context *ctx, 847 const struct dmub_cmd_fused_request *request 848 ) 849 { 850 union dmub_rb_cmd command = { 0 }; 851 struct dmub_rb_cmd_fused_io *io = &command.fused_io; 852 853 io->header.type = DMUB_CMD__FUSED_IO; 854 io->header.sub_type = DMUB_CMD__FUSED_IO_ABORT; 855 io->header.payload_bytes = sizeof(*io) - sizeof(io->header); 856 io->request = *request; 857 dm_execute_dmub_cmd(ctx, &command, DM_DMUB_WAIT_TYPE_NO_WAIT); 858 } 859 EXPORT_IF_KUNIT(abort_fused_io); 860 861 static bool execute_fused_io( 862 struct amdgpu_device *dev, 863 struct dc_context *ctx, 864 union dmub_rb_cmd *commands, 865 uint8_t count, 866 uint32_t timeout_us 867 ) 868 { 869 const uint8_t ddc_line = commands[0].fused_io.request.u.aux.ddc_line; 870 871 if (ddc_line >= ARRAY_SIZE(dev->dm.fused_io)) 872 return false; 873 874 struct fused_io_sync *sync = &dev->dm.fused_io[ddc_line]; 875 struct dmub_rb_cmd_fused_io *first = &commands[0].fused_io; 876 const bool result = dm_execute_dmub_cmd_list(ctx, count, commands, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) 877 && first->header.ret_status 878 && first->request.status == FUSED_REQUEST_STATUS_SUCCESS; 879 880 if (!result) 881 return false; 882 883 while (wait_for_completion_timeout(&sync->replied, usecs_to_jiffies(timeout_us))) { 884 reinit_completion(&sync->replied); 885 886 struct dmub_cmd_fused_request *reply = (struct dmub_cmd_fused_request *) sync->reply_data; 887 888 static_assert(sizeof(*reply) <= sizeof(sync->reply_data), "Size mismatch"); 889 890 if (reply->identifier == first->request.identifier) { 891 first->request = *reply; 892 return true; 893 } 894 } 895 896 reinit_completion(&sync->replied); 897 first->request.status = FUSED_REQUEST_STATUS_TIMEOUT; 898 abort_fused_io(ctx, &first->request); 899 return false; 900 } 901 902 bool amdgpu_dm_execute_fused_io( 903 struct amdgpu_device *dev, 904 struct dc_link *link, 905 union dmub_rb_cmd *commands, 906 uint8_t count, 907 uint32_t timeout_us) 908 { 909 struct amdgpu_display_manager *dm = &dev->dm; 910 911 mutex_lock(&dm->dpia_aux_lock); 912 913 const bool result = execute_fused_io(dev, link->ctx, commands, count, timeout_us); 914 915 mutex_unlock(&dm->dpia_aux_lock); 916 return result; 917 } 918 919 int amdgpu_dm_process_dmub_set_config_sync( 920 struct dc_context *ctx, 921 unsigned int link_index, 922 struct set_config_cmd_payload *payload, 923 enum set_config_status *operation_result) 924 { 925 struct amdgpu_device *adev = ctx->driver_context; 926 bool is_cmd_complete; 927 int ret; 928 929 mutex_lock(&adev->dm.dpia_aux_lock); 930 is_cmd_complete = dc_process_dmub_set_config_async(ctx->dc, 931 link_index, payload, adev->dm.dmub_notify); 932 933 if (is_cmd_complete || wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) { 934 ret = 0; 935 *operation_result = adev->dm.dmub_notify->sc_status; 936 } else { 937 drm_err(adev_to_drm(adev), "wait_for_completion_timeout timeout!"); 938 ret = -1; 939 *operation_result = SET_CONFIG_UNKNOWN_ERROR; 940 } 941 942 if (!is_cmd_complete) 943 reinit_completion(&adev->dm.dmub_aux_transfer_done); 944 mutex_unlock(&adev->dm.dpia_aux_lock); 945 return ret; 946 } 947 EXPORT_IF_KUNIT(amdgpu_dm_process_dmub_set_config_sync); 948 949 bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type) 950 { 951 struct amdgpu_device *adev = ctx->driver_context; 952 953 guard(spinlock_irqsave)(&adev->dm.dmub_lock); 954 return dc_dmub_srv_cmd_run(ctx->dmub_srv, cmd, wait_type); 955 } 956 EXPORT_IF_KUNIT(dm_execute_dmub_cmd); 957 958 bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type) 959 { 960 struct amdgpu_device *adev = ctx->driver_context; 961 962 guard(spinlock_irqsave)(&adev->dm.dmub_lock); 963 return dc_dmub_srv_cmd_run_list(ctx->dmub_srv, count, cmd, wait_type); 964 } 965