Version:  2.0.40 2.2.26 2.4.37 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9

Linux/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_atomic.h>
 17 #include <drm/drm_atomic_helper.h>
 18 #include <drm/drm_crtc_helper.h>
 19 
 20 #include <linux/component.h>
 21 
 22 #include <drm/exynos_drm.h>
 23 
 24 #include "exynos_drm_drv.h"
 25 #include "exynos_drm_crtc.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_g2d.h"
 32 #include "exynos_drm_ipp.h"
 33 #include "exynos_drm_iommu.h"
 34 
 35 #define DRIVER_NAME     "exynos"
 36 #define DRIVER_DESC     "Samsung SoC DRM"
 37 #define DRIVER_DATE     "20110530"
 38 #define DRIVER_MAJOR    1
 39 #define DRIVER_MINOR    0
 40 
 41 struct exynos_atomic_commit {
 42         struct work_struct      work;
 43         struct drm_device       *dev;
 44         struct drm_atomic_state *state;
 45         u32                     crtcs;
 46 };
 47 
 48 static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
 49 {
 50         struct drm_device *dev = commit->dev;
 51         struct exynos_drm_private *priv = dev->dev_private;
 52         struct drm_atomic_state *state = commit->state;
 53 
 54         drm_atomic_helper_commit_modeset_disables(dev, state);
 55 
 56         drm_atomic_helper_commit_modeset_enables(dev, state);
 57 
 58         /*
 59          * Exynos can't update planes with CRTCs and encoders disabled,
 60          * its updates routines, specially for FIMD, requires the clocks
 61          * to be enabled. So it is necessary to handle the modeset operations
 62          * *before* the commit_planes() step, this way it will always
 63          * have the relevant clocks enabled to perform the update.
 64          */
 65 
 66         drm_atomic_helper_commit_planes(dev, state, 0);
 67 
 68         drm_atomic_helper_wait_for_vblanks(dev, state);
 69 
 70         drm_atomic_helper_cleanup_planes(dev, state);
 71 
 72         drm_atomic_state_free(state);
 73 
 74         spin_lock(&priv->lock);
 75         priv->pending &= ~commit->crtcs;
 76         spin_unlock(&priv->lock);
 77 
 78         wake_up_all(&priv->wait);
 79 
 80         kfree(commit);
 81 }
 82 
 83 static void exynos_drm_atomic_work(struct work_struct *work)
 84 {
 85         struct exynos_atomic_commit *commit = container_of(work,
 86                                 struct exynos_atomic_commit, work);
 87 
 88         exynos_atomic_commit_complete(commit);
 89 }
 90 
 91 static struct device *exynos_drm_get_dma_device(void);
 92 
 93 static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 94 {
 95         struct exynos_drm_private *private;
 96         struct drm_encoder *encoder;
 97         unsigned int clone_mask;
 98         int cnt, ret;
 99 
100         private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
101         if (!private)
102                 return -ENOMEM;
103 
104         init_waitqueue_head(&private->wait);
105         spin_lock_init(&private->lock);
106 
107         dev_set_drvdata(dev->dev, dev);
108         dev->dev_private = (void *)private;
109 
110         /* the first real CRTC device is used for all dma mapping operations */
111         private->dma_dev = exynos_drm_get_dma_device();
112         if (!private->dma_dev) {
113                 DRM_ERROR("no device found for DMA mapping operations.\n");
114                 ret = -ENODEV;
115                 goto err_free_private;
116         }
117         DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
118                  dev_name(private->dma_dev));
119 
120         /* create common IOMMU mapping for all devices attached to Exynos DRM */
121         ret = drm_create_iommu_mapping(dev);
122         if (ret < 0) {
123                 DRM_ERROR("failed to create iommu mapping.\n");
124                 goto err_free_private;
125         }
126 
127         drm_mode_config_init(dev);
128 
129         exynos_drm_mode_config_init(dev);
130 
131         /* setup possible_clones. */
132         cnt = 0;
133         clone_mask = 0;
134         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
135                 clone_mask |= (1 << (cnt++));
136 
137         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
138                 encoder->possible_clones = clone_mask;
139 
140         platform_set_drvdata(dev->platformdev, dev);
141 
142         /* Try to bind all sub drivers. */
143         ret = component_bind_all(dev->dev, dev);
144         if (ret)
145                 goto err_mode_config_cleanup;
146 
147         ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
148         if (ret)
149                 goto err_unbind_all;
150 
151         /* Probe non kms sub drivers and virtual display driver. */
152         ret = exynos_drm_device_subdrv_probe(dev);
153         if (ret)
154                 goto err_cleanup_vblank;
155 
156         drm_mode_config_reset(dev);
157 
158         /*
159          * enable drm irq mode.
160          * - with irq_enabled = true, we can use the vblank feature.
161          *
162          * P.S. note that we wouldn't use drm irq handler but
163          *      just specific driver own one instead because
164          *      drm framework supports only one irq handler.
165          */
166         dev->irq_enabled = true;
167 
168         /* init kms poll for handling hpd */
169         drm_kms_helper_poll_init(dev);
170 
171         /* force connectors detection */
172         drm_helper_hpd_irq_event(dev);
173 
174         return 0;
175 
176 err_cleanup_vblank:
177         drm_vblank_cleanup(dev);
178 err_unbind_all:
179         component_unbind_all(dev->dev, dev);
180 err_mode_config_cleanup:
181         drm_mode_config_cleanup(dev);
182         drm_release_iommu_mapping(dev);
183 err_free_private:
184         kfree(private);
185 
186         return ret;
187 }
188 
189 static int exynos_drm_unload(struct drm_device *dev)
190 {
191         exynos_drm_device_subdrv_remove(dev);
192 
193         exynos_drm_fbdev_fini(dev);
194         drm_kms_helper_poll_fini(dev);
195 
196         drm_vblank_cleanup(dev);
197         component_unbind_all(dev->dev, dev);
198         drm_mode_config_cleanup(dev);
199         drm_release_iommu_mapping(dev);
200 
201         kfree(dev->dev_private);
202         dev->dev_private = NULL;
203 
204         return 0;
205 }
206 
207 static int commit_is_pending(struct exynos_drm_private *priv, u32 crtcs)
208 {
209         bool pending;
210 
211         spin_lock(&priv->lock);
212         pending = priv->pending & crtcs;
213         spin_unlock(&priv->lock);
214 
215         return pending;
216 }
217 
218 int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
219                          bool nonblock)
220 {
221         struct exynos_drm_private *priv = dev->dev_private;
222         struct exynos_atomic_commit *commit;
223         struct drm_crtc *crtc;
224         struct drm_crtc_state *crtc_state;
225         int i, ret;
226 
227         commit = kzalloc(sizeof(*commit), GFP_KERNEL);
228         if (!commit)
229                 return -ENOMEM;
230 
231         ret = drm_atomic_helper_prepare_planes(dev, state);
232         if (ret) {
233                 kfree(commit);
234                 return ret;
235         }
236 
237         /* This is the point of no return */
238 
239         INIT_WORK(&commit->work, exynos_drm_atomic_work);
240         commit->dev = dev;
241         commit->state = state;
242 
243         /* Wait until all affected CRTCs have completed previous commits and
244          * mark them as pending.
245          */
246         for_each_crtc_in_state(state, crtc, crtc_state, i)
247                 commit->crtcs |= drm_crtc_mask(crtc);
248 
249         wait_event(priv->wait, !commit_is_pending(priv, commit->crtcs));
250 
251         spin_lock(&priv->lock);
252         priv->pending |= commit->crtcs;
253         spin_unlock(&priv->lock);
254 
255         drm_atomic_helper_swap_state(state, true);
256 
257         if (nonblock)
258                 schedule_work(&commit->work);
259         else
260                 exynos_atomic_commit_complete(commit);
261 
262         return 0;
263 }
264 
265 int exynos_atomic_check(struct drm_device *dev,
266                         struct drm_atomic_state *state)
267 {
268         int ret;
269 
270         ret = drm_atomic_helper_check_modeset(dev, state);
271         if (ret)
272                 return ret;
273 
274         ret = drm_atomic_normalize_zpos(dev, state);
275         if (ret)
276                 return ret;
277 
278         ret = drm_atomic_helper_check_planes(dev, state);
279         if (ret)
280                 return ret;
281 
282         return ret;
283 }
284 
285 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
286 {
287         struct drm_exynos_file_private *file_priv;
288         int ret;
289 
290         file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
291         if (!file_priv)
292                 return -ENOMEM;
293 
294         file->driver_priv = file_priv;
295 
296         ret = exynos_drm_subdrv_open(dev, file);
297         if (ret)
298                 goto err_file_priv_free;
299 
300         return ret;
301 
302 err_file_priv_free:
303         kfree(file_priv);
304         file->driver_priv = NULL;
305         return ret;
306 }
307 
308 static void exynos_drm_preclose(struct drm_device *dev,
309                                         struct drm_file *file)
310 {
311         struct drm_crtc *crtc;
312 
313         exynos_drm_subdrv_close(dev, file);
314 
315         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
316                 exynos_drm_crtc_cancel_page_flip(crtc, file);
317 }
318 
319 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
320 {
321         kfree(file->driver_priv);
322         file->driver_priv = NULL;
323 }
324 
325 static void exynos_drm_lastclose(struct drm_device *dev)
326 {
327         exynos_drm_fbdev_restore_mode(dev);
328 }
329 
330 static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
331         .fault = exynos_drm_gem_fault,
332         .open = drm_gem_vm_open,
333         .close = drm_gem_vm_close,
334 };
335 
336 static const struct drm_ioctl_desc exynos_ioctls[] = {
337         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
338                         DRM_AUTH | DRM_RENDER_ALLOW),
339         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP, exynos_drm_gem_map_ioctl,
340                         DRM_AUTH | DRM_RENDER_ALLOW),
341         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl,
342                         DRM_RENDER_ALLOW),
343         DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl,
344                         DRM_AUTH),
345         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, exynos_g2d_get_ver_ioctl,
346                         DRM_AUTH | DRM_RENDER_ALLOW),
347         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, exynos_g2d_set_cmdlist_ioctl,
348                         DRM_AUTH | DRM_RENDER_ALLOW),
349         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl,
350                         DRM_AUTH | DRM_RENDER_ALLOW),
351         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, exynos_drm_ipp_get_property,
352                         DRM_AUTH | DRM_RENDER_ALLOW),
353         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, exynos_drm_ipp_set_property,
354                         DRM_AUTH | DRM_RENDER_ALLOW),
355         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF, exynos_drm_ipp_queue_buf,
356                         DRM_AUTH | DRM_RENDER_ALLOW),
357         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL, exynos_drm_ipp_cmd_ctrl,
358                         DRM_AUTH | DRM_RENDER_ALLOW),
359 };
360 
361 static const struct file_operations exynos_drm_driver_fops = {
362         .owner          = THIS_MODULE,
363         .open           = drm_open,
364         .mmap           = exynos_drm_gem_mmap,
365         .poll           = drm_poll,
366         .read           = drm_read,
367         .unlocked_ioctl = drm_ioctl,
368 #ifdef CONFIG_COMPAT
369         .compat_ioctl = drm_compat_ioctl,
370 #endif
371         .release        = drm_release,
372 };
373 
374 static struct drm_driver exynos_drm_driver = {
375         .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
376                                   | DRIVER_ATOMIC | DRIVER_RENDER,
377         .load                   = exynos_drm_load,
378         .unload                 = exynos_drm_unload,
379         .open                   = exynos_drm_open,
380         .preclose               = exynos_drm_preclose,
381         .lastclose              = exynos_drm_lastclose,
382         .postclose              = exynos_drm_postclose,
383         .get_vblank_counter     = drm_vblank_no_hw_counter,
384         .enable_vblank          = exynos_drm_crtc_enable_vblank,
385         .disable_vblank         = exynos_drm_crtc_disable_vblank,
386         .gem_free_object_unlocked = exynos_drm_gem_free_object,
387         .gem_vm_ops             = &exynos_drm_gem_vm_ops,
388         .dumb_create            = exynos_drm_gem_dumb_create,
389         .dumb_map_offset        = exynos_drm_gem_dumb_map_offset,
390         .dumb_destroy           = drm_gem_dumb_destroy,
391         .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
392         .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
393         .gem_prime_export       = drm_gem_prime_export,
394         .gem_prime_import       = drm_gem_prime_import,
395         .gem_prime_get_sg_table = exynos_drm_gem_prime_get_sg_table,
396         .gem_prime_import_sg_table      = exynos_drm_gem_prime_import_sg_table,
397         .gem_prime_vmap         = exynos_drm_gem_prime_vmap,
398         .gem_prime_vunmap       = exynos_drm_gem_prime_vunmap,
399         .gem_prime_mmap         = exynos_drm_gem_prime_mmap,
400         .ioctls                 = exynos_ioctls,
401         .num_ioctls             = ARRAY_SIZE(exynos_ioctls),
402         .fops                   = &exynos_drm_driver_fops,
403         .name   = DRIVER_NAME,
404         .desc   = DRIVER_DESC,
405         .date   = DRIVER_DATE,
406         .major  = DRIVER_MAJOR,
407         .minor  = DRIVER_MINOR,
408 };
409 
410 #ifdef CONFIG_PM_SLEEP
411 static int exynos_drm_suspend(struct device *dev)
412 {
413         struct drm_device *drm_dev = dev_get_drvdata(dev);
414         struct drm_connector *connector;
415 
416         if (pm_runtime_suspended(dev) || !drm_dev)
417                 return 0;
418 
419         drm_modeset_lock_all(drm_dev);
420         drm_for_each_connector(connector, drm_dev) {
421                 int old_dpms = connector->dpms;
422 
423                 if (connector->funcs->dpms)
424                         connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
425 
426                 /* Set the old mode back to the connector for resume */
427                 connector->dpms = old_dpms;
428         }
429         drm_modeset_unlock_all(drm_dev);
430 
431         return 0;
432 }
433 
434 static int exynos_drm_resume(struct device *dev)
435 {
436         struct drm_device *drm_dev = dev_get_drvdata(dev);
437         struct drm_connector *connector;
438 
439         if (pm_runtime_suspended(dev) || !drm_dev)
440                 return 0;
441 
442         drm_modeset_lock_all(drm_dev);
443         drm_for_each_connector(connector, drm_dev) {
444                 if (connector->funcs->dpms) {
445                         int dpms = connector->dpms;
446 
447                         connector->dpms = DRM_MODE_DPMS_OFF;
448                         connector->funcs->dpms(connector, dpms);
449                 }
450         }
451         drm_modeset_unlock_all(drm_dev);
452 
453         return 0;
454 }
455 #endif
456 
457 static const struct dev_pm_ops exynos_drm_pm_ops = {
458         SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_suspend, exynos_drm_resume)
459 };
460 
461 /* forward declaration */
462 static struct platform_driver exynos_drm_platform_driver;
463 
464 struct exynos_drm_driver_info {
465         struct platform_driver *driver;
466         unsigned int flags;
467 };
468 
469 #define DRM_COMPONENT_DRIVER    BIT(0)  /* supports component framework */
470 #define DRM_VIRTUAL_DEVICE      BIT(1)  /* create virtual platform device */
471 #define DRM_DMA_DEVICE          BIT(2)  /* can be used for dma allocations */
472 
473 #define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)
474 
475 /*
476  * Connector drivers should not be placed before associated crtc drivers,
477  * because connector requires pipe number of its crtc during initialization.
478  */
479 static struct exynos_drm_driver_info exynos_drm_drivers[] = {
480         {
481                 DRV_PTR(fimd_driver, CONFIG_DRM_EXYNOS_FIMD),
482                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
483         }, {
484                 DRV_PTR(exynos5433_decon_driver, CONFIG_DRM_EXYNOS5433_DECON),
485                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
486         }, {
487                 DRV_PTR(decon_driver, CONFIG_DRM_EXYNOS7_DECON),
488                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
489         }, {
490                 DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
491                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
492         }, {
493                 DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
494                 DRM_COMPONENT_DRIVER
495         }, {
496                 DRV_PTR(dp_driver, CONFIG_DRM_EXYNOS_DP),
497                 DRM_COMPONENT_DRIVER
498         }, {
499                 DRV_PTR(dsi_driver, CONFIG_DRM_EXYNOS_DSI),
500                 DRM_COMPONENT_DRIVER
501         }, {
502                 DRV_PTR(hdmi_driver, CONFIG_DRM_EXYNOS_HDMI),
503                 DRM_COMPONENT_DRIVER
504         }, {
505                 DRV_PTR(vidi_driver, CONFIG_DRM_EXYNOS_VIDI),
506                 DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE
507         }, {
508                 DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
509         }, {
510                 DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
511         }, {
512                 DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
513         }, {
514                 DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
515         }, {
516                 DRV_PTR(ipp_driver, CONFIG_DRM_EXYNOS_IPP),
517                 DRM_VIRTUAL_DEVICE
518         }, {
519                 &exynos_drm_platform_driver,
520                 DRM_VIRTUAL_DEVICE
521         }
522 };
523 
524 static int compare_dev(struct device *dev, void *data)
525 {
526         return dev == (struct device *)data;
527 }
528 
529 static struct component_match *exynos_drm_match_add(struct device *dev)
530 {
531         struct component_match *match = NULL;
532         int i;
533 
534         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
535                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
536                 struct device *p = NULL, *d;
537 
538                 if (!info->driver || !(info->flags & DRM_COMPONENT_DRIVER))
539                         continue;
540 
541                 while ((d = bus_find_device(&platform_bus_type, p,
542                                             &info->driver->driver,
543                                             (void *)platform_bus_type.match))) {
544                         put_device(p);
545                         component_match_add(dev, &match, compare_dev, d);
546                         p = d;
547                 }
548                 put_device(p);
549         }
550 
551         return match ?: ERR_PTR(-ENODEV);
552 }
553 
554 static int exynos_drm_bind(struct device *dev)
555 {
556         return drm_platform_init(&exynos_drm_driver, to_platform_device(dev));
557 }
558 
559 static void exynos_drm_unbind(struct device *dev)
560 {
561         drm_put_dev(dev_get_drvdata(dev));
562 }
563 
564 static const struct component_master_ops exynos_drm_ops = {
565         .bind           = exynos_drm_bind,
566         .unbind         = exynos_drm_unbind,
567 };
568 
569 static int exynos_drm_platform_probe(struct platform_device *pdev)
570 {
571         struct component_match *match;
572 
573         pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
574         exynos_drm_driver.num_ioctls = ARRAY_SIZE(exynos_ioctls);
575 
576         match = exynos_drm_match_add(&pdev->dev);
577         if (IS_ERR(match))
578                 return PTR_ERR(match);
579 
580         return component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
581                                                match);
582 }
583 
584 static int exynos_drm_platform_remove(struct platform_device *pdev)
585 {
586         component_master_del(&pdev->dev, &exynos_drm_ops);
587         return 0;
588 }
589 
590 static struct platform_driver exynos_drm_platform_driver = {
591         .probe  = exynos_drm_platform_probe,
592         .remove = exynos_drm_platform_remove,
593         .driver = {
594                 .name   = "exynos-drm",
595                 .pm     = &exynos_drm_pm_ops,
596         },
597 };
598 
599 static struct device *exynos_drm_get_dma_device(void)
600 {
601         int i;
602 
603         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
604                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
605                 struct device *dev;
606 
607                 if (!info->driver || !(info->flags & DRM_DMA_DEVICE))
608                         continue;
609 
610                 while ((dev = bus_find_device(&platform_bus_type, NULL,
611                                             &info->driver->driver,
612                                             (void *)platform_bus_type.match))) {
613                         put_device(dev);
614                         return dev;
615                 }
616         }
617         return NULL;
618 }
619 
620 static void exynos_drm_unregister_devices(void)
621 {
622         int i;
623 
624         for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
625                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
626                 struct device *dev;
627 
628                 if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
629                         continue;
630 
631                 while ((dev = bus_find_device(&platform_bus_type, NULL,
632                                             &info->driver->driver,
633                                             (void *)platform_bus_type.match))) {
634                         put_device(dev);
635                         platform_device_unregister(to_platform_device(dev));
636                 }
637         }
638 }
639 
640 static int exynos_drm_register_devices(void)
641 {
642         struct platform_device *pdev;
643         int i;
644 
645         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
646                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
647 
648                 if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
649                         continue;
650 
651                 pdev = platform_device_register_simple(
652                                         info->driver->driver.name, -1, NULL, 0);
653                 if (IS_ERR(pdev))
654                         goto fail;
655         }
656 
657         return 0;
658 fail:
659         exynos_drm_unregister_devices();
660         return PTR_ERR(pdev);
661 }
662 
663 static void exynos_drm_unregister_drivers(void)
664 {
665         int i;
666 
667         for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
668                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
669 
670                 if (!info->driver)
671                         continue;
672 
673                 platform_driver_unregister(info->driver);
674         }
675 }
676 
677 static int exynos_drm_register_drivers(void)
678 {
679         int i, ret;
680 
681         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
682                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
683 
684                 if (!info->driver)
685                         continue;
686 
687                 ret = platform_driver_register(info->driver);
688                 if (ret)
689                         goto fail;
690         }
691         return 0;
692 fail:
693         exynos_drm_unregister_drivers();
694         return ret;
695 }
696 
697 static int exynos_drm_init(void)
698 {
699         int ret;
700 
701         ret = exynos_drm_register_devices();
702         if (ret)
703                 return ret;
704 
705         ret = exynos_drm_register_drivers();
706         if (ret)
707                 goto err_unregister_pdevs;
708 
709         return 0;
710 
711 err_unregister_pdevs:
712         exynos_drm_unregister_devices();
713 
714         return ret;
715 }
716 
717 static void exynos_drm_exit(void)
718 {
719         exynos_drm_unregister_drivers();
720         exynos_drm_unregister_devices();
721 }
722 
723 module_init(exynos_drm_init);
724 module_exit(exynos_drm_exit);
725 
726 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
727 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
728 MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
729 MODULE_DESCRIPTION("Samsung SoC DRM Driver");
730 MODULE_LICENSE("GPL");
731 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us