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