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 vlv_update_plane(struct drm_plane *dplane, 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 = dplane->dev; 47 struct drm_i915_private *dev_priv = dev->dev_private; 48 struct intel_plane *intel_plane = to_intel_plane(dplane); 49 int pipe = intel_plane->pipe; 50 int plane = intel_plane->plane; 51 u32 sprctl; 52 unsigned long sprsurf_offset, linear_offset; 53 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 54 55 sprctl = I915_READ(SPCNTR(pipe, plane)); 56 57 /* Mask out pixel format bits in case we change it */ 58 sprctl &= ~SP_PIXFORMAT_MASK; 59 sprctl &= ~SP_YUV_BYTE_ORDER_MASK; 60 sprctl &= ~SP_TILED; 61 62 switch (fb->pixel_format) { 63 case DRM_FORMAT_YUYV: 64 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; 65 break; 66 case DRM_FORMAT_YVYU: 67 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; 68 break; 69 case DRM_FORMAT_UYVY: 70 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; 71 break; 72 case DRM_FORMAT_VYUY: 73 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; 74 break; 75 case DRM_FORMAT_RGB565: 76 sprctl |= SP_FORMAT_BGR565; 77 break; 78 case DRM_FORMAT_XRGB8888: 79 sprctl |= SP_FORMAT_BGRX8888; 80 break; 81 case DRM_FORMAT_ARGB8888: 82 sprctl |= SP_FORMAT_BGRA8888; 83 break; 84 case DRM_FORMAT_XBGR2101010: 85 sprctl |= SP_FORMAT_RGBX1010102; 86 break; 87 case DRM_FORMAT_ABGR2101010: 88 sprctl |= SP_FORMAT_RGBA1010102; 89 break; 90 case DRM_FORMAT_XBGR8888: 91 sprctl |= SP_FORMAT_RGBX8888; 92 break; 93 case DRM_FORMAT_ABGR8888: 94 sprctl |= SP_FORMAT_RGBA8888; 95 break; 96 default: 97 /* 98 * If we get here one of the upper layers failed to filter 99 * out the unsupported plane formats 100 */ 101 BUG(); 102 break; 103 } 104 105 if (obj->tiling_mode != I915_TILING_NONE) 106 sprctl |= SP_TILED; 107 108 sprctl |= SP_ENABLE; 109 110 /* Sizes are 0 based */ 111 src_w--; 112 src_h--; 113 crtc_w--; 114 crtc_h--; 115 116 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); 117 118 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); 119 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); 120 121 linear_offset = y * fb->pitches[0] + x * pixel_size; 122 sprsurf_offset = intel_gen4_compute_page_offset(&x, &y, 123 obj->tiling_mode, 124 pixel_size, 125 fb->pitches[0]); 126 linear_offset -= sprsurf_offset; 127 128 if (obj->tiling_mode != I915_TILING_NONE) 129 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); 130 else 131 I915_WRITE(SPLINOFF(pipe, plane), linear_offset); 132 133 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); 134 I915_WRITE(SPCNTR(pipe, plane), sprctl); 135 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset + 136 sprsurf_offset); 137 POSTING_READ(SPSURF(pipe, plane)); 138 } 139 140 static void 141 vlv_disable_plane(struct drm_plane *dplane) 142 { 143 struct drm_device *dev = dplane->dev; 144 struct drm_i915_private *dev_priv = dev->dev_private; 145 struct intel_plane *intel_plane = to_intel_plane(dplane); 146 int pipe = intel_plane->pipe; 147 int plane = intel_plane->plane; 148 149 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & 150 ~SP_ENABLE); 151 /* Activate double buffered register update */ 152 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0); 153 POSTING_READ(SPSURF(pipe, plane)); 154 } 155 156 static int 157 vlv_update_colorkey(struct drm_plane *dplane, 158 struct drm_intel_sprite_colorkey *key) 159 { 160 struct drm_device *dev = dplane->dev; 161 struct drm_i915_private *dev_priv = dev->dev_private; 162 struct intel_plane *intel_plane = to_intel_plane(dplane); 163 int pipe = intel_plane->pipe; 164 int plane = intel_plane->plane; 165 u32 sprctl; 166 167 if (key->flags & I915_SET_COLORKEY_DESTINATION) 168 return -EINVAL; 169 170 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); 171 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); 172 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); 173 174 sprctl = I915_READ(SPCNTR(pipe, plane)); 175 sprctl &= ~SP_SOURCE_KEY; 176 if (key->flags & I915_SET_COLORKEY_SOURCE) 177 sprctl |= SP_SOURCE_KEY; 178 I915_WRITE(SPCNTR(pipe, plane), sprctl); 179 180 POSTING_READ(SPKEYMSK(pipe, plane)); 181 182 return 0; 183 } 184 185 static void 186 vlv_get_colorkey(struct drm_plane *dplane, 187 struct drm_intel_sprite_colorkey *key) 188 { 189 struct drm_device *dev = dplane->dev; 190 struct drm_i915_private *dev_priv = dev->dev_private; 191 struct intel_plane *intel_plane = to_intel_plane(dplane); 192 int pipe = intel_plane->pipe; 193 int plane = intel_plane->plane; 194 u32 sprctl; 195 196 key->min_value = I915_READ(SPKEYMINVAL(pipe, plane)); 197 key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane)); 198 key->channel_mask = I915_READ(SPKEYMSK(pipe, plane)); 199 200 sprctl = I915_READ(SPCNTR(pipe, plane)); 201 if (sprctl & SP_SOURCE_KEY) 202 key->flags = I915_SET_COLORKEY_SOURCE; 203 else 204 key->flags = I915_SET_COLORKEY_NONE; 205 } 206 207 static void 208 ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, 209 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 210 unsigned int crtc_w, unsigned int crtc_h, 211 uint32_t x, uint32_t y, 212 uint32_t src_w, uint32_t src_h) 213 { 214 struct drm_device *dev = plane->dev; 215 struct drm_i915_private *dev_priv = dev->dev_private; 216 struct intel_plane *intel_plane = to_intel_plane(plane); 217 int pipe = intel_plane->pipe; 218 u32 sprctl, sprscale = 0; 219 unsigned long sprsurf_offset, linear_offset; 220 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 221 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; 222 223 sprctl = I915_READ(SPRCTL(pipe)); 224 225 /* Mask out pixel format bits in case we change it */ 226 sprctl &= ~SPRITE_PIXFORMAT_MASK; 227 sprctl &= ~SPRITE_RGB_ORDER_RGBX; 228 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; 229 sprctl &= ~SPRITE_TILED; 230 231 switch (fb->pixel_format) { 232 case DRM_FORMAT_XBGR8888: 233 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; 234 break; 235 case DRM_FORMAT_XRGB8888: 236 sprctl |= SPRITE_FORMAT_RGBX888; 237 break; 238 case DRM_FORMAT_YUYV: 239 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; 240 break; 241 case DRM_FORMAT_YVYU: 242 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; 243 break; 244 case DRM_FORMAT_UYVY: 245 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; 246 break; 247 case DRM_FORMAT_VYUY: 248 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; 249 break; 250 default: 251 BUG(); 252 } 253 254 if (obj->tiling_mode != I915_TILING_NONE) 255 sprctl |= SPRITE_TILED; 256 257 /* must disable */ 258 sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 259 sprctl |= SPRITE_ENABLE; 260 261 if (IS_HASWELL(dev)) 262 sprctl |= SPRITE_PIPE_CSC_ENABLE; 263 264 /* Sizes are 0 based */ 265 src_w--; 266 src_h--; 267 crtc_w--; 268 crtc_h--; 269 270 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); 271 272 /* 273 * IVB workaround: must disable low power watermarks for at least 274 * one frame before enabling scaling. LP watermarks can be re-enabled 275 * when scaling is disabled. 276 */ 277 if (crtc_w != src_w || crtc_h != src_h) { 278 dev_priv->sprite_scaling_enabled |= 1 << pipe; 279 280 if (!scaling_was_enabled) { 281 intel_update_watermarks(dev); 282 intel_wait_for_vblank(dev, pipe); 283 } 284 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; 285 } else 286 dev_priv->sprite_scaling_enabled &= ~(1 << pipe); 287 288 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); 289 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); 290 291 linear_offset = y * fb->pitches[0] + x * pixel_size; 292 sprsurf_offset = 293 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, 294 pixel_size, fb->pitches[0]); 295 linear_offset -= sprsurf_offset; 296 297 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET 298 * register */ 299 if (IS_HASWELL(dev)) 300 I915_WRITE(SPROFFSET(pipe), (y << 16) | x); 301 else if (obj->tiling_mode != I915_TILING_NONE) 302 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); 303 else 304 I915_WRITE(SPRLINOFF(pipe), linear_offset); 305 306 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); 307 if (intel_plane->can_scale) 308 I915_WRITE(SPRSCALE(pipe), sprscale); 309 I915_WRITE(SPRCTL(pipe), sprctl); 310 I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset); 311 POSTING_READ(SPRSURF(pipe)); 312 313 /* potentially re-enable LP watermarks */ 314 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) 315 intel_update_watermarks(dev); 316 } 317 318 static void 319 ivb_disable_plane(struct drm_plane *plane) 320 { 321 struct drm_device *dev = plane->dev; 322 struct drm_i915_private *dev_priv = dev->dev_private; 323 struct intel_plane *intel_plane = to_intel_plane(plane); 324 int pipe = intel_plane->pipe; 325 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; 326 327 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); 328 /* Can't leave the scaler enabled... */ 329 if (intel_plane->can_scale) 330 I915_WRITE(SPRSCALE(pipe), 0); 331 /* Activate double buffered register update */ 332 I915_MODIFY_DISPBASE(SPRSURF(pipe), 0); 333 POSTING_READ(SPRSURF(pipe)); 334 335 dev_priv->sprite_scaling_enabled &= ~(1 << pipe); 336 337 /* potentially re-enable LP watermarks */ 338 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) 339 intel_update_watermarks(dev); 340 } 341 342 static int 343 ivb_update_colorkey(struct drm_plane *plane, 344 struct drm_intel_sprite_colorkey *key) 345 { 346 struct drm_device *dev = plane->dev; 347 struct drm_i915_private *dev_priv = dev->dev_private; 348 struct intel_plane *intel_plane; 349 u32 sprctl; 350 int ret = 0; 351 352 intel_plane = to_intel_plane(plane); 353 354 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value); 355 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value); 356 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask); 357 358 sprctl = I915_READ(SPRCTL(intel_plane->pipe)); 359 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY); 360 if (key->flags & I915_SET_COLORKEY_DESTINATION) 361 sprctl |= SPRITE_DEST_KEY; 362 else if (key->flags & I915_SET_COLORKEY_SOURCE) 363 sprctl |= SPRITE_SOURCE_KEY; 364 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl); 365 366 POSTING_READ(SPRKEYMSK(intel_plane->pipe)); 367 368 return ret; 369 } 370 371 static void 372 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) 373 { 374 struct drm_device *dev = plane->dev; 375 struct drm_i915_private *dev_priv = dev->dev_private; 376 struct intel_plane *intel_plane; 377 u32 sprctl; 378 379 intel_plane = to_intel_plane(plane); 380 381 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe)); 382 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe)); 383 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe)); 384 key->flags = 0; 385 386 sprctl = I915_READ(SPRCTL(intel_plane->pipe)); 387 388 if (sprctl & SPRITE_DEST_KEY) 389 key->flags = I915_SET_COLORKEY_DESTINATION; 390 else if (sprctl & SPRITE_SOURCE_KEY) 391 key->flags = I915_SET_COLORKEY_SOURCE; 392 else 393 key->flags = I915_SET_COLORKEY_NONE; 394 } 395 396 static void 397 ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, 398 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 399 unsigned int crtc_w, unsigned int crtc_h, 400 uint32_t x, uint32_t y, 401 uint32_t src_w, uint32_t src_h) 402 { 403 struct drm_device *dev = plane->dev; 404 struct drm_i915_private *dev_priv = dev->dev_private; 405 struct intel_plane *intel_plane = to_intel_plane(plane); 406 int pipe = intel_plane->pipe; 407 unsigned long dvssurf_offset, linear_offset; 408 u32 dvscntr, dvsscale; 409 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 410 411 dvscntr = I915_READ(DVSCNTR(pipe)); 412 413 /* Mask out pixel format bits in case we change it */ 414 dvscntr &= ~DVS_PIXFORMAT_MASK; 415 dvscntr &= ~DVS_RGB_ORDER_XBGR; 416 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; 417 dvscntr &= ~DVS_TILED; 418 419 switch (fb->pixel_format) { 420 case DRM_FORMAT_XBGR8888: 421 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; 422 break; 423 case DRM_FORMAT_XRGB8888: 424 dvscntr |= DVS_FORMAT_RGBX888; 425 break; 426 case DRM_FORMAT_YUYV: 427 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; 428 break; 429 case DRM_FORMAT_YVYU: 430 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; 431 break; 432 case DRM_FORMAT_UYVY: 433 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; 434 break; 435 case DRM_FORMAT_VYUY: 436 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; 437 break; 438 default: 439 BUG(); 440 } 441 442 if (obj->tiling_mode != I915_TILING_NONE) 443 dvscntr |= DVS_TILED; 444 445 if (IS_GEN6(dev)) 446 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ 447 dvscntr |= DVS_ENABLE; 448 449 /* Sizes are 0 based */ 450 src_w--; 451 src_h--; 452 crtc_w--; 453 crtc_h--; 454 455 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); 456 457 dvsscale = 0; 458 if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h) 459 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; 460 461 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); 462 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); 463 464 linear_offset = y * fb->pitches[0] + x * pixel_size; 465 dvssurf_offset = 466 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, 467 pixel_size, fb->pitches[0]); 468 linear_offset -= dvssurf_offset; 469 470 if (obj->tiling_mode != I915_TILING_NONE) 471 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); 472 else 473 I915_WRITE(DVSLINOFF(pipe), linear_offset); 474 475 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); 476 I915_WRITE(DVSSCALE(pipe), dvsscale); 477 I915_WRITE(DVSCNTR(pipe), dvscntr); 478 I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset); 479 POSTING_READ(DVSSURF(pipe)); 480 } 481 482 static void 483 ilk_disable_plane(struct drm_plane *plane) 484 { 485 struct drm_device *dev = plane->dev; 486 struct drm_i915_private *dev_priv = dev->dev_private; 487 struct intel_plane *intel_plane = to_intel_plane(plane); 488 int pipe = intel_plane->pipe; 489 490 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE); 491 /* Disable the scaler */ 492 I915_WRITE(DVSSCALE(pipe), 0); 493 /* Flush double buffered register updates */ 494 I915_MODIFY_DISPBASE(DVSSURF(pipe), 0); 495 POSTING_READ(DVSSURF(pipe)); 496 } 497 498 static void 499 intel_enable_primary(struct drm_crtc *crtc) 500 { 501 struct drm_device *dev = crtc->dev; 502 struct drm_i915_private *dev_priv = dev->dev_private; 503 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 504 int reg = DSPCNTR(intel_crtc->plane); 505 506 if (!intel_crtc->primary_disabled) 507 return; 508 509 intel_crtc->primary_disabled = false; 510 intel_update_fbc(dev); 511 512 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); 513 } 514 515 static void 516 intel_disable_primary(struct drm_crtc *crtc) 517 { 518 struct drm_device *dev = crtc->dev; 519 struct drm_i915_private *dev_priv = dev->dev_private; 520 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 521 int reg = DSPCNTR(intel_crtc->plane); 522 523 if (intel_crtc->primary_disabled) 524 return; 525 526 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); 527 528 intel_crtc->primary_disabled = true; 529 intel_update_fbc(dev); 530 } 531 532 static int 533 ilk_update_colorkey(struct drm_plane *plane, 534 struct drm_intel_sprite_colorkey *key) 535 { 536 struct drm_device *dev = plane->dev; 537 struct drm_i915_private *dev_priv = dev->dev_private; 538 struct intel_plane *intel_plane; 539 u32 dvscntr; 540 int ret = 0; 541 542 intel_plane = to_intel_plane(plane); 543 544 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value); 545 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value); 546 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask); 547 548 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); 549 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY); 550 if (key->flags & I915_SET_COLORKEY_DESTINATION) 551 dvscntr |= DVS_DEST_KEY; 552 else if (key->flags & I915_SET_COLORKEY_SOURCE) 553 dvscntr |= DVS_SOURCE_KEY; 554 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr); 555 556 POSTING_READ(DVSKEYMSK(intel_plane->pipe)); 557 558 return ret; 559 } 560 561 static void 562 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) 563 { 564 struct drm_device *dev = plane->dev; 565 struct drm_i915_private *dev_priv = dev->dev_private; 566 struct intel_plane *intel_plane; 567 u32 dvscntr; 568 569 intel_plane = to_intel_plane(plane); 570 571 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe)); 572 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe)); 573 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe)); 574 key->flags = 0; 575 576 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); 577 578 if (dvscntr & DVS_DEST_KEY) 579 key->flags = I915_SET_COLORKEY_DESTINATION; 580 else if (dvscntr & DVS_SOURCE_KEY) 581 key->flags = I915_SET_COLORKEY_SOURCE; 582 else 583 key->flags = I915_SET_COLORKEY_NONE; 584 } 585 586 static int 587 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 588 struct drm_framebuffer *fb, int crtc_x, int crtc_y, 589 unsigned int crtc_w, unsigned int crtc_h, 590 uint32_t src_x, uint32_t src_y, 591 uint32_t src_w, uint32_t src_h) 592 { 593 struct drm_device *dev = plane->dev; 594 struct drm_i915_private *dev_priv = dev->dev_private; 595 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 596 struct intel_plane *intel_plane = to_intel_plane(plane); 597 struct intel_framebuffer *intel_fb; 598 struct drm_i915_gem_object *obj, *old_obj; 599 int pipe = intel_plane->pipe; 600 enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, 601 pipe); 602 int ret = 0; 603 int x = src_x >> 16, y = src_y >> 16; 604 int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay; 605 bool disable_primary = false; 606 607 intel_fb = to_intel_framebuffer(fb); 608 obj = intel_fb->obj; 609 610 old_obj = intel_plane->obj; 611 612 intel_plane->crtc_x = crtc_x; 613 intel_plane->crtc_y = crtc_y; 614 intel_plane->crtc_w = crtc_w; 615 intel_plane->crtc_h = crtc_h; 616 intel_plane->src_x = src_x; 617 intel_plane->src_y = src_y; 618 intel_plane->src_w = src_w; 619 intel_plane->src_h = src_h; 620 621 src_w = src_w >> 16; 622 src_h = src_h >> 16; 623 624 /* Pipe must be running... */ 625 if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) 626 return -EINVAL; 627 628 if (crtc_x >= primary_w || crtc_y >= primary_h) 629 return -EINVAL; 630 631 /* Don't modify another pipe's plane */ 632 if (intel_plane->pipe != intel_crtc->pipe) 633 return -EINVAL; 634 635 /* Sprite planes can be linear or x-tiled surfaces */ 636 switch (obj->tiling_mode) { 637 case I915_TILING_NONE: 638 case I915_TILING_X: 639 break; 640 default: 641 return -EINVAL; 642 } 643 644 /* 645 * Clamp the width & height into the visible area. Note we don't 646 * try to scale the source if part of the visible region is offscreen. 647 * The caller must handle that by adjusting source offset and size. 648 */ 649 if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) { 650 crtc_w += crtc_x; 651 crtc_x = 0; 652 } 653 if ((crtc_x + crtc_w) <= 0) /* Nothing to display */ 654 goto out; 655 if ((crtc_x + crtc_w) > primary_w) 656 crtc_w = primary_w - crtc_x; 657 658 if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) { 659 crtc_h += crtc_y; 660 crtc_y = 0; 661 } 662 if ((crtc_y + crtc_h) <= 0) /* Nothing to display */ 663 goto out; 664 if (crtc_y + crtc_h > primary_h) 665 crtc_h = primary_h - crtc_y; 666 667 if (!crtc_w || !crtc_h) /* Again, nothing to display */ 668 goto out; 669 670 /* 671 * We may not have a scaler, eg. HSW does not have it any more 672 */ 673 if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h)) 674 return -EINVAL; 675 676 /* 677 * We can take a larger source and scale it down, but 678 * only so much... 16x is the max on SNB. 679 */ 680 if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale) 681 return -EINVAL; 682 683 /* 684 * If the sprite is completely covering the primary plane, 685 * we can disable the primary and save power. 686 */ 687 if ((crtc_x == 0) && (crtc_y == 0) && 688 (crtc_w == primary_w) && (crtc_h == primary_h)) 689 disable_primary = true; 690 691 mutex_lock(&dev->struct_mutex); 692 693 /* Note that this will apply the VT-d workaround for scanouts, 694 * which is more restrictive than required for sprites. (The 695 * primary plane requires 256KiB alignment with 64 PTE padding, 696 * the sprite planes only require 128KiB alignment and 32 PTE padding. 697 */ 698 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); 699 if (ret) 700 goto out_unlock; 701 702 intel_plane->obj = obj; 703 704 /* 705 * Be sure to re-enable the primary before the sprite is no longer 706 * covering it fully. 707 */ 708 if (!disable_primary) 709 intel_enable_primary(crtc); 710 711 intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, 712 crtc_w, crtc_h, x, y, src_w, src_h); 713 714 if (disable_primary) 715 intel_disable_primary(crtc); 716 717 /* Unpin old obj after new one is active to avoid ugliness */ 718 if (old_obj) { 719 /* 720 * It's fairly common to simply update the position of 721 * an existing object. In that case, we don't need to 722 * wait for vblank to avoid ugliness, we only need to 723 * do the pin & ref bookkeeping. 724 */ 725 if (old_obj != obj) { 726 mutex_unlock(&dev->struct_mutex); 727 intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); 728 mutex_lock(&dev->struct_mutex); 729 } 730 intel_unpin_fb_obj(old_obj); 731 } 732 733 out_unlock: 734 mutex_unlock(&dev->struct_mutex); 735 out: 736 return ret; 737 } 738 739 static int 740 intel_disable_plane(struct drm_plane *plane) 741 { 742 struct drm_device *dev = plane->dev; 743 struct intel_plane *intel_plane = to_intel_plane(plane); 744 int ret = 0; 745 746 if (plane->crtc) 747 intel_enable_primary(plane->crtc); 748 intel_plane->disable_plane(plane); 749 750 if (!intel_plane->obj) 751 goto out; 752 753 intel_wait_for_vblank(dev, intel_plane->pipe); 754 755 mutex_lock(&dev->struct_mutex); 756 intel_unpin_fb_obj(intel_plane->obj); 757 intel_plane->obj = NULL; 758 mutex_unlock(&dev->struct_mutex); 759 out: 760 761 return ret; 762 } 763 764 static void intel_destroy_plane(struct drm_plane *plane) 765 { 766 struct intel_plane *intel_plane = to_intel_plane(plane); 767 intel_disable_plane(plane); 768 drm_plane_cleanup(plane); 769 kfree(intel_plane); 770 } 771 772 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 773 struct drm_file *file_priv) 774 { 775 struct drm_intel_sprite_colorkey *set = data; 776 struct drm_mode_object *obj; 777 struct drm_plane *plane; 778 struct intel_plane *intel_plane; 779 int ret = 0; 780 781 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 782 return -ENODEV; 783 784 /* Make sure we don't try to enable both src & dest simultaneously */ 785 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) 786 return -EINVAL; 787 788 drm_modeset_lock_all(dev); 789 790 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); 791 if (!obj) { 792 ret = -EINVAL; 793 goto out_unlock; 794 } 795 796 plane = obj_to_plane(obj); 797 intel_plane = to_intel_plane(plane); 798 ret = intel_plane->update_colorkey(plane, set); 799 800 out_unlock: 801 drm_modeset_unlock_all(dev); 802 return ret; 803 } 804 805 int intel_sprite_get_colorkey(struct drm_device *dev, void *data, 806 struct drm_file *file_priv) 807 { 808 struct drm_intel_sprite_colorkey *get = data; 809 struct drm_mode_object *obj; 810 struct drm_plane *plane; 811 struct intel_plane *intel_plane; 812 int ret = 0; 813 814 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 815 return -ENODEV; 816 817 drm_modeset_lock_all(dev); 818 819 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); 820 if (!obj) { 821 ret = -EINVAL; 822 goto out_unlock; 823 } 824 825 plane = obj_to_plane(obj); 826 intel_plane = to_intel_plane(plane); 827 intel_plane->get_colorkey(plane, get); 828 829 out_unlock: 830 drm_modeset_unlock_all(dev); 831 return ret; 832 } 833 834 void intel_plane_restore(struct drm_plane *plane) 835 { 836 struct intel_plane *intel_plane = to_intel_plane(plane); 837 838 if (!plane->crtc || !plane->fb) 839 return; 840 841 intel_update_plane(plane, plane->crtc, plane->fb, 842 intel_plane->crtc_x, intel_plane->crtc_y, 843 intel_plane->crtc_w, intel_plane->crtc_h, 844 intel_plane->src_x, intel_plane->src_y, 845 intel_plane->src_w, intel_plane->src_h); 846 } 847 848 static const struct drm_plane_funcs intel_plane_funcs = { 849 .update_plane = intel_update_plane, 850 .disable_plane = intel_disable_plane, 851 .destroy = intel_destroy_plane, 852 }; 853 854 static uint32_t ilk_plane_formats[] = { 855 DRM_FORMAT_XRGB8888, 856 DRM_FORMAT_YUYV, 857 DRM_FORMAT_YVYU, 858 DRM_FORMAT_UYVY, 859 DRM_FORMAT_VYUY, 860 }; 861 862 static uint32_t snb_plane_formats[] = { 863 DRM_FORMAT_XBGR8888, 864 DRM_FORMAT_XRGB8888, 865 DRM_FORMAT_YUYV, 866 DRM_FORMAT_YVYU, 867 DRM_FORMAT_UYVY, 868 DRM_FORMAT_VYUY, 869 }; 870 871 static uint32_t vlv_plane_formats[] = { 872 DRM_FORMAT_RGB565, 873 DRM_FORMAT_ABGR8888, 874 DRM_FORMAT_ARGB8888, 875 DRM_FORMAT_XBGR8888, 876 DRM_FORMAT_XRGB8888, 877 DRM_FORMAT_XBGR2101010, 878 DRM_FORMAT_ABGR2101010, 879 DRM_FORMAT_YUYV, 880 DRM_FORMAT_YVYU, 881 DRM_FORMAT_UYVY, 882 DRM_FORMAT_VYUY, 883 }; 884 885 int 886 intel_plane_init(struct drm_device *dev, enum i915_pipe pipe, int plane) 887 { 888 struct intel_plane *intel_plane; 889 unsigned long possible_crtcs; 890 const uint32_t *plane_formats; 891 int num_plane_formats; 892 int ret; 893 894 if (INTEL_INFO(dev)->gen < 5) 895 return -ENODEV; 896 897 intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); 898 if (!intel_plane) 899 return -ENOMEM; 900 901 switch (INTEL_INFO(dev)->gen) { 902 case 5: 903 case 6: 904 intel_plane->can_scale = true; 905 intel_plane->max_downscale = 16; 906 intel_plane->update_plane = ilk_update_plane; 907 intel_plane->disable_plane = ilk_disable_plane; 908 intel_plane->update_colorkey = ilk_update_colorkey; 909 intel_plane->get_colorkey = ilk_get_colorkey; 910 911 if (IS_GEN6(dev)) { 912 plane_formats = snb_plane_formats; 913 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 914 } else { 915 plane_formats = ilk_plane_formats; 916 num_plane_formats = ARRAY_SIZE(ilk_plane_formats); 917 } 918 break; 919 920 case 7: 921 if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev)) 922 intel_plane->can_scale = false; 923 else 924 intel_plane->can_scale = true; 925 926 if (IS_VALLEYVIEW(dev)) { 927 intel_plane->max_downscale = 1; 928 intel_plane->update_plane = vlv_update_plane; 929 intel_plane->disable_plane = vlv_disable_plane; 930 intel_plane->update_colorkey = vlv_update_colorkey; 931 intel_plane->get_colorkey = vlv_get_colorkey; 932 933 plane_formats = vlv_plane_formats; 934 num_plane_formats = ARRAY_SIZE(vlv_plane_formats); 935 } else { 936 intel_plane->max_downscale = 2; 937 intel_plane->update_plane = ivb_update_plane; 938 intel_plane->disable_plane = ivb_disable_plane; 939 intel_plane->update_colorkey = ivb_update_colorkey; 940 intel_plane->get_colorkey = ivb_get_colorkey; 941 942 plane_formats = snb_plane_formats; 943 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 944 } 945 break; 946 947 default: 948 kfree(intel_plane); 949 return -ENODEV; 950 } 951 952 intel_plane->pipe = pipe; 953 intel_plane->plane = plane; 954 possible_crtcs = (1 << pipe); 955 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, 956 &intel_plane_funcs, 957 plane_formats, num_plane_formats, 958 false); 959 if (ret) 960 kfree(intel_plane); 961 962 return ret; 963 } 964