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_page_offset(&x, &y, obj->tiling_mode, 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_page_offset(&x, &y, obj->tiling_mode, 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 enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, 425 pipe); 426 int ret = 0; 427 int x = src_x >> 16, y = src_y >> 16; 428 int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay; 429 bool disable_primary = false; 430 431 intel_fb = to_intel_framebuffer(fb); 432 obj = intel_fb->obj; 433 434 old_obj = intel_plane->obj; 435 436 src_w = src_w >> 16; 437 src_h = src_h >> 16; 438 439 /* Pipe must be running... */ 440 if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) 441 return -EINVAL; 442 443 if (crtc_x >= primary_w || crtc_y >= primary_h) 444 return -EINVAL; 445 446 /* Don't modify another pipe's plane */ 447 if (intel_plane->pipe != intel_crtc->pipe) 448 return -EINVAL; 449 450 /* Sprite planes can be linear or x-tiled surfaces */ 451 switch (obj->tiling_mode) { 452 case I915_TILING_NONE: 453 case I915_TILING_X: 454 break; 455 default: 456 return -EINVAL; 457 } 458 459 /* 460 * Clamp the width & height into the visible area. Note we don't 461 * try to scale the source if part of the visible region is offscreen. 462 * The caller must handle that by adjusting source offset and size. 463 */ 464 if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) { 465 crtc_w += crtc_x; 466 crtc_x = 0; 467 } 468 if ((crtc_x + crtc_w) <= 0) /* Nothing to display */ 469 goto out; 470 if ((crtc_x + crtc_w) > primary_w) 471 crtc_w = primary_w - crtc_x; 472 473 if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) { 474 crtc_h += crtc_y; 475 crtc_y = 0; 476 } 477 if ((crtc_y + crtc_h) <= 0) /* Nothing to display */ 478 goto out; 479 if (crtc_y + crtc_h > primary_h) 480 crtc_h = primary_h - crtc_y; 481 482 if (!crtc_w || !crtc_h) /* Again, nothing to display */ 483 goto out; 484 485 /* 486 * We may not have a scaler, eg. HSW does not have it any more 487 */ 488 if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h)) 489 return -EINVAL; 490 491 /* 492 * We can take a larger source and scale it down, but 493 * only so much... 16x is the max on SNB. 494 */ 495 if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale) 496 return -EINVAL; 497 498 /* 499 * If the sprite is completely covering the primary plane, 500 * we can disable the primary and save power. 501 */ 502 if ((crtc_x == 0) && (crtc_y == 0) && 503 (crtc_w == primary_w) && (crtc_h == primary_h)) 504 disable_primary = true; 505 506 DRM_LOCK(dev); 507 508 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); 509 if (ret) 510 goto out_unlock; 511 512 intel_plane->obj = obj; 513 514 /* 515 * Be sure to re-enable the primary before the sprite is no longer 516 * covering it fully. 517 */ 518 if (!disable_primary) 519 intel_enable_primary(crtc); 520 521 intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, 522 crtc_w, crtc_h, x, y, src_w, src_h); 523 524 if (disable_primary) 525 intel_disable_primary(crtc); 526 527 /* Unpin old obj after new one is active to avoid ugliness */ 528 if (old_obj) { 529 /* 530 * It's fairly common to simply update the position of 531 * an existing object. In that case, we don't need to 532 * wait for vblank to avoid ugliness, we only need to 533 * do the pin & ref bookkeeping. 534 */ 535 if (old_obj != obj) { 536 DRM_UNLOCK(dev); 537 intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); 538 DRM_LOCK(dev); 539 } 540 intel_unpin_fb_obj(old_obj); 541 } 542 543 out_unlock: 544 DRM_UNLOCK(dev); 545 out: 546 return ret; 547 } 548 549 static int 550 intel_disable_plane(struct drm_plane *plane) 551 { 552 struct drm_device *dev = plane->dev; 553 struct intel_plane *intel_plane = to_intel_plane(plane); 554 int ret = 0; 555 556 if (plane->crtc) 557 intel_enable_primary(plane->crtc); 558 intel_plane->disable_plane(plane); 559 560 if (!intel_plane->obj) 561 goto out; 562 563 DRM_LOCK(dev); 564 intel_unpin_fb_obj(intel_plane->obj); 565 intel_plane->obj = NULL; 566 DRM_UNLOCK(dev); 567 out: 568 569 return ret; 570 } 571 572 static void intel_destroy_plane(struct drm_plane *plane) 573 { 574 struct intel_plane *intel_plane = to_intel_plane(plane); 575 intel_disable_plane(plane); 576 drm_plane_cleanup(plane); 577 kfree(intel_plane, M_DRM); 578 } 579 580 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 581 struct drm_file *file_priv) 582 { 583 struct drm_intel_sprite_colorkey *set = data; 584 struct drm_mode_object *obj; 585 struct drm_plane *plane; 586 struct intel_plane *intel_plane; 587 int ret = 0; 588 589 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 590 return -ENODEV; 591 592 /* Make sure we don't try to enable both src & dest simultaneously */ 593 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) 594 return -EINVAL; 595 596 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 597 598 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); 599 if (!obj) { 600 ret = -EINVAL; 601 goto out_unlock; 602 } 603 604 plane = obj_to_plane(obj); 605 intel_plane = to_intel_plane(plane); 606 ret = intel_plane->update_colorkey(plane, set); 607 608 out_unlock: 609 lockmgr(&dev->mode_config.mutex, LK_RELEASE); 610 return ret; 611 } 612 613 int intel_sprite_get_colorkey(struct drm_device *dev, void *data, 614 struct drm_file *file_priv) 615 { 616 struct drm_intel_sprite_colorkey *get = data; 617 struct drm_mode_object *obj; 618 struct drm_plane *plane; 619 struct intel_plane *intel_plane; 620 int ret = 0; 621 622 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 623 return -ENODEV; 624 625 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 626 627 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); 628 if (!obj) { 629 ret = -EINVAL; 630 goto out_unlock; 631 } 632 633 plane = obj_to_plane(obj); 634 intel_plane = to_intel_plane(plane); 635 intel_plane->get_colorkey(plane, get); 636 637 out_unlock: 638 lockmgr(&dev->mode_config.mutex, LK_RELEASE); 639 return ret; 640 } 641 642 static const struct drm_plane_funcs intel_plane_funcs = { 643 .update_plane = intel_update_plane, 644 .disable_plane = intel_disable_plane, 645 .destroy = intel_destroy_plane, 646 }; 647 648 static uint32_t ilk_plane_formats[] = { 649 DRM_FORMAT_XRGB8888, 650 DRM_FORMAT_YUYV, 651 DRM_FORMAT_YVYU, 652 DRM_FORMAT_UYVY, 653 DRM_FORMAT_VYUY, 654 }; 655 656 static uint32_t snb_plane_formats[] = { 657 DRM_FORMAT_XBGR8888, 658 DRM_FORMAT_XRGB8888, 659 DRM_FORMAT_YUYV, 660 DRM_FORMAT_YVYU, 661 DRM_FORMAT_UYVY, 662 DRM_FORMAT_VYUY, 663 }; 664 665 int 666 intel_plane_init(struct drm_device *dev, enum i915_pipe pipe) 667 { 668 struct intel_plane *intel_plane; 669 unsigned long possible_crtcs; 670 const uint32_t *plane_formats; 671 int num_plane_formats; 672 int ret; 673 674 if (INTEL_INFO(dev)->gen < 5) 675 return -ENODEV; 676 677 intel_plane = kmalloc(sizeof(struct intel_plane), M_DRM, 678 M_WAITOK | M_ZERO); 679 if (!intel_plane) 680 return -ENOMEM; 681 682 switch (INTEL_INFO(dev)->gen) { 683 case 5: 684 case 6: 685 intel_plane->can_scale = true; 686 intel_plane->max_downscale = 16; 687 intel_plane->update_plane = ilk_update_plane; 688 intel_plane->disable_plane = ilk_disable_plane; 689 intel_plane->update_colorkey = ilk_update_colorkey; 690 intel_plane->get_colorkey = ilk_get_colorkey; 691 692 if (IS_GEN6(dev)) { 693 plane_formats = snb_plane_formats; 694 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 695 } else { 696 plane_formats = ilk_plane_formats; 697 num_plane_formats = ARRAY_SIZE(ilk_plane_formats); 698 } 699 break; 700 701 case 7: 702 if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev)) 703 intel_plane->can_scale = false; 704 else 705 intel_plane->can_scale = true; 706 intel_plane->max_downscale = 2; 707 intel_plane->update_plane = ivb_update_plane; 708 intel_plane->disable_plane = ivb_disable_plane; 709 intel_plane->update_colorkey = ivb_update_colorkey; 710 intel_plane->get_colorkey = ivb_get_colorkey; 711 712 plane_formats = snb_plane_formats; 713 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 714 break; 715 716 default: 717 kfree(intel_plane, M_DRM); 718 return -ENODEV; 719 } 720 721 intel_plane->pipe = pipe; 722 possible_crtcs = (1 << pipe); 723 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, 724 &intel_plane_funcs, 725 plane_formats, num_plane_formats, 726 false); 727 if (ret) 728 kfree(intel_plane, M_DRM); 729 730 return ret; 731 } 732