AMD General
> -----Original Message-----
> From: Lazar, Lijo <[email protected]>
> Sent: Monday, October 12, 2026 12:12
> To: Wang, Kevin <[email protected]>; [email protected]
> Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking
> <[email protected]>; Feng, Kenneth <[email protected]>
> Subject: Re: [PATCH] drm/amd/pm: mark the current DPM clock level active
>
>
>
> On 12-Oct-26 6:57 AM, Kevin Wang wrote:
> > PMFW can report clocks outside or between advertised DPM levels.
> >
> > Report a clock below DPM0 as a special active S level.
> > Mark the nearest level active for a discrete DPM table.
> > Clamp a clock above the table range to the maximum DPM level.
> > Keep reporting the actual clock for a fine-grained DPM table.
> >
> > Signed-off-by: Kevin Wang <[email protected]>
> > ---
> > drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 35 ++++++++++++++++++++------
> > 1 file changed, 27 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
> > b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
> > index 361657c19ea3..8cf616517ddd 100644
> > --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
> > +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
> > @@ -1391,11 +1391,12 @@ int smu_cmn_print_dpm_clk_levels(struct
> smu_context *smu,
> > uint32_t cur_clk, char *buf, int *offset)
> > {
> > uint32_t min_clk, max_clk, level_index, count;
> > + uint32_t nearest_level = 0, nearest_diff = U32_MAX;
> > uint32_t freq_values[3];
> > + uint32_t clk_diff, level_clk;
> > int size, lvl, i;
> > bool is_fine_grained;
> > bool is_deep_sleep;
> > - bool freq_match;
> >
> > if (!dpm_table || !buf)
> > return -EINVAL;
> > @@ -1407,23 +1408,41 @@ int smu_cmn_print_dpm_clk_levels(struct
> smu_context *smu,
> > min_clk = SMU_DPM_TABLE_MIN(dpm_table);
> > max_clk = SMU_DPM_TABLE_MAX(dpm_table);
> >
> > - /* Deep sleep - current clock < min_clock/2, TBD: cur_clk = 0 as GFXOFF
> > */
> > - is_deep_sleep = cur_clk < min_clk / 2;
> > + /* A clock below DPM0 is reported as a special deep-sleep level. */
> > + is_deep_sleep = cur_clk < min_clk;
> > if (is_deep_sleep) {
> > size += sysfs_emit_at(buf, size, "S: %uMhz *\n", cur_clk);
> > level_index = 1;
> > }
> >
> > + /*
> > + * Discrete tables mark the level nearest to the current clock. Clamp
> > + * clocks above the advertised range to the last level. Fine-grained
> > + * tables keep reporting the actual current clock between min and max.
> > + */
> > if (!is_fine_grained || count == 1) {
> > + if (!is_deep_sleep) {
> > + if (cur_clk >= max_clk) {
> > + nearest_level = count - 1;
> > + } else {
> > + for (i = 0; i < count; i++) {
> > + level_clk =
> > dpm_table->dpm_levels[i].value;
> > + clk_diff = cur_clk > level_clk ?
> > + cur_clk - level_clk :
> > level_clk -
> cur_clk;
> > + if (clk_diff < nearest_diff) {
> > + nearest_diff = clk_diff;
> > + nearest_level = i;
> > + }
> > + }
> > + }
> > + }
> > +
> > for (i = 0; i < count; i++) {
> > - freq_match = !is_deep_sleep &&
> > - smu_cmn_freqs_match(
> > - cur_clk,
> > - dpm_table->dpm_levels[i].value);
>
> By this change, if this function is no longer used, it can be removed as well.
this function is still used in fine-grained case.
Best Regards,
Kevin
>
> Thanks,
> Lijo
>
> > size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
> > level_index + i,
> > dpm_table->dpm_levels[i].value,
> > - freq_match ? "*" : "");
> > + (!is_deep_sleep &&
> > + i == nearest_level) ? "*" : "");
> > }
> > } else {
> > count = 2;