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