((adev)->powerplay.pp_funcs->reset_power_profile_state(\
(adev)->powerplay.pp_handle, request))
-#define amdgpu_dpm_get_power_profile_state(adev, query) \
- ((adev)->powerplay.pp_funcs->get_power_profile_state(\
- (adev)->powerplay.pp_handle, query))
-
-#define amdgpu_dpm_set_power_profile_state(adev, request) \
- ((adev)->powerplay.pp_funcs->set_power_profile_state(\
- (adev)->powerplay.pp_handle, request))
-
#define amdgpu_dpm_switch_power_profile(adev, type) \
((adev)->powerplay.pp_funcs->switch_power_profile(\
(adev)->powerplay.pp_handle, type))
return -EINVAL;
}
-static ssize_t amdgpu_get_pp_power_profile(struct device *dev,
- char *buf, struct amd_pp_profile *query)
-{
- struct drm_device *ddev = dev_get_drvdata(dev);
- struct amdgpu_device *adev = ddev->dev_private;
- int ret = 0xff;
-
- if (adev->powerplay.pp_funcs->get_power_profile_state)
- ret = amdgpu_dpm_get_power_profile_state(
- adev, query);
-
- if (ret)
- return ret;
-
- return snprintf(buf, PAGE_SIZE,
- "%d %d %d %d %d\n",
- query->min_sclk / 100,
- query->min_mclk / 100,
- query->activity_threshold,
- query->up_hyst,
- query->down_hyst);
-}
-
-static ssize_t amdgpu_get_pp_gfx_power_profile(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct amd_pp_profile query = {0};
-
- query.type = AMD_PP_GFX_PROFILE;
-
- return amdgpu_get_pp_power_profile(dev, buf, &query);
-}
-
-static ssize_t amdgpu_get_pp_compute_power_profile(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct amd_pp_profile query = {0};
-
- query.type = AMD_PP_COMPUTE_PROFILE;
-
- return amdgpu_get_pp_power_profile(dev, buf, &query);
-}
-
-static ssize_t amdgpu_set_pp_power_profile(struct device *dev,
- const char *buf,
- size_t count,
- struct amd_pp_profile *request)
-{
- struct drm_device *ddev = dev_get_drvdata(dev);
- struct amdgpu_device *adev = ddev->dev_private;
- uint32_t loop = 0;
- char *sub_str, buf_cpy[128], *tmp_str;
- const char delimiter[3] = {' ', '\n', '\0'};
- long int value;
- int ret = 0xff;
-
- if (strncmp("reset", buf, strlen("reset")) == 0) {
- if (adev->powerplay.pp_funcs->reset_power_profile_state)
- ret = amdgpu_dpm_reset_power_profile_state(
- adev, request);
- if (ret) {
- count = -EINVAL;
- goto fail;
- }
- return count;
- }
-
- if (strncmp("set", buf, strlen("set")) == 0) {
- if (adev->powerplay.pp_funcs->set_power_profile_state)
- ret = amdgpu_dpm_set_power_profile_state(
- adev, request);
-
- if (ret) {
- count = -EINVAL;
- goto fail;
- }
- return count;
- }
-
- if (count + 1 >= 128) {
- count = -EINVAL;
- goto fail;
- }
-
- memcpy(buf_cpy, buf, count + 1);
- tmp_str = buf_cpy;
-
- while (tmp_str[0]) {
- sub_str = strsep(&tmp_str, delimiter);
- ret = kstrtol(sub_str, 0, &value);
- if (ret) {
- count = -EINVAL;
- goto fail;
- }
-
- switch (loop) {
- case 0:
- /* input unit MHz convert to dpm table unit 10KHz*/
- request->min_sclk = (uint32_t)value * 100;
- break;
- case 1:
- /* input unit MHz convert to dpm table unit 10KHz*/
- request->min_mclk = (uint32_t)value * 100;
- break;
- case 2:
- request->activity_threshold = (uint16_t)value;
- break;
- case 3:
- request->up_hyst = (uint8_t)value;
- break;
- case 4:
- request->down_hyst = (uint8_t)value;
- break;
- default:
- break;
- }
-
- loop++;
- }
- if (adev->powerplay.pp_funcs->set_power_profile_state)
- ret = amdgpu_dpm_set_power_profile_state(adev, request);
-
- if (ret)
- count = -EINVAL;
-
-fail:
- return count;
-}
-
-static ssize_t amdgpu_set_pp_gfx_power_profile(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct amd_pp_profile request = {0};
-
- request.type = AMD_PP_GFX_PROFILE;
-
- return amdgpu_set_pp_power_profile(dev, buf, count, &request);
-}
-
-static ssize_t amdgpu_set_pp_compute_power_profile(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct amd_pp_profile request = {0};
-
- request.type = AMD_PP_COMPUTE_PROFILE;
-
- return amdgpu_set_pp_power_profile(dev, buf, count, &request);
-}
-
static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
amdgpu_get_dpm_forced_performance_level,
static DEVICE_ATTR(pp_mclk_od, S_IRUGO | S_IWUSR,
amdgpu_get_pp_mclk_od,
amdgpu_set_pp_mclk_od);
-static DEVICE_ATTR(pp_gfx_power_profile, S_IRUGO | S_IWUSR,
- amdgpu_get_pp_gfx_power_profile,
- amdgpu_set_pp_gfx_power_profile);
-static DEVICE_ATTR(pp_compute_power_profile, S_IRUGO | S_IWUSR,
- amdgpu_get_pp_compute_power_profile,
- amdgpu_set_pp_compute_power_profile);
static DEVICE_ATTR(pp_power_profile_mode, S_IRUGO | S_IWUSR,
amdgpu_get_pp_power_profile_mode,
amdgpu_set_pp_power_profile_mode);
DRM_ERROR("failed to create device file pp_mclk_od\n");
return ret;
}
- ret = device_create_file(adev->dev,
- &dev_attr_pp_gfx_power_profile);
- if (ret) {
- DRM_ERROR("failed to create device file "
- "pp_gfx_power_profile\n");
- return ret;
- }
- ret = device_create_file(adev->dev,
- &dev_attr_pp_compute_power_profile);
- if (ret) {
- DRM_ERROR("failed to create device file "
- "pp_compute_power_profile\n");
- return ret;
- }
-
ret = device_create_file(adev->dev,
&dev_attr_pp_power_profile_mode);
if (ret) {
device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
- device_remove_file(adev->dev,
- &dev_attr_pp_gfx_power_profile);
- device_remove_file(adev->dev,
- &dev_attr_pp_compute_power_profile);
device_remove_file(adev->dev,
&dev_attr_pp_power_profile_mode);
device_remove_file(adev->dev,
return ret;
}
-static void ci_save_default_power_profile(struct amdgpu_device *adev)
-{
- struct ci_power_info *pi = ci_get_pi(adev);
- struct SMU7_Discrete_GraphicsLevel *levels =
- pi->smc_state_table.GraphicsLevel;
- uint32_t min_level = 0;
-
- pi->default_gfx_power_profile.activity_threshold =
- be16_to_cpu(levels[0].ActivityLevel);
- pi->default_gfx_power_profile.up_hyst = levels[0].UpH;
- pi->default_gfx_power_profile.down_hyst = levels[0].DownH;
- pi->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
-
- pi->default_compute_power_profile = pi->default_gfx_power_profile;
- pi->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
- /* Optimize compute power profile: Use only highest
- * 2 power levels (if more than 2 are available), Hysteresis:
- * 0ms up, 5ms down
- */
- if (pi->smc_state_table.GraphicsDpmLevelCount > 2)
- min_level = pi->smc_state_table.GraphicsDpmLevelCount - 2;
- else if (pi->smc_state_table.GraphicsDpmLevelCount == 2)
- min_level = 1;
- pi->default_compute_power_profile.min_sclk =
- be32_to_cpu(levels[min_level].SclkFrequency);
-
- pi->default_compute_power_profile.up_hyst = 0;
- pi->default_compute_power_profile.down_hyst = 5;
-
- pi->gfx_power_profile = pi->default_gfx_power_profile;
- pi->compute_power_profile = pi->default_compute_power_profile;
-}
-
static int ci_init_smc_table(struct amdgpu_device *adev)
{
struct ci_power_info *pi = ci_get_pi(adev);
if (ret)
return ret;
- ci_save_default_power_profile(adev);
-
return 0;
}
return 0;
}
-static int ci_dpm_get_power_profile_state(void *handle,
- struct amd_pp_profile *query)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct ci_power_info *pi = ci_get_pi(adev);
-
- if (!pi || !query)
- return -EINVAL;
-
- if (query->type == AMD_PP_GFX_PROFILE)
- memcpy(query, &pi->gfx_power_profile,
- sizeof(struct amd_pp_profile));
- else if (query->type == AMD_PP_COMPUTE_PROFILE)
- memcpy(query, &pi->compute_power_profile,
- sizeof(struct amd_pp_profile));
- else
- return -EINVAL;
-
- return 0;
-}
-
-static int ci_populate_requested_graphic_levels(struct amdgpu_device *adev,
- struct amd_pp_profile *request)
-{
- struct ci_power_info *pi = ci_get_pi(adev);
- struct ci_dpm_table *dpm_table = &(pi->dpm_table);
- struct SMU7_Discrete_GraphicsLevel *levels =
- pi->smc_state_table.GraphicsLevel;
- uint32_t array = pi->dpm_table_start +
- offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) *
- SMU7_MAX_LEVELS_GRAPHICS;
- uint32_t i;
-
- for (i = 0; i < dpm_table->sclk_table.count; i++) {
- levels[i].ActivityLevel =
- cpu_to_be16(request->activity_threshold);
- levels[i].EnabledForActivity = 1;
- levels[i].UpH = request->up_hyst;
- levels[i].DownH = request->down_hyst;
- }
-
- return amdgpu_ci_copy_bytes_to_smc(adev, array, (uint8_t *)levels,
- array_size, pi->sram_end);
-}
-
-static void ci_find_min_clock_masks(struct amdgpu_device *adev,
- uint32_t *sclk_mask, uint32_t *mclk_mask,
- uint32_t min_sclk, uint32_t min_mclk)
-{
- struct ci_power_info *pi = ci_get_pi(adev);
- struct ci_dpm_table *dpm_table = &(pi->dpm_table);
- uint32_t i;
-
- for (i = 0; i < dpm_table->sclk_table.count; i++) {
- if (dpm_table->sclk_table.dpm_levels[i].enabled &&
- dpm_table->sclk_table.dpm_levels[i].value >= min_sclk)
- *sclk_mask |= 1 << i;
- }
-
- for (i = 0; i < dpm_table->mclk_table.count; i++) {
- if (dpm_table->mclk_table.dpm_levels[i].enabled &&
- dpm_table->mclk_table.dpm_levels[i].value >= min_mclk)
- *mclk_mask |= 1 << i;
- }
-}
-
-static int ci_set_power_profile_state(struct amdgpu_device *adev,
- struct amd_pp_profile *request)
-{
- struct ci_power_info *pi = ci_get_pi(adev);
- int tmp_result, result = 0;
- uint32_t sclk_mask = 0, mclk_mask = 0;
-
- tmp_result = ci_freeze_sclk_mclk_dpm(adev);
- if (tmp_result) {
- DRM_ERROR("Failed to freeze SCLK MCLK DPM!");
- result = tmp_result;
- }
-
- tmp_result = ci_populate_requested_graphic_levels(adev,
- request);
- if (tmp_result) {
- DRM_ERROR("Failed to populate requested graphic levels!");
- result = tmp_result;
- }
-
- tmp_result = ci_unfreeze_sclk_mclk_dpm(adev);
- if (tmp_result) {
- DRM_ERROR("Failed to unfreeze SCLK MCLK DPM!");
- result = tmp_result;
- }
-
- ci_find_min_clock_masks(adev, &sclk_mask, &mclk_mask,
- request->min_sclk, request->min_mclk);
-
- if (sclk_mask) {
- if (!pi->sclk_dpm_key_disabled)
- amdgpu_ci_send_msg_to_smc_with_parameter(
- adev,
- PPSMC_MSG_SCLKDPM_SetEnabledMask,
- pi->dpm_level_enable_mask.
- sclk_dpm_enable_mask &
- sclk_mask);
- }
-
- if (mclk_mask) {
- if (!pi->mclk_dpm_key_disabled)
- amdgpu_ci_send_msg_to_smc_with_parameter(
- adev,
- PPSMC_MSG_MCLKDPM_SetEnabledMask,
- pi->dpm_level_enable_mask.
- mclk_dpm_enable_mask &
- mclk_mask);
- }
-
-
- return result;
-}
-
-static int ci_dpm_set_power_profile_state(void *handle,
- struct amd_pp_profile *request)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct ci_power_info *pi = ci_get_pi(adev);
- int ret = -1;
-
- if (!pi || !request)
- return -EINVAL;
-
- if (adev->pm.dpm.forced_level !=
- AMD_DPM_FORCED_LEVEL_AUTO)
- return -EINVAL;
-
- if (request->min_sclk ||
- request->min_mclk ||
- request->activity_threshold ||
- request->up_hyst ||
- request->down_hyst) {
- if (request->type == AMD_PP_GFX_PROFILE)
- memcpy(&pi->gfx_power_profile, request,
- sizeof(struct amd_pp_profile));
- else if (request->type == AMD_PP_COMPUTE_PROFILE)
- memcpy(&pi->compute_power_profile, request,
- sizeof(struct amd_pp_profile));
- else
- return -EINVAL;
-
- if (request->type == pi->current_power_profile)
- ret = ci_set_power_profile_state(
- adev,
- request);
- } else {
- /* set power profile if it exists */
- switch (request->type) {
- case AMD_PP_GFX_PROFILE:
- ret = ci_set_power_profile_state(
- adev,
- &pi->gfx_power_profile);
- break;
- case AMD_PP_COMPUTE_PROFILE:
- ret = ci_set_power_profile_state(
- adev,
- &pi->compute_power_profile);
- break;
- default:
- return -EINVAL;
- }
- }
-
- if (!ret)
- pi->current_power_profile = request->type;
-
- return 0;
-}
-
-static int ci_dpm_reset_power_profile_state(void *handle,
- struct amd_pp_profile *request)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct ci_power_info *pi = ci_get_pi(adev);
-
- if (!pi || !request)
- return -EINVAL;
-
- if (request->type == AMD_PP_GFX_PROFILE) {
- pi->gfx_power_profile = pi->default_gfx_power_profile;
- return ci_dpm_set_power_profile_state(adev,
- &pi->gfx_power_profile);
- } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
- pi->compute_power_profile =
- pi->default_compute_power_profile;
- return ci_dpm_set_power_profile_state(adev,
- &pi->compute_power_profile);
- } else
- return -EINVAL;
-}
-
-static int ci_dpm_switch_power_profile(void *handle,
- enum amd_pp_profile_type type)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct ci_power_info *pi = ci_get_pi(adev);
- struct amd_pp_profile request = {0};
-
- if (!pi)
- return -EINVAL;
-
- if (pi->current_power_profile != type) {
- request.type = type;
- return ci_dpm_set_power_profile_state(adev, &request);
- }
-
- return 0;
-}
-
static int ci_dpm_read_sensor(void *handle, int idx,
void *value, int *size)
{
.set_mclk_od = ci_dpm_set_mclk_od,
.check_state_equal = ci_check_state_equal,
.get_vce_clock_state = amdgpu_get_vce_clock_state,
- .get_power_profile_state = ci_dpm_get_power_profile_state,
- .set_power_profile_state = ci_dpm_set_power_profile_state,
- .reset_power_profile_state = ci_dpm_reset_power_profile_state,
- .switch_power_profile = ci_dpm_switch_power_profile,
.read_sensor = ci_dpm_read_sensor,
};
bool fan_is_controlled_by_smc;
u32 t_min;
u32 fan_ctrl_default_mode;
-
- /* power profile */
- struct amd_pp_profile gfx_power_profile;
- struct amd_pp_profile compute_power_profile;
- struct amd_pp_profile default_gfx_power_profile;
- struct amd_pp_profile default_compute_power_profile;
- enum amd_pp_profile_type current_power_profile;
};
#define CISLANDS_VOLTAGE_CONTROL_NONE 0x0
int (*get_pp_table)(void *handle, char **table);
int (*set_pp_table)(void *handle, const char *buf, size_t size);
void (*debugfs_print_current_performance_level)(void *handle, struct seq_file *m);
-
- int (*reset_power_profile_state)(void *handle,
- struct amd_pp_profile *request);
- int (*get_power_profile_state)(void *handle,
- struct amd_pp_profile *query);
- int (*set_power_profile_state)(void *handle,
- struct amd_pp_profile *request);
int (*switch_power_profile)(void *handle,
enum amd_pp_profile_type type);
/* export to amdgpu */
return NULL;
}
-static int pp_dpm_reset_power_profile_state(void *handle,
- struct amd_pp_profile *request)
-{
- struct pp_hwmgr *hwmgr;
- struct pp_instance *pp_handle = (struct pp_instance *)handle;
-
- if (!request || pp_check(pp_handle))
- return -EINVAL;
-
- hwmgr = pp_handle->hwmgr;
-
- if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
- pr_info("%s was not implemented.\n", __func__);
- return 0;
- }
-
- if (request->type == AMD_PP_GFX_PROFILE) {
- hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
- return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
- &hwmgr->gfx_power_profile);
- } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
- hwmgr->compute_power_profile =
- hwmgr->default_compute_power_profile;
- return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
- &hwmgr->compute_power_profile);
- } else
- return -EINVAL;
-}
-
-static int pp_dpm_get_power_profile_state(void *handle,
- struct amd_pp_profile *query)
-{
- struct pp_hwmgr *hwmgr;
- struct pp_instance *pp_handle = (struct pp_instance *)handle;
-
- if (!query || pp_check(pp_handle))
- return -EINVAL;
-
- hwmgr = pp_handle->hwmgr;
-
- if (query->type == AMD_PP_GFX_PROFILE)
- memcpy(query, &hwmgr->gfx_power_profile,
- sizeof(struct amd_pp_profile));
- else if (query->type == AMD_PP_COMPUTE_PROFILE)
- memcpy(query, &hwmgr->compute_power_profile,
- sizeof(struct amd_pp_profile));
- else
- return -EINVAL;
-
- return 0;
-}
-
static int pp_get_power_profile_mode(void *handle, char *buf)
{
struct pp_hwmgr *hwmgr;
return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
}
-static int pp_dpm_set_power_profile_state(void *handle,
- struct amd_pp_profile *request)
-{
- struct pp_hwmgr *hwmgr;
- struct pp_instance *pp_handle = (struct pp_instance *)handle;
- int ret = -1;
-
- if (!request || pp_check(pp_handle))
- return -EINVAL;
-
- hwmgr = pp_handle->hwmgr;
-
- if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
- pr_info("%s was not implemented.\n", __func__);
- return 0;
- }
-
- if (request->min_sclk ||
- request->min_mclk ||
- request->activity_threshold ||
- request->up_hyst ||
- request->down_hyst) {
- if (request->type == AMD_PP_GFX_PROFILE)
- memcpy(&hwmgr->gfx_power_profile, request,
- sizeof(struct amd_pp_profile));
- else if (request->type == AMD_PP_COMPUTE_PROFILE)
- memcpy(&hwmgr->compute_power_profile, request,
- sizeof(struct amd_pp_profile));
- else
- return -EINVAL;
-
- if (request->type == hwmgr->current_power_profile)
- ret = hwmgr->hwmgr_func->set_power_profile_state(
- hwmgr,
- request);
- } else {
- /* set power profile if it exists */
- switch (request->type) {
- case AMD_PP_GFX_PROFILE:
- ret = hwmgr->hwmgr_func->set_power_profile_state(
- hwmgr,
- &hwmgr->gfx_power_profile);
- break;
- case AMD_PP_COMPUTE_PROFILE:
- ret = hwmgr->hwmgr_func->set_power_profile_state(
- hwmgr,
- &hwmgr->compute_power_profile);
- break;
- default:
- return -EINVAL;
- }
- }
-
- if (!ret)
- hwmgr->current_power_profile = request->type;
-
- return 0;
-}
-
static int pp_dpm_switch_power_profile(void *handle,
enum amd_pp_profile_type type)
{
.set_mclk_od = pp_dpm_set_mclk_od,
.read_sensor = pp_dpm_read_sensor,
.get_vce_clock_state = pp_dpm_get_vce_clock_state,
- .reset_power_profile_state = pp_dpm_reset_power_profile_state,
- .get_power_profile_state = pp_dpm_get_power_profile_state,
- .set_power_profile_state = pp_dpm_set_power_profile_state,
.switch_power_profile = pp_dpm_switch_power_profile,
.set_clockgating_by_smu = pp_set_clockgating_by_smu,
.notify_smu_memory_info = pp_dpm_notify_smu_memory_info,
return ret;
}
-int phm_reset_power_profile_state(struct pp_hwmgr *hwmgr)
-{
- int ret = 0;
-
- if (hwmgr->hwmgr_func->set_power_profile_state) {
- if (hwmgr->current_power_profile == AMD_PP_GFX_PROFILE)
- ret = hwmgr->hwmgr_func->set_power_profile_state(
- hwmgr,
- &hwmgr->gfx_power_profile);
- else if (hwmgr->current_power_profile == AMD_PP_COMPUTE_PROFILE)
- ret = hwmgr->hwmgr_func->set_power_profile_state(
- hwmgr,
- &hwmgr->compute_power_profile);
- }
- return ret;
-}
-
int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
struct pp_power_state *adjusted_ps,
const struct pp_power_state *current_ps)
if (!phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level))
hwmgr->dpm_level = hwmgr->request_dpm_level;
- phm_reset_power_profile_state(hwmgr);
-
return 0;
}
return 0;
}
-static void smu7_find_min_clock_masks(struct pp_hwmgr *hwmgr,
- uint32_t *sclk_mask, uint32_t *mclk_mask,
- uint32_t min_sclk, uint32_t min_mclk)
-{
- struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
- struct smu7_dpm_table *dpm_table = &(data->dpm_table);
- uint32_t i;
-
- for (i = 0; i < dpm_table->sclk_table.count; i++) {
- if (dpm_table->sclk_table.dpm_levels[i].enabled &&
- dpm_table->sclk_table.dpm_levels[i].value >= min_sclk)
- *sclk_mask |= 1 << i;
- }
-
- for (i = 0; i < dpm_table->mclk_table.count; i++) {
- if (dpm_table->mclk_table.dpm_levels[i].enabled &&
- dpm_table->mclk_table.dpm_levels[i].value >= min_mclk)
- *mclk_mask |= 1 << i;
- }
-}
-
-static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
- int tmp_result, result = 0;
- uint32_t sclk_mask = 0, mclk_mask = 0;
-
- if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)
- return -EINVAL;
-
- if (smum_is_dpm_running(hwmgr)) {
- if (!data->sclk_dpm_key_disabled)
- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
-
- if (!data->mclk_dpm_key_disabled)
- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
- }
-
- tmp_result = smum_populate_requested_graphic_levels(hwmgr, request);
- PP_ASSERT_WITH_CODE(!tmp_result,
- "Failed to populate requested graphic levels!",
- result = tmp_result);
-
- if (smum_is_dpm_running(hwmgr)) {
- if (!data->sclk_dpm_key_disabled)
- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
-
- if (!data->mclk_dpm_key_disabled)
- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
- }
-
- smu7_find_min_clock_masks(hwmgr, &sclk_mask, &mclk_mask,
- request->min_sclk, request->min_mclk);
-
- if (sclk_mask) {
- if (!data->sclk_dpm_key_disabled)
- smum_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SCLKDPM_SetEnabledMask,
- data->dpm_level_enable_mask.
- sclk_dpm_enable_mask &
- sclk_mask);
- }
-
- if (mclk_mask) {
- if (!data->mclk_dpm_key_disabled)
- smum_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_MCLKDPM_SetEnabledMask,
- data->dpm_level_enable_mask.
- mclk_dpm_enable_mask &
- mclk_mask);
- }
-
- return result;
-}
-
static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
uint32_t virtual_addr_low,
uint32_t virtual_addr_hi,
.get_clock_by_type = smu7_get_clock_by_type,
.read_sensor = smu7_read_sensor,
.dynamic_state_management_disable = smu7_disable_dpm_tasks,
- .set_power_profile_state = smu7_set_power_profile_state,
.avfs_control = smu7_avfs_control,
.disable_smc_firmware_ctf = smu7_thermal_disable_alert,
.start_thermal_controller = smu7_start_thermal_controller,
return result;
}
-static int vega10_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
- struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
- uint32_t min_level;
-
- hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
- hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
- /* Optimize compute power profile: Use only highest
- * 2 power levels (if more than 2 are available)
- */
- if (dpm_table->count > 2)
- min_level = dpm_table->count - 2;
- else if (dpm_table->count == 2)
- min_level = 1;
- else
- min_level = 0;
-
- hwmgr->default_compute_power_profile.min_sclk =
- dpm_table->dpm_levels[min_level].value;
-
- hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
-
- return 0;
-}
-
/**
* Initializes the SMC table and uploads it
*
PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
return result);
vega10_acg_enable(hwmgr);
- vega10_save_default_power_profile(hwmgr);
return 0;
}
return result;
}
-static void vega10_find_min_clock_index(struct pp_hwmgr *hwmgr,
- uint32_t *sclk_idx, uint32_t *mclk_idx,
- uint32_t min_sclk, uint32_t min_mclk)
-{
- struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
- struct vega10_dpm_table *dpm_table = &(data->dpm_table);
- uint32_t i;
-
- for (i = 0; i < dpm_table->gfx_table.count; i++) {
- if (dpm_table->gfx_table.dpm_levels[i].enabled &&
- dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) {
- *sclk_idx = i;
- break;
- }
- }
-
- for (i = 0; i < dpm_table->mem_table.count; i++) {
- if (dpm_table->mem_table.dpm_levels[i].enabled &&
- dpm_table->mem_table.dpm_levels[i].value >= min_mclk) {
- *mclk_idx = i;
- break;
- }
- }
-}
-
-static int vega10_set_power_profile_state(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
- uint32_t sclk_idx = ~0, mclk_idx = ~0;
-
- if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)
- return -EINVAL;
-
- vega10_find_min_clock_index(hwmgr, &sclk_idx, &mclk_idx,
- request->min_sclk, request->min_mclk);
-
- if (sclk_idx != ~0) {
- if (!data->registry_data.sclk_dpm_key_disabled)
- smum_send_msg_to_smc_with_parameter(
- hwmgr,
- PPSMC_MSG_SetSoftMinGfxclkByIndex,
- sclk_idx);
- }
-
- if (mclk_idx != ~0) {
- if (!data->registry_data.mclk_dpm_key_disabled)
- smum_send_msg_to_smc_with_parameter(
- hwmgr,
- PPSMC_MSG_SetSoftMinUclkByIndex,
- mclk_idx);
- }
-
- return 0;
-}
-
static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
{
struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
vega10_check_smc_update_required_for_display_configuration,
.power_off_asic = vega10_power_off_asic,
.disable_smc_firmware_ctf = vega10_thermal_disable_alert,
- .set_power_profile_state = vega10_set_power_profile_state,
.get_sclk_od = vega10_get_sclk_od,
.set_sclk_od = vega10_set_sclk_od,
.get_mclk_od = vega10_get_mclk_od,
extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks);
extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr);
-extern int phm_reset_power_profile_state(struct pp_hwmgr *hwmgr);
#endif /* _HARDWARE_MANAGER_H_ */
uint32_t (*get_offsetof)(uint32_t type, uint32_t member);
uint32_t (*get_mac_definition)(uint32_t value);
bool (*is_dpm_running)(struct pp_hwmgr *hwmgr);
- int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request);
bool (*is_hw_avfs_present)(struct pp_hwmgr *hwmgr);
int (*update_dpm_settings)(struct pp_hwmgr *hwmgr, void *profile_setting);
};
int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value, int *size);
- int (*set_power_profile_state)(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request);
int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable);
int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr);
int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count);
uint32_t feature_mask;
/* UMD Pstate */
- struct amd_pp_profile gfx_power_profile;
- struct amd_pp_profile compute_power_profile;
- struct amd_pp_profile default_gfx_power_profile;
- struct amd_pp_profile default_compute_power_profile;
- enum amd_pp_profile_type current_power_profile;
bool en_umd_pstate;
uint32_t power_profile_mode;
uint32_t default_power_profile_mode;
extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr);
-extern int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request);
-
extern bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr);
extern int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_setting);
return ci_is_smc_ram_running(hwmgr);
}
-static int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct ci_smumgr *smu_data = (struct ci_smumgr *)
- (hwmgr->smu_backend);
- struct SMU7_Discrete_GraphicsLevel *levels =
- smu_data->smc_state_table.GraphicsLevel;
- uint32_t array = smu_data->dpm_table_start +
- offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) *
- SMU7_MAX_LEVELS_GRAPHICS;
- uint32_t i;
-
- 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].UpH = request->up_hyst;
- levels[i].DownH = request->down_hyst;
- }
-
- return ci_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
-}
-
-
static int ci_smu_init(struct pp_hwmgr *hwmgr)
{
struct ci_smumgr *ci_priv = NULL;
.get_mac_definition = ci_get_mac_definition,
.initialize_mc_reg_table = ci_initialize_mc_reg_table,
.is_dpm_running = ci_is_dpm_running,
- .populate_requested_graphic_levels = ci_populate_requested_graphic_levels,
.update_dpm_settings = ci_update_dpm_settings,
};
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;
PP_ASSERT_WITH_CODE(0 == result,
"Failed to setup dpm led config", return result);
- fiji_save_default_power_profile(hwmgr);
-
return 0;
}
? true : false;
}
-static int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct fiji_smumgr *smu_data = (struct fiji_smumgr *)
- (hwmgr->smu_backend);
- 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 i;
-
- 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;
- }
-
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
-}
-
static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr,
void *profile_setting)
{
.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,
};
}
-static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smu_backend);
- struct SMU74_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].SclkSetting.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;
-}
-
static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
{
int result;
PP_ASSERT_WITH_CODE(0 == result,
"Failed to populate PM fuses to SMC memory!", return result);
- polaris10_save_default_power_profile(hwmgr);
-
return 0;
}
? true : false;
}
-static int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)
- (hwmgr->smu_backend);
- struct SMU74_Discrete_GraphicsLevel *levels =
- smu_data->smc_state_table.GraphicsLevel;
- uint32_t array = smu_data->smu7_data.dpm_table_start +
- offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
- SMU74_MAX_LEVELS_GRAPHICS;
- uint32_t i;
-
- 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;
- }
-
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
-}
-
static int polaris10_update_dpm_settings(struct pp_hwmgr *hwmgr,
void *profile_setting)
{
.populate_all_memory_levels = polaris10_populate_all_memory_levels,
.get_mac_definition = polaris10_get_mac_definition,
.is_dpm_running = polaris10_is_dpm_running,
- .populate_requested_graphic_levels = polaris10_populate_requested_graphic_levels,
.is_hw_avfs_present = polaris10_is_hw_avfs_present,
.update_dpm_settings = polaris10_update_dpm_settings,
};
return true;
}
-int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- if (hwmgr->smumgr_funcs->populate_requested_graphic_levels)
- return hwmgr->smumgr_funcs->populate_requested_graphic_levels(
- hwmgr, request);
-
- return 0;
-}
-
bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
{
if (hwmgr->smumgr_funcs->is_hw_avfs_present)
smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0];
}
-static void tonga_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct tonga_smumgr *data = (struct tonga_smumgr *)(hwmgr->smu_backend);
- struct SMU72_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;
-}
-
static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
{
int result;
PP_ASSERT_WITH_CODE((!result),
"Failed to populate initialize MC Reg table !", return result);
- tonga_save_default_power_profile(hwmgr);
-
return 0;
}
? true : false;
}
-static int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct tonga_smumgr *smu_data = (struct tonga_smumgr *)
- (hwmgr->smu_backend);
- struct SMU72_Discrete_GraphicsLevel *levels =
- smu_data->smc_state_table.GraphicsLevel;
- uint32_t array = smu_data->smu7_data.dpm_table_start +
- offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU72_Discrete_GraphicsLevel) *
- SMU72_MAX_LEVELS_GRAPHICS;
- uint32_t i;
-
- 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;
- }
-
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
-}
-
static int tonga_update_dpm_settings(struct pp_hwmgr *hwmgr,
void *profile_setting)
{
.get_mac_definition = tonga_get_mac_definition,
.initialize_mc_reg_table = tonga_initialize_mc_reg_table,
.is_dpm_running = tonga_is_dpm_running,
- .populate_requested_graphic_levels = tonga_populate_requested_graphic_levels,
.update_dpm_settings = tonga_update_dpm_settings,
};