1e3adcf8fSFrançois Tigeot /* 2e3adcf8fSFrançois Tigeot * Copyright © 2008 Intel Corporation 3e3adcf8fSFrançois Tigeot * 4e3adcf8fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5e3adcf8fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6e3adcf8fSFrançois Tigeot * to deal in the Software without restriction, including without limitation 7e3adcf8fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e3adcf8fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9e3adcf8fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10e3adcf8fSFrançois Tigeot * 11e3adcf8fSFrançois Tigeot * The above copyright notice and this permission notice (including the next 12e3adcf8fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13e3adcf8fSFrançois Tigeot * Software. 14e3adcf8fSFrançois Tigeot * 15e3adcf8fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16e3adcf8fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17e3adcf8fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18e3adcf8fSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19e3adcf8fSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20e3adcf8fSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21e3adcf8fSFrançois Tigeot * IN THE SOFTWARE. 22e3adcf8fSFrançois Tigeot * 23e3adcf8fSFrançois Tigeot * Authors: 24e3adcf8fSFrançois Tigeot * Eric Anholt <eric@anholt.net> 25e3adcf8fSFrançois Tigeot * 26e3adcf8fSFrançois Tigeot */ 27e3adcf8fSFrançois Tigeot 281487f786SFrançois Tigeot #include <linux/string.h> 29e3440f96SFrançois Tigeot #include <linux/bitops.h> 3018e26a6dSFrançois Tigeot #include <drm/drmP.h> 315c6c6f23SFrançois Tigeot #include <drm/i915_drm.h> 32e3adcf8fSFrançois Tigeot #include "i915_drv.h" 33e3adcf8fSFrançois Tigeot 34e3adcf8fSFrançois Tigeot /** 35a05eeebfSFrançois Tigeot * DOC: buffer object tiling 361b13d190SFrançois Tigeot * 37a05eeebfSFrançois Tigeot * i915_gem_set_tiling() and i915_gem_get_tiling() is the userspace interface to 38a05eeebfSFrançois Tigeot * declare fence register requirements. 39e3adcf8fSFrançois Tigeot * 40a05eeebfSFrançois Tigeot * In principle GEM doesn't care at all about the internal data layout of an 41a05eeebfSFrançois Tigeot * object, and hence it also doesn't care about tiling or swizzling. There's two 42a05eeebfSFrançois Tigeot * exceptions: 43e3adcf8fSFrançois Tigeot * 44a05eeebfSFrançois Tigeot * - For X and Y tiling the hardware provides detilers for CPU access, so called 45a05eeebfSFrançois Tigeot * fences. Since there's only a limited amount of them the kernel must manage 46a05eeebfSFrançois Tigeot * these, and therefore userspace must tell the kernel the object tiling if it 47a05eeebfSFrançois Tigeot * wants to use fences for detiling. 48a05eeebfSFrançois Tigeot * - On gen3 and gen4 platforms have a swizzling pattern for tiled objects which 49a05eeebfSFrançois Tigeot * depends upon the physical page frame number. When swapping such objects the 50a05eeebfSFrançois Tigeot * page frame number might change and the kernel must be able to fix this up 51a05eeebfSFrançois Tigeot * and hence now the tiling. Note that on a subset of platforms with 52a05eeebfSFrançois Tigeot * asymmetric memory channel population the swizzling pattern changes in an 53a05eeebfSFrançois Tigeot * unknown way, and for those the kernel simply forbids swapping completely. 54a05eeebfSFrançois Tigeot * 55a05eeebfSFrançois Tigeot * Since neither of this applies for new tiling layouts on modern platforms like 56a05eeebfSFrançois Tigeot * W, Ys and Yf tiling GEM only allows object tiling to be set to X or Y tiled. 57a05eeebfSFrançois Tigeot * Anything else can be handled in userspace entirely without the kernel's 58a05eeebfSFrançois Tigeot * invovlement. 59e3adcf8fSFrançois Tigeot */ 60e3adcf8fSFrançois Tigeot 61e3adcf8fSFrançois Tigeot /* Check pitch constriants for all chips & tiling formats */ 62e3adcf8fSFrançois Tigeot static bool 63e3adcf8fSFrançois Tigeot i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) 64e3adcf8fSFrançois Tigeot { 65e3adcf8fSFrançois Tigeot int tile_width; 66e3adcf8fSFrançois Tigeot 67e3adcf8fSFrançois Tigeot /* Linear is always fine */ 68e3adcf8fSFrançois Tigeot if (tiling_mode == I915_TILING_NONE) 69e9243325SFrançois Tigeot return true; 70e3adcf8fSFrançois Tigeot 71e3adcf8fSFrançois Tigeot if (IS_GEN2(dev) || 72e3adcf8fSFrançois Tigeot (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) 73e3adcf8fSFrançois Tigeot tile_width = 128; 74e3adcf8fSFrançois Tigeot else 75e3adcf8fSFrançois Tigeot tile_width = 512; 76e3adcf8fSFrançois Tigeot 77e3adcf8fSFrançois Tigeot /* check maximum stride & object size */ 788e26cdf6SFrançois Tigeot /* i965+ stores the end address of the gtt mapping in the fence 79e3adcf8fSFrançois Tigeot * reg, so dont bother to check the size */ 808e26cdf6SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 7) { 818e26cdf6SFrançois Tigeot if (stride / 128 > GEN7_FENCE_MAX_PITCH_VAL) 828e26cdf6SFrançois Tigeot return false; 838e26cdf6SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 4) { 84e3adcf8fSFrançois Tigeot if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) 85e9243325SFrançois Tigeot return false; 86e3adcf8fSFrançois Tigeot } else { 87e3adcf8fSFrançois Tigeot if (stride > 8192) 88e9243325SFrançois Tigeot return false; 89e3adcf8fSFrançois Tigeot 90e3adcf8fSFrançois Tigeot if (IS_GEN3(dev)) { 91e3adcf8fSFrançois Tigeot if (size > I830_FENCE_MAX_SIZE_VAL << 20) 92e9243325SFrançois Tigeot return false; 93e3adcf8fSFrançois Tigeot } else { 94e3adcf8fSFrançois Tigeot if (size > I830_FENCE_MAX_SIZE_VAL << 19) 95e9243325SFrançois Tigeot return false; 96e3adcf8fSFrançois Tigeot } 97e3adcf8fSFrançois Tigeot } 98e3adcf8fSFrançois Tigeot 998e26cdf6SFrançois Tigeot if (stride < tile_width) 1008e26cdf6SFrançois Tigeot return false; 1018e26cdf6SFrançois Tigeot 102e3adcf8fSFrançois Tigeot /* 965+ just needs multiples of tile width */ 103e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) { 104e3adcf8fSFrançois Tigeot if (stride & (tile_width - 1)) 105e9243325SFrançois Tigeot return false; 106e9243325SFrançois Tigeot return true; 107e3adcf8fSFrançois Tigeot } 108e3adcf8fSFrançois Tigeot 109e3adcf8fSFrançois Tigeot /* Pre-965 needs power of two tile widths */ 110e3adcf8fSFrançois Tigeot if (stride & (stride - 1)) 111e9243325SFrançois Tigeot return false; 112e3adcf8fSFrançois Tigeot 113e9243325SFrançois Tigeot return true; 114e3adcf8fSFrançois Tigeot } 115e3adcf8fSFrançois Tigeot 116e3adcf8fSFrançois Tigeot /* Is the current GTT allocation valid for the change in tiling? */ 117e3adcf8fSFrançois Tigeot static bool 118e3adcf8fSFrançois Tigeot i915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode) 119e3adcf8fSFrançois Tigeot { 120e3adcf8fSFrançois Tigeot u32 size; 121e3adcf8fSFrançois Tigeot 122e3adcf8fSFrançois Tigeot if (tiling_mode == I915_TILING_NONE) 123e9243325SFrançois Tigeot return true; 124e3adcf8fSFrançois Tigeot 125e3adcf8fSFrançois Tigeot if (INTEL_INFO(obj->base.dev)->gen >= 4) 126e9243325SFrançois Tigeot return true; 127e3adcf8fSFrançois Tigeot 1281487f786SFrançois Tigeot if (IS_GEN3(obj->base.dev)) { 1299edbd4a0SFrançois Tigeot if (i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK) 130e9243325SFrançois Tigeot return false; 131e3adcf8fSFrançois Tigeot } else { 1329edbd4a0SFrançois Tigeot if (i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK) 133e9243325SFrançois Tigeot return false; 134e3adcf8fSFrançois Tigeot } 135e3adcf8fSFrançois Tigeot 136a2fdbec6SFrançois Tigeot size = i915_gem_get_gtt_size(obj->base.dev, obj->base.size, tiling_mode); 1379edbd4a0SFrançois Tigeot if (i915_gem_obj_ggtt_size(obj) != size) 138e9243325SFrançois Tigeot return false; 139e3adcf8fSFrançois Tigeot 1409edbd4a0SFrançois Tigeot if (i915_gem_obj_ggtt_offset(obj) & (size - 1)) 141e9243325SFrançois Tigeot return false; 142e3adcf8fSFrançois Tigeot 143e9243325SFrançois Tigeot return true; 144e3adcf8fSFrançois Tigeot } 145e3adcf8fSFrançois Tigeot 146e3adcf8fSFrançois Tigeot /** 147a05eeebfSFrançois Tigeot * i915_gem_set_tiling - IOCTL handler to set tiling mode 148a05eeebfSFrançois Tigeot * @dev: DRM device 149a05eeebfSFrançois Tigeot * @data: data pointer for the ioctl 150a05eeebfSFrançois Tigeot * @file: DRM file for the ioctl call 151a05eeebfSFrançois Tigeot * 152e3adcf8fSFrançois Tigeot * Sets the tiling mode of an object, returning the required swizzling of 153e3adcf8fSFrançois Tigeot * bit 6 of addresses in the object. 154a05eeebfSFrançois Tigeot * 155a05eeebfSFrançois Tigeot * Called by the user via ioctl. 156a05eeebfSFrançois Tigeot * 157a05eeebfSFrançois Tigeot * Returns: 158a05eeebfSFrançois Tigeot * Zero on success, negative errno on failure. 159e3adcf8fSFrançois Tigeot */ 160e3adcf8fSFrançois Tigeot int 161e3adcf8fSFrançois Tigeot i915_gem_set_tiling(struct drm_device *dev, void *data, 162e3adcf8fSFrançois Tigeot struct drm_file *file) 163e3adcf8fSFrançois Tigeot { 164e3adcf8fSFrançois Tigeot struct drm_i915_gem_set_tiling *args = data; 165*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 166e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 167e9243325SFrançois Tigeot int ret = 0; 168e3adcf8fSFrançois Tigeot 1698621f407SFrançois Tigeot obj = to_intel_bo(drm_gem_object_lookup(file, args->handle)); 170e3adcf8fSFrançois Tigeot if (&obj->base == NULL) 171e3adcf8fSFrançois Tigeot return -ENOENT; 172e3adcf8fSFrançois Tigeot 173e3adcf8fSFrançois Tigeot if (!i915_tiling_ok(dev, 174e3adcf8fSFrançois Tigeot args->stride, obj->base.size, args->tiling_mode)) { 175f192107fSFrançois Tigeot drm_gem_object_unreference_unlocked(&obj->base); 176e3adcf8fSFrançois Tigeot return -EINVAL; 177e3adcf8fSFrançois Tigeot } 178e3adcf8fSFrançois Tigeot 179aee94f86SFrançois Tigeot intel_runtime_pm_get(dev_priv); 180aee94f86SFrançois Tigeot 1812c9916cdSFrançois Tigeot mutex_lock(&dev->struct_mutex); 18219c468b4SFrançois Tigeot if (obj->pin_display || obj->framebuffer_references) { 1832c9916cdSFrançois Tigeot ret = -EBUSY; 1842c9916cdSFrançois Tigeot goto err; 185e3adcf8fSFrançois Tigeot } 186e3adcf8fSFrançois Tigeot 187e3adcf8fSFrançois Tigeot if (args->tiling_mode == I915_TILING_NONE) { 188e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 189e3adcf8fSFrançois Tigeot args->stride = 0; 190e3adcf8fSFrançois Tigeot } else { 191e3adcf8fSFrançois Tigeot if (args->tiling_mode == I915_TILING_X) 192e3adcf8fSFrançois Tigeot args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x; 193e3adcf8fSFrançois Tigeot else 194e3adcf8fSFrançois Tigeot args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y; 195e3adcf8fSFrançois Tigeot 196e3adcf8fSFrançois Tigeot /* Hide bit 17 swizzling from the user. This prevents old Mesa 197e3adcf8fSFrançois Tigeot * from aborting the application on sw fallbacks to bit 17, 198e3adcf8fSFrançois Tigeot * and we use the pread/pwrite bit17 paths to swizzle for it. 199e3adcf8fSFrançois Tigeot * If there was a user that was relying on the swizzle 200e3adcf8fSFrançois Tigeot * information for drm_intel_bo_map()ed reads/writes this would 201e3adcf8fSFrançois Tigeot * break it, but we don't have any of those. 202e3adcf8fSFrançois Tigeot */ 203e3adcf8fSFrançois Tigeot if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17) 204e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_9; 205e3adcf8fSFrançois Tigeot if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) 206e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10; 207e3adcf8fSFrançois Tigeot 208e3adcf8fSFrançois Tigeot /* If we can't handle the swizzling, make it untiled. */ 209e3adcf8fSFrançois Tigeot if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) { 210e3adcf8fSFrançois Tigeot args->tiling_mode = I915_TILING_NONE; 211e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 212e3adcf8fSFrançois Tigeot args->stride = 0; 213e3adcf8fSFrançois Tigeot } 214e3adcf8fSFrançois Tigeot } 215e3adcf8fSFrançois Tigeot 216e3adcf8fSFrançois Tigeot if (args->tiling_mode != obj->tiling_mode || 217e3adcf8fSFrançois Tigeot args->stride != obj->stride) { 218e3adcf8fSFrançois Tigeot /* We need to rebind the object if its current allocation 219e3adcf8fSFrançois Tigeot * no longer meets the alignment restrictions for its new 220e3adcf8fSFrançois Tigeot * tiling mode. Otherwise we can just leave it alone, but 221e3440f96SFrançois Tigeot * need to ensure that any fence register is updated before 222e3440f96SFrançois Tigeot * the next fenced (either through the GTT or by the BLT unit 223e3440f96SFrançois Tigeot * on older GPUs) access. 224e9243325SFrançois Tigeot * 225e9243325SFrançois Tigeot * After updating the tiling parameters, we then flag whether 226e9243325SFrançois Tigeot * we need to update an associated fence register. Note this 227e9243325SFrançois Tigeot * has to also include the unfenced register the GPU uses 228e9243325SFrançois Tigeot * whilst executing a fenced command for an untiled object. 229e3adcf8fSFrançois Tigeot */ 2301b13d190SFrançois Tigeot if (obj->map_and_fenceable && 2311b13d190SFrançois Tigeot !i915_gem_object_fence_ok(obj, args->tiling_mode)) 2321487f786SFrançois Tigeot ret = i915_vma_unbind(i915_gem_obj_to_ggtt(obj)); 233f192107fSFrançois Tigeot 234e3adcf8fSFrançois Tigeot if (ret == 0) { 2352c9916cdSFrançois Tigeot if (obj->pages && 2362c9916cdSFrançois Tigeot obj->madv == I915_MADV_WILLNEED && 2372c9916cdSFrançois Tigeot dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { 2382c9916cdSFrançois Tigeot if (args->tiling_mode == I915_TILING_NONE) 2392c9916cdSFrançois Tigeot i915_gem_object_unpin_pages(obj); 2402c9916cdSFrançois Tigeot if (obj->tiling_mode == I915_TILING_NONE) 2412c9916cdSFrançois Tigeot i915_gem_object_pin_pages(obj); 2422c9916cdSFrançois Tigeot } 2432c9916cdSFrançois Tigeot 244f192107fSFrançois Tigeot obj->fence_dirty = 2452c9916cdSFrançois Tigeot obj->last_fenced_req || 246f192107fSFrançois Tigeot obj->fence_reg != I915_FENCE_REG_NONE; 247f192107fSFrançois Tigeot 248e3adcf8fSFrançois Tigeot obj->tiling_mode = args->tiling_mode; 249e3adcf8fSFrançois Tigeot obj->stride = args->stride; 250e3440f96SFrançois Tigeot 251e3440f96SFrançois Tigeot /* Force the fence to be reacquired for GTT access */ 252e3440f96SFrançois Tigeot i915_gem_release_mmap(obj); 253e3adcf8fSFrançois Tigeot } 254e3adcf8fSFrançois Tigeot } 255e3adcf8fSFrançois Tigeot /* we have to maintain this existing ABI... */ 256e3adcf8fSFrançois Tigeot args->stride = obj->stride; 257e3adcf8fSFrançois Tigeot args->tiling_mode = obj->tiling_mode; 258a2fdbec6SFrançois Tigeot 259a2fdbec6SFrançois Tigeot /* Try to preallocate memory required to save swizzling on put-pages */ 260a2fdbec6SFrançois Tigeot if (i915_gem_object_needs_bit17_swizzle(obj)) { 261a2fdbec6SFrançois Tigeot if (obj->bit_17 == NULL) { 26222ee5efbSFrançois Tigeot obj->bit_17 = kcalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT), 26322ee5efbSFrançois Tigeot sizeof(long), GFP_KERNEL); 264a2fdbec6SFrançois Tigeot } 265a2fdbec6SFrançois Tigeot } else { 2669edbd4a0SFrançois Tigeot kfree(obj->bit_17); 267a2fdbec6SFrançois Tigeot obj->bit_17 = NULL; 268a2fdbec6SFrançois Tigeot } 269a2fdbec6SFrançois Tigeot 2702c9916cdSFrançois Tigeot err: 271e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 272a2fdbec6SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 273e3adcf8fSFrançois Tigeot 274aee94f86SFrançois Tigeot intel_runtime_pm_put(dev_priv); 275aee94f86SFrançois Tigeot 276e9243325SFrançois Tigeot return ret; 277e3adcf8fSFrançois Tigeot } 278e3adcf8fSFrançois Tigeot 279e3adcf8fSFrançois Tigeot /** 280a05eeebfSFrançois Tigeot * i915_gem_get_tiling - IOCTL handler to get tiling mode 281a05eeebfSFrançois Tigeot * @dev: DRM device 282a05eeebfSFrançois Tigeot * @data: data pointer for the ioctl 283a05eeebfSFrançois Tigeot * @file: DRM file for the ioctl call 284a05eeebfSFrançois Tigeot * 285e3adcf8fSFrançois Tigeot * Returns the current tiling mode and required bit 6 swizzling for the object. 286a05eeebfSFrançois Tigeot * 287a05eeebfSFrançois Tigeot * Called by the user via ioctl. 288a05eeebfSFrançois Tigeot * 289a05eeebfSFrançois Tigeot * Returns: 290a05eeebfSFrançois Tigeot * Zero on success, negative errno on failure. 291e3adcf8fSFrançois Tigeot */ 292e3adcf8fSFrançois Tigeot int 293e3adcf8fSFrançois Tigeot i915_gem_get_tiling(struct drm_device *dev, void *data, 294e3adcf8fSFrançois Tigeot struct drm_file *file) 295e3adcf8fSFrançois Tigeot { 296e3adcf8fSFrançois Tigeot struct drm_i915_gem_get_tiling *args = data; 297*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 298e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 299e3adcf8fSFrançois Tigeot 3008621f407SFrançois Tigeot obj = to_intel_bo(drm_gem_object_lookup(file, args->handle)); 301e3adcf8fSFrançois Tigeot if (&obj->base == NULL) 302e3adcf8fSFrançois Tigeot return -ENOENT; 303e3adcf8fSFrançois Tigeot 304a2fdbec6SFrançois Tigeot mutex_lock(&dev->struct_mutex); 305283d6aceSFrançois Tigeot 306e3adcf8fSFrançois Tigeot args->tiling_mode = obj->tiling_mode; 307e3adcf8fSFrançois Tigeot switch (obj->tiling_mode) { 308e3adcf8fSFrançois Tigeot case I915_TILING_X: 309e3adcf8fSFrançois Tigeot args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x; 310e3adcf8fSFrançois Tigeot break; 311e3adcf8fSFrançois Tigeot case I915_TILING_Y: 312e3adcf8fSFrançois Tigeot args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y; 313e3adcf8fSFrançois Tigeot break; 314e3adcf8fSFrançois Tigeot case I915_TILING_NONE: 315e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 316e3adcf8fSFrançois Tigeot break; 317e3adcf8fSFrançois Tigeot default: 318e3adcf8fSFrançois Tigeot DRM_ERROR("unknown tiling mode\n"); 319e3adcf8fSFrançois Tigeot } 320e3adcf8fSFrançois Tigeot 321e3adcf8fSFrançois Tigeot /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ 32219c468b4SFrançois Tigeot if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) 32319c468b4SFrançois Tigeot args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN; 32419c468b4SFrançois Tigeot else 3252c9916cdSFrançois Tigeot args->phys_swizzle_mode = args->swizzle_mode; 326e3adcf8fSFrançois Tigeot if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17) 327e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_9; 328e3adcf8fSFrançois Tigeot if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) 329e3adcf8fSFrançois Tigeot args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10; 330e3adcf8fSFrançois Tigeot 331e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 332a2fdbec6SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 333e3adcf8fSFrançois Tigeot 334e3adcf8fSFrançois Tigeot return 0; 335e3adcf8fSFrançois Tigeot } 336