aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSonny Jiang <sonny.jiang@amd.com>2015-05-12 16:13:35 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-06-03 21:03:48 -0400
commit564ea7900cffbe2eddb3bcfb09b700ad7942aef4 (patch)
tree8108238d468c78a9776900aeaa637d2c46951f96
parent5bbc553a1acce5d1792ba778273ffbea5af1695d (diff)
drm/amdgpu: enable uvd dpm and powergating
Enable UVD dpm (dynamic power management) and powergating. UVD dpm dynamically scales the UVD clocks on demand. Powergating turns off the power to the block when it's not in use. Signed-off-by: Sonny Jiang <sonny.jiang@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.c90
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c2
3 files changed, 91 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index adf4dbc3f6a0..2649b505d2d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -42,6 +42,8 @@
42#include "bif/bif_5_1_d.h" 42#include "bif/bif_5_1_d.h"
43#include "gfx_v8_0.h" 43#include "gfx_v8_0.h"
44 44
45static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate);
46
45static struct cz_ps *cz_get_ps(struct amdgpu_ps *rps) 47static struct cz_ps *cz_get_ps(struct amdgpu_ps *rps)
46{ 48{
47 struct cz_ps *ps = rps->ps_priv; 49 struct cz_ps *ps = rps->ps_priv;
@@ -474,6 +476,7 @@ static int cz_dpm_init(struct amdgpu_device *adev)
474 return ret; 476 return ret;
475 477
476 pi->dpm_enabled = true; 478 pi->dpm_enabled = true;
479 pi->uvd_dynamic_pg = false;
477 480
478 return 0; 481 return 0;
479} 482}
@@ -546,6 +549,15 @@ static int cz_dpm_early_init(struct amdgpu_device *adev)
546 return 0; 549 return 0;
547} 550}
548 551
552
553static int cz_dpm_late_init(struct amdgpu_device *adev)
554{
555 /* powerdown unused blocks for now */
556 cz_dpm_powergate_uvd(adev, true);
557
558 return 0;
559}
560
549static int cz_dpm_sw_init(struct amdgpu_device *adev) 561static int cz_dpm_sw_init(struct amdgpu_device *adev)
550{ 562{
551 int ret = 0; 563 int ret = 0;
@@ -1260,6 +1272,9 @@ static int cz_dpm_disable(struct amdgpu_device *adev)
1260 return -EINVAL; 1272 return -EINVAL;
1261 } 1273 }
1262 1274
1275 /* powerup blocks */
1276 cz_dpm_powergate_uvd(adev, false);
1277
1263 cz_clear_voting_clients(adev); 1278 cz_clear_voting_clients(adev);
1264 cz_stop_dpm(adev); 1279 cz_stop_dpm(adev);
1265 cz_update_current_ps(adev, adev->pm.dpm.boot_ps); 1280 cz_update_current_ps(adev, adev->pm.dpm.boot_ps);
@@ -1677,9 +1692,80 @@ static uint32_t cz_dpm_get_mclk(struct amdgpu_device *adev, bool low)
1677 return pi->sys_info.bootup_uma_clk; 1692 return pi->sys_info.bootup_uma_clk;
1678} 1693}
1679 1694
1695static int cz_enable_uvd_dpm(struct amdgpu_device *adev, bool enable)
1696{
1697 struct cz_power_info *pi = cz_get_pi(adev);
1698 int ret = 0;
1699
1700 if (enable && pi->caps_uvd_dpm ) {
1701 pi->dpm_flags |= DPMFlags_UVD_Enabled;
1702 DRM_DEBUG("UVD DPM Enabled.\n");
1703
1704 ret = cz_send_msg_to_smc_with_parameter(adev,
1705 PPSMC_MSG_EnableAllSmuFeatures, UVD_DPM_MASK);
1706 } else {
1707 pi->dpm_flags &= ~DPMFlags_UVD_Enabled;
1708 DRM_DEBUG("UVD DPM Stopped\n");
1709
1710 ret = cz_send_msg_to_smc_with_parameter(adev,
1711 PPSMC_MSG_DisableAllSmuFeatures, UVD_DPM_MASK);
1712 }
1713
1714 return ret;
1715}
1716
1717static int cz_update_uvd_dpm(struct amdgpu_device *adev, bool gate)
1718{
1719 return cz_enable_uvd_dpm(adev, !gate);
1720}
1721
1722
1723static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
1724{
1725 struct cz_power_info *pi = cz_get_pi(adev);
1726 int ret;
1727
1728 if (pi->uvd_power_gated == gate)
1729 return;
1730
1731 pi->uvd_power_gated = gate;
1732
1733 if (gate) {
1734 if (pi->caps_uvd_pg) {
1735 /* disable clockgating so we can properly shut down the block */
1736 ret = amdgpu_set_clockgating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
1737 AMDGPU_CG_STATE_UNGATE);
1738 /* shutdown the UVD block */
1739 ret = amdgpu_set_powergating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
1740 AMDGPU_PG_STATE_GATE);
1741 /* XXX: check for errors */
1742 }
1743 cz_update_uvd_dpm(adev, gate);
1744 if (pi->caps_uvd_pg)
1745 /* power off the UVD block */
1746 cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF);
1747 } else {
1748 if (pi->caps_uvd_pg) {
1749 /* power on the UVD block */
1750 if (pi->uvd_dynamic_pg)
1751 cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1);
1752 else
1753 cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0);
1754 /* re-init the UVD block */
1755 ret = amdgpu_set_powergating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
1756 AMDGPU_PG_STATE_UNGATE);
1757 /* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
1758 ret = amdgpu_set_clockgating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
1759 AMDGPU_CG_STATE_GATE);
1760 /* XXX: check for errors */
1761 }
1762 cz_update_uvd_dpm(adev, gate);
1763 }
1764}
1765
1680const struct amdgpu_ip_funcs cz_dpm_ip_funcs = { 1766const struct amdgpu_ip_funcs cz_dpm_ip_funcs = {
1681 .early_init = cz_dpm_early_init, 1767 .early_init = cz_dpm_early_init,
1682 .late_init = NULL, 1768 .late_init = cz_dpm_late_init,
1683 .sw_init = cz_dpm_sw_init, 1769 .sw_init = cz_dpm_sw_init,
1684 .sw_fini = cz_dpm_sw_fini, 1770 .sw_fini = cz_dpm_sw_fini,
1685 .hw_init = cz_dpm_hw_init, 1771 .hw_init = cz_dpm_hw_init,
@@ -1707,7 +1793,7 @@ static const struct amdgpu_dpm_funcs cz_dpm_funcs = {
1707 cz_dpm_debugfs_print_current_performance_level, 1793 cz_dpm_debugfs_print_current_performance_level,
1708 .force_performance_level = cz_dpm_force_dpm_level, 1794 .force_performance_level = cz_dpm_force_dpm_level,
1709 .vblank_too_short = NULL, 1795 .vblank_too_short = NULL,
1710 .powergate_uvd = NULL, 1796 .powergate_uvd = cz_dpm_powergate_uvd,
1711}; 1797};
1712 1798
1713static void cz_dpm_set_funcs(struct amdgpu_device *adev) 1799static void cz_dpm_set_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
index ed6449de5dc5..782a74107664 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
@@ -221,6 +221,8 @@ struct cz_power_info {
221 bool uvd_power_down; 221 bool uvd_power_down;
222 bool vce_power_down; 222 bool vce_power_down;
223 bool acp_power_down; 223 bool acp_power_down;
224
225 bool uvd_dynamic_pg;
224}; 226};
225 227
226/* cz_smc.c */ 228/* cz_smc.c */
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 20a159803983..59a073aa42a4 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -1266,7 +1266,7 @@ static int vi_common_early_init(struct amdgpu_device *adev)
1266 case CHIP_CARRIZO: 1266 case CHIP_CARRIZO:
1267 adev->has_uvd = true; 1267 adev->has_uvd = true;
1268 adev->cg_flags = 0; 1268 adev->cg_flags = 0;
1269 adev->pg_flags = 0; 1269 adev->pg_flags = AMDGPU_PG_SUPPORT_UVD;
1270 adev->external_rev_id = adev->rev_id + 0x1; 1270 adev->external_rev_id = adev->rev_id + 0x1;
1271 if (amdgpu_smc_load_fw && smc_enabled) 1271 if (amdgpu_smc_load_fw && smc_enabled)
1272 adev->firmware.smu_load = true; 1272 adev->firmware.smu_load = true;