Version:  2.0.40 2.2.26 2.4.37 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 4.10

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_put(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         drm_atomic_state_get(state);
258         if (nonblock)
259                 schedule_work(&commit->work);
260         else
261                 exynos_atomic_commit_complete(commit);
262 
263         return 0;
264 }
265 
266 int exynos_atomic_check(struct drm_device *dev,
267                         struct drm_atomic_state *state)
268 {
269         int ret;
270 
271         ret = drm_atomic_helper_check_modeset(dev, state);
272         if (ret)
273                 return ret;
274 
275         ret = drm_atomic_normalize_zpos(dev, state);
276         if (ret)
277                 return ret;
278 
279         ret = drm_atomic_helper_check_planes(dev, state);
280         if (ret)
281                 return ret;
282 
283         return ret;
284 }
285 
286 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
287 {
288         struct drm_exynos_file_private *file_priv;
289         int ret;
290 
291         file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
292         if (!file_priv)
293                 return -ENOMEM;
294 
295         file->driver_priv = file_priv;
296 
297         ret = exynos_drm_subdrv_open(dev, file);
298         if (ret)
299                 goto err_file_priv_free;
300 
301         return ret;
302 
303 err_file_priv_free:
304         kfree(file_priv);
305         file->driver_priv = NULL;
306         return ret;
307 }
308 
309 static void exynos_drm_preclose(struct drm_device *dev,
310                                         struct drm_file *file)
311 {
312         struct drm_crtc *crtc;
313 
314         exynos_drm_subdrv_close(dev, file);
315 
316         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
317                 exynos_drm_crtc_cancel_page_flip(crtc, file);
318 }
319 
320 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
321 {
322         kfree(file->driver_priv);
323         file->driver_priv = NULL;
324 }
325 
326 static void exynos_drm_lastclose(struct drm_device *dev)
327 {
328         exynos_drm_fbdev_restore_mode(dev);
329 }
330 
331 static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
332         .fault = exynos_drm_gem_fault,
333         .open = drm_gem_vm_open,
334         .close = drm_gem_vm_close,
335 };
336 
337 static const struct drm_ioctl_desc exynos_ioctls[] = {
338         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
339                         DRM_AUTH | DRM_RENDER_ALLOW),
340         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP, exynos_drm_gem_map_ioctl,
341                         DRM_AUTH | DRM_RENDER_ALLOW),
342         DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl,
343                         DRM_RENDER_ALLOW),
344         DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl,
345                         DRM_AUTH),
346         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, exynos_g2d_get_ver_ioctl,
347                         DRM_AUTH | DRM_RENDER_ALLOW),
348         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, exynos_g2d_set_cmdlist_ioctl,
349                         DRM_AUTH | DRM_RENDER_ALLOW),
350         DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl,
351                         DRM_AUTH | DRM_RENDER_ALLOW),
352         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, exynos_drm_ipp_get_property,
353                         DRM_AUTH | DRM_RENDER_ALLOW),
354         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, exynos_drm_ipp_set_property,
355                         DRM_AUTH | DRM_RENDER_ALLOW),
356         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF, exynos_drm_ipp_queue_buf,
357                         DRM_AUTH | DRM_RENDER_ALLOW),
358         DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL, exynos_drm_ipp_cmd_ctrl,
359                         DRM_AUTH | DRM_RENDER_ALLOW),
360 };
361 
362 static const struct file_operations exynos_drm_driver_fops = {
363         .owner          = THIS_MODULE,
364         .open           = drm_open,
365         .mmap           = exynos_drm_gem_mmap,
366         .poll           = drm_poll,
367         .read           = drm_read,
368         .unlocked_ioctl = drm_ioctl,
369         .compat_ioctl = drm_compat_ioctl,
370         .release        = drm_release,
371 };
372 
373 static struct drm_driver exynos_drm_driver = {
374         .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
375                                   | DRIVER_ATOMIC | DRIVER_RENDER,
376         .load                   = exynos_drm_load,
377         .unload                 = exynos_drm_unload,
378         .open                   = exynos_drm_open,
379         .preclose               = exynos_drm_preclose,
380         .lastclose              = exynos_drm_lastclose,
381         .postclose              = exynos_drm_postclose,
382         .get_vblank_counter     = drm_vblank_no_hw_counter,
383         .enable_vblank          = exynos_drm_crtc_enable_vblank,
384         .disable_vblank         = exynos_drm_crtc_disable_vblank,
385         .gem_free_object_unlocked = exynos_drm_gem_free_object,
386         .gem_vm_ops             = &exynos_drm_gem_vm_ops,
387         .dumb_create            = exynos_drm_gem_dumb_create,
388         .dumb_map_offset        = exynos_drm_gem_dumb_map_offset,
389         .dumb_destroy           = drm_gem_dumb_destroy,
390         .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
391         .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
392         .gem_prime_export       = drm_gem_prime_export,
393         .gem_prime_import       = drm_gem_prime_import,
394         .gem_prime_get_sg_table = exynos_drm_gem_prime_get_sg_table,
395         .gem_prime_import_sg_table      = exynos_drm_gem_prime_import_sg_table,
396         .gem_prime_vmap         = exynos_drm_gem_prime_vmap,
397         .gem_prime_vunmap       = exynos_drm_gem_prime_vunmap,
398         .gem_prime_mmap         = exynos_drm_gem_prime_mmap,
399         .ioctls                 = exynos_ioctls,
400         .num_ioctls             = ARRAY_SIZE(exynos_ioctls),
401         .fops                   = &exynos_drm_driver_fops,
402         .name   = DRIVER_NAME,
403         .desc   = DRIVER_DESC,
404         .date   = DRIVER_DATE,
405         .major  = DRIVER_MAJOR,
406         .minor  = DRIVER_MINOR,
407 };
408 
409 #ifdef CONFIG_PM_SLEEP
410 static int exynos_drm_suspend(struct device *dev)
411 {
412         struct drm_device *drm_dev = dev_get_drvdata(dev);
413         struct drm_connector *connector;
414 
415         if (pm_runtime_suspended(dev) || !drm_dev)
416                 return 0;
417 
418         drm_modeset_lock_all(drm_dev);
419         drm_for_each_connector(connector, drm_dev) {
420                 int old_dpms = connector->dpms;
421 
422                 if (connector->funcs->dpms)
423                         connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
424 
425                 /* Set the old mode back to the connector for resume */
426                 connector->dpms = old_dpms;
427         }
428         drm_modeset_unlock_all(drm_dev);
429 
430         return 0;
431 }
432 
433 static int exynos_drm_resume(struct device *dev)
434 {
435         struct drm_device *drm_dev = dev_get_drvdata(dev);
436         struct drm_connector *connector;
437 
438         if (pm_runtime_suspended(dev) || !drm_dev)
439                 return 0;
440 
441         drm_modeset_lock_all(drm_dev);
442         drm_for_each_connector(connector, drm_dev) {
443                 if (connector->funcs->dpms) {
444                         int dpms = connector->dpms;
445 
446                         connector->dpms = DRM_MODE_DPMS_OFF;
447                         connector->funcs->dpms(connector, dpms);
448                 }
449         }
450         drm_modeset_unlock_all(drm_dev);
451 
452         return 0;
453 }
454 #endif
455 
456 static const struct dev_pm_ops exynos_drm_pm_ops = {
457         SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_suspend, exynos_drm_resume)
458 };
459 
460 /* forward declaration */
461 static struct platform_driver exynos_drm_platform_driver;
462 
463 struct exynos_drm_driver_info {
464         struct platform_driver *driver;
465         unsigned int flags;
466 };
467 
468 #define DRM_COMPONENT_DRIVER    BIT(0)  /* supports component framework */
469 #define DRM_VIRTUAL_DEVICE      BIT(1)  /* create virtual platform device */
470 #define DRM_DMA_DEVICE          BIT(2)  /* can be used for dma allocations */
471 
472 #define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)
473 
474 /*
475  * Connector drivers should not be placed before associated crtc drivers,
476  * because connector requires pipe number of its crtc during initialization.
477  */
478 static struct exynos_drm_driver_info exynos_drm_drivers[] = {
479         {
480                 DRV_PTR(fimd_driver, CONFIG_DRM_EXYNOS_FIMD),
481                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
482         }, {
483                 DRV_PTR(exynos5433_decon_driver, CONFIG_DRM_EXYNOS5433_DECON),
484                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
485         }, {
486                 DRV_PTR(decon_driver, CONFIG_DRM_EXYNOS7_DECON),
487                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
488         }, {
489                 DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
490                 DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
491         }, {
492                 DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
493                 DRM_COMPONENT_DRIVER
494         }, {
495                 DRV_PTR(dp_driver, CONFIG_DRM_EXYNOS_DP),
496                 DRM_COMPONENT_DRIVER
497         }, {
498                 DRV_PTR(dsi_driver, CONFIG_DRM_EXYNOS_DSI),
499                 DRM_COMPONENT_DRIVER
500         }, {
501                 DRV_PTR(hdmi_driver, CONFIG_DRM_EXYNOS_HDMI),
502                 DRM_COMPONENT_DRIVER
503         }, {
504                 DRV_PTR(vidi_driver, CONFIG_DRM_EXYNOS_VIDI),
505                 DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE
506         }, {
507                 DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
508         }, {
509                 DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
510         }, {
511                 DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
512         }, {
513                 DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
514         }, {
515                 DRV_PTR(ipp_driver, CONFIG_DRM_EXYNOS_IPP),
516                 DRM_VIRTUAL_DEVICE
517         }, {
518                 &exynos_drm_platform_driver,
519                 DRM_VIRTUAL_DEVICE
520         }
521 };
522 
523 static int compare_dev(struct device *dev, void *data)
524 {
525         return dev == (struct device *)data;
526 }
527 
528 static struct component_match *exynos_drm_match_add(struct device *dev)
529 {
530         struct component_match *match = NULL;
531         int i;
532 
533         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
534                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
535                 struct device *p = NULL, *d;
536 
537                 if (!info->driver || !(info->flags & DRM_COMPONENT_DRIVER))
538                         continue;
539 
540                 while ((d = bus_find_device(&platform_bus_type, p,
541                                             &info->driver->driver,
542                                             (void *)platform_bus_type.match))) {
543                         put_device(p);
544                         component_match_add(dev, &match, compare_dev, d);
545                         p = d;
546                 }
547                 put_device(p);
548         }
549 
550         return match ?: ERR_PTR(-ENODEV);
551 }
552 
553 static int exynos_drm_bind(struct device *dev)
554 {
555         return drm_platform_init(&exynos_drm_driver, to_platform_device(dev));
556 }
557 
558 static void exynos_drm_unbind(struct device *dev)
559 {
560         drm_put_dev(dev_get_drvdata(dev));
561 }
562 
563 static const struct component_master_ops exynos_drm_ops = {
564         .bind           = exynos_drm_bind,
565         .unbind         = exynos_drm_unbind,
566 };
567 
568 static int exynos_drm_platform_probe(struct platform_device *pdev)
569 {
570         struct component_match *match;
571 
572         pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
573         exynos_drm_driver.num_ioctls = ARRAY_SIZE(exynos_ioctls);
574 
575         match = exynos_drm_match_add(&pdev->dev);
576         if (IS_ERR(match))
577                 return PTR_ERR(match);
578 
579         return component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
580                                                match);
581 }
582 
583 static int exynos_drm_platform_remove(struct platform_device *pdev)
584 {
585         component_master_del(&pdev->dev, &exynos_drm_ops);
586         return 0;
587 }
588 
589 static struct platform_driver exynos_drm_platform_driver = {
590         .probe  = exynos_drm_platform_probe,
591         .remove = exynos_drm_platform_remove,
592         .driver = {
593                 .name   = "exynos-drm",
594                 .pm     = &exynos_drm_pm_ops,
595         },
596 };
597 
598 static struct device *exynos_drm_get_dma_device(void)
599 {
600         int i;
601 
602         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
603                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
604                 struct device *dev;
605 
606                 if (!info->driver || !(info->flags & DRM_DMA_DEVICE))
607                         continue;
608 
609                 while ((dev = bus_find_device(&platform_bus_type, NULL,
610                                             &info->driver->driver,
611                                             (void *)platform_bus_type.match))) {
612                         put_device(dev);
613                         return dev;
614                 }
615         }
616         return NULL;
617 }
618 
619 static void exynos_drm_unregister_devices(void)
620 {
621         int i;
622 
623         for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
624                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
625                 struct device *dev;
626 
627                 if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
628                         continue;
629 
630                 while ((dev = bus_find_device(&platform_bus_type, NULL,
631                                             &info->driver->driver,
632                                             (void *)platform_bus_type.match))) {
633                         put_device(dev);
634                         platform_device_unregister(to_platform_device(dev));
635                 }
636         }
637 }
638 
639 static int exynos_drm_register_devices(void)
640 {
641         struct platform_device *pdev;
642         int i;
643 
644         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
645                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
646 
647                 if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
648                         continue;
649 
650                 pdev = platform_device_register_simple(
651                                         info->driver->driver.name, -1, NULL, 0);
652                 if (IS_ERR(pdev))
653                         goto fail;
654         }
655 
656         return 0;
657 fail:
658         exynos_drm_unregister_devices();
659         return PTR_ERR(pdev);
660 }
661 
662 static void exynos_drm_unregister_drivers(void)
663 {
664         int i;
665 
666         for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
667                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
668 
669                 if (!info->driver)
670                         continue;
671 
672                 platform_driver_unregister(info->driver);
673         }
674 }
675 
676 static int exynos_drm_register_drivers(void)
677 {
678         int i, ret;
679 
680         for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
681                 struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
682 
683                 if (!info->driver)
684                         continue;
685 
686                 ret = platform_driver_register(info->driver);
687                 if (ret)
688                         goto fail;
689         }
690         return 0;
691 fail:
692         exynos_drm_unregister_drivers();
693         return ret;
694 }
695 
696 static int exynos_drm_init(void)
697 {
698         int ret;
699 
700         ret = exynos_drm_register_devices();
701         if (ret)
702                 return ret;
703 
704         ret = exynos_drm_register_drivers();
705         if (ret)
706                 goto err_unregister_pdevs;
707 
708         return 0;
709 
710 err_unregister_pdevs:
711         exynos_drm_unregister_devices();
712 
713         return ret;
714 }
715 
716 static void exynos_drm_exit(void)
717 {
718         exynos_drm_unregister_drivers();
719         exynos_drm_unregister_devices();
720 }
721 
722 module_init(exynos_drm_init);
723 module_exit(exynos_drm_exit);
724 
725 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
726 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
727 MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
728 MODULE_DESCRIPTION("Samsung SoC DRM Driver");
729 MODULE_LICENSE("GPL");
730 

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