Linux Audio

Check our new training course

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