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