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 <drm/drm_atomic.h> 37 #include <drm/drm_plane_helper.h> 38 #include "intel_drv.h" 39 #include <drm/i915_drm.h> 40 #include "i915_drv.h" 41 42 static bool 43 format_is_yuv(uint32_t format) 44 { 45 switch (format) { 46 case DRM_FORMAT_YUYV: 47 case DRM_FORMAT_UYVY: 48 case DRM_FORMAT_VYUY: 49 case DRM_FORMAT_YVYU: 50 return true; 51 default: 52 return false; 53 } 54 } 55 56 static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, 57 int usecs) 58 { 59 /* paranoia */ 60 if (!adjusted_mode->crtc_htotal) 61 return 1; 62 63 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock, 64 1000 * adjusted_mode->crtc_htotal); 65 } 66 67 /** 68 * intel_pipe_update_start() - start update of a set of display registers 69 * @crtc: the crtc of which the registers are going to be updated 70 * @start_vbl_count: vblank counter return pointer used for error checking 71 * 72 * Mark the start of an update to pipe registers that should be updated 73 * atomically regarding vblank. If the next vblank will happens within 74 * the next 100 us, this function waits until the vblank passes. 75 * 76 * After a successful call to this function, interrupts will be disabled 77 * until a subsequent call to intel_pipe_update_end(). That is done to 78 * avoid random delays. The value written to @start_vbl_count should be 79 * supplied to intel_pipe_update_end() for error checking. 80 */ 81 void intel_pipe_update_start(struct intel_crtc *crtc) 82 { 83 struct drm_device *dev = crtc->base.dev; 84 const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; 85 enum i915_pipe pipe = crtc->pipe; 86 long timeout = msecs_to_jiffies_timeout(1); 87 int scanline, min, max, vblank_start; 88 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); 89 DEFINE_WAIT(wait); 90 91 vblank_start = adjusted_mode->crtc_vblank_start; 92 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) 93 vblank_start = DIV_ROUND_UP(vblank_start, 2); 94 95 /* FIXME needs to be calibrated sensibly */ 96 min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); 97 max = vblank_start - 1; 98 99 local_irq_disable(); 100 101 if (min <= 0 || max <= 0) 102 return; 103 104 if (WARN_ON(drm_crtc_vblank_get(&crtc->base))) 105 return; 106 107 crtc->debug.min_vbl = min; 108 crtc->debug.max_vbl = max; 109 trace_i915_pipe_update_start(crtc); 110 111 for (;;) { 112 /* 113 * prepare_to_wait() has a memory barrier, which guarantees 114 * other CPUs can see the task state update by the time we 115 * read the scanline. 116 */ 117 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); 118 119 scanline = intel_get_crtc_scanline(crtc); 120 if (scanline < min || scanline > max) 121 break; 122 123 if (timeout <= 0) { 124 DRM_ERROR("Potential atomic update failure on pipe %c\n", 125 pipe_name(crtc->pipe)); 126 break; 127 } 128 129 local_irq_enable(); 130 131 timeout = schedule_timeout(timeout); 132 133 local_irq_disable(); 134 } 135 136 finish_wait(wq, &wait); 137 138 drm_crtc_vblank_put(&crtc->base); 139 140 crtc->debug.scanline_start = scanline; 141 crtc->debug.start_vbl_time = ktime_get(); 142 crtc->debug.start_vbl_count = 143 dev->driver->get_vblank_counter(dev, pipe); 144 145 trace_i915_pipe_update_vblank_evaded(crtc); 146 } 147 148 /** 149 * intel_pipe_update_end() - end update of a set of display registers 150 * @crtc: the crtc of which the registers were updated 151 * @start_vbl_count: start vblank counter (used for error checking) 152 * 153 * Mark the end of an update started with intel_pipe_update_start(). This 154 * re-enables interrupts and verifies the update was actually completed 155 * before a vblank using the value of @start_vbl_count. 156 */ 157 void intel_pipe_update_end(struct intel_crtc *crtc) 158 { 159 struct drm_device *dev = crtc->base.dev; 160 enum i915_pipe pipe = crtc->pipe; 161 int scanline_end = intel_get_crtc_scanline(crtc); 162 u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); 163 ktime_t end_vbl_time = ktime_get(); 164 165 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); 166 167 local_irq_enable(); 168 169 if (crtc->debug.start_vbl_count && 170 crtc->debug.start_vbl_count != end_vbl_count) { 171 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n", 172 pipe_name(pipe), crtc->debug.start_vbl_count, 173 end_vbl_count, 174 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), 175 crtc->debug.min_vbl, crtc->debug.max_vbl, 176 crtc->debug.scanline_start, scanline_end); 177 } 178 } 179 180 static void 181 skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, 182 struct drm_framebuffer *fb, 183 int crtc_x, int crtc_y, 184 unsigned int crtc_w, unsigned int crtc_h, 185 uint32_t x, uint32_t y, 186 uint32_t src_w, uint32_t src_h) 187 { 188 struct drm_device *dev = drm_plane->dev; 189 struct drm_i915_private *dev_priv = dev->dev_private; 190 struct intel_plane *intel_plane = to_intel_plane(drm_plane); 191 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 192 const int pipe = intel_plane->pipe; 193 const int plane = intel_plane->plane + 1; 194 u32 plane_ctl, stride_div, stride; 195 const struct drm_intel_sprite_colorkey *key = 196 &to_intel_plane_state(drm_plane->state)->ckey; 197 u32 surf_addr; 198 u32 tile_height, plane_offset, plane_size; 199 unsigned int rotation; 200 int x_offset, y_offset; 201 struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config; 202 int scaler_id; 203 204 plane_ctl = PLANE_CTL_ENABLE | 205 PLANE_CTL_PIPE_GAMMA_ENABLE | 206 PLANE_CTL_PIPE_CSC_ENABLE; 207 208 plane_ctl |= skl_plane_ctl_format(fb->pixel_format); 209 plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]); 210 211 rotation = drm_plane->state->rotation; 212 plane_ctl |= skl_plane_ctl_rotation(rotation); 213 214 stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], 215 fb->pixel_format); 216 217 scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id; 218 219 /* Sizes are 0 based */ 220 src_w--; 221 src_h--; 222 crtc_w--; 223 crtc_h--; 224 225 if (key->flags) { 226 I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); 227 I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value); 228 I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask); 229 } 230 231 if (key->flags & I915_SET_COLORKEY_DESTINATION) 232 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; 233 else if (key->flags & I915_SET_COLORKEY_SOURCE) 234 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; 235 236 surf_addr = intel_plane_obj_offset(intel_plane, obj, 0); 237 238 if (intel_rotation_90_or_270(rotation)) { 239 /* stride: Surface height in tiles */ 240 tile_height = intel_tile_height(dev, fb->pixel_format, 241 fb->modifier[0], 0); 242 stride = DIV_ROUND_UP(fb->height, tile_height); 243 plane_size = (src_w << 16) | src_h; 244 x_offset = stride * tile_height - y - (src_h + 1); 245 y_offset = x; 246 } else { 247 stride = fb->pitches[0] / stride_div; 248 plane_size = (src_h << 16) | src_w; 249 x_offset = x; 250 y_offset = y; 251 } 252 plane_offset = y_offset << 16 | x_offset; 253 254 I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset); 255 I915_WRITE(PLANE_STRIDE(pipe, plane), stride); 256 I915_WRITE(PLANE_SIZE(pipe, plane), plane_size); 257 258 /* program plane scaler */ 259 if (scaler_id >= 0) { 260 uint32_t ps_ctrl = 0; 261 262 DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane, 263 PS_PLANE_SEL(plane)); 264 ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) | 265 crtc_state->scaler_state.scalers[scaler_id].mode; 266 I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl); 267 I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0); 268 I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); 269 I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), 270 ((crtc_w + 1) << 16)|(crtc_h + 1)); 271 272 I915_WRITE(PLANE_POS(pipe, plane), 0); 273 } else { 274 I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x); 275 } 276 277 I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl); 278 I915_WRITE(PLANE_SURF(pipe, plane), surf_addr); 279 POSTING_READ(PLANE_SURF(pipe, plane)); 280 } 281 282 static void 283 skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) 284 { 285 struct drm_device *dev = dplane->dev; 286 struct drm_i915_private *dev_priv = dev->dev_private; 287 struct intel_plane *intel_plane = to_intel_plane(dplane); 288 const int pipe = intel_plane->pipe; 289 const int plane = intel_plane->plane + 1; 290 291 I915_WRITE(PLANE_CTL(pipe, plane), 0); 292 293 I915_WRITE(PLANE_SURF(pipe, plane), 0); 294 POSTING_READ(PLANE_SURF(pipe, plane)); 295 } 296 297 static void 298 chv_update_csc(struct intel_plane *intel_plane, uint32_t format) 299 { 300 struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private; 301 int plane = intel_plane->plane; 302 303 /* Seems RGB data bypasses the CSC always */ 304 if (!format_is_yuv(format)) 305 return; 306 307 /* 308 * BT.601 limited range YCbCr -> full range RGB 309 * 310 * |r| | 6537 4769 0| |cr | 311 * |g| = |-3330 4769 -1605| x |y-64| 312 * |b| | 0 4769 8263| |cb | 313 * 314 * Cb and Cr apparently come in as signed already, so no 315 * need for any offset. For Y we need to remove the offset. 316 */ 317 I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64)); 318 I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); 319 I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); 320 321 I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537)); 322 I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0)); 323 I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769)); 324 I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0)); 325 I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263)); 326 327 I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64)); 328 I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); 329 I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); 330 331 I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 332 I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 333 I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 334 } 335 336 static void 337 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, 338 struct drm_framebuffer *fb, 339 int crtc_x, int crtc_y, 340 unsigned int crtc_w, unsigned int crtc_h, 341 uint32_t x, uint32_t y, 342 uint32_t src_w, uint32_t src_h) 343 { 344 struct drm_device *dev = dplane->dev; 345 struct drm_i915_private *dev_priv = dev->dev_private; 346 struct intel_plane *intel_plane = to_intel_plane(dplane); 347 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 348 int pipe = intel_plane->pipe; 349 int plane = intel_plane->plane; 350 u32 sprctl; 351 unsigned long sprsurf_offset, linear_offset; 352 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 353 const struct drm_intel_sprite_colorkey *key = 354 &to_intel_plane_state(dplane->state)->ckey; 355 356 sprctl = SP_ENABLE; 357 358 switch (fb->pixel_format) { 359 case DRM_FORMAT_YUYV: 360 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; 361 break; 362 case DRM_FORMAT_YVYU: 363 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; 364 break; 365 case DRM_FORMAT_UYVY: 366 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; 367 break; 368 case DRM_FORMAT_VYUY: 369 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; 370 break; 371 case DRM_FORMAT_RGB565: 372 sprctl |= SP_FORMAT_BGR565; 373 break; 374 case DRM_FORMAT_XRGB8888: 375 sprctl |= SP_FORMAT_BGRX8888; 376 break; 377 case DRM_FORMAT_ARGB8888: 378 sprctl |= SP_FORMAT_BGRA8888; 379 break; 380 case DRM_FORMAT_XBGR2101010: 381 sprctl |= SP_FORMAT_RGBX1010102; 382 break; 383 case DRM_FORMAT_ABGR2101010: 384 sprctl |= SP_FORMAT_RGBA1010102; 385 break; 386 case DRM_FORMAT_XBGR8888: 387 sprctl |= SP_FORMAT_RGBX8888; 388 break; 389 case DRM_FORMAT_ABGR8888: 390 sprctl |= SP_FORMAT_RGBA8888; 391 break; 392 default: 393 /* 394 * If we get here one of the upper layers failed to filter 395 * out the unsupported plane formats 396 */ 397 BUG(); 398 break; 399 } 400 401 /* 402 * Enable gamma to match primary/cursor plane behaviour. 403 * FIXME should be user controllable via propertiesa. 404 */ 405 sprctl |= SP_GAMMA_ENABLE; 406 407 if (obj->tiling_mode != I915_TILING_NONE) 408 sprctl |= SP_TILED; 409 410 /* Sizes are 0 based */ 411 src_w--; 412 src_h--; 413 crtc_w--; 414 crtc_h--; 415 416 linear_offset = y * fb->pitches[0] + x * pixel_size; 417 sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, 418 &x, &y, 419 obj->tiling_mode, 420 pixel_size, 421 fb->pitches[0]); 422 linear_offset -= sprsurf_offset; 423 424 if (dplane->state->rotation == BIT(DRM_ROTATE_180)) { 425 sprctl |= SP_ROTATE_180; 426 427 x += src_w; 428 y += src_h; 429 linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; 430 } 431 432 if (key->flags) { 433 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); 434 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); 435 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); 436 } 437 438 if (key->flags & I915_SET_COLORKEY_SOURCE) 439 sprctl |= SP_SOURCE_KEY; 440 441 if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) 442 chv_update_csc(intel_plane, fb->pixel_format); 443 444 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); 445 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); 446 447 if (obj->tiling_mode != I915_TILING_NONE) 448 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); 449 else 450 I915_WRITE(SPLINOFF(pipe, plane), linear_offset); 451 452 I915_WRITE(SPCONSTALPHA(pipe, plane), 0); 453 454 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); 455 I915_WRITE(SPCNTR(pipe, plane), sprctl); 456 I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + 457 sprsurf_offset); 458 POSTING_READ(SPSURF(pipe, plane)); 459 } 460 461 static void 462 vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) 463 { 464 struct drm_device *dev = dplane->dev; 465 struct drm_i915_private *dev_priv = dev->dev_private; 466 struct intel_plane *intel_plane = to_intel_plane(dplane); 467 int pipe = intel_plane->pipe; 468 int plane = intel_plane->plane; 469 470 I915_WRITE(SPCNTR(pipe, plane), 0); 471 472 I915_WRITE(SPSURF(pipe, plane), 0); 473 POSTING_READ(SPSURF(pipe, plane)); 474 } 475 476 static void 477 ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 478 struct drm_framebuffer *fb, 479 int crtc_x, int crtc_y, 480 unsigned int crtc_w, unsigned int crtc_h, 481 uint32_t x, uint32_t y, 482 uint32_t src_w, uint32_t src_h) 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 drm_i915_gem_object *obj = intel_fb_obj(fb); 488 enum i915_pipe pipe = intel_plane->pipe; 489 u32 sprctl, sprscale = 0; 490 unsigned long sprsurf_offset, linear_offset; 491 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 492 const struct drm_intel_sprite_colorkey *key = 493 &to_intel_plane_state(plane->state)->ckey; 494 495 sprctl = SPRITE_ENABLE; 496 497 switch (fb->pixel_format) { 498 case DRM_FORMAT_XBGR8888: 499 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; 500 break; 501 case DRM_FORMAT_XRGB8888: 502 sprctl |= SPRITE_FORMAT_RGBX888; 503 break; 504 case DRM_FORMAT_YUYV: 505 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; 506 break; 507 case DRM_FORMAT_YVYU: 508 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; 509 break; 510 case DRM_FORMAT_UYVY: 511 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; 512 break; 513 case DRM_FORMAT_VYUY: 514 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; 515 break; 516 default: 517 BUG(); 518 } 519 520 /* 521 * Enable gamma to match primary/cursor plane behaviour. 522 * FIXME should be user controllable via propertiesa. 523 */ 524 sprctl |= SPRITE_GAMMA_ENABLE; 525 526 if (obj->tiling_mode != I915_TILING_NONE) 527 sprctl |= SPRITE_TILED; 528 529 if (IS_HASWELL(dev) || IS_BROADWELL(dev)) 530 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; 531 else 532 sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 533 534 if (IS_HASWELL(dev) || IS_BROADWELL(dev)) 535 sprctl |= SPRITE_PIPE_CSC_ENABLE; 536 537 /* Sizes are 0 based */ 538 src_w--; 539 src_h--; 540 crtc_w--; 541 crtc_h--; 542 543 if (crtc_w != src_w || crtc_h != src_h) 544 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; 545 546 linear_offset = y * fb->pitches[0] + x * pixel_size; 547 sprsurf_offset = 548 intel_gen4_compute_page_offset(dev_priv, 549 &x, &y, obj->tiling_mode, 550 pixel_size, fb->pitches[0]); 551 linear_offset -= sprsurf_offset; 552 553 if (plane->state->rotation == BIT(DRM_ROTATE_180)) { 554 sprctl |= SPRITE_ROTATE_180; 555 556 /* HSW and BDW does this automagically in hardware */ 557 if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { 558 x += src_w; 559 y += src_h; 560 linear_offset += src_h * fb->pitches[0] + 561 src_w * pixel_size; 562 } 563 } 564 565 if (key->flags) { 566 I915_WRITE(SPRKEYVAL(pipe), key->min_value); 567 I915_WRITE(SPRKEYMAX(pipe), key->max_value); 568 I915_WRITE(SPRKEYMSK(pipe), key->channel_mask); 569 } 570 571 if (key->flags & I915_SET_COLORKEY_DESTINATION) 572 sprctl |= SPRITE_DEST_KEY; 573 else if (key->flags & I915_SET_COLORKEY_SOURCE) 574 sprctl |= SPRITE_SOURCE_KEY; 575 576 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); 577 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); 578 579 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET 580 * register */ 581 if (IS_HASWELL(dev) || IS_BROADWELL(dev)) 582 I915_WRITE(SPROFFSET(pipe), (y << 16) | x); 583 else if (obj->tiling_mode != I915_TILING_NONE) 584 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); 585 else 586 I915_WRITE(SPRLINOFF(pipe), linear_offset); 587 588 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); 589 if (intel_plane->can_scale) 590 I915_WRITE(SPRSCALE(pipe), sprscale); 591 I915_WRITE(SPRCTL(pipe), sprctl); 592 I915_WRITE(SPRSURF(pipe), 593 i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); 594 POSTING_READ(SPRSURF(pipe)); 595 } 596 597 static void 598 ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) 599 { 600 struct drm_device *dev = plane->dev; 601 struct drm_i915_private *dev_priv = dev->dev_private; 602 struct intel_plane *intel_plane = to_intel_plane(plane); 603 int pipe = intel_plane->pipe; 604 605 I915_WRITE(SPRCTL(pipe), 0); 606 /* Can't leave the scaler enabled... */ 607 if (intel_plane->can_scale) 608 I915_WRITE(SPRSCALE(pipe), 0); 609 610 I915_WRITE(SPRSURF(pipe), 0); 611 POSTING_READ(SPRSURF(pipe)); 612 } 613 614 static void 615 ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 616 struct drm_framebuffer *fb, 617 int crtc_x, int crtc_y, 618 unsigned int crtc_w, unsigned int crtc_h, 619 uint32_t x, uint32_t y, 620 uint32_t src_w, uint32_t src_h) 621 { 622 struct drm_device *dev = plane->dev; 623 struct drm_i915_private *dev_priv = dev->dev_private; 624 struct intel_plane *intel_plane = to_intel_plane(plane); 625 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 626 int pipe = intel_plane->pipe; 627 unsigned long dvssurf_offset, linear_offset; 628 u32 dvscntr, dvsscale; 629 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 630 const struct drm_intel_sprite_colorkey *key = 631 &to_intel_plane_state(plane->state)->ckey; 632 633 dvscntr = DVS_ENABLE; 634 635 switch (fb->pixel_format) { 636 case DRM_FORMAT_XBGR8888: 637 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; 638 break; 639 case DRM_FORMAT_XRGB8888: 640 dvscntr |= DVS_FORMAT_RGBX888; 641 break; 642 case DRM_FORMAT_YUYV: 643 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; 644 break; 645 case DRM_FORMAT_YVYU: 646 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; 647 break; 648 case DRM_FORMAT_UYVY: 649 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; 650 break; 651 case DRM_FORMAT_VYUY: 652 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; 653 break; 654 default: 655 BUG(); 656 } 657 658 /* 659 * Enable gamma to match primary/cursor plane behaviour. 660 * FIXME should be user controllable via propertiesa. 661 */ 662 dvscntr |= DVS_GAMMA_ENABLE; 663 664 if (obj->tiling_mode != I915_TILING_NONE) 665 dvscntr |= DVS_TILED; 666 667 if (IS_GEN6(dev)) 668 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ 669 670 /* Sizes are 0 based */ 671 src_w--; 672 src_h--; 673 crtc_w--; 674 crtc_h--; 675 676 dvsscale = 0; 677 if (crtc_w != src_w || crtc_h != src_h) 678 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; 679 680 linear_offset = y * fb->pitches[0] + x * pixel_size; 681 dvssurf_offset = 682 intel_gen4_compute_page_offset(dev_priv, 683 &x, &y, obj->tiling_mode, 684 pixel_size, fb->pitches[0]); 685 linear_offset -= dvssurf_offset; 686 687 if (plane->state->rotation == BIT(DRM_ROTATE_180)) { 688 dvscntr |= DVS_ROTATE_180; 689 690 x += src_w; 691 y += src_h; 692 linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; 693 } 694 695 if (key->flags) { 696 I915_WRITE(DVSKEYVAL(pipe), key->min_value); 697 I915_WRITE(DVSKEYMAX(pipe), key->max_value); 698 I915_WRITE(DVSKEYMSK(pipe), key->channel_mask); 699 } 700 701 if (key->flags & I915_SET_COLORKEY_DESTINATION) 702 dvscntr |= DVS_DEST_KEY; 703 else if (key->flags & I915_SET_COLORKEY_SOURCE) 704 dvscntr |= DVS_SOURCE_KEY; 705 706 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); 707 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); 708 709 if (obj->tiling_mode != I915_TILING_NONE) 710 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); 711 else 712 I915_WRITE(DVSLINOFF(pipe), linear_offset); 713 714 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); 715 I915_WRITE(DVSSCALE(pipe), dvsscale); 716 I915_WRITE(DVSCNTR(pipe), dvscntr); 717 I915_WRITE(DVSSURF(pipe), 718 i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); 719 POSTING_READ(DVSSURF(pipe)); 720 } 721 722 static void 723 ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) 724 { 725 struct drm_device *dev = plane->dev; 726 struct drm_i915_private *dev_priv = dev->dev_private; 727 struct intel_plane *intel_plane = to_intel_plane(plane); 728 int pipe = intel_plane->pipe; 729 730 I915_WRITE(DVSCNTR(pipe), 0); 731 /* Disable the scaler */ 732 I915_WRITE(DVSSCALE(pipe), 0); 733 734 I915_WRITE(DVSSURF(pipe), 0); 735 POSTING_READ(DVSSURF(pipe)); 736 } 737 738 static int 739 intel_check_sprite_plane(struct drm_plane *plane, 740 struct intel_crtc_state *crtc_state, 741 struct intel_plane_state *state) 742 { 743 struct drm_device *dev = plane->dev; 744 struct drm_crtc *crtc = state->base.crtc; 745 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 746 struct intel_plane *intel_plane = to_intel_plane(plane); 747 struct drm_framebuffer *fb = state->base.fb; 748 int crtc_x, crtc_y; 749 unsigned int crtc_w, crtc_h; 750 uint32_t src_x, src_y, src_w, src_h; 751 struct drm_rect *src = &state->src; 752 struct drm_rect *dst = &state->dst; 753 const struct drm_rect *clip = &state->clip; 754 int hscale, vscale; 755 int max_scale, min_scale; 756 bool can_scale; 757 int pixel_size; 758 759 if (!fb) { 760 state->visible = false; 761 return 0; 762 } 763 764 /* Don't modify another pipe's plane */ 765 if (intel_plane->pipe != intel_crtc->pipe) { 766 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); 767 return -EINVAL; 768 } 769 770 /* FIXME check all gen limits */ 771 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) { 772 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); 773 return -EINVAL; 774 } 775 776 /* setup can_scale, min_scale, max_scale */ 777 if (INTEL_INFO(dev)->gen >= 9) { 778 /* use scaler when colorkey is not required */ 779 if (state->ckey.flags == I915_SET_COLORKEY_NONE) { 780 can_scale = 1; 781 min_scale = 1; 782 max_scale = skl_max_scale(intel_crtc, crtc_state); 783 } else { 784 can_scale = 0; 785 min_scale = DRM_PLANE_HELPER_NO_SCALING; 786 max_scale = DRM_PLANE_HELPER_NO_SCALING; 787 } 788 } else { 789 can_scale = intel_plane->can_scale; 790 max_scale = intel_plane->max_downscale << 16; 791 min_scale = intel_plane->can_scale ? 1 : (1 << 16); 792 } 793 794 /* 795 * FIXME the following code does a bunch of fuzzy adjustments to the 796 * coordinates and sizes. We probably need some way to decide whether 797 * more strict checking should be done instead. 798 */ 799 drm_rect_rotate(src, fb->width << 16, fb->height << 16, 800 state->base.rotation); 801 802 hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale); 803 BUG_ON(hscale < 0); 804 805 vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale); 806 BUG_ON(vscale < 0); 807 808 state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); 809 810 crtc_x = dst->x1; 811 crtc_y = dst->y1; 812 crtc_w = drm_rect_width(dst); 813 crtc_h = drm_rect_height(dst); 814 815 if (state->visible) { 816 /* check again in case clipping clamped the results */ 817 hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); 818 if (hscale < 0) { 819 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); 820 drm_rect_debug_print("src: ", src, true); 821 drm_rect_debug_print("dst: ", dst, false); 822 823 return hscale; 824 } 825 826 vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); 827 if (vscale < 0) { 828 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); 829 drm_rect_debug_print("src: ", src, true); 830 drm_rect_debug_print("dst: ", dst, false); 831 832 return vscale; 833 } 834 835 /* Make the source viewport size an exact multiple of the scaling factors. */ 836 drm_rect_adjust_size(src, 837 drm_rect_width(dst) * hscale - drm_rect_width(src), 838 drm_rect_height(dst) * vscale - drm_rect_height(src)); 839 840 drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, 841 state->base.rotation); 842 843 /* sanity check to make sure the src viewport wasn't enlarged */ 844 WARN_ON(src->x1 < (int) state->base.src_x || 845 src->y1 < (int) state->base.src_y || 846 src->x2 > (int) state->base.src_x + state->base.src_w || 847 src->y2 > (int) state->base.src_y + state->base.src_h); 848 849 /* 850 * Hardware doesn't handle subpixel coordinates. 851 * Adjust to (macro)pixel boundary, but be careful not to 852 * increase the source viewport size, because that could 853 * push the downscaling factor out of bounds. 854 */ 855 src_x = src->x1 >> 16; 856 src_w = drm_rect_width(src) >> 16; 857 src_y = src->y1 >> 16; 858 src_h = drm_rect_height(src) >> 16; 859 860 if (format_is_yuv(fb->pixel_format)) { 861 src_x &= ~1; 862 src_w &= ~1; 863 864 /* 865 * Must keep src and dst the 866 * same if we can't scale. 867 */ 868 if (!can_scale) 869 crtc_w &= ~1; 870 871 if (crtc_w == 0) 872 state->visible = false; 873 } 874 } 875 876 /* Check size restrictions when scaling */ 877 if (state->visible && (src_w != crtc_w || src_h != crtc_h)) { 878 unsigned int width_bytes; 879 880 WARN_ON(!can_scale); 881 882 /* FIXME interlacing min height is 6 */ 883 884 if (crtc_w < 3 || crtc_h < 3) 885 state->visible = false; 886 887 if (src_w < 3 || src_h < 3) 888 state->visible = false; 889 890 pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 891 width_bytes = ((src_x * pixel_size) & 63) + 892 src_w * pixel_size; 893 894 if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 || 895 width_bytes > 4096 || fb->pitches[0] > 4096)) { 896 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); 897 return -EINVAL; 898 } 899 } 900 901 if (state->visible) { 902 src->x1 = src_x << 16; 903 src->x2 = (src_x + src_w) << 16; 904 src->y1 = src_y << 16; 905 src->y2 = (src_y + src_h) << 16; 906 } 907 908 dst->x1 = crtc_x; 909 dst->x2 = crtc_x + crtc_w; 910 dst->y1 = crtc_y; 911 dst->y2 = crtc_y + crtc_h; 912 913 return 0; 914 } 915 916 static void 917 intel_commit_sprite_plane(struct drm_plane *plane, 918 struct intel_plane_state *state) 919 { 920 struct drm_crtc *crtc = state->base.crtc; 921 struct intel_plane *intel_plane = to_intel_plane(plane); 922 struct drm_framebuffer *fb = state->base.fb; 923 924 crtc = crtc ? crtc : plane->crtc; 925 926 if (state->visible) { 927 intel_plane->update_plane(plane, crtc, fb, 928 state->dst.x1, state->dst.y1, 929 drm_rect_width(&state->dst), 930 drm_rect_height(&state->dst), 931 state->src.x1 >> 16, 932 state->src.y1 >> 16, 933 drm_rect_width(&state->src) >> 16, 934 drm_rect_height(&state->src) >> 16); 935 } else { 936 intel_plane->disable_plane(plane, crtc); 937 } 938 } 939 940 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 941 struct drm_file *file_priv) 942 { 943 struct drm_intel_sprite_colorkey *set = data; 944 struct drm_plane *plane; 945 struct drm_plane_state *plane_state; 946 struct drm_atomic_state *state; 947 struct drm_modeset_acquire_ctx ctx; 948 int ret = 0; 949 950 /* Make sure we don't try to enable both src & dest simultaneously */ 951 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) 952 return -EINVAL; 953 954 if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && 955 set->flags & I915_SET_COLORKEY_DESTINATION) 956 return -EINVAL; 957 958 plane = drm_plane_find(dev, set->plane_id); 959 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) 960 return -ENOENT; 961 962 drm_modeset_acquire_init(&ctx, 0); 963 964 state = drm_atomic_state_alloc(plane->dev); 965 if (!state) { 966 ret = -ENOMEM; 967 goto out; 968 } 969 state->acquire_ctx = &ctx; 970 971 while (1) { 972 plane_state = drm_atomic_get_plane_state(state, plane); 973 ret = PTR_ERR_OR_ZERO(plane_state); 974 if (!ret) { 975 to_intel_plane_state(plane_state)->ckey = *set; 976 ret = drm_atomic_commit(state); 977 } 978 979 if (ret != -EDEADLK) 980 break; 981 982 drm_atomic_state_clear(state); 983 drm_modeset_backoff(&ctx); 984 } 985 986 if (ret) 987 drm_atomic_state_free(state); 988 989 out: 990 drm_modeset_drop_locks(&ctx); 991 drm_modeset_acquire_fini(&ctx); 992 return ret; 993 } 994 995 static const uint32_t ilk_plane_formats[] = { 996 DRM_FORMAT_XRGB8888, 997 DRM_FORMAT_YUYV, 998 DRM_FORMAT_YVYU, 999 DRM_FORMAT_UYVY, 1000 DRM_FORMAT_VYUY, 1001 }; 1002 1003 static const uint32_t snb_plane_formats[] = { 1004 DRM_FORMAT_XBGR8888, 1005 DRM_FORMAT_XRGB8888, 1006 DRM_FORMAT_YUYV, 1007 DRM_FORMAT_YVYU, 1008 DRM_FORMAT_UYVY, 1009 DRM_FORMAT_VYUY, 1010 }; 1011 1012 static const uint32_t vlv_plane_formats[] = { 1013 DRM_FORMAT_RGB565, 1014 DRM_FORMAT_ABGR8888, 1015 DRM_FORMAT_ARGB8888, 1016 DRM_FORMAT_XBGR8888, 1017 DRM_FORMAT_XRGB8888, 1018 DRM_FORMAT_XBGR2101010, 1019 DRM_FORMAT_ABGR2101010, 1020 DRM_FORMAT_YUYV, 1021 DRM_FORMAT_YVYU, 1022 DRM_FORMAT_UYVY, 1023 DRM_FORMAT_VYUY, 1024 }; 1025 1026 static uint32_t skl_plane_formats[] = { 1027 DRM_FORMAT_RGB565, 1028 DRM_FORMAT_ABGR8888, 1029 DRM_FORMAT_ARGB8888, 1030 DRM_FORMAT_XBGR8888, 1031 DRM_FORMAT_XRGB8888, 1032 DRM_FORMAT_YUYV, 1033 DRM_FORMAT_YVYU, 1034 DRM_FORMAT_UYVY, 1035 DRM_FORMAT_VYUY, 1036 }; 1037 1038 int 1039 intel_plane_init(struct drm_device *dev, enum i915_pipe pipe, int plane) 1040 { 1041 struct intel_plane *intel_plane; 1042 struct intel_plane_state *state; 1043 unsigned long possible_crtcs; 1044 const uint32_t *plane_formats; 1045 int num_plane_formats; 1046 int ret; 1047 1048 if (INTEL_INFO(dev)->gen < 5) 1049 return -ENODEV; 1050 1051 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); 1052 if (!intel_plane) 1053 return -ENOMEM; 1054 1055 state = intel_create_plane_state(&intel_plane->base); 1056 if (!state) { 1057 kfree(intel_plane); 1058 return -ENOMEM; 1059 } 1060 intel_plane->base.state = &state->base; 1061 1062 switch (INTEL_INFO(dev)->gen) { 1063 case 5: 1064 case 6: 1065 intel_plane->can_scale = true; 1066 intel_plane->max_downscale = 16; 1067 intel_plane->update_plane = ilk_update_plane; 1068 intel_plane->disable_plane = ilk_disable_plane; 1069 1070 if (IS_GEN6(dev)) { 1071 plane_formats = snb_plane_formats; 1072 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 1073 } else { 1074 plane_formats = ilk_plane_formats; 1075 num_plane_formats = ARRAY_SIZE(ilk_plane_formats); 1076 } 1077 break; 1078 1079 case 7: 1080 case 8: 1081 if (IS_IVYBRIDGE(dev)) { 1082 intel_plane->can_scale = true; 1083 intel_plane->max_downscale = 2; 1084 } else { 1085 intel_plane->can_scale = false; 1086 intel_plane->max_downscale = 1; 1087 } 1088 1089 if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { 1090 intel_plane->update_plane = vlv_update_plane; 1091 intel_plane->disable_plane = vlv_disable_plane; 1092 1093 plane_formats = vlv_plane_formats; 1094 num_plane_formats = ARRAY_SIZE(vlv_plane_formats); 1095 } else { 1096 intel_plane->update_plane = ivb_update_plane; 1097 intel_plane->disable_plane = ivb_disable_plane; 1098 1099 plane_formats = snb_plane_formats; 1100 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 1101 } 1102 break; 1103 case 9: 1104 intel_plane->can_scale = true; 1105 intel_plane->update_plane = skl_update_plane; 1106 intel_plane->disable_plane = skl_disable_plane; 1107 state->scaler_id = -1; 1108 1109 plane_formats = skl_plane_formats; 1110 num_plane_formats = ARRAY_SIZE(skl_plane_formats); 1111 break; 1112 default: 1113 kfree(intel_plane); 1114 return -ENODEV; 1115 } 1116 1117 intel_plane->pipe = pipe; 1118 intel_plane->plane = plane; 1119 intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); 1120 intel_plane->check_plane = intel_check_sprite_plane; 1121 intel_plane->commit_plane = intel_commit_sprite_plane; 1122 possible_crtcs = (1 << pipe); 1123 ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, 1124 &intel_plane_funcs, 1125 plane_formats, num_plane_formats, 1126 DRM_PLANE_TYPE_OVERLAY, NULL); 1127 if (ret) { 1128 kfree(intel_plane); 1129 goto out; 1130 } 1131 1132 intel_create_rotation_property(dev, intel_plane); 1133 1134 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); 1135 1136 out: 1137 return ret; 1138 } 1139