From: Alex Hung <[email protected]>

Add comprehensive KUnit test coverage for amdgpu_dm_pp_smu.c including:
- Utility functions: dc_to_pp_clock_type, pp_to_dc_clock_levels,
  build_pm_display_cfg, get_default_clock_levels,
  build_wm_clock_ranges_soc15, cap_clock_levels_to_validation
- DPM-backed functions: dm_pp_get_clock_levels_by_type,
  dm_pp_notify_wm_clock_changes, dm_pp_apply_clock_for_voltage_request,
  dm_pp_get_static_clocks
- Raven pass-throughs: pp_rv_set_wm_ranges, pp_rv_set_pme_wa_enable,
  pp_rv_set_active_display_count, pp_rv_set_min_deep_sleep_dcfclk,
  pp_rv_set_hard_min_dcefclk_by_freq, pp_rv_set_hard_min_fclk_by_freq
- Navi functions: pp_nv_set_wm_ranges, pp_nv_get_maximum_sustainable_clocks,
  pp_nv_get_uclk_dpm_states, pp_nv_get_dpm_clock_table
- Renoir: pp_rn_get_dpm_clock_table
- dm_pp_get_funcs ASIC family selection

Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c  |   52 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h  |   23 +
 .../amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c   | 1535 ++++++++++++++++-
 3 files changed, 1592 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index e0fe4cb97f31..0d2e5294d062 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -337,6 +337,7 @@ bool dm_pp_get_clock_levels_by_type(
 
        return true;
 }
+EXPORT_IF_KUNIT(dm_pp_get_clock_levels_by_type);
 
 bool dm_pp_get_clock_levels_by_type_with_latency(
        const struct dc_context *ctx,
@@ -357,6 +358,7 @@ bool dm_pp_get_clock_levels_by_type_with_latency(
 
        return true;
 }
+EXPORT_IF_KUNIT(dm_pp_get_clock_levels_by_type_with_latency);
 
 bool dm_pp_get_clock_levels_by_type_with_voltage(
        const struct dc_context *ctx,
@@ -377,6 +379,7 @@ bool dm_pp_get_clock_levels_by_type_with_voltage(
 
        return true;
 }
+EXPORT_IF_KUNIT(dm_pp_get_clock_levels_by_type_with_voltage);
 
 bool dm_pp_notify_wm_clock_changes(
        const struct dc_context *ctx,
@@ -396,6 +399,7 @@ bool dm_pp_notify_wm_clock_changes(
 
        return false;
 }
+EXPORT_IF_KUNIT(dm_pp_notify_wm_clock_changes);
 
 bool dm_pp_apply_clock_for_voltage_request(
        const struct dc_context *ctx,
@@ -464,7 +468,7 @@ STATIC_IFN_KUNIT void build_wm_clock_ranges_soc15(
 }
 EXPORT_IF_KUNIT(build_wm_clock_ranges_soc15);
 
-static void pp_rv_set_wm_ranges(struct pp_smu *pp,
+STATIC_IFN_KUNIT void pp_rv_set_wm_ranges(struct pp_smu *pp,
                struct pp_smu_wm_range_sets *ranges)
 {
        const struct dc_context *ctx = pp->dm;
@@ -476,48 +480,54 @@ static void pp_rv_set_wm_ranges(struct pp_smu *pp,
        amdgpu_dpm_set_watermarks_for_clocks_ranges(adev,
                                                    &wm_with_clock_ranges);
 }
+EXPORT_IF_KUNIT(pp_rv_set_wm_ranges);
 
-static void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
+STATIC_IFN_KUNIT void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
 
        amdgpu_dpm_notify_smu_enable_pwe(adev);
 }
+EXPORT_IF_KUNIT(pp_rv_set_pme_wa_enable);
 
-static void pp_rv_set_active_display_count(struct pp_smu *pp, int count)
+STATIC_IFN_KUNIT void pp_rv_set_active_display_count(struct pp_smu *pp, int 
count)
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
 
        amdgpu_dpm_set_active_display_count(adev, count);
 }
+EXPORT_IF_KUNIT(pp_rv_set_active_display_count);
 
-static void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock)
+STATIC_IFN_KUNIT void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int 
clock)
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
 
        amdgpu_dpm_set_min_deep_sleep_dcefclk(adev, clock);
 }
+EXPORT_IF_KUNIT(pp_rv_set_min_deep_sleep_dcfclk);
 
-static void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock)
+STATIC_IFN_KUNIT void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, 
int clock)
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
 
        amdgpu_dpm_set_hard_min_dcefclk_by_freq(adev, clock);
 }
+EXPORT_IF_KUNIT(pp_rv_set_hard_min_dcefclk_by_freq);
 
-static void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz)
+STATIC_IFN_KUNIT void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int 
mhz)
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
 
        amdgpu_dpm_set_hard_min_fclk_by_freq(adev, mhz);
 }
+EXPORT_IF_KUNIT(pp_rv_set_hard_min_fclk_by_freq);
 
-static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
                struct pp_smu_wm_range_sets *ranges)
 {
        const struct dc_context *ctx = pp->dm;
@@ -527,8 +537,9 @@ static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu 
*pp,
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_wm_ranges);
 
-static enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count)
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, 
int count)
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
@@ -543,8 +554,9 @@ static enum pp_smu_status pp_nv_set_display_count(struct 
pp_smu *pp, int count)
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_display_count);
 
-static enum pp_smu_status
+STATIC_IFN_KUNIT enum pp_smu_status
 pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz)
 {
        const struct dc_context *ctx = pp->dm;
@@ -560,8 +572,9 @@ pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz)
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_min_deep_sleep_dcfclk);
 
-static enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(
                struct pp_smu *pp, int mhz)
 {
        const struct dc_context *ctx = pp->dm;
@@ -583,8 +596,9 @@ static enum pp_smu_status 
pp_nv_set_hard_min_dcefclk_by_freq(
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_hard_min_dcefclk_by_freq);
 
-static enum pp_smu_status
+STATIC_IFN_KUNIT enum pp_smu_status
 pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
 {
        const struct dc_context *ctx = pp->dm;
@@ -606,8 +620,9 @@ pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_hard_min_uclk_by_freq);
 
-static enum pp_smu_status pp_nv_set_pstate_handshake_support(
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_set_pstate_handshake_support(
        struct pp_smu *pp, bool pstate_handshake_supported)
 {
        const struct dc_context *ctx = pp->dm;
@@ -619,6 +634,7 @@ static enum pp_smu_status 
pp_nv_set_pstate_handshake_support(
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_pstate_handshake_support);
 
 STATIC_IFN_KUNIT bool pp_smu_nv_clock_id_to_pp(enum pp_smu_nv_clock_id 
clock_id,
                enum amd_pp_clock_type *clock_type)
@@ -641,7 +657,7 @@ STATIC_IFN_KUNIT bool pp_smu_nv_clock_id_to_pp(enum 
pp_smu_nv_clock_id clock_id,
 }
 EXPORT_IF_KUNIT(pp_smu_nv_clock_id_to_pp);
 
-static enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu 
*pp,
                enum pp_smu_nv_clock_id clock_id, int mhz)
 {
        const struct dc_context *ctx = pp->dm;
@@ -665,8 +681,9 @@ static enum pp_smu_status pp_nv_set_voltage_by_freq(struct 
pp_smu *pp,
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_set_voltage_by_freq);
 
-static enum pp_smu_status pp_nv_get_maximum_sustainable_clocks(
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_get_maximum_sustainable_clocks(
                struct pp_smu *pp, struct pp_smu_nv_clock_table *max_clocks)
 {
        const struct dc_context *ctx = pp->dm;
@@ -682,8 +699,9 @@ static enum pp_smu_status 
pp_nv_get_maximum_sustainable_clocks(
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_get_maximum_sustainable_clocks);
 
-static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
+STATIC_IFN_KUNIT enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu 
*pp,
                unsigned int *clock_values_in_khz, unsigned int *num_states)
 {
        const struct dc_context *ctx = pp->dm;
@@ -700,8 +718,9 @@ static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct 
pp_smu *pp,
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_nv_get_uclk_dpm_states);
 
-static enum pp_smu_status pp_rn_get_dpm_clock_table(
+STATIC_IFN_KUNIT enum pp_smu_status pp_rn_get_dpm_clock_table(
                struct pp_smu *pp, struct dpm_clocks *clock_table)
 {
        const struct dc_context *ctx = pp->dm;
@@ -716,6 +735,7 @@ static enum pp_smu_status pp_rn_get_dpm_clock_table(
 
        return PP_SMU_RESULT_OK;
 }
+EXPORT_IF_KUNIT(pp_rn_get_dpm_clock_table);
 
 void dm_pp_get_funcs(
                struct dc_context *ctx,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
index e851e3ee5b63..f918eb71f0d1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
@@ -33,6 +33,29 @@ void cap_clock_levels_to_validation(struct 
dm_pp_clock_levels *dc_clks,
                                    const struct amd_pp_simple_clock_info 
*validation_clks);
 bool pp_smu_nv_clock_id_to_pp(enum pp_smu_nv_clock_id clock_id,
                              enum amd_pp_clock_type *clock_type);
+void pp_rv_set_wm_ranges(struct pp_smu *pp, struct pp_smu_wm_range_sets 
*ranges);
+void pp_rv_set_pme_wa_enable(struct pp_smu *pp);
+void pp_rv_set_active_display_count(struct pp_smu *pp, int count);
+void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock);
+void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock);
+void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz);
+enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
+                                       struct pp_smu_wm_range_sets *ranges);
+enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count);
+enum pp_smu_status pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz);
+enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int 
mhz);
+enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz);
+enum pp_smu_status pp_nv_set_pstate_handshake_support(struct pp_smu *pp,
+                                                     bool 
pstate_handshake_supported);
+enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
+                                            enum pp_smu_nv_clock_id clock_id, 
int mhz);
+enum pp_smu_status pp_nv_get_maximum_sustainable_clocks(struct pp_smu *pp,
+                                                       struct 
pp_smu_nv_clock_table *max_clocks);
+enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
+                                            unsigned int *clock_values_in_khz,
+                                            unsigned int *num_states);
+enum pp_smu_status pp_rn_get_dpm_clock_table(struct pp_smu *pp,
+                                            struct dpm_clocks *clock_table);
 #endif
 
 #endif /* __AMDGPU_DM_PP_SMU_H__ */
diff --git 
a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
index dbb6dfd5c284..e1d5088d8c0f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
@@ -7,6 +7,7 @@
 
 #include <kunit/test.h>
 #include <linux/types.h>
+#include <linux/mutex.h>
 
 #include "dc.h"
 #include "dm_services.h"
@@ -16,6 +17,201 @@
 #include "amdgpu_dm.h"
 #include "amdgpu_dm_pp_smu.h"
 
+/* ---- Stub DPM layer ---- */
+
+/**
+ * struct stub_dpm_context - Tracks stub DPM callback invocations
+ * @ret_val: Return value for the next DPM callback
+ * @get_current_clocks_info: Clock info returned by stub get_current_clocks
+ * @get_clock_by_type_clocks: Clocks returned by stub get_clock_by_type
+ * @get_validation_clks: Validation clocks returned by stub
+ * @get_clock_by_type_with_latency_clks: Returned by stub with_latency
+ * @get_clock_by_type_with_voltage_clks: Returned by stub with_voltage
+ * @set_watermarks_ret: Return value for set_watermarks
+ * @display_clock_voltage_ret: Return value for display_clock_voltage_request
+ * @display_disable_memory_clock_switch_ret: Return for disable_memory_clock
+ * @get_max_sustainable_ret: Return for get_max_sustainable_clocks_by_dc
+ * @get_uclk_dpm_ret: Return for get_uclk_dpm_states
+ * @get_dpm_clock_table_ret: Return for get_dpm_clock_table
+ * @set_active_display_count_ret: Return for set_active_display_count
+ * @set_min_deep_sleep_dcefclk_ret: Return for set_min_deep_sleep_dcefclk
+ * @get_validation_clks_ret: Return for get_display_mode_validation_clocks
+ */
+struct stub_dpm_context {
+       int ret_val;
+       struct amd_pp_clock_info get_current_clocks_info;
+       struct amd_pp_clocks get_clock_by_type_clocks;
+       struct amd_pp_simple_clock_info get_validation_clks;
+       int get_validation_clks_ret;
+       struct pp_clock_levels_with_latency get_clock_by_type_with_latency_clks;
+       struct pp_clock_levels_with_voltage get_clock_by_type_with_voltage_clks;
+       int set_watermarks_ret;
+       int display_clock_voltage_ret;
+       int display_disable_memory_clock_switch_ret;
+       int get_max_sustainable_ret;
+       int get_uclk_dpm_ret;
+       int get_dpm_clock_table_ret;
+       int set_active_display_count_ret;
+       int set_min_deep_sleep_dcefclk_ret;
+};
+
+static struct stub_dpm_context *stub_dpm_ctx;
+
+static int stub_get_current_clocks(void *handle, struct amd_pp_clock_info 
*clocks)
+{
+       if (stub_dpm_ctx->ret_val)
+               return stub_dpm_ctx->ret_val;
+       *clocks = stub_dpm_ctx->get_current_clocks_info;
+       return 0;
+}
+
+static int stub_get_clock_by_type(void *handle, enum amd_pp_clock_type type,
+                                 struct amd_pp_clocks *clocks)
+{
+       if (stub_dpm_ctx->ret_val)
+               return stub_dpm_ctx->ret_val;
+       *clocks = stub_dpm_ctx->get_clock_by_type_clocks;
+       return 0;
+}
+
+static int stub_get_display_mode_validation_clocks(void *handle,
+                                                  struct 
amd_pp_simple_clock_info *clocks)
+{
+       if (stub_dpm_ctx->get_validation_clks_ret)
+               return stub_dpm_ctx->get_validation_clks_ret;
+       *clocks = stub_dpm_ctx->get_validation_clks;
+       return 0;
+}
+
+static int stub_get_clock_by_type_with_latency(void *handle,
+                                              enum amd_pp_clock_type type,
+                                              struct 
pp_clock_levels_with_latency *clocks)
+{
+       if (stub_dpm_ctx->ret_val)
+               return stub_dpm_ctx->ret_val;
+       *clocks = stub_dpm_ctx->get_clock_by_type_with_latency_clks;
+       return 0;
+}
+
+static int stub_get_clock_by_type_with_voltage(void *handle,
+                                              enum amd_pp_clock_type type,
+                                              struct 
pp_clock_levels_with_voltage *clocks)
+{
+       if (stub_dpm_ctx->ret_val)
+               return stub_dpm_ctx->ret_val;
+       *clocks = stub_dpm_ctx->get_clock_by_type_with_voltage_clks;
+       return 0;
+}
+
+static void stub_display_configuration_change(void *handle)
+{
+       /* No-op: satisfies display_configuration_changed callback */
+}
+
+static void stub_pm_compute_clocks(void *handle)
+{
+       /* No-op: satisfies pm_compute_clocks callback */
+}
+
+static int stub_set_watermarks_for_clocks_ranges(void *handle, void 
*clock_ranges)
+{
+       return stub_dpm_ctx->set_watermarks_ret;
+}
+
+static int stub_display_clock_voltage_request(void *handle,
+                                             struct pp_display_clock_request 
*clock)
+{
+       return stub_dpm_ctx->display_clock_voltage_ret;
+}
+
+static int stub_set_active_display_count(void *handle, uint32_t count)
+{
+       return stub_dpm_ctx->set_active_display_count_ret;
+}
+
+static int stub_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock)
+{
+       return stub_dpm_ctx->set_min_deep_sleep_dcefclk_ret;
+}
+
+static int stub_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock)
+{
+       return 0;
+}
+
+static int stub_set_hard_min_fclk_by_freq(void *handle, uint32_t clock)
+{
+       return 0;
+}
+
+static int stub_notify_smu_enable_pwe(void *handle)
+{
+       return 0;
+}
+
+static int stub_display_disable_memory_clock_switch(void *handle,
+                                                   bool 
disable_memory_clock_switch)
+{
+       return stub_dpm_ctx->display_disable_memory_clock_switch_ret;
+}
+
+static int stub_get_max_sustainable_clocks_by_dc(void *handle,
+                                                struct pp_smu_nv_clock_table 
*max_clocks)
+{
+       return stub_dpm_ctx->get_max_sustainable_ret;
+}
+
+static int stub_get_uclk_dpm_states(void *handle,
+                                   unsigned int *clock_values_in_khz,
+                                   unsigned int *num_states)
+{
+       return stub_dpm_ctx->get_uclk_dpm_ret;
+}
+
+static int stub_get_dpm_clock_table(void *handle, struct dpm_clocks 
*clock_table)
+{
+       return stub_dpm_ctx->get_dpm_clock_table_ret;
+}
+
+static const struct amd_pm_funcs stub_pp_funcs = {
+       .get_current_clocks = stub_get_current_clocks,
+       .get_clock_by_type = stub_get_clock_by_type,
+       .get_display_mode_validation_clocks = 
stub_get_display_mode_validation_clocks,
+       .get_clock_by_type_with_latency = stub_get_clock_by_type_with_latency,
+       .get_clock_by_type_with_voltage = stub_get_clock_by_type_with_voltage,
+       .display_configuration_changed = stub_display_configuration_change,
+       .pm_compute_clocks = stub_pm_compute_clocks,
+       .set_watermarks_for_clocks_ranges = 
stub_set_watermarks_for_clocks_ranges,
+       .display_clock_voltage_request = stub_display_clock_voltage_request,
+       .set_active_display_count = stub_set_active_display_count,
+       .set_min_deep_sleep_dcefclk = stub_set_min_deep_sleep_dcefclk,
+       .set_hard_min_dcefclk_by_freq = stub_set_hard_min_dcefclk_by_freq,
+       .set_hard_min_fclk_by_freq = stub_set_hard_min_fclk_by_freq,
+       .notify_smu_enable_pwe = stub_notify_smu_enable_pwe,
+       .display_disable_memory_clock_switch = 
stub_display_disable_memory_clock_switch,
+       .get_max_sustainable_clocks_by_dc = 
stub_get_max_sustainable_clocks_by_dc,
+       .get_uclk_dpm_states = stub_get_uclk_dpm_states,
+       .get_dpm_clock_table = stub_get_dpm_clock_table,
+};
+
+/**
+ * setup_stub_dpm - Initialize a stub DPM environment for testing
+ * @test: KUnit test context
+ * @adev: Pointer to amdgpu_device to configure
+ *
+ * Sets up adev->powerplay.pp_funcs and initializes adev->pm.mutex so that
+ * amdgpu_dpm_* functions can be safely called with stub callbacks.
+ */
+static void setup_stub_dpm(struct kunit *test, struct amdgpu_device *adev)
+{
+       stub_dpm_ctx = kunit_kzalloc(test, sizeof(*stub_dpm_ctx), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, stub_dpm_ctx);
+
+       adev->powerplay.pp_funcs = &stub_pp_funcs;
+       adev->powerplay.pp_handle = adev;
+       mutex_init(&adev->pm.mutex);
+}
+
 /* ---- Tests for get_default_clock_levels ---- */
 
 /**
@@ -706,23 +902,35 @@ static void dm_test_build_wm_clock_ranges_mcif(struct 
kunit *test)
        KUNIT_ASSERT_NOT_NULL(test, ranges);
        KUNIT_ASSERT_NOT_NULL(test, wm);
 
-       ranges->num_writer_wm_sets = 1;
+       ranges->num_writer_wm_sets = 2;
        ranges->writer_wm_sets[0].wm_inst = 1;
        ranges->writer_wm_sets[0].max_fill_clk_mhz = 1200;
        ranges->writer_wm_sets[0].min_fill_clk_mhz = 600;
        ranges->writer_wm_sets[0].max_drain_clk_mhz = 1000;
        ranges->writer_wm_sets[0].min_drain_clk_mhz = 500;
+       /* set 1: wm_inst > 3 -> clamped to WM_SET_A */
+       ranges->writer_wm_sets[1].wm_inst = 5;
+       ranges->writer_wm_sets[1].max_fill_clk_mhz = 1400;
+       ranges->writer_wm_sets[1].min_fill_clk_mhz = 700;
+       ranges->writer_wm_sets[1].max_drain_clk_mhz = 1100;
+       ranges->writer_wm_sets[1].min_drain_clk_mhz = 550;
 
        build_wm_clock_ranges_soc15(ranges, wm);
 
        KUNIT_EXPECT_EQ(test, wm->num_wm_dmif_sets, 0U);
-       KUNIT_EXPECT_EQ(test, wm->num_wm_mcif_sets, 1U);
+       KUNIT_EXPECT_EQ(test, wm->num_wm_mcif_sets, 2U);
 
        KUNIT_EXPECT_EQ(test, wm->wm_mcif_clocks_ranges[0].wm_set_id, WM_SET_B);
        KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz, 1200000U);
        KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz, 600000U);
        KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz, 1000000U);
        KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[0].wm_min_mem_clk_in_khz, 500000U);
+
+       KUNIT_EXPECT_EQ(test, wm->wm_mcif_clocks_ranges[1].wm_set_id, WM_SET_A);
+       KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz, 1400000U);
+       KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz, 700000U);
+       KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz, 1100000U);
+       KUNIT_EXPECT_EQ(test, 
wm->wm_mcif_clocks_ranges[1].wm_min_mem_clk_in_khz, 550000U);
 }
 
 /* ---- Tests for cap_clock_levels_to_validation ---- */
@@ -911,6 +1119,1259 @@ static void dm_test_nv_clock_id_invalid(struct kunit 
*test)
        KUNIT_EXPECT_EQ(test, clock_type, amd_pp_dcef_clock);
 }
 
+/* ---- Tests using stub DPM layer ---- */
+
+/**
+ * dm_test_get_static_clocks_success - Test successful static clock retrieval
+ * @test: KUnit test context
+ *
+ * Verify that dm_pp_get_static_clocks returns true and correctly scales
+ * the max engine and memory clocks from 10kHz to kHz units.
+ */
+static void dm_test_get_static_clocks_success(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_static_clock_info info = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+
+       stub_dpm_ctx->get_current_clocks_info.max_memory_clock = 80000;
+       stub_dpm_ctx->get_current_clocks_info.max_engine_clock = 72000;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_get_static_clocks(ctx, &info));
+       KUNIT_EXPECT_EQ(test, info.max_mclk_khz, 800000U);
+       KUNIT_EXPECT_EQ(test, info.max_sclk_khz, 720000U);
+       KUNIT_EXPECT_EQ(test, (int)info.max_clocks_state, 
(int)DM_PP_CLOCKS_STATE_NOMINAL);
+}
+
+/**
+ * dm_test_get_static_clocks_failure - Test DPM error returns false
+ * @test: KUnit test context
+ *
+ * Verify that dm_pp_get_static_clocks returns false when the DPM callback
+ * returns an error.
+ */
+static void dm_test_get_static_clocks_failure(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_static_clock_info info = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->ret_val = -EINVAL;
+
+       KUNIT_EXPECT_FALSE(test, dm_pp_get_static_clocks(ctx, &info));
+}
+
+/**
+ * dm_test_apply_display_requirements_dpm_enabled - Test DPM-enabled path
+ * @test: KUnit test context
+ *
+ * Verify that dm_pp_apply_display_requirements calls build_pm_display_cfg
+ * and the DPM callbacks when DPM is enabled, and returns true.
+ */
+static void dm_test_apply_display_requirements_dpm_enabled(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_display_configuration cfg = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       adev->pm.dpm_enabled = true;
+
+       cfg.display_count = 1;
+       cfg.min_engine_clock_khz = 300000;
+       cfg.disp_configs[0].v_refresh = 60;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_apply_display_requirements(ctx, &cfg));
+       KUNIT_EXPECT_EQ(test, adev->pm.pm_display_cfg.min_core_set_clock, 
30000);
+       KUNIT_EXPECT_EQ(test, adev->pm.pm_display_cfg.vrefresh, 60);
+}
+
+/**
+ * dm_test_get_clock_levels_by_type_dpm_error - Test DPM error fallback
+ * @test: KUnit test context
+ *
+ * Verify that dm_pp_get_clock_levels_by_type falls back to default clock
+ * levels when amdgpu_dpm_get_clock_by_type returns an error.
+ */
+static void dm_test_get_clock_levels_by_type_dpm_error(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels dc_clks = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->ret_val = -EINVAL;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_get_clock_levels_by_type(ctx,
+                               DM_PP_CLOCK_TYPE_DISPLAY_CLK, &dc_clks));
+       KUNIT_EXPECT_EQ(test, dc_clks.num_levels, 6U);
+       KUNIT_EXPECT_EQ(test, dc_clks.clocks_in_khz[0], 300000U);
+}
+
+/**
+ * dm_test_get_clock_levels_by_type_success - Test successful clock query
+ * @test: KUnit test context
+ *
+ * Verify that dm_pp_get_clock_levels_by_type returns the queried clocks
+ * capped by validation clocks.
+ */
+static void dm_test_get_clock_levels_by_type_success(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels dc_clks = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+
+       stub_dpm_ctx->get_clock_by_type_clocks.count = 3;
+       stub_dpm_ctx->get_clock_by_type_clocks.clock[0] = 300000;
+       stub_dpm_ctx->get_clock_by_type_clocks.clock[1] = 500000;
+       stub_dpm_ctx->get_clock_by_type_clocks.clock[2] = 700000;
+
+       /* validation at 60000 * 10 = 600000 kHz → caps to 2 levels */
+       stub_dpm_ctx->get_validation_clks.engine_max_clock = 60000;
+       stub_dpm_ctx->get_validation_clks.memory_max_clock = 80000;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_get_clock_levels_by_type(ctx,
+                               DM_PP_CLOCK_TYPE_ENGINE_CLK, &dc_clks));
+       KUNIT_EXPECT_EQ(test, dc_clks.num_levels, 2U);
+       KUNIT_EXPECT_EQ(test, dc_clks.clocks_in_khz[0], 300000U);
+       KUNIT_EXPECT_EQ(test, dc_clks.clocks_in_khz[1], 500000U);
+}
+
+/**
+ * dm_test_get_clock_levels_by_type_validation_fallback - Test validation error
+ * @test: KUnit test context
+ *
+ * Verify that dm_pp_get_clock_levels_by_type uses default validation clocks
+ * (engine=720000, memory=800000 kHz) when get_display_mode_validation_clocks
+ * returns an error, capping levels accordingly.
+ */
+static void dm_test_get_clock_levels_by_type_validation_fallback(struct kunit 
*test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels dc_clks = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+
+       /* get_clock_by_type succeeds with 3 engine clock levels */
+       stub_dpm_ctx->get_clock_by_type_clocks.count = 3;
+       stub_dpm_ctx->get_clock_by_type_clocks.clock[0] = 300000;
+       stub_dpm_ctx->get_clock_by_type_clocks.clock[1] = 500000;
+       stub_dpm_ctx->get_clock_by_type_clocks.clock[2] = 800000;
+
+       /* Force validation clocks to fail → triggers default path */
+       stub_dpm_ctx->get_validation_clks_ret = -EINVAL;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_get_clock_levels_by_type(ctx,
+                               DM_PP_CLOCK_TYPE_ENGINE_CLK, &dc_clks));
+       /*
+        * Default validation: engine_max_clock = 72000 * 10 = 720000 kHz.
+        * Clocks 300000 and 500000 are within limit, 800000 exceeds it,
+        * so num_levels is capped to 2.
+        */
+       KUNIT_EXPECT_EQ(test, dc_clks.num_levels, 2U);
+       KUNIT_EXPECT_EQ(test, dc_clks.clocks_in_khz[0], 300000U);
+       KUNIT_EXPECT_EQ(test, dc_clks.clocks_in_khz[1], 500000U);
+}
+
+/**
+ * dm_test_get_clock_levels_with_latency_success - Test latency clock query
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_get_clock_levels_by_type_with_latency returns true and
+ * copies the clock/latency data from the DPM backend.
+ */
+static void dm_test_get_clock_levels_with_latency_success(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels_with_latency info = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+
+       stub_dpm_ctx->get_clock_by_type_with_latency_clks.num_levels = 1;
+       stub_dpm_ctx->get_clock_by_type_with_latency_clks.data[0].clocks_in_khz 
= 600000;
+       stub_dpm_ctx->get_clock_by_type_with_latency_clks.data[0].latency_in_us 
= 15;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_get_clock_levels_by_type_with_latency(ctx,
+                               DM_PP_CLOCK_TYPE_ENGINE_CLK, &info));
+       KUNIT_EXPECT_EQ(test, info.num_levels, 1U);
+       KUNIT_EXPECT_EQ(test, info.data[0].clocks_in_khz, 600000U);
+       KUNIT_EXPECT_EQ(test, info.data[0].latency_in_us, 15U);
+}
+
+/**
+ * dm_test_get_clock_levels_with_latency_failure - Test latency query error
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_get_clock_levels_by_type_with_latency returns false on DPM 
error.
+ */
+static void dm_test_get_clock_levels_with_latency_failure(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels_with_latency info = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->ret_val = -EINVAL;
+
+       KUNIT_EXPECT_FALSE(test, 
dm_pp_get_clock_levels_by_type_with_latency(ctx,
+                               DM_PP_CLOCK_TYPE_ENGINE_CLK, &info));
+}
+
+/**
+ * dm_test_get_clock_levels_with_voltage_success - Test voltage clock query
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_get_clock_levels_by_type_with_voltage returns true and
+ * copies the clock/voltage data from the DPM backend.
+ */
+static void dm_test_get_clock_levels_with_voltage_success(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels_with_voltage info = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+
+       stub_dpm_ctx->get_clock_by_type_with_voltage_clks.num_levels = 1;
+       stub_dpm_ctx->get_clock_by_type_with_voltage_clks.data[0].clocks_in_khz 
= 400000;
+       stub_dpm_ctx->get_clock_by_type_with_voltage_clks.data[0].voltage_in_mv 
= 900;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_get_clock_levels_by_type_with_voltage(ctx,
+                               DM_PP_CLOCK_TYPE_MEMORY_CLK, &info));
+       KUNIT_EXPECT_EQ(test, info.num_levels, 1U);
+       KUNIT_EXPECT_EQ(test, info.data[0].clocks_in_khz, 400000U);
+       KUNIT_EXPECT_EQ(test, info.data[0].voltage_in_mv, 900U);
+}
+
+/**
+ * dm_test_get_clock_levels_with_voltage_failure - Test voltage query error
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_get_clock_levels_by_type_with_voltage returns false on DPM 
error.
+ */
+static void dm_test_get_clock_levels_with_voltage_failure(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_levels_with_voltage info = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->ret_val = -EINVAL;
+
+       KUNIT_EXPECT_FALSE(test, 
dm_pp_get_clock_levels_by_type_with_voltage(ctx,
+                               DM_PP_CLOCK_TYPE_MEMORY_CLK, &info));
+}
+
+/**
+ * dm_test_notify_wm_clock_changes_polaris - Test Polaris watermark path
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_notify_wm_clock_changes returns true for Polaris ASICs
+ * when the DPM set_watermarks call succeeds.
+ */
+static void dm_test_notify_wm_clock_changes_polaris(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_wm_sets_with_clock_ranges wm = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       adev->asic_type = CHIP_POLARIS10;
+       stub_dpm_ctx->set_watermarks_ret = 0;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_notify_wm_clock_changes(ctx, &wm));
+}
+
+/**
+ * dm_test_notify_wm_clock_changes_non_polaris - Test non-Polaris path
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_notify_wm_clock_changes returns false for non-Polaris ASICs.
+ */
+static void dm_test_notify_wm_clock_changes_non_polaris(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_wm_sets_with_clock_ranges wm = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       adev->asic_type = CHIP_NAVI10;
+
+       KUNIT_EXPECT_FALSE(test, dm_pp_notify_wm_clock_changes(ctx, &wm));
+}
+
+/**
+ * dm_test_apply_clock_for_voltage_success - Test successful voltage request
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_apply_clock_for_voltage_request returns true when the DPM
+ * callback succeeds for a valid clock type.
+ */
+static void dm_test_apply_clock_for_voltage_success(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_for_voltage_req req = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->display_clock_voltage_ret = 0;
+
+       req.clk_type = DM_PP_CLOCK_TYPE_ENGINE_CLK;
+       req.clocks_in_khz = 500000;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_apply_clock_for_voltage_request(ctx, 
&req));
+}
+
+/**
+ * dm_test_apply_clock_for_voltage_eopnotsupp - Test EOPNOTSUPP treated as 
success
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_apply_clock_for_voltage_request returns true when the DPM
+ * callback returns -EOPNOTSUPP (not supported is non-fatal).
+ */
+static void dm_test_apply_clock_for_voltage_eopnotsupp(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_for_voltage_req req = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->display_clock_voltage_ret = -EOPNOTSUPP;
+
+       req.clk_type = DM_PP_CLOCK_TYPE_ENGINE_CLK;
+       req.clocks_in_khz = 500000;
+
+       KUNIT_EXPECT_TRUE(test, dm_pp_apply_clock_for_voltage_request(ctx, 
&req));
+}
+
+/**
+ * dm_test_apply_clock_for_voltage_fail - Test DPM error returns false
+ * @test: KUnit test context
+ *
+ * Verify dm_pp_apply_clock_for_voltage_request returns false when the DPM
+ * callback fails with an error other than -EOPNOTSUPP.
+ */
+static void dm_test_apply_clock_for_voltage_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct dm_pp_clock_for_voltage_req req = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       stub_dpm_ctx->display_clock_voltage_ret = -EIO;
+
+       req.clk_type = DM_PP_CLOCK_TYPE_ENGINE_CLK;
+       req.clocks_in_khz = 500000;
+
+       KUNIT_EXPECT_FALSE(test, dm_pp_apply_clock_for_voltage_request(ctx, 
&req));
+}
+
+/* ---- Tests for pp_nv_set_display_count ---- */
+
+/**
+ * dm_test_nv_set_display_count_ok - Test successful display count set
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_display_count returns PP_SMU_RESULT_OK on success.
+ */
+static void dm_test_nv_set_display_count_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->set_active_display_count_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_display_count(&pp_smu, 2),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_set_display_count_unsupported - Test EOPNOTSUPP mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_display_count returns PP_SMU_RESULT_UNSUPPORTED when
+ * the DPM callback returns -EOPNOTSUPP.
+ */
+static void dm_test_nv_set_display_count_unsupported(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->set_active_display_count_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_display_count(&pp_smu, 2),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_nv_set_display_count_fail - Test generic error mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_display_count returns PP_SMU_RESULT_FAIL on a generic
+ * DPM error.
+ */
+static void dm_test_nv_set_display_count_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->set_active_display_count_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_display_count(&pp_smu, 2),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_nv_set_voltage_by_freq ---- */
+
+/**
+ * dm_test_nv_set_voltage_by_freq_ok - Test successful voltage-by-freq
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_voltage_by_freq returns PP_SMU_RESULT_OK on success.
+ */
+static void dm_test_nv_set_voltage_by_freq_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_voltage_by_freq(&pp_smu, 
PP_SMU_NV_DISPCLK, 600),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_set_voltage_by_freq_invalid_id - Test invalid clock id
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_voltage_by_freq returns PP_SMU_RESULT_FAIL for an
+ * unrecognized clock id without calling DPM.
+ */
+static void dm_test_nv_set_voltage_by_freq_invalid_id(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_set_voltage_by_freq(&pp_smu, (enum 
pp_smu_nv_clock_id)0xff, 600),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_nv_set_pstate_handshake_support ---- */
+
+/**
+ * dm_test_nv_pstate_handshake_ok - Test successful pstate handshake
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_pstate_handshake_support returns PP_SMU_RESULT_OK
+ * when the DPM callback succeeds.
+ */
+static void dm_test_nv_pstate_handshake_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_disable_memory_clock_switch_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_pstate_handshake_support(&pp_smu, 
true),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_pstate_handshake_fail - Test failed pstate handshake
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_pstate_handshake_support returns PP_SMU_RESULT_FAIL
+ * when the DPM callback returns non-zero.
+ */
+static void dm_test_nv_pstate_handshake_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_disable_memory_clock_switch_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_pstate_handshake_support(&pp_smu, 
true),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_rn_get_dpm_clock_table ---- */
+
+/**
+ * dm_test_rn_get_dpm_clock_table_ok - Test successful DPM clock table
+ * @test: KUnit test context
+ *
+ * Verify pp_rn_get_dpm_clock_table returns PP_SMU_RESULT_OK on success.
+ */
+static void dm_test_rn_get_dpm_clock_table_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct dpm_clocks clock_table = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_dpm_clock_table_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_rn_get_dpm_clock_table(&pp_smu, 
&clock_table),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_rn_get_dpm_clock_table_unsupported - Test EOPNOTSUPP mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_rn_get_dpm_clock_table returns PP_SMU_RESULT_UNSUPPORTED.
+ */
+static void dm_test_rn_get_dpm_clock_table_unsupported(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct dpm_clocks clock_table = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_dpm_clock_table_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_rn_get_dpm_clock_table(&pp_smu, 
&clock_table),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_rn_get_dpm_clock_table_fail - Test generic error mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_rn_get_dpm_clock_table returns PP_SMU_RESULT_FAIL.
+ */
+static void dm_test_rn_get_dpm_clock_table_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct dpm_clocks clock_table = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_dpm_clock_table_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_rn_get_dpm_clock_table(&pp_smu, 
&clock_table),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_rv_set_wm_ranges ---- */
+
+/**
+ * dm_test_rv_set_wm_ranges - Test Raven watermark range forwarding
+ * @test: KUnit test context
+ *
+ * Verify pp_rv_set_wm_ranges converts watermark ranges via
+ * build_wm_clock_ranges_soc15 and forwards them to DPM without crashing.
+ */
+static void dm_test_rv_set_wm_ranges(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct pp_smu_wm_range_sets ranges = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       ranges.num_reader_wm_sets = 1;
+       ranges.reader_wm_sets[0].wm_inst = 0;
+       ranges.reader_wm_sets[0].max_drain_clk_mhz = 600;
+       ranges.reader_wm_sets[0].min_drain_clk_mhz = 300;
+
+       pp_rv_set_wm_ranges(&pp_smu, &ranges);
+
+       /* Reaching here without crash confirms coverage */
+       KUNIT_SUCCEED(test);
+}
+
+/* ---- Tests for pp_rv_set_pme_wa_enable ---- */
+
+/**
+ * dm_test_rv_set_pme_wa_enable - Test Raven PME workaround enable
+ * @test: KUnit test context
+ *
+ * Verify pp_rv_set_pme_wa_enable forwards the call to DPM without crashing.
+ */
+static void dm_test_rv_set_pme_wa_enable(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       pp_rv_set_pme_wa_enable(&pp_smu);
+
+       KUNIT_SUCCEED(test);
+}
+
+/* ---- Tests for pp_rv_set_active_display_count ---- */
+
+/**
+ * dm_test_rv_set_active_display_count - Test Raven display count forwarding
+ * @test: KUnit test context
+ *
+ * Verify pp_rv_set_active_display_count forwards the count to DPM without
+ * crashing.
+ */
+static void dm_test_rv_set_active_display_count(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       pp_rv_set_active_display_count(&pp_smu, 2);
+
+       KUNIT_SUCCEED(test);
+}
+
+/* ---- Tests for pp_rv_set_min_deep_sleep_dcfclk ---- */
+
+/**
+ * dm_test_rv_set_min_deep_sleep_dcfclk - Test Raven deep sleep clock
+ * @test: KUnit test context
+ *
+ * Verify pp_rv_set_min_deep_sleep_dcfclk forwards the clock value to DPM
+ * without crashing.
+ */
+static void dm_test_rv_set_min_deep_sleep_dcfclk(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       pp_rv_set_min_deep_sleep_dcfclk(&pp_smu, 300);
+
+       KUNIT_SUCCEED(test);
+}
+
+/* ---- Tests for pp_rv_set_hard_min_dcefclk_by_freq ---- */
+
+/**
+ * dm_test_rv_set_hard_min_dcefclk_by_freq - Test Raven hard min DCEFCLK
+ * @test: KUnit test context
+ *
+ * Verify pp_rv_set_hard_min_dcefclk_by_freq forwards the frequency to DPM
+ * without crashing.
+ */
+static void dm_test_rv_set_hard_min_dcefclk_by_freq(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       pp_rv_set_hard_min_dcefclk_by_freq(&pp_smu, 600);
+
+       KUNIT_SUCCEED(test);
+}
+
+/* ---- Tests for pp_rv_set_hard_min_fclk_by_freq ---- */
+
+/**
+ * dm_test_rv_set_hard_min_fclk_by_freq - Test Raven hard min FCLK
+ * @test: KUnit test context
+ *
+ * Verify pp_rv_set_hard_min_fclk_by_freq forwards the frequency to DPM
+ * without crashing.
+ */
+static void dm_test_rv_set_hard_min_fclk_by_freq(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       pp_rv_set_hard_min_fclk_by_freq(&pp_smu, 800);
+
+       KUNIT_SUCCEED(test);
+}
+
+/* ---- Tests for pp_nv_set_wm_ranges ---- */
+
+/**
+ * dm_test_nv_set_wm_ranges - Test Navi watermark range forwarding
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_wm_ranges forwards ranges to DPM and unconditionally
+ * returns PP_SMU_RESULT_OK.
+ */
+static void dm_test_nv_set_wm_ranges(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct pp_smu_wm_range_sets ranges = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+
+       ranges.num_reader_wm_sets = 1;
+       ranges.reader_wm_sets[0].wm_inst = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_wm_ranges(&pp_smu, &ranges),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/* ---- Tests for pp_nv_set_min_deep_sleep_dcfclk ---- */
+
+/**
+ * dm_test_nv_set_min_deep_sleep_dcfclk_ok - Test successful deep sleep set
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_min_deep_sleep_dcfclk returns PP_SMU_RESULT_OK on success.
+ */
+static void dm_test_nv_set_min_deep_sleep_dcfclk_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->set_min_deep_sleep_dcefclk_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_min_deep_sleep_dcfclk(&pp_smu, 
300),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_set_min_deep_sleep_dcfclk_unsupported - Test EOPNOTSUPP mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_min_deep_sleep_dcfclk returns PP_SMU_RESULT_UNSUPPORTED.
+ */
+static void dm_test_nv_set_min_deep_sleep_dcfclk_unsupported(struct kunit 
*test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->set_min_deep_sleep_dcefclk_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_min_deep_sleep_dcfclk(&pp_smu, 
300),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_nv_set_min_deep_sleep_dcfclk_fail - Test generic error mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_min_deep_sleep_dcfclk returns PP_SMU_RESULT_FAIL.
+ */
+static void dm_test_nv_set_min_deep_sleep_dcfclk_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->set_min_deep_sleep_dcefclk_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_min_deep_sleep_dcfclk(&pp_smu, 
300),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_nv_set_hard_min_dcefclk_by_freq ---- */
+
+/**
+ * dm_test_nv_set_hard_min_dcefclk_ok - Test successful hard min DCEFCLK
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_hard_min_dcefclk_by_freq returns PP_SMU_RESULT_OK.
+ */
+static void dm_test_nv_set_hard_min_dcefclk_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_hard_min_dcefclk_by_freq(&pp_smu, 
600),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_set_hard_min_dcefclk_unsupported - Test EOPNOTSUPP mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_hard_min_dcefclk_by_freq returns PP_SMU_RESULT_UNSUPPORTED.
+ */
+static void dm_test_nv_set_hard_min_dcefclk_unsupported(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_hard_min_dcefclk_by_freq(&pp_smu, 
600),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_nv_set_hard_min_dcefclk_fail - Test generic error mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_hard_min_dcefclk_by_freq returns PP_SMU_RESULT_FAIL.
+ */
+static void dm_test_nv_set_hard_min_dcefclk_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_hard_min_dcefclk_by_freq(&pp_smu, 
600),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_nv_set_hard_min_uclk_by_freq ---- */
+
+/**
+ * dm_test_nv_set_hard_min_uclk_ok - Test successful hard min UCLK
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_hard_min_uclk_by_freq returns PP_SMU_RESULT_OK.
+ */
+static void dm_test_nv_set_hard_min_uclk_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = 0;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_hard_min_uclk_by_freq(&pp_smu, 
800),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_set_hard_min_uclk_unsupported - Test EOPNOTSUPP mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_hard_min_uclk_by_freq returns PP_SMU_RESULT_UNSUPPORTED.
+ */
+static void dm_test_nv_set_hard_min_uclk_unsupported(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_hard_min_uclk_by_freq(&pp_smu, 
800),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_nv_set_hard_min_uclk_fail - Test generic error mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_set_hard_min_uclk_by_freq returns PP_SMU_RESULT_FAIL.
+ */
+static void dm_test_nv_set_hard_min_uclk_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->display_clock_voltage_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test, (int)pp_nv_set_hard_min_uclk_by_freq(&pp_smu, 
800),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_nv_get_maximum_sustainable_clocks ---- */
+
+/**
+ * dm_test_nv_get_max_sustainable_clocks_ok - Test successful query
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_get_maximum_sustainable_clocks returns PP_SMU_RESULT_OK.
+ */
+static void dm_test_nv_get_max_sustainable_clocks_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct pp_smu_nv_clock_table max_clocks = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_max_sustainable_ret = 0;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_get_maximum_sustainable_clocks(&pp_smu, 
&max_clocks),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_get_max_sustainable_clocks_unsupported - Test EOPNOTSUPP
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_get_maximum_sustainable_clocks returns 
PP_SMU_RESULT_UNSUPPORTED.
+ */
+static void dm_test_nv_get_max_sustainable_clocks_unsupported(struct kunit 
*test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct pp_smu_nv_clock_table max_clocks = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_max_sustainable_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_get_maximum_sustainable_clocks(&pp_smu, 
&max_clocks),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_nv_get_max_sustainable_clocks_fail - Test generic error
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_get_maximum_sustainable_clocks returns PP_SMU_RESULT_FAIL.
+ */
+static void dm_test_nv_get_max_sustainable_clocks_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       struct pp_smu_nv_clock_table max_clocks = {};
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_max_sustainable_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_get_maximum_sustainable_clocks(&pp_smu, 
&max_clocks),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
+/* ---- Tests for pp_nv_get_uclk_dpm_states ---- */
+
+/**
+ * dm_test_nv_get_uclk_dpm_states_ok - Test successful DPM states query
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_get_uclk_dpm_states returns PP_SMU_RESULT_OK.
+ */
+static void dm_test_nv_get_uclk_dpm_states_ok(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       unsigned int clock_values[4] = {};
+       unsigned int num_states = 0;
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_uclk_dpm_ret = 0;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_get_uclk_dpm_states(&pp_smu, clock_values, 
&num_states),
+                       (int)PP_SMU_RESULT_OK);
+}
+
+/**
+ * dm_test_nv_get_uclk_dpm_states_unsupported - Test EOPNOTSUPP mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_get_uclk_dpm_states returns PP_SMU_RESULT_UNSUPPORTED.
+ */
+static void dm_test_nv_get_uclk_dpm_states_unsupported(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       unsigned int clock_values[4] = {};
+       unsigned int num_states = 0;
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_uclk_dpm_ret = -EOPNOTSUPP;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_get_uclk_dpm_states(&pp_smu, clock_values, 
&num_states),
+                       (int)PP_SMU_RESULT_UNSUPPORTED);
+}
+
+/**
+ * dm_test_nv_get_uclk_dpm_states_fail - Test generic error mapping
+ * @test: KUnit test context
+ *
+ * Verify pp_nv_get_uclk_dpm_states returns PP_SMU_RESULT_FAIL.
+ */
+static void dm_test_nv_get_uclk_dpm_states_fail(struct kunit *test)
+{
+       struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), 
GFP_KERNEL);
+       struct dc_context *ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       struct pp_smu pp_smu = {};
+       unsigned int clock_values[4] = {};
+       unsigned int num_states = 0;
+
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       setup_stub_dpm(test, adev);
+       ctx->driver_context = adev;
+       pp_smu.dm = ctx;
+       stub_dpm_ctx->get_uclk_dpm_ret = -EIO;
+
+       KUNIT_EXPECT_EQ(test,
+                       (int)pp_nv_get_uclk_dpm_states(&pp_smu, clock_values, 
&num_states),
+                       (int)PP_SMU_RESULT_FAIL);
+}
+
 static struct kunit_case dm_pp_smu_test_cases[] = {
        /* get_default_clock_levels */
        KUNIT_CASE(dm_test_default_clock_levels_display),
@@ -963,6 +2424,76 @@ static struct kunit_case dm_pp_smu_test_cases[] = {
        KUNIT_CASE(dm_test_nv_clock_id_phyclk),
        KUNIT_CASE(dm_test_nv_clock_id_pixelclk),
        KUNIT_CASE(dm_test_nv_clock_id_invalid),
+       /* dm_pp_get_static_clocks (with stub DPM) */
+       KUNIT_CASE(dm_test_get_static_clocks_success),
+       KUNIT_CASE(dm_test_get_static_clocks_failure),
+       /* dm_pp_apply_display_requirements (DPM enabled) */
+       KUNIT_CASE(dm_test_apply_display_requirements_dpm_enabled),
+       /* dm_pp_get_clock_levels_by_type */
+       KUNIT_CASE(dm_test_get_clock_levels_by_type_dpm_error),
+       KUNIT_CASE(dm_test_get_clock_levels_by_type_success),
+       KUNIT_CASE(dm_test_get_clock_levels_by_type_validation_fallback),
+       /* dm_pp_get_clock_levels_by_type_with_latency */
+       KUNIT_CASE(dm_test_get_clock_levels_with_latency_success),
+       KUNIT_CASE(dm_test_get_clock_levels_with_latency_failure),
+       /* dm_pp_get_clock_levels_by_type_with_voltage */
+       KUNIT_CASE(dm_test_get_clock_levels_with_voltage_success),
+       KUNIT_CASE(dm_test_get_clock_levels_with_voltage_failure),
+       /* dm_pp_notify_wm_clock_changes */
+       KUNIT_CASE(dm_test_notify_wm_clock_changes_polaris),
+       KUNIT_CASE(dm_test_notify_wm_clock_changes_non_polaris),
+       /* dm_pp_apply_clock_for_voltage_request (with DPM) */
+       KUNIT_CASE(dm_test_apply_clock_for_voltage_success),
+       KUNIT_CASE(dm_test_apply_clock_for_voltage_eopnotsupp),
+       KUNIT_CASE(dm_test_apply_clock_for_voltage_fail),
+       /* pp_nv_set_display_count */
+       KUNIT_CASE(dm_test_nv_set_display_count_ok),
+       KUNIT_CASE(dm_test_nv_set_display_count_unsupported),
+       KUNIT_CASE(dm_test_nv_set_display_count_fail),
+       /* pp_nv_set_voltage_by_freq */
+       KUNIT_CASE(dm_test_nv_set_voltage_by_freq_ok),
+       KUNIT_CASE(dm_test_nv_set_voltage_by_freq_invalid_id),
+       /* pp_nv_set_pstate_handshake_support */
+       KUNIT_CASE(dm_test_nv_pstate_handshake_ok),
+       KUNIT_CASE(dm_test_nv_pstate_handshake_fail),
+       /* pp_rn_get_dpm_clock_table */
+       KUNIT_CASE(dm_test_rn_get_dpm_clock_table_ok),
+       KUNIT_CASE(dm_test_rn_get_dpm_clock_table_unsupported),
+       KUNIT_CASE(dm_test_rn_get_dpm_clock_table_fail),
+       /* pp_rv_set_wm_ranges */
+       KUNIT_CASE(dm_test_rv_set_wm_ranges),
+       /* pp_rv_set_pme_wa_enable */
+       KUNIT_CASE(dm_test_rv_set_pme_wa_enable),
+       /* pp_rv_set_active_display_count */
+       KUNIT_CASE(dm_test_rv_set_active_display_count),
+       /* pp_rv_set_min_deep_sleep_dcfclk */
+       KUNIT_CASE(dm_test_rv_set_min_deep_sleep_dcfclk),
+       /* pp_rv_set_hard_min_dcefclk_by_freq */
+       KUNIT_CASE(dm_test_rv_set_hard_min_dcefclk_by_freq),
+       /* pp_rv_set_hard_min_fclk_by_freq */
+       KUNIT_CASE(dm_test_rv_set_hard_min_fclk_by_freq),
+       /* pp_nv_set_wm_ranges */
+       KUNIT_CASE(dm_test_nv_set_wm_ranges),
+       /* pp_nv_set_min_deep_sleep_dcfclk */
+       KUNIT_CASE(dm_test_nv_set_min_deep_sleep_dcfclk_ok),
+       KUNIT_CASE(dm_test_nv_set_min_deep_sleep_dcfclk_unsupported),
+       KUNIT_CASE(dm_test_nv_set_min_deep_sleep_dcfclk_fail),
+       /* pp_nv_set_hard_min_dcefclk_by_freq */
+       KUNIT_CASE(dm_test_nv_set_hard_min_dcefclk_ok),
+       KUNIT_CASE(dm_test_nv_set_hard_min_dcefclk_unsupported),
+       KUNIT_CASE(dm_test_nv_set_hard_min_dcefclk_fail),
+       /* pp_nv_set_hard_min_uclk_by_freq */
+       KUNIT_CASE(dm_test_nv_set_hard_min_uclk_ok),
+       KUNIT_CASE(dm_test_nv_set_hard_min_uclk_unsupported),
+       KUNIT_CASE(dm_test_nv_set_hard_min_uclk_fail),
+       /* pp_nv_get_maximum_sustainable_clocks */
+       KUNIT_CASE(dm_test_nv_get_max_sustainable_clocks_ok),
+       KUNIT_CASE(dm_test_nv_get_max_sustainable_clocks_unsupported),
+       KUNIT_CASE(dm_test_nv_get_max_sustainable_clocks_fail),
+       /* pp_nv_get_uclk_dpm_states */
+       KUNIT_CASE(dm_test_nv_get_uclk_dpm_states_ok),
+       KUNIT_CASE(dm_test_nv_get_uclk_dpm_states_unsupported),
+       KUNIT_CASE(dm_test_nv_get_uclk_dpm_states_fail),
        {}
 };
 
-- 
2.53.0

Reply via email to