144d1240dSMarek Szyprowski /* 244d1240dSMarek Szyprowski * Copyright (C) 2016 Samsung Electronics Co.Ltd 344d1240dSMarek Szyprowski * Authors: 444d1240dSMarek Szyprowski * Marek Szyprowski <m.szyprowski@samsung.com> 544d1240dSMarek Szyprowski * 644d1240dSMarek Szyprowski * DRM core plane blending related functions 744d1240dSMarek Szyprowski * 844d1240dSMarek Szyprowski * Permission to use, copy, modify, distribute, and sell this software and its 944d1240dSMarek Szyprowski * documentation for any purpose is hereby granted without fee, provided that 1044d1240dSMarek Szyprowski * the above copyright notice appear in all copies and that both that copyright 1144d1240dSMarek Szyprowski * notice and this permission notice appear in supporting documentation, and 1244d1240dSMarek Szyprowski * that the name of the copyright holders not be used in advertising or 1344d1240dSMarek Szyprowski * publicity pertaining to distribution of the software without specific, 1444d1240dSMarek Szyprowski * written prior permission. The copyright holders make no representations 1544d1240dSMarek Szyprowski * about the suitability of this software for any purpose. It is provided "as 1644d1240dSMarek Szyprowski * is" without express or implied warranty. 1744d1240dSMarek Szyprowski * 1844d1240dSMarek Szyprowski * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1944d1240dSMarek Szyprowski * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 2044d1240dSMarek Szyprowski * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 2144d1240dSMarek Szyprowski * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2244d1240dSMarek Szyprowski * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2344d1240dSMarek Szyprowski * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2444d1240dSMarek Szyprowski * OF THIS SOFTWARE. 2544d1240dSMarek Szyprowski */ 2644d1240dSMarek Szyprowski #include <drm/drmP.h> 2744d1240dSMarek Szyprowski #include <drm/drm_atomic.h> 2818733802SDaniel Vetter #include <drm/drm_blend.h> 2944d1240dSMarek Szyprowski #include <linux/export.h> 3044d1240dSMarek Szyprowski #include <linux/slab.h> 3144d1240dSMarek Szyprowski #include <linux/sort.h> 3244d1240dSMarek Szyprowski 33c30b4400SVille Syrjälä #include "drm_crtc_internal.h" 3444d1240dSMarek Szyprowski 351e4d84c6SDaniel Vetter /** 361e4d84c6SDaniel Vetter * DOC: overview 371e4d84c6SDaniel Vetter * 381e4d84c6SDaniel Vetter * The basic plane composition model supported by standard plane properties only 391e4d84c6SDaniel Vetter * has a source rectangle (in logical pixels within the &drm_framebuffer), with 401e4d84c6SDaniel Vetter * sub-pixel accuracy, which is scaled up to a pixel-aligned destination 411e4d84c6SDaniel Vetter * rectangle in the visible area of a &drm_crtc. The visible area of a CRTC is 421e4d84c6SDaniel Vetter * defined by the horizontal and vertical visible pixels (stored in @hdisplay 431e4d84c6SDaniel Vetter * and @vdisplay) of the requested mode (stored in @mode in the 441e4d84c6SDaniel Vetter * &drm_crtc_state). These two rectangles are both stored in the 451e4d84c6SDaniel Vetter * &drm_plane_state. 461e4d84c6SDaniel Vetter * 471e4d84c6SDaniel Vetter * For the atomic ioctl the following standard (atomic) properties on the plane object 481e4d84c6SDaniel Vetter * encode the basic plane composition model: 491e4d84c6SDaniel Vetter * 501e4d84c6SDaniel Vetter * SRC_X: 511e4d84c6SDaniel Vetter * X coordinate offset for the source rectangle within the 521e4d84c6SDaniel Vetter * &drm_framebuffer, in 16.16 fixed point. Must be positive. 531e4d84c6SDaniel Vetter * SRC_Y: 541e4d84c6SDaniel Vetter * Y coordinate offset for the source rectangle within the 551e4d84c6SDaniel Vetter * &drm_framebuffer, in 16.16 fixed point. Must be positive. 561e4d84c6SDaniel Vetter * SRC_W: 571e4d84c6SDaniel Vetter * Width for the source rectangle within the &drm_framebuffer, in 16.16 581e4d84c6SDaniel Vetter * fixed point. SRC_X plus SRC_W must be within the width of the source 591e4d84c6SDaniel Vetter * framebuffer. Must be positive. 601e4d84c6SDaniel Vetter * SRC_H: 611e4d84c6SDaniel Vetter * Height for the source rectangle within the &drm_framebuffer, in 16.16 621e4d84c6SDaniel Vetter * fixed point. SRC_Y plus SRC_H must be within the height of the source 631e4d84c6SDaniel Vetter * framebuffer. Must be positive. 641e4d84c6SDaniel Vetter * CRTC_X: 651e4d84c6SDaniel Vetter * X coordinate offset for the destination rectangle. Can be negative. 661e4d84c6SDaniel Vetter * CRTC_Y: 671e4d84c6SDaniel Vetter * Y coordinate offset for the destination rectangle. Can be negative. 681e4d84c6SDaniel Vetter * CRTC_W: 691e4d84c6SDaniel Vetter * Width for the destination rectangle. CRTC_X plus CRTC_W can extend past 701e4d84c6SDaniel Vetter * the currently visible horizontal area of the &drm_crtc. 711e4d84c6SDaniel Vetter * CRTC_H: 721e4d84c6SDaniel Vetter * Height for the destination rectangle. CRTC_Y plus CRTC_H can extend past 731e4d84c6SDaniel Vetter * the currently visible vertical area of the &drm_crtc. 741e4d84c6SDaniel Vetter * FB_ID: 751e4d84c6SDaniel Vetter * Mode object ID of the &drm_framebuffer this plane should scan out. 761e4d84c6SDaniel Vetter * CRTC_ID: 771e4d84c6SDaniel Vetter * Mode object ID of the &drm_crtc this plane should be connected to. 781e4d84c6SDaniel Vetter * 791e4d84c6SDaniel Vetter * Note that the source rectangle must fully lie within the bounds of the 801e4d84c6SDaniel Vetter * &drm_framebuffer. The destination rectangle can lie outside of the visible 811e4d84c6SDaniel Vetter * area of the current mode of the CRTC. It must be apprpriately clipped by the 821e4d84c6SDaniel Vetter * driver, which can be done by calling drm_plane_helper_check_update(). Drivers 831e4d84c6SDaniel Vetter * are also allowed to round the subpixel sampling positions appropriately, but 841e4d84c6SDaniel Vetter * only to the next full pixel. No pixel outside of the source rectangle may 851e4d84c6SDaniel Vetter * ever be sampled, which is important when applying more sophisticated 861e4d84c6SDaniel Vetter * filtering than just a bilinear one when scaling. The filtering mode when 871e4d84c6SDaniel Vetter * scaling is unspecified. 881e4d84c6SDaniel Vetter * 891e4d84c6SDaniel Vetter * On top of this basic transformation additional properties can be exposed by 901e4d84c6SDaniel Vetter * the driver: 911e4d84c6SDaniel Vetter * 926686df8cSVille Syrjälä * - Rotation is set up with drm_plane_create_rotation_property(). It adds a 931e4d84c6SDaniel Vetter * rotation and reflection step between the source and destination rectangles. 941e4d84c6SDaniel Vetter * Without this property the rectangle is only scaled, but not rotated or 951e4d84c6SDaniel Vetter * reflected. 961e4d84c6SDaniel Vetter * 971e4d84c6SDaniel Vetter * - Z position is set up with drm_plane_create_zpos_immutable_property() and 981e4d84c6SDaniel Vetter * drm_plane_create_zpos_property(). It controls the visibility of overlapping 991e4d84c6SDaniel Vetter * planes. Without this property the primary plane is always below the cursor 1001e4d84c6SDaniel Vetter * plane, and ordering between all other planes is undefined. 1011e4d84c6SDaniel Vetter * 1021e4d84c6SDaniel Vetter * Note that all the property extensions described here apply either to the 1031e4d84c6SDaniel Vetter * plane or the CRTC (e.g. for the background color, which currently is not 1041e4d84c6SDaniel Vetter * exposed and assumed to be black). 1051e4d84c6SDaniel Vetter */ 1061e4d84c6SDaniel Vetter 1071e4d84c6SDaniel Vetter /** 1086686df8cSVille Syrjälä * drm_plane_create_rotation_property - create a new rotation property 1096686df8cSVille Syrjälä * @plane: drm plane 1106686df8cSVille Syrjälä * @rotation: initial value of the rotation property 1111e4d84c6SDaniel Vetter * @supported_rotations: bitmask of supported rotations and reflections 1121e4d84c6SDaniel Vetter * 1131e4d84c6SDaniel Vetter * This creates a new property with the selected support for transformations. 1141e4d84c6SDaniel Vetter * 1151e4d84c6SDaniel Vetter * Since a rotation by 180° degress is the same as reflecting both along the x 1161e4d84c6SDaniel Vetter * and the y axis the rotation property is somewhat redundant. Drivers can use 1171e4d84c6SDaniel Vetter * drm_rotation_simplify() to normalize values of this property. 1181e4d84c6SDaniel Vetter * 1191e4d84c6SDaniel Vetter * The property exposed to userspace is a bitmask property (see 1201e4d84c6SDaniel Vetter * drm_property_create_bitmask()) called "rotation" and has the following 1211e4d84c6SDaniel Vetter * bitmask enumaration values: 1221e4d84c6SDaniel Vetter * 1231e4d84c6SDaniel Vetter * DRM_ROTATE_0: 1241e4d84c6SDaniel Vetter * "rotate-0" 1251e4d84c6SDaniel Vetter * DRM_ROTATE_90: 1261e4d84c6SDaniel Vetter * "rotate-90" 1271e4d84c6SDaniel Vetter * DRM_ROTATE_180: 1281e4d84c6SDaniel Vetter * "rotate-180" 1291e4d84c6SDaniel Vetter * DRM_ROTATE_270: 1301e4d84c6SDaniel Vetter * "rotate-270" 1311e4d84c6SDaniel Vetter * DRM_REFLECT_X: 1321e4d84c6SDaniel Vetter * "reflect-x" 1331e4d84c6SDaniel Vetter * DRM_REFELCT_Y: 1341e4d84c6SDaniel Vetter * "reflect-y" 1351e4d84c6SDaniel Vetter * 1361e4d84c6SDaniel Vetter * Rotation is the specified amount in degrees in counter clockwise direction, 1371e4d84c6SDaniel Vetter * the X and Y axis are within the source rectangle, i.e. the X/Y axis before 1381e4d84c6SDaniel Vetter * rotation. After reflection, the rotation is applied to the image sampled from 1391e4d84c6SDaniel Vetter * the source rectangle, before scaling it to fit the destination rectangle. 1401e4d84c6SDaniel Vetter */ 141d138dd3cSVille Syrjälä int drm_plane_create_rotation_property(struct drm_plane *plane, 142d138dd3cSVille Syrjälä unsigned int rotation, 143d138dd3cSVille Syrjälä unsigned int supported_rotations) 144d138dd3cSVille Syrjälä { 145d138dd3cSVille Syrjälä static const struct drm_prop_enum_list props[] = { 146d138dd3cSVille Syrjälä { __builtin_ffs(DRM_ROTATE_0) - 1, "rotate-0" }, 147d138dd3cSVille Syrjälä { __builtin_ffs(DRM_ROTATE_90) - 1, "rotate-90" }, 148d138dd3cSVille Syrjälä { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" }, 149d138dd3cSVille Syrjälä { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" }, 150d138dd3cSVille Syrjälä { __builtin_ffs(DRM_REFLECT_X) - 1, "reflect-x" }, 151d138dd3cSVille Syrjälä { __builtin_ffs(DRM_REFLECT_Y) - 1, "reflect-y" }, 152d138dd3cSVille Syrjälä }; 153d138dd3cSVille Syrjälä struct drm_property *prop; 154d138dd3cSVille Syrjälä 155d138dd3cSVille Syrjälä WARN_ON((supported_rotations & DRM_ROTATE_MASK) == 0); 156d138dd3cSVille Syrjälä WARN_ON(!is_power_of_2(rotation & DRM_ROTATE_MASK)); 157d138dd3cSVille Syrjälä WARN_ON(rotation & ~supported_rotations); 158d138dd3cSVille Syrjälä 159d138dd3cSVille Syrjälä prop = drm_property_create_bitmask(plane->dev, 0, "rotation", 160d138dd3cSVille Syrjälä props, ARRAY_SIZE(props), 161d138dd3cSVille Syrjälä supported_rotations); 162d138dd3cSVille Syrjälä if (!prop) 163d138dd3cSVille Syrjälä return -ENOMEM; 164d138dd3cSVille Syrjälä 165d138dd3cSVille Syrjälä drm_object_attach_property(&plane->base, prop, rotation); 166d138dd3cSVille Syrjälä 167d138dd3cSVille Syrjälä if (plane->state) 168d138dd3cSVille Syrjälä plane->state->rotation = rotation; 169d138dd3cSVille Syrjälä 170d138dd3cSVille Syrjälä plane->rotation_property = prop; 171d138dd3cSVille Syrjälä 172d138dd3cSVille Syrjälä return 0; 173d138dd3cSVille Syrjälä } 174d138dd3cSVille Syrjälä EXPORT_SYMBOL(drm_plane_create_rotation_property); 175d138dd3cSVille Syrjälä 17618733802SDaniel Vetter /** 17718733802SDaniel Vetter * drm_rotation_simplify() - Try to simplify the rotation 17818733802SDaniel Vetter * @rotation: Rotation to be simplified 17918733802SDaniel Vetter * @supported_rotations: Supported rotations 18018733802SDaniel Vetter * 18118733802SDaniel Vetter * Attempt to simplify the rotation to a form that is supported. 18218733802SDaniel Vetter * Eg. if the hardware supports everything except DRM_REFLECT_X 18318733802SDaniel Vetter * one could call this function like this: 18418733802SDaniel Vetter * 18518733802SDaniel Vetter * drm_rotation_simplify(rotation, DRM_ROTATE_0 | 18618733802SDaniel Vetter * DRM_ROTATE_90 | DRM_ROTATE_180 | 18718733802SDaniel Vetter * DRM_ROTATE_270 | DRM_REFLECT_Y); 18818733802SDaniel Vetter * 18918733802SDaniel Vetter * to eliminate the DRM_ROTATE_X flag. Depending on what kind of 19018733802SDaniel Vetter * transforms the hardware supports, this function may not 19118733802SDaniel Vetter * be able to produce a supported transform, so the caller should 19218733802SDaniel Vetter * check the result afterwards. 19318733802SDaniel Vetter */ 19418733802SDaniel Vetter unsigned int drm_rotation_simplify(unsigned int rotation, 19518733802SDaniel Vetter unsigned int supported_rotations) 19618733802SDaniel Vetter { 19718733802SDaniel Vetter if (rotation & ~supported_rotations) { 19818733802SDaniel Vetter rotation ^= DRM_REFLECT_X | DRM_REFLECT_Y; 19918733802SDaniel Vetter rotation = (rotation & DRM_REFLECT_MASK) | 20018733802SDaniel Vetter BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4); 20118733802SDaniel Vetter } 20218733802SDaniel Vetter 20318733802SDaniel Vetter return rotation; 20418733802SDaniel Vetter } 20518733802SDaniel Vetter EXPORT_SYMBOL(drm_rotation_simplify); 20618733802SDaniel Vetter 20744d1240dSMarek Szyprowski /** 20844d1240dSMarek Szyprowski * drm_plane_create_zpos_property - create mutable zpos property 20944d1240dSMarek Szyprowski * @plane: drm plane 21044d1240dSMarek Szyprowski * @zpos: initial value of zpos property 21144d1240dSMarek Szyprowski * @min: minimal possible value of zpos property 21244d1240dSMarek Szyprowski * @max: maximal possible value of zpos property 21344d1240dSMarek Szyprowski * 21444d1240dSMarek Szyprowski * This function initializes generic mutable zpos property and enables support 21544d1240dSMarek Szyprowski * for it in drm core. Drivers can then attach this property to planes to enable 21644d1240dSMarek Szyprowski * support for configurable planes arrangement during blending operation. 21744d1240dSMarek Szyprowski * Once mutable zpos property has been enabled, the DRM core will automatically 21844d1240dSMarek Szyprowski * calculate drm_plane_state->normalized_zpos values. Usually min should be set 21944d1240dSMarek Szyprowski * to 0 and max to maximal number of planes for given crtc - 1. 22044d1240dSMarek Szyprowski * 22144d1240dSMarek Szyprowski * If zpos of some planes cannot be changed (like fixed background or 22244d1240dSMarek Szyprowski * cursor/topmost planes), driver should adjust min/max values and assign those 22344d1240dSMarek Szyprowski * planes immutable zpos property with lower or higher values (for more 2241e4d84c6SDaniel Vetter * information, see drm_plane_create_zpos_immutable_property() function). In such 22544d1240dSMarek Szyprowski * case driver should also assign proper initial zpos values for all planes in 22644d1240dSMarek Szyprowski * its plane_reset() callback, so the planes will be always sorted properly. 22744d1240dSMarek Szyprowski * 2281e4d84c6SDaniel Vetter * See also drm_atomic_normalize_zpos(). 2291e4d84c6SDaniel Vetter * 2301e4d84c6SDaniel Vetter * The property exposed to userspace is called "zpos". 2311e4d84c6SDaniel Vetter * 23244d1240dSMarek Szyprowski * Returns: 23344d1240dSMarek Szyprowski * Zero on success, negative errno on failure. 23444d1240dSMarek Szyprowski */ 23544d1240dSMarek Szyprowski int drm_plane_create_zpos_property(struct drm_plane *plane, 23644d1240dSMarek Szyprowski unsigned int zpos, 23744d1240dSMarek Szyprowski unsigned int min, unsigned int max) 23844d1240dSMarek Szyprowski { 23944d1240dSMarek Szyprowski struct drm_property *prop; 24044d1240dSMarek Szyprowski 24144d1240dSMarek Szyprowski prop = drm_property_create_range(plane->dev, 0, "zpos", min, max); 24244d1240dSMarek Szyprowski if (!prop) 24344d1240dSMarek Szyprowski return -ENOMEM; 24444d1240dSMarek Szyprowski 24544d1240dSMarek Szyprowski drm_object_attach_property(&plane->base, prop, zpos); 24644d1240dSMarek Szyprowski 24744d1240dSMarek Szyprowski plane->zpos_property = prop; 24844d1240dSMarek Szyprowski 24944d1240dSMarek Szyprowski if (plane->state) { 25044d1240dSMarek Szyprowski plane->state->zpos = zpos; 25144d1240dSMarek Szyprowski plane->state->normalized_zpos = zpos; 25244d1240dSMarek Szyprowski } 25344d1240dSMarek Szyprowski 25444d1240dSMarek Szyprowski return 0; 25544d1240dSMarek Szyprowski } 25644d1240dSMarek Szyprowski EXPORT_SYMBOL(drm_plane_create_zpos_property); 25744d1240dSMarek Szyprowski 25844d1240dSMarek Szyprowski /** 25944d1240dSMarek Szyprowski * drm_plane_create_zpos_immutable_property - create immuttable zpos property 26044d1240dSMarek Szyprowski * @plane: drm plane 26144d1240dSMarek Szyprowski * @zpos: value of zpos property 26244d1240dSMarek Szyprowski * 26344d1240dSMarek Szyprowski * This function initializes generic immutable zpos property and enables 26444d1240dSMarek Szyprowski * support for it in drm core. Using this property driver lets userspace 26544d1240dSMarek Szyprowski * to get the arrangement of the planes for blending operation and notifies 26644d1240dSMarek Szyprowski * it that the hardware (or driver) doesn't support changing of the planes' 2671e4d84c6SDaniel Vetter * order. For mutable zpos see drm_plane_create_zpos_property(). 2681e4d84c6SDaniel Vetter * 2691e4d84c6SDaniel Vetter * The property exposed to userspace is called "zpos". 27044d1240dSMarek Szyprowski * 27144d1240dSMarek Szyprowski * Returns: 27244d1240dSMarek Szyprowski * Zero on success, negative errno on failure. 27344d1240dSMarek Szyprowski */ 27444d1240dSMarek Szyprowski int drm_plane_create_zpos_immutable_property(struct drm_plane *plane, 27544d1240dSMarek Szyprowski unsigned int zpos) 27644d1240dSMarek Szyprowski { 27744d1240dSMarek Szyprowski struct drm_property *prop; 27844d1240dSMarek Szyprowski 27944d1240dSMarek Szyprowski prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE, 28044d1240dSMarek Szyprowski "zpos", zpos, zpos); 28144d1240dSMarek Szyprowski if (!prop) 28244d1240dSMarek Szyprowski return -ENOMEM; 28344d1240dSMarek Szyprowski 28444d1240dSMarek Szyprowski drm_object_attach_property(&plane->base, prop, zpos); 28544d1240dSMarek Szyprowski 28644d1240dSMarek Szyprowski plane->zpos_property = prop; 28744d1240dSMarek Szyprowski 28844d1240dSMarek Szyprowski if (plane->state) { 28944d1240dSMarek Szyprowski plane->state->zpos = zpos; 29044d1240dSMarek Szyprowski plane->state->normalized_zpos = zpos; 29144d1240dSMarek Szyprowski } 29244d1240dSMarek Szyprowski 29344d1240dSMarek Szyprowski return 0; 29444d1240dSMarek Szyprowski } 29544d1240dSMarek Szyprowski EXPORT_SYMBOL(drm_plane_create_zpos_immutable_property); 29644d1240dSMarek Szyprowski 29744d1240dSMarek Szyprowski static int drm_atomic_state_zpos_cmp(const void *a, const void *b) 29844d1240dSMarek Szyprowski { 29944d1240dSMarek Szyprowski const struct drm_plane_state *sa = *(struct drm_plane_state **)a; 30044d1240dSMarek Szyprowski const struct drm_plane_state *sb = *(struct drm_plane_state **)b; 30144d1240dSMarek Szyprowski 30244d1240dSMarek Szyprowski if (sa->zpos != sb->zpos) 30344d1240dSMarek Szyprowski return sa->zpos - sb->zpos; 30444d1240dSMarek Szyprowski else 30544d1240dSMarek Szyprowski return sa->plane->base.id - sb->plane->base.id; 30644d1240dSMarek Szyprowski } 30744d1240dSMarek Szyprowski 30844d1240dSMarek Szyprowski static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc, 30944d1240dSMarek Szyprowski struct drm_crtc_state *crtc_state) 31044d1240dSMarek Szyprowski { 31144d1240dSMarek Szyprowski struct drm_atomic_state *state = crtc_state->state; 31244d1240dSMarek Szyprowski struct drm_device *dev = crtc->dev; 31344d1240dSMarek Szyprowski int total_planes = dev->mode_config.num_total_plane; 31444d1240dSMarek Szyprowski struct drm_plane_state **states; 31544d1240dSMarek Szyprowski struct drm_plane *plane; 31644d1240dSMarek Szyprowski int i, n = 0; 31744d1240dSMarek Szyprowski int ret = 0; 31844d1240dSMarek Szyprowski 31944d1240dSMarek Szyprowski DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n", 32044d1240dSMarek Szyprowski crtc->base.id, crtc->name); 32144d1240dSMarek Szyprowski 32244d1240dSMarek Szyprowski states = kmalloc_array(total_planes, sizeof(*states), GFP_TEMPORARY); 32344d1240dSMarek Szyprowski if (!states) 32444d1240dSMarek Szyprowski return -ENOMEM; 32544d1240dSMarek Szyprowski 32644d1240dSMarek Szyprowski /* 32744d1240dSMarek Szyprowski * Normalization process might create new states for planes which 32844d1240dSMarek Szyprowski * normalized_zpos has to be recalculated. 32944d1240dSMarek Szyprowski */ 33044d1240dSMarek Szyprowski drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) { 33144d1240dSMarek Szyprowski struct drm_plane_state *plane_state = 33244d1240dSMarek Szyprowski drm_atomic_get_plane_state(state, plane); 33344d1240dSMarek Szyprowski if (IS_ERR(plane_state)) { 33444d1240dSMarek Szyprowski ret = PTR_ERR(plane_state); 33544d1240dSMarek Szyprowski goto done; 33644d1240dSMarek Szyprowski } 33744d1240dSMarek Szyprowski states[n++] = plane_state; 33844d1240dSMarek Szyprowski DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n", 33944d1240dSMarek Szyprowski plane->base.id, plane->name, 34044d1240dSMarek Szyprowski plane_state->zpos); 34144d1240dSMarek Szyprowski } 34244d1240dSMarek Szyprowski 34344d1240dSMarek Szyprowski sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL); 34444d1240dSMarek Szyprowski 34544d1240dSMarek Szyprowski for (i = 0; i < n; i++) { 34644d1240dSMarek Szyprowski plane = states[i]->plane; 34744d1240dSMarek Szyprowski 34844d1240dSMarek Szyprowski states[i]->normalized_zpos = i; 34944d1240dSMarek Szyprowski DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n", 35044d1240dSMarek Szyprowski plane->base.id, plane->name, i); 35144d1240dSMarek Szyprowski } 35244d1240dSMarek Szyprowski crtc_state->zpos_changed = true; 35344d1240dSMarek Szyprowski 35444d1240dSMarek Szyprowski done: 35544d1240dSMarek Szyprowski kfree(states); 35644d1240dSMarek Szyprowski return ret; 35744d1240dSMarek Szyprowski } 35844d1240dSMarek Szyprowski 35944d1240dSMarek Szyprowski /** 36052a9fcdaSDaniel Vetter * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs 36144d1240dSMarek Szyprowski * @dev: DRM device 36244d1240dSMarek Szyprowski * @state: atomic state of DRM device 36344d1240dSMarek Szyprowski * 36444d1240dSMarek Szyprowski * This function calculates normalized zpos value for all modified planes in 3651e4d84c6SDaniel Vetter * the provided atomic state of DRM device. 3661e4d84c6SDaniel Vetter * 3671e4d84c6SDaniel Vetter * For every CRTC this function checks new states of all planes assigned to 3681e4d84c6SDaniel Vetter * it and calculates normalized zpos value for these planes. Planes are compared 3691e4d84c6SDaniel Vetter * first by their zpos values, then by plane id (if zpos is equal). The plane 3701e4d84c6SDaniel Vetter * with lowest zpos value is at the bottom. The plane_state->normalized_zpos is 3711e4d84c6SDaniel Vetter * then filled with unique values from 0 to number of active planes in crtc 3721e4d84c6SDaniel Vetter * minus one. 37344d1240dSMarek Szyprowski * 37444d1240dSMarek Szyprowski * RETURNS 37544d1240dSMarek Szyprowski * Zero for success or -errno 37644d1240dSMarek Szyprowski */ 37752a9fcdaSDaniel Vetter int drm_atomic_normalize_zpos(struct drm_device *dev, 37844d1240dSMarek Szyprowski struct drm_atomic_state *state) 37944d1240dSMarek Szyprowski { 38044d1240dSMarek Szyprowski struct drm_crtc *crtc; 38144d1240dSMarek Szyprowski struct drm_crtc_state *crtc_state; 38244d1240dSMarek Szyprowski struct drm_plane *plane; 38344d1240dSMarek Szyprowski struct drm_plane_state *plane_state; 38444d1240dSMarek Szyprowski int i, ret = 0; 38544d1240dSMarek Szyprowski 38644d1240dSMarek Szyprowski for_each_plane_in_state(state, plane, plane_state, i) { 38744d1240dSMarek Szyprowski crtc = plane_state->crtc; 38844d1240dSMarek Szyprowski if (!crtc) 38944d1240dSMarek Szyprowski continue; 39044d1240dSMarek Szyprowski if (plane->state->zpos != plane_state->zpos) { 39144d1240dSMarek Szyprowski crtc_state = 39244d1240dSMarek Szyprowski drm_atomic_get_existing_crtc_state(state, crtc); 39344d1240dSMarek Szyprowski crtc_state->zpos_changed = true; 39444d1240dSMarek Szyprowski } 39544d1240dSMarek Szyprowski } 39644d1240dSMarek Szyprowski 39744d1240dSMarek Szyprowski for_each_crtc_in_state(state, crtc, crtc_state, i) { 39844d1240dSMarek Szyprowski if (crtc_state->plane_mask != crtc->state->plane_mask || 39944d1240dSMarek Szyprowski crtc_state->zpos_changed) { 40044d1240dSMarek Szyprowski ret = drm_atomic_helper_crtc_normalize_zpos(crtc, 40144d1240dSMarek Szyprowski crtc_state); 40244d1240dSMarek Szyprowski if (ret) 40344d1240dSMarek Szyprowski return ret; 40444d1240dSMarek Szyprowski } 40544d1240dSMarek Szyprowski } 40644d1240dSMarek Szyprowski return 0; 40744d1240dSMarek Szyprowski } 40852a9fcdaSDaniel Vetter EXPORT_SYMBOL(drm_atomic_normalize_zpos); 409