1 // SPDX-License-Identifier: MIT 2 /* Copyright © 2024 Intel Corporation */ 3 4 #include <linux/fb.h> 5 6 #include <drm/drm_gem.h> 7 #include <drm/intel/display_parent_interface.h> 8 9 #include "intel_fb.h" 10 #include "xe_bo.h" 11 #include "xe_display_bo.h" 12 #include "xe_pxp.h" 13 #include "xe_ttm_stolen_mgr.h" 14 #include "xe_wa.h" 15 16 #include <generated/xe_device_wa_oob.h> 17 18 static bool xe_display_bo_is_protected(struct drm_gem_object *obj) 19 { 20 return xe_bo_is_protected(gem_to_xe_bo(obj)); 21 } 22 23 static int xe_display_bo_read_from_page(struct drm_gem_object *obj, u64 offset, void *dst, int size) 24 { 25 struct xe_bo *bo = gem_to_xe_bo(obj); 26 27 return xe_bo_read(bo, offset, dst, size); 28 } 29 30 static int xe_display_bo_framebuffer_init(struct drm_gem_object *obj, 31 struct drm_mode_fb_cmd2 *mode_cmd) 32 { 33 struct xe_bo *bo = gem_to_xe_bo(obj); 34 struct xe_device *xe = to_xe_device(bo->ttm.base.dev); 35 int ret; 36 37 /* 38 * Some modifiers require physical alignment of 64KiB VRAM pages; 39 * require that the BO in those cases is created correctly. 40 */ 41 if (XE_IOCTL_DBG(xe, intel_fb_needs_64k_phys(mode_cmd->modifier[0]) && 42 !(bo->flags & XE_BO_FLAG_NEEDS_64K))) 43 return -EINVAL; 44 45 xe_bo_get(bo); 46 47 ret = ttm_bo_reserve(&bo->ttm, true, false, NULL); 48 if (ret) 49 goto err; 50 51 if (!(bo->flags & XE_BO_FLAG_FORCE_WC)) { 52 /* 53 * XE_BO_FLAG_FORCE_WC should ideally be set at creation, or is 54 * automatically set when creating FB. We cannot change caching 55 * mode when the bo is VM_BINDed, so we can only set 56 * coherency with display when unbound. 57 */ 58 if (XE_IOCTL_DBG(xe, xe_bo_is_vm_bound(bo))) { 59 ttm_bo_unreserve(&bo->ttm); 60 ret = -EINVAL; 61 goto err; 62 } 63 bo->flags |= XE_BO_FLAG_FORCE_WC; 64 } 65 ttm_bo_unreserve(&bo->ttm); 66 return 0; 67 68 err: 69 xe_bo_put(bo); 70 return ret; 71 } 72 73 static void xe_display_bo_framebuffer_fini(struct drm_gem_object *obj) 74 { 75 struct xe_bo *bo = gem_to_xe_bo(obj); 76 77 if (bo->flags & XE_BO_FLAG_PINNED) { 78 /* Unpin our kernel fb first */ 79 xe_bo_lock(bo, false); 80 xe_bo_unpin(bo); 81 xe_bo_unlock(bo); 82 } 83 xe_bo_put(bo); 84 } 85 86 static struct drm_gem_object * 87 xe_display_bo_framebuffer_lookup(struct drm_device *drm, 88 struct drm_file *filp, 89 const struct drm_mode_fb_cmd2 *mode_cmd) 90 { 91 struct xe_device *xe = to_xe_device(drm); 92 struct xe_bo *bo; 93 struct drm_gem_object *gem = drm_gem_object_lookup(filp, mode_cmd->handles[0]); 94 95 if (!gem) 96 return ERR_PTR(-ENOENT); 97 98 bo = gem_to_xe_bo(gem); 99 /* Require vram placement or dma-buf import */ 100 if (IS_DGFX(xe) && 101 !xe_bo_can_migrate(bo, XE_PL_VRAM0) && 102 bo->ttm.type != ttm_bo_type_sg) { 103 drm_gem_object_put(gem); 104 return ERR_PTR(-EREMOTE); 105 } 106 107 return gem; 108 } 109 110 #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) 111 /* 112 * FIXME: There shouldn't be any reason to have XE_PAGE_SIZE stride 113 * alignment. The same 64 as i915 uses should be fine, and we shouldn't need to 114 * have driver specific values. However, dropping the stride alignment to 64 115 * leads to underflowing the bo pin count in the atomic cleanup work. 116 */ 117 static u32 xe_display_bo_fbdev_pitch_align(u32 stride) 118 { 119 return ALIGN(stride, XE_PAGE_SIZE); 120 } 121 122 bool xe_display_bo_fbdev_prefer_stolen(struct xe_device *xe, unsigned int size) 123 { 124 struct ttm_resource_manager *stolen; 125 126 stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); 127 if (!stolen) 128 return false; 129 130 if (IS_DGFX(xe)) 131 return false; 132 133 if (XE_DEVICE_WA(xe, 22019338487_display)) 134 return false; 135 136 /* 137 * If the FB is too big, just don't use it since fbdev is not very 138 * important and we should probably use that space with FBC or other 139 * features. 140 */ 141 return stolen->size >= (size * 2) >> PAGE_SHIFT; 142 } 143 144 static struct drm_gem_object *xe_display_bo_fbdev_create(struct drm_device *drm, int size) 145 { 146 struct xe_device *xe = to_xe_device(drm); 147 struct xe_bo *obj; 148 149 obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size, 150 ttm_bo_type_kernel, 151 XE_BO_FLAG_FORCE_WC | 152 XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | 153 XE_BO_FLAG_GGTT, 154 false); 155 if (IS_ERR(obj)) { 156 drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj); 157 return ERR_PTR(-ENOMEM); 158 } 159 160 return &obj->ttm.base; 161 } 162 163 static void xe_display_bo_fbdev_destroy(struct drm_gem_object *obj) 164 { 165 xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj)); 166 } 167 168 static int xe_display_bo_fbdev_fill_info(struct drm_gem_object *_obj, struct fb_info *info, 169 struct i915_vma *vma) 170 { 171 struct xe_bo *obj = gem_to_xe_bo(_obj); 172 struct pci_dev *pdev = to_pci_dev(_obj->dev->dev); 173 174 if (!(obj->flags & XE_BO_FLAG_SYSTEM)) { 175 if (obj->flags & XE_BO_FLAG_STOLEN) 176 info->fix.smem_start = xe_ttm_stolen_io_offset(obj, 0); 177 else 178 info->fix.smem_start = 179 pci_resource_start(pdev, 2) + 180 xe_bo_addr(obj, 0, XE_PAGE_SIZE); 181 182 info->fix.smem_len = obj->ttm.base.size; 183 } else { 184 /* XXX: Pure fiction, as the BO may not be physically accessible.. */ 185 info->fix.smem_start = 0; 186 info->fix.smem_len = obj->ttm.base.size; 187 } 188 XE_WARN_ON(iosys_map_is_null(&obj->vmap)); 189 190 info->screen_base = obj->vmap.vaddr_iomem; 191 info->screen_size = obj->ttm.base.size; 192 193 return 0; 194 } 195 #endif 196 197 const struct intel_display_bo_interface xe_display_bo_interface = { 198 .is_protected = xe_display_bo_is_protected, 199 .key_check = xe_pxp_obj_key_check, 200 .fb_mmap = drm_gem_prime_mmap, 201 .read_from_page = xe_display_bo_read_from_page, 202 .framebuffer_init = xe_display_bo_framebuffer_init, 203 .framebuffer_fini = xe_display_bo_framebuffer_fini, 204 .framebuffer_lookup = xe_display_bo_framebuffer_lookup, 205 #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) 206 .fbdev_create = xe_display_bo_fbdev_create, 207 .fbdev_destroy = xe_display_bo_fbdev_destroy, 208 .fbdev_fill_info = xe_display_bo_fbdev_fill_info, 209 .fbdev_pitch_align = xe_display_bo_fbdev_pitch_align, 210 #endif 211 }; 212