diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 152 |
1 files changed, 132 insertions, 20 deletions
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 56d400ffa7ac..4a122925c3ae 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -32,6 +32,9 @@ #include "dmub_dcn302.h" #include "dmub_dcn303.h" #include "dmub_dcn31.h" +#include "dmub_dcn315.h" +#include "dmub_dcn316.h" +#include "dmub_dcn32.h" #include "os_types.h" /* * Note: the DMUB service is standalone. No additional headers should be @@ -100,24 +103,9 @@ void dmub_flush_buffer_mem(const struct dmub_fb *fb) } static const struct dmub_fw_meta_info * -dmub_get_fw_meta_info(const struct dmub_srv_region_params *params) +dmub_get_fw_meta_info_from_blob(const uint8_t *blob, uint32_t blob_size, uint32_t meta_offset) { const union dmub_fw_meta *meta; - const uint8_t *blob = NULL; - uint32_t blob_size = 0; - uint32_t meta_offset = 0; - - if (params->fw_bss_data && params->bss_data_size) { - /* Legacy metadata region. */ - blob = params->fw_bss_data; - blob_size = params->bss_data_size; - meta_offset = DMUB_FW_META_OFFSET; - } else if (params->fw_inst_const && params->inst_const_size) { - /* Combined metadata region. */ - blob = params->fw_inst_const; - blob_size = params->inst_const_size; - meta_offset = 0; - } if (!blob || !blob_size) return NULL; @@ -134,6 +122,32 @@ dmub_get_fw_meta_info(const struct dmub_srv_region_params *params) return &meta->info; } +static const struct dmub_fw_meta_info * +dmub_get_fw_meta_info(const struct dmub_srv_region_params *params) +{ + const struct dmub_fw_meta_info *info = NULL; + + if (params->fw_bss_data && params->bss_data_size) { + /* Legacy metadata region. */ + info = dmub_get_fw_meta_info_from_blob(params->fw_bss_data, + params->bss_data_size, + DMUB_FW_META_OFFSET); + } else if (params->fw_inst_const && params->inst_const_size) { + /* Combined metadata region - can be aligned to 16-bytes. */ + uint32_t i; + + for (i = 0; i < 16; ++i) { + info = dmub_get_fw_meta_info_from_blob( + params->fw_inst_const, params->inst_const_size, i); + + if (info) + break; + } + } + + return info; +} + static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) { struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs; @@ -209,7 +223,15 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) case DMUB_ASIC_DCN31: case DMUB_ASIC_DCN31B: - dmub->regs_dcn31 = &dmub_srv_dcn31_regs; + case DMUB_ASIC_DCN314: + case DMUB_ASIC_DCN315: + case DMUB_ASIC_DCN316: + if (asic == DMUB_ASIC_DCN315) + dmub->regs_dcn31 = &dmub_srv_dcn315_regs; + else if (asic == DMUB_ASIC_DCN316) + dmub->regs_dcn31 = &dmub_srv_dcn316_regs; + else + dmub->regs_dcn31 = &dmub_srv_dcn31_regs; funcs->reset = dmub_dcn31_reset; funcs->reset_release = dmub_dcn31_reset_release; funcs->backdoor_load = dmub_dcn31_backdoor_load; @@ -240,6 +262,43 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) break; + case DMUB_ASIC_DCN32: + case DMUB_ASIC_DCN321: + dmub->regs_dcn32 = &dmub_srv_dcn32_regs; + funcs->configure_dmub_in_system_memory = dmub_dcn32_configure_dmub_in_system_memory; + funcs->send_inbox0_cmd = dmub_dcn32_send_inbox0_cmd; + funcs->clear_inbox0_ack_register = dmub_dcn32_clear_inbox0_ack_register; + funcs->read_inbox0_ack_register = dmub_dcn32_read_inbox0_ack_register; + funcs->reset = dmub_dcn32_reset; + funcs->reset_release = dmub_dcn32_reset_release; + funcs->backdoor_load = dmub_dcn32_backdoor_load; + funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode; + funcs->setup_windows = dmub_dcn32_setup_windows; + funcs->setup_mailbox = dmub_dcn32_setup_mailbox; + funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr; + funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr; + funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox; + funcs->get_outbox1_wptr = dmub_dcn32_get_outbox1_wptr; + funcs->set_outbox1_rptr = dmub_dcn32_set_outbox1_rptr; + funcs->is_supported = dmub_dcn32_is_supported; + funcs->is_hw_init = dmub_dcn32_is_hw_init; + funcs->set_gpint = dmub_dcn32_set_gpint; + funcs->is_gpint_acked = dmub_dcn32_is_gpint_acked; + funcs->get_gpint_response = dmub_dcn32_get_gpint_response; + funcs->get_gpint_dataout = dmub_dcn32_get_gpint_dataout; + funcs->get_fw_status = dmub_dcn32_get_fw_boot_status; + funcs->enable_dmub_boot_options = dmub_dcn32_enable_dmub_boot_options; + funcs->skip_dmub_panel_power_sequence = dmub_dcn32_skip_dmub_panel_power_sequence; + + /* outbox0 call stacks */ + funcs->setup_outbox0 = dmub_dcn32_setup_outbox0; + funcs->get_outbox0_wptr = dmub_dcn32_get_outbox0_wptr; + funcs->set_outbox0_rptr = dmub_dcn32_set_outbox0_rptr; + funcs->get_current_time = dmub_dcn32_get_current_time; + funcs->get_diagnostic_data = dmub_dcn32_get_diagnostic_data; + + break; + default: return false; } @@ -481,6 +540,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, cw1.region.base = DMUB_CW1_BASE; cw1.region.top = cw1.region.base + stack_fb->size - 1; + if (params->fw_in_system_memory && dmub->hw_funcs.configure_dmub_in_system_memory) + dmub->hw_funcs.configure_dmub_in_system_memory(dmub); + if (params->load_inst_const && dmub->hw_funcs.backdoor_load) { /** * Read back all the instruction memory so we don't hang the @@ -488,7 +550,11 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, * flushed yet. This only occurs in backdoor loading. */ dmub_flush_buffer_mem(inst_fb); - dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1); + + if (params->fw_in_system_memory && dmub->hw_funcs.backdoor_load_zfb_mode) + dmub->hw_funcs.backdoor_load_zfb_mode(dmub, &cw0, &cw1); + else + dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1); } cw2.offset.quad_part = data_fb->gpu_addr; @@ -563,6 +629,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, if (dmub->hw_funcs.enable_dmub_boot_options) dmub->hw_funcs.enable_dmub_boot_options(dmub, params); + if (dmub->hw_funcs.skip_dmub_panel_power_sequence) + dmub->hw_funcs.skip_dmub_panel_power_sequence(dmub, + params->skip_panel_power_sequence); + if (dmub->hw_funcs.reset_release) dmub->hw_funcs.reset_release(dmub); @@ -598,6 +668,8 @@ enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub, enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub) { + struct dmub_rb flush_rb; + if (!dmub->hw_init) return DMUB_STATUS_INVALID; @@ -606,9 +678,14 @@ enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub) * been flushed to framebuffer memory. Otherwise DMCUB might * read back stale, fully invalid or partially invalid data. */ - dmub_rb_flush_pending(&dmub->inbox1_rb); + flush_rb = dmub->inbox1_rb; + flush_rb.rptr = dmub->inbox1_last_wptr; + dmub_rb_flush_pending(&flush_rb); + + dmub->hw_funcs.set_inbox1_wptr(dmub, dmub->inbox1_rb.wrpt); + + dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt; - dmub->hw_funcs.set_inbox1_wptr(dmub, dmub->inbox1_rb.wrpt); return DMUB_STATUS_OK; } @@ -831,3 +908,38 @@ bool dmub_srv_should_detect(struct dmub_srv *dmub) return dmub->hw_funcs.should_detect(dmub); } + +enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub) +{ + if (!dmub->hw_init || !dmub->hw_funcs.clear_inbox0_ack_register) + return DMUB_STATUS_INVALID; + + dmub->hw_funcs.clear_inbox0_ack_register(dmub); + return DMUB_STATUS_OK; +} + +enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t timeout_us) +{ + uint32_t i = 0; + uint32_t ack = 0; + + if (!dmub->hw_init || !dmub->hw_funcs.read_inbox0_ack_register) + return DMUB_STATUS_INVALID; + + for (i = 0; i <= timeout_us; i++) { + ack = dmub->hw_funcs.read_inbox0_ack_register(dmub); + if (ack) + return DMUB_STATUS_OK; + } + return DMUB_STATUS_TIMEOUT; +} + +enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub, + union dmub_inbox0_data_register data) +{ + if (!dmub->hw_init || !dmub->hw_funcs.send_inbox0_cmd) + return DMUB_STATUS_INVALID; + + dmub->hw_funcs.send_inbox0_cmd(dmub, data); + return DMUB_STATUS_OK; +} |