GNU Linux-libre 4.14.254-gnu1
[releases.git] / drivers / gpu / drm / amd / powerplay / smumgr / smumgr.c
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23
24 #include <linux/delay.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/types.h>
29 #include <drm/amdgpu_drm.h>
30 #include "pp_instance.h"
31 #include "smumgr.h"
32 #include "cgs_common.h"
33
34 /*(DEBLOBBED)*/
35
36 int smum_early_init(struct pp_instance *handle)
37 {
38         struct pp_smumgr *smumgr;
39
40         if (handle == NULL)
41                 return -EINVAL;
42
43         smumgr = kzalloc(sizeof(struct pp_smumgr), GFP_KERNEL);
44         if (smumgr == NULL)
45                 return -ENOMEM;
46
47         smumgr->device = handle->device;
48         smumgr->chip_family = handle->chip_family;
49         smumgr->chip_id = handle->chip_id;
50         smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
51         smumgr->reload_fw = 1;
52         handle->smu_mgr = smumgr;
53
54         switch (smumgr->chip_family) {
55         case AMDGPU_FAMILY_CZ:
56                 smumgr->smumgr_funcs = &cz_smu_funcs;
57                 break;
58         case AMDGPU_FAMILY_VI:
59                 switch (smumgr->chip_id) {
60                 case CHIP_TOPAZ:
61                         smumgr->smumgr_funcs = &iceland_smu_funcs;
62                         break;
63                 case CHIP_TONGA:
64                         smumgr->smumgr_funcs = &tonga_smu_funcs;
65                         break;
66                 case CHIP_FIJI:
67                         smumgr->smumgr_funcs = &fiji_smu_funcs;
68                         break;
69                 case CHIP_POLARIS11:
70                 case CHIP_POLARIS10:
71                 case CHIP_POLARIS12:
72                         smumgr->smumgr_funcs = &polaris10_smu_funcs;
73                         break;
74                 default:
75                         return -EINVAL;
76                 }
77                 break;
78         case AMDGPU_FAMILY_AI:
79                 switch (smumgr->chip_id) {
80                 case CHIP_VEGA10:
81                         smumgr->smumgr_funcs = &vega10_smu_funcs;
82                         break;
83                 default:
84                         return -EINVAL;
85                 }
86                 break;
87         case AMDGPU_FAMILY_RV:
88                 switch (smumgr->chip_id) {
89                 case CHIP_RAVEN:
90                         smumgr->smumgr_funcs = &rv_smu_funcs;
91                         break;
92                 default:
93                         return -EINVAL;
94                 }
95                 break;
96         default:
97                 kfree(smumgr);
98                 return -EINVAL;
99         }
100
101         return 0;
102 }
103
104 int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
105                 void *input, void *output, void *storage, int result)
106 {
107         if (NULL != hwmgr->smumgr->smumgr_funcs->thermal_avfs_enable)
108                 return hwmgr->smumgr->smumgr_funcs->thermal_avfs_enable(hwmgr);
109
110         return 0;
111 }
112
113 int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
114                 void *input, void *output, void *storage, int result)
115 {
116         if (NULL != hwmgr->smumgr->smumgr_funcs->thermal_setup_fan_table)
117                 return hwmgr->smumgr->smumgr_funcs->thermal_setup_fan_table(hwmgr);
118
119         return 0;
120 }
121
122 int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr)
123 {
124
125         if (NULL != hwmgr->smumgr->smumgr_funcs->update_sclk_threshold)
126                 return hwmgr->smumgr->smumgr_funcs->update_sclk_threshold(hwmgr);
127
128         return 0;
129 }
130
131 int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
132 {
133
134         if (NULL != hwmgr->smumgr->smumgr_funcs->update_smc_table)
135                 return hwmgr->smumgr->smumgr_funcs->update_smc_table(hwmgr, type);
136
137         return 0;
138 }
139
140 uint32_t smum_get_offsetof(struct pp_smumgr *smumgr, uint32_t type, uint32_t member)
141 {
142         if (NULL != smumgr->smumgr_funcs->get_offsetof)
143                 return smumgr->smumgr_funcs->get_offsetof(type, member);
144
145         return 0;
146 }
147
148 int smum_process_firmware_header(struct pp_hwmgr *hwmgr)
149 {
150         if (NULL != hwmgr->smumgr->smumgr_funcs->process_firmware_header)
151                 return hwmgr->smumgr->smumgr_funcs->process_firmware_header(hwmgr);
152         return 0;
153 }
154
155 int smum_get_argument(struct pp_smumgr *smumgr)
156 {
157         if (NULL != smumgr->smumgr_funcs->get_argument)
158                 return smumgr->smumgr_funcs->get_argument(smumgr);
159
160         return 0;
161 }
162
163 uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value)
164 {
165         if (NULL != smumgr->smumgr_funcs->get_mac_definition)
166                 return smumgr->smumgr_funcs->get_mac_definition(value);
167
168         return 0;
169 }
170
171 int smum_download_powerplay_table(struct pp_smumgr *smumgr,
172                                                                 void **table)
173 {
174         if (NULL != smumgr->smumgr_funcs->download_pptable_settings)
175                 return smumgr->smumgr_funcs->download_pptable_settings(smumgr,
176                                                                         table);
177         return 0;
178 }
179
180 int smum_upload_powerplay_table(struct pp_smumgr *smumgr)
181 {
182         if (NULL != smumgr->smumgr_funcs->upload_pptable_settings)
183                 return smumgr->smumgr_funcs->upload_pptable_settings(smumgr);
184
185         return 0;
186 }
187
188 int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
189 {
190         if (smumgr == NULL || smumgr->smumgr_funcs->send_msg_to_smc == NULL)
191                 return -EINVAL;
192
193         return smumgr->smumgr_funcs->send_msg_to_smc(smumgr, msg);
194 }
195
196 int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
197                                         uint16_t msg, uint32_t parameter)
198 {
199         if (smumgr == NULL ||
200                 smumgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL)
201                 return -EINVAL;
202         return smumgr->smumgr_funcs->send_msg_to_smc_with_parameter(
203                                                 smumgr, msg, parameter);
204 }
205
206 /*
207  * Returns once the part of the register indicated by the mask has
208  * reached the given value.
209  */
210 int smum_wait_on_register(struct pp_smumgr *smumgr,
211                                 uint32_t index,
212                                 uint32_t value, uint32_t mask)
213 {
214         uint32_t i;
215         uint32_t cur_value;
216
217         if (smumgr == NULL || smumgr->device == NULL)
218                 return -EINVAL;
219
220         for (i = 0; i < smumgr->usec_timeout; i++) {
221                 cur_value = cgs_read_register(smumgr->device, index);
222                 if ((cur_value & mask) == (value & mask))
223                         break;
224                 udelay(1);
225         }
226
227         /* timeout means wrong logic*/
228         if (i == smumgr->usec_timeout)
229                 return -1;
230
231         return 0;
232 }
233
234 int smum_wait_for_register_unequal(struct pp_smumgr *smumgr,
235                                         uint32_t index,
236                                         uint32_t value, uint32_t mask)
237 {
238         uint32_t i;
239         uint32_t cur_value;
240
241         if (smumgr == NULL)
242                 return -EINVAL;
243
244         for (i = 0; i < smumgr->usec_timeout; i++) {
245                 cur_value = cgs_read_register(smumgr->device,
246                                                                         index);
247                 if ((cur_value & mask) != (value & mask))
248                         break;
249                 udelay(1);
250         }
251
252         /* timeout means wrong logic */
253         if (i == smumgr->usec_timeout)
254                 return -1;
255
256         return 0;
257 }
258
259
260 /*
261  * Returns once the part of the register indicated by the mask
262  * has reached the given value.The indirect space is described by
263  * giving the memory-mapped index of the indirect index register.
264  */
265 int smum_wait_on_indirect_register(struct pp_smumgr *smumgr,
266                                         uint32_t indirect_port,
267                                         uint32_t index,
268                                         uint32_t value,
269                                         uint32_t mask)
270 {
271         if (smumgr == NULL || smumgr->device == NULL)
272                 return -EINVAL;
273
274         cgs_write_register(smumgr->device, indirect_port, index);
275         return smum_wait_on_register(smumgr, indirect_port + 1,
276                                                 mask, value);
277 }
278
279 void smum_wait_for_indirect_register_unequal(
280                                                 struct pp_smumgr *smumgr,
281                                                 uint32_t indirect_port,
282                                                 uint32_t index,
283                                                 uint32_t value,
284                                                 uint32_t mask)
285 {
286         if (smumgr == NULL || smumgr->device == NULL)
287                 return;
288         cgs_write_register(smumgr->device, indirect_port, index);
289         smum_wait_for_register_unequal(smumgr, indirect_port + 1,
290                                                 value, mask);
291 }
292
293 int smu_allocate_memory(void *device, uint32_t size,
294                          enum cgs_gpu_mem_type type,
295                          uint32_t byte_align, uint64_t *mc_addr,
296                          void **kptr, void *handle)
297 {
298         int ret = 0;
299         cgs_handle_t cgs_handle;
300
301         if (device == NULL || handle == NULL ||
302             mc_addr == NULL || kptr == NULL)
303                 return -EINVAL;
304
305         ret = cgs_alloc_gpu_mem(device, type, size, byte_align,
306                                 0, 0, (cgs_handle_t *)handle);
307         if (ret)
308                 return -ENOMEM;
309
310         cgs_handle = *(cgs_handle_t *)handle;
311
312         ret = cgs_gmap_gpu_mem(device, cgs_handle, mc_addr);
313         if (ret)
314                 goto error_gmap;
315
316         ret = cgs_kmap_gpu_mem(device, cgs_handle, kptr);
317         if (ret)
318                 goto error_kmap;
319
320         return 0;
321
322 error_kmap:
323         cgs_gunmap_gpu_mem(device, cgs_handle);
324
325 error_gmap:
326         cgs_free_gpu_mem(device, cgs_handle);
327         return ret;
328 }
329
330 int smu_free_memory(void *device, void *handle)
331 {
332         cgs_handle_t cgs_handle = (cgs_handle_t)handle;
333
334         if (device == NULL || handle == NULL)
335                 return -EINVAL;
336
337         cgs_kunmap_gpu_mem(device, cgs_handle);
338         cgs_gunmap_gpu_mem(device, cgs_handle);
339         cgs_free_gpu_mem(device, cgs_handle);
340
341         return 0;
342 }
343
344 int smum_init_smc_table(struct pp_hwmgr *hwmgr)
345 {
346         if (NULL != hwmgr->smumgr->smumgr_funcs->init_smc_table)
347                 return hwmgr->smumgr->smumgr_funcs->init_smc_table(hwmgr);
348
349         return 0;
350 }
351
352 int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
353 {
354         if (NULL != hwmgr->smumgr->smumgr_funcs->populate_all_graphic_levels)
355                 return hwmgr->smumgr->smumgr_funcs->populate_all_graphic_levels(hwmgr);
356
357         return 0;
358 }
359
360 int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
361 {
362         if (NULL != hwmgr->smumgr->smumgr_funcs->populate_all_memory_levels)
363                 return hwmgr->smumgr->smumgr_funcs->populate_all_memory_levels(hwmgr);
364
365         return 0;
366 }
367
368 /*this interface is needed by island ci/vi */
369 int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
370 {
371         if (NULL != hwmgr->smumgr->smumgr_funcs->initialize_mc_reg_table)
372                 return hwmgr->smumgr->smumgr_funcs->initialize_mc_reg_table(hwmgr);
373
374         return 0;
375 }
376
377 bool smum_is_dpm_running(struct pp_hwmgr *hwmgr)
378 {
379         if (NULL != hwmgr->smumgr->smumgr_funcs->is_dpm_running)
380                 return hwmgr->smumgr->smumgr_funcs->is_dpm_running(hwmgr);
381
382         return true;
383 }
384
385 int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
386                 struct amd_pp_profile *request)
387 {
388         if (hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels)
389                 return hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels(
390                                 hwmgr, request);
391
392         return 0;
393 }
394
395 bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr)
396 {
397         if (smumgr->smumgr_funcs->is_hw_avfs_present)
398                 return smumgr->smumgr_funcs->is_hw_avfs_present(smumgr);
399
400         return false;
401 }