diff options
author | Chengming Gui <Jack.Gui@amd.com> | 2019-01-17 22:27:25 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-03-19 16:04:00 -0400 |
commit | 9a431038e30a45c470c5f949824a76538809662d (patch) | |
tree | 362245c3d675cced1cb3b5cca0a05881ca9184f2 | |
parent | f277ff0feacc09c11b26654df9d2b8f1b339cbd8 (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.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 99 |
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 | ||
428 | struct smu_funcs | 430 | struct 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 | ||
1131 | failed: | 1130 | failed: |
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 | ||
1747 | static 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 | |||
1761 | static int | ||
1762 | vega20_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 | |||
1839 | failed: | ||
1840 | mutex_unlock(&smu->mutex); | ||
1841 | return ret; | ||
1842 | } | ||
1843 | |||
1747 | static const struct pptable_funcs vega20_ppt_funcs = { | 1844 | static 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 | ||
1766 | void vega20_set_ppt_funcs(struct smu_context *smu) | 1865 | void vega20_set_ppt_funcs(struct smu_context *smu) |