aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c58
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
242int amdgpu_uvd_suspend(struct amdgpu_device *adev) 242int 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}