intel_overlay.c revision 282199
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 282199 2015-04-28 19:35:05Z dumbbell $"); 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 778 ret = intel_overlay_release_old_vid(overlay); 779 if (ret != 0) 780 return ret; 781 782 ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL); 783 if (ret != 0) 784 goto out_unpin; 785 786 ret = i915_gem_object_put_fence(new_bo); 787 if (ret) 788 goto out_unpin; 789 790 if (!overlay->active) { 791 u32 oconfig; 792 regs = intel_overlay_map_regs(overlay); 793 if (!regs) { 794 ret = -ENOMEM; 795 goto out_unpin; 796 } 797 oconfig = OCONF_CC_OUT_8BIT; 798 if (IS_GEN4(overlay->dev)) 799 oconfig |= OCONF_CSC_MODE_BT709; 800 oconfig |= overlay->crtc->pipe == 0 ? 801 OCONF_PIPE_A : OCONF_PIPE_B; 802 regs->OCONFIG = oconfig; 803 intel_overlay_unmap_regs(overlay, regs); 804 805 ret = intel_overlay_on(overlay); 806 if (ret != 0) 807 goto out_unpin; 808 } 809 810 regs = intel_overlay_map_regs(overlay); 811 if (!regs) { 812 ret = -ENOMEM; 813 goto out_unpin; 814 } 815 816 regs->DWINPOS = (params->dst_y << 16) | params->dst_x; 817 regs->DWINSZ = (params->dst_h << 16) | params->dst_w; 818 819 if (params->format & I915_OVERLAY_YUV_PACKED) 820 tmp_width = packed_width_bytes(params->format, params->src_w); 821 else 822 tmp_width = params->src_w; 823 824 swidth = params->src_w; 825 swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width); 826 sheight = params->src_h; 827 regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y; 828 ostride = params->stride_Y; 829 830 if (params->format & I915_OVERLAY_YUV_PLANAR) { 831 int uv_hscale = uv_hsubsampling(params->format); 832 int uv_vscale = uv_vsubsampling(params->format); 833 u32 tmp_U, tmp_V; 834 swidth |= (params->src_w/uv_hscale) << 16; 835 tmp_U = calc_swidthsw(overlay->dev, params->offset_U, 836 params->src_w/uv_hscale); 837 tmp_V = calc_swidthsw(overlay->dev, params->offset_V, 838 params->src_w/uv_hscale); 839 swidthsw |= max_u32(tmp_U, tmp_V) << 16; 840 sheight |= (params->src_h/uv_vscale) << 16; 841 regs->OBUF_0U = new_bo->gtt_offset + params->offset_U; 842 regs->OBUF_0V = new_bo->gtt_offset + params->offset_V; 843 ostride |= params->stride_UV << 16; 844 } 845 846 regs->SWIDTH = swidth; 847 regs->SWIDTHSW = swidthsw; 848 regs->SHEIGHT = sheight; 849 regs->OSTRIDE = ostride; 850 851 scale_changed = update_scaling_factors(overlay, regs, params); 852 853 update_colorkey(overlay, regs); 854 855 regs->OCMD = overlay_cmd_reg(params); 856 857 intel_overlay_unmap_regs(overlay, regs); 858 859 ret = intel_overlay_continue(overlay, scale_changed); 860 if (ret) 861 goto out_unpin; 862 863 overlay->old_vid_bo = overlay->vid_bo; 864 overlay->vid_bo = new_bo; 865 866 return 0; 867 868out_unpin: 869 i915_gem_object_unpin(new_bo); 870 return ret; 871} 872 873int intel_overlay_switch_off(struct intel_overlay *overlay) 874{ 875 struct overlay_registers *regs; 876 int ret; 877 878 DRM_LOCK_ASSERT(overlay->dev); 879 880 ret = intel_overlay_recover_from_interrupt(overlay); 881 if (ret != 0) 882 return ret; 883 884 if (!overlay->active) 885 return 0; 886 887 ret = intel_overlay_release_old_vid(overlay); 888 if (ret != 0) 889 return ret; 890 891 regs = intel_overlay_map_regs(overlay); 892 regs->OCMD = 0; 893 intel_overlay_unmap_regs(overlay, regs); 894 895 ret = intel_overlay_off(overlay); 896 if (ret != 0) 897 return ret; 898 899 intel_overlay_off_tail(overlay); 900 return 0; 901} 902 903static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, 904 struct intel_crtc *crtc) 905{ 906 drm_i915_private_t *dev_priv = overlay->dev->dev_private; 907 908 if (!crtc->active) 909 return -EINVAL; 910 911 /* can't use the overlay with double wide pipe */ 912 if (INTEL_INFO(overlay->dev)->gen < 4 && 913 (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE) 914 return -EINVAL; 915 916 return 0; 917} 918 919static void update_pfit_vscale_ratio(struct intel_overlay *overlay) 920{ 921 struct drm_device *dev = overlay->dev; 922 drm_i915_private_t *dev_priv = dev->dev_private; 923 u32 pfit_control = I915_READ(PFIT_CONTROL); 924 u32 ratio; 925 926 /* XXX: This is not the same logic as in the xorg driver, but more in 927 * line with the intel documentation for the i965 928 */ 929 if (INTEL_INFO(dev)->gen >= 4) { 930 /* on i965 use the PGM reg to read out the autoscaler values */ 931 ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; 932 } else { 933 if (pfit_control & VERT_AUTO_SCALE) 934 ratio = I915_READ(PFIT_AUTO_RATIOS); 935 else 936 ratio = I915_READ(PFIT_PGM_RATIOS); 937 ratio >>= PFIT_VERT_SCALE_SHIFT; 938 } 939 940 overlay->pfit_vscale_ratio = ratio; 941} 942 943static int check_overlay_dst(struct intel_overlay *overlay, 944 struct drm_intel_overlay_put_image *rec) 945{ 946 struct drm_display_mode *mode = &overlay->crtc->base.mode; 947 948 if (rec->dst_x < mode->hdisplay && 949 rec->dst_x + rec->dst_width <= mode->hdisplay && 950 rec->dst_y < mode->vdisplay && 951 rec->dst_y + rec->dst_height <= mode->vdisplay) 952 return 0; 953 else 954 return -EINVAL; 955} 956 957static int check_overlay_scaling(struct put_image_params *rec) 958{ 959 u32 tmp; 960 961 /* downscaling limit is 8.0 */ 962 tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16; 963 if (tmp > 7) 964 return -EINVAL; 965 tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16; 966 if (tmp > 7) 967 return -EINVAL; 968 969 return 0; 970} 971 972static int check_overlay_src(struct drm_device *dev, 973 struct drm_intel_overlay_put_image *rec, 974 struct drm_i915_gem_object *new_bo) 975{ 976 int uv_hscale = uv_hsubsampling(rec->flags); 977 int uv_vscale = uv_vsubsampling(rec->flags); 978 u32 stride_mask; 979 int depth; 980 u32 tmp; 981 982 /* check src dimensions */ 983 if (IS_845G(dev) || IS_I830(dev)) { 984 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY || 985 rec->src_width > IMAGE_MAX_WIDTH_LEGACY) 986 return -EINVAL; 987 } else { 988 if (rec->src_height > IMAGE_MAX_HEIGHT || 989 rec->src_width > IMAGE_MAX_WIDTH) 990 return -EINVAL; 991 } 992 993 /* better safe than sorry, use 4 as the maximal subsampling ratio */ 994 if (rec->src_height < N_VERT_Y_TAPS*4 || 995 rec->src_width < N_HORIZ_Y_TAPS*4) 996 return -EINVAL; 997 998 /* check alignment constraints */ 999 switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 1000 case I915_OVERLAY_RGB: 1001 /* not implemented */ 1002 return -EINVAL; 1003 1004 case I915_OVERLAY_YUV_PACKED: 1005 if (uv_vscale != 1) 1006 return -EINVAL; 1007 1008 depth = packed_depth_bytes(rec->flags); 1009 if (depth < 0) 1010 return depth; 1011 1012 /* ignore UV planes */ 1013 rec->stride_UV = 0; 1014 rec->offset_U = 0; 1015 rec->offset_V = 0; 1016 /* check pixel alignment */ 1017 if (rec->offset_Y % depth) 1018 return -EINVAL; 1019 break; 1020 1021 case I915_OVERLAY_YUV_PLANAR: 1022 if (uv_vscale < 0 || uv_hscale < 0) 1023 return -EINVAL; 1024 /* no offset restrictions for planar formats */ 1025 break; 1026 1027 default: 1028 return -EINVAL; 1029 } 1030 1031 if (rec->src_width % uv_hscale) 1032 return -EINVAL; 1033 1034 /* stride checking */ 1035 if (IS_I830(dev) || IS_845G(dev)) 1036 stride_mask = 255; 1037 else 1038 stride_mask = 63; 1039 1040 if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) 1041 return -EINVAL; 1042 if (IS_GEN4(dev) && rec->stride_Y < 512) 1043 return -EINVAL; 1044 1045 tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? 1046 4096 : 8192; 1047 if (rec->stride_Y > tmp || rec->stride_UV > 2*1024) 1048 return -EINVAL; 1049 1050 /* check buffer dimensions */ 1051 switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 1052 case I915_OVERLAY_RGB: 1053 case I915_OVERLAY_YUV_PACKED: 1054 /* always 4 Y values per depth pixels */ 1055 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y) 1056 return -EINVAL; 1057 1058 tmp = rec->stride_Y*rec->src_height; 1059 if (rec->offset_Y + tmp > new_bo->base.size) 1060 return -EINVAL; 1061 break; 1062 1063 case I915_OVERLAY_YUV_PLANAR: 1064 if (rec->src_width > rec->stride_Y) 1065 return -EINVAL; 1066 if (rec->src_width/uv_hscale > rec->stride_UV) 1067 return -EINVAL; 1068 1069 tmp = rec->stride_Y * rec->src_height; 1070 if (rec->offset_Y + tmp > new_bo->base.size) 1071 return -EINVAL; 1072 1073 tmp = rec->stride_UV * (rec->src_height / uv_vscale); 1074 if (rec->offset_U + tmp > new_bo->base.size || 1075 rec->offset_V + tmp > new_bo->base.size) 1076 return -EINVAL; 1077 break; 1078 } 1079 1080 return 0; 1081} 1082 1083/** 1084 * Return the pipe currently connected to the panel fitter, 1085 * or -1 if the panel fitter is not present or not in use 1086 */ 1087static int intel_panel_fitter_pipe(struct drm_device *dev) 1088{ 1089 struct drm_i915_private *dev_priv = dev->dev_private; 1090 u32 pfit_control; 1091 1092 /* i830 doesn't have a panel fitter */ 1093 if (IS_I830(dev)) 1094 return -1; 1095 1096 pfit_control = I915_READ(PFIT_CONTROL); 1097 1098 /* See if the panel fitter is in use */ 1099 if ((pfit_control & PFIT_ENABLE) == 0) 1100 return -1; 1101 1102 /* 965 can place panel fitter on either pipe */ 1103 if (IS_GEN4(dev)) 1104 return (pfit_control >> 29) & 0x3; 1105 1106 /* older chips can only use pipe 1 */ 1107 return 1; 1108} 1109 1110int intel_overlay_put_image(struct drm_device *dev, void *data, 1111 struct drm_file *file_priv) 1112{ 1113 struct drm_intel_overlay_put_image *put_image_rec = data; 1114 drm_i915_private_t *dev_priv = dev->dev_private; 1115 struct intel_overlay *overlay; 1116 struct drm_mode_object *drmmode_obj; 1117 struct intel_crtc *crtc; 1118 struct drm_i915_gem_object *new_bo; 1119 struct put_image_params *params; 1120 int ret; 1121 1122 /* No need to check for DRIVER_MODESET - we don't set it up then. */ 1123 overlay = dev_priv->overlay; 1124 if (!overlay) { 1125 DRM_DEBUG("userspace bug: no overlay\n"); 1126 return -ENODEV; 1127 } 1128 1129 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { 1130 sx_xlock(&dev->mode_config.mutex); 1131 DRM_LOCK(dev); 1132 1133 ret = intel_overlay_switch_off(overlay); 1134 1135 DRM_UNLOCK(dev); 1136 sx_xunlock(&dev->mode_config.mutex); 1137 1138 return ret; 1139 } 1140 1141 params = malloc(sizeof(struct put_image_params), DRM_I915_GEM, 1142 M_WAITOK | M_ZERO); 1143 1144 drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, 1145 DRM_MODE_OBJECT_CRTC); 1146 if (!drmmode_obj) { 1147 ret = -ENOENT; 1148 goto out_free; 1149 } 1150 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); 1151 1152 new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv, 1153 put_image_rec->bo_handle)); 1154 if (&new_bo->base == NULL) { 1155 ret = -ENOENT; 1156 goto out_free; 1157 } 1158 1159 sx_xlock(&dev->mode_config.mutex); 1160 DRM_LOCK(dev); 1161 1162 if (new_bo->tiling_mode) { 1163 DRM_ERROR("buffer used for overlay image can not be tiled\n"); 1164 ret = -EINVAL; 1165 goto out_unlock; 1166 } 1167 1168 ret = intel_overlay_recover_from_interrupt(overlay); 1169 if (ret != 0) 1170 goto out_unlock; 1171 1172 if (overlay->crtc != crtc) { 1173 struct drm_display_mode *mode = &crtc->base.mode; 1174 ret = intel_overlay_switch_off(overlay); 1175 if (ret != 0) 1176 goto out_unlock; 1177 1178 ret = check_overlay_possible_on_crtc(overlay, crtc); 1179 if (ret != 0) 1180 goto out_unlock; 1181 1182 overlay->crtc = crtc; 1183 crtc->overlay = overlay; 1184 1185 /* line too wide, i.e. one-line-mode */ 1186 if (mode->hdisplay > 1024 && 1187 intel_panel_fitter_pipe(dev) == crtc->pipe) { 1188 overlay->pfit_active = 1; 1189 update_pfit_vscale_ratio(overlay); 1190 } else 1191 overlay->pfit_active = 0; 1192 } 1193 1194 ret = check_overlay_dst(overlay, put_image_rec); 1195 if (ret != 0) 1196 goto out_unlock; 1197 1198 if (overlay->pfit_active) { 1199 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / 1200 overlay->pfit_vscale_ratio); 1201 /* shifting right rounds downwards, so add 1 */ 1202 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / 1203 overlay->pfit_vscale_ratio) + 1; 1204 } else { 1205 params->dst_y = put_image_rec->dst_y; 1206 params->dst_h = put_image_rec->dst_height; 1207 } 1208 params->dst_x = put_image_rec->dst_x; 1209 params->dst_w = put_image_rec->dst_width; 1210 1211 params->src_w = put_image_rec->src_width; 1212 params->src_h = put_image_rec->src_height; 1213 params->src_scan_w = put_image_rec->src_scan_width; 1214 params->src_scan_h = put_image_rec->src_scan_height; 1215 if (params->src_scan_h > params->src_h || 1216 params->src_scan_w > params->src_w) { 1217 ret = -EINVAL; 1218 goto out_unlock; 1219 } 1220 1221 ret = check_overlay_src(dev, put_image_rec, new_bo); 1222 if (ret != 0) 1223 goto out_unlock; 1224 params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK; 1225 params->stride_Y = put_image_rec->stride_Y; 1226 params->stride_UV = put_image_rec->stride_UV; 1227 params->offset_Y = put_image_rec->offset_Y; 1228 params->offset_U = put_image_rec->offset_U; 1229 params->offset_V = put_image_rec->offset_V; 1230 1231 /* Check scaling after src size to prevent a divide-by-zero. */ 1232 ret = check_overlay_scaling(params); 1233 if (ret != 0) 1234 goto out_unlock; 1235 1236 ret = intel_overlay_do_put_image(overlay, new_bo, params); 1237 if (ret != 0) 1238 goto out_unlock; 1239 1240 DRM_UNLOCK(dev); 1241 sx_xunlock(&dev->mode_config.mutex); 1242 1243 free(params, DRM_I915_GEM); 1244 1245 return 0; 1246 1247out_unlock: 1248 DRM_UNLOCK(dev); 1249 sx_xunlock(&dev->mode_config.mutex); 1250 drm_gem_object_unreference_unlocked(&new_bo->base); 1251out_free: 1252 free(params, DRM_I915_GEM); 1253 1254 return ret; 1255} 1256 1257static void update_reg_attrs(struct intel_overlay *overlay, 1258 struct overlay_registers *regs) 1259{ 1260 regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff); 1261 regs->OCLRC1 = overlay->saturation; 1262} 1263 1264static bool check_gamma_bounds(u32 gamma1, u32 gamma2) 1265{ 1266 int i; 1267 1268 if (gamma1 & 0xff000000 || gamma2 & 0xff000000) 1269 return false; 1270 1271 for (i = 0; i < 3; i++) { 1272 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) 1273 return false; 1274 } 1275 1276 return true; 1277} 1278 1279static bool check_gamma5_errata(u32 gamma5) 1280{ 1281 int i; 1282 1283 for (i = 0; i < 3; i++) { 1284 if (((gamma5 >> i*8) & 0xff) == 0x80) 1285 return false; 1286 } 1287 1288 return true; 1289} 1290 1291static int check_gamma(struct drm_intel_overlay_attrs *attrs) 1292{ 1293 if (!check_gamma_bounds(0, attrs->gamma0) || 1294 !check_gamma_bounds(attrs->gamma0, attrs->gamma1) || 1295 !check_gamma_bounds(attrs->gamma1, attrs->gamma2) || 1296 !check_gamma_bounds(attrs->gamma2, attrs->gamma3) || 1297 !check_gamma_bounds(attrs->gamma3, attrs->gamma4) || 1298 !check_gamma_bounds(attrs->gamma4, attrs->gamma5) || 1299 !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) 1300 return -EINVAL; 1301 1302 if (!check_gamma5_errata(attrs->gamma5)) 1303 return -EINVAL; 1304 1305 return 0; 1306} 1307 1308int intel_overlay_attrs(struct drm_device *dev, void *data, 1309 struct drm_file *file_priv) 1310{ 1311 struct drm_intel_overlay_attrs *attrs = data; 1312 drm_i915_private_t *dev_priv = dev->dev_private; 1313 struct intel_overlay *overlay; 1314 struct overlay_registers *regs; 1315 int ret; 1316 1317 /* No need to check for DRIVER_MODESET - we don't set it up then. */ 1318 overlay = dev_priv->overlay; 1319 if (!overlay) { 1320 DRM_DEBUG("userspace bug: no overlay\n"); 1321 return -ENODEV; 1322 } 1323 1324 sx_xlock(&dev->mode_config.mutex); 1325 DRM_LOCK(dev); 1326 1327 ret = -EINVAL; 1328 if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { 1329 attrs->color_key = overlay->color_key; 1330 attrs->brightness = overlay->brightness; 1331 attrs->contrast = overlay->contrast; 1332 attrs->saturation = overlay->saturation; 1333 1334 if (!IS_GEN2(dev)) { 1335 attrs->gamma0 = I915_READ(OGAMC0); 1336 attrs->gamma1 = I915_READ(OGAMC1); 1337 attrs->gamma2 = I915_READ(OGAMC2); 1338 attrs->gamma3 = I915_READ(OGAMC3); 1339 attrs->gamma4 = I915_READ(OGAMC4); 1340 attrs->gamma5 = I915_READ(OGAMC5); 1341 } 1342 } else { 1343 if (attrs->brightness < -128 || attrs->brightness > 127) 1344 goto out_unlock; 1345 if (attrs->contrast > 255) 1346 goto out_unlock; 1347 if (attrs->saturation > 1023) 1348 goto out_unlock; 1349 1350 overlay->color_key = attrs->color_key; 1351 overlay->brightness = attrs->brightness; 1352 overlay->contrast = attrs->contrast; 1353 overlay->saturation = attrs->saturation; 1354 1355 regs = intel_overlay_map_regs(overlay); 1356 if (!regs) { 1357 ret = -ENOMEM; 1358 goto out_unlock; 1359 } 1360 1361 update_reg_attrs(overlay, regs); 1362 1363 intel_overlay_unmap_regs(overlay, regs); 1364 1365 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { 1366 if (IS_GEN2(dev)) 1367 goto out_unlock; 1368 1369 if (overlay->active) { 1370 ret = -EBUSY; 1371 goto out_unlock; 1372 } 1373 1374 ret = check_gamma(attrs); 1375 if (ret) 1376 goto out_unlock; 1377 1378 I915_WRITE(OGAMC0, attrs->gamma0); 1379 I915_WRITE(OGAMC1, attrs->gamma1); 1380 I915_WRITE(OGAMC2, attrs->gamma2); 1381 I915_WRITE(OGAMC3, attrs->gamma3); 1382 I915_WRITE(OGAMC4, attrs->gamma4); 1383 I915_WRITE(OGAMC5, attrs->gamma5); 1384 } 1385 } 1386 1387 ret = 0; 1388out_unlock: 1389 DRM_UNLOCK(dev); 1390 sx_xunlock(&dev->mode_config.mutex); 1391 1392 return ret; 1393} 1394 1395void intel_setup_overlay(struct drm_device *dev) 1396{ 1397 drm_i915_private_t *dev_priv = dev->dev_private; 1398 struct intel_overlay *overlay; 1399 struct drm_i915_gem_object *reg_bo; 1400 struct overlay_registers *regs; 1401 int ret; 1402 1403 if (!HAS_OVERLAY(dev)) 1404 return; 1405 1406 overlay = malloc(sizeof(struct intel_overlay), DRM_I915_GEM, 1407 M_WAITOK | M_ZERO); 1408 DRM_LOCK(dev); 1409 if (dev_priv->overlay != NULL) 1410 goto out_free; 1411 overlay->dev = dev; 1412 1413 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); 1414 if (!reg_bo) 1415 goto out_free; 1416 overlay->reg_bo = reg_bo; 1417 1418 if (OVERLAY_NEEDS_PHYSICAL(dev)) { 1419 ret = i915_gem_attach_phys_object(dev, reg_bo, 1420 I915_GEM_PHYS_OVERLAY_REGS, 1421 PAGE_SIZE); 1422 if (ret) { 1423 DRM_ERROR("failed to attach phys overlay regs\n"); 1424 goto out_free_bo; 1425 } 1426 overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; 1427 } else { 1428 ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true); 1429 if (ret) { 1430 DRM_ERROR("failed to pin overlay register bo\n"); 1431 goto out_free_bo; 1432 } 1433 overlay->flip_addr = reg_bo->gtt_offset; 1434 1435 ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); 1436 if (ret) { 1437 DRM_ERROR("failed to move overlay register bo into the GTT\n"); 1438 goto out_unpin_bo; 1439 } 1440 } 1441 1442 /* init all values */ 1443 overlay->color_key = 0x0101fe; 1444 overlay->brightness = -19; 1445 overlay->contrast = 75; 1446 overlay->saturation = 146; 1447 1448 regs = intel_overlay_map_regs(overlay); 1449 if (!regs) 1450 goto out_unpin_bo; 1451 1452 memset(regs, 0, sizeof(struct overlay_registers)); 1453 update_polyphase_filter(regs); 1454 update_reg_attrs(overlay, regs); 1455 1456 intel_overlay_unmap_regs(overlay, regs); 1457 1458 dev_priv->overlay = overlay; 1459 DRM_UNLOCK(dev); 1460 DRM_INFO("initialized overlay support\n"); 1461 return; 1462 1463out_unpin_bo: 1464 if (!OVERLAY_NEEDS_PHYSICAL(dev)) 1465 i915_gem_object_unpin(reg_bo); 1466out_free_bo: 1467 drm_gem_object_unreference(®_bo->base); 1468out_free: 1469 DRM_UNLOCK(dev); 1470 free(overlay, DRM_I915_GEM); 1471 return; 1472} 1473 1474void intel_cleanup_overlay(struct drm_device *dev) 1475{ 1476 drm_i915_private_t *dev_priv = dev->dev_private; 1477 1478 if (!dev_priv->overlay) 1479 return; 1480 1481 /* The bo's should be free'd by the generic code already. 1482 * Furthermore modesetting teardown happens beforehand so the 1483 * hardware should be off already */ 1484 KASSERT(!dev_priv->overlay->active, ("Overlay still active")); 1485 1486 drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base); 1487 free(dev_priv->overlay, DRM_I915_GEM); 1488} 1489 1490struct intel_overlay_error_state { 1491 struct overlay_registers regs; 1492 unsigned long base; 1493 u32 dovsta; 1494 u32 isr; 1495}; 1496 1497struct intel_overlay_error_state * 1498intel_overlay_capture_error_state(struct drm_device *dev) 1499{ 1500 drm_i915_private_t *dev_priv = dev->dev_private; 1501 struct intel_overlay *overlay = dev_priv->overlay; 1502 struct intel_overlay_error_state *error; 1503 struct overlay_registers __iomem *regs; 1504 1505 if (!overlay || !overlay->active) 1506 return NULL; 1507 1508 error = malloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT); 1509 if (error == NULL) 1510 return NULL; 1511 1512 error->dovsta = I915_READ(DOVSTA); 1513 error->isr = I915_READ(ISR); 1514 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) 1515 error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; 1516 else 1517 error->base = (long) overlay->reg_bo->gtt_offset; 1518 1519 regs = intel_overlay_map_regs(overlay); 1520 if (!regs) 1521 goto err; 1522 1523 memcpy(&error->regs, regs, sizeof(struct overlay_registers)); 1524 intel_overlay_unmap_regs(overlay, regs); 1525 1526 return (error); 1527 1528err: 1529 free(error, DRM_I915_GEM); 1530 return (NULL); 1531} 1532 1533void 1534intel_overlay_print_error_state(struct sbuf *m, 1535 struct intel_overlay_error_state *error) 1536{ 1537 sbuf_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n", 1538 error->dovsta, error->isr); 1539 sbuf_printf(m, " Register file at 0x%08lx:\n", 1540 error->base); 1541 1542#define P(x) sbuf_printf(m, " " #x ": 0x%08x\n", error->regs.x) 1543 P(OBUF_0Y); 1544 P(OBUF_1Y); 1545 P(OBUF_0U); 1546 P(OBUF_0V); 1547 P(OBUF_1U); 1548 P(OBUF_1V); 1549 P(OSTRIDE); 1550 P(YRGB_VPH); 1551 P(UV_VPH); 1552 P(HORZ_PH); 1553 P(INIT_PHS); 1554 P(DWINPOS); 1555 P(DWINSZ); 1556 P(SWIDTH); 1557 P(SWIDTHSW); 1558 P(SHEIGHT); 1559 P(YRGBSCALE); 1560 P(UVSCALE); 1561 P(OCLRC0); 1562 P(OCLRC1); 1563 P(DCLRKV); 1564 P(DCLRKM); 1565 P(SCLRKVH); 1566 P(SCLRKVL); 1567 P(SCLRKEN); 1568 P(OCONFIG); 1569 P(OCMD); 1570 P(OSTART_0Y); 1571 P(OSTART_1Y); 1572 P(OSTART_0U); 1573 P(OSTART_0V); 1574 P(OSTART_1U); 1575 P(OSTART_1V); 1576 P(OTILEOFF_0Y); 1577 P(OTILEOFF_1Y); 1578 P(OTILEOFF_0U); 1579 P(OTILEOFF_0V); 1580 P(OTILEOFF_1U); 1581 P(OTILEOFF_1V); 1582 P(FASTHSCALE); 1583 P(UVSCALEV); 1584#undef P 1585} 1586