• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "linux/delay.h"
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <drm/amdgpu_drm.h>
28 #include "cgs_common.h"
29 #include "power_state.h"
30 #include "hwmgr.h"
31 #include "pppcielanes.h"
32 #include "pp_debug.h"
33 #include "ppatomctrl.h"
34 #include "ppsmc.h"
35 #include "pp_acpi.h"
36 #include "amd_acpi.h"
37 
38 extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
39 
40 static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
41 static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr);
42 static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr);
43 static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr);
44 static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr);
45 static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr);
46 
convert_to_vid(uint16_t vddc)47 uint8_t convert_to_vid(uint16_t vddc)
48 {
49 	return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25);
50 }
51 
hwmgr_init(struct amd_pp_init * pp_init,struct pp_instance * handle)52 int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
53 {
54 	struct pp_hwmgr *hwmgr;
55 
56 	if ((handle == NULL) || (pp_init == NULL))
57 		return -EINVAL;
58 
59 	hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
60 	if (hwmgr == NULL)
61 		return -ENOMEM;
62 
63 	handle->hwmgr = hwmgr;
64 	hwmgr->smumgr = handle->smu_mgr;
65 	hwmgr->device = pp_init->device;
66 	hwmgr->chip_family = pp_init->chip_family;
67 	hwmgr->chip_id = pp_init->chip_id;
68 	hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
69 	hwmgr->power_source = PP_PowerSource_AC;
70 	hwmgr->pp_table_version = PP_TABLE_V1;
71 
72 	hwmgr_init_default_caps(hwmgr);
73 	hwmgr_set_user_specify_caps(hwmgr);
74 
75 	switch (hwmgr->chip_family) {
76 	case AMDGPU_FAMILY_CZ:
77 		cz_hwmgr_init(hwmgr);
78 		break;
79 	case AMDGPU_FAMILY_VI:
80 		switch (hwmgr->chip_id) {
81 		case CHIP_TOPAZ:
82 			topaz_set_asic_special_caps(hwmgr);
83 			hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
84 						PP_VBI_TIME_SUPPORT_MASK |
85 						PP_ENABLE_GFX_CG_THRU_SMU);
86 			hwmgr->pp_table_version = PP_TABLE_V0;
87 			break;
88 		case CHIP_TONGA:
89 			tonga_set_asic_special_caps(hwmgr);
90 			hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
91 						PP_VBI_TIME_SUPPORT_MASK);
92 			break;
93 		case CHIP_FIJI:
94 			fiji_set_asic_special_caps(hwmgr);
95 			hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
96 						PP_VBI_TIME_SUPPORT_MASK |
97 						PP_ENABLE_GFX_CG_THRU_SMU);
98 			break;
99 		case CHIP_POLARIS11:
100 		case CHIP_POLARIS10:
101 			polaris_set_asic_special_caps(hwmgr);
102 			hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
103 			break;
104 		default:
105 			return -EINVAL;
106 		}
107 		smu7_hwmgr_init(hwmgr);
108 		break;
109 	default:
110 		return -EINVAL;
111 	}
112 
113 	return 0;
114 }
115 
hwmgr_fini(struct pp_hwmgr * hwmgr)116 int hwmgr_fini(struct pp_hwmgr *hwmgr)
117 {
118 	if (hwmgr == NULL || hwmgr->ps == NULL)
119 		return -EINVAL;
120 
121 	/* do hwmgr finish*/
122 	kfree(hwmgr->hardcode_pp_table);
123 
124 	kfree(hwmgr->backend);
125 
126 	kfree(hwmgr->start_thermal_controller.function_list);
127 
128 	kfree(hwmgr->set_temperature_range.function_list);
129 
130 	kfree(hwmgr->ps);
131 	kfree(hwmgr->current_ps);
132 	kfree(hwmgr->request_ps);
133 	kfree(hwmgr);
134 	return 0;
135 }
136 
hw_init_power_state_table(struct pp_hwmgr * hwmgr)137 int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
138 {
139 	int result;
140 	unsigned int i;
141 	unsigned int table_entries;
142 	struct pp_power_state *state;
143 	int size;
144 
145 	if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
146 		return -EINVAL;
147 
148 	if (hwmgr->hwmgr_func->get_power_state_size == NULL)
149 		return -EINVAL;
150 
151 	hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
152 
153 	hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
154 					  sizeof(struct pp_power_state);
155 
156 	hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
157 	if (hwmgr->ps == NULL)
158 		return -ENOMEM;
159 
160 	hwmgr->request_ps = kzalloc(size, GFP_KERNEL);
161 	if (hwmgr->request_ps == NULL)
162 		return -ENOMEM;
163 
164 	hwmgr->current_ps = kzalloc(size, GFP_KERNEL);
165 	if (hwmgr->current_ps == NULL)
166 		return -ENOMEM;
167 
168 	state = hwmgr->ps;
169 
170 	for (i = 0; i < table_entries; i++) {
171 		result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
172 
173 		if (state->classification.flags & PP_StateClassificationFlag_Boot) {
174 			hwmgr->boot_ps = state;
175 			memcpy(hwmgr->current_ps, state, size);
176 			memcpy(hwmgr->request_ps, state, size);
177 		}
178 
179 		state->id = i + 1; /* assigned unique num for every power state id */
180 
181 		if (state->classification.flags & PP_StateClassificationFlag_Uvd)
182 			hwmgr->uvd_ps = state;
183 		state = (struct pp_power_state *)((unsigned long)state + size);
184 	}
185 
186 
187 	return 0;
188 }
189 
190 
191 /**
192  * Returns once the part of the register indicated by the mask has
193  * reached the given value.
194  */
phm_wait_on_register(struct pp_hwmgr * hwmgr,uint32_t index,uint32_t value,uint32_t mask)195 int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
196 			 uint32_t value, uint32_t mask)
197 {
198 	uint32_t i;
199 	uint32_t cur_value;
200 
201 	if (hwmgr == NULL || hwmgr->device == NULL) {
202 		printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
203 		return -EINVAL;
204 	}
205 
206 	for (i = 0; i < hwmgr->usec_timeout; i++) {
207 		cur_value = cgs_read_register(hwmgr->device, index);
208 		if ((cur_value & mask) == (value & mask))
209 			break;
210 		udelay(1);
211 	}
212 
213 	/* timeout means wrong logic*/
214 	if (i == hwmgr->usec_timeout)
215 		return -1;
216 	return 0;
217 }
218 
219 
220 /**
221  * Returns once the part of the register indicated by the mask has
222  * reached the given value.The indirect space is described by giving
223  * the memory-mapped index of the indirect index register.
224  */
phm_wait_on_indirect_register(struct pp_hwmgr * hwmgr,uint32_t indirect_port,uint32_t index,uint32_t value,uint32_t mask)225 void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
226 				uint32_t indirect_port,
227 				uint32_t index,
228 				uint32_t value,
229 				uint32_t mask)
230 {
231 	if (hwmgr == NULL || hwmgr->device == NULL) {
232 		printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
233 		return;
234 	}
235 
236 	cgs_write_register(hwmgr->device, indirect_port, index);
237 	phm_wait_on_register(hwmgr, indirect_port + 1, mask, value);
238 }
239 
240 
241 
phm_cf_want_uvd_power_gating(struct pp_hwmgr * hwmgr)242 bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr)
243 {
244 	return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating);
245 }
246 
phm_cf_want_vce_power_gating(struct pp_hwmgr * hwmgr)247 bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
248 {
249 	return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
250 }
251 
252 
phm_trim_voltage_table(struct pp_atomctrl_voltage_table * vol_table)253 int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table)
254 {
255 	uint32_t i, j;
256 	uint16_t vvalue;
257 	bool found = false;
258 	struct pp_atomctrl_voltage_table *table;
259 
260 	PP_ASSERT_WITH_CODE((NULL != vol_table),
261 			"Voltage Table empty.", return -EINVAL);
262 
263 	table = kzalloc(sizeof(struct pp_atomctrl_voltage_table),
264 			GFP_KERNEL);
265 
266 	if (NULL == table)
267 		return -EINVAL;
268 
269 	table->mask_low = vol_table->mask_low;
270 	table->phase_delay = vol_table->phase_delay;
271 
272 	for (i = 0; i < vol_table->count; i++) {
273 		vvalue = vol_table->entries[i].value;
274 		found = false;
275 
276 		for (j = 0; j < table->count; j++) {
277 			if (vvalue == table->entries[j].value) {
278 				found = true;
279 				break;
280 			}
281 		}
282 
283 		if (!found) {
284 			table->entries[table->count].value = vvalue;
285 			table->entries[table->count].smio_low =
286 					vol_table->entries[i].smio_low;
287 			table->count++;
288 		}
289 	}
290 
291 	memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
292 	kfree(table);
293 
294 	return 0;
295 }
296 
phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table * vol_table,phm_ppt_v1_clock_voltage_dependency_table * dep_table)297 int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
298 		phm_ppt_v1_clock_voltage_dependency_table *dep_table)
299 {
300 	uint32_t i;
301 	int result;
302 
303 	PP_ASSERT_WITH_CODE((0 != dep_table->count),
304 			"Voltage Dependency Table empty.", return -EINVAL);
305 
306 	PP_ASSERT_WITH_CODE((NULL != vol_table),
307 			"vol_table empty.", return -EINVAL);
308 
309 	vol_table->mask_low = 0;
310 	vol_table->phase_delay = 0;
311 	vol_table->count = dep_table->count;
312 
313 	for (i = 0; i < dep_table->count; i++) {
314 		vol_table->entries[i].value = dep_table->entries[i].mvdd;
315 		vol_table->entries[i].smio_low = 0;
316 	}
317 
318 	result = phm_trim_voltage_table(vol_table);
319 	PP_ASSERT_WITH_CODE((0 == result),
320 			"Failed to trim MVDD table.", return result);
321 
322 	return 0;
323 }
324 
phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table * vol_table,phm_ppt_v1_clock_voltage_dependency_table * dep_table)325 int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
326 		phm_ppt_v1_clock_voltage_dependency_table *dep_table)
327 {
328 	uint32_t i;
329 	int result;
330 
331 	PP_ASSERT_WITH_CODE((0 != dep_table->count),
332 			"Voltage Dependency Table empty.", return -EINVAL);
333 
334 	PP_ASSERT_WITH_CODE((NULL != vol_table),
335 			"vol_table empty.", return -EINVAL);
336 
337 	vol_table->mask_low = 0;
338 	vol_table->phase_delay = 0;
339 	vol_table->count = dep_table->count;
340 
341 	for (i = 0; i < dep_table->count; i++) {
342 		vol_table->entries[i].value = dep_table->entries[i].vddci;
343 		vol_table->entries[i].smio_low = 0;
344 	}
345 
346 	result = phm_trim_voltage_table(vol_table);
347 	PP_ASSERT_WITH_CODE((0 == result),
348 			"Failed to trim VDDCI table.", return result);
349 
350 	return 0;
351 }
352 
phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table * vol_table,phm_ppt_v1_voltage_lookup_table * lookup_table)353 int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
354 		phm_ppt_v1_voltage_lookup_table *lookup_table)
355 {
356 	int i = 0;
357 
358 	PP_ASSERT_WITH_CODE((0 != lookup_table->count),
359 			"Voltage Lookup Table empty.", return -EINVAL);
360 
361 	PP_ASSERT_WITH_CODE((NULL != vol_table),
362 			"vol_table empty.", return -EINVAL);
363 
364 	vol_table->mask_low = 0;
365 	vol_table->phase_delay = 0;
366 
367 	vol_table->count = lookup_table->count;
368 
369 	for (i = 0; i < vol_table->count; i++) {
370 		vol_table->entries[i].value = lookup_table->entries[i].us_vdd;
371 		vol_table->entries[i].smio_low = 0;
372 	}
373 
374 	return 0;
375 }
376 
phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps,struct pp_atomctrl_voltage_table * vol_table)377 void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps,
378 				struct pp_atomctrl_voltage_table *vol_table)
379 {
380 	unsigned int i, diff;
381 
382 	if (vol_table->count <= max_vol_steps)
383 		return;
384 
385 	diff = vol_table->count - max_vol_steps;
386 
387 	for (i = 0; i < max_vol_steps; i++)
388 		vol_table->entries[i] = vol_table->entries[i + diff];
389 
390 	vol_table->count = max_vol_steps;
391 
392 	return;
393 }
394 
phm_reset_single_dpm_table(void * table,uint32_t count,int max)395 int phm_reset_single_dpm_table(void *table,
396 				uint32_t count, int max)
397 {
398 	int i;
399 
400 	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
401 
402 	dpm_table->count = count > max ? max : count;
403 
404 	for (i = 0; i < dpm_table->count; i++)
405 		dpm_table->dpm_level[i].enabled = false;
406 
407 	return 0;
408 }
409 
phm_setup_pcie_table_entry(void * table,uint32_t index,uint32_t pcie_gen,uint32_t pcie_lanes)410 void phm_setup_pcie_table_entry(
411 	void *table,
412 	uint32_t index, uint32_t pcie_gen,
413 	uint32_t pcie_lanes)
414 {
415 	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
416 	dpm_table->dpm_level[index].value = pcie_gen;
417 	dpm_table->dpm_level[index].param1 = pcie_lanes;
418 	dpm_table->dpm_level[index].enabled = 1;
419 }
420 
phm_get_dpm_level_enable_mask_value(void * table)421 int32_t phm_get_dpm_level_enable_mask_value(void *table)
422 {
423 	int32_t i;
424 	int32_t mask = 0;
425 	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
426 
427 	for (i = dpm_table->count; i > 0; i--) {
428 		mask = mask << 1;
429 		if (dpm_table->dpm_level[i - 1].enabled)
430 			mask |= 0x1;
431 		else
432 			mask &= 0xFFFFFFFE;
433 	}
434 
435 	return mask;
436 }
437 
phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table * lookup_table,uint16_t voltage)438 uint8_t phm_get_voltage_index(
439 		struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage)
440 {
441 	uint8_t count = (uint8_t) (lookup_table->count);
442 	uint8_t i;
443 
444 	PP_ASSERT_WITH_CODE((NULL != lookup_table),
445 			"Lookup Table empty.", return 0);
446 	PP_ASSERT_WITH_CODE((0 != count),
447 			"Lookup Table empty.", return 0);
448 
449 	for (i = 0; i < lookup_table->count; i++) {
450 		/* find first voltage equal or bigger than requested */
451 		if (lookup_table->entries[i].us_vdd >= voltage)
452 			return i;
453 	}
454 	/* voltage is bigger than max voltage in the table */
455 	return i - 1;
456 }
457 
phm_get_voltage_id(pp_atomctrl_voltage_table * voltage_table,uint32_t voltage)458 uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table,
459 		uint32_t voltage)
460 {
461 	uint8_t count = (uint8_t) (voltage_table->count);
462 	uint8_t i = 0;
463 
464 	PP_ASSERT_WITH_CODE((NULL != voltage_table),
465 		"Voltage Table empty.", return 0;);
466 	PP_ASSERT_WITH_CODE((0 != count),
467 		"Voltage Table empty.", return 0;);
468 
469 	for (i = 0; i < count; i++) {
470 		/* find first voltage bigger than requested */
471 		if (voltage_table->entries[i].value >= voltage)
472 			return i;
473 	}
474 
475 	/* voltage is bigger than max voltage in the table */
476 	return i - 1;
477 }
478 
phm_find_closest_vddci(struct pp_atomctrl_voltage_table * vddci_table,uint16_t vddci)479 uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci)
480 {
481 	uint32_t  i;
482 
483 	for (i = 0; i < vddci_table->count; i++) {
484 		if (vddci_table->entries[i].value >= vddci)
485 			return vddci_table->entries[i].value;
486 	}
487 
488 	PP_ASSERT_WITH_CODE(false,
489 			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
490 			return vddci_table->entries[i-1].value);
491 }
492 
phm_find_boot_level(void * table,uint32_t value,uint32_t * boot_level)493 int phm_find_boot_level(void *table,
494 		uint32_t value, uint32_t *boot_level)
495 {
496 	int result = -EINVAL;
497 	uint32_t i;
498 	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
499 
500 	for (i = 0; i < dpm_table->count; i++) {
501 		if (value == dpm_table->dpm_level[i].value) {
502 			*boot_level = i;
503 			result = 0;
504 		}
505 	}
506 
507 	return result;
508 }
509 
phm_get_sclk_for_voltage_evv(struct pp_hwmgr * hwmgr,phm_ppt_v1_voltage_lookup_table * lookup_table,uint16_t virtual_voltage_id,int32_t * sclk)510 int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
511 	phm_ppt_v1_voltage_lookup_table *lookup_table,
512 	uint16_t virtual_voltage_id, int32_t *sclk)
513 {
514 	uint8_t entryId;
515 	uint8_t voltageId;
516 	struct phm_ppt_v1_information *table_info =
517 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
518 
519 	PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
520 
521 	/* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
522 	for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) {
523 		voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd;
524 		if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
525 			break;
526 	}
527 
528 	PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count,
529 			"Can't find requested voltage id in vdd_dep_on_sclk table!",
530 			return -EINVAL;
531 			);
532 
533 	*sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk;
534 
535 	return 0;
536 }
537 
538 /**
539  * Initialize Dynamic State Adjustment Rule Settings
540  *
541  * @param    hwmgr  the address of the powerplay hardware manager.
542  */
phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr * hwmgr)543 int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
544 {
545 	uint32_t table_size;
546 	struct phm_clock_voltage_dependency_table *table_clk_vlt;
547 	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
548 
549 	/* initialize vddc_dep_on_dal_pwrl table */
550 	table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
551 	table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
552 
553 	if (NULL == table_clk_vlt) {
554 		printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
555 		return -ENOMEM;
556 	} else {
557 		table_clk_vlt->count = 4;
558 		table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
559 		table_clk_vlt->entries[0].v = 0;
560 		table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
561 		table_clk_vlt->entries[1].v = 720;
562 		table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
563 		table_clk_vlt->entries[2].v = 810;
564 		table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
565 		table_clk_vlt->entries[3].v = 900;
566 		if (pptable_info != NULL)
567 			pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
568 		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
569 	}
570 
571 	return 0;
572 }
573 
phm_hwmgr_backend_fini(struct pp_hwmgr * hwmgr)574 int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
575 {
576 	if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) {
577 		kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
578 		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
579 	}
580 
581 	if (NULL != hwmgr->backend) {
582 		kfree(hwmgr->backend);
583 		hwmgr->backend = NULL;
584 	}
585 
586 	return 0;
587 }
588 
phm_get_lowest_enabled_level(struct pp_hwmgr * hwmgr,uint32_t mask)589 uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
590 {
591 	uint32_t level = 0;
592 
593 	while (0 == (mask & (1 << level)))
594 		level++;
595 
596 	return level;
597 }
598 
phm_apply_dal_min_voltage_request(struct pp_hwmgr * hwmgr)599 void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
600 {
601 	struct phm_ppt_v1_information *table_info =
602 			(struct phm_ppt_v1_information *)hwmgr->pptable;
603 	struct phm_clock_voltage_dependency_table *table =
604 				table_info->vddc_dep_on_dal_pwrl;
605 	struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
606 	enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
607 	uint32_t req_vddc = 0, req_volt, i;
608 
609 	if (!table || table->count <= 0
610 		|| dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
611 		|| dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
612 		return;
613 
614 	for (i = 0; i < table->count; i++) {
615 		if (dal_power_level == table->entries[i].clk) {
616 			req_vddc = table->entries[i].v;
617 			break;
618 		}
619 	}
620 
621 	vddc_table = table_info->vdd_dep_on_sclk;
622 	for (i = 0; i < vddc_table->count; i++) {
623 		if (req_vddc <= vddc_table->entries[i].vddc) {
624 			req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
625 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
626 					PPSMC_MSG_VddC_Request, req_volt);
627 			return;
628 		}
629 	}
630 	printk(KERN_ERR "DAL requested level can not"
631 			" found a available voltage in VDDC DPM Table \n");
632 }
633 
hwmgr_init_default_caps(struct pp_hwmgr * hwmgr)634 void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr)
635 {
636 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition);
637 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition);
638 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition);
639 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating);
640 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM);
641 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating);
642 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport);
643 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep);
644 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS);
645 	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating);
646 
647 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM);
648 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake);
649 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling);
650 
651 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
652 
653 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support);
654 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays);
655 
656 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress);
657 
658 	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM);
659 	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM);
660 
661 	if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) &&
662 		acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION))
663 		phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
664 
665 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
666 		PHM_PlatformCaps_DynamicPatchPowerState);
667 
668 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
669 		PHM_PlatformCaps_EnableSMU7ThermalManagement);
670 
671 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
672 			PHM_PlatformCaps_DynamicPowerManagement);
673 
674 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
675 					PHM_PlatformCaps_SMC);
676 
677 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
678 					PHM_PlatformCaps_DynamicUVDState);
679 
680 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
681 						PHM_PlatformCaps_FanSpeedInTableIsRPM);
682 
683 	return;
684 }
685 
hwmgr_set_user_specify_caps(struct pp_hwmgr * hwmgr)686 int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr)
687 {
688 	if (amdgpu_sclk_deep_sleep_en)
689 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
690 			PHM_PlatformCaps_SclkDeepSleep);
691 	else
692 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
693 			PHM_PlatformCaps_SclkDeepSleep);
694 
695 	if (amdgpu_powercontainment)
696 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
697 			    PHM_PlatformCaps_PowerContainment);
698 	else
699 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
700 			    PHM_PlatformCaps_PowerContainment);
701 
702 	hwmgr->feature_mask = amdgpu_pp_feature_mask;
703 
704 	return 0;
705 }
706 
phm_get_voltage_evv_on_sclk(struct pp_hwmgr * hwmgr,uint8_t voltage_type,uint32_t sclk,uint16_t id,uint16_t * voltage)707 int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
708 				uint32_t sclk, uint16_t id, uint16_t *voltage)
709 {
710 	uint32_t vol;
711 	int ret = 0;
712 
713 	if (hwmgr->chip_id < CHIP_TONGA) {
714 		ret = atomctrl_get_voltage_evv(hwmgr, id, voltage);
715 	} else if (hwmgr->chip_id < CHIP_POLARIS10) {
716 		ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage);
717 		if (*voltage >= 2000 || *voltage == 0)
718 			*voltage = 1150;
719 	} else {
720 		ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol);
721 		*voltage = (uint16_t)(vol/100);
722 	}
723 	return ret;
724 }
725 
polaris_set_asic_special_caps(struct pp_hwmgr * hwmgr)726 int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
727 {
728 	/* power tune caps Assume disabled */
729 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
730 						PHM_PlatformCaps_SQRamping);
731 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
732 						PHM_PlatformCaps_DBRamping);
733 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
734 						PHM_PlatformCaps_TDRamping);
735 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
736 						PHM_PlatformCaps_TCPRamping);
737 
738 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
739 							PHM_PlatformCaps_CAC);
740 
741 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
742 						PHM_PlatformCaps_RegulatorHot);
743 
744 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
745 					PHM_PlatformCaps_AutomaticDCTransition);
746 
747 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
748 				PHM_PlatformCaps_TablelessHardwareInterface);
749 
750 	if (hwmgr->chip_id == CHIP_POLARIS11)
751 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
752 					PHM_PlatformCaps_SPLLShutdownSupport);
753 	return 0;
754 }
755 
fiji_set_asic_special_caps(struct pp_hwmgr * hwmgr)756 int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr)
757 {
758 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
759 			PHM_PlatformCaps_SQRamping);
760 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
761 			PHM_PlatformCaps_DBRamping);
762 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
763 			PHM_PlatformCaps_TDRamping);
764 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
765 			PHM_PlatformCaps_TCPRamping);
766 
767 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
768 			PHM_PlatformCaps_TablelessHardwareInterface);
769 
770 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
771 			PHM_PlatformCaps_CAC);
772 	return 0;
773 }
774 
tonga_set_asic_special_caps(struct pp_hwmgr * hwmgr)775 int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr)
776 {
777 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
778 			PHM_PlatformCaps_SQRamping);
779 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
780 			PHM_PlatformCaps_DBRamping);
781 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
782 			PHM_PlatformCaps_TDRamping);
783 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
784 			PHM_PlatformCaps_TCPRamping);
785 
786 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
787 		      PHM_PlatformCaps_UVDPowerGating);
788 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
789 		      PHM_PlatformCaps_VCEPowerGating);
790 
791 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
792 			 PHM_PlatformCaps_TablelessHardwareInterface);
793 
794 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
795 			PHM_PlatformCaps_CAC);
796 
797 	return 0;
798 }
799 
topaz_set_asic_special_caps(struct pp_hwmgr * hwmgr)800 int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr)
801 {
802 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
803 			PHM_PlatformCaps_SQRamping);
804 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
805 			PHM_PlatformCaps_DBRamping);
806 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
807 			PHM_PlatformCaps_TDRamping);
808 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
809 			PHM_PlatformCaps_TCPRamping);
810 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
811 			 PHM_PlatformCaps_TablelessHardwareInterface);
812 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
813 			PHM_PlatformCaps_CAC);
814 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
815 		    PHM_PlatformCaps_EVV);
816 	return 0;
817 }
818