Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016 Intel Corporation
0003  *
0004  * Permission to use, copy, modify, distribute, and sell this software and its
0005  * documentation for any purpose is hereby granted without fee, provided that
0006  * the above copyright notice appear in all copies and that both that copyright
0007  * notice and this permission notice appear in supporting documentation, and
0008  * that the name of the copyright holders not be used in advertising or
0009  * publicity pertaining to distribution of the software without specific,
0010  * written prior permission.  The copyright holders make no representations
0011  * about the suitability of this software for any purpose.  It is provided "as
0012  * is" without express or implied warranty.
0013  *
0014  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0015  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
0016  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0017  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
0018  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
0019  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
0020  * OF THIS SOFTWARE.
0021  */
0022 
0023 #include <linux/slab.h>
0024 #include <linux/uaccess.h>
0025 
0026 #include <drm/drm_plane.h>
0027 #include <drm/drm_drv.h>
0028 #include <drm/drm_print.h>
0029 #include <drm/drm_framebuffer.h>
0030 #include <drm/drm_file.h>
0031 #include <drm/drm_crtc.h>
0032 #include <drm/drm_fourcc.h>
0033 #include <drm/drm_managed.h>
0034 #include <drm/drm_vblank.h>
0035 
0036 #include "drm_crtc_internal.h"
0037 
0038 /**
0039  * DOC: overview
0040  *
0041  * A plane represents an image source that can be blended with or overlaid on
0042  * top of a CRTC during the scanout process. Planes take their input data from a
0043  * &drm_framebuffer object. The plane itself specifies the cropping and scaling
0044  * of that image, and where it is placed on the visible area of a display
0045  * pipeline, represented by &drm_crtc. A plane can also have additional
0046  * properties that specify how the pixels are positioned and blended, like
0047  * rotation or Z-position. All these properties are stored in &drm_plane_state.
0048  *
0049  * To create a plane, a KMS drivers allocates and zeroes an instances of
0050  * &struct drm_plane (possibly as part of a larger structure) and registers it
0051  * with a call to drm_universal_plane_init().
0052  *
0053  * Each plane has a type, see enum drm_plane_type. A plane can be compatible
0054  * with multiple CRTCs, see &drm_plane.possible_crtcs.
0055  *
0056  * Each CRTC must have a unique primary plane userspace can attach to enable
0057  * the CRTC. In other words, userspace must be able to attach a different
0058  * primary plane to each CRTC at the same time. Primary planes can still be
0059  * compatible with multiple CRTCs. There must be exactly as many primary planes
0060  * as there are CRTCs.
0061  *
0062  * Legacy uAPI doesn't expose the primary and cursor planes directly. DRM core
0063  * relies on the driver to set the primary and optionally the cursor plane used
0064  * for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). All
0065  * drivers must provide one primary plane per CRTC to avoid surprising legacy
0066  * userspace too much.
0067  */
0068 
0069 /**
0070  * DOC: standard plane properties
0071  *
0072  * DRM planes have a few standardized properties:
0073  *
0074  * type:
0075  *     Immutable property describing the type of the plane.
0076  *
0077  *     For user-space which has enabled the &DRM_CLIENT_CAP_ATOMIC capability,
0078  *     the plane type is just a hint and is mostly superseded by atomic
0079  *     test-only commits. The type hint can still be used to come up more
0080  *     easily with a plane configuration accepted by the driver.
0081  *
0082  *     The value of this property can be one of the following:
0083  *
0084  *     "Primary":
0085  *         To light up a CRTC, attaching a primary plane is the most likely to
0086  *         work if it covers the whole CRTC and doesn't have scaling or
0087  *         cropping set up.
0088  *
0089  *         Drivers may support more features for the primary plane, user-space
0090  *         can find out with test-only atomic commits.
0091  *
0092  *         Some primary planes are implicitly used by the kernel in the legacy
0093  *         IOCTLs &DRM_IOCTL_MODE_SETCRTC and &DRM_IOCTL_MODE_PAGE_FLIP.
0094  *         Therefore user-space must not mix explicit usage of any primary
0095  *         plane (e.g. through an atomic commit) with these legacy IOCTLs.
0096  *
0097  *     "Cursor":
0098  *         To enable this plane, using a framebuffer configured without scaling
0099  *         or cropping and with the following properties is the most likely to
0100  *         work:
0101  *
0102  *         - If the driver provides the capabilities &DRM_CAP_CURSOR_WIDTH and
0103  *           &DRM_CAP_CURSOR_HEIGHT, create the framebuffer with this size.
0104  *           Otherwise, create a framebuffer with the size 64x64.
0105  *         - If the driver doesn't support modifiers, create a framebuffer with
0106  *           a linear layout. Otherwise, use the IN_FORMATS plane property.
0107  *
0108  *         Drivers may support more features for the cursor plane, user-space
0109  *         can find out with test-only atomic commits.
0110  *
0111  *         Some cursor planes are implicitly used by the kernel in the legacy
0112  *         IOCTLs &DRM_IOCTL_MODE_CURSOR and &DRM_IOCTL_MODE_CURSOR2.
0113  *         Therefore user-space must not mix explicit usage of any cursor
0114  *         plane (e.g. through an atomic commit) with these legacy IOCTLs.
0115  *
0116  *         Some drivers may support cursors even if no cursor plane is exposed.
0117  *         In this case, the legacy cursor IOCTLs can be used to configure the
0118  *         cursor.
0119  *
0120  *     "Overlay":
0121  *         Neither primary nor cursor.
0122  *
0123  *         Overlay planes are the only planes exposed when the
0124  *         &DRM_CLIENT_CAP_UNIVERSAL_PLANES capability is disabled.
0125  *
0126  * IN_FORMATS:
0127  *     Blob property which contains the set of buffer format and modifier
0128  *     pairs supported by this plane. The blob is a struct
0129  *     drm_format_modifier_blob. Without this property the plane doesn't
0130  *     support buffers with modifiers. Userspace cannot change this property.
0131  *
0132  *     Note that userspace can check the &DRM_CAP_ADDFB2_MODIFIERS driver
0133  *     capability for general modifier support. If this flag is set then every
0134  *     plane will have the IN_FORMATS property, even when it only supports
0135  *     DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have been
0136  *     various bugs in this area with inconsistencies between the capability
0137  *     flag and per-plane properties.
0138  */
0139 
0140 static unsigned int drm_num_planes(struct drm_device *dev)
0141 {
0142     unsigned int num = 0;
0143     struct drm_plane *tmp;
0144 
0145     drm_for_each_plane(tmp, dev) {
0146         num++;
0147     }
0148 
0149     return num;
0150 }
0151 
0152 static inline u32 *
0153 formats_ptr(struct drm_format_modifier_blob *blob)
0154 {
0155     return (u32 *)(((char *)blob) + blob->formats_offset);
0156 }
0157 
0158 static inline struct drm_format_modifier *
0159 modifiers_ptr(struct drm_format_modifier_blob *blob)
0160 {
0161     return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
0162 }
0163 
0164 static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane)
0165 {
0166     const struct drm_mode_config *config = &dev->mode_config;
0167     struct drm_property_blob *blob;
0168     struct drm_format_modifier *mod;
0169     size_t blob_size, formats_size, modifiers_size;
0170     struct drm_format_modifier_blob *blob_data;
0171     unsigned int i, j;
0172 
0173     formats_size = sizeof(__u32) * plane->format_count;
0174     if (WARN_ON(!formats_size)) {
0175         /* 0 formats are never expected */
0176         return 0;
0177     }
0178 
0179     modifiers_size =
0180         sizeof(struct drm_format_modifier) * plane->modifier_count;
0181 
0182     blob_size = sizeof(struct drm_format_modifier_blob);
0183     /* Modifiers offset is a pointer to a struct with a 64 bit field so it
0184      * should be naturally aligned to 8B.
0185      */
0186     BUILD_BUG_ON(sizeof(struct drm_format_modifier_blob) % 8);
0187     blob_size += ALIGN(formats_size, 8);
0188     blob_size += modifiers_size;
0189 
0190     blob = drm_property_create_blob(dev, blob_size, NULL);
0191     if (IS_ERR(blob))
0192         return -1;
0193 
0194     blob_data = blob->data;
0195     blob_data->version = FORMAT_BLOB_CURRENT;
0196     blob_data->count_formats = plane->format_count;
0197     blob_data->formats_offset = sizeof(struct drm_format_modifier_blob);
0198     blob_data->count_modifiers = plane->modifier_count;
0199 
0200     blob_data->modifiers_offset =
0201         ALIGN(blob_data->formats_offset + formats_size, 8);
0202 
0203     memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
0204 
0205     mod = modifiers_ptr(blob_data);
0206     for (i = 0; i < plane->modifier_count; i++) {
0207         for (j = 0; j < plane->format_count; j++) {
0208             if (!plane->funcs->format_mod_supported ||
0209                 plane->funcs->format_mod_supported(plane,
0210                                    plane->format_types[j],
0211                                    plane->modifiers[i])) {
0212                 mod->formats |= 1ULL << j;
0213             }
0214         }
0215 
0216         mod->modifier = plane->modifiers[i];
0217         mod->offset = 0;
0218         mod->pad = 0;
0219         mod++;
0220     }
0221 
0222     drm_object_attach_property(&plane->base, config->modifiers_property,
0223                    blob->base.id);
0224 
0225     return 0;
0226 }
0227 
0228 __printf(9, 0)
0229 static int __drm_universal_plane_init(struct drm_device *dev,
0230                       struct drm_plane *plane,
0231                       uint32_t possible_crtcs,
0232                       const struct drm_plane_funcs *funcs,
0233                       const uint32_t *formats,
0234                       unsigned int format_count,
0235                       const uint64_t *format_modifiers,
0236                       enum drm_plane_type type,
0237                       const char *name, va_list ap)
0238 {
0239     struct drm_mode_config *config = &dev->mode_config;
0240     static const uint64_t default_modifiers[] = {
0241         DRM_FORMAT_MOD_LINEAR,
0242     };
0243     unsigned int format_modifier_count = 0;
0244     int ret;
0245 
0246     /* plane index is used with 32bit bitmasks */
0247     if (WARN_ON(config->num_total_plane >= 32))
0248         return -EINVAL;
0249 
0250     /*
0251      * First driver to need more than 64 formats needs to fix this. Each
0252      * format is encoded as a bit and the current code only supports a u64.
0253      */
0254     if (WARN_ON(format_count > 64))
0255         return -EINVAL;
0256 
0257     WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
0258         (!funcs->atomic_destroy_state ||
0259          !funcs->atomic_duplicate_state));
0260 
0261     ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
0262     if (ret)
0263         return ret;
0264 
0265     drm_modeset_lock_init(&plane->mutex);
0266 
0267     plane->base.properties = &plane->properties;
0268     plane->dev = dev;
0269     plane->funcs = funcs;
0270     plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
0271                         GFP_KERNEL);
0272     if (!plane->format_types) {
0273         DRM_DEBUG_KMS("out of memory when allocating plane\n");
0274         drm_mode_object_unregister(dev, &plane->base);
0275         return -ENOMEM;
0276     }
0277 
0278     if (format_modifiers) {
0279         const uint64_t *temp_modifiers = format_modifiers;
0280 
0281         while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
0282             format_modifier_count++;
0283     } else {
0284         if (!dev->mode_config.fb_modifiers_not_supported) {
0285             format_modifiers = default_modifiers;
0286             format_modifier_count = ARRAY_SIZE(default_modifiers);
0287         }
0288     }
0289 
0290     /* autoset the cap and check for consistency across all planes */
0291     drm_WARN_ON(dev, config->fb_modifiers_not_supported &&
0292                 format_modifier_count);
0293 
0294     plane->modifier_count = format_modifier_count;
0295     plane->modifiers = kmalloc_array(format_modifier_count,
0296                      sizeof(format_modifiers[0]),
0297                      GFP_KERNEL);
0298 
0299     if (format_modifier_count && !plane->modifiers) {
0300         DRM_DEBUG_KMS("out of memory when allocating plane\n");
0301         kfree(plane->format_types);
0302         drm_mode_object_unregister(dev, &plane->base);
0303         return -ENOMEM;
0304     }
0305 
0306     if (name) {
0307         plane->name = kvasprintf(GFP_KERNEL, name, ap);
0308     } else {
0309         plane->name = kasprintf(GFP_KERNEL, "plane-%d",
0310                     drm_num_planes(dev));
0311     }
0312     if (!plane->name) {
0313         kfree(plane->format_types);
0314         kfree(plane->modifiers);
0315         drm_mode_object_unregister(dev, &plane->base);
0316         return -ENOMEM;
0317     }
0318 
0319     memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
0320     plane->format_count = format_count;
0321     memcpy(plane->modifiers, format_modifiers,
0322            format_modifier_count * sizeof(format_modifiers[0]));
0323     plane->possible_crtcs = possible_crtcs;
0324     plane->type = type;
0325 
0326     list_add_tail(&plane->head, &config->plane_list);
0327     plane->index = config->num_total_plane++;
0328 
0329     drm_object_attach_property(&plane->base,
0330                    config->plane_type_property,
0331                    plane->type);
0332 
0333     if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
0334         drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
0335         drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
0336         drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
0337         drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
0338         drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
0339         drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
0340         drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
0341         drm_object_attach_property(&plane->base, config->prop_src_x, 0);
0342         drm_object_attach_property(&plane->base, config->prop_src_y, 0);
0343         drm_object_attach_property(&plane->base, config->prop_src_w, 0);
0344         drm_object_attach_property(&plane->base, config->prop_src_h, 0);
0345     }
0346 
0347     if (format_modifier_count)
0348         create_in_format_blob(dev, plane);
0349 
0350     return 0;
0351 }
0352 
0353 /**
0354  * drm_universal_plane_init - Initialize a new universal plane object
0355  * @dev: DRM device
0356  * @plane: plane object to init
0357  * @possible_crtcs: bitmask of possible CRTCs
0358  * @funcs: callbacks for the new plane
0359  * @formats: array of supported formats (DRM_FORMAT\_\*)
0360  * @format_count: number of elements in @formats
0361  * @format_modifiers: array of struct drm_format modifiers terminated by
0362  *                    DRM_FORMAT_MOD_INVALID
0363  * @type: type of plane (overlay, primary, cursor)
0364  * @name: printf style format string for the plane name, or NULL for default name
0365  *
0366  * Initializes a plane object of type @type. The &drm_plane_funcs.destroy hook
0367  * should call drm_plane_cleanup() and kfree() the plane structure. The plane
0368  * structure should not be allocated with devm_kzalloc().
0369  *
0370  * Note: consider using drmm_universal_plane_alloc() instead of
0371  * drm_universal_plane_init() to let the DRM managed resource infrastructure
0372  * take care of cleanup and deallocation.
0373  *
0374  * Drivers that only support the DRM_FORMAT_MOD_LINEAR modifier support may set
0375  * @format_modifiers to NULL. The plane will advertise the linear modifier.
0376  *
0377  * Returns:
0378  * Zero on success, error code on failure.
0379  */
0380 int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
0381                  uint32_t possible_crtcs,
0382                  const struct drm_plane_funcs *funcs,
0383                  const uint32_t *formats, unsigned int format_count,
0384                  const uint64_t *format_modifiers,
0385                  enum drm_plane_type type,
0386                  const char *name, ...)
0387 {
0388     va_list ap;
0389     int ret;
0390 
0391     WARN_ON(!funcs->destroy);
0392 
0393     va_start(ap, name);
0394     ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
0395                      formats, format_count, format_modifiers,
0396                      type, name, ap);
0397     va_end(ap);
0398     return ret;
0399 }
0400 EXPORT_SYMBOL(drm_universal_plane_init);
0401 
0402 static void drmm_universal_plane_alloc_release(struct drm_device *dev, void *ptr)
0403 {
0404     struct drm_plane *plane = ptr;
0405 
0406     if (WARN_ON(!plane->dev))
0407         return;
0408 
0409     drm_plane_cleanup(plane);
0410 }
0411 
0412 void *__drmm_universal_plane_alloc(struct drm_device *dev, size_t size,
0413                    size_t offset, uint32_t possible_crtcs,
0414                    const struct drm_plane_funcs *funcs,
0415                    const uint32_t *formats, unsigned int format_count,
0416                    const uint64_t *format_modifiers,
0417                    enum drm_plane_type type,
0418                    const char *name, ...)
0419 {
0420     void *container;
0421     struct drm_plane *plane;
0422     va_list ap;
0423     int ret;
0424 
0425     if (WARN_ON(!funcs || funcs->destroy))
0426         return ERR_PTR(-EINVAL);
0427 
0428     container = drmm_kzalloc(dev, size, GFP_KERNEL);
0429     if (!container)
0430         return ERR_PTR(-ENOMEM);
0431 
0432     plane = container + offset;
0433 
0434     va_start(ap, name);
0435     ret = __drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
0436                      formats, format_count, format_modifiers,
0437                      type, name, ap);
0438     va_end(ap);
0439     if (ret)
0440         return ERR_PTR(ret);
0441 
0442     ret = drmm_add_action_or_reset(dev, drmm_universal_plane_alloc_release,
0443                        plane);
0444     if (ret)
0445         return ERR_PTR(ret);
0446 
0447     return container;
0448 }
0449 EXPORT_SYMBOL(__drmm_universal_plane_alloc);
0450 
0451 int drm_plane_register_all(struct drm_device *dev)
0452 {
0453     unsigned int num_planes = 0;
0454     unsigned int num_zpos = 0;
0455     struct drm_plane *plane;
0456     int ret = 0;
0457 
0458     drm_for_each_plane(plane, dev) {
0459         if (plane->funcs->late_register)
0460             ret = plane->funcs->late_register(plane);
0461         if (ret)
0462             return ret;
0463 
0464         if (plane->zpos_property)
0465             num_zpos++;
0466         num_planes++;
0467     }
0468 
0469     drm_WARN(dev, num_zpos && num_planes != num_zpos,
0470          "Mixing planes with and without zpos property is invalid\n");
0471 
0472     return 0;
0473 }
0474 
0475 void drm_plane_unregister_all(struct drm_device *dev)
0476 {
0477     struct drm_plane *plane;
0478 
0479     drm_for_each_plane(plane, dev) {
0480         if (plane->funcs->early_unregister)
0481             plane->funcs->early_unregister(plane);
0482     }
0483 }
0484 
0485 /**
0486  * drm_plane_init - Initialize a legacy plane
0487  * @dev: DRM device
0488  * @plane: plane object to init
0489  * @possible_crtcs: bitmask of possible CRTCs
0490  * @funcs: callbacks for the new plane
0491  * @formats: array of supported formats (DRM_FORMAT\_\*)
0492  * @format_count: number of elements in @formats
0493  * @is_primary: plane type (primary vs overlay)
0494  *
0495  * Legacy API to initialize a DRM plane.
0496  *
0497  * New drivers should call drm_universal_plane_init() instead.
0498  *
0499  * Returns:
0500  * Zero on success, error code on failure.
0501  */
0502 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
0503            uint32_t possible_crtcs,
0504            const struct drm_plane_funcs *funcs,
0505            const uint32_t *formats, unsigned int format_count,
0506            bool is_primary)
0507 {
0508     enum drm_plane_type type;
0509 
0510     type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
0511     return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
0512                     formats, format_count,
0513                     NULL, type, NULL);
0514 }
0515 EXPORT_SYMBOL(drm_plane_init);
0516 
0517 /**
0518  * drm_plane_cleanup - Clean up the core plane usage
0519  * @plane: plane to cleanup
0520  *
0521  * This function cleans up @plane and removes it from the DRM mode setting
0522  * core. Note that the function does *not* free the plane structure itself,
0523  * this is the responsibility of the caller.
0524  */
0525 void drm_plane_cleanup(struct drm_plane *plane)
0526 {
0527     struct drm_device *dev = plane->dev;
0528 
0529     drm_modeset_lock_fini(&plane->mutex);
0530 
0531     kfree(plane->format_types);
0532     kfree(plane->modifiers);
0533     drm_mode_object_unregister(dev, &plane->base);
0534 
0535     BUG_ON(list_empty(&plane->head));
0536 
0537     /* Note that the plane_list is considered to be static; should we
0538      * remove the drm_plane at runtime we would have to decrement all
0539      * the indices on the drm_plane after us in the plane_list.
0540      */
0541 
0542     list_del(&plane->head);
0543     dev->mode_config.num_total_plane--;
0544 
0545     WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
0546     if (plane->state && plane->funcs->atomic_destroy_state)
0547         plane->funcs->atomic_destroy_state(plane, plane->state);
0548 
0549     kfree(plane->name);
0550 
0551     memset(plane, 0, sizeof(*plane));
0552 }
0553 EXPORT_SYMBOL(drm_plane_cleanup);
0554 
0555 /**
0556  * drm_plane_from_index - find the registered plane at an index
0557  * @dev: DRM device
0558  * @idx: index of registered plane to find for
0559  *
0560  * Given a plane index, return the registered plane from DRM device's
0561  * list of planes with matching index. This is the inverse of drm_plane_index().
0562  */
0563 struct drm_plane *
0564 drm_plane_from_index(struct drm_device *dev, int idx)
0565 {
0566     struct drm_plane *plane;
0567 
0568     drm_for_each_plane(plane, dev)
0569         if (idx == plane->index)
0570             return plane;
0571 
0572     return NULL;
0573 }
0574 EXPORT_SYMBOL(drm_plane_from_index);
0575 
0576 /**
0577  * drm_plane_force_disable - Forcibly disable a plane
0578  * @plane: plane to disable
0579  *
0580  * Forces the plane to be disabled.
0581  *
0582  * Used when the plane's current framebuffer is destroyed,
0583  * and when restoring fbdev mode.
0584  *
0585  * Note that this function is not suitable for atomic drivers, since it doesn't
0586  * wire through the lock acquisition context properly and hence can't handle
0587  * retries or driver private locks. You probably want to use
0588  * drm_atomic_helper_disable_plane() or
0589  * drm_atomic_helper_disable_planes_on_crtc() instead.
0590  */
0591 void drm_plane_force_disable(struct drm_plane *plane)
0592 {
0593     int ret;
0594 
0595     if (!plane->fb)
0596         return;
0597 
0598     WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
0599 
0600     plane->old_fb = plane->fb;
0601     ret = plane->funcs->disable_plane(plane, NULL);
0602     if (ret) {
0603         DRM_ERROR("failed to disable plane with busy fb\n");
0604         plane->old_fb = NULL;
0605         return;
0606     }
0607     /* disconnect the plane from the fb and crtc: */
0608     drm_framebuffer_put(plane->old_fb);
0609     plane->old_fb = NULL;
0610     plane->fb = NULL;
0611     plane->crtc = NULL;
0612 }
0613 EXPORT_SYMBOL(drm_plane_force_disable);
0614 
0615 /**
0616  * drm_mode_plane_set_obj_prop - set the value of a property
0617  * @plane: drm plane object to set property value for
0618  * @property: property to set
0619  * @value: value the property should be set to
0620  *
0621  * This functions sets a given property on a given plane object. This function
0622  * calls the driver's ->set_property callback and changes the software state of
0623  * the property if the callback succeeds.
0624  *
0625  * Returns:
0626  * Zero on success, error code on failure.
0627  */
0628 int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
0629                 struct drm_property *property,
0630                 uint64_t value)
0631 {
0632     int ret = -EINVAL;
0633     struct drm_mode_object *obj = &plane->base;
0634 
0635     if (plane->funcs->set_property)
0636         ret = plane->funcs->set_property(plane, property, value);
0637     if (!ret)
0638         drm_object_property_set_value(obj, property, value);
0639 
0640     return ret;
0641 }
0642 EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
0643 
0644 int drm_mode_getplane_res(struct drm_device *dev, void *data,
0645               struct drm_file *file_priv)
0646 {
0647     struct drm_mode_get_plane_res *plane_resp = data;
0648     struct drm_plane *plane;
0649     uint32_t __user *plane_ptr;
0650     int count = 0;
0651 
0652     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0653         return -EOPNOTSUPP;
0654 
0655     plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr);
0656 
0657     /*
0658      * This ioctl is called twice, once to determine how much space is
0659      * needed, and the 2nd time to fill it.
0660      */
0661     drm_for_each_plane(plane, dev) {
0662         /*
0663          * Unless userspace set the 'universal planes'
0664          * capability bit, only advertise overlays.
0665          */
0666         if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
0667             !file_priv->universal_planes)
0668             continue;
0669 
0670         if (drm_lease_held(file_priv, plane->base.id)) {
0671             if (count < plane_resp->count_planes &&
0672                 put_user(plane->base.id, plane_ptr + count))
0673                 return -EFAULT;
0674             count++;
0675         }
0676     }
0677     plane_resp->count_planes = count;
0678 
0679     return 0;
0680 }
0681 
0682 int drm_mode_getplane(struct drm_device *dev, void *data,
0683               struct drm_file *file_priv)
0684 {
0685     struct drm_mode_get_plane *plane_resp = data;
0686     struct drm_plane *plane;
0687     uint32_t __user *format_ptr;
0688 
0689     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0690         return -EOPNOTSUPP;
0691 
0692     plane = drm_plane_find(dev, file_priv, plane_resp->plane_id);
0693     if (!plane)
0694         return -ENOENT;
0695 
0696     drm_modeset_lock(&plane->mutex, NULL);
0697     if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
0698         plane_resp->crtc_id = plane->state->crtc->base.id;
0699     else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
0700         plane_resp->crtc_id = plane->crtc->base.id;
0701     else
0702         plane_resp->crtc_id = 0;
0703 
0704     if (plane->state && plane->state->fb)
0705         plane_resp->fb_id = plane->state->fb->base.id;
0706     else if (!plane->state && plane->fb)
0707         plane_resp->fb_id = plane->fb->base.id;
0708     else
0709         plane_resp->fb_id = 0;
0710     drm_modeset_unlock(&plane->mutex);
0711 
0712     plane_resp->plane_id = plane->base.id;
0713     plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
0714                                 plane->possible_crtcs);
0715 
0716     plane_resp->gamma_size = 0;
0717 
0718     /*
0719      * This ioctl is called twice, once to determine how much space is
0720      * needed, and the 2nd time to fill it.
0721      */
0722     if (plane->format_count &&
0723         (plane_resp->count_format_types >= plane->format_count)) {
0724         format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
0725         if (copy_to_user(format_ptr,
0726                  plane->format_types,
0727                  sizeof(uint32_t) * plane->format_count)) {
0728             return -EFAULT;
0729         }
0730     }
0731     plane_resp->count_format_types = plane->format_count;
0732 
0733     return 0;
0734 }
0735 
0736 int drm_plane_check_pixel_format(struct drm_plane *plane,
0737                  u32 format, u64 modifier)
0738 {
0739     unsigned int i;
0740 
0741     for (i = 0; i < plane->format_count; i++) {
0742         if (format == plane->format_types[i])
0743             break;
0744     }
0745     if (i == plane->format_count)
0746         return -EINVAL;
0747 
0748     if (plane->funcs->format_mod_supported) {
0749         if (!plane->funcs->format_mod_supported(plane, format, modifier))
0750             return -EINVAL;
0751     } else {
0752         if (!plane->modifier_count)
0753             return 0;
0754 
0755         for (i = 0; i < plane->modifier_count; i++) {
0756             if (modifier == plane->modifiers[i])
0757                 break;
0758         }
0759         if (i == plane->modifier_count)
0760             return -EINVAL;
0761     }
0762 
0763     return 0;
0764 }
0765 
0766 static int __setplane_check(struct drm_plane *plane,
0767                 struct drm_crtc *crtc,
0768                 struct drm_framebuffer *fb,
0769                 int32_t crtc_x, int32_t crtc_y,
0770                 uint32_t crtc_w, uint32_t crtc_h,
0771                 uint32_t src_x, uint32_t src_y,
0772                 uint32_t src_w, uint32_t src_h)
0773 {
0774     int ret;
0775 
0776     /* Check whether this plane is usable on this CRTC */
0777     if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
0778         DRM_DEBUG_KMS("Invalid crtc for plane\n");
0779         return -EINVAL;
0780     }
0781 
0782     /* Check whether this plane supports the fb pixel format. */
0783     ret = drm_plane_check_pixel_format(plane, fb->format->format,
0784                        fb->modifier);
0785     if (ret) {
0786         DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
0787                   &fb->format->format, fb->modifier);
0788         return ret;
0789     }
0790 
0791     /* Give drivers some help against integer overflows */
0792     if (crtc_w > INT_MAX ||
0793         crtc_x > INT_MAX - (int32_t) crtc_w ||
0794         crtc_h > INT_MAX ||
0795         crtc_y > INT_MAX - (int32_t) crtc_h) {
0796         DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
0797                   crtc_w, crtc_h, crtc_x, crtc_y);
0798         return -ERANGE;
0799     }
0800 
0801     ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
0802     if (ret)
0803         return ret;
0804 
0805     return 0;
0806 }
0807 
0808 /**
0809  * drm_any_plane_has_format - Check whether any plane supports this format and modifier combination
0810  * @dev: DRM device
0811  * @format: pixel format (DRM_FORMAT_*)
0812  * @modifier: data layout modifier
0813  *
0814  * Returns:
0815  * Whether at least one plane supports the specified format and modifier combination.
0816  */
0817 bool drm_any_plane_has_format(struct drm_device *dev,
0818                   u32 format, u64 modifier)
0819 {
0820     struct drm_plane *plane;
0821 
0822     drm_for_each_plane(plane, dev) {
0823         if (drm_plane_check_pixel_format(plane, format, modifier) == 0)
0824             return true;
0825     }
0826 
0827     return false;
0828 }
0829 EXPORT_SYMBOL(drm_any_plane_has_format);
0830 
0831 /*
0832  * __setplane_internal - setplane handler for internal callers
0833  *
0834  * This function will take a reference on the new fb for the plane
0835  * on success.
0836  *
0837  * src_{x,y,w,h} are provided in 16.16 fixed point format
0838  */
0839 static int __setplane_internal(struct drm_plane *plane,
0840                    struct drm_crtc *crtc,
0841                    struct drm_framebuffer *fb,
0842                    int32_t crtc_x, int32_t crtc_y,
0843                    uint32_t crtc_w, uint32_t crtc_h,
0844                    /* src_{x,y,w,h} values are 16.16 fixed point */
0845                    uint32_t src_x, uint32_t src_y,
0846                    uint32_t src_w, uint32_t src_h,
0847                    struct drm_modeset_acquire_ctx *ctx)
0848 {
0849     int ret = 0;
0850 
0851     WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
0852 
0853     /* No fb means shut it down */
0854     if (!fb) {
0855         plane->old_fb = plane->fb;
0856         ret = plane->funcs->disable_plane(plane, ctx);
0857         if (!ret) {
0858             plane->crtc = NULL;
0859             plane->fb = NULL;
0860         } else {
0861             plane->old_fb = NULL;
0862         }
0863         goto out;
0864     }
0865 
0866     ret = __setplane_check(plane, crtc, fb,
0867                    crtc_x, crtc_y, crtc_w, crtc_h,
0868                    src_x, src_y, src_w, src_h);
0869     if (ret)
0870         goto out;
0871 
0872     plane->old_fb = plane->fb;
0873     ret = plane->funcs->update_plane(plane, crtc, fb,
0874                      crtc_x, crtc_y, crtc_w, crtc_h,
0875                      src_x, src_y, src_w, src_h, ctx);
0876     if (!ret) {
0877         plane->crtc = crtc;
0878         plane->fb = fb;
0879         drm_framebuffer_get(plane->fb);
0880     } else {
0881         plane->old_fb = NULL;
0882     }
0883 
0884 out:
0885     if (plane->old_fb)
0886         drm_framebuffer_put(plane->old_fb);
0887     plane->old_fb = NULL;
0888 
0889     return ret;
0890 }
0891 
0892 static int __setplane_atomic(struct drm_plane *plane,
0893                  struct drm_crtc *crtc,
0894                  struct drm_framebuffer *fb,
0895                  int32_t crtc_x, int32_t crtc_y,
0896                  uint32_t crtc_w, uint32_t crtc_h,
0897                  uint32_t src_x, uint32_t src_y,
0898                  uint32_t src_w, uint32_t src_h,
0899                  struct drm_modeset_acquire_ctx *ctx)
0900 {
0901     int ret;
0902 
0903     WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev));
0904 
0905     /* No fb means shut it down */
0906     if (!fb)
0907         return plane->funcs->disable_plane(plane, ctx);
0908 
0909     /*
0910      * FIXME: This is redundant with drm_atomic_plane_check(),
0911      * but the legacy cursor/"async" .update_plane() tricks
0912      * don't call that so we still need this here. Should remove
0913      * this when all .update_plane() implementations have been
0914      * fixed to call drm_atomic_plane_check().
0915      */
0916     ret = __setplane_check(plane, crtc, fb,
0917                    crtc_x, crtc_y, crtc_w, crtc_h,
0918                    src_x, src_y, src_w, src_h);
0919     if (ret)
0920         return ret;
0921 
0922     return plane->funcs->update_plane(plane, crtc, fb,
0923                       crtc_x, crtc_y, crtc_w, crtc_h,
0924                       src_x, src_y, src_w, src_h, ctx);
0925 }
0926 
0927 static int setplane_internal(struct drm_plane *plane,
0928                  struct drm_crtc *crtc,
0929                  struct drm_framebuffer *fb,
0930                  int32_t crtc_x, int32_t crtc_y,
0931                  uint32_t crtc_w, uint32_t crtc_h,
0932                  /* src_{x,y,w,h} values are 16.16 fixed point */
0933                  uint32_t src_x, uint32_t src_y,
0934                  uint32_t src_w, uint32_t src_h)
0935 {
0936     struct drm_modeset_acquire_ctx ctx;
0937     int ret;
0938 
0939     DRM_MODESET_LOCK_ALL_BEGIN(plane->dev, ctx,
0940                    DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
0941 
0942     if (drm_drv_uses_atomic_modeset(plane->dev))
0943         ret = __setplane_atomic(plane, crtc, fb,
0944                     crtc_x, crtc_y, crtc_w, crtc_h,
0945                     src_x, src_y, src_w, src_h, &ctx);
0946     else
0947         ret = __setplane_internal(plane, crtc, fb,
0948                       crtc_x, crtc_y, crtc_w, crtc_h,
0949                       src_x, src_y, src_w, src_h, &ctx);
0950 
0951     DRM_MODESET_LOCK_ALL_END(plane->dev, ctx, ret);
0952 
0953     return ret;
0954 }
0955 
0956 int drm_mode_setplane(struct drm_device *dev, void *data,
0957               struct drm_file *file_priv)
0958 {
0959     struct drm_mode_set_plane *plane_req = data;
0960     struct drm_plane *plane;
0961     struct drm_crtc *crtc = NULL;
0962     struct drm_framebuffer *fb = NULL;
0963     int ret;
0964 
0965     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0966         return -EOPNOTSUPP;
0967 
0968     /*
0969      * First, find the plane, crtc, and fb objects.  If not available,
0970      * we don't bother to call the driver.
0971      */
0972     plane = drm_plane_find(dev, file_priv, plane_req->plane_id);
0973     if (!plane) {
0974         DRM_DEBUG_KMS("Unknown plane ID %d\n",
0975                   plane_req->plane_id);
0976         return -ENOENT;
0977     }
0978 
0979     if (plane_req->fb_id) {
0980         fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id);
0981         if (!fb) {
0982             DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
0983                       plane_req->fb_id);
0984             return -ENOENT;
0985         }
0986 
0987         crtc = drm_crtc_find(dev, file_priv, plane_req->crtc_id);
0988         if (!crtc) {
0989             drm_framebuffer_put(fb);
0990             DRM_DEBUG_KMS("Unknown crtc ID %d\n",
0991                       plane_req->crtc_id);
0992             return -ENOENT;
0993         }
0994     }
0995 
0996     ret = setplane_internal(plane, crtc, fb,
0997                 plane_req->crtc_x, plane_req->crtc_y,
0998                 plane_req->crtc_w, plane_req->crtc_h,
0999                 plane_req->src_x, plane_req->src_y,
1000                 plane_req->src_w, plane_req->src_h);
1001 
1002     if (fb)
1003         drm_framebuffer_put(fb);
1004 
1005     return ret;
1006 }
1007 
1008 static int drm_mode_cursor_universal(struct drm_crtc *crtc,
1009                      struct drm_mode_cursor2 *req,
1010                      struct drm_file *file_priv,
1011                      struct drm_modeset_acquire_ctx *ctx)
1012 {
1013     struct drm_device *dev = crtc->dev;
1014     struct drm_plane *plane = crtc->cursor;
1015     struct drm_framebuffer *fb = NULL;
1016     struct drm_mode_fb_cmd2 fbreq = {
1017         .width = req->width,
1018         .height = req->height,
1019         .pixel_format = DRM_FORMAT_ARGB8888,
1020         .pitches = { req->width * 4 },
1021         .handles = { req->handle },
1022     };
1023     int32_t crtc_x, crtc_y;
1024     uint32_t crtc_w = 0, crtc_h = 0;
1025     uint32_t src_w = 0, src_h = 0;
1026     int ret = 0;
1027 
1028     BUG_ON(!plane);
1029     WARN_ON(plane->crtc != crtc && plane->crtc != NULL);
1030 
1031     /*
1032      * Obtain fb we'll be using (either new or existing) and take an extra
1033      * reference to it if fb != null.  setplane will take care of dropping
1034      * the reference if the plane update fails.
1035      */
1036     if (req->flags & DRM_MODE_CURSOR_BO) {
1037         if (req->handle) {
1038             fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
1039             if (IS_ERR(fb)) {
1040                 DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
1041                 return PTR_ERR(fb);
1042             }
1043 
1044             fb->hot_x = req->hot_x;
1045             fb->hot_y = req->hot_y;
1046         } else {
1047             fb = NULL;
1048         }
1049     } else {
1050         if (plane->state)
1051             fb = plane->state->fb;
1052         else
1053             fb = plane->fb;
1054 
1055         if (fb)
1056             drm_framebuffer_get(fb);
1057     }
1058 
1059     if (req->flags & DRM_MODE_CURSOR_MOVE) {
1060         crtc_x = req->x;
1061         crtc_y = req->y;
1062     } else {
1063         crtc_x = crtc->cursor_x;
1064         crtc_y = crtc->cursor_y;
1065     }
1066 
1067     if (fb) {
1068         crtc_w = fb->width;
1069         crtc_h = fb->height;
1070         src_w = fb->width << 16;
1071         src_h = fb->height << 16;
1072     }
1073 
1074     if (drm_drv_uses_atomic_modeset(dev))
1075         ret = __setplane_atomic(plane, crtc, fb,
1076                     crtc_x, crtc_y, crtc_w, crtc_h,
1077                     0, 0, src_w, src_h, ctx);
1078     else
1079         ret = __setplane_internal(plane, crtc, fb,
1080                       crtc_x, crtc_y, crtc_w, crtc_h,
1081                       0, 0, src_w, src_h, ctx);
1082 
1083     if (fb)
1084         drm_framebuffer_put(fb);
1085 
1086     /* Update successful; save new cursor position, if necessary */
1087     if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
1088         crtc->cursor_x = req->x;
1089         crtc->cursor_y = req->y;
1090     }
1091 
1092     return ret;
1093 }
1094 
1095 static int drm_mode_cursor_common(struct drm_device *dev,
1096                   struct drm_mode_cursor2 *req,
1097                   struct drm_file *file_priv)
1098 {
1099     struct drm_crtc *crtc;
1100     struct drm_modeset_acquire_ctx ctx;
1101     int ret = 0;
1102 
1103     if (!drm_core_check_feature(dev, DRIVER_MODESET))
1104         return -EOPNOTSUPP;
1105 
1106     if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
1107         return -EINVAL;
1108 
1109     crtc = drm_crtc_find(dev, file_priv, req->crtc_id);
1110     if (!crtc) {
1111         DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
1112         return -ENOENT;
1113     }
1114 
1115     drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1116 retry:
1117     ret = drm_modeset_lock(&crtc->mutex, &ctx);
1118     if (ret)
1119         goto out;
1120     /*
1121      * If this crtc has a universal cursor plane, call that plane's update
1122      * handler rather than using legacy cursor handlers.
1123      */
1124     if (crtc->cursor) {
1125         ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
1126         if (ret)
1127             goto out;
1128 
1129         if (!drm_lease_held(file_priv, crtc->cursor->base.id)) {
1130             ret = -EACCES;
1131             goto out;
1132         }
1133 
1134         ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
1135         goto out;
1136     }
1137 
1138     if (req->flags & DRM_MODE_CURSOR_BO) {
1139         if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
1140             ret = -ENXIO;
1141             goto out;
1142         }
1143         /* Turns off the cursor if handle is 0 */
1144         if (crtc->funcs->cursor_set2)
1145             ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
1146                               req->width, req->height, req->hot_x, req->hot_y);
1147         else
1148             ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
1149                               req->width, req->height);
1150     }
1151 
1152     if (req->flags & DRM_MODE_CURSOR_MOVE) {
1153         if (crtc->funcs->cursor_move) {
1154             ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
1155         } else {
1156             ret = -EFAULT;
1157             goto out;
1158         }
1159     }
1160 out:
1161     if (ret == -EDEADLK) {
1162         ret = drm_modeset_backoff(&ctx);
1163         if (!ret)
1164             goto retry;
1165     }
1166 
1167     drm_modeset_drop_locks(&ctx);
1168     drm_modeset_acquire_fini(&ctx);
1169 
1170     return ret;
1171 
1172 }
1173 
1174 
1175 int drm_mode_cursor_ioctl(struct drm_device *dev,
1176               void *data, struct drm_file *file_priv)
1177 {
1178     struct drm_mode_cursor *req = data;
1179     struct drm_mode_cursor2 new_req;
1180 
1181     memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
1182     new_req.hot_x = new_req.hot_y = 0;
1183 
1184     return drm_mode_cursor_common(dev, &new_req, file_priv);
1185 }
1186 
1187 /*
1188  * Set the cursor configuration based on user request. This implements the 2nd
1189  * version of the cursor ioctl, which allows userspace to additionally specify
1190  * the hotspot of the pointer.
1191  */
1192 int drm_mode_cursor2_ioctl(struct drm_device *dev,
1193                void *data, struct drm_file *file_priv)
1194 {
1195     struct drm_mode_cursor2 *req = data;
1196 
1197     return drm_mode_cursor_common(dev, req, file_priv);
1198 }
1199 
1200 int drm_mode_page_flip_ioctl(struct drm_device *dev,
1201                  void *data, struct drm_file *file_priv)
1202 {
1203     struct drm_mode_crtc_page_flip_target *page_flip = data;
1204     struct drm_crtc *crtc;
1205     struct drm_plane *plane;
1206     struct drm_framebuffer *fb = NULL, *old_fb;
1207     struct drm_pending_vblank_event *e = NULL;
1208     u32 target_vblank = page_flip->sequence;
1209     struct drm_modeset_acquire_ctx ctx;
1210     int ret = -EINVAL;
1211 
1212     if (!drm_core_check_feature(dev, DRIVER_MODESET))
1213         return -EOPNOTSUPP;
1214 
1215     if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
1216         return -EINVAL;
1217 
1218     if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
1219         return -EINVAL;
1220 
1221     /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
1222      * can be specified
1223      */
1224     if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
1225         return -EINVAL;
1226 
1227     if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
1228         return -EINVAL;
1229 
1230     crtc = drm_crtc_find(dev, file_priv, page_flip->crtc_id);
1231     if (!crtc)
1232         return -ENOENT;
1233 
1234     plane = crtc->primary;
1235 
1236     if (!drm_lease_held(file_priv, plane->base.id))
1237         return -EACCES;
1238 
1239     if (crtc->funcs->page_flip_target) {
1240         u32 current_vblank;
1241         int r;
1242 
1243         r = drm_crtc_vblank_get(crtc);
1244         if (r)
1245             return r;
1246 
1247         current_vblank = (u32)drm_crtc_vblank_count(crtc);
1248 
1249         switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
1250         case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
1251             if ((int)(target_vblank - current_vblank) > 1) {
1252                 DRM_DEBUG("Invalid absolute flip target %u, "
1253                       "must be <= %u\n", target_vblank,
1254                       current_vblank + 1);
1255                 drm_crtc_vblank_put(crtc);
1256                 return -EINVAL;
1257             }
1258             break;
1259         case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
1260             if (target_vblank != 0 && target_vblank != 1) {
1261                 DRM_DEBUG("Invalid relative flip target %u, "
1262                       "must be 0 or 1\n", target_vblank);
1263                 drm_crtc_vblank_put(crtc);
1264                 return -EINVAL;
1265             }
1266             target_vblank += current_vblank;
1267             break;
1268         default:
1269             target_vblank = current_vblank +
1270                 !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
1271             break;
1272         }
1273     } else if (crtc->funcs->page_flip == NULL ||
1274            (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
1275         return -EINVAL;
1276     }
1277 
1278     drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1279 retry:
1280     ret = drm_modeset_lock(&crtc->mutex, &ctx);
1281     if (ret)
1282         goto out;
1283     ret = drm_modeset_lock(&plane->mutex, &ctx);
1284     if (ret)
1285         goto out;
1286 
1287     if (plane->state)
1288         old_fb = plane->state->fb;
1289     else
1290         old_fb = plane->fb;
1291 
1292     if (old_fb == NULL) {
1293         /* The framebuffer is currently unbound, presumably
1294          * due to a hotplug event, that userspace has not
1295          * yet discovered.
1296          */
1297         ret = -EBUSY;
1298         goto out;
1299     }
1300 
1301     fb = drm_framebuffer_lookup(dev, file_priv, page_flip->fb_id);
1302     if (!fb) {
1303         ret = -ENOENT;
1304         goto out;
1305     }
1306 
1307     if (plane->state) {
1308         const struct drm_plane_state *state = plane->state;
1309 
1310         ret = drm_framebuffer_check_src_coords(state->src_x,
1311                                state->src_y,
1312                                state->src_w,
1313                                state->src_h,
1314                                fb);
1315     } else {
1316         ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y,
1317                           &crtc->mode, fb);
1318     }
1319     if (ret)
1320         goto out;
1321 
1322     /*
1323      * Only check the FOURCC format code, excluding modifiers. This is
1324      * enough for all legacy drivers. Atomic drivers have their own
1325      * checks in their ->atomic_check implementation, which will
1326      * return -EINVAL if any hw or driver constraint is violated due
1327      * to modifier changes.
1328      */
1329     if (old_fb->format->format != fb->format->format) {
1330         DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
1331         ret = -EINVAL;
1332         goto out;
1333     }
1334 
1335     if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1336         e = kzalloc(sizeof *e, GFP_KERNEL);
1337         if (!e) {
1338             ret = -ENOMEM;
1339             goto out;
1340         }
1341 
1342         e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
1343         e->event.base.length = sizeof(e->event);
1344         e->event.vbl.user_data = page_flip->user_data;
1345         e->event.vbl.crtc_id = crtc->base.id;
1346 
1347         ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
1348         if (ret) {
1349             kfree(e);
1350             e = NULL;
1351             goto out;
1352         }
1353     }
1354 
1355     plane->old_fb = plane->fb;
1356     if (crtc->funcs->page_flip_target)
1357         ret = crtc->funcs->page_flip_target(crtc, fb, e,
1358                             page_flip->flags,
1359                             target_vblank,
1360                             &ctx);
1361     else
1362         ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
1363                          &ctx);
1364     if (ret) {
1365         if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
1366             drm_event_cancel_free(dev, &e->base);
1367         /* Keep the old fb, don't unref it. */
1368         plane->old_fb = NULL;
1369     } else {
1370         if (!plane->state) {
1371             plane->fb = fb;
1372             drm_framebuffer_get(fb);
1373         }
1374     }
1375 
1376 out:
1377     if (fb)
1378         drm_framebuffer_put(fb);
1379     if (plane->old_fb)
1380         drm_framebuffer_put(plane->old_fb);
1381     plane->old_fb = NULL;
1382 
1383     if (ret == -EDEADLK) {
1384         ret = drm_modeset_backoff(&ctx);
1385         if (!ret)
1386             goto retry;
1387     }
1388 
1389     drm_modeset_drop_locks(&ctx);
1390     drm_modeset_acquire_fini(&ctx);
1391 
1392     if (ret && crtc->funcs->page_flip_target)
1393         drm_crtc_vblank_put(crtc);
1394 
1395     return ret;
1396 }
1397 
1398 /**
1399  * DOC: damage tracking
1400  *
1401  * FB_DAMAGE_CLIPS is an optional plane property which provides a means to
1402  * specify a list of damage rectangles on a plane in framebuffer coordinates of
1403  * the framebuffer attached to the plane. In current context damage is the area
1404  * of plane framebuffer that has changed since last plane update (also called
1405  * page-flip), irrespective of whether currently attached framebuffer is same as
1406  * framebuffer attached during last plane update or not.
1407  *
1408  * FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
1409  * to optimize internally especially for virtual devices where each framebuffer
1410  * change needs to be transmitted over network, usb, etc.
1411  *
1412  * Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
1413  * ignore damage clips property and in that case driver will do a full plane
1414  * update. In case damage clips are provided then it is guaranteed that the area
1415  * inside damage clips will be updated to plane. For efficiency driver can do
1416  * full update or can update more than specified in damage clips. Since driver
1417  * is free to read more, user-space must always render the entire visible
1418  * framebuffer. Otherwise there can be corruptions. Also, if a user-space
1419  * provides damage clips which doesn't encompass the actual damage to
1420  * framebuffer (since last plane update) can result in incorrect rendering.
1421  *
1422  * FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
1423  * array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
1424  * damage clips are not in 16.16 fixed point. Similar to plane src in
1425  * framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
1426  * inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
1427  * damage clips, it is strongly discouraged.
1428  *
1429  * Drivers that are interested in damage interface for plane should enable
1430  * FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
1431  * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
1432  * drm_atomic_helper_damage_iter_next() helper iterator function to get damage
1433  * rectangles clipped to &drm_plane_state.src.
1434  */
1435 
1436 /**
1437  * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
1438  * @plane: Plane on which to enable damage clips property.
1439  *
1440  * This function lets driver to enable the damage clips property on a plane.
1441  */
1442 void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
1443 {
1444     struct drm_device *dev = plane->dev;
1445     struct drm_mode_config *config = &dev->mode_config;
1446 
1447     drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
1448                    0);
1449 }
1450 EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
1451 
1452 /**
1453  * drm_plane_get_damage_clips_count - Returns damage clips count.
1454  * @state: Plane state.
1455  *
1456  * Simple helper to get the number of &drm_mode_rect clips set by user-space
1457  * during plane update.
1458  *
1459  * Return: Number of clips in plane fb_damage_clips blob property.
1460  */
1461 unsigned int
1462 drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
1463 {
1464     return (state && state->fb_damage_clips) ?
1465         state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
1466 }
1467 EXPORT_SYMBOL(drm_plane_get_damage_clips_count);
1468 
1469 struct drm_mode_rect *
1470 __drm_plane_get_damage_clips(const struct drm_plane_state *state)
1471 {
1472     return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
1473                     state->fb_damage_clips->data : NULL);
1474 }
1475 
1476 /**
1477  * drm_plane_get_damage_clips - Returns damage clips.
1478  * @state: Plane state.
1479  *
1480  * Note that this function returns uapi type &drm_mode_rect. Drivers might want
1481  * to use the helper functions drm_atomic_helper_damage_iter_init() and
1482  * drm_atomic_helper_damage_iter_next() or drm_atomic_helper_damage_merged() if
1483  * the driver can only handle a single damage region at most.
1484  *
1485  * Return: Damage clips in plane fb_damage_clips blob property.
1486  */
1487 struct drm_mode_rect *
1488 drm_plane_get_damage_clips(const struct drm_plane_state *state)
1489 {
1490     struct drm_device *dev = state->plane->dev;
1491     struct drm_mode_config *config = &dev->mode_config;
1492 
1493     /* check that drm_plane_enable_fb_damage_clips() was called */
1494     if (!drm_mode_obj_find_prop_id(&state->plane->base,
1495                        config->prop_fb_damage_clips->base.id))
1496         drm_warn_once(dev, "drm_plane_enable_fb_damage_clips() not called\n");
1497 
1498     return __drm_plane_get_damage_clips(state);
1499 }
1500 EXPORT_SYMBOL(drm_plane_get_damage_clips);
1501 
1502 struct drm_property *
1503 drm_create_scaling_filter_prop(struct drm_device *dev,
1504                    unsigned int supported_filters)
1505 {
1506     struct drm_property *prop;
1507     static const struct drm_prop_enum_list props[] = {
1508         { DRM_SCALING_FILTER_DEFAULT, "Default" },
1509         { DRM_SCALING_FILTER_NEAREST_NEIGHBOR, "Nearest Neighbor" },
1510     };
1511     unsigned int valid_mode_mask = BIT(DRM_SCALING_FILTER_DEFAULT) |
1512                        BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
1513     int i;
1514 
1515     if (WARN_ON((supported_filters & ~valid_mode_mask) ||
1516             ((supported_filters & BIT(DRM_SCALING_FILTER_DEFAULT)) == 0)))
1517         return ERR_PTR(-EINVAL);
1518 
1519     prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
1520                    "SCALING_FILTER",
1521                    hweight32(supported_filters));
1522     if (!prop)
1523         return ERR_PTR(-ENOMEM);
1524 
1525     for (i = 0; i < ARRAY_SIZE(props); i++) {
1526         int ret;
1527 
1528         if (!(BIT(props[i].type) & supported_filters))
1529             continue;
1530 
1531         ret = drm_property_add_enum(prop, props[i].type,
1532                         props[i].name);
1533 
1534         if (ret) {
1535             drm_property_destroy(dev, prop);
1536 
1537             return ERR_PTR(ret);
1538         }
1539     }
1540 
1541     return prop;
1542 }
1543 
1544 /**
1545  * drm_plane_create_scaling_filter_property - create a new scaling filter
1546  * property
1547  *
1548  * @plane: drm plane
1549  * @supported_filters: bitmask of supported scaling filters, must include
1550  *             BIT(DRM_SCALING_FILTER_DEFAULT).
1551  *
1552  * This function lets driver to enable the scaling filter property on a given
1553  * plane.
1554  *
1555  * RETURNS:
1556  * Zero for success or -errno
1557  */
1558 int drm_plane_create_scaling_filter_property(struct drm_plane *plane,
1559                          unsigned int supported_filters)
1560 {
1561     struct drm_property *prop =
1562         drm_create_scaling_filter_prop(plane->dev, supported_filters);
1563 
1564     if (IS_ERR(prop))
1565         return PTR_ERR(prop);
1566 
1567     drm_object_attach_property(&plane->base, prop,
1568                    DRM_SCALING_FILTER_DEFAULT);
1569     plane->scaling_filter_property = prop;
1570 
1571     return 0;
1572 }
1573 EXPORT_SYMBOL(drm_plane_create_scaling_filter_property);