summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c258
1 files changed, 135 insertions, 123 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
index 085d81c..faef783 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
@@ -205,9 +205,9 @@ static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr)
int result = 0;
struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
- if (0 != smu_data->avfs.avfs_btc_param) {
+ if (0 != smu_data->avfs_btc_param) {
if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) {
+ PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param)) {
pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed");
result = -EINVAL;
}
@@ -261,43 +261,24 @@ static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr)
return 0;
}
-static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool smu_started)
+static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr)
{
- struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
+ if (!hwmgr->avfs_supported)
+ return 0;
- switch (smu_data->avfs.avfs_btc_status) {
- case AVFS_BTC_COMPLETED_PREVIOUSLY:
- break;
+ PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr),
+ "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
+ " table over to SMU",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
+ "[AVFS][fiji_avfs_event_mgr] Could not setup "
+ "Pwr Virus for AVFS ",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr),
+ "[AVFS][fiji_avfs_event_mgr] Failure at "
+ "fiji_start_avfs_btc. AVFS Disabled",
+ return -EINVAL);
- case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/
- if (!smu_started)
- break;
- smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED;
- PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr),
- "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
- " table over to SMU",
- return -EINVAL;);
- smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL;
- PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
- "[AVFS][fiji_avfs_event_mgr] Could not setup "
- "Pwr Virus for AVFS ",
- return -EINVAL;);
- smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED;
- PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr),
- "[AVFS][fiji_avfs_event_mgr] Failure at "
- "fiji_start_avfs_btc. AVFS Disabled",
- return -EINVAL;);
-
- smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS;
- break;
- case AVFS_BTC_DISABLED: /* Do nothing */
- case AVFS_BTC_NOTSUPPORTED: /* Do nothing */
- case AVFS_BTC_ENABLEAVFS:
- break;
- default:
- pr_err("AVFS failed status is %x !\n", smu_data->avfs.avfs_btc_status);
- break;
- }
return 0;
}
@@ -309,8 +290,6 @@ static int fiji_start_smu(struct pp_hwmgr *hwmgr)
/* Only start SMC if SMC RAM is not running */
if (!(smu7_is_smc_ram_running(hwmgr)
|| cgs_is_virtualization_enabled(hwmgr->device))) {
- fiji_avfs_event_mgr(hwmgr, false);
-
/* Check if SMU is running in protected mode */
if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
CGS_IND_REG__SMC,
@@ -323,7 +302,8 @@ static int fiji_start_smu(struct pp_hwmgr *hwmgr)
if (result)
return result;
}
- fiji_avfs_event_mgr(hwmgr, true);
+ if (fiji_avfs_event_mgr(hwmgr))
+ hwmgr->avfs_supported = false;
}
/* To initialize all clock gating before RLC loaded and running.*/
@@ -368,7 +348,6 @@ static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
static int fiji_smu_init(struct pp_hwmgr *hwmgr)
{
- int i;
struct fiji_smumgr *fiji_priv = NULL;
fiji_priv = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
@@ -378,11 +357,10 @@ static int fiji_smu_init(struct pp_hwmgr *hwmgr)
hwmgr->smu_backend = fiji_priv;
- if (smu7_init(hwmgr))
+ if (smu7_init(hwmgr)) {
+ kfree(fiji_priv);
return -EINVAL;
-
- for (i = 0; i < SMU73_MAX_LEVELS_GRAPHICS; i++)
- fiji_priv->activity_target[i] = 30;
+ }
return 0;
}
@@ -972,8 +950,7 @@ static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr,
}
static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
- uint32_t clock, uint16_t sclk_al_threshold,
- struct SMU73_Discrete_GraphicsLevel *level)
+ uint32_t clock, struct SMU73_Discrete_GraphicsLevel *level)
{
int result;
/* PP_Clocks minClocks; */
@@ -981,12 +958,18 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
result = fiji_calculate_sclk_params(hwmgr, clock, level);
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
+ else
+ vdd_dep_table = table_info->vdd_dep_on_sclk;
+
/* populate graphics levels */
result = fiji_get_dependency_volt_by_clk(hwmgr,
- table_info->vdd_dep_on_sclk, clock,
+ vdd_dep_table, clock,
(uint32_t *)(&level->MinVoltage), &mvdd);
PP_ASSERT_WITH_CODE((0 == result),
"can not find VDDC voltage value for "
@@ -994,13 +977,13 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
return result);
level->SclkFrequency = clock;
- level->ActivityLevel = sclk_al_threshold;
+ level->ActivityLevel = data->current_profile_setting.sclk_activity;
level->CcPwrDynRm = 0;
level->CcPwrDynRm1 = 0;
level->EnabledForActivity = 0;
level->EnabledForThrottle = 1;
- level->UpHyst = 10;
- level->DownHyst = 0;
+ level->UpHyst = data->current_profile_setting.sclk_up_hyst;
+ level->DownHyst = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownHyst = 0;
level->PowerThrottle = 0;
@@ -1057,7 +1040,6 @@ static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = fiji_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value,
- (uint16_t)smu_data->activity_target[i],
&levels[i]);
if (result)
return result;
@@ -1202,10 +1184,16 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
(struct phm_ppt_v1_information *)(hwmgr->pptable);
int result = 0;
uint32_t mclk_stutter_mode_threshold = 60000;
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
- if (table_info->vdd_dep_on_mclk) {
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
+ else
+ vdd_dep_table = table_info->vdd_dep_on_mclk;
+
+ if (vdd_dep_table) {
result = fiji_get_dependency_volt_by_clk(hwmgr,
- table_info->vdd_dep_on_mclk, clock,
+ vdd_dep_table, clock,
(uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd);
PP_ASSERT_WITH_CODE((0 == result),
"can not find MinVddc voltage value from memory "
@@ -1214,10 +1202,10 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0;
- mem_level->UpHyst = 0;
- mem_level->DownHyst = 100;
+ mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
+ mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
mem_level->VoltageDownHyst = 0;
- mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+ mem_level->ActivityLevel = data->current_profile_setting.mclk_activity;
mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
@@ -1435,7 +1423,7 @@ static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0;
table->MemoryACPILevel.ActivityLevel =
- PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+ PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = false;
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
@@ -1799,7 +1787,7 @@ static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher);
PP_ASSERT_WITH_CODE(false,
- "Stretch Amount in PPTable not supported\n",
+ "Stretch Amount in PPTable not supported",
return -EINVAL);
}
@@ -1954,44 +1942,6 @@ static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr)
smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END);
}
-static int fiji_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct fiji_smumgr *data = (struct fiji_smumgr *)(hwmgr->smu_backend);
- struct SMU73_Discrete_GraphicsLevel *levels =
- data->smc_state_table.GraphicsLevel;
- unsigned min_level = 1;
-
- hwmgr->default_gfx_power_profile.activity_threshold =
- be16_to_cpu(levels[0].ActivityLevel);
- hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst;
- hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst;
- hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
-
- hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
- /* Workaround compute SDMA instability: disable lowest SCLK
- * DPM level. Optimize compute power profile: Use only highest
- * 2 power levels (if more than 2 are available), Hysteresis:
- * 0ms up, 5ms down
- */
- if (data->smc_state_table.GraphicsDpmLevelCount > 2)
- min_level = data->smc_state_table.GraphicsDpmLevelCount - 2;
- else if (data->smc_state_table.GraphicsDpmLevelCount == 2)
- min_level = 1;
- else
- min_level = 0;
- hwmgr->default_compute_power_profile.min_sclk =
- be32_to_cpu(levels[min_level].SclkFrequency);
- hwmgr->default_compute_power_profile.up_hyst = 0;
- hwmgr->default_compute_power_profile.down_hyst = 5;
-
- hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
-
- return 0;
-}
-
static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
{
pp_atomctrl_voltage_table param_led_dpm;
@@ -2141,7 +2091,7 @@ static int fiji_init_smc_table(struct pp_hwmgr *hwmgr)
result = fiji_populate_vr_config(hwmgr, table);
PP_ASSERT_WITH_CODE(0 == result,
"Failed to populate VRConfig setting!", return result);
-
+ data->vr_config = table->VRConfig;
table->ThermGpio = 17;
table->SclkStepSize = 0x4000;
@@ -2232,8 +2182,6 @@ static int fiji_init_smc_table(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE(0 == result,
"Failed to setup dpm led config", return result);
- fiji_save_default_power_profile(hwmgr);
-
return 0;
}
@@ -2309,7 +2257,7 @@ static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
fan_table.TempRespLim = cpu_to_be16(5);
- reference_clock = smu7_get_xclk(hwmgr);
+ reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
thermal_controller.advanceFanControlParameters.ulCycleDelay *
@@ -2349,19 +2297,12 @@ static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
{
- int ret;
- struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
-
- if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS)
+ if (!hwmgr->avfs_supported)
return 0;
- ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
-
- if (!ret)
- /* If this param is not changed, this function could fire unnecessarily */
- smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
- return ret;
+ return 0;
}
static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
@@ -2688,29 +2629,100 @@ static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr)
? true : false;
}
-static int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
+static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr,
+ void *profile_setting)
{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct fiji_smumgr *smu_data = (struct fiji_smumgr *)
(hwmgr->smu_backend);
+ struct profile_mode_setting *setting;
struct SMU73_Discrete_GraphicsLevel *levels =
smu_data->smc_state_table.GraphicsLevel;
uint32_t array = smu_data->smu7_data.dpm_table_start +
offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) *
- SMU73_MAX_LEVELS_GRAPHICS;
+
+ uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
+ offsetof(SMU73_Discrete_DpmTable, MemoryLevel);
+ struct SMU73_Discrete_MemoryLevel *mclk_levels =
+ smu_data->smc_state_table.MemoryLevel;
uint32_t i;
+ uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
- for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
- levels[i].ActivityLevel =
- cpu_to_be16(request->activity_threshold);
- levels[i].EnabledForActivity = 1;
- levels[i].UpHyst = request->up_hyst;
- levels[i].DownHyst = request->down_hyst;
+ if (profile_setting == NULL)
+ return -EINVAL;
+
+ setting = (struct profile_mode_setting *)profile_setting;
+
+ if (setting->bupdate_sclk) {
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
+ if (levels[i].ActivityLevel !=
+ cpu_to_be16(setting->sclk_activity)) {
+ levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
+
+ clk_activity_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU73_Discrete_GraphicsLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (levels[i].UpHyst != setting->sclk_up_hyst ||
+ levels[i].DownHyst != setting->sclk_down_hyst) {
+ levels[i].UpHyst = setting->sclk_up_hyst;
+ levels[i].DownHyst = setting->sclk_down_hyst;
+ up_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU73_Discrete_GraphicsLevel, UpHyst);
+ down_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU73_Discrete_GraphicsLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
}
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
+ if (setting->bupdate_mclk) {
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
+ if (mclk_levels[i].ActivityLevel !=
+ cpu_to_be16(setting->mclk_activity)) {
+ mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
+
+ clk_activity_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
+ + offsetof(SMU73_Discrete_MemoryLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
+ mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
+ mclk_levels[i].UpHyst = setting->mclk_up_hyst;
+ mclk_levels[i].DownHyst = setting->mclk_down_hyst;
+ up_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
+ + offsetof(SMU73_Discrete_MemoryLevel, UpHyst);
+ down_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
+ + offsetof(SMU73_Discrete_MemoryLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
+ }
+ return 0;
}
const struct pp_smumgr_func fiji_smu_funcs = {
@@ -2736,6 +2748,6 @@ const struct pp_smumgr_func fiji_smu_funcs = {
.get_mac_definition = fiji_get_mac_definition,
.initialize_mc_reg_table = fiji_initialize_mc_reg_table,
.is_dpm_running = fiji_is_dpm_running,
- .populate_requested_graphic_levels = fiji_populate_requested_graphic_levels,
.is_hw_avfs_present = fiji_is_hw_avfs_present,
+ .update_dpm_settings = fiji_update_dpm_settings,
};
OpenPOWER on IntegriCloud