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