xref: /dragonfly/sys/dev/drm/amd/powerplay/hwmgr/hardwaremanager.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "pp_debug.h"
24 #include <linux/errno.h>
25 #include "hwmgr.h"
26 #include "hardwaremanager.h"
27 #include "power_state.h"
28 
29 
30 #define TEMP_RANGE_MIN (0)
31 #define TEMP_RANGE_MAX (80 * 1000)
32 
33 #define PHM_FUNC_CHECK(hw) \
34           do {                                                                  \
35                     if ((hw) == NULL || (hw)->hwmgr_func == NULL)     \
36                               return -EINVAL;                                   \
37           } while (0)
38 
phm_setup_asic(struct pp_hwmgr * hwmgr)39 int phm_setup_asic(struct pp_hwmgr *hwmgr)
40 {
41           PHM_FUNC_CHECK(hwmgr);
42 
43           if (NULL != hwmgr->hwmgr_func->asic_setup)
44                     return hwmgr->hwmgr_func->asic_setup(hwmgr);
45 
46           return 0;
47 }
48 
phm_power_down_asic(struct pp_hwmgr * hwmgr)49 int phm_power_down_asic(struct pp_hwmgr *hwmgr)
50 {
51           PHM_FUNC_CHECK(hwmgr);
52 
53           if (NULL != hwmgr->hwmgr_func->power_off_asic)
54                     return hwmgr->hwmgr_func->power_off_asic(hwmgr);
55 
56           return 0;
57 }
58 
phm_set_power_state(struct pp_hwmgr * hwmgr,const struct pp_hw_power_state * pcurrent_state,const struct pp_hw_power_state * pnew_power_state)59 int phm_set_power_state(struct pp_hwmgr *hwmgr,
60                         const struct pp_hw_power_state *pcurrent_state,
61                         const struct pp_hw_power_state *pnew_power_state)
62 {
63           struct phm_set_power_state_input states;
64 
65           PHM_FUNC_CHECK(hwmgr);
66 
67           states.pcurrent_state = pcurrent_state;
68           states.pnew_state = pnew_power_state;
69 
70           if (NULL != hwmgr->hwmgr_func->power_state_set)
71                     return hwmgr->hwmgr_func->power_state_set(hwmgr, &states);
72 
73           return 0;
74 }
75 
phm_enable_dynamic_state_management(struct pp_hwmgr * hwmgr)76 int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
77 {
78           struct amdgpu_device *adev = NULL;
79           int ret = -EINVAL;;
80           PHM_FUNC_CHECK(hwmgr);
81           adev = hwmgr->adev;
82 
83           if (smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev)) {
84                     pr_info("dpm has been enabled\n");
85                     return 0;
86           }
87 
88           if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable)
89                     ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr);
90 
91           return ret;
92 }
93 
phm_disable_dynamic_state_management(struct pp_hwmgr * hwmgr)94 int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr)
95 {
96           int ret = -EINVAL;
97 
98           PHM_FUNC_CHECK(hwmgr);
99 
100           if (!smum_is_dpm_running(hwmgr)) {
101                     pr_info("dpm has been disabled\n");
102                     return 0;
103           }
104 
105           if (hwmgr->hwmgr_func->dynamic_state_management_disable)
106                     ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr);
107 
108           return ret;
109 }
110 
phm_force_dpm_levels(struct pp_hwmgr * hwmgr,enum amd_dpm_forced_level level)111 int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level)
112 {
113           int ret = 0;
114 
115           PHM_FUNC_CHECK(hwmgr);
116 
117           if (hwmgr->hwmgr_func->force_dpm_level != NULL)
118                     ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
119 
120           return ret;
121 }
122 
phm_apply_state_adjust_rules(struct pp_hwmgr * hwmgr,struct pp_power_state * adjusted_ps,const struct pp_power_state * current_ps)123 int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
124                                            struct pp_power_state *adjusted_ps,
125                                    const struct pp_power_state *current_ps)
126 {
127           PHM_FUNC_CHECK(hwmgr);
128 
129           if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL)
130                     return hwmgr->hwmgr_func->apply_state_adjust_rules(
131                                                                                           hwmgr,
132                                                                                  adjusted_ps,
133                                                                                  current_ps);
134           return 0;
135 }
136 
phm_apply_clock_adjust_rules(struct pp_hwmgr * hwmgr)137 int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr)
138 {
139           PHM_FUNC_CHECK(hwmgr);
140 
141           if (hwmgr->hwmgr_func->apply_clocks_adjust_rules != NULL)
142                     return hwmgr->hwmgr_func->apply_clocks_adjust_rules(hwmgr);
143           return 0;
144 }
145 
phm_powerdown_uvd(struct pp_hwmgr * hwmgr)146 int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
147 {
148           PHM_FUNC_CHECK(hwmgr);
149 
150           if (hwmgr->hwmgr_func->powerdown_uvd != NULL)
151                     return hwmgr->hwmgr_func->powerdown_uvd(hwmgr);
152           return 0;
153 }
154 
phm_enable_clock_power_gatings(struct pp_hwmgr * hwmgr)155 int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr)
156 {
157           PHM_FUNC_CHECK(hwmgr);
158 
159           if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating)
160                     return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr);
161 
162           return 0;
163 }
164 
phm_disable_clock_power_gatings(struct pp_hwmgr * hwmgr)165 int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
166 {
167           PHM_FUNC_CHECK(hwmgr);
168 
169           if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating)
170                     return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr);
171 
172           return 0;
173 }
174 
phm_pre_display_configuration_changed(struct pp_hwmgr * hwmgr)175 int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr)
176 {
177           PHM_FUNC_CHECK(hwmgr);
178 
179           if (NULL != hwmgr->hwmgr_func->pre_display_config_changed)
180                     hwmgr->hwmgr_func->pre_display_config_changed(hwmgr);
181 
182           return 0;
183 
184 }
185 
phm_display_configuration_changed(struct pp_hwmgr * hwmgr)186 int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
187 {
188           PHM_FUNC_CHECK(hwmgr);
189 
190           if (NULL != hwmgr->hwmgr_func->display_config_changed)
191                     hwmgr->hwmgr_func->display_config_changed(hwmgr);
192 
193           return 0;
194 }
195 
phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr * hwmgr)196 int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
197 {
198           PHM_FUNC_CHECK(hwmgr);
199 
200           if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment)
201                               hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr);
202 
203           return 0;
204 }
205 
phm_stop_thermal_controller(struct pp_hwmgr * hwmgr)206 int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr)
207 {
208           PHM_FUNC_CHECK(hwmgr);
209 
210           if (hwmgr->hwmgr_func->stop_thermal_controller == NULL)
211                     return -EINVAL;
212 
213           return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr);
214 }
215 
phm_register_irq_handlers(struct pp_hwmgr * hwmgr)216 int phm_register_irq_handlers(struct pp_hwmgr *hwmgr)
217 {
218           PHM_FUNC_CHECK(hwmgr);
219 
220           if (hwmgr->hwmgr_func->register_irq_handlers != NULL)
221                     return hwmgr->hwmgr_func->register_irq_handlers(hwmgr);
222 
223           return 0;
224 }
225 
226 /**
227 * Initializes the thermal controller subsystem.
228 *
229 * @param    pHwMgr  the address of the powerplay hardware manager.
230 * @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher.
231 */
phm_start_thermal_controller(struct pp_hwmgr * hwmgr)232 int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
233 {
234           int ret = 0;
235           struct PP_TemperatureRange range = {TEMP_RANGE_MIN, TEMP_RANGE_MAX};
236           struct amdgpu_device *adev = hwmgr->adev;
237 
238           if (hwmgr->hwmgr_func->get_thermal_temperature_range)
239                     hwmgr->hwmgr_func->get_thermal_temperature_range(
240                                         hwmgr, &range);
241 
242           if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
243                               PHM_PlatformCaps_ThermalController)
244                               && hwmgr->hwmgr_func->start_thermal_controller != NULL)
245                     ret = hwmgr->hwmgr_func->start_thermal_controller(hwmgr, &range);
246 
247           adev->pm.dpm.thermal.min_temp = range.min;
248           adev->pm.dpm.thermal.max_temp = range.max;
249 
250           return ret;
251 }
252 
253 
phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr * hwmgr)254 bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
255 {
256           PHM_FUNC_CHECK(hwmgr);
257 
258           if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL)
259                     return false;
260 
261           return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr);
262 }
263 
264 
phm_check_states_equal(struct pp_hwmgr * hwmgr,const struct pp_hw_power_state * pstate1,const struct pp_hw_power_state * pstate2,bool * equal)265 int phm_check_states_equal(struct pp_hwmgr *hwmgr,
266                                          const struct pp_hw_power_state *pstate1,
267                                          const struct pp_hw_power_state *pstate2,
268                                          bool *equal)
269 {
270           PHM_FUNC_CHECK(hwmgr);
271 
272           if (hwmgr->hwmgr_func->check_states_equal == NULL)
273                     return -EINVAL;
274 
275           return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal);
276 }
277 
phm_store_dal_configuration_data(struct pp_hwmgr * hwmgr,const struct amd_pp_display_configuration * display_config)278 int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
279                         const struct amd_pp_display_configuration *display_config)
280 {
281           int index = 0;
282           int number_of_active_display = 0;
283 
284           PHM_FUNC_CHECK(hwmgr);
285 
286           if (display_config == NULL)
287                     return -EINVAL;
288 
289           if (NULL != hwmgr->hwmgr_func->set_deep_sleep_dcefclk)
290                     hwmgr->hwmgr_func->set_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk);
291 
292           for (index = 0; index < display_config->num_path_including_non_display; index++) {
293                     if (display_config->displays[index].controller_id != 0)
294                               number_of_active_display++;
295           }
296 
297           if (NULL != hwmgr->hwmgr_func->set_active_display_count)
298                     hwmgr->hwmgr_func->set_active_display_count(hwmgr, number_of_active_display);
299 
300           if (hwmgr->hwmgr_func->store_cc6_data == NULL)
301                     return -EINVAL;
302 
303           /* TODO: pass other display configuration in the future */
304 
305           if (hwmgr->hwmgr_func->store_cc6_data)
306                     hwmgr->hwmgr_func->store_cc6_data(hwmgr,
307                                         display_config->cpu_pstate_separation_time,
308                                         display_config->cpu_cc6_disable,
309                                         display_config->cpu_pstate_disable,
310                                         display_config->nb_pstate_switch_disable);
311 
312           return 0;
313 }
314 
phm_get_dal_power_level(struct pp_hwmgr * hwmgr,struct amd_pp_simple_clock_info * info)315 int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
316                     struct amd_pp_simple_clock_info *info)
317 {
318           PHM_FUNC_CHECK(hwmgr);
319 
320           if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL)
321                     return -EINVAL;
322           return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info);
323 }
324 
phm_set_cpu_power_state(struct pp_hwmgr * hwmgr)325 int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr)
326 {
327           PHM_FUNC_CHECK(hwmgr);
328 
329           if (hwmgr->hwmgr_func->set_cpu_power_state != NULL)
330                     return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr);
331 
332           return 0;
333 }
334 
335 
phm_get_performance_level(struct pp_hwmgr * hwmgr,const struct pp_hw_power_state * state,PHM_PerformanceLevelDesignation designation,uint32_t index,PHM_PerformanceLevel * level)336 int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
337                                         PHM_PerformanceLevelDesignation designation, uint32_t index,
338                                         PHM_PerformanceLevel *level)
339 {
340           PHM_FUNC_CHECK(hwmgr);
341           if (hwmgr->hwmgr_func->get_performance_level == NULL)
342                     return -EINVAL;
343 
344           return hwmgr->hwmgr_func->get_performance_level(hwmgr, state, designation, index, level);
345 
346 
347 }
348 
349 
350 /**
351 * Gets Clock Info.
352 *
353 * @param    pHwMgr  the address of the powerplay hardware manager.
354 * @param    pPowerState the address of the Power State structure.
355 * @param    pClockInfo the address of PP_ClockInfo structure where the result will be returned.
356 * @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end.
357 */
phm_get_clock_info(struct pp_hwmgr * hwmgr,const struct pp_hw_power_state * state,struct pp_clock_info * pclock_info,PHM_PerformanceLevelDesignation designation)358 int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info,
359                               PHM_PerformanceLevelDesignation designation)
360 {
361           int result;
362           PHM_PerformanceLevel performance_level;
363 
364           PHM_FUNC_CHECK(hwmgr);
365 
366           PP_ASSERT_WITH_CODE((NULL != state), "Invalid Input!", return -EINVAL);
367           PP_ASSERT_WITH_CODE((NULL != pclock_info), "Invalid Input!", return -EINVAL);
368 
369           result = phm_get_performance_level(hwmgr, state, PHM_PerformanceLevelDesignation_Activity, 0, &performance_level);
370 
371           PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve minimum clocks.", return result);
372 
373 
374           pclock_info->min_mem_clk = performance_level.memory_clock;
375           pclock_info->min_eng_clk = performance_level.coreClock;
376           pclock_info->min_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
377 
378 
379           result = phm_get_performance_level(hwmgr, state, designation,
380                                                   (hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1), &performance_level);
381 
382           PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve maximum clocks.", return result);
383 
384           pclock_info->max_mem_clk = performance_level.memory_clock;
385           pclock_info->max_eng_clk = performance_level.coreClock;
386           pclock_info->max_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
387 
388           return 0;
389 }
390 
phm_get_current_shallow_sleep_clocks(struct pp_hwmgr * hwmgr,const struct pp_hw_power_state * state,struct pp_clock_info * clock_info)391 int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
392 {
393           PHM_FUNC_CHECK(hwmgr);
394 
395           if (hwmgr->hwmgr_func->get_current_shallow_sleep_clocks == NULL)
396                     return -EINVAL;
397 
398           return hwmgr->hwmgr_func->get_current_shallow_sleep_clocks(hwmgr, state, clock_info);
399 
400 }
401 
phm_get_clock_by_type(struct pp_hwmgr * hwmgr,enum amd_pp_clock_type type,struct amd_pp_clocks * clocks)402 int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
403 {
404           PHM_FUNC_CHECK(hwmgr);
405 
406           if (hwmgr->hwmgr_func->get_clock_by_type == NULL)
407                     return -EINVAL;
408 
409           return hwmgr->hwmgr_func->get_clock_by_type(hwmgr, type, clocks);
410 
411 }
412 
phm_get_clock_by_type_with_latency(struct pp_hwmgr * hwmgr,enum amd_pp_clock_type type,struct pp_clock_levels_with_latency * clocks)413 int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
414                     enum amd_pp_clock_type type,
415                     struct pp_clock_levels_with_latency *clocks)
416 {
417           PHM_FUNC_CHECK(hwmgr);
418 
419           if (hwmgr->hwmgr_func->get_clock_by_type_with_latency == NULL)
420                     return -EINVAL;
421 
422           return hwmgr->hwmgr_func->get_clock_by_type_with_latency(hwmgr, type, clocks);
423 
424 }
425 
phm_get_clock_by_type_with_voltage(struct pp_hwmgr * hwmgr,enum amd_pp_clock_type type,struct pp_clock_levels_with_voltage * clocks)426 int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
427                     enum amd_pp_clock_type type,
428                     struct pp_clock_levels_with_voltage *clocks)
429 {
430           PHM_FUNC_CHECK(hwmgr);
431 
432           if (hwmgr->hwmgr_func->get_clock_by_type_with_voltage == NULL)
433                     return -EINVAL;
434 
435           return hwmgr->hwmgr_func->get_clock_by_type_with_voltage(hwmgr, type, clocks);
436 
437 }
438 
phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr * hwmgr,void * clock_ranges)439 int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
440                                                   void *clock_ranges)
441 {
442           PHM_FUNC_CHECK(hwmgr);
443 
444           if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges)
445                     return -EINVAL;
446 
447           return hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr,
448                                                                                 clock_ranges);
449 }
450 
phm_display_clock_voltage_request(struct pp_hwmgr * hwmgr,struct pp_display_clock_request * clock)451 int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
452                     struct pp_display_clock_request *clock)
453 {
454           PHM_FUNC_CHECK(hwmgr);
455 
456           if (!hwmgr->hwmgr_func->display_clock_voltage_request)
457                     return -EINVAL;
458 
459           return hwmgr->hwmgr_func->display_clock_voltage_request(hwmgr, clock);
460 }
461 
phm_get_max_high_clocks(struct pp_hwmgr * hwmgr,struct amd_pp_simple_clock_info * clocks)462 int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
463 {
464           PHM_FUNC_CHECK(hwmgr);
465 
466           if (hwmgr->hwmgr_func->get_max_high_clocks == NULL)
467                     return -EINVAL;
468 
469           return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks);
470 }
471 
phm_disable_smc_firmware_ctf(struct pp_hwmgr * hwmgr)472 int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr)
473 {
474           PHM_FUNC_CHECK(hwmgr);
475 
476           if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL)
477                     return -EINVAL;
478 
479           return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr);
480 }
481