]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/pm: Fix si_upload_smc_data (v3)
authorTimur Kristóf <timur.kristof@gmail.com>
Thu, 28 Aug 2025 15:11:06 +0000 (17:11 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 2 Sep 2025 19:55:10 +0000 (15:55 -0400)
The si_upload_smc_data function uses si_write_smc_soft_register
to set some register values in the SMC, and expects the result
to be PPSMC_Result_OK which is 1.

The PPSMC_Result_OK / PPSMC_Result_Failed values are used for
checking the result of a command sent to the SMC.
However, the si_write_smc_soft_register actually doesn't send
any commands to the SMC and returns zero on success,
so this check was incorrect.

Fix that by not checking the return value, just like other
calls to si_write_smc_soft_register.

v3:
Additionally, when no display is plugged in, there is no need
to restrict MCLK switching, so program the registers to zero.

Fixes: 841686df9f7d ("drm/amdgpu: add SI DPM support (v4)")
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c

index e71070a23b91515611ddff9fa207e5cfe4264b88..6736c592dfdc607e06a133c6cf8d62d1cf5ca6af 100644 (file)
@@ -5813,9 +5813,9 @@ static int si_upload_smc_data(struct amdgpu_device *adev)
 {
        struct amdgpu_crtc *amdgpu_crtc = NULL;
        int i;
-
-       if (adev->pm.dpm.new_active_crtc_count == 0)
-               return 0;
+       u32 crtc_index = 0;
+       u32 mclk_change_block_cp_min = 0;
+       u32 mclk_change_block_cp_max = 0;
 
        for (i = 0; i < adev->mode_info.num_crtc; i++) {
                if (adev->pm.dpm.new_active_crtcs & (1 << i)) {
@@ -5824,26 +5824,31 @@ static int si_upload_smc_data(struct amdgpu_device *adev)
                }
        }
 
-       if (amdgpu_crtc == NULL)
-               return 0;
+       /* When a display is plugged in, program these so that the SMC
+        * performs MCLK switching when it doesn't cause flickering.
+        * When no display is plugged in, there is no need to restrict
+        * MCLK switching, so program them to zero.
+        */
+       if (adev->pm.dpm.new_active_crtc_count && amdgpu_crtc) {
+               crtc_index = amdgpu_crtc->crtc_id;
 
-       if (amdgpu_crtc->line_time <= 0)
-               return 0;
+               if (amdgpu_crtc->line_time) {
+                       mclk_change_block_cp_min = amdgpu_crtc->wm_high / amdgpu_crtc->line_time;
+                       mclk_change_block_cp_max = amdgpu_crtc->wm_low / amdgpu_crtc->line_time;
+               }
+       }
 
-       if (si_write_smc_soft_register(adev,
-                                      SI_SMC_SOFT_REGISTER_crtc_index,
-                                      amdgpu_crtc->crtc_id) != PPSMC_Result_OK)
-               return 0;
+       si_write_smc_soft_register(adev,
+               SI_SMC_SOFT_REGISTER_crtc_index,
+               crtc_index);
 
-       if (si_write_smc_soft_register(adev,
-                                      SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min,
-                                      amdgpu_crtc->wm_high / amdgpu_crtc->line_time) != PPSMC_Result_OK)
-               return 0;
+       si_write_smc_soft_register(adev,
+               SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min,
+               mclk_change_block_cp_min);
 
-       if (si_write_smc_soft_register(adev,
-                                      SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max,
-                                      amdgpu_crtc->wm_low / amdgpu_crtc->line_time) != PPSMC_Result_OK)
-               return 0;
+       si_write_smc_soft_register(adev,
+               SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max,
+               mclk_change_block_cp_max);
 
        return 0;
 }