Merge tag 'drm/tegra/for-5.3-rc4' of git://anongit.freedesktop.org/tegra/linux into...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / powerplay / hwmgr / smu10_hwmgr.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 #include "pp_debug.h"
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include "atom-types.h"
28 #include "atombios.h"
29 #include "processpptables.h"
30 #include "cgs_common.h"
31 #include "smumgr.h"
32 #include "hwmgr.h"
33 #include "hardwaremanager.h"
34 #include "rv_ppsmc.h"
35 #include "smu10_hwmgr.h"
36 #include "power_state.h"
37 #include "soc15_common.h"
38 #include "smu10.h"
39
40 #define SMU10_MAX_DEEPSLEEP_DIVIDER_ID     5
41 #define SMU10_MINIMUM_ENGINE_CLOCK         800   /* 8Mhz, the low boundary of engine clock allowed on this chip */
42 #define SCLK_MIN_DIV_INTV_SHIFT         12
43 #define SMU10_DISPCLK_BYPASS_THRESHOLD     10000 /* 100Mhz */
44 #define SMC_RAM_END                     0x40000
45
46 #define mmPWR_MISC_CNTL_STATUS                                  0x0183
47 #define mmPWR_MISC_CNTL_STATUS_BASE_IDX                         0
48 #define PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN__SHIFT        0x0
49 #define PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT          0x1
50 #define PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN_MASK          0x00000001L
51 #define PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK            0x00000006L
52
53 static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic;
54
55
56 static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
57                 struct pp_display_clock_request *clock_req)
58 {
59         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
60         enum amd_pp_clock_type clk_type = clock_req->clock_type;
61         uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
62         PPSMC_Msg        msg;
63
64         switch (clk_type) {
65         case amd_pp_dcf_clock:
66                 if (clk_freq == smu10_data->dcf_actual_hard_min_freq)
67                         return 0;
68                 msg =  PPSMC_MSG_SetHardMinDcefclkByFreq;
69                 smu10_data->dcf_actual_hard_min_freq = clk_freq;
70                 break;
71         case amd_pp_soc_clock:
72                  msg = PPSMC_MSG_SetHardMinSocclkByFreq;
73                 break;
74         case amd_pp_f_clock:
75                 if (clk_freq == smu10_data->f_actual_hard_min_freq)
76                         return 0;
77                 smu10_data->f_actual_hard_min_freq = clk_freq;
78                 msg = PPSMC_MSG_SetHardMinFclkByFreq;
79                 break;
80         default:
81                 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
82                 return -EINVAL;
83         }
84         smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq);
85
86         return 0;
87 }
88
89 static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps)
90 {
91         if (SMU10_Magic != hw_ps->magic)
92                 return NULL;
93
94         return (struct smu10_power_state *)hw_ps;
95 }
96
97 static const struct smu10_power_state *cast_const_smu10_ps(
98                                 const struct pp_hw_power_state *hw_ps)
99 {
100         if (SMU10_Magic != hw_ps->magic)
101                 return NULL;
102
103         return (struct smu10_power_state *)hw_ps;
104 }
105
106 static int smu10_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
107 {
108         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
109
110         smu10_data->dce_slow_sclk_threshold = 30000;
111         smu10_data->thermal_auto_throttling_treshold = 0;
112         smu10_data->is_nb_dpm_enabled = 1;
113         smu10_data->dpm_flags = 1;
114         smu10_data->need_min_deep_sleep_dcefclk = true;
115         smu10_data->num_active_display = 0;
116         smu10_data->deep_sleep_dcefclk = 0;
117
118         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
119                                         PHM_PlatformCaps_SclkDeepSleep);
120
121         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
122                                 PHM_PlatformCaps_SclkThrottleLowNotification);
123
124         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
125                                 PHM_PlatformCaps_PowerPlaySupport);
126         return 0;
127 }
128
129 static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr,
130                         struct phm_clock_and_voltage_limits *table)
131 {
132         return 0;
133 }
134
135 static int smu10_init_dynamic_state_adjustment_rule_settings(
136                                                         struct pp_hwmgr *hwmgr)
137 {
138         struct phm_clock_voltage_dependency_table *table_clk_vlt;
139
140         table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7),
141                                 GFP_KERNEL);
142
143         if (NULL == table_clk_vlt) {
144                 pr_err("Can not allocate memory!\n");
145                 return -ENOMEM;
146         }
147
148         table_clk_vlt->count = 8;
149         table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0;
150         table_clk_vlt->entries[0].v = 0;
151         table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1;
152         table_clk_vlt->entries[1].v = 1;
153         table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2;
154         table_clk_vlt->entries[2].v = 2;
155         table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3;
156         table_clk_vlt->entries[3].v = 3;
157         table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4;
158         table_clk_vlt->entries[4].v = 4;
159         table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5;
160         table_clk_vlt->entries[5].v = 5;
161         table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6;
162         table_clk_vlt->entries[6].v = 6;
163         table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7;
164         table_clk_vlt->entries[7].v = 7;
165         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
166
167         return 0;
168 }
169
170 static int smu10_get_system_info_data(struct pp_hwmgr *hwmgr)
171 {
172         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)hwmgr->backend;
173
174         smu10_data->sys_info.htc_hyst_lmt = 5;
175         smu10_data->sys_info.htc_tmp_lmt = 203;
176
177         if (smu10_data->thermal_auto_throttling_treshold == 0)
178                  smu10_data->thermal_auto_throttling_treshold = 203;
179
180         smu10_construct_max_power_limits_table (hwmgr,
181                                     &hwmgr->dyn_state.max_clock_voltage_on_ac);
182
183         smu10_init_dynamic_state_adjustment_rule_settings(hwmgr);
184
185         return 0;
186 }
187
188 static int smu10_construct_boot_state(struct pp_hwmgr *hwmgr)
189 {
190         return 0;
191 }
192
193 static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input)
194 {
195         struct PP_Clocks clocks = {0};
196         struct pp_display_clock_request clock_req;
197
198         clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
199         clock_req.clock_type = amd_pp_dcf_clock;
200         clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
201
202         PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, &clock_req),
203                                 "Attempt to set DCF Clock Failed!", return -EINVAL);
204
205         return 0;
206 }
207
208 static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock)
209 {
210         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
211
212         if (smu10_data->need_min_deep_sleep_dcefclk &&
213                 smu10_data->deep_sleep_dcefclk != clock) {
214                 smu10_data->deep_sleep_dcefclk = clock;
215                 smum_send_msg_to_smc_with_parameter(hwmgr,
216                                         PPSMC_MSG_SetMinDeepSleepDcefclk,
217                                         smu10_data->deep_sleep_dcefclk);
218         }
219         return 0;
220 }
221
222 static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
223 {
224         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
225
226         if (smu10_data->dcf_actual_hard_min_freq &&
227                 smu10_data->dcf_actual_hard_min_freq != clock) {
228                 smu10_data->dcf_actual_hard_min_freq = clock;
229                 smum_send_msg_to_smc_with_parameter(hwmgr,
230                                         PPSMC_MSG_SetHardMinDcefclkByFreq,
231                                         smu10_data->dcf_actual_hard_min_freq);
232         }
233         return 0;
234 }
235
236 static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
237 {
238         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
239
240         if (smu10_data->f_actual_hard_min_freq &&
241                 smu10_data->f_actual_hard_min_freq != clock) {
242                 smu10_data->f_actual_hard_min_freq = clock;
243                 smum_send_msg_to_smc_with_parameter(hwmgr,
244                                         PPSMC_MSG_SetHardMinFclkByFreq,
245                                         smu10_data->f_actual_hard_min_freq);
246         }
247         return 0;
248 }
249
250 static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count)
251 {
252         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
253
254         if (smu10_data->num_active_display != count) {
255                 smu10_data->num_active_display = count;
256                 smum_send_msg_to_smc_with_parameter(hwmgr,
257                                 PPSMC_MSG_SetDisplayCount,
258                                 smu10_data->num_active_display);
259         }
260
261         return 0;
262 }
263
264 static int smu10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
265 {
266         return smu10_set_clock_limit(hwmgr, input);
267 }
268
269 static int smu10_init_power_gate_state(struct pp_hwmgr *hwmgr)
270 {
271         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
272         struct amdgpu_device *adev = hwmgr->adev;
273
274         smu10_data->vcn_power_gated = true;
275         smu10_data->isp_tileA_power_gated = true;
276         smu10_data->isp_tileB_power_gated = true;
277
278         if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)
279                 return smum_send_msg_to_smc_with_parameter(hwmgr,
280                                                            PPSMC_MSG_SetGfxCGPG,
281                                                            true);
282         else
283                 return 0;
284 }
285
286
287 static int smu10_setup_asic_task(struct pp_hwmgr *hwmgr)
288 {
289         return smu10_init_power_gate_state(hwmgr);
290 }
291
292 static int smu10_reset_cc6_data(struct pp_hwmgr *hwmgr)
293 {
294         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
295
296         smu10_data->separation_time = 0;
297         smu10_data->cc6_disable = false;
298         smu10_data->pstate_disable = false;
299         smu10_data->cc6_setting_changed = false;
300
301         return 0;
302 }
303
304 static int smu10_power_off_asic(struct pp_hwmgr *hwmgr)
305 {
306         return smu10_reset_cc6_data(hwmgr);
307 }
308
309 static bool smu10_is_gfx_on(struct pp_hwmgr *hwmgr)
310 {
311         uint32_t reg;
312         struct amdgpu_device *adev = hwmgr->adev;
313
314         reg = RREG32_SOC15(PWR, 0, mmPWR_MISC_CNTL_STATUS);
315         if ((reg & PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK) ==
316             (0x2 << PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT))
317                 return true;
318
319         return false;
320 }
321
322 static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr)
323 {
324         struct amdgpu_device *adev = hwmgr->adev;
325
326         if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
327                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff);
328
329                 /* confirm gfx is back to "on" state */
330                 while (!smu10_is_gfx_on(hwmgr))
331                         msleep(1);
332         }
333
334         return 0;
335 }
336
337 static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
338 {
339         return 0;
340 }
341
342 static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr)
343 {
344         struct amdgpu_device *adev = hwmgr->adev;
345
346         if (adev->pm.pp_feature & PP_GFXOFF_MASK)
347                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff);
348
349         return 0;
350 }
351
352 static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
353 {
354         return 0;
355 }
356
357 static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable)
358 {
359         if (enable)
360                 return smu10_enable_gfx_off(hwmgr);
361         else
362                 return smu10_disable_gfx_off(hwmgr);
363 }
364
365 static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
366                                 struct pp_power_state  *prequest_ps,
367                         const struct pp_power_state *pcurrent_ps)
368 {
369         return 0;
370 }
371
372 /* temporary hardcoded clock voltage breakdown tables */
373 static const DpmClock_t VddDcfClk[]= {
374         { 300, 2600},
375         { 600, 3200},
376         { 600, 3600},
377 };
378
379 static const DpmClock_t VddSocClk[]= {
380         { 478, 2600},
381         { 722, 3200},
382         { 722, 3600},
383 };
384
385 static const DpmClock_t VddFClk[]= {
386         { 400, 2600},
387         {1200, 3200},
388         {1200, 3600},
389 };
390
391 static const DpmClock_t VddDispClk[]= {
392         { 435, 2600},
393         { 661, 3200},
394         {1086, 3600},
395 };
396
397 static const DpmClock_t VddDppClk[]= {
398         { 435, 2600},
399         { 661, 3200},
400         { 661, 3600},
401 };
402
403 static const DpmClock_t VddPhyClk[]= {
404         { 540, 2600},
405         { 810, 3200},
406         { 810, 3600},
407 };
408
409 static int smu10_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
410                         struct smu10_voltage_dependency_table **pptable,
411                         uint32_t num_entry, const DpmClock_t *pclk_dependency_table)
412 {
413         uint32_t table_size, i;
414         struct smu10_voltage_dependency_table *ptable;
415
416         table_size = sizeof(uint32_t) + sizeof(struct smu10_voltage_dependency_table) * num_entry;
417         ptable = kzalloc(table_size, GFP_KERNEL);
418
419         if (NULL == ptable)
420                 return -ENOMEM;
421
422         ptable->count = num_entry;
423
424         for (i = 0; i < ptable->count; i++) {
425                 ptable->entries[i].clk         = pclk_dependency_table->Freq * 100;
426                 ptable->entries[i].vol         = pclk_dependency_table->Vol;
427                 pclk_dependency_table++;
428         }
429
430         *pptable = ptable;
431
432         return 0;
433 }
434
435
436 static int smu10_populate_clock_table(struct pp_hwmgr *hwmgr)
437 {
438         uint32_t result;
439
440         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
441         DpmClocks_t  *table = &(smu10_data->clock_table);
442         struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
443
444         result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true);
445
446         PP_ASSERT_WITH_CODE((0 == result),
447                         "Attempt to copy clock table from smc failed",
448                         return result);
449
450         if (0 == result && table->DcefClocks[0].Freq != 0) {
451                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
452                                                 NUM_DCEFCLK_DPM_LEVELS,
453                                                 &smu10_data->clock_table.DcefClocks[0]);
454                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
455                                                 NUM_SOCCLK_DPM_LEVELS,
456                                                 &smu10_data->clock_table.SocClocks[0]);
457                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
458                                                 NUM_FCLK_DPM_LEVELS,
459                                                 &smu10_data->clock_table.FClocks[0]);
460                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk,
461                                                 NUM_MEMCLK_DPM_LEVELS,
462                                                 &smu10_data->clock_table.MemClocks[0]);
463         } else {
464                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
465                                                 ARRAY_SIZE(VddDcfClk),
466                                                 &VddDcfClk[0]);
467                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
468                                                 ARRAY_SIZE(VddSocClk),
469                                                 &VddSocClk[0]);
470                 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
471                                                 ARRAY_SIZE(VddFClk),
472                                                 &VddFClk[0]);
473         }
474         smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk,
475                                         ARRAY_SIZE(VddDispClk),
476                                         &VddDispClk[0]);
477         smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk,
478                                         ARRAY_SIZE(VddDppClk), &VddDppClk[0]);
479         smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk,
480                                         ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]);
481
482         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency);
483         result = smum_get_argument(hwmgr);
484         smu10_data->gfx_min_freq_limit = result / 10 * 1000;
485
486         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency);
487         result = smum_get_argument(hwmgr);
488         smu10_data->gfx_max_freq_limit = result / 10 * 1000;
489
490         return 0;
491 }
492
493 static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
494 {
495         int result = 0;
496         struct smu10_hwmgr *data;
497
498         data = kzalloc(sizeof(struct smu10_hwmgr), GFP_KERNEL);
499         if (data == NULL)
500                 return -ENOMEM;
501
502         hwmgr->backend = data;
503
504         result = smu10_initialize_dpm_defaults(hwmgr);
505         if (result != 0) {
506                 pr_err("smu10_initialize_dpm_defaults failed\n");
507                 return result;
508         }
509
510         smu10_populate_clock_table(hwmgr);
511
512         result = smu10_get_system_info_data(hwmgr);
513         if (result != 0) {
514                 pr_err("smu10_get_system_info_data failed\n");
515                 return result;
516         }
517
518         smu10_construct_boot_state(hwmgr);
519
520         hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
521                                                 SMU10_MAX_HARDWARE_POWERLEVELS;
522
523         hwmgr->platform_descriptor.hardwarePerformanceLevels =
524                                                 SMU10_MAX_HARDWARE_POWERLEVELS;
525
526         hwmgr->platform_descriptor.vbiosInterruptId = 0;
527
528         hwmgr->platform_descriptor.clockStep.engineClock = 500;
529
530         hwmgr->platform_descriptor.clockStep.memoryClock = 500;
531
532         hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
533
534         hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK * 100;
535         hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK * 100;
536
537         return result;
538 }
539
540 static int smu10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
541 {
542         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
543         struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
544
545         kfree(pinfo->vdd_dep_on_dcefclk);
546         pinfo->vdd_dep_on_dcefclk = NULL;
547         kfree(pinfo->vdd_dep_on_socclk);
548         pinfo->vdd_dep_on_socclk = NULL;
549         kfree(pinfo->vdd_dep_on_fclk);
550         pinfo->vdd_dep_on_fclk = NULL;
551         kfree(pinfo->vdd_dep_on_dispclk);
552         pinfo->vdd_dep_on_dispclk = NULL;
553         kfree(pinfo->vdd_dep_on_dppclk);
554         pinfo->vdd_dep_on_dppclk = NULL;
555         kfree(pinfo->vdd_dep_on_phyclk);
556         pinfo->vdd_dep_on_phyclk = NULL;
557
558         kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
559         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
560
561         kfree(hwmgr->backend);
562         hwmgr->backend = NULL;
563
564         return 0;
565 }
566
567 static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
568                                 enum amd_dpm_forced_level level)
569 {
570         struct smu10_hwmgr *data = hwmgr->backend;
571         uint32_t min_sclk = hwmgr->display_config->min_core_set_clock;
572         uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100;
573
574         if (hwmgr->smu_version < 0x1E3700) {
575                 pr_info("smu firmware version too old, can not set dpm level\n");
576                 return 0;
577         }
578
579         if (min_sclk < data->gfx_min_freq_limit)
580                 min_sclk = data->gfx_min_freq_limit;
581
582         min_sclk /= 100; /* transfer 10KHz to MHz */
583         if (min_mclk < data->clock_table.FClocks[0].Freq)
584                 min_mclk = data->clock_table.FClocks[0].Freq;
585
586         switch (level) {
587         case AMD_DPM_FORCED_LEVEL_HIGH:
588         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
589                 smum_send_msg_to_smc_with_parameter(hwmgr,
590                                                 PPSMC_MSG_SetHardMinGfxClk,
591                                                 data->gfx_max_freq_limit/100);
592                 smum_send_msg_to_smc_with_parameter(hwmgr,
593                                                 PPSMC_MSG_SetHardMinFclkByFreq,
594                                                 SMU10_UMD_PSTATE_PEAK_FCLK);
595                 smum_send_msg_to_smc_with_parameter(hwmgr,
596                                                 PPSMC_MSG_SetHardMinSocclkByFreq,
597                                                 SMU10_UMD_PSTATE_PEAK_SOCCLK);
598                 smum_send_msg_to_smc_with_parameter(hwmgr,
599                                                 PPSMC_MSG_SetHardMinVcn,
600                                                 SMU10_UMD_PSTATE_VCE);
601
602                 smum_send_msg_to_smc_with_parameter(hwmgr,
603                                                 PPSMC_MSG_SetSoftMaxGfxClk,
604                                                 data->gfx_max_freq_limit/100);
605                 smum_send_msg_to_smc_with_parameter(hwmgr,
606                                                 PPSMC_MSG_SetSoftMaxFclkByFreq,
607                                                 SMU10_UMD_PSTATE_PEAK_FCLK);
608                 smum_send_msg_to_smc_with_parameter(hwmgr,
609                                                 PPSMC_MSG_SetSoftMaxSocclkByFreq,
610                                                 SMU10_UMD_PSTATE_PEAK_SOCCLK);
611                 smum_send_msg_to_smc_with_parameter(hwmgr,
612                                                 PPSMC_MSG_SetSoftMaxVcn,
613                                                 SMU10_UMD_PSTATE_VCE);
614                 break;
615         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
616                 smum_send_msg_to_smc_with_parameter(hwmgr,
617                                                 PPSMC_MSG_SetHardMinGfxClk,
618                                                 min_sclk);
619                 smum_send_msg_to_smc_with_parameter(hwmgr,
620                                                 PPSMC_MSG_SetSoftMaxGfxClk,
621                                                 min_sclk);
622                 break;
623         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
624                 smum_send_msg_to_smc_with_parameter(hwmgr,
625                                                 PPSMC_MSG_SetHardMinFclkByFreq,
626                                                 min_mclk);
627                 smum_send_msg_to_smc_with_parameter(hwmgr,
628                                                 PPSMC_MSG_SetSoftMaxFclkByFreq,
629                                                 min_mclk);
630                 break;
631         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
632                 smum_send_msg_to_smc_with_parameter(hwmgr,
633                                                 PPSMC_MSG_SetHardMinGfxClk,
634                                                 SMU10_UMD_PSTATE_GFXCLK);
635                 smum_send_msg_to_smc_with_parameter(hwmgr,
636                                                 PPSMC_MSG_SetHardMinFclkByFreq,
637                                                 SMU10_UMD_PSTATE_FCLK);
638                 smum_send_msg_to_smc_with_parameter(hwmgr,
639                                                 PPSMC_MSG_SetHardMinSocclkByFreq,
640                                                 SMU10_UMD_PSTATE_SOCCLK);
641                 smum_send_msg_to_smc_with_parameter(hwmgr,
642                                                 PPSMC_MSG_SetHardMinVcn,
643                                                 SMU10_UMD_PSTATE_VCE);
644
645                 smum_send_msg_to_smc_with_parameter(hwmgr,
646                                                 PPSMC_MSG_SetSoftMaxGfxClk,
647                                                 SMU10_UMD_PSTATE_GFXCLK);
648                 smum_send_msg_to_smc_with_parameter(hwmgr,
649                                                 PPSMC_MSG_SetSoftMaxFclkByFreq,
650                                                 SMU10_UMD_PSTATE_FCLK);
651                 smum_send_msg_to_smc_with_parameter(hwmgr,
652                                                 PPSMC_MSG_SetSoftMaxSocclkByFreq,
653                                                 SMU10_UMD_PSTATE_SOCCLK);
654                 smum_send_msg_to_smc_with_parameter(hwmgr,
655                                                 PPSMC_MSG_SetSoftMaxVcn,
656                                                 SMU10_UMD_PSTATE_VCE);
657                 break;
658         case AMD_DPM_FORCED_LEVEL_AUTO:
659                 smum_send_msg_to_smc_with_parameter(hwmgr,
660                                                 PPSMC_MSG_SetHardMinGfxClk,
661                                                 min_sclk);
662                 smum_send_msg_to_smc_with_parameter(hwmgr,
663                                                 PPSMC_MSG_SetHardMinFclkByFreq,
664                                                 hwmgr->display_config->num_display > 3 ?
665                                                 SMU10_UMD_PSTATE_PEAK_FCLK :
666                                                 min_mclk);
667
668                 smum_send_msg_to_smc_with_parameter(hwmgr,
669                                                 PPSMC_MSG_SetHardMinSocclkByFreq,
670                                                 SMU10_UMD_PSTATE_MIN_SOCCLK);
671                 smum_send_msg_to_smc_with_parameter(hwmgr,
672                                                 PPSMC_MSG_SetHardMinVcn,
673                                                 SMU10_UMD_PSTATE_MIN_VCE);
674
675                 smum_send_msg_to_smc_with_parameter(hwmgr,
676                                                 PPSMC_MSG_SetSoftMaxGfxClk,
677                                                 data->gfx_max_freq_limit/100);
678                 smum_send_msg_to_smc_with_parameter(hwmgr,
679                                                 PPSMC_MSG_SetSoftMaxFclkByFreq,
680                                                 SMU10_UMD_PSTATE_PEAK_FCLK);
681                 smum_send_msg_to_smc_with_parameter(hwmgr,
682                                                 PPSMC_MSG_SetSoftMaxSocclkByFreq,
683                                                 SMU10_UMD_PSTATE_PEAK_SOCCLK);
684                 smum_send_msg_to_smc_with_parameter(hwmgr,
685                                                 PPSMC_MSG_SetSoftMaxVcn,
686                                                 SMU10_UMD_PSTATE_VCE);
687                 break;
688         case AMD_DPM_FORCED_LEVEL_LOW:
689                 smum_send_msg_to_smc_with_parameter(hwmgr,
690                                                 PPSMC_MSG_SetHardMinGfxClk,
691                                                 data->gfx_min_freq_limit/100);
692                 smum_send_msg_to_smc_with_parameter(hwmgr,
693                                                 PPSMC_MSG_SetSoftMaxGfxClk,
694                                                 data->gfx_min_freq_limit/100);
695                 smum_send_msg_to_smc_with_parameter(hwmgr,
696                                                 PPSMC_MSG_SetHardMinFclkByFreq,
697                                                 min_mclk);
698                 smum_send_msg_to_smc_with_parameter(hwmgr,
699                                                 PPSMC_MSG_SetSoftMaxFclkByFreq,
700                                                 min_mclk);
701                 break;
702         case AMD_DPM_FORCED_LEVEL_MANUAL:
703         case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
704         default:
705                 break;
706         }
707         return 0;
708 }
709
710 static uint32_t smu10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
711 {
712         struct smu10_hwmgr *data;
713
714         if (hwmgr == NULL)
715                 return -EINVAL;
716
717         data = (struct smu10_hwmgr *)(hwmgr->backend);
718
719         if (low)
720                 return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
721         else
722                 return data->clock_vol_info.vdd_dep_on_fclk->entries[
723                         data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
724 }
725
726 static uint32_t smu10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
727 {
728         struct smu10_hwmgr *data;
729
730         if (hwmgr == NULL)
731                 return -EINVAL;
732
733         data = (struct smu10_hwmgr *)(hwmgr->backend);
734
735         if (low)
736                 return data->gfx_min_freq_limit;
737         else
738                 return data->gfx_max_freq_limit;
739 }
740
741 static int smu10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
742                                         struct pp_hw_power_state *hw_ps)
743 {
744         return 0;
745 }
746
747 static int smu10_dpm_get_pp_table_entry_callback(
748                                                      struct pp_hwmgr *hwmgr,
749                                            struct pp_hw_power_state *hw_ps,
750                                                           unsigned int index,
751                                                      const void *clock_info)
752 {
753         struct smu10_power_state *smu10_ps = cast_smu10_ps(hw_ps);
754
755         smu10_ps->levels[index].engine_clock = 0;
756
757         smu10_ps->levels[index].vddc_index = 0;
758         smu10_ps->level = index + 1;
759
760         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
761                 smu10_ps->levels[index].ds_divider_index = 5;
762                 smu10_ps->levels[index].ss_divider_index = 5;
763         }
764
765         return 0;
766 }
767
768 static int smu10_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr)
769 {
770         int result;
771         unsigned long ret = 0;
772
773         result = pp_tables_get_num_of_entries(hwmgr, &ret);
774
775         return result ? 0 : ret;
776 }
777
778 static int smu10_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
779                     unsigned long entry, struct pp_power_state *ps)
780 {
781         int result;
782         struct smu10_power_state *smu10_ps;
783
784         ps->hardware.magic = SMU10_Magic;
785
786         smu10_ps = cast_smu10_ps(&(ps->hardware));
787
788         result = pp_tables_get_entry(hwmgr, entry, ps,
789                         smu10_dpm_get_pp_table_entry_callback);
790
791         smu10_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK;
792         smu10_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK;
793
794         return result;
795 }
796
797 static int smu10_get_power_state_size(struct pp_hwmgr *hwmgr)
798 {
799         return sizeof(struct smu10_power_state);
800 }
801
802 static int smu10_set_cpu_power_state(struct pp_hwmgr *hwmgr)
803 {
804         return 0;
805 }
806
807
808 static int smu10_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time,
809                         bool cc6_disable, bool pstate_disable, bool pstate_switch_disable)
810 {
811         struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend);
812
813         if (separation_time != data->separation_time ||
814                         cc6_disable != data->cc6_disable ||
815                         pstate_disable != data->pstate_disable) {
816                 data->separation_time = separation_time;
817                 data->cc6_disable = cc6_disable;
818                 data->pstate_disable = pstate_disable;
819                 data->cc6_setting_changed = true;
820         }
821         return 0;
822 }
823
824 static int smu10_get_dal_power_level(struct pp_hwmgr *hwmgr,
825                 struct amd_pp_simple_clock_info *info)
826 {
827         return -EINVAL;
828 }
829
830 static int smu10_force_clock_level(struct pp_hwmgr *hwmgr,
831                 enum pp_clock_type type, uint32_t mask)
832 {
833         struct smu10_hwmgr *data = hwmgr->backend;
834         struct smu10_voltage_dependency_table *mclk_table =
835                                         data->clock_vol_info.vdd_dep_on_fclk;
836         uint32_t low, high;
837
838         low = mask ? (ffs(mask) - 1) : 0;
839         high = mask ? (fls(mask) - 1) : 0;
840
841         switch (type) {
842         case PP_SCLK:
843                 if (low > 2 || high > 2) {
844                         pr_info("Currently sclk only support 3 levels on RV\n");
845                         return -EINVAL;
846                 }
847
848                 smum_send_msg_to_smc_with_parameter(hwmgr,
849                                                 PPSMC_MSG_SetHardMinGfxClk,
850                                                 low == 2 ? data->gfx_max_freq_limit/100 :
851                                                 low == 1 ? SMU10_UMD_PSTATE_GFXCLK :
852                                                 data->gfx_min_freq_limit/100);
853
854                 smum_send_msg_to_smc_with_parameter(hwmgr,
855                                                 PPSMC_MSG_SetSoftMaxGfxClk,
856                                                 high == 0 ? data->gfx_min_freq_limit/100 :
857                                                 high == 1 ? SMU10_UMD_PSTATE_GFXCLK :
858                                                 data->gfx_max_freq_limit/100);
859                 break;
860
861         case PP_MCLK:
862                 if (low > mclk_table->count - 1 || high > mclk_table->count - 1)
863                         return -EINVAL;
864
865                 smum_send_msg_to_smc_with_parameter(hwmgr,
866                                                 PPSMC_MSG_SetHardMinFclkByFreq,
867                                                 mclk_table->entries[low].clk/100);
868
869                 smum_send_msg_to_smc_with_parameter(hwmgr,
870                                                 PPSMC_MSG_SetSoftMaxFclkByFreq,
871                                                 mclk_table->entries[high].clk/100);
872                 break;
873
874         case PP_PCIE:
875         default:
876                 break;
877         }
878         return 0;
879 }
880
881 static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
882                 enum pp_clock_type type, char *buf)
883 {
884         struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend);
885         struct smu10_voltage_dependency_table *mclk_table =
886                         data->clock_vol_info.vdd_dep_on_fclk;
887         uint32_t i, now, size = 0;
888
889         switch (type) {
890         case PP_SCLK:
891                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency);
892                 now = smum_get_argument(hwmgr);
893
894         /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */
895                 if (now == data->gfx_max_freq_limit/100)
896                         i = 2;
897                 else if (now == data->gfx_min_freq_limit/100)
898                         i = 0;
899                 else
900                         i = 1;
901
902                 size += sprintf(buf + size, "0: %uMhz %s\n",
903                                         data->gfx_min_freq_limit/100,
904                                         i == 0 ? "*" : "");
905                 size += sprintf(buf + size, "1: %uMhz %s\n",
906                                         i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK,
907                                         i == 1 ? "*" : "");
908                 size += sprintf(buf + size, "2: %uMhz %s\n",
909                                         data->gfx_max_freq_limit/100,
910                                         i == 2 ? "*" : "");
911                 break;
912         case PP_MCLK:
913                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency);
914                 now = smum_get_argument(hwmgr);
915
916                 for (i = 0; i < mclk_table->count; i++)
917                         size += sprintf(buf + size, "%d: %uMhz %s\n",
918                                         i,
919                                         mclk_table->entries[i].clk / 100,
920                                         ((mclk_table->entries[i].clk / 100)
921                                          == now) ? "*" : "");
922                 break;
923         default:
924                 break;
925         }
926
927         return size;
928 }
929
930 static int smu10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
931                                 PHM_PerformanceLevelDesignation designation, uint32_t index,
932                                 PHM_PerformanceLevel *level)
933 {
934         struct smu10_hwmgr *data;
935
936         if (level == NULL || hwmgr == NULL || state == NULL)
937                 return -EINVAL;
938
939         data = (struct smu10_hwmgr *)(hwmgr->backend);
940
941         if (index == 0) {
942                 level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
943                 level->coreClock = data->gfx_min_freq_limit;
944         } else {
945                 level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[
946                         data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
947                 level->coreClock = data->gfx_max_freq_limit;
948         }
949
950         level->nonLocalMemoryFreq = 0;
951         level->nonLocalMemoryWidth = 0;
952
953         return 0;
954 }
955
956 static int smu10_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr,
957         const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
958 {
959         const struct smu10_power_state *ps = cast_const_smu10_ps(state);
960
961         clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index));
962         clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index));
963
964         return 0;
965 }
966
967 #define MEM_FREQ_LOW_LATENCY        25000
968 #define MEM_FREQ_HIGH_LATENCY       80000
969 #define MEM_LATENCY_HIGH            245
970 #define MEM_LATENCY_LOW             35
971 #define MEM_LATENCY_ERR             0xFFFF
972
973
974 static uint32_t smu10_get_mem_latency(struct pp_hwmgr *hwmgr,
975                 uint32_t clock)
976 {
977         if (clock >= MEM_FREQ_LOW_LATENCY &&
978                         clock < MEM_FREQ_HIGH_LATENCY)
979                 return MEM_LATENCY_HIGH;
980         else if (clock >= MEM_FREQ_HIGH_LATENCY)
981                 return MEM_LATENCY_LOW;
982         else
983                 return MEM_LATENCY_ERR;
984 }
985
986 static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
987                 enum amd_pp_clock_type type,
988                 struct pp_clock_levels_with_latency *clocks)
989 {
990         uint32_t i;
991         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
992         struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
993         struct smu10_voltage_dependency_table *pclk_vol_table;
994         bool latency_required = false;
995
996         if (pinfo == NULL)
997                 return -EINVAL;
998
999         switch (type) {
1000         case amd_pp_mem_clock:
1001                 pclk_vol_table = pinfo->vdd_dep_on_mclk;
1002                 latency_required = true;
1003                 break;
1004         case amd_pp_f_clock:
1005                 pclk_vol_table = pinfo->vdd_dep_on_fclk;
1006                 latency_required = true;
1007                 break;
1008         case amd_pp_dcf_clock:
1009                 pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
1010                 break;
1011         case amd_pp_disp_clock:
1012                 pclk_vol_table = pinfo->vdd_dep_on_dispclk;
1013                 break;
1014         case amd_pp_phy_clock:
1015                 pclk_vol_table = pinfo->vdd_dep_on_phyclk;
1016                 break;
1017         case amd_pp_dpp_clock:
1018                 pclk_vol_table = pinfo->vdd_dep_on_dppclk;
1019                 break;
1020         default:
1021                 return -EINVAL;
1022         }
1023
1024         if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
1025                 return -EINVAL;
1026
1027         clocks->num_levels = 0;
1028         for (i = 0; i < pclk_vol_table->count; i++) {
1029                 clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk * 10;
1030                 clocks->data[i].latency_in_us = latency_required ?
1031                                                 smu10_get_mem_latency(hwmgr,
1032                                                 pclk_vol_table->entries[i].clk) :
1033                                                 0;
1034                 clocks->num_levels++;
1035         }
1036
1037         return 0;
1038 }
1039
1040 static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
1041                 enum amd_pp_clock_type type,
1042                 struct pp_clock_levels_with_voltage *clocks)
1043 {
1044         uint32_t i;
1045         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1046         struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
1047         struct smu10_voltage_dependency_table *pclk_vol_table = NULL;
1048
1049         if (pinfo == NULL)
1050                 return -EINVAL;
1051
1052         switch (type) {
1053         case amd_pp_mem_clock:
1054                 pclk_vol_table = pinfo->vdd_dep_on_mclk;
1055                 break;
1056         case amd_pp_f_clock:
1057                 pclk_vol_table = pinfo->vdd_dep_on_fclk;
1058                 break;
1059         case amd_pp_dcf_clock:
1060                 pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
1061                 break;
1062         case amd_pp_soc_clock:
1063                 pclk_vol_table = pinfo->vdd_dep_on_socclk;
1064                 break;
1065         case amd_pp_disp_clock:
1066                 pclk_vol_table = pinfo->vdd_dep_on_dispclk;
1067                 break;
1068         case amd_pp_phy_clock:
1069                 pclk_vol_table = pinfo->vdd_dep_on_phyclk;
1070                 break;
1071         default:
1072                 return -EINVAL;
1073         }
1074
1075         if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
1076                 return -EINVAL;
1077
1078         clocks->num_levels = 0;
1079         for (i = 0; i < pclk_vol_table->count; i++) {
1080                 clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk  * 10;
1081                 clocks->data[i].voltage_in_mv = pclk_vol_table->entries[i].vol;
1082                 clocks->num_levels++;
1083         }
1084
1085         return 0;
1086 }
1087
1088
1089
1090 static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
1091 {
1092         clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */
1093         return 0;
1094 }
1095
1096 static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
1097 {
1098         struct amdgpu_device *adev = hwmgr->adev;
1099         uint32_t reg_value = RREG32_SOC15(THM, 0, mmTHM_TCON_CUR_TMP);
1100         int cur_temp =
1101                 (reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT;
1102
1103         if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK)
1104                 cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1105         else
1106                 cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1107
1108         return cur_temp;
1109 }
1110
1111 static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
1112                           void *value, int *size)
1113 {
1114         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1115         uint32_t sclk, mclk;
1116         int ret = 0;
1117
1118         switch (idx) {
1119         case AMDGPU_PP_SENSOR_GFX_SCLK:
1120                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency);
1121                 sclk = smum_get_argument(hwmgr);
1122                         /* in units of 10KHZ */
1123                 *((uint32_t *)value) = sclk * 100;
1124                 *size = 4;
1125                 break;
1126         case AMDGPU_PP_SENSOR_GFX_MCLK:
1127                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency);
1128                 mclk = smum_get_argument(hwmgr);
1129                         /* in units of 10KHZ */
1130                 *((uint32_t *)value) = mclk * 100;
1131                 *size = 4;
1132                 break;
1133         case AMDGPU_PP_SENSOR_GPU_TEMP:
1134                 *((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr);
1135                 break;
1136         case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
1137                 *(uint32_t *)value =  smu10_data->vcn_power_gated ? 0 : 1;
1138                 *size = 4;
1139                 break;
1140         default:
1141                 ret = -EINVAL;
1142                 break;
1143         }
1144
1145         return ret;
1146 }
1147
1148 static int smu10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
1149                 void *clock_ranges)
1150 {
1151         struct smu10_hwmgr *data = hwmgr->backend;
1152         struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
1153         Watermarks_t *table = &(data->water_marks_table);
1154         int result = 0;
1155
1156         smu_set_watermarks_for_clocks_ranges(table,wm_with_clock_ranges);
1157         smum_smc_table_manager(hwmgr, (uint8_t *)table, (uint16_t)SMU10_WMTABLE, false);
1158         data->water_marks_exist = true;
1159         return result;
1160 }
1161
1162 static int smu10_smus_notify_pwe(struct pp_hwmgr *hwmgr)
1163 {
1164
1165         return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SetRccPfcPmeRestoreRegister);
1166 }
1167
1168 static int smu10_powergate_mmhub(struct pp_hwmgr *hwmgr)
1169 {
1170         return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub);
1171 }
1172
1173 static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate)
1174 {
1175         if (gate)
1176                 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma);
1177         else
1178                 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma);
1179 }
1180
1181 static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate)
1182 {
1183         struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1184
1185         if (bgate) {
1186                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
1187                                                 AMD_IP_BLOCK_TYPE_VCN,
1188                                                 AMD_PG_STATE_GATE);
1189                 smum_send_msg_to_smc_with_parameter(hwmgr,
1190                                         PPSMC_MSG_PowerDownVcn, 0);
1191                 smu10_data->vcn_power_gated = true;
1192         } else {
1193                 smum_send_msg_to_smc_with_parameter(hwmgr,
1194                                                 PPSMC_MSG_PowerUpVcn, 0);
1195                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
1196                                                 AMD_IP_BLOCK_TYPE_VCN,
1197                                                 AMD_PG_STATE_UNGATE);
1198                 smu10_data->vcn_power_gated = false;
1199         }
1200 }
1201
1202 static int conv_power_profile_to_pplib_workload(int power_profile)
1203 {
1204         int pplib_workload = 0;
1205
1206         switch (power_profile) {
1207         case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
1208                 pplib_workload = WORKLOAD_DEFAULT_BIT;
1209                 break;
1210         case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
1211                 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
1212                 break;
1213         case PP_SMC_POWER_PROFILE_POWERSAVING:
1214                 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
1215                 break;
1216         case PP_SMC_POWER_PROFILE_VIDEO:
1217                 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
1218                 break;
1219         case PP_SMC_POWER_PROFILE_VR:
1220                 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
1221                 break;
1222         case PP_SMC_POWER_PROFILE_COMPUTE:
1223                 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
1224                 break;
1225         }
1226
1227         return pplib_workload;
1228 }
1229
1230 static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
1231 {
1232         uint32_t i, size = 0;
1233         static const uint8_t
1234                 profile_mode_setting[6][4] = {{70, 60, 0, 0,},
1235                                                 {70, 60, 1, 3,},
1236                                                 {90, 60, 0, 0,},
1237                                                 {70, 60, 0, 0,},
1238                                                 {70, 90, 0, 0,},
1239                                                 {30, 60, 0, 6,},
1240                                                 };
1241         static const char *profile_name[6] = {
1242                                         "BOOTUP_DEFAULT",
1243                                         "3D_FULL_SCREEN",
1244                                         "POWER_SAVING",
1245                                         "VIDEO",
1246                                         "VR",
1247                                         "COMPUTE"};
1248         static const char *title[6] = {"NUM",
1249                         "MODE_NAME",
1250                         "BUSY_SET_POINT",
1251                         "FPS",
1252                         "USE_RLC_BUSY",
1253                         "MIN_ACTIVE_LEVEL"};
1254
1255         if (!buf)
1256                 return -EINVAL;
1257
1258         size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
1259                         title[1], title[2], title[3], title[4], title[5]);
1260
1261         for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++)
1262                 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n",
1263                         i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
1264                         profile_mode_setting[i][0], profile_mode_setting[i][1],
1265                         profile_mode_setting[i][2], profile_mode_setting[i][3]);
1266
1267         return size;
1268 }
1269
1270 static bool smu10_is_raven1_refresh(struct pp_hwmgr *hwmgr)
1271 {
1272         struct amdgpu_device *adev = hwmgr->adev;
1273         if ((adev->asic_type == CHIP_RAVEN) &&
1274             (adev->rev_id != 0x15d8) &&
1275             (hwmgr->smu_version >= 0x41e2b))
1276                 return true;
1277         else
1278                 return false;
1279 }
1280
1281 static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
1282 {
1283         int workload_type = 0;
1284         int result = 0;
1285
1286         if (input[size] > PP_SMC_POWER_PROFILE_COMPUTE) {
1287                 pr_err("Invalid power profile mode %ld\n", input[size]);
1288                 return -EINVAL;
1289         }
1290         if (hwmgr->power_profile_mode == input[size])
1291                 return 0;
1292
1293         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1294         workload_type =
1295                 conv_power_profile_to_pplib_workload(input[size]);
1296         if (workload_type &&
1297             smu10_is_raven1_refresh(hwmgr) &&
1298             !hwmgr->gfxoff_state_changed_by_workload) {
1299                 smu10_gfx_off_control(hwmgr, false);
1300                 hwmgr->gfxoff_state_changed_by_workload = true;
1301         }
1302         result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify,
1303                                                 1 << workload_type);
1304         if (!result)
1305                 hwmgr->power_profile_mode = input[size];
1306         if (workload_type && hwmgr->gfxoff_state_changed_by_workload) {
1307                 smu10_gfx_off_control(hwmgr, true);
1308                 hwmgr->gfxoff_state_changed_by_workload = false;
1309         }
1310
1311         return 0;
1312 }
1313
1314
1315 static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
1316         .backend_init = smu10_hwmgr_backend_init,
1317         .backend_fini = smu10_hwmgr_backend_fini,
1318         .asic_setup = NULL,
1319         .apply_state_adjust_rules = smu10_apply_state_adjust_rules,
1320         .force_dpm_level = smu10_dpm_force_dpm_level,
1321         .get_power_state_size = smu10_get_power_state_size,
1322         .powerdown_uvd = NULL,
1323         .powergate_uvd = smu10_powergate_vcn,
1324         .powergate_vce = NULL,
1325         .get_mclk = smu10_dpm_get_mclk,
1326         .get_sclk = smu10_dpm_get_sclk,
1327         .patch_boot_state = smu10_dpm_patch_boot_state,
1328         .get_pp_table_entry = smu10_dpm_get_pp_table_entry,
1329         .get_num_of_pp_table_entries = smu10_dpm_get_num_of_pp_table_entries,
1330         .set_cpu_power_state = smu10_set_cpu_power_state,
1331         .store_cc6_data = smu10_store_cc6_data,
1332         .force_clock_level = smu10_force_clock_level,
1333         .print_clock_levels = smu10_print_clock_levels,
1334         .get_dal_power_level = smu10_get_dal_power_level,
1335         .get_performance_level = smu10_get_performance_level,
1336         .get_current_shallow_sleep_clocks = smu10_get_current_shallow_sleep_clocks,
1337         .get_clock_by_type_with_latency = smu10_get_clock_by_type_with_latency,
1338         .get_clock_by_type_with_voltage = smu10_get_clock_by_type_with_voltage,
1339         .set_watermarks_for_clocks_ranges = smu10_set_watermarks_for_clocks_ranges,
1340         .get_max_high_clocks = smu10_get_max_high_clocks,
1341         .read_sensor = smu10_read_sensor,
1342         .set_active_display_count = smu10_set_active_display_count,
1343         .set_min_deep_sleep_dcefclk = smu10_set_min_deep_sleep_dcefclk,
1344         .dynamic_state_management_enable = smu10_enable_dpm_tasks,
1345         .power_off_asic = smu10_power_off_asic,
1346         .asic_setup = smu10_setup_asic_task,
1347         .power_state_set = smu10_set_power_state_tasks,
1348         .dynamic_state_management_disable = smu10_disable_dpm_tasks,
1349         .powergate_mmhub = smu10_powergate_mmhub,
1350         .smus_notify_pwe = smu10_smus_notify_pwe,
1351         .display_clock_voltage_request = smu10_display_clock_voltage_request,
1352         .powergate_gfx = smu10_gfx_off_control,
1353         .powergate_sdma = smu10_powergate_sdma,
1354         .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq,
1355         .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq,
1356         .get_power_profile_mode = smu10_get_power_profile_mode,
1357         .set_power_profile_mode = smu10_set_power_profile_mode,
1358 };
1359
1360 int smu10_init_function_pointers(struct pp_hwmgr *hwmgr)
1361 {
1362         hwmgr->hwmgr_func = &smu10_hwmgr_funcs;
1363         hwmgr->pptable_func = &pptable_funcs;
1364         return 0;
1365 }