mirror of
https://github.com/torvalds/linux.git
synced 2024-09-20 06:53:04 +00:00
drm/amd/display: Notify DMCUB of D0/D3 state
[Why] We want to avoid arming the HPD timer in firmware when preparing for S0i3 entry when DC is considered in D3. [How] Notify DMCUB of the power state transitions so it can decide to arm the HPD timer for idle in DCN35 only in D0. Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Ovidiu Bunea <Ovidiu.Bunea@amd.com> Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
4437936c6b
commit
9793a4a6e5
|
@ -5161,6 +5161,8 @@ void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state)
|
|||
|
||||
dc_z10_restore(dc);
|
||||
|
||||
dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state);
|
||||
|
||||
dc->hwss.init_hw(dc);
|
||||
|
||||
if (dc->hwss.init_sys_ctx != NULL &&
|
||||
|
@ -5172,6 +5174,8 @@ void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state)
|
|||
default:
|
||||
ASSERT(dc->current_state->stream_count == 0);
|
||||
|
||||
dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state);
|
||||
|
||||
dc_state_destruct(dc->current_state);
|
||||
|
||||
break;
|
||||
|
|
|
@ -1476,7 +1476,7 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
|||
ips2_exit_count);
|
||||
}
|
||||
|
||||
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState)
|
||||
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state power_state)
|
||||
{
|
||||
struct dmub_srv *dmub;
|
||||
|
||||
|
@ -1485,12 +1485,38 @@ void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_c
|
|||
|
||||
dmub = dc_dmub_srv->dmub;
|
||||
|
||||
if (powerState == DC_ACPI_CM_POWER_STATE_D0)
|
||||
if (power_state == DC_ACPI_CM_POWER_STATE_D0)
|
||||
dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D0);
|
||||
else
|
||||
dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3);
|
||||
}
|
||||
|
||||
void dc_dmub_srv_notify_fw_dc_power_state(struct dc_dmub_srv *dc_dmub_srv,
|
||||
enum dc_acpi_cm_power_state power_state)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
|
||||
if (!dc_dmub_srv)
|
||||
return;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.idle_opt_set_dc_power_state.header.type = DMUB_CMD__IDLE_OPT;
|
||||
cmd.idle_opt_set_dc_power_state.header.sub_type = DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE;
|
||||
cmd.idle_opt_set_dc_power_state.header.payload_bytes =
|
||||
sizeof(cmd.idle_opt_set_dc_power_state) - sizeof(cmd.idle_opt_set_dc_power_state.header);
|
||||
|
||||
if (power_state == DC_ACPI_CM_POWER_STATE_D0) {
|
||||
cmd.idle_opt_set_dc_power_state.data.power_state = DMUB_IDLE_OPT_DC_POWER_STATE_D0;
|
||||
} else if (power_state == DC_ACPI_CM_POWER_STATE_D3) {
|
||||
cmd.idle_opt_set_dc_power_state.data.power_state = DMUB_IDLE_OPT_DC_POWER_STATE_D3;
|
||||
} else {
|
||||
cmd.idle_opt_set_dc_power_state.data.power_state = DMUB_IDLE_OPT_DC_POWER_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_should_detect(struct dc_dmub_srv *dc_dmub_srv)
|
||||
{
|
||||
volatile const struct dmub_shared_state_ips_fw *ips_fw;
|
||||
|
|
|
@ -109,7 +109,29 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait);
|
|||
|
||||
void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle);
|
||||
|
||||
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState);
|
||||
/**
|
||||
* dc_dmub_srv_set_power_state() - Sets the power state for DMUB service.
|
||||
*
|
||||
* Controls whether messaging the DMCUB or interfacing with it via HW register
|
||||
* interaction is permittable.
|
||||
*
|
||||
* @dc_dmub_srv - The DC DMUB service pointer
|
||||
* @power_state - the DC power state
|
||||
*/
|
||||
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state power_state);
|
||||
|
||||
/**
|
||||
* dc_dmub_srv_notify_fw_dc_power_state() - Notifies firmware of the DC power state.
|
||||
*
|
||||
* Differs from dc_dmub_srv_set_power_state in that it needs to access HW in order
|
||||
* to message DMCUB of the state transition. Should come after the D0 exit and
|
||||
* before D3 set power state.
|
||||
*
|
||||
* @dc_dmub_srv - The DC DMUB service pointer
|
||||
* @power_state - the DC power state
|
||||
*/
|
||||
void dc_dmub_srv_notify_fw_dc_power_state(struct dc_dmub_srv *dc_dmub_srv,
|
||||
enum dc_acpi_cm_power_state power_state);
|
||||
|
||||
/**
|
||||
* @dc_dmub_srv_should_detect() - Checks if link detection is required.
|
||||
|
|
|
@ -1879,7 +1879,12 @@ enum dmub_cmd_idle_opt_type {
|
|||
/**
|
||||
* DCN hardware notify idle.
|
||||
*/
|
||||
DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE = 2
|
||||
DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE = 2,
|
||||
|
||||
/**
|
||||
* DCN hardware notify power state.
|
||||
*/
|
||||
DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1906,6 +1911,33 @@ struct dmub_rb_cmd_idle_opt_dcn_notify_idle {
|
|||
struct dmub_dcn_notify_idle_cntl_data cntl_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dmub_idle_opt_dc_power_state - DC power states.
|
||||
*/
|
||||
enum dmub_idle_opt_dc_power_state {
|
||||
DMUB_IDLE_OPT_DC_POWER_STATE_UNKNOWN = 0,
|
||||
DMUB_IDLE_OPT_DC_POWER_STATE_D0 = 1,
|
||||
DMUB_IDLE_OPT_DC_POWER_STATE_D1 = 2,
|
||||
DMUB_IDLE_OPT_DC_POWER_STATE_D2 = 4,
|
||||
DMUB_IDLE_OPT_DC_POWER_STATE_D3 = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dmub_idle_opt_set_dc_power_state_data - Data passed to FW in a DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE command.
|
||||
*/
|
||||
struct dmub_idle_opt_set_dc_power_state_data {
|
||||
uint8_t power_state; /**< power state */
|
||||
uint8_t pad[3]; /**< padding */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dmub_rb_cmd_idle_opt_set_dc_power_state - Data passed to FW in a DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE command.
|
||||
*/
|
||||
struct dmub_rb_cmd_idle_opt_set_dc_power_state {
|
||||
struct dmub_cmd_header header; /**< header */
|
||||
struct dmub_idle_opt_set_dc_power_state_data data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dmub_clocks - Clock update notification.
|
||||
*/
|
||||
|
@ -5298,6 +5330,10 @@ union dmub_rb_cmd {
|
|||
* Definition of a DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE command.
|
||||
*/
|
||||
struct dmub_rb_cmd_idle_opt_dcn_notify_idle idle_opt_notify_idle;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE command.
|
||||
*/
|
||||
struct dmub_rb_cmd_idle_opt_set_dc_power_state idle_opt_set_dc_power_state;
|
||||
/*
|
||||
* Definition of a DMUB_CMD__REPLAY_COPY_SETTINGS command.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user