drm/amd/powerplay: implement functions of amd_powerplay_func
authorRex Zhu <Rex.Zhu@amd.com>
Fri, 28 Aug 2015 04:56:43 +0000 (12:56 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 21 Dec 2015 21:42:12 +0000 (16:42 -0500)
This is the common interface for interacting with the powerplay
module.

v2: squash in fixes

Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Acked-by: Jammy Zhou <Jammy.Zhou@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/amd_powerplay.c

index 1964a2add63fbef1ad5047ddb8e7ad9fd5fcd7cd..66ccfc0fc6221568d4998db7db95dd2a7180da6f 100644 (file)
@@ -27,6 +27,8 @@
 #include "amd_shared.h"
 #include "amd_powerplay.h"
 #include "pp_instance.h"
+#include "power_state.h"
+#include "eventmanager.h"
 
 static int pp_early_init(void *handle)
 {
@@ -177,11 +179,31 @@ static int pp_set_powergating_state(void *handle,
 
 static int pp_suspend(void *handle)
 {
+       struct pp_instance *pp_handle;
+       struct pp_eventmgr *eventmgr;
+       struct pem_event_data event_data = { {0} };
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       pp_handle = (struct pp_instance *)handle;
+       eventmgr = pp_handle->eventmgr;
+       pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
        return 0;
 }
 
 static int pp_resume(void *handle)
 {
+       struct pp_instance *pp_handle;
+       struct pp_eventmgr *eventmgr;
+       struct pem_event_data event_data = { {0} };
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       pp_handle = (struct pp_instance *)handle;
+       eventmgr = pp_handle->eventmgr;
+       pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
        return 0;
 }
 
@@ -215,45 +237,198 @@ static int pp_dpm_fw_loading_complete(void *handle)
 static int pp_dpm_force_performance_level(void *handle,
                                        enum amd_dpm_forced_level level)
 {
+       struct pp_instance *pp_handle;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       pp_handle = (struct pp_instance *)handle;
+
+       hwmgr = pp_handle->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+           hwmgr->hwmgr_func->force_dpm_level == NULL)
+               return -EINVAL;
+
+       hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
+
        return 0;
 }
+
 static enum amd_dpm_forced_level pp_dpm_get_performance_level(
                                                                void *handle)
 {
-       return 0;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL)
+               return -EINVAL;
+
+       return (((struct pp_instance *)handle)->hwmgr->dpm_level);
 }
+
 static int pp_dpm_get_sclk(void *handle, bool low)
 {
-       return 0;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+           hwmgr->hwmgr_func->get_sclk == NULL)
+               return -EINVAL;
+
+       return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
 }
+
 static int pp_dpm_get_mclk(void *handle, bool low)
 {
-       return 0;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+           hwmgr->hwmgr_func->get_mclk == NULL)
+               return -EINVAL;
+
+       return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
 }
+
 static int pp_dpm_powergate_vce(void *handle, bool gate)
 {
-       return 0;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+           hwmgr->hwmgr_func->powergate_vce == NULL)
+               return -EINVAL;
+
+       return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
 }
+
 static int pp_dpm_powergate_uvd(void *handle, bool gate)
 {
-       return 0;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+           hwmgr->hwmgr_func->powergate_uvd == NULL)
+               return -EINVAL;
+
+       return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
+}
+
+static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
+{
+       switch (state) {
+       case POWER_STATE_TYPE_BATTERY:
+               return PP_StateUILabel_Battery;
+       case POWER_STATE_TYPE_BALANCED:
+               return PP_StateUILabel_Balanced;
+       case POWER_STATE_TYPE_PERFORMANCE:
+               return PP_StateUILabel_Performance;
+       default:
+               return PP_StateUILabel_None;
+       }
 }
 
 int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output)
 {
-       return 0;
+       int ret = 0;
+       struct pp_instance *pp_handle;
+       struct pem_event_data data = { {0} };
+
+       pp_handle = (struct pp_instance *)handle;
+
+       if (pp_handle == NULL)
+               return -EINVAL;
+
+       switch (event_id) {
+       case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
+               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+               break;
+       case AMD_PP_EVENT_ENABLE_USER_STATE:
+       {
+               enum amd_pm_state_type  ps;
+
+               if (input == NULL)
+                       return -EINVAL;
+               ps = *(unsigned long *)input;
+
+               data.requested_ui_label = power_state_convert(ps);
+               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+       }
+       break;
+       default:
+               break;
+       }
+       return ret;
 }
+
 enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
 {
-       return 0;
+       struct pp_hwmgr *hwmgr;
+       struct pp_power_state *state;
+
+       if (handle == NULL)
+               return -EINVAL;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->current_ps == NULL)
+               return -EINVAL;
+
+       state = hwmgr->current_ps;
+
+       switch (state->classification.ui_label) {
+       case PP_StateUILabel_Battery:
+               return POWER_STATE_TYPE_BATTERY;
+       case PP_StateUILabel_Balanced:
+               return POWER_STATE_TYPE_BALANCED;
+       case PP_StateUILabel_Performance:
+               return POWER_STATE_TYPE_PERFORMANCE;
+       default:
+               return POWER_STATE_TYPE_DEFAULT;
+       }
 }
+
 static void
 pp_debugfs_print_current_performance_level(void *handle,
                                               struct seq_file *m)
 {
-       return;
+       struct pp_hwmgr  *hwmgr;
+
+       if (handle == NULL)
+               return;
+
+       hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+       if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+         hwmgr->hwmgr_func->print_current_perforce_level == NULL)
+               return;
+
+       hwmgr->hwmgr_func->print_current_perforce_level(hwmgr, m);
 }
 
+
 const struct amd_powerplay_funcs pp_dpm_funcs = {
        .get_temperature = NULL,
        .load_firmware = pp_dpm_load_fw,