drm/etnaviv: Expose our reservation object when exporting a dmabuf.
[linux-2.6-block.git] / drivers / gpu / drm / etnaviv / etnaviv_drv.c
CommitLineData
a8c21a54
T
1/*
2 * Copyright (C) 2015 Etnaviv Project
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/component.h>
18#include <linux/of_platform.h>
97ac0e47 19#include <drm/drm_of.h>
a8c21a54 20
ea1f5729 21#include "etnaviv_cmdbuf.h"
a8c21a54
T
22#include "etnaviv_drv.h"
23#include "etnaviv_gpu.h"
24#include "etnaviv_gem.h"
25#include "etnaviv_mmu.h"
a8c21a54
T
26
27#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
28static bool reglog;
29MODULE_PARM_DESC(reglog, "Enable register read/write logging");
30module_param(reglog, bool, 0600);
31#else
32#define reglog 0
33#endif
34
35void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name,
36 const char *dbgname)
37{
38 struct resource *res;
39 void __iomem *ptr;
40
41 if (name)
42 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
43 else
44 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
45
46 ptr = devm_ioremap_resource(&pdev->dev, res);
47 if (IS_ERR(ptr)) {
48 dev_err(&pdev->dev, "failed to ioremap %s: %ld\n", name,
49 PTR_ERR(ptr));
50 return ptr;
51 }
52
53 if (reglog)
54 dev_printk(KERN_DEBUG, &pdev->dev, "IO:region %s 0x%p %08zx\n",
55 dbgname, ptr, (size_t)resource_size(res));
56
57 return ptr;
58}
59
60void etnaviv_writel(u32 data, void __iomem *addr)
61{
62 if (reglog)
63 printk(KERN_DEBUG "IO:W %p %08x\n", addr, data);
64
65 writel(data, addr);
66}
67
68u32 etnaviv_readl(const void __iomem *addr)
69{
70 u32 val = readl(addr);
71
72 if (reglog)
73 printk(KERN_DEBUG "IO:R %p %08x\n", addr, val);
74
75 return val;
76}
77
78/*
79 * DRM operations:
80 */
81
82
83static void load_gpu(struct drm_device *dev)
84{
85 struct etnaviv_drm_private *priv = dev->dev_private;
86 unsigned int i;
87
88 for (i = 0; i < ETNA_MAX_PIPES; i++) {
89 struct etnaviv_gpu *g = priv->gpu[i];
90
91 if (g) {
92 int ret;
93
94 ret = etnaviv_gpu_init(g);
c1c77b0e 95 if (ret)
a8c21a54 96 priv->gpu[i] = NULL;
a8c21a54
T
97 }
98 }
99}
100
101static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
102{
103 struct etnaviv_file_private *ctx;
104
105 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
106 if (!ctx)
107 return -ENOMEM;
108
109 file->driver_priv = ctx;
110
111 return 0;
112}
113
fda8fa5b 114static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file)
a8c21a54
T
115{
116 struct etnaviv_drm_private *priv = dev->dev_private;
117 struct etnaviv_file_private *ctx = file->driver_priv;
118 unsigned int i;
119
120 for (i = 0; i < ETNA_MAX_PIPES; i++) {
121 struct etnaviv_gpu *gpu = priv->gpu[i];
122
123 if (gpu) {
124 mutex_lock(&gpu->lock);
125 if (gpu->lastctx == ctx)
126 gpu->lastctx = NULL;
127 mutex_unlock(&gpu->lock);
128 }
129 }
130
131 kfree(ctx);
132}
133
134/*
135 * DRM debugfs:
136 */
137
138#ifdef CONFIG_DEBUG_FS
139static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m)
140{
141 struct etnaviv_drm_private *priv = dev->dev_private;
142
143 etnaviv_gem_describe_objects(priv, m);
144
145 return 0;
146}
147
148static int etnaviv_mm_show(struct drm_device *dev, struct seq_file *m)
149{
b5c3714f 150 struct drm_printer p = drm_seq_file_printer(m);
a8c21a54
T
151
152 read_lock(&dev->vma_offset_manager->vm_lock);
b5c3714f 153 drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p);
a8c21a54
T
154 read_unlock(&dev->vma_offset_manager->vm_lock);
155
b5c3714f 156 return 0;
a8c21a54
T
157}
158
159static int etnaviv_mmu_show(struct etnaviv_gpu *gpu, struct seq_file *m)
160{
b5c3714f
DV
161 struct drm_printer p = drm_seq_file_printer(m);
162
a8c21a54
T
163 seq_printf(m, "Active Objects (%s):\n", dev_name(gpu->dev));
164
165 mutex_lock(&gpu->mmu->lock);
b5c3714f 166 drm_mm_print(&gpu->mmu->mm, &p);
a8c21a54
T
167 mutex_unlock(&gpu->mmu->lock);
168
169 return 0;
170}
171
172static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m)
173{
174 struct etnaviv_cmdbuf *buf = gpu->buffer;
175 u32 size = buf->size;
176 u32 *ptr = buf->vaddr;
177 u32 i;
178
179 seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n",
9912b4db
LS
180 buf->vaddr, (u64)etnaviv_cmdbuf_get_pa(buf),
181 size - buf->user_size);
a8c21a54
T
182
183 for (i = 0; i < size / 4; i++) {
184 if (i && !(i % 4))
185 seq_puts(m, "\n");
186 if (i % 4 == 0)
187 seq_printf(m, "\t0x%p: ", ptr + i);
188 seq_printf(m, "%08x ", *(ptr + i));
189 }
190 seq_puts(m, "\n");
191}
192
193static int etnaviv_ring_show(struct etnaviv_gpu *gpu, struct seq_file *m)
194{
195 seq_printf(m, "Ring Buffer (%s): ", dev_name(gpu->dev));
196
197 mutex_lock(&gpu->lock);
198 etnaviv_buffer_dump(gpu, m);
199 mutex_unlock(&gpu->lock);
200
201 return 0;
202}
203
204static int show_unlocked(struct seq_file *m, void *arg)
205{
206 struct drm_info_node *node = (struct drm_info_node *) m->private;
207 struct drm_device *dev = node->minor->dev;
208 int (*show)(struct drm_device *dev, struct seq_file *m) =
209 node->info_ent->data;
210
211 return show(dev, m);
212}
213
214static int show_each_gpu(struct seq_file *m, void *arg)
215{
216 struct drm_info_node *node = (struct drm_info_node *) m->private;
217 struct drm_device *dev = node->minor->dev;
218 struct etnaviv_drm_private *priv = dev->dev_private;
219 struct etnaviv_gpu *gpu;
220 int (*show)(struct etnaviv_gpu *gpu, struct seq_file *m) =
221 node->info_ent->data;
222 unsigned int i;
223 int ret = 0;
224
225 for (i = 0; i < ETNA_MAX_PIPES; i++) {
226 gpu = priv->gpu[i];
227 if (!gpu)
228 continue;
229
230 ret = show(gpu, m);
231 if (ret < 0)
232 break;
233 }
234
235 return ret;
236}
237
238static struct drm_info_list etnaviv_debugfs_list[] = {
239 {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs},
240 {"gem", show_unlocked, 0, etnaviv_gem_show},
241 { "mm", show_unlocked, 0, etnaviv_mm_show },
242 {"mmu", show_each_gpu, 0, etnaviv_mmu_show},
243 {"ring", show_each_gpu, 0, etnaviv_ring_show},
244};
245
246static int etnaviv_debugfs_init(struct drm_minor *minor)
247{
248 struct drm_device *dev = minor->dev;
249 int ret;
250
251 ret = drm_debugfs_create_files(etnaviv_debugfs_list,
252 ARRAY_SIZE(etnaviv_debugfs_list),
253 minor->debugfs_root, minor);
254
255 if (ret) {
256 dev_err(dev->dev, "could not install etnaviv_debugfs_list\n");
257 return ret;
258 }
259
260 return ret;
261}
a8c21a54
T
262#endif
263
264/*
265 * DRM ioctls:
266 */
267
268static int etnaviv_ioctl_get_param(struct drm_device *dev, void *data,
269 struct drm_file *file)
270{
271 struct etnaviv_drm_private *priv = dev->dev_private;
272 struct drm_etnaviv_param *args = data;
273 struct etnaviv_gpu *gpu;
274
275 if (args->pipe >= ETNA_MAX_PIPES)
276 return -EINVAL;
277
278 gpu = priv->gpu[args->pipe];
279 if (!gpu)
280 return -ENXIO;
281
282 return etnaviv_gpu_get_param(gpu, args->param, &args->value);
283}
284
285static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data,
286 struct drm_file *file)
287{
288 struct drm_etnaviv_gem_new *args = data;
289
290 if (args->flags & ~(ETNA_BO_CACHED | ETNA_BO_WC | ETNA_BO_UNCACHED |
291 ETNA_BO_FORCE_MMU))
292 return -EINVAL;
293
294 return etnaviv_gem_new_handle(dev, file, args->size,
295 args->flags, &args->handle);
296}
297
298#define TS(t) ((struct timespec){ \
299 .tv_sec = (t).tv_sec, \
300 .tv_nsec = (t).tv_nsec \
301})
302
303static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
304 struct drm_file *file)
305{
306 struct drm_etnaviv_gem_cpu_prep *args = data;
307 struct drm_gem_object *obj;
308 int ret;
309
310 if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC))
311 return -EINVAL;
312
a8ad0bd8 313 obj = drm_gem_object_lookup(file, args->handle);
a8c21a54
T
314 if (!obj)
315 return -ENOENT;
316
317 ret = etnaviv_gem_cpu_prep(obj, args->op, &TS(args->timeout));
318
319 drm_gem_object_unreference_unlocked(obj);
320
321 return ret;
322}
323
324static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
325 struct drm_file *file)
326{
327 struct drm_etnaviv_gem_cpu_fini *args = data;
328 struct drm_gem_object *obj;
329 int ret;
330
331 if (args->flags)
332 return -EINVAL;
333
a8ad0bd8 334 obj = drm_gem_object_lookup(file, args->handle);
a8c21a54
T
335 if (!obj)
336 return -ENOENT;
337
338 ret = etnaviv_gem_cpu_fini(obj);
339
340 drm_gem_object_unreference_unlocked(obj);
341
342 return ret;
343}
344
345static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data,
346 struct drm_file *file)
347{
348 struct drm_etnaviv_gem_info *args = data;
349 struct drm_gem_object *obj;
350 int ret;
351
352 if (args->pad)
353 return -EINVAL;
354
a8ad0bd8 355 obj = drm_gem_object_lookup(file, args->handle);
a8c21a54
T
356 if (!obj)
357 return -ENOENT;
358
359 ret = etnaviv_gem_mmap_offset(obj, &args->offset);
360 drm_gem_object_unreference_unlocked(obj);
361
362 return ret;
363}
364
365static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data,
366 struct drm_file *file)
367{
368 struct drm_etnaviv_wait_fence *args = data;
369 struct etnaviv_drm_private *priv = dev->dev_private;
370 struct timespec *timeout = &TS(args->timeout);
371 struct etnaviv_gpu *gpu;
372
373 if (args->flags & ~(ETNA_WAIT_NONBLOCK))
374 return -EINVAL;
375
376 if (args->pipe >= ETNA_MAX_PIPES)
377 return -EINVAL;
378
379 gpu = priv->gpu[args->pipe];
380 if (!gpu)
381 return -ENXIO;
382
383 if (args->flags & ETNA_WAIT_NONBLOCK)
384 timeout = NULL;
385
386 return etnaviv_gpu_wait_fence_interruptible(gpu, args->fence,
387 timeout);
388}
389
390static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data,
391 struct drm_file *file)
392{
393 struct drm_etnaviv_gem_userptr *args = data;
394 int access;
395
396 if (args->flags & ~(ETNA_USERPTR_READ|ETNA_USERPTR_WRITE) ||
397 args->flags == 0)
398 return -EINVAL;
399
400 if (offset_in_page(args->user_ptr | args->user_size) ||
401 (uintptr_t)args->user_ptr != args->user_ptr ||
402 (u32)args->user_size != args->user_size ||
403 args->user_ptr & ~PAGE_MASK)
404 return -EINVAL;
405
406 if (args->flags & ETNA_USERPTR_WRITE)
407 access = VERIFY_WRITE;
408 else
409 access = VERIFY_READ;
410
411 if (!access_ok(access, (void __user *)(unsigned long)args->user_ptr,
412 args->user_size))
413 return -EFAULT;
414
415 return etnaviv_gem_new_userptr(dev, file, args->user_ptr,
416 args->user_size, args->flags,
417 &args->handle);
418}
419
420static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data,
421 struct drm_file *file)
422{
423 struct etnaviv_drm_private *priv = dev->dev_private;
424 struct drm_etnaviv_gem_wait *args = data;
425 struct timespec *timeout = &TS(args->timeout);
426 struct drm_gem_object *obj;
427 struct etnaviv_gpu *gpu;
428 int ret;
429
430 if (args->flags & ~(ETNA_WAIT_NONBLOCK))
431 return -EINVAL;
432
433 if (args->pipe >= ETNA_MAX_PIPES)
434 return -EINVAL;
435
436 gpu = priv->gpu[args->pipe];
437 if (!gpu)
438 return -ENXIO;
439
a8ad0bd8 440 obj = drm_gem_object_lookup(file, args->handle);
a8c21a54
T
441 if (!obj)
442 return -ENOENT;
443
444 if (args->flags & ETNA_WAIT_NONBLOCK)
445 timeout = NULL;
446
447 ret = etnaviv_gem_wait_bo(gpu, obj, timeout);
448
449 drm_gem_object_unreference_unlocked(obj);
450
451 return ret;
452}
453
454static const struct drm_ioctl_desc etnaviv_ioctls[] = {
455#define ETNA_IOCTL(n, func, flags) \
456 DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
457 ETNA_IOCTL(GET_PARAM, get_param, DRM_AUTH|DRM_RENDER_ALLOW),
458 ETNA_IOCTL(GEM_NEW, gem_new, DRM_AUTH|DRM_RENDER_ALLOW),
459 ETNA_IOCTL(GEM_INFO, gem_info, DRM_AUTH|DRM_RENDER_ALLOW),
460 ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
461 ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
462 ETNA_IOCTL(GEM_SUBMIT, gem_submit, DRM_AUTH|DRM_RENDER_ALLOW),
463 ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW),
464 ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW),
465 ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW),
466};
467
468static const struct vm_operations_struct vm_ops = {
469 .fault = etnaviv_gem_fault,
470 .open = drm_gem_vm_open,
471 .close = drm_gem_vm_close,
472};
473
474static const struct file_operations fops = {
475 .owner = THIS_MODULE,
476 .open = drm_open,
477 .release = drm_release,
478 .unlocked_ioctl = drm_ioctl,
a8c21a54 479 .compat_ioctl = drm_compat_ioctl,
a8c21a54
T
480 .poll = drm_poll,
481 .read = drm_read,
482 .llseek = no_llseek,
483 .mmap = etnaviv_gem_mmap,
484};
485
486static struct drm_driver etnaviv_drm_driver = {
e1f96ef4 487 .driver_features = DRIVER_GEM |
a8c21a54
T
488 DRIVER_PRIME |
489 DRIVER_RENDER,
490 .open = etnaviv_open,
fda8fa5b 491 .postclose = etnaviv_postclose,
1d657c58 492 .gem_free_object_unlocked = etnaviv_gem_free_object,
a8c21a54
T
493 .gem_vm_ops = &vm_ops,
494 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
495 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
496 .gem_prime_export = drm_gem_prime_export,
497 .gem_prime_import = drm_gem_prime_import,
8555137e 498 .gem_prime_res_obj = etnaviv_gem_prime_res_obj,
a8c21a54
T
499 .gem_prime_pin = etnaviv_gem_prime_pin,
500 .gem_prime_unpin = etnaviv_gem_prime_unpin,
501 .gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table,
502 .gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
503 .gem_prime_vmap = etnaviv_gem_prime_vmap,
504 .gem_prime_vunmap = etnaviv_gem_prime_vunmap,
5688e57e 505 .gem_prime_mmap = etnaviv_gem_prime_mmap,
a8c21a54
T
506#ifdef CONFIG_DEBUG_FS
507 .debugfs_init = etnaviv_debugfs_init,
a8c21a54
T
508#endif
509 .ioctls = etnaviv_ioctls,
510 .num_ioctls = DRM_ETNAVIV_NUM_IOCTLS,
511 .fops = &fops,
512 .name = "etnaviv",
513 .desc = "etnaviv DRM",
514 .date = "20151214",
515 .major = 1,
78ec187f 516 .minor = 1,
a8c21a54
T
517};
518
519/*
520 * Platform driver:
521 */
522static int etnaviv_bind(struct device *dev)
523{
524 struct etnaviv_drm_private *priv;
525 struct drm_device *drm;
526 int ret;
527
528 drm = drm_dev_alloc(&etnaviv_drm_driver, dev);
0f288605
TG
529 if (IS_ERR(drm))
530 return PTR_ERR(drm);
a8c21a54 531
a8c21a54
T
532 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
533 if (!priv) {
534 dev_err(dev, "failed to allocate private data\n");
535 ret = -ENOMEM;
536 goto out_unref;
537 }
538 drm->dev_private = priv;
539
540 priv->wq = alloc_ordered_workqueue("etnaviv", 0);
541 if (!priv->wq) {
542 ret = -ENOMEM;
543 goto out_wq;
544 }
545
546 mutex_init(&priv->gem_lock);
547 INIT_LIST_HEAD(&priv->gem_list);
548 priv->num_gpus = 0;
549
550 dev_set_drvdata(dev, drm);
551
552 ret = component_bind_all(dev, drm);
553 if (ret < 0)
554 goto out_bind;
555
556 load_gpu(drm);
557
558 ret = drm_dev_register(drm, 0);
559 if (ret)
560 goto out_register;
561
562 return 0;
563
564out_register:
565 component_unbind_all(dev, drm);
566out_bind:
567 flush_workqueue(priv->wq);
568 destroy_workqueue(priv->wq);
569out_wq:
570 kfree(priv);
571out_unref:
572 drm_dev_unref(drm);
573
574 return ret;
575}
576
577static void etnaviv_unbind(struct device *dev)
578{
579 struct drm_device *drm = dev_get_drvdata(dev);
580 struct etnaviv_drm_private *priv = drm->dev_private;
581
582 drm_dev_unregister(drm);
583
584 flush_workqueue(priv->wq);
585 destroy_workqueue(priv->wq);
586
587 component_unbind_all(dev, drm);
588
589 drm->dev_private = NULL;
590 kfree(priv);
591
ecdfcebb 592 drm_dev_unref(drm);
a8c21a54
T
593}
594
595static const struct component_master_ops etnaviv_master_ops = {
596 .bind = etnaviv_bind,
597 .unbind = etnaviv_unbind,
598};
599
600static int compare_of(struct device *dev, void *data)
601{
602 struct device_node *np = data;
603
604 return dev->of_node == np;
605}
606
607static int compare_str(struct device *dev, void *data)
608{
609 return !strcmp(dev_name(dev), data);
610}
611
612static int etnaviv_pdev_probe(struct platform_device *pdev)
613{
614 struct device *dev = &pdev->dev;
615 struct device_node *node = dev->of_node;
616 struct component_match *match = NULL;
617
618 dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
619
620 if (node) {
621 struct device_node *core_node;
622 int i;
623
624 for (i = 0; ; i++) {
625 core_node = of_parse_phandle(node, "cores", i);
626 if (!core_node)
627 break;
628
97ac0e47
RK
629 drm_of_component_match_add(&pdev->dev, &match,
630 compare_of, core_node);
a8c21a54
T
631 of_node_put(core_node);
632 }
633 } else if (dev->platform_data) {
634 char **names = dev->platform_data;
635 unsigned i;
636
637 for (i = 0; names[i]; i++)
638 component_match_add(dev, &match, compare_str, names[i]);
639 }
640
641 return component_master_add_with_match(dev, &etnaviv_master_ops, match);
642}
643
644static int etnaviv_pdev_remove(struct platform_device *pdev)
645{
646 component_master_del(&pdev->dev, &etnaviv_master_ops);
647
648 return 0;
649}
650
651static const struct of_device_id dt_match[] = {
652 { .compatible = "fsl,imx-gpu-subsystem" },
653 { .compatible = "marvell,dove-gpu-subsystem" },
654 {}
655};
656MODULE_DEVICE_TABLE(of, dt_match);
657
658static struct platform_driver etnaviv_platform_driver = {
659 .probe = etnaviv_pdev_probe,
660 .remove = etnaviv_pdev_remove,
661 .driver = {
a8c21a54
T
662 .name = "etnaviv",
663 .of_match_table = dt_match,
664 },
665};
666
667static int __init etnaviv_init(void)
668{
669 int ret;
670
671 etnaviv_validate_init();
672
673 ret = platform_driver_register(&etnaviv_gpu_driver);
674 if (ret != 0)
675 return ret;
676
677 ret = platform_driver_register(&etnaviv_platform_driver);
678 if (ret != 0)
679 platform_driver_unregister(&etnaviv_gpu_driver);
680
681 return ret;
682}
683module_init(etnaviv_init);
684
685static void __exit etnaviv_exit(void)
686{
687 platform_driver_unregister(&etnaviv_gpu_driver);
688 platform_driver_unregister(&etnaviv_platform_driver);
689}
690module_exit(etnaviv_exit);
691
692MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>");
693MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
694MODULE_AUTHOR("Lucas Stach <l.stach@pengutronix.de>");
695MODULE_DESCRIPTION("etnaviv DRM Driver");
696MODULE_LICENSE("GPL v2");
697MODULE_ALIAS("platform:etnaviv");