On 12-Oct-26 12:45 PM, Wang, Kevin wrote:
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.


Thanks for the clarification. I think we should consider keeping this logic as a separate smu_cmn function to be used from other places also like - smu_v14_0_0_find_clk_level

Reviewed-by: Lijo Lazar <[email protected]>

Thanks,
Lijo

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;


Reply via email to