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