GNU Linux-libre 4.14.257-gnu1
[releases.git] / drivers / gpu / drm / amd / powerplay / hwmgr / hwmgr.c
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
24 #include "pp_debug.h"
25 #include <linux/delay.h>
26 #include <linux/kernel.h>
27 #include <linux/slab.h>
28 #include <linux/types.h>
29 #include <drm/amdgpu_drm.h>
30 #include "cgs_common.h"
31 #include "power_state.h"
32 #include "hwmgr.h"
33 #include "pppcielanes.h"
34 #include "ppatomctrl.h"
35 #include "ppsmc.h"
36 #include "pp_acpi.h"
37 #include "amd_acpi.h"
38
39 extern int cz_init_function_pointers(struct pp_hwmgr *hwmgr);
40
41 static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
42 static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr);
43 static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr);
44 static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr);
45 static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr);
46 static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr);
47
48 uint8_t convert_to_vid(uint16_t vddc)
49 {
50         return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25);
51 }
52
53 int hwmgr_early_init(struct pp_instance *handle)
54 {
55         struct pp_hwmgr *hwmgr;
56
57         if (handle == NULL)
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;
66         hwmgr->device = handle->device;
67         hwmgr->chip_family = handle->chip_family;
68         hwmgr->chip_id = handle->chip_id;
69         hwmgr->feature_mask = handle->feature_mask;
70         hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
71         hwmgr->power_source = PP_PowerSource_AC;
72         hwmgr->pp_table_version = PP_TABLE_V1;
73         hwmgr->dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
74         hwmgr_init_default_caps(hwmgr);
75         hwmgr_set_user_specify_caps(hwmgr);
76
77         switch (hwmgr->chip_family) {
78         case AMDGPU_FAMILY_CZ:
79                 cz_init_function_pointers(hwmgr);
80                 break;
81         case AMDGPU_FAMILY_VI:
82                 switch (hwmgr->chip_id) {
83                 case CHIP_TOPAZ:
84                         topaz_set_asic_special_caps(hwmgr);
85                         hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
86                                                 PP_ENABLE_GFX_CG_THRU_SMU);
87                         hwmgr->pp_table_version = PP_TABLE_V0;
88                         break;
89                 case CHIP_TONGA:
90                         tonga_set_asic_special_caps(hwmgr);
91                         hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK;
92                         break;
93                 case CHIP_FIJI:
94                         fiji_set_asic_special_caps(hwmgr);
95                         hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
96                                                 PP_ENABLE_GFX_CG_THRU_SMU);
97                         break;
98                 case CHIP_POLARIS11:
99                 case CHIP_POLARIS10:
100                 case CHIP_POLARIS12:
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_init_function_pointers(hwmgr);
108                 break;
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;
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;
127         default:
128                 return -EINVAL;
129         }
130
131         return 0;
132 }
133
134 static int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
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);
154         if (hwmgr->ps == NULL)
155                 return -ENOMEM;
156
157         hwmgr->request_ps = kzalloc(size, GFP_KERNEL);
158         if (hwmgr->request_ps == NULL) {
159                 kfree(hwmgr->ps);
160                 hwmgr->ps = NULL;
161                 return -ENOMEM;
162         }
163
164         hwmgr->current_ps = kzalloc(size, GFP_KERNEL);
165         if (hwmgr->current_ps == NULL) {
166                 kfree(hwmgr->request_ps);
167                 kfree(hwmgr->ps);
168                 hwmgr->request_ps = NULL;
169                 hwmgr->ps = NULL;
170                 return -ENOMEM;
171         }
172
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);
177
178                 if (state->classification.flags & PP_StateClassificationFlag_Boot) {
179                         hwmgr->boot_ps = state;
180                         memcpy(hwmgr->current_ps, state, size);
181                         memcpy(hwmgr->request_ps, state, size);
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;
188                 state = (struct pp_power_state *)((unsigned long)state + size);
189         }
190
191         return 0;
192 }
193
194 static 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
208 int 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;
222
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;
234         return 0;
235 err2:
236         if (hwmgr->hwmgr_func->backend_fini)
237                 hwmgr->hwmgr_func->backend_fini(hwmgr);
238 err1:
239         if (hwmgr->pptable_func->pptable_fini)
240                 hwmgr->pptable_func->pptable_fini(hwmgr);
241 err:
242         pr_err("amdgpu: powerplay initialization failed\n");
243         return ret;
244 }
245
246 int 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);
260 }
261
262
263 /**
264  * Returns once the part of the register indicated by the mask has
265  * reached the given value.
266  */
267 int 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) {
274                 pr_err("Invalid Hardware Manager!");
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
291
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  */
297 void 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) {
304                 pr_err("Invalid Hardware Manager!");
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
312
313
314 bool 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
319 bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
320 {
321         return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
322 }
323
324
325 int 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);
365         table = NULL;
366         return 0;
367 }
368
369 int 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
397 int 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
425 int 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
449 void 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
467 int 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
474         dpm_table->count = count > max ? max : count;
475
476         for (i = 0; i < dpm_table->count; i++)
477                 dpm_table->dpm_level[i].enabled = false;
478
479         return 0;
480 }
481
482 void 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
493 int32_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
510 uint8_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
530 uint8_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
551 uint16_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         pr_debug("vddci is larger than max value in vddci_table\n");
561         return vddci_table->entries[i-1].value;
562 }
563
564 int phm_find_boot_level(void *table,
565                 uint32_t value, uint32_t *boot_level)
566 {
567         int result = -EINVAL;
568         uint32_t i;
569         struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
570
571         for (i = 0; i < dpm_table->count; i++) {
572                 if (value == dpm_table->dpm_level[i].value) {
573                         *boot_level = i;
574                         result = 0;
575                 }
576         }
577
578         return result;
579 }
580
581 int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
582         phm_ppt_v1_voltage_lookup_table *lookup_table,
583         uint16_t virtual_voltage_id, int32_t *sclk)
584 {
585         uint8_t entry_id;
586         uint8_t voltage_id;
587         struct phm_ppt_v1_information *table_info =
588                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
589
590         PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
591
592         /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
593         for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) {
594                 voltage_id = table_info->vdd_dep_on_sclk->entries[entry_id].vddInd;
595                 if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id)
596                         break;
597         }
598
599         if (entry_id >= table_info->vdd_dep_on_sclk->count) {
600                 pr_debug("Can't find requested voltage id in vdd_dep_on_sclk table\n");
601                 return -EINVAL;
602         }
603
604         *sclk = table_info->vdd_dep_on_sclk->entries[entry_id].clk;
605
606         return 0;
607 }
608
609 /**
610  * Initialize Dynamic State Adjustment Rule Settings
611  *
612  * @param    hwmgr  the address of the powerplay hardware manager.
613  */
614 int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
615 {
616         uint32_t table_size;
617         struct phm_clock_voltage_dependency_table *table_clk_vlt;
618         struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
619
620         /* initialize vddc_dep_on_dal_pwrl table */
621         table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
622         table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
623
624         if (NULL == table_clk_vlt) {
625                 pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n");
626                 return -ENOMEM;
627         } else {
628                 table_clk_vlt->count = 4;
629                 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
630                 table_clk_vlt->entries[0].v = 0;
631                 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
632                 table_clk_vlt->entries[1].v = 720;
633                 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
634                 table_clk_vlt->entries[2].v = 810;
635                 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
636                 table_clk_vlt->entries[3].v = 900;
637                 if (pptable_info != NULL)
638                         pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
639                 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
640         }
641
642         return 0;
643 }
644
645 uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
646 {
647         uint32_t level = 0;
648
649         while (0 == (mask & (1 << level)))
650                 level++;
651
652         return level;
653 }
654
655 void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
656 {
657         struct phm_ppt_v1_information *table_info =
658                         (struct phm_ppt_v1_information *)hwmgr->pptable;
659         struct phm_clock_voltage_dependency_table *table =
660                                 table_info->vddc_dep_on_dal_pwrl;
661         struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
662         enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
663         uint32_t req_vddc = 0, req_volt, i;
664
665         if (!table || table->count <= 0
666                 || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
667                 || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
668                 return;
669
670         for (i = 0; i < table->count; i++) {
671                 if (dal_power_level == table->entries[i].clk) {
672                         req_vddc = table->entries[i].v;
673                         break;
674                 }
675         }
676
677         vddc_table = table_info->vdd_dep_on_sclk;
678         for (i = 0; i < vddc_table->count; i++) {
679                 if (req_vddc <= vddc_table->entries[i].vddc) {
680                         req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
681                         smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
682                                         PPSMC_MSG_VddC_Request, req_volt);
683                         return;
684                 }
685         }
686         pr_err("DAL requested level can not"
687                         " found a available voltage in VDDC DPM Table \n");
688 }
689
690 void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr)
691 {
692         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition);
693         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition);
694         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition);
695         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating);
696         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM);
697         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating);
698         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport);
699         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep);
700         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS);
701         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating);
702
703         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM);
704         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake);
705         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling);
706
707         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
708
709         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support);
710         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays);
711
712         phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress);
713
714         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM);
715         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM);
716
717         if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) &&
718                 acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION))
719                 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
720
721         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
722                 PHM_PlatformCaps_DynamicPatchPowerState);
723
724         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
725                 PHM_PlatformCaps_EnableSMU7ThermalManagement);
726
727         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
728                         PHM_PlatformCaps_DynamicPowerManagement);
729
730         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
731                                         PHM_PlatformCaps_SMC);
732
733         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
734                                         PHM_PlatformCaps_DynamicUVDState);
735
736         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
737                                                 PHM_PlatformCaps_FanSpeedInTableIsRPM);
738
739         return;
740 }
741
742 int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr)
743 {
744         if (hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK)
745                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
746                         PHM_PlatformCaps_SclkDeepSleep);
747         else
748                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
749                         PHM_PlatformCaps_SclkDeepSleep);
750
751         if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
752                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
753                             PHM_PlatformCaps_PowerContainment);
754                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
755                         PHM_PlatformCaps_CAC);
756         } else {
757                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
758                             PHM_PlatformCaps_PowerContainment);
759                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
760                         PHM_PlatformCaps_CAC);
761         }
762
763         return 0;
764 }
765
766 int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
767                                 uint32_t sclk, uint16_t id, uint16_t *voltage)
768 {
769         uint32_t vol;
770         int ret = 0;
771
772         if (hwmgr->chip_id < CHIP_TONGA) {
773                 ret = atomctrl_get_voltage_evv(hwmgr, id, voltage);
774         } else if (hwmgr->chip_id < CHIP_POLARIS10) {
775                 ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage);
776                 if (*voltage >= 2000 || *voltage == 0)
777                         *voltage = 1150;
778         } else {
779                 ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol);
780                 *voltage = (uint16_t)(vol/100);
781         }
782         return ret;
783 }
784
785 int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
786 {
787
788         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
789                                                 PHM_PlatformCaps_SQRamping);
790         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
791                                                 PHM_PlatformCaps_RegulatorHot);
792
793         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
794                                         PHM_PlatformCaps_AutomaticDCTransition);
795
796         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
797                                 PHM_PlatformCaps_TablelessHardwareInterface);
798
799
800         if (hwmgr->chip_id != CHIP_POLARIS10)
801                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
802                                         PHM_PlatformCaps_SPLLShutdownSupport);
803
804         if (hwmgr->chip_id != CHIP_POLARIS11) {
805                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
806                                                         PHM_PlatformCaps_DBRamping);
807                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
808                                                         PHM_PlatformCaps_TDRamping);
809                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
810                                                         PHM_PlatformCaps_TCPRamping);
811         }
812         return 0;
813 }
814
815 int fiji_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_set(hwmgr->platform_descriptor.platformCaps,
827                         PHM_PlatformCaps_TablelessHardwareInterface);
828
829         return 0;
830 }
831
832 int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr)
833 {
834         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
835                         PHM_PlatformCaps_SQRamping);
836         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
837                         PHM_PlatformCaps_DBRamping);
838         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
839                         PHM_PlatformCaps_TDRamping);
840         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
841                         PHM_PlatformCaps_TCPRamping);
842
843         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
844                       PHM_PlatformCaps_UVDPowerGating);
845         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
846                       PHM_PlatformCaps_VCEPowerGating);
847
848         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
849                          PHM_PlatformCaps_TablelessHardwareInterface);
850
851         return 0;
852 }
853
854 int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr)
855 {
856         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
857                         PHM_PlatformCaps_SQRamping);
858         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
859                         PHM_PlatformCaps_DBRamping);
860         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
861                         PHM_PlatformCaps_TDRamping);
862         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
863                         PHM_PlatformCaps_TCPRamping);
864         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
865                          PHM_PlatformCaps_TablelessHardwareInterface);
866         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
867                     PHM_PlatformCaps_EVV);
868         return 0;
869 }