Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[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         GEM_BUG_ON(size != obj->base.size);
36
37         ret = drm_gem_handle_create(file, &obj->base, &handle);
38         /* drop reference from allocate - handle holds it now */
39         i915_gem_object_put(obj);
40         if (ret)
41                 return ret;
42
43         *handle_p = handle;
44         *size_p = size;
45         return 0;
46 }
47
48 int
49 i915_gem_dumb_create(struct drm_file *file,
50                      struct drm_device *dev,
51                      struct drm_mode_create_dumb *args)
52 {
53         enum intel_memory_type mem_type;
54         int cpp = DIV_ROUND_UP(args->bpp, 8);
55         u32 format;
56
57         switch (cpp) {
58         case 1:
59                 format = DRM_FORMAT_C8;
60                 break;
61         case 2:
62                 format = DRM_FORMAT_RGB565;
63                 break;
64         case 4:
65                 format = DRM_FORMAT_XRGB8888;
66                 break;
67         default:
68                 return -EINVAL;
69         }
70
71         /* have to work out size/pitch and return them */
72         args->pitch = ALIGN(args->width * cpp, 64);
73
74         /* align stride to page size so that we can remap */
75         if (args->pitch > intel_plane_fb_max_stride(to_i915(dev), format,
76                                                     DRM_FORMAT_MOD_LINEAR))
77                 args->pitch = ALIGN(args->pitch, 4096);
78
79         if (args->pitch < args->width)
80                 return -EINVAL;
81
82         args->size = mul_u32_u32(args->pitch, args->height);
83
84         mem_type = INTEL_MEMORY_SYSTEM;
85         if (HAS_LMEM(to_i915(dev)))
86                 mem_type = INTEL_MEMORY_LOCAL;
87
88         return i915_gem_create(file,
89                                intel_memory_region_by_type(to_i915(dev),
90                                                            mem_type),
91                                &args->size, &args->handle);
92 }
93
94 /**
95  * Creates a new mm object and returns a handle to it.
96  * @dev: drm device pointer
97  * @data: ioctl data blob
98  * @file: drm file pointer
99  */
100 int
101 i915_gem_create_ioctl(struct drm_device *dev, void *data,
102                       struct drm_file *file)
103 {
104         struct drm_i915_private *i915 = to_i915(dev);
105         struct drm_i915_gem_create *args = data;
106
107         i915_gem_flush_free_objects(i915);
108
109         return i915_gem_create(file,
110                                intel_memory_region_by_type(i915,
111                                                            INTEL_MEMORY_SYSTEM),
112                                &args->size, &args->handle);
113 }