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