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_atomic_helper.h> 34 #include <drm/drm_crtc.h> 35 #include <drm/drm_fourcc.h> 36 #include <drm/drm_rect.h> 37 #include <drm/drm_atomic.h> 38 #include <drm/drm_plane_helper.h> 39 #include "intel_drv.h" 40 #include "intel_frontbuffer.h" 41 #include <drm/i915_drm.h> 42 #include "i915_drv.h" 43 44 static bool 45 format_is_yuv(uint32_t format) 46 { 47 switch (format) { 48 case DRM_FORMAT_YUYV: 49 case DRM_FORMAT_UYVY: 50 case DRM_FORMAT_VYUY: 51 case DRM_FORMAT_YVYU: 52 return true; 53 default: 54 return false; 55 } 56 } 57 58 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, 59 int usecs) 60 { 61 /* paranoia */ 62 if (!adjusted_mode->crtc_htotal) 63 return 1; 64 65 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock, 66 1000 * adjusted_mode->crtc_htotal); 67 } 68 69 /* FIXME: We should instead only take spinlocks once for the entire update 70 * instead of once per mmio. */ 71 #if IS_ENABLED(CONFIG_PROVE_LOCKING) 72 #define VBLANK_EVASION_TIME_US 250 73 #else 74 #define VBLANK_EVASION_TIME_US 100 75 #endif 76 77 /** 78 * intel_pipe_update_start() - start update of a set of display registers 79 * @new_crtc_state: the new crtc state 80 * 81 * Mark the start of an update to pipe registers that should be updated 82 * atomically regarding vblank. If the next vblank will happens within 83 * the next 100 us, this function waits until the vblank passes. 84 * 85 * After a successful call to this function, interrupts will be disabled 86 * until a subsequent call to intel_pipe_update_end(). That is done to 87 * avoid random delays. 88 */ 89 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) 90 { 91 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); 92 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 93 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode; 94 long timeout = msecs_to_jiffies_timeout(1); 95 int scanline, min, max, vblank_start; 96 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); 97 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && 98 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI); 99 DEFINE_WAIT(wait); 100 101 vblank_start = adjusted_mode->crtc_vblank_start; 102 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) 103 vblank_start = DIV_ROUND_UP(vblank_start, 2); 104 105 /* FIXME needs to be calibrated sensibly */ 106 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode, 107 VBLANK_EVASION_TIME_US); 108 max = vblank_start - 1; 109 110 local_irq_disable(); 111 112 if (min <= 0 || max <= 0) 113 return; 114 115 if (WARN_ON(drm_crtc_vblank_get(&crtc->base))) 116 return; 117 118 crtc->debug.min_vbl = min; 119 crtc->debug.max_vbl = max; 120 trace_i915_pipe_update_start(crtc); 121 122 for (;;) { 123 /* 124 * prepare_to_wait() has a memory barrier, which guarantees 125 * other CPUs can see the task state update by the time we 126 * read the scanline. 127 */ 128 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); 129 130 scanline = intel_get_crtc_scanline(crtc); 131 if (scanline < min || scanline > max) 132 break; 133 134 if (timeout <= 0) { 135 DRM_ERROR("Potential atomic update failure on pipe %c\n", 136 pipe_name(crtc->pipe)); 137 break; 138 } 139 140 local_irq_enable(); 141 142 timeout = schedule_timeout(timeout); 143 144 local_irq_disable(); 145 } 146 147 finish_wait(wq, &wait); 148 149 drm_crtc_vblank_put(&crtc->base); 150 151 /* 152 * On VLV/CHV DSI the scanline counter would appear to 153 * increment approx. 1/3 of a scanline before start of vblank. 154 * The registers still get latched at start of vblank however. 155 * This means we must not write any registers on the first 156 * line of vblank (since not the whole line is actually in 157 * vblank). And unfortunately we can't use the interrupt to 158 * wait here since it will fire too soon. We could use the 159 * frame start interrupt instead since it will fire after the 160 * critical scanline, but that would require more changes 161 * in the interrupt code. So for now we'll just do the nasty 162 * thing and poll for the bad scanline to pass us by. 163 * 164 * FIXME figure out if BXT+ DSI suffers from this as well 165 */ 166 while (need_vlv_dsi_wa && scanline == vblank_start) 167 scanline = intel_get_crtc_scanline(crtc); 168 169 crtc->debug.scanline_start = scanline; 170 crtc->debug.start_vbl_time = ktime_get(); 171 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc); 172 173 trace_i915_pipe_update_vblank_evaded(crtc); 174 } 175 176 /** 177 * intel_pipe_update_end() - end update of a set of display registers 178 * @new_crtc_state: the new crtc state 179 * 180 * Mark the end of an update started with intel_pipe_update_start(). This 181 * re-enables interrupts and verifies the update was actually completed 182 * before a vblank. 183 */ 184 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) 185 { 186 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); 187 enum i915_pipe pipe = crtc->pipe; 188 int scanline_end = intel_get_crtc_scanline(crtc); 189 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc); 190 ktime_t end_vbl_time = ktime_get(); 191 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 192 193 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); 194 195 /* We're still in the vblank-evade critical section, this can't race. 196 * Would be slightly nice to just grab the vblank count and arm the 197 * event outside of the critical section - the spinlock might spin for a 198 * while ... */ 199 if (new_crtc_state->base.event) { 200 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0); 201 202 lockmgr(&crtc->base.dev->event_lock, LK_EXCLUSIVE); 203 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event); 204 lockmgr(&crtc->base.dev->event_lock, LK_RELEASE); 205 206 new_crtc_state->base.event = NULL; 207 } 208 209 local_irq_enable(); 210 211 if (intel_vgpu_active(dev_priv)) 212 return; 213 214 if (crtc->debug.start_vbl_count && 215 crtc->debug.start_vbl_count != end_vbl_count) { 216 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", 217 pipe_name(pipe), crtc->debug.start_vbl_count, 218 end_vbl_count, 219 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), 220 crtc->debug.min_vbl, crtc->debug.max_vbl, 221 crtc->debug.scanline_start, scanline_end); 222 } 223 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE 224 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > 225 VBLANK_EVASION_TIME_US) 226 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n", 227 pipe_name(pipe), 228 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), 229 VBLANK_EVASION_TIME_US); 230 #endif 231 } 232 233 void 234 skl_update_plane(struct intel_plane *plane, 235 const struct intel_crtc_state *crtc_state, 236 const struct intel_plane_state *plane_state) 237 { 238 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 239 const struct drm_framebuffer *fb = plane_state->base.fb; 240 enum plane_id plane_id = plane->id; 241 enum i915_pipe pipe = plane->pipe; 242 u32 plane_ctl = plane_state->ctl; 243 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 244 u32 surf_addr = plane_state->main.offset; 245 unsigned int rotation = plane_state->base.rotation; 246 u32 stride = skl_plane_stride(fb, 0, rotation); 247 u32 aux_stride = skl_plane_stride(fb, 1, rotation); 248 int crtc_x = plane_state->base.dst.x1; 249 int crtc_y = plane_state->base.dst.y1; 250 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); 251 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); 252 uint32_t x = plane_state->main.x; 253 uint32_t y = plane_state->main.y; 254 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; 255 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; 256 unsigned long irqflags; 257 258 /* Sizes are 0 based */ 259 src_w--; 260 src_h--; 261 crtc_w--; 262 crtc_h--; 263 264 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 265 266 if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { 267 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), 268 PLANE_COLOR_PIPE_GAMMA_ENABLE | 269 PLANE_COLOR_PIPE_CSC_ENABLE | 270 PLANE_COLOR_PLANE_GAMMA_DISABLE); 271 } 272 273 if (key->flags) { 274 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value); 275 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value); 276 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask); 277 } 278 279 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x); 280 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); 281 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); 282 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), 283 (plane_state->aux.offset - surf_addr) | aux_stride); 284 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), 285 (plane_state->aux.y << 16) | plane_state->aux.x); 286 287 /* program plane scaler */ 288 if (plane_state->scaler_id >= 0) { 289 int scaler_id = plane_state->scaler_id; 290 const struct intel_scaler *scaler; 291 292 scaler = &crtc_state->scaler_state.scalers[scaler_id]; 293 294 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), 295 PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode); 296 I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0); 297 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); 298 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), 299 ((crtc_w + 1) << 16)|(crtc_h + 1)); 300 301 I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); 302 } else { 303 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x); 304 } 305 306 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl); 307 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 308 intel_plane_ggtt_offset(plane_state) + surf_addr); 309 POSTING_READ_FW(PLANE_SURF(pipe, plane_id)); 310 311 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 312 } 313 314 void 315 skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) 316 { 317 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 318 enum plane_id plane_id = plane->id; 319 enum i915_pipe pipe = plane->pipe; 320 unsigned long irqflags; 321 322 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 323 324 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0); 325 326 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0); 327 POSTING_READ_FW(PLANE_SURF(pipe, plane_id)); 328 329 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 330 } 331 332 bool 333 skl_plane_get_hw_state(struct intel_plane *plane) 334 { 335 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 336 enum intel_display_power_domain power_domain; 337 enum plane_id plane_id = plane->id; 338 enum i915_pipe pipe = plane->pipe; 339 bool ret; 340 341 power_domain = POWER_DOMAIN_PIPE(pipe); 342 if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) 343 return false; 344 345 ret = I915_READ(PLANE_CTL(pipe, plane_id)) & PLANE_CTL_ENABLE; 346 347 intel_display_power_put(dev_priv, power_domain); 348 349 return ret; 350 } 351 352 static void 353 chv_update_csc(struct intel_plane *plane, uint32_t format) 354 { 355 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 356 enum plane_id plane_id = plane->id; 357 358 /* Seems RGB data bypasses the CSC always */ 359 if (!format_is_yuv(format)) 360 return; 361 362 /* 363 * BT.601 limited range YCbCr -> full range RGB 364 * 365 * |r| | 6537 4769 0| |cr | 366 * |g| = |-3330 4769 -1605| x |y-64| 367 * |b| | 0 4769 8263| |cb | 368 * 369 * Cb and Cr apparently come in as signed already, so no 370 * need for any offset. For Y we need to remove the offset. 371 */ 372 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64)); 373 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); 374 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); 375 376 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(4769) | SPCSC_C0(6537)); 377 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(-3330) | SPCSC_C0(0)); 378 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(-1605) | SPCSC_C0(4769)); 379 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(4769) | SPCSC_C0(0)); 380 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(8263)); 381 382 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64)); 383 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); 384 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); 385 386 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 387 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 388 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 389 } 390 391 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, 392 const struct intel_plane_state *plane_state) 393 { 394 const struct drm_framebuffer *fb = plane_state->base.fb; 395 unsigned int rotation = plane_state->base.rotation; 396 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 397 u32 sprctl; 398 399 sprctl = SP_ENABLE | SP_GAMMA_ENABLE; 400 401 switch (fb->format->format) { 402 case DRM_FORMAT_YUYV: 403 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; 404 break; 405 case DRM_FORMAT_YVYU: 406 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; 407 break; 408 case DRM_FORMAT_UYVY: 409 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; 410 break; 411 case DRM_FORMAT_VYUY: 412 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; 413 break; 414 case DRM_FORMAT_RGB565: 415 sprctl |= SP_FORMAT_BGR565; 416 break; 417 case DRM_FORMAT_XRGB8888: 418 sprctl |= SP_FORMAT_BGRX8888; 419 break; 420 case DRM_FORMAT_ARGB8888: 421 sprctl |= SP_FORMAT_BGRA8888; 422 break; 423 case DRM_FORMAT_XBGR2101010: 424 sprctl |= SP_FORMAT_RGBX1010102; 425 break; 426 case DRM_FORMAT_ABGR2101010: 427 sprctl |= SP_FORMAT_RGBA1010102; 428 break; 429 case DRM_FORMAT_XBGR8888: 430 sprctl |= SP_FORMAT_RGBX8888; 431 break; 432 case DRM_FORMAT_ABGR8888: 433 sprctl |= SP_FORMAT_RGBA8888; 434 break; 435 default: 436 MISSING_CASE(fb->format->format); 437 return 0; 438 } 439 440 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 441 sprctl |= SP_TILED; 442 443 if (rotation & DRM_MODE_ROTATE_180) 444 sprctl |= SP_ROTATE_180; 445 446 if (rotation & DRM_MODE_REFLECT_X) 447 sprctl |= SP_MIRROR; 448 449 if (key->flags & I915_SET_COLORKEY_SOURCE) 450 sprctl |= SP_SOURCE_KEY; 451 452 return sprctl; 453 } 454 455 static void 456 vlv_update_plane(struct intel_plane *plane, 457 const struct intel_crtc_state *crtc_state, 458 const struct intel_plane_state *plane_state) 459 { 460 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 461 const struct drm_framebuffer *fb = plane_state->base.fb; 462 enum i915_pipe pipe = plane->pipe; 463 enum plane_id plane_id = plane->id; 464 u32 sprctl = plane_state->ctl; 465 u32 sprsurf_offset = plane_state->main.offset; 466 u32 linear_offset; 467 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 468 int crtc_x = plane_state->base.dst.x1; 469 int crtc_y = plane_state->base.dst.y1; 470 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); 471 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); 472 uint32_t x = plane_state->main.x; 473 uint32_t y = plane_state->main.y; 474 unsigned long irqflags; 475 476 /* Sizes are 0 based */ 477 crtc_w--; 478 crtc_h--; 479 480 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); 481 482 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 483 484 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) 485 chv_update_csc(plane, fb->format->format); 486 487 if (key->flags) { 488 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value); 489 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value); 490 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask); 491 } 492 I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]); 493 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); 494 495 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 496 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x); 497 else 498 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset); 499 500 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0); 501 502 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w); 503 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl); 504 I915_WRITE_FW(SPSURF(pipe, plane_id), 505 intel_plane_ggtt_offset(plane_state) + sprsurf_offset); 506 POSTING_READ_FW(SPSURF(pipe, plane_id)); 507 508 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 509 } 510 511 static void 512 vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) 513 { 514 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 515 enum i915_pipe pipe = plane->pipe; 516 enum plane_id plane_id = plane->id; 517 unsigned long irqflags; 518 519 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 520 521 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0); 522 523 I915_WRITE_FW(SPSURF(pipe, plane_id), 0); 524 POSTING_READ_FW(SPSURF(pipe, plane_id)); 525 526 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 527 } 528 529 static bool 530 vlv_plane_get_hw_state(struct intel_plane *plane) 531 { 532 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 533 enum intel_display_power_domain power_domain; 534 enum plane_id plane_id = plane->id; 535 enum i915_pipe pipe = plane->pipe; 536 bool ret; 537 538 power_domain = POWER_DOMAIN_PIPE(pipe); 539 if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) 540 return false; 541 542 ret = I915_READ(SPCNTR(pipe, plane_id)) & SP_ENABLE; 543 544 intel_display_power_put(dev_priv, power_domain); 545 546 return ret; 547 } 548 549 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, 550 const struct intel_plane_state *plane_state) 551 { 552 struct drm_i915_private *dev_priv = 553 to_i915(plane_state->base.plane->dev); 554 const struct drm_framebuffer *fb = plane_state->base.fb; 555 unsigned int rotation = plane_state->base.rotation; 556 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 557 u32 sprctl; 558 559 sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE; 560 561 if (IS_IVYBRIDGE(dev_priv)) 562 sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 563 564 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) 565 sprctl |= SPRITE_PIPE_CSC_ENABLE; 566 567 switch (fb->format->format) { 568 case DRM_FORMAT_XBGR8888: 569 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; 570 break; 571 case DRM_FORMAT_XRGB8888: 572 sprctl |= SPRITE_FORMAT_RGBX888; 573 break; 574 case DRM_FORMAT_YUYV: 575 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; 576 break; 577 case DRM_FORMAT_YVYU: 578 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; 579 break; 580 case DRM_FORMAT_UYVY: 581 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; 582 break; 583 case DRM_FORMAT_VYUY: 584 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; 585 break; 586 default: 587 MISSING_CASE(fb->format->format); 588 return 0; 589 } 590 591 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 592 sprctl |= SPRITE_TILED; 593 594 if (rotation & DRM_MODE_ROTATE_180) 595 sprctl |= SPRITE_ROTATE_180; 596 597 if (key->flags & I915_SET_COLORKEY_DESTINATION) 598 sprctl |= SPRITE_DEST_KEY; 599 else if (key->flags & I915_SET_COLORKEY_SOURCE) 600 sprctl |= SPRITE_SOURCE_KEY; 601 602 return sprctl; 603 } 604 605 static void 606 ivb_update_plane(struct intel_plane *plane, 607 const struct intel_crtc_state *crtc_state, 608 const struct intel_plane_state *plane_state) 609 { 610 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 611 const struct drm_framebuffer *fb = plane_state->base.fb; 612 enum i915_pipe pipe = plane->pipe; 613 u32 sprctl = plane_state->ctl, sprscale = 0; 614 u32 sprsurf_offset = plane_state->main.offset; 615 u32 linear_offset; 616 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 617 int crtc_x = plane_state->base.dst.x1; 618 int crtc_y = plane_state->base.dst.y1; 619 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); 620 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); 621 uint32_t x = plane_state->main.x; 622 uint32_t y = plane_state->main.y; 623 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; 624 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; 625 unsigned long irqflags; 626 627 /* Sizes are 0 based */ 628 src_w--; 629 src_h--; 630 crtc_w--; 631 crtc_h--; 632 633 if (crtc_w != src_w || crtc_h != src_h) 634 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; 635 636 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); 637 638 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 639 640 if (key->flags) { 641 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value); 642 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value); 643 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask); 644 } 645 646 I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]); 647 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x); 648 649 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET 650 * register */ 651 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) 652 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x); 653 else if (fb->modifier == I915_FORMAT_MOD_X_TILED) 654 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x); 655 else 656 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset); 657 658 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); 659 if (plane->can_scale) 660 I915_WRITE_FW(SPRSCALE(pipe), sprscale); 661 I915_WRITE_FW(SPRCTL(pipe), sprctl); 662 I915_WRITE_FW(SPRSURF(pipe), 663 intel_plane_ggtt_offset(plane_state) + sprsurf_offset); 664 POSTING_READ_FW(SPRSURF(pipe)); 665 666 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 667 } 668 669 static void 670 ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) 671 { 672 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 673 enum i915_pipe pipe = plane->pipe; 674 unsigned long irqflags; 675 676 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 677 678 I915_WRITE_FW(SPRCTL(pipe), 0); 679 /* Can't leave the scaler enabled... */ 680 if (plane->can_scale) 681 I915_WRITE_FW(SPRSCALE(pipe), 0); 682 683 I915_WRITE_FW(SPRSURF(pipe), 0); 684 POSTING_READ_FW(SPRSURF(pipe)); 685 686 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 687 } 688 689 static bool 690 ivb_plane_get_hw_state(struct intel_plane *plane) 691 { 692 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 693 enum intel_display_power_domain power_domain; 694 enum i915_pipe pipe = plane->pipe; 695 bool ret; 696 697 power_domain = POWER_DOMAIN_PIPE(pipe); 698 if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) 699 return false; 700 701 ret = I915_READ(SPRCTL(pipe)) & SPRITE_ENABLE; 702 703 intel_display_power_put(dev_priv, power_domain); 704 705 return ret; 706 } 707 708 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, 709 const struct intel_plane_state *plane_state) 710 { 711 struct drm_i915_private *dev_priv = 712 to_i915(plane_state->base.plane->dev); 713 const struct drm_framebuffer *fb = plane_state->base.fb; 714 unsigned int rotation = plane_state->base.rotation; 715 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 716 u32 dvscntr; 717 718 dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE; 719 720 if (IS_GEN6(dev_priv)) 721 dvscntr |= DVS_TRICKLE_FEED_DISABLE; 722 723 switch (fb->format->format) { 724 case DRM_FORMAT_XBGR8888: 725 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; 726 break; 727 case DRM_FORMAT_XRGB8888: 728 dvscntr |= DVS_FORMAT_RGBX888; 729 break; 730 case DRM_FORMAT_YUYV: 731 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; 732 break; 733 case DRM_FORMAT_YVYU: 734 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; 735 break; 736 case DRM_FORMAT_UYVY: 737 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; 738 break; 739 case DRM_FORMAT_VYUY: 740 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; 741 break; 742 default: 743 MISSING_CASE(fb->format->format); 744 return 0; 745 } 746 747 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 748 dvscntr |= DVS_TILED; 749 750 if (rotation & DRM_MODE_ROTATE_180) 751 dvscntr |= DVS_ROTATE_180; 752 753 if (key->flags & I915_SET_COLORKEY_DESTINATION) 754 dvscntr |= DVS_DEST_KEY; 755 else if (key->flags & I915_SET_COLORKEY_SOURCE) 756 dvscntr |= DVS_SOURCE_KEY; 757 758 return dvscntr; 759 } 760 761 static void 762 g4x_update_plane(struct intel_plane *plane, 763 const struct intel_crtc_state *crtc_state, 764 const struct intel_plane_state *plane_state) 765 { 766 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 767 const struct drm_framebuffer *fb = plane_state->base.fb; 768 enum i915_pipe pipe = plane->pipe; 769 u32 dvscntr = plane_state->ctl, dvsscale = 0; 770 u32 dvssurf_offset = plane_state->main.offset; 771 u32 linear_offset; 772 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 773 int crtc_x = plane_state->base.dst.x1; 774 int crtc_y = plane_state->base.dst.y1; 775 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); 776 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); 777 uint32_t x = plane_state->main.x; 778 uint32_t y = plane_state->main.y; 779 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; 780 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; 781 unsigned long irqflags; 782 783 /* Sizes are 0 based */ 784 src_w--; 785 src_h--; 786 crtc_w--; 787 crtc_h--; 788 789 if (crtc_w != src_w || crtc_h != src_h) 790 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; 791 792 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); 793 794 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 795 796 if (key->flags) { 797 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value); 798 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value); 799 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask); 800 } 801 802 I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]); 803 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x); 804 805 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 806 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x); 807 else 808 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset); 809 810 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); 811 I915_WRITE_FW(DVSSCALE(pipe), dvsscale); 812 I915_WRITE_FW(DVSCNTR(pipe), dvscntr); 813 I915_WRITE_FW(DVSSURF(pipe), 814 intel_plane_ggtt_offset(plane_state) + dvssurf_offset); 815 POSTING_READ_FW(DVSSURF(pipe)); 816 817 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 818 } 819 820 static void 821 g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) 822 { 823 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 824 enum i915_pipe pipe = plane->pipe; 825 unsigned long irqflags; 826 827 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 828 829 I915_WRITE_FW(DVSCNTR(pipe), 0); 830 /* Disable the scaler */ 831 I915_WRITE_FW(DVSSCALE(pipe), 0); 832 833 I915_WRITE_FW(DVSSURF(pipe), 0); 834 POSTING_READ_FW(DVSSURF(pipe)); 835 836 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 837 } 838 839 static bool 840 g4x_plane_get_hw_state(struct intel_plane *plane) 841 { 842 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 843 enum intel_display_power_domain power_domain; 844 enum i915_pipe pipe = plane->pipe; 845 bool ret; 846 847 power_domain = POWER_DOMAIN_PIPE(pipe); 848 if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) 849 return false; 850 851 ret = I915_READ(DVSCNTR(pipe)) & DVS_ENABLE; 852 853 intel_display_power_put(dev_priv, power_domain); 854 855 return ret; 856 } 857 858 static int 859 intel_check_sprite_plane(struct intel_plane *plane, 860 struct intel_crtc_state *crtc_state, 861 struct intel_plane_state *state) 862 { 863 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 864 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); 865 struct drm_framebuffer *fb = state->base.fb; 866 int crtc_x, crtc_y; 867 unsigned int crtc_w, crtc_h; 868 uint32_t src_x, src_y, src_w, src_h; 869 struct drm_rect *src = &state->base.src; 870 struct drm_rect *dst = &state->base.dst; 871 const struct drm_rect *clip = &state->clip; 872 int hscale, vscale; 873 int max_scale, min_scale; 874 bool can_scale; 875 int ret; 876 877 *src = drm_plane_state_src(&state->base); 878 *dst = drm_plane_state_dest(&state->base); 879 880 if (!fb) { 881 state->base.visible = false; 882 return 0; 883 } 884 885 /* Don't modify another pipe's plane */ 886 if (plane->pipe != crtc->pipe) { 887 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); 888 return -EINVAL; 889 } 890 891 /* FIXME check all gen limits */ 892 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) { 893 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); 894 return -EINVAL; 895 } 896 897 /* setup can_scale, min_scale, max_scale */ 898 if (INTEL_GEN(dev_priv) >= 9) { 899 /* use scaler when colorkey is not required */ 900 if (state->ckey.flags == I915_SET_COLORKEY_NONE) { 901 can_scale = 1; 902 min_scale = 1; 903 max_scale = skl_max_scale(crtc, crtc_state); 904 } else { 905 can_scale = 0; 906 min_scale = DRM_PLANE_HELPER_NO_SCALING; 907 max_scale = DRM_PLANE_HELPER_NO_SCALING; 908 } 909 } else { 910 can_scale = plane->can_scale; 911 max_scale = plane->max_downscale << 16; 912 min_scale = plane->can_scale ? 1 : (1 << 16); 913 } 914 915 /* 916 * FIXME the following code does a bunch of fuzzy adjustments to the 917 * coordinates and sizes. We probably need some way to decide whether 918 * more strict checking should be done instead. 919 */ 920 drm_rect_rotate(src, fb->width << 16, fb->height << 16, 921 state->base.rotation); 922 923 hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale); 924 BUG_ON(hscale < 0); 925 926 vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale); 927 BUG_ON(vscale < 0); 928 929 state->base.visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); 930 931 crtc_x = dst->x1; 932 crtc_y = dst->y1; 933 crtc_w = drm_rect_width(dst); 934 crtc_h = drm_rect_height(dst); 935 936 if (state->base.visible) { 937 /* check again in case clipping clamped the results */ 938 hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); 939 if (hscale < 0) { 940 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); 941 drm_rect_debug_print("src: ", src, true); 942 drm_rect_debug_print("dst: ", dst, false); 943 944 return hscale; 945 } 946 947 vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); 948 if (vscale < 0) { 949 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); 950 drm_rect_debug_print("src: ", src, true); 951 drm_rect_debug_print("dst: ", dst, false); 952 953 return vscale; 954 } 955 956 /* Make the source viewport size an exact multiple of the scaling factors. */ 957 drm_rect_adjust_size(src, 958 drm_rect_width(dst) * hscale - drm_rect_width(src), 959 drm_rect_height(dst) * vscale - drm_rect_height(src)); 960 961 drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, 962 state->base.rotation); 963 964 /* sanity check to make sure the src viewport wasn't enlarged */ 965 WARN_ON(src->x1 < (int) state->base.src_x || 966 src->y1 < (int) state->base.src_y || 967 src->x2 > (int) state->base.src_x + state->base.src_w || 968 src->y2 > (int) state->base.src_y + state->base.src_h); 969 970 /* 971 * Hardware doesn't handle subpixel coordinates. 972 * Adjust to (macro)pixel boundary, but be careful not to 973 * increase the source viewport size, because that could 974 * push the downscaling factor out of bounds. 975 */ 976 src_x = src->x1 >> 16; 977 src_w = drm_rect_width(src) >> 16; 978 src_y = src->y1 >> 16; 979 src_h = drm_rect_height(src) >> 16; 980 981 if (format_is_yuv(fb->format->format)) { 982 src_x &= ~1; 983 src_w &= ~1; 984 985 /* 986 * Must keep src and dst the 987 * same if we can't scale. 988 */ 989 if (!can_scale) 990 crtc_w &= ~1; 991 992 if (crtc_w == 0) 993 state->base.visible = false; 994 } 995 } 996 997 /* Check size restrictions when scaling */ 998 if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) { 999 unsigned int width_bytes; 1000 int cpp = fb->format->cpp[0]; 1001 1002 WARN_ON(!can_scale); 1003 1004 /* FIXME interlacing min height is 6 */ 1005 1006 if (crtc_w < 3 || crtc_h < 3) 1007 state->base.visible = false; 1008 1009 if (src_w < 3 || src_h < 3) 1010 state->base.visible = false; 1011 1012 width_bytes = ((src_x * cpp) & 63) + src_w * cpp; 1013 1014 if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 || 1015 width_bytes > 4096 || fb->pitches[0] > 4096)) { 1016 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); 1017 return -EINVAL; 1018 } 1019 } 1020 1021 if (state->base.visible) { 1022 src->x1 = src_x << 16; 1023 src->x2 = (src_x + src_w) << 16; 1024 src->y1 = src_y << 16; 1025 src->y2 = (src_y + src_h) << 16; 1026 } 1027 1028 dst->x1 = crtc_x; 1029 dst->x2 = crtc_x + crtc_w; 1030 dst->y1 = crtc_y; 1031 dst->y2 = crtc_y + crtc_h; 1032 1033 if (INTEL_GEN(dev_priv) >= 9) { 1034 ret = skl_check_plane_surface(state); 1035 if (ret) 1036 return ret; 1037 1038 state->ctl = skl_plane_ctl(crtc_state, state); 1039 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 1040 ret = i9xx_check_plane_surface(state); 1041 if (ret) 1042 return ret; 1043 1044 state->ctl = vlv_sprite_ctl(crtc_state, state); 1045 } else if (INTEL_GEN(dev_priv) >= 7) { 1046 ret = i9xx_check_plane_surface(state); 1047 if (ret) 1048 return ret; 1049 1050 state->ctl = ivb_sprite_ctl(crtc_state, state); 1051 } else { 1052 ret = i9xx_check_plane_surface(state); 1053 if (ret) 1054 return ret; 1055 1056 state->ctl = g4x_sprite_ctl(crtc_state, state); 1057 } 1058 1059 return 0; 1060 } 1061 1062 int intel_sprite_set_colorkey(struct drm_device *dev, void *data, 1063 struct drm_file *file_priv) 1064 { 1065 struct drm_i915_private *dev_priv = to_i915(dev); 1066 struct drm_intel_sprite_colorkey *set = data; 1067 struct drm_plane *plane; 1068 struct drm_plane_state *plane_state; 1069 struct drm_atomic_state *state; 1070 struct drm_modeset_acquire_ctx ctx; 1071 int ret = 0; 1072 1073 /* Make sure we don't try to enable both src & dest simultaneously */ 1074 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) 1075 return -EINVAL; 1076 1077 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && 1078 set->flags & I915_SET_COLORKEY_DESTINATION) 1079 return -EINVAL; 1080 1081 plane = drm_plane_find(dev, file_priv, set->plane_id); 1082 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) 1083 return -ENOENT; 1084 1085 drm_modeset_acquire_init(&ctx, 0); 1086 1087 state = drm_atomic_state_alloc(plane->dev); 1088 if (!state) { 1089 ret = -ENOMEM; 1090 goto out; 1091 } 1092 state->acquire_ctx = &ctx; 1093 1094 while (1) { 1095 plane_state = drm_atomic_get_plane_state(state, plane); 1096 ret = PTR_ERR_OR_ZERO(plane_state); 1097 if (!ret) { 1098 to_intel_plane_state(plane_state)->ckey = *set; 1099 ret = drm_atomic_commit(state); 1100 } 1101 1102 if (ret != -EDEADLK) 1103 break; 1104 1105 drm_atomic_state_clear(state); 1106 drm_modeset_backoff(&ctx); 1107 } 1108 1109 drm_atomic_state_put(state); 1110 out: 1111 drm_modeset_drop_locks(&ctx); 1112 drm_modeset_acquire_fini(&ctx); 1113 return ret; 1114 } 1115 1116 static const uint32_t g4x_plane_formats[] = { 1117 DRM_FORMAT_XRGB8888, 1118 DRM_FORMAT_YUYV, 1119 DRM_FORMAT_YVYU, 1120 DRM_FORMAT_UYVY, 1121 DRM_FORMAT_VYUY, 1122 }; 1123 1124 static const uint64_t i9xx_plane_format_modifiers[] = { 1125 I915_FORMAT_MOD_X_TILED, 1126 DRM_FORMAT_MOD_LINEAR, 1127 DRM_FORMAT_MOD_INVALID 1128 }; 1129 1130 static const uint32_t snb_plane_formats[] = { 1131 DRM_FORMAT_XBGR8888, 1132 DRM_FORMAT_XRGB8888, 1133 DRM_FORMAT_YUYV, 1134 DRM_FORMAT_YVYU, 1135 DRM_FORMAT_UYVY, 1136 DRM_FORMAT_VYUY, 1137 }; 1138 1139 static const uint32_t vlv_plane_formats[] = { 1140 DRM_FORMAT_RGB565, 1141 DRM_FORMAT_ABGR8888, 1142 DRM_FORMAT_ARGB8888, 1143 DRM_FORMAT_XBGR8888, 1144 DRM_FORMAT_XRGB8888, 1145 DRM_FORMAT_XBGR2101010, 1146 DRM_FORMAT_ABGR2101010, 1147 DRM_FORMAT_YUYV, 1148 DRM_FORMAT_YVYU, 1149 DRM_FORMAT_UYVY, 1150 DRM_FORMAT_VYUY, 1151 }; 1152 1153 static uint32_t skl_plane_formats[] = { 1154 DRM_FORMAT_RGB565, 1155 DRM_FORMAT_ABGR8888, 1156 DRM_FORMAT_ARGB8888, 1157 DRM_FORMAT_XBGR8888, 1158 DRM_FORMAT_XRGB8888, 1159 DRM_FORMAT_YUYV, 1160 DRM_FORMAT_YVYU, 1161 DRM_FORMAT_UYVY, 1162 DRM_FORMAT_VYUY, 1163 }; 1164 1165 static const uint64_t skl_plane_format_modifiers[] = { 1166 I915_FORMAT_MOD_X_TILED, 1167 DRM_FORMAT_MOD_LINEAR, 1168 DRM_FORMAT_MOD_INVALID 1169 }; 1170 1171 static bool g4x_sprite_plane_format_mod_supported(struct drm_plane *plane, 1172 uint32_t format, 1173 uint64_t modifier) 1174 { 1175 switch (format) { 1176 case DRM_FORMAT_XBGR8888: 1177 case DRM_FORMAT_XRGB8888: 1178 case DRM_FORMAT_YUYV: 1179 case DRM_FORMAT_YVYU: 1180 case DRM_FORMAT_UYVY: 1181 case DRM_FORMAT_VYUY: 1182 if (modifier == DRM_FORMAT_MOD_LINEAR || 1183 modifier == I915_FORMAT_MOD_X_TILED) 1184 return true; 1185 /* fall through */ 1186 default: 1187 return false; 1188 } 1189 } 1190 1191 static bool vlv_sprite_plane_format_mod_supported(struct drm_plane *plane, 1192 uint32_t format, 1193 uint64_t modifier) 1194 { 1195 switch (format) { 1196 case DRM_FORMAT_YUYV: 1197 case DRM_FORMAT_YVYU: 1198 case DRM_FORMAT_UYVY: 1199 case DRM_FORMAT_VYUY: 1200 case DRM_FORMAT_RGB565: 1201 case DRM_FORMAT_XRGB8888: 1202 case DRM_FORMAT_ARGB8888: 1203 case DRM_FORMAT_XBGR2101010: 1204 case DRM_FORMAT_ABGR2101010: 1205 case DRM_FORMAT_XBGR8888: 1206 case DRM_FORMAT_ABGR8888: 1207 if (modifier == DRM_FORMAT_MOD_LINEAR || 1208 modifier == I915_FORMAT_MOD_X_TILED) 1209 return true; 1210 /* fall through */ 1211 default: 1212 return false; 1213 } 1214 } 1215 1216 static bool skl_sprite_plane_format_mod_supported(struct drm_plane *plane, 1217 uint32_t format, 1218 uint64_t modifier) 1219 { 1220 /* This is the same as primary plane since SKL has universal planes */ 1221 switch (format) { 1222 case DRM_FORMAT_XRGB8888: 1223 case DRM_FORMAT_XBGR8888: 1224 case DRM_FORMAT_ARGB8888: 1225 case DRM_FORMAT_ABGR8888: 1226 case DRM_FORMAT_RGB565: 1227 case DRM_FORMAT_XRGB2101010: 1228 case DRM_FORMAT_XBGR2101010: 1229 case DRM_FORMAT_YUYV: 1230 case DRM_FORMAT_YVYU: 1231 case DRM_FORMAT_UYVY: 1232 case DRM_FORMAT_VYUY: 1233 if (modifier == I915_FORMAT_MOD_Yf_TILED) 1234 return true; 1235 /* fall through */ 1236 case DRM_FORMAT_C8: 1237 if (modifier == DRM_FORMAT_MOD_LINEAR || 1238 modifier == I915_FORMAT_MOD_X_TILED || 1239 modifier == I915_FORMAT_MOD_Y_TILED) 1240 return true; 1241 /* fall through */ 1242 default: 1243 return false; 1244 } 1245 } 1246 1247 static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane, 1248 uint32_t format, 1249 uint64_t modifier) 1250 { 1251 struct drm_i915_private *dev_priv = to_i915(plane->dev); 1252 1253 if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID)) 1254 return false; 1255 1256 if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL && 1257 modifier != DRM_FORMAT_MOD_LINEAR) 1258 return false; 1259 1260 if (INTEL_GEN(dev_priv) >= 9) 1261 return skl_sprite_plane_format_mod_supported(plane, format, modifier); 1262 else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 1263 return vlv_sprite_plane_format_mod_supported(plane, format, modifier); 1264 else 1265 return g4x_sprite_plane_format_mod_supported(plane, format, modifier); 1266 1267 unreachable(); 1268 } 1269 1270 static const struct drm_plane_funcs intel_sprite_plane_funcs = { 1271 .update_plane = drm_atomic_helper_update_plane, 1272 .disable_plane = drm_atomic_helper_disable_plane, 1273 .destroy = intel_plane_destroy, 1274 .atomic_get_property = intel_plane_atomic_get_property, 1275 .atomic_set_property = intel_plane_atomic_set_property, 1276 .atomic_duplicate_state = intel_plane_duplicate_state, 1277 .atomic_destroy_state = intel_plane_destroy_state, 1278 .format_mod_supported = intel_sprite_plane_format_mod_supported, 1279 }; 1280 1281 struct intel_plane * 1282 intel_sprite_plane_create(struct drm_i915_private *dev_priv, 1283 enum i915_pipe pipe, int plane) 1284 { 1285 struct intel_plane *intel_plane = NULL; 1286 struct intel_plane_state *state = NULL; 1287 unsigned long possible_crtcs; 1288 const uint32_t *plane_formats; 1289 const uint64_t *modifiers; 1290 unsigned int supported_rotations; 1291 int num_plane_formats; 1292 int ret; 1293 1294 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); 1295 if (!intel_plane) { 1296 ret = -ENOMEM; 1297 goto fail; 1298 } 1299 1300 state = intel_create_plane_state(&intel_plane->base); 1301 if (!state) { 1302 ret = -ENOMEM; 1303 goto fail; 1304 } 1305 intel_plane->base.state = &state->base; 1306 1307 if (INTEL_GEN(dev_priv) >= 10) { 1308 intel_plane->can_scale = true; 1309 state->scaler_id = -1; 1310 1311 intel_plane->update_plane = skl_update_plane; 1312 intel_plane->disable_plane = skl_disable_plane; 1313 intel_plane->get_hw_state = skl_plane_get_hw_state; 1314 1315 plane_formats = skl_plane_formats; 1316 num_plane_formats = ARRAY_SIZE(skl_plane_formats); 1317 modifiers = skl_plane_format_modifiers; 1318 } else if (INTEL_GEN(dev_priv) >= 9) { 1319 intel_plane->can_scale = true; 1320 state->scaler_id = -1; 1321 1322 intel_plane->update_plane = skl_update_plane; 1323 intel_plane->disable_plane = skl_disable_plane; 1324 intel_plane->get_hw_state = skl_plane_get_hw_state; 1325 1326 plane_formats = skl_plane_formats; 1327 num_plane_formats = ARRAY_SIZE(skl_plane_formats); 1328 modifiers = skl_plane_format_modifiers; 1329 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 1330 intel_plane->can_scale = false; 1331 intel_plane->max_downscale = 1; 1332 1333 intel_plane->update_plane = vlv_update_plane; 1334 intel_plane->disable_plane = vlv_disable_plane; 1335 intel_plane->get_hw_state = vlv_plane_get_hw_state; 1336 1337 plane_formats = vlv_plane_formats; 1338 num_plane_formats = ARRAY_SIZE(vlv_plane_formats); 1339 modifiers = i9xx_plane_format_modifiers; 1340 } else if (INTEL_GEN(dev_priv) >= 7) { 1341 if (IS_IVYBRIDGE(dev_priv)) { 1342 intel_plane->can_scale = true; 1343 intel_plane->max_downscale = 2; 1344 } else { 1345 intel_plane->can_scale = false; 1346 intel_plane->max_downscale = 1; 1347 } 1348 1349 intel_plane->update_plane = ivb_update_plane; 1350 intel_plane->disable_plane = ivb_disable_plane; 1351 intel_plane->get_hw_state = ivb_plane_get_hw_state; 1352 1353 plane_formats = snb_plane_formats; 1354 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 1355 modifiers = i9xx_plane_format_modifiers; 1356 } else { 1357 intel_plane->can_scale = true; 1358 intel_plane->max_downscale = 16; 1359 1360 intel_plane->update_plane = g4x_update_plane; 1361 intel_plane->disable_plane = g4x_disable_plane; 1362 intel_plane->get_hw_state = g4x_plane_get_hw_state; 1363 1364 modifiers = i9xx_plane_format_modifiers; 1365 if (IS_GEN6(dev_priv)) { 1366 plane_formats = snb_plane_formats; 1367 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 1368 } else { 1369 plane_formats = g4x_plane_formats; 1370 num_plane_formats = ARRAY_SIZE(g4x_plane_formats); 1371 } 1372 } 1373 1374 if (INTEL_GEN(dev_priv) >= 9) { 1375 supported_rotations = 1376 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | 1377 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; 1378 } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { 1379 supported_rotations = 1380 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 1381 DRM_MODE_REFLECT_X; 1382 } else { 1383 supported_rotations = 1384 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 1385 } 1386 1387 intel_plane->pipe = pipe; 1388 intel_plane->plane = plane; 1389 intel_plane->id = PLANE_SPRITE0 + plane; 1390 intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); 1391 intel_plane->check_plane = intel_check_sprite_plane; 1392 1393 possible_crtcs = (1 << pipe); 1394 1395 if (INTEL_GEN(dev_priv) >= 9) 1396 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base, 1397 possible_crtcs, &intel_sprite_plane_funcs, 1398 plane_formats, num_plane_formats, 1399 modifiers, 1400 DRM_PLANE_TYPE_OVERLAY, 1401 "plane %d%c", plane + 2, pipe_name(pipe)); 1402 else 1403 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base, 1404 possible_crtcs, &intel_sprite_plane_funcs, 1405 plane_formats, num_plane_formats, 1406 modifiers, 1407 DRM_PLANE_TYPE_OVERLAY, 1408 "sprite %c", sprite_name(pipe, plane)); 1409 if (ret) 1410 goto fail; 1411 1412 drm_plane_create_rotation_property(&intel_plane->base, 1413 DRM_MODE_ROTATE_0, 1414 supported_rotations); 1415 1416 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); 1417 1418 return intel_plane; 1419 1420 fail: 1421 kfree(state); 1422 kfree(intel_plane); 1423 1424 return ERR_PTR(ret); 1425 } 1426