]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/powerplay/renoir_ppt.c
e73644beffd964b5f2921b4cdfc101a1b714df94
[linux.git] / drivers / gpu / drm / amd / powerplay / renoir_ppt.c
1 /*
2  * Copyright 2019 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 "amdgpu.h"
25 #include "amdgpu_smu.h"
26 #include "smu_internal.h"
27 #include "soc15_common.h"
28 #include "smu_v12_0_ppsmc.h"
29 #include "smu12_driver_if.h"
30 #include "smu_v12_0.h"
31 #include "renoir_ppt.h"
32
33
34 #define CLK_MAP(clk, index) \
35         [SMU_##clk] = {1, (index)}
36
37 #define MSG_MAP(msg, index) \
38         [SMU_MSG_##msg] = {1, (index)}
39
40 #define TAB_MAP_VALID(tab) \
41         [SMU_TABLE_##tab] = {1, TABLE_##tab}
42
43 #define TAB_MAP_INVALID(tab) \
44         [SMU_TABLE_##tab] = {0, TABLE_##tab}
45
46 static struct smu_12_0_cmn2aisc_mapping renoir_message_map[SMU_MSG_MAX_COUNT] = {
47         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage),
48         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion),
49         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion),
50         MSG_MAP(PowerUpGfx,                     PPSMC_MSG_PowerUpGfx),
51         MSG_MAP(AllowGfxOff,                    PPSMC_MSG_EnableGfxOff),
52         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisableGfxOff),
53         MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile),
54         MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile),
55         MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn),
56         MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn),
57         MSG_MAP(PowerDownSdma,                  PPSMC_MSG_PowerDownSdma),
58         MSG_MAP(PowerUpSdma,                    PPSMC_MSG_PowerUpSdma),
59         MSG_MAP(SetHardMinIspclkByFreq,         PPSMC_MSG_SetHardMinIspclkByFreq),
60         MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn),
61         MSG_MAP(Spare1,                         PPSMC_MSG_spare1),
62         MSG_MAP(Spare2,                         PPSMC_MSG_spare2),
63         MSG_MAP(SetAllowFclkSwitch,             PPSMC_MSG_SetAllowFclkSwitch),
64         MSG_MAP(SetMinVideoGfxclkFreq,          PPSMC_MSG_SetMinVideoGfxclkFreq),
65         MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify),
66         MSG_MAP(SetCustomPolicy,                PPSMC_MSG_SetCustomPolicy),
67         MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps),
68         MSG_MAP(NumOfDisplays,                  PPSMC_MSG_SetDisplayCount),
69         MSG_MAP(QueryPowerLimit,                PPSMC_MSG_QueryPowerLimit),
70         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh),
71         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow),
72         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram),
73         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu),
74         MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset),
75         MSG_MAP(SetGfxclkOverdriveByFreqVid,    PPSMC_MSG_SetGfxclkOverdriveByFreqVid),
76         MSG_MAP(SetHardMinDcfclkByFreq,         PPSMC_MSG_SetHardMinDcfclkByFreq),
77         MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq),
78         MSG_MAP(ControlIgpuATS,                 PPSMC_MSG_ControlIgpuATS),
79         MSG_MAP(SetMinVideoFclkFreq,            PPSMC_MSG_SetMinVideoFclkFreq),
80         MSG_MAP(SetMinDeepSleepDcfclk,          PPSMC_MSG_SetMinDeepSleepDcfclk),
81         MSG_MAP(ForcePowerDownGfx,              PPSMC_MSG_ForcePowerDownGfx),
82         MSG_MAP(SetPhyclkVoltageByFreq,         PPSMC_MSG_SetPhyclkVoltageByFreq),
83         MSG_MAP(SetDppclkVoltageByFreq,         PPSMC_MSG_SetDppclkVoltageByFreq),
84         MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn),
85         MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode),
86         MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency),
87         MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency),
88         MSG_MAP(GetMinGfxclkFrequency,          PPSMC_MSG_GetMinGfxclkFrequency),
89         MSG_MAP(GetMaxGfxclkFrequency,          PPSMC_MSG_GetMaxGfxclkFrequency),
90         MSG_MAP(SoftReset,                      PPSMC_MSG_SoftReset),
91         MSG_MAP(SetGfxCGPG,                     PPSMC_MSG_SetGfxCGPG),
92         MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk),
93         MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk),
94         MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq),
95         MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq),
96         MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn),
97         MSG_MAP(PowerGateMmHub,                 PPSMC_MSG_PowerGateMmHub),
98         MSG_MAP(UpdatePmeRestore,               PPSMC_MSG_UpdatePmeRestore),
99         MSG_MAP(GpuChangeState,                 PPSMC_MSG_GpuChangeState),
100         MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage),
101         MSG_MAP(ForceGfxContentSave,            PPSMC_MSG_ForceGfxContentSave),
102         MSG_MAP(EnableTmdp48MHzRefclkPwrDown,   PPSMC_MSG_EnableTmdp48MHzRefclkPwrDown),
103         MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg),
104         MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg),
105         MSG_MAP(PowerGateAtHub,                 PPSMC_MSG_PowerGateAtHub),
106         MSG_MAP(SetSoftMinJpeg,                 PPSMC_MSG_SetSoftMinJpeg),
107         MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq),
108 };
109
110 static struct smu_12_0_cmn2aisc_mapping renoir_clk_map[SMU_CLK_COUNT] = {
111         CLK_MAP(GFXCLK, CLOCK_GFXCLK),
112         CLK_MAP(SCLK,   CLOCK_GFXCLK),
113         CLK_MAP(SOCCLK, CLOCK_SOCCLK),
114         CLK_MAP(UCLK, CLOCK_UMCCLK),
115         CLK_MAP(MCLK, CLOCK_UMCCLK),
116 };
117
118 static struct smu_12_0_cmn2aisc_mapping renoir_table_map[SMU_TABLE_COUNT] = {
119         TAB_MAP_VALID(WATERMARKS),
120         TAB_MAP_INVALID(CUSTOM_DPM),
121         TAB_MAP_VALID(DPMCLOCKS),
122         TAB_MAP_VALID(SMU_METRICS),
123 };
124
125 static int renoir_get_smu_msg_index(struct smu_context *smc, uint32_t index)
126 {
127         struct smu_12_0_cmn2aisc_mapping mapping;
128
129         if (index >= SMU_MSG_MAX_COUNT)
130                 return -EINVAL;
131
132         mapping = renoir_message_map[index];
133         if (!(mapping.valid_mapping))
134                 return -EINVAL;
135
136         return mapping.map_to;
137 }
138
139 static int renoir_get_smu_clk_index(struct smu_context *smc, uint32_t index)
140 {
141         struct smu_12_0_cmn2aisc_mapping mapping;
142
143         if (index >= SMU_CLK_COUNT)
144                 return -EINVAL;
145
146         mapping = renoir_clk_map[index];
147         if (!(mapping.valid_mapping)) {
148                 return -EINVAL;
149         }
150
151         return mapping.map_to;
152 }
153
154 static int renoir_get_smu_table_index(struct smu_context *smc, uint32_t index)
155 {
156         struct smu_12_0_cmn2aisc_mapping mapping;
157
158         if (index >= SMU_TABLE_COUNT)
159                 return -EINVAL;
160
161         mapping = renoir_table_map[index];
162         if (!(mapping.valid_mapping))
163                 return -EINVAL;
164
165         return mapping.map_to;
166 }
167
168 static int renoir_get_metrics_table(struct smu_context *smu,
169                                     SmuMetrics_t *metrics_table)
170 {
171         struct smu_table_context *smu_table= &smu->smu_table;
172         int ret = 0;
173
174         mutex_lock(&smu->metrics_lock);
175         if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) {
176                 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
177                                 (void *)smu_table->metrics_table, false);
178                 if (ret) {
179                         pr_info("Failed to export SMU metrics table!\n");
180                         mutex_unlock(&smu->metrics_lock);
181                         return ret;
182                 }
183                 smu_table->metrics_time = jiffies;
184         }
185
186         memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
187         mutex_unlock(&smu->metrics_lock);
188
189         return ret;
190 }
191
192 static int renoir_tables_init(struct smu_context *smu, struct smu_table *tables)
193 {
194         struct smu_table_context *smu_table = &smu->smu_table;
195
196         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
197                 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
198         SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
199                 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
200         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
201                 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
202
203         smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
204         if (!smu_table->clocks_table)
205                 return -ENOMEM;
206
207         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
208         if (!smu_table->metrics_table)
209                 return -ENOMEM;
210         smu_table->metrics_time = 0;
211
212         return 0;
213 }
214
215 /**
216  * This interface just for getting uclk ultimate freq and should't introduce
217  * other likewise function result in overmuch callback.
218  */
219 static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type,
220                                                 uint32_t dpm_level, uint32_t *freq)
221 {
222         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
223
224         if (!clk_table || clk_type >= SMU_CLK_COUNT)
225                 return -EINVAL;
226
227         GET_DPM_CUR_FREQ(clk_table, clk_type, dpm_level, *freq);
228
229         return 0;
230 }
231
232 static int renoir_print_clk_levels(struct smu_context *smu,
233                         enum smu_clk_type clk_type, char *buf)
234 {
235         int i, size = 0, ret = 0;
236         uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0;
237         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
238         SmuMetrics_t metrics;
239
240         if (!clk_table || clk_type >= SMU_CLK_COUNT)
241                 return -EINVAL;
242
243         memset(&metrics, 0, sizeof(metrics));
244
245         ret = renoir_get_metrics_table(smu, &metrics);
246         if (ret)
247                 return ret;
248
249         switch (clk_type) {
250         case SMU_GFXCLK:
251         case SMU_SCLK:
252                 /* retirve table returned paramters unit is MHz */
253                 cur_value = metrics.ClockFrequency[CLOCK_GFXCLK];
254                 ret = smu_get_dpm_freq_range(smu, SMU_GFXCLK, &min, &max, false);
255                 if (!ret) {
256                         /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */
257                         if (cur_value  == max)
258                                 i = 2;
259                         else if (cur_value == min)
260                                 i = 0;
261                         else
262                                 i = 1;
263
264                         size += sprintf(buf + size, "0: %uMhz %s\n", min,
265                                         i == 0 ? "*" : "");
266                         size += sprintf(buf + size, "1: %uMhz %s\n",
267                                         i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK,
268                                         i == 1 ? "*" : "");
269                         size += sprintf(buf + size, "2: %uMhz %s\n", max,
270                                         i == 2 ? "*" : "");
271                 }
272                 return size;
273         case SMU_SOCCLK:
274                 count = NUM_SOCCLK_DPM_LEVELS;
275                 cur_value = metrics.ClockFrequency[CLOCK_SOCCLK];
276                 break;
277         case SMU_MCLK:
278                 count = NUM_MEMCLK_DPM_LEVELS;
279                 cur_value = metrics.ClockFrequency[CLOCK_UMCCLK];
280                 break;
281         case SMU_DCEFCLK:
282                 count = NUM_DCFCLK_DPM_LEVELS;
283                 cur_value = metrics.ClockFrequency[CLOCK_DCFCLK];
284                 break;
285         case SMU_FCLK:
286                 count = NUM_FCLK_DPM_LEVELS;
287                 cur_value = metrics.ClockFrequency[CLOCK_FCLK];
288                 break;
289         default:
290                 return -EINVAL;
291         }
292
293         for (i = 0; i < count; i++) {
294                 GET_DPM_CUR_FREQ(clk_table, clk_type, i, value);
295                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
296                                 cur_value == value ? "*" : "");
297         }
298
299         return size;
300 }
301
302 static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context *smu)
303 {
304         enum amd_pm_state_type pm_type;
305         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
306
307         if (!smu_dpm_ctx->dpm_context ||
308             !smu_dpm_ctx->dpm_current_power_state)
309                 return -EINVAL;
310
311         switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
312         case SMU_STATE_UI_LABEL_BATTERY:
313                 pm_type = POWER_STATE_TYPE_BATTERY;
314                 break;
315         case SMU_STATE_UI_LABEL_BALLANCED:
316                 pm_type = POWER_STATE_TYPE_BALANCED;
317                 break;
318         case SMU_STATE_UI_LABEL_PERFORMANCE:
319                 pm_type = POWER_STATE_TYPE_PERFORMANCE;
320                 break;
321         default:
322                 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
323                         pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
324                 else
325                         pm_type = POWER_STATE_TYPE_DEFAULT;
326                 break;
327         }
328
329         return pm_type;
330 }
331
332 static int renoir_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
333 {
334         struct smu_power_context *smu_power = &smu->smu_power;
335         struct smu_power_gate *power_gate = &smu_power->power_gate;
336         int ret = 0;
337
338         if (enable) {
339                 /* vcn dpm on is a prerequisite for vcn power gate messages */
340                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
341                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0);
342                         if (ret)
343                                 return ret;
344                 }
345                 power_gate->vcn_gated = false;
346         } else {
347                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
348                         ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
349                         if (ret)
350                                 return ret;
351                 }
352                 power_gate->vcn_gated = true;
353         }
354
355         return ret;
356 }
357
358 static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
359 {
360         struct smu_power_context *smu_power = &smu->smu_power;
361         struct smu_power_gate *power_gate = &smu_power->power_gate;
362         int ret = 0;
363
364         if (enable) {
365                 if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
366                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0);
367                         if (ret)
368                                 return ret;
369                 }
370                 power_gate->jpeg_gated = false;
371         } else {
372                 if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
373                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0);
374                         if (ret)
375                                 return ret;
376                 }
377                 power_gate->jpeg_gated = true;
378         }
379
380         return ret;
381 }
382
383 static int renoir_get_current_clk_freq_by_table(struct smu_context *smu,
384                                        enum smu_clk_type clk_type,
385                                        uint32_t *value)
386 {
387         int ret = 0, clk_id = 0;
388         SmuMetrics_t metrics;
389
390         ret = renoir_get_metrics_table(smu, &metrics);
391         if (ret)
392                 return ret;
393
394         clk_id = smu_clk_get_index(smu, clk_type);
395         if (clk_id < 0)
396                 return clk_id;
397
398         *value = metrics.ClockFrequency[clk_id];
399
400         return ret;
401 }
402
403 static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest)
404 {
405         int ret = 0, i = 0;
406         uint32_t min_freq, max_freq, force_freq;
407         enum smu_clk_type clk_type;
408
409         enum smu_clk_type clks[] = {
410                 SMU_GFXCLK,
411                 SMU_MCLK,
412                 SMU_SOCCLK,
413         };
414
415         for (i = 0; i < ARRAY_SIZE(clks); i++) {
416                 clk_type = clks[i];
417                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false);
418                 if (ret)
419                         return ret;
420
421                 force_freq = highest ? max_freq : min_freq;
422                 ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq);
423                 if (ret)
424                         return ret;
425         }
426
427         return ret;
428 }
429
430 static int renoir_unforce_dpm_levels(struct smu_context *smu) {
431
432         int ret = 0, i = 0;
433         uint32_t min_freq, max_freq;
434         enum smu_clk_type clk_type;
435
436         struct clk_feature_map {
437                 enum smu_clk_type clk_type;
438                 uint32_t        feature;
439         } clk_feature_map[] = {
440                 {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT},
441                 {SMU_MCLK,   SMU_FEATURE_DPM_UCLK_BIT},
442                 {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT},
443         };
444
445         for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) {
446                 if (!smu_feature_is_enabled(smu, clk_feature_map[i].feature))
447                     continue;
448
449                 clk_type = clk_feature_map[i].clk_type;
450
451                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false);
452                 if (ret)
453                         return ret;
454
455                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
456                 if (ret)
457                         return ret;
458         }
459
460         return ret;
461 }
462
463 static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value)
464 {
465         int ret = 0;
466         SmuMetrics_t metrics;
467
468         if (!value)
469                 return -EINVAL;
470
471         ret = renoir_get_metrics_table(smu, &metrics);
472         if (ret)
473                 return ret;
474
475         *value = (metrics.GfxTemperature / 100) *
476                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
477
478         return 0;
479 }
480
481 static int renoir_get_current_activity_percent(struct smu_context *smu,
482                                                enum amd_pp_sensors sensor,
483                                                uint32_t *value)
484 {
485         int ret = 0;
486         SmuMetrics_t metrics;
487
488         if (!value)
489                 return -EINVAL;
490
491         ret = renoir_get_metrics_table(smu, &metrics);
492         if (ret)
493                 return ret;
494
495         switch (sensor) {
496         case AMDGPU_PP_SENSOR_GPU_LOAD:
497                 *value = metrics.AverageGfxActivity / 100;
498                 break;
499         default:
500                 pr_err("Invalid sensor for retrieving clock activity\n");
501                 return -EINVAL;
502         }
503
504         return 0;
505 }
506
507 static int renoir_get_workload_type(struct smu_context *smu, uint32_t profile)
508 {
509
510         uint32_t  pplib_workload = 0;
511
512         switch (profile) {
513         case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
514                 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
515                 break;
516         case PP_SMC_POWER_PROFILE_CUSTOM:
517                 pplib_workload = WORKLOAD_PPLIB_COUNT;
518                 break;
519         case PP_SMC_POWER_PROFILE_VIDEO:
520                 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
521                 break;
522         case PP_SMC_POWER_PROFILE_VR:
523                 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
524                 break;
525         case PP_SMC_POWER_PROFILE_COMPUTE:
526                 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
527                 break;
528         default:
529                 return -EINVAL;
530         }
531
532         return pplib_workload;
533 }
534
535 static int renoir_get_profiling_clk_mask(struct smu_context *smu,
536                                          enum amd_dpm_forced_level level,
537                                          uint32_t *sclk_mask,
538                                          uint32_t *mclk_mask,
539                                          uint32_t *soc_mask)
540 {
541
542         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
543                 if (sclk_mask)
544                         *sclk_mask = 0;
545         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
546                 if (mclk_mask)
547                         *mclk_mask = 0;
548         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
549                 if(sclk_mask)
550                         /* The sclk as gfxclk and has three level about max/min/current */
551                         *sclk_mask = 3 - 1;
552
553                 if(mclk_mask)
554                         *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1;
555
556                 if(soc_mask)
557                         *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1;
558         }
559
560         return 0;
561 }
562
563 /**
564  * This interface get dpm clock table for dc
565  */
566 static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
567 {
568         DpmClocks_t *table = smu->smu_table.clocks_table;
569         int i;
570
571         if (!clock_table || !table)
572                 return -EINVAL;
573
574         for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
575                 clock_table->DcfClocks[i].Freq = table->DcfClocks[i].Freq;
576                 clock_table->DcfClocks[i].Vol = table->DcfClocks[i].Vol;
577         }
578
579         for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
580                 clock_table->SocClocks[i].Freq = table->SocClocks[i].Freq;
581                 clock_table->SocClocks[i].Vol = table->SocClocks[i].Vol;
582         }
583
584         for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
585                 clock_table->FClocks[i].Freq = table->FClocks[i].Freq;
586                 clock_table->FClocks[i].Vol = table->FClocks[i].Vol;
587         }
588
589         for (i = 0; i<  NUM_MEMCLK_DPM_LEVELS; i++) {
590                 clock_table->MemClocks[i].Freq = table->MemClocks[i].Freq;
591                 clock_table->MemClocks[i].Vol = table->MemClocks[i].Vol;
592         }
593
594         return 0;
595 }
596
597 static int renoir_force_clk_levels(struct smu_context *smu,
598                                    enum smu_clk_type clk_type, uint32_t mask)
599 {
600
601         int ret = 0 ;
602         uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
603         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
604
605         soft_min_level = mask ? (ffs(mask) - 1) : 0;
606         soft_max_level = mask ? (fls(mask) - 1) : 0;
607
608         switch (clk_type) {
609         case SMU_GFXCLK:
610         case SMU_SCLK:
611                 if (soft_min_level > 2 || soft_max_level > 2) {
612                         pr_info("Currently sclk only support 3 levels on APU\n");
613                         return -EINVAL;
614                 }
615
616                 ret = smu_get_dpm_freq_range(smu, SMU_GFXCLK, &min_freq, &max_freq, false);
617                 if (ret)
618                         return ret;
619                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
620                                         soft_max_level == 0 ? min_freq :
621                                         soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq);
622                 if (ret)
623                         return ret;
624                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
625                                         soft_min_level == 2 ? max_freq :
626                                         soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq);
627                 if (ret)
628                         return ret;
629                 break;
630         case SMU_SOCCLK:
631                 GET_DPM_CUR_FREQ(clk_table, clk_type, soft_min_level, min_freq);
632                 GET_DPM_CUR_FREQ(clk_table, clk_type, soft_max_level, max_freq);
633                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq);
634                 if (ret)
635                         return ret;
636                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq);
637                 if (ret)
638                         return ret;
639                 break;
640         case SMU_MCLK:
641         case SMU_FCLK:
642                 GET_DPM_CUR_FREQ(clk_table, clk_type, soft_min_level, min_freq);
643                 GET_DPM_CUR_FREQ(clk_table, clk_type, soft_max_level, max_freq);
644                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq);
645                 if (ret)
646                         return ret;
647                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq);
648                 if (ret)
649                         return ret;
650                 break;
651         default:
652                 break;
653         }
654
655         return ret;
656 }
657
658 static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
659 {
660         int workload_type, ret;
661         uint32_t profile_mode = input[size];
662
663         if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
664                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
665                 return -EINVAL;
666         }
667
668         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
669         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
670         if (workload_type < 0) {
671                 pr_err("Unsupported power profile mode %d on RENOIR\n",smu->power_profile_mode);
672                 return -EINVAL;
673         }
674
675         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
676                                     1 << workload_type);
677         if (ret) {
678                 pr_err("Fail to set workload type %d\n", workload_type);
679                 return ret;
680         }
681
682         smu->power_profile_mode = profile_mode;
683
684         return 0;
685 }
686
687 static int renoir_set_peak_clock_by_device(struct smu_context *smu)
688 {
689         int ret = 0;
690         uint32_t sclk_freq = 0, uclk_freq = 0;
691
692         ret = smu_get_dpm_freq_range(smu, SMU_SCLK, NULL, &sclk_freq, false);
693         if (ret)
694                 return ret;
695
696         ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
697         if (ret)
698                 return ret;
699
700         ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &uclk_freq, false);
701         if (ret)
702                 return ret;
703
704         ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
705         if (ret)
706                 return ret;
707
708         return ret;
709 }
710
711 static int renoir_set_performance_level(struct smu_context *smu,
712                                         enum amd_dpm_forced_level level)
713 {
714         int ret = 0;
715         uint32_t sclk_mask, mclk_mask, soc_mask;
716
717         switch (level) {
718         case AMD_DPM_FORCED_LEVEL_HIGH:
719                 ret = smu_force_dpm_limit_value(smu, true);
720                 break;
721         case AMD_DPM_FORCED_LEVEL_LOW:
722                 ret = smu_force_dpm_limit_value(smu, false);
723                 break;
724         case AMD_DPM_FORCED_LEVEL_AUTO:
725         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
726                 ret = smu_unforce_dpm_levels(smu);
727                 break;
728         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
729         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
730                 ret = smu_get_profiling_clk_mask(smu, level,
731                                                  &sclk_mask,
732                                                  &mclk_mask,
733                                                  &soc_mask);
734                 if (ret)
735                         return ret;
736                 smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask, false);
737                 smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask, false);
738                 smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask, false);
739                 break;
740         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
741                 ret = renoir_set_peak_clock_by_device(smu);
742                 break;
743         case AMD_DPM_FORCED_LEVEL_MANUAL:
744         case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
745         default:
746                 break;
747         }
748         return ret;
749 }
750
751 /* save watermark settings into pplib smu structure,
752  * also pass data to smu controller
753  */
754 static int renoir_set_watermarks_table(
755                 struct smu_context *smu,
756                 void *watermarks,
757                 struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges)
758 {
759         int i;
760         int ret = 0;
761         Watermarks_t *table = watermarks;
762
763         if (!table || !clock_ranges)
764                 return -EINVAL;
765
766         if (clock_ranges->num_wm_dmif_sets > 4 ||
767                         clock_ranges->num_wm_mcif_sets > 4)
768                 return -EINVAL;
769
770         /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/
771         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
772                 table->WatermarkRow[WM_DCFCLK][i].MinClock =
773                         cpu_to_le16((uint16_t)
774                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz));
775                 table->WatermarkRow[WM_DCFCLK][i].MaxClock =
776                         cpu_to_le16((uint16_t)
777                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz));
778                 table->WatermarkRow[WM_DCFCLK][i].MinMclk =
779                         cpu_to_le16((uint16_t)
780                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz));
781                 table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
782                         cpu_to_le16((uint16_t)
783                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz));
784                 table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t)
785                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
786         }
787
788         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
789                 table->WatermarkRow[WM_SOCCLK][i].MinClock =
790                         cpu_to_le16((uint16_t)
791                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz));
792                 table->WatermarkRow[WM_SOCCLK][i].MaxClock =
793                         cpu_to_le16((uint16_t)
794                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz));
795                 table->WatermarkRow[WM_SOCCLK][i].MinMclk =
796                         cpu_to_le16((uint16_t)
797                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz));
798                 table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
799                         cpu_to_le16((uint16_t)
800                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz));
801                 table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t)
802                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
803         }
804
805         /* pass data to smu controller */
806         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
807                         !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
808                 ret = smu_write_watermarks_table(smu);
809                 if (ret) {
810                         pr_err("Failed to update WMTABLE!");
811                         return ret;
812                 }
813                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
814         }
815
816         return 0;
817 }
818
819 static int renoir_get_power_profile_mode(struct smu_context *smu,
820                                            char *buf)
821 {
822         static const char *profile_name[] = {
823                                         "BOOTUP_DEFAULT",
824                                         "3D_FULL_SCREEN",
825                                         "POWER_SAVING",
826                                         "VIDEO",
827                                         "VR",
828                                         "COMPUTE",
829                                         "CUSTOM"};
830         uint32_t i, size = 0;
831         int16_t workload_type = 0;
832
833         if (!smu->pm_enabled || !buf)
834                 return -EINVAL;
835
836         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
837                 /*
838                  * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
839                  * Not all profile modes are supported on arcturus.
840                  */
841                 workload_type = smu_workload_get_type(smu, i);
842                 if (workload_type < 0)
843                         continue;
844
845                 size += sprintf(buf + size, "%2d %14s%s\n",
846                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
847         }
848
849         return size;
850 }
851
852 static int renoir_read_sensor(struct smu_context *smu,
853                                  enum amd_pp_sensors sensor,
854                                  void *data, uint32_t *size)
855 {
856         int ret = 0;
857
858         if (!data || !size)
859                 return -EINVAL;
860
861         mutex_lock(&smu->sensor_lock);
862         switch (sensor) {
863         case AMDGPU_PP_SENSOR_GPU_LOAD:
864                 ret = renoir_get_current_activity_percent(smu, sensor, (uint32_t *)data);
865                 *size = 4;
866                 break;
867         case AMDGPU_PP_SENSOR_GPU_TEMP:
868                 ret = renoir_get_gpu_temperature(smu, (uint32_t *)data);
869                 *size = 4;
870                 break;
871         default:
872                 ret = smu_v12_0_read_sensor(smu, sensor, data, size);
873         }
874         mutex_unlock(&smu->sensor_lock);
875
876         return ret;
877 }
878
879 static const struct pptable_funcs renoir_ppt_funcs = {
880         .get_smu_msg_index = renoir_get_smu_msg_index,
881         .get_smu_clk_index = renoir_get_smu_clk_index,
882         .get_smu_table_index = renoir_get_smu_table_index,
883         .tables_init = renoir_tables_init,
884         .set_power_state = NULL,
885         .get_dpm_clk_limited = renoir_get_dpm_clk_limited,
886         .print_clk_levels = renoir_print_clk_levels,
887         .get_current_power_state = renoir_get_current_power_state,
888         .dpm_set_uvd_enable = renoir_dpm_set_uvd_enable,
889         .dpm_set_jpeg_enable = renoir_dpm_set_jpeg_enable,
890         .get_current_clk_freq_by_table = renoir_get_current_clk_freq_by_table,
891         .force_dpm_limit_value = renoir_force_dpm_limit_value,
892         .unforce_dpm_levels = renoir_unforce_dpm_levels,
893         .get_workload_type = renoir_get_workload_type,
894         .get_profiling_clk_mask = renoir_get_profiling_clk_mask,
895         .force_clk_levels = renoir_force_clk_levels,
896         .set_power_profile_mode = renoir_set_power_profile_mode,
897         .set_performance_level = renoir_set_performance_level,
898         .get_dpm_clock_table = renoir_get_dpm_clock_table,
899         .set_watermarks_table = renoir_set_watermarks_table,
900         .get_power_profile_mode = renoir_get_power_profile_mode,
901         .read_sensor = renoir_read_sensor,
902         .check_fw_status = smu_v12_0_check_fw_status,
903         .check_fw_version = smu_v12_0_check_fw_version,
904         .powergate_sdma = smu_v12_0_powergate_sdma,
905         .powergate_vcn = smu_v12_0_powergate_vcn,
906         .powergate_jpeg = smu_v12_0_powergate_jpeg,
907         .send_smc_msg_with_param = smu_v12_0_send_msg_with_param,
908         .read_smc_arg = smu_v12_0_read_arg,
909         .set_gfx_cgpg = smu_v12_0_set_gfx_cgpg,
910         .gfx_off_control = smu_v12_0_gfx_off_control,
911         .init_smc_tables = smu_v12_0_init_smc_tables,
912         .fini_smc_tables = smu_v12_0_fini_smc_tables,
913         .populate_smc_tables = smu_v12_0_populate_smc_tables,
914         .get_enabled_mask = smu_v12_0_get_enabled_mask,
915         .get_current_clk_freq = smu_v12_0_get_current_clk_freq,
916         .get_dpm_ultimate_freq = smu_v12_0_get_dpm_ultimate_freq,
917         .mode2_reset = smu_v12_0_mode2_reset,
918         .set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range,
919 };
920
921 void renoir_set_ppt_funcs(struct smu_context *smu)
922 {
923         smu->ppt_funcs = &renoir_ppt_funcs;
924         smu->smc_if_version = SMU12_DRIVER_IF_VERSION;
925         smu->is_apu = true;
926 }