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