diff options
author | Rex Zhu <Rex.Zhu@amd.com> | 2018-05-16 08:18:22 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-05-24 11:07:52 -0400 |
commit | 22cc6c5e1958e5a08b4c44203d1810ab07ce5a16 (patch) | |
tree | c7d8453d77bece8c1e8425f18bd256718653f27a /drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | |
parent | 61c8e90d965ba944d8b56c29c2c7bb9ec34f45d5 (diff) |
drm/amdgpu: Add runtime VCN PG support
Enable support for dynamically powering up/down VCN on demand.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index dcb60ee0d9e2..110b294ebed3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include "mmhub/mmhub_9_1_offset.h" | 35 | #include "mmhub/mmhub_9_1_offset.h" |
36 | #include "mmhub/mmhub_9_1_sh_mask.h" | 36 | #include "mmhub/mmhub_9_1_sh_mask.h" |
37 | 37 | ||
38 | static int vcn_v1_0_start(struct amdgpu_device *adev); | ||
39 | static int vcn_v1_0_stop(struct amdgpu_device *adev); | 38 | static int vcn_v1_0_stop(struct amdgpu_device *adev); |
40 | static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); | 39 | static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); |
41 | static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); | 40 | static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); |
@@ -146,10 +145,6 @@ static int vcn_v1_0_hw_init(void *handle) | |||
146 | struct amdgpu_ring *ring = &adev->vcn.ring_dec; | 145 | struct amdgpu_ring *ring = &adev->vcn.ring_dec; |
147 | int i, r; | 146 | int i, r; |
148 | 147 | ||
149 | r = vcn_v1_0_start(adev); | ||
150 | if (r) | ||
151 | goto done; | ||
152 | |||
153 | ring->ready = true; | 148 | ring->ready = true; |
154 | r = amdgpu_ring_test_ring(ring); | 149 | r = amdgpu_ring_test_ring(ring); |
155 | if (r) { | 150 | if (r) { |
@@ -185,11 +180,9 @@ static int vcn_v1_0_hw_fini(void *handle) | |||
185 | { | 180 | { |
186 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 181 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
187 | struct amdgpu_ring *ring = &adev->vcn.ring_dec; | 182 | struct amdgpu_ring *ring = &adev->vcn.ring_dec; |
188 | int r; | ||
189 | 183 | ||
190 | r = vcn_v1_0_stop(adev); | 184 | if (RREG32_SOC15(VCN, 0, mmUVD_STATUS)) |
191 | if (r) | 185 | vcn_v1_0_stop(adev); |
192 | return r; | ||
193 | 186 | ||
194 | ring->ready = false; | 187 | ring->ready = false; |
195 | 188 | ||
@@ -769,7 +762,7 @@ static int vcn_v1_0_stop(struct amdgpu_device *adev) | |||
769 | WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2), 0, | 762 | WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2), 0, |
770 | ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); | 763 | ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); |
771 | 764 | ||
772 | /* enable clock gating */ | 765 | WREG32_SOC15(VCN, 0, mmUVD_STATUS, 0); |
773 | 766 | ||
774 | vcn_v1_0_enable_clock_gating(adev); | 767 | vcn_v1_0_enable_clock_gating(adev); |
775 | vcn_1_0_enable_static_power_gating(adev); | 768 | vcn_1_0_enable_static_power_gating(adev); |
@@ -1179,6 +1172,23 @@ static void vcn_v1_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t coun | |||
1179 | } | 1172 | } |
1180 | } | 1173 | } |
1181 | 1174 | ||
1175 | static int vcn_v1_0_set_powergating_state(void *handle, | ||
1176 | enum amd_powergating_state state) | ||
1177 | { | ||
1178 | /* This doesn't actually powergate the VCN block. | ||
1179 | * That's done in the dpm code via the SMC. This | ||
1180 | * just re-inits the block as necessary. The actual | ||
1181 | * gating still happens in the dpm code. We should | ||
1182 | * revisit this when there is a cleaner line between | ||
1183 | * the smc and the hw blocks | ||
1184 | */ | ||
1185 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||
1186 | |||
1187 | if (state == AMD_PG_STATE_GATE) | ||
1188 | return vcn_v1_0_stop(adev); | ||
1189 | else | ||
1190 | return vcn_v1_0_start(adev); | ||
1191 | } | ||
1182 | 1192 | ||
1183 | static const struct amd_ip_funcs vcn_v1_0_ip_funcs = { | 1193 | static const struct amd_ip_funcs vcn_v1_0_ip_funcs = { |
1184 | .name = "vcn_v1_0", | 1194 | .name = "vcn_v1_0", |
@@ -1197,7 +1207,7 @@ static const struct amd_ip_funcs vcn_v1_0_ip_funcs = { | |||
1197 | .soft_reset = NULL /* vcn_v1_0_soft_reset */, | 1207 | .soft_reset = NULL /* vcn_v1_0_soft_reset */, |
1198 | .post_soft_reset = NULL /* vcn_v1_0_post_soft_reset */, | 1208 | .post_soft_reset = NULL /* vcn_v1_0_post_soft_reset */, |
1199 | .set_clockgating_state = vcn_v1_0_set_clockgating_state, | 1209 | .set_clockgating_state = vcn_v1_0_set_clockgating_state, |
1200 | .set_powergating_state = NULL /* vcn_v1_0_set_powergating_state */, | 1210 | .set_powergating_state = vcn_v1_0_set_powergating_state, |
1201 | }; | 1211 | }; |
1202 | 1212 | ||
1203 | static const struct amdgpu_ring_funcs vcn_v1_0_dec_ring_vm_funcs = { | 1213 | static const struct amdgpu_ring_funcs vcn_v1_0_dec_ring_vm_funcs = { |