drm/amd/powerplay: add power profile support for SMU7
authorEric Huang <JinHuiEric.Huang@amd.com>
Tue, 24 Jan 2017 15:47:25 +0000 (10:47 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 30 Mar 2017 03:52:49 +0000 (23:52 -0400)
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>
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/smumgr.h
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c

index f75ee33ec5bb344f11ab968d39d4db5b469cb373..31289a8d5cec095f923fe7c242b20cea379a51a7 100644 (file)
@@ -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,
index 7c318a95e0c280406dfd5e70f23fd06e863814de..52f56f40bc54fd90800d025c003f0ae8e7b8f04b 100644 (file)
@@ -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
index c0956a4207a9a8d9e86692ffaeb631a9b4d797fd..454f4459131f464f16b9405ac11c5e86e8e8f111 100644 (file)
@@ -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;
+}