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