aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2015-12-18 11:06:42 -0500
committerAlex Deucher <alexander.deucher@amd.com>2016-01-13 12:11:30 -0500
commitd83b1e8132f91ba9e038b5206dc81d32ecac1f75 (patch)
treeec747b7c51cc8fb123f0cde32120d0a122d4007d
parent888c9e33e4c5a503285921046c621f7c73199d2f (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.c129
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.h1
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
1081static 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
1081static int cz_program_bootup_state(struct amdgpu_device *adev) 1112static 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
1774static 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
1794static 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
1813static 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
1830static 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
1742static int cz_dpm_force_dpm_level(struct amdgpu_device *adev, 1871static 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;