xref: /dragonfly/sys/dev/drm/amd/amdgpu/amdgpu_dpm.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
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 #include "amd_pcie.h"
32 
amdgpu_dpm_print_class_info(u32 class,u32 class2)33 void amdgpu_dpm_print_class_info(u32 class, u32 class2)
34 {
35           const char *s;
36 
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;
51           }
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");
90           }
91           pr_cont("\n");
92 }
93 
amdgpu_dpm_print_cap_info(u32 caps)94 void amdgpu_dpm_print_cap_info(u32 caps)
95 {
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");
104 }
105 
amdgpu_dpm_print_ps_status(struct amdgpu_device * adev,struct amdgpu_ps * rps)106 void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
107                                         struct amdgpu_ps *rps)
108 {
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");
117 }
118 
amdgpu_dpm_get_active_displays(struct amdgpu_device * adev)119 void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
120 {
121           struct drm_device *ddev = adev->ddev;
122           struct drm_crtc *crtc;
123           struct amdgpu_crtc *amdgpu_crtc;
124 
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++;
134                               }
135                     }
136           }
137 }
138 
139 
amdgpu_dpm_get_vblank_time(struct amdgpu_device * adev)140 u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
141 {
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 */
147 
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));
157 
158                                         vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
159                                         break;
160                               }
161                     }
162           }
163 
164           return vblank_time_us;
165 }
166 
amdgpu_dpm_get_vrefresh(struct amdgpu_device * adev)167 u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
168 {
169           struct drm_device *dev = adev->ddev;
170           struct drm_crtc *crtc;
171           struct amdgpu_crtc *amdgpu_crtc;
172           u32 vrefresh = 0;
173 
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;
180                               }
181                     }
182           }
183 
184           return vrefresh;
185 }
186 
amdgpu_calculate_u_and_p(u32 i,u32 r_c,u32 p_b,u32 * p,u32 * u)187 void amdgpu_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
188                                     u32 *p, u32 *u)
189 {
190           u32 b_c = 0;
191           u32 i_c;
192           u32 tmp;
193 
194           i_c = (i * r_c) / 100;
195           tmp = i_c >> p_b;
196 
197           while (tmp) {
198                     b_c++;
199                     tmp >>= 1;
200           }
201 
202           *u = (b_c + 1) / 2;
203           *p = i_c / (1 << (2 * (*u)));
204 }
205 
amdgpu_calculate_at(u32 t,u32 h,u32 fh,u32 fl,u32 * tl,u32 * th)206 int amdgpu_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)
207 {
208           u32 k, a, ah, al;
209           u32 t1;
210 
211           if ((fl == 0) || (fh == 0) || (fl > fh))
212                     return -EINVAL;
213 
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;
220 
221           *th = t - ah;
222           *tl = t + al;
223 
224           return 0;
225 }
226 
amdgpu_is_uvd_state(u32 class,u32 class2)227 bool amdgpu_is_uvd_state(u32 class, u32 class2)
228 {
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;
240 }
241 
amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)242 bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
243 {
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;
262           }
263 }
264 
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;
274 };
275 
276 union fan_info {
277           struct _ATOM_PPLIB_FANTABLE fan;
278           struct _ATOM_PPLIB_FANTABLE2 fan2;
279           struct _ATOM_PPLIB_FANTABLE3 fan3;
280 };
281 
amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table * amdgpu_table,ATOM_PPLIB_Clock_Voltage_Dependency_Table * atom_table)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)
284 {
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;
289 
290           amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
291           if (!amdgpu_table->entries)
292                     return -ENOMEM;
293 
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));
301           }
302           amdgpu_table->count = atom_table->ucNumEntries;
303 
304           return 0;
305 }
306 
amdgpu_get_platform_caps(struct amdgpu_device * adev)307 int amdgpu_get_platform_caps(struct amdgpu_device *adev)
308 {
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;
314 
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);
319 
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);
323 
324           return 0;
325 }
326 
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
336 
amdgpu_parse_extended_power_table(struct amdgpu_device * adev)337 int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
338 {
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;
347 
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);
352 
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);
378                               }
379                               adev->pm.dpm.fan.ucode_fan_control = true;
380                     }
381           }
382 
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;
395                               }
396                     }
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;
406                               }
407                     }
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;
417                               }
418                     }
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;
428                               }
429                     }
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);
446                               }
447                     }
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;
454 
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;
462                               }
463 
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));
474                               }
475                               adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
476                                         psl->ucNumEntries;
477                     }
478           }
479 
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;
506                               }
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);
521                                         }
522                                         entry = (ATOM_PPLIB_CAC_Leakage_Record *)
523                                                   ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
524                               }
525                               adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
526                     }
527           }
528 
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;
561                               }
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));
578                               }
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));
596                               }
597                     }
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;
616                               }
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));
632                               }
633                     }
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;
648                               }
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));
659                               }
660                     }
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;
671                               }
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);
691                     }
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;
706                               }
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));
717                               }
718                     }
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;
729                               }
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;
743                               }
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);
756                     }
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;
768                               }
769                     }
770           }
771 
772           return 0;
773 }
774 
amdgpu_free_extended_power_table(struct amdgpu_device * adev)775 void amdgpu_free_extended_power_table(struct amdgpu_device *adev)
776 {
777           struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
778 
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);
792 }
793 
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",
815 };
816 
amdgpu_add_thermal_controller(struct amdgpu_device * adev)817 void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
818 {
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;
826 
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;
833 
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;
843                     }
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);
916                               }
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");
923                     }
924           }
925 }
926 
amdgpu_get_pcie_gen_support(struct amdgpu_device * adev,u32 sys_mask,enum amdgpu_pcie_gen asic_gen,enum amdgpu_pcie_gen default_gen)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)
931 {
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;
948           }
949           return AMDGPU_PCIE_GEN1;
950 }
951 
amdgpu_get_pcie_lane_support(struct amdgpu_device * adev,u16 asic_lanes,u16 default_lanes)952 u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev,
953                                          u16 asic_lanes,
954                                          u16 default_lanes)
955 {
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;
972           }
973 }
974 
amdgpu_encode_pci_lane_width(u32 lanes)975 u8 amdgpu_encode_pci_lane_width(u32 lanes)
976 {
977           u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 };
978 
979           if (lanes > 16)
980                     return 0;
981 
982           return encoded_lanes[lanes];
983 }
984 
985 struct amd_vce_state*
amdgpu_get_vce_clock_state(void * handle,u32 idx)986 amdgpu_get_vce_clock_state(void *handle, u32 idx)
987 {
988           struct amdgpu_device *adev = (struct amdgpu_device *)handle;
989 
990           if (idx < adev->pm.dpm.num_of_vce_states)
991                     return &adev->pm.dpm.vce_states[idx];
992 
993           return NULL;
994 }
995