drm/amd/powerplay: add power profile support for Polaris
authorEric Huang <JinHuiEric.Huang@amd.com>
Tue, 24 Jan 2017 15:57:22 +0000 (10:57 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 30 Mar 2017 03:52:51 +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/smumgr/polaris10_smc.c
drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h
drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c

index 80e2329a1b9ebf1be1ed24fa6c058c8f15c92ec7..1eedab143aa9c28331f9afefd9f5c138b5e448c9 100644 (file)
@@ -1613,6 +1613,42 @@ static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
 
 }
 
+static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr)
+{
+       struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
+       struct SMU74_Discrete_GraphicsLevel *levels =
+                               data->smc_state_table.GraphicsLevel;
+       unsigned min_level = 1;
+
+       hwmgr->default_gfx_power_profile.activity_threshold =
+                       be16_to_cpu(levels[0].ActivityLevel);
+       hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst;
+       hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst;
+       hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
+
+       hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile;
+       hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
+
+       /* Workaround compute SDMA instability: disable lowest SCLK
+        * DPM level. Optimize compute power profile: Use only highest
+        * 2 power levels (if more than 2 are available), Hysteresis:
+        * 0ms up, 5ms down
+        */
+       if (data->smc_state_table.GraphicsDpmLevelCount > 2)
+               min_level = data->smc_state_table.GraphicsDpmLevelCount - 2;
+       else if (data->smc_state_table.GraphicsDpmLevelCount == 2)
+               min_level = 1;
+       else
+               min_level = 0;
+       hwmgr->default_compute_power_profile.min_sclk =
+               be32_to_cpu(levels[min_level].SclkSetting.SclkFrequency);
+       hwmgr->default_compute_power_profile.up_hyst = 0;
+       hwmgr->default_compute_power_profile.down_hyst = 5;
+
+       hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
+       hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
+}
+
 /**
 * Initializes the SMC table and uploads it
 *
@@ -1832,6 +1868,9 @@ int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
        result = polaris10_populate_pm_fuses(hwmgr);
        PP_ASSERT_WITH_CODE(0 == result,
                        "Failed to  populate PM fuses to SMC memory!", return result);
+
+       polaris10_save_default_power_profile(hwmgr);
+
        return 0;
 }
 
@@ -2298,3 +2337,28 @@ bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr)
                        CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
                        ? true : false;
 }
+
+int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
+               struct amd_pp_profile *request)
+{
+       struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)
+                       (hwmgr->smumgr->backend);
+       struct SMU74_Discrete_GraphicsLevel *levels =
+                       smu_data->smc_state_table.GraphicsLevel;
+       uint32_t array = smu_data->smu7_data.dpm_table_start +
+                       offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
+       uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
+                       SMU74_MAX_LEVELS_GRAPHICS;
+       uint32_t i;
+
+       for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
+               levels[i].ActivityLevel =
+                               cpu_to_be16(request->activity_threshold);
+               levels[i].EnabledForActivity = 1;
+               levels[i].UpHyst = request->up_hyst;
+               levels[i].DownHyst = request->down_hyst;
+       }
+
+       return smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
+                               array_size, SMC_RAM_END);
+}
index 5ade3cea8bb70d9f41319fc0ff869ba49bf1c3db..1df8154d06261319b125a3c043ab665685d48956 100644 (file)
@@ -37,6 +37,8 @@ uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member);
 uint32_t polaris10_get_mac_definition(uint32_t value);
 int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr);
 bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr);
+int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
+               struct amd_pp_profile *request);
 
 #endif
 
index ce20ae2e520eca7a683db1d5fb1894023d08f517..9616cedc139cebe35557adb324bb39c8087d5c4d 100644 (file)
@@ -409,4 +409,5 @@ const struct pp_smumgr_func polaris10_smu_funcs = {
        .populate_all_memory_levels = polaris10_populate_all_memory_levels,
        .get_mac_definition = polaris10_get_mac_definition,
        .is_dpm_running = polaris10_is_dpm_running,
+       .populate_requested_graphic_levels = polaris10_populate_requested_graphic_levels,
 };