drm/amd/powerplay: Allow duplicate enteries in pptable.
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / hwmgr / vega10_processpptables.c
CommitLineData
f83a9991
EH
1/*
2 * Copyright 2016 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 <linux/module.h>
24#include <linux/slab.h>
25#include <linux/fb.h>
26
27#include "vega10_processpptables.h"
28#include "ppatomfwctrl.h"
29#include "atomfirmware.h"
30#include "pp_debug.h"
31#include "cgs_common.h"
32#include "vega10_pptable.h"
33
34static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
35 enum phm_platform_caps cap)
36{
37 if (enable)
38 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
39 else
40 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
41}
42
43static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
44{
45 int index = GetIndexIntoMasterDataTable(powerplayinfo);
46
47 u16 size;
48 u8 frev, crev;
49 const void *table_address = hwmgr->soft_pp_table;
50
51 if (!table_address) {
52 table_address = (ATOM_Vega10_POWERPLAYTABLE *)
53 cgs_atom_get_data_table(hwmgr->device, index,
54 &size, &frev, &crev);
55
56 hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/
57 }
58
59 return table_address;
60}
61
62static int check_powerplay_tables(
63 struct pp_hwmgr *hwmgr,
64 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
65{
66 const ATOM_Vega10_State_Array *state_arrays;
67
68 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) +
69 le16_to_cpu(powerplay_table->usStateArrayOffset));
70
71 PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
72 ATOM_Vega10_TABLE_REVISION_VEGA10),
73 "Unsupported PPTable format!", return -1);
74 PP_ASSERT_WITH_CODE(powerplay_table->usStateArrayOffset,
75 "State table is not set!", return -1);
76 PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0,
77 "Invalid PowerPlay Table!", return -1);
78 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
79 "Invalid PowerPlay Table!", return -1);
80
81 return 0;
82}
83
84static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
85{
86 set_hw_cap(
87 hwmgr,
88 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY),
89 PHM_PlatformCaps_PowerPlaySupport);
90
91 set_hw_cap(
92 hwmgr,
93 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
94 PHM_PlatformCaps_BiosPowerSourceControl);
95
96 set_hw_cap(
97 hwmgr,
98 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC),
99 PHM_PlatformCaps_AutomaticDCTransition);
100
101 set_hw_cap(
102 hwmgr,
103 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_BACO),
104 PHM_PlatformCaps_BACO);
105
106 set_hw_cap(
107 hwmgr,
108 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
109 PHM_PlatformCaps_CombinePCCWithThermalSignal);
110
111 return 0;
112}
113
114static int init_thermal_controller(
115 struct pp_hwmgr *hwmgr,
116 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
117{
118 const ATOM_Vega10_Thermal_Controller *thermal_controller;
8250880e
RZ
119 const Vega10_PPTable_Generic_SubTable_Header *header;
120 const ATOM_Vega10_Fan_Table *fan_table_v1;
121 const ATOM_Vega10_Fan_Table_V2 *fan_table_v2;
f83a9991
EH
122
123 thermal_controller = (ATOM_Vega10_Thermal_Controller *)
124 (((unsigned long)powerplay_table) +
125 le16_to_cpu(powerplay_table->usThermalControllerOffset));
126
127 PP_ASSERT_WITH_CODE((powerplay_table->usThermalControllerOffset != 0),
8250880e 128 "Thermal controller table not set!", return -EINVAL);
f83a9991
EH
129
130 hwmgr->thermal_controller.ucType = thermal_controller->ucType;
131 hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
132 hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
133
134 hwmgr->thermal_controller.fanInfo.bNoFan =
135 (0 != (thermal_controller->ucFanParameters &
136 ATOM_VEGA10_PP_FANPARAMETERS_NOFAN));
137
138 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
139 thermal_controller->ucFanParameters &
140 ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
141
142 hwmgr->thermal_controller.fanInfo.ulMinRPM =
143 thermal_controller->ucFanMinRPM * 100UL;
144 hwmgr->thermal_controller.fanInfo.ulMaxRPM =
145 thermal_controller->ucFanMaxRPM * 100UL;
146
8250880e
RZ
147 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
148 = 100000;
149
f83a9991
EH
150 set_hw_cap(
151 hwmgr,
152 ATOM_VEGA10_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
153 PHM_PlatformCaps_ThermalController);
154
155 if (!powerplay_table->usFanTableOffset)
156 return 0;
157
8250880e 158 header = (const Vega10_PPTable_Generic_SubTable_Header *)
f83a9991
EH
159 (((unsigned long)powerplay_table) +
160 le16_to_cpu(powerplay_table->usFanTableOffset));
161
8250880e
RZ
162 if (header->ucRevId == 10) {
163 fan_table_v1 = (ATOM_Vega10_Fan_Table *)header;
164
165 PP_ASSERT_WITH_CODE((fan_table_v1->ucRevId >= 8),
166 "Invalid Input Fan Table!", return -EINVAL);
167
168 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
169 PHM_PlatformCaps_MicrocodeFanControl);
170
171 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
172 le16_to_cpu(fan_table_v1->usFanOutputSensitivity);
173 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
174 le16_to_cpu(fan_table_v1->usFanRPMMax);
175 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit =
176 le16_to_cpu(fan_table_v1->usThrottlingRPM);
177 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit =
178 le16_to_cpu(fan_table_v1->usFanAcousticLimit);
179 hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
180 le16_to_cpu(fan_table_v1->usTargetTemperature);
181 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
182 le16_to_cpu(fan_table_v1->usMinimumPWMLimit);
183 hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk =
184 le16_to_cpu(fan_table_v1->usTargetGfxClk);
185 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge =
186 le16_to_cpu(fan_table_v1->usFanGainEdge);
187 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot =
188 le16_to_cpu(fan_table_v1->usFanGainHotspot);
189 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid =
190 le16_to_cpu(fan_table_v1->usFanGainLiquid);
191 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc =
192 le16_to_cpu(fan_table_v1->usFanGainVrVddc);
193 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd =
194 le16_to_cpu(fan_table_v1->usFanGainVrMvdd);
195 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx =
196 le16_to_cpu(fan_table_v1->usFanGainPlx);
197 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm =
198 le16_to_cpu(fan_table_v1->usFanGainHbm);
199
200 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM =
201 fan_table_v1->ucEnableZeroRPM;
202 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature =
203 le16_to_cpu(fan_table_v1->usFanStopTemperature);
204 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature =
205 le16_to_cpu(fan_table_v1->usFanStartTemperature);
206 } else if (header->ucRevId > 10) {
207 fan_table_v2 = (ATOM_Vega10_Fan_Table_V2 *)header;
208
209 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
210 fan_table_v2->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
211 hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v2->ucFanMinRPM * 100UL;
212 hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v2->ucFanMaxRPM * 100UL;
213
214 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
215 PHM_PlatformCaps_MicrocodeFanControl);
216
217 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
218 le16_to_cpu(fan_table_v2->usFanOutputSensitivity);
219 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
220 fan_table_v2->ucFanMaxRPM * 100UL;
221 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit =
222 le16_to_cpu(fan_table_v2->usThrottlingRPM);
223 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit =
224 le16_to_cpu(fan_table_v2->usFanAcousticLimitRpm);
225 hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
226 le16_to_cpu(fan_table_v2->usTargetTemperature);
227 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
228 le16_to_cpu(fan_table_v2->usMinimumPWMLimit);
229 hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk =
230 le16_to_cpu(fan_table_v2->usTargetGfxClk);
231 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge =
232 le16_to_cpu(fan_table_v2->usFanGainEdge);
233 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot =
234 le16_to_cpu(fan_table_v2->usFanGainHotspot);
235 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid =
236 le16_to_cpu(fan_table_v2->usFanGainLiquid);
237 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc =
238 le16_to_cpu(fan_table_v2->usFanGainVrVddc);
239 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd =
240 le16_to_cpu(fan_table_v2->usFanGainVrMvdd);
241 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx =
242 le16_to_cpu(fan_table_v2->usFanGainPlx);
243 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm =
244 le16_to_cpu(fan_table_v2->usFanGainHbm);
245
246 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM =
247 fan_table_v2->ucEnableZeroRPM;
248 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature =
249 le16_to_cpu(fan_table_v2->usFanStopTemperature);
250 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature =
251 le16_to_cpu(fan_table_v2->usFanStartTemperature);
252 }
f83a9991
EH
253 return 0;
254}
255
256static int init_over_drive_limits(
257 struct pp_hwmgr *hwmgr,
258 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
259{
260 hwmgr->platform_descriptor.overdriveLimit.engineClock =
261 le32_to_cpu(powerplay_table->ulMaxODEngineClock);
262 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
263 le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
264
265 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
266 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
267 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
268
269 if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 &&
270 hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) {
271 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
272 PHM_PlatformCaps_ACOverdriveSupport);
273 }
274
275 return 0;
276}
277
278static int get_mm_clock_voltage_table(
279 struct pp_hwmgr *hwmgr,
280 phm_ppt_v1_mm_clock_voltage_dependency_table **vega10_mm_table,
281 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table)
282{
283 uint32_t table_size, i;
284 const ATOM_Vega10_MM_Dependency_Record *mm_dependency_record;
285 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
286
287 PP_ASSERT_WITH_CODE((mm_dependency_table->ucNumEntries != 0),
288 "Invalid PowerPlay Table!", return -1);
289
290 table_size = sizeof(uint32_t) +
291 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) *
292 mm_dependency_table->ucNumEntries;
293 mm_table = (phm_ppt_v1_mm_clock_voltage_dependency_table *)
294 kzalloc(table_size, GFP_KERNEL);
295
296 if (!mm_table)
297 return -ENOMEM;
298
299 mm_table->count = mm_dependency_table->ucNumEntries;
300
301 for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
302 mm_dependency_record = &mm_dependency_table->entries[i];
303 mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd;
304 mm_table->entries[i].samclock =
305 le32_to_cpu(mm_dependency_record->ulPSPClk);
306 mm_table->entries[i].eclk = le32_to_cpu(mm_dependency_record->ulEClk);
307 mm_table->entries[i].vclk = le32_to_cpu(mm_dependency_record->ulVClk);
308 mm_table->entries[i].dclk = le32_to_cpu(mm_dependency_record->ulDClk);
309 }
310
311 *vega10_mm_table = mm_table;
312
313 return 0;
314}
315
1e1eb6a8
RZ
316static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda)
317{
318 switch(line){
319 case Vega10_I2CLineID_DDC1:
320 *scl = Vega10_I2C_DDC1CLK;
321 *sda = Vega10_I2C_DDC1DATA;
322 break;
323 case Vega10_I2CLineID_DDC2:
324 *scl = Vega10_I2C_DDC2CLK;
325 *sda = Vega10_I2C_DDC2DATA;
326 break;
327 case Vega10_I2CLineID_DDC3:
328 *scl = Vega10_I2C_DDC3CLK;
329 *sda = Vega10_I2C_DDC3DATA;
330 break;
331 case Vega10_I2CLineID_DDC4:
332 *scl = Vega10_I2C_DDC4CLK;
333 *sda = Vega10_I2C_DDC4DATA;
334 break;
335 case Vega10_I2CLineID_DDC5:
336 *scl = Vega10_I2C_DDC5CLK;
337 *sda = Vega10_I2C_DDC5DATA;
338 break;
339 case Vega10_I2CLineID_DDC6:
340 *scl = Vega10_I2C_DDC6CLK;
341 *sda = Vega10_I2C_DDC6DATA;
342 break;
343 case Vega10_I2CLineID_SCLSDA:
344 *scl = Vega10_I2C_SCL;
345 *sda = Vega10_I2C_SDA;
346 break;
347 case Vega10_I2CLineID_DDCVGA:
348 *scl = Vega10_I2C_DDCVGACLK;
349 *sda = Vega10_I2C_DDCVGADATA;
350 break;
351 default:
352 *scl = 0;
353 *sda = 0;
354 break;
355 }
356}
357
f83a9991
EH
358static int get_tdp_table(
359 struct pp_hwmgr *hwmgr,
360 struct phm_tdp_table **info_tdp_table,
361 const Vega10_PPTable_Generic_SubTable_Header *table)
362{
363 uint32_t table_size;
364 struct phm_tdp_table *tdp_table;
1e1eb6a8
RZ
365 uint8_t scl;
366 uint8_t sda;
367 const ATOM_Vega10_PowerTune_Table *power_tune_table;
368 const ATOM_Vega10_PowerTune_Table_V2 *power_tune_table_v2;
f83a9991
EH
369
370 table_size = sizeof(uint32_t) + sizeof(struct phm_tdp_table);
1e1eb6a8 371
f83a9991
EH
372 tdp_table = kzalloc(table_size, GFP_KERNEL);
373
1e1eb6a8 374 if (!tdp_table)
f83a9991 375 return -ENOMEM;
f83a9991 376
1e1eb6a8
RZ
377 if (table->ucRevId == 5) {
378 power_tune_table = (ATOM_Vega10_PowerTune_Table *)table;
379 tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table->usSocketPowerLimit);
380 tdp_table->usTDC = le16_to_cpu(power_tune_table->usTdcLimit);
381 tdp_table->usEDCLimit = le16_to_cpu(power_tune_table->usEdcLimit);
382 tdp_table->usSoftwareShutdownTemp =
383 le16_to_cpu(power_tune_table->usSoftwareShutdownTemp);
384 tdp_table->usTemperatureLimitTedge =
385 le16_to_cpu(power_tune_table->usTemperatureLimitTedge);
386 tdp_table->usTemperatureLimitHotspot =
387 le16_to_cpu(power_tune_table->usTemperatureLimitHotSpot);
388 tdp_table->usTemperatureLimitLiquid1 =
389 le16_to_cpu(power_tune_table->usTemperatureLimitLiquid1);
390 tdp_table->usTemperatureLimitLiquid2 =
391 le16_to_cpu(power_tune_table->usTemperatureLimitLiquid2);
392 tdp_table->usTemperatureLimitHBM =
393 le16_to_cpu(power_tune_table->usTemperatureLimitHBM);
394 tdp_table->usTemperatureLimitVrVddc =
395 le16_to_cpu(power_tune_table->usTemperatureLimitVrSoc);
396 tdp_table->usTemperatureLimitVrMvdd =
397 le16_to_cpu(power_tune_table->usTemperatureLimitVrMem);
398 tdp_table->usTemperatureLimitPlx =
399 le16_to_cpu(power_tune_table->usTemperatureLimitPlx);
400 tdp_table->ucLiquid1_I2C_address = power_tune_table->ucLiquid1_I2C_address;
401 tdp_table->ucLiquid2_I2C_address = power_tune_table->ucLiquid2_I2C_address;
402 tdp_table->ucLiquid_I2C_Line = power_tune_table->ucLiquid_I2C_LineSCL;
403 tdp_table->ucLiquid_I2C_LineSDA = power_tune_table->ucLiquid_I2C_LineSDA;
404 tdp_table->ucVr_I2C_address = power_tune_table->ucVr_I2C_address;
405 tdp_table->ucVr_I2C_Line = power_tune_table->ucVr_I2C_LineSCL;
406 tdp_table->ucVr_I2C_LineSDA = power_tune_table->ucVr_I2C_LineSDA;
407 tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address;
408 tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL;
409 tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA;
410 hwmgr->platform_descriptor.LoadLineSlope = power_tune_table->usLoadLineResistance;
411 } else {
412 power_tune_table_v2 = (ATOM_Vega10_PowerTune_Table_V2 *)table;
413 tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v2->usSocketPowerLimit);
414 tdp_table->usTDC = le16_to_cpu(power_tune_table_v2->usTdcLimit);
415 tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v2->usEdcLimit);
416 tdp_table->usSoftwareShutdownTemp =
417 le16_to_cpu(power_tune_table_v2->usSoftwareShutdownTemp);
418 tdp_table->usTemperatureLimitTedge =
419 le16_to_cpu(power_tune_table_v2->usTemperatureLimitTedge);
420 tdp_table->usTemperatureLimitHotspot =
421 le16_to_cpu(power_tune_table_v2->usTemperatureLimitHotSpot);
422 tdp_table->usTemperatureLimitLiquid1 =
423 le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid1);
424 tdp_table->usTemperatureLimitLiquid2 =
425 le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid2);
426 tdp_table->usTemperatureLimitHBM =
427 le16_to_cpu(power_tune_table_v2->usTemperatureLimitHBM);
428 tdp_table->usTemperatureLimitVrVddc =
429 le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrSoc);
430 tdp_table->usTemperatureLimitVrMvdd =
431 le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrMem);
432 tdp_table->usTemperatureLimitPlx =
433 le16_to_cpu(power_tune_table_v2->usTemperatureLimitPlx);
434 tdp_table->ucLiquid1_I2C_address = power_tune_table_v2->ucLiquid1_I2C_address;
435 tdp_table->ucLiquid2_I2C_address = power_tune_table_v2->ucLiquid2_I2C_address;
436
437 get_scl_sda_value(power_tune_table_v2->ucLiquid_I2C_Line, &scl, &sda);
438
439 tdp_table->ucLiquid_I2C_Line = scl;
440 tdp_table->ucLiquid_I2C_LineSDA = sda;
441
442 tdp_table->ucVr_I2C_address = power_tune_table_v2->ucVr_I2C_address;
443
444 get_scl_sda_value(power_tune_table_v2->ucVr_I2C_Line, &scl, &sda);
445
446 tdp_table->ucVr_I2C_Line = scl;
447 tdp_table->ucVr_I2C_LineSDA = sda;
448 tdp_table->ucPlx_I2C_address = power_tune_table_v2->ucPlx_I2C_address;
449
450 get_scl_sda_value(power_tune_table_v2->ucPlx_I2C_Line, &scl, &sda);
451
452 tdp_table->ucPlx_I2C_Line = scl;
453 tdp_table->ucPlx_I2C_LineSDA = sda;
454
455 hwmgr->platform_descriptor.LoadLineSlope =
456 power_tune_table_v2->usLoadLineResistance;
457 }
f83a9991
EH
458
459 *info_tdp_table = tdp_table;
460
461 return 0;
462}
463
464static int get_socclk_voltage_dependency_table(
465 struct pp_hwmgr *hwmgr,
466 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_clk_dep_table,
467 const ATOM_Vega10_SOCCLK_Dependency_Table *clk_dep_table)
468{
469 uint32_t table_size, i;
470 phm_ppt_v1_clock_voltage_dependency_table *clk_table;
471
472 PP_ASSERT_WITH_CODE(clk_dep_table->ucNumEntries,
473 "Invalid PowerPlay Table!", return -1);
474
475 table_size = sizeof(uint32_t) +
476 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
477 clk_dep_table->ucNumEntries;
478
479 clk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
480 kzalloc(table_size, GFP_KERNEL);
481
482 if (!clk_table)
483 return -ENOMEM;
484
485 clk_table->count = (uint32_t)clk_dep_table->ucNumEntries;
486
487 for (i = 0; i < clk_dep_table->ucNumEntries; i++) {
488 clk_table->entries[i].vddInd =
489 clk_dep_table->entries[i].ucVddInd;
490 clk_table->entries[i].clk =
491 le32_to_cpu(clk_dep_table->entries[i].ulClk);
492 }
493
494 *pp_vega10_clk_dep_table = clk_table;
495
496 return 0;
497}
498
499static int get_mclk_voltage_dependency_table(
500 struct pp_hwmgr *hwmgr,
501 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table,
502 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table)
503{
504 uint32_t table_size, i;
505 phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
506
507 PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries,
508 "Invalid PowerPlay Table!", return -1);
509
510 table_size = sizeof(uint32_t) +
511 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
512 mclk_dep_table->ucNumEntries;
513
514 mclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
515 kzalloc(table_size, GFP_KERNEL);
516
517 if (!mclk_table)
518 return -ENOMEM;
519
520 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
521
522 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
523 mclk_table->entries[i].vddInd =
524 mclk_dep_table->entries[i].ucVddInd;
525 mclk_table->entries[i].vddciInd =
526 mclk_dep_table->entries[i].ucVddciInd;
527 mclk_table->entries[i].mvddInd =
528 mclk_dep_table->entries[i].ucVddMemInd;
529 mclk_table->entries[i].clk =
530 le32_to_cpu(mclk_dep_table->entries[i].ulMemClk);
531 }
532
533 *pp_vega10_mclk_dep_table = mclk_table;
534
535 return 0;
536}
537
538static int get_gfxclk_voltage_dependency_table(
539 struct pp_hwmgr *hwmgr,
540 struct phm_ppt_v1_clock_voltage_dependency_table
541 **pp_vega10_clk_dep_table,
542 const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table)
543{
544 uint32_t table_size, i;
545 struct phm_ppt_v1_clock_voltage_dependency_table
546 *clk_table;
547
548 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0),
549 "Invalid PowerPlay Table!", return -1);
550
551 table_size = sizeof(uint32_t) +
552 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
553 clk_dep_table->ucNumEntries;
554
555 clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)
556 kzalloc(table_size, GFP_KERNEL);
557
558 if (!clk_table)
559 return -ENOMEM;
560
561 clk_table->count = clk_dep_table->ucNumEntries;
562
563 for (i = 0; i < clk_table->count; i++) {
564 clk_table->entries[i].vddInd =
565 clk_dep_table->entries[i].ucVddInd;
566 clk_table->entries[i].clk =
567 le32_to_cpu(clk_dep_table->entries[i].ulClk);
568 clk_table->entries[i].cks_enable =
569 (((clk_dep_table->entries[i].usCKSVOffsetandDisable & 0x80)
570 >> 15) == 0) ? 1 : 0;
571 clk_table->entries[i].cks_voffset =
572 (clk_dep_table->entries[i].usCKSVOffsetandDisable & 0x7F);
573 clk_table->entries[i].sclk_offset =
574 clk_dep_table->entries[i].usAVFSOffset;
575 }
576
577 *pp_vega10_clk_dep_table = clk_table;
578
579 return 0;
580}
581
582static int get_dcefclk_voltage_dependency_table(
583 struct pp_hwmgr *hwmgr,
584 struct phm_ppt_v1_clock_voltage_dependency_table
585 **pp_vega10_clk_dep_table,
586 const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table)
587{
588 uint32_t table_size, i;
589 struct phm_ppt_v1_clock_voltage_dependency_table
590 *clk_table;
591
592 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0),
593 "Invalid PowerPlay Table!", return -1);
594
595 table_size = sizeof(uint32_t) +
596 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
597 clk_dep_table->ucNumEntries;
598
599 clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)
600 kzalloc(table_size, GFP_KERNEL);
601
602 if (!clk_table)
603 return -ENOMEM;
604
605 clk_table->count = clk_dep_table->ucNumEntries;
606
607 for (i = 0; i < clk_table->count; i++) {
608 clk_table->entries[i].vddInd =
609 clk_dep_table->entries[i].ucVddInd;
610 clk_table->entries[i].clk =
611 le32_to_cpu(clk_dep_table->entries[i].ulClk);
612 }
613
614 *pp_vega10_clk_dep_table = clk_table;
615
616 return 0;
617}
618
619static int get_pcie_table(struct pp_hwmgr *hwmgr,
620 struct phm_ppt_v1_pcie_table **vega10_pcie_table,
621 const Vega10_PPTable_Generic_SubTable_Header *table)
622{
623 uint32_t table_size, i, pcie_count;
624 struct phm_ppt_v1_pcie_table *pcie_table;
625 struct phm_ppt_v2_information *table_info =
626 (struct phm_ppt_v2_information *)(hwmgr->pptable);
627 const ATOM_Vega10_PCIE_Table *atom_pcie_table =
628 (ATOM_Vega10_PCIE_Table *)table;
629
630 PP_ASSERT_WITH_CODE(atom_pcie_table->ucNumEntries,
631 "Invalid PowerPlay Table!",
632 return 0);
633
634 table_size = sizeof(uint32_t) +
635 sizeof(struct phm_ppt_v1_pcie_record) *
636 atom_pcie_table->ucNumEntries;
637
638 pcie_table = (struct phm_ppt_v1_pcie_table *)
639 kzalloc(table_size, GFP_KERNEL);
640
641 if (!pcie_table)
642 return -ENOMEM;
643
644 pcie_count = table_info->vdd_dep_on_sclk->count;
645 if (atom_pcie_table->ucNumEntries <= pcie_count)
646 pcie_count = atom_pcie_table->ucNumEntries;
647 else
648 pr_info("Number of Pcie Entries exceed the number of"
649 " GFXCLK Dpm Levels!"
650 " Disregarding the excess entries...\n");
651
652 pcie_table->count = pcie_count;
653
654 for (i = 0; i < pcie_count; i++) {
655 pcie_table->entries[i].gen_speed =
656 atom_pcie_table->entries[i].ucPCIEGenSpeed;
657 pcie_table->entries[i].lane_width =
658 atom_pcie_table->entries[i].ucPCIELaneWidth;
659 pcie_table->entries[i].pcie_sclk =
660 atom_pcie_table->entries[i].ulLCLK;
661 }
662
663 *vega10_pcie_table = pcie_table;
664
665 return 0;
666}
667
668static int get_hard_limits(
669 struct pp_hwmgr *hwmgr,
670 struct phm_clock_and_voltage_limits *limits,
671 const ATOM_Vega10_Hard_Limit_Table *limit_table)
672{
673 PP_ASSERT_WITH_CODE(limit_table->ucNumEntries,
674 "Invalid PowerPlay Table!", return -1);
675
676 /* currently we always take entries[0] parameters */
677 limits->sclk = le32_to_cpu(limit_table->entries[0].ulSOCCLKLimit);
678 limits->mclk = le32_to_cpu(limit_table->entries[0].ulMCLKLimit);
679 limits->gfxclk = le32_to_cpu(limit_table->entries[0].ulGFXCLKLimit);
680 limits->vddc = le16_to_cpu(limit_table->entries[0].usVddcLimit);
681 limits->vddci = le16_to_cpu(limit_table->entries[0].usVddciLimit);
682 limits->vddmem = le16_to_cpu(limit_table->entries[0].usVddMemLimit);
683
684 return 0;
685}
686
687static int get_valid_clk(
688 struct pp_hwmgr *hwmgr,
689 struct phm_clock_array **clk_table,
690 const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table)
691{
692 uint32_t table_size, i;
693 struct phm_clock_array *table;
694
695 PP_ASSERT_WITH_CODE(clk_volt_pp_table->count,
696 "Invalid PowerPlay Table!", return -1);
697
698 table_size = sizeof(uint32_t) +
699 sizeof(uint32_t) * clk_volt_pp_table->count;
700
701 table = kzalloc(table_size, GFP_KERNEL);
702
703 if (!table)
704 return -ENOMEM;
705
706 table->count = (uint32_t)clk_volt_pp_table->count;
707
708 for (i = 0; i < table->count; i++)
709 table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk;
710
711 *clk_table = table;
712
713 return 0;
714}
715
716static int init_powerplay_extended_tables(
717 struct pp_hwmgr *hwmgr,
718 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
719{
720 int result = 0;
721 struct phm_ppt_v2_information *pp_table_info =
722 (struct phm_ppt_v2_information *)(hwmgr->pptable);
723
724 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table =
725 (const ATOM_Vega10_MM_Dependency_Table *)
726 (((unsigned long) powerplay_table) +
727 le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
728 const Vega10_PPTable_Generic_SubTable_Header *power_tune_table =
729 (const Vega10_PPTable_Generic_SubTable_Header *)
730 (((unsigned long) powerplay_table) +
731 le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
732 const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table =
733 (const ATOM_Vega10_SOCCLK_Dependency_Table *)
734 (((unsigned long) powerplay_table) +
735 le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset));
736 const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
737 (const ATOM_Vega10_GFXCLK_Dependency_Table *)
738 (((unsigned long) powerplay_table) +
739 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
740 const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table =
741 (const ATOM_Vega10_DCEFCLK_Dependency_Table *)
742 (((unsigned long) powerplay_table) +
743 le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset));
744 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table =
745 (const ATOM_Vega10_MCLK_Dependency_Table *)
746 (((unsigned long) powerplay_table) +
747 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
748 const ATOM_Vega10_Hard_Limit_Table *hard_limits =
749 (const ATOM_Vega10_Hard_Limit_Table *)
750 (((unsigned long) powerplay_table) +
751 le16_to_cpu(powerplay_table->usHardLimitTableOffset));
752 const Vega10_PPTable_Generic_SubTable_Header *pcie_table =
753 (const Vega10_PPTable_Generic_SubTable_Header *)
754 (((unsigned long) powerplay_table) +
755 le16_to_cpu(powerplay_table->usPCIETableOffset));
756 const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table =
757 (const ATOM_Vega10_PIXCLK_Dependency_Table *)
758 (((unsigned long) powerplay_table) +
759 le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset));
760 const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table =
761 (const ATOM_Vega10_PHYCLK_Dependency_Table *)
762 (((unsigned long) powerplay_table) +
763 le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset));
764 const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table =
765 (const ATOM_Vega10_DISPCLK_Dependency_Table *)
766 (((unsigned long) powerplay_table) +
767 le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset));
768
769 pp_table_info->vdd_dep_on_socclk = NULL;
770 pp_table_info->vdd_dep_on_sclk = NULL;
771 pp_table_info->vdd_dep_on_mclk = NULL;
772 pp_table_info->vdd_dep_on_dcefclk = NULL;
773 pp_table_info->mm_dep_table = NULL;
774 pp_table_info->tdp_table = NULL;
775 pp_table_info->vdd_dep_on_pixclk = NULL;
776 pp_table_info->vdd_dep_on_phyclk = NULL;
777 pp_table_info->vdd_dep_on_dispclk = NULL;
778
779 if (powerplay_table->usMMDependencyTableOffset)
780 result = get_mm_clock_voltage_table(hwmgr,
781 &pp_table_info->mm_dep_table,
782 mm_dependency_table);
783
784 if (!result && powerplay_table->usPowerTuneTableOffset)
785 result = get_tdp_table(hwmgr,
786 &pp_table_info->tdp_table,
787 power_tune_table);
788
789 if (!result && powerplay_table->usSocclkDependencyTableOffset)
790 result = get_socclk_voltage_dependency_table(hwmgr,
791 &pp_table_info->vdd_dep_on_socclk,
792 socclk_dep_table);
793
794 if (!result && powerplay_table->usGfxclkDependencyTableOffset)
795 result = get_gfxclk_voltage_dependency_table(hwmgr,
796 &pp_table_info->vdd_dep_on_sclk,
797 gfxclk_dep_table);
798
799 if (!result && powerplay_table->usPixclkDependencyTableOffset)
800 result = get_dcefclk_voltage_dependency_table(hwmgr,
801 &pp_table_info->vdd_dep_on_pixclk,
802 (const ATOM_Vega10_DCEFCLK_Dependency_Table*)
803 pixclk_dep_table);
804
805 if (!result && powerplay_table->usPhyClkDependencyTableOffset)
806 result = get_dcefclk_voltage_dependency_table(hwmgr,
807 &pp_table_info->vdd_dep_on_phyclk,
808 (const ATOM_Vega10_DCEFCLK_Dependency_Table *)
809 phyclk_dep_table);
810
811 if (!result && powerplay_table->usDispClkDependencyTableOffset)
812 result = get_dcefclk_voltage_dependency_table(hwmgr,
813 &pp_table_info->vdd_dep_on_dispclk,
814 (const ATOM_Vega10_DCEFCLK_Dependency_Table *)
815 dispclk_dep_table);
816
817 if (!result && powerplay_table->usDcefclkDependencyTableOffset)
818 result = get_dcefclk_voltage_dependency_table(hwmgr,
819 &pp_table_info->vdd_dep_on_dcefclk,
820 dcefclk_dep_table);
821
822 if (!result && powerplay_table->usMclkDependencyTableOffset)
823 result = get_mclk_voltage_dependency_table(hwmgr,
824 &pp_table_info->vdd_dep_on_mclk,
825 mclk_dep_table);
826
827 if (!result && powerplay_table->usPCIETableOffset)
828 result = get_pcie_table(hwmgr,
829 &pp_table_info->pcie_table,
830 pcie_table);
831
832 if (!result && powerplay_table->usHardLimitTableOffset)
833 result = get_hard_limits(hwmgr,
834 &pp_table_info->max_clock_voltage_on_dc,
835 hard_limits);
836
837 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
838 pp_table_info->max_clock_voltage_on_dc.sclk;
839 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
840 pp_table_info->max_clock_voltage_on_dc.mclk;
841 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
842 pp_table_info->max_clock_voltage_on_dc.vddc;
843 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
844 pp_table_info->max_clock_voltage_on_dc.vddci;
845
846 if (!result &&
847 pp_table_info->vdd_dep_on_socclk &&
848 pp_table_info->vdd_dep_on_socclk->count)
849 result = get_valid_clk(hwmgr,
850 &pp_table_info->valid_socclk_values,
851 pp_table_info->vdd_dep_on_socclk);
852
853 if (!result &&
854 pp_table_info->vdd_dep_on_sclk &&
855 pp_table_info->vdd_dep_on_sclk->count)
856 result = get_valid_clk(hwmgr,
857 &pp_table_info->valid_sclk_values,
858 pp_table_info->vdd_dep_on_sclk);
859
860 if (!result &&
861 pp_table_info->vdd_dep_on_dcefclk &&
862 pp_table_info->vdd_dep_on_dcefclk->count)
863 result = get_valid_clk(hwmgr,
864 &pp_table_info->valid_dcefclk_values,
865 pp_table_info->vdd_dep_on_dcefclk);
866
867 if (!result &&
868 pp_table_info->vdd_dep_on_mclk &&
869 pp_table_info->vdd_dep_on_mclk->count)
870 result = get_valid_clk(hwmgr,
871 &pp_table_info->valid_mclk_values,
872 pp_table_info->vdd_dep_on_mclk);
873
874 return result;
875}
876
877static int get_vddc_lookup_table(
878 struct pp_hwmgr *hwmgr,
879 phm_ppt_v1_voltage_lookup_table **lookup_table,
880 const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables,
881 uint32_t max_levels)
882{
883 uint32_t table_size, i;
884 phm_ppt_v1_voltage_lookup_table *table;
885
886 PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0),
887 "Invalid SOC_VDDD Lookup Table!", return 1);
888
889 table_size = sizeof(uint32_t) +
890 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels;
891
892 table = (phm_ppt_v1_voltage_lookup_table *)
893 kzalloc(table_size, GFP_KERNEL);
894
895 if (NULL == table)
896 return -ENOMEM;
897
898 table->count = vddc_lookup_pp_tables->ucNumEntries;
899
900 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++)
901 table->entries[i].us_vdd =
902 le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd);
903
904 *lookup_table = table;
905
906 return 0;
907}
908
909static int init_dpm_2_parameters(
910 struct pp_hwmgr *hwmgr,
911 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
912{
913 int result = 0;
914 struct phm_ppt_v2_information *pp_table_info =
915 (struct phm_ppt_v2_information *)(hwmgr->pptable);
916 uint32_t disable_power_control = 0;
917
918 pp_table_info->us_ulv_voltage_offset =
919 le16_to_cpu(powerplay_table->usUlvVoltageOffset);
920
921 pp_table_info->us_ulv_smnclk_did =
922 le16_to_cpu(powerplay_table->usUlvSmnclkDid);
923 pp_table_info->us_ulv_mp1clk_did =
924 le16_to_cpu(powerplay_table->usUlvMp1clkDid);
925 pp_table_info->us_ulv_gfxclk_bypass =
926 le16_to_cpu(powerplay_table->usUlvGfxclkBypass);
927 pp_table_info->us_gfxclk_slew_rate =
928 le16_to_cpu(powerplay_table->usGfxclkSlewRate);
929 pp_table_info->uc_gfx_dpm_voltage_mode =
930 le16_to_cpu(powerplay_table->ucGfxVoltageMode);
931 pp_table_info->uc_soc_dpm_voltage_mode =
932 le16_to_cpu(powerplay_table->ucSocVoltageMode);
933 pp_table_info->uc_uclk_dpm_voltage_mode =
934 le16_to_cpu(powerplay_table->ucUclkVoltageMode);
935 pp_table_info->uc_uvd_dpm_voltage_mode =
936 le16_to_cpu(powerplay_table->ucUvdVoltageMode);
937 pp_table_info->uc_vce_dpm_voltage_mode =
938 le16_to_cpu(powerplay_table->ucVceVoltageMode);
939 pp_table_info->uc_mp0_dpm_voltage_mode =
940 le16_to_cpu(powerplay_table->ucMp0VoltageMode);
941 pp_table_info->uc_dcef_dpm_voltage_mode =
942 le16_to_cpu(powerplay_table->ucDcefVoltageMode);
943
944 pp_table_info->ppm_parameter_table = NULL;
945 pp_table_info->vddc_lookup_table = NULL;
946 pp_table_info->vddmem_lookup_table = NULL;
947 pp_table_info->vddci_lookup_table = NULL;
948
949 /* TDP limits */
950 hwmgr->platform_descriptor.TDPODLimit =
951 le16_to_cpu(powerplay_table->usPowerControlLimit);
952 hwmgr->platform_descriptor.TDPAdjustment = 0;
953 hwmgr->platform_descriptor.VidAdjustment = 0;
954 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
955 hwmgr->platform_descriptor.VidMinLimit = 0;
956 hwmgr->platform_descriptor.VidMaxLimit = 1500000;
957 hwmgr->platform_descriptor.VidStep = 6250;
958
959 disable_power_control = 0;
960 if (!disable_power_control) {
961 /* enable TDP overdrive (PowerControl) feature as well if supported */
962 if (hwmgr->platform_descriptor.TDPODLimit)
963 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
964 PHM_PlatformCaps_PowerControl);
965 }
966
967 if (powerplay_table->usVddcLookupTableOffset) {
968 const ATOM_Vega10_Voltage_Lookup_Table *vddc_table =
969 (ATOM_Vega10_Voltage_Lookup_Table *)
970 (((unsigned long)powerplay_table) +
971 le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
972 result = get_vddc_lookup_table(hwmgr,
1e1eb6a8 973 &pp_table_info->vddc_lookup_table, vddc_table, 8);
f83a9991
EH
974 }
975
976 if (powerplay_table->usVddmemLookupTableOffset) {
977 const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table =
978 (ATOM_Vega10_Voltage_Lookup_Table *)
979 (((unsigned long)powerplay_table) +
980 le16_to_cpu(powerplay_table->usVddmemLookupTableOffset));
981 result = get_vddc_lookup_table(hwmgr,
1e1eb6a8 982 &pp_table_info->vddmem_lookup_table, vdd_mem_table, 4);
f83a9991
EH
983 }
984
985 if (powerplay_table->usVddciLookupTableOffset) {
986 const ATOM_Vega10_Voltage_Lookup_Table *vddci_table =
987 (ATOM_Vega10_Voltage_Lookup_Table *)
988 (((unsigned long)powerplay_table) +
989 le16_to_cpu(powerplay_table->usVddciLookupTableOffset));
990 result = get_vddc_lookup_table(hwmgr,
1e1eb6a8 991 &pp_table_info->vddci_lookup_table, vddci_table, 4);
f83a9991
EH
992 }
993
994 return result;
995}
996
997int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr)
998{
999 int result = 0;
1000 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table;
1001
1002 hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL);
1003
1004 PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
1005 "Failed to allocate hwmgr->pptable!", return -ENOMEM);
1006
1007 powerplay_table = get_powerplay_table(hwmgr);
1008
1009 PP_ASSERT_WITH_CODE((NULL != powerplay_table),
1010 "Missing PowerPlay Table!", return -1);
1011
1012 result = check_powerplay_tables(hwmgr, powerplay_table);
1013
1014 PP_ASSERT_WITH_CODE((result == 0),
1015 "check_powerplay_tables failed", return result);
1016
1017 result = set_platform_caps(hwmgr,
1018 le32_to_cpu(powerplay_table->ulPlatformCaps));
1019
1020 PP_ASSERT_WITH_CODE((result == 0),
1021 "set_platform_caps failed", return result);
1022
1023 result = init_thermal_controller(hwmgr, powerplay_table);
1024
1025 PP_ASSERT_WITH_CODE((result == 0),
1026 "init_thermal_controller failed", return result);
1027
1028 result = init_over_drive_limits(hwmgr, powerplay_table);
1029
1030 PP_ASSERT_WITH_CODE((result == 0),
1031 "init_over_drive_limits failed", return result);
1032
1033 result = init_powerplay_extended_tables(hwmgr, powerplay_table);
1034
1035 PP_ASSERT_WITH_CODE((result == 0),
1036 "init_powerplay_extended_tables failed", return result);
1037
1038 result = init_dpm_2_parameters(hwmgr, powerplay_table);
1039
1040 PP_ASSERT_WITH_CODE((result == 0),
1041 "init_dpm_2_parameters failed", return result);
1042
1043 return result;
1044}
1045
1046static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1047{
1048 int result = 0;
1049 struct phm_ppt_v2_information *pp_table_info =
1050 (struct phm_ppt_v2_information *)(hwmgr->pptable);
1051
1052 kfree(pp_table_info->vdd_dep_on_sclk);
1053 pp_table_info->vdd_dep_on_sclk = NULL;
1054
1055 kfree(pp_table_info->vdd_dep_on_mclk);
1056 pp_table_info->vdd_dep_on_mclk = NULL;
1057
1058 kfree(pp_table_info->valid_mclk_values);
1059 pp_table_info->valid_mclk_values = NULL;
1060
1061 kfree(pp_table_info->valid_sclk_values);
1062 pp_table_info->valid_sclk_values = NULL;
1063
1064 kfree(pp_table_info->vddc_lookup_table);
1065 pp_table_info->vddc_lookup_table = NULL;
1066
1067 kfree(pp_table_info->vddmem_lookup_table);
1068 pp_table_info->vddmem_lookup_table = NULL;
1069
1070 kfree(pp_table_info->vddci_lookup_table);
1071 pp_table_info->vddci_lookup_table = NULL;
1072
1073 kfree(pp_table_info->ppm_parameter_table);
1074 pp_table_info->ppm_parameter_table = NULL;
1075
1076 kfree(pp_table_info->mm_dep_table);
1077 pp_table_info->mm_dep_table = NULL;
1078
1079 kfree(pp_table_info->cac_dtp_table);
1080 pp_table_info->cac_dtp_table = NULL;
1081
1082 kfree(hwmgr->dyn_state.cac_dtp_table);
1083 hwmgr->dyn_state.cac_dtp_table = NULL;
1084
1085 kfree(pp_table_info->tdp_table);
1086 pp_table_info->tdp_table = NULL;
1087
1088 kfree(hwmgr->pptable);
1089 hwmgr->pptable = NULL;
1090
1091 return result;
1092}
1093
1094const struct pp_table_func vega10_pptable_funcs = {
1095 .pptable_init = vega10_pp_tables_initialize,
1096 .pptable_fini = vega10_pp_tables_uninitialize,
1097};
1098
1099int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
1100{
1101 const ATOM_Vega10_State_Array *state_arrays;
1102 const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1103
1104 PP_ASSERT_WITH_CODE((NULL != pp_table),
1105 "Missing PowerPlay Table!", return -1);
1106 PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >=
1107 ATOM_Vega10_TABLE_REVISION_VEGA10),
1108 "Incorrect PowerPlay table revision!", return -1);
1109
1110 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) +
1111 le16_to_cpu(pp_table->usStateArrayOffset));
1112
1113 return (uint32_t)(state_arrays->ucNumEntries);
1114}
1115
1116static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
1117 uint16_t classification, uint16_t classification2)
1118{
1119 uint32_t result = 0;
1120
1121 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
1122 result |= PP_StateClassificationFlag_Boot;
1123
1124 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1125 result |= PP_StateClassificationFlag_Thermal;
1126
1127 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
1128 result |= PP_StateClassificationFlag_LimitedPowerSource;
1129
1130 if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
1131 result |= PP_StateClassificationFlag_Rest;
1132
1133 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
1134 result |= PP_StateClassificationFlag_Forced;
1135
1136 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
1137 result |= PP_StateClassificationFlag_ACPI;
1138
1139 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
1140 result |= PP_StateClassificationFlag_LimitedPowerSource_2;
1141
1142 return result;
1143}
1144
1145int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr,
1146 uint32_t entry_index, struct pp_power_state *power_state,
1147 int (*call_back_func)(struct pp_hwmgr *, void *,
1148 struct pp_power_state *, void *, uint32_t))
1149{
1150 int result = 0;
1151 const ATOM_Vega10_State_Array *state_arrays;
1152 const ATOM_Vega10_State *state_entry;
1153 const ATOM_Vega10_POWERPLAYTABLE *pp_table =
1154 get_powerplay_table(hwmgr);
1155
1156 PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!",
1157 return -1;);
1158 power_state->classification.bios_index = entry_index;
1159
1160 if (pp_table->sHeader.format_revision >=
1161 ATOM_Vega10_TABLE_REVISION_VEGA10) {
1162 state_arrays = (ATOM_Vega10_State_Array *)
1163 (((unsigned long)pp_table) +
1164 le16_to_cpu(pp_table->usStateArrayOffset));
1165
1166 PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0,
1167 "Invalid PowerPlay Table State Array Offset.",
1168 return -1);
1169 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
1170 "Invalid PowerPlay Table State Array.",
1171 return -1);
1172 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
1173 "Invalid PowerPlay Table State Array Entry.",
1174 return -1);
1175
1176 state_entry = &(state_arrays->states[entry_index]);
1177
1178 result = call_back_func(hwmgr, (void *)state_entry, power_state,
1179 (void *)pp_table,
1180 make_classification_flags(hwmgr,
1181 le16_to_cpu(state_entry->usClassification),
1182 le16_to_cpu(state_entry->usClassification2)));
1183 }
1184
1185 if (!result && (power_state->classification.flags &
1186 PP_StateClassificationFlag_Boot))
1187 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
1188
1189 return result;
1190}