]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/host1x/drm/drm.c
4e503613536bb3b96a9f132c9636ad732b874d70
[karo-tx-linux.git] / drivers / gpu / host1x / drm / drm.c
1 /*
2  * Copyright (C) 2012 Avionic Design GmbH
3  * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
4  *
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.
8  */
9
10 #include "host1x_client.h"
11 #include "dev.h"
12 #include "drm.h"
13 #include "gem.h"
14 #include "syncpt.h"
15
16 #define DRIVER_NAME "tegra"
17 #define DRIVER_DESC "NVIDIA Tegra graphics"
18 #define DRIVER_DATE "20120330"
19 #define DRIVER_MAJOR 0
20 #define DRIVER_MINOR 0
21 #define DRIVER_PATCHLEVEL 0
22
23 struct tegra_drm_file {
24         struct list_head contexts;
25 };
26
27 struct host1x_subdev {
28         struct host1x_client *client;
29         struct device_node *np;
30         struct list_head list;
31 };
32
33 static int host1x_subdev_add(struct tegra_drm *tegra, struct device_node *np)
34 {
35         struct host1x_subdev *subdev;
36
37         subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
38         if (!subdev)
39                 return -ENOMEM;
40
41         INIT_LIST_HEAD(&subdev->list);
42         subdev->np = of_node_get(np);
43
44         list_add_tail(&subdev->list, &tegra->subdevs);
45
46         return 0;
47 }
48
49 static int host1x_subdev_register(struct tegra_drm *tegra,
50                                   struct host1x_subdev *subdev,
51                                   struct host1x_client *client)
52 {
53         mutex_lock(&tegra->subdevs_lock);
54         list_del_init(&subdev->list);
55         list_add_tail(&subdev->list, &tegra->active);
56         subdev->client = client;
57         mutex_unlock(&tegra->subdevs_lock);
58
59         return 0;
60 }
61
62 static int host1x_subdev_unregister(struct tegra_drm *tegra,
63                                     struct host1x_subdev *subdev)
64 {
65         mutex_lock(&tegra->subdevs_lock);
66         list_del_init(&subdev->list);
67         mutex_unlock(&tegra->subdevs_lock);
68
69         of_node_put(subdev->np);
70         kfree(subdev);
71
72         return 0;
73 }
74
75 static int tegra_parse_dt(struct tegra_drm *tegra)
76 {
77         static const char * const compat[] = {
78                 "nvidia,tegra20-dc",
79                 "nvidia,tegra20-hdmi",
80                 "nvidia,tegra20-gr2d",
81                 "nvidia,tegra30-dc",
82                 "nvidia,tegra30-hdmi",
83                 "nvidia,tegra30-gr2d",
84         };
85         unsigned int i;
86         int err;
87
88         for (i = 0; i < ARRAY_SIZE(compat); i++) {
89                 struct device_node *np;
90
91                 for_each_child_of_node(tegra->dev->of_node, np) {
92                         if (of_device_is_compatible(np, compat[i]) &&
93                             of_device_is_available(np)) {
94                                 err = host1x_subdev_add(tegra, np);
95                                 if (err < 0)
96                                         return err;
97                         }
98                 }
99         }
100
101         return 0;
102 }
103
104 int tegra_drm_alloc(struct platform_device *pdev)
105 {
106         struct tegra_drm *tegra;
107         int err;
108
109         tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
110         if (!tegra)
111                 return -ENOMEM;
112
113         mutex_init(&tegra->subdevs_lock);
114         INIT_LIST_HEAD(&tegra->subdevs);
115         INIT_LIST_HEAD(&tegra->active);
116         mutex_init(&tegra->clients_lock);
117         INIT_LIST_HEAD(&tegra->clients);
118         tegra->dev = &pdev->dev;
119
120         err = tegra_parse_dt(tegra);
121         if (err < 0) {
122                 dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
123                 return err;
124         }
125
126         host1x_set_drm_data(&pdev->dev, tegra);
127
128         return 0;
129 }
130
131 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm)
132 {
133         struct host1x_client *client;
134
135         mutex_lock(&tegra->clients_lock);
136
137         list_for_each_entry(client, &tegra->clients, list) {
138                 if (client->ops && client->ops->drm_init) {
139                         int err = client->ops->drm_init(client, drm);
140                         if (err < 0) {
141                                 dev_err(tegra->dev,
142                                         "DRM setup failed for %s: %d\n",
143                                         dev_name(client->dev), err);
144                                 mutex_unlock(&tegra->clients_lock);
145                                 return err;
146                         }
147                 }
148         }
149
150         mutex_unlock(&tegra->clients_lock);
151
152         return 0;
153 }
154
155 int tegra_drm_exit(struct tegra_drm *tegra)
156 {
157         struct platform_device *pdev = to_platform_device(tegra->dev);
158         struct host1x_client *client;
159
160         if (!tegra->drm)
161                 return 0;
162
163         mutex_lock(&tegra->clients_lock);
164
165         list_for_each_entry_reverse(client, &tegra->clients, list) {
166                 if (client->ops && client->ops->drm_exit) {
167                         int err = client->ops->drm_exit(client);
168                         if (err < 0) {
169                                 dev_err(tegra->dev,
170                                         "DRM cleanup failed for %s: %d\n",
171                                         dev_name(client->dev), err);
172                                 mutex_unlock(&tegra->clients_lock);
173                                 return err;
174                         }
175                 }
176         }
177
178         mutex_unlock(&tegra->clients_lock);
179
180         drm_platform_exit(&tegra_drm_driver, pdev);
181         tegra->drm = NULL;
182
183         return 0;
184 }
185
186 int host1x_register_client(struct tegra_drm *tegra,
187                            struct host1x_client *client)
188 {
189         struct host1x_subdev *subdev, *tmp;
190         int err;
191
192         mutex_lock(&tegra->clients_lock);
193         list_add_tail(&client->list, &tegra->clients);
194         mutex_unlock(&tegra->clients_lock);
195
196         list_for_each_entry_safe(subdev, tmp, &tegra->subdevs, list)
197                 if (subdev->np == client->dev->of_node)
198                         host1x_subdev_register(tegra, subdev, client);
199
200         if (list_empty(&tegra->subdevs)) {
201                 struct platform_device *pdev = to_platform_device(tegra->dev);
202
203                 err = drm_platform_init(&tegra_drm_driver, pdev);
204                 if (err < 0) {
205                         dev_err(tegra->dev, "drm_platform_init(): %d\n", err);
206                         return err;
207                 }
208         }
209
210         return 0;
211 }
212
213 int host1x_unregister_client(struct tegra_drm *tegra,
214                              struct host1x_client *client)
215 {
216         struct host1x_subdev *subdev, *tmp;
217         int err;
218
219         list_for_each_entry_safe(subdev, tmp, &tegra->active, list) {
220                 if (subdev->client == client) {
221                         err = tegra_drm_exit(tegra);
222                         if (err < 0) {
223                                 dev_err(tegra->dev, "tegra_drm_exit(): %d\n",
224                                         err);
225                                 return err;
226                         }
227
228                         host1x_subdev_unregister(tegra, subdev);
229                         break;
230                 }
231         }
232
233         mutex_lock(&tegra->clients_lock);
234         list_del_init(&client->list);
235         mutex_unlock(&tegra->clients_lock);
236
237         return 0;
238 }
239
240 static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
241 {
242         struct tegra_drm *tegra;
243         int err;
244
245         tegra = host1x_get_drm_data(drm->dev);
246         drm->dev_private = tegra;
247         tegra->drm = drm;
248
249         drm_mode_config_init(drm);
250
251         err = tegra_drm_init(tegra, drm);
252         if (err < 0)
253                 return err;
254
255         /*
256          * We don't use the drm_irq_install() helpers provided by the DRM
257          * core, so we need to set this manually in order to allow the
258          * DRM_IOCTL_WAIT_VBLANK to operate correctly.
259          */
260         drm->irq_enabled = true;
261
262         err = drm_vblank_init(drm, drm->mode_config.num_crtc);
263         if (err < 0)
264                 return err;
265
266         err = tegra_drm_fb_init(drm);
267         if (err < 0)
268                 return err;
269
270         drm_kms_helper_poll_init(drm);
271
272         return 0;
273 }
274
275 static int tegra_drm_unload(struct drm_device *drm)
276 {
277         drm_kms_helper_poll_fini(drm);
278         tegra_drm_fb_exit(drm);
279
280         drm_mode_config_cleanup(drm);
281
282         return 0;
283 }
284
285 static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
286 {
287         struct tegra_drm_file *fpriv;
288
289         fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
290         if (!fpriv)
291                 return -ENOMEM;
292
293         INIT_LIST_HEAD(&fpriv->contexts);
294         filp->driver_priv = fpriv;
295
296         return 0;
297 }
298
299 static void tegra_drm_context_free(struct tegra_drm_context *context)
300 {
301         context->client->ops->close_channel(context);
302         kfree(context);
303 }
304
305 static void tegra_drm_lastclose(struct drm_device *drm)
306 {
307         struct tegra_drm *tegra = drm->dev_private;
308
309         tegra_fbdev_restore_mode(tegra->fbdev);
310 }
311
312 #ifdef CONFIG_DRM_TEGRA_STAGING
313 static struct tegra_drm_context *tegra_drm_get_context(__u64 context)
314 {
315         return (struct tegra_drm_context *)(uintptr_t)context;
316 }
317
318 static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
319                                         struct tegra_drm_context *context)
320 {
321         struct tegra_drm_context *ctx;
322
323         list_for_each_entry(ctx, &file->contexts, list)
324                 if (ctx == context)
325                         return true;
326
327         return false;
328 }
329
330 static int tegra_gem_create(struct drm_device *drm, void *data,
331                             struct drm_file *file)
332 {
333         struct drm_tegra_gem_create *args = data;
334         struct tegra_bo *bo;
335
336         bo = tegra_bo_create_with_handle(file, drm, args->size,
337                                          &args->handle);
338         if (IS_ERR(bo))
339                 return PTR_ERR(bo);
340
341         return 0;
342 }
343
344 static int tegra_gem_mmap(struct drm_device *drm, void *data,
345                           struct drm_file *file)
346 {
347         struct drm_tegra_gem_mmap *args = data;
348         struct drm_gem_object *gem;
349         struct tegra_bo *bo;
350
351         gem = drm_gem_object_lookup(drm, file, args->handle);
352         if (!gem)
353                 return -EINVAL;
354
355         bo = to_tegra_bo(gem);
356
357         args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
358
359         drm_gem_object_unreference(gem);
360
361         return 0;
362 }
363
364 static int tegra_syncpt_read(struct drm_device *drm, void *data,
365                              struct drm_file *file)
366 {
367         struct drm_tegra_syncpt_read *args = data;
368         struct host1x *host = dev_get_drvdata(drm->dev);
369         struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
370
371         if (!sp)
372                 return -EINVAL;
373
374         args->value = host1x_syncpt_read_min(sp);
375         return 0;
376 }
377
378 static int tegra_syncpt_incr(struct drm_device *drm, void *data,
379                              struct drm_file *file)
380 {
381         struct drm_tegra_syncpt_incr *args = data;
382         struct host1x *host = dev_get_drvdata(drm->dev);
383         struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
384
385         if (!sp)
386                 return -EINVAL;
387
388         return host1x_syncpt_incr(sp);
389 }
390
391 static int tegra_syncpt_wait(struct drm_device *drm, void *data,
392                              struct drm_file *file)
393 {
394         struct drm_tegra_syncpt_wait *args = data;
395         struct host1x *host = dev_get_drvdata(drm->dev);
396         struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
397
398         if (!sp)
399                 return -EINVAL;
400
401         return host1x_syncpt_wait(sp, args->thresh, args->timeout,
402                                   &args->value);
403 }
404
405 static int tegra_open_channel(struct drm_device *drm, void *data,
406                               struct drm_file *file)
407 {
408         struct tegra_drm_file *fpriv = file->driver_priv;
409         struct tegra_drm *tegra = drm->dev_private;
410         struct drm_tegra_open_channel *args = data;
411         struct tegra_drm_context *context;
412         struct host1x_client *client;
413         int err = -ENODEV;
414
415         context = kzalloc(sizeof(*context), GFP_KERNEL);
416         if (!context)
417                 return -ENOMEM;
418
419         list_for_each_entry(client, &tegra->clients, list)
420                 if (client->class == args->client) {
421                         err = client->ops->open_channel(client, context);
422                         if (err)
423                                 break;
424
425                         context->client = client;
426                         list_add(&context->list, &fpriv->contexts);
427                         args->context = (uintptr_t)context;
428                         return 0;
429                 }
430
431         kfree(context);
432         return err;
433 }
434
435 static int tegra_close_channel(struct drm_device *drm, void *data,
436                                struct drm_file *file)
437 {
438         struct drm_tegra_close_channel *args = data;
439         struct tegra_drm_file *fpriv = file->driver_priv;
440         struct tegra_drm_context *context;
441
442         context = tegra_drm_get_context(args->context);
443
444         if (!tegra_drm_file_owns_context(fpriv, context))
445                 return -EINVAL;
446
447         list_del(&context->list);
448         tegra_drm_context_free(context);
449
450         return 0;
451 }
452
453 static int tegra_get_syncpt(struct drm_device *drm, void *data,
454                             struct drm_file *file)
455 {
456         struct tegra_drm_file *fpriv = file->driver_priv;
457         struct drm_tegra_get_syncpt *args = data;
458         struct tegra_drm_context *context;
459         struct host1x_syncpt *syncpt;
460
461         context = tegra_drm_get_context(args->context);
462
463         if (!tegra_drm_file_owns_context(fpriv, context))
464                 return -ENODEV;
465
466         if (args->index >= context->client->num_syncpts)
467                 return -EINVAL;
468
469         syncpt = context->client->syncpts[args->index];
470         args->id = host1x_syncpt_id(syncpt);
471
472         return 0;
473 }
474
475 static int tegra_submit(struct drm_device *drm, void *data,
476                         struct drm_file *file)
477 {
478         struct tegra_drm_file *fpriv = file->driver_priv;
479         struct drm_tegra_submit *args = data;
480         struct tegra_drm_context *context;
481
482         context = tegra_drm_get_context(args->context);
483
484         if (!tegra_drm_file_owns_context(fpriv, context))
485                 return -ENODEV;
486
487         return context->client->ops->submit(context, args, drm, file);
488 }
489 #endif
490
491 static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
492 #ifdef CONFIG_DRM_TEGRA_STAGING
493         DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
494         DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
495         DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
496         DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
497         DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED),
498         DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED),
499         DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED),
500         DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
501         DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
502 #endif
503 };
504
505 static const struct file_operations tegra_drm_fops = {
506         .owner = THIS_MODULE,
507         .open = drm_open,
508         .release = drm_release,
509         .unlocked_ioctl = drm_ioctl,
510         .mmap = tegra_drm_mmap,
511         .poll = drm_poll,
512         .read = drm_read,
513 #ifdef CONFIG_COMPAT
514         .compat_ioctl = drm_compat_ioctl,
515 #endif
516         .llseek = noop_llseek,
517 };
518
519 static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe)
520 {
521         struct drm_crtc *crtc;
522
523         list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) {
524                 struct tegra_dc *dc = to_tegra_dc(crtc);
525
526                 if (dc->pipe == pipe)
527                         return crtc;
528         }
529
530         return NULL;
531 }
532
533 static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc)
534 {
535         /* TODO: implement real hardware counter using syncpoints */
536         return drm_vblank_count(dev, crtc);
537 }
538
539 static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
540 {
541         struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
542         struct tegra_dc *dc = to_tegra_dc(crtc);
543
544         if (!crtc)
545                 return -ENODEV;
546
547         tegra_dc_enable_vblank(dc);
548
549         return 0;
550 }
551
552 static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
553 {
554         struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
555         struct tegra_dc *dc = to_tegra_dc(crtc);
556
557         if (crtc)
558                 tegra_dc_disable_vblank(dc);
559 }
560
561 static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
562 {
563         struct tegra_drm_file *fpriv = file->driver_priv;
564         struct tegra_drm_context *context, *tmp;
565         struct drm_crtc *crtc;
566
567         list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
568                 tegra_dc_cancel_page_flip(crtc, file);
569
570         list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
571                 tegra_drm_context_free(context);
572
573         kfree(fpriv);
574 }
575
576 #ifdef CONFIG_DEBUG_FS
577 static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
578 {
579         struct drm_info_node *node = (struct drm_info_node *)s->private;
580         struct drm_device *drm = node->minor->dev;
581         struct drm_framebuffer *fb;
582
583         mutex_lock(&drm->mode_config.fb_lock);
584
585         list_for_each_entry(fb, &drm->mode_config.fb_list, head) {
586                 seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
587                            fb->base.id, fb->width, fb->height, fb->depth,
588                            fb->bits_per_pixel,
589                            atomic_read(&fb->refcount.refcount));
590         }
591
592         mutex_unlock(&drm->mode_config.fb_lock);
593
594         return 0;
595 }
596
597 static struct drm_info_list tegra_debugfs_list[] = {
598         { "framebuffers", tegra_debugfs_framebuffers, 0 },
599 };
600
601 static int tegra_debugfs_init(struct drm_minor *minor)
602 {
603         return drm_debugfs_create_files(tegra_debugfs_list,
604                                         ARRAY_SIZE(tegra_debugfs_list),
605                                         minor->debugfs_root, minor);
606 }
607
608 static void tegra_debugfs_cleanup(struct drm_minor *minor)
609 {
610         drm_debugfs_remove_files(tegra_debugfs_list,
611                                  ARRAY_SIZE(tegra_debugfs_list), minor);
612 }
613 #endif
614
615 struct drm_driver tegra_drm_driver = {
616         .driver_features = DRIVER_MODESET | DRIVER_GEM,
617         .load = tegra_drm_load,
618         .unload = tegra_drm_unload,
619         .open = tegra_drm_open,
620         .preclose = tegra_drm_preclose,
621         .lastclose = tegra_drm_lastclose,
622
623         .get_vblank_counter = tegra_drm_get_vblank_counter,
624         .enable_vblank = tegra_drm_enable_vblank,
625         .disable_vblank = tegra_drm_disable_vblank,
626
627 #if defined(CONFIG_DEBUG_FS)
628         .debugfs_init = tegra_debugfs_init,
629         .debugfs_cleanup = tegra_debugfs_cleanup,
630 #endif
631
632         .gem_free_object = tegra_bo_free_object,
633         .gem_vm_ops = &tegra_bo_vm_ops,
634         .dumb_create = tegra_bo_dumb_create,
635         .dumb_map_offset = tegra_bo_dumb_map_offset,
636         .dumb_destroy = drm_gem_dumb_destroy,
637
638         .ioctls = tegra_drm_ioctls,
639         .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
640         .fops = &tegra_drm_fops,
641
642         .name = DRIVER_NAME,
643         .desc = DRIVER_DESC,
644         .date = DRIVER_DATE,
645         .major = DRIVER_MAJOR,
646         .minor = DRIVER_MINOR,
647         .patchlevel = DRIVER_PATCHLEVEL,
648 };