summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/powerplay
diff options
context:
space:
mode:
authorEric Huang <JinHuiEric.Huang@amd.com>2016-09-12 16:17:44 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-03-29 23:52:48 -0400
commit34bb2734d1bc3c72e4739234481c0efab0941d14 (patch)
treec31583ca0511581253f37aea943ba840d8388bfd /drivers/gpu/drm/amd/powerplay
parent3f14e6231858f4d9a2e965f54202f7a3f69c79d0 (diff)
drm/amd/amdgpu: add power profile sysfs entry
Add the sysfs entries pp_gfx_power_profile and pp_compute_power_profile which give user a way to set power profile through parameters minimum sclk, minimum mclk, activity threshold, up hysteresis and down hysteresis only when the entry power_dpm_force_performance_level is in default value "auto". It is read and write. Example: echo 500 800 20 0 5 > /sys/class/drm/card0/device/pp_*_power_profile cat /sys/class/drm/card0/device/pp_*_power_profile 500 800 20 0 5 Note: first parameter is sclk in MHz, second is mclk in MHz, third is activity threshold in percentage, fourth is up hysteresis in ms and fifth is down hysteresis in ms. echo set > /sys/class/drm/card0/device/pp_*_power_profile To set power profile state if it exists. echo reset > /sys/class/drm/card0/device/pp_*_power_profile To restore default state and clear previous setting. Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com> Acked-by: Rex Zhu <Rex.Zhu@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay')
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c136
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h8
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h9
3 files changed, 152 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index e9cf207b9dcf..8074386da36f 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -917,10 +917,140 @@ pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
if (hwmgr && idx < hwmgr->num_vce_state_tables)
return &hwmgr->vce_states[idx];
-
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_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)
+{
+ struct pp_hwmgr *hwmgr;
+ struct amd_pp_profile request = {0};
+ struct pp_instance *pp_handle = (struct pp_instance *)handle;
+
+ if (pp_check(pp_handle))
+ return -EINVAL;
+
+ hwmgr = pp_handle->hwmgr;
+
+ if (hwmgr->current_power_profile != type) {
+ request.type = type;
+ pp_dpm_set_power_profile_state(handle, &request);
+ }
+
+ return 0;
+}
+
const struct amd_powerplay_funcs pp_dpm_funcs = {
.get_temperature = pp_dpm_get_temperature,
.load_firmware = pp_dpm_load_fw,
@@ -949,6 +1079,10 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
.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,
};
int amd_powerplay_create(struct amd_pp_init *pp_init,
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
index 6dd5f0e9ef87..4b4f5ff2f039 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
@@ -361,6 +361,14 @@ struct amd_powerplay_funcs {
int (*set_mclk_od)(void *handle, uint32_t value);
int (*read_sensor)(void *handle, int idx, int32_t *value);
struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx);
+ 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);
};
struct amd_powerplay {
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 7275a29293eb..768f81f365ca 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -358,6 +358,8 @@ struct pp_hwmgr_func {
int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, int32_t *value);
int (*request_firmware)(struct pp_hwmgr *hwmgr);
int (*release_firmware)(struct pp_hwmgr *hwmgr);
+ int (*set_power_profile_state)(struct pp_hwmgr *hwmgr,
+ struct amd_pp_profile *request);
};
struct pp_table_func {
@@ -650,6 +652,13 @@ struct pp_hwmgr {
struct pp_power_state *uvd_ps;
struct amd_pp_display_configuration display_config;
uint32_t feature_mask;
+
+ /* 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;
};
extern int hwmgr_early_init(struct pp_instance *handle);