mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 18:14:07 +08:00
drm/amd/pm: store and reinstate swsmu user power configurations
store swsmu user power configurations which include power limit, clock frequencies, fan speed and fan mode on suspend and reinstate on resume. V2: Addressed Lijo's review comments added a function to set clock interdependencies add check on fan control mode to reapply fan speed V3: Addressed review comments from Alex moved store logic and reinstate function call into swSMU V4: added a logic to keep off storing configurations in suspend V5: Addressed review comments from Lijo add a restore flag give restore priority to mclk comparing fclk and socclk Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
64dcf2f01d
commit
eb3b425166
@ -33,6 +33,8 @@
|
|||||||
#define SMU_TEMPERATURE_UNITS_PER_CENTIGRADES 1000
|
#define SMU_TEMPERATURE_UNITS_PER_CENTIGRADES 1000
|
||||||
#define SMU_FW_NAME_LEN 0x24
|
#define SMU_FW_NAME_LEN 0x24
|
||||||
|
|
||||||
|
#define SMU_DPM_USER_PROFILE_RESTORE (1 << 0)
|
||||||
|
|
||||||
struct smu_hw_power_state {
|
struct smu_hw_power_state {
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
};
|
};
|
||||||
@ -168,6 +170,17 @@ enum smu_memory_pool_size
|
|||||||
SMU_MEMORY_POOL_SIZE_2_GB = 0x80000000,
|
SMU_MEMORY_POOL_SIZE_2_GB = 0x80000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct smu_user_dpm_profile {
|
||||||
|
uint32_t fan_mode;
|
||||||
|
uint32_t power_limit;
|
||||||
|
uint32_t fan_speed_rpm;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
/* user clock state information */
|
||||||
|
uint32_t clk_mask[SMU_CLK_COUNT];
|
||||||
|
uint32_t clk_dependency;
|
||||||
|
};
|
||||||
|
|
||||||
#define SMU_TABLE_INIT(tables, table_id, s, a, d) \
|
#define SMU_TABLE_INIT(tables, table_id, s, a, d) \
|
||||||
do { \
|
do { \
|
||||||
tables[table_id].size = s; \
|
tables[table_id].size = s; \
|
||||||
@ -473,6 +486,8 @@ struct smu_context
|
|||||||
uint32_t cpu_actual_soft_max_freq;
|
uint32_t cpu_actual_soft_max_freq;
|
||||||
uint32_t cpu_core_id_select;
|
uint32_t cpu_core_id_select;
|
||||||
uint16_t cpu_core_num;
|
uint16_t cpu_core_num;
|
||||||
|
|
||||||
|
struct smu_user_dpm_profile user_dpm_profile;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct i2c_adapter;
|
struct i2c_adapter;
|
||||||
|
@ -266,6 +266,119 @@ int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smu_set_user_clk_dependencies - set user profile clock dependencies
|
||||||
|
*
|
||||||
|
* @smu: smu_context pointer
|
||||||
|
* @clk: enum smu_clk_type type
|
||||||
|
*
|
||||||
|
* Enable/Disable the clock dependency for the @clk type.
|
||||||
|
*/
|
||||||
|
static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_type clk)
|
||||||
|
{
|
||||||
|
if (smu->adev->in_suspend)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mclk, fclk and socclk are interdependent
|
||||||
|
* on each other
|
||||||
|
*/
|
||||||
|
if (clk == SMU_MCLK) {
|
||||||
|
/* reset clock dependency */
|
||||||
|
smu->user_dpm_profile.clk_dependency = 0;
|
||||||
|
/* set mclk dependent clocks(fclk and socclk) */
|
||||||
|
smu->user_dpm_profile.clk_dependency = BIT(SMU_FCLK) | BIT(SMU_SOCCLK);
|
||||||
|
} else if (clk == SMU_FCLK) {
|
||||||
|
/* give priority to mclk, if mclk dependent clocks are set */
|
||||||
|
if (smu->user_dpm_profile.clk_dependency == (BIT(SMU_FCLK) | BIT(SMU_SOCCLK)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* reset clock dependency */
|
||||||
|
smu->user_dpm_profile.clk_dependency = 0;
|
||||||
|
/* set fclk dependent clocks(mclk and socclk) */
|
||||||
|
smu->user_dpm_profile.clk_dependency = BIT(SMU_MCLK) | BIT(SMU_SOCCLK);
|
||||||
|
} else if (clk == SMU_SOCCLK) {
|
||||||
|
/* give priority to mclk, if mclk dependent clocks are set */
|
||||||
|
if (smu->user_dpm_profile.clk_dependency == (BIT(SMU_FCLK) | BIT(SMU_SOCCLK)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* reset clock dependency */
|
||||||
|
smu->user_dpm_profile.clk_dependency = 0;
|
||||||
|
/* set socclk dependent clocks(mclk and fclk) */
|
||||||
|
smu->user_dpm_profile.clk_dependency = BIT(SMU_MCLK) | BIT(SMU_FCLK);
|
||||||
|
} else
|
||||||
|
/* add clk dependencies here, if any */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smu_restore_dpm_user_profile - reinstate user dpm profile
|
||||||
|
*
|
||||||
|
* @smu: smu_context pointer
|
||||||
|
*
|
||||||
|
* Restore the saved user power configurations include power limit,
|
||||||
|
* clock frequencies, fan control mode and fan speed.
|
||||||
|
*/
|
||||||
|
static void smu_restore_dpm_user_profile(struct smu_context *smu)
|
||||||
|
{
|
||||||
|
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!smu->adev->in_suspend)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Enable restore flag */
|
||||||
|
smu->user_dpm_profile.flags = SMU_DPM_USER_PROFILE_RESTORE;
|
||||||
|
|
||||||
|
/* set the user dpm power limit */
|
||||||
|
if (smu->user_dpm_profile.power_limit) {
|
||||||
|
ret = smu_set_power_limit(smu, smu->user_dpm_profile.power_limit);
|
||||||
|
if (ret)
|
||||||
|
dev_err(smu->adev->dev, "Failed to set power limit value\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the user dpm clock configurations */
|
||||||
|
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
|
||||||
|
enum smu_clk_type clk_type;
|
||||||
|
|
||||||
|
for (clk_type = 0; clk_type < SMU_CLK_COUNT; clk_type++) {
|
||||||
|
/*
|
||||||
|
* Iterate over smu clk type and force the saved user clk
|
||||||
|
* configs, skip if clock dependency is enabled
|
||||||
|
*/
|
||||||
|
if (!(smu->user_dpm_profile.clk_dependency & BIT(clk_type)) &&
|
||||||
|
smu->user_dpm_profile.clk_mask[clk_type]) {
|
||||||
|
ret = smu_force_clk_levels(smu, clk_type,
|
||||||
|
smu->user_dpm_profile.clk_mask[clk_type]);
|
||||||
|
if (ret)
|
||||||
|
dev_err(smu->adev->dev, "Failed to set clock type = %d\n",
|
||||||
|
clk_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the user dpm fan configurations */
|
||||||
|
if (smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_MANUAL) {
|
||||||
|
ret = smu_set_fan_control_mode(smu, smu->user_dpm_profile.fan_mode);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(smu->adev->dev, "Failed to set manual fan control mode\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret && smu->user_dpm_profile.fan_speed_rpm) {
|
||||||
|
ret = smu_set_fan_speed_rpm(smu, smu->user_dpm_profile.fan_speed_rpm);
|
||||||
|
if (ret)
|
||||||
|
dev_err(smu->adev->dev, "Failed to set manual fan speed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable restore flag */
|
||||||
|
smu->user_dpm_profile.flags &= ~SMU_DPM_USER_PROFILE_RESTORE;
|
||||||
|
}
|
||||||
|
|
||||||
int smu_get_power_num_states(struct smu_context *smu,
|
int smu_get_power_num_states(struct smu_context *smu,
|
||||||
struct pp_states_info *state_info)
|
struct pp_states_info *state_info)
|
||||||
{
|
{
|
||||||
@ -529,6 +642,8 @@ static int smu_late_init(void *handle)
|
|||||||
AMD_PP_TASK_COMPLETE_INIT,
|
AMD_PP_TASK_COMPLETE_INIT,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
smu_restore_dpm_user_profile(smu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1622,6 +1737,12 @@ int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_lev
|
|||||||
|
|
||||||
mutex_unlock(&smu->mutex);
|
mutex_unlock(&smu->mutex);
|
||||||
|
|
||||||
|
/* reset user dpm clock state */
|
||||||
|
if (!ret && smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
|
||||||
|
memset(smu->user_dpm_profile.clk_mask, 0, sizeof(smu->user_dpm_profile.clk_mask));
|
||||||
|
smu->user_dpm_profile.clk_dependency = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1656,8 +1777,13 @@ int smu_force_clk_levels(struct smu_context *smu,
|
|||||||
|
|
||||||
mutex_lock(&smu->mutex);
|
mutex_lock(&smu->mutex);
|
||||||
|
|
||||||
if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels)
|
if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels) {
|
||||||
ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask);
|
ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask);
|
||||||
|
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE) {
|
||||||
|
smu->user_dpm_profile.clk_mask[clk_type] = mask;
|
||||||
|
smu_set_user_clk_dependencies(smu, clk_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&smu->mutex);
|
mutex_unlock(&smu->mutex);
|
||||||
|
|
||||||
@ -1906,8 +2032,11 @@ int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed)
|
|||||||
|
|
||||||
mutex_lock(&smu->mutex);
|
mutex_lock(&smu->mutex);
|
||||||
|
|
||||||
if (smu->ppt_funcs->set_fan_speed_rpm)
|
if (smu->ppt_funcs->set_fan_speed_rpm) {
|
||||||
ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed);
|
ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed);
|
||||||
|
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||||
|
smu->user_dpm_profile.fan_speed_rpm = speed;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&smu->mutex);
|
mutex_unlock(&smu->mutex);
|
||||||
|
|
||||||
@ -1949,8 +2078,11 @@ int smu_set_power_limit(struct smu_context *smu, uint32_t limit)
|
|||||||
if (!limit)
|
if (!limit)
|
||||||
limit = smu->current_power_limit;
|
limit = smu->current_power_limit;
|
||||||
|
|
||||||
if (smu->ppt_funcs->set_power_limit)
|
if (smu->ppt_funcs->set_power_limit) {
|
||||||
ret = smu->ppt_funcs->set_power_limit(smu, limit);
|
ret = smu->ppt_funcs->set_power_limit(smu, limit);
|
||||||
|
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||||
|
smu->user_dpm_profile.power_limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&smu->mutex);
|
mutex_unlock(&smu->mutex);
|
||||||
@ -2127,11 +2259,19 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value)
|
|||||||
|
|
||||||
mutex_lock(&smu->mutex);
|
mutex_lock(&smu->mutex);
|
||||||
|
|
||||||
if (smu->ppt_funcs->set_fan_control_mode)
|
if (smu->ppt_funcs->set_fan_control_mode) {
|
||||||
ret = smu->ppt_funcs->set_fan_control_mode(smu, value);
|
ret = smu->ppt_funcs->set_fan_control_mode(smu, value);
|
||||||
|
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||||
|
smu->user_dpm_profile.fan_mode = value;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&smu->mutex);
|
mutex_unlock(&smu->mutex);
|
||||||
|
|
||||||
|
/* reset user dpm fan speed */
|
||||||
|
if (!ret && value != AMD_FAN_CTRL_MANUAL &&
|
||||||
|
smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||||
|
smu->user_dpm_profile.fan_speed_rpm = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user