1fda9279dSmrg/* 2fda9279dSmrg * Copyright 1996-1997 David J. McKay 3fda9279dSmrg * 4fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5fda9279dSmrg * copy of this software and associated documentation files (the "Software"), 6fda9279dSmrg * to deal in the Software without restriction, including without limitation 7fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9fda9279dSmrg * Software is furnished to do so, subject to the following conditions: 10fda9279dSmrg * 11fda9279dSmrg * The above copyright notice and this permission notice shall be included in 12fda9279dSmrg * all copies or substantial portions of the Software. 13fda9279dSmrg * 14fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20fda9279dSmrg * SOFTWARE. 21fda9279dSmrg */ 22fda9279dSmrg 23fda9279dSmrg#include <stdio.h> 2416ee1e9aSmrg#include <fcntl.h> 25fda9279dSmrg 26fda9279dSmrg#include "nv_include.h" 27fda9279dSmrg 28fda9279dSmrg#include "xorg-server.h" 29fda9279dSmrg#include "xf86drm.h" 30fda9279dSmrg#include "xf86drmMode.h" 31fda9279dSmrg#include "nouveau_drm.h" 32fda9279dSmrg#ifdef DRI2 33fda9279dSmrg#include "dri2.h" 34fda9279dSmrg#endif 35fda9279dSmrg 36fda9279dSmrg#include "nouveau_copy.h" 37fda9279dSmrg#include "nouveau_present.h" 38fda9279dSmrg#include "nouveau_sync.h" 39fda9279dSmrg 40fda9279dSmrg/* 41fda9279dSmrg * Forward definitions for the functions that make up the driver. 42fda9279dSmrg */ 43fda9279dSmrg/* Mandatory functions */ 44fda9279dSmrgstatic const OptionInfoRec * NVAvailableOptions(int chipid, int busid); 45fda9279dSmrgstatic void NVIdentify(int flags); 46fda9279dSmrgstatic Bool NVPreInit(ScrnInfoPtr pScrn, int flags); 47fda9279dSmrgstatic Bool NVScreenInit(SCREEN_INIT_ARGS_DECL); 48fda9279dSmrgstatic Bool NVEnterVT(VT_FUNC_ARGS_DECL); 49fda9279dSmrgstatic void NVLeaveVT(VT_FUNC_ARGS_DECL); 50fda9279dSmrgstatic Bool NVCloseScreen(CLOSE_SCREEN_ARGS_DECL); 51fda9279dSmrgstatic Bool NVSaveScreen(ScreenPtr pScreen, int mode); 52fda9279dSmrgstatic void NVCloseDRM(ScrnInfoPtr); 53fda9279dSmrg 54fda9279dSmrg/* Optional functions */ 55fda9279dSmrgstatic Bool NVDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, 56fda9279dSmrg void *data); 57fda9279dSmrgstatic Bool NVSwitchMode(SWITCH_MODE_ARGS_DECL); 58fda9279dSmrgstatic void NVAdjustFrame(ADJUST_FRAME_ARGS_DECL); 59fda9279dSmrgstatic void NVFreeScreen(FREE_SCREEN_ARGS_DECL); 60fda9279dSmrg 61fda9279dSmrg/* Internally used functions */ 62fda9279dSmrg 63fda9279dSmrgstatic Bool NVMapMem(ScrnInfoPtr pScrn); 64fda9279dSmrgstatic Bool NVUnmapMem(ScrnInfoPtr pScrn); 65fda9279dSmrg 66fda9279dSmrg#define NOUVEAU_PCI_DEVICE(_vendor_id, _device_id) \ 67fda9279dSmrg { (_vendor_id), (_device_id), PCI_MATCH_ANY, PCI_MATCH_ANY, \ 68fda9279dSmrg 0x00030000, 0x00ff0000, 0 } 69fda9279dSmrg 70fda9279dSmrgstatic const struct pci_id_match nouveau_device_match[] = { 71fda9279dSmrg NOUVEAU_PCI_DEVICE(0x12d2, PCI_MATCH_ANY), 72fda9279dSmrg NOUVEAU_PCI_DEVICE(0x10de, PCI_MATCH_ANY), 73fda9279dSmrg { 0, 0, 0 }, 74fda9279dSmrg}; 75fda9279dSmrg 76fda9279dSmrgstatic Bool NVPciProbe ( DriverPtr drv, 77fda9279dSmrg int entity_num, 78fda9279dSmrg struct pci_device *dev, 79fda9279dSmrg intptr_t match_data ); 80fda9279dSmrg 81fda9279dSmrg#ifdef XSERVER_PLATFORM_BUS 82fda9279dSmrgstatic Bool NVPlatformProbe(DriverPtr driver, 83fda9279dSmrg int entity_num, int flags, 84fda9279dSmrg struct xf86_platform_device *dev, 85fda9279dSmrg intptr_t dev_match_data); 86fda9279dSmrg#endif 87fda9279dSmrg 88fda9279dSmrg_X_EXPORT int NVEntityIndex = -1; 89fda9279dSmrg 90fda9279dSmrgstatic int getNVEntityIndex(void) 91fda9279dSmrg{ 92fda9279dSmrg return NVEntityIndex; 93fda9279dSmrg} 94fda9279dSmrg 95fda9279dSmrg/* 96fda9279dSmrg * This contains the functions needed by the server after loading the 97fda9279dSmrg * driver module. It must be supplied, and gets added the driver list by 98fda9279dSmrg * the Module Setup funtion in the dynamic case. In the static case a 99fda9279dSmrg * reference to this is compiled in, and this requires that the name of 100fda9279dSmrg * this DriverRec be an upper-case version of the driver name. 101fda9279dSmrg */ 102fda9279dSmrg 103fda9279dSmrg_X_EXPORT DriverRec NV = { 104fda9279dSmrg NV_VERSION, 105fda9279dSmrg NV_DRIVER_NAME, 106fda9279dSmrg NVIdentify, 107fda9279dSmrg NULL, 108fda9279dSmrg NVAvailableOptions, 109fda9279dSmrg NULL, 110fda9279dSmrg 0, 111fda9279dSmrg NVDriverFunc, 112fda9279dSmrg nouveau_device_match, 113fda9279dSmrg NVPciProbe, 114fda9279dSmrg#ifdef XSERVER_PLATFORM_BUS 115fda9279dSmrg NVPlatformProbe, 116fda9279dSmrg#endif 117fda9279dSmrg}; 118fda9279dSmrg 119fda9279dSmrgstruct NvFamily 120fda9279dSmrg{ 121fda9279dSmrg char *name; 122fda9279dSmrg char *chipset; 123fda9279dSmrg}; 124fda9279dSmrg 125fda9279dSmrgstatic struct NvFamily NVKnownFamilies[] = 126fda9279dSmrg{ 127fda9279dSmrg { "RIVA TNT", "NV04" }, 128fda9279dSmrg { "RIVA TNT2", "NV05" }, 129fda9279dSmrg { "GeForce 256", "NV10" }, 130fda9279dSmrg { "GeForce 2", "NV11, NV15" }, 131fda9279dSmrg { "GeForce 4MX", "NV17, NV18" }, 132fda9279dSmrg { "GeForce 3", "NV20" }, 133fda9279dSmrg { "GeForce 4Ti", "NV25, NV28" }, 134fda9279dSmrg { "GeForce FX", "NV3x" }, 135fda9279dSmrg { "GeForce 6", "NV4x" }, 136fda9279dSmrg { "GeForce 7", "G7x" }, 137fda9279dSmrg { "GeForce 8", "G8x" }, 13822d74663Smrg { "GeForce 9", "G9x" }, 13922d74663Smrg { "GeForce GTX 2xx/3xx", "GT2xx" }, 14022d74663Smrg { "GeForce GTX 4xx/5xx", "GFxxx" }, 14122d74663Smrg { "GeForce GTX 6xx/7xx", "GKxxx" }, 14222d74663Smrg { "GeForce GTX 9xx", "GMxxx" }, 14322d74663Smrg { "GeForce GTX 10xx", "GPxxx" }, 144fda9279dSmrg { NULL, NULL} 145fda9279dSmrg}; 146fda9279dSmrg 147fda9279dSmrgstatic MODULESETUPPROTO(nouveauSetup); 148fda9279dSmrg 149fda9279dSmrgstatic XF86ModuleVersionInfo nouveauVersRec = 150fda9279dSmrg{ 151fda9279dSmrg "nouveau", 152fda9279dSmrg MODULEVENDORSTRING, 153fda9279dSmrg MODINFOSTRING1, 154fda9279dSmrg MODINFOSTRING2, 155fda9279dSmrg XORG_VERSION_CURRENT, 15622d74663Smrg PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 157fda9279dSmrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 158fda9279dSmrg ABI_VIDEODRV_VERSION, 159fda9279dSmrg MOD_CLASS_VIDEODRV, 160fda9279dSmrg {0,0,0,0} 161fda9279dSmrg}; 162fda9279dSmrg 163fda9279dSmrg_X_EXPORT XF86ModuleData nouveauModuleData = { &nouveauVersRec, nouveauSetup, NULL }; 164fda9279dSmrg 165fda9279dSmrgstatic pointer 166fda9279dSmrgnouveauSetup(pointer module, pointer opts, int *errmaj, int *errmin) 167fda9279dSmrg{ 168fda9279dSmrg static Bool setupDone = FALSE; 169fda9279dSmrg 170fda9279dSmrg /* This module should be loaded only once, but check to be sure. */ 171fda9279dSmrg 172fda9279dSmrg if (!setupDone) { 173fda9279dSmrg setupDone = TRUE; 174fda9279dSmrg /* The 1 here is needed to turn off a backwards compatibility mode */ 175fda9279dSmrg /* Otherwise NVPciProbe() is not called */ 176fda9279dSmrg xf86AddDriver(&NV, module, 1); 177fda9279dSmrg 178fda9279dSmrg /* 179fda9279dSmrg * The return value must be non-NULL on success even though there 180fda9279dSmrg * is no TearDownProc. 181fda9279dSmrg */ 182fda9279dSmrg return (pointer)1; 183fda9279dSmrg } else { 184fda9279dSmrg if (errmaj) *errmaj = LDR_ONCEONLY; 185fda9279dSmrg return NULL; 186fda9279dSmrg } 187fda9279dSmrg} 188fda9279dSmrg 189fda9279dSmrgstatic const OptionInfoRec * 190fda9279dSmrgNVAvailableOptions(int chipid, int busid) 191fda9279dSmrg{ 192fda9279dSmrg return NVOptions; 193fda9279dSmrg} 194fda9279dSmrg 195fda9279dSmrg/* Mandatory */ 196fda9279dSmrgstatic void 197fda9279dSmrgNVIdentify(int flags) 198fda9279dSmrg{ 199fda9279dSmrg struct NvFamily *family; 200fda9279dSmrg size_t maxLen=0; 201fda9279dSmrg 202fda9279dSmrg xf86DrvMsg(0, X_INFO, NV_NAME " driver " NV_DRIVER_DATE "\n"); 203fda9279dSmrg xf86DrvMsg(0, X_INFO, NV_NAME " driver for NVIDIA chipset families :\n"); 204fda9279dSmrg 205fda9279dSmrg /* maximum length for alignment */ 206fda9279dSmrg family = NVKnownFamilies; 207fda9279dSmrg while(family->name && family->chipset) 208fda9279dSmrg { 209fda9279dSmrg maxLen = max(maxLen, strlen(family->name)); 210fda9279dSmrg family++; 211fda9279dSmrg } 212fda9279dSmrg 213fda9279dSmrg /* display */ 214fda9279dSmrg family = NVKnownFamilies; 215fda9279dSmrg while(family->name && family->chipset) 216fda9279dSmrg { 217fda9279dSmrg size_t len = strlen(family->name); 218fda9279dSmrg xf86ErrorF("\t%s", family->name); 219fda9279dSmrg while(len<maxLen+1) 220fda9279dSmrg { 221fda9279dSmrg xf86ErrorF(" "); 222fda9279dSmrg len++; 223fda9279dSmrg } 224fda9279dSmrg xf86ErrorF("(%s)\n", family->chipset); 225fda9279dSmrg family++; 226fda9279dSmrg } 227fda9279dSmrg} 228fda9279dSmrg 229fda9279dSmrgstatic Bool 230fda9279dSmrgNVDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data) 231fda9279dSmrg{ 232fda9279dSmrg xorgHWFlags *flag; 233fda9279dSmrg 234fda9279dSmrg switch (op) { 235fda9279dSmrg case GET_REQUIRED_HW_INTERFACES: 236fda9279dSmrg flag = (CARD32 *)data; 237fda9279dSmrg (*flag) = 0; 238fda9279dSmrg return TRUE; 239fda9279dSmrg case SUPPORTS_SERVER_FDS: 240fda9279dSmrg return TRUE; 241fda9279dSmrg default: 242fda9279dSmrg return FALSE; 243fda9279dSmrg } 244fda9279dSmrg} 245fda9279dSmrg 246fda9279dSmrgstatic void 247fda9279dSmrgNVInitScrn(ScrnInfoPtr pScrn, struct xf86_platform_device *platform_dev, 248fda9279dSmrg int entity_num) 249fda9279dSmrg{ 250fda9279dSmrg DevUnion *pPriv; 251fda9279dSmrg NVEntPtr pNVEnt; 252fda9279dSmrg 253fda9279dSmrg pScrn->driverVersion = NV_VERSION; 254fda9279dSmrg pScrn->driverName = NV_DRIVER_NAME; 255fda9279dSmrg pScrn->name = NV_NAME; 256fda9279dSmrg 257fda9279dSmrg pScrn->Probe = NULL; 258fda9279dSmrg pScrn->PreInit = NVPreInit; 259fda9279dSmrg pScrn->ScreenInit = NVScreenInit; 260fda9279dSmrg pScrn->SwitchMode = NVSwitchMode; 261fda9279dSmrg pScrn->AdjustFrame = NVAdjustFrame; 262fda9279dSmrg pScrn->EnterVT = NVEnterVT; 263fda9279dSmrg pScrn->LeaveVT = NVLeaveVT; 264fda9279dSmrg pScrn->FreeScreen = NVFreeScreen; 265fda9279dSmrg 266fda9279dSmrg xf86SetEntitySharable(entity_num); 267fda9279dSmrg if (NVEntityIndex == -1) 268fda9279dSmrg NVEntityIndex = xf86AllocateEntityPrivateIndex(); 269fda9279dSmrg 270fda9279dSmrg pPriv = xf86GetEntityPrivate(entity_num, 271fda9279dSmrg NVEntityIndex); 272fda9279dSmrg if (!pPriv->ptr) { 273a5560a61Smrg pPriv->ptr = XNFcallocarray(sizeof(NVEntRec), 1); 274fda9279dSmrg pNVEnt = pPriv->ptr; 275fda9279dSmrg pNVEnt->platform_dev = platform_dev; 276fda9279dSmrg } 277fda9279dSmrg else 278fda9279dSmrg pNVEnt = pPriv->ptr; 279fda9279dSmrg 280fda9279dSmrg /* Reset settings which must not persist across server regeneration */ 281fda9279dSmrg if (pNVEnt->reinitGeneration != serverGeneration) { 282fda9279dSmrg pNVEnt->reinitGeneration = serverGeneration; 283fda9279dSmrg /* Clear mask of assigned crtc's in this generation to "none" */ 284fda9279dSmrg pNVEnt->assigned_crtcs = 0; 285fda9279dSmrg } 286fda9279dSmrg 287fda9279dSmrg xf86SetEntityInstanceForScreen(pScrn, entity_num, 288fda9279dSmrg xf86GetNumEntityInstances(entity_num) - 1); 289fda9279dSmrg} 290fda9279dSmrg 291fda9279dSmrgstatic struct nouveau_device * 292fda9279dSmrgNVOpenNouveauDevice(struct pci_device *pci_dev, 293fda9279dSmrg struct xf86_platform_device *platform_dev, int scrnIndex, Bool probe) 294fda9279dSmrg{ 295fda9279dSmrg struct nouveau_device *dev = NULL; 296fda9279dSmrg char *busid; 297fda9279dSmrg int ret, fd = -1; 298fda9279dSmrg 29916ee1e9aSmrg#ifdef ODEV_ATTRIB_PATH 30016ee1e9aSmrg if (platform_dev) 30116ee1e9aSmrg busid = NULL; 30216ee1e9aSmrg else 30316ee1e9aSmrg#endif 30416ee1e9aSmrg { 30516ee1e9aSmrg XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d", 30616ee1e9aSmrg pci_dev->domain, pci_dev->bus, 30716ee1e9aSmrg pci_dev->dev, pci_dev->func); 308fda9279dSmrg } 309fda9279dSmrg 310fda9279dSmrg#if defined(ODEV_ATTRIB_FD) 311fda9279dSmrg if (platform_dev) 312fda9279dSmrg fd = xf86_get_platform_device_int_attrib(platform_dev, 313fda9279dSmrg ODEV_ATTRIB_FD, -1); 314fda9279dSmrg#endif 315fda9279dSmrg if (fd != -1) 316fda9279dSmrg ret = nouveau_device_wrap(fd, 0, &dev); 31716ee1e9aSmrg#ifdef ODEV_ATTRIB_PATH 31816ee1e9aSmrg else if (platform_dev) { 31916ee1e9aSmrg const char *path; 32016ee1e9aSmrg 32116ee1e9aSmrg path = xf86_get_platform_device_attrib(platform_dev, 32216ee1e9aSmrg ODEV_ATTRIB_PATH); 32316ee1e9aSmrg 32416ee1e9aSmrg fd = open(path, O_RDWR | O_CLOEXEC); 32516ee1e9aSmrg ret = nouveau_device_wrap(fd, 1, &dev); 32616ee1e9aSmrg if (ret) 32716ee1e9aSmrg close(fd); 32816ee1e9aSmrg } 32916ee1e9aSmrg#endif 330fda9279dSmrg else 331fda9279dSmrg ret = nouveau_device_open(busid, &dev); 332fda9279dSmrg if (ret) 333fda9279dSmrg xf86DrvMsg(scrnIndex, X_ERROR, 334fda9279dSmrg "[drm] Failed to open DRM device for %s: %d\n", 335fda9279dSmrg busid, ret); 336fda9279dSmrg 337fda9279dSmrg free(busid); 338fda9279dSmrg return dev; 339fda9279dSmrg} 340fda9279dSmrg 341fda9279dSmrgstatic Bool 342fda9279dSmrgNVHasKMS(struct pci_device *pci_dev, struct xf86_platform_device *platform_dev) 343fda9279dSmrg{ 344fda9279dSmrg struct nouveau_device *dev = NULL; 345fda9279dSmrg drmVersion *version; 346fda9279dSmrg int chipset; 347fda9279dSmrg 348fda9279dSmrg dev = NVOpenNouveauDevice(pci_dev, platform_dev, -1, TRUE); 349fda9279dSmrg if (!dev) 350fda9279dSmrg return FALSE; 351fda9279dSmrg 352fda9279dSmrg /* Check the version reported by the kernel module. In theory we 353fda9279dSmrg * shouldn't have to do this, as libdrm_nouveau will do its own checks. 354fda9279dSmrg * But, we're currently using the kernel patchlevel to also version 355fda9279dSmrg * the DRI interface. 356fda9279dSmrg */ 357fda9279dSmrg version = drmGetVersion(dev->fd); 358fda9279dSmrg xf86DrvMsg(-1, X_INFO, "[drm] nouveau interface version: %d.%d.%d\n", 359fda9279dSmrg version->version_major, version->version_minor, 360fda9279dSmrg version->version_patchlevel); 361fda9279dSmrg drmFree(version); 362fda9279dSmrg 363fda9279dSmrg chipset = dev->chipset; 364fda9279dSmrg nouveau_device_del(&dev); 365fda9279dSmrg 366fda9279dSmrg 367fda9279dSmrg switch (chipset & ~0xf) { 368fda9279dSmrg case 0x00: 369fda9279dSmrg case 0x10: 370fda9279dSmrg case 0x20: 371fda9279dSmrg case 0x30: 372fda9279dSmrg case 0x40: 373fda9279dSmrg case 0x60: 374fda9279dSmrg case 0x50: 375fda9279dSmrg case 0x80: 376fda9279dSmrg case 0x90: 377fda9279dSmrg case 0xa0: 378fda9279dSmrg case 0xc0: 379fda9279dSmrg case 0xd0: 380fda9279dSmrg case 0xe0: 381fda9279dSmrg case 0xf0: 382fda9279dSmrg case 0x100: 383cd34e0e1Smrg case 0x110: 384cd34e0e1Smrg case 0x120: 385cd34e0e1Smrg case 0x130: 386fda9279dSmrg break; 387fda9279dSmrg default: 38816ee1e9aSmrg xf86DrvMsg(-1, X_ERROR, "Unknown chipset: NV%02X\n", chipset); 389fda9279dSmrg return FALSE; 390fda9279dSmrg } 391fda9279dSmrg return TRUE; 392fda9279dSmrg} 393fda9279dSmrg 394fda9279dSmrgstatic Bool 395fda9279dSmrgNVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev, 396fda9279dSmrg intptr_t match_data) 397fda9279dSmrg{ 398fda9279dSmrg PciChipsets NVChipsets[] = { 399fda9279dSmrg { pci_dev->device_id, 400fda9279dSmrg (pci_dev->vendor_id << 16) | pci_dev->device_id, NULL }, 401fda9279dSmrg { -1, -1, NULL } 402fda9279dSmrg }; 403fda9279dSmrg ScrnInfoPtr pScrn = NULL; 404fda9279dSmrg 405fda9279dSmrg if (!NVHasKMS(pci_dev, NULL)) 406fda9279dSmrg return FALSE; 407fda9279dSmrg 408fda9279dSmrg pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NVChipsets, 409fda9279dSmrg NULL, NULL, NULL, NULL, NULL); 410fda9279dSmrg if (!pScrn) 411fda9279dSmrg return FALSE; 412fda9279dSmrg 413fda9279dSmrg NVInitScrn(pScrn, NULL, entity_num); 414fda9279dSmrg 415fda9279dSmrg return TRUE; 416fda9279dSmrg} 417fda9279dSmrg 418fda9279dSmrg#ifdef XSERVER_PLATFORM_BUS 419fda9279dSmrgstatic Bool 420fda9279dSmrgNVPlatformProbe(DriverPtr driver, 421fda9279dSmrg int entity_num, int flags, struct xf86_platform_device *dev, intptr_t dev_match_data) 422fda9279dSmrg{ 423fda9279dSmrg ScrnInfoPtr scrn = NULL; 424fda9279dSmrg uint32_t scr_flags = 0; 425fda9279dSmrg 426fda9279dSmrg if (!NVHasKMS(dev->pdev, dev)) 427fda9279dSmrg return FALSE; 428fda9279dSmrg 429fda9279dSmrg if (flags & PLATFORM_PROBE_GPU_SCREEN) 430fda9279dSmrg scr_flags = XF86_ALLOCATE_GPU_SCREEN; 431fda9279dSmrg 432fda9279dSmrg scrn = xf86AllocateScreen(driver, scr_flags); 433fda9279dSmrg if (!scrn) 434fda9279dSmrg return FALSE; 435fda9279dSmrg 436fda9279dSmrg if (xf86IsEntitySharable(entity_num)) 437fda9279dSmrg xf86SetEntityShared(entity_num); 438fda9279dSmrg xf86AddEntityToScreen(scrn, entity_num); 439fda9279dSmrg 440fda9279dSmrg NVInitScrn(scrn, dev, entity_num); 441fda9279dSmrg 442fda9279dSmrg return TRUE; 443fda9279dSmrg} 444fda9279dSmrg#endif 445fda9279dSmrg 446fda9279dSmrg#define MAX_CHIPS MAXSCREENS 447fda9279dSmrg 448fda9279dSmrgBool 449fda9279dSmrgNVSwitchMode(SWITCH_MODE_ARGS_DECL) 450fda9279dSmrg{ 451fda9279dSmrg SCRN_INFO_PTR(arg); 452fda9279dSmrg 453fda9279dSmrg return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 454fda9279dSmrg} 455fda9279dSmrg 456fda9279dSmrg/* 457fda9279dSmrg * This function is used to initialize the Start Address - the first 458fda9279dSmrg * displayed location in the video memory. 459fda9279dSmrg */ 460fda9279dSmrg/* Usually mandatory */ 461fda9279dSmrgvoid 462fda9279dSmrgNVAdjustFrame(ADJUST_FRAME_ARGS_DECL) 463fda9279dSmrg{ 464fda9279dSmrg SCRN_INFO_PTR(arg); 465fda9279dSmrg drmmode_adjust_frame(pScrn, x, y); 466fda9279dSmrg} 467fda9279dSmrg 468fda9279dSmrg/* 469fda9279dSmrg * This is called when VT switching back to the X server. Its job is 470fda9279dSmrg * to reinitialise the video mode. 471fda9279dSmrg */ 472fda9279dSmrg 473fda9279dSmrg/* Mandatory */ 474fda9279dSmrgstatic Bool 475fda9279dSmrgNVEnterVT(VT_FUNC_ARGS_DECL) 476fda9279dSmrg{ 477fda9279dSmrg SCRN_INFO_PTR(arg); 478fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 479fda9279dSmrg#ifdef XF86_PDEV_SERVER_FD 480fda9279dSmrg NVEntPtr pNVEnt = NVEntPriv(pScrn); 481fda9279dSmrg#endif 482fda9279dSmrg int ret; 483fda9279dSmrg 484fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVEnterVT is called.\n"); 485fda9279dSmrg 486fda9279dSmrg#ifdef XF86_PDEV_SERVER_FD 487fda9279dSmrg if (!(pNVEnt->platform_dev && 488fda9279dSmrg (pNVEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))) 489fda9279dSmrg#endif 490fda9279dSmrg { 491fda9279dSmrg ret = drmSetMaster(pNv->dev->fd); 492fda9279dSmrg if (ret) 493fda9279dSmrg ErrorF("Unable to get master: %s\n", strerror(errno)); 494fda9279dSmrg } 495fda9279dSmrg 496fda9279dSmrg if (XF86_CRTC_CONFIG_PTR(pScrn)->num_crtc && !xf86SetDesiredModes(pScrn)) 497fda9279dSmrg return FALSE; 498fda9279dSmrg 499fda9279dSmrg if (pNv->overlayAdaptor && pNv->Architecture != NV_ARCH_04) 500fda9279dSmrg NV10WriteOverlayParameters(pScrn); 501fda9279dSmrg 502fda9279dSmrg return TRUE; 503fda9279dSmrg} 504fda9279dSmrg 505fda9279dSmrg/* 506fda9279dSmrg * This is called when VT switching away from the X server. Its job is 507fda9279dSmrg * to restore the previous (text) mode. 508fda9279dSmrg */ 509fda9279dSmrg 510fda9279dSmrg/* Mandatory */ 511fda9279dSmrgstatic void 512fda9279dSmrgNVLeaveVT(VT_FUNC_ARGS_DECL) 513fda9279dSmrg{ 514fda9279dSmrg SCRN_INFO_PTR(arg); 515fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 516fda9279dSmrg#ifdef XF86_PDEV_SERVER_FD 517fda9279dSmrg NVEntPtr pNVEnt = NVEntPriv(pScrn); 518fda9279dSmrg#endif 519fda9279dSmrg int ret; 520fda9279dSmrg 521fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVLeaveVT is called.\n"); 522fda9279dSmrg 523fda9279dSmrg#ifdef XF86_PDEV_SERVER_FD 524fda9279dSmrg if (pNVEnt->platform_dev && 525fda9279dSmrg (pNVEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 526fda9279dSmrg return; 527fda9279dSmrg#endif 528fda9279dSmrg 529fda9279dSmrg ret = drmDropMaster(pNv->dev->fd); 530fda9279dSmrg if (ret && errno != EIO && errno != ENODEV) 531fda9279dSmrg ErrorF("Error dropping master: %i(%m)\n", -errno); 532fda9279dSmrg} 533fda9279dSmrg 534fda9279dSmrgstatic void 535fda9279dSmrgNVFlushCallback(CallbackListPtr *list, pointer user_data, pointer call_data) 536fda9279dSmrg{ 537fda9279dSmrg ScrnInfoPtr pScrn = user_data; 538fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 539fda9279dSmrg if (pScrn->vtSema && pNv->Flush) 540fda9279dSmrg pNv->Flush(pScrn); 541fda9279dSmrg} 542fda9279dSmrg 543fda9279dSmrg#ifdef NOUVEAU_PIXMAP_SHARING 544fda9279dSmrgstatic void 545fda9279dSmrgredisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) 546fda9279dSmrg{ 547fda9279dSmrg RegionRec pixregion; 548fda9279dSmrg 549a5560a61Smrg PixmapRegionInit(&pixregion, dirty->secondary_dst); 550fda9279dSmrg 551a5560a61Smrg DamageRegionAppend(&dirty->secondary_dst->drawable, &pixregion); 55216ee1e9aSmrg PixmapSyncDirtyHelper(dirty); 553fda9279dSmrg 554a5560a61Smrg DamageRegionProcessPending(&dirty->secondary_dst->drawable); 555fda9279dSmrg RegionUninit(&pixregion); 556fda9279dSmrg} 557fda9279dSmrg 558fda9279dSmrgstatic void 559fda9279dSmrgnouveau_dirty_update(ScreenPtr screen) 560fda9279dSmrg{ 561fda9279dSmrg RegionPtr region; 562fda9279dSmrg PixmapDirtyUpdatePtr ent; 563fda9279dSmrg 564fda9279dSmrg if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 565fda9279dSmrg return; 566fda9279dSmrg 567fda9279dSmrg xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 568fda9279dSmrg region = DamageRegion(ent->damage); 569fda9279dSmrg if (RegionNotEmpty(region)) { 570fda9279dSmrg redisplay_dirty(screen, ent); 571fda9279dSmrg DamageEmpty(ent->damage); 572fda9279dSmrg } 573fda9279dSmrg } 574fda9279dSmrg} 575fda9279dSmrg#endif 576fda9279dSmrg 577fda9279dSmrgstatic void 578fda9279dSmrgNVBlockHandler (BLOCKHANDLER_ARGS_DECL) 579fda9279dSmrg{ 580fda9279dSmrg SCREEN_PTR(arg); 581fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 582fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 583fda9279dSmrg 584fda9279dSmrg pScreen->BlockHandler = pNv->BlockHandler; 585fda9279dSmrg (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 586fda9279dSmrg pScreen->BlockHandler = NVBlockHandler; 587fda9279dSmrg 588fda9279dSmrg#ifdef NOUVEAU_PIXMAP_SHARING 589fda9279dSmrg nouveau_dirty_update(pScreen); 590fda9279dSmrg#endif 591fda9279dSmrg 592fda9279dSmrg NVFlushCallback(NULL, pScrn, NULL); 593fda9279dSmrg 594fda9279dSmrg if (pNv->VideoTimerCallback) 595fda9279dSmrg (*pNv->VideoTimerCallback)(pScrn, currentTime.milliseconds); 596fda9279dSmrg} 597fda9279dSmrg 598fda9279dSmrgstatic Bool 599fda9279dSmrgNVCreateScreenResources(ScreenPtr pScreen) 600fda9279dSmrg{ 601fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 602fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 603fda9279dSmrg 604fda9279dSmrg pScreen->CreateScreenResources = pNv->CreateScreenResources; 605fda9279dSmrg if (!(*pScreen->CreateScreenResources)(pScreen)) 606fda9279dSmrg return FALSE; 607fda9279dSmrg pScreen->CreateScreenResources = NVCreateScreenResources; 608fda9279dSmrg 609fda9279dSmrg drmmode_fbcon_copy(pScreen); 610fda9279dSmrg if (!NVEnterVT(VT_FUNC_ARGS(0))) 611fda9279dSmrg return FALSE; 612fda9279dSmrg 613fda9279dSmrg if (pNv->AccelMethod == EXA) { 614fda9279dSmrg PixmapPtr ppix = pScreen->GetScreenPixmap(pScreen); 615fda9279dSmrg nouveau_bo_ref(pNv->scanout, &nouveau_pixmap(ppix)->bo); 616fda9279dSmrg } 617fda9279dSmrg 618fda9279dSmrg return TRUE; 619fda9279dSmrg} 620fda9279dSmrg 621fda9279dSmrg/* 622fda9279dSmrg * This is called at the end of each server generation. It restores the 623fda9279dSmrg * original (text) mode. It should also unmap the video memory, and free 624fda9279dSmrg * any per-generation data allocated by the driver. It should finish 625fda9279dSmrg * by unwrapping and calling the saved CloseScreen function. 626fda9279dSmrg */ 627fda9279dSmrg 628fda9279dSmrg/* Mandatory */ 629fda9279dSmrgstatic Bool 630fda9279dSmrgNVCloseScreen(CLOSE_SCREEN_ARGS_DECL) 631fda9279dSmrg{ 632fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 633fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 634fda9279dSmrg 635fda9279dSmrg if (XF86_CRTC_CONFIG_PTR(pScrn)->num_crtc) 636fda9279dSmrg drmmode_screen_fini(pScreen); 637fda9279dSmrg 638fda9279dSmrg nouveau_present_fini(pScreen); 639fda9279dSmrg nouveau_dri2_fini(pScreen); 640fda9279dSmrg nouveau_sync_fini(pScreen); 641fda9279dSmrg nouveau_copy_fini(pScreen); 642fda9279dSmrg 643fda9279dSmrg if (pScrn->vtSema) { 644fda9279dSmrg NVLeaveVT(VT_FUNC_ARGS(0)); 645fda9279dSmrg pScrn->vtSema = FALSE; 646fda9279dSmrg } 647fda9279dSmrg 648fda9279dSmrg NVTakedownVideo(pScrn); 649fda9279dSmrg NVAccelCommonFini(pScrn); 650fda9279dSmrg NVUnmapMem(pScrn); 651fda9279dSmrg 652fda9279dSmrg xf86_cursors_fini(pScreen); 653fda9279dSmrg 654fda9279dSmrg DeleteCallback(&FlushCallback, NVFlushCallback, pScrn); 655fda9279dSmrg 656fda9279dSmrg if (pNv->ShadowPtr) { 657fda9279dSmrg free(pNv->ShadowPtr); 658fda9279dSmrg pNv->ShadowPtr = NULL; 659fda9279dSmrg } 660fda9279dSmrg if (pNv->overlayAdaptor) { 661fda9279dSmrg free(pNv->overlayAdaptor); 662fda9279dSmrg pNv->overlayAdaptor = NULL; 663fda9279dSmrg } 664fda9279dSmrg if (pNv->blitAdaptor) { 665fda9279dSmrg free(pNv->blitAdaptor); 666fda9279dSmrg pNv->blitAdaptor = NULL; 667fda9279dSmrg } 668fda9279dSmrg if (pNv->textureAdaptor[0]) { 669fda9279dSmrg free(pNv->textureAdaptor[0]); 670fda9279dSmrg pNv->textureAdaptor[0] = NULL; 671fda9279dSmrg } 672fda9279dSmrg if (pNv->textureAdaptor[1]) { 673fda9279dSmrg free(pNv->textureAdaptor[1]); 674fda9279dSmrg pNv->textureAdaptor[1] = NULL; 675fda9279dSmrg } 676fda9279dSmrg if (pNv->EXADriverPtr) { 677fda9279dSmrg exaDriverFini(pScreen); 678fda9279dSmrg free(pNv->EXADriverPtr); 679fda9279dSmrg pNv->EXADriverPtr = NULL; 680fda9279dSmrg } 681fda9279dSmrg 682fda9279dSmrg pScrn->vtSema = FALSE; 683fda9279dSmrg pScreen->CloseScreen = pNv->CloseScreen; 684fda9279dSmrg pScreen->BlockHandler = pNv->BlockHandler; 685fda9279dSmrg return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 686fda9279dSmrg} 687fda9279dSmrg 688fda9279dSmrg/* Free up any persistent data structures */ 689fda9279dSmrg 690fda9279dSmrg/* Optional */ 691fda9279dSmrgstatic void 692fda9279dSmrgNVFreeScreen(FREE_SCREEN_ARGS_DECL) 693fda9279dSmrg{ 694fda9279dSmrg /* 695fda9279dSmrg * This only gets called when a screen is being deleted. It does not 696fda9279dSmrg * get called routinely at the end of a server generation. 697fda9279dSmrg */ 698fda9279dSmrg SCRN_INFO_PTR(arg); 699fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 700fda9279dSmrg 701fda9279dSmrg if (!pNv) 702fda9279dSmrg return; 703fda9279dSmrg 704fda9279dSmrg NVCloseDRM(pScrn); 705fda9279dSmrg 706fda9279dSmrg free(pScrn->driverPrivate); 707fda9279dSmrg pScrn->driverPrivate = NULL; 708fda9279dSmrg} 709fda9279dSmrg 710fda9279dSmrg#define NVPreInitFail(fmt, args...) do { \ 711fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%d: "fmt, __LINE__, ##args); \ 712fda9279dSmrg NVFreeScreen(FREE_SCREEN_ARGS(pScrn)); \ 713fda9279dSmrg return FALSE; \ 714fda9279dSmrg} while(0) 715fda9279dSmrg 716fda9279dSmrgstatic void 717fda9279dSmrgNVCloseDRM(ScrnInfoPtr pScrn) 718fda9279dSmrg{ 719fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 720fda9279dSmrg 721fda9279dSmrg drmFree(pNv->drm_device_name); 722fda9279dSmrg nouveau_client_del(&pNv->client); 723fda9279dSmrg nouveau_device_del(&pNv->dev); 72416ee1e9aSmrg free(pNv->render_node); 725fda9279dSmrg} 726fda9279dSmrg 727fda9279dSmrgstatic void 728fda9279dSmrgnouveau_setup_capabilities(ScrnInfoPtr pScrn) 729fda9279dSmrg{ 730fda9279dSmrg#ifdef NOUVEAU_PIXMAP_SHARING 731fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 732fda9279dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 733fda9279dSmrg uint64_t value; 734fda9279dSmrg int ret; 735fda9279dSmrg 736fda9279dSmrg pScrn->capabilities = 0; 737fda9279dSmrg ret = drmGetCap(pNv->dev->fd, DRM_CAP_PRIME, &value); 738fda9279dSmrg if (ret == 0) { 739fda9279dSmrg if (value & DRM_PRIME_CAP_EXPORT) 740fda9279dSmrg pScrn->capabilities |= RR_Capability_SourceOutput; 741fda9279dSmrg if (value & DRM_PRIME_CAP_IMPORT) { 742fda9279dSmrg pScrn->capabilities |= RR_Capability_SourceOffload; 743fda9279dSmrg if (xf86_config->num_crtc) 744fda9279dSmrg pScrn->capabilities |= RR_Capability_SinkOutput; 745fda9279dSmrg } 746fda9279dSmrg } 747fda9279dSmrg#endif 748fda9279dSmrg} 749fda9279dSmrg 750fda9279dSmrgNVEntPtr NVEntPriv(ScrnInfoPtr pScrn) 751fda9279dSmrg{ 752fda9279dSmrg DevUnion *pPriv; 753fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 754fda9279dSmrg pPriv = xf86GetEntityPrivate(pNv->pEnt->index, 755fda9279dSmrg getNVEntityIndex()); 756fda9279dSmrg return pPriv->ptr; 757fda9279dSmrg} 758fda9279dSmrg 759fda9279dSmrgstatic Bool NVOpenDRMMaster(ScrnInfoPtr pScrn) 760fda9279dSmrg{ 761fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 762fda9279dSmrg NVEntPtr pNVEnt = NVEntPriv(pScrn); 763fda9279dSmrg drmSetVersion sv; 764fda9279dSmrg int err; 765fda9279dSmrg int ret; 766fda9279dSmrg 767fda9279dSmrg if (pNVEnt->fd) { 768fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 769fda9279dSmrg " reusing fd for second head\n"); 770fda9279dSmrg ret = nouveau_device_wrap(pNVEnt->fd, 0, &pNv->dev); 771fda9279dSmrg if (ret) { 772fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 773fda9279dSmrg "[drm] error creating device\n"); 774fda9279dSmrg return FALSE; 775fda9279dSmrg } 776fda9279dSmrg return TRUE; 777fda9279dSmrg } 778fda9279dSmrg 779fda9279dSmrg pNv->dev = NVOpenNouveauDevice(pNv->PciInfo, pNVEnt->platform_dev, 780fda9279dSmrg pScrn->scrnIndex, FALSE); 781fda9279dSmrg if (!pNv->dev) 782fda9279dSmrg return FALSE; 783fda9279dSmrg 784fda9279dSmrg sv.drm_di_major = 1; 785fda9279dSmrg sv.drm_di_minor = 1; 786fda9279dSmrg sv.drm_dd_major = -1; 787fda9279dSmrg sv.drm_dd_minor = -1; 788fda9279dSmrg err = drmSetInterfaceVersion(pNv->dev->fd, &sv); 789fda9279dSmrg if (err != 0) { 790fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 791fda9279dSmrg "[drm] failed to set drm interface version.\n"); 792fda9279dSmrg nouveau_device_del(&pNv->dev); 793fda9279dSmrg return FALSE; 794fda9279dSmrg } 795fda9279dSmrg pNVEnt->fd = pNv->dev->fd; 796fda9279dSmrg return TRUE; 797fda9279dSmrg} 798fda9279dSmrg 799fda9279dSmrgstatic Bool 800fda9279dSmrgNVPreInitDRM(ScrnInfoPtr pScrn) 801fda9279dSmrg{ 802fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 803fda9279dSmrg int ret; 804fda9279dSmrg 805fda9279dSmrg if (!xf86LoadSubModule(pScrn, "dri2")) 806fda9279dSmrg return FALSE; 807fda9279dSmrg 808fda9279dSmrg /* Load the kernel module, and open the DRM */ 809fda9279dSmrg ret = NVOpenDRMMaster(pScrn); 810fda9279dSmrg if (!ret) { 811fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 812fda9279dSmrg "[drm] error opening the drm\n"); 813fda9279dSmrg return FALSE; 814fda9279dSmrg } 815fda9279dSmrg 816fda9279dSmrg ret = nouveau_client_new(pNv->dev, &pNv->client); 817fda9279dSmrg if (ret) 818fda9279dSmrg return FALSE; 819fda9279dSmrg 820fda9279dSmrg pNv->drm_device_name = drmGetDeviceNameFromFd(pNv->dev->fd); 821fda9279dSmrg 822fda9279dSmrg return TRUE; 823fda9279dSmrg} 824fda9279dSmrg 825fda9279dSmrg/* Mandatory */ 826fda9279dSmrgBool 827fda9279dSmrgNVPreInit(ScrnInfoPtr pScrn, int flags) 828fda9279dSmrg{ 829fda9279dSmrg struct nouveau_device *dev; 830fda9279dSmrg NVPtr pNv; 831fda9279dSmrg MessageType from; 832fda9279dSmrg const char *reason, *string; 833fda9279dSmrg uint64_t v; 834fda9279dSmrg int ret; 835fda9279dSmrg int defaultDepth = 0; 836fda9279dSmrg 837fda9279dSmrg if (flags & PROBE_DETECT) { 838fda9279dSmrg EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 839fda9279dSmrg 840fda9279dSmrg if (!pEnt) 841fda9279dSmrg return FALSE; 842fda9279dSmrg 843fda9279dSmrg free(pEnt); 844fda9279dSmrg 845fda9279dSmrg return TRUE; 846fda9279dSmrg } 847fda9279dSmrg 848fda9279dSmrg /* 849fda9279dSmrg * Note: This function is only called once at server startup, and 850fda9279dSmrg * not at the start of each server generation. This means that 851fda9279dSmrg * only things that are persistent across server generations can 852fda9279dSmrg * be initialised here. xf86Screens[] is (pScrn is a pointer to one 853fda9279dSmrg * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 854fda9279dSmrg * are too, and should be used for data that must persist across 855fda9279dSmrg * server generations. 856fda9279dSmrg * 857fda9279dSmrg * Per-generation data should be allocated with 858fda9279dSmrg * AllocateScreenPrivateIndex() from the ScreenInit() function. 859fda9279dSmrg */ 860fda9279dSmrg 861fda9279dSmrg /* Check the number of entities, and fail if it isn't one. */ 862fda9279dSmrg if (pScrn->numEntities != 1) 863fda9279dSmrg return FALSE; 864fda9279dSmrg 865fda9279dSmrg /* Allocate the NVRec driverPrivate */ 866a5560a61Smrg if (!(pScrn->driverPrivate = XNFcallocarray(1, sizeof(NVRec)))) 867fda9279dSmrg return FALSE; 868fda9279dSmrg pNv = NVPTR(pScrn); 869fda9279dSmrg 870fda9279dSmrg /* Get the entity, and make sure it is PCI. */ 871fda9279dSmrg pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 872fda9279dSmrg if (pNv->pEnt->location.type != BUS_PCI 873fda9279dSmrg#ifdef XSERVER_PLATFORM_BUS 874fda9279dSmrg && pNv->pEnt->location.type != BUS_PLATFORM 875fda9279dSmrg#endif 876fda9279dSmrg ) 877fda9279dSmrg return FALSE; 878fda9279dSmrg 879fda9279dSmrg if (xf86IsEntityShared(pScrn->entityList[0])) { 880fda9279dSmrg if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 881fda9279dSmrg pNv->Primary = TRUE; 882fda9279dSmrg xf86SetPrimInitDone(pScrn->entityList[0]); 883fda9279dSmrg } else { 884fda9279dSmrg pNv->Secondary = TRUE; 885fda9279dSmrg } 886fda9279dSmrg } 887fda9279dSmrg 888fda9279dSmrg /* Find the PCI info for this screen */ 889fda9279dSmrg pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index); 890fda9279dSmrg 891fda9279dSmrg /* Initialise the kernel module */ 892fda9279dSmrg if (!NVPreInitDRM(pScrn)) 893fda9279dSmrg NVPreInitFail("\n"); 894fda9279dSmrg dev = pNv->dev; 895fda9279dSmrg 896fda9279dSmrg pScrn->chipset = malloc(sizeof(char) * 25); 897fda9279dSmrg sprintf((char *)pScrn->chipset, "NVIDIA NV%02X", dev->chipset); 898fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chipset: \"%s\"\n", pScrn->chipset); 899fda9279dSmrg 900fda9279dSmrg switch (dev->chipset & ~0xf) { 901fda9279dSmrg case 0x00: 902fda9279dSmrg pNv->Architecture = NV_ARCH_04; 903fda9279dSmrg break; 904fda9279dSmrg case 0x10: 905fda9279dSmrg pNv->Architecture = NV_ARCH_10; 906fda9279dSmrg break; 907fda9279dSmrg case 0x20: 908fda9279dSmrg pNv->Architecture = NV_ARCH_20; 909fda9279dSmrg break; 910fda9279dSmrg case 0x30: 911fda9279dSmrg pNv->Architecture = NV_ARCH_30; 912fda9279dSmrg break; 913fda9279dSmrg case 0x40: 914fda9279dSmrg case 0x60: 915fda9279dSmrg pNv->Architecture = NV_ARCH_40; 916fda9279dSmrg break; 917fda9279dSmrg case 0x50: 918fda9279dSmrg case 0x80: 919fda9279dSmrg case 0x90: 920fda9279dSmrg case 0xa0: 921fda9279dSmrg pNv->Architecture = NV_TESLA; 922fda9279dSmrg break; 923fda9279dSmrg case 0xc0: 924fda9279dSmrg case 0xd0: 925fda9279dSmrg pNv->Architecture = NV_FERMI; 926fda9279dSmrg break; 927fda9279dSmrg case 0xe0: 928fda9279dSmrg case 0xf0: 929fda9279dSmrg case 0x100: 930fda9279dSmrg pNv->Architecture = NV_KEPLER; 931fda9279dSmrg break; 932fda9279dSmrg case 0x110: 933cd34e0e1Smrg case 0x120: 934fda9279dSmrg pNv->Architecture = NV_MAXWELL; 935fda9279dSmrg break; 936cd34e0e1Smrg case 0x130: 937cd34e0e1Smrg pNv->Architecture = NV_PASCAL; 938cd34e0e1Smrg break; 939fda9279dSmrg default: 940fda9279dSmrg return FALSE; 941fda9279dSmrg } 942fda9279dSmrg 943fda9279dSmrg /* Set pScrn->monitor */ 944fda9279dSmrg pScrn->monitor = pScrn->confScreen->monitor; 945fda9279dSmrg 946fda9279dSmrg /* 947fda9279dSmrg * The first thing we should figure out is the depth, bpp, etc. 948fda9279dSmrg */ 949fda9279dSmrg 950fda9279dSmrg if (dev->vram_size <= 16 * 1024 * 1024) 951fda9279dSmrg defaultDepth = 16; 952fda9279dSmrg if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, 0, Support32bppFb)) { 953fda9279dSmrg NVPreInitFail("\n"); 954fda9279dSmrg } else { 955fda9279dSmrg /* Check that the returned depth is one we support */ 956fda9279dSmrg switch (pScrn->depth) { 957fda9279dSmrg case 16: 958fda9279dSmrg case 24: 959fda9279dSmrg /* OK */ 960fda9279dSmrg break; 961fda9279dSmrg case 30: 962fda9279dSmrg /* OK on NV50 KMS */ 963fda9279dSmrg if (pNv->Architecture < NV_TESLA) 964fda9279dSmrg NVPreInitFail("Depth 30 supported on G80+ only\n"); 965fda9279dSmrg break; 966fda9279dSmrg case 15: /* 15 may get done one day, so leave any code for it in place */ 967fda9279dSmrg default: 968fda9279dSmrg NVPreInitFail("Given depth (%d) is not supported by this driver\n", 969fda9279dSmrg pScrn->depth); 970fda9279dSmrg } 971fda9279dSmrg } 972fda9279dSmrg xf86PrintDepthBpp(pScrn); 973fda9279dSmrg 974fda9279dSmrg /* 975fda9279dSmrg * This must happen after pScrn->display has been set because 976fda9279dSmrg * xf86SetWeight references it. 977fda9279dSmrg */ 978fda9279dSmrg rgb rgbzeros = {0, 0, 0}; 979fda9279dSmrg 980fda9279dSmrg if (pScrn->depth == 30) { 981fda9279dSmrg rgb rgbmask; 982fda9279dSmrg 983fda9279dSmrg rgbmask.red = 0x000003ff; 984fda9279dSmrg rgbmask.green = 0x000ffc00; 985fda9279dSmrg rgbmask.blue = 0x3ff00000; 986fda9279dSmrg if (!xf86SetWeight(pScrn, rgbzeros, rgbmask)) 987fda9279dSmrg NVPreInitFail("\n"); 988fda9279dSmrg 989fda9279dSmrg /* xf86SetWeight() seems to think ffs(1) == 0... */ 990fda9279dSmrg pScrn->offset.red--; 991fda9279dSmrg pScrn->offset.green--; 992fda9279dSmrg pScrn->offset.blue--; 993fda9279dSmrg } else { 994fda9279dSmrg if (!xf86SetWeight(pScrn, rgbzeros, rgbzeros)) 995fda9279dSmrg NVPreInitFail("\n"); 996fda9279dSmrg } 997fda9279dSmrg 998fda9279dSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 999fda9279dSmrg NVPreInitFail("\n"); 1000fda9279dSmrg 1001fda9279dSmrg /* We don't support DirectColor */ 1002fda9279dSmrg if (pScrn->defaultVisual != TrueColor) { 1003fda9279dSmrg NVPreInitFail("Given default visual (%s) is not supported at depth %d\n", 1004fda9279dSmrg xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 1005fda9279dSmrg } 1006fda9279dSmrg 1007fda9279dSmrg /* We use a programmable clock */ 1008fda9279dSmrg pScrn->progClock = TRUE; 1009fda9279dSmrg 1010fda9279dSmrg /* Collect all of the relevant option flags (fill in pScrn->options) */ 1011fda9279dSmrg xf86CollectOptions(pScrn, NULL); 1012fda9279dSmrg 1013fda9279dSmrg /* Process the options */ 1014fda9279dSmrg if (!(pNv->Options = malloc(sizeof(NVOptions)))) 1015fda9279dSmrg return FALSE; 1016fda9279dSmrg memcpy(pNv->Options, NVOptions, sizeof(NVOptions)); 1017fda9279dSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options); 1018fda9279dSmrg 1019fda9279dSmrg from = X_DEFAULT; 1020fda9279dSmrg 1021fda9279dSmrg pNv->HWCursor = TRUE; 1022fda9279dSmrg /* 1023fda9279dSmrg * The preferred method is to use the "hw cursor" option as a tri-state 1024fda9279dSmrg * option, with the default set above. 1025fda9279dSmrg */ 1026fda9279dSmrg if (xf86GetOptValBool(pNv->Options, OPTION_HW_CURSOR, &pNv->HWCursor)) { 1027fda9279dSmrg from = X_CONFIG; 1028fda9279dSmrg } 1029fda9279dSmrg /* For compatibility, accept this too (as an override) */ 1030fda9279dSmrg if (xf86ReturnOptValBool(pNv->Options, OPTION_SW_CURSOR, FALSE)) { 1031fda9279dSmrg from = X_CONFIG; 1032fda9279dSmrg pNv->HWCursor = FALSE; 1033fda9279dSmrg } 1034fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 1035fda9279dSmrg pNv->HWCursor ? "HW" : "SW"); 1036fda9279dSmrg 1037fda9279dSmrg string = xf86GetOptValString(pNv->Options, OPTION_ACCELMETHOD); 1038fda9279dSmrg if (string) { 1039fda9279dSmrg if (!strcmp(string, "none")) pNv->AccelMethod = NONE; 1040fda9279dSmrg else if (!strcmp(string, "exa")) pNv->AccelMethod = EXA; 1041fda9279dSmrg else { 1042fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1043fda9279dSmrg "Invalid AccelMethod specified\n"); 1044fda9279dSmrg } 1045fda9279dSmrg } 1046fda9279dSmrg 1047fda9279dSmrg if (pNv->AccelMethod == UNKNOWN) { 104816ee1e9aSmrg pNv->AccelMethod = EXA; 1049fda9279dSmrg } 1050fda9279dSmrg 1051fda9279dSmrg if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) { 1052fda9279dSmrg pNv->AccelMethod = NONE; 1053fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 1054fda9279dSmrg } 1055fda9279dSmrg 1056fda9279dSmrg if (xf86ReturnOptValBool(pNv->Options, OPTION_SHADOW_FB, FALSE)) { 1057fda9279dSmrg pNv->ShadowFB = TRUE; 1058fda9279dSmrg pNv->AccelMethod = NONE; 1059fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1060fda9279dSmrg "Using \"Shadow Framebuffer\" - acceleration disabled\n"); 1061fda9279dSmrg } 1062fda9279dSmrg 1063fda9279dSmrg if (pNv->AccelMethod > NONE) { 1064fe196524Smrg#if 0 1065fda9279dSmrg if (pNv->Architecture >= NV_TESLA) 1066fda9279dSmrg pNv->wfb_enabled = xf86ReturnOptValBool( 1067fda9279dSmrg pNv->Options, OPTION_WFB, FALSE); 1068fe196524Smrg#endif 1069fda9279dSmrg 10702a7e9763Smrg if (pNv->Architecture >= NV_ARCH_10) 10712a7e9763Smrg pNv->tiled_scanout = TRUE; 1072fda9279dSmrg } 1073fda9279dSmrg 1074fda9279dSmrg pNv->ce_enabled = 1075fda9279dSmrg xf86ReturnOptValBool(pNv->Options, OPTION_ASYNC_COPY, FALSE); 1076fda9279dSmrg 107716ee1e9aSmrg /* Define maximum allowed level of DRI implementation to use. 107816ee1e9aSmrg * We default to DRI2 on EXA for now, as DRI3 still has some 107916ee1e9aSmrg * problems. 108016ee1e9aSmrg */ 108116ee1e9aSmrg pNv->max_dri_level = 2; 108216ee1e9aSmrg from = X_DEFAULT; 108316ee1e9aSmrg 108416ee1e9aSmrg if (xf86GetOptValInteger(pNv->Options, OPTION_DRI, 108516ee1e9aSmrg &pNv->max_dri_level)) { 108616ee1e9aSmrg from = X_CONFIG; 108716ee1e9aSmrg if (pNv->max_dri_level < 2) 108816ee1e9aSmrg pNv->max_dri_level = 2; 108916ee1e9aSmrg if (pNv->max_dri_level > 3) 109016ee1e9aSmrg pNv->max_dri_level = 3; 109116ee1e9aSmrg } 109216ee1e9aSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Allowed maximum DRI level %i.\n", 109316ee1e9aSmrg pNv->max_dri_level); 109416ee1e9aSmrg 1095fda9279dSmrg if (pNv->AccelMethod > NONE && pNv->dev->chipset >= 0x11) { 1096fda9279dSmrg from = X_DEFAULT; 1097fda9279dSmrg pNv->glx_vblank = TRUE; 1098fda9279dSmrg if (xf86GetOptValBool(pNv->Options, OPTION_GLX_VBLANK, 1099fda9279dSmrg &pNv->glx_vblank)) 1100fda9279dSmrg from = X_CONFIG; 1101fda9279dSmrg 1102fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "GLX sync to VBlank %s.\n", 1103fda9279dSmrg pNv->glx_vblank ? "enabled" : "disabled"); 1104fda9279dSmrg } 1105fda9279dSmrg 1106fda9279dSmrg#ifdef NOUVEAU_GETPARAM_HAS_PAGEFLIP 1107fda9279dSmrg reason = ": no kernel support"; 1108fda9279dSmrg from = X_DEFAULT; 1109fda9279dSmrg 1110fda9279dSmrg ret = nouveau_getparam(pNv->dev, NOUVEAU_GETPARAM_HAS_PAGEFLIP, &v); 1111fda9279dSmrg if (ret == 0 && v == 1) { 1112fda9279dSmrg pNv->has_pageflip = TRUE; 1113fda9279dSmrg if (xf86GetOptValBool(pNv->Options, OPTION_PAGE_FLIP, &pNv->has_pageflip)) 1114fda9279dSmrg from = X_CONFIG; 1115fda9279dSmrg reason = ""; 1116fda9279dSmrg } 1117fda9279dSmrg#else 1118fda9279dSmrg reason = ": not available at build time"; 1119fda9279dSmrg#endif 1120fda9279dSmrg 1121fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Page flipping %sabled%s\n", 1122fda9279dSmrg pNv->has_pageflip ? "en" : "dis", reason); 1123fda9279dSmrg 1124fda9279dSmrg if(xf86GetOptValInteger(pNv->Options, OPTION_VIDEO_KEY, &(pNv->videoKey))) { 1125fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", 1126fda9279dSmrg pNv->videoKey); 1127fda9279dSmrg } else { 1128fda9279dSmrg pNv->videoKey = (1 << pScrn->offset.red) | 1129fda9279dSmrg (1 << pScrn->offset.green) | 1130fda9279dSmrg (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 1131fda9279dSmrg } 1132fda9279dSmrg 1133fda9279dSmrg /* Limit to max 2 pending swaps - we can't handle more than triple-buffering: */ 1134fda9279dSmrg pNv->max_swap_limit = 2; 1135fda9279dSmrg 1136fda9279dSmrg if(xf86GetOptValInteger(pNv->Options, OPTION_SWAP_LIMIT, &(pNv->swap_limit))) { 1137fda9279dSmrg if (pNv->swap_limit < 1) 1138fda9279dSmrg pNv->swap_limit = 1; 1139fda9279dSmrg 1140fda9279dSmrg if (pNv->swap_limit > pNv->max_swap_limit) 1141fda9279dSmrg pNv->swap_limit = pNv->max_swap_limit; 1142fda9279dSmrg 1143fda9279dSmrg reason = ""; 1144fda9279dSmrg from = X_CONFIG; 1145fda9279dSmrg 1146fda9279dSmrg if ((DRI2INFOREC_VERSION < 6) && (pNv->swap_limit > 1)) { 1147fda9279dSmrg /* No swap limit api in server. A value > 1 requires use 1148fda9279dSmrg * of problematic hacks. 1149fda9279dSmrg */ 1150fda9279dSmrg from = X_WARNING; 1151fda9279dSmrg reason = ": Caution: Use of this swap limit > 1 violates OML_sync_control spec on this X-Server!\n"; 1152fda9279dSmrg } 1153fda9279dSmrg } else { 1154fda9279dSmrg /* Always default to double-buffering, because it avoids artifacts like 1155fda9279dSmrg * unthrottled rendering of non-fullscreen clients under desktop composition. 1156fda9279dSmrg */ 1157fda9279dSmrg pNv->swap_limit = 1; 1158fda9279dSmrg reason = ""; 1159fda9279dSmrg from = X_DEFAULT; 1160fda9279dSmrg } 1161fda9279dSmrg 1162fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Swap limit set to %d [Max allowed %d]%s\n", 1163fda9279dSmrg pNv->swap_limit, pNv->max_swap_limit, reason); 1164fda9279dSmrg 1165fda9279dSmrg /* Does kernel do the sync of pageflips to vblank? */ 1166fda9279dSmrg pNv->has_async_pageflip = FALSE; 1167fda9279dSmrg#ifdef DRM_CAP_ASYNC_PAGE_FLIP 1168fda9279dSmrg ret = drmGetCap(pNv->dev->fd, DRM_CAP_ASYNC_PAGE_FLIP, &v); 1169fda9279dSmrg if (ret == 0 && v == 1) { 1170fda9279dSmrg pNv->has_async_pageflip = TRUE; 1171fda9279dSmrg } 1172fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Page flipping synced to vblank by %s.\n", 1173fda9279dSmrg pNv->has_async_pageflip ? "kernel" : "ddx"); 1174fda9279dSmrg#endif 1175fda9279dSmrg 1176fda9279dSmrg ret = drmmode_pre_init(pScrn, pNv->dev->fd, pScrn->bitsPerPixel >> 3); 1177fda9279dSmrg if (ret == FALSE) 1178fda9279dSmrg NVPreInitFail("Kernel modesetting failed to initialize\n"); 1179fda9279dSmrg 1180fda9279dSmrg /* 1181fda9279dSmrg * If the driver can do gamma correction, it should call xf86SetGamma() 1182fda9279dSmrg * here. 1183fda9279dSmrg */ 1184fda9279dSmrg Gamma gammazeros = {0.0, 0.0, 0.0}; 1185fda9279dSmrg 1186fda9279dSmrg if (!xf86SetGamma(pScrn, gammazeros)) 1187fda9279dSmrg NVPreInitFail("\n"); 1188fda9279dSmrg 1189fda9279dSmrg#ifdef NOUVEAU_PIXMAP_SHARING 1190fda9279dSmrg /* 1191fda9279dSmrg * The driver will not work as gpu screen without acceleration enabled. 1192fda9279dSmrg * To support this usecase modesetting ddx can be used instead. 1193fda9279dSmrg */ 1194fda9279dSmrg if (pNv->AccelMethod <= NONE || pNv->ShadowFB) { 1195fda9279dSmrg /* 1196fda9279dSmrg * Optimus mode requires acceleration enabled. 1197fda9279dSmrg * So if no mode is found, or the screen is created 1198fda9279dSmrg * as a gpu screen the pre init should fail. 1199fda9279dSmrg */ 1200fda9279dSmrg if (pScrn->is_gpu || !pScrn->modes) 1201fda9279dSmrg return FALSE; 1202fda9279dSmrg } 1203fda9279dSmrg 1204fda9279dSmrg#else 1205fda9279dSmrg /* No usable mode, no optimus config possible */ 1206fda9279dSmrg if (!pScrn->modes) 1207fda9279dSmrg return FALSE; 1208fda9279dSmrg#endif 1209fda9279dSmrg 1210fda9279dSmrg nouveau_setup_capabilities(pScrn); 1211fda9279dSmrg 1212fda9279dSmrg if (!pScrn->modes) { 12136e60514dSmacallan DisplayModePtr m; 12146e60514dSmacallan 12156e60514dSmacallan m = xf86CVTMode(pScrn->display->virtualX, 1216fda9279dSmrg pScrn->display->virtualY, 12176e60514dSmacallan 60, 0, 0); 12186e60514dSmacallan xf86SetModeDefaultName(m); 12196e60514dSmacallan pScrn->modes = xf86ModesAdd(pScrn->modes, m); 1220fda9279dSmrg } 1221fda9279dSmrg 1222fda9279dSmrg /* Set the current mode to the first in the list */ 1223fda9279dSmrg pScrn->currentMode = pScrn->modes; 1224fda9279dSmrg 1225fda9279dSmrg /* Print the list of modes being used */ 1226fda9279dSmrg xf86PrintModes(pScrn); 1227fda9279dSmrg 1228fda9279dSmrg /* Set display resolution */ 1229fda9279dSmrg xf86SetDpi(pScrn, 0, 0); 1230fda9279dSmrg 1231fe196524Smrg#if 0 1232fda9279dSmrg if (pNv->wfb_enabled) { 1233fda9279dSmrg if (xf86LoadSubModule(pScrn, "wfb") == NULL) 1234fda9279dSmrg NVPreInitFail("\n"); 1235fda9279dSmrg } 1236fe196524Smrg#endif 1237fda9279dSmrg 1238fda9279dSmrg if (xf86LoadSubModule(pScrn, "fb") == NULL) 1239fda9279dSmrg NVPreInitFail("\n"); 1240fda9279dSmrg 1241fda9279dSmrg /* Load shadowfb */ 1242fda9279dSmrg if (!xf86LoadSubModule(pScrn, "shadowfb")) 1243fda9279dSmrg NVPreInitFail("\n"); 1244fda9279dSmrg 1245fda9279dSmrg return TRUE; 1246fda9279dSmrg} 1247fda9279dSmrg 1248fda9279dSmrg 1249fda9279dSmrgstatic Bool 1250fda9279dSmrgNVMapMem(ScrnInfoPtr pScrn) 1251fda9279dSmrg{ 1252fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1253fda9279dSmrg int ret, pitch; 1254fda9279dSmrg 1255fda9279dSmrg ret = nouveau_allocate_surface(pScrn, pScrn->virtualX, pScrn->virtualY, 1256fda9279dSmrg pScrn->bitsPerPixel, 1257fda9279dSmrg NOUVEAU_CREATE_PIXMAP_SCANOUT, 1258fda9279dSmrg &pitch, &pNv->scanout); 1259fda9279dSmrg if (!ret) { 1260fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1261fda9279dSmrg "Error allocating scanout buffer: %d\n", ret); 1262fda9279dSmrg return FALSE; 1263fda9279dSmrg } 1264fda9279dSmrg 1265fda9279dSmrg pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); 1266fda9279dSmrg return TRUE; 1267fda9279dSmrg} 1268fda9279dSmrg 1269fda9279dSmrg/* 1270fda9279dSmrg * Unmap the framebuffer and offscreen memory. 1271fda9279dSmrg */ 1272fda9279dSmrg 1273fda9279dSmrgstatic Bool 1274fda9279dSmrgNVUnmapMem(ScrnInfoPtr pScrn) 1275fda9279dSmrg{ 1276fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1277fda9279dSmrg 1278fda9279dSmrg drmmode_remove_fb(pScrn); 1279fda9279dSmrg 1280fda9279dSmrg nouveau_bo_ref(NULL, &pNv->transfer); 1281fda9279dSmrg nouveau_bo_ref(NULL, &pNv->scanout); 1282fda9279dSmrg return TRUE; 1283fda9279dSmrg} 1284fda9279dSmrg 1285fda9279dSmrgstatic void 1286fda9279dSmrgNVLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 1287fda9279dSmrg LOCO * colors, VisualPtr pVisual) 1288fda9279dSmrg{ 1289fda9279dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1290fda9279dSmrg int c; 1291fda9279dSmrg int i, j, index; 1292fda9279dSmrg CARD16 lut_r[256], lut_g[256], lut_b[256]; 1293fda9279dSmrg 1294fda9279dSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1295fda9279dSmrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 1296fda9279dSmrg 1297fda9279dSmrg /* code borrowed from intel driver */ 1298fda9279dSmrg switch (pScrn->depth) { 1299fda9279dSmrg case 15: 1300fda9279dSmrg for (i = 0; i < numColors; i++) { 1301fda9279dSmrg index = indices[i]; 1302fda9279dSmrg for (j = 0; j < 8; j++) { 1303fda9279dSmrg lut_r[index * 8 + j] = colors[index].red << 8; 1304fda9279dSmrg lut_g[index * 8 + j] = colors[index].green << 8; 1305fda9279dSmrg lut_b[index * 8 + j] = colors[index].blue << 8; 1306fda9279dSmrg } 1307fda9279dSmrg } 1308fda9279dSmrg break; 1309fda9279dSmrg 1310fda9279dSmrg case 16: 1311fda9279dSmrg for (i = 0; i < numColors; i++) { 1312fda9279dSmrg index = indices[i]; 1313fda9279dSmrg 1314fda9279dSmrg if (i <= 31) { 1315fda9279dSmrg for (j = 0; j < 8; j++) { 1316fda9279dSmrg lut_r[index * 8 + j] = colors[index].red << 8; 1317fda9279dSmrg lut_b[index * 8 + j] = colors[index].blue << 8; 1318fda9279dSmrg } 1319fda9279dSmrg } 1320fda9279dSmrg 1321fda9279dSmrg for (j = 0; j < 4; j++) { 1322fda9279dSmrg lut_g[index * 4 + j] = colors[index].green << 8; 1323fda9279dSmrg } 1324fda9279dSmrg } 1325fda9279dSmrg break; 1326fda9279dSmrg 1327fda9279dSmrg default: 1328fda9279dSmrg for (i = 0; i < numColors; i++) { 1329fda9279dSmrg index = indices[i]; 1330fda9279dSmrg lut_r[index] = colors[index].red << 8; 1331fda9279dSmrg lut_g[index] = colors[index].green << 8; 1332fda9279dSmrg lut_b[index] = colors[index].blue << 8; 1333fda9279dSmrg } 1334fda9279dSmrg break; 1335fda9279dSmrg } 1336fda9279dSmrg 1337fda9279dSmrg if (crtc->randr_crtc) 1338fda9279dSmrg /* Make the change through RandR */ 1339fda9279dSmrg RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 1340fda9279dSmrg } 1341fda9279dSmrg} 1342fda9279dSmrg 1343fda9279dSmrg/* Mandatory */ 1344fda9279dSmrg 1345fda9279dSmrg/* This gets called at the start of each server generation */ 1346fda9279dSmrgstatic Bool 1347fda9279dSmrgNVScreenInit(SCREEN_INIT_ARGS_DECL) 1348fda9279dSmrg{ 1349fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1350fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1351fda9279dSmrg int ret; 1352fda9279dSmrg VisualPtr visual; 1353fda9279dSmrg unsigned char *FBStart; 1354fda9279dSmrg int displayWidth; 1355fda9279dSmrg 1356fda9279dSmrg if (pNv->AccelMethod == EXA) { 1357fda9279dSmrg if (!NVAccelCommonInit(pScrn)) { 1358fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1359fda9279dSmrg "Error initialising acceleration. " 1360fda9279dSmrg "Falling back to NoAccel\n"); 1361fda9279dSmrg pNv->AccelMethod = NONE; 1362fda9279dSmrg pNv->ShadowFB = TRUE; 1363fe196524Smrg#if 0 1364fda9279dSmrg pNv->wfb_enabled = FALSE; 1365fe196524Smrg#endif 1366fda9279dSmrg pNv->tiled_scanout = FALSE; 13672a7e9763Smrg pScrn->capabilities &= ~(RR_Capability_SourceOutput | 13682a7e9763Smrg RR_Capability_SourceOffload | 13692a7e9763Smrg RR_Capability_SinkOutput); 1370fda9279dSmrg pScrn->displayWidth = nv_pitch_align(pNv, 1371fda9279dSmrg pScrn->virtualX, 1372fda9279dSmrg pScrn->depth); 1373fda9279dSmrg } 1374fda9279dSmrg } 1375fda9279dSmrg 1376fda9279dSmrg nouveau_copy_init(pScreen); 1377fda9279dSmrg 1378fda9279dSmrg /* Allocate and map memory areas we need */ 1379fda9279dSmrg if (!NVMapMem(pScrn)) 1380fda9279dSmrg return FALSE; 1381fda9279dSmrg 1382fda9279dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1383fda9279dSmrg int i; 1384fda9279dSmrg 1385fda9279dSmrg /* need to point to new screen on server regeneration */ 1386fda9279dSmrg for (i = 0; i < xf86_config->num_crtc; i++) 1387fda9279dSmrg xf86_config->crtc[i]->scrn = pScrn; 1388fda9279dSmrg for (i = 0; i < xf86_config->num_output; i++) 1389fda9279dSmrg xf86_config->output[i]->scrn = pScrn; 1390fda9279dSmrg 1391fda9279dSmrg /* 1392fda9279dSmrg * The next step is to setup the screen's visuals, and initialise the 1393fda9279dSmrg * framebuffer code. In cases where the framebuffer's default 1394fda9279dSmrg * choices for things like visual layouts and bits per RGB are OK, 1395fda9279dSmrg * this may be as simple as calling the framebuffer's ScreenInit() 1396fda9279dSmrg * function. If not, the visuals will need to be setup before calling 1397fda9279dSmrg * a fb ScreenInit() function and fixed up after. 1398fda9279dSmrg * 1399fda9279dSmrg * For most PC hardware at depths >= 8, the defaults that fb uses 1400fda9279dSmrg * are not appropriate. In this driver, we fixup the visuals after. 1401fda9279dSmrg */ 1402fda9279dSmrg 1403fda9279dSmrg /* 1404fda9279dSmrg * Reset the visual list. 1405fda9279dSmrg */ 1406fda9279dSmrg miClearVisualTypes(); 1407fda9279dSmrg 1408fda9279dSmrg /* Setup the visuals we support. */ 1409fda9279dSmrg if (!miSetVisualTypes(pScrn->depth, 1410fda9279dSmrg miGetDefaultVisualMask(pScrn->depth), 1411fda9279dSmrg pScrn->rgbBits, pScrn->defaultVisual)) 1412fda9279dSmrg return FALSE; 1413fda9279dSmrg 1414fda9279dSmrg if (!miSetPixmapDepths ()) 1415fda9279dSmrg return FALSE; 1416fda9279dSmrg 1417fda9279dSmrg /* 1418fda9279dSmrg * Call the framebuffer layer's ScreenInit function, and fill in other 1419fda9279dSmrg * pScreen fields. 1420fda9279dSmrg */ 1421fda9279dSmrg 1422fda9279dSmrg if (pNv->ShadowFB) { 1423fda9279dSmrg pNv->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * pScrn->virtualX); 1424fda9279dSmrg pNv->ShadowPtr = malloc(pNv->ShadowPitch * pScrn->virtualY); 1425fda9279dSmrg displayWidth = pNv->ShadowPitch / (pScrn->bitsPerPixel >> 3); 1426fda9279dSmrg FBStart = pNv->ShadowPtr; 1427fda9279dSmrg } else 1428fda9279dSmrg if (pNv->AccelMethod <= NONE) { 1429fda9279dSmrg pNv->ShadowPtr = NULL; 1430fda9279dSmrg displayWidth = pScrn->displayWidth; 1431fda9279dSmrg nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR, pNv->client); 1432fda9279dSmrg FBStart = pNv->scanout->map; 1433fda9279dSmrg } else { 1434fda9279dSmrg pNv->ShadowPtr = NULL; 1435fda9279dSmrg displayWidth = pScrn->displayWidth; 1436fda9279dSmrg FBStart = NULL; 1437fda9279dSmrg } 1438fda9279dSmrg 1439fda9279dSmrg switch (pScrn->bitsPerPixel) { 1440fda9279dSmrg case 16: 1441fda9279dSmrg case 32: 1442fe196524Smrg#if 0 1443fda9279dSmrg if (pNv->wfb_enabled) { 1444fda9279dSmrg ret = wfbScreenInit(pScreen, FBStart, pScrn->virtualX, 1445fda9279dSmrg pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 1446fda9279dSmrg displayWidth, pScrn->bitsPerPixel, 1447fda9279dSmrg nouveau_wfb_setup_wrap, 1448fda9279dSmrg nouveau_wfb_finish_wrap); 1449fda9279dSmrg } else { 1450fe196524Smrg#endif 1451fda9279dSmrg ret = fbScreenInit(pScreen, FBStart, pScrn->virtualX, 1452fda9279dSmrg pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 1453fda9279dSmrg displayWidth, pScrn->bitsPerPixel); 1454fe196524Smrg#if 0 1455fda9279dSmrg } 1456fe196524Smrg#endif 1457fda9279dSmrg break; 1458fda9279dSmrg default: 1459fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1460fda9279dSmrg "Internal error: invalid bpp (%d) in NVScreenInit\n", 1461fda9279dSmrg pScrn->bitsPerPixel); 1462fda9279dSmrg ret = FALSE; 1463fda9279dSmrg break; 1464fda9279dSmrg } 1465fda9279dSmrg if (!ret) 1466fda9279dSmrg return FALSE; 1467fda9279dSmrg 1468fda9279dSmrg /* Fixup RGB ordering */ 1469fda9279dSmrg visual = pScreen->visuals + pScreen->numVisuals; 1470fda9279dSmrg while (--visual >= pScreen->visuals) { 1471fda9279dSmrg if ((visual->class | DynamicClass) == DirectColor) { 1472fda9279dSmrg visual->offsetRed = pScrn->offset.red; 1473fda9279dSmrg visual->offsetGreen = pScrn->offset.green; 1474fda9279dSmrg visual->offsetBlue = pScrn->offset.blue; 1475fda9279dSmrg visual->redMask = pScrn->mask.red; 1476fda9279dSmrg visual->greenMask = pScrn->mask.green; 1477fda9279dSmrg visual->blueMask = pScrn->mask.blue; 1478fda9279dSmrg } 1479fda9279dSmrg } 1480fda9279dSmrg 1481fe196524Smrg#if 0 1482fda9279dSmrg if (pNv->wfb_enabled) 1483fda9279dSmrg wfbPictureInit (pScreen, 0, 0); 1484fda9279dSmrg else 1485fe196524Smrg#endif 1486fda9279dSmrg fbPictureInit (pScreen, 0, 0); 1487fda9279dSmrg 1488fda9279dSmrg xf86SetBlackWhitePixels(pScreen); 1489fda9279dSmrg 14902a7e9763Smrg if (pNv->AccelMethod == EXA && nouveau_present_init(pScreen)) 149116ee1e9aSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 149216ee1e9aSmrg "Hardware support for Present enabled\n"); 149316ee1e9aSmrg else 149416ee1e9aSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 149516ee1e9aSmrg "Hardware support for Present disabled\n"); 149616ee1e9aSmrg 149716ee1e9aSmrg nouveau_sync_init(pScreen); 149816ee1e9aSmrg nouveau_dri2_init(pScreen); 1499fda9279dSmrg if (pNv->AccelMethod == EXA) { 150016ee1e9aSmrg if (pNv->max_dri_level >= 3 && 150116ee1e9aSmrg !nouveau_dri3_screen_init(pScreen)) 150216ee1e9aSmrg return FALSE; 150316ee1e9aSmrg 1504fda9279dSmrg if (!nouveau_exa_init(pScreen)) 1505fda9279dSmrg return FALSE; 1506fda9279dSmrg } 1507fda9279dSmrg 1508fda9279dSmrg xf86SetBackingStore(pScreen); 1509fda9279dSmrg xf86SetSilkenMouse(pScreen); 1510fda9279dSmrg 1511fda9279dSmrg /* 1512fda9279dSmrg * Initialize software cursor. 1513fda9279dSmrg * Must precede creation of the default colormap. 1514fda9279dSmrg */ 1515fda9279dSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1516fda9279dSmrg 1517fda9279dSmrg /* 1518fda9279dSmrg * Initialize HW cursor layer. 1519fda9279dSmrg * Must follow software cursor initialization. 1520fda9279dSmrg */ 1521fda9279dSmrg if (xf86_config->num_crtc && pNv->HWCursor) { 1522fda9279dSmrg ret = drmmode_cursor_init(pScreen); 1523fda9279dSmrg if (ret != TRUE) { 1524fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1525fda9279dSmrg "Hardware cursor initialization failed\n"); 1526fda9279dSmrg pNv->HWCursor = FALSE; 1527fda9279dSmrg } 1528fda9279dSmrg } 1529fda9279dSmrg 1530fda9279dSmrg if (pNv->ShadowFB) 1531fda9279dSmrg ShadowFBInit(pScreen, NVRefreshArea); 1532fda9279dSmrg 1533fda9279dSmrg pScrn->fbOffset = 0; 1534fda9279dSmrg 1535fda9279dSmrg NVInitVideo(pScreen); 1536fda9279dSmrg 1537fda9279dSmrg /* Wrap the block handler here, if we do it after the EnterVT we 1538fda9279dSmrg * can end up in the unfortunate case where we've wrapped the 1539fda9279dSmrg * xf86RotateBlockHandler which sometimes is not expecting to 1540fda9279dSmrg * be in the wrap chain and calls a NULL pointer... 1541fda9279dSmrg */ 1542fda9279dSmrg pNv->BlockHandler = pScreen->BlockHandler; 1543fda9279dSmrg pScreen->BlockHandler = NVBlockHandler; 1544fda9279dSmrg 1545fda9279dSmrg if (!AddCallback(&FlushCallback, NVFlushCallback, pScrn)) 1546fda9279dSmrg return FALSE; 1547fda9279dSmrg 1548fda9279dSmrg pScrn->vtSema = TRUE; 1549fda9279dSmrg pScrn->pScreen = pScreen; 1550fda9279dSmrg 1551fda9279dSmrg xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1552fda9279dSmrg 1553fda9279dSmrg /* Wrap the current CloseScreen function */ 1554fda9279dSmrg pScreen->SaveScreen = NVSaveScreen; 1555fda9279dSmrg pNv->CloseScreen = pScreen->CloseScreen; 1556fda9279dSmrg pScreen->CloseScreen = NVCloseScreen; 1557fda9279dSmrg pNv->CreateScreenResources = pScreen->CreateScreenResources; 1558fda9279dSmrg pScreen->CreateScreenResources = NVCreateScreenResources; 1559fda9279dSmrg 1560fda9279dSmrg#ifdef NOUVEAU_PIXMAP_SHARING 1561fda9279dSmrg pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1562fda9279dSmrg pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1563fda9279dSmrg#endif 1564fda9279dSmrg 1565fda9279dSmrg if (!xf86CrtcScreenInit(pScreen)) 1566fda9279dSmrg return FALSE; 1567fda9279dSmrg 1568fda9279dSmrg /* Initialise default colourmap */ 1569fda9279dSmrg if (!miCreateDefColormap(pScreen)) 1570fda9279dSmrg return FALSE; 1571fda9279dSmrg 1572fda9279dSmrg /* 1573fda9279dSmrg * Initialize colormap layer. 157422d74663Smrg * Must follow initialization of the default colormap. 157522d74663Smrg * X-Server < 1.20 mishandles > 256 slots / > 8 bpc color maps, so skip 157622d74663Smrg * color map setup on old servers at > 8 bpc. Gamma luts still work. 1577fda9279dSmrg */ 157822d74663Smrg if (xf86_config->num_crtc && (pScrn->rgbBits <= 8 || 157922d74663Smrg XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,20,0,0,0)) && 158022d74663Smrg !xf86HandleColormaps(pScreen, 1 << pScrn->rgbBits, pScrn->rgbBits, 158122d74663Smrg NVLoadPalette, NULL, CMAP_PALETTED_TRUECOLOR)) 1582fda9279dSmrg return FALSE; 1583fda9279dSmrg 1584fda9279dSmrg /* Report any unused options (only for the first generation) */ 1585fda9279dSmrg if (serverGeneration == 1) 1586fda9279dSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1587fda9279dSmrg 1588fda9279dSmrg if (xf86_config->num_crtc) 1589fda9279dSmrg drmmode_screen_init(pScreen); 1590fda9279dSmrg else 1591fda9279dSmrg pNv->glx_vblank = FALSE; 1592fda9279dSmrg return TRUE; 1593fda9279dSmrg} 1594fda9279dSmrg 1595fda9279dSmrgstatic Bool 1596fda9279dSmrgNVSaveScreen(ScreenPtr pScreen, int mode) 1597fda9279dSmrg{ 1598fda9279dSmrg return TRUE; 1599fda9279dSmrg} 1600fda9279dSmrg 1601