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