Loading...
1/*
2 * Copyright 2011 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 * Authors: Alex Deucher
23 */
24
25#include <drm/drmP.h>
26#include "amdgpu.h"
27#include "amdgpu_atombios.h"
28#include "amdgpu_i2c.h"
29#include "amdgpu_dpm.h"
30#include "atom.h"
31
32void amdgpu_dpm_print_class_info(u32 class, u32 class2)
33{
34 const char *s;
35
36 switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
37 case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
38 default:
39 s = "none";
40 break;
41 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
42 s = "battery";
43 break;
44 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
45 s = "balanced";
46 break;
47 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
48 s = "performance";
49 break;
50 }
51 printk("\tui class: %s\n", s);
52 printk("\tinternal class:");
53 if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&
54 (class2 == 0))
55 pr_cont(" none");
56 else {
57 if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)
58 pr_cont(" boot");
59 if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
60 pr_cont(" thermal");
61 if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
62 pr_cont(" limited_pwr");
63 if (class & ATOM_PPLIB_CLASSIFICATION_REST)
64 pr_cont(" rest");
65 if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)
66 pr_cont(" forced");
67 if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
68 pr_cont(" 3d_perf");
69 if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
70 pr_cont(" ovrdrv");
71 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
72 pr_cont(" uvd");
73 if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)
74 pr_cont(" 3d_low");
75 if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)
76 pr_cont(" acpi");
77 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
78 pr_cont(" uvd_hd2");
79 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
80 pr_cont(" uvd_hd");
81 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
82 pr_cont(" uvd_sd");
83 if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
84 pr_cont(" limited_pwr2");
85 if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
86 pr_cont(" ulv");
87 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
88 pr_cont(" uvd_mvc");
89 }
90 pr_cont("\n");
91}
92
93void amdgpu_dpm_print_cap_info(u32 caps)
94{
95 printk("\tcaps:");
96 if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
97 pr_cont(" single_disp");
98 if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)
99 pr_cont(" video");
100 if (caps & ATOM_PPLIB_DISALLOW_ON_DC)
101 pr_cont(" no_dc");
102 pr_cont("\n");
103}
104
105void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
106 struct amdgpu_ps *rps)
107{
108 printk("\tstatus:");
109 if (rps == adev->pm.dpm.current_ps)
110 pr_cont(" c");
111 if (rps == adev->pm.dpm.requested_ps)
112 pr_cont(" r");
113 if (rps == adev->pm.dpm.boot_ps)
114 pr_cont(" b");
115 pr_cont("\n");
116}
117
118
119u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
120{
121 struct drm_device *dev = adev->ddev;
122 struct drm_crtc *crtc;
123 struct amdgpu_crtc *amdgpu_crtc;
124 u32 vblank_in_pixels;
125 u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
126
127 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
128 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
129 amdgpu_crtc = to_amdgpu_crtc(crtc);
130 if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
131 vblank_in_pixels =
132 amdgpu_crtc->hw_mode.crtc_htotal *
133 (amdgpu_crtc->hw_mode.crtc_vblank_end -
134 amdgpu_crtc->hw_mode.crtc_vdisplay +
135 (amdgpu_crtc->v_border * 2));
136
137 vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
138 break;
139 }
140 }
141 }
142
143 return vblank_time_us;
144}
145
146u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
147{
148 struct drm_device *dev = adev->ddev;
149 struct drm_crtc *crtc;
150 struct amdgpu_crtc *amdgpu_crtc;
151 u32 vrefresh = 0;
152
153 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
154 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
155 amdgpu_crtc = to_amdgpu_crtc(crtc);
156 if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
157 vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
158 break;
159 }
160 }
161 }
162
163 return vrefresh;
164}
165
166void amdgpu_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
167 u32 *p, u32 *u)
168{
169 u32 b_c = 0;
170 u32 i_c;
171 u32 tmp;
172
173 i_c = (i * r_c) / 100;
174 tmp = i_c >> p_b;
175
176 while (tmp) {
177 b_c++;
178 tmp >>= 1;
179 }
180
181 *u = (b_c + 1) / 2;
182 *p = i_c / (1 << (2 * (*u)));
183}
184
185int amdgpu_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)
186{
187 u32 k, a, ah, al;
188 u32 t1;
189
190 if ((fl == 0) || (fh == 0) || (fl > fh))
191 return -EINVAL;
192
193 k = (100 * fh) / fl;
194 t1 = (t * (k - 100));
195 a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100));
196 a = (a + 5) / 10;
197 ah = ((a * t) + 5000) / 10000;
198 al = a - ah;
199
200 *th = t - ah;
201 *tl = t + al;
202
203 return 0;
204}
205
206bool amdgpu_is_uvd_state(u32 class, u32 class2)
207{
208 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
209 return true;
210 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
211 return true;
212 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
213 return true;
214 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
215 return true;
216 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
217 return true;
218 return false;
219}
220
221bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
222{
223 switch (sensor) {
224 case THERMAL_TYPE_RV6XX:
225 case THERMAL_TYPE_RV770:
226 case THERMAL_TYPE_EVERGREEN:
227 case THERMAL_TYPE_SUMO:
228 case THERMAL_TYPE_NI:
229 case THERMAL_TYPE_SI:
230 case THERMAL_TYPE_CI:
231 case THERMAL_TYPE_KV:
232 return true;
233 case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
234 case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
235 return false; /* need special handling */
236 case THERMAL_TYPE_NONE:
237 case THERMAL_TYPE_EXTERNAL:
238 case THERMAL_TYPE_EXTERNAL_GPIO:
239 default:
240 return false;
241 }
242}
243
244union power_info {
245 struct _ATOM_POWERPLAY_INFO info;
246 struct _ATOM_POWERPLAY_INFO_V2 info_2;
247 struct _ATOM_POWERPLAY_INFO_V3 info_3;
248 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
249 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
250 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
251 struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
252 struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
253};
254
255union fan_info {
256 struct _ATOM_PPLIB_FANTABLE fan;
257 struct _ATOM_PPLIB_FANTABLE2 fan2;
258 struct _ATOM_PPLIB_FANTABLE3 fan3;
259};
260
261static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table,
262 ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
263{
264 u32 size = atom_table->ucNumEntries *
265 sizeof(struct amdgpu_clock_voltage_dependency_entry);
266 int i;
267 ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;
268
269 amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
270 if (!amdgpu_table->entries)
271 return -ENOMEM;
272
273 entry = &atom_table->entries[0];
274 for (i = 0; i < atom_table->ucNumEntries; i++) {
275 amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |
276 (entry->ucClockHigh << 16);
277 amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage);
278 entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)
279 ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
280 }
281 amdgpu_table->count = atom_table->ucNumEntries;
282
283 return 0;
284}
285
286int amdgpu_get_platform_caps(struct amdgpu_device *adev)
287{
288 struct amdgpu_mode_info *mode_info = &adev->mode_info;
289 union power_info *power_info;
290 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
291 u16 data_offset;
292 u8 frev, crev;
293
294 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
295 &frev, &crev, &data_offset))
296 return -EINVAL;
297 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
298
299 adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
300 adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
301 adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
302
303 return 0;
304}
305
306/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
307#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
308#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
309#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
310#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
311#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
312#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
313#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
314#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
315
316int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
317{
318 struct amdgpu_mode_info *mode_info = &adev->mode_info;
319 union power_info *power_info;
320 union fan_info *fan_info;
321 ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
322 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
323 u16 data_offset;
324 u8 frev, crev;
325 int ret, i;
326
327 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
328 &frev, &crev, &data_offset))
329 return -EINVAL;
330 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
331
332 /* fan table */
333 if (le16_to_cpu(power_info->pplib.usTableSize) >=
334 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
335 if (power_info->pplib3.usFanTableOffset) {
336 fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
337 le16_to_cpu(power_info->pplib3.usFanTableOffset));
338 adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
339 adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
340 adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
341 adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
342 adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
343 adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
344 adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
345 if (fan_info->fan.ucFanTableFormat >= 2)
346 adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
347 else
348 adev->pm.dpm.fan.t_max = 10900;
349 adev->pm.dpm.fan.cycle_delay = 100000;
350 if (fan_info->fan.ucFanTableFormat >= 3) {
351 adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;
352 adev->pm.dpm.fan.default_max_fan_pwm =
353 le16_to_cpu(fan_info->fan3.usFanPWMMax);
354 adev->pm.dpm.fan.default_fan_output_sensitivity = 4836;
355 adev->pm.dpm.fan.fan_output_sensitivity =
356 le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);
357 }
358 adev->pm.dpm.fan.ucode_fan_control = true;
359 }
360 }
361
362 /* clock dependancy tables, shedding tables */
363 if (le16_to_cpu(power_info->pplib.usTableSize) >=
364 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
365 if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
366 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
367 (mode_info->atom_context->bios + data_offset +
368 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
369 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
370 dep_table);
371 if (ret) {
372 amdgpu_free_extended_power_table(adev);
373 return ret;
374 }
375 }
376 if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
377 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
378 (mode_info->atom_context->bios + data_offset +
379 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
380 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
381 dep_table);
382 if (ret) {
383 amdgpu_free_extended_power_table(adev);
384 return ret;
385 }
386 }
387 if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
388 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
389 (mode_info->atom_context->bios + data_offset +
390 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
391 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
392 dep_table);
393 if (ret) {
394 amdgpu_free_extended_power_table(adev);
395 return ret;
396 }
397 }
398 if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
399 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
400 (mode_info->atom_context->bios + data_offset +
401 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
402 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
403 dep_table);
404 if (ret) {
405 amdgpu_free_extended_power_table(adev);
406 return ret;
407 }
408 }
409 if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
410 ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
411 (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
412 (mode_info->atom_context->bios + data_offset +
413 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
414 if (clk_v->ucNumEntries) {
415 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
416 le16_to_cpu(clk_v->entries[0].usSclkLow) |
417 (clk_v->entries[0].ucSclkHigh << 16);
418 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
419 le16_to_cpu(clk_v->entries[0].usMclkLow) |
420 (clk_v->entries[0].ucMclkHigh << 16);
421 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
422 le16_to_cpu(clk_v->entries[0].usVddc);
423 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
424 le16_to_cpu(clk_v->entries[0].usVddci);
425 }
426 }
427 if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {
428 ATOM_PPLIB_PhaseSheddingLimits_Table *psl =
429 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
430 (mode_info->atom_context->bios + data_offset +
431 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));
432 ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
433
434 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
435 kzalloc(psl->ucNumEntries *
436 sizeof(struct amdgpu_phase_shedding_limits_entry),
437 GFP_KERNEL);
438 if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
439 amdgpu_free_extended_power_table(adev);
440 return -ENOMEM;
441 }
442
443 entry = &psl->entries[0];
444 for (i = 0; i < psl->ucNumEntries; i++) {
445 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =
446 le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);
447 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =
448 le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);
449 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =
450 le16_to_cpu(entry->usVoltage);
451 entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)
452 ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
453 }
454 adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
455 psl->ucNumEntries;
456 }
457 }
458
459 /* cac data */
460 if (le16_to_cpu(power_info->pplib.usTableSize) >=
461 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
462 adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
463 adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
464 adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit;
465 adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
466 if (adev->pm.dpm.tdp_od_limit)
467 adev->pm.dpm.power_control = true;
468 else
469 adev->pm.dpm.power_control = false;
470 adev->pm.dpm.tdp_adjustment = 0;
471 adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
472 adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
473 adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
474 if (power_info->pplib5.usCACLeakageTableOffset) {
475 ATOM_PPLIB_CAC_Leakage_Table *cac_table =
476 (ATOM_PPLIB_CAC_Leakage_Table *)
477 (mode_info->atom_context->bios + data_offset +
478 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
479 ATOM_PPLIB_CAC_Leakage_Record *entry;
480 u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
481 adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
482 if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
483 amdgpu_free_extended_power_table(adev);
484 return -ENOMEM;
485 }
486 entry = &cac_table->entries[0];
487 for (i = 0; i < cac_table->ucNumEntries; i++) {
488 if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
489 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =
490 le16_to_cpu(entry->usVddc1);
491 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =
492 le16_to_cpu(entry->usVddc2);
493 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =
494 le16_to_cpu(entry->usVddc3);
495 } else {
496 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
497 le16_to_cpu(entry->usVddc);
498 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
499 le32_to_cpu(entry->ulLeakageValue);
500 }
501 entry = (ATOM_PPLIB_CAC_Leakage_Record *)
502 ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
503 }
504 adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
505 }
506 }
507
508 /* ext tables */
509 if (le16_to_cpu(power_info->pplib.usTableSize) >=
510 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
511 ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
512 (mode_info->atom_context->bios + data_offset +
513 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
514 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
515 ext_hdr->usVCETableOffset) {
516 VCEClockInfoArray *array = (VCEClockInfoArray *)
517 (mode_info->atom_context->bios + data_offset +
518 le16_to_cpu(ext_hdr->usVCETableOffset) + 1);
519 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =
520 (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
521 (mode_info->atom_context->bios + data_offset +
522 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
523 1 + array->ucNumEntries * sizeof(VCEClockInfo));
524 ATOM_PPLIB_VCE_State_Table *states =
525 (ATOM_PPLIB_VCE_State_Table *)
526 (mode_info->atom_context->bios + data_offset +
527 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
528 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
529 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
530 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
531 ATOM_PPLIB_VCE_State_Record *state_entry;
532 VCEClockInfo *vce_clk;
533 u32 size = limits->numEntries *
534 sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
535 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
536 kzalloc(size, GFP_KERNEL);
537 if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
538 amdgpu_free_extended_power_table(adev);
539 return -ENOMEM;
540 }
541 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
542 limits->numEntries;
543 entry = &limits->entries[0];
544 state_entry = &states->entries[0];
545 for (i = 0; i < limits->numEntries; i++) {
546 vce_clk = (VCEClockInfo *)
547 ((u8 *)&array->entries[0] +
548 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
549 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
550 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
551 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =
552 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
553 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =
554 le16_to_cpu(entry->usVoltage);
555 entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
556 ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
557 }
558 adev->pm.dpm.num_of_vce_states =
559 states->numEntries > AMD_MAX_VCE_LEVELS ?
560 AMD_MAX_VCE_LEVELS : states->numEntries;
561 for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
562 vce_clk = (VCEClockInfo *)
563 ((u8 *)&array->entries[0] +
564 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
565 adev->pm.dpm.vce_states[i].evclk =
566 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
567 adev->pm.dpm.vce_states[i].ecclk =
568 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
569 adev->pm.dpm.vce_states[i].clk_idx =
570 state_entry->ucClockInfoIndex & 0x3f;
571 adev->pm.dpm.vce_states[i].pstate =
572 (state_entry->ucClockInfoIndex & 0xc0) >> 6;
573 state_entry = (ATOM_PPLIB_VCE_State_Record *)
574 ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
575 }
576 }
577 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
578 ext_hdr->usUVDTableOffset) {
579 UVDClockInfoArray *array = (UVDClockInfoArray *)
580 (mode_info->atom_context->bios + data_offset +
581 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);
582 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =
583 (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
584 (mode_info->atom_context->bios + data_offset +
585 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +
586 1 + (array->ucNumEntries * sizeof (UVDClockInfo)));
587 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;
588 u32 size = limits->numEntries *
589 sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
590 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
591 kzalloc(size, GFP_KERNEL);
592 if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
593 amdgpu_free_extended_power_table(adev);
594 return -ENOMEM;
595 }
596 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
597 limits->numEntries;
598 entry = &limits->entries[0];
599 for (i = 0; i < limits->numEntries; i++) {
600 UVDClockInfo *uvd_clk = (UVDClockInfo *)
601 ((u8 *)&array->entries[0] +
602 (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));
603 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =
604 le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);
605 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
606 le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
607 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
608 le16_to_cpu(entry->usVoltage);
609 entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
610 ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
611 }
612 }
613 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
614 ext_hdr->usSAMUTableOffset) {
615 ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
616 (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
617 (mode_info->atom_context->bios + data_offset +
618 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);
619 ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;
620 u32 size = limits->numEntries *
621 sizeof(struct amdgpu_clock_voltage_dependency_entry);
622 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
623 kzalloc(size, GFP_KERNEL);
624 if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
625 amdgpu_free_extended_power_table(adev);
626 return -ENOMEM;
627 }
628 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
629 limits->numEntries;
630 entry = &limits->entries[0];
631 for (i = 0; i < limits->numEntries; i++) {
632 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =
633 le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);
634 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =
635 le16_to_cpu(entry->usVoltage);
636 entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)
637 ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
638 }
639 }
640 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
641 ext_hdr->usPPMTableOffset) {
642 ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
643 (mode_info->atom_context->bios + data_offset +
644 le16_to_cpu(ext_hdr->usPPMTableOffset));
645 adev->pm.dpm.dyn_state.ppm_table =
646 kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
647 if (!adev->pm.dpm.dyn_state.ppm_table) {
648 amdgpu_free_extended_power_table(adev);
649 return -ENOMEM;
650 }
651 adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
652 adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
653 le16_to_cpu(ppm->usCpuCoreNumber);
654 adev->pm.dpm.dyn_state.ppm_table->platform_tdp =
655 le32_to_cpu(ppm->ulPlatformTDP);
656 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =
657 le32_to_cpu(ppm->ulSmallACPlatformTDP);
658 adev->pm.dpm.dyn_state.ppm_table->platform_tdc =
659 le32_to_cpu(ppm->ulPlatformTDC);
660 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =
661 le32_to_cpu(ppm->ulSmallACPlatformTDC);
662 adev->pm.dpm.dyn_state.ppm_table->apu_tdp =
663 le32_to_cpu(ppm->ulApuTDP);
664 adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =
665 le32_to_cpu(ppm->ulDGpuTDP);
666 adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =
667 le32_to_cpu(ppm->ulDGpuUlvPower);
668 adev->pm.dpm.dyn_state.ppm_table->tj_max =
669 le32_to_cpu(ppm->ulTjmax);
670 }
671 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
672 ext_hdr->usACPTableOffset) {
673 ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
674 (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
675 (mode_info->atom_context->bios + data_offset +
676 le16_to_cpu(ext_hdr->usACPTableOffset) + 1);
677 ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;
678 u32 size = limits->numEntries *
679 sizeof(struct amdgpu_clock_voltage_dependency_entry);
680 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
681 kzalloc(size, GFP_KERNEL);
682 if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
683 amdgpu_free_extended_power_table(adev);
684 return -ENOMEM;
685 }
686 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
687 limits->numEntries;
688 entry = &limits->entries[0];
689 for (i = 0; i < limits->numEntries; i++) {
690 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =
691 le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);
692 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =
693 le16_to_cpu(entry->usVoltage);
694 entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)
695 ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
696 }
697 }
698 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
699 ext_hdr->usPowerTuneTableOffset) {
700 u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
701 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
702 ATOM_PowerTune_Table *pt;
703 adev->pm.dpm.dyn_state.cac_tdp_table =
704 kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
705 if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
706 amdgpu_free_extended_power_table(adev);
707 return -ENOMEM;
708 }
709 if (rev > 0) {
710 ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
711 (mode_info->atom_context->bios + data_offset +
712 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
713 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
714 ppt->usMaximumPowerDeliveryLimit;
715 pt = &ppt->power_tune_table;
716 } else {
717 ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
718 (mode_info->atom_context->bios + data_offset +
719 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
720 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;
721 pt = &ppt->power_tune_table;
722 }
723 adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);
724 adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =
725 le16_to_cpu(pt->usConfigurableTDP);
726 adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);
727 adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =
728 le16_to_cpu(pt->usBatteryPowerLimit);
729 adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =
730 le16_to_cpu(pt->usSmallPowerLimit);
731 adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =
732 le16_to_cpu(pt->usLowCACLeakage);
733 adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =
734 le16_to_cpu(pt->usHighCACLeakage);
735 }
736 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) &&
737 ext_hdr->usSclkVddgfxTableOffset) {
738 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
739 (mode_info->atom_context->bios + data_offset +
740 le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset));
741 ret = amdgpu_parse_clk_voltage_dep_table(
742 &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
743 dep_table);
744 if (ret) {
745 kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
746 return ret;
747 }
748 }
749 }
750
751 return 0;
752}
753
754void amdgpu_free_extended_power_table(struct amdgpu_device *adev)
755{
756 struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
757
758 kfree(dyn_state->vddc_dependency_on_sclk.entries);
759 kfree(dyn_state->vddci_dependency_on_mclk.entries);
760 kfree(dyn_state->vddc_dependency_on_mclk.entries);
761 kfree(dyn_state->mvdd_dependency_on_mclk.entries);
762 kfree(dyn_state->cac_leakage_table.entries);
763 kfree(dyn_state->phase_shedding_limits_table.entries);
764 kfree(dyn_state->ppm_table);
765 kfree(dyn_state->cac_tdp_table);
766 kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
767 kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
768 kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
769 kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
770 kfree(dyn_state->vddgfx_dependency_on_sclk.entries);
771}
772
773static const char *pp_lib_thermal_controller_names[] = {
774 "NONE",
775 "lm63",
776 "adm1032",
777 "adm1030",
778 "max6649",
779 "lm64",
780 "f75375",
781 "RV6xx",
782 "RV770",
783 "adt7473",
784 "NONE",
785 "External GPIO",
786 "Evergreen",
787 "emc2103",
788 "Sumo",
789 "Northern Islands",
790 "Southern Islands",
791 "lm96163",
792 "Sea Islands",
793 "Kaveri/Kabini",
794};
795
796void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
797{
798 struct amdgpu_mode_info *mode_info = &adev->mode_info;
799 ATOM_PPLIB_POWERPLAYTABLE *power_table;
800 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
801 ATOM_PPLIB_THERMALCONTROLLER *controller;
802 struct amdgpu_i2c_bus_rec i2c_bus;
803 u16 data_offset;
804 u8 frev, crev;
805
806 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
807 &frev, &crev, &data_offset))
808 return;
809 power_table = (ATOM_PPLIB_POWERPLAYTABLE *)
810 (mode_info->atom_context->bios + data_offset);
811 controller = &power_table->sThermalController;
812
813 /* add the i2c bus for thermal/fan chip */
814 if (controller->ucType > 0) {
815 if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
816 adev->pm.no_fan = true;
817 adev->pm.fan_pulses_per_revolution =
818 controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
819 if (adev->pm.fan_pulses_per_revolution) {
820 adev->pm.fan_min_rpm = controller->ucFanMinRPM;
821 adev->pm.fan_max_rpm = controller->ucFanMaxRPM;
822 }
823 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
824 DRM_INFO("Internal thermal controller %s fan control\n",
825 (controller->ucFanParameters &
826 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
827 adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
828 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
829 DRM_INFO("Internal thermal controller %s fan control\n",
830 (controller->ucFanParameters &
831 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
832 adev->pm.int_thermal_type = THERMAL_TYPE_RV770;
833 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
834 DRM_INFO("Internal thermal controller %s fan control\n",
835 (controller->ucFanParameters &
836 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
837 adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
838 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
839 DRM_INFO("Internal thermal controller %s fan control\n",
840 (controller->ucFanParameters &
841 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
842 adev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
843 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
844 DRM_INFO("Internal thermal controller %s fan control\n",
845 (controller->ucFanParameters &
846 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
847 adev->pm.int_thermal_type = THERMAL_TYPE_NI;
848 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
849 DRM_INFO("Internal thermal controller %s fan control\n",
850 (controller->ucFanParameters &
851 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
852 adev->pm.int_thermal_type = THERMAL_TYPE_SI;
853 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
854 DRM_INFO("Internal thermal controller %s fan control\n",
855 (controller->ucFanParameters &
856 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
857 adev->pm.int_thermal_type = THERMAL_TYPE_CI;
858 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
859 DRM_INFO("Internal thermal controller %s fan control\n",
860 (controller->ucFanParameters &
861 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
862 adev->pm.int_thermal_type = THERMAL_TYPE_KV;
863 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
864 DRM_INFO("External GPIO thermal controller %s fan control\n",
865 (controller->ucFanParameters &
866 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
867 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
868 } else if (controller->ucType ==
869 ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
870 DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
871 (controller->ucFanParameters &
872 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
873 adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
874 } else if (controller->ucType ==
875 ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
876 DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
877 (controller->ucFanParameters &
878 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
879 adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
880 } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
881 DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
882 pp_lib_thermal_controller_names[controller->ucType],
883 controller->ucI2cAddress >> 1,
884 (controller->ucFanParameters &
885 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
886 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
887 i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine);
888 adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus);
889 if (adev->pm.i2c_bus) {
890 struct i2c_board_info info = { };
891 const char *name = pp_lib_thermal_controller_names[controller->ucType];
892 info.addr = controller->ucI2cAddress >> 1;
893 strlcpy(info.type, name, sizeof(info.type));
894 i2c_new_device(&adev->pm.i2c_bus->adapter, &info);
895 }
896 } else {
897 DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
898 controller->ucType,
899 controller->ucI2cAddress >> 1,
900 (controller->ucFanParameters &
901 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
902 }
903 }
904}
905
906enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev,
907 u32 sys_mask,
908 enum amdgpu_pcie_gen asic_gen,
909 enum amdgpu_pcie_gen default_gen)
910{
911 switch (asic_gen) {
912 case AMDGPU_PCIE_GEN1:
913 return AMDGPU_PCIE_GEN1;
914 case AMDGPU_PCIE_GEN2:
915 return AMDGPU_PCIE_GEN2;
916 case AMDGPU_PCIE_GEN3:
917 return AMDGPU_PCIE_GEN3;
918 default:
919 if ((sys_mask & DRM_PCIE_SPEED_80) && (default_gen == AMDGPU_PCIE_GEN3))
920 return AMDGPU_PCIE_GEN3;
921 else if ((sys_mask & DRM_PCIE_SPEED_50) && (default_gen == AMDGPU_PCIE_GEN2))
922 return AMDGPU_PCIE_GEN2;
923 else
924 return AMDGPU_PCIE_GEN1;
925 }
926 return AMDGPU_PCIE_GEN1;
927}
928
929u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev,
930 u16 asic_lanes,
931 u16 default_lanes)
932{
933 switch (asic_lanes) {
934 case 0:
935 default:
936 return default_lanes;
937 case 1:
938 return 1;
939 case 2:
940 return 2;
941 case 4:
942 return 4;
943 case 8:
944 return 8;
945 case 12:
946 return 12;
947 case 16:
948 return 16;
949 }
950}
951
952u8 amdgpu_encode_pci_lane_width(u32 lanes)
953{
954 u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 };
955
956 if (lanes > 16)
957 return 0;
958
959 return encoded_lanes[lanes];
960}
961
962struct amd_vce_state*
963amdgpu_get_vce_clock_state(void *handle, u32 idx)
964{
965 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
966
967 if (idx < adev->pm.dpm.num_of_vce_states)
968 return &adev->pm.dpm.vce_states[idx];
969
970 return NULL;
971}
1/*
2 * Copyright 2011 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 * Authors: Alex Deucher
23 */
24
25#include "amdgpu.h"
26#include "amdgpu_atombios.h"
27#include "amdgpu_i2c.h"
28#include "amdgpu_dpm.h"
29#include "atom.h"
30#include "amd_pcie.h"
31
32void amdgpu_dpm_print_class_info(u32 class, u32 class2)
33{
34 const char *s;
35
36 switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
37 case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
38 default:
39 s = "none";
40 break;
41 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
42 s = "battery";
43 break;
44 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
45 s = "balanced";
46 break;
47 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
48 s = "performance";
49 break;
50 }
51 printk("\tui class: %s\n", s);
52 printk("\tinternal class:");
53 if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&
54 (class2 == 0))
55 pr_cont(" none");
56 else {
57 if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)
58 pr_cont(" boot");
59 if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
60 pr_cont(" thermal");
61 if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
62 pr_cont(" limited_pwr");
63 if (class & ATOM_PPLIB_CLASSIFICATION_REST)
64 pr_cont(" rest");
65 if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)
66 pr_cont(" forced");
67 if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
68 pr_cont(" 3d_perf");
69 if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
70 pr_cont(" ovrdrv");
71 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
72 pr_cont(" uvd");
73 if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)
74 pr_cont(" 3d_low");
75 if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)
76 pr_cont(" acpi");
77 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
78 pr_cont(" uvd_hd2");
79 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
80 pr_cont(" uvd_hd");
81 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
82 pr_cont(" uvd_sd");
83 if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
84 pr_cont(" limited_pwr2");
85 if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
86 pr_cont(" ulv");
87 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
88 pr_cont(" uvd_mvc");
89 }
90 pr_cont("\n");
91}
92
93void amdgpu_dpm_print_cap_info(u32 caps)
94{
95 printk("\tcaps:");
96 if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
97 pr_cont(" single_disp");
98 if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)
99 pr_cont(" video");
100 if (caps & ATOM_PPLIB_DISALLOW_ON_DC)
101 pr_cont(" no_dc");
102 pr_cont("\n");
103}
104
105void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
106 struct amdgpu_ps *rps)
107{
108 printk("\tstatus:");
109 if (rps == adev->pm.dpm.current_ps)
110 pr_cont(" c");
111 if (rps == adev->pm.dpm.requested_ps)
112 pr_cont(" r");
113 if (rps == adev->pm.dpm.boot_ps)
114 pr_cont(" b");
115 pr_cont("\n");
116}
117
118void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
119{
120 struct drm_device *ddev = adev->ddev;
121 struct drm_crtc *crtc;
122 struct amdgpu_crtc *amdgpu_crtc;
123
124 adev->pm.dpm.new_active_crtcs = 0;
125 adev->pm.dpm.new_active_crtc_count = 0;
126 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
127 list_for_each_entry(crtc,
128 &ddev->mode_config.crtc_list, head) {
129 amdgpu_crtc = to_amdgpu_crtc(crtc);
130 if (amdgpu_crtc->enabled) {
131 adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
132 adev->pm.dpm.new_active_crtc_count++;
133 }
134 }
135 }
136}
137
138
139u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
140{
141 struct drm_device *dev = adev->ddev;
142 struct drm_crtc *crtc;
143 struct amdgpu_crtc *amdgpu_crtc;
144 u32 vblank_in_pixels;
145 u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
146
147 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
148 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
149 amdgpu_crtc = to_amdgpu_crtc(crtc);
150 if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
151 vblank_in_pixels =
152 amdgpu_crtc->hw_mode.crtc_htotal *
153 (amdgpu_crtc->hw_mode.crtc_vblank_end -
154 amdgpu_crtc->hw_mode.crtc_vdisplay +
155 (amdgpu_crtc->v_border * 2));
156
157 vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
158 break;
159 }
160 }
161 }
162
163 return vblank_time_us;
164}
165
166u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
167{
168 struct drm_device *dev = adev->ddev;
169 struct drm_crtc *crtc;
170 struct amdgpu_crtc *amdgpu_crtc;
171 u32 vrefresh = 0;
172
173 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
174 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
175 amdgpu_crtc = to_amdgpu_crtc(crtc);
176 if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
177 vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
178 break;
179 }
180 }
181 }
182
183 return vrefresh;
184}
185
186bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
187{
188 switch (sensor) {
189 case THERMAL_TYPE_RV6XX:
190 case THERMAL_TYPE_RV770:
191 case THERMAL_TYPE_EVERGREEN:
192 case THERMAL_TYPE_SUMO:
193 case THERMAL_TYPE_NI:
194 case THERMAL_TYPE_SI:
195 case THERMAL_TYPE_CI:
196 case THERMAL_TYPE_KV:
197 return true;
198 case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
199 case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
200 return false; /* need special handling */
201 case THERMAL_TYPE_NONE:
202 case THERMAL_TYPE_EXTERNAL:
203 case THERMAL_TYPE_EXTERNAL_GPIO:
204 default:
205 return false;
206 }
207}
208
209union power_info {
210 struct _ATOM_POWERPLAY_INFO info;
211 struct _ATOM_POWERPLAY_INFO_V2 info_2;
212 struct _ATOM_POWERPLAY_INFO_V3 info_3;
213 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
214 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
215 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
216 struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
217 struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
218};
219
220union fan_info {
221 struct _ATOM_PPLIB_FANTABLE fan;
222 struct _ATOM_PPLIB_FANTABLE2 fan2;
223 struct _ATOM_PPLIB_FANTABLE3 fan3;
224};
225
226static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table,
227 ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
228{
229 u32 size = atom_table->ucNumEntries *
230 sizeof(struct amdgpu_clock_voltage_dependency_entry);
231 int i;
232 ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;
233
234 amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
235 if (!amdgpu_table->entries)
236 return -ENOMEM;
237
238 entry = &atom_table->entries[0];
239 for (i = 0; i < atom_table->ucNumEntries; i++) {
240 amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |
241 (entry->ucClockHigh << 16);
242 amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage);
243 entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)
244 ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
245 }
246 amdgpu_table->count = atom_table->ucNumEntries;
247
248 return 0;
249}
250
251int amdgpu_get_platform_caps(struct amdgpu_device *adev)
252{
253 struct amdgpu_mode_info *mode_info = &adev->mode_info;
254 union power_info *power_info;
255 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
256 u16 data_offset;
257 u8 frev, crev;
258
259 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
260 &frev, &crev, &data_offset))
261 return -EINVAL;
262 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
263
264 adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
265 adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
266 adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
267
268 return 0;
269}
270
271/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
272#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
273#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
274#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
275#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
276#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
277#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
278#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
279#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
280
281int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
282{
283 struct amdgpu_mode_info *mode_info = &adev->mode_info;
284 union power_info *power_info;
285 union fan_info *fan_info;
286 ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
287 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
288 u16 data_offset;
289 u8 frev, crev;
290 int ret, i;
291
292 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
293 &frev, &crev, &data_offset))
294 return -EINVAL;
295 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
296
297 /* fan table */
298 if (le16_to_cpu(power_info->pplib.usTableSize) >=
299 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
300 if (power_info->pplib3.usFanTableOffset) {
301 fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
302 le16_to_cpu(power_info->pplib3.usFanTableOffset));
303 adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
304 adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
305 adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
306 adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
307 adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
308 adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
309 adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
310 if (fan_info->fan.ucFanTableFormat >= 2)
311 adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
312 else
313 adev->pm.dpm.fan.t_max = 10900;
314 adev->pm.dpm.fan.cycle_delay = 100000;
315 if (fan_info->fan.ucFanTableFormat >= 3) {
316 adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;
317 adev->pm.dpm.fan.default_max_fan_pwm =
318 le16_to_cpu(fan_info->fan3.usFanPWMMax);
319 adev->pm.dpm.fan.default_fan_output_sensitivity = 4836;
320 adev->pm.dpm.fan.fan_output_sensitivity =
321 le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);
322 }
323 adev->pm.dpm.fan.ucode_fan_control = true;
324 }
325 }
326
327 /* clock dependancy tables, shedding tables */
328 if (le16_to_cpu(power_info->pplib.usTableSize) >=
329 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
330 if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
331 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
332 (mode_info->atom_context->bios + data_offset +
333 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
334 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
335 dep_table);
336 if (ret) {
337 amdgpu_free_extended_power_table(adev);
338 return ret;
339 }
340 }
341 if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
342 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
343 (mode_info->atom_context->bios + data_offset +
344 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
345 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
346 dep_table);
347 if (ret) {
348 amdgpu_free_extended_power_table(adev);
349 return ret;
350 }
351 }
352 if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
353 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
354 (mode_info->atom_context->bios + data_offset +
355 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
356 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
357 dep_table);
358 if (ret) {
359 amdgpu_free_extended_power_table(adev);
360 return ret;
361 }
362 }
363 if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
364 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
365 (mode_info->atom_context->bios + data_offset +
366 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
367 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
368 dep_table);
369 if (ret) {
370 amdgpu_free_extended_power_table(adev);
371 return ret;
372 }
373 }
374 if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
375 ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
376 (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
377 (mode_info->atom_context->bios + data_offset +
378 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
379 if (clk_v->ucNumEntries) {
380 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
381 le16_to_cpu(clk_v->entries[0].usSclkLow) |
382 (clk_v->entries[0].ucSclkHigh << 16);
383 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
384 le16_to_cpu(clk_v->entries[0].usMclkLow) |
385 (clk_v->entries[0].ucMclkHigh << 16);
386 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
387 le16_to_cpu(clk_v->entries[0].usVddc);
388 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
389 le16_to_cpu(clk_v->entries[0].usVddci);
390 }
391 }
392 if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {
393 ATOM_PPLIB_PhaseSheddingLimits_Table *psl =
394 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
395 (mode_info->atom_context->bios + data_offset +
396 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));
397 ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
398
399 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
400 kcalloc(psl->ucNumEntries,
401 sizeof(struct amdgpu_phase_shedding_limits_entry),
402 GFP_KERNEL);
403 if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
404 amdgpu_free_extended_power_table(adev);
405 return -ENOMEM;
406 }
407
408 entry = &psl->entries[0];
409 for (i = 0; i < psl->ucNumEntries; i++) {
410 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =
411 le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);
412 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =
413 le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);
414 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =
415 le16_to_cpu(entry->usVoltage);
416 entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)
417 ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
418 }
419 adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
420 psl->ucNumEntries;
421 }
422 }
423
424 /* cac data */
425 if (le16_to_cpu(power_info->pplib.usTableSize) >=
426 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
427 adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
428 adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
429 adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit;
430 adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
431 if (adev->pm.dpm.tdp_od_limit)
432 adev->pm.dpm.power_control = true;
433 else
434 adev->pm.dpm.power_control = false;
435 adev->pm.dpm.tdp_adjustment = 0;
436 adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
437 adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
438 adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
439 if (power_info->pplib5.usCACLeakageTableOffset) {
440 ATOM_PPLIB_CAC_Leakage_Table *cac_table =
441 (ATOM_PPLIB_CAC_Leakage_Table *)
442 (mode_info->atom_context->bios + data_offset +
443 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
444 ATOM_PPLIB_CAC_Leakage_Record *entry;
445 u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
446 adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
447 if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
448 amdgpu_free_extended_power_table(adev);
449 return -ENOMEM;
450 }
451 entry = &cac_table->entries[0];
452 for (i = 0; i < cac_table->ucNumEntries; i++) {
453 if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
454 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =
455 le16_to_cpu(entry->usVddc1);
456 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =
457 le16_to_cpu(entry->usVddc2);
458 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =
459 le16_to_cpu(entry->usVddc3);
460 } else {
461 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
462 le16_to_cpu(entry->usVddc);
463 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
464 le32_to_cpu(entry->ulLeakageValue);
465 }
466 entry = (ATOM_PPLIB_CAC_Leakage_Record *)
467 ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
468 }
469 adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
470 }
471 }
472
473 /* ext tables */
474 if (le16_to_cpu(power_info->pplib.usTableSize) >=
475 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
476 ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
477 (mode_info->atom_context->bios + data_offset +
478 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
479 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
480 ext_hdr->usVCETableOffset) {
481 VCEClockInfoArray *array = (VCEClockInfoArray *)
482 (mode_info->atom_context->bios + data_offset +
483 le16_to_cpu(ext_hdr->usVCETableOffset) + 1);
484 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =
485 (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
486 (mode_info->atom_context->bios + data_offset +
487 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
488 1 + array->ucNumEntries * sizeof(VCEClockInfo));
489 ATOM_PPLIB_VCE_State_Table *states =
490 (ATOM_PPLIB_VCE_State_Table *)
491 (mode_info->atom_context->bios + data_offset +
492 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
493 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
494 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
495 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
496 ATOM_PPLIB_VCE_State_Record *state_entry;
497 VCEClockInfo *vce_clk;
498 u32 size = limits->numEntries *
499 sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
500 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
501 kzalloc(size, GFP_KERNEL);
502 if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
503 amdgpu_free_extended_power_table(adev);
504 return -ENOMEM;
505 }
506 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
507 limits->numEntries;
508 entry = &limits->entries[0];
509 state_entry = &states->entries[0];
510 for (i = 0; i < limits->numEntries; i++) {
511 vce_clk = (VCEClockInfo *)
512 ((u8 *)&array->entries[0] +
513 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
514 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
515 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
516 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =
517 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
518 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =
519 le16_to_cpu(entry->usVoltage);
520 entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
521 ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
522 }
523 adev->pm.dpm.num_of_vce_states =
524 states->numEntries > AMD_MAX_VCE_LEVELS ?
525 AMD_MAX_VCE_LEVELS : states->numEntries;
526 for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
527 vce_clk = (VCEClockInfo *)
528 ((u8 *)&array->entries[0] +
529 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
530 adev->pm.dpm.vce_states[i].evclk =
531 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
532 adev->pm.dpm.vce_states[i].ecclk =
533 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
534 adev->pm.dpm.vce_states[i].clk_idx =
535 state_entry->ucClockInfoIndex & 0x3f;
536 adev->pm.dpm.vce_states[i].pstate =
537 (state_entry->ucClockInfoIndex & 0xc0) >> 6;
538 state_entry = (ATOM_PPLIB_VCE_State_Record *)
539 ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
540 }
541 }
542 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
543 ext_hdr->usUVDTableOffset) {
544 UVDClockInfoArray *array = (UVDClockInfoArray *)
545 (mode_info->atom_context->bios + data_offset +
546 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);
547 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =
548 (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
549 (mode_info->atom_context->bios + data_offset +
550 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +
551 1 + (array->ucNumEntries * sizeof (UVDClockInfo)));
552 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;
553 u32 size = limits->numEntries *
554 sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
555 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
556 kzalloc(size, GFP_KERNEL);
557 if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
558 amdgpu_free_extended_power_table(adev);
559 return -ENOMEM;
560 }
561 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
562 limits->numEntries;
563 entry = &limits->entries[0];
564 for (i = 0; i < limits->numEntries; i++) {
565 UVDClockInfo *uvd_clk = (UVDClockInfo *)
566 ((u8 *)&array->entries[0] +
567 (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));
568 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =
569 le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);
570 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
571 le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
572 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
573 le16_to_cpu(entry->usVoltage);
574 entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
575 ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
576 }
577 }
578 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
579 ext_hdr->usSAMUTableOffset) {
580 ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
581 (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
582 (mode_info->atom_context->bios + data_offset +
583 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);
584 ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;
585 u32 size = limits->numEntries *
586 sizeof(struct amdgpu_clock_voltage_dependency_entry);
587 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
588 kzalloc(size, GFP_KERNEL);
589 if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
590 amdgpu_free_extended_power_table(adev);
591 return -ENOMEM;
592 }
593 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
594 limits->numEntries;
595 entry = &limits->entries[0];
596 for (i = 0; i < limits->numEntries; i++) {
597 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =
598 le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);
599 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =
600 le16_to_cpu(entry->usVoltage);
601 entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)
602 ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
603 }
604 }
605 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
606 ext_hdr->usPPMTableOffset) {
607 ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
608 (mode_info->atom_context->bios + data_offset +
609 le16_to_cpu(ext_hdr->usPPMTableOffset));
610 adev->pm.dpm.dyn_state.ppm_table =
611 kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
612 if (!adev->pm.dpm.dyn_state.ppm_table) {
613 amdgpu_free_extended_power_table(adev);
614 return -ENOMEM;
615 }
616 adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
617 adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
618 le16_to_cpu(ppm->usCpuCoreNumber);
619 adev->pm.dpm.dyn_state.ppm_table->platform_tdp =
620 le32_to_cpu(ppm->ulPlatformTDP);
621 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =
622 le32_to_cpu(ppm->ulSmallACPlatformTDP);
623 adev->pm.dpm.dyn_state.ppm_table->platform_tdc =
624 le32_to_cpu(ppm->ulPlatformTDC);
625 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =
626 le32_to_cpu(ppm->ulSmallACPlatformTDC);
627 adev->pm.dpm.dyn_state.ppm_table->apu_tdp =
628 le32_to_cpu(ppm->ulApuTDP);
629 adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =
630 le32_to_cpu(ppm->ulDGpuTDP);
631 adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =
632 le32_to_cpu(ppm->ulDGpuUlvPower);
633 adev->pm.dpm.dyn_state.ppm_table->tj_max =
634 le32_to_cpu(ppm->ulTjmax);
635 }
636 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
637 ext_hdr->usACPTableOffset) {
638 ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
639 (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
640 (mode_info->atom_context->bios + data_offset +
641 le16_to_cpu(ext_hdr->usACPTableOffset) + 1);
642 ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;
643 u32 size = limits->numEntries *
644 sizeof(struct amdgpu_clock_voltage_dependency_entry);
645 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
646 kzalloc(size, GFP_KERNEL);
647 if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
648 amdgpu_free_extended_power_table(adev);
649 return -ENOMEM;
650 }
651 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
652 limits->numEntries;
653 entry = &limits->entries[0];
654 for (i = 0; i < limits->numEntries; i++) {
655 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =
656 le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);
657 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =
658 le16_to_cpu(entry->usVoltage);
659 entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)
660 ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
661 }
662 }
663 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
664 ext_hdr->usPowerTuneTableOffset) {
665 u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
666 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
667 ATOM_PowerTune_Table *pt;
668 adev->pm.dpm.dyn_state.cac_tdp_table =
669 kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
670 if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
671 amdgpu_free_extended_power_table(adev);
672 return -ENOMEM;
673 }
674 if (rev > 0) {
675 ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
676 (mode_info->atom_context->bios + data_offset +
677 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
678 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
679 ppt->usMaximumPowerDeliveryLimit;
680 pt = &ppt->power_tune_table;
681 } else {
682 ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
683 (mode_info->atom_context->bios + data_offset +
684 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
685 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;
686 pt = &ppt->power_tune_table;
687 }
688 adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);
689 adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =
690 le16_to_cpu(pt->usConfigurableTDP);
691 adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);
692 adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =
693 le16_to_cpu(pt->usBatteryPowerLimit);
694 adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =
695 le16_to_cpu(pt->usSmallPowerLimit);
696 adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =
697 le16_to_cpu(pt->usLowCACLeakage);
698 adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =
699 le16_to_cpu(pt->usHighCACLeakage);
700 }
701 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) &&
702 ext_hdr->usSclkVddgfxTableOffset) {
703 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
704 (mode_info->atom_context->bios + data_offset +
705 le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset));
706 ret = amdgpu_parse_clk_voltage_dep_table(
707 &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
708 dep_table);
709 if (ret) {
710 kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
711 return ret;
712 }
713 }
714 }
715
716 return 0;
717}
718
719void amdgpu_free_extended_power_table(struct amdgpu_device *adev)
720{
721 struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
722
723 kfree(dyn_state->vddc_dependency_on_sclk.entries);
724 kfree(dyn_state->vddci_dependency_on_mclk.entries);
725 kfree(dyn_state->vddc_dependency_on_mclk.entries);
726 kfree(dyn_state->mvdd_dependency_on_mclk.entries);
727 kfree(dyn_state->cac_leakage_table.entries);
728 kfree(dyn_state->phase_shedding_limits_table.entries);
729 kfree(dyn_state->ppm_table);
730 kfree(dyn_state->cac_tdp_table);
731 kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
732 kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
733 kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
734 kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
735 kfree(dyn_state->vddgfx_dependency_on_sclk.entries);
736}
737
738static const char *pp_lib_thermal_controller_names[] = {
739 "NONE",
740 "lm63",
741 "adm1032",
742 "adm1030",
743 "max6649",
744 "lm64",
745 "f75375",
746 "RV6xx",
747 "RV770",
748 "adt7473",
749 "NONE",
750 "External GPIO",
751 "Evergreen",
752 "emc2103",
753 "Sumo",
754 "Northern Islands",
755 "Southern Islands",
756 "lm96163",
757 "Sea Islands",
758 "Kaveri/Kabini",
759};
760
761void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
762{
763 struct amdgpu_mode_info *mode_info = &adev->mode_info;
764 ATOM_PPLIB_POWERPLAYTABLE *power_table;
765 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
766 ATOM_PPLIB_THERMALCONTROLLER *controller;
767 struct amdgpu_i2c_bus_rec i2c_bus;
768 u16 data_offset;
769 u8 frev, crev;
770
771 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
772 &frev, &crev, &data_offset))
773 return;
774 power_table = (ATOM_PPLIB_POWERPLAYTABLE *)
775 (mode_info->atom_context->bios + data_offset);
776 controller = &power_table->sThermalController;
777
778 /* add the i2c bus for thermal/fan chip */
779 if (controller->ucType > 0) {
780 if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
781 adev->pm.no_fan = true;
782 adev->pm.fan_pulses_per_revolution =
783 controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
784 if (adev->pm.fan_pulses_per_revolution) {
785 adev->pm.fan_min_rpm = controller->ucFanMinRPM;
786 adev->pm.fan_max_rpm = controller->ucFanMaxRPM;
787 }
788 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
789 DRM_INFO("Internal thermal controller %s fan control\n",
790 (controller->ucFanParameters &
791 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
792 adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
793 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
794 DRM_INFO("Internal thermal controller %s fan control\n",
795 (controller->ucFanParameters &
796 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
797 adev->pm.int_thermal_type = THERMAL_TYPE_RV770;
798 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
799 DRM_INFO("Internal thermal controller %s fan control\n",
800 (controller->ucFanParameters &
801 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
802 adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
803 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
804 DRM_INFO("Internal thermal controller %s fan control\n",
805 (controller->ucFanParameters &
806 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
807 adev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
808 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
809 DRM_INFO("Internal thermal controller %s fan control\n",
810 (controller->ucFanParameters &
811 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
812 adev->pm.int_thermal_type = THERMAL_TYPE_NI;
813 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
814 DRM_INFO("Internal thermal controller %s fan control\n",
815 (controller->ucFanParameters &
816 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
817 adev->pm.int_thermal_type = THERMAL_TYPE_SI;
818 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
819 DRM_INFO("Internal thermal controller %s fan control\n",
820 (controller->ucFanParameters &
821 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
822 adev->pm.int_thermal_type = THERMAL_TYPE_CI;
823 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
824 DRM_INFO("Internal thermal controller %s fan control\n",
825 (controller->ucFanParameters &
826 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
827 adev->pm.int_thermal_type = THERMAL_TYPE_KV;
828 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
829 DRM_INFO("External GPIO thermal controller %s fan control\n",
830 (controller->ucFanParameters &
831 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
832 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
833 } else if (controller->ucType ==
834 ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
835 DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
836 (controller->ucFanParameters &
837 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
838 adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
839 } else if (controller->ucType ==
840 ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
841 DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
842 (controller->ucFanParameters &
843 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
844 adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
845 } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
846 DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
847 pp_lib_thermal_controller_names[controller->ucType],
848 controller->ucI2cAddress >> 1,
849 (controller->ucFanParameters &
850 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
851 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
852 i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine);
853 adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus);
854 if (adev->pm.i2c_bus) {
855 struct i2c_board_info info = { };
856 const char *name = pp_lib_thermal_controller_names[controller->ucType];
857 info.addr = controller->ucI2cAddress >> 1;
858 strlcpy(info.type, name, sizeof(info.type));
859 i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info);
860 }
861 } else {
862 DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
863 controller->ucType,
864 controller->ucI2cAddress >> 1,
865 (controller->ucFanParameters &
866 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
867 }
868 }
869}
870
871enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev,
872 u32 sys_mask,
873 enum amdgpu_pcie_gen asic_gen,
874 enum amdgpu_pcie_gen default_gen)
875{
876 switch (asic_gen) {
877 case AMDGPU_PCIE_GEN1:
878 return AMDGPU_PCIE_GEN1;
879 case AMDGPU_PCIE_GEN2:
880 return AMDGPU_PCIE_GEN2;
881 case AMDGPU_PCIE_GEN3:
882 return AMDGPU_PCIE_GEN3;
883 default:
884 if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) &&
885 (default_gen == AMDGPU_PCIE_GEN3))
886 return AMDGPU_PCIE_GEN3;
887 else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) &&
888 (default_gen == AMDGPU_PCIE_GEN2))
889 return AMDGPU_PCIE_GEN2;
890 else
891 return AMDGPU_PCIE_GEN1;
892 }
893 return AMDGPU_PCIE_GEN1;
894}
895
896struct amd_vce_state*
897amdgpu_get_vce_clock_state(void *handle, u32 idx)
898{
899 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
900
901 if (idx < adev->pm.dpm.num_of_vce_states)
902 return &adev->pm.dpm.vce_states[idx];
903
904 return NULL;
905}
906
907int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
908{
909 uint32_t clk_freq;
910 int ret = 0;
911 if (is_support_sw_smu(adev)) {
912 ret = smu_get_dpm_freq_range(&adev->smu, SMU_GFXCLK,
913 low ? &clk_freq : NULL,
914 !low ? &clk_freq : NULL);
915 if (ret)
916 return 0;
917 return clk_freq * 100;
918
919 } else {
920 return (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (low));
921 }
922}
923
924int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low)
925{
926 uint32_t clk_freq;
927 int ret = 0;
928 if (is_support_sw_smu(adev)) {
929 ret = smu_get_dpm_freq_range(&adev->smu, SMU_UCLK,
930 low ? &clk_freq : NULL,
931 !low ? &clk_freq : NULL);
932 if (ret)
933 return 0;
934 return clk_freq * 100;
935
936 } else {
937 return (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (low));
938 }
939}
940
941int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate)
942{
943 int ret = 0;
944 bool swsmu = is_support_sw_smu(adev);
945
946 switch (block_type) {
947 case AMD_IP_BLOCK_TYPE_UVD:
948 case AMD_IP_BLOCK_TYPE_VCE:
949 if (swsmu) {
950 ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
951 } else if (adev->powerplay.pp_funcs &&
952 adev->powerplay.pp_funcs->set_powergating_by_smu) {
953 /*
954 * TODO: need a better lock mechanism
955 *
956 * Here adev->pm.mutex lock protection is enforced on
957 * UVD and VCE cases only. Since for other cases, there
958 * may be already lock protection in amdgpu_pm.c.
959 * This is a quick fix for the deadlock issue below.
960 * NFO: task ocltst:2028 blocked for more than 120 seconds.
961 * Tainted: G OE 5.0.0-37-generic #40~18.04.1-Ubuntu
962 * echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
963 * cltst D 0 2028 2026 0x00000000
964 * all Trace:
965 * __schedule+0x2c0/0x870
966 * schedule+0x2c/0x70
967 * schedule_preempt_disabled+0xe/0x10
968 * __mutex_lock.isra.9+0x26d/0x4e0
969 * __mutex_lock_slowpath+0x13/0x20
970 * ? __mutex_lock_slowpath+0x13/0x20
971 * mutex_lock+0x2f/0x40
972 * amdgpu_dpm_set_powergating_by_smu+0x64/0xe0 [amdgpu]
973 * gfx_v8_0_enable_gfx_static_mg_power_gating+0x3c/0x70 [amdgpu]
974 * gfx_v8_0_set_powergating_state+0x66/0x260 [amdgpu]
975 * amdgpu_device_ip_set_powergating_state+0x62/0xb0 [amdgpu]
976 * pp_dpm_force_performance_level+0xe7/0x100 [amdgpu]
977 * amdgpu_set_dpm_forced_performance_level+0x129/0x330 [amdgpu]
978 */
979 mutex_lock(&adev->pm.mutex);
980 ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
981 (adev)->powerplay.pp_handle, block_type, gate));
982 mutex_unlock(&adev->pm.mutex);
983 }
984 break;
985 case AMD_IP_BLOCK_TYPE_GFX:
986 case AMD_IP_BLOCK_TYPE_VCN:
987 case AMD_IP_BLOCK_TYPE_SDMA:
988 if (swsmu)
989 ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
990 else if (adev->powerplay.pp_funcs &&
991 adev->powerplay.pp_funcs->set_powergating_by_smu)
992 ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
993 (adev)->powerplay.pp_handle, block_type, gate));
994 break;
995 case AMD_IP_BLOCK_TYPE_JPEG:
996 if (swsmu)
997 ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
998 break;
999 case AMD_IP_BLOCK_TYPE_GMC:
1000 case AMD_IP_BLOCK_TYPE_ACP:
1001 if (adev->powerplay.pp_funcs &&
1002 adev->powerplay.pp_funcs->set_powergating_by_smu)
1003 ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
1004 (adev)->powerplay.pp_handle, block_type, gate));
1005 break;
1006 default:
1007 break;
1008 }
1009
1010 return ret;
1011}
1012
1013int amdgpu_dpm_baco_enter(struct amdgpu_device *adev)
1014{
1015 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1016 void *pp_handle = adev->powerplay.pp_handle;
1017 struct smu_context *smu = &adev->smu;
1018 int ret = 0;
1019
1020 if (is_support_sw_smu(adev)) {
1021 ret = smu_baco_enter(smu);
1022 } else {
1023 if (!pp_funcs || !pp_funcs->set_asic_baco_state)
1024 return -ENOENT;
1025
1026 /* enter BACO state */
1027 ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
1028 }
1029
1030 return ret;
1031}
1032
1033int amdgpu_dpm_baco_exit(struct amdgpu_device *adev)
1034{
1035 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1036 void *pp_handle = adev->powerplay.pp_handle;
1037 struct smu_context *smu = &adev->smu;
1038 int ret = 0;
1039
1040 if (is_support_sw_smu(adev)) {
1041 ret = smu_baco_exit(smu);
1042 } else {
1043 if (!pp_funcs || !pp_funcs->set_asic_baco_state)
1044 return -ENOENT;
1045
1046 /* exit BACO state */
1047 ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
1048 }
1049
1050 return ret;
1051}
1052
1053int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
1054 enum pp_mp1_state mp1_state)
1055{
1056 int ret = 0;
1057
1058 if (is_support_sw_smu(adev)) {
1059 ret = smu_set_mp1_state(&adev->smu, mp1_state);
1060 } else if (adev->powerplay.pp_funcs &&
1061 adev->powerplay.pp_funcs->set_mp1_state) {
1062 ret = adev->powerplay.pp_funcs->set_mp1_state(
1063 adev->powerplay.pp_handle,
1064 mp1_state);
1065 }
1066
1067 return ret;
1068}
1069
1070bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev)
1071{
1072 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1073 void *pp_handle = adev->powerplay.pp_handle;
1074 struct smu_context *smu = &adev->smu;
1075 bool baco_cap;
1076
1077 if (is_support_sw_smu(adev)) {
1078 return smu_baco_is_support(smu);
1079 } else {
1080 if (!pp_funcs || !pp_funcs->get_asic_baco_capability)
1081 return false;
1082
1083 if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap))
1084 return false;
1085
1086 return baco_cap ? true : false;
1087 }
1088}
1089
1090int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev)
1091{
1092 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1093 void *pp_handle = adev->powerplay.pp_handle;
1094 struct smu_context *smu = &adev->smu;
1095
1096 if (is_support_sw_smu(adev)) {
1097 return smu_mode2_reset(smu);
1098 } else {
1099 if (!pp_funcs || !pp_funcs->asic_reset_mode_2)
1100 return -ENOENT;
1101
1102 return pp_funcs->asic_reset_mode_2(pp_handle);
1103 }
1104}
1105
1106int amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
1107{
1108 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1109 void *pp_handle = adev->powerplay.pp_handle;
1110 struct smu_context *smu = &adev->smu;
1111 int ret = 0;
1112
1113 dev_info(adev->dev, "GPU BACO reset\n");
1114
1115 if (is_support_sw_smu(adev)) {
1116 ret = smu_baco_enter(smu);
1117 if (ret)
1118 return ret;
1119
1120 ret = smu_baco_exit(smu);
1121 if (ret)
1122 return ret;
1123 } else {
1124 if (!pp_funcs
1125 || !pp_funcs->set_asic_baco_state)
1126 return -ENOENT;
1127
1128 /* enter BACO state */
1129 ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
1130 if (ret)
1131 return ret;
1132
1133 /* exit BACO state */
1134 ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
1135 if (ret)
1136 return ret;
1137 }
1138
1139 return 0;
1140}
1141
1142bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev)
1143{
1144 struct smu_context *smu = &adev->smu;
1145
1146 if (is_support_sw_smu(adev))
1147 return smu_mode1_reset_is_support(smu);
1148
1149 return false;
1150}
1151
1152int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev)
1153{
1154 struct smu_context *smu = &adev->smu;
1155
1156 if (is_support_sw_smu(adev))
1157 return smu_mode1_reset(smu);
1158
1159 return -EOPNOTSUPP;
1160}
1161
1162int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
1163 enum PP_SMC_POWER_PROFILE type,
1164 bool en)
1165{
1166 int ret = 0;
1167
1168 if (is_support_sw_smu(adev))
1169 ret = smu_switch_power_profile(&adev->smu, type, en);
1170 else if (adev->powerplay.pp_funcs &&
1171 adev->powerplay.pp_funcs->switch_power_profile)
1172 ret = adev->powerplay.pp_funcs->switch_power_profile(
1173 adev->powerplay.pp_handle, type, en);
1174
1175 return ret;
1176}
1177
1178int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
1179 uint32_t pstate)
1180{
1181 int ret = 0;
1182
1183 if (is_support_sw_smu(adev))
1184 ret = smu_set_xgmi_pstate(&adev->smu, pstate);
1185 else if (adev->powerplay.pp_funcs &&
1186 adev->powerplay.pp_funcs->set_xgmi_pstate)
1187 ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle,
1188 pstate);
1189
1190 return ret;
1191}
1192
1193int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev,
1194 uint32_t cstate)
1195{
1196 int ret = 0;
1197 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1198 void *pp_handle = adev->powerplay.pp_handle;
1199 struct smu_context *smu = &adev->smu;
1200
1201 if (is_support_sw_smu(adev))
1202 ret = smu_set_df_cstate(smu, cstate);
1203 else if (pp_funcs &&
1204 pp_funcs->set_df_cstate)
1205 ret = pp_funcs->set_df_cstate(pp_handle, cstate);
1206
1207 return ret;
1208}
1209
1210int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en)
1211{
1212 struct smu_context *smu = &adev->smu;
1213
1214 if (is_support_sw_smu(adev))
1215 return smu_allow_xgmi_power_down(smu, en);
1216
1217 return 0;
1218}