aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChengming Gui <Jack.Gui@amd.com>2019-01-17 22:27:25 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-03-19 16:04:00 -0400
commit9a431038e30a45c470c5f949824a76538809662d (patch)
tree362245c3d675cced1cb3b5cca0a05881ca9184f2
parentf277ff0feacc09c11b26654df9d2b8f1b339cbd8 (diff)
drm/amd/powerplay: implement power_dpm_force_performance_level for SMU11
add get_performance_level and force_performance_level to implement the sys interface for SMU11. Signed-off-by: Chengming Gui <Jack.Gui@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c23
-rw-r--r--drivers/gpu/drm/amd/powerplay/amdgpu_smu.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h6
-rw-r--r--drivers/gpu/drm/amd/powerplay/smu_v11_0.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/vega20_ppt.c99
5 files changed, 127 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 694d85b0f0a0..77d946f8fca5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -264,7 +264,9 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
264 (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) 264 (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
265 return snprintf(buf, PAGE_SIZE, "off\n"); 265 return snprintf(buf, PAGE_SIZE, "off\n");
266 266
267 if (adev->powerplay.pp_funcs->get_performance_level) 267 if (is_support_sw_smu(adev))
268 level = smu_get_performance_level(&adev->smu);
269 else if (adev->powerplay.pp_funcs->get_performance_level)
268 level = amdgpu_dpm_get_performance_level(adev); 270 level = amdgpu_dpm_get_performance_level(adev);
269 else 271 else
270 level = adev->pm.dpm.forced_level; 272 level = adev->pm.dpm.forced_level;
@@ -297,7 +299,9 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
297 (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) 299 (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
298 return -EINVAL; 300 return -EINVAL;
299 301
300 if (adev->powerplay.pp_funcs->get_performance_level) 302 if (is_support_sw_smu(adev))
303 current_level = smu_get_performance_level(&adev->smu);
304 else if (adev->powerplay.pp_funcs->get_performance_level)
301 current_level = amdgpu_dpm_get_performance_level(adev); 305 current_level = amdgpu_dpm_get_performance_level(adev);
302 306
303 if (strncmp("low", buf, strlen("low")) == 0) { 307 if (strncmp("low", buf, strlen("low")) == 0) {
@@ -326,7 +330,20 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
326 if (current_level == level) 330 if (current_level == level)
327 return count; 331 return count;
328 332
329 if (adev->powerplay.pp_funcs->force_performance_level) { 333 if (is_support_sw_smu(adev)) {
334 mutex_lock(&adev->pm.mutex);
335 if (adev->pm.dpm.thermal_active) {
336 count = -EINVAL;
337 mutex_unlock(&adev->pm.mutex);
338 goto fail;
339 }
340 ret = smu_force_performance_level(&adev->smu, level);
341 if (ret)
342 count = -EINVAL;
343 else
344 adev->pm.dpm.forced_level = level;
345 mutex_unlock(&adev->pm.mutex);
346 } else if (adev->powerplay.pp_funcs->force_performance_level) {
330 mutex_lock(&adev->pm.mutex); 347 mutex_lock(&adev->pm.mutex);
331 if (adev->pm.dpm.thermal_active) { 348 if (adev->pm.dpm.thermal_active) {
332 count = -EINVAL; 349 count = -EINVAL;
diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index 83fadcac18e6..2917411a10eb 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -351,6 +351,8 @@ static int smu_sw_init(void *handle)
351 smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM; 351 smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM;
352 smu->display_config = &adev->pm.pm_display_cfg; 352 smu->display_config = &adev->pm.pm_display_cfg;
353 353
354 smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
355 smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
354 ret = smu_init_microcode(smu); 356 ret = smu_init_microcode(smu);
355 if (ret) { 357 if (ret) {
356 pr_err("Failed to load smu firmware!\n"); 358 pr_err("Failed to load smu firmware!\n");
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index 63cd1ba60dc2..111424d0581d 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -423,6 +423,8 @@ struct pptable_funcs {
423 *clocks); 423 *clocks);
424 int (*get_power_profile_mode)(struct smu_context *smu, char *buf); 424 int (*get_power_profile_mode)(struct smu_context *smu, char *buf);
425 int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size); 425 int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size);
426 enum amd_dpm_forced_level (*get_performance_level)(struct smu_context *smu);
427 int (*force_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level);
426}; 428};
427 429
428struct smu_funcs 430struct smu_funcs
@@ -594,6 +596,10 @@ struct smu_funcs
594 ((smu)->funcs->get_power_profile_mode ? (smu)->funcs->get_power_profile_mode((smu), buf) : 0) 596 ((smu)->funcs->get_power_profile_mode ? (smu)->funcs->get_power_profile_mode((smu), buf) : 0)
595#define smu_set_power_profile_mode(smu, param, param_size) \ 597#define smu_set_power_profile_mode(smu, param, param_size) \
596 ((smu)->funcs->set_power_profile_mode ? (smu)->funcs->set_power_profile_mode((smu), (param), (param_size)) : 0) 598 ((smu)->funcs->set_power_profile_mode ? (smu)->funcs->set_power_profile_mode((smu), (param), (param_size)) : 0)
599#define smu_get_performance_level(smu) \
600 ((smu)->ppt_funcs->get_performance_level ? (smu)->ppt_funcs->get_performance_level((smu)) : 0)
601#define smu_force_performance_level(smu, level) \
602 ((smu)->ppt_funcs->force_performance_level ? (smu)->ppt_funcs->force_performance_level((smu), (level)) : 0)
597 603
598#define smu_msg_get_index(smu, msg) \ 604#define smu_msg_get_index(smu, msg) \
599 ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_smu_msg_index? (smu)->ppt_funcs->get_smu_msg_index((smu), (msg)) : -EINVAL) : -EINVAL) 605 ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_smu_msg_index? (smu)->ppt_funcs->get_smu_msg_index((smu), (msg)) : -EINVAL) : -EINVAL)
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 93552d8c39fb..74ad160e1335 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -1100,7 +1100,6 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
1100 PPCLK_e clk_select = 0; 1100 PPCLK_e clk_select = 0;
1101 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; 1101 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
1102 1102
1103 mutex_lock(&smu->mutex);
1104 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) { 1103 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
1105 switch (clk_type) { 1104 switch (clk_type) {
1106 case amd_pp_dcef_clock: 1105 case amd_pp_dcef_clock:
@@ -1129,7 +1128,6 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
1129 } 1128 }
1130 1129
1131failed: 1130failed:
1132 mutex_unlock(&smu->mutex);
1133 return ret; 1131 return ret;
1134} 1132}
1135 1133
diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
index 5de0eabbeb29..911296d1f7cc 100644
--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
@@ -1744,6 +1744,103 @@ static int vega20_unforce_dpm_levels(struct smu_context *smu)
1744 return ret; 1744 return ret;
1745} 1745}
1746 1746
1747static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context *smu)
1748{
1749 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1750 if (!smu_dpm_ctx->dpm_context)
1751 return -EINVAL;
1752
1753 if (smu_dpm_ctx->dpm_level != smu_dpm_ctx->saved_dpm_level) {
1754 mutex_lock(&(smu->mutex));
1755 smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
1756 mutex_unlock(&(smu->mutex));
1757 }
1758 return smu_dpm_ctx->dpm_level;
1759}
1760
1761static int
1762vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1763{
1764 int ret = 0;
1765 int index = 0;
1766 int i = 0;
1767 uint32_t sclk_mask, mclk_mask, soc_mask;
1768 long workload;
1769 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1770 if (!smu_dpm_ctx->dpm_context)
1771 return -EINVAL;
1772
1773 for (i = 0; i < smu->adev->num_ip_blocks; i++) {
1774 if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
1775 break;
1776 }
1777 mutex_lock(&smu->mutex);
1778 smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
1779 ret = vega20_display_config_changed(smu);
1780 if (ret) {
1781 pr_err("Failed to change display config!");
1782 goto failed;
1783 }
1784 ret = vega20_apply_clocks_adjust_rules(smu);
1785 if (ret) {
1786 pr_err("Failed to apply clocks adjust rules!");
1787 goto failed;
1788 }
1789 ret = vega20_notify_smc_dispaly_config(smu);
1790 if (ret) {
1791 pr_err("Failed to notify smc display config!");
1792 goto failed;
1793 }
1794 switch (level) {
1795 case AMD_DPM_FORCED_LEVEL_HIGH:
1796 ret = vega20_force_dpm_highest(smu);
1797 break;
1798
1799 case AMD_DPM_FORCED_LEVEL_LOW:
1800 ret = vega20_force_dpm_lowest(smu);
1801 break;
1802
1803 case AMD_DPM_FORCED_LEVEL_AUTO:
1804 ret = vega20_unforce_dpm_levels(smu);
1805 break;
1806
1807 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1808 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1809 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1810 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1811 ret = vega20_get_profiling_clk_mask(smu, level,
1812 &sclk_mask,
1813 &mclk_mask,
1814 &soc_mask);
1815 if (ret)
1816 goto failed;
1817 vega20_force_clk_levels(smu, PP_SCLK, 1 << sclk_mask);
1818 vega20_force_clk_levels(smu, PP_MCLK, 1 << mclk_mask);
1819 break;
1820
1821 case AMD_DPM_FORCED_LEVEL_MANUAL:
1822 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1823 default:
1824 break;
1825 }
1826
1827 if (!ret)
1828 smu_dpm_ctx->dpm_level = level;
1829
1830 if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
1831 index = fls(smu->workload_mask);
1832 index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
1833 workload = smu->workload_setting[index];
1834
1835 if (smu->power_profile_mode != workload)
1836 smu->funcs->set_power_profile_mode(smu, &workload, 0);
1837 }
1838
1839failed:
1840 mutex_unlock(&smu->mutex);
1841 return ret;
1842}
1843
1747static const struct pptable_funcs vega20_ppt_funcs = { 1844static const struct pptable_funcs vega20_ppt_funcs = {
1748 .alloc_dpm_context = vega20_allocate_dpm_context, 1845 .alloc_dpm_context = vega20_allocate_dpm_context,
1749 .store_powerplay_table = vega20_store_powerplay_table, 1846 .store_powerplay_table = vega20_store_powerplay_table,
@@ -1761,6 +1858,8 @@ static const struct pptable_funcs vega20_ppt_funcs = {
1761 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency, 1858 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
1762 .set_default_od8_settings = vega20_set_default_od8_setttings, 1859 .set_default_od8_settings = vega20_set_default_od8_setttings,
1763 .get_od_percentage = vega20_get_od_percentage, 1860 .get_od_percentage = vega20_get_od_percentage,
1861 .get_performance_level = vega20_get_performance_level,
1862 .force_performance_level = vega20_force_performance_level,
1764}; 1863};
1765 1864
1766void vega20_set_ppt_funcs(struct smu_context *smu) 1865void vega20_set_ppt_funcs(struct smu_context *smu)