]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drm/amd/powerplay: add new bit mask to ctrl clock stretch feature.
[mirror_ubuntu-focal-kernel.git] / drivers / gpu / drm / amd / powerplay / hwmgr / hwmgr.c
CommitLineData
3bace359
JZ
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>
bb06d7ef 27#include <drm/amdgpu_drm.h>
3bace359
JZ
28#include "cgs_common.h"
29#include "power_state.h"
30#include "hwmgr.h"
17c00a2f
RZ
31#include "pppcielanes.h"
32#include "pp_debug.h"
33#include "ppatomctrl.h"
8b41e7a0 34#include "ppsmc.h"
9597f403
RZ
35#include "pp_acpi.h"
36#include "amd_acpi.h"
8b41e7a0 37
17c00a2f 38extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
aabcb7c1 39
4be051ae 40static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
9597f403
RZ
41static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr);
42static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr);
b859c207 43static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr);
fb044ed9 44static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr);
ab4f06d3 45static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr);
af223dfa 46
41698abb
RZ
47uint8_t convert_to_vid(uint16_t vddc)
48{
49 return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25);
50}
51
3bace359
JZ
52int 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;
3bace359
JZ
68 hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
69 hwmgr->power_source = PP_PowerSource_AC;
b1c8e1e2 70 hwmgr->pp_table_version = PP_TABLE_V1;
af223dfa 71
9597f403
RZ
72 hwmgr_init_default_caps(hwmgr);
73 hwmgr_set_user_specify_caps(hwmgr);
3bace359
JZ
74
75 switch (hwmgr->chip_family) {
bb06d7ef 76 case AMDGPU_FAMILY_CZ:
bdecc20a
JZ
77 cz_hwmgr_init(hwmgr);
78 break;
bb06d7ef 79 case AMDGPU_FAMILY_VI:
c82baa28 80 switch (hwmgr->chip_id) {
025f8bfb 81 case CHIP_TOPAZ:
ab4f06d3
RZ
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;
025f8bfb 87 break;
c82baa28 88 case CHIP_TONGA:
fb044ed9
RZ
89 tonga_set_asic_special_caps(hwmgr);
90 hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
91 PP_VBI_TIME_SUPPORT_MASK);
c82baa28 92 break;
aabcb7c1 93 case CHIP_FIJI:
b859c207
RZ
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);
aabcb7c1 98 break;
2cc0c0b5
FC
99 case CHIP_POLARIS11:
100 case CHIP_POLARIS10:
4be051ae
RZ
101 polaris_set_asic_special_caps(hwmgr);
102 hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
b83c4ab9 103 break;
c82baa28 104 default:
105 return -EINVAL;
106 }
ab4f06d3 107 smu7_hwmgr_init(hwmgr);
c82baa28 108 break;
3bace359
JZ
109 default:
110 return -EINVAL;
111 }
112
3bace359
JZ
113 return 0;
114}
115
116int hwmgr_fini(struct pp_hwmgr *hwmgr)
117{
118 if (hwmgr == NULL || hwmgr->ps == NULL)
119 return -EINVAL;
120
61da601b 121 /* do hwmgr finish*/
4dcf9e6f
EH
122 kfree(hwmgr->hardcode_pp_table);
123
61da601b
ML
124 kfree(hwmgr->backend);
125
126 kfree(hwmgr->start_thermal_controller.function_list);
127
128 kfree(hwmgr->set_temperature_range.function_list);
129
3bace359 130 kfree(hwmgr->ps);
48fad3af
RZ
131 kfree(hwmgr->current_ps);
132 kfree(hwmgr->request_ps);
3bace359
JZ
133 kfree(hwmgr);
134 return 0;
135}
136
137int 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);
c15c8d70
RZ
157 if (hwmgr->ps == NULL)
158 return -ENOMEM;
159
48fad3af
RZ
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
3bace359
JZ
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);
17c00a2f 172
3bace359
JZ
173 if (state->classification.flags & PP_StateClassificationFlag_Boot) {
174 hwmgr->boot_ps = state;
48fad3af
RZ
175 memcpy(hwmgr->current_ps, state, size);
176 memcpy(hwmgr->request_ps, state, size);
3bace359
JZ
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;
09b7a986 183 state = (struct pp_power_state *)((unsigned long)state + size);
3bace359
JZ
184 }
185
48fad3af 186
3bace359
JZ
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 */
195int 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
3bace359 219
3bace359
JZ
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 */
225void 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
3bace359 240
28a18bab
RZ
241
242bool 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
247bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
248{
249 return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
250}
17c00a2f
RZ
251
252
253int 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
297int 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
325int 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
353int 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
377void 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
395int 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
c07aefc2 402 dpm_table->count = count > max ? max : count;
17c00a2f 403
c07aefc2 404 for (i = 0; i < dpm_table->count; i++)
17c00a2f
RZ
405 dpm_table->dpm_level[i].enabled = false;
406
407 return 0;
408}
409
410void 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
421int32_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
438uint8_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
8bea2527
RZ
458uint8_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
17c00a2f
RZ
479uint16_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!",
d2e31218 490 return vddci_table->entries[i-1].value);
17c00a2f
RZ
491}
492
493int 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
510int 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 */
543int 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);
5969a8c7 551 table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
17c00a2f
RZ
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;
aa0ef3cc
RZ
566 if (pptable_info != NULL)
567 pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
17c00a2f
RZ
568 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
569 }
570
571 return 0;
572}
573
574int 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
589uint32_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}
8b41e7a0
RZ
598
599void 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}
9597f403
RZ
633
634void 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
9597f403
RZ
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
9597f403
RZ
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
686int 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
026c8810
RZ
707int 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_POLARIS10) {
714 atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage);
715 if (*voltage >= 2000 || *voltage == 0)
716 *voltage = 1150;
717 } else {
718 ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol);
a2941d01 719 *voltage = (uint16_t)(vol/100);
026c8810
RZ
720 }
721 return ret;
722}
723
4be051ae
RZ
724int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
725{
726 /* power tune caps Assume disabled */
727 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
728 PHM_PlatformCaps_SQRamping);
729 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
730 PHM_PlatformCaps_DBRamping);
731 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
732 PHM_PlatformCaps_TDRamping);
733 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
734 PHM_PlatformCaps_TCPRamping);
735
736 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
737 PHM_PlatformCaps_CAC);
738
739 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
740 PHM_PlatformCaps_RegulatorHot);
741
742 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
743 PHM_PlatformCaps_AutomaticDCTransition);
744
745 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
746 PHM_PlatformCaps_TablelessHardwareInterface);
747
748 if (hwmgr->chip_id == CHIP_POLARIS11)
749 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
750 PHM_PlatformCaps_SPLLShutdownSupport);
751 return 0;
752}
753
b859c207
RZ
754int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr)
755{
756 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
757 PHM_PlatformCaps_SQRamping);
758 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
759 PHM_PlatformCaps_DBRamping);
760 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
761 PHM_PlatformCaps_TDRamping);
762 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
763 PHM_PlatformCaps_TCPRamping);
764
765 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
766 PHM_PlatformCaps_TablelessHardwareInterface);
767
768 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
769 PHM_PlatformCaps_CAC);
770 return 0;
771}
772
fb044ed9
RZ
773int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr)
774{
775 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
776 PHM_PlatformCaps_SQRamping);
777 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
778 PHM_PlatformCaps_DBRamping);
779 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
780 PHM_PlatformCaps_TDRamping);
781 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
782 PHM_PlatformCaps_TCPRamping);
783
784 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
785 PHM_PlatformCaps_UVDPowerGating);
786 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
787 PHM_PlatformCaps_VCEPowerGating);
788
789 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
790 PHM_PlatformCaps_TablelessHardwareInterface);
791
792 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
793 PHM_PlatformCaps_CAC);
794
795 return 0;
796}
ab4f06d3
RZ
797
798int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr)
799{
800 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
801 PHM_PlatformCaps_SQRamping);
802 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
803 PHM_PlatformCaps_DBRamping);
804 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
805 PHM_PlatformCaps_TDRamping);
806 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
807 PHM_PlatformCaps_TCPRamping);
808 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
809 PHM_PlatformCaps_TablelessHardwareInterface);
810 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
811 PHM_PlatformCaps_CAC);
812 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
813 PHM_PlatformCaps_EVV);
814 return 0;
815}