]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/amd/powerplay: delete eventmgr layer in poweprlay
authorRex Zhu <Rex.Zhu@amd.com>
Fri, 1 Sep 2017 05:46:20 +0000 (13:46 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 12 Sep 2017 18:21:50 +0000 (14:21 -0400)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
13 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/powerplay/Makefile
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/amd/powerplay/inc/pp_instance.h

index 8c96a4caa715eefbc81d398381e5e26a7c17742f..3eba4137508be32fd67f44c42b1126d417b62ef7 100644 (file)
@@ -383,8 +383,8 @@ struct amdgpu_dpm_funcs {
 #define amdgpu_dpm_set_mclk_od(adev, value) \
        ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value))
 
-#define amdgpu_dpm_dispatch_task(adev, event_id, input, output)                \
-       (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
+#define amdgpu_dpm_dispatch_task(adev, task_id, input, output)         \
+       ((adev)->powerplay.pp_funcs->dispatch_tasks)((adev)->powerplay.pp_handle, (task_id), (input), (output))
 
 #define amgdpu_dpm_check_state_equal(adev, cps, rps, equal) (adev)->pm.funcs->check_state_equal((adev), (cps),(rps),(equal))
 
index 7df503aedb692b86c7111bd81f63ac60eba793c4..10c5d78081edfd8cbc926c28e74420be84fb75eb 100644 (file)
@@ -119,7 +119,7 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev,
        }
 
        if (adev->pp_enabled) {
-               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state, NULL);
        } else {
                mutex_lock(&adev->pm.mutex);
                adev->pm.dpm.user_state = state;
@@ -330,7 +330,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
                if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
                    state != POWER_STATE_TYPE_DEFAULT) {
                        amdgpu_dpm_dispatch_task(adev,
-                                       AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
+                                       AMD_PP_TASK_ENABLE_USER_STATE, &state, NULL);
                        adev->pp_force_state_enabled = true;
                }
        }
@@ -559,7 +559,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev,
 
        if (adev->pp_enabled) {
                amdgpu_dpm_set_sclk_od(adev, (uint32_t)value);
-               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
        } else if (adev->pm.funcs->set_sclk_od) {
                adev->pm.funcs->set_sclk_od(adev, (uint32_t)value);
                adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
@@ -605,7 +605,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev,
 
        if (adev->pp_enabled) {
                amdgpu_dpm_set_mclk_od(adev, (uint32_t)value);
-               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
        } else if (adev->pm.funcs->set_mclk_od) {
                adev->pm.funcs->set_mclk_od(adev, (uint32_t)value);
                adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
@@ -1496,7 +1496,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
        }
 
        if (adev->pp_enabled) {
-               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL, NULL);
        } else {
                mutex_lock(&adev->pm.mutex);
                adev->pm.dpm.new_active_crtcs = 0;
index b7e1c026c0c861435346adc4a703724fecf6aab6..b0c4db8098edc43fb9f8f64b7b7568875f0f0a89 100644 (file)
@@ -128,7 +128,7 @@ static int amdgpu_pp_late_init(void *handle)
 
        if (adev->pp_enabled && adev->pm.dpm_enabled) {
                amdgpu_pm_sysfs_init(adev);
-               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
        }
 
        return ret;
index 4e132b936e3d2afdc885c21adbeba1280259405c..68b417ac94ddb4db2890270446bdf87cf4a67165 100644 (file)
@@ -4,12 +4,11 @@ subdir-ccflags-y += \
                -I$(FULL_AMD_PATH)/include/asic_reg  \
                -I$(FULL_AMD_PATH)/include  \
                -I$(FULL_AMD_PATH)/powerplay/smumgr\
-               -I$(FULL_AMD_PATH)/powerplay/hwmgr \
-               -I$(FULL_AMD_PATH)/powerplay/eventmgr
+               -I$(FULL_AMD_PATH)/powerplay/hwmgr
 
 AMD_PP_PATH = ../powerplay
 
-PP_LIBS = smumgr hwmgr eventmgr
+PP_LIBS = smumgr hwmgr
 
 AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/powerplay/,$(PP_LIBS)))
 
index f73e80c4bf3374b136a816f4c4dc72ccca05e62d..94bed3c08161b2b0d4081559d3183ca5c07959ca 100644 (file)
@@ -29,7 +29,6 @@
 #include "amd_powerplay.h"
 #include "pp_instance.h"
 #include "power_state.h"
-#include "eventmanager.h"
 
 
 static inline int pp_check(struct pp_instance *handle)
@@ -43,8 +42,7 @@ static inline int pp_check(struct pp_instance *handle)
        if (handle->pm_en == 0)
                return PP_DPM_DISABLED;
 
-       if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL
-               || handle->eventmgr == NULL)
+       if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL)
                return PP_DPM_DISABLED;
 
        return 0;
@@ -69,14 +67,6 @@ static int pp_early_init(void *handle)
                return PP_DPM_DISABLED;
        }
 
-       ret = eventmgr_early_init(pp_handle);
-       if (ret) {
-               kfree(pp_handle->hwmgr);
-               pp_handle->hwmgr = NULL;
-               pp_handle->pm_en = 0;
-               return PP_DPM_DISABLED;
-       }
-
        return 0;
 }
 
@@ -122,7 +112,6 @@ static int pp_sw_fini(void *handle)
 static int pp_hw_init(void *handle)
 {
        struct pp_smumgr *smumgr;
-       struct pp_eventmgr *eventmgr;
        int ret = 0;
        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 
@@ -146,38 +135,23 @@ static int pp_hw_init(void *handle)
        ret = hwmgr_hw_init(pp_handle);
        if (ret)
                goto err;
-
-       eventmgr = pp_handle->eventmgr;
-       if (eventmgr->pp_eventmgr_init == NULL ||
-               eventmgr->pp_eventmgr_init(eventmgr))
-               goto err;
-
        return 0;
 err:
        pp_handle->pm_en = 0;
-       kfree(pp_handle->eventmgr);
        kfree(pp_handle->hwmgr);
        pp_handle->hwmgr = NULL;
-       pp_handle->eventmgr = NULL;
        return PP_DPM_DISABLED;
 }
 
 static int pp_hw_fini(void *handle)
 {
-       struct pp_eventmgr *eventmgr;
        struct pp_instance *pp_handle = (struct pp_instance *)handle;
        int ret = 0;
 
        ret = pp_check(pp_handle);
-
-       if (ret == 0) {
-               eventmgr = pp_handle->eventmgr;
-
-               if (eventmgr->pp_eventmgr_fini != NULL)
-                       eventmgr->pp_eventmgr_fini(eventmgr);
-
+       if (ret == 0)
                hwmgr_hw_fini(pp_handle);
-       }
+
        return 0;
 }
 
@@ -244,8 +218,6 @@ static int pp_set_powergating_state(void *handle,
 
 static int pp_suspend(void *handle)
 {
-       struct pp_eventmgr *eventmgr;
-       struct pem_event_data event_data = { {0} };
        struct pp_instance *pp_handle = (struct pp_instance *)handle;
        int ret = 0;
 
@@ -256,16 +228,11 @@ static int pp_suspend(void *handle)
        else if (ret != 0)
                return ret;
 
-       eventmgr = pp_handle->eventmgr;
-       pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
-
-       return 0;
+       return hwmgr_hw_suspend(pp_handle);
 }
 
 static int pp_resume(void *handle)
 {
-       struct pp_eventmgr *eventmgr;
-       struct pem_event_data event_data = { {0} };
        struct pp_smumgr *smumgr;
        int ret, ret1;
        struct pp_instance *pp_handle = (struct pp_instance *)handle;
@@ -290,11 +257,7 @@ static int pp_resume(void *handle)
        if (ret1 == PP_DPM_DISABLED)
                return 0;
 
-       eventmgr = pp_handle->eventmgr;
-
-       pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
-
-       return 0;
+       return hwmgr_hw_resume(pp_handle);
 }
 
 const struct amd_ip_funcs pp_ip_funcs = {
@@ -344,6 +307,7 @@ static int pp_dpm_force_performance_level(void *handle,
        }
 
        mutex_lock(&pp_handle->pp_lock);
+       hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
        hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
        mutex_unlock(&pp_handle->pp_lock);
        return 0;
@@ -461,60 +425,21 @@ static int pp_dpm_powergate_uvd(void *handle, bool gate)
        return ret;
 }
 
-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;
-       }
-}
-
-static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
+static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
                void *input, void *output)
 {
        int ret = 0;
-       struct pem_event_data data = { {0} };
        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 
        ret = pp_check(pp_handle);
 
        if (ret != 0)
                return ret;
-       mutex_lock(&pp_handle->pp_lock);
-       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) {
-                       ret = -EINVAL;
-                       break;
-               }
-               ps = *(unsigned long *)input;
 
-               data.requested_ui_label = power_state_convert(ps);
-               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
-               break;
-       }
-       case AMD_PP_EVENT_COMPLETE_INIT:
-               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
-               break;
-       case AMD_PP_EVENT_READJUST_POWER_STATE:
-               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
-               break;
-       default:
-               break;
-       }
+       mutex_lock(&pp_handle->pp_lock);
+       ret = hwmgr_handle_task(pp_handle, task_id, input, output);
        mutex_unlock(&pp_handle->pp_lock);
+
        return ret;
 }
 
@@ -1190,10 +1115,8 @@ int amd_powerplay_destroy(void *handle)
        struct pp_instance *instance = (struct pp_instance *)handle;
 
        if (instance->pm_en) {
-               kfree(instance->eventmgr);
                kfree(instance->hwmgr);
                instance->hwmgr = NULL;
-               instance->eventmgr = NULL;
        }
 
        kfree(instance->smu_mgr);
@@ -1206,8 +1129,6 @@ int amd_powerplay_destroy(void *handle)
 int amd_powerplay_reset(void *handle)
 {
        struct pp_instance *instance = (struct pp_instance *)handle;
-       struct pp_eventmgr *eventmgr;
-       struct pem_event_data event_data = { {0} };
        int ret;
 
        if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
@@ -1217,7 +1138,7 @@ int amd_powerplay_reset(void *handle)
        if (ret != 0)
                return ret;
 
-       ret = pp_hw_fini(handle);
+       ret = pp_hw_fini(instance);
        if (ret)
                return ret;
 
@@ -1225,16 +1146,7 @@ int amd_powerplay_reset(void *handle)
        if (ret)
                return PP_DPM_DISABLED;
 
-       eventmgr = instance->eventmgr;
-
-       if (eventmgr->pp_eventmgr_init == NULL)
-               return PP_DPM_DISABLED;
-
-       ret = eventmgr->pp_eventmgr_init(eventmgr);
-       if (ret)
-               return ret;
-
-       return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
+       return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
 }
 
 /* export this function to DAL */
index f0277c16c2bff5b62497d24b3f85e2437dd4fc54..79119d6cd07f21d666855d58ead5c4f855a09347 100644 (file)
@@ -9,7 +9,8 @@ HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \
                smu7_hwmgr.o smu7_powertune.o smu7_thermal.o \
                smu7_clockpowergating.o \
                vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \
-               vega10_thermal.o pp_overdriver.o rv_hwmgr.o
+               vega10_thermal.o rv_hwmgr.o pp_psm.o\
+               pp_overdriver.o
 
 AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
 
index 967f50f54384d4a560a133ba6822168c5ed42006..ce378bd21661334ff960ea03c6aa86fd5d0d33e5 100644 (file)
 #include "hardwaremanager.h"
 #include "power_state.h"
 
+
+#define TEMP_RANGE_MIN (90 * 1000)
+#define TEMP_RANGE_MAX (120 * 1000)
+
 #define PHM_FUNC_CHECK(hw) \
        do {                                                    \
                if ((hw) == NULL || (hw)->hwmgr_func == NULL)   \
@@ -292,7 +296,19 @@ int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info)
 */
 int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range)
 {
-       return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL);
+       struct PP_TemperatureRange range;
+
+       if (temperature_range == NULL) {
+               range.max = TEMP_RANGE_MAX;
+               range.min = TEMP_RANGE_MIN;
+       } else {
+               range.max = temperature_range->max;
+               range.min = temperature_range->min;
+       }
+       if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+                       PHM_PlatformCaps_ThermalController))
+               return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), &range, NULL);
+       return 0;
 }
 
 
index 9547f265a8bb86d11e1edd42637eda55adb6c8d3..c6157bcdf7d690063178c4acace1504609f563be 100644 (file)
@@ -35,9 +35,9 @@
 #include "ppsmc.h"
 #include "pp_acpi.h"
 #include "amd_acpi.h"
+#include "pp_psm.h"
 
 extern int cz_init_function_pointers(struct pp_hwmgr *hwmgr);
-
 static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
 static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr);
 static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr);
@@ -131,80 +131,6 @@ int hwmgr_early_init(struct pp_instance *handle)
        return 0;
 }
 
-static int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
-{
-       int result;
-       unsigned int i;
-       unsigned int table_entries;
-       struct pp_power_state *state;
-       int size;
-
-       if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
-               return -EINVAL;
-
-       if (hwmgr->hwmgr_func->get_power_state_size == NULL)
-               return -EINVAL;
-
-       hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
-
-       hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
-                                         sizeof(struct pp_power_state);
-
-       hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
-       if (hwmgr->ps == NULL)
-               return -ENOMEM;
-
-       hwmgr->request_ps = kzalloc(size, GFP_KERNEL);
-       if (hwmgr->request_ps == NULL) {
-               kfree(hwmgr->ps);
-               hwmgr->ps = NULL;
-               return -ENOMEM;
-       }
-
-       hwmgr->current_ps = kzalloc(size, GFP_KERNEL);
-       if (hwmgr->current_ps == NULL) {
-               kfree(hwmgr->request_ps);
-               kfree(hwmgr->ps);
-               hwmgr->request_ps = NULL;
-               hwmgr->ps = NULL;
-               return -ENOMEM;
-       }
-
-       state = hwmgr->ps;
-
-       for (i = 0; i < table_entries; i++) {
-               result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
-
-               if (state->classification.flags & PP_StateClassificationFlag_Boot) {
-                       hwmgr->boot_ps = state;
-                       memcpy(hwmgr->current_ps, state, size);
-                       memcpy(hwmgr->request_ps, state, size);
-               }
-
-               state->id = i + 1; /* assigned unique num for every power state id */
-
-               if (state->classification.flags & PP_StateClassificationFlag_Uvd)
-                       hwmgr->uvd_ps = state;
-               state = (struct pp_power_state *)((unsigned long)state + size);
-       }
-
-       return 0;
-}
-
-static int hw_fini_power_state_table(struct pp_hwmgr *hwmgr)
-{
-       if (hwmgr == NULL)
-               return -EINVAL;
-
-       kfree(hwmgr->current_ps);
-       kfree(hwmgr->request_ps);
-       kfree(hwmgr->ps);
-       hwmgr->request_ps = NULL;
-       hwmgr->ps = NULL;
-       hwmgr->current_ps = NULL;
-       return 0;
-}
-
 int hwmgr_hw_init(struct pp_instance *handle)
 {
        struct pp_hwmgr *hwmgr;
@@ -228,9 +154,22 @@ int hwmgr_hw_init(struct pp_instance *handle)
        if (ret)
                goto err1;
 
-       ret = hw_init_power_state_table(hwmgr);
+       ret = psm_init_power_state_table(hwmgr);
+       if (ret)
+               goto err2;
+
+       ret = phm_setup_asic(hwmgr);
        if (ret)
                goto err2;
+
+       ret = phm_enable_dynamic_state_management(hwmgr);
+       if (ret)
+               goto err2;
+       ret = phm_start_thermal_controller(hwmgr, NULL);
+       ret |= psm_set_performance_states(hwmgr);
+       if (ret)
+               goto err2;
+
        return 0;
 err2:
        if (hwmgr->hwmgr_func->backend_fini)
@@ -247,19 +186,138 @@ int hwmgr_hw_fini(struct pp_instance *handle)
 {
        struct pp_hwmgr *hwmgr;
 
-       if (handle == NULL)
+       if (handle == NULL || handle->hwmgr == NULL)
                return -EINVAL;
 
        hwmgr = handle->hwmgr;
 
+       phm_stop_thermal_controller(hwmgr);
+       psm_set_boot_states(hwmgr);
+       phm_display_configuration_changed(hwmgr);
+       psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+       phm_disable_dynamic_state_management(hwmgr);
+       phm_disable_clock_power_gatings(hwmgr);
+
        if (hwmgr->hwmgr_func->backend_fini)
                hwmgr->hwmgr_func->backend_fini(hwmgr);
        if (hwmgr->pptable_func->pptable_fini)
                hwmgr->pptable_func->pptable_fini(hwmgr);
-       return hw_fini_power_state_table(hwmgr);
+       return psm_fini_power_state_table(hwmgr);
 }
 
+int hwmgr_hw_suspend(struct pp_instance *handle)
+{
+       struct pp_hwmgr *hwmgr;
+       int ret = 0;
+
+       if (handle == NULL || handle->hwmgr == NULL)
+               return -EINVAL;
 
+       hwmgr = handle->hwmgr;
+       phm_disable_smc_firmware_ctf(hwmgr);
+       ret = psm_set_boot_states(hwmgr);
+       if (ret)
+               return ret;
+       ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+       if (ret)
+               return ret;
+       ret = phm_power_down_asic(hwmgr);
+
+       return ret;
+}
+
+int hwmgr_hw_resume(struct pp_instance *handle)
+{
+       struct pp_hwmgr *hwmgr;
+       int ret = 0;
+
+       if (handle == NULL || handle->hwmgr == NULL)
+               return -EINVAL;
+
+       hwmgr = handle->hwmgr;
+       ret = phm_setup_asic(hwmgr);
+       if (ret)
+               return ret;
+
+       ret = phm_enable_dynamic_state_management(hwmgr);
+       if (ret)
+               return ret;
+       ret = phm_start_thermal_controller(hwmgr, NULL);
+       if (ret)
+               return ret;
+
+       ret |= psm_set_performance_states(hwmgr);
+       if (ret)
+               return ret;
+
+       ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+
+       return ret;
+}
+
+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 hwmgr_handle_task(struct pp_instance *handle, enum amd_pp_task task_id,
+               void *input, void *output)
+{
+       int ret = 0;
+       struct pp_hwmgr *hwmgr;
+
+       if (handle == NULL || handle->hwmgr == NULL)
+               return -EINVAL;
+
+       hwmgr = handle->hwmgr;
+
+       switch (task_id) {
+       case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE:
+               ret = phm_set_cpu_power_state(hwmgr);
+               if (ret)
+                       return ret;
+               ret = psm_set_performance_states(hwmgr);
+               if (ret)
+                       return ret;
+               ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+               break;
+       case AMD_PP_TASK_ENABLE_USER_STATE:
+       {
+               enum amd_pm_state_type ps;
+               enum PP_StateUILabel requested_ui_label;
+               struct pp_power_state *requested_ps;
+
+               if (input == NULL) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ps = *(unsigned long *)input;
+
+               requested_ui_label = power_state_convert(ps);
+               ret = psm_set_user_performance_state(hwmgr, requested_ui_label, requested_ps);
+               if (ret)
+                       return ret;
+               ret = psm_adjust_power_state_dynamic(hwmgr, false, requested_ps);
+               break;
+       }
+       case AMD_PP_TASK_COMPLETE_INIT:
+       case AMD_PP_TASK_READJUST_POWER_STATE:
+               ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
 /**
  * Returns once the part of the register indicated by the mask has
  * reached the given value.
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
new file mode 100644 (file)
index 0000000..7656324
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "pp_psm.h"
+
+int psm_init_power_state_table(struct pp_hwmgr *hwmgr)
+{
+       int result;
+       unsigned int i;
+       unsigned int table_entries;
+       struct pp_power_state *state;
+       int size;
+
+       if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
+               return -EINVAL;
+
+       if (hwmgr->hwmgr_func->get_power_state_size == NULL)
+               return -EINVAL;
+
+       hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
+
+       hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
+                                         sizeof(struct pp_power_state);
+
+       hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
+       if (hwmgr->ps == NULL)
+               return -ENOMEM;
+
+       hwmgr->request_ps = kzalloc(size, GFP_KERNEL);
+       if (hwmgr->request_ps == NULL) {
+               kfree(hwmgr->ps);
+               hwmgr->ps = NULL;
+               return -ENOMEM;
+       }
+
+       hwmgr->current_ps = kzalloc(size, GFP_KERNEL);
+       if (hwmgr->current_ps == NULL) {
+               kfree(hwmgr->request_ps);
+               kfree(hwmgr->ps);
+               hwmgr->request_ps = NULL;
+               hwmgr->ps = NULL;
+               return -ENOMEM;
+       }
+
+       state = hwmgr->ps;
+
+       for (i = 0; i < table_entries; i++) {
+               result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
+
+               if (state->classification.flags & PP_StateClassificationFlag_Boot) {
+                       hwmgr->boot_ps = state;
+                       memcpy(hwmgr->current_ps, state, size);
+                       memcpy(hwmgr->request_ps, state, size);
+               }
+
+               state->id = i + 1; /* assigned unique num for every power state id */
+
+               if (state->classification.flags & PP_StateClassificationFlag_Uvd)
+                       hwmgr->uvd_ps = state;
+               state = (struct pp_power_state *)((unsigned long)state + size);
+       }
+
+       return 0;
+}
+
+int psm_fini_power_state_table(struct pp_hwmgr *hwmgr)
+{
+       if (hwmgr == NULL)
+               return -EINVAL;
+
+       kfree(hwmgr->current_ps);
+       kfree(hwmgr->request_ps);
+       kfree(hwmgr->ps);
+       hwmgr->request_ps = NULL;
+       hwmgr->ps = NULL;
+       hwmgr->current_ps = NULL;
+       return 0;
+}
+
+static int psm_get_ui_state(struct pp_hwmgr *hwmgr,
+                               enum PP_StateUILabel ui_label,
+                               unsigned long *state_id)
+{
+       struct pp_power_state *state;
+       int table_entries;
+       int i;
+
+       table_entries = hwmgr->num_ps;
+       state = hwmgr->ps;
+
+       for (i = 0; i < table_entries; i++) {
+               if (state->classification.ui_label & ui_label) {
+                       *state_id = state->id;
+                       return 0;
+               }
+               state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+       }
+       return -EINVAL;
+}
+
+static int psm_get_state_by_classification(struct pp_hwmgr *hwmgr,
+                                       enum PP_StateClassificationFlag flag,
+                                       unsigned long *state_id)
+{
+       struct pp_power_state *state;
+       int table_entries;
+       int i;
+
+       table_entries = hwmgr->num_ps;
+       state = hwmgr->ps;
+
+       for (i = 0; i < table_entries; i++) {
+               if (state->classification.flags & flag) {
+                       *state_id = state->id;
+                       return 0;
+               }
+               state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+       }
+       return -EINVAL;
+}
+
+static int psm_set_states(struct pp_hwmgr *hwmgr, unsigned long state_id)
+{
+       struct pp_power_state *state;
+       int table_entries;
+       int i;
+
+       table_entries = hwmgr->num_ps;
+
+       state = hwmgr->ps;
+
+       for (i = 0; i < table_entries; i++) {
+               if (state->id == state_id) {
+                       memcpy(hwmgr->request_ps, state, hwmgr->ps_size);
+                       return 0;
+               }
+               state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+       }
+       return -EINVAL;
+}
+
+int psm_set_boot_states(struct pp_hwmgr *hwmgr)
+{
+       unsigned long state_id;
+       int ret = -EINVAL;
+
+       if (!psm_get_state_by_classification(hwmgr, PP_StateClassificationFlag_Boot,
+                                       &state_id))
+               ret = psm_set_states(hwmgr, state_id);
+
+       return ret;
+}
+
+int psm_set_performance_states(struct pp_hwmgr *hwmgr)
+{
+       unsigned long state_id;
+       int ret = -EINVAL;
+
+       if (!psm_get_ui_state(hwmgr, PP_StateUILabel_Performance,
+                                       &state_id))
+               ret = psm_set_states(hwmgr, state_id);
+
+       return ret;
+}
+
+int psm_set_user_performance_state(struct pp_hwmgr *hwmgr,
+                                       enum PP_StateUILabel label_id,
+                                       struct pp_power_state *state)
+{
+       int table_entries;
+       int i;
+
+       table_entries = hwmgr->num_ps;
+       state = hwmgr->ps;
+
+restart_search:
+       for (i = 0; i < table_entries; i++) {
+               if (state->classification.ui_label & label_id)
+                       return 0;
+               state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+       }
+
+       switch (label_id) {
+       case PP_StateUILabel_Battery:
+       case PP_StateUILabel_Balanced:
+               label_id = PP_StateUILabel_Performance;
+               goto restart_search;
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
+int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
+                                               struct pp_power_state *new_ps)
+{
+       struct pp_power_state *pcurrent;
+       struct pp_power_state *requested;
+       bool equal;
+
+       if (skip)
+               return 0;
+
+       if (new_ps != NULL)
+               requested = new_ps;
+       else
+               requested = hwmgr->request_ps;
+
+       pcurrent = hwmgr->current_ps;
+
+       phm_apply_state_adjust_rules(hwmgr, requested, pcurrent);
+
+       if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr,
+                       &pcurrent->hardware, &requested->hardware, &equal)))
+               equal = false;
+
+       if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) {
+               phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware);
+               memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size);
+       }
+       return 0;
+}
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h
new file mode 100644 (file)
index 0000000..aa44e60
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef PP_PSM_H
+#define PP_PSM_H
+
+#include "hwmgr.h"
+
+int psm_init_power_state_table(struct pp_hwmgr *hwmgr);
+int psm_fini_power_state_table(struct pp_hwmgr *hwmgr);
+int psm_set_boot_states(struct pp_hwmgr *hwmgr);
+int psm_set_performance_states(struct pp_hwmgr *hwmgr);
+int psm_set_user_performance_state(struct pp_hwmgr *hwmgr,
+                                       enum PP_StateUILabel label_id,
+                                       struct pp_power_state *state);
+int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr,
+                               bool skip,
+                               struct pp_power_state *new_ps);
+
+#endif
index 07e9c0b5915db453ddb131fbdc4bf13e135a5036..f471b99f456bdc2efc8309fa8b31deaf7cece072 100644 (file)
@@ -50,94 +50,12 @@ enum amd_pp_sensors {
        AMDGPU_PP_SENSOR_GPU_POWER,
 };
 
-enum amd_pp_event {
-       AMD_PP_EVENT_INITIALIZE = 0,
-       AMD_PP_EVENT_UNINITIALIZE,
-       AMD_PP_EVENT_POWER_SOURCE_CHANGE,
-       AMD_PP_EVENT_SUSPEND,
-       AMD_PP_EVENT_RESUME,
-       AMD_PP_EVENT_ENTER_REST_STATE,
-       AMD_PP_EVENT_EXIT_REST_STATE,
-       AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE,
-       AMD_PP_EVENT_THERMAL_NOTIFICATION,
-       AMD_PP_EVENT_VBIOS_NOTIFICATION,
-       AMD_PP_EVENT_ENTER_THERMAL_STATE,
-       AMD_PP_EVENT_EXIT_THERMAL_STATE,
-       AMD_PP_EVENT_ENTER_FORCED_STATE,
-       AMD_PP_EVENT_EXIT_FORCED_STATE,
-       AMD_PP_EVENT_ENTER_EXCLUSIVE_MODE,
-       AMD_PP_EVENT_EXIT_EXCLUSIVE_MODE,
-       AMD_PP_EVENT_ENTER_SCREEN_SAVER,
-       AMD_PP_EVENT_EXIT_SCREEN_SAVER,
-       AMD_PP_EVENT_VPU_RECOVERY_BEGIN,
-       AMD_PP_EVENT_VPU_RECOVERY_END,
-       AMD_PP_EVENT_ENABLE_POWER_PLAY,
-       AMD_PP_EVENT_DISABLE_POWER_PLAY,
-       AMD_PP_EVENT_CHANGE_POWER_SOURCE_UI_LABEL,
-       AMD_PP_EVENT_ENABLE_USER2D_PERFORMANCE,
-       AMD_PP_EVENT_DISABLE_USER2D_PERFORMANCE,
-       AMD_PP_EVENT_ENABLE_USER3D_PERFORMANCE,
-       AMD_PP_EVENT_DISABLE_USER3D_PERFORMANCE,
-       AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST,
-       AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST,
-       AMD_PP_EVENT_ENABLE_REDUCED_REFRESH_RATE,
-       AMD_PP_EVENT_DISABLE_REDUCED_REFRESH_RATE,
-       AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING,
-       AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING,
-       AMD_PP_EVENT_ENABLE_CGPG,
-       AMD_PP_EVENT_DISABLE_CGPG,
-       AMD_PP_EVENT_ENTER_TEXT_MODE,
-       AMD_PP_EVENT_EXIT_TEXT_MODE,
-       AMD_PP_EVENT_VIDEO_START,
-       AMD_PP_EVENT_VIDEO_STOP,
-       AMD_PP_EVENT_ENABLE_USER_STATE,
-       AMD_PP_EVENT_DISABLE_USER_STATE,
-       AMD_PP_EVENT_READJUST_POWER_STATE,
-       AMD_PP_EVENT_START_INACTIVITY,
-       AMD_PP_EVENT_STOP_INACTIVITY,
-       AMD_PP_EVENT_LINKED_ADAPTERS_READY,
-       AMD_PP_EVENT_ADAPTER_SAFE_TO_DISABLE,
-       AMD_PP_EVENT_COMPLETE_INIT,
-       AMD_PP_EVENT_CRITICAL_THERMAL_FAULT,
-       AMD_PP_EVENT_BACKLIGHT_CHANGED,
-       AMD_PP_EVENT_ENABLE_VARI_BRIGHT,
-       AMD_PP_EVENT_DISABLE_VARI_BRIGHT,
-       AMD_PP_EVENT_ENABLE_VARI_BRIGHT_ON_POWER_XPRESS,
-       AMD_PP_EVENT_DISABLE_VARI_BRIGHT_ON_POWER_XPRESS,
-       AMD_PP_EVENT_SET_VARI_BRIGHT_LEVEL,
-       AMD_PP_EVENT_VARI_BRIGHT_MONITOR_MEASUREMENT,
-       AMD_PP_EVENT_SCREEN_ON,
-       AMD_PP_EVENT_SCREEN_OFF,
-       AMD_PP_EVENT_PRE_DISPLAY_CONFIG_CHANGE,
-       AMD_PP_EVENT_ENTER_ULP_STATE,
-       AMD_PP_EVENT_EXIT_ULP_STATE,
-       AMD_PP_EVENT_REGISTER_IP_STATE,
-       AMD_PP_EVENT_UNREGISTER_IP_STATE,
-       AMD_PP_EVENT_ENTER_MGPU_MODE,
-       AMD_PP_EVENT_EXIT_MGPU_MODE,
-       AMD_PP_EVENT_ENTER_MULTI_GPU_MODE,
-       AMD_PP_EVENT_PRE_SUSPEND,
-       AMD_PP_EVENT_PRE_RESUME,
-       AMD_PP_EVENT_ENTER_BACOS,
-       AMD_PP_EVENT_EXIT_BACOS,
-       AMD_PP_EVENT_RESUME_BACO,
-       AMD_PP_EVENT_RESET_BACO,
-       AMD_PP_EVENT_PRE_DISPLAY_PHY_ACCESS,
-       AMD_PP_EVENT_POST_DISPLAY_PHY_CCESS,
-       AMD_PP_EVENT_START_COMPUTE_APPLICATION,
-       AMD_PP_EVENT_STOP_COMPUTE_APPLICATION,
-       AMD_PP_EVENT_REDUCE_POWER_LIMIT,
-       AMD_PP_EVENT_ENTER_FRAME_LOCK,
-       AMD_PP_EVENT_EXIT_FRAME_LOOCK,
-       AMD_PP_EVENT_LONG_IDLE_REQUEST_BACO,
-       AMD_PP_EVENT_LONG_IDLE_ENTER_BACO,
-       AMD_PP_EVENT_LONG_IDLE_EXIT_BACO,
-       AMD_PP_EVENT_HIBERNATE,
-       AMD_PP_EVENT_CONNECTED_STANDBY,
-       AMD_PP_EVENT_ENTER_SELF_REFRESH,
-       AMD_PP_EVENT_EXIT_SELF_REFRESH,
-       AMD_PP_EVENT_START_AVFS_BTC,
-       AMD_PP_EVENT_MAX
+enum amd_pp_task {
+       AMD_PP_TASK_DISPLAY_CONFIG_CHANGE,
+       AMD_PP_TASK_ENABLE_USER_STATE,
+       AMD_PP_TASK_READJUST_POWER_STATE,
+       AMD_PP_TASK_COMPLETE_INIT,
+       AMD_PP_TASK_MAX
 };
 
 struct amd_pp_init {
@@ -366,7 +284,7 @@ struct amd_powerplay_funcs {
        int (*get_mclk)(void *handle, bool low);
        int (*powergate_vce)(void *handle, bool gate);
        int (*powergate_uvd)(void *handle, bool gate);
-       int (*dispatch_tasks)(void *handle, enum amd_pp_event event_id,
+       int (*dispatch_tasks)(void *handle, enum amd_pp_task task_id,
                                   void *input, void *output);
        int (*set_fan_control_mode)(void *handle, uint32_t mode);
        int (*get_fan_control_mode)(void *handle);
index b1a6372608de7c07de14c4b00462eb034b39fe9a..c649354f08ca957774f20ec46308e0271cbc06a8 100644 (file)
@@ -797,6 +797,11 @@ struct pp_hwmgr {
 extern int hwmgr_early_init(struct pp_instance *handle);
 extern int hwmgr_hw_init(struct pp_instance *handle);
 extern int hwmgr_hw_fini(struct pp_instance *handle);
+extern int hwmgr_hw_suspend(struct pp_instance *handle);
+extern int hwmgr_hw_resume(struct pp_instance *handle);
+extern int hwmgr_handle_task(struct pp_instance *handle,
+                               enum amd_pp_task task_id,
+                               void *input, void *output);
 extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
                                uint32_t value, uint32_t mask);
 
index 4c3b537a714f5b8c318678150da7641d2e4fb366..5bf2ee449e42cdf857143d5b5a15c5a9472322cb 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "smumgr.h"
 #include "hwmgr.h"
-#include "eventmgr.h"
 
 #define PP_VALID  0x1F1F1F1F
 
@@ -38,7 +37,6 @@ struct pp_instance {
        void *device;
        struct pp_smumgr *smu_mgr;
        struct pp_hwmgr *hwmgr;
-       struct pp_eventmgr *eventmgr;
        struct mutex pp_lock;
 };