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 }
114