drm/amd/pm: fulfill SMU13 OD settings init and restore
Gfxclk fmin/fmax, Uclk fmin/fmax and Gfx v/f curve voltage offset OD settings are supported for SMU13. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
a159afdad2
commit
8f4f5f0b90
|
@ -678,7 +678,12 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
|
||||||
* clock labeled OD_MCLK
|
* clock labeled OD_MCLK
|
||||||
*
|
*
|
||||||
* - three <frequency, voltage> points labeled OD_VDDC_CURVE.
|
* - three <frequency, voltage> points labeled OD_VDDC_CURVE.
|
||||||
* They can be used to calibrate the sclk voltage curve.
|
* They can be used to calibrate the sclk voltage curve. This is
|
||||||
|
* available for Vega20 and NV1X.
|
||||||
|
*
|
||||||
|
* - voltage offset for the six anchor points of the v/f curve labeled
|
||||||
|
* OD_VDDC_CURVE. They can be used to calibrate the v/f curve. This
|
||||||
|
* is only availabe for some SMU13 ASICs.
|
||||||
*
|
*
|
||||||
* - voltage offset(in mV) applied on target voltage calculation.
|
* - voltage offset(in mV) applied on target voltage calculation.
|
||||||
* This is available for Sienna Cichlid, Navy Flounder and Dimgrey
|
* This is available for Sienna Cichlid, Navy Flounder and Dimgrey
|
||||||
|
@ -719,12 +724,19 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
|
||||||
* E.g., "p 2 0 800" would set the minimum core clock on core
|
* E.g., "p 2 0 800" would set the minimum core clock on core
|
||||||
* 2 to 800Mhz.
|
* 2 to 800Mhz.
|
||||||
*
|
*
|
||||||
* For sclk voltage curve, enter the new values by writing a
|
* For sclk voltage curve,
|
||||||
* string that contains "vc point clock voltage" to the file. The
|
* - For NV1X, enter the new values by writing a string that
|
||||||
* points are indexed by 0, 1 and 2. E.g., "vc 0 300 600" will
|
* contains "vc point clock voltage" to the file. The points
|
||||||
* update point1 with clock set as 300Mhz and voltage as
|
* are indexed by 0, 1 and 2. E.g., "vc 0 300 600" will update
|
||||||
* 600mV. "vc 2 1000 1000" will update point3 with clock set
|
* point1 with clock set as 300Mhz and voltage as 600mV. "vc 2
|
||||||
* as 1000Mhz and voltage 1000mV.
|
* 1000 1000" will update point3 with clock set as 1000Mhz and
|
||||||
|
* voltage 1000mV.
|
||||||
|
* - For SMU13 ASICs, enter the new values by writing a string that
|
||||||
|
* contains "vc anchor_point_index voltage_offset" to the file.
|
||||||
|
* There are total six anchor points defined on the v/f curve with
|
||||||
|
* index as 0 - 5.
|
||||||
|
* - "vc 0 10" will update the voltage offset for point1 as 10mv.
|
||||||
|
* - "vc 5 -10" will update the voltage offset for point6 as -10mv.
|
||||||
*
|
*
|
||||||
* To update the voltage offset applied for gfxclk/voltage calculation,
|
* To update the voltage offset applied for gfxclk/voltage calculation,
|
||||||
* enter the new value by writing a string that contains "vo offset".
|
* enter the new value by writing a string that contains "vo offset".
|
||||||
|
|
|
@ -467,17 +467,26 @@ int smu_v13_0_init_smc_tables(struct smu_context *smu)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err3_out;
|
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 =
|
smu_table->combo_pptable =
|
||||||
kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL);
|
kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL);
|
||||||
if (!smu_table->combo_pptable) {
|
if (!smu_table->combo_pptable) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err4_out;
|
goto err5_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err5_out:
|
||||||
|
kfree(smu_table->user_overdrive_table);
|
||||||
err4_out:
|
err4_out:
|
||||||
kfree(smu_table->boot_overdrive_table);
|
kfree(smu_table->boot_overdrive_table);
|
||||||
err3_out:
|
err3_out:
|
||||||
|
@ -497,12 +506,14 @@ int smu_v13_0_fini_smc_tables(struct smu_context *smu)
|
||||||
|
|
||||||
kfree(smu_table->gpu_metrics_table);
|
kfree(smu_table->gpu_metrics_table);
|
||||||
kfree(smu_table->combo_pptable);
|
kfree(smu_table->combo_pptable);
|
||||||
|
kfree(smu_table->user_overdrive_table);
|
||||||
kfree(smu_table->boot_overdrive_table);
|
kfree(smu_table->boot_overdrive_table);
|
||||||
kfree(smu_table->overdrive_table);
|
kfree(smu_table->overdrive_table);
|
||||||
kfree(smu_table->max_sustainable_clocks);
|
kfree(smu_table->max_sustainable_clocks);
|
||||||
kfree(smu_table->driver_pptable);
|
kfree(smu_table->driver_pptable);
|
||||||
smu_table->gpu_metrics_table = NULL;
|
smu_table->gpu_metrics_table = NULL;
|
||||||
smu_table->combo_pptable = NULL;
|
smu_table->combo_pptable = NULL;
|
||||||
|
smu_table->user_overdrive_table = NULL;
|
||||||
smu_table->boot_overdrive_table = NULL;
|
smu_table->boot_overdrive_table = NULL;
|
||||||
smu_table->overdrive_table = NULL;
|
smu_table->overdrive_table = NULL;
|
||||||
smu_table->max_sustainable_clocks = NULL;
|
smu_table->max_sustainable_clocks = NULL;
|
||||||
|
|
|
@ -237,6 +237,7 @@ static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
|
||||||
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
|
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
|
||||||
TAB_MAP(I2C_COMMANDS),
|
TAB_MAP(I2C_COMMANDS),
|
||||||
TAB_MAP(ECCINFO),
|
TAB_MAP(ECCINFO),
|
||||||
|
TAB_MAP(OVERDRIVE),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
|
static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
|
||||||
|
@ -331,6 +332,11 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
|
||||||
struct smu_13_0_0_powerplay_table *powerplay_table =
|
struct smu_13_0_0_powerplay_table *powerplay_table =
|
||||||
table_context->power_play_table;
|
table_context->power_play_table;
|
||||||
struct smu_baco_context *smu_baco = &smu->smu_baco;
|
struct smu_baco_context *smu_baco = &smu->smu_baco;
|
||||||
|
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.OverDriveLimitsMin;
|
||||||
|
|
||||||
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
|
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
|
||||||
smu->dc_controlled_by_gpio = true;
|
smu->dc_controlled_by_gpio = true;
|
||||||
|
@ -342,6 +348,10 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
|
||||||
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
|
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
|
||||||
smu_baco->maco_support = true;
|
smu_baco->maco_support = true;
|
||||||
|
|
||||||
|
if (!overdrive_lowerlimits->FeatureCtrlMask ||
|
||||||
|
!overdrive_upperlimits->FeatureCtrlMask)
|
||||||
|
smu->od_enabled = false;
|
||||||
|
|
||||||
table_context->thermal_controller_type =
|
table_context->thermal_controller_type =
|
||||||
powerplay_table->thermal_controller_type;
|
powerplay_table->thermal_controller_type;
|
||||||
|
|
||||||
|
@ -461,7 +471,7 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu)
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
|
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
|
SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTableExternal_t),
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
|
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
|
@ -1384,6 +1394,121 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
|
||||||
return sizeof(struct gpu_metrics_v1_3);
|
return sizeof(struct gpu_metrics_v1_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int smu_v13_0_0_get_overdrive_table(struct smu_context *smu,
|
||||||
|
OverDriveTableExternal_t *od_table)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
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_v13_0_0_upload_overdrive_table(struct smu_context *smu,
|
||||||
|
OverDriveTableExternal_t *od_table)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
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_v13_0_0_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_v13_0_0_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 = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ret = smu_v13_0_0_get_overdrive_table(smu, boot_od_table);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
smu_v13_0_0_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];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int smu_v13_0_0_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 = 1U << PP_OD_FEATURE_GFXCLK_BIT |
|
||||||
|
1U << PP_OD_FEATURE_UCLK_BIT |
|
||||||
|
1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
|
||||||
|
res = smu_v13_0_0_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_v13_0_0_populate_umd_state_clk(struct smu_context *smu)
|
static int smu_v13_0_0_populate_umd_state_clk(struct smu_context *smu)
|
||||||
{
|
{
|
||||||
struct smu_13_0_dpm_context *dpm_context =
|
struct smu_13_0_dpm_context *dpm_context =
|
||||||
|
@ -2150,6 +2275,8 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
|
||||||
.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
|
.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
|
||||||
.get_gpu_metrics = smu_v13_0_0_get_gpu_metrics,
|
.get_gpu_metrics = smu_v13_0_0_get_gpu_metrics,
|
||||||
.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
|
.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
|
||||||
|
.set_default_od_settings = smu_v13_0_0_set_default_od_settings,
|
||||||
|
.restore_user_od_settings = smu_v13_0_0_restore_user_od_settings,
|
||||||
.init_pptable_microcode = smu_v13_0_init_pptable_microcode,
|
.init_pptable_microcode = smu_v13_0_init_pptable_microcode,
|
||||||
.populate_umd_state_clk = smu_v13_0_0_populate_umd_state_clk,
|
.populate_umd_state_clk = smu_v13_0_0_populate_umd_state_clk,
|
||||||
.set_performance_level = smu_v13_0_set_performance_level,
|
.set_performance_level = smu_v13_0_set_performance_level,
|
||||||
|
|
|
@ -206,6 +206,7 @@ static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
|
||||||
TAB_MAP(DRIVER_SMU_CONFIG),
|
TAB_MAP(DRIVER_SMU_CONFIG),
|
||||||
TAB_MAP(ACTIVITY_MONITOR_COEFF),
|
TAB_MAP(ACTIVITY_MONITOR_COEFF),
|
||||||
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
|
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
|
||||||
|
TAB_MAP(OVERDRIVE),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
|
static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
|
||||||
|
@ -322,6 +323,10 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
|
||||||
struct smu_baco_context *smu_baco = &smu->smu_baco;
|
struct smu_baco_context *smu_baco = &smu->smu_baco;
|
||||||
PPTable_t *smc_pptable = table_context->driver_pptable;
|
PPTable_t *smc_pptable = table_context->driver_pptable;
|
||||||
BoardTable_t *BoardTable = &smc_pptable->BoardTable;
|
BoardTable_t *BoardTable = &smc_pptable->BoardTable;
|
||||||
|
const OverDriveLimits_t * const overdrive_upperlimits =
|
||||||
|
&smc_pptable->SkuTable.OverDriveLimitsBasicMax;
|
||||||
|
const OverDriveLimits_t * const overdrive_lowerlimits =
|
||||||
|
&smc_pptable->SkuTable.OverDriveLimitsMin;
|
||||||
|
|
||||||
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
|
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
|
||||||
smu->dc_controlled_by_gpio = true;
|
smu->dc_controlled_by_gpio = true;
|
||||||
|
@ -333,6 +338,10 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
|
||||||
if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
|
if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
|
||||||
smu_baco->maco_support = true;
|
smu_baco->maco_support = true;
|
||||||
|
|
||||||
|
if (!overdrive_lowerlimits->FeatureCtrlMask ||
|
||||||
|
!overdrive_upperlimits->FeatureCtrlMask)
|
||||||
|
smu->od_enabled = false;
|
||||||
|
|
||||||
table_context->thermal_controller_type =
|
table_context->thermal_controller_type =
|
||||||
powerplay_table->thermal_controller_type;
|
powerplay_table->thermal_controller_type;
|
||||||
|
|
||||||
|
@ -479,7 +488,7 @@ static int smu_v13_0_7_tables_init(struct smu_context *smu)
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
|
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
|
SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTableExternal_t),
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
|
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
|
||||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
|
||||||
|
@ -1371,6 +1380,121 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
|
||||||
return sizeof(struct gpu_metrics_v1_3);
|
return sizeof(struct gpu_metrics_v1_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int smu_v13_0_7_get_overdrive_table(struct smu_context *smu,
|
||||||
|
OverDriveTableExternal_t *od_table)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
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_v13_0_7_upload_overdrive_table(struct smu_context *smu,
|
||||||
|
OverDriveTableExternal_t *od_table)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
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_v13_0_7_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_v13_0_7_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 = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ret = smu_v13_0_7_get_overdrive_table(smu, boot_od_table);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
smu_v13_0_7_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];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int smu_v13_0_7_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 = 1U << PP_OD_FEATURE_GFXCLK_BIT |
|
||||||
|
1U << PP_OD_FEATURE_UCLK_BIT |
|
||||||
|
1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
|
||||||
|
res = smu_v13_0_7_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_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
|
static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
|
||||||
{
|
{
|
||||||
struct smu_13_0_dpm_context *dpm_context =
|
struct smu_13_0_dpm_context *dpm_context =
|
||||||
|
@ -1760,6 +1884,8 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
|
||||||
.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
|
.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
|
||||||
.get_gpu_metrics = smu_v13_0_7_get_gpu_metrics,
|
.get_gpu_metrics = smu_v13_0_7_get_gpu_metrics,
|
||||||
.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
|
.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
|
||||||
|
.set_default_od_settings = smu_v13_0_7_set_default_od_settings,
|
||||||
|
.restore_user_od_settings = smu_v13_0_7_restore_user_od_settings,
|
||||||
.set_performance_level = smu_v13_0_set_performance_level,
|
.set_performance_level = smu_v13_0_set_performance_level,
|
||||||
.gfx_off_control = smu_v13_0_gfx_off_control,
|
.gfx_off_control = smu_v13_0_gfx_off_control,
|
||||||
.get_fan_speed_pwm = smu_v13_0_7_get_fan_speed_pwm,
|
.get_fan_speed_pwm = smu_v13_0_7_get_fan_speed_pwm,
|
||||||
|
|
Loading…
Reference in New Issue