1 /* 2 * Copyright © 2009 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 * Daniel Vetter <daniel@ffwll.ch> 25 * 26 * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c 27 */ 28 29 #include <drm/drmP.h> 30 #include <drm/i915_drm.h> 31 #include "i915_drv.h" 32 #include "i915_reg.h" 33 #include "intel_drv.h" 34 35 /* Limits for overlay size. According to intel doc, the real limits are: 36 * Y width: 4095, UV width (planar): 2047, Y height: 2047, 37 * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use 38 * the mininum of both. */ 39 #define IMAGE_MAX_WIDTH 2048 40 #define IMAGE_MAX_HEIGHT 2046 /* 2 * 1023 */ 41 /* on 830 and 845 these large limits result in the card hanging */ 42 #define IMAGE_MAX_WIDTH_LEGACY 1024 43 #define IMAGE_MAX_HEIGHT_LEGACY 1088 44 45 /* overlay register definitions */ 46 /* OCMD register */ 47 #define OCMD_TILED_SURFACE (0x1<<19) 48 #define OCMD_MIRROR_MASK (0x3<<17) 49 #define OCMD_MIRROR_MODE (0x3<<17) 50 #define OCMD_MIRROR_HORIZONTAL (0x1<<17) 51 #define OCMD_MIRROR_VERTICAL (0x2<<17) 52 #define OCMD_MIRROR_BOTH (0x3<<17) 53 #define OCMD_BYTEORDER_MASK (0x3<<14) /* zero for YUYV or FOURCC YUY2 */ 54 #define OCMD_UV_SWAP (0x1<<14) /* YVYU */ 55 #define OCMD_Y_SWAP (0x2<<14) /* UYVY or FOURCC UYVY */ 56 #define OCMD_Y_AND_UV_SWAP (0x3<<14) /* VYUY */ 57 #define OCMD_SOURCE_FORMAT_MASK (0xf<<10) 58 #define OCMD_RGB_888 (0x1<<10) /* not in i965 Intel docs */ 59 #define OCMD_RGB_555 (0x2<<10) /* not in i965 Intel docs */ 60 #define OCMD_RGB_565 (0x3<<10) /* not in i965 Intel docs */ 61 #define OCMD_YUV_422_PACKED (0x8<<10) 62 #define OCMD_YUV_411_PACKED (0x9<<10) /* not in i965 Intel docs */ 63 #define OCMD_YUV_420_PLANAR (0xc<<10) 64 #define OCMD_YUV_422_PLANAR (0xd<<10) 65 #define OCMD_YUV_410_PLANAR (0xe<<10) /* also 411 */ 66 #define OCMD_TVSYNCFLIP_PARITY (0x1<<9) 67 #define OCMD_TVSYNCFLIP_ENABLE (0x1<<7) 68 #define OCMD_BUF_TYPE_MASK (0x1<<5) 69 #define OCMD_BUF_TYPE_FRAME (0x0<<5) 70 #define OCMD_BUF_TYPE_FIELD (0x1<<5) 71 #define OCMD_TEST_MODE (0x1<<4) 72 #define OCMD_BUFFER_SELECT (0x3<<2) 73 #define OCMD_BUFFER0 (0x0<<2) 74 #define OCMD_BUFFER1 (0x1<<2) 75 #define OCMD_FIELD_SELECT (0x1<<2) 76 #define OCMD_FIELD0 (0x0<<1) 77 #define OCMD_FIELD1 (0x1<<1) 78 #define OCMD_ENABLE (0x1<<0) 79 80 /* OCONFIG register */ 81 #define OCONF_PIPE_MASK (0x1<<18) 82 #define OCONF_PIPE_A (0x0<<18) 83 #define OCONF_PIPE_B (0x1<<18) 84 #define OCONF_GAMMA2_ENABLE (0x1<<16) 85 #define OCONF_CSC_MODE_BT601 (0x0<<5) 86 #define OCONF_CSC_MODE_BT709 (0x1<<5) 87 #define OCONF_CSC_BYPASS (0x1<<4) 88 #define OCONF_CC_OUT_8BIT (0x1<<3) 89 #define OCONF_TEST_MODE (0x1<<2) 90 #define OCONF_THREE_LINE_BUFFER (0x1<<0) 91 #define OCONF_TWO_LINE_BUFFER (0x0<<0) 92 93 /* DCLRKM (dst-key) register */ 94 #define DST_KEY_ENABLE (0x1<<31) 95 #define CLK_RGB24_MASK 0x0 96 #define CLK_RGB16_MASK 0x070307 97 #define CLK_RGB15_MASK 0x070707 98 #define CLK_RGB8I_MASK 0xffffff 99 100 #define RGB16_TO_COLORKEY(c) \ 101 (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) 102 #define RGB15_TO_COLORKEY(c) \ 103 (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) 104 105 /* overlay flip addr flag */ 106 #define OFC_UPDATE 0x1 107 108 /* polyphase filter coefficients */ 109 #define N_HORIZ_Y_TAPS 5 110 #define N_VERT_Y_TAPS 3 111 #define N_HORIZ_UV_TAPS 3 112 #define N_VERT_UV_TAPS 3 113 #define N_PHASES 17 114 #define MAX_TAPS 5 115 116 /* memory bufferd overlay registers */ 117 struct overlay_registers { 118 u32 OBUF_0Y; 119 u32 OBUF_1Y; 120 u32 OBUF_0U; 121 u32 OBUF_0V; 122 u32 OBUF_1U; 123 u32 OBUF_1V; 124 u32 OSTRIDE; 125 u32 YRGB_VPH; 126 u32 UV_VPH; 127 u32 HORZ_PH; 128 u32 INIT_PHS; 129 u32 DWINPOS; 130 u32 DWINSZ; 131 u32 SWIDTH; 132 u32 SWIDTHSW; 133 u32 SHEIGHT; 134 u32 YRGBSCALE; 135 u32 UVSCALE; 136 u32 OCLRC0; 137 u32 OCLRC1; 138 u32 DCLRKV; 139 u32 DCLRKM; 140 u32 SCLRKVH; 141 u32 SCLRKVL; 142 u32 SCLRKEN; 143 u32 OCONFIG; 144 u32 OCMD; 145 u32 RESERVED1; /* 0x6C */ 146 u32 OSTART_0Y; 147 u32 OSTART_1Y; 148 u32 OSTART_0U; 149 u32 OSTART_0V; 150 u32 OSTART_1U; 151 u32 OSTART_1V; 152 u32 OTILEOFF_0Y; 153 u32 OTILEOFF_1Y; 154 u32 OTILEOFF_0U; 155 u32 OTILEOFF_0V; 156 u32 OTILEOFF_1U; 157 u32 OTILEOFF_1V; 158 u32 FASTHSCALE; /* 0xA0 */ 159 u32 UVSCALEV; /* 0xA4 */ 160 u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */ 161 u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */ 162 u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES]; 163 u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */ 164 u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES]; 165 u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */ 166 u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES]; 167 u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */ 168 u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; 169 }; 170 171 struct intel_overlay { 172 struct drm_device *dev; 173 struct intel_crtc *crtc; 174 struct drm_i915_gem_object *vid_bo; 175 struct drm_i915_gem_object *old_vid_bo; 176 int active; 177 int pfit_active; 178 u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ 179 u32 color_key; 180 u32 brightness, contrast, saturation; 181 u32 old_xscale, old_yscale; 182 /* register access */ 183 u32 flip_addr; 184 struct drm_i915_gem_object *reg_bo; 185 /* flip handling */ 186 uint32_t last_flip_req; 187 void (*flip_tail)(struct intel_overlay *); 188 }; 189 190 static struct overlay_registers * 191 intel_overlay_map_regs(struct intel_overlay *overlay) 192 { 193 struct overlay_registers *regs; 194 195 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) { 196 regs = overlay->reg_bo->phys_obj->handle->vaddr; 197 } else { 198 regs = pmap_mapdev_attr(overlay->dev->agp->base + 199 overlay->reg_bo->gtt_offset, PAGE_SIZE, 200 PAT_WRITE_COMBINING); 201 } 202 return (regs); 203 } 204 205 static void intel_overlay_unmap_regs(struct intel_overlay *overlay, 206 struct overlay_registers *regs) 207 { 208 if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) 209 pmap_unmapdev((vm_offset_t)regs, PAGE_SIZE); 210 } 211 212 static int intel_overlay_do_wait_request(struct intel_overlay *overlay, 213 void (*tail)(struct intel_overlay *)) 214 { 215 struct drm_device *dev = overlay->dev; 216 drm_i915_private_t *dev_priv = dev->dev_private; 217 struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 218 int ret; 219 220 BUG_ON(overlay->last_flip_req); 221 ret = i915_add_request(ring, NULL, &overlay->last_flip_req); 222 if (ret) 223 return ret; 224 225 overlay->flip_tail = tail; 226 ret = i915_wait_seqno(ring, overlay->last_flip_req); 227 if (ret) 228 return ret; 229 i915_gem_retire_requests(dev); 230 231 overlay->last_flip_req = 0; 232 return 0; 233 } 234 235 /* overlay needs to be disable in OCMD reg */ 236 static int intel_overlay_on(struct intel_overlay *overlay) 237 { 238 struct drm_device *dev = overlay->dev; 239 struct drm_i915_private *dev_priv = dev->dev_private; 240 struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 241 int ret; 242 243 BUG_ON(overlay->active); 244 overlay->active = 1; 245 246 WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); 247 248 ret = intel_ring_begin(ring, 4); 249 if (ret) 250 return ret; 251 252 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); 253 intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); 254 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 255 intel_ring_emit(ring, MI_NOOP); 256 intel_ring_advance(ring); 257 258 return intel_overlay_do_wait_request(overlay, NULL); 259 } 260 261 /* overlay needs to be enabled in OCMD reg */ 262 static int intel_overlay_continue(struct intel_overlay *overlay, 263 bool load_polyphase_filter) 264 { 265 struct drm_device *dev = overlay->dev; 266 drm_i915_private_t *dev_priv = dev->dev_private; 267 struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 268 u32 flip_addr = overlay->flip_addr; 269 u32 tmp; 270 int ret; 271 272 BUG_ON(!overlay->active); 273 274 if (load_polyphase_filter) 275 flip_addr |= OFC_UPDATE; 276 277 /* check for underruns */ 278 tmp = I915_READ(DOVSTA); 279 if (tmp & (1 << 17)) 280 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); 281 282 ret = intel_ring_begin(ring, 2); 283 if (ret) 284 return ret; 285 286 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); 287 intel_ring_emit(ring, flip_addr); 288 intel_ring_advance(ring); 289 290 return i915_add_request(ring, NULL, &overlay->last_flip_req); 291 } 292 293 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) 294 { 295 struct drm_i915_gem_object *obj = overlay->old_vid_bo; 296 297 i915_gem_object_unpin(obj); 298 drm_gem_object_unreference(&obj->base); 299 300 overlay->old_vid_bo = NULL; 301 } 302 303 static void intel_overlay_off_tail(struct intel_overlay *overlay) 304 { 305 struct drm_i915_gem_object *obj = overlay->vid_bo; 306 307 /* never have the overlay hw on without showing a frame */ 308 KASSERT(overlay->vid_bo != NULL, ("No vid_bo")); 309 310 i915_gem_object_unpin(obj); 311 drm_gem_object_unreference(&obj->base); 312 overlay->vid_bo = NULL; 313 314 overlay->crtc->overlay = NULL; 315 overlay->crtc = NULL; 316 overlay->active = 0; 317 } 318 319 /* overlay needs to be disabled in OCMD reg */ 320 static int intel_overlay_off(struct intel_overlay *overlay) 321 { 322 struct drm_device *dev = overlay->dev; 323 struct drm_i915_private *dev_priv = dev->dev_private; 324 struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 325 u32 flip_addr = overlay->flip_addr; 326 int ret; 327 328 BUG_ON(!overlay->active); 329 330 /* According to intel docs the overlay hw may hang (when switching 331 * off) without loading the filter coeffs. It is however unclear whether 332 * this applies to the disabling of the overlay or to the switching off 333 * of the hw. Do it in both cases */ 334 flip_addr |= OFC_UPDATE; 335 336 ret = intel_ring_begin(ring, 6); 337 if (ret) 338 return ret; 339 340 /* wait for overlay to go idle */ 341 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); 342 intel_ring_emit(ring, flip_addr); 343 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 344 /* turn overlay off */ 345 if (IS_I830(dev)) { 346 /* Workaround: Don't disable the overlay fully, since otherwise 347 * it dies on the next OVERLAY_ON cmd. */ 348 intel_ring_emit(ring, MI_NOOP); 349 intel_ring_emit(ring, MI_NOOP); 350 intel_ring_emit(ring, MI_NOOP); 351 } else { 352 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); 353 intel_ring_emit(ring, flip_addr); 354 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 355 } 356 intel_ring_advance(ring); 357 358 return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); 359 } 360 361 /* recover from an interruption due to a signal 362 * We have to be careful not to repeat work forever an make forward progess. */ 363 static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) 364 { 365 struct drm_device *dev = overlay->dev; 366 drm_i915_private_t *dev_priv = dev->dev_private; 367 struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 368 int ret; 369 370 if (overlay->last_flip_req == 0) 371 return 0; 372 373 ret = i915_wait_seqno(ring, overlay->last_flip_req); 374 if (ret) 375 return ret; 376 i915_gem_retire_requests(dev); 377 378 if (overlay->flip_tail) 379 overlay->flip_tail(overlay); 380 381 overlay->last_flip_req = 0; 382 return 0; 383 } 384 385 /* Wait for pending overlay flip and release old frame. 386 * Needs to be called before the overlay register are changed 387 * via intel_overlay_(un)map_regs 388 */ 389 static int intel_overlay_release_old_vid(struct intel_overlay *overlay) 390 { 391 struct drm_device *dev = overlay->dev; 392 drm_i915_private_t *dev_priv = dev->dev_private; 393 struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 394 int ret; 395 396 /* Only wait if there is actually an old frame to release to 397 * guarantee forward progress. 398 */ 399 if (!overlay->old_vid_bo) 400 return 0; 401 402 if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { 403 /* synchronous slowpath */ 404 ret = intel_ring_begin(ring, 2); 405 if (ret) 406 return ret; 407 408 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 409 intel_ring_emit(ring, MI_NOOP); 410 intel_ring_advance(ring); 411 412 ret = intel_overlay_do_wait_request(overlay, 413 intel_overlay_release_old_vid_tail); 414 if (ret) 415 return ret; 416 } 417 418 intel_overlay_release_old_vid_tail(overlay); 419 return 0; 420 } 421 422 struct put_image_params { 423 int format; 424 short dst_x; 425 short dst_y; 426 short dst_w; 427 short dst_h; 428 short src_w; 429 short src_scan_h; 430 short src_scan_w; 431 short src_h; 432 short stride_Y; 433 short stride_UV; 434 int offset_Y; 435 int offset_U; 436 int offset_V; 437 }; 438 439 static int packed_depth_bytes(u32 format) 440 { 441 switch (format & I915_OVERLAY_DEPTH_MASK) { 442 case I915_OVERLAY_YUV422: 443 return 4; 444 case I915_OVERLAY_YUV411: 445 /* return 6; not implemented */ 446 default: 447 return -EINVAL; 448 } 449 } 450 451 static int packed_width_bytes(u32 format, short width) 452 { 453 switch (format & I915_OVERLAY_DEPTH_MASK) { 454 case I915_OVERLAY_YUV422: 455 return width << 1; 456 default: 457 return -EINVAL; 458 } 459 } 460 461 static int uv_hsubsampling(u32 format) 462 { 463 switch (format & I915_OVERLAY_DEPTH_MASK) { 464 case I915_OVERLAY_YUV422: 465 case I915_OVERLAY_YUV420: 466 return 2; 467 case I915_OVERLAY_YUV411: 468 case I915_OVERLAY_YUV410: 469 return 4; 470 default: 471 return -EINVAL; 472 } 473 } 474 475 static int uv_vsubsampling(u32 format) 476 { 477 switch (format & I915_OVERLAY_DEPTH_MASK) { 478 case I915_OVERLAY_YUV420: 479 case I915_OVERLAY_YUV410: 480 return 2; 481 case I915_OVERLAY_YUV422: 482 case I915_OVERLAY_YUV411: 483 return 1; 484 default: 485 return -EINVAL; 486 } 487 } 488 489 static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) 490 { 491 u32 mask, shift, ret; 492 if (IS_GEN2(dev)) { 493 mask = 0x1f; 494 shift = 5; 495 } else { 496 mask = 0x3f; 497 shift = 6; 498 } 499 ret = ((offset + width + mask) >> shift) - (offset >> shift); 500 if (!IS_GEN2(dev)) 501 ret <<= 1; 502 ret -= 1; 503 return ret << 2; 504 } 505 506 static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = { 507 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0, 508 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440, 509 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0, 510 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380, 511 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320, 512 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0, 513 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260, 514 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200, 515 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0, 516 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160, 517 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120, 518 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0, 519 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0, 520 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, 521 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, 522 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, 523 0xb000, 0x3000, 0x0800, 0x3000, 0xb000 524 }; 525 526 static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { 527 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, 528 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, 529 0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880, 530 0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00, 531 0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0, 532 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, 533 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, 534 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, 535 0x3000, 0x0800, 0x3000 536 }; 537 538 static void update_polyphase_filter(struct overlay_registers *regs) 539 { 540 memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs)); 541 memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs)); 542 } 543 544 static bool update_scaling_factors(struct intel_overlay *overlay, 545 struct overlay_registers *regs, 546 struct put_image_params *params) 547 { 548 /* fixed point with a 12 bit shift */ 549 u32 xscale, yscale, xscale_UV, yscale_UV; 550 #define FP_SHIFT 12 551 #define FRACT_MASK 0xfff 552 bool scale_changed = false; 553 int uv_hscale = uv_hsubsampling(params->format); 554 int uv_vscale = uv_vsubsampling(params->format); 555 556 if (params->dst_w > 1) 557 xscale = ((params->src_scan_w - 1) << FP_SHIFT) 558 /(params->dst_w); 559 else 560 xscale = 1 << FP_SHIFT; 561 562 if (params->dst_h > 1) 563 yscale = ((params->src_scan_h - 1) << FP_SHIFT) 564 /(params->dst_h); 565 else 566 yscale = 1 << FP_SHIFT; 567 568 /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ 569 xscale_UV = xscale/uv_hscale; 570 yscale_UV = yscale/uv_vscale; 571 /* make the Y scale to UV scale ratio an exact multiply */ 572 xscale = xscale_UV * uv_hscale; 573 yscale = yscale_UV * uv_vscale; 574 /*} else { 575 xscale_UV = 0; 576 yscale_UV = 0; 577 }*/ 578 579 if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) 580 scale_changed = true; 581 overlay->old_xscale = xscale; 582 overlay->old_yscale = yscale; 583 584 regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) | 585 ((xscale >> FP_SHIFT) << 16) | 586 ((xscale & FRACT_MASK) << 3)); 587 588 regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) | 589 ((xscale_UV >> FP_SHIFT) << 16) | 590 ((xscale_UV & FRACT_MASK) << 3)); 591 592 regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) | 593 ((yscale_UV >> FP_SHIFT) << 0))); 594 595 if (scale_changed) 596 update_polyphase_filter(regs); 597 598 return scale_changed; 599 } 600 601 static void update_colorkey(struct intel_overlay *overlay, 602 struct overlay_registers *regs) 603 { 604 u32 key = overlay->color_key; 605 606 switch (overlay->crtc->base.fb->bits_per_pixel) { 607 case 8: 608 regs->DCLRKV = 0; 609 regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; 610 break; 611 612 case 16: 613 if (overlay->crtc->base.fb->depth == 15) { 614 regs->DCLRKV = RGB15_TO_COLORKEY(key); 615 regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; 616 } else { 617 regs->DCLRKV = RGB16_TO_COLORKEY(key); 618 regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; 619 } 620 break; 621 622 case 24: 623 case 32: 624 regs->DCLRKV = key; 625 regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; 626 break; 627 } 628 } 629 630 static u32 overlay_cmd_reg(struct put_image_params *params) 631 { 632 u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0; 633 634 if (params->format & I915_OVERLAY_YUV_PLANAR) { 635 switch (params->format & I915_OVERLAY_DEPTH_MASK) { 636 case I915_OVERLAY_YUV422: 637 cmd |= OCMD_YUV_422_PLANAR; 638 break; 639 case I915_OVERLAY_YUV420: 640 cmd |= OCMD_YUV_420_PLANAR; 641 break; 642 case I915_OVERLAY_YUV411: 643 case I915_OVERLAY_YUV410: 644 cmd |= OCMD_YUV_410_PLANAR; 645 break; 646 } 647 } else { /* YUV packed */ 648 switch (params->format & I915_OVERLAY_DEPTH_MASK) { 649 case I915_OVERLAY_YUV422: 650 cmd |= OCMD_YUV_422_PACKED; 651 break; 652 case I915_OVERLAY_YUV411: 653 cmd |= OCMD_YUV_411_PACKED; 654 break; 655 } 656 657 switch (params->format & I915_OVERLAY_SWAP_MASK) { 658 case I915_OVERLAY_NO_SWAP: 659 break; 660 case I915_OVERLAY_UV_SWAP: 661 cmd |= OCMD_UV_SWAP; 662 break; 663 case I915_OVERLAY_Y_SWAP: 664 cmd |= OCMD_Y_SWAP; 665 break; 666 case I915_OVERLAY_Y_AND_UV_SWAP: 667 cmd |= OCMD_Y_AND_UV_SWAP; 668 break; 669 } 670 } 671 672 return cmd; 673 } 674 675 static u32 676 max_u32(u32 a, u32 b) 677 { 678 679 return (a > b ? a : b); 680 } 681 682 static int intel_overlay_do_put_image(struct intel_overlay *overlay, 683 struct drm_i915_gem_object *new_bo, 684 struct put_image_params *params) 685 { 686 int ret, tmp_width; 687 struct overlay_registers *regs; 688 bool scale_changed = false; 689 690 KASSERT(overlay != NULL, ("No overlay ?")); 691 DRM_LOCK_ASSERT(overlay->dev); 692 693 ret = intel_overlay_release_old_vid(overlay); 694 if (ret != 0) 695 return ret; 696 697 ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL); 698 if (ret != 0) 699 goto out_unpin; 700 701 ret = i915_gem_object_put_fence(new_bo); 702 if (ret) 703 goto out_unpin; 704 705 if (!overlay->active) { 706 regs = intel_overlay_map_regs(overlay); 707 if (!regs) { 708 ret = -ENOMEM; 709 goto out_unpin; 710 } 711 regs->OCONFIG = OCONF_CC_OUT_8BIT; 712 if (IS_GEN4(overlay->dev)) 713 regs->OCONFIG |= OCONF_CSC_MODE_BT709; 714 regs->OCONFIG |= overlay->crtc->pipe == 0 ? 715 OCONF_PIPE_A : OCONF_PIPE_B; 716 intel_overlay_unmap_regs(overlay, regs); 717 718 ret = intel_overlay_on(overlay); 719 if (ret != 0) 720 goto out_unpin; 721 } 722 723 regs = intel_overlay_map_regs(overlay); 724 if (!regs) { 725 ret = -ENOMEM; 726 goto out_unpin; 727 } 728 729 regs->DWINPOS = (params->dst_y << 16) | params->dst_x; 730 regs->DWINSZ = (params->dst_h << 16) | params->dst_w; 731 732 if (params->format & I915_OVERLAY_YUV_PACKED) 733 tmp_width = packed_width_bytes(params->format, params->src_w); 734 else 735 tmp_width = params->src_w; 736 737 regs->SWIDTH = params->src_w; 738 regs->SWIDTHSW = calc_swidthsw(overlay->dev, 739 params->offset_Y, tmp_width); 740 regs->SHEIGHT = params->src_h; 741 regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y; 742 regs->OSTRIDE = params->stride_Y; 743 744 if (params->format & I915_OVERLAY_YUV_PLANAR) { 745 int uv_hscale = uv_hsubsampling(params->format); 746 int uv_vscale = uv_vsubsampling(params->format); 747 u32 tmp_U, tmp_V; 748 regs->SWIDTH |= (params->src_w/uv_hscale) << 16; 749 tmp_U = calc_swidthsw(overlay->dev, params->offset_U, 750 params->src_w/uv_hscale); 751 tmp_V = calc_swidthsw(overlay->dev, params->offset_V, 752 params->src_w/uv_hscale); 753 regs->SWIDTHSW |= max_u32(tmp_U, tmp_V) << 16; 754 regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; 755 regs->OBUF_0U = new_bo->gtt_offset + params->offset_U; 756 regs->OBUF_0V = new_bo->gtt_offset + params->offset_V; 757 regs->OSTRIDE |= params->stride_UV << 16; 758 } 759 760 scale_changed = update_scaling_factors(overlay, regs, params); 761 762 update_colorkey(overlay, regs); 763 764 regs->OCMD = overlay_cmd_reg(params); 765 766 intel_overlay_unmap_regs(overlay, regs); 767 768 ret = intel_overlay_continue(overlay, scale_changed); 769 if (ret) 770 goto out_unpin; 771 772 overlay->old_vid_bo = overlay->vid_bo; 773 overlay->vid_bo = new_bo; 774 775 return 0; 776 777 out_unpin: 778 i915_gem_object_unpin(new_bo); 779 return ret; 780 } 781 782 int intel_overlay_switch_off(struct intel_overlay *overlay) 783 { 784 struct overlay_registers *regs; 785 int ret; 786 787 DRM_LOCK_ASSERT(overlay->dev); 788 789 ret = intel_overlay_recover_from_interrupt(overlay); 790 if (ret != 0) 791 return ret; 792 793 if (!overlay->active) 794 return 0; 795 796 ret = intel_overlay_release_old_vid(overlay); 797 if (ret != 0) 798 return ret; 799 800 regs = intel_overlay_map_regs(overlay); 801 regs->OCMD = 0; 802 intel_overlay_unmap_regs(overlay, regs); 803 804 ret = intel_overlay_off(overlay); 805 if (ret != 0) 806 return ret; 807 808 intel_overlay_off_tail(overlay); 809 return 0; 810 } 811 812 static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, 813 struct intel_crtc *crtc) 814 { 815 drm_i915_private_t *dev_priv = overlay->dev->dev_private; 816 817 if (!crtc->active) 818 return -EINVAL; 819 820 /* can't use the overlay with double wide pipe */ 821 if (INTEL_INFO(overlay->dev)->gen < 4 && 822 (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE) 823 return -EINVAL; 824 825 return 0; 826 } 827 828 static void update_pfit_vscale_ratio(struct intel_overlay *overlay) 829 { 830 struct drm_device *dev = overlay->dev; 831 drm_i915_private_t *dev_priv = dev->dev_private; 832 u32 pfit_control = I915_READ(PFIT_CONTROL); 833 u32 ratio; 834 835 /* XXX: This is not the same logic as in the xorg driver, but more in 836 * line with the intel documentation for the i965 837 */ 838 if (INTEL_INFO(dev)->gen >= 4) { 839 /* on i965 use the PGM reg to read out the autoscaler values */ 840 ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; 841 } else { 842 if (pfit_control & VERT_AUTO_SCALE) 843 ratio = I915_READ(PFIT_AUTO_RATIOS); 844 else 845 ratio = I915_READ(PFIT_PGM_RATIOS); 846 ratio >>= PFIT_VERT_SCALE_SHIFT; 847 } 848 849 overlay->pfit_vscale_ratio = ratio; 850 } 851 852 static int check_overlay_dst(struct intel_overlay *overlay, 853 struct drm_intel_overlay_put_image *rec) 854 { 855 struct drm_display_mode *mode = &overlay->crtc->base.mode; 856 857 if (rec->dst_x < mode->hdisplay && 858 rec->dst_x + rec->dst_width <= mode->hdisplay && 859 rec->dst_y < mode->vdisplay && 860 rec->dst_y + rec->dst_height <= mode->vdisplay) 861 return 0; 862 else 863 return -EINVAL; 864 } 865 866 static int check_overlay_scaling(struct put_image_params *rec) 867 { 868 u32 tmp; 869 870 /* downscaling limit is 8.0 */ 871 tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16; 872 if (tmp > 7) 873 return -EINVAL; 874 tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16; 875 if (tmp > 7) 876 return -EINVAL; 877 878 return 0; 879 } 880 881 static int check_overlay_src(struct drm_device *dev, 882 struct drm_intel_overlay_put_image *rec, 883 struct drm_i915_gem_object *new_bo) 884 { 885 int uv_hscale = uv_hsubsampling(rec->flags); 886 int uv_vscale = uv_vsubsampling(rec->flags); 887 u32 stride_mask; 888 int depth; 889 u32 tmp; 890 891 /* check src dimensions */ 892 if (IS_845G(dev) || IS_I830(dev)) { 893 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY || 894 rec->src_width > IMAGE_MAX_WIDTH_LEGACY) 895 return -EINVAL; 896 } else { 897 if (rec->src_height > IMAGE_MAX_HEIGHT || 898 rec->src_width > IMAGE_MAX_WIDTH) 899 return -EINVAL; 900 } 901 902 /* better safe than sorry, use 4 as the maximal subsampling ratio */ 903 if (rec->src_height < N_VERT_Y_TAPS*4 || 904 rec->src_width < N_HORIZ_Y_TAPS*4) 905 return -EINVAL; 906 907 /* check alignment constraints */ 908 switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 909 case I915_OVERLAY_RGB: 910 /* not implemented */ 911 return -EINVAL; 912 913 case I915_OVERLAY_YUV_PACKED: 914 if (uv_vscale != 1) 915 return -EINVAL; 916 917 depth = packed_depth_bytes(rec->flags); 918 if (depth < 0) 919 return depth; 920 921 /* ignore UV planes */ 922 rec->stride_UV = 0; 923 rec->offset_U = 0; 924 rec->offset_V = 0; 925 /* check pixel alignment */ 926 if (rec->offset_Y % depth) 927 return -EINVAL; 928 break; 929 930 case I915_OVERLAY_YUV_PLANAR: 931 if (uv_vscale < 0 || uv_hscale < 0) 932 return -EINVAL; 933 /* no offset restrictions for planar formats */ 934 break; 935 936 default: 937 return -EINVAL; 938 } 939 940 if (rec->src_width % uv_hscale) 941 return -EINVAL; 942 943 /* stride checking */ 944 if (IS_I830(dev) || IS_845G(dev)) 945 stride_mask = 255; 946 else 947 stride_mask = 63; 948 949 if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) 950 return -EINVAL; 951 if (IS_GEN4(dev) && rec->stride_Y < 512) 952 return -EINVAL; 953 954 tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? 955 4096 : 8192; 956 if (rec->stride_Y > tmp || rec->stride_UV > 2*1024) 957 return -EINVAL; 958 959 /* check buffer dimensions */ 960 switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 961 case I915_OVERLAY_RGB: 962 case I915_OVERLAY_YUV_PACKED: 963 /* always 4 Y values per depth pixels */ 964 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y) 965 return -EINVAL; 966 967 tmp = rec->stride_Y*rec->src_height; 968 if (rec->offset_Y + tmp > new_bo->base.size) 969 return -EINVAL; 970 break; 971 972 case I915_OVERLAY_YUV_PLANAR: 973 if (rec->src_width > rec->stride_Y) 974 return -EINVAL; 975 if (rec->src_width/uv_hscale > rec->stride_UV) 976 return -EINVAL; 977 978 tmp = rec->stride_Y * rec->src_height; 979 if (rec->offset_Y + tmp > new_bo->base.size) 980 return -EINVAL; 981 982 tmp = rec->stride_UV * (rec->src_height / uv_vscale); 983 if (rec->offset_U + tmp > new_bo->base.size || 984 rec->offset_V + tmp > new_bo->base.size) 985 return -EINVAL; 986 break; 987 } 988 989 return 0; 990 } 991 992 /** 993 * Return the pipe currently connected to the panel fitter, 994 * or -1 if the panel fitter is not present or not in use 995 */ 996 static int intel_panel_fitter_pipe(struct drm_device *dev) 997 { 998 struct drm_i915_private *dev_priv = dev->dev_private; 999 u32 pfit_control; 1000 1001 /* i830 doesn't have a panel fitter */ 1002 if (IS_I830(dev)) 1003 return -1; 1004 1005 pfit_control = I915_READ(PFIT_CONTROL); 1006 1007 /* See if the panel fitter is in use */ 1008 if ((pfit_control & PFIT_ENABLE) == 0) 1009 return -1; 1010 1011 /* 965 can place panel fitter on either pipe */ 1012 if (IS_GEN4(dev)) 1013 return (pfit_control >> 29) & 0x3; 1014 1015 /* older chips can only use pipe 1 */ 1016 return 1; 1017 } 1018 1019 int intel_overlay_put_image(struct drm_device *dev, void *data, 1020 struct drm_file *file_priv) 1021 { 1022 struct drm_intel_overlay_put_image *put_image_rec = data; 1023 drm_i915_private_t *dev_priv = dev->dev_private; 1024 struct intel_overlay *overlay; 1025 struct drm_mode_object *drmmode_obj; 1026 struct intel_crtc *crtc; 1027 struct drm_i915_gem_object *new_bo; 1028 struct put_image_params *params; 1029 int ret; 1030 1031 if (!dev_priv) { 1032 DRM_ERROR("called with no initialization\n"); 1033 return -EINVAL; 1034 } 1035 1036 overlay = dev_priv->overlay; 1037 if (!overlay) { 1038 DRM_DEBUG("userspace bug: no overlay\n"); 1039 return -ENODEV; 1040 } 1041 1042 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { 1043 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 1044 DRM_LOCK(dev); 1045 1046 ret = intel_overlay_switch_off(overlay); 1047 1048 DRM_UNLOCK(dev); 1049 lockmgr(&dev->mode_config.mutex, LK_RELEASE); 1050 1051 return ret; 1052 } 1053 1054 params = kmalloc(sizeof(struct put_image_params), DRM_I915_GEM, 1055 M_WAITOK | M_ZERO); 1056 1057 drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, 1058 DRM_MODE_OBJECT_CRTC); 1059 if (!drmmode_obj) { 1060 ret = -ENOENT; 1061 goto out_free; 1062 } 1063 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); 1064 1065 new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv, 1066 put_image_rec->bo_handle)); 1067 if (&new_bo->base == NULL) { 1068 ret = -ENOENT; 1069 goto out_free; 1070 } 1071 1072 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 1073 DRM_LOCK(dev); 1074 1075 if (new_bo->tiling_mode) { 1076 DRM_ERROR("buffer used for overlay image can not be tiled\n"); 1077 ret = -EINVAL; 1078 goto out_unlock; 1079 } 1080 1081 ret = intel_overlay_recover_from_interrupt(overlay); 1082 if (ret != 0) 1083 goto out_unlock; 1084 1085 if (overlay->crtc != crtc) { 1086 struct drm_display_mode *mode = &crtc->base.mode; 1087 ret = intel_overlay_switch_off(overlay); 1088 if (ret != 0) 1089 goto out_unlock; 1090 1091 ret = check_overlay_possible_on_crtc(overlay, crtc); 1092 if (ret != 0) 1093 goto out_unlock; 1094 1095 overlay->crtc = crtc; 1096 crtc->overlay = overlay; 1097 1098 /* line too wide, i.e. one-line-mode */ 1099 if (mode->hdisplay > 1024 && 1100 intel_panel_fitter_pipe(dev) == crtc->pipe) { 1101 overlay->pfit_active = 1; 1102 update_pfit_vscale_ratio(overlay); 1103 } else 1104 overlay->pfit_active = 0; 1105 } 1106 1107 ret = check_overlay_dst(overlay, put_image_rec); 1108 if (ret != 0) 1109 goto out_unlock; 1110 1111 if (overlay->pfit_active) { 1112 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / 1113 overlay->pfit_vscale_ratio); 1114 /* shifting right rounds downwards, so add 1 */ 1115 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / 1116 overlay->pfit_vscale_ratio) + 1; 1117 } else { 1118 params->dst_y = put_image_rec->dst_y; 1119 params->dst_h = put_image_rec->dst_height; 1120 } 1121 params->dst_x = put_image_rec->dst_x; 1122 params->dst_w = put_image_rec->dst_width; 1123 1124 params->src_w = put_image_rec->src_width; 1125 params->src_h = put_image_rec->src_height; 1126 params->src_scan_w = put_image_rec->src_scan_width; 1127 params->src_scan_h = put_image_rec->src_scan_height; 1128 if (params->src_scan_h > params->src_h || 1129 params->src_scan_w > params->src_w) { 1130 ret = -EINVAL; 1131 goto out_unlock; 1132 } 1133 1134 ret = check_overlay_src(dev, put_image_rec, new_bo); 1135 if (ret != 0) 1136 goto out_unlock; 1137 params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK; 1138 params->stride_Y = put_image_rec->stride_Y; 1139 params->stride_UV = put_image_rec->stride_UV; 1140 params->offset_Y = put_image_rec->offset_Y; 1141 params->offset_U = put_image_rec->offset_U; 1142 params->offset_V = put_image_rec->offset_V; 1143 1144 /* Check scaling after src size to prevent a divide-by-zero. */ 1145 ret = check_overlay_scaling(params); 1146 if (ret != 0) 1147 goto out_unlock; 1148 1149 ret = intel_overlay_do_put_image(overlay, new_bo, params); 1150 if (ret != 0) 1151 goto out_unlock; 1152 1153 DRM_UNLOCK(dev); 1154 lockmgr(&dev->mode_config.mutex, LK_RELEASE); 1155 1156 drm_free(params, DRM_I915_GEM); 1157 1158 return 0; 1159 1160 out_unlock: 1161 DRM_UNLOCK(dev); 1162 lockmgr(&dev->mode_config.mutex, LK_RELEASE); 1163 drm_gem_object_unreference_unlocked(&new_bo->base); 1164 out_free: 1165 drm_free(params, DRM_I915_GEM); 1166 1167 return ret; 1168 } 1169 1170 static void update_reg_attrs(struct intel_overlay *overlay, 1171 struct overlay_registers *regs) 1172 { 1173 regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff); 1174 regs->OCLRC1 = overlay->saturation; 1175 } 1176 1177 static bool check_gamma_bounds(u32 gamma1, u32 gamma2) 1178 { 1179 int i; 1180 1181 if (gamma1 & 0xff000000 || gamma2 & 0xff000000) 1182 return false; 1183 1184 for (i = 0; i < 3; i++) { 1185 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) 1186 return false; 1187 } 1188 1189 return true; 1190 } 1191 1192 static bool check_gamma5_errata(u32 gamma5) 1193 { 1194 int i; 1195 1196 for (i = 0; i < 3; i++) { 1197 if (((gamma5 >> i*8) & 0xff) == 0x80) 1198 return false; 1199 } 1200 1201 return true; 1202 } 1203 1204 static int check_gamma(struct drm_intel_overlay_attrs *attrs) 1205 { 1206 if (!check_gamma_bounds(0, attrs->gamma0) || 1207 !check_gamma_bounds(attrs->gamma0, attrs->gamma1) || 1208 !check_gamma_bounds(attrs->gamma1, attrs->gamma2) || 1209 !check_gamma_bounds(attrs->gamma2, attrs->gamma3) || 1210 !check_gamma_bounds(attrs->gamma3, attrs->gamma4) || 1211 !check_gamma_bounds(attrs->gamma4, attrs->gamma5) || 1212 !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) 1213 return -EINVAL; 1214 1215 if (!check_gamma5_errata(attrs->gamma5)) 1216 return -EINVAL; 1217 1218 return 0; 1219 } 1220 1221 int intel_overlay_attrs(struct drm_device *dev, void *data, 1222 struct drm_file *file_priv) 1223 { 1224 struct drm_intel_overlay_attrs *attrs = data; 1225 drm_i915_private_t *dev_priv = dev->dev_private; 1226 struct intel_overlay *overlay; 1227 struct overlay_registers *regs; 1228 int ret; 1229 1230 if (!dev_priv) { 1231 DRM_ERROR("called with no initialization\n"); 1232 return -EINVAL; 1233 } 1234 1235 overlay = dev_priv->overlay; 1236 if (!overlay) { 1237 DRM_DEBUG("userspace bug: no overlay\n"); 1238 return -ENODEV; 1239 } 1240 1241 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE); 1242 DRM_LOCK(dev); 1243 1244 ret = -EINVAL; 1245 if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { 1246 attrs->color_key = overlay->color_key; 1247 attrs->brightness = overlay->brightness; 1248 attrs->contrast = overlay->contrast; 1249 attrs->saturation = overlay->saturation; 1250 1251 if (!IS_GEN2(dev)) { 1252 attrs->gamma0 = I915_READ(OGAMC0); 1253 attrs->gamma1 = I915_READ(OGAMC1); 1254 attrs->gamma2 = I915_READ(OGAMC2); 1255 attrs->gamma3 = I915_READ(OGAMC3); 1256 attrs->gamma4 = I915_READ(OGAMC4); 1257 attrs->gamma5 = I915_READ(OGAMC5); 1258 } 1259 } else { 1260 if (attrs->brightness < -128 || attrs->brightness > 127) 1261 goto out_unlock; 1262 if (attrs->contrast > 255) 1263 goto out_unlock; 1264 if (attrs->saturation > 1023) 1265 goto out_unlock; 1266 1267 overlay->color_key = attrs->color_key; 1268 overlay->brightness = attrs->brightness; 1269 overlay->contrast = attrs->contrast; 1270 overlay->saturation = attrs->saturation; 1271 1272 regs = intel_overlay_map_regs(overlay); 1273 if (!regs) { 1274 ret = -ENOMEM; 1275 goto out_unlock; 1276 } 1277 1278 update_reg_attrs(overlay, regs); 1279 1280 intel_overlay_unmap_regs(overlay, regs); 1281 1282 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { 1283 if (IS_GEN2(dev)) 1284 goto out_unlock; 1285 1286 if (overlay->active) { 1287 ret = -EBUSY; 1288 goto out_unlock; 1289 } 1290 1291 ret = check_gamma(attrs); 1292 if (ret) 1293 goto out_unlock; 1294 1295 I915_WRITE(OGAMC0, attrs->gamma0); 1296 I915_WRITE(OGAMC1, attrs->gamma1); 1297 I915_WRITE(OGAMC2, attrs->gamma2); 1298 I915_WRITE(OGAMC3, attrs->gamma3); 1299 I915_WRITE(OGAMC4, attrs->gamma4); 1300 I915_WRITE(OGAMC5, attrs->gamma5); 1301 } 1302 } 1303 1304 ret = 0; 1305 out_unlock: 1306 DRM_UNLOCK(dev); 1307 lockmgr(&dev->mode_config.mutex, LK_RELEASE); 1308 1309 return ret; 1310 } 1311 1312 void intel_setup_overlay(struct drm_device *dev) 1313 { 1314 drm_i915_private_t *dev_priv = dev->dev_private; 1315 struct intel_overlay *overlay; 1316 struct drm_i915_gem_object *reg_bo; 1317 struct overlay_registers *regs; 1318 int ret; 1319 1320 if (!HAS_OVERLAY(dev)) 1321 return; 1322 1323 overlay = kmalloc(sizeof(struct intel_overlay), DRM_I915_GEM, 1324 M_WAITOK | M_ZERO); 1325 DRM_LOCK(dev); 1326 if (dev_priv->overlay != NULL) 1327 goto out_free; 1328 overlay->dev = dev; 1329 1330 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); 1331 if (!reg_bo) 1332 goto out_free; 1333 overlay->reg_bo = reg_bo; 1334 1335 if (OVERLAY_NEEDS_PHYSICAL(dev)) { 1336 ret = i915_gem_attach_phys_object(dev, reg_bo, 1337 I915_GEM_PHYS_OVERLAY_REGS, 1338 PAGE_SIZE); 1339 if (ret) { 1340 DRM_ERROR("failed to attach phys overlay regs\n"); 1341 goto out_free_bo; 1342 } 1343 overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; 1344 } else { 1345 ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true); 1346 if (ret) { 1347 DRM_ERROR("failed to pin overlay register bo\n"); 1348 goto out_free_bo; 1349 } 1350 overlay->flip_addr = reg_bo->gtt_offset; 1351 1352 ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); 1353 if (ret) { 1354 DRM_ERROR("failed to move overlay register bo into the GTT\n"); 1355 goto out_unpin_bo; 1356 } 1357 } 1358 1359 /* init all values */ 1360 overlay->color_key = 0x0101fe; 1361 overlay->brightness = -19; 1362 overlay->contrast = 75; 1363 overlay->saturation = 146; 1364 1365 regs = intel_overlay_map_regs(overlay); 1366 if (!regs) 1367 goto out_unpin_bo; 1368 1369 memset(regs, 0, sizeof(struct overlay_registers)); 1370 update_polyphase_filter(regs); 1371 update_reg_attrs(overlay, regs); 1372 1373 intel_overlay_unmap_regs(overlay, regs); 1374 1375 dev_priv->overlay = overlay; 1376 DRM_INFO("initialized overlay support\n"); 1377 DRM_UNLOCK(dev); 1378 return; 1379 1380 out_unpin_bo: 1381 if (!OVERLAY_NEEDS_PHYSICAL(dev)) 1382 i915_gem_object_unpin(reg_bo); 1383 out_free_bo: 1384 drm_gem_object_unreference(®_bo->base); 1385 out_free: 1386 DRM_UNLOCK(dev); 1387 drm_free(overlay, DRM_I915_GEM); 1388 return; 1389 } 1390 1391 void intel_cleanup_overlay(struct drm_device *dev) 1392 { 1393 drm_i915_private_t *dev_priv = dev->dev_private; 1394 1395 if (!dev_priv->overlay) 1396 return; 1397 1398 /* The bo's should be free'd by the generic code already. 1399 * Furthermore modesetting teardown happens beforehand so the 1400 * hardware should be off already */ 1401 KASSERT(!dev_priv->overlay->active, ("Overlay still active")); 1402 1403 drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base); 1404 drm_free(dev_priv->overlay, DRM_I915_GEM); 1405 } 1406 1407 #ifdef CONFIG_DEBUG_FS 1408 #include <linux/seq_file.h> 1409 1410 struct intel_overlay_error_state { 1411 struct overlay_registers regs; 1412 unsigned long base; 1413 u32 dovsta; 1414 u32 isr; 1415 }; 1416 1417 struct intel_overlay_error_state * 1418 intel_overlay_capture_error_state(struct drm_device *dev) 1419 { 1420 drm_i915_private_t *dev_priv = dev->dev_private; 1421 struct intel_overlay *overlay = dev_priv->overlay; 1422 struct intel_overlay_error_state *error; 1423 struct overlay_registers __iomem *regs; 1424 1425 if (!overlay || !overlay->active) 1426 return NULL; 1427 1428 error = kmalloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT); 1429 if (error == NULL) 1430 return NULL; 1431 1432 error->dovsta = I915_READ(DOVSTA); 1433 error->isr = I915_READ(ISR); 1434 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) 1435 error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; 1436 else 1437 error->base = (long) overlay->reg_bo->gtt_offset; 1438 1439 regs = intel_overlay_map_regs(overlay); 1440 if (!regs) 1441 goto err; 1442 1443 memcpy(&error->regs, regs, sizeof(struct overlay_registers)); 1444 intel_overlay_unmap_regs(overlay, regs); 1445 1446 return (error); 1447 1448 err: 1449 drm_free(error, DRM_I915_GEM); 1450 return (NULL); 1451 } 1452 1453 void 1454 intel_overlay_print_error_state(struct sbuf *m, 1455 struct intel_overlay_error_state *error) 1456 { 1457 sbuf_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n", 1458 error->dovsta, error->isr); 1459 sbuf_printf(m, " Register file at 0x%08lx:\n", 1460 error->base); 1461 1462 #define P(x) sbuf_printf(m, " " #x ": 0x%08x\n", error->regs.x) 1463 P(OBUF_0Y); 1464 P(OBUF_1Y); 1465 P(OBUF_0U); 1466 P(OBUF_0V); 1467 P(OBUF_1U); 1468 P(OBUF_1V); 1469 P(OSTRIDE); 1470 P(YRGB_VPH); 1471 P(UV_VPH); 1472 P(HORZ_PH); 1473 P(INIT_PHS); 1474 P(DWINPOS); 1475 P(DWINSZ); 1476 P(SWIDTH); 1477 P(SWIDTHSW); 1478 P(SHEIGHT); 1479 P(YRGBSCALE); 1480 P(UVSCALE); 1481 P(OCLRC0); 1482 P(OCLRC1); 1483 P(DCLRKV); 1484 P(DCLRKM); 1485 P(SCLRKVH); 1486 P(SCLRKVL); 1487 P(SCLRKEN); 1488 P(OCONFIG); 1489 P(OCMD); 1490 P(OSTART_0Y); 1491 P(OSTART_1Y); 1492 P(OSTART_0U); 1493 P(OSTART_0V); 1494 P(OSTART_1U); 1495 P(OSTART_1V); 1496 P(OTILEOFF_0Y); 1497 P(OTILEOFF_1Y); 1498 P(OTILEOFF_0U); 1499 P(OTILEOFF_0V); 1500 P(OTILEOFF_1U); 1501 P(OTILEOFF_1V); 1502 P(FASTHSCALE); 1503 P(UVSCALEV); 1504 #undef P 1505 } 1506 #endif 1507