linux/drivers/gpu/drm/omapdrm/omap_drv.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   3 * Author: Rob Clark <rob@ti.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of the GNU General Public License version 2 as published by
   7 * the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program.  If not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#include <linux/sys_soc.h>
  19
  20#include <drm/drm_atomic.h>
  21#include <drm/drm_atomic_helper.h>
  22#include <drm/drm_crtc_helper.h>
  23#include <drm/drm_fb_helper.h>
  24
  25#include "omap_dmm_tiler.h"
  26#include "omap_drv.h"
  27
  28#define DRIVER_NAME             MODULE_NAME
  29#define DRIVER_DESC             "OMAP DRM"
  30#define DRIVER_DATE             "20110917"
  31#define DRIVER_MAJOR            1
  32#define DRIVER_MINOR            0
  33#define DRIVER_PATCHLEVEL       0
  34
  35/*
  36 * mode config funcs
  37 */
  38
  39/* Notes about mapping DSS and DRM entities:
  40 *    CRTC:        overlay
  41 *    encoder:     manager.. with some extension to allow one primary CRTC
  42 *                 and zero or more video CRTC's to be mapped to one encoder?
  43 *    connector:   dssdev.. manager can be attached/detached from different
  44 *                 devices
  45 */
  46
  47static void omap_atomic_wait_for_completion(struct drm_device *dev,
  48                                            struct drm_atomic_state *old_state)
  49{
  50        struct drm_crtc_state *new_crtc_state;
  51        struct drm_crtc *crtc;
  52        unsigned int i;
  53        int ret;
  54
  55        for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
  56                if (!new_crtc_state->active)
  57                        continue;
  58
  59                ret = omap_crtc_wait_pending(crtc);
  60
  61                if (!ret)
  62                        dev_warn(dev->dev,
  63                                 "atomic complete timeout (pipe %u)!\n", i);
  64        }
  65}
  66
  67static void omap_atomic_commit_tail(struct drm_atomic_state *old_state)
  68{
  69        struct drm_device *dev = old_state->dev;
  70        struct omap_drm_private *priv = dev->dev_private;
  71
  72        priv->dispc_ops->runtime_get(priv->dispc);
  73
  74        /* Apply the atomic update. */
  75        drm_atomic_helper_commit_modeset_disables(dev, old_state);
  76
  77        if (priv->omaprev != 0x3430) {
  78                /* With the current dss dispc implementation we have to enable
  79                 * the new modeset before we can commit planes. The dispc ovl
  80                 * configuration relies on the video mode configuration been
  81                 * written into the HW when the ovl configuration is
  82                 * calculated.
  83                 *
  84                 * This approach is not ideal because after a mode change the
  85                 * plane update is executed only after the first vblank
  86                 * interrupt. The dispc implementation should be fixed so that
  87                 * it is able use uncommitted drm state information.
  88                 */
  89                drm_atomic_helper_commit_modeset_enables(dev, old_state);
  90                omap_atomic_wait_for_completion(dev, old_state);
  91
  92                drm_atomic_helper_commit_planes(dev, old_state, 0);
  93
  94                drm_atomic_helper_commit_hw_done(old_state);
  95        } else {
  96                /*
  97                 * OMAP3 DSS seems to have issues with the work-around above,
  98                 * resulting in endless sync losts if a crtc is enabled without
  99                 * a plane. For now, skip the WA for OMAP3.
 100                 */
 101                drm_atomic_helper_commit_planes(dev, old_state, 0);
 102
 103                drm_atomic_helper_commit_modeset_enables(dev, old_state);
 104
 105                drm_atomic_helper_commit_hw_done(old_state);
 106        }
 107
 108        /*
 109         * Wait for completion of the page flips to ensure that old buffers
 110         * can't be touched by the hardware anymore before cleaning up planes.
 111         */
 112        omap_atomic_wait_for_completion(dev, old_state);
 113
 114        drm_atomic_helper_cleanup_planes(dev, old_state);
 115
 116        priv->dispc_ops->runtime_put(priv->dispc);
 117}
 118
 119static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs = {
 120        .atomic_commit_tail = omap_atomic_commit_tail,
 121};
 122
 123static const struct drm_mode_config_funcs omap_mode_config_funcs = {
 124        .fb_create = omap_framebuffer_create,
 125        .output_poll_changed = drm_fb_helper_output_poll_changed,
 126        .atomic_check = drm_atomic_helper_check,
 127        .atomic_commit = drm_atomic_helper_commit,
 128};
 129
 130static int get_connector_type(struct omap_dss_device *dssdev)
 131{
 132        switch (dssdev->type) {
 133        case OMAP_DISPLAY_TYPE_HDMI:
 134                return DRM_MODE_CONNECTOR_HDMIA;
 135        case OMAP_DISPLAY_TYPE_DVI:
 136                return DRM_MODE_CONNECTOR_DVID;
 137        case OMAP_DISPLAY_TYPE_DSI:
 138                return DRM_MODE_CONNECTOR_DSI;
 139        case OMAP_DISPLAY_TYPE_DPI:
 140        case OMAP_DISPLAY_TYPE_DBI:
 141                return DRM_MODE_CONNECTOR_DPI;
 142        case OMAP_DISPLAY_TYPE_VENC:
 143                /* TODO: This could also be composite */
 144                return DRM_MODE_CONNECTOR_SVIDEO;
 145        case OMAP_DISPLAY_TYPE_SDI:
 146                return DRM_MODE_CONNECTOR_LVDS;
 147        default:
 148                return DRM_MODE_CONNECTOR_Unknown;
 149        }
 150}
 151
 152static void omap_disconnect_dssdevs(void)
 153{
 154        struct omap_dss_device *dssdev = NULL;
 155
 156        for_each_dss_dev(dssdev)
 157                dssdev->driver->disconnect(dssdev);
 158}
 159
 160static int omap_connect_dssdevs(void)
 161{
 162        int r;
 163        struct omap_dss_device *dssdev = NULL;
 164
 165        if (!omapdss_stack_is_ready())
 166                return -EPROBE_DEFER;
 167
 168        for_each_dss_dev(dssdev) {
 169                r = dssdev->driver->connect(dssdev);
 170                if (r == -EPROBE_DEFER) {
 171                        omap_dss_put_device(dssdev);
 172                        goto cleanup;
 173                } else if (r) {
 174                        dev_warn(dssdev->dev, "could not connect display: %s\n",
 175                                dssdev->name);
 176                }
 177        }
 178
 179        return 0;
 180
 181cleanup:
 182        /*
 183         * if we are deferring probe, we disconnect the devices we previously
 184         * connected
 185         */
 186        omap_disconnect_dssdevs();
 187
 188        return r;
 189}
 190
 191static int omap_modeset_init_properties(struct drm_device *dev)
 192{
 193        struct omap_drm_private *priv = dev->dev_private;
 194        unsigned int num_planes = priv->dispc_ops->get_num_ovls(priv->dispc);
 195
 196        priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0,
 197                                                      num_planes - 1);
 198        if (!priv->zorder_prop)
 199                return -ENOMEM;
 200
 201        return 0;
 202}
 203
 204static int omap_modeset_init(struct drm_device *dev)
 205{
 206        struct omap_drm_private *priv = dev->dev_private;
 207        struct omap_dss_device *dssdev = NULL;
 208        int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc);
 209        int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc);
 210        int num_crtcs, crtc_idx, plane_idx;
 211        int ret;
 212        u32 plane_crtc_mask;
 213
 214        drm_mode_config_init(dev);
 215
 216        ret = omap_modeset_init_properties(dev);
 217        if (ret < 0)
 218                return ret;
 219
 220        /*
 221         * This function creates exactly one connector, encoder, crtc,
 222         * and primary plane per each connected dss-device. Each
 223         * connector->encoder->crtc chain is expected to be separate
 224         * and each crtc is connect to a single dss-channel. If the
 225         * configuration does not match the expectations or exceeds
 226         * the available resources, the configuration is rejected.
 227         */
 228        num_crtcs = 0;
 229        for_each_dss_dev(dssdev)
 230                if (omapdss_device_is_connected(dssdev))
 231                        num_crtcs++;
 232
 233        if (num_crtcs > num_mgrs || num_crtcs > num_ovls ||
 234            num_crtcs > ARRAY_SIZE(priv->crtcs) ||
 235            num_crtcs > ARRAY_SIZE(priv->planes) ||
 236            num_crtcs > ARRAY_SIZE(priv->encoders) ||
 237            num_crtcs > ARRAY_SIZE(priv->connectors)) {
 238                dev_err(dev->dev, "%s(): Too many connected displays\n",
 239                        __func__);
 240                return -EINVAL;
 241        }
 242
 243        /* All planes can be put to any CRTC */
 244        plane_crtc_mask = (1 << num_crtcs) - 1;
 245
 246        dssdev = NULL;
 247
 248        crtc_idx = 0;
 249        plane_idx = 0;
 250        for_each_dss_dev(dssdev) {
 251                struct drm_connector *connector;
 252                struct drm_encoder *encoder;
 253                struct drm_plane *plane;
 254                struct drm_crtc *crtc;
 255
 256                if (!omapdss_device_is_connected(dssdev))
 257                        continue;
 258
 259                encoder = omap_encoder_init(dev, dssdev);
 260                if (!encoder)
 261                        return -ENOMEM;
 262
 263                connector = omap_connector_init(dev,
 264                                get_connector_type(dssdev), dssdev, encoder);
 265                if (!connector)
 266                        return -ENOMEM;
 267
 268                plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_PRIMARY,
 269                                        plane_crtc_mask);
 270                if (IS_ERR(plane))
 271                        return PTR_ERR(plane);
 272
 273                crtc = omap_crtc_init(dev, plane, dssdev);
 274                if (IS_ERR(crtc))
 275                        return PTR_ERR(crtc);
 276
 277                drm_mode_connector_attach_encoder(connector, encoder);
 278                encoder->possible_crtcs = (1 << crtc_idx);
 279
 280                priv->crtcs[priv->num_crtcs++] = crtc;
 281                priv->planes[priv->num_planes++] = plane;
 282                priv->encoders[priv->num_encoders++] = encoder;
 283                priv->connectors[priv->num_connectors++] = connector;
 284
 285                plane_idx++;
 286                crtc_idx++;
 287        }
 288
 289        /*
 290         * Create normal planes for the remaining overlays:
 291         */
 292        for (; plane_idx < num_ovls; plane_idx++) {
 293                struct drm_plane *plane;
 294
 295                if (WARN_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)))
 296                        return -EINVAL;
 297
 298                plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_OVERLAY,
 299                        plane_crtc_mask);
 300                if (IS_ERR(plane))
 301                        return PTR_ERR(plane);
 302
 303                priv->planes[priv->num_planes++] = plane;
 304        }
 305
 306        DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n",
 307                priv->num_planes, priv->num_crtcs, priv->num_encoders,
 308                priv->num_connectors);
 309
 310        dev->mode_config.min_width = 8;
 311        dev->mode_config.min_height = 2;
 312
 313        /*
 314         * Note: these values are used for multiple independent things:
 315         * connector mode filtering, buffer sizes, crtc sizes...
 316         * Use big enough values here to cover all use cases, and do more
 317         * specific checking in the respective code paths.
 318         */
 319        dev->mode_config.max_width = 8192;
 320        dev->mode_config.max_height = 8192;
 321
 322        dev->mode_config.funcs = &omap_mode_config_funcs;
 323        dev->mode_config.helper_private = &omap_mode_config_helper_funcs;
 324
 325        drm_mode_config_reset(dev);
 326
 327        omap_drm_irq_install(dev);
 328
 329        return 0;
 330}
 331
 332/*
 333 * Enable the HPD in external components if supported
 334 */
 335static void omap_modeset_enable_external_hpd(void)
 336{
 337        struct omap_dss_device *dssdev = NULL;
 338
 339        for_each_dss_dev(dssdev) {
 340                if (dssdev->driver->enable_hpd)
 341                        dssdev->driver->enable_hpd(dssdev);
 342        }
 343}
 344
 345/*
 346 * Disable the HPD in external components if supported
 347 */
 348static void omap_modeset_disable_external_hpd(void)
 349{
 350        struct omap_dss_device *dssdev = NULL;
 351
 352        for_each_dss_dev(dssdev) {
 353                if (dssdev->driver->disable_hpd)
 354                        dssdev->driver->disable_hpd(dssdev);
 355        }
 356}
 357
 358/*
 359 * drm ioctl funcs
 360 */
 361
 362
 363static int ioctl_get_param(struct drm_device *dev, void *data,
 364                struct drm_file *file_priv)
 365{
 366        struct omap_drm_private *priv = dev->dev_private;
 367        struct drm_omap_param *args = data;
 368
 369        DBG("%p: param=%llu", dev, args->param);
 370
 371        switch (args->param) {
 372        case OMAP_PARAM_CHIPSET_ID:
 373                args->value = priv->omaprev;
 374                break;
 375        default:
 376                DBG("unknown parameter %lld", args->param);
 377                return -EINVAL;
 378        }
 379
 380        return 0;
 381}
 382
 383static int ioctl_set_param(struct drm_device *dev, void *data,
 384                struct drm_file *file_priv)
 385{
 386        struct drm_omap_param *args = data;
 387
 388        switch (args->param) {
 389        default:
 390                DBG("unknown parameter %lld", args->param);
 391                return -EINVAL;
 392        }
 393
 394        return 0;
 395}
 396
 397#define OMAP_BO_USER_MASK       0x00ffffff      /* flags settable by userspace */
 398
 399static int ioctl_gem_new(struct drm_device *dev, void *data,
 400                struct drm_file *file_priv)
 401{
 402        struct drm_omap_gem_new *args = data;
 403        u32 flags = args->flags & OMAP_BO_USER_MASK;
 404
 405        VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
 406             args->size.bytes, flags);
 407
 408        return omap_gem_new_handle(dev, file_priv, args->size, flags,
 409                                   &args->handle);
 410}
 411
 412static int ioctl_gem_info(struct drm_device *dev, void *data,
 413                struct drm_file *file_priv)
 414{
 415        struct drm_omap_gem_info *args = data;
 416        struct drm_gem_object *obj;
 417        int ret = 0;
 418
 419        VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
 420
 421        obj = drm_gem_object_lookup(file_priv, args->handle);
 422        if (!obj)
 423                return -ENOENT;
 424
 425        args->size = omap_gem_mmap_size(obj);
 426        args->offset = omap_gem_mmap_offset(obj);
 427
 428        drm_gem_object_unreference_unlocked(obj);
 429
 430        return ret;
 431}
 432
 433static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
 434        DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param,
 435                          DRM_AUTH | DRM_RENDER_ALLOW),
 436        DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param,
 437                          DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
 438        DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new,
 439                          DRM_AUTH | DRM_RENDER_ALLOW),
 440        /* Deprecated, to be removed. */
 441        DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, drm_noop,
 442                          DRM_AUTH | DRM_RENDER_ALLOW),
 443        /* Deprecated, to be removed. */
 444        DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, drm_noop,
 445                          DRM_AUTH | DRM_RENDER_ALLOW),
 446        DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info,
 447                          DRM_AUTH | DRM_RENDER_ALLOW),
 448};
 449
 450/*
 451 * drm driver funcs
 452 */
 453
 454static int dev_open(struct drm_device *dev, struct drm_file *file)
 455{
 456        file->driver_priv = NULL;
 457
 458        DBG("open: dev=%p, file=%p", dev, file);
 459
 460        return 0;
 461}
 462
 463static const struct vm_operations_struct omap_gem_vm_ops = {
 464        .fault = omap_gem_fault,
 465        .open = drm_gem_vm_open,
 466        .close = drm_gem_vm_close,
 467};
 468
 469static const struct file_operations omapdriver_fops = {
 470        .owner = THIS_MODULE,
 471        .open = drm_open,
 472        .unlocked_ioctl = drm_ioctl,
 473        .compat_ioctl = drm_compat_ioctl,
 474        .release = drm_release,
 475        .mmap = omap_gem_mmap,
 476        .poll = drm_poll,
 477        .read = drm_read,
 478        .llseek = noop_llseek,
 479};
 480
 481static struct drm_driver omap_drm_driver = {
 482        .driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME |
 483                DRIVER_ATOMIC | DRIVER_RENDER,
 484        .open = dev_open,
 485        .lastclose = drm_fb_helper_lastclose,
 486#ifdef CONFIG_DEBUG_FS
 487        .debugfs_init = omap_debugfs_init,
 488#endif
 489        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
 490        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 491        .gem_prime_export = omap_gem_prime_export,
 492        .gem_prime_import = omap_gem_prime_import,
 493        .gem_free_object = omap_gem_free_object,
 494        .gem_vm_ops = &omap_gem_vm_ops,
 495        .dumb_create = omap_gem_dumb_create,
 496        .dumb_map_offset = omap_gem_dumb_map_offset,
 497        .ioctls = ioctls,
 498        .num_ioctls = DRM_OMAP_NUM_IOCTLS,
 499        .fops = &omapdriver_fops,
 500        .name = DRIVER_NAME,
 501        .desc = DRIVER_DESC,
 502        .date = DRIVER_DATE,
 503        .major = DRIVER_MAJOR,
 504        .minor = DRIVER_MINOR,
 505        .patchlevel = DRIVER_PATCHLEVEL,
 506};
 507
 508static const struct soc_device_attribute omapdrm_soc_devices[] = {
 509        { .family = "OMAP3", .data = (void *)0x3430 },
 510        { .family = "OMAP4", .data = (void *)0x4430 },
 511        { .family = "OMAP5", .data = (void *)0x5430 },
 512        { .family = "DRA7",  .data = (void *)0x0752 },
 513        { /* sentinel */ }
 514};
 515
 516static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
 517{
 518        const struct soc_device_attribute *soc;
 519        struct drm_device *ddev;
 520        unsigned int i;
 521        int ret;
 522
 523        DBG("%s", dev_name(dev));
 524
 525        priv->dev = dev;
 526        priv->dss = omapdss_get_dss();
 527        priv->dispc = dispc_get_dispc(priv->dss);
 528        priv->dispc_ops = dispc_get_ops(priv->dss);
 529
 530        omap_crtc_pre_init(priv);
 531
 532        ret = omap_connect_dssdevs();
 533        if (ret)
 534                goto err_crtc_uninit;
 535
 536        soc = soc_device_match(omapdrm_soc_devices);
 537        priv->omaprev = soc ? (unsigned int)soc->data : 0;
 538        priv->wq = alloc_ordered_workqueue("omapdrm", 0);
 539
 540        spin_lock_init(&priv->list_lock);
 541        INIT_LIST_HEAD(&priv->obj_list);
 542
 543        /* Allocate and initialize the DRM device. */
 544        ddev = drm_dev_alloc(&omap_drm_driver, priv->dev);
 545        if (IS_ERR(ddev)) {
 546                ret = PTR_ERR(ddev);
 547                goto err_destroy_wq;
 548        }
 549
 550        priv->ddev = ddev;
 551        ddev->dev_private = priv;
 552
 553        /* Get memory bandwidth limits */
 554        if (priv->dispc_ops->get_memory_bandwidth_limit)
 555                priv->max_bandwidth =
 556                        priv->dispc_ops->get_memory_bandwidth_limit(priv->dispc);
 557
 558        omap_gem_init(ddev);
 559
 560        ret = omap_modeset_init(ddev);
 561        if (ret) {
 562                dev_err(priv->dev, "omap_modeset_init failed: ret=%d\n", ret);
 563                goto err_free_drm_dev;
 564        }
 565
 566        /* Initialize vblank handling, start with all CRTCs disabled. */
 567        ret = drm_vblank_init(ddev, priv->num_crtcs);
 568        if (ret) {
 569                dev_err(priv->dev, "could not init vblank\n");
 570                goto err_cleanup_modeset;
 571        }
 572
 573        for (i = 0; i < priv->num_crtcs; i++)
 574                drm_crtc_vblank_off(priv->crtcs[i]);
 575
 576        omap_fbdev_init(ddev);
 577
 578        drm_kms_helper_poll_init(ddev);
 579        omap_modeset_enable_external_hpd();
 580
 581        /*
 582         * Register the DRM device with the core and the connectors with
 583         * sysfs.
 584         */
 585        ret = drm_dev_register(ddev, 0);
 586        if (ret)
 587                goto err_cleanup_helpers;
 588
 589        return 0;
 590
 591err_cleanup_helpers:
 592        omap_modeset_disable_external_hpd();
 593        drm_kms_helper_poll_fini(ddev);
 594
 595        omap_fbdev_fini(ddev);
 596err_cleanup_modeset:
 597        drm_mode_config_cleanup(ddev);
 598        omap_drm_irq_uninstall(ddev);
 599err_free_drm_dev:
 600        omap_gem_deinit(ddev);
 601        drm_dev_unref(ddev);
 602err_destroy_wq:
 603        destroy_workqueue(priv->wq);
 604        omap_disconnect_dssdevs();
 605err_crtc_uninit:
 606        omap_crtc_pre_uninit();
 607        return ret;
 608}
 609
 610static void omapdrm_cleanup(struct omap_drm_private *priv)
 611{
 612        struct drm_device *ddev = priv->ddev;
 613
 614        DBG("");
 615
 616        drm_dev_unregister(ddev);
 617
 618        omap_modeset_disable_external_hpd();
 619        drm_kms_helper_poll_fini(ddev);
 620
 621        omap_fbdev_fini(ddev);
 622
 623        drm_atomic_helper_shutdown(ddev);
 624
 625        drm_mode_config_cleanup(ddev);
 626
 627        omap_drm_irq_uninstall(ddev);
 628        omap_gem_deinit(ddev);
 629
 630        drm_dev_unref(ddev);
 631
 632        destroy_workqueue(priv->wq);
 633
 634        omap_disconnect_dssdevs();
 635        omap_crtc_pre_uninit();
 636}
 637
 638static int pdev_probe(struct platform_device *pdev)
 639{
 640        struct omap_drm_private *priv;
 641        int ret;
 642
 643        if (omapdss_is_initialized() == false)
 644                return -EPROBE_DEFER;
 645
 646        ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 647        if (ret) {
 648                dev_err(&pdev->dev, "Failed to set the DMA mask\n");
 649                return ret;
 650        }
 651
 652        /* Allocate and initialize the driver private structure. */
 653        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 654        if (!priv)
 655                return -ENOMEM;
 656
 657        platform_set_drvdata(pdev, priv);
 658
 659        ret = omapdrm_init(priv, &pdev->dev);
 660        if (ret < 0)
 661                kfree(priv);
 662
 663        return ret;
 664}
 665
 666static int pdev_remove(struct platform_device *pdev)
 667{
 668        struct omap_drm_private *priv = platform_get_drvdata(pdev);
 669
 670        omapdrm_cleanup(priv);
 671        kfree(priv);
 672
 673        return 0;
 674}
 675
 676#ifdef CONFIG_PM_SLEEP
 677static int omap_drm_suspend_all_displays(void)
 678{
 679        struct omap_dss_device *dssdev = NULL;
 680
 681        for_each_dss_dev(dssdev) {
 682                if (!dssdev->driver)
 683                        continue;
 684
 685                if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
 686                        dssdev->driver->disable(dssdev);
 687                        dssdev->activate_after_resume = true;
 688                } else {
 689                        dssdev->activate_after_resume = false;
 690                }
 691        }
 692
 693        return 0;
 694}
 695
 696static int omap_drm_resume_all_displays(void)
 697{
 698        struct omap_dss_device *dssdev = NULL;
 699
 700        for_each_dss_dev(dssdev) {
 701                if (!dssdev->driver)
 702                        continue;
 703
 704                if (dssdev->activate_after_resume) {
 705                        dssdev->driver->enable(dssdev);
 706                        dssdev->activate_after_resume = false;
 707                }
 708        }
 709
 710        return 0;
 711}
 712
 713static int omap_drm_suspend(struct device *dev)
 714{
 715        struct omap_drm_private *priv = dev_get_drvdata(dev);
 716        struct drm_device *drm_dev = priv->ddev;
 717
 718        drm_kms_helper_poll_disable(drm_dev);
 719
 720        drm_modeset_lock_all(drm_dev);
 721        omap_drm_suspend_all_displays();
 722        drm_modeset_unlock_all(drm_dev);
 723
 724        return 0;
 725}
 726
 727static int omap_drm_resume(struct device *dev)
 728{
 729        struct omap_drm_private *priv = dev_get_drvdata(dev);
 730        struct drm_device *drm_dev = priv->ddev;
 731
 732        drm_modeset_lock_all(drm_dev);
 733        omap_drm_resume_all_displays();
 734        drm_modeset_unlock_all(drm_dev);
 735
 736        drm_kms_helper_poll_enable(drm_dev);
 737
 738        return omap_gem_resume(drm_dev);
 739}
 740#endif
 741
 742static SIMPLE_DEV_PM_OPS(omapdrm_pm_ops, omap_drm_suspend, omap_drm_resume);
 743
 744static struct platform_driver pdev = {
 745        .driver = {
 746                .name = "omapdrm",
 747                .pm = &omapdrm_pm_ops,
 748        },
 749        .probe = pdev_probe,
 750        .remove = pdev_remove,
 751};
 752
 753static struct platform_driver * const drivers[] = {
 754        &omap_dmm_driver,
 755        &pdev,
 756};
 757
 758static int __init omap_drm_init(void)
 759{
 760        DBG("init");
 761
 762        return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
 763}
 764
 765static void __exit omap_drm_fini(void)
 766{
 767        DBG("fini");
 768
 769        platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 770}
 771
 772/* need late_initcall() so we load after dss_driver's are loaded */
 773late_initcall(omap_drm_init);
 774module_exit(omap_drm_fini);
 775
 776MODULE_AUTHOR("Rob Clark <rob@ti.com>");
 777MODULE_DESCRIPTION("OMAP DRM Display Driver");
 778MODULE_ALIAS("platform:" DRIVER_NAME);
 779MODULE_LICENSE("GPL v2");
 780