2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013 NVIDIA CORPORATION. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/host1x.h>
15 #define DRIVER_NAME "tegra"
16 #define DRIVER_DESC "NVIDIA Tegra graphics"
17 #define DRIVER_DATE "20120330"
18 #define DRIVER_MAJOR 0
19 #define DRIVER_MINOR 0
20 #define DRIVER_PATCHLEVEL 0
22 struct tegra_drm_file
{
23 struct list_head contexts
;
26 static int tegra_drm_load(struct drm_device
*drm
, unsigned long flags
)
28 struct host1x_device
*device
= to_host1x_device(drm
->dev
);
29 struct tegra_drm
*tegra
;
32 tegra
= kzalloc(sizeof(*tegra
), GFP_KERNEL
);
36 dev_set_drvdata(drm
->dev
, tegra
);
37 mutex_init(&tegra
->clients_lock
);
38 INIT_LIST_HEAD(&tegra
->clients
);
39 drm
->dev_private
= tegra
;
42 drm_mode_config_init(drm
);
44 err
= host1x_device_init(device
);
49 * We don't use the drm_irq_install() helpers provided by the DRM
50 * core, so we need to set this manually in order to allow the
51 * DRM_IOCTL_WAIT_VBLANK to operate correctly.
53 drm
->irq_enabled
= true;
55 err
= drm_vblank_init(drm
, drm
->mode_config
.num_crtc
);
59 err
= tegra_drm_fb_init(drm
);
63 drm_kms_helper_poll_init(drm
);
68 static int tegra_drm_unload(struct drm_device
*drm
)
70 struct host1x_device
*device
= to_host1x_device(drm
->dev
);
73 drm_kms_helper_poll_fini(drm
);
74 tegra_drm_fb_exit(drm
);
75 drm_vblank_cleanup(drm
);
76 drm_mode_config_cleanup(drm
);
78 err
= host1x_device_exit(device
);
85 static int tegra_drm_open(struct drm_device
*drm
, struct drm_file
*filp
)
87 struct tegra_drm_file
*fpriv
;
89 fpriv
= kzalloc(sizeof(*fpriv
), GFP_KERNEL
);
93 INIT_LIST_HEAD(&fpriv
->contexts
);
94 filp
->driver_priv
= fpriv
;
99 static void tegra_drm_context_free(struct tegra_drm_context
*context
)
101 context
->client
->ops
->close_channel(context
);
105 static void tegra_drm_lastclose(struct drm_device
*drm
)
107 struct tegra_drm
*tegra
= drm
->dev_private
;
109 tegra_fbdev_restore_mode(tegra
->fbdev
);
112 static struct host1x_bo
*
113 host1x_bo_lookup(struct drm_device
*drm
, struct drm_file
*file
, u32 handle
)
115 struct drm_gem_object
*gem
;
118 gem
= drm_gem_object_lookup(drm
, file
, handle
);
122 mutex_lock(&drm
->struct_mutex
);
123 drm_gem_object_unreference(gem
);
124 mutex_unlock(&drm
->struct_mutex
);
126 bo
= to_tegra_bo(gem
);
130 int tegra_drm_submit(struct tegra_drm_context
*context
,
131 struct drm_tegra_submit
*args
, struct drm_device
*drm
,
132 struct drm_file
*file
)
134 unsigned int num_cmdbufs
= args
->num_cmdbufs
;
135 unsigned int num_relocs
= args
->num_relocs
;
136 unsigned int num_waitchks
= args
->num_waitchks
;
137 struct drm_tegra_cmdbuf __user
*cmdbufs
=
138 (void * __user
)(uintptr_t)args
->cmdbufs
;
139 struct drm_tegra_reloc __user
*relocs
=
140 (void * __user
)(uintptr_t)args
->relocs
;
141 struct drm_tegra_waitchk __user
*waitchks
=
142 (void * __user
)(uintptr_t)args
->waitchks
;
143 struct drm_tegra_syncpt syncpt
;
144 struct host1x_job
*job
;
147 /* We don't yet support other than one syncpt_incr struct per submit */
148 if (args
->num_syncpts
!= 1)
151 job
= host1x_job_alloc(context
->channel
, args
->num_cmdbufs
,
152 args
->num_relocs
, args
->num_waitchks
);
156 job
->num_relocs
= args
->num_relocs
;
157 job
->num_waitchk
= args
->num_waitchks
;
158 job
->client
= (u32
)args
->context
;
159 job
->class = context
->client
->base
.class;
160 job
->serialize
= true;
162 while (num_cmdbufs
) {
163 struct drm_tegra_cmdbuf cmdbuf
;
164 struct host1x_bo
*bo
;
166 err
= copy_from_user(&cmdbuf
, cmdbufs
, sizeof(cmdbuf
));
170 bo
= host1x_bo_lookup(drm
, file
, cmdbuf
.handle
);
176 host1x_job_add_gather(job
, bo
, cmdbuf
.words
, cmdbuf
.offset
);
181 err
= copy_from_user(job
->relocarray
, relocs
,
182 sizeof(*relocs
) * num_relocs
);
186 while (num_relocs
--) {
187 struct host1x_reloc
*reloc
= &job
->relocarray
[num_relocs
];
188 struct host1x_bo
*cmdbuf
, *target
;
190 cmdbuf
= host1x_bo_lookup(drm
, file
, (u32
)reloc
->cmdbuf
);
191 target
= host1x_bo_lookup(drm
, file
, (u32
)reloc
->target
);
193 reloc
->cmdbuf
= cmdbuf
;
194 reloc
->target
= target
;
196 if (!reloc
->target
|| !reloc
->cmdbuf
) {
202 err
= copy_from_user(job
->waitchk
, waitchks
,
203 sizeof(*waitchks
) * num_waitchks
);
207 err
= copy_from_user(&syncpt
, (void * __user
)(uintptr_t)args
->syncpts
,
212 job
->is_addr_reg
= context
->client
->ops
->is_addr_reg
;
213 job
->syncpt_incrs
= syncpt
.incrs
;
214 job
->syncpt_id
= syncpt
.id
;
215 job
->timeout
= 10000;
217 if (args
->timeout
&& args
->timeout
< 10000)
218 job
->timeout
= args
->timeout
;
220 err
= host1x_job_pin(job
, context
->client
->base
.dev
);
224 err
= host1x_job_submit(job
);
228 args
->fence
= job
->syncpt_end
;
234 host1x_job_unpin(job
);
241 #ifdef CONFIG_DRM_TEGRA_STAGING
242 static struct tegra_drm_context
*tegra_drm_get_context(__u64 context
)
244 return (struct tegra_drm_context
*)(uintptr_t)context
;
247 static bool tegra_drm_file_owns_context(struct tegra_drm_file
*file
,
248 struct tegra_drm_context
*context
)
250 struct tegra_drm_context
*ctx
;
252 list_for_each_entry(ctx
, &file
->contexts
, list
)
259 static int tegra_gem_create(struct drm_device
*drm
, void *data
,
260 struct drm_file
*file
)
262 struct drm_tegra_gem_create
*args
= data
;
265 bo
= tegra_bo_create_with_handle(file
, drm
, args
->size
,
273 static int tegra_gem_mmap(struct drm_device
*drm
, void *data
,
274 struct drm_file
*file
)
276 struct drm_tegra_gem_mmap
*args
= data
;
277 struct drm_gem_object
*gem
;
280 gem
= drm_gem_object_lookup(drm
, file
, args
->handle
);
284 bo
= to_tegra_bo(gem
);
286 args
->offset
= drm_vma_node_offset_addr(&bo
->gem
.vma_node
);
288 drm_gem_object_unreference(gem
);
293 static int tegra_syncpt_read(struct drm_device
*drm
, void *data
,
294 struct drm_file
*file
)
296 struct host1x
*host
= dev_get_drvdata(drm
->dev
->parent
);
297 struct drm_tegra_syncpt_read
*args
= data
;
298 struct host1x_syncpt
*sp
;
300 sp
= host1x_syncpt_get(host
, args
->id
);
304 args
->value
= host1x_syncpt_read_min(sp
);
308 static int tegra_syncpt_incr(struct drm_device
*drm
, void *data
,
309 struct drm_file
*file
)
311 struct host1x
*host1x
= dev_get_drvdata(drm
->dev
->parent
);
312 struct drm_tegra_syncpt_incr
*args
= data
;
313 struct host1x_syncpt
*sp
;
315 sp
= host1x_syncpt_get(host1x
, args
->id
);
319 return host1x_syncpt_incr(sp
);
322 static int tegra_syncpt_wait(struct drm_device
*drm
, void *data
,
323 struct drm_file
*file
)
325 struct host1x
*host1x
= dev_get_drvdata(drm
->dev
->parent
);
326 struct drm_tegra_syncpt_wait
*args
= data
;
327 struct host1x_syncpt
*sp
;
329 sp
= host1x_syncpt_get(host1x
, args
->id
);
333 return host1x_syncpt_wait(sp
, args
->thresh
, args
->timeout
,
337 static int tegra_open_channel(struct drm_device
*drm
, void *data
,
338 struct drm_file
*file
)
340 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
341 struct tegra_drm
*tegra
= drm
->dev_private
;
342 struct drm_tegra_open_channel
*args
= data
;
343 struct tegra_drm_context
*context
;
344 struct tegra_drm_client
*client
;
347 context
= kzalloc(sizeof(*context
), GFP_KERNEL
);
351 list_for_each_entry(client
, &tegra
->clients
, list
)
352 if (client
->base
.class == args
->client
) {
353 err
= client
->ops
->open_channel(client
, context
);
357 list_add(&context
->list
, &fpriv
->contexts
);
358 args
->context
= (uintptr_t)context
;
359 context
->client
= client
;
367 static int tegra_close_channel(struct drm_device
*drm
, void *data
,
368 struct drm_file
*file
)
370 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
371 struct drm_tegra_close_channel
*args
= data
;
372 struct tegra_drm_context
*context
;
374 context
= tegra_drm_get_context(args
->context
);
376 if (!tegra_drm_file_owns_context(fpriv
, context
))
379 list_del(&context
->list
);
380 tegra_drm_context_free(context
);
385 static int tegra_get_syncpt(struct drm_device
*drm
, void *data
,
386 struct drm_file
*file
)
388 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
389 struct drm_tegra_get_syncpt
*args
= data
;
390 struct tegra_drm_context
*context
;
391 struct host1x_syncpt
*syncpt
;
393 context
= tegra_drm_get_context(args
->context
);
395 if (!tegra_drm_file_owns_context(fpriv
, context
))
398 if (args
->index
>= context
->client
->base
.num_syncpts
)
401 syncpt
= context
->client
->base
.syncpts
[args
->index
];
402 args
->id
= host1x_syncpt_id(syncpt
);
407 static int tegra_submit(struct drm_device
*drm
, void *data
,
408 struct drm_file
*file
)
410 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
411 struct drm_tegra_submit
*args
= data
;
412 struct tegra_drm_context
*context
;
414 context
= tegra_drm_get_context(args
->context
);
416 if (!tegra_drm_file_owns_context(fpriv
, context
))
419 return context
->client
->ops
->submit(context
, args
, drm
, file
);
423 static const struct drm_ioctl_desc tegra_drm_ioctls
[] = {
424 #ifdef CONFIG_DRM_TEGRA_STAGING
425 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE
, tegra_gem_create
, DRM_UNLOCKED
| DRM_AUTH
),
426 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP
, tegra_gem_mmap
, DRM_UNLOCKED
),
427 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ
, tegra_syncpt_read
, DRM_UNLOCKED
),
428 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR
, tegra_syncpt_incr
, DRM_UNLOCKED
),
429 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT
, tegra_syncpt_wait
, DRM_UNLOCKED
),
430 DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL
, tegra_open_channel
, DRM_UNLOCKED
),
431 DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL
, tegra_close_channel
, DRM_UNLOCKED
),
432 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT
, tegra_get_syncpt
, DRM_UNLOCKED
),
433 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT
, tegra_submit
, DRM_UNLOCKED
),
437 static const struct file_operations tegra_drm_fops
= {
438 .owner
= THIS_MODULE
,
440 .release
= drm_release
,
441 .unlocked_ioctl
= drm_ioctl
,
442 .mmap
= tegra_drm_mmap
,
446 .compat_ioctl
= drm_compat_ioctl
,
448 .llseek
= noop_llseek
,
451 static struct drm_crtc
*tegra_crtc_from_pipe(struct drm_device
*drm
, int pipe
)
453 struct drm_crtc
*crtc
;
455 list_for_each_entry(crtc
, &drm
->mode_config
.crtc_list
, head
) {
456 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
458 if (dc
->pipe
== pipe
)
465 static u32
tegra_drm_get_vblank_counter(struct drm_device
*dev
, int crtc
)
467 /* TODO: implement real hardware counter using syncpoints */
468 return drm_vblank_count(dev
, crtc
);
471 static int tegra_drm_enable_vblank(struct drm_device
*drm
, int pipe
)
473 struct drm_crtc
*crtc
= tegra_crtc_from_pipe(drm
, pipe
);
474 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
479 tegra_dc_enable_vblank(dc
);
484 static void tegra_drm_disable_vblank(struct drm_device
*drm
, int pipe
)
486 struct drm_crtc
*crtc
= tegra_crtc_from_pipe(drm
, pipe
);
487 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
490 tegra_dc_disable_vblank(dc
);
493 static void tegra_drm_preclose(struct drm_device
*drm
, struct drm_file
*file
)
495 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
496 struct tegra_drm_context
*context
, *tmp
;
497 struct drm_crtc
*crtc
;
499 list_for_each_entry(crtc
, &drm
->mode_config
.crtc_list
, head
)
500 tegra_dc_cancel_page_flip(crtc
, file
);
502 list_for_each_entry_safe(context
, tmp
, &fpriv
->contexts
, list
)
503 tegra_drm_context_free(context
);
508 #ifdef CONFIG_DEBUG_FS
509 static int tegra_debugfs_framebuffers(struct seq_file
*s
, void *data
)
511 struct drm_info_node
*node
= (struct drm_info_node
*)s
->private;
512 struct drm_device
*drm
= node
->minor
->dev
;
513 struct drm_framebuffer
*fb
;
515 mutex_lock(&drm
->mode_config
.fb_lock
);
517 list_for_each_entry(fb
, &drm
->mode_config
.fb_list
, head
) {
518 seq_printf(s
, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
519 fb
->base
.id
, fb
->width
, fb
->height
, fb
->depth
,
521 atomic_read(&fb
->refcount
.refcount
));
524 mutex_unlock(&drm
->mode_config
.fb_lock
);
529 static struct drm_info_list tegra_debugfs_list
[] = {
530 { "framebuffers", tegra_debugfs_framebuffers
, 0 },
533 static int tegra_debugfs_init(struct drm_minor
*minor
)
535 return drm_debugfs_create_files(tegra_debugfs_list
,
536 ARRAY_SIZE(tegra_debugfs_list
),
537 minor
->debugfs_root
, minor
);
540 static void tegra_debugfs_cleanup(struct drm_minor
*minor
)
542 drm_debugfs_remove_files(tegra_debugfs_list
,
543 ARRAY_SIZE(tegra_debugfs_list
), minor
);
547 struct drm_driver tegra_drm_driver
= {
548 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
,
549 .load
= tegra_drm_load
,
550 .unload
= tegra_drm_unload
,
551 .open
= tegra_drm_open
,
552 .preclose
= tegra_drm_preclose
,
553 .lastclose
= tegra_drm_lastclose
,
555 .get_vblank_counter
= tegra_drm_get_vblank_counter
,
556 .enable_vblank
= tegra_drm_enable_vblank
,
557 .disable_vblank
= tegra_drm_disable_vblank
,
559 #if defined(CONFIG_DEBUG_FS)
560 .debugfs_init
= tegra_debugfs_init
,
561 .debugfs_cleanup
= tegra_debugfs_cleanup
,
564 .gem_free_object
= tegra_bo_free_object
,
565 .gem_vm_ops
= &tegra_bo_vm_ops
,
566 .dumb_create
= tegra_bo_dumb_create
,
567 .dumb_map_offset
= tegra_bo_dumb_map_offset
,
568 .dumb_destroy
= drm_gem_dumb_destroy
,
570 .ioctls
= tegra_drm_ioctls
,
571 .num_ioctls
= ARRAY_SIZE(tegra_drm_ioctls
),
572 .fops
= &tegra_drm_fops
,
577 .major
= DRIVER_MAJOR
,
578 .minor
= DRIVER_MINOR
,
579 .patchlevel
= DRIVER_PATCHLEVEL
,
582 int tegra_drm_register_client(struct tegra_drm
*tegra
,
583 struct tegra_drm_client
*client
)
585 mutex_lock(&tegra
->clients_lock
);
586 list_add_tail(&client
->list
, &tegra
->clients
);
587 mutex_unlock(&tegra
->clients_lock
);
592 int tegra_drm_unregister_client(struct tegra_drm
*tegra
,
593 struct tegra_drm_client
*client
)
595 mutex_lock(&tegra
->clients_lock
);
596 list_del_init(&client
->list
);
597 mutex_unlock(&tegra
->clients_lock
);
602 static int host1x_drm_probe(struct host1x_device
*device
)
604 return drm_host1x_init(&tegra_drm_driver
, device
);
607 static int host1x_drm_remove(struct host1x_device
*device
)
609 drm_host1x_exit(&tegra_drm_driver
, device
);
614 static const struct of_device_id host1x_drm_subdevs
[] = {
615 { .compatible
= "nvidia,tegra20-dc", },
616 { .compatible
= "nvidia,tegra20-hdmi", },
617 { .compatible
= "nvidia,tegra20-gr2d", },
618 { .compatible
= "nvidia,tegra30-dc", },
619 { .compatible
= "nvidia,tegra30-hdmi", },
620 { .compatible
= "nvidia,tegra30-gr2d", },
621 { .compatible
= "nvidia,tegra114-hdmi", },
625 static struct host1x_driver host1x_drm_driver
= {
627 .probe
= host1x_drm_probe
,
628 .remove
= host1x_drm_remove
,
629 .subdevs
= host1x_drm_subdevs
,
632 static int __init
host1x_drm_init(void)
636 err
= host1x_driver_register(&host1x_drm_driver
);
640 err
= platform_driver_register(&tegra_dc_driver
);
642 goto unregister_host1x
;
644 err
= platform_driver_register(&tegra_hdmi_driver
);
648 err
= platform_driver_register(&tegra_gr2d_driver
);
650 goto unregister_hdmi
;
655 platform_driver_unregister(&tegra_hdmi_driver
);
657 platform_driver_unregister(&tegra_dc_driver
);
659 host1x_driver_unregister(&host1x_drm_driver
);
662 module_init(host1x_drm_init
);
664 static void __exit
host1x_drm_exit(void)
666 platform_driver_unregister(&tegra_gr2d_driver
);
667 platform_driver_unregister(&tegra_hdmi_driver
);
668 platform_driver_unregister(&tegra_dc_driver
);
669 host1x_driver_unregister(&host1x_drm_driver
);
671 module_exit(host1x_drm_exit
);
673 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
674 MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
675 MODULE_LICENSE("GPL v2");