aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0222-drm-amdgpu-enable-uvd-dpm-and-powergating.patch
blob: 43644b8c005fb0807184e053cc5756a198b06738 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
From 564ea7900cffbe2eddb3bcfb09b700ad7942aef4 Mon Sep 17 00:00:00 2001
From: Sonny Jiang <sonny.jiang@amd.com>
Date: Tue, 12 May 2015 16:13:35 -0400
Subject: [PATCH 0222/1050] drm/amdgpu: enable uvd dpm and powergating
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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>
---
 drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 90 ++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/cz_dpm.h |  2 +
 drivers/gpu/drm/amd/amdgpu/vi.c     |  2 +-
 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 adf4dbc..2649b50 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -42,6 +42,8 @@
 #include "bif/bif_5_1_d.h"
 #include "gfx_v8_0.h"
 
+static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate);
+
 static struct cz_ps *cz_get_ps(struct amdgpu_ps *rps)
 {
 	struct cz_ps *ps = rps->ps_priv;
@@ -474,6 +476,7 @@ static int cz_dpm_init(struct amdgpu_device *adev)
 		return ret;
 
 	pi->dpm_enabled = true;
+	pi->uvd_dynamic_pg = false;
 
 	return 0;
 }
@@ -546,6 +549,15 @@ static int cz_dpm_early_init(struct amdgpu_device *adev)
 	return 0;
 }
 
+
+static int cz_dpm_late_init(struct amdgpu_device *adev)
+{
+	/* powerdown unused blocks for now */
+	cz_dpm_powergate_uvd(adev, true);
+
+	return 0;
+}
+
 static int cz_dpm_sw_init(struct amdgpu_device *adev)
 {
 	int ret = 0;
@@ -1260,6 +1272,9 @@ static int cz_dpm_disable(struct amdgpu_device *adev)
 		return -EINVAL;
 	}
 
+	/* powerup blocks */
+	cz_dpm_powergate_uvd(adev, false);
+
 	cz_clear_voting_clients(adev);
 	cz_stop_dpm(adev);
 	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)
 	return pi->sys_info.bootup_uma_clk;
 }
 
+static int cz_enable_uvd_dpm(struct amdgpu_device *adev, bool enable)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	int ret = 0;
+
+	if (enable && pi->caps_uvd_dpm ) {
+		pi->dpm_flags |= DPMFlags_UVD_Enabled;
+		DRM_DEBUG("UVD DPM Enabled.\n");
+
+		ret = cz_send_msg_to_smc_with_parameter(adev,
+			PPSMC_MSG_EnableAllSmuFeatures, UVD_DPM_MASK);
+	} else {
+		pi->dpm_flags &= ~DPMFlags_UVD_Enabled;
+		DRM_DEBUG("UVD DPM Stopped\n");
+
+		ret = cz_send_msg_to_smc_with_parameter(adev,
+			PPSMC_MSG_DisableAllSmuFeatures, UVD_DPM_MASK);
+	}
+
+	return ret;
+}
+
+static int cz_update_uvd_dpm(struct amdgpu_device *adev, bool gate)
+{
+	return cz_enable_uvd_dpm(adev, !gate);
+}
+
+
+static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	int ret;
+
+	if (pi->uvd_power_gated == gate)
+		return;
+
+	pi->uvd_power_gated = gate;
+
+	if (gate) {
+		if (pi->caps_uvd_pg) {
+			/* disable clockgating so we can properly shut down the block */
+			ret = amdgpu_set_clockgating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
+							    AMDGPU_CG_STATE_UNGATE);
+			/* shutdown the UVD block */
+			ret = amdgpu_set_powergating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
+							    AMDGPU_PG_STATE_GATE);
+			/* XXX: check for errors */
+		}
+		cz_update_uvd_dpm(adev, gate);
+		if (pi->caps_uvd_pg)
+			/* power off the UVD block */
+			cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF);
+	} else {
+		if (pi->caps_uvd_pg) {
+			/* power on the UVD block */
+			if (pi->uvd_dynamic_pg)
+				cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1);
+			else
+				cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0);
+			/* re-init the UVD block */
+			ret = amdgpu_set_powergating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
+							    AMDGPU_PG_STATE_UNGATE);
+			/* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
+			ret = amdgpu_set_clockgating_state(adev, AMDGPU_IP_BLOCK_TYPE_UVD,
+							    AMDGPU_CG_STATE_GATE);
+			/* XXX: check for errors */
+		}
+		cz_update_uvd_dpm(adev, gate);
+	}
+}
+
 const struct amdgpu_ip_funcs cz_dpm_ip_funcs = {
 	.early_init = cz_dpm_early_init,
-	.late_init = NULL,
+	.late_init = cz_dpm_late_init,
 	.sw_init = cz_dpm_sw_init,
 	.sw_fini = cz_dpm_sw_fini,
 	.hw_init = cz_dpm_hw_init,
@@ -1707,7 +1793,7 @@ static const struct amdgpu_dpm_funcs cz_dpm_funcs = {
 				cz_dpm_debugfs_print_current_performance_level,
 	.force_performance_level = cz_dpm_force_dpm_level,
 	.vblank_too_short = NULL,
-	.powergate_uvd = NULL,
+	.powergate_uvd = cz_dpm_powergate_uvd,
 };
 
 static 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 ed6449d..782a741 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 {
 	bool uvd_power_down;
 	bool vce_power_down;
 	bool acp_power_down;
+
+	bool uvd_dynamic_pg;
 };
 
 /* cz_smc.c */
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 20a1598..59a073a 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)
 	case CHIP_CARRIZO:
 		adev->has_uvd = true;
 		adev->cg_flags = 0;
-		adev->pg_flags = 0;
+		adev->pg_flags = AMDGPU_PG_SUPPORT_UVD;
 		adev->external_rev_id = adev->rev_id + 0x1;
 		if (amdgpu_smc_load_fw && smc_enabled)
 			adev->firmware.smu_load = true;
-- 
1.9.1