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