Commit 18d7ab98 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher

drm/amd/powerplay: support custom power profile setting

Support custom power profile mode settings on Arcturus.
Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c103c5a3
......@@ -179,6 +179,7 @@ static struct smu_11_0_cmn2aisc_mapping arcturus_table_map[SMU_TABLE_COUNT] = {
TAB_MAP(DRIVER_SMU_CONFIG),
TAB_MAP(OVERDRIVE),
TAB_MAP(I2C_COMMANDS),
TAB_MAP(ACTIVITY_MONITOR_COEFF),
};
static struct smu_11_0_cmn2aisc_mapping arcturus_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
......@@ -302,6 +303,10 @@ static int arcturus_tables_init(struct smu_context *smu, struct smu_table *table
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
if (!smu_table->metrics_table)
return -ENOMEM;
......@@ -1313,6 +1318,7 @@ static int arcturus_get_power_limit(struct smu_context *smu,
static int arcturus_get_power_profile_mode(struct smu_context *smu,
char *buf)
{
DpmActivityMonitorCoeffInt_t activity_monitor;
static const char *profile_name[] = {
"BOOTUP_DEFAULT",
"3D_FULL_SCREEN",
......@@ -1322,14 +1328,35 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
"COMPUTE",
"CUSTOM"};
static const char *title[] = {
"PROFILE_INDEX(NAME)"};
"PROFILE_INDEX(NAME)",
"CLOCK_TYPE(NAME)",
"FPS",
"UseRlcBusy",
"MinActiveFreqType",
"MinActiveFreq",
"BoosterFreqType",
"BoosterFreq",
"PD_Data_limit_c",
"PD_Data_error_coeff",
"PD_Data_error_rate_coeff"};
uint32_t i, size = 0;
int16_t workload_type = 0;
int result = 0;
uint32_t smu_version;
if (!smu->pm_enabled || !buf)
if (!buf)
return -EINVAL;
size += sprintf(buf + size, "%16s\n",
result = smu_get_smc_version(smu, NULL, &smu_version);
if (result)
return result;
if (smu_version >= 0x360d00)
size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
title[0], title[1], title[2], title[3], title[4], title[5],
title[6], title[7], title[8], title[9], title[10]);
else
size += sprintf(buf + size, "%16s\n",
title[0]);
for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
......@@ -1341,8 +1368,50 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
if (workload_type < 0)
continue;
if (smu_version >= 0x360d00) {
result = smu_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
workload_type,
(void *)(&activity_monitor),
false);
if (result) {
pr_err("[%s] Failed to get activity monitor!", __func__);
return result;
}
}
size += sprintf(buf + size, "%2d %14s%s\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
if (smu_version >= 0x360d00) {
size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
"GFXCLK",
activity_monitor.Gfx_FPS,
activity_monitor.Gfx_UseRlcBusy,
activity_monitor.Gfx_MinActiveFreqType,
activity_monitor.Gfx_MinActiveFreq,
activity_monitor.Gfx_BoosterFreqType,
activity_monitor.Gfx_BoosterFreq,
activity_monitor.Gfx_PD_Data_limit_c,
activity_monitor.Gfx_PD_Data_error_coeff,
activity_monitor.Gfx_PD_Data_error_rate_coeff);
size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
1,
"UCLK",
activity_monitor.Mem_FPS,
activity_monitor.Mem_UseRlcBusy,
activity_monitor.Mem_MinActiveFreqType,
activity_monitor.Mem_MinActiveFreq,
activity_monitor.Mem_BoosterFreqType,
activity_monitor.Mem_BoosterFreq,
activity_monitor.Mem_PD_Data_limit_c,
activity_monitor.Mem_PD_Data_error_coeff,
activity_monitor.Mem_PD_Data_error_rate_coeff);
}
}
return size;
......@@ -1352,18 +1421,69 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
long *input,
uint32_t size)
{
DpmActivityMonitorCoeffInt_t activity_monitor;
int workload_type = 0;
uint32_t profile_mode = input[size];
int ret = 0;
if (!smu->pm_enabled)
return -EINVAL;
uint32_t smu_version;
if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
pr_err("Invalid power profile mode %d\n", profile_mode);
return -EINVAL;
}
ret = smu_get_smc_version(smu, NULL, &smu_version);
if (ret)
return ret;
if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
(smu_version >=0x360d00)) {
ret = smu_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
WORKLOAD_PPLIB_CUSTOM_BIT,
(void *)(&activity_monitor),
false);
if (ret) {
pr_err("[%s] Failed to get activity monitor!", __func__);
return ret;
}
switch (input[0]) {
case 0: /* Gfxclk */
activity_monitor.Gfx_FPS = input[1];
activity_monitor.Gfx_UseRlcBusy = input[2];
activity_monitor.Gfx_MinActiveFreqType = input[3];
activity_monitor.Gfx_MinActiveFreq = input[4];
activity_monitor.Gfx_BoosterFreqType = input[5];
activity_monitor.Gfx_BoosterFreq = input[6];
activity_monitor.Gfx_PD_Data_limit_c = input[7];
activity_monitor.Gfx_PD_Data_error_coeff = input[8];
activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
break;
case 1: /* Uclk */
activity_monitor.Mem_FPS = input[1];
activity_monitor.Mem_UseRlcBusy = input[2];
activity_monitor.Mem_MinActiveFreqType = input[3];
activity_monitor.Mem_MinActiveFreq = input[4];
activity_monitor.Mem_BoosterFreqType = input[5];
activity_monitor.Mem_BoosterFreq = input[6];
activity_monitor.Mem_PD_Data_limit_c = input[7];
activity_monitor.Mem_PD_Data_error_coeff = input[8];
activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
break;
}
ret = smu_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
WORKLOAD_PPLIB_CUSTOM_BIT,
(void *)(&activity_monitor),
true);
if (ret) {
pr_err("[%s] Failed to set activity monitor!", __func__);
return ret;
}
}
/*
* Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
* Not all profile modes are supported on arcturus.
......
......@@ -823,7 +823,6 @@ typedef struct {
uint32_t MmHubPadding[8]; // SMU internal use
} AvfsFuseOverride_t;
/* NOT CURRENTLY USED
typedef struct {
uint8_t Gfx_ActiveHystLimit;
uint8_t Gfx_IdleHystLimit;
......@@ -866,7 +865,6 @@ typedef struct {
uint32_t MmHubPadding[8]; // SMU internal use
} DpmActivityMonitorCoeffInt_t;
*/
// These defines are used with the following messages:
// SMC_MSG_TransferTableDram2Smu
......@@ -878,11 +876,11 @@ typedef struct {
#define TABLE_PMSTATUSLOG 4
#define TABLE_SMU_METRICS 5
#define TABLE_DRIVER_SMU_CONFIG 6
//#define TABLE_ACTIVITY_MONITOR_COEFF 7
#define TABLE_OVERDRIVE 7
#define TABLE_WAFL_XGMI_TOPOLOGY 8
#define TABLE_I2C_COMMANDS 9
#define TABLE_COUNT 10
#define TABLE_ACTIVITY_MONITOR_COEFF 10
#define TABLE_COUNT 11
// These defines are used with the SMC_MSG_SetUclkFastSwitch message.
typedef enum {
......
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