linux/drivers/gpu/drm/exynos/exynos_drm_drv.c
<<
>>
Prefs
   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 <drm/drmP.h>
  15#include <drm/drm_crtc_helper.h>
  16
  17#include <drm/exynos_drm.h>
  18
  19#include "exynos_drm_drv.h"
  20#include "exynos_drm_crtc.h"
  21#include "exynos_drm_encoder.h"
  22#include "exynos_drm_fbdev.h"
  23#include "exynos_drm_fb.h"
  24#include "exynos_drm_gem.h"
  25#include "exynos_drm_plane.h"
  26#include "exynos_drm_vidi.h"
  27#include "exynos_drm_dmabuf.h"
  28#include "exynos_drm_g2d.h"
  29#include "exynos_drm_ipp.h"
  30#include "exynos_drm_iommu.h"
  31
  32#define DRIVER_NAME     "exynos"
  33#define DRIVER_DESC     "Samsung SoC DRM"
  34#define DRIVER_DATE     "20110530"
  35#define DRIVER_MAJOR    1
  36#define DRIVER_MINOR    0
  37
  38#define VBLANK_OFF_DELAY        50000
  39
  40/* platform device pointer for eynos drm device. */
  41static struct platform_device *exynos_drm_pdev;
  42
  43static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
  44{
  45        struct exynos_drm_private *private;
  46        int ret;
  47        int nr;
  48
  49        DRM_DEBUG_DRIVER("%s\n", __FILE__);
  50
  51        private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
  52        if (!private) {
  53                DRM_ERROR("failed to allocate private\n");
  54                return -ENOMEM;
  55        }
  56
  57        INIT_LIST_HEAD(&private->pageflip_event_list);
  58        dev->dev_private = (void *)private;
  59
  60        /*
  61         * create mapping to manage iommu table and set a pointer to iommu
  62         * mapping structure to iommu_mapping of private data.
  63         * also this iommu_mapping can be used to check if iommu is supported
  64         * or not.
  65         */
  66        ret = drm_create_iommu_mapping(dev);
  67        if (ret < 0) {
  68                DRM_ERROR("failed to create iommu mapping.\n");
  69                goto err_crtc;
  70        }
  71
  72        drm_mode_config_init(dev);
  73
  74        /* init kms poll for handling hpd */
  75        drm_kms_helper_poll_init(dev);
  76
  77        exynos_drm_mode_config_init(dev);
  78
  79        /*
  80         * EXYNOS4 is enough to have two CRTCs and each crtc would be used
  81         * without dependency of hardware.
  82         */
  83        for (nr = 0; nr < MAX_CRTC; nr++) {
  84                ret = exynos_drm_crtc_create(dev, nr);
  85                if (ret)
  86                        goto err_release_iommu_mapping;
  87        }
  88
  89        for (nr = 0; nr < MAX_PLANE; nr++) {
  90                struct drm_plane *plane;
  91                unsigned int possible_crtcs = (1 << MAX_CRTC) - 1;
  92
  93                plane = exynos_plane_init(dev, possible_crtcs, false);
  94                if (!plane)
  95                        goto err_release_iommu_mapping;
  96        }
  97
  98        ret = drm_vblank_init(dev, MAX_CRTC);
  99        if (ret)
 100                goto err_release_iommu_mapping;
 101
 102        /*
 103         * probe sub drivers such as display controller and hdmi driver,
 104         * that were registered at probe() of platform driver
 105         * to the sub driver and create encoder and connector for them.
 106         */
 107        ret = exynos_drm_device_register(dev);
 108        if (ret)
 109                goto err_vblank;
 110
 111        /* setup possible_clones. */
 112        exynos_drm_encoder_setup(dev);
 113
 114        /*
 115         * create and configure fb helper and also exynos specific
 116         * fbdev object.
 117         */
 118        ret = exynos_drm_fbdev_init(dev);
 119        if (ret) {
 120                DRM_ERROR("failed to initialize drm fbdev\n");
 121                goto err_drm_device;
 122        }
 123
 124        drm_vblank_offdelay = VBLANK_OFF_DELAY;
 125
 126        return 0;
 127
 128err_drm_device:
 129        exynos_drm_device_unregister(dev);
 130err_vblank:
 131        drm_vblank_cleanup(dev);
 132err_release_iommu_mapping:
 133        drm_release_iommu_mapping(dev);
 134err_crtc:
 135        drm_mode_config_cleanup(dev);
 136        kfree(private);
 137
 138        return ret;
 139}
 140
 141static int exynos_drm_unload(struct drm_device *dev)
 142{
 143        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 144
 145        exynos_drm_fbdev_fini(dev);
 146        exynos_drm_device_unregister(dev);
 147        drm_vblank_cleanup(dev);
 148        drm_kms_helper_poll_fini(dev);
 149        drm_mode_config_cleanup(dev);
 150
 151        drm_release_iommu_mapping(dev);
 152        kfree(dev->dev_private);
 153
 154        dev->dev_private = NULL;
 155
 156        return 0;
 157}
 158
 159static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 160{
 161        struct drm_exynos_file_private *file_priv;
 162
 163        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 164
 165        file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
 166        if (!file_priv)
 167                return -ENOMEM;
 168
 169        file->driver_priv = file_priv;
 170
 171        return exynos_drm_subdrv_open(dev, file);
 172}
 173
 174static void exynos_drm_preclose(struct drm_device *dev,
 175                                        struct drm_file *file)
 176{
 177        struct exynos_drm_private *private = dev->dev_private;
 178        struct drm_pending_vblank_event *e, *t;
 179        unsigned long flags;
 180
 181        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 182
 183        /* release events of current file */
 184        spin_lock_irqsave(&dev->event_lock, flags);
 185        list_for_each_entry_safe(e, t, &private->pageflip_event_list,
 186                        base.link) {
 187                if (e->base.file_priv == file) {
 188                        list_del(&e->base.link);
 189                        e->base.destroy(&e->base);
 190                }
 191        }
 192        spin_unlock_irqrestore(&dev->event_lock, flags);
 193
 194        exynos_drm_subdrv_close(dev, file);
 195}
 196
 197static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 198{
 199        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 200
 201        if (!file->driver_priv)
 202                return;
 203
 204        kfree(file->driver_priv);
 205        file->driver_priv = NULL;
 206}
 207
 208static void exynos_drm_lastclose(struct drm_device *dev)
 209{
 210        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 211
 212        exynos_drm_fbdev_restore_mode(dev);
 213}
 214
 215static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
 216        .fault = exynos_drm_gem_fault,
 217        .open = drm_gem_vm_open,
 218        .close = drm_gem_vm_close,
 219};
 220
 221static struct drm_ioctl_desc exynos_ioctls[] = {
 222        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
 223                        DRM_UNLOCKED | DRM_AUTH),
 224        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
 225                        exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
 226                        DRM_AUTH),
 227        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
 228                        exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
 229        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET,
 230                        exynos_drm_gem_get_ioctl, DRM_UNLOCKED),
 231        DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
 232                        vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH),
 233        DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER,
 234                        exynos_g2d_get_ver_ioctl, DRM_UNLOCKED | DRM_AUTH),
 235        DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST,
 236                        exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH),
 237        DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC,
 238                        exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
 239        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY,
 240                        exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH),
 241        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY,
 242                        exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH),
 243        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF,
 244                        exynos_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH),
 245        DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL,
 246                        exynos_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH),
 247};
 248
 249static const struct file_operations exynos_drm_driver_fops = {
 250        .owner          = THIS_MODULE,
 251        .open           = drm_open,
 252        .mmap           = exynos_drm_gem_mmap,
 253        .poll           = drm_poll,
 254        .read           = drm_read,
 255        .unlocked_ioctl = drm_ioctl,
 256#ifdef CONFIG_COMPAT
 257        .compat_ioctl = drm_compat_ioctl,
 258#endif
 259        .release        = drm_release,
 260};
 261
 262static struct drm_driver exynos_drm_driver = {
 263        .driver_features        = DRIVER_HAVE_IRQ | DRIVER_MODESET |
 264                                        DRIVER_GEM | DRIVER_PRIME,
 265        .load                   = exynos_drm_load,
 266        .unload                 = exynos_drm_unload,
 267        .open                   = exynos_drm_open,
 268        .preclose               = exynos_drm_preclose,
 269        .lastclose              = exynos_drm_lastclose,
 270        .postclose              = exynos_drm_postclose,
 271        .get_vblank_counter     = drm_vblank_count,
 272        .enable_vblank          = exynos_drm_crtc_enable_vblank,
 273        .disable_vblank         = exynos_drm_crtc_disable_vblank,
 274        .gem_init_object        = exynos_drm_gem_init_object,
 275        .gem_free_object        = exynos_drm_gem_free_object,
 276        .gem_vm_ops             = &exynos_drm_gem_vm_ops,
 277        .dumb_create            = exynos_drm_gem_dumb_create,
 278        .dumb_map_offset        = exynos_drm_gem_dumb_map_offset,
 279        .dumb_destroy           = exynos_drm_gem_dumb_destroy,
 280        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
 281        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
 282        .gem_prime_export       = exynos_dmabuf_prime_export,
 283        .gem_prime_import       = exynos_dmabuf_prime_import,
 284        .ioctls                 = exynos_ioctls,
 285        .fops                   = &exynos_drm_driver_fops,
 286        .name   = DRIVER_NAME,
 287        .desc   = DRIVER_DESC,
 288        .date   = DRIVER_DATE,
 289        .major  = DRIVER_MAJOR,
 290        .minor  = DRIVER_MINOR,
 291};
 292
 293static int exynos_drm_platform_probe(struct platform_device *pdev)
 294{
 295        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 296
 297        pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 298        exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
 299
 300        return drm_platform_init(&exynos_drm_driver, pdev);
 301}
 302
 303static int exynos_drm_platform_remove(struct platform_device *pdev)
 304{
 305        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 306
 307        drm_platform_exit(&exynos_drm_driver, pdev);
 308
 309        return 0;
 310}
 311
 312static struct platform_driver exynos_drm_platform_driver = {
 313        .probe          = exynos_drm_platform_probe,
 314        .remove         = exynos_drm_platform_remove,
 315        .driver         = {
 316                .owner  = THIS_MODULE,
 317                .name   = "exynos-drm",
 318        },
 319};
 320
 321static int __init exynos_drm_init(void)
 322{
 323        int ret;
 324
 325        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 326
 327#ifdef CONFIG_DRM_EXYNOS_FIMD
 328        ret = platform_driver_register(&fimd_driver);
 329        if (ret < 0)
 330                goto out_fimd;
 331#endif
 332
 333#ifdef CONFIG_DRM_EXYNOS_HDMI
 334        ret = platform_driver_register(&hdmi_driver);
 335        if (ret < 0)
 336                goto out_hdmi;
 337        ret = platform_driver_register(&mixer_driver);
 338        if (ret < 0)
 339                goto out_mixer;
 340        ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
 341        if (ret < 0)
 342                goto out_common_hdmi;
 343
 344        ret = exynos_platform_device_hdmi_register();
 345        if (ret < 0)
 346                goto out_common_hdmi_dev;
 347#endif
 348
 349#ifdef CONFIG_DRM_EXYNOS_VIDI
 350        ret = platform_driver_register(&vidi_driver);
 351        if (ret < 0)
 352                goto out_vidi;
 353#endif
 354
 355#ifdef CONFIG_DRM_EXYNOS_G2D
 356        ret = platform_driver_register(&g2d_driver);
 357        if (ret < 0)
 358                goto out_g2d;
 359#endif
 360
 361#ifdef CONFIG_DRM_EXYNOS_FIMC
 362        ret = platform_driver_register(&fimc_driver);
 363        if (ret < 0)
 364                goto out_fimc;
 365#endif
 366
 367#ifdef CONFIG_DRM_EXYNOS_ROTATOR
 368        ret = platform_driver_register(&rotator_driver);
 369        if (ret < 0)
 370                goto out_rotator;
 371#endif
 372
 373#ifdef CONFIG_DRM_EXYNOS_GSC
 374        ret = platform_driver_register(&gsc_driver);
 375        if (ret < 0)
 376                goto out_gsc;
 377#endif
 378
 379#ifdef CONFIG_DRM_EXYNOS_IPP
 380        ret = platform_driver_register(&ipp_driver);
 381        if (ret < 0)
 382                goto out_ipp;
 383
 384        ret = exynos_platform_device_ipp_register();
 385        if (ret < 0)
 386                goto out_ipp_dev;
 387#endif
 388
 389        ret = platform_driver_register(&exynos_drm_platform_driver);
 390        if (ret < 0)
 391                goto out_drm;
 392
 393        exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
 394                                NULL, 0);
 395        if (IS_ERR(exynos_drm_pdev)) {
 396                ret = PTR_ERR(exynos_drm_pdev);
 397                goto out;
 398        }
 399
 400        return 0;
 401
 402out:
 403        platform_driver_unregister(&exynos_drm_platform_driver);
 404
 405out_drm:
 406#ifdef CONFIG_DRM_EXYNOS_IPP
 407        exynos_platform_device_ipp_unregister();
 408out_ipp_dev:
 409        platform_driver_unregister(&ipp_driver);
 410out_ipp:
 411#endif
 412
 413#ifdef CONFIG_DRM_EXYNOS_GSC
 414        platform_driver_unregister(&gsc_driver);
 415out_gsc:
 416#endif
 417
 418#ifdef CONFIG_DRM_EXYNOS_ROTATOR
 419        platform_driver_unregister(&rotator_driver);
 420out_rotator:
 421#endif
 422
 423#ifdef CONFIG_DRM_EXYNOS_FIMC
 424        platform_driver_unregister(&fimc_driver);
 425out_fimc:
 426#endif
 427
 428#ifdef CONFIG_DRM_EXYNOS_G2D
 429        platform_driver_unregister(&g2d_driver);
 430out_g2d:
 431#endif
 432
 433#ifdef CONFIG_DRM_EXYNOS_VIDI
 434        platform_driver_unregister(&vidi_driver);
 435out_vidi:
 436#endif
 437
 438#ifdef CONFIG_DRM_EXYNOS_HDMI
 439        exynos_platform_device_hdmi_unregister();
 440out_common_hdmi_dev:
 441        platform_driver_unregister(&exynos_drm_common_hdmi_driver);
 442out_common_hdmi:
 443        platform_driver_unregister(&mixer_driver);
 444out_mixer:
 445        platform_driver_unregister(&hdmi_driver);
 446out_hdmi:
 447#endif
 448
 449#ifdef CONFIG_DRM_EXYNOS_FIMD
 450        platform_driver_unregister(&fimd_driver);
 451out_fimd:
 452#endif
 453        return ret;
 454}
 455
 456static void __exit exynos_drm_exit(void)
 457{
 458        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 459
 460        platform_device_unregister(exynos_drm_pdev);
 461
 462        platform_driver_unregister(&exynos_drm_platform_driver);
 463
 464#ifdef CONFIG_DRM_EXYNOS_IPP
 465        exynos_platform_device_ipp_unregister();
 466        platform_driver_unregister(&ipp_driver);
 467#endif
 468
 469#ifdef CONFIG_DRM_EXYNOS_GSC
 470        platform_driver_unregister(&gsc_driver);
 471#endif
 472
 473#ifdef CONFIG_DRM_EXYNOS_ROTATOR
 474        platform_driver_unregister(&rotator_driver);
 475#endif
 476
 477#ifdef CONFIG_DRM_EXYNOS_FIMC
 478        platform_driver_unregister(&fimc_driver);
 479#endif
 480
 481#ifdef CONFIG_DRM_EXYNOS_G2D
 482        platform_driver_unregister(&g2d_driver);
 483#endif
 484
 485#ifdef CONFIG_DRM_EXYNOS_HDMI
 486        exynos_platform_device_hdmi_unregister();
 487        platform_driver_unregister(&exynos_drm_common_hdmi_driver);
 488        platform_driver_unregister(&mixer_driver);
 489        platform_driver_unregister(&hdmi_driver);
 490#endif
 491
 492#ifdef CONFIG_DRM_EXYNOS_VIDI
 493        platform_driver_unregister(&vidi_driver);
 494#endif
 495
 496#ifdef CONFIG_DRM_EXYNOS_FIMD
 497        platform_driver_unregister(&fimd_driver);
 498#endif
 499}
 500
 501module_init(exynos_drm_init);
 502module_exit(exynos_drm_exit);
 503
 504MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
 505MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
 506MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
 507MODULE_DESCRIPTION("Samsung SoC DRM Driver");
 508MODULE_LICENSE("GPL");
 509