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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 */
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 
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 
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 
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 
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 
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 
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 */
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 
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 
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 
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 
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 
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 
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 
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 
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