drm/imx: parallel-display: add bridge support
[cascardo/linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / fiji_powertune.c
1 /*
2  * Copyright 2015 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
24 #include "hwmgr.h"
25 #include "smumgr.h"
26 #include "fiji_hwmgr.h"
27 #include "fiji_powertune.h"
28 #include "fiji_smumgr.h"
29 #include "smu73_discrete.h"
30 #include "pp_debug.h"
31
32 #define VOLTAGE_SCALE  4
33 #define POWERTUNE_DEFAULT_SET_MAX    1
34
35 const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
36                 /*sviLoadLIneEn,  SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
37                 {1,               0xF,             0xFD,
38                 /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
39                 0x19,        5,               45}
40 };
41
42 void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
43 {
44         struct fiji_hwmgr *fiji_hwmgr = (struct fiji_hwmgr *)(hwmgr->backend);
45         struct  phm_ppt_v1_information *table_info =
46                         (struct  phm_ppt_v1_information *)(hwmgr->pptable);
47         uint32_t tmp = 0;
48
49         if(table_info &&
50                         table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
51                         table_info->cac_dtp_table->usPowerTuneDataSetID)
52                 fiji_hwmgr->power_tune_defaults =
53                                 &fiji_power_tune_data_set_array
54                                 [table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
55         else
56                 fiji_hwmgr->power_tune_defaults = &fiji_power_tune_data_set_array[0];
57
58         /* Assume disabled */
59         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
60                         PHM_PlatformCaps_PowerContainment);
61         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
62                         PHM_PlatformCaps_CAC);
63         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
64                         PHM_PlatformCaps_SQRamping);
65         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
66                         PHM_PlatformCaps_DBRamping);
67         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
68                         PHM_PlatformCaps_TDRamping);
69         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
70                         PHM_PlatformCaps_TCPRamping);
71
72         fiji_hwmgr->dte_tj_offset = tmp;
73
74         if (!tmp) {
75                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
76                                 PHM_PlatformCaps_PowerContainment);
77
78                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
79                                 PHM_PlatformCaps_CAC);
80
81                 fiji_hwmgr->fast_watermark_threshold = 100;
82
83                 tmp = 1;
84                 fiji_hwmgr->enable_dte_feature = tmp ? false : true;
85                 fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false;
86                 fiji_hwmgr->enable_pkg_pwr_tracking_feature = tmp ? true : false;
87         }
88 }
89
90 /* PPGen has the gain setting generated in x * 100 unit
91  * This function is to convert the unit to x * 4096(0x1000) unit.
92  *  This is the unit expected by SMC firmware
93  */
94 static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
95 {
96         uint32_t tmp;
97         tmp = raw_setting * 4096 / 100;
98         return (uint16_t)tmp;
99 }
100
101 static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda)
102 {
103         switch (line) {
104         case Fiji_I2CLineID_DDC1 :
105                 *scl = Fiji_I2C_DDC1CLK;
106                 *sda = Fiji_I2C_DDC1DATA;
107                 break;
108         case Fiji_I2CLineID_DDC2 :
109                 *scl = Fiji_I2C_DDC2CLK;
110                 *sda = Fiji_I2C_DDC2DATA;
111                 break;
112         case Fiji_I2CLineID_DDC3 :
113                 *scl = Fiji_I2C_DDC3CLK;
114                 *sda = Fiji_I2C_DDC3DATA;
115                 break;
116         case Fiji_I2CLineID_DDC4 :
117                 *scl = Fiji_I2C_DDC4CLK;
118                 *sda = Fiji_I2C_DDC4DATA;
119                 break;
120         case Fiji_I2CLineID_DDC5 :
121                 *scl = Fiji_I2C_DDC5CLK;
122                 *sda = Fiji_I2C_DDC5DATA;
123                 break;
124         case Fiji_I2CLineID_DDC6 :
125                 *scl = Fiji_I2C_DDC6CLK;
126                 *sda = Fiji_I2C_DDC6DATA;
127                 break;
128         case Fiji_I2CLineID_SCLSDA :
129                 *scl = Fiji_I2C_SCL;
130                 *sda = Fiji_I2C_SDA;
131                 break;
132         case Fiji_I2CLineID_DDCVGA :
133                 *scl = Fiji_I2C_DDCVGACLK;
134                 *sda = Fiji_I2C_DDCVGADATA;
135                 break;
136         default:
137                 *scl = 0;
138                 *sda = 0;
139                 break;
140         }
141 }
142
143 int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
144 {
145         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
146         const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
147         SMU73_Discrete_DpmTable  *dpm_table = &(data->smc_state_table);
148         struct phm_ppt_v1_information *table_info =
149                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
150         struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
151         struct pp_advance_fan_control_parameters *fan_table=
152                         &hwmgr->thermal_controller.advanceFanControlParameters;
153         uint8_t uc_scl, uc_sda;
154
155         /* TDP number of fraction bits are changed from 8 to 7 for Fiji
156          * as requested by SMC team
157          */
158         dpm_table->DefaultTdp = PP_HOST_TO_SMC_US(
159                         (uint16_t)(cac_dtp_table->usTDP * 128));
160         dpm_table->TargetTdp = PP_HOST_TO_SMC_US(
161                         (uint16_t)(cac_dtp_table->usTDP * 128));
162
163         PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
164                         "Target Operating Temp is out of Range!",);
165
166         dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp);
167         dpm_table->GpuTjHyst = 8;
168
169         dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase;
170
171         /* The following are for new Fiji Multi-input fan/thermal control */
172         dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US(
173                         cac_dtp_table->usTargetOperatingTemp * 256);
174         dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US(
175                         cac_dtp_table->usTemperatureLimitHotspot * 256);
176         dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US(
177                         cac_dtp_table->usTemperatureLimitLiquid1 * 256);
178         dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US(
179                         cac_dtp_table->usTemperatureLimitLiquid2 * 256);
180         dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US(
181                         cac_dtp_table->usTemperatureLimitVrVddc * 256);
182         dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US(
183                         cac_dtp_table->usTemperatureLimitVrMvdd * 256);
184         dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US(
185                         cac_dtp_table->usTemperatureLimitPlx * 256);
186
187         dpm_table->FanGainEdge = PP_HOST_TO_SMC_US(
188                         scale_fan_gain_settings(fan_table->usFanGainEdge));
189         dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US(
190                         scale_fan_gain_settings(fan_table->usFanGainHotspot));
191         dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US(
192                         scale_fan_gain_settings(fan_table->usFanGainLiquid));
193         dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US(
194                         scale_fan_gain_settings(fan_table->usFanGainVrVddc));
195         dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US(
196                         scale_fan_gain_settings(fan_table->usFanGainVrMvdd));
197         dpm_table->FanGainPlx = PP_HOST_TO_SMC_US(
198                         scale_fan_gain_settings(fan_table->usFanGainPlx));
199         dpm_table->FanGainHbm = PP_HOST_TO_SMC_US(
200                         scale_fan_gain_settings(fan_table->usFanGainHbm));
201
202         dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address;
203         dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address;
204         dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address;
205         dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address;
206
207         get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda);
208         dpm_table->Liquid_I2C_LineSCL = uc_scl;
209         dpm_table->Liquid_I2C_LineSDA = uc_sda;
210
211         get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda);
212         dpm_table->Vr_I2C_LineSCL = uc_scl;
213         dpm_table->Vr_I2C_LineSDA = uc_sda;
214
215         get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda);
216         dpm_table->Plx_I2C_LineSCL = uc_scl;
217         dpm_table->Plx_I2C_LineSDA = uc_sda;
218
219         return 0;
220 }
221
222 static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr)
223 {
224     struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
225     const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
226
227     data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
228     data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
229     data->power_tune_table.SviLoadLineTrimVddC = 3;
230     data->power_tune_table.SviLoadLineOffsetVddC = 0;
231
232     return 0;
233 }
234
235 static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr)
236 {
237         uint16_t tdc_limit;
238         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
239         struct phm_ppt_v1_information *table_info =
240                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
241         const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
242
243         /* TDC number of fraction bits are changed from 8 to 7
244          * for Fiji as requested by SMC team
245          */
246         tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128);
247         data->power_tune_table.TDC_VDDC_PkgLimit =
248                         CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
249         data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
250                         defaults->TDC_VDDC_ThrottleReleaseLimitPerc;
251         data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt;
252
253         return 0;
254 }
255
256 static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
257 {
258         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
259         const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
260         uint32_t temp;
261
262         if (fiji_read_smc_sram_dword(hwmgr->smumgr,
263                         fuse_table_offset +
264                         offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl),
265                         (uint32_t *)&temp, data->sram_end))
266                 PP_ASSERT_WITH_CODE(false,
267                                 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
268                                 return -EINVAL);
269         else {
270                 data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl;
271                 data->power_tune_table.LPMLTemperatureMin =
272                                 (uint8_t)((temp >> 16) & 0xff);
273                 data->power_tune_table.LPMLTemperatureMax =
274                                 (uint8_t)((temp >> 8) & 0xff);
275                 data->power_tune_table.Reserved = (uint8_t)(temp & 0xff);
276         }
277         return 0;
278 }
279
280 static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
281 {
282         int i;
283         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
284
285         /* Currently not used. Set all to zero. */
286         for (i = 0; i < 16; i++)
287                 data->power_tune_table.LPMLTemperatureScaler[i] = 0;
288
289         return 0;
290 }
291
292 static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
293 {
294         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
295
296         if( (hwmgr->thermal_controller.advanceFanControlParameters.
297                         usFanOutputSensitivity & (1 << 15)) ||
298                         0 == hwmgr->thermal_controller.advanceFanControlParameters.
299                         usFanOutputSensitivity )
300                 hwmgr->thermal_controller.advanceFanControlParameters.
301                 usFanOutputSensitivity = hwmgr->thermal_controller.
302                         advanceFanControlParameters.usDefaultFanOutputSensitivity;
303
304         data->power_tune_table.FuzzyFan_PwmSetDelta =
305                         PP_HOST_TO_SMC_US(hwmgr->thermal_controller.
306                                         advanceFanControlParameters.usFanOutputSensitivity);
307         return 0;
308 }
309
310 static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
311 {
312         int i;
313         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
314
315         /* Currently not used. Set all to zero. */
316         for (i = 0; i < 16; i++)
317                 data->power_tune_table.GnbLPML[i] = 0;
318
319         return 0;
320 }
321
322 static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
323 {
324  /*   int  i, min, max;
325     struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
326     uint8_t * pHiVID = data->power_tune_table.BapmVddCVidHiSidd;
327     uint8_t * pLoVID = data->power_tune_table.BapmVddCVidLoSidd;
328
329     min = max = pHiVID[0];
330     for (i = 0; i < 8; i++) {
331         if (0 != pHiVID[i]) {
332             if (min > pHiVID[i])
333                 min = pHiVID[i];
334             if (max < pHiVID[i])
335                 max = pHiVID[i];
336         }
337
338         if (0 != pLoVID[i]) {
339             if (min > pLoVID[i])
340                 min = pLoVID[i];
341             if (max < pLoVID[i])
342                 max = pLoVID[i];
343         }
344     }
345
346     PP_ASSERT_WITH_CODE((0 != min) && (0 != max), "BapmVddcVidSidd table does not exist!", return int_Failed);
347     data->power_tune_table.GnbLPMLMaxVid = (uint8_t)max;
348     data->power_tune_table.GnbLPMLMinVid = (uint8_t)min;
349 */
350     return 0;
351 }
352
353 static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
354 {
355         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
356         struct phm_ppt_v1_information *table_info =
357                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
358         uint16_t HiSidd = data->power_tune_table.BapmVddCBaseLeakageHiSidd;
359         uint16_t LoSidd = data->power_tune_table.BapmVddCBaseLeakageLoSidd;
360         struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
361
362         HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
363         LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
364
365         data->power_tune_table.BapmVddCBaseLeakageHiSidd =
366                         CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
367         data->power_tune_table.BapmVddCBaseLeakageLoSidd =
368                         CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
369
370         return 0;
371 }
372
373 int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr)
374 {
375         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
376         uint32_t pm_fuse_table_offset;
377
378         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
379                         PHM_PlatformCaps_PowerContainment)) {
380                 if (fiji_read_smc_sram_dword(hwmgr->smumgr,
381                                 SMU7_FIRMWARE_HEADER_LOCATION +
382                                 offsetof(SMU73_Firmware_Header, PmFuseTable),
383                                 &pm_fuse_table_offset, data->sram_end))
384                         PP_ASSERT_WITH_CODE(false,
385                                         "Attempt to get pm_fuse_table_offset Failed!",
386                                         return -EINVAL);
387
388                 /* DW6 */
389                 if (fiji_populate_svi_load_line(hwmgr))
390                         PP_ASSERT_WITH_CODE(false,
391                                         "Attempt to populate SviLoadLine Failed!",
392                                         return -EINVAL);
393                 /* DW7 */
394                 if (fiji_populate_tdc_limit(hwmgr))
395                         PP_ASSERT_WITH_CODE(false,
396                                         "Attempt to populate TDCLimit Failed!", return -EINVAL);
397                 /* DW8 */
398                 if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset))
399                         PP_ASSERT_WITH_CODE(false,
400                                         "Attempt to populate TdcWaterfallCtl, "
401                                         "LPMLTemperature Min and Max Failed!",
402                                         return -EINVAL);
403
404                 /* DW9-DW12 */
405                 if (0 != fiji_populate_temperature_scaler(hwmgr))
406                         PP_ASSERT_WITH_CODE(false,
407                                         "Attempt to populate LPMLTemperatureScaler Failed!",
408                                         return -EINVAL);
409
410                 /* DW13-DW14 */
411                 if(fiji_populate_fuzzy_fan(hwmgr))
412                         PP_ASSERT_WITH_CODE(false,
413                                         "Attempt to populate Fuzzy Fan Control parameters Failed!",
414                                         return -EINVAL);
415
416                 /* DW15-DW18 */
417                 if (fiji_populate_gnb_lpml(hwmgr))
418                         PP_ASSERT_WITH_CODE(false,
419                                         "Attempt to populate GnbLPML Failed!",
420                                         return -EINVAL);
421
422                 /* DW19 */
423                 if (fiji_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
424                         PP_ASSERT_WITH_CODE(false,
425                                         "Attempt to populate GnbLPML Min and Max Vid Failed!",
426                                         return -EINVAL);
427
428                 /* DW20 */
429                 if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr))
430                         PP_ASSERT_WITH_CODE(false,
431                                         "Attempt to populate BapmVddCBaseLeakage Hi and Lo "
432                                         "Sidd Failed!", return -EINVAL);
433
434                 if (fiji_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
435                                 (uint8_t *)&data->power_tune_table,
436                                 sizeof(struct SMU73_Discrete_PmFuses), data->sram_end))
437                         PP_ASSERT_WITH_CODE(false,
438                                         "Attempt to download PmFuseTable Failed!",
439                                         return -EINVAL);
440         }
441         return 0;
442 }
443
444 int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr)
445 {
446         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
447         int result = 0;
448
449         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
450                         PHM_PlatformCaps_CAC)) {
451                 int smc_result;
452                 smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
453                                 (uint16_t)(PPSMC_MSG_EnableCac));
454                 PP_ASSERT_WITH_CODE((0 == smc_result),
455                                 "Failed to enable CAC in SMC.", result = -1);
456
457         data->cac_enabled = (0 == smc_result) ? true : false;
458         }
459         return result;
460 }
461
462 int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
463 {
464         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
465
466         if(data->power_containment_features &
467                         POWERCONTAINMENT_FEATURE_PkgPwrLimit)
468                 return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
469                                 PPSMC_MSG_PkgPwrSetLimit, n);
470         return 0;
471 }
472
473 static int fiji_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
474 {
475         return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
476                         PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
477 }
478
479 int fiji_enable_power_containment(struct pp_hwmgr *hwmgr)
480 {
481         struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
482         struct phm_ppt_v1_information *table_info =
483                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
484         int smc_result;
485         int result = 0;
486
487         data->power_containment_features = 0;
488         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
489                         PHM_PlatformCaps_PowerContainment)) {
490                 if (data->enable_dte_feature) {
491                         smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
492                                         (uint16_t)(PPSMC_MSG_EnableDTE));
493                         PP_ASSERT_WITH_CODE((0 == smc_result),
494                                         "Failed to enable DTE in SMC.", result = -1;);
495                         if (0 == smc_result)
496                                 data->power_containment_features |= POWERCONTAINMENT_FEATURE_DTE;
497                 }
498
499                 if (data->enable_tdc_limit_feature) {
500                         smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
501                                         (uint16_t)(PPSMC_MSG_TDCLimitEnable));
502                         PP_ASSERT_WITH_CODE((0 == smc_result),
503                                         "Failed to enable TDCLimit in SMC.", result = -1;);
504                         if (0 == smc_result)
505                                 data->power_containment_features |=
506                                                 POWERCONTAINMENT_FEATURE_TDCLimit;
507                 }
508
509                 if (data->enable_pkg_pwr_tracking_feature) {
510                         smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
511                                         (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable));
512                         PP_ASSERT_WITH_CODE((0 == smc_result),
513                                         "Failed to enable PkgPwrTracking in SMC.", result = -1;);
514                         if (0 == smc_result) {
515                                 struct phm_cac_tdp_table *cac_table =
516                                                 table_info->cac_dtp_table;
517                                 uint32_t default_limit =
518                                         (uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256);
519
520                                 data->power_containment_features |=
521                                                 POWERCONTAINMENT_FEATURE_PkgPwrLimit;
522
523                                 if (fiji_set_power_limit(hwmgr, default_limit))
524                                         printk(KERN_ERR "Failed to set Default Power Limit in SMC!");
525                         }
526                 }
527         }
528         return result;
529 }
530
531 int fiji_power_control_set_level(struct pp_hwmgr *hwmgr)
532 {
533         struct phm_ppt_v1_information *table_info =
534                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
535         struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
536         int adjust_percent, target_tdp;
537         int result = 0;
538
539         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
540                         PHM_PlatformCaps_PowerContainment)) {
541                 /* adjustment percentage has already been validated */
542                 adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
543                                 hwmgr->platform_descriptor.TDPAdjustment :
544                                 (-1 * hwmgr->platform_descriptor.TDPAdjustment);
545                 /* SMC requested that target_tdp to be 7 bit fraction in DPM table
546                  * but message to be 8 bit fraction for messages
547                  */
548                 target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100;
549                 result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp);
550         }
551
552         return result;
553 }