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