summary refs log tree commit diff
path: root/drivers/gpu/drm/amd/powerplay
diff options
context:
space:
mode:
authorEric Huang <JinHuiEric.Huang@amd.com>2017-01-24 10:47:25 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-03-29 23:52:49 -0400
commitff3953d49c0acafab527ec97a665df87ab6bbc70 (patch)
treed133f3cae01ed4e635c402e76ffb034da1e9e3af /drivers/gpu/drm/amd/powerplay
parent789fd60fa66ceb74957d58a3a8a3160724fb59b7 (diff)
downloadlinux-ff3953d49c0acafab527ec97a665df87ab6bbc70.tar.gz
drm/amd/powerplay: add power profile support for SMU7
Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com>
Acked-by: Rex Zhu <Rex.Zhu@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay')
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c71
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/smumgr.h5
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c10
3 files changed, 86 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index f75ee33ec5bb..31289a8d5cec 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -4502,6 +4502,76 @@ static int smu7_release_firmware(struct pp_hwmgr *hwmgr)
 	return 0;
 }
 
+static void smu7_find_min_clock_masks(struct pp_hwmgr *hwmgr,
+		uint32_t *sclk_mask, uint32_t *mclk_mask,
+		uint32_t min_sclk, uint32_t min_mclk)
+{
+	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+	struct smu7_dpm_table *dpm_table = &(data->dpm_table);
+	uint32_t i;
+
+	for (i = 0; i < dpm_table->sclk_table.count; i++) {
+		if (dpm_table->sclk_table.dpm_levels[i].enabled &&
+			dpm_table->sclk_table.dpm_levels[i].value >= min_sclk)
+			*sclk_mask |= 1 << i;
+	}
+
+	for (i = 0; i < dpm_table->mclk_table.count; i++) {
+		if (dpm_table->mclk_table.dpm_levels[i].enabled &&
+			dpm_table->mclk_table.dpm_levels[i].value >= min_mclk)
+			*mclk_mask |= 1 << i;
+	}
+}
+
+static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr,
+		struct amd_pp_profile *request)
+{
+	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+	int tmp_result, result = 0;
+	uint32_t sclk_mask = 0, mclk_mask = 0;
+
+	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)
+		return -EINVAL;
+
+	tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE(!tmp_result,
+			"Failed to freeze SCLK MCLK DPM!",
+			result = tmp_result);
+
+	tmp_result = smum_populate_requested_graphic_levels(hwmgr, request);
+	PP_ASSERT_WITH_CODE(!tmp_result,
+			"Failed to populate requested graphic levels!",
+			result = tmp_result);
+
+	tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE(!tmp_result,
+			"Failed to unfreeze SCLK MCLK DPM!",
+			result = tmp_result);
+
+	smu7_find_min_clock_masks(hwmgr, &sclk_mask, &mclk_mask,
+			request->min_sclk, request->min_mclk);
+
+	if (sclk_mask) {
+		if (!data->sclk_dpm_key_disabled)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_SetEnabledMask,
+				data->dpm_level_enable_mask.
+				sclk_dpm_enable_mask &
+				sclk_mask);
+	}
+
+	if (mclk_mask) {
+		if (!data->mclk_dpm_key_disabled)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_MCLKDPM_SetEnabledMask,
+				data->dpm_level_enable_mask.
+				mclk_dpm_enable_mask &
+				mclk_mask);
+	}
+
+	return result;
+}
+
 static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
 	.backend_init = &smu7_hwmgr_backend_init,
 	.backend_fini = &smu7_hwmgr_backend_fini,
@@ -4551,6 +4621,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
 	.dynamic_state_management_disable = smu7_disable_dpm_tasks,
 	.request_firmware = smu7_request_firmware,
 	.release_firmware = smu7_release_firmware,
+	.set_power_profile_state = smu7_set_power_profile_state,
 };
 
 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
index 7c318a95e0c2..52f56f40bc54 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
@@ -127,6 +127,8 @@ struct pp_smumgr_func {
 	uint32_t (*get_offsetof)(uint32_t type, uint32_t member);
 	uint32_t (*get_mac_definition)(uint32_t value);
 	bool (*is_dpm_running)(struct pp_hwmgr *hwmgr);
+	int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr,
+			struct amd_pp_profile *request);
 };
 
 struct pp_smumgr {
@@ -193,6 +195,9 @@ extern uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value
 
 extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr);
 
+extern int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
+		struct amd_pp_profile *request);
+
 #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
 
 #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
index c0956a4207a9..454f4459131f 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
@@ -374,3 +374,13 @@ bool smum_is_dpm_running(struct pp_hwmgr *hwmgr)
 
 	return true;
 }
+
+int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
+		struct amd_pp_profile *request)
+{
+	if (hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels)
+		return hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels(
+				hwmgr, request);
+
+	return 0;
+}