1 /* $NetBSD: amdgpu_processpptables.c,v 1.2 2021/12/18 23:45:26 riastradh Exp $ */
2
3 /*
4 * Copyright 2015 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25 #include <sys/cdefs.h>
26 __KERNEL_RCSID(0, "$NetBSD: amdgpu_processpptables.c,v 1.2 2021/12/18 23:45:26 riastradh Exp $");
27
28 #include "pp_debug.h"
29 #include <linux/types.h>
30 #include <linux/kernel.h>
31 #include <linux/slab.h>
32 #include <drm/amdgpu_drm.h>
33 #include "processpptables.h"
34 #include <atom-types.h>
35 #include <atombios.h>
36 #include "pptable.h"
37 #include "power_state.h"
38 #include "hwmgr.h"
39 #include "hardwaremanager.h"
40
41
42 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
43 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
44 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
45 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
46 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
47 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
48 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
49 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
50
51 #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
52
get_vce_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)53 static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
54 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
55 {
56 uint16_t vce_table_offset = 0;
57
58 if (le16_to_cpu(powerplay_table->usTableSize) >=
59 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
60 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
61 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
62
63 if (powerplay_table3->usExtendendedHeaderOffset > 0) {
64 const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
65 (const ATOM_PPLIB_EXTENDEDHEADER *)
66 (((unsigned long)powerplay_table3) +
67 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
68 if (le16_to_cpu(extended_header->usSize) >=
69 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
70 vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
71 }
72 }
73
74 return vce_table_offset;
75 }
76
get_vce_clock_info_array_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)77 static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,
78 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
79 {
80 uint16_t table_offset = get_vce_table_offset(hwmgr,
81 powerplay_table);
82
83 if (table_offset > 0)
84 return table_offset + 1;
85
86 return 0;
87 }
88
get_vce_clock_info_array_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)89 static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
90 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
91 {
92 uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
93 powerplay_table);
94 uint16_t table_size = 0;
95
96 if (table_offset > 0) {
97 const VCEClockInfoArray *p = (const VCEClockInfoArray *)
98 (((unsigned long) powerplay_table) + table_offset);
99 table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
100 }
101
102 return table_size;
103 }
104
get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)105 static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
106 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
107 {
108 uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
109 powerplay_table);
110
111 if (table_offset > 0)
112 return table_offset + get_vce_clock_info_array_size(hwmgr,
113 powerplay_table);
114
115 return 0;
116 }
117
get_vce_clock_voltage_limit_table_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)118 static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
119 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
120 {
121 uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
122 uint16_t table_size = 0;
123
124 if (table_offset > 0) {
125 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
126 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
127
128 table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
129 }
130 return table_size;
131 }
132
get_vce_state_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)133 static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
134 {
135 uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
136
137 if (table_offset > 0)
138 return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
139
140 return 0;
141 }
142
get_vce_state_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)143 static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
144 struct pp_hwmgr *hwmgr,
145 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
146 {
147 uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
148
149 if (table_offset > 0)
150 return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
151
152 return NULL;
153 }
154
get_uvd_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)155 static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
156 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
157 {
158 uint16_t uvd_table_offset = 0;
159
160 if (le16_to_cpu(powerplay_table->usTableSize) >=
161 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
162 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
163 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
164 if (powerplay_table3->usExtendendedHeaderOffset > 0) {
165 const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
166 (const ATOM_PPLIB_EXTENDEDHEADER *)
167 (((unsigned long)powerplay_table3) +
168 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
169 if (le16_to_cpu(extended_header->usSize) >=
170 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
171 uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
172 }
173 }
174 return uvd_table_offset;
175 }
176
get_uvd_clock_info_array_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)177 static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,
178 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
179 {
180 uint16_t table_offset = get_uvd_table_offset(hwmgr,
181 powerplay_table);
182
183 if (table_offset > 0)
184 return table_offset + 1;
185 return 0;
186 }
187
get_uvd_clock_info_array_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)188 static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
189 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
190 {
191 uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
192 powerplay_table);
193 uint16_t table_size = 0;
194
195 if (table_offset > 0) {
196 const UVDClockInfoArray *p = (const UVDClockInfoArray *)
197 (((unsigned long) powerplay_table)
198 + table_offset);
199 table_size = sizeof(UCHAR) +
200 p->ucNumEntries * sizeof(UVDClockInfo);
201 }
202
203 return table_size;
204 }
205
get_uvd_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)206 static uint16_t get_uvd_clock_voltage_limit_table_offset(
207 struct pp_hwmgr *hwmgr,
208 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
209 {
210 uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
211 powerplay_table);
212
213 if (table_offset > 0)
214 return table_offset +
215 get_uvd_clock_info_array_size(hwmgr, powerplay_table);
216
217 return 0;
218 }
219
get_samu_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)220 static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
221 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
222 {
223 uint16_t samu_table_offset = 0;
224
225 if (le16_to_cpu(powerplay_table->usTableSize) >=
226 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
227 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
228 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
229 if (powerplay_table3->usExtendendedHeaderOffset > 0) {
230 const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
231 (const ATOM_PPLIB_EXTENDEDHEADER *)
232 (((unsigned long)powerplay_table3) +
233 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
234 if (le16_to_cpu(extended_header->usSize) >=
235 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
236 samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
237 }
238 }
239
240 return samu_table_offset;
241 }
242
get_samu_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)243 static uint16_t get_samu_clock_voltage_limit_table_offset(
244 struct pp_hwmgr *hwmgr,
245 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
246 {
247 uint16_t table_offset = get_samu_table_offset(hwmgr,
248 powerplay_table);
249
250 if (table_offset > 0)
251 return table_offset + 1;
252
253 return 0;
254 }
255
get_acp_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)256 static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
257 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
258 {
259 uint16_t acp_table_offset = 0;
260
261 if (le16_to_cpu(powerplay_table->usTableSize) >=
262 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
263 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
264 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
265 if (powerplay_table3->usExtendendedHeaderOffset > 0) {
266 const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
267 (const ATOM_PPLIB_EXTENDEDHEADER *)
268 (((unsigned long)powerplay_table3) +
269 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
270 if (le16_to_cpu(pExtendedHeader->usSize) >=
271 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
272 acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
273 }
274 }
275
276 return acp_table_offset;
277 }
278
get_acp_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)279 static uint16_t get_acp_clock_voltage_limit_table_offset(
280 struct pp_hwmgr *hwmgr,
281 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
282 {
283 uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);
284
285 if (tableOffset > 0)
286 return tableOffset + 1;
287
288 return 0;
289 }
290
get_cacp_tdp_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)291 static uint16_t get_cacp_tdp_table_offset(
292 struct pp_hwmgr *hwmgr,
293 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
294 {
295 uint16_t cacTdpTableOffset = 0;
296
297 if (le16_to_cpu(powerplay_table->usTableSize) >=
298 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
299 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
300 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
301 if (powerplay_table3->usExtendendedHeaderOffset > 0) {
302 const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
303 (const ATOM_PPLIB_EXTENDEDHEADER *)
304 (((unsigned long)powerplay_table3) +
305 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
306 if (le16_to_cpu(pExtendedHeader->usSize) >=
307 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
308 cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
309 }
310 }
311
312 return cacTdpTableOffset;
313 }
314
get_cac_tdp_table(struct pp_hwmgr * hwmgr,struct phm_cac_tdp_table ** ptable,const ATOM_PowerTune_Table * table,uint16_t us_maximum_power_delivery_limit)315 static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,
316 struct phm_cac_tdp_table **ptable,
317 const ATOM_PowerTune_Table *table,
318 uint16_t us_maximum_power_delivery_limit)
319 {
320 unsigned long table_size;
321 struct phm_cac_tdp_table *tdp_table;
322
323 table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);
324
325 tdp_table = kzalloc(table_size, GFP_KERNEL);
326 if (NULL == tdp_table)
327 return -ENOMEM;
328
329 tdp_table->usTDP = le16_to_cpu(table->usTDP);
330 tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);
331 tdp_table->usTDC = le16_to_cpu(table->usTDC);
332 tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);
333 tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);
334 tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);
335 tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);
336 tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;
337
338 *ptable = tdp_table;
339
340 return 0;
341 }
342
get_sclk_vdd_gfx_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)343 static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
344 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
345 {
346 uint16_t sclk_vdd_gfx_table_offset = 0;
347
348 if (le16_to_cpu(powerplay_table->usTableSize) >=
349 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
350 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
351 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
352 if (powerplay_table3->usExtendendedHeaderOffset > 0) {
353 const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
354 (const ATOM_PPLIB_EXTENDEDHEADER *)
355 (((unsigned long)powerplay_table3) +
356 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
357 if (le16_to_cpu(pExtendedHeader->usSize) >=
358 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
359 sclk_vdd_gfx_table_offset =
360 le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
361 }
362 }
363
364 return sclk_vdd_gfx_table_offset;
365 }
366
get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)367 static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
368 struct pp_hwmgr *hwmgr,
369 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
370 {
371 uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);
372
373 if (tableOffset > 0)
374 return tableOffset;
375
376 return 0;
377 }
378
379
get_clock_voltage_dependency_table(struct pp_hwmgr * hwmgr,struct phm_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_Clock_Voltage_Dependency_Table * table)380 static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
381 struct phm_clock_voltage_dependency_table **ptable,
382 const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)
383 {
384
385 unsigned long table_size, i;
386 struct phm_clock_voltage_dependency_table *dep_table;
387
388 table_size = sizeof(unsigned long) +
389 sizeof(struct phm_clock_voltage_dependency_table)
390 * table->ucNumEntries;
391
392 dep_table = kzalloc(table_size, GFP_KERNEL);
393 if (NULL == dep_table)
394 return -ENOMEM;
395
396 dep_table->count = (unsigned long)table->ucNumEntries;
397
398 for (i = 0; i < dep_table->count; i++) {
399 dep_table->entries[i].clk =
400 ((unsigned long)table->entries[i].ucClockHigh << 16) |
401 le16_to_cpu(table->entries[i].usClockLow);
402 dep_table->entries[i].v =
403 (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
404 }
405
406 *ptable = dep_table;
407
408 return 0;
409 }
410
get_valid_clk(struct pp_hwmgr * hwmgr,struct phm_clock_array ** ptable,const struct phm_clock_voltage_dependency_table * table)411 static int get_valid_clk(struct pp_hwmgr *hwmgr,
412 struct phm_clock_array **ptable,
413 const struct phm_clock_voltage_dependency_table *table)
414 {
415 unsigned long table_size, i;
416 struct phm_clock_array *clock_table;
417
418 table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count;
419 clock_table = kzalloc(table_size, GFP_KERNEL);
420 if (NULL == clock_table)
421 return -ENOMEM;
422
423 clock_table->count = (unsigned long)table->count;
424
425 for (i = 0; i < clock_table->count; i++)
426 clock_table->values[i] = (unsigned long)table->entries[i].clk;
427
428 *ptable = clock_table;
429
430 return 0;
431 }
432
get_clock_voltage_limit(struct pp_hwmgr * hwmgr,struct phm_clock_and_voltage_limits * limits,const ATOM_PPLIB_Clock_Voltage_Limit_Table * table)433 static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
434 struct phm_clock_and_voltage_limits *limits,
435 const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
436 {
437 limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
438 le16_to_cpu(table->entries[0].usSclkLow);
439 limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
440 le16_to_cpu(table->entries[0].usMclkLow);
441 limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
442 limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
443
444 return 0;
445 }
446
447
set_hw_cap(struct pp_hwmgr * hwmgr,bool enable,enum phm_platform_caps cap)448 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
449 enum phm_platform_caps cap)
450 {
451 if (enable)
452 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
453 else
454 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
455 }
456
set_platform_caps(struct pp_hwmgr * hwmgr,unsigned long powerplay_caps)457 static int set_platform_caps(struct pp_hwmgr *hwmgr,
458 unsigned long powerplay_caps)
459 {
460 set_hw_cap(
461 hwmgr,
462 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
463 PHM_PlatformCaps_PowerPlaySupport
464 );
465
466 set_hw_cap(
467 hwmgr,
468 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
469 PHM_PlatformCaps_BiosPowerSourceControl
470 );
471
472 set_hw_cap(
473 hwmgr,
474 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
475 PHM_PlatformCaps_EnableASPML0s
476 );
477
478 set_hw_cap(
479 hwmgr,
480 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
481 PHM_PlatformCaps_EnableASPML1
482 );
483
484 set_hw_cap(
485 hwmgr,
486 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
487 PHM_PlatformCaps_EnableBackbias
488 );
489
490 set_hw_cap(
491 hwmgr,
492 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
493 PHM_PlatformCaps_AutomaticDCTransition
494 );
495
496 set_hw_cap(
497 hwmgr,
498 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
499 PHM_PlatformCaps_GeminiPrimary
500 );
501
502 set_hw_cap(
503 hwmgr,
504 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
505 PHM_PlatformCaps_StepVddc
506 );
507
508 set_hw_cap(
509 hwmgr,
510 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
511 PHM_PlatformCaps_EnableVoltageControl
512 );
513
514 set_hw_cap(
515 hwmgr,
516 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
517 PHM_PlatformCaps_EnableSideportControl
518 );
519
520 set_hw_cap(
521 hwmgr,
522 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
523 PHM_PlatformCaps_TurnOffPll_ASPML1
524 );
525
526 set_hw_cap(
527 hwmgr,
528 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
529 PHM_PlatformCaps_EnableHTLinkControl
530 );
531
532 set_hw_cap(
533 hwmgr,
534 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
535 PHM_PlatformCaps_EnableMVDDControl
536 );
537
538 set_hw_cap(
539 hwmgr,
540 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
541 PHM_PlatformCaps_ControlVDDCI
542 );
543
544 set_hw_cap(
545 hwmgr,
546 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
547 PHM_PlatformCaps_RegulatorHot
548 );
549
550 set_hw_cap(
551 hwmgr,
552 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
553 PHM_PlatformCaps_BootStateOnAlert
554 );
555
556 set_hw_cap(
557 hwmgr,
558 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
559 PHM_PlatformCaps_DontWaitForVBlankOnAlert
560 );
561
562 set_hw_cap(
563 hwmgr,
564 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
565 PHM_PlatformCaps_BACO
566 );
567
568 set_hw_cap(
569 hwmgr,
570 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
571 PHM_PlatformCaps_NewCACVoltage
572 );
573
574 set_hw_cap(
575 hwmgr,
576 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
577 PHM_PlatformCaps_RevertGPIO5Polarity
578 );
579
580 set_hw_cap(
581 hwmgr,
582 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
583 PHM_PlatformCaps_Thermal2GPIO17
584 );
585
586 set_hw_cap(
587 hwmgr,
588 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
589 PHM_PlatformCaps_VRHotGPIOConfigurable
590 );
591
592 set_hw_cap(
593 hwmgr,
594 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
595 PHM_PlatformCaps_TempInversion
596 );
597
598 set_hw_cap(
599 hwmgr,
600 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
601 PHM_PlatformCaps_EVV
602 );
603
604 set_hw_cap(
605 hwmgr,
606 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
607 PHM_PlatformCaps_CombinePCCWithThermalSignal
608 );
609
610 set_hw_cap(
611 hwmgr,
612 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
613 PHM_PlatformCaps_LoadPostProductionFirmware
614 );
615
616 set_hw_cap(
617 hwmgr,
618 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
619 PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
620 );
621
622 return 0;
623 }
624
make_classification_flags(struct pp_hwmgr * hwmgr,USHORT classification,USHORT classification2)625 static PP_StateClassificationFlags make_classification_flags(
626 struct pp_hwmgr *hwmgr,
627 USHORT classification,
628 USHORT classification2)
629 {
630 PP_StateClassificationFlags result = 0;
631
632 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
633 result |= PP_StateClassificationFlag_Boot;
634
635 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
636 result |= PP_StateClassificationFlag_Thermal;
637
638 if (classification &
639 ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
640 result |= PP_StateClassificationFlag_LimitedPowerSource;
641
642 if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
643 result |= PP_StateClassificationFlag_Rest;
644
645 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
646 result |= PP_StateClassificationFlag_Forced;
647
648 if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
649 result |= PP_StateClassificationFlag_3DPerformance;
650
651
652 if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
653 result |= PP_StateClassificationFlag_ACOverdriveTemplate;
654
655 if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
656 result |= PP_StateClassificationFlag_Uvd;
657
658 if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
659 result |= PP_StateClassificationFlag_UvdHD;
660
661 if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
662 result |= PP_StateClassificationFlag_UvdSD;
663
664 if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
665 result |= PP_StateClassificationFlag_HD2;
666
667 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
668 result |= PP_StateClassificationFlag_ACPI;
669
670 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
671 result |= PP_StateClassificationFlag_LimitedPowerSource_2;
672
673
674 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
675 result |= PP_StateClassificationFlag_ULV;
676
677 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
678 result |= PP_StateClassificationFlag_UvdMVC;
679
680 return result;
681 }
682
init_non_clock_fields(struct pp_hwmgr * hwmgr,struct pp_power_state * ps,uint8_t version,const ATOM_PPLIB_NONCLOCK_INFO * pnon_clock_info)683 static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
684 struct pp_power_state *ps,
685 uint8_t version,
686 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
687 unsigned long rrr_index;
688 unsigned long tmp;
689
690 ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
691 ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
692 ps->classification.flags = make_classification_flags(hwmgr,
693 le16_to_cpu(pnon_clock_info->usClassification),
694 le16_to_cpu(pnon_clock_info->usClassification2));
695
696 ps->classification.temporary_state = false;
697 ps->classification.to_be_deleted = false;
698 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
699 ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
700
701 ps->validation.singleDisplayOnly = (0 != tmp);
702
703 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
704 ATOM_PPLIB_DISALLOW_ON_DC;
705
706 ps->validation.disallowOnDC = (0 != tmp);
707
708 ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
709 ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
710 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
711
712 ps->pcie.lanes = 0;
713
714 ps->display.disableFrameModulation = false;
715
716 rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
717 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
718 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
719
720 if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
721 static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
722 { 0, 50, 0 };
723
724 ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
725 ps->display.explicitRefreshrate = look_up[rrr_index];
726 ps->display.limitRefreshrate = true;
727
728 if (ps->display.explicitRefreshrate == 0)
729 ps->display.limitRefreshrate = false;
730 } else
731 ps->display.limitRefreshrate = false;
732
733 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
734 ATOM_PPLIB_ENABLE_VARIBRIGHT;
735
736 ps->display.enableVariBright = (0 != tmp);
737
738 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
739 ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
740
741 ps->memory.dllOff = (0 != tmp);
742
743 ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
744 ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
745
746 ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
747 pnon_clock_info->ucMinTemperature;
748
749 ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
750 pnon_clock_info->ucMaxTemperature;
751
752 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
753 ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
754
755 ps->software.disableLoadBalancing = tmp;
756
757 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
758 ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
759
760 ps->software.enableSleepForTimestamps = (0 != tmp);
761
762 ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
763
764 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
765 ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
766 ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
767 } else {
768 ps->uvd_clocks.VCLK = 0;
769 ps->uvd_clocks.DCLK = 0;
770 }
771
772 return 0;
773 }
774
size_of_entry_v2(ULONG num_dpm_levels)775 static ULONG size_of_entry_v2(ULONG num_dpm_levels)
776 {
777 return (sizeof(UCHAR) + sizeof(UCHAR) +
778 (num_dpm_levels * sizeof(UCHAR)));
779 }
780
get_state_entry_v2(const StateArray * pstate_arrays,ULONG entry_index)781 static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
782 const StateArray * pstate_arrays,
783 ULONG entry_index)
784 {
785 ULONG i;
786 const ATOM_PPLIB_STATE_V2 *pstate;
787
788 pstate = pstate_arrays->states;
789 if (entry_index <= pstate_arrays->ucNumEntries) {
790 for (i = 0; i < entry_index; i++)
791 pstate = (ATOM_PPLIB_STATE_V2 *)(
792 (unsigned long)pstate +
793 size_of_entry_v2(pstate->ucNumDPMLevels));
794 }
795 return pstate;
796 }
797
798 static const unsigned char soft_dummy_pp_table[] = {
799 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
801 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
804 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
805 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
810 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
811 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
812 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
813 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
814 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
815 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
816 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
817 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
818 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
819 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
820 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
821 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
822 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
823 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
824 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
825 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
826 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
827 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
828 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
829 0x00
830 };
831
get_powerplay_table(struct pp_hwmgr * hwmgr)832 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
833 struct pp_hwmgr *hwmgr)
834 {
835 const void *table_addr = hwmgr->soft_pp_table;
836 uint8_t frev, crev;
837 uint16_t size;
838
839 if (!table_addr) {
840 if (hwmgr->chip_id == CHIP_RAVEN) {
841 table_addr = &soft_dummy_pp_table[0];
842 hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
843 hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
844 } else {
845 table_addr = smu_atom_get_data_table(hwmgr->adev,
846 GetIndexIntoMasterTable(DATA, PowerPlayInfo),
847 &size, &frev, &crev);
848 hwmgr->soft_pp_table = table_addr;
849 hwmgr->soft_pp_table_size = size;
850 }
851 }
852
853 return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
854 }
855
pp_tables_get_response_times(struct pp_hwmgr * hwmgr,uint32_t * vol_rep_time,uint32_t * bb_rep_time)856 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
857 uint32_t *vol_rep_time, uint32_t *bb_rep_time)
858 {
859 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
860
861 PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
862 "Missing PowerPlay Table!", return -EINVAL);
863
864 *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
865 *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
866
867 return 0;
868 }
869
pp_tables_get_num_of_entries(struct pp_hwmgr * hwmgr,unsigned long * num_of_entries)870 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
871 unsigned long *num_of_entries)
872 {
873 const StateArray *pstate_arrays;
874 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
875
876 if (powerplay_table == NULL)
877 return -1;
878
879 if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
880 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
881 le16_to_cpu(powerplay_table->usStateArrayOffset));
882
883 *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
884 } else
885 *num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
886
887 return 0;
888 }
889
pp_tables_get_entry(struct pp_hwmgr * hwmgr,unsigned long entry_index,struct pp_power_state * ps,pp_tables_hw_clock_info_callback func)890 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
891 unsigned long entry_index,
892 struct pp_power_state *ps,
893 pp_tables_hw_clock_info_callback func)
894 {
895 int i;
896 const StateArray *pstate_arrays;
897 const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
898 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
899 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
900 int result = 0;
901 int res = 0;
902
903 const ClockInfoArray *pclock_arrays;
904
905 const NonClockInfoArray *pnon_clock_arrays;
906
907 const ATOM_PPLIB_STATE *pstate_entry;
908
909 if (powerplay_table == NULL)
910 return -1;
911
912 ps->classification.bios_index = entry_index;
913
914 if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
915 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
916 le16_to_cpu(powerplay_table->usStateArrayOffset));
917
918 if (entry_index > pstate_arrays->ucNumEntries)
919 return -1;
920
921 pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
922 pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
923 le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
924
925 pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
926 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
927
928 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
929 (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
930
931 result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
932
933 for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
934 const void *pclock_info = (const void *)(
935 (unsigned long)(pclock_arrays->clockInfo) +
936 (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
937 res = func(hwmgr, &ps->hardware, i, pclock_info);
938 if ((0 == result) && (0 != res))
939 result = res;
940 }
941 } else {
942 if (entry_index > powerplay_table->ucNumStates)
943 return -1;
944
945 pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
946 le16_to_cpu(powerplay_table->usStateArrayOffset) +
947 entry_index * powerplay_table->ucStateEntrySize);
948
949 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
950 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
951 pstate_entry->ucNonClockStateIndex *
952 powerplay_table->ucNonClockSize);
953
954 result = init_non_clock_fields(hwmgr, ps,
955 powerplay_table->ucNonClockSize,
956 pnon_clock_info);
957
958 for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
959 const void *pclock_info = (const void *)((unsigned long)powerplay_table +
960 le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
961 pstate_entry->ucClockStateIndices[i] *
962 powerplay_table->ucClockInfoSize);
963
964 int res = func(hwmgr, &ps->hardware, i, pclock_info);
965
966 if ((0 == result) && (0 != res))
967 result = res;
968 }
969 }
970
971 if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
972 if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
973 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
974 }
975
976 return result;
977 }
978
init_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)979 static int init_powerplay_tables(
980 struct pp_hwmgr *hwmgr,
981 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
982 )
983 {
984 return 0;
985 }
986
987
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)988 static int init_thermal_controller(
989 struct pp_hwmgr *hwmgr,
990 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
991 {
992 return 0;
993 }
994
init_overdrive_limits_V1_4(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V1_4 * fw_info)995 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
996 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
997 const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
998 {
999 hwmgr->platform_descriptor.overdriveLimit.engineClock =
1000 le32_to_cpu(fw_info->ulASICMaxEngineClock);
1001
1002 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1003 le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1004
1005 hwmgr->platform_descriptor.maxOverdriveVDDC =
1006 le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1007
1008 hwmgr->platform_descriptor.minOverdriveVDDC =
1009 le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1010
1011 hwmgr->platform_descriptor.maxOverdriveVDDC =
1012 le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1013
1014 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1015 return 0;
1016 }
1017
init_overdrive_limits_V2_1(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V2_1 * fw_info)1018 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1019 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1020 const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1021 {
1022 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1023 const ATOM_PPLIB_EXTENDEDHEADER *header;
1024
1025 if (le16_to_cpu(powerplay_table->usTableSize) <
1026 sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1027 return 0;
1028
1029 powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1030
1031 if (0 == powerplay_table3->usExtendendedHeaderOffset)
1032 return 0;
1033
1034 header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1035 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1036
1037 hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1038 hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1039
1040
1041 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1042 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1043 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1044
1045 return 0;
1046 }
1047
init_overdrive_limits(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1048 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1049 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1050 {
1051 int result = 0;
1052 uint8_t frev, crev;
1053 uint16_t size;
1054
1055 const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1056
1057 hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1058 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1059 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1060 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1061 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1062
1063 if (hwmgr->chip_id == CHIP_RAVEN)
1064 return 0;
1065
1066 /* We assume here that fw_info is unchanged if this call fails.*/
1067 fw_info = smu_atom_get_data_table(hwmgr->adev,
1068 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1069 &size, &frev, &crev);
1070
1071 if ((fw_info->ucTableFormatRevision == 1)
1072 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1073 result = init_overdrive_limits_V1_4(hwmgr,
1074 powerplay_table,
1075 (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1076
1077 else if ((fw_info->ucTableFormatRevision == 2)
1078 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1079 result = init_overdrive_limits_V2_1(hwmgr,
1080 powerplay_table,
1081 (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1082
1083 return result;
1084 }
1085
get_uvd_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_uvd_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table * table,const UVDClockInfoArray * array)1086 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1087 struct phm_uvd_clock_voltage_dependency_table **ptable,
1088 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1089 const UVDClockInfoArray *array)
1090 {
1091 unsigned long table_size, i;
1092 struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1093
1094 table_size = sizeof(unsigned long) +
1095 sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1096 table->numEntries;
1097
1098 uvd_table = kzalloc(table_size, GFP_KERNEL);
1099 if (NULL == uvd_table)
1100 return -ENOMEM;
1101
1102 uvd_table->count = table->numEntries;
1103
1104 for (i = 0; i < table->numEntries; i++) {
1105 const UVDClockInfo *entry =
1106 &array->entries[table->entries[i].ucUVDClockInfoIndex];
1107 uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1108 uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1109 | le16_to_cpu(entry->usVClkLow);
1110 uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1111 | le16_to_cpu(entry->usDClkLow);
1112 }
1113
1114 *ptable = uvd_table;
1115
1116 return 0;
1117 }
1118
get_vce_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_vce_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table * table,const VCEClockInfoArray * array)1119 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1120 struct phm_vce_clock_voltage_dependency_table **ptable,
1121 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1122 const VCEClockInfoArray *array)
1123 {
1124 unsigned long table_size, i;
1125 struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1126
1127 table_size = sizeof(unsigned long) +
1128 sizeof(struct phm_vce_clock_voltage_dependency_table)
1129 * table->numEntries;
1130
1131 vce_table = kzalloc(table_size, GFP_KERNEL);
1132 if (NULL == vce_table)
1133 return -ENOMEM;
1134
1135 vce_table->count = table->numEntries;
1136 for (i = 0; i < table->numEntries; i++) {
1137 const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1138
1139 vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1140 vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1141 | le16_to_cpu(entry->usEVClkLow);
1142 vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1143 | le16_to_cpu(entry->usECClkLow);
1144 }
1145
1146 *ptable = vce_table;
1147
1148 return 0;
1149 }
1150
get_samu_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_samu_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_SAMClk_Voltage_Limit_Table * table)1151 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1152 struct phm_samu_clock_voltage_dependency_table **ptable,
1153 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1154 {
1155 unsigned long table_size, i;
1156 struct phm_samu_clock_voltage_dependency_table *samu_table;
1157
1158 table_size = sizeof(unsigned long) +
1159 sizeof(struct phm_samu_clock_voltage_dependency_table) *
1160 table->numEntries;
1161
1162 samu_table = kzalloc(table_size, GFP_KERNEL);
1163 if (NULL == samu_table)
1164 return -ENOMEM;
1165
1166 samu_table->count = table->numEntries;
1167
1168 for (i = 0; i < table->numEntries; i++) {
1169 samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1170 samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1171 | le16_to_cpu(table->entries[i].usSAMClockLow);
1172 }
1173
1174 *ptable = samu_table;
1175
1176 return 0;
1177 }
1178
get_acp_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_acp_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_ACPClk_Voltage_Limit_Table * table)1179 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1180 struct phm_acp_clock_voltage_dependency_table **ptable,
1181 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1182 {
1183 unsigned table_size, i;
1184 struct phm_acp_clock_voltage_dependency_table *acp_table;
1185
1186 table_size = sizeof(unsigned long) +
1187 sizeof(struct phm_acp_clock_voltage_dependency_table) *
1188 table->numEntries;
1189
1190 acp_table = kzalloc(table_size, GFP_KERNEL);
1191 if (NULL == acp_table)
1192 return -ENOMEM;
1193
1194 acp_table->count = (unsigned long)table->numEntries;
1195
1196 for (i = 0; i < table->numEntries; i++) {
1197 acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1198 acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1199 | le16_to_cpu(table->entries[i].usACPClockLow);
1200 }
1201
1202 *ptable = acp_table;
1203
1204 return 0;
1205 }
1206
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1207 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1208 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1209 {
1210 ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1211 ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1212 int result = 0;
1213
1214 uint16_t vce_clock_info_array_offset;
1215 uint16_t uvd_clock_info_array_offset;
1216 uint16_t table_offset;
1217
1218 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1219 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1220 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1221 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1222 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1223 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1224 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1225 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1226 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1227 hwmgr->dyn_state.ppm_parameter_table = NULL;
1228 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1229
1230 vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1231 hwmgr, powerplay_table);
1232 table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1233 powerplay_table);
1234 if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1235 const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1236 (((unsigned long) powerplay_table) +
1237 vce_clock_info_array_offset);
1238 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1239 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1240 (((unsigned long) powerplay_table) + table_offset);
1241 result = get_vce_clock_voltage_limit_table(hwmgr,
1242 &hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1243 table, array);
1244 }
1245
1246 uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1247 table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1248
1249 if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1250 const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1251 (((unsigned long) powerplay_table) +
1252 uvd_clock_info_array_offset);
1253 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1254 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1255 (((unsigned long) powerplay_table) + table_offset);
1256 result = get_uvd_clock_voltage_limit_table(hwmgr,
1257 &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1258 }
1259
1260 table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1261 powerplay_table);
1262
1263 if (table_offset > 0) {
1264 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1265 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1266 (((unsigned long) powerplay_table) + table_offset);
1267 result = get_samu_clock_voltage_limit_table(hwmgr,
1268 &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1269 }
1270
1271 table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1272 powerplay_table);
1273
1274 if (table_offset > 0) {
1275 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1276 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1277 (((unsigned long) powerplay_table) + table_offset);
1278 result = get_acp_clock_voltage_limit_table(hwmgr,
1279 &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1280 }
1281
1282 table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1283 if (table_offset > 0) {
1284 UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1285
1286 if (rev_id > 0) {
1287 const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1288 (const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1289 (((unsigned long) powerplay_table) + table_offset);
1290 result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1291 &tune_table->power_tune_table,
1292 le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1293 hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1294 le16_to_cpu(tune_table->usTjMax);
1295 } else {
1296 const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1297 (const ATOM_PPLIB_POWERTUNE_Table *)
1298 (((unsigned long) powerplay_table) + table_offset);
1299 result = get_cac_tdp_table(hwmgr,
1300 &hwmgr->dyn_state.cac_dtp_table,
1301 &tune_table->power_tune_table, 255);
1302 }
1303 }
1304
1305 if (le16_to_cpu(powerplay_table->usTableSize) >=
1306 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1307 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1308 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1309 if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1310 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1311 (((unsigned long) powerplay_table4) +
1312 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1313 result = get_clock_voltage_dependency_table(hwmgr,
1314 &hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1315 }
1316
1317 if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1318 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1319 (((unsigned long) powerplay_table4) +
1320 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1321 result = get_clock_voltage_dependency_table(hwmgr,
1322 &hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1323 }
1324
1325 if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1326 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1327 (((unsigned long) powerplay_table4) +
1328 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1329 result = get_clock_voltage_dependency_table(hwmgr,
1330 &hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1331 }
1332
1333 if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1334 limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1335 (((unsigned long) powerplay_table4) +
1336 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1337 result = get_clock_voltage_limit(hwmgr,
1338 &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1339 }
1340
1341 if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1342 (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1343 result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1344 hwmgr->dyn_state.vddc_dependency_on_mclk);
1345
1346 if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1347 (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1348 result = get_valid_clk(hwmgr,
1349 &hwmgr->dyn_state.valid_sclk_values,
1350 hwmgr->dyn_state.vddc_dependency_on_sclk);
1351
1352 if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1353 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1354 (((unsigned long) powerplay_table4) +
1355 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1356 result = get_clock_voltage_dependency_table(hwmgr,
1357 &hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1358 }
1359 }
1360
1361 table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1362 powerplay_table);
1363
1364 if (table_offset > 0) {
1365 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1366 (((unsigned long) powerplay_table) + table_offset);
1367 result = get_clock_voltage_dependency_table(hwmgr,
1368 &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1369 }
1370
1371 return result;
1372 }
1373
get_cac_leakage_table(struct pp_hwmgr * hwmgr,struct phm_cac_leakage_table ** ptable,const ATOM_PPLIB_CAC_Leakage_Table * table)1374 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1375 struct phm_cac_leakage_table **ptable,
1376 const ATOM_PPLIB_CAC_Leakage_Table *table)
1377 {
1378 struct phm_cac_leakage_table *cac_leakage_table;
1379 unsigned long table_size, i;
1380
1381 if (hwmgr == NULL || table == NULL || ptable == NULL)
1382 return -EINVAL;
1383
1384 table_size = sizeof(ULONG) +
1385 (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1386
1387 cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1388
1389 if (cac_leakage_table == NULL)
1390 return -ENOMEM;
1391
1392 cac_leakage_table->count = (ULONG)table->ucNumEntries;
1393
1394 for (i = 0; i < cac_leakage_table->count; i++) {
1395 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1396 PHM_PlatformCaps_EVV)) {
1397 cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1398 cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1399 cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1400 } else {
1401 cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc);
1402 cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1403 }
1404 }
1405
1406 *ptable = cac_leakage_table;
1407
1408 return 0;
1409 }
1410
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_PPLIB_PPM_Table * atom_ppm_table)1411 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1412 ATOM_PPLIB_PPM_Table *atom_ppm_table)
1413 {
1414 struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1415
1416 if (NULL == ptr)
1417 return -ENOMEM;
1418
1419 ptr->ppm_design = atom_ppm_table->ucPpmDesign;
1420 ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1421 ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1422 ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1423 ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1424 ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1425 ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP);
1426 ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1427 ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1428 ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax);
1429 hwmgr->dyn_state.ppm_parameter_table = ptr;
1430
1431 return 0;
1432 }
1433
init_dpm2_parameters(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1434 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1435 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1436 {
1437 int result = 0;
1438
1439 if (le16_to_cpu(powerplay_table->usTableSize) >=
1440 sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1441 const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1442 (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1443 const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1444 (const ATOM_PPLIB_POWERPLAYTABLE4 *)
1445 (&ptable5->basicTable4);
1446 const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1447 (const ATOM_PPLIB_POWERPLAYTABLE3 *)
1448 (&ptable4->basicTable3);
1449 const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
1450 uint16_t table_offset;
1451 ATOM_PPLIB_PPM_Table *atom_ppm_table;
1452
1453 hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit);
1454 hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1455
1456 hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit);
1457 hwmgr->platform_descriptor.TDPAdjustment = 0;
1458
1459 hwmgr->platform_descriptor.VidAdjustment = 0;
1460 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1461 hwmgr->platform_descriptor.VidMinLimit = 0;
1462 hwmgr->platform_descriptor.VidMaxLimit = 1500000;
1463 hwmgr->platform_descriptor.VidStep = 6250;
1464
1465 hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1466
1467 if (hwmgr->platform_descriptor.TDPODLimit != 0)
1468 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1469 PHM_PlatformCaps_PowerControl);
1470
1471 hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1472
1473 hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1474
1475 hwmgr->dyn_state.cac_leakage_table = NULL;
1476
1477 if (0 != ptable5->usCACLeakageTableOffset) {
1478 const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1479 (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1480 le16_to_cpu(ptable5->usCACLeakageTableOffset));
1481 result = get_cac_leakage_table(hwmgr,
1482 &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1483 }
1484
1485 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1486
1487 hwmgr->dyn_state.ppm_parameter_table = NULL;
1488
1489 if (0 != ptable3->usExtendendedHeaderOffset) {
1490 extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1491 (((unsigned long)powerplay_table) +
1492 le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1493 if ((extended_header->usPPMTableOffset > 0) &&
1494 le16_to_cpu(extended_header->usSize) >=
1495 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1496 table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1497 atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1498 (((unsigned long)powerplay_table) + table_offset);
1499 if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1500 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1501 PHM_PlatformCaps_EnablePlatformPowerManagement);
1502 }
1503 }
1504 }
1505 return result;
1506 }
1507
init_phase_shedding_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1508 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1509 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1510 {
1511 if (le16_to_cpu(powerplay_table->usTableSize) >=
1512 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1513 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1514 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1515
1516 if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1517 const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1518 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
1519 (((unsigned long)powerplay_table4) +
1520 le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1521 struct phm_phase_shedding_limits_table *table;
1522 unsigned long size, i;
1523
1524
1525 size = sizeof(unsigned long) +
1526 (sizeof(struct phm_phase_shedding_limits_table) *
1527 ptable->ucNumEntries);
1528
1529 table = kzalloc(size, GFP_KERNEL);
1530
1531 if (table == NULL)
1532 return -ENOMEM;
1533
1534 table->count = (unsigned long)ptable->ucNumEntries;
1535
1536 for (i = 0; i < table->count; i++) {
1537 table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1538 table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1539 | le16_to_cpu(ptable->entries[i].usSclkLow);
1540 table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1541 | le16_to_cpu(ptable->entries[i].usMclkLow);
1542 }
1543 hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1544 }
1545 }
1546
1547 return 0;
1548 }
1549
get_number_of_vce_state_table_entries(struct pp_hwmgr * hwmgr)1550 static int get_number_of_vce_state_table_entries(
1551 struct pp_hwmgr *hwmgr)
1552 {
1553 const ATOM_PPLIB_POWERPLAYTABLE *table =
1554 get_powerplay_table(hwmgr);
1555 const ATOM_PPLIB_VCE_State_Table *vce_table =
1556 get_vce_state_table(hwmgr, table);
1557
1558 if (vce_table)
1559 return vce_table->numEntries;
1560
1561 return 0;
1562 }
1563
get_vce_state_table_entry(struct pp_hwmgr * hwmgr,unsigned long i,struct amd_vce_state * vce_state,void ** clock_info,unsigned long * flag)1564 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1565 unsigned long i,
1566 struct amd_vce_state *vce_state,
1567 void **clock_info,
1568 unsigned long *flag)
1569 {
1570 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1571
1572 const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1573
1574 unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1575
1576 const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1577
1578 const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1579 le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1580
1581 const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1582
1583 const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1584
1585 unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1586
1587 *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1588
1589 vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1590 vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1591
1592 *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1593
1594 return 0;
1595 }
1596
1597
pp_tables_initialize(struct pp_hwmgr * hwmgr)1598 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1599 {
1600 int result;
1601 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1602
1603 if (hwmgr->chip_id == CHIP_RAVEN)
1604 return 0;
1605
1606 hwmgr->need_pp_table_upload = true;
1607
1608 powerplay_table = get_powerplay_table(hwmgr);
1609
1610 result = init_powerplay_tables(hwmgr, powerplay_table);
1611
1612 PP_ASSERT_WITH_CODE((result == 0),
1613 "init_powerplay_tables failed", return result);
1614
1615 result = set_platform_caps(hwmgr,
1616 le32_to_cpu(powerplay_table->ulPlatformCaps));
1617
1618 PP_ASSERT_WITH_CODE((result == 0),
1619 "set_platform_caps failed", return result);
1620
1621 result = init_thermal_controller(hwmgr, powerplay_table);
1622
1623 PP_ASSERT_WITH_CODE((result == 0),
1624 "init_thermal_controller failed", return result);
1625
1626 result = init_overdrive_limits(hwmgr, powerplay_table);
1627
1628 PP_ASSERT_WITH_CODE((result == 0),
1629 "init_overdrive_limits failed", return result);
1630
1631 result = init_clock_voltage_dependency(hwmgr,
1632 powerplay_table);
1633
1634 PP_ASSERT_WITH_CODE((result == 0),
1635 "init_clock_voltage_dependency failed", return result);
1636
1637 result = init_dpm2_parameters(hwmgr, powerplay_table);
1638
1639 PP_ASSERT_WITH_CODE((result == 0),
1640 "init_dpm2_parameters failed", return result);
1641
1642 result = init_phase_shedding_table(hwmgr, powerplay_table);
1643
1644 PP_ASSERT_WITH_CODE((result == 0),
1645 "init_phase_shedding_table failed", return result);
1646
1647 return result;
1648 }
1649
pp_tables_uninitialize(struct pp_hwmgr * hwmgr)1650 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1651 {
1652 if (hwmgr->chip_id == CHIP_RAVEN)
1653 return 0;
1654
1655 kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1656 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1657
1658 kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1659 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1660
1661 kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1662 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1663
1664 kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1665 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1666
1667 kfree(hwmgr->dyn_state.valid_mclk_values);
1668 hwmgr->dyn_state.valid_mclk_values = NULL;
1669
1670 kfree(hwmgr->dyn_state.valid_sclk_values);
1671 hwmgr->dyn_state.valid_sclk_values = NULL;
1672
1673 kfree(hwmgr->dyn_state.cac_leakage_table);
1674 hwmgr->dyn_state.cac_leakage_table = NULL;
1675
1676 kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1677 hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1678
1679 kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1680 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1681
1682 kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1683 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1684
1685 kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1686 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1687
1688 kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1689 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1690
1691 kfree(hwmgr->dyn_state.cac_dtp_table);
1692 hwmgr->dyn_state.cac_dtp_table = NULL;
1693
1694 kfree(hwmgr->dyn_state.ppm_parameter_table);
1695 hwmgr->dyn_state.ppm_parameter_table = NULL;
1696
1697 kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1698 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1699
1700 return 0;
1701 }
1702
1703 const struct pp_table_func pptable_funcs = {
1704 .pptable_init = pp_tables_initialize,
1705 .pptable_fini = pp_tables_uninitialize,
1706 .pptable_get_number_of_vce_state_table_entries =
1707 get_number_of_vce_state_table_entries,
1708 .pptable_get_vce_state_table_entry =
1709 get_vce_state_table_entry,
1710 };
1711
1712