root/drivers/gpu/drm/drm_mode_config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. drm_modeset_register_all
  2. drm_modeset_unregister_all
  3. drm_mode_getresources
  4. drm_mode_config_reset
  5. drm_mode_create_standard_properties
  6. drm_mode_config_init
  7. drm_mode_config_cleanup

   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 
  34 int 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 
  56 err_connector:
  57         drm_encoder_unregister_all(dev);
  58 err_encoder:
  59         drm_crtc_unregister_all(dev);
  60 err_crtc:
  61         drm_plane_unregister_all(dev);
  62 err_plane:
  63         return ret;
  64 }
  65 
  66 void 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  */
  88 int 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  */
 179 void 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 }
 205 EXPORT_SYMBOL(drm_mode_config_reset);
 206 
 207 /*
 208  * Global properties
 209  */
 210 static 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 
 216 static 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  */
 387 void 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 }
 419 EXPORT_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  */
 434 void 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 }
 508 EXPORT_SYMBOL(drm_mode_config_cleanup);

/* [<][>][^][v][top][bottom][index][help] */