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