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