xref: /dragonfly/sys/dev/drm/amd/amdgpu/amdgpu_dpm.c (revision 655933d6)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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*
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