Linux 4.19.133
[linux/fpc-iii.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_dpm.c
blob1c4595562f8fd29bc682764265e5d2fd472b1f2c
1 /*
2 * Copyright 2011 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Authors: Alex Deucher
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 #include "amd_pcie.h"
33 void amdgpu_dpm_print_class_info(u32 class, u32 class2)
35 const char *s;
37 switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
38 case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
39 default:
40 s = "none";
41 break;
42 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
43 s = "battery";
44 break;
45 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
46 s = "balanced";
47 break;
48 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
49 s = "performance";
50 break;
52 printk("\tui class: %s\n", s);
53 printk("\tinternal class:");
54 if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&
55 (class2 == 0))
56 pr_cont(" none");
57 else {
58 if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)
59 pr_cont(" boot");
60 if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
61 pr_cont(" thermal");
62 if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
63 pr_cont(" limited_pwr");
64 if (class & ATOM_PPLIB_CLASSIFICATION_REST)
65 pr_cont(" rest");
66 if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)
67 pr_cont(" forced");
68 if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
69 pr_cont(" 3d_perf");
70 if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
71 pr_cont(" ovrdrv");
72 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
73 pr_cont(" uvd");
74 if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)
75 pr_cont(" 3d_low");
76 if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)
77 pr_cont(" acpi");
78 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
79 pr_cont(" uvd_hd2");
80 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
81 pr_cont(" uvd_hd");
82 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
83 pr_cont(" uvd_sd");
84 if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
85 pr_cont(" limited_pwr2");
86 if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
87 pr_cont(" ulv");
88 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
89 pr_cont(" uvd_mvc");
91 pr_cont("\n");
94 void amdgpu_dpm_print_cap_info(u32 caps)
96 printk("\tcaps:");
97 if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
98 pr_cont(" single_disp");
99 if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)
100 pr_cont(" video");
101 if (caps & ATOM_PPLIB_DISALLOW_ON_DC)
102 pr_cont(" no_dc");
103 pr_cont("\n");
106 void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
107 struct amdgpu_ps *rps)
109 printk("\tstatus:");
110 if (rps == adev->pm.dpm.current_ps)
111 pr_cont(" c");
112 if (rps == adev->pm.dpm.requested_ps)
113 pr_cont(" r");
114 if (rps == adev->pm.dpm.boot_ps)
115 pr_cont(" b");
116 pr_cont("\n");
119 void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
121 struct drm_device *ddev = adev->ddev;
122 struct drm_crtc *crtc;
123 struct amdgpu_crtc *amdgpu_crtc;
125 adev->pm.dpm.new_active_crtcs = 0;
126 adev->pm.dpm.new_active_crtc_count = 0;
127 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
128 list_for_each_entry(crtc,
129 &ddev->mode_config.crtc_list, head) {
130 amdgpu_crtc = to_amdgpu_crtc(crtc);
131 if (amdgpu_crtc->enabled) {
132 adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
133 adev->pm.dpm.new_active_crtc_count++;
140 u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
142 struct drm_device *dev = adev->ddev;
143 struct drm_crtc *crtc;
144 struct amdgpu_crtc *amdgpu_crtc;
145 u32 vblank_in_pixels;
146 u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
148 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
149 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
150 amdgpu_crtc = to_amdgpu_crtc(crtc);
151 if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
152 vblank_in_pixels =
153 amdgpu_crtc->hw_mode.crtc_htotal *
154 (amdgpu_crtc->hw_mode.crtc_vblank_end -
155 amdgpu_crtc->hw_mode.crtc_vdisplay +
156 (amdgpu_crtc->v_border * 2));
158 vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
159 break;
164 return vblank_time_us;
167 u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
169 struct drm_device *dev = adev->ddev;
170 struct drm_crtc *crtc;
171 struct amdgpu_crtc *amdgpu_crtc;
172 u32 vrefresh = 0;
174 if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
175 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
176 amdgpu_crtc = to_amdgpu_crtc(crtc);
177 if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
178 vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
179 break;
184 return vrefresh;
187 void amdgpu_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
188 u32 *p, u32 *u)
190 u32 b_c = 0;
191 u32 i_c;
192 u32 tmp;
194 i_c = (i * r_c) / 100;
195 tmp = i_c >> p_b;
197 while (tmp) {
198 b_c++;
199 tmp >>= 1;
202 *u = (b_c + 1) / 2;
203 *p = i_c / (1 << (2 * (*u)));
206 int amdgpu_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)
208 u32 k, a, ah, al;
209 u32 t1;
211 if ((fl == 0) || (fh == 0) || (fl > fh))
212 return -EINVAL;
214 k = (100 * fh) / fl;
215 t1 = (t * (k - 100));
216 a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100));
217 a = (a + 5) / 10;
218 ah = ((a * t) + 5000) / 10000;
219 al = a - ah;
221 *th = t - ah;
222 *tl = t + al;
224 return 0;
227 bool amdgpu_is_uvd_state(u32 class, u32 class2)
229 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
230 return true;
231 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
232 return true;
233 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
234 return true;
235 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
236 return true;
237 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
238 return true;
239 return false;
242 bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
244 switch (sensor) {
245 case THERMAL_TYPE_RV6XX:
246 case THERMAL_TYPE_RV770:
247 case THERMAL_TYPE_EVERGREEN:
248 case THERMAL_TYPE_SUMO:
249 case THERMAL_TYPE_NI:
250 case THERMAL_TYPE_SI:
251 case THERMAL_TYPE_CI:
252 case THERMAL_TYPE_KV:
253 return true;
254 case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
255 case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
256 return false; /* need special handling */
257 case THERMAL_TYPE_NONE:
258 case THERMAL_TYPE_EXTERNAL:
259 case THERMAL_TYPE_EXTERNAL_GPIO:
260 default:
261 return false;
265 union power_info {
266 struct _ATOM_POWERPLAY_INFO info;
267 struct _ATOM_POWERPLAY_INFO_V2 info_2;
268 struct _ATOM_POWERPLAY_INFO_V3 info_3;
269 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
270 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
271 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
272 struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
273 struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
276 union fan_info {
277 struct _ATOM_PPLIB_FANTABLE fan;
278 struct _ATOM_PPLIB_FANTABLE2 fan2;
279 struct _ATOM_PPLIB_FANTABLE3 fan3;
282 static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table,
283 ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
285 u32 size = atom_table->ucNumEntries *
286 sizeof(struct amdgpu_clock_voltage_dependency_entry);
287 int i;
288 ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;
290 amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
291 if (!amdgpu_table->entries)
292 return -ENOMEM;
294 entry = &atom_table->entries[0];
295 for (i = 0; i < atom_table->ucNumEntries; i++) {
296 amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |
297 (entry->ucClockHigh << 16);
298 amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage);
299 entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)
300 ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
302 amdgpu_table->count = atom_table->ucNumEntries;
304 return 0;
307 int amdgpu_get_platform_caps(struct amdgpu_device *adev)
309 struct amdgpu_mode_info *mode_info = &adev->mode_info;
310 union power_info *power_info;
311 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
312 u16 data_offset;
313 u8 frev, crev;
315 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
316 &frev, &crev, &data_offset))
317 return -EINVAL;
318 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
320 adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
321 adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
322 adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
324 return 0;
327 /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
328 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
329 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
330 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
331 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
332 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
333 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
334 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
335 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
337 int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
339 struct amdgpu_mode_info *mode_info = &adev->mode_info;
340 union power_info *power_info;
341 union fan_info *fan_info;
342 ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
343 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
344 u16 data_offset;
345 u8 frev, crev;
346 int ret, i;
348 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
349 &frev, &crev, &data_offset))
350 return -EINVAL;
351 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
353 /* fan table */
354 if (le16_to_cpu(power_info->pplib.usTableSize) >=
355 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
356 if (power_info->pplib3.usFanTableOffset) {
357 fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
358 le16_to_cpu(power_info->pplib3.usFanTableOffset));
359 adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
360 adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
361 adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
362 adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
363 adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
364 adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
365 adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
366 if (fan_info->fan.ucFanTableFormat >= 2)
367 adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
368 else
369 adev->pm.dpm.fan.t_max = 10900;
370 adev->pm.dpm.fan.cycle_delay = 100000;
371 if (fan_info->fan.ucFanTableFormat >= 3) {
372 adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;
373 adev->pm.dpm.fan.default_max_fan_pwm =
374 le16_to_cpu(fan_info->fan3.usFanPWMMax);
375 adev->pm.dpm.fan.default_fan_output_sensitivity = 4836;
376 adev->pm.dpm.fan.fan_output_sensitivity =
377 le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);
379 adev->pm.dpm.fan.ucode_fan_control = true;
383 /* clock dependancy tables, shedding tables */
384 if (le16_to_cpu(power_info->pplib.usTableSize) >=
385 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
386 if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
387 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
388 (mode_info->atom_context->bios + data_offset +
389 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
390 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
391 dep_table);
392 if (ret) {
393 amdgpu_free_extended_power_table(adev);
394 return ret;
397 if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
398 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
399 (mode_info->atom_context->bios + data_offset +
400 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
401 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
402 dep_table);
403 if (ret) {
404 amdgpu_free_extended_power_table(adev);
405 return ret;
408 if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
409 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
410 (mode_info->atom_context->bios + data_offset +
411 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
412 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
413 dep_table);
414 if (ret) {
415 amdgpu_free_extended_power_table(adev);
416 return ret;
419 if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
420 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
421 (mode_info->atom_context->bios + data_offset +
422 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
423 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
424 dep_table);
425 if (ret) {
426 amdgpu_free_extended_power_table(adev);
427 return ret;
430 if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
431 ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
432 (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
433 (mode_info->atom_context->bios + data_offset +
434 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
435 if (clk_v->ucNumEntries) {
436 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
437 le16_to_cpu(clk_v->entries[0].usSclkLow) |
438 (clk_v->entries[0].ucSclkHigh << 16);
439 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
440 le16_to_cpu(clk_v->entries[0].usMclkLow) |
441 (clk_v->entries[0].ucMclkHigh << 16);
442 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
443 le16_to_cpu(clk_v->entries[0].usVddc);
444 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
445 le16_to_cpu(clk_v->entries[0].usVddci);
448 if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {
449 ATOM_PPLIB_PhaseSheddingLimits_Table *psl =
450 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
451 (mode_info->atom_context->bios + data_offset +
452 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));
453 ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
455 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
456 kcalloc(psl->ucNumEntries,
457 sizeof(struct amdgpu_phase_shedding_limits_entry),
458 GFP_KERNEL);
459 if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
460 amdgpu_free_extended_power_table(adev);
461 return -ENOMEM;
464 entry = &psl->entries[0];
465 for (i = 0; i < psl->ucNumEntries; i++) {
466 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =
467 le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);
468 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =
469 le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);
470 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =
471 le16_to_cpu(entry->usVoltage);
472 entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)
473 ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
475 adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
476 psl->ucNumEntries;
480 /* cac data */
481 if (le16_to_cpu(power_info->pplib.usTableSize) >=
482 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
483 adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
484 adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
485 adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit;
486 adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
487 if (adev->pm.dpm.tdp_od_limit)
488 adev->pm.dpm.power_control = true;
489 else
490 adev->pm.dpm.power_control = false;
491 adev->pm.dpm.tdp_adjustment = 0;
492 adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
493 adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
494 adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
495 if (power_info->pplib5.usCACLeakageTableOffset) {
496 ATOM_PPLIB_CAC_Leakage_Table *cac_table =
497 (ATOM_PPLIB_CAC_Leakage_Table *)
498 (mode_info->atom_context->bios + data_offset +
499 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
500 ATOM_PPLIB_CAC_Leakage_Record *entry;
501 u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
502 adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
503 if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
504 amdgpu_free_extended_power_table(adev);
505 return -ENOMEM;
507 entry = &cac_table->entries[0];
508 for (i = 0; i < cac_table->ucNumEntries; i++) {
509 if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
510 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =
511 le16_to_cpu(entry->usVddc1);
512 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =
513 le16_to_cpu(entry->usVddc2);
514 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =
515 le16_to_cpu(entry->usVddc3);
516 } else {
517 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
518 le16_to_cpu(entry->usVddc);
519 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
520 le32_to_cpu(entry->ulLeakageValue);
522 entry = (ATOM_PPLIB_CAC_Leakage_Record *)
523 ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
525 adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
529 /* ext tables */
530 if (le16_to_cpu(power_info->pplib.usTableSize) >=
531 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
532 ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
533 (mode_info->atom_context->bios + data_offset +
534 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
535 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
536 ext_hdr->usVCETableOffset) {
537 VCEClockInfoArray *array = (VCEClockInfoArray *)
538 (mode_info->atom_context->bios + data_offset +
539 le16_to_cpu(ext_hdr->usVCETableOffset) + 1);
540 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =
541 (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
542 (mode_info->atom_context->bios + data_offset +
543 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
544 1 + array->ucNumEntries * sizeof(VCEClockInfo));
545 ATOM_PPLIB_VCE_State_Table *states =
546 (ATOM_PPLIB_VCE_State_Table *)
547 (mode_info->atom_context->bios + data_offset +
548 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
549 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
550 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
551 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
552 ATOM_PPLIB_VCE_State_Record *state_entry;
553 VCEClockInfo *vce_clk;
554 u32 size = limits->numEntries *
555 sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
556 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
557 kzalloc(size, GFP_KERNEL);
558 if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
559 amdgpu_free_extended_power_table(adev);
560 return -ENOMEM;
562 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
563 limits->numEntries;
564 entry = &limits->entries[0];
565 state_entry = &states->entries[0];
566 for (i = 0; i < limits->numEntries; i++) {
567 vce_clk = (VCEClockInfo *)
568 ((u8 *)&array->entries[0] +
569 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
570 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
571 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
572 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =
573 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
574 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =
575 le16_to_cpu(entry->usVoltage);
576 entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
577 ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
579 adev->pm.dpm.num_of_vce_states =
580 states->numEntries > AMD_MAX_VCE_LEVELS ?
581 AMD_MAX_VCE_LEVELS : states->numEntries;
582 for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
583 vce_clk = (VCEClockInfo *)
584 ((u8 *)&array->entries[0] +
585 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
586 adev->pm.dpm.vce_states[i].evclk =
587 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
588 adev->pm.dpm.vce_states[i].ecclk =
589 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
590 adev->pm.dpm.vce_states[i].clk_idx =
591 state_entry->ucClockInfoIndex & 0x3f;
592 adev->pm.dpm.vce_states[i].pstate =
593 (state_entry->ucClockInfoIndex & 0xc0) >> 6;
594 state_entry = (ATOM_PPLIB_VCE_State_Record *)
595 ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
598 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
599 ext_hdr->usUVDTableOffset) {
600 UVDClockInfoArray *array = (UVDClockInfoArray *)
601 (mode_info->atom_context->bios + data_offset +
602 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);
603 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =
604 (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
605 (mode_info->atom_context->bios + data_offset +
606 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +
607 1 + (array->ucNumEntries * sizeof (UVDClockInfo)));
608 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;
609 u32 size = limits->numEntries *
610 sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
611 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
612 kzalloc(size, GFP_KERNEL);
613 if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
614 amdgpu_free_extended_power_table(adev);
615 return -ENOMEM;
617 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
618 limits->numEntries;
619 entry = &limits->entries[0];
620 for (i = 0; i < limits->numEntries; i++) {
621 UVDClockInfo *uvd_clk = (UVDClockInfo *)
622 ((u8 *)&array->entries[0] +
623 (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));
624 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =
625 le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);
626 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
627 le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
628 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
629 le16_to_cpu(entry->usVoltage);
630 entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
631 ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
634 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
635 ext_hdr->usSAMUTableOffset) {
636 ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
637 (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
638 (mode_info->atom_context->bios + data_offset +
639 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);
640 ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;
641 u32 size = limits->numEntries *
642 sizeof(struct amdgpu_clock_voltage_dependency_entry);
643 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
644 kzalloc(size, GFP_KERNEL);
645 if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
646 amdgpu_free_extended_power_table(adev);
647 return -ENOMEM;
649 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
650 limits->numEntries;
651 entry = &limits->entries[0];
652 for (i = 0; i < limits->numEntries; i++) {
653 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =
654 le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);
655 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =
656 le16_to_cpu(entry->usVoltage);
657 entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)
658 ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
661 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
662 ext_hdr->usPPMTableOffset) {
663 ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
664 (mode_info->atom_context->bios + data_offset +
665 le16_to_cpu(ext_hdr->usPPMTableOffset));
666 adev->pm.dpm.dyn_state.ppm_table =
667 kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
668 if (!adev->pm.dpm.dyn_state.ppm_table) {
669 amdgpu_free_extended_power_table(adev);
670 return -ENOMEM;
672 adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
673 adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
674 le16_to_cpu(ppm->usCpuCoreNumber);
675 adev->pm.dpm.dyn_state.ppm_table->platform_tdp =
676 le32_to_cpu(ppm->ulPlatformTDP);
677 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =
678 le32_to_cpu(ppm->ulSmallACPlatformTDP);
679 adev->pm.dpm.dyn_state.ppm_table->platform_tdc =
680 le32_to_cpu(ppm->ulPlatformTDC);
681 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =
682 le32_to_cpu(ppm->ulSmallACPlatformTDC);
683 adev->pm.dpm.dyn_state.ppm_table->apu_tdp =
684 le32_to_cpu(ppm->ulApuTDP);
685 adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =
686 le32_to_cpu(ppm->ulDGpuTDP);
687 adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =
688 le32_to_cpu(ppm->ulDGpuUlvPower);
689 adev->pm.dpm.dyn_state.ppm_table->tj_max =
690 le32_to_cpu(ppm->ulTjmax);
692 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
693 ext_hdr->usACPTableOffset) {
694 ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
695 (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
696 (mode_info->atom_context->bios + data_offset +
697 le16_to_cpu(ext_hdr->usACPTableOffset) + 1);
698 ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;
699 u32 size = limits->numEntries *
700 sizeof(struct amdgpu_clock_voltage_dependency_entry);
701 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
702 kzalloc(size, GFP_KERNEL);
703 if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
704 amdgpu_free_extended_power_table(adev);
705 return -ENOMEM;
707 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
708 limits->numEntries;
709 entry = &limits->entries[0];
710 for (i = 0; i < limits->numEntries; i++) {
711 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =
712 le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);
713 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =
714 le16_to_cpu(entry->usVoltage);
715 entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)
716 ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
719 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
720 ext_hdr->usPowerTuneTableOffset) {
721 u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
722 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
723 ATOM_PowerTune_Table *pt;
724 adev->pm.dpm.dyn_state.cac_tdp_table =
725 kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
726 if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
727 amdgpu_free_extended_power_table(adev);
728 return -ENOMEM;
730 if (rev > 0) {
731 ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
732 (mode_info->atom_context->bios + data_offset +
733 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
734 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
735 ppt->usMaximumPowerDeliveryLimit;
736 pt = &ppt->power_tune_table;
737 } else {
738 ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
739 (mode_info->atom_context->bios + data_offset +
740 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
741 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;
742 pt = &ppt->power_tune_table;
744 adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);
745 adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =
746 le16_to_cpu(pt->usConfigurableTDP);
747 adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);
748 adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =
749 le16_to_cpu(pt->usBatteryPowerLimit);
750 adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =
751 le16_to_cpu(pt->usSmallPowerLimit);
752 adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =
753 le16_to_cpu(pt->usLowCACLeakage);
754 adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =
755 le16_to_cpu(pt->usHighCACLeakage);
757 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) &&
758 ext_hdr->usSclkVddgfxTableOffset) {
759 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
760 (mode_info->atom_context->bios + data_offset +
761 le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset));
762 ret = amdgpu_parse_clk_voltage_dep_table(
763 &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
764 dep_table);
765 if (ret) {
766 kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
767 return ret;
772 return 0;
775 void amdgpu_free_extended_power_table(struct amdgpu_device *adev)
777 struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
779 kfree(dyn_state->vddc_dependency_on_sclk.entries);
780 kfree(dyn_state->vddci_dependency_on_mclk.entries);
781 kfree(dyn_state->vddc_dependency_on_mclk.entries);
782 kfree(dyn_state->mvdd_dependency_on_mclk.entries);
783 kfree(dyn_state->cac_leakage_table.entries);
784 kfree(dyn_state->phase_shedding_limits_table.entries);
785 kfree(dyn_state->ppm_table);
786 kfree(dyn_state->cac_tdp_table);
787 kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
788 kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
789 kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
790 kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
791 kfree(dyn_state->vddgfx_dependency_on_sclk.entries);
794 static const char *pp_lib_thermal_controller_names[] = {
795 "NONE",
796 "lm63",
797 "adm1032",
798 "adm1030",
799 "max6649",
800 "lm64",
801 "f75375",
802 "RV6xx",
803 "RV770",
804 "adt7473",
805 "NONE",
806 "External GPIO",
807 "Evergreen",
808 "emc2103",
809 "Sumo",
810 "Northern Islands",
811 "Southern Islands",
812 "lm96163",
813 "Sea Islands",
814 "Kaveri/Kabini",
817 void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
819 struct amdgpu_mode_info *mode_info = &adev->mode_info;
820 ATOM_PPLIB_POWERPLAYTABLE *power_table;
821 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
822 ATOM_PPLIB_THERMALCONTROLLER *controller;
823 struct amdgpu_i2c_bus_rec i2c_bus;
824 u16 data_offset;
825 u8 frev, crev;
827 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
828 &frev, &crev, &data_offset))
829 return;
830 power_table = (ATOM_PPLIB_POWERPLAYTABLE *)
831 (mode_info->atom_context->bios + data_offset);
832 controller = &power_table->sThermalController;
834 /* add the i2c bus for thermal/fan chip */
835 if (controller->ucType > 0) {
836 if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
837 adev->pm.no_fan = true;
838 adev->pm.fan_pulses_per_revolution =
839 controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
840 if (adev->pm.fan_pulses_per_revolution) {
841 adev->pm.fan_min_rpm = controller->ucFanMinRPM;
842 adev->pm.fan_max_rpm = controller->ucFanMaxRPM;
844 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
845 DRM_INFO("Internal thermal controller %s fan control\n",
846 (controller->ucFanParameters &
847 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
848 adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
849 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
850 DRM_INFO("Internal thermal controller %s fan control\n",
851 (controller->ucFanParameters &
852 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
853 adev->pm.int_thermal_type = THERMAL_TYPE_RV770;
854 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
855 DRM_INFO("Internal thermal controller %s fan control\n",
856 (controller->ucFanParameters &
857 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
858 adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
859 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
860 DRM_INFO("Internal thermal controller %s fan control\n",
861 (controller->ucFanParameters &
862 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
863 adev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
864 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
865 DRM_INFO("Internal thermal controller %s fan control\n",
866 (controller->ucFanParameters &
867 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
868 adev->pm.int_thermal_type = THERMAL_TYPE_NI;
869 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
870 DRM_INFO("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_SI;
874 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
875 DRM_INFO("Internal thermal controller %s fan control\n",
876 (controller->ucFanParameters &
877 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
878 adev->pm.int_thermal_type = THERMAL_TYPE_CI;
879 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
880 DRM_INFO("Internal thermal controller %s fan control\n",
881 (controller->ucFanParameters &
882 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
883 adev->pm.int_thermal_type = THERMAL_TYPE_KV;
884 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
885 DRM_INFO("External GPIO thermal controller %s fan control\n",
886 (controller->ucFanParameters &
887 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
888 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
889 } else if (controller->ucType ==
890 ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
891 DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
892 (controller->ucFanParameters &
893 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
894 adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
895 } else if (controller->ucType ==
896 ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
897 DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
898 (controller->ucFanParameters &
899 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
900 adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
901 } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
902 DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
903 pp_lib_thermal_controller_names[controller->ucType],
904 controller->ucI2cAddress >> 1,
905 (controller->ucFanParameters &
906 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
907 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
908 i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine);
909 adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus);
910 if (adev->pm.i2c_bus) {
911 struct i2c_board_info info = { };
912 const char *name = pp_lib_thermal_controller_names[controller->ucType];
913 info.addr = controller->ucI2cAddress >> 1;
914 strlcpy(info.type, name, sizeof(info.type));
915 i2c_new_device(&adev->pm.i2c_bus->adapter, &info);
917 } else {
918 DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
919 controller->ucType,
920 controller->ucI2cAddress >> 1,
921 (controller->ucFanParameters &
922 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
927 enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev,
928 u32 sys_mask,
929 enum amdgpu_pcie_gen asic_gen,
930 enum amdgpu_pcie_gen default_gen)
932 switch (asic_gen) {
933 case AMDGPU_PCIE_GEN1:
934 return AMDGPU_PCIE_GEN1;
935 case AMDGPU_PCIE_GEN2:
936 return AMDGPU_PCIE_GEN2;
937 case AMDGPU_PCIE_GEN3:
938 return AMDGPU_PCIE_GEN3;
939 default:
940 if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) &&
941 (default_gen == AMDGPU_PCIE_GEN3))
942 return AMDGPU_PCIE_GEN3;
943 else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) &&
944 (default_gen == AMDGPU_PCIE_GEN2))
945 return AMDGPU_PCIE_GEN2;
946 else
947 return AMDGPU_PCIE_GEN1;
949 return AMDGPU_PCIE_GEN1;
952 u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev,
953 u16 asic_lanes,
954 u16 default_lanes)
956 switch (asic_lanes) {
957 case 0:
958 default:
959 return default_lanes;
960 case 1:
961 return 1;
962 case 2:
963 return 2;
964 case 4:
965 return 4;
966 case 8:
967 return 8;
968 case 12:
969 return 12;
970 case 16:
971 return 16;
975 u8 amdgpu_encode_pci_lane_width(u32 lanes)
977 u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 };
979 if (lanes > 16)
980 return 0;
982 return encoded_lanes[lanes];
985 struct amd_vce_state*
986 amdgpu_get_vce_clock_state(void *handle, u32 idx)
988 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
990 if (idx < adev->pm.dpm.num_of_vce_states)
991 return &adev->pm.dpm.vce_states[idx];
993 return NULL;