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 ¶ms->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, ®ion6);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