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