On Thu, Jan 18, 2018 at 3:37 AM, Rex Zhu <Rex.Zhu at amd.com> wrote: > when cat pp_od_clk_voltage it show > OD_SCLK: > 0: 300Mhz 800 mV > 1: 466Mhz 818 mV > 2: 751Mhz 824 mV > 3: 1019Mhz 987 mV > 4: 1074Mhz 1037 mV > 5: 1126Mhz 1087 mV > 6: 1169Mhz 1137 mV > 7: 1206Mhz 1150 mV > OD_MCLK: > 0: 300Mhz 800 mV > 1: 1650Mhz 1000 mV > > echo "s/m level clock voltage" to change > sclk/mclk's clock and voltage > > echo "r" to restore default value. > echo "c" to commit the user setting. > > Signed-off-by: Rex Zhu <Rex.Zhu at amd.com> Reviewed-by: Alex Deucher <alexander.deucher at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 4 ++ > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 96 +++++++++++++++++++++++++- > drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 + > drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 19 +++++ > 4 files changed, 119 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > index 986f1d5..4b5755e 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > @@ -374,6 +374,10 @@ enum amdgpu_pcie_gen { > ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ > (adev)->powerplay.pp_handle, parameter, size)) > > +#define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ > + ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ > + (adev)->powerplay.pp_handle, type, parameter, size)) > + > struct amdgpu_dpm { > struct amdgpu_ps *ps; > /* number of valid power states */ > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > index ed9012a..f8ba194 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > @@ -360,6 +360,88 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, > return count; > } > > +static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, > + struct device_attribute *attr, > + const char *buf, > + size_t count) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + int ret; > + uint32_t parameter_size = 0; > + long parameter[64]; > + char buf_cpy[128]; > + char *tmp_str; > + char *sub_str; > + const char delimiter[3] = {' ', '\n', '\0'}; > + uint32_t type; > + > + if (count > 127) > + return -EINVAL; > + > + if (*buf == 'c') { > + if (adev->powerplay.pp_funcs->dispatch_tasks) { > + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); > + return count; > + } else { > + return -EINVAL; > + } > + } > + > + if (*buf == 's') > + type = PP_ODN_SCLK_VDDC_TABLE; > + else if (*buf == 'm') > + type = PP_ODN_MCLK_VDDC_TABLE; > + else if(*buf == 'r') > + type = PP_ODN_RESET_DEFAULT_TABLE; > + else > + return -EINVAL; > + > + memcpy(buf_cpy, buf, count+1); > + > + tmp_str = buf_cpy; > + > + while (isspace(*++tmp_str)); > + > + while (tmp_str[0]) { > + sub_str = strsep(&tmp_str, delimiter); > + ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); > + if (ret) > + return -EINVAL; > + parameter_size++; > + > + while (isspace(*tmp_str)) > + tmp_str++; > + } > + > + if (adev->powerplay.pp_funcs->odn_edit_dpm_table) > + ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, > + parameter, parameter_size); > + > + if (ret) > + return -EINVAL; > + > + return count; > +} > + > +static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + uint32_t size = 0; > + > + if (adev->powerplay.pp_funcs->print_clock_levels) { > + size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); > + size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); > + return size; > + } else { > + return snprintf(buf, PAGE_SIZE, "\n"); > + } > + > +} > + > static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, > struct device_attribute *attr, > char *buf) > @@ -842,6 +924,10 @@ static DEVICE_ATTR(pp_compute_power_profile, S_IRUGO | S_IWUSR, > static DEVICE_ATTR(pp_power_profile_mode, S_IRUGO | S_IWUSR, > amdgpu_get_pp_power_profile_mode, > amdgpu_set_pp_power_profile_mode); > +static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, > + amdgpu_get_pp_od_clk_voltage, > + amdgpu_set_pp_od_clk_voltage); > + > static ssize_t amdgpu_hwmon_show_temp(struct device *dev, > struct device_attribute *attr, > char *buf) > @@ -1481,7 +1567,13 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) > "pp_power_profile_mode\n"); > return ret; > } > - > + ret = device_create_file(adev->dev, > + &dev_attr_pp_od_clk_voltage); > + if (ret) { > + DRM_ERROR("failed to create device file " > + "pp_od_clk_voltage\n"); > + return ret; > + } > ret = amdgpu_debugfs_pm_init(adev); > if (ret) { > DRM_ERROR("Failed to register debugfs file for dpm!\n"); > @@ -1519,6 +1611,8 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) > &dev_attr_pp_compute_power_profile); > device_remove_file(adev->dev, > &dev_attr_pp_power_profile_mode); > + device_remove_file(adev->dev, > + &dev_attr_pp_od_clk_voltage); > } > > void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) > diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h > index 3e8b9cc..f7393f9 100644 > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h > @@ -309,6 +309,7 @@ struct amd_pm_funcs { > struct amd_pp_simple_clock_info *clocks); > int (*get_power_profile_mode)(void *handle, char *buf); > int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); > + int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); > }; > > #endif > diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > index d9cb424..854c43c 100644 > --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > @@ -1122,6 +1122,24 @@ static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) > return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); > } > > +static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) > +{ > + struct pp_hwmgr *hwmgr; > + struct pp_instance *pp_handle = (struct pp_instance *)handle; > + > + if (pp_check(pp_handle)) > + return -EINVAL; > + > + hwmgr = pp_handle->hwmgr; > + > + if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { > + pr_info("%s was not implemented.\n", __func__); > + return -EINVAL; > + } > + > + 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) > { > @@ -1507,6 +1525,7 @@ static int pp_get_display_mode_validation_clocks(void *handle, > .notify_smu_memory_info = pp_dpm_notify_smu_memory_info, > .get_power_profile_mode = pp_get_power_profile_mode, > .set_power_profile_mode = pp_set_power_profile_mode, > + .odn_edit_dpm_table = pp_odn_edit_dpm_table, > /* export to DC */ > .get_sclk = pp_dpm_get_sclk, > .get_mclk = pp_dpm_get_mclk, > -- > 1.9.1 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx