summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/amd_powerplay.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index 39ffc5d4e49f..ea78525e26a5 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -23,8 +23,10 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/gfp.h>
+#include <linux/slab.h>
#include "amd_shared.h"
#include "amd_powerplay.h"
+#include "pp_instance.h"
static int pp_early_init(void *handle)
{
@@ -43,11 +45,51 @@ static int pp_sw_fini(void *handle)
static int pp_hw_init(void *handle)
{
+ struct pp_instance *pp_handle;
+ struct pp_smumgr *smumgr;
+ int ret = 0;
+
+ if (handle == NULL)
+ return -EINVAL;
+
+ pp_handle = (struct pp_instance *)handle;
+ smumgr = pp_handle->smu_mgr;
+
+ if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
+ smumgr->smumgr_funcs->smu_init == NULL ||
+ smumgr->smumgr_funcs->start_smu == NULL)
+ return -EINVAL;
+
+ ret = smumgr->smumgr_funcs->smu_init(smumgr);
+ if (ret) {
+ printk(KERN_ERR "[ powerplay ] smc initialization failed\n");
+ return ret;
+ }
+
+ ret = smumgr->smumgr_funcs->start_smu(smumgr);
+ if (ret) {
+ printk(KERN_ERR "[ powerplay ] smc start failed\n");
+ smumgr->smumgr_funcs->smu_fini(smumgr);
+ return ret;
+ }
return 0;
}
static int pp_hw_fini(void *handle)
{
+ struct pp_instance *pp_handle;
+ struct pp_smumgr *smumgr;
+
+ if (handle == NULL)
+ return -EINVAL;
+
+ pp_handle = (struct pp_instance *)handle;
+ smumgr = pp_handle->smu_mgr;
+
+ if (smumgr != NULL || smumgr->smumgr_funcs != NULL ||
+ smumgr->smumgr_funcs->smu_fini != NULL)
+ smumgr->smumgr_funcs->smu_fini(smumgr);
+
return 0;
}
@@ -176,12 +218,49 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
.print_current_performance_level = pp_debugfs_print_current_performance_level,
};
+static int amd_pp_instance_init(struct amd_pp_init *pp_init,
+ struct amd_powerplay *amd_pp)
+{
+ int ret;
+ struct pp_instance *handle;
+
+ handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
+ if (handle == NULL)
+ return -ENOMEM;
+
+ ret = smum_init(pp_init, handle);
+ if (ret)
+ return ret;
+
+ amd_pp->pp_handle = handle;
+ return 0;
+}
+
+static int amd_pp_instance_fini(void *handle)
+{
+ struct pp_instance *instance = (struct pp_instance *)handle;
+ if (instance == NULL)
+ return -EINVAL;
+
+ smum_fini(instance->smu_mgr);
+
+ kfree(handle);
+ return 0;
+}
+
int amd_powerplay_init(struct amd_pp_init *pp_init,
struct amd_powerplay *amd_pp)
{
+ int ret;
+
if (pp_init == NULL || amd_pp == NULL)
return -EINVAL;
+ ret = amd_pp_instance_init(pp_init, amd_pp);
+
+ if (ret)
+ return ret;
+
amd_pp->ip_funcs = &pp_ip_funcs;
amd_pp->pp_funcs = &pp_dpm_funcs;
@@ -190,5 +269,7 @@ int amd_powerplay_init(struct amd_pp_init *pp_init,
int amd_powerplay_fini(void *handle)
{
+ amd_pp_instance_fini(handle);
+
return 0;
}
OpenPOWER on IntegriCloud