xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
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 = &notify->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(&region_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, &region_params,
644 					   &region_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 = &region_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