[PATCH] drm/amd/powerplay: expose vega20 OD features

Zhu, Rex Rex.Zhu at amd.com
Fri Aug 24 16:32:18 UTC 2018



> -----Original Message-----
> From: Alex Deucher <alexdeucher at gmail.com>
> Sent: Friday, August 24, 2018 11:48 PM
> To: Quan, Evan <Evan.Quan at amd.com>
> Cc: amd-gfx list <amd-gfx at lists.freedesktop.org>; Xu, Feifei
> <Feifei.Xu at amd.com>; Kuehling, Felix <Felix.Kuehling at amd.com>; Deucher,
> Alexander <Alexander.Deucher at amd.com>; Zhu, Rex <Rex.Zhu at amd.com>;
> Zhang, Hawking <Hawking.Zhang at amd.com>
> Subject: Re: [PATCH] drm/amd/powerplay: expose vega20 OD features
> 
> On Fri, Aug 24, 2018 at 3:45 AM Evan Quan <evan.quan at amd.com> wrote:
> >
> > Vega20 simplifies the OD logics and it can not fit old OD interfaces.
> > Thus we design new OD interfaces for vega20.
> 
> Please split this into two patches, one to add the internal od8_settings API,
> and one to wire it up to sysfs.  A few more comments below.
> 
> >
> > Change-Id: I888faec46a81287ae24f452ce16b42c1f6d06d7d
> > Signed-off-by: Evan Quan <evan.quan at amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h       |   8 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 125 ++++++++++++
> >  .../gpu/drm/amd/include/kgd_pp_interface.h    |   2 +
> >  drivers/gpu/drm/amd/powerplay/amd_powerplay.c |  37 ++++
> >  .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 191
> +++++++++++++++++-
> >  drivers/gpu/drm/amd/powerplay/inc/hwmgr.h     |   2 +
> >  6 files changed, 362 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
> > index ff24e1cc5b65..84b3e6f87abf 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
> > @@ -357,6 +357,14 @@ enum amdgpu_pcie_gen {
> >                 ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\
> >                         (adev)->powerplay.pp_handle, type, parameter,
> > size))
> >
> > +#define amdgpu_dpm_get_od8_settings(adev, buf) \
> > +               ((adev)->powerplay.pp_funcs->get_od8_settings(\
> > +                       (adev)->powerplay.pp_handle, buf))
> > +
> > +#define amdgpu_dpm_set_od8_settings(adev, parameter, size) \
> > +               ((adev)->powerplay.pp_funcs->set_od8_settings(\
> > +                       (adev)->powerplay.pp_handle, 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 daa55fb06171..94cd7c503372 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > @@ -934,6 +934,121 @@ static ssize_t amdgpu_get_busy_percent(struct
> device *dev,
> >         return snprintf(buf, PAGE_SIZE, "%d\n", value);  }
> >
> > +/**
> > + * DOC: pp_od8_settings
> > + *
> > + * The amdgpu driver provides a sysfs API for adjusting the clocks,
> > +voltages,
> > + * power limit, fan speed and temperature. The pp_od8_settings is
> > +used for
> > + * this.
> > + *
> > + * Reading the file will display:
> > + *
> > + * - a name list of the features that are able to be adjusted
> > + *
> > + * - the mininum and maximum allowed value for each supported
> > + *   feature labeled in format of "[mininum - maximum]"
> > + *
> > + * - the current value for each supported feature labeled after
> > + *   ":"
> > + *
> > + * To manually adjust these settings:
> > + *
> > + * - write a string that contains the new value for each supported
> > + *   feature. For those which do not need to be changed, just enter
> > + *   their old value
> > + *
> > + * - make sure the new value is within the allowed ranges between
> > + *   the minimum and maximum
> 
> We should probably also make it a set and commit model like we do for
> previous asics for consistency.  That way you can see the changes, and then
> apply them.
> 
> > + *
> > + * All the possible supported features:
> > + *
> > + * - Gfx clock
> > + *   The min and max frequency can be specified by GfxclkFmin
> > + *   and GfxclkFmax(both in Mhz). Intermediate levels are
> > + *   stretched/shrunk according to ratio in original table.
> > + *
> > + * - Gfx voltage
> > + *   With three pairs of gfx clk(in Mhz) and offset voltage(in mV)
> > + *   combinations specified, smu fw can calibrate the voltage
> > + *   curve automatically.
> > + *     - GfxclkFreq1 <-> GfxclkOffsetVolt1
> > + *     - GfxclkFreq2 <-> GfxclkOffsetVolt2
> > + *     - GfxclkFreq3 <-> GfxclkOffsetVolt3
> > + *
> > + * - Uclk
> > + *   The max memory clock can be specified by UclkFmax(in Mhz).
> > + *
> > + * - Power limit
> > + *   The power limit can be increased or descreased by
> > + *   OverDrivePct(in percent).
> 
> We already expose the power limit via hwmon.  Do we still need it here?
> 
> > + *
> > + * - Fan spped
> 
> spped -> speed
> 
> > + *   The max fan speed can be set by FanMaxinumRpm and the
> 
> FanMaxinumRpm -> FanMaximumRpm
> 
> > + *   min fan speed by FanMinimumPwm. Also zero rpm enablement
> > + *   is specified by FanZeroRpmEnable.
> > + *
> > + * - Temperature
> > + *   The fan target temperature can be set by FanTargetTemperature
> > + *   and max Tj temperature by MaxOpTemp.
> 
> The fan and temp stuff might be a better fit for the hwmon interfaces:
> https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
> 
> > + *
> > + */
> > +
> > +static ssize_t amdgpu_get_pp_od8_settings(struct device *dev,
> > +               struct device_attribute *attr,
> > +               char *buf)
> > +{
> > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > +       struct amdgpu_device *adev = ddev->dev_private;
> > +
> > +       if (adev->powerplay.pp_funcs->get_od8_settings)
> > +               return amdgpu_dpm_get_od8_settings(adev, buf);
> > +
> > +       return snprintf(buf, PAGE_SIZE, "\n"); }
> > +
> > +static ssize_t amdgpu_set_pp_od8_settings(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;
> > +       char *sub_str, *tmp_str, buf_cpy[128];
> > +       const char delimiter[3] = {' ', '\n', '\0'};
> > +       uint32_t parameter_size = 0;
> > +       long parameter[64];
> > +       int ret = 0xff;
> > +
> > +       if (count >= sizeof(buf_cpy) / sizeof(buf_cpy[0]))
> > +               return -EINVAL;
> > +
> > +       memcpy(buf_cpy, buf, count);
> > +       buf_cpy[count] = '\0';
> > +
> > +       tmp_str = buf_cpy;
> > +
> > +       while (isspace(*tmp_str)) tmp_str++;
> > +
> > +       while (tmp_str[0]) {
> > +               sub_str = strsep(&tmp_str, delimiter);
> > +               ret = kstrtol(sub_str, 0, &parameter[parameter_size]);
> > +               if (ret)
> > +                       return -EINVAL;
> > +               parameter_size++;
> > +
> > +               while (isspace(*tmp_str))
> > +                       tmp_str++;
> > +       }
> > +
> > +       if (adev->powerplay.pp_funcs->set_od8_settings)
> > +               ret = amdgpu_dpm_set_od8_settings(adev, parameter,
> > + parameter_size);
> > +
> > +       if (ret)
> > +               return -EINVAL;
> > +
> > +       return count;
> > +}
> > +
> >  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,
> > @@ -969,6 +1084,9 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO
> | S_IWUSR,
> >                 amdgpu_set_pp_od_clk_voltage);  static
> > DEVICE_ATTR(gpu_busy_percent, S_IRUGO,
> >                 amdgpu_get_busy_percent, NULL);
> > +static DEVICE_ATTR(pp_od8_settings, S_IRUGO | S_IWUSR,
> > +               amdgpu_get_pp_od8_settings,
> > +               amdgpu_set_pp_od8_settings);
> 
> Rather than adding a new file, would it make more sense to expose this new
> API on the same file we use for older asics?  Otherwise, every time the
> interface changes, we'll need to add a new file.  We already handle asic
> specific differences in the power profile sysfs files.
> 
> >
> >  static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
> >                                       struct device_attribute *attr,
> > @@ -1879,6 +1997,13 @@ int amdgpu_pm_sysfs_init(struct
> amdgpu_device *adev)
> >                                 "gpu_busy_level\n");
> >                 return ret;
> >         }
> > +       ret = device_create_file(adev->dev,
> > +                       &dev_attr_pp_od8_settings);
> > +       if (ret) {
> > +               DRM_ERROR("failed to create device file "
> > +                               "pp_od8_settings\n");
> > +               return ret;
> > +       }
> >         ret = amdgpu_debugfs_pm_init(adev);
> >         if (ret) {
> >                 DRM_ERROR("Failed to register debugfs file for
> > dpm!\n"); diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > index 6a41b81c7325..e23746ba53bf 100644
> > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > @@ -269,6 +269,8 @@ struct amd_pm_funcs {
> >         int (*get_display_mode_validation_clocks)(void *handle,
> >                 struct amd_pp_simple_clock_info *clocks);
> >         int (*notify_smu_enable_pwe)(void *handle);
> > +       int (*get_od8_settings)(void *handle, char *buf);
> > +       int (*set_od8_settings)(void *handle, 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 da4ebff5b74d..4bcd06306698 100644
> > --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
> > +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
> > @@ -883,6 +883,41 @@ static int pp_odn_edit_dpm_table(void *handle,
> uint32_t type, long *input, uint3
> >         return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type,
> > input, size);  }
> >
> > +static int pp_get_od8_settings(void *handle, char *buf) {
> > +       struct pp_hwmgr *hwmgr = handle;
> > +
> > +       if (!hwmgr || !hwmgr->pm_en || !buf)
> > +               return -EINVAL;
> > +
> > +       if (hwmgr->hwmgr_func->get_od8_settings == NULL) {
> > +               pr_info("%s was not implemented.\n", __func__);
> > +               return snprintf(buf, PAGE_SIZE, "\n");
> > +       }
> > +
> > +       return hwmgr->hwmgr_func->get_od8_settings(hwmgr, buf); }
> > +
> > +static int pp_set_od8_settings(void *handle, long *input, uint32_t
> > +size) {
> > +       struct pp_hwmgr *hwmgr = handle;
> > +       int ret = -EINVAL;
> > +
> > +       if (!hwmgr || !hwmgr->pm_en)
> > +               return ret;
> > +
> > +       if (hwmgr->hwmgr_func->set_od8_settings == NULL) {
> > +               pr_info("%s was not implemented.\n", __func__);
> > +               return ret;
> > +       }
> > +
> > +       mutex_lock(&hwmgr->smu_lock);
> > +       ret = hwmgr->hwmgr_func->set_od8_settings(hwmgr, input, size);
> > +       mutex_unlock(&hwmgr->smu_lock);
> > +
> > +       return ret;
> > +}
> > +
> >  static int pp_dpm_switch_power_profile(void *handle,
> >                 enum PP_SMC_POWER_PROFILE type, bool en)  { @@ -1272,6
> > +1307,8 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
> >         .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,
> > +       .get_od8_settings = pp_get_od8_settings,
> > +       .set_od8_settings = pp_set_od8_settings,
> >         .set_power_limit = pp_set_power_limit,
> >         .get_power_limit = pp_get_power_limit,
> >  /* export to DC */
> > diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > index fb32b28afa66..ececa2f7fe5f 100644
> > --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > @@ -1099,7 +1099,188 @@ static int
> vega20_od8_initialize_default_settings(
> >         return 0;
> >  }
> >
> > -static int vega20_od8_set_settings(
> > +static int vega20_get_od8_settings(
> > +               struct pp_hwmgr *hwmgr,
> > +               char *buf)
> > +{
> > +       struct vega20_hwmgr *data =
> > +                       (struct vega20_hwmgr *)(hwmgr->backend);
> > +       struct vega20_od8_single_setting *od8_settings =
> > +                       data->od8_settings.od8_settings_array;
> > +       OverDriveTable_t od_table;
> > +       uint32_t size = 0;
> > +       int ret = 0;
> > +
> > +       if (!buf)
> > +               return -EINVAL;
> > +
> > +       ret = vega20_copy_table_from_smc(hwmgr,
> > +                       (uint8_t *)(&od_table),
> > +                       TABLE_OVERDRIVE);
> > +       PP_ASSERT_WITH_CODE(!ret,
> > +                       "Failed to export over drive table!",
> > +                       return ret);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFmin",
> > +                               od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
> > +                               od8_settings[OD8_SETTING_GFXCLK_FMIN].max_value,
> > +                               od_table.GfxclkFmin);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFmax",
> > +                               od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value,
> > +                               od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value,
> > +                               od_table.GfxclkFmax);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFreq1",
> > +                               od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
> > +                               od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value,
> > +                               od_table.GfxclkFreq1);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "GfxclkOffsetVolt1",
> > +
> od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
> > +
> od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value,
> > +                               od_table.GfxclkOffsetVolt1);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFreq2",
> > +                               od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
> > +                               od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value,
> > +                               od_table.GfxclkFreq2);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "GfxclkOffsetVolt2",
> > +
> od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
> > +
> od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value,
> > +                               od_table.GfxclkOffsetVolt2);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFreq3",
> > +                               od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
> > +                               od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value,
> > +                               od_table.GfxclkFreq3);
> > +
> > +       if (od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "GfxclkOffsetVolt3",
> > +
> od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
> > +
> od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value,
> > +                               od_table.GfxclkOffsetVolt3);
> > +
> > +       if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "UclkFmax",
> > +                               od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
> > +                               od8_settings[OD8_SETTING_UCLK_FMAX].max_value,
> > +                               od_table.UclkFmax);
> > +
> > +       if (od8_settings[OD8_SETTING_POWER_PERCENTAGE].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "OverDrivePct",
> > +
> od8_settings[OD8_SETTING_POWER_PERCENTAGE].min_value,
> > +
> od8_settings[OD8_SETTING_POWER_PERCENTAGE].max_value,
> > +                               od_table.OverDrivePct);
> > +
> > +       if (od8_settings[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "FanMaximumRpm",
> > +
> od8_settings[OD8_SETTING_FAN_ACOUSTIC_LIMIT].min_value,
> > +
> od8_settings[OD8_SETTING_FAN_ACOUSTIC_LIMIT].max_value,
> > +                               od_table.FanMaximumRpm);
> > +
> > +       if (od8_settings[OD8_SETTING_FAN_MIN_SPEED].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "FanMinimumPwm",
> > +
> od8_settings[OD8_SETTING_FAN_MIN_SPEED].min_value,
> > +
> od8_settings[OD8_SETTING_FAN_MIN_SPEED].max_value,
> > +                               od_table.FanMinimumPwm);
> > +
> > +       if (od8_settings[OD8_SETTING_FAN_TARGET_TEMP].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "FanTargetTemperautre",
> > +
> od8_settings[OD8_SETTING_FAN_TARGET_TEMP].min_value,
> > +
> od8_settings[OD8_SETTING_FAN_TARGET_TEMP].max_value,
> > +                               od_table.FanTargetTemperature);
> > +
> > +       if (od8_settings[OD8_SETTING_OPERATING_TEMP_MAX].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "MaxOpTemp",
> > +
> od8_settings[OD8_SETTING_OPERATING_TEMP_MAX].min_value,
> > +
> od8_settings[OD8_SETTING_OPERATING_TEMP_MAX].max_value,
> > +                               od_table.MaxOpTemp);
> > +
> > +       if (od8_settings[OD8_SETTING_FAN_ZERO_RPM_CONTROL].feature_id)
> > +               size += sprintf(buf + size, "%22s[%d - %d]: %u\n",
> "FanZeroRpmEnable",
> > +
> od8_settings[OD8_SETTING_FAN_ZERO_RPM_CONTROL].min_value,
> > +
> od8_settings[OD8_SETTING_FAN_ZERO_RPM_CONTROL].max_value,
> > +                               od_table.FanZeroRpmEnable);
> > +
> > +       return size;
> > +}
> > +
> > +static int vega20_set_od8_settings(
> > +               struct pp_hwmgr *hwmgr,
> > +               long *input,
> > +               uint32_t size)
> > +{
> > +       struct vega20_hwmgr *data =
> > +                       (struct vega20_hwmgr *)(hwmgr->backend);
> > +       struct vega20_od8_single_setting *od8_settings =
> > +                       data->od8_settings.od8_settings_array;
> > +       OverDriveTable_t od_table;
> > +       uint16_t *buf = (uint16_t *)(&od_table);
> > +       uint32_t i, j = 0, k;
> > +       int ret = 0;
> > +
> > +       /* retrieve current overdrive settings */
> > +       ret = vega20_copy_table_from_smc(hwmgr,
> > +                       (uint8_t *)(&od_table),
> > +                       TABLE_OVERDRIVE);
> > +       PP_ASSERT_WITH_CODE(!ret,
> > +                       "Failed to export over drive table!",
> > +                       return ret);
> > +
> > +       for (i = 0;
> > +            i < (sizeof(OverDriveTable_t) / sizeof(uint16_t)) - 1;
> > +            i++) {
> > +               /* overdrive table supports no dram timing setting */
> > +               k = (i == OD8_SETTING_AC_TIMING) ?
> > +                       OD8_SETTING_FAN_ZERO_RPM_CONTROL : i;
> > +               /*
> > +                * Not all OD settings are supported and exported
> > +                * to user.
> > +                * So, updated only those which are supported and
> > +                * exported to user.
> > +                */
> > +               if (od8_settings[k].feature_id) {
> > +                       if (input[j] < od8_settings[k].min_value ||
> > +                           input[j] > od8_settings[k].max_value)
> > +                               return -EINVAL;
> > +
> > +                       buf[i] = input[j];
> > +                       if (j++ >= size - 1)
> > +                               break;
> > +               }
> > +       }
> > +
> > +       /* enable the new overdrive settings */
> > +       ret = vega20_copy_table_to_smc(hwmgr,
> > +                       (uint8_t *)(&od_table),
> > +                       TABLE_OVERDRIVE);
> > +       PP_ASSERT_WITH_CODE(!ret,
> > +                       "Failed to import over drive table!",
> > +                       return ret);
> > +
> > +       /* update the current_value of overdrive settings */
> > +       for (i = 0;
> > +            i < (sizeof(OverDriveTable_t) / sizeof(uint16_t)) - 1;
> > +            i++) {
> > +               k = (i == OD8_SETTING_AC_TIMING) ?
> > +                       OD8_SETTING_FAN_ZERO_RPM_CONTROL : i;
> > +               if (od8_settings[k].feature_id)
> > +                       od8_settings[k].current_value = buf[i];
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int vega20_od8_set_single_setting(
> >                 struct pp_hwmgr *hwmgr,
> >                 uint32_t index,
> >                 uint32_t value)
> > @@ -1198,7 +1379,7 @@ static int vega20_set_sclk_od(
> >         do_div(od_sclk, 100);
> >         od_sclk +=
> > golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
> >
> > -       ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX,
> od_sclk);
> > +       ret = vega20_od8_set_single_setting(hwmgr,
> > + OD8_SETTING_GFXCLK_FMAX, od_sclk);
> >         PP_ASSERT_WITH_CODE(!ret,
> >                         "[SetSclkOD] failed to set od gfxclk!",
> >                         return ret);
> > @@ -1245,7 +1426,7 @@ static int vega20_set_mclk_od(
> >         do_div(od_mclk, 100);
> >         od_mclk +=
> > golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
> >
> > -       ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX,
> od_mclk);
> > +       ret = vega20_od8_set_single_setting(hwmgr,
> > + OD8_SETTING_UCLK_FMAX, od_mclk);
> >         PP_ASSERT_WITH_CODE(!ret,
> >                         "[SetMclkOD] failed to set od memclk!",
> >                         return ret);
> > @@ -2966,6 +3147,10 @@ static const struct pp_hwmgr_func
> vega20_hwmgr_funcs = {
> >                 vega20_get_power_profile_mode,
> >         .set_power_profile_mode =
> >                 vega20_set_power_profile_mode,
> > +       .get_od8_settings =
> > +               vega20_get_od8_settings,
> > +       .set_od8_settings =
> > +               vega20_set_od8_settings,
> >         /* od related */
> >         .set_power_limit =
> >                 vega20_set_power_limit, diff --git
> > a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
> > b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
> > index a6d92128b19c..285af1728e2e 100644
> > --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
> > +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
> > @@ -328,6 +328,8 @@ struct pp_hwmgr_func {
> >         int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n);
> >         int (*powergate_mmhub)(struct pp_hwmgr *hwmgr);
> >         int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr);
> > +       int (*get_od8_settings)(struct pp_hwmgr *hwmgr, char *buf);
> > +       int (*set_od8_settings)(struct pp_hwmgr *hwmgr, long *input,
> > + uint32_t size);

Those new added interfaces for OD parameters get/set seems have no difference with the old interface.
  
	int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf);
	int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, enum PP_OD_DPM_TABLE_COMMAND type, long *input, uint32_t size);

Regards
Rex
> >  };
> >
> >  struct pp_table_func {
> > --
> > 2.18.0
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list