1e3adcf8fSFrançois Tigeot /* 2e3adcf8fSFrançois Tigeot * Copyright © 2011 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 FROM, 20e3adcf8fSFrançois Tigeot * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21e3adcf8fSFrançois Tigeot * SOFTWARE. 22e3adcf8fSFrançois Tigeot * 23e3adcf8fSFrançois Tigeot * Authors: 24e3adcf8fSFrançois Tigeot * Jesse Barnes <jbarnes@virtuousgeek.org> 25e3adcf8fSFrançois Tigeot * 26e3adcf8fSFrançois Tigeot * New plane/sprite handling. 27e3adcf8fSFrançois Tigeot * 28e3adcf8fSFrançois Tigeot * The older chips had a separate interface for programming plane related 29e3adcf8fSFrançois Tigeot * registers; newer ones are much simpler and we can use the new DRM plane 30e3adcf8fSFrançois Tigeot * support. 31e3adcf8fSFrançois Tigeot * 32e3adcf8fSFrançois Tigeot * $FreeBSD: src/sys/dev/drm2/i915/intel_sprite.c,v 1.1 2012/05/22 11:07:44 kib Exp $ 33e3adcf8fSFrançois Tigeot */ 34e3adcf8fSFrançois Tigeot 3518e26a6dSFrançois Tigeot #include <drm/drmP.h> 3618e26a6dSFrançois Tigeot #include <drm/drm_crtc.h> 3718e26a6dSFrançois Tigeot #include <uapi_drm/drm_fourcc.h> 3818e26a6dSFrançois Tigeot #include "intel_drv.h" 395c6c6f23SFrançois Tigeot #include <drm/i915_drm.h> 40e3adcf8fSFrançois Tigeot #include "i915_drv.h" 41e3adcf8fSFrançois Tigeot 42e3adcf8fSFrançois Tigeot static void 43e3adcf8fSFrançois Tigeot ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, 44e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 45e3adcf8fSFrançois Tigeot unsigned int crtc_w, unsigned int crtc_h, 46e3adcf8fSFrançois Tigeot uint32_t x, uint32_t y, 47e3adcf8fSFrançois Tigeot uint32_t src_w, uint32_t src_h) 48e3adcf8fSFrançois Tigeot { 49e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 50e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 51e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 52e3adcf8fSFrançois Tigeot int pipe = intel_plane->pipe; 53e3adcf8fSFrançois Tigeot u32 sprctl, sprscale = 0; 54e3adcf8fSFrançois Tigeot int pixel_size; 55e3adcf8fSFrançois Tigeot 56e3adcf8fSFrançois Tigeot sprctl = I915_READ(SPRCTL(pipe)); 57e3adcf8fSFrançois Tigeot 58e3adcf8fSFrançois Tigeot /* Mask out pixel format bits in case we change it */ 59e3adcf8fSFrançois Tigeot sprctl &= ~SPRITE_PIXFORMAT_MASK; 60e3adcf8fSFrançois Tigeot sprctl &= ~SPRITE_RGB_ORDER_RGBX; 61e3adcf8fSFrançois Tigeot sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; 62e3adcf8fSFrançois Tigeot 63e3adcf8fSFrançois Tigeot switch (fb->pixel_format) { 64e3adcf8fSFrançois Tigeot case DRM_FORMAT_XBGR8888: 65e3adcf8fSFrançois Tigeot sprctl |= SPRITE_FORMAT_RGBX888; 66e3adcf8fSFrançois Tigeot pixel_size = 4; 67e3adcf8fSFrançois Tigeot break; 68e3adcf8fSFrançois Tigeot case DRM_FORMAT_XRGB8888: 69e3adcf8fSFrançois Tigeot sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; 70e3adcf8fSFrançois Tigeot pixel_size = 4; 71e3adcf8fSFrançois Tigeot break; 72e3adcf8fSFrançois Tigeot case DRM_FORMAT_YUYV: 73e3adcf8fSFrançois Tigeot sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; 74e3adcf8fSFrançois Tigeot pixel_size = 2; 75e3adcf8fSFrançois Tigeot break; 76e3adcf8fSFrançois Tigeot case DRM_FORMAT_YVYU: 77e3adcf8fSFrançois Tigeot sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; 78e3adcf8fSFrançois Tigeot pixel_size = 2; 79e3adcf8fSFrançois Tigeot break; 80e3adcf8fSFrançois Tigeot case DRM_FORMAT_UYVY: 81e3adcf8fSFrançois Tigeot sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; 82e3adcf8fSFrançois Tigeot pixel_size = 2; 83e3adcf8fSFrançois Tigeot break; 84e3adcf8fSFrançois Tigeot case DRM_FORMAT_VYUY: 85e3adcf8fSFrançois Tigeot sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; 86e3adcf8fSFrançois Tigeot pixel_size = 2; 87e3adcf8fSFrançois Tigeot break; 88e3adcf8fSFrançois Tigeot default: 89e3adcf8fSFrançois Tigeot DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); 90e3adcf8fSFrançois Tigeot sprctl |= DVS_FORMAT_RGBX888; 91e3adcf8fSFrançois Tigeot pixel_size = 4; 92e3adcf8fSFrançois Tigeot break; 93e3adcf8fSFrançois Tigeot } 94e3adcf8fSFrançois Tigeot 95e3adcf8fSFrançois Tigeot if (obj->tiling_mode != I915_TILING_NONE) 96e3adcf8fSFrançois Tigeot sprctl |= SPRITE_TILED; 97e3adcf8fSFrançois Tigeot 98e3adcf8fSFrançois Tigeot /* must disable */ 99e3adcf8fSFrançois Tigeot sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 100e3adcf8fSFrançois Tigeot sprctl |= SPRITE_ENABLE; 101e3adcf8fSFrançois Tigeot 102e3adcf8fSFrançois Tigeot /* Sizes are 0 based */ 103e3adcf8fSFrançois Tigeot src_w--; 104e3adcf8fSFrançois Tigeot src_h--; 105e3adcf8fSFrançois Tigeot crtc_w--; 106e3adcf8fSFrançois Tigeot crtc_h--; 107e3adcf8fSFrançois Tigeot 108e3adcf8fSFrançois Tigeot intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); 109e3adcf8fSFrançois Tigeot 110e3adcf8fSFrançois Tigeot /* 111e3adcf8fSFrançois Tigeot * IVB workaround: must disable low power watermarks for at least 112e3adcf8fSFrançois Tigeot * one frame before enabling scaling. LP watermarks can be re-enabled 113e3adcf8fSFrançois Tigeot * when scaling is disabled. 114e3adcf8fSFrançois Tigeot */ 115e3adcf8fSFrançois Tigeot if (crtc_w != src_w || crtc_h != src_h) { 116e3adcf8fSFrançois Tigeot dev_priv->sprite_scaling_enabled = true; 117e3adcf8fSFrançois Tigeot sandybridge_update_wm(dev); 118e3adcf8fSFrançois Tigeot intel_wait_for_vblank(dev, pipe); 119e3adcf8fSFrançois Tigeot sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; 120e3adcf8fSFrançois Tigeot } else { 121e3adcf8fSFrançois Tigeot dev_priv->sprite_scaling_enabled = false; 122e3adcf8fSFrançois Tigeot /* potentially re-enable LP watermarks */ 123e3adcf8fSFrançois Tigeot sandybridge_update_wm(dev); 124e3adcf8fSFrançois Tigeot } 125e3adcf8fSFrançois Tigeot 126e3adcf8fSFrançois Tigeot I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); 127e3adcf8fSFrançois Tigeot I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); 128e3adcf8fSFrançois Tigeot if (obj->tiling_mode != I915_TILING_NONE) { 129e3adcf8fSFrançois Tigeot I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); 130e3adcf8fSFrançois Tigeot } else { 131e3adcf8fSFrançois Tigeot unsigned long offset; 132e3adcf8fSFrançois Tigeot 133e3adcf8fSFrançois Tigeot offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); 134e3adcf8fSFrançois Tigeot I915_WRITE(SPRLINOFF(pipe), offset); 135e3adcf8fSFrançois Tigeot } 136e3adcf8fSFrançois Tigeot I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); 137e3adcf8fSFrançois Tigeot I915_WRITE(SPRSCALE(pipe), sprscale); 138e3adcf8fSFrançois Tigeot I915_WRITE(SPRCTL(pipe), sprctl); 139e3adcf8fSFrançois Tigeot I915_WRITE(SPRSURF(pipe), obj->gtt_offset); 140e3adcf8fSFrançois Tigeot POSTING_READ(SPRSURF(pipe)); 141e3adcf8fSFrançois Tigeot } 142e3adcf8fSFrançois Tigeot 143e3adcf8fSFrançois Tigeot static void 144e3adcf8fSFrançois Tigeot ivb_disable_plane(struct drm_plane *plane) 145e3adcf8fSFrançois Tigeot { 146e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 147e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 148e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 149e3adcf8fSFrançois Tigeot int pipe = intel_plane->pipe; 150e3adcf8fSFrançois Tigeot 151e3adcf8fSFrançois Tigeot I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); 152e3adcf8fSFrançois Tigeot /* Can't leave the scaler enabled... */ 153e3adcf8fSFrançois Tigeot I915_WRITE(SPRSCALE(pipe), 0); 154e3adcf8fSFrançois Tigeot /* Activate double buffered register update */ 155e3adcf8fSFrançois Tigeot I915_WRITE(SPRSURF(pipe), 0); 156e3adcf8fSFrançois Tigeot POSTING_READ(SPRSURF(pipe)); 157e3adcf8fSFrançois Tigeot } 158e3adcf8fSFrançois Tigeot 159e3adcf8fSFrançois Tigeot static int 160e3adcf8fSFrançois Tigeot ivb_update_colorkey(struct drm_plane *plane, 161e3adcf8fSFrançois Tigeot struct drm_intel_sprite_colorkey *key) 162e3adcf8fSFrançois Tigeot { 163e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 164e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 165e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 166e3adcf8fSFrançois Tigeot u32 sprctl; 167e3adcf8fSFrançois Tigeot int ret = 0; 168e3adcf8fSFrançois Tigeot 169e3adcf8fSFrançois Tigeot intel_plane = to_intel_plane(plane); 170e3adcf8fSFrançois Tigeot 171e3adcf8fSFrançois Tigeot I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value); 172e3adcf8fSFrançois Tigeot I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value); 173e3adcf8fSFrançois Tigeot I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask); 174e3adcf8fSFrançois Tigeot 175e3adcf8fSFrançois Tigeot sprctl = I915_READ(SPRCTL(intel_plane->pipe)); 176e3adcf8fSFrançois Tigeot sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY); 177e3adcf8fSFrançois Tigeot if (key->flags & I915_SET_COLORKEY_DESTINATION) 178e3adcf8fSFrançois Tigeot sprctl |= SPRITE_DEST_KEY; 179e3adcf8fSFrançois Tigeot else if (key->flags & I915_SET_COLORKEY_SOURCE) 180e3adcf8fSFrançois Tigeot sprctl |= SPRITE_SOURCE_KEY; 181e3adcf8fSFrançois Tigeot I915_WRITE(SPRCTL(intel_plane->pipe), sprctl); 182e3adcf8fSFrançois Tigeot 183e3adcf8fSFrançois Tigeot POSTING_READ(SPRKEYMSK(intel_plane->pipe)); 184e3adcf8fSFrançois Tigeot 185e3adcf8fSFrançois Tigeot return ret; 186e3adcf8fSFrançois Tigeot } 187e3adcf8fSFrançois Tigeot 188e3adcf8fSFrançois Tigeot static void 189e3adcf8fSFrançois Tigeot ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) 190e3adcf8fSFrançois Tigeot { 191e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 192e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 193e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 194e3adcf8fSFrançois Tigeot u32 sprctl; 195e3adcf8fSFrançois Tigeot 196e3adcf8fSFrançois Tigeot intel_plane = to_intel_plane(plane); 197e3adcf8fSFrançois Tigeot 198e3adcf8fSFrançois Tigeot key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe)); 199e3adcf8fSFrançois Tigeot key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe)); 200e3adcf8fSFrançois Tigeot key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe)); 201e3adcf8fSFrançois Tigeot key->flags = 0; 202e3adcf8fSFrançois Tigeot 203e3adcf8fSFrançois Tigeot sprctl = I915_READ(SPRCTL(intel_plane->pipe)); 204e3adcf8fSFrançois Tigeot 205e3adcf8fSFrançois Tigeot if (sprctl & SPRITE_DEST_KEY) 206e3adcf8fSFrançois Tigeot key->flags = I915_SET_COLORKEY_DESTINATION; 207e3adcf8fSFrançois Tigeot else if (sprctl & SPRITE_SOURCE_KEY) 208e3adcf8fSFrançois Tigeot key->flags = I915_SET_COLORKEY_SOURCE; 209e3adcf8fSFrançois Tigeot else 210e3adcf8fSFrançois Tigeot key->flags = I915_SET_COLORKEY_NONE; 211e3adcf8fSFrançois Tigeot } 212e3adcf8fSFrançois Tigeot 213e3adcf8fSFrançois Tigeot static void 214e3adcf8fSFrançois Tigeot snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, 215e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 216e3adcf8fSFrançois Tigeot unsigned int crtc_w, unsigned int crtc_h, 217e3adcf8fSFrançois Tigeot uint32_t x, uint32_t y, 218e3adcf8fSFrançois Tigeot uint32_t src_w, uint32_t src_h) 219e3adcf8fSFrançois Tigeot { 220e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 221e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 222e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 223e3adcf8fSFrançois Tigeot int pipe = intel_plane->pipe, pixel_size; 224e3adcf8fSFrançois Tigeot u32 dvscntr, dvsscale = 0; 225e3adcf8fSFrançois Tigeot 226e3adcf8fSFrançois Tigeot dvscntr = I915_READ(DVSCNTR(pipe)); 227e3adcf8fSFrançois Tigeot 228e3adcf8fSFrançois Tigeot /* Mask out pixel format bits in case we change it */ 229e3adcf8fSFrançois Tigeot dvscntr &= ~DVS_PIXFORMAT_MASK; 230e3adcf8fSFrançois Tigeot dvscntr &= ~DVS_RGB_ORDER_XBGR; 231e3adcf8fSFrançois Tigeot dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; 232e3adcf8fSFrançois Tigeot 233e3adcf8fSFrançois Tigeot switch (fb->pixel_format) { 234e3adcf8fSFrançois Tigeot case DRM_FORMAT_XBGR8888: 235e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; 236e3adcf8fSFrançois Tigeot pixel_size = 4; 237e3adcf8fSFrançois Tigeot break; 238e3adcf8fSFrançois Tigeot case DRM_FORMAT_XRGB8888: 239e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_RGBX888; 240e3adcf8fSFrançois Tigeot pixel_size = 4; 241e3adcf8fSFrançois Tigeot break; 242e3adcf8fSFrançois Tigeot case DRM_FORMAT_YUYV: 243e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; 244e3adcf8fSFrançois Tigeot pixel_size = 2; 245e3adcf8fSFrançois Tigeot break; 246e3adcf8fSFrançois Tigeot case DRM_FORMAT_YVYU: 247e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; 248e3adcf8fSFrançois Tigeot pixel_size = 2; 249e3adcf8fSFrançois Tigeot break; 250e3adcf8fSFrançois Tigeot case DRM_FORMAT_UYVY: 251e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; 252e3adcf8fSFrançois Tigeot pixel_size = 2; 253e3adcf8fSFrançois Tigeot break; 254e3adcf8fSFrançois Tigeot case DRM_FORMAT_VYUY: 255e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; 256e3adcf8fSFrançois Tigeot pixel_size = 2; 257e3adcf8fSFrançois Tigeot break; 258e3adcf8fSFrançois Tigeot default: 259e3adcf8fSFrançois Tigeot DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); 260e3adcf8fSFrançois Tigeot dvscntr |= DVS_FORMAT_RGBX888; 261e3adcf8fSFrançois Tigeot pixel_size = 4; 262e3adcf8fSFrançois Tigeot break; 263e3adcf8fSFrançois Tigeot } 264e3adcf8fSFrançois Tigeot 265e3adcf8fSFrançois Tigeot if (obj->tiling_mode != I915_TILING_NONE) 266e3adcf8fSFrançois Tigeot dvscntr |= DVS_TILED; 267e3adcf8fSFrançois Tigeot 268e3adcf8fSFrançois Tigeot /* must disable */ 269e3adcf8fSFrançois Tigeot dvscntr |= DVS_TRICKLE_FEED_DISABLE; 270e3adcf8fSFrançois Tigeot dvscntr |= DVS_ENABLE; 271e3adcf8fSFrançois Tigeot 272e3adcf8fSFrançois Tigeot /* Sizes are 0 based */ 273e3adcf8fSFrançois Tigeot src_w--; 274e3adcf8fSFrançois Tigeot src_h--; 275e3adcf8fSFrançois Tigeot crtc_w--; 276e3adcf8fSFrançois Tigeot crtc_h--; 277e3adcf8fSFrançois Tigeot 278e3adcf8fSFrançois Tigeot intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); 279e3adcf8fSFrançois Tigeot 280e3adcf8fSFrançois Tigeot if (crtc_w != src_w || crtc_h != src_h) 281e3adcf8fSFrançois Tigeot dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; 282e3adcf8fSFrançois Tigeot 283e3adcf8fSFrançois Tigeot I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); 284e3adcf8fSFrançois Tigeot I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); 285e3adcf8fSFrançois Tigeot if (obj->tiling_mode != I915_TILING_NONE) { 286e3adcf8fSFrançois Tigeot I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); 287e3adcf8fSFrançois Tigeot } else { 288e3adcf8fSFrançois Tigeot unsigned long offset; 289e3adcf8fSFrançois Tigeot 290e3adcf8fSFrançois Tigeot offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); 291e3adcf8fSFrançois Tigeot I915_WRITE(DVSLINOFF(pipe), offset); 292e3adcf8fSFrançois Tigeot } 293e3adcf8fSFrançois Tigeot I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); 294e3adcf8fSFrançois Tigeot I915_WRITE(DVSSCALE(pipe), dvsscale); 295e3adcf8fSFrançois Tigeot I915_WRITE(DVSCNTR(pipe), dvscntr); 296e3adcf8fSFrançois Tigeot I915_WRITE(DVSSURF(pipe), obj->gtt_offset); 297e3adcf8fSFrançois Tigeot POSTING_READ(DVSSURF(pipe)); 298e3adcf8fSFrançois Tigeot } 299e3adcf8fSFrançois Tigeot 300e3adcf8fSFrançois Tigeot static void 301e3adcf8fSFrançois Tigeot snb_disable_plane(struct drm_plane *plane) 302e3adcf8fSFrançois Tigeot { 303e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 304e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 305e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 306e3adcf8fSFrançois Tigeot int pipe = intel_plane->pipe; 307e3adcf8fSFrançois Tigeot 308e3adcf8fSFrançois Tigeot I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE); 309e3adcf8fSFrançois Tigeot /* Disable the scaler */ 310e3adcf8fSFrançois Tigeot I915_WRITE(DVSSCALE(pipe), 0); 311e3adcf8fSFrançois Tigeot /* Flush double buffered register updates */ 312e3adcf8fSFrançois Tigeot I915_WRITE(DVSSURF(pipe), 0); 313e3adcf8fSFrançois Tigeot POSTING_READ(DVSSURF(pipe)); 314e3adcf8fSFrançois Tigeot } 315e3adcf8fSFrançois Tigeot 316e3adcf8fSFrançois Tigeot static void 317e3adcf8fSFrançois Tigeot intel_enable_primary(struct drm_crtc *crtc) 318e3adcf8fSFrançois Tigeot { 319e3adcf8fSFrançois Tigeot struct drm_device *dev = crtc->dev; 320e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 321e3adcf8fSFrançois Tigeot struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 322e3adcf8fSFrançois Tigeot int reg = DSPCNTR(intel_crtc->plane); 323e3adcf8fSFrançois Tigeot 324e3adcf8fSFrançois Tigeot I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); 325e3adcf8fSFrançois Tigeot } 326e3adcf8fSFrançois Tigeot 327e3adcf8fSFrançois Tigeot static void 328e3adcf8fSFrançois Tigeot intel_disable_primary(struct drm_crtc *crtc) 329e3adcf8fSFrançois Tigeot { 330e3adcf8fSFrançois Tigeot struct drm_device *dev = crtc->dev; 331e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 332e3adcf8fSFrançois Tigeot struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 333e3adcf8fSFrançois Tigeot int reg = DSPCNTR(intel_crtc->plane); 334e3adcf8fSFrançois Tigeot 335e3adcf8fSFrançois Tigeot I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); 336e3adcf8fSFrançois Tigeot } 337e3adcf8fSFrançois Tigeot 338e3adcf8fSFrançois Tigeot static int 339e3adcf8fSFrançois Tigeot snb_update_colorkey(struct drm_plane *plane, 340e3adcf8fSFrançois Tigeot struct drm_intel_sprite_colorkey *key) 341e3adcf8fSFrançois Tigeot { 342e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 343e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 344e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 345e3adcf8fSFrançois Tigeot u32 dvscntr; 346e3adcf8fSFrançois Tigeot int ret = 0; 347e3adcf8fSFrançois Tigeot 348e3adcf8fSFrançois Tigeot intel_plane = to_intel_plane(plane); 349e3adcf8fSFrançois Tigeot 350e3adcf8fSFrançois Tigeot I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value); 351e3adcf8fSFrançois Tigeot I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value); 352e3adcf8fSFrançois Tigeot I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask); 353e3adcf8fSFrançois Tigeot 354e3adcf8fSFrançois Tigeot dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); 355e3adcf8fSFrançois Tigeot dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY); 356e3adcf8fSFrançois Tigeot if (key->flags & I915_SET_COLORKEY_DESTINATION) 357e3adcf8fSFrançois Tigeot dvscntr |= DVS_DEST_KEY; 358e3adcf8fSFrançois Tigeot else if (key->flags & I915_SET_COLORKEY_SOURCE) 359e3adcf8fSFrançois Tigeot dvscntr |= DVS_SOURCE_KEY; 360e3adcf8fSFrançois Tigeot I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr); 361e3adcf8fSFrançois Tigeot 362e3adcf8fSFrançois Tigeot POSTING_READ(DVSKEYMSK(intel_plane->pipe)); 363e3adcf8fSFrançois Tigeot 364e3adcf8fSFrançois Tigeot return ret; 365e3adcf8fSFrançois Tigeot } 366e3adcf8fSFrançois Tigeot 367e3adcf8fSFrançois Tigeot static void 368e3adcf8fSFrançois Tigeot snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) 369e3adcf8fSFrançois Tigeot { 370e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 371e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 372e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 373e3adcf8fSFrançois Tigeot u32 dvscntr; 374e3adcf8fSFrançois Tigeot 375e3adcf8fSFrançois Tigeot intel_plane = to_intel_plane(plane); 376e3adcf8fSFrançois Tigeot 377e3adcf8fSFrançois Tigeot key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe)); 378e3adcf8fSFrançois Tigeot key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe)); 379e3adcf8fSFrançois Tigeot key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe)); 380e3adcf8fSFrançois Tigeot key->flags = 0; 381e3adcf8fSFrançois Tigeot 382e3adcf8fSFrançois Tigeot dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); 383e3adcf8fSFrançois Tigeot 384e3adcf8fSFrançois Tigeot if (dvscntr & DVS_DEST_KEY) 385e3adcf8fSFrançois Tigeot key->flags = I915_SET_COLORKEY_DESTINATION; 386e3adcf8fSFrançois Tigeot else if (dvscntr & DVS_SOURCE_KEY) 387e3adcf8fSFrançois Tigeot key->flags = I915_SET_COLORKEY_SOURCE; 388e3adcf8fSFrançois Tigeot else 389e3adcf8fSFrançois Tigeot key->flags = I915_SET_COLORKEY_NONE; 390e3adcf8fSFrançois Tigeot } 391e3adcf8fSFrançois Tigeot 392e3adcf8fSFrançois Tigeot static int 393e3adcf8fSFrançois Tigeot intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 394e3adcf8fSFrançois Tigeot struct drm_framebuffer *fb, int crtc_x, int crtc_y, 395e3adcf8fSFrançois Tigeot unsigned int crtc_w, unsigned int crtc_h, 396e3adcf8fSFrançois Tigeot uint32_t src_x, uint32_t src_y, 397e3adcf8fSFrançois Tigeot uint32_t src_w, uint32_t src_h) 398e3adcf8fSFrançois Tigeot { 399e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 400e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 401e3adcf8fSFrançois Tigeot struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 402e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 403e3adcf8fSFrançois Tigeot struct intel_framebuffer *intel_fb; 404e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj, *old_obj; 405e3adcf8fSFrançois Tigeot int pipe = intel_plane->pipe; 406e3adcf8fSFrançois Tigeot int ret = 0; 407e3adcf8fSFrançois Tigeot int x = src_x >> 16, y = src_y >> 16; 408e3adcf8fSFrançois Tigeot int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay; 409e3adcf8fSFrançois Tigeot bool disable_primary = false; 410e3adcf8fSFrançois Tigeot 411e3adcf8fSFrançois Tigeot intel_fb = to_intel_framebuffer(fb); 412e3adcf8fSFrançois Tigeot obj = intel_fb->obj; 413e3adcf8fSFrançois Tigeot 414e3adcf8fSFrançois Tigeot old_obj = intel_plane->obj; 415e3adcf8fSFrançois Tigeot 416e3adcf8fSFrançois Tigeot src_w = src_w >> 16; 417e3adcf8fSFrançois Tigeot src_h = src_h >> 16; 418e3adcf8fSFrançois Tigeot 419e3adcf8fSFrançois Tigeot /* Pipe must be running... */ 420e3adcf8fSFrançois Tigeot if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE)) 421e3adcf8fSFrançois Tigeot return -EINVAL; 422e3adcf8fSFrançois Tigeot 423e3adcf8fSFrançois Tigeot if (crtc_x >= primary_w || crtc_y >= primary_h) 424e3adcf8fSFrançois Tigeot return -EINVAL; 425e3adcf8fSFrançois Tigeot 426e3adcf8fSFrançois Tigeot /* Don't modify another pipe's plane */ 427e3adcf8fSFrançois Tigeot if (intel_plane->pipe != intel_crtc->pipe) 428e3adcf8fSFrançois Tigeot return -EINVAL; 429e3adcf8fSFrançois Tigeot 430e3adcf8fSFrançois Tigeot /* 431e3adcf8fSFrançois Tigeot * Clamp the width & height into the visible area. Note we don't 432e3adcf8fSFrançois Tigeot * try to scale the source if part of the visible region is offscreen. 433e3adcf8fSFrançois Tigeot * The caller must handle that by adjusting source offset and size. 434e3adcf8fSFrançois Tigeot */ 435e3adcf8fSFrançois Tigeot if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) { 436e3adcf8fSFrançois Tigeot crtc_w += crtc_x; 437e3adcf8fSFrançois Tigeot crtc_x = 0; 438e3adcf8fSFrançois Tigeot } 439e3adcf8fSFrançois Tigeot if ((crtc_x + crtc_w) <= 0) /* Nothing to display */ 440e3adcf8fSFrançois Tigeot goto out; 441e3adcf8fSFrançois Tigeot if ((crtc_x + crtc_w) > primary_w) 442e3adcf8fSFrançois Tigeot crtc_w = primary_w - crtc_x; 443e3adcf8fSFrançois Tigeot 444e3adcf8fSFrançois Tigeot if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) { 445e3adcf8fSFrançois Tigeot crtc_h += crtc_y; 446e3adcf8fSFrançois Tigeot crtc_y = 0; 447e3adcf8fSFrançois Tigeot } 448e3adcf8fSFrançois Tigeot if ((crtc_y + crtc_h) <= 0) /* Nothing to display */ 449e3adcf8fSFrançois Tigeot goto out; 450e3adcf8fSFrançois Tigeot if (crtc_y + crtc_h > primary_h) 451e3adcf8fSFrançois Tigeot crtc_h = primary_h - crtc_y; 452e3adcf8fSFrançois Tigeot 453e3adcf8fSFrançois Tigeot if (!crtc_w || !crtc_h) /* Again, nothing to display */ 454e3adcf8fSFrançois Tigeot goto out; 455e3adcf8fSFrançois Tigeot 456e3adcf8fSFrançois Tigeot /* 457e3adcf8fSFrançois Tigeot * We can take a larger source and scale it down, but 458e3adcf8fSFrançois Tigeot * only so much... 16x is the max on SNB. 459e3adcf8fSFrançois Tigeot */ 460e3adcf8fSFrançois Tigeot if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale) 461e3adcf8fSFrançois Tigeot return -EINVAL; 462e3adcf8fSFrançois Tigeot 463e3adcf8fSFrançois Tigeot /* 464e3adcf8fSFrançois Tigeot * If the sprite is completely covering the primary plane, 465e3adcf8fSFrançois Tigeot * we can disable the primary and save power. 466e3adcf8fSFrançois Tigeot */ 467e3adcf8fSFrançois Tigeot if ((crtc_x == 0) && (crtc_y == 0) && 468e3adcf8fSFrançois Tigeot (crtc_w == primary_w) && (crtc_h == primary_h)) 469e3adcf8fSFrançois Tigeot disable_primary = true; 470e3adcf8fSFrançois Tigeot 471e3adcf8fSFrançois Tigeot DRM_LOCK(dev); 472e3adcf8fSFrançois Tigeot 473e3adcf8fSFrançois Tigeot ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); 474e3adcf8fSFrançois Tigeot if (ret) 475e3adcf8fSFrançois Tigeot goto out_unlock; 476e3adcf8fSFrançois Tigeot 477e3adcf8fSFrançois Tigeot intel_plane->obj = obj; 478e3adcf8fSFrançois Tigeot 479e3adcf8fSFrançois Tigeot /* 480e3adcf8fSFrançois Tigeot * Be sure to re-enable the primary before the sprite is no longer 481e3adcf8fSFrançois Tigeot * covering it fully. 482e3adcf8fSFrançois Tigeot */ 483e3adcf8fSFrançois Tigeot if (!disable_primary && intel_plane->primary_disabled) { 484e3adcf8fSFrançois Tigeot intel_enable_primary(crtc); 485e3adcf8fSFrançois Tigeot intel_plane->primary_disabled = false; 486e3adcf8fSFrançois Tigeot } 487e3adcf8fSFrançois Tigeot 488e3adcf8fSFrançois Tigeot intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, 489e3adcf8fSFrançois Tigeot crtc_w, crtc_h, x, y, src_w, src_h); 490e3adcf8fSFrançois Tigeot 491e3adcf8fSFrançois Tigeot if (disable_primary) { 492e3adcf8fSFrançois Tigeot intel_disable_primary(crtc); 493e3adcf8fSFrançois Tigeot intel_plane->primary_disabled = true; 494e3adcf8fSFrançois Tigeot } 495e3adcf8fSFrançois Tigeot 496e3adcf8fSFrançois Tigeot /* Unpin old obj after new one is active to avoid ugliness */ 497e3adcf8fSFrançois Tigeot if (old_obj) { 498e3adcf8fSFrançois Tigeot /* 499e3adcf8fSFrançois Tigeot * It's fairly common to simply update the position of 500e3adcf8fSFrançois Tigeot * an existing object. In that case, we don't need to 501e3adcf8fSFrançois Tigeot * wait for vblank to avoid ugliness, we only need to 502e3adcf8fSFrançois Tigeot * do the pin & ref bookkeeping. 503e3adcf8fSFrançois Tigeot */ 504e3adcf8fSFrançois Tigeot if (old_obj != obj) { 505e3adcf8fSFrançois Tigeot DRM_UNLOCK(dev); 506e3adcf8fSFrançois Tigeot intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); 507e3adcf8fSFrançois Tigeot DRM_LOCK(dev); 508e3adcf8fSFrançois Tigeot } 509e3adcf8fSFrançois Tigeot intel_unpin_fb_obj(old_obj); 510e3adcf8fSFrançois Tigeot } 511e3adcf8fSFrançois Tigeot 512e3adcf8fSFrançois Tigeot out_unlock: 513e3adcf8fSFrançois Tigeot DRM_UNLOCK(dev); 514e3adcf8fSFrançois Tigeot out: 515e3adcf8fSFrançois Tigeot return ret; 516e3adcf8fSFrançois Tigeot } 517e3adcf8fSFrançois Tigeot 518e3adcf8fSFrançois Tigeot static int 519e3adcf8fSFrançois Tigeot intel_disable_plane(struct drm_plane *plane) 520e3adcf8fSFrançois Tigeot { 521e3adcf8fSFrançois Tigeot struct drm_device *dev = plane->dev; 522e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 523e3adcf8fSFrançois Tigeot int ret = 0; 524e3adcf8fSFrançois Tigeot 525e3adcf8fSFrançois Tigeot if (intel_plane->primary_disabled) { 526e3adcf8fSFrançois Tigeot intel_enable_primary(plane->crtc); 527e3adcf8fSFrançois Tigeot intel_plane->primary_disabled = false; 528e3adcf8fSFrançois Tigeot } 529e3adcf8fSFrançois Tigeot 530e3adcf8fSFrançois Tigeot intel_plane->disable_plane(plane); 531e3adcf8fSFrançois Tigeot 532e3adcf8fSFrançois Tigeot if (!intel_plane->obj) 533e3adcf8fSFrançois Tigeot goto out; 534e3adcf8fSFrançois Tigeot 535e3adcf8fSFrançois Tigeot DRM_LOCK(dev); 536e3adcf8fSFrançois Tigeot intel_unpin_fb_obj(intel_plane->obj); 537e3adcf8fSFrançois Tigeot intel_plane->obj = NULL; 538e3adcf8fSFrançois Tigeot DRM_UNLOCK(dev); 539e3adcf8fSFrançois Tigeot out: 540e3adcf8fSFrançois Tigeot 541e3adcf8fSFrançois Tigeot return ret; 542e3adcf8fSFrançois Tigeot } 543e3adcf8fSFrançois Tigeot 544e3adcf8fSFrançois Tigeot static void intel_destroy_plane(struct drm_plane *plane) 545e3adcf8fSFrançois Tigeot { 546e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane = to_intel_plane(plane); 547e3adcf8fSFrançois Tigeot intel_disable_plane(plane); 548e3adcf8fSFrançois Tigeot drm_plane_cleanup(plane); 549e3adcf8fSFrançois Tigeot drm_free(intel_plane, DRM_MEM_KMS); 550e3adcf8fSFrançois Tigeot } 551e3adcf8fSFrançois Tigeot 552e3adcf8fSFrançois Tigeot int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 553e3adcf8fSFrançois Tigeot struct drm_file *file_priv) 554e3adcf8fSFrançois Tigeot { 555e3adcf8fSFrançois Tigeot struct drm_intel_sprite_colorkey *set = data; 556e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 557e3adcf8fSFrançois Tigeot struct drm_mode_object *obj; 558e3adcf8fSFrançois Tigeot struct drm_plane *plane; 559e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 560e3adcf8fSFrançois Tigeot int ret = 0; 561e3adcf8fSFrançois Tigeot 562e3adcf8fSFrançois Tigeot if (!dev_priv) 563e3adcf8fSFrançois Tigeot return -EINVAL; 564e3adcf8fSFrançois Tigeot 565e3adcf8fSFrançois Tigeot /* Make sure we don't try to enable both src & dest simultaneously */ 566e3adcf8fSFrançois Tigeot if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) 567e3adcf8fSFrançois Tigeot return -EINVAL; 568e3adcf8fSFrançois Tigeot 569*af4b81b9SFrançois Tigeot lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 570e3adcf8fSFrançois Tigeot 571e3adcf8fSFrançois Tigeot obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); 572e3adcf8fSFrançois Tigeot if (!obj) { 573e3adcf8fSFrançois Tigeot ret = -EINVAL; 574e3adcf8fSFrançois Tigeot goto out_unlock; 575e3adcf8fSFrançois Tigeot } 576e3adcf8fSFrançois Tigeot 577e3adcf8fSFrançois Tigeot plane = obj_to_plane(obj); 578e3adcf8fSFrançois Tigeot intel_plane = to_intel_plane(plane); 579e3adcf8fSFrançois Tigeot ret = intel_plane->update_colorkey(plane, set); 580e3adcf8fSFrançois Tigeot 581e3adcf8fSFrançois Tigeot out_unlock: 582*af4b81b9SFrançois Tigeot lockmgr(&dev->mode_config.mutex, LK_RELEASE); 583e3adcf8fSFrançois Tigeot return ret; 584e3adcf8fSFrançois Tigeot } 585e3adcf8fSFrançois Tigeot 586e3adcf8fSFrançois Tigeot int intel_sprite_get_colorkey(struct drm_device *dev, void *data, 587e3adcf8fSFrançois Tigeot struct drm_file *file_priv) 588e3adcf8fSFrançois Tigeot { 589e3adcf8fSFrançois Tigeot struct drm_intel_sprite_colorkey *get = data; 590e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 591e3adcf8fSFrançois Tigeot struct drm_mode_object *obj; 592e3adcf8fSFrançois Tigeot struct drm_plane *plane; 593e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 594e3adcf8fSFrançois Tigeot int ret = 0; 595e3adcf8fSFrançois Tigeot 596e3adcf8fSFrançois Tigeot if (!dev_priv) 597e3adcf8fSFrançois Tigeot return -EINVAL; 598e3adcf8fSFrançois Tigeot 599*af4b81b9SFrançois Tigeot lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 600e3adcf8fSFrançois Tigeot 601e3adcf8fSFrançois Tigeot obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); 602e3adcf8fSFrançois Tigeot if (!obj) { 603e3adcf8fSFrançois Tigeot ret = -EINVAL; 604e3adcf8fSFrançois Tigeot goto out_unlock; 605e3adcf8fSFrançois Tigeot } 606e3adcf8fSFrançois Tigeot 607e3adcf8fSFrançois Tigeot plane = obj_to_plane(obj); 608e3adcf8fSFrançois Tigeot intel_plane = to_intel_plane(plane); 609e3adcf8fSFrançois Tigeot intel_plane->get_colorkey(plane, get); 610e3adcf8fSFrançois Tigeot 611e3adcf8fSFrançois Tigeot out_unlock: 612*af4b81b9SFrançois Tigeot lockmgr(&dev->mode_config.mutex, LK_RELEASE); 613e3adcf8fSFrançois Tigeot return ret; 614e3adcf8fSFrançois Tigeot } 615e3adcf8fSFrançois Tigeot 616e3adcf8fSFrançois Tigeot static const struct drm_plane_funcs intel_plane_funcs = { 617e3adcf8fSFrançois Tigeot .update_plane = intel_update_plane, 618e3adcf8fSFrançois Tigeot .disable_plane = intel_disable_plane, 619e3adcf8fSFrançois Tigeot .destroy = intel_destroy_plane, 620e3adcf8fSFrançois Tigeot }; 621e3adcf8fSFrançois Tigeot 622e3adcf8fSFrançois Tigeot static uint32_t snb_plane_formats[] = { 623e3adcf8fSFrançois Tigeot DRM_FORMAT_XBGR8888, 624e3adcf8fSFrançois Tigeot DRM_FORMAT_XRGB8888, 625e3adcf8fSFrançois Tigeot DRM_FORMAT_YUYV, 626e3adcf8fSFrançois Tigeot DRM_FORMAT_YVYU, 627e3adcf8fSFrançois Tigeot DRM_FORMAT_UYVY, 628e3adcf8fSFrançois Tigeot DRM_FORMAT_VYUY, 629e3adcf8fSFrançois Tigeot }; 630e3adcf8fSFrançois Tigeot 631e3adcf8fSFrançois Tigeot int 632e3adcf8fSFrançois Tigeot intel_plane_init(struct drm_device *dev, enum i915_pipe pipe) 633e3adcf8fSFrançois Tigeot { 634e3adcf8fSFrançois Tigeot struct intel_plane *intel_plane; 635e3adcf8fSFrançois Tigeot unsigned long possible_crtcs; 636e3adcf8fSFrançois Tigeot int ret; 637e3adcf8fSFrançois Tigeot 638e3adcf8fSFrançois Tigeot if (!(IS_GEN6(dev) || IS_GEN7(dev))) 639e3adcf8fSFrançois Tigeot return -ENODEV; 640e3adcf8fSFrançois Tigeot 641e3adcf8fSFrançois Tigeot intel_plane = kmalloc(sizeof(struct intel_plane), DRM_MEM_KMS, 642e3adcf8fSFrançois Tigeot M_WAITOK | M_ZERO); 643e3adcf8fSFrançois Tigeot 644e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 645e3adcf8fSFrançois Tigeot intel_plane->max_downscale = 16; 646e3adcf8fSFrançois Tigeot intel_plane->update_plane = snb_update_plane; 647e3adcf8fSFrançois Tigeot intel_plane->disable_plane = snb_disable_plane; 648e3adcf8fSFrançois Tigeot intel_plane->update_colorkey = snb_update_colorkey; 649e3adcf8fSFrançois Tigeot intel_plane->get_colorkey = snb_get_colorkey; 650e3adcf8fSFrançois Tigeot } else if (IS_GEN7(dev)) { 651e3adcf8fSFrançois Tigeot intel_plane->max_downscale = 2; 652e3adcf8fSFrançois Tigeot intel_plane->update_plane = ivb_update_plane; 653e3adcf8fSFrançois Tigeot intel_plane->disable_plane = ivb_disable_plane; 654e3adcf8fSFrançois Tigeot intel_plane->update_colorkey = ivb_update_colorkey; 655e3adcf8fSFrançois Tigeot intel_plane->get_colorkey = ivb_get_colorkey; 656e3adcf8fSFrançois Tigeot } 657e3adcf8fSFrançois Tigeot 658e3adcf8fSFrançois Tigeot intel_plane->pipe = pipe; 659e3adcf8fSFrançois Tigeot possible_crtcs = (1 << pipe); 660e3adcf8fSFrançois Tigeot ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, 661e3adcf8fSFrançois Tigeot &intel_plane_funcs, snb_plane_formats, 662e3adcf8fSFrançois Tigeot DRM_ARRAY_SIZE(snb_plane_formats), false); 663e3adcf8fSFrançois Tigeot if (ret) 664e3adcf8fSFrançois Tigeot drm_free(intel_plane, DRM_MEM_KMS); 665e3adcf8fSFrançois Tigeot 666e3adcf8fSFrançois Tigeot return ret; 667e3adcf8fSFrançois Tigeot } 668e3adcf8fSFrançois Tigeot 669