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