Commit f3898ea1 authored by Eric Huang's avatar Eric Huang Committed by Alex Deucher

drm/amd/powerplay: add some sysfs interfaces for powerplay.

The new sysfs interfaces:
pp_num_states: Read-only, return the number of all pp states, 0 if powerplay is not available.
pp_cur_state: Read-only, return the index number of current pp state.
pp_force_state: Read-write, to write a power state index will switch to selected state forcedly and
		enable forced state mode, disable forced state mode. such as "echo >...".
pp_table: Read-write, binary output, to be used to read or write the dpm table, the maximum
		file size is 4KB of page size.
pp_dpm_sclk: Read-write, reading will return a dpm levels list, to write an index number will force
		powerplay to set the corresponding dpm level.
pp_dpm_mclk: same as sclk.
pp_dpm_pcie: same as sclk.

And add new setting "manual" to the existing interface power_dpm_force_performance_level.
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarEric Huang <JinHuiEric.Huang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c7e6be23
...@@ -1503,6 +1503,7 @@ enum amdgpu_dpm_forced_level { ...@@ -1503,6 +1503,7 @@ enum amdgpu_dpm_forced_level {
AMDGPU_DPM_FORCED_LEVEL_AUTO = 0, AMDGPU_DPM_FORCED_LEVEL_AUTO = 0,
AMDGPU_DPM_FORCED_LEVEL_LOW = 1, AMDGPU_DPM_FORCED_LEVEL_LOW = 1,
AMDGPU_DPM_FORCED_LEVEL_HIGH = 2, AMDGPU_DPM_FORCED_LEVEL_HIGH = 2,
AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3,
}; };
struct amdgpu_vce_state { struct amdgpu_vce_state {
...@@ -2014,6 +2015,7 @@ struct amdgpu_device { ...@@ -2014,6 +2015,7 @@ struct amdgpu_device {
/* powerplay */ /* powerplay */
struct amd_powerplay powerplay; struct amd_powerplay powerplay;
bool pp_enabled; bool pp_enabled;
bool pp_force_state_enabled;
/* dpm */ /* dpm */
struct amdgpu_pm pm; struct amdgpu_pm pm;
...@@ -2301,6 +2303,21 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) ...@@ -2301,6 +2303,21 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_dpm_get_performance_level(adev) \ #define amdgpu_dpm_get_performance_level(adev) \
(adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
#define amdgpu_dpm_get_pp_num_states(adev, data) \
(adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)
#define amdgpu_dpm_get_pp_table(adev, table) \
(adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)
#define amdgpu_dpm_set_pp_table(adev, buf, size) \
(adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)
#define amdgpu_dpm_print_clock_levels(adev, type, buf) \
(adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)
#define amdgpu_dpm_force_clock_level(adev, type, level) \
(adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)
#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \
(adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
......
This diff is collapsed.
...@@ -433,6 +433,9 @@ enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) ...@@ -433,6 +433,9 @@ enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
case PP_StateUILabel_Performance: case PP_StateUILabel_Performance:
return POWER_STATE_TYPE_PERFORMANCE; return POWER_STATE_TYPE_PERFORMANCE;
default: default:
if (state->classification.flags & PP_StateClassificationFlag_Boot)
return POWER_STATE_TYPE_INTERNAL_BOOT;
else
return POWER_STATE_TYPE_DEFAULT; return POWER_STATE_TYPE_DEFAULT;
} }
} }
...@@ -535,6 +538,112 @@ static int pp_dpm_get_temperature(void *handle) ...@@ -535,6 +538,112 @@ static int pp_dpm_get_temperature(void *handle)
return hwmgr->hwmgr_func->get_temperature(hwmgr); return hwmgr->hwmgr_func->get_temperature(hwmgr);
} }
static int pp_dpm_get_pp_num_states(void *handle,
struct pp_states_info *data)
{
struct pp_hwmgr *hwmgr;
int i;
if (!handle)
return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr;
if (hwmgr == NULL || hwmgr->ps == NULL)
return -EINVAL;
data->nums = hwmgr->num_ps;
for (i = 0; i < hwmgr->num_ps; i++) {
struct pp_power_state *state = (struct pp_power_state *)
((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
switch (state->classification.ui_label) {
case PP_StateUILabel_Battery:
data->states[i] = POWER_STATE_TYPE_BATTERY;
break;
case PP_StateUILabel_Balanced:
data->states[i] = POWER_STATE_TYPE_BALANCED;
break;
case PP_StateUILabel_Performance:
data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
break;
default:
if (state->classification.flags & PP_StateClassificationFlag_Boot)
data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
else
data->states[i] = POWER_STATE_TYPE_DEFAULT;
}
}
return 0;
}
static int pp_dpm_get_pp_table(void *handle, char **table)
{
struct pp_hwmgr *hwmgr;
if (!handle)
return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr;
if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
hwmgr->hwmgr_func->get_pp_table == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_pp_table(hwmgr, table);
}
static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
{
struct pp_hwmgr *hwmgr;
if (!handle)
return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr;
if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
hwmgr->hwmgr_func->set_pp_table == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->set_pp_table(hwmgr, buf, size);
}
static int pp_dpm_force_clock_level(void *handle,
enum pp_clock_type type, int level)
{
struct pp_hwmgr *hwmgr;
if (!handle)
return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr;
if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
hwmgr->hwmgr_func->force_clock_level == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, level);
}
static int pp_dpm_print_clock_levels(void *handle,
enum pp_clock_type type, char *buf)
{
struct pp_hwmgr *hwmgr;
if (!handle)
return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr;
if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
hwmgr->hwmgr_func->print_clock_levels == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
}
const struct amd_powerplay_funcs pp_dpm_funcs = { const struct amd_powerplay_funcs pp_dpm_funcs = {
.get_temperature = pp_dpm_get_temperature, .get_temperature = pp_dpm_get_temperature,
.load_firmware = pp_dpm_load_fw, .load_firmware = pp_dpm_load_fw,
...@@ -552,6 +661,11 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { ...@@ -552,6 +661,11 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
.get_fan_control_mode = pp_dpm_get_fan_control_mode, .get_fan_control_mode = pp_dpm_get_fan_control_mode,
.set_fan_speed_percent = pp_dpm_set_fan_speed_percent, .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
.get_fan_speed_percent = pp_dpm_get_fan_speed_percent, .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
.get_pp_num_states = pp_dpm_get_pp_num_states,
.get_pp_table = pp_dpm_get_pp_table,
.set_pp_table = pp_dpm_set_pp_table,
.force_clock_level = pp_dpm_force_clock_level,
.print_clock_levels = pp_dpm_print_clock_levels,
}; };
static int amd_pp_instance_init(struct amd_pp_init *pp_init, static int amd_pp_instance_init(struct amd_pp_init *pp_init,
......
...@@ -123,6 +123,7 @@ enum amd_dpm_forced_level { ...@@ -123,6 +123,7 @@ enum amd_dpm_forced_level {
AMD_DPM_FORCED_LEVEL_AUTO = 0, AMD_DPM_FORCED_LEVEL_AUTO = 0,
AMD_DPM_FORCED_LEVEL_LOW = 1, AMD_DPM_FORCED_LEVEL_LOW = 1,
AMD_DPM_FORCED_LEVEL_HIGH = 2, AMD_DPM_FORCED_LEVEL_HIGH = 2,
AMD_DPM_FORCED_LEVEL_MANUAL = 3,
}; };
struct amd_pp_init { struct amd_pp_init {
...@@ -225,6 +226,17 @@ enum { ...@@ -225,6 +226,17 @@ enum {
PP_GROUP_MAX PP_GROUP_MAX
}; };
enum pp_clock_type {
PP_SCLK,
PP_MCLK,
PP_PCIE,
};
struct pp_states_info {
uint32_t nums;
uint32_t states[16];
};
#define PP_GROUP_MASK 0xF0000000 #define PP_GROUP_MASK 0xF0000000
#define PP_GROUP_SHIFT 28 #define PP_GROUP_SHIFT 28
...@@ -278,6 +290,11 @@ struct amd_powerplay_funcs { ...@@ -278,6 +290,11 @@ struct amd_powerplay_funcs {
int (*get_fan_control_mode)(void *handle); int (*get_fan_control_mode)(void *handle);
int (*set_fan_speed_percent)(void *handle, uint32_t percent); int (*set_fan_speed_percent)(void *handle, uint32_t percent);
int (*get_fan_speed_percent)(void *handle, uint32_t *speed); int (*get_fan_speed_percent)(void *handle, uint32_t *speed);
int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
int (*get_pp_table)(void *handle, char **table);
int (*set_pp_table)(void *handle, const char *buf, size_t size);
int (*force_clock_level)(void *handle, enum pp_clock_type type, int level);
int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
}; };
struct amd_powerplay { struct amd_powerplay {
......
...@@ -327,6 +327,10 @@ struct pp_hwmgr_func { ...@@ -327,6 +327,10 @@ struct pp_hwmgr_func {
int (*get_dal_power_level)(struct pp_hwmgr *hwmgr, int (*get_dal_power_level)(struct pp_hwmgr *hwmgr,
struct amd_pp_dal_clock_info *info); struct amd_pp_dal_clock_info *info);
int (*power_off_asic)(struct pp_hwmgr *hwmgr); int (*power_off_asic)(struct pp_hwmgr *hwmgr);
int (*get_pp_table)(struct pp_hwmgr *hwmgr, char **table);
int (*set_pp_table)(struct pp_hwmgr *hwmgr, const char *buf, size_t size);
int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, int level);
int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf);
}; };
struct pp_table_func { struct pp_table_func {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment