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 33 #include <linux/string_helpers.h> 34 35 #include <drm/drm_atomic_helper.h> 36 #include <drm/drm_blend.h> 37 #include <drm/drm_color_mgmt.h> 38 #include <drm/drm_fourcc.h> 39 #include <drm/drm_rect.h> 40 41 #include "i915_drv.h" 42 #include "i915_reg.h" 43 #include "i9xx_plane.h" 44 #include "intel_atomic_plane.h" 45 #include "intel_de.h" 46 #include "intel_display_types.h" 47 #include "intel_fb.h" 48 #include "intel_frontbuffer.h" 49 #include "intel_sprite.h" 50 #include "intel_sprite_regs.h" 51 52 static char sprite_name(struct drm_i915_private *i915, enum pipe pipe, int sprite) 53 { 54 return pipe * DISPLAY_RUNTIME_INFO(i915)->num_sprites[pipe] + sprite + 'A'; 55 } 56 57 static void i9xx_plane_linear_gamma(u16 gamma[8]) 58 { 59 /* The points are not evenly spaced. */ 60 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 }; 61 int i; 62 63 for (i = 0; i < 8; i++) 64 gamma[i] = (in[i] << 8) / 32; 65 } 66 67 static void 68 chv_sprite_update_csc(const struct intel_plane_state *plane_state) 69 { 70 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 71 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 72 const struct drm_framebuffer *fb = plane_state->hw.fb; 73 enum plane_id plane_id = plane->id; 74 /* 75 * |r| | c0 c1 c2 | |cr| 76 * |g| = | c3 c4 c5 | x |y | 77 * |b| | c6 c7 c8 | |cb| 78 * 79 * Coefficients are s3.12. 80 * 81 * Cb and Cr apparently come in as signed already, and 82 * we always get full range data in on account of CLRC0/1. 83 */ 84 static const s16 csc_matrix[][9] = { 85 /* BT.601 full range YCbCr -> full range RGB */ 86 [DRM_COLOR_YCBCR_BT601] = { 87 5743, 4096, 0, 88 -2925, 4096, -1410, 89 0, 4096, 7258, 90 }, 91 /* BT.709 full range YCbCr -> full range RGB */ 92 [DRM_COLOR_YCBCR_BT709] = { 93 6450, 4096, 0, 94 -1917, 4096, -767, 95 0, 4096, 7601, 96 }, 97 }; 98 const s16 *csc = csc_matrix[plane_state->hw.color_encoding]; 99 100 /* Seems RGB data bypasses the CSC always */ 101 if (!fb->format->is_yuv) 102 return; 103 104 intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id), 105 SPCSC_OOFF(0) | SPCSC_IOFF(0)); 106 intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id), 107 SPCSC_OOFF(0) | SPCSC_IOFF(0)); 108 intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id), 109 SPCSC_OOFF(0) | SPCSC_IOFF(0)); 110 111 intel_de_write_fw(dev_priv, SPCSCC01(plane_id), 112 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0])); 113 intel_de_write_fw(dev_priv, SPCSCC23(plane_id), 114 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2])); 115 intel_de_write_fw(dev_priv, SPCSCC45(plane_id), 116 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4])); 117 intel_de_write_fw(dev_priv, SPCSCC67(plane_id), 118 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6])); 119 intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8])); 120 121 intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id), 122 SPCSC_IMAX(1023) | SPCSC_IMIN(0)); 123 intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id), 124 SPCSC_IMAX(512) | SPCSC_IMIN(-512)); 125 intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id), 126 SPCSC_IMAX(512) | SPCSC_IMIN(-512)); 127 128 intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id), 129 SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 130 intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id), 131 SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 132 intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id), 133 SPCSC_OMAX(1023) | SPCSC_OMIN(0)); 134 } 135 136 #define SIN_0 0 137 #define COS_0 1 138 139 static void 140 vlv_sprite_update_clrc(const struct intel_plane_state *plane_state) 141 { 142 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 143 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 144 const struct drm_framebuffer *fb = plane_state->hw.fb; 145 enum pipe pipe = plane->pipe; 146 enum plane_id plane_id = plane->id; 147 int contrast, brightness, sh_scale, sh_sin, sh_cos; 148 149 if (fb->format->is_yuv && 150 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) { 151 /* 152 * Expand limited range to full range: 153 * Contrast is applied first and is used to expand Y range. 154 * Brightness is applied second and is used to remove the 155 * offset from Y. Saturation/hue is used to expand CbCr range. 156 */ 157 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16); 158 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16); 159 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128); 160 sh_sin = SIN_0 * sh_scale; 161 sh_cos = COS_0 * sh_scale; 162 } else { 163 /* Pass-through everything. */ 164 contrast = 1 << 6; 165 brightness = 0; 166 sh_scale = 1 << 7; 167 sh_sin = SIN_0 * sh_scale; 168 sh_cos = COS_0 * sh_scale; 169 } 170 171 /* FIXME these register are single buffered :( */ 172 intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id), 173 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness)); 174 intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id), 175 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos)); 176 } 177 178 static void 179 vlv_plane_ratio(const struct intel_crtc_state *crtc_state, 180 const struct intel_plane_state *plane_state, 181 unsigned int *num, unsigned int *den) 182 { 183 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); 184 const struct drm_framebuffer *fb = plane_state->hw.fb; 185 unsigned int cpp = fb->format->cpp[0]; 186 187 /* 188 * VLV bspec only considers cases where all three planes are 189 * enabled, and cases where the primary and one sprite is enabled. 190 * Let's assume the case with just two sprites enabled also 191 * maps to the latter case. 192 */ 193 if (hweight8(active_planes) == 3) { 194 switch (cpp) { 195 case 8: 196 *num = 11; 197 *den = 8; 198 break; 199 case 4: 200 *num = 18; 201 *den = 16; 202 break; 203 default: 204 *num = 1; 205 *den = 1; 206 break; 207 } 208 } else if (hweight8(active_planes) == 2) { 209 switch (cpp) { 210 case 8: 211 *num = 10; 212 *den = 8; 213 break; 214 case 4: 215 *num = 17; 216 *den = 16; 217 break; 218 default: 219 *num = 1; 220 *den = 1; 221 break; 222 } 223 } else { 224 switch (cpp) { 225 case 8: 226 *num = 10; 227 *den = 8; 228 break; 229 default: 230 *num = 1; 231 *den = 1; 232 break; 233 } 234 } 235 } 236 237 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 238 const struct intel_plane_state *plane_state) 239 { 240 unsigned int pixel_rate; 241 unsigned int num, den; 242 243 /* 244 * Note that crtc_state->pixel_rate accounts for both 245 * horizontal and vertical panel fitter downscaling factors. 246 * Pre-HSW bspec tells us to only consider the horizontal 247 * downscaling factor here. We ignore that and just consider 248 * both for simplicity. 249 */ 250 pixel_rate = crtc_state->pixel_rate; 251 252 vlv_plane_ratio(crtc_state, plane_state, &num, &den); 253 254 return DIV_ROUND_UP(pixel_rate * num, den); 255 } 256 257 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) 258 { 259 u32 sprctl = 0; 260 261 if (crtc_state->gamma_enable) 262 sprctl |= SP_PIPE_GAMMA_ENABLE; 263 264 return sprctl; 265 } 266 267 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, 268 const struct intel_plane_state *plane_state) 269 { 270 const struct drm_framebuffer *fb = plane_state->hw.fb; 271 unsigned int rotation = plane_state->hw.rotation; 272 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 273 u32 sprctl; 274 275 sprctl = SP_ENABLE; 276 277 switch (fb->format->format) { 278 case DRM_FORMAT_YUYV: 279 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; 280 break; 281 case DRM_FORMAT_YVYU: 282 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; 283 break; 284 case DRM_FORMAT_UYVY: 285 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; 286 break; 287 case DRM_FORMAT_VYUY: 288 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; 289 break; 290 case DRM_FORMAT_C8: 291 sprctl |= SP_FORMAT_8BPP; 292 break; 293 case DRM_FORMAT_RGB565: 294 sprctl |= SP_FORMAT_BGR565; 295 break; 296 case DRM_FORMAT_XRGB8888: 297 sprctl |= SP_FORMAT_BGRX8888; 298 break; 299 case DRM_FORMAT_ARGB8888: 300 sprctl |= SP_FORMAT_BGRA8888; 301 break; 302 case DRM_FORMAT_XBGR2101010: 303 sprctl |= SP_FORMAT_RGBX1010102; 304 break; 305 case DRM_FORMAT_ABGR2101010: 306 sprctl |= SP_FORMAT_RGBA1010102; 307 break; 308 case DRM_FORMAT_XRGB2101010: 309 sprctl |= SP_FORMAT_BGRX1010102; 310 break; 311 case DRM_FORMAT_ARGB2101010: 312 sprctl |= SP_FORMAT_BGRA1010102; 313 break; 314 case DRM_FORMAT_XBGR8888: 315 sprctl |= SP_FORMAT_RGBX8888; 316 break; 317 case DRM_FORMAT_ABGR8888: 318 sprctl |= SP_FORMAT_RGBA8888; 319 break; 320 default: 321 MISSING_CASE(fb->format->format); 322 return 0; 323 } 324 325 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) 326 sprctl |= SP_YUV_FORMAT_BT709; 327 328 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 329 sprctl |= SP_TILED; 330 331 if (rotation & DRM_MODE_ROTATE_180) 332 sprctl |= SP_ROTATE_180; 333 334 if (rotation & DRM_MODE_REFLECT_X) 335 sprctl |= SP_MIRROR; 336 337 if (key->flags & I915_SET_COLORKEY_SOURCE) 338 sprctl |= SP_SOURCE_KEY; 339 340 return sprctl; 341 } 342 343 static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state) 344 { 345 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 346 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 347 const struct drm_framebuffer *fb = plane_state->hw.fb; 348 enum pipe pipe = plane->pipe; 349 enum plane_id plane_id = plane->id; 350 u16 gamma[8]; 351 int i; 352 353 /* Seems RGB data bypasses the gamma always */ 354 if (!fb->format->is_yuv) 355 return; 356 357 i9xx_plane_linear_gamma(gamma); 358 359 /* FIXME these register are single buffered :( */ 360 /* The two end points are implicit (0.0 and 1.0) */ 361 for (i = 1; i < 8 - 1; i++) 362 intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1), 363 gamma[i] << 16 | gamma[i] << 8 | gamma[i]); 364 } 365 366 static void 367 vlv_sprite_update_noarm(struct intel_plane *plane, 368 const struct intel_crtc_state *crtc_state, 369 const struct intel_plane_state *plane_state) 370 { 371 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 372 enum pipe pipe = plane->pipe; 373 enum plane_id plane_id = plane->id; 374 int crtc_x = plane_state->uapi.dst.x1; 375 int crtc_y = plane_state->uapi.dst.y1; 376 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); 377 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); 378 379 intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id), 380 plane_state->view.color_plane[0].mapping_stride); 381 intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id), 382 SP_POS_Y(crtc_y) | SP_POS_X(crtc_x)); 383 intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id), 384 SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1)); 385 } 386 387 static void 388 vlv_sprite_update_arm(struct intel_plane *plane, 389 const struct intel_crtc_state *crtc_state, 390 const struct intel_plane_state *plane_state) 391 { 392 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 393 enum pipe pipe = plane->pipe; 394 enum plane_id plane_id = plane->id; 395 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 396 u32 sprsurf_offset = plane_state->view.color_plane[0].offset; 397 u32 x = plane_state->view.color_plane[0].x; 398 u32 y = plane_state->view.color_plane[0].y; 399 u32 sprctl, linear_offset; 400 401 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state); 402 403 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); 404 405 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) 406 chv_sprite_update_csc(plane_state); 407 408 if (key->flags) { 409 intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id), 410 key->min_value); 411 intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id), 412 key->channel_mask); 413 intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id), 414 key->max_value); 415 } 416 417 intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0); 418 419 intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset); 420 intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), 421 SP_OFFSET_Y(y) | SP_OFFSET_X(x)); 422 423 /* 424 * The control register self-arms if the plane was previously 425 * disabled. Try to make the plane enable atomic by writing 426 * the control register just before the surface register. 427 */ 428 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl); 429 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 430 intel_plane_ggtt_offset(plane_state) + sprsurf_offset); 431 432 vlv_sprite_update_clrc(plane_state); 433 vlv_sprite_update_gamma(plane_state); 434 } 435 436 static void 437 vlv_sprite_disable_arm(struct intel_plane *plane, 438 const struct intel_crtc_state *crtc_state) 439 { 440 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 441 enum pipe pipe = plane->pipe; 442 enum plane_id plane_id = plane->id; 443 444 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0); 445 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0); 446 } 447 448 static bool 449 vlv_sprite_get_hw_state(struct intel_plane *plane, 450 enum pipe *pipe) 451 { 452 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 453 enum intel_display_power_domain power_domain; 454 enum plane_id plane_id = plane->id; 455 intel_wakeref_t wakeref; 456 bool ret; 457 458 power_domain = POWER_DOMAIN_PIPE(plane->pipe); 459 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); 460 if (!wakeref) 461 return false; 462 463 ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE; 464 465 *pipe = plane->pipe; 466 467 intel_display_power_put(dev_priv, power_domain, wakeref); 468 469 return ret; 470 } 471 472 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state, 473 const struct intel_plane_state *plane_state, 474 unsigned int *num, unsigned int *den) 475 { 476 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); 477 const struct drm_framebuffer *fb = plane_state->hw.fb; 478 unsigned int cpp = fb->format->cpp[0]; 479 480 if (hweight8(active_planes) == 2) { 481 switch (cpp) { 482 case 8: 483 *num = 10; 484 *den = 8; 485 break; 486 case 4: 487 *num = 17; 488 *den = 16; 489 break; 490 default: 491 *num = 1; 492 *den = 1; 493 break; 494 } 495 } else { 496 switch (cpp) { 497 case 8: 498 *num = 9; 499 *den = 8; 500 break; 501 default: 502 *num = 1; 503 *den = 1; 504 break; 505 } 506 } 507 } 508 509 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state, 510 const struct intel_plane_state *plane_state, 511 unsigned int *num, unsigned int *den) 512 { 513 const struct drm_framebuffer *fb = plane_state->hw.fb; 514 unsigned int cpp = fb->format->cpp[0]; 515 516 switch (cpp) { 517 case 8: 518 *num = 12; 519 *den = 8; 520 break; 521 case 4: 522 *num = 19; 523 *den = 16; 524 break; 525 case 2: 526 *num = 33; 527 *den = 32; 528 break; 529 default: 530 *num = 1; 531 *den = 1; 532 break; 533 } 534 } 535 536 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 537 const struct intel_plane_state *plane_state) 538 { 539 unsigned int pixel_rate; 540 unsigned int num, den; 541 542 /* 543 * Note that crtc_state->pixel_rate accounts for both 544 * horizontal and vertical panel fitter downscaling factors. 545 * Pre-HSW bspec tells us to only consider the horizontal 546 * downscaling factor here. We ignore that and just consider 547 * both for simplicity. 548 */ 549 pixel_rate = crtc_state->pixel_rate; 550 551 ivb_plane_ratio(crtc_state, plane_state, &num, &den); 552 553 return DIV_ROUND_UP(pixel_rate * num, den); 554 } 555 556 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, 557 const struct intel_plane_state *plane_state) 558 { 559 unsigned int src_w, dst_w, pixel_rate; 560 unsigned int num, den; 561 562 /* 563 * Note that crtc_state->pixel_rate accounts for both 564 * horizontal and vertical panel fitter downscaling factors. 565 * Pre-HSW bspec tells us to only consider the horizontal 566 * downscaling factor here. We ignore that and just consider 567 * both for simplicity. 568 */ 569 pixel_rate = crtc_state->pixel_rate; 570 571 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 572 dst_w = drm_rect_width(&plane_state->uapi.dst); 573 574 if (src_w != dst_w) 575 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den); 576 else 577 ivb_plane_ratio(crtc_state, plane_state, &num, &den); 578 579 /* Horizontal downscaling limits the maximum pixel rate */ 580 dst_w = min(src_w, dst_w); 581 582 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w), 583 den * dst_w); 584 } 585 586 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state, 587 const struct intel_plane_state *plane_state, 588 unsigned int *num, unsigned int *den) 589 { 590 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); 591 const struct drm_framebuffer *fb = plane_state->hw.fb; 592 unsigned int cpp = fb->format->cpp[0]; 593 594 if (hweight8(active_planes) == 2) { 595 switch (cpp) { 596 case 8: 597 *num = 10; 598 *den = 8; 599 break; 600 default: 601 *num = 1; 602 *den = 1; 603 break; 604 } 605 } else { 606 switch (cpp) { 607 case 8: 608 *num = 9; 609 *den = 8; 610 break; 611 default: 612 *num = 1; 613 *den = 1; 614 break; 615 } 616 } 617 } 618 619 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 620 const struct intel_plane_state *plane_state) 621 { 622 unsigned int pixel_rate = crtc_state->pixel_rate; 623 unsigned int num, den; 624 625 hsw_plane_ratio(crtc_state, plane_state, &num, &den); 626 627 return DIV_ROUND_UP(pixel_rate * num, den); 628 } 629 630 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) 631 { 632 u32 sprctl = 0; 633 634 if (crtc_state->gamma_enable) 635 sprctl |= SPRITE_PIPE_GAMMA_ENABLE; 636 637 if (crtc_state->csc_enable) 638 sprctl |= SPRITE_PIPE_CSC_ENABLE; 639 640 return sprctl; 641 } 642 643 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state) 644 { 645 struct drm_i915_private *dev_priv = 646 to_i915(plane_state->uapi.plane->dev); 647 const struct drm_framebuffer *fb = plane_state->hw.fb; 648 649 return fb->format->cpp[0] == 8 && 650 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)); 651 } 652 653 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, 654 const struct intel_plane_state *plane_state) 655 { 656 struct drm_i915_private *dev_priv = 657 to_i915(plane_state->uapi.plane->dev); 658 const struct drm_framebuffer *fb = plane_state->hw.fb; 659 unsigned int rotation = plane_state->hw.rotation; 660 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 661 u32 sprctl; 662 663 sprctl = SPRITE_ENABLE; 664 665 if (IS_IVYBRIDGE(dev_priv)) 666 sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 667 668 switch (fb->format->format) { 669 case DRM_FORMAT_XBGR8888: 670 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; 671 break; 672 case DRM_FORMAT_XRGB8888: 673 sprctl |= SPRITE_FORMAT_RGBX888; 674 break; 675 case DRM_FORMAT_XBGR2101010: 676 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX; 677 break; 678 case DRM_FORMAT_XRGB2101010: 679 sprctl |= SPRITE_FORMAT_RGBX101010; 680 break; 681 case DRM_FORMAT_XBGR16161616F: 682 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX; 683 break; 684 case DRM_FORMAT_XRGB16161616F: 685 sprctl |= SPRITE_FORMAT_RGBX161616; 686 break; 687 case DRM_FORMAT_YUYV: 688 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; 689 break; 690 case DRM_FORMAT_YVYU: 691 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; 692 break; 693 case DRM_FORMAT_UYVY: 694 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; 695 break; 696 case DRM_FORMAT_VYUY: 697 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; 698 break; 699 default: 700 MISSING_CASE(fb->format->format); 701 return 0; 702 } 703 704 if (!ivb_need_sprite_gamma(plane_state)) 705 sprctl |= SPRITE_PLANE_GAMMA_DISABLE; 706 707 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) 708 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709; 709 710 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 711 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE; 712 713 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 714 sprctl |= SPRITE_TILED; 715 716 if (rotation & DRM_MODE_ROTATE_180) 717 sprctl |= SPRITE_ROTATE_180; 718 719 if (key->flags & I915_SET_COLORKEY_DESTINATION) 720 sprctl |= SPRITE_DEST_KEY; 721 else if (key->flags & I915_SET_COLORKEY_SOURCE) 722 sprctl |= SPRITE_SOURCE_KEY; 723 724 return sprctl; 725 } 726 727 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state, 728 u16 gamma[18]) 729 { 730 int scale, i; 731 732 /* 733 * WaFP16GammaEnabling:ivb,hsw 734 * "Workaround : When using the 64-bit format, the sprite output 735 * on each color channel has one quarter amplitude. It can be 736 * brought up to full amplitude by using sprite internal gamma 737 * correction, pipe gamma correction, or pipe color space 738 * conversion to multiply the sprite output by four." 739 */ 740 scale = 4; 741 742 for (i = 0; i < 16; i++) 743 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1); 744 745 gamma[i] = min((scale * i << 10) / 16, 1 << 10); 746 i++; 747 748 gamma[i] = 3 << 10; 749 i++; 750 } 751 752 static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state) 753 { 754 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 755 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 756 enum pipe pipe = plane->pipe; 757 u16 gamma[18]; 758 int i; 759 760 if (!ivb_need_sprite_gamma(plane_state)) 761 return; 762 763 ivb_sprite_linear_gamma(plane_state, gamma); 764 765 /* FIXME these register are single buffered :( */ 766 for (i = 0; i < 16; i++) 767 intel_de_write_fw(dev_priv, SPRGAMC(pipe, i), 768 gamma[i] << 20 | gamma[i] << 10 | gamma[i]); 769 770 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]); 771 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]); 772 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]); 773 i++; 774 775 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]); 776 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]); 777 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]); 778 i++; 779 } 780 781 static void 782 ivb_sprite_update_noarm(struct intel_plane *plane, 783 const struct intel_crtc_state *crtc_state, 784 const struct intel_plane_state *plane_state) 785 { 786 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 787 enum pipe pipe = plane->pipe; 788 int crtc_x = plane_state->uapi.dst.x1; 789 int crtc_y = plane_state->uapi.dst.y1; 790 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); 791 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); 792 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 793 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 794 u32 sprscale = 0; 795 796 if (crtc_w != src_w || crtc_h != src_h) 797 sprscale = SPRITE_SCALE_ENABLE | 798 SPRITE_SRC_WIDTH(src_w - 1) | 799 SPRITE_SRC_HEIGHT(src_h - 1); 800 801 intel_de_write_fw(dev_priv, SPRSTRIDE(pipe), 802 plane_state->view.color_plane[0].mapping_stride); 803 intel_de_write_fw(dev_priv, SPRPOS(pipe), 804 SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x)); 805 intel_de_write_fw(dev_priv, SPRSIZE(pipe), 806 SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1)); 807 if (IS_IVYBRIDGE(dev_priv)) 808 intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale); 809 } 810 811 static void 812 ivb_sprite_update_arm(struct intel_plane *plane, 813 const struct intel_crtc_state *crtc_state, 814 const struct intel_plane_state *plane_state) 815 { 816 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 817 enum pipe pipe = plane->pipe; 818 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 819 u32 sprsurf_offset = plane_state->view.color_plane[0].offset; 820 u32 x = plane_state->view.color_plane[0].x; 821 u32 y = plane_state->view.color_plane[0].y; 822 u32 sprctl, linear_offset; 823 824 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state); 825 826 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); 827 828 if (key->flags) { 829 intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value); 830 intel_de_write_fw(dev_priv, SPRKEYMSK(pipe), 831 key->channel_mask); 832 intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value); 833 } 834 835 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET 836 * register */ 837 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { 838 intel_de_write_fw(dev_priv, SPROFFSET(pipe), 839 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x)); 840 } else { 841 intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset); 842 intel_de_write_fw(dev_priv, SPRTILEOFF(pipe), 843 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x)); 844 } 845 846 /* 847 * The control register self-arms if the plane was previously 848 * disabled. Try to make the plane enable atomic by writing 849 * the control register just before the surface register. 850 */ 851 intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl); 852 intel_de_write_fw(dev_priv, SPRSURF(pipe), 853 intel_plane_ggtt_offset(plane_state) + sprsurf_offset); 854 855 ivb_sprite_update_gamma(plane_state); 856 } 857 858 static void 859 ivb_sprite_disable_arm(struct intel_plane *plane, 860 const struct intel_crtc_state *crtc_state) 861 { 862 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 863 enum pipe pipe = plane->pipe; 864 865 intel_de_write_fw(dev_priv, SPRCTL(pipe), 0); 866 /* Disable the scaler */ 867 if (IS_IVYBRIDGE(dev_priv)) 868 intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0); 869 intel_de_write_fw(dev_priv, SPRSURF(pipe), 0); 870 } 871 872 static bool 873 ivb_sprite_get_hw_state(struct intel_plane *plane, 874 enum pipe *pipe) 875 { 876 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 877 enum intel_display_power_domain power_domain; 878 intel_wakeref_t wakeref; 879 bool ret; 880 881 power_domain = POWER_DOMAIN_PIPE(plane->pipe); 882 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); 883 if (!wakeref) 884 return false; 885 886 ret = intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE; 887 888 *pipe = plane->pipe; 889 890 intel_display_power_put(dev_priv, power_domain, wakeref); 891 892 return ret; 893 } 894 895 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, 896 const struct intel_plane_state *plane_state) 897 { 898 const struct drm_framebuffer *fb = plane_state->hw.fb; 899 unsigned int hscale, pixel_rate; 900 unsigned int limit, decimate; 901 902 /* 903 * Note that crtc_state->pixel_rate accounts for both 904 * horizontal and vertical panel fitter downscaling factors. 905 * Pre-HSW bspec tells us to only consider the horizontal 906 * downscaling factor here. We ignore that and just consider 907 * both for simplicity. 908 */ 909 pixel_rate = crtc_state->pixel_rate; 910 911 /* Horizontal downscaling limits the maximum pixel rate */ 912 hscale = drm_rect_calc_hscale(&plane_state->uapi.src, 913 &plane_state->uapi.dst, 914 0, INT_MAX); 915 hscale = max(hscale, 0x10000u); 916 917 /* Decimation steps at 2x,4x,8x,16x */ 918 decimate = ilog2(hscale >> 16); 919 hscale >>= decimate; 920 921 /* Starting limit is 90% of cdclk */ 922 limit = 9; 923 924 /* -10% per decimation step */ 925 limit -= decimate; 926 927 /* -10% for RGB */ 928 if (!fb->format->is_yuv) 929 limit--; 930 931 /* 932 * We should also do -10% if sprite scaling is enabled 933 * on the other pipe, but we can't really check for that, 934 * so we ignore it. 935 */ 936 937 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale), 938 limit << 16); 939 } 940 941 static unsigned int 942 g4x_sprite_max_stride(struct intel_plane *plane, 943 u32 pixel_format, u64 modifier, 944 unsigned int rotation) 945 { 946 const struct drm_format_info *info = drm_format_info(pixel_format); 947 int cpp = info->cpp[0]; 948 949 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */ 950 if (modifier == I915_FORMAT_MOD_X_TILED) 951 return min(4096 * cpp, 16 * 1024); 952 else 953 return 16 * 1024; 954 } 955 956 static unsigned int 957 hsw_sprite_max_stride(struct intel_plane *plane, 958 u32 pixel_format, u64 modifier, 959 unsigned int rotation) 960 { 961 const struct drm_format_info *info = drm_format_info(pixel_format); 962 int cpp = info->cpp[0]; 963 964 /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */ 965 return min(8192 * cpp, 16 * 1024); 966 } 967 968 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) 969 { 970 u32 dvscntr = 0; 971 972 if (crtc_state->gamma_enable) 973 dvscntr |= DVS_PIPE_GAMMA_ENABLE; 974 975 if (crtc_state->csc_enable) 976 dvscntr |= DVS_PIPE_CSC_ENABLE; 977 978 return dvscntr; 979 } 980 981 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, 982 const struct intel_plane_state *plane_state) 983 { 984 struct drm_i915_private *dev_priv = 985 to_i915(plane_state->uapi.plane->dev); 986 const struct drm_framebuffer *fb = plane_state->hw.fb; 987 unsigned int rotation = plane_state->hw.rotation; 988 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 989 u32 dvscntr; 990 991 dvscntr = DVS_ENABLE; 992 993 if (IS_SANDYBRIDGE(dev_priv)) 994 dvscntr |= DVS_TRICKLE_FEED_DISABLE; 995 996 switch (fb->format->format) { 997 case DRM_FORMAT_XBGR8888: 998 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; 999 break; 1000 case DRM_FORMAT_XRGB8888: 1001 dvscntr |= DVS_FORMAT_RGBX888; 1002 break; 1003 case DRM_FORMAT_XBGR2101010: 1004 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR; 1005 break; 1006 case DRM_FORMAT_XRGB2101010: 1007 dvscntr |= DVS_FORMAT_RGBX101010; 1008 break; 1009 case DRM_FORMAT_XBGR16161616F: 1010 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR; 1011 break; 1012 case DRM_FORMAT_XRGB16161616F: 1013 dvscntr |= DVS_FORMAT_RGBX161616; 1014 break; 1015 case DRM_FORMAT_YUYV: 1016 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; 1017 break; 1018 case DRM_FORMAT_YVYU: 1019 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; 1020 break; 1021 case DRM_FORMAT_UYVY: 1022 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; 1023 break; 1024 case DRM_FORMAT_VYUY: 1025 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; 1026 break; 1027 default: 1028 MISSING_CASE(fb->format->format); 1029 return 0; 1030 } 1031 1032 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) 1033 dvscntr |= DVS_YUV_FORMAT_BT709; 1034 1035 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1036 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE; 1037 1038 if (fb->modifier == I915_FORMAT_MOD_X_TILED) 1039 dvscntr |= DVS_TILED; 1040 1041 if (rotation & DRM_MODE_ROTATE_180) 1042 dvscntr |= DVS_ROTATE_180; 1043 1044 if (key->flags & I915_SET_COLORKEY_DESTINATION) 1045 dvscntr |= DVS_DEST_KEY; 1046 else if (key->flags & I915_SET_COLORKEY_SOURCE) 1047 dvscntr |= DVS_SOURCE_KEY; 1048 1049 return dvscntr; 1050 } 1051 1052 static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state) 1053 { 1054 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1055 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1056 const struct drm_framebuffer *fb = plane_state->hw.fb; 1057 enum pipe pipe = plane->pipe; 1058 u16 gamma[8]; 1059 int i; 1060 1061 /* Seems RGB data bypasses the gamma always */ 1062 if (!fb->format->is_yuv) 1063 return; 1064 1065 i9xx_plane_linear_gamma(gamma); 1066 1067 /* FIXME these register are single buffered :( */ 1068 /* The two end points are implicit (0.0 and 1.0) */ 1069 for (i = 1; i < 8 - 1; i++) 1070 intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1), 1071 gamma[i] << 16 | gamma[i] << 8 | gamma[i]); 1072 } 1073 1074 static void ilk_sprite_linear_gamma(u16 gamma[17]) 1075 { 1076 int i; 1077 1078 for (i = 0; i < 17; i++) 1079 gamma[i] = (i << 10) / 16; 1080 } 1081 1082 static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state) 1083 { 1084 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1085 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1086 const struct drm_framebuffer *fb = plane_state->hw.fb; 1087 enum pipe pipe = plane->pipe; 1088 u16 gamma[17]; 1089 int i; 1090 1091 /* Seems RGB data bypasses the gamma always */ 1092 if (!fb->format->is_yuv) 1093 return; 1094 1095 ilk_sprite_linear_gamma(gamma); 1096 1097 /* FIXME these register are single buffered :( */ 1098 for (i = 0; i < 16; i++) 1099 intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i), 1100 gamma[i] << 20 | gamma[i] << 10 | gamma[i]); 1101 1102 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]); 1103 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]); 1104 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]); 1105 i++; 1106 } 1107 1108 static void 1109 g4x_sprite_update_noarm(struct intel_plane *plane, 1110 const struct intel_crtc_state *crtc_state, 1111 const struct intel_plane_state *plane_state) 1112 { 1113 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1114 enum pipe pipe = plane->pipe; 1115 int crtc_x = plane_state->uapi.dst.x1; 1116 int crtc_y = plane_state->uapi.dst.y1; 1117 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); 1118 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); 1119 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1120 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 1121 u32 dvsscale = 0; 1122 1123 if (crtc_w != src_w || crtc_h != src_h) 1124 dvsscale = DVS_SCALE_ENABLE | 1125 DVS_SRC_WIDTH(src_w - 1) | 1126 DVS_SRC_HEIGHT(src_h - 1); 1127 1128 intel_de_write_fw(dev_priv, DVSSTRIDE(pipe), 1129 plane_state->view.color_plane[0].mapping_stride); 1130 intel_de_write_fw(dev_priv, DVSPOS(pipe), 1131 DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x)); 1132 intel_de_write_fw(dev_priv, DVSSIZE(pipe), 1133 DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1)); 1134 intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale); 1135 } 1136 1137 static void 1138 g4x_sprite_update_arm(struct intel_plane *plane, 1139 const struct intel_crtc_state *crtc_state, 1140 const struct intel_plane_state *plane_state) 1141 { 1142 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1143 enum pipe pipe = plane->pipe; 1144 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1145 u32 dvssurf_offset = plane_state->view.color_plane[0].offset; 1146 u32 x = plane_state->view.color_plane[0].x; 1147 u32 y = plane_state->view.color_plane[0].y; 1148 u32 dvscntr, linear_offset; 1149 1150 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state); 1151 1152 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); 1153 1154 if (key->flags) { 1155 intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value); 1156 intel_de_write_fw(dev_priv, DVSKEYMSK(pipe), 1157 key->channel_mask); 1158 intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value); 1159 } 1160 1161 intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset); 1162 intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), 1163 DVS_OFFSET_Y(y) | DVS_OFFSET_X(x)); 1164 1165 /* 1166 * The control register self-arms if the plane was previously 1167 * disabled. Try to make the plane enable atomic by writing 1168 * the control register just before the surface register. 1169 */ 1170 intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr); 1171 intel_de_write_fw(dev_priv, DVSSURF(pipe), 1172 intel_plane_ggtt_offset(plane_state) + dvssurf_offset); 1173 1174 if (IS_G4X(dev_priv)) 1175 g4x_sprite_update_gamma(plane_state); 1176 else 1177 ilk_sprite_update_gamma(plane_state); 1178 } 1179 1180 static void 1181 g4x_sprite_disable_arm(struct intel_plane *plane, 1182 const struct intel_crtc_state *crtc_state) 1183 { 1184 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1185 enum pipe pipe = plane->pipe; 1186 1187 intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0); 1188 /* Disable the scaler */ 1189 intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0); 1190 intel_de_write_fw(dev_priv, DVSSURF(pipe), 0); 1191 } 1192 1193 static bool 1194 g4x_sprite_get_hw_state(struct intel_plane *plane, 1195 enum pipe *pipe) 1196 { 1197 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1198 enum intel_display_power_domain power_domain; 1199 intel_wakeref_t wakeref; 1200 bool ret; 1201 1202 power_domain = POWER_DOMAIN_PIPE(plane->pipe); 1203 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); 1204 if (!wakeref) 1205 return false; 1206 1207 ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE; 1208 1209 *pipe = plane->pipe; 1210 1211 intel_display_power_put(dev_priv, power_domain, wakeref); 1212 1213 return ret; 1214 } 1215 1216 static bool g4x_fb_scalable(const struct drm_framebuffer *fb) 1217 { 1218 if (!fb) 1219 return false; 1220 1221 switch (fb->format->format) { 1222 case DRM_FORMAT_C8: 1223 case DRM_FORMAT_XRGB16161616F: 1224 case DRM_FORMAT_ARGB16161616F: 1225 case DRM_FORMAT_XBGR16161616F: 1226 case DRM_FORMAT_ABGR16161616F: 1227 return false; 1228 default: 1229 return true; 1230 } 1231 } 1232 1233 static int 1234 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, 1235 struct intel_plane_state *plane_state) 1236 { 1237 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); 1238 const struct drm_framebuffer *fb = plane_state->hw.fb; 1239 const struct drm_rect *src = &plane_state->uapi.src; 1240 const struct drm_rect *dst = &plane_state->uapi.dst; 1241 int src_x, src_w, src_h, crtc_w, crtc_h; 1242 const struct drm_display_mode *adjusted_mode = 1243 &crtc_state->hw.adjusted_mode; 1244 unsigned int stride = plane_state->view.color_plane[0].mapping_stride; 1245 unsigned int cpp = fb->format->cpp[0]; 1246 unsigned int width_bytes; 1247 int min_width, min_height; 1248 1249 crtc_w = drm_rect_width(dst); 1250 crtc_h = drm_rect_height(dst); 1251 1252 src_x = src->x1 >> 16; 1253 src_w = drm_rect_width(src) >> 16; 1254 src_h = drm_rect_height(src) >> 16; 1255 1256 if (src_w == crtc_w && src_h == crtc_h) 1257 return 0; 1258 1259 min_width = 3; 1260 1261 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { 1262 if (src_h & 1) { 1263 drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n"); 1264 return -EINVAL; 1265 } 1266 min_height = 6; 1267 } else { 1268 min_height = 3; 1269 } 1270 1271 width_bytes = ((src_x * cpp) & 63) + src_w * cpp; 1272 1273 if (src_w < min_width || src_h < min_height || 1274 src_w > 2048 || src_h > 2048) { 1275 drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n", 1276 src_w, src_h, min_width, min_height, 2048, 2048); 1277 return -EINVAL; 1278 } 1279 1280 if (width_bytes > 4096) { 1281 drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n", 1282 width_bytes, 4096); 1283 return -EINVAL; 1284 } 1285 1286 if (stride > 4096) { 1287 drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n", 1288 stride, 4096); 1289 return -EINVAL; 1290 } 1291 1292 return 0; 1293 } 1294 1295 static int 1296 g4x_sprite_check(struct intel_crtc_state *crtc_state, 1297 struct intel_plane_state *plane_state) 1298 { 1299 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1300 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1301 int min_scale = DRM_PLANE_NO_SCALING; 1302 int max_scale = DRM_PLANE_NO_SCALING; 1303 int ret; 1304 1305 if (g4x_fb_scalable(plane_state->hw.fb)) { 1306 if (DISPLAY_VER(dev_priv) < 7) { 1307 min_scale = 1; 1308 max_scale = 16 << 16; 1309 } else if (IS_IVYBRIDGE(dev_priv)) { 1310 min_scale = 1; 1311 max_scale = 2 << 16; 1312 } 1313 } 1314 1315 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, 1316 min_scale, max_scale, true); 1317 if (ret) 1318 return ret; 1319 1320 ret = i9xx_check_plane_surface(plane_state); 1321 if (ret) 1322 return ret; 1323 1324 if (!plane_state->uapi.visible) 1325 return 0; 1326 1327 ret = intel_plane_check_src_coordinates(plane_state); 1328 if (ret) 1329 return ret; 1330 1331 ret = g4x_sprite_check_scaling(crtc_state, plane_state); 1332 if (ret) 1333 return ret; 1334 1335 if (DISPLAY_VER(dev_priv) >= 7) 1336 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state); 1337 else 1338 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state); 1339 1340 return 0; 1341 } 1342 1343 int chv_plane_check_rotation(const struct intel_plane_state *plane_state) 1344 { 1345 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1346 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1347 unsigned int rotation = plane_state->hw.rotation; 1348 1349 /* CHV ignores the mirror bit when the rotate bit is set :( */ 1350 if (IS_CHERRYVIEW(dev_priv) && 1351 rotation & DRM_MODE_ROTATE_180 && 1352 rotation & DRM_MODE_REFLECT_X) { 1353 drm_dbg_kms(&dev_priv->drm, 1354 "Cannot rotate and reflect at the same time\n"); 1355 return -EINVAL; 1356 } 1357 1358 return 0; 1359 } 1360 1361 static int 1362 vlv_sprite_check(struct intel_crtc_state *crtc_state, 1363 struct intel_plane_state *plane_state) 1364 { 1365 int ret; 1366 1367 ret = chv_plane_check_rotation(plane_state); 1368 if (ret) 1369 return ret; 1370 1371 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, 1372 DRM_PLANE_NO_SCALING, 1373 DRM_PLANE_NO_SCALING, 1374 true); 1375 if (ret) 1376 return ret; 1377 1378 ret = i9xx_check_plane_surface(plane_state); 1379 if (ret) 1380 return ret; 1381 1382 if (!plane_state->uapi.visible) 1383 return 0; 1384 1385 ret = intel_plane_check_src_coordinates(plane_state); 1386 if (ret) 1387 return ret; 1388 1389 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state); 1390 1391 return 0; 1392 } 1393 1394 static const u32 g4x_sprite_formats[] = { 1395 DRM_FORMAT_XRGB8888, 1396 DRM_FORMAT_YUYV, 1397 DRM_FORMAT_YVYU, 1398 DRM_FORMAT_UYVY, 1399 DRM_FORMAT_VYUY, 1400 }; 1401 1402 static const u32 snb_sprite_formats[] = { 1403 DRM_FORMAT_XRGB8888, 1404 DRM_FORMAT_XBGR8888, 1405 DRM_FORMAT_XRGB2101010, 1406 DRM_FORMAT_XBGR2101010, 1407 DRM_FORMAT_XRGB16161616F, 1408 DRM_FORMAT_XBGR16161616F, 1409 DRM_FORMAT_YUYV, 1410 DRM_FORMAT_YVYU, 1411 DRM_FORMAT_UYVY, 1412 DRM_FORMAT_VYUY, 1413 }; 1414 1415 static const u32 vlv_sprite_formats[] = { 1416 DRM_FORMAT_C8, 1417 DRM_FORMAT_RGB565, 1418 DRM_FORMAT_XRGB8888, 1419 DRM_FORMAT_XBGR8888, 1420 DRM_FORMAT_ARGB8888, 1421 DRM_FORMAT_ABGR8888, 1422 DRM_FORMAT_XBGR2101010, 1423 DRM_FORMAT_ABGR2101010, 1424 DRM_FORMAT_YUYV, 1425 DRM_FORMAT_YVYU, 1426 DRM_FORMAT_UYVY, 1427 DRM_FORMAT_VYUY, 1428 }; 1429 1430 static const u32 chv_pipe_b_sprite_formats[] = { 1431 DRM_FORMAT_C8, 1432 DRM_FORMAT_RGB565, 1433 DRM_FORMAT_XRGB8888, 1434 DRM_FORMAT_XBGR8888, 1435 DRM_FORMAT_ARGB8888, 1436 DRM_FORMAT_ABGR8888, 1437 DRM_FORMAT_XRGB2101010, 1438 DRM_FORMAT_XBGR2101010, 1439 DRM_FORMAT_ARGB2101010, 1440 DRM_FORMAT_ABGR2101010, 1441 DRM_FORMAT_YUYV, 1442 DRM_FORMAT_YVYU, 1443 DRM_FORMAT_UYVY, 1444 DRM_FORMAT_VYUY, 1445 }; 1446 1447 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane, 1448 u32 format, u64 modifier) 1449 { 1450 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) 1451 return false; 1452 1453 switch (format) { 1454 case DRM_FORMAT_XRGB8888: 1455 case DRM_FORMAT_YUYV: 1456 case DRM_FORMAT_YVYU: 1457 case DRM_FORMAT_UYVY: 1458 case DRM_FORMAT_VYUY: 1459 if (modifier == DRM_FORMAT_MOD_LINEAR || 1460 modifier == I915_FORMAT_MOD_X_TILED) 1461 return true; 1462 fallthrough; 1463 default: 1464 return false; 1465 } 1466 } 1467 1468 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane, 1469 u32 format, u64 modifier) 1470 { 1471 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) 1472 return false; 1473 1474 switch (format) { 1475 case DRM_FORMAT_XRGB8888: 1476 case DRM_FORMAT_XBGR8888: 1477 case DRM_FORMAT_XRGB2101010: 1478 case DRM_FORMAT_XBGR2101010: 1479 case DRM_FORMAT_XRGB16161616F: 1480 case DRM_FORMAT_XBGR16161616F: 1481 case DRM_FORMAT_YUYV: 1482 case DRM_FORMAT_YVYU: 1483 case DRM_FORMAT_UYVY: 1484 case DRM_FORMAT_VYUY: 1485 if (modifier == DRM_FORMAT_MOD_LINEAR || 1486 modifier == I915_FORMAT_MOD_X_TILED) 1487 return true; 1488 fallthrough; 1489 default: 1490 return false; 1491 } 1492 } 1493 1494 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane, 1495 u32 format, u64 modifier) 1496 { 1497 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier)) 1498 return false; 1499 1500 switch (format) { 1501 case DRM_FORMAT_C8: 1502 case DRM_FORMAT_RGB565: 1503 case DRM_FORMAT_ABGR8888: 1504 case DRM_FORMAT_ARGB8888: 1505 case DRM_FORMAT_XBGR8888: 1506 case DRM_FORMAT_XRGB8888: 1507 case DRM_FORMAT_XBGR2101010: 1508 case DRM_FORMAT_ABGR2101010: 1509 case DRM_FORMAT_XRGB2101010: 1510 case DRM_FORMAT_ARGB2101010: 1511 case DRM_FORMAT_YUYV: 1512 case DRM_FORMAT_YVYU: 1513 case DRM_FORMAT_UYVY: 1514 case DRM_FORMAT_VYUY: 1515 if (modifier == DRM_FORMAT_MOD_LINEAR || 1516 modifier == I915_FORMAT_MOD_X_TILED) 1517 return true; 1518 fallthrough; 1519 default: 1520 return false; 1521 } 1522 } 1523 1524 static const struct drm_plane_funcs g4x_sprite_funcs = { 1525 .update_plane = drm_atomic_helper_update_plane, 1526 .disable_plane = drm_atomic_helper_disable_plane, 1527 .destroy = intel_plane_destroy, 1528 .atomic_duplicate_state = intel_plane_duplicate_state, 1529 .atomic_destroy_state = intel_plane_destroy_state, 1530 .format_mod_supported = g4x_sprite_format_mod_supported, 1531 }; 1532 1533 static const struct drm_plane_funcs snb_sprite_funcs = { 1534 .update_plane = drm_atomic_helper_update_plane, 1535 .disable_plane = drm_atomic_helper_disable_plane, 1536 .destroy = intel_plane_destroy, 1537 .atomic_duplicate_state = intel_plane_duplicate_state, 1538 .atomic_destroy_state = intel_plane_destroy_state, 1539 .format_mod_supported = snb_sprite_format_mod_supported, 1540 }; 1541 1542 static const struct drm_plane_funcs vlv_sprite_funcs = { 1543 .update_plane = drm_atomic_helper_update_plane, 1544 .disable_plane = drm_atomic_helper_disable_plane, 1545 .destroy = intel_plane_destroy, 1546 .atomic_duplicate_state = intel_plane_duplicate_state, 1547 .atomic_destroy_state = intel_plane_destroy_state, 1548 .format_mod_supported = vlv_sprite_format_mod_supported, 1549 }; 1550 1551 struct intel_plane * 1552 intel_sprite_plane_create(struct drm_i915_private *dev_priv, 1553 enum pipe pipe, int sprite) 1554 { 1555 struct intel_plane *plane; 1556 const struct drm_plane_funcs *plane_funcs; 1557 unsigned int supported_rotations; 1558 const u64 *modifiers; 1559 const u32 *formats; 1560 int num_formats; 1561 int ret, zpos; 1562 1563 plane = intel_plane_alloc(); 1564 if (IS_ERR(plane)) 1565 return plane; 1566 1567 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 1568 plane->update_noarm = vlv_sprite_update_noarm; 1569 plane->update_arm = vlv_sprite_update_arm; 1570 plane->disable_arm = vlv_sprite_disable_arm; 1571 plane->get_hw_state = vlv_sprite_get_hw_state; 1572 plane->check_plane = vlv_sprite_check; 1573 plane->max_stride = i965_plane_max_stride; 1574 plane->min_cdclk = vlv_plane_min_cdclk; 1575 1576 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { 1577 formats = chv_pipe_b_sprite_formats; 1578 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats); 1579 } else { 1580 formats = vlv_sprite_formats; 1581 num_formats = ARRAY_SIZE(vlv_sprite_formats); 1582 } 1583 1584 plane_funcs = &vlv_sprite_funcs; 1585 } else if (DISPLAY_VER(dev_priv) >= 7) { 1586 plane->update_noarm = ivb_sprite_update_noarm; 1587 plane->update_arm = ivb_sprite_update_arm; 1588 plane->disable_arm = ivb_sprite_disable_arm; 1589 plane->get_hw_state = ivb_sprite_get_hw_state; 1590 plane->check_plane = g4x_sprite_check; 1591 1592 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { 1593 plane->max_stride = hsw_sprite_max_stride; 1594 plane->min_cdclk = hsw_plane_min_cdclk; 1595 } else { 1596 plane->max_stride = g4x_sprite_max_stride; 1597 plane->min_cdclk = ivb_sprite_min_cdclk; 1598 } 1599 1600 formats = snb_sprite_formats; 1601 num_formats = ARRAY_SIZE(snb_sprite_formats); 1602 1603 plane_funcs = &snb_sprite_funcs; 1604 } else { 1605 plane->update_noarm = g4x_sprite_update_noarm; 1606 plane->update_arm = g4x_sprite_update_arm; 1607 plane->disable_arm = g4x_sprite_disable_arm; 1608 plane->get_hw_state = g4x_sprite_get_hw_state; 1609 plane->check_plane = g4x_sprite_check; 1610 plane->max_stride = g4x_sprite_max_stride; 1611 plane->min_cdclk = g4x_sprite_min_cdclk; 1612 1613 if (IS_SANDYBRIDGE(dev_priv)) { 1614 formats = snb_sprite_formats; 1615 num_formats = ARRAY_SIZE(snb_sprite_formats); 1616 1617 plane_funcs = &snb_sprite_funcs; 1618 } else { 1619 formats = g4x_sprite_formats; 1620 num_formats = ARRAY_SIZE(g4x_sprite_formats); 1621 1622 plane_funcs = &g4x_sprite_funcs; 1623 } 1624 } 1625 1626 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { 1627 supported_rotations = 1628 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 1629 DRM_MODE_REFLECT_X; 1630 } else { 1631 supported_rotations = 1632 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 1633 } 1634 1635 plane->pipe = pipe; 1636 plane->id = PLANE_SPRITE0 + sprite; 1637 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); 1638 1639 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X); 1640 1641 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 1642 0, plane_funcs, 1643 formats, num_formats, modifiers, 1644 DRM_PLANE_TYPE_OVERLAY, 1645 "sprite %c", sprite_name(dev_priv, pipe, sprite)); 1646 kfree(modifiers); 1647 1648 if (ret) 1649 goto fail; 1650 1651 drm_plane_create_rotation_property(&plane->base, 1652 DRM_MODE_ROTATE_0, 1653 supported_rotations); 1654 1655 drm_plane_create_color_properties(&plane->base, 1656 BIT(DRM_COLOR_YCBCR_BT601) | 1657 BIT(DRM_COLOR_YCBCR_BT709), 1658 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 1659 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 1660 DRM_COLOR_YCBCR_BT709, 1661 DRM_COLOR_YCBCR_LIMITED_RANGE); 1662 1663 zpos = sprite + 1; 1664 drm_plane_create_zpos_immutable_property(&plane->base, zpos); 1665 1666 intel_plane_helper_add(plane); 1667 1668 return plane; 1669 1670 fail: 1671 intel_plane_free(plane); 1672 1673 return ERR_PTR(ret); 1674 } 1675