.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Hisilicon Hibmc SoC drm driver |
---|
2 | 3 | * |
---|
3 | 4 | * Based on the bochs drm driver. |
---|
.. | .. |
---|
8 | 9 | * Rongrong Zou <zourongrong@huawei.com> |
---|
9 | 10 | * Rongrong Zou <zourongrong@gmail.com> |
---|
10 | 11 | * Jianhua Li <lijianhua@huawei.com> |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License as published by |
---|
14 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
15 | | - * (at your option) any later version. |
---|
16 | | - * |
---|
17 | 12 | */ |
---|
18 | 13 | |
---|
| 14 | +#include <linux/pci.h> |
---|
| 15 | + |
---|
19 | 16 | #include <drm/drm_atomic_helper.h> |
---|
20 | | -#include <drm/ttm/ttm_page_alloc.h> |
---|
| 17 | +#include <drm/drm_gem.h> |
---|
| 18 | +#include <drm/drm_gem_framebuffer_helper.h> |
---|
| 19 | +#include <drm/drm_gem_vram_helper.h> |
---|
| 20 | +#include <drm/drm_print.h> |
---|
21 | 21 | |
---|
22 | 22 | #include "hibmc_drm_drv.h" |
---|
23 | 23 | |
---|
24 | | -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) |
---|
25 | | - |
---|
26 | | -static inline struct hibmc_drm_private * |
---|
27 | | -hibmc_bdev(struct ttm_bo_device *bd) |
---|
28 | | -{ |
---|
29 | | - return container_of(bd, struct hibmc_drm_private, bdev); |
---|
30 | | -} |
---|
31 | | - |
---|
32 | | -static int |
---|
33 | | -hibmc_ttm_mem_global_init(struct drm_global_reference *ref) |
---|
34 | | -{ |
---|
35 | | - return ttm_mem_global_init(ref->object); |
---|
36 | | -} |
---|
37 | | - |
---|
38 | | -static void |
---|
39 | | -hibmc_ttm_mem_global_release(struct drm_global_reference *ref) |
---|
40 | | -{ |
---|
41 | | - ttm_mem_global_release(ref->object); |
---|
42 | | -} |
---|
43 | | - |
---|
44 | | -static int hibmc_ttm_global_init(struct hibmc_drm_private *hibmc) |
---|
45 | | -{ |
---|
46 | | - int ret; |
---|
47 | | - |
---|
48 | | - hibmc->mem_global_ref.global_type = DRM_GLOBAL_TTM_MEM; |
---|
49 | | - hibmc->mem_global_ref.size = sizeof(struct ttm_mem_global); |
---|
50 | | - hibmc->mem_global_ref.init = &hibmc_ttm_mem_global_init; |
---|
51 | | - hibmc->mem_global_ref.release = &hibmc_ttm_mem_global_release; |
---|
52 | | - ret = drm_global_item_ref(&hibmc->mem_global_ref); |
---|
53 | | - if (ret) { |
---|
54 | | - DRM_ERROR("could not get ref on ttm global: %d\n", ret); |
---|
55 | | - return ret; |
---|
56 | | - } |
---|
57 | | - |
---|
58 | | - hibmc->bo_global_ref.mem_glob = |
---|
59 | | - hibmc->mem_global_ref.object; |
---|
60 | | - hibmc->bo_global_ref.ref.global_type = DRM_GLOBAL_TTM_BO; |
---|
61 | | - hibmc->bo_global_ref.ref.size = sizeof(struct ttm_bo_global); |
---|
62 | | - hibmc->bo_global_ref.ref.init = &ttm_bo_global_init; |
---|
63 | | - hibmc->bo_global_ref.ref.release = &ttm_bo_global_release; |
---|
64 | | - ret = drm_global_item_ref(&hibmc->bo_global_ref.ref); |
---|
65 | | - if (ret) { |
---|
66 | | - DRM_ERROR("failed setting up TTM BO subsystem: %d\n", ret); |
---|
67 | | - drm_global_item_unref(&hibmc->mem_global_ref); |
---|
68 | | - return ret; |
---|
69 | | - } |
---|
70 | | - return 0; |
---|
71 | | -} |
---|
72 | | - |
---|
73 | | -static void |
---|
74 | | -hibmc_ttm_global_release(struct hibmc_drm_private *hibmc) |
---|
75 | | -{ |
---|
76 | | - drm_global_item_unref(&hibmc->bo_global_ref.ref); |
---|
77 | | - drm_global_item_unref(&hibmc->mem_global_ref); |
---|
78 | | - hibmc->mem_global_ref.release = NULL; |
---|
79 | | -} |
---|
80 | | - |
---|
81 | | -static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo) |
---|
82 | | -{ |
---|
83 | | - struct hibmc_bo *bo = container_of(tbo, struct hibmc_bo, bo); |
---|
84 | | - |
---|
85 | | - drm_gem_object_release(&bo->gem); |
---|
86 | | - kfree(bo); |
---|
87 | | -} |
---|
88 | | - |
---|
89 | | -static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo) |
---|
90 | | -{ |
---|
91 | | - return bo->destroy == &hibmc_bo_ttm_destroy; |
---|
92 | | -} |
---|
93 | | - |
---|
94 | | -static int |
---|
95 | | -hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, |
---|
96 | | - struct ttm_mem_type_manager *man) |
---|
97 | | -{ |
---|
98 | | - switch (type) { |
---|
99 | | - case TTM_PL_SYSTEM: |
---|
100 | | - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; |
---|
101 | | - man->available_caching = TTM_PL_MASK_CACHING; |
---|
102 | | - man->default_caching = TTM_PL_FLAG_CACHED; |
---|
103 | | - break; |
---|
104 | | - case TTM_PL_VRAM: |
---|
105 | | - man->func = &ttm_bo_manager_func; |
---|
106 | | - man->flags = TTM_MEMTYPE_FLAG_FIXED | |
---|
107 | | - TTM_MEMTYPE_FLAG_MAPPABLE; |
---|
108 | | - man->available_caching = TTM_PL_FLAG_UNCACHED | |
---|
109 | | - TTM_PL_FLAG_WC; |
---|
110 | | - man->default_caching = TTM_PL_FLAG_WC; |
---|
111 | | - break; |
---|
112 | | - default: |
---|
113 | | - DRM_ERROR("unsupported memory type %u\n", type); |
---|
114 | | - return -EINVAL; |
---|
115 | | - } |
---|
116 | | - return 0; |
---|
117 | | -} |
---|
118 | | - |
---|
119 | | -void hibmc_ttm_placement(struct hibmc_bo *bo, int domain) |
---|
120 | | -{ |
---|
121 | | - u32 count = 0; |
---|
122 | | - u32 i; |
---|
123 | | - |
---|
124 | | - bo->placement.placement = bo->placements; |
---|
125 | | - bo->placement.busy_placement = bo->placements; |
---|
126 | | - if (domain & TTM_PL_FLAG_VRAM) |
---|
127 | | - bo->placements[count++].flags = TTM_PL_FLAG_WC | |
---|
128 | | - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; |
---|
129 | | - if (domain & TTM_PL_FLAG_SYSTEM) |
---|
130 | | - bo->placements[count++].flags = TTM_PL_MASK_CACHING | |
---|
131 | | - TTM_PL_FLAG_SYSTEM; |
---|
132 | | - if (!count) |
---|
133 | | - bo->placements[count++].flags = TTM_PL_MASK_CACHING | |
---|
134 | | - TTM_PL_FLAG_SYSTEM; |
---|
135 | | - |
---|
136 | | - bo->placement.num_placement = count; |
---|
137 | | - bo->placement.num_busy_placement = count; |
---|
138 | | - for (i = 0; i < count; i++) { |
---|
139 | | - bo->placements[i].fpfn = 0; |
---|
140 | | - bo->placements[i].lpfn = 0; |
---|
141 | | - } |
---|
142 | | -} |
---|
143 | | - |
---|
144 | | -static void |
---|
145 | | -hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) |
---|
146 | | -{ |
---|
147 | | - struct hibmc_bo *hibmcbo = hibmc_bo(bo); |
---|
148 | | - |
---|
149 | | - if (!hibmc_ttm_bo_is_hibmc_bo(bo)) |
---|
150 | | - return; |
---|
151 | | - |
---|
152 | | - hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM); |
---|
153 | | - *pl = hibmcbo->placement; |
---|
154 | | -} |
---|
155 | | - |
---|
156 | | -static int hibmc_bo_verify_access(struct ttm_buffer_object *bo, |
---|
157 | | - struct file *filp) |
---|
158 | | -{ |
---|
159 | | - struct hibmc_bo *hibmcbo = hibmc_bo(bo); |
---|
160 | | - |
---|
161 | | - return drm_vma_node_verify_access(&hibmcbo->gem.vma_node, |
---|
162 | | - filp->private_data); |
---|
163 | | -} |
---|
164 | | - |
---|
165 | | -static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev, |
---|
166 | | - struct ttm_mem_reg *mem) |
---|
167 | | -{ |
---|
168 | | - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; |
---|
169 | | - struct hibmc_drm_private *hibmc = hibmc_bdev(bdev); |
---|
170 | | - |
---|
171 | | - mem->bus.addr = NULL; |
---|
172 | | - mem->bus.offset = 0; |
---|
173 | | - mem->bus.size = mem->num_pages << PAGE_SHIFT; |
---|
174 | | - mem->bus.base = 0; |
---|
175 | | - mem->bus.is_iomem = false; |
---|
176 | | - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) |
---|
177 | | - return -EINVAL; |
---|
178 | | - switch (mem->mem_type) { |
---|
179 | | - case TTM_PL_SYSTEM: |
---|
180 | | - /* system memory */ |
---|
181 | | - return 0; |
---|
182 | | - case TTM_PL_VRAM: |
---|
183 | | - mem->bus.offset = mem->start << PAGE_SHIFT; |
---|
184 | | - mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0); |
---|
185 | | - mem->bus.is_iomem = true; |
---|
186 | | - break; |
---|
187 | | - default: |
---|
188 | | - return -EINVAL; |
---|
189 | | - } |
---|
190 | | - return 0; |
---|
191 | | -} |
---|
192 | | - |
---|
193 | | -static void hibmc_ttm_backend_destroy(struct ttm_tt *tt) |
---|
194 | | -{ |
---|
195 | | - ttm_tt_fini(tt); |
---|
196 | | - kfree(tt); |
---|
197 | | -} |
---|
198 | | - |
---|
199 | | -static struct ttm_backend_func hibmc_tt_backend_func = { |
---|
200 | | - .destroy = &hibmc_ttm_backend_destroy, |
---|
201 | | -}; |
---|
202 | | - |
---|
203 | | -static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_buffer_object *bo, |
---|
204 | | - u32 page_flags) |
---|
205 | | -{ |
---|
206 | | - struct ttm_tt *tt; |
---|
207 | | - int ret; |
---|
208 | | - |
---|
209 | | - tt = kzalloc(sizeof(*tt), GFP_KERNEL); |
---|
210 | | - if (!tt) { |
---|
211 | | - DRM_ERROR("failed to allocate ttm_tt\n"); |
---|
212 | | - return NULL; |
---|
213 | | - } |
---|
214 | | - tt->func = &hibmc_tt_backend_func; |
---|
215 | | - ret = ttm_tt_init(tt, bo, page_flags); |
---|
216 | | - if (ret) { |
---|
217 | | - DRM_ERROR("failed to initialize ttm_tt: %d\n", ret); |
---|
218 | | - kfree(tt); |
---|
219 | | - return NULL; |
---|
220 | | - } |
---|
221 | | - return tt; |
---|
222 | | -} |
---|
223 | | - |
---|
224 | | -struct ttm_bo_driver hibmc_bo_driver = { |
---|
225 | | - .ttm_tt_create = hibmc_ttm_tt_create, |
---|
226 | | - .init_mem_type = hibmc_bo_init_mem_type, |
---|
227 | | - .evict_flags = hibmc_bo_evict_flags, |
---|
228 | | - .move = NULL, |
---|
229 | | - .verify_access = hibmc_bo_verify_access, |
---|
230 | | - .io_mem_reserve = &hibmc_ttm_io_mem_reserve, |
---|
231 | | - .io_mem_free = NULL, |
---|
232 | | -}; |
---|
233 | | - |
---|
234 | 24 | int hibmc_mm_init(struct hibmc_drm_private *hibmc) |
---|
235 | 25 | { |
---|
| 26 | + struct drm_vram_mm *vmm; |
---|
236 | 27 | int ret; |
---|
237 | 28 | struct drm_device *dev = hibmc->dev; |
---|
238 | | - struct ttm_bo_device *bdev = &hibmc->bdev; |
---|
239 | 29 | |
---|
240 | | - ret = hibmc_ttm_global_init(hibmc); |
---|
241 | | - if (ret) |
---|
242 | | - return ret; |
---|
243 | | - |
---|
244 | | - ret = ttm_bo_device_init(&hibmc->bdev, |
---|
245 | | - hibmc->bo_global_ref.ref.object, |
---|
246 | | - &hibmc_bo_driver, |
---|
247 | | - dev->anon_inode->i_mapping, |
---|
248 | | - DRM_FILE_PAGE_OFFSET, |
---|
249 | | - true); |
---|
250 | | - if (ret) { |
---|
251 | | - hibmc_ttm_global_release(hibmc); |
---|
252 | | - DRM_ERROR("error initializing bo driver: %d\n", ret); |
---|
| 30 | + vmm = drm_vram_helper_alloc_mm(dev, |
---|
| 31 | + pci_resource_start(dev->pdev, 0), |
---|
| 32 | + hibmc->fb_size); |
---|
| 33 | + if (IS_ERR(vmm)) { |
---|
| 34 | + ret = PTR_ERR(vmm); |
---|
| 35 | + drm_err(dev, "Error initializing VRAM MM; %d\n", ret); |
---|
253 | 36 | return ret; |
---|
254 | 37 | } |
---|
255 | 38 | |
---|
256 | | - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, |
---|
257 | | - hibmc->fb_size >> PAGE_SHIFT); |
---|
258 | | - if (ret) { |
---|
259 | | - hibmc_ttm_global_release(hibmc); |
---|
260 | | - DRM_ERROR("failed ttm VRAM init: %d\n", ret); |
---|
261 | | - return ret; |
---|
262 | | - } |
---|
263 | | - |
---|
264 | | - hibmc->mm_inited = true; |
---|
265 | 39 | return 0; |
---|
266 | 40 | } |
---|
267 | 41 | |
---|
268 | 42 | void hibmc_mm_fini(struct hibmc_drm_private *hibmc) |
---|
269 | 43 | { |
---|
270 | | - if (!hibmc->mm_inited) |
---|
| 44 | + if (!hibmc->dev->vram_mm) |
---|
271 | 45 | return; |
---|
272 | 46 | |
---|
273 | | - ttm_bo_device_release(&hibmc->bdev); |
---|
274 | | - hibmc_ttm_global_release(hibmc); |
---|
275 | | - hibmc->mm_inited = false; |
---|
276 | | -} |
---|
277 | | - |
---|
278 | | -static void hibmc_bo_unref(struct hibmc_bo **bo) |
---|
279 | | -{ |
---|
280 | | - struct ttm_buffer_object *tbo; |
---|
281 | | - |
---|
282 | | - if ((*bo) == NULL) |
---|
283 | | - return; |
---|
284 | | - |
---|
285 | | - tbo = &((*bo)->bo); |
---|
286 | | - ttm_bo_unref(&tbo); |
---|
287 | | - *bo = NULL; |
---|
288 | | -} |
---|
289 | | - |
---|
290 | | -int hibmc_bo_create(struct drm_device *dev, int size, int align, |
---|
291 | | - u32 flags, struct hibmc_bo **phibmcbo) |
---|
292 | | -{ |
---|
293 | | - struct hibmc_drm_private *hibmc = dev->dev_private; |
---|
294 | | - struct hibmc_bo *hibmcbo; |
---|
295 | | - size_t acc_size; |
---|
296 | | - int ret; |
---|
297 | | - |
---|
298 | | - hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL); |
---|
299 | | - if (!hibmcbo) { |
---|
300 | | - DRM_ERROR("failed to allocate hibmcbo\n"); |
---|
301 | | - return -ENOMEM; |
---|
302 | | - } |
---|
303 | | - ret = drm_gem_object_init(dev, &hibmcbo->gem, size); |
---|
304 | | - if (ret) { |
---|
305 | | - DRM_ERROR("failed to initialize drm gem object: %d\n", ret); |
---|
306 | | - kfree(hibmcbo); |
---|
307 | | - return ret; |
---|
308 | | - } |
---|
309 | | - |
---|
310 | | - hibmcbo->bo.bdev = &hibmc->bdev; |
---|
311 | | - |
---|
312 | | - hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); |
---|
313 | | - |
---|
314 | | - acc_size = ttm_bo_dma_acc_size(&hibmc->bdev, size, |
---|
315 | | - sizeof(struct hibmc_bo)); |
---|
316 | | - |
---|
317 | | - ret = ttm_bo_init(&hibmc->bdev, &hibmcbo->bo, size, |
---|
318 | | - ttm_bo_type_device, &hibmcbo->placement, |
---|
319 | | - align >> PAGE_SHIFT, false, acc_size, |
---|
320 | | - NULL, NULL, hibmc_bo_ttm_destroy); |
---|
321 | | - if (ret) { |
---|
322 | | - hibmc_bo_unref(&hibmcbo); |
---|
323 | | - DRM_ERROR("failed to initialize ttm_bo: %d\n", ret); |
---|
324 | | - return ret; |
---|
325 | | - } |
---|
326 | | - |
---|
327 | | - *phibmcbo = hibmcbo; |
---|
328 | | - return 0; |
---|
329 | | -} |
---|
330 | | - |
---|
331 | | -int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr) |
---|
332 | | -{ |
---|
333 | | - struct ttm_operation_ctx ctx = { false, false }; |
---|
334 | | - int i, ret; |
---|
335 | | - |
---|
336 | | - if (bo->pin_count) { |
---|
337 | | - bo->pin_count++; |
---|
338 | | - if (gpu_addr) |
---|
339 | | - *gpu_addr = bo->bo.offset; |
---|
340 | | - return 0; |
---|
341 | | - } |
---|
342 | | - |
---|
343 | | - hibmc_ttm_placement(bo, pl_flag); |
---|
344 | | - for (i = 0; i < bo->placement.num_placement; i++) |
---|
345 | | - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; |
---|
346 | | - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); |
---|
347 | | - if (ret) |
---|
348 | | - return ret; |
---|
349 | | - |
---|
350 | | - bo->pin_count = 1; |
---|
351 | | - if (gpu_addr) |
---|
352 | | - *gpu_addr = bo->bo.offset; |
---|
353 | | - return 0; |
---|
354 | | -} |
---|
355 | | - |
---|
356 | | -int hibmc_bo_unpin(struct hibmc_bo *bo) |
---|
357 | | -{ |
---|
358 | | - struct ttm_operation_ctx ctx = { false, false }; |
---|
359 | | - int i, ret; |
---|
360 | | - |
---|
361 | | - if (!bo->pin_count) { |
---|
362 | | - DRM_ERROR("unpin bad %p\n", bo); |
---|
363 | | - return 0; |
---|
364 | | - } |
---|
365 | | - bo->pin_count--; |
---|
366 | | - if (bo->pin_count) |
---|
367 | | - return 0; |
---|
368 | | - |
---|
369 | | - for (i = 0; i < bo->placement.num_placement ; i++) |
---|
370 | | - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; |
---|
371 | | - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); |
---|
372 | | - if (ret) { |
---|
373 | | - DRM_ERROR("validate failed for unpin: %d\n", ret); |
---|
374 | | - return ret; |
---|
375 | | - } |
---|
376 | | - |
---|
377 | | - return 0; |
---|
378 | | -} |
---|
379 | | - |
---|
380 | | -int hibmc_mmap(struct file *filp, struct vm_area_struct *vma) |
---|
381 | | -{ |
---|
382 | | - struct drm_file *file_priv; |
---|
383 | | - struct hibmc_drm_private *hibmc; |
---|
384 | | - |
---|
385 | | - if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) |
---|
386 | | - return -EINVAL; |
---|
387 | | - |
---|
388 | | - file_priv = filp->private_data; |
---|
389 | | - hibmc = file_priv->minor->dev->dev_private; |
---|
390 | | - return ttm_bo_mmap(filp, vma, &hibmc->bdev); |
---|
391 | | -} |
---|
392 | | - |
---|
393 | | -int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel, |
---|
394 | | - struct drm_gem_object **obj) |
---|
395 | | -{ |
---|
396 | | - struct hibmc_bo *hibmcbo; |
---|
397 | | - int ret; |
---|
398 | | - |
---|
399 | | - *obj = NULL; |
---|
400 | | - |
---|
401 | | - size = PAGE_ALIGN(size); |
---|
402 | | - if (size == 0) { |
---|
403 | | - DRM_ERROR("error: zero size\n"); |
---|
404 | | - return -EINVAL; |
---|
405 | | - } |
---|
406 | | - |
---|
407 | | - ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo); |
---|
408 | | - if (ret) { |
---|
409 | | - if (ret != -ERESTARTSYS) |
---|
410 | | - DRM_ERROR("failed to allocate GEM object: %d\n", ret); |
---|
411 | | - return ret; |
---|
412 | | - } |
---|
413 | | - *obj = &hibmcbo->gem; |
---|
414 | | - return 0; |
---|
| 47 | + drm_vram_helper_release_mm(hibmc->dev); |
---|
415 | 48 | } |
---|
416 | 49 | |
---|
417 | 50 | int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, |
---|
418 | 51 | struct drm_mode_create_dumb *args) |
---|
419 | 52 | { |
---|
420 | | - struct drm_gem_object *gobj; |
---|
421 | | - u32 handle; |
---|
422 | | - int ret; |
---|
423 | | - |
---|
424 | | - args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 16); |
---|
425 | | - args->size = args->pitch * args->height; |
---|
426 | | - |
---|
427 | | - ret = hibmc_gem_create(dev, args->size, false, |
---|
428 | | - &gobj); |
---|
429 | | - if (ret) { |
---|
430 | | - DRM_ERROR("failed to create GEM object: %d\n", ret); |
---|
431 | | - return ret; |
---|
432 | | - } |
---|
433 | | - |
---|
434 | | - ret = drm_gem_handle_create(file, gobj, &handle); |
---|
435 | | - drm_gem_object_put_unlocked(gobj); |
---|
436 | | - if (ret) { |
---|
437 | | - DRM_ERROR("failed to unreference GEM object: %d\n", ret); |
---|
438 | | - return ret; |
---|
439 | | - } |
---|
440 | | - |
---|
441 | | - args->handle = handle; |
---|
442 | | - return 0; |
---|
443 | | -} |
---|
444 | | - |
---|
445 | | -void hibmc_gem_free_object(struct drm_gem_object *obj) |
---|
446 | | -{ |
---|
447 | | - struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj); |
---|
448 | | - |
---|
449 | | - hibmc_bo_unref(&hibmcbo); |
---|
450 | | -} |
---|
451 | | - |
---|
452 | | -static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo) |
---|
453 | | -{ |
---|
454 | | - return drm_vma_node_offset_addr(&bo->bo.vma_node); |
---|
455 | | -} |
---|
456 | | - |
---|
457 | | -int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, |
---|
458 | | - u32 handle, u64 *offset) |
---|
459 | | -{ |
---|
460 | | - struct drm_gem_object *obj; |
---|
461 | | - struct hibmc_bo *bo; |
---|
462 | | - |
---|
463 | | - obj = drm_gem_object_lookup(file, handle); |
---|
464 | | - if (!obj) |
---|
465 | | - return -ENOENT; |
---|
466 | | - |
---|
467 | | - bo = gem_to_hibmc_bo(obj); |
---|
468 | | - *offset = hibmc_bo_mmap_offset(bo); |
---|
469 | | - |
---|
470 | | - drm_gem_object_put_unlocked(obj); |
---|
471 | | - return 0; |
---|
472 | | -} |
---|
473 | | - |
---|
474 | | -static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb) |
---|
475 | | -{ |
---|
476 | | - struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb); |
---|
477 | | - |
---|
478 | | - drm_gem_object_put_unlocked(hibmc_fb->obj); |
---|
479 | | - drm_framebuffer_cleanup(fb); |
---|
480 | | - kfree(hibmc_fb); |
---|
481 | | -} |
---|
482 | | - |
---|
483 | | -static const struct drm_framebuffer_funcs hibmc_fb_funcs = { |
---|
484 | | - .destroy = hibmc_user_framebuffer_destroy, |
---|
485 | | -}; |
---|
486 | | - |
---|
487 | | -struct hibmc_framebuffer * |
---|
488 | | -hibmc_framebuffer_init(struct drm_device *dev, |
---|
489 | | - const struct drm_mode_fb_cmd2 *mode_cmd, |
---|
490 | | - struct drm_gem_object *obj) |
---|
491 | | -{ |
---|
492 | | - struct hibmc_framebuffer *hibmc_fb; |
---|
493 | | - int ret; |
---|
494 | | - |
---|
495 | | - hibmc_fb = kzalloc(sizeof(*hibmc_fb), GFP_KERNEL); |
---|
496 | | - if (!hibmc_fb) { |
---|
497 | | - DRM_ERROR("failed to allocate hibmc_fb\n"); |
---|
498 | | - return ERR_PTR(-ENOMEM); |
---|
499 | | - } |
---|
500 | | - |
---|
501 | | - drm_helper_mode_fill_fb_struct(dev, &hibmc_fb->fb, mode_cmd); |
---|
502 | | - hibmc_fb->obj = obj; |
---|
503 | | - ret = drm_framebuffer_init(dev, &hibmc_fb->fb, &hibmc_fb_funcs); |
---|
504 | | - if (ret) { |
---|
505 | | - DRM_ERROR("drm_framebuffer_init failed: %d\n", ret); |
---|
506 | | - kfree(hibmc_fb); |
---|
507 | | - return ERR_PTR(ret); |
---|
508 | | - } |
---|
509 | | - |
---|
510 | | - return hibmc_fb; |
---|
511 | | -} |
---|
512 | | - |
---|
513 | | -static struct drm_framebuffer * |
---|
514 | | -hibmc_user_framebuffer_create(struct drm_device *dev, |
---|
515 | | - struct drm_file *filp, |
---|
516 | | - const struct drm_mode_fb_cmd2 *mode_cmd) |
---|
517 | | -{ |
---|
518 | | - struct drm_gem_object *obj; |
---|
519 | | - struct hibmc_framebuffer *hibmc_fb; |
---|
520 | | - |
---|
521 | | - DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n", |
---|
522 | | - mode_cmd->width, mode_cmd->height, |
---|
523 | | - (mode_cmd->pixel_format) & 0xff, |
---|
524 | | - (mode_cmd->pixel_format >> 8) & 0xff, |
---|
525 | | - (mode_cmd->pixel_format >> 16) & 0xff, |
---|
526 | | - (mode_cmd->pixel_format >> 24) & 0xff); |
---|
527 | | - |
---|
528 | | - obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); |
---|
529 | | - if (!obj) |
---|
530 | | - return ERR_PTR(-ENOENT); |
---|
531 | | - |
---|
532 | | - hibmc_fb = hibmc_framebuffer_init(dev, mode_cmd, obj); |
---|
533 | | - if (IS_ERR(hibmc_fb)) { |
---|
534 | | - drm_gem_object_put_unlocked(obj); |
---|
535 | | - return ERR_PTR((long)hibmc_fb); |
---|
536 | | - } |
---|
537 | | - return &hibmc_fb->fb; |
---|
| 53 | + return drm_gem_vram_fill_create_dumb(file, dev, 0, 128, args); |
---|
538 | 54 | } |
---|
539 | 55 | |
---|
540 | 56 | const struct drm_mode_config_funcs hibmc_mode_funcs = { |
---|
| 57 | + .mode_valid = drm_vram_helper_mode_valid, |
---|
541 | 58 | .atomic_check = drm_atomic_helper_check, |
---|
542 | 59 | .atomic_commit = drm_atomic_helper_commit, |
---|
543 | | - .fb_create = hibmc_user_framebuffer_create, |
---|
| 60 | + .fb_create = drm_gem_fb_create, |
---|
544 | 61 | }; |
---|