linux/drivers/gpu/drm/drm_plane.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/drmP.h>
  24#include <drm/drm_plane.h>
  25
  26#include "drm_crtc_internal.h"
  27
  28/**
  29 * DOC: overview
  30 *
  31 * A plane represents an image source that can be blended with or overlayed on
  32 * top of a CRTC during the scanout process. Planes take their input data from a
  33 * &drm_framebuffer object. The plane itself specifies the cropping and scaling
  34 * of that image, and where it is placed on the visible are of a display
  35 * pipeline, represented by &drm_crtc. A plane can also have additional
  36 * properties that specify how the pixels are positioned and blended, like
  37 * rotation or Z-position. All these properties are stored in &drm_plane_state.
  38 *
  39 * To create a plane, a KMS drivers allocates and zeroes an instances of
  40 * &struct drm_plane (possibly as part of a larger structure) and registers it
  41 * with a call to drm_universal_plane_init().
  42 *
  43 * Cursor and overlay planes are optional. All drivers should provide one
  44 * primary plane per CRTC to avoid surprising userspace too much. See enum
  45 * drm_plane_type for a more in-depth discussion of these special uapi-relevant
  46 * plane types. Special planes are associated with their CRTC by calling
  47 * drm_crtc_init_with_planes().
  48 *
  49 * The type of a plane is exposed in the immutable "type" enumeration property,
  50 * which has one of the following values: "Overlay", "Primary", "Cursor".
  51 */
  52
  53static unsigned int drm_num_planes(struct drm_device *dev)
  54{
  55        unsigned int num = 0;
  56        struct drm_plane *tmp;
  57
  58        drm_for_each_plane(tmp, dev) {
  59                num++;
  60        }
  61
  62        return num;
  63}
  64
  65static inline u32 *
  66formats_ptr(struct drm_format_modifier_blob *blob)
  67{
  68        return (u32 *)(((char *)blob) + blob->formats_offset);
  69}
  70
  71static inline struct drm_format_modifier *
  72modifiers_ptr(struct drm_format_modifier_blob *blob)
  73{
  74        return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
  75}
  76
  77static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane)
  78{
  79        const struct drm_mode_config *config = &dev->mode_config;
  80        struct drm_property_blob *blob;
  81        struct drm_format_modifier *mod;
  82        size_t blob_size, formats_size, modifiers_size;
  83        struct drm_format_modifier_blob *blob_data;
  84        unsigned int i, j;
  85
  86        formats_size = sizeof(__u32) * plane->format_count;
  87        if (WARN_ON(!formats_size)) {
  88                /* 0 formats are never expected */
  89                return 0;
  90        }
  91
  92        modifiers_size =
  93                sizeof(struct drm_format_modifier) * plane->modifier_count;
  94
  95        blob_size = sizeof(struct drm_format_modifier_blob);
  96        /* Modifiers offset is a pointer to a struct with a 64 bit field so it
  97         * should be naturally aligned to 8B.
  98         */
  99        BUILD_BUG_ON(sizeof(struct drm_format_modifier_blob) % 8);
 100        blob_size += ALIGN(formats_size, 8);
 101        blob_size += modifiers_size;
 102
 103        blob = drm_property_create_blob(dev, blob_size, NULL);
 104        if (IS_ERR(blob))
 105                return -1;
 106
 107        blob_data = (struct drm_format_modifier_blob *)blob->data;
 108        blob_data->version = FORMAT_BLOB_CURRENT;
 109        blob_data->count_formats = plane->format_count;
 110        blob_data->formats_offset = sizeof(struct drm_format_modifier_blob);
 111        blob_data->count_modifiers = plane->modifier_count;
 112
 113        blob_data->modifiers_offset =
 114                ALIGN(blob_data->formats_offset + formats_size, 8);
 115
 116        memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
 117
 118        /* If we can't determine support, just bail */
 119        if (!plane->funcs->format_mod_supported)
 120                goto done;
 121
 122        mod = modifiers_ptr(blob_data);
 123        for (i = 0; i < plane->modifier_count; i++) {
 124                for (j = 0; j < plane->format_count; j++) {
 125                        if (plane->funcs->format_mod_supported(plane,
 126                                                               plane->format_types[j],
 127                                                               plane->modifiers[i])) {
 128
 129                                mod->formats |= 1ULL << j;
 130                        }
 131                }
 132
 133                mod->modifier = plane->modifiers[i];
 134                mod->offset = 0;
 135                mod->pad = 0;
 136                mod++;
 137        }
 138
 139done:
 140        drm_object_attach_property(&plane->base, config->modifiers_property,
 141                                   blob->base.id);
 142
 143        return 0;
 144}
 145
 146/**
 147 * drm_universal_plane_init - Initialize a new universal plane object
 148 * @dev: DRM device
 149 * @plane: plane object to init
 150 * @possible_crtcs: bitmask of possible CRTCs
 151 * @funcs: callbacks for the new plane
 152 * @formats: array of supported formats (DRM_FORMAT\_\*)
 153 * @format_count: number of elements in @formats
 154 * @format_modifiers: array of struct drm_format modifiers terminated by
 155 *                    DRM_FORMAT_MOD_INVALID
 156 * @type: type of plane (overlay, primary, cursor)
 157 * @name: printf style format string for the plane name, or NULL for default name
 158 *
 159 * Initializes a plane object of type @type.
 160 *
 161 * Returns:
 162 * Zero on success, error code on failure.
 163 */
 164int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 165                             uint32_t possible_crtcs,
 166                             const struct drm_plane_funcs *funcs,
 167                             const uint32_t *formats, unsigned int format_count,
 168                             const uint64_t *format_modifiers,
 169                             enum drm_plane_type type,
 170                             const char *name, ...)
 171{
 172        struct drm_mode_config *config = &dev->mode_config;
 173        unsigned int format_modifier_count = 0;
 174        int ret;
 175
 176        ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
 177        if (ret)
 178                return ret;
 179
 180        drm_modeset_lock_init(&plane->mutex);
 181
 182        plane->base.properties = &plane->properties;
 183        plane->dev = dev;
 184        plane->funcs = funcs;
 185        plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
 186                                            GFP_KERNEL);
 187        if (!plane->format_types) {
 188                DRM_DEBUG_KMS("out of memory when allocating plane\n");
 189                drm_mode_object_unregister(dev, &plane->base);
 190                return -ENOMEM;
 191        }
 192
 193        /*
 194         * First driver to need more than 64 formats needs to fix this. Each
 195         * format is encoded as a bit and the current code only supports a u64.
 196         */
 197        if (WARN_ON(format_count > 64))
 198                return -EINVAL;
 199
 200        if (format_modifiers) {
 201                const uint64_t *temp_modifiers = format_modifiers;
 202                while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
 203                        format_modifier_count++;
 204        }
 205
 206        plane->modifier_count = format_modifier_count;
 207        plane->modifiers = kmalloc_array(format_modifier_count,
 208                                         sizeof(format_modifiers[0]),
 209                                         GFP_KERNEL);
 210
 211        if (format_modifier_count && !plane->modifiers) {
 212                DRM_DEBUG_KMS("out of memory when allocating plane\n");
 213                kfree(plane->format_types);
 214                drm_mode_object_unregister(dev, &plane->base);
 215                return -ENOMEM;
 216        }
 217
 218        if (name) {
 219                va_list ap;
 220
 221                va_start(ap, name);
 222                plane->name = kvasprintf(GFP_KERNEL, name, ap);
 223                va_end(ap);
 224        } else {
 225                plane->name = kasprintf(GFP_KERNEL, "plane-%d",
 226                                        drm_num_planes(dev));
 227        }
 228        if (!plane->name) {
 229                kfree(plane->format_types);
 230                kfree(plane->modifiers);
 231                drm_mode_object_unregister(dev, &plane->base);
 232                return -ENOMEM;
 233        }
 234
 235        memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 236        plane->format_count = format_count;
 237        memcpy(plane->modifiers, format_modifiers,
 238               format_modifier_count * sizeof(format_modifiers[0]));
 239        plane->possible_crtcs = possible_crtcs;
 240        plane->type = type;
 241
 242        list_add_tail(&plane->head, &config->plane_list);
 243        plane->index = config->num_total_plane++;
 244        if (plane->type == DRM_PLANE_TYPE_OVERLAY)
 245                config->num_overlay_plane++;
 246
 247        drm_object_attach_property(&plane->base,
 248                                   config->plane_type_property,
 249                                   plane->type);
 250
 251        if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
 252                drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
 253                drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
 254                drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
 255                drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
 256                drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
 257                drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
 258                drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
 259                drm_object_attach_property(&plane->base, config->prop_src_x, 0);
 260                drm_object_attach_property(&plane->base, config->prop_src_y, 0);
 261                drm_object_attach_property(&plane->base, config->prop_src_w, 0);
 262                drm_object_attach_property(&plane->base, config->prop_src_h, 0);
 263        }
 264
 265        if (config->allow_fb_modifiers)
 266                create_in_format_blob(dev, plane);
 267
 268        return 0;
 269}
 270EXPORT_SYMBOL(drm_universal_plane_init);
 271
 272int drm_plane_register_all(struct drm_device *dev)
 273{
 274        struct drm_plane *plane;
 275        int ret = 0;
 276
 277        drm_for_each_plane(plane, dev) {
 278                if (plane->funcs->late_register)
 279                        ret = plane->funcs->late_register(plane);
 280                if (ret)
 281                        return ret;
 282        }
 283
 284        return 0;
 285}
 286
 287void drm_plane_unregister_all(struct drm_device *dev)
 288{
 289        struct drm_plane *plane;
 290
 291        drm_for_each_plane(plane, dev) {
 292                if (plane->funcs->early_unregister)
 293                        plane->funcs->early_unregister(plane);
 294        }
 295}
 296
 297/**
 298 * drm_plane_init - Initialize a legacy plane
 299 * @dev: DRM device
 300 * @plane: plane object to init
 301 * @possible_crtcs: bitmask of possible CRTCs
 302 * @funcs: callbacks for the new plane
 303 * @formats: array of supported formats (DRM_FORMAT\_\*)
 304 * @format_count: number of elements in @formats
 305 * @is_primary: plane type (primary vs overlay)
 306 *
 307 * Legacy API to initialize a DRM plane.
 308 *
 309 * New drivers should call drm_universal_plane_init() instead.
 310 *
 311 * Returns:
 312 * Zero on success, error code on failure.
 313 */
 314int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 315                   uint32_t possible_crtcs,
 316                   const struct drm_plane_funcs *funcs,
 317                   const uint32_t *formats, unsigned int format_count,
 318                   bool is_primary)
 319{
 320        enum drm_plane_type type;
 321
 322        type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 323        return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
 324                                        formats, format_count,
 325                                        NULL, type, NULL);
 326}
 327EXPORT_SYMBOL(drm_plane_init);
 328
 329/**
 330 * drm_plane_cleanup - Clean up the core plane usage
 331 * @plane: plane to cleanup
 332 *
 333 * This function cleans up @plane and removes it from the DRM mode setting
 334 * core. Note that the function does *not* free the plane structure itself,
 335 * this is the responsibility of the caller.
 336 */
 337void drm_plane_cleanup(struct drm_plane *plane)
 338{
 339        struct drm_device *dev = plane->dev;
 340
 341        drm_modeset_lock_fini(&plane->mutex);
 342
 343        kfree(plane->format_types);
 344        kfree(plane->modifiers);
 345        drm_mode_object_unregister(dev, &plane->base);
 346
 347        BUG_ON(list_empty(&plane->head));
 348
 349        /* Note that the plane_list is considered to be static; should we
 350         * remove the drm_plane at runtime we would have to decrement all
 351         * the indices on the drm_plane after us in the plane_list.
 352         */
 353
 354        list_del(&plane->head);
 355        dev->mode_config.num_total_plane--;
 356        if (plane->type == DRM_PLANE_TYPE_OVERLAY)
 357                dev->mode_config.num_overlay_plane--;
 358
 359        WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
 360        if (plane->state && plane->funcs->atomic_destroy_state)
 361                plane->funcs->atomic_destroy_state(plane, plane->state);
 362
 363        kfree(plane->name);
 364
 365        memset(plane, 0, sizeof(*plane));
 366}
 367EXPORT_SYMBOL(drm_plane_cleanup);
 368
 369/**
 370 * drm_plane_from_index - find the registered plane at an index
 371 * @dev: DRM device
 372 * @idx: index of registered plane to find for
 373 *
 374 * Given a plane index, return the registered plane from DRM device's
 375 * list of planes with matching index. This is the inverse of drm_plane_index().
 376 */
 377struct drm_plane *
 378drm_plane_from_index(struct drm_device *dev, int idx)
 379{
 380        struct drm_plane *plane;
 381
 382        drm_for_each_plane(plane, dev)
 383                if (idx == plane->index)
 384                        return plane;
 385
 386        return NULL;
 387}
 388EXPORT_SYMBOL(drm_plane_from_index);
 389
 390/**
 391 * drm_plane_force_disable - Forcibly disable a plane
 392 * @plane: plane to disable
 393 *
 394 * Forces the plane to be disabled.
 395 *
 396 * Used when the plane's current framebuffer is destroyed,
 397 * and when restoring fbdev mode.
 398 *
 399 * Note that this function is not suitable for atomic drivers, since it doesn't
 400 * wire through the lock acquisition context properly and hence can't handle
 401 * retries or driver private locks. You probably want to use
 402 * drm_atomic_helper_disable_plane() or
 403 * drm_atomic_helper_disable_planes_on_crtc() instead.
 404 */
 405void drm_plane_force_disable(struct drm_plane *plane)
 406{
 407        int ret;
 408
 409        if (!plane->fb)
 410                return;
 411
 412        WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
 413
 414        plane->old_fb = plane->fb;
 415        ret = plane->funcs->disable_plane(plane, NULL);
 416        if (ret) {
 417                DRM_ERROR("failed to disable plane with busy fb\n");
 418                plane->old_fb = NULL;
 419                return;
 420        }
 421        /* disconnect the plane from the fb and crtc: */
 422        drm_framebuffer_put(plane->old_fb);
 423        plane->old_fb = NULL;
 424        plane->fb = NULL;
 425        plane->crtc = NULL;
 426}
 427EXPORT_SYMBOL(drm_plane_force_disable);
 428
 429/**
 430 * drm_mode_plane_set_obj_prop - set the value of a property
 431 * @plane: drm plane object to set property value for
 432 * @property: property to set
 433 * @value: value the property should be set to
 434 *
 435 * This functions sets a given property on a given plane object. This function
 436 * calls the driver's ->set_property callback and changes the software state of
 437 * the property if the callback succeeds.
 438 *
 439 * Returns:
 440 * Zero on success, error code on failure.
 441 */
 442int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
 443                                struct drm_property *property,
 444                                uint64_t value)
 445{
 446        int ret = -EINVAL;
 447        struct drm_mode_object *obj = &plane->base;
 448
 449        if (plane->funcs->set_property)
 450                ret = plane->funcs->set_property(plane, property, value);
 451        if (!ret)
 452                drm_object_property_set_value(obj, property, value);
 453
 454        return ret;
 455}
 456EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
 457
 458int drm_mode_getplane_res(struct drm_device *dev, void *data,
 459                          struct drm_file *file_priv)
 460{
 461        struct drm_mode_get_plane_res *plane_resp = data;
 462        struct drm_mode_config *config;
 463        struct drm_plane *plane;
 464        uint32_t __user *plane_ptr;
 465        int copied = 0;
 466        unsigned num_planes;
 467
 468        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 469                return -EINVAL;
 470
 471        config = &dev->mode_config;
 472
 473        if (file_priv->universal_planes)
 474                num_planes = config->num_total_plane;
 475        else
 476                num_planes = config->num_overlay_plane;
 477
 478        /*
 479         * This ioctl is called twice, once to determine how much space is
 480         * needed, and the 2nd time to fill it.
 481         */
 482        if (num_planes &&
 483            (plane_resp->count_planes >= num_planes)) {
 484                plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
 485
 486                /* Plane lists are invariant, no locking needed. */
 487                drm_for_each_plane(plane, dev) {
 488                        /*
 489                         * Unless userspace set the 'universal planes'
 490                         * capability bit, only advertise overlays.
 491                         */
 492                        if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
 493                            !file_priv->universal_planes)
 494                                continue;
 495
 496                        if (put_user(plane->base.id, plane_ptr + copied))
 497                                return -EFAULT;
 498                        copied++;
 499                }
 500        }
 501        plane_resp->count_planes = num_planes;
 502
 503        return 0;
 504}
 505
 506int drm_mode_getplane(struct drm_device *dev, void *data,
 507                      struct drm_file *file_priv)
 508{
 509        struct drm_mode_get_plane *plane_resp = data;
 510        struct drm_plane *plane;
 511        uint32_t __user *format_ptr;
 512
 513        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 514                return -EINVAL;
 515
 516        plane = drm_plane_find(dev, plane_resp->plane_id);
 517        if (!plane)
 518                return -ENOENT;
 519
 520        drm_modeset_lock(&plane->mutex, NULL);
 521        if (plane->state && plane->state->crtc)
 522                plane_resp->crtc_id = plane->state->crtc->base.id;
 523        else if (!plane->state && plane->crtc)
 524                plane_resp->crtc_id = plane->crtc->base.id;
 525        else
 526                plane_resp->crtc_id = 0;
 527
 528        if (plane->state && plane->state->fb)
 529                plane_resp->fb_id = plane->state->fb->base.id;
 530        else if (!plane->state && plane->fb)
 531                plane_resp->fb_id = plane->fb->base.id;
 532        else
 533                plane_resp->fb_id = 0;
 534        drm_modeset_unlock(&plane->mutex);
 535
 536        plane_resp->plane_id = plane->base.id;
 537        plane_resp->possible_crtcs = plane->possible_crtcs;
 538        plane_resp->gamma_size = 0;
 539
 540        /*
 541         * This ioctl is called twice, once to determine how much space is
 542         * needed, and the 2nd time to fill it.
 543         */
 544        if (plane->format_count &&
 545            (plane_resp->count_format_types >= plane->format_count)) {
 546                format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
 547                if (copy_to_user(format_ptr,
 548                                 plane->format_types,
 549                                 sizeof(uint32_t) * plane->format_count)) {
 550                        return -EFAULT;
 551                }
 552        }
 553        plane_resp->count_format_types = plane->format_count;
 554
 555        return 0;
 556}
 557
 558int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
 559{
 560        unsigned int i;
 561
 562        for (i = 0; i < plane->format_count; i++) {
 563                if (format == plane->format_types[i])
 564                        return 0;
 565        }
 566
 567        return -EINVAL;
 568}
 569
 570/*
 571 * setplane_internal - setplane handler for internal callers
 572 *
 573 * Note that we assume an extra reference has already been taken on fb.  If the
 574 * update fails, this reference will be dropped before return; if it succeeds,
 575 * the previous framebuffer (if any) will be unreferenced instead.
 576 *
 577 * src_{x,y,w,h} are provided in 16.16 fixed point format
 578 */
 579static int __setplane_internal(struct drm_plane *plane,
 580                               struct drm_crtc *crtc,
 581                               struct drm_framebuffer *fb,
 582                               int32_t crtc_x, int32_t crtc_y,
 583                               uint32_t crtc_w, uint32_t crtc_h,
 584                               /* src_{x,y,w,h} values are 16.16 fixed point */
 585                               uint32_t src_x, uint32_t src_y,
 586                               uint32_t src_w, uint32_t src_h,
 587                               struct drm_modeset_acquire_ctx *ctx)
 588{
 589        int ret = 0;
 590
 591        /* No fb means shut it down */
 592        if (!fb) {
 593                plane->old_fb = plane->fb;
 594                ret = plane->funcs->disable_plane(plane, ctx);
 595                if (!ret) {
 596                        plane->crtc = NULL;
 597                        plane->fb = NULL;
 598                } else {
 599                        plane->old_fb = NULL;
 600                }
 601                goto out;
 602        }
 603
 604        /* Check whether this plane is usable on this CRTC */
 605        if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
 606                DRM_DEBUG_KMS("Invalid crtc for plane\n");
 607                ret = -EINVAL;
 608                goto out;
 609        }
 610
 611        /* Check whether this plane supports the fb pixel format. */
 612        ret = drm_plane_check_pixel_format(plane, fb->format->format);
 613        if (ret) {
 614                struct drm_format_name_buf format_name;
 615                DRM_DEBUG_KMS("Invalid pixel format %s\n",
 616                              drm_get_format_name(fb->format->format,
 617                                                  &format_name));
 618                goto out;
 619        }
 620
 621        /* Give drivers some help against integer overflows */
 622        if (crtc_w > INT_MAX ||
 623            crtc_x > INT_MAX - (int32_t) crtc_w ||
 624            crtc_h > INT_MAX ||
 625            crtc_y > INT_MAX - (int32_t) crtc_h) {
 626                DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
 627                              crtc_w, crtc_h, crtc_x, crtc_y);
 628                ret = -ERANGE;
 629                goto out;
 630        }
 631
 632        ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
 633        if (ret)
 634                goto out;
 635
 636        plane->old_fb = plane->fb;
 637        ret = plane->funcs->update_plane(plane, crtc, fb,
 638                                         crtc_x, crtc_y, crtc_w, crtc_h,
 639                                         src_x, src_y, src_w, src_h, ctx);
 640        if (!ret) {
 641                plane->crtc = crtc;
 642                plane->fb = fb;
 643                fb = NULL;
 644        } else {
 645                plane->old_fb = NULL;
 646        }
 647
 648out:
 649        if (fb)
 650                drm_framebuffer_put(fb);
 651        if (plane->old_fb)
 652                drm_framebuffer_put(plane->old_fb);
 653        plane->old_fb = NULL;
 654
 655        return ret;
 656}
 657
 658static int setplane_internal(struct drm_plane *plane,
 659                             struct drm_crtc *crtc,
 660                             struct drm_framebuffer *fb,
 661                             int32_t crtc_x, int32_t crtc_y,
 662                             uint32_t crtc_w, uint32_t crtc_h,
 663                             /* src_{x,y,w,h} values are 16.16 fixed point */
 664                             uint32_t src_x, uint32_t src_y,
 665                             uint32_t src_w, uint32_t src_h)
 666{
 667        struct drm_modeset_acquire_ctx ctx;
 668        int ret;
 669
 670        drm_modeset_acquire_init(&ctx, 0);
 671retry:
 672        ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
 673        if (ret)
 674                goto fail;
 675        ret = __setplane_internal(plane, crtc, fb,
 676                                  crtc_x, crtc_y, crtc_w, crtc_h,
 677                                  src_x, src_y, src_w, src_h, &ctx);
 678
 679fail:
 680        if (ret == -EDEADLK) {
 681                drm_modeset_backoff(&ctx);
 682                goto retry;
 683        }
 684        drm_modeset_drop_locks(&ctx);
 685        drm_modeset_acquire_fini(&ctx);
 686
 687        return ret;
 688}
 689
 690int drm_mode_setplane(struct drm_device *dev, void *data,
 691                      struct drm_file *file_priv)
 692{
 693        struct drm_mode_set_plane *plane_req = data;
 694        struct drm_plane *plane;
 695        struct drm_crtc *crtc = NULL;
 696        struct drm_framebuffer *fb = NULL;
 697
 698        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 699                return -EINVAL;
 700
 701        /*
 702         * First, find the plane, crtc, and fb objects.  If not available,
 703         * we don't bother to call the driver.
 704         */
 705        plane = drm_plane_find(dev, plane_req->plane_id);
 706        if (!plane) {
 707                DRM_DEBUG_KMS("Unknown plane ID %d\n",
 708                              plane_req->plane_id);
 709                return -ENOENT;
 710        }
 711
 712        if (plane_req->fb_id) {
 713                fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
 714                if (!fb) {
 715                        DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
 716                                      plane_req->fb_id);
 717                        return -ENOENT;
 718                }
 719
 720                crtc = drm_crtc_find(dev, plane_req->crtc_id);
 721                if (!crtc) {
 722                        drm_framebuffer_put(fb);
 723                        DRM_DEBUG_KMS("Unknown crtc ID %d\n",
 724                                      plane_req->crtc_id);
 725                        return -ENOENT;
 726                }
 727        }
 728
 729        /*
 730         * setplane_internal will take care of deref'ing either the old or new
 731         * framebuffer depending on success.
 732         */
 733        return setplane_internal(plane, crtc, fb,
 734                                 plane_req->crtc_x, plane_req->crtc_y,
 735                                 plane_req->crtc_w, plane_req->crtc_h,
 736                                 plane_req->src_x, plane_req->src_y,
 737                                 plane_req->src_w, plane_req->src_h);
 738}
 739
 740static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 741                                     struct drm_mode_cursor2 *req,
 742                                     struct drm_file *file_priv,
 743                                     struct drm_modeset_acquire_ctx *ctx)
 744{
 745        struct drm_device *dev = crtc->dev;
 746        struct drm_framebuffer *fb = NULL;
 747        struct drm_mode_fb_cmd2 fbreq = {
 748                .width = req->width,
 749                .height = req->height,
 750                .pixel_format = DRM_FORMAT_ARGB8888,
 751                .pitches = { req->width * 4 },
 752                .handles = { req->handle },
 753        };
 754        int32_t crtc_x, crtc_y;
 755        uint32_t crtc_w = 0, crtc_h = 0;
 756        uint32_t src_w = 0, src_h = 0;
 757        int ret = 0;
 758
 759        BUG_ON(!crtc->cursor);
 760        WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
 761
 762        /*
 763         * Obtain fb we'll be using (either new or existing) and take an extra
 764         * reference to it if fb != null.  setplane will take care of dropping
 765         * the reference if the plane update fails.
 766         */
 767        if (req->flags & DRM_MODE_CURSOR_BO) {
 768                if (req->handle) {
 769                        fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
 770                        if (IS_ERR(fb)) {
 771                                DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
 772                                return PTR_ERR(fb);
 773                        }
 774                        fb->hot_x = req->hot_x;
 775                        fb->hot_y = req->hot_y;
 776                } else {
 777                        fb = NULL;
 778                }
 779        } else {
 780                fb = crtc->cursor->fb;
 781                if (fb)
 782                        drm_framebuffer_get(fb);
 783        }
 784
 785        if (req->flags & DRM_MODE_CURSOR_MOVE) {
 786                crtc_x = req->x;
 787                crtc_y = req->y;
 788        } else {
 789                crtc_x = crtc->cursor_x;
 790                crtc_y = crtc->cursor_y;
 791        }
 792
 793        if (fb) {
 794                crtc_w = fb->width;
 795                crtc_h = fb->height;
 796                src_w = fb->width << 16;
 797                src_h = fb->height << 16;
 798        }
 799
 800        /*
 801         * setplane_internal will take care of deref'ing either the old or new
 802         * framebuffer depending on success.
 803         */
 804        ret = __setplane_internal(crtc->cursor, crtc, fb,
 805                                crtc_x, crtc_y, crtc_w, crtc_h,
 806                                0, 0, src_w, src_h, ctx);
 807
 808        /* Update successful; save new cursor position, if necessary */
 809        if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
 810                crtc->cursor_x = req->x;
 811                crtc->cursor_y = req->y;
 812        }
 813
 814        return ret;
 815}
 816
 817static int drm_mode_cursor_common(struct drm_device *dev,
 818                                  struct drm_mode_cursor2 *req,
 819                                  struct drm_file *file_priv)
 820{
 821        struct drm_crtc *crtc;
 822        struct drm_modeset_acquire_ctx ctx;
 823        int ret = 0;
 824
 825        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 826                return -EINVAL;
 827
 828        if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
 829                return -EINVAL;
 830
 831        crtc = drm_crtc_find(dev, req->crtc_id);
 832        if (!crtc) {
 833                DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
 834                return -ENOENT;
 835        }
 836
 837        drm_modeset_acquire_init(&ctx, 0);
 838retry:
 839        ret = drm_modeset_lock(&crtc->mutex, &ctx);
 840        if (ret)
 841                goto out;
 842        /*
 843         * If this crtc has a universal cursor plane, call that plane's update
 844         * handler rather than using legacy cursor handlers.
 845         */
 846        if (crtc->cursor) {
 847                ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
 848                if (ret)
 849                        goto out;
 850
 851                ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
 852                goto out;
 853        }
 854
 855        if (req->flags & DRM_MODE_CURSOR_BO) {
 856                if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
 857                        ret = -ENXIO;
 858                        goto out;
 859                }
 860                /* Turns off the cursor if handle is 0 */
 861                if (crtc->funcs->cursor_set2)
 862                        ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
 863                                                      req->width, req->height, req->hot_x, req->hot_y);
 864                else
 865                        ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
 866                                                      req->width, req->height);
 867        }
 868
 869        if (req->flags & DRM_MODE_CURSOR_MOVE) {
 870                if (crtc->funcs->cursor_move) {
 871                        ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
 872                } else {
 873                        ret = -EFAULT;
 874                        goto out;
 875                }
 876        }
 877out:
 878        if (ret == -EDEADLK) {
 879                drm_modeset_backoff(&ctx);
 880                goto retry;
 881        }
 882
 883        drm_modeset_drop_locks(&ctx);
 884        drm_modeset_acquire_fini(&ctx);
 885
 886        return ret;
 887
 888}
 889
 890
 891int drm_mode_cursor_ioctl(struct drm_device *dev,
 892                          void *data, struct drm_file *file_priv)
 893{
 894        struct drm_mode_cursor *req = data;
 895        struct drm_mode_cursor2 new_req;
 896
 897        memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
 898        new_req.hot_x = new_req.hot_y = 0;
 899
 900        return drm_mode_cursor_common(dev, &new_req, file_priv);
 901}
 902
 903/*
 904 * Set the cursor configuration based on user request. This implements the 2nd
 905 * version of the cursor ioctl, which allows userspace to additionally specify
 906 * the hotspot of the pointer.
 907 */
 908int drm_mode_cursor2_ioctl(struct drm_device *dev,
 909                           void *data, struct drm_file *file_priv)
 910{
 911        struct drm_mode_cursor2 *req = data;
 912
 913        return drm_mode_cursor_common(dev, req, file_priv);
 914}
 915
 916int drm_mode_page_flip_ioctl(struct drm_device *dev,
 917                             void *data, struct drm_file *file_priv)
 918{
 919        struct drm_mode_crtc_page_flip_target *page_flip = data;
 920        struct drm_crtc *crtc;
 921        struct drm_framebuffer *fb = NULL;
 922        struct drm_pending_vblank_event *e = NULL;
 923        u32 target_vblank = page_flip->sequence;
 924        struct drm_modeset_acquire_ctx ctx;
 925        int ret = -EINVAL;
 926
 927        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 928                return -EINVAL;
 929
 930        if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
 931                return -EINVAL;
 932
 933        if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
 934                return -EINVAL;
 935
 936        /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
 937         * can be specified
 938         */
 939        if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
 940                return -EINVAL;
 941
 942        if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
 943                return -EINVAL;
 944
 945        crtc = drm_crtc_find(dev, page_flip->crtc_id);
 946        if (!crtc)
 947                return -ENOENT;
 948
 949        if (crtc->funcs->page_flip_target) {
 950                u32 current_vblank;
 951                int r;
 952
 953                r = drm_crtc_vblank_get(crtc);
 954                if (r)
 955                        return r;
 956
 957                current_vblank = drm_crtc_vblank_count(crtc);
 958
 959                switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
 960                case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
 961                        if ((int)(target_vblank - current_vblank) > 1) {
 962                                DRM_DEBUG("Invalid absolute flip target %u, "
 963                                          "must be <= %u\n", target_vblank,
 964                                          current_vblank + 1);
 965                                drm_crtc_vblank_put(crtc);
 966                                return -EINVAL;
 967                        }
 968                        break;
 969                case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
 970                        if (target_vblank != 0 && target_vblank != 1) {
 971                                DRM_DEBUG("Invalid relative flip target %u, "
 972                                          "must be 0 or 1\n", target_vblank);
 973                                drm_crtc_vblank_put(crtc);
 974                                return -EINVAL;
 975                        }
 976                        target_vblank += current_vblank;
 977                        break;
 978                default:
 979                        target_vblank = current_vblank +
 980                                !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
 981                        break;
 982                }
 983        } else if (crtc->funcs->page_flip == NULL ||
 984                   (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
 985                return -EINVAL;
 986        }
 987
 988        drm_modeset_acquire_init(&ctx, 0);
 989retry:
 990        ret = drm_modeset_lock(&crtc->mutex, &ctx);
 991        if (ret)
 992                goto out;
 993        ret = drm_modeset_lock(&crtc->primary->mutex, &ctx);
 994        if (ret)
 995                goto out;
 996
 997        if (crtc->primary->fb == NULL) {
 998                /* The framebuffer is currently unbound, presumably
 999                 * due to a hotplug event, that userspace has not
1000                 * yet discovered.
1001                 */
1002                ret = -EBUSY;
1003                goto out;
1004        }
1005
1006        fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
1007        if (!fb) {
1008                ret = -ENOENT;
1009                goto out;
1010        }
1011
1012        if (crtc->state) {
1013                const struct drm_plane_state *state = crtc->primary->state;
1014
1015                ret = drm_framebuffer_check_src_coords(state->src_x,
1016                                                       state->src_y,
1017                                                       state->src_w,
1018                                                       state->src_h,
1019                                                       fb);
1020        } else {
1021                ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
1022        }
1023        if (ret)
1024                goto out;
1025
1026        if (crtc->primary->fb->format != fb->format) {
1027                DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
1028                ret = -EINVAL;
1029                goto out;
1030        }
1031
1032        if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1033                e = kzalloc(sizeof *e, GFP_KERNEL);
1034                if (!e) {
1035                        ret = -ENOMEM;
1036                        goto out;
1037                }
1038                e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
1039                e->event.base.length = sizeof(e->event);
1040                e->event.user_data = page_flip->user_data;
1041                ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
1042                if (ret) {
1043                        kfree(e);
1044                        e = NULL;
1045                        goto out;
1046                }
1047        }
1048
1049        crtc->primary->old_fb = crtc->primary->fb;
1050        if (crtc->funcs->page_flip_target)
1051                ret = crtc->funcs->page_flip_target(crtc, fb, e,
1052                                                    page_flip->flags,
1053                                                    target_vblank,
1054                                                    &ctx);
1055        else
1056                ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
1057                                             &ctx);
1058        if (ret) {
1059                if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
1060                        drm_event_cancel_free(dev, &e->base);
1061                /* Keep the old fb, don't unref it. */
1062                crtc->primary->old_fb = NULL;
1063        } else {
1064                crtc->primary->fb = fb;
1065                /* Unref only the old framebuffer. */
1066                fb = NULL;
1067        }
1068
1069out:
1070        if (fb)
1071                drm_framebuffer_put(fb);
1072        if (crtc->primary->old_fb)
1073                drm_framebuffer_put(crtc->primary->old_fb);
1074        crtc->primary->old_fb = NULL;
1075
1076        if (ret == -EDEADLK) {
1077                drm_modeset_backoff(&ctx);
1078                goto retry;
1079        }
1080
1081        drm_modeset_drop_locks(&ctx);
1082        drm_modeset_acquire_fini(&ctx);
1083
1084        if (ret && crtc->funcs->page_flip_target)
1085                drm_crtc_vblank_put(crtc);
1086
1087        return ret;
1088}
1089