Commit 65138eb7 authored by Qingqing Zhuo's avatar Qingqing Zhuo Committed by Alex Deucher

drm/amd/display: Add DCN35 DMUB

[Why & How]
Add DMUB handling for DCN35.
Signed-off-by: default avatarQingqing Zhuo <Qingqing.Zhuo@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9d6fa676
......@@ -32,6 +32,7 @@
#include "../basics/conversion.h"
#include "cursor_reg_cache.h"
#include "resource.h"
#include "clk_mgr.h"
#define CTX dc_dmub_srv->ctx
#define DC_LOGGER CTX->logger
......@@ -1061,4 +1062,65 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index)
{
dmub_srv_subvp_save_surf_addr(dc_dmub_srv->dmub, addr, subvp_index);
}
\ No newline at end of file
}
bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait)
{
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status;
if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation)
return true;
if (wait) {
status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error querying DMUB hw power up status: error=%d\n", status);
return false;
}
} else
return dmub_srv_is_hw_pwr_up(dc_dmub_srv->dmub);
return true;
}
void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
{
union dmub_rb_cmd cmd = {0};
if (dc->debug.dmcub_emulation)
return;
memset(&cmd, 0, sizeof(cmd));
cmd.idle_opt_notify_idle.header.type = DMUB_CMD__IDLE_OPT;
cmd.idle_opt_notify_idle.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE;
cmd.idle_opt_notify_idle.header.payload_bytes =
sizeof(cmd.idle_opt_notify_idle) -
sizeof(cmd.idle_opt_notify_idle.header);
cmd.idle_opt_notify_idle.cntl_data.driver_idle = allow_idle;
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
if (allow_idle)
udelay(500);
}
void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
{
if (dc->debug.dmcub_emulation)
return;
// Tell PMFW to exit low power state
if (dc->clk_mgr->funcs->exit_low_power_state)
dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);
// Wait for dmcub to load up
dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true);
// Notify dmcub disallow idle
dc_dmub_srv_notify_idle(dc, false);
// Confirm dmu is powered up
dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true);
}
......@@ -91,4 +91,7 @@ bool dc_dmub_check_min_version(struct dmub_srv *srv);
void dc_dmub_srv_enable_dpia_trace(const struct dc *dc);
void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index);
bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait);
void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle);
void dc_dmub_srv_exit_low_power_state(const struct dc *dc);
#endif /* _DMUB_DC_SRV_H_ */
......@@ -104,6 +104,7 @@ enum dmub_asic {
DMUB_ASIC_DCN316,
DMUB_ASIC_DCN32,
DMUB_ASIC_DCN321,
DMUB_ASIC_DCN35,
DMUB_ASIC_MAX,
};
......@@ -272,6 +273,7 @@ struct dmub_srv_hw_params {
bool disable_clock_gate;
bool disallow_dispclk_dppclk_ds;
enum dmub_memory_access_type mem_access_type;
enum dmub_ips_disable_type disable_ips;
};
/**
......@@ -379,6 +381,7 @@ struct dmub_srv_hw_funcs {
bool (*is_psrsu_supported)(struct dmub_srv *dmub);
bool (*is_hw_init)(struct dmub_srv *dmub);
bool (*is_hw_powered_up)(struct dmub_srv *dmub);
void (*enable_dmub_boot_options)(struct dmub_srv *dmub,
const struct dmub_srv_hw_params *params);
......@@ -426,6 +429,7 @@ struct dmub_srv_create_params {
struct dmub_srv_base_funcs funcs;
struct dmub_srv_hw_funcs *hw_funcs;
void *user_ctx;
struct dc_context *dc_ctx;
enum dmub_asic asic;
uint32_t fw_version;
bool is_virtual;
......@@ -451,6 +455,7 @@ struct dmub_srv {
const struct dmub_srv_common_regs *regs;
const struct dmub_srv_dcn31_regs *regs_dcn31;
struct dmub_srv_dcn32_regs *regs_dcn32;
struct dmub_srv_dcn35_regs *regs_dcn35;
struct dmub_srv_base_funcs funcs;
struct dmub_srv_hw_funcs hw_funcs;
......@@ -658,6 +663,24 @@ enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub,
*/
enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub);
/**
* dmub_srv_wait_for_hw_pwr_up() - Waits for firmware hardware power up is completed
* @dmub: the dmub service
* @timeout_us: the maximum number of microseconds to wait
*
* Waits until firmware hardware is powered up. The maximum
* wait time is given in microseconds to prevent spinning forever.
*
* Return:
* DMUB_STATUS_OK - success
* DMUB_STATUS_TIMEOUT - timed out
* DMUB_STATUS_INVALID - unspecified error
*/
enum dmub_status dmub_srv_wait_for_hw_pwr_up(struct dmub_srv *dmub,
uint32_t timeout_us);
bool dmub_srv_is_hw_pwr_up(struct dmub_srv *dmub);
/**
* dmub_srv_wait_for_auto_load() - Waits for firmware auto load to complete
* @dmub: the dmub service
......
......@@ -24,6 +24,7 @@ DMUB = dmub_srv.o dmub_srv_stat.o dmub_reg.o dmub_dcn20.o dmub_dcn21.o
DMUB += dmub_dcn30.o dmub_dcn301.o dmub_dcn302.o dmub_dcn303.o
DMUB += dmub_dcn31.o dmub_dcn314.o dmub_dcn315.o dmub_dcn316.o
DMUB += dmub_dcn32.o
DMUB += dmub_dcn35.o
AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB))
......
This diff is collapsed.
This diff is collapsed.
......@@ -36,6 +36,7 @@
#include "dmub_dcn315.h"
#include "dmub_dcn316.h"
#include "dmub_dcn32.h"
#include "dmub_dcn35.h"
#include "os_types.h"
/*
* Note: the DMUB service is standalone. No additional headers should be
......@@ -79,6 +80,7 @@
#define DMUB_REGION5_BASE (0xA0000000)
static struct dmub_srv_dcn32_regs dmub_srv_dcn32_regs;
static struct dmub_srv_dcn35_regs dmub_srv_dcn35_regs;
static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
{
......@@ -311,6 +313,47 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
break;
case DMUB_ASIC_DCN35:
dmub->regs_dcn35 = &dmub_srv_dcn35_regs;
funcs->configure_dmub_in_system_memory = dmub_dcn35_configure_dmub_in_system_memory;
funcs->send_inbox0_cmd = dmub_dcn35_send_inbox0_cmd;
funcs->clear_inbox0_ack_register = dmub_dcn35_clear_inbox0_ack_register;
funcs->read_inbox0_ack_register = dmub_dcn35_read_inbox0_ack_register;
funcs->reset = dmub_dcn35_reset;
funcs->reset_release = dmub_dcn35_reset_release;
funcs->backdoor_load = dmub_dcn35_backdoor_load;
funcs->backdoor_load_zfb_mode = dmub_dcn35_backdoor_load_zfb_mode;
funcs->setup_windows = dmub_dcn35_setup_windows;
funcs->setup_mailbox = dmub_dcn35_setup_mailbox;
funcs->get_inbox1_wptr = dmub_dcn35_get_inbox1_wptr;
funcs->get_inbox1_rptr = dmub_dcn35_get_inbox1_rptr;
funcs->set_inbox1_wptr = dmub_dcn35_set_inbox1_wptr;
funcs->setup_out_mailbox = dmub_dcn35_setup_out_mailbox;
funcs->get_outbox1_wptr = dmub_dcn35_get_outbox1_wptr;
funcs->set_outbox1_rptr = dmub_dcn35_set_outbox1_rptr;
funcs->is_supported = dmub_dcn35_is_supported;
funcs->is_hw_init = dmub_dcn35_is_hw_init;
funcs->set_gpint = dmub_dcn35_set_gpint;
funcs->is_gpint_acked = dmub_dcn35_is_gpint_acked;
funcs->get_gpint_response = dmub_dcn35_get_gpint_response;
funcs->get_gpint_dataout = dmub_dcn35_get_gpint_dataout;
funcs->get_fw_status = dmub_dcn35_get_fw_boot_status;
funcs->get_fw_boot_option = dmub_dcn35_get_fw_boot_option;
funcs->enable_dmub_boot_options = dmub_dcn35_enable_dmub_boot_options;
funcs->skip_dmub_panel_power_sequence = dmub_dcn35_skip_dmub_panel_power_sequence;
//outbox0 call stacks
funcs->setup_outbox0 = dmub_dcn35_setup_outbox0;
funcs->get_outbox0_wptr = dmub_dcn35_get_outbox0_wptr;
funcs->set_outbox0_rptr = dmub_dcn35_set_outbox0_rptr;
funcs->get_current_time = dmub_dcn35_get_current_time;
funcs->get_diagnostic_data = dmub_dcn35_get_diagnostic_data;
funcs->init_reg_offsets = dmub_srv_dcn35_regs_init;
funcs->is_hw_powered_up = dmub_dcn35_is_hw_powered_up;
break;
default:
return false;
}
......@@ -728,10 +771,38 @@ enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub)
return DMUB_STATUS_OK;
}
bool dmub_srv_is_hw_pwr_up(struct dmub_srv *dmub)
{
if (!dmub->hw_funcs.is_hw_powered_up)
return true;
return dmub->hw_funcs.is_hw_powered_up(dmub) &&
dmub->hw_funcs.is_hw_init(dmub);
}
enum dmub_status dmub_srv_wait_for_hw_pwr_up(struct dmub_srv *dmub,
uint32_t timeout_us)
{
uint32_t i;
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
for (i = 0; i <= timeout_us; i += 100) {
if (dmub_srv_is_hw_pwr_up(dmub))
return DMUB_STATUS_OK;
udelay(100);
}
return DMUB_STATUS_TIMEOUT;
}
enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
uint32_t timeout_us)
{
uint32_t i;
bool hw_on = true;
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
......@@ -739,7 +810,10 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
for (i = 0; i <= timeout_us; i += 100) {
union dmub_fw_boot_status status = dmub->hw_funcs.get_fw_status(dmub);
if (status.bits.dal_fw && status.bits.mailbox_rdy)
if (dmub->hw_funcs.is_hw_powered_up)
hw_on = dmub->hw_funcs.is_hw_powered_up(dmub);
if (status.bits.dal_fw && status.bits.mailbox_rdy && hw_on)
return DMUB_STATUS_OK;
udelay(100);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment