]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/gpu/drm/radeon/radeon_uvd.c
drm/radeon: only save UVD bo when we have open handles
[linux-imx.git] / drivers / gpu / drm / radeon / radeon_uvd.c
index 41efcec28cd806620961505380e34860644b1f3d..ca0d7358ed33548496c981e68e54f53586434e11 100644 (file)
@@ -56,20 +56,12 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work);
 
 int radeon_uvd_init(struct radeon_device *rdev)
 {
-       struct platform_device *pdev;
        unsigned long bo_size;
        const char *fw_name;
        int i, r;
 
        INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler);
 
-       pdev = platform_device_register_simple("radeon_uvd", 0, NULL, 0);
-       r = IS_ERR(pdev);
-       if (r) {
-               dev_err(rdev->dev, "radeon_uvd: Failed to register firmware\n");
-               return -EINVAL;
-       }
-
        switch (rdev->family) {
        case CHIP_RV710:
        case CHIP_RV730:
@@ -112,16 +104,13 @@ int radeon_uvd_init(struct radeon_device *rdev)
                return -EINVAL;
        }
 
-       r = request_firmware(&rdev->uvd_fw, fw_name, &pdev->dev);
+       r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
        if (r) {
                dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
                        fw_name);
-               platform_device_unregister(pdev);
                return r;
        }
 
-       platform_device_unregister(pdev);
-
        bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
                  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
        r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
@@ -131,16 +120,29 @@ int radeon_uvd_init(struct radeon_device *rdev)
                return r;
        }
 
-       r = radeon_uvd_resume(rdev);
-       if (r)
+       r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
+       if (r) {
+               radeon_bo_unref(&rdev->uvd.vcpu_bo);
+               dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
                return r;
+       }
 
-       memset(rdev->uvd.cpu_addr, 0, bo_size);
-       memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
+       r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
+                         &rdev->uvd.gpu_addr);
+       if (r) {
+               radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+               radeon_bo_unref(&rdev->uvd.vcpu_bo);
+               dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
+               return r;
+       }
 
-       r = radeon_uvd_suspend(rdev);
-       if (r)
+       r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
+       if (r) {
+               dev_err(rdev->dev, "(%d) UVD map failed\n", r);
                return r;
+       }
+
+       radeon_bo_unreserve(rdev->uvd.vcpu_bo);
 
        for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
                atomic_set(&rdev->uvd.handles[i], 0);
@@ -151,71 +153,74 @@ int radeon_uvd_init(struct radeon_device *rdev)
 }
 
 void radeon_uvd_fini(struct radeon_device *rdev)
-{
-       radeon_uvd_suspend(rdev);
-       radeon_bo_unref(&rdev->uvd.vcpu_bo);
-}
-
-int radeon_uvd_suspend(struct radeon_device *rdev)
 {
        int r;
 
        if (rdev->uvd.vcpu_bo == NULL)
-               return 0;
+               return;
 
        r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
        if (!r) {
                radeon_bo_kunmap(rdev->uvd.vcpu_bo);
                radeon_bo_unpin(rdev->uvd.vcpu_bo);
-               rdev->uvd.cpu_addr = NULL;
-               if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) {
-                       radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
-               }
                radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-
-               if (rdev->uvd.cpu_addr) {
-                       radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
-               } else {
-                       rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL;
-               }
        }
-       return r;
+
+       radeon_bo_unref(&rdev->uvd.vcpu_bo);
+
+       release_firmware(rdev->uvd_fw);
+}
+
+int radeon_uvd_suspend(struct radeon_device *rdev)
+{
+       unsigned size;
+       void *ptr;
+       int i;
+
+       if (rdev->uvd.vcpu_bo == NULL)
+               return 0;
+
+       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
+               if (atomic_read(&rdev->uvd.handles[i]))
+                       break;
+
+       if (i == RADEON_MAX_UVD_HANDLES)
+               return 0;
+
+       size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       size -= rdev->uvd_fw->size;
+
+       ptr = rdev->uvd.cpu_addr;
+       ptr += rdev->uvd_fw->size;
+
+       rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
+       memcpy(rdev->uvd.saved_bo, ptr, size);
+
+       return 0;
 }
 
 int radeon_uvd_resume(struct radeon_device *rdev)
 {
-       int r;
+       unsigned size;
+       void *ptr;
 
        if (rdev->uvd.vcpu_bo == NULL)
                return -EINVAL;
 
-       r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
-       if (r) {
-               radeon_bo_unref(&rdev->uvd.vcpu_bo);
-               dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
-               return r;
-       }
-
-       /* Have been pin in cpu unmap unpin */
-       radeon_bo_kunmap(rdev->uvd.vcpu_bo);
-       radeon_bo_unpin(rdev->uvd.vcpu_bo);
+       memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
 
-       r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
-                         &rdev->uvd.gpu_addr);
-       if (r) {
-               radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-               radeon_bo_unref(&rdev->uvd.vcpu_bo);
-               dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
-               return r;
-       }
+       size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       size -= rdev->uvd_fw->size;
 
-       r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
-       if (r) {
-               dev_err(rdev->dev, "(%d) UVD map failed\n", r);
-               return r;
-       }
+       ptr = rdev->uvd.cpu_addr;
+       ptr += rdev->uvd_fw->size;
 
-       radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+       if (rdev->uvd.saved_bo != NULL) {
+               memcpy(ptr, rdev->uvd.saved_bo, size);
+               kfree(rdev->uvd.saved_bo);
+               rdev->uvd.saved_bo = NULL;
+       } else
+               memset(ptr, 0, size);
 
        return 0;
 }