diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2015-12-18 11:06:42 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-01-13 12:11:30 -0500 |
commit | d83b1e8132f91ba9e038b5206dc81d32ecac1f75 (patch) | |
tree | ec747b7c51cc8fb123f0cde32120d0a122d4007d | |
parent | 888c9e33e4c5a503285921046c621f7c73199d2f (diff) |
drm/amdgpu/cz: add code to enable forcing UVD clocks
UVD DPM works similarly to SCLK DPM. Add a similar interface
for UVD for forcing the UVD clocks.
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 129 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/cz_dpm.h | 1 |
2 files changed, 130 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 8035d4d6a4f5..5ccea9f9c634 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c | |||
@@ -1078,6 +1078,37 @@ static uint32_t cz_get_eclk_level(struct amdgpu_device *adev, | |||
1078 | return i; | 1078 | return i; |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | static uint32_t cz_get_uvd_level(struct amdgpu_device *adev, | ||
1082 | uint32_t clock, uint16_t msg) | ||
1083 | { | ||
1084 | int i = 0; | ||
1085 | struct amdgpu_uvd_clock_voltage_dependency_table *table = | ||
1086 | &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; | ||
1087 | |||
1088 | switch (msg) { | ||
1089 | case PPSMC_MSG_SetUvdSoftMin: | ||
1090 | case PPSMC_MSG_SetUvdHardMin: | ||
1091 | for (i = 0; i < table->count; i++) | ||
1092 | if (clock <= table->entries[i].vclk) | ||
1093 | break; | ||
1094 | if (i == table->count) | ||
1095 | i = table->count - 1; | ||
1096 | break; | ||
1097 | case PPSMC_MSG_SetUvdSoftMax: | ||
1098 | case PPSMC_MSG_SetUvdHardMax: | ||
1099 | for (i = table->count - 1; i >= 0; i--) | ||
1100 | if (clock >= table->entries[i].vclk) | ||
1101 | break; | ||
1102 | if (i < 0) | ||
1103 | i = 0; | ||
1104 | break; | ||
1105 | default: | ||
1106 | break; | ||
1107 | } | ||
1108 | |||
1109 | return i; | ||
1110 | } | ||
1111 | |||
1081 | static int cz_program_bootup_state(struct amdgpu_device *adev) | 1112 | static int cz_program_bootup_state(struct amdgpu_device *adev) |
1082 | { | 1113 | { |
1083 | struct cz_power_info *pi = cz_get_pi(adev); | 1114 | struct cz_power_info *pi = cz_get_pi(adev); |
@@ -1739,6 +1770,104 @@ static int cz_dpm_unforce_dpm_levels(struct amdgpu_device *adev) | |||
1739 | return 0; | 1770 | return 0; |
1740 | } | 1771 | } |
1741 | 1772 | ||
1773 | |||
1774 | static int cz_dpm_uvd_force_highest(struct amdgpu_device *adev) | ||
1775 | { | ||
1776 | struct cz_power_info *pi = cz_get_pi(adev); | ||
1777 | int ret = 0; | ||
1778 | |||
1779 | if (pi->uvd_dpm.soft_min_clk != pi->uvd_dpm.soft_max_clk) { | ||
1780 | pi->uvd_dpm.soft_min_clk = | ||
1781 | pi->uvd_dpm.soft_max_clk; | ||
1782 | ret = cz_send_msg_to_smc_with_parameter(adev, | ||
1783 | PPSMC_MSG_SetUvdSoftMin, | ||
1784 | cz_get_uvd_level(adev, | ||
1785 | pi->uvd_dpm.soft_min_clk, | ||
1786 | PPSMC_MSG_SetUvdSoftMin)); | ||
1787 | if (ret) | ||
1788 | return ret; | ||
1789 | } | ||
1790 | |||
1791 | return ret; | ||
1792 | } | ||
1793 | |||
1794 | static int cz_dpm_uvd_force_lowest(struct amdgpu_device *adev) | ||
1795 | { | ||
1796 | struct cz_power_info *pi = cz_get_pi(adev); | ||
1797 | int ret = 0; | ||
1798 | |||
1799 | if (pi->uvd_dpm.soft_max_clk != pi->uvd_dpm.soft_min_clk) { | ||
1800 | pi->uvd_dpm.soft_max_clk = pi->uvd_dpm.soft_min_clk; | ||
1801 | ret = cz_send_msg_to_smc_with_parameter(adev, | ||
1802 | PPSMC_MSG_SetUvdSoftMax, | ||
1803 | cz_get_uvd_level(adev, | ||
1804 | pi->uvd_dpm.soft_max_clk, | ||
1805 | PPSMC_MSG_SetUvdSoftMax)); | ||
1806 | if (ret) | ||
1807 | return ret; | ||
1808 | } | ||
1809 | |||
1810 | return ret; | ||
1811 | } | ||
1812 | |||
1813 | static uint32_t cz_dpm_get_max_uvd_level(struct amdgpu_device *adev) | ||
1814 | { | ||
1815 | struct cz_power_info *pi = cz_get_pi(adev); | ||
1816 | |||
1817 | if (!pi->max_uvd_level) { | ||
1818 | cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel); | ||
1819 | pi->max_uvd_level = cz_get_argument(adev) + 1; | ||
1820 | } | ||
1821 | |||
1822 | if (pi->max_uvd_level > CZ_MAX_HARDWARE_POWERLEVELS) { | ||
1823 | DRM_ERROR("Invalid max uvd level!\n"); | ||
1824 | return -EINVAL; | ||
1825 | } | ||
1826 | |||
1827 | return pi->max_uvd_level; | ||
1828 | } | ||
1829 | |||
1830 | static int cz_dpm_unforce_uvd_dpm_levels(struct amdgpu_device *adev) | ||
1831 | { | ||
1832 | struct cz_power_info *pi = cz_get_pi(adev); | ||
1833 | struct amdgpu_uvd_clock_voltage_dependency_table *dep_table = | ||
1834 | &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; | ||
1835 | uint32_t level = 0; | ||
1836 | int ret = 0; | ||
1837 | |||
1838 | pi->uvd_dpm.soft_min_clk = dep_table->entries[0].vclk; | ||
1839 | level = cz_dpm_get_max_uvd_level(adev) - 1; | ||
1840 | if (level < dep_table->count) | ||
1841 | pi->uvd_dpm.soft_max_clk = dep_table->entries[level].vclk; | ||
1842 | else | ||
1843 | pi->uvd_dpm.soft_max_clk = | ||
1844 | dep_table->entries[dep_table->count - 1].vclk; | ||
1845 | |||
1846 | /* get min/max sclk soft value | ||
1847 | * notify SMU to execute */ | ||
1848 | ret = cz_send_msg_to_smc_with_parameter(adev, | ||
1849 | PPSMC_MSG_SetUvdSoftMin, | ||
1850 | cz_get_uvd_level(adev, | ||
1851 | pi->uvd_dpm.soft_min_clk, | ||
1852 | PPSMC_MSG_SetUvdSoftMin)); | ||
1853 | if (ret) | ||
1854 | return ret; | ||
1855 | |||
1856 | ret = cz_send_msg_to_smc_with_parameter(adev, | ||
1857 | PPSMC_MSG_SetUvdSoftMax, | ||
1858 | cz_get_uvd_level(adev, | ||
1859 | pi->uvd_dpm.soft_max_clk, | ||
1860 | PPSMC_MSG_SetUvdSoftMax)); | ||
1861 | if (ret) | ||
1862 | return ret; | ||
1863 | |||
1864 | DRM_DEBUG("DPM uvd unforce state min=%d, max=%d.\n", | ||
1865 | pi->uvd_dpm.soft_min_clk, | ||
1866 | pi->uvd_dpm.soft_max_clk); | ||
1867 | |||
1868 | return 0; | ||
1869 | } | ||
1870 | |||
1742 | static int cz_dpm_force_dpm_level(struct amdgpu_device *adev, | 1871 | static int cz_dpm_force_dpm_level(struct amdgpu_device *adev, |
1743 | enum amdgpu_dpm_forced_level level) | 1872 | enum amdgpu_dpm_forced_level level) |
1744 | { | 1873 | { |
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h index 99e1afc89629..6a6a6fe7967f 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h | |||
@@ -183,6 +183,7 @@ struct cz_power_info { | |||
183 | uint32_t voltage_drop_threshold; | 183 | uint32_t voltage_drop_threshold; |
184 | uint32_t gfx_pg_threshold; | 184 | uint32_t gfx_pg_threshold; |
185 | uint32_t max_sclk_level; | 185 | uint32_t max_sclk_level; |
186 | uint32_t max_uvd_level; | ||
186 | /* flags */ | 187 | /* flags */ |
187 | bool didt_enabled; | 188 | bool didt_enabled; |
188 | bool video_start; | 189 | bool video_start; |