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.c63
1 files changed, 35 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..871018c634e0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -158,6 +158,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
158 DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n", 158 DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
159 version_major, version_minor, family_id); 159 version_major, version_minor, family_id);
160 160
161 adev->uvd.fw_version = ((version_major << 24) | (version_minor << 16) |
162 (family_id << 8));
163
161 bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8) 164 bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8)
162 + AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE; 165 + AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE;
163 r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true, 166 r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true,
@@ -241,32 +244,30 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
241 244
242int amdgpu_uvd_suspend(struct amdgpu_device *adev) 245int amdgpu_uvd_suspend(struct amdgpu_device *adev)
243{ 246{
244 struct amdgpu_ring *ring = &adev->uvd.ring; 247 unsigned size;
245 int i, r; 248 void *ptr;
249 int i;
246 250
247 if (adev->uvd.vcpu_bo == NULL) 251 if (adev->uvd.vcpu_bo == NULL)
248 return 0; 252 return 0;
249 253
250 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) { 254 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
251 uint32_t handle = atomic_read(&adev->uvd.handles[i]); 255 if (atomic_read(&adev->uvd.handles[i]))
252 if (handle != 0) { 256 break;
253 struct fence *fence;
254 257
255 amdgpu_uvd_note_usage(adev); 258 if (i == AMDGPU_MAX_UVD_HANDLES)
259 return 0;
256 260
257 r = amdgpu_uvd_get_destroy_msg(ring, handle, false, &fence); 261 cancel_delayed_work_sync(&adev->uvd.idle_work);
258 if (r) {
259 DRM_ERROR("Error destroying UVD (%d)!\n", r);
260 continue;
261 }
262 262
263 fence_wait(fence, false); 263 size = amdgpu_bo_size(adev->uvd.vcpu_bo);
264 fence_put(fence); 264 ptr = adev->uvd.cpu_addr;
265 265
266 adev->uvd.filp[i] = NULL; 266 adev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
267 atomic_set(&adev->uvd.handles[i], 0); 267 if (!adev->uvd.saved_bo)
268 } 268 return -ENOMEM;
269 } 269
270 memcpy(adev->uvd.saved_bo, ptr, size);
270 271
271 return 0; 272 return 0;
272} 273}
@@ -275,23 +276,29 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
275{ 276{
276 unsigned size; 277 unsigned size;
277 void *ptr; 278 void *ptr;
278 const struct common_firmware_header *hdr;
279 unsigned offset;
280 279
281 if (adev->uvd.vcpu_bo == NULL) 280 if (adev->uvd.vcpu_bo == NULL)
282 return -EINVAL; 281 return -EINVAL;
283 282
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); 283 size = amdgpu_bo_size(adev->uvd.vcpu_bo);
290 size -= le32_to_cpu(hdr->ucode_size_bytes);
291 ptr = adev->uvd.cpu_addr; 284 ptr = adev->uvd.cpu_addr;
292 ptr += le32_to_cpu(hdr->ucode_size_bytes);
293 285
294 memset(ptr, 0, size); 286 if (adev->uvd.saved_bo != NULL) {
287 memcpy(ptr, adev->uvd.saved_bo, size);
288 kfree(adev->uvd.saved_bo);
289 adev->uvd.saved_bo = NULL;
290 } else {
291 const struct common_firmware_header *hdr;
292 unsigned offset;
293
294 hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
295 offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
296 memcpy(adev->uvd.cpu_addr, (adev->uvd.fw->data) + offset,
297 (adev->uvd.fw->size) - offset);
298 size -= le32_to_cpu(hdr->ucode_size_bytes);
299 ptr += le32_to_cpu(hdr->ucode_size_bytes);
300 memset(ptr, 0, size);
301 }
295 302
296 return 0; 303 return 0;
297} 304}