Merge remote-tracking branches 'asoc/topic/rockchip', 'asoc/topic/rt5514', 'asoc...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / powerplay / amd_powerplay.c
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "pp_debug.h"
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/gfp.h>
27 #include <linux/slab.h>
28 #include "amd_shared.h"
29 #include "amd_powerplay.h"
30 #include "pp_instance.h"
31 #include "power_state.h"
32 #include "eventmanager.h"
33
34
35 static inline int pp_check(struct pp_instance *handle)
36 {
37         if (handle == NULL || handle->pp_valid != PP_VALID)
38                 return -EINVAL;
39
40         if (handle->smu_mgr == NULL || handle->smu_mgr->smumgr_funcs == NULL)
41                 return -EINVAL;
42
43         if (handle->pm_en == 0)
44                 return PP_DPM_DISABLED;
45
46         if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL
47                 || handle->eventmgr == NULL)
48                 return PP_DPM_DISABLED;
49
50         return 0;
51 }
52
53 static int pp_early_init(void *handle)
54 {
55         int ret;
56         struct pp_instance *pp_handle = (struct pp_instance *)handle;
57
58         ret = smum_early_init(pp_handle);
59         if (ret)
60                 return ret;
61
62         if ((pp_handle->pm_en == 0)
63                 || cgs_is_virtualization_enabled(pp_handle->device))
64                 return PP_DPM_DISABLED;
65
66         ret = hwmgr_early_init(pp_handle);
67         if (ret) {
68                 pp_handle->pm_en = 0;
69                 return PP_DPM_DISABLED;
70         }
71
72         ret = eventmgr_early_init(pp_handle);
73         if (ret) {
74                 kfree(pp_handle->hwmgr);
75                 pp_handle->hwmgr = NULL;
76                 pp_handle->pm_en = 0;
77                 return PP_DPM_DISABLED;
78         }
79
80         return 0;
81 }
82
83 static int pp_sw_init(void *handle)
84 {
85         struct pp_smumgr *smumgr;
86         int ret = 0;
87         struct pp_instance *pp_handle = (struct pp_instance *)handle;
88
89         ret = pp_check(pp_handle);
90
91         if (ret == 0 || ret == PP_DPM_DISABLED) {
92                 smumgr = pp_handle->smu_mgr;
93
94                 if (smumgr->smumgr_funcs->smu_init == NULL)
95                         return -EINVAL;
96
97                 ret = smumgr->smumgr_funcs->smu_init(smumgr);
98
99                 pr_info("amdgpu: powerplay sw initialized\n");
100         }
101         return ret;
102 }
103
104 static int pp_sw_fini(void *handle)
105 {
106         struct pp_smumgr *smumgr;
107         int ret = 0;
108         struct pp_instance *pp_handle = (struct pp_instance *)handle;
109
110         ret = pp_check(pp_handle);
111         if (ret == 0 || ret == PP_DPM_DISABLED) {
112                 smumgr = pp_handle->smu_mgr;
113
114                 if (smumgr->smumgr_funcs->smu_fini == NULL)
115                         return -EINVAL;
116
117                 ret = smumgr->smumgr_funcs->smu_fini(smumgr);
118         }
119         return ret;
120 }
121
122 static int pp_hw_init(void *handle)
123 {
124         struct pp_smumgr *smumgr;
125         struct pp_eventmgr *eventmgr;
126         int ret = 0;
127         struct pp_instance *pp_handle = (struct pp_instance *)handle;
128
129         ret = pp_check(pp_handle);
130
131         if (ret == 0 || ret == PP_DPM_DISABLED) {
132                 smumgr = pp_handle->smu_mgr;
133
134                 if (smumgr->smumgr_funcs->start_smu == NULL)
135                         return -EINVAL;
136
137                 if(smumgr->smumgr_funcs->start_smu(smumgr)) {
138                         pr_err("smc start failed\n");
139                         smumgr->smumgr_funcs->smu_fini(smumgr);
140                         return -EINVAL;;
141                 }
142                 if (ret == PP_DPM_DISABLED)
143                         return PP_DPM_DISABLED;
144         }
145
146         ret = hwmgr_hw_init(pp_handle);
147         if (ret)
148                 goto err;
149
150         eventmgr = pp_handle->eventmgr;
151         if (eventmgr->pp_eventmgr_init == NULL ||
152                 eventmgr->pp_eventmgr_init(eventmgr))
153                 goto err;
154
155         return 0;
156 err:
157         pp_handle->pm_en = 0;
158         kfree(pp_handle->eventmgr);
159         kfree(pp_handle->hwmgr);
160         pp_handle->hwmgr = NULL;
161         pp_handle->eventmgr = NULL;
162         return PP_DPM_DISABLED;
163 }
164
165 static int pp_hw_fini(void *handle)
166 {
167         struct pp_eventmgr *eventmgr;
168         struct pp_instance *pp_handle = (struct pp_instance *)handle;
169         int ret = 0;
170
171         ret = pp_check(pp_handle);
172
173         if (ret == 0) {
174                 eventmgr = pp_handle->eventmgr;
175
176                 if (eventmgr->pp_eventmgr_fini != NULL)
177                         eventmgr->pp_eventmgr_fini(eventmgr);
178
179                 hwmgr_hw_fini(pp_handle);
180         }
181         return 0;
182 }
183
184 static bool pp_is_idle(void *handle)
185 {
186         return false;
187 }
188
189 static int pp_wait_for_idle(void *handle)
190 {
191         return 0;
192 }
193
194 static int pp_sw_reset(void *handle)
195 {
196         return 0;
197 }
198
199
200 int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
201 {
202         struct pp_hwmgr  *hwmgr;
203         struct pp_instance *pp_handle = (struct pp_instance *)handle;
204         int ret = 0;
205
206         ret = pp_check(pp_handle);
207
208         if (ret != 0)
209                 return ret;
210
211         hwmgr = pp_handle->hwmgr;
212
213         if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
214                 pr_info("%s was not implemented.\n", __func__);
215                 return 0;
216         }
217
218         return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
219 }
220
221 static int pp_set_powergating_state(void *handle,
222                                     enum amd_powergating_state state)
223 {
224         struct pp_hwmgr  *hwmgr;
225         struct pp_instance *pp_handle = (struct pp_instance *)handle;
226         int ret = 0;
227
228         ret = pp_check(pp_handle);
229
230         if (ret != 0)
231                 return ret;
232
233         hwmgr = pp_handle->hwmgr;
234
235         if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
236                 pr_info("%s was not implemented.\n", __func__);
237                 return 0;
238         }
239
240         /* Enable/disable GFX per cu powergating through SMU */
241         return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
242                         state == AMD_PG_STATE_GATE ? true : false);
243 }
244
245 static int pp_suspend(void *handle)
246 {
247         struct pp_eventmgr *eventmgr;
248         struct pem_event_data event_data = { {0} };
249         struct pp_instance *pp_handle = (struct pp_instance *)handle;
250         int ret = 0;
251
252         ret = pp_check(pp_handle);
253
254         if (ret != 0)
255                 return ret;
256
257         eventmgr = pp_handle->eventmgr;
258         pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
259
260         return 0;
261 }
262
263 static int pp_resume(void *handle)
264 {
265         struct pp_eventmgr *eventmgr;
266         struct pem_event_data event_data = { {0} };
267         struct pp_smumgr *smumgr;
268         int ret, ret1;
269         struct pp_instance *pp_handle = (struct pp_instance *)handle;
270
271         ret1 = pp_check(pp_handle);
272
273         if (ret1 != 0 && ret1 != PP_DPM_DISABLED)
274                 return ret1;
275
276         smumgr = pp_handle->smu_mgr;
277
278         if (smumgr->smumgr_funcs->start_smu == NULL)
279                 return -EINVAL;
280
281         ret = smumgr->smumgr_funcs->start_smu(smumgr);
282         if (ret) {
283                 pr_err("smc start failed\n");
284                 smumgr->smumgr_funcs->smu_fini(smumgr);
285                 return ret;
286         }
287
288         if (ret1 == PP_DPM_DISABLED)
289                 return ret1;
290
291         eventmgr = pp_handle->eventmgr;
292
293         pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
294
295         return 0;
296 }
297
298 const struct amd_ip_funcs pp_ip_funcs = {
299         .name = "powerplay",
300         .early_init = pp_early_init,
301         .late_init = NULL,
302         .sw_init = pp_sw_init,
303         .sw_fini = pp_sw_fini,
304         .hw_init = pp_hw_init,
305         .hw_fini = pp_hw_fini,
306         .suspend = pp_suspend,
307         .resume = pp_resume,
308         .is_idle = pp_is_idle,
309         .wait_for_idle = pp_wait_for_idle,
310         .soft_reset = pp_sw_reset,
311         .set_clockgating_state = NULL,
312         .set_powergating_state = pp_set_powergating_state,
313 };
314
315 static int pp_dpm_load_fw(void *handle)
316 {
317         return 0;
318 }
319
320 static int pp_dpm_fw_loading_complete(void *handle)
321 {
322         return 0;
323 }
324
325 static int pp_dpm_force_performance_level(void *handle,
326                                         enum amd_dpm_forced_level level)
327 {
328         struct pp_hwmgr  *hwmgr;
329         struct pp_instance *pp_handle = (struct pp_instance *)handle;
330         int ret = 0;
331
332         ret = pp_check(pp_handle);
333
334         if (ret != 0)
335                 return ret;
336
337         hwmgr = pp_handle->hwmgr;
338
339         if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
340                 pr_info("%s was not implemented.\n", __func__);
341                 return 0;
342         }
343
344         hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
345
346         return 0;
347 }
348
349 static enum amd_dpm_forced_level pp_dpm_get_performance_level(
350                                                                 void *handle)
351 {
352         struct pp_hwmgr  *hwmgr;
353         struct pp_instance *pp_handle = (struct pp_instance *)handle;
354         int ret = 0;
355
356         ret = pp_check(pp_handle);
357
358         if (ret != 0)
359                 return ret;
360
361         hwmgr = pp_handle->hwmgr;
362
363         return hwmgr->dpm_level;
364 }
365
366 static int pp_dpm_get_sclk(void *handle, bool low)
367 {
368         struct pp_hwmgr  *hwmgr;
369         struct pp_instance *pp_handle = (struct pp_instance *)handle;
370         int ret = 0;
371
372         ret = pp_check(pp_handle);
373
374         if (ret != 0)
375                 return ret;
376
377         hwmgr = pp_handle->hwmgr;
378
379         if (hwmgr->hwmgr_func->get_sclk == NULL) {
380                 pr_info("%s was not implemented.\n", __func__);
381                 return 0;
382         }
383
384         return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
385 }
386
387 static int pp_dpm_get_mclk(void *handle, bool low)
388 {
389         struct pp_hwmgr  *hwmgr;
390         struct pp_instance *pp_handle = (struct pp_instance *)handle;
391         int ret = 0;
392
393         ret = pp_check(pp_handle);
394
395         if (ret != 0)
396                 return ret;
397
398         hwmgr = pp_handle->hwmgr;
399
400         if (hwmgr->hwmgr_func->get_mclk == NULL) {
401                 pr_info("%s was not implemented.\n", __func__);
402                 return 0;
403         }
404
405         return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
406 }
407
408 static int pp_dpm_powergate_vce(void *handle, bool gate)
409 {
410         struct pp_hwmgr  *hwmgr;
411         struct pp_instance *pp_handle = (struct pp_instance *)handle;
412         int ret = 0;
413
414         ret = pp_check(pp_handle);
415
416         if (ret != 0)
417                 return ret;
418
419         hwmgr = pp_handle->hwmgr;
420
421         if (hwmgr->hwmgr_func->powergate_vce == NULL) {
422                 pr_info("%s was not implemented.\n", __func__);
423                 return 0;
424         }
425
426         return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
427 }
428
429 static int pp_dpm_powergate_uvd(void *handle, bool gate)
430 {
431         struct pp_hwmgr  *hwmgr;
432         struct pp_instance *pp_handle = (struct pp_instance *)handle;
433         int ret = 0;
434
435         ret = pp_check(pp_handle);
436
437         if (ret != 0)
438                 return ret;
439
440         hwmgr = pp_handle->hwmgr;
441
442         if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
443                 pr_info("%s was not implemented.\n", __func__);
444                 return 0;
445         }
446
447         return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
448 }
449
450 static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
451 {
452         switch (state) {
453         case POWER_STATE_TYPE_BATTERY:
454                 return PP_StateUILabel_Battery;
455         case POWER_STATE_TYPE_BALANCED:
456                 return PP_StateUILabel_Balanced;
457         case POWER_STATE_TYPE_PERFORMANCE:
458                 return PP_StateUILabel_Performance;
459         default:
460                 return PP_StateUILabel_None;
461         }
462 }
463
464 static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
465                 void *input, void *output)
466 {
467         int ret = 0;
468         struct pem_event_data data = { {0} };
469         struct pp_instance *pp_handle = (struct pp_instance *)handle;
470
471         ret = pp_check(pp_handle);
472
473         if (ret != 0)
474                 return ret;
475
476         switch (event_id) {
477         case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
478                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
479                 break;
480         case AMD_PP_EVENT_ENABLE_USER_STATE:
481         {
482                 enum amd_pm_state_type  ps;
483
484                 if (input == NULL)
485                         return -EINVAL;
486                 ps = *(unsigned long *)input;
487
488                 data.requested_ui_label = power_state_convert(ps);
489                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
490                 break;
491         }
492         case AMD_PP_EVENT_COMPLETE_INIT:
493                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
494                 break;
495         case AMD_PP_EVENT_READJUST_POWER_STATE:
496                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
497                 break;
498         default:
499                 break;
500         }
501         return ret;
502 }
503
504 static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
505 {
506         struct pp_hwmgr *hwmgr;
507         struct pp_power_state *state;
508         struct pp_instance *pp_handle = (struct pp_instance *)handle;
509         int ret = 0;
510
511         ret = pp_check(pp_handle);
512
513         if (ret != 0)
514                 return ret;
515
516         hwmgr = pp_handle->hwmgr;
517
518         if (hwmgr->current_ps == NULL)
519                 return -EINVAL;
520
521         state = hwmgr->current_ps;
522
523         switch (state->classification.ui_label) {
524         case PP_StateUILabel_Battery:
525                 return POWER_STATE_TYPE_BATTERY;
526         case PP_StateUILabel_Balanced:
527                 return POWER_STATE_TYPE_BALANCED;
528         case PP_StateUILabel_Performance:
529                 return POWER_STATE_TYPE_PERFORMANCE;
530         default:
531                 if (state->classification.flags & PP_StateClassificationFlag_Boot)
532                         return  POWER_STATE_TYPE_INTERNAL_BOOT;
533                 else
534                         return POWER_STATE_TYPE_DEFAULT;
535         }
536 }
537
538 static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
539 {
540         struct pp_hwmgr  *hwmgr;
541         struct pp_instance *pp_handle = (struct pp_instance *)handle;
542         int ret = 0;
543
544         ret = pp_check(pp_handle);
545
546         if (ret != 0)
547                 return ret;
548
549         hwmgr = pp_handle->hwmgr;
550
551         if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
552                 pr_info("%s was not implemented.\n", __func__);
553                 return 0;
554         }
555
556         return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
557 }
558
559 static int pp_dpm_get_fan_control_mode(void *handle)
560 {
561         struct pp_hwmgr  *hwmgr;
562         struct pp_instance *pp_handle = (struct pp_instance *)handle;
563         int ret = 0;
564
565         ret = pp_check(pp_handle);
566
567         if (ret != 0)
568                 return ret;
569
570         hwmgr = pp_handle->hwmgr;
571
572         if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
573                 pr_info("%s was not implemented.\n", __func__);
574                 return 0;
575         }
576
577         return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
578 }
579
580 static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
581 {
582         struct pp_hwmgr  *hwmgr;
583         struct pp_instance *pp_handle = (struct pp_instance *)handle;
584         int ret = 0;
585
586         ret = pp_check(pp_handle);
587
588         if (ret != 0)
589                 return ret;
590
591         hwmgr = pp_handle->hwmgr;
592
593         if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
594                 pr_info("%s was not implemented.\n", __func__);
595                 return 0;
596         }
597
598         return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
599 }
600
601 static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
602 {
603         struct pp_hwmgr  *hwmgr;
604         struct pp_instance *pp_handle = (struct pp_instance *)handle;
605         int ret = 0;
606
607         ret = pp_check(pp_handle);
608
609         if (ret != 0)
610                 return ret;
611
612         hwmgr = pp_handle->hwmgr;
613
614         if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
615                 pr_info("%s was not implemented.\n", __func__);
616                 return 0;
617         }
618
619         return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
620 }
621
622 static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
623 {
624         struct pp_hwmgr *hwmgr;
625         struct pp_instance *pp_handle = (struct pp_instance *)handle;
626         int ret = 0;
627
628         ret = pp_check(pp_handle);
629
630         if (ret != 0)
631                 return ret;
632
633         hwmgr = pp_handle->hwmgr;
634
635         if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
636                 return -EINVAL;
637
638         return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
639 }
640
641 static int pp_dpm_get_temperature(void *handle)
642 {
643         struct pp_hwmgr  *hwmgr;
644         struct pp_instance *pp_handle = (struct pp_instance *)handle;
645         int ret = 0;
646
647         ret = pp_check(pp_handle);
648
649         if (ret != 0)
650                 return ret;
651
652         hwmgr = pp_handle->hwmgr;
653
654         if (hwmgr->hwmgr_func->get_temperature == NULL) {
655                 pr_info("%s was not implemented.\n", __func__);
656                 return 0;
657         }
658
659         return hwmgr->hwmgr_func->get_temperature(hwmgr);
660 }
661
662 static int pp_dpm_get_pp_num_states(void *handle,
663                 struct pp_states_info *data)
664 {
665         struct pp_hwmgr *hwmgr;
666         int i;
667         struct pp_instance *pp_handle = (struct pp_instance *)handle;
668         int ret = 0;
669
670         ret = pp_check(pp_handle);
671
672         if (ret != 0)
673                 return ret;
674
675         hwmgr = pp_handle->hwmgr;
676
677         if (hwmgr->ps == NULL)
678                 return -EINVAL;
679
680         data->nums = hwmgr->num_ps;
681
682         for (i = 0; i < hwmgr->num_ps; i++) {
683                 struct pp_power_state *state = (struct pp_power_state *)
684                                 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
685                 switch (state->classification.ui_label) {
686                 case PP_StateUILabel_Battery:
687                         data->states[i] = POWER_STATE_TYPE_BATTERY;
688                         break;
689                 case PP_StateUILabel_Balanced:
690                         data->states[i] = POWER_STATE_TYPE_BALANCED;
691                         break;
692                 case PP_StateUILabel_Performance:
693                         data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
694                         break;
695                 default:
696                         if (state->classification.flags & PP_StateClassificationFlag_Boot)
697                                 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
698                         else
699                                 data->states[i] = POWER_STATE_TYPE_DEFAULT;
700                 }
701         }
702
703         return 0;
704 }
705
706 static int pp_dpm_get_pp_table(void *handle, char **table)
707 {
708         struct pp_hwmgr *hwmgr;
709         struct pp_instance *pp_handle = (struct pp_instance *)handle;
710         int ret = 0;
711
712         ret = pp_check(pp_handle);
713
714         if (ret != 0)
715                 return ret;
716
717         hwmgr = pp_handle->hwmgr;
718
719         if (!hwmgr->soft_pp_table)
720                 return -EINVAL;
721
722         *table = (char *)hwmgr->soft_pp_table;
723
724         return hwmgr->soft_pp_table_size;
725 }
726
727 static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
728 {
729         struct pp_hwmgr *hwmgr;
730         struct pp_instance *pp_handle = (struct pp_instance *)handle;
731         int ret = 0;
732
733         ret = pp_check(pp_handle);
734
735         if (ret != 0)
736                 return ret;
737
738         hwmgr = pp_handle->hwmgr;
739
740         if (!hwmgr->hardcode_pp_table) {
741                 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
742                                                    hwmgr->soft_pp_table_size,
743                                                    GFP_KERNEL);
744
745                 if (!hwmgr->hardcode_pp_table)
746                         return -ENOMEM;
747         }
748
749         memcpy(hwmgr->hardcode_pp_table, buf, size);
750
751         hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
752
753         return amd_powerplay_reset(handle);
754 }
755
756 static int pp_dpm_force_clock_level(void *handle,
757                 enum pp_clock_type type, uint32_t mask)
758 {
759         struct pp_hwmgr *hwmgr;
760         struct pp_instance *pp_handle = (struct pp_instance *)handle;
761         int ret = 0;
762
763         ret = pp_check(pp_handle);
764
765         if (ret != 0)
766                 return ret;
767
768         hwmgr = pp_handle->hwmgr;
769
770         if (hwmgr->hwmgr_func->force_clock_level == NULL) {
771                 pr_info("%s was not implemented.\n", __func__);
772                 return 0;
773         }
774
775         return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
776 }
777
778 static int pp_dpm_print_clock_levels(void *handle,
779                 enum pp_clock_type type, char *buf)
780 {
781         struct pp_hwmgr *hwmgr;
782         struct pp_instance *pp_handle = (struct pp_instance *)handle;
783         int ret = 0;
784
785         ret = pp_check(pp_handle);
786
787         if (ret != 0)
788                 return ret;
789
790         hwmgr = pp_handle->hwmgr;
791
792         if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
793                 pr_info("%s was not implemented.\n", __func__);
794                 return 0;
795         }
796         return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
797 }
798
799 static int pp_dpm_get_sclk_od(void *handle)
800 {
801         struct pp_hwmgr *hwmgr;
802         struct pp_instance *pp_handle = (struct pp_instance *)handle;
803         int ret = 0;
804
805         ret = pp_check(pp_handle);
806
807         if (ret != 0)
808                 return ret;
809
810         hwmgr = pp_handle->hwmgr;
811
812         if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
813                 pr_info("%s was not implemented.\n", __func__);
814                 return 0;
815         }
816
817         return hwmgr->hwmgr_func->get_sclk_od(hwmgr);
818 }
819
820 static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
821 {
822         struct pp_hwmgr *hwmgr;
823         struct pp_instance *pp_handle = (struct pp_instance *)handle;
824         int ret = 0;
825
826         ret = pp_check(pp_handle);
827
828         if (ret != 0)
829                 return ret;
830
831         hwmgr = pp_handle->hwmgr;
832
833         if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
834                 pr_info("%s was not implemented.\n", __func__);
835                 return 0;
836         }
837
838         return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
839 }
840
841 static int pp_dpm_get_mclk_od(void *handle)
842 {
843         struct pp_hwmgr *hwmgr;
844         struct pp_instance *pp_handle = (struct pp_instance *)handle;
845         int ret = 0;
846
847         ret = pp_check(pp_handle);
848
849         if (ret != 0)
850                 return ret;
851
852         hwmgr = pp_handle->hwmgr;
853
854         if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
855                 pr_info("%s was not implemented.\n", __func__);
856                 return 0;
857         }
858
859         return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
860 }
861
862 static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
863 {
864         struct pp_hwmgr *hwmgr;
865         struct pp_instance *pp_handle = (struct pp_instance *)handle;
866         int ret = 0;
867
868         ret = pp_check(pp_handle);
869
870         if (ret != 0)
871                 return ret;
872
873         hwmgr = pp_handle->hwmgr;
874
875         if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
876                 pr_info("%s was not implemented.\n", __func__);
877                 return 0;
878         }
879
880         return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
881 }
882
883 static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value)
884 {
885         struct pp_hwmgr *hwmgr;
886         struct pp_instance *pp_handle = (struct pp_instance *)handle;
887         int ret = 0;
888
889         ret = pp_check(pp_handle);
890
891         if (ret != 0)
892                 return ret;
893
894         hwmgr = pp_handle->hwmgr;
895
896         if (hwmgr->hwmgr_func->read_sensor == NULL) {
897                 pr_info("%s was not implemented.\n", __func__);
898                 return 0;
899         }
900
901         return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value);
902 }
903
904 static struct amd_vce_state*
905 pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
906 {
907         struct pp_hwmgr *hwmgr;
908         struct pp_instance *pp_handle = (struct pp_instance *)handle;
909         int ret = 0;
910
911         ret = pp_check(pp_handle);
912
913         if (ret != 0)
914                 return NULL;
915
916         hwmgr = pp_handle->hwmgr;
917
918         if (hwmgr && idx < hwmgr->num_vce_state_tables)
919                 return &hwmgr->vce_states[idx];
920
921         return NULL;
922 }
923
924 const struct amd_powerplay_funcs pp_dpm_funcs = {
925         .get_temperature = pp_dpm_get_temperature,
926         .load_firmware = pp_dpm_load_fw,
927         .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
928         .force_performance_level = pp_dpm_force_performance_level,
929         .get_performance_level = pp_dpm_get_performance_level,
930         .get_current_power_state = pp_dpm_get_current_power_state,
931         .get_sclk = pp_dpm_get_sclk,
932         .get_mclk = pp_dpm_get_mclk,
933         .powergate_vce = pp_dpm_powergate_vce,
934         .powergate_uvd = pp_dpm_powergate_uvd,
935         .dispatch_tasks = pp_dpm_dispatch_tasks,
936         .set_fan_control_mode = pp_dpm_set_fan_control_mode,
937         .get_fan_control_mode = pp_dpm_get_fan_control_mode,
938         .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
939         .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
940         .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
941         .get_pp_num_states = pp_dpm_get_pp_num_states,
942         .get_pp_table = pp_dpm_get_pp_table,
943         .set_pp_table = pp_dpm_set_pp_table,
944         .force_clock_level = pp_dpm_force_clock_level,
945         .print_clock_levels = pp_dpm_print_clock_levels,
946         .get_sclk_od = pp_dpm_get_sclk_od,
947         .set_sclk_od = pp_dpm_set_sclk_od,
948         .get_mclk_od = pp_dpm_get_mclk_od,
949         .set_mclk_od = pp_dpm_set_mclk_od,
950         .read_sensor = pp_dpm_read_sensor,
951         .get_vce_clock_state = pp_dpm_get_vce_clock_state,
952 };
953
954 int amd_powerplay_create(struct amd_pp_init *pp_init,
955                                 void **handle)
956 {
957         struct pp_instance *instance;
958
959         if (pp_init == NULL || handle == NULL)
960                 return -EINVAL;
961
962         instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
963         if (instance == NULL)
964                 return -ENOMEM;
965
966         instance->pp_valid = PP_VALID;
967         instance->chip_family = pp_init->chip_family;
968         instance->chip_id = pp_init->chip_id;
969         instance->pm_en = pp_init->pm_en;
970         instance->feature_mask = pp_init->feature_mask;
971         instance->device = pp_init->device;
972         *handle = instance;
973
974         return 0;
975 }
976
977 int amd_powerplay_destroy(void *handle)
978 {
979         struct pp_instance *instance = (struct pp_instance *)handle;
980
981         if (instance->pm_en) {
982                 kfree(instance->eventmgr);
983                 kfree(instance->hwmgr);
984                 instance->hwmgr = NULL;
985                 instance->eventmgr = NULL;
986         }
987
988         kfree(instance->smu_mgr);
989         instance->smu_mgr = NULL;
990         kfree(instance);
991         instance = NULL;
992         return 0;
993 }
994
995 int amd_powerplay_reset(void *handle)
996 {
997         struct pp_instance *instance = (struct pp_instance *)handle;
998         struct pp_eventmgr *eventmgr;
999         struct pem_event_data event_data = { {0} };
1000         int ret;
1001
1002         if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1003                 return PP_DPM_DISABLED;
1004
1005         ret = pp_check(instance);
1006         if (ret != 0)
1007                 return ret;
1008
1009         ret = pp_hw_fini(handle);
1010         if (ret)
1011                 return ret;
1012
1013         ret = hwmgr_hw_init(instance);
1014         if (ret)
1015                 return PP_DPM_DISABLED;
1016
1017         eventmgr = instance->eventmgr;
1018
1019         if (eventmgr->pp_eventmgr_init == NULL)
1020                 return PP_DPM_DISABLED;
1021
1022         ret = eventmgr->pp_eventmgr_init(eventmgr);
1023         if (ret)
1024                 return ret;
1025
1026         return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
1027 }
1028
1029 /* export this function to DAL */
1030
1031 int amd_powerplay_display_configuration_change(void *handle,
1032         const struct amd_pp_display_configuration *display_config)
1033 {
1034         struct pp_hwmgr  *hwmgr;
1035         struct pp_instance *pp_handle = (struct pp_instance *)handle;
1036         int ret = 0;
1037
1038         ret = pp_check(pp_handle);
1039
1040         if (ret != 0)
1041                 return ret;
1042
1043         hwmgr = pp_handle->hwmgr;
1044
1045         phm_store_dal_configuration_data(hwmgr, display_config);
1046
1047         return 0;
1048 }
1049
1050 int amd_powerplay_get_display_power_level(void *handle,
1051                 struct amd_pp_simple_clock_info *output)
1052 {
1053         struct pp_hwmgr  *hwmgr;
1054         struct pp_instance *pp_handle = (struct pp_instance *)handle;
1055         int ret = 0;
1056
1057         ret = pp_check(pp_handle);
1058
1059         if (ret != 0)
1060                 return ret;
1061
1062         hwmgr = pp_handle->hwmgr;
1063
1064         if (output == NULL)
1065                 return -EINVAL;
1066
1067         return phm_get_dal_power_level(hwmgr, output);
1068 }
1069
1070 int amd_powerplay_get_current_clocks(void *handle,
1071                 struct amd_pp_clock_info *clocks)
1072 {
1073         struct amd_pp_simple_clock_info simple_clocks;
1074         struct pp_clock_info hw_clocks;
1075         struct pp_hwmgr  *hwmgr;
1076         struct pp_instance *pp_handle = (struct pp_instance *)handle;
1077         int ret = 0;
1078
1079         ret = pp_check(pp_handle);
1080
1081         if (ret != 0)
1082                 return ret;
1083
1084         hwmgr = pp_handle->hwmgr;
1085
1086         phm_get_dal_power_level(hwmgr, &simple_clocks);
1087
1088         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
1089                 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment))
1090                         PP_ASSERT_WITH_CODE(0, "Error in PHM_GetPowerContainmentClockInfo", return -1);
1091         } else {
1092                 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity))
1093                         PP_ASSERT_WITH_CODE(0, "Error in PHM_GetClockInfo", return -1);
1094         }
1095
1096         clocks->min_engine_clock = hw_clocks.min_eng_clk;
1097         clocks->max_engine_clock = hw_clocks.max_eng_clk;
1098         clocks->min_memory_clock = hw_clocks.min_mem_clk;
1099         clocks->max_memory_clock = hw_clocks.max_mem_clk;
1100         clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1101         clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1102
1103         clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1104         clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1105
1106         clocks->max_clocks_state = simple_clocks.level;
1107
1108         if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1109                 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1110                 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1111         }
1112
1113         return 0;
1114
1115 }
1116
1117 int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1118 {
1119         int result = -1;
1120         struct pp_hwmgr  *hwmgr;
1121         struct pp_instance *pp_handle = (struct pp_instance *)handle;
1122         int ret = 0;
1123
1124         ret = pp_check(pp_handle);
1125
1126         if (ret != 0)
1127                 return ret;
1128
1129         hwmgr = pp_handle->hwmgr;
1130
1131         if (clocks == NULL)
1132                 return -EINVAL;
1133
1134         result = phm_get_clock_by_type(hwmgr, type, clocks);
1135
1136         return result;
1137 }
1138
1139 int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1140                 struct amd_pp_simple_clock_info *clocks)
1141 {
1142         struct pp_hwmgr  *hwmgr;
1143         struct pp_instance *pp_handle = (struct pp_instance *)handle;
1144         int ret = 0;
1145
1146         ret = pp_check(pp_handle);
1147
1148         if (ret != 0)
1149                 return ret;
1150
1151         hwmgr = pp_handle->hwmgr;
1152
1153
1154         if (clocks == NULL)
1155                 return -EINVAL;
1156
1157         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1158                 ret = phm_get_max_high_clocks(hwmgr, clocks);
1159
1160         return ret;
1161 }
1162