drm/exynos: remove redundant mutex_unlock
[cascardo/linux.git] / drivers / gpu / drm / exynos / exynos_drm_drv.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
3  * Authors:
4  *      Inki Dae <inki.dae@samsung.com>
5  *      Joonyoung Shim <jy0922.shim@samsung.com>
6  *      Seung-Woo Kim <sw0312.kim@samsung.com>
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13
14 #include <linux/pm_runtime.h>
15 #include <drm/drmP.h>
16 #include <drm/drm_crtc_helper.h>
17
18 #include <linux/anon_inodes.h>
19 #include <linux/component.h>
20
21 #include <drm/exynos_drm.h>
22
23 #include "exynos_drm_drv.h"
24 #include "exynos_drm_crtc.h"
25 #include "exynos_drm_encoder.h"
26 #include "exynos_drm_fbdev.h"
27 #include "exynos_drm_fb.h"
28 #include "exynos_drm_gem.h"
29 #include "exynos_drm_plane.h"
30 #include "exynos_drm_vidi.h"
31 #include "exynos_drm_dmabuf.h"
32 #include "exynos_drm_g2d.h"
33 #include "exynos_drm_ipp.h"
34 #include "exynos_drm_iommu.h"
35
36 #define DRIVER_NAME     "exynos"
37 #define DRIVER_DESC     "Samsung SoC DRM"
38 #define DRIVER_DATE     "20110530"
39 #define DRIVER_MAJOR    1
40 #define DRIVER_MINOR    0
41
42 #define VBLANK_OFF_DELAY        50000
43
44 static struct platform_device *exynos_drm_pdev;
45
46 static DEFINE_MUTEX(drm_component_lock);
47 static LIST_HEAD(drm_component_list);
48
49 struct component_dev {
50         struct list_head list;
51         struct device *dev;
52 };
53
54 static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
55 {
56         struct exynos_drm_private *private;
57         int ret;
58         int nr;
59
60         private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
61         if (!private)
62                 return -ENOMEM;
63
64         INIT_LIST_HEAD(&private->pageflip_event_list);
65         dev_set_drvdata(dev->dev, dev);
66         dev->dev_private = (void *)private;
67
68         /*
69          * create mapping to manage iommu table and set a pointer to iommu
70          * mapping structure to iommu_mapping of private data.
71          * also this iommu_mapping can be used to check if iommu is supported
72          * or not.
73          */
74         ret = drm_create_iommu_mapping(dev);
75         if (ret < 0) {
76                 DRM_ERROR("failed to create iommu mapping.\n");
77                 goto err_free_private;
78         }
79
80         drm_mode_config_init(dev);
81
82         exynos_drm_mode_config_init(dev);
83
84         for (nr = 0; nr < MAX_PLANE; nr++) {
85                 struct drm_plane *plane;
86                 unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
87
88                 plane = exynos_plane_init(dev, possible_crtcs, false);
89                 if (!plane)
90                         goto err_mode_config_cleanup;
91         }
92
93         /* init kms poll for handling hpd */
94         drm_kms_helper_poll_init(dev);
95
96         ret = drm_vblank_init(dev, MAX_CRTC);
97         if (ret)
98                 goto err_mode_config_cleanup;
99
100         /* setup possible_clones. */
101         exynos_drm_encoder_setup(dev);
102
103         drm_vblank_offdelay = VBLANK_OFF_DELAY;
104
105         platform_set_drvdata(dev->platformdev, dev);
106
107         /* Try to bind all sub drivers. */
108         ret = component_bind_all(dev->dev, dev);
109         if (ret)
110                 goto err_cleanup_vblank;
111
112         /* Probe non kms sub drivers and virtual display driver. */
113         ret = exynos_drm_device_subdrv_probe(dev);
114         if (ret)
115                 goto err_unbind_all;
116
117         /* force connectors detection */
118         drm_helper_hpd_irq_event(dev);
119
120         return 0;
121
122 err_unbind_all:
123         component_unbind_all(dev->dev, dev);
124 err_cleanup_vblank:
125         drm_vblank_cleanup(dev);
126 err_mode_config_cleanup:
127         drm_mode_config_cleanup(dev);
128         drm_release_iommu_mapping(dev);
129 err_free_private:
130         kfree(private);
131
132         return ret;
133 }
134
135 static int exynos_drm_unload(struct drm_device *dev)
136 {
137         exynos_drm_device_subdrv_remove(dev);
138
139         exynos_drm_fbdev_fini(dev);
140         drm_vblank_cleanup(dev);
141         drm_kms_helper_poll_fini(dev);
142         drm_mode_config_cleanup(dev);
143
144         drm_release_iommu_mapping(dev);
145         kfree(dev->dev_private);
146
147         component_unbind_all(dev->dev, dev);
148         dev->dev_private = NULL;
149
150         return 0;
151 }
152
153 static const struct file_operations exynos_drm_gem_fops = {
154         .mmap = exynos_drm_gem_mmap_buffer,
155 };
156
157 static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
158 {
159         struct drm_connector *connector;
160
161         drm_modeset_lock_all(dev);
162         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
163                 int old_dpms = connector->dpms;
164
165                 if (connector->funcs->dpms)
166                         connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
167
168                 /* Set the old mode back to the connector for resume */
169                 connector->dpms = old_dpms;
170         }
171         drm_modeset_unlock_all(dev);
172
173         return 0;
174 }
175
176 static int exynos_drm_resume(struct drm_device *dev)
177 {
178         struct drm_connector *connector;
179
180         drm_modeset_lock_all(dev);
181         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
182                 if (connector->funcs->dpms)
183                         connector->funcs->dpms(connector, connector->dpms);
184         }
185         drm_modeset_unlock_all(dev);
186
187         drm_helper_resume_force_mode(dev);
188
189         return 0;
190 }
191
192 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
193 {
194         struct drm_exynos_file_private *file_priv;
195         struct file *anon_filp;
196         int ret;
197
198         file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
199         if (!file_priv)
200                 return -ENOMEM;
201
202         file->driver_priv = file_priv;
203
204         ret = exynos_drm_subdrv_open(dev, file);
205         if (ret)
206                 goto err_file_priv_free;
207
208         anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops,
209                                         NULL, 0);
210         if (IS_ERR(anon_filp)) {
211                 ret = PTR_ERR(anon_filp);
212                 goto err_subdrv_close;
213         }
214
215         anon_filp->f_mode = FMODE_READ | FMODE_WRITE;
216         file_priv->anon_filp = anon_filp;
217
218         return ret;
219
220 err_subdrv_close:
221         exynos_drm_subdrv_close(dev, file);
222
223 err_file_priv_free:
224         kfree(file_priv);
225         file->driver_priv = NULL;
226         return ret;
227 }
228
229 static void exynos_drm_preclose(struct drm_device *dev,
230                                         struct drm_file *file)
231 {
232         exynos_drm_subdrv_close(dev, file);
233 }
234
235 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
236 {
237         struct exynos_drm_private *private = dev->dev_private;
238         struct drm_exynos_file_private *file_priv;
239         struct drm_pending_vblank_event *v, *vt;
240         struct drm_pending_event *e, *et;
241         unsigned long flags;
242
243         if (!file->driver_priv)
244                 return;
245
246         /* Release all events not unhandled by page flip handler. */
247         spin_lock_irqsave(&dev->event_lock, flags);
248         list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
249                         base.link) {
250                 if (v->base.file_priv == file) {
251                         list_del(&v->base.link);
252                         drm_vblank_put(dev, v->pipe);
253                         v->base.destroy(&v->base);
254                 }
255         }
256
257         /* Release all events handled by page flip handler but not freed. */
258         list_for_each_entry_safe(e, et, &file->event_list, link) {
259                 list_del(&e->link);
260                 e->destroy(e);
261         }
262         spin_unlock_irqrestore(&dev->event_lock, flags);
263
264         file_priv = file->driver_priv;
265         if (file_priv->anon_filp)
266                 fput(file_priv->anon_filp);
267
268         kfree(file->driver_priv);
269         file->driver_priv = NULL;
270 }
271
272 static void exynos_drm_lastclose(struct drm_device *dev)
273 {
274         exynos_drm_fbdev_restore_mode(dev);
275 }
276
277 static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
278         .fault = exynos_drm_gem_fault,
279         .open = drm_gem_vm_open,
280         .close = drm_gem_vm_close,
281 };
282
283 static const struct drm_ioctl_desc exynos_ioctls[] = {
284         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
285                         DRM_UNLOCKED | DRM_AUTH),
286         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
287                         exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
288                         DRM_AUTH),
289         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
290                         exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
291         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET,
292                         exynos_drm_gem_get_ioctl, DRM_UNLOCKED),
293         DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
294                         vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH),
295         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER,
296                         exynos_g2d_get_ver_ioctl, DRM_UNLOCKED | DRM_AUTH),
297         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST,
298                         exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH),
299         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC,
300                         exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
301         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY,
302                         exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH),
303         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY,
304                         exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH),
305         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF,
306                         exynos_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH),
307         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL,
308                         exynos_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH),
309 };
310
311 static const struct file_operations exynos_drm_driver_fops = {
312         .owner          = THIS_MODULE,
313         .open           = drm_open,
314         .mmap           = exynos_drm_gem_mmap,
315         .poll           = drm_poll,
316         .read           = drm_read,
317         .unlocked_ioctl = drm_ioctl,
318 #ifdef CONFIG_COMPAT
319         .compat_ioctl = drm_compat_ioctl,
320 #endif
321         .release        = drm_release,
322 };
323
324 static struct drm_driver exynos_drm_driver = {
325         .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
326         .load                   = exynos_drm_load,
327         .unload                 = exynos_drm_unload,
328         .suspend                = exynos_drm_suspend,
329         .resume                 = exynos_drm_resume,
330         .open                   = exynos_drm_open,
331         .preclose               = exynos_drm_preclose,
332         .lastclose              = exynos_drm_lastclose,
333         .postclose              = exynos_drm_postclose,
334         .get_vblank_counter     = drm_vblank_count,
335         .enable_vblank          = exynos_drm_crtc_enable_vblank,
336         .disable_vblank         = exynos_drm_crtc_disable_vblank,
337         .gem_free_object        = exynos_drm_gem_free_object,
338         .gem_vm_ops             = &exynos_drm_gem_vm_ops,
339         .dumb_create            = exynos_drm_gem_dumb_create,
340         .dumb_map_offset        = exynos_drm_gem_dumb_map_offset,
341         .dumb_destroy           = drm_gem_dumb_destroy,
342         .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
343         .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
344         .gem_prime_export       = exynos_dmabuf_prime_export,
345         .gem_prime_import       = exynos_dmabuf_prime_import,
346         .ioctls                 = exynos_ioctls,
347         .num_ioctls             = ARRAY_SIZE(exynos_ioctls),
348         .fops                   = &exynos_drm_driver_fops,
349         .name   = DRIVER_NAME,
350         .desc   = DRIVER_DESC,
351         .date   = DRIVER_DATE,
352         .major  = DRIVER_MAJOR,
353         .minor  = DRIVER_MINOR,
354 };
355
356 #ifdef CONFIG_PM_SLEEP
357 static int exynos_drm_sys_suspend(struct device *dev)
358 {
359         struct drm_device *drm_dev = dev_get_drvdata(dev);
360         pm_message_t message;
361
362         if (pm_runtime_suspended(dev))
363                 return 0;
364
365         message.event = PM_EVENT_SUSPEND;
366         return exynos_drm_suspend(drm_dev, message);
367 }
368
369 static int exynos_drm_sys_resume(struct device *dev)
370 {
371         struct drm_device *drm_dev = dev_get_drvdata(dev);
372
373         if (pm_runtime_suspended(dev))
374                 return 0;
375
376         return exynos_drm_resume(drm_dev);
377 }
378 #endif
379
380 static const struct dev_pm_ops exynos_drm_pm_ops = {
381         SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
382 };
383
384 int exynos_drm_component_add(struct device *dev,
385                                 const struct component_ops *ops)
386 {
387         struct component_dev *cdev;
388         int ret;
389
390         cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
391         if (!cdev)
392                 return -ENOMEM;
393
394         ret = component_add(dev, ops);
395         if (ret) {
396                 kfree(cdev);
397                 return ret;
398         }
399
400         cdev->dev = dev;
401
402         mutex_lock(&drm_component_lock);
403         list_add_tail(&cdev->list, &drm_component_list);
404         mutex_unlock(&drm_component_lock);
405
406         return 0;
407 }
408
409 void exynos_drm_component_del(struct device *dev,
410                                 const struct component_ops *ops)
411 {
412         struct component_dev *cdev, *next;
413
414         mutex_lock(&drm_component_lock);
415
416         list_for_each_entry_safe(cdev, next, &drm_component_list, list) {
417                 if (dev == cdev->dev) {
418                         list_del(&cdev->list);
419                         kfree(cdev);
420                         break;
421                 }
422         }
423
424         mutex_unlock(&drm_component_lock);
425
426         component_del(dev, ops);
427 }
428
429 static int compare_of(struct device *dev, void *data)
430 {
431         return dev == (struct device *)data;
432 }
433
434 static int exynos_drm_add_components(struct device *dev, struct master *m)
435 {
436         unsigned int attached_cnt = 0;
437         struct component_dev *cdev;
438
439         mutex_lock(&drm_component_lock);
440
441         list_for_each_entry(cdev, &drm_component_list, list) {
442                 int ret;
443
444                 mutex_unlock(&drm_component_lock);
445
446                 ret = component_master_add_child(m, compare_of, cdev->dev);
447                 if (!ret)
448                         attached_cnt++;
449
450                 mutex_lock(&drm_component_lock);
451         }
452
453         mutex_unlock(&drm_component_lock);
454
455         if (!attached_cnt)
456                 return -ENXIO;
457
458         return 0;
459 }
460
461 static int exynos_drm_bind(struct device *dev)
462 {
463         return drm_platform_init(&exynos_drm_driver, to_platform_device(dev));
464 }
465
466 static void exynos_drm_unbind(struct device *dev)
467 {
468         drm_put_dev(dev_get_drvdata(dev));
469 }
470
471 static const struct component_master_ops exynos_drm_ops = {
472         .add_components = exynos_drm_add_components,
473         .bind           = exynos_drm_bind,
474         .unbind         = exynos_drm_unbind,
475 };
476
477 static int exynos_drm_platform_probe(struct platform_device *pdev)
478 {
479         int ret;
480
481         pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
482         exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
483
484 #ifdef CONFIG_DRM_EXYNOS_FIMD
485         ret = platform_driver_register(&fimd_driver);
486         if (ret < 0)
487                 return ret;
488 #endif
489
490 #ifdef CONFIG_DRM_EXYNOS_DP
491         ret = platform_driver_register(&dp_driver);
492         if (ret < 0)
493                 goto err_unregister_fimd_drv;
494 #endif
495
496 #ifdef CONFIG_DRM_EXYNOS_DSI
497         ret = platform_driver_register(&dsi_driver);
498         if (ret < 0)
499                 goto err_unregister_dp_drv;
500 #endif
501
502 #ifdef CONFIG_DRM_EXYNOS_HDMI
503         ret = platform_driver_register(&mixer_driver);
504         if (ret < 0)
505                 goto err_unregister_dsi_drv;
506         ret = platform_driver_register(&hdmi_driver);
507         if (ret < 0)
508                 goto err_unregister_mixer_drv;
509 #endif
510
511 #ifdef CONFIG_DRM_EXYNOS_G2D
512         ret = platform_driver_register(&g2d_driver);
513         if (ret < 0)
514                 goto err_unregister_hdmi_drv;
515 #endif
516
517 #ifdef CONFIG_DRM_EXYNOS_FIMC
518         ret = platform_driver_register(&fimc_driver);
519         if (ret < 0)
520                 goto err_unregister_g2d_drv;
521 #endif
522
523 #ifdef CONFIG_DRM_EXYNOS_ROTATOR
524         ret = platform_driver_register(&rotator_driver);
525         if (ret < 0)
526                 goto err_unregister_fimc_drv;
527 #endif
528
529 #ifdef CONFIG_DRM_EXYNOS_GSC
530         ret = platform_driver_register(&gsc_driver);
531         if (ret < 0)
532                 goto err_unregister_rotator_drv;
533 #endif
534
535 #ifdef CONFIG_DRM_EXYNOS_IPP
536         ret = platform_driver_register(&ipp_driver);
537         if (ret < 0)
538                 goto err_unregister_gsc_drv;
539
540         ret = exynos_platform_device_ipp_register();
541         if (ret < 0)
542                 goto err_unregister_ipp_drv;
543 #endif
544
545         ret = component_master_add(&pdev->dev, &exynos_drm_ops);
546         if (ret < 0)
547                 DRM_DEBUG_KMS("re-tried by last sub driver probed later.\n");
548
549         return 0;
550
551 #ifdef CONFIG_DRM_EXYNOS_IPP
552 err_unregister_ipp_drv:
553         platform_driver_unregister(&ipp_driver);
554 err_unregister_gsc_drv:
555 #endif
556
557 #ifdef CONFIG_DRM_EXYNOS_GSC
558         platform_driver_unregister(&gsc_driver);
559 err_unregister_rotator_drv:
560 #endif
561
562 #ifdef CONFIG_DRM_EXYNOS_ROTATOR
563         platform_driver_unregister(&rotator_driver);
564 err_unregister_fimc_drv:
565 #endif
566
567 #ifdef CONFIG_DRM_EXYNOS_FIMC
568         platform_driver_unregister(&fimc_driver);
569 err_unregister_g2d_drv:
570 #endif
571
572 #ifdef CONFIG_DRM_EXYNOS_G2D
573         platform_driver_unregister(&g2d_driver);
574 err_unregister_hdmi_drv:
575 #endif
576
577 #ifdef CONFIG_DRM_EXYNOS_HDMI
578         platform_driver_unregister(&hdmi_driver);
579 err_unregister_mixer_drv:
580         platform_driver_unregister(&mixer_driver);
581 err_unregister_dsi_drv:
582 #endif
583
584 #ifdef CONFIG_DRM_EXYNOS_DSI
585         platform_driver_unregister(&dsi_driver);
586 err_unregister_dp_drv:
587 #endif
588
589 #ifdef CONFIG_DRM_EXYNOS_DP
590         platform_driver_unregister(&dp_driver);
591 err_unregister_fimd_drv:
592 #endif
593
594 #ifdef CONFIG_DRM_EXYNOS_FIMD
595         platform_driver_unregister(&fimd_driver);
596 #endif
597         return ret;
598 }
599
600 static int exynos_drm_platform_remove(struct platform_device *pdev)
601 {
602 #ifdef CONFIG_DRM_EXYNOS_IPP
603         exynos_platform_device_ipp_unregister();
604         platform_driver_unregister(&ipp_driver);
605 #endif
606
607 #ifdef CONFIG_DRM_EXYNOS_GSC
608         platform_driver_unregister(&gsc_driver);
609 #endif
610
611 #ifdef CONFIG_DRM_EXYNOS_ROTATOR
612         platform_driver_unregister(&rotator_driver);
613 #endif
614
615 #ifdef CONFIG_DRM_EXYNOS_FIMC
616         platform_driver_unregister(&fimc_driver);
617 #endif
618
619 #ifdef CONFIG_DRM_EXYNOS_G2D
620         platform_driver_unregister(&g2d_driver);
621 #endif
622
623 #ifdef CONFIG_DRM_EXYNOS_HDMI
624         platform_driver_unregister(&mixer_driver);
625         platform_driver_unregister(&hdmi_driver);
626 #endif
627
628 #ifdef CONFIG_DRM_EXYNOS_FIMD
629         platform_driver_unregister(&fimd_driver);
630 #endif
631
632 #ifdef CONFIG_DRM_EXYNOS_DSI
633         platform_driver_unregister(&dsi_driver);
634 #endif
635
636 #ifdef CONFIG_DRM_EXYNOS_DP
637         platform_driver_unregister(&dp_driver);
638 #endif
639         component_master_del(&pdev->dev, &exynos_drm_ops);
640         return 0;
641 }
642
643 static struct platform_driver exynos_drm_platform_driver = {
644         .probe  = exynos_drm_platform_probe,
645         .remove = exynos_drm_platform_remove,
646         .driver = {
647                 .owner  = THIS_MODULE,
648                 .name   = "exynos-drm",
649                 .pm     = &exynos_drm_pm_ops,
650         },
651 };
652
653 static int exynos_drm_init(void)
654 {
655         int ret;
656
657         exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
658                                                                 NULL, 0);
659         if (IS_ERR(exynos_drm_pdev))
660                 return PTR_ERR(exynos_drm_pdev);
661
662 #ifdef CONFIG_DRM_EXYNOS_VIDI
663         ret = exynos_drm_probe_vidi();
664         if (ret < 0)
665                 goto err_unregister_pd;
666 #endif
667
668         ret = platform_driver_register(&exynos_drm_platform_driver);
669         if (ret)
670                 goto err_remove_vidi;
671
672         return 0;
673
674 err_unregister_pd:
675         platform_device_unregister(exynos_drm_pdev);
676
677 err_remove_vidi:
678 #ifdef CONFIG_DRM_EXYNOS_VIDI
679         exynos_drm_remove_vidi();
680 #endif
681
682         return ret;
683 }
684
685 static void exynos_drm_exit(void)
686 {
687 #ifdef CONFIG_DRM_EXYNOS_VIDI
688         exynos_drm_remove_vidi();
689 #endif
690         platform_device_unregister(exynos_drm_pdev);
691         platform_driver_unregister(&exynos_drm_platform_driver);
692 }
693
694 module_init(exynos_drm_init);
695 module_exit(exynos_drm_exit);
696
697 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
698 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
699 MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
700 MODULE_DESCRIPTION("Samsung SoC DRM Driver");
701 MODULE_LICENSE("GPL");