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