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