1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
4 #include <linux/module.h>
5 #include <linux/of_platform.h>
6 #include <linux/uaccess.h>
7 #include <linux/slab.h>
8 #include <drm/drm_ioctl.h>
9 #include <drm/drm_drv.h>
10 #include <drm/drm_prime.h>
11 #include <drm/lima_drm.h>
17 int lima_sched_timeout_ms
;
19 MODULE_PARM_DESC(sched_timeout_ms
, "task run timeout in ms");
20 module_param_named(sched_timeout_ms
, lima_sched_timeout_ms
, int, 0444);
22 static int lima_ioctl_get_param(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
24 struct drm_lima_get_param
*args
= data
;
25 struct lima_device
*ldev
= to_lima_dev(dev
);
30 switch (args
->param
) {
31 case DRM_LIMA_PARAM_GPU_ID
:
33 case lima_gpu_mali400
:
34 args
->value
= DRM_LIMA_PARAM_GPU_ID_MALI400
;
36 case lima_gpu_mali450
:
37 args
->value
= DRM_LIMA_PARAM_GPU_ID_MALI450
;
40 args
->value
= DRM_LIMA_PARAM_GPU_ID_UNKNOWN
;
45 case DRM_LIMA_PARAM_NUM_PP
:
46 args
->value
= ldev
->pipe
[lima_pipe_pp
].num_processor
;
49 case DRM_LIMA_PARAM_GP_VERSION
:
50 args
->value
= ldev
->gp_version
;
53 case DRM_LIMA_PARAM_PP_VERSION
:
54 args
->value
= ldev
->pp_version
;
64 static int lima_ioctl_gem_create(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
66 struct drm_lima_gem_create
*args
= data
;
77 return lima_gem_create_handle(dev
, file
, args
->size
, args
->flags
, &args
->handle
);
80 static int lima_ioctl_gem_info(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
82 struct drm_lima_gem_info
*args
= data
;
84 return lima_gem_get_info(file
, args
->handle
, &args
->va
, &args
->offset
);
87 static int lima_ioctl_gem_submit(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
89 struct drm_lima_gem_submit
*args
= data
;
90 struct lima_device
*ldev
= to_lima_dev(dev
);
91 struct lima_drm_priv
*priv
= file
->driver_priv
;
92 struct drm_lima_gem_submit_bo
*bos
;
93 struct lima_sched_pipe
*pipe
;
94 struct lima_sched_task
*task
;
96 struct lima_submit submit
= {0};
100 if (args
->pipe
>= lima_pipe_num
|| args
->nr_bos
== 0)
103 if (args
->flags
& ~(LIMA_SUBMIT_FLAG_EXPLICIT_FENCE
))
106 pipe
= ldev
->pipe
+ args
->pipe
;
107 if (args
->frame_size
!= pipe
->frame_size
)
110 bos
= kvcalloc(args
->nr_bos
, sizeof(*submit
.bos
) + sizeof(*submit
.lbos
), GFP_KERNEL
);
114 size
= args
->nr_bos
* sizeof(*submit
.bos
);
115 if (copy_from_user(bos
, u64_to_user_ptr(args
->bos
), size
)) {
120 task
= kmem_cache_zalloc(pipe
->task_slab
, GFP_KERNEL
);
126 task
->frame
= task
+ 1;
127 if (copy_from_user(task
->frame
, u64_to_user_ptr(args
->frame
), args
->frame_size
)) {
132 err
= pipe
->task_validate(pipe
, task
);
136 ctx
= lima_ctx_get(&priv
->ctx_mgr
, args
->ctx
);
142 submit
.pipe
= args
->pipe
;
144 submit
.lbos
= (void *)bos
+ size
;
145 submit
.nr_bos
= args
->nr_bos
;
148 submit
.flags
= args
->flags
;
149 submit
.in_sync
[0] = args
->in_sync
[0];
150 submit
.in_sync
[1] = args
->in_sync
[1];
151 submit
.out_sync
= args
->out_sync
;
153 err
= lima_gem_submit(file
, &submit
);
158 kmem_cache_free(pipe
->task_slab
, task
);
164 static int lima_ioctl_gem_wait(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
166 struct drm_lima_gem_wait
*args
= data
;
168 if (args
->op
& ~(LIMA_GEM_WAIT_READ
|LIMA_GEM_WAIT_WRITE
))
171 return lima_gem_wait(file
, args
->handle
, args
->op
, args
->timeout_ns
);
174 static int lima_ioctl_ctx_create(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
176 struct drm_lima_ctx_create
*args
= data
;
177 struct lima_drm_priv
*priv
= file
->driver_priv
;
178 struct lima_device
*ldev
= to_lima_dev(dev
);
183 return lima_ctx_create(ldev
, &priv
->ctx_mgr
, &args
->id
);
186 static int lima_ioctl_ctx_free(struct drm_device
*dev
, void *data
, struct drm_file
*file
)
188 struct drm_lima_ctx_create
*args
= data
;
189 struct lima_drm_priv
*priv
= file
->driver_priv
;
194 return lima_ctx_free(&priv
->ctx_mgr
, args
->id
);
197 static int lima_drm_driver_open(struct drm_device
*dev
, struct drm_file
*file
)
200 struct lima_drm_priv
*priv
;
201 struct lima_device
*ldev
= to_lima_dev(dev
);
203 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
207 priv
->vm
= lima_vm_create(ldev
);
213 lima_ctx_mgr_init(&priv
->ctx_mgr
);
215 file
->driver_priv
= priv
;
223 static void lima_drm_driver_postclose(struct drm_device
*dev
, struct drm_file
*file
)
225 struct lima_drm_priv
*priv
= file
->driver_priv
;
227 lima_ctx_mgr_fini(&priv
->ctx_mgr
);
228 lima_vm_put(priv
->vm
);
232 static const struct drm_ioctl_desc lima_drm_driver_ioctls
[] = {
233 DRM_IOCTL_DEF_DRV(LIMA_GET_PARAM
, lima_ioctl_get_param
, DRM_RENDER_ALLOW
),
234 DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE
, lima_ioctl_gem_create
, DRM_RENDER_ALLOW
),
235 DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO
, lima_ioctl_gem_info
, DRM_RENDER_ALLOW
),
236 DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT
, lima_ioctl_gem_submit
, DRM_RENDER_ALLOW
),
237 DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT
, lima_ioctl_gem_wait
, DRM_RENDER_ALLOW
),
238 DRM_IOCTL_DEF_DRV(LIMA_CTX_CREATE
, lima_ioctl_ctx_create
, DRM_RENDER_ALLOW
),
239 DRM_IOCTL_DEF_DRV(LIMA_CTX_FREE
, lima_ioctl_ctx_free
, DRM_RENDER_ALLOW
),
242 DEFINE_DRM_GEM_FOPS(lima_drm_driver_fops
);
244 static struct drm_driver lima_drm_driver
= {
245 .driver_features
= DRIVER_RENDER
| DRIVER_GEM
| DRIVER_SYNCOBJ
,
246 .open
= lima_drm_driver_open
,
247 .postclose
= lima_drm_driver_postclose
,
248 .ioctls
= lima_drm_driver_ioctls
,
249 .num_ioctls
= ARRAY_SIZE(lima_drm_driver_ioctls
),
250 .fops
= &lima_drm_driver_fops
,
258 .gem_create_object
= lima_gem_create_object
,
259 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
260 .gem_prime_import_sg_table
= drm_gem_shmem_prime_import_sg_table
,
261 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
262 .gem_prime_mmap
= drm_gem_prime_mmap
,
265 static int lima_pdev_probe(struct platform_device
*pdev
)
267 struct lima_device
*ldev
;
268 struct drm_device
*ddev
;
271 err
= lima_sched_slab_init();
275 ldev
= devm_kzalloc(&pdev
->dev
, sizeof(*ldev
), GFP_KERNEL
);
282 ldev
->dev
= &pdev
->dev
;
283 ldev
->id
= (enum lima_gpu_id
)of_device_get_match_data(&pdev
->dev
);
285 platform_set_drvdata(pdev
, ldev
);
287 /* Allocate and initialize the DRM device. */
288 ddev
= drm_dev_alloc(&lima_drm_driver
, &pdev
->dev
);
290 return PTR_ERR(ddev
);
292 ddev
->dev_private
= ldev
;
295 err
= lima_device_init(ldev
);
300 * Register the DRM device with the core and the connectors with
303 err
= drm_dev_register(ddev
, 0);
310 lima_device_fini(ldev
);
314 lima_sched_slab_fini();
318 static int lima_pdev_remove(struct platform_device
*pdev
)
320 struct lima_device
*ldev
= platform_get_drvdata(pdev
);
321 struct drm_device
*ddev
= ldev
->ddev
;
323 drm_dev_unregister(ddev
);
324 lima_device_fini(ldev
);
326 lima_sched_slab_fini();
330 static const struct of_device_id dt_match
[] = {
331 { .compatible
= "arm,mali-400", .data
= (void *)lima_gpu_mali400
},
332 { .compatible
= "arm,mali-450", .data
= (void *)lima_gpu_mali450
},
335 MODULE_DEVICE_TABLE(of
, dt_match
);
337 static struct platform_driver lima_platform_driver
= {
338 .probe
= lima_pdev_probe
,
339 .remove
= lima_pdev_remove
,
342 .of_match_table
= dt_match
,
346 static int __init
lima_init(void)
348 return platform_driver_register(&lima_platform_driver
);
350 module_init(lima_init
);
352 static void __exit
lima_exit(void)
354 platform_driver_unregister(&lima_platform_driver
);
356 module_exit(lima_exit
);
358 MODULE_AUTHOR("Lima Project Developers");
359 MODULE_DESCRIPTION("Lima DRM Driver");
360 MODULE_LICENSE("GPL v2");