]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/powerplay/amd_powerplay.c
Merge branch 'cec-defines' into for-linus
[linux.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 #define PP_CHECK(handle)                                                \
35         do {                                                            \
36                 if ((handle) == NULL || (handle)->pp_valid != PP_VALID) \
37                         return -EINVAL;                                 \
38         } while (0)
39
40 static int pp_early_init(void *handle)
41 {
42         return 0;
43 }
44
45 static int pp_sw_init(void *handle)
46 {
47         struct pp_instance *pp_handle;
48         struct pp_hwmgr  *hwmgr;
49         int ret = 0;
50
51         if (handle == NULL)
52                 return -EINVAL;
53
54         pp_handle = (struct pp_instance *)handle;
55         hwmgr = pp_handle->hwmgr;
56
57         if (hwmgr == NULL || hwmgr->pptable_func == NULL ||
58             hwmgr->hwmgr_func == NULL ||
59             hwmgr->pptable_func->pptable_init == NULL ||
60             hwmgr->hwmgr_func->backend_init == NULL)
61                 return -EINVAL;
62
63         ret = hwmgr->pptable_func->pptable_init(hwmgr);
64
65         if (ret == 0)
66                 ret = hwmgr->hwmgr_func->backend_init(hwmgr);
67
68         if (ret)
69                 printk("amdgpu: powerplay initialization failed\n");
70         else
71                 printk("amdgpu: powerplay initialized\n");
72
73         return ret;
74 }
75
76 static int pp_sw_fini(void *handle)
77 {
78         struct pp_instance *pp_handle;
79         struct pp_hwmgr  *hwmgr;
80         int ret = 0;
81
82         if (handle == NULL)
83                 return -EINVAL;
84
85         pp_handle = (struct pp_instance *)handle;
86         hwmgr = pp_handle->hwmgr;
87
88         if (hwmgr != NULL || hwmgr->hwmgr_func != NULL ||
89             hwmgr->hwmgr_func->backend_fini != NULL)
90                 ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
91
92         return ret;
93 }
94
95 static int pp_hw_init(void *handle)
96 {
97         struct pp_instance *pp_handle;
98         struct pp_smumgr *smumgr;
99         struct pp_eventmgr *eventmgr;
100         int ret = 0;
101
102         if (handle == NULL)
103                 return -EINVAL;
104
105         pp_handle = (struct pp_instance *)handle;
106         smumgr = pp_handle->smu_mgr;
107
108         if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
109                 smumgr->smumgr_funcs->smu_init == NULL ||
110                 smumgr->smumgr_funcs->start_smu == NULL)
111                 return -EINVAL;
112
113         ret = smumgr->smumgr_funcs->smu_init(smumgr);
114         if (ret) {
115                 printk(KERN_ERR "[ powerplay ] smc initialization failed\n");
116                 return ret;
117         }
118
119         ret = smumgr->smumgr_funcs->start_smu(smumgr);
120         if (ret) {
121                 printk(KERN_ERR "[ powerplay ] smc start failed\n");
122                 smumgr->smumgr_funcs->smu_fini(smumgr);
123                 return ret;
124         }
125
126         hw_init_power_state_table(pp_handle->hwmgr);
127         eventmgr = pp_handle->eventmgr;
128
129         if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
130                 return -EINVAL;
131
132         ret = eventmgr->pp_eventmgr_init(eventmgr);
133         return 0;
134 }
135
136 static int pp_hw_fini(void *handle)
137 {
138         struct pp_instance *pp_handle;
139         struct pp_smumgr *smumgr;
140         struct pp_eventmgr *eventmgr;
141
142         if (handle == NULL)
143                 return -EINVAL;
144
145         pp_handle = (struct pp_instance *)handle;
146         eventmgr = pp_handle->eventmgr;
147
148         if (eventmgr != NULL || eventmgr->pp_eventmgr_fini != NULL)
149                 eventmgr->pp_eventmgr_fini(eventmgr);
150
151         smumgr = pp_handle->smu_mgr;
152
153         if (smumgr != NULL || smumgr->smumgr_funcs != NULL ||
154                 smumgr->smumgr_funcs->smu_fini != NULL)
155                 smumgr->smumgr_funcs->smu_fini(smumgr);
156
157         return 0;
158 }
159
160 static bool pp_is_idle(void *handle)
161 {
162         return 0;
163 }
164
165 static int pp_wait_for_idle(void *handle)
166 {
167         return 0;
168 }
169
170 static int pp_sw_reset(void *handle)
171 {
172         return 0;
173 }
174
175 static void pp_print_status(void *handle)
176 {
177
178 }
179
180 static int pp_set_clockgating_state(void *handle,
181                                     enum amd_clockgating_state state)
182 {
183         return 0;
184 }
185
186 static int pp_set_powergating_state(void *handle,
187                                     enum amd_powergating_state state)
188 {
189         return 0;
190 }
191
192 static int pp_suspend(void *handle)
193 {
194         struct pp_instance *pp_handle;
195         struct pp_eventmgr *eventmgr;
196         struct pem_event_data event_data = { {0} };
197
198         if (handle == NULL)
199                 return -EINVAL;
200
201         pp_handle = (struct pp_instance *)handle;
202         eventmgr = pp_handle->eventmgr;
203         pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
204         return 0;
205 }
206
207 static int pp_resume(void *handle)
208 {
209         struct pp_instance *pp_handle;
210         struct pp_eventmgr *eventmgr;
211         struct pem_event_data event_data = { {0} };
212         struct pp_smumgr *smumgr;
213         int ret;
214
215         if (handle == NULL)
216                 return -EINVAL;
217
218         pp_handle = (struct pp_instance *)handle;
219         smumgr = pp_handle->smu_mgr;
220
221         if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
222                 smumgr->smumgr_funcs->start_smu == NULL)
223                 return -EINVAL;
224
225         ret = smumgr->smumgr_funcs->start_smu(smumgr);
226         if (ret) {
227                 printk(KERN_ERR "[ powerplay ] smc start failed\n");
228                 smumgr->smumgr_funcs->smu_fini(smumgr);
229                 return ret;
230         }
231
232         eventmgr = pp_handle->eventmgr;
233         pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
234
235         return 0;
236 }
237
238 const struct amd_ip_funcs pp_ip_funcs = {
239         .early_init = pp_early_init,
240         .late_init = NULL,
241         .sw_init = pp_sw_init,
242         .sw_fini = pp_sw_fini,
243         .hw_init = pp_hw_init,
244         .hw_fini = pp_hw_fini,
245         .suspend = pp_suspend,
246         .resume = pp_resume,
247         .is_idle = pp_is_idle,
248         .wait_for_idle = pp_wait_for_idle,
249         .soft_reset = pp_sw_reset,
250         .print_status = pp_print_status,
251         .set_clockgating_state = pp_set_clockgating_state,
252         .set_powergating_state = pp_set_powergating_state,
253 };
254
255 static int pp_dpm_load_fw(void *handle)
256 {
257         return 0;
258 }
259
260 static int pp_dpm_fw_loading_complete(void *handle)
261 {
262         return 0;
263 }
264
265 static int pp_dpm_force_performance_level(void *handle,
266                                         enum amd_dpm_forced_level level)
267 {
268         struct pp_instance *pp_handle;
269         struct pp_hwmgr  *hwmgr;
270
271         if (handle == NULL)
272                 return -EINVAL;
273
274         pp_handle = (struct pp_instance *)handle;
275
276         hwmgr = pp_handle->hwmgr;
277
278         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
279             hwmgr->hwmgr_func->force_dpm_level == NULL)
280                 return -EINVAL;
281
282         hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
283
284         return 0;
285 }
286
287 static enum amd_dpm_forced_level pp_dpm_get_performance_level(
288                                                                 void *handle)
289 {
290         struct pp_hwmgr  *hwmgr;
291
292         if (handle == NULL)
293                 return -EINVAL;
294
295         hwmgr = ((struct pp_instance *)handle)->hwmgr;
296
297         if (hwmgr == NULL)
298                 return -EINVAL;
299
300         return (((struct pp_instance *)handle)->hwmgr->dpm_level);
301 }
302
303 static int pp_dpm_get_sclk(void *handle, bool low)
304 {
305         struct pp_hwmgr  *hwmgr;
306
307         if (handle == NULL)
308                 return -EINVAL;
309
310         hwmgr = ((struct pp_instance *)handle)->hwmgr;
311
312         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
313             hwmgr->hwmgr_func->get_sclk == NULL)
314                 return -EINVAL;
315
316         return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
317 }
318
319 static int pp_dpm_get_mclk(void *handle, bool low)
320 {
321         struct pp_hwmgr  *hwmgr;
322
323         if (handle == NULL)
324                 return -EINVAL;
325
326         hwmgr = ((struct pp_instance *)handle)->hwmgr;
327
328         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
329             hwmgr->hwmgr_func->get_mclk == NULL)
330                 return -EINVAL;
331
332         return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
333 }
334
335 static int pp_dpm_powergate_vce(void *handle, bool gate)
336 {
337         struct pp_hwmgr  *hwmgr;
338
339         if (handle == NULL)
340                 return -EINVAL;
341
342         hwmgr = ((struct pp_instance *)handle)->hwmgr;
343
344         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
345             hwmgr->hwmgr_func->powergate_vce == NULL)
346                 return -EINVAL;
347
348         return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
349 }
350
351 static int pp_dpm_powergate_uvd(void *handle, bool gate)
352 {
353         struct pp_hwmgr  *hwmgr;
354
355         if (handle == NULL)
356                 return -EINVAL;
357
358         hwmgr = ((struct pp_instance *)handle)->hwmgr;
359
360         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
361             hwmgr->hwmgr_func->powergate_uvd == NULL)
362                 return -EINVAL;
363
364         return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
365 }
366
367 static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
368 {
369         switch (state) {
370         case POWER_STATE_TYPE_BATTERY:
371                 return PP_StateUILabel_Battery;
372         case POWER_STATE_TYPE_BALANCED:
373                 return PP_StateUILabel_Balanced;
374         case POWER_STATE_TYPE_PERFORMANCE:
375                 return PP_StateUILabel_Performance;
376         default:
377                 return PP_StateUILabel_None;
378         }
379 }
380
381 int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output)
382 {
383         int ret = 0;
384         struct pp_instance *pp_handle;
385         struct pem_event_data data = { {0} };
386
387         pp_handle = (struct pp_instance *)handle;
388
389         if (pp_handle == NULL)
390                 return -EINVAL;
391
392         switch (event_id) {
393         case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
394                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
395                 break;
396         case AMD_PP_EVENT_ENABLE_USER_STATE:
397         {
398                 enum amd_pm_state_type  ps;
399
400                 if (input == NULL)
401                         return -EINVAL;
402                 ps = *(unsigned long *)input;
403
404                 data.requested_ui_label = power_state_convert(ps);
405                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
406                 break;
407         }
408         case AMD_PP_EVENT_COMPLETE_INIT:
409                 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
410                 break;
411         default:
412                 break;
413         }
414         return ret;
415 }
416
417 enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
418 {
419         struct pp_hwmgr *hwmgr;
420         struct pp_power_state *state;
421
422         if (handle == NULL)
423                 return -EINVAL;
424
425         hwmgr = ((struct pp_instance *)handle)->hwmgr;
426
427         if (hwmgr == NULL || hwmgr->current_ps == NULL)
428                 return -EINVAL;
429
430         state = hwmgr->current_ps;
431
432         switch (state->classification.ui_label) {
433         case PP_StateUILabel_Battery:
434                 return POWER_STATE_TYPE_BATTERY;
435         case PP_StateUILabel_Balanced:
436                 return POWER_STATE_TYPE_BALANCED;
437         case PP_StateUILabel_Performance:
438                 return POWER_STATE_TYPE_PERFORMANCE;
439         default:
440                 if (state->classification.flags & PP_StateClassificationFlag_Boot)
441                         return  POWER_STATE_TYPE_INTERNAL_BOOT;
442                 else
443                         return POWER_STATE_TYPE_DEFAULT;
444         }
445 }
446
447 static void
448 pp_debugfs_print_current_performance_level(void *handle,
449                                                struct seq_file *m)
450 {
451         struct pp_hwmgr  *hwmgr;
452
453         if (handle == NULL)
454                 return;
455
456         hwmgr = ((struct pp_instance *)handle)->hwmgr;
457
458         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
459           hwmgr->hwmgr_func->print_current_perforce_level == NULL)
460                 return;
461
462         hwmgr->hwmgr_func->print_current_perforce_level(hwmgr, m);
463 }
464
465 static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
466 {
467         struct pp_hwmgr  *hwmgr;
468
469         if (handle == NULL)
470                 return -EINVAL;
471
472         hwmgr = ((struct pp_instance *)handle)->hwmgr;
473
474         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
475           hwmgr->hwmgr_func->set_fan_control_mode == NULL)
476                 return -EINVAL;
477
478         return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
479 }
480
481 static int pp_dpm_get_fan_control_mode(void *handle)
482 {
483         struct pp_hwmgr  *hwmgr;
484
485         if (handle == NULL)
486                 return -EINVAL;
487
488         hwmgr = ((struct pp_instance *)handle)->hwmgr;
489
490         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
491           hwmgr->hwmgr_func->get_fan_control_mode == NULL)
492                 return -EINVAL;
493
494         return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
495 }
496
497 static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
498 {
499         struct pp_hwmgr  *hwmgr;
500
501         if (handle == NULL)
502                 return -EINVAL;
503
504         hwmgr = ((struct pp_instance *)handle)->hwmgr;
505
506         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
507           hwmgr->hwmgr_func->set_fan_speed_percent == NULL)
508                 return -EINVAL;
509
510         return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
511 }
512
513 static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
514 {
515         struct pp_hwmgr  *hwmgr;
516
517         if (handle == NULL)
518                 return -EINVAL;
519
520         hwmgr = ((struct pp_instance *)handle)->hwmgr;
521
522         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
523           hwmgr->hwmgr_func->get_fan_speed_percent == NULL)
524                 return -EINVAL;
525
526         return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
527 }
528
529 static int pp_dpm_get_temperature(void *handle)
530 {
531         struct pp_hwmgr  *hwmgr;
532
533         if (handle == NULL)
534                 return -EINVAL;
535
536         hwmgr = ((struct pp_instance *)handle)->hwmgr;
537
538         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
539           hwmgr->hwmgr_func->get_temperature == NULL)
540                 return -EINVAL;
541
542         return hwmgr->hwmgr_func->get_temperature(hwmgr);
543 }
544
545 static int pp_dpm_get_pp_num_states(void *handle,
546                 struct pp_states_info *data)
547 {
548         struct pp_hwmgr *hwmgr;
549         int i;
550
551         if (!handle)
552                 return -EINVAL;
553
554         hwmgr = ((struct pp_instance *)handle)->hwmgr;
555
556         if (hwmgr == NULL || hwmgr->ps == NULL)
557                 return -EINVAL;
558
559         data->nums = hwmgr->num_ps;
560
561         for (i = 0; i < hwmgr->num_ps; i++) {
562                 struct pp_power_state *state = (struct pp_power_state *)
563                                 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
564                 switch (state->classification.ui_label) {
565                 case PP_StateUILabel_Battery:
566                         data->states[i] = POWER_STATE_TYPE_BATTERY;
567                         break;
568                 case PP_StateUILabel_Balanced:
569                         data->states[i] = POWER_STATE_TYPE_BALANCED;
570                         break;
571                 case PP_StateUILabel_Performance:
572                         data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
573                         break;
574                 default:
575                         if (state->classification.flags & PP_StateClassificationFlag_Boot)
576                                 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
577                         else
578                                 data->states[i] = POWER_STATE_TYPE_DEFAULT;
579                 }
580         }
581
582         return 0;
583 }
584
585 static int pp_dpm_get_pp_table(void *handle, char **table)
586 {
587         struct pp_hwmgr *hwmgr;
588
589         if (!handle)
590                 return -EINVAL;
591
592         hwmgr = ((struct pp_instance *)handle)->hwmgr;
593
594         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
595                 hwmgr->hwmgr_func->get_pp_table == NULL)
596                 return -EINVAL;
597
598         return hwmgr->hwmgr_func->get_pp_table(hwmgr, table);
599 }
600
601 static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
602 {
603         struct pp_hwmgr *hwmgr;
604
605         if (!handle)
606                 return -EINVAL;
607
608         hwmgr = ((struct pp_instance *)handle)->hwmgr;
609
610         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
611                 hwmgr->hwmgr_func->set_pp_table == NULL)
612                 return -EINVAL;
613
614         return hwmgr->hwmgr_func->set_pp_table(hwmgr, buf, size);
615 }
616
617 static int pp_dpm_force_clock_level(void *handle,
618                 enum pp_clock_type type, int level)
619 {
620         struct pp_hwmgr *hwmgr;
621
622         if (!handle)
623                 return -EINVAL;
624
625         hwmgr = ((struct pp_instance *)handle)->hwmgr;
626
627         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
628                         hwmgr->hwmgr_func->force_clock_level == NULL)
629                 return -EINVAL;
630
631         return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, level);
632 }
633
634 static int pp_dpm_print_clock_levels(void *handle,
635                 enum pp_clock_type type, char *buf)
636 {
637         struct pp_hwmgr *hwmgr;
638
639         if (!handle)
640                 return -EINVAL;
641
642         hwmgr = ((struct pp_instance *)handle)->hwmgr;
643
644         if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
645                         hwmgr->hwmgr_func->print_clock_levels == NULL)
646                 return -EINVAL;
647
648         return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
649 }
650
651 const struct amd_powerplay_funcs pp_dpm_funcs = {
652         .get_temperature = pp_dpm_get_temperature,
653         .load_firmware = pp_dpm_load_fw,
654         .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
655         .force_performance_level = pp_dpm_force_performance_level,
656         .get_performance_level = pp_dpm_get_performance_level,
657         .get_current_power_state = pp_dpm_get_current_power_state,
658         .get_sclk = pp_dpm_get_sclk,
659         .get_mclk = pp_dpm_get_mclk,
660         .powergate_vce = pp_dpm_powergate_vce,
661         .powergate_uvd = pp_dpm_powergate_uvd,
662         .dispatch_tasks = pp_dpm_dispatch_tasks,
663         .print_current_performance_level = pp_debugfs_print_current_performance_level,
664         .set_fan_control_mode = pp_dpm_set_fan_control_mode,
665         .get_fan_control_mode = pp_dpm_get_fan_control_mode,
666         .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
667         .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
668         .get_pp_num_states = pp_dpm_get_pp_num_states,
669         .get_pp_table = pp_dpm_get_pp_table,
670         .set_pp_table = pp_dpm_set_pp_table,
671         .force_clock_level = pp_dpm_force_clock_level,
672         .print_clock_levels = pp_dpm_print_clock_levels,
673 };
674
675 static int amd_pp_instance_init(struct amd_pp_init *pp_init,
676                                 struct amd_powerplay *amd_pp)
677 {
678         int ret;
679         struct pp_instance *handle;
680
681         handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
682         if (handle == NULL)
683                 return -ENOMEM;
684
685         handle->pp_valid = PP_VALID;
686
687         ret = smum_init(pp_init, handle);
688         if (ret)
689                 goto fail_smum;
690
691         ret = hwmgr_init(pp_init, handle);
692         if (ret)
693                 goto fail_hwmgr;
694
695         ret = eventmgr_init(handle);
696         if (ret)
697                 goto fail_eventmgr;
698
699         amd_pp->pp_handle = handle;
700         return 0;
701
702 fail_eventmgr:
703         hwmgr_fini(handle->hwmgr);
704 fail_hwmgr:
705         smum_fini(handle->smu_mgr);
706 fail_smum:
707         kfree(handle);
708         return ret;
709 }
710
711 static int amd_pp_instance_fini(void *handle)
712 {
713         struct pp_instance *instance = (struct pp_instance *)handle;
714
715         if (instance == NULL)
716                 return -EINVAL;
717
718         eventmgr_fini(instance->eventmgr);
719
720         hwmgr_fini(instance->hwmgr);
721
722         smum_fini(instance->smu_mgr);
723
724         kfree(handle);
725         return 0;
726 }
727
728 int amd_powerplay_init(struct amd_pp_init *pp_init,
729                        struct amd_powerplay *amd_pp)
730 {
731         int ret;
732
733         if (pp_init == NULL || amd_pp == NULL)
734                 return -EINVAL;
735
736         ret = amd_pp_instance_init(pp_init, amd_pp);
737
738         if (ret)
739                 return ret;
740
741         amd_pp->ip_funcs = &pp_ip_funcs;
742         amd_pp->pp_funcs = &pp_dpm_funcs;
743
744         return 0;
745 }
746
747 int amd_powerplay_fini(void *handle)
748 {
749         amd_pp_instance_fini(handle);
750
751         return 0;
752 }
753
754 /* export this function to DAL */
755
756 int amd_powerplay_display_configuration_change(void *handle,
757         const struct amd_pp_display_configuration *display_config)
758 {
759         struct pp_hwmgr  *hwmgr;
760
761         PP_CHECK((struct pp_instance *)handle);
762
763         hwmgr = ((struct pp_instance *)handle)->hwmgr;
764
765         phm_store_dal_configuration_data(hwmgr, display_config);
766
767         return 0;
768 }
769
770 int amd_powerplay_get_display_power_level(void *handle,
771                 struct amd_pp_simple_clock_info *output)
772 {
773         struct pp_hwmgr  *hwmgr;
774
775         PP_CHECK((struct pp_instance *)handle);
776
777         if (output == NULL)
778                 return -EINVAL;
779
780         hwmgr = ((struct pp_instance *)handle)->hwmgr;
781
782         return phm_get_dal_power_level(hwmgr, output);
783 }
784
785 int amd_powerplay_get_current_clocks(void *handle,
786                 struct amd_pp_clock_info *clocks)
787 {
788         struct pp_hwmgr  *hwmgr;
789         struct amd_pp_simple_clock_info simple_clocks;
790         struct pp_clock_info hw_clocks;
791
792         PP_CHECK((struct pp_instance *)handle);
793
794         if (clocks == NULL)
795                 return -EINVAL;
796
797         hwmgr = ((struct pp_instance *)handle)->hwmgr;
798
799         phm_get_dal_power_level(hwmgr, &simple_clocks);
800
801         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
802                 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment))
803                         PP_ASSERT_WITH_CODE(0, "Error in PHM_GetPowerContainmentClockInfo", return -1);
804         } else {
805                 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity))
806                         PP_ASSERT_WITH_CODE(0, "Error in PHM_GetClockInfo", return -1);
807         }
808
809         clocks->min_engine_clock = hw_clocks.min_eng_clk;
810         clocks->max_engine_clock = hw_clocks.max_eng_clk;
811         clocks->min_memory_clock = hw_clocks.min_mem_clk;
812         clocks->max_memory_clock = hw_clocks.max_mem_clk;
813         clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
814         clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
815
816         clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
817         clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
818
819         clocks->max_clocks_state = simple_clocks.level;
820
821         if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
822                 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
823                 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
824         }
825
826         return 0;
827
828 }
829
830 int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
831 {
832         int result = -1;
833
834         struct pp_hwmgr *hwmgr;
835
836         PP_CHECK((struct pp_instance *)handle);
837
838         if (clocks == NULL)
839                 return -EINVAL;
840
841         hwmgr = ((struct pp_instance *)handle)->hwmgr;
842
843         result = phm_get_clock_by_type(hwmgr, type, clocks);
844
845         return result;
846 }
847
848 int amd_powerplay_get_display_mode_validation_clocks(void *handle,
849                 struct amd_pp_simple_clock_info *clocks)
850 {
851         int result = -1;
852         struct pp_hwmgr  *hwmgr;
853
854         PP_CHECK((struct pp_instance *)handle);
855
856         if (clocks == NULL)
857                 return -EINVAL;
858
859         hwmgr = ((struct pp_instance *)handle)->hwmgr;
860
861         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
862                 result = phm_get_max_high_clocks(hwmgr, clocks);
863
864         return result;
865 }
866