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