<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<p style="font-family:Arial;font-size:10pt;color:#0000FF;margin:5pt;" align="Left">
[AMD Official Use Only]<br>
</p>
<br>
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255);display:inline !important">> The whole idea seems
 fine to me. However, we are trying to do some cleanups to avoid spiking into power internals(as above via adev->powerplay.pp_funcs->emit_clock_levels).</span><br>
<span style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255);display:inline !important">> Check the patch series
 below:</span><br style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255)">
> <a href="https://lists.freedesktop.org/archives/amd-gfx/2021-December/072096.html" style="margin:0px;font-size:14.6667px;font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;background-color:rgb(255, 255, 255)">https://lists.freedesktop.org/archives/amd-gfx/2021-December/072096.html</a><br style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255)">
<span style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255);display:inline !important">> So, it would be better
 if you can rebase the patches here based on that. Or you can wait a while to let me land them first.</span><br style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255)">
<br style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255)">
<span style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255);display:inline !important">> BR</span><br style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255)">
<span style="font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;font-size:14.6667px;background-color:rgb(255, 255, 255);display:inline !important">> Evan</span><br>
</div>
<div id="appendonsend"></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
I can wait for it to land and rebase then, will send v2 of series once this happens</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
Darren</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Quan, Evan <Evan.Quan@amd.com><br>
<b>Sent:</b> Wednesday, December 8, 2021 8:48 PM<br>
<b>To:</b> Powell, Darren <Darren.Powell@amd.com>; amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org><br>
<b>Cc:</b> Powell, Darren <Darren.Powell@amd.com><br>
<b>Subject:</b> RE: [PATCH 1/3] amdgpu/pm: Implement new API function "emit" that accepts buffer base and write offset</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="PlainText">[AMD Official Use Only]<br>
<br>
<br>
<br>
> -----Original Message-----<br>
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of<br>
> Darren Powell<br>
> Sent: Wednesday, December 8, 2021 2:36 PM<br>
> To: amd-gfx@lists.freedesktop.org<br>
> Cc: Powell, Darren <Darren.Powell@amd.com><br>
> Subject: [PATCH 1/3] amdgpu/pm: Implement new API function "emit" that<br>
> accepts buffer base and write offset<br>
> <br>
>  - new power management function emit_clk_levels implemented by<br>
> navi10_emit_clk_levels()<br>
>        This function currently duplicates the functionality of<br>
> navi10_print_clk_levels, where<br>
>        snprintf is used write to the sysfs buffer. The first implementation to use<br>
> sysfs_emit<br>
>        was unsuccessful due to requirement that buf must be aligned to a<br>
> specific memory<br>
>        boundary. This solution passes the buffer base and write offset down the<br>
> stack.<br>
>  - new power management function emit_clock_levels implemented by<br>
> smu_emit_ppclk_levels()<br>
>        This function combines implementation of smu_print_ppclk_levels and<br>
>        smu_print_smuclk_levels and calls emit_clk_levels<br>
>  - new helper function smu_convert_to_smuclk called by<br>
> smu_print_ppclk_levels and<br>
>        smu_emit_ppclk_levels<br>
>  - emit_clock_levels currently returns the length of the string written to the<br>
> buffer,<br>
>        maintaining the behaviour of print_clock_levels, but will be upgraded to<br>
> return<br>
>        error values in a subsequent patch<br>
>  - failure of the emit_clock_levels at the top level<br>
> (amdgpu_get_pp_dpm_clock) triggers a<br>
>        fallback to the print_clock_levels, which can be removed after<br>
> emit_clock_levels is<br>
>        implemented across all platforms.<br>
> <br>
>  == Test ==<br>
>  LOGFILE=pp_clk.test.log<br>
>  AMDGPU_PCI_ADDR=`lspci -nn | grep "VGA\|Display" | cut -d " " -f 1`<br>
>  AMDGPU_HWMON=`ls -la /sys/class/hwmon | grep $AMDGPU_PCI_ADDR |<br>
> awk '{print $9}'`<br>
>  HWMON_DIR=/sys/class/hwmon/${AMDGPU_HWMON}<br>
> <br>
>  lspci -nn | grep "VGA\|Display"  > $LOGFILE<br>
>  FILES="pp_od_clk_voltage<br>
>  pp_dpm_sclk<br>
>  pp_dpm_mclk<br>
>  pp_dpm_pcie<br>
>  pp_dpm_socclk<br>
>  pp_dpm_fclk<br>
>  pp_dpm_dcefclk<br>
>  pp_dpm_vclk<br>
>  pp_dpm_dclk "<br>
> <br>
>  for f in $FILES<br>
>  do<br>
>    echo === $f === >> $LOGFILE<br>
>    cat $HWMON_DIR/device/$f >> $LOGFILE<br>
>  done<br>
>  cat $LOGFILE<br>
> <br>
> Signed-off-by: Darren Powell <darren.powell@amd.com><br>
> ---<br>
>  .../gpu/drm/amd/include/kgd_pp_interface.h    |   1 +<br>
>  drivers/gpu/drm/amd/pm/amdgpu_pm.c            |  20 +-<br>
>  drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h       |   3 +<br>
>  drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h       |  10 +<br>
>  drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     |  50 ++++-<br>
>  .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 189<br>
> ++++++++++++++++++<br>
>  6 files changed, 262 insertions(+), 11 deletions(-)<br>
> <br>
> diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h<br>
> b/drivers/gpu/drm/amd/include/kgd_pp_interface.h<br>
> index bac15c466733..43f43a4f321b 100644<br>
> --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h<br>
> +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h<br>
> @@ -310,6 +310,7 @@ struct amd_pm_funcs {<br>
>        int (*get_fan_speed_pwm)(void *handle, u32 *speed);<br>
>        int (*force_clock_level)(void *handle, enum pp_clock_type type,<br>
> uint32_t mask);<br>
>        int (*print_clock_levels)(void *handle, enum pp_clock_type type,<br>
> char *buf);<br>
> +     int (*emit_clock_levels)(void *handle, enum pp_clock_type type,<br>
> char *buf, int *offset);<br>
>        int (*force_performance_level)(void *handle, enum<br>
> amd_dpm_forced_level level);<br>
>        int (*get_sclk_od)(void *handle);<br>
>        int (*set_sclk_od)(void *handle, uint32_t value);<br>
> diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c<br>
> b/drivers/gpu/drm/amd/pm/amdgpu_pm.c<br>
> index 49df4c20f09e..a1169a2397ca 100644<br>
> --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c<br>
> +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c<br>
> @@ -1056,8 +1056,8 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct<br>
> device *dev,<br>
>  {<br>
>        struct drm_device *ddev = dev_get_drvdata(dev);<br>
>        struct amdgpu_device *adev = drm_to_adev(ddev);<br>
> -     ssize_t size;<br>
> -     int ret;<br>
> +     int size = 0;<br>
> +     int ret = 0;<br>
> <br>
>        if (amdgpu_in_reset(adev))<br>
>                return -EPERM;<br>
> @@ -1070,10 +1070,18 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct<br>
> device *dev,<br>
>                return ret;<br>
>        }<br>
> <br>
> -     if (adev->powerplay.pp_funcs->print_clock_levels)<br>
> -             size = amdgpu_dpm_print_clock_levels(adev, type, buf);<br>
> -     else<br>
> -             size = sysfs_emit(buf, "\n");<br>
> +     ret = -EOPNOTSUPP;<br>
> +     if (adev->powerplay.pp_funcs->emit_clock_levels) {<br>
> +             ret = amdgpu_dpm_emit_clock_levels(adev, type, buf,<br>
> &size);<br>
> +     }<br>
The whole idea seems fine to me. However, we are trying to do some cleanups to avoid spiking into power internals(as above via adev->powerplay.pp_funcs->emit_clock_levels).<br>
Check the patch series below:<br>
<a href="https://lists.freedesktop.org/archives/amd-gfx/2021-December/072096.html">https://lists.freedesktop.org/archives/amd-gfx/2021-December/072096.html</a><br>
So, it would be better if you can rebase the patches here based on that. Or you can wait a while to let me land them first.<br>
<br>
BR<br>
Evan<br>
> +<br>
> +     if (ret < 0) {<br>
> +             if (adev->powerplay.pp_funcs->print_clock_levels) {<br>
> +                     size = amdgpu_dpm_print_clock_levels(adev, type,<br>
> buf);<br>
> +             }<br>
> +             else<br>
> +                     size = sysfs_emit(buf, "\n");<br>
> +     }<br>
> <br>
>        pm_runtime_mark_last_busy(ddev->dev);<br>
>        pm_runtime_put_autosuspend(ddev->dev);<br>
> diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h<br>
> b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h<br>
> index 16e3f72d31b9..95add7afcc86 100644<br>
> --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h<br>
> +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h<br>
> @@ -310,6 +310,9 @@ enum amdgpu_pcie_gen {<br>
>  #define amdgpu_dpm_print_clock_levels(adev, type, buf) \<br>
>                ((adev)->powerplay.pp_funcs->print_clock_levels((adev)-<br>
> >powerplay.pp_handle, type, buf))<br>
> <br>
> +#define amdgpu_dpm_emit_clock_levels(adev, type, buf, offset) \<br>
> +             ((adev)->powerplay.pp_funcs->emit_clock_levels((adev)-<br>
> >powerplay.pp_handle, type, buf, offset))<br>
> +<br>
>  #define amdgpu_dpm_force_clock_level(adev, type, level) \<br>
>                ((adev)->powerplay.pp_funcs->force_clock_level((adev)-<br>
> >powerplay.pp_handle, type, level))<br>
> <br>
> diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h<br>
> b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h<br>
> index f738f7dc20c9..dc1325783c10 100644<br>
> --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h<br>
> +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h<br>
> @@ -620,6 +620,16 @@ struct pptable_funcs {<br>
>         */<br>
>        int (*print_clk_levels)(struct smu_context *smu, enum<br>
> smu_clk_type clk_type, char *buf);<br>
> <br>
> +     /**<br>
> +      * @emit_clk_levels: Print DPM clock levels for a clock domain<br>
> +      *                    to buffer using sysfs_emit_at. Star current level.<br>
> +      *<br>
> +      * Used for sysfs interfaces.<br>
> +      * &buf: sysfs buffer<br>
> +      * &offset: offset within buffer to start printing<br>
> +      */<br>
> +     int (*emit_clk_levels)(struct smu_context *smu, enum<br>
> smu_clk_type clk_type, char *buf, int *offset);<br>
> +<br>
>        /**<br>
>         * @force_clk_levels: Set a range of allowed DPM levels for a clock<br>
>         *                    domain.<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> index e156add7b560..b0638d8308d2 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> @@ -2397,11 +2397,8 @@ static int smu_print_smuclk_levels(struct<br>
> smu_context *smu, enum smu_clk_type cl<br>
>        return ret;<br>
>  }<br>
> <br>
> -static int smu_print_ppclk_levels(void *handle,<br>
> -                               enum pp_clock_type type,<br>
> -                               char *buf)<br>
> +static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type<br>
> type)<br>
>  {<br>
> -     struct smu_context *smu = handle;<br>
>        enum smu_clk_type clk_type;<br>
> <br>
>        switch (type) {<br>
> @@ -2434,12 +2431,54 @@ static int smu_print_ppclk_levels(void *handle,<br>
>        case OD_CCLK:<br>
>                clk_type = SMU_OD_CCLK; break;<br>
>        default:<br>
> -             return -EINVAL;<br>
> +             clk_type = SMU_CLK_COUNT; break;<br>
>        }<br>
> <br>
> +     return clk_type;<br>
> +}<br>
> +<br>
> +static int smu_print_ppclk_levels(void *handle,<br>
> +                               enum pp_clock_type type,<br>
> +                               char *buf)<br>
> +{<br>
> +     struct smu_context *smu = handle;<br>
> +     enum smu_clk_type clk_type;<br>
> +<br>
> +     clk_type = smu_convert_to_smuclk(type);<br>
> +     if (clk_type == SMU_CLK_COUNT)<br>
> +             return -EINVAL;<br>
> +<br>
>        return smu_print_smuclk_levels(smu, clk_type, buf);<br>
>  }<br>
> <br>
> +static int smu_emit_ppclk_levels(void *handle, enum pp_clock_type type,<br>
> char *buf, int *offset)<br>
> +{<br>
> +     struct smu_context *smu = handle;<br>
> +     enum smu_clk_type clk_type;<br>
> +     int ret = 0;<br>
> +<br>
> +     clk_type = smu_convert_to_smuclk(type);<br>
> +     if (clk_type == SMU_CLK_COUNT)<br>
> +             return -EINVAL;<br>
> +<br>
> +     if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)<br>
> +             return -EOPNOTSUPP;<br>
> +<br>
> +     mutex_lock(&smu->mutex);<br>
> +<br>
> +     if (smu->ppt_funcs->emit_clk_levels) {<br>
> +             ret = smu->ppt_funcs->emit_clk_levels(smu, clk_type, buf,<br>
> offset);<br>
> +     }<br>
> +     else {<br>
> +             ret = -EOPNOTSUPP;<br>
> +     }<br>
> +<br>
> +     mutex_unlock(&smu->mutex);<br>
> +<br>
> +     return ret;<br>
> +<br>
> +}<br>
> +<br>
>  static int smu_od_edit_dpm_table(void *handle,<br>
>                                 enum PP_OD_DPM_TABLE_COMMAND<br>
> type,<br>
>                                 long *input, uint32_t size)<br>
> @@ -3117,6 +3156,7 @@ static const struct amd_pm_funcs<br>
> swsmu_pm_funcs = {<br>
>        .get_fan_speed_pwm   = smu_get_fan_speed_pwm,<br>
>        .force_clock_level       = smu_force_ppclk_levels,<br>
>        .print_clock_levels      = smu_print_ppclk_levels,<br>
> +     .emit_clock_levels       = smu_emit_ppclk_levels,<br>
>        .force_performance_level = smu_force_performance_level,<br>
>        .read_sensor             = smu_read_sensor,<br>
>        .get_performance_level   = smu_get_performance_level,<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> index 60a557068ea4..e43c7e950a55 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> @@ -1261,6 +1261,194 @@ static void navi10_od_setting_get_range(struct<br>
> smu_11_0_overdrive_table *od_tabl<br>
>                *max = od_table->max[setting];<br>
>  }<br>
> <br>
> +static int navi10_emit_clk_levels(struct smu_context *smu,<br>
> +                     enum smu_clk_type clk_type, char *buf, int *offset)<br>
> +{<br>
> +     uint16_t *curve_settings;<br>
> +     int ret = 0;<br>
> +     uint32_t cur_value = 0, value = 0;<br>
> +     uint32_t freq_values[3] = {0};<br>
> +     uint32_t i, levels, mark_index = 0, count = 0;<br>
> +     struct smu_table_context *table_context = &smu->smu_table;<br>
> +     uint32_t gen_speed, lane_width;<br>
> +     struct smu_dpm_context *smu_dpm = &smu->smu_dpm;<br>
> +     struct smu_11_0_dpm_context *dpm_context = smu_dpm-<br>
> >dpm_context;<br>
> +     PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;<br>
> +     OverDriveTable_t *od_table =<br>
> +             (OverDriveTable_t *)table_context->overdrive_table;<br>
> +     struct smu_11_0_overdrive_table *od_settings = smu->od_settings;<br>
> +     uint32_t min_value, max_value;<br>
> +     int save_offset = *offset;<br>
> +<br>
> +     switch (clk_type) {<br>
> +     case SMU_GFXCLK:<br>
> +     case SMU_SCLK:<br>
> +     case SMU_SOCCLK:<br>
> +     case SMU_MCLK:<br>
> +     case SMU_UCLK:<br>
> +     case SMU_FCLK:<br>
> +     case SMU_VCLK:<br>
> +     case SMU_DCLK:<br>
> +     case SMU_DCEFCLK:<br>
> +             ret = navi10_get_current_clk_freq_by_table(smu, clk_type,<br>
> &cur_value);<br>
> +             if (ret)<br>
> +                     return 0;<br>
> +<br>
> +             ret = smu_v11_0_get_dpm_level_count(smu, clk_type,<br>
> &count);<br>
> +             if (ret)<br>
> +                     return 0;<br>
> +<br>
> +             if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {<br>
> +                     for (i = 0; i < count; i++) {<br>
> +                             ret =<br>
> smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value);<br>
> +                             if (ret)<br>
> +                                     return (*offset - save_offset);<br>
> +<br>
> +                             *offset += sysfs_emit_at(buf, *offset,<br>
> "%d: %uMhz %s\n", i, value,<br>
> +                                             cur_value == value ? "*" : "");<br>
> +<br>
> +                     }<br>
> +             } else {<br>
> +                     ret = smu_v11_0_get_dpm_freq_by_index(smu,<br>
> clk_type, 0, &freq_values[0]);<br>
> +                     if (ret)<br>
> +                             return 0;<br>
> +                     ret = smu_v11_0_get_dpm_freq_by_index(smu,<br>
> clk_type, count - 1, &freq_values[2]);<br>
> +                     if (ret)<br>
> +                             return 0;<br>
> +<br>
> +                     freq_values[1] = cur_value;<br>
> +                     mark_index = cur_value == freq_values[0] ? 0 :<br>
> +                                  cur_value == freq_values[2] ? 2 : 1;<br>
> +<br>
> +                     levels = 3;<br>
> +                     if (mark_index != 1) {<br>
> +                             levels = 2;<br>
> +                             freq_values[1] = freq_values[2];<br>
> +                     }<br>
> +<br>
> +                     for (i = 0; i < levels; i++) {<br>
> +                             *offset += sysfs_emit_at(buf, *offset,<br>
> "%d: %uMhz %s\n", i, freq_values[i],<br>
> +                                             i == mark_index ? "*" : "");<br>
> +                     }<br>
> +             }<br>
> +             break;<br>
> +     case SMU_PCIE:<br>
> +             gen_speed =<br>
> smu_v11_0_get_current_pcie_link_speed_level(smu);<br>
> +             lane_width =<br>
> smu_v11_0_get_current_pcie_link_width_level(smu);<br>
> +             for (i = 0; i < NUM_LINK_LEVELS; i++) {<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "%d: %s %s %dMhz %s\n", i,<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "",<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" :<br>
> +                                     (dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "",<br>
> +                                     pptable->LclkFreq[i],<br>
> +                                     (gen_speed == dpm_context-<br>
> >dpm_tables.pcie_table.pcie_gen[i]) &&<br>
> +                                     (lane_width == dpm_context-<br>
> >dpm_tables.pcie_table.pcie_lane[i]) ?<br>
> +                                     "*" : "");<br>
> +             }<br>
> +             break;<br>
> +     case SMU_OD_SCLK:<br>
> +             if (!smu->od_enabled || !od_table || !od_settings)<br>
> +                     break;<br>
> +             if (!navi10_od_feature_is_supported(od_settings,<br>
> SMU_11_0_ODCAP_GFXCLK_LIMITS))<br>
> +                     break;<br>
> +             *offset += sysfs_emit_at(buf, *offset,<br>
> "OD_SCLK:\n0: %uMhz\n1: %uMhz\n",<br>
> +                                       od_table->GfxclkFmin, od_table-<br>
> >GfxclkFmax);<br>
> +             break;<br>
> +     case SMU_OD_MCLK:<br>
> +             if (!smu->od_enabled || !od_table || !od_settings)<br>
> +                     break;<br>
> +             if (!navi10_od_feature_is_supported(od_settings,<br>
> SMU_11_0_ODCAP_UCLK_MAX))<br>
> +                     break;<br>
> +             *offset += sysfs_emit_at(buf, *offset,<br>
> "OD_MCLK:\n1: %uMHz\n", od_table->UclkFmax);<br>
> +             break;<br>
> +     case SMU_OD_VDDC_CURVE:<br>
> +             if (!smu->od_enabled || !od_table || !od_settings)<br>
> +                     break;<br>
> +             if (!navi10_od_feature_is_supported(od_settings,<br>
> SMU_11_0_ODCAP_GFXCLK_CURVE))<br>
> +                     break;<br>
> +             *offset += sysfs_emit_at(buf, *offset,<br>
> "OD_VDDC_CURVE:\n");<br>
> +             for (i = 0; i < 3; i++) {<br>
> +                     switch (i) {<br>
> +                     case 0:<br>
> +                             curve_settings = &od_table->GfxclkFreq1;<br>
> +                             break;<br>
> +                     case 1:<br>
> +                             curve_settings = &od_table->GfxclkFreq2;<br>
> +                             break;<br>
> +                     case 2:<br>
> +                             curve_settings = &od_table->GfxclkFreq3;<br>
> +                             break;<br>
> +                     default:<br>
> +                             break;<br>
> +                     }<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "%d: %uMHz %umV\n",<br>
> +                                               i, curve_settings[0],<br>
> +                                     curve_settings[1] /<br>
> NAVI10_VOLTAGE_SCALE);<br>
> +             }<br>
> +             break;<br>
> +     case SMU_OD_RANGE:<br>
> +             if (!smu->od_enabled || !od_table || !od_settings)<br>
> +                     break;<br>
> +             *offset += sysfs_emit_at(buf, *offset, "%s:\n",<br>
> "OD_RANGE");<br>
> +<br>
> +             if (navi10_od_feature_is_supported(od_settings,<br>
> SMU_11_0_ODCAP_GFXCLK_LIMITS)) {<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_GFXCLKFMIN,<br>
> +                                                 &min_value, NULL);<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_GFXCLKFMAX,<br>
> +                                                 NULL, &max_value);<br>
> +                     *offset+= sysfs_emit_at(buf, *offset,<br>
> "SCLK: %7uMhz %10uMhz\n",<br>
> +                                     min_value, max_value);<br>
> +             }<br>
> +<br>
> +             if (navi10_od_feature_is_supported(od_settings,<br>
> SMU_11_0_ODCAP_UCLK_MAX)) {<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_UCLKFMAX,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset+= sysfs_emit_at(buf, *offset,<br>
> "MCLK: %7uMhz %10uMhz\n",<br>
> +                                     min_value, max_value);<br>
> +             }<br>
> +<br>
> +             if (navi10_od_feature_is_supported(od_settings,<br>
> SMU_11_0_ODCAP_GFXCLK_CURVE)) {<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",<br>
> +                                           min_value, max_value);<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",<br>
> +                                           min_value, max_value);<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",<br>
> +                                           min_value, max_value);<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",<br>
> +                                           min_value, max_value);<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",<br>
> +                                           min_value, max_value);<br>
> +                     navi10_od_setting_get_range(od_settings,<br>
> SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3,<br>
> +                                                 &min_value, &max_value);<br>
> +                     *offset += sysfs_emit_at(buf, *offset,<br>
> "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",<br>
> +                                           min_value, max_value);<br>
> +             }<br>
> +<br>
> +             break;<br>
> +     default:<br>
> +             break;<br>
> +     }<br>
> +<br>
> +     return (*offset - save_offset);<br>
> +}<br>
> +<br>
>  static int navi10_print_clk_levels(struct smu_context *smu,<br>
>                        enum smu_clk_type clk_type, char *buf)<br>
>  {<br>
> @@ -3245,6 +3433,7 @@ static const struct pptable_funcs navi10_ppt_funcs<br>
> = {<br>
>        .i2c_init = navi10_i2c_control_init,<br>
>        .i2c_fini = navi10_i2c_control_fini,<br>
>        .print_clk_levels = navi10_print_clk_levels,<br>
> +     .emit_clk_levels = navi10_emit_clk_levels,<br>
>        .force_clk_levels = navi10_force_clk_levels,<br>
>        .populate_umd_state_clk = navi10_populate_umd_state_clk,<br>
>        .get_clock_by_type_with_latency =<br>
> navi10_get_clock_by_type_with_latency,<br>
> --<br>
> 2.34.1<br>
</div>
</span></font></div>
</div>
</body>
</html>