ce923ed49eeee2959dafec486f4ac8459047ca6a
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / gem / i915_gem_create.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5
6 #include "gem/i915_gem_ioctls.h"
7 #include "gem/i915_gem_region.h"
8
9 #include "i915_drv.h"
10
11 static int
12 i915_gem_create(struct drm_file *file,
13                 struct intel_memory_region *mr,
14                 u64 *size_p,
15                 u32 *handle_p)
16 {
17         struct drm_i915_gem_object *obj;
18         u32 handle;
19         u64 size;
20         int ret;
21
22         GEM_BUG_ON(!is_power_of_2(mr->min_page_size));
23         size = round_up(*size_p, mr->min_page_size);
24         if (size == 0)
25                 return -EINVAL;
26
27         /* For most of the ABI (e.g. mmap) we think in system pages */
28         GEM_BUG_ON(!IS_ALIGNED(size, PAGE_SIZE));
29
30         /* Allocate the new object */
31         obj = i915_gem_object_create_region(mr, size, 0);
32         if (IS_ERR(obj))
33                 return PTR_ERR(obj);
34
35         ret = drm_gem_handle_create(file, &obj->base, &handle);
36         /* drop reference from allocate - handle holds it now */
37         i915_gem_object_put(obj);
38         if (ret)
39                 return ret;
40
41         *handle_p = handle;
42         *size_p = size;
43         return 0;
44 }
45
46 int
47 i915_gem_dumb_create(struct drm_file *file,
48                      struct drm_device *dev,
49                      struct drm_mode_create_dumb *args)
50 {
51         enum intel_memory_type mem_type;
52         int cpp = DIV_ROUND_UP(args->bpp, 8);
53         u32 format;
54
55         switch (cpp) {
56         case 1:
57                 format = DRM_FORMAT_C8;
58                 break;
59         case 2:
60                 format = DRM_FORMAT_RGB565;
61                 break;
62         case 4:
63                 format = DRM_FORMAT_XRGB8888;
64                 break;
65         default:
66                 return -EINVAL;
67         }
68
69         /* have to work out size/pitch and return them */
70         args->pitch = ALIGN(args->width * cpp, 64);
71
72         /* align stride to page size so that we can remap */
73         if (args->pitch > intel_plane_fb_max_stride(to_i915(dev), format,
74                                                     DRM_FORMAT_MOD_LINEAR))
75                 args->pitch = ALIGN(args->pitch, 4096);
76
77         if (args->pitch < args->width)
78                 return -EINVAL;
79
80         args->size = mul_u32_u32(args->pitch, args->height);
81
82         mem_type = INTEL_MEMORY_SYSTEM;
83         if (HAS_LMEM(to_i915(dev)))
84                 mem_type = INTEL_MEMORY_LOCAL;
85
86         return i915_gem_create(file,
87                                intel_memory_region_by_type(to_i915(dev),
88                                                            mem_type),
89                                &args->size, &args->handle);
90 }
91
92 /**
93  * Creates a new mm object and returns a handle to it.
94  * @dev: drm device pointer
95  * @data: ioctl data blob
96  * @file: drm file pointer
97  */
98 int
99 i915_gem_create_ioctl(struct drm_device *dev, void *data,
100                       struct drm_file *file)
101 {
102         struct drm_i915_private *i915 = to_i915(dev);
103         struct drm_i915_gem_create *args = data;
104
105         i915_gem_flush_free_objects(i915);
106
107         return i915_gem_create(file,
108                                intel_memory_region_by_type(i915,
109                                                            INTEL_MEMORY_SYSTEM),
110                                &args->size, &args->handle);
111 }