mirror of
https://github.com/torvalds/linux.git
synced 2024-09-20 06:53:04 +00:00
drm/amd/pm: add overdrive support on smu v14.0.2/3
add overdrive support on smu v14.0.2/3 Signed-off-by: Kenneth Feng <kenneth.feng@amd.com> Reviewed-by: Yang Wang <kevinyang.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
8141f21b94
commit
9710b84e2a
|
@ -452,17 +452,26 @@ int smu_v14_0_init_smc_tables(struct smu_context *smu)
|
|||
ret = -ENOMEM;
|
||||
goto err3_out;
|
||||
}
|
||||
|
||||
smu_table->user_overdrive_table =
|
||||
kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
|
||||
if (!smu_table->user_overdrive_table) {
|
||||
ret = -ENOMEM;
|
||||
goto err4_out;
|
||||
}
|
||||
}
|
||||
|
||||
smu_table->combo_pptable =
|
||||
kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL);
|
||||
if (!smu_table->combo_pptable) {
|
||||
ret = -ENOMEM;
|
||||
goto err4_out;
|
||||
goto err5_out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err5_out:
|
||||
kfree(smu_table->user_overdrive_table);
|
||||
err4_out:
|
||||
kfree(smu_table->boot_overdrive_table);
|
||||
err3_out:
|
||||
|
|
|
@ -68,6 +68,18 @@
|
|||
#define DEBUGSMC_MSG_Mode1Reset 2
|
||||
#define LINK_SPEED_MAX 3
|
||||
|
||||
#define PP_OD_FEATURE_GFXCLK_FMIN 0
|
||||
#define PP_OD_FEATURE_GFXCLK_FMAX 1
|
||||
#define PP_OD_FEATURE_UCLK_FMIN 2
|
||||
#define PP_OD_FEATURE_UCLK_FMAX 3
|
||||
#define PP_OD_FEATURE_GFX_VF_CURVE 4
|
||||
#define PP_OD_FEATURE_FAN_CURVE_TEMP 5
|
||||
#define PP_OD_FEATURE_FAN_CURVE_PWM 6
|
||||
#define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7
|
||||
#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8
|
||||
#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9
|
||||
#define PP_OD_FEATURE_FAN_MINIMUM_PWM 10
|
||||
|
||||
static struct cmn2asic_msg_mapping smu_v14_0_2_message_map[SMU_MSG_MAX_COUNT] = {
|
||||
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
|
||||
MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
|
||||
|
@ -204,6 +216,7 @@ static struct cmn2asic_mapping smu_v14_0_2_table_map[SMU_TABLE_COUNT] = {
|
|||
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
|
||||
TAB_MAP(I2C_COMMANDS),
|
||||
TAB_MAP(ECCINFO),
|
||||
TAB_MAP(OVERDRIVE),
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v14_0_2_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
|
||||
|
@ -1029,16 +1042,97 @@ static int smu_v14_0_2_get_current_clk_freq_by_table(struct smu_context *smu,
|
|||
value);
|
||||
}
|
||||
|
||||
static bool smu_v14_0_2_is_od_feature_supported(struct smu_context *smu,
|
||||
int od_feature_bit)
|
||||
{
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
const OverDriveLimits_t * const overdrive_upperlimits =
|
||||
&pptable->SkuTable.OverDriveLimitsBasicMax;
|
||||
|
||||
return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
|
||||
}
|
||||
|
||||
static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
|
||||
int od_feature_bit,
|
||||
int32_t *min,
|
||||
int32_t *max)
|
||||
{
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
const OverDriveLimits_t * const overdrive_upperlimits =
|
||||
&pptable->SkuTable.OverDriveLimitsBasicMax;
|
||||
const OverDriveLimits_t * const overdrive_lowerlimits =
|
||||
&pptable->SkuTable.OverDriveLimitsBasicMin;
|
||||
int32_t od_min_setting, od_max_setting;
|
||||
|
||||
switch (od_feature_bit) {
|
||||
case PP_OD_FEATURE_GFXCLK_FMIN:
|
||||
od_min_setting = overdrive_lowerlimits->GfxclkFmin;
|
||||
od_max_setting = overdrive_upperlimits->GfxclkFmin;
|
||||
break;
|
||||
case PP_OD_FEATURE_GFXCLK_FMAX:
|
||||
od_min_setting = overdrive_lowerlimits->GfxclkFmax;
|
||||
od_max_setting = overdrive_upperlimits->GfxclkFmax;
|
||||
break;
|
||||
case PP_OD_FEATURE_UCLK_FMIN:
|
||||
od_min_setting = overdrive_lowerlimits->UclkFmin;
|
||||
od_max_setting = overdrive_upperlimits->UclkFmin;
|
||||
break;
|
||||
case PP_OD_FEATURE_UCLK_FMAX:
|
||||
od_min_setting = overdrive_lowerlimits->UclkFmax;
|
||||
od_max_setting = overdrive_upperlimits->UclkFmax;
|
||||
break;
|
||||
case PP_OD_FEATURE_GFX_VF_CURVE:
|
||||
od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary[0];
|
||||
od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary[0];
|
||||
break;
|
||||
case PP_OD_FEATURE_FAN_CURVE_TEMP:
|
||||
od_min_setting = overdrive_lowerlimits->FanLinearTempPoints[0];
|
||||
od_max_setting = overdrive_upperlimits->FanLinearTempPoints[0];
|
||||
break;
|
||||
case PP_OD_FEATURE_FAN_CURVE_PWM:
|
||||
od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints[0];
|
||||
od_max_setting = overdrive_upperlimits->FanLinearPwmPoints[0];
|
||||
break;
|
||||
case PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT:
|
||||
od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold;
|
||||
od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold;
|
||||
break;
|
||||
case PP_OD_FEATURE_FAN_ACOUSTIC_TARGET:
|
||||
od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold;
|
||||
od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold;
|
||||
break;
|
||||
case PP_OD_FEATURE_FAN_TARGET_TEMPERATURE:
|
||||
od_min_setting = overdrive_lowerlimits->FanTargetTemperature;
|
||||
od_max_setting = overdrive_upperlimits->FanTargetTemperature;
|
||||
break;
|
||||
case PP_OD_FEATURE_FAN_MINIMUM_PWM:
|
||||
od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
|
||||
od_max_setting = overdrive_upperlimits->FanMinimumPwm;
|
||||
break;
|
||||
default:
|
||||
od_min_setting = od_max_setting = INT_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
if (min)
|
||||
*min = od_min_setting;
|
||||
if (max)
|
||||
*max = od_max_setting;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_print_clk_levels(struct smu_context *smu,
|
||||
enum smu_clk_type clk_type,
|
||||
char *buf)
|
||||
{
|
||||
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
|
||||
struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context;
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
|
||||
struct smu_14_0_dpm_table *single_dpm_table;
|
||||
struct smu_14_0_pcie_table *pcie_table;
|
||||
uint32_t gen_speed, lane_width;
|
||||
int i, curr_freq, size = 0;
|
||||
int32_t min_value, max_value;
|
||||
int ret = 0;
|
||||
|
||||
smu_cmn_get_sysfs_buf(&buf, &size);
|
||||
|
@ -1159,6 +1253,183 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu,
|
|||
"*" : "");
|
||||
break;
|
||||
|
||||
case SMU_OD_SCLK:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_GFXCLK_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
|
||||
size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
|
||||
od_table->OverDriveTable.GfxclkFmin,
|
||||
od_table->OverDriveTable.GfxclkFmax);
|
||||
break;
|
||||
|
||||
case SMU_OD_MCLK:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_UCLK_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
|
||||
size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n",
|
||||
od_table->OverDriveTable.UclkFmin,
|
||||
od_table->OverDriveTable.UclkFmax);
|
||||
break;
|
||||
|
||||
case SMU_OD_VDDGFX_OFFSET:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_GFX_VF_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "OD_VDDGFX_OFFSET:\n");
|
||||
size += sysfs_emit_at(buf, size, "%dmV\n",
|
||||
od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[0]);
|
||||
break;
|
||||
|
||||
case SMU_OD_FAN_CURVE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "OD_FAN_CURVE:\n");
|
||||
for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++)
|
||||
size += sysfs_emit_at(buf, size, "%d: %dC %d%%\n",
|
||||
i,
|
||||
(int)od_table->OverDriveTable.FanLinearTempPoints[i],
|
||||
(int)od_table->OverDriveTable.FanLinearPwmPoints[i]);
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_TEMP,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "FAN_CURVE(hotspot temp): %uC %uC\n",
|
||||
min_value, max_value);
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_PWM,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "FAN_CURVE(fan speed): %u%% %u%%\n",
|
||||
min_value, max_value);
|
||||
|
||||
break;
|
||||
|
||||
case SMU_OD_ACOUSTIC_LIMIT:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_LIMIT:\n");
|
||||
size += sysfs_emit_at(buf, size, "%d\n",
|
||||
(int)od_table->OverDriveTable.AcousticLimitRpmThreshold);
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "ACOUSTIC_LIMIT: %u %u\n",
|
||||
min_value, max_value);
|
||||
break;
|
||||
|
||||
case SMU_OD_ACOUSTIC_TARGET:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_TARGET:\n");
|
||||
size += sysfs_emit_at(buf, size, "%d\n",
|
||||
(int)od_table->OverDriveTable.AcousticTargetRpmThreshold);
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_ACOUSTIC_TARGET,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "ACOUSTIC_TARGET: %u %u\n",
|
||||
min_value, max_value);
|
||||
break;
|
||||
|
||||
case SMU_OD_FAN_TARGET_TEMPERATURE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "FAN_TARGET_TEMPERATURE:\n");
|
||||
size += sysfs_emit_at(buf, size, "%d\n",
|
||||
(int)od_table->OverDriveTable.FanTargetTemperature);
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_TARGET_TEMPERATURE,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n",
|
||||
min_value, max_value);
|
||||
break;
|
||||
|
||||
case SMU_OD_FAN_MINIMUM_PWM:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n");
|
||||
size += sysfs_emit_at(buf, size, "%d\n",
|
||||
(int)od_table->OverDriveTable.FanMinimumPwm);
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_MINIMUM_PWM,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n",
|
||||
min_value, max_value);
|
||||
break;
|
||||
|
||||
case SMU_OD_RANGE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
|
||||
!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
|
||||
!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT))
|
||||
break;
|
||||
|
||||
size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
|
||||
|
||||
if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_GFXCLK_FMIN,
|
||||
&min_value,
|
||||
NULL);
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_GFXCLK_FMAX,
|
||||
NULL,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
|
||||
min_value, max_value);
|
||||
}
|
||||
|
||||
if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_UCLK_FMIN,
|
||||
&min_value,
|
||||
NULL);
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_UCLK_FMAX,
|
||||
NULL,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
|
||||
min_value, max_value);
|
||||
}
|
||||
|
||||
if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_GFX_VF_CURVE,
|
||||
&min_value,
|
||||
&max_value);
|
||||
size += sysfs_emit_at(buf, size, "VDDGFX_OFFSET: %7dmv %10dmv\n",
|
||||
min_value, max_value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1400,7 +1671,27 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
|
|||
uint32_t *max_power_limit,
|
||||
uint32_t *min_power_limit)
|
||||
{
|
||||
// TODO
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
PPTable_t *pptable = table_context->driver_pptable;
|
||||
CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
|
||||
uint32_t power_limit;
|
||||
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
|
||||
if (smu_v14_0_get_current_power_limit(smu, &power_limit))
|
||||
power_limit = smu->adev->pm.ac_power ?
|
||||
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
|
||||
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
|
||||
|
||||
if (current_power_limit)
|
||||
*current_power_limit = power_limit;
|
||||
if (default_power_limit)
|
||||
*default_power_limit = power_limit;
|
||||
|
||||
if (max_power_limit)
|
||||
*max_power_limit = msg_limit;
|
||||
|
||||
if (min_power_limit)
|
||||
*min_power_limit = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1950,6 +2241,594 @@ static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu,
|
|||
return sizeof(struct gpu_metrics_v1_3);
|
||||
}
|
||||
|
||||
static void smu_v14_0_2_dump_od_table(struct smu_context *smu,
|
||||
OverDriveTableExternal_t *od_table)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
|
||||
dev_dbg(adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->OverDriveTable.GfxclkFmin,
|
||||
od_table->OverDriveTable.GfxclkFmax);
|
||||
dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin,
|
||||
od_table->OverDriveTable.UclkFmax);
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_upload_overdrive_table(struct smu_context *smu,
|
||||
OverDriveTableExternal_t *od_table)
|
||||
{
|
||||
int ret;
|
||||
ret = smu_cmn_update_table(smu,
|
||||
SMU_TABLE_OVERDRIVE,
|
||||
0,
|
||||
(void *)od_table,
|
||||
true);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void smu_v14_0_2_set_supported_od_feature_mask(struct smu_context *smu)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
|
||||
if (smu_v14_0_2_is_od_feature_supported(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_BIT))
|
||||
adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE |
|
||||
OD_OPS_SUPPORT_FAN_CURVE_SET |
|
||||
OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE |
|
||||
OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET |
|
||||
OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE |
|
||||
OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET |
|
||||
OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
|
||||
OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
|
||||
OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
|
||||
OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_get_overdrive_table(struct smu_context *smu,
|
||||
OverDriveTableExternal_t *od_table)
|
||||
{
|
||||
int ret;
|
||||
ret = smu_cmn_update_table(smu,
|
||||
SMU_TABLE_OVERDRIVE,
|
||||
0,
|
||||
(void *)od_table,
|
||||
false);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_set_default_od_settings(struct smu_context *smu)
|
||||
{
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
|
||||
OverDriveTableExternal_t *boot_od_table =
|
||||
(OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table;
|
||||
OverDriveTableExternal_t *user_od_table =
|
||||
(OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table;
|
||||
OverDriveTableExternal_t user_od_table_bak;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = smu_v14_0_2_get_overdrive_table(smu, boot_od_table);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
smu_v14_0_2_dump_od_table(smu, boot_od_table);
|
||||
|
||||
memcpy(od_table,
|
||||
boot_od_table,
|
||||
sizeof(OverDriveTableExternal_t));
|
||||
|
||||
/*
|
||||
* For S3/S4/Runpm resume, we need to setup those overdrive tables again,
|
||||
* but we have to preserve user defined values in "user_od_table".
|
||||
*/
|
||||
if (!smu->adev->in_suspend) {
|
||||
memcpy(user_od_table,
|
||||
boot_od_table,
|
||||
sizeof(OverDriveTableExternal_t));
|
||||
smu->user_dpm_profile.user_od = false;
|
||||
} else if (smu->user_dpm_profile.user_od) {
|
||||
memcpy(&user_od_table_bak,
|
||||
user_od_table,
|
||||
sizeof(OverDriveTableExternal_t));
|
||||
memcpy(user_od_table,
|
||||
boot_od_table,
|
||||
sizeof(OverDriveTableExternal_t));
|
||||
user_od_table->OverDriveTable.GfxclkFmin =
|
||||
user_od_table_bak.OverDriveTable.GfxclkFmin;
|
||||
user_od_table->OverDriveTable.GfxclkFmax =
|
||||
user_od_table_bak.OverDriveTable.GfxclkFmax;
|
||||
user_od_table->OverDriveTable.UclkFmin =
|
||||
user_od_table_bak.OverDriveTable.UclkFmin;
|
||||
user_od_table->OverDriveTable.UclkFmax =
|
||||
user_od_table_bak.OverDriveTable.UclkFmax;
|
||||
for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
|
||||
user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
|
||||
user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
|
||||
for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) {
|
||||
user_od_table->OverDriveTable.FanLinearTempPoints[i] =
|
||||
user_od_table_bak.OverDriveTable.FanLinearTempPoints[i];
|
||||
user_od_table->OverDriveTable.FanLinearPwmPoints[i] =
|
||||
user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i];
|
||||
}
|
||||
user_od_table->OverDriveTable.AcousticLimitRpmThreshold =
|
||||
user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold;
|
||||
user_od_table->OverDriveTable.AcousticTargetRpmThreshold =
|
||||
user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold;
|
||||
user_od_table->OverDriveTable.FanTargetTemperature =
|
||||
user_od_table_bak.OverDriveTable.FanTargetTemperature;
|
||||
user_od_table->OverDriveTable.FanMinimumPwm =
|
||||
user_od_table_bak.OverDriveTable.FanMinimumPwm;
|
||||
}
|
||||
|
||||
smu_v14_0_2_set_supported_od_feature_mask(smu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_restore_user_od_settings(struct smu_context *smu)
|
||||
{
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
OverDriveTableExternal_t *od_table = table_context->overdrive_table;
|
||||
OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
|
||||
int res;
|
||||
|
||||
user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) |
|
||||
BIT(PP_OD_FEATURE_UCLK_BIT) |
|
||||
BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) |
|
||||
BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
res = smu_v14_0_2_upload_overdrive_table(smu, user_od_table);
|
||||
user_od_table->OverDriveTable.FeatureCtrlMask = 0;
|
||||
if (res == 0)
|
||||
memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_od_restore_table_single(struct smu_context *smu, long input)
|
||||
{
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
OverDriveTableExternal_t *boot_overdrive_table =
|
||||
(OverDriveTableExternal_t *)table_context->boot_overdrive_table;
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)table_context->overdrive_table;
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
int i;
|
||||
|
||||
switch (input) {
|
||||
case PP_OD_EDIT_FAN_CURVE:
|
||||
for (i = 0; i < NUM_OD_FAN_MAX_POINTS; i++) {
|
||||
od_table->OverDriveTable.FanLinearTempPoints[i] =
|
||||
boot_overdrive_table->OverDriveTable.FanLinearTempPoints[i];
|
||||
od_table->OverDriveTable.FanLinearPwmPoints[i] =
|
||||
boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
|
||||
}
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
case PP_OD_EDIT_ACOUSTIC_LIMIT:
|
||||
od_table->OverDriveTable.AcousticLimitRpmThreshold =
|
||||
boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
case PP_OD_EDIT_ACOUSTIC_TARGET:
|
||||
od_table->OverDriveTable.AcousticTargetRpmThreshold =
|
||||
boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
|
||||
od_table->OverDriveTable.FanTargetTemperature =
|
||||
boot_overdrive_table->OverDriveTable.FanTargetTemperature;
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
case PP_OD_EDIT_FAN_MINIMUM_PWM:
|
||||
od_table->OverDriveTable.FanMinimumPwm =
|
||||
boot_overdrive_table->OverDriveTable.FanMinimumPwm;
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
default:
|
||||
dev_info(adev->dev, "Invalid table index: %ld\n", input);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu,
|
||||
enum PP_OD_DPM_TABLE_COMMAND type,
|
||||
long input[],
|
||||
uint32_t size)
|
||||
{
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)table_context->overdrive_table;
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
uint32_t offset_of_voltageoffset;
|
||||
int32_t minimum, maximum;
|
||||
uint32_t feature_ctrlmask;
|
||||
int i, ret = 0;
|
||||
|
||||
switch (type) {
|
||||
case PP_OD_EDIT_SCLK_VDDC_TABLE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
|
||||
dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i += 2) {
|
||||
if (i + 2 > size) {
|
||||
dev_info(adev->dev, "invalid number of input parameters %d\n", size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (input[i]) {
|
||||
case 0:
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_GFXCLK_FMIN,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[i + 1] < minimum ||
|
||||
input[i + 1] > maximum) {
|
||||
dev_info(adev->dev, "GfxclkFmin (%ld) must be within [%u, %u]!\n",
|
||||
input[i + 1], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.GfxclkFmin = input[i + 1];
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_GFXCLK_FMAX,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[i + 1] < minimum ||
|
||||
input[i + 1] > maximum) {
|
||||
dev_info(adev->dev, "GfxclkFmax (%ld) must be within [%u, %u]!\n",
|
||||
input[i + 1], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.GfxclkFmax = input[i + 1];
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_info(adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
|
||||
dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (od_table->OverDriveTable.GfxclkFmin > od_table->OverDriveTable.GfxclkFmax) {
|
||||
dev_err(adev->dev,
|
||||
"Invalid setting: GfxclkFmin(%u) is bigger than GfxclkFmax(%u)\n",
|
||||
(uint32_t)od_table->OverDriveTable.GfxclkFmin,
|
||||
(uint32_t)od_table->OverDriveTable.GfxclkFmax);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_MCLK_VDDC_TABLE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
|
||||
dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i += 2) {
|
||||
if (i + 2 > size) {
|
||||
dev_info(adev->dev, "invalid number of input parameters %d\n", size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (input[i]) {
|
||||
case 0:
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_UCLK_FMIN,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[i + 1] < minimum ||
|
||||
input[i + 1] > maximum) {
|
||||
dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n",
|
||||
input[i + 1], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.UclkFmin = input[i + 1];
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_UCLK_FMAX,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[i + 1] < minimum ||
|
||||
input[i + 1] > maximum) {
|
||||
dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n",
|
||||
input[i + 1], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.UclkFmax = input[i + 1];
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]);
|
||||
dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) {
|
||||
dev_err(adev->dev,
|
||||
"Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n",
|
||||
(uint32_t)od_table->OverDriveTable.UclkFmin,
|
||||
(uint32_t)od_table->OverDriveTable.UclkFmax);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_VDDGFX_OFFSET:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
|
||||
dev_warn(adev->dev, "Gfx offset setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_GFX_VF_CURVE,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[0] < minimum ||
|
||||
input[0] > maximum) {
|
||||
dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n",
|
||||
input[0], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
|
||||
od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = input[0];
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT);
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_FAN_CURVE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
|
||||
dev_warn(adev->dev, "Fan curve setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (input[0] >= NUM_OD_FAN_MAX_POINTS - 1 ||
|
||||
input[0] < 0)
|
||||
return -EINVAL;
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_TEMP,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[1] < minimum ||
|
||||
input[1] > maximum) {
|
||||
dev_info(adev->dev, "Fan curve temp setting(%ld) must be within [%d, %d]!\n",
|
||||
input[1], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_CURVE_PWM,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[2] < minimum ||
|
||||
input[2] > maximum) {
|
||||
dev_info(adev->dev, "Fan curve pwm setting(%ld) must be within [%d, %d]!\n",
|
||||
input[2], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.FanLinearTempPoints[input[0]] = input[1];
|
||||
od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2];
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_ACOUSTIC_LIMIT:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
|
||||
dev_warn(adev->dev, "Fan curve setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[0] < minimum ||
|
||||
input[0] > maximum) {
|
||||
dev_info(adev->dev, "acoustic limit threshold setting(%ld) must be within [%d, %d]!\n",
|
||||
input[0], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.AcousticLimitRpmThreshold = input[0];
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_ACOUSTIC_TARGET:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
|
||||
dev_warn(adev->dev, "Fan curve setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_ACOUSTIC_TARGET,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[0] < minimum ||
|
||||
input[0] > maximum) {
|
||||
dev_info(adev->dev, "acoustic target threshold setting(%ld) must be within [%d, %d]!\n",
|
||||
input[0], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.AcousticTargetRpmThreshold = input[0];
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
|
||||
dev_warn(adev->dev, "Fan curve setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_TARGET_TEMPERATURE,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[0] < minimum ||
|
||||
input[0] > maximum) {
|
||||
dev_info(adev->dev, "fan target temperature setting(%ld) must be within [%d, %d]!\n",
|
||||
input[0], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.FanTargetTemperature = input[0];
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
|
||||
case PP_OD_EDIT_FAN_MINIMUM_PWM:
|
||||
if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
|
||||
dev_warn(adev->dev, "Fan curve setting not supported!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
smu_v14_0_2_get_od_setting_limits(smu,
|
||||
PP_OD_FEATURE_FAN_MINIMUM_PWM,
|
||||
&minimum,
|
||||
&maximum);
|
||||
if (input[0] < minimum ||
|
||||
input[0] > maximum) {
|
||||
dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n",
|
||||
input[0], minimum, maximum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.FanMinimumPwm = input[0];
|
||||
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
|
||||
break;
|
||||
|
||||
case PP_OD_RESTORE_DEFAULT_TABLE:
|
||||
if (size == 1) {
|
||||
ret = smu_v14_0_2_od_restore_table_single(smu, input[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
|
||||
memcpy(od_table,
|
||||
table_context->boot_overdrive_table,
|
||||
sizeof(OverDriveTableExternal_t));
|
||||
od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
|
||||
}
|
||||
fallthrough;
|
||||
case PP_OD_COMMIT_DPM_TABLE:
|
||||
/*
|
||||
* The member below instructs PMFW the settings focused in
|
||||
* this single operation.
|
||||
* `uint32_t FeatureCtrlMask;`
|
||||
* It does not contain actual informations about user's custom
|
||||
* settings. Thus we do not cache it.
|
||||
*/
|
||||
offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary);
|
||||
if (memcmp((u8 *)od_table + offset_of_voltageoffset,
|
||||
table_context->user_overdrive_table + offset_of_voltageoffset,
|
||||
sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) {
|
||||
smu_v14_0_2_dump_od_table(smu, od_table);
|
||||
|
||||
ret = smu_v14_0_2_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
od_table->OverDriveTable.FeatureCtrlMask = 0;
|
||||
memcpy(table_context->user_overdrive_table + offset_of_voltageoffset,
|
||||
(u8 *)od_table + offset_of_voltageoffset,
|
||||
sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset);
|
||||
|
||||
if (!memcmp(table_context->user_overdrive_table,
|
||||
table_context->boot_overdrive_table,
|
||||
sizeof(OverDriveTableExternal_t)))
|
||||
smu->user_dpm_profile.user_od = false;
|
||||
else
|
||||
smu->user_dpm_profile.user_od = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int smu_v14_0_2_set_power_limit(struct smu_context *smu,
|
||||
enum smu_ppt_limit_type limit_type,
|
||||
uint32_t limit)
|
||||
{
|
||||
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
||||
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
OverDriveTableExternal_t *od_table =
|
||||
(OverDriveTableExternal_t *)table_context->overdrive_table;
|
||||
int ret = 0;
|
||||
|
||||
if (limit_type != SMU_DEFAULT_PPT_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
if (limit <= msg_limit) {
|
||||
if (smu->current_power_limit > msg_limit) {
|
||||
od_table->OverDriveTable.Ppt = 0;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
|
||||
|
||||
ret = smu_v14_0_2_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return smu_v14_0_set_power_limit(smu, limit_type, limit);
|
||||
} else if (smu->od_enabled) {
|
||||
ret = smu_v14_0_set_power_limit(smu, limit_type, msg_limit);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
|
||||
od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
|
||||
|
||||
ret = smu_v14_0_2_upload_overdrive_table(smu, od_table);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
smu->current_power_limit = limit;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
|
||||
.get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask,
|
||||
.set_default_dpm_table = smu_v14_0_2_set_default_dpm_table,
|
||||
|
@ -1988,13 +2867,16 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
|
|||
.notify_memory_pool_location = smu_v14_0_notify_memory_pool_location,
|
||||
.get_gpu_metrics = smu_v14_0_2_get_gpu_metrics,
|
||||
.set_soft_freq_limited_range = smu_v14_0_set_soft_freq_limited_range,
|
||||
.set_default_od_settings = smu_v14_0_2_set_default_od_settings,
|
||||
.restore_user_od_settings = smu_v14_0_2_restore_user_od_settings,
|
||||
.od_edit_dpm_table = smu_v14_0_2_od_edit_dpm_table,
|
||||
.init_pptable_microcode = smu_v14_0_init_pptable_microcode,
|
||||
.populate_umd_state_clk = smu_v14_0_2_populate_umd_state_clk,
|
||||
.set_performance_level = smu_v14_0_set_performance_level,
|
||||
.gfx_off_control = smu_v14_0_gfx_off_control,
|
||||
.get_unique_id = smu_v14_0_2_get_unique_id,
|
||||
.get_power_limit = smu_v14_0_2_get_power_limit,
|
||||
.set_power_limit = smu_v14_0_set_power_limit,
|
||||
.set_power_limit = smu_v14_0_2_set_power_limit,
|
||||
.set_power_source = smu_v14_0_set_power_source,
|
||||
.get_power_profile_mode = smu_v14_0_2_get_power_profile_mode,
|
||||
.set_power_profile_mode = smu_v14_0_2_set_power_profile_mode,
|
||||
|
|
Loading…
Reference in New Issue
Block a user