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