int (*get_fan_speed_pwm)(void *handle, u32 *speed);
int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask);
int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
+ int (*emit_clock_levels)(void *handle, enum pp_clock_type type, char *buf, int *offset);
int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level);
int (*get_sclk_od)(void *handle);
int (*set_sclk_od)(void *handle, uint32_t value);
return ret;
}
+int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev,
+ enum pp_clock_type type,
+ char *buf,
+ int *offset)
+{
+ const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+ int ret = 0;
+
+ if (!pp_funcs->emit_clock_levels)
+ return -ENOENT;
+
+ mutex_lock(&adev->pm.mutex);
+ ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle,
+ type,
+ buf,
+ offset);
+ mutex_unlock(&adev->pm.mutex);
+
+ return ret;
+}
+
int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
uint64_t ppfeature_masks)
{
int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
enum pp_clock_type type,
char *buf);
+int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev,
+ enum pp_clock_type type,
+ char *buf,
+ int *offset);
int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
uint64_t ppfeature_masks);
int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf);
return ret;
}
-static int smu_print_ppclk_levels(void *handle,
- enum pp_clock_type type,
- char *buf)
+static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
{
- struct smu_context *smu = handle;
enum smu_clk_type clk_type;
switch (type) {
case OD_CCLK:
clk_type = SMU_OD_CCLK; break;
default:
- return -EINVAL;
+ clk_type = SMU_CLK_COUNT; break;
}
+ return clk_type;
+}
+
+static int smu_print_ppclk_levels(void *handle,
+ enum pp_clock_type type,
+ char *buf)
+{
+ struct smu_context *smu = handle;
+ enum smu_clk_type clk_type;
+
+ clk_type = smu_convert_to_smuclk(type);
+ if (clk_type == SMU_CLK_COUNT)
+ return -EINVAL;
+
return smu_print_smuclk_levels(smu, clk_type, buf);
}
+static int smu_emit_ppclk_levels(void *handle, enum pp_clock_type type, char *buf, int *offset)
+{
+ struct smu_context *smu = handle;
+ enum smu_clk_type clk_type;
+ int ret = 0;
+
+ clk_type = smu_convert_to_smuclk(type);
+ if (clk_type == SMU_CLK_COUNT)
+ return -EINVAL;
+
+ if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
+ return -EOPNOTSUPP;
+
+ if (!smu->ppt_funcs->emit_clk_levels)
+ ret = -ENOENT;
+
+ return smu->ppt_funcs->emit_clk_levels(smu, clk_type, buf, offset);
+
+}
+
static int smu_od_edit_dpm_table(void *handle,
enum PP_OD_DPM_TABLE_COMMAND type,
long *input, uint32_t size)
.get_fan_speed_pwm = smu_get_fan_speed_pwm,
.force_clock_level = smu_force_ppclk_levels,
.print_clock_levels = smu_print_ppclk_levels,
+ .emit_clock_levels = smu_emit_ppclk_levels,
.force_performance_level = smu_force_performance_level,
.read_sensor = smu_read_sensor,
.get_performance_level = smu_get_performance_level,
* to buffer. Star current level.
*
* Used for sysfs interfaces.
+ * Return: Number of characters written to the buffer
*/
int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf);
+ /**
+ * @emit_clk_levels: Print DPM clock levels for a clock domain
+ * to buffer using sysfs_emit_at. Star current level.
+ *
+ * Used for sysfs interfaces.
+ * &buf: sysfs buffer
+ * &offset: offset within buffer to start printing, which is updated by the
+ * function.
+ *
+ * Return: 0 on Success or Negative to indicate an error occurred.
+ */
+ int (*emit_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf, int *offset);
+
/**
* @force_clk_levels: Set a range of allowed DPM levels for a clock
* domain.