Merge branch 'drm-next-4.14' of git://people.freedesktop.org/~agd5f/linux into drm...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / powerplay / smumgr / polaris10_smc.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 "pp_debug.h"
25 #include "polaris10_smc.h"
26 #include "smu7_dyn_defaults.h"
27
28 #include "smu7_hwmgr.h"
29 #include "hardwaremanager.h"
30 #include "ppatomctrl.h"
31 #include "cgs_common.h"
32 #include "atombios.h"
33 #include "polaris10_smumgr.h"
34 #include "pppcielanes.h"
35
36 #include "smu_ucode_xfer_vi.h"
37 #include "smu74_discrete.h"
38 #include "smu/smu_7_1_3_d.h"
39 #include "smu/smu_7_1_3_sh_mask.h"
40 #include "gmc/gmc_8_1_d.h"
41 #include "gmc/gmc_8_1_sh_mask.h"
42 #include "oss/oss_3_0_d.h"
43 #include "gca/gfx_8_0_d.h"
44 #include "bif/bif_5_0_d.h"
45 #include "bif/bif_5_0_sh_mask.h"
46 #include "dce/dce_10_0_d.h"
47 #include "dce/dce_10_0_sh_mask.h"
48 #include "polaris10_pwrvirus.h"
49 #include "smu7_ppsmc.h"
50 #include "smu7_smumgr.h"
51
52 #define POLARIS10_SMC_SIZE 0x20000
53 #define VOLTAGE_VID_OFFSET_SCALE1   625
54 #define VOLTAGE_VID_OFFSET_SCALE2   100
55 #define POWERTUNE_DEFAULT_SET_MAX    1
56 #define VDDC_VDDCI_DELTA            200
57 #define MC_CG_ARB_FREQ_F1           0x0b
58
59 static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
60         /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
61          * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */
62         { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
63         { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
64         { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } },
65 };
66
67 static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = {
68                         {VCO_2_4, POSTDIV_DIV_BY_16,  75, 160, 112},
69                         {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160},
70                         {VCO_2_4, POSTDIV_DIV_BY_8,   75, 160, 112},
71                         {VCO_3_6, POSTDIV_DIV_BY_8,  112, 224, 160},
72                         {VCO_2_4, POSTDIV_DIV_BY_4,   75, 160, 112},
73                         {VCO_3_6, POSTDIV_DIV_BY_4,  112, 216, 160},
74                         {VCO_2_4, POSTDIV_DIV_BY_2,   75, 160, 108},
75                         {VCO_3_6, POSTDIV_DIV_BY_2,  112, 216, 160} };
76
77 static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
78                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
79                 uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
80 {
81         uint32_t i;
82         uint16_t vddci;
83         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
84
85         *voltage = *mvdd = 0;
86
87         /* clock - voltage dependency table is empty table */
88         if (dep_table->count == 0)
89                 return -EINVAL;
90
91         for (i = 0; i < dep_table->count; i++) {
92                 /* find first sclk bigger than request */
93                 if (dep_table->entries[i].clk >= clock) {
94                         *voltage |= (dep_table->entries[i].vddc *
95                                         VOLTAGE_SCALE) << VDDC_SHIFT;
96                         if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
97                                 *voltage |= (data->vbios_boot_state.vddci_bootup_value *
98                                                 VOLTAGE_SCALE) << VDDCI_SHIFT;
99                         else if (dep_table->entries[i].vddci)
100                                 *voltage |= (dep_table->entries[i].vddci *
101                                                 VOLTAGE_SCALE) << VDDCI_SHIFT;
102                         else {
103                                 vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
104                                                 (dep_table->entries[i].vddc -
105                                                                 (uint16_t)VDDC_VDDCI_DELTA));
106                                 *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
107                         }
108
109                         if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
110                                 *mvdd = data->vbios_boot_state.mvdd_bootup_value *
111                                         VOLTAGE_SCALE;
112                         else if (dep_table->entries[i].mvdd)
113                                 *mvdd = (uint32_t) dep_table->entries[i].mvdd *
114                                         VOLTAGE_SCALE;
115
116                         *voltage |= 1 << PHASES_SHIFT;
117                         return 0;
118                 }
119         }
120
121         /* sclk is bigger than max sclk in the dependence table */
122         *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
123
124         if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
125                 *voltage |= (data->vbios_boot_state.vddci_bootup_value *
126                                 VOLTAGE_SCALE) << VDDCI_SHIFT;
127         else if (dep_table->entries[i-1].vddci) {
128                 vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
129                                 (dep_table->entries[i].vddc -
130                                                 (uint16_t)VDDC_VDDCI_DELTA));
131                 *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
132         }
133
134         if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
135                 *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
136         else if (dep_table->entries[i].mvdd)
137                 *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE;
138
139         return 0;
140 }
141
142 static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
143 {
144         uint32_t tmp;
145         tmp = raw_setting * 4096 / 100;
146         return (uint16_t)tmp;
147 }
148
149 static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
150 {
151         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
152
153         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
154         SMU74_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
155         struct phm_ppt_v1_information *table_info =
156                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
157         struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
158         struct pp_advance_fan_control_parameters *fan_table =
159                         &hwmgr->thermal_controller.advanceFanControlParameters;
160         int i, j, k;
161         const uint16_t *pdef1;
162         const uint16_t *pdef2;
163
164         table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128));
165         table->TargetTdp  = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128));
166
167         PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
168                                 "Target Operating Temp is out of Range!",
169                                 );
170
171         table->TemperatureLimitEdge = PP_HOST_TO_SMC_US(
172                         cac_dtp_table->usTargetOperatingTemp * 256);
173         table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US(
174                         cac_dtp_table->usTemperatureLimitHotspot * 256);
175         table->FanGainEdge = PP_HOST_TO_SMC_US(
176                         scale_fan_gain_settings(fan_table->usFanGainEdge));
177         table->FanGainHotspot = PP_HOST_TO_SMC_US(
178                         scale_fan_gain_settings(fan_table->usFanGainHotspot));
179
180         pdef1 = defaults->BAPMTI_R;
181         pdef2 = defaults->BAPMTI_RC;
182
183         for (i = 0; i < SMU74_DTE_ITERATIONS; i++) {
184                 for (j = 0; j < SMU74_DTE_SOURCES; j++) {
185                         for (k = 0; k < SMU74_DTE_SINKS; k++) {
186                                 table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1);
187                                 table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2);
188                                 pdef1++;
189                                 pdef2++;
190                         }
191                 }
192         }
193
194         return 0;
195 }
196
197 static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr)
198 {
199         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
200         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
201
202         smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
203         smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
204         smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
205         smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
206
207         return 0;
208 }
209
210 static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr)
211 {
212         uint16_t tdc_limit;
213         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
214         struct phm_ppt_v1_information *table_info =
215                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
216         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
217
218         tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128);
219         smu_data->power_tune_table.TDC_VDDC_PkgLimit =
220                         CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
221         smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
222                         defaults->TDC_VDDC_ThrottleReleaseLimitPerc;
223         smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt;
224
225         return 0;
226 }
227
228 static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
229 {
230         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
231         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
232         uint32_t temp;
233
234         if (smu7_read_smc_sram_dword(hwmgr->smumgr,
235                         fuse_table_offset +
236                         offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl),
237                         (uint32_t *)&temp, SMC_RAM_END))
238                 PP_ASSERT_WITH_CODE(false,
239                                 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
240                                 return -EINVAL);
241         else {
242                 smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl;
243                 smu_data->power_tune_table.LPMLTemperatureMin =
244                                 (uint8_t)((temp >> 16) & 0xff);
245                 smu_data->power_tune_table.LPMLTemperatureMax =
246                                 (uint8_t)((temp >> 8) & 0xff);
247                 smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff);
248         }
249         return 0;
250 }
251
252 static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
253 {
254         int i;
255         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
256
257         /* Currently not used. Set all to zero. */
258         for (i = 0; i < 16; i++)
259                 smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0;
260
261         return 0;
262 }
263
264 static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
265 {
266         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
267
268 /* TO DO move to hwmgr */
269         if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15))
270                 || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity)
271                 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
272                         hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity;
273
274         smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US(
275                                 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity);
276         return 0;
277 }
278
279 static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
280 {
281         int i;
282         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
283
284         /* Currently not used. Set all to zero. */
285         for (i = 0; i < 16; i++)
286                 smu_data->power_tune_table.GnbLPML[i] = 0;
287
288         return 0;
289 }
290
291 static int polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
292 {
293         return 0;
294 }
295
296 static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
297 {
298         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
299         struct phm_ppt_v1_information *table_info =
300                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
301         uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
302         uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
303         struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
304
305         hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
306         lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
307
308         smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
309                         CONVERT_FROM_HOST_TO_SMC_US(hi_sidd);
310         smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
311                         CONVERT_FROM_HOST_TO_SMC_US(lo_sidd);
312
313         return 0;
314 }
315
316 static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr)
317 {
318         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
319         uint32_t pm_fuse_table_offset;
320
321         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
322                         PHM_PlatformCaps_PowerContainment)) {
323                 if (smu7_read_smc_sram_dword(hwmgr->smumgr,
324                                 SMU7_FIRMWARE_HEADER_LOCATION +
325                                 offsetof(SMU74_Firmware_Header, PmFuseTable),
326                                 &pm_fuse_table_offset, SMC_RAM_END))
327                         PP_ASSERT_WITH_CODE(false,
328                                         "Attempt to get pm_fuse_table_offset Failed!",
329                                         return -EINVAL);
330
331                 if (polaris10_populate_svi_load_line(hwmgr))
332                         PP_ASSERT_WITH_CODE(false,
333                                         "Attempt to populate SviLoadLine Failed!",
334                                         return -EINVAL);
335
336                 if (polaris10_populate_tdc_limit(hwmgr))
337                         PP_ASSERT_WITH_CODE(false,
338                                         "Attempt to populate TDCLimit Failed!", return -EINVAL);
339
340                 if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset))
341                         PP_ASSERT_WITH_CODE(false,
342                                         "Attempt to populate TdcWaterfallCtl, "
343                                         "LPMLTemperature Min and Max Failed!",
344                                         return -EINVAL);
345
346                 if (0 != polaris10_populate_temperature_scaler(hwmgr))
347                         PP_ASSERT_WITH_CODE(false,
348                                         "Attempt to populate LPMLTemperatureScaler Failed!",
349                                         return -EINVAL);
350
351                 if (polaris10_populate_fuzzy_fan(hwmgr))
352                         PP_ASSERT_WITH_CODE(false,
353                                         "Attempt to populate Fuzzy Fan Control parameters Failed!",
354                                         return -EINVAL);
355
356                 if (polaris10_populate_gnb_lpml(hwmgr))
357                         PP_ASSERT_WITH_CODE(false,
358                                         "Attempt to populate GnbLPML Failed!",
359                                         return -EINVAL);
360
361                 if (polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
362                         PP_ASSERT_WITH_CODE(false,
363                                         "Attempt to populate GnbLPML Min and Max Vid Failed!",
364                                         return -EINVAL);
365
366                 if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr))
367                         PP_ASSERT_WITH_CODE(false,
368                                         "Attempt to populate BapmVddCBaseLeakage Hi and Lo "
369                                         "Sidd Failed!", return -EINVAL);
370
371                 if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
372                                 (uint8_t *)&smu_data->power_tune_table,
373                                 (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END))
374                         PP_ASSERT_WITH_CODE(false,
375                                         "Attempt to download PmFuseTable Failed!",
376                                         return -EINVAL);
377         }
378         return 0;
379 }
380
381 /**
382  * Mvdd table preparation for SMC.
383  *
384  * @param    *hwmgr The address of the hardware manager.
385  * @param    *table The SMC DPM table structure to be populated.
386  * @return   0
387  */
388 static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
389                         SMU74_Discrete_DpmTable *table)
390 {
391         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
392         uint32_t count, level;
393
394         if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
395                 count = data->mvdd_voltage_table.count;
396                 if (count > SMU_MAX_SMIO_LEVELS)
397                         count = SMU_MAX_SMIO_LEVELS;
398                 for (level = 0; level < count; level++) {
399                         table->SmioTable2.Pattern[level].Voltage =
400                                 PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
401                         /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
402                         table->SmioTable2.Pattern[level].Smio =
403                                 (uint8_t) level;
404                         table->Smio[level] |=
405                                 data->mvdd_voltage_table.entries[level].smio_low;
406                 }
407                 table->SmioMask2 = data->mvdd_voltage_table.mask_low;
408
409                 table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count);
410         }
411
412         return 0;
413 }
414
415 static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr,
416                                         struct SMU74_Discrete_DpmTable *table)
417 {
418         uint32_t count, level;
419         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
420
421         count = data->vddci_voltage_table.count;
422
423         if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
424                 if (count > SMU_MAX_SMIO_LEVELS)
425                         count = SMU_MAX_SMIO_LEVELS;
426                 for (level = 0; level < count; ++level) {
427                         table->SmioTable1.Pattern[level].Voltage =
428                                 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE);
429                         table->SmioTable1.Pattern[level].Smio = (uint8_t) level;
430
431                         table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low;
432                 }
433         }
434
435         table->SmioMask1 = data->vddci_voltage_table.mask_low;
436
437         return 0;
438 }
439
440 /**
441 * Preparation of vddc and vddgfx CAC tables for SMC.
442 *
443 * @param    hwmgr  the address of the hardware manager
444 * @param    table  the SMC DPM table structure to be populated
445 * @return   always 0
446 */
447 static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr,
448                 struct SMU74_Discrete_DpmTable *table)
449 {
450         uint32_t count;
451         uint8_t index;
452         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
453         struct phm_ppt_v1_information *table_info =
454                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
455         struct phm_ppt_v1_voltage_lookup_table *lookup_table =
456                         table_info->vddc_lookup_table;
457         /* tables is already swapped, so in order to use the value from it,
458          * we need to swap it back.
459          * We are populating vddc CAC data to BapmVddc table
460          * in split and merged mode
461          */
462         for (count = 0; count < lookup_table->count; count++) {
463                 index = phm_get_voltage_index(lookup_table,
464                                 data->vddc_voltage_table.entries[count].value);
465                 table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low);
466                 table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid);
467                 table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high);
468         }
469
470         return 0;
471 }
472
473 /**
474 * Preparation of voltage tables for SMC.
475 *
476 * @param    hwmgr   the address of the hardware manager
477 * @param    table   the SMC DPM table structure to be populated
478 * @return   always  0
479 */
480
481 static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
482                 struct SMU74_Discrete_DpmTable *table)
483 {
484         polaris10_populate_smc_vddci_table(hwmgr, table);
485         polaris10_populate_smc_mvdd_table(hwmgr, table);
486         polaris10_populate_cac_table(hwmgr, table);
487
488         return 0;
489 }
490
491 static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr,
492                 struct SMU74_Discrete_Ulv *state)
493 {
494         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
495         struct phm_ppt_v1_information *table_info =
496                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
497         struct pp_smumgr *smumgr = hwmgr->smumgr;
498
499         state->CcPwrDynRm = 0;
500         state->CcPwrDynRm1 = 0;
501
502         state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
503         state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
504                         VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
505
506         if (smumgr->chip_id == CHIP_POLARIS12 || smumgr->is_kicker)
507                 state->VddcPhase = data->vddc_phase_shed_control ^ 0x3;
508         else
509                 state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1;
510
511         CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
512         CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
513         CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
514
515         return 0;
516 }
517
518 static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr,
519                 struct SMU74_Discrete_DpmTable *table)
520 {
521         return polaris10_populate_ulv_level(hwmgr, &table->Ulv);
522 }
523
524 static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr,
525                 struct SMU74_Discrete_DpmTable *table)
526 {
527         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
528         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
529         struct smu7_dpm_table *dpm_table = &data->dpm_table;
530         int i;
531
532         /* Index (dpm_table->pcie_speed_table.count)
533          * is reserved for PCIE boot level. */
534         for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
535                 table->LinkLevel[i].PcieGenSpeed  =
536                                 (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
537                 table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width(
538                                 dpm_table->pcie_speed_table.dpm_levels[i].param1);
539                 table->LinkLevel[i].EnabledForActivity = 1;
540                 table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff);
541                 table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5);
542                 table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30);
543         }
544
545         smu_data->smc_state_table.LinkLevelCount =
546                         (uint8_t)dpm_table->pcie_speed_table.count;
547
548 /* To Do move to hwmgr */
549         data->dpm_level_enable_mask.pcie_dpm_enable_mask =
550                         phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
551
552         return 0;
553 }
554
555
556 static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr,
557                                    SMU74_Discrete_DpmTable  *table)
558 {
559         struct pp_smumgr *smumgr = hwmgr->smumgr;
560         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
561         uint32_t i, ref_clk;
562
563         struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } };
564
565         ref_clk = smu7_get_xclk(hwmgr);
566
567         if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) {
568                 for (i = 0; i < NUM_SCLK_RANGE; i++) {
569                         table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting;
570                         table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv;
571                         table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc;
572
573                         table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper;
574                         table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower;
575
576                         CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc);
577                         CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper);
578                         CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower);
579                 }
580                 return;
581         }
582
583         for (i = 0; i < NUM_SCLK_RANGE; i++) {
584                 smu_data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv;
585                 smu_data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv;
586
587                 table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting;
588                 table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv;
589                 table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc;
590
591                 table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper;
592                 table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower;
593
594                 CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc);
595                 CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper);
596                 CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower);
597         }
598 }
599
600 /**
601 * Calculates the SCLK dividers using the provided engine clock
602 *
603 * @param    hwmgr  the address of the hardware manager
604 * @param    clock  the engine clock to use to populate the structure
605 * @param    sclk   the SMC SCLK structure to be populated
606 */
607 static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr,
608                 uint32_t clock, SMU_SclkSetting *sclk_setting)
609 {
610         struct pp_smumgr *smumgr = hwmgr->smumgr;
611         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
612         const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table);
613         struct pp_atomctrl_clock_dividers_ai dividers;
614         uint32_t ref_clock;
615         uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq;
616         uint8_t i;
617         int result;
618         uint64_t temp;
619
620         sclk_setting->SclkFrequency = clock;
621         /* get the engine clock dividers for this clock value */
622         result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock,  &dividers);
623         if (result == 0) {
624                 sclk_setting->Fcw_int = dividers.usSclk_fcw_int;
625                 sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac;
626                 sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int;
627                 sclk_setting->PllRange = dividers.ucSclkPllRange;
628                 sclk_setting->Sclk_slew_rate = 0x400;
629                 sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac;
630                 sclk_setting->Pcc_down_slew_rate = 0xffff;
631                 sclk_setting->SSc_En = dividers.ucSscEnable;
632                 sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int;
633                 sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac;
634                 sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac;
635                 return result;
636         }
637
638         ref_clock = smu7_get_xclk(hwmgr);
639
640         for (i = 0; i < NUM_SCLK_RANGE; i++) {
641                 if (clock > smu_data->range_table[i].trans_lower_frequency
642                 && clock <= smu_data->range_table[i].trans_upper_frequency) {
643                         sclk_setting->PllRange = i;
644                         break;
645                 }
646         }
647
648         sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
649         temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv;
650         temp <<= 0x10;
651         do_div(temp, ref_clock);
652         sclk_setting->Fcw_frac = temp & 0xffff;
653
654         pcc_target_percent = 10; /*  Hardcode 10% for now. */
655         pcc_target_freq = clock - (clock * pcc_target_percent / 100);
656         sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
657
658         ss_target_percent = 2; /*  Hardcode 2% for now. */
659         sclk_setting->SSc_En = 0;
660         if (ss_target_percent) {
661                 sclk_setting->SSc_En = 1;
662                 ss_target_freq = clock - (clock * ss_target_percent / 100);
663                 sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
664                 temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv;
665                 temp <<= 0x10;
666                 do_div(temp, ref_clock);
667                 sclk_setting->Fcw1_frac = temp & 0xffff;
668         }
669
670         return 0;
671 }
672
673 /**
674 * Populates single SMC SCLK structure using the provided engine clock
675 *
676 * @param    hwmgr      the address of the hardware manager
677 * @param    clock the engine clock to use to populate the structure
678 * @param    sclk        the SMC SCLK structure to be populated
679 */
680
681 static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
682                 uint32_t clock, uint16_t sclk_al_threshold,
683                 struct SMU74_Discrete_GraphicsLevel *level)
684 {
685         int result;
686         /* PP_Clocks minClocks; */
687         uint32_t mvdd;
688         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
689         struct phm_ppt_v1_information *table_info =
690                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
691         SMU_SclkSetting curr_sclk_setting = { 0 };
692
693         result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting);
694
695         /* populate graphics levels */
696         result = polaris10_get_dependency_volt_by_clk(hwmgr,
697                         table_info->vdd_dep_on_sclk, clock,
698                         &level->MinVoltage, &mvdd);
699
700         PP_ASSERT_WITH_CODE((0 == result),
701                         "can not find VDDC voltage value for "
702                         "VDDC engine clock dependency table",
703                         return result);
704         level->ActivityLevel = sclk_al_threshold;
705
706         level->CcPwrDynRm = 0;
707         level->CcPwrDynRm1 = 0;
708         level->EnabledForActivity = 0;
709         level->EnabledForThrottle = 1;
710         level->UpHyst = 10;
711         level->DownHyst = 0;
712         level->VoltageDownHyst = 0;
713         level->PowerThrottle = 0;
714         data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
715
716         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
717                 level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock,
718                                                                 hwmgr->display_config.min_core_set_clock_in_sr);
719
720         /* Default to slow, highest DPM level will be
721          * set to PPSMC_DISPLAY_WATERMARK_LOW later.
722          */
723         if (data->update_up_hyst)
724                 level->UpHyst = (uint8_t)data->up_hyst;
725         if (data->update_down_hyst)
726                 level->DownHyst = (uint8_t)data->down_hyst;
727
728         level->SclkSetting = curr_sclk_setting;
729
730         CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage);
731         CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm);
732         CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1);
733         CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel);
734         CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency);
735         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int);
736         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac);
737         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int);
738         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate);
739         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate);
740         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate);
741         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int);
742         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac);
743         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate);
744         return 0;
745 }
746
747 /**
748 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
749 *
750 * @param    hwmgr      the address of the hardware manager
751 */
752 int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
753 {
754         struct pp_smumgr *smumgr = hwmgr->smumgr;
755         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
756         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
757         struct smu7_dpm_table *dpm_table = &hw_data->dpm_table;
758         struct phm_ppt_v1_information *table_info =
759                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
760         struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
761         uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count;
762         int result = 0;
763         uint32_t array = smu_data->smu7_data.dpm_table_start +
764                         offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
765         uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
766                         SMU74_MAX_LEVELS_GRAPHICS;
767         struct SMU74_Discrete_GraphicsLevel *levels =
768                         smu_data->smc_state_table.GraphicsLevel;
769         uint32_t i, max_entry;
770         uint8_t hightest_pcie_level_enabled = 0,
771                 lowest_pcie_level_enabled = 0,
772                 mid_pcie_level_enabled = 0,
773                 count = 0;
774
775         polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table));
776
777         for (i = 0; i < dpm_table->sclk_table.count; i++) {
778
779                 result = polaris10_populate_single_graphic_level(hwmgr,
780                                 dpm_table->sclk_table.dpm_levels[i].value,
781                                 (uint16_t)smu_data->activity_target[i],
782                                 &(smu_data->smc_state_table.GraphicsLevel[i]));
783                 if (result)
784                         return result;
785
786                 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
787                 if (i > 1)
788                         levels[i].DeepSleepDivId = 0;
789         }
790         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
791                                         PHM_PlatformCaps_SPLLShutdownSupport))
792                 smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0;
793
794         smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
795         smu_data->smc_state_table.GraphicsDpmLevelCount =
796                         (uint8_t)dpm_table->sclk_table.count;
797         hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask =
798                         phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
799
800
801         if (pcie_table != NULL) {
802                 PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt),
803                                 "There must be 1 or more PCIE levels defined in PPTable.",
804                                 return -EINVAL);
805                 max_entry = pcie_entry_cnt - 1;
806                 for (i = 0; i < dpm_table->sclk_table.count; i++)
807                         levels[i].pcieDpmLevel =
808                                         (uint8_t) ((i < max_entry) ? i : max_entry);
809         } else {
810                 while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
811                                 ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &
812                                                 (1 << (hightest_pcie_level_enabled + 1))) != 0))
813                         hightest_pcie_level_enabled++;
814
815                 while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
816                                 ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &
817                                                 (1 << lowest_pcie_level_enabled)) == 0))
818                         lowest_pcie_level_enabled++;
819
820                 while ((count < hightest_pcie_level_enabled) &&
821                                 ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &
822                                                 (1 << (lowest_pcie_level_enabled + 1 + count))) == 0))
823                         count++;
824
825                 mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) <
826                                 hightest_pcie_level_enabled ?
827                                                 (lowest_pcie_level_enabled + 1 + count) :
828                                                 hightest_pcie_level_enabled;
829
830                 /* set pcieDpmLevel to hightest_pcie_level_enabled */
831                 for (i = 2; i < dpm_table->sclk_table.count; i++)
832                         levels[i].pcieDpmLevel = hightest_pcie_level_enabled;
833
834                 /* set pcieDpmLevel to lowest_pcie_level_enabled */
835                 levels[0].pcieDpmLevel = lowest_pcie_level_enabled;
836
837                 /* set pcieDpmLevel to mid_pcie_level_enabled */
838                 levels[1].pcieDpmLevel = mid_pcie_level_enabled;
839         }
840         /* level count will send to smc once at init smc table and never change */
841         result = smu7_copy_bytes_to_smc(smumgr, array, (uint8_t *)levels,
842                         (uint32_t)array_size, SMC_RAM_END);
843
844         return result;
845 }
846
847
848 static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
849                 uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level)
850 {
851         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
852         struct phm_ppt_v1_information *table_info =
853                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
854         int result = 0;
855         struct cgs_display_info info = {0, 0, NULL};
856         uint32_t mclk_stutter_mode_threshold = 40000;
857
858         cgs_get_active_displays_info(hwmgr->device, &info);
859
860         if (table_info->vdd_dep_on_mclk) {
861                 result = polaris10_get_dependency_volt_by_clk(hwmgr,
862                                 table_info->vdd_dep_on_mclk, clock,
863                                 &mem_level->MinVoltage, &mem_level->MinMvdd);
864                 PP_ASSERT_WITH_CODE((0 == result),
865                                 "can not find MinVddc voltage value from memory "
866                                 "VDDC voltage dependency table", return result);
867         }
868
869         mem_level->MclkFrequency = clock;
870         mem_level->EnabledForThrottle = 1;
871         mem_level->EnabledForActivity = 0;
872         mem_level->UpHyst = 0;
873         mem_level->DownHyst = 100;
874         mem_level->VoltageDownHyst = 0;
875         mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
876         mem_level->StutterEnable = false;
877         mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
878
879         data->display_timing.num_existing_displays = info.display_count;
880
881         if (mclk_stutter_mode_threshold &&
882                 (clock <= mclk_stutter_mode_threshold) &&
883                 (SMUM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL,
884                                 STUTTER_ENABLE) & 0x1))
885                 mem_level->StutterEnable = true;
886
887         if (!result) {
888                 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd);
889                 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency);
890                 CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel);
891                 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage);
892         }
893         return result;
894 }
895
896 /**
897 * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
898 *
899 * @param    hwmgr      the address of the hardware manager
900 */
901 int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
902 {
903         struct pp_smumgr *smumgr = hwmgr->smumgr;
904         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
905         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
906         struct smu7_dpm_table *dpm_table = &hw_data->dpm_table;
907         int result;
908         /* populate MCLK dpm table to SMU7 */
909         uint32_t array = smu_data->smu7_data.dpm_table_start +
910                         offsetof(SMU74_Discrete_DpmTable, MemoryLevel);
911         uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) *
912                         SMU74_MAX_LEVELS_MEMORY;
913         struct SMU74_Discrete_MemoryLevel *levels =
914                         smu_data->smc_state_table.MemoryLevel;
915         uint32_t i;
916
917         for (i = 0; i < dpm_table->mclk_table.count; i++) {
918                 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
919                                 "can not populate memory level as memory clock is zero",
920                                 return -EINVAL);
921                 result = polaris10_populate_single_memory_level(hwmgr,
922                                 dpm_table->mclk_table.dpm_levels[i].value,
923                                 &levels[i]);
924                 if (i == dpm_table->mclk_table.count - 1) {
925                         levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
926                         levels[i].EnabledForActivity = 1;
927                 }
928                 if (result)
929                         return result;
930         }
931
932         /* In order to prevent MC activity from stutter mode to push DPM up,
933          * the UVD change complements this by putting the MCLK in
934          * a higher state by default such that we are not affected by
935          * up threshold or and MCLK DPM latency.
936          */
937         levels[0].ActivityLevel = 0x1f;
938         CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
939
940         smu_data->smc_state_table.MemoryDpmLevelCount =
941                         (uint8_t)dpm_table->mclk_table.count;
942         hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask =
943                         phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
944
945         /* level count will send to smc once at init smc table and never change */
946         result = smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
947                         (uint32_t)array_size, SMC_RAM_END);
948
949         return result;
950 }
951
952 /**
953 * Populates the SMC MVDD structure using the provided memory clock.
954 *
955 * @param    hwmgr      the address of the hardware manager
956 * @param    mclk        the MCLK value to be used in the decision if MVDD should be high or low.
957 * @param    voltage     the SMC VOLTAGE structure to be populated
958 */
959 static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr,
960                 uint32_t mclk, SMIO_Pattern *smio_pat)
961 {
962         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
963         struct phm_ppt_v1_information *table_info =
964                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
965         uint32_t i = 0;
966
967         if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
968                 /* find mvdd value which clock is more than request */
969                 for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
970                         if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
971                                 smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value;
972                                 break;
973                         }
974                 }
975                 PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
976                                 "MVDD Voltage is outside the supported range.",
977                                 return -EINVAL);
978         } else
979                 return -EINVAL;
980
981         return 0;
982 }
983
984 static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
985                 SMU74_Discrete_DpmTable *table)
986 {
987         int result = 0;
988         uint32_t sclk_frequency;
989         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
990         struct phm_ppt_v1_information *table_info =
991                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
992         SMIO_Pattern vol_level;
993         uint32_t mvdd;
994         uint16_t us_mvdd;
995
996         table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
997
998         /* Get MinVoltage and Frequency from DPM0,
999          * already converted to SMC_UL */
1000         sclk_frequency = data->vbios_boot_state.sclk_bootup_value;
1001         result = polaris10_get_dependency_volt_by_clk(hwmgr,
1002                         table_info->vdd_dep_on_sclk,
1003                         sclk_frequency,
1004                         &table->ACPILevel.MinVoltage, &mvdd);
1005         PP_ASSERT_WITH_CODE((0 == result),
1006                         "Cannot find ACPI VDDC voltage value "
1007                         "in Clock Dependency Table",
1008                         );
1009
1010         result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency,  &(table->ACPILevel.SclkSetting));
1011         PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result);
1012
1013         table->ACPILevel.DeepSleepDivId = 0;
1014         table->ACPILevel.CcPwrDynRm = 0;
1015         table->ACPILevel.CcPwrDynRm1 = 0;
1016
1017         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1018         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage);
1019         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1020         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1021
1022         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency);
1023         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int);
1024         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac);
1025         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int);
1026         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate);
1027         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate);
1028         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate);
1029         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int);
1030         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac);
1031         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate);
1032
1033
1034         /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
1035         table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value;
1036         result = polaris10_get_dependency_volt_by_clk(hwmgr,
1037                         table_info->vdd_dep_on_mclk,
1038                         table->MemoryACPILevel.MclkFrequency,
1039                         &table->MemoryACPILevel.MinVoltage, &mvdd);
1040         PP_ASSERT_WITH_CODE((0 == result),
1041                         "Cannot find ACPI VDDCI voltage value "
1042                         "in Clock Dependency Table",
1043                         );
1044
1045         us_mvdd = 0;
1046         if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) ||
1047                         (data->mclk_dpm_key_disabled))
1048                 us_mvdd = data->vbios_boot_state.mvdd_bootup_value;
1049         else {
1050                 if (!polaris10_populate_mvdd_value(hwmgr,
1051                                 data->dpm_table.mclk_table.dpm_levels[0].value,
1052                                 &vol_level))
1053                         us_mvdd = vol_level.Voltage;
1054         }
1055
1056         if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level))
1057                 table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage);
1058         else
1059                 table->MemoryACPILevel.MinMvdd = 0;
1060
1061         table->MemoryACPILevel.StutterEnable = false;
1062
1063         table->MemoryACPILevel.EnabledForThrottle = 0;
1064         table->MemoryACPILevel.EnabledForActivity = 0;
1065         table->MemoryACPILevel.UpHyst = 0;
1066         table->MemoryACPILevel.DownHyst = 100;
1067         table->MemoryACPILevel.VoltageDownHyst = 0;
1068         table->MemoryACPILevel.ActivityLevel =
1069                         PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
1070
1071         CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
1072         CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
1073
1074         return result;
1075 }
1076
1077 static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1078                 SMU74_Discrete_DpmTable *table)
1079 {
1080         int result = -EINVAL;
1081         uint8_t count;
1082         struct pp_atomctrl_clock_dividers_vi dividers;
1083         struct phm_ppt_v1_information *table_info =
1084                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1085         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1086                         table_info->mm_dep_table;
1087         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1088         uint32_t vddci;
1089
1090         table->VceLevelCount = (uint8_t)(mm_table->count);
1091         table->VceBootLevel = 0;
1092
1093         for (count = 0; count < table->VceLevelCount; count++) {
1094                 table->VceLevel[count].Frequency = mm_table->entries[count].eclk;
1095                 table->VceLevel[count].MinVoltage = 0;
1096                 table->VceLevel[count].MinVoltage |=
1097                                 (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
1098
1099                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
1100                         vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
1101                                                 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1102                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1103                         vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
1104                 else
1105                         vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
1106
1107
1108                 table->VceLevel[count].MinVoltage |=
1109                                 (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
1110                 table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1111
1112                 /*retrieve divider value for VBIOS */
1113                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1114                                 table->VceLevel[count].Frequency, &dividers);
1115                 PP_ASSERT_WITH_CODE((0 == result),
1116                                 "can not find divide id for VCE engine clock",
1117                                 return result);
1118
1119                 table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1120
1121                 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
1122                 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage);
1123         }
1124         return result;
1125 }
1126
1127
1128 static int polaris10_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
1129                 SMU74_Discrete_DpmTable *table)
1130 {
1131         int result = -EINVAL;
1132         uint8_t count;
1133         struct pp_atomctrl_clock_dividers_vi dividers;
1134         struct phm_ppt_v1_information *table_info =
1135                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1136         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1137                         table_info->mm_dep_table;
1138         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1139         uint32_t vddci;
1140
1141         table->SamuBootLevel = 0;
1142         table->SamuLevelCount = (uint8_t)(mm_table->count);
1143
1144         for (count = 0; count < table->SamuLevelCount; count++) {
1145                 /* not sure whether we need evclk or not */
1146                 table->SamuLevel[count].MinVoltage = 0;
1147                 table->SamuLevel[count].Frequency = mm_table->entries[count].samclock;
1148                 table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1149                                 VOLTAGE_SCALE) << VDDC_SHIFT;
1150
1151                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
1152                         vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
1153                                                 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1154                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1155                         vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
1156                 else
1157                         vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
1158
1159                 table->SamuLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
1160                 table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1161
1162                 /* retrieve divider value for VBIOS */
1163                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1164                                 table->SamuLevel[count].Frequency, &dividers);
1165                 PP_ASSERT_WITH_CODE((0 == result),
1166                                 "can not find divide id for samu clock", return result);
1167
1168                 table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1169
1170                 CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
1171                 CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage);
1172         }
1173         return result;
1174 }
1175
1176 static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr,
1177                 int32_t eng_clock, int32_t mem_clock,
1178                 SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs)
1179 {
1180         uint32_t dram_timing;
1181         uint32_t dram_timing2;
1182         uint32_t burst_time;
1183         int result;
1184
1185         result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1186                         eng_clock, mem_clock);
1187         PP_ASSERT_WITH_CODE(result == 0,
1188                         "Error calling VBIOS to set DRAM_TIMING.", return result);
1189
1190         dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1191         dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1192         burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1193
1194
1195         arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dram_timing);
1196         arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2);
1197         arb_regs->McArbBurstTime   = (uint8_t)burst_time;
1198
1199         return 0;
1200 }
1201
1202 static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1203 {
1204         struct pp_smumgr *smumgr = hwmgr->smumgr;
1205         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
1206         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1207         struct SMU74_Discrete_MCArbDramTimingTable arb_regs;
1208         uint32_t i, j;
1209         int result = 0;
1210
1211         for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) {
1212                 for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) {
1213                         result = polaris10_populate_memory_timing_parameters(hwmgr,
1214                                         hw_data->dpm_table.sclk_table.dpm_levels[i].value,
1215                                         hw_data->dpm_table.mclk_table.dpm_levels[j].value,
1216                                         &arb_regs.entries[i][j]);
1217                         if (result == 0)
1218                                 result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j);
1219                         if (result != 0)
1220                                 return result;
1221                 }
1222         }
1223
1224         result = smu7_copy_bytes_to_smc(
1225                         hwmgr->smumgr,
1226                         smu_data->smu7_data.arb_table_start,
1227                         (uint8_t *)&arb_regs,
1228                         sizeof(SMU74_Discrete_MCArbDramTimingTable),
1229                         SMC_RAM_END);
1230         return result;
1231 }
1232
1233 static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1234                 struct SMU74_Discrete_DpmTable *table)
1235 {
1236         int result = -EINVAL;
1237         uint8_t count;
1238         struct pp_atomctrl_clock_dividers_vi dividers;
1239         struct phm_ppt_v1_information *table_info =
1240                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1241         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1242                         table_info->mm_dep_table;
1243         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1244         uint32_t vddci;
1245
1246         table->UvdLevelCount = (uint8_t)(mm_table->count);
1247         table->UvdBootLevel = 0;
1248
1249         for (count = 0; count < table->UvdLevelCount; count++) {
1250                 table->UvdLevel[count].MinVoltage = 0;
1251                 table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
1252                 table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
1253                 table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1254                                 VOLTAGE_SCALE) << VDDC_SHIFT;
1255
1256                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
1257                         vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
1258                                                 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1259                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1260                         vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
1261                 else
1262                         vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
1263
1264                 table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
1265                 table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1266
1267                 /* retrieve divider value for VBIOS */
1268                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1269                                 table->UvdLevel[count].VclkFrequency, &dividers);
1270                 PP_ASSERT_WITH_CODE((0 == result),
1271                                 "can not find divide id for Vclk clock", return result);
1272
1273                 table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
1274
1275                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1276                                 table->UvdLevel[count].DclkFrequency, &dividers);
1277                 PP_ASSERT_WITH_CODE((0 == result),
1278                                 "can not find divide id for Dclk clock", return result);
1279
1280                 table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
1281
1282                 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
1283                 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
1284                 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage);
1285         }
1286
1287         return result;
1288 }
1289
1290 static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1291                 struct SMU74_Discrete_DpmTable *table)
1292 {
1293         int result = 0;
1294         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1295
1296         table->GraphicsBootLevel = 0;
1297         table->MemoryBootLevel = 0;
1298
1299         /* find boot level from dpm table */
1300         result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1301                         data->vbios_boot_state.sclk_bootup_value,
1302                         (uint32_t *)&(table->GraphicsBootLevel));
1303
1304         result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1305                         data->vbios_boot_state.mclk_bootup_value,
1306                         (uint32_t *)&(table->MemoryBootLevel));
1307
1308         table->BootVddc  = data->vbios_boot_state.vddc_bootup_value *
1309                         VOLTAGE_SCALE;
1310         table->BootVddci = data->vbios_boot_state.vddci_bootup_value *
1311                         VOLTAGE_SCALE;
1312         table->BootMVdd  = data->vbios_boot_state.mvdd_bootup_value *
1313                         VOLTAGE_SCALE;
1314
1315         CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc);
1316         CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci);
1317         CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
1318
1319         return 0;
1320 }
1321
1322 static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
1323 {
1324         struct pp_smumgr *smumgr = hwmgr->smumgr;
1325         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
1326         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1327         struct phm_ppt_v1_information *table_info =
1328                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1329         uint8_t count, level;
1330
1331         count = (uint8_t)(table_info->vdd_dep_on_sclk->count);
1332
1333         for (level = 0; level < count; level++) {
1334                 if (table_info->vdd_dep_on_sclk->entries[level].clk >=
1335                                 hw_data->vbios_boot_state.sclk_bootup_value) {
1336                         smu_data->smc_state_table.GraphicsBootLevel = level;
1337                         break;
1338                 }
1339         }
1340
1341         count = (uint8_t)(table_info->vdd_dep_on_mclk->count);
1342         for (level = 0; level < count; level++) {
1343                 if (table_info->vdd_dep_on_mclk->entries[level].clk >=
1344                                 hw_data->vbios_boot_state.mclk_bootup_value) {
1345                         smu_data->smc_state_table.MemoryBootLevel = level;
1346                         break;
1347                 }
1348         }
1349
1350         return 0;
1351 }
1352
1353
1354 static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
1355 {
1356         uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min;
1357         struct pp_smumgr *smumgr = hwmgr->smumgr;
1358         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1359
1360         uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0;
1361         struct phm_ppt_v1_information *table_info =
1362                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1363         struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1364                         table_info->vdd_dep_on_sclk;
1365
1366         stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
1367
1368         /* Read SMU_Eefuse to read and calculate RO and determine
1369          * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1370          */
1371         efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1372                         ixSMU_EFUSE_0 + (67 * 4));
1373         efuse &= 0xFF000000;
1374         efuse = efuse >> 24;
1375
1376         if (hwmgr->chip_id == CHIP_POLARIS10) {
1377                 min = 1000;
1378                 max = 2300;
1379         } else {
1380                 min = 1100;
1381                 max = 2100;
1382         }
1383
1384         ro = efuse * (max - min) / 255 + min;
1385
1386         /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1387         for (i = 0; i < sclk_table->count; i++) {
1388                 smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |=
1389                                 sclk_table->entries[i].cks_enable << i;
1390                 if (hwmgr->chip_id == CHIP_POLARIS10) {
1391                         volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 - (ro - 70) * 1000000) / \
1392                                                 (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000));
1393                         volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \
1394                                         (2522480 - sclk_table->entries[i].clk/100 * 115764/100));
1395                 } else {
1396                         volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 - (ro - 50) * 1000000) / \
1397                                                 (2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000)));
1398                         volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \
1399                                         (3422454 - sclk_table->entries[i].clk/100 * (18886376/10000)));
1400                 }
1401
1402                 if (volt_without_cks >= volt_with_cks)
1403                         volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
1404                                         sclk_table->entries[i].cks_voffset) * 100 + 624) / 625);
1405
1406                 smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
1407         }
1408
1409         smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6;
1410         /* Populate CKS Lookup Table */
1411         if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
1412                 stretch_amount2 = 0;
1413         else if (stretch_amount == 3 || stretch_amount == 4)
1414                 stretch_amount2 = 1;
1415         else {
1416                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1417                                 PHM_PlatformCaps_ClockStretcher);
1418                 PP_ASSERT_WITH_CODE(false,
1419                                 "Stretch Amount in PPTable not supported\n",
1420                                 return -EINVAL);
1421         }
1422
1423         value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
1424         value &= 0xFFFFFFFE;
1425         cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
1426
1427         return 0;
1428 }
1429
1430 /**
1431 * Populates the SMC VRConfig field in DPM table.
1432 *
1433 * @param    hwmgr   the address of the hardware manager
1434 * @param    table   the SMC DPM table structure to be populated
1435 * @return   always 0
1436 */
1437 static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr,
1438                 struct SMU74_Discrete_DpmTable *table)
1439 {
1440         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1441         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1442         uint16_t config;
1443
1444         config = VR_MERGED_WITH_VDDC;
1445         table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT);
1446
1447         /* Set Vddc Voltage Controller */
1448         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1449                 config = VR_SVI2_PLANE_1;
1450                 table->VRConfig |= config;
1451         } else {
1452                 PP_ASSERT_WITH_CODE(false,
1453                                 "VDDC should be on SVI2 control in merged mode!",
1454                                 );
1455         }
1456         /* Set Vddci Voltage Controller */
1457         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
1458                 config = VR_SVI2_PLANE_2;  /* only in merged mode */
1459                 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1460         } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
1461                 config = VR_SMIO_PATTERN_1;
1462                 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1463         } else {
1464                 config = VR_STATIC_VOLTAGE;
1465                 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1466         }
1467         /* Set Mvdd Voltage Controller */
1468         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
1469                 config = VR_SVI2_PLANE_2;
1470                 table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1471                 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start +
1472                         offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1);
1473         } else {
1474                 config = VR_STATIC_VOLTAGE;
1475                 table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1476         }
1477
1478         return 0;
1479 }
1480
1481
1482 static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
1483 {
1484         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1485         struct pp_smumgr *smumgr = hwmgr->smumgr;
1486         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1487
1488         SMU74_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
1489         int result = 0;
1490         struct pp_atom_ctrl__avfs_parameters avfs_params = {0};
1491         AVFS_meanNsigma_t AVFS_meanNsigma = { {0} };
1492         AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} };
1493         uint32_t tmp, i;
1494
1495         struct phm_ppt_v1_information *table_info =
1496                         (struct phm_ppt_v1_information *)hwmgr->pptable;
1497         struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1498                         table_info->vdd_dep_on_sclk;
1499
1500
1501         if (((struct smu7_smumgr *)smu_data)->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
1502                 return result;
1503
1504         result = atomctrl_get_avfs_information(hwmgr, &avfs_params);
1505
1506         if (0 == result) {
1507                 table->BTCGB_VDROOP_TABLE[0].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0);
1508                 table->BTCGB_VDROOP_TABLE[0].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1);
1509                 table->BTCGB_VDROOP_TABLE[0].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2);
1510                 table->BTCGB_VDROOP_TABLE[1].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0);
1511                 table->BTCGB_VDROOP_TABLE[1].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1);
1512                 table->BTCGB_VDROOP_TABLE[1].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2);
1513                 table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1);
1514                 table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2);
1515                 table->AVFSGB_VDROOP_TABLE[0].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b);
1516                 table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24;
1517                 table->AVFSGB_VDROOP_TABLE[0].m2_shift  = 12;
1518                 table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1);
1519                 table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2);
1520                 table->AVFSGB_VDROOP_TABLE[1].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b);
1521                 table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24;
1522                 table->AVFSGB_VDROOP_TABLE[1].m2_shift  = 12;
1523                 table->MaxVoltage                = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv);
1524                 AVFS_meanNsigma.Aconstant[0]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0);
1525                 AVFS_meanNsigma.Aconstant[1]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1);
1526                 AVFS_meanNsigma.Aconstant[2]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2);
1527                 AVFS_meanNsigma.DC_tol_sigma      = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma);
1528                 AVFS_meanNsigma.Platform_mean     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean);
1529                 AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor);
1530                 AVFS_meanNsigma.Platform_sigma     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma);
1531
1532                 for (i = 0; i < NUM_VFT_COLUMNS; i++) {
1533                         AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625);
1534                         AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100);
1535                 }
1536
1537                 result = smu7_read_smc_sram_dword(smumgr,
1538                                 SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma),
1539                                 &tmp, SMC_RAM_END);
1540
1541                 smu7_copy_bytes_to_smc(smumgr,
1542                                         tmp,
1543                                         (uint8_t *)&AVFS_meanNsigma,
1544                                         sizeof(AVFS_meanNsigma_t),
1545                                         SMC_RAM_END);
1546
1547                 result = smu7_read_smc_sram_dword(smumgr,
1548                                 SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable),
1549                                 &tmp, SMC_RAM_END);
1550                 smu7_copy_bytes_to_smc(smumgr,
1551                                         tmp,
1552                                         (uint8_t *)&AVFS_SclkOffset,
1553                                         sizeof(AVFS_Sclk_Offset_t),
1554                                         SMC_RAM_END);
1555
1556                 data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) |
1557                                                 (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) |
1558                                                 (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) |
1559                                                 (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT);
1560                 data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false;
1561         }
1562         return result;
1563 }
1564
1565
1566 /**
1567 * Initialize the ARB DRAM timing table's index field.
1568 *
1569 * @param    hwmgr  the address of the powerplay hardware manager.
1570 * @return   always 0
1571 */
1572 static int polaris10_init_arb_table_index(struct pp_smumgr *smumgr)
1573 {
1574         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1575         uint32_t tmp;
1576         int result;
1577
1578         /* This is a read-modify-write on the first byte of the ARB table.
1579          * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
1580          * is the field 'current'.
1581          * This solution is ugly, but we never write the whole table only
1582          * individual fields in it.
1583          * In reality this field should not be in that structure
1584          * but in a soft register.
1585          */
1586         result = smu7_read_smc_sram_dword(smumgr,
1587                         smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END);
1588
1589         if (result)
1590                 return result;
1591
1592         tmp &= 0x00FFFFFF;
1593         tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
1594
1595         return smu7_write_smc_sram_dword(smumgr,
1596                         smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END);
1597 }
1598
1599 static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
1600 {
1601         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1602         struct  phm_ppt_v1_information *table_info =
1603                         (struct  phm_ppt_v1_information *)(hwmgr->pptable);
1604
1605         if (table_info &&
1606                         table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
1607                         table_info->cac_dtp_table->usPowerTuneDataSetID)
1608                 smu_data->power_tune_defaults =
1609                                 &polaris10_power_tune_data_set_array
1610                                 [table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
1611         else
1612                 smu_data->power_tune_defaults = &polaris10_power_tune_data_set_array[0];
1613
1614 }
1615
1616 static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr)
1617 {
1618         struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1619         struct SMU74_Discrete_GraphicsLevel *levels =
1620                                 data->smc_state_table.GraphicsLevel;
1621         unsigned min_level = 1;
1622
1623         hwmgr->default_gfx_power_profile.activity_threshold =
1624                         be16_to_cpu(levels[0].ActivityLevel);
1625         hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst;
1626         hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst;
1627         hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
1628
1629         hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile;
1630         hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
1631
1632         /* Workaround compute SDMA instability: disable lowest SCLK
1633          * DPM level. Optimize compute power profile: Use only highest
1634          * 2 power levels (if more than 2 are available), Hysteresis:
1635          * 0ms up, 5ms down
1636          */
1637         if (data->smc_state_table.GraphicsDpmLevelCount > 2)
1638                 min_level = data->smc_state_table.GraphicsDpmLevelCount - 2;
1639         else if (data->smc_state_table.GraphicsDpmLevelCount == 2)
1640                 min_level = 1;
1641         else
1642                 min_level = 0;
1643         hwmgr->default_compute_power_profile.min_sclk =
1644                 be32_to_cpu(levels[min_level].SclkSetting.SclkFrequency);
1645         hwmgr->default_compute_power_profile.up_hyst = 0;
1646         hwmgr->default_compute_power_profile.down_hyst = 5;
1647
1648         hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1649         hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
1650 }
1651
1652 /**
1653 * Initializes the SMC table and uploads it
1654 *
1655 * @param    hwmgr  the address of the powerplay hardware manager.
1656 * @return   always 0
1657 */
1658 int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
1659 {
1660         int result;
1661         struct pp_smumgr *smumgr = hwmgr->smumgr;
1662         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
1663         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1664         struct phm_ppt_v1_information *table_info =
1665                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1666         struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table);
1667         uint8_t i;
1668         struct pp_atomctrl_gpio_pin_assignment gpio_pin;
1669         pp_atomctrl_clock_dividers_vi dividers;
1670
1671         polaris10_initialize_power_tune_defaults(hwmgr);
1672
1673         if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control)
1674                 polaris10_populate_smc_voltage_tables(hwmgr, table);
1675
1676         table->SystemFlags = 0;
1677         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1678                         PHM_PlatformCaps_AutomaticDCTransition))
1679                 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
1680
1681         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1682                         PHM_PlatformCaps_StepVddc))
1683                 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
1684
1685         if (hw_data->is_memory_gddr5)
1686                 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
1687
1688         if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) {
1689                 result = polaris10_populate_ulv_state(hwmgr, table);
1690                 PP_ASSERT_WITH_CODE(0 == result,
1691                                 "Failed to initialize ULV state!", return result);
1692                 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1693                                 ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT);
1694         }
1695
1696         result = polaris10_populate_smc_link_level(hwmgr, table);
1697         PP_ASSERT_WITH_CODE(0 == result,
1698                         "Failed to initialize Link Level!", return result);
1699
1700         result = polaris10_populate_all_graphic_levels(hwmgr);
1701         PP_ASSERT_WITH_CODE(0 == result,
1702                         "Failed to initialize Graphics Level!", return result);
1703
1704         result = polaris10_populate_all_memory_levels(hwmgr);
1705         PP_ASSERT_WITH_CODE(0 == result,
1706                         "Failed to initialize Memory Level!", return result);
1707
1708         result = polaris10_populate_smc_acpi_level(hwmgr, table);
1709         PP_ASSERT_WITH_CODE(0 == result,
1710                         "Failed to initialize ACPI Level!", return result);
1711
1712         result = polaris10_populate_smc_vce_level(hwmgr, table);
1713         PP_ASSERT_WITH_CODE(0 == result,
1714                         "Failed to initialize VCE Level!", return result);
1715
1716         result = polaris10_populate_smc_samu_level(hwmgr, table);
1717         PP_ASSERT_WITH_CODE(0 == result,
1718                         "Failed to initialize SAMU Level!", return result);
1719
1720         /* Since only the initial state is completely set up at this point
1721          * (the other states are just copies of the boot state) we only
1722          * need to populate the  ARB settings for the initial state.
1723          */
1724         result = polaris10_program_memory_timing_parameters(hwmgr);
1725         PP_ASSERT_WITH_CODE(0 == result,
1726                         "Failed to Write ARB settings for the initial state.", return result);
1727
1728         result = polaris10_populate_smc_uvd_level(hwmgr, table);
1729         PP_ASSERT_WITH_CODE(0 == result,
1730                         "Failed to initialize UVD Level!", return result);
1731
1732         result = polaris10_populate_smc_boot_level(hwmgr, table);
1733         PP_ASSERT_WITH_CODE(0 == result,
1734                         "Failed to initialize Boot Level!", return result);
1735
1736         result = polaris10_populate_smc_initailial_state(hwmgr);
1737         PP_ASSERT_WITH_CODE(0 == result,
1738                         "Failed to initialize Boot State!", return result);
1739
1740         result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr);
1741         PP_ASSERT_WITH_CODE(0 == result,
1742                         "Failed to populate BAPM Parameters!", return result);
1743
1744         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1745                         PHM_PlatformCaps_ClockStretcher)) {
1746                 result = polaris10_populate_clock_stretcher_data_table(hwmgr);
1747                 PP_ASSERT_WITH_CODE(0 == result,
1748                                 "Failed to populate Clock Stretcher Data Table!",
1749                                 return result);
1750         }
1751
1752         result = polaris10_populate_avfs_parameters(hwmgr);
1753         PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;);
1754
1755         table->CurrSclkPllRange = 0xff;
1756         table->GraphicsVoltageChangeEnable  = 1;
1757         table->GraphicsThermThrottleEnable  = 1;
1758         table->GraphicsInterval = 1;
1759         table->VoltageInterval  = 1;
1760         table->ThermalInterval  = 1;
1761         table->TemperatureLimitHigh =
1762                         table_info->cac_dtp_table->usTargetOperatingTemp *
1763                         SMU7_Q88_FORMAT_CONVERSION_UNIT;
1764         table->TemperatureLimitLow  =
1765                         (table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
1766                         SMU7_Q88_FORMAT_CONVERSION_UNIT;
1767         table->MemoryVoltageChangeEnable = 1;
1768         table->MemoryInterval = 1;
1769         table->VoltageResponseTime = 0;
1770         table->PhaseResponseTime = 0;
1771         table->MemoryThermThrottleEnable = 1;
1772         table->PCIeBootLinkLevel = 0;
1773         table->PCIeGenInterval = 1;
1774         table->VRConfig = 0;
1775
1776         result = polaris10_populate_vr_config(hwmgr, table);
1777         PP_ASSERT_WITH_CODE(0 == result,
1778                         "Failed to populate VRConfig setting!", return result);
1779
1780         table->ThermGpio = 17;
1781         table->SclkStepSize = 0x4000;
1782
1783         if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) {
1784                 table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift;
1785         } else {
1786                 table->VRHotGpio = SMU7_UNUSED_GPIO_PIN;
1787                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1788                                 PHM_PlatformCaps_RegulatorHot);
1789         }
1790
1791         if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
1792                         &gpio_pin)) {
1793                 table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift;
1794                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1795                                 PHM_PlatformCaps_AutomaticDCTransition);
1796         } else {
1797                 table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
1798                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1799                                 PHM_PlatformCaps_AutomaticDCTransition);
1800         }
1801
1802         /* Thermal Output GPIO */
1803         if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID,
1804                         &gpio_pin)) {
1805                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1806                                 PHM_PlatformCaps_ThermalOutGPIO);
1807
1808                 table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift;
1809
1810                 /* For porlarity read GPIOPAD_A with assigned Gpio pin
1811                  * since VBIOS will program this register to set 'inactive state',
1812                  * driver can then determine 'active state' from this and
1813                  * program SMU with correct polarity
1814                  */
1815                 table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A)
1816                                         & (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0;
1817                 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
1818
1819                 /* if required, combine VRHot/PCC with thermal out GPIO */
1820                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot)
1821                 && phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal))
1822                         table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
1823         } else {
1824                 table->ThermOutGpio = 17;
1825                 table->ThermOutPolarity = 1;
1826                 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
1827         }
1828
1829         /* Populate BIF_SCLK levels into SMC DPM table */
1830         for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) {
1831                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, smu_data->bif_sclk_table[i], &dividers);
1832                 PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result);
1833
1834                 if (i == 0)
1835                         table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
1836                 else
1837                         table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
1838         }
1839
1840         for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++)
1841                 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
1842
1843         CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
1844         CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
1845         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
1846         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
1847         CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
1848         CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange);
1849         CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
1850         CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
1851         CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
1852         CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
1853
1854         /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
1855         result = smu7_copy_bytes_to_smc(hwmgr->smumgr,
1856                         smu_data->smu7_data.dpm_table_start +
1857                         offsetof(SMU74_Discrete_DpmTable, SystemFlags),
1858                         (uint8_t *)&(table->SystemFlags),
1859                         sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController),
1860                         SMC_RAM_END);
1861         PP_ASSERT_WITH_CODE(0 == result,
1862                         "Failed to upload dpm data to SMC memory!", return result);
1863
1864         result = polaris10_init_arb_table_index(hwmgr->smumgr);
1865         PP_ASSERT_WITH_CODE(0 == result,
1866                         "Failed to upload arb data to SMC memory!", return result);
1867
1868         result = polaris10_populate_pm_fuses(hwmgr);
1869         PP_ASSERT_WITH_CODE(0 == result,
1870                         "Failed to  populate PM fuses to SMC memory!", return result);
1871
1872         polaris10_save_default_power_profile(hwmgr);
1873
1874         return 0;
1875 }
1876
1877 static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
1878 {
1879         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1880
1881         if (data->need_update_smu7_dpm_table &
1882                 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
1883                 return polaris10_program_memory_timing_parameters(hwmgr);
1884
1885         return 0;
1886 }
1887
1888 int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
1889 {
1890         int ret;
1891         struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
1892         struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend);
1893         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1894
1895         if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
1896                 return 0;
1897
1898         ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
1899                         PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
1900
1901         ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ?
1902                         0 : -1;
1903
1904         if (!ret)
1905                 /* If this param is not changed, this function could fire unnecessarily */
1906                 smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
1907
1908         return ret;
1909 }
1910
1911 /**
1912 * Set up the fan table to control the fan using the SMC.
1913 * @param    hwmgr  the address of the powerplay hardware manager.
1914 * @param    pInput the pointer to input data
1915 * @param    pOutput the pointer to output data
1916 * @param    pStorage the pointer to temporary storage
1917 * @param    Result the last failure code
1918 * @return   result from set temperature range routine
1919 */
1920 int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
1921 {
1922         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1923         SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
1924         uint32_t duty100;
1925         uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
1926         uint16_t fdo_min, slope1, slope2;
1927         uint32_t reference_clock;
1928         int res;
1929         uint64_t tmp64;
1930
1931         if (hwmgr->thermal_controller.fanInfo.bNoFan) {
1932                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1933                         PHM_PlatformCaps_MicrocodeFanControl);
1934                 return 0;
1935         }
1936
1937         if (smu_data->smu7_data.fan_table_start == 0) {
1938                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1939                                 PHM_PlatformCaps_MicrocodeFanControl);
1940                 return 0;
1941         }
1942
1943         duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1944                         CG_FDO_CTRL1, FMAX_DUTY100);
1945
1946         if (duty100 == 0) {
1947                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1948                                 PHM_PlatformCaps_MicrocodeFanControl);
1949                 return 0;
1950         }
1951
1952         tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
1953                         usPWMMin * duty100;
1954         do_div(tmp64, 10000);
1955         fdo_min = (uint16_t)tmp64;
1956
1957         t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
1958                         hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
1959         t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
1960                         hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
1961
1962         pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
1963                         hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
1964         pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
1965                         hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
1966
1967         slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
1968         slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
1969
1970         fan_table.TempMin = cpu_to_be16((50 + hwmgr->
1971                         thermal_controller.advanceFanControlParameters.usTMin) / 100);
1972         fan_table.TempMed = cpu_to_be16((50 + hwmgr->
1973                         thermal_controller.advanceFanControlParameters.usTMed) / 100);
1974         fan_table.TempMax = cpu_to_be16((50 + hwmgr->
1975                         thermal_controller.advanceFanControlParameters.usTMax) / 100);
1976
1977         fan_table.Slope1 = cpu_to_be16(slope1);
1978         fan_table.Slope2 = cpu_to_be16(slope2);
1979
1980         fan_table.FdoMin = cpu_to_be16(fdo_min);
1981
1982         fan_table.HystDown = cpu_to_be16(hwmgr->
1983                         thermal_controller.advanceFanControlParameters.ucTHyst);
1984
1985         fan_table.HystUp = cpu_to_be16(1);
1986
1987         fan_table.HystSlope = cpu_to_be16(1);
1988
1989         fan_table.TempRespLim = cpu_to_be16(5);
1990
1991         reference_clock = smu7_get_xclk(hwmgr);
1992
1993         fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
1994                         thermal_controller.advanceFanControlParameters.ulCycleDelay *
1995                         reference_clock) / 1600);
1996
1997         fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
1998
1999         fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
2000                         hwmgr->device, CGS_IND_REG__SMC,
2001                         CG_MULT_THERMAL_CTRL, TEMP_SEL);
2002
2003         res = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu_data->smu7_data.fan_table_start,
2004                         (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table),
2005                         SMC_RAM_END);
2006
2007         if (!res && hwmgr->thermal_controller.
2008                         advanceFanControlParameters.ucMinimumPWMLimit)
2009                 res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2010                                 PPSMC_MSG_SetFanMinPwm,
2011                                 hwmgr->thermal_controller.
2012                                 advanceFanControlParameters.ucMinimumPWMLimit);
2013
2014         if (!res && hwmgr->thermal_controller.
2015                         advanceFanControlParameters.ulMinFanSCLKAcousticLimit)
2016                 res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2017                                 PPSMC_MSG_SetFanSclkTarget,
2018                                 hwmgr->thermal_controller.
2019                                 advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
2020
2021         if (res)
2022                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2023                                 PHM_PlatformCaps_MicrocodeFanControl);
2024
2025         return 0;
2026 }
2027
2028 static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr)
2029 {
2030         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2031         uint32_t mm_boot_level_offset, mm_boot_level_value;
2032         struct phm_ppt_v1_information *table_info =
2033                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
2034
2035         smu_data->smc_state_table.UvdBootLevel = 0;
2036         if (table_info->mm_dep_table->count > 0)
2037                 smu_data->smc_state_table.UvdBootLevel =
2038                                 (uint8_t) (table_info->mm_dep_table->count - 1);
2039         mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable,
2040                                                 UvdBootLevel);
2041         mm_boot_level_offset /= 4;
2042         mm_boot_level_offset *= 4;
2043         mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2044                         CGS_IND_REG__SMC, mm_boot_level_offset);
2045         mm_boot_level_value &= 0x00FFFFFF;
2046         mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24;
2047         cgs_write_ind_register(hwmgr->device,
2048                         CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2049
2050         if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2051                         PHM_PlatformCaps_UVDDPM) ||
2052                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2053                         PHM_PlatformCaps_StablePState))
2054                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2055                                 PPSMC_MSG_UVDDPM_SetEnabledMask,
2056                                 (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel));
2057         return 0;
2058 }
2059
2060 static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr)
2061 {
2062         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2063         uint32_t mm_boot_level_offset, mm_boot_level_value;
2064         struct phm_ppt_v1_information *table_info =
2065                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
2066
2067         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2068                                         PHM_PlatformCaps_StablePState))
2069                 smu_data->smc_state_table.VceBootLevel =
2070                         (uint8_t) (table_info->mm_dep_table->count - 1);
2071         else
2072                 smu_data->smc_state_table.VceBootLevel = 0;
2073
2074         mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2075                                         offsetof(SMU74_Discrete_DpmTable, VceBootLevel);
2076         mm_boot_level_offset /= 4;
2077         mm_boot_level_offset *= 4;
2078         mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2079                         CGS_IND_REG__SMC, mm_boot_level_offset);
2080         mm_boot_level_value &= 0xFF00FFFF;
2081         mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16;
2082         cgs_write_ind_register(hwmgr->device,
2083                         CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2084
2085         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
2086                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2087                                 PPSMC_MSG_VCEDPM_SetEnabledMask,
2088                                 (uint32_t)1 << smu_data->smc_state_table.VceBootLevel);
2089         return 0;
2090 }
2091
2092 static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr)
2093 {
2094         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2095         uint32_t mm_boot_level_offset, mm_boot_level_value;
2096
2097
2098         smu_data->smc_state_table.SamuBootLevel = 0;
2099         mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2100                                 offsetof(SMU74_Discrete_DpmTable, SamuBootLevel);
2101
2102         mm_boot_level_offset /= 4;
2103         mm_boot_level_offset *= 4;
2104         mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2105                         CGS_IND_REG__SMC, mm_boot_level_offset);
2106         mm_boot_level_value &= 0xFFFFFF00;
2107         mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0;
2108         cgs_write_ind_register(hwmgr->device,
2109                         CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2110
2111         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2112                         PHM_PlatformCaps_StablePState))
2113                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2114                                 PPSMC_MSG_SAMUDPM_SetEnabledMask,
2115                                 (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel));
2116         return 0;
2117 }
2118
2119
2120 static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr)
2121 {
2122         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2123         struct phm_ppt_v1_information *table_info =
2124                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
2125         struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
2126         int max_entry, i;
2127
2128         max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ?
2129                                                 SMU74_MAX_LEVELS_LINK :
2130                                                 pcie_table->count;
2131         /* Setup BIF_SCLK levels */
2132         for (i = 0; i < max_entry; i++)
2133                 smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk;
2134         return 0;
2135 }
2136
2137 int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
2138 {
2139         switch (type) {
2140         case SMU_UVD_TABLE:
2141                 polaris10_update_uvd_smc_table(hwmgr);
2142                 break;
2143         case SMU_VCE_TABLE:
2144                 polaris10_update_vce_smc_table(hwmgr);
2145                 break;
2146         case SMU_SAMU_TABLE:
2147                 polaris10_update_samu_smc_table(hwmgr);
2148                 break;
2149         case SMU_BIF_TABLE:
2150                 polaris10_update_bif_smc_table(hwmgr);
2151         default:
2152                 break;
2153         }
2154         return 0;
2155 }
2156
2157 int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2158 {
2159         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2160         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2161
2162         int result = 0;
2163         uint32_t low_sclk_interrupt_threshold = 0;
2164
2165         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2166                         PHM_PlatformCaps_SclkThrottleLowNotification)
2167                 && (hwmgr->gfx_arbiter.sclk_threshold !=
2168                                 data->low_sclk_interrupt_threshold)) {
2169                 data->low_sclk_interrupt_threshold =
2170                                 hwmgr->gfx_arbiter.sclk_threshold;
2171                 low_sclk_interrupt_threshold =
2172                                 data->low_sclk_interrupt_threshold;
2173
2174                 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2175
2176                 result = smu7_copy_bytes_to_smc(
2177                                 hwmgr->smumgr,
2178                                 smu_data->smu7_data.dpm_table_start +
2179                                 offsetof(SMU74_Discrete_DpmTable,
2180                                         LowSclkInterruptThreshold),
2181                                 (uint8_t *)&low_sclk_interrupt_threshold,
2182                                 sizeof(uint32_t),
2183                                 SMC_RAM_END);
2184         }
2185         PP_ASSERT_WITH_CODE((result == 0),
2186                         "Failed to update SCLK threshold!", return result);
2187
2188         result = polaris10_program_mem_timing_parameters(hwmgr);
2189         PP_ASSERT_WITH_CODE((result == 0),
2190                         "Failed to program memory timing parameters!",
2191                         );
2192
2193         return result;
2194 }
2195
2196 uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member)
2197 {
2198         switch (type) {
2199         case SMU_SoftRegisters:
2200                 switch (member) {
2201                 case HandshakeDisables:
2202                         return offsetof(SMU74_SoftRegisters, HandshakeDisables);
2203                 case VoltageChangeTimeout:
2204                         return offsetof(SMU74_SoftRegisters, VoltageChangeTimeout);
2205                 case AverageGraphicsActivity:
2206                         return offsetof(SMU74_SoftRegisters, AverageGraphicsActivity);
2207                 case PreVBlankGap:
2208                         return offsetof(SMU74_SoftRegisters, PreVBlankGap);
2209                 case VBlankTimeout:
2210                         return offsetof(SMU74_SoftRegisters, VBlankTimeout);
2211                 case UcodeLoadStatus:
2212                         return offsetof(SMU74_SoftRegisters, UcodeLoadStatus);
2213                 }
2214         case SMU_Discrete_DpmTable:
2215                 switch (member) {
2216                 case UvdBootLevel:
2217                         return offsetof(SMU74_Discrete_DpmTable, UvdBootLevel);
2218                 case VceBootLevel:
2219                         return offsetof(SMU74_Discrete_DpmTable, VceBootLevel);
2220                 case SamuBootLevel:
2221                         return offsetof(SMU74_Discrete_DpmTable, SamuBootLevel);
2222                 case LowSclkInterruptThreshold:
2223                         return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold);
2224                 }
2225         }
2226         pr_warn("can't get the offset of type %x member %x\n", type, member);
2227         return 0;
2228 }
2229
2230 uint32_t polaris10_get_mac_definition(uint32_t value)
2231 {
2232         switch (value) {
2233         case SMU_MAX_LEVELS_GRAPHICS:
2234                 return SMU74_MAX_LEVELS_GRAPHICS;
2235         case SMU_MAX_LEVELS_MEMORY:
2236                 return SMU74_MAX_LEVELS_MEMORY;
2237         case SMU_MAX_LEVELS_LINK:
2238                 return SMU74_MAX_LEVELS_LINK;
2239         case SMU_MAX_ENTRIES_SMIO:
2240                 return SMU74_MAX_ENTRIES_SMIO;
2241         case SMU_MAX_LEVELS_VDDC:
2242                 return SMU74_MAX_LEVELS_VDDC;
2243         case SMU_MAX_LEVELS_VDDGFX:
2244                 return SMU74_MAX_LEVELS_VDDGFX;
2245         case SMU_MAX_LEVELS_VDDCI:
2246                 return SMU74_MAX_LEVELS_VDDCI;
2247         case SMU_MAX_LEVELS_MVDD:
2248                 return SMU74_MAX_LEVELS_MVDD;
2249         case SMU_UVD_MCLK_HANDSHAKE_DISABLE:
2250                 return SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
2251         }
2252
2253         pr_warn("can't get the mac of %x\n", value);
2254         return 0;
2255 }
2256
2257 /**
2258 * Get the location of various tables inside the FW image.
2259 *
2260 * @param    hwmgr  the address of the powerplay hardware manager.
2261 * @return   always  0
2262 */
2263 int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr)
2264 {
2265         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2266         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2267         uint32_t tmp;
2268         int result;
2269         bool error = false;
2270
2271         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2272                         SMU7_FIRMWARE_HEADER_LOCATION +
2273                         offsetof(SMU74_Firmware_Header, DpmTable),
2274                         &tmp, SMC_RAM_END);
2275
2276         if (0 == result)
2277                 smu_data->smu7_data.dpm_table_start = tmp;
2278
2279         error |= (0 != result);
2280
2281         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2282                         SMU7_FIRMWARE_HEADER_LOCATION +
2283                         offsetof(SMU74_Firmware_Header, SoftRegisters),
2284                         &tmp, SMC_RAM_END);
2285
2286         if (!result) {
2287                 data->soft_regs_start = tmp;
2288                 smu_data->smu7_data.soft_regs_start = tmp;
2289         }
2290
2291         error |= (0 != result);
2292
2293         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2294                         SMU7_FIRMWARE_HEADER_LOCATION +
2295                         offsetof(SMU74_Firmware_Header, mcRegisterTable),
2296                         &tmp, SMC_RAM_END);
2297
2298         if (!result)
2299                 smu_data->smu7_data.mc_reg_table_start = tmp;
2300
2301         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2302                         SMU7_FIRMWARE_HEADER_LOCATION +
2303                         offsetof(SMU74_Firmware_Header, FanTable),
2304                         &tmp, SMC_RAM_END);
2305
2306         if (!result)
2307                 smu_data->smu7_data.fan_table_start = tmp;
2308
2309         error |= (0 != result);
2310
2311         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2312                         SMU7_FIRMWARE_HEADER_LOCATION +
2313                         offsetof(SMU74_Firmware_Header, mcArbDramTimingTable),
2314                         &tmp, SMC_RAM_END);
2315
2316         if (!result)
2317                 smu_data->smu7_data.arb_table_start = tmp;
2318
2319         error |= (0 != result);
2320
2321         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2322                         SMU7_FIRMWARE_HEADER_LOCATION +
2323                         offsetof(SMU74_Firmware_Header, Version),
2324                         &tmp, SMC_RAM_END);
2325
2326         if (!result)
2327                 hwmgr->microcode_version_info.SMC = tmp;
2328
2329         error |= (0 != result);
2330
2331         return error ? -1 : 0;
2332 }
2333
2334 bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr)
2335 {
2336         return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
2337                         CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
2338                         ? true : false;
2339 }
2340
2341 int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
2342                 struct amd_pp_profile *request)
2343 {
2344         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)
2345                         (hwmgr->smumgr->backend);
2346         struct SMU74_Discrete_GraphicsLevel *levels =
2347                         smu_data->smc_state_table.GraphicsLevel;
2348         uint32_t array = smu_data->smu7_data.dpm_table_start +
2349                         offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
2350         uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
2351                         SMU74_MAX_LEVELS_GRAPHICS;
2352         uint32_t i;
2353
2354         for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
2355                 levels[i].ActivityLevel =
2356                                 cpu_to_be16(request->activity_threshold);
2357                 levels[i].EnabledForActivity = 1;
2358                 levels[i].UpHyst = request->up_hyst;
2359                 levels[i].DownHyst = request->down_hyst;
2360         }
2361
2362         return smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
2363                                 array_size, SMC_RAM_END);
2364 }