xref: /linux/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
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.dpm.new_active_crtc_count < 2) ?
775 		true : false;
776 
777 	/* check if the vblank period is too short to adjust the mclk */
778 	if (single_display && adev->powerplay.pp_funcs->vblank_too_short) {
779 		if (amdgpu_dpm_vblank_too_short(adev))
780 			single_display = false;
781 	}
782 
783 	/* certain older asics have a separare 3D performance state,
784 	 * so try that first if the user selected performance
785 	 */
786 	if (dpm_state == POWER_STATE_TYPE_PERFORMANCE)
787 		dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF;
788 	/* balanced states don't exist at the moment */
789 	if (dpm_state == POWER_STATE_TYPE_BALANCED)
790 		dpm_state = POWER_STATE_TYPE_PERFORMANCE;
791 
792 restart_search:
793 	/* Pick the best power state based on current conditions */
794 	for (i = 0; i < adev->pm.dpm.num_ps; i++) {
795 		ps = &adev->pm.dpm.ps[i];
796 		ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK;
797 		switch (dpm_state) {
798 		/* user states */
799 		case POWER_STATE_TYPE_BATTERY:
800 			if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) {
801 				if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
802 					if (single_display)
803 						return ps;
804 				} else
805 					return ps;
806 			}
807 			break;
808 		case POWER_STATE_TYPE_PERFORMANCE:
809 			if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
810 				if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
811 					if (single_display)
812 						return ps;
813 				} else
814 					return ps;
815 			}
816 			break;
817 		/* internal states */
818 		case POWER_STATE_TYPE_INTERNAL_UVD:
819 			if (adev->pm.dpm.uvd_ps)
820 				return adev->pm.dpm.uvd_ps;
821 			else
822 				break;
823 		case POWER_STATE_TYPE_INTERNAL_UVD_SD:
824 			if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
825 				return ps;
826 			break;
827 		case POWER_STATE_TYPE_INTERNAL_UVD_HD:
828 			if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
829 				return ps;
830 			break;
831 		case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
832 			if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
833 				return ps;
834 			break;
835 		case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
836 			if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
837 				return ps;
838 			break;
839 		case POWER_STATE_TYPE_INTERNAL_BOOT:
840 			return adev->pm.dpm.boot_ps;
841 		case POWER_STATE_TYPE_INTERNAL_THERMAL:
842 			if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
843 				return ps;
844 			break;
845 		case POWER_STATE_TYPE_INTERNAL_ACPI:
846 			if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI)
847 				return ps;
848 			break;
849 		case POWER_STATE_TYPE_INTERNAL_ULV:
850 			if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
851 				return ps;
852 			break;
853 		case POWER_STATE_TYPE_INTERNAL_3DPERF:
854 			if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
855 				return ps;
856 			break;
857 		default:
858 			break;
859 		}
860 	}
861 	/* use a fallback state if we didn't match */
862 	switch (dpm_state) {
863 	case POWER_STATE_TYPE_INTERNAL_UVD_SD:
864 		dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD;
865 		goto restart_search;
866 	case POWER_STATE_TYPE_INTERNAL_UVD_HD:
867 	case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
868 	case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
869 		if (adev->pm.dpm.uvd_ps) {
870 			return adev->pm.dpm.uvd_ps;
871 		} else {
872 			dpm_state = POWER_STATE_TYPE_PERFORMANCE;
873 			goto restart_search;
874 		}
875 	case POWER_STATE_TYPE_INTERNAL_THERMAL:
876 		dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI;
877 		goto restart_search;
878 	case POWER_STATE_TYPE_INTERNAL_ACPI:
879 		dpm_state = POWER_STATE_TYPE_BATTERY;
880 		goto restart_search;
881 	case POWER_STATE_TYPE_BATTERY:
882 	case POWER_STATE_TYPE_BALANCED:
883 	case POWER_STATE_TYPE_INTERNAL_3DPERF:
884 		dpm_state = POWER_STATE_TYPE_PERFORMANCE;
885 		goto restart_search;
886 	default:
887 		break;
888 	}
889 
890 	return NULL;
891 }
892 
893 static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
894 {
895 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
896 	struct amdgpu_ps *ps;
897 	enum amd_pm_state_type dpm_state;
898 	int ret;
899 	bool equal = false;
900 
901 	/* if dpm init failed */
902 	if (!adev->pm.dpm_enabled)
903 		return 0;
904 
905 	if (adev->pm.dpm.user_state != adev->pm.dpm.state) {
906 		/* add other state override checks here */
907 		if ((!adev->pm.dpm.thermal_active) &&
908 		    (!adev->pm.dpm.uvd_active))
909 			adev->pm.dpm.state = adev->pm.dpm.user_state;
910 	}
911 	dpm_state = adev->pm.dpm.state;
912 
913 	ps = amdgpu_dpm_pick_power_state(adev, dpm_state);
914 	if (ps)
915 		adev->pm.dpm.requested_ps = ps;
916 	else
917 		return -EINVAL;
918 
919 	if (amdgpu_dpm == 1 && pp_funcs->print_power_state) {
920 		drm_dbg(adev_to_drm(adev), "switching from power state\n");
921 		amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps);
922 		drm_dbg(adev_to_drm(adev), "switching to power state\n");
923 		amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps);
924 	}
925 
926 	/* update whether vce is active */
927 	ps->vce_active = adev->pm.dpm.vce_active;
928 	if (pp_funcs->display_configuration_changed)
929 		amdgpu_dpm_display_configuration_changed(adev);
930 
931 	ret = amdgpu_dpm_pre_set_power_state(adev);
932 	if (ret)
933 		return ret;
934 
935 	if (pp_funcs->check_state_equal) {
936 		if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal))
937 			equal = false;
938 	}
939 
940 	if (equal)
941 		return 0;
942 
943 	if (pp_funcs->set_power_state)
944 		pp_funcs->set_power_state(adev->powerplay.pp_handle);
945 
946 	amdgpu_dpm_post_set_power_state(adev);
947 
948 	adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
949 	adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
950 
951 	if (pp_funcs->force_performance_level) {
952 		if (adev->pm.dpm.thermal_active) {
953 			enum amd_dpm_forced_level level = adev->pm.dpm.forced_level;
954 			/* force low perf level for thermal */
955 			pp_funcs->force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW);
956 			/* save the user's level */
957 			adev->pm.dpm.forced_level = level;
958 		} else {
959 			/* otherwise, user selected level */
960 			pp_funcs->force_performance_level(adev, adev->pm.dpm.forced_level);
961 		}
962 	}
963 
964 	return 0;
965 }
966 
967 void amdgpu_legacy_dpm_compute_clocks(void *handle)
968 {
969 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
970 
971 	amdgpu_dpm_get_active_displays(adev);
972 
973 	amdgpu_dpm_change_power_state_locked(adev);
974 }
975 
976 void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
977 {
978 	struct amdgpu_device *adev =
979 		container_of(work, struct amdgpu_device,
980 			     pm.dpm.thermal.work);
981 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
982 	/* switch to the thermal state */
983 	enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
984 	int temp, size = sizeof(temp);
985 
986 	mutex_lock(&adev->pm.mutex);
987 
988 	if (!adev->pm.dpm_enabled) {
989 		mutex_unlock(&adev->pm.mutex);
990 		return;
991 	}
992 	if (!pp_funcs->read_sensor(adev->powerplay.pp_handle,
993 				   AMDGPU_PP_SENSOR_GPU_TEMP,
994 				   (void *)&temp,
995 				   &size)) {
996 		if (temp < adev->pm.dpm.thermal.min_temp)
997 			/* switch back the user state */
998 			dpm_state = adev->pm.dpm.user_state;
999 	} else {
1000 		if (adev->pm.dpm.thermal.high_to_low)
1001 			/* switch back the user state */
1002 			dpm_state = adev->pm.dpm.user_state;
1003 	}
1004 
1005 	if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL)
1006 		adev->pm.dpm.thermal_active = true;
1007 	else
1008 		adev->pm.dpm.thermal_active = false;
1009 
1010 	adev->pm.dpm.state = dpm_state;
1011 
1012 	amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle);
1013 	mutex_unlock(&adev->pm.mutex);
1014 }
1015