diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 63 |
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 | ||
242 | int amdgpu_uvd_suspend(struct amdgpu_device *adev) | 245 | int 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 | } |