Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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