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