drm/amdgpu: add helpers for baco entry and exit
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 4 Oct 2019 17:33:09 +0000 (12:33 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 19 Nov 2019 21:42:52 +0000 (16:42 -0500)
BACO - Bus Active, Chip Off

Will be used for runtime pm.  Entry will enter the BACO
state (chip off).  Exit will exit the BACO state (chip on).

Reviewed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

index 56ef197..c1e6a5f 100644 (file)
@@ -1144,6 +1144,8 @@ bool amdgpu_device_supports_boco(struct drm_device *dev);
 bool amdgpu_device_supports_baco(struct drm_device *dev);
 bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
                                      struct amdgpu_device *peer_adev);
+int amdgpu_device_baco_enter(struct drm_device *dev);
+int amdgpu_device_baco_exit(struct drm_device *dev);
 
 /* atpx handler */
 #if defined(CONFIG_VGA_SWITCHEROO)
index 635091b..612c4cc 100644 (file)
@@ -4296,3 +4296,64 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
        }
 }
 
+int amdgpu_device_baco_enter(struct drm_device *dev)
+{
+       struct amdgpu_device *adev = dev->dev_private;
+
+       if (!amdgpu_device_supports_baco(adev->ddev))
+               return -ENOTSUPP;
+
+       if (is_support_sw_smu(adev)) {
+               struct smu_context *smu = &adev->smu;
+               int ret;
+
+               ret = smu_baco_enter(smu);
+               if (ret)
+                       return ret;
+
+               return 0;
+       } else {
+               void *pp_handle = adev->powerplay.pp_handle;
+               const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+               if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
+                       return -ENOENT;
+
+               /* enter BACO state */
+               if (pp_funcs->set_asic_baco_state(pp_handle, 1))
+                       return -EIO;
+
+               return 0;
+       }
+}
+
+int amdgpu_device_baco_exit(struct drm_device *dev)
+{
+       struct amdgpu_device *adev = dev->dev_private;
+
+       if (!amdgpu_device_supports_baco(adev->ddev))
+               return -ENOTSUPP;
+
+       if (is_support_sw_smu(adev)) {
+               struct smu_context *smu = &adev->smu;
+               int ret;
+
+               ret = smu_baco_exit(smu);
+               if (ret)
+                       return ret;
+
+               return 0;
+       } else {
+               void *pp_handle = adev->powerplay.pp_handle;
+               const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+               if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
+                       return -ENOENT;
+
+               /* exit BACO state */
+               if (pp_funcs->set_asic_baco_state(pp_handle, 0))
+                       return -EIO;
+
+               return 0;
+       }
+}