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