Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.16-rc3 795 lines 19 kB view raw
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 44static struct platform_device *exynos_drm_pdev; 45 46static DEFINE_MUTEX(drm_component_lock); 47static LIST_HEAD(drm_component_list); 48 49struct component_dev { 50 struct list_head list; 51 struct device *crtc_dev; 52 struct device *conn_dev; 53 enum exynos_drm_output_type out_type; 54 unsigned int dev_type_flag; 55}; 56 57static int exynos_drm_load(struct drm_device *dev, unsigned long flags) 58{ 59 struct exynos_drm_private *private; 60 int ret; 61 int nr; 62 63 private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); 64 if (!private) 65 return -ENOMEM; 66 67 INIT_LIST_HEAD(&private->pageflip_event_list); 68 dev_set_drvdata(dev->dev, dev); 69 dev->dev_private = (void *)private; 70 71 /* 72 * create mapping to manage iommu table and set a pointer to iommu 73 * mapping structure to iommu_mapping of private data. 74 * also this iommu_mapping can be used to check if iommu is supported 75 * or not. 76 */ 77 ret = drm_create_iommu_mapping(dev); 78 if (ret < 0) { 79 DRM_ERROR("failed to create iommu mapping.\n"); 80 goto err_free_private; 81 } 82 83 drm_mode_config_init(dev); 84 85 exynos_drm_mode_config_init(dev); 86 87 for (nr = 0; nr < MAX_PLANE; nr++) { 88 struct drm_plane *plane; 89 unsigned long possible_crtcs = (1 << MAX_CRTC) - 1; 90 91 plane = exynos_plane_init(dev, possible_crtcs, false); 92 if (!plane) 93 goto err_mode_config_cleanup; 94 } 95 96 /* init kms poll for handling hpd */ 97 drm_kms_helper_poll_init(dev); 98 99 ret = drm_vblank_init(dev, MAX_CRTC); 100 if (ret) 101 goto err_mode_config_cleanup; 102 103 /* setup possible_clones. */ 104 exynos_drm_encoder_setup(dev); 105 106 drm_vblank_offdelay = VBLANK_OFF_DELAY; 107 108 platform_set_drvdata(dev->platformdev, dev); 109 110 /* Try to bind all sub drivers. */ 111 ret = component_bind_all(dev->dev, dev); 112 if (ret) 113 goto err_cleanup_vblank; 114 115 /* Probe non kms sub drivers and virtual display driver. */ 116 ret = exynos_drm_device_subdrv_probe(dev); 117 if (ret) 118 goto err_unbind_all; 119 120 /* force connectors detection */ 121 drm_helper_hpd_irq_event(dev); 122 123 return 0; 124 125err_unbind_all: 126 component_unbind_all(dev->dev, dev); 127err_cleanup_vblank: 128 drm_vblank_cleanup(dev); 129err_mode_config_cleanup: 130 drm_mode_config_cleanup(dev); 131 drm_release_iommu_mapping(dev); 132err_free_private: 133 kfree(private); 134 135 return ret; 136} 137 138static int exynos_drm_unload(struct drm_device *dev) 139{ 140 exynos_drm_device_subdrv_remove(dev); 141 142 exynos_drm_fbdev_fini(dev); 143 drm_vblank_cleanup(dev); 144 drm_kms_helper_poll_fini(dev); 145 drm_mode_config_cleanup(dev); 146 147 drm_release_iommu_mapping(dev); 148 kfree(dev->dev_private); 149 150 component_unbind_all(dev->dev, dev); 151 dev->dev_private = NULL; 152 153 return 0; 154} 155 156static const struct file_operations exynos_drm_gem_fops = { 157 .mmap = exynos_drm_gem_mmap_buffer, 158}; 159 160static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state) 161{ 162 struct drm_connector *connector; 163 164 drm_modeset_lock_all(dev); 165 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 166 int old_dpms = connector->dpms; 167 168 if (connector->funcs->dpms) 169 connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF); 170 171 /* Set the old mode back to the connector for resume */ 172 connector->dpms = old_dpms; 173 } 174 drm_modeset_unlock_all(dev); 175 176 return 0; 177} 178 179static int exynos_drm_resume(struct drm_device *dev) 180{ 181 struct drm_connector *connector; 182 183 drm_modeset_lock_all(dev); 184 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 185 if (connector->funcs->dpms) 186 connector->funcs->dpms(connector, connector->dpms); 187 } 188 drm_modeset_unlock_all(dev); 189 190 drm_helper_resume_force_mode(dev); 191 192 return 0; 193} 194 195static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) 196{ 197 struct drm_exynos_file_private *file_priv; 198 struct file *anon_filp; 199 int ret; 200 201 file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); 202 if (!file_priv) 203 return -ENOMEM; 204 205 file->driver_priv = file_priv; 206 207 ret = exynos_drm_subdrv_open(dev, file); 208 if (ret) 209 goto err_file_priv_free; 210 211 anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops, 212 NULL, 0); 213 if (IS_ERR(anon_filp)) { 214 ret = PTR_ERR(anon_filp); 215 goto err_subdrv_close; 216 } 217 218 anon_filp->f_mode = FMODE_READ | FMODE_WRITE; 219 file_priv->anon_filp = anon_filp; 220 221 return ret; 222 223err_subdrv_close: 224 exynos_drm_subdrv_close(dev, file); 225 226err_file_priv_free: 227 kfree(file_priv); 228 file->driver_priv = NULL; 229 return ret; 230} 231 232static void exynos_drm_preclose(struct drm_device *dev, 233 struct drm_file *file) 234{ 235 exynos_drm_subdrv_close(dev, file); 236} 237 238static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) 239{ 240 struct exynos_drm_private *private = dev->dev_private; 241 struct drm_exynos_file_private *file_priv; 242 struct drm_pending_vblank_event *v, *vt; 243 struct drm_pending_event *e, *et; 244 unsigned long flags; 245 246 if (!file->driver_priv) 247 return; 248 249 /* Release all events not unhandled by page flip handler. */ 250 spin_lock_irqsave(&dev->event_lock, flags); 251 list_for_each_entry_safe(v, vt, &private->pageflip_event_list, 252 base.link) { 253 if (v->base.file_priv == file) { 254 list_del(&v->base.link); 255 drm_vblank_put(dev, v->pipe); 256 v->base.destroy(&v->base); 257 } 258 } 259 260 /* Release all events handled by page flip handler but not freed. */ 261 list_for_each_entry_safe(e, et, &file->event_list, link) { 262 list_del(&e->link); 263 e->destroy(e); 264 } 265 spin_unlock_irqrestore(&dev->event_lock, flags); 266 267 file_priv = file->driver_priv; 268 if (file_priv->anon_filp) 269 fput(file_priv->anon_filp); 270 271 kfree(file->driver_priv); 272 file->driver_priv = NULL; 273} 274 275static void exynos_drm_lastclose(struct drm_device *dev) 276{ 277 exynos_drm_fbdev_restore_mode(dev); 278} 279 280static const struct vm_operations_struct exynos_drm_gem_vm_ops = { 281 .fault = exynos_drm_gem_fault, 282 .open = drm_gem_vm_open, 283 .close = drm_gem_vm_close, 284}; 285 286static const struct drm_ioctl_desc exynos_ioctls[] = { 287 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, 288 DRM_UNLOCKED | DRM_AUTH), 289 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET, 290 exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED | 291 DRM_AUTH), 292 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, 293 exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), 294 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, 295 exynos_drm_gem_get_ioctl, DRM_UNLOCKED), 296 DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, 297 vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH), 298 DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, 299 exynos_g2d_get_ver_ioctl, DRM_UNLOCKED | DRM_AUTH), 300 DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, 301 exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH), 302 DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, 303 exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH), 304 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, 305 exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH), 306 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, 307 exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH), 308 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF, 309 exynos_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH), 310 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL, 311 exynos_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH), 312}; 313 314static const struct file_operations exynos_drm_driver_fops = { 315 .owner = THIS_MODULE, 316 .open = drm_open, 317 .mmap = exynos_drm_gem_mmap, 318 .poll = drm_poll, 319 .read = drm_read, 320 .unlocked_ioctl = drm_ioctl, 321#ifdef CONFIG_COMPAT 322 .compat_ioctl = drm_compat_ioctl, 323#endif 324 .release = drm_release, 325}; 326 327static struct drm_driver exynos_drm_driver = { 328 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, 329 .load = exynos_drm_load, 330 .unload = exynos_drm_unload, 331 .suspend = exynos_drm_suspend, 332 .resume = exynos_drm_resume, 333 .open = exynos_drm_open, 334 .preclose = exynos_drm_preclose, 335 .lastclose = exynos_drm_lastclose, 336 .postclose = exynos_drm_postclose, 337 .get_vblank_counter = drm_vblank_count, 338 .enable_vblank = exynos_drm_crtc_enable_vblank, 339 .disable_vblank = exynos_drm_crtc_disable_vblank, 340 .gem_free_object = exynos_drm_gem_free_object, 341 .gem_vm_ops = &exynos_drm_gem_vm_ops, 342 .dumb_create = exynos_drm_gem_dumb_create, 343 .dumb_map_offset = exynos_drm_gem_dumb_map_offset, 344 .dumb_destroy = drm_gem_dumb_destroy, 345 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 346 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 347 .gem_prime_export = exynos_dmabuf_prime_export, 348 .gem_prime_import = exynos_dmabuf_prime_import, 349 .ioctls = exynos_ioctls, 350 .num_ioctls = ARRAY_SIZE(exynos_ioctls), 351 .fops = &exynos_drm_driver_fops, 352 .name = DRIVER_NAME, 353 .desc = DRIVER_DESC, 354 .date = DRIVER_DATE, 355 .major = DRIVER_MAJOR, 356 .minor = DRIVER_MINOR, 357}; 358 359#ifdef CONFIG_PM_SLEEP 360static int exynos_drm_sys_suspend(struct device *dev) 361{ 362 struct drm_device *drm_dev = dev_get_drvdata(dev); 363 pm_message_t message; 364 365 if (pm_runtime_suspended(dev)) 366 return 0; 367 368 message.event = PM_EVENT_SUSPEND; 369 return exynos_drm_suspend(drm_dev, message); 370} 371 372static int exynos_drm_sys_resume(struct device *dev) 373{ 374 struct drm_device *drm_dev = dev_get_drvdata(dev); 375 376 if (pm_runtime_suspended(dev)) 377 return 0; 378 379 return exynos_drm_resume(drm_dev); 380} 381#endif 382 383static const struct dev_pm_ops exynos_drm_pm_ops = { 384 SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume) 385}; 386 387int exynos_drm_component_add(struct device *dev, 388 enum exynos_drm_device_type dev_type, 389 enum exynos_drm_output_type out_type) 390{ 391 struct component_dev *cdev; 392 393 if (dev_type != EXYNOS_DEVICE_TYPE_CRTC && 394 dev_type != EXYNOS_DEVICE_TYPE_CONNECTOR) { 395 DRM_ERROR("invalid device type.\n"); 396 return -EINVAL; 397 } 398 399 mutex_lock(&drm_component_lock); 400 401 /* 402 * Make sure to check if there is a component which has two device 403 * objects, for connector and for encoder/connector. 404 * It should make sure that crtc and encoder/connector drivers are 405 * ready before exynos drm core binds them. 406 */ 407 list_for_each_entry(cdev, &drm_component_list, list) { 408 if (cdev->out_type == out_type) { 409 /* 410 * If crtc and encoder/connector device objects are 411 * added already just return. 412 */ 413 if (cdev->dev_type_flag == (EXYNOS_DEVICE_TYPE_CRTC | 414 EXYNOS_DEVICE_TYPE_CONNECTOR)) { 415 mutex_unlock(&drm_component_lock); 416 return 0; 417 } 418 419 if (dev_type == EXYNOS_DEVICE_TYPE_CRTC) { 420 cdev->crtc_dev = dev; 421 cdev->dev_type_flag |= dev_type; 422 } 423 424 if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR) { 425 cdev->conn_dev = dev; 426 cdev->dev_type_flag |= dev_type; 427 } 428 429 mutex_unlock(&drm_component_lock); 430 return 0; 431 } 432 } 433 434 mutex_unlock(&drm_component_lock); 435 436 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 437 if (!cdev) 438 return -ENOMEM; 439 440 if (dev_type == EXYNOS_DEVICE_TYPE_CRTC) 441 cdev->crtc_dev = dev; 442 if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR) 443 cdev->conn_dev = dev; 444 445 cdev->out_type = out_type; 446 cdev->dev_type_flag = dev_type; 447 448 mutex_lock(&drm_component_lock); 449 list_add_tail(&cdev->list, &drm_component_list); 450 mutex_unlock(&drm_component_lock); 451 452 return 0; 453} 454 455void exynos_drm_component_del(struct device *dev, 456 enum exynos_drm_device_type dev_type) 457{ 458 struct component_dev *cdev, *next; 459 460 mutex_lock(&drm_component_lock); 461 462 list_for_each_entry_safe(cdev, next, &drm_component_list, list) { 463 if (dev_type == EXYNOS_DEVICE_TYPE_CRTC) { 464 if (cdev->crtc_dev == dev) { 465 cdev->crtc_dev = NULL; 466 cdev->dev_type_flag &= ~dev_type; 467 } 468 } 469 470 if (dev_type == EXYNOS_DEVICE_TYPE_CONNECTOR) { 471 if (cdev->conn_dev == dev) { 472 cdev->conn_dev = NULL; 473 cdev->dev_type_flag &= ~dev_type; 474 } 475 } 476 477 /* 478 * Release cdev object only in case that both of crtc and 479 * encoder/connector device objects are NULL. 480 */ 481 if (!cdev->crtc_dev && !cdev->conn_dev) { 482 list_del(&cdev->list); 483 kfree(cdev); 484 } 485 486 break; 487 } 488 489 mutex_unlock(&drm_component_lock); 490} 491 492static int compare_of(struct device *dev, void *data) 493{ 494 return dev == (struct device *)data; 495} 496 497static int exynos_drm_add_components(struct device *dev, struct master *m) 498{ 499 struct component_dev *cdev; 500 unsigned int attach_cnt = 0; 501 502 mutex_lock(&drm_component_lock); 503 504 list_for_each_entry(cdev, &drm_component_list, list) { 505 int ret; 506 507 /* 508 * Add components to master only in case that crtc and 509 * encoder/connector device objects exist. 510 */ 511 if (!cdev->crtc_dev || !cdev->conn_dev) 512 continue; 513 514 attach_cnt++; 515 516 mutex_unlock(&drm_component_lock); 517 518 /* 519 * fimd and dpi modules have same device object so add 520 * only crtc device object in this case. 521 * 522 * TODO. if dpi module follows driver-model driver then 523 * below codes can be removed. 524 */ 525 if (cdev->crtc_dev == cdev->conn_dev) { 526 ret = component_master_add_child(m, compare_of, 527 cdev->crtc_dev); 528 if (ret < 0) 529 return ret; 530 531 goto out_lock; 532 } 533 534 /* 535 * Do not chage below call order. 536 * crtc device first should be added to master because 537 * connector/encoder need pipe number of crtc when they 538 * are created. 539 */ 540 ret = component_master_add_child(m, compare_of, cdev->crtc_dev); 541 ret |= component_master_add_child(m, compare_of, 542 cdev->conn_dev); 543 if (ret < 0) 544 return ret; 545 546out_lock: 547 mutex_lock(&drm_component_lock); 548 } 549 550 mutex_unlock(&drm_component_lock); 551 552 return attach_cnt ? 0 : -ENODEV; 553} 554 555static int exynos_drm_bind(struct device *dev) 556{ 557 return drm_platform_init(&exynos_drm_driver, to_platform_device(dev)); 558} 559 560static void exynos_drm_unbind(struct device *dev) 561{ 562 drm_put_dev(dev_get_drvdata(dev)); 563} 564 565static const struct component_master_ops exynos_drm_ops = { 566 .add_components = exynos_drm_add_components, 567 .bind = exynos_drm_bind, 568 .unbind = exynos_drm_unbind, 569}; 570 571static int exynos_drm_platform_probe(struct platform_device *pdev) 572{ 573 int ret; 574 575 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 576 exynos_drm_driver.num_ioctls = ARRAY_SIZE(exynos_ioctls); 577 578#ifdef CONFIG_DRM_EXYNOS_FIMD 579 ret = platform_driver_register(&fimd_driver); 580 if (ret < 0) 581 return ret; 582#endif 583 584#ifdef CONFIG_DRM_EXYNOS_DP 585 ret = platform_driver_register(&dp_driver); 586 if (ret < 0) 587 goto err_unregister_fimd_drv; 588#endif 589 590#ifdef CONFIG_DRM_EXYNOS_DSI 591 ret = platform_driver_register(&dsi_driver); 592 if (ret < 0) 593 goto err_unregister_dp_drv; 594#endif 595 596#ifdef CONFIG_DRM_EXYNOS_HDMI 597 ret = platform_driver_register(&mixer_driver); 598 if (ret < 0) 599 goto err_unregister_dsi_drv; 600 ret = platform_driver_register(&hdmi_driver); 601 if (ret < 0) 602 goto err_unregister_mixer_drv; 603#endif 604 605#ifdef CONFIG_DRM_EXYNOS_G2D 606 ret = platform_driver_register(&g2d_driver); 607 if (ret < 0) 608 goto err_unregister_hdmi_drv; 609#endif 610 611#ifdef CONFIG_DRM_EXYNOS_FIMC 612 ret = platform_driver_register(&fimc_driver); 613 if (ret < 0) 614 goto err_unregister_g2d_drv; 615#endif 616 617#ifdef CONFIG_DRM_EXYNOS_ROTATOR 618 ret = platform_driver_register(&rotator_driver); 619 if (ret < 0) 620 goto err_unregister_fimc_drv; 621#endif 622 623#ifdef CONFIG_DRM_EXYNOS_GSC 624 ret = platform_driver_register(&gsc_driver); 625 if (ret < 0) 626 goto err_unregister_rotator_drv; 627#endif 628 629#ifdef CONFIG_DRM_EXYNOS_IPP 630 ret = platform_driver_register(&ipp_driver); 631 if (ret < 0) 632 goto err_unregister_gsc_drv; 633 634 ret = exynos_platform_device_ipp_register(); 635 if (ret < 0) 636 goto err_unregister_ipp_drv; 637#endif 638 639 ret = component_master_add(&pdev->dev, &exynos_drm_ops); 640 if (ret < 0) 641 DRM_DEBUG_KMS("re-tried by last sub driver probed later.\n"); 642 643 return 0; 644 645#ifdef CONFIG_DRM_EXYNOS_IPP 646err_unregister_ipp_drv: 647 platform_driver_unregister(&ipp_driver); 648err_unregister_gsc_drv: 649#endif 650 651#ifdef CONFIG_DRM_EXYNOS_GSC 652 platform_driver_unregister(&gsc_driver); 653err_unregister_rotator_drv: 654#endif 655 656#ifdef CONFIG_DRM_EXYNOS_ROTATOR 657 platform_driver_unregister(&rotator_driver); 658err_unregister_fimc_drv: 659#endif 660 661#ifdef CONFIG_DRM_EXYNOS_FIMC 662 platform_driver_unregister(&fimc_driver); 663err_unregister_g2d_drv: 664#endif 665 666#ifdef CONFIG_DRM_EXYNOS_G2D 667 platform_driver_unregister(&g2d_driver); 668err_unregister_hdmi_drv: 669#endif 670 671#ifdef CONFIG_DRM_EXYNOS_HDMI 672 platform_driver_unregister(&hdmi_driver); 673err_unregister_mixer_drv: 674 platform_driver_unregister(&mixer_driver); 675err_unregister_dsi_drv: 676#endif 677 678#ifdef CONFIG_DRM_EXYNOS_DSI 679 platform_driver_unregister(&dsi_driver); 680err_unregister_dp_drv: 681#endif 682 683#ifdef CONFIG_DRM_EXYNOS_DP 684 platform_driver_unregister(&dp_driver); 685err_unregister_fimd_drv: 686#endif 687 688#ifdef CONFIG_DRM_EXYNOS_FIMD 689 platform_driver_unregister(&fimd_driver); 690#endif 691 return ret; 692} 693 694static int exynos_drm_platform_remove(struct platform_device *pdev) 695{ 696#ifdef CONFIG_DRM_EXYNOS_IPP 697 exynos_platform_device_ipp_unregister(); 698 platform_driver_unregister(&ipp_driver); 699#endif 700 701#ifdef CONFIG_DRM_EXYNOS_GSC 702 platform_driver_unregister(&gsc_driver); 703#endif 704 705#ifdef CONFIG_DRM_EXYNOS_ROTATOR 706 platform_driver_unregister(&rotator_driver); 707#endif 708 709#ifdef CONFIG_DRM_EXYNOS_FIMC 710 platform_driver_unregister(&fimc_driver); 711#endif 712 713#ifdef CONFIG_DRM_EXYNOS_G2D 714 platform_driver_unregister(&g2d_driver); 715#endif 716 717#ifdef CONFIG_DRM_EXYNOS_HDMI 718 platform_driver_unregister(&mixer_driver); 719 platform_driver_unregister(&hdmi_driver); 720#endif 721 722#ifdef CONFIG_DRM_EXYNOS_FIMD 723 platform_driver_unregister(&fimd_driver); 724#endif 725 726#ifdef CONFIG_DRM_EXYNOS_DSI 727 platform_driver_unregister(&dsi_driver); 728#endif 729 730#ifdef CONFIG_DRM_EXYNOS_DP 731 platform_driver_unregister(&dp_driver); 732#endif 733 component_master_del(&pdev->dev, &exynos_drm_ops); 734 return 0; 735} 736 737static struct platform_driver exynos_drm_platform_driver = { 738 .probe = exynos_drm_platform_probe, 739 .remove = exynos_drm_platform_remove, 740 .driver = { 741 .owner = THIS_MODULE, 742 .name = "exynos-drm", 743 .pm = &exynos_drm_pm_ops, 744 }, 745}; 746 747static int exynos_drm_init(void) 748{ 749 int ret; 750 751 exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, 752 NULL, 0); 753 if (IS_ERR(exynos_drm_pdev)) 754 return PTR_ERR(exynos_drm_pdev); 755 756#ifdef CONFIG_DRM_EXYNOS_VIDI 757 ret = exynos_drm_probe_vidi(); 758 if (ret < 0) 759 goto err_unregister_pd; 760#endif 761 762 ret = platform_driver_register(&exynos_drm_platform_driver); 763 if (ret) 764 goto err_remove_vidi; 765 766 return 0; 767 768err_remove_vidi: 769#ifdef CONFIG_DRM_EXYNOS_VIDI 770 exynos_drm_remove_vidi(); 771 772err_unregister_pd: 773#endif 774 platform_device_unregister(exynos_drm_pdev); 775 776 return ret; 777} 778 779static void exynos_drm_exit(void) 780{ 781 platform_driver_unregister(&exynos_drm_platform_driver); 782#ifdef CONFIG_DRM_EXYNOS_VIDI 783 exynos_drm_remove_vidi(); 784#endif 785 platform_device_unregister(exynos_drm_pdev); 786} 787 788module_init(exynos_drm_init); 789module_exit(exynos_drm_exit); 790 791MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); 792MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 793MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>"); 794MODULE_DESCRIPTION("Samsung SoC DRM Driver"); 795MODULE_LICENSE("GPL");