Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2015 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 #include "pp_debug.h"
0024 #include <linux/errno.h>
0025 #include "hwmgr.h"
0026 #include "hardwaremanager.h"
0027 #include "power_state.h"
0028 
0029 
0030 #define TEMP_RANGE_MIN (0)
0031 #define TEMP_RANGE_MAX (80 * 1000)
0032 
0033 #define PHM_FUNC_CHECK(hw) \
0034     do {                            \
0035         if ((hw) == NULL || (hw)->hwmgr_func == NULL)   \
0036             return -EINVAL;             \
0037     } while (0)
0038 
0039 int phm_setup_asic(struct pp_hwmgr *hwmgr)
0040 {
0041     PHM_FUNC_CHECK(hwmgr);
0042 
0043     if (NULL != hwmgr->hwmgr_func->asic_setup)
0044         return hwmgr->hwmgr_func->asic_setup(hwmgr);
0045 
0046     return 0;
0047 }
0048 
0049 int phm_power_down_asic(struct pp_hwmgr *hwmgr)
0050 {
0051     PHM_FUNC_CHECK(hwmgr);
0052 
0053     if (NULL != hwmgr->hwmgr_func->power_off_asic)
0054         return hwmgr->hwmgr_func->power_off_asic(hwmgr);
0055 
0056     return 0;
0057 }
0058 
0059 int phm_set_power_state(struct pp_hwmgr *hwmgr,
0060             const struct pp_hw_power_state *pcurrent_state,
0061             const struct pp_hw_power_state *pnew_power_state)
0062 {
0063     struct phm_set_power_state_input states;
0064 
0065     PHM_FUNC_CHECK(hwmgr);
0066 
0067     states.pcurrent_state = pcurrent_state;
0068     states.pnew_state = pnew_power_state;
0069 
0070     if (NULL != hwmgr->hwmgr_func->power_state_set)
0071         return hwmgr->hwmgr_func->power_state_set(hwmgr, &states);
0072 
0073     return 0;
0074 }
0075 
0076 int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
0077 {
0078     struct amdgpu_device *adev = NULL;
0079     int ret = -EINVAL;
0080     PHM_FUNC_CHECK(hwmgr);
0081     adev = hwmgr->adev;
0082 
0083     /* Skip for suspend/resume case */
0084     if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr)
0085         && !amdgpu_passthrough(adev) && adev->in_suspend
0086         && adev->asic_type != CHIP_RAVEN) {
0087         pr_info("dpm has been enabled\n");
0088         return 0;
0089     }
0090 
0091     if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable)
0092         ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr);
0093 
0094     return ret;
0095 }
0096 
0097 int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr)
0098 {
0099     int ret = -EINVAL;
0100 
0101     PHM_FUNC_CHECK(hwmgr);
0102 
0103     if (!hwmgr->not_vf)
0104         return 0;
0105 
0106     if (!smum_is_dpm_running(hwmgr)) {
0107         pr_info("dpm has been disabled\n");
0108         return 0;
0109     }
0110 
0111     if (hwmgr->hwmgr_func->dynamic_state_management_disable)
0112         ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr);
0113 
0114     return ret;
0115 }
0116 
0117 int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level)
0118 {
0119     int ret = 0;
0120 
0121     PHM_FUNC_CHECK(hwmgr);
0122 
0123     if (hwmgr->hwmgr_func->force_dpm_level != NULL)
0124         ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
0125 
0126     return ret;
0127 }
0128 
0129 int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
0130                    struct pp_power_state *adjusted_ps,
0131                  const struct pp_power_state *current_ps)
0132 {
0133     PHM_FUNC_CHECK(hwmgr);
0134 
0135     if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL)
0136         return hwmgr->hwmgr_func->apply_state_adjust_rules(
0137                                     hwmgr,
0138                                  adjusted_ps,
0139                                  current_ps);
0140     return 0;
0141 }
0142 
0143 int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr)
0144 {
0145     PHM_FUNC_CHECK(hwmgr);
0146 
0147     if (hwmgr->hwmgr_func->apply_clocks_adjust_rules != NULL)
0148         return hwmgr->hwmgr_func->apply_clocks_adjust_rules(hwmgr);
0149     return 0;
0150 }
0151 
0152 int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
0153 {
0154     PHM_FUNC_CHECK(hwmgr);
0155 
0156     if (hwmgr->hwmgr_func->powerdown_uvd != NULL)
0157         return hwmgr->hwmgr_func->powerdown_uvd(hwmgr);
0158     return 0;
0159 }
0160 
0161 
0162 int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
0163 {
0164     PHM_FUNC_CHECK(hwmgr);
0165 
0166     if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating)
0167         return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr);
0168 
0169     return 0;
0170 }
0171 
0172 int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr)
0173 {
0174     PHM_FUNC_CHECK(hwmgr);
0175 
0176     if (NULL != hwmgr->hwmgr_func->pre_display_config_changed)
0177         hwmgr->hwmgr_func->pre_display_config_changed(hwmgr);
0178 
0179     return 0;
0180 
0181 }
0182 
0183 int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
0184 {
0185     PHM_FUNC_CHECK(hwmgr);
0186 
0187     if (NULL != hwmgr->hwmgr_func->display_config_changed)
0188         hwmgr->hwmgr_func->display_config_changed(hwmgr);
0189 
0190     return 0;
0191 }
0192 
0193 int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
0194 {
0195     PHM_FUNC_CHECK(hwmgr);
0196 
0197     if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment)
0198             hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr);
0199 
0200     return 0;
0201 }
0202 
0203 int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr)
0204 {
0205     PHM_FUNC_CHECK(hwmgr);
0206 
0207     if (!hwmgr->not_vf)
0208         return 0;
0209 
0210     if (hwmgr->hwmgr_func->stop_thermal_controller == NULL)
0211         return -EINVAL;
0212 
0213     return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr);
0214 }
0215 
0216 int phm_register_irq_handlers(struct pp_hwmgr *hwmgr)
0217 {
0218     PHM_FUNC_CHECK(hwmgr);
0219 
0220     if (hwmgr->hwmgr_func->register_irq_handlers != NULL)
0221         return hwmgr->hwmgr_func->register_irq_handlers(hwmgr);
0222 
0223     return 0;
0224 }
0225 
0226 /**
0227  * phm_start_thermal_controller - Initializes the thermal controller subsystem.
0228  *
0229  * @hwmgr:   the address of the powerplay hardware manager.
0230  * Exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher.
0231  */
0232 int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
0233 {
0234     int ret = 0;
0235     struct PP_TemperatureRange range = {
0236         TEMP_RANGE_MIN,
0237         TEMP_RANGE_MAX,
0238         TEMP_RANGE_MAX,
0239         TEMP_RANGE_MIN,
0240         TEMP_RANGE_MAX,
0241         TEMP_RANGE_MAX,
0242         TEMP_RANGE_MIN,
0243         TEMP_RANGE_MAX,
0244         TEMP_RANGE_MAX};
0245     struct amdgpu_device *adev = hwmgr->adev;
0246 
0247     if (!hwmgr->not_vf)
0248         return 0;
0249 
0250     if (hwmgr->hwmgr_func->get_thermal_temperature_range)
0251         hwmgr->hwmgr_func->get_thermal_temperature_range(
0252                 hwmgr, &range);
0253 
0254     if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
0255             PHM_PlatformCaps_ThermalController)
0256             && hwmgr->hwmgr_func->start_thermal_controller != NULL)
0257         ret = hwmgr->hwmgr_func->start_thermal_controller(hwmgr, &range);
0258 
0259     adev->pm.dpm.thermal.min_temp = range.min;
0260     adev->pm.dpm.thermal.max_temp = range.max;
0261     adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max;
0262     adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min;
0263     adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max;
0264     adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max;
0265     adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
0266     adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
0267     adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
0268 
0269     return ret;
0270 }
0271 
0272 
0273 bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
0274 {
0275     if (hwmgr == NULL ||
0276         hwmgr->hwmgr_func == NULL)
0277         return false;
0278 
0279     if (hwmgr->pp_one_vf)
0280         return false;
0281 
0282     if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL)
0283         return false;
0284 
0285     return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr);
0286 }
0287 
0288 
0289 int phm_check_states_equal(struct pp_hwmgr *hwmgr,
0290                  const struct pp_hw_power_state *pstate1,
0291                  const struct pp_hw_power_state *pstate2,
0292                  bool *equal)
0293 {
0294     PHM_FUNC_CHECK(hwmgr);
0295 
0296     if (hwmgr->hwmgr_func->check_states_equal == NULL)
0297         return -EINVAL;
0298 
0299     return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal);
0300 }
0301 
0302 int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
0303             const struct amd_pp_display_configuration *display_config)
0304 {
0305     int index = 0;
0306     int number_of_active_display = 0;
0307 
0308     PHM_FUNC_CHECK(hwmgr);
0309 
0310     if (display_config == NULL)
0311         return -EINVAL;
0312 
0313     if (NULL != hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk)
0314         hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk);
0315 
0316     for (index = 0; index < display_config->num_path_including_non_display; index++) {
0317         if (display_config->displays[index].controller_id != 0)
0318             number_of_active_display++;
0319     }
0320 
0321     if (NULL != hwmgr->hwmgr_func->set_active_display_count)
0322         hwmgr->hwmgr_func->set_active_display_count(hwmgr, number_of_active_display);
0323 
0324     if (hwmgr->hwmgr_func->store_cc6_data == NULL)
0325         return -EINVAL;
0326 
0327     /* TODO: pass other display configuration in the future */
0328 
0329     if (hwmgr->hwmgr_func->store_cc6_data)
0330         hwmgr->hwmgr_func->store_cc6_data(hwmgr,
0331                 display_config->cpu_pstate_separation_time,
0332                 display_config->cpu_cc6_disable,
0333                 display_config->cpu_pstate_disable,
0334                 display_config->nb_pstate_switch_disable);
0335 
0336     return 0;
0337 }
0338 
0339 int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
0340         struct amd_pp_simple_clock_info *info)
0341 {
0342     PHM_FUNC_CHECK(hwmgr);
0343 
0344     if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL)
0345         return -EINVAL;
0346     return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info);
0347 }
0348 
0349 int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr)
0350 {
0351     PHM_FUNC_CHECK(hwmgr);
0352 
0353     if (hwmgr->hwmgr_func->set_cpu_power_state != NULL)
0354         return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr);
0355 
0356     return 0;
0357 }
0358 
0359 
0360 int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
0361                 PHM_PerformanceLevelDesignation designation, uint32_t index,
0362                 PHM_PerformanceLevel *level)
0363 {
0364     PHM_FUNC_CHECK(hwmgr);
0365     if (hwmgr->hwmgr_func->get_performance_level == NULL)
0366         return -EINVAL;
0367 
0368     return hwmgr->hwmgr_func->get_performance_level(hwmgr, state, designation, index, level);
0369 
0370 
0371 }
0372 
0373 
0374 /**
0375  * phm_get_clock_info
0376  *
0377  * @hwmgr:  the address of the powerplay hardware manager.
0378  * @state: the address of the Power State structure.
0379  * @pclock_info: the address of PP_ClockInfo structure where the result will be returned.
0380  * @designation: PHM performance level designation
0381  * Exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end.
0382  */
0383 int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info,
0384             PHM_PerformanceLevelDesignation designation)
0385 {
0386     int result;
0387     PHM_PerformanceLevel performance_level = {0};
0388 
0389     PHM_FUNC_CHECK(hwmgr);
0390 
0391     PP_ASSERT_WITH_CODE((NULL != state), "Invalid Input!", return -EINVAL);
0392     PP_ASSERT_WITH_CODE((NULL != pclock_info), "Invalid Input!", return -EINVAL);
0393 
0394     result = phm_get_performance_level(hwmgr, state, PHM_PerformanceLevelDesignation_Activity, 0, &performance_level);
0395 
0396     PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve minimum clocks.", return result);
0397 
0398 
0399     pclock_info->min_mem_clk = performance_level.memory_clock;
0400     pclock_info->min_eng_clk = performance_level.coreClock;
0401     pclock_info->min_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
0402 
0403 
0404     result = phm_get_performance_level(hwmgr, state, designation,
0405                     (hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1), &performance_level);
0406 
0407     PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve maximum clocks.", return result);
0408 
0409     pclock_info->max_mem_clk = performance_level.memory_clock;
0410     pclock_info->max_eng_clk = performance_level.coreClock;
0411     pclock_info->max_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
0412 
0413     return 0;
0414 }
0415 
0416 int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
0417 {
0418     PHM_FUNC_CHECK(hwmgr);
0419 
0420     if (hwmgr->hwmgr_func->get_current_shallow_sleep_clocks == NULL)
0421         return -EINVAL;
0422 
0423     return hwmgr->hwmgr_func->get_current_shallow_sleep_clocks(hwmgr, state, clock_info);
0424 
0425 }
0426 
0427 int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
0428 {
0429     PHM_FUNC_CHECK(hwmgr);
0430 
0431     if (hwmgr->hwmgr_func->get_clock_by_type == NULL)
0432         return -EINVAL;
0433 
0434     return hwmgr->hwmgr_func->get_clock_by_type(hwmgr, type, clocks);
0435 
0436 }
0437 
0438 int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
0439         enum amd_pp_clock_type type,
0440         struct pp_clock_levels_with_latency *clocks)
0441 {
0442     PHM_FUNC_CHECK(hwmgr);
0443 
0444     if (hwmgr->hwmgr_func->get_clock_by_type_with_latency == NULL)
0445         return -EINVAL;
0446 
0447     return hwmgr->hwmgr_func->get_clock_by_type_with_latency(hwmgr, type, clocks);
0448 
0449 }
0450 
0451 int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
0452         enum amd_pp_clock_type type,
0453         struct pp_clock_levels_with_voltage *clocks)
0454 {
0455     PHM_FUNC_CHECK(hwmgr);
0456 
0457     if (hwmgr->hwmgr_func->get_clock_by_type_with_voltage == NULL)
0458         return -EINVAL;
0459 
0460     return hwmgr->hwmgr_func->get_clock_by_type_with_voltage(hwmgr, type, clocks);
0461 
0462 }
0463 
0464 int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
0465                     void *clock_ranges)
0466 {
0467     PHM_FUNC_CHECK(hwmgr);
0468 
0469     if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges)
0470         return -EINVAL;
0471 
0472     return hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr,
0473                                 clock_ranges);
0474 }
0475 
0476 int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
0477         struct pp_display_clock_request *clock)
0478 {
0479     PHM_FUNC_CHECK(hwmgr);
0480 
0481     if (!hwmgr->hwmgr_func->display_clock_voltage_request)
0482         return -EINVAL;
0483 
0484     return hwmgr->hwmgr_func->display_clock_voltage_request(hwmgr, clock);
0485 }
0486 
0487 int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
0488 {
0489     PHM_FUNC_CHECK(hwmgr);
0490 
0491     if (hwmgr->hwmgr_func->get_max_high_clocks == NULL)
0492         return -EINVAL;
0493 
0494     return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks);
0495 }
0496 
0497 int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr)
0498 {
0499     PHM_FUNC_CHECK(hwmgr);
0500 
0501     if (!hwmgr->not_vf)
0502         return 0;
0503 
0504     if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL)
0505         return -EINVAL;
0506 
0507     return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr);
0508 }
0509 
0510 int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count)
0511 {
0512     PHM_FUNC_CHECK(hwmgr);
0513 
0514     if (!hwmgr->hwmgr_func->set_active_display_count)
0515         return -EINVAL;
0516 
0517     return hwmgr->hwmgr_func->set_active_display_count(hwmgr, count);
0518 }