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