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