linux/drivers/gpu/drm/drm_mode_config.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 Intel Corporation
   3 *
   4 * Permission to use, copy, modify, distribute, and sell this software and its
   5 * documentation for any purpose is hereby granted without fee, provided that
   6 * the above copyright notice appear in all copies and that both that copyright
   7 * notice and this permission notice appear in supporting documentation, and
   8 * that the name of the copyright holders not be used in advertising or
   9 * publicity pertaining to distribution of the software without specific,
  10 * written prior permission.  The copyright holders make no representations
  11 * about the suitability of this software for any purpose.  It is provided "as
  12 * is" without express or implied warranty.
  13 *
  14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20 * OF THIS SOFTWARE.
  21 */
  22
  23#include <drm/drm_encoder.h>
  24#include <drm/drm_mode_config.h>
  25#include <drm/drmP.h>
  26
  27#include "drm_crtc_internal.h"
  28#include "drm_internal.h"
  29
  30int drm_modeset_register_all(struct drm_device *dev)
  31{
  32        int ret;
  33
  34        ret = drm_plane_register_all(dev);
  35        if (ret)
  36                goto err_plane;
  37
  38        ret = drm_crtc_register_all(dev);
  39        if  (ret)
  40                goto err_crtc;
  41
  42        ret = drm_encoder_register_all(dev);
  43        if (ret)
  44                goto err_encoder;
  45
  46        ret = drm_connector_register_all(dev);
  47        if (ret)
  48                goto err_connector;
  49
  50        return 0;
  51
  52err_connector:
  53        drm_encoder_unregister_all(dev);
  54err_encoder:
  55        drm_crtc_unregister_all(dev);
  56err_crtc:
  57        drm_plane_unregister_all(dev);
  58err_plane:
  59        return ret;
  60}
  61
  62void drm_modeset_unregister_all(struct drm_device *dev)
  63{
  64        drm_connector_unregister_all(dev);
  65        drm_encoder_unregister_all(dev);
  66        drm_crtc_unregister_all(dev);
  67        drm_plane_unregister_all(dev);
  68}
  69
  70/**
  71 * drm_mode_getresources - get graphics configuration
  72 * @dev: drm device for the ioctl
  73 * @data: data pointer for the ioctl
  74 * @file_priv: drm file for the ioctl call
  75 *
  76 * Construct a set of configuration description structures and return
  77 * them to the user, including CRTC, connector and framebuffer configuration.
  78 *
  79 * Called by the user via ioctl.
  80 *
  81 * Returns:
  82 * Zero on success, negative errno on failure.
  83 */
  84int drm_mode_getresources(struct drm_device *dev, void *data,
  85                          struct drm_file *file_priv)
  86{
  87        struct drm_mode_card_res *card_res = data;
  88        struct drm_framebuffer *fb;
  89        struct drm_connector *connector;
  90        struct drm_crtc *crtc;
  91        struct drm_encoder *encoder;
  92        int count, ret = 0;
  93        uint32_t __user *fb_id;
  94        uint32_t __user *crtc_id;
  95        uint32_t __user *connector_id;
  96        uint32_t __user *encoder_id;
  97        struct drm_connector_list_iter conn_iter;
  98
  99        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 100                return -EINVAL;
 101
 102
 103        mutex_lock(&file_priv->fbs_lock);
 104        count = 0;
 105        fb_id = u64_to_user_ptr(card_res->fb_id_ptr);
 106        list_for_each_entry(fb, &file_priv->fbs, filp_head) {
 107                if (count < card_res->count_fbs &&
 108                    put_user(fb->base.id, fb_id + count)) {
 109                        mutex_unlock(&file_priv->fbs_lock);
 110                        return -EFAULT;
 111                }
 112                count++;
 113        }
 114        card_res->count_fbs = count;
 115        mutex_unlock(&file_priv->fbs_lock);
 116
 117        card_res->max_height = dev->mode_config.max_height;
 118        card_res->min_height = dev->mode_config.min_height;
 119        card_res->max_width = dev->mode_config.max_width;
 120        card_res->min_width = dev->mode_config.min_width;
 121
 122        count = 0;
 123        crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
 124        drm_for_each_crtc(crtc, dev) {
 125                if (drm_lease_held(file_priv, crtc->base.id)) {
 126                        if (count < card_res->count_crtcs &&
 127                            put_user(crtc->base.id, crtc_id + count))
 128                                return -EFAULT;
 129                        count++;
 130                }
 131        }
 132        card_res->count_crtcs = count;
 133
 134        count = 0;
 135        encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
 136        drm_for_each_encoder(encoder, dev) {
 137                if (count < card_res->count_encoders &&
 138                    put_user(encoder->base.id, encoder_id + count))
 139                        return -EFAULT;
 140                count++;
 141        }
 142        card_res->count_encoders = count;
 143
 144        drm_connector_list_iter_begin(dev, &conn_iter);
 145        count = 0;
 146        connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
 147        drm_for_each_connector_iter(connector, &conn_iter) {
 148                if (drm_lease_held(file_priv, connector->base.id)) {
 149                        if (count < card_res->count_connectors &&
 150                            put_user(connector->base.id, connector_id + count)) {
 151                                drm_connector_list_iter_end(&conn_iter);
 152                                return -EFAULT;
 153                        }
 154                        count++;
 155                }
 156        }
 157        card_res->count_connectors = count;
 158        drm_connector_list_iter_end(&conn_iter);
 159
 160        return ret;
 161}
 162
 163/**
 164 * drm_mode_config_reset - call ->reset callbacks
 165 * @dev: drm device
 166 *
 167 * This functions calls all the crtc's, encoder's and connector's ->reset
 168 * callback. Drivers can use this in e.g. their driver load or resume code to
 169 * reset hardware and software state.
 170 */
 171void drm_mode_config_reset(struct drm_device *dev)
 172{
 173        struct drm_crtc *crtc;
 174        struct drm_plane *plane;
 175        struct drm_encoder *encoder;
 176        struct drm_connector *connector;
 177        struct drm_connector_list_iter conn_iter;
 178
 179        drm_for_each_plane(plane, dev)
 180                if (plane->funcs->reset)
 181                        plane->funcs->reset(plane);
 182
 183        drm_for_each_crtc(crtc, dev)
 184                if (crtc->funcs->reset)
 185                        crtc->funcs->reset(crtc);
 186
 187        drm_for_each_encoder(encoder, dev)
 188                if (encoder->funcs->reset)
 189                        encoder->funcs->reset(encoder);
 190
 191        drm_connector_list_iter_begin(dev, &conn_iter);
 192        drm_for_each_connector_iter(connector, &conn_iter)
 193                if (connector->funcs->reset)
 194                        connector->funcs->reset(connector);
 195        drm_connector_list_iter_end(&conn_iter);
 196}
 197EXPORT_SYMBOL(drm_mode_config_reset);
 198
 199/*
 200 * Global properties
 201 */
 202static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
 203        { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
 204        { DRM_PLANE_TYPE_PRIMARY, "Primary" },
 205        { DRM_PLANE_TYPE_CURSOR, "Cursor" },
 206};
 207
 208static int drm_mode_create_standard_properties(struct drm_device *dev)
 209{
 210        struct drm_property *prop;
 211        int ret;
 212
 213        ret = drm_connector_create_standard_properties(dev);
 214        if (ret)
 215                return ret;
 216
 217        prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
 218                                        "type", drm_plane_type_enum_list,
 219                                        ARRAY_SIZE(drm_plane_type_enum_list));
 220        if (!prop)
 221                return -ENOMEM;
 222        dev->mode_config.plane_type_property = prop;
 223
 224        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 225                        "SRC_X", 0, UINT_MAX);
 226        if (!prop)
 227                return -ENOMEM;
 228        dev->mode_config.prop_src_x = prop;
 229
 230        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 231                        "SRC_Y", 0, UINT_MAX);
 232        if (!prop)
 233                return -ENOMEM;
 234        dev->mode_config.prop_src_y = prop;
 235
 236        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 237                        "SRC_W", 0, UINT_MAX);
 238        if (!prop)
 239                return -ENOMEM;
 240        dev->mode_config.prop_src_w = prop;
 241
 242        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 243                        "SRC_H", 0, UINT_MAX);
 244        if (!prop)
 245                return -ENOMEM;
 246        dev->mode_config.prop_src_h = prop;
 247
 248        prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
 249                        "CRTC_X", INT_MIN, INT_MAX);
 250        if (!prop)
 251                return -ENOMEM;
 252        dev->mode_config.prop_crtc_x = prop;
 253
 254        prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
 255                        "CRTC_Y", INT_MIN, INT_MAX);
 256        if (!prop)
 257                return -ENOMEM;
 258        dev->mode_config.prop_crtc_y = prop;
 259
 260        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 261                        "CRTC_W", 0, INT_MAX);
 262        if (!prop)
 263                return -ENOMEM;
 264        dev->mode_config.prop_crtc_w = prop;
 265
 266        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 267                        "CRTC_H", 0, INT_MAX);
 268        if (!prop)
 269                return -ENOMEM;
 270        dev->mode_config.prop_crtc_h = prop;
 271
 272        prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
 273                        "FB_ID", DRM_MODE_OBJECT_FB);
 274        if (!prop)
 275                return -ENOMEM;
 276        dev->mode_config.prop_fb_id = prop;
 277
 278        prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
 279                        "IN_FENCE_FD", -1, INT_MAX);
 280        if (!prop)
 281                return -ENOMEM;
 282        dev->mode_config.prop_in_fence_fd = prop;
 283
 284        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 285                        "OUT_FENCE_PTR", 0, U64_MAX);
 286        if (!prop)
 287                return -ENOMEM;
 288        dev->mode_config.prop_out_fence_ptr = prop;
 289
 290        prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
 291                        "CRTC_ID", DRM_MODE_OBJECT_CRTC);
 292        if (!prop)
 293                return -ENOMEM;
 294        dev->mode_config.prop_crtc_id = prop;
 295
 296        prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
 297                        "ACTIVE");
 298        if (!prop)
 299                return -ENOMEM;
 300        dev->mode_config.prop_active = prop;
 301
 302        prop = drm_property_create(dev,
 303                        DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
 304                        "MODE_ID", 0);
 305        if (!prop)
 306                return -ENOMEM;
 307        dev->mode_config.prop_mode_id = prop;
 308
 309        prop = drm_property_create(dev,
 310                        DRM_MODE_PROP_BLOB,
 311                        "DEGAMMA_LUT", 0);
 312        if (!prop)
 313                return -ENOMEM;
 314        dev->mode_config.degamma_lut_property = prop;
 315
 316        prop = drm_property_create_range(dev,
 317                        DRM_MODE_PROP_IMMUTABLE,
 318                        "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
 319        if (!prop)
 320                return -ENOMEM;
 321        dev->mode_config.degamma_lut_size_property = prop;
 322
 323        prop = drm_property_create(dev,
 324                        DRM_MODE_PROP_BLOB,
 325                        "CTM", 0);
 326        if (!prop)
 327                return -ENOMEM;
 328        dev->mode_config.ctm_property = prop;
 329
 330        prop = drm_property_create(dev,
 331                        DRM_MODE_PROP_BLOB,
 332                        "GAMMA_LUT", 0);
 333        if (!prop)
 334                return -ENOMEM;
 335        dev->mode_config.gamma_lut_property = prop;
 336
 337        prop = drm_property_create_range(dev,
 338                        DRM_MODE_PROP_IMMUTABLE,
 339                        "GAMMA_LUT_SIZE", 0, UINT_MAX);
 340        if (!prop)
 341                return -ENOMEM;
 342        dev->mode_config.gamma_lut_size_property = prop;
 343
 344        prop = drm_property_create(dev,
 345                                   DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
 346                                   "IN_FORMATS", 0);
 347        if (!prop)
 348                return -ENOMEM;
 349        dev->mode_config.modifiers_property = prop;
 350
 351        return 0;
 352}
 353
 354/**
 355 * drm_mode_config_init - initialize DRM mode_configuration structure
 356 * @dev: DRM device
 357 *
 358 * Initialize @dev's mode_config structure, used for tracking the graphics
 359 * configuration of @dev.
 360 *
 361 * Since this initializes the modeset locks, no locking is possible. Which is no
 362 * problem, since this should happen single threaded at init time. It is the
 363 * driver's problem to ensure this guarantee.
 364 *
 365 */
 366void drm_mode_config_init(struct drm_device *dev)
 367{
 368        mutex_init(&dev->mode_config.mutex);
 369        drm_modeset_lock_init(&dev->mode_config.connection_mutex);
 370        mutex_init(&dev->mode_config.idr_mutex);
 371        mutex_init(&dev->mode_config.fb_lock);
 372        mutex_init(&dev->mode_config.blob_lock);
 373        INIT_LIST_HEAD(&dev->mode_config.fb_list);
 374        INIT_LIST_HEAD(&dev->mode_config.crtc_list);
 375        INIT_LIST_HEAD(&dev->mode_config.connector_list);
 376        INIT_LIST_HEAD(&dev->mode_config.encoder_list);
 377        INIT_LIST_HEAD(&dev->mode_config.property_list);
 378        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
 379        INIT_LIST_HEAD(&dev->mode_config.plane_list);
 380        idr_init(&dev->mode_config.crtc_idr);
 381        idr_init(&dev->mode_config.tile_idr);
 382        ida_init(&dev->mode_config.connector_ida);
 383        spin_lock_init(&dev->mode_config.connector_list_lock);
 384
 385        init_llist_head(&dev->mode_config.connector_free_list);
 386        INIT_WORK(&dev->mode_config.connector_free_work, drm_connector_free_work_fn);
 387
 388        drm_mode_create_standard_properties(dev);
 389
 390        /* Just to be sure */
 391        dev->mode_config.num_fb = 0;
 392        dev->mode_config.num_connector = 0;
 393        dev->mode_config.num_crtc = 0;
 394        dev->mode_config.num_encoder = 0;
 395        dev->mode_config.num_total_plane = 0;
 396}
 397EXPORT_SYMBOL(drm_mode_config_init);
 398
 399/**
 400 * drm_mode_config_cleanup - free up DRM mode_config info
 401 * @dev: DRM device
 402 *
 403 * Free up all the connectors and CRTCs associated with this DRM device, then
 404 * free up the framebuffers and associated buffer objects.
 405 *
 406 * Note that since this /should/ happen single-threaded at driver/device
 407 * teardown time, no locking is required. It's the driver's job to ensure that
 408 * this guarantee actually holds true.
 409 *
 410 * FIXME: cleanup any dangling user buffer objects too
 411 */
 412void drm_mode_config_cleanup(struct drm_device *dev)
 413{
 414        struct drm_connector *connector;
 415        struct drm_connector_list_iter conn_iter;
 416        struct drm_crtc *crtc, *ct;
 417        struct drm_encoder *encoder, *enct;
 418        struct drm_framebuffer *fb, *fbt;
 419        struct drm_property *property, *pt;
 420        struct drm_property_blob *blob, *bt;
 421        struct drm_plane *plane, *plt;
 422
 423        list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
 424                                 head) {
 425                encoder->funcs->destroy(encoder);
 426        }
 427
 428        drm_connector_list_iter_begin(dev, &conn_iter);
 429        drm_for_each_connector_iter(connector, &conn_iter) {
 430                /* drm_connector_list_iter holds an full reference to the
 431                 * current connector itself, which means it is inherently safe
 432                 * against unreferencing the current connector - but not against
 433                 * deleting it right away. */
 434                drm_connector_put(connector);
 435        }
 436        drm_connector_list_iter_end(&conn_iter);
 437        /* connector_iter drops references in a work item. */
 438        flush_work(&dev->mode_config.connector_free_work);
 439        if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) {
 440                drm_connector_list_iter_begin(dev, &conn_iter);
 441                drm_for_each_connector_iter(connector, &conn_iter)
 442                        DRM_ERROR("connector %s leaked!\n", connector->name);
 443                drm_connector_list_iter_end(&conn_iter);
 444        }
 445
 446        list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
 447                                 head) {
 448                drm_property_destroy(dev, property);
 449        }
 450
 451        list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
 452                                 head) {
 453                plane->funcs->destroy(plane);
 454        }
 455
 456        list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
 457                crtc->funcs->destroy(crtc);
 458        }
 459
 460        list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
 461                                 head_global) {
 462                drm_property_blob_put(blob);
 463        }
 464
 465        /*
 466         * Single-threaded teardown context, so it's not required to grab the
 467         * fb_lock to protect against concurrent fb_list access. Contrary, it
 468         * would actually deadlock with the drm_framebuffer_cleanup function.
 469         *
 470         * Also, if there are any framebuffers left, that's a driver leak now,
 471         * so politely WARN about this.
 472         */
 473        WARN_ON(!list_empty(&dev->mode_config.fb_list));
 474        list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
 475                struct drm_printer p = drm_debug_printer("[leaked fb]");
 476                drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
 477                drm_framebuffer_print_info(&p, 1, fb);
 478                drm_framebuffer_free(&fb->base.refcount);
 479        }
 480
 481        ida_destroy(&dev->mode_config.connector_ida);
 482        idr_destroy(&dev->mode_config.tile_idr);
 483        idr_destroy(&dev->mode_config.crtc_idr);
 484        drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
 485}
 486EXPORT_SYMBOL(drm_mode_config_cleanup);
 487