Merge tag 'lkdtm-next' of https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / pm / legacy-dpm / legacy_dpm.c
1 /*
2  * Copyright 2021 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include "amdgpu.h"
24 #include "amdgpu_i2c.h"
25 #include "amdgpu_atombios.h"
26 #include "atom.h"
27 #include "amd_pcie.h"
28 #include "legacy_dpm.h"
29 #include "amdgpu_dpm_internal.h"
30 #include "amdgpu_display.h"
31
32 #define amdgpu_dpm_pre_set_power_state(adev) \
33                 ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle))
34
35 #define amdgpu_dpm_post_set_power_state(adev) \
36                 ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle))
37
38 #define amdgpu_dpm_display_configuration_changed(adev) \
39                 ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle))
40
41 #define amdgpu_dpm_print_power_state(adev, ps) \
42                 ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps)))
43
44 #define amdgpu_dpm_vblank_too_short(adev) \
45                 ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle))
46
47 #define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \
48                 ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal)))
49
50 void amdgpu_dpm_print_class_info(u32 class, u32 class2)
51 {
52         const char *s;
53
54         switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
55         case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
56         default:
57                 s = "none";
58                 break;
59         case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
60                 s = "battery";
61                 break;
62         case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
63                 s = "balanced";
64                 break;
65         case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
66                 s = "performance";
67                 break;
68         }
69         printk("\tui class: %s\n", s);
70         printk("\tinternal class:");
71         if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&
72             (class2 == 0))
73                 pr_cont(" none");
74         else {
75                 if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)
76                         pr_cont(" boot");
77                 if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
78                         pr_cont(" thermal");
79                 if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
80                         pr_cont(" limited_pwr");
81                 if (class & ATOM_PPLIB_CLASSIFICATION_REST)
82                         pr_cont(" rest");
83                 if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)
84                         pr_cont(" forced");
85                 if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
86                         pr_cont(" 3d_perf");
87                 if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
88                         pr_cont(" ovrdrv");
89                 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
90                         pr_cont(" uvd");
91                 if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)
92                         pr_cont(" 3d_low");
93                 if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)
94                         pr_cont(" acpi");
95                 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
96                         pr_cont(" uvd_hd2");
97                 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
98                         pr_cont(" uvd_hd");
99                 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
100                         pr_cont(" uvd_sd");
101                 if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
102                         pr_cont(" limited_pwr2");
103                 if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
104                         pr_cont(" ulv");
105                 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
106                         pr_cont(" uvd_mvc");
107         }
108         pr_cont("\n");
109 }
110
111 void amdgpu_dpm_print_cap_info(u32 caps)
112 {
113         printk("\tcaps:");
114         if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
115                 pr_cont(" single_disp");
116         if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)
117                 pr_cont(" video");
118         if (caps & ATOM_PPLIB_DISALLOW_ON_DC)
119                 pr_cont(" no_dc");
120         pr_cont("\n");
121 }
122
123 void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
124                                 struct amdgpu_ps *rps)
125 {
126         printk("\tstatus:");
127         if (rps == adev->pm.dpm.current_ps)
128                 pr_cont(" c");
129         if (rps == adev->pm.dpm.requested_ps)
130                 pr_cont(" r");
131         if (rps == adev->pm.dpm.boot_ps)
132                 pr_cont(" b");
133         pr_cont("\n");
134 }
135
136 void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
137 {
138         int i;
139
140         if (adev->powerplay.pp_funcs->print_power_state == NULL)
141                 return;
142
143         for (i = 0; i < adev->pm.dpm.num_ps; i++)
144                 amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]);
145
146 }
147
148 union power_info {
149         struct _ATOM_POWERPLAY_INFO info;
150         struct _ATOM_POWERPLAY_INFO_V2 info_2;
151         struct _ATOM_POWERPLAY_INFO_V3 info_3;
152         struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
153         struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
154         struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
155         struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
156         struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
157 };
158
159 int amdgpu_get_platform_caps(struct amdgpu_device *adev)
160 {
161         struct amdgpu_mode_info *mode_info = &adev->mode_info;
162         union power_info *power_info;
163         int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
164         u16 data_offset;
165         u8 frev, crev;
166
167         if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
168                                    &frev, &crev, &data_offset))
169                 return -EINVAL;
170         power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
171
172         adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
173         adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
174         adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
175
176         return 0;
177 }
178
179 union fan_info {
180         struct _ATOM_PPLIB_FANTABLE fan;
181         struct _ATOM_PPLIB_FANTABLE2 fan2;
182         struct _ATOM_PPLIB_FANTABLE3 fan3;
183 };
184
185 static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table,
186                                               ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
187 {
188         u32 size = atom_table->ucNumEntries *
189                 sizeof(struct amdgpu_clock_voltage_dependency_entry);
190         int i;
191         ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;
192
193         amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
194         if (!amdgpu_table->entries)
195                 return -ENOMEM;
196
197         entry = &atom_table->entries[0];
198         for (i = 0; i < atom_table->ucNumEntries; i++) {
199                 amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |
200                         (entry->ucClockHigh << 16);
201                 amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage);
202                 entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)
203                         ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
204         }
205         amdgpu_table->count = atom_table->ucNumEntries;
206
207         return 0;
208 }
209
210 /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
211 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
212 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
213 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
214 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
215 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
216 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
217 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
218 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
219
220 int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
221 {
222         struct amdgpu_mode_info *mode_info = &adev->mode_info;
223         union power_info *power_info;
224         union fan_info *fan_info;
225         ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
226         int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
227         u16 data_offset;
228         u8 frev, crev;
229         int ret, i;
230
231         if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
232                                    &frev, &crev, &data_offset))
233                 return -EINVAL;
234         power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
235
236         /* fan table */
237         if (le16_to_cpu(power_info->pplib.usTableSize) >=
238             sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
239                 if (power_info->pplib3.usFanTableOffset) {
240                         fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
241                                                       le16_to_cpu(power_info->pplib3.usFanTableOffset));
242                         adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
243                         adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
244                         adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
245                         adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
246                         adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
247                         adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
248                         adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
249                         if (fan_info->fan.ucFanTableFormat >= 2)
250                                 adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
251                         else
252                                 adev->pm.dpm.fan.t_max = 10900;
253                         adev->pm.dpm.fan.cycle_delay = 100000;
254                         if (fan_info->fan.ucFanTableFormat >= 3) {
255                                 adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;
256                                 adev->pm.dpm.fan.default_max_fan_pwm =
257                                         le16_to_cpu(fan_info->fan3.usFanPWMMax);
258                                 adev->pm.dpm.fan.default_fan_output_sensitivity = 4836;
259                                 adev->pm.dpm.fan.fan_output_sensitivity =
260                                         le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);
261                         }
262                         adev->pm.dpm.fan.ucode_fan_control = true;
263                 }
264         }
265
266         /* clock dependancy tables, shedding tables */
267         if (le16_to_cpu(power_info->pplib.usTableSize) >=
268             sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
269                 if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
270                         dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
271                                 (mode_info->atom_context->bios + data_offset +
272                                  le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
273                         ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
274                                                                  dep_table);
275                         if (ret) {
276                                 amdgpu_free_extended_power_table(adev);
277                                 return ret;
278                         }
279                 }
280                 if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
281                         dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
282                                 (mode_info->atom_context->bios + data_offset +
283                                  le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
284                         ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
285                                                                  dep_table);
286                         if (ret) {
287                                 amdgpu_free_extended_power_table(adev);
288                                 return ret;
289                         }
290                 }
291                 if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
292                         dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
293                                 (mode_info->atom_context->bios + data_offset +
294                                  le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
295                         ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
296                                                                  dep_table);
297                         if (ret) {
298                                 amdgpu_free_extended_power_table(adev);
299                                 return ret;
300                         }
301                 }
302                 if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
303                         dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
304                                 (mode_info->atom_context->bios + data_offset +
305                                  le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
306                         ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
307                                                                  dep_table);
308                         if (ret) {
309                                 amdgpu_free_extended_power_table(adev);
310                                 return ret;
311                         }
312                 }
313                 if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
314                         ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
315                                 (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
316                                 (mode_info->atom_context->bios + data_offset +
317                                  le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
318                         if (clk_v->ucNumEntries) {
319                                 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
320                                         le16_to_cpu(clk_v->entries[0].usSclkLow) |
321                                         (clk_v->entries[0].ucSclkHigh << 16);
322                                 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
323                                         le16_to_cpu(clk_v->entries[0].usMclkLow) |
324                                         (clk_v->entries[0].ucMclkHigh << 16);
325                                 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
326                                         le16_to_cpu(clk_v->entries[0].usVddc);
327                                 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
328                                         le16_to_cpu(clk_v->entries[0].usVddci);
329                         }
330                 }
331                 if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {
332                         ATOM_PPLIB_PhaseSheddingLimits_Table *psl =
333                                 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
334                                 (mode_info->atom_context->bios + data_offset +
335                                  le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));
336                         ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
337
338                         adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
339                                 kcalloc(psl->ucNumEntries,
340                                         sizeof(struct amdgpu_phase_shedding_limits_entry),
341                                         GFP_KERNEL);
342                         if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
343                                 amdgpu_free_extended_power_table(adev);
344                                 return -ENOMEM;
345                         }
346
347                         entry = &psl->entries[0];
348                         for (i = 0; i < psl->ucNumEntries; i++) {
349                                 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =
350                                         le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);
351                                 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =
352                                         le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);
353                                 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =
354                                         le16_to_cpu(entry->usVoltage);
355                                 entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)
356                                         ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
357                         }
358                         adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
359                                 psl->ucNumEntries;
360                 }
361         }
362
363         /* cac data */
364         if (le16_to_cpu(power_info->pplib.usTableSize) >=
365             sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
366                 adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
367                 adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
368                 adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit;
369                 adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
370                 if (adev->pm.dpm.tdp_od_limit)
371                         adev->pm.dpm.power_control = true;
372                 else
373                         adev->pm.dpm.power_control = false;
374                 adev->pm.dpm.tdp_adjustment = 0;
375                 adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
376                 adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
377                 adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
378                 if (power_info->pplib5.usCACLeakageTableOffset) {
379                         ATOM_PPLIB_CAC_Leakage_Table *cac_table =
380                                 (ATOM_PPLIB_CAC_Leakage_Table *)
381                                 (mode_info->atom_context->bios + data_offset +
382                                  le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
383                         ATOM_PPLIB_CAC_Leakage_Record *entry;
384                         u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
385                         adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
386                         if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
387                                 amdgpu_free_extended_power_table(adev);
388                                 return -ENOMEM;
389                         }
390                         entry = &cac_table->entries[0];
391                         for (i = 0; i < cac_table->ucNumEntries; i++) {
392                                 if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
393                                         adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =
394                                                 le16_to_cpu(entry->usVddc1);
395                                         adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =
396                                                 le16_to_cpu(entry->usVddc2);
397                                         adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =
398                                                 le16_to_cpu(entry->usVddc3);
399                                 } else {
400                                         adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
401                                                 le16_to_cpu(entry->usVddc);
402                                         adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
403                                                 le32_to_cpu(entry->ulLeakageValue);
404                                 }
405                                 entry = (ATOM_PPLIB_CAC_Leakage_Record *)
406                                         ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
407                         }
408                         adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
409                 }
410         }
411
412         /* ext tables */
413         if (le16_to_cpu(power_info->pplib.usTableSize) >=
414             sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
415                 ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
416                         (mode_info->atom_context->bios + data_offset +
417                          le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
418                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
419                         ext_hdr->usVCETableOffset) {
420                         VCEClockInfoArray *array = (VCEClockInfoArray *)
421                                 (mode_info->atom_context->bios + data_offset +
422                                  le16_to_cpu(ext_hdr->usVCETableOffset) + 1);
423                         ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =
424                                 (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
425                                 (mode_info->atom_context->bios + data_offset +
426                                  le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
427                                  1 + array->ucNumEntries * sizeof(VCEClockInfo));
428                         ATOM_PPLIB_VCE_State_Table *states =
429                                 (ATOM_PPLIB_VCE_State_Table *)
430                                 (mode_info->atom_context->bios + data_offset +
431                                  le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
432                                  1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
433                                  1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
434                         ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
435                         ATOM_PPLIB_VCE_State_Record *state_entry;
436                         VCEClockInfo *vce_clk;
437                         u32 size = limits->numEntries *
438                                 sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
439                         adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
440                                 kzalloc(size, GFP_KERNEL);
441                         if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
442                                 amdgpu_free_extended_power_table(adev);
443                                 return -ENOMEM;
444                         }
445                         adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
446                                 limits->numEntries;
447                         entry = &limits->entries[0];
448                         state_entry = &states->entries[0];
449                         for (i = 0; i < limits->numEntries; i++) {
450                                 vce_clk = (VCEClockInfo *)
451                                         ((u8 *)&array->entries[0] +
452                                          (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
453                                 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
454                                         le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
455                                 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =
456                                         le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
457                                 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =
458                                         le16_to_cpu(entry->usVoltage);
459                                 entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
460                                         ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
461                         }
462                         adev->pm.dpm.num_of_vce_states =
463                                         states->numEntries > AMD_MAX_VCE_LEVELS ?
464                                         AMD_MAX_VCE_LEVELS : states->numEntries;
465                         for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
466                                 vce_clk = (VCEClockInfo *)
467                                         ((u8 *)&array->entries[0] +
468                                          (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
469                                 adev->pm.dpm.vce_states[i].evclk =
470                                         le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
471                                 adev->pm.dpm.vce_states[i].ecclk =
472                                         le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
473                                 adev->pm.dpm.vce_states[i].clk_idx =
474                                         state_entry->ucClockInfoIndex & 0x3f;
475                                 adev->pm.dpm.vce_states[i].pstate =
476                                         (state_entry->ucClockInfoIndex & 0xc0) >> 6;
477                                 state_entry = (ATOM_PPLIB_VCE_State_Record *)
478                                         ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
479                         }
480                 }
481                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
482                         ext_hdr->usUVDTableOffset) {
483                         UVDClockInfoArray *array = (UVDClockInfoArray *)
484                                 (mode_info->atom_context->bios + data_offset +
485                                  le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);
486                         ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =
487                                 (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
488                                 (mode_info->atom_context->bios + data_offset +
489                                  le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +
490                                  1 + (array->ucNumEntries * sizeof (UVDClockInfo)));
491                         ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;
492                         u32 size = limits->numEntries *
493                                 sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
494                         adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
495                                 kzalloc(size, GFP_KERNEL);
496                         if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
497                                 amdgpu_free_extended_power_table(adev);
498                                 return -ENOMEM;
499                         }
500                         adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
501                                 limits->numEntries;
502                         entry = &limits->entries[0];
503                         for (i = 0; i < limits->numEntries; i++) {
504                                 UVDClockInfo *uvd_clk = (UVDClockInfo *)
505                                         ((u8 *)&array->entries[0] +
506                                          (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));
507                                 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =
508                                         le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);
509                                 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
510                                         le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
511                                 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
512                                         le16_to_cpu(entry->usVoltage);
513                                 entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
514                                         ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
515                         }
516                 }
517                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
518                         ext_hdr->usSAMUTableOffset) {
519                         ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
520                                 (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
521                                 (mode_info->atom_context->bios + data_offset +
522                                  le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);
523                         ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;
524                         u32 size = limits->numEntries *
525                                 sizeof(struct amdgpu_clock_voltage_dependency_entry);
526                         adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
527                                 kzalloc(size, GFP_KERNEL);
528                         if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
529                                 amdgpu_free_extended_power_table(adev);
530                                 return -ENOMEM;
531                         }
532                         adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
533                                 limits->numEntries;
534                         entry = &limits->entries[0];
535                         for (i = 0; i < limits->numEntries; i++) {
536                                 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =
537                                         le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);
538                                 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =
539                                         le16_to_cpu(entry->usVoltage);
540                                 entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)
541                                         ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
542                         }
543                 }
544                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
545                     ext_hdr->usPPMTableOffset) {
546                         ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
547                                 (mode_info->atom_context->bios + data_offset +
548                                  le16_to_cpu(ext_hdr->usPPMTableOffset));
549                         adev->pm.dpm.dyn_state.ppm_table =
550                                 kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
551                         if (!adev->pm.dpm.dyn_state.ppm_table) {
552                                 amdgpu_free_extended_power_table(adev);
553                                 return -ENOMEM;
554                         }
555                         adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
556                         adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
557                                 le16_to_cpu(ppm->usCpuCoreNumber);
558                         adev->pm.dpm.dyn_state.ppm_table->platform_tdp =
559                                 le32_to_cpu(ppm->ulPlatformTDP);
560                         adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =
561                                 le32_to_cpu(ppm->ulSmallACPlatformTDP);
562                         adev->pm.dpm.dyn_state.ppm_table->platform_tdc =
563                                 le32_to_cpu(ppm->ulPlatformTDC);
564                         adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =
565                                 le32_to_cpu(ppm->ulSmallACPlatformTDC);
566                         adev->pm.dpm.dyn_state.ppm_table->apu_tdp =
567                                 le32_to_cpu(ppm->ulApuTDP);
568                         adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =
569                                 le32_to_cpu(ppm->ulDGpuTDP);
570                         adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =
571                                 le32_to_cpu(ppm->ulDGpuUlvPower);
572                         adev->pm.dpm.dyn_state.ppm_table->tj_max =
573                                 le32_to_cpu(ppm->ulTjmax);
574                 }
575                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
576                         ext_hdr->usACPTableOffset) {
577                         ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
578                                 (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
579                                 (mode_info->atom_context->bios + data_offset +
580                                  le16_to_cpu(ext_hdr->usACPTableOffset) + 1);
581                         ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;
582                         u32 size = limits->numEntries *
583                                 sizeof(struct amdgpu_clock_voltage_dependency_entry);
584                         adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
585                                 kzalloc(size, GFP_KERNEL);
586                         if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
587                                 amdgpu_free_extended_power_table(adev);
588                                 return -ENOMEM;
589                         }
590                         adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
591                                 limits->numEntries;
592                         entry = &limits->entries[0];
593                         for (i = 0; i < limits->numEntries; i++) {
594                                 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =
595                                         le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);
596                                 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =
597                                         le16_to_cpu(entry->usVoltage);
598                                 entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)
599                                         ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
600                         }
601                 }
602                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
603                         ext_hdr->usPowerTuneTableOffset) {
604                         u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
605                                          le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
606                         ATOM_PowerTune_Table *pt;
607                         adev->pm.dpm.dyn_state.cac_tdp_table =
608                                 kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
609                         if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
610                                 amdgpu_free_extended_power_table(adev);
611                                 return -ENOMEM;
612                         }
613                         if (rev > 0) {
614                                 ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
615                                         (mode_info->atom_context->bios + data_offset +
616                                          le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
617                                 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
618                                         ppt->usMaximumPowerDeliveryLimit;
619                                 pt = &ppt->power_tune_table;
620                         } else {
621                                 ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
622                                         (mode_info->atom_context->bios + data_offset +
623                                          le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
624                                 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;
625                                 pt = &ppt->power_tune_table;
626                         }
627                         adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);
628                         adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =
629                                 le16_to_cpu(pt->usConfigurableTDP);
630                         adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);
631                         adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =
632                                 le16_to_cpu(pt->usBatteryPowerLimit);
633                         adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =
634                                 le16_to_cpu(pt->usSmallPowerLimit);
635                         adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =
636                                 le16_to_cpu(pt->usLowCACLeakage);
637                         adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =
638                                 le16_to_cpu(pt->usHighCACLeakage);
639                 }
640                 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) &&
641                                 ext_hdr->usSclkVddgfxTableOffset) {
642                         dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
643                                 (mode_info->atom_context->bios + data_offset +
644                                  le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset));
645                         ret = amdgpu_parse_clk_voltage_dep_table(
646                                         &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
647                                         dep_table);
648                         if (ret) {
649                                 kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
650                                 return ret;
651                         }
652                 }
653         }
654
655         return 0;
656 }
657
658 void amdgpu_free_extended_power_table(struct amdgpu_device *adev)
659 {
660         struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
661
662         kfree(dyn_state->vddc_dependency_on_sclk.entries);
663         kfree(dyn_state->vddci_dependency_on_mclk.entries);
664         kfree(dyn_state->vddc_dependency_on_mclk.entries);
665         kfree(dyn_state->mvdd_dependency_on_mclk.entries);
666         kfree(dyn_state->cac_leakage_table.entries);
667         kfree(dyn_state->phase_shedding_limits_table.entries);
668         kfree(dyn_state->ppm_table);
669         kfree(dyn_state->cac_tdp_table);
670         kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
671         kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
672         kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
673         kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
674         kfree(dyn_state->vddgfx_dependency_on_sclk.entries);
675 }
676
677 static const char *pp_lib_thermal_controller_names[] = {
678         "NONE",
679         "lm63",
680         "adm1032",
681         "adm1030",
682         "max6649",
683         "lm64",
684         "f75375",
685         "RV6xx",
686         "RV770",
687         "adt7473",
688         "NONE",
689         "External GPIO",
690         "Evergreen",
691         "emc2103",
692         "Sumo",
693         "Northern Islands",
694         "Southern Islands",
695         "lm96163",
696         "Sea Islands",
697         "Kaveri/Kabini",
698 };
699
700 void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
701 {
702         struct amdgpu_mode_info *mode_info = &adev->mode_info;
703         ATOM_PPLIB_POWERPLAYTABLE *power_table;
704         int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
705         ATOM_PPLIB_THERMALCONTROLLER *controller;
706         struct amdgpu_i2c_bus_rec i2c_bus;
707         u16 data_offset;
708         u8 frev, crev;
709
710         if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
711                                    &frev, &crev, &data_offset))
712                 return;
713         power_table = (ATOM_PPLIB_POWERPLAYTABLE *)
714                 (mode_info->atom_context->bios + data_offset);
715         controller = &power_table->sThermalController;
716
717         /* add the i2c bus for thermal/fan chip */
718         if (controller->ucType > 0) {
719                 if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
720                         adev->pm.no_fan = true;
721                 adev->pm.fan_pulses_per_revolution =
722                         controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
723                 if (adev->pm.fan_pulses_per_revolution) {
724                         adev->pm.fan_min_rpm = controller->ucFanMinRPM;
725                         adev->pm.fan_max_rpm = controller->ucFanMaxRPM;
726                 }
727                 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
728                         DRM_INFO("Internal thermal controller %s fan control\n",
729                                  (controller->ucFanParameters &
730                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
731                         adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
732                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
733                         DRM_INFO("Internal thermal controller %s fan control\n",
734                                  (controller->ucFanParameters &
735                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
736                         adev->pm.int_thermal_type = THERMAL_TYPE_RV770;
737                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
738                         DRM_INFO("Internal thermal controller %s fan control\n",
739                                  (controller->ucFanParameters &
740                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
741                         adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
742                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
743                         DRM_INFO("Internal thermal controller %s fan control\n",
744                                  (controller->ucFanParameters &
745                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
746                         adev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
747                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
748                         DRM_INFO("Internal thermal controller %s fan control\n",
749                                  (controller->ucFanParameters &
750                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
751                         adev->pm.int_thermal_type = THERMAL_TYPE_NI;
752                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
753                         DRM_INFO("Internal thermal controller %s fan control\n",
754                                  (controller->ucFanParameters &
755                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
756                         adev->pm.int_thermal_type = THERMAL_TYPE_SI;
757                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
758                         DRM_INFO("Internal thermal controller %s fan control\n",
759                                  (controller->ucFanParameters &
760                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
761                         adev->pm.int_thermal_type = THERMAL_TYPE_CI;
762                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
763                         DRM_INFO("Internal thermal controller %s fan control\n",
764                                  (controller->ucFanParameters &
765                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
766                         adev->pm.int_thermal_type = THERMAL_TYPE_KV;
767                 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
768                         DRM_INFO("External GPIO thermal controller %s fan control\n",
769                                  (controller->ucFanParameters &
770                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
771                         adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
772                 } else if (controller->ucType ==
773                            ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
774                         DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
775                                  (controller->ucFanParameters &
776                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
777                         adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
778                 } else if (controller->ucType ==
779                            ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
780                         DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
781                                  (controller->ucFanParameters &
782                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
783                         adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
784                 } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
785                         DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
786                                  pp_lib_thermal_controller_names[controller->ucType],
787                                  controller->ucI2cAddress >> 1,
788                                  (controller->ucFanParameters &
789                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
790                         adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
791                         i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine);
792                         adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus);
793                         if (adev->pm.i2c_bus) {
794                                 struct i2c_board_info info = { };
795                                 const char *name = pp_lib_thermal_controller_names[controller->ucType];
796                                 info.addr = controller->ucI2cAddress >> 1;
797                                 strlcpy(info.type, name, sizeof(info.type));
798                                 i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info);
799                         }
800                 } else {
801                         DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
802                                  controller->ucType,
803                                  controller->ucI2cAddress >> 1,
804                                  (controller->ucFanParameters &
805                                   ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
806                 }
807         }
808 }
809
810 struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx)
811 {
812         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
813
814         if (idx < adev->pm.dpm.num_of_vce_states)
815                 return &adev->pm.dpm.vce_states[idx];
816
817         return NULL;
818 }
819
820 static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev,
821                                                      enum amd_pm_state_type dpm_state)
822 {
823         int i;
824         struct amdgpu_ps *ps;
825         u32 ui_class;
826         bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ?
827                 true : false;
828
829         /* check if the vblank period is too short to adjust the mclk */
830         if (single_display && adev->powerplay.pp_funcs->vblank_too_short) {
831                 if (amdgpu_dpm_vblank_too_short(adev))
832                         single_display = false;
833         }
834
835         /* certain older asics have a separare 3D performance state,
836          * so try that first if the user selected performance
837          */
838         if (dpm_state == POWER_STATE_TYPE_PERFORMANCE)
839                 dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF;
840         /* balanced states don't exist at the moment */
841         if (dpm_state == POWER_STATE_TYPE_BALANCED)
842                 dpm_state = POWER_STATE_TYPE_PERFORMANCE;
843
844 restart_search:
845         /* Pick the best power state based on current conditions */
846         for (i = 0; i < adev->pm.dpm.num_ps; i++) {
847                 ps = &adev->pm.dpm.ps[i];
848                 ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK;
849                 switch (dpm_state) {
850                 /* user states */
851                 case POWER_STATE_TYPE_BATTERY:
852                         if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) {
853                                 if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
854                                         if (single_display)
855                                                 return ps;
856                                 } else
857                                         return ps;
858                         }
859                         break;
860                 case POWER_STATE_TYPE_BALANCED:
861                         if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) {
862                                 if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
863                                         if (single_display)
864                                                 return ps;
865                                 } else
866                                         return ps;
867                         }
868                         break;
869                 case POWER_STATE_TYPE_PERFORMANCE:
870                         if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
871                                 if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
872                                         if (single_display)
873                                                 return ps;
874                                 } else
875                                         return ps;
876                         }
877                         break;
878                 /* internal states */
879                 case POWER_STATE_TYPE_INTERNAL_UVD:
880                         if (adev->pm.dpm.uvd_ps)
881                                 return adev->pm.dpm.uvd_ps;
882                         else
883                                 break;
884                 case POWER_STATE_TYPE_INTERNAL_UVD_SD:
885                         if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
886                                 return ps;
887                         break;
888                 case POWER_STATE_TYPE_INTERNAL_UVD_HD:
889                         if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
890                                 return ps;
891                         break;
892                 case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
893                         if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
894                                 return ps;
895                         break;
896                 case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
897                         if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
898                                 return ps;
899                         break;
900                 case POWER_STATE_TYPE_INTERNAL_BOOT:
901                         return adev->pm.dpm.boot_ps;
902                 case POWER_STATE_TYPE_INTERNAL_THERMAL:
903                         if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
904                                 return ps;
905                         break;
906                 case POWER_STATE_TYPE_INTERNAL_ACPI:
907                         if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI)
908                                 return ps;
909                         break;
910                 case POWER_STATE_TYPE_INTERNAL_ULV:
911                         if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
912                                 return ps;
913                         break;
914                 case POWER_STATE_TYPE_INTERNAL_3DPERF:
915                         if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
916                                 return ps;
917                         break;
918                 default:
919                         break;
920                 }
921         }
922         /* use a fallback state if we didn't match */
923         switch (dpm_state) {
924         case POWER_STATE_TYPE_INTERNAL_UVD_SD:
925                 dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD;
926                 goto restart_search;
927         case POWER_STATE_TYPE_INTERNAL_UVD_HD:
928         case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
929         case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
930                 if (adev->pm.dpm.uvd_ps) {
931                         return adev->pm.dpm.uvd_ps;
932                 } else {
933                         dpm_state = POWER_STATE_TYPE_PERFORMANCE;
934                         goto restart_search;
935                 }
936         case POWER_STATE_TYPE_INTERNAL_THERMAL:
937                 dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI;
938                 goto restart_search;
939         case POWER_STATE_TYPE_INTERNAL_ACPI:
940                 dpm_state = POWER_STATE_TYPE_BATTERY;
941                 goto restart_search;
942         case POWER_STATE_TYPE_BATTERY:
943         case POWER_STATE_TYPE_BALANCED:
944         case POWER_STATE_TYPE_INTERNAL_3DPERF:
945                 dpm_state = POWER_STATE_TYPE_PERFORMANCE;
946                 goto restart_search;
947         default:
948                 break;
949         }
950
951         return NULL;
952 }
953
954 static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
955 {
956         const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
957         struct amdgpu_ps *ps;
958         enum amd_pm_state_type dpm_state;
959         int ret;
960         bool equal = false;
961
962         /* if dpm init failed */
963         if (!adev->pm.dpm_enabled)
964                 return 0;
965
966         if (adev->pm.dpm.user_state != adev->pm.dpm.state) {
967                 /* add other state override checks here */
968                 if ((!adev->pm.dpm.thermal_active) &&
969                     (!adev->pm.dpm.uvd_active))
970                         adev->pm.dpm.state = adev->pm.dpm.user_state;
971         }
972         dpm_state = adev->pm.dpm.state;
973
974         ps = amdgpu_dpm_pick_power_state(adev, dpm_state);
975         if (ps)
976                 adev->pm.dpm.requested_ps = ps;
977         else
978                 return -EINVAL;
979
980         if (amdgpu_dpm == 1 && pp_funcs->print_power_state) {
981                 printk("switching from power state:\n");
982                 amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps);
983                 printk("switching to power state:\n");
984                 amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps);
985         }
986
987         /* update whether vce is active */
988         ps->vce_active = adev->pm.dpm.vce_active;
989         if (pp_funcs->display_configuration_changed)
990                 amdgpu_dpm_display_configuration_changed(adev);
991
992         ret = amdgpu_dpm_pre_set_power_state(adev);
993         if (ret)
994                 return ret;
995
996         if (pp_funcs->check_state_equal) {
997                 if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal))
998                         equal = false;
999         }
1000
1001         if (equal)
1002                 return 0;
1003
1004         if (pp_funcs->set_power_state)
1005                 pp_funcs->set_power_state(adev->powerplay.pp_handle);
1006
1007         amdgpu_dpm_post_set_power_state(adev);
1008
1009         adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
1010         adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
1011
1012         if (pp_funcs->force_performance_level) {
1013                 if (adev->pm.dpm.thermal_active) {
1014                         enum amd_dpm_forced_level level = adev->pm.dpm.forced_level;
1015                         /* force low perf level for thermal */
1016                         pp_funcs->force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW);
1017                         /* save the user's level */
1018                         adev->pm.dpm.forced_level = level;
1019                 } else {
1020                         /* otherwise, user selected level */
1021                         pp_funcs->force_performance_level(adev, adev->pm.dpm.forced_level);
1022                 }
1023         }
1024
1025         return 0;
1026 }
1027
1028 void amdgpu_legacy_dpm_compute_clocks(void *handle)
1029 {
1030         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1031
1032         amdgpu_dpm_get_active_displays(adev);
1033
1034         amdgpu_dpm_change_power_state_locked(adev);
1035 }
1036
1037 void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
1038 {
1039         struct amdgpu_device *adev =
1040                 container_of(work, struct amdgpu_device,
1041                              pm.dpm.thermal.work);
1042         const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1043         /* switch to the thermal state */
1044         enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
1045         int temp, size = sizeof(temp);
1046
1047         if (!adev->pm.dpm_enabled)
1048                 return;
1049
1050         if (!pp_funcs->read_sensor(adev->powerplay.pp_handle,
1051                                    AMDGPU_PP_SENSOR_GPU_TEMP,
1052                                    (void *)&temp,
1053                                    &size)) {
1054                 if (temp < adev->pm.dpm.thermal.min_temp)
1055                         /* switch back the user state */
1056                         dpm_state = adev->pm.dpm.user_state;
1057         } else {
1058                 if (adev->pm.dpm.thermal.high_to_low)
1059                         /* switch back the user state */
1060                         dpm_state = adev->pm.dpm.user_state;
1061         }
1062
1063         if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL)
1064                 adev->pm.dpm.thermal_active = true;
1065         else
1066                 adev->pm.dpm.thermal_active = false;
1067
1068         adev->pm.dpm.state = dpm_state;
1069
1070         amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle);
1071 }