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 #ifdef CONFIG_DRM_TEGRA_FBDEV
108 struct tegra_drm
*tegra
= drm
->dev_private
;
110 tegra_fbdev_restore_mode(tegra
->fbdev
);
114 static struct host1x_bo
*
115 host1x_bo_lookup(struct drm_device
*drm
, struct drm_file
*file
, u32 handle
)
117 struct drm_gem_object
*gem
;
120 gem
= drm_gem_object_lookup(drm
, file
, handle
);
124 mutex_lock(&drm
->struct_mutex
);
125 drm_gem_object_unreference(gem
);
126 mutex_unlock(&drm
->struct_mutex
);
128 bo
= to_tegra_bo(gem
);
132 int tegra_drm_submit(struct tegra_drm_context
*context
,
133 struct drm_tegra_submit
*args
, struct drm_device
*drm
,
134 struct drm_file
*file
)
136 unsigned int num_cmdbufs
= args
->num_cmdbufs
;
137 unsigned int num_relocs
= args
->num_relocs
;
138 unsigned int num_waitchks
= args
->num_waitchks
;
139 struct drm_tegra_cmdbuf __user
*cmdbufs
=
140 (void __user
*)(uintptr_t)args
->cmdbufs
;
141 struct drm_tegra_reloc __user
*relocs
=
142 (void __user
*)(uintptr_t)args
->relocs
;
143 struct drm_tegra_waitchk __user
*waitchks
=
144 (void __user
*)(uintptr_t)args
->waitchks
;
145 struct drm_tegra_syncpt syncpt
;
146 struct host1x_job
*job
;
149 /* We don't yet support other than one syncpt_incr struct per submit */
150 if (args
->num_syncpts
!= 1)
153 job
= host1x_job_alloc(context
->channel
, args
->num_cmdbufs
,
154 args
->num_relocs
, args
->num_waitchks
);
158 job
->num_relocs
= args
->num_relocs
;
159 job
->num_waitchk
= args
->num_waitchks
;
160 job
->client
= (u32
)args
->context
;
161 job
->class = context
->client
->base
.class;
162 job
->serialize
= true;
164 while (num_cmdbufs
) {
165 struct drm_tegra_cmdbuf cmdbuf
;
166 struct host1x_bo
*bo
;
168 if (copy_from_user(&cmdbuf
, cmdbufs
, sizeof(cmdbuf
))) {
173 bo
= host1x_bo_lookup(drm
, file
, cmdbuf
.handle
);
179 host1x_job_add_gather(job
, bo
, cmdbuf
.words
, cmdbuf
.offset
);
184 if (copy_from_user(job
->relocarray
, relocs
,
185 sizeof(*relocs
) * num_relocs
)) {
190 while (num_relocs
--) {
191 struct host1x_reloc
*reloc
= &job
->relocarray
[num_relocs
];
192 struct host1x_bo
*cmdbuf
, *target
;
194 cmdbuf
= host1x_bo_lookup(drm
, file
, (u32
)reloc
->cmdbuf
);
195 target
= host1x_bo_lookup(drm
, file
, (u32
)reloc
->target
);
197 reloc
->cmdbuf
= cmdbuf
;
198 reloc
->target
= target
;
200 if (!reloc
->target
|| !reloc
->cmdbuf
) {
206 if (copy_from_user(job
->waitchk
, waitchks
,
207 sizeof(*waitchks
) * num_waitchks
)) {
212 if (copy_from_user(&syncpt
, (void __user
*)(uintptr_t)args
->syncpts
,
218 job
->is_addr_reg
= context
->client
->ops
->is_addr_reg
;
219 job
->syncpt_incrs
= syncpt
.incrs
;
220 job
->syncpt_id
= syncpt
.id
;
221 job
->timeout
= 10000;
223 if (args
->timeout
&& args
->timeout
< 10000)
224 job
->timeout
= args
->timeout
;
226 err
= host1x_job_pin(job
, context
->client
->base
.dev
);
230 err
= host1x_job_submit(job
);
234 args
->fence
= job
->syncpt_end
;
240 host1x_job_unpin(job
);
247 #ifdef CONFIG_DRM_TEGRA_STAGING
248 static struct tegra_drm_context
*tegra_drm_get_context(__u64 context
)
250 return (struct tegra_drm_context
*)(uintptr_t)context
;
253 static bool tegra_drm_file_owns_context(struct tegra_drm_file
*file
,
254 struct tegra_drm_context
*context
)
256 struct tegra_drm_context
*ctx
;
258 list_for_each_entry(ctx
, &file
->contexts
, list
)
265 static int tegra_gem_create(struct drm_device
*drm
, void *data
,
266 struct drm_file
*file
)
268 struct drm_tegra_gem_create
*args
= data
;
271 bo
= tegra_bo_create_with_handle(file
, drm
, args
->size
, args
->flags
,
279 static int tegra_gem_mmap(struct drm_device
*drm
, void *data
,
280 struct drm_file
*file
)
282 struct drm_tegra_gem_mmap
*args
= data
;
283 struct drm_gem_object
*gem
;
286 gem
= drm_gem_object_lookup(drm
, file
, args
->handle
);
290 bo
= to_tegra_bo(gem
);
292 args
->offset
= drm_vma_node_offset_addr(&bo
->gem
.vma_node
);
294 drm_gem_object_unreference(gem
);
299 static int tegra_syncpt_read(struct drm_device
*drm
, void *data
,
300 struct drm_file
*file
)
302 struct host1x
*host
= dev_get_drvdata(drm
->dev
->parent
);
303 struct drm_tegra_syncpt_read
*args
= data
;
304 struct host1x_syncpt
*sp
;
306 sp
= host1x_syncpt_get(host
, args
->id
);
310 args
->value
= host1x_syncpt_read_min(sp
);
314 static int tegra_syncpt_incr(struct drm_device
*drm
, void *data
,
315 struct drm_file
*file
)
317 struct host1x
*host1x
= dev_get_drvdata(drm
->dev
->parent
);
318 struct drm_tegra_syncpt_incr
*args
= data
;
319 struct host1x_syncpt
*sp
;
321 sp
= host1x_syncpt_get(host1x
, args
->id
);
325 return host1x_syncpt_incr(sp
);
328 static int tegra_syncpt_wait(struct drm_device
*drm
, void *data
,
329 struct drm_file
*file
)
331 struct host1x
*host1x
= dev_get_drvdata(drm
->dev
->parent
);
332 struct drm_tegra_syncpt_wait
*args
= data
;
333 struct host1x_syncpt
*sp
;
335 sp
= host1x_syncpt_get(host1x
, args
->id
);
339 return host1x_syncpt_wait(sp
, args
->thresh
, args
->timeout
,
343 static int tegra_open_channel(struct drm_device
*drm
, void *data
,
344 struct drm_file
*file
)
346 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
347 struct tegra_drm
*tegra
= drm
->dev_private
;
348 struct drm_tegra_open_channel
*args
= data
;
349 struct tegra_drm_context
*context
;
350 struct tegra_drm_client
*client
;
353 context
= kzalloc(sizeof(*context
), GFP_KERNEL
);
357 list_for_each_entry(client
, &tegra
->clients
, list
)
358 if (client
->base
.class == args
->client
) {
359 err
= client
->ops
->open_channel(client
, context
);
363 list_add(&context
->list
, &fpriv
->contexts
);
364 args
->context
= (uintptr_t)context
;
365 context
->client
= client
;
373 static int tegra_close_channel(struct drm_device
*drm
, void *data
,
374 struct drm_file
*file
)
376 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
377 struct drm_tegra_close_channel
*args
= data
;
378 struct tegra_drm_context
*context
;
380 context
= tegra_drm_get_context(args
->context
);
382 if (!tegra_drm_file_owns_context(fpriv
, context
))
385 list_del(&context
->list
);
386 tegra_drm_context_free(context
);
391 static int tegra_get_syncpt(struct drm_device
*drm
, void *data
,
392 struct drm_file
*file
)
394 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
395 struct drm_tegra_get_syncpt
*args
= data
;
396 struct tegra_drm_context
*context
;
397 struct host1x_syncpt
*syncpt
;
399 context
= tegra_drm_get_context(args
->context
);
401 if (!tegra_drm_file_owns_context(fpriv
, context
))
404 if (args
->index
>= context
->client
->base
.num_syncpts
)
407 syncpt
= context
->client
->base
.syncpts
[args
->index
];
408 args
->id
= host1x_syncpt_id(syncpt
);
413 static int tegra_submit(struct drm_device
*drm
, void *data
,
414 struct drm_file
*file
)
416 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
417 struct drm_tegra_submit
*args
= data
;
418 struct tegra_drm_context
*context
;
420 context
= tegra_drm_get_context(args
->context
);
422 if (!tegra_drm_file_owns_context(fpriv
, context
))
425 return context
->client
->ops
->submit(context
, args
, drm
, file
);
428 static int tegra_get_syncpt_base(struct drm_device
*drm
, void *data
,
429 struct drm_file
*file
)
431 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
432 struct drm_tegra_get_syncpt_base
*args
= data
;
433 struct tegra_drm_context
*context
;
434 struct host1x_syncpt_base
*base
;
435 struct host1x_syncpt
*syncpt
;
437 context
= tegra_drm_get_context(args
->context
);
439 if (!tegra_drm_file_owns_context(fpriv
, context
))
442 if (args
->syncpt
>= context
->client
->base
.num_syncpts
)
445 syncpt
= context
->client
->base
.syncpts
[args
->syncpt
];
447 base
= host1x_syncpt_get_base(syncpt
);
451 args
->id
= host1x_syncpt_base_id(base
);
457 static const struct drm_ioctl_desc tegra_drm_ioctls
[] = {
458 #ifdef CONFIG_DRM_TEGRA_STAGING
459 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE
, tegra_gem_create
, DRM_UNLOCKED
| DRM_AUTH
),
460 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP
, tegra_gem_mmap
, DRM_UNLOCKED
),
461 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ
, tegra_syncpt_read
, DRM_UNLOCKED
),
462 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR
, tegra_syncpt_incr
, DRM_UNLOCKED
),
463 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT
, tegra_syncpt_wait
, DRM_UNLOCKED
),
464 DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL
, tegra_open_channel
, DRM_UNLOCKED
),
465 DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL
, tegra_close_channel
, DRM_UNLOCKED
),
466 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT
, tegra_get_syncpt
, DRM_UNLOCKED
),
467 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT
, tegra_submit
, DRM_UNLOCKED
),
468 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE
, tegra_get_syncpt_base
, DRM_UNLOCKED
),
472 static const struct file_operations tegra_drm_fops
= {
473 .owner
= THIS_MODULE
,
475 .release
= drm_release
,
476 .unlocked_ioctl
= drm_ioctl
,
477 .mmap
= tegra_drm_mmap
,
481 .compat_ioctl
= drm_compat_ioctl
,
483 .llseek
= noop_llseek
,
486 static struct drm_crtc
*tegra_crtc_from_pipe(struct drm_device
*drm
, int pipe
)
488 struct drm_crtc
*crtc
;
490 list_for_each_entry(crtc
, &drm
->mode_config
.crtc_list
, head
) {
491 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
493 if (dc
->pipe
== pipe
)
500 static u32
tegra_drm_get_vblank_counter(struct drm_device
*dev
, int crtc
)
502 /* TODO: implement real hardware counter using syncpoints */
503 return drm_vblank_count(dev
, crtc
);
506 static int tegra_drm_enable_vblank(struct drm_device
*drm
, int pipe
)
508 struct drm_crtc
*crtc
= tegra_crtc_from_pipe(drm
, pipe
);
509 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
514 tegra_dc_enable_vblank(dc
);
519 static void tegra_drm_disable_vblank(struct drm_device
*drm
, int pipe
)
521 struct drm_crtc
*crtc
= tegra_crtc_from_pipe(drm
, pipe
);
522 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
525 tegra_dc_disable_vblank(dc
);
528 static void tegra_drm_preclose(struct drm_device
*drm
, struct drm_file
*file
)
530 struct tegra_drm_file
*fpriv
= file
->driver_priv
;
531 struct tegra_drm_context
*context
, *tmp
;
532 struct drm_crtc
*crtc
;
534 list_for_each_entry(crtc
, &drm
->mode_config
.crtc_list
, head
)
535 tegra_dc_cancel_page_flip(crtc
, file
);
537 list_for_each_entry_safe(context
, tmp
, &fpriv
->contexts
, list
)
538 tegra_drm_context_free(context
);
543 #ifdef CONFIG_DEBUG_FS
544 static int tegra_debugfs_framebuffers(struct seq_file
*s
, void *data
)
546 struct drm_info_node
*node
= (struct drm_info_node
*)s
->private;
547 struct drm_device
*drm
= node
->minor
->dev
;
548 struct drm_framebuffer
*fb
;
550 mutex_lock(&drm
->mode_config
.fb_lock
);
552 list_for_each_entry(fb
, &drm
->mode_config
.fb_list
, head
) {
553 seq_printf(s
, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
554 fb
->base
.id
, fb
->width
, fb
->height
, fb
->depth
,
556 atomic_read(&fb
->refcount
.refcount
));
559 mutex_unlock(&drm
->mode_config
.fb_lock
);
564 static struct drm_info_list tegra_debugfs_list
[] = {
565 { "framebuffers", tegra_debugfs_framebuffers
, 0 },
568 static int tegra_debugfs_init(struct drm_minor
*minor
)
570 return drm_debugfs_create_files(tegra_debugfs_list
,
571 ARRAY_SIZE(tegra_debugfs_list
),
572 minor
->debugfs_root
, minor
);
575 static void tegra_debugfs_cleanup(struct drm_minor
*minor
)
577 drm_debugfs_remove_files(tegra_debugfs_list
,
578 ARRAY_SIZE(tegra_debugfs_list
), minor
);
582 static struct drm_driver tegra_drm_driver
= {
583 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_PRIME
,
584 .load
= tegra_drm_load
,
585 .unload
= tegra_drm_unload
,
586 .open
= tegra_drm_open
,
587 .preclose
= tegra_drm_preclose
,
588 .lastclose
= tegra_drm_lastclose
,
590 .get_vblank_counter
= tegra_drm_get_vblank_counter
,
591 .enable_vblank
= tegra_drm_enable_vblank
,
592 .disable_vblank
= tegra_drm_disable_vblank
,
594 #if defined(CONFIG_DEBUG_FS)
595 .debugfs_init
= tegra_debugfs_init
,
596 .debugfs_cleanup
= tegra_debugfs_cleanup
,
599 .gem_free_object
= tegra_bo_free_object
,
600 .gem_vm_ops
= &tegra_bo_vm_ops
,
602 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
603 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
604 .gem_prime_export
= tegra_gem_prime_export
,
605 .gem_prime_import
= tegra_gem_prime_import
,
607 .dumb_create
= tegra_bo_dumb_create
,
608 .dumb_map_offset
= tegra_bo_dumb_map_offset
,
609 .dumb_destroy
= drm_gem_dumb_destroy
,
611 .ioctls
= tegra_drm_ioctls
,
612 .num_ioctls
= ARRAY_SIZE(tegra_drm_ioctls
),
613 .fops
= &tegra_drm_fops
,
618 .major
= DRIVER_MAJOR
,
619 .minor
= DRIVER_MINOR
,
620 .patchlevel
= DRIVER_PATCHLEVEL
,
623 int tegra_drm_register_client(struct tegra_drm
*tegra
,
624 struct tegra_drm_client
*client
)
626 mutex_lock(&tegra
->clients_lock
);
627 list_add_tail(&client
->list
, &tegra
->clients
);
628 mutex_unlock(&tegra
->clients_lock
);
633 int tegra_drm_unregister_client(struct tegra_drm
*tegra
,
634 struct tegra_drm_client
*client
)
636 mutex_lock(&tegra
->clients_lock
);
637 list_del_init(&client
->list
);
638 mutex_unlock(&tegra
->clients_lock
);
643 static int host1x_drm_probe(struct host1x_device
*device
)
645 return drm_host1x_init(&tegra_drm_driver
, device
);
648 static int host1x_drm_remove(struct host1x_device
*device
)
650 drm_host1x_exit(&tegra_drm_driver
, device
);
655 static const struct of_device_id host1x_drm_subdevs
[] = {
656 { .compatible
= "nvidia,tegra20-dc", },
657 { .compatible
= "nvidia,tegra20-hdmi", },
658 { .compatible
= "nvidia,tegra20-gr2d", },
659 { .compatible
= "nvidia,tegra20-gr3d", },
660 { .compatible
= "nvidia,tegra30-dc", },
661 { .compatible
= "nvidia,tegra30-hdmi", },
662 { .compatible
= "nvidia,tegra30-gr2d", },
663 { .compatible
= "nvidia,tegra30-gr3d", },
664 { .compatible
= "nvidia,tegra114-dsi", },
665 { .compatible
= "nvidia,tegra114-hdmi", },
666 { .compatible
= "nvidia,tegra114-gr3d", },
667 { .compatible
= "nvidia,tegra124-dc", },
668 { .compatible
= "nvidia,tegra124-sor", },
669 { .compatible
= "nvidia,tegra124-hdmi", },
673 static struct host1x_driver host1x_drm_driver
= {
675 .probe
= host1x_drm_probe
,
676 .remove
= host1x_drm_remove
,
677 .subdevs
= host1x_drm_subdevs
,
680 static int __init
host1x_drm_init(void)
684 err
= host1x_driver_register(&host1x_drm_driver
);
688 err
= platform_driver_register(&tegra_dc_driver
);
690 goto unregister_host1x
;
692 err
= platform_driver_register(&tegra_dsi_driver
);
696 err
= platform_driver_register(&tegra_sor_driver
);
700 err
= platform_driver_register(&tegra_hdmi_driver
);
704 err
= platform_driver_register(&tegra_dpaux_driver
);
706 goto unregister_hdmi
;
708 err
= platform_driver_register(&tegra_gr2d_driver
);
710 goto unregister_dpaux
;
712 err
= platform_driver_register(&tegra_gr3d_driver
);
714 goto unregister_gr2d
;
719 platform_driver_unregister(&tegra_gr2d_driver
);
721 platform_driver_unregister(&tegra_dpaux_driver
);
723 platform_driver_unregister(&tegra_hdmi_driver
);
725 platform_driver_unregister(&tegra_sor_driver
);
727 platform_driver_unregister(&tegra_dsi_driver
);
729 platform_driver_unregister(&tegra_dc_driver
);
731 host1x_driver_unregister(&host1x_drm_driver
);
734 module_init(host1x_drm_init
);
736 static void __exit
host1x_drm_exit(void)
738 platform_driver_unregister(&tegra_gr3d_driver
);
739 platform_driver_unregister(&tegra_gr2d_driver
);
740 platform_driver_unregister(&tegra_dpaux_driver
);
741 platform_driver_unregister(&tegra_hdmi_driver
);
742 platform_driver_unregister(&tegra_sor_driver
);
743 platform_driver_unregister(&tegra_dsi_driver
);
744 platform_driver_unregister(&tegra_dc_driver
);
745 host1x_driver_unregister(&host1x_drm_driver
);
747 module_exit(host1x_drm_exit
);
749 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
750 MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
751 MODULE_LICENSE("GPL v2");