drm/amd/display: add mechanism to skip DCN init

[Why]
If optimized init is done in FW. DCN init be skipped in driver. This
need to be communicated between driver and fw and maintain backwards
compatibility.

[How]
Use DMUB scratch 0 bit 2 to indicate optimized init done in fw and
use DMUB scatch 4 bit 0 to indicate drive supports the optimized flow
so FW will perform it.

Signed-off-by: Eric Yang <Eric.Yang2@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Eric Yang 2020-05-29 17:13:57 -04:00 committed by Alex Deucher
parent c04bd16e48
commit 8f95ff284c
10 changed files with 46 additions and 72 deletions

View File

@ -2681,6 +2681,7 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
dal_irq_service_ack(dc->res_pool->irqs, src);
}
void dc_set_power_state(
struct dc *dc,
enum dc_acpi_cm_power_state power_state)
@ -2692,9 +2693,6 @@ void dc_set_power_state(
case DC_ACPI_CM_POWER_STATE_D0:
dc_resource_state_construct(dc, dc->current_state);
if (dc->ctx->dmub_srv)
dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv);
dc->hwss.init_hw(dc);
if (dc->hwss.init_sys_ctx != NULL &&

View File

@ -106,29 +106,17 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
}
void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv)
bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv)
{
struct dmub_srv *dmub = dc_dmub_srv->dmub;
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status;
struct dmub_srv *dmub;
union dmub_fw_boot_status status;
for (;;) {
/* Wait up to a second for PHY init. */
status = dmub_srv_wait_for_phy_init(dmub, 1000000);
if (status == DMUB_STATUS_OK)
/* Initialization OK */
break;
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
return false;
DC_ERROR("DMCUB PHY init failed: status=%d\n", status);
ASSERT(0);
dmub = dc_dmub_srv->dmub;
if (status != DMUB_STATUS_TIMEOUT)
/*
* Server likely initialized or we don't have
* DMCUB HW support - this won't end.
*/
break;
status = dmub->hw_funcs.get_fw_status(dmub);
/* Continue spinning so we don't hang the ASIC. */
}
return status.bits.optimized_init_done;
}

View File

@ -56,4 +56,6 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);
void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv);
bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv);
#endif /* _DMUB_DC_SRV_H_ */

View File

@ -1288,7 +1288,9 @@ void dcn10_init_hw(struct dc *dc)
if (!dcb->funcs->is_accelerated_mode(dcb))
hws->funcs.disable_vga(dc->hwseq);
hws->funcs.bios_golden_init(dc);
if (!dc_dmub_srv_optimized_init_done(dc->ctx->dmub_srv))
hws->funcs.bios_golden_init(dc);
if (dc->ctx->dc_bios->fw_info_valid) {
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;

View File

@ -264,9 +264,10 @@ struct dmub_srv_hw_funcs {
bool (*is_hw_init)(struct dmub_srv *dmub);
bool (*is_phy_init)(struct dmub_srv *dmub);
void (*enable_dmub_boot_options)(struct dmub_srv *dmub);
union dmub_fw_boot_status (*get_fw_status)(struct dmub_srv *dmub);
bool (*is_auto_load_done)(struct dmub_srv *dmub);
void (*set_gpint)(struct dmub_srv *dmub,
union dmub_gpint_data_register reg);

View File

@ -312,3 +312,18 @@ uint32_t dmub_dcn20_get_gpint_response(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_SCRATCH7);
}
union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub)
{
union dmub_fw_boot_status status;
status.all = REG_READ(DMCUB_SCRATCH0);
return status;
}
void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub)
{
union dmub_fw_boot_options boot_options = {0};
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
}

View File

@ -192,4 +192,8 @@ bool dmub_dcn20_is_gpint_acked(struct dmub_srv *dmub,
uint32_t dmub_dcn20_get_gpint_response(struct dmub_srv *dmub);
void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub);
union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub);
#endif /* _DMUB_DCN20_H_ */

View File

@ -51,14 +51,4 @@ const struct dmub_srv_common_regs dmub_srv_dcn21_regs = {
#undef DMUB_SF
};
/* Shared functions. */
bool dmub_dcn21_is_auto_load_done(struct dmub_srv *dmub)
{
return (REG_READ(DMCUB_SCRATCH0) == 3);
}
bool dmub_dcn21_is_phy_init(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_SCRATCH10) == 0;
}

View File

@ -32,10 +32,4 @@
extern const struct dmub_srv_common_regs dmub_srv_dcn21_regs;
/* Hardware functions. */
bool dmub_dcn21_is_auto_load_done(struct dmub_srv *dmub);
bool dmub_dcn21_is_phy_init(struct dmub_srv *dmub);
#endif /* _DMUB_DCN21_H_ */

View File

@ -153,18 +153,16 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->set_gpint = dmub_dcn20_set_gpint;
funcs->is_gpint_acked = dmub_dcn20_is_gpint_acked;
funcs->get_gpint_response = dmub_dcn20_get_gpint_response;
funcs->get_fw_status = dmub_dcn20_get_fw_boot_status;
funcs->enable_dmub_boot_options = dmub_dcn20_enable_dmub_boot_options;
if (asic == DMUB_ASIC_DCN21) {
if (asic == DMUB_ASIC_DCN21)
dmub->regs = &dmub_srv_dcn21_regs;
funcs->is_auto_load_done = dmub_dcn21_is_auto_load_done;
funcs->is_phy_init = dmub_dcn21_is_phy_init;
}
#ifdef CONFIG_DRM_AMD_DC_DCN3_0
if (asic == DMUB_ASIC_DCN30) {
dmub->regs = &dmub_srv_dcn30_regs;
funcs->is_auto_load_done = dmub_dcn30_is_auto_load_done;
funcs->backdoor_load = dmub_dcn30_backdoor_load;
funcs->setup_windows = dmub_dcn30_setup_windows;
}
@ -454,6 +452,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
dmub_rb_init(&dmub->inbox1_rb, &rb_params);
}
/* Report to DMUB what features are supported by current driver */
if (dmub->hw_funcs.enable_dmub_boot_options)
dmub->hw_funcs.enable_dmub_boot_options(dmub);
if (dmub->hw_funcs.reset_release)
dmub->hw_funcs.reset_release(dmub);
@ -514,11 +516,10 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
if (!dmub->hw_funcs.is_auto_load_done)
return DMUB_STATUS_OK;
for (i = 0; i <= timeout_us; i += 100) {
if (dmub->hw_funcs.is_auto_load_done(dmub))
union dmub_fw_boot_status status = dmub->hw_funcs.get_fw_status(dmub);
if (status.bits.dal_fw && status.bits.mailbox_rdy)
return DMUB_STATUS_OK;
udelay(100);
@ -527,27 +528,6 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
return DMUB_STATUS_TIMEOUT;
}
enum dmub_status dmub_srv_wait_for_phy_init(struct dmub_srv *dmub,
uint32_t timeout_us)
{
uint32_t i = 0;
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
if (!dmub->hw_funcs.is_phy_init)
return DMUB_STATUS_OK;
for (i = 0; i <= timeout_us; i += 10) {
if (dmub->hw_funcs.is_phy_init(dmub))
return DMUB_STATUS_OK;
udelay(10);
}
return DMUB_STATUS_TIMEOUT;
}
enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub,
uint32_t timeout_us)
{