Commit 5d24af84 authored by Rex Zhu's avatar Rex Zhu Committed by Alex Deucher

drm/amd/pp: Implement get/set_power_profile_mode on smu7

It show what parameters can be configured to tune
the behavior of natural dpm for perf/watt on smu7.

user can select the mode per workload, but even the default per
workload settings are not bulletproof.

user can configure custom settings per different use case
for better perf or better perf/watt.

cat pp_power_profile_mode
NUM        MODE_NAME     SCLK_UP_HYST   SCLK_DOWN_HYST SCLK_ACTIVE_LEVEL     MCLK_UP_HYST   MCLK_DOWN_HYST MCLK_ACTIVE_LEVEL
  0   3D_FULL_SCREEN:        0              100               30                0              100               10
  1     POWER_SAVING:       10                0               30                -                -                -
  2            VIDEO:        -                -                -               10               16               31
  3               VR:        0               11               50                0              100               10
  4          COMPUTE:        0                5               30                -                -                -
  5           CUSTOM:        0                0                0                0                0                0
  *          CURRENT:        0              100               30                0              100               10

Under manual dpm level,

user can echo "0/1/2/3/4">pp_power_profile_mode
to select 3D_FULL_SCREEN/POWER_SAVING/VIDEO/VR/COMPUTE
mode.

echo "5 * * * * * * * *">pp_power_profile_mode
to set custom settings.
"5 * * * * * * * *" mean "CUSTOM enable_sclk SCLK_UP_HYST
SCLK_DOWN_HYST SCLK_ACTIVE_LEVEL enable_mclk MCLK_UP_HYST
MCLK_DOWN_HYST MCLK_ACTIVE_LEVEL"

if the parameter enable_sclk/enable_mclk is true,
driver will update the following parameters to dpm table.
if false, ignore the following parameters.
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarRex Zhu <Rex.Zhu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6dcd30aa
......@@ -80,6 +80,13 @@
#define PCIE_BUS_CLK 10000
#define TCLK (PCIE_BUS_CLK / 10)
static const struct profile_mode_setting smu7_profiling[5] =
{{1, 0, 100, 30, 1, 0, 100, 10},
{1, 10, 0, 30, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 10, 16, 31},
{1, 0, 11, 50, 1, 0, 100, 10},
{1, 0, 5, 30, 0, 0, 0, 0},
};
/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
enum DPM_EVENT_SRC {
......@@ -2459,6 +2466,9 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
smu7_patch_voltage_workaround(hwmgr);
smu7_init_dpm_defaults(hwmgr);
hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
/* Get leakage voltage based on leakage ID. */
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EVV)) {
......@@ -4895,6 +4905,137 @@ static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
return 0;
}
static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
uint32_t i, size = 0;
uint32_t len;
static const char *profile_name[6] = {"3D_FULL_SCREEN",
"POWER_SAVING",
"VIDEO",
"VR",
"COMPUTE",
"CUSTOM"};
static const char *title[8] = {"NUM",
"MODE_NAME",
"SCLK_UP_HYST",
"SCLK_DOWN_HYST",
"SCLK_ACTIVE_LEVEL",
"MCLK_UP_HYST",
"MCLK_DOWN_HYST",
"MCLK_ACTIVE_LEVEL"};
if (!buf)
return -EINVAL;
size += sprintf(buf + size, "%s %16s %16s %16s %16s %16s %16s %16s\n",
title[0], title[1], title[2], title[3],
title[4], title[5], title[6], title[7]);
len = sizeof(smu7_profiling) / sizeof(struct profile_mode_setting);
for (i = 0; i < len; i++) {
if (smu7_profiling[i].bupdate_sclk)
size += sprintf(buf + size, "%3d %16s: %8d %16d %16d ",
i, profile_name[i], smu7_profiling[i].sclk_up_hyst,
smu7_profiling[i].sclk_down_hyst,
smu7_profiling[i].sclk_activity);
else
size += sprintf(buf + size, "%3d %16s: %8s %16s %16s ",
i, profile_name[i], "-", "-", "-");
if (smu7_profiling[i].bupdate_mclk)
size += sprintf(buf + size, "%16d %16d %16d\n",
smu7_profiling[i].mclk_up_hyst,
smu7_profiling[i].mclk_down_hyst,
smu7_profiling[i].mclk_activity);
else
size += sprintf(buf + size, "%16s %16s %16s\n",
"-", "-", "-");
}
size += sprintf(buf + size, "%3d %16s: %8d %16d %16d %16d %16d %16d\n",
i, profile_name[i],
data->custom_profile_setting.sclk_up_hyst,
data->custom_profile_setting.sclk_down_hyst,
data->custom_profile_setting.sclk_activity,
data->custom_profile_setting.mclk_up_hyst,
data->custom_profile_setting.mclk_down_hyst,
data->custom_profile_setting.mclk_activity);
size += sprintf(buf + size, "%3s %16s: %8d %16d %16d %16d %16d %16d\n",
"*", "CURRENT",
data->current_profile_setting.sclk_up_hyst,
data->current_profile_setting.sclk_down_hyst,
data->current_profile_setting.sclk_activity,
data->current_profile_setting.mclk_up_hyst,
data->current_profile_setting.mclk_down_hyst,
data->current_profile_setting.mclk_activity);
return size;
}
static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct profile_mode_setting tmp;
enum PP_SMC_POWER_PROFILE mode;
if (input == NULL)
return -EINVAL;
mode = input[size];
switch (mode) {
case PP_SMC_POWER_PROFILE_CUSTOM:
if (size < 8)
return -EINVAL;
data->custom_profile_setting.bupdate_sclk = input[0];
data->custom_profile_setting.sclk_up_hyst = input[1];
data->custom_profile_setting.sclk_down_hyst = input[2];
data->custom_profile_setting.sclk_activity = input[3];
data->custom_profile_setting.bupdate_mclk = input[4];
data->custom_profile_setting.mclk_up_hyst = input[5];
data->custom_profile_setting.mclk_down_hyst = input[6];
data->custom_profile_setting.mclk_activity = input[7];
if (!smum_update_dpm_settings(hwmgr, &data->custom_profile_setting)) {
memcpy(&data->current_profile_setting, &data->custom_profile_setting, sizeof(struct profile_mode_setting));
hwmgr->power_profile_mode = mode;
}
break;
case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
case PP_SMC_POWER_PROFILE_POWERSAVING:
case PP_SMC_POWER_PROFILE_VIDEO:
case PP_SMC_POWER_PROFILE_VR:
case PP_SMC_POWER_PROFILE_COMPUTE:
if (mode == hwmgr->power_profile_mode)
return 0;
memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting));
if (!smum_update_dpm_settings(hwmgr, &tmp)) {
if (tmp.bupdate_sclk) {
data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk;
data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst;
data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst;
data->current_profile_setting.sclk_activity = tmp.sclk_activity;
}
if (tmp.bupdate_mclk) {
data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk;
data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst;
data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst;
data->current_profile_setting.mclk_activity = tmp.mclk_activity;
}
hwmgr->power_profile_mode = mode;
}
break;
default:
return -EINVAL;
}
return 0;
}
static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
.backend_init = &smu7_hwmgr_backend_init,
......@@ -4951,6 +5092,8 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
.get_thermal_temperature_range = smu7_get_thermal_temperature_range,
.odn_edit_dpm_table = smu7_odn_edit_dpm_table,
.set_power_limit = smu7_set_power_limit,
.get_power_profile_mode = smu7_get_power_profile_mode,
.set_power_profile_mode = smu7_set_power_profile_mode,
};
uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
......
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