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