1/************************************************************************** 2 3Copyright 2001 VA Linux Systems Inc., Fremont, California. 4Copyright © 2002 by David Dawes 5 6All Rights Reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a 9copy of this software and associated documentation files (the "Software"), 10to deal in the Software without restriction, including without limitation 11on the rights to use, copy, modify, merge, publish, distribute, sub 12license, and/or sell copies of the Software, and to permit persons to whom 13the Software is furnished to do so, subject to the following conditions: 14 15The above copyright notice and this permission notice (including the next 16paragraph) shall be included in all copies or substantial portions of the 17Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 23DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29/* 30 * Authors: Jeff Hartmann <jhartmann@valinux.com> 31 * Abraham van der Merwe <abraham@2d3d.co.za> 32 * David Dawes <dawes@xfree86.org> 33 * Alan Hourihane <alanh@tungstengraphics.com> 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include <assert.h> 41#include <string.h> 42#include <stdio.h> 43#include <unistd.h> 44#include <stdlib.h> 45#include <stdio.h> 46#include <errno.h> 47 48#include "xorg-server.h" 49#include "xf86.h" 50#include "xf86_OSproc.h" 51#include "xf86cmap.h" 52#include "xf86drm.h" 53#include "compiler.h" 54#include "mipointer.h" 55#include "micmap.h" 56#include <X11/extensions/randr.h> 57#include "fb.h" 58#include "miscstruct.h" 59#include "dixstruct.h" 60#include "xf86xv.h" 61#include "shadow.h" 62#include "intel.h" 63#include "intel_video.h" 64#include "uxa_module.h" 65 66#ifdef INTEL_XVMC 67#define _INTEL_XVMC_SERVER_ 68#include "intel_xvmc.h" 69#endif 70 71#if USE_UXA 72#include "intel_uxa.h" 73#endif 74 75#include "intel_options.h" 76#include "i915_drm.h" 77 78static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL); 79static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL); 80static Bool I830EnterVT(VT_FUNC_ARGS_DECL); 81 82/* temporary */ 83extern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y); 84 85/* Export I830 options to i830 driver where necessary */ 86static void 87I830LoadPalette(ScrnInfoPtr scrn, int numColors, int *indices, 88 LOCO * colors, VisualPtr pVisual) 89{ 90 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 91 int i, j, index; 92 int p; 93 uint16_t lut_r[256], lut_g[256], lut_b[256]; 94 95 for (p = 0; p < xf86_config->num_crtc; p++) { 96 xf86CrtcPtr crtc = xf86_config->crtc[p]; 97 98 switch (scrn->depth) { 99 case 15: 100 for (i = 0; i < numColors; i++) { 101 index = indices[i]; 102 for (j = 0; j < 8; j++) { 103 lut_r[index * 8 + j] = 104 colors[index].red << 8; 105 lut_g[index * 8 + j] = 106 colors[index].green << 8; 107 lut_b[index * 8 + j] = 108 colors[index].blue << 8; 109 } 110 } 111 break; 112 case 16: 113 for (i = 0; i < numColors; i++) { 114 index = indices[i]; 115 116 if (index <= 31) { 117 for (j = 0; j < 8; j++) { 118 lut_r[index * 8 + j] = 119 colors[index].red << 8; 120 lut_b[index * 8 + j] = 121 colors[index].blue << 8; 122 } 123 } 124 125 for (j = 0; j < 4; j++) { 126 lut_g[index * 4 + j] = 127 colors[index].green << 8; 128 } 129 } 130 break; 131 default: 132 for (i = 0; i < numColors; i++) { 133 index = indices[i]; 134 lut_r[index] = colors[index].red << 8; 135 lut_g[index] = colors[index].green << 8; 136 lut_b[index] = colors[index].blue << 8; 137 } 138 break; 139 } 140 141 /* Make the change through RandR */ 142#ifdef RANDR_12_INTERFACE 143 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 144#else 145 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 146#endif 147 } 148} 149 150/** 151 * Adjust the screen pixmap for the current location of the front buffer. 152 * This is done at EnterVT when buffers are bound as long as the resources 153 * have already been created, but the first EnterVT happens before 154 * CreateScreenResources. 155 */ 156static Bool i830CreateScreenResources(ScreenPtr screen) 157{ 158 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 159 intel_screen_private *intel = intel_get_screen_private(scrn); 160 161 screen->CreateScreenResources = intel->CreateScreenResources; 162 if (!(*screen->CreateScreenResources) (screen)) 163 return FALSE; 164 165 if (!intel_uxa_create_screen_resources(screen)) 166 return FALSE; 167 168 intel_copy_fb(scrn); 169 return TRUE; 170} 171 172void 173intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo) 174{ 175 intel_uxa_set_pixmap_bo(pixmap, bo); 176} 177 178dri_bo * 179intel_get_pixmap_bo(PixmapPtr pixmap) 180{ 181 return intel_uxa_get_pixmap_bo(pixmap); 182} 183 184void 185intel_flush(intel_screen_private *intel) 186{ 187 intel_batch_submit(intel->scrn); 188} 189 190static void PreInitCleanup(ScrnInfoPtr scrn) 191{ 192 if (!scrn || !scrn->driverPrivate) 193 return; 194 195 free(scrn->driverPrivate); 196 scrn->driverPrivate = NULL; 197} 198 199static void intel_check_chipset_option(ScrnInfoPtr scrn) 200{ 201 intel_screen_private *intel = intel_get_screen_private(scrn); 202 intel_detect_chipset(scrn, intel->dev); 203} 204 205static Bool I830GetEarlyOptions(ScrnInfoPtr scrn) 206{ 207 intel_screen_private *intel = intel_get_screen_private(scrn); 208 209 /* Process the options */ 210 intel->Options = intel_options_get(scrn); 211 if (!intel->Options) 212 return FALSE; 213 214#if USE_UXA 215 intel->fallback_debug = xf86ReturnOptValBool(intel->Options, 216 OPTION_FALLBACKDEBUG, 217 FALSE); 218 219 intel->debug_flush = 0; 220 221 if (xf86ReturnOptValBool(intel->Options, 222 OPTION_DEBUG_FLUSH_BATCHES, 223 FALSE)) 224 intel->debug_flush |= DEBUG_FLUSH_BATCHES; 225 226 if (xf86ReturnOptValBool(intel->Options, 227 OPTION_DEBUG_FLUSH_CACHES, 228 FALSE)) 229 intel->debug_flush |= DEBUG_FLUSH_CACHES; 230 231 if (xf86ReturnOptValBool(intel->Options, 232 OPTION_DEBUG_WAIT, 233 FALSE)) 234 intel->debug_flush |= DEBUG_FLUSH_WAIT; 235 236#endif 237 return TRUE; 238} 239 240static Bool intel_option_cast_string_to_bool(intel_screen_private *intel, 241 int id, Bool val) 242{ 243#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0) 244 xf86getBoolValue(&val, xf86GetOptValString(intel->Options, id)); 245 return val; 246#else 247 return val; 248#endif 249} 250 251static void intel_check_dri_option(ScrnInfoPtr scrn) 252{ 253 intel_screen_private *intel = intel_get_screen_private(scrn); 254 255 intel->dri2 = intel->dri3 = DRI_NONE; 256 if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE)) 257 intel->dri2 = intel->dri3 = DRI_DISABLED; 258 259 if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) { 260 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 261 "DRI is disabled because it " 262 "runs only at depths 16, 24, and 30.\n"); 263 intel->dri2 = intel->dri3 = DRI_DISABLED; 264 } 265} 266 267static Bool intel_open_drm_master(ScrnInfoPtr scrn) 268{ 269 intel_screen_private *intel = intel_get_screen_private(scrn); 270 intel->dev = intel_get_device(scrn, &intel->drmSubFD); 271 return intel->dev != NULL; 272} 273 274static int intel_init_bufmgr(intel_screen_private *intel) 275{ 276 int batch_size; 277 278 batch_size = 4096 * 4; 279 if (IS_I865G(intel)) 280 /* The 865 has issues with larger-than-page-sized batch buffers. */ 281 batch_size = 4096; 282 283 intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size); 284 if (!intel->bufmgr) 285 return FALSE; 286 287 if (xf86ReturnOptValBool(intel->Options, OPTION_BUFFER_CACHE, TRUE)) 288 drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr); 289 drm_intel_bufmgr_gem_set_vma_cache_size(intel->bufmgr, 512); 290 drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr); 291 292 list_init(&intel->batch_pixmaps); 293 294 if ((INTEL_INFO(intel)->gen == 060)) { 295 intel->wa_scratch_bo = 296 drm_intel_bo_alloc(intel->bufmgr, "wa scratch", 297 4096, 4096); 298 } 299 300 return TRUE; 301} 302 303static void intel_bufmgr_fini(intel_screen_private *intel) 304{ 305 if (intel->bufmgr == NULL) 306 return; 307 308 drm_intel_bo_unreference(intel->wa_scratch_bo); 309 drm_intel_bufmgr_destroy(intel->bufmgr); 310} 311 312static void I830XvInit(ScrnInfoPtr scrn) 313{ 314 intel_screen_private *intel = intel_get_screen_private(scrn); 315 MessageType from = X_PROBED; 316 317 intel->XvPreferOverlay = 318 xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE); 319 320 if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY, 321 &(intel->colorKey))) { 322 from = X_CONFIG; 323 } else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY, 324 &(intel->colorKey))) { 325 from = X_CONFIG; 326 } else { 327 intel->colorKey = 328 (1 << scrn->offset.red) | (1 << scrn->offset.green) | 329 (((scrn->mask.blue >> scrn->offset.blue) - 1) << 330 scrn->offset.blue); 331 from = X_DEFAULT; 332 } 333 xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n", 334 intel->colorKey); 335} 336 337static Bool drm_has_boolean_param(struct intel_screen_private *intel, 338 int param) 339{ 340 drm_i915_getparam_t gp; 341 int value; 342 343 gp.value = &value; 344 gp.param = param; 345 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp)) 346 return FALSE; 347 348 return value; 349} 350 351static Bool has_kernel_flush(struct intel_screen_private *intel) 352{ 353 /* The BLT ring was introduced at the same time as the 354 * automatic flush for the busy-ioctl. 355 */ 356 return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT); 357} 358 359static Bool has_relaxed_fencing(struct intel_screen_private *intel) 360{ 361 return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING); 362} 363 364static Bool has_prime_vmap_flush(struct intel_screen_private *intel) 365{ 366 return drm_has_boolean_param(intel, I915_PARAM_HAS_PRIME_VMAP_FLUSH); 367} 368 369static Bool can_accelerate_blt(struct intel_screen_private *intel) 370{ 371 if (INTEL_INFO(intel)->gen == -1) 372 return FALSE; 373 374 if (xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_DISABLE, FALSE) || 375 !intel_option_cast_string_to_bool(intel, OPTION_ACCEL_METHOD, TRUE)) { 376 xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG, 377 "Disabling hardware acceleration.\n"); 378 return FALSE; 379 } 380 381 if (INTEL_INFO(intel)->gen == 060) { 382 struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index); 383 384 /* Sandybridge rev07 locks up easily, even with the 385 * BLT ring workaround in place. 386 * Thus use shadowfb by default. 387 */ 388 if (device->revision < 8) { 389 xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING, 390 "Disabling hardware acceleration on this pre-production hardware.\n"); 391 392 return FALSE; 393 } 394 } 395 396 if (INTEL_INFO(intel)->gen >= 060) { 397 drm_i915_getparam_t gp; 398 int value; 399 400 /* On Sandybridge we need the BLT in order to do anything since 401 * it so frequently used in the acceleration code paths. 402 */ 403 gp.value = &value; 404 gp.param = I915_PARAM_HAS_BLT; 405 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp)) 406 return FALSE; 407 } 408 409 return TRUE; 410} 411 412static void intel_setup_capabilities(ScrnInfoPtr scrn) 413{ 414#ifdef INTEL_PIXMAP_SHARING 415 intel_screen_private *intel = intel_get_screen_private(scrn); 416 uint64_t value; 417 int ret; 418 419 scrn->capabilities = 0; 420 421 ret = drmGetCap(intel->drmSubFD, DRM_CAP_PRIME, &value); 422 if (ret == 0) { 423 if (value & DRM_PRIME_CAP_EXPORT) 424 scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; 425 if (value & DRM_PRIME_CAP_IMPORT) 426 scrn->capabilities |= RR_Capability_SinkOutput; 427 } 428#endif 429} 430 431/** 432 * This is called before ScreenInit to do any require probing of screen 433 * configuration. 434 * 435 * This code generally covers probing, module loading, option handling 436 * card mapping, and RandR setup. 437 * 438 * Since xf86InitialConfiguration ends up requiring that we set video modes 439 * in order to detect configuration, we end up having to do a lot of driver 440 * setup (talking to the DRM, mapping the device, etc.) in this function. 441 * As a result, we want to set up that server initialization once rather 442 * that doing it per generation. 443 */ 444static Bool I830PreInit(ScrnInfoPtr scrn, int flags) 445{ 446 intel_screen_private *intel; 447 rgb defaultWeight = { 0, 0, 0 }; 448 EntityInfoPtr pEnt; 449 int flags24; 450 Gamma zeros = { 0.0, 0.0, 0.0 }; 451 452 if (scrn->numEntities != 1) 453 return FALSE; 454 455 pEnt = xf86GetEntityInfo(scrn->entityList[0]); 456 if (pEnt == NULL) 457 return FALSE; 458 459 if (pEnt->location.type != BUS_PCI 460#ifdef XSERVER_PLATFORM_BUS 461 && pEnt->location.type != BUS_PLATFORM 462#endif 463 ) 464 return FALSE; 465 466 if (flags & PROBE_DETECT) 467 return TRUE; 468 469 if (((uintptr_t)scrn->driverPrivate) & 3) { 470 intel = xnfcalloc(sizeof(*intel), 1); 471 if (intel == NULL) 472 return FALSE; 473 474 intel->info = (void *)((uintptr_t)scrn->driverPrivate & ~3); 475 scrn->driverPrivate = intel; 476 } 477 intel = intel_get_screen_private(scrn); 478 intel->scrn = scrn; 479 intel->pEnt = pEnt; 480 481 scrn->displayWidth = 640; /* default it */ 482 483 if (!intel_open_drm_master(scrn)) { 484 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 485 "Failed to become DRM master.\n"); 486 return FALSE; 487 } 488 489 scrn->monitor = scrn->confScreen->monitor; 490 scrn->progClock = TRUE; 491 scrn->rgbBits = 8; 492 493 flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32; 494 495 if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24)) 496 return FALSE; 497 498 switch (scrn->depth) { 499 case 15: 500 case 16: 501 case 24: 502 case 30: 503 break; 504 case 8: 505 default: 506 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 507 "Given depth (%d) is not supported by intel driver\n", 508 scrn->depth); 509 return FALSE; 510 } 511 xf86PrintDepthBpp(scrn); 512 513 if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 514 return FALSE; 515 if (!xf86SetDefaultVisual(scrn, -1)) 516 return FALSE; 517 518 intel->cpp = scrn->bitsPerPixel / 8; 519 520 if (!I830GetEarlyOptions(scrn)) 521 return FALSE; 522 523 intel_setup_capabilities(scrn); 524 intel_check_chipset_option(scrn); 525 intel_check_dri_option(scrn); 526 527 if (!intel_init_bufmgr(intel)) { 528 PreInitCleanup(scrn); 529 return FALSE; 530 } 531 532 intel->force_fallback = 533 drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0; 534 535 /* Enable tiling by default */ 536 intel->tiling = INTEL_TILING_ALL; 537 538 /* Allow user override if they set a value */ 539 if (!xf86ReturnOptValBool(intel->Options, OPTION_TILING_2D, TRUE)) 540 intel->tiling &= ~INTEL_TILING_2D; 541 if (xf86ReturnOptValBool(intel->Options, OPTION_TILING_FB, FALSE)) 542 intel->tiling &= ~INTEL_TILING_FB; 543 if (!can_accelerate_blt(intel)) { 544 intel->force_fallback = TRUE; 545 intel->tiling &= ~INTEL_TILING_FB; 546 } 547 548 intel->has_kernel_flush = has_kernel_flush(intel); 549 550 intel->has_prime_vmap_flush = has_prime_vmap_flush(intel); 551 552 intel->has_relaxed_fencing = INTEL_INFO(intel)->gen >= 033; 553 /* And override the user if there is no kernel support */ 554 if (intel->has_relaxed_fencing) 555 intel->has_relaxed_fencing = has_relaxed_fencing(intel); 556 557 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 558 "Relaxed fencing %s\n", 559 intel->has_relaxed_fencing ? "enabled" : "disabled"); 560 561 /* SwapBuffers delays to avoid tearing */ 562 intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options, 563 OPTION_SWAPBUFFERS_WAIT, 564 TRUE); 565 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Wait on SwapBuffers? %s\n", 566 intel->swapbuffers_wait ? "enabled" : "disabled"); 567 568 intel->use_triple_buffer = 569 xf86ReturnOptValBool(intel->Options, 570 OPTION_TRIPLE_BUFFER, 571 TRUE); 572 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Triple buffering? %s\n", 573 intel->use_triple_buffer ? "enabled" : "disabled"); 574 575 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n", 576 intel->tiling & INTEL_TILING_FB ? "tiled" : "linear"); 577 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Pixmaps %s\n", 578 intel->tiling & INTEL_TILING_2D ? "tiled" : "linear"); 579 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n", 580 intel->tiling & INTEL_TILING_3D ? "tiled" : "linear"); 581 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n", 582 intel->swapbuffers_wait ? "en" : "dis"); 583 584 I830XvInit(scrn); 585 586 if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) { 587 PreInitCleanup(scrn); 588 return FALSE; 589 } 590 591 if (!xf86SetGamma(scrn, zeros)) { 592 PreInitCleanup(scrn); 593 return FALSE; 594 } 595 596 if (scrn->modes == NULL) { 597 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n"); 598 PreInitCleanup(scrn); 599 return FALSE; 600 } 601 scrn->currentMode = scrn->modes; 602 603 /* Set display resolution */ 604 xf86SetDpi(scrn, 0, 0); 605 606 /* Load the required sub modules */ 607 if (!xf86LoadSubModule(scrn, "fb")) { 608 PreInitCleanup(scrn); 609 return FALSE; 610 } 611 612 /* Load the dri modules if requested. */ 613#if HAVE_DRI2 614 if (intel->dri2 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri2")) 615 intel->dri2 = DRI_DISABLED; 616#endif 617#if HAVE_DRI3 618 if (intel->dri3 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri3")) 619 intel->dri3 = DRI_DISABLED; 620#endif 621 622 return TRUE; 623} 624 625#ifdef INTEL_PIXMAP_SHARING 626#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 25 627#define slave_dst secondary_dst 628#define master_pixmap primary_pixmap 629#endif 630static void 631redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) 632{ 633 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 634 intel_screen_private *intel = intel_get_screen_private(scrn); 635 RegionRec pixregion; 636 int was_blocked; 637 638 PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap); 639 RegionTranslate(&pixregion, dirty->x, dirty->y); 640 RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage)); 641 RegionTranslate(&pixregion, -dirty->x, -dirty->y); 642 was_blocked = RegionNil(&pixregion); 643 DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); 644 RegionUninit(&pixregion); 645 if (was_blocked) 646 return; 647 648 PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap); 649#ifdef HAS_DIRTYTRACKING_ROTATION 650 PixmapSyncDirtyHelper(dirty); 651#else 652 PixmapSyncDirtyHelper(dirty, &pixregion); 653#endif 654 RegionUninit(&pixregion); 655 656 intel_flush(intel); 657 if (!intel->has_prime_vmap_flush) { 658 drm_intel_bo *bo = intel_uxa_get_pixmap_bo(dirty->slave_dst->master_pixmap); 659 was_blocked = xf86BlockSIGIO(); 660 drm_intel_bo_map(bo, FALSE); 661 drm_intel_bo_unmap(bo); 662 xf86UnblockSIGIO(was_blocked); 663 } 664 665 DamageRegionProcessPending(&dirty->slave_dst->drawable); 666 return; 667} 668 669static void 670intel_dirty_update(ScreenPtr screen) 671{ 672 RegionPtr region; 673 PixmapDirtyUpdatePtr ent; 674 675 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 676 return; 677 678 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 679 region = DamageRegion(ent->damage); 680 if (RegionNotEmpty(region)) { 681 redisplay_dirty(screen, ent); 682 DamageEmpty(ent->damage); 683 } 684 } 685} 686#endif 687 688static void 689I830BlockHandler(BLOCKHANDLER_ARGS_DECL) 690{ 691 SCREEN_PTR(arg); 692 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 693 intel_screen_private *intel = intel_get_screen_private(scrn); 694 695 screen->BlockHandler = intel->BlockHandler; 696 697 (*screen->BlockHandler) (BLOCKHANDLER_ARGS); 698 699 intel->BlockHandler = screen->BlockHandler; 700 screen->BlockHandler = I830BlockHandler; 701 702 intel_uxa_block_handler(intel); 703 intel_video_block_handler(intel); 704#ifdef INTEL_PIXMAP_SHARING 705 intel_dirty_update(screen); 706#endif 707} 708 709static Bool 710intel_init_initial_framebuffer(ScrnInfoPtr scrn) 711{ 712 intel_screen_private *intel = intel_get_screen_private(scrn); 713 int width = scrn->virtualX; 714 int height = scrn->virtualY; 715 int pitch; 716 uint32_t tiling; 717 718 intel->front_buffer = intel_allocate_framebuffer(scrn, 719 width, height, 720 intel->cpp, 721 &pitch, &tiling); 722 723 if (!intel->front_buffer) { 724 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 725 "Couldn't allocate initial framebuffer.\n"); 726 return FALSE; 727 } 728 729 intel->front_pitch = pitch; 730 intel->front_tiling = tiling; 731 scrn->displayWidth = pitch / intel->cpp; 732 733 return TRUE; 734} 735 736static void 737intel_flush_callback(CallbackListPtr *list, 738 pointer user_data, pointer call_data) 739{ 740 ScrnInfoPtr scrn = user_data; 741 if (scrn->vtSema) 742 intel_flush(intel_get_screen_private(scrn)); 743} 744 745#if HAVE_UDEV 746static void 747I830HandleUEvents(int fd, void *closure) 748{ 749 ScrnInfoPtr scrn = closure; 750 intel_screen_private *intel = intel_get_screen_private(scrn); 751 struct udev_device *dev; 752 const char *hotplug; 753 struct stat s; 754 dev_t udev_devnum; 755 756 dev = udev_monitor_receive_device(intel->uevent_monitor); 757 if (!dev) 758 return; 759 760 udev_devnum = udev_device_get_devnum(dev); 761 if (fstat(intel->drmSubFD, &s)) { 762 udev_device_unref(dev); 763 return; 764 } 765 /* 766 * Check to make sure this event is directed at our 767 * device (by comparing dev_t values), then make 768 * sure it's a hotplug event (HOTPLUG=1) 769 */ 770 771 hotplug = udev_device_get_property_value(dev, "HOTPLUG"); 772 773 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && 774 hotplug && atoi(hotplug) == 1) 775 { 776 intel_mode_hotplug(intel); 777 } 778 779 udev_device_unref(dev); 780} 781 782static void 783I830UeventInit(ScrnInfoPtr scrn) 784{ 785 intel_screen_private *intel = intel_get_screen_private(scrn); 786 struct udev *u; 787 struct udev_monitor *mon; 788 Bool hotplug; 789 MessageType from = X_CONFIG; 790 791 if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) { 792 from = X_DEFAULT; 793 hotplug = TRUE; 794 } 795 796 xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n", 797 hotplug ? "enabled" : "disabled"); 798 if (!hotplug) 799 return; 800 801 u = udev_new(); 802 if (!u) 803 return; 804 805 mon = udev_monitor_new_from_netlink(u, "udev"); 806 807 if (!mon) { 808 udev_unref(u); 809 return; 810 } 811 812 if (udev_monitor_filter_add_match_subsystem_devtype(mon, 813 "drm", 814 "drm_minor") < 0 || 815 udev_monitor_enable_receiving(mon) < 0) 816 { 817 udev_monitor_unref(mon); 818 udev_unref(u); 819 return; 820 } 821 822 intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), 823 I830HandleUEvents, scrn); 824 if (!intel->uevent_handler) { 825 udev_monitor_unref(mon); 826 udev_unref(u); 827 return; 828 } 829 830 intel->uevent_monitor = mon; 831} 832 833static void 834I830UeventFini(ScrnInfoPtr scrn) 835{ 836 intel_screen_private *intel = intel_get_screen_private(scrn); 837 838 if (intel->uevent_handler) { 839 struct udev *u = udev_monitor_get_udev(intel->uevent_monitor); 840 841 xf86RemoveGeneralHandler(intel->uevent_handler); 842 843 udev_monitor_unref(intel->uevent_monitor); 844 udev_unref(u); 845 intel->uevent_handler = NULL; 846 intel->uevent_monitor = NULL; 847 } 848} 849#endif /* HAVE_UDEV */ 850 851static Bool 852I830ScreenInit(SCREEN_INIT_ARGS_DECL) 853{ 854 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 855 intel_screen_private *intel = intel_get_screen_private(scrn); 856 VisualPtr visual; 857#ifdef INTEL_XVMC 858 MessageType from; 859#endif 860 struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index); 861 int fb_bar = IS_GEN2(intel) ? 0 : 2; 862 863 scrn->videoRam = device->regions[fb_bar].size / 1024; 864 865 intel->last_3d = LAST_3D_OTHER; 866 intel->overlayOn = FALSE; 867 868 /* 869 * Set this so that the overlay allocation is factored in when 870 * appropriate. 871 */ 872 intel->XvEnabled = TRUE; 873 874 if (!intel_init_initial_framebuffer(scrn)) 875 return FALSE; 876 877 miClearVisualTypes(); 878 if (!miSetVisualTypes(scrn->depth, 879 miGetDefaultVisualMask(scrn->depth), 880 scrn->rgbBits, scrn->defaultVisual)) 881 return FALSE; 882 if (!miSetPixmapDepths()) 883 return FALSE; 884 885 /* Must be first, before anything else installs screen callbacks. */ 886 if (!fbScreenInit(screen, NULL, 887 scrn->virtualX, scrn->virtualY, 888 scrn->xDpi, scrn->yDpi, 889 scrn->displayWidth, scrn->bitsPerPixel)) 890 return FALSE; 891 892 if (scrn->bitsPerPixel > 8) { 893 /* Fixup RGB ordering */ 894 visual = screen->visuals + screen->numVisuals; 895 while (--visual >= screen->visuals) { 896 if ((visual->class | DynamicClass) == DirectColor) { 897 visual->offsetRed = scrn->offset.red; 898 visual->offsetGreen = scrn->offset.green; 899 visual->offsetBlue = scrn->offset.blue; 900 visual->redMask = scrn->mask.red; 901 visual->greenMask = scrn->mask.green; 902 visual->blueMask = scrn->mask.blue; 903 } 904 } 905 } 906 907 fbPictureInit(screen, NULL, 0); 908 909 xf86SetBlackWhitePixels(screen); 910 911 if (!intel_uxa_init(screen)) { 912 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 913 "Hardware acceleration initialization failed\n"); 914 return FALSE; 915 } 916 917#if HAVE_DRI2 918 if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen)) 919 intel->dri2 = DRI_ACTIVE; 920#endif 921 922#if HAVE_DRI3 923 if (!intel_sync_init(screen)) 924 intel->dri3 = DRI_DISABLED; 925 if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen)) 926 intel->dri3 = DRI_ACTIVE; 927#endif 928 929 if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE)) 930 intel_present_screen_init(screen); 931 932 xf86SetBackingStore(screen); 933 xf86SetSilkenMouse(screen); 934 miDCInitialize(screen, xf86GetPointerScreenFuncs()); 935 936 xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); 937 if (!xf86_cursors_init(screen, 64, 64, 938 (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 939 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 940 HARDWARE_CURSOR_INVERT_MASK | 941 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 942 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 943 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 944 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 945 HARDWARE_CURSOR_ARGB))) { 946 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 947 "Hardware cursor initialization failed\n"); 948 } 949 950 intel->BlockHandler = screen->BlockHandler; 951 screen->BlockHandler = I830BlockHandler; 952 953#ifdef INTEL_PIXMAP_SHARING 954 screen->StartPixmapTracking = PixmapStartDirtyTracking; 955 screen->StopPixmapTracking = PixmapStopDirtyTracking; 956#endif 957 958 if (!AddCallback(&FlushCallback, intel_flush_callback, scrn)) 959 return FALSE; 960 961 screen->SaveScreen = xf86SaveScreen; 962 intel->CloseScreen = screen->CloseScreen; 963 screen->CloseScreen = I830CloseScreen; 964 intel->CreateScreenResources = screen->CreateScreenResources; 965 screen->CreateScreenResources = i830CreateScreenResources; 966 967 if (!xf86CrtcScreenInit(screen)) 968 return FALSE; 969 970 if (!miCreateDefColormap(screen)) 971 return FALSE; 972 973 if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL, 974 CMAP_RELOAD_ON_MODE_SWITCH | 975 CMAP_PALETTED_TRUECOLOR)) { 976 return FALSE; 977 } 978 979 xf86DPMSInit(screen, xf86DPMSSet, 0); 980 981#ifdef INTEL_XVMC 982 if (INTEL_INFO(intel)->gen >= 040) 983 intel->XvMCEnabled = TRUE; 984 from = (intel->dri2 == DRI_ACTIVE && 985 xf86GetOptValBool(intel->Options, OPTION_XVMC, 986 &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT); 987 xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n", 988 intel->XvMCEnabled ? "en" : "dis"); 989#endif 990 /* Init video */ 991 if (intel->XvEnabled) 992 intel_video_init(screen); 993 994#if HAVE_DRI2 995 switch (intel->dri2) { 996 case DRI_ACTIVE: 997 xf86DrvMsg(scrn->scrnIndex, X_INFO, 998 "DRI2: Enabled\n"); 999 break; 1000 case DRI_DISABLED: 1001 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1002 "DRI2: Disabled\n"); 1003 break; 1004 case DRI_NONE: 1005 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1006 "DRI2: Failed\n"); 1007 break; 1008 } 1009#else 1010 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1011 "DRI2: Not available\n"); 1012#endif 1013 1014#if HAVE_DRI3 1015 switch (intel->dri3) { 1016 case DRI_ACTIVE: 1017 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1018 "DRI3: Enabled\n"); 1019 break; 1020 case DRI_DISABLED: 1021 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1022 "DRI3: Disabled\n"); 1023 break; 1024 case DRI_NONE: 1025 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1026 "DRI3: Failed\n"); 1027 break; 1028 } 1029#else 1030 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1031 "DRI3: Not available\n"); 1032#endif 1033 1034 if (serverGeneration == 1) 1035 xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 1036 1037 intel_mode_init(intel); 1038 1039 intel->suspended = FALSE; 1040 1041#if HAVE_UDEV 1042 I830UeventInit(scrn); 1043#endif 1044 1045 /* Must force it before EnterVT, so we are in control of VT and 1046 * later memory should be bound when allocating, e.g rotate_mem */ 1047 scrn->vtSema = TRUE; 1048 1049 return I830EnterVT(VT_FUNC_ARGS(0)); 1050} 1051 1052static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL) 1053{ 1054} 1055 1056static void I830FreeScreen(FREE_SCREEN_ARGS_DECL) 1057{ 1058 SCRN_INFO_PTR(arg); 1059 intel_screen_private *intel = intel_get_screen_private(scrn); 1060 1061 if (intel && !((uintptr_t)intel & 3)) { 1062 intel_mode_fini(intel); 1063 intel_bufmgr_fini(intel); 1064 intel_put_device(intel->dev); 1065 1066 free(intel); 1067 scrn->driverPrivate = NULL; 1068 } 1069} 1070 1071static void I830LeaveVT(VT_FUNC_ARGS_DECL) 1072{ 1073 SCRN_INFO_PTR(arg); 1074 intel_screen_private *intel = intel_get_screen_private(scrn); 1075 1076 xf86RotateFreeShadow(scrn); 1077 1078 xf86_hide_cursors(scrn); 1079 1080 if (intel_put_master(intel->dev)) 1081 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1082 "drmDropMaster failed: %s\n", strerror(errno)); 1083} 1084 1085/* 1086 * This gets called when gaining control of the VT, and from ScreenInit(). 1087 */ 1088static Bool I830EnterVT(VT_FUNC_ARGS_DECL) 1089{ 1090 SCRN_INFO_PTR(arg); 1091 intel_screen_private *intel = intel_get_screen_private(scrn); 1092 1093 if (intel_get_master(intel->dev)) { 1094 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1095 "drmSetMaster failed: %s\n", 1096 strerror(errno)); 1097 return FALSE; 1098 } 1099 1100 if (!xf86SetDesiredModes(scrn)) 1101 return FALSE; 1102 1103 intel_mode_disable_unused_functions(scrn); 1104 return TRUE; 1105} 1106 1107static Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL) 1108{ 1109 SCRN_INFO_PTR(arg); 1110 1111 return xf86SetSingleMode(scrn, mode, RR_Rotate_0); 1112} 1113 1114static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1115{ 1116 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1117 intel_screen_private *intel = intel_get_screen_private(scrn); 1118 1119#if HAVE_UDEV 1120 I830UeventFini(scrn); 1121#endif 1122 1123 intel_mode_close(intel); 1124 1125 DeleteCallback(&FlushCallback, intel_flush_callback, scrn); 1126 1127 TimerFree(intel->cache_expire); 1128 intel->cache_expire = NULL; 1129 1130 if (intel->uxa_driver) { 1131 uxa_driver_fini(screen); 1132 free(intel->uxa_driver); 1133 intel->uxa_driver = NULL; 1134 } 1135 1136 if (intel->back_buffer) { 1137 drm_intel_bo_unreference(intel->back_buffer); 1138 intel->back_buffer = NULL; 1139 } 1140 1141 if (intel->front_buffer) { 1142 intel_mode_remove_fb(intel); 1143 drm_intel_bo_unreference(intel->front_buffer); 1144 intel->front_buffer = NULL; 1145 } 1146 1147 if (scrn->vtSema == TRUE) { 1148 I830LeaveVT(VT_FUNC_ARGS(0)); 1149 } 1150 1151 intel_batch_teardown(scrn); 1152 1153 if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100) 1154 gen4_render_state_cleanup(scrn); 1155 1156 xf86_cursors_fini(screen); 1157 1158 i965_free_video(scrn); 1159 1160 screen->CloseScreen = intel->CloseScreen; 1161 (*screen->CloseScreen) (CLOSE_SCREEN_ARGS); 1162 1163 if (intel->dri2 == DRI_ACTIVE) { 1164 I830DRI2CloseScreen(screen); 1165 intel->dri2 = DRI_NONE; 1166 } 1167 1168 if (intel->dri3 == DRI_ACTIVE) { 1169 /* nothing to do here? */ 1170 intel->dri3 = DRI_NONE; 1171 } 1172 1173 intel_sync_close(screen); 1174 1175 xf86GARTCloseScreen(scrn->scrnIndex); 1176 1177 scrn->vtSema = FALSE; 1178 return TRUE; 1179} 1180 1181static ModeStatus 1182I830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1183{ 1184 SCRN_INFO_PTR(arg); 1185 if (mode->Flags & V_INTERLACE) { 1186 if (verbose) { 1187 xf86DrvMsg(scrn->scrnIndex, X_PROBED, 1188 "Removing interlaced mode \"%s\"\n", 1189 mode->name); 1190 } 1191 return MODE_BAD; 1192 } 1193 return MODE_OK; 1194} 1195 1196#ifndef SUSPEND_SLEEP 1197#define SUSPEND_SLEEP 0 1198#endif 1199#ifndef RESUME_SLEEP 1200#define RESUME_SLEEP 0 1201#endif 1202 1203/* 1204 * This function is only required if we need to do anything differently from 1205 * DoApmEvent() in common/xf86PM.c, including if we want to see events other 1206 * than suspend/resume. 1207 */ 1208static Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo) 1209{ 1210 SCRN_INFO_PTR(arg); 1211 intel_screen_private *intel = intel_get_screen_private(scrn); 1212 1213 switch (event) { 1214 case XF86_APM_SYS_SUSPEND: 1215 case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */ 1216 case XF86_APM_USER_SUSPEND: 1217 case XF86_APM_SYS_STANDBY: 1218 case XF86_APM_USER_STANDBY: 1219 if (!undo && !intel->suspended) { 1220 scrn->LeaveVT(VT_FUNC_ARGS(0)); 1221 intel->suspended = TRUE; 1222 sleep(SUSPEND_SLEEP); 1223 } else if (undo && intel->suspended) { 1224 sleep(RESUME_SLEEP); 1225 scrn->EnterVT(VT_FUNC_ARGS(0)); 1226 intel->suspended = FALSE; 1227 } 1228 break; 1229 case XF86_APM_STANDBY_RESUME: 1230 case XF86_APM_NORMAL_RESUME: 1231 case XF86_APM_CRITICAL_RESUME: 1232 if (intel->suspended) { 1233 sleep(RESUME_SLEEP); 1234 scrn->EnterVT(VT_FUNC_ARGS(0)); 1235 intel->suspended = FALSE; 1236 /* 1237 * Turn the screen saver off when resuming. This seems to be 1238 * needed to stop xscreensaver kicking in (when used). 1239 * 1240 * XXX DoApmEvent() should probably call this just like 1241 * xf86VTSwitch() does. Maybe do it here only in 4.2 1242 * compatibility mode. 1243 */ 1244 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 1245 } 1246 break; 1247 /* This is currently used for ACPI */ 1248 case XF86_APM_CAPABILITY_CHANGED: 1249 ErrorF("I830PMEvent: Capability change\n"); 1250 1251 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 1252 1253 break; 1254 default: 1255 ErrorF("I830PMEvent: received APM event %d\n", event); 1256 } 1257 return TRUE; 1258} 1259 1260Bool intel_init_scrn(ScrnInfoPtr scrn) 1261{ 1262 scrn->PreInit = I830PreInit; 1263 scrn->ScreenInit = I830ScreenInit; 1264 scrn->SwitchMode = I830SwitchMode; 1265 scrn->AdjustFrame = i830AdjustFrame; 1266 scrn->EnterVT = I830EnterVT; 1267 scrn->LeaveVT = I830LeaveVT; 1268 scrn->FreeScreen = I830FreeScreen; 1269 scrn->ValidMode = I830ValidMode; 1270 scrn->PMEvent = I830PMEvent; 1271 return TRUE; 1272} 1273