brintos

brintos / linux-shallow public Read only

0
0
Text · 36.4 KiB · db16066 Raw
1204 lines · c
1/*2 * Copyright 2019 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "../dmub_srv.h"27#include "dmub_dcn20.h"28#include "dmub_dcn21.h"29#include "dmub_cmd.h"30#include "dmub_dcn30.h"31#include "dmub_dcn301.h"32#include "dmub_dcn302.h"33#include "dmub_dcn303.h"34#include "dmub_dcn31.h"35#include "dmub_dcn314.h"36#include "dmub_dcn315.h"37#include "dmub_dcn316.h"38#include "dmub_dcn32.h"39#include "dmub_dcn35.h"40#include "dmub_dcn351.h"41#include "dmub_dcn401.h"42#include "os_types.h"43/*44 * Note: the DMUB service is standalone. No additional headers should be45 * added below or above this line unless they reside within the DMUB46 * folder.47 */48 49/* Alignment for framebuffer memory. */50#define DMUB_FB_ALIGNMENT (1024 * 1024)51 52/* Stack size. */53#define DMUB_STACK_SIZE (128 * 1024)54 55/* Context size. */56#define DMUB_CONTEXT_SIZE (512 * 1024)57 58/* Mailbox size : Ring buffers are required for both inbox and outbox */59#define DMUB_MAILBOX_SIZE ((2 * DMUB_RB_SIZE))60 61/* Default state size if meta is absent. */62#define DMUB_FW_STATE_SIZE (64 * 1024)63 64/* Default tracebuffer size if meta is absent. */65#define DMUB_TRACE_BUFFER_SIZE (64 * 1024)66 67 68/* Default scratch mem size. */69#define DMUB_SCRATCH_MEM_SIZE (1024)70 71/* Number of windows in use. */72#define DMUB_NUM_WINDOWS (DMUB_WINDOW_TOTAL)73/* Base addresses. */74 75#define DMUB_CW0_BASE (0x60000000)76#define DMUB_CW1_BASE (0x61000000)77#define DMUB_CW3_BASE (0x63000000)78#define DMUB_CW4_BASE (0x64000000)79#define DMUB_CW5_BASE (0x65000000)80#define DMUB_CW6_BASE (0x66000000)81 82#define DMUB_REGION5_BASE (0xA0000000)83#define DMUB_REGION6_BASE (0xC0000000)84 85static struct dmub_srv_dcn32_regs dmub_srv_dcn32_regs;86static struct dmub_srv_dcn35_regs dmub_srv_dcn35_regs;87 88static inline uint32_t dmub_align(uint32_t val, uint32_t factor)89{90	return (val + factor - 1) / factor * factor;91}92 93void dmub_flush_buffer_mem(const struct dmub_fb *fb)94{95	const uint8_t *base = (const uint8_t *)fb->cpu_addr;96	uint8_t buf[64];97	uint32_t pos, end;98 99	/**100	 * Read 64-byte chunks since we don't want to store a101	 * large temporary buffer for this purpose.102	 */103	end = fb->size / sizeof(buf) * sizeof(buf);104 105	for (pos = 0; pos < end; pos += sizeof(buf))106		dmub_memcpy(buf, base + pos, sizeof(buf));107 108	/* Read anything leftover into the buffer. */109	if (end < fb->size)110		dmub_memcpy(buf, base + pos, fb->size - end);111}112 113static const struct dmub_fw_meta_info *114dmub_get_fw_meta_info_from_blob(const uint8_t *blob, uint32_t blob_size, uint32_t meta_offset)115{116	const union dmub_fw_meta *meta;117 118	if (!blob || !blob_size)119		return NULL;120 121	if (blob_size < sizeof(union dmub_fw_meta) + meta_offset)122		return NULL;123 124	meta = (const union dmub_fw_meta *)(blob + blob_size - meta_offset -125					    sizeof(union dmub_fw_meta));126 127	if (meta->info.magic_value != DMUB_FW_META_MAGIC)128		return NULL;129 130	return &meta->info;131}132 133static const struct dmub_fw_meta_info *134dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)135{136	const struct dmub_fw_meta_info *info = NULL;137 138	if (params->fw_bss_data && params->bss_data_size) {139		/* Legacy metadata region. */140		info = dmub_get_fw_meta_info_from_blob(params->fw_bss_data,141						       params->bss_data_size,142						       DMUB_FW_META_OFFSET);143	} else if (params->fw_inst_const && params->inst_const_size) {144		/* Combined metadata region - can be aligned to 16-bytes. */145		uint32_t i;146 147		for (i = 0; i < 16; ++i) {148			info = dmub_get_fw_meta_info_from_blob(149				params->fw_inst_const, params->inst_const_size, i);150 151			if (info)152				break;153		}154	}155 156	return info;157}158 159static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)160{161	struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs;162 163	switch (asic) {164	case DMUB_ASIC_DCN20:165	case DMUB_ASIC_DCN21:166	case DMUB_ASIC_DCN30:167	case DMUB_ASIC_DCN301:168	case DMUB_ASIC_DCN302:169	case DMUB_ASIC_DCN303:170		dmub->regs = &dmub_srv_dcn20_regs;171 172		funcs->reset = dmub_dcn20_reset;173		funcs->reset_release = dmub_dcn20_reset_release;174		funcs->backdoor_load = dmub_dcn20_backdoor_load;175		funcs->setup_windows = dmub_dcn20_setup_windows;176		funcs->setup_mailbox = dmub_dcn20_setup_mailbox;177		funcs->get_inbox1_wptr = dmub_dcn20_get_inbox1_wptr;178		funcs->get_inbox1_rptr = dmub_dcn20_get_inbox1_rptr;179		funcs->set_inbox1_wptr = dmub_dcn20_set_inbox1_wptr;180		funcs->is_supported = dmub_dcn20_is_supported;181		funcs->is_hw_init = dmub_dcn20_is_hw_init;182		funcs->set_gpint = dmub_dcn20_set_gpint;183		funcs->is_gpint_acked = dmub_dcn20_is_gpint_acked;184		funcs->get_gpint_response = dmub_dcn20_get_gpint_response;185		funcs->get_fw_status = dmub_dcn20_get_fw_boot_status;186		funcs->enable_dmub_boot_options = dmub_dcn20_enable_dmub_boot_options;187		funcs->skip_dmub_panel_power_sequence = dmub_dcn20_skip_dmub_panel_power_sequence;188		funcs->get_current_time = dmub_dcn20_get_current_time;189 190		// Out mailbox register access functions for RN and above191		funcs->setup_out_mailbox = dmub_dcn20_setup_out_mailbox;192		funcs->get_outbox1_wptr = dmub_dcn20_get_outbox1_wptr;193		funcs->set_outbox1_rptr = dmub_dcn20_set_outbox1_rptr;194 195		//outbox0 call stacks196		funcs->setup_outbox0 = dmub_dcn20_setup_outbox0;197		funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr;198		funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr;199 200		funcs->get_diagnostic_data = dmub_dcn20_get_diagnostic_data;201 202		if (asic == DMUB_ASIC_DCN21)203			dmub->regs = &dmub_srv_dcn21_regs;204 205		if (asic == DMUB_ASIC_DCN30) {206			dmub->regs = &dmub_srv_dcn30_regs;207 208			funcs->backdoor_load = dmub_dcn30_backdoor_load;209			funcs->setup_windows = dmub_dcn30_setup_windows;210		}211		if (asic == DMUB_ASIC_DCN301) {212			dmub->regs = &dmub_srv_dcn301_regs;213 214			funcs->backdoor_load = dmub_dcn30_backdoor_load;215			funcs->setup_windows = dmub_dcn30_setup_windows;216		}217		if (asic == DMUB_ASIC_DCN302) {218			dmub->regs = &dmub_srv_dcn302_regs;219 220			funcs->backdoor_load = dmub_dcn30_backdoor_load;221			funcs->setup_windows = dmub_dcn30_setup_windows;222		}223		if (asic == DMUB_ASIC_DCN303) {224			dmub->regs = &dmub_srv_dcn303_regs;225 226			funcs->backdoor_load = dmub_dcn30_backdoor_load;227			funcs->setup_windows = dmub_dcn30_setup_windows;228		}229		break;230 231	case DMUB_ASIC_DCN31:232	case DMUB_ASIC_DCN31B:233	case DMUB_ASIC_DCN314:234	case DMUB_ASIC_DCN315:235	case DMUB_ASIC_DCN316:236		if (asic == DMUB_ASIC_DCN314) {237			dmub->regs_dcn31 = &dmub_srv_dcn314_regs;238			funcs->is_psrsu_supported = dmub_dcn314_is_psrsu_supported;239		} else if (asic == DMUB_ASIC_DCN315) {240			dmub->regs_dcn31 = &dmub_srv_dcn315_regs;241		} else if (asic == DMUB_ASIC_DCN316) {242			dmub->regs_dcn31 = &dmub_srv_dcn316_regs;243		} else {244			dmub->regs_dcn31 = &dmub_srv_dcn31_regs;245			funcs->is_psrsu_supported = dmub_dcn31_is_psrsu_supported;246		}247		funcs->reset = dmub_dcn31_reset;248		funcs->reset_release = dmub_dcn31_reset_release;249		funcs->backdoor_load = dmub_dcn31_backdoor_load;250		funcs->setup_windows = dmub_dcn31_setup_windows;251		funcs->setup_mailbox = dmub_dcn31_setup_mailbox;252		funcs->get_inbox1_wptr = dmub_dcn31_get_inbox1_wptr;253		funcs->get_inbox1_rptr = dmub_dcn31_get_inbox1_rptr;254		funcs->set_inbox1_wptr = dmub_dcn31_set_inbox1_wptr;255		funcs->setup_out_mailbox = dmub_dcn31_setup_out_mailbox;256		funcs->get_outbox1_wptr = dmub_dcn31_get_outbox1_wptr;257		funcs->set_outbox1_rptr = dmub_dcn31_set_outbox1_rptr;258		funcs->is_supported = dmub_dcn31_is_supported;259		funcs->is_hw_init = dmub_dcn31_is_hw_init;260		funcs->set_gpint = dmub_dcn31_set_gpint;261		funcs->is_gpint_acked = dmub_dcn31_is_gpint_acked;262		funcs->get_gpint_response = dmub_dcn31_get_gpint_response;263		funcs->get_gpint_dataout = dmub_dcn31_get_gpint_dataout;264		funcs->get_fw_status = dmub_dcn31_get_fw_boot_status;265		funcs->get_fw_boot_option = dmub_dcn31_get_fw_boot_option;266		funcs->enable_dmub_boot_options = dmub_dcn31_enable_dmub_boot_options;267		funcs->skip_dmub_panel_power_sequence = dmub_dcn31_skip_dmub_panel_power_sequence;268		//outbox0 call stacks269		funcs->setup_outbox0 = dmub_dcn31_setup_outbox0;270		funcs->get_outbox0_wptr = dmub_dcn31_get_outbox0_wptr;271		funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr;272 273		funcs->get_diagnostic_data = dmub_dcn31_get_diagnostic_data;274		funcs->should_detect = dmub_dcn31_should_detect;275		funcs->get_current_time = dmub_dcn31_get_current_time;276 277		break;278 279	case DMUB_ASIC_DCN32:280	case DMUB_ASIC_DCN321:281		dmub->regs_dcn32 = &dmub_srv_dcn32_regs;282		funcs->configure_dmub_in_system_memory = dmub_dcn32_configure_dmub_in_system_memory;283		funcs->send_inbox0_cmd = dmub_dcn32_send_inbox0_cmd;284		funcs->clear_inbox0_ack_register = dmub_dcn32_clear_inbox0_ack_register;285		funcs->read_inbox0_ack_register = dmub_dcn32_read_inbox0_ack_register;286		funcs->subvp_save_surf_addr = dmub_dcn32_save_surf_addr;287		funcs->reset = dmub_dcn32_reset;288		funcs->reset_release = dmub_dcn32_reset_release;289		funcs->backdoor_load = dmub_dcn32_backdoor_load;290		funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode;291		funcs->setup_windows = dmub_dcn32_setup_windows;292		funcs->setup_mailbox = dmub_dcn32_setup_mailbox;293		funcs->get_inbox1_wptr = dmub_dcn32_get_inbox1_wptr;294		funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr;295		funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr;296		funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox;297		funcs->get_outbox1_wptr = dmub_dcn32_get_outbox1_wptr;298		funcs->set_outbox1_rptr = dmub_dcn32_set_outbox1_rptr;299		funcs->is_supported = dmub_dcn32_is_supported;300		funcs->is_hw_init = dmub_dcn32_is_hw_init;301		funcs->set_gpint = dmub_dcn32_set_gpint;302		funcs->is_gpint_acked = dmub_dcn32_is_gpint_acked;303		funcs->get_gpint_response = dmub_dcn32_get_gpint_response;304		funcs->get_gpint_dataout = dmub_dcn32_get_gpint_dataout;305		funcs->get_fw_status = dmub_dcn32_get_fw_boot_status;306		funcs->enable_dmub_boot_options = dmub_dcn32_enable_dmub_boot_options;307		funcs->skip_dmub_panel_power_sequence = dmub_dcn32_skip_dmub_panel_power_sequence;308 309		/* outbox0 call stacks */310		funcs->setup_outbox0 = dmub_dcn32_setup_outbox0;311		funcs->get_outbox0_wptr = dmub_dcn32_get_outbox0_wptr;312		funcs->set_outbox0_rptr = dmub_dcn32_set_outbox0_rptr;313		funcs->get_current_time = dmub_dcn32_get_current_time;314		funcs->get_diagnostic_data = dmub_dcn32_get_diagnostic_data;315		funcs->init_reg_offsets = dmub_srv_dcn32_regs_init;316 317		break;318 319	case DMUB_ASIC_DCN35:320	case DMUB_ASIC_DCN351:321			dmub->regs_dcn35 = &dmub_srv_dcn35_regs;322			funcs->configure_dmub_in_system_memory = dmub_dcn35_configure_dmub_in_system_memory;323			funcs->send_inbox0_cmd = dmub_dcn35_send_inbox0_cmd;324			funcs->clear_inbox0_ack_register = dmub_dcn35_clear_inbox0_ack_register;325			funcs->read_inbox0_ack_register = dmub_dcn35_read_inbox0_ack_register;326			funcs->reset = dmub_dcn35_reset;327			funcs->reset_release = dmub_dcn35_reset_release;328			funcs->backdoor_load = dmub_dcn35_backdoor_load;329			funcs->backdoor_load_zfb_mode = dmub_dcn35_backdoor_load_zfb_mode;330			funcs->setup_windows = dmub_dcn35_setup_windows;331			funcs->setup_mailbox = dmub_dcn35_setup_mailbox;332			funcs->get_inbox1_wptr = dmub_dcn35_get_inbox1_wptr;333			funcs->get_inbox1_rptr = dmub_dcn35_get_inbox1_rptr;334			funcs->set_inbox1_wptr = dmub_dcn35_set_inbox1_wptr;335			funcs->setup_out_mailbox = dmub_dcn35_setup_out_mailbox;336			funcs->get_outbox1_wptr = dmub_dcn35_get_outbox1_wptr;337			funcs->set_outbox1_rptr = dmub_dcn35_set_outbox1_rptr;338			funcs->is_supported = dmub_dcn35_is_supported;339			funcs->is_hw_init = dmub_dcn35_is_hw_init;340			funcs->set_gpint = dmub_dcn35_set_gpint;341			funcs->is_gpint_acked = dmub_dcn35_is_gpint_acked;342			funcs->get_gpint_response = dmub_dcn35_get_gpint_response;343			funcs->get_gpint_dataout = dmub_dcn35_get_gpint_dataout;344			funcs->get_fw_status = dmub_dcn35_get_fw_boot_status;345			funcs->get_fw_boot_option = dmub_dcn35_get_fw_boot_option;346			funcs->enable_dmub_boot_options = dmub_dcn35_enable_dmub_boot_options;347			funcs->skip_dmub_panel_power_sequence = dmub_dcn35_skip_dmub_panel_power_sequence;348			//outbox0 call stacks349			funcs->setup_outbox0 = dmub_dcn35_setup_outbox0;350			funcs->get_outbox0_wptr = dmub_dcn35_get_outbox0_wptr;351			funcs->set_outbox0_rptr = dmub_dcn35_set_outbox0_rptr;352 353			funcs->get_current_time = dmub_dcn35_get_current_time;354			funcs->get_diagnostic_data = dmub_dcn35_get_diagnostic_data;355 356			funcs->init_reg_offsets = dmub_srv_dcn35_regs_init;357			if (asic == DMUB_ASIC_DCN351)358                                funcs->init_reg_offsets = dmub_srv_dcn351_regs_init;359 360			funcs->is_hw_powered_up = dmub_dcn35_is_hw_powered_up;361			funcs->should_detect = dmub_dcn35_should_detect;362			break;363 364	case DMUB_ASIC_DCN401:365		dmub->regs_dcn401 = &dmub_srv_dcn401_regs;366		funcs->configure_dmub_in_system_memory = dmub_dcn401_configure_dmub_in_system_memory;367		funcs->send_inbox0_cmd = dmub_dcn401_send_inbox0_cmd;368		funcs->clear_inbox0_ack_register = dmub_dcn401_clear_inbox0_ack_register;369		funcs->read_inbox0_ack_register = dmub_dcn401_read_inbox0_ack_register;370		funcs->reset = dmub_dcn401_reset;371		funcs->reset_release = dmub_dcn401_reset_release;372		funcs->backdoor_load = dmub_dcn401_backdoor_load;373		funcs->backdoor_load_zfb_mode = dmub_dcn401_backdoor_load_zfb_mode;374		funcs->setup_windows = dmub_dcn401_setup_windows;375		funcs->setup_mailbox = dmub_dcn401_setup_mailbox;376		funcs->get_inbox1_wptr = dmub_dcn401_get_inbox1_wptr;377		funcs->get_inbox1_rptr = dmub_dcn401_get_inbox1_rptr;378		funcs->set_inbox1_wptr = dmub_dcn401_set_inbox1_wptr;379		funcs->setup_out_mailbox = dmub_dcn401_setup_out_mailbox;380		funcs->get_outbox1_wptr = dmub_dcn401_get_outbox1_wptr;381		funcs->set_outbox1_rptr = dmub_dcn401_set_outbox1_rptr;382		funcs->is_supported = dmub_dcn401_is_supported;383		funcs->is_hw_init = dmub_dcn401_is_hw_init;384		funcs->set_gpint = dmub_dcn401_set_gpint;385		funcs->is_gpint_acked = dmub_dcn401_is_gpint_acked;386		funcs->get_gpint_response = dmub_dcn401_get_gpint_response;387		funcs->get_gpint_dataout = dmub_dcn401_get_gpint_dataout;388		funcs->get_fw_status = dmub_dcn401_get_fw_boot_status;389		funcs->enable_dmub_boot_options = dmub_dcn401_enable_dmub_boot_options;390		funcs->skip_dmub_panel_power_sequence = dmub_dcn401_skip_dmub_panel_power_sequence;391		//outbox0 call stacks392		funcs->setup_outbox0 = dmub_dcn401_setup_outbox0;393		funcs->get_outbox0_wptr = dmub_dcn401_get_outbox0_wptr;394		funcs->set_outbox0_rptr = dmub_dcn401_set_outbox0_rptr;395 396		funcs->get_current_time = dmub_dcn401_get_current_time;397		funcs->get_diagnostic_data = dmub_dcn401_get_diagnostic_data;398		funcs->send_reg_inbox0_cmd_msg = dmub_dcn401_send_reg_inbox0_cmd_msg;399		funcs->read_reg_inbox0_rsp_int_status = dmub_dcn401_read_reg_inbox0_rsp_int_status;400		funcs->read_reg_inbox0_cmd_rsp = dmub_dcn401_read_reg_inbox0_cmd_rsp;401		funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn401_write_reg_inbox0_rsp_int_ack;402		funcs->write_reg_outbox0_rdy_int_ack = dmub_dcn401_write_reg_outbox0_rdy_int_ack;403		funcs->read_reg_outbox0_msg = dmub_dcn401_read_reg_outbox0_msg;404		funcs->write_reg_outbox0_rsp = dmub_dcn401_write_reg_outbox0_rsp;405		funcs->read_reg_outbox0_rdy_int_status = dmub_dcn401_read_reg_outbox0_rdy_int_status;406		funcs->read_reg_outbox0_rsp_int_status = dmub_dcn401_read_reg_outbox0_rsp_int_status;407		funcs->enable_reg_inbox0_rsp_int = dmub_dcn401_enable_reg_inbox0_rsp_int;408		funcs->enable_reg_outbox0_rdy_int = dmub_dcn401_enable_reg_outbox0_rdy_int;409		break;410	default:411		return false;412	}413 414	return true;415}416 417enum dmub_status dmub_srv_create(struct dmub_srv *dmub,418				 const struct dmub_srv_create_params *params)419{420	enum dmub_status status = DMUB_STATUS_OK;421 422	dmub_memset(dmub, 0, sizeof(*dmub));423 424	dmub->funcs = params->funcs;425	dmub->user_ctx = params->user_ctx;426	dmub->asic = params->asic;427	dmub->fw_version = params->fw_version;428	dmub->is_virtual = params->is_virtual;429 430	/* Setup asic dependent hardware funcs. */431	if (!dmub_srv_hw_setup(dmub, params->asic)) {432		status = DMUB_STATUS_INVALID;433		goto cleanup;434	}435 436	/* Override (some) hardware funcs based on user params. */437	if (params->hw_funcs) {438		if (params->hw_funcs->emul_get_inbox1_rptr)439			dmub->hw_funcs.emul_get_inbox1_rptr =440				params->hw_funcs->emul_get_inbox1_rptr;441 442		if (params->hw_funcs->emul_set_inbox1_wptr)443			dmub->hw_funcs.emul_set_inbox1_wptr =444				params->hw_funcs->emul_set_inbox1_wptr;445 446		if (params->hw_funcs->is_supported)447			dmub->hw_funcs.is_supported =448				params->hw_funcs->is_supported;449	}450 451	/* Sanity checks for required hw func pointers. */452	if (!dmub->hw_funcs.get_inbox1_rptr ||453	    !dmub->hw_funcs.set_inbox1_wptr) {454		status = DMUB_STATUS_INVALID;455		goto cleanup;456	}457 458cleanup:459	if (status == DMUB_STATUS_OK)460		dmub->sw_init = true;461	else462		dmub_srv_destroy(dmub);463 464	return status;465}466 467void dmub_srv_destroy(struct dmub_srv *dmub)468{469	dmub_memset(dmub, 0, sizeof(*dmub));470}471 472static uint32_t dmub_srv_calc_regions_for_memory_type(const struct dmub_srv_region_params *params,473	struct dmub_srv_region_info *out,474	const uint32_t *window_sizes,475	enum dmub_window_memory_type memory_type)476{477	uint32_t i, top = 0;478 479	for (i = 0; i < DMUB_WINDOW_TOTAL; ++i) {480		if (params->window_memory_type[i] == memory_type) {481			struct dmub_region *region = &out->regions[i];482 483			region->base = dmub_align(top, 256);484			region->top = region->base + dmub_align(window_sizes[i], 64);485			top = region->top;486		}487	}488 489	return dmub_align(top, 4096);490}491 492enum dmub_status493	dmub_srv_calc_region_info(struct dmub_srv *dmub,494		const struct dmub_srv_region_params *params,495		struct dmub_srv_region_info *out)496{497	const struct dmub_fw_meta_info *fw_info;498	uint32_t fw_state_size = DMUB_FW_STATE_SIZE;499	uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;500	uint32_t window_sizes[DMUB_WINDOW_TOTAL] = { 0 };501 502	if (!dmub->sw_init)503		return DMUB_STATUS_INVALID;504 505	memset(out, 0, sizeof(*out));506	memset(window_sizes, 0, sizeof(window_sizes));507 508	out->num_regions = DMUB_NUM_WINDOWS;509 510	fw_info = dmub_get_fw_meta_info(params);511 512	if (fw_info) {513		memcpy(&dmub->meta_info, fw_info, sizeof(*fw_info));514 515		fw_state_size = fw_info->fw_region_size;516		trace_buffer_size = fw_info->trace_buffer_size;517 518		/**519		 * If DM didn't fill in a version, then fill it in based on520		 * the firmware meta now that we have it.521		 *522		 * TODO: Make it easier for driver to extract this out to523		 * pass during creation.524		 */525		if (dmub->fw_version == 0)526			dmub->fw_version = fw_info->fw_version;527	}528 529	window_sizes[DMUB_WINDOW_0_INST_CONST] = params->inst_const_size;530	window_sizes[DMUB_WINDOW_1_STACK] = DMUB_STACK_SIZE + DMUB_CONTEXT_SIZE;531	window_sizes[DMUB_WINDOW_2_BSS_DATA] = params->bss_data_size;532	window_sizes[DMUB_WINDOW_3_VBIOS] = params->vbios_size;533	window_sizes[DMUB_WINDOW_4_MAILBOX] = DMUB_MAILBOX_SIZE;534	window_sizes[DMUB_WINDOW_5_TRACEBUFF] = trace_buffer_size;535	window_sizes[DMUB_WINDOW_6_FW_STATE] = fw_state_size;536	window_sizes[DMUB_WINDOW_7_SCRATCH_MEM] = DMUB_SCRATCH_MEM_SIZE;537	window_sizes[DMUB_WINDOW_SHARED_STATE] = DMUB_FW_HEADER_SHARED_STATE_SIZE;538 539	out->fb_size =540		dmub_srv_calc_regions_for_memory_type(params, out, window_sizes, DMUB_WINDOW_MEMORY_TYPE_FB);541 542	out->gart_size =543		dmub_srv_calc_regions_for_memory_type(params, out, window_sizes, DMUB_WINDOW_MEMORY_TYPE_GART);544 545	return DMUB_STATUS_OK;546}547 548enum dmub_status dmub_srv_calc_mem_info(struct dmub_srv *dmub,549				       const struct dmub_srv_memory_params *params,550				       struct dmub_srv_fb_info *out)551{552	uint32_t i;553 554	if (!dmub->sw_init)555		return DMUB_STATUS_INVALID;556 557	memset(out, 0, sizeof(*out));558 559	if (params->region_info->num_regions != DMUB_NUM_WINDOWS)560		return DMUB_STATUS_INVALID;561 562	for (i = 0; i < DMUB_NUM_WINDOWS; ++i) {563		const struct dmub_region *reg =564			&params->region_info->regions[i];565 566		if (params->window_memory_type[i] == DMUB_WINDOW_MEMORY_TYPE_GART) {567			out->fb[i].cpu_addr = (uint8_t *)params->cpu_gart_addr + reg->base;568			out->fb[i].gpu_addr = params->gpu_gart_addr + reg->base;569		} else {570			out->fb[i].cpu_addr = (uint8_t *)params->cpu_fb_addr + reg->base;571			out->fb[i].gpu_addr = params->gpu_fb_addr + reg->base;572		}573 574		out->fb[i].size = reg->top - reg->base;575	}576 577	out->num_fb = DMUB_NUM_WINDOWS;578 579	return DMUB_STATUS_OK;580}581 582enum dmub_status dmub_srv_has_hw_support(struct dmub_srv *dmub,583					 bool *is_supported)584{585	*is_supported = false;586 587	if (!dmub->sw_init)588		return DMUB_STATUS_INVALID;589 590	if (dmub->hw_funcs.is_supported)591		*is_supported = dmub->hw_funcs.is_supported(dmub);592 593	return DMUB_STATUS_OK;594}595 596enum dmub_status dmub_srv_is_hw_init(struct dmub_srv *dmub, bool *is_hw_init)597{598	*is_hw_init = false;599 600	if (!dmub->sw_init)601		return DMUB_STATUS_INVALID;602 603	if (!dmub->hw_init)604		return DMUB_STATUS_OK;605 606	if (dmub->hw_funcs.is_hw_init)607		*is_hw_init = dmub->hw_funcs.is_hw_init(dmub);608 609	return DMUB_STATUS_OK;610}611 612enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,613				  const struct dmub_srv_hw_params *params)614{615	struct dmub_fb *inst_fb = params->fb[DMUB_WINDOW_0_INST_CONST];616	struct dmub_fb *stack_fb = params->fb[DMUB_WINDOW_1_STACK];617	struct dmub_fb *data_fb = params->fb[DMUB_WINDOW_2_BSS_DATA];618	struct dmub_fb *bios_fb = params->fb[DMUB_WINDOW_3_VBIOS];619	struct dmub_fb *mail_fb = params->fb[DMUB_WINDOW_4_MAILBOX];620	struct dmub_fb *tracebuff_fb = params->fb[DMUB_WINDOW_5_TRACEBUFF];621	struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE];622	struct dmub_fb *scratch_mem_fb = params->fb[DMUB_WINDOW_7_SCRATCH_MEM];623	struct dmub_fb *shared_state_fb = params->fb[DMUB_WINDOW_SHARED_STATE];624 625	struct dmub_rb_init_params rb_params, outbox0_rb_params;626	struct dmub_window cw0, cw1, cw2, cw3, cw4, cw5, cw6, region6;627	struct dmub_region inbox1, outbox1, outbox0;628 629	if (!dmub->sw_init)630		return DMUB_STATUS_INVALID;631 632	if (!inst_fb || !stack_fb || !data_fb || !bios_fb || !mail_fb ||633		!tracebuff_fb || !fw_state_fb || !scratch_mem_fb) {634		ASSERT(0);635		return DMUB_STATUS_INVALID;636	}637 638	dmub->fb_base = params->fb_base;639	dmub->fb_offset = params->fb_offset;640	dmub->psp_version = params->psp_version;641 642	if (dmub->hw_funcs.reset)643		dmub->hw_funcs.reset(dmub);644 645	/* reset the cache of the last wptr as well now that hw is reset */646	dmub->inbox1_last_wptr = 0;647 648	cw0.offset.quad_part = inst_fb->gpu_addr;649	cw0.region.base = DMUB_CW0_BASE;650	cw0.region.top = cw0.region.base + inst_fb->size - 1;651 652	cw1.offset.quad_part = stack_fb->gpu_addr;653	cw1.region.base = DMUB_CW1_BASE;654	cw1.region.top = cw1.region.base + stack_fb->size - 1;655 656	if (params->fw_in_system_memory && dmub->hw_funcs.configure_dmub_in_system_memory)657		dmub->hw_funcs.configure_dmub_in_system_memory(dmub);658 659	if (params->load_inst_const && dmub->hw_funcs.backdoor_load) {660		/**661		 * Read back all the instruction memory so we don't hang the662		 * DMCUB when backdoor loading if the write from x86 hasn't been663		 * flushed yet. This only occurs in backdoor loading.664		 */665		if (params->mem_access_type == DMUB_MEMORY_ACCESS_CPU)666			dmub_flush_buffer_mem(inst_fb);667 668		if (params->fw_in_system_memory && dmub->hw_funcs.backdoor_load_zfb_mode)669			dmub->hw_funcs.backdoor_load_zfb_mode(dmub, &cw0, &cw1);670		else671			dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1);672	}673 674	cw2.offset.quad_part = data_fb->gpu_addr;675	cw2.region.base = DMUB_CW0_BASE + inst_fb->size;676	cw2.region.top = cw2.region.base + data_fb->size;677 678	cw3.offset.quad_part = bios_fb->gpu_addr;679	cw3.region.base = DMUB_CW3_BASE;680	cw3.region.top = cw3.region.base + bios_fb->size;681 682	cw4.offset.quad_part = mail_fb->gpu_addr;683	cw4.region.base = DMUB_CW4_BASE;684	cw4.region.top = cw4.region.base + mail_fb->size;685 686	/**687	 * Doubled the mailbox region to accomodate inbox and outbox.688	 * Note: Currently, currently total mailbox size is 16KB. It is split689	 * equally into 8KB between inbox and outbox. If this config is690	 * changed, then uncached base address configuration of outbox1691	 * has to be updated in funcs->setup_out_mailbox.692	 */693	inbox1.base = cw4.region.base;694	inbox1.top = cw4.region.base + DMUB_RB_SIZE;695	outbox1.base = inbox1.top;696	outbox1.top = cw4.region.top;697 698	cw5.offset.quad_part = tracebuff_fb->gpu_addr;699	cw5.region.base = DMUB_CW5_BASE;700	cw5.region.top = cw5.region.base + tracebuff_fb->size;701 702	outbox0.base = DMUB_REGION5_BASE + TRACE_BUFFER_ENTRY_OFFSET;703	outbox0.top = outbox0.base + tracebuff_fb->size - TRACE_BUFFER_ENTRY_OFFSET;704 705	cw6.offset.quad_part = fw_state_fb->gpu_addr;706	cw6.region.base = DMUB_CW6_BASE;707	cw6.region.top = cw6.region.base + fw_state_fb->size;708 709	dmub->fw_state = fw_state_fb->cpu_addr;710 711	region6.offset.quad_part = shared_state_fb->gpu_addr;712	region6.region.base = DMUB_CW6_BASE;713	region6.region.top = region6.region.base + shared_state_fb->size;714 715	dmub->shared_state = shared_state_fb->cpu_addr;716 717	dmub->scratch_mem_fb = *scratch_mem_fb;718 719	if (dmub->hw_funcs.setup_windows)720		dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4, &cw5, &cw6, &region6);721 722	if (dmub->hw_funcs.setup_outbox0)723		dmub->hw_funcs.setup_outbox0(dmub, &outbox0);724 725	if (dmub->hw_funcs.setup_mailbox)726		dmub->hw_funcs.setup_mailbox(dmub, &inbox1);727	if (dmub->hw_funcs.setup_out_mailbox)728		dmub->hw_funcs.setup_out_mailbox(dmub, &outbox1);729	if (dmub->hw_funcs.enable_reg_inbox0_rsp_int)730		dmub->hw_funcs.enable_reg_inbox0_rsp_int(dmub, true);731	if (dmub->hw_funcs.enable_reg_outbox0_rdy_int)732		dmub->hw_funcs.enable_reg_outbox0_rdy_int(dmub, true);733 734	dmub_memset(&rb_params, 0, sizeof(rb_params));735	rb_params.ctx = dmub;736	rb_params.base_address = mail_fb->cpu_addr;737	rb_params.capacity = DMUB_RB_SIZE;738	dmub_rb_init(&dmub->inbox1_rb, &rb_params);739 740	// Initialize outbox1 ring buffer741	rb_params.ctx = dmub;742	rb_params.base_address = (void *) ((uint8_t *) (mail_fb->cpu_addr) + DMUB_RB_SIZE);743	rb_params.capacity = DMUB_RB_SIZE;744	dmub_rb_init(&dmub->outbox1_rb, &rb_params);745 746	dmub_memset(&outbox0_rb_params, 0, sizeof(outbox0_rb_params));747	outbox0_rb_params.ctx = dmub;748	outbox0_rb_params.base_address = (void *)((uintptr_t)(tracebuff_fb->cpu_addr) + TRACE_BUFFER_ENTRY_OFFSET);749	outbox0_rb_params.capacity = tracebuff_fb->size - dmub_align(TRACE_BUFFER_ENTRY_OFFSET, 64);750	dmub_rb_init(&dmub->outbox0_rb, &outbox0_rb_params);751 752	/* Report to DMUB what features are supported by current driver */753	if (dmub->hw_funcs.enable_dmub_boot_options)754		dmub->hw_funcs.enable_dmub_boot_options(dmub, params);755 756	if (dmub->hw_funcs.skip_dmub_panel_power_sequence && !dmub->is_virtual)757		dmub->hw_funcs.skip_dmub_panel_power_sequence(dmub,758			params->skip_panel_power_sequence);759 760	if (dmub->hw_funcs.reset_release && !dmub->is_virtual)761		dmub->hw_funcs.reset_release(dmub);762 763	dmub->hw_init = true;764	dmub->power_state = DMUB_POWER_STATE_D0;765 766	return DMUB_STATUS_OK;767}768 769enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub)770{771	if (!dmub->sw_init)772		return DMUB_STATUS_INVALID;773 774	if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) {775		uint32_t rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);776		uint32_t wptr = dmub->hw_funcs.get_inbox1_wptr(dmub);777 778		if (rptr > dmub->inbox1_rb.capacity || wptr > dmub->inbox1_rb.capacity) {779			return DMUB_STATUS_HW_FAILURE;780		} else {781			dmub->inbox1_rb.rptr = rptr;782			dmub->inbox1_rb.wrpt = wptr;783			dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;784		}785	}786 787	return DMUB_STATUS_OK;788}789 790enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)791{792	if (!dmub->sw_init)793		return DMUB_STATUS_INVALID;794 795	if (dmub->hw_funcs.reset)796		dmub->hw_funcs.reset(dmub);797 798	/* mailboxes have been reset in hw, so reset the sw state as well */799	dmub->inbox1_last_wptr = 0;800	dmub->inbox1_rb.wrpt = 0;801	dmub->inbox1_rb.rptr = 0;802	dmub->outbox0_rb.wrpt = 0;803	dmub->outbox0_rb.rptr = 0;804	dmub->outbox1_rb.wrpt = 0;805	dmub->outbox1_rb.rptr = 0;806 807	dmub->hw_init = false;808 809	return DMUB_STATUS_OK;810}811 812enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub,813				    const union dmub_rb_cmd *cmd)814{815	if (!dmub->hw_init)816		return DMUB_STATUS_INVALID;817 818	if (dmub->power_state != DMUB_POWER_STATE_D0)819		return DMUB_STATUS_POWER_STATE_D3;820 821	if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity ||822	    dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) {823		return DMUB_STATUS_HW_FAILURE;824	}825 826	if (dmub_rb_push_front(&dmub->inbox1_rb, cmd))827		return DMUB_STATUS_OK;828 829	return DMUB_STATUS_QUEUE_FULL;830}831 832enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub)833{834	struct dmub_rb flush_rb;835 836	if (!dmub->hw_init)837		return DMUB_STATUS_INVALID;838 839	if (dmub->power_state != DMUB_POWER_STATE_D0)840		return DMUB_STATUS_POWER_STATE_D3;841 842	/**843	 * Read back all the queued commands to ensure that they've844	 * been flushed to framebuffer memory. Otherwise DMCUB might845	 * read back stale, fully invalid or partially invalid data.846	 */847	flush_rb = dmub->inbox1_rb;848	flush_rb.rptr = dmub->inbox1_last_wptr;849	dmub_rb_flush_pending(&flush_rb);850 851	dmub->hw_funcs.set_inbox1_wptr(dmub, dmub->inbox1_rb.wrpt);852 853	dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;854 855	return DMUB_STATUS_OK;856}857 858bool dmub_srv_is_hw_pwr_up(struct dmub_srv *dmub)859{860	if (!dmub->hw_funcs.is_hw_powered_up)861		return true;862 863	if (!dmub->hw_funcs.is_hw_powered_up(dmub))864		return false;865 866	return true;867}868 869enum dmub_status dmub_srv_wait_for_hw_pwr_up(struct dmub_srv *dmub,870					     uint32_t timeout_us)871{872	uint32_t i;873 874	if (!dmub->hw_init)875		return DMUB_STATUS_INVALID;876 877	for (i = 0; i <= timeout_us; i += 100) {878		if (dmub_srv_is_hw_pwr_up(dmub))879			return DMUB_STATUS_OK;880 881		udelay(100);882	}883 884	return DMUB_STATUS_TIMEOUT;885}886 887enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,888					     uint32_t timeout_us)889{890	uint32_t i;891	bool hw_on = true;892 893	if (!dmub->hw_init)894		return DMUB_STATUS_INVALID;895 896	for (i = 0; i <= timeout_us; i += 100) {897		union dmub_fw_boot_status status = dmub->hw_funcs.get_fw_status(dmub);898 899		if (dmub->hw_funcs.is_hw_powered_up)900			hw_on = dmub->hw_funcs.is_hw_powered_up(dmub);901 902		if (status.bits.dal_fw && status.bits.mailbox_rdy && hw_on)903			return DMUB_STATUS_OK;904 905		udelay(100);906	}907 908	return DMUB_STATUS_TIMEOUT;909}910 911enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub,912					uint32_t timeout_us)913{914	uint32_t i, rptr;915 916	if (!dmub->hw_init)917		return DMUB_STATUS_INVALID;918 919	for (i = 0; i <= timeout_us; ++i) {920		rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);921 922		if (rptr > dmub->inbox1_rb.capacity)923			return DMUB_STATUS_HW_FAILURE;924 925		dmub->inbox1_rb.rptr = rptr;926 927		if (dmub_rb_empty(&dmub->inbox1_rb))928			return DMUB_STATUS_OK;929 930		udelay(1);931	}932 933	return DMUB_STATUS_TIMEOUT;934}935 936enum dmub_status937dmub_srv_send_gpint_command(struct dmub_srv *dmub,938			    enum dmub_gpint_command command_code,939			    uint16_t param, uint32_t timeout_us)940{941	union dmub_gpint_data_register reg;942	uint32_t i;943 944	if (!dmub->sw_init)945		return DMUB_STATUS_INVALID;946 947	if (!dmub->hw_funcs.set_gpint)948		return DMUB_STATUS_INVALID;949 950	if (!dmub->hw_funcs.is_gpint_acked)951		return DMUB_STATUS_INVALID;952 953	reg.bits.status = 1;954	reg.bits.command_code = command_code;955	reg.bits.param = param;956 957	dmub->hw_funcs.set_gpint(dmub, reg);958 959	for (i = 0; i < timeout_us; ++i) {960		udelay(1);961 962		if (dmub->hw_funcs.is_gpint_acked(dmub, reg))963			return DMUB_STATUS_OK;964	}965 966	return DMUB_STATUS_TIMEOUT;967}968 969enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,970					     uint32_t *response)971{972	*response = 0;973 974	if (!dmub->sw_init)975		return DMUB_STATUS_INVALID;976 977	if (!dmub->hw_funcs.get_gpint_response)978		return DMUB_STATUS_INVALID;979 980	*response = dmub->hw_funcs.get_gpint_response(dmub);981 982	return DMUB_STATUS_OK;983}984 985enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,986					     uint32_t *dataout)987{988	*dataout = 0;989 990	if (!dmub->sw_init)991		return DMUB_STATUS_INVALID;992 993	if (!dmub->hw_funcs.get_gpint_dataout)994		return DMUB_STATUS_INVALID;995 996	*dataout = dmub->hw_funcs.get_gpint_dataout(dmub);997 998	return DMUB_STATUS_OK;999}1000 1001enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub,1002					     union dmub_fw_boot_status *status)1003{1004	status->all = 0;1005 1006	if (!dmub->sw_init)1007		return DMUB_STATUS_INVALID;1008 1009	if (dmub->hw_funcs.get_fw_status)1010		*status = dmub->hw_funcs.get_fw_status(dmub);1011 1012	return DMUB_STATUS_OK;1013}1014 1015enum dmub_status dmub_srv_get_fw_boot_option(struct dmub_srv *dmub,1016					     union dmub_fw_boot_options *option)1017{1018	option->all = 0;1019 1020	if (!dmub->sw_init)1021		return DMUB_STATUS_INVALID;1022 1023	if (dmub->hw_funcs.get_fw_boot_option)1024		*option = dmub->hw_funcs.get_fw_boot_option(dmub);1025 1026	return DMUB_STATUS_OK;1027}1028 1029enum dmub_status dmub_srv_set_skip_panel_power_sequence(struct dmub_srv *dmub,1030					     bool skip)1031{1032	if (!dmub->sw_init)1033		return DMUB_STATUS_INVALID;1034 1035	if (dmub->hw_funcs.skip_dmub_panel_power_sequence && !dmub->is_virtual)1036		dmub->hw_funcs.skip_dmub_panel_power_sequence(dmub, skip);1037 1038	return DMUB_STATUS_OK;1039}1040 1041enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub,1042					      union dmub_rb_cmd *cmd)1043{1044	enum dmub_status status = DMUB_STATUS_OK;1045 1046	// Queue command1047	status = dmub_srv_cmd_queue(dmub, cmd);1048 1049	if (status != DMUB_STATUS_OK)1050		return status;1051 1052	// Execute command1053	status = dmub_srv_cmd_execute(dmub);1054 1055	if (status != DMUB_STATUS_OK)1056		return status;1057 1058	// Wait for DMUB to process command1059	status = dmub_srv_wait_for_idle(dmub, 100000);1060 1061	if (status != DMUB_STATUS_OK)1062		return status;1063 1064	// Copy data back from ring buffer into command1065	dmub_rb_get_return_data(&dmub->inbox1_rb, cmd);1066 1067	return status;1068}1069 1070static inline bool dmub_rb_out_trace_buffer_front(struct dmub_rb *rb,1071				 void *entry)1072{1073	const uint64_t *src = (const uint64_t *)(rb->base_address) + rb->rptr / sizeof(uint64_t);1074	uint64_t *dst = (uint64_t *)entry;1075	uint8_t i;1076	uint8_t loop_count;1077 1078	if (rb->rptr == rb->wrpt)1079		return false;1080 1081	loop_count = sizeof(struct dmcub_trace_buf_entry) / sizeof(uint64_t);1082	// copying data1083	for (i = 0; i < loop_count; i++)1084		*dst++ = *src++;1085 1086	rb->rptr += sizeof(struct dmcub_trace_buf_entry);1087 1088	rb->rptr %= rb->capacity;1089 1090	return true;1091}1092 1093bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry)1094{1095	dmub->outbox0_rb.wrpt = dmub->hw_funcs.get_outbox0_wptr(dmub);1096 1097	return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry);1098}1099 1100bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)1101{1102	if (!dmub || !dmub->hw_funcs.get_diagnostic_data || !diag_data)1103		return false;1104	dmub->hw_funcs.get_diagnostic_data(dmub, diag_data);1105	return true;1106}1107 1108bool dmub_srv_should_detect(struct dmub_srv *dmub)1109{1110	if (!dmub->hw_init || !dmub->hw_funcs.should_detect)1111		return false;1112 1113	return dmub->hw_funcs.should_detect(dmub);1114}1115 1116enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub)1117{1118	if (!dmub->hw_init || !dmub->hw_funcs.clear_inbox0_ack_register)1119		return DMUB_STATUS_INVALID;1120 1121	dmub->hw_funcs.clear_inbox0_ack_register(dmub);1122	return DMUB_STATUS_OK;1123}1124 1125enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t timeout_us)1126{1127	uint32_t i = 0;1128	uint32_t ack = 0;1129 1130	if (!dmub->hw_init || !dmub->hw_funcs.read_inbox0_ack_register)1131		return DMUB_STATUS_INVALID;1132 1133	for (i = 0; i <= timeout_us; i++) {1134		ack = dmub->hw_funcs.read_inbox0_ack_register(dmub);1135		if (ack)1136			return DMUB_STATUS_OK;1137		udelay(1);1138	}1139	return DMUB_STATUS_TIMEOUT;1140}1141 1142enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub,1143		union dmub_inbox0_data_register data)1144{1145	if (!dmub->hw_init || !dmub->hw_funcs.send_inbox0_cmd)1146		return DMUB_STATUS_INVALID;1147 1148	dmub->hw_funcs.send_inbox0_cmd(dmub, data);1149	return DMUB_STATUS_OK;1150}1151 1152void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index)1153{1154	if (dmub->hw_funcs.subvp_save_surf_addr) {1155		dmub->hw_funcs.subvp_save_surf_addr(dmub,1156				addr,1157				subvp_index);1158	}1159}1160 1161enum dmub_status dmub_srv_send_reg_inbox0_cmd(1162		struct dmub_srv *dmub,1163		union dmub_rb_cmd *cmd,1164		bool with_reply, uint32_t timeout_us)1165{1166	uint32_t rsp_ready = 0;1167	uint32_t i;1168 1169	dmub->hw_funcs.send_reg_inbox0_cmd_msg(dmub, cmd);1170 1171	for (i = 0; i < timeout_us; i++) {1172		rsp_ready = dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub);1173		if (rsp_ready)1174			break;1175		udelay(1);1176	}1177	if (rsp_ready == 0)1178		return DMUB_STATUS_TIMEOUT;1179 1180	if (with_reply)1181		dmub->hw_funcs.read_reg_inbox0_cmd_rsp(dmub, cmd);1182 1183	dmub->hw_funcs.write_reg_inbox0_rsp_int_ack(dmub);1184 1185	/* wait for rsp int status is cleared to initial state before exit */1186	for (; i <= timeout_us; i++) {1187		rsp_ready = dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub);1188		if (rsp_ready == 0)1189			break;1190		udelay(1);1191	}1192	ASSERT(rsp_ready == 0);1193 1194	return DMUB_STATUS_OK;1195}1196 1197void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state)1198{1199	if (!dmub || !dmub->hw_init)1200		return;1201 1202	dmub->power_state = dmub_srv_power_state;1203}1204