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