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 <drm/drm_rect.h> 36 #include "intel_drv.h" 37 #include <drm/i915_drm.h> 38 #include "i915_drv.h" 39 40 static void 41 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, 42 struct drm_framebuffer *fb, 43 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 44 unsigned int crtc_w, unsigned int crtc_h, 45 uint32_t x, uint32_t y, 46 uint32_t src_w, uint32_t src_h) 47 { 48 struct drm_device *dev = dplane->dev; 49 struct drm_i915_private *dev_priv = dev->dev_private; 50 struct intel_plane *intel_plane = to_intel_plane(dplane); 51 int pipe = intel_plane->pipe; 52 int plane = intel_plane->plane; 53 u32 sprctl; 54 unsigned long sprsurf_offset, linear_offset; 55 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 56 57 sprctl = I915_READ(SPCNTR(pipe, plane)); 58 59 /* Mask out pixel format bits in case we change it */ 60 sprctl &= ~SP_PIXFORMAT_MASK; 61 sprctl &= ~SP_YUV_BYTE_ORDER_MASK; 62 sprctl &= ~SP_TILED; 63 64 switch (fb->pixel_format) { 65 case DRM_FORMAT_YUYV: 66 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; 67 break; 68 case DRM_FORMAT_YVYU: 69 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; 70 break; 71 case DRM_FORMAT_UYVY: 72 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; 73 break; 74 case DRM_FORMAT_VYUY: 75 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; 76 break; 77 case DRM_FORMAT_RGB565: 78 sprctl |= SP_FORMAT_BGR565; 79 break; 80 case DRM_FORMAT_XRGB8888: 81 sprctl |= SP_FORMAT_BGRX8888; 82 break; 83 case DRM_FORMAT_ARGB8888: 84 sprctl |= SP_FORMAT_BGRA8888; 85 break; 86 case DRM_FORMAT_XBGR2101010: 87 sprctl |= SP_FORMAT_RGBX1010102; 88 break; 89 case DRM_FORMAT_ABGR2101010: 90 sprctl |= SP_FORMAT_RGBA1010102; 91 break; 92 case DRM_FORMAT_XBGR8888: 93 sprctl |= SP_FORMAT_RGBX8888; 94 break; 95 case DRM_FORMAT_ABGR8888: 96 sprctl |= SP_FORMAT_RGBA8888; 97 break; 98 default: 99 /* 100 * If we get here one of the upper layers failed to filter 101 * out the unsupported plane formats 102 */ 103 BUG(); 104 break; 105 } 106 107 /* 108 * Enable gamma to match primary/cursor plane behaviour. 109 * FIXME should be user controllable via propertiesa. 110 */ 111 sprctl |= SP_GAMMA_ENABLE; 112 113 if (obj->tiling_mode != I915_TILING_NONE) 114 sprctl |= SP_TILED; 115 116 sprctl |= SP_ENABLE; 117 118 intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true, 119 src_w != crtc_w || src_h != crtc_h); 120 121 /* Sizes are 0 based */ 122 src_w--; 123 src_h--; 124 crtc_w--; 125 crtc_h--; 126 127 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); 128 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); 129 130 linear_offset = y * fb->pitches[0] + x * pixel_size; 131 sprsurf_offset = intel_gen4_compute_page_offset(&x, &y, 132 obj->tiling_mode, 133 pixel_size, 134 fb->pitches[0]); 135 linear_offset -= sprsurf_offset; 136 137 if (obj->tiling_mode != I915_TILING_NONE) 138 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); 139 else 140 I915_WRITE(SPLINOFF(pipe, plane), linear_offset); 141 142 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); 143 I915_WRITE(SPCNTR(pipe, plane), sprctl); 144 I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + 145 sprsurf_offset); 146 POSTING_READ(SPSURF(pipe, plane)); 147 } 148 149 static void 150 vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) 151 { 152 struct drm_device *dev = dplane->dev; 153 struct drm_i915_private *dev_priv = dev->dev_private; 154 struct intel_plane *intel_plane = to_intel_plane(dplane); 155 int pipe = intel_plane->pipe; 156 int plane = intel_plane->plane; 157 158 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & 159 ~SP_ENABLE); 160 /* Activate double buffered register update */ 161 I915_WRITE(SPSURF(pipe, plane), 0); 162 POSTING_READ(SPSURF(pipe, plane)); 163 164 intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false); 165 } 166 167 static int 168 vlv_update_colorkey(struct drm_plane *dplane, 169 struct drm_intel_sprite_colorkey *key) 170 { 171 struct drm_device *dev = dplane->dev; 172 struct drm_i915_private *dev_priv = dev->dev_private; 173 struct intel_plane *intel_plane = to_intel_plane(dplane); 174 int pipe = intel_plane->pipe; 175 int plane = intel_plane->plane; 176 u32 sprctl; 177 178 if (key->flags & I915_SET_COLORKEY_DESTINATION) 179 return -EINVAL; 180 181 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); 182 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); 183 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); 184 185 sprctl = I915_READ(SPCNTR(pipe, plane)); 186 sprctl &= ~SP_SOURCE_KEY; 187 if (key->flags & I915_SET_COLORKEY_SOURCE) 188 sprctl |= SP_SOURCE_KEY; 189 I915_WRITE(SPCNTR(pipe, plane), sprctl); 190 191 POSTING_READ(SPKEYMSK(pipe, plane)); 192 193 return 0; 194 } 195 196 static void 197 vlv_get_colorkey(struct drm_plane *dplane, 198 struct drm_intel_sprite_colorkey *key) 199 { 200 struct drm_device *dev = dplane->dev; 201 struct drm_i915_private *dev_priv = dev->dev_private; 202 struct intel_plane *intel_plane = to_intel_plane(dplane); 203 int pipe = intel_plane->pipe; 204 int plane = intel_plane->plane; 205 u32 sprctl; 206 207 key->min_value = I915_READ(SPKEYMINVAL(pipe, plane)); 208 key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane)); 209 key->channel_mask = I915_READ(SPKEYMSK(pipe, plane)); 210 211 sprctl = I915_READ(SPCNTR(pipe, plane)); 212 if (sprctl & SP_SOURCE_KEY) 213 key->flags = I915_SET_COLORKEY_SOURCE; 214 else 215 key->flags = I915_SET_COLORKEY_NONE; 216 } 217 218 static void 219 ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 220 struct drm_framebuffer *fb, 221 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 222 unsigned int crtc_w, unsigned int crtc_h, 223 uint32_t x, uint32_t y, 224 uint32_t src_w, uint32_t src_h) 225 { 226 struct drm_device *dev = plane->dev; 227 struct drm_i915_private *dev_priv = dev->dev_private; 228 struct intel_plane *intel_plane = to_intel_plane(plane); 229 int pipe = intel_plane->pipe; 230 u32 sprctl, sprscale = 0; 231 unsigned long sprsurf_offset, linear_offset; 232 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 233 234 sprctl = I915_READ(SPRCTL(pipe)); 235 236 /* Mask out pixel format bits in case we change it */ 237 sprctl &= ~SPRITE_PIXFORMAT_MASK; 238 sprctl &= ~SPRITE_RGB_ORDER_RGBX; 239 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; 240 sprctl &= ~SPRITE_TILED; 241 242 switch (fb->pixel_format) { 243 case DRM_FORMAT_XBGR8888: 244 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; 245 break; 246 case DRM_FORMAT_XRGB8888: 247 sprctl |= SPRITE_FORMAT_RGBX888; 248 break; 249 case DRM_FORMAT_YUYV: 250 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; 251 break; 252 case DRM_FORMAT_YVYU: 253 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; 254 break; 255 case DRM_FORMAT_UYVY: 256 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; 257 break; 258 case DRM_FORMAT_VYUY: 259 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; 260 break; 261 default: 262 BUG(); 263 } 264 265 /* 266 * Enable gamma to match primary/cursor plane behaviour. 267 * FIXME should be user controllable via propertiesa. 268 */ 269 sprctl |= SPRITE_GAMMA_ENABLE; 270 271 if (obj->tiling_mode != I915_TILING_NONE) 272 sprctl |= SPRITE_TILED; 273 274 if (IS_HASWELL(dev) || IS_BROADWELL(dev)) 275 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; 276 else 277 sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 278 279 sprctl |= SPRITE_ENABLE; 280 281 if (IS_HASWELL(dev) || IS_BROADWELL(dev)) 282 sprctl |= SPRITE_PIPE_CSC_ENABLE; 283 284 intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, 285 src_w != crtc_w || src_h != crtc_h); 286 287 /* Sizes are 0 based */ 288 src_w--; 289 src_h--; 290 crtc_w--; 291 crtc_h--; 292 293 if (crtc_w != src_w || crtc_h != src_h) 294 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; 295 296 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); 297 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); 298 299 linear_offset = y * fb->pitches[0] + x * pixel_size; 300 sprsurf_offset = 301 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, 302 pixel_size, fb->pitches[0]); 303 linear_offset -= sprsurf_offset; 304 305 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET 306 * register */ 307 if (IS_HASWELL(dev) || IS_BROADWELL(dev)) 308 I915_WRITE(SPROFFSET(pipe), (y << 16) | x); 309 else if (obj->tiling_mode != I915_TILING_NONE) 310 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); 311 else 312 I915_WRITE(SPRLINOFF(pipe), linear_offset); 313 314 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); 315 if (intel_plane->can_scale) 316 I915_WRITE(SPRSCALE(pipe), sprscale); 317 I915_WRITE(SPRCTL(pipe), sprctl); 318 I915_WRITE(SPRSURF(pipe), 319 i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); 320 POSTING_READ(SPRSURF(pipe)); 321 } 322 323 static void 324 ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) 325 { 326 struct drm_device *dev = plane->dev; 327 struct drm_i915_private *dev_priv = dev->dev_private; 328 struct intel_plane *intel_plane = to_intel_plane(plane); 329 int pipe = intel_plane->pipe; 330 331 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); 332 /* Can't leave the scaler enabled... */ 333 if (intel_plane->can_scale) 334 I915_WRITE(SPRSCALE(pipe), 0); 335 /* Activate double buffered register update */ 336 I915_WRITE(SPRSURF(pipe), 0); 337 POSTING_READ(SPRSURF(pipe)); 338 339 /* 340 * Avoid underruns when disabling the sprite. 341 * FIXME remove once watermark updates are done properly. 342 */ 343 intel_wait_for_vblank(dev, pipe); 344 345 intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); 346 } 347 348 static int 349 ivb_update_colorkey(struct drm_plane *plane, 350 struct drm_intel_sprite_colorkey *key) 351 { 352 struct drm_device *dev = plane->dev; 353 struct drm_i915_private *dev_priv = dev->dev_private; 354 struct intel_plane *intel_plane; 355 u32 sprctl; 356 int ret = 0; 357 358 intel_plane = to_intel_plane(plane); 359 360 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value); 361 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value); 362 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask); 363 364 sprctl = I915_READ(SPRCTL(intel_plane->pipe)); 365 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY); 366 if (key->flags & I915_SET_COLORKEY_DESTINATION) 367 sprctl |= SPRITE_DEST_KEY; 368 else if (key->flags & I915_SET_COLORKEY_SOURCE) 369 sprctl |= SPRITE_SOURCE_KEY; 370 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl); 371 372 POSTING_READ(SPRKEYMSK(intel_plane->pipe)); 373 374 return ret; 375 } 376 377 static void 378 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) 379 { 380 struct drm_device *dev = plane->dev; 381 struct drm_i915_private *dev_priv = dev->dev_private; 382 struct intel_plane *intel_plane; 383 u32 sprctl; 384 385 intel_plane = to_intel_plane(plane); 386 387 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe)); 388 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe)); 389 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe)); 390 key->flags = 0; 391 392 sprctl = I915_READ(SPRCTL(intel_plane->pipe)); 393 394 if (sprctl & SPRITE_DEST_KEY) 395 key->flags = I915_SET_COLORKEY_DESTINATION; 396 else if (sprctl & SPRITE_SOURCE_KEY) 397 key->flags = I915_SET_COLORKEY_SOURCE; 398 else 399 key->flags = I915_SET_COLORKEY_NONE; 400 } 401 402 static void 403 ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 404 struct drm_framebuffer *fb, 405 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 406 unsigned int crtc_w, unsigned int crtc_h, 407 uint32_t x, uint32_t y, 408 uint32_t src_w, uint32_t src_h) 409 { 410 struct drm_device *dev = plane->dev; 411 struct drm_i915_private *dev_priv = dev->dev_private; 412 struct intel_plane *intel_plane = to_intel_plane(plane); 413 int pipe = intel_plane->pipe; 414 unsigned long dvssurf_offset, linear_offset; 415 u32 dvscntr, dvsscale; 416 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 417 418 dvscntr = I915_READ(DVSCNTR(pipe)); 419 420 /* Mask out pixel format bits in case we change it */ 421 dvscntr &= ~DVS_PIXFORMAT_MASK; 422 dvscntr &= ~DVS_RGB_ORDER_XBGR; 423 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; 424 dvscntr &= ~DVS_TILED; 425 426 switch (fb->pixel_format) { 427 case DRM_FORMAT_XBGR8888: 428 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; 429 break; 430 case DRM_FORMAT_XRGB8888: 431 dvscntr |= DVS_FORMAT_RGBX888; 432 break; 433 case DRM_FORMAT_YUYV: 434 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; 435 break; 436 case DRM_FORMAT_YVYU: 437 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; 438 break; 439 case DRM_FORMAT_UYVY: 440 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; 441 break; 442 case DRM_FORMAT_VYUY: 443 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; 444 break; 445 default: 446 BUG(); 447 } 448 449 /* 450 * Enable gamma to match primary/cursor plane behaviour. 451 * FIXME should be user controllable via propertiesa. 452 */ 453 dvscntr |= DVS_GAMMA_ENABLE; 454 455 if (obj->tiling_mode != I915_TILING_NONE) 456 dvscntr |= DVS_TILED; 457 458 if (IS_GEN6(dev)) 459 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ 460 dvscntr |= DVS_ENABLE; 461 462 intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, 463 src_w != crtc_w || src_h != crtc_h); 464 465 /* Sizes are 0 based */ 466 src_w--; 467 src_h--; 468 crtc_w--; 469 crtc_h--; 470 471 dvsscale = 0; 472 if (crtc_w != src_w || crtc_h != src_h) 473 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; 474 475 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); 476 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); 477 478 linear_offset = y * fb->pitches[0] + x * pixel_size; 479 dvssurf_offset = 480 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, 481 pixel_size, fb->pitches[0]); 482 linear_offset -= dvssurf_offset; 483 484 if (obj->tiling_mode != I915_TILING_NONE) 485 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); 486 else 487 I915_WRITE(DVSLINOFF(pipe), linear_offset); 488 489 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); 490 I915_WRITE(DVSSCALE(pipe), dvsscale); 491 I915_WRITE(DVSCNTR(pipe), dvscntr); 492 I915_WRITE(DVSSURF(pipe), 493 i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); 494 POSTING_READ(DVSSURF(pipe)); 495 } 496 497 static void 498 ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) 499 { 500 struct drm_device *dev = plane->dev; 501 struct drm_i915_private *dev_priv = dev->dev_private; 502 struct intel_plane *intel_plane = to_intel_plane(plane); 503 int pipe = intel_plane->pipe; 504 505 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE); 506 /* Disable the scaler */ 507 I915_WRITE(DVSSCALE(pipe), 0); 508 /* Flush double buffered register updates */ 509 I915_WRITE(DVSSURF(pipe), 0); 510 POSTING_READ(DVSSURF(pipe)); 511 512 /* 513 * Avoid underruns when disabling the sprite. 514 * FIXME remove once watermark updates are done properly. 515 */ 516 intel_wait_for_vblank(dev, pipe); 517 518 intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); 519 } 520 521 static void 522 intel_enable_primary(struct drm_crtc *crtc) 523 { 524 struct drm_device *dev = crtc->dev; 525 struct drm_i915_private *dev_priv = dev->dev_private; 526 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 527 int reg = DSPCNTR(intel_crtc->plane); 528 529 if (intel_crtc->primary_enabled) 530 return; 531 532 intel_crtc->primary_enabled = true; 533 534 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); 535 intel_flush_primary_plane(dev_priv, intel_crtc->plane); 536 537 /* 538 * FIXME IPS should be fine as long as one plane is 539 * enabled, but in practice it seems to have problems 540 * when going from primary only to sprite only and vice 541 * versa. 542 */ 543 if (intel_crtc->config.ips_enabled) { 544 intel_wait_for_vblank(dev, intel_crtc->pipe); 545 hsw_enable_ips(intel_crtc); 546 } 547 548 mutex_lock(&dev->struct_mutex); 549 intel_update_fbc(dev); 550 mutex_unlock(&dev->struct_mutex); 551 } 552 553 static void 554 intel_disable_primary(struct drm_crtc *crtc) 555 { 556 struct drm_device *dev = crtc->dev; 557 struct drm_i915_private *dev_priv = dev->dev_private; 558 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 559 int reg = DSPCNTR(intel_crtc->plane); 560 561 if (!intel_crtc->primary_enabled) 562 return; 563 564 intel_crtc->primary_enabled = false; 565 566 mutex_lock(&dev->struct_mutex); 567 if (dev_priv->fbc.plane == intel_crtc->plane) 568 intel_disable_fbc(dev); 569 mutex_unlock(&dev->struct_mutex); 570 571 /* 572 * FIXME IPS should be fine as long as one plane is 573 * enabled, but in practice it seems to have problems 574 * when going from primary only to sprite only and vice 575 * versa. 576 */ 577 hsw_disable_ips(intel_crtc); 578 579 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); 580 intel_flush_primary_plane(dev_priv, intel_crtc->plane); 581 } 582 583 static int 584 ilk_update_colorkey(struct drm_plane *plane, 585 struct drm_intel_sprite_colorkey *key) 586 { 587 struct drm_device *dev = plane->dev; 588 struct drm_i915_private *dev_priv = dev->dev_private; 589 struct intel_plane *intel_plane; 590 u32 dvscntr; 591 int ret = 0; 592 593 intel_plane = to_intel_plane(plane); 594 595 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value); 596 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value); 597 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask); 598 599 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); 600 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY); 601 if (key->flags & I915_SET_COLORKEY_DESTINATION) 602 dvscntr |= DVS_DEST_KEY; 603 else if (key->flags & I915_SET_COLORKEY_SOURCE) 604 dvscntr |= DVS_SOURCE_KEY; 605 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr); 606 607 POSTING_READ(DVSKEYMSK(intel_plane->pipe)); 608 609 return ret; 610 } 611 612 static void 613 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) 614 { 615 struct drm_device *dev = plane->dev; 616 struct drm_i915_private *dev_priv = dev->dev_private; 617 struct intel_plane *intel_plane; 618 u32 dvscntr; 619 620 intel_plane = to_intel_plane(plane); 621 622 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe)); 623 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe)); 624 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe)); 625 key->flags = 0; 626 627 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); 628 629 if (dvscntr & DVS_DEST_KEY) 630 key->flags = I915_SET_COLORKEY_DESTINATION; 631 else if (dvscntr & DVS_SOURCE_KEY) 632 key->flags = I915_SET_COLORKEY_SOURCE; 633 else 634 key->flags = I915_SET_COLORKEY_NONE; 635 } 636 637 static bool 638 format_is_yuv(uint32_t format) 639 { 640 switch (format) { 641 case DRM_FORMAT_YUYV: 642 case DRM_FORMAT_UYVY: 643 case DRM_FORMAT_VYUY: 644 case DRM_FORMAT_YVYU: 645 return true; 646 default: 647 return false; 648 } 649 } 650 651 static bool colorkey_enabled(struct intel_plane *intel_plane) 652 { 653 struct drm_intel_sprite_colorkey key; 654 655 intel_plane->get_colorkey(&intel_plane->base, &key); 656 657 return key.flags != I915_SET_COLORKEY_NONE; 658 } 659 660 static int 661 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 662 struct drm_framebuffer *fb, int crtc_x, int crtc_y, 663 unsigned int crtc_w, unsigned int crtc_h, 664 uint32_t src_x, uint32_t src_y, 665 uint32_t src_w, uint32_t src_h) 666 { 667 struct drm_device *dev = plane->dev; 668 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 669 struct intel_plane *intel_plane = to_intel_plane(plane); 670 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 671 struct drm_i915_gem_object *obj = intel_fb->obj; 672 struct drm_i915_gem_object *old_obj = intel_plane->obj; 673 int ret; 674 bool disable_primary = false; 675 bool visible; 676 int hscale, vscale; 677 int max_scale, min_scale; 678 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 679 struct drm_rect src = { 680 /* sample coordinates in 16.16 fixed point */ 681 .x1 = src_x, 682 .x2 = src_x + src_w, 683 .y1 = src_y, 684 .y2 = src_y + src_h, 685 }; 686 struct drm_rect dst = { 687 /* integer pixels */ 688 .x1 = crtc_x, 689 .x2 = crtc_x + crtc_w, 690 .y1 = crtc_y, 691 .y2 = crtc_y + crtc_h, 692 }; 693 const struct drm_rect clip = { 694 .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0, 695 .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0, 696 }; 697 const struct { 698 int crtc_x, crtc_y; 699 unsigned int crtc_w, crtc_h; 700 uint32_t src_x, src_y, src_w, src_h; 701 } orig = { 702 .crtc_x = crtc_x, 703 .crtc_y = crtc_y, 704 .crtc_w = crtc_w, 705 .crtc_h = crtc_h, 706 .src_x = src_x, 707 .src_y = src_y, 708 .src_w = src_w, 709 .src_h = src_h, 710 }; 711 712 /* Don't modify another pipe's plane */ 713 if (intel_plane->pipe != intel_crtc->pipe) { 714 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); 715 return -EINVAL; 716 } 717 718 /* FIXME check all gen limits */ 719 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) { 720 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); 721 return -EINVAL; 722 } 723 724 /* Sprite planes can be linear or x-tiled surfaces */ 725 switch (obj->tiling_mode) { 726 case I915_TILING_NONE: 727 case I915_TILING_X: 728 break; 729 default: 730 DRM_DEBUG_KMS("Unsupported tiling mode\n"); 731 return -EINVAL; 732 } 733 734 /* 735 * FIXME the following code does a bunch of fuzzy adjustments to the 736 * coordinates and sizes. We probably need some way to decide whether 737 * more strict checking should be done instead. 738 */ 739 max_scale = intel_plane->max_downscale << 16; 740 min_scale = intel_plane->can_scale ? 1 : (1 << 16); 741 742 hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale); 743 BUG_ON(hscale < 0); 744 745 vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale); 746 BUG_ON(vscale < 0); 747 748 visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale); 749 750 crtc_x = dst.x1; 751 crtc_y = dst.y1; 752 crtc_w = drm_rect_width(&dst); 753 crtc_h = drm_rect_height(&dst); 754 755 if (visible) { 756 /* check again in case clipping clamped the results */ 757 hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale); 758 if (hscale < 0) { 759 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); 760 drm_rect_debug_print(&src, true); 761 drm_rect_debug_print(&dst, false); 762 763 return hscale; 764 } 765 766 vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale); 767 if (vscale < 0) { 768 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); 769 drm_rect_debug_print(&src, true); 770 drm_rect_debug_print(&dst, false); 771 772 return vscale; 773 } 774 775 /* Make the source viewport size an exact multiple of the scaling factors. */ 776 drm_rect_adjust_size(&src, 777 drm_rect_width(&dst) * hscale - drm_rect_width(&src), 778 drm_rect_height(&dst) * vscale - drm_rect_height(&src)); 779 780 /* sanity check to make sure the src viewport wasn't enlarged */ 781 WARN_ON(src.x1 < (int) src_x || 782 src.y1 < (int) src_y || 783 src.x2 > (int) (src_x + src_w) || 784 src.y2 > (int) (src_y + src_h)); 785 786 /* 787 * Hardware doesn't handle subpixel coordinates. 788 * Adjust to (macro)pixel boundary, but be careful not to 789 * increase the source viewport size, because that could 790 * push the downscaling factor out of bounds. 791 */ 792 src_x = src.x1 >> 16; 793 src_w = drm_rect_width(&src) >> 16; 794 src_y = src.y1 >> 16; 795 src_h = drm_rect_height(&src) >> 16; 796 797 if (format_is_yuv(fb->pixel_format)) { 798 src_x &= ~1; 799 src_w &= ~1; 800 801 /* 802 * Must keep src and dst the 803 * same if we can't scale. 804 */ 805 if (!intel_plane->can_scale) 806 crtc_w &= ~1; 807 808 if (crtc_w == 0) 809 visible = false; 810 } 811 } 812 813 /* Check size restrictions when scaling */ 814 if (visible && (src_w != crtc_w || src_h != crtc_h)) { 815 unsigned int width_bytes; 816 817 WARN_ON(!intel_plane->can_scale); 818 819 /* FIXME interlacing min height is 6 */ 820 821 if (crtc_w < 3 || crtc_h < 3) 822 visible = false; 823 824 if (src_w < 3 || src_h < 3) 825 visible = false; 826 827 width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size; 828 829 if (src_w > 2048 || src_h > 2048 || 830 width_bytes > 4096 || fb->pitches[0] > 4096) { 831 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); 832 return -EINVAL; 833 } 834 } 835 836 dst.x1 = crtc_x; 837 dst.x2 = crtc_x + crtc_w; 838 dst.y1 = crtc_y; 839 dst.y2 = crtc_y + crtc_h; 840 841 /* 842 * If the sprite is completely covering the primary plane, 843 * we can disable the primary and save power. 844 */ 845 disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane); 846 WARN_ON(disable_primary && !visible && intel_crtc->active); 847 848 mutex_lock(&dev->struct_mutex); 849 850 /* Note that this will apply the VT-d workaround for scanouts, 851 * which is more restrictive than required for sprites. (The 852 * primary plane requires 256KiB alignment with 64 PTE padding, 853 * the sprite planes only require 128KiB alignment and 32 PTE padding. 854 */ 855 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); 856 857 mutex_unlock(&dev->struct_mutex); 858 859 if (ret) 860 return ret; 861 862 intel_plane->crtc_x = orig.crtc_x; 863 intel_plane->crtc_y = orig.crtc_y; 864 intel_plane->crtc_w = orig.crtc_w; 865 intel_plane->crtc_h = orig.crtc_h; 866 intel_plane->src_x = orig.src_x; 867 intel_plane->src_y = orig.src_y; 868 intel_plane->src_w = orig.src_w; 869 intel_plane->src_h = orig.src_h; 870 intel_plane->obj = obj; 871 872 if (intel_crtc->active) { 873 /* 874 * Be sure to re-enable the primary before the sprite is no longer 875 * covering it fully. 876 */ 877 if (!disable_primary) 878 intel_enable_primary(crtc); 879 880 if (visible) 881 intel_plane->update_plane(plane, crtc, fb, obj, 882 crtc_x, crtc_y, crtc_w, crtc_h, 883 src_x, src_y, src_w, src_h); 884 else 885 intel_plane->disable_plane(plane, crtc); 886 887 if (disable_primary) 888 intel_disable_primary(crtc); 889 } 890 891 /* Unpin old obj after new one is active to avoid ugliness */ 892 if (old_obj) { 893 /* 894 * It's fairly common to simply update the position of 895 * an existing object. In that case, we don't need to 896 * wait for vblank to avoid ugliness, we only need to 897 * do the pin & ref bookkeeping. 898 */ 899 if (old_obj != obj && intel_crtc->active) 900 intel_wait_for_vblank(dev, intel_crtc->pipe); 901 902 mutex_lock(&dev->struct_mutex); 903 intel_unpin_fb_obj(old_obj); 904 mutex_unlock(&dev->struct_mutex); 905 } 906 907 return 0; 908 } 909 910 static int 911 intel_disable_plane(struct drm_plane *plane) 912 { 913 struct drm_device *dev = plane->dev; 914 struct intel_plane *intel_plane = to_intel_plane(plane); 915 struct intel_crtc *intel_crtc; 916 917 if (!plane->fb) 918 return 0; 919 920 if (WARN_ON(!plane->crtc)) 921 return -EINVAL; 922 923 intel_crtc = to_intel_crtc(plane->crtc); 924 925 if (intel_crtc->active) { 926 intel_enable_primary(plane->crtc); 927 intel_plane->disable_plane(plane, plane->crtc); 928 } 929 930 if (intel_plane->obj) { 931 if (intel_crtc->active) 932 intel_wait_for_vblank(dev, intel_plane->pipe); 933 934 mutex_lock(&dev->struct_mutex); 935 intel_unpin_fb_obj(intel_plane->obj); 936 mutex_unlock(&dev->struct_mutex); 937 938 intel_plane->obj = NULL; 939 } 940 941 return 0; 942 } 943 944 static void intel_destroy_plane(struct drm_plane *plane) 945 { 946 struct intel_plane *intel_plane = to_intel_plane(plane); 947 intel_disable_plane(plane); 948 drm_plane_cleanup(plane); 949 kfree(intel_plane); 950 } 951 952 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 953 struct drm_file *file_priv) 954 { 955 struct drm_intel_sprite_colorkey *set = data; 956 struct drm_mode_object *obj; 957 struct drm_plane *plane; 958 struct intel_plane *intel_plane; 959 int ret = 0; 960 961 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 962 return -ENODEV; 963 964 /* Make sure we don't try to enable both src & dest simultaneously */ 965 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) 966 return -EINVAL; 967 968 drm_modeset_lock_all(dev); 969 970 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); 971 if (!obj) { 972 ret = -ENOENT; 973 goto out_unlock; 974 } 975 976 plane = obj_to_plane(obj); 977 intel_plane = to_intel_plane(plane); 978 ret = intel_plane->update_colorkey(plane, set); 979 980 out_unlock: 981 drm_modeset_unlock_all(dev); 982 return ret; 983 } 984 985 int intel_sprite_get_colorkey(struct drm_device *dev, void *data, 986 struct drm_file *file_priv) 987 { 988 struct drm_intel_sprite_colorkey *get = data; 989 struct drm_mode_object *obj; 990 struct drm_plane *plane; 991 struct intel_plane *intel_plane; 992 int ret = 0; 993 994 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 995 return -ENODEV; 996 997 drm_modeset_lock_all(dev); 998 999 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); 1000 if (!obj) { 1001 ret = -ENOENT; 1002 goto out_unlock; 1003 } 1004 1005 plane = obj_to_plane(obj); 1006 intel_plane = to_intel_plane(plane); 1007 intel_plane->get_colorkey(plane, get); 1008 1009 out_unlock: 1010 drm_modeset_unlock_all(dev); 1011 return ret; 1012 } 1013 1014 void intel_plane_restore(struct drm_plane *plane) 1015 { 1016 struct intel_plane *intel_plane = to_intel_plane(plane); 1017 1018 if (!plane->crtc || !plane->fb) 1019 return; 1020 1021 intel_update_plane(plane, plane->crtc, plane->fb, 1022 intel_plane->crtc_x, intel_plane->crtc_y, 1023 intel_plane->crtc_w, intel_plane->crtc_h, 1024 intel_plane->src_x, intel_plane->src_y, 1025 intel_plane->src_w, intel_plane->src_h); 1026 } 1027 1028 void intel_plane_disable(struct drm_plane *plane) 1029 { 1030 if (!plane->crtc || !plane->fb) 1031 return; 1032 1033 intel_disable_plane(plane); 1034 } 1035 1036 static const struct drm_plane_funcs intel_plane_funcs = { 1037 .update_plane = intel_update_plane, 1038 .disable_plane = intel_disable_plane, 1039 .destroy = intel_destroy_plane, 1040 }; 1041 1042 static uint32_t ilk_plane_formats[] = { 1043 DRM_FORMAT_XRGB8888, 1044 DRM_FORMAT_YUYV, 1045 DRM_FORMAT_YVYU, 1046 DRM_FORMAT_UYVY, 1047 DRM_FORMAT_VYUY, 1048 }; 1049 1050 static uint32_t snb_plane_formats[] = { 1051 DRM_FORMAT_XBGR8888, 1052 DRM_FORMAT_XRGB8888, 1053 DRM_FORMAT_YUYV, 1054 DRM_FORMAT_YVYU, 1055 DRM_FORMAT_UYVY, 1056 DRM_FORMAT_VYUY, 1057 }; 1058 1059 static uint32_t vlv_plane_formats[] = { 1060 DRM_FORMAT_RGB565, 1061 DRM_FORMAT_ABGR8888, 1062 DRM_FORMAT_ARGB8888, 1063 DRM_FORMAT_XBGR8888, 1064 DRM_FORMAT_XRGB8888, 1065 DRM_FORMAT_XBGR2101010, 1066 DRM_FORMAT_ABGR2101010, 1067 DRM_FORMAT_YUYV, 1068 DRM_FORMAT_YVYU, 1069 DRM_FORMAT_UYVY, 1070 DRM_FORMAT_VYUY, 1071 }; 1072 1073 int 1074 intel_plane_init(struct drm_device *dev, enum i915_pipe pipe, int plane) 1075 { 1076 struct intel_plane *intel_plane; 1077 unsigned long possible_crtcs; 1078 const uint32_t *plane_formats; 1079 int num_plane_formats; 1080 int ret; 1081 1082 if (INTEL_INFO(dev)->gen < 5) 1083 return -ENODEV; 1084 1085 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); 1086 if (!intel_plane) 1087 return -ENOMEM; 1088 1089 switch (INTEL_INFO(dev)->gen) { 1090 case 5: 1091 case 6: 1092 intel_plane->can_scale = true; 1093 intel_plane->max_downscale = 16; 1094 intel_plane->update_plane = ilk_update_plane; 1095 intel_plane->disable_plane = ilk_disable_plane; 1096 intel_plane->update_colorkey = ilk_update_colorkey; 1097 intel_plane->get_colorkey = ilk_get_colorkey; 1098 1099 if (IS_GEN6(dev)) { 1100 plane_formats = snb_plane_formats; 1101 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 1102 } else { 1103 plane_formats = ilk_plane_formats; 1104 num_plane_formats = ARRAY_SIZE(ilk_plane_formats); 1105 } 1106 break; 1107 1108 case 7: 1109 case 8: 1110 if (IS_IVYBRIDGE(dev)) { 1111 intel_plane->can_scale = true; 1112 intel_plane->max_downscale = 2; 1113 } else { 1114 intel_plane->can_scale = false; 1115 intel_plane->max_downscale = 1; 1116 } 1117 1118 if (IS_VALLEYVIEW(dev)) { 1119 intel_plane->update_plane = vlv_update_plane; 1120 intel_plane->disable_plane = vlv_disable_plane; 1121 intel_plane->update_colorkey = vlv_update_colorkey; 1122 intel_plane->get_colorkey = vlv_get_colorkey; 1123 1124 plane_formats = vlv_plane_formats; 1125 num_plane_formats = ARRAY_SIZE(vlv_plane_formats); 1126 } else { 1127 intel_plane->update_plane = ivb_update_plane; 1128 intel_plane->disable_plane = ivb_disable_plane; 1129 intel_plane->update_colorkey = ivb_update_colorkey; 1130 intel_plane->get_colorkey = ivb_get_colorkey; 1131 1132 plane_formats = snb_plane_formats; 1133 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 1134 } 1135 break; 1136 1137 default: 1138 kfree(intel_plane); 1139 return -ENODEV; 1140 } 1141 1142 intel_plane->pipe = pipe; 1143 intel_plane->plane = plane; 1144 possible_crtcs = (1 << pipe); 1145 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, 1146 &intel_plane_funcs, 1147 plane_formats, num_plane_formats, 1148 false); 1149 if (ret) 1150 kfree(intel_plane); 1151 1152 return ret; 1153 } 1154