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