diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index c1a581044417..338da80006b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | |||
@@ -241,32 +241,28 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) | |||
241 | 241 | ||
242 | int amdgpu_uvd_suspend(struct amdgpu_device *adev) | 242 | int amdgpu_uvd_suspend(struct amdgpu_device *adev) |
243 | { | 243 | { |
244 | struct amdgpu_ring *ring = &adev->uvd.ring; | 244 | unsigned size; |
245 | int i, r; | 245 | void *ptr; |
246 | int i; | ||
246 | 247 | ||
247 | if (adev->uvd.vcpu_bo == NULL) | 248 | if (adev->uvd.vcpu_bo == NULL) |
248 | return 0; | 249 | return 0; |
249 | 250 | ||
250 | for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) { | 251 | for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) |
251 | uint32_t handle = atomic_read(&adev->uvd.handles[i]); | 252 | if (atomic_read(&adev->uvd.handles[i])) |
252 | if (handle != 0) { | 253 | break; |
253 | struct fence *fence; | ||
254 | 254 | ||
255 | amdgpu_uvd_note_usage(adev); | 255 | if (i == AMDGPU_MAX_UVD_HANDLES) |
256 | return 0; | ||
256 | 257 | ||
257 | r = amdgpu_uvd_get_destroy_msg(ring, handle, false, &fence); | 258 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); |
258 | if (r) { | 259 | ptr = adev->uvd.cpu_addr; |
259 | DRM_ERROR("Error destroying UVD (%d)!\n", r); | ||
260 | continue; | ||
261 | } | ||
262 | 260 | ||
263 | fence_wait(fence, false); | 261 | adev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); |
264 | fence_put(fence); | 262 | if (!adev->uvd.saved_bo) |
263 | return -ENOMEM; | ||
265 | 264 | ||
266 | adev->uvd.filp[i] = NULL; | 265 | memcpy(adev->uvd.saved_bo, ptr, size); |
267 | atomic_set(&adev->uvd.handles[i], 0); | ||
268 | } | ||
269 | } | ||
270 | 266 | ||
271 | return 0; | 267 | return 0; |
272 | } | 268 | } |
@@ -275,23 +271,29 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev) | |||
275 | { | 271 | { |
276 | unsigned size; | 272 | unsigned size; |
277 | void *ptr; | 273 | void *ptr; |
278 | const struct common_firmware_header *hdr; | ||
279 | unsigned offset; | ||
280 | 274 | ||
281 | if (adev->uvd.vcpu_bo == NULL) | 275 | if (adev->uvd.vcpu_bo == NULL) |
282 | return -EINVAL; | 276 | return -EINVAL; |
283 | 277 | ||
284 | hdr = (const struct common_firmware_header *)adev->uvd.fw->data; | ||
285 | offset = le32_to_cpu(hdr->ucode_array_offset_bytes); | ||
286 | memcpy(adev->uvd.cpu_addr, (adev->uvd.fw->data) + offset, | ||
287 | (adev->uvd.fw->size) - offset); | ||
288 | |||
289 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); | 278 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); |
290 | size -= le32_to_cpu(hdr->ucode_size_bytes); | ||
291 | ptr = adev->uvd.cpu_addr; | 279 | ptr = adev->uvd.cpu_addr; |
292 | ptr += le32_to_cpu(hdr->ucode_size_bytes); | ||
293 | 280 | ||
294 | memset(ptr, 0, size); | 281 | if (adev->uvd.saved_bo != NULL) { |
282 | memcpy(ptr, adev->uvd.saved_bo, size); | ||
283 | kfree(adev->uvd.saved_bo); | ||
284 | adev->uvd.saved_bo = NULL; | ||
285 | } else { | ||
286 | const struct common_firmware_header *hdr; | ||
287 | unsigned offset; | ||
288 | |||
289 | hdr = (const struct common_firmware_header *)adev->uvd.fw->data; | ||
290 | offset = le32_to_cpu(hdr->ucode_array_offset_bytes); | ||
291 | memcpy(adev->uvd.cpu_addr, (adev->uvd.fw->data) + offset, | ||
292 | (adev->uvd.fw->size) - offset); | ||
293 | size -= le32_to_cpu(hdr->ucode_size_bytes); | ||
294 | ptr += le32_to_cpu(hdr->ucode_size_bytes); | ||
295 | memset(ptr, 0, size); | ||
296 | } | ||
295 | 297 | ||
296 | return 0; | 298 | return 0; |
297 | } | 299 | } |