driver.c revision 35c4bbdf
1/* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * Copyright 2011 Dave Airlie 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * 27 * Original Author: Alan Hourihane <alanh@tungstengraphics.com> 28 * Rewrite: Dave Airlie <airlied@redhat.com> 29 * 30 */ 31 32#ifdef HAVE_DIX_CONFIG_H 33#include "dix-config.h" 34#endif 35 36#include <unistd.h> 37#include <fcntl.h> 38#include "xf86.h" 39#include "xf86_OSproc.h" 40#include "compiler.h" 41#include "xf86Pci.h" 42#include "mipointer.h" 43#include "micmap.h" 44#include <X11/extensions/randr.h> 45#include "fb.h" 46#include "edid.h" 47#include "xf86i2c.h" 48#include "xf86Crtc.h" 49#include "miscstruct.h" 50#include "dixstruct.h" 51#include "shadow.h" 52#include "xf86xv.h" 53#include <X11/extensions/Xv.h> 54#include <xorg-config.h> 55#ifdef XSERVER_PLATFORM_BUS 56#include "xf86platformBus.h" 57#endif 58#if XSERVER_LIBPCIACCESS 59#include <pciaccess.h> 60#endif 61 62#include "driver.h" 63#include "sh3224.h" 64 65static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y); 66static Bool CloseScreen(ScreenPtr pScreen); 67static Bool EnterVT(ScrnInfoPtr pScrn); 68static void Identify(int flags); 69static const OptionInfoRec *AvailableOptions(int chipid, int busid); 70static ModeStatus ValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, 71 Bool verbose, int flags); 72static void FreeScreen(ScrnInfoPtr pScrn); 73static void LeaveVT(ScrnInfoPtr pScrn); 74static Bool SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode); 75static Bool ScreenInit(ScreenPtr pScreen, int argc, char **argv); 76static Bool PreInit(ScrnInfoPtr pScrn, int flags); 77 78static Bool Probe(DriverPtr drv, int flags); 79static Bool ms_pci_probe(DriverPtr driver, 80 int entity_num, struct pci_device *device, 81 intptr_t match_data); 82static Bool ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data); 83 84#ifdef XSERVER_LIBPCIACCESS 85static const struct pci_id_match ms_device_match[] = { 86 { 87 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 88 0x00030000, 0x00ff0000, 0}, 89 90 {0, 0, 0}, 91}; 92#endif 93 94#ifndef XSERVER_PLATFORM_BUS 95struct xf86_platform_device; 96#endif 97 98#ifdef XSERVER_PLATFORM_BUS 99static Bool ms_platform_probe(DriverPtr driver, 100 int entity_num, int flags, 101 struct xf86_platform_device *device, 102 intptr_t match_data); 103#endif 104 105_X_EXPORT DriverRec modesetting = { 106 1, 107 "modesetting", 108 Identify, 109 Probe, 110 AvailableOptions, 111 NULL, 112 0, 113 ms_driver_func, 114 ms_device_match, 115 ms_pci_probe, 116#ifdef XSERVER_PLATFORM_BUS 117 ms_platform_probe, 118#endif 119}; 120 121static SymTabRec Chipsets[] = { 122 {0, "kms"}, 123 {-1, NULL} 124}; 125 126static const OptionInfoRec Options[] = { 127 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 128 {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE}, 129 {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, 130 {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 131 {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, 132 {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, 133 {-1, NULL, OPTV_NONE, {0}, FALSE} 134}; 135 136int ms_entity_index = -1; 137 138static MODULESETUPPROTO(Setup); 139 140static XF86ModuleVersionInfo VersRec = { 141 "modesetting", 142 MODULEVENDORSTRING, 143 MODINFOSTRING1, 144 MODINFOSTRING2, 145 XORG_VERSION_CURRENT, 146 XORG_VERSION_MAJOR, 147 XORG_VERSION_MINOR, 148 XORG_VERSION_PATCH, 149 ABI_CLASS_VIDEODRV, 150 ABI_VIDEODRV_VERSION, 151 MOD_CLASS_VIDEODRV, 152 {0, 0, 0, 0} 153}; 154 155_X_EXPORT XF86ModuleData modesettingModuleData = { &VersRec, Setup, NULL }; 156 157static void * 158Setup(void *module, void *opts, int *errmaj, int *errmin) 159{ 160 static Bool setupDone = 0; 161 162 /* This module should be loaded only once, but check to be sure. 163 */ 164 if (!setupDone) { 165 setupDone = 1; 166 xf86AddDriver(&modesetting, module, HaveDriverFuncs); 167 168 /* 169 * The return value must be non-NULL on success even though there 170 * is no TearDownProc. 171 */ 172 return (void *) 1; 173 } 174 else { 175 if (errmaj) 176 *errmaj = LDR_ONCEONLY; 177 return NULL; 178 } 179} 180 181static void 182Identify(int flags) 183{ 184 xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers", 185 Chipsets); 186} 187 188modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn) 189{ 190 DevUnion *pPriv; 191 modesettingPtr ms = modesettingPTR(scrn); 192 pPriv = xf86GetEntityPrivate(ms->pEnt->index, 193 ms_entity_index); 194 return pPriv->ptr; 195} 196 197static int 198open_hw(const char *dev) 199{ 200 int fd; 201 202 if (dev) 203 fd = open(dev, O_RDWR, 0); 204 else { 205 dev = getenv("KMSDEVICE"); 206 if ((NULL == dev) || ((fd = open(dev, O_RDWR, 0)) == -1)) { 207 dev = "/dev/dri/card0"; 208 fd = open(dev, O_RDWR, 0); 209 } 210 } 211 if (fd == -1) 212 xf86DrvMsg(-1, X_ERROR, "open %s: %s\n", dev, strerror(errno)); 213 214 return fd; 215} 216 217static int 218check_outputs(int fd) 219{ 220 drmModeResPtr res = drmModeGetResources(fd); 221 int ret; 222 223 if (!res) 224 return FALSE; 225 ret = res->count_connectors > 0; 226 drmModeFreeResources(res); 227 return ret; 228} 229 230static Bool 231probe_hw(const char *dev, struct xf86_platform_device *platform_dev) 232{ 233 int fd; 234 235#if XF86_PDEV_SERVER_FD 236 if (platform_dev && (platform_dev->flags & XF86_PDEV_SERVER_FD)) { 237 fd = xf86_platform_device_odev_attributes(platform_dev)->fd; 238 if (fd == -1) 239 return FALSE; 240 return check_outputs(fd); 241 } 242#endif 243 244 fd = open_hw(dev); 245 if (fd != -1) { 246 int ret = check_outputs(fd); 247 248 close(fd); 249 return ret; 250 } 251 return FALSE; 252} 253 254static char * 255ms_DRICreatePCIBusID(const struct pci_device *dev) 256{ 257 char *busID; 258 259 if (asprintf(&busID, "pci:%04x:%02x:%02x.%d", 260 dev->domain, dev->bus, dev->dev, dev->func) == -1) 261 return NULL; 262 263 return busID; 264} 265 266static Bool 267probe_hw_pci(const char *dev, struct pci_device *pdev) 268{ 269 int ret = FALSE, fd = open_hw(dev); 270 char *id, *devid; 271 drmSetVersion sv; 272 273 if (fd == -1) 274 return FALSE; 275 276 sv.drm_di_major = 1; 277 sv.drm_di_minor = 4; 278 sv.drm_dd_major = -1; 279 sv.drm_dd_minor = -1; 280 if (drmSetInterfaceVersion(fd, &sv)) { 281 close(fd); 282 return FALSE; 283 } 284 285 id = drmGetBusid(fd); 286 devid = ms_DRICreatePCIBusID(pdev); 287 288 if (id && devid && !strcmp(id, devid)) 289 ret = check_outputs(fd); 290 291 close(fd); 292 free(id); 293 free(devid); 294 return ret; 295} 296 297static const OptionInfoRec * 298AvailableOptions(int chipid, int busid) 299{ 300 return Options; 301} 302 303static Bool 304ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data) 305{ 306 xorgHWFlags *flag; 307 308 switch (op) { 309 case GET_REQUIRED_HW_INTERFACES: 310 flag = (CARD32 *) data; 311 (*flag) = 0; 312 return TRUE; 313 case SUPPORTS_SERVER_FDS: 314 return TRUE; 315 default: 316 return FALSE; 317 } 318} 319 320static void 321ms_setup_scrn_hooks(ScrnInfoPtr scrn) 322{ 323 scrn->driverVersion = 1; 324 scrn->driverName = "modesetting"; 325 scrn->name = "modeset"; 326 327 scrn->Probe = NULL; 328 scrn->PreInit = PreInit; 329 scrn->ScreenInit = ScreenInit; 330 scrn->SwitchMode = SwitchMode; 331 scrn->AdjustFrame = AdjustFrame; 332 scrn->EnterVT = EnterVT; 333 scrn->LeaveVT = LeaveVT; 334 scrn->FreeScreen = FreeScreen; 335 scrn->ValidMode = ValidMode; 336} 337 338static void 339ms_setup_entity(ScrnInfoPtr scrn, int entity_num) 340{ 341 DevUnion *pPriv; 342 343 xf86SetEntitySharable(entity_num); 344 345 if (ms_entity_index == -1) 346 ms_entity_index = xf86AllocateEntityPrivateIndex(); 347 348 pPriv = xf86GetEntityPrivate(entity_num, 349 ms_entity_index); 350 351 xf86SetEntityInstanceForScreen(scrn, entity_num, xf86GetNumEntityInstances(entity_num) - 1); 352 353 if (!pPriv->ptr) 354 pPriv->ptr = xnfcalloc(sizeof(modesettingEntRec), 1); 355} 356 357#if XSERVER_LIBPCIACCESS 358static Bool 359ms_pci_probe(DriverPtr driver, 360 int entity_num, struct pci_device *dev, intptr_t match_data) 361{ 362 ScrnInfoPtr scrn = NULL; 363 364 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, NULL, 365 NULL, NULL, NULL, NULL, NULL); 366 if (scrn) { 367 const char *devpath; 368 GDevPtr devSection = xf86GetDevFromEntity(scrn->entityList[0], 369 scrn->entityInstanceList[0]); 370 371 devpath = xf86FindOptionValue(devSection->options, "kmsdev"); 372 if (probe_hw_pci(devpath, dev)) { 373 ms_setup_scrn_hooks(scrn); 374 375 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 376 "claimed PCI slot %d@%d:%d:%d\n", 377 dev->bus, dev->domain, dev->dev, dev->func); 378 xf86DrvMsg(scrn->scrnIndex, X_INFO, 379 "using %s\n", devpath ? devpath : "default device"); 380 381 ms_setup_entity(scrn, entity_num); 382 } 383 else 384 scrn = NULL; 385 } 386 return scrn != NULL; 387} 388#endif 389 390#ifdef XSERVER_PLATFORM_BUS 391static Bool 392ms_platform_probe(DriverPtr driver, 393 int entity_num, int flags, struct xf86_platform_device *dev, 394 intptr_t match_data) 395{ 396 ScrnInfoPtr scrn = NULL; 397 const char *path = xf86_platform_device_odev_attributes(dev)->path; 398 int scr_flags = 0; 399 400 if (flags & PLATFORM_PROBE_GPU_SCREEN) 401 scr_flags = XF86_ALLOCATE_GPU_SCREEN; 402 403 if (probe_hw(path, dev)) { 404 scrn = xf86AllocateScreen(driver, scr_flags); 405 if (xf86IsEntitySharable(entity_num)) 406 xf86SetEntityShared(entity_num); 407 xf86AddEntityToScreen(scrn, entity_num); 408 409 ms_setup_scrn_hooks(scrn); 410 411 xf86DrvMsg(scrn->scrnIndex, X_INFO, 412 "using drv %s\n", path ? path : "default device"); 413 414 ms_setup_entity(scrn, entity_num); 415 } 416 417 return scrn != NULL; 418} 419#endif 420 421static Bool 422Probe(DriverPtr drv, int flags) 423{ 424 int i, numDevSections; 425 GDevPtr *devSections; 426 Bool foundScreen = FALSE; 427 const char *dev; 428 ScrnInfoPtr scrn = NULL; 429 430 /* For now, just bail out for PROBE_DETECT. */ 431 if (flags & PROBE_DETECT) 432 return FALSE; 433 434 /* 435 * Find the config file Device sections that match this 436 * driver, and return if there are none. 437 */ 438 if ((numDevSections = xf86MatchDevice("modesetting", &devSections)) <= 0) { 439 return FALSE; 440 } 441 442 for (i = 0; i < numDevSections; i++) { 443 int entity_num; 444 dev = xf86FindOptionValue(devSections[i]->options, "kmsdev"); 445 if (probe_hw(dev, NULL)) { 446 447 entity_num = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); 448 scrn = xf86ConfigFbEntity(scrn, 0, entity_num, NULL, NULL, NULL, NULL); 449 } 450 451 if (scrn) { 452 foundScreen = TRUE; 453 ms_setup_scrn_hooks(scrn); 454 scrn->Probe = Probe; 455 456 xf86DrvMsg(scrn->scrnIndex, X_INFO, 457 "using %s\n", dev ? dev : "default device"); 458 ms_setup_entity(scrn, entity_num); 459 } 460 } 461 462 free(devSections); 463 464 return foundScreen; 465} 466 467static Bool 468GetRec(ScrnInfoPtr pScrn) 469{ 470 if (pScrn->driverPrivate) 471 return TRUE; 472 473 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1); 474 475 return TRUE; 476} 477 478static int 479dispatch_dirty_region(ScrnInfoPtr scrn, 480 PixmapPtr pixmap, DamagePtr damage, int fb_id) 481{ 482 modesettingPtr ms = modesettingPTR(scrn); 483 RegionPtr dirty = DamageRegion(damage); 484 unsigned num_cliprects = REGION_NUM_RECTS(dirty); 485 int ret = 0; 486 487 if (num_cliprects) { 488 drmModeClip *clip = xallocarray(num_cliprects, sizeof(drmModeClip)); 489 BoxPtr rect = REGION_RECTS(dirty); 490 int i; 491 492 if (!clip) 493 return -ENOMEM; 494 495 /* XXX no need for copy? */ 496 for (i = 0; i < num_cliprects; i++, rect++) { 497 clip[i].x1 = rect->x1; 498 clip[i].y1 = rect->y1; 499 clip[i].x2 = rect->x2; 500 clip[i].y2 = rect->y2; 501 } 502 503 /* TODO query connector property to see if this is needed */ 504 ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects); 505 506 /* if we're swamping it with work, try one at a time */ 507 if (ret == -EINVAL) { 508 for (i = 0; i < num_cliprects; i++) { 509 if ((ret = drmModeDirtyFB(ms->fd, fb_id, &clip[i], 1)) < 0) 510 break; 511 } 512 } 513 514 free(clip); 515 DamageEmpty(damage); 516 } 517 return ret; 518} 519 520static void 521dispatch_dirty(ScreenPtr pScreen) 522{ 523 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 524 modesettingPtr ms = modesettingPTR(scrn); 525 PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); 526 int fb_id = ms->drmmode.fb_id; 527 int ret; 528 529 ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id); 530 if (ret == -EINVAL || ret == -ENOSYS) { 531 ms->dirty_enabled = FALSE; 532 DamageUnregister(ms->damage); 533 DamageDestroy(ms->damage); 534 ms->damage = NULL; 535 xf86DrvMsg(scrn->scrnIndex, X_INFO, 536 "Disabling kernel dirty updates, not required.\n"); 537 return; 538 } 539} 540 541static void 542dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc) 543{ 544 modesettingPtr ms = modesettingPTR(scrn); 545 PixmapPtr pixmap = crtc->randr_crtc->scanout_pixmap; 546 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap); 547 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 548 DamagePtr damage = drmmode_crtc->slave_damage; 549 int fb_id = ppriv->fb_id; 550 int ret; 551 552 ret = dispatch_dirty_region(scrn, pixmap, damage, fb_id); 553 if (ret) { 554 555 } 556} 557 558static void 559dispatch_slave_dirty(ScreenPtr pScreen) 560{ 561 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 562 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 563 int c; 564 565 for (c = 0; c < xf86_config->num_crtc; c++) { 566 xf86CrtcPtr crtc = xf86_config->crtc[c]; 567 568 if (!crtc->randr_crtc) 569 continue; 570 if (!crtc->randr_crtc->scanout_pixmap) 571 continue; 572 573 dispatch_dirty_crtc(scrn, crtc); 574 } 575} 576 577static void 578redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) 579{ 580 581 RegionRec pixregion; 582 583 PixmapRegionInit(&pixregion, dirty->slave_dst); 584 DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); 585 PixmapSyncDirtyHelper(dirty); 586 587 DamageRegionProcessPending(&dirty->slave_dst->drawable); 588 RegionUninit(&pixregion); 589} 590 591static void 592ms_dirty_update(ScreenPtr screen) 593{ 594 RegionPtr region; 595 PixmapDirtyUpdatePtr ent; 596 597 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 598 return; 599 600 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 601 region = DamageRegion(ent->damage); 602 if (RegionNotEmpty(region)) { 603 redisplay_dirty(screen, ent); 604 DamageEmpty(ent->damage); 605 } 606 } 607} 608 609static void 610msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask) 611{ 612 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 613 614 pScreen->BlockHandler = ms->BlockHandler; 615 pScreen->BlockHandler(pScreen, pTimeout, pReadmask); 616 ms->BlockHandler = pScreen->BlockHandler; 617 pScreen->BlockHandler = msBlockHandler; 618 if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode) 619 dispatch_slave_dirty(pScreen); 620 else if (ms->dirty_enabled) 621 dispatch_dirty(pScreen); 622 623 ms_dirty_update(pScreen); 624} 625 626static void 627FreeRec(ScrnInfoPtr pScrn) 628{ 629 modesettingPtr ms; 630 631 if (!pScrn) 632 return; 633 634 ms = modesettingPTR(pScrn); 635 if (!ms) 636 return; 637 638 if (ms->fd > 0) { 639 modesettingEntPtr ms_ent; 640 int ret; 641 642 ms_ent = ms_ent_priv(pScrn); 643 ms_ent->fd_ref--; 644 if (!ms_ent->fd_ref) { 645 if (ms->pEnt->location.type == BUS_PCI) 646 ret = drmClose(ms->fd); 647 else 648#ifdef XF86_PDEV_SERVER_FD 649 if (!(ms->pEnt->location.type == BUS_PLATFORM && 650 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))) 651#endif 652 ret = close(ms->fd); 653 (void) ret; 654 ms_ent->fd = 0; 655 } 656 } 657 pScrn->driverPrivate = NULL; 658 free(ms->drmmode.Options); 659 free(ms); 660 661} 662 663static void 664try_enable_glamor(ScrnInfoPtr pScrn) 665{ 666 modesettingPtr ms = modesettingPTR(pScrn); 667 const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options, 668 OPTION_ACCEL_METHOD); 669 Bool do_glamor = (!accel_method_str || 670 strcmp(accel_method_str, "glamor") == 0); 671 672 ms->drmmode.glamor = FALSE; 673 674#ifdef GLAMOR 675 if (ms->drmmode.force_24_32) { 676 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n"); 677 return; 678 } 679 680 if (!do_glamor) { 681 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n"); 682 return; 683 } 684 685 if (xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME)) { 686 if (glamor_egl_init(pScrn, ms->fd)) { 687 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n"); 688 ms->drmmode.glamor = TRUE; 689 } else { 690 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 691 "glamor initialization failed\n"); 692 } 693 } else { 694 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 695 "Failed to load glamor module.\n"); 696 } 697#else 698 if (do_glamor) { 699 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 700 "No glamor support in the X Server\n"); 701 } 702#endif 703} 704 705#ifndef DRM_CAP_CURSOR_WIDTH 706#define DRM_CAP_CURSOR_WIDTH 0x8 707#endif 708 709#ifndef DRM_CAP_CURSOR_HEIGHT 710#define DRM_CAP_CURSOR_HEIGHT 0x9 711#endif 712 713static Bool 714ms_get_drm_master_fd(ScrnInfoPtr pScrn) 715{ 716 EntityInfoPtr pEnt; 717 modesettingPtr ms; 718 modesettingEntPtr ms_ent; 719 char *BusID = NULL; 720 721 ms = modesettingPTR(pScrn); 722 ms_ent = ms_ent_priv(pScrn); 723 724 pEnt = ms->pEnt; 725 726 if (ms_ent->fd) { 727 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 728 " reusing fd for second head\n"); 729 ms->fd = ms_ent->fd; 730 ms_ent->fd_ref++; 731 return TRUE; 732 } 733 734#if XSERVER_PLATFORM_BUS 735 if (pEnt->location.type == BUS_PLATFORM) { 736#ifdef XF86_PDEV_SERVER_FD 737 if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD) 738 ms->fd = 739 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 740 fd; 741 else 742#endif 743 { 744 char *path = 745 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 746 path; 747 ms->fd = open_hw(path); 748 } 749 } 750 else 751#endif 752 if (pEnt->location.type == BUS_PCI) { 753 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); 754 if (ms->PciInfo) { 755 BusID = malloc(64); 756 sprintf(BusID, "PCI:%d:%d:%d", 757#if XSERVER_LIBPCIACCESS 758 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus), 759 ms->PciInfo->dev, ms->PciInfo->func 760#else 761 ((pciConfigPtr) ms->PciInfo->thisCard)->busnum, 762 ((pciConfigPtr) ms->PciInfo->thisCard)->devnum, 763 ((pciConfigPtr) ms->PciInfo->thisCard)->funcnum 764#endif 765 ); 766 } 767 ms->fd = drmOpen(NULL, BusID); 768 } 769 else { 770 const char *devicename; 771 devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev"); 772 ms->fd = open_hw(devicename); 773 } 774 if (ms->fd < 0) 775 return FALSE; 776 777 ms_ent->fd = ms->fd; 778 ms_ent->fd_ref = 1; 779 return TRUE; 780} 781 782static Bool 783PreInit(ScrnInfoPtr pScrn, int flags) 784{ 785 modesettingPtr ms; 786 rgb defaultWeight = { 0, 0, 0 }; 787 EntityInfoPtr pEnt; 788 uint64_t value = 0; 789 int ret; 790 int bppflags; 791 int defaultdepth, defaultbpp; 792 793 if (pScrn->numEntities != 1) 794 return FALSE; 795 796 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 797 798 if (flags & PROBE_DETECT) { 799 return FALSE; 800 } 801 802 /* Allocate driverPrivate */ 803 if (!GetRec(pScrn)) 804 return FALSE; 805 806 ms = modesettingPTR(pScrn); 807 ms->SaveGeneration = -1; 808 ms->pEnt = pEnt; 809 ms->drmmode.is_secondary = FALSE; 810 pScrn->displayWidth = 640; /* default it */ 811 812 if (xf86IsEntityShared(pScrn->entityList[0])) { 813 if (xf86IsPrimInitDone(pScrn->entityList[0])) 814 ms->drmmode.is_secondary = TRUE; 815 else 816 xf86SetPrimInitDone(pScrn->entityList[0]); 817 } 818 819 pScrn->monitor = pScrn->confScreen->monitor; 820 pScrn->progClock = TRUE; 821 pScrn->rgbBits = 8; 822 823 if (!ms_get_drm_master_fd(pScrn)) 824 return FALSE; 825 ms->drmmode.fd = ms->fd; 826 827 drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp); 828 if (defaultdepth == 24 && defaultbpp == 24) { 829 ms->drmmode.force_24_32 = TRUE; 830 ms->drmmode.kbpp = 24; 831 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 832 "Using 24bpp hw front buffer with 32bpp shadow\n"); 833 defaultbpp = 32; 834 } else { 835 ms->drmmode.kbpp = defaultbpp; 836 } 837 bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb; 838 839 if (!xf86SetDepthBpp 840 (pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags)) 841 return FALSE; 842 843 switch (pScrn->depth) { 844 case 15: 845 case 16: 846 case 24: 847 break; 848 default: 849 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 850 "Given depth (%d) is not supported by the driver\n", 851 pScrn->depth); 852 return FALSE; 853 } 854 xf86PrintDepthBpp(pScrn); 855 856 /* Process the options */ 857 xf86CollectOptions(pScrn, NULL); 858 if (!(ms->drmmode.Options = malloc(sizeof(Options)))) 859 return FALSE; 860 memcpy(ms->drmmode.Options, Options, sizeof(Options)); 861 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options); 862 863 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 864 return FALSE; 865 if (!xf86SetDefaultVisual(pScrn, -1)) 866 return FALSE; 867 868 if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) { 869 ms->drmmode.sw_cursor = TRUE; 870 } 871 872 ms->cursor_width = 64; 873 ms->cursor_height = 64; 874 ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value); 875 if (!ret) { 876 ms->cursor_width = value; 877 } 878 ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value); 879 if (!ret) { 880 ms->cursor_height = value; 881 } 882 883 try_enable_glamor(pScrn); 884 885 if (ms->drmmode.glamor) { 886 ms->drmmode.pageflip = 887 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE); 888 } else { 889 Bool prefer_shadow = TRUE; 890 891 if (ms->drmmode.force_24_32) { 892 prefer_shadow = TRUE; 893 ms->drmmode.shadow_enable = TRUE; 894 } else { 895 ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); 896 if (!ret) { 897 prefer_shadow = !!value; 898 } 899 900 ms->drmmode.shadow_enable = 901 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB, 902 prefer_shadow); 903 } 904 905 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 906 "ShadowFB: preferred %s, enabled %s\n", 907 prefer_shadow ? "YES" : "NO", 908 ms->drmmode.force_24_32 ? "FORCE" : 909 ms->drmmode.shadow_enable ? "YES" : "NO"); 910 911 ms->drmmode.pageflip = FALSE; 912 } 913 914 pScrn->capabilities = 0; 915#ifdef DRM_CAP_PRIME 916 ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value); 917 if (ret == 0) { 918 if (value & DRM_PRIME_CAP_IMPORT) { 919 pScrn->capabilities |= RR_Capability_SinkOutput; 920 if (ms->drmmode.glamor) 921 pScrn->capabilities |= RR_Capability_SinkOffload; 922 } 923#if GLAMOR_HAS_GBM_LINEAR 924 if (value & DRM_PRIME_CAP_EXPORT && ms->drmmode.glamor) 925 pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; 926#endif 927 } 928#endif 929 930 if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) { 931 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n"); 932 goto fail; 933 } 934 935 /* 936 * If the driver can do gamma correction, it should call xf86SetGamma() here. 937 */ 938 { 939 Gamma zeros = { 0.0, 0.0, 0.0 }; 940 941 if (!xf86SetGamma(pScrn, zeros)) { 942 return FALSE; 943 } 944 } 945 946 if (pScrn->modes == NULL) { 947 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 948 return FALSE; 949 } 950 951 pScrn->currentMode = pScrn->modes; 952 953 /* Set display resolution */ 954 xf86SetDpi(pScrn, 0, 0); 955 956 /* Load the required sub modules */ 957 if (!xf86LoadSubModule(pScrn, "fb")) { 958 return FALSE; 959 } 960 961 if (ms->drmmode.shadow_enable) { 962 if (!xf86LoadSubModule(pScrn, "shadow")) { 963 return FALSE; 964 } 965 } 966 967 return TRUE; 968 fail: 969 return FALSE; 970} 971 972static void * 973msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, 974 CARD32 *size, void *closure) 975{ 976 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 977 modesettingPtr ms = modesettingPTR(pScrn); 978 int stride; 979 980 stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8; 981 *size = stride; 982 983 return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset); 984} 985 986static void 987msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 988{ 989 shadowUpdatePacked(pScreen, pBuf); 990} 991 992static Bool 993CreateScreenResources(ScreenPtr pScreen) 994{ 995 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 996 modesettingPtr ms = modesettingPTR(pScrn); 997 PixmapPtr rootPixmap; 998 Bool ret; 999 void *pixels = NULL; 1000 int err; 1001 Bool use_ms_shadow = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32; 1002 1003 pScreen->CreateScreenResources = ms->createScreenResources; 1004 ret = pScreen->CreateScreenResources(pScreen); 1005 pScreen->CreateScreenResources = CreateScreenResources; 1006 1007 if (!drmmode_set_desired_modes(pScrn, &ms->drmmode)) 1008 return FALSE; 1009 1010 if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode)) 1011 return FALSE; 1012 1013 drmmode_uevent_init(pScrn, &ms->drmmode); 1014 1015 if (!ms->drmmode.sw_cursor) 1016 drmmode_map_cursor_bos(pScrn, &ms->drmmode); 1017 1018 if (!ms->drmmode.gbm) { 1019 pixels = drmmode_map_front_bo(&ms->drmmode); 1020 if (!pixels) 1021 return FALSE; 1022 } 1023 1024 rootPixmap = pScreen->GetScreenPixmap(pScreen); 1025 1026 if (ms->drmmode.shadow_enable) 1027 pixels = ms->drmmode.shadow_fb; 1028 1029 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) 1030 FatalError("Couldn't adjust screen pixmap\n"); 1031 1032 if (ms->drmmode.shadow_enable) { 1033 if (!shadowAdd(pScreen, rootPixmap, 1034 use_ms_shadow ? ms_shadowUpdate32to24 : msUpdatePacked, 1035 msShadowWindow, 0, 0)) 1036 return FALSE; 1037 } 1038 1039 err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0); 1040 1041 if (err != -EINVAL && err != -ENOSYS) { 1042 ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, 1043 pScreen, rootPixmap); 1044 1045 if (ms->damage) { 1046 DamageRegister(&rootPixmap->drawable, ms->damage); 1047 ms->dirty_enabled = TRUE; 1048 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); 1049 } 1050 else { 1051 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1052 "Failed to create screen damage record\n"); 1053 return FALSE; 1054 } 1055 } 1056 return ret; 1057} 1058 1059static Bool 1060msShadowInit(ScreenPtr pScreen) 1061{ 1062 if (!shadowSetup(pScreen)) { 1063 return FALSE; 1064 } 1065 return TRUE; 1066} 1067 1068static Bool 1069msSharePixmapBacking(PixmapPtr ppix, ScreenPtr screen, void **handle) 1070{ 1071#ifdef GLAMOR_HAS_GBM 1072 int ret; 1073 CARD16 stride; 1074 CARD32 size; 1075 ret = glamor_fd_from_pixmap(ppix->drawable.pScreen, ppix, &stride, &size); 1076 if (ret == -1) 1077 return FALSE; 1078 1079 *handle = (void *)(long)(ret); 1080 return TRUE; 1081#endif 1082 return FALSE; 1083} 1084 1085static Bool 1086msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) 1087{ 1088#ifdef GLAMOR 1089 ScreenPtr screen = ppix->drawable.pScreen; 1090 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1091 modesettingPtr ms = modesettingPTR(scrn); 1092 Bool ret; 1093 int ihandle = (int) (long) fd_handle; 1094 1095 if (ms->drmmode.reverse_prime_offload_mode) { 1096 ret = glamor_back_pixmap_from_fd(ppix, ihandle, 1097 ppix->drawable.width, 1098 ppix->drawable.height, 1099 ppix->devKind, ppix->drawable.depth, 1100 ppix->drawable.bitsPerPixel); 1101 } else { 1102 int size = ppix->devKind * ppix->drawable.height; 1103 ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size); 1104 } 1105 if (ret == FALSE) 1106 return ret; 1107 1108 return TRUE; 1109#else 1110 return FALSE; 1111#endif 1112} 1113 1114static Bool 1115SetMaster(ScrnInfoPtr pScrn) 1116{ 1117 modesettingPtr ms = modesettingPTR(pScrn); 1118 int ret; 1119 1120#ifdef XF86_PDEV_SERVER_FD 1121 if (ms->pEnt->location.type == BUS_PLATFORM && 1122 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) 1123 return TRUE; 1124#endif 1125 1126 ret = drmSetMaster(ms->fd); 1127 if (ret) 1128 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n", 1129 strerror(errno)); 1130 1131 return ret == 0; 1132} 1133 1134static Bool 1135ScreenInit(ScreenPtr pScreen, int argc, char **argv) 1136{ 1137 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1138 modesettingPtr ms = modesettingPTR(pScrn); 1139 VisualPtr visual; 1140 1141 pScrn->pScreen = pScreen; 1142 1143 if (!SetMaster(pScrn)) 1144 return FALSE; 1145 1146#ifdef GLAMOR_HAS_GBM 1147 if (ms->drmmode.glamor) 1148 ms->drmmode.gbm = glamor_egl_get_gbm_device(pScreen); 1149#endif 1150 1151 /* HW dependent - FIXME */ 1152 pScrn->displayWidth = pScrn->virtualX; 1153 if (!drmmode_create_initial_bos(pScrn, &ms->drmmode)) 1154 return FALSE; 1155 1156 if (ms->drmmode.shadow_enable) { 1157 ms->drmmode.shadow_fb = 1158 calloc(1, 1159 pScrn->displayWidth * pScrn->virtualY * 1160 ((pScrn->bitsPerPixel + 7) >> 3)); 1161 if (!ms->drmmode.shadow_fb) 1162 ms->drmmode.shadow_enable = FALSE; 1163 } 1164 1165 miClearVisualTypes(); 1166 1167 if (!miSetVisualTypes(pScrn->depth, 1168 miGetDefaultVisualMask(pScrn->depth), 1169 pScrn->rgbBits, pScrn->defaultVisual)) 1170 return FALSE; 1171 1172 if (!miSetPixmapDepths()) 1173 return FALSE; 1174 1175 if (!dixRegisterScreenSpecificPrivateKey 1176 (pScreen, &ms->drmmode.pixmapPrivateKeyRec, PRIVATE_PIXMAP, 1177 sizeof(msPixmapPrivRec))) { 1178 return FALSE; 1179 } 1180 1181 pScrn->memPhysBase = 0; 1182 pScrn->fbOffset = 0; 1183 1184 if (!fbScreenInit(pScreen, NULL, 1185 pScrn->virtualX, pScrn->virtualY, 1186 pScrn->xDpi, pScrn->yDpi, 1187 pScrn->displayWidth, pScrn->bitsPerPixel)) 1188 return FALSE; 1189 1190 if (pScrn->bitsPerPixel > 8) { 1191 /* Fixup RGB ordering */ 1192 visual = pScreen->visuals + pScreen->numVisuals; 1193 while (--visual >= pScreen->visuals) { 1194 if ((visual->class | DynamicClass) == DirectColor) { 1195 visual->offsetRed = pScrn->offset.red; 1196 visual->offsetGreen = pScrn->offset.green; 1197 visual->offsetBlue = pScrn->offset.blue; 1198 visual->redMask = pScrn->mask.red; 1199 visual->greenMask = pScrn->mask.green; 1200 visual->blueMask = pScrn->mask.blue; 1201 } 1202 } 1203 } 1204 1205 fbPictureInit(pScreen, NULL, 0); 1206 1207#ifdef GLAMOR 1208 if (ms->drmmode.glamor) { 1209 if (!glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN)) { 1210 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1211 "Failed to initialize glamor at ScreenInit() time.\n"); 1212 return FALSE; 1213 } 1214 } 1215#endif 1216 1217 if (ms->drmmode.shadow_enable && !msShadowInit(pScreen)) { 1218 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n"); 1219 return FALSE; 1220 } 1221 1222 ms->createScreenResources = pScreen->CreateScreenResources; 1223 pScreen->CreateScreenResources = CreateScreenResources; 1224 1225 xf86SetBlackWhitePixels(pScreen); 1226 1227 xf86SetBackingStore(pScreen); 1228 xf86SetSilkenMouse(pScreen); 1229 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1230 1231 /* Need to extend HWcursor support to handle mask interleave */ 1232 if (!ms->drmmode.sw_cursor) 1233 xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height, 1234 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 1235 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 1236 HARDWARE_CURSOR_ARGB); 1237 1238 /* Must force it before EnterVT, so we are in control of VT and 1239 * later memory should be bound when allocating, e.g rotate_mem */ 1240 pScrn->vtSema = TRUE; 1241 1242 pScreen->SaveScreen = xf86SaveScreen; 1243 ms->CloseScreen = pScreen->CloseScreen; 1244 pScreen->CloseScreen = CloseScreen; 1245 1246 ms->BlockHandler = pScreen->BlockHandler; 1247 pScreen->BlockHandler = msBlockHandler; 1248 1249 pScreen->SharePixmapBacking = msSharePixmapBacking; 1250 pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking; 1251 pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1252 pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1253 1254 if (!xf86CrtcScreenInit(pScreen)) 1255 return FALSE; 1256 1257 if (!miCreateDefColormap(pScreen)) 1258 return FALSE; 1259 1260 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1261 1262#ifdef GLAMOR 1263 if (ms->drmmode.glamor) { 1264 XF86VideoAdaptorPtr glamor_adaptor; 1265 1266 glamor_adaptor = glamor_xv_init(pScreen, 16); 1267 if (glamor_adaptor != NULL) 1268 xf86XVScreenInit(pScreen, &glamor_adaptor, 1); 1269 else 1270 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1271 "Failed to initialize XV support.\n"); 1272 } 1273#endif 1274 1275 if (serverGeneration == 1) 1276 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1277 1278 if (!ms_vblank_screen_init(pScreen)) { 1279 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1280 "Failed to initialize vblank support.\n"); 1281 return FALSE; 1282 } 1283 1284#ifdef GLAMOR 1285 if (ms->drmmode.glamor) { 1286 if (!ms_dri2_screen_init(pScreen)) { 1287 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1288 "Failed to initialize the DRI2 extension.\n"); 1289 } 1290 1291 if (!ms_present_screen_init(pScreen)) { 1292 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1293 "Failed to initialize the Present extension.\n"); 1294 } 1295 /* enable reverse prime if we are a GPU screen, and accelerated */ 1296 if (pScreen->isGPU) 1297 ms->drmmode.reverse_prime_offload_mode = TRUE; 1298 } 1299#endif 1300 1301 return EnterVT(pScrn); 1302} 1303 1304static void 1305AdjustFrame(ScrnInfoPtr pScrn, int x, int y) 1306{ 1307 modesettingPtr ms = modesettingPTR(pScrn); 1308 1309 drmmode_adjust_frame(pScrn, &ms->drmmode, x, y); 1310} 1311 1312static void 1313FreeScreen(ScrnInfoPtr pScrn) 1314{ 1315 FreeRec(pScrn); 1316} 1317 1318static void 1319LeaveVT(ScrnInfoPtr pScrn) 1320{ 1321 modesettingPtr ms = modesettingPTR(pScrn); 1322 1323 xf86_hide_cursors(pScrn); 1324 1325 pScrn->vtSema = FALSE; 1326 1327#ifdef XF86_PDEV_SERVER_FD 1328 if (ms->pEnt->location.type == BUS_PLATFORM && 1329 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) 1330 return; 1331#endif 1332 1333 drmDropMaster(ms->fd); 1334} 1335 1336/* 1337 * This gets called when gaining control of the VT, and from ScreenInit(). 1338 */ 1339static Bool 1340EnterVT(ScrnInfoPtr pScrn) 1341{ 1342 modesettingPtr ms = modesettingPTR(pScrn); 1343 1344 pScrn->vtSema = TRUE; 1345 1346 SetMaster(pScrn); 1347 1348 if (!drmmode_set_desired_modes(pScrn, &ms->drmmode)) 1349 return FALSE; 1350 1351 return TRUE; 1352} 1353 1354static Bool 1355SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 1356{ 1357 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1358} 1359 1360static Bool 1361CloseScreen(ScreenPtr pScreen) 1362{ 1363 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1364 modesettingPtr ms = modesettingPTR(pScrn); 1365 modesettingEntPtr ms_ent = ms_ent_priv(pScrn); 1366 1367 /* Clear mask of assigned crtc's in this generation */ 1368 ms_ent->assigned_crtcs = 0; 1369 1370#ifdef GLAMOR 1371 if (ms->drmmode.glamor) { 1372 ms_dri2_close_screen(pScreen); 1373 } 1374#endif 1375 1376 ms_vblank_close_screen(pScreen); 1377 1378 if (ms->damage) { 1379 DamageUnregister(ms->damage); 1380 DamageDestroy(ms->damage); 1381 ms->damage = NULL; 1382 } 1383 1384 if (ms->drmmode.shadow_enable) { 1385 shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); 1386 free(ms->drmmode.shadow_fb); 1387 ms->drmmode.shadow_fb = NULL; 1388 } 1389 drmmode_uevent_fini(pScrn, &ms->drmmode); 1390 1391 drmmode_free_bos(pScrn, &ms->drmmode); 1392 1393 if (pScrn->vtSema) { 1394 LeaveVT(pScrn); 1395 } 1396 1397 pScreen->CreateScreenResources = ms->createScreenResources; 1398 pScreen->BlockHandler = ms->BlockHandler; 1399 1400 pScrn->vtSema = FALSE; 1401 pScreen->CloseScreen = ms->CloseScreen; 1402 return (*pScreen->CloseScreen) (pScreen); 1403} 1404 1405static ModeStatus 1406ValidMode(ScrnInfoPtr arg, DisplayModePtr mode, Bool verbose, int flags) 1407{ 1408 return MODE_OK; 1409} 1410